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

Last change on this file since 10005 was 10005, checked in by sandervl, 22 years ago

PF: MSVCRT update

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