source: trunk/src/shlwapi/path.c@ 3879

Last change on this file since 3879 was 3879, checked in by sandervl, 25 years ago

Registry key & directory name for 'Start Menu'

File size: 52.6 KB
Line 
1/* $Id: path.c,v 1.5 2000-07-21 18:30:29 sandervl Exp $ */
2
3/*
4 * Path Functions
5 *
6 * Project Odin Software License can be found in LICENSE.TXT
7 *
8 *
9 * NOTE: SHGetSpecialFolderPathA: StartMenu changed in 'Start Menu'
10 *
11 *
12 * Copyright 1997 Marcus Meissner
13 *
14 * WINE 20000430 level
15 */
16
17/*****************************************************************************
18 * Remark *
19 *****************************************************************************
20
21 */
22
23
24/*****************************************************************************
25 * Includes *
26 *****************************************************************************/
27
28#include <odin.h>
29#include <odinwrap.h>
30#include <os2sel.h>
31
32#include <string.h>
33#include <ctype.h>
34#include <wctype.h>
35#include <wcstr.h>
36#define HAVE_WCTYPE_H
37
38#include "debugtools.h"
39
40#include <winreg.h>
41
42#include <heapstring.h>
43#include <misc.h>
44#include <win\shell.h>
45#include <win\winerror.h>
46#include <win\crtdll.h>
47#include <win\winversion.h>
48#include <winuser.h>
49
50#include "shlwapi.h"
51
52#define strncasecmp lstrncmpA
53#define strcasecmp lstrcmpA
54
55
56ODINDEBUGCHANNEL(SHLWAPI-PATH)
57
58
59/*************************************************************************
60 * PathAppendA [SHLWAPI.@]
61 *
62 * NOTES
63 * concat path lpszPath2 onto lpszPath1
64 *
65 * FIXME
66 * the resulting path is also canonicalized
67 */
68LPSTR WINAPI PathAppendA(
69 LPSTR lpszPath1,
70 LPCSTR lpszPath2)
71{
72 TRACE("%s %s\n",lpszPath1, lpszPath2);
73 while (lpszPath2[0]=='\\') lpszPath2++;
74 return PathCombineA(lpszPath1,lpszPath1,lpszPath2);
75}
76
77/*************************************************************************
78 * PathAppendW [SHLWAPI.@]
79 */
80LPSTR WINAPI PathAppendW(
81 LPWSTR lpszPath1,
82 LPCWSTR lpszPath2)
83{
84 FIXME("%s %s\n",debugstr_w(lpszPath1), debugstr_w(lpszPath2));
85 return NULL;
86}
87
88/*************************************************************************
89 * PathAppendAW [SHELL32.36]
90 */
91LPVOID WINAPI PathAppendAW(
92 LPVOID lpszPath1,
93 LPCVOID lpszPath2)
94{
95 if (VERSION_OsIsUnicode())
96 return PathAppendW(lpszPath1, lpszPath2);
97 return PathAppendA(lpszPath1, lpszPath2);
98}
99
100/*************************************************************************
101 * PathCombineA [SHLWAPI.@]
102 *
103 * NOTES
104 * if lpszFile='.' skip it
105 * szDest can be equal to lpszFile. Thats why we use sTemp
106 *
107 * FIXME
108 * the resulting path is also canonicalized
109 * If lpszSrcPath2 starts with a backslash it is appended
110 * to the root of lpszSrcPath1.
111 */
112LPSTR WINAPI PathCombineA(
113 LPSTR szDest,
114 LPCSTR lpszDir,
115 LPCSTR lpszFile)
116{
117 char sTemp[MAX_PATH];
118 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
119
120
121 if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) )
122 {
123 strcpy(szDest,lpszDir);
124 return szDest;
125 }
126
127 /* if lpszFile is a complete path don't care about lpszDir */
128 if (PathIsRootA(lpszFile))
129 {
130 strcpy(szDest,lpszFile);
131 }
132 else
133 {
134 strcpy(sTemp,lpszDir);
135 PathAddBackslashA(sTemp);
136 strcat(sTemp,lpszFile);
137 strcpy(szDest,sTemp);
138 }
139 return szDest;
140}
141
142/*************************************************************************
143 * PathCombineW [SHLWAPI.@]
144 */
145LPWSTR WINAPI PathCombineW(
146 LPWSTR szDest,
147 LPCWSTR lpszDir,
148 LPCWSTR lpszFile)
149{
150 WCHAR sTemp[MAX_PATH];
151 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
152 lpszFile, debugstr_w(lpszFile));
153
154
155 if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) )
156 {
157 CRTDLL_wcscpy(szDest,lpszDir);
158 return szDest;
159 }
160
161 /* if lpszFile is a complete path don't care about lpszDir */
162 if (PathIsRootW(lpszFile))
163 {
164 CRTDLL_wcscpy(szDest,lpszFile);
165 }
166 else
167 {
168 CRTDLL_wcscpy(sTemp,lpszDir);
169 PathAddBackslashW(sTemp);
170 CRTDLL_wcscat(sTemp,lpszFile);
171 CRTDLL_wcscpy(szDest,sTemp);
172 }
173 return szDest;
174}
175
176/*************************************************************************
177 * PathCombineAW [SHELL32.37]
178 */
179LPVOID WINAPI PathCombineAW(
180 LPVOID szDest,
181 LPCVOID lpszDir,
182 LPCVOID lpszFile)
183{
184 if (VERSION_OsIsUnicode())
185 return PathCombineW( szDest, lpszDir, lpszFile );
186 return PathCombineA( szDest, lpszDir, lpszFile );
187}
188
189/*************************************************************************
190 * PathAddBackslashA [SHLWAPI.@]
191 *
192 * NOTES
193 * append \ if there is none
194 */
195LPSTR WINAPI PathAddBackslashA(LPSTR lpszPath)
196{
197 int len;
198 TRACE("%p->%s\n",lpszPath,lpszPath);
199
200 len = strlen(lpszPath);
201 if (len && lpszPath[len-1]!='\\')
202 {
203 lpszPath[len] = '\\';
204 lpszPath[len+1]= 0x00;
205 return lpszPath+len+1;
206 }
207 return lpszPath+len;
208}
209
210/*************************************************************************
211 * PathAddBackslashW [SHLWAPI.@]
212 */
213LPWSTR WINAPI PathAddBackslashW(LPWSTR lpszPath)
214{
215 int len;
216 TRACE("%p->%s\n",lpszPath,debugstr_w(lpszPath));
217
218 len = CRTDLL_wcslen(lpszPath);
219 if (len && lpszPath[len-1]!=(WCHAR)'\\')
220 {
221 lpszPath[len] = (WCHAR)'\\';
222 lpszPath[len+1]= 0x00;
223 return lpszPath+len+1;
224 }
225 return lpszPath+len;
226}
227
228/*************************************************************************
229 * PathAddBackslashAW [SHELL32.32]
230 */
231LPVOID WINAPI PathAddBackslashAW(LPVOID lpszPath)
232{
233 if(VERSION_OsIsUnicode())
234 return PathAddBackslashW(lpszPath);
235 return PathAddBackslashA(lpszPath);
236}
237
238/*************************************************************************
239 * PathBuildRootA [SHLWAPI.@]
240 */
241LPSTR WINAPI PathBuildRootA(LPSTR lpszPath, int drive)
242{
243 TRACE("%p %i\n",lpszPath, drive);
244
245 strcpy(lpszPath,"A:\\");
246 lpszPath[0]+=drive;
247 return lpszPath;
248}
249
250/*************************************************************************
251 * PathBuildRootW [SHLWAPI.@]
252 */
253LPWSTR WINAPI PathBuildRootW(LPWSTR lpszPath, int drive)
254{
255 TRACE("%p %i\n",debugstr_w(lpszPath), drive);
256
257 lstrcpyAtoW(lpszPath,"A:\\");
258 lpszPath[0]+=drive;
259 return lpszPath;
260}
261
262/*************************************************************************
263 * PathBuildRootAW [SHELL32.30]
264 */
265LPVOID WINAPI PathBuildRootAW(LPVOID lpszPath, int drive)
266{
267 if(VERSION_OsIsUnicode())
268 return PathBuildRootW(lpszPath, drive);
269 return PathBuildRootA(lpszPath, drive);
270}
271
272/*
273 Extracting Component Parts
274*/
275
276/*************************************************************************
277 * PathFindFileNameA [SHLWAPI.@]
278 */
279LPSTR WINAPI PathFindFileNameA(LPCSTR lpszPath)
280{
281 LPCSTR aslash;
282 aslash = lpszPath;
283
284 TRACE("%s\n",aslash);
285 while (lpszPath[0])
286 {
287 if (((lpszPath[0]=='\\') || (lpszPath[0]==':')) && lpszPath[1] && lpszPath[1]!='\\')
288 aslash = lpszPath+1;
289 lpszPath++;
290 }
291 return (LPSTR)aslash;
292
293}
294
295/*************************************************************************
296 * PathFindFileNameW [SHLWAPI.@]
297 */
298LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
299{
300 LPCWSTR wslash;
301 wslash = lpszPath;
302
303 TRACE("%s\n",debugstr_w(wslash));
304 while (lpszPath[0])
305 {
306 if (((lpszPath[0]=='\\') || (lpszPath[0]==':')) && lpszPath[1] && lpszPath[1]!='\\')
307 wslash = lpszPath+1;
308 lpszPath++;
309 }
310 return (LPWSTR)wslash;
311}
312
313/*************************************************************************
314 * PathFindFileNameAW [SHELL32.34]
315 */
316LPVOID WINAPI PathFindFileNameAW(LPCVOID lpszPath)
317{
318 if(VERSION_OsIsUnicode())
319 return PathFindFileNameW(lpszPath);
320 return PathFindFileNameA(lpszPath);
321}
322
323/*************************************************************************
324 * PathFindExtensionA [SHLWAPI.@]
325 *
326 * NOTES
327 * returns pointer to last . in last lpszPath component or at \0.
328 */
329
330LPSTR WINAPI PathFindExtensionA(LPCSTR lpszPath)
331{
332 LPCSTR lastpoint = NULL;
333
334 TRACE("%p %s\n",lpszPath,lpszPath);
335
336 while (*lpszPath)
337 {
338 if (*lpszPath=='\\'||*lpszPath==' ')
339 lastpoint=NULL;
340 if (*lpszPath=='.')
341 lastpoint=lpszPath;
342 lpszPath++;
343 }
344 return (LPSTR)(lastpoint?lastpoint:lpszPath);
345}
346
347/*************************************************************************
348 * PathFindExtensionW [SHLWAPI.@]
349 */
350LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
351{
352 LPCWSTR lastpoint = NULL;
353
354 TRACE("(%p %s)\n",lpszPath,debugstr_w(lpszPath));
355
356 while (*lpszPath)
357 {
358 if (*lpszPath==(WCHAR)'\\'||*lpszPath==(WCHAR)' ')
359 lastpoint=NULL;
360 if (*lpszPath==(WCHAR)'.')
361 lastpoint=lpszPath;
362 lpszPath++;
363 }
364 return (LPWSTR)(lastpoint?lastpoint:lpszPath);
365}
366
367/*************************************************************************
368 * PathFindExtensionAW [SHELL32.31]
369 */
370LPVOID WINAPI PathFindExtensionAW(LPCVOID lpszPath)
371{
372 if (VERSION_OsIsUnicode())
373 return PathFindExtensionW(lpszPath);
374 return PathFindExtensionA(lpszPath);
375
376}
377
378/*************************************************************************
379 * PathGetExtensionA [internal]
380 *
381 * NOTES
382 * exported by ordinal
383 * return value points to the first char after the dot
384 */
385LPSTR WINAPI PathGetExtensionA(LPCSTR lpszPath)
386{
387 TRACE("(%s)\n",lpszPath);
388
389 lpszPath = PathFindExtensionA(lpszPath);
390 return (LPSTR)(*lpszPath?(lpszPath+1):lpszPath);
391}
392
393/*************************************************************************
394 * PathGetExtensionW [internal]
395 */
396LPWSTR WINAPI PathGetExtensionW(LPCWSTR lpszPath)
397{
398 TRACE("(%s)\n",debugstr_w(lpszPath));
399
400 lpszPath = PathFindExtensionW(lpszPath);
401 return (LPWSTR)(*lpszPath?(lpszPath+1):lpszPath);
402}
403
404/*************************************************************************
405 * PathGetExtensionAW [SHELL32.158]
406 */
407LPVOID WINAPI PathGetExtensionAW(LPCVOID lpszPath)
408{
409 if (VERSION_OsIsUnicode())
410 return PathGetExtensionW(lpszPath);
411 return PathGetExtensionA(lpszPath);
412}
413
414/*************************************************************************
415 * PathGetArgsA [SHLWAPI.@]
416 *
417 * NOTES
418 * look for next arg in string. handle "quoted" strings
419 * returns pointer to argument *AFTER* the space. Or to the \0.
420 *
421 * FIXME
422 * quoting by '\'
423 */
424LPSTR WINAPI PathGetArgsA(LPCSTR lpszPath)
425{
426 BOOL qflag = FALSE;
427
428 TRACE("%s\n",lpszPath);
429
430 while (*lpszPath)
431 {
432 if ((*lpszPath==' ') && !qflag)
433 return (LPSTR)lpszPath+1;
434 if (*lpszPath=='"')
435 qflag=!qflag;
436 lpszPath++;
437 }
438 return (LPSTR)lpszPath;
439
440}
441
442/*************************************************************************
443 * PathGetArgsW [SHLWAPI.@]
444 */
445LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath)
446{
447 BOOL qflag = FALSE;
448
449 TRACE("%s\n",debugstr_w(lpszPath));
450
451 while (*lpszPath)
452 {
453 if ((*lpszPath==' ') && !qflag)
454 return (LPWSTR)lpszPath+1;
455 if (*lpszPath=='"')
456 qflag=!qflag;
457 lpszPath++;
458 }
459 return (LPWSTR)lpszPath;
460}
461
462/*************************************************************************
463 * PathGetArgsAW [SHELL32.52]
464 */
465LPVOID WINAPI PathGetArgsAW(LPVOID lpszPath)
466{
467 if (VERSION_OsIsUnicode())
468 return PathGetArgsW(lpszPath);
469 return PathGetArgsA(lpszPath);
470}
471
472/*************************************************************************
473 * PathGetDriveNumberA [SHLWAPI.@]
474 */
475int WINAPI PathGetDriveNumberA(LPCSTR lpszPath)
476{
477 int chr = tolower(lpszPath[0]);
478
479 TRACE ("%s\n",debugstr_a(lpszPath));
480
481 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
482 return tolower(lpszPath[0]) - 'a' ;
483}
484
485/*************************************************************************
486 * PathGetDriveNumberW [SHLWAPI.@]
487 */
488int WINAPI PathGetDriveNumberW(LPCWSTR lpszPath)
489{
490 int chr = towlower(lpszPath[0]);
491
492 TRACE ("%s\n",debugstr_w(lpszPath));
493
494 if (!lpszPath || lpszPath[1]!=':' || chr < 'a' || chr > 'z') return -1;
495 return tolower(lpszPath[0]) - 'a' ;
496}
497
498/*************************************************************************
499 * PathGetDriveNumber [SHELL32.57]
500 */
501int WINAPI PathGetDriveNumberAW(LPVOID lpszPath)
502{
503 if (VERSION_OsIsUnicode())
504 return PathGetDriveNumberW(lpszPath);
505 return PathGetDriveNumberA(lpszPath);
506}
507
508/*************************************************************************
509 * PathRemoveFileSpecA [SHLWAPI.@]
510 *
511 * NOTES
512 * truncates passed argument to a valid path
513 * returns if the string was modified or not.
514 * "\foo\xx\foo"-> "\foo\xx"
515 * "\" -> "\"
516 * "a:\foo" -> "a:\"
517 */
518BOOL WINAPI PathRemoveFileSpecA(LPSTR lpszPath)
519{
520 LPSTR cutplace;
521
522 TRACE("%s\n",lpszPath);
523
524 if (!lpszPath[0]) return 0;
525
526 cutplace = PathFindFileNameA(lpszPath);
527 if (cutplace)
528 {
529 *cutplace='\0';
530 if (PathIsRootA(lpszPath))
531 {
532 PathAddBackslashA(lpszPath);
533 }
534 else
535 {
536 PathRemoveBackslashA(lpszPath);
537 }
538 return TRUE;
539 }
540 return FALSE;
541}
542
543/*************************************************************************
544 * PathRemoveFileSpecW [SHLWAPI.@]
545 */
546BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
547{
548 LPWSTR cutplace;
549
550 TRACE("%s\n",debugstr_w(lpszPath));
551
552 if (!lpszPath[0]) return 0;
553 cutplace = PathFindFileNameW(lpszPath);
554 if (cutplace)
555 {
556 *cutplace='\0';
557 if (PathIsRootW(lpszPath))
558 {
559 PathAddBackslashW(lpszPath);
560 }
561 else
562 {
563 PathRemoveBackslashW(lpszPath);
564 }
565 return TRUE;
566 }
567 return FALSE;
568}
569
570/*************************************************************************
571 * PathRemoveFileSpec [SHELL32.35]
572 */
573BOOL WINAPI PathRemoveFileSpecAW(LPVOID lpszPath)
574{
575 if (VERSION_OsIsUnicode())
576 return PathRemoveFileSpecW(lpszPath);
577 return PathRemoveFileSpecA(lpszPath);
578}
579
580/*************************************************************************
581 * PathStripPathA [SHELLWAPI.@]
582 *
583 * NOTES
584 * removes the path from the beginning of a filename
585 */
586void WINAPI PathStripPathA(LPSTR lpszPath)
587{
588 LPSTR lpszFileName = PathFindFileNameA(lpszPath);
589
590 TRACE("%s\n", lpszPath);
591
592 if(lpszFileName)
593 RtlMoveMemory(lpszPath, lpszFileName, strlen(lpszFileName));
594}
595
596/*************************************************************************
597 * PathStripPathW [SHELLWAPI.@]
598 */
599void WINAPI PathStripPathW(LPWSTR lpszPath)
600{
601 LPWSTR lpszFileName = PathFindFileNameW(lpszPath);
602
603 TRACE("%s\n", debugstr_w(lpszPath));
604 if(lpszFileName)
605 RtlMoveMemory(lpszPath, lpszFileName, lstrlenW(lpszFileName)*sizeof(WCHAR));
606}
607
608/*************************************************************************
609 * PathStripPathAW [SHELL32.38]
610 */
611void WINAPI PathStripPathAW(LPVOID lpszPath)
612{
613 if (VERSION_OsIsUnicode())
614 PathStripPathW(lpszPath);
615 PathStripPathA(lpszPath);
616}
617
618/*************************************************************************
619 * PathStripToRootA [SHLWAPI.@]
620 */
621BOOL WINAPI PathStripToRootA(LPSTR lpszPath)
622{
623 TRACE("%s\n", lpszPath);
624
625 /* X:\ */
626 if (lpszPath[1]==':' && lpszPath[2]=='\\')
627 {
628 lpszPath[3]='\0';
629 return TRUE;
630 }
631
632 /* "\" */
633 if (lpszPath[0]=='\\')
634 {
635 lpszPath[1]='\0';
636 return TRUE;
637 }
638
639 /* UNC "\\<computer>\<share>" */
640 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
641 {
642 int foundbackslash = 0;
643 lpszPath += 2;
644 while (*lpszPath)
645 {
646 if (*lpszPath=='\\') foundbackslash++;
647 if (foundbackslash==2)
648 {
649 *lpszPath = '\0';
650 return TRUE;
651 }
652 lpszPath++;
653 }
654 }
655
656 return FALSE;
657}
658
659/*************************************************************************
660 * PathStripToRootW [SHLWAPI.@]
661 */
662BOOL WINAPI PathStripToRootW(LPWSTR lpszPath)
663{
664 TRACE("%s\n", debugstr_w(lpszPath));
665
666 /* X:\ */
667 if (lpszPath[1]==':' && lpszPath[2]=='\\')
668 {
669 lpszPath[3]='\0';
670 return TRUE;
671 }
672
673 /* "\" */
674 if (lpszPath[0]=='\\')
675 {
676 lpszPath[1]='\0';
677 return TRUE;
678 }
679
680 /* UNC "\\<computer>\<share>" */
681 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
682 {
683 int foundbackslash = 0;
684 lpszPath += 2;
685 while (*lpszPath)
686 {
687 if (*lpszPath=='\\') foundbackslash++;
688 if (foundbackslash==2)
689 {
690 *lpszPath = '\0';
691 return TRUE;
692 }
693 lpszPath++;
694 }
695 }
696
697 return FALSE;
698}
699
700/*************************************************************************
701 * PathStripToRootAW [SHELL32.50]
702 */
703BOOL WINAPI PathStripToRootAW(LPVOID lpszPath)
704{
705 if (VERSION_OsIsUnicode())
706 return PathStripToRootW(lpszPath);
707 return PathStripToRootA(lpszPath);
708}
709
710/*************************************************************************
711 * PathRemoveArgsA [SHLWAPI.@]
712 */
713void WINAPI PathRemoveArgsA(LPSTR lpszPath)
714{
715 LPSTR lpszArgs = PathGetArgsA(lpszPath);
716
717 TRACE("%s\n", lpszPath);
718
719 if (lpszArgs) *(--lpszArgs)='\0';
720}
721
722/*************************************************************************
723 * PathRemoveArgsW [SHLWAPI.@]
724 */
725void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
726{
727 LPWSTR lpszArgs = PathGetArgsW(lpszPath);
728
729 TRACE("%s\n", debugstr_w(lpszPath));
730
731 if (lpszArgs) *(--lpszArgs)='\0';
732}
733
734/*************************************************************************
735 * PathRemoveArgsAW [SHELL32.251]
736 */
737void WINAPI PathRemoveArgsAW(LPVOID lpszPath)
738{
739 if (VERSION_OsIsUnicode())
740 PathRemoveArgsW(lpszPath);
741 PathRemoveArgsA(lpszPath);
742}
743
744/*************************************************************************
745 * PathRemoveExtensionA [SHLWAPI.@]
746 */
747void WINAPI PathRemoveExtensionA(LPSTR lpszPath)
748{
749 LPSTR lpszExtension = PathFindExtensionA(lpszPath);
750
751 TRACE("%s\n", lpszPath);
752
753 if (lpszExtension) *lpszExtension='\0';
754}
755
756/*************************************************************************
757 * PathRemoveExtensionW [SHLWAPI.@]
758 */
759void WINAPI PathRemoveExtensionW(LPWSTR lpszPath)
760{
761 LPWSTR lpszExtension = PathFindExtensionW(lpszPath);
762
763 TRACE("%s\n", debugstr_w(lpszPath));
764
765 if (lpszExtension) *lpszExtension='\0';
766}
767
768/*************************************************************************
769 * PathRemoveExtensionAW [SHELL32.250]
770 */
771void WINAPI PathRemoveExtensionAW(LPVOID lpszPath)
772{
773 if (VERSION_OsIsUnicode())
774 PathRemoveExtensionW(lpszPath);
775 PathRemoveExtensionA(lpszPath);
776}
777
778/*************************************************************************
779 * PathRemoveBackslashA [SHLWAPI.@]
780 *
781 * If the path ends in a backslash it is replaced by a NULL
782 * and the address of the NULL is returned
783 * Otherwise
784 * the address of the last character is returned.
785 *
786 */
787LPSTR WINAPI PathRemoveBackslashA( LPSTR lpszPath )
788{
789 LPSTR p = lpszPath;
790
791 while (*lpszPath) p = lpszPath++;
792 if ( *p == (CHAR)'\\') *p = (CHAR)'\0';
793 return p;
794}
795
796/*************************************************************************
797 * PathRemoveBackslashW [SHLWAPI.@]
798 */
799LPWSTR WINAPI PathRemoveBackslashW( LPWSTR lpszPath )
800{
801 LPWSTR p = lpszPath;
802
803 while (*lpszPath); p = lpszPath++;
804 if ( *p == (WCHAR)'\\') *p = (WCHAR)'\0';
805 return p;
806}
807
808/*
809 Path Manipulations
810*/
811
812/*************************************************************************
813 * PathGetShortPathA [internal]
814 */
815LPSTR WINAPI PathGetShortPathA(LPSTR lpszPath)
816{
817 FIXME("%s stub\n", lpszPath);
818 return NULL;
819}
820
821/*************************************************************************
822 * PathGetShortPathW [internal]
823 */
824LPWSTR WINAPI PathGetShortPathW(LPWSTR lpszPath)
825{
826 FIXME("%s stub\n", debugstr_w(lpszPath));
827 return NULL;
828}
829
830/*************************************************************************
831 * PathGetShortPathAW [SHELL32.92]
832 */
833LPVOID WINAPI PathGetShortPathAW(LPVOID lpszPath)
834{
835 if(VERSION_OsIsUnicode())
836 return PathGetShortPathW(lpszPath);
837 return PathGetShortPathA(lpszPath);
838}
839
840/*************************************************************************
841 * PathRemoveBlanksA [SHLWAPI.@]
842 *
843 * NOTES
844 * remove spaces from beginning and end of passed string
845 */
846LPSTR WINAPI PathRemoveBlanksA(LPSTR str)
847{
848 LPSTR x = str;
849
850 TRACE("%s\n",str);
851
852 while (*x==' ') x++;
853 if (x!=str)
854 strcpy(str,x);
855 if (!*str)
856 return str;
857 x=str+strlen(str)-1;
858 while (*x==' ')
859 x--;
860 if (*x==' ')
861 *x='\0';
862 return x;
863}
864
865/*************************************************************************
866 * PathRemoveBlanksW [SHLWAPI.@]
867 */
868LPWSTR WINAPI PathRemoveBlanksW(LPWSTR str)
869{
870 LPWSTR x = str;
871
872 TRACE("%s\n",debugstr_w(str));
873
874 while (*x==' ') x++;
875 if (x!=str)
876 CRTDLL_wcscpy(str,x);
877 if (!*str)
878 return str;
879 x=str+CRTDLL_wcslen(str)-1;
880 while (*x==' ')
881 x--;
882 if (*x==' ')
883 *x='\0';
884 return x;
885}
886
887/*************************************************************************
888 * PathRemoveBlanksAW [SHELL32.33]
889 */
890LPVOID WINAPI PathRemoveBlanksAW(LPVOID str)
891{
892 if(VERSION_OsIsUnicode())
893 return PathRemoveBlanksW(str);
894 return PathRemoveBlanksA(str);
895}
896
897/*************************************************************************
898 * PathQuoteSpacesA [SHLWAPI.@]
899 *
900 * NOTES
901 */
902LPSTR WINAPI PathQuoteSpacesA(LPCSTR lpszPath)
903{
904 FIXME("%s\n",lpszPath);
905 return 0;
906}
907
908/*************************************************************************
909 * PathQuoteSpacesW [SHLWAPI.@]
910 */
911LPWSTR WINAPI PathQuoteSpacesW(LPCWSTR lpszPath)
912{
913 FIXME("%s\n",debugstr_w(lpszPath));
914 return 0;
915}
916
917/*************************************************************************
918 * PathQuoteSpacesAW [SHELL32.55]
919 */
920LPVOID WINAPI PathQuoteSpacesAW (LPCVOID lpszPath)
921{
922 if(VERSION_OsIsUnicode())
923 return PathQuoteSpacesW(lpszPath);
924 return PathQuoteSpacesA(lpszPath);
925}
926
927/*************************************************************************
928 * PathUnquoteSpacesA [SHLWAPI.@]
929 *
930 * NOTES
931 * unquote string (remove ")
932 */
933VOID WINAPI PathUnquoteSpacesA(LPSTR str)
934{
935 DWORD len = lstrlenA(str);
936
937 TRACE("%s\n",str);
938
939 if (*str!='"')
940 return;
941 if (str[len-1]!='"')
942 return;
943 str[len-1]='\0';
944 lstrcpyA(str,str+1);
945 return;
946}
947
948/*************************************************************************
949 * PathUnquoteSpacesW [SHLWAPI.@]
950 */
951VOID WINAPI PathUnquoteSpacesW(LPWSTR str)
952{
953 DWORD len = CRTDLL_wcslen(str);
954
955 TRACE("%s\n",debugstr_w(str));
956
957 if (*str!='"')
958 return;
959 if (str[len-1]!='"')
960 return;
961 str[len-1]='\0';
962 CRTDLL_wcscpy(str,str+1);
963 return;
964}
965
966/*************************************************************************
967 * PathUnquoteSpacesAW [SHELL32.56]
968 */
969VOID WINAPI PathUnquoteSpacesAW(LPVOID str)
970{
971 if(VERSION_OsIsUnicode())
972 PathUnquoteSpacesW(str);
973 else
974 PathUnquoteSpacesA(str);
975}
976
977/*************************************************************************
978 * PathParseIconLocationA [SHLWAPI.@]
979 */
980int WINAPI PathParseIconLocationA(LPSTR lpszPath)
981{
982 LPSTR lpstrComma = strchr(lpszPath, ',');
983
984 FIXME("%s stub\n", debugstr_a(lpszPath));
985
986 if (lpstrComma && lpstrComma[1])
987 {
988 lpstrComma[0]='\0';
989/* return atoi(&lpstrComma[1]); FIXME */
990 }
991 return 0;
992}
993
994/*************************************************************************
995 * PathParseIconLocationW [SHLWAPI.@]
996 */
997int WINAPI PathParseIconLocationW(LPWSTR lpszPath)
998{
999 LPWSTR lpstrComma = CRTDLL_wcschr(lpszPath, ',');
1000
1001 FIXME("%s stub\n", debugstr_w(lpszPath));
1002
1003 if (lpstrComma && lpstrComma[1])
1004 {
1005 lpstrComma[0]='\0';
1006/* return _wtoi(&lpstrComma[1]); FIXME */
1007 }
1008 return 0;
1009}
1010
1011/*************************************************************************
1012 * PathParseIconLocationAW [SHELL32.249]
1013 */
1014int WINAPI PathParseIconLocationAW (LPVOID lpszPath)
1015{
1016 if(VERSION_OsIsUnicode())
1017 return PathParseIconLocationW(lpszPath);
1018 return PathParseIconLocationA(lpszPath);
1019}
1020
1021/*
1022 Path Testing
1023*/
1024/*************************************************************************
1025 * PathIsUNCA [SHLWAPI.@]
1026 *
1027 * NOTES
1028 * PathIsUNC(char*path);
1029 */
1030BOOL WINAPI PathIsUNCA(LPCSTR lpszPath)
1031{
1032 TRACE("%s\n",lpszPath);
1033
1034 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
1035}
1036
1037/*************************************************************************
1038 * PathIsUNCW [SHLWAPI.@]
1039 */
1040BOOL WINAPI PathIsUNCW(LPCWSTR lpszPath)
1041{
1042 TRACE("%s\n",debugstr_w(lpszPath));
1043
1044 return (lpszPath && (lpszPath[0]=='\\') && (lpszPath[1]=='\\'));
1045}
1046
1047/*************************************************************************
1048 * PathIsUNCAW [SHELL32.39]
1049 */
1050BOOL WINAPI PathIsUNCAW (LPCVOID lpszPath)
1051{
1052 if (VERSION_OsIsUnicode())
1053 return PathIsUNCW( lpszPath );
1054 return PathIsUNCA( lpszPath );
1055}
1056
1057/*************************************************************************
1058 * PathIsRelativeA [SHLWAPI.@]
1059 */
1060BOOL WINAPI PathIsRelativeA (LPCSTR lpszPath)
1061{
1062 TRACE("lpszPath=%s\n",lpszPath);
1063
1064 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
1065}
1066
1067/*************************************************************************
1068 * PathIsRelativeW [SHLWAPI.@]
1069 */
1070BOOL WINAPI PathIsRelativeW (LPCWSTR lpszPath)
1071{
1072 TRACE("lpszPath=%s\n",debugstr_w(lpszPath));
1073
1074 return (lpszPath && (lpszPath[0]!='\\' && lpszPath[1]!=':'));
1075}
1076
1077/*************************************************************************
1078 * PathIsRelativeAW [SHELL32.40]
1079 */
1080BOOL WINAPI PathIsRelativeAW (LPCVOID lpszPath)
1081{
1082 if (VERSION_OsIsUnicode())
1083 return PathIsRelativeW( lpszPath );
1084 return PathIsRelativeA( lpszPath );
1085}
1086
1087/*************************************************************************
1088 * PathIsRootA [SHLWAPI.@]
1089 *
1090 * notes
1091 * TRUE if the path points to a root directory
1092 */
1093BOOL WINAPI PathIsRootA(LPCSTR lpszPath)
1094{
1095 TRACE("%s\n",lpszPath);
1096
1097 /* X:\ */
1098 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
1099 return TRUE;
1100
1101 /* "\" */
1102 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
1103 return TRUE;
1104
1105 /* UNC "\\<computer>\<share>" */
1106 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1107 {
1108 int foundbackslash = 0;
1109 lpszPath += 2;
1110 while (*lpszPath)
1111 {
1112 if (*(lpszPath++)=='\\') foundbackslash++;
1113 }
1114 if (foundbackslash==1)
1115 return TRUE;
1116 }
1117 return FALSE;
1118}
1119
1120/*************************************************************************
1121 * PathIsRootW [SHLWAPI.@]
1122 */
1123BOOL WINAPI PathIsRootW(LPCWSTR lpszPath)
1124{
1125 TRACE("%s\n",debugstr_w(lpszPath));
1126
1127 /* X:\ */
1128 if (lpszPath[1]==':' && lpszPath[2]=='\\' && lpszPath[3]=='\0')
1129 return TRUE;
1130
1131 /* "\" */
1132 if (lpszPath[0]=='\\' && lpszPath[1]=='\0')
1133 return TRUE;
1134
1135 /* UNC "\\<computer>\<share>" */
1136 if (lpszPath[0]=='\\' && lpszPath[1]=='\\')
1137 {
1138 int foundbackslash = 0;
1139 lpszPath += 2;
1140 while (*lpszPath)
1141 {
1142 if (*(lpszPath++)=='\\') foundbackslash++;
1143 }
1144 if (foundbackslash==1)
1145 return TRUE;
1146 }
1147 return FALSE;
1148
1149}
1150
1151/*************************************************************************
1152 * PathIsRootAW [SHELL32.29]
1153 */
1154BOOL WINAPI PathIsRootAW(LPCVOID lpszPath)
1155{
1156 if (VERSION_OsIsUnicode())
1157 return PathIsRootW(lpszPath);
1158 return PathIsRootA(lpszPath);
1159}
1160
1161/*************************************************************************
1162 * PathIsExeA [internal]
1163 */
1164BOOL WINAPI PathIsExeA (LPCSTR lpszPath)
1165{
1166 LPCSTR lpszExtension = PathGetExtensionA(lpszPath);
1167 int i = 0;
1168 static char * lpszExtensions[6] = {"exe", "com", "pid", "cmd", "bat", NULL };
1169
1170 TRACE("path=%s\n",lpszPath);
1171
1172 for(i=0; lpszExtensions[i]; i++)
1173 if (!strcasecmp(lpszExtension,lpszExtensions[i])) return TRUE;
1174
1175 return FALSE;
1176}
1177
1178/*************************************************************************
1179 * PathIsExeW [internal]
1180 */
1181BOOL WINAPI PathIsExeW (LPCWSTR lpszPath)
1182{
1183 LPCWSTR lpszExtension = PathGetExtensionW(lpszPath);
1184 int i = 0;
1185 static WCHAR lpszExtensions[6][4] =
1186 {{'e','x','e','\0'}, {'c','o','m','\0'}, {'p','i','d','\0'},
1187 {'c','m','d','\0'}, {'b','a','t','\0'}, {'\0'} };
1188
1189 TRACE("path=%s\n",debugstr_w(lpszPath));
1190
1191 for(i=0; lpszExtensions[i]; i++)
1192 if (!CRTDLL__wcsicmp(lpszExtension,lpszExtensions[i])) return TRUE;
1193
1194 return FALSE;
1195}
1196
1197/*************************************************************************
1198 * PathIsExeAW [SHELL32.43]
1199 */
1200BOOL WINAPI PathIsExeAW (LPCVOID path)
1201{
1202 if (VERSION_OsIsUnicode())
1203 return PathIsExeW (path);
1204 return PathIsExeA(path);
1205}
1206
1207/*************************************************************************
1208 * PathIsDirectoryA [SHLWAPI.@]
1209 */
1210BOOL WINAPI PathIsDirectoryA(LPCSTR lpszPath)
1211{
1212 HANDLE hFile;
1213 WIN32_FIND_DATAA stffile;
1214
1215 TRACE("%s\n", debugstr_a(lpszPath));
1216
1217 hFile = FindFirstFileA(lpszPath, &stffile);
1218
1219 if ( hFile != INVALID_HANDLE_VALUE )
1220 {
1221 FindClose (hFile);
1222 return (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
1223 }
1224
1225 return FALSE;
1226}
1227
1228/*************************************************************************
1229 * PathIsDirectoryW [SHLWAPI.@]
1230 */
1231BOOL WINAPI PathIsDirectoryW(LPCWSTR lpszPath)
1232{
1233 HANDLE hFile;
1234 WIN32_FIND_DATAW stffile;
1235
1236 TRACE("%s\n", debugstr_w(lpszPath));
1237
1238 hFile = FindFirstFileW(lpszPath, &stffile);
1239
1240 if ( hFile != INVALID_HANDLE_VALUE )
1241 {
1242 FindClose (hFile);
1243 return (stffile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
1244 }
1245
1246 return FALSE;
1247}
1248
1249/*************************************************************************
1250 * PathIsDirectoryAW [SHELL32.159]
1251 */
1252BOOL WINAPI PathIsDirectoryAW (LPCVOID lpszPath)
1253{
1254 if (VERSION_OsIsUnicode())
1255 return PathIsDirectoryW (lpszPath);
1256 return PathIsDirectoryA (lpszPath);
1257}
1258
1259/*************************************************************************
1260 * PathFileExistsA [SHLWAPI.@]
1261 *
1262 * NOTES
1263 * file_exists(char *fn);
1264 */
1265BOOL WINAPI PathFileExistsA(LPCSTR lpszPath)
1266{
1267 TRACE("%s\n",lpszPath);
1268 return (GetFileAttributesA(lpszPath)!=-1);
1269}
1270
1271/*************************************************************************
1272 * PathFileExistsW [SHLWAPI.@]
1273 */
1274BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
1275{
1276 TRACE("%s\n",debugstr_w(lpszPath));
1277 return (GetFileAttributesW(lpszPath)!=-1);
1278}
1279
1280/*************************************************************************
1281 * PathFileExistsAW [SHELL32.45]
1282 */
1283BOOL WINAPI PathFileExistsAW (LPCVOID lpszPath)
1284{
1285 if (VERSION_OsIsUnicode())
1286 return PathFileExistsW (lpszPath);
1287 return PathFileExistsA (lpszPath);
1288}
1289
1290/*************************************************************************
1291 * PathMatchSingleMaskA [internal]
1292 *
1293 * NOTES
1294 * internal (used by PathMatchSpec)
1295 */
1296static BOOL PathMatchSingleMaskA(LPCSTR name, LPCSTR mask)
1297{
1298 while (*name && *mask && *mask!=';')
1299 {
1300 if (*mask=='*')
1301 {
1302 do
1303 {
1304 if (PathMatchSingleMaskA(name,mask+1)) return 1; /* try substrings */
1305 } while (*name++);
1306 return 0;
1307 }
1308 if (toupper(*mask)!=toupper(*name) && *mask!='?') return 0;
1309 name++;
1310 mask++;
1311 }
1312 if (!*name)
1313 {
1314 while (*mask=='*') mask++;
1315 if (!*mask || *mask==';') return 1;
1316 }
1317 return 0;
1318}
1319
1320/*************************************************************************
1321 * PathMatchSingleMaskW [internal]
1322 */
1323static BOOL PathMatchSingleMaskW(LPCWSTR name, LPCWSTR mask)
1324{
1325 while (*name && *mask && *mask!=';')
1326 {
1327 if (*mask=='*')
1328 {
1329 do
1330 {
1331 if (PathMatchSingleMaskW(name,mask+1)) return 1; /* try substrings */
1332 } while (*name++);
1333 return 0;
1334 }
1335 if (towupper(*mask)!=towupper(*name) && *mask!='?') return 0;
1336 name++;
1337 mask++;
1338 }
1339 if (!*name)
1340 {
1341 while (*mask=='*') mask++;
1342 if (!*mask || *mask==';') return 1;
1343 }
1344 return 0;
1345}
1346/*************************************************************************
1347 * PathMatchSpecA [SHLWAPI.@]
1348 *
1349 * NOTES
1350 * used from COMDLG32
1351 */
1352BOOL WINAPI PathMatchSpecA(LPCSTR name, LPCSTR mask)
1353{
1354 TRACE("%s %s\n",name,mask);
1355
1356 if (!lstrcmpA( mask, "*.*" )) return 1; /* we don't require a period */
1357
1358 while (*mask)
1359 {
1360 if (PathMatchSingleMaskA(name,mask)) return 1; /* helper function */
1361 while (*mask && *mask!=';') mask++;
1362 if (*mask==';')
1363 {
1364 mask++;
1365 while (*mask==' ') mask++; /* masks may be separated by "; " */
1366 }
1367 }
1368 return 0;
1369}
1370
1371/*************************************************************************
1372 * PathMatchSpecW [SHLWAPI.@]
1373 */
1374BOOL WINAPI PathMatchSpecW(LPCWSTR name, LPCWSTR mask)
1375{
1376 WCHAR stemp[4];
1377 TRACE("%s %s\n",debugstr_w(name),debugstr_w(mask));
1378
1379 lstrcpyAtoW(stemp,"*.*");
1380 if (!lstrcmpW( mask, stemp )) return 1; /* we don't require a period */
1381
1382 while (*mask)
1383 {
1384 if (PathMatchSingleMaskW(name,mask)) return 1; /* helper function */
1385 while (*mask && *mask!=';') mask++;
1386 if (*mask==';')
1387 {
1388 mask++;
1389 while (*mask==' ') mask++; /* masks may be separated by "; " */
1390 }
1391 }
1392 return 0;
1393}
1394
1395/*************************************************************************
1396 * PathMatchSpecAW [SHELL32.46]
1397 */
1398BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask)
1399{
1400 if (VERSION_OsIsUnicode())
1401 return PathMatchSpecW( name, mask );
1402 return PathMatchSpecA( name, mask );
1403}
1404
1405/*************************************************************************
1406 * PathIsSameRootA [SHLWAPI.@]
1407 *
1408 * FIXME
1409 * what to do with "\path" ??
1410 */
1411BOOL WINAPI PathIsSameRootA(LPCSTR lpszPath1, LPCSTR lpszPath2)
1412{
1413 TRACE("%s %s\n", lpszPath1, lpszPath2);
1414
1415 if (PathIsRelativeA(lpszPath1) || PathIsRelativeA(lpszPath2)) return FALSE;
1416
1417 /* usual path */
1418 if ( toupper(lpszPath1[0])==toupper(lpszPath2[0]) &&
1419 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1420 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1421 return TRUE;
1422
1423 /* UNC */
1424 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1425 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1426 {
1427 int pos=2, bsfound=0;
1428 while (lpszPath1[pos] && lpszPath2[pos] &&
1429 (lpszPath1[pos] == lpszPath2[pos]))
1430 {
1431 if (lpszPath1[pos]=='\\') bsfound++;
1432 if (bsfound == 2) return TRUE;
1433 pos++;
1434 }
1435 return (lpszPath1[pos] == lpszPath2[pos]);
1436 }
1437 return FALSE;
1438}
1439
1440/*************************************************************************
1441 * PathIsSameRootW [SHLWAPI.@]
1442 */
1443BOOL WINAPI PathIsSameRootW(LPCWSTR lpszPath1, LPCWSTR lpszPath2)
1444{
1445 TRACE("%s %s\n", debugstr_w(lpszPath1), debugstr_w(lpszPath2));
1446
1447 if (PathIsRelativeW(lpszPath1) || PathIsRelativeW(lpszPath2)) return FALSE;
1448
1449 /* usual path */
1450 if ( towupper(lpszPath1[0])==towupper(lpszPath2[0]) &&
1451 lpszPath1[1]==':' && lpszPath2[1]==':' &&
1452 lpszPath1[2]=='\\' && lpszPath2[2]=='\\')
1453 return TRUE;
1454
1455 /* UNC */
1456 if (lpszPath1[0]=='\\' && lpszPath2[0]=='\\' &&
1457 lpszPath1[1]=='\\' && lpszPath2[1]=='\\')
1458 {
1459 int pos=2, bsfound=0;
1460 while (lpszPath1[pos] && lpszPath2[pos] &&
1461 (lpszPath1[pos] == lpszPath2[pos]))
1462 {
1463 if (lpszPath1[pos]=='\\') bsfound++;
1464 if (bsfound == 2) return TRUE;
1465 pos++;
1466 }
1467 return (lpszPath1[pos] == lpszPath2[pos]);
1468 }
1469 return FALSE;
1470}
1471
1472/*************************************************************************
1473 * PathIsSameRootAW [SHELL32.650]
1474 */
1475BOOL WINAPI PathIsSameRootAW(LPCVOID lpszPath1, LPCVOID lpszPath2)
1476{
1477 if (VERSION_OsIsUnicode())
1478 return PathIsSameRootW(lpszPath1, lpszPath2);
1479 return PathIsSameRootA(lpszPath1, lpszPath2);
1480}
1481
1482/*************************************************************************
1483 * PathIsURLA
1484 */
1485BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
1486{
1487 LPSTR lpstrRes;
1488 int iSize, i=0;
1489 static LPSTR SupportedProtocol[] =
1490 {"http","https","ftp","gopher","file","mailto",NULL};
1491
1492 if(!lpstrPath) return FALSE;
1493
1494 /* get protocol */
1495 lpstrRes = strchr(lpstrPath,':');
1496 if(!lpstrRes) return FALSE;
1497 iSize = lpstrRes - lpstrPath;
1498
1499 while(SupportedProtocol[i])
1500 {
1501 if (iSize == strlen(SupportedProtocol[i]))
1502 if(!strncasecmp(lpstrPath, SupportedProtocol[i], iSize));
1503 return TRUE;
1504 i++;
1505 }
1506
1507 return FALSE;
1508}
1509
1510/*************************************************************************
1511 * PathIsURLW
1512 */
1513BOOL WINAPI PathIsURLW(LPCWSTR lpstrPath)
1514{
1515 LPWSTR lpstrRes;
1516 int iSize, i=0;
1517 static WCHAR SupportedProtocol[7][7] =
1518 {{'h','t','t','p','\0'},{'h','t','t','p','s','\0'},{'f','t','p','\0'},
1519 {'g','o','p','h','e','r','\0'},{'f','i','l','e','\0'},
1520 {'m','a','i','l','t','o','\0'},{0}};
1521
1522 if(!lpstrPath) return FALSE;
1523
1524 /* get protocol */
1525 lpstrRes = CRTDLL_wcschr(lpstrPath,':');
1526 if(!lpstrRes) return FALSE;
1527 iSize = lpstrRes - lpstrPath;
1528
1529 while(SupportedProtocol[i])
1530 {
1531 if (iSize == CRTDLL_wcslen(SupportedProtocol[i]))
1532 if(!CRTDLL__wcsnicmp(lpstrPath, SupportedProtocol[i], iSize));
1533 return TRUE;
1534 i++;
1535 }
1536
1537 return FALSE;
1538}
1539
1540/*************************************************************************
1541 * IsLFNDriveA [SHELL32.119]
1542 *
1543 * NOTES
1544 * exported by ordinal Name
1545 */
1546BOOL WINAPI IsLFNDriveA(LPCSTR lpszPath)
1547{
1548 DWORD fnlen;
1549
1550 if (!GetVolumeInformationA(lpszPath,NULL,0,NULL,&fnlen,NULL,NULL,0))
1551 return FALSE;
1552 return fnlen>12;
1553}
1554
1555/*
1556 Creating Something Unique
1557*/
1558/*************************************************************************
1559 * PathMakeUniqueNameA [internal]
1560 */
1561BOOL WINAPI PathMakeUniqueNameA(
1562 LPSTR lpszBuffer,
1563 DWORD dwBuffSize,
1564 LPCSTR lpszShortName,
1565 LPCSTR lpszLongName,
1566 LPCSTR lpszPathName)
1567{
1568 FIXME("%p %lu %s %s %s stub\n",
1569 lpszBuffer, dwBuffSize, debugstr_a(lpszShortName),
1570 debugstr_a(lpszLongName), debugstr_a(lpszPathName));
1571 return TRUE;
1572}
1573
1574/*************************************************************************
1575 * PathMakeUniqueNameW [internal]
1576 */
1577BOOL WINAPI PathMakeUniqueNameW(
1578 LPWSTR lpszBuffer,
1579 DWORD dwBuffSize,
1580 LPCWSTR lpszShortName,
1581 LPCWSTR lpszLongName,
1582 LPCWSTR lpszPathName)
1583{
1584 FIXME("%p %lu %s %s %s stub\n",
1585 lpszBuffer, dwBuffSize, debugstr_w(lpszShortName),
1586 debugstr_w(lpszLongName), debugstr_w(lpszPathName));
1587 return TRUE;
1588}
1589
1590/*************************************************************************
1591 * PathMakeUniqueNameAW [SHELL32.47]
1592 */
1593BOOL WINAPI PathMakeUniqueNameAW(
1594 LPVOID lpszBuffer,
1595 DWORD dwBuffSize,
1596 LPCVOID lpszShortName,
1597 LPCVOID lpszLongName,
1598 LPCVOID lpszPathName)
1599{
1600 if (VERSION_OsIsUnicode())
1601 return PathMakeUniqueNameW(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
1602 return PathMakeUniqueNameA(lpszBuffer,dwBuffSize, lpszShortName,lpszLongName,lpszPathName);
1603}
1604
1605/*************************************************************************
1606 * PathYetAnotherMakeUniqueNameA [SHELL32.75]
1607 *
1608 * NOTES
1609 * exported by ordinal
1610 */
1611BOOL WINAPI PathYetAnotherMakeUniqueNameA(
1612 LPSTR lpszBuffer,
1613 LPCSTR lpszPathName,
1614 LPCSTR lpszShortName,
1615 LPCSTR lpszLongName)
1616{
1617 FIXME("(%p,%p, %p ,%p):stub.\n",
1618 lpszBuffer, lpszPathName, lpszShortName, lpszLongName);
1619 return TRUE;
1620}
1621
1622/*************************************************************************
1623 * PathYetAnotherMakeUniqueNameA [SHELL32.75]
1624 *
1625 * NOTES
1626 * exported by ordinal
1627 */
1628BOOL WINAPI PathYetAnotherMakeUniqueNameW(
1629 LPWSTR lpszBuffer,
1630 LPCWSTR lpszPathName,
1631 LPCWSTR lpszShortName,
1632 LPCWSTR lpszLongName)
1633{
1634 FIXME("(%p,%p, %p ,%p):stub.\n",
1635 lpszBuffer, lpszPathName, lpszShortName, lpszLongName);
1636 return TRUE;
1637}
1638
1639BOOL WINAPI PathYetAnotherMakeUniqueNameAW(
1640 LPSTR lpszBuffer,
1641 LPCSTR lpszPathName,
1642 LPCSTR lpszShortName,
1643 LPCSTR lpszLongName)
1644{
1645 if (VERSION_OsIsUnicode())
1646 return PathYetAnotherMakeUniqueNameW((LPWSTR)lpszBuffer,(LPCWSTR)lpszPathName, (LPCWSTR)lpszShortName,(LPCWSTR)lpszLongName);
1647 return PathYetAnotherMakeUniqueNameA(lpszBuffer, lpszPathName, lpszShortName,lpszLongName);
1648}
1649
1650
1651/*
1652 cleaning and resolving paths
1653 */
1654
1655/*************************************************************************
1656 * PathFindOnPathA [SHELL32.479]
1657 */
1658BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR sOtherDirs)
1659{
1660 FIXME("%s %s\n",sFile, sOtherDirs);
1661 return FALSE;
1662}
1663
1664/*************************************************************************
1665 * PathFindOnPathW [SHELL32]
1666 */
1667BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR sOtherDirs)
1668{
1669 FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
1670 return FALSE;
1671}
1672
1673/*************************************************************************
1674 * PathFindOnPathAW [SHELL32]
1675 */
1676BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs)
1677{
1678 if (VERSION_OsIsUnicode())
1679 return PathFindOnPathW(sFile, sOtherDirs);
1680 return PathFindOnPathA(sFile, sOtherDirs);
1681}
1682
1683/*************************************************************************
1684 * PathCleanupSpecA [SHELL32.171]
1685 */
1686DWORD WINAPI PathCleanupSpecA(LPSTR x, LPSTR y)
1687{
1688 FIXME("(%p %s, %p %s) stub\n",x,debugstr_a(x),y,debugstr_a(y));
1689 return TRUE;
1690}
1691
1692/*************************************************************************
1693 * PathCleanupSpecA [SHELL32]
1694 */
1695DWORD WINAPI PathCleanupSpecW(LPWSTR x, LPWSTR y)
1696{
1697 FIXME("(%p %s, %p %s) stub\n",x,debugstr_w(x),y,debugstr_w(y));
1698 return TRUE;
1699}
1700
1701/*************************************************************************
1702 * PathCleanupSpecAW [SHELL32]
1703 */
1704DWORD WINAPI PathCleanupSpecAW (LPVOID x, LPVOID y)
1705{
1706 if (VERSION_OsIsUnicode())
1707 return PathCleanupSpecW(x,y);
1708 return PathCleanupSpecA(x,y);
1709}
1710
1711/*************************************************************************
1712 * PathQualifyA [SHELL32]
1713 */
1714BOOL WINAPI PathQualifyA(LPCSTR pszPath)
1715{
1716 FIXME("%s\n",pszPath);
1717 return 0;
1718}
1719
1720/*************************************************************************
1721 * PathQualifyW [SHELL32]
1722 */
1723BOOL WINAPI PathQualifyW(LPCWSTR pszPath)
1724{
1725 FIXME("%s\n",debugstr_w(pszPath));
1726 return 0;
1727}
1728
1729/*************************************************************************
1730 * PathQualifyAW [SHELL32]
1731 */
1732BOOL WINAPI PathQualifyAW(LPCVOID pszPath)
1733{
1734 if (VERSION_OsIsUnicode())
1735 return PathQualifyW(pszPath);
1736 return PathQualifyA(pszPath);
1737}
1738
1739/*************************************************************************
1740 * PathResolveA [SHELL32.51]
1741 */
1742BOOL WINAPI PathResolveA(
1743 LPSTR lpszPath,
1744 LPCSTR *alpszPaths,
1745 DWORD dwFlags)
1746{
1747 FIXME("(%s,%p,0x%08lx),stub!\n",
1748 lpszPath, *alpszPaths, dwFlags);
1749 return 0;
1750}
1751
1752/*************************************************************************
1753 * PathResolveW [SHELL32]
1754 */
1755BOOL WINAPI PathResolveW(
1756 LPWSTR lpszPath,
1757 LPCWSTR *alpszPaths,
1758 DWORD dwFlags)
1759{
1760 FIXME("(%s,%p,0x%08lx),stub!\n",
1761 debugstr_w(lpszPath), debugstr_w(*alpszPaths), dwFlags);
1762 return 0;
1763}
1764
1765/*************************************************************************
1766 * PathResolveAW [SHELL32]
1767 */
1768BOOL WINAPI PathResolveAW(
1769 LPVOID lpszPath,
1770 LPCVOID *alpszPaths,
1771 DWORD dwFlags)
1772{
1773 if (VERSION_OsIsUnicode())
1774 return PathResolveW(lpszPath, (LPCWSTR*)alpszPaths, dwFlags);
1775 return PathResolveA(lpszPath, (LPCSTR*)alpszPaths, dwFlags);
1776}
1777
1778/*************************************************************************
1779* PathProcessCommandA [SHELL32.653]
1780*/
1781HRESULT WINAPI PathProcessCommandA (
1782 LPCSTR lpszPath,
1783 LPSTR lpszBuff,
1784 DWORD dwBuffSize,
1785 DWORD dwFlags)
1786{
1787 FIXME("%s %p 0x%04lx 0x%04lx stub\n",
1788 lpszPath, lpszBuff, dwBuffSize, dwFlags);
1789 lstrcpyA(lpszBuff, lpszPath);
1790 return 0;
1791}
1792
1793/*************************************************************************
1794* PathProcessCommandW
1795*/
1796HRESULT WINAPI PathProcessCommandW (
1797 LPCWSTR lpszPath,
1798 LPWSTR lpszBuff,
1799 DWORD dwBuffSize,
1800 DWORD dwFlags)
1801{
1802 FIXME("(%s, %p, 0x%04lx, 0x%04lx) stub\n",
1803 debugstr_w(lpszPath), lpszBuff, dwBuffSize, dwFlags);
1804 lstrcpyW(lpszBuff, lpszPath);
1805 return 0;
1806}
1807
1808/*************************************************************************
1809* PathProcessCommandAW
1810*/
1811HRESULT WINAPI PathProcessCommandAW (
1812 LPCVOID lpszPath,
1813 LPVOID lpszBuff,
1814 DWORD dwBuffSize,
1815 DWORD dwFlags)
1816{
1817 if (VERSION_OsIsUnicode())
1818 return PathProcessCommandW(lpszPath, lpszBuff, dwBuffSize, dwFlags);
1819 return PathProcessCommandA(lpszPath, lpszBuff, dwBuffSize, dwFlags);
1820}
1821
1822/*
1823 special
1824*/
1825
1826/*************************************************************************
1827 * PathSetDlgItemPathA
1828 *
1829 * NOTES
1830 * use PathCompactPath to make sure, the path fits into the control
1831 */
1832BOOL WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR pszPath)
1833{ TRACE("%x %x %s\n",hDlg, id, pszPath);
1834 return SetDlgItemTextA(hDlg, id, pszPath);
1835}
1836
1837/*************************************************************************
1838 * PathSetDlgItemPathW
1839 */
1840BOOL WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR pszPath)
1841{ TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
1842 return SetDlgItemTextW(hDlg, id, pszPath);
1843}
1844
1845/*************************************************************************
1846 * PathSetDlgItemPathAW
1847 */
1848BOOL WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath)
1849{ if (VERSION_OsIsUnicode())
1850 return PathSetDlgItemPathW(hDlg, id, pszPath);
1851 return PathSetDlgItemPathA(hDlg, id, pszPath);
1852}
1853
1854
1855/*************************************************************************
1856 * SHGetSpecialFolderPathA [SHELL32.175]
1857 *
1858 * converts csidl to path
1859 *
1860 */
1861
1862static char * szSHFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
1863static char * szSHUserFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders";
1864
1865BOOL WINAPI SHGetSpecialFolderPathA (
1866 HWND hwndOwner,
1867 LPSTR szPath,
1868 DWORD csidl,
1869 BOOL bCreate)
1870{
1871 CHAR szValueName[MAX_PATH], szDefaultPath[MAX_PATH];
1872 HKEY hRootKey, hKey;
1873 BOOL bRelative = TRUE;
1874 DWORD dwType, dwDisp, dwPathLen = MAX_PATH;
1875
1876 TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
1877
1878 /* build default values */
1879 switch(csidl)
1880 {
1881 case CSIDL_APPDATA:
1882 hRootKey = HKEY_CURRENT_USER;
1883 strcpy (szValueName, "AppData");
1884 strcpy (szDefaultPath, "AppData");
1885 break;
1886
1887 case CSIDL_COOKIES:
1888 hRootKey = HKEY_CURRENT_USER;
1889 strcpy (szValueName, "Cookies");
1890 strcpy(szDefaultPath, "Cookies");
1891 break;
1892
1893 case CSIDL_DESKTOPDIRECTORY:
1894 hRootKey = HKEY_CURRENT_USER;
1895 strcpy(szValueName, "Desktop");
1896 strcpy(szDefaultPath, "Desktop");
1897 break;
1898
1899 case CSIDL_COMMON_DESKTOPDIRECTORY:
1900 hRootKey = HKEY_LOCAL_MACHINE;
1901 strcpy(szValueName, "Common Desktop");
1902 strcpy(szDefaultPath, "Desktop");
1903 break;
1904
1905 case CSIDL_FAVORITES:
1906 hRootKey = HKEY_CURRENT_USER;
1907 strcpy(szValueName, "Favorites");
1908 strcpy(szDefaultPath, "Favorites");
1909 break;
1910
1911 case CSIDL_FONTS:
1912 hRootKey = HKEY_CURRENT_USER;
1913 strcpy(szValueName, "Fonts");
1914 strcpy(szDefaultPath, "Fonts");
1915 break;
1916
1917 case CSIDL_HISTORY:
1918 hRootKey = HKEY_CURRENT_USER;
1919 strcpy(szValueName, "History");
1920 strcpy(szDefaultPath, "History");
1921 break;
1922
1923 case CSIDL_NETHOOD:
1924 hRootKey = HKEY_CURRENT_USER;
1925 strcpy(szValueName, "NetHood");
1926 strcpy(szDefaultPath, "NetHood");
1927 break;
1928
1929 case CSIDL_INTERNET_CACHE:
1930 hRootKey = HKEY_CURRENT_USER;
1931 strcpy(szValueName, "Cache");
1932 strcpy(szDefaultPath, "Temporary Internet Files");
1933 break;
1934
1935 case CSIDL_PERSONAL:
1936 hRootKey = HKEY_CURRENT_USER;
1937 strcpy(szValueName, "Personal");
1938 strcpy(szDefaultPath, "My Own Files");
1939 bRelative = FALSE;
1940 break;
1941
1942 case CSIDL_PRINTHOOD:
1943 hRootKey = HKEY_CURRENT_USER;
1944 strcpy(szValueName, "PrintHood");
1945 strcpy(szDefaultPath, "PrintHood");
1946 break;
1947
1948 case CSIDL_PROGRAMS:
1949 hRootKey = HKEY_CURRENT_USER;
1950 strcpy(szValueName, "Programs");
1951 strcpy(szDefaultPath, "Start Menu\\Programs");
1952 break;
1953
1954 case CSIDL_COMMON_PROGRAMS:
1955 hRootKey = HKEY_LOCAL_MACHINE;
1956 strcpy(szValueName, "Common Programs");
1957 strcpy(szDefaultPath, "");
1958 break;
1959
1960 case CSIDL_RECENT:
1961 hRootKey = HKEY_CURRENT_USER;
1962 strcpy(szValueName, "Recent");
1963 strcpy(szDefaultPath, "Recent");
1964 break;
1965
1966 case CSIDL_SENDTO:
1967 hRootKey = HKEY_CURRENT_USER;
1968 strcpy(szValueName, "SendTo");
1969 strcpy(szDefaultPath, "SendTo");
1970 break;
1971
1972 case CSIDL_STARTMENU:
1973 hRootKey = HKEY_CURRENT_USER;
1974 strcpy(szValueName, "Start Menu");
1975 strcpy(szDefaultPath, "Start Menu");
1976 break;
1977
1978 case CSIDL_COMMON_STARTMENU:
1979 hRootKey = HKEY_LOCAL_MACHINE;
1980 strcpy(szValueName, "Common StartMenu"); //TODO: Start Menu?
1981 strcpy(szDefaultPath, "Start Menu");
1982 break;
1983
1984 case CSIDL_STARTUP:
1985 hRootKey = HKEY_CURRENT_USER;
1986 strcpy(szValueName, "Startup");
1987 strcpy(szDefaultPath, "Start Menu\\Programs\\Startup");
1988 break;
1989
1990 case CSIDL_COMMON_STARTUP:
1991 hRootKey = HKEY_LOCAL_MACHINE;
1992 strcpy(szValueName, "Common Startup");
1993 strcpy(szDefaultPath, "Start Menu\\Programs\\Startup");
1994 break;
1995
1996 case CSIDL_TEMPLATES:
1997 hRootKey = HKEY_CURRENT_USER;
1998 strcpy(szValueName, "Templates");
1999 strcpy(szDefaultPath, "ShellNew");
2000 break;
2001
2002 default:
2003 ERR("folder unknown or not allowed\n");
2004 return FALSE;
2005 }
2006
2007 /* user shell folders */
2008 if (RegCreateKeyExA(hRootKey,szSHUserFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
2009
2010 if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
2011 {
2012 RegCloseKey(hKey);
2013
2014 /* shell folders */
2015 if (RegCreateKeyExA(hRootKey,szSHFolders,0,NULL,0,KEY_ALL_ACCESS,NULL,&hKey,&dwDisp)) return FALSE;
2016
2017 if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
2018 {
2019
2020 /* value not existing */
2021 if (bRelative)
2022 {
2023 GetWindowsDirectoryA(szPath, MAX_PATH);
2024 PathAddBackslashA(szPath);
2025 strcat(szPath, szDefaultPath);
2026 }
2027 else
2028 {
2029 strcpy(szPath, "C:\\"); /* fixme ??? */
2030 strcat(szPath, szDefaultPath);
2031 }
2032 RegSetValueExA(hKey,szValueName,0,REG_SZ,(LPBYTE)szPath,strlen(szPath)+1);
2033 }
2034 }
2035 RegCloseKey(hKey);
2036
2037 if (bCreate && CreateDirectoryA(szPath,NULL))
2038 {
2039 MESSAGE("Created not existing system directory '%s'\n", szPath);
2040 }
2041
2042 return TRUE;
2043}
2044
2045/*************************************************************************
2046 * SHGetSpecialFolderPathW
2047 */
2048BOOL WINAPI SHGetSpecialFolderPathW (
2049 HWND hwndOwner,
2050 LPWSTR szPath,
2051 DWORD csidl,
2052 BOOL bCreate)
2053{
2054 char szTemp[MAX_PATH];
2055
2056 if (SHGetSpecialFolderPathA(hwndOwner, szTemp, csidl, bCreate))
2057 {
2058 lstrcpynAtoW(szPath, szTemp, MAX_PATH);
2059 }
2060
2061 TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
2062
2063 return TRUE;
2064}
2065
2066/*************************************************************************
2067 * SHGetSpecialFolderPathAW
2068 */
2069BOOL WINAPI SHGetSpecialFolderPathAW (
2070 HWND hwndOwner,
2071 LPVOID szPath,
2072 DWORD csidl,
2073 BOOL bCreate)
2074
2075{
2076 if (VERSION_OsIsUnicode())
2077 return SHGetSpecialFolderPathW (hwndOwner, szPath, csidl, bCreate);
2078 return SHGetSpecialFolderPathA (hwndOwner, szPath, csidl, bCreate);
2079}
2080
2081/*************************************************************************
2082 * PathCanonicalizeA
2083 *
2084 * FIXME
2085 * returnvalue
2086 */
2087
2088BOOL WINAPI PathCanonicalizeA(LPSTR pszBuf, LPCSTR pszPath)
2089{
2090 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = strlen(pszPath);
2091 BOOL bModifyed = FALSE;
2092
2093 TRACE("%p %s\n", pszBuf, pszPath);
2094
2095 pszBuf[OffsetDst]='\0';
2096
2097 /* keep the root of the path */
2098 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
2099 {
2100 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2101 }
2102 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
2103 {
2104 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2105 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2106 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
2107 {
2108 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2109 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
2110 {
2111 /* C:\. */
2112 OffsetSrc++; LenSrc--; bModifyed = TRUE;
2113 }
2114 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
2115 {
2116 /* C:\.. */
2117 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
2118 }
2119 }
2120 }
2121
2122 /* ".\" at the beginning of the path */
2123 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
2124 {
2125 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
2126 }
2127
2128 while ( LenSrc )
2129 {
2130 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
2131 {
2132 /* "\.." found, go one deeper */
2133 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
2134 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
2135 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
2136 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
2137 }
2138 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
2139 {
2140 /* "\." found, skip it */
2141 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
2142 }
2143 else
2144 {
2145 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
2146 }
2147 }
2148 pszBuf[OffsetDst] = '\0';
2149 TRACE("-- %s %u\n", pszBuf, bModifyed);
2150 return bModifyed;
2151}
2152
2153
2154/*************************************************************************
2155 * PathCanonicalizeW
2156 *
2157 * FIXME
2158 * returnvalue
2159 */
2160BOOL WINAPI PathCanonicalizeW(LPWSTR pszBuf, LPCWSTR pszPath)
2161{
2162 int OffsetMin = 0, OffsetSrc = 0, OffsetDst = 0, LenSrc = lstrlenW(pszPath);
2163 BOOL bModifyed = FALSE;
2164
2165 TRACE("%p %s\n", pszBuf, debugstr_w(pszPath));
2166
2167 pszBuf[OffsetDst]='\0';
2168
2169 /* keep the root of the path */
2170 if( LenSrc && (pszPath[OffsetSrc]=='\\'))
2171 {
2172 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2173 }
2174 else if ( (LenSrc >= 2) && (pszPath[OffsetSrc+1] == ':'))
2175 {
2176 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2177 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2178 if (LenSrc && (pszPath[OffsetSrc] == '\\'))
2179 {
2180 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; OffsetMin++; LenSrc--;
2181 if (LenSrc == 1 && pszPath[OffsetSrc]=='.')
2182 {
2183 /* C:\. */
2184 OffsetSrc++; LenSrc--; bModifyed = TRUE;
2185 }
2186 else if (LenSrc == 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='.')
2187 {
2188 /* C:\.. */
2189 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
2190 }
2191 }
2192 }
2193
2194 /* ".\" at the beginning of the path */
2195 if (LenSrc >= 2 && pszPath[OffsetSrc]=='.' && pszPath[OffsetSrc+1]=='\\')
2196 {
2197 OffsetSrc+=2; LenSrc-=2; bModifyed = TRUE;
2198 }
2199
2200 while ( LenSrc )
2201 {
2202 if((LenSrc>=3) && (pszPath[OffsetSrc]=='\\') && (pszPath[OffsetSrc+1]=='.') && (pszPath[OffsetSrc+2]=='.'))
2203 {
2204 /* "\.." found, go one deeper */
2205 while((OffsetDst > OffsetMin) && (pszBuf[OffsetDst]!='\\')) OffsetDst--;
2206 OffsetSrc += 3; LenSrc -= 3; bModifyed = TRUE;
2207 if(OffsetDst == OffsetMin && pszPath[OffsetSrc]=='\\') OffsetSrc++;
2208 pszBuf[OffsetDst] = '\0'; /* important for \..\.. */
2209 }
2210 else if(LenSrc>=2 && pszPath[OffsetSrc]=='\\' && pszPath[OffsetSrc+1]=='.' )
2211 {
2212 /* "\." found, skip it */
2213 OffsetSrc += 2; LenSrc-=2; bModifyed = TRUE;
2214 }
2215 else
2216 {
2217 pszBuf[OffsetDst++] = pszPath[OffsetSrc++]; LenSrc--;
2218 }
2219 }
2220 pszBuf[OffsetDst] = '\0';
2221 TRACE("-- %s %u\n", debugstr_w(pszBuf), bModifyed);
2222 return bModifyed;
2223}
2224
2225/*************************************************************************
2226 * PathFindNextComponentA
2227 */
2228LPSTR WINAPI PathFindNextComponentA(LPCSTR pszPath)
2229{
2230 while( *pszPath )
2231 {
2232 if(*pszPath++=='\\')
2233 return (LPSTR)((*pszPath)? pszPath : NULL);
2234 }
2235 return NULL;
2236}
2237
2238/*************************************************************************
2239 * PathFindNextComponentW
2240 */
2241LPWSTR WINAPI PathFindNextComponentW(LPCWSTR pszPath)
2242{
2243 while( *pszPath )
2244 {
2245 if(*pszPath++=='\\')
2246 return (LPWSTR)((*pszPath)? pszPath : NULL);
2247 }
2248 return NULL;
2249}
2250
Note: See TracBrowser for help on using the repository browser.