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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wine/port.h"
34 #include "wine/unicode.h"
36 #include "msvcrt/errno.h"
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"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
49 /* INTERNAL: Translate WIN32_FIND_DATAA to finddata_t */
50 static void msvcrt_fttofd( const WIN32_FIND_DATAA
*fd
, struct _finddata_t
* ft
)
54 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
57 ft
->attrib
= fd
->dwFileAttributes
;
59 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
61 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
63 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
65 ft
->size
= fd
->nFileSizeLow
;
66 strcpy(ft
->name
, fd
->cFileName
);
69 /* INTERNAL: Translate WIN32_FIND_DATAW to wfinddata_t */
70 static void msvcrt_wfttofd( const WIN32_FIND_DATAW
*fd
, struct _wfinddata_t
* ft
)
74 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
77 ft
->attrib
= fd
->dwFileAttributes
;
79 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
81 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
83 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
85 ft
->size
= fd
->nFileSizeLow
;
86 strcpyW(ft
->name
, fd
->cFileName
);
89 /* INTERNAL: Translate WIN32_FIND_DATAA to finddatai64_t */
90 static void msvcrt_fttofdi64( const WIN32_FIND_DATAA
*fd
, struct _finddatai64_t
* ft
)
94 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
97 ft
->attrib
= fd
->dwFileAttributes
;
99 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
100 ft
->time_create
= dw
;
101 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
102 ft
->time_access
= dw
;
103 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
105 ft
->size
= ((__int64
)fd
->nFileSizeHigh
) << 32 | fd
->nFileSizeLow
;
106 strcpy(ft
->name
, fd
->cFileName
);
109 /* INTERNAL: Translate WIN32_FIND_DATAW to wfinddatai64_t */
110 static void msvcrt_wfttofdi64( const WIN32_FIND_DATAW
*fd
, struct _wfinddatai64_t
* ft
)
114 if (fd
->dwFileAttributes
== FILE_ATTRIBUTE_NORMAL
)
117 ft
->attrib
= fd
->dwFileAttributes
;
119 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftCreationTime
, &dw
);
120 ft
->time_create
= dw
;
121 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftLastAccessTime
, &dw
);
122 ft
->time_access
= dw
;
123 RtlTimeToSecondsSince1970( (LARGE_INTEGER
*)&fd
->ftLastWriteTime
, &dw
);
125 ft
->size
= ((__int64
)fd
->nFileSizeHigh
) << 32 | fd
->nFileSizeLow
;
126 strcpyW(ft
->name
, fd
->cFileName
);
129 /*********************************************************************
132 int _chdir(const char * newdir
)
134 if (!SetCurrentDirectoryA(newdir
))
136 MSVCRT__set_errno(newdir
?GetLastError():0);
142 /*********************************************************************
145 int _wchdir(const MSVCRT_wchar_t
* newdir
)
147 if (!SetCurrentDirectoryW(newdir
))
149 MSVCRT__set_errno(newdir
?GetLastError():0);
155 /*********************************************************************
156 * _chdrive (MSVCRT.@)
158 int _chdrive(int newdrive
)
160 char buffer
[3] = "A:";
161 buffer
[0] += newdrive
- 1;
162 if (!SetCurrentDirectoryA( buffer
))
164 MSVCRT__set_errno(GetLastError());
166 *MSVCRT__errno() = MSVCRT_EACCES
;
172 /*********************************************************************
173 * _findclose (MSVCRT.@)
175 int _findclose(long hand
)
177 TRACE(":handle %ld\n",hand
);
178 if (!FindClose((HANDLE
)hand
))
180 MSVCRT__set_errno(GetLastError());
186 /*********************************************************************
187 * _findfirst (MSVCRT.@)
189 long _findfirst(const char * fspec
, struct _finddata_t
* ft
)
191 WIN32_FIND_DATAA find_data
;
194 hfind
= FindFirstFileA(fspec
, &find_data
);
195 if (hfind
== INVALID_HANDLE_VALUE
)
197 MSVCRT__set_errno(GetLastError());
200 msvcrt_fttofd(&find_data
,ft
);
201 TRACE(":got handle %p\n",hfind
);
205 /*********************************************************************
206 * _wfindfirst (MSVCRT.@)
208 long _wfindfirst(const MSVCRT_wchar_t
* fspec
, struct _wfinddata_t
* ft
)
210 WIN32_FIND_DATAW find_data
;
213 hfind
= FindFirstFileW(fspec
, &find_data
);
214 if (hfind
== INVALID_HANDLE_VALUE
)
216 MSVCRT__set_errno(GetLastError());
219 msvcrt_wfttofd(&find_data
,ft
);
220 TRACE(":got handle %p\n",hfind
);
224 /*********************************************************************
225 * _findfirsti64 (MSVCRT.@)
227 long _findfirsti64(const char * fspec
, struct _finddatai64_t
* ft
)
229 WIN32_FIND_DATAA find_data
;
232 hfind
= FindFirstFileA(fspec
, &find_data
);
233 if (hfind
== INVALID_HANDLE_VALUE
)
235 MSVCRT__set_errno(GetLastError());
238 msvcrt_fttofdi64(&find_data
,ft
);
239 TRACE(":got handle %p\n",hfind
);
243 /*********************************************************************
244 * _wfindfirsti64 (MSVCRT.@)
246 long _wfindfirsti64(const MSVCRT_wchar_t
* fspec
, struct _wfinddatai64_t
* ft
)
248 WIN32_FIND_DATAW find_data
;
251 hfind
= FindFirstFileW(fspec
, &find_data
);
252 if (hfind
== INVALID_HANDLE_VALUE
)
254 MSVCRT__set_errno(GetLastError());
257 msvcrt_wfttofdi64(&find_data
,ft
);
258 TRACE(":got handle %p\n",hfind
);
262 /*********************************************************************
263 * _findnext (MSVCRT.@)
265 int _findnext(long hand
, struct _finddata_t
* ft
)
267 WIN32_FIND_DATAA find_data
;
269 if (!FindNextFileA((HANDLE
)hand
, &find_data
))
271 *MSVCRT__errno() = MSVCRT_ENOENT
;
275 msvcrt_fttofd(&find_data
,ft
);
279 /*********************************************************************
280 * _wfindnext (MSVCRT.@)
282 int _wfindnext(long hand
, struct _wfinddata_t
* ft
)
284 WIN32_FIND_DATAW find_data
;
286 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
288 *MSVCRT__errno() = MSVCRT_ENOENT
;
292 msvcrt_wfttofd(&find_data
,ft
);
296 /*********************************************************************
297 * _findnexti64 (MSVCRT.@)
299 int _findnexti64(long hand
, struct _finddatai64_t
* ft
)
301 WIN32_FIND_DATAA find_data
;
303 if (!FindNextFileA((HANDLE
)hand
, &find_data
))
305 *MSVCRT__errno() = MSVCRT_ENOENT
;
309 msvcrt_fttofdi64(&find_data
,ft
);
313 /*********************************************************************
314 * _wfindnexti64 (MSVCRT.@)
316 int _wfindnexti64(long hand
, struct _wfinddatai64_t
* ft
)
318 WIN32_FIND_DATAW find_data
;
320 if (!FindNextFileW((HANDLE
)hand
, &find_data
))
322 *MSVCRT__errno() = MSVCRT_ENOENT
;
326 msvcrt_wfttofdi64(&find_data
,ft
);
330 /*********************************************************************
333 char* _getcwd(char * buf
, int size
)
336 int dir_len
= GetCurrentDirectoryA(MAX_PATH
,dir
);
339 return NULL
; /* FIXME: Real return value untested */
345 return msvcrt_strndup(dir
,size
);
349 *MSVCRT__errno() = MSVCRT_ERANGE
;
350 return NULL
; /* buf too small */
356 /*********************************************************************
357 * _wgetcwd (MSVCRT.@)
359 MSVCRT_wchar_t
* _wgetcwd(MSVCRT_wchar_t
* buf
, int size
)
361 MSVCRT_wchar_t dir
[MAX_PATH
];
362 int dir_len
= GetCurrentDirectoryW(MAX_PATH
,dir
);
365 return NULL
; /* FIXME: Real return value untested */
371 return msvcrt_wstrndup(dir
,size
);
375 *MSVCRT__errno() = MSVCRT_ERANGE
;
376 return NULL
; /* buf too small */
382 /*********************************************************************
383 * _getdrive (MSVCRT.@)
387 char buffer
[MAX_PATH
];
388 if (!GetCurrentDirectoryA( sizeof(buffer
), buffer
)) return 0;
389 if (buffer
[1] != ':') return 0;
390 return toupper(buffer
[0]) - 'A' + 1;
393 /*********************************************************************
394 * _getdcwd (MSVCRT.@)
396 char* _getdcwd(int drive
, char * buf
, int size
)
400 TRACE(":drive %d(%c), size %d\n",drive
, drive
+ 'A' - 1, size
);
402 if (!drive
|| drive
== _getdrive())
403 return _getcwd(buf
,size
); /* current */
407 char drivespec
[4] = {'A', ':', '\\', 0};
410 drivespec
[0] += drive
- 1;
411 if (GetDriveTypeA(drivespec
) < DRIVE_REMOVABLE
)
413 *MSVCRT__errno() = MSVCRT_EACCES
;
417 dir_len
= GetFullPathNameA(drivespec
,MAX_PATH
,dir
,&dummy
);
418 if (dir_len
>= size
|| dir_len
< 1)
420 *MSVCRT__errno() = MSVCRT_ERANGE
;
421 return NULL
; /* buf too small */
424 TRACE(":returning '%s'\n", dir
);
426 return _strdup(dir
); /* allocate */
433 /*********************************************************************
434 * _wgetdcwd (MSVCRT.@)
436 MSVCRT_wchar_t
* _wgetdcwd(int drive
, MSVCRT_wchar_t
* buf
, int size
)
438 static MSVCRT_wchar_t
* dummy
;
440 TRACE(":drive %d(%c), size %d\n",drive
, drive
+ 'A' - 1, size
);
442 if (!drive
|| drive
== _getdrive())
443 return _wgetcwd(buf
,size
); /* current */
446 MSVCRT_wchar_t dir
[MAX_PATH
];
447 MSVCRT_wchar_t drivespec
[4] = {'A', ':', '\\', 0};
450 drivespec
[0] += drive
- 1;
451 if (GetDriveTypeW(drivespec
) < DRIVE_REMOVABLE
)
453 *MSVCRT__errno() = MSVCRT_EACCES
;
457 dir_len
= GetFullPathNameW(drivespec
,MAX_PATH
,dir
,&dummy
);
458 if (dir_len
>= size
|| dir_len
< 1)
460 *MSVCRT__errno() = MSVCRT_ERANGE
;
461 return NULL
; /* buf too small */
464 TRACE(":returning %s\n", debugstr_w(dir
));
466 return _wcsdup(dir
); /* allocate */
472 /*********************************************************************
473 * _getdiskfree (MSVCRT.@)
475 unsigned int _getdiskfree(unsigned int disk
, struct _diskfree_t
* d
)
477 char drivespec
[4] = {'@', ':', '\\', 0};
482 return ERROR_INVALID_PARAMETER
; /* MSVCRT doesn't set errno here */
484 drivespec
[0] += disk
; /* make a drive letter */
486 if (GetDiskFreeSpaceA(disk
==0?NULL
:drivespec
,ret
,ret
+1,ret
+2,ret
+3))
488 d
->sectors_per_cluster
= (unsigned)ret
[0];
489 d
->bytes_per_sector
= (unsigned)ret
[1];
490 d
->avail_clusters
= (unsigned)ret
[2];
491 d
->total_clusters
= (unsigned)ret
[3];
494 err
= GetLastError();
495 MSVCRT__set_errno(err
);
499 /*********************************************************************
502 int _mkdir(const char * newdir
)
504 if (CreateDirectoryA(newdir
,NULL
))
506 MSVCRT__set_errno(GetLastError());
510 /*********************************************************************
513 int _wmkdir(const MSVCRT_wchar_t
* newdir
)
515 if (CreateDirectoryW(newdir
,NULL
))
517 MSVCRT__set_errno(GetLastError());
521 /*********************************************************************
524 int _rmdir(const char * dir
)
526 if (RemoveDirectoryA(dir
))
528 MSVCRT__set_errno(GetLastError());
532 /*********************************************************************
535 int _wrmdir(const MSVCRT_wchar_t
* dir
)
537 if (RemoveDirectoryW(dir
))
539 MSVCRT__set_errno(GetLastError());
543 /*********************************************************************
544 * _wsplitpath (MSVCRT.@)
546 void _wsplitpath(const MSVCRT_wchar_t
*inpath
, MSVCRT_wchar_t
*drv
, MSVCRT_wchar_t
*dir
,
547 MSVCRT_wchar_t
*fname
, MSVCRT_wchar_t
*ext
)
549 const MSVCRT_wchar_t
*p
, *end
;
551 if (inpath
[0] && inpath
[1] == ':')
561 else if (drv
) drv
[0] = 0;
563 /* look for end of directory part */
565 for (p
= inpath
; *p
; p
++) if (*p
== '/' || *p
== '\\') end
= p
+ 1;
567 if (end
) /* got a directory */
571 memcpy( dir
, inpath
, (end
- inpath
) * sizeof(MSVCRT_wchar_t
) );
572 dir
[end
- inpath
] = 0;
576 else if (dir
) dir
[0] = 0;
578 /* look for extension: what's after the last dot */
580 for (p
= inpath
; *p
; p
++) if (*p
== '.') end
= p
;
582 if (!end
) end
= p
; /* there's no extension */
586 memcpy( fname
, inpath
, (end
- inpath
) * sizeof(MSVCRT_wchar_t
) );
587 fname
[end
- inpath
] = 0;
589 if (ext
) strcpyW( ext
, end
);
592 /* INTERNAL: Helper for _fullpath. Modified PD code from 'snippets'. */
593 static void wmsvcrt_fln_fix(MSVCRT_wchar_t
*path
)
595 int dir_flag
= 0, root_flag
= 0;
596 MSVCRT_wchar_t
*r
, *p
, *q
, *s
;
597 MSVCRT_wchar_t szbsdot
[] = { '\\', '.', 0 };
600 if (NULL
== (r
= strrchrW(path
, ':')))
605 /* Ignore leading slashes */
615 p
= r
; /* Change "\\" to "\" */
616 while (NULL
!= (p
= strchrW(p
, '\\')))
622 while ('.' == *r
) /* Scrunch leading ".\" */
626 /* Ignore leading ".." */
627 for (p
= (r
+= 2); *p
&& (*p
!= '\\'); ++p
)
632 for (p
= r
+ 1 ;*p
&& (*p
!= '\\'); ++p
)
635 strcpyW(r
, p
+ ((*p
) ? 1 : 0));
638 while ('\\' == path
[strlenW(path
)-1]) /* Strip last '\\' */
641 path
[strlenW(path
)-1] = '\0';
646 /* Look for "\." in path */
648 while (NULL
!= (p
= strstrW(s
, szbsdot
)))
652 /* Execute this section if ".." found */
654 while (q
> r
) /* Backup one level */
667 strcpyW(q
+ ((*q
== '\\') ? 1 : 0),
668 p
+ 3 + ((*(p
+ 3)) ? 1 : 0));
675 /* Execute this section if "." found */
677 for ( ;*q
&& (*q
!= '\\'); ++q
)
683 if (root_flag
) /* Embedded ".." could have bubbled up to root */
685 for (p
= r
; *p
&& ('.' == *p
|| '\\' == *p
); ++p
)
693 MSVCRT_wchar_t szbs
[] = { '\\', 0 };
699 /*********************************************************************
700 * _wfullpath (MSVCRT.@)
702 MSVCRT_wchar_t
*_wfullpath(MSVCRT_wchar_t
* absPath
, const MSVCRT_wchar_t
* relPath
, MSVCRT_size_t size
)
704 MSVCRT_wchar_t drive
[5],dir
[MAX_PATH
],file
[MAX_PATH
],ext
[MAX_PATH
];
705 MSVCRT_wchar_t res
[MAX_PATH
];
707 MSVCRT_wchar_t szbs
[] = { '\\', 0 };
712 if (!relPath
|| !*relPath
)
713 return _wgetcwd(absPath
, size
);
717 *MSVCRT__errno() = MSVCRT_ERANGE
;
721 TRACE(":resolving relative path '%s'\n",debugstr_w(relPath
));
723 _wsplitpath(relPath
, drive
, dir
, file
, ext
);
725 /* Get Directory and drive into 'res' */
726 if (!dir
[0] || (dir
[0] != '/' && dir
[0] != '\\'))
728 /* Relative or no directory given */
729 _wgetdcwd(drive
[0] ? toupper(drive
[0]) - 'A' + 1 : 0, res
, MAX_PATH
);
734 res
[0] = drive
[0]; /* If given a drive, preserve the letter case */
745 wmsvcrt_fln_fix(res
);
748 if (len
>= MAX_PATH
|| len
>= (size_t)size
)
749 return NULL
; /* FIXME: errno? */
753 strcpyW(absPath
,res
);
757 /* INTERNAL: Helper for _fullpath. Modified PD code from 'snippets'. */
758 static void msvcrt_fln_fix(char *path
)
760 int dir_flag
= 0, root_flag
= 0;
764 if (NULL
== (r
= strrchr(path
, ':')))
769 /* Ignore leading slashes */
779 p
= r
; /* Change "\\" to "\" */
780 while (NULL
!= (p
= strchr(p
, '\\')))
786 while ('.' == *r
) /* Scrunch leading ".\" */
790 /* Ignore leading ".." */
791 for (p
= (r
+= 2); *p
&& (*p
!= '\\'); ++p
)
796 for (p
= r
+ 1 ;*p
&& (*p
!= '\\'); ++p
)
799 strcpy(r
, p
+ ((*p
) ? 1 : 0));
802 while ('\\' == path
[strlen(path
)-1]) /* Strip last '\\' */
805 path
[strlen(path
)-1] = '\0';
810 /* Look for "\." in path */
812 while (NULL
!= (p
= strstr(s
, "\\.")))
816 /* Execute this section if ".." found */
818 while (q
> r
) /* Backup one level */
831 strcpy(q
+ ((*q
== '\\') ? 1 : 0),
832 p
+ 3 + ((*(p
+ 3)) ? 1 : 0));
839 /* Execute this section if "." found */
841 for ( ;*q
&& (*q
!= '\\'); ++q
)
847 if (root_flag
) /* Embedded ".." could have bubbled up to root */
849 for (p
= r
; *p
&& ('.' == *p
|| '\\' == *p
); ++p
)
859 /*********************************************************************
860 * _fullpath (MSVCRT.@)
862 char *_fullpath(char * absPath
, const char* relPath
, unsigned int size
)
864 char drive
[5],dir
[MAX_PATH
],file
[MAX_PATH
],ext
[MAX_PATH
];
870 if (!relPath
|| !*relPath
)
871 return _getcwd(absPath
, size
);
875 *MSVCRT__errno() = MSVCRT_ERANGE
;
879 TRACE(":resolving relative path '%s'\n",relPath
);
881 _splitpath(relPath
, drive
, dir
, file
, ext
);
883 /* Get Directory and drive into 'res' */
884 if (!dir
[0] || (dir
[0] != '/' && dir
[0] != '\\'))
886 /* Relative or no directory given */
887 _getdcwd(drive
[0] ? toupper(drive
[0]) - 'A' + 1 : 0, res
, MAX_PATH
);
892 res
[0] = drive
[0]; /* If given a drive, preserve the letter case */
906 if (len
>= MAX_PATH
|| len
>= (size_t)size
)
907 return NULL
; /* FIXME: errno? */
915 /*********************************************************************
916 * _makepath (MSVCRT.@)
918 VOID
_makepath(char * path
, const char * drive
,
919 const char *directory
, const char * filename
,
920 const char * extension
)
923 char tmpPath
[MAX_PATH
];
924 TRACE("got %s %s %s %s\n", debugstr_a(drive
), debugstr_a(directory
),
925 debugstr_a(filename
), debugstr_a(extension
) );
931 if (drive
&& drive
[0])
933 tmpPath
[0] = drive
[0];
937 if (directory
&& directory
[0])
939 strcat(tmpPath
, directory
);
940 ch
= tmpPath
[strlen(tmpPath
)-1];
941 if (ch
!= '/' && ch
!= '\\')
942 strcat(tmpPath
,"\\");
944 if (filename
&& filename
[0])
946 strcat(tmpPath
, filename
);
947 if (extension
&& extension
[0])
949 if ( extension
[0] != '.' )
951 strcat(tmpPath
,extension
);
955 strcpy( path
, tmpPath
);
957 TRACE("returning %s\n",path
);
960 /*********************************************************************
961 * _wmakepath (MSVCRT.@)
963 VOID
_wmakepath(MSVCRT_wchar_t
*path
, const MSVCRT_wchar_t
*drive
, const MSVCRT_wchar_t
*directory
,
964 const MSVCRT_wchar_t
*filename
, const MSVCRT_wchar_t
*extension
)
967 TRACE("%s %s %s %s\n", debugstr_w(drive
), debugstr_w(directory
),
968 debugstr_w(filename
), debugstr_w(extension
));
974 if (drive
&& drive
[0])
980 if (directory
&& directory
[0])
982 strcatW(path
, directory
);
983 ch
= path
[strlenW(path
) - 1];
984 if (ch
!= '/' && ch
!= '\\')
986 static const MSVCRT_wchar_t backslashW
[] = {'\\',0};
987 strcatW(path
, backslashW
);
990 if (filename
&& filename
[0])
992 strcatW(path
, filename
);
993 if (extension
&& extension
[0])
995 if ( extension
[0] != '.' )
997 static const MSVCRT_wchar_t dotW
[] = {'.',0};
1000 strcatW(path
, extension
);
1004 TRACE("returning %s\n", debugstr_w(path
));
1007 /*********************************************************************
1008 * _searchenv (MSVCRT.@)
1010 void _searchenv(const char* file
, const char* env
, char *buf
)
1013 char curPath
[MAX_PATH
];
1018 if (GetFileAttributesA( file
) != INVALID_FILE_ATTRIBUTES
)
1020 GetFullPathNameA( file
, MAX_PATH
, buf
, NULL
);
1021 /* Sigh. This error is *always* set, regardless of success */
1022 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND
);
1026 /* Search given environment variable */
1027 envVal
= MSVCRT_getenv(env
);
1030 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND
);
1035 TRACE(":searching for %s in paths %s\n", file
, envVal
);
1041 while(*end
&& *end
!= ';') end
++; /* Find end of next path */
1042 if (penv
== end
|| !*penv
)
1044 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND
);
1047 strncpy(curPath
, penv
, end
- penv
);
1048 if (curPath
[end
- penv
] != '/' || curPath
[end
- penv
] != '\\')
1050 curPath
[end
- penv
] = '\\';
1051 curPath
[end
- penv
+ 1] = '\0';
1054 curPath
[end
- penv
] = '\0';
1056 strcat(curPath
, file
);
1057 TRACE("Checking for file %s\n", curPath
);
1058 if (GetFileAttributesA( curPath
) != INVALID_FILE_ATTRIBUTES
)
1060 strcpy(buf
, curPath
);
1061 MSVCRT__set_errno(ERROR_FILE_NOT_FOUND
);
1064 penv
= *end
? end
+ 1 : end
;