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

Last change on this file since 21439 was 21439, checked in by dmik, 15 years ago

minivcrt: Provide a _fullpath() reimplementation that returns char * (as required by MSVCRT specs) instead of int returned by the EMX version, when building under EMX.

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