source: trunk/src/msvcrt/dir.c@ 9633

Last change on this file since 9633 was 9633, checked in by sandervl, 23 years ago

PF: Msvcrt Wine port with GCC

File size: 18.4 KB
Line 
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23#ifdef __WIN32OS2__
24#include <emxheader.h>
25#include <winbase.h>
26#else
27#include "config.h"
28#endif
29
30#include "wine/port.h"
31
32#include <time.h>
33#include "winternl.h"
34#include "wine/unicode.h"
35#include "msvcrt.h"
36#include "msvcrt/errno.h"
37
38#include "wine/unicode.h"
39#include "msvcrt/direct.h"
40#include "msvcrt/dos.h"
41#include "msvcrt/io.h"
42#include "msvcrt/stdlib.h"
43#include "msvcrt/string.h"
44
45#include "wine/debug.h"
46
47WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
48
49/* INTERNAL: Translate finddata_t to PWIN32_FIND_DATAA */
50static void msvcrt_fttofd(LPWIN32_FIND_DATAA fd, struct _finddata_t* ft)
51{
52 DWORD dw;
53
54 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
55 ft->attrib = 0;
56 else
57 ft->attrib = fd->dwFileAttributes;
58
59 RtlTimeToSecondsSince1970( (LARGE_INTEGER *)&fd->ftCreationTime, &dw );
60 ft->time_create = dw;
61 RtlTimeToSecondsSince1970( (LARGE_INTEGER *)&fd->ftLastAccessTime, &dw );
62 ft->time_access = dw;
63 RtlTimeToSecondsSince1970( (LARGE_INTEGER *)&fd->ftLastWriteTime, &dw );
64 ft->time_write = dw;
65 ft->size = fd->nFileSizeLow;
66 strcpy(ft->name, fd->cFileName);
67}
68
69/* INTERNAL: Translate wfinddata_t to PWIN32_FIND_DATAA */
70static void msvcrt_wfttofd(LPWIN32_FIND_DATAW fd, struct _wfinddata_t* ft)
71{
72 DWORD dw;
73
74 if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL)
75 ft->attrib = 0;
76 else
77 ft->attrib = fd->dwFileAttributes;
78
79 RtlTimeToSecondsSince1970( (LARGE_INTEGER *)&fd->ftCreationTime, &dw );
80 ft->time_create = dw;
81 RtlTimeToSecondsSince1970( (LARGE_INTEGER *)&fd->ftLastAccessTime, &dw );
82 ft->time_access = dw;
83 RtlTimeToSecondsSince1970( (LARGE_INTEGER *)&fd->ftLastWriteTime, &dw );
84 ft->time_write = dw;
85 ft->size = fd->nFileSizeLow;
86 strcpyW(ft->name, fd->cFileName);
87}
88
89/*********************************************************************
90 * _chdir (MSVCRT.@)
91 */
92int _chdir(const char * newdir)
93{
94 if (!SetCurrentDirectoryA(newdir))
95 {
96 MSVCRT__set_errno(newdir?GetLastError():0);
97 return -1;
98 }
99 return 0;
100}
101
102/*********************************************************************
103 * _wchdir (MSVCRT.@)
104 */
105int _wchdir(const MSVCRT_wchar_t * newdir)
106{
107 if (!SetCurrentDirectoryW(newdir))
108 {
109 MSVCRT__set_errno(newdir?GetLastError():0);
110 return -1;
111 }
112 return 0;
113}
114
115/*********************************************************************
116 * _chdrive (MSVCRT.@)
117 */
118int _chdrive(int newdrive)
119{
120 char buffer[3] = "A:";
121 buffer[0] += newdrive - 1;
122 if (!SetCurrentDirectoryA( buffer ))
123 {
124 MSVCRT__set_errno(GetLastError());
125 if (newdrive <= 0)
126 *MSVCRT__errno() = MSVCRT_EACCES;
127 return -1;
128 }
129 return 0;
130}
131
132/*********************************************************************
133 * _findclose (MSVCRT.@)
134 */
135int _findclose(long hand)
136{
137 TRACE(":handle %ld\n",hand);
138 if (!FindClose((HANDLE)hand))
139 {
140 MSVCRT__set_errno(GetLastError());
141 return -1;
142 }
143 return 0;
144}
145
146/*********************************************************************
147 * _findfirst (MSVCRT.@)
148 */
149long _findfirst(const char * fspec, struct _finddata_t* ft)
150{
151 WIN32_FIND_DATAA find_data;
152 HANDLE hfind;
153
154 hfind = FindFirstFileA(fspec, &find_data);
155 if (hfind == INVALID_HANDLE_VALUE)
156 {
157 MSVCRT__set_errno(GetLastError());
158 return -1;
159 }
160 msvcrt_fttofd(&find_data,ft);
161 TRACE(":got handle %p\n",hfind);
162 return (long)hfind;
163}
164
165/*********************************************************************
166 * _wfindfirst (MSVCRT.@)
167 */
168long _wfindfirst(const MSVCRT_wchar_t * fspec, struct _wfinddata_t* ft)
169{
170 WIN32_FIND_DATAW find_data;
171 HANDLE hfind;
172
173 hfind = FindFirstFileW(fspec, &find_data);
174 if (hfind == INVALID_HANDLE_VALUE)
175 {
176 MSVCRT__set_errno(GetLastError());
177 return -1;
178 }
179 msvcrt_wfttofd(&find_data,ft);
180 TRACE(":got handle %p\n",hfind);
181 return (long)hfind;
182}
183
184/*********************************************************************
185 * _findnext (MSVCRT.@)
186 */
187int _findnext(long hand, struct _finddata_t * ft)
188{
189 WIN32_FIND_DATAA find_data;
190
191 if (!FindNextFileA((HANDLE)hand, &find_data))
192 {
193 *MSVCRT__errno() = MSVCRT_ENOENT;
194 return -1;
195 }
196
197 msvcrt_fttofd(&find_data,ft);
198 return 0;
199}
200
201/*********************************************************************
202 * _wfindnext (MSVCRT.@)
203 */
204int _wfindnext(long hand, struct _wfinddata_t * ft)
205{
206 WIN32_FIND_DATAW find_data;
207
208 if (!FindNextFileW((HANDLE)hand, &find_data))
209 {
210 *MSVCRT__errno() = MSVCRT_ENOENT;
211 return -1;
212 }
213
214 msvcrt_wfttofd(&find_data,ft);
215 return 0;
216}
217
218/*********************************************************************
219 * _getcwd (MSVCRT.@)
220 */
221char* _getcwd(char * buf, int size)
222{
223 char dir[MAX_PATH];
224 int dir_len = GetCurrentDirectoryA(MAX_PATH,dir);
225
226 if (dir_len < 1)
227 return NULL; /* FIXME: Real return value untested */
228
229 if (!buf)
230 {
231 if (size < 0)
232 return _strdup(dir);
233 return msvcrt_strndup(dir,size);
234 }
235 if (dir_len >= size)
236 {
237 *MSVCRT__errno() = MSVCRT_ERANGE;
238 return NULL; /* buf too small */
239 }
240 strcpy(buf,dir);
241 return buf;
242}
243
244/*********************************************************************
245 * _wgetcwd (MSVCRT.@)
246 */
247MSVCRT_wchar_t* _wgetcwd(MSVCRT_wchar_t * buf, int size)
248{
249 MSVCRT_wchar_t dir[MAX_PATH];
250 int dir_len = GetCurrentDirectoryW(MAX_PATH,dir);
251
252 if (dir_len < 1)
253 return NULL; /* FIXME: Real return value untested */
254
255 if (!buf)
256 {
257 if (size < 0)
258 return _wcsdup(dir);
259 return msvcrt_wstrndup(dir,size);
260 }
261 if (dir_len >= size)
262 {
263 *MSVCRT__errno() = MSVCRT_ERANGE;
264 return NULL; /* buf too small */
265 }
266 strcpyW(buf,dir);
267 return buf;
268}
269
270/*********************************************************************
271 * _getdrive (MSVCRT.@)
272 */
273int _getdrive(void)
274{
275 char buffer[MAX_PATH];
276 if (!GetCurrentDirectoryA( sizeof(buffer), buffer )) return 0;
277 if (buffer[1] != ':') return 0;
278 return toupper(buffer[0]) - 'A' + 1;
279}
280
281/*********************************************************************
282 * _getdcwd (MSVCRT.@)
283 */
284char* _getdcwd(int drive, char * buf, int size)
285{
286 static char* dummy;
287
288 TRACE(":drive %d(%c), size %d\n",drive, drive + 'A' - 1, size);
289
290 if (!drive || drive == _getdrive())
291 return _getcwd(buf,size); /* current */
292 else
293 {
294 char dir[MAX_PATH];
295 char drivespec[4] = {'A', ':', '\\', 0};
296 int dir_len;
297
298 drivespec[0] += drive - 1;
299 if (GetDriveTypeA(drivespec) < DRIVE_REMOVABLE)
300 {
301 *MSVCRT__errno() = MSVCRT_EACCES;
302 return NULL;
303 }
304
305 dir_len = GetFullPathNameA(drivespec,MAX_PATH,dir,&dummy);
306 if (dir_len >= size || dir_len < 1)
307 {
308 *MSVCRT__errno() = MSVCRT_ERANGE;
309 return NULL; /* buf too small */
310 }
311
312 TRACE(":returning '%s'\n", dir);
313 if (!buf)
314 return _strdup(dir); /* allocate */
315
316 strcpy(buf,dir);
317 }
318 return buf;
319}
320
321/*********************************************************************
322 * _wgetdcwd (MSVCRT.@)
323 */
324MSVCRT_wchar_t* _wgetdcwd(int drive, MSVCRT_wchar_t * buf, int size)
325{
326 static MSVCRT_wchar_t* dummy;
327
328 TRACE(":drive %d(%c), size %d\n",drive, drive + 'A' - 1, size);
329
330 if (!drive || drive == _getdrive())
331 return _wgetcwd(buf,size); /* current */
332 else
333 {
334 MSVCRT_wchar_t dir[MAX_PATH];
335 MSVCRT_wchar_t drivespec[4] = {'A', ':', '\\', 0};
336 int dir_len;
337
338 drivespec[0] += drive - 1;
339 if (GetDriveTypeW(drivespec) < DRIVE_REMOVABLE)
340 {
341 *MSVCRT__errno() = MSVCRT_EACCES;
342 return NULL;
343 }
344
345 dir_len = GetFullPathNameW(drivespec,MAX_PATH,dir,&dummy);
346 if (dir_len >= size || dir_len < 1)
347 {
348 *MSVCRT__errno() = MSVCRT_ERANGE;
349 return NULL; /* buf too small */
350 }
351
352 TRACE(":returning %s\n", debugstr_w(dir));
353 if (!buf)
354 return _wcsdup(dir); /* allocate */
355 strcpyW(buf,dir);
356 }
357 return buf;
358}
359
360/*********************************************************************
361 * _getdiskfree (MSVCRT.@)
362 */
363unsigned int _getdiskfree(unsigned int disk, struct _diskfree_t* d)
364{
365 char drivespec[4] = {'@', ':', '\\', 0};
366 DWORD ret[4];
367 unsigned int err;
368
369 if (disk > 26)
370 return ERROR_INVALID_PARAMETER; /* MSVCRT doesn't set errno here */
371
372 drivespec[0] += disk; /* make a drive letter */
373
374 if (GetDiskFreeSpaceA(disk==0?NULL:drivespec,ret,ret+1,ret+2,ret+3))
375 {
376 d->sectors_per_cluster = (unsigned)ret[0];
377 d->bytes_per_sector = (unsigned)ret[1];
378 d->avail_clusters = (unsigned)ret[2];
379 d->total_clusters = (unsigned)ret[3];
380 return 0;
381 }
382 err = GetLastError();
383 MSVCRT__set_errno(err);
384 return err;
385}
386
387/*********************************************************************
388 * _mkdir (MSVCRT.@)
389 */
390int _mkdir(const char * newdir)
391{
392 if (CreateDirectoryA(newdir,NULL))
393 return 0;
394 MSVCRT__set_errno(GetLastError());
395 return -1;
396}
397
398/*********************************************************************
399 * _wmkdir (MSVCRT.@)
400 */
401int _wmkdir(const MSVCRT_wchar_t* newdir)
402{
403 if (CreateDirectoryW(newdir,NULL))
404 return 0;
405 MSVCRT__set_errno(GetLastError());
406 return -1;
407}
408
409/*********************************************************************
410 * _rmdir (MSVCRT.@)
411 */
412int _rmdir(const char * dir)
413{
414 if (RemoveDirectoryA(dir))
415 return 0;
416 MSVCRT__set_errno(GetLastError());
417 return -1;
418}
419
420/*********************************************************************
421 * _wrmdir (MSVCRT.@)
422 */
423int _wrmdir(const MSVCRT_wchar_t * dir)
424{
425 if (RemoveDirectoryW(dir))
426 return 0;
427 MSVCRT__set_errno(GetLastError());
428 return -1;
429}
430
431/*********************************************************************
432 * _wsplitpath (MSVCRT.@)
433 */
434void _wsplitpath(const MSVCRT_wchar_t *inpath, MSVCRT_wchar_t *drv, MSVCRT_wchar_t *dir,
435 MSVCRT_wchar_t *fname, MSVCRT_wchar_t *ext )
436{
437 /* Modified PD code from 'snippets' collection. */
438 MSVCRT_wchar_t ch, *ptr, *p;
439 MSVCRT_wchar_t pathbuff[MAX_PATH],*path=pathbuff;
440
441 TRACE(":splitting path %s\n",debugstr_w(path));
442 /* FIXME: Should be an strncpyW or something */
443 strcpyW(pathbuff, inpath);
444
445 /* convert slashes to backslashes for searching */
446 for (ptr = (MSVCRT_wchar_t*)path; *ptr; ++ptr)
447 if (*ptr == '/')
448 *ptr = '\\';
449
450 /* look for drive spec */
451 if ((ptr = strchrW(path, ':')) != 0)
452 {
453 ++ptr;
454 if (drv)
455 {
456 strncpyW(drv, path, ptr - path);
457 drv[ptr - path] = 0;
458 }
459 path = ptr;
460 }
461 else if (drv)
462 *drv = 0;
463
464 /* find rightmost backslash or leftmost colon */
465 if ((ptr = strrchrW(path, '\\')) == NULL)
466 ptr = (strchrW(path, ':'));
467
468 if (!ptr)
469 {
470 ptr = (MSVCRT_wchar_t *)path; /* no path */
471 if (dir)
472 *dir = 0;
473 }
474 else
475 {
476 ++ptr; /* skip the delimiter */
477 if (dir)
478 {
479 ch = *ptr;
480 *ptr = 0;
481 strcpyW(dir, path);
482 *ptr = ch;
483 }
484 }
485
486 if ((p = strrchrW(ptr, '.')) == NULL)
487 {
488 if (fname)
489 strcpyW(fname, ptr);
490 if (ext)
491 *ext = 0;
492 }
493 else
494 {
495 *p = 0;
496 if (fname)
497 strcpyW(fname, ptr);
498 *p = '.';
499 if (ext)
500 strcpyW(ext, p);
501 }
502
503 /* Fix pathological case - Win returns ':' as part of the
504 * directory when no drive letter is given.
505 */
506 if (drv && drv[0] == ':')
507 {
508 *drv = 0;
509 if (dir)
510 {
511 pathbuff[0] = ':';
512 pathbuff[1] = 0;
513 strcatW(pathbuff,dir);
514 strcpyW(dir, pathbuff);
515 }
516 }
517}
518
519/* INTERNAL: Helper for _fullpath. Modified PD code from 'snippets'. */
520static void msvcrt_fln_fix(char *path)
521{
522 int dir_flag = 0, root_flag = 0;
523 char *r, *p, *q, *s;
524
525 /* Skip drive */
526 if (NULL == (r = strrchr(path, ':')))
527 r = path;
528 else
529 ++r;
530
531 /* Ignore leading slashes */
532 while ('\\' == *r)
533 if ('\\' == r[1])
534 strcpy(r, &r[1]);
535 else
536 {
537 root_flag = 1;
538 ++r;
539 }
540
541 p = r; /* Change "\\" to "\" */
542 while (NULL != (p = strchr(p, '\\')))
543 if ('\\' == p[1])
544 strcpy(p, &p[1]);
545 else
546 ++p;
547
548 while ('.' == *r) /* Scrunch leading ".\" */
549 {
550 if ('.' == r[1])
551 {
552 /* Ignore leading ".." */
553 for (p = (r += 2); *p && (*p != '\\'); ++p)
554 ;
555 }
556 else
557 {
558 for (p = r + 1 ;*p && (*p != '\\'); ++p)
559 ;
560 }
561 strcpy(r, p + ((*p) ? 1 : 0));
562 }
563
564 while ('\\' == path[strlen(path)-1]) /* Strip last '\\' */
565 {
566 dir_flag = 1;
567 path[strlen(path)-1] = '\0';
568 }
569
570 s = r;
571
572 /* Look for "\." in path */
573
574 while (NULL != (p = strstr(s, "\\.")))
575 {
576 if ('.' == p[2])
577 {
578 /* Execute this section if ".." found */
579 q = p - 1;
580 while (q > r) /* Backup one level */
581 {
582 if (*q == '\\')
583 break;
584 --q;
585 }
586 if (q > r)
587 {
588 strcpy(q, p + 3);
589 s = q;
590 }
591 else if ('.' != *q)
592 {
593 strcpy(q + ((*q == '\\') ? 1 : 0),
594 p + 3 + ((*(p + 3)) ? 1 : 0));
595 s = q;
596 }
597 else s = ++p;
598 }
599 else
600 {
601 /* Execute this section if "." found */
602 q = p + 2;
603 for ( ;*q && (*q != '\\'); ++q)
604 ;
605 strcpy (p, q);
606 }
607 }
608
609 if (root_flag) /* Embedded ".." could have bubbled up to root */
610 {
611 for (p = r; *p && ('.' == *p || '\\' == *p); ++p)
612 ;
613 if (r != p)
614 strcpy(r, p);
615 }
616
617 if (dir_flag)
618 strcat(path, "\\");
619}
620
621/*********************************************************************
622 * _fullpath (MSVCRT.@)
623 */
624char *_fullpath(char * absPath, const char* relPath, unsigned int size)
625{
626 char drive[5],dir[MAX_PATH],file[MAX_PATH],ext[MAX_PATH];
627 char res[MAX_PATH];
628 size_t len;
629
630 res[0] = '\0';
631
632 if (!relPath || !*relPath)
633 return _getcwd(absPath, size);
634
635 if (size < 4)
636 {
637 *MSVCRT__errno() = MSVCRT_ERANGE;
638 return NULL;
639 }
640
641 TRACE(":resolving relative path '%s'\n",relPath);
642
643 _splitpath(relPath, drive, dir, file, ext);
644
645 /* Get Directory and drive into 'res' */
646 if (!dir[0] || (dir[0] != '/' && dir[0] != '\\'))
647 {
648 /* Relative or no directory given */
649 _getdcwd(drive[0] ? toupper(drive[0]) - 'A' + 1 : 0, res, MAX_PATH);
650 strcat(res,"\\");
651 if (dir[0])
652 strcat(res,dir);
653 if (drive[0])
654 res[0] = drive[0]; /* If given a drive, preserve the letter case */
655 }
656 else
657 {
658 strcpy(res,drive);
659 strcat(res,dir);
660 }
661
662 strcat(res,"\\");
663 strcat(res, file);
664 strcat(res, ext);
665 msvcrt_fln_fix(res);
666
667 len = strlen(res);
668 if (len >= MAX_PATH || len >= (size_t)size)
669 return NULL; /* FIXME: errno? */
670
671 if (!absPath)
672 return _strdup(res);
673 strcpy(absPath,res);
674 return absPath;
675}
676
677/*********************************************************************
678 * _makepath (MSVCRT.@)
679 */
680VOID _makepath(char * path, const char * drive,
681 const char *directory, const char * filename,
682 const char * extension )
683{
684 char ch;
685 TRACE("got %s %s %s %s\n", drive, directory,
686 filename, extension);
687
688 if ( !path )
689 return;
690
691 path[0] = 0;
692 if (drive && drive[0])
693 {
694 path[0] = drive[0];
695 path[1] = ':';
696 path[2] = 0;
697 }
698 if (directory && directory[0])
699 {
700 strcat(path, directory);
701 ch = path[strlen(path)-1];
702 if (ch != '/' && ch != '\\')
703 strcat(path,"\\");
704 }
705 if (filename && filename[0])
706 {
707 strcat(path, filename);
708 if (extension && extension[0])
709 {
710 if ( extension[0] != '.' )
711 strcat(path,".");
712 strcat(path,extension);
713 }
714 }
715
716 TRACE("returning %s\n",path);
717}
718
719/*********************************************************************
720 * _wmakepath (MSVCRT.@)
721 */
722VOID _wmakepath(MSVCRT_wchar_t *path, const MSVCRT_wchar_t *drive, const MSVCRT_wchar_t *directory,
723 const MSVCRT_wchar_t *filename, const MSVCRT_wchar_t *extension)
724{
725 MSVCRT_wchar_t ch;
726 TRACE("%s %s %s %s\n", debugstr_w(drive), debugstr_w(directory),
727 debugstr_w(filename), debugstr_w(extension));
728
729 if ( !path )
730 return;
731
732 path[0] = 0;
733 if (drive && drive[0])
734 {
735 path[0] = drive[0];
736 path[1] = ':';
737 path[2] = 0;
738 }
739 if (directory && directory[0])
740 {
741 strcatW(path, directory);
742 ch = path[strlenW(path) - 1];
743 if (ch != '/' && ch != '\\')
744 {
745 static const MSVCRT_wchar_t backslashW[] = {'\\',0};
746 strcatW(path, backslashW);
747 }
748 }
749 if (filename && filename[0])
750 {
751 strcatW(path, filename);
752 if (extension && extension[0])
753 {
754 if ( extension[0] != '.' )
755 {
756 static const MSVCRT_wchar_t dotW[] = {'.',0};
757 strcatW(path, dotW);
758 }
759 strcatW(path, extension);
760 }
761 }
762
763 TRACE("returning %s\n", debugstr_w(path));
764}
765
766/*********************************************************************
767 * _searchenv (MSVCRT.@)
768 */
769void _searchenv(const char* file, const char* env, char *buf)
770{
771 char*envVal, *penv;
772 char curPath[MAX_PATH];
773
774 *buf = '\0';
775
776 /* Try CWD first */
777 if (GetFileAttributesA( file ) != 0xFFFFFFFF)
778 {
779 GetFullPathNameA( file, MAX_PATH, buf, NULL );
780 /* Sigh. This error is *always* set, regardless of success */
781 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND);
782 return;
783 }
784
785 /* Search given environment variable */
786 envVal = MSVCRT_getenv(env);
787 if (!envVal)
788 {
789 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND);
790 return;
791 }
792
793 penv = envVal;
794 TRACE(":searching for %s in paths %s\n", file, envVal);
795
796 do
797 {
798 char *end = penv;
799
800 while(*end && *end != ';') end++; /* Find end of next path */
801 if (penv == end || !*penv)
802 {
803 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND);
804 return;
805 }
806 strncpy(curPath, penv, end - penv);
807 if (curPath[end - penv] != '/' || curPath[end - penv] != '\\')
808 {
809 curPath[end - penv] = '\\';
810 curPath[end - penv + 1] = '\0';
811 }
812 else
813 curPath[end - penv] = '\0';
814
815 strcat(curPath, file);
816 TRACE("Checking for file %s\n", curPath);
817 if (GetFileAttributesA( curPath ) != 0xFFFFFFFF)
818 {
819 strcpy(buf, curPath);
820 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND);
821 return; /* Found */
822 }
823 penv = *end ? end + 1 : end;
824 } while(1);
825}
Note: See TracBrowser for help on using the repository browser.