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

Last change on this file since 3468 was 3468, checked in by phaller, 25 years ago

Fix: PathFindFilename 3x faster now, just a test for the profiling

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