1 /* 2 * The parameters of many functions changes between different OS versions 3 * (NT uses Unicode strings, 95 uses ASCII strings) 4 * 5 * Copyright 1997 Marcus Meissner 6 * 1998 J�rgen Schmied 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include <wine/config.h> 24 25 #define WIN32_NO_STATUS 26 #define _INC_WINDOWS 27 #define COBJMACROS 28 29 #include <windef.h> 30 #include <winbase.h> 31 #include <wine/winternl.h> 32 #include <shlobj.h> 33 #include <undocshell.h> 34 #include <shlwapi.h> 35 #include <commdlg.h> 36 #include <commoncontrols.h> 37 #include "../shellrecyclebin/recyclebin.h" 38 39 #include <wine/debug.h> 40 #include <wine/unicode.h> 41 42 #include "pidl.h" 43 #include "shell32_main.h" 44 45 WINE_DEFAULT_DEBUG_CHANNEL(shell); 46 WINE_DECLARE_DEBUG_CHANNEL(pidl); 47 48 /* FIXME: !!! move CREATEMRULIST and flags to header file !!! */ 49 /* !!! it is in both here and comctl32undoc.c !!! */ 50 typedef struct tagCREATEMRULIST 51 { 52 DWORD cbSize; /* size of struct */ 53 DWORD nMaxItems; /* max no. of items in list */ 54 DWORD dwFlags; /* see below */ 55 HKEY hKey; /* root reg. key under which list is saved */ 56 LPCSTR lpszSubKey; /* reg. subkey */ 57 int (CALLBACK *lpfnCompare)(LPCVOID, LPCVOID, DWORD); /* item compare proc */ 58 } CREATEMRULISTA, *LPCREATEMRULISTA; 59 60 /* dwFlags */ 61 #define MRUF_STRING_LIST 0 /* list will contain strings */ 62 #define MRUF_BINARY_LIST 1 /* list will contain binary data */ 63 #define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */ 64 65 extern HANDLE WINAPI CreateMRUListA(LPCREATEMRULISTA lpcml); 66 extern VOID WINAPI FreeMRUList(HANDLE hMRUList); 67 extern INT WINAPI AddMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData); 68 extern INT WINAPI FindMRUData(HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum); 69 extern INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer, DWORD nBufferSize); 70 71 72 /************************************************************************* 73 * ParseFieldA [internal] 74 * 75 * copies a field from a ',' delimited string 76 * 77 * first field is nField = 1 78 */ 79 DWORD WINAPI ParseFieldA( 80 LPCSTR src, 81 DWORD nField, 82 LPSTR dst, 83 DWORD len) 84 { 85 WARN("(%s,0x%08x,%p,%d) semi-stub.\n",debugstr_a(src),nField,dst,len); 86 87 if (!src || !src[0] || !dst || !len) 88 return 0; 89 90 /* skip n fields delimited by ',' */ 91 while (nField > 1) 92 { 93 if (*src=='\0') return FALSE; 94 if (*(src++)==',') nField--; 95 } 96 97 /* copy part till the next ',' to dst */ 98 while ( *src!='\0' && *src!=',' && (len--)>0 ) *(dst++)=*(src++); 99 100 /* finalize the string */ 101 *dst=0x0; 102 103 return TRUE; 104 } 105 106 /************************************************************************* 107 * ParseFieldW [internal] 108 * 109 * copies a field from a ',' delimited string 110 * 111 * first field is nField = 1 112 */ 113 DWORD WINAPI ParseFieldW(LPCWSTR src, DWORD nField, LPWSTR dst, DWORD len) 114 { 115 WARN("(%s,0x%08x,%p,%d) semi-stub.\n", debugstr_w(src), nField, dst, len); 116 117 if (!src || !src[0] || !dst || !len) 118 return 0; 119 120 /* skip n fields delimited by ',' */ 121 while (nField > 1) 122 { 123 if (*src == 0x0) return FALSE; 124 if (*src++ == ',') nField--; 125 } 126 127 /* copy part till the next ',' to dst */ 128 while ( *src != 0x0 && *src != ',' && (len--)>0 ) *(dst++) = *(src++); 129 130 /* finalize the string */ 131 *dst = 0x0; 132 133 return TRUE; 134 } 135 136 /************************************************************************* 137 * ParseField [SHELL32.58] 138 */ 139 DWORD WINAPI ParseFieldAW(LPCVOID src, DWORD nField, LPVOID dst, DWORD len) 140 { 141 if (SHELL_OsIsUnicode()) 142 return ParseFieldW(src, nField, dst, len); 143 return ParseFieldA(src, nField, dst, len); 144 } 145 146 /************************************************************************* 147 * GetFileNameFromBrowse [SHELL32.63] 148 * 149 */ 150 BOOL WINAPI GetFileNameFromBrowse( 151 HWND hwndOwner, 152 LPWSTR lpstrFile, 153 UINT nMaxFile, 154 LPCWSTR lpstrInitialDir, 155 LPCWSTR lpstrDefExt, 156 LPCWSTR lpstrFilter, 157 LPCWSTR lpstrTitle) 158 { 159 typedef BOOL (WINAPI *GetOpenFileNameProc)(OPENFILENAMEW *ofn); 160 HMODULE hmodule; 161 GetOpenFileNameProc pGetOpenFileNameW; 162 OPENFILENAMEW ofn; 163 BOOL ret; 164 165 TRACE("%p, %s, %d, %s, %s, %s, %s)\n", 166 hwndOwner, debugstr_w(lpstrFile), nMaxFile, lpstrInitialDir, lpstrDefExt, 167 lpstrFilter, lpstrTitle); 168 169 hmodule = LoadLibraryW(L"comdlg32.dll"); 170 if(!hmodule) return FALSE; 171 pGetOpenFileNameW = (GetOpenFileNameProc)GetProcAddress(hmodule, "GetOpenFileNameW"); 172 if(!pGetOpenFileNameW) 173 { 174 FreeLibrary(hmodule); 175 return FALSE; 176 } 177 178 memset(&ofn, 0, sizeof(ofn)); 179 180 ofn.lStructSize = sizeof(ofn); 181 ofn.hwndOwner = hwndOwner; 182 ofn.lpstrFilter = lpstrFilter; 183 ofn.lpstrFile = lpstrFile; 184 ofn.nMaxFile = nMaxFile; 185 ofn.lpstrInitialDir = lpstrInitialDir; 186 ofn.lpstrTitle = lpstrTitle; 187 ofn.lpstrDefExt = lpstrDefExt; 188 ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST; 189 ret = pGetOpenFileNameW(&ofn); 190 191 FreeLibrary(hmodule); 192 return ret; 193 } 194 195 /************************************************************************* 196 * SHGetSetSettings [SHELL32.68] 197 */ 198 VOID WINAPI SHGetSetSettings(LPSHELLSTATE lpss, DWORD dwMask, BOOL bSet) 199 { 200 if(bSet) 201 { 202 FIXME("%p 0x%08x TRUE\n", lpss, dwMask); 203 } 204 else 205 { 206 SHGetSettings((LPSHELLFLAGSTATE)lpss,dwMask); 207 } 208 } 209 210 /************************************************************************* 211 * SHGetSettings [SHELL32.@] 212 * 213 * NOTES 214 * the registry path are for win98 (tested) 215 * and possibly are the same in nt40 216 * 217 */ 218 VOID WINAPI SHGetSettings(LPSHELLFLAGSTATE lpsfs, DWORD dwMask) 219 { 220 HKEY hKey; 221 DWORD dwData; 222 DWORD dwDataSize = sizeof (DWORD); 223 224 TRACE("(%p 0x%08x)\n",lpsfs,dwMask); 225 226 if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced", 227 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0)) 228 return; 229 230 if ( (SSF_SHOWEXTENSIONS & dwMask) && !RegQueryValueExA(hKey, "HideFileExt", 0, 0, (LPBYTE)&dwData, &dwDataSize)) 231 lpsfs->fShowExtensions = ((dwData == 0) ? 0 : 1); 232 233 if ( (SSF_SHOWINFOTIP & dwMask) && !RegQueryValueExA(hKey, "ShowInfoTip", 0, 0, (LPBYTE)&dwData, &dwDataSize)) 234 lpsfs->fShowInfoTip = ((dwData == 0) ? 0 : 1); 235 236 if ( (SSF_DONTPRETTYPATH & dwMask) && !RegQueryValueExA(hKey, "DontPrettyPath", 0, 0, (LPBYTE)&dwData, &dwDataSize)) 237 lpsfs->fDontPrettyPath = ((dwData == 0) ? 0 : 1); 238 239 if ( (SSF_HIDEICONS & dwMask) && !RegQueryValueExA(hKey, "HideIcons", 0, 0, (LPBYTE)&dwData, &dwDataSize)) 240 lpsfs->fHideIcons = ((dwData == 0) ? 0 : 1); 241 242 if ( (SSF_MAPNETDRVBUTTON & dwMask) && !RegQueryValueExA(hKey, "MapNetDrvBtn", 0, 0, (LPBYTE)&dwData, &dwDataSize)) 243 lpsfs->fMapNetDrvBtn = ((dwData == 0) ? 0 : 1); 244 245 if ( (SSF_SHOWATTRIBCOL & dwMask) && !RegQueryValueExA(hKey, "ShowAttribCol", 0, 0, (LPBYTE)&dwData, &dwDataSize)) 246 lpsfs->fShowAttribCol = ((dwData == 0) ? 0 : 1); 247 248 if (((SSF_SHOWALLOBJECTS | SSF_SHOWSYSFILES) & dwMask) && !RegQueryValueExA(hKey, "Hidden", 0, 0, (LPBYTE)&dwData, &dwDataSize)) 249 { if (dwData == 0) 250 { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 0; 251 if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 0; 252 } 253 else if (dwData == 1) 254 { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 1; 255 if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 0; 256 } 257 else if (dwData == 2) 258 { if (SSF_SHOWALLOBJECTS & dwMask) lpsfs->fShowAllObjects = 0; 259 if (SSF_SHOWSYSFILES & dwMask) lpsfs->fShowSysFiles = 1; 260 } 261 } 262 RegCloseKey (hKey); 263 264 TRACE("-- 0x%04x\n", *(WORD*)lpsfs); 265 } 266 267 /************************************************************************* 268 * SHShellFolderView_Message [SHELL32.73] 269 * 270 * Send a message to an explorer cabinet window. 271 * 272 * PARAMS 273 * hwndCabinet [I] The window containing the shellview to communicate with 274 * dwMessage [I] The SFVM message to send 275 * dwParam [I] Message parameter 276 * 277 * RETURNS 278 * fixme. 279 * 280 * NOTES 281 * Message SFVM_REARRANGE = 1 282 * 283 * This message gets sent when a column gets clicked to instruct the 284 * shell view to re-sort the item list. dwParam identifies the column 285 * that was clicked. 286 */ 287 LRESULT WINAPI SHShellFolderView_Message( 288 HWND hwndCabinet, 289 UINT uMessage, 290 LPARAM lParam) 291 { 292 FIXME("%p %08x %08lx stub\n",hwndCabinet, uMessage, lParam); 293 return 0; 294 } 295 296 /************************************************************************* 297 * RegisterShellHook [SHELL32.181] 298 * 299 * Register a shell hook. 300 * 301 * PARAMS 302 * hwnd [I] Window handle 303 * dwType [I] Type of hook. 304 * 305 * NOTES 306 * Exported by ordinal 307 */ 308 BOOL WINAPI RegisterShellHook( 309 HWND hWnd, 310 DWORD dwType) 311 { 312 if (dwType == 3) 313 { 314 SetTaskmanWindow(hWnd); 315 return RegisterShellHookWindow(hWnd); 316 } 317 else if (dwType == 0) 318 { 319 return DeregisterShellHookWindow(hWnd); 320 } 321 322 ERR("Unsupported argument"); 323 return FALSE; 324 } 325 326 /************************************************************************* 327 * ShellMessageBoxW [SHELL32.182] 328 * 329 * See ShellMessageBoxA. 330 * 331 * NOTE: 332 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW 333 * because we can't forward to it in the .spec file since it's exported by 334 * ordinal. If you change the implementation here please update the code in 335 * shlwapi as well. 336 */ 337 int ShellMessageBoxW( 338 HINSTANCE hInstance, 339 HWND hWnd, 340 LPCWSTR lpText, 341 LPCWSTR lpCaption, 342 UINT uType, 343 ...) 344 { 345 WCHAR szText[100],szTitle[100]; 346 LPCWSTR pszText = szText, pszTitle = szTitle; 347 LPWSTR pszTemp; 348 __ms_va_list args; 349 int ret; 350 351 __ms_va_start(args, uType); 352 /* wvsprintfA(buf,fmt, args); */ 353 354 TRACE("(%p,%p,%p,%p,%08x)\n", 355 hInstance,hWnd,lpText,lpCaption,uType); 356 357 if (IS_INTRESOURCE(lpCaption)) 358 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0])); 359 else 360 pszTitle = lpCaption; 361 362 if (IS_INTRESOURCE(lpText)) 363 LoadStringW(hInstance, LOWORD(lpText), szText, sizeof(szText)/sizeof(szText[0])); 364 else 365 pszText = lpText; 366 367 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, 368 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args); 369 370 __ms_va_end(args); 371 372 ret = MessageBoxW(hWnd,pszTemp,pszTitle,uType); 373 LocalFree(pszTemp); 374 return ret; 375 } 376 377 /************************************************************************* 378 * ShellMessageBoxA [SHELL32.183] 379 * 380 * Format and output an error message. 381 * 382 * PARAMS 383 * hInstance [I] Instance handle of message creator 384 * hWnd [I] Window handle of message creator 385 * lpText [I] Resource Id of title or LPSTR 386 * lpCaption [I] Resource Id of title or LPSTR 387 * uType [I] Type of error message 388 * 389 * RETURNS 390 * A return value from MessageBoxA(). 391 * 392 * NOTES 393 * Exported by ordinal 394 */ 395 int ShellMessageBoxA( 396 HINSTANCE hInstance, 397 HWND hWnd, 398 LPCSTR lpText, 399 LPCSTR lpCaption, 400 UINT uType, 401 ...) 402 { 403 char szText[100],szTitle[100]; 404 LPCSTR pszText = szText, pszTitle = szTitle; 405 LPSTR pszTemp; 406 __ms_va_list args; 407 int ret; 408 409 __ms_va_start(args, uType); 410 /* wvsprintfA(buf,fmt, args); */ 411 412 TRACE("(%p,%p,%p,%p,%08x)\n", 413 hInstance,hWnd,lpText,lpCaption,uType); 414 415 if (IS_INTRESOURCE(lpCaption)) 416 LoadStringA(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)); 417 else 418 pszTitle = lpCaption; 419 420 if (IS_INTRESOURCE(lpText)) 421 LoadStringA(hInstance, LOWORD(lpText), szText, sizeof(szText)); 422 else 423 pszText = lpText; 424 425 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, 426 pszText, 0, 0, (LPSTR)&pszTemp, 0, &args); 427 428 __ms_va_end(args); 429 430 ret = MessageBoxA(hWnd,pszTemp,pszTitle,uType); 431 LocalFree(pszTemp); 432 return ret; 433 } 434 435 /************************************************************************* 436 * SHRegisterDragDrop [SHELL32.86] 437 * 438 * Probably equivalent to RegisterDragDrop but under Windows 95 it could use the 439 * shell32 built-in "mini-COM" without the need to load ole32.dll - see SHLoadOLE 440 * for details. Under Windows 98 this function initializes the true OLE when called 441 * the first time, on XP always returns E_OUTOFMEMORY and it got removed from Vista. 442 * 443 * We follow Windows 98 behaviour. 444 * 445 * NOTES 446 * exported by ordinal 447 * 448 * SEE ALSO 449 * RegisterDragDrop, SHLoadOLE 450 */ 451 HRESULT WINAPI SHRegisterDragDrop( 452 HWND hWnd, 453 LPDROPTARGET pDropTarget) 454 { 455 static BOOL ole_initialized = FALSE; 456 HRESULT hr; 457 458 TRACE("(%p,%p)\n", hWnd, pDropTarget); 459 460 if (!ole_initialized) 461 { 462 hr = OleInitialize(NULL); 463 if (FAILED(hr)) 464 return hr; 465 ole_initialized = TRUE; 466 } 467 return RegisterDragDrop(hWnd, pDropTarget); 468 } 469 470 /************************************************************************* 471 * SHRevokeDragDrop [SHELL32.87] 472 * 473 * Probably equivalent to RevokeDragDrop but under Windows 95 it could use the 474 * shell32 built-in "mini-COM" without the need to load ole32.dll - see SHLoadOLE 475 * for details. Function removed from Windows Vista. 476 * 477 * We call ole32 RevokeDragDrop which seems to work even if OleInitialize was 478 * not called. 479 * 480 * NOTES 481 * exported by ordinal 482 * 483 * SEE ALSO 484 * RevokeDragDrop, SHLoadOLE 485 */ 486 HRESULT WINAPI SHRevokeDragDrop(HWND hWnd) 487 { 488 TRACE("(%p)\n", hWnd); 489 return RevokeDragDrop(hWnd); 490 } 491 492 /************************************************************************* 493 * SHDoDragDrop [SHELL32.88] 494 * 495 * Probably equivalent to DoDragDrop but under Windows 9x it could use the 496 * shell32 built-in "mini-COM" without the need to load ole32.dll - see SHLoadOLE 497 * for details 498 * 499 * NOTES 500 * exported by ordinal 501 * 502 * SEE ALSO 503 * DoDragDrop, SHLoadOLE 504 */ 505 HRESULT WINAPI SHDoDragDrop( 506 HWND hWnd, 507 LPDATAOBJECT lpDataObject, 508 LPDROPSOURCE lpDropSource, 509 DWORD dwOKEffect, 510 LPDWORD pdwEffect) 511 { 512 FIXME("(%p %p %p 0x%08x %p):stub.\n", 513 hWnd, lpDataObject, lpDropSource, dwOKEffect, pdwEffect); 514 return DoDragDrop(lpDataObject, lpDropSource, dwOKEffect, pdwEffect); 515 } 516 517 /************************************************************************* 518 * ArrangeWindows [SHELL32.184] 519 * 520 */ 521 WORD WINAPI ArrangeWindows(HWND hwndParent, DWORD dwReserved, const RECT *lpRect, 522 WORD cKids, const HWND *lpKids) 523 { 524 /* Unimplemented in WinXP SP3 */ 525 TRACE("(%p 0x%08x %p 0x%04x %p):stub.\n", 526 hwndParent, dwReserved, lpRect, cKids, lpKids); 527 return 0; 528 } 529 530 /************************************************************************* 531 * SignalFileOpen [SHELL32.103] 532 * 533 * NOTES 534 * exported by ordinal 535 */ 536 BOOL WINAPI 537 SignalFileOpen (PCIDLIST_ABSOLUTE pidl) 538 { 539 FIXME("(%p):stub.\n", pidl); 540 541 return FALSE; 542 } 543 544 /************************************************************************* 545 * SHADD_get_policy - helper function for SHAddToRecentDocs 546 * 547 * PARAMETERS 548 * policy [IN] policy name (null termed string) to find 549 * type [OUT] ptr to DWORD to receive type 550 * buffer [OUT] ptr to area to hold data retrieved 551 * len [IN/OUT] ptr to DWORD holding size of buffer and getting 552 * length filled 553 * 554 * RETURNS 555 * result of the SHQueryValueEx call 556 */ 557 static INT SHADD_get_policy(LPCSTR policy, LPDWORD type, LPVOID buffer, LPDWORD len) 558 { 559 HKEY Policy_basekey; 560 INT ret; 561 562 /* Get the key for the policies location in the registry 563 */ 564 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, 565 "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", 566 0, KEY_READ, &Policy_basekey)) { 567 568 if (RegOpenKeyExA(HKEY_CURRENT_USER, 569 "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\Explorer", 570 0, KEY_READ, &Policy_basekey)) { 571 TRACE("No Explorer Policies location exists. Policy wanted=%s\n", 572 policy); 573 *len = 0; 574 return ERROR_FILE_NOT_FOUND; 575 } 576 } 577 578 /* Retrieve the data if it exists 579 */ 580 ret = SHQueryValueExA(Policy_basekey, policy, 0, type, buffer, len); 581 RegCloseKey(Policy_basekey); 582 return ret; 583 } 584 585 586 /************************************************************************* 587 * SHADD_compare_mru - helper function for SHAddToRecentDocs 588 * 589 * PARAMETERS 590 * data1 [IN] data being looked for 591 * data2 [IN] data in MRU 592 * cbdata [IN] length from FindMRUData call (not used) 593 * 594 * RETURNS 595 * position within MRU list that data was added. 596 */ 597 static INT CALLBACK SHADD_compare_mru(LPCVOID data1, LPCVOID data2, DWORD cbData) 598 { 599 return lstrcmpiA(data1, data2); 600 } 601 602 /************************************************************************* 603 * SHADD_create_add_mru_data - helper function for SHAddToRecentDocs 604 * 605 * PARAMETERS 606 * mruhandle [IN] handle for created MRU list 607 * doc_name [IN] null termed pure doc name 608 * new_lnk_name [IN] null termed path and file name for .lnk file 609 * buffer [IN/OUT] 2048 byte area to construct MRU data 610 * len [OUT] ptr to int to receive space used in buffer 611 * 612 * RETURNS 613 * position within MRU list that data was added. 614 */ 615 static INT SHADD_create_add_mru_data(HANDLE mruhandle, LPCSTR doc_name, LPCSTR new_lnk_name, 616 LPSTR buffer, INT *len) 617 { 618 LPSTR ptr; 619 INT wlen; 620 621 /*FIXME: Document: 622 * RecentDocs MRU data structure seems to be: 623 * +0h document file name w/ terminating 0h 624 * +nh short int w/ size of remaining 625 * +n+2h 02h 30h, or 01h 30h, or 00h 30h - unknown 626 * +n+4h 10 bytes zeros - unknown 627 * +n+eh shortcut file name w/ terminating 0h 628 * +n+e+nh 3 zero bytes - unknown 629 */ 630 631 /* Create the MRU data structure for "RecentDocs" 632 */ 633 ptr = buffer; 634 lstrcpyA(ptr, doc_name); 635 ptr += (lstrlenA(buffer) + 1); 636 wlen= lstrlenA(new_lnk_name) + 1 + 12; 637 *((short int*)ptr) = wlen; 638 ptr += 2; /* step past the length */ 639 *(ptr++) = 0x30; /* unknown reason */ 640 *(ptr++) = 0; /* unknown, but can be 0x00, 0x01, 0x02 */ 641 memset(ptr, 0, 10); 642 ptr += 10; 643 lstrcpyA(ptr, new_lnk_name); 644 ptr += (lstrlenA(new_lnk_name) + 1); 645 memset(ptr, 0, 3); 646 ptr += 3; 647 *len = ptr - buffer; 648 649 /* Add the new entry into the MRU list 650 */ 651 return AddMRUData(mruhandle, buffer, *len); 652 } 653 654 /************************************************************************* 655 * SHAddToRecentDocs [SHELL32.@] 656 * 657 * Modify (add/clear) Shell's list of recently used documents. 658 * 659 * PARAMETERS 660 * uFlags [IN] SHARD_PATHA, SHARD_PATHW or SHARD_PIDL 661 * pv [IN] string or pidl, NULL clears the list 662 * 663 * NOTES 664 * exported by name 665 * 666 * FIXME 667 * convert to unicode 668 */ 669 void WINAPI SHAddToRecentDocs (UINT uFlags,LPCVOID pv) 670 { 671 /* If list is a string list lpfnCompare has the following prototype 672 * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2) 673 * for binary lists the prototype is 674 * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData) 675 * where cbData is the no. of bytes to compare. 676 * Need to check what return value means identical - 0? 677 */ 678 679 680 UINT olderrormode; 681 HKEY HCUbasekey; 682 CHAR doc_name[MAX_PATH]; 683 CHAR link_dir[MAX_PATH]; 684 CHAR new_lnk_filepath[MAX_PATH]; 685 CHAR new_lnk_name[MAX_PATH]; 686 CHAR * ext; 687 IMalloc *ppM; 688 LPITEMIDLIST pidl; 689 HWND hwnd = 0; /* FIXME: get real window handle */ 690 INT ret; 691 DWORD data[64], datalen, type; 692 693 TRACE("%04x %p\n", uFlags, pv); 694 695 /*FIXME: Document: 696 * RecentDocs MRU data structure seems to be: 697 * +0h document file name w/ terminating 0h 698 * +nh short int w/ size of remaining 699 * +n+2h 02h 30h, or 01h 30h, or 00h 30h - unknown 700 * +n+4h 10 bytes zeros - unknown 701 * +n+eh shortcut file name w/ terminating 0h 702 * +n+e+nh 3 zero bytes - unknown 703 */ 704 705 /* See if we need to do anything. 706 */ 707 datalen = 64; 708 ret=SHADD_get_policy( "NoRecentDocsHistory", &type, data, &datalen); 709 if ((ret > 0) && (ret != ERROR_FILE_NOT_FOUND)) { 710 ERR("Error %d getting policy \"NoRecentDocsHistory\"\n", ret); 711 return; 712 } 713 if (ret == ERROR_SUCCESS) { 714 if (!( (type == REG_DWORD) || 715 ((type == REG_BINARY) && (datalen == 4)) )) { 716 ERR("Error policy data for \"NoRecentDocsHistory\" not formatted correctly, type=%d, len=%d\n", 717 type, datalen); 718 return; 719 } 720 721 TRACE("policy value for NoRecentDocsHistory = %08x\n", data[0]); 722 /* now test the actual policy value */ 723 if ( data[0] != 0) 724 return; 725 } 726 727 /* Open key to where the necessary info is 728 */ 729 /* FIXME: This should be done during DLL PROCESS_ATTACH (or THREAD_ATTACH) 730 * and the close should be done during the _DETACH. The resulting 731 * key is stored in the DLL global data. 732 */ 733 if (RegCreateKeyExA(HKEY_CURRENT_USER, 734 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer", 735 0, 0, 0, KEY_READ, 0, &HCUbasekey, 0)) { 736 ERR("Failed to create 'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer'\n"); 737 return; 738 } 739 740 /* Get path to user's "Recent" directory 741 */ 742 if(SUCCEEDED(SHGetMalloc(&ppM))) { 743 if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_RECENT, 744 &pidl))) { 745 SHGetPathFromIDListA(pidl, link_dir); 746 IMalloc_Free(ppM, pidl); 747 } 748 else { 749 /* serious issues */ 750 link_dir[0] = 0; 751 ERR("serious issues 1\n"); 752 } 753 IMalloc_Release(ppM); 754 } 755 else { 756 /* serious issues */ 757 link_dir[0] = 0; 758 ERR("serious issues 2\n"); 759 } 760 TRACE("Users Recent dir %s\n", link_dir); 761 762 /* If no input, then go clear the lists */ 763 if (!pv) { 764 /* clear user's Recent dir 765 */ 766 767 /* FIXME: delete all files in "link_dir" 768 * 769 * while( more files ) { 770 * lstrcpyA(old_lnk_name, link_dir); 771 * PathAppendA(old_lnk_name, filenam); 772 * DeleteFileA(old_lnk_name); 773 * } 774 */ 775 FIXME("should delete all files in %s\\\n", link_dir); 776 777 /* clear MRU list 778 */ 779 /* MS Bug ?? v4.72.3612.1700 of shell32 does the delete against 780 * HKEY_LOCAL_MACHINE version of ...CurrentVersion\Explorer 781 * and naturally it fails w/ rc=2. It should do it against 782 * HKEY_CURRENT_USER which is where it is stored, and where 783 * the MRU routines expect it!!!! 784 */ 785 RegDeleteKeyA(HCUbasekey, "RecentDocs"); 786 RegCloseKey(HCUbasekey); 787 return; 788 } 789 790 /* Have data to add, the jobs to be done: 791 * 1. Add document to MRU list in registry "HKCU\Software\ 792 * Microsoft\Windows\CurrentVersion\Explorer\RecentDocs". 793 * 2. Add shortcut to document in the user's Recent directory 794 * (CSIDL_RECENT). 795 * 3. Add shortcut to Start menu's Documents submenu. 796 */ 797 798 /* Get the pure document name from the input 799 */ 800 switch (uFlags) 801 { 802 case SHARD_PIDL: 803 if (!SHGetPathFromIDListA(pv, doc_name)) 804 { 805 WARN("can't get path from PIDL\n"); 806 return; 807 } 808 break; 809 810 case SHARD_PATHA: 811 lstrcpynA(doc_name, pv, MAX_PATH); 812 break; 813 814 case SHARD_PATHW: 815 WideCharToMultiByte(CP_ACP, 0, pv, -1, doc_name, MAX_PATH, NULL, NULL); 816 break; 817 818 default: 819 FIXME("Unsupported flags: %u\n", uFlags); 820 return; 821 } 822 823 TRACE("full document name %s\n", debugstr_a(doc_name)); 824 825 #ifdef __REACTOS__ 826 /* check if file is a shortcut */ 827 ext = strrchr(doc_name, '.'); 828 if (!lstrcmpiA(ext, ".lnk")) 829 { 830 WCHAR doc_nameW[MAX_PATH]; 831 IShellLinkA* ShellLink; 832 int nLength = MultiByteToWideChar(CP_ACP, 0, doc_name, -1, doc_nameW, MAX_PATH); 833 if (nLength == 0) 834 return; 835 836 IShellLink_ConstructFromPath(doc_nameW, &IID_IShellLinkA, (LPVOID*)&ShellLink); 837 IShellLinkA_GetPath(ShellLink, doc_name, MAX_PATH, NULL, 0); 838 IShellLinkA_Release(ShellLink); 839 } 840 841 ext = strrchr(doc_name, '.'); 842 if (!lstrcmpiA(ext, ".exe")) 843 { 844 /* executables are not added */ 845 return; 846 } 847 #endif 848 849 PathStripPathA(doc_name); 850 TRACE("stripped document name %s\n", debugstr_a(doc_name)); 851 852 853 /* *** JOB 1: Update registry for ...\Explorer\RecentDocs list *** */ 854 855 { /* on input needs: 856 * doc_name - pure file-spec, no path 857 * link_dir - path to the user's Recent directory 858 * HCUbasekey - key of ...Windows\CurrentVersion\Explorer" node 859 * creates: 860 * new_lnk_name- pure file-spec, no path for new .lnk file 861 * new_lnk_filepath 862 * - path and file name of new .lnk file 863 */ 864 CREATEMRULISTA mymru; 865 HANDLE mruhandle; 866 INT len, pos, bufused, err; 867 INT i; 868 DWORD attr; 869 CHAR buffer[2048]; 870 CHAR *ptr; 871 CHAR old_lnk_name[MAX_PATH]; 872 short int slen; 873 874 mymru.cbSize = sizeof(CREATEMRULISTA); 875 mymru.nMaxItems = 15; 876 mymru.dwFlags = MRUF_BINARY_LIST | MRUF_DELAYED_SAVE; 877 mymru.hKey = HCUbasekey; 878 mymru.lpszSubKey = "RecentDocs"; 879 mymru.lpfnCompare = SHADD_compare_mru; 880 mruhandle = CreateMRUListA(&mymru); 881 if (!mruhandle) { 882 /* MRU failed */ 883 ERR("MRU processing failed, handle zero\n"); 884 RegCloseKey(HCUbasekey); 885 return; 886 } 887 len = lstrlenA(doc_name); 888 pos = FindMRUData(mruhandle, doc_name, len, 0); 889 890 /* Now get the MRU entry that will be replaced 891 * and delete the .lnk file for it 892 */ 893 if ((bufused = EnumMRUListA(mruhandle, (pos == -1) ? 14 : pos, 894 buffer, 2048)) != -1) { 895 ptr = buffer; 896 ptr += (lstrlenA(buffer) + 1); 897 slen = *((short int*)ptr); 898 ptr += 2; /* skip the length area */ 899 if (bufused >= slen + (ptr-buffer)) { 900 /* buffer size looks good */ 901 ptr += 12; /* get to string */ 902 len = bufused - (ptr-buffer); /* get length of buf remaining */ 903 if (ptr[0] && (lstrlenA(ptr) <= len-1)) { 904 /* appears to be good string */ 905 lstrcpyA(old_lnk_name, link_dir); 906 PathAppendA(old_lnk_name, ptr); 907 if (!DeleteFileA(old_lnk_name)) { 908 if ((attr = GetFileAttributesA(old_lnk_name)) == INVALID_FILE_ATTRIBUTES) { 909 if ((err = GetLastError()) != ERROR_FILE_NOT_FOUND) { 910 ERR("Delete for %s failed, err=%d, attr=%08x\n", 911 old_lnk_name, err, attr); 912 } 913 else { 914 TRACE("old .lnk file %s did not exist\n", 915 old_lnk_name); 916 } 917 } 918 else { 919 ERR("Delete for %s failed, attr=%08x\n", 920 old_lnk_name, attr); 921 } 922 } 923 else { 924 TRACE("deleted old .lnk file %s\n", old_lnk_name); 925 } 926 } 927 } 928 } 929 930 /* Create usable .lnk file name for the "Recent" directory 931 */ 932 wsprintfA(new_lnk_name, "%s.lnk", doc_name); 933 lstrcpyA(new_lnk_filepath, link_dir); 934 PathAppendA(new_lnk_filepath, new_lnk_name); 935 i = 1; 936 olderrormode = SetErrorMode(SEM_FAILCRITICALERRORS); 937 while (GetFileAttributesA(new_lnk_filepath) != INVALID_FILE_ATTRIBUTES) { 938 i++; 939 wsprintfA(new_lnk_name, "%s (%u).lnk", doc_name, i); 940 lstrcpyA(new_lnk_filepath, link_dir); 941 PathAppendA(new_lnk_filepath, new_lnk_name); 942 } 943 SetErrorMode(olderrormode); 944 TRACE("new shortcut will be %s\n", new_lnk_filepath); 945 946 /* Now add the new MRU entry and data 947 */ 948 pos = SHADD_create_add_mru_data(mruhandle, doc_name, new_lnk_name, 949 buffer, &len); 950 FreeMRUList(mruhandle); 951 TRACE("Updated MRU list, new doc is position %d\n", pos); 952 } 953 954 /* *** JOB 2: Create shortcut in user's "Recent" directory *** */ 955 956 { /* on input needs: 957 * doc_name - pure file-spec, no path 958 * new_lnk_filepath 959 * - path and file name of new .lnk file 960 * uFlags[in] - flags on call to SHAddToRecentDocs 961 * pv[in] - document path/pidl on call to SHAddToRecentDocs 962 */ 963 IShellLinkA *psl = NULL; 964 IPersistFile *pPf = NULL; 965 HRESULT hres; 966 CHAR desc[MAX_PATH]; 967 WCHAR widelink[MAX_PATH]; 968 969 CoInitialize(0); 970 971 hres = CoCreateInstance( &CLSID_ShellLink, 972 NULL, 973 CLSCTX_INPROC_SERVER, 974 &IID_IShellLinkA, 975 (LPVOID )&psl); 976 if(SUCCEEDED(hres)) { 977 978 hres = IShellLinkA_QueryInterface(psl, &IID_IPersistFile, 979 (LPVOID *)&pPf); 980 if(FAILED(hres)) { 981 /* bombed */ 982 ERR("failed QueryInterface for IPersistFile %08x\n", hres); 983 goto fail; 984 } 985 986 /* Set the document path or pidl */ 987 if (uFlags == SHARD_PIDL) { 988 hres = IShellLinkA_SetIDList(psl, pv); 989 } else { 990 hres = IShellLinkA_SetPath(psl, pv); 991 } 992 if(FAILED(hres)) { 993 /* bombed */ 994 ERR("failed Set{IDList|Path} %08x\n", hres); 995 goto fail; 996 } 997 998 lstrcpyA(desc, "Shortcut to "); 999 lstrcatA(desc, doc_name); 1000 hres = IShellLinkA_SetDescription(psl, desc); 1001 if(FAILED(hres)) { 1002 /* bombed */ 1003 ERR("failed SetDescription %08x\n", hres); 1004 goto fail; 1005 } 1006 1007 MultiByteToWideChar(CP_ACP, 0, new_lnk_filepath, -1, 1008 widelink, MAX_PATH); 1009 /* create the short cut */ 1010 hres = IPersistFile_Save(pPf, widelink, TRUE); 1011 if(FAILED(hres)) { 1012 /* bombed */ 1013 ERR("failed IPersistFile::Save %08x\n", hres); 1014 IPersistFile_Release(pPf); 1015 IShellLinkA_Release(psl); 1016 goto fail; 1017 } 1018 hres = IPersistFile_SaveCompleted(pPf, widelink); 1019 IPersistFile_Release(pPf); 1020 IShellLinkA_Release(psl); 1021 TRACE("shortcut %s has been created, result=%08x\n", 1022 new_lnk_filepath, hres); 1023 } 1024 else { 1025 ERR("CoCreateInstance failed, hres=%08x\n", hres); 1026 } 1027 } 1028 1029 fail: 1030 CoUninitialize(); 1031 1032 /* all done */ 1033 RegCloseKey(HCUbasekey); 1034 return; 1035 } 1036 1037 /************************************************************************* 1038 * SHCreateShellFolderViewEx [SHELL32.174] 1039 * 1040 * Create a new instance of the default Shell folder view object. 1041 * 1042 * RETURNS 1043 * Success: S_OK 1044 * Failure: error value 1045 * 1046 * NOTES 1047 * see IShellFolder::CreateViewObject 1048 */ 1049 #ifndef __REACTOS__ 1050 1051 HRESULT WINAPI SHCreateShellFolderViewEx( 1052 LPCSFV psvcbi, /* [in] shelltemplate struct */ 1053 IShellView **ppv) /* [out] IShellView pointer */ 1054 { 1055 IShellView * psf; 1056 HRESULT hRes; 1057 1058 TRACE("sf=%p pidl=%p cb=%p mode=0x%08x parm=%p\n", 1059 psvcbi->pshf, psvcbi->pidl, psvcbi->pfnCallback, 1060 psvcbi->fvm, psvcbi->psvOuter); 1061 1062 *ppv = NULL; 1063 hRes = IShellView_Constructor(psvcbi->pshf, &psf); 1064 1065 if (FAILED(hRes)) 1066 return hRes; 1067 1068 hRes = IShellView_QueryInterface(psf, &IID_IShellView, (LPVOID *)ppv); 1069 IShellView_Release(psf); 1070 1071 return hRes; 1072 } 1073 #endif 1074 1075 /************************************************************************* 1076 * SHWinHelp [SHELL32.127] 1077 * 1078 */ 1079 HRESULT WINAPI SHWinHelp (DWORD v, DWORD w, DWORD x, DWORD z) 1080 { FIXME("0x%08x 0x%08x 0x%08x 0x%08x stub\n",v,w,x,z); 1081 return 0; 1082 } 1083 /************************************************************************* 1084 * SHRunControlPanel [SHELL32.161] 1085 * 1086 */ 1087 BOOL WINAPI SHRunControlPanel (LPCWSTR commandLine, HWND parent) 1088 { 1089 FIXME("(%s, %p): stub\n", debugstr_w(commandLine), parent); 1090 return FALSE; 1091 } 1092 1093 static LPUNKNOWN SHELL32_IExplorerInterface=0; 1094 /************************************************************************* 1095 * SHSetInstanceExplorer [SHELL32.176] 1096 * 1097 * NOTES 1098 * Sets the interface 1099 */ 1100 VOID WINAPI SHSetInstanceExplorer (LPUNKNOWN lpUnknown) 1101 { TRACE("%p\n", lpUnknown); 1102 SHELL32_IExplorerInterface = lpUnknown; 1103 } 1104 /************************************************************************* 1105 * SHGetInstanceExplorer [SHELL32.@] 1106 * 1107 * NOTES 1108 * gets the interface pointer of the explorer and a reference 1109 */ 1110 HRESULT WINAPI SHGetInstanceExplorer (IUnknown **lpUnknown) 1111 { TRACE("%p\n", lpUnknown); 1112 1113 *lpUnknown = SHELL32_IExplorerInterface; 1114 1115 if (!SHELL32_IExplorerInterface) 1116 return E_FAIL; 1117 1118 IUnknown_AddRef(SHELL32_IExplorerInterface); 1119 return S_OK; 1120 } 1121 /************************************************************************* 1122 * SHFreeUnusedLibraries [SHELL32.123] 1123 * 1124 * Probably equivalent to CoFreeUnusedLibraries but under Windows 9x it could use 1125 * the shell32 built-in "mini-COM" without the need to load ole32.dll - see SHLoadOLE 1126 * for details 1127 * 1128 * NOTES 1129 * exported by ordinal 1130 * 1131 * SEE ALSO 1132 * CoFreeUnusedLibraries, SHLoadOLE 1133 */ 1134 void WINAPI SHFreeUnusedLibraries (void) 1135 { 1136 FIXME("stub\n"); 1137 CoFreeUnusedLibraries(); 1138 } 1139 /************************************************************************* 1140 * DAD_AutoScroll [SHELL32.129] 1141 * 1142 */ 1143 BOOL WINAPI DAD_AutoScroll(HWND hwnd, AUTO_SCROLL_DATA *samples, const POINT * pt) 1144 { 1145 FIXME("hwnd = %p %p %p\n",hwnd,samples,pt); 1146 return FALSE; 1147 } 1148 /************************************************************************* 1149 * DAD_DragEnter [SHELL32.130] 1150 * 1151 */ 1152 BOOL WINAPI DAD_DragEnter(HWND hwnd) 1153 { 1154 FIXME("hwnd = %p\n",hwnd); 1155 return FALSE; 1156 } 1157 /************************************************************************* 1158 * DAD_DragEnterEx [SHELL32.131] 1159 * 1160 */ 1161 BOOL WINAPI DAD_DragEnterEx(HWND hwnd, POINT p) 1162 { 1163 FIXME("hwnd = %p (%d,%d)\n",hwnd,p.x,p.y); 1164 return FALSE; 1165 } 1166 /************************************************************************* 1167 * DAD_DragMove [SHELL32.134] 1168 * 1169 */ 1170 BOOL WINAPI DAD_DragMove(POINT p) 1171 { 1172 FIXME("(%d,%d)\n",p.x,p.y); 1173 return FALSE; 1174 } 1175 /************************************************************************* 1176 * DAD_DragLeave [SHELL32.132] 1177 * 1178 */ 1179 BOOL WINAPI DAD_DragLeave(VOID) 1180 { 1181 FIXME("\n"); 1182 return FALSE; 1183 } 1184 /************************************************************************* 1185 * DAD_SetDragImage [SHELL32.136] 1186 * 1187 * NOTES 1188 * exported by name 1189 */ 1190 BOOL WINAPI DAD_SetDragImage( 1191 HIMAGELIST himlTrack, 1192 LPPOINT lppt) 1193 { 1194 FIXME("%p %p stub\n",himlTrack, lppt); 1195 return FALSE; 1196 } 1197 /************************************************************************* 1198 * DAD_ShowDragImage [SHELL32.137] 1199 * 1200 * NOTES 1201 * exported by name 1202 */ 1203 BOOL WINAPI DAD_ShowDragImage(BOOL bShow) 1204 { 1205 FIXME("0x%08x stub\n",bShow); 1206 return FALSE; 1207 } 1208 1209 static const WCHAR szwCabLocation[] = { 1210 'S','o','f','t','w','a','r','e','\\', 1211 'M','i','c','r','o','s','o','f','t','\\', 1212 'W','i','n','d','o','w','s','\\', 1213 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 1214 'E','x','p','l','o','r','e','r','\\', 1215 'C','a','b','i','n','e','t','S','t','a','t','e',0 1216 }; 1217 1218 static const WCHAR szwSettings[] = { 'S','e','t','t','i','n','g','s',0 }; 1219 1220 /************************************************************************* 1221 * ReadCabinetState [SHELL32.651] NT 4.0 1222 * 1223 */ 1224 BOOL WINAPI ReadCabinetState(CABINETSTATE *cs, int length) 1225 { 1226 HKEY hkey = 0; 1227 DWORD type, r; 1228 1229 TRACE("%p %d\n", cs, length); 1230 1231 if( (cs == NULL) || (length < (int)sizeof(*cs)) ) 1232 return FALSE; 1233 1234 r = RegOpenKeyW( HKEY_CURRENT_USER, szwCabLocation, &hkey ); 1235 if( r == ERROR_SUCCESS ) 1236 { 1237 type = REG_BINARY; 1238 r = RegQueryValueExW( hkey, szwSettings, 1239 NULL, &type, (LPBYTE)cs, (LPDWORD)&length ); 1240 RegCloseKey( hkey ); 1241 1242 } 1243 1244 /* if we can't read from the registry, create default values */ 1245 if ( (r != ERROR_SUCCESS) || (cs->cLength < sizeof(*cs)) || 1246 (cs->cLength != length) ) 1247 { 1248 TRACE("Initializing shell cabinet settings\n"); 1249 memset(cs, 0, sizeof(*cs)); 1250 cs->cLength = sizeof(*cs); 1251 cs->nVersion = 2; 1252 cs->fFullPathTitle = FALSE; 1253 cs->fSaveLocalView = TRUE; 1254 cs->fNotShell = FALSE; 1255 cs->fSimpleDefault = TRUE; 1256 cs->fDontShowDescBar = FALSE; 1257 cs->fNewWindowMode = FALSE; 1258 cs->fShowCompColor = FALSE; 1259 cs->fDontPrettyNames = FALSE; 1260 cs->fAdminsCreateCommonGroups = TRUE; 1261 cs->fMenuEnumFilter = 96; 1262 } 1263 1264 return TRUE; 1265 } 1266 1267 /************************************************************************* 1268 * WriteCabinetState [SHELL32.652] NT 4.0 1269 * 1270 */ 1271 BOOL WINAPI WriteCabinetState(CABINETSTATE *cs) 1272 { 1273 DWORD r; 1274 HKEY hkey = 0; 1275 1276 TRACE("%p\n",cs); 1277 1278 if( cs == NULL ) 1279 return FALSE; 1280 1281 r = RegCreateKeyExW( HKEY_CURRENT_USER, szwCabLocation, 0, 1282 NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL); 1283 if( r == ERROR_SUCCESS ) 1284 { 1285 r = RegSetValueExW( hkey, szwSettings, 0, 1286 REG_BINARY, (LPBYTE) cs, cs->cLength); 1287 1288 RegCloseKey( hkey ); 1289 } 1290 1291 return (r==ERROR_SUCCESS); 1292 } 1293 1294 /************************************************************************* 1295 * FileIconInit [SHELL32.660] 1296 * 1297 */ 1298 BOOL WINAPI FileIconInit(BOOL bFullInit) 1299 { 1300 return SIC_Initialize(); 1301 } 1302 1303 /************************************************************************* 1304 * IsUserAnAdmin [SHELL32.680] NT 4.0 1305 * 1306 * Checks whether the current user is a member of the Administrators group. 1307 * 1308 * PARAMS 1309 * None 1310 * 1311 * RETURNS 1312 * Success: TRUE 1313 * Failure: FALSE 1314 */ 1315 BOOL WINAPI IsUserAnAdmin(VOID) 1316 { 1317 SID_IDENTIFIER_AUTHORITY Authority = {SECURITY_NT_AUTHORITY}; 1318 HANDLE hToken; 1319 DWORD dwSize; 1320 PTOKEN_GROUPS lpGroups; 1321 PSID lpSid; 1322 DWORD i; 1323 BOOL bResult = FALSE; 1324 1325 TRACE("\n"); 1326 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) 1327 { 1328 return FALSE; 1329 } 1330 1331 if (!GetTokenInformation(hToken, TokenGroups, NULL, 0, &dwSize)) 1332 { 1333 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) 1334 { 1335 CloseHandle(hToken); 1336 return FALSE; 1337 } 1338 } 1339 1340 lpGroups = HeapAlloc(GetProcessHeap(), 0, dwSize); 1341 if (lpGroups == NULL) 1342 { 1343 CloseHandle(hToken); 1344 return FALSE; 1345 } 1346 1347 if (!GetTokenInformation(hToken, TokenGroups, lpGroups, dwSize, &dwSize)) 1348 { 1349 HeapFree(GetProcessHeap(), 0, lpGroups); 1350 CloseHandle(hToken); 1351 return FALSE; 1352 } 1353 1354 CloseHandle(hToken); 1355 if (!AllocateAndInitializeSid(&Authority, 2, SECURITY_BUILTIN_DOMAIN_RID, 1356 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, 1357 &lpSid)) 1358 { 1359 HeapFree(GetProcessHeap(), 0, lpGroups); 1360 return FALSE; 1361 } 1362 1363 for (i = 0; i < lpGroups->GroupCount; i++) 1364 { 1365 if (EqualSid(lpSid, lpGroups->Groups[i].Sid)) 1366 { 1367 bResult = TRUE; 1368 break; 1369 } 1370 } 1371 1372 FreeSid(lpSid); 1373 HeapFree(GetProcessHeap(), 0, lpGroups); 1374 return bResult; 1375 } 1376 1377 /************************************************************************* 1378 * SetAppStartingCursor [SHELL32.99] 1379 */ 1380 HRESULT WINAPI SetAppStartingCursor(HWND u, DWORD v) 1381 { FIXME("hwnd=%p 0x%04x stub\n",u,v ); 1382 return 0; 1383 } 1384 1385 /************************************************************************* 1386 * SHLoadOLE [SHELL32.151] 1387 * 1388 * To reduce the memory usage of Windows 95, its shell32 contained an 1389 * internal implementation of a part of COM (see e.g. SHGetMalloc, SHCoCreateInstance, 1390 * SHRegisterDragDrop etc.) that allowed to use in-process STA objects without 1391 * the need to load OLE32.DLL. If OLE32.DLL was already loaded, the SH* function 1392 * would just call the Co* functions. 1393 * 1394 * The SHLoadOLE was called when OLE32.DLL was being loaded to transfer all the 1395 * information from the shell32 "mini-COM" to ole32.dll. 1396 * 1397 * See http://blogs.msdn.com/oldnewthing/archive/2004/07/05/173226.aspx for a 1398 * detailed description. 1399 * 1400 * Under wine ole32.dll is always loaded as it is imported by shlwapi.dll which is 1401 * imported by shell32 and no "mini-COM" is used (except for the "LoadWithoutCOM" 1402 * hack in SHCoCreateInstance) 1403 */ 1404 HRESULT WINAPI SHLoadOLE(LPARAM lParam) 1405 { FIXME("0x%08lx stub\n",lParam); 1406 return S_OK; 1407 } 1408 /************************************************************************* 1409 * DriveType [SHELL32.64] 1410 * 1411 */ 1412 int WINAPI DriveType(int DriveType) 1413 { 1414 WCHAR root[] = L"A:\\"; 1415 root[0] = L'A' + DriveType; 1416 return GetDriveTypeW(root); 1417 } 1418 /************************************************************************* 1419 * InvalidateDriveType [SHELL32.65] 1420 * Unimplemented in XP SP3 1421 */ 1422 int WINAPI InvalidateDriveType(int u) 1423 { 1424 TRACE("0x%08x stub\n",u); 1425 return 0; 1426 } 1427 /************************************************************************* 1428 * SHAbortInvokeCommand [SHELL32.198] 1429 * 1430 */ 1431 HRESULT WINAPI SHAbortInvokeCommand(void) 1432 { FIXME("stub\n"); 1433 return 1; 1434 } 1435 /************************************************************************* 1436 * SHOutOfMemoryMessageBox [SHELL32.126] 1437 * 1438 */ 1439 int WINAPI SHOutOfMemoryMessageBox( 1440 HWND hwndOwner, 1441 LPCSTR lpCaption, 1442 UINT uType) 1443 { 1444 FIXME("%p %s 0x%08x stub\n",hwndOwner, lpCaption, uType); 1445 return 0; 1446 } 1447 /************************************************************************* 1448 * SHFlushClipboard [SHELL32.121] 1449 * 1450 */ 1451 HRESULT WINAPI SHFlushClipboard(void) 1452 { 1453 return OleFlushClipboard(); 1454 } 1455 1456 /************************************************************************* 1457 * SHWaitForFileToOpen [SHELL32.97] 1458 * 1459 */ 1460 BOOL WINAPI SHWaitForFileToOpen( 1461 LPCITEMIDLIST pidl, 1462 DWORD dwFlags, 1463 DWORD dwTimeout) 1464 { 1465 FIXME("%p 0x%08x 0x%08x stub\n", pidl, dwFlags, dwTimeout); 1466 return FALSE; 1467 } 1468 1469 /************************************************************************ 1470 * RLBuildListOfPaths [SHELL32.146] 1471 * 1472 * NOTES 1473 * builds a DPA 1474 */ 1475 DWORD WINAPI RLBuildListOfPaths (void) 1476 { FIXME("stub\n"); 1477 return 0; 1478 } 1479 /************************************************************************ 1480 * SHValidateUNC [SHELL32.173] 1481 * 1482 */ 1483 BOOL WINAPI SHValidateUNC (HWND hwndOwner, PWSTR pszFile, UINT fConnect) 1484 { 1485 FIXME("(%p, %s, 0x%08x): stub\n", hwndOwner, debugstr_w(pszFile), fConnect); 1486 return FALSE; 1487 } 1488 1489 /************************************************************************ 1490 * DoEnvironmentSubstA [SHELL32.@] 1491 * 1492 * See DoEnvironmentSubstW. 1493 */ 1494 DWORD WINAPI DoEnvironmentSubstA(LPSTR pszString, UINT cchString) 1495 { 1496 LPSTR dst; 1497 BOOL res = FALSE; 1498 DWORD len = cchString; 1499 1500 TRACE("(%s, %d)\n", debugstr_a(pszString), cchString); 1501 if (pszString == NULL) /* Really return 0? */ 1502 return 0; 1503 if ((dst = (LPSTR)HeapAlloc(GetProcessHeap(), 0, cchString * sizeof(CHAR)))) 1504 { 1505 len = ExpandEnvironmentStringsA(pszString, dst, cchString); 1506 /* len includes the terminating 0 */ 1507 if (len && len < cchString) 1508 { 1509 res = TRUE; 1510 memcpy(pszString, dst, len); 1511 } 1512 else 1513 len = cchString; 1514 1515 HeapFree(GetProcessHeap(), 0, dst); 1516 } 1517 return MAKELONG(len, res); 1518 } 1519 1520 /************************************************************************ 1521 * DoEnvironmentSubstW [SHELL32.@] 1522 * 1523 * Replace all %KEYWORD% in the string with the value of the named 1524 * environment variable. If the buffer is too small, the string is not modified. 1525 * 1526 * PARAMS 1527 * pszString [I] '\0' terminated string with %keyword%. 1528 * [O] '\0' terminated string with %keyword% substituted. 1529 * cchString [I] size of str. 1530 * 1531 * RETURNS 1532 * Success: The string in the buffer is updated 1533 * HIWORD: TRUE 1534 * LOWORD: characters used in the buffer, including space for the terminating 0 1535 * Failure: buffer too small. The string is not modified. 1536 * HIWORD: FALSE 1537 * LOWORD: provided size of the buffer in characters 1538 */ 1539 DWORD WINAPI DoEnvironmentSubstW(LPWSTR pszString, UINT cchString) 1540 { 1541 LPWSTR dst; 1542 BOOL res = FALSE; 1543 DWORD len = cchString; 1544 1545 TRACE("(%s, %d)\n", debugstr_w(pszString), cchString); 1546 1547 if ((cchString < MAXLONG) && (dst = HeapAlloc(GetProcessHeap(), 0, cchString * sizeof(WCHAR)))) 1548 { 1549 len = ExpandEnvironmentStringsW(pszString, dst, cchString); 1550 /* len includes the terminating 0 */ 1551 if (len && len <= cchString) 1552 { 1553 res = TRUE; 1554 memcpy(pszString, dst, len * sizeof(WCHAR)); 1555 } 1556 else 1557 len = cchString; 1558 1559 HeapFree(GetProcessHeap(), 0, dst); 1560 } 1561 return MAKELONG(len, res); 1562 } 1563 1564 /************************************************************************ 1565 * DoEnvironmentSubst [SHELL32.53] 1566 * 1567 * See DoEnvironmentSubstA. 1568 */ 1569 DWORD WINAPI DoEnvironmentSubstAW(LPVOID x, UINT y) 1570 { 1571 if (SHELL_OsIsUnicode()) 1572 return DoEnvironmentSubstW(x, y); 1573 return DoEnvironmentSubstA(x, y); 1574 } 1575 1576 /************************************************************************* 1577 * GUIDFromStringA [SHELL32.703] 1578 */ 1579 BOOL WINAPI GUIDFromStringA(LPCSTR str, LPGUID guid) 1580 { 1581 TRACE("GUIDFromStringA() stub\n"); 1582 return FALSE; 1583 } 1584 1585 /************************************************************************* 1586 * GUIDFromStringW [SHELL32.704] 1587 */ 1588 BOOL WINAPI GUIDFromStringW(LPCWSTR str, LPGUID guid) 1589 { 1590 UNICODE_STRING guid_str; 1591 1592 RtlInitUnicodeString(&guid_str, str); 1593 return !RtlGUIDFromString(&guid_str, guid); 1594 } 1595 1596 /************************************************************************* 1597 * PathIsTemporaryA [SHELL32.713] 1598 */ 1599 BOOL WINAPI PathIsTemporaryA(LPSTR Str) 1600 { 1601 FIXME("(%s)stub\n", debugstr_a(Str)); 1602 return FALSE; 1603 } 1604 1605 /************************************************************************* 1606 * PathIsTemporaryW [SHELL32.714] 1607 */ 1608 BOOL WINAPI PathIsTemporaryW(LPWSTR Str) 1609 { 1610 FIXME("(%s)stub\n", debugstr_w(Str)); 1611 return FALSE; 1612 } 1613 1614 typedef struct _PSXA 1615 { 1616 UINT uiCount; 1617 UINT uiAllocated; 1618 IShellPropSheetExt *pspsx[1]; 1619 } PSXA, *PPSXA; 1620 1621 typedef struct _PSXA_CALL 1622 { 1623 LPFNADDPROPSHEETPAGE lpfnAddReplaceWith; 1624 LPARAM lParam; 1625 BOOL bCalled; 1626 BOOL bMultiple; 1627 UINT uiCount; 1628 } PSXA_CALL, *PPSXA_CALL; 1629 1630 static BOOL CALLBACK PsxaCall(HPROPSHEETPAGE hpage, LPARAM lParam) 1631 { 1632 PPSXA_CALL Call = (PPSXA_CALL)lParam; 1633 1634 if (Call != NULL) 1635 { 1636 if ((Call->bMultiple || !Call->bCalled) && 1637 Call->lpfnAddReplaceWith(hpage, Call->lParam)) 1638 { 1639 Call->bCalled = TRUE; 1640 Call->uiCount++; 1641 return TRUE; 1642 } 1643 } 1644 1645 return FALSE; 1646 } 1647 1648 /************************************************************************* 1649 * SHAddFromPropSheetExtArray [SHELL32.167] 1650 */ 1651 UINT WINAPI SHAddFromPropSheetExtArray(HPSXA hpsxa, LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam) 1652 { 1653 PSXA_CALL Call; 1654 UINT i; 1655 PPSXA psxa = (PPSXA)hpsxa; 1656 1657 TRACE("(%p,%p,%08lx)\n", hpsxa, lpfnAddPage, lParam); 1658 1659 if (psxa) 1660 { 1661 ZeroMemory(&Call, sizeof(Call)); 1662 Call.lpfnAddReplaceWith = lpfnAddPage; 1663 Call.lParam = lParam; 1664 Call.bMultiple = TRUE; 1665 1666 /* Call the AddPage method of all registered IShellPropSheetExt interfaces */ 1667 for (i = 0; i != psxa->uiCount; i++) 1668 { 1669 psxa->pspsx[i]->lpVtbl->AddPages(psxa->pspsx[i], PsxaCall, (LPARAM)&Call); 1670 } 1671 1672 return Call.uiCount; 1673 } 1674 1675 return 0; 1676 } 1677 1678 /************************************************************************* 1679 * SHCreatePropSheetExtArray [SHELL32.168] 1680 */ 1681 HPSXA WINAPI SHCreatePropSheetExtArray(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface) 1682 { 1683 return SHCreatePropSheetExtArrayEx(hKey, pszSubKey, max_iface, NULL); 1684 } 1685 1686 /************************************************************************* 1687 * SHCreatePropSheetExtArrayEx [SHELL32.194] 1688 */ 1689 HPSXA WINAPI SHCreatePropSheetExtArrayEx(HKEY hKey, LPCWSTR pszSubKey, UINT max_iface, LPDATAOBJECT pDataObj) 1690 { 1691 static const WCHAR szPropSheetSubKey[] = {'s','h','e','l','l','e','x','\\','P','r','o','p','e','r','t','y','S','h','e','e','t','H','a','n','d','l','e','r','s',0}; 1692 WCHAR szHandler[64]; 1693 DWORD dwHandlerLen; 1694 WCHAR szClsidHandler[39]; 1695 DWORD dwClsidSize; 1696 CLSID clsid; 1697 LONG lRet; 1698 DWORD dwIndex; 1699 IShellExtInit *psxi; 1700 IShellPropSheetExt *pspsx; 1701 HKEY hkBase, hkPropSheetHandlers; 1702 PPSXA psxa = NULL; 1703 1704 TRACE("(%p,%s,%u)\n", hKey, debugstr_w(pszSubKey), max_iface); 1705 1706 if (max_iface == 0) 1707 return NULL; 1708 1709 /* Open the registry key */ 1710 lRet = RegOpenKeyW(hKey, pszSubKey, &hkBase); 1711 if (lRet != ERROR_SUCCESS) 1712 return NULL; 1713 1714 lRet = RegOpenKeyExW(hkBase, szPropSheetSubKey, 0, KEY_ENUMERATE_SUB_KEYS, &hkPropSheetHandlers); 1715 RegCloseKey(hkBase); 1716 if (lRet == ERROR_SUCCESS) 1717 { 1718 /* Create and initialize the Property Sheet Extensions Array */ 1719 psxa = LocalAlloc(LMEM_FIXED, FIELD_OFFSET(PSXA, pspsx[max_iface])); 1720 if (psxa) 1721 { 1722 ZeroMemory(psxa, FIELD_OFFSET(PSXA, pspsx[max_iface])); 1723 psxa->uiAllocated = max_iface; 1724 1725 /* Enumerate all subkeys and attempt to load the shell extensions */ 1726 dwIndex = 0; 1727 do 1728 { 1729 dwHandlerLen = sizeof(szHandler) / sizeof(szHandler[0]); 1730 lRet = RegEnumKeyExW(hkPropSheetHandlers, dwIndex++, szHandler, &dwHandlerLen, NULL, NULL, NULL, NULL); 1731 if (lRet != ERROR_SUCCESS) 1732 { 1733 if (lRet == ERROR_MORE_DATA) 1734 continue; 1735 1736 if (lRet == ERROR_NO_MORE_ITEMS) 1737 lRet = ERROR_SUCCESS; 1738 break; 1739 } 1740 1741 /* The CLSID is stored either in the key itself or in its default value. */ 1742 if (FAILED(lRet = SHCLSIDFromStringW(szHandler, &clsid))) 1743 { 1744 dwClsidSize = sizeof(szClsidHandler); 1745 if (SHGetValueW(hkPropSheetHandlers, szHandler, NULL, NULL, szClsidHandler, &dwClsidSize) == ERROR_SUCCESS) 1746 { 1747 /* Force a NULL-termination and convert the string */ 1748 szClsidHandler[(sizeof(szClsidHandler) / sizeof(szClsidHandler[0])) - 1] = 0; 1749 lRet = SHCLSIDFromStringW(szClsidHandler, &clsid); 1750 } 1751 } 1752 1753 if (SUCCEEDED(lRet)) 1754 { 1755 /* Attempt to get an IShellPropSheetExt and an IShellExtInit instance. 1756 Only if both interfaces are supported it's a real shell extension. 1757 Then call IShellExtInit's Initialize method. */ 1758 if (SUCCEEDED(CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER/* | CLSCTX_NO_CODE_DOWNLOAD */, &IID_IShellPropSheetExt, (LPVOID *)&pspsx))) 1759 { 1760 if (SUCCEEDED(pspsx->lpVtbl->QueryInterface(pspsx, &IID_IShellExtInit, (PVOID *)&psxi))) 1761 { 1762 if (SUCCEEDED(psxi->lpVtbl->Initialize(psxi, NULL, pDataObj, hKey))) 1763 { 1764 /* Add the IShellPropSheetExt instance to the array */ 1765 psxa->pspsx[psxa->uiCount++] = pspsx; 1766 } 1767 else 1768 { 1769 psxi->lpVtbl->Release(psxi); 1770 pspsx->lpVtbl->Release(pspsx); 1771 } 1772 } 1773 else 1774 pspsx->lpVtbl->Release(pspsx); 1775 } 1776 } 1777 1778 } while (psxa->uiCount != psxa->uiAllocated); 1779 } 1780 else 1781 lRet = ERROR_NOT_ENOUGH_MEMORY; 1782 1783 RegCloseKey(hkPropSheetHandlers); 1784 } 1785 1786 if (lRet != ERROR_SUCCESS && psxa) 1787 { 1788 SHDestroyPropSheetExtArray((HPSXA)psxa); 1789 psxa = NULL; 1790 } 1791 1792 return (HPSXA)psxa; 1793 } 1794 1795 /************************************************************************* 1796 * SHReplaceFromPropSheetExtArray [SHELL32.170] 1797 */ 1798 UINT WINAPI SHReplaceFromPropSheetExtArray(HPSXA hpsxa, UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplaceWith, LPARAM lParam) 1799 { 1800 PSXA_CALL Call; 1801 UINT i; 1802 PPSXA psxa = (PPSXA)hpsxa; 1803 1804 TRACE("(%p,%u,%p,%08lx)\n", hpsxa, uPageID, lpfnReplaceWith, lParam); 1805 1806 if (psxa) 1807 { 1808 ZeroMemory(&Call, sizeof(Call)); 1809 Call.lpfnAddReplaceWith = lpfnReplaceWith; 1810 Call.lParam = lParam; 1811 1812 /* Call the ReplacePage method of all registered IShellPropSheetExt interfaces. 1813 Each shell extension is only allowed to call the callback once during the callback. */ 1814 for (i = 0; i != psxa->uiCount; i++) 1815 { 1816 Call.bCalled = FALSE; 1817 psxa->pspsx[i]->lpVtbl->ReplacePage(psxa->pspsx[i], uPageID, PsxaCall, (LPARAM)&Call); 1818 } 1819 1820 return Call.uiCount; 1821 } 1822 1823 return 0; 1824 } 1825 1826 /************************************************************************* 1827 * SHDestroyPropSheetExtArray [SHELL32.169] 1828 */ 1829 void WINAPI SHDestroyPropSheetExtArray(HPSXA hpsxa) 1830 { 1831 UINT i; 1832 PPSXA psxa = (PPSXA)hpsxa; 1833 1834 TRACE("(%p)\n", hpsxa); 1835 1836 if (psxa) 1837 { 1838 for (i = 0; i != psxa->uiCount; i++) 1839 { 1840 psxa->pspsx[i]->lpVtbl->Release(psxa->pspsx[i]); 1841 } 1842 1843 LocalFree(psxa); 1844 } 1845 } 1846 1847 /************************************************************************* 1848 * CIDLData_CreateFromIDArray [SHELL32.83] 1849 * 1850 * Create IDataObject from PIDLs?? 1851 */ 1852 HRESULT WINAPI CIDLData_CreateFromIDArray( 1853 PCIDLIST_ABSOLUTE pidlFolder, 1854 UINT cpidlFiles, 1855 PCUIDLIST_RELATIVE_ARRAY lppidlFiles, 1856 LPDATAOBJECT *ppdataObject) 1857 { 1858 UINT i; 1859 HWND hwnd = 0; /*FIXME: who should be hwnd of owner? set to desktop */ 1860 HRESULT hResult; 1861 1862 TRACE("(%p, %d, %p, %p)\n", pidlFolder, cpidlFiles, lppidlFiles, ppdataObject); 1863 if (TRACE_ON(pidl)) 1864 { 1865 pdump (pidlFolder); 1866 for (i=0; i<cpidlFiles; i++) pdump (lppidlFiles[i]); 1867 } 1868 hResult = IDataObject_Constructor(hwnd, pidlFolder, lppidlFiles, cpidlFiles, ppdataObject); 1869 return hResult; 1870 } 1871 1872 /************************************************************************* 1873 * SHCreateStdEnumFmtEtc [SHELL32.74] 1874 * 1875 * NOTES 1876 * 1877 */ 1878 HRESULT WINAPI SHCreateStdEnumFmtEtc( 1879 UINT cFormats, 1880 const FORMATETC *lpFormats, 1881 LPENUMFORMATETC *ppenumFormatetc) 1882 { 1883 IEnumFORMATETC *pef; 1884 HRESULT hRes; 1885 TRACE("cf=%d fe=%p pef=%p\n", cFormats, lpFormats, ppenumFormatetc); 1886 1887 hRes = IEnumFORMATETC_Constructor(cFormats, lpFormats, &pef); 1888 if (FAILED(hRes)) 1889 return hRes; 1890 1891 IEnumFORMATETC_AddRef(pef); 1892 hRes = IEnumFORMATETC_QueryInterface(pef, &IID_IEnumFORMATETC, (LPVOID*)ppenumFormatetc); 1893 IEnumFORMATETC_Release(pef); 1894 1895 return hRes; 1896 } 1897 1898 /************************************************************************* 1899 * SHFindFiles (SHELL32.90) 1900 */ 1901 BOOL WINAPI SHFindFiles( LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlSaveFile ) 1902 { 1903 FIXME("%p %p\n", pidlFolder, pidlSaveFile ); 1904 return FALSE; 1905 } 1906 1907 /************************************************************************* 1908 * SHUpdateImageW (SHELL32.192) 1909 * 1910 * Notifies the shell that an icon in the system image list has been changed. 1911 * 1912 * PARAMS 1913 * pszHashItem [I] Path to file that contains the icon. 1914 * iIndex [I] Zero-based index of the icon in the file. 1915 * uFlags [I] Flags determining the icon attributes. See notes. 1916 * iImageIndex [I] Index of the icon in the system image list. 1917 * 1918 * RETURNS 1919 * Nothing 1920 * 1921 * NOTES 1922 * uFlags can be one or more of the following flags: 1923 * GIL_NOTFILENAME - pszHashItem is not a file name. 1924 * GIL_SIMULATEDOC - Create a document icon using the specified icon. 1925 */ 1926 void WINAPI SHUpdateImageW(LPCWSTR pszHashItem, int iIndex, UINT uFlags, int iImageIndex) 1927 { 1928 FIXME("%s, %d, 0x%x, %d - stub\n", debugstr_w(pszHashItem), iIndex, uFlags, iImageIndex); 1929 } 1930 1931 /************************************************************************* 1932 * SHUpdateImageA (SHELL32.191) 1933 * 1934 * See SHUpdateImageW. 1935 */ 1936 VOID WINAPI SHUpdateImageA(LPCSTR pszHashItem, INT iIndex, UINT uFlags, INT iImageIndex) 1937 { 1938 FIXME("%s, %d, 0x%x, %d - stub\n", debugstr_a(pszHashItem), iIndex, uFlags, iImageIndex); 1939 } 1940 1941 INT WINAPI SHHandleUpdateImage(LPCITEMIDLIST pidlExtra) 1942 { 1943 FIXME("%p - stub\n", pidlExtra); 1944 1945 return -1; 1946 } 1947 1948 BOOL WINAPI SHObjectProperties(HWND hwnd, DWORD dwType, LPCWSTR szObject, LPCWSTR szPage) 1949 { 1950 FIXME("%p, 0x%08x, %s, %s - stub\n", hwnd, dwType, debugstr_w(szObject), debugstr_w(szPage)); 1951 1952 return TRUE; 1953 } 1954 1955 BOOL WINAPI SHGetNewLinkInfoA(LPCSTR pszLinkTo, LPCSTR pszDir, LPSTR pszName, BOOL *pfMustCopy, 1956 UINT uFlags) 1957 { 1958 WCHAR wszLinkTo[MAX_PATH]; 1959 WCHAR wszDir[MAX_PATH]; 1960 WCHAR wszName[MAX_PATH]; 1961 BOOL res; 1962 1963 MultiByteToWideChar(CP_ACP, 0, pszLinkTo, -1, wszLinkTo, MAX_PATH); 1964 MultiByteToWideChar(CP_ACP, 0, pszDir, -1, wszDir, MAX_PATH); 1965 1966 res = SHGetNewLinkInfoW(wszLinkTo, wszDir, wszName, pfMustCopy, uFlags); 1967 1968 if (res) 1969 WideCharToMultiByte(CP_ACP, 0, wszName, -1, pszName, MAX_PATH, NULL, NULL); 1970 1971 return res; 1972 } 1973 1974 BOOL WINAPI SHGetNewLinkInfoW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName, BOOL *pfMustCopy, 1975 UINT uFlags) 1976 { 1977 const WCHAR *basename; 1978 WCHAR *dst_basename; 1979 int i=2; 1980 static const WCHAR lnkformat[] = {'%','s','.','l','n','k',0}; 1981 static const WCHAR lnkformatnum[] = {'%','s',' ','(','%','d',')','.','l','n','k',0}; 1982 1983 TRACE("(%s, %s, %p, %p, 0x%08x)\n", debugstr_w(pszLinkTo), debugstr_w(pszDir), 1984 pszName, pfMustCopy, uFlags); 1985 1986 *pfMustCopy = FALSE; 1987 1988 if (uFlags & SHGNLI_PIDL) 1989 { 1990 FIXME("SHGNLI_PIDL flag unsupported\n"); 1991 return FALSE; 1992 } 1993 1994 if (uFlags) 1995 FIXME("ignoring flags: 0x%08x\n", uFlags); 1996 1997 /* FIXME: should test if the file is a shortcut or DOS program */ 1998 if (GetFileAttributesW(pszLinkTo) == INVALID_FILE_ATTRIBUTES) 1999 return FALSE; 2000 2001 basename = strrchrW(pszLinkTo, '\\'); 2002 if (basename) 2003 basename = basename+1; 2004 else 2005 basename = pszLinkTo; 2006 2007 lstrcpynW(pszName, pszDir, MAX_PATH); 2008 if (!PathAddBackslashW(pszName)) 2009 return FALSE; 2010 2011 dst_basename = pszName + strlenW(pszName); 2012 2013 snprintfW(dst_basename, pszName + MAX_PATH - dst_basename, lnkformat, basename); 2014 2015 while (GetFileAttributesW(pszName) != INVALID_FILE_ATTRIBUTES) 2016 { 2017 snprintfW(dst_basename, pszName + MAX_PATH - dst_basename, lnkformatnum, basename, i); 2018 i++; 2019 } 2020 2021 return TRUE; 2022 } 2023 2024 HRESULT WINAPI SHStartNetConnectionDialog(HWND hwnd, LPCSTR pszRemoteName, DWORD dwType) 2025 { 2026 FIXME("%p, %s, 0x%08x - stub\n", hwnd, debugstr_a(pszRemoteName), dwType); 2027 2028 return S_OK; 2029 } 2030 /************************************************************************* 2031 * SHSetLocalizedName (SHELL32.@) 2032 */ 2033 HRESULT WINAPI SHSetLocalizedName(LPCWSTR pszPath, LPCWSTR pszResModule, int idsRes) 2034 { 2035 FIXME("%p, %s, %d - stub\n", pszPath, debugstr_w(pszResModule), idsRes); 2036 2037 return S_OK; 2038 } 2039 2040 /************************************************************************* 2041 * LinkWindow_RegisterClass (SHELL32.258) 2042 */ 2043 BOOL WINAPI LinkWindow_RegisterClass(void) 2044 { 2045 FIXME("()\n"); 2046 return TRUE; 2047 } 2048 2049 /************************************************************************* 2050 * LinkWindow_UnregisterClass (SHELL32.259) 2051 */ 2052 BOOL WINAPI LinkWindow_UnregisterClass(DWORD dwUnused) 2053 { 2054 FIXME("()\n"); 2055 return TRUE; 2056 } 2057 2058 /************************************************************************* 2059 * SHFlushSFCache (SHELL32.526) 2060 * 2061 * Notifies the shell that a user-specified special folder location has changed. 2062 * 2063 * NOTES 2064 * In Wine, the shell folder registry values are not cached, so this function 2065 * has no effect. 2066 */ 2067 void WINAPI SHFlushSFCache(void) 2068 { 2069 } 2070 2071 /************************************************************************* 2072 * SHGetImageList (SHELL32.727) 2073 * 2074 * Returns a copy of a shell image list. 2075 * 2076 * NOTES 2077 * Windows XP features 4 sizes of image list, and Vista 5. Wine currently 2078 * only supports the traditional small and large image lists, so requests 2079 * for the others will currently fail. 2080 */ 2081 HRESULT WINAPI SHGetImageList(int iImageList, REFIID riid, void **ppv) 2082 { 2083 HIMAGELIST hLarge, hSmall; 2084 HIMAGELIST hNew; 2085 HRESULT ret = E_FAIL; 2086 2087 /* Wine currently only maintains large and small image lists */ 2088 if ((iImageList != SHIL_LARGE) && (iImageList != SHIL_SMALL) && (iImageList != SHIL_SYSSMALL)) 2089 { 2090 FIXME("Unsupported image list %i requested\n", iImageList); 2091 return E_FAIL; 2092 } 2093 2094 Shell_GetImageLists(&hLarge, &hSmall); 2095 #ifndef __REACTOS__ 2096 hNew = ImageList_Duplicate(iImageList == SHIL_LARGE ? hLarge : hSmall); 2097 2098 /* Get the interface for the new image list */ 2099 if (hNew) 2100 { 2101 ret = HIMAGELIST_QueryInterface(hNew, riid, ppv); 2102 ImageList_Destroy(hNew); 2103 } 2104 #else 2105 /* Duplicating the imagelist causes the start menu items not to draw on 2106 * the first show. Was the Duplicate necessary for some reason? I believe 2107 * Windows returns the raw pointer here. */ 2108 hNew = (iImageList == SHIL_LARGE ? hLarge : hSmall); 2109 ret = IImageList2_QueryInterface((IImageList2 *) hNew, riid, ppv); 2110 #endif 2111 2112 return ret; 2113 } 2114 2115 #ifndef __REACTOS__ 2116 2117 /************************************************************************* 2118 * SHCreateShellFolderView [SHELL32.256] 2119 * 2120 * Create a new instance of the default Shell folder view object. 2121 * 2122 * RETURNS 2123 * Success: S_OK 2124 * Failure: error value 2125 * 2126 * NOTES 2127 * see IShellFolder::CreateViewObject 2128 */ 2129 HRESULT WINAPI SHCreateShellFolderView(const SFV_CREATE *pcsfv, 2130 IShellView **ppsv) 2131 { 2132 IShellView * psf; 2133 HRESULT hRes; 2134 2135 *ppsv = NULL; 2136 if (!pcsfv || pcsfv->cbSize != sizeof(*pcsfv)) 2137 return E_INVALIDARG; 2138 2139 TRACE("sf=%p outer=%p callback=%p\n", 2140 pcsfv->pshf, pcsfv->psvOuter, pcsfv->psfvcb); 2141 2142 hRes = IShellView_Constructor(pcsfv->pshf, &psf); 2143 if (FAILED(hRes)) 2144 return hRes; 2145 2146 hRes = IShellView_QueryInterface(psf, &IID_IShellView, (LPVOID *)ppsv); 2147 IShellView_Release(psf); 2148 2149 return hRes; 2150 } 2151 #endif 2152