23 struct FindFileContext32
{
27 char unixpath
[PATH_LEN
];
30 typedef struct FindFileContext32 FindFileContext32
;
32 const char *DOSFS_Hash(const char *, int, int);
35 * 1) Check volume information to see if long file names supported
36 * and do separate wildcard matching if so. Win95 has extended wildcard
37 * matching - It can have wildcards like '*foo*'. These can match both
38 * the long file name and the short file name.
39 * 2) These file functions may be called from an interrupt
40 * Interrupt 21h Function 714Eh FindFirstFile
41 * Interrupt 21h Function 714Fh FindNextFile
42 * Interrupt 21h Function 71A1h FindClose
45 static BOOL32
MatchWildCard(LPCSTR file
, LPCSTR mask
)
51 if (strcmp(mask
, "*.*") == 0)
57 while (*file
&& (toupper(*file
) != *(mask
+1))) file
++;
65 if (*mask
!= '?' && *mask
!= toupper(*file
)) {
75 /* Functionality is same as GetFileInformationByHandle, but the structures
76 * it fills out are different. This needs to be kept the same as the above
81 static BOOL32
FINDFILE_GetFileInfo(const char *filename
,
82 LPWIN32_FIND_DATA32A finfo
)
84 struct stat file_stat
;
86 if (stat(filename
, &file_stat
) == -1) {
87 SetLastError(ErrnoToLastError(errno
));
90 finfo
->dwFileAttributes
= 0;
91 if (file_stat
.st_mode
& S_IFREG
)
92 finfo
->dwFileAttributes
|= FILE_ATTRIBUTE_NORMAL
;
93 if (file_stat
.st_mode
& S_IFDIR
)
94 finfo
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
95 if ((file_stat
.st_mode
& S_IRUSR
) == 0)
96 finfo
->dwFileAttributes
|= FILE_ATTRIBUTE_READONLY
;
98 /* Translate the file times. Use the last modification time
99 * for both the creation time and write time.
101 DOSFS_UnixTimeToFileTime(file_stat
.st_mtime
, &(finfo
->ftCreationTime
));
102 DOSFS_UnixTimeToFileTime(file_stat
.st_mtime
, &(finfo
->ftLastWriteTime
));
103 DOSFS_UnixTimeToFileTime(file_stat
.st_atime
, &(finfo
->ftLastAccessTime
));
105 finfo
->nFileSizeLow
= file_stat
.st_size
;
107 /* Zero out currently unused fields.
109 finfo
->nFileSizeHigh
= 0;
110 finfo
->dwReserved0
= 0;
111 finfo
->dwReserved1
= 0;
117 /*************************************************************************
118 * FindNextFile32A (KERNEL32.126)
120 BOOL32
FindNextFile32A(HANDLE32 handle
, LPWIN32_FIND_DATA32A data
)
122 FindFileContext32
*context
;
123 struct dirent
*dirent
;
125 char fullfilename
[PATH_LEN
];
127 memset(data
, 0, sizeof(WIN32_FIND_DATA32A
));
128 context
= (FindFileContext32
*) handle
;
130 while ((dirent
= readdir(context
->dir
)) != NULL
) {
131 if (strcmp(dirent
->d_name
, "..") == 0 ||
132 strcmp(dirent
->d_name
, ".") == 0)
135 lstrcpy32A(dosname
, DOSFS_Hash(dirent
->d_name
, FALSE
, FALSE
));
137 if (MatchWildCard(dirent
->d_name
, context
->mask
)) {
138 /* fill in file information */
139 lstrcpy32A(fullfilename
, context
->unixpath
);
140 if (context
->unixpath
[strlen(context
->unixpath
)-1] != '/')
141 strcat(fullfilename
, "/");
142 strcat(fullfilename
, dirent
->d_name
);
143 FINDFILE_GetFileInfo(fullfilename
, data
);
146 lstrcpy32A(data
->cFileName
, dirent
->d_name
);
148 /* file name expressed in 8.3 format */
149 lstrcpy32A(data
->cAlternateFileName
, dosname
);
151 dprintf_file(stddeb
, "FindNextFile32A: %s (%s)\n",
152 data
->cFileName
, data
->cAlternateFileName
);
160 /*************************************************************************
161 * FindNextFile32W (KERNEL32.127)
163 BOOL32
FindNextFile32W(HANDLE32 handle
, LPWIN32_FIND_DATA32W data
)
165 WIN32_FIND_DATA32A adata
;
168 adata
.dwFileAttributes
= data
->dwFileAttributes
;
169 adata
.ftCreationTime
= data
->ftCreationTime
;
170 adata
.ftLastAccessTime
= data
->ftLastAccessTime
;
171 adata
.ftLastWriteTime
= data
->ftLastWriteTime
;
172 adata
.nFileSizeHigh
= data
->nFileSizeHigh
;
173 adata
.nFileSizeLow
= data
->nFileSizeLow
;
174 adata
.dwReserved0
= data
->dwReserved0
;
175 adata
.dwReserved1
= data
->dwReserved1
;
176 STRING32_UniToAnsi(adata
.cFileName
,data
->cFileName
);
177 STRING32_UniToAnsi(adata
.cAlternateFileName
,data
->cAlternateFileName
);
178 res
=FindNextFile32A(handle
,&adata
);
180 data
->dwFileAttributes
= adata
.dwFileAttributes
;
181 data
->ftCreationTime
= adata
.ftCreationTime
;
182 data
->ftLastAccessTime
= adata
.ftLastAccessTime
;
183 data
->ftLastWriteTime
= adata
.ftLastWriteTime
;
184 data
->nFileSizeHigh
= adata
.nFileSizeHigh
;
185 data
->nFileSizeLow
= adata
.nFileSizeLow
;
186 data
->dwReserved0
= adata
.dwReserved0
;
187 data
->dwReserved1
= adata
.dwReserved1
;
188 STRING32_AnsiToUni(data
->cFileName
,adata
.cFileName
);
189 STRING32_AnsiToUni(data
->cAlternateFileName
,adata
.cAlternateFileName
);
194 /*************************************************************************
195 * FindFirstFile32A (KERNEL32.123)
198 HANDLE32
FindFirstFile32A(LPCSTR lpfilename_in
,
199 LPWIN32_FIND_DATA32A lpFindFileData
)
201 const char *unixpath
;
203 FindFileContext32
*context
;
204 char lpfilename
[PATH_LEN
];
207 context
= HeapAlloc(SystemHeap
, 0, sizeof(FindFileContext32
));
209 return (INVALID_HANDLE_VALUE
);
211 /* These type of cases
217 lstrcpy32A(lpfilename
, lpfilename_in
);
218 if (lpfilename
[1] != ':' &&
219 lpfilename
[0] != '\\') {
220 /* drive and root path are not set */
221 len
= GetCurrentDirectory32A(PATH_LEN
, lpfilename
);
222 if (lpfilename
[len
-1] != '\\')
223 strcat(lpfilename
, "\\");
224 strcat(lpfilename
, lpfilename_in
);
226 else if (lpfilename
[1] != ':') {
227 /* drive not set, but path is rooted */
228 memmove(&lpfilename
[2], lpfilename
, strlen(lpfilename
));
229 lpfilename
[0] = DRIVE_GetCurrentDrive();
232 else if (lpfilename
[1] == ':' &&
233 lpfilename
[2] != '\\') {
234 /* drive is set, but not root path */
235 lstrcpy32A(lpfilename
, DRIVE_GetDosCwd(lpfilename
[0]));
236 strcat(lpfilename
, lpfilename_in
);
239 dprintf_file(stddeb
, "FindFirstFile32A: %s -> %s .\n",
240 lpfilename_in
, lpfilename
);
242 slash
= strrchr(lpfilename
, '\\');
245 lstrcpyn32A(context
->path
, lpfilename
, slash
- lpfilename
+ 1);
246 context
->path
[slash
- lpfilename
+ 1] = '\0';
247 unixpath
= DOSFS_GetUnixFileName(context
->path
, FALSE
);
249 /* FIXME: SetLastError(??) */
250 HeapFree(SystemHeap
, 0, context
);
251 return INVALID_HANDLE_VALUE
;
253 lstrcpy32A(context
->mask
, slash
+1);
256 /* shouldn't really get here now */
257 context
->path
[0] = '\0';
259 lstrcpy32A(context
->mask
, lpfilename
);
262 lstrcpy32A(context
->unixpath
, unixpath
);
263 context
->dir
= opendir(unixpath
);
265 /* FIXME: SetLastError(??) */
266 HeapFree(SystemHeap
, 0, context
);
267 return INVALID_HANDLE_VALUE
;
270 /* uppercase mask in place */
271 for (p
= context
->mask
; *p
; p
++)
274 if (!FindNextFile32A((HANDLE32
) context
, lpFindFileData
))
275 return (INVALID_HANDLE_VALUE
);
276 return ((HANDLE32
) context
);
279 /*************************************************************************
280 * FindFirstFile32W (KERNEL32.124)
282 HANDLE32
FindFirstFile32W(LPCWSTR filename
,LPWIN32_FIND_DATA32W data
)
284 WIN32_FIND_DATA32A adata
;
285 LPSTR afn
= STRING32_DupUniToAnsi(filename
);
288 res
=FindFirstFile32A(afn
,&adata
);
290 data
->dwFileAttributes
= adata
.dwFileAttributes
;
291 data
->ftCreationTime
= adata
.ftCreationTime
;
292 data
->ftLastAccessTime
= adata
.ftLastAccessTime
;
293 data
->ftLastWriteTime
= adata
.ftLastWriteTime
;
294 data
->nFileSizeHigh
= adata
.nFileSizeHigh
;
295 data
->nFileSizeLow
= adata
.nFileSizeLow
;
296 data
->dwReserved0
= adata
.dwReserved0
;
297 data
->dwReserved1
= adata
.dwReserved1
;
298 STRING32_AnsiToUni(data
->cFileName
,adata
.cFileName
);
299 STRING32_AnsiToUni(data
->cAlternateFileName
,adata
.cAlternateFileName
);
305 /*************************************************************************
306 * FindClose32 (KERNEL32.119)
308 BOOL32
FindClose32(HANDLE32 handle
)
310 FindFileContext32
*context
;
312 /* Windows95 ignores an invalid handle. */
313 if (handle
== INVALID_HANDLE_VALUE
)
315 SetLastError(ERROR_INVALID_HANDLE
);
318 context
= (FindFileContext32
*) handle
;
320 closedir(context
->dir
);
321 HeapFree(SystemHeap
, 0, context
);
325 /* 16 bit versions of find functions */
326 /*************************************************************************
327 * FindFirstFile16 (KERNEL.413)
331 FindFirstFile16(LPCSTR lpFileName
, LPVOID lpdata
)
333 WIN32_FIND_DATA32A
*findData
= (WIN32_FIND_DATA32A
*) lpdata
;
338 /* get a handle to the real pointer */
341 h32
= FindFirstFile32A(lpFileName
, findData
);
343 h16
= GlobalAlloc16(0, sizeof(h32
));
344 ptr
= GlobalLock16(h16
);
349 return ((HANDLE16
) h32
);
352 /*************************************************************************
353 * FindNextFile16 (KERNEL.414)
357 FindNextFile16(HANDLE16 handle
, LPVOID lpdata
)
359 WIN32_FIND_DATA32A
*findData
= (WIN32_FIND_DATA32A
*) lpdata
;
362 lph32
= GlobalLock16(handle
);
363 if (FindNextFile32A(*lph32
, findData
)) {
370 /*************************************************************************
371 * FindClose16 (KERNEL.415)
375 FindClose16(HANDLE16 handle
)
380 if (handle
== (HANDLE16
) INVALID_HANDLE_VALUE
) {
381 SetLastError(ERROR_INVALID_HANDLE
);
385 lph32
= GlobalLock16(handle
);
386 ret
= FindClose32(*lph32
);
387 GlobalFree16(handle
);