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

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

compile errors fixed

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