source: trunk/src/shell32/shellpath.cpp@ 3243

Last change on this file since 3243 was 3243, checked in by cbratschi, 25 years ago

merged with Corel WINE 20000324

File size: 32.0 KB
Line 
1/* $Id: shellpath.cpp,v 1.7 2000-03-26 16:34:52 cbratschi Exp $ */
2
3/*
4 * Win32 SHELL32 for OS/2
5 *
6 * Copyright 1997 Marcus Meissner
7 * Copyright 1999 Patrick Haller (haller@zebra.fh-weingarten.de)
8 * Project Odin Software License can be found in LICENSE.TXT
9 *
10 * Path Functions
11 *
12 * Many of this functions are in SHLWAPI.DLL also
13 *
14 * Corel WINE 20000324 level (without CRTDLL_* calls)
15 */
16
17
18/*****************************************************************************
19 * Includes *
20 *****************************************************************************/
21
22#include <odin.h>
23#include <odinwrap.h>
24#include <os2sel.h>
25
26#include <string.h>
27#include <ctype.h>
28#include <wctype.h>
29#define HAVE_WCTYPE_H
30#include <odin.h>
31
32#define ICOM_CINTERFACE 1
33#define CINTERFACE 1
34
35#include "debugtools.h"
36#include "winnls.h"
37#include "winversion.h"
38#include "winreg.h"
39#include "crtdll.h"
40
41#include "shlobj.h"
42#include "shell32_main.h"
43
44#include <heapstring.h>
45#include <misc.h>
46
47
48ODINDEBUGCHANNEL(SHELL32-SHELLPATH)
49
50/* Supported protocols for PathIsURL */
51LPSTR SupportedProtocol[] = {"http","https","ftp","gopher","file","mailto",""};
52
53/*************************************************************************
54 * PathIsRoot [SHELL32.29]
55 */
56ODINFUNCTION1(BOOL, PathIsRootA,
57 LPCSTR, x)
58{ TRACE("%s\n",x);
59 if (*(x+1)==':' && *(x+2)=='\\') /* "X:\" */
60 return 1;
61 if (*x=='\\' || *x=='/') /* "\" */
62 return 1;
63 if (x[0]=='\\' && x[1]=='\\') /* UNC "\\<xx>\" */
64 { int foundbackslash = 0;
65 x=x+2;
66 while (*x)
67 { if (*x++=='\\')
68 foundbackslash++;
69 }
70 if (foundbackslash<=1) /* max 1 \ more ... */
71 return 1;
72 }
73 return 0;
74}
75ODINFUNCTION1(BOOL, PathIsRootW,
76 LPCWSTR, x)
77{ TRACE("%s\n",debugstr_w(x));
78 if (*(x+1)==':' && *(x+2)=='\\') /* "X:\" */
79 return 1;
80 if (*x == (WCHAR) '\\' || *x == (WCHAR) '/') /* "\" */
81 return 1;
82 if (x[0]==(WCHAR)'\\' && x[1]==(WCHAR)'\\') /* UNC "\\<xx>\" */
83 { int foundbackslash = 0;
84 x=x+2;
85 while (*x)
86 { if (*x++==(WCHAR)'\\')
87 foundbackslash++;
88 }
89 if (foundbackslash<=1) /* max 1 \ more ... */
90 return 1;
91 }
92 return 0;
93}
94ODINFUNCTION1(BOOL, PathIsRootAW,
95 LPCVOID, x)
96{ if (VERSION_OsIsUnicode())
97 return PathIsRootW((LPWSTR)x);
98 return PathIsRootA((LPSTR)x);
99
100}
101/*************************************************************************
102 * PathBuildRoot [SHELL32.30]
103 */
104LPSTR WINAPI PathBuildRootA(LPSTR root, BYTE drive)
105{
106 TRACE("%p %i\n",root, drive);
107 strcpy(root,"A:\\");
108 root[0]+=drive;
109 return root;
110}
111
112/*************************************************************************
113 */
114LPWSTR WINAPI PathBuildRootW(LPWSTR root, BYTE drive)
115{
116 lstrcpyW(root, (LPWSTR)L"A:\\");
117 root[0]+=drive;
118 return root;
119}
120
121/*************************************************************************
122 * PathFindExtension [SHELL32.31]
123 *
124 * NOTES
125 * returns pointer to last . in last pathcomponent or at \0.
126 */
127ODINFUNCTION1(LPCSTR, PathFindExtensionA,
128 LPCSTR, path)
129{ LPCSTR lastpoint = NULL;
130 TRACE("%p %s\n",path,path);
131 while (*path)
132 { if (*path=='\\'||*path==' ')
133 lastpoint=NULL;
134 if (*path=='.')
135 lastpoint=path;
136 path++;
137 }
138 return lastpoint?lastpoint:path;
139}
140ODINFUNCTION1(LPCWSTR, PathFindExtensionW,
141 LPCWSTR, path)
142{ LPCWSTR lastpoint = NULL;
143 TRACE("%p L%s\n",path,debugstr_w(path));
144 while (*path)
145 { if (*path==(WCHAR)'\\'||*path==(WCHAR)' ')
146 lastpoint=NULL;
147 if (*path==(WCHAR)'.')
148 lastpoint=path;
149 path++;
150 }
151 return lastpoint?lastpoint:path;
152}
153ODINFUNCTION1(LPCVOID, PathFindExtensionAW,
154 LPCVOID, path)
155{ if (VERSION_OsIsUnicode())
156 return PathFindExtensionW((LPWSTR)path);
157 return PathFindExtensionA((LPSTR)path);
158
159}
160
161/*************************************************************************
162 * PathAddBackslash [SHELL32.32]
163 *
164 * NOTES
165 * append \ if there is none
166 */
167ODINFUNCTION1(LPSTR, PathAddBackslashA,
168 LPSTR, path)
169{ int len;
170 TRACE("%p->%s\n",path,path);
171
172 len = strlen(path);
173 if (len && path[len-1]!='\\')
174 { path[len] = '\\';
175 path[len+1]= 0x00;
176 return path+len+1;
177 }
178 return path+len;
179}
180ODINFUNCTION1(LPWSTR, PathAddBackslashW,
181 LPWSTR, path)
182{ int len;
183 TRACE("%p->%s\n",path,debugstr_w(path));
184
185 len = lstrlenW(path);
186 if (len && path[len-1]!=(WCHAR)'\\')
187 { path[len] = (WCHAR)'\\';
188 path[len+1]= 0x00;
189 return path+len+1;
190 }
191 return path+len;
192}
193ODINFUNCTION1(LPVOID, PathAddBackslashAW,
194 LPVOID, path)
195{ if(VERSION_OsIsUnicode())
196 return PathAddBackslashW((LPWSTR)path);
197 return PathAddBackslashA((LPSTR)path);
198}
199
200/*************************************************************************
201 * PathRemoveBlanks [SHELL32.33]
202 *
203 * NOTES
204 * remove spaces from beginning and end of passed string
205 */
206ODINFUNCTION1(LPSTR, PathRemoveBlanksA,
207 LPSTR, str)
208{ LPSTR x = str;
209 TRACE("%s\n",str);
210 while (*x==' ') x++;
211 if (x!=str)
212 strcpy(str,x);
213 if (!*str)
214 return str;
215 x=str+strlen(str)-1;
216 while (*x==' ')
217 x--;
218 if (*x==' ')
219 *x='\0';
220 return x;
221}
222ODINFUNCTION1(LPWSTR, PathRemoveBlanksW,
223 LPWSTR, str)
224{ LPWSTR x = str;
225 TRACE("%s\n",debugstr_w(str));
226 while (*x==' ') x++;
227 if (x!=str)
228 lstrcpyW(str,x);
229 if (!*str)
230 return str;
231 x=str+lstrlenW(str)-1;
232 while (*x==' ')
233 x--;
234 if (*x==' ')
235 *x='\0';
236 return x;
237}
238ODINFUNCTION1(LPVOID, PathRemoveBlanksAW,
239 LPVOID, str)
240{ if(VERSION_OsIsUnicode())
241 return PathRemoveBlanksW((LPWSTR)str);
242 return PathRemoveBlanksA((LPSTR)str);
243}
244
245
246
247/*************************************************************************
248 * PathFindFilename [SHELL32.34]
249 *
250 * NOTES
251 * basename(char *fn);
252 */
253ODINFUNCTION1(LPCSTR, PathFindFilenameA,
254 LPCSTR, aptr)
255{ LPCSTR aslash;
256 aslash = aptr;
257
258 TRACE("%s\n",aslash);
259 while (aptr[0])
260 { if (((aptr[0]=='\\') || (aptr[0]==':')) && aptr[1] && aptr[1]!='\\')
261 aslash = aptr+1;
262 aptr++;
263 }
264 return aslash;
265
266}
267ODINFUNCTION1(LPCWSTR, PathFindFilenameW,
268 LPCWSTR, wptr)
269{ LPCWSTR wslash;
270 wslash = wptr;
271
272 TRACE("L%s\n",debugstr_w(wslash));
273 while (wptr[0])
274 { if (((wptr[0]=='\\') || (wptr[0]==':')) && wptr[1] && wptr[1]!='\\')
275 wslash = wptr+1;
276 wptr++;
277 }
278 return wslash;
279}
280ODINFUNCTION1(LPCVOID, PathFindFilenameAW,
281 LPCVOID, fn)
282{
283 if(VERSION_OsIsUnicode())
284 return PathFindFilenameW((LPWSTR)fn);
285 return PathFindFilenameA((LPSTR)fn);
286}
287
288/*************************************************************************
289 * PathRemoveFileSpec [SHELL32.35]
290 *
291 * NOTES
292 * bool getpath(char *pathname); truncates passed argument to a valid path
293 * returns if the string was modified or not.
294 * "\foo\xx\foo"-> "\foo\xx"
295 * "\" -> "\"
296 * "a:\foo" -> "a:\"
297 */
298ODINFUNCTION1(DWORD, PathRemoveFileSpecA,
299 LPSTR, fn)
300{
301 LPSTR x,cutplace;
302 TRACE("%s\n",fn);
303 if (!fn[0])
304 return 0;
305 x=fn;
306 cutplace = fn;
307 while (*x) {
308 if (*x=='\\') {
309 cutplace=x++;
310 continue;
311 }
312 if (*x==':') {
313 x++;
314 if (*x=='\\')
315 cutplace=++x;
316 continue; /* already x++ed */
317 }
318 x++;
319 }
320 if (!*cutplace)
321 return 0;
322 if (cutplace==fn) {
323 if (fn[0]=='\\') {
324 if (!fn[1])
325 return 0;
326 fn[0]='\0';
327 return 1;
328 }
329 }
330 *cutplace='\0';
331 return 1;
332}
333
334/*************************************************************************
335 * PathAppend [SHELL32.36]
336 *
337 * NOTES
338 * concat_paths(char*target,const char*add);
339 * concats "target\\add" and writes them to target
340 */
341LPSTR WINAPI PathAppendA(LPSTR x1, LPSTR x2)
342{
343 TRACE("%s %s\n",x1,x2);
344 while (x2[0]=='\\') x2++;
345 return PathCombineA(x1,x1,x2);
346}
347
348/*************************************************************************
349 * PathAppend [SHELL32.36]
350 *
351 * NOTES
352 * concat_paths(char*target,const char*add);
353 * concats "target\\add" and writes them to target
354 */
355LPWSTR WINAPI PathAppendW(LPWSTR x1, LPWSTR x2)
356{
357 while (x2[0] == (WCHAR)'\\') x2++;
358 return PathCombineW(x1,x1,x2);
359}
360
361/*************************************************************************
362 * PathCombine [SHELL32.37]
363 *
364 * NOTES
365 * if lpszFile='.' skip it
366 * szDest can be equal to lpszFile. Thats why we use sTemp
367 */
368ODINFUNCTION3(LPSTR, PathCombineA,
369 LPSTR, szDest,
370 LPCSTR, lpszDir,
371 LPCSTR, lpszFile)
372{ char sTemp[MAX_PATH];
373 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, lpszDir, lpszFile, lpszFile);
374
375
376 if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) )
377 { strcpy(szDest,lpszDir);
378 return szDest;
379 }
380
381 /* if lpszFile is a complete path don't care about lpszDir */
382 if (PathIsRootA(lpszFile))
383 { strcpy(szDest,lpszFile);
384 }
385 else
386 { strcpy(sTemp,lpszDir);
387 PathAddBackslashA(sTemp);
388 strcat(sTemp,lpszFile);
389 strcpy(szDest,sTemp);
390 }
391 return szDest;
392}
393ODINFUNCTION3(LPWSTR, PathCombineW,
394 LPWSTR, szDest,
395 LPCWSTR, lpszDir,
396 LPCWSTR, lpszFile)
397{ WCHAR sTemp[MAX_PATH];
398 TRACE("%p %p->%s %p->%s\n",szDest, lpszDir, debugstr_w(lpszDir),
399 lpszFile, debugstr_w(lpszFile));
400
401
402 if (!lpszFile || !lpszFile[0] || (lpszFile[0]==(WCHAR)'.' && !lpszFile[1]) )
403 { lstrcpyW(szDest,lpszDir);
404 return szDest;
405 }
406
407 /* if lpszFile is a complete path don't care about lpszDir */
408 if (PathIsRootW(lpszFile))
409 { lstrcpyW(szDest,lpszFile);
410 }
411 else
412 { lstrcpyW(sTemp,lpszDir);
413 PathAddBackslashW(sTemp);
414 lstrcatW(sTemp,lpszFile);
415 lstrcpyW(szDest,sTemp);
416 }
417 return szDest;
418}
419ODINFUNCTION3(LPVOID, PathCombineAW,
420 LPVOID, szDest,
421 LPCVOID, lpszDir,
422 LPCVOID, lpszFile)
423{ if (VERSION_OsIsUnicode())
424 return PathCombineW( (LPWSTR)szDest, (LPWSTR)lpszDir, (LPWSTR)lpszFile );
425 return PathCombineA( (LPSTR)szDest, (LPSTR)lpszDir, (LPSTR)lpszFile );
426}
427
428/*************************************************************************
429 * PathIsUNC [SHELL32.39]
430 *
431 * NOTES
432 * PathIsUNC(char*path);
433 */
434ODINFUNCTION1(BOOL, PathIsUNCA,
435 LPCSTR, path)
436{ TRACE("%s\n",path);
437
438 if ((path[0]=='\\') && (path[1]=='\\'))
439 return TRUE;
440 return FALSE;
441}
442ODINFUNCTION1(BOOL, PathIsUNCW,
443 LPCWSTR, path)
444{ TRACE("%s\n",debugstr_w(path));
445
446 if ((path[0]=='\\') && (path[1]=='\\'))
447 return TRUE;
448 return FALSE;
449}
450ODINFUNCTION1(BOOL, PathIsUNCAW,
451 LPCVOID, path)
452{ if (VERSION_OsIsUnicode())
453 return PathIsUNCW( (LPWSTR)path );
454 return PathIsUNCA( (LPSTR)path );
455}
456/*************************************************************************
457 * PathIsRelativ [SHELL32.40]
458 *
459 */
460ODINFUNCTION1(BOOL, PathIsRelativeA,
461 LPCSTR, path)
462{ TRACE("path=%s\n",path);
463
464 if (path && (path[0]!='\\' && path[1]==':'))
465 return TRUE;
466 return FALSE;
467}
468ODINFUNCTION1(BOOL, PathIsRelativeW,
469 LPCWSTR, path)
470{ TRACE("path=%s\n",debugstr_w(path));
471
472 if (path && (path[0]!='\\' && path[1]==':'))
473 return TRUE;
474 return FALSE;
475}
476ODINFUNCTION1(BOOL, PathIsRelativeAW,
477 LPCVOID, path)
478{ if (VERSION_OsIsUnicode())
479 return PathIsRelativeW( (LPWSTR)path );
480 return PathIsRelativeA( (LPSTR)path );
481}
482/*************************************************************************
483 * PathIsExe [SHELL32.43]
484 *
485 */
486ODINFUNCTION1(BOOL, PathIsExeA,
487 LPCSTR, path)
488{ FIXME("path=%s\n",path);
489 return FALSE;
490}
491ODINFUNCTION1(BOOL, PathIsExeW,
492 LPCWSTR, path)
493{ FIXME("path=%s\n",debugstr_w(path));
494 return FALSE;
495}
496ODINFUNCTION1(BOOL, PathIsExeAW,
497 LPCVOID, path)
498{ if (VERSION_OsIsUnicode())
499 return PathIsExeW ((LPWSTR)path);
500 return PathIsExeA((LPSTR)path);
501}
502
503/*************************************************************************
504 * PathFileExists [SHELL32.45]
505 *
506 * NOTES
507 * file_exists(char *fn);
508 */
509ODINFUNCTION1(BOOL, PathFileExistsA,
510 LPSTR, fn)
511{
512 TRACE("%s\n",fn);
513 if (GetFileAttributesA(fn)==-1)
514 return FALSE;
515 else
516 return TRUE;
517}
518/*************************************************************************
519 * PathFileExists [SHELL32.45]
520 *
521 * NOTES
522 * file_exists(char *fn);
523 */
524ODINFUNCTION1(BOOL, PathFileExistsW,
525 LPWSTR, fn)
526{
527 if (GetFileAttributesW(fn)==-1)
528 return FALSE;
529 else
530 return TRUE;
531}
532/*************************************************************************
533 * PathMatchSingleMask
534 *
535 * NOTES
536 * internal (used by PathMatchSpec)
537 */
538static BOOL PathMatchSingleMaskA(LPCSTR name, LPCSTR mask)
539{
540 while (*name && *mask && *mask!=';') {
541 if (*mask=='*') {
542 do {
543 if (PathMatchSingleMaskA(name,mask+1)) return 1; /* try substrings */
544 } while (*name++);
545 return 0;
546 }
547 if (toupper(*mask)!=toupper(*name) && *mask!='?') return 0;
548 name++;
549 mask++;
550 }
551 if (!*name) {
552 while (*mask=='*') mask++;
553 if (!*mask || *mask==';') return 1;
554 }
555 return 0;
556}
557static BOOL PathMatchSingleMaskW(LPCWSTR name, LPCWSTR mask)
558{
559 while (*name && *mask && *mask!=';') {
560 if (*mask=='*') {
561 do {
562 if (PathMatchSingleMaskW(name,mask+1)) return 1; /* try substrings */
563 } while (*name++);
564 return 0;
565 }
566 if (towupper(*mask)!=towupper(*name) && *mask!='?') return 0;
567 name++;
568 mask++;
569 }
570 if (!*name) {
571 while (*mask=='*') mask++;
572 if (!*mask || *mask==';') return 1;
573 }
574 return 0;
575}
576/*************************************************************************
577 * PathMatchSpec [SHELL32.46]
578 *
579 * NOTES
580 * used from COMDLG32
581 */
582ODINFUNCTION2(BOOL, PathMatchSpecA,
583 LPCSTR, name,
584 LPCSTR, mask)
585{
586 TRACE("%s %s\n",name,mask);
587
588 if (!lstrcmpA( mask, "*.*" )) return 1; /* we don't require a period */
589
590 while (*mask) {
591 if (PathMatchSingleMaskA(name,mask)) return 1; /* helper function */
592 while (*mask && *mask!=';') mask++;
593 if (*mask==';') {
594 mask++;
595 while (*mask==' ') mask++; /* masks may be separated by "; " */
596 }
597 }
598 return 0;
599}
600ODINFUNCTION2(BOOL, PathMatchSpecW,
601 LPCWSTR, name,
602 LPCWSTR, mask)
603{ WCHAR stemp[4];
604 TRACE("%ls %ls\n",name,mask);
605 lstrcpyAtoW(stemp,"*.*");
606 if (!lstrcmpW( mask, stemp )) return 1; /* we don't require a period */
607
608 while (*mask) {
609 if (PathMatchSingleMaskW(name,mask)) return 1; /* helper function */
610 while (*mask && *mask!=';') mask++;
611 if (*mask==';') {
612 mask++;
613 while (*mask==' ') mask++; /* masks may be separated by "; " */
614 }
615 }
616 return 0;
617}
618ODINFUNCTION2(BOOL, PathMatchSpecAW,
619 LPVOID, name,
620 LPVOID, mask)
621{ if (VERSION_OsIsUnicode())
622 return PathMatchSpecW( (LPWSTR)name, (LPWSTR)mask );
623 return PathMatchSpecA( (LPSTR)name, (LPSTR)mask );
624}
625/*************************************************************************
626 * PathSetDlgItemPathAW [SHELL32.48]
627 * NOTES
628 * use PathCompactPath to make sure, the path fits into the control
629 */
630
631ODINFUNCTION3(BOOL, PathSetDlgItemPathA,
632 HWND, hDlg,
633 int, id,
634 LPCSTR, pszPath)
635{ TRACE("%x %x %s\n",hDlg, id, pszPath);
636 return SetDlgItemTextA(hDlg, id, pszPath);
637}
638ODINFUNCTION3(BOOL, PathSetDlgItemPathW,
639 HWND, hDlg,
640 int, id,
641 LPCWSTR, pszPath)
642{ TRACE("%x %x %s\n",hDlg, id, debugstr_w(pszPath));
643 return SetDlgItemTextW(hDlg, id, pszPath);
644}
645ODINFUNCTION3(BOOL, PathSetDlgItemPathAW,
646 HWND, hDlg,
647 int, id,
648 LPCVOID, pszPath)
649{ if (VERSION_OsIsUnicode())
650 return PathSetDlgItemPathW(hDlg, id, (LPWSTR)pszPath);
651 return PathSetDlgItemPathA(hDlg, id, (LPSTR)pszPath);
652}
653
654/*************************************************************************
655 * PathQualifyAW [SHELL32.49]
656 */
657
658ODINFUNCTION1(BOOL, PathQualifyA,
659 LPCSTR, pszPath)
660{ FIXME("%s\n",pszPath);
661 return 0;
662}
663ODINFUNCTION1(BOOL, PathQualifyW,
664 LPCWSTR, pszPath)
665{ FIXME("%s\n",debugstr_w(pszPath));
666 return 0;
667}
668ODINFUNCTION1(BOOL, PathQualifyAW,
669 LPCVOID, pszPath)
670{ if (VERSION_OsIsUnicode())
671 return PathQualifyW((LPWSTR)pszPath);
672 return PathQualifyA((LPSTR)pszPath);
673}
674
675/*************************************************************************
676 * PathResolve [SHELL32.51]
677 */
678ODINFUNCTION3(DWORD, PathResolve,
679 LPCSTR, s,
680 DWORD, x2,
681 DWORD, x3)
682{
683 FIXME("(%s,0x%08lx,0x%08lx),stub!\n",s,x2,x3);
684 return 0;
685}
686
687/*************************************************************************
688 * PathGetArgs [SHELL32.52]
689 *
690 * NOTES
691 * look for next arg in string. handle "quoted" strings
692 * returns pointer to argument *AFTER* the space. Or to the \0.
693 */
694ODINFUNCTION1(LPCSTR, PathGetArgsA,
695 LPCSTR, cmdline)
696{ BOOL qflag = FALSE;
697
698 TRACE("%s\n",cmdline);
699
700 while (*cmdline)
701 { if ((*cmdline==' ') && !qflag)
702 return cmdline+1;
703 if (*cmdline=='"')
704 qflag=!qflag;
705 cmdline++;
706 }
707 return cmdline;
708
709}
710ODINFUNCTION1(LPCWSTR, PathGetArgsW,
711 LPCWSTR, cmdline)
712{ BOOL qflag = FALSE;
713
714 TRACE("%sL\n",debugstr_w(cmdline));
715
716 while (*cmdline)
717 { if ((*cmdline==' ') && !qflag)
718 return cmdline+1;
719 if (*cmdline=='"')
720 qflag=!qflag;
721 cmdline++;
722 }
723 return cmdline;
724}
725ODINFUNCTION1(LPCVOID, PathGetArgsAW,
726 LPVOID, cmdline)
727{ if (VERSION_OsIsUnicode())
728 return PathGetArgsW((LPWSTR)cmdline);
729 return PathGetArgsA((LPSTR)cmdline);
730}
731/*************************************************************************
732 * PathQuoteSpaces [SHELL32.55]
733 *
734 * NOTES
735 * basename(char *fn);
736 */
737ODINFUNCTION1(LPSTR, PathQuoteSpacesA,
738 LPCSTR, aptr)
739{ FIXME("%s\n",aptr);
740 return 0;
741
742}
743ODINFUNCTION1(LPWSTR, PathQuoteSpacesW,
744 LPCWSTR, wptr)
745{ FIXME("L%s\n",debugstr_w(wptr));
746 return 0;
747}
748ODINFUNCTION1(LPVOID, PathQuoteSpacesAW,
749 LPCVOID, fn)
750{ if(VERSION_OsIsUnicode())
751 return PathQuoteSpacesW((LPWSTR)fn);
752 return PathQuoteSpacesA((LPSTR)fn);
753}
754
755
756/*************************************************************************
757 * PathUnquoteSpaces [SHELL32.56]
758 *
759 * NOTES
760 * unquote string (remove ")
761 */
762ODINPROCEDURE1(PathUnquoteSpacesA,
763 LPSTR, str)
764{ DWORD len = lstrlenA(str);
765 TRACE("%s\n",str);
766 if (*str!='"')
767 return;
768 if (str[len-1]!='"')
769 return;
770 str[len-1]='\0';
771 lstrcpyA(str,str+1);
772 return;
773}
774ODINPROCEDURE1(PathUnquoteSpacesW,
775 LPWSTR, str)
776{ DWORD len = lstrlenW(str);
777
778 TRACE("%s\n",debugstr_w(str));
779
780 if (*str!='"')
781 return;
782 if (str[len-1]!='"')
783 return;
784 str[len-1]='\0';
785 lstrcpyW(str,str+1);
786 return;
787}
788ODINPROCEDURE1(PathUnquoteSpacesAW,
789 LPVOID, str)
790{ if(VERSION_OsIsUnicode())
791 PathUnquoteSpacesW((LPWSTR)str);
792 PathUnquoteSpacesA((LPSTR)str);
793}
794
795
796/*************************************************************************
797 * PathGetDriveNumber32 [SHELL32.57]
798 *
799 */
800ODINFUNCTION1(HRESULT, PathGetDriveNumberAW,
801 LPSTR, u)
802{ FIXME("%s stub\n",debugstr_a(u));
803 return 0;
804}
805
806/*************************************************************************
807 * PathGetDriveNumber32 [SHELL32.57]
808 *
809 */
810ODINFUNCTION1(HRESULT, PathGetDriveNumberA,
811 LPSTR, u)
812{ FIXME("%s stub\n",debugstr_a(u));
813 return 0;
814}
815
816/*************************************************************************
817 * PathGetDriveNumber32 [SHELL32.57]
818 *
819 */
820ODINFUNCTION1(HRESULT, PathGetDriveNumberW,
821 LPWSTR, u)
822{ FIXME("%s stub\n",debugstr_a(u));
823 return 0;
824}
825
826/*************************************************************************
827 * PathYetAnotherMakeUniqueName [SHELL32.75]
828 *
829 * NOTES
830 * exported by ordinal
831 */
832ODINFUNCTION2(BOOL, PathYetAnotherMakeUniqueNameA,
833 LPDWORD, x,
834 LPDWORD, y)
835{
836 FIXME("(%p,%p):stub.\n",x,y);
837 return TRUE;
838}
839
840/*************************************************************************
841 * IsLFNDrive [SHELL32.119]
842 *
843 * NOTES
844 * exported by ordinal Name
845 */
846ODINFUNCTION1(BOOL, IsLFNDriveA,
847 LPCSTR, path)
848{
849 DWORD fnlen;
850
851 if (!GetVolumeInformationA(path,NULL,0,NULL,&fnlen,NULL,NULL,0))
852 return FALSE;
853 return fnlen>12;
854}
855/*************************************************************************
856 * PathFindOnPath [SHELL32.145]
857 */
858ODINFUNCTION2(BOOL, PathFindOnPathA,
859 LPSTR, sFile,
860 LPCSTR, sOtherDirs)
861{ FIXME("%s %s\n",sFile, sOtherDirs);
862 return FALSE;
863}
864ODINFUNCTION2(BOOL, PathFindOnPathW,
865 LPWSTR, sFile,
866 LPCWSTR, sOtherDirs)
867{ FIXME("%s %s\n",debugstr_w(sFile), debugstr_w(sOtherDirs));
868 return FALSE;
869}
870ODINFUNCTION2(BOOL, PathFindOnPathAW,
871 LPVOID, sFile,
872 LPCVOID, sOtherDirs)
873{ if (VERSION_OsIsUnicode())
874 return PathFindOnPathW((LPWSTR)sFile, (LPWSTR)sOtherDirs);
875 return PathFindOnPathA((LPSTR)sFile, (LPSTR)sOtherDirs);
876}
877
878/*************************************************************************
879 * PathGetExtension [SHELL32.158]
880 *
881 * NOTES
882 * exported by ordinal
883 */
884ODINFUNCTION3(LPCSTR, PathGetExtensionA,
885 LPCSTR, path,
886 DWORD, y,
887 DWORD, z)
888{ TRACE("(%s,%08lx,%08lx)\n",path,y,z);
889 path = PathFindExtensionA(path);
890 return *path?(path+1):path;
891}
892ODINFUNCTION3(LPCWSTR, PathGetExtensionW,
893 LPCWSTR, path,
894 DWORD, y,
895 DWORD, z)
896{ TRACE("(L%s,%08lx,%08lx)\n",debugstr_w(path),y,z);
897 path = PathFindExtensionW(path);
898 return *path?(path+1):path;
899}
900ODINFUNCTION3(LPCVOID, PathGetExtensionAW,
901 LPCVOID, path,
902 DWORD, y,
903 DWORD, z)
904{ if (VERSION_OsIsUnicode())
905 return PathGetExtensionW((LPWSTR)path,y,z);
906 return PathGetExtensionA((LPSTR)path,y,z);
907}
908
909/*************************************************************************
910 * PathCleanupSpec [SHELL32.171]
911 *
912 */
913ODINFUNCTION2(DWORD, PathCleanupSpecA,
914 LPSTR, x,
915 LPSTR, y)
916{
917 FIXME("%p(%s) %p(%s) stub\n",x,x,y,y);
918 return TRUE;
919}
920
921ODINFUNCTION2(DWORD, PathCleanupSpecW,
922 LPWSTR, x,
923 LPWSTR, y)
924{
925 FIXME("%p(%s) %p(%s) stub\n",x,debugstr_w(x),y,debugstr_w(y));
926 return TRUE;
927}
928
929ODINFUNCTION2(DWORD, PathCleanupSpecAW,
930 LPVOID, x,
931 LPVOID, y)
932{
933 if (VERSION_OsIsUnicode())
934 return PathCleanupSpecW((LPWSTR)x,(LPWSTR)y);
935 return PathCleanupSpecA((LPSTR)x,(LPSTR)y);
936}
937
938/*************************************************************************
939 * SheGetDirW [SHELL32.281]
940 *
941 */
942ODINFUNCTION2(HRESULT, SheGetDirW,
943 LPWSTR, u,
944 LPWSTR, v)
945{ FIXME("%p %p stub\n",u,v);
946 return 0;
947}
948
949/*************************************************************************
950 * SheChangeDirW [SHELL32.274]
951 *
952 */
953ODINFUNCTION1(HRESULT, SheChangeDirW,
954 LPWSTR, u)
955{ FIXME("(%s),stub\n",debugstr_w(u));
956 return 0;
957}
958
959/*************************************************************************
960* PathProcessCommand [SHELL32.653]
961*/
962ODINFUNCTION4(HRESULT, PathProcessCommandA,
963 LPSTR, lpCommand,
964 LPSTR, v,
965 DWORD, w,
966 DWORD, x)
967{
968 FIXME("%p(%s) %p 0x%04lx 0x%04lx stub\n",
969 lpCommand, lpCommand, v, w,x );
970 lstrcpyA(v,lpCommand);
971 return 0;
972}
973
974ODINFUNCTION4(HRESULT, PathProcessCommandW,
975 LPWSTR, lpCommand,
976 LPSTR, v,
977 DWORD, w,
978 DWORD, x)
979{
980 FIXME("%p(%s) %p 0x%04lx 0x%04lx stub\n",
981 lpCommand, debugstr_w(lpCommand), v, w,x );
982 return 0;
983}
984
985ODINFUNCTION4(HRESULT, PathProcessCommandAW,
986 LPVOID, lpCommand,
987 LPSTR, v,
988 DWORD, w,
989 DWORD, x)
990{
991 if (VERSION_OsIsUnicode())
992 return PathProcessCommandW((LPWSTR)lpCommand, v, w, x);
993 return PathProcessCommandA((LPSTR)lpCommand, v, w, x);
994}
995
996/*************************************************************************
997 * SHGetSpecialFolderPath [SHELL32.175]
998 *
999 * converts csidl to path
1000 *
1001 */
1002
1003static char * szSHFolders = "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders";
1004
1005ODINFUNCTION4(BOOL, SHGetSpecialFolderPathA,
1006 HWND, hwndOwner,
1007 LPSTR, szPath,
1008 DWORD, csidl,
1009 BOOL, bCreate)
1010{
1011 CHAR szValueName[MAX_PATH], szDefaultPath[MAX_PATH];
1012 HKEY hRootKey, hKey;
1013 BOOL bRelative = TRUE;
1014 DWORD dwType, dwDisp, dwPathLen = MAX_PATH;
1015
1016 TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
1017
1018 /* build default values */
1019 switch(csidl)
1020 {
1021 case CSIDL_APPDATA:
1022 hRootKey = HKEY_CURRENT_USER;
1023 strcpy (szValueName, "AppData");
1024 strcpy (szDefaultPath, "AppData");
1025 break;
1026
1027 case CSIDL_COOKIES:
1028 hRootKey = HKEY_CURRENT_USER;
1029 strcpy (szValueName, "Cookies");
1030 strcpy(szDefaultPath, "Cookies");
1031 break;
1032
1033 case CSIDL_DESKTOPDIRECTORY:
1034 hRootKey = HKEY_CURRENT_USER;
1035 strcpy(szValueName, "Desktop");
1036 strcpy(szDefaultPath, "Desktop");
1037 break;
1038
1039 case CSIDL_COMMON_DESKTOPDIRECTORY:
1040 hRootKey = HKEY_LOCAL_MACHINE;
1041 strcpy(szValueName, "Common Desktop");
1042 strcpy(szDefaultPath, "Desktop");
1043 break;
1044
1045 case CSIDL_FAVORITES:
1046 hRootKey = HKEY_CURRENT_USER;
1047 strcpy(szValueName, "Favorites");
1048 strcpy(szDefaultPath, "Favorites");
1049 break;
1050
1051 case CSIDL_FONTS:
1052 hRootKey = HKEY_CURRENT_USER;
1053 strcpy(szValueName, "Fonts");
1054 strcpy(szDefaultPath, "Fonts");
1055 break;
1056
1057 case CSIDL_HISTORY:
1058 hRootKey = HKEY_CURRENT_USER;
1059 strcpy(szValueName, "History");
1060 strcpy(szDefaultPath, "History");
1061 break;
1062
1063 case CSIDL_NETHOOD:
1064 hRootKey = HKEY_CURRENT_USER;
1065 strcpy(szValueName, "NetHood");
1066 strcpy(szDefaultPath, "NetHood");
1067 break;
1068
1069 case CSIDL_INTERNET_CACHE:
1070 hRootKey = HKEY_CURRENT_USER;
1071 strcpy(szValueName, "Cache");
1072 strcpy(szDefaultPath, "Temporary Internet Files");
1073 break;
1074
1075 case CSIDL_PERSONAL:
1076 hRootKey = HKEY_CURRENT_USER;
1077 strcpy(szValueName, "Personal");
1078 strcpy(szDefaultPath, "My Own Files");
1079 bRelative = FALSE;
1080 break;
1081
1082 case CSIDL_PRINTHOOD:
1083 hRootKey = HKEY_CURRENT_USER;
1084 strcpy(szValueName, "PrintHood");
1085 strcpy(szDefaultPath, "PrintHood");
1086 break;
1087
1088 case CSIDL_PROGRAMS:
1089 hRootKey = HKEY_CURRENT_USER;
1090 strcpy(szValueName, "Programs");
1091 strcpy(szDefaultPath, "StartMenu\\Programs");
1092 break;
1093
1094 case CSIDL_COMMON_PROGRAMS:
1095 hRootKey = HKEY_LOCAL_MACHINE;
1096 strcpy(szValueName, "Common Programs");
1097 strcpy(szDefaultPath, "");
1098 break;
1099
1100 case CSIDL_RECENT:
1101 hRootKey = HKEY_CURRENT_USER;
1102 strcpy(szValueName, "Recent");
1103 strcpy(szDefaultPath, "Recent");
1104 break;
1105
1106 case CSIDL_SENDTO:
1107 hRootKey = HKEY_CURRENT_USER;
1108 strcpy(szValueName, "SendTo");
1109 strcpy(szDefaultPath, "SendTo");
1110 break;
1111
1112 case CSIDL_STARTMENU:
1113 hRootKey = HKEY_CURRENT_USER;
1114 strcpy(szValueName, "StartMenu");
1115 strcpy(szDefaultPath, "StartMenu");
1116 break;
1117
1118 case CSIDL_COMMON_STARTMENU:
1119 hRootKey = HKEY_LOCAL_MACHINE;
1120 strcpy(szValueName, "Common StartMenu");
1121 strcpy(szDefaultPath, "StartMenu");
1122 break;
1123
1124 case CSIDL_STARTUP:
1125 hRootKey = HKEY_CURRENT_USER;
1126 strcpy(szValueName, "Startup");
1127 strcpy(szDefaultPath, "StartMenu\\Programs\\Startup");
1128 break;
1129
1130 case CSIDL_COMMON_STARTUP:
1131 hRootKey = HKEY_LOCAL_MACHINE;
1132 strcpy(szValueName, "Common Startup");
1133 strcpy(szDefaultPath, "StartMenu\\Programs\\Startup");
1134 break;
1135
1136 case CSIDL_TEMPLATES:
1137 hRootKey = HKEY_CURRENT_USER;
1138 strcpy(szValueName, "Templates");
1139 strcpy(szDefaultPath, "ShellNew");
1140 break;
1141
1142 default:
1143 ERR("folder unknown or not allowed\n");
1144 return FALSE;
1145 }
1146
1147 if (RegCreateKeyExA(hRootKey,szSHFolders,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey,&dwDisp))
1148 {
1149 return FALSE;
1150 }
1151
1152 if (RegQueryValueExA(hKey,szValueName,NULL,&dwType,(LPBYTE)szPath,&dwPathLen))
1153 {
1154 /* value not existing */
1155 if (bRelative)
1156 {
1157 GetWindowsDirectoryA(szPath, MAX_PATH);
1158 PathAddBackslashA(szPath);
1159 strcat(szPath, szDefaultPath);
1160 }
1161 else
1162 {
1163 strcpy(szPath, szDefaultPath);
1164 }
1165 if (bCreate)
1166 {
1167 CreateDirectoryA(szPath,NULL);
1168 }
1169 RegSetValueExA(hKey,szValueName,0,REG_SZ,(LPBYTE)szPath,strlen(szPath)+1);
1170 }
1171 RegCloseKey(hKey);
1172
1173 return TRUE;
1174}
1175ODINFUNCTION4(BOOL, SHGetSpecialFolderPathW,
1176 HWND, hwndOwner,
1177 LPWSTR, szPath,
1178 DWORD, csidl,
1179 BOOL, bCreate)
1180{
1181 char szTemp[MAX_PATH];
1182
1183 if (SHGetSpecialFolderPathA(hwndOwner, szTemp, csidl, bCreate))
1184 {
1185 lstrcpynAtoW(szPath, szTemp, MAX_PATH);
1186 }
1187
1188 TRACE("0x%04x,%p,csidl=%lu,0x%04x\n", hwndOwner,szPath,csidl,bCreate);
1189
1190 return TRUE;
1191}
1192ODINFUNCTION4(BOOL, SHGetSpecialFolderPathAW,
1193 HWND, hwndOwner,
1194 LPVOID, szPath,
1195 DWORD, csidl,
1196 BOOL, bCreate)
1197{
1198 if (VERSION_OsIsUnicode())
1199 return SHGetSpecialFolderPathW (hwndOwner, (LPWSTR)szPath, csidl, bCreate);
1200 return SHGetSpecialFolderPathA (hwndOwner, (LPSTR)szPath, csidl, bCreate);
1201}
1202
1203/* PathRemoveBackslash
1204 *
1205 * If the path ends in a backslash it is replaced by a NULL
1206 * and the address of the NULL is returned
1207 * Otherwise
1208 * the address of the last character is returned.
1209 *
1210 */
1211LPSTR WINAPI PathRemoveBackslashA(LPSTR lpPath)
1212{
1213 LPSTR temp = lpPath;
1214 LPSTR prev = lpPath;
1215
1216 while (*temp)
1217 {
1218 prev = temp++;
1219 }
1220 if ( *prev == (CHAR)'\\')
1221 {
1222 *prev = (CHAR)'\0';
1223 }
1224
1225 return prev;
1226}
1227
1228LPWSTR WINAPI PathRemoveBackslashW(LPWSTR lpPath)
1229{
1230 LPWSTR temp = lpPath;
1231 LPWSTR prev = lpPath;
1232
1233 while (*temp)
1234 {
1235 prev = temp++;
1236 }
1237 if ( *prev == (WCHAR)'\\')
1238 {
1239 *prev = (WCHAR)'\0';
1240 }
1241
1242 return prev;
1243}
1244
1245/*
1246 shlwapi functions that have found their way in because most of
1247 shlwapi is unimplemented and doesn't have a home.
1248
1249 FIXME: move to a more appropriate file( when one exists )
1250*/
1251
1252 /* SHGetValue: Gets a value from the registry */
1253
1254
1255BOOL WINAPI PathIsURLA(LPCSTR lpstrPath)
1256{
1257 LPSTR lpstrRes;
1258 char lpstrFileType[10] = "";
1259 int iSize;
1260 int i = 0;
1261 /* sanity check */
1262 if(!lpstrPath)
1263 return FALSE;
1264
1265 /* get protocol */
1266 /* protocol://location */
1267 if(!(lpstrRes = strchr(lpstrPath,':')))
1268 {
1269 return FALSE;
1270 }
1271 iSize = lpstrRes - lpstrPath;
1272 if(iSize > sizeof(lpstrFileType))
1273 return FALSE;
1274
1275 strncpy(lpstrFileType,lpstrPath,iSize);
1276
1277 while(strlen(SupportedProtocol[i]))
1278 {
1279 if(!stricmp(lpstrFileType,SupportedProtocol[i++]))
1280 return TRUE;
1281 }
1282
1283 return FALSE;
1284}
1285
1286DWORD WINAPI SHGetValueA(
1287 HKEY hkey,
1288 LPCSTR pSubKey,
1289 LPCSTR pValue,
1290 LPDWORD pwType,
1291 LPVOID pvData,
1292 LPDWORD pbData
1293 )
1294{
1295 FIXME("(%p),stub!\n", pSubKey);
1296
1297 return ERROR_SUCCESS; /* return success */
1298}
1299
1300DWORD WINAPI SHGetValueW(
1301 HKEY hkey,
1302 LPCWSTR pSubKey,
1303 LPCWSTR pValue,
1304 LPDWORD pwType,
1305 LPVOID pvData,
1306 LPDWORD pbData
1307 )
1308{
1309 FIXME("(%p),stub!\n", pSubKey);
1310
1311 return ERROR_SUCCESS; /* return success */
1312}
1313
1314/* gets a user-specific registry value. */
1315
1316LONG WINAPI SHRegGetUSValueA(
1317 LPCSTR pSubKey,
1318 LPCSTR pValue,
1319 LPDWORD pwType,
1320 LPVOID pvData,
1321 LPDWORD pbData,
1322 BOOL fIgnoreHKCU,
1323 LPVOID pDefaultData,
1324 DWORD wDefaultDataSize
1325 )
1326{
1327 FIXME("(%p),stub!\n", pSubKey);
1328
1329 return ERROR_SUCCESS; /* return success */
1330}
1331
1332LONG WINAPI SHRegGetUSValueW(
1333 LPCWSTR pSubKey,
1334 LPCWSTR pValue,
1335 LPDWORD pwType,
1336 LPVOID pvData,
1337 LPDWORD pbData,
1338 BOOL flagIgnoreHKCU,
1339 LPVOID pDefaultData,
1340 DWORD wDefaultDataSize
1341 )
1342{
1343 FIXME("(%p),stub!\n", pSubKey);
1344
1345 return ERROR_SUCCESS; /* return success */
1346}
1347
Note: See TracBrowser for help on using the repository browser.