Removed calls to Wine internal functions.
[wine] / dlls / crtdll / dir.c
1 /*
2  * CRTDLL drive/directory functions
3  * 
4  * Copyright 1996,1998 Marcus Meissner
5  * Copyright 1996 Jukka Iivonen
6  * Copyright 1997,2000 Uwe Bonnes
7  * Copyright 2000 Jon Griffiths
8  *
9  *
10  * Implementation Notes:
11  * MT Safe.
12  */
13
14 #include "crtdll.h"
15 #include <errno.h>
16
17 #include "ntddk.h"
18 #include <time.h>
19
20 DEFAULT_DEBUG_CHANNEL(crtdll);
21
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)
25 {
26   DWORD dw;
27
28   /* Tested with crtdll.dll Version 2.50.4170 (NT) from win98 SE:
29    * attrib 0x80 (FILE_ATTRIBUTE_NORMAL)is returned as 0.
30    */
31   if (fd->dwFileAttributes  == FILE_ATTRIBUTE_NORMAL)
32     ft->attrib = 0;
33   else
34     ft->attrib = fd->dwFileAttributes;
35
36   RtlTimeToSecondsSince1970( &fd->ftCreationTime, &dw );
37   ft->time_create = dw;
38   RtlTimeToSecondsSince1970( &fd->ftLastAccessTime, &dw );
39   ft->time_access = dw;
40   RtlTimeToSecondsSince1970( &fd->ftLastWriteTime, &dw );
41   ft->time_write = dw;
42   ft->size = fd->nFileSizeLow;
43   strcpy(ft->name, fd->cFileName);
44 }
45
46
47 /*********************************************************************
48  *                  _chdir           (CRTDLL.51)
49  *
50  * Change the current directory.
51  *
52  * PARAMS
53  *   newdir [in] Directory to change to
54  *
55  * RETURNS
56  * Sucess:  0
57  * 
58  * Failure: -1
59  */
60 INT __cdecl CRTDLL__chdir(LPCSTR newdir)
61 {
62   if (!SetCurrentDirectoryA(newdir))
63   {
64     __CRTDLL__set_errno(newdir?GetLastError():0);
65     return -1;
66   }
67   return 0;
68 }
69
70
71 /*********************************************************************
72  *                  _chdrive           (CRTDLL.52)
73  *
74  * Change the current drive.
75  *
76  * PARAMS
77  *   newdrive [in] new drive to change to, A: =1, B: =2, etc
78  *
79  * RETURNS
80  * Sucess:  0
81  * 
82  * Failure: 1 
83  */
84 BOOL __cdecl CRTDLL__chdrive(INT newdrive)
85 {
86   char buffer[3] = "A:";
87   buffer[0] += newdrive - 1;
88   if (!SetCurrentDirectoryA( buffer ))
89   {
90     __CRTDLL__set_errno(GetLastError());
91     if (newdrive <= 0)
92       CRTDLL_errno = EACCES;
93     return -1;
94   }
95   return 0;
96 }
97
98
99 /*********************************************************************
100  *                  _findclose     (CRTDLL.098)
101  * 
102  * Free the resources from a search handle created from _findfirst.
103  *
104  * PARAMS
105  *   hand [in]: Search handle to close
106  *
107  * RETURNS
108  * Success:  0
109  *
110  * Failure:  -1
111  */
112 INT __cdecl CRTDLL__findclose(DWORD hand)
113 {
114   TRACE(":handle %ld\n",hand);
115   if (!FindClose((HANDLE)hand))
116   {
117     __CRTDLL__set_errno(GetLastError());
118     return -1;
119   }
120   return 0;
121 }
122
123
124  /*********************************************************************
125  *                  _findfirst    (CRTDLL.099)
126  *
127  * Create and return a search handle for iterating through a file and
128  * directory list.
129  *
130  * PARAMS
131  *   fspec [in]  File specification string for search, e.g "C:\*.BAT"
132  * 
133  *   ft [out]    A pointer to a find_t structure to populate.
134  *
135  * RETURNS
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.
139  *
140  * Failure:  -1.
141  */
142 DWORD __cdecl CRTDLL__findfirst(LPCSTR fspec, find_t* ft)
143 {
144   WIN32_FIND_DATAA find_data;
145   HANDLE hfind;
146
147   hfind  = FindFirstFileA(fspec, &find_data);
148   if (hfind == INVALID_HANDLE_VALUE)
149   {
150     __CRTDLL__set_errno(GetLastError());
151     return -1;
152   }
153   __CRTDLL__fttofd(&find_data,ft);
154   TRACE(":got handle %d\n",hfind);
155   return hfind;
156 }
157
158
159 /*********************************************************************
160  *                  _findnext     (CRTDLL.100)
161  * 
162  * Return the next matching file/directory from a search hadle.
163  *
164  * PARAMS
165  *   hand [in] Search handle from a pervious call to _findfirst
166  * 
167  *   ft [out]  A pointer to a find_t structure to populate.
168  *
169  * RETURNS
170  * Success:  0. Populates the members of ft with the details
171  *           of the first matching file
172  *
173  * Failure:  -1
174  */
175 INT __cdecl CRTDLL__findnext(DWORD hand, find_t * ft)
176 {
177   WIN32_FIND_DATAA find_data;
178
179   if (!FindNextFileA(hand, &find_data))
180   {
181     SetLastError(ERROR_INVALID_DRIVE);
182     __CRTDLL__set_errno(GetLastError());
183     return -1;
184   }
185
186   __CRTDLL__fttofd(&find_data,ft);
187   return 0;
188 }
189
190
191 /*********************************************************************
192  *                  _getcwd           (CRTDLL.120)
193  *
194  * Get the current directory.
195  *
196  * PARAMS
197  * buf [out]  A buffer to place the current directory name in
198  *
199  * size [in]  The size of buf.
200  *
201  * RETURNS
202  * Success: buf, or if buf is NULL, an allocated buffer
203  *
204  * Failure: NULL
205  */
206 CHAR* __cdecl CRTDLL__getcwd(LPSTR buf, INT size)
207 {
208   char dir[_MAX_PATH];
209   int dir_len = GetCurrentDirectoryA(_MAX_PATH,dir);
210
211   if (dir_len < 1)
212     return NULL; /* FIXME: Real return value untested */
213
214   if (!buf)
215   {
216     if (size < 0)
217       return CRTDLL__strdup(dir);
218     return __CRTDLL__strndup(dir,size);
219   }
220   if (dir_len >= size)
221   {
222     CRTDLL_errno = ERANGE;
223     return NULL; /* buf too small */
224   }
225   strcpy(buf,dir);
226   return buf;
227 }
228
229
230 /*********************************************************************
231  *                  _getdcwd           (CRTDLL.121)
232  *
233  * Get the current directory on a drive. A: =1, B: =2, etc.
234  * Passing drive 0 means the current drive.
235  */
236 CHAR* __cdecl CRTDLL__getdcwd(INT drive,LPSTR buf, INT size)
237 {
238   static CHAR* dummy;
239
240   if (!drive || drive == CRTDLL__getdrive())
241     return CRTDLL__getcwd(buf,size); /* current */
242   else
243   {
244     char dir[_MAX_PATH];
245     char drivespec[4] = {'A', ':', '\\', 0};
246     int dir_len;
247
248     drivespec[0] += drive - 1;
249     if (GetDriveTypeA(drivespec) < DRIVE_REMOVABLE)
250     {
251       CRTDLL_errno = EACCES;
252       return NULL;
253     }
254
255     dir_len = GetFullPathNameA(drivespec,_MAX_PATH,dir,&dummy);
256     if (dir_len >= size || dir_len < 1)
257     {
258       CRTDLL_errno = ERANGE;
259       return NULL; /* buf too small */
260     }
261
262     if (!buf)
263       return CRTDLL__strdup(dir); /* allocate */
264
265     strcpy(buf,dir);
266   }
267   return buf;
268 }
269
270
271 /*********************************************************************
272  *                  _getdiskfree     (CRTDLL.122)
273  *
274  * Get free disk space on given drive or the current drive.
275  *
276  */
277 UINT __cdecl CRTDLL__getdiskfree(UINT disk, diskfree_t* d)
278 {
279   char drivespec[4] = {'@', ':', '\\', 0};
280   DWORD ret[4];
281   UINT err;
282
283   if (disk > 26)
284     return ERROR_INVALID_PARAMETER; /* CRTDLL doesn't set errno here */
285
286   drivespec[0] += disk; /* make a drive letter */
287
288   if (GetDiskFreeSpaceA(disk==0?NULL:drivespec,ret,ret+1,ret+2,ret+3))
289   {
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];
294     return 0;
295   }
296   err = GetLastError();
297   __CRTDLL__set_errno(err);
298   return err;
299 }
300
301
302 /*********************************************************************
303  *                  _getdrive           (CRTDLL.124)
304  *
305  *  Return current drive, A: =1, B: =2, etc
306  */
307 INT __cdecl CRTDLL__getdrive(VOID)
308 {
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;
313 }
314
315
316 /*********************************************************************
317  *                  _mkdir           (CRTDLL.234)
318  *
319  * Create a directory.
320  */
321 INT __cdecl CRTDLL__mkdir(LPCSTR newdir)
322 {
323   if (CreateDirectoryA(newdir,NULL))
324     return 0;
325
326   __CRTDLL__set_errno(GetLastError());
327   return -1;
328 }
329
330 /*********************************************************************
331  *                  _rmdir           (CRTDLL.255)
332  *
333  * Delete a directory 
334  *
335  */
336 INT __cdecl CRTDLL__rmdir(LPSTR dir)
337 {
338   if (RemoveDirectoryA(dir))
339     return 0;
340
341   __CRTDLL__set_errno(GetLastError());
342   return -1;
343 }