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
_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
++) if (*p
== '/' || *p
== '\\') end
= p
+ 1;
1064 if (end
) /* got a directory */
1068 if (sz_dir
<= end
- inpath
) goto do_error
;
1069 memcpy( dir
, inpath
, (end
- inpath
) );
1070 dir
[end
- inpath
] = 0;
1074 else if (dir
) dir
[0] = 0;
1076 /* look for extension: what's after the last dot */
1078 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
1080 if (!end
) end
= p
; /* there's no extension */
1084 if (sz_fname
<= end
- inpath
) goto do_error
;
1085 memcpy( fname
, inpath
, (end
- inpath
) );
1086 fname
[end
- inpath
] = 0;
1090 if (sz_ext
<= strlen(end
)) goto do_error
;
1095 if (drive
) drive
[0] = '\0';
1096 if (dir
) dir
[0] = '\0';
1097 if (fname
) fname
[0]= '\0';
1098 if (ext
) ext
[0]= '\0';
1099 *MSVCRT__errno() = MSVCRT_ERANGE
;
1100 return MSVCRT_ERANGE
;
1103 /*********************************************************************
1104 * _splitpath (MSVCRT.@)
1106 void CDECL
_splitpath(const char *inpath
, char *drv
, char *dir
,
1107 char *fname
, char *ext
)
1109 _splitpath_s(inpath
, drv
, drv
?MSVCRT__MAX_DRIVE
:0, dir
, dir
?MSVCRT__MAX_DIR
:0,
1110 fname
, fname
?MSVCRT__MAX_FNAME
:0, ext
, ext
?MSVCRT__MAX_EXT
:0);
1113 /******************************************************************
1114 * _wsplitpath_s (MSVCRT.@)
1116 * Secure version of _wsplitpath
1118 int CDECL
_wsplitpath_s(const MSVCRT_wchar_t
* inpath
,
1119 MSVCRT_wchar_t
* drive
, MSVCRT_size_t sz_drive
,
1120 MSVCRT_wchar_t
* dir
, MSVCRT_size_t sz_dir
,
1121 MSVCRT_wchar_t
* fname
, MSVCRT_size_t sz_fname
,
1122 MSVCRT_wchar_t
* ext
, MSVCRT_size_t sz_ext
)
1124 const MSVCRT_wchar_t
*p
, *end
;
1126 if (!inpath
|| (!drive
&& sz_drive
) ||
1127 (drive
&& !sz_drive
) ||
1130 (!fname
&& sz_fname
) ||
1131 (fname
&& !sz_fname
) ||
1135 *MSVCRT__errno() = MSVCRT_EINVAL
;
1136 return MSVCRT_EINVAL
;
1139 if (inpath
[0] && inpath
[1] == ':')
1143 if (sz_drive
<= 2) goto do_error
;
1144 drive
[0] = inpath
[0];
1145 drive
[1] = inpath
[1];
1150 else if (drive
) drive
[0] = '\0';
1152 /* look for end of directory part */
1154 for (p
= inpath
; *p
; p
++) if (*p
== '/' || *p
== '\\') end
= p
+ 1;
1156 if (end
) /* got a directory */
1160 if (sz_dir
<= end
- inpath
) goto do_error
;
1161 memcpy( dir
, inpath
, (end
- inpath
) * sizeof(MSVCRT_wchar_t
) );
1162 dir
[end
- inpath
] = 0;
1166 else if (dir
) dir
[0] = 0;
1168 /* look for extension: what's after the last dot */
1170 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
1172 if (!end
) end
= p
; /* there's no extension */
1176 if (sz_fname
<= end
- inpath
) goto do_error
;
1177 memcpy( fname
, inpath
, (end
- inpath
) * sizeof(MSVCRT_wchar_t
) );
1178 fname
[end
- inpath
] = 0;
1182 if (sz_ext
<= strlenW(end
)) goto do_error
;
1183 strcpyW( ext
, end
);
1187 if (drive
) drive
[0] = '\0';
1188 if (dir
) dir
[0] = '\0';
1189 if (fname
) fname
[0]= '\0';
1190 if (ext
) ext
[0]= '\0';
1191 *MSVCRT__errno() = MSVCRT_ERANGE
;
1192 return MSVCRT_ERANGE
;
1195 /*********************************************************************
1196 * _wsplitpath (MSVCRT.@)
1198 * Unicode version of _splitpath.
1200 void CDECL
_wsplitpath(const MSVCRT_wchar_t
*inpath
, MSVCRT_wchar_t
*drv
, MSVCRT_wchar_t
*dir
,
1201 MSVCRT_wchar_t
*fname
, MSVCRT_wchar_t
*ext
)
1203 _wsplitpath_s(inpath
, drv
, drv
?MSVCRT__MAX_DRIVE
:0, dir
, dir
?MSVCRT__MAX_DIR
:0,
1204 fname
, fname
?MSVCRT__MAX_FNAME
:0, ext
, ext
?MSVCRT__MAX_EXT
:0);
1207 /*********************************************************************
1208 * _wfullpath (MSVCRT.@)
1210 * Unicode version of _fullpath.
1212 MSVCRT_wchar_t
* CDECL
_wfullpath(MSVCRT_wchar_t
* absPath
, const MSVCRT_wchar_t
* relPath
, MSVCRT_size_t size
)
1217 BOOL alloced
= FALSE
;
1219 if (!relPath
|| !*relPath
)
1220 return MSVCRT__wgetcwd(absPath
, size
);
1222 if (absPath
== NULL
)
1224 buffer
= MSVCRT_malloc(MAX_PATH
* sizeof(WCHAR
));
1233 *MSVCRT__errno() = MSVCRT_ERANGE
;
1237 TRACE(":resolving relative path %s\n",debugstr_w(relPath
));
1239 rc
= GetFullPathNameW(relPath
,size
,buffer
,&lastpart
);
1241 if (rc
> 0 && rc
<= size
)
1246 MSVCRT_free(buffer
);
1251 /*********************************************************************
1252 * _fullpath (MSVCRT.@)
1254 * Create an absolute path from a relative path.
1257 * absPath [O] Destination for absolute path
1258 * relPath [I] Relative path to convert to absolute
1259 * size [I] Length of absPath in characters.
1262 * Success: If absPath is NULL, returns an allocated string containing the path.
1263 * Otherwise populates absPath with the path and returns it.
1264 * Failure: NULL. errno indicates the error.
1266 char * CDECL
_fullpath(char * absPath
, const char* relPath
, unsigned int size
)
1271 BOOL alloced
= FALSE
;
1273 if (!relPath
|| !*relPath
)
1274 return MSVCRT__getcwd(absPath
, size
);
1276 if (absPath
== NULL
)
1278 buffer
= MSVCRT_malloc(MAX_PATH
);
1287 *MSVCRT__errno() = MSVCRT_ERANGE
;
1291 TRACE(":resolving relative path '%s'\n",relPath
);
1293 rc
= GetFullPathNameA(relPath
,size
,buffer
,&lastpart
);
1295 if (rc
> 0 && rc
<= size
)
1300 MSVCRT_free(buffer
);
1305 /*********************************************************************
1306 * _makepath (MSVCRT.@)
1308 * Create a pathname.
1311 * path [O] Destination for created pathname
1312 * drive [I] Drive letter (e.g. "A:")
1313 * directory [I] Directory
1314 * filename [I] Name of the file, excluding extension
1315 * extension [I] File extension (e.g. ".TXT")
1318 * Nothing. If path is not large enough to hold the resulting pathname,
1319 * random process memory will be overwritten.
1321 VOID CDECL
_makepath(char * path
, const char * drive
,
1322 const char *directory
, const char * filename
,
1323 const char * extension
)
1327 TRACE("(%s %s %s %s)\n", debugstr_a(drive
), debugstr_a(directory
),
1328 debugstr_a(filename
), debugstr_a(extension
) );
1333 if (drive
&& drive
[0])
1338 if (directory
&& directory
[0])
1340 unsigned int len
= strlen(directory
);
1341 memmove(p
, directory
, len
);
1343 if (p
[-1] != '/' && p
[-1] != '\\')
1346 if (filename
&& filename
[0])
1348 unsigned int len
= strlen(filename
);
1349 memmove(p
, filename
, len
);
1352 if (extension
&& extension
[0])
1354 if (extension
[0] != '.')
1356 strcpy(p
, extension
);
1360 TRACE("returning %s\n",path
);
1363 /*********************************************************************
1364 * _wmakepath (MSVCRT.@)
1366 * Unicode version of _wmakepath.
1368 VOID CDECL
_wmakepath(MSVCRT_wchar_t
*path
, const MSVCRT_wchar_t
*drive
, const MSVCRT_wchar_t
*directory
,
1369 const MSVCRT_wchar_t
*filename
, const MSVCRT_wchar_t
*extension
)
1371 MSVCRT_wchar_t
*p
= path
;
1373 TRACE("%s %s %s %s\n", debugstr_w(drive
), debugstr_w(directory
),
1374 debugstr_w(filename
), debugstr_w(extension
));
1379 if (drive
&& drive
[0])
1384 if (directory
&& directory
[0])
1386 unsigned int len
= strlenW(directory
);
1387 memmove(p
, directory
, len
* sizeof(MSVCRT_wchar_t
));
1389 if (p
[-1] != '/' && p
[-1] != '\\')
1392 if (filename
&& filename
[0])
1394 unsigned int len
= strlenW(filename
);
1395 memmove(p
, filename
, len
* sizeof(MSVCRT_wchar_t
));
1398 if (extension
&& extension
[0])
1400 if (extension
[0] != '.')
1402 strcpyW(p
, extension
);
1407 TRACE("returning %s\n", debugstr_w(path
));
1410 /*********************************************************************
1411 * _makepath_s (MSVCRT.@)
1413 * Safe version of _makepath.
1415 int CDECL
_makepath_s(char *path
, MSVCRT_size_t size
, const char *drive
,
1416 const char *directory
, const char *filename
,
1417 const char *extension
)
1423 *MSVCRT__errno() = MSVCRT_EINVAL
;
1424 return MSVCRT_EINVAL
;
1427 if (drive
&& drive
[0])
1437 if (directory
&& directory
[0])
1439 unsigned int len
= strlen(directory
);
1440 unsigned int needs_separator
= directory
[len
- 1] != '/' && directory
[len
- 1] != '\\';
1441 unsigned int copylen
= min(size
- 1, len
);
1446 memmove(p
, directory
, copylen
);
1454 if (needs_separator
)
1464 if (filename
&& filename
[0])
1466 unsigned int len
= strlen(filename
);
1467 unsigned int copylen
= min(size
- 1, len
);
1472 memmove(p
, filename
, copylen
);
1481 if (extension
&& extension
[0])
1483 unsigned int len
= strlen(extension
);
1484 unsigned int needs_period
= extension
[0] != '.';
1485 unsigned int copylen
;
1496 copylen
= min(size
- 1, len
);
1497 memcpy(p
, extension
, copylen
);
1510 *MSVCRT__errno() = MSVCRT_ERANGE
;
1511 return MSVCRT_ERANGE
;
1514 /*********************************************************************
1515 * _wmakepath_s (MSVCRT.@)
1517 * Safe version of _wmakepath.
1519 int CDECL
_wmakepath_s(MSVCRT_wchar_t
*path
, MSVCRT_size_t size
, const MSVCRT_wchar_t
*drive
,
1520 const MSVCRT_wchar_t
*directory
, const MSVCRT_wchar_t
*filename
,
1521 const MSVCRT_wchar_t
*extension
)
1523 MSVCRT_wchar_t
*p
= path
;
1527 *MSVCRT__errno() = MSVCRT_EINVAL
;
1528 return MSVCRT_EINVAL
;
1531 if (drive
&& drive
[0])
1541 if (directory
&& directory
[0])
1543 unsigned int len
= strlenW(directory
);
1544 unsigned int needs_separator
= directory
[len
- 1] != '/' && directory
[len
- 1] != '\\';
1545 unsigned int copylen
= min(size
- 1, len
);
1550 memmove(p
, directory
, copylen
* sizeof(MSVCRT_wchar_t
));
1558 if (needs_separator
)
1568 if (filename
&& filename
[0])
1570 unsigned int len
= strlenW(filename
);
1571 unsigned int copylen
= min(size
- 1, len
);
1576 memmove(p
, filename
, copylen
* sizeof(MSVCRT_wchar_t
));
1585 if (extension
&& extension
[0])
1587 unsigned int len
= strlenW(extension
);
1588 unsigned int needs_period
= extension
[0] != '.';
1589 unsigned int copylen
;
1600 copylen
= min(size
- 1, len
);
1601 memcpy(p
, extension
, copylen
* sizeof(MSVCRT_wchar_t
));
1614 *MSVCRT__errno() = MSVCRT_ERANGE
;
1615 return MSVCRT_ERANGE
;
1618 /*********************************************************************
1619 * _searchenv (MSVCRT.@)
1621 * Search for a file in a list of paths from an environment variable.
1624 * file [I] Name of the file to search for.
1625 * env [I] Name of the environment variable containing a list of paths.
1626 * buf [O] Destination for the found file path.
1629 * Nothing. If the file is not found, buf will contain an empty string
1632 void CDECL
MSVCRT__searchenv(const char* file
, const char* env
, char *buf
)
1635 char curPath
[MAX_PATH
];
1640 if (GetFileAttributesA( file
) != INVALID_FILE_ATTRIBUTES
)
1642 GetFullPathNameA( file
, MAX_PATH
, buf
, NULL
);
1643 /* Sigh. This error is *always* set, regardless of success */
1644 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1648 /* Search given environment variable */
1649 envVal
= MSVCRT_getenv(env
);
1652 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1657 TRACE(":searching for %s in paths %s\n", file
, envVal
);
1663 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1664 if (penv
== end
|| !*penv
)
1666 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1669 memcpy(curPath
, penv
, end
- penv
);
1670 if (curPath
[end
- penv
] != '/' && curPath
[end
- penv
] != '\\')
1672 curPath
[end
- penv
] = '\\';
1673 curPath
[end
- penv
+ 1] = '\0';
1676 curPath
[end
- penv
] = '\0';
1678 strcat(curPath
, file
);
1679 TRACE("Checking for file %s\n", curPath
);
1680 if (GetFileAttributesA( curPath
) != INVALID_FILE_ATTRIBUTES
)
1682 strcpy(buf
, curPath
);
1683 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1686 penv
= *end
? end
+ 1 : end
;
1690 /*********************************************************************
1691 * _searchenv_s (MSVCRT.@)
1693 int CDECL
_searchenv_s(const char* file
, const char* env
, char *buf
, MSVCRT_size_t count
)
1696 char curPath
[MAX_PATH
];
1698 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EINVAL
;
1699 if (!MSVCRT_CHECK_PMT(buf
!= NULL
)) return MSVCRT_EINVAL
;
1700 if (!MSVCRT_CHECK_PMT(count
> 0)) return MSVCRT_EINVAL
;
1705 if (GetFileAttributesA( file
) != INVALID_FILE_ATTRIBUTES
)
1707 if (GetFullPathNameA( file
, count
, buf
, NULL
)) return 0;
1708 msvcrt_set_errno(GetLastError());
1712 /* Search given environment variable */
1713 envVal
= MSVCRT_getenv(env
);
1716 *MSVCRT__errno() = MSVCRT_ENOENT
;
1717 return MSVCRT_ENOENT
;
1721 TRACE(":searching for %s in paths %s\n", file
, envVal
);
1727 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1728 if (penv
== end
|| !*penv
)
1730 *MSVCRT__errno() = MSVCRT_ENOENT
;
1731 return MSVCRT_ENOENT
;
1733 memcpy(curPath
, penv
, end
- penv
);
1734 if (curPath
[end
- penv
] != '/' && curPath
[end
- penv
] != '\\')
1736 curPath
[end
- penv
] = '\\';
1737 curPath
[end
- penv
+ 1] = '\0';
1740 curPath
[end
- penv
] = '\0';
1742 strcat(curPath
, file
);
1743 TRACE("Checking for file %s\n", curPath
);
1744 if (GetFileAttributesA( curPath
) != INVALID_FILE_ATTRIBUTES
)
1746 if (strlen(curPath
) + 1 > count
)
1748 MSVCRT_INVALID_PMT("buf[count] is too small", MSVCRT_ERANGE
);
1749 return MSVCRT_ERANGE
;
1751 strcpy(buf
, curPath
);
1754 penv
= *end
? end
+ 1 : end
;
1758 /*********************************************************************
1759 * _wsearchenv (MSVCRT.@)
1761 * Unicode version of _searchenv
1763 void CDECL
MSVCRT__wsearchenv(const MSVCRT_wchar_t
* file
, const MSVCRT_wchar_t
* env
, MSVCRT_wchar_t
*buf
)
1765 MSVCRT_wchar_t
*envVal
, *penv
;
1766 MSVCRT_wchar_t curPath
[MAX_PATH
];
1771 if (GetFileAttributesW( file
) != INVALID_FILE_ATTRIBUTES
)
1773 GetFullPathNameW( file
, MAX_PATH
, buf
, NULL
);
1774 /* Sigh. This error is *always* set, regardless of success */
1775 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1779 /* Search given environment variable */
1780 envVal
= MSVCRT__wgetenv(env
);
1783 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1788 TRACE(":searching for %s in paths %s\n", debugstr_w(file
), debugstr_w(envVal
));
1792 MSVCRT_wchar_t
*end
= penv
;
1794 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1795 if (penv
== end
|| !*penv
)
1797 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1800 memcpy(curPath
, penv
, (end
- penv
) * sizeof(MSVCRT_wchar_t
));
1801 if (curPath
[end
- penv
] != '/' && curPath
[end
- penv
] != '\\')
1803 curPath
[end
- penv
] = '\\';
1804 curPath
[end
- penv
+ 1] = '\0';
1807 curPath
[end
- penv
] = '\0';
1809 strcatW(curPath
, file
);
1810 TRACE("Checking for file %s\n", debugstr_w(curPath
));
1811 if (GetFileAttributesW( curPath
) != INVALID_FILE_ATTRIBUTES
)
1813 strcpyW(buf
, curPath
);
1814 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1817 penv
= *end
? end
+ 1 : end
;
1821 /*********************************************************************
1822 * _wsearchenv_s (MSVCRT.@)
1824 int CDECL
_wsearchenv_s(const MSVCRT_wchar_t
* file
, const MSVCRT_wchar_t
* env
,
1825 MSVCRT_wchar_t
*buf
, MSVCRT_size_t count
)
1827 MSVCRT_wchar_t
* envVal
, *penv
;
1828 MSVCRT_wchar_t curPath
[MAX_PATH
];
1830 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EINVAL
;
1831 if (!MSVCRT_CHECK_PMT(buf
!= NULL
)) return MSVCRT_EINVAL
;
1832 if (!MSVCRT_CHECK_PMT(count
> 0)) return MSVCRT_EINVAL
;
1837 if (GetFileAttributesW( file
) != INVALID_FILE_ATTRIBUTES
)
1839 if (GetFullPathNameW( file
, count
, buf
, NULL
)) return 0;
1840 msvcrt_set_errno(GetLastError());
1844 /* Search given environment variable */
1845 envVal
= MSVCRT__wgetenv(env
);
1848 *MSVCRT__errno() = MSVCRT_ENOENT
;
1849 return MSVCRT_ENOENT
;
1853 TRACE(":searching for %s in paths %s\n", debugstr_w(file
), debugstr_w(envVal
));
1857 MSVCRT_wchar_t
*end
= penv
;
1859 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1860 if (penv
== end
|| !*penv
)
1862 *MSVCRT__errno() = MSVCRT_ENOENT
;
1863 return MSVCRT_ENOENT
;
1865 memcpy(curPath
, penv
, (end
- penv
) * sizeof(MSVCRT_wchar_t
));
1866 if (curPath
[end
- penv
] != '/' && curPath
[end
- penv
] != '\\')
1868 curPath
[end
- penv
] = '\\';
1869 curPath
[end
- penv
+ 1] = '\0';
1872 curPath
[end
- penv
] = '\0';
1874 strcatW(curPath
, file
);
1875 TRACE("Checking for file %s\n", debugstr_w(curPath
));
1876 if (GetFileAttributesW( curPath
) != INVALID_FILE_ATTRIBUTES
)
1878 if (strlenW(curPath
) + 1 > count
)
1880 MSVCRT_INVALID_PMT("buf[count] is too small", MSVCRT_ERANGE
);
1881 return MSVCRT_ERANGE
;
1883 strcpyW(buf
, curPath
);
1886 penv
= *end
? end
+ 1 : end
;