Subversion Repositories SvarDOS

Rev

Rev 2042 | Rev 2045 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2019 mateusz.vi 1
/****************************************************************************
2
 
2026 mateusz.vi 3
  Win32 File compatibility for DOS.
2019 mateusz.vi 4
  [This version does support LFNs, if available.]
5
 
6
  Written by: Kenneth J. Davis
7
  Date:       August, 2000
8
  Contact:    jeremyd@computer.org
9
 
10
 
11
Copyright (c): Public Domain [United States Definition]
12
 
13
Permission is hereby granted, free of charge, to any person obtaining a copy
14
of this software and associated documentation files (the "Software"), to deal
15
in the Software without restriction, including without limitation the rights
16
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
copies of the Software, and to permit persons to whom the Software is
18
furnished to do so, subject to the following conditions:
19
 
20
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR AUTHORS BE
24
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
25
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
26
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
DEALINGS IN THE SOFTWARE.
28
 
29
****************************************************************************/
30
 
31
 
32
/*** Expects Pointers to be near (Tiny, Small, and Medium models ONLY) ***/
33
 
2041 mateusz.vi 34
#include <dos.h>
2019 mateusz.vi 35
#include <stdlib.h>
36
#include <string.h>
37
 
2041 mateusz.vi 38
#include "dosdisk.h"
39
 
2019 mateusz.vi 40
#define searchAttr ( FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN | \
41
   FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_ARCHIVE )
42
 
2026 mateusz.vi 43
/* If this variable is nonzero then will 1st attempt LFN findfirst
2019 mateusz.vi 44
 * (findfirst calls sets flag, so findnext/findclose know proper method to continue)
45
 * else if 0 then only attempt old 0x4E findfirst.
46
 * This is mostly a debugging tool, may be useful during runtime.
47
 * Default is LFN_ENABLE.
48
 */
49
int LFN_Enable_Flag = LFN_ENABLE;
50
 
51
 
2026 mateusz.vi 52
/* copy old style findfirst data FFDTA to a WIN32_FIND_DATA
53
 * NOTE: does not map exactly.
2019 mateusz.vi 54
 * internal to this module only.
55
 */
2041 mateusz.vi 56
static void copyFileData(struct WIN32_FIND_DATA *findData, const struct FFDTA *finfo)
2019 mateusz.vi 57
{
58
  /* Copy requried contents over into required structure */
59
  strcpy(findData->cFileName, finfo->ff_name);
2041 mateusz.vi 60
  findData->dwFileAttributes = (DWORD)finfo->ff_attr;
2019 mateusz.vi 61
 
62
  /* copy over rest (not quite properly) */
63
  findData->ftCreationTime.ldw[0] = finfo->ff_ftime;
64
  findData->ftLastAccessTime.ldw[0] = finfo->ff_ftime;
65
  findData->ftLastWriteTime.ldw[0] = finfo->ff_ftime;
66
  findData->ftCreationTime.ldw[1] = finfo->ff_fdate;
67
  findData->ftLastAccessTime.ldw[1] = finfo->ff_fdate;
68
  findData->ftLastWriteTime.ldw[1] = finfo->ff_fdate;
69
  findData->ftCreationTime.hdw = 0;
70
  findData->ftLastAccessTime.hdw = 0;
71
  findData->ftLastWriteTime.hdw = 0;
72
  findData->nFileSizeHigh = 0;
73
  findData->nFileSizeLow = (DWORD)finfo->ff_fsize;
74
  findData->dwReserved0 = 0;
75
  findData->dwReserved1 = 0;
76
}
77
 
2040 mateusz.vi 78
HANDLE FindFirstFile(const char *pathname, struct WIN32_FIND_DATA *findData)
2019 mateusz.vi 79
{
2044 mateusz.vi 80
  static char path[1024];
2019 mateusz.vi 81
  HANDLE hnd;
82
  short cflag = 0;  /* used to indicate if findfirst is succesful or not */
83
 
84
  /* verify findData is valid */
85
  if (findData == NULL)
86
    return INVALID_HANDLE_VALUE;
87
 
88
  /* allocate memory for the handle */
89
  if ((hnd = (HANDLE)malloc(sizeof(struct FindFileStruct))) == NULL)
90
    return INVALID_HANDLE_VALUE;
91
 
92
  /* initialize structure (clear) */
93
  /* hnd->handle = 0;  hnd->ffdtaptr = NULL; */
94
  memset(hnd, 0, sizeof(struct FindFileStruct));
95
 
96
  /* Clear findData, this is to fix a glitch under NT, with 'special' $???? files */
97
  memset(findData, 0, sizeof(struct WIN32_FIND_DATA));
98
 
99
  /* First try DOS LFN (0x714E) findfirst, going to old (0x4E) if error */
100
  if (LFN_Enable_Flag)
101
  {
2044 mateusz.vi 102
    unsigned short attr = searchAttr;
103
    unsigned short varax = 0xffff;
104
    unsigned short finddata_seg = FP_SEG(findData);
105
    unsigned short finddata_off = FP_OFF(findData);
106
    unsigned char cf = 1;
107
    unsigned short pathname_seg = FP_SEG(pathname);
108
    unsigned short pathname_off = FP_OFF(pathname);
2019 mateusz.vi 109
    hnd->flag = FINDFILELFN;
110
 
2044 mateusz.vi 111
    _asm {
112
      push ax
113
      push bx
114
      push cx
115
      push dx
116
      push es
117
      push si
118
      push di
119
 
120
      stc                          //; In case not supported
121
      mov si, 1                    //; same format as when old style used, set to 0 for 64bit value
122
      mov di, finddata_off         //; Set address of findData into ES:DI
123
      mov es, finddata_seg
124
      mov ax, 0x714E               //; LFN version of FindFirst
125
      mov cx, attr
126
      mov dx, pathname_off         //; Load DS:DX with pointer to path for Findfirst
127
      push ds
128
      mov ds, pathname_seg
129
      int 0x21                     //; Execute interrupt
130
      pop ds
131
      jc lfnerror
132
      mov cf, 0
133
      mov varax, ax
134
      lfnerror:
135
 
136
      pop di
137
      pop si
138
      pop es
139
      pop dx
140
      pop cx
141
      pop bx
142
      pop ax
2019 mateusz.vi 143
    }
2044 mateusz.vi 144
    if (cf == 0) {
145
      hnd->fhnd.handle = varax;  /* store handle finally :) */
146
      return hnd;
2019 mateusz.vi 147
    }
148
 
149
    /* AX is supposed to contain 7100h if function not supported, else real error */
150
    /* However, FreeDOS returns AX = 1 = Invalid function number instead.         */
2044 mateusz.vi 151
    if ((varax != 0x7100) && (varax != 0x0001)) {
2019 mateusz.vi 152
      free(hnd);
153
      return INVALID_HANDLE_VALUE;
154
    }
155
  }
156
 
157
  /* Use DOS (0x4E) findfirst, returning if error */
158
  hnd->flag = FINDFILEOLD;
159
 
160
  /* allocate memory for the FFDTA */
2041 mateusz.vi 161
  if ((hnd->fhnd.ffdtaptr = (struct FFDTA *)malloc(sizeof(struct FFDTA))) == NULL)
2019 mateusz.vi 162
  {
163
    free(hnd);
164
    return INVALID_HANDLE_VALUE;
165
  }
166
 
167
  /* if pathname ends in \* convert to \*.* */
168
  strcpy(path, pathname);
2032 mateusz.vi 169
  {
170
  int eos = strlen(path) - 1;
171
  if ((path[eos] == '*') && (path[eos - 1] == '\\')) strcat(path, ".*");
172
  }
2019 mateusz.vi 173
 
2044 mateusz.vi 174
  {
175
    unsigned short ffdta_seg, ffdta_off;
176
    unsigned short path_seg, path_off;
177
    unsigned short sattr = searchAttr;
178
    ffdta_seg = FP_SEG((*hnd).fhnd.ffdtaptr);
179
    ffdta_off = FP_OFF((*hnd).fhnd.ffdtaptr);
180
    path_seg = FP_SEG(path);
181
    path_off = FP_OFF(path);
182
 
183
  _asm {
184
    push ax
185
    push bx
186
    push cx
187
    push dx
188
    push es
189
 
190
    mov ah, 0x2F                   //; Get Current DTA
191
    int 0x21                       //; Execute interrupt, returned in ES:BX
192
    push bx                        //; Store its Offset, then Segment
193
    push es
194
    mov ah, 0x1A                   //; Set Current DTA to our buffer, DS:DX
195
    mov dx, ffdta_off
196
    push ds
197
    mov ds, ffdta_seg
198
    int 0x21                       //; Execute interrupt
199
    pop ds
200
    mov ax, 0x4E00                 //; Actual findfirst call
201
    mov cx, sattr
202
    mov dx, path_off               //; Load DS:DX with pointer to path for Findfirt
203
    push ds
204
    mov ds, path_seg
205
    int 0x21                       //; Execute interrupt
206
    pop ds
207
    jnc success                    //; If carry is not set then succesful
208
    mov [cflag], ax                //; Set flag with error.
209
success:
210
    mov ah, 0x1A              //; Set Current DTA back to original, DS:DX
211
    mov dx, ds                //; Store DS, must be preserved
212
    pop ds                    //; Popping ES into DS since thats where we need it.
213
    pop bx                    //; Now DS:BX points to original DTA
214
    int 0x21                  //; Execute interrupt to restore.
215
    mov ds, dx                //; Restore DS
216
 
217
    pop es
218
    pop dx
219
    pop cx
220
    pop bx
221
    pop ax
2019 mateusz.vi 222
  }
223
  }
224
 
225
  if (cflag)
226
  {
227
    free(hnd->fhnd.ffdtaptr);
228
    free(hnd);
229
    return INVALID_HANDLE_VALUE;
230
  }
231
 
232
  /* copy its results over */
233
  copyFileData(findData, hnd->fhnd.ffdtaptr);
234
 
235
  return hnd;
236
}
237
 
238
 
2040 mateusz.vi 239
int FindNextFile(HANDLE hnd, struct WIN32_FIND_DATA *findData)
2019 mateusz.vi 240
{
241
  short cflag = 0;  /* used to indicate if dos findnext succesful or not */
242
 
243
  /* if bad handle given return */
244
  if ((hnd == NULL) || (hnd == INVALID_HANDLE_VALUE)) return 0;
245
 
246
  /* verify findData is valid */
247
  if (findData == NULL) return 0;
248
 
249
  /* Clear findData, this is to fix a glitch under NT, with 'special' $???? files */
250
  memset(findData, 0, sizeof(struct WIN32_FIND_DATA));
251
 
252
  /* Flag indicate if using LFN DOS (0x714F) or not */
253
  if (hnd->flag == FINDFILELFN)
254
  {
2044 mateusz.vi 255
    unsigned short handle = hnd->fhnd.handle;
256
    unsigned char cf = 0;
257
    _asm {
258
      push ax
259
      push bx
260
      push cx
261
      push dx
262
      push es
263
      push si
264
      push di
265
 
266
      mov bx, handle               //; Move the Handle returned by prev findfirst into BX
267
      stc                          //; In case not supported
268
      mov si, 1                    //; same format as when old style used, set to 0 for 64bit value
269
      mov ax, ds                   //; Set address of findData into ES:DI
270
      mov es, ax
271
      mov di, [findData]
272
      mov ax, 0x714F               //; LFN version of FindNext
273
      int 0x21                     //; Execute interrupt
274
      jnc DONE
275
      mov cf, 1
276
      DONE:
277
 
278
      pop di
279
      pop si
280
      pop es
281
      pop dx
282
      pop cx
283
      pop bx
284
      pop ax
2019 mateusz.vi 285
    }
2044 mateusz.vi 286
    if (cf == 0) return 1;   /* success */
287
    return 0;   /* Any errors here, no other option but to return error/no more files */
288
  } else { /* Use DOS (0x4F) findnext, returning if error */
289
    unsigned short dta_seg = FP_SEG((*hnd).fhnd.ffdtaptr);
290
    unsigned short dta_off = FP_OFF((*hnd).fhnd.ffdtaptr);
291
    _asm {
292
      push ax
293
      push bx
294
      push cx
295
      push dx
296
      push es
2019 mateusz.vi 297
 
2044 mateusz.vi 298
      mov ah, 0x2F                  //; Get Current DTA
299
      int 0x21                      //; Execute interrupt, returned in ES:BX
300
      push bx                       //; Store its Offset, then Segment
301
      push es
302
      mov ax, 0x1A00                //; Set Current DTA to our buffer, DS:DX
303
      mov dx, dta_off
304
      push ds
305
      mov ds, dta_seg
306
      int 0x21                      //; Execute interrupt
307
      pop ds
308
      mov ax, 0x4F00                //; Actual findnext call
309
      int 0x21                      //; Execute interrupt
2019 mateusz.vi 310
      JNC success                   //; If carry is not set then succesful
2044 mateusz.vi 311
      mov [cflag], ax               //; Set flag with error.
2019 mateusz.vi 312
success:
2044 mateusz.vi 313
      mov ah, 0x1A                  //; Set Current DTA back to original, DS:DX
314
      MOV dx, ds                    //; Store DS, must be preserved
315
      pop ds                        //; Popping ES into DS since thats where we need it.
316
      pop bx                        //; Now DS:BX points to original DTA
317
      int 0x21                      //; Execute interrupt to restore.
318
      mov ds, dx                    //; Restore DS
319
 
320
      pop es
321
      pop dx
322
      pop cx
323
      pop bx
324
      pop ax
2019 mateusz.vi 325
    }
326
 
2044 mateusz.vi 327
  if (cflag) return 0;
2019 mateusz.vi 328
 
329
  /* copy its results over */
330
  copyFileData(findData, hnd->fhnd.ffdtaptr);
331
 
332
  return 1;
333
  }
334
}
335
 
336
 
337
/* free resources to prevent memory leaks */
338
void FindClose(HANDLE hnd)
339
{
340
  /* 1st check if valid handle given */
341
  if ((hnd != NULL) && (hnd != INVALID_HANDLE_VALUE))
342
  {
343
    /* See if its for the new or old style findfirst */
344
    if (hnd->flag == FINDFILEOLD) /* Just free memory allocated */
345
    {
2026 mateusz.vi 346
      if (hnd->fhnd.ffdtaptr != NULL)
2019 mateusz.vi 347
        free(hnd->fhnd.ffdtaptr);
348
      hnd->fhnd.ffdtaptr = NULL;
349
    }
350
    else /* must call LFN findclose */
351
    {
2044 mateusz.vi 352
      unsigned short handle = hnd->fhnd.handle;
353
      _asm {
354
        push ax
355
        push bx
356
 
357
        mov bx, handle            /* Move handle returned from findfirst into BX */
358
        stc
359
        mov ax, 0x71A1
360
        int 0x21                  /* carry set on error */
361
 
362
        pop bx
363
        pop ax
2019 mateusz.vi 364
      }
365
      hnd->fhnd.handle = 0;
366
    }
367
 
368
    free(hnd);                    /* Free memory used for the handle itself */
369
  }
370
}
371
 
372
#include <stdio.h>
373
 
374
/**
375
 Try LFN getVolumeInformation 1st
376
 if successful, assume valid drive/share (ie will return 1 unless error getting label)
377
 if failed (any error other than unsupported) return 0
378
 if a drive (ie a hard drive, ram drive, network mapped to letter) [has : as second letter]
379
 {
380
   try findfirst for volume label. (The LFN api does not seem to support LABEL attribute searches.)
381
     If getVolInfo unsupported but get findfirst succeed, assume valid (ie return 1)
382
   Try Get Serial#
383
 }
384
 else a network give \\server\share and LFN getVol unsupported, assume failed 0, as the
385
   original findfirst/next I haven't seen support UNC naming, clear serial and volume.
386
*** Currently trying to find a way to get a \\server\share 's serial & volume if LFN available ***
387
*/
388
 
2042 mateusz.vi 389
/* returns zero on failure, if lpRootPathName is NULL or "" we use current
390
 * default drive. */
391
int GetVolumeInformation(const char *lpRootPathName, char *lpVolumeNameBuffer,
392
  DWORD nVolumeNameSize, DWORD *lpVolumeSerialNumber) {
393
 
2019 mateusz.vi 394
  /* Using DOS interrupt to get serial number */
2044 mateusz.vi 395
  struct media_info {
2019 mateusz.vi 396
    short dummy;
397
    DWORD serial;
398
    char volume[11];
399
    short ftype[8];
400
  } media;
401
 
402
  /* buffer to store file system name in lfn get volume information */
2026 mateusz.vi 403
  char fsystem[32];
2019 mateusz.vi 404
 
405
  /* Stores the root path we use. */
406
  char pathname[260];
407
 
2026 mateusz.vi 408
  /* Used to determine if drive valid (success/failure of this function)
2019 mateusz.vi 409
   * 0 = success
410
   * 1 = failure
411
   * 2 = LFN api unsupported (tentative failure)
412
   */
413
  int cflag=2;
414
 
415
  /* validate root path to obtain info on, NULL or "" means use current */
2044 mateusz.vi 416
  if ((lpRootPathName == NULL) || (*lpRootPathName == '\0')) {
2019 mateusz.vi 417
    /* Assume if NULL user wants current drive, eg C:\ */
2044 mateusz.vi 418
    _asm {
419
      push ax
420
      push bx
421
 
422
      mov ah, 0x19            //; Get Current Default Drive
423
      int 0x21                //; returned in AL, 0=A, 1=B,...
424
      lea bx, pathname        //; load pointer to our buffer
425
      add al, 'A'             //; Convert #returned to a letter
426
      mov [bx], al            //; Store drive letter
427
      inc bx                  //; point to next character
428
      mov byte ptr [bx], ':'  //; Store the colon
429
      inc bx
430
      mov byte ptr [bx], '\'  //; this gets converted correctly as a single bkslsh
431
      inc bx
432
      mov byte ptr [bx], 0    //; Most importantly the '\0' terminator
433
 
434
      pop bx
435
      pop ax
2019 mateusz.vi 436
    }
2042 mateusz.vi 437
  } else {
438
    strcpy(pathname, lpRootPathName);
2019 mateusz.vi 439
  }
440
 
441
  /* Flag indicate if using LFN DOS or not */
442
  if (LFN_Enable_Flag)
443
  {
2044 mateusz.vi 444
    _asm {
445
      push ax
446
      push bx
447
      push cx
448
      push dx
449
      push es
450
      push di
451
 
452
      mov ax, 0x71A0           //; LFN GetVolumeInformation
453
      mov dx, ds               //; Load buffer for file system name into ES:DI
454
      MOV es, dx
455
      lea di, fsystem
456
      mov cx, 32               //; size of ES:DI buffer
457
      lea dx, pathname         //; Load root name into DS:DX
458
      stc                      //; in case LFN api unsupported
459
      int 0x21
460
      jc getvolerror           //; on any error skip storing any info
461
      mov cflag, 0             //; indicate no error
462
      jmp endgetvol
2019 mateusz.vi 463
    /* store stuff
2044 mateusz.vi 464
       BX = file system flags (see #01783)
465
       CX = maximum length of file name [usually 255]
466
       DX = maximum length of path [usually 260]
467
       fsystem buffer filled (ASCIZ, e.g. "FAT","NTFS","CDFS")
2019 mateusz.vi 468
    */
2044 mateusz.vi 469
getvolerror:
470
      cmp ax, 0x7100           //; see if real error or unsupported
471
      je endgetvol             //; if so skip ahead
472
      cmp ax, 0x0001           //; FreeDOS returns AX = 1 = Invalid function number
473
      je endgetvol
474
      mov cflag, 1             //; indicate failure
475
endgetvol:
2019 mateusz.vi 476
 
2044 mateusz.vi 477
      pop di
478
      pop es
479
      pop dx
480
      pop cx
481
      pop bx
482
      pop ax
2019 mateusz.vi 483
    }
484
  }
485
 
486
 
487
  if (cflag != 1)  /* if no error validating volume info or LFN getVolInfo unsupported */
488
  {
489
    /* if a drive, test if valid, get volume, and possibly serial # */
2044 mateusz.vi 490
    if (pathname[1] == ':') {
491
      struct FFDTA finfo;
492
      unsigned short attr_seg = FP_SEG(finfo.ff_attr);
493
      unsigned short attr_off = FP_OFF(finfo.ff_attr);
494
      unsigned short finfo_seg = FP_SEG(&finfo);
495
      unsigned short finfo_off = FP_OFF(&finfo);
496
      unsigned short pathname_seg = FP_SEG(pathname);
497
      unsigned short pathname_off = FP_OFF(pathname);
498
 
2019 mateusz.vi 499
      /* assume these calls will succeed, change on an error */
500
      cflag = 0;
501
 
502
      /* get path ending in \*.*, */
503
      if (pathname[strlen(pathname)-1] != '\\')
504
	strcat(pathname, "\\*.*");
505
      else
506
	strcat(pathname, "*.*");
507
 
508
      /* Search for volume using old findfirst, as LFN version (NT5 DOS box) does
509
       * not recognize FILE_ATTRIBUTE_LABEL = 0x0008 as label attribute.
510
       */
2044 mateusz.vi 511
      _asm {
512
        push ax
513
        push bx
514
        push cx
515
        push dx
516
        push es
517
 
518
        mov ah, 0x2F              //; Get Current DTA
519
        int 0x21                  //; Execute interrupt, returned in ES:BX
520
        push bx                   //; Store its Offset, then Segment
521
        push es
522
        mov ah, 0x1A              //; Set Current DTA to our buffer, DS:DX
523
        mov dx, finfo_off         //; Load our buffer for new DTA.
524
        push ds
525
        mov ds, finfo_seg
526
        int 0x21                  //; Execute interrupt
527
        pop ds
528
        mov ax, 0x4E00            //; Actual findfirst call
529
        mov cx, FILE_ATTRIBUTE_LABEL
530
        mov dx, pathname_off      //; Load DS:DX with pointer to modified RootPath for Findfirt
531
        push ds
532
        mov ds, pathname_seg
533
        int 0x21                  //; Execute interrupt, Carry set on error, unset on success
534
        pop ds
535
        jnc success               //; If carry is not set then succesful
536
        mov [cflag], ax           //; Set flag with error.
537
        jmp cleanup               //; Restore DTA
2019 mateusz.vi 538
success:                        //; True volume entry only has volume attribute set [MS' LFNspec]
2044 mateusz.vi 539
        mov bx, attr_off
540
        push es
541
        mov es, attr_seg
542
        mov al, [es:bx]              //; Looking for a BYTE that is FILE_ATTRIBUTE_LABEL only
543
        pop es
544
        and al, 0xDF              //; Ignore Archive bit
545
        cmp al, FILE_ATTRIBUTE_LABEL
546
        je cleanup                //; They match, so should be true volume entry.
547
        mov ax, 0x4F00            //; Otherwise keep looking (findnext)
548
        int 0x21                  //; Execute interrupt
549
        jnc success               //; If carry is not set then succesful
550
        mov [cflag], ax           //; Set flag with error.
2019 mateusz.vi 551
cleanup:
2044 mateusz.vi 552
        mov ah, 0x1A              //; Set Current DTA back to original, DS:DX
553
        mov dx, ds                //; Store DS, must be preserved
554
        pop ds                    //; Popping ES into DS since thats where we need it.
555
        pop bx                    //; Now DS:BX points to original DTA
556
        int 0x21                  //; Execute interrupt to restore.
557
        mov ds, dx                //; Restore DS
558
 
559
        pop es
560
        pop dx
561
        pop cx
562
        pop bx
563
        pop ax
2019 mateusz.vi 564
      }
565
      /* copy over volume label, if buffer given */
566
      if (lpVolumeNameBuffer != NULL)
567
      {
568
	if (cflag != 0)    /* error or no label */
569
	  lpVolumeNameBuffer[0] = '\0';
570
	else                        /* copy up to buffer's size of label */
571
	{
572
	  strncpy(lpVolumeNameBuffer, finfo.ff_name, nVolumeNameSize);
573
	  lpVolumeNameBuffer[nVolumeNameSize-1] = '\0';
574
          /* slide characters over if longer than 8 to remove . */
575
          if (lpVolumeNameBuffer[8] == '.')
576
          {
577
            lpVolumeNameBuffer[8] = lpVolumeNameBuffer[9];
578
            lpVolumeNameBuffer[9] = lpVolumeNameBuffer[10];
579
            lpVolumeNameBuffer[10] = lpVolumeNameBuffer[11];
580
            lpVolumeNameBuffer[11] = '\0';
581
          }
582
        }
583
      }
584
      /* Test for no label found, which is not an error,
585
         Note: added the check for 0x02 as FreeDOS returns this instead
586
         at least for disks with LFN entries and no volume label.
587
      */
588
      if ((cflag == 0x12) || /* No more files or   */
589
          (cflag == 0x02))   /* File not found     */
590
        cflag = 0;       /* so assume valid drive  */
591
 
592
 
2026 mateusz.vi 593
      /* Get Serial Number, only supports drives mapped to letters */
2019 mateusz.vi 594
      media.serial = 0;         /* set to 0, stays 0 on an error */
2044 mateusz.vi 595
      {
596
        unsigned short media_off = FP_OFF(&media);
597
        unsigned short media_seg = FP_SEG(&media);
598
        unsigned char drv = (pathname[0] & 0xDF) - 'A' + 1;
599
      _asm {
600
        push ax
601
        push bx
602
        push cx
603
        push dx
2019 mateusz.vi 604
 
2044 mateusz.vi 605
        xor bh, bh
606
        mov bl, drv             //; Clear BH, drive in BL
607
        mov cx, 0x0866          //; CH=disk drive, CL=Get Serial #
608
        mov ax, 0x440D          //; Generic IOCTL
609
        mov dx, media_off       //; DS:DX pointer to media structure
610
        push ds
611
        mov ds, media_seg
612
        int 0x21
613
        pop ds
614
 
615
        pop dx
616
        pop cx
617
        pop bx
618
        pop ax
2019 mateusz.vi 619
      }
2044 mateusz.vi 620
      }
2019 mateusz.vi 621
 
622
/***************** Replaced with 'documented' version of Get Serial Number *********************/
2026 mateusz.vi 623
      /* NT2000pro does NOT set or clear the carry for int21h subfunction 6900h
2019 mateusz.vi 624
       *   if an error occurs, it leaves media unchanged.
625
       */
626
//      asm {
627
//        MOV AX, 0x6900
628
//        INT 21h                 //; Should set carry on error, clear on success [note NT5 does not]
629
//      }
630
/***************** End with 'undocumented' version of Get Serial Number *********************/
631
 
632
      if (lpVolumeSerialNumber != NULL)
633
        *lpVolumeSerialNumber = media.serial;
634
    }
635
    else /* a network drive, assume results of LFN getVolInfo, no volume or serial [for now] */
636
    {
637
      if (lpVolumeNameBuffer != NULL)
638
        lpVolumeNameBuffer[0] = '\0';
639
 
640
      if (lpVolumeSerialNumber != NULL)
641
        *lpVolumeSerialNumber = 0x0;
642
    }
643
  }
2026 mateusz.vi 644
 
2019 mateusz.vi 645
  /* If there was an error getting the validating drive return failure) */
646
  if (cflag)    /* cflag is nonzero on any errors */
647
    return 0;   /* zero means error! */
648
  else
649
    return 1;   /* Success (drive exists we think anyway) */
650
}
651
 
2041 mateusz.vi 652
 
653
/* retrieve attributes (ReadOnly/System/...) about file or directory
654
 * returns (DWORD)-1 on error
655
 */
656
DWORD GetFileAttributes(const char *pathname) {
657
  union REGS r;
658
  struct SREGS s;
659
  char buffer[260];
660
  int slen;
661
 
662
  /* 1st try LFN - Extended get/set attributes (in case LFN used) */
663
  if (LFN_Enable_Flag)
664
  {
665
    r.x.ax = 0x7143;                  /* LFN API, Extended Get/Set Attributes */
666
    r.x.bx = 0x00;                    /* BL=0, get file attributes            */
667
    r.x.dx = FP_OFF(pathname);        /* DS:DX points to ASCIIZ filename      */
668
 
669
    segread(&s);                      /* load with current segment values     */
670
    s.ds = FP_SEG(pathname);          /* get Segment of our filename pointer  */
671
 
672
    r.x.cflag = 1;                    /* should be set when unsupported ***   */
2044 mateusz.vi 673
    _asm stc;                          /* but clib usually ignores on entry    */
2041 mateusz.vi 674
 
675
    /* Actually perform the call, carry should be set on error or unuspported */
676
    intdosx(&r, &r, &s);         /* Clib function to invoke DOS int21h call   */
677
 
678
    if (!r.x.cflag)              /* if carry not set then cx has desired info */
679
      return (DWORD)r.x.cx;
680
    /* else error other than unsupported LFN api or invalid function [FreeDOS]*/
681
    else if ((r.x.ax != 0x7100) || (r.x.ax != 0x01))
682
      return (DWORD)-1;
683
    /* else fall through to standard get/set file attribute call */
684
  }
685
 
686
  /* we must remove any slashes from end */
687
  slen = strlen(pathname) - 1;  /* Warning, assuming pathname is not ""   */
688
  strcpy(buffer, pathname);
689
  if ((buffer[slen] == '\\') || (buffer[slen] == '/')) /* ends in a slash */
690
  {
691
    /* don't remove from root directory (slen == 0),
692
     * ignore UNC paths as SFN doesn't handle them anyway
693
     * if slen == 2, then check if drive given (e.g. C:\)
694
     */
695
    if (slen && !(slen == 2 &&  buffer[1] == ':'))
696
      buffer[slen] = '\0';
697
  }
698
  /* return standard attributes */
699
  r.x.ax = 0x4300;                  /* standard Get/Set File Attributes */
700
  r.x.dx = FP_OFF(buffer);          /* DS:DX points to ASCIIZ filename      */
701
  segread(&s);                      /* load with current segment values     */
702
  s.ds = FP_SEG(buffer);            /* get Segment of our filename pointer  */
703
  intdosx(&r, &r, &s);              /* invoke the DOS int21h call           */
704
 
705
  //if (r.x.cflag) printf("ERROR getting std attributes of %s, DOS err %i\n", buffer, r.x.ax);
706
  if (r.x.cflag) return (DWORD)-1;  /* error obtaining attributes           */
707
  return (DWORD)(0x3F & r.x.cx); /* mask off any DRDOS bits     */
708
}