ReactOS 0.4.16-dev-2104-gb84fa49
dir.c
Go to the documentation of this file.
1/*
2 * msvcrt.dll drive/directory functions
3 *
4 * Copyright 1996,1998 Marcus Meissner
5 * Copyright 1996 Jukka Iivonen
6 * Copyright 1997,2000 Uwe Bonnes
7 * Copyright 2000 Jon Griffiths
8 *
9 * 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.
13 *
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.
18 *
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
22 */
23
24#include <corecrt_io.h>
25#include <mbctype.h>
26#include <stdarg.h>
27#include <stdlib.h>
28#include <direct.h>
29
30#include "windef.h"
31#include "winbase.h"
32#include "winternl.h"
33#include "msvcrt.h"
34#include "wine/debug.h"
35
37
38#undef _wfindfirst
39#undef _wfindfirsti64
40#undef _wfindnext
41#undef _wfindnexti64
42#undef _wfindfirst32
43#undef _wfindnext32
44#undef _wfindfirst64i32
45#undef _wfindfirst64
46#undef _wfindnext64i32
47#undef _wfindnext64
48
49#undef _findfirst
50#undef _findfirsti64
51#undef _findnext
52#undef _findnexti64
53#undef _findfirst32
54#undef _findnext32
55#undef _findfirst64i32
56#undef _findfirst64
57#undef _findnext64i32
58#undef _findnext64
59
60/* INTERNAL: Translate WIN32_FIND_DATAA to finddata_t */
61static void msvcrt_fttofd( const WIN32_FIND_DATAA *fd, struct _finddata_t* ft)
62{
63 DWORD dw;
64
65 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
66 ft->attrib = 0;
67 else
68 ft->attrib = fd->dwFileAttributes;
69
70 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftCreationTime, &dw );
71 ft->time_create = dw;
72 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastAccessTime, &dw );
73 ft->time_access = dw;
74 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastWriteTime, &dw );
75 ft->time_write = dw;
76 ft->size = fd->nFileSizeLow;
77 strcpy(ft->name, fd->cFileName);
78}
79
80/* INTERNAL: Translate WIN32_FIND_DATAW to wfinddata_t */
81static void msvcrt_wfttofd( const WIN32_FIND_DATAW *fd, struct _wfinddata_t* ft)
82{
83 DWORD dw;
84
85 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
86 ft->attrib = 0;
87 else
88 ft->attrib = fd->dwFileAttributes;
89
90 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftCreationTime, &dw );
91 ft->time_create = dw;
92 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastAccessTime, &dw );
93 ft->time_access = dw;
94 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastWriteTime, &dw );
95 ft->time_write = dw;
96 ft->size = fd->nFileSizeLow;
97 wcscpy(ft->name, fd->cFileName);
98}
99
100/* INTERNAL: Translate WIN32_FIND_DATAW to wfinddata32_t */
101static void msvcrt_wfttofd32(const WIN32_FIND_DATAW *fd, struct _wfinddata32_t* ft)
102{
103 DWORD dw;
104
105 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
106 ft->attrib = 0;
107 else
108 ft->attrib = fd->dwFileAttributes;
109
110 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftCreationTime, &dw );
111 ft->time_create = dw;
112 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastAccessTime, &dw );
113 ft->time_access = dw;
114 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastWriteTime, &dw );
115 ft->time_write = dw;
116 ft->size = fd->nFileSizeLow;
117 wcscpy(ft->name, fd->cFileName);
118}
119
120/* INTERNAL: Translate WIN32_FIND_DATAA to finddatai64_t */
121static void msvcrt_fttofdi64( const WIN32_FIND_DATAA *fd, struct _finddatai64_t* ft)
122{
123 DWORD dw;
124
125 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
126 ft->attrib = 0;
127 else
128 ft->attrib = fd->dwFileAttributes;
129
130 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftCreationTime, &dw );
131 ft->time_create = dw;
132 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastAccessTime, &dw );
133 ft->time_access = dw;
134 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastWriteTime, &dw );
135 ft->time_write = dw;
136 ft->size = ((__int64)fd->nFileSizeHigh) << 32 | fd->nFileSizeLow;
137 strcpy(ft->name, fd->cFileName);
138}
139
140/* INTERNAL: Translate WIN32_FIND_DATAW to wfinddata64_t */
141static void msvcrt_wfttofd64( const WIN32_FIND_DATAW *fd, struct _wfinddata64_t* ft)
142{
143 DWORD dw;
144
145 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
146 ft->attrib = 0;
147 else
148 ft->attrib = fd->dwFileAttributes;
149
150 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftCreationTime, &dw );
151 ft->time_create = dw;
152 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastAccessTime, &dw );
153 ft->time_access = dw;
154 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastWriteTime, &dw );
155 ft->time_write = dw;
156 ft->size = ((__int64)fd->nFileSizeHigh) << 32 | fd->nFileSizeLow;
157 wcscpy(ft->name, fd->cFileName);
158}
159
160/* INTERNAL: Translate WIN32_FIND_DATAW to wfinddatai64_t */
161static void msvcrt_wfttofdi64( const WIN32_FIND_DATAW *fd, struct _wfinddatai64_t* ft)
162{
163 DWORD dw;
164
165 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
166 ft->attrib = 0;
167 else
168 ft->attrib = fd->dwFileAttributes;
169
170 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftCreationTime, &dw );
171 ft->time_create = dw;
172 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastAccessTime, &dw );
173 ft->time_access = dw;
174 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastWriteTime, &dw );
175 ft->time_write = dw;
176 ft->size = ((__int64)fd->nFileSizeHigh) << 32 | fd->nFileSizeLow;
177 wcscpy(ft->name, fd->cFileName);
178}
179
180/* INTERNAL: Translate WIN32_FIND_DATAW to wfinddata64i32_t */
182{
183 DWORD dw;
184
185 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
186 ft->attrib = 0;
187 else
188 ft->attrib = fd->dwFileAttributes;
189
190 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftCreationTime, &dw );
191 ft->time_create = dw;
192 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastAccessTime, &dw );
193 ft->time_access = dw;
194 RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastWriteTime, &dw );
195 ft->time_write = dw;
196 ft->size = fd->nFileSizeLow;
197 wcscpy(ft->name, fd->cFileName);
198}
199
200/*********************************************************************
201 * _chdir (MSVCRT.@)
202 *
203 * Change the current working directory.
204 *
205 * PARAMS
206 * newdir [I] Directory to change to
207 *
208 * RETURNS
209 * Success: 0. The current working directory is set to newdir.
210 * Failure: -1. errno indicates the error.
211 *
212 * NOTES
213 * See SetCurrentDirectoryA.
214 */
215int CDECL _chdir(const char * newdir)
216{
217 wchar_t *newdirW = NULL;
218 int ret;
219
220 if (newdir && !(newdirW = wstrdupa_utf8(newdir))) return -1;
221 ret = _wchdir(newdirW);
222 free(newdirW);
223 return ret;
224}
225
226/*********************************************************************
227 * _wchdir (MSVCRT.@)
228 *
229 * Unicode version of _chdir.
230 */
231int CDECL _wchdir(const wchar_t * newdir)
232{
233 if (!SetCurrentDirectoryW(newdir))
234 {
235 msvcrt_set_errno(newdir?GetLastError():0);
236 return -1;
237 }
238#ifdef __REACTOS__
239 /* Update the drive-specific current directory variable */
240 WCHAR fulldir[MAX_PATH];
241 if (GetCurrentDirectoryW(ARRAYSIZE(fulldir), fulldir) >= 2)
242 {
243 if (fulldir[1] == L':')
244 {
245 WCHAR envvar[4] = { L'=', towupper(fulldir[0]), L':', L'\0' };
246 SetEnvironmentVariableW(envvar, fulldir);
247 }
248 }
249#endif
250 return 0;
251}
252
253/*********************************************************************
254 * _chdrive (MSVCRT.@)
255 *
256 * Change the current drive.
257 *
258 * PARAMS
259 * newdrive [I] Drive number to change to (1 = 'A', 2 = 'B', ...)
260 *
261 * RETURNS
262 * Success: 0. The current drive is set to newdrive.
263 * Failure: -1. errno indicates the error.
264 *
265 * NOTES
266 * See SetCurrentDirectoryA.
267 */
268int CDECL _chdrive(int newdrive)
269{
270 WCHAR buffer[] = L"A:";
271
272 buffer[0] += newdrive - 1;
274 {
276 if (newdrive <= 0)
277 *_errno() = EACCES;
278 return -1;
279 }
280 return 0;
281}
282
283/*********************************************************************
284 * _findclose (MSVCRT.@)
285 *
286 * Close a handle returned by _findfirst().
287 *
288 * PARAMS
289 * hand [I] Handle to close
290 *
291 * RETURNS
292 * Success: 0. All resources associated with hand are freed.
293 * Failure: -1. errno indicates the error.
294 *
295 * NOTES
296 * See FindClose.
297 */
299{
300 TRACE(":handle %Iu\n",hand);
301 if (!FindClose((HANDLE)hand))
302 {
304 return -1;
305 }
306 return 0;
307}
308
309/*********************************************************************
310 * _findfirst (MSVCRT.@)
311 *
312 * Open a handle for iterating through a directory.
313 *
314 * PARAMS
315 * fspec [I] File specification of files to iterate.
316 * ft [O] Information for the first file found.
317 *
318 * RETURNS
319 * Success: A handle suitable for passing to _findnext() and _findclose().
320 * ft is populated with the details of the found file.
321 * Failure: -1. errno indicates the error.
322 *
323 * NOTES
324 * See FindFirstFileA.
325 */
326intptr_t CDECL _findfirst(const char * fspec, struct _finddata_t* ft)
327{
329 HANDLE hfind;
330
331 hfind = FindFirstFileA(fspec, &find_data);
332 if (hfind == INVALID_HANDLE_VALUE)
333 {
335 return -1;
336 }
338 TRACE(":got handle %p\n",hfind);
339 return (intptr_t)hfind;
340}
341
342/*********************************************************************
343 * _wfindfirst (MSVCRT.@)
344 *
345 * Unicode version of _findfirst.
346 */
347intptr_t CDECL _wfindfirst(const wchar_t * fspec, struct _wfinddata_t* ft)
348{
350 HANDLE hfind;
351
352 hfind = FindFirstFileW(fspec, &find_data);
353 if (hfind == INVALID_HANDLE_VALUE)
354 {
356 return -1;
357 }
359 TRACE(":got handle %p\n",hfind);
360 return (intptr_t)hfind;
361}
362
363/*********************************************************************
364 * _wfindfirst32 (MSVCRT.@)
365 *
366 * Unicode version of _findfirst32.
367 */
368intptr_t CDECL _wfindfirst32(const wchar_t * fspec, struct _wfinddata32_t* ft)
369{
371 HANDLE hfind;
372
373 hfind = FindFirstFileW(fspec, &find_data);
374 if (hfind == INVALID_HANDLE_VALUE)
375 {
377 return -1;
378 }
380 TRACE(":got handle %p\n", hfind);
381 return (intptr_t)hfind;
382}
383
384static int finddata32_wtoa(const struct _wfinddata32_t *wfd, struct _finddata32_t *fd)
385{
386 fd->attrib = wfd->attrib;
387 fd->time_create = wfd->time_create;
388 fd->time_access = wfd->time_access;
389 fd->time_write = wfd->time_write;
390 fd->size = wfd->size;
391 return convert_wcs_to_acp_utf8(wfd->name, fd->name, ARRAY_SIZE(fd->name));
392}
393
394/*********************************************************************
395 * _findfirst32 (MSVCRT.@)
396 */
397intptr_t CDECL _findfirst32(const char *fspec, struct _finddata32_t *ft)
398{
399 struct _wfinddata32_t wft;
400 wchar_t *fspecW = NULL;
402
403 if (fspec && !(fspecW = wstrdupa_utf8(fspec))) return -1;
404 ret = _wfindfirst32(fspecW, &wft);
405 free(fspecW);
406 if (ret != -1 && !finddata32_wtoa(&wft, ft))
407 {
409 return -1;
410 }
411 return ret;
412}
413
414/*********************************************************************
415 * _findfirsti64 (MSVCRT.@)
416 *
417 * 64-bit version of _findfirst.
418 */
419intptr_t CDECL _findfirsti64(const char * fspec, struct _finddatai64_t* ft)
420{
422 HANDLE hfind;
423
424 hfind = FindFirstFileA(fspec, &find_data);
425 if (hfind == INVALID_HANDLE_VALUE)
426 {
428 return -1;
429 }
431 TRACE(":got handle %p\n",hfind);
432 return (intptr_t)hfind;
433}
434
435/*********************************************************************
436 * _wfindfirst64 (MSVCRT.@)
437 *
438 * Unicode version of _findfirst64.
439 */
440intptr_t CDECL _wfindfirst64(const wchar_t * fspec, struct _wfinddata64_t* ft)
441{
443 HANDLE hfind;
444
445 hfind = FindFirstFileW(fspec, &find_data);
446 if (hfind == INVALID_HANDLE_VALUE)
447 {
449 return -1;
450 }
452 TRACE(":got handle %p\n",hfind);
453 return (intptr_t)hfind;
454}
455
456static int finddata64_wtoa(const struct _wfinddata64_t *wfd, struct _finddata64_t *fd)
457{
458 fd->attrib = wfd->attrib;
459 fd->time_create = wfd->time_create;
460 fd->time_access = wfd->time_access;
461 fd->time_write = wfd->time_write;
462 fd->size = wfd->size;
463 return convert_wcs_to_acp_utf8(wfd->name, fd->name, ARRAY_SIZE(fd->name));
464}
465
466/*********************************************************************
467 * _findfirst64 (MSVCRT.@)
468 *
469 * 64-bit version of _findfirst.
470 */
471intptr_t CDECL _findfirst64(const char *fspec, struct _finddata64_t *ft)
472{
473 struct _wfinddata64_t wft;
474 wchar_t *fspecW = NULL;
476
477 if (fspec && !(fspecW = wstrdupa_utf8(fspec))) return -1;
478 ret = _wfindfirst64(fspecW, &wft);
479 free(fspecW);
480 if (ret != -1 && !finddata64_wtoa(&wft, ft))
481 {
483 return -1;
484 }
485 return ret;
486}
487
488/*********************************************************************
489 * _wfindfirst64i32 (MSVCRT.@)
490 *
491 * Unicode version of _findfirst64i32.
492 */
493intptr_t CDECL _wfindfirst64i32(const wchar_t * fspec, struct _wfinddata64i32_t* ft)
494{
496 HANDLE hfind;
497
498 hfind = FindFirstFileW(fspec, &find_data);
499 if (hfind == INVALID_HANDLE_VALUE)
500 {
502 return -1;
503 }
505 TRACE(":got handle %p\n",hfind);
506 return (intptr_t)hfind;
507}
508
509static int finddata64i32_wtoa(const struct _wfinddata64i32_t *wfd, struct _finddata64i32_t *fd)
510{
511 fd->attrib = wfd->attrib;
512 fd->time_create = wfd->time_create;
513 fd->time_access = wfd->time_access;
514 fd->time_write = wfd->time_write;
515 fd->size = wfd->size;
516 return convert_wcs_to_acp_utf8(wfd->name, fd->name, ARRAY_SIZE(fd->name));
517}
518
519/*********************************************************************
520 * _findfirst64i32 (MSVCRT.@)
521 *
522 * 64-bit/32-bit version of _findfirst.
523 */
524intptr_t CDECL _findfirst64i32(const char *fspec, struct _finddata64i32_t *ft)
525{
526 struct _wfinddata64i32_t wft;
527 wchar_t *fspecW = NULL;
529
530 if (fspec && !(fspecW = wstrdupa_utf8(fspec))) return -1;
531 ret = _wfindfirst64i32(fspecW, &wft);
532 free(fspecW);
533 if (ret != -1 && !finddata64i32_wtoa(&wft, ft))
534 {
536 return -1;
537 }
538 return ret;
539}
540
541/*********************************************************************
542 * _wfindfirsti64 (MSVCRT.@)
543 *
544 * Unicode version of _findfirsti64.
545 */
546intptr_t CDECL _wfindfirsti64(const wchar_t * fspec, struct _wfinddatai64_t* ft)
547{
549 HANDLE hfind;
550
551 hfind = FindFirstFileW(fspec, &find_data);
552 if (hfind == INVALID_HANDLE_VALUE)
553 {
555 return -1;
556 }
558 TRACE(":got handle %p\n",hfind);
559 return (intptr_t)hfind;
560}
561
562/*********************************************************************
563 * _findnext (MSVCRT.@)
564 *
565 * Find the next file from a file search handle.
566 *
567 * PARAMS
568 * hand [I] Handle to the search returned from _findfirst().
569 * ft [O] Information for the file found.
570 *
571 * RETURNS
572 * Success: 0. ft is populated with the details of the found file.
573 * Failure: -1. errno indicates the error.
574 *
575 * NOTES
576 * See FindNextFileA.
577 */
578int CDECL _findnext(intptr_t hand, struct _finddata_t * ft)
579{
581
582 if (!FindNextFileA((HANDLE)hand, &find_data))
583 {
584 *_errno() = ENOENT;
585 return -1;
586 }
587
589 return 0;
590}
591
592/*********************************************************************
593 * _wfindnext32 (MSVCRT.@)
594 */
596{
598
599 if (!FindNextFileW((HANDLE)hand, &find_data))
600 {
601 *_errno() = ENOENT;
602 return -1;
603 }
604
606 return 0;
607}
608
609/*********************************************************************
610 * _findnext32 (MSVCRT.@)
611 */
613{
614 struct _wfinddata32_t wft;
615 int ret;
616
617 ret = _wfindnext32(hand, &wft);
618 if (!ret && !finddata32_wtoa(&wft, ft)) ret = -1;
619 return ret;
620}
621
622/*********************************************************************
623 * _wfindnext (MSVCRT.@)
624 *
625 * Unicode version of _findnext.
626 */
627int CDECL _wfindnext(intptr_t hand, struct _wfinddata_t * ft)
628{
630
631 if (!FindNextFileW((HANDLE)hand, &find_data))
632 {
633 *_errno() = ENOENT;
634 return -1;
635 }
636
638 return 0;
639}
640
641/*********************************************************************
642 * _findnexti64 (MSVCRT.@)
643 *
644 * 64-bit version of _findnext.
645 */
647{
649
650 if (!FindNextFileA((HANDLE)hand, &find_data))
651 {
652 *_errno() = ENOENT;
653 return -1;
654 }
655
657 return 0;
658}
659
660/*********************************************************************
661 * _wfindnext64 (MSVCRT.@)
662 *
663 * Unicode version of _wfindnext64.
664 */
666{
668
669 if (!FindNextFileW((HANDLE)hand, &find_data))
670 {
671 *_errno() = ENOENT;
672 return -1;
673 }
674
676 return 0;
677}
678
679/*********************************************************************
680 * _findnext64 (MSVCRT.@)
681 *
682 * 64-bit version of _findnext.
683 */
685{
686 struct _wfinddata64_t wft;
687 int ret;
688
689 ret = _wfindnext64(hand, &wft);
690 if (!ret && !finddata64_wtoa(&wft, ft)) ret = -1;
691 return ret;
692}
693
694/*********************************************************************
695 * _wfindnexti64 (MSVCRT.@)
696 *
697 * Unicode version of _findnexti64.
698 */
700{
702
703 if (!FindNextFileW((HANDLE)hand, &find_data))
704 {
705 *_errno() = ENOENT;
706 return -1;
707 }
708
710 return 0;
711}
712
713/*********************************************************************
714 * _wfindnext64i32 (MSVCRT.@)
715 *
716 * Unicode version of _findnext64i32.
717 */
719{
721
722 if (!FindNextFileW((HANDLE)hand, &find_data))
723 {
724 *_errno() = ENOENT;
725 return -1;
726 }
727
729 return 0;
730}
731
732/*********************************************************************
733 * _findnext64i32 (MSVCRT.@)
734 *
735 * 64-bit/32-bit version of _findnext.
736 */
738{
739 struct _wfinddata64i32_t wft;
740 int ret;
741
742 ret = _wfindnext64i32(hand, &wft);
743 if (!ret && !finddata64i32_wtoa(&wft, ft)) ret = -1;
744 return ret;
745}
746
747/*********************************************************************
748 * _getcwd (MSVCRT.@)
749 *
750 * Get the current working directory.
751 *
752 * PARAMS
753 * buf [O] Destination for current working directory.
754 * size [I] Size of buf in characters
755 *
756 * RETURNS
757 * Success: If buf is NULL, returns an allocated string containing the path.
758 * Otherwise populates buf with the path and returns it.
759 * Failure: NULL. errno indicates the error.
760 */
761char* CDECL _getcwd(char * buf, int size)
762{
763 wchar_t dirW[MAX_PATH];
764 int len;
765
766 if (!_wgetcwd(dirW, ARRAY_SIZE(dirW))) return NULL;
767
768 if (!buf) return astrdupw_utf8(dirW);
769 len = convert_wcs_to_acp_utf8(dirW, NULL, 0);
770 if (!len) return NULL;
771 if (len > size)
772 {
773 *_errno() = ERANGE;
774 return NULL;
775 }
777 return buf;
778}
779
780/*********************************************************************
781 * _wgetcwd (MSVCRT.@)
782 *
783 * Unicode version of _getcwd.
784 */
785wchar_t* CDECL _wgetcwd(wchar_t * buf, int size)
786{
787 wchar_t dir[MAX_PATH];
788 int dir_len = GetCurrentDirectoryW(MAX_PATH,dir);
789
790 if (dir_len < 1)
791 return NULL; /* FIXME: Real return value untested */
792
793 if (!buf)
794 {
795 if (size <= dir_len) size = dir_len + 1;
796 if (!(buf = malloc( size * sizeof(WCHAR) ))) return NULL;
797 }
798 else if (dir_len >= size)
799 {
800 *_errno() = ERANGE;
801 return NULL; /* buf too small */
802 }
803 wcscpy(buf,dir);
804 return buf;
805}
806
807/*********************************************************************
808 * _getdrive (MSVCRT.@)
809 *
810 * Get the current drive number.
811 *
812 * PARAMS
813 * None.
814 *
815 * RETURNS
816 * Success: The drive letter number from 1 to 26 ("A:" to "Z:").
817 * Failure: 0.
818 */
820{
823 buffer[0] >= 'A' && buffer[0] <= 'z' && buffer[1] == ':')
824 return towupper(buffer[0]) - 'A' + 1;
825 return 0;
826}
827
828/*********************************************************************
829 * _getdcwd (MSVCRT.@)
830 *
831 * Get the current working directory on a given disk.
832 *
833 * PARAMS
834 * drive [I] Drive letter to get the current working directory from.
835 * buf [O] Destination for the current working directory.
836 * size [I] Length of drive in characters.
837 *
838 * RETURNS
839 * Success: If drive is NULL, returns an allocated string containing the path.
840 * Otherwise populates drive with the path and returns it.
841 * Failure: NULL. errno indicates the error.
842 */
843char* CDECL _getdcwd(int drive, char * buf, int size)
844{
845 wchar_t dirW[MAX_PATH];
846 int len;
847
848 if (!_wgetdcwd(drive, dirW, ARRAY_SIZE(dirW))) return NULL;
849
850 if (!buf) return astrdupw_utf8(dirW);
851 len = convert_wcs_to_acp_utf8(dirW, NULL, 0);
852 if (!len) return NULL;
853 if (len > size)
854 {
855 *_errno() = ERANGE;
856 return NULL;
857 }
859 return buf;
860}
861
862/*********************************************************************
863 * _wgetdcwd (MSVCRT.@)
864 *
865 * Unicode version of _wgetdcwd.
866 */
867wchar_t* CDECL _wgetdcwd(int drive, wchar_t * buf, int size)
868{
869 static wchar_t* dummy;
870
871 TRACE(":drive %d(%c), size %d\n",drive, drive + 'A' - 1, size);
872
873 if (!drive || drive == _getdrive())
874 return _wgetcwd(buf,size); /* current */
875 else
876 {
877 wchar_t dir[MAX_PATH];
878 wchar_t drivespec[4] = L"A:\\";
879 int dir_len;
880
881 drivespec[0] += drive - 1;
882 if (GetDriveTypeW(drivespec) < DRIVE_REMOVABLE)
883 {
884 *_errno() = EACCES;
885 return NULL;
886 }
887
888 dir_len = GetFullPathNameW(drivespec,MAX_PATH,dir,&dummy);
889 if (dir_len >= size || dir_len < 1)
890 {
891 *_errno() = ERANGE;
892 return NULL; /* buf too small */
893 }
894
895 TRACE(":returning %s\n", debugstr_w(dir));
896 if (!buf)
897 return _wcsdup(dir); /* allocate */
898 wcscpy(buf,dir);
899 }
900 return buf;
901}
902
903/*********************************************************************
904 * _getdiskfree (MSVCRT.@)
905 *
906 * Get information about the free space on a drive.
907 *
908 * PARAMS
909 * disk [I] Drive number to get information about (1 = 'A', 2 = 'B', ...)
910 * info [O] Destination for the resulting information.
911 *
912 * RETURNS
913 * Success: 0. info is updated with the free space information.
914 * Failure: An error code from GetLastError().
915 *
916 * NOTES
917 * See GetLastError().
918 */
919unsigned int CDECL _getdiskfree(unsigned int disk, struct _diskfree_t * d)
920{
921 WCHAR drivespec[] = L"@:\\";
922 DWORD ret[4];
923 unsigned int err;
924
925 if (disk > 26)
926 return ERROR_INVALID_PARAMETER; /* MSVCRT doesn't set errno here */
927
928 drivespec[0] += disk; /* make a drive letter */
929
930 if (GetDiskFreeSpaceW(disk==0?NULL:drivespec,ret,ret+1,ret+2,ret+3))
931 {
932 d->sectors_per_cluster = ret[0];
933 d->bytes_per_sector = ret[1];
934 d->avail_clusters = ret[2];
935 d->total_clusters = ret[3];
936 return 0;
937 }
938 err = GetLastError();
940 return err;
941}
942
943/*********************************************************************
944 * _mkdir (MSVCRT.@)
945 *
946 * Create a directory.
947 *
948 * PARAMS
949 * newdir [I] Name of directory to create.
950 *
951 * RETURNS
952 * Success: 0. The directory indicated by newdir is created.
953 * Failure: -1. errno indicates the error.
954 *
955 * NOTES
956 * See CreateDirectoryA.
957 */
958int CDECL _mkdir(const char * newdir)
959{
960 wchar_t *newdirW = NULL;
961 int ret;
962
963 if (newdir && !(newdirW = wstrdupa_utf8(newdir))) return -1;
964 ret = _wmkdir(newdirW);
965 free(newdirW);
966 return ret;
967}
968
969/*********************************************************************
970 * _wmkdir (MSVCRT.@)
971 *
972 * Unicode version of _mkdir.
973 */
974int CDECL _wmkdir(const wchar_t* newdir)
975{
976 if (CreateDirectoryW(newdir,NULL))
977 return 0;
979 return -1;
980}
981
982/*********************************************************************
983 * _rmdir (MSVCRT.@)
984 *
985 * Delete a directory.
986 *
987 * PARAMS
988 * dir [I] Name of directory to delete.
989 *
990 * RETURNS
991 * Success: 0. The directory indicated by newdir is deleted.
992 * Failure: -1. errno indicates the error.
993 *
994 * NOTES
995 * See RemoveDirectoryA.
996 */
997int CDECL _rmdir(const char * dir)
998{
999 wchar_t *dirW = NULL;
1000 int ret;
1001
1002 if (dir && !(dirW = wstrdupa_utf8(dir))) return -1;
1003 ret = _wrmdir(dirW);
1004 free(dirW);
1005 return ret;
1006}
1007
1008/*********************************************************************
1009 * _wrmdir (MSVCRT.@)
1010 *
1011 * Unicode version of _rmdir.
1012 */
1013int CDECL _wrmdir(const wchar_t * dir)
1014{
1015 if (RemoveDirectoryW(dir))
1016 return 0;
1018 return -1;
1019}
1020
1021/******************************************************************
1022 * _splitpath_s (MSVCRT.@)
1023 */
1024errno_t CDECL _splitpath_s(const char* inpath,
1025 char* drive, size_t sz_drive,
1026 char* dir, size_t sz_dir,
1027 char* fname, size_t sz_fname,
1028 char* ext, size_t sz_ext)
1029{
1030 const char *p, *end;
1031
1032 if (!inpath || (!drive && sz_drive) ||
1033 (drive && !sz_drive) ||
1034 (!dir && sz_dir) ||
1035 (dir && !sz_dir) ||
1036 (!fname && sz_fname) ||
1037 (fname && !sz_fname) ||
1038 (!ext && sz_ext) ||
1039 (ext && !sz_ext))
1040 {
1041 *_errno() = EINVAL;
1042 return EINVAL;
1043 }
1044
1045 if (inpath[0] && inpath[1] == ':')
1046 {
1047 if (drive)
1048 {
1049 if (sz_drive <= 2) goto do_error;
1050 drive[0] = inpath[0];
1051 drive[1] = inpath[1];
1052 drive[2] = 0;
1053 }
1054 inpath += 2;
1055 }
1056 else if (drive) drive[0] = '\0';
1057
1058 /* look for end of directory part */
1059 end = NULL;
1060 for (p = inpath; *p; p++)
1061 {
1062 if (_ismbblead((unsigned char)*p))
1063 {
1064 p++;
1065 continue;
1066 }
1067 if (*p == '/' || *p == '\\') end = p + 1;
1068 }
1069
1070 if (end) /* got a directory */
1071 {
1072 if (dir)
1073 {
1074 if (sz_dir <= end - inpath) goto do_error;
1075 memcpy( dir, inpath, (end - inpath) );
1076 dir[end - inpath] = 0;
1077 }
1078 inpath = end;
1079 }
1080 else if (dir) dir[0] = 0;
1081
1082 /* look for extension: what's after the last dot */
1083 end = NULL;
1084 for (p = inpath; *p; p++) if (*p == '.') end = p;
1085
1086 if (!end) end = p; /* there's no extension */
1087
1088 if (fname)
1089 {
1090 if (sz_fname <= end - inpath) goto do_error;
1091 memcpy( fname, inpath, (end - inpath) );
1092 fname[end - inpath] = 0;
1093 }
1094 if (ext)
1095 {
1096 if (sz_ext <= strlen(end)) goto do_error;
1097 strcpy( ext, end );
1098 }
1099 return 0;
1100do_error:
1101 if (drive) drive[0] = '\0';
1102 if (dir) dir[0] = '\0';
1103 if (fname) fname[0]= '\0';
1104 if (ext) ext[0]= '\0';
1105 *_errno() = ERANGE;
1106 return ERANGE;
1107}
1108
1109/*********************************************************************
1110 * _splitpath (MSVCRT.@)
1111 */
1112void CDECL _splitpath(const char *inpath, char *drv, char *dir,
1113 char *fname, char *ext)
1114{
1115 _splitpath_s(inpath, drv, drv ? _MAX_DRIVE : 0, dir, dir ? _MAX_DIR : 0,
1116 fname, fname ? _MAX_FNAME : 0, ext, ext ? _MAX_EXT : 0);
1117}
1118
1119/******************************************************************
1120 * _wsplitpath_s (MSVCRT.@)
1121 *
1122 * Secure version of _wsplitpath
1123 */
1124int CDECL _wsplitpath_s(const wchar_t* inpath,
1125 wchar_t* drive, size_t sz_drive,
1126 wchar_t* dir, size_t sz_dir,
1127 wchar_t* fname, size_t sz_fname,
1128 wchar_t* ext, size_t sz_ext)
1129{
1130 const wchar_t *p, *end;
1131
1132 if (!inpath || (!drive && sz_drive) ||
1133 (drive && !sz_drive) ||
1134 (!dir && sz_dir) ||
1135 (dir && !sz_dir) ||
1136 (!fname && sz_fname) ||
1137 (fname && !sz_fname) ||
1138 (!ext && sz_ext) ||
1139 (ext && !sz_ext))
1140 {
1141 *_errno() = EINVAL;
1142 return EINVAL;
1143 }
1144
1145 if (inpath[0] && inpath[1] == ':')
1146 {
1147 if (drive)
1148 {
1149 if (sz_drive <= 2) goto do_error;
1150 drive[0] = inpath[0];
1151 drive[1] = inpath[1];
1152 drive[2] = 0;
1153 }
1154 inpath += 2;
1155 }
1156 else if (drive) drive[0] = '\0';
1157
1158 /* look for end of directory part */
1159 end = NULL;
1160 for (p = inpath; *p; p++) if (*p == '/' || *p == '\\') end = p + 1;
1161
1162 if (end) /* got a directory */
1163 {
1164 if (dir)
1165 {
1166 if (sz_dir <= end - inpath) goto do_error;
1167 memcpy( dir, inpath, (end - inpath) * sizeof(wchar_t) );
1168 dir[end - inpath] = 0;
1169 }
1170 inpath = end;
1171 }
1172 else if (dir) dir[0] = 0;
1173
1174 /* look for extension: what's after the last dot */
1175 end = NULL;
1176 for (p = inpath; *p; p++) if (*p == '.') end = p;
1177
1178 if (!end) end = p; /* there's no extension */
1179
1180 if (fname)
1181 {
1182 if (sz_fname <= end - inpath) goto do_error;
1183 memcpy( fname, inpath, (end - inpath) * sizeof(wchar_t) );
1184 fname[end - inpath] = 0;
1185 }
1186 if (ext)
1187 {
1188 if (sz_ext <= wcslen(end)) goto do_error;
1189 wcscpy( ext, end );
1190 }
1191 return 0;
1192do_error:
1193 if (drive) drive[0] = '\0';
1194 if (dir) dir[0] = '\0';
1195 if (fname) fname[0]= '\0';
1196 if (ext) ext[0]= '\0';
1197 *_errno() = ERANGE;
1198 return ERANGE;
1199}
1200
1201/*********************************************************************
1202 * _wsplitpath (MSVCRT.@)
1203 *
1204 * Unicode version of _splitpath.
1205 */
1206void CDECL _wsplitpath(const wchar_t *inpath, wchar_t *drv, wchar_t *dir,
1207 wchar_t *fname, wchar_t *ext)
1208{
1209 _wsplitpath_s(inpath, drv, drv ? _MAX_DRIVE : 0, dir, dir ? _MAX_DIR : 0,
1210 fname, fname ? _MAX_FNAME : 0, ext, ext ? _MAX_EXT : 0);
1211}
1212
1213/*********************************************************************
1214 * _wfullpath (MSVCRT.@)
1215 *
1216 * Unicode version of _fullpath.
1217 */
1218wchar_t * CDECL _wfullpath(wchar_t * absPath, const wchar_t* relPath, size_t size)
1219{
1220 DWORD rc;
1221 WCHAR* buffer;
1222 WCHAR* lastpart;
1223 BOOL alloced = FALSE;
1224
1225 if (!relPath || !*relPath)
1226 return _wgetcwd(absPath, size);
1227
1228 if (absPath == NULL)
1229 {
1230 buffer = malloc(MAX_PATH * sizeof(WCHAR));
1231 size = MAX_PATH;
1232 alloced = TRUE;
1233 }
1234 else
1235 buffer = absPath;
1236
1237 if (size < 4)
1238 {
1239 *_errno() = ERANGE;
1240 return NULL;
1241 }
1242
1243 TRACE(":resolving relative path %s\n",debugstr_w(relPath));
1244
1245 rc = GetFullPathNameW(relPath,size,buffer,&lastpart);
1246
1247 if (rc > 0 && rc <= size )
1248 return buffer;
1249 else
1250 {
1251 if (alloced)
1252 free(buffer);
1253 return NULL;
1254 }
1255}
1256
1257/*********************************************************************
1258 * _fullpath (MSVCRT.@)
1259 *
1260 * Create an absolute path from a relative path.
1261 *
1262 * PARAMS
1263 * absPath [O] Destination for absolute path
1264 * relPath [I] Relative path to convert to absolute
1265 * size [I] Length of absPath in characters.
1266 *
1267 * RETURNS
1268 * Success: If absPath is NULL, returns an allocated string containing the path.
1269 * Otherwise populates absPath with the path and returns it.
1270 * Failure: NULL. errno indicates the error.
1271 */
1272char * CDECL _fullpath(char *abs_path, const char *rel_path, size_t size)
1273{
1274 wchar_t abs_pathW[MAX_PATH], *rel_pathW = NULL, *retW;
1275 size_t len;
1276
1277 if (rel_path && !(rel_pathW = wstrdupa_utf8(rel_path))) return NULL;
1278 retW = _wfullpath(abs_pathW, rel_pathW, ARRAY_SIZE(abs_pathW));
1279 free(rel_pathW);
1280 if (!retW) return NULL;
1281
1282 if (!abs_path) return astrdupw_utf8(abs_pathW);
1283 len = convert_wcs_to_acp_utf8(abs_pathW, NULL, 0);
1284 if (!len) return NULL;
1285 if (len > size)
1286 {
1287 *_errno() = ERANGE;
1288 return NULL;
1289 }
1290 convert_wcs_to_acp_utf8(abs_pathW, abs_path, size);
1291 return abs_path;
1292}
1293
1294/*********************************************************************
1295 * _makepath (MSVCRT.@)
1296 *
1297 * Create a pathname.
1298 *
1299 * PARAMS
1300 * path [O] Destination for created pathname
1301 * drive [I] Drive letter (e.g. "A:")
1302 * directory [I] Directory
1303 * filename [I] Name of the file, excluding extension
1304 * extension [I] File extension (e.g. ".TXT")
1305 *
1306 * RETURNS
1307 * Nothing. If path is not large enough to hold the resulting pathname,
1308 * random process memory will be overwritten.
1309 */
1310VOID CDECL _makepath(char * path, const char * drive,
1311 const char *directory, const char * filename,
1312 const char * extension)
1313{
1314 char *p = path;
1315
1316 TRACE("(%s %s %s %s)\n", debugstr_a(drive), debugstr_a(directory),
1317 debugstr_a(filename), debugstr_a(extension) );
1318
1319 if ( !path )
1320 return;
1321
1322 if (drive && drive[0])
1323 {
1324 *p++ = drive[0];
1325 *p++ = ':';
1326 }
1327 if (directory && directory[0])
1328 {
1329 unsigned int len = strlen(directory);
1331 p += len;
1332 if (p[-1] != '/' && p[-1] != '\\')
1333 *p++ = '\\';
1334 }
1335 if (filename && filename[0])
1336 {
1337 unsigned int len = strlen(filename);
1338 memmove(p, filename, len);
1339 p += len;
1340 }
1341 if (extension && extension[0])
1342 {
1343 if (extension[0] != '.')
1344 *p++ = '.';
1345 strcpy(p, extension);
1346 }
1347 else
1348 *p = '\0';
1349 TRACE("returning %s\n",path);
1350}
1351
1352/*********************************************************************
1353 * _wmakepath (MSVCRT.@)
1354 *
1355 * Unicode version of _wmakepath.
1356 */
1357VOID CDECL _wmakepath(wchar_t *path, const wchar_t *drive, const wchar_t *directory,
1358 const wchar_t *filename, const wchar_t *extension)
1359{
1360 wchar_t *p = path;
1361
1362 TRACE("%s %s %s %s\n", debugstr_w(drive), debugstr_w(directory),
1363 debugstr_w(filename), debugstr_w(extension));
1364
1365 if ( !path )
1366 return;
1367
1368 if (drive && drive[0])
1369 {
1370 *p++ = drive[0];
1371 *p++ = ':';
1372 }
1373 if (directory && directory[0])
1374 {
1375 unsigned int len = wcslen(directory);
1376 memmove(p, directory, len * sizeof(wchar_t));
1377 p += len;
1378 if (p[-1] != '/' && p[-1] != '\\')
1379 *p++ = '\\';
1380 }
1381 if (filename && filename[0])
1382 {
1383 unsigned int len = wcslen(filename);
1384 memmove(p, filename, len * sizeof(wchar_t));
1385 p += len;
1386 }
1387 if (extension && extension[0])
1388 {
1389 if (extension[0] != '.')
1390 *p++ = '.';
1391 wcscpy(p, extension);
1392 }
1393 else
1394 *p = '\0';
1395
1396 TRACE("returning %s\n", debugstr_w(path));
1397}
1398
1399/*********************************************************************
1400 * _makepath_s (MSVCRT.@)
1401 *
1402 * Safe version of _makepath.
1403 */
1404int CDECL _makepath_s(char *path, size_t size, const char *drive,
1405 const char *directory, const char *filename,
1406 const char *extension)
1407{
1408 char *p = path;
1409
1410 if (!path || !size)
1411 {
1412 *_errno() = EINVAL;
1413 return EINVAL;
1414 }
1415
1416 if (drive && drive[0])
1417 {
1418 if (size <= 2)
1419 goto range;
1420
1421 *p++ = drive[0];
1422 *p++ = ':';
1423 size -= 2;
1424 }
1425
1426 if (directory && directory[0])
1427 {
1428 unsigned int len = strlen(directory);
1429 unsigned int needs_separator = directory[len - 1] != '/' && directory[len - 1] != '\\';
1430 unsigned int copylen = min(size - 1, len);
1431
1432 if (size < 2)
1433 goto range;
1434
1435 memmove(p, directory, copylen);
1436
1437 if (size <= len)
1438 goto range;
1439
1440 p += copylen;
1441 size -= copylen;
1442
1443 if (needs_separator)
1444 {
1445 if (size < 2)
1446 goto range;
1447
1448 *p++ = '\\';
1449 size -= 1;
1450 }
1451 }
1452
1453 if (filename && filename[0])
1454 {
1455 unsigned int len = strlen(filename);
1456 unsigned int copylen = min(size - 1, len);
1457
1458 if (size < 2)
1459 goto range;
1460
1461 memmove(p, filename, copylen);
1462
1463 if (size <= len)
1464 goto range;
1465
1466 p += len;
1467 size -= len;
1468 }
1469
1470 if (extension && extension[0])
1471 {
1472 unsigned int len = strlen(extension);
1473 unsigned int needs_period = extension[0] != '.';
1474 unsigned int copylen;
1475
1476 if (size < 2)
1477 goto range;
1478
1479 if (needs_period)
1480 {
1481 *p++ = '.';
1482 size -= 1;
1483 }
1484
1485 copylen = min(size - 1, len);
1486 memcpy(p, extension, copylen);
1487
1488 if (size <= len)
1489 goto range;
1490
1491 p += copylen;
1492 }
1493
1494 *p = '\0';
1495 return 0;
1496
1497range:
1498 path[0] = '\0';
1499 *_errno() = ERANGE;
1500 return ERANGE;
1501}
1502
1503/*********************************************************************
1504 * _wmakepath_s (MSVCRT.@)
1505 *
1506 * Safe version of _wmakepath.
1507 */
1508int CDECL _wmakepath_s(wchar_t *path, size_t size, const wchar_t *drive,
1509 const wchar_t *directory, const wchar_t *filename,
1510 const wchar_t *extension)
1511{
1512 wchar_t *p = path;
1513
1514 if (!path || !size)
1515 {
1516 *_errno() = EINVAL;
1517 return EINVAL;
1518 }
1519
1520 if (drive && drive[0])
1521 {
1522 if (size <= 2)
1523 goto range;
1524
1525 *p++ = drive[0];
1526 *p++ = ':';
1527 size -= 2;
1528 }
1529
1530 if (directory && directory[0])
1531 {
1532 unsigned int len = wcslen(directory);
1533 unsigned int needs_separator = directory[len - 1] != '/' && directory[len - 1] != '\\';
1534 unsigned int copylen = min(size - 1, len);
1535
1536 if (size < 2)
1537 goto range;
1538
1539 memmove(p, directory, copylen * sizeof(wchar_t));
1540
1541 if (size <= len)
1542 goto range;
1543
1544 p += copylen;
1545 size -= copylen;
1546
1547 if (needs_separator)
1548 {
1549 if (size < 2)
1550 goto range;
1551
1552 *p++ = '\\';
1553 size -= 1;
1554 }
1555 }
1556
1557 if (filename && filename[0])
1558 {
1559 unsigned int len = wcslen(filename);
1560 unsigned int copylen = min(size - 1, len);
1561
1562 if (size < 2)
1563 goto range;
1564
1565 memmove(p, filename, copylen * sizeof(wchar_t));
1566
1567 if (size <= len)
1568 goto range;
1569
1570 p += len;
1571 size -= len;
1572 }
1573
1574 if (extension && extension[0])
1575 {
1576 unsigned int len = wcslen(extension);
1577 unsigned int needs_period = extension[0] != '.';
1578 unsigned int copylen;
1579
1580 if (size < 2)
1581 goto range;
1582
1583 if (needs_period)
1584 {
1585 *p++ = '.';
1586 size -= 1;
1587 }
1588
1589 copylen = min(size - 1, len);
1590 memcpy(p, extension, copylen * sizeof(wchar_t));
1591
1592 if (size <= len)
1593 goto range;
1594
1595 p += copylen;
1596 }
1597
1598 *p = '\0';
1599 return 0;
1600
1601range:
1602 path[0] = '\0';
1603 *_errno() = ERANGE;
1604 return ERANGE;
1605}
1606
1607/*********************************************************************
1608 * _searchenv_s (MSVCRT.@)
1609 */
1610int CDECL _searchenv_s(const char* file, const char* env, char *buf, size_t count)
1611{
1612 char *envVal, *penv, *end;
1613 char path[MAX_PATH];
1614 size_t path_len, fname_len;
1615 int old_errno, access;
1616
1617 if (!MSVCRT_CHECK_PMT(file != NULL)) return EINVAL;
1618 if (!MSVCRT_CHECK_PMT(buf != NULL)) return EINVAL;
1619 if (!MSVCRT_CHECK_PMT(count > 0)) return EINVAL;
1620
1621 if (count > MAX_PATH)
1622 FIXME("count > MAX_PATH not supported\n");
1623
1624 fname_len = strlen(file);
1625 *buf = '\0';
1626
1627 /* Try CWD first */
1628 old_errno = *_errno();
1629 access = _access(file, 0);
1630 *_errno() = old_errno;
1631 if (!access)
1632 {
1633 if (!_fullpath(buf, file, count))
1634 return *_errno();
1635 return 0;
1636 }
1637
1638 /* Search given environment variable */
1639 envVal = getenv(env);
1640 if (!envVal)
1641 {
1642 *_errno() = ENOENT;
1643 return ENOENT;
1644 }
1645
1646 penv = envVal;
1647 TRACE(":searching for %s in paths %s\n", file, envVal);
1648
1649 for(; *penv; penv = (*end ? end + 1 : end))
1650 {
1651 end = penv;
1652 path_len = 0;
1653 while(*end && *end != ';' && path_len < MAX_PATH)
1654 {
1655 if (*end == '"')
1656 {
1657 end++;
1658 while(*end && *end != '"' && path_len < MAX_PATH)
1659 {
1660 path[path_len++] = *end;
1661 end++;
1662 }
1663 if (*end == '"') end++;
1664 continue;
1665 }
1666
1667 path[path_len++] = *end;
1668 end++;
1669 }
1670 if (!path_len || path_len >= MAX_PATH)
1671 continue;
1672
1673 if (path[path_len - 1] != '/' && path[path_len - 1] != '\\')
1674 path[path_len++] = '\\';
1675 if (path_len + fname_len >= MAX_PATH)
1676 continue;
1677
1678 memcpy(path + path_len, file, fname_len + 1);
1679 TRACE("Checking for file %s\n", path);
1680 old_errno = *_errno();
1681 access = _access(path, 0);
1682 *_errno() = old_errno;
1683 if (!access)
1684 {
1685 if (path_len + fname_len + 1 > count)
1686 {
1687 MSVCRT_INVALID_PMT("buf[count] is too small", ERANGE);
1688 return ERANGE;
1689 }
1690 memcpy(buf, path, path_len + fname_len + 1);
1691 return 0;
1692 }
1693 }
1694
1695 *_errno() = ENOENT;
1696 return ENOENT;
1697}
1698
1699/*********************************************************************
1700 * _searchenv (MSVCRT.@)
1701 */
1702void CDECL _searchenv(const char* file, const char* env, char *buf)
1703{
1705}
1706
1707/*********************************************************************
1708 * _wsearchenv_s (MSVCRT.@)
1709 */
1710int CDECL _wsearchenv_s(const wchar_t* file, const wchar_t* env,
1711 wchar_t *buf, size_t count)
1712{
1713 wchar_t *envVal, *penv, *end;
1714 wchar_t path[MAX_PATH];
1715 size_t path_len, fname_len;
1716
1717 if (!MSVCRT_CHECK_PMT(file != NULL)) return EINVAL;
1718 if (!MSVCRT_CHECK_PMT(buf != NULL)) return EINVAL;
1719 if (!MSVCRT_CHECK_PMT(count > 0)) return EINVAL;
1720
1721 if (count > MAX_PATH)
1722 FIXME("count > MAX_PATH not supported\n");
1723
1724 fname_len = wcslen(file);
1725 *buf = '\0';
1726
1727 /* Try CWD first */
1729 {
1730 if (!_wfullpath(buf, file, count))
1731 return *_errno();
1732 return 0;
1733 }
1734
1735 /* Search given environment variable */
1736 envVal = _wgetenv(env);
1737 if (!envVal)
1738 {
1739 *_errno() = ENOENT;
1740 return ENOENT;
1741 }
1742
1743 penv = envVal;
1744 TRACE(":searching for %s in paths %s\n", debugstr_w(file), debugstr_w(envVal));
1745
1746 for(; *penv; penv = (*end ? end + 1 : end))
1747 {
1748 end = penv;
1749 path_len = 0;
1750 while(*end && *end != ';' && path_len < MAX_PATH)
1751 {
1752 if (*end == '"')
1753 {
1754 end++;
1755 while(*end && *end != '"' && path_len < MAX_PATH)
1756 {
1757 path[path_len++] = *end;
1758 end++;
1759 }
1760 if (*end == '"') end++;
1761 continue;
1762 }
1763
1764 path[path_len++] = *end;
1765 end++;
1766 }
1767 if (!path_len || path_len >= MAX_PATH)
1768 continue;
1769
1770 if (path[path_len - 1] != '/' && path[path_len - 1] != '\\')
1771 path[path_len++] = '\\';
1772 if (path_len + fname_len >= MAX_PATH)
1773 continue;
1774
1775 memcpy(path + path_len, file, (fname_len + 1) * sizeof(wchar_t));
1776 TRACE("Checking for file %s\n", debugstr_w(path));
1778 {
1779 if (path_len + fname_len + 1 > count)
1780 {
1781 MSVCRT_INVALID_PMT("buf[count] is too small", ERANGE);
1782 return ERANGE;
1783 }
1784 memcpy(buf, path, (path_len + fname_len + 1) * sizeof(wchar_t));
1785 return 0;
1786 }
1787 }
1788
1789 *_errno() = ENOENT;
1790 return ENOENT;
1791}
1792
1793/*********************************************************************
1794 * _wsearchenv (MSVCRT.@)
1795 */
1796void CDECL _wsearchenv(const wchar_t* file, const wchar_t* env, wchar_t *buf)
1797{
1799}
unsigned int dir
Definition: maze.c:112
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:171
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
static int find_data(const struct Vector *v, const BYTE *pData, int size)
Definition: filtermapper.c:162
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define CDECL
Definition: compat.h:29
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
static const WCHAR *const ext[]
Definition: module.c:53
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableW(IN LPCWSTR lpName, IN LPCWSTR lpValue)
Definition: environ.c:259
BOOL WINAPI CreateDirectoryW(IN LPCWSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:90
BOOL WINAPI RemoveDirectoryW(IN LPCWSTR lpPathName)
Definition: dir.c:732
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
BOOL WINAPI GetDiskFreeSpaceW(IN LPCWSTR lpRootPathName, OUT LPDWORD lpSectorsPerCluster, OUT LPDWORD lpBytesPerSector, OUT LPDWORD lpNumberOfFreeClusters, OUT LPDWORD lpTotalNumberOfClusters)
Definition: disk.c:173
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
HANDLE WINAPI FindFirstFileA(IN LPCSTR lpFileName, OUT LPWIN32_FIND_DATAA lpFindFileData)
Definition: find.c:263
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
BOOL WINAPI FindNextFileA(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAA lpFindFileData)
Definition: find.c:336
BOOL WINAPI SetCurrentDirectoryW(IN LPCWSTR lpPathName)
Definition: path.c:2249
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
char *CDECL _getdcwd(int drive, char *buf, int size)
Definition: dir.c:843
static void msvcrt_wfttofd(const WIN32_FIND_DATAW *fd, struct _wfinddata_t *ft)
Definition: dir.c:81
static void msvcrt_fttofd(const WIN32_FIND_DATAA *fd, struct _finddata_t *ft)
Definition: dir.c:61
wchar_t *CDECL _wgetdcwd(int drive, wchar_t *buf, int size)
Definition: dir.c:867
char *CDECL _getcwd(char *buf, int size)
Definition: dir.c:761
static int finddata64_wtoa(const struct _wfinddata64_t *wfd, struct _finddata64_t *fd)
Definition: dir.c:456
static void msvcrt_wfttofd32(const WIN32_FIND_DATAW *fd, struct _wfinddata32_t *ft)
Definition: dir.c:101
int CDECL _wsearchenv_s(const wchar_t *file, const wchar_t *env, wchar_t *buf, size_t count)
Definition: dir.c:1710
void CDECL _wsearchenv(const wchar_t *file, const wchar_t *env, wchar_t *buf)
Definition: dir.c:1796
static void msvcrt_wfttofdi64(const WIN32_FIND_DATAW *fd, struct _wfinddatai64_t *ft)
Definition: dir.c:161
int CDECL _searchenv_s(const char *file, const char *env, char *buf, size_t count)
Definition: dir.c:1610
void CDECL _searchenv(const char *file, const char *env, char *buf)
Definition: dir.c:1702
static void msvcrt_fttofdi64(const WIN32_FIND_DATAA *fd, struct _finddatai64_t *ft)
Definition: dir.c:121
static void msvcrt_wfttofd64i32(const WIN32_FIND_DATAW *fd, struct _wfinddata64i32_t *ft)
Definition: dir.c:181
int CDECL _wrmdir(const wchar_t *dir)
Definition: dir.c:1013
int CDECL _wfindnext32(intptr_t hand, struct _wfinddata32_t *ft)
Definition: dir.c:595
int CDECL _rmdir(const char *dir)
Definition: dir.c:997
char *CDECL _fullpath(char *abs_path, const char *rel_path, size_t size)
Definition: dir.c:1272
int CDECL _wchdir(const wchar_t *newdir)
Definition: dir.c:231
int CDECL _getdrive(void)
Definition: dir.c:819
int CDECL _chdir(const char *newdir)
Definition: dir.c:215
void CDECL _wsplitpath(const wchar_t *inpath, wchar_t *drv, wchar_t *dir, wchar_t *fname, wchar_t *ext)
Definition: dir.c:1206
int CDECL _mkdir(const char *newdir)
Definition: dir.c:958
int CDECL _chdrive(int newdrive)
Definition: dir.c:268
int CDECL _makepath_s(char *path, size_t size, const char *drive, const char *directory, const char *filename, const char *extension)
Definition: dir.c:1404
unsigned int CDECL _getdiskfree(unsigned int disk, struct _diskfree_t *d)
Definition: dir.c:919
wchar_t *CDECL _wgetcwd(wchar_t *buf, int size)
Definition: dir.c:785
intptr_t CDECL _findfirst32(const char *fspec, struct _finddata32_t *ft)
Definition: dir.c:397
int CDECL _wmakepath_s(wchar_t *path, size_t size, const wchar_t *drive, const wchar_t *directory, const wchar_t *filename, const wchar_t *extension)
Definition: dir.c:1508
wchar_t *CDECL _wfullpath(wchar_t *absPath, const wchar_t *relPath, size_t size)
Definition: dir.c:1218
static int finddata32_wtoa(const struct _wfinddata32_t *wfd, struct _finddata32_t *fd)
Definition: dir.c:384
static int finddata64i32_wtoa(const struct _wfinddata64i32_t *wfd, struct _finddata64i32_t *fd)
Definition: dir.c:509
static void msvcrt_wfttofd64(const WIN32_FIND_DATAW *fd, struct _wfinddata64_t *ft)
Definition: dir.c:141
int CDECL _wmkdir(const wchar_t *newdir)
Definition: dir.c:974
int CDECL _findnext32(intptr_t hand, struct _finddata32_t *ft)
Definition: dir.c:612
void CDECL _splitpath(const char *inpath, char *drv, char *dir, char *fname, char *ext)
Definition: dir.c:1112
intptr_t CDECL _wfindfirst32(const wchar_t *fspec, struct _wfinddata32_t *ft)
Definition: dir.c:368
int CDECL _findclose(intptr_t hand)
Definition: dir.c:298
VOID CDECL _wmakepath(wchar_t *path, const wchar_t *drive, const wchar_t *directory, const wchar_t *filename, const wchar_t *extension)
Definition: dir.c:1357
wchar_t *CDECL _wgetenv(const wchar_t *name)
Definition: environ.c:254
char *CDECL getenv(const char *name)
Definition: environ.c:227
int *CDECL _errno(void)
Definition: errno.c:215
int CDECL _access(const char *filename, int mode)
Definition: file.c:990
int errno_t
Definition: corecrt.h:249
int intptr_t
Definition: corecrt.h:176
#define __int64
Definition: corecrt.h:72
#define _findnext64
Definition: corecrt_io.h:88
#define _findfirst64
Definition: corecrt_io.h:86
#define _findnext64i32
Definition: corecrt_io.h:87
#define _finddatai64_t
Definition: corecrt_io.h:18
#define _findfirst64i32
Definition: corecrt_io.h:85
#define _wfindnext64i32
Definition: corecrt_wio.h:80
#define _wfindfirst64i32
Definition: corecrt_wio.h:78
#define _wfinddatai64_t
Definition: corecrt_wio.h:20
#define _wfindnext64
Definition: corecrt_wio.h:81
#define _wfindfirst64
Definition: corecrt_wio.h:79
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
_ACRTIMP wchar_t *__cdecl _wcsdup(const wchar_t *) __WINE_DEALLOC(free) __WINE_MALLOC
Definition: wcs.c:81
#define ENOENT
Definition: errno.h:25
#define EINVAL
Definition: errno.h:44
#define ERANGE
Definition: errno.h:55
#define EACCES
Definition: errno.h:36
_ACRTIMP int __cdecl _ismbblead(unsigned int)
Definition: mbcs.c:2077
#define _MAX_FNAME
Definition: stdlib.h:38
#define _MAX_DIR
Definition: stdlib.h:39
#define _MAX_DRIVE
Definition: stdlib.h:37
#define _MAX_EXT
Definition: stdlib.h:40
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
static wchar_t * wstrdupa_utf8(const char *str)
Definition: msvcrt.h:440
static char * astrdupw_utf8(const wchar_t *wstr)
Definition: msvcrt.h:452
static int convert_wcs_to_acp_utf8(const wchar_t *wstr, char *str, int len)
Definition: msvcrt.h:435
#define MSVCRT_INVALID_PMT(x, err)
Definition: msvcrt.h:376
#define MSVCRT_CHECK_PMT(x)
Definition: msvcrt.h:378
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint end
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLenum GLint * range
Definition: glext.h:7539
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
BOOLEAN NTAPI RtlTimeToSecondsSince1970(PLARGE_INTEGER Time, PULONG ElapsedSeconds)
REFIID LPVOID DWORD_PTR dw
Definition: atlbase.h:40
const char * filename
Definition: ioapi.h:137
#define d
Definition: ke_i.h:81
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define _wsplitpath_s(f, d, dl, p, pl, n, nl, e, el)
Definition: utility.h:211
#define _splitpath_s(f, d, dl, p, pl, n, nl, e, el)
Definition: utility.h:212
static DWORD path_len
Definition: batch.c:31
#define min(a, b)
Definition: monoChain.cc:55
#define err(...)
#define _findfirsti64
Definition: corecrt_io.h:103
#define _findnexti64
Definition: corecrt_io.h:104
#define _findfirst
Definition: corecrt_io.h:101
#define _findnext
Definition: corecrt_io.h:102
#define _wfindnexti64
Definition: corecrt_wio.h:91
#define _wfindfirst
Definition: corecrt_wio.h:88
#define _wfindnext
Definition: corecrt_wio.h:89
#define _wfindfirsti64
Definition: corecrt_wio.h:90
wcscpy
_makepath
Definition: stdlib.h:1096
strcpy
Definition: string.h:131
#define msvcrt_set_errno
Definition: heap.c:50
static int fd
Definition: io.c:51
#define towupper(c)
Definition: wctype.h:99
#define TRACE(s)
Definition: solgame.cpp:4
Definition: io.h:37
time_t time_access
Definition: io.h:40
time_t time_write
Definition: io.h:41
unsigned attrib
Definition: io.h:38
time_t time_create
Definition: io.h:39
_fsize_t size
Definition: io.h:42
char name[260]
Definition: io.h:43
__time32_t time_access
Definition: corecrt_wio.h:26
__time32_t time_write
Definition: corecrt_wio.h:27
unsigned attrib
Definition: corecrt_wio.h:24
__time32_t time_create
Definition: corecrt_wio.h:25
wchar_t name[260]
Definition: corecrt_wio.h:29
_fsize_t size
Definition: corecrt_wio.h:28
wchar_t name[260]
Definition: corecrt_wio.h:56
__time64_t time_create
Definition: corecrt_wio.h:52
unsigned attrib
Definition: corecrt_wio.h:51
__int64 size
Definition: corecrt_wio.h:71
__time64_t time_access
Definition: corecrt_wio.h:53
__time64_t time_write
Definition: corecrt_wio.h:54
__time64_t time_access
Definition: corecrt_wio.h:44
wchar_t name[260]
Definition: corecrt_wio.h:47
__time64_t time_create
Definition: corecrt_wio.h:43
__time64_t time_write
Definition: corecrt_wio.h:45
time_t time_access
Definition: io.h:102
_fsize_t size
Definition: io.h:104
time_t time_create
Definition: io.h:101
time_t time_write
Definition: io.h:103
unsigned attrib
Definition: io.h:100
wchar_t name[260]
Definition: io.h:105
Definition: fci.c:127
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define DRIVE_REMOVABLE
Definition: winbase.h:275
__wchar_t WCHAR
Definition: xmlstorage.h:180