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 * _wfindnext32 (MSVCRT.@)
604 int CDECL
MSVCRT__wfindnext32(MSVCRT_intptr_t hand
, struct MSVCRT__wfinddata32_t
* ft
)
606 WIN32_FIND_DATAW find_data
;
608 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
610 *MSVCRT__errno() = MSVCRT_ENOENT
;
614 msvcrt_wfttofd32(&find_data
, ft
);
618 /*********************************************************************
619 * _wfindnext (MSVCRT.@)
621 * Unicode version of _findnext.
623 int CDECL
MSVCRT__wfindnext(MSVCRT_intptr_t hand
, struct MSVCRT__wfinddata_t
* ft
)
625 WIN32_FIND_DATAW find_data
;
627 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
629 *MSVCRT__errno() = MSVCRT_ENOENT
;
633 msvcrt_wfttofd(&find_data
,ft
);
637 /*********************************************************************
638 * _findnexti64 (MSVCRT.@)
640 * 64-bit version of _findnext.
642 int CDECL
MSVCRT__findnexti64(MSVCRT_intptr_t hand
, struct MSVCRT__finddatai64_t
* ft
)
644 WIN32_FIND_DATAA find_data
;
646 if (!FindNextFileA((HANDLE
)hand
, &find_data
))
648 *MSVCRT__errno() = MSVCRT_ENOENT
;
652 msvcrt_fttofdi64(&find_data
,ft
);
656 /*********************************************************************
657 * _findnext64 (MSVCRT.@)
659 * 64-bit version of _findnext.
661 int CDECL
MSVCRT__findnext64(MSVCRT_intptr_t hand
, struct MSVCRT__finddata64_t
* ft
)
663 WIN32_FIND_DATAA find_data
;
665 if (!FindNextFileA((HANDLE
)hand
, &find_data
))
667 *MSVCRT__errno() = MSVCRT_ENOENT
;
671 msvcrt_fttofd64(&find_data
,ft
);
675 /*********************************************************************
676 * _wfindnext64 (MSVCRT.@)
678 * Unicode version of _wfindnext64.
680 int CDECL
MSVCRT__wfindnext64(MSVCRT_intptr_t hand
, struct MSVCRT__wfinddata64_t
* ft
)
682 WIN32_FIND_DATAW find_data
;
684 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
686 *MSVCRT__errno() = MSVCRT_ENOENT
;
690 msvcrt_wfttofd64(&find_data
,ft
);
694 /*********************************************************************
695 * _findnext64i32 (MSVCRT.@)
697 * 64-bit/32-bit version of _findnext.
699 int CDECL
MSVCRT__findnext64i32(MSVCRT_intptr_t hand
, struct MSVCRT__finddata64i32_t
* ft
)
701 WIN32_FIND_DATAA find_data
;
703 if (!FindNextFileA((HANDLE
)hand
, &find_data
))
705 *MSVCRT__errno() = MSVCRT_ENOENT
;
709 msvcrt_fttofd64i32(&find_data
,ft
);
713 /*********************************************************************
714 * _wfindnexti64 (MSVCRT.@)
716 * Unicode version of _findnexti64.
718 int CDECL
MSVCRT__wfindnexti64(MSVCRT_intptr_t hand
, struct MSVCRT__wfinddatai64_t
* ft
)
720 WIN32_FIND_DATAW find_data
;
722 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
724 *MSVCRT__errno() = MSVCRT_ENOENT
;
728 msvcrt_wfttofdi64(&find_data
,ft
);
732 /*********************************************************************
733 * _wfindnext64i32 (MSVCRT.@)
735 * Unicode version of _findnext64i32.
737 int CDECL
MSVCRT__wfindnext64i32(MSVCRT_intptr_t hand
, struct MSVCRT__wfinddata64i32_t
* ft
)
739 WIN32_FIND_DATAW find_data
;
741 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
743 *MSVCRT__errno() = MSVCRT_ENOENT
;
747 msvcrt_wfttofd64i32(&find_data
,ft
);
751 /*********************************************************************
754 * Get the current working directory.
757 * buf [O] Destination for current working directory.
758 * size [I] Size of buf in characters
761 * Success: If buf is NULL, returns an allocated string containing the path.
762 * Otherwise populates buf with the path and returns it.
763 * Failure: NULL. errno indicates the error.
765 char* CDECL
MSVCRT__getcwd(char * buf
, int size
)
768 int dir_len
= GetCurrentDirectoryA(MAX_PATH
,dir
);
771 return NULL
; /* FIXME: Real return value untested */
775 if (size
<= dir_len
) size
= dir_len
+ 1;
776 if (!(buf
= MSVCRT_malloc( size
))) return NULL
;
778 else if (dir_len
>= size
)
780 *MSVCRT__errno() = MSVCRT_ERANGE
;
781 return NULL
; /* buf too small */
787 /*********************************************************************
788 * _wgetcwd (MSVCRT.@)
790 * Unicode version of _getcwd.
792 MSVCRT_wchar_t
* CDECL
MSVCRT__wgetcwd(MSVCRT_wchar_t
* buf
, int size
)
794 MSVCRT_wchar_t dir
[MAX_PATH
];
795 int dir_len
= GetCurrentDirectoryW(MAX_PATH
,dir
);
798 return NULL
; /* FIXME: Real return value untested */
802 if (size
<= dir_len
) size
= dir_len
+ 1;
803 if (!(buf
= MSVCRT_malloc( size
* sizeof(WCHAR
) ))) return NULL
;
807 *MSVCRT__errno() = MSVCRT_ERANGE
;
808 return NULL
; /* buf too small */
814 /*********************************************************************
815 * _getdrive (MSVCRT.@)
817 * Get the current drive number.
823 * Success: The drive letter number from 1 to 26 ("A:" to "Z:").
826 int CDECL
MSVCRT__getdrive(void)
828 WCHAR buffer
[MAX_PATH
];
829 if (GetCurrentDirectoryW( MAX_PATH
, buffer
) &&
830 buffer
[0] >= 'A' && buffer
[0] <= 'z' && buffer
[1] == ':')
831 return toupperW(buffer
[0]) - 'A' + 1;
835 /*********************************************************************
836 * _getdcwd (MSVCRT.@)
838 * Get the current working directory on a given disk.
841 * drive [I] Drive letter to get the current working directory from.
842 * buf [O] Destination for the current working directory.
843 * size [I] Length of drive in characters.
846 * Success: If drive is NULL, returns an allocated string containing the path.
847 * Otherwise populates drive with the path and returns it.
848 * Failure: NULL. errno indicates the error.
850 char* CDECL
MSVCRT__getdcwd(int drive
, char * buf
, int size
)
854 TRACE(":drive %d(%c), size %d\n",drive
, drive
+ 'A' - 1, size
);
856 if (!drive
|| drive
== MSVCRT__getdrive())
857 return MSVCRT__getcwd(buf
,size
); /* current */
861 char drivespec
[] = {'A', ':', 0};
864 drivespec
[0] += drive
- 1;
865 if (GetDriveTypeA(drivespec
) < DRIVE_REMOVABLE
)
867 *MSVCRT__errno() = MSVCRT_EACCES
;
871 dir_len
= GetFullPathNameA(drivespec
,MAX_PATH
,dir
,&dummy
);
872 if (dir_len
>= size
|| dir_len
< 1)
874 *MSVCRT__errno() = MSVCRT_ERANGE
;
875 return NULL
; /* buf too small */
878 TRACE(":returning '%s'\n", dir
);
880 return MSVCRT__strdup(dir
); /* allocate */
887 /*********************************************************************
888 * _wgetdcwd (MSVCRT.@)
890 * Unicode version of _wgetdcwd.
892 MSVCRT_wchar_t
* CDECL
MSVCRT__wgetdcwd(int drive
, MSVCRT_wchar_t
* buf
, int size
)
894 static MSVCRT_wchar_t
* dummy
;
896 TRACE(":drive %d(%c), size %d\n",drive
, drive
+ 'A' - 1, size
);
898 if (!drive
|| drive
== MSVCRT__getdrive())
899 return MSVCRT__wgetcwd(buf
,size
); /* current */
902 MSVCRT_wchar_t dir
[MAX_PATH
];
903 MSVCRT_wchar_t drivespec
[4] = {'A', ':', '\\', 0};
906 drivespec
[0] += drive
- 1;
907 if (GetDriveTypeW(drivespec
) < DRIVE_REMOVABLE
)
909 *MSVCRT__errno() = MSVCRT_EACCES
;
913 dir_len
= GetFullPathNameW(drivespec
,MAX_PATH
,dir
,&dummy
);
914 if (dir_len
>= size
|| dir_len
< 1)
916 *MSVCRT__errno() = MSVCRT_ERANGE
;
917 return NULL
; /* buf too small */
920 TRACE(":returning %s\n", debugstr_w(dir
));
922 return MSVCRT__wcsdup(dir
); /* allocate */
928 /*********************************************************************
929 * _getdiskfree (MSVCRT.@)
931 * Get information about the free space on a drive.
934 * disk [I] Drive number to get information about (1 = 'A', 2 = 'B', ...)
935 * info [O] Destination for the resulting information.
938 * Success: 0. info is updated with the free space information.
939 * Failure: An error code from GetLastError().
942 * See GetLastError().
944 unsigned int CDECL
MSVCRT__getdiskfree(unsigned int disk
, struct MSVCRT__diskfree_t
* d
)
946 WCHAR drivespec
[] = {'@', ':', '\\', 0};
951 return ERROR_INVALID_PARAMETER
; /* MSVCRT doesn't set errno here */
953 drivespec
[0] += disk
; /* make a drive letter */
955 if (GetDiskFreeSpaceW(disk
==0?NULL
:drivespec
,ret
,ret
+1,ret
+2,ret
+3))
957 d
->sectors_per_cluster
= ret
[0];
958 d
->bytes_per_sector
= ret
[1];
959 d
->avail_clusters
= ret
[2];
960 d
->total_clusters
= ret
[3];
963 err
= GetLastError();
964 msvcrt_set_errno(err
);
968 /*********************************************************************
971 * Create a directory.
974 * newdir [I] Name of directory to create.
977 * Success: 0. The directory indicated by newdir is created.
978 * Failure: -1. errno indicates the error.
981 * See CreateDirectoryA.
983 int CDECL
MSVCRT__mkdir(const char * newdir
)
985 if (CreateDirectoryA(newdir
,NULL
))
987 msvcrt_set_errno(GetLastError());
991 /*********************************************************************
994 * Unicode version of _mkdir.
996 int CDECL
MSVCRT__wmkdir(const MSVCRT_wchar_t
* newdir
)
998 if (CreateDirectoryW(newdir
,NULL
))
1000 msvcrt_set_errno(GetLastError());
1004 /*********************************************************************
1007 * Delete a directory.
1010 * dir [I] Name of directory to delete.
1013 * Success: 0. The directory indicated by newdir is deleted.
1014 * Failure: -1. errno indicates the error.
1017 * See RemoveDirectoryA.
1019 int CDECL
MSVCRT__rmdir(const char * dir
)
1021 if (RemoveDirectoryA(dir
))
1023 msvcrt_set_errno(GetLastError());
1027 /*********************************************************************
1028 * _wrmdir (MSVCRT.@)
1030 * Unicode version of _rmdir.
1032 int CDECL
MSVCRT__wrmdir(const MSVCRT_wchar_t
* dir
)
1034 if (RemoveDirectoryW(dir
))
1036 msvcrt_set_errno(GetLastError());
1040 /******************************************************************
1041 * _splitpath_s (MSVCRT.@)
1043 int CDECL
MSVCRT__splitpath_s(const char* inpath
,
1044 char* drive
, MSVCRT_size_t sz_drive
,
1045 char* dir
, MSVCRT_size_t sz_dir
,
1046 char* fname
, MSVCRT_size_t sz_fname
,
1047 char* ext
, MSVCRT_size_t sz_ext
)
1049 const char *p
, *end
;
1051 if (!inpath
|| (!drive
&& sz_drive
) ||
1052 (drive
&& !sz_drive
) ||
1055 (!fname
&& sz_fname
) ||
1056 (fname
&& !sz_fname
) ||
1060 *MSVCRT__errno() = MSVCRT_EINVAL
;
1061 return MSVCRT_EINVAL
;
1064 if (inpath
[0] && inpath
[1] == ':')
1068 if (sz_drive
<= 2) goto do_error
;
1069 drive
[0] = inpath
[0];
1070 drive
[1] = inpath
[1];
1075 else if (drive
) drive
[0] = '\0';
1077 /* look for end of directory part */
1079 for (p
= inpath
; *p
; p
++)
1081 if (_ismbblead((unsigned char)*p
))
1086 if (*p
== '/' || *p
== '\\') end
= p
+ 1;
1089 if (end
) /* got a directory */
1093 if (sz_dir
<= end
- inpath
) goto do_error
;
1094 memcpy( dir
, inpath
, (end
- inpath
) );
1095 dir
[end
- inpath
] = 0;
1099 else if (dir
) dir
[0] = 0;
1101 /* look for extension: what's after the last dot */
1103 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
1105 if (!end
) end
= p
; /* there's no extension */
1109 if (sz_fname
<= end
- inpath
) goto do_error
;
1110 memcpy( fname
, inpath
, (end
- inpath
) );
1111 fname
[end
- inpath
] = 0;
1115 if (sz_ext
<= strlen(end
)) goto do_error
;
1120 if (drive
) drive
[0] = '\0';
1121 if (dir
) dir
[0] = '\0';
1122 if (fname
) fname
[0]= '\0';
1123 if (ext
) ext
[0]= '\0';
1124 *MSVCRT__errno() = MSVCRT_ERANGE
;
1125 return MSVCRT_ERANGE
;
1128 /*********************************************************************
1129 * _splitpath (MSVCRT.@)
1131 void CDECL
MSVCRT__splitpath(const char *inpath
, char *drv
, char *dir
,
1132 char *fname
, char *ext
)
1134 MSVCRT__splitpath_s(inpath
, drv
, drv
?MSVCRT__MAX_DRIVE
:0, dir
, dir
?MSVCRT__MAX_DIR
:0,
1135 fname
, fname
?MSVCRT__MAX_FNAME
:0, ext
, ext
?MSVCRT__MAX_EXT
:0);
1138 /******************************************************************
1139 * _wsplitpath_s (MSVCRT.@)
1141 * Secure version of _wsplitpath
1143 int CDECL
MSVCRT__wsplitpath_s(const MSVCRT_wchar_t
* inpath
,
1144 MSVCRT_wchar_t
* drive
, MSVCRT_size_t sz_drive
,
1145 MSVCRT_wchar_t
* dir
, MSVCRT_size_t sz_dir
,
1146 MSVCRT_wchar_t
* fname
, MSVCRT_size_t sz_fname
,
1147 MSVCRT_wchar_t
* ext
, MSVCRT_size_t sz_ext
)
1149 const MSVCRT_wchar_t
*p
, *end
;
1151 if (!inpath
|| (!drive
&& sz_drive
) ||
1152 (drive
&& !sz_drive
) ||
1155 (!fname
&& sz_fname
) ||
1156 (fname
&& !sz_fname
) ||
1160 *MSVCRT__errno() = MSVCRT_EINVAL
;
1161 return MSVCRT_EINVAL
;
1164 if (inpath
[0] && inpath
[1] == ':')
1168 if (sz_drive
<= 2) goto do_error
;
1169 drive
[0] = inpath
[0];
1170 drive
[1] = inpath
[1];
1175 else if (drive
) drive
[0] = '\0';
1177 /* look for end of directory part */
1179 for (p
= inpath
; *p
; p
++) if (*p
== '/' || *p
== '\\') end
= p
+ 1;
1181 if (end
) /* got a directory */
1185 if (sz_dir
<= end
- inpath
) goto do_error
;
1186 memcpy( dir
, inpath
, (end
- inpath
) * sizeof(MSVCRT_wchar_t
) );
1187 dir
[end
- inpath
] = 0;
1191 else if (dir
) dir
[0] = 0;
1193 /* look for extension: what's after the last dot */
1195 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
1197 if (!end
) end
= p
; /* there's no extension */
1201 if (sz_fname
<= end
- inpath
) goto do_error
;
1202 memcpy( fname
, inpath
, (end
- inpath
) * sizeof(MSVCRT_wchar_t
) );
1203 fname
[end
- inpath
] = 0;
1207 if (sz_ext
<= strlenW(end
)) goto do_error
;
1208 strcpyW( ext
, end
);
1212 if (drive
) drive
[0] = '\0';
1213 if (dir
) dir
[0] = '\0';
1214 if (fname
) fname
[0]= '\0';
1215 if (ext
) ext
[0]= '\0';
1216 *MSVCRT__errno() = MSVCRT_ERANGE
;
1217 return MSVCRT_ERANGE
;
1220 /*********************************************************************
1221 * _wsplitpath (MSVCRT.@)
1223 * Unicode version of _splitpath.
1225 void CDECL
MSVCRT__wsplitpath(const MSVCRT_wchar_t
*inpath
, MSVCRT_wchar_t
*drv
, MSVCRT_wchar_t
*dir
,
1226 MSVCRT_wchar_t
*fname
, MSVCRT_wchar_t
*ext
)
1228 MSVCRT__wsplitpath_s(inpath
, drv
, drv
?MSVCRT__MAX_DRIVE
:0, dir
, dir
?MSVCRT__MAX_DIR
:0,
1229 fname
, fname
?MSVCRT__MAX_FNAME
:0, ext
, ext
?MSVCRT__MAX_EXT
:0);
1232 /*********************************************************************
1233 * _wfullpath (MSVCRT.@)
1235 * Unicode version of _fullpath.
1237 MSVCRT_wchar_t
* CDECL
MSVCRT__wfullpath(MSVCRT_wchar_t
* absPath
, const MSVCRT_wchar_t
* relPath
, MSVCRT_size_t size
)
1242 BOOL alloced
= FALSE
;
1244 if (!relPath
|| !*relPath
)
1245 return MSVCRT__wgetcwd(absPath
, size
);
1247 if (absPath
== NULL
)
1249 buffer
= MSVCRT_malloc(MAX_PATH
* sizeof(WCHAR
));
1258 *MSVCRT__errno() = MSVCRT_ERANGE
;
1262 TRACE(":resolving relative path %s\n",debugstr_w(relPath
));
1264 rc
= GetFullPathNameW(relPath
,size
,buffer
,&lastpart
);
1266 if (rc
> 0 && rc
<= size
)
1271 MSVCRT_free(buffer
);
1276 /*********************************************************************
1277 * _fullpath (MSVCRT.@)
1279 * Create an absolute path from a relative path.
1282 * absPath [O] Destination for absolute path
1283 * relPath [I] Relative path to convert to absolute
1284 * size [I] Length of absPath in characters.
1287 * Success: If absPath is NULL, returns an allocated string containing the path.
1288 * Otherwise populates absPath with the path and returns it.
1289 * Failure: NULL. errno indicates the error.
1291 char * CDECL
MSVCRT__fullpath(char * absPath
, const char* relPath
, unsigned int size
)
1296 BOOL alloced
= FALSE
;
1298 if (!relPath
|| !*relPath
)
1299 return MSVCRT__getcwd(absPath
, size
);
1301 if (absPath
== NULL
)
1303 buffer
= MSVCRT_malloc(MAX_PATH
);
1312 *MSVCRT__errno() = MSVCRT_ERANGE
;
1316 TRACE(":resolving relative path '%s'\n",relPath
);
1318 rc
= GetFullPathNameA(relPath
,size
,buffer
,&lastpart
);
1320 if (rc
> 0 && rc
<= size
)
1325 MSVCRT_free(buffer
);
1330 /*********************************************************************
1331 * _makepath (MSVCRT.@)
1333 * Create a pathname.
1336 * path [O] Destination for created pathname
1337 * drive [I] Drive letter (e.g. "A:")
1338 * directory [I] Directory
1339 * filename [I] Name of the file, excluding extension
1340 * extension [I] File extension (e.g. ".TXT")
1343 * Nothing. If path is not large enough to hold the resulting pathname,
1344 * random process memory will be overwritten.
1346 VOID CDECL
MSVCRT__makepath(char * path
, const char * drive
,
1347 const char *directory
, const char * filename
,
1348 const char * extension
)
1352 TRACE("(%s %s %s %s)\n", debugstr_a(drive
), debugstr_a(directory
),
1353 debugstr_a(filename
), debugstr_a(extension
) );
1358 if (drive
&& drive
[0])
1363 if (directory
&& directory
[0])
1365 unsigned int len
= strlen(directory
);
1366 memmove(p
, directory
, len
);
1368 if (p
[-1] != '/' && p
[-1] != '\\')
1371 if (filename
&& filename
[0])
1373 unsigned int len
= strlen(filename
);
1374 memmove(p
, filename
, len
);
1377 if (extension
&& extension
[0])
1379 if (extension
[0] != '.')
1381 strcpy(p
, extension
);
1385 TRACE("returning %s\n",path
);
1388 /*********************************************************************
1389 * _wmakepath (MSVCRT.@)
1391 * Unicode version of _wmakepath.
1393 VOID CDECL
MSVCRT__wmakepath(MSVCRT_wchar_t
*path
, const MSVCRT_wchar_t
*drive
, const MSVCRT_wchar_t
*directory
,
1394 const MSVCRT_wchar_t
*filename
, const MSVCRT_wchar_t
*extension
)
1396 MSVCRT_wchar_t
*p
= path
;
1398 TRACE("%s %s %s %s\n", debugstr_w(drive
), debugstr_w(directory
),
1399 debugstr_w(filename
), debugstr_w(extension
));
1404 if (drive
&& drive
[0])
1409 if (directory
&& directory
[0])
1411 unsigned int len
= strlenW(directory
);
1412 memmove(p
, directory
, len
* sizeof(MSVCRT_wchar_t
));
1414 if (p
[-1] != '/' && p
[-1] != '\\')
1417 if (filename
&& filename
[0])
1419 unsigned int len
= strlenW(filename
);
1420 memmove(p
, filename
, len
* sizeof(MSVCRT_wchar_t
));
1423 if (extension
&& extension
[0])
1425 if (extension
[0] != '.')
1427 strcpyW(p
, extension
);
1432 TRACE("returning %s\n", debugstr_w(path
));
1435 /*********************************************************************
1436 * _makepath_s (MSVCRT.@)
1438 * Safe version of _makepath.
1440 int CDECL
MSVCRT__makepath_s(char *path
, MSVCRT_size_t size
, const char *drive
,
1441 const char *directory
, const char *filename
,
1442 const char *extension
)
1448 *MSVCRT__errno() = MSVCRT_EINVAL
;
1449 return MSVCRT_EINVAL
;
1452 if (drive
&& drive
[0])
1462 if (directory
&& directory
[0])
1464 unsigned int len
= strlen(directory
);
1465 unsigned int needs_separator
= directory
[len
- 1] != '/' && directory
[len
- 1] != '\\';
1466 unsigned int copylen
= min(size
- 1, len
);
1471 memmove(p
, directory
, copylen
);
1479 if (needs_separator
)
1489 if (filename
&& filename
[0])
1491 unsigned int len
= strlen(filename
);
1492 unsigned int copylen
= min(size
- 1, len
);
1497 memmove(p
, filename
, copylen
);
1506 if (extension
&& extension
[0])
1508 unsigned int len
= strlen(extension
);
1509 unsigned int needs_period
= extension
[0] != '.';
1510 unsigned int copylen
;
1521 copylen
= min(size
- 1, len
);
1522 memcpy(p
, extension
, copylen
);
1535 *MSVCRT__errno() = MSVCRT_ERANGE
;
1536 return MSVCRT_ERANGE
;
1539 /*********************************************************************
1540 * _wmakepath_s (MSVCRT.@)
1542 * Safe version of _wmakepath.
1544 int CDECL
MSVCRT__wmakepath_s(MSVCRT_wchar_t
*path
, MSVCRT_size_t size
, const MSVCRT_wchar_t
*drive
,
1545 const MSVCRT_wchar_t
*directory
, const MSVCRT_wchar_t
*filename
,
1546 const MSVCRT_wchar_t
*extension
)
1548 MSVCRT_wchar_t
*p
= path
;
1552 *MSVCRT__errno() = MSVCRT_EINVAL
;
1553 return MSVCRT_EINVAL
;
1556 if (drive
&& drive
[0])
1566 if (directory
&& directory
[0])
1568 unsigned int len
= strlenW(directory
);
1569 unsigned int needs_separator
= directory
[len
- 1] != '/' && directory
[len
- 1] != '\\';
1570 unsigned int copylen
= min(size
- 1, len
);
1575 memmove(p
, directory
, copylen
* sizeof(MSVCRT_wchar_t
));
1583 if (needs_separator
)
1593 if (filename
&& filename
[0])
1595 unsigned int len
= strlenW(filename
);
1596 unsigned int copylen
= min(size
- 1, len
);
1601 memmove(p
, filename
, copylen
* sizeof(MSVCRT_wchar_t
));
1610 if (extension
&& extension
[0])
1612 unsigned int len
= strlenW(extension
);
1613 unsigned int needs_period
= extension
[0] != '.';
1614 unsigned int copylen
;
1625 copylen
= min(size
- 1, len
);
1626 memcpy(p
, extension
, copylen
* sizeof(MSVCRT_wchar_t
));
1639 *MSVCRT__errno() = MSVCRT_ERANGE
;
1640 return MSVCRT_ERANGE
;
1643 /*********************************************************************
1644 * _searchenv (MSVCRT.@)
1646 * Search for a file in a list of paths from an environment variable.
1649 * file [I] Name of the file to search for.
1650 * env [I] Name of the environment variable containing a list of paths.
1651 * buf [O] Destination for the found file path.
1654 * Nothing. If the file is not found, buf will contain an empty string
1657 void CDECL
MSVCRT__searchenv(const char* file
, const char* env
, char *buf
)
1659 char*envVal
, *penv
, *end
;
1660 char path
[MAX_PATH
];
1661 MSVCRT_size_t path_len
, fname_len
= strlen(file
);
1666 if (GetFileAttributesA( file
) != INVALID_FILE_ATTRIBUTES
)
1668 GetFullPathNameA( file
, MAX_PATH
, buf
, NULL
);
1672 /* Search given environment variable */
1673 envVal
= MSVCRT_getenv(env
);
1676 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1681 TRACE(":searching for %s in paths %s\n", file
, envVal
);
1683 for(; *penv
; penv
= (*end
? end
+ 1 : end
))
1686 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1687 path_len
= end
- penv
;
1688 if (!path_len
|| path_len
>= MAX_PATH
)
1691 memcpy(path
, penv
, path_len
);
1692 if (path
[path_len
- 1] != '/' && path
[path_len
- 1] != '\\')
1693 path
[path_len
++] = '\\';
1694 if (path_len
+ fname_len
>= MAX_PATH
)
1697 memcpy(path
+ path_len
, file
, fname_len
+ 1);
1698 TRACE("Checking for file %s\n", path
);
1699 if (GetFileAttributesA( path
) != INVALID_FILE_ATTRIBUTES
)
1701 memcpy(buf
, path
, path_len
+ fname_len
+ 1);
1706 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1710 /*********************************************************************
1711 * _searchenv_s (MSVCRT.@)
1713 int CDECL
MSVCRT__searchenv_s(const char* file
, const char* env
, char *buf
, MSVCRT_size_t count
)
1715 char *envVal
, *penv
, *end
;
1716 char path
[MAX_PATH
];
1717 MSVCRT_size_t path_len
, fname_len
;
1719 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EINVAL
;
1720 if (!MSVCRT_CHECK_PMT(buf
!= NULL
)) return MSVCRT_EINVAL
;
1721 if (!MSVCRT_CHECK_PMT(count
> 0)) return MSVCRT_EINVAL
;
1723 if (count
> MAX_PATH
)
1724 FIXME("count > MAX_PATH not supported\n");
1726 fname_len
= strlen(file
);
1730 if (GetFileAttributesA( file
) != INVALID_FILE_ATTRIBUTES
)
1732 if (GetFullPathNameA( file
, count
, buf
, NULL
)) return 0;
1733 msvcrt_set_errno(GetLastError());
1737 /* Search given environment variable */
1738 envVal
= MSVCRT_getenv(env
);
1741 *MSVCRT__errno() = MSVCRT_ENOENT
;
1742 return MSVCRT_ENOENT
;
1746 TRACE(":searching for %s in paths %s\n", file
, envVal
);
1748 for(; *penv
; penv
= (*end
? end
+ 1 : end
))
1751 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1752 path_len
= end
- penv
;
1753 if (!path_len
|| path_len
>= MAX_PATH
)
1756 memcpy(path
, penv
, path_len
);
1757 if (path
[path_len
- 1] != '/' && path
[path_len
- 1] != '\\')
1758 path
[path_len
++] = '\\';
1759 if (path_len
+ fname_len
>= MAX_PATH
)
1762 memcpy(path
+ path_len
, file
, fname_len
+ 1);
1763 TRACE("Checking for file %s\n", path
);
1764 if (GetFileAttributesA( path
) != INVALID_FILE_ATTRIBUTES
)
1766 if (path_len
+ fname_len
+ 1 > count
)
1768 MSVCRT_INVALID_PMT("buf[count] is too small", MSVCRT_ERANGE
);
1769 return MSVCRT_ERANGE
;
1771 memcpy(buf
, path
, path_len
+ fname_len
+ 1);
1776 *MSVCRT__errno() = MSVCRT_ENOENT
;
1777 return MSVCRT_ENOENT
;
1780 /*********************************************************************
1781 * _wsearchenv (MSVCRT.@)
1783 * Unicode version of _searchenv
1785 void CDECL
MSVCRT__wsearchenv(const MSVCRT_wchar_t
* file
, const MSVCRT_wchar_t
* env
, MSVCRT_wchar_t
*buf
)
1787 MSVCRT_wchar_t
*envVal
, *penv
, *end
;
1788 MSVCRT_wchar_t path
[MAX_PATH
];
1789 MSVCRT_size_t path_len
, fname_len
= strlenW(file
);
1794 if (GetFileAttributesW( file
) != INVALID_FILE_ATTRIBUTES
)
1796 GetFullPathNameW( file
, MAX_PATH
, buf
, NULL
);
1800 /* Search given environment variable */
1801 envVal
= MSVCRT__wgetenv(env
);
1804 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1809 TRACE(":searching for %s in paths %s\n", debugstr_w(file
), debugstr_w(envVal
));
1811 for(; *penv
; penv
= (*end
? end
+ 1 : end
))
1814 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1815 path_len
= end
- penv
;
1816 if (!path_len
|| path_len
>= MAX_PATH
)
1819 memcpy(path
, penv
, path_len
* sizeof(MSVCRT_wchar_t
));
1820 if (path
[path_len
- 1] != '/' && path
[path_len
- 1] != '\\')
1821 path
[path_len
++] = '\\';
1822 if (path_len
+ fname_len
>= MAX_PATH
)
1825 memcpy(path
+ path_len
, file
, (fname_len
+ 1) * sizeof(MSVCRT_wchar_t
));
1826 TRACE("Checking for file %s\n", debugstr_w(path
));
1827 if (GetFileAttributesW( path
) != INVALID_FILE_ATTRIBUTES
)
1829 memcpy(buf
, path
, (path_len
+ fname_len
+ 1) * sizeof(MSVCRT_wchar_t
));
1834 msvcrt_set_errno(ERROR_FILE_NOT_FOUND
);
1838 /*********************************************************************
1839 * _wsearchenv_s (MSVCRT.@)
1841 int CDECL
MSVCRT__wsearchenv_s(const MSVCRT_wchar_t
* file
, const MSVCRT_wchar_t
* env
,
1842 MSVCRT_wchar_t
*buf
, MSVCRT_size_t count
)
1844 MSVCRT_wchar_t
*envVal
, *penv
, *end
;
1845 MSVCRT_wchar_t path
[MAX_PATH
];
1846 MSVCRT_size_t path_len
, fname_len
;
1848 if (!MSVCRT_CHECK_PMT(file
!= NULL
)) return MSVCRT_EINVAL
;
1849 if (!MSVCRT_CHECK_PMT(buf
!= NULL
)) return MSVCRT_EINVAL
;
1850 if (!MSVCRT_CHECK_PMT(count
> 0)) return MSVCRT_EINVAL
;
1852 if (count
> MAX_PATH
)
1853 FIXME("count > MAX_PATH not supported\n");
1855 fname_len
= strlenW(file
);
1859 if (GetFileAttributesW( file
) != INVALID_FILE_ATTRIBUTES
)
1861 if (GetFullPathNameW( file
, count
, buf
, NULL
)) return 0;
1862 msvcrt_set_errno(GetLastError());
1866 /* Search given environment variable */
1867 envVal
= MSVCRT__wgetenv(env
);
1870 *MSVCRT__errno() = MSVCRT_ENOENT
;
1871 return MSVCRT_ENOENT
;
1875 TRACE(":searching for %s in paths %s\n", debugstr_w(file
), debugstr_w(envVal
));
1877 for(; *penv
; penv
= (*end
? end
+ 1 : end
))
1880 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1881 path_len
= end
- penv
;
1882 if (!path_len
|| path_len
>= MAX_PATH
)
1885 memcpy(path
, penv
, path_len
* sizeof(MSVCRT_wchar_t
));
1886 if (path
[path_len
- 1] != '/' && path
[path_len
- 1] != '\\')
1887 path
[path_len
++] = '\\';
1888 if (path_len
+ fname_len
>= MAX_PATH
)
1891 memcpy(path
+ path_len
, file
, (fname_len
+ 1) * sizeof(MSVCRT_wchar_t
));
1892 TRACE("Checking for file %s\n", debugstr_w(path
));
1893 if (GetFileAttributesW( path
) != INVALID_FILE_ATTRIBUTES
)
1895 if (path_len
+ fname_len
+ 1 > count
)
1897 MSVCRT_INVALID_PMT("buf[count] is too small", MSVCRT_ERANGE
);
1898 return MSVCRT_ERANGE
;
1900 memcpy(buf
, path
, (path_len
+ fname_len
+ 1) * sizeof(MSVCRT_wchar_t
));
1905 *MSVCRT__errno() = MSVCRT_ENOENT
;
1906 return MSVCRT_ENOENT
;