2 * CRTDLL drive/directory functions
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
10 * Implementation Notes:
20 DEFAULT_DEBUG_CHANNEL(crtdll);
22 /* INTERNAL: Translate find_t to PWIN32_FIND_DATAA */
23 static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft)
27 /* Tested with crtdll.dll Version 2.50.4170 (NT) from win98 SE:
28 * attrib 0x80 (FILE_ATTRIBUTE_NORMAL)is returned as 0.
30 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
33 ft->attrib = fd->dwFileAttributes;
35 RtlTimeToSecondsSince1970( &fd->ftCreationTime, &dw );
37 RtlTimeToSecondsSince1970( &fd->ftLastAccessTime, &dw );
39 RtlTimeToSecondsSince1970( &fd->ftLastWriteTime, &dw );
41 ft->size = fd->nFileSizeLow;
42 strcpy(ft->name, fd->cFileName);
46 /*********************************************************************
49 * Change the current directory.
52 * newdir [in] Directory to change to
59 INT __cdecl CRTDLL__chdir(LPCSTR newdir)
61 if (!SetCurrentDirectoryA(newdir))
63 __CRTDLL__set_errno(newdir?GetLastError():0);
70 /*********************************************************************
71 * _chdrive (CRTDLL.52)
73 * Change the current drive.
76 * newdrive [in] new drive to change to, A: =1, B: =2, etc
83 BOOL __cdecl CRTDLL__chdrive(INT newdrive)
85 char buffer[3] = "A:";
86 buffer[0] += newdrive - 1;
87 if (!SetCurrentDirectoryA( buffer ))
89 __CRTDLL__set_errno(GetLastError());
91 CRTDLL_errno = EACCES;
98 /*********************************************************************
99 * _findclose (CRTDLL.098)
101 * Free the resources from a search handle created from _findfirst.
104 * hand [in]: Search handle to close
111 INT __cdecl CRTDLL__findclose(DWORD hand)
113 TRACE(":handle %ld\n",hand);
114 if (!FindClose((HANDLE)hand))
116 __CRTDLL__set_errno(GetLastError());
123 /*********************************************************************
124 * _findfirst (CRTDLL.099)
126 * Create and return a search handle for iterating through a file and
130 * fspec [in] File specification string for search, e.g "C:\*.BAT"
132 * ft [out] A pointer to a find_t structure to populate.
135 * Success: A handle for the search, suitable for passing to _findnext
136 * or _findclose. Populates the members of ft with the details
137 * of the first matching file.
141 DWORD __cdecl CRTDLL__findfirst(LPCSTR fspec, find_t* ft)
143 WIN32_FIND_DATAA find_data;
146 hfind = FindFirstFileA(fspec, &find_data);
147 if (hfind == INVALID_HANDLE_VALUE)
149 __CRTDLL__set_errno(GetLastError());
152 __CRTDLL__fttofd(&find_data,ft);
153 TRACE(":got handle %d\n",hfind);
158 /*********************************************************************
159 * _findnext (CRTDLL.100)
161 * Return the next matching file/directory from a search hadle.
164 * hand [in] Search handle from a pervious call to _findfirst
166 * ft [out] A pointer to a find_t structure to populate.
169 * Success: 0. Populates the members of ft with the details
170 * of the first matching file
174 INT __cdecl CRTDLL__findnext(DWORD hand, find_t * ft)
176 WIN32_FIND_DATAA find_data;
178 if (!FindNextFileA(hand, &find_data))
180 SetLastError(ERROR_INVALID_DRIVE);
181 __CRTDLL__set_errno(GetLastError());
185 __CRTDLL__fttofd(&find_data,ft);
190 /*********************************************************************
191 * _getcwd (CRTDLL.120)
193 * Get the current directory.
196 * buf [out] A buffer to place the current directory name in
198 * size [in] The size of buf.
201 * Success: buf, or if buf is NULL, an allocated buffer
205 CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT size)
208 int dir_len = GetCurrentDirectoryA(MAX_PATH,dir);
211 return NULL; /* FIXME: Real return value untested */
213 TRACE(":returning '%s'\n", dir);
218 return CRTDLL__strdup(dir);
219 return __CRTDLL__strndup(dir,size);
223 CRTDLL_errno = ERANGE;
224 return NULL; /* buf too small */
231 /*********************************************************************
232 * _getdcwd (CRTDLL.121)
234 * Get the current directory on a drive. A: =1, B: =2, etc.
235 * Passing drive 0 means the current drive.
237 CHAR* __cdecl CRTDLL__getdcwd(INT drive, LPSTR buf, INT size)
241 TRACE(":drive %d(%c), size %d\n",drive, drive + 'A' - 1, size);
243 if (!drive || drive == CRTDLL__getdrive())
244 return CRTDLL__getcwd(buf,size); /* current */
248 char drivespec[4] = {'A', ':', '\\', 0};
251 drivespec[0] += drive - 1;
252 if (GetDriveTypeA(drivespec) < DRIVE_REMOVABLE)
254 CRTDLL_errno = EACCES;
258 dir_len = GetFullPathNameA(drivespec,_MAX_PATH,dir,&dummy);
259 if (dir_len >= size || dir_len < 1)
261 CRTDLL_errno = ERANGE;
262 return NULL; /* buf too small */
265 TRACE(":returning '%s'\n", dir);
267 return CRTDLL__strdup(dir); /* allocate */
275 /*********************************************************************
276 * _getdiskfree (CRTDLL.122)
278 * Get free disk space on given drive or the current drive.
281 UINT __cdecl CRTDLL__getdiskfree(UINT disk, diskfree_t* d)
283 char drivespec[4] = {'@', ':', '\\', 0};
288 return ERROR_INVALID_PARAMETER; /* CRTDLL doesn't set errno here */
290 drivespec[0] += disk; /* make a drive letter */
292 if (GetDiskFreeSpaceA(disk==0?NULL:drivespec,ret,ret+1,ret+2,ret+3))
294 d->cluster_sectors = (unsigned)ret[0];
295 d->sector_bytes = (unsigned)ret[1];
296 d->available = (unsigned)ret[2];
297 d->num_clusters = (unsigned)ret[3];
300 err = GetLastError();
301 __CRTDLL__set_errno(err);
306 /*********************************************************************
307 * _getdrive (CRTDLL.124)
309 * Return current drive, A: =1, B: =2, etc
311 INT __cdecl CRTDLL__getdrive(VOID)
313 char buffer[MAX_PATH];
314 if (!GetCurrentDirectoryA( sizeof(buffer), buffer )) return 0;
315 if (buffer[1] != ':') return 0;
316 return toupper(buffer[0]) - 'A' + 1;
320 /*********************************************************************
321 * _mkdir (CRTDLL.234)
323 * Create a directory.
325 INT __cdecl CRTDLL__mkdir(LPCSTR newdir)
327 if (CreateDirectoryA(newdir,NULL))
330 __CRTDLL__set_errno(GetLastError());
334 /*********************************************************************
335 * _rmdir (CRTDLL.255)
340 INT __cdecl CRTDLL__rmdir(LPSTR dir)
342 if (RemoveDirectoryA(dir))
345 __CRTDLL__set_errno(GetLastError());