2 * msvcrt.dll 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
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wine/port.h"
32 #include "wine/unicode.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
38 /* INTERNAL: Translate WIN32_FIND_DATAA to finddata_t */
39 static void msvcrt_fttofd( const WIN32_FIND_DATAA
*fd
, struct MSVCRT__finddata_t
* ft
)
43 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
46 ft
->attrib
= fd
->dwFileAttributes
;
48 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
50 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
52 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
54 ft
->size
= fd
->nFileSizeLow
;
55 strcpy(ft
->name
, fd
->cFileName
);
58 /* INTERNAL: Translate WIN32_FIND_DATAA to finddata32_t */
59 static void msvcrt_fttofd32( const WIN32_FIND_DATAA
*fd
, struct MSVCRT__finddata32_t
* ft
)
63 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
66 ft
->attrib
= fd
->dwFileAttributes
;
68 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
70 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
72 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
74 ft
->size
= fd
->nFileSizeLow
;
75 strcpy(ft
->name
, fd
->cFileName
);
78 /* INTERNAL: Translate WIN32_FIND_DATAW to wfinddata_t */
79 static void msvcrt_wfttofd( const WIN32_FIND_DATAW
*fd
, struct MSVCRT__wfinddata_t
* ft
)
83 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
86 ft
->attrib
= fd
->dwFileAttributes
;
88 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
90 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
92 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
94 ft
->size
= fd
->nFileSizeLow
;
95 strcpyW(ft
->name
, fd
->cFileName
);
98 /* INTERNAL: Translate WIN32_FIND_DATAW to wfinddata32_t */
99 static void msvcrt_wfttofd32(const WIN32_FIND_DATAW
*fd
, struct MSVCRT__wfinddata32_t
* ft
)
103 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
106 ft
->attrib
= fd
->dwFileAttributes
;
108 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
109 ft
->time_create
= dw
;
110 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
111 ft
->time_access
= dw
;
112 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
114 ft
->size
= fd
->nFileSizeLow
;
115 strcpyW(ft
->name
, fd
->cFileName
);
118 /* INTERNAL: Translate WIN32_FIND_DATAA to finddatai64_t */
119 static void msvcrt_fttofdi64( const WIN32_FIND_DATAA
*fd
, struct MSVCRT__finddatai64_t
* ft
)
123 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
126 ft
->attrib
= fd
->dwFileAttributes
;
128 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
129 ft
->time_create
= dw
;
130 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
131 ft
->time_access
= dw
;
132 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
134 ft
->size
= ((__int64
)fd
->nFileSizeHigh
) << 32 | fd
->nFileSizeLow
;
135 strcpy(ft
->name
, fd
->cFileName
);
138 /* INTERNAL: Translate WIN32_FIND_DATAA to finddata64_t */
139 static void msvcrt_fttofd64( const WIN32_FIND_DATAA
*fd
, struct MSVCRT__finddata64_t
* ft
)
143 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
146 ft
->attrib
= fd
->dwFileAttributes
;
148 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
149 ft
->time_create
= dw
;
150 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
151 ft
->time_access
= dw
;
152 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
154 ft
->size
= ((__int64
)fd
->nFileSizeHigh
) << 32 | fd
->nFileSizeLow
;
155 strcpy(ft
->name
, fd
->cFileName
);
158 /* INTERNAL: Translate WIN32_FIND_DATAW to wfinddata64_t */
159 static void msvcrt_wfttofd64( const WIN32_FIND_DATAW
*fd
, struct MSVCRT__wfinddata64_t
* ft
)
163 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
166 ft
->attrib
= fd
->dwFileAttributes
;
168 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
169 ft
->time_create
= dw
;
170 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
171 ft
->time_access
= dw
;
172 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
174 ft
->size
= ((__int64
)fd
->nFileSizeHigh
) << 32 | fd
->nFileSizeLow
;
175 strcpyW(ft
->name
, fd
->cFileName
);
178 /* INTERNAL: Translate WIN32_FIND_DATAA to finddata64i32_t */
179 static void msvcrt_fttofd64i32( const WIN32_FIND_DATAA
*fd
, struct MSVCRT__finddata64i32_t
* ft
)
183 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
186 ft
->attrib
= fd
->dwFileAttributes
;
188 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
189 ft
->time_create
= dw
;
190 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
191 ft
->time_access
= dw
;
192 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
194 ft
->size
= fd
->nFileSizeLow
;
195 strcpy(ft
->name
, fd
->cFileName
);
198 /* INTERNAL: Translate WIN32_FIND_DATAW to wfinddatai64_t */
199 static void msvcrt_wfttofdi64( const WIN32_FIND_DATAW
*fd
, struct MSVCRT__wfinddatai64_t
* ft
)
203 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
206 ft
->attrib
= fd
->dwFileAttributes
;
208 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
209 ft
->time_create
= dw
;
210 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
211 ft
->time_access
= dw
;
212 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
214 ft
->size
= ((__int64
)fd
->nFileSizeHigh
) << 32 | fd
->nFileSizeLow
;
215 strcpyW(ft
->name
, fd
->cFileName
);
218 /* INTERNAL: Translate WIN32_FIND_DATAW to wfinddata64i32_t */
219 static void msvcrt_wfttofd64i32( const WIN32_FIND_DATAW
*fd
, struct MSVCRT__wfinddata64i32_t
* ft
)
223 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
226 ft
->attrib
= fd
->dwFileAttributes
;
228 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
229 ft
->time_create
= dw
;
230 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
231 ft
->time_access
= dw
;
232 RtlTimeToSecondsSince1970( (const LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
234 ft
->size
= fd
->nFileSizeLow
;
235 strcpyW(ft
->name
, fd
->cFileName
);
238 /*********************************************************************
241 * Change the current working directory.
244 * newdir [I] Directory to change to
247 * Success: 0. The current working directory is set to newdir.
248 * Failure: -1. errno indicates the error.
251 * See SetCurrentDirectoryA.
253 int CDECL
MSVCRT__chdir(const char * newdir
)
255 if (!SetCurrentDirectoryA(newdir
))
257 msvcrt_set_errno(newdir
?GetLastError():0);
263 /*********************************************************************
266 * Unicode version of _chdir.
268 int CDECL
MSVCRT__wchdir(const MSVCRT_wchar_t
* newdir
)
270 if (!SetCurrentDirectoryW(newdir
))
272 msvcrt_set_errno(newdir
?GetLastError():0);
278 /*********************************************************************
279 * _chdrive (MSVCRT.@)
281 * Change the current drive.
284 * newdrive [I] Drive number to change to (1 = 'A', 2 = 'B', ...)
287 * Success: 0. The current drive is set to newdrive.
288 * Failure: -1. errno indicates the error.
291 * See SetCurrentDirectoryA.
293 int CDECL
MSVCRT__chdrive(int newdrive
)
295 WCHAR buffer
[] = {'A', ':', 0};
297 buffer
[0] += newdrive
- 1;
298 if (!SetCurrentDirectoryW( buffer
))
300 msvcrt_set_errno(GetLastError());
302 *MSVCRT__errno() = MSVCRT_EACCES
;
308 /*********************************************************************
309 * _findclose (MSVCRT.@)
311 * Close a handle returned by _findfirst().
314 * hand [I] Handle to close
317 * Success: 0. All resources associated with hand are freed.
318 * Failure: -1. errno indicates the error.
323 int CDECL
MSVCRT__findclose(MSVCRT_intptr_t hand
)
325 TRACE(":handle %ld\n",hand
);
326 if (!FindClose((HANDLE
)hand
))
328 msvcrt_set_errno(GetLastError());
334 /*********************************************************************
335 * _findfirst (MSVCRT.@)
337 * Open a handle for iterating through a directory.
340 * fspec [I] File specification of files to iterate.
341 * ft [O] Information for the first file found.
344 * Success: A handle suitable for passing to _findnext() and _findclose().
345 * ft is populated with the details of the found file.
346 * Failure: -1. errno indicates the error.
349 * See FindFirstFileA.
351 MSVCRT_intptr_t CDECL
MSVCRT__findfirst(const char * fspec
, struct MSVCRT__finddata_t
* ft
)
353 WIN32_FIND_DATAA find_data
;
356 hfind
= FindFirstFileA(fspec
, &find_data
);
357 if (hfind
== INVALID_HANDLE_VALUE
)
359 msvcrt_set_errno(GetLastError());
362 msvcrt_fttofd(&find_data
,ft
);
363 TRACE(":got handle %p\n",hfind
);
364 return (MSVCRT_intptr_t
)hfind
;
367 /*********************************************************************
368 * _findfirst32 (MSVCRT.@)
370 MSVCRT_intptr_t CDECL
MSVCRT__findfirst32(const char * fspec
, struct MSVCRT__finddata32_t
* ft
)
372 WIN32_FIND_DATAA find_data
;
375 hfind
= FindFirstFileA(fspec
, &find_data
);
376 if (hfind
== INVALID_HANDLE_VALUE
)
378 msvcrt_set_errno(GetLastError());
381 msvcrt_fttofd32(&find_data
, ft
);
382 TRACE(":got handle %p\n", hfind
);
383 return (MSVCRT_intptr_t
)hfind
;
386 /*********************************************************************
387 * _wfindfirst (MSVCRT.@)
389 * Unicode version of _findfirst.
391 MSVCRT_intptr_t CDECL
MSVCRT__wfindfirst(const MSVCRT_wchar_t
* fspec
, struct MSVCRT__wfinddata_t
* ft
)
393 WIN32_FIND_DATAW find_data
;
396 hfind
= FindFirstFileW(fspec
, &find_data
);
397 if (hfind
== INVALID_HANDLE_VALUE
)
399 msvcrt_set_errno(GetLastError());
402 msvcrt_wfttofd(&find_data
,ft
);
403 TRACE(":got handle %p\n",hfind
);
404 return (MSVCRT_intptr_t
)hfind
;
407 /*********************************************************************
408 * _wfindfirst32 (MSVCRT.@)
410 * Unicode version of _findfirst32.
412 MSVCRT_intptr_t CDECL
MSVCRT__wfindfirst32(const MSVCRT_wchar_t
* fspec
, struct MSVCRT__wfinddata32_t
* ft
)
414 WIN32_FIND_DATAW find_data
;
417 hfind
= FindFirstFileW(fspec
, &find_data
);
418 if (hfind
== INVALID_HANDLE_VALUE
)
420 msvcrt_set_errno(GetLastError());
423 msvcrt_wfttofd32(&find_data
, ft
);
424 TRACE(":got handle %p\n", hfind
);
425 return (MSVCRT_intptr_t
)hfind
;
428 /*********************************************************************
429 * _findfirsti64 (MSVCRT.@)
431 * 64-bit version of _findfirst.
433 MSVCRT_intptr_t CDECL
MSVCRT__findfirsti64(const char * fspec
, struct MSVCRT__finddatai64_t
* ft
)
435 WIN32_FIND_DATAA find_data
;
438 hfind
= FindFirstFileA(fspec
, &find_data
);
439 if (hfind
== INVALID_HANDLE_VALUE
)
441 msvcrt_set_errno(GetLastError());
444 msvcrt_fttofdi64(&find_data
,ft
);
445 TRACE(":got handle %p\n",hfind
);
446 return (MSVCRT_intptr_t
)hfind
;
449 /*********************************************************************
450 * _findfirst64 (MSVCRT.@)
452 * 64-bit version of _findfirst.
454 MSVCRT_intptr_t CDECL
MSVCRT__findfirst64(const char * fspec
, struct MSVCRT__finddata64_t
* ft
)
456 WIN32_FIND_DATAA find_data
;
459 hfind
= FindFirstFileA(fspec
, &find_data
);
460 if (hfind
== INVALID_HANDLE_VALUE
)
462 msvcrt_set_errno(GetLastError());
465 msvcrt_fttofd64(&find_data
,ft
);
466 TRACE(":got handle %p\n",hfind
);
467 return (MSVCRT_intptr_t
)hfind
;
470 /*********************************************************************
471 * _wfindfirst64 (MSVCRT.@)
473 * Unicode version of _findfirst64.
475 MSVCRT_intptr_t CDECL
MSVCRT__wfindfirst64(const MSVCRT_wchar_t
* fspec
, struct MSVCRT__wfinddata64_t
* ft
)
477 WIN32_FIND_DATAW find_data
;
480 hfind
= FindFirstFileW(fspec
, &find_data
);
481 if (hfind
== INVALID_HANDLE_VALUE
)
483 msvcrt_set_errno(GetLastError());
486 msvcrt_wfttofd64(&find_data
,ft
);
487 TRACE(":got handle %p\n",hfind
);
488 return (MSVCRT_intptr_t
)hfind
;
491 /*********************************************************************
492 * _findfirst64i32 (MSVCRT.@)
494 * 64-bit/32-bit version of _findfirst.
496 MSVCRT_intptr_t CDECL
MSVCRT__findfirst64i32(const char * fspec
, struct MSVCRT__finddata64i32_t
* ft
)
498 WIN32_FIND_DATAA find_data
;
501 hfind
= FindFirstFileA(fspec
, &find_data
);
502 if (hfind
== INVALID_HANDLE_VALUE
)
504 msvcrt_set_errno(GetLastError());
507 msvcrt_fttofd64i32(&find_data
,ft
);
508 TRACE(":got handle %p\n",hfind
);
509 return (MSVCRT_intptr_t
)hfind
;
512 /*********************************************************************
513 * _wfindfirst64i32 (MSVCRT.@)
515 * Unicode version of _findfirst64i32.
517 MSVCRT_intptr_t CDECL
MSVCRT__wfindfirst64i32(const MSVCRT_wchar_t
* fspec
, struct MSVCRT__wfinddata64i32_t
* ft
)
519 WIN32_FIND_DATAW find_data
;
522 hfind
= FindFirstFileW(fspec
, &find_data
);
523 if (hfind
== INVALID_HANDLE_VALUE
)
525 msvcrt_set_errno(GetLastError());
528 msvcrt_wfttofd64i32(&find_data
,ft
);
529 TRACE(":got handle %p\n",hfind
);
530 return (MSVCRT_intptr_t
)hfind
;
533 /*********************************************************************
534 * _wfindfirsti64 (MSVCRT.@)
536 * Unicode version of _findfirsti64.
538 MSVCRT_intptr_t CDECL
MSVCRT__wfindfirsti64(const MSVCRT_wchar_t
* fspec
, struct MSVCRT__wfinddatai64_t
* ft
)
540 WIN32_FIND_DATAW find_data
;
543 hfind
= FindFirstFileW(fspec
, &find_data
);
544 if (hfind
== INVALID_HANDLE_VALUE
)
546 msvcrt_set_errno(GetLastError());
549 msvcrt_wfttofdi64(&find_data
,ft
);
550 TRACE(":got handle %p\n",hfind
);
551 return (MSVCRT_intptr_t
)hfind
;
554 /*********************************************************************
555 * _findnext (MSVCRT.@)
557 * Find the next file from a file search handle.
560 * hand [I] Handle to the search returned from _findfirst().
561 * ft [O] Information for the file found.
564 * Success: 0. ft is populated with the details of the found file.
565 * Failure: -1. errno indicates the error.
570 int CDECL
MSVCRT__findnext(MSVCRT_intptr_t hand
, struct MSVCRT__finddata_t
* ft
)
572 WIN32_FIND_DATAA find_data
;
574 if (!FindNextFileA((HANDLE
)hand
, &find_data
))
576 *MSVCRT__errno() = MSVCRT_ENOENT
;
580 msvcrt_fttofd(&find_data
,ft
);
584 /*********************************************************************
585 * _findnext32 (MSVCRT.@)
587 int CDECL
MSVCRT__findnext32(MSVCRT_intptr_t hand
, struct MSVCRT__finddata32_t
* ft
)
589 WIN32_FIND_DATAA find_data
;
591 if (!FindNextFileA((HANDLE
)hand
, &find_data
))
593 *MSVCRT__errno() = MSVCRT_ENOENT
;
597 msvcrt_fttofd32(&find_data
, ft
);
601 /*********************************************************************
602 * _wfindnext (MSVCRT.@)
604 * Unicode version of _findnext.
606 int CDECL
MSVCRT__wfindnext(MSVCRT_intptr_t hand
, struct MSVCRT__wfinddata_t
* ft
)
608 WIN32_FIND_DATAW find_data
;
610 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
612 *MSVCRT__errno() = MSVCRT_ENOENT
;
616 msvcrt_wfttofd(&find_data
,ft
);
620 /*********************************************************************
621 * _findnexti64 (MSVCRT.@)
623 * 64-bit version of _findnext.
625 int CDECL
MSVCRT__findnexti64(MSVCRT_intptr_t hand
, struct MSVCRT__finddatai64_t
* ft
)
627 WIN32_FIND_DATAA find_data
;
629 if (!FindNextFileA((HANDLE
)hand
, &find_data
))
631 *MSVCRT__errno() = MSVCRT_ENOENT
;
635 msvcrt_fttofdi64(&find_data
,ft
);
639 /*********************************************************************
640 * _findnext64 (MSVCRT.@)
642 * 64-bit version of _findnext.
644 int CDECL
MSVCRT__findnext64(MSVCRT_intptr_t hand
, struct MSVCRT__finddata64_t
* ft
)
646 WIN32_FIND_DATAA find_data
;
648 if (!FindNextFileA((HANDLE
)hand
, &find_data
))
650 *MSVCRT__errno() = MSVCRT_ENOENT
;
654 msvcrt_fttofd64(&find_data
,ft
);
658 /*********************************************************************
659 * _wfindnext64 (MSVCRT.@)
661 * Unicode version of _wfindnext64.
663 int CDECL
MSVCRT__wfindnext64(MSVCRT_intptr_t hand
, struct MSVCRT__wfinddata64_t
* ft
)
665 WIN32_FIND_DATAW find_data
;
667 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
669 *MSVCRT__errno() = MSVCRT_ENOENT
;
673 msvcrt_wfttofd64(&find_data
,ft
);
677 /*********************************************************************
678 * _findnext64i32 (MSVCRT.@)
680 * 64-bit/32-bit version of _findnext.
682 int CDECL
MSVCRT__findnext64i32(MSVCRT_intptr_t hand
, struct MSVCRT__finddata64i32_t
* ft
)
684 WIN32_FIND_DATAA find_data
;
686 if (!FindNextFileA((HANDLE
)hand
, &find_data
))
688 *MSVCRT__errno() = MSVCRT_ENOENT
;
692 msvcrt_fttofd64i32(&find_data
,ft
);
696 /*********************************************************************
697 * _wfindnexti64 (MSVCRT.@)
699 * Unicode version of _findnexti64.
701 int CDECL
MSVCRT__wfindnexti64(MSVCRT_intptr_t hand
, struct MSVCRT__wfinddatai64_t
* ft
)
703 WIN32_FIND_DATAW find_data
;
705 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
707 *MSVCRT__errno() = MSVCRT_ENOENT
;
711 msvcrt_wfttofdi64(&find_data
,ft
);
715 /*********************************************************************
716 * _wfindnext64i32 (MSVCRT.@)
718 * Unicode version of _findnext64i32.
720 int CDECL
MSVCRT__wfindnext64i32(MSVCRT_intptr_t hand
, struct MSVCRT__wfinddata64i32_t
* ft
)
722 WIN32_FIND_DATAW find_data
;
724 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
726 *MSVCRT__errno() = MSVCRT_ENOENT
;
730 msvcrt_wfttofd64i32(&find_data
,ft
);
734 /*********************************************************************
737 * Get the current working directory.
740 * buf [O] Destination for current working directory.
741 * size [I] Size of buf in characters
744 * Success: If buf is NULL, returns an allocated string containing the path.
745 * Otherwise populates buf with the path and returns it.
746 * Failure: NULL. errno indicates the error.
748 char* CDECL
MSVCRT__getcwd(char * buf
, int size
)
751 int dir_len
= GetCurrentDirectoryA(MAX_PATH
,dir
);
754 return NULL
; /* FIXME: Real return value untested */
758 if (size
<= dir_len
) size
= dir_len
+ 1;
759 if (!(buf
= MSVCRT_malloc( size
))) return NULL
;
761 else if (dir_len
>= size
)
763 *MSVCRT__errno() = MSVCRT_ERANGE
;
764 return NULL
; /* buf too small */
770 /*********************************************************************
771 * _wgetcwd (MSVCRT.@)
773 * Unicode version of _getcwd.
775 MSVCRT_wchar_t
* CDECL
MSVCRT__wgetcwd(MSVCRT_wchar_t
* buf
, int size
)
777 MSVCRT_wchar_t dir
[MAX_PATH
];
778 int dir_len
= GetCurrentDirectoryW(MAX_PATH
,dir
);
781 return NULL
; /* FIXME: Real return value untested */
785 if (size
<= dir_len
) size
= dir_len
+ 1;
786 if (!(buf
= MSVCRT_malloc( size
* sizeof(WCHAR
) ))) return NULL
;
790 *MSVCRT__errno() = MSVCRT_ERANGE
;
791 return NULL
; /* buf too small */
797 /*********************************************************************
798 * _getdrive (MSVCRT.@)
800 * Get the current drive number.
806 * Success: The drive letter number from 1 to 26 ("A:" to "Z:").
809 int CDECL
MSVCRT__getdrive(void)
811 WCHAR buffer
[MAX_PATH
];
812 if (GetCurrentDirectoryW( MAX_PATH
, buffer
) &&
813 buffer
[0] >= 'A' && buffer
[0] <= 'z' && buffer
[1] == ':')
814 return toupperW(buffer
[0]) - 'A' + 1;
818 /*********************************************************************
819 * _getdcwd (MSVCRT.@)
821 * Get the current working directory on a given disk.
824 * drive [I] Drive letter to get the current working directory from.
825 * buf [O] Destination for the current working directory.
826 * size [I] Length of drive in characters.
829 * Success: If drive is NULL, returns an allocated string containing the path.
830 * Otherwise populates drive with the path and returns it.
831 * Failure: NULL. errno indicates the error.
833 char* CDECL
MSVCRT__getdcwd(int drive
, char * buf
, int size
)
837 TRACE(":drive %d(%c), size %d\n",drive
, drive
+ 'A' - 1, size
);
839 if (!drive
|| drive
== MSVCRT__getdrive())
840 return MSVCRT__getcwd(buf
,size
); /* current */
844 char drivespec
[] = {'A', ':', 0};
847 drivespec
[0] += drive
- 1;
848 if (GetDriveTypeA(drivespec
) < DRIVE_REMOVABLE
)
850 *MSVCRT__errno() = MSVCRT_EACCES
;
854 dir_len
= GetFullPathNameA(drivespec
,MAX_PATH
,dir
,&dummy
);
855 if (dir_len
>= size
|| dir_len
< 1)
857 *MSVCRT__errno() = MSVCRT_ERANGE
;
858 return NULL
; /* buf too small */
861 TRACE(":returning '%s'\n", dir
);
863 return MSVCRT__strdup(dir
); /* allocate */
870 /*********************************************************************
871 * _wgetdcwd (MSVCRT.@)
873 * Unicode version of _wgetdcwd.
875 MSVCRT_wchar_t
* CDECL
MSVCRT__wgetdcwd(int drive
, MSVCRT_wchar_t
* buf
, int size
)
877 static MSVCRT_wchar_t
* dummy
;
879 TRACE(":drive %d(%c), size %d\n",drive
, drive
+ 'A' - 1, size
);
881 if (!drive
|| drive
== MSVCRT__getdrive())
882 return MSVCRT__wgetcwd(buf
,size
); /* current */
885 MSVCRT_wchar_t dir
[MAX_PATH
];
886 MSVCRT_wchar_t drivespec
[4] = {'A', ':', '\\', 0};
889 drivespec
[0] += drive
- 1;
890 if (GetDriveTypeW(drivespec
) < DRIVE_REMOVABLE
)
892 *MSVCRT__errno() = MSVCRT_EACCES
;
896 dir_len
= GetFullPathNameW(drivespec
,MAX_PATH
,dir
,&dummy
);
897 if (dir_len
>= size
|| dir_len
< 1)
899 *MSVCRT__errno() = MSVCRT_ERANGE
;
900 return NULL
; /* buf too small */
903 TRACE(":returning %s\n", debugstr_w(dir
));
905 return MSVCRT__wcsdup(dir
); /* allocate */
911 /*********************************************************************
912 * _getdiskfree (MSVCRT.@)
914 * Get information about the free space on a drive.
917 * disk [I] Drive number to get information about (1 = 'A', 2 = 'B', ...)
918 * info [O] Destination for the resulting information.
921 * Success: 0. info is updated with the free space information.
922 * Failure: An error code from GetLastError().
925 * See GetLastError().
927 unsigned int CDECL
MSVCRT__getdiskfree(unsigned int disk
, struct MSVCRT__diskfree_t
* d
)
929 WCHAR drivespec
[] = {'@', ':', '\\', 0};
934 return ERROR_INVALID_PARAMETER
; /* MSVCRT doesn't set errno here */
936 drivespec
[0] += disk
; /* make a drive letter */
938 if (GetDiskFreeSpaceW(disk
==0?NULL
:drivespec
,ret
,ret
+1,ret
+2,ret
+3))
940 d
->sectors_per_cluster
= ret
[0];
941 d
->bytes_per_sector
= ret
[1];
942 d
->avail_clusters
= ret
[2];
943 d
->total_clusters
= ret
[3];
946 err
= GetLastError();
947 msvcrt_set_errno(err
);
951 /*********************************************************************
954 * Create a directory.
957 * newdir [I] Name of directory to create.
960 * Success: 0. The directory indicated by newdir is created.
961 * Failure: -1. errno indicates the error.
964 * See CreateDirectoryA.
966 int CDECL
MSVCRT__mkdir(const char * newdir
)
968 if (CreateDirectoryA(newdir
,NULL
))
970 msvcrt_set_errno(GetLastError());
974 /*********************************************************************
977 * Unicode version of _mkdir.
979 int CDECL
MSVCRT__wmkdir(const MSVCRT_wchar_t
* newdir
)
981 if (CreateDirectoryW(newdir
,NULL
))
983 msvcrt_set_errno(GetLastError());
987 /*********************************************************************
990 * Delete a directory.
993 * dir [I] Name of directory to delete.
996 * Success: 0. The directory indicated by newdir is deleted.
997 * Failure: -1. errno indicates the error.
1000 * See RemoveDirectoryA.
1002 int CDECL
MSVCRT__rmdir(const char * dir
)
1004 if (RemoveDirectoryA(dir
))
1006 msvcrt_set_errno(GetLastError());
1010 /*********************************************************************
1011 * _wrmdir (MSVCRT.@)
1013 * Unicode version of _rmdir.
1015 int CDECL
MSVCRT__wrmdir(const MSVCRT_wchar_t
* dir
)
1017 if (RemoveDirectoryW(dir
))
1019 msvcrt_set_errno(GetLastError());
1023 /******************************************************************
1024 * _splitpath_s (MSVCRT.@)
1026 int CDECL
MSVCRT__splitpath_s(const char* inpath
,
1027 char* drive
, MSVCRT_size_t sz_drive
,
1028 char* dir
, MSVCRT_size_t sz_dir
,
1029 char* fname
, MSVCRT_size_t sz_fname
,
1030 char* ext
, MSVCRT_size_t sz_ext
)
1032 const char *p
, *end
;
1034 if (!inpath
|| (!drive
&& sz_drive
) ||
1035 (drive
&& !sz_drive
) ||
1038 (!fname
&& sz_fname
) ||
1039 (fname
&& !sz_fname
) ||
1043 *MSVCRT__errno() = MSVCRT_EINVAL
;
1044 return MSVCRT_EINVAL
;
1047 if (inpath
[0] && inpath
[1] == ':')
1051 if (sz_drive
<= 2) goto do_error
;
1052 drive
[0] = inpath
[0];
1053 drive
[1] = inpath
[1];
1058 else if (drive
) drive
[0] = '\0';
1060 /* look for end of directory part */
1062 for (p
= inpath
; *p
; p
++)
1064 if (_ismbblead((unsigned char)*p
))
1069 if (*p
== '/' || *p
== '\\') end
= p
+ 1;
1072 if (end
) /* got a directory */
1076 if (sz_dir
<= end
- inpath
) goto do_error
;
1077 memcpy( dir
, inpath
, (end
- inpath
) );
1078 dir
[end
- inpath
] = 0;
1082 else if (dir
) dir
[0] = 0;
1084 /* look for extension: what's after the last dot */
1086 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
1088 if (!end
) end
= p
; /* there's no extension */
1092 if (sz_fname
<= end
- inpath
) goto do_error
;
1093 memcpy( fname
, inpath
, (end
- inpath
) );
1094 fname
[end
- inpath
] = 0;
1098 if (sz_ext
<= strlen(end
)) goto do_error
;
1103 if (drive
) drive
[0] = '\0';
1104 if (dir
) dir
[0] = '\0';
1105 if (fname
) fname
[0]= '\0';
1106 if (ext
) ext
[0]= '\0';
1107 *MSVCRT__errno() = MSVCRT_ERANGE
;
1108 return MSVCRT_ERANGE
;
1111 /*********************************************************************
1112 * _splitpath (MSVCRT.@)
1114 void CDECL
MSVCRT__splitpath(const char *inpath
, char *drv
, char *dir
,
1115 char *fname
, char *ext
)
1117 MSVCRT__splitpath_s(inpath
, drv
, drv
?MSVCRT__MAX_DRIVE
:0, dir
, dir
?MSVCRT__MAX_DIR
:0,
1118 fname
, fname
?MSVCRT__MAX_FNAME
:0, ext
, ext
?MSVCRT__MAX_EXT
:0);
1121 /******************************************************************
1122 * _wsplitpath_s (MSVCRT.@)
1124 * Secure version of _wsplitpath
1126 int CDECL
MSVCRT__wsplitpath_s(const MSVCRT_wchar_t
* inpath
,
1127 MSVCRT_wchar_t
* drive
, MSVCRT_size_t sz_drive
,
1128 MSVCRT_wchar_t
* dir
, MSVCRT_size_t sz_dir
,
1129 MSVCRT_wchar_t
* fname
, MSVCRT_size_t sz_fname
,
1130 MSVCRT_wchar_t
* ext
, MSVCRT_size_t sz_ext
)
1132 const MSVCRT_wchar_t
*p
, *end
;
1134 if (!inpath
|| (!drive
&& sz_drive
) ||
1135 (drive
&& !sz_drive
) ||
1138 (!fname
&& sz_fname
) ||
1139 (fname
&& !sz_fname
) ||
1143 *MSVCRT__errno() = MSVCRT_EINVAL
;
1144 return MSVCRT_EINVAL
;
1147 if (inpath
[0] && inpath
[1] == ':')
1151 if (sz_drive
<= 2) goto do_error
;
1152 drive
[0] = inpath
[0];
1153 drive
[1] = inpath
[1];
1158 else if (drive
) drive
[0] = '\0';
1160 /* look for end of directory part */
1162 for (p
= inpath
; *p
; p
++) if (*p
== '/' || *p
== '\\') end
= p
+ 1;
1164 if (end
) /* got a directory */
1168 if (sz_dir
<= end
- inpath
) goto do_error
;
1169 memcpy( dir
, inpath
, (end
- inpath
) * sizeof(MSVCRT_wchar_t
) );
1170 dir
[end
- inpath
] = 0;
1174 else if (dir
) dir
[0] = 0;
1176 /* look for extension: what's after the last dot */
1178 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
1180 if (!end
) end
= p
; /* there's no extension */
1184 if (sz_fname
<= end
- inpath
) goto do_error
;
1185 memcpy( fname
, inpath
, (end
- inpath
) * sizeof(MSVCRT_wchar_t
) );
1186 fname
[end
- inpath
] = 0;
1190 if (sz_ext
<= strlenW(end
)) goto do_error
;
1191 strcpyW( ext
, end
);
1195 if (drive
) drive
[0] = '\0';
1196 if (dir
) dir
[0] = '\0';
1197 if (fname
) fname
[0]= '\0';
1198 if (ext
) ext
[0]= '\0';
1199 *MSVCRT__errno() = MSVCRT_ERANGE
;
1200 return MSVCRT_ERANGE
;
1203 /*********************************************************************
1204 * _wsplitpath (MSVCRT.@)
1206 * Unicode version of _splitpath.
1208 void CDECL
MSVCRT__wsplitpath(const MSVCRT_wchar_t
*inpath
, MSVCRT_wchar_t
*drv
, MSVCRT_wchar_t
*dir
,
1209 MSVCRT_wchar_t
*fname
, MSVCRT_wchar_t
*ext
)
1211 MSVCRT__wsplitpath_s(inpath
, drv
, drv
?MSVCRT__MAX_DRIVE
:0, dir
, dir
?MSVCRT__MAX_DIR
:0,
1212 fname
, fname
?MSVCRT__MAX_FNAME
:0, ext
, ext
?MSVCRT__MAX_EXT
:0);
1215 /*********************************************************************
1216 * _wfullpath (MSVCRT.@)
1218 * Unicode version of _fullpath.
1220 MSVCRT_wchar_t
* CDECL
MSVCRT__wfullpath(MSVCRT_wchar_t
* absPath
, const MSVCRT_wchar_t
* relPath
, MSVCRT_size_t size
)
1225 BOOL alloced
= FALSE
;
1227 if (!relPath
|| !*relPath
)
1228 return MSVCRT__wgetcwd(absPath
, size
);
1230 if (absPath
== NULL
)
1232 buffer
= MSVCRT_malloc(MAX_PATH
* sizeof(WCHAR
));
1241 *MSVCRT__errno() = MSVCRT_ERANGE
;
1245 TRACE(":resolving relative path %s\n",debugstr_w(relPath
));
1247 rc
= GetFullPathNameW(relPath
,size
,buffer
,&lastpart
);
1249 if (rc
> 0 && rc
<= size
)
1254 MSVCRT_free(buffer
);
1259 /*********************************************************************
1260 * _fullpath (MSVCRT.@)
1262 * Create an absolute path from a relative path.
1265 * absPath [O] Destination for absolute path
1266 * relPath [I] Relative path to convert to absolute
1267 * size [I] Length of absPath in characters.
1270 * Success: If absPath is NULL, returns an allocated string containing the path.
1271 * Otherwise populates absPath with the path and returns it.
1272 * Failure: NULL. errno indicates the error.
1274 char * CDECL
MSVCRT__fullpath(char * absPath
, const char* relPath
, unsigned int size
)
1279 BOOL alloced
= FALSE
;
1281 if (!relPath
|| !*relPath
)
1282 return MSVCRT__getcwd(absPath
, size
);
1284 if (absPath
== NULL
)
1286 buffer
= MSVCRT_malloc(MAX_PATH
);
1295 *MSVCRT__errno() = MSVCRT_ERANGE
;
1299 TRACE(":resolving relative path '%s'\n",relPath
);
1301 rc
= GetFullPathNameA(relPath
,size
,buffer
,&lastpart
);
1303 if (rc
> 0 && rc
<= size
)
1308 MSVCRT_free(buffer
);
1313 /*********************************************************************
1314 * _makepath (MSVCRT.@)
1316 * Create a pathname.
1319 * path [O] Destination for created pathname
1320 * drive [I] Drive letter (e.g. "A:")
1321 * directory [I] Directory
1322 * filename [I] Name of the file, excluding extension
1323 * extension [I] File extension (e.g. ".TXT")
1326 * Nothing. If path is not large enough to hold the resulting pathname,
1327 * random process memory will be overwritten.
1329 VOID CDECL
MSVCRT__makepath(char * path
, const char * drive
,
1330 const char *directory
, const char * filename
,
1331 const char * extension
)
1335 TRACE("(%s %s %s %s)\n", debugstr_a(drive
), debugstr_a(directory
),
1336 debugstr_a(filename
), debugstr_a(extension
) );
1341 if (drive
&& drive
[0])
1346 if (directory
&& directory
[0])
1348 unsigned int len
= strlen(directory
);
1349 memmove(p
, directory
, len
);
1351 if (p
[-1] != '/' && p
[-1] != '\\')
1354 if (filename
&& filename
[0])
1356 unsigned int len
= strlen(filename
);
1357 memmove(p
, filename
, len
);
1360 if (extension
&& extension
[0])
1362 if (extension
[0] != '.')
1364 strcpy(p
, extension
);
1368 TRACE("returning %s\n",path
);
1371 /*********************************************************************
1372 * _wmakepath (MSVCRT.@)
1374 * Unicode version of _wmakepath.
1376 VOID CDECL
MSVCRT__wmakepath(MSVCRT_wchar_t
*path
, const MSVCRT_wchar_t
*drive
, const MSVCRT_wchar_t
*directory
,
1377 const MSVCRT_wchar_t
*filename
, const MSVCRT_wchar_t
*extension
)
1379 MSVCRT_wchar_t
*p
= path
;
1381 TRACE("%s %s %s %s\n", debugstr_w(drive
), debugstr_w(directory
),
1382 debugstr_w(filename
), debugstr_w(extension
));
1387 if (drive
&& drive
[0])
1392 if (directory
&& directory
[0])
1394 unsigned int len
= strlenW(directory
);
1395 memmove(p
, directory
, len
* sizeof(MSVCRT_wchar_t
));
1397 if (p
[-1] != '/' && p
[-1] != '\\')
1400 if (filename
&& filename
[0])
1402 unsigned int len
= strlenW(filename
);
1403 memmove(p
, filename
, len
* sizeof(MSVCRT_wchar_t
));
1406 if (extension
&& extension
[0])
1408 if (extension
[0] != '.')
1410 strcpyW(p
, extension
);
1415 TRACE("returning %s\n", debugstr_w(path
));
1418 /*********************************************************************
1419 * _makepath_s (MSVCRT.@)
1421 * Safe version of _makepath.
1423 int CDECL
MSVCRT__makepath_s(char *path
, MSVCRT_size_t size
, const char *drive
,
1424 const char *directory
, const char *filename
,
1425 const char *extension
)
1431 *MSVCRT__errno() = MSVCRT_EINVAL
;
1432 return MSVCRT_EINVAL
;
1435 if (drive
&& drive
[0])
1445 if (directory
&& directory
[0])
1447 unsigned int len
= strlen(directory
);
1448 unsigned int needs_separator
= directory
[len
- 1] != '/' && directory
[len
- 1] != '\\';
1449 unsigned int copylen
= min(size
- 1, len
);
1454 memmove(p
, directory
, copylen
);
1462 if (needs_separator
)
1472 if (filename
&& filename
[0])
1474 unsigned int len
= strlen(filename
);
1475 unsigned int copylen
= min(size
- 1, len
);
1480 memmove(p
, filename
, copylen
);
1489 if (extension
&& extension
[0])
1491 unsigned int len
= strlen(extension
);
1492 unsigned int needs_period
= extension
[0] != '.';
1493 unsigned int copylen
;
1504 copylen
= min(size
- 1, len
);
1505 memcpy(p
, extension
, copylen
);
1518 *MSVCRT__errno() = MSVCRT_ERANGE
;
1519 return MSVCRT_ERANGE
;
1522 /*********************************************************************
1523 * _wmakepath_s (MSVCRT.@)
1525 * Safe version of _wmakepath.
1527 int CDECL
MSVCRT__wmakepath_s(MSVCRT_wchar_t
*path
, MSVCRT_size_t size
, const MSVCRT_wchar_t
*drive
,
1528 const MSVCRT_wchar_t
*directory
, const MSVCRT_wchar_t
*filename
,
1529 const MSVCRT_wchar_t
*extension
)
1531 MSVCRT_wchar_t
*p
= path
;
1535 *MSVCRT__errno() = MSVCRT_EINVAL
;
1536 return MSVCRT_EINVAL
;
1539 if (drive
&& drive
[0])
1549 if (directory
&& directory
[0])
1551 unsigned int len
= strlenW(directory
);
1552 unsigned int needs_separator
= directory
[len
- 1] != '/' && directory
[len
- 1] != '\\';
1553 unsigned int copylen
= min(size
- 1, len
);
1558 memmove(p
, directory
, copylen
* sizeof(MSVCRT_wchar_t
));
1566 if (needs_separator
)
1576 if (filename
&& filename
[0])
1578 unsigned int len
= strlenW(filename
);
1579 unsigned int copylen
= min(size
- 1, len
);
1584 memmove(p
, filename
, copylen
* sizeof(MSVCRT_wchar_t
));
1593 if (extension
&& extension
[0])
1595 unsigned int len
= strlenW(extension
);
1596 unsigned int needs_period
= extension
[0] != '.';
1597 unsigned int copylen
;
1608 copylen
= min(size
- 1, len
);
1609 memcpy(p
, extension
, copylen
* sizeof(MSVCRT_wchar_t
));
1622 *MSVCRT__errno() = MSVCRT_ERANGE
;
1623 return MSVCRT_ERANGE
;
1626 /*********************************************************************
1627 * _searchenv (MSVCRT.@)
1629 * Search for a file in a list of paths from an environment variable.
1632 * file [I] Name of the file to search for.
1633 * env [I] Name of the environment variable containing a list of paths.
1634 * buf [O] Destination for the found file path.
1637 * Nothing. If the file is not found, buf will contain an empty string
1640 void CDECL
MSVCRT__searchenv(const char* file
, const char* env
, char *buf
)
1643 char curPath
[MAX_PATH
];
1648 if (GetFileAttributesA( file
) != INVALID_FILE_ATTRIBUTES
)
1650 GetFullPathNameA( file
, MAX_PATH
, buf
, NULL
);
1651 /* Sigh. This error is *always* set, regardless of success */
1652 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1656 /* Search given environment variable */
1657 envVal
= MSVCRT_getenv(env
);
1660 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1665 TRACE(":searching for %s in paths %s\n", file
, envVal
);
1671 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1672 if (penv
== end
|| !*penv
)
1674 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1677 memcpy(curPath
, penv
, end
- penv
);
1678 if (curPath
[end
- penv
] != '/' && curPath
[end
- penv
] != '\\')
1680 curPath
[end
- penv
] = '\\';
1681 curPath
[end
- penv
+ 1] = '\0';
1684 curPath
[end
- penv
] = '\0';
1686 strcat(curPath
, file
);
1687 TRACE("Checking for file %s\n", curPath
);
1688 if (GetFileAttributesA( curPath
) != INVALID_FILE_ATTRIBUTES
)
1690 strcpy(buf
, curPath
);
1691 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1694 penv
= *end
? end
+ 1 : end
;
1698 /*********************************************************************
1699 * _searchenv_s (MSVCRT.@)
1701 int CDECL
MSVCRT__searchenv_s(const char* file
, const char* env
, char *buf
, MSVCRT_size_t count
)
1704 char curPath
[MAX_PATH
];
1706 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EINVAL
;
1707 if (!MSVCRT_CHECK_PMT(buf
!= NULL
)) return MSVCRT_EINVAL
;
1708 if (!MSVCRT_CHECK_PMT(count
> 0)) return MSVCRT_EINVAL
;
1713 if (GetFileAttributesA( file
) != INVALID_FILE_ATTRIBUTES
)
1715 if (GetFullPathNameA( file
, count
, buf
, NULL
)) return 0;
1716 msvcrt_set_errno(GetLastError());
1720 /* Search given environment variable */
1721 envVal
= MSVCRT_getenv(env
);
1724 *MSVCRT__errno() = MSVCRT_ENOENT
;
1725 return MSVCRT_ENOENT
;
1729 TRACE(":searching for %s in paths %s\n", file
, envVal
);
1735 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1736 if (penv
== end
|| !*penv
)
1738 *MSVCRT__errno() = MSVCRT_ENOENT
;
1739 return MSVCRT_ENOENT
;
1741 memcpy(curPath
, penv
, end
- penv
);
1742 if (curPath
[end
- penv
] != '/' && curPath
[end
- penv
] != '\\')
1744 curPath
[end
- penv
] = '\\';
1745 curPath
[end
- penv
+ 1] = '\0';
1748 curPath
[end
- penv
] = '\0';
1750 strcat(curPath
, file
);
1751 TRACE("Checking for file %s\n", curPath
);
1752 if (GetFileAttributesA( curPath
) != INVALID_FILE_ATTRIBUTES
)
1754 if (strlen(curPath
) + 1 > count
)
1756 MSVCRT_INVALID_PMT("buf[count] is too small", MSVCRT_ERANGE
);
1757 return MSVCRT_ERANGE
;
1759 strcpy(buf
, curPath
);
1762 penv
= *end
? end
+ 1 : end
;
1766 /*********************************************************************
1767 * _wsearchenv (MSVCRT.@)
1769 * Unicode version of _searchenv
1771 void CDECL
MSVCRT__wsearchenv(const MSVCRT_wchar_t
* file
, const MSVCRT_wchar_t
* env
, MSVCRT_wchar_t
*buf
)
1773 MSVCRT_wchar_t
*envVal
, *penv
;
1774 MSVCRT_wchar_t curPath
[MAX_PATH
];
1779 if (GetFileAttributesW( file
) != INVALID_FILE_ATTRIBUTES
)
1781 GetFullPathNameW( file
, MAX_PATH
, buf
, NULL
);
1782 /* Sigh. This error is *always* set, regardless of success */
1783 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1787 /* Search given environment variable */
1788 envVal
= MSVCRT__wgetenv(env
);
1791 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1796 TRACE(":searching for %s in paths %s\n", debugstr_w(file
), debugstr_w(envVal
));
1800 MSVCRT_wchar_t
*end
= penv
;
1802 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1803 if (penv
== end
|| !*penv
)
1805 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1808 memcpy(curPath
, penv
, (end
- penv
) * sizeof(MSVCRT_wchar_t
));
1809 if (curPath
[end
- penv
] != '/' && curPath
[end
- penv
] != '\\')
1811 curPath
[end
- penv
] = '\\';
1812 curPath
[end
- penv
+ 1] = '\0';
1815 curPath
[end
- penv
] = '\0';
1817 strcatW(curPath
, file
);
1818 TRACE("Checking for file %s\n", debugstr_w(curPath
));
1819 if (GetFileAttributesW( curPath
) != INVALID_FILE_ATTRIBUTES
)
1821 strcpyW(buf
, curPath
);
1822 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1825 penv
= *end
? end
+ 1 : end
;
1829 /*********************************************************************
1830 * _wsearchenv_s (MSVCRT.@)
1832 int CDECL
MSVCRT__wsearchenv_s(const MSVCRT_wchar_t
* file
, const MSVCRT_wchar_t
* env
,
1833 MSVCRT_wchar_t
*buf
, MSVCRT_size_t count
)
1835 MSVCRT_wchar_t
* envVal
, *penv
;
1836 MSVCRT_wchar_t curPath
[MAX_PATH
];
1838 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EINVAL
;
1839 if (!MSVCRT_CHECK_PMT(buf
!= NULL
)) return MSVCRT_EINVAL
;
1840 if (!MSVCRT_CHECK_PMT(count
> 0)) return MSVCRT_EINVAL
;
1845 if (GetFileAttributesW( file
) != INVALID_FILE_ATTRIBUTES
)
1847 if (GetFullPathNameW( file
, count
, buf
, NULL
)) return 0;
1848 msvcrt_set_errno(GetLastError());
1852 /* Search given environment variable */
1853 envVal
= MSVCRT__wgetenv(env
);
1856 *MSVCRT__errno() = MSVCRT_ENOENT
;
1857 return MSVCRT_ENOENT
;
1861 TRACE(":searching for %s in paths %s\n", debugstr_w(file
), debugstr_w(envVal
));
1865 MSVCRT_wchar_t
*end
= penv
;
1867 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1868 if (penv
== end
|| !*penv
)
1870 *MSVCRT__errno() = MSVCRT_ENOENT
;
1871 return MSVCRT_ENOENT
;
1873 memcpy(curPath
, penv
, (end
- penv
) * sizeof(MSVCRT_wchar_t
));
1874 if (curPath
[end
- penv
] != '/' && curPath
[end
- penv
] != '\\')
1876 curPath
[end
- penv
] = '\\';
1877 curPath
[end
- penv
+ 1] = '\0';
1880 curPath
[end
- penv
] = '\0';
1882 strcatW(curPath
, file
);
1883 TRACE("Checking for file %s\n", debugstr_w(curPath
));
1884 if (GetFileAttributesW( curPath
) != INVALID_FILE_ATTRIBUTES
)
1886 if (strlenW(curPath
) + 1 > count
)
1888 MSVCRT_INVALID_PMT("buf[count] is too small", MSVCRT_ERANGE
);
1889 return MSVCRT_ERANGE
;
1891 strcpyW(buf
, curPath
);
1894 penv
= *end
? end
+ 1 : end
;