22 struct FindFileContext32
{
26 char unixpath
[PATH_LEN
];
29 typedef struct FindFileContext32 FindFileContext32
;
31 const char *DOSFS_Hash(const char *, int, int);
34 * 1) Check volume information to see if long file names supported
35 * and do separate wildcard matching if so. Win95 has extended wildcard
36 * matching - It can have wildcards like '*foo*'. These can match both
37 * the long file name and the short file name.
38 * 2) These file functions may be called from an interrupt
39 * Interrupt 21h Function 714Eh FindFirstFile
40 * Interrupt 21h Function 714Fh FindNextFile
41 * Interrupt 21h Function 71A1h FindClose
44 static BOOL32
MatchWildCard(LPCSTR file
, LPCSTR mask
)
50 if (strcmp(mask
, "*.*") == 0)
56 while (*file
&& (toupper(*file
) != *(mask
+1))) file
++;
64 if (*mask
!= '?' && *mask
!= toupper(*file
)) {
74 /* Functionality is same as GetFileInformationByHandle, but the structures
75 * it fills out are different. This needs to be kept the same as the above
80 static BOOL32
FINDFILE_GetFileInfo(const char *filename
,
81 LPWIN32_FIND_DATA32A finfo
)
83 struct stat file_stat
;
85 if (stat(filename
, &file_stat
) == -1) {
86 SetLastError(ErrnoToLastError(errno
));
89 finfo
->dwFileAttributes
= 0;
90 if (file_stat
.st_mode
& S_IFREG
)
91 finfo
->dwFileAttributes
|= FILE_ATTRIBUTE_NORMAL
;
92 if (file_stat
.st_mode
& S_IFDIR
)
93 finfo
->dwFileAttributes
|= FILE_ATTRIBUTE_DIRECTORY
;
94 if ((file_stat
.st_mode
& S_IRUSR
) == 0)
95 finfo
->dwFileAttributes
|= FILE_ATTRIBUTE_READONLY
;
97 /* Translate the file times. Use the last modification time
98 * for both the creation time and write time.
100 DOSFS_UnixTimeToFileTime(file_stat
.st_mtime
, &(finfo
->ftCreationTime
));
101 DOSFS_UnixTimeToFileTime(file_stat
.st_mtime
, &(finfo
->ftLastWriteTime
));
102 DOSFS_UnixTimeToFileTime(file_stat
.st_atime
, &(finfo
->ftLastAccessTime
));
104 finfo
->nFileSizeLow
= file_stat
.st_size
;
106 /* Zero out currently unused fields.
108 finfo
->nFileSizeHigh
= 0;
109 finfo
->dwReserved0
= 0;
110 finfo
->dwReserved1
= 0;
116 /*************************************************************************
117 * FindNextFile32A (KERNEL32.126)
119 BOOL32
FindNextFile32A(HANDLE32 handle
, LPWIN32_FIND_DATA32A data
)
121 FindFileContext32
*context
;
122 struct dirent
*dirent
;
124 char fullfilename
[PATH_LEN
];
126 memset(data
, 0, sizeof(WIN32_FIND_DATA32A
));
127 context
= (FindFileContext32
*) handle
;
129 while ((dirent
= readdir(context
->dir
)) != NULL
) {
130 if (strcmp(dirent
->d_name
, "..") == 0 ||
131 strcmp(dirent
->d_name
, ".") == 0)
134 lstrcpy32A(dosname
, DOSFS_Hash(dirent
->d_name
, FALSE
, FALSE
));
136 if (MatchWildCard(dirent
->d_name
, context
->mask
)) {
137 /* fill in file information */
138 lstrcpy32A(fullfilename
, context
->unixpath
);
139 if (context
->unixpath
[strlen(context
->unixpath
)-1] != '/')
140 strcat(fullfilename
, "/");
141 strcat(fullfilename
, dirent
->d_name
);
142 FINDFILE_GetFileInfo(fullfilename
, data
);
145 lstrcpy32A(data
->cFileName
, dirent
->d_name
);
147 /* file name expressed in 8.3 format */
148 lstrcpy32A(data
->cAlternateFileName
, dosname
);
150 dprintf_file(stddeb
, "FindNextFile32A: %s (%s)\n",
151 data
->cFileName
, data
->cAlternateFileName
);
159 /*************************************************************************
160 * FindNextFile32W (KERNEL32.127)
162 BOOL32
FindNextFile32W(HANDLE32 handle
, LPWIN32_FIND_DATA32W data
)
164 WIN32_FIND_DATA32A adata
;
167 adata
.dwFileAttributes
= data
->dwFileAttributes
;
168 adata
.ftCreationTime
= data
->ftCreationTime
;
169 adata
.ftLastAccessTime
= data
->ftLastAccessTime
;
170 adata
.ftLastWriteTime
= data
->ftLastWriteTime
;
171 adata
.nFileSizeHigh
= data
->nFileSizeHigh
;
172 adata
.nFileSizeLow
= data
->nFileSizeLow
;
173 adata
.dwReserved0
= data
->dwReserved0
;
174 adata
.dwReserved1
= data
->dwReserved1
;
175 lstrcpyWtoA(adata
.cFileName
,data
->cFileName
);
176 lstrcpyWtoA(adata
.cAlternateFileName
,data
->cAlternateFileName
);
177 res
=FindNextFile32A(handle
,&adata
);
179 data
->dwFileAttributes
= adata
.dwFileAttributes
;
180 data
->ftCreationTime
= adata
.ftCreationTime
;
181 data
->ftLastAccessTime
= adata
.ftLastAccessTime
;
182 data
->ftLastWriteTime
= adata
.ftLastWriteTime
;
183 data
->nFileSizeHigh
= adata
.nFileSizeHigh
;
184 data
->nFileSizeLow
= adata
.nFileSizeLow
;
185 data
->dwReserved0
= adata
.dwReserved0
;
186 data
->dwReserved1
= adata
.dwReserved1
;
187 lstrcpyAtoW(data
->cFileName
,adata
.cFileName
);
188 lstrcpyAtoW(data
->cAlternateFileName
,adata
.cAlternateFileName
);
193 /*************************************************************************
194 * FindFirstFile32A (KERNEL32.123)
197 HANDLE32
FindFirstFile32A(LPCSTR lpfilename_in
,
198 LPWIN32_FIND_DATA32A lpFindFileData
)
200 const char *unixpath
;
202 FindFileContext32
*context
;
203 char lpfilename
[PATH_LEN
];
206 context
= HeapAlloc(SystemHeap
, 0, sizeof(FindFileContext32
));
208 return (INVALID_HANDLE_VALUE
);
210 /* These type of cases
216 lstrcpy32A(lpfilename
, lpfilename_in
);
217 if (lpfilename
[1] != ':' &&
218 lpfilename
[0] != '\\') {
219 /* drive and root path are not set */
220 len
= GetCurrentDirectory32A(PATH_LEN
, lpfilename
);
221 if (lpfilename
[len
-1] != '\\')
222 strcat(lpfilename
, "\\");
223 strcat(lpfilename
, lpfilename_in
);
225 else if (lpfilename
[1] != ':') {
226 /* drive not set, but path is rooted */
227 memmove(&lpfilename
[2], lpfilename
, strlen(lpfilename
));
228 lpfilename
[0] = DRIVE_GetCurrentDrive();
231 else if (lpfilename
[1] == ':' &&
232 lpfilename
[2] != '\\') {
233 /* drive is set, but not root path */
234 lstrcpy32A(lpfilename
, DRIVE_GetDosCwd(lpfilename
[0]));
235 strcat(lpfilename
, lpfilename_in
);
238 dprintf_file(stddeb
, "FindFirstFile32A: %s -> %s .\n",
239 lpfilename_in
, lpfilename
);
241 slash
= strrchr(lpfilename
, '\\');
244 lstrcpyn32A(context
->path
, lpfilename
, slash
- lpfilename
+ 1);
245 context
->path
[slash
- lpfilename
+ 1] = '\0';
246 unixpath
= DOSFS_GetUnixFileName(context
->path
, FALSE
);
248 /* FIXME: SetLastError(??) */
249 HeapFree(SystemHeap
, 0, context
);
250 return INVALID_HANDLE_VALUE
;
252 lstrcpy32A(context
->mask
, slash
+1);
255 /* shouldn't really get here now */
256 context
->path
[0] = '\0';
258 lstrcpy32A(context
->mask
, lpfilename
);
261 lstrcpy32A(context
->unixpath
, unixpath
);
262 context
->dir
= opendir(unixpath
);
264 /* FIXME: SetLastError(??) */
265 HeapFree(SystemHeap
, 0, context
);
266 return INVALID_HANDLE_VALUE
;
269 /* uppercase mask in place */
270 for (p
= context
->mask
; *p
; p
++)
273 if (!FindNextFile32A((HANDLE32
) context
, lpFindFileData
))
274 return (INVALID_HANDLE_VALUE
);
275 return ((HANDLE32
) context
);
278 /*************************************************************************
279 * FindFirstFile32W (KERNEL32.124)
281 HANDLE32
FindFirstFile32W(LPCWSTR filename
,LPWIN32_FIND_DATA32W data
)
283 WIN32_FIND_DATA32A adata
;
284 LPSTR afn
= HEAP_strdupWtoA( GetProcessHeap(), 0, filename
);
285 HANDLE32 res
= FindFirstFile32A(afn
,&adata
);
288 data
->dwFileAttributes
= adata
.dwFileAttributes
;
289 data
->ftCreationTime
= adata
.ftCreationTime
;
290 data
->ftLastAccessTime
= adata
.ftLastAccessTime
;
291 data
->ftLastWriteTime
= adata
.ftLastWriteTime
;
292 data
->nFileSizeHigh
= adata
.nFileSizeHigh
;
293 data
->nFileSizeLow
= adata
.nFileSizeLow
;
294 data
->dwReserved0
= adata
.dwReserved0
;
295 data
->dwReserved1
= adata
.dwReserved1
;
296 lstrcpyAtoW(data
->cFileName
,adata
.cFileName
);
297 lstrcpyAtoW(data
->cAlternateFileName
,adata
.cAlternateFileName
);
299 HeapFree( GetProcessHeap(), 0, afn
);
303 /*************************************************************************
304 * FindClose32 (KERNEL32.119)
306 BOOL32
FindClose32(HANDLE32 handle
)
308 FindFileContext32
*context
;
310 /* Windows95 ignores an invalid handle. */
311 if (handle
== INVALID_HANDLE_VALUE
)
313 SetLastError(ERROR_INVALID_HANDLE
);
316 context
= (FindFileContext32
*) handle
;
318 closedir(context
->dir
);
319 HeapFree(SystemHeap
, 0, context
);
323 /* 16 bit versions of find functions */
324 /*************************************************************************
325 * FindFirstFile16 (KERNEL.413)
329 FindFirstFile16(LPCSTR lpFileName
, LPVOID lpdata
)
331 WIN32_FIND_DATA32A
*findData
= (WIN32_FIND_DATA32A
*) lpdata
;
336 /* get a handle to the real pointer */
339 h32
= FindFirstFile32A(lpFileName
, findData
);
341 h16
= GlobalAlloc16(0, sizeof(h32
));
342 ptr
= GlobalLock16(h16
);
347 return ((HANDLE16
) h32
);
350 /*************************************************************************
351 * FindNextFile16 (KERNEL.414)
355 FindNextFile16(HANDLE16 handle
, LPVOID lpdata
)
357 WIN32_FIND_DATA32A
*findData
= (WIN32_FIND_DATA32A
*) lpdata
;
360 lph32
= GlobalLock16(handle
);
361 if (FindNextFile32A(*lph32
, findData
)) {
368 /*************************************************************************
369 * FindClose16 (KERNEL.415)
373 FindClose16(HANDLE16 handle
)
378 if (handle
== (HANDLE16
) INVALID_HANDLE_VALUE
) {
379 SetLastError(ERROR_INVALID_HANDLE
);
383 lph32
= GlobalLock16(handle
);
384 ret
= FindClose32(*lph32
);
385 GlobalFree16(handle
);