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

Last change on this file since 3698 was 3698, checked in by achimha, 25 years ago

corrected prototype

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