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);
24 static void __CRTDLL__fttofd(LPWIN32_FIND_DATAA fd, find_t* ft)
28 /* Tested with crtdll.dll Version 2.50.4170 (NT) from win98 SE:
29 * attrib 0x80 (FILE_ATTRIBUTE_NORMAL)is returned as 0.
31 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
34 ft->attrib = fd->dwFileAttributes;
36 RtlTimeToSecondsSince1970( &fd->ftCreationTime, &dw );
38 RtlTimeToSecondsSince1970( &fd->ftLastAccessTime, &dw );
40 RtlTimeToSecondsSince1970( &fd->ftLastWriteTime, &dw );
42 ft->size = fd->nFileSizeLow;
43 strcpy(ft->name, fd->cFileName);
47 /*********************************************************************
50 * Change the current directory.
53 * newdir [in] Directory to change to
60 INT __cdecl CRTDLL__chdir(LPCSTR newdir)
62 if (!SetCurrentDirectoryA(newdir))
64 __CRTDLL__set_errno(newdir?GetLastError():0);
71 /*********************************************************************
72 * _chdrive (CRTDLL.52)
74 * Change the current drive.
77 * newdrive [in] new drive to change to, A: =1, B: =2, etc
84 BOOL __cdecl CRTDLL__chdrive(INT newdrive)
86 char buffer[3] = "A:";
87 buffer[0] += newdrive - 1;
88 if (!SetCurrentDirectoryA( buffer ))
90 __CRTDLL__set_errno(GetLastError());
92 CRTDLL_errno = EACCES;
99 /*********************************************************************
100 * _findclose (CRTDLL.098)
102 * Free the resources from a search handle created from _findfirst.
105 * hand [in]: Search handle to close
112 INT __cdecl CRTDLL__findclose(DWORD hand)
114 TRACE(":handle %ld\n",hand);
115 if (!FindClose((HANDLE)hand))
117 __CRTDLL__set_errno(GetLastError());
124 /*********************************************************************
125 * _findfirst (CRTDLL.099)
127 * Create and return a search handle for iterating through a file and
131 * fspec [in] File specification string for search, e.g "C:\*.BAT"
133 * ft [out] A pointer to a find_t structure to populate.
136 * Success: A handle for the search, suitable for passing to _findnext
137 * or _findclose. Populates the members of ft with the details
138 * of the first matching file.
142 DWORD __cdecl CRTDLL__findfirst(LPCSTR fspec, find_t* ft)
144 WIN32_FIND_DATAA find_data;
147 hfind = FindFirstFileA(fspec, &find_data);
148 if (hfind == INVALID_HANDLE_VALUE)
150 __CRTDLL__set_errno(GetLastError());
153 __CRTDLL__fttofd(&find_data,ft);
154 TRACE(":got handle %d\n",hfind);
159 /*********************************************************************
160 * _findnext (CRTDLL.100)
162 * Return the next matching file/directory from a search hadle.
165 * hand [in] Search handle from a pervious call to _findfirst
167 * ft [out] A pointer to a find_t structure to populate.
170 * Success: 0. Populates the members of ft with the details
171 * of the first matching file
175 INT __cdecl CRTDLL__findnext(DWORD hand, find_t * ft)
177 WIN32_FIND_DATAA find_data;
179 if (!FindNextFileA(hand, &find_data))
181 SetLastError(ERROR_INVALID_DRIVE);
182 __CRTDLL__set_errno(GetLastError());
186 __CRTDLL__fttofd(&find_data,ft);
191 /*********************************************************************
192 * _getcwd (CRTDLL.120)
194 * Get the current directory.
197 * buf [out] A buffer to place the current directory name in
199 * size [in] The size of buf.
202 * Success: buf, or if buf is NULL, an allocated buffer
206 CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT size)
209 int dir_len = GetCurrentDirectoryA(_MAX_PATH,dir);
212 return NULL; /* FIXME: Real return value untested */
217 return CRTDLL__strdup(dir);
218 return __CRTDLL__strndup(dir,size);
222 CRTDLL_errno = ERANGE;
223 return NULL; /* buf too small */
230 /*********************************************************************
231 * _getdcwd (CRTDLL.121)
233 * Get the current directory on a drive. A: =1, B: =2, etc.
234 * Passing drive 0 means the current drive.
236 CHAR* __cdecl CRTDLL__getdcwd(INT drive,LPSTR buf, INT size)
240 if (!drive || drive == CRTDLL__getdrive())
241 return CRTDLL__getcwd(buf,size); /* current */
245 char drivespec[4] = {'A', ':', '\\', 0};
248 drivespec[0] += drive - 1;
249 if (GetDriveTypeA(drivespec) < DRIVE_REMOVABLE)
251 CRTDLL_errno = EACCES;
255 dir_len = GetFullPathNameA(drivespec,_MAX_PATH,dir,&dummy);
256 if (dir_len >= size || dir_len < 1)
258 CRTDLL_errno = ERANGE;
259 return NULL; /* buf too small */
263 return CRTDLL__strdup(dir); /* allocate */
271 /*********************************************************************
272 * _getdiskfree (CRTDLL.122)
274 * Get free disk space on given drive or the current drive.
277 UINT __cdecl CRTDLL__getdiskfree(UINT disk, diskfree_t* d)
279 char drivespec[4] = {'@', ':', '\\', 0};
284 return ERROR_INVALID_PARAMETER; /* CRTDLL doesn't set errno here */
286 drivespec[0] += disk; /* make a drive letter */
288 if (GetDiskFreeSpaceA(disk==0?NULL:drivespec,ret,ret+1,ret+2,ret+3))
290 d->cluster_sectors = (unsigned)ret[0];
291 d->sector_bytes = (unsigned)ret[1];
292 d->available = (unsigned)ret[2];
293 d->num_clusters = (unsigned)ret[3];
296 err = GetLastError();
297 __CRTDLL__set_errno(err);
302 /*********************************************************************
303 * _getdrive (CRTDLL.124)
305 * Return current drive, A: =1, B: =2, etc
307 INT __cdecl CRTDLL__getdrive(VOID)
309 char buffer[MAX_PATH];
310 if (!GetCurrentDirectoryA( sizeof(buffer), buffer )) return 0;
311 if (buffer[1] != ':') return 0;
312 return toupper(buffer[0]) - 'A' + 1;
316 /*********************************************************************
317 * _mkdir (CRTDLL.234)
319 * Create a directory.
321 INT __cdecl CRTDLL__mkdir(LPCSTR newdir)
323 if (CreateDirectoryA(newdir,NULL))
326 __CRTDLL__set_errno(GetLastError());
330 /*********************************************************************
331 * _rmdir (CRTDLL.255)
336 INT __cdecl CRTDLL__rmdir(LPSTR dir)
338 if (RemoveDirectoryA(dir))
341 __CRTDLL__set_errno(GetLastError());