Fixed some issues reported by winapi_check.
[wine.git] / dlls / shell32 / shellpath.c
blobab96739faa081cb40ae46c61766188c5e21884e6
1 /*
2 * Path Functions
4 * Many of this functions are in SHLWAPI.DLL also
6 */
7 #include <string.h>
8 #include <ctype.h>
9 #include "debugtools.h"
10 #include "winnls.h"
11 #include "winversion.h"
12 #include "winreg.h"
13 #include "crtdll.h"
14 #include "tchar.h"
16 #include "shlobj.h"
17 #include "shell32_main.h"
18 #include "windef.h"
19 #include "options.h"
21 DEFAULT_DEBUG_CHANNEL(shell)
23 /* Supported protocols for PathIsURL */
24 LPSTR SupportedProtocol[] = {"http","https","ftp","gopher","file","mailto",""};
26 /*************************************************************************
27 * PathIsRootA
29 BOOL WINAPI PathIsRootA(LPCSTR x)
30 { TRACE("%s\n",x);
31 if (*(x+1)==':' && *(x+2)=='\\') /* "X:\" */
32 return 1;
33 if (*x=='\\') /* "\" */
34 return 0;
35 if (x[0]=='\\' && x[1]=='\\') /* UNC "\\<xx>\" */
36 { int foundbackslash = 0;
37 x=x+2;
38 while (*x)
39 { if (*x++=='\\')
40 foundbackslash++;
42 if (foundbackslash<=1) /* max 1 \ more ... */
43 return 1;
45 return 0;
48 /*************************************************************************
49 * PathIsRootW
51 BOOL WINAPI PathIsRootW(LPCWSTR x)
52 { TRACE("%s\n",debugstr_w(x));
53 if (*(x+1)==':' && *(x+2)=='\\') /* "X:\" */
54 return 1;
55 if (*x == (WCHAR) '\\') /* "\" */
56 return 0;
57 if (x[0]==(WCHAR)'\\' && x[1]==(WCHAR)'\\') /* UNC "\\<xx>\" */
58 { int foundbackslash = 0;
59 x=x+2;
60 while (*x)
61 { if (*x++==(WCHAR)'\\')
62 foundbackslash++;
64 if (foundbackslash<=1) /* max 1 \ more ... */
65 return 1;
67 return 0;
70 /*************************************************************************
71 * PathIsRoot [SHELL32.29]
73 BOOL WINAPI PathIsRootAW(LPCVOID x)
74 { if (VERSION_OsIsUnicode())
75 return PathIsRootW(x);
76 return PathIsRootA(x);
80 /*************************************************************************
81 * PathBuildRootA [SHELL32.30]
83 LPSTR WINAPI PathBuildRootA(LPSTR root,BYTE drive) {
84 TRACE("%p %i\n",root, drive);
85 strcpy(root,"A:\\");
86 root[0]+=drive;
87 return root;
90 /*************************************************************************
91 * PathFindExtensionA
93 * NOTES
94 * returns pointer to last . in last pathcomponent or at \0.
96 LPCSTR WINAPI PathFindExtensionA(LPCSTR path)
97 { LPCSTR lastpoint = NULL;
98 TRACE("%p %s\n",path,path);
99 while (*path)
100 { if (*path=='\\'||*path==' ')
101 lastpoint=NULL;
102 if (*path=='.')
103 lastpoint=path;
104 path++;
106 return lastpoint?lastpoint:path;
109 /*************************************************************************
110 * PathFindExtensionW
112 * NOTES
113 * returns pointer to last . in last pathcomponent or at \0.
115 LPCWSTR WINAPI PathFindExtensionW(LPCWSTR path)
116 { LPCWSTR lastpoint = NULL;
117 TRACE("(%p %s)\n",path,debugstr_w(path));
118 while (*path)
119 { if (*path==(WCHAR)'\\'||*path==(WCHAR)' ')
120 lastpoint=NULL;
121 if (*path==(WCHAR)'.')
122 lastpoint=path;
123 path++;
125 return lastpoint?lastpoint:path;
128 /*************************************************************************
129 * PathFindExtension [SHELL32.31]
131 * NOTES
132 * returns pointer to last . in last pathcomponent or at \0.
134 LPCVOID WINAPI PathFindExtensionAW(LPCVOID path)
135 { if (VERSION_OsIsUnicode())
136 return PathFindExtensionW(path);
137 return PathFindExtensionA(path);
141 /*************************************************************************
142 * PathAddBackslashA
144 * NOTES
145 * append \ if there is none
147 LPSTR WINAPI PathAddBackslashA(LPSTR path)
148 { int len;
149 TRACE("%p->%s\n",path,path);
151 len = strlen(path);
152 if (len && path[len-1]!='\\')
153 { path[len] = '\\';
154 path[len+1]= 0x00;
155 return path+len+1;
157 return path+len;
160 /*************************************************************************
161 * PathAddBackslashW
163 * NOTES
164 * append \ if there is none
166 LPWSTR WINAPI PathAddBackslashW(LPWSTR path)
167 { int len;
168 TRACE("%p->%s\n",path,debugstr_w(path));
170 len = CRTDLL_wcslen(path);
171 if (len && path[len-1]!=(WCHAR)'\\')
172 { path[len] = (WCHAR)'\\';
173 path[len+1]= 0x00;
174 return path+len+1;
176 return path+len;
179 /*************************************************************************
180 * PathAddBackslash [SHELL32.32]
182 * NOTES
183 * append \ if there is none
185 LPVOID WINAPI PathAddBackslashAW(LPVOID path)
186 { if(VERSION_OsIsUnicode())
187 return PathAddBackslashW(path);
188 return PathAddBackslashA(path);
191 /*************************************************************************
192 * PathRemoveBlanksA
194 * NOTES
195 * remove spaces from beginning and end of passed string
197 LPSTR WINAPI PathRemoveBlanksA(LPSTR str)
198 { LPSTR x = str;
199 TRACE("%s\n",str);
200 while (*x==' ') x++;
201 if (x!=str)
202 strcpy(str,x);
203 if (!*str)
204 return str;
205 x=str+strlen(str)-1;
206 while (*x==' ')
207 x--;
208 if (*x==' ')
209 *x='\0';
210 return x;
213 /*************************************************************************
214 * PathRemoveBlanksW
216 * NOTES
217 * remove spaces from beginning and end of passed string
219 LPWSTR WINAPI PathRemoveBlanksW(LPWSTR str)
220 { LPWSTR x = str;
221 TRACE("%s\n",debugstr_w(str));
222 while (*x==' ') x++;
223 if (x!=str)
224 CRTDLL_wcscpy(str,x);
225 if (!*str)
226 return str;
227 x=str+CRTDLL_wcslen(str)-1;
228 while (*x==' ')
229 x--;
230 if (*x==' ')
231 *x='\0';
232 return x;
235 /*************************************************************************
236 * PathRemoveBlanks [SHELL32.33]
238 * NOTES
239 * remove spaces from beginning and end of passed string
241 LPVOID WINAPI PathRemoveBlanksAW(LPVOID str)
242 { if(VERSION_OsIsUnicode())
243 return PathRemoveBlanksW(str);
244 return PathRemoveBlanksA(str);
247 /*************************************************************************
248 * PathFindFilenameA
250 * NOTES
251 * basename(char *fn);
253 LPCSTR WINAPI PathFindFilenameA(LPCSTR aptr)
254 { LPCSTR aslash;
255 aslash = aptr;
257 TRACE("%s\n",aslash);
258 while (aptr[0])
259 { if (((aptr[0]=='\\') || (aptr[0]==':')) && aptr[1] && aptr[1]!='\\')
260 aslash = aptr+1;
261 aptr++;
263 return aslash;
267 /*************************************************************************
268 * PathFindFilenameW
270 * NOTES
271 * basename(char *fn);
273 LPCWSTR WINAPI PathFindFilenameW(LPCWSTR wptr)
274 { LPCWSTR wslash;
275 wslash = wptr;
277 TRACE("%s\n",debugstr_w(wslash));
278 while (wptr[0])
279 { if (((wptr[0]=='\\') || (wptr[0]==':')) && wptr[1] && wptr[1]!='\\')
280 wslash = wptr+1;
281 wptr++;
283 return wslash;
286 /*************************************************************************
287 * PathFindFilename [SHELL32.34]
289 * NOTES
290 * basename(char *fn);
292 LPCVOID WINAPI PathFindFilenameAW(LPCVOID fn)
294 if(VERSION_OsIsUnicode())
295 return PathFindFilenameW(fn);
296 return PathFindFilenameA(fn);
299 /*************************************************************************
300 * PathRemoveFileSpecA [SHELL32.35]
302 * NOTES
303 * bool getpath(char *pathname); truncates passed argument to a valid path
304 * returns if the string was modified or not.
305 * "\foo\xx\foo"-> "\foo\xx"
306 * "\" -> "\"
307 * "a:\foo" -> "a:\"
309 DWORD WINAPI PathRemoveFileSpecA(LPSTR fn) {
310 LPSTR x,cutplace;
311 TRACE("%s\n",fn);
312 if (!fn[0])
313 return 0;
314 x=fn;
315 cutplace = fn;
316 while (*x) {
317 if (*x=='\\') {
318 cutplace=x++;
319 continue;
321 if (*x==':') {
322 x++;
323 if (*x=='\\')
324 cutplace=++x;
325 continue; /* already x++ed */
327 x++;
329 if (!*cutplace)
330 return 0;
331 if (cutplace==fn) {
332 if (fn[0]=='\\') {
333 if (!fn[1])
334 return 0;
335 fn[0]='\0';
336 return 1;
339 *cutplace='\0';
340 return 1;
343 /*************************************************************************
344 * PathAppendA [SHELL32.36]
346 * NOTES
347 * concat_paths(char*target,const char*add);
348 * concats "target\\add" and writes them to target
350 LPSTR WINAPI PathAppendA(LPSTR x1,LPSTR x2) {
351 TRACE("%s %s\n",x1,x2);
352 while (x2[0]=='\\') x2++;
353 return PathCombineA(x1,x1,x2);
356 /*************************************************************************
357 * PathCombineA
359 * NOTES
360 * if lpszFile='.' skip it
361 * szDest can be equal to lpszFile. Thats why we use sTemp
363 LPSTR WINAPI PathCombineA(LPSTR szDest, LPCSTR lpszDir, LPCSTR lpszFile)
364 { char sTemp[MAX_PATH];
365 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
368 if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) )
369 { strcpy(szDest,lpszDir);
370 return szDest;
373 /* if lpszFile is a complete path don't care about lpszDir */
374 if (PathIsRootA(lpszFile))
375 { strcpy(szDest,lpszFile);
377 else
378 { strcpy(sTemp,lpszDir);
379 PathAddBackslashA(sTemp);
380 strcat(sTemp,lpszFile);
381 strcpy(szDest,sTemp);
383 return szDest;
386 /*************************************************************************
387 * PathCombineW
389 * NOTES
390 * if lpszFile='.' skip it
391 * szDest can be equal to lpszFile. Thats why we use sTemp
393 LPWSTR WINAPI PathCombineW(LPWSTR szDest, LPCWSTR lpszDir, LPCWSTR lpszFile)
394 { WCHAR sTemp[MAX_PATH];
395 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
396 lpszFile, debugstr_w(lpszFile));
399 if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) )
400 { CRTDLL_wcscpy(szDest,lpszDir);
401 return szDest;
404 /* if lpszFile is a complete path don't care about lpszDir */
405 if (PathIsRootW(lpszFile))
406 { CRTDLL_wcscpy(szDest,lpszFile);
408 else
409 { CRTDLL_wcscpy(sTemp,lpszDir);
410 PathAddBackslashW(sTemp);
411 CRTDLL_wcscat(sTemp,lpszFile);
412 CRTDLL_wcscpy(szDest,sTemp);
414 return szDest;
417 /*************************************************************************
418 * PathCombine [SHELL32.37]
420 * NOTES
421 * if lpszFile='.' skip it
422 * szDest can be equal to lpszFile. Thats why we use sTemp
424 LPVOID WINAPI PathCombineAW(LPVOID szDest, LPCVOID lpszDir, LPCVOID lpszFile)
425 { if (VERSION_OsIsUnicode())
426 return PathCombineW( szDest, lpszDir, lpszFile );
427 return PathCombineA( szDest, lpszDir, lpszFile );
430 /*************************************************************************
431 * PathIsUNCA
433 * NOTES
434 * PathIsUNC(char*path);
436 BOOL WINAPI PathIsUNCA(LPCSTR path)
437 { TRACE("%s\n",path);
439 if ((path[0]=='\\') && (path[1]=='\\'))
440 return TRUE;
441 return FALSE;
444 /*************************************************************************
445 * PathIsUNCW
447 * NOTES
448 * PathIsUNC(char*path);
450 BOOL WINAPI PathIsUNCW(LPCWSTR path)
451 { TRACE("%s\n",debugstr_w(path));
453 if ((path[0]=='\\') && (path[1]=='\\'))
454 return TRUE;
455 return FALSE;
458 /*************************************************************************
459 * PathIsUNC [SHELL32.39]
461 * NOTES
462 * PathIsUNC(char*path);
464 BOOL WINAPI PathIsUNCAW (LPCVOID path)
465 { if (VERSION_OsIsUnicode())
466 return PathIsUNCW( path );
467 return PathIsUNCA( path );
470 /*************************************************************************
471 * PathIsRelativeA
474 BOOL WINAPI PathIsRelativeA (LPCSTR path)
475 { TRACE("path=%s\n",path);
477 if (path && (path[0]!='\\' && path[1]==':'))
478 return TRUE;
479 return FALSE;
482 /*************************************************************************
483 * PathIsRelativeW
486 BOOL WINAPI PathIsRelativeW (LPCWSTR path)
487 { TRACE("path=%s\n",debugstr_w(path));
489 if (path && (path[0]!='\\' && path[1]==':'))
490 return TRUE;
491 return FALSE;
494 /*************************************************************************
495 * PathIsRelative [SHELL32.40]
498 BOOL WINAPI PathIsRelativeAW (LPCVOID path)
499 { if (VERSION_OsIsUnicode())
500 return PathIsRelativeW( path );
501 return PathIsRelativeA( path );
504 /*************************************************************************
505 * PathIsExeA
508 BOOL WINAPI PathIsExeA (LPCSTR path)
509 { FIXME("path=%s\n",path);
510 return FALSE;
513 /*************************************************************************
514 * PathIsExeW
517 BOOL WINAPI PathIsExeW (LPCWSTR path)
518 { FIXME("path=%s\n",debugstr_w(path));
519 return FALSE;
522 /*************************************************************************
523 * PathIsExe [SHELL32.43]
526 BOOL WINAPI PathIsExeAW (LPCVOID path)
527 { if (VERSION_OsIsUnicode())
528 return PathIsExeW (path);
529 return PathIsExeA(path);
532 /*************************************************************************
533 * PathFileExistsA [SHELL32.45]
535 * NOTES
536 * file_exists(char *fn);
538 BOOL WINAPI PathFileExistsA(LPSTR fn) {
539 TRACE("%s\n",fn);
540 if (GetFileAttributesA(fn)==-1)
541 return FALSE;
542 else
543 return TRUE;
545 /*************************************************************************
546 * PathMatchSingleMask
548 * NOTES
549 * internal (used by PathMatchSpec)
551 static BOOL PathMatchSingleMaskA(LPCSTR name, LPCSTR mask)
553 while (*name && *mask && *mask!=';') {
554 if (*mask=='*') {
555 do {
556 if (PathMatchSingleMaskA(name,mask+1)) return 1; /* try substrings */
557 } while (*name++);
558 return 0;
560 if (toupper(*mask)!=toupper(*name) && *mask!='?') return 0;
561 name++;
562 mask++;
564 if (!*name) {
565 while (*mask=='*') mask++;
566 if (!*mask || *mask==';') return 1;
568 return 0;
570 static BOOL PathMatchSingleMaskW(LPCWSTR name, LPCWSTR mask)
572 while (*name && *mask && *mask!=';') {
573 if (*mask=='*') {
574 do {
575 if (PathMatchSingleMaskW(name,mask+1)) return 1; /* try substrings */
576 } while (*name++);
577 return 0;
579 if (towupper(*mask)!=towupper(*name) && *mask!='?') return 0;
580 name++;
581 mask++;
583 if (!*name) {
584 while (*mask=='*') mask++;
585 if (!*mask || *mask==';') return 1;
587 return 0;
590 /*************************************************************************
591 * PathMatchSpecA
593 * NOTES
594 * used from COMDLG32
596 BOOL WINAPI PathMatchSpecA(LPCSTR name, LPCSTR mask)
598 TRACE("%s %s\n",name,mask);
600 if (!lstrcmpA( mask, "*.*" )) return 1; /* we don't require a period */
602 while (*mask) {
603 if (PathMatchSingleMaskA(name,mask)) return 1; /* helper function */
604 while (*mask && *mask!=';') mask++;
605 if (*mask==';') {
606 mask++;
607 while (*mask==' ') mask++; /* masks may be separated by "; " */
610 return 0;
613 /*************************************************************************
614 * PathMatchSpecW
616 * NOTES
617 * used from COMDLG32
619 BOOL WINAPI PathMatchSpecW(LPCWSTR name, LPCWSTR mask)
621 WCHAR stemp[4];
622 TRACE("%s %s\n",debugstr_w(name),debugstr_w(mask));
624 lstrcpyAtoW(stemp,"*.*");
625 if (!lstrcmpW( mask, stemp )) return 1; /* we don't require a period */
627 while (*mask) {
628 if (PathMatchSingleMaskW(name,mask)) return 1; /* helper function */
629 while (*mask && *mask!=';') mask++;
630 if (*mask==';') {
631 mask++;
632 while (*mask==' ') mask++; /* masks may be separated by "; " */
635 return 0;
638 /*************************************************************************
639 * PathMatchSpec [SHELL32.46]
641 * NOTES
642 * used from COMDLG32
644 BOOL WINAPI PathMatchSpecAW(LPVOID name, LPVOID mask)
645 { if (VERSION_OsIsUnicode())
646 return PathMatchSpecW( name, mask );
647 return PathMatchSpecA( name, mask );
649 /*************************************************************************
650 * PathSetDlgItemPathA
651 * NOTES
652 * use PathCompactPath to make sure, the path fits into the control
654 BOOL WINAPI PathSetDlgItemPathA(HWND hDlg, int id, LPCSTR pszPath)
655 { TRACE("%x %x %s\n",hDlg, id, pszPath);
656 return SetDlgItemTextA(hDlg, id, pszPath);
659 /*************************************************************************
660 * PathSetDlgItemPathW
661 * NOTES
662 * use PathCompactPath to make sure, the path fits into the control
664 BOOL WINAPI PathSetDlgItemPathW(HWND hDlg, int id, LPCWSTR pszPath)
665 { TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
666 return SetDlgItemTextW(hDlg, id, pszPath);
669 /*************************************************************************
670 * PathSetDlgItemPath [SHELL32.48]
671 * NOTES
672 * use PathCompactPath to make sure, the path fits into the control
674 BOOL WINAPI PathSetDlgItemPathAW(HWND hDlg, int id, LPCVOID pszPath)
675 { if (VERSION_OsIsUnicode())
676 return PathSetDlgItemPathW(hDlg, id, pszPath);
677 return PathSetDlgItemPathA(hDlg, id, pszPath);
680 /*************************************************************************
681 * PathQualifyA
683 BOOL WINAPI PathQualifyA(LPCSTR pszPath)
684 { FIXME("%s\n",pszPath);
685 return 0;
688 /*************************************************************************
689 * PathQualifyW
691 BOOL WINAPI PathQualifyW(LPCWSTR pszPath)
692 { FIXME("%s\n",debugstr_w(pszPath));
693 return 0;
696 /*************************************************************************
697 * PathQualify [SHELL32.49]
699 BOOL WINAPI PathQualifyAW(LPCVOID pszPath)
700 { if (VERSION_OsIsUnicode())
701 return PathQualifyW(pszPath);
702 return PathQualifyA(pszPath);
705 /*************************************************************************
706 * PathResolve [SHELL32.51]
708 DWORD WINAPI PathResolve(LPCSTR s,DWORD x2,DWORD x3) {
709 FIXME("(%s,0x%08lx,0x%08lx),stub!\n",s,x2,x3);
710 return 0;
713 /*************************************************************************
714 * PathGetArgsA
716 * NOTES
717 * look for next arg in string. handle "quoted" strings
718 * returns pointer to argument *AFTER* the space. Or to the \0.
720 LPCSTR WINAPI PathGetArgsA(LPCSTR cmdline)
721 { BOOL qflag = FALSE;
723 TRACE("%s\n",cmdline);
725 while (*cmdline)
726 { if ((*cmdline==' ') && !qflag)
727 return cmdline+1;
728 if (*cmdline=='"')
729 qflag=!qflag;
730 cmdline++;
732 return cmdline;
736 /*************************************************************************
737 * PathGetArgsW
739 * NOTES
740 * look for next arg in string. handle "quoted" strings
741 * returns pointer to argument *AFTER* the space. Or to the \0.
743 LPCWSTR WINAPI PathGetArgsW(LPCWSTR cmdline)
744 { BOOL qflag = FALSE;
746 TRACE("%s\n",debugstr_w(cmdline));
748 while (*cmdline)
749 { if ((*cmdline==' ') && !qflag)
750 return cmdline+1;
751 if (*cmdline=='"')
752 qflag=!qflag;
753 cmdline++;
755 return cmdline;
758 /*************************************************************************
759 * PathGetArgs [SHELL32.52]
761 * NOTES
762 * look for next arg in string. handle "quoted" strings
763 * returns pointer to argument *AFTER* the space. Or to the \0.
765 LPCVOID WINAPI PathGetArgsAW(LPVOID cmdline)
766 { if (VERSION_OsIsUnicode())
767 return PathGetArgsW(cmdline);
768 return PathGetArgsA(cmdline);
771 /*************************************************************************
772 * PathQuoteSpacesA
774 * NOTES
775 * basename(char *fn);
777 LPSTR WINAPI PathQuoteSpacesA(LPCSTR aptr)
778 { FIXME("%s\n",aptr);
779 return 0;
783 /*************************************************************************
784 * PathQuoteSpacesW
786 * NOTES
787 * basename(char *fn);
789 LPWSTR WINAPI PathQuoteSpacesW(LPCWSTR wptr)
790 { FIXME("%s\n",debugstr_w(wptr));
791 return 0;
794 /*************************************************************************
795 * PathQuoteSpaces [SHELL32.55]
797 * NOTES
798 * basename(char *fn);
800 LPVOID WINAPI PathQuoteSpacesAW (LPCVOID fn)
801 { if(VERSION_OsIsUnicode())
802 return PathQuoteSpacesW(fn);
803 return PathQuoteSpacesA(fn);
807 /*************************************************************************
808 * PathUnquoteSpacesA
810 * NOTES
811 * unquote string (remove ")
813 VOID WINAPI PathUnquoteSpacesA(LPSTR str)
814 { DWORD len = lstrlenA(str);
815 TRACE("%s\n",str);
816 if (*str!='"')
817 return;
818 if (str[len-1]!='"')
819 return;
820 str[len-1]='\0';
821 lstrcpyA(str,str+1);
822 return;
825 /*************************************************************************
826 * PathUnquoteSpacesW
828 * NOTES
829 * unquote string (remove ")
831 VOID WINAPI PathUnquoteSpacesW(LPWSTR str)
832 { DWORD len = CRTDLL_wcslen(str);
834 TRACE("%s\n",debugstr_w(str));
836 if (*str!='"')
837 return;
838 if (str[len-1]!='"')
839 return;
840 str[len-1]='\0';
841 CRTDLL_wcscpy(str,str+1);
842 return;
845 /*************************************************************************
846 * PathUnquoteSpaces [SHELL32.56]
848 * NOTES
849 * unquote string (remove ")
851 VOID WINAPI PathUnquoteSpacesAW(LPVOID str)
853 if(VERSION_OsIsUnicode())
854 PathUnquoteSpacesW(str);
855 else
856 PathUnquoteSpacesA(str);
859 /*************************************************************************
860 * PathGetDriveNumberA [SHLWAPI.@]
863 HRESULT WINAPI PathGetDriveNumberA(LPSTR u)
864 { FIXME("%s stub\n",debugstr_a(u));
865 return 0;
868 /*************************************************************************
869 * PathGetDriveNumberW [SHLWAPI.@]
872 HRESULT WINAPI PathGetDriveNumberW(LPWSTR u)
873 { FIXME("%s stub\n",debugstr_w(u));
874 return 0;
877 /*************************************************************************
878 * PathGetDriveNumber [SHELL32.57]
881 HRESULT WINAPI PathGetDriveNumberAW(LPVOID str)
883 if(VERSION_OsIsUnicode())
884 return PathGetDriveNumberW(str);
885 return PathGetDriveNumberA(str);
888 /*************************************************************************
889 * PathYetAnotherMakeUniqueNameA [SHELL32.75]
891 * NOTES
892 * exported by ordinal
894 BOOL WINAPI PathYetAnotherMakeUniqueNameA(LPDWORD x,LPDWORD y) {
895 FIXME("(%p,%p):stub.\n",x,y);
896 return TRUE;
899 /*************************************************************************
900 * IsLFNDriveA [SHELL32.119]
902 * NOTES
903 * exported by ordinal Name
905 BOOL WINAPI IsLFNDriveA(LPCSTR path) {
906 DWORD fnlen;
908 if (!GetVolumeInformationA(path,NULL,0,NULL,&fnlen,NULL,NULL,0))
909 return FALSE;
910 return fnlen>12;
913 /*************************************************************************
914 * PathFindOnPathA
916 BOOL WINAPI PathFindOnPathA(LPSTR sFile, LPCSTR sOtherDirs)
917 { FIXME("%s %s\n",sFile, sOtherDirs);
918 return FALSE;
921 /*************************************************************************
922 * PathFindOnPathW
924 BOOL WINAPI PathFindOnPathW(LPWSTR sFile, LPCWSTR sOtherDirs)
925 { FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
926 return FALSE;
929 /*************************************************************************
930 * PathFindOnPath [SHELL32.145]
932 BOOL WINAPI PathFindOnPathAW(LPVOID sFile, LPCVOID sOtherDirs)
933 { if (VERSION_OsIsUnicode())
934 return PathFindOnPathW(sFile, sOtherDirs);
935 return PathFindOnPathA(sFile, sOtherDirs);
938 /*************************************************************************
939 * PathGetExtension [SHELL32.158]
941 * NOTES
942 * exported by ordinal
944 LPCSTR WINAPI PathGetExtensionA(LPCSTR path,DWORD y,DWORD z)
945 { TRACE("(%s,%08lx,%08lx)\n",path,y,z);
946 path = PathFindExtensionA(path);
947 return *path?(path+1):path;
949 LPCWSTR WINAPI PathGetExtensionW(LPCWSTR path,DWORD y,DWORD z)
950 { TRACE("(%s, %08lx, %08lx)\n",debugstr_w(path),y,z);
951 path = PathFindExtensionW(path);
952 return *path?(path+1):path;
954 LPCVOID WINAPI PathGetExtensionAW(LPCVOID path,DWORD y,DWORD z)
955 { if (VERSION_OsIsUnicode())
956 return PathGetExtensionW(path,y,z);
957 return PathGetExtensionA(path,y,z);
960 /*************************************************************************
961 * PathCleanupSpec [SHELL32.171]
964 DWORD WINAPI PathCleanupSpecA(LPSTR x, LPSTR y)
966 FIXME("(%p %s, %p %s) stub\n",x,debugstr_a(x),y,debugstr_a(y));
967 return TRUE;
970 DWORD WINAPI PathCleanupSpecW(LPWSTR x, LPWSTR y)
972 FIXME("(%p %s, %p %s) stub\n",x,debugstr_w(x),y,debugstr_w(y));
973 return TRUE;
976 DWORD WINAPI PathCleanupSpecAW (LPVOID x, LPVOID y)
978 if (VERSION_OsIsUnicode())
979 return PathCleanupSpecW(x,y);
980 return PathCleanupSpecA(x,y);
983 /*************************************************************************
984 * SheGetDirW [SHELL32.281]
987 HRESULT WINAPI SheGetDirW(LPWSTR u, LPWSTR v)
988 { FIXME("%p %p stub\n",u,v);
989 return 0;
992 /*************************************************************************
993 * SheChangeDirW [SHELL32.274]
996 HRESULT WINAPI SheChangeDirW(LPWSTR u)
997 { FIXME("(%s),stub\n",debugstr_w(u));
998 return 0;
1001 /*************************************************************************
1002 * PathProcessCommand [SHELL32.653]
1004 HRESULT WINAPI PathProcessCommandA (LPSTR lpCommand, LPSTR v, DWORD w, DWORD x)
1006 FIXME("%p(%s) %p 0x%04lx 0x%04lx stub\n",
1007 lpCommand, lpCommand, v, w,x );
1008 lstrcpyA(v, lpCommand);
1009 return 0;
1012 HRESULT WINAPI PathProcessCommandW (LPWSTR lpCommand, LPSTR v, DWORD w, DWORD x)
1014 FIXME("(%p %s, %p, 0x%04lx, 0x%04lx) stub\n",
1015 lpCommand, debugstr_w(lpCommand), v, w,x );
1016 return 0;
1019 HRESULT WINAPI PathProcessCommandAW (LPVOID lpCommand, LPSTR v, DWORD w, DWORD x)
1021 if (VERSION_OsIsUnicode())
1022 return PathProcessCommandW(lpCommand, v, w, x);
1023 return PathProcessCommandA(lpCommand, v, w, x);
1026 /*************************************************************************
1027 * SHGetSpecialFolderPathA
1029 * converts csidl to path
1033 static char * szSHFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
1035 BOOL WINAPI SHGetSpecialFolderPathA (
1036 HWND hwndOwner,
1037 LPSTR szPath,
1038 DWORD csidl,
1039 BOOL bCreate)
1041 CHAR szValueName[MAX_PATH], szDefaultPath[MAX_PATH];
1042 HKEY hRootKey, hKey;
1043 BOOL bRelative = TRUE;
1044 DWORD dwType, dwDisp, dwPathLen = MAX_PATH;
1046 TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
1048 /* build default values */
1049 switch(csidl)
1051 case CSIDL_APPDATA:
1052 hRootKey = HKEY_CURRENT_USER;
1053 strcpy (szValueName, "AppData");
1054 strcpy (szDefaultPath, "AppData");
1055 break;
1057 case CSIDL_COOKIES:
1058 hRootKey = HKEY_CURRENT_USER;
1059 strcpy (szValueName, "Cookies");
1060 strcpy(szDefaultPath, "Cookies");
1061 break;
1063 case CSIDL_DESKTOPDIRECTORY:
1064 hRootKey = HKEY_CURRENT_USER;
1065 strcpy(szValueName, "Desktop");
1066 strcpy(szDefaultPath, "Desktop");
1067 break;
1069 case CSIDL_COMMON_DESKTOPDIRECTORY:
1070 hRootKey = HKEY_LOCAL_MACHINE;
1071 strcpy(szValueName, "Common Desktop");
1072 strcpy(szDefaultPath, "Desktop");
1073 break;
1075 case CSIDL_FAVORITES:
1076 hRootKey = HKEY_CURRENT_USER;
1077 strcpy(szValueName, "Favorites");
1078 strcpy(szDefaultPath, "Favorites");
1079 break;
1081 case CSIDL_FONTS:
1082 hRootKey = HKEY_CURRENT_USER;
1083 strcpy(szValueName, "Fonts");
1084 strcpy(szDefaultPath, "Fonts");
1085 break;
1087 case CSIDL_HISTORY:
1088 hRootKey = HKEY_CURRENT_USER;
1089 strcpy(szValueName, "History");
1090 strcpy(szDefaultPath, "History");
1091 break;
1093 case CSIDL_NETHOOD:
1094 hRootKey = HKEY_CURRENT_USER;
1095 strcpy(szValueName, "NetHood");
1096 strcpy(szDefaultPath, "NetHood");
1097 break;
1099 case CSIDL_INTERNET_CACHE:
1100 hRootKey = HKEY_CURRENT_USER;
1101 strcpy(szValueName, "Cache");
1102 strcpy(szDefaultPath, "Temporary Internet Files");
1103 break;
1105 case CSIDL_PERSONAL:
1106 hRootKey = HKEY_CURRENT_USER;
1107 strcpy(szValueName, "Personal");
1108 strcpy(szDefaultPath, "My Own Files");
1109 bRelative = FALSE;
1110 break;
1112 case CSIDL_PRINTHOOD:
1113 hRootKey = HKEY_CURRENT_USER;
1114 strcpy(szValueName, "PrintHood");
1115 strcpy(szDefaultPath, "PrintHood");
1116 break;
1118 case CSIDL_PROGRAMS:
1119 hRootKey = HKEY_CURRENT_USER;
1120 strcpy(szValueName, "Programs");
1121 strcpy(szDefaultPath, "StartMenu\\Programs");
1122 break;
1124 case CSIDL_COMMON_PROGRAMS:
1125 hRootKey = HKEY_LOCAL_MACHINE;
1126 strcpy(szValueName, "Common Programs");
1127 strcpy(szDefaultPath, "");
1128 break;
1130 case CSIDL_RECENT:
1131 hRootKey = HKEY_CURRENT_USER;
1132 strcpy(szValueName, "Recent");
1133 strcpy(szDefaultPath, "Recent");
1134 break;
1136 case CSIDL_SENDTO:
1137 hRootKey = HKEY_CURRENT_USER;
1138 strcpy(szValueName, "SendTo");
1139 strcpy(szDefaultPath, "SendTo");
1140 break;
1142 case CSIDL_STARTMENU:
1143 hRootKey = HKEY_CURRENT_USER;
1144 strcpy(szValueName, "StartMenu");
1145 strcpy(szDefaultPath, "StartMenu");
1146 break;
1148 case CSIDL_COMMON_STARTMENU:
1149 hRootKey = HKEY_LOCAL_MACHINE;
1150 strcpy(szValueName, "Common StartMenu");
1151 strcpy(szDefaultPath, "StartMenu");
1152 break;
1154 case CSIDL_STARTUP:
1155 hRootKey = HKEY_CURRENT_USER;
1156 strcpy(szValueName, "Startup");
1157 strcpy(szDefaultPath, "StartMenu\\Programs\\Startup");
1158 break;
1160 case CSIDL_COMMON_STARTUP:
1161 hRootKey = HKEY_LOCAL_MACHINE;
1162 strcpy(szValueName, "Common Startup");
1163 strcpy(szDefaultPath, "StartMenu\\Programs\\Startup");
1164 break;
1166 case CSIDL_TEMPLATES:
1167 hRootKey = HKEY_CURRENT_USER;
1168 strcpy(szValueName, "Templates");
1169 strcpy(szDefaultPath, "ShellNew");
1170 break;
1172 default:
1173 ERR("folder unknown or not allowed\n");
1174 return FALSE;
1177 if (RegCreateKeyExA(hRootKey,szSHFolders,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey,&dwDisp))
1179 return FALSE;
1182 if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
1184 /* value not existing */
1185 if (bRelative)
1187 GetWindowsDirectoryA(szPath, MAX_PATH);
1188 PathAddBackslashA(szPath);
1189 strcat(szPath, szDefaultPath);
1191 else
1193 strcpy(szPath, szDefaultPath);
1195 if (bCreate)
1197 CreateDirectoryA(szPath,NULL);
1199 RegSetValueExA(hKey,szValueName,0,REG_SZ,(LPBYTE)szPath,strlen(szPath)+1);
1201 RegCloseKey(hKey);
1203 return TRUE;
1206 /*************************************************************************
1207 * SHGetSpecialFolderPathW
1209 * converts csidl to path
1212 BOOL WINAPI SHGetSpecialFolderPathW (
1213 HWND hwndOwner,
1214 LPWSTR szPath,
1215 DWORD csidl,
1216 BOOL bCreate)
1218 char szTemp[MAX_PATH];
1220 if (SHGetSpecialFolderPathA(hwndOwner, szTemp, csidl, bCreate))
1222 lstrcpynAtoW(szPath, szTemp, MAX_PATH);
1225 TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
1227 return TRUE;
1230 /*************************************************************************
1231 * SHGetSpecialFolderPath [SHELL32.175]
1233 * converts csidl to path
1236 BOOL WINAPI SHGetSpecialFolderPathAW (
1237 HWND hwndOwner,
1238 LPVOID szPath,
1239 DWORD csidl,
1240 BOOL bCreate)
1243 if (VERSION_OsIsUnicode())
1244 return SHGetSpecialFolderPathW (hwndOwner, szPath, csidl, bCreate);
1245 return SHGetSpecialFolderPathA (hwndOwner, szPath, csidl, bCreate);
1248 /*************************************************************************
1249 * PathRemoveBackslashA
1251 * If the path ends in a backslash it is replaced by a NULL
1252 * and the address of the NULL is returned
1253 * Otherwise
1254 * the address of the last character is returned.
1257 LPSTR WINAPI PathRemoveBackslashA( LPSTR lpPath )
1259 LPSTR p = lpPath;
1261 while (*lpPath) p = lpPath++;
1262 if ( *p == (CHAR)'\\') *p = (CHAR)'\0';
1263 return p;
1266 /*************************************************************************
1267 * PathRemoveBackslashW
1270 LPWSTR WINAPI PathRemoveBackslashW( LPWSTR lpPath )
1272 LPWSTR p = lpPath;
1274 while (*lpPath); p = lpPath++;
1275 if ( *p == (WCHAR)'\\') *p = (WCHAR)'\0';
1276 return p;
1279 /*************************************************************************
1280 * PathIsURLA
1283 BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
1285 LPSTR lpstrRes;
1286 char lpstrFileType[10] = "";
1287 int iSize;
1288 int i = 0;
1289 /* sanity check */
1290 if(!lpstrPath)
1291 return FALSE;
1293 /* get protocol */
1294 /* protocol://location */
1295 if(!(lpstrRes = strchr(lpstrPath,':')))
1297 return FALSE;
1299 iSize = lpstrRes - lpstrPath;
1300 if(iSize > sizeof(lpstrFileType))
1301 return FALSE;
1303 strncpy(lpstrFileType,lpstrPath,iSize);
1305 while(strlen(SupportedProtocol[i]))
1307 if(!_stricmp(lpstrFileType,SupportedProtocol[i++]))
1308 return TRUE;
1311 return FALSE;
1314 /*************************************************************************
1315 * PathIsDirectoryA
1318 BOOL WINAPI PathIsDirectoryA(LPCSTR pszPath)
1320 FIXME("%s\n", debugstr_a(pszPath));
1321 return TRUE;
1324 /*************************************************************************
1325 * PathIsDirectoryW
1328 BOOL WINAPI PathIsDirectoryW(LPCWSTR pszPath)
1330 FIXME("%s\n", debugstr_w(pszPath));
1331 return TRUE;
1333 /*************************************************************************
1334 * PathIsDirectory
1337 BOOL WINAPI PathIsDirectoryAW (LPCVOID pszPath)
1339 if (VERSION_OsIsUnicode())
1340 return PathIsDirectoryW (pszPath);
1341 return PathIsDirectoryA (pszPath);