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