1 /* 2 * SHLWAPI ordinal functions 3 * 4 * Copyright 1997 Marcus Meissner 5 * 1998 Jürgen Schmied 6 * 2001-2003 Jon Griffiths 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 "config.h" 24 #include "wine/port.h" 25 26 #include <stdarg.h> 27 #include <stdio.h> 28 #include <string.h> 29 30 #define COBJMACROS 31 32 #include "windef.h" 33 #include "winbase.h" 34 #include "winnls.h" 35 #include "winreg.h" 36 #include "wingdi.h" 37 #include "winuser.h" 38 #include "winver.h" 39 #include "winnetwk.h" 40 #include "mmsystem.h" 41 #include "objbase.h" 42 #include "exdisp.h" 43 #include "shdeprecated.h" 44 #include "shlobj.h" 45 #include "shlwapi.h" 46 #include "shellapi.h" 47 #include "commdlg.h" 48 #include "mlang.h" 49 #include "mshtmhst.h" 50 #ifdef __REACTOS__ 51 #include <shlwapi_undoc.h> 52 #endif 53 #include "wine/unicode.h" 54 #include "wine/debug.h" 55 56 57 WINE_DEFAULT_DEBUG_CHANNEL(shell); 58 59 /* DLL handles for late bound calls */ 60 extern HINSTANCE shlwapi_hInstance; 61 extern DWORD SHLWAPI_ThreadRef_index; 62 63 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*); 64 #ifdef __REACTOS__ 65 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, LPCSTR lpVerb); 66 #else 67 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,DWORD); 68 #endif 69 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD); 70 71 /* 72 NOTES: Most functions exported by ordinal seem to be superfluous. 73 The reason for these functions to be there is to provide a wrapper 74 for unicode functions to provide these functions on systems without 75 unicode functions eg. win95/win98. Since we have such functions we just 76 call these. If running Wine with native DLLs, some late bound calls may 77 fail. However, it is better to implement the functions in the forward DLL 78 and recommend the builtin rather than reimplementing the calls here! 79 */ 80 81 /************************************************************************* 82 * @ [SHLWAPI.11] 83 * 84 * Copy a sharable memory handle from one process to another. 85 * 86 * PARAMS 87 * hShared [I] Shared memory handle to duplicate 88 * dwSrcProcId [I] ID of the process owning hShared 89 * dwDstProcId [I] ID of the process wanting the duplicated handle 90 * dwAccess [I] Desired DuplicateHandle() access 91 * dwOptions [I] Desired DuplicateHandle() options 92 * 93 * RETURNS 94 * Success: A handle suitable for use by the dwDstProcId process. 95 * Failure: A NULL handle. 96 * 97 */ 98 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwSrcProcId, DWORD dwDstProcId, 99 DWORD dwAccess, DWORD dwOptions) 100 { 101 HANDLE hDst, hSrc; 102 DWORD dwMyProcId = GetCurrentProcessId(); 103 HANDLE hRet = NULL; 104 105 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId, 106 dwAccess, dwOptions); 107 108 if (!hShared) 109 { 110 TRACE("Returning handle NULL\n"); 111 return NULL; 112 } 113 114 /* Get dest process handle */ 115 if (dwDstProcId == dwMyProcId) 116 hDst = GetCurrentProcess(); 117 else 118 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId); 119 120 if (hDst) 121 { 122 /* Get src process handle */ 123 if (dwSrcProcId == dwMyProcId) 124 hSrc = GetCurrentProcess(); 125 else 126 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId); 127 128 if (hSrc) 129 { 130 /* Make handle available to dest process */ 131 if (!DuplicateHandle(hSrc, hShared, hDst, &hRet, 132 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS)) 133 hRet = NULL; 134 135 if (dwSrcProcId != dwMyProcId) 136 CloseHandle(hSrc); 137 } 138 139 if (dwDstProcId != dwMyProcId) 140 CloseHandle(hDst); 141 } 142 143 TRACE("Returning handle %p\n", hRet); 144 return hRet; 145 } 146 147 /************************************************************************* 148 * @ [SHLWAPI.7] 149 * 150 * Create a block of sharable memory and initialise it with data. 151 * 152 * PARAMS 153 * lpvData [I] Pointer to data to write 154 * dwSize [I] Size of data 155 * dwProcId [I] ID of process owning data 156 * 157 * RETURNS 158 * Success: A shared memory handle 159 * Failure: NULL 160 * 161 * NOTES 162 * Ordinals 7-11 provide a set of calls to create shared memory between a 163 * group of processes. The shared memory is treated opaquely in that its size 164 * is not exposed to clients who map it. This is accomplished by storing 165 * the size of the map as the first DWORD of mapped data, and then offsetting 166 * the view pointer returned by this size. 167 * 168 */ 169 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId) 170 { 171 HANDLE hMap; 172 LPVOID pMapped; 173 HANDLE hRet = NULL; 174 175 TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId); 176 177 /* Create file mapping of the correct length */ 178 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0, 179 dwSize + sizeof(dwSize), NULL); 180 if (!hMap) 181 return hRet; 182 183 /* Get a view in our process address space */ 184 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); 185 186 if (pMapped) 187 { 188 /* Write size of data, followed by the data, to the view */ 189 *((DWORD*)pMapped) = dwSize; 190 if (lpvData) 191 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize); 192 193 /* Release view. All further views mapped will be opaque */ 194 UnmapViewOfFile(pMapped); 195 hRet = SHMapHandle(hMap, GetCurrentProcessId(), dwProcId, 196 FILE_MAP_ALL_ACCESS, DUPLICATE_SAME_ACCESS); 197 } 198 199 CloseHandle(hMap); 200 return hRet; 201 } 202 203 #ifdef __REACTOS__ 204 /************************************************************************* 205 * @ [SHLWAPI.510] 206 * 207 * Get a pointer to a block of shared memory from a shared memory handle, 208 * with specified access rights. 209 * 210 * PARAMS 211 * hShared [I] Shared memory handle 212 * dwProcId [I] ID of process owning hShared 213 * bWriteAccess [I] TRUE to get a writable block, 214 * FALSE to get a read-only block 215 * 216 * RETURNS 217 * Success: A pointer to the shared memory 218 * Failure: NULL 219 */ 220 LPVOID WINAPI 221 SHLockSharedEx(HANDLE hShared, DWORD dwProcId, BOOL bWriteAccess) 222 { 223 HANDLE hDup; 224 LPVOID pMapped; 225 DWORD dwAccess; 226 227 TRACE("(%p %d %d)\n", hShared, dwProcId, bWriteAccess); 228 229 /* Get handle to shared memory for current process */ 230 hDup = SHMapHandle(hShared, dwProcId, GetCurrentProcessId(), FILE_MAP_ALL_ACCESS, 0); 231 if (hDup == NULL) 232 return NULL; 233 234 /* Get View */ 235 dwAccess = (FILE_MAP_READ | (bWriteAccess ? FILE_MAP_WRITE : 0)); 236 pMapped = MapViewOfFile(hDup, dwAccess, 0, 0, 0); 237 CloseHandle(hDup); 238 239 if (pMapped) 240 return (char *) pMapped + sizeof(DWORD); /* Hide size */ 241 return NULL; 242 } 243 244 #endif 245 /************************************************************************* 246 * @ [SHLWAPI.8] 247 * 248 * Get a pointer to a block of shared memory from a shared memory handle. 249 * 250 * PARAMS 251 * hShared [I] Shared memory handle 252 * dwProcId [I] ID of process owning hShared 253 * 254 * RETURNS 255 * Success: A pointer to the shared memory 256 * Failure: NULL 257 * 258 */ 259 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId) 260 { 261 #ifdef __REACTOS__ 262 return SHLockSharedEx(hShared, dwProcId, TRUE); 263 #else 264 HANDLE hDup; 265 LPVOID pMapped; 266 267 TRACE("(%p %d)\n", hShared, dwProcId); 268 269 /* Get handle to shared memory for current process */ 270 hDup = SHMapHandle(hShared, dwProcId, GetCurrentProcessId(), FILE_MAP_ALL_ACCESS, 0); 271 272 /* Get View */ 273 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); 274 CloseHandle(hDup); 275 276 if (pMapped) 277 return (char *) pMapped + sizeof(DWORD); /* Hide size */ 278 return NULL; 279 #endif 280 } 281 282 /************************************************************************* 283 * @ [SHLWAPI.9] 284 * 285 * Release a pointer to a block of shared memory. 286 * 287 * PARAMS 288 * lpView [I] Shared memory pointer 289 * 290 * RETURNS 291 * Success: TRUE 292 * Failure: FALSE 293 * 294 */ 295 BOOL WINAPI SHUnlockShared(LPVOID lpView) 296 { 297 TRACE("(%p)\n", lpView); 298 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */ 299 } 300 301 /************************************************************************* 302 * @ [SHLWAPI.10] 303 * 304 * Destroy a block of sharable memory. 305 * 306 * PARAMS 307 * hShared [I] Shared memory handle 308 * dwProcId [I] ID of process owning hShared 309 * 310 * RETURNS 311 * Success: TRUE 312 * Failure: FALSE 313 * 314 */ 315 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId) 316 { 317 HANDLE hClose; 318 319 TRACE("(%p %d)\n", hShared, dwProcId); 320 321 if (!hShared) 322 return TRUE; 323 324 /* Get a copy of the handle for our process, closing the source handle */ 325 hClose = SHMapHandle(hShared, dwProcId, GetCurrentProcessId(), 326 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE); 327 /* Close local copy */ 328 return CloseHandle(hClose); 329 } 330 331 /************************************************************************* 332 * @ [SHLWAPI.13] 333 * 334 * Create and register a clipboard enumerator for a web browser. 335 * 336 * PARAMS 337 * lpBC [I] Binding context 338 * lpUnknown [I] An object exposing the IWebBrowserApp interface 339 * 340 * RETURNS 341 * Success: S_OK. 342 * Failure: An HRESULT error code. 343 * 344 * NOTES 345 * The enumerator is stored as a property of the web browser. If it does not 346 * yet exist, it is created and set before being registered. 347 */ 348 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown) 349 { 350 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0', 351 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0', 352 '0','A','A','0','0','4','A','E','8','3','7','}','\0' }; 353 BSTR property; 354 IEnumFORMATETC* pIEnumFormatEtc = NULL; 355 VARIANTARG var; 356 HRESULT hr; 357 IWebBrowserApp* pBrowser; 358 359 TRACE("(%p, %p)\n", lpBC, lpUnknown); 360 361 hr = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (void**)&pBrowser); 362 if (FAILED(hr)) 363 return hr; 364 365 V_VT(&var) = VT_EMPTY; 366 367 /* The property we get is the browsers clipboard enumerator */ 368 property = SysAllocString(szProperty); 369 hr = IWebBrowserApp_GetProperty(pBrowser, property, &var); 370 SysFreeString(property); 371 if (FAILED(hr)) goto exit; 372 373 if (V_VT(&var) == VT_EMPTY) 374 { 375 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */ 376 char szKeyBuff[128], szValueBuff[128]; 377 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType; 378 FORMATETC* formatList, *format; 379 HKEY hDocs; 380 381 TRACE("Registering formats and creating IEnumFORMATETC instance\n"); 382 383 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current" 384 "Version\\Internet Settings\\Accepted Documents", &hDocs)) 385 { 386 hr = E_FAIL; 387 goto exit; 388 } 389 390 /* Get count of values in key */ 391 while (!dwRet) 392 { 393 dwKeySize = sizeof(szKeyBuff); 394 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0); 395 dwCount++; 396 } 397 398 dwNumValues = dwCount; 399 400 /* Note: dwCount = number of items + 1; The extra item is the end node */ 401 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC)); 402 if (!formatList) 403 { 404 RegCloseKey(hDocs); 405 hr = E_OUTOFMEMORY; 406 goto exit; 407 } 408 409 if (dwNumValues > 1) 410 { 411 dwRet = 0; 412 dwCount = 0; 413 414 dwNumValues--; 415 416 /* Register clipboard formats for the values and populate format list */ 417 while(!dwRet && dwCount < dwNumValues) 418 { 419 dwKeySize = sizeof(szKeyBuff); 420 dwValueSize = sizeof(szValueBuff); 421 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType, 422 (PBYTE)szValueBuff, &dwValueSize); 423 if (!dwRet) 424 { 425 HeapFree(GetProcessHeap(), 0, formatList); 426 RegCloseKey(hDocs); 427 hr = E_FAIL; 428 goto exit; 429 } 430 431 format->cfFormat = RegisterClipboardFormatA(szValueBuff); 432 format->ptd = NULL; 433 format->dwAspect = 1; 434 format->lindex = 4; 435 format->tymed = -1; 436 437 format++; 438 dwCount++; 439 } 440 } 441 442 RegCloseKey(hDocs); 443 444 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */ 445 format->cfFormat = 0; 446 format->ptd = NULL; 447 format->dwAspect = 1; 448 format->lindex = 4; 449 format->tymed = -1; 450 451 /* Create a clipboard enumerator */ 452 hr = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc); 453 HeapFree(GetProcessHeap(), 0, formatList); 454 if (FAILED(hr)) goto exit; 455 456 /* Set our enumerator as the browsers property */ 457 V_VT(&var) = VT_UNKNOWN; 458 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc; 459 460 property = SysAllocString(szProperty); 461 hr = IWebBrowserApp_PutProperty(pBrowser, property, var); 462 SysFreeString(property); 463 if (FAILED(hr)) 464 { 465 IEnumFORMATETC_Release(pIEnumFormatEtc); 466 goto exit; 467 } 468 } 469 470 if (V_VT(&var) == VT_UNKNOWN) 471 { 472 /* Our variant is holding the clipboard enumerator */ 473 IUnknown* pIUnknown = V_UNKNOWN(&var); 474 IEnumFORMATETC* pClone = NULL; 475 476 TRACE("Retrieved IEnumFORMATETC property\n"); 477 478 /* Get an IEnumFormatEtc interface from the variants value */ 479 pIEnumFormatEtc = NULL; 480 hr = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC, (void**)&pIEnumFormatEtc); 481 if (hr == S_OK && pIEnumFormatEtc) 482 { 483 /* Clone and register the enumerator */ 484 hr = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone); 485 if (hr == S_OK && pClone) 486 { 487 RegisterFormatEnumerator(lpBC, pClone, 0); 488 489 IEnumFORMATETC_Release(pClone); 490 } 491 492 IUnknown_Release(pIUnknown); 493 } 494 IUnknown_Release(V_UNKNOWN(&var)); 495 } 496 497 exit: 498 IWebBrowserApp_Release(pBrowser); 499 return hr; 500 } 501 502 /************************************************************************* 503 * @ [SHLWAPI.15] 504 * 505 * Get Explorers "AcceptLanguage" setting. 506 * 507 * PARAMS 508 * langbuf [O] Destination for language string 509 * buflen [I] Length of langbuf in characters 510 * [0] Success: used length of langbuf 511 * 512 * RETURNS 513 * Success: S_OK. langbuf is set to the language string found. 514 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer 515 * does not contain the setting. 516 * E_NOT_SUFFICIENT_BUFFER, If the buffer is not big enough 517 */ 518 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen) 519 { 520 static const WCHAR szkeyW[] = { 521 'S','o','f','t','w','a','r','e','\\', 522 'M','i','c','r','o','s','o','f','t','\\', 523 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\', 524 'I','n','t','e','r','n','a','t','i','o','n','a','l',0}; 525 static const WCHAR valueW[] = { 526 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0}; 527 DWORD mystrlen, mytype; 528 DWORD len; 529 HKEY mykey; 530 LCID mylcid; 531 WCHAR *mystr; 532 LONG lres; 533 534 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1); 535 536 if(!langbuf || !buflen || !*buflen) 537 return E_FAIL; 538 539 mystrlen = (*buflen > 20) ? *buflen : 20 ; 540 len = mystrlen * sizeof(WCHAR); 541 mystr = HeapAlloc(GetProcessHeap(), 0, len); 542 mystr[0] = 0; 543 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey); 544 lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len); 545 RegCloseKey(mykey); 546 len = lstrlenW(mystr); 547 548 if (!lres && (*buflen > len)) { 549 lstrcpyW(langbuf, mystr); 550 *buflen = len; 551 HeapFree(GetProcessHeap(), 0, mystr); 552 return S_OK; 553 } 554 555 /* Did not find a value in the registry or the user buffer is too small */ 556 mylcid = GetUserDefaultLCID(); 557 LcidToRfc1766W(mylcid, mystr, mystrlen); 558 len = lstrlenW(mystr); 559 560 memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) ); 561 HeapFree(GetProcessHeap(), 0, mystr); 562 563 if (*buflen > len) { 564 *buflen = len; 565 return S_OK; 566 } 567 568 *buflen = 0; 569 return E_NOT_SUFFICIENT_BUFFER; 570 } 571 572 /************************************************************************* 573 * @ [SHLWAPI.14] 574 * 575 * Ascii version of GetAcceptLanguagesW. 576 */ 577 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen) 578 { 579 WCHAR *langbufW; 580 DWORD buflenW, convlen; 581 HRESULT retval; 582 583 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1); 584 585 if(!langbuf || !buflen || !*buflen) return E_FAIL; 586 587 buflenW = *buflen; 588 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW); 589 retval = GetAcceptLanguagesW(langbufW, &buflenW); 590 591 if (retval == S_OK) 592 { 593 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL); 594 convlen--; /* do not count the terminating 0 */ 595 } 596 else /* copy partial string anyway */ 597 { 598 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL); 599 if (convlen < *buflen) 600 { 601 langbuf[convlen] = 0; 602 convlen--; /* do not count the terminating 0 */ 603 } 604 else 605 { 606 convlen = *buflen; 607 } 608 } 609 *buflen = buflenW ? convlen : 0; 610 611 HeapFree(GetProcessHeap(), 0, langbufW); 612 return retval; 613 } 614 615 /************************************************************************* 616 * @ [SHLWAPI.23] 617 * 618 * Convert a GUID to a string. 619 * 620 * PARAMS 621 * guid [I] GUID to convert 622 * lpszDest [O] Destination for string 623 * cchMax [I] Length of output buffer 624 * 625 * RETURNS 626 * The length of the string created. 627 */ 628 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax) 629 { 630 char xguid[40]; 631 INT iLen; 632 633 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax); 634 635 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", 636 guid->Data1, guid->Data2, guid->Data3, 637 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], 638 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); 639 640 iLen = strlen(xguid) + 1; 641 642 if (iLen > cchMax) 643 return 0; 644 memcpy(lpszDest, xguid, iLen); 645 return iLen; 646 } 647 648 /************************************************************************* 649 * @ [SHLWAPI.24] 650 * 651 * Convert a GUID to a string. 652 * 653 * PARAMS 654 * guid [I] GUID to convert 655 * str [O] Destination for string 656 * cmax [I] Length of output buffer 657 * 658 * RETURNS 659 * The length of the string created. 660 */ 661 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax) 662 { 663 WCHAR xguid[40]; 664 INT iLen; 665 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-', 666 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2', 667 'X','%','0','2','X','%','0','2','X','}',0}; 668 669 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax); 670 671 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3, 672 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3], 673 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]); 674 675 iLen = strlenW(xguid) + 1; 676 677 if (iLen > cchMax) 678 return 0; 679 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR)); 680 return iLen; 681 } 682 683 /************************************************************************* 684 * @ [SHLWAPI.30] 685 * 686 * Determine if a Unicode character is a blank. 687 * 688 * PARAMS 689 * wc [I] Character to check. 690 * 691 * RETURNS 692 * TRUE, if wc is a blank, 693 * FALSE otherwise. 694 * 695 */ 696 BOOL WINAPI IsCharBlankW(WCHAR wc) 697 { 698 WORD CharType; 699 700 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK); 701 } 702 703 /************************************************************************* 704 * @ [SHLWAPI.31] 705 * 706 * Determine if a Unicode character is punctuation. 707 * 708 * PARAMS 709 * wc [I] Character to check. 710 * 711 * RETURNS 712 * TRUE, if wc is punctuation, 713 * FALSE otherwise. 714 */ 715 BOOL WINAPI IsCharPunctW(WCHAR wc) 716 { 717 WORD CharType; 718 719 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT); 720 } 721 722 /************************************************************************* 723 * @ [SHLWAPI.32] 724 * 725 * Determine if a Unicode character is a control character. 726 * 727 * PARAMS 728 * wc [I] Character to check. 729 * 730 * RETURNS 731 * TRUE, if wc is a control character, 732 * FALSE otherwise. 733 */ 734 BOOL WINAPI IsCharCntrlW(WCHAR wc) 735 { 736 WORD CharType; 737 738 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL); 739 } 740 741 /************************************************************************* 742 * @ [SHLWAPI.33] 743 * 744 * Determine if a Unicode character is a digit. 745 * 746 * PARAMS 747 * wc [I] Character to check. 748 * 749 * RETURNS 750 * TRUE, if wc is a digit, 751 * FALSE otherwise. 752 */ 753 BOOL WINAPI IsCharDigitW(WCHAR wc) 754 { 755 WORD CharType; 756 757 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT); 758 } 759 760 /************************************************************************* 761 * @ [SHLWAPI.34] 762 * 763 * Determine if a Unicode character is a hex digit. 764 * 765 * PARAMS 766 * wc [I] Character to check. 767 * 768 * RETURNS 769 * TRUE, if wc is a hex digit, 770 * FALSE otherwise. 771 */ 772 BOOL WINAPI IsCharXDigitW(WCHAR wc) 773 { 774 WORD CharType; 775 776 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT); 777 } 778 779 /************************************************************************* 780 * @ [SHLWAPI.35] 781 * 782 */ 783 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type) 784 { 785 return GetStringTypeW(CT_CTYPE3, src, count, type); 786 } 787 788 /************************************************************************* 789 * @ [SHLWAPI.151] 790 * 791 * Compare two Ascii strings up to a given length. 792 * 793 * PARAMS 794 * lpszSrc [I] Source string 795 * lpszCmp [I] String to compare to lpszSrc 796 * len [I] Maximum length 797 * 798 * RETURNS 799 * A number greater than, less than or equal to 0 depending on whether 800 * lpszSrc is greater than, less than or equal to lpszCmp. 801 */ 802 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len) 803 { 804 return StrCmpNA(lpszSrc, lpszCmp, len); 805 } 806 807 /************************************************************************* 808 * @ [SHLWAPI.152] 809 * 810 * Unicode version of StrCmpNCA. 811 */ 812 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len) 813 { 814 return StrCmpNW(lpszSrc, lpszCmp, len); 815 } 816 817 /************************************************************************* 818 * @ [SHLWAPI.153] 819 * 820 * Compare two Ascii strings up to a given length, ignoring case. 821 * 822 * PARAMS 823 * lpszSrc [I] Source string 824 * lpszCmp [I] String to compare to lpszSrc 825 * len [I] Maximum length 826 * 827 * RETURNS 828 * A number greater than, less than or equal to 0 depending on whether 829 * lpszSrc is greater than, less than or equal to lpszCmp. 830 */ 831 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len) 832 { 833 return StrCmpNIA(lpszSrc, lpszCmp, len); 834 } 835 836 /************************************************************************* 837 * @ [SHLWAPI.154] 838 * 839 * Unicode version of StrCmpNICA. 840 */ 841 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len) 842 { 843 return StrCmpNIW(lpszSrc, lpszCmp, len); 844 } 845 846 /************************************************************************* 847 * @ [SHLWAPI.155] 848 * 849 * Compare two Ascii strings. 850 * 851 * PARAMS 852 * lpszSrc [I] Source string 853 * lpszCmp [I] String to compare to lpszSrc 854 * 855 * RETURNS 856 * A number greater than, less than or equal to 0 depending on whether 857 * lpszSrc is greater than, less than or equal to lpszCmp. 858 */ 859 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp) 860 { 861 return lstrcmpA(lpszSrc, lpszCmp); 862 } 863 864 /************************************************************************* 865 * @ [SHLWAPI.156] 866 * 867 * Unicode version of StrCmpCA. 868 */ 869 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp) 870 { 871 return lstrcmpW(lpszSrc, lpszCmp); 872 } 873 874 /************************************************************************* 875 * @ [SHLWAPI.157] 876 * 877 * Compare two Ascii strings, ignoring case. 878 * 879 * PARAMS 880 * lpszSrc [I] Source string 881 * lpszCmp [I] String to compare to lpszSrc 882 * 883 * RETURNS 884 * A number greater than, less than or equal to 0 depending on whether 885 * lpszSrc is greater than, less than or equal to lpszCmp. 886 */ 887 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp) 888 { 889 return lstrcmpiA(lpszSrc, lpszCmp); 890 } 891 892 /************************************************************************* 893 * @ [SHLWAPI.158] 894 * 895 * Unicode version of StrCmpICA. 896 */ 897 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp) 898 { 899 return lstrcmpiW(lpszSrc, lpszCmp); 900 } 901 902 /************************************************************************* 903 * @ [SHLWAPI.160] 904 * 905 * Get an identification string for the OS and explorer. 906 * 907 * PARAMS 908 * lpszDest [O] Destination for Id string 909 * dwDestLen [I] Length of lpszDest 910 * 911 * RETURNS 912 * TRUE, If the string was created successfully 913 * FALSE, Otherwise 914 */ 915 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen) 916 { 917 WCHAR buff[2084]; 918 919 TRACE("(%p,%d)\n", lpszDest, dwDestLen); 920 921 if (lpszDest && SHAboutInfoW(buff, dwDestLen)) 922 { 923 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL); 924 return TRUE; 925 } 926 return FALSE; 927 } 928 929 /************************************************************************* 930 * @ [SHLWAPI.161] 931 * 932 * Unicode version of SHAboutInfoA. 933 */ 934 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen) 935 { 936 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\', 937 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t', 938 ' ','E','x','p','l','o','r','e','r','\0' }; 939 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\', 940 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ', 941 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' }; 942 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\', 943 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', 944 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' }; 945 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\', 946 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t', 947 ' ','E','x','p','l','o','r','e','r','\\', 948 'R','e','g','i','s','t','r','a','t','i','o','n','\0' }; 949 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' }; 950 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d', 951 'V','e','r','s','i','o','n','\0' }; 952 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d', 953 'O','w','n','e','r','\0' }; 954 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d', 955 'O','r','g','a','n','i','z','a','t','i','o','n','\0' }; 956 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' }; 957 static const WCHAR szUpdate[] = { 'I','E','A','K', 958 'U','p','d','a','t','e','U','r','l','\0' }; 959 static const WCHAR szHelp[] = { 'I','E','A','K', 960 'H','e','l','p','S','t','r','i','n','g','\0' }; 961 WCHAR buff[2084]; 962 HKEY hReg; 963 DWORD dwType, dwLen; 964 965 TRACE("(%p,%d)\n", lpszDest, dwDestLen); 966 967 if (!lpszDest) 968 return FALSE; 969 970 *lpszDest = '\0'; 971 972 /* Try the NT key first, followed by 95/98 key */ 973 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) && 974 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg)) 975 return FALSE; 976 977 /* OS Version */ 978 buff[0] = '\0'; 979 dwLen = 30; 980 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen)) 981 { 982 DWORD dwStrLen = strlenW(buff); 983 dwLen = 30 - dwStrLen; 984 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, 985 szCustomized, &dwType, buff+dwStrLen, &dwLen); 986 } 987 StrCatBuffW(lpszDest, buff, dwDestLen); 988 989 /* ~Registered Owner */ 990 buff[0] = '~'; 991 dwLen = 256; 992 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen)) 993 buff[1] = '\0'; 994 StrCatBuffW(lpszDest, buff, dwDestLen); 995 996 /* ~Registered Organization */ 997 dwLen = 256; 998 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen)) 999 buff[1] = '\0'; 1000 StrCatBuffW(lpszDest, buff, dwDestLen); 1001 1002 /* FIXME: Not sure where this number comes from */ 1003 buff[0] = '~'; 1004 buff[1] = '0'; 1005 buff[2] = '\0'; 1006 StrCatBuffW(lpszDest, buff, dwDestLen); 1007 1008 /* ~Product Id */ 1009 dwLen = 256; 1010 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen)) 1011 buff[1] = '\0'; 1012 StrCatBuffW(lpszDest, buff, dwDestLen); 1013 1014 /* ~IE Update Url */ 1015 dwLen = 2048; 1016 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen)) 1017 buff[1] = '\0'; 1018 StrCatBuffW(lpszDest, buff, dwDestLen); 1019 1020 /* ~IE Help String */ 1021 dwLen = 256; 1022 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen)) 1023 buff[1] = '\0'; 1024 StrCatBuffW(lpszDest, buff, dwDestLen); 1025 1026 RegCloseKey(hReg); 1027 return TRUE; 1028 } 1029 1030 /************************************************************************* 1031 * @ [SHLWAPI.163] 1032 * 1033 * Call IOleCommandTarget_QueryStatus() on an object. 1034 * 1035 * PARAMS 1036 * lpUnknown [I] Object supporting the IOleCommandTarget interface 1037 * pguidCmdGroup [I] GUID for the command group 1038 * cCmds [I] 1039 * prgCmds [O] Commands 1040 * pCmdText [O] Command text 1041 * 1042 * RETURNS 1043 * Success: S_OK. 1044 * Failure: E_FAIL, if lpUnknown is NULL. 1045 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget. 1046 * Otherwise, an error code from IOleCommandTarget_QueryStatus(). 1047 */ 1048 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup, 1049 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText) 1050 { 1051 HRESULT hRet = E_FAIL; 1052 1053 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText); 1054 1055 if (lpUnknown) 1056 { 1057 IOleCommandTarget* lpOle; 1058 1059 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget, 1060 (void**)&lpOle); 1061 1062 if (SUCCEEDED(hRet) && lpOle) 1063 { 1064 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds, 1065 prgCmds, pCmdText); 1066 IOleCommandTarget_Release(lpOle); 1067 } 1068 } 1069 return hRet; 1070 } 1071 1072 /************************************************************************* 1073 * @ [SHLWAPI.164] 1074 * 1075 * Call IOleCommandTarget_Exec() on an object. 1076 * 1077 * PARAMS 1078 * lpUnknown [I] Object supporting the IOleCommandTarget interface 1079 * pguidCmdGroup [I] GUID for the command group 1080 * 1081 * RETURNS 1082 * Success: S_OK. 1083 * Failure: E_FAIL, if lpUnknown is NULL. 1084 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget. 1085 * Otherwise, an error code from IOleCommandTarget_Exec(). 1086 */ 1087 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup, 1088 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn, 1089 VARIANT* pvaOut) 1090 { 1091 HRESULT hRet = E_FAIL; 1092 1093 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID, 1094 nCmdexecopt, pvaIn, pvaOut); 1095 1096 if (lpUnknown) 1097 { 1098 IOleCommandTarget* lpOle; 1099 1100 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget, 1101 (void**)&lpOle); 1102 if (SUCCEEDED(hRet) && lpOle) 1103 { 1104 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID, 1105 nCmdexecopt, pvaIn, pvaOut); 1106 IOleCommandTarget_Release(lpOle); 1107 } 1108 } 1109 return hRet; 1110 } 1111 1112 /************************************************************************* 1113 * @ [SHLWAPI.165] 1114 * 1115 * Retrieve, modify, and re-set a value from a window. 1116 * 1117 * PARAMS 1118 * hWnd [I] Window to get value from 1119 * offset [I] Offset of value 1120 * mask [I] Mask for flags 1121 * flags [I] Bits to set in window value 1122 * 1123 * RETURNS 1124 * The new value as it was set, or 0 if any parameter is invalid. 1125 * 1126 * NOTES 1127 * Only bits specified in mask are affected - set if present in flags and 1128 * reset otherwise. 1129 */ 1130 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT mask, UINT flags) 1131 { 1132 LONG ret = GetWindowLongW(hwnd, offset); 1133 LONG new_flags = (flags & mask) | (ret & ~mask); 1134 1135 TRACE("%p %d %x %x\n", hwnd, offset, mask, flags); 1136 1137 if (new_flags != ret) 1138 ret = SetWindowLongW(hwnd, offset, new_flags); 1139 return ret; 1140 } 1141 1142 /************************************************************************* 1143 * @ [SHLWAPI.167] 1144 * 1145 * Change a window's parent. 1146 * 1147 * PARAMS 1148 * hWnd [I] Window to change parent of 1149 * hWndParent [I] New parent window 1150 * 1151 * RETURNS 1152 * The old parent of hWnd. 1153 * 1154 * NOTES 1155 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP. 1156 * If hWndParent is NOT NULL then we set the WS_CHILD style. 1157 */ 1158 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent) 1159 { 1160 TRACE("%p, %p\n", hWnd, hWndParent); 1161 1162 if(GetParent(hWnd) == hWndParent) 1163 return NULL; 1164 1165 if(hWndParent) 1166 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD | WS_POPUP, WS_CHILD); 1167 else 1168 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD | WS_POPUP, WS_POPUP); 1169 1170 return hWndParent ? SetParent(hWnd, hWndParent) : NULL; 1171 } 1172 1173 /************************************************************************* 1174 * @ [SHLWAPI.168] 1175 * 1176 * Locate and advise a connection point in an IConnectionPointContainer object. 1177 * 1178 * PARAMS 1179 * lpUnkSink [I] Sink for the connection point advise call 1180 * riid [I] REFIID of connection point to advise 1181 * fConnect [I] TRUE = Connection being establisted, FALSE = broken 1182 * lpUnknown [I] Object supporting the IConnectionPointContainer interface 1183 * lpCookie [O] Pointer to connection point cookie 1184 * lppCP [O] Destination for the IConnectionPoint found 1185 * 1186 * RETURNS 1187 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint 1188 * that was advised. The caller is responsible for releasing it. 1189 * Failure: E_FAIL, if any arguments are invalid. 1190 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer, 1191 * Or an HRESULT error code if any call fails. 1192 */ 1193 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL fConnect, 1194 IUnknown* lpUnknown, LPDWORD lpCookie, 1195 IConnectionPoint **lppCP) 1196 { 1197 HRESULT hRet; 1198 IConnectionPointContainer* lpContainer; 1199 IConnectionPoint *lpCP; 1200 1201 if(!lpUnknown || (fConnect && !lpUnkSink)) 1202 return E_FAIL; 1203 1204 if(lppCP) 1205 *lppCP = NULL; 1206 1207 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, 1208 (void**)&lpContainer); 1209 if (SUCCEEDED(hRet)) 1210 { 1211 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP); 1212 1213 if (SUCCEEDED(hRet)) 1214 { 1215 if(!fConnect) 1216 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie); 1217 else 1218 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie); 1219 1220 if (FAILED(hRet)) 1221 *lpCookie = 0; 1222 1223 if (lppCP && SUCCEEDED(hRet)) 1224 *lppCP = lpCP; /* Caller keeps the interface */ 1225 else 1226 IConnectionPoint_Release(lpCP); /* Release it */ 1227 } 1228 1229 IConnectionPointContainer_Release(lpContainer); 1230 } 1231 return hRet; 1232 } 1233 1234 /************************************************************************* 1235 * @ [SHLWAPI.169] 1236 * 1237 * Release an interface and zero a supplied pointer. 1238 * 1239 * PARAMS 1240 * lpUnknown [I] Object to release 1241 * 1242 * RETURNS 1243 * Nothing. 1244 */ 1245 void WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown) 1246 { 1247 TRACE("(%p)\n", lpUnknown); 1248 1249 if(!lpUnknown || !*lpUnknown) return; 1250 1251 TRACE("doing Release\n"); 1252 1253 IUnknown_Release(*lpUnknown); 1254 *lpUnknown = NULL; 1255 } 1256 1257 /************************************************************************* 1258 * @ [SHLWAPI.170] 1259 * 1260 * Skip '//' if present in a string. 1261 * 1262 * PARAMS 1263 * lpszSrc [I] String to check for '//' 1264 * 1265 * RETURNS 1266 * Success: The next character after the '//' or the string if not present 1267 * Failure: NULL, if lpszStr is NULL. 1268 */ 1269 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc) 1270 { 1271 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/') 1272 lpszSrc += 2; 1273 return lpszSrc; 1274 } 1275 1276 /************************************************************************* 1277 * @ [SHLWAPI.171] 1278 * 1279 * Check if two interfaces come from the same object. 1280 * 1281 * PARAMS 1282 * lpInt1 [I] Interface to check against lpInt2. 1283 * lpInt2 [I] Interface to check against lpInt1. 1284 * 1285 * RETURNS 1286 * TRUE, If the interfaces come from the same object. 1287 * FALSE Otherwise. 1288 */ 1289 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2) 1290 { 1291 IUnknown *lpUnknown1, *lpUnknown2; 1292 BOOL ret; 1293 1294 TRACE("(%p %p)\n", lpInt1, lpInt2); 1295 1296 if (!lpInt1 || !lpInt2) 1297 return FALSE; 1298 1299 if (lpInt1 == lpInt2) 1300 return TRUE; 1301 1302 if (IUnknown_QueryInterface(lpInt1, &IID_IUnknown, (void**)&lpUnknown1) != S_OK) 1303 return FALSE; 1304 1305 if (IUnknown_QueryInterface(lpInt2, &IID_IUnknown, (void**)&lpUnknown2) != S_OK) 1306 { 1307 IUnknown_Release(lpUnknown1); 1308 return FALSE; 1309 } 1310 1311 ret = lpUnknown1 == lpUnknown2; 1312 1313 IUnknown_Release(lpUnknown1); 1314 IUnknown_Release(lpUnknown2); 1315 1316 return ret; 1317 } 1318 1319 /************************************************************************* 1320 * @ [SHLWAPI.172] 1321 * 1322 * Get the window handle of an object. 1323 * 1324 * PARAMS 1325 * lpUnknown [I] Object to get the window handle of 1326 * lphWnd [O] Destination for window handle 1327 * 1328 * RETURNS 1329 * Success: S_OK. lphWnd contains the objects window handle. 1330 * Failure: An HRESULT error code. 1331 * 1332 * NOTES 1333 * lpUnknown is expected to support one of the following interfaces: 1334 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView(). 1335 */ 1336 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd) 1337 { 1338 IUnknown *lpOle; 1339 HRESULT hRet = E_FAIL; 1340 1341 TRACE("(%p,%p)\n", lpUnknown, lphWnd); 1342 1343 if (!lpUnknown) 1344 return hRet; 1345 1346 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle); 1347 1348 if (FAILED(hRet)) 1349 { 1350 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle); 1351 1352 if (FAILED(hRet)) 1353 { 1354 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite, 1355 (void**)&lpOle); 1356 } 1357 } 1358 1359 if (SUCCEEDED(hRet)) 1360 { 1361 /* Laziness here - Since GetWindow() is the first method for the above 3 1362 * interfaces, we use the same call for them all. 1363 */ 1364 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd); 1365 IUnknown_Release(lpOle); 1366 if (lphWnd) 1367 TRACE("Returning HWND=%p\n", *lphWnd); 1368 } 1369 1370 return hRet; 1371 } 1372 1373 /************************************************************************* 1374 * @ [SHLWAPI.173] 1375 * 1376 * Call a SetOwner method of IShellService from specified object. 1377 * 1378 * PARAMS 1379 * iface [I] Object that supports IShellService 1380 * pUnk [I] Argument for the SetOwner call 1381 * 1382 * RETURNS 1383 * Corresponding return value from last call or E_FAIL for null input 1384 */ 1385 HRESULT WINAPI IUnknown_SetOwner(IUnknown *iface, IUnknown *pUnk) 1386 { 1387 IShellService *service; 1388 HRESULT hr; 1389 1390 TRACE("(%p, %p)\n", iface, pUnk); 1391 1392 if (!iface) return E_FAIL; 1393 1394 hr = IUnknown_QueryInterface(iface, &IID_IShellService, (void**)&service); 1395 if (hr == S_OK) 1396 { 1397 hr = IShellService_SetOwner(service, pUnk); 1398 IShellService_Release(service); 1399 } 1400 1401 return hr; 1402 } 1403 1404 /************************************************************************* 1405 * @ [SHLWAPI.174] 1406 * 1407 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on 1408 * an object. 1409 * 1410 */ 1411 HRESULT WINAPI IUnknown_SetSite( 1412 IUnknown *obj, /* [in] OLE object */ 1413 IUnknown *site) /* [in] Site interface */ 1414 { 1415 HRESULT hr; 1416 IObjectWithSite *iobjwithsite; 1417 IInternetSecurityManager *isecmgr; 1418 1419 if (!obj) return E_FAIL; 1420 1421 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite); 1422 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite); 1423 if (SUCCEEDED(hr)) 1424 { 1425 hr = IObjectWithSite_SetSite(iobjwithsite, site); 1426 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr); 1427 IObjectWithSite_Release(iobjwithsite); 1428 } 1429 else 1430 { 1431 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr); 1432 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr); 1433 if (FAILED(hr)) return hr; 1434 1435 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site); 1436 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr); 1437 IInternetSecurityManager_Release(isecmgr); 1438 } 1439 return hr; 1440 } 1441 1442 /************************************************************************* 1443 * @ [SHLWAPI.175] 1444 * 1445 * Call IPersist_GetClassID() on an object. 1446 * 1447 * PARAMS 1448 * lpUnknown [I] Object supporting the IPersist interface 1449 * clsid [O] Destination for Class Id 1450 * 1451 * RETURNS 1452 * Success: S_OK. lpClassId contains the Class Id requested. 1453 * Failure: E_FAIL, If lpUnknown is NULL, 1454 * E_NOINTERFACE If lpUnknown does not support IPersist, 1455 * Or an HRESULT error code. 1456 */ 1457 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID *clsid) 1458 { 1459 IPersist *persist; 1460 HRESULT hr; 1461 1462 TRACE("(%p, %p)\n", lpUnknown, clsid); 1463 1464 if (!lpUnknown) 1465 { 1466 memset(clsid, 0, sizeof(*clsid)); 1467 return E_FAIL; 1468 } 1469 1470 hr = IUnknown_QueryInterface(lpUnknown, &IID_IPersist, (void**)&persist); 1471 if (hr != S_OK) 1472 { 1473 hr = IUnknown_QueryInterface(lpUnknown, &IID_IPersistFolder, (void**)&persist); 1474 if (hr != S_OK) 1475 return hr; 1476 } 1477 1478 hr = IPersist_GetClassID(persist, clsid); 1479 IPersist_Release(persist); 1480 return hr; 1481 } 1482 1483 /************************************************************************* 1484 * @ [SHLWAPI.176] 1485 * 1486 * Retrieve a Service Interface from an object. 1487 * 1488 * PARAMS 1489 * lpUnknown [I] Object to get an IServiceProvider interface from 1490 * sid [I] Service ID for IServiceProvider_QueryService() call 1491 * riid [I] Function requested for QueryService call 1492 * lppOut [O] Destination for the service interface pointer 1493 * 1494 * RETURNS 1495 * Success: S_OK. lppOut contains an object providing the requested service 1496 * Failure: An HRESULT error code 1497 * 1498 * NOTES 1499 * lpUnknown is expected to support the IServiceProvider interface. 1500 */ 1501 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid, 1502 LPVOID *lppOut) 1503 { 1504 IServiceProvider* pService = NULL; 1505 HRESULT hRet; 1506 1507 if (!lppOut) 1508 return E_FAIL; 1509 1510 *lppOut = NULL; 1511 1512 if (!lpUnknown) 1513 return E_FAIL; 1514 1515 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider, 1516 (LPVOID*)&pService); 1517 1518 if (hRet == S_OK && pService) 1519 { 1520 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService); 1521 1522 /* Get a Service interface from the object */ 1523 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut); 1524 1525 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut); 1526 1527 IServiceProvider_Release(pService); 1528 } 1529 return hRet; 1530 } 1531 1532 /************************************************************************* 1533 * @ [SHLWAPI.484] 1534 * 1535 * Calls IOleCommandTarget::Exec() for specified service object. 1536 * 1537 * PARAMS 1538 * lpUnknown [I] Object to get an IServiceProvider interface from 1539 * service [I] Service ID for IServiceProvider_QueryService() call 1540 * group [I] Group ID for IOleCommandTarget::Exec() call 1541 * cmdId [I] Command ID for IOleCommandTarget::Exec() call 1542 * cmdOpt [I] Options flags for command 1543 * pIn [I] Input arguments for command 1544 * pOut [O] Output arguments for command 1545 * 1546 * RETURNS 1547 * Success: S_OK. lppOut contains an object providing the requested service 1548 * Failure: An HRESULT error code 1549 * 1550 * NOTES 1551 * lpUnknown is expected to support the IServiceProvider interface. 1552 */ 1553 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *lpUnknown, REFIID service, 1554 const GUID *group, DWORD cmdId, DWORD cmdOpt, VARIANT *pIn, VARIANT *pOut) 1555 { 1556 IOleCommandTarget *target; 1557 HRESULT hr; 1558 1559 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown, debugstr_guid(service), 1560 debugstr_guid(group), cmdId, cmdOpt, pIn, pOut); 1561 1562 hr = IUnknown_QueryService(lpUnknown, service, &IID_IOleCommandTarget, (void**)&target); 1563 if (hr == S_OK) 1564 { 1565 hr = IOleCommandTarget_Exec(target, group, cmdId, cmdOpt, pIn, pOut); 1566 IOleCommandTarget_Release(target); 1567 } 1568 1569 TRACE("<-- hr=0x%08x\n", hr); 1570 1571 return hr; 1572 } 1573 1574 /************************************************************************* 1575 * @ [SHLWAPI.514] 1576 * 1577 * Calls IProfferService methods to proffer/revoke specified service. 1578 * 1579 * PARAMS 1580 * lpUnknown [I] Object to get an IServiceProvider interface from 1581 * service [I] Service ID for IProfferService::Proffer/Revoke calls 1582 * pService [I] Service to proffer. If NULL ::Revoke is called 1583 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call 1584 * 1585 * RETURNS 1586 * Success: S_OK. IProffer method returns S_OK 1587 * Failure: An HRESULT error code 1588 * 1589 * NOTES 1590 * lpUnknown is expected to support the IServiceProvider interface. 1591 */ 1592 HRESULT WINAPI IUnknown_ProfferService(IUnknown *lpUnknown, REFGUID service, IServiceProvider *pService, DWORD *pCookie) 1593 { 1594 IProfferService *proffer; 1595 HRESULT hr; 1596 1597 TRACE("%p %s %p %p\n", lpUnknown, debugstr_guid(service), pService, pCookie); 1598 1599 hr = IUnknown_QueryService(lpUnknown, &IID_IProfferService, &IID_IProfferService, (void**)&proffer); 1600 if (hr == S_OK) 1601 { 1602 if (pService) 1603 hr = IProfferService_ProfferService(proffer, service, pService, pCookie); 1604 else 1605 { 1606 hr = IProfferService_RevokeService(proffer, *pCookie); 1607 *pCookie = 0; 1608 } 1609 1610 IProfferService_Release(proffer); 1611 } 1612 1613 return hr; 1614 } 1615 1616 /************************************************************************* 1617 * @ [SHLWAPI.479] 1618 * 1619 * Call an object's UIActivateIO method. 1620 * 1621 * PARAMS 1622 * unknown [I] Object to call the UIActivateIO method on 1623 * activate [I] Parameter for UIActivateIO call 1624 * msg [I] Parameter for UIActivateIO call 1625 * 1626 * RETURNS 1627 * Success: Value of UI_ActivateIO call 1628 * Failure: An HRESULT error code 1629 * 1630 * NOTES 1631 * unknown is expected to support the IInputObject interface. 1632 */ 1633 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg) 1634 { 1635 IInputObject* object = NULL; 1636 HRESULT ret; 1637 1638 if (!unknown) 1639 return E_FAIL; 1640 1641 /* Get an IInputObject interface from the object */ 1642 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object); 1643 1644 if (ret == S_OK) 1645 { 1646 ret = IInputObject_UIActivateIO(object, activate, msg); 1647 IInputObject_Release(object); 1648 } 1649 1650 return ret; 1651 } 1652 1653 /************************************************************************* 1654 * @ [SHLWAPI.177] 1655 * 1656 * Loads a popup menu. 1657 * 1658 * PARAMS 1659 * hInst [I] Instance handle 1660 * szName [I] Menu name 1661 * 1662 * RETURNS 1663 * Success: TRUE. 1664 * Failure: FALSE. 1665 */ 1666 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName) 1667 { 1668 HMENU hMenu; 1669 1670 TRACE("%p %s\n", hInst, debugstr_w(szName)); 1671 1672 if ((hMenu = LoadMenuW(hInst, szName))) 1673 { 1674 if (GetSubMenu(hMenu, 0)) 1675 RemoveMenu(hMenu, 0, MF_BYPOSITION); 1676 1677 DestroyMenu(hMenu); 1678 return TRUE; 1679 } 1680 return FALSE; 1681 } 1682 1683 typedef struct _enumWndData 1684 { 1685 UINT uiMsgId; 1686 WPARAM wParam; 1687 LPARAM lParam; 1688 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM); 1689 } enumWndData; 1690 1691 /* Callback for SHLWAPI_178 */ 1692 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam) 1693 { 1694 enumWndData *data = (enumWndData *)lParam; 1695 1696 TRACE("(%p,%p)\n", hWnd, data); 1697 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam); 1698 return TRUE; 1699 } 1700 1701 /************************************************************************* 1702 * @ [SHLWAPI.178] 1703 * 1704 * Send or post a message to every child of a window. 1705 * 1706 * PARAMS 1707 * hWnd [I] Window whose children will get the messages 1708 * uiMsgId [I] Message Id 1709 * wParam [I] WPARAM of message 1710 * lParam [I] LPARAM of message 1711 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA() 1712 * 1713 * RETURNS 1714 * Nothing. 1715 * 1716 * NOTES 1717 * The appropriate ASCII or Unicode function is called for the window. 1718 */ 1719 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend) 1720 { 1721 enumWndData data; 1722 1723 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend); 1724 1725 if(hWnd) 1726 { 1727 data.uiMsgId = uiMsgId; 1728 data.wParam = wParam; 1729 data.lParam = lParam; 1730 1731 if (bSend) 1732 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA; 1733 else 1734 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA; 1735 1736 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data); 1737 } 1738 } 1739 1740 /************************************************************************* 1741 * @ [SHLWAPI.180] 1742 * 1743 * Remove all sub-menus from a menu. 1744 * 1745 * PARAMS 1746 * hMenu [I] Menu to remove sub-menus from 1747 * 1748 * RETURNS 1749 * Success: 0. All sub-menus under hMenu are removed 1750 * Failure: -1, if any parameter is invalid 1751 */ 1752 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu) 1753 { 1754 int iItemCount = GetMenuItemCount(hMenu) - 1; 1755 1756 TRACE("%p\n", hMenu); 1757 1758 while (iItemCount >= 0) 1759 { 1760 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount); 1761 if (hSubMenu) 1762 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION); 1763 iItemCount--; 1764 } 1765 return iItemCount; 1766 } 1767 1768 /************************************************************************* 1769 * @ [SHLWAPI.181] 1770 * 1771 * Enable or disable a menu item. 1772 * 1773 * PARAMS 1774 * hMenu [I] Menu holding menu item 1775 * uID [I] ID of menu item to enable/disable 1776 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item. 1777 * 1778 * RETURNS 1779 * The return code from EnableMenuItem. 1780 */ 1781 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable) 1782 { 1783 TRACE("%p, %u, %d\n", hMenu, wItemID, bEnable); 1784 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED); 1785 } 1786 1787 /************************************************************************* 1788 * @ [SHLWAPI.182] 1789 * 1790 * Check or uncheck a menu item. 1791 * 1792 * PARAMS 1793 * hMenu [I] Menu holding menu item 1794 * uID [I] ID of menu item to check/uncheck 1795 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item. 1796 * 1797 * RETURNS 1798 * The return code from CheckMenuItem. 1799 */ 1800 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck) 1801 { 1802 TRACE("%p, %u, %d\n", hMenu, uID, bCheck); 1803 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED); 1804 } 1805 1806 /************************************************************************* 1807 * @ [SHLWAPI.183] 1808 * 1809 * Register a window class if it isn't already. 1810 * 1811 * PARAMS 1812 * lpWndClass [I] Window class to register 1813 * 1814 * RETURNS 1815 * The result of the RegisterClassA call. 1816 */ 1817 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass) 1818 { 1819 WNDCLASSA wca; 1820 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca)) 1821 return TRUE; 1822 return (DWORD)RegisterClassA(wndclass); 1823 } 1824 1825 /************************************************************************* 1826 * @ [SHLWAPI.186] 1827 */ 1828 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj, 1829 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect) 1830 { 1831 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY; 1832 POINTL pt = { 0, 0 }; 1833 1834 TRACE("%p %p 0x%08x %p %p\n", pDrop, pDataObj, grfKeyState, lpPt, pdwEffect); 1835 1836 if (!lpPt) 1837 lpPt = &pt; 1838 1839 if (!pdwEffect) 1840 pdwEffect = &dwEffect; 1841 1842 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect); 1843 1844 if (*pdwEffect != DROPEFFECT_NONE) 1845 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect); 1846 1847 IDropTarget_DragLeave(pDrop); 1848 return TRUE; 1849 } 1850 1851 /************************************************************************* 1852 * @ [SHLWAPI.187] 1853 * 1854 * Call IPersistPropertyBag_Load() on an object. 1855 * 1856 * PARAMS 1857 * lpUnknown [I] Object supporting the IPersistPropertyBag interface 1858 * lpPropBag [O] Destination for loaded IPropertyBag 1859 * 1860 * RETURNS 1861 * Success: S_OK. 1862 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL. 1863 */ 1864 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag) 1865 { 1866 IPersistPropertyBag* lpPPBag; 1867 HRESULT hRet = E_FAIL; 1868 1869 TRACE("(%p,%p)\n", lpUnknown, lpPropBag); 1870 1871 if (lpUnknown) 1872 { 1873 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag, 1874 (void**)&lpPPBag); 1875 if (SUCCEEDED(hRet) && lpPPBag) 1876 { 1877 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL); 1878 IPersistPropertyBag_Release(lpPPBag); 1879 } 1880 } 1881 return hRet; 1882 } 1883 1884 /************************************************************************* 1885 * @ [SHLWAPI.188] 1886 * 1887 * Call IOleControlSite_TranslateAccelerator() on an object. 1888 * 1889 * PARAMS 1890 * lpUnknown [I] Object supporting the IOleControlSite interface. 1891 * lpMsg [I] Key message to be processed. 1892 * dwModifiers [I] Flags containing the state of the modifier keys. 1893 * 1894 * RETURNS 1895 * Success: S_OK. 1896 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL. 1897 */ 1898 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers) 1899 { 1900 IOleControlSite* lpCSite = NULL; 1901 HRESULT hRet = E_INVALIDARG; 1902 1903 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers); 1904 if (lpUnknown) 1905 { 1906 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite, 1907 (void**)&lpCSite); 1908 if (SUCCEEDED(hRet) && lpCSite) 1909 { 1910 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers); 1911 IOleControlSite_Release(lpCSite); 1912 } 1913 } 1914 return hRet; 1915 } 1916 1917 1918 /************************************************************************* 1919 * @ [SHLWAPI.189] 1920 * 1921 * Call IOleControlSite_OnFocus() on an object. 1922 * 1923 * PARAMS 1924 * lpUnknown [I] Object supporting the IOleControlSite interface. 1925 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE). 1926 * 1927 * RETURNS 1928 * Success: S_OK. 1929 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL. 1930 */ 1931 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus) 1932 { 1933 IOleControlSite* lpCSite = NULL; 1934 HRESULT hRet = E_FAIL; 1935 1936 TRACE("(%p, %d)\n", lpUnknown, fGotFocus); 1937 if (lpUnknown) 1938 { 1939 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite, 1940 (void**)&lpCSite); 1941 if (SUCCEEDED(hRet) && lpCSite) 1942 { 1943 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus); 1944 IOleControlSite_Release(lpCSite); 1945 } 1946 } 1947 return hRet; 1948 } 1949 1950 /************************************************************************* 1951 * @ [SHLWAPI.190] 1952 */ 1953 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1, 1954 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4) 1955 { 1956 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */ 1957 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 }; 1958 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */ 1959 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 }; 1960 HRESULT hRet = E_INVALIDARG; 1961 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */ 1962 1963 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4); 1964 1965 if (lpUnknown && lpArg4) 1966 { 1967 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id, 1968 (REFGUID)function_id, (void**)&lpUnkInner); 1969 1970 if (SUCCEEDED(hRet) && lpUnkInner) 1971 { 1972 /* FIXME: The type of service object requested is unknown, however 1973 * testing shows that its first method is called with 4 parameters. 1974 * Fake this by using IParseDisplayName_ParseDisplayName since the 1975 * signature and position in the vtable matches our unknown object type. 1976 */ 1977 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner, 1978 lpArg1, lpArg2, lpArg3, lpArg4); 1979 IUnknown_Release(lpUnkInner); 1980 } 1981 } 1982 return hRet; 1983 } 1984 1985 /************************************************************************* 1986 * @ [SHLWAPI.192] 1987 * 1988 * Get a sub-menu from a menu item. 1989 * 1990 * PARAMS 1991 * hMenu [I] Menu to get sub-menu from 1992 * uID [I] ID of menu item containing sub-menu 1993 * 1994 * RETURNS 1995 * The sub-menu of the item, or a NULL handle if any parameters are invalid. 1996 */ 1997 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID) 1998 { 1999 MENUITEMINFOW mi; 2000 2001 TRACE("(%p,%u)\n", hMenu, uID); 2002 2003 mi.cbSize = sizeof(mi); 2004 mi.fMask = MIIM_SUBMENU; 2005 2006 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi)) 2007 return NULL; 2008 2009 return mi.hSubMenu; 2010 } 2011 2012 /************************************************************************* 2013 * @ [SHLWAPI.193] 2014 * 2015 * Get the color depth of the primary display. 2016 * 2017 * PARAMS 2018 * None. 2019 * 2020 * RETURNS 2021 * The color depth of the primary display. 2022 */ 2023 DWORD WINAPI SHGetCurColorRes(void) 2024 { 2025 HDC hdc; 2026 DWORD ret; 2027 2028 TRACE("()\n"); 2029 2030 hdc = GetDC(0); 2031 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES); 2032 ReleaseDC(0, hdc); 2033 return ret; 2034 } 2035 2036 /************************************************************************* 2037 * @ [SHLWAPI.194] 2038 * 2039 * Wait for a message to arrive, with a timeout. 2040 * 2041 * PARAMS 2042 * hand [I] Handle to query 2043 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout 2044 * 2045 * RETURNS 2046 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes. 2047 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a 2048 * message is available. 2049 */ 2050 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout) 2051 { 2052 DWORD dwEndTicks = GetTickCount() + dwTimeout; 2053 DWORD dwRet; 2054 2055 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1) 2056 { 2057 MSG msg; 2058 2059 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE); 2060 2061 if (dwTimeout != INFINITE) 2062 { 2063 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0) 2064 return WAIT_TIMEOUT; 2065 } 2066 } 2067 2068 return dwRet; 2069 } 2070 2071 /************************************************************************* 2072 * @ [SHLWAPI.195] 2073 * 2074 * Determine if a shell folder can be expanded. 2075 * 2076 * PARAMS 2077 * lpFolder [I] Parent folder containing the object to test. 2078 * pidl [I] Id of the object to test. 2079 * 2080 * RETURNS 2081 * Success: S_OK, if the object is expandable, S_FALSE otherwise. 2082 * Failure: E_INVALIDARG, if any argument is invalid. 2083 * 2084 * NOTES 2085 * If the object to be tested does not expose the IQueryInfo() interface it 2086 * will not be identified as an expandable folder. 2087 */ 2088 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl) 2089 { 2090 HRESULT hRet = E_INVALIDARG; 2091 IQueryInfo *lpInfo; 2092 2093 if (lpFolder && pidl) 2094 { 2095 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo, 2096 NULL, (void**)&lpInfo); 2097 if (FAILED(hRet)) 2098 hRet = S_FALSE; /* Doesn't expose IQueryInfo */ 2099 else 2100 { 2101 DWORD dwFlags = 0; 2102 2103 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not 2104 * currently used". Really? You wouldn't be holding out on me would you? 2105 */ 2106 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags); 2107 2108 if (SUCCEEDED(hRet)) 2109 { 2110 /* 0x2 is an undocumented flag apparently indicating expandability */ 2111 hRet = dwFlags & 0x2 ? S_OK : S_FALSE; 2112 } 2113 2114 IQueryInfo_Release(lpInfo); 2115 } 2116 } 2117 return hRet; 2118 } 2119 2120 /************************************************************************* 2121 * @ [SHLWAPI.197] 2122 * 2123 * Blank out a region of text by drawing the background only. 2124 * 2125 * PARAMS 2126 * hDC [I] Device context to draw in 2127 * pRect [I] Area to draw in 2128 * cRef [I] Color to draw in 2129 * 2130 * RETURNS 2131 * Nothing. 2132 */ 2133 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef) 2134 { 2135 COLORREF cOldColor = SetBkColor(hDC, cRef); 2136 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0); 2137 SetBkColor(hDC, cOldColor); 2138 return 0; 2139 } 2140 2141 /************************************************************************* 2142 * @ [SHLWAPI.198] 2143 * 2144 * Return the value associated with a key in a map. 2145 * 2146 * PARAMS 2147 * lpKeys [I] A list of keys of length iLen 2148 * lpValues [I] A list of values associated with lpKeys, of length iLen 2149 * iLen [I] Length of both lpKeys and lpValues 2150 * iKey [I] The key value to look up in lpKeys 2151 * 2152 * RETURNS 2153 * The value in lpValues associated with iKey, or -1 if iKey is not 2154 * found in lpKeys. 2155 * 2156 * NOTES 2157 * - If two elements in the map share the same key, this function returns 2158 * the value closest to the start of the map 2159 * - The native version of this function crashes if lpKeys or lpValues is NULL. 2160 */ 2161 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey) 2162 { 2163 if (lpKeys && lpValues) 2164 { 2165 int i = 0; 2166 2167 while (i < iLen) 2168 { 2169 if (lpKeys[i] == iKey) 2170 return lpValues[i]; /* Found */ 2171 i++; 2172 } 2173 } 2174 return -1; /* Not found */ 2175 } 2176 2177 2178 /************************************************************************* 2179 * @ [SHLWAPI.199] 2180 * 2181 * Copy an interface pointer 2182 * 2183 * PARAMS 2184 * lppDest [O] Destination for copy 2185 * lpUnknown [I] Source for copy 2186 * 2187 * RETURNS 2188 * Nothing. 2189 */ 2190 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown) 2191 { 2192 TRACE("(%p,%p)\n", lppDest, lpUnknown); 2193 2194 IUnknown_AtomicRelease(lppDest); 2195 2196 if (lpUnknown) 2197 { 2198 IUnknown_AddRef(lpUnknown); 2199 *lppDest = lpUnknown; 2200 } 2201 } 2202 2203 /************************************************************************* 2204 * @ [SHLWAPI.200] 2205 * 2206 */ 2207 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved, 2208 REFGUID riidCmdGrp, ULONG cCmds, 2209 OLECMD *prgCmds, OLECMDTEXT* pCmdText) 2210 { 2211 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n", 2212 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText); 2213 2214 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */ 2215 return DRAGDROP_E_NOTREGISTERED; 2216 } 2217 2218 /************************************************************************* 2219 * @ [SHLWAPI.201] 2220 * 2221 */ 2222 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup, 2223 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn, 2224 VARIANT* pvaOut) 2225 { 2226 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup, 2227 nCmdID, nCmdexecopt, pvaIn, pvaOut); 2228 return DRAGDROP_E_NOTREGISTERED; 2229 } 2230 2231 /************************************************************************* 2232 * @ [SHLWAPI.202] 2233 * 2234 */ 2235 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds) 2236 { 2237 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds); 2238 return DRAGDROP_E_NOTREGISTERED; 2239 } 2240 2241 /************************************************************************* 2242 * @ [SHLWAPI.204] 2243 * 2244 * Determine if a window is not a child of another window. 2245 * 2246 * PARAMS 2247 * hParent [I] Suspected parent window 2248 * hChild [I] Suspected child window 2249 * 2250 * RETURNS 2251 * TRUE: If hChild is a child window of hParent 2252 * FALSE: If hChild is not a child window of hParent, or they are equal 2253 */ 2254 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild) 2255 { 2256 TRACE("(%p,%p)\n", hParent, hChild); 2257 2258 if (!hParent || !hChild) 2259 return TRUE; 2260 else if(hParent == hChild) 2261 return FALSE; 2262 return !IsChild(hParent, hChild); 2263 } 2264 2265 /************************************************************************* 2266 * FDSA functions. Manage a dynamic array of fixed size memory blocks. 2267 */ 2268 2269 typedef struct 2270 { 2271 DWORD num_items; /* Number of elements inserted */ 2272 void *mem; /* Ptr to array */ 2273 DWORD blocks_alloced; /* Number of elements allocated */ 2274 BYTE inc; /* Number of elements to grow by when we need to expand */ 2275 BYTE block_size; /* Size in bytes of an element */ 2276 BYTE flags; /* Flags */ 2277 } FDSA_info; 2278 2279 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */ 2280 2281 /************************************************************************* 2282 * @ [SHLWAPI.208] 2283 * 2284 * Initialize an FDSA array. 2285 */ 2286 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem, 2287 DWORD init_blocks) 2288 { 2289 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks); 2290 2291 if(inc == 0) 2292 inc = 1; 2293 2294 if(mem) 2295 memset(mem, 0, block_size * init_blocks); 2296 2297 info->num_items = 0; 2298 info->inc = inc; 2299 info->mem = mem; 2300 info->blocks_alloced = init_blocks; 2301 info->block_size = block_size; 2302 info->flags = 0; 2303 2304 return TRUE; 2305 } 2306 2307 /************************************************************************* 2308 * @ [SHLWAPI.209] 2309 * 2310 * Destroy an FDSA array 2311 */ 2312 BOOL WINAPI FDSA_Destroy(FDSA_info *info) 2313 { 2314 TRACE("(%p)\n", info); 2315 2316 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC) 2317 { 2318 HeapFree(GetProcessHeap(), 0, info->mem); 2319 return FALSE; 2320 } 2321 2322 return TRUE; 2323 } 2324 2325 /************************************************************************* 2326 * @ [SHLWAPI.210] 2327 * 2328 * Insert element into an FDSA array 2329 */ 2330 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block) 2331 { 2332 TRACE("(%p 0x%08x %p)\n", info, where, block); 2333 if(where > info->num_items) 2334 where = info->num_items; 2335 2336 if(info->num_items >= info->blocks_alloced) 2337 { 2338 DWORD size = (info->blocks_alloced + info->inc) * info->block_size; 2339 if(info->flags & 0x1) 2340 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size); 2341 else 2342 { 2343 void *old_mem = info->mem; 2344 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 2345 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size); 2346 } 2347 info->blocks_alloced += info->inc; 2348 info->flags |= 0x1; 2349 } 2350 2351 if(where < info->num_items) 2352 { 2353 memmove((char*)info->mem + (where + 1) * info->block_size, 2354 (char*)info->mem + where * info->block_size, 2355 (info->num_items - where) * info->block_size); 2356 } 2357 memcpy((char*)info->mem + where * info->block_size, block, info->block_size); 2358 2359 info->num_items++; 2360 return where; 2361 } 2362 2363 /************************************************************************* 2364 * @ [SHLWAPI.211] 2365 * 2366 * Delete an element from an FDSA array. 2367 */ 2368 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where) 2369 { 2370 TRACE("(%p 0x%08x)\n", info, where); 2371 2372 if(where >= info->num_items) 2373 return FALSE; 2374 2375 if(where < info->num_items - 1) 2376 { 2377 memmove((char*)info->mem + where * info->block_size, 2378 (char*)info->mem + (where + 1) * info->block_size, 2379 (info->num_items - where - 1) * info->block_size); 2380 } 2381 memset((char*)info->mem + (info->num_items - 1) * info->block_size, 2382 0, info->block_size); 2383 info->num_items--; 2384 return TRUE; 2385 } 2386 2387 /************************************************************************* 2388 * @ [SHLWAPI.219] 2389 * 2390 * Call IUnknown_QueryInterface() on a table of objects. 2391 * 2392 * RETURNS 2393 * Success: S_OK. 2394 * Failure: E_POINTER or E_NOINTERFACE. 2395 */ 2396 HRESULT WINAPI QISearch( 2397 void *base, /* [in] Table of interfaces */ 2398 const QITAB *table, /* [in] Array of REFIIDs and indexes into the table */ 2399 REFIID riid, /* [in] REFIID to get interface for */ 2400 void **ppv) /* [out] Destination for interface pointer */ 2401 { 2402 HRESULT ret; 2403 IUnknown *a_vtbl; 2404 const QITAB *xmove; 2405 2406 TRACE("(%p %p %s %p)\n", base, table, debugstr_guid(riid), ppv); 2407 if (ppv) { 2408 xmove = table; 2409 while (xmove->piid) { 2410 TRACE("trying (offset %d) %s\n", xmove->dwOffset, debugstr_guid(xmove->piid)); 2411 if (IsEqualIID(riid, xmove->piid)) { 2412 a_vtbl = (IUnknown*)(xmove->dwOffset + (LPBYTE)base); 2413 TRACE("matched, returning (%p)\n", a_vtbl); 2414 *ppv = a_vtbl; 2415 IUnknown_AddRef(a_vtbl); 2416 return S_OK; 2417 } 2418 xmove++; 2419 } 2420 2421 if (IsEqualIID(riid, &IID_IUnknown)) { 2422 a_vtbl = (IUnknown*)(table->dwOffset + (LPBYTE)base); 2423 TRACE("returning first for IUnknown (%p)\n", a_vtbl); 2424 *ppv = a_vtbl; 2425 IUnknown_AddRef(a_vtbl); 2426 return S_OK; 2427 } 2428 *ppv = 0; 2429 ret = E_NOINTERFACE; 2430 } else 2431 ret = E_POINTER; 2432 2433 TRACE("-- 0x%08x\n", ret); 2434 return ret; 2435 } 2436 2437 /************************************************************************* 2438 * @ [SHLWAPI.220] 2439 * 2440 * Set the Font for a window and the "PropDlgFont" property of the parent window. 2441 * 2442 * PARAMS 2443 * hWnd [I] Parent Window to set the property 2444 * id [I] Index of child Window to set the Font 2445 * 2446 * RETURNS 2447 #ifdef __REACTOS__ 2448 * VOID 2449 #else 2450 * Success: S_OK 2451 #endif 2452 * 2453 */ 2454 #ifdef __REACTOS__ 2455 VOID WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id) 2456 #else 2457 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id) 2458 #endif 2459 { 2460 #ifdef __REACTOS__ 2461 HFONT hOldFont, hNewFont; 2462 LOGFONTW lfOldFont, lfNewFont; 2463 HWND hwndItem; 2464 2465 TRACE("(%p, %d)\n", hWnd, id); 2466 2467 hOldFont = (HFONT)SendMessageW(hWnd, WM_GETFONT, 0, 0); 2468 GetObjectW(hOldFont, sizeof(lfOldFont), &lfOldFont); 2469 SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lfNewFont), &lfNewFont, 0); 2470 2471 if (lfOldFont.lfCharSet == lfNewFont.lfCharSet) 2472 return; 2473 2474 hNewFont = GetPropW(hWnd, L"PropDlgFont"); 2475 if (!hNewFont) 2476 { 2477 /* Create the icon-title font of the same height */ 2478 lfNewFont.lfHeight = lfOldFont.lfHeight; 2479 hNewFont = CreateFontIndirectW(&lfNewFont); 2480 2481 /* If creating the font is failed, then keep the old font */ 2482 if (!hNewFont) 2483 hNewFont = hOldFont; 2484 2485 /* Set "PropDlgFont" property if the font is changed */ 2486 if (hOldFont != hNewFont) 2487 SetPropW(hWnd, L"PropDlgFont", hNewFont); 2488 } 2489 2490 hwndItem = GetDlgItem(hWnd, id); 2491 SendMessageW(hwndItem, WM_SETFONT, (WPARAM)hNewFont, 0); 2492 #else 2493 FIXME("(%p, %d) stub\n", hWnd, id); 2494 return S_OK; 2495 #endif 2496 } 2497 2498 /************************************************************************* 2499 * @ [SHLWAPI.221] 2500 * 2501 * Remove the "PropDlgFont" property from a window. 2502 * 2503 * PARAMS 2504 * hWnd [I] Window to remove the property from 2505 * 2506 * RETURNS 2507 * A handle to the removed property, or NULL if it did not exist. 2508 */ 2509 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd) 2510 { 2511 HANDLE hProp; 2512 2513 TRACE("(%p)\n", hWnd); 2514 2515 hProp = GetPropA(hWnd, "PropDlgFont"); 2516 2517 if(hProp) 2518 { 2519 DeleteObject(hProp); 2520 hProp = RemovePropA(hWnd, "PropDlgFont"); 2521 } 2522 return hProp; 2523 } 2524 2525 /************************************************************************* 2526 * @ [SHLWAPI.236] 2527 * 2528 * Load the in-process server of a given GUID. 2529 * 2530 * PARAMS 2531 * refiid [I] GUID of the server to load. 2532 * 2533 * RETURNS 2534 * Success: A handle to the loaded server dll. 2535 * Failure: A NULL handle. 2536 */ 2537 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid) 2538 { 2539 HKEY newkey; 2540 DWORD type, count; 2541 CHAR value[MAX_PATH], string[MAX_PATH]; 2542 2543 strcpy(string, "CLSID\\"); 2544 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6); 2545 strcat(string, "\\InProcServer32"); 2546 2547 count = MAX_PATH; 2548 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey); 2549 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count); 2550 RegCloseKey(newkey); 2551 return LoadLibraryExA(value, 0, 0); 2552 } 2553 2554 /************************************************************************* 2555 * @ [SHLWAPI.237] 2556 * 2557 * Unicode version of SHLWAPI_183. 2558 */ 2559 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass) 2560 { 2561 WNDCLASSW WndClass; 2562 2563 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName)); 2564 2565 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass)) 2566 return TRUE; 2567 return RegisterClassW(lpWndClass); 2568 } 2569 2570 /************************************************************************* 2571 * @ [SHLWAPI.238] 2572 * 2573 * Unregister a list of classes. 2574 * 2575 * PARAMS 2576 * hInst [I] Application instance that registered the classes 2577 * lppClasses [I] List of class names 2578 * iCount [I] Number of names in lppClasses 2579 * 2580 * RETURNS 2581 * Nothing. 2582 */ 2583 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount) 2584 { 2585 WNDCLASSA WndClass; 2586 2587 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount); 2588 2589 while (iCount > 0) 2590 { 2591 if (GetClassInfoA(hInst, *lppClasses, &WndClass)) 2592 UnregisterClassA(*lppClasses, hInst); 2593 lppClasses++; 2594 iCount--; 2595 } 2596 } 2597 2598 /************************************************************************* 2599 * @ [SHLWAPI.239] 2600 * 2601 * Unicode version of SHUnregisterClassesA. 2602 */ 2603 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount) 2604 { 2605 WNDCLASSW WndClass; 2606 2607 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount); 2608 2609 while (iCount > 0) 2610 { 2611 if (GetClassInfoW(hInst, *lppClasses, &WndClass)) 2612 UnregisterClassW(*lppClasses, hInst); 2613 lppClasses++; 2614 iCount--; 2615 } 2616 } 2617 2618 /************************************************************************* 2619 * @ [SHLWAPI.240] 2620 * 2621 * Call The correct (Ascii/Unicode) default window procedure for a window. 2622 * 2623 * PARAMS 2624 * hWnd [I] Window to call the default procedure for 2625 * uMessage [I] Message ID 2626 * wParam [I] WPARAM of message 2627 * lParam [I] LPARAM of message 2628 * 2629 * RETURNS 2630 * The result of calling DefWindowProcA() or DefWindowProcW(). 2631 */ 2632 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) 2633 { 2634 if (IsWindowUnicode(hWnd)) 2635 return DefWindowProcW(hWnd, uMessage, wParam, lParam); 2636 return DefWindowProcA(hWnd, uMessage, wParam, lParam); 2637 } 2638 2639 /************************************************************************* 2640 * @ [SHLWAPI.256] 2641 */ 2642 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite) 2643 { 2644 HRESULT hRet = E_INVALIDARG; 2645 LPOBJECTWITHSITE lpSite = NULL; 2646 2647 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite); 2648 2649 if (lpUnknown && iid && lppSite) 2650 { 2651 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite, 2652 (void**)&lpSite); 2653 if (SUCCEEDED(hRet) && lpSite) 2654 { 2655 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite); 2656 IObjectWithSite_Release(lpSite); 2657 } 2658 } 2659 return hRet; 2660 } 2661 2662 /************************************************************************* 2663 * @ [SHLWAPI.257] 2664 * 2665 * Create a worker window using CreateWindowExA(). 2666 * 2667 * PARAMS 2668 * wndProc [I] Window procedure 2669 * hWndParent [I] Parent window 2670 * dwExStyle [I] Extra style flags 2671 * dwStyle [I] Style flags 2672 * hMenu [I] Window menu 2673 * wnd_extra [I] Window extra bytes value 2674 * 2675 * RETURNS 2676 * Success: The window handle of the newly created window. 2677 * Failure: 0. 2678 */ 2679 HWND WINAPI SHCreateWorkerWindowA(WNDPROC wndProc, HWND hWndParent, DWORD dwExStyle, 2680 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra) 2681 { 2682 static const char szClass[] = "WorkerA"; 2683 WNDCLASSA wc; 2684 HWND hWnd; 2685 2686 TRACE("(%p, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n", 2687 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra); 2688 2689 /* Create Window class */ 2690 wc.style = 0; 2691 wc.lpfnWndProc = DefWindowProcA; 2692 wc.cbClsExtra = 0; 2693 wc.cbWndExtra = sizeof(LONG_PTR); 2694 wc.hInstance = shlwapi_hInstance; 2695 wc.hIcon = NULL; 2696 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW); 2697 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); 2698 wc.lpszMenuName = NULL; 2699 wc.lpszClassName = szClass; 2700 2701 SHRegisterClassA(&wc); 2702 2703 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0, 2704 hWndParent, hMenu, shlwapi_hInstance, 0); 2705 if (hWnd) 2706 { 2707 SetWindowLongPtrW(hWnd, 0, wnd_extra); 2708 if (wndProc) SetWindowLongPtrA(hWnd, GWLP_WNDPROC, (LONG_PTR)wndProc); 2709 } 2710 2711 return hWnd; 2712 } 2713 2714 #ifndef __REACTOS__ /* The followings are defined in <shlwapi_undoc.h> */ 2715 typedef struct tagPOLICYDATA 2716 { 2717 DWORD policy; /* flags value passed to SHRestricted */ 2718 LPCWSTR appstr; /* application str such as "Explorer" */ 2719 LPCWSTR keystr; /* name of the actual registry key / policy */ 2720 } POLICYDATA, *LPPOLICYDATA; 2721 2722 #define SHELL_NO_POLICY 0xffffffff 2723 2724 /* default shell policy registry key */ 2725 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o', 2726 's','o','f','t','\\','W','i','n','d','o','w','s','\\', 2727 'C','u','r','r','e','n','t','V','e','r','s','i','o','n', 2728 '\\','P','o','l','i','c','i','e','s',0}; 2729 #endif /* ndef __REACTOS__ */ 2730 2731 /************************************************************************* 2732 * @ [SHLWAPI.271] 2733 * 2734 * Retrieve a policy value from the registry. 2735 * 2736 * PARAMS 2737 * lpSubKey [I] registry key name 2738 * lpSubName [I] subname of registry key 2739 * lpValue [I] value name of registry value 2740 * 2741 * RETURNS 2742 * the value associated with the registry key or 0 if not found 2743 */ 2744 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue) 2745 { 2746 #ifdef __REACTOS__ 2747 WCHAR szPath[MAX_PATH]; 2748 DWORD dwSize, dwValue = 0; 2749 2750 TRACE("(%s, %s, %s)\n", debugstr_w(lpSubKey), debugstr_w(lpSubName), debugstr_w(lpValue)); 2751 2752 if (!lpSubKey) 2753 lpSubKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies"; 2754 2755 PathCombineW(szPath, lpSubKey, lpSubName); 2756 2757 dwSize = sizeof(dwValue); 2758 if (SHGetValueW(HKEY_LOCAL_MACHINE, szPath, lpValue, NULL, &dwValue, &dwSize) == ERROR_SUCCESS) 2759 return dwValue; 2760 2761 dwSize = sizeof(dwValue); 2762 SHGetValueW(HKEY_CURRENT_USER, szPath, lpValue, NULL, &dwValue, &dwSize); 2763 return dwValue; 2764 #else 2765 DWORD retval, datsize = sizeof(retval); 2766 HKEY hKey; 2767 2768 if (!lpSubKey) 2769 lpSubKey = strRegistryPolicyW; 2770 2771 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey); 2772 if (retval != ERROR_SUCCESS) 2773 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey); 2774 if (retval != ERROR_SUCCESS) 2775 return 0; 2776 2777 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize); 2778 RegCloseKey(hKey); 2779 return retval; 2780 #endif 2781 } 2782 2783 /************************************************************************* 2784 * @ [SHLWAPI.266] 2785 * 2786 * Helper function to retrieve the possibly cached value for a specific policy 2787 * 2788 * PARAMS 2789 * policy [I] The policy to look for 2790 * initial [I] Main registry key to open, if NULL use default 2791 * polTable [I] Table of known policies, 0 terminated 2792 * polArr [I] Cache array of policy values 2793 * 2794 * RETURNS 2795 * The retrieved policy value or 0 if not successful 2796 * 2797 * NOTES 2798 * This function is used by the native SHRestricted function to search for the 2799 * policy and cache it once retrieved. The current Wine implementation uses a 2800 * different POLICYDATA structure and implements a similar algorithm adapted to 2801 * that structure. 2802 */ 2803 #ifdef __REACTOS__ 2804 DWORD WINAPI 2805 SHRestrictionLookup( 2806 _In_ DWORD policy, 2807 _In_ LPCWSTR initial, 2808 _In_ const POLICYDATA *polTable, 2809 _Inout_ LPDWORD polArr) 2810 #else 2811 DWORD WINAPI SHRestrictionLookup( 2812 DWORD policy, 2813 LPCWSTR initial, 2814 LPPOLICYDATA polTable, 2815 LPDWORD polArr) 2816 #endif 2817 { 2818 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr); 2819 2820 #ifndef __REACTOS__ 2821 if (!polTable || !polArr) 2822 return 0; 2823 #endif 2824 2825 #ifndef __REACTOS__ 2826 for (;polTable->appstr; polTable++, polArr++) 2827 #else 2828 for (;polTable->policy; polTable++, polArr++) 2829 #endif 2830 { 2831 if (policy == polTable->policy) 2832 { 2833 /* we have a known policy */ 2834 2835 /* check if this policy has been cached */ 2836 if (*polArr == SHELL_NO_POLICY) 2837 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr); 2838 return *polArr; 2839 } 2840 } 2841 /* we don't know this policy, return 0 */ 2842 TRACE("unknown policy: (%08x)\n", policy); 2843 return 0; 2844 } 2845 2846 /************************************************************************* 2847 * @ [SHLWAPI.267] 2848 * 2849 * Get an interface from an object. 2850 * 2851 * RETURNS 2852 * Success: S_OK. ppv contains the requested interface. 2853 * Failure: An HRESULT error code. 2854 * 2855 * NOTES 2856 * This QueryInterface asks the inner object for an interface. In case 2857 * of aggregation this request would be forwarded by the inner to the 2858 * outer object. This function asks the inner object directly for the 2859 * interface circumventing the forwarding to the outer object. 2860 */ 2861 HRESULT WINAPI SHWeakQueryInterface( 2862 IUnknown * pUnk, /* [in] Outer object */ 2863 IUnknown * pInner, /* [in] Inner object */ 2864 IID * riid, /* [in] Interface GUID to query for */ 2865 LPVOID* ppv) /* [out] Destination for queried interface */ 2866 { 2867 HRESULT hret = E_NOINTERFACE; 2868 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv); 2869 2870 *ppv = NULL; 2871 if(pUnk && pInner) { 2872 hret = IUnknown_QueryInterface(pInner, riid, ppv); 2873 if (SUCCEEDED(hret)) IUnknown_Release(pUnk); 2874 } 2875 TRACE("-- 0x%08x\n", hret); 2876 return hret; 2877 } 2878 2879 /************************************************************************* 2880 * @ [SHLWAPI.268] 2881 * 2882 * Move a reference from one interface to another. 2883 * 2884 * PARAMS 2885 * lpDest [O] Destination to receive the reference 2886 * lppUnknown [O] Source to give up the reference to lpDest 2887 * 2888 * RETURNS 2889 * Nothing. 2890 */ 2891 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown) 2892 { 2893 TRACE("(%p,%p)\n", lpDest, lppUnknown); 2894 2895 if (*lppUnknown) 2896 { 2897 /* Copy Reference*/ 2898 IUnknown_AddRef(lpDest); 2899 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */ 2900 } 2901 } 2902 2903 /************************************************************************* 2904 * @ [SHLWAPI.269] 2905 * 2906 * Convert an ASCII string of a CLSID into a CLSID. 2907 * 2908 * PARAMS 2909 * idstr [I] String representing a CLSID in registry format 2910 * id [O] Destination for the converted CLSID 2911 * 2912 * RETURNS 2913 * Success: TRUE. id contains the converted CLSID. 2914 * Failure: FALSE. 2915 */ 2916 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id) 2917 { 2918 WCHAR wClsid[40]; 2919 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR)); 2920 return SUCCEEDED(CLSIDFromString(wClsid, id)); 2921 } 2922 2923 /************************************************************************* 2924 * @ [SHLWAPI.270] 2925 * 2926 * Unicode version of GUIDFromStringA. 2927 */ 2928 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id) 2929 { 2930 return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id)); 2931 } 2932 2933 /************************************************************************* 2934 * @ [SHLWAPI.276] 2935 * 2936 * Determine if the browser is integrated into the shell, and set a registry 2937 * key accordingly. 2938 * 2939 * PARAMS 2940 * None. 2941 * 2942 * RETURNS 2943 * 1, If the browser is not integrated. 2944 * 2, If the browser is integrated. 2945 * 2946 * NOTES 2947 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is 2948 * either set to TRUE, or removed depending on whether the browser is deemed 2949 * to be integrated. 2950 */ 2951 DWORD WINAPI WhichPlatform(void) 2952 { 2953 static const char szIntegratedBrowser[] = "IntegratedBrowser"; 2954 static DWORD dwState = 0; 2955 HKEY hKey; 2956 DWORD dwRet, dwData, dwSize; 2957 HMODULE hshell32; 2958 2959 if (dwState) 2960 return dwState; 2961 2962 /* If shell32 exports DllGetVersion(), the browser is integrated */ 2963 dwState = 1; 2964 hshell32 = LoadLibraryA("shell32.dll"); 2965 if (hshell32) 2966 { 2967 FARPROC pDllGetVersion; 2968 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion"); 2969 dwState = pDllGetVersion ? 2 : 1; 2970 FreeLibrary(hshell32); 2971 } 2972 2973 /* Set or delete the key accordingly */ 2974 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 2975 "Software\\Microsoft\\Internet Explorer", 0, 2976 KEY_ALL_ACCESS, &hKey); 2977 if (!dwRet) 2978 { 2979 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0, 2980 (LPBYTE)&dwData, &dwSize); 2981 2982 if (!dwRet && dwState == 1) 2983 { 2984 /* Value exists but browser is not integrated */ 2985 RegDeleteValueA(hKey, szIntegratedBrowser); 2986 } 2987 else if (dwRet && dwState == 2) 2988 { 2989 /* Browser is integrated but value does not exist */ 2990 dwData = TRUE; 2991 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD, 2992 (LPBYTE)&dwData, sizeof(dwData)); 2993 } 2994 RegCloseKey(hKey); 2995 } 2996 return dwState; 2997 } 2998 2999 /************************************************************************* 3000 * @ [SHLWAPI.278] 3001 * 3002 * Unicode version of SHCreateWorkerWindowA. 3003 */ 3004 HWND WINAPI SHCreateWorkerWindowW(WNDPROC wndProc, HWND hWndParent, DWORD dwExStyle, 3005 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra) 3006 { 3007 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 }; 3008 WNDCLASSW wc; 3009 HWND hWnd; 3010 3011 TRACE("(%p, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n", 3012 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra); 3013 3014 /* If our OS is natively ANSI, use the ANSI version */ 3015 if (GetVersion() & 0x80000000) /* not NT */ 3016 { 3017 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion()); 3018 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra); 3019 } 3020 3021 /* Create Window class */ 3022 wc.style = 0; 3023 wc.lpfnWndProc = DefWindowProcW; 3024 wc.cbClsExtra = 0; 3025 wc.cbWndExtra = sizeof(LONG_PTR); 3026 wc.hInstance = shlwapi_hInstance; 3027 wc.hIcon = NULL; 3028 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); 3029 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); 3030 wc.lpszMenuName = NULL; 3031 wc.lpszClassName = szClass; 3032 3033 SHRegisterClassW(&wc); 3034 3035 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0, 3036 hWndParent, hMenu, shlwapi_hInstance, 0); 3037 if (hWnd) 3038 { 3039 SetWindowLongPtrW(hWnd, 0, wnd_extra); 3040 if (wndProc) SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)wndProc); 3041 } 3042 3043 return hWnd; 3044 } 3045 3046 /************************************************************************* 3047 * @ [SHLWAPI.279] 3048 * 3049 * Get and show a context menu from a shell folder. 3050 * 3051 * PARAMS 3052 * hWnd [I] Window displaying the shell folder 3053 * lpFolder [I] IShellFolder interface 3054 * lpApidl [I] Id for the particular folder desired 3055 * 3056 * RETURNS 3057 * Success: S_OK. 3058 * Failure: An HRESULT error code indicating the error. 3059 */ 3060 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl) 3061 { 3062 TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl); 3063 #ifdef __REACTOS__ 3064 return SHInvokeCommand(hWnd, lpFolder, lpApidl, NULL); 3065 #else 3066 return SHInvokeCommand(hWnd, lpFolder, lpApidl, 0); 3067 #endif 3068 } 3069 3070 /************************************************************************* 3071 * @ [SHLWAPI.281] 3072 * 3073 * _SHPackDispParamsV 3074 */ 3075 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist) 3076 { 3077 VARIANTARG *iter; 3078 3079 TRACE("(%p %p %u ...)\n", params, args, cnt); 3080 3081 params->rgvarg = args; 3082 params->rgdispidNamedArgs = NULL; 3083 params->cArgs = cnt; 3084 params->cNamedArgs = 0; 3085 3086 iter = args+cnt; 3087 3088 while(iter-- > args) { 3089 V_VT(iter) = va_arg(valist, enum VARENUM); 3090 3091 TRACE("vt=%d\n", V_VT(iter)); 3092 3093 if(V_VT(iter) & VT_BYREF) { 3094 V_BYREF(iter) = va_arg(valist, LPVOID); 3095 } else { 3096 switch(V_VT(iter)) { 3097 case VT_I4: 3098 V_I4(iter) = va_arg(valist, LONG); 3099 break; 3100 case VT_BSTR: 3101 V_BSTR(iter) = va_arg(valist, BSTR); 3102 break; 3103 case VT_DISPATCH: 3104 V_DISPATCH(iter) = va_arg(valist, IDispatch*); 3105 break; 3106 case VT_BOOL: 3107 V_BOOL(iter) = va_arg(valist, int); 3108 break; 3109 case VT_UNKNOWN: 3110 V_UNKNOWN(iter) = va_arg(valist, IUnknown*); 3111 break; 3112 default: 3113 V_VT(iter) = VT_I4; 3114 V_I4(iter) = va_arg(valist, LONG); 3115 } 3116 } 3117 } 3118 3119 return S_OK; 3120 } 3121 3122 /************************************************************************* 3123 * @ [SHLWAPI.282] 3124 * 3125 * SHPackDispParams 3126 */ 3127 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...) 3128 { 3129 __ms_va_list valist; 3130 HRESULT hres; 3131 3132 __ms_va_start(valist, cnt); 3133 hres = SHPackDispParamsV(params, args, cnt, valist); 3134 __ms_va_end(valist); 3135 return hres; 3136 } 3137 3138 /************************************************************************* 3139 * SHLWAPI_InvokeByIID 3140 * 3141 * This helper function calls IDispatch::Invoke for each sink 3142 * which implements given iid or IDispatch. 3143 * 3144 */ 3145 static HRESULT SHLWAPI_InvokeByIID( 3146 IConnectionPoint* iCP, 3147 REFIID iid, 3148 DISPID dispId, 3149 DISPPARAMS* dispParams) 3150 { 3151 IEnumConnections *enumerator; 3152 CONNECTDATA rgcd; 3153 static DISPPARAMS empty = {NULL, NULL, 0, 0}; 3154 DISPPARAMS* params = dispParams; 3155 3156 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator); 3157 if (FAILED(result)) 3158 return result; 3159 3160 /* Invoke is never happening with an NULL dispParams */ 3161 if (!params) 3162 params = ∅ 3163 3164 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK) 3165 { 3166 IDispatch *dispIface; 3167 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) || 3168 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface))) 3169 { 3170 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL); 3171 IDispatch_Release(dispIface); 3172 } 3173 IUnknown_Release(rgcd.pUnk); 3174 } 3175 3176 IEnumConnections_Release(enumerator); 3177 3178 return S_OK; 3179 } 3180 3181 /************************************************************************* 3182 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283] 3183 */ 3184 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP, 3185 DISPID dispId, DISPPARAMS* dispParams, 3186 DWORD unknown1, DWORD unknown2 ) 3187 { 3188 IID iid; 3189 HRESULT result; 3190 3191 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2); 3192 3193 result = IConnectionPoint_GetConnectionInterface(iCP, &iid); 3194 if (SUCCEEDED(result)) 3195 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams); 3196 else 3197 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams); 3198 3199 return result; 3200 } 3201 3202 3203 /************************************************************************* 3204 * @ [SHLWAPI.284] 3205 * 3206 * IConnectionPoint_SimpleInvoke 3207 */ 3208 HRESULT WINAPI IConnectionPoint_SimpleInvoke( 3209 IConnectionPoint* iCP, 3210 DISPID dispId, 3211 DISPPARAMS* dispParams) 3212 { 3213 IID iid; 3214 HRESULT result; 3215 3216 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams); 3217 3218 result = IConnectionPoint_GetConnectionInterface(iCP, &iid); 3219 if (SUCCEEDED(result)) 3220 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams); 3221 else 3222 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams); 3223 3224 return result; 3225 } 3226 3227 /************************************************************************* 3228 * @ [SHLWAPI.285] 3229 * 3230 * Notify an IConnectionPoint object of changes. 3231 * 3232 * PARAMS 3233 * lpCP [I] Object to notify 3234 * dispID [I] 3235 * 3236 * RETURNS 3237 * Success: S_OK. 3238 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the 3239 * IConnectionPoint interface. 3240 */ 3241 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID) 3242 { 3243 IEnumConnections *lpEnum; 3244 HRESULT hRet = E_NOINTERFACE; 3245 3246 TRACE("(%p,0x%8X)\n", lpCP, dispID); 3247 3248 /* Get an enumerator for the connections */ 3249 if (lpCP) 3250 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum); 3251 3252 if (SUCCEEDED(hRet)) 3253 { 3254 IPropertyNotifySink *lpSink; 3255 CONNECTDATA connData; 3256 ULONG ulFetched; 3257 3258 /* Call OnChanged() for every notify sink in the connection point */ 3259 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK) 3260 { 3261 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) && 3262 lpSink) 3263 { 3264 IPropertyNotifySink_OnChanged(lpSink, dispID); 3265 IPropertyNotifySink_Release(lpSink); 3266 } 3267 IUnknown_Release(connData.pUnk); 3268 } 3269 3270 IEnumConnections_Release(lpEnum); 3271 } 3272 return hRet; 3273 } 3274 3275 /************************************************************************* 3276 * @ [SHLWAPI.286] 3277 * 3278 * IUnknown_CPContainerInvokeParam 3279 */ 3280 HRESULT WINAPIV IUnknown_CPContainerInvokeParam( 3281 IUnknown *container, 3282 REFIID riid, 3283 DISPID dispId, 3284 VARIANTARG* buffer, 3285 DWORD cParams, ...) 3286 { 3287 HRESULT result; 3288 IConnectionPoint *iCP; 3289 IConnectionPointContainer *iCPC; 3290 DISPPARAMS dispParams = {buffer, NULL, cParams, 0}; 3291 __ms_va_list valist; 3292 3293 if (!container) 3294 return E_NOINTERFACE; 3295 3296 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC); 3297 if (FAILED(result)) 3298 return result; 3299 3300 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP); 3301 IConnectionPointContainer_Release(iCPC); 3302 if(FAILED(result)) 3303 return result; 3304 3305 __ms_va_start(valist, cParams); 3306 SHPackDispParamsV(&dispParams, buffer, cParams, valist); 3307 __ms_va_end(valist); 3308 3309 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams); 3310 IConnectionPoint_Release(iCP); 3311 3312 return result; 3313 } 3314 3315 /************************************************************************* 3316 * @ [SHLWAPI.287] 3317 * 3318 * Notify an IConnectionPointContainer object of changes. 3319 * 3320 * PARAMS 3321 * lpUnknown [I] Object to notify 3322 * dispID [I] 3323 * 3324 * RETURNS 3325 * Success: S_OK. 3326 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the 3327 * IConnectionPointContainer interface. 3328 */ 3329 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID) 3330 { 3331 IConnectionPointContainer* lpCPC = NULL; 3332 HRESULT hRet = E_NOINTERFACE; 3333 3334 TRACE("(%p,0x%8X)\n", lpUnknown, dispID); 3335 3336 if (lpUnknown) 3337 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC); 3338 3339 if (SUCCEEDED(hRet)) 3340 { 3341 IConnectionPoint* lpCP; 3342 3343 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP); 3344 IConnectionPointContainer_Release(lpCPC); 3345 3346 hRet = IConnectionPoint_OnChanged(lpCP, dispID); 3347 IConnectionPoint_Release(lpCP); 3348 } 3349 return hRet; 3350 } 3351 3352 /************************************************************************* 3353 * @ [SHLWAPI.289] 3354 * 3355 * See PlaySoundW. 3356 */ 3357 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound) 3358 { 3359 return PlaySoundW(pszSound, hmod, fdwSound); 3360 } 3361 3362 #ifndef __REACTOS__ /* See propbag.cpp */ 3363 /************************************************************************* 3364 * @ [SHLWAPI.294] 3365 * 3366 * Retrieve a key value from an INI file. See GetPrivateProfileString for 3367 * more information. 3368 * 3369 * PARAMS 3370 * appName [I] The section in the INI file that contains the key 3371 * keyName [I] The key to be retrieved 3372 * out [O] The buffer into which the key's value will be copied 3373 * outLen [I] The length of the `out' buffer 3374 * filename [I] The location of the INI file 3375 * 3376 * RETURNS 3377 * Length of string copied into `out'. 3378 */ 3379 DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out, 3380 DWORD outLen, LPCWSTR filename) 3381 { 3382 INT ret; 3383 WCHAR *buf; 3384 3385 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName), debugstr_w(keyName), 3386 out, outLen, debugstr_w(filename)); 3387 3388 if(outLen == 0) 3389 return 0; 3390 3391 buf = HeapAlloc(GetProcessHeap(), 0, outLen * sizeof(WCHAR)); 3392 if(!buf){ 3393 *out = 0; 3394 return 0; 3395 } 3396 3397 ret = GetPrivateProfileStringW(appName, keyName, NULL, buf, outLen, filename); 3398 if(ret) 3399 strcpyW(out, buf); 3400 else 3401 *out = 0; 3402 3403 HeapFree(GetProcessHeap(), 0, buf); 3404 3405 return strlenW(out); 3406 } 3407 #endif 3408 3409 #ifndef __REACTOS__ /* See propbag.cpp */ 3410 /************************************************************************* 3411 * @ [SHLWAPI.295] 3412 * 3413 * Set a key value in an INI file. See WritePrivateProfileString for 3414 * more information. 3415 * 3416 * PARAMS 3417 * appName [I] The section in the INI file that contains the key 3418 * keyName [I] The key to be set 3419 * str [O] The value of the key 3420 * filename [I] The location of the INI file 3421 * 3422 * RETURNS 3423 * Success: TRUE 3424 * Failure: FALSE 3425 */ 3426 BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str, 3427 LPCWSTR filename) 3428 { 3429 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str), 3430 debugstr_w(filename)); 3431 3432 return WritePrivateProfileStringW(appName, keyName, str, filename); 3433 } 3434 #endif 3435 3436 /************************************************************************* 3437 * @ [SHLWAPI.313] 3438 * 3439 * See SHGetFileInfoW. 3440 */ 3441 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes, 3442 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags) 3443 { 3444 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags); 3445 } 3446 3447 /************************************************************************* 3448 * @ [SHLWAPI.318] 3449 * 3450 * See DragQueryFileW. 3451 */ 3452 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength) 3453 { 3454 return DragQueryFileW(hDrop, lFile, lpszFile, lLength); 3455 } 3456 3457 /************************************************************************* 3458 * @ [SHLWAPI.333] 3459 * 3460 * See SHBrowseForFolderW. 3461 */ 3462 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi) 3463 { 3464 return SHBrowseForFolderW(lpBi); 3465 } 3466 3467 /************************************************************************* 3468 * @ [SHLWAPI.334] 3469 * 3470 * See SHGetPathFromIDListW. 3471 */ 3472 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath) 3473 { 3474 return SHGetPathFromIDListW(pidl, pszPath); 3475 } 3476 3477 /************************************************************************* 3478 * @ [SHLWAPI.335] 3479 * 3480 * See ShellExecuteExW. 3481 */ 3482 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo) 3483 { 3484 return ShellExecuteExW(lpExecInfo); 3485 } 3486 3487 /************************************************************************* 3488 * @ [SHLWAPI.336] 3489 * 3490 * See SHFileOperationW. 3491 */ 3492 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp) 3493 { 3494 return SHFileOperationW(lpFileOp); 3495 } 3496 3497 /************************************************************************* 3498 * @ [SHLWAPI.342] 3499 * 3500 */ 3501 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare ) 3502 { 3503 return InterlockedCompareExchangePointer( dest, xchg, compare ); 3504 } 3505 3506 /************************************************************************* 3507 * @ [SHLWAPI.350] 3508 * 3509 * See GetFileVersionInfoSizeW. 3510 */ 3511 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle ) 3512 { 3513 return GetFileVersionInfoSizeW( filename, handle ); 3514 } 3515 3516 /************************************************************************* 3517 * @ [SHLWAPI.351] 3518 * 3519 * See GetFileVersionInfoW. 3520 */ 3521 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle, 3522 DWORD datasize, LPVOID data ) 3523 { 3524 return GetFileVersionInfoW( filename, handle, datasize, data ); 3525 } 3526 3527 /************************************************************************* 3528 * @ [SHLWAPI.352] 3529 * 3530 * See VerQueryValueW. 3531 */ 3532 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock, 3533 LPVOID *lplpBuffer, UINT *puLen ) 3534 { 3535 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen ); 3536 } 3537 3538 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj))) 3539 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB 3540 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless) 3541 3542 /************************************************************************* 3543 * @ [SHLWAPI.355] 3544 * 3545 * Change the modality of a shell object. 3546 * 3547 * PARAMS 3548 * lpUnknown [I] Object to make modeless 3549 * bModeless [I] TRUE=Make modeless, FALSE=Make modal 3550 * 3551 * RETURNS 3552 * Success: S_OK. The modality lpUnknown is changed. 3553 * Failure: An HRESULT error code indicating the error. 3554 * 3555 * NOTES 3556 * lpUnknown must support the IOleInPlaceFrame interface, the 3557 * IInternetSecurityMgrSite interface, the IShellBrowser interface 3558 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface, 3559 * or this call will fail. 3560 */ 3561 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless) 3562 { 3563 IUnknown *lpObj; 3564 HRESULT hRet; 3565 3566 TRACE("(%p,%d)\n", lpUnknown, bModeless); 3567 3568 if (!lpUnknown) 3569 return E_FAIL; 3570 3571 if (IsIface(IOleInPlaceActiveObject)) 3572 EnableModeless(IOleInPlaceActiveObject); 3573 else if (IsIface(IOleInPlaceFrame)) 3574 EnableModeless(IOleInPlaceFrame); 3575 else if (IsIface(IShellBrowser)) 3576 EnableModeless(IShellBrowser); 3577 else if (IsIface(IInternetSecurityMgrSite)) 3578 EnableModeless(IInternetSecurityMgrSite); 3579 else if (IsIface(IDocHostUIHandler)) 3580 EnableModeless(IDocHostUIHandler); 3581 else 3582 return hRet; 3583 3584 IUnknown_Release(lpObj); 3585 return S_OK; 3586 } 3587 3588 /************************************************************************* 3589 * @ [SHLWAPI.357] 3590 * 3591 * See SHGetNewLinkInfoW. 3592 */ 3593 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName, 3594 BOOL *pfMustCopy, UINT uFlags) 3595 { 3596 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags); 3597 } 3598 3599 /************************************************************************* 3600 * @ [SHLWAPI.358] 3601 * 3602 * See SHDefExtractIconW. 3603 */ 3604 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge, 3605 HICON* phiconSmall, UINT nIconSize) 3606 { 3607 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize); 3608 } 3609 3610 /************************************************************************* 3611 * @ [SHLWAPI.363] 3612 * 3613 * Get and show a context menu from a shell folder. 3614 * 3615 * PARAMS 3616 * hWnd [I] Window displaying the shell folder 3617 * lpFolder [I] IShellFolder interface 3618 * lpApidl [I] Id for the particular folder desired 3619 * dwCommandId [I] The command ID to invoke (0=invoke default) 3620 * 3621 * RETURNS 3622 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was 3623 * executed. 3624 * Failure: An HRESULT error code indicating the error. 3625 */ 3626 #ifdef __REACTOS__ 3627 EXTERN_C HRESULT WINAPI SHInvokeCommandWithFlagsAndSite(HWND, IUnknown*, IShellFolder*, LPCITEMIDLIST, UINT, LPCSTR); 3628 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, LPCSTR lpVerb) 3629 { 3630 return SHInvokeCommandWithFlagsAndSite(hWnd, NULL, lpFolder, lpApidl, 0, lpVerb); 3631 } 3632 #else 3633 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, DWORD dwCommandId) 3634 { 3635 IContextMenu *iContext; 3636 HRESULT hRet; 3637 3638 TRACE("(%p, %p, %p, %u)\n", hWnd, lpFolder, lpApidl, dwCommandId); 3639 3640 if (!lpFolder) 3641 return E_FAIL; 3642 3643 /* Get the context menu from the shell folder */ 3644 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl, 3645 &IID_IContextMenu, 0, (void**)&iContext); 3646 if (SUCCEEDED(hRet)) 3647 { 3648 HMENU hMenu; 3649 if ((hMenu = CreatePopupMenu())) 3650 { 3651 HRESULT hQuery; 3652 3653 /* Add the context menu entries to the popup */ 3654 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF, 3655 dwCommandId ? CMF_NORMAL : CMF_DEFAULTONLY); 3656 3657 if (SUCCEEDED(hQuery)) 3658 { 3659 if (!dwCommandId) 3660 dwCommandId = GetMenuDefaultItem(hMenu, 0, 0); 3661 if (dwCommandId != (UINT)-1) 3662 { 3663 CMINVOKECOMMANDINFO cmIci; 3664 /* Invoke the default item */ 3665 memset(&cmIci,0,sizeof(cmIci)); 3666 cmIci.cbSize = sizeof(cmIci); 3667 cmIci.fMask = CMIC_MASK_ASYNCOK; 3668 cmIci.hwnd = hWnd; 3669 #ifdef __REACTOS__ /* r75561 */ 3670 cmIci.lpVerb = MAKEINTRESOURCEA(dwCommandId - 1); 3671 #else 3672 cmIci.lpVerb = MAKEINTRESOURCEA(dwCommandId); 3673 #endif 3674 cmIci.nShow = SW_SHOWNORMAL; 3675 3676 hRet = IContextMenu_InvokeCommand(iContext, &cmIci); 3677 } 3678 } 3679 DestroyMenu(hMenu); 3680 } 3681 IContextMenu_Release(iContext); 3682 } 3683 return hRet; 3684 } 3685 #endif /* __REACTOS__ */ 3686 3687 /************************************************************************* 3688 * @ [SHLWAPI.370] 3689 * 3690 * See ExtractIconW. 3691 */ 3692 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName, 3693 UINT nIconIndex) 3694 { 3695 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex); 3696 } 3697 3698 /************************************************************************* 3699 * @ [SHLWAPI.377] 3700 * 3701 * Load a library from the directory of a particular process. 3702 * 3703 * PARAMS 3704 * new_mod [I] Library name 3705 * inst_hwnd [I] Module whose directory is to be used 3706 * dwCrossCodePage [I] Should be FALSE (currently ignored) 3707 * 3708 * RETURNS 3709 * Success: A handle to the loaded module 3710 * Failure: A NULL handle. 3711 */ 3712 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage) 3713 { 3714 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for 3715 * each call here. 3716 * FIXME: Native shows calls to: 3717 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International" 3718 * CheckVersion 3719 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer" 3720 * RegQueryValueExA for "LPKInstalled" 3721 * RegCloseKey 3722 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International" 3723 * RegQueryValueExA for "ResourceLocale" 3724 * RegCloseKey 3725 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}" 3726 * RegQueryValueExA for "Locale" 3727 * RegCloseKey 3728 * and then tests the Locale ("en" for me). 3729 * code below 3730 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done. 3731 */ 3732 CHAR mod_path[2*MAX_PATH]; 3733 LPSTR ptr; 3734 DWORD len; 3735 3736 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage); 3737 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path)); 3738 if (!len || len >= sizeof(mod_path)) return NULL; 3739 3740 ptr = strrchr(mod_path, '\\'); 3741 if (ptr) { 3742 strcpy(ptr+1, new_mod); 3743 TRACE("loading %s\n", debugstr_a(mod_path)); 3744 return LoadLibraryA(mod_path); 3745 } 3746 return NULL; 3747 } 3748 3749 /************************************************************************* 3750 * @ [SHLWAPI.378] 3751 * 3752 * Unicode version of MLLoadLibraryA. 3753 */ 3754 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage) 3755 { 3756 WCHAR mod_path[2*MAX_PATH]; 3757 LPWSTR ptr; 3758 DWORD len; 3759 3760 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage); 3761 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR)); 3762 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL; 3763 3764 ptr = strrchrW(mod_path, '\\'); 3765 if (ptr) { 3766 strcpyW(ptr+1, new_mod); 3767 TRACE("loading %s\n", debugstr_w(mod_path)); 3768 return LoadLibraryW(mod_path); 3769 } 3770 return NULL; 3771 } 3772 3773 /************************************************************************* 3774 * ColorAdjustLuma [SHLWAPI.@] 3775 * 3776 * Adjust the luminosity of a color 3777 * 3778 * PARAMS 3779 * cRGB [I] RGB value to convert 3780 * dwLuma [I] Luma adjustment 3781 * bUnknown [I] Unknown 3782 * 3783 * RETURNS 3784 * The adjusted RGB color. 3785 */ 3786 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown) 3787 { 3788 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown); 3789 3790 if (dwLuma) 3791 { 3792 WORD wH, wL, wS; 3793 3794 ColorRGBToHLS(cRGB, &wH, &wL, &wS); 3795 3796 FIXME("Ignoring luma adjustment\n"); 3797 3798 /* FIXME: The adjustment is not linear */ 3799 3800 cRGB = ColorHLSToRGB(wH, wL, wS); 3801 } 3802 return cRGB; 3803 } 3804 3805 /************************************************************************* 3806 * @ [SHLWAPI.389] 3807 * 3808 * See GetSaveFileNameW. 3809 */ 3810 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn) 3811 { 3812 return GetSaveFileNameW(ofn); 3813 } 3814 3815 /************************************************************************* 3816 * @ [SHLWAPI.390] 3817 * 3818 * See WNetRestoreConnectionW. 3819 */ 3820 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice) 3821 { 3822 return WNetRestoreConnectionW(hwndOwner, lpszDevice); 3823 } 3824 3825 /************************************************************************* 3826 * @ [SHLWAPI.391] 3827 * 3828 * See WNetGetLastErrorW. 3829 */ 3830 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize, 3831 LPWSTR lpNameBuf, DWORD nNameBufSize) 3832 { 3833 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize); 3834 } 3835 3836 /************************************************************************* 3837 * @ [SHLWAPI.401] 3838 * 3839 * See PageSetupDlgW. 3840 */ 3841 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg) 3842 { 3843 return PageSetupDlgW(pagedlg); 3844 } 3845 3846 /************************************************************************* 3847 * @ [SHLWAPI.402] 3848 * 3849 * See PrintDlgW. 3850 */ 3851 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg) 3852 { 3853 return PrintDlgW(printdlg); 3854 } 3855 3856 /************************************************************************* 3857 * @ [SHLWAPI.403] 3858 * 3859 * See GetOpenFileNameW. 3860 */ 3861 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn) 3862 { 3863 return GetOpenFileNameW(ofn); 3864 } 3865 3866 /************************************************************************* 3867 * @ [SHLWAPI.404] 3868 */ 3869 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum) 3870 { 3871 /* Windows attempts to get an IPersist interface and, if that fails, an 3872 * IPersistFolder interface on the folder passed-in here. If one of those 3873 * interfaces is available, it then calls GetClassID on the folder... and 3874 * then calls IShellFolder_EnumObjects no matter what, even crashing if 3875 * lpFolder isn't actually an IShellFolder object. The purpose of getting 3876 * the ClassID is unknown, so we don't do it here. 3877 * 3878 * For discussion and detailed tests, see: 3879 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated" 3880 * wine-devel mailing list, 3 Jun 2010 3881 */ 3882 3883 return IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum); 3884 } 3885 3886 /* INTERNAL: Map from HLS color space to RGB */ 3887 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2) 3888 { 3889 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue; 3890 3891 if (wHue > 160) 3892 return wMid1; 3893 else if (wHue > 120) 3894 wHue = 160 - wHue; 3895 else if (wHue > 40) 3896 return wMid2; 3897 3898 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1; 3899 } 3900 3901 /* Convert to RGB and scale into RGB range (0..255) */ 3902 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240 3903 3904 /************************************************************************* 3905 * ColorHLSToRGB [SHLWAPI.@] 3906 * 3907 * Convert from hls color space into an rgb COLORREF. 3908 * 3909 * PARAMS 3910 * wHue [I] Hue amount 3911 * wLuminosity [I] Luminosity amount 3912 * wSaturation [I] Saturation amount 3913 * 3914 * RETURNS 3915 * A COLORREF representing the converted color. 3916 * 3917 * NOTES 3918 * Input hls values are constrained to the range (0..240). 3919 */ 3920 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation) 3921 { 3922 WORD wRed; 3923 3924 if (wSaturation) 3925 { 3926 WORD wGreen, wBlue, wMid1, wMid2; 3927 3928 if (wLuminosity > 120) 3929 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240; 3930 else 3931 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240; 3932 3933 wMid1 = wLuminosity * 2 - wMid2; 3934 3935 wRed = GET_RGB(wHue + 80); 3936 wGreen = GET_RGB(wHue); 3937 wBlue = GET_RGB(wHue - 80); 3938 3939 return RGB(wRed, wGreen, wBlue); 3940 } 3941 3942 wRed = wLuminosity * 255 / 240; 3943 return RGB(wRed, wRed, wRed); 3944 } 3945 3946 /************************************************************************* 3947 * @ [SHLWAPI.413] 3948 * 3949 * Get the current docking status of the system. 3950 * 3951 * PARAMS 3952 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused 3953 * 3954 * RETURNS 3955 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not 3956 * a notebook. 3957 */ 3958 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags) 3959 { 3960 HW_PROFILE_INFOA hwInfo; 3961 3962 TRACE("(0x%08x)\n", dwFlags); 3963 3964 GetCurrentHwProfileA(&hwInfo); 3965 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED)) 3966 { 3967 case DOCKINFO_DOCKED: 3968 case DOCKINFO_UNDOCKED: 3969 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED); 3970 default: 3971 return 0; 3972 } 3973 } 3974 3975 /************************************************************************* 3976 * @ [SHLWAPI.416] 3977 * 3978 */ 3979 DWORD WINAPI SHWinHelpOnDemandW(HWND hwnd, LPCWSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2) 3980 { 3981 3982 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_w(helpfile), flags1, ptr1, flags2); 3983 return 0; 3984 } 3985 3986 /************************************************************************* 3987 * @ [SHLWAPI.417] 3988 * 3989 */ 3990 DWORD WINAPI SHWinHelpOnDemandA(HWND hwnd, LPCSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2) 3991 { 3992 3993 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_a(helpfile), flags1, ptr1, flags2); 3994 return 0; 3995 } 3996 3997 /************************************************************************* 3998 * @ [SHLWAPI.418] 3999 * 4000 * Function seems to do FreeLibrary plus other things. 4001 * 4002 * FIXME native shows the following calls: 4003 * RtlEnterCriticalSection 4004 * LocalFree 4005 * GetProcAddress(Comctl32??, 150L) 4006 * DPA_DeletePtr 4007 * RtlLeaveCriticalSection 4008 * followed by the FreeLibrary. 4009 * The above code may be related to .377 above. 4010 */ 4011 BOOL WINAPI MLFreeLibrary(HMODULE hModule) 4012 { 4013 FIXME("(%p) semi-stub\n", hModule); 4014 return FreeLibrary(hModule); 4015 } 4016 4017 /************************************************************************* 4018 * @ [SHLWAPI.419] 4019 */ 4020 BOOL WINAPI SHFlushSFCacheWrap(void) { 4021 FIXME(": stub\n"); 4022 return TRUE; 4023 } 4024 4025 /************************************************************************* 4026 * @ [SHLWAPI.429] 4027 * FIXME I have no idea what this function does or what its arguments are. 4028 */ 4029 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst) 4030 { 4031 FIXME("(%p) stub\n", hInst); 4032 return FALSE; 4033 } 4034 4035 4036 /************************************************************************* 4037 * @ [SHLWAPI.430] 4038 */ 4039 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap) 4040 { 4041 FIXME("(%p,%p) stub\n", hInst, hHeap); 4042 return E_FAIL; /* This is what is used if shlwapi not loaded */ 4043 } 4044 4045 /************************************************************************* 4046 * @ [SHLWAPI.431] 4047 */ 4048 DWORD WINAPI MLClearMLHInstance(DWORD x) 4049 { 4050 FIXME("(0x%08x)stub\n", x); 4051 return 0xabba1247; 4052 } 4053 4054 /************************************************************************* 4055 * @ [SHLWAPI.432] 4056 * 4057 * See SHSendMessageBroadcastW 4058 * 4059 */ 4060 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam) 4061 { 4062 return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam, 4063 SMTO_ABORTIFHUNG, 2000, NULL); 4064 } 4065 4066 /************************************************************************* 4067 * @ [SHLWAPI.433] 4068 * 4069 * A wrapper for sending Broadcast Messages to all top level Windows 4070 * 4071 */ 4072 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam) 4073 { 4074 return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam, 4075 SMTO_ABORTIFHUNG, 2000, NULL); 4076 } 4077 4078 /************************************************************************* 4079 * @ [SHLWAPI.436] 4080 * 4081 * Convert a Unicode string CLSID into a CLSID. 4082 * 4083 * PARAMS 4084 * idstr [I] string containing a CLSID in text form 4085 * id [O] CLSID extracted from the string 4086 * 4087 * RETURNS 4088 * S_OK on success or E_INVALIDARG on failure 4089 */ 4090 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id) 4091 { 4092 return CLSIDFromString((LPCOLESTR)idstr, id); 4093 } 4094 4095 /************************************************************************* 4096 * @ [SHLWAPI.437] 4097 * 4098 * Determine if the OS supports a given feature. 4099 * 4100 * PARAMS 4101 * dwFeature [I] Feature requested (undocumented) 4102 * 4103 * RETURNS 4104 * TRUE If the feature is available. 4105 * FALSE If the feature is not available. 4106 */ 4107 BOOL WINAPI IsOS(DWORD feature) 4108 { 4109 OSVERSIONINFOA osvi; 4110 DWORD platform, majorv, minorv; 4111 4112 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); 4113 if(!GetVersionExA(&osvi)) { 4114 ERR("GetVersionEx failed\n"); 4115 return FALSE; 4116 } 4117 4118 majorv = osvi.dwMajorVersion; 4119 minorv = osvi.dwMinorVersion; 4120 platform = osvi.dwPlatformId; 4121 4122 #define ISOS_RETURN(x) \ 4123 TRACE("(0x%x) ret=%d\n",feature,(x)); \ 4124 return (x); 4125 4126 switch(feature) { 4127 case OS_WIN32SORGREATER: 4128 ISOS_RETURN(platform == VER_PLATFORM_WIN32s 4129 || platform == VER_PLATFORM_WIN32_WINDOWS) 4130 case OS_NT: 4131 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4132 case OS_WIN95ORGREATER: 4133 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS) 4134 case OS_NT4ORGREATER: 4135 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4) 4136 case OS_WIN2000ORGREATER_ALT: 4137 case OS_WIN2000ORGREATER: 4138 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5) 4139 case OS_WIN98ORGREATER: 4140 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10) 4141 case OS_WIN98_GOLD: 4142 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10) 4143 case OS_WIN2000PRO: 4144 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5) 4145 case OS_WIN2000SERVER: 4146 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1)) 4147 case OS_WIN2000ADVSERVER: 4148 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1)) 4149 case OS_WIN2000DATACENTER: 4150 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1)) 4151 case OS_WIN2000TERMINAL: 4152 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1)) 4153 case OS_EMBEDDED: 4154 FIXME("(OS_EMBEDDED) What should we return here?\n"); 4155 return FALSE; 4156 case OS_TERMINALCLIENT: 4157 FIXME("(OS_TERMINALCLIENT) What should we return here?\n"); 4158 return FALSE; 4159 case OS_TERMINALREMOTEADMIN: 4160 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n"); 4161 return FALSE; 4162 case OS_WIN95_GOLD: 4163 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0) 4164 case OS_MEORGREATER: 4165 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90) 4166 case OS_XPORGREATER: 4167 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1) 4168 case OS_HOME: 4169 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1) 4170 case OS_PROFESSIONAL: 4171 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4172 case OS_DATACENTER: 4173 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4174 case OS_ADVSERVER: 4175 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5) 4176 case OS_SERVER: 4177 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4178 case OS_TERMINALSERVER: 4179 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4180 case OS_PERSONALTERMINALSERVER: 4181 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5) 4182 case OS_FASTUSERSWITCHING: 4183 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n"); 4184 return TRUE; 4185 case OS_WELCOMELOGONUI: 4186 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n"); 4187 return FALSE; 4188 case OS_DOMAINMEMBER: 4189 FIXME("(OS_DOMAINMEMBER) What should we return here?\n"); 4190 return TRUE; 4191 case OS_ANYSERVER: 4192 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4193 case OS_WOW6432: 4194 { 4195 BOOL is_wow64; 4196 IsWow64Process(GetCurrentProcess(), &is_wow64); 4197 return is_wow64; 4198 } 4199 case OS_WEBSERVER: 4200 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4201 case OS_SMALLBUSINESSSERVER: 4202 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4203 case OS_TABLETPC: 4204 FIXME("(OS_TABLETPC) What should we return here?\n"); 4205 return FALSE; 4206 case OS_SERVERADMINUI: 4207 FIXME("(OS_SERVERADMINUI) What should we return here?\n"); 4208 return FALSE; 4209 case OS_MEDIACENTER: 4210 FIXME("(OS_MEDIACENTER) What should we return here?\n"); 4211 return FALSE; 4212 case OS_APPLIANCE: 4213 FIXME("(OS_APPLIANCE) What should we return here?\n"); 4214 return FALSE; 4215 case 0x25: /*OS_VISTAORGREATER*/ 4216 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6) 4217 } 4218 4219 #undef ISOS_RETURN 4220 4221 WARN("(0x%x) unknown parameter\n",feature); 4222 4223 return FALSE; 4224 } 4225 4226 #ifdef __REACTOS__ 4227 /************************************************************************* 4228 * @ [SHLWAPI.438] 4229 */ 4230 HRESULT WINAPI SHLoadRegUIStringA(HKEY hkey, LPCSTR value, LPSTR buf, DWORD size) 4231 { 4232 WCHAR valueW[MAX_PATH], bufferW[MAX_PATH]; 4233 DWORD dwSize = ARRAY_SIZE(bufferW) * sizeof(CHAR); 4234 HRESULT hr; 4235 4236 MultiByteToWideChar(CP_ACP, 0, value, -1, valueW, ARRAY_SIZE(valueW)); 4237 valueW[ARRAY_SIZE(valueW) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ 4238 4239 if (RegQueryValueExW(hkey, valueW, NULL, NULL, (LPBYTE)bufferW, &dwSize) != ERROR_SUCCESS) 4240 return E_FAIL; 4241 4242 hr = SHLoadIndirectString(bufferW, bufferW, ARRAY_SIZE(bufferW), NULL); 4243 if (FAILED(hr)) 4244 return hr; 4245 4246 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buf, size, NULL, NULL); 4247 if (size > 0) 4248 buf[size - 1] = ANSI_NULL; /* Avoid buffer overrun */ 4249 return S_OK; 4250 } 4251 #endif 4252 4253 /************************************************************************* 4254 * @ [SHLWAPI.439] 4255 */ 4256 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size) 4257 { 4258 DWORD type, sz = size * sizeof(WCHAR); 4259 4260 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS) 4261 return E_FAIL; 4262 4263 return SHLoadIndirectString(buf, buf, size, NULL); 4264 } 4265 4266 /************************************************************************* 4267 * @ [SHLWAPI.478] 4268 * 4269 * Call IInputObject_TranslateAcceleratorIO() on an object. 4270 * 4271 * PARAMS 4272 * lpUnknown [I] Object supporting the IInputObject interface. 4273 * lpMsg [I] Key message to be processed. 4274 * 4275 * RETURNS 4276 * Success: S_OK. 4277 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL. 4278 */ 4279 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg) 4280 { 4281 IInputObject* lpInput = NULL; 4282 HRESULT hRet = E_INVALIDARG; 4283 4284 TRACE("(%p,%p)\n", lpUnknown, lpMsg); 4285 if (lpUnknown) 4286 { 4287 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject, 4288 (void**)&lpInput); 4289 if (SUCCEEDED(hRet) && lpInput) 4290 { 4291 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg); 4292 IInputObject_Release(lpInput); 4293 } 4294 } 4295 return hRet; 4296 } 4297 4298 /************************************************************************* 4299 * @ [SHLWAPI.481] 4300 * 4301 * Call IInputObject_HasFocusIO() on an object. 4302 * 4303 * PARAMS 4304 * lpUnknown [I] Object supporting the IInputObject interface. 4305 * 4306 * RETURNS 4307 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus, 4308 * or S_FALSE otherwise. 4309 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL. 4310 */ 4311 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown) 4312 { 4313 IInputObject* lpInput = NULL; 4314 HRESULT hRet = E_INVALIDARG; 4315 4316 TRACE("(%p)\n", lpUnknown); 4317 if (lpUnknown) 4318 { 4319 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject, 4320 (void**)&lpInput); 4321 if (SUCCEEDED(hRet) && lpInput) 4322 { 4323 hRet = IInputObject_HasFocusIO(lpInput); 4324 IInputObject_Release(lpInput); 4325 } 4326 } 4327 return hRet; 4328 } 4329 4330 /************************************************************************* 4331 * ColorRGBToHLS [SHLWAPI.@] 4332 * 4333 * Convert an rgb COLORREF into the hls color space. 4334 * 4335 * PARAMS 4336 * cRGB [I] Source rgb value 4337 * pwHue [O] Destination for converted hue 4338 * pwLuminance [O] Destination for converted luminance 4339 * pwSaturation [O] Destination for converted saturation 4340 * 4341 * RETURNS 4342 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted 4343 * values. 4344 * 4345 * NOTES 4346 * Output HLS values are constrained to the range (0..240). 4347 * For Achromatic conversions, Hue is set to 160. 4348 */ 4349 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue, 4350 LPWORD pwLuminance, LPWORD pwSaturation) 4351 { 4352 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation; 4353 4354 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation); 4355 4356 wR = GetRValue(cRGB); 4357 wG = GetGValue(cRGB); 4358 wB = GetBValue(cRGB); 4359 4360 wMax = max(wR, max(wG, wB)); 4361 wMin = min(wR, min(wG, wB)); 4362 4363 /* Luminosity */ 4364 wLuminosity = ((wMax + wMin) * 240 + 255) / 510; 4365 4366 if (wMax == wMin) 4367 { 4368 /* Achromatic case */ 4369 wSaturation = 0; 4370 /* Hue is now unrepresentable, but this is what native returns... */ 4371 wHue = 160; 4372 } 4373 else 4374 { 4375 /* Chromatic case */ 4376 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm; 4377 4378 /* Saturation */ 4379 if (wLuminosity <= 120) 4380 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin); 4381 else 4382 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin); 4383 4384 /* Hue */ 4385 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta; 4386 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta; 4387 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta; 4388 4389 if (wR == wMax) 4390 wHue = wBNorm - wGNorm; 4391 else if (wG == wMax) 4392 wHue = 80 + wRNorm - wBNorm; 4393 else 4394 wHue = 160 + wGNorm - wRNorm; 4395 if (wHue < 0) 4396 wHue += 240; 4397 else if (wHue > 240) 4398 wHue -= 240; 4399 } 4400 if (pwHue) 4401 *pwHue = wHue; 4402 if (pwLuminance) 4403 *pwLuminance = wLuminosity; 4404 if (pwSaturation) 4405 *pwSaturation = wSaturation; 4406 } 4407 4408 /************************************************************************* 4409 * SHCreateShellPalette [SHLWAPI.@] 4410 */ 4411 HPALETTE WINAPI SHCreateShellPalette(HDC hdc) 4412 { 4413 FIXME("stub\n"); 4414 return CreateHalftonePalette(hdc); 4415 } 4416 4417 /************************************************************************* 4418 * SHGetInverseCMAP (SHLWAPI.@) 4419 * 4420 * Get an inverse color map table. 4421 * 4422 * PARAMS 4423 * lpCmap [O] Destination for color map 4424 * dwSize [I] Size of memory pointed to by lpCmap 4425 * 4426 * RETURNS 4427 * Success: S_OK. 4428 * Failure: E_POINTER, If lpCmap is invalid. 4429 * E_INVALIDARG, If dwFlags is invalid 4430 * E_OUTOFMEMORY, If there is no memory available 4431 * 4432 * NOTES 4433 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192). 4434 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's 4435 * internal CMap. 4436 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from 4437 * this DLL's internal CMap. 4438 */ 4439 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize) 4440 { 4441 if (dwSize == 4) { 4442 FIXME(" - returning bogus address for SHGetInverseCMAP\n"); 4443 *dest = (DWORD)0xabba1249; 4444 return 0; 4445 } 4446 FIXME("(%p, %#x) stub\n", dest, dwSize); 4447 return 0; 4448 } 4449 4450 /************************************************************************* 4451 * SHIsLowMemoryMachine [SHLWAPI.@] 4452 * 4453 * Determine if the current computer has low memory. 4454 * 4455 * PARAMS 4456 * dwType [I] Zero. 4457 * 4458 * RETURNS 4459 * TRUE if the users machine has 16 Megabytes of memory or less, 4460 * FALSE otherwise. 4461 */ 4462 BOOL WINAPI SHIsLowMemoryMachine(DWORD dwType) 4463 { 4464 #ifdef __REACTOS__ 4465 MEMORYSTATUS status; 4466 static int is_low = -1; 4467 TRACE("(0x%08x)\n", dwType); 4468 if (dwType == 0 && is_low == -1) 4469 { 4470 GlobalMemoryStatus(&status); 4471 is_low = (status.dwTotalPhys <= 0x1000000); 4472 } 4473 return is_low; 4474 #else 4475 FIXME("(0x%08x) stub\n", dwType); 4476 return FALSE; 4477 #endif 4478 } 4479 4480 /************************************************************************* 4481 * GetMenuPosFromID [SHLWAPI.@] 4482 * 4483 * Return the position of a menu item from its Id. 4484 * 4485 * PARAMS 4486 * hMenu [I] Menu containing the item 4487 * wID [I] Id of the menu item 4488 * 4489 * RETURNS 4490 * Success: The index of the menu item in hMenu. 4491 * Failure: -1, If the item is not found. 4492 */ 4493 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID) 4494 { 4495 MENUITEMINFOW mi; 4496 INT nCount = GetMenuItemCount(hMenu), nIter = 0; 4497 4498 TRACE("%p %u\n", hMenu, wID); 4499 4500 while (nIter < nCount) 4501 { 4502 mi.cbSize = sizeof(mi); 4503 mi.fMask = MIIM_ID; 4504 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID) 4505 { 4506 TRACE("ret %d\n", nIter); 4507 return nIter; 4508 } 4509 nIter++; 4510 } 4511 4512 return -1; 4513 } 4514 4515 /************************************************************************* 4516 * @ [SHLWAPI.179] 4517 * 4518 * Same as SHLWAPI.GetMenuPosFromID 4519 */ 4520 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID) 4521 { 4522 TRACE("%p %u\n", hMenu, uID); 4523 return GetMenuPosFromID(hMenu, uID); 4524 } 4525 4526 4527 /************************************************************************* 4528 * @ [SHLWAPI.448] 4529 */ 4530 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr) 4531 { 4532 while (*lpwstr) 4533 { 4534 if (*lpwstr == '/') 4535 *lpwstr = '\\'; 4536 lpwstr++; 4537 } 4538 } 4539 4540 4541 /************************************************************************* 4542 * @ [SHLWAPI.461] 4543 */ 4544 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown) 4545 { 4546 FIXME("(0x%08x) stub\n", dwUnknown); 4547 return 0; 4548 } 4549 4550 4551 /************************************************************************* 4552 * @ [SHLWAPI.549] 4553 */ 4554 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter, 4555 DWORD dwClsContext, REFIID iid, LPVOID *ppv) 4556 { 4557 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv); 4558 } 4559 4560 /************************************************************************* 4561 * SHSkipJunction [SHLWAPI.@] 4562 * 4563 * Determine if a bind context can be bound to an object 4564 * 4565 * PARAMS 4566 * pbc [I] Bind context to check 4567 * pclsid [I] CLSID of object to be bound to 4568 * 4569 * RETURNS 4570 * TRUE: If it is safe to bind 4571 * FALSE: If pbc is invalid or binding would not be safe 4572 * 4573 */ 4574 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid) 4575 { 4576 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ', 4577 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' }; 4578 BOOL bRet = FALSE; 4579 4580 if (pbc) 4581 { 4582 IUnknown* lpUnk; 4583 4584 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk))) 4585 { 4586 CLSID clsid; 4587 4588 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) && 4589 IsEqualGUID(pclsid, &clsid)) 4590 bRet = TRUE; 4591 4592 IUnknown_Release(lpUnk); 4593 } 4594 } 4595 return bRet; 4596 } 4597 4598 /*********************************************************************** 4599 * SHGetShellKey (SHLWAPI.491) 4600 */ 4601 HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create) 4602 { 4603 #ifndef __REACTOS__ 4604 enum _shellkey_flags { 4605 SHKEY_Root_HKCU = 0x1, 4606 SHKEY_Root_HKLM = 0x2, 4607 SHKEY_Key_Explorer = 0x00, 4608 SHKEY_Key_Shell = 0x10, 4609 SHKEY_Key_ShellNoRoam = 0x20, 4610 SHKEY_Key_Classes = 0x30, 4611 SHKEY_Subkey_Default = 0x0000, 4612 SHKEY_Subkey_ResourceName = 0x1000, 4613 SHKEY_Subkey_Handlers = 0x2000, 4614 SHKEY_Subkey_Associations = 0x3000, 4615 SHKEY_Subkey_Volatile = 0x4000, 4616 SHKEY_Subkey_MUICache = 0x5000, 4617 SHKEY_Subkey_FileExts = 0x6000 4618 }; 4619 #endif 4620 4621 static const WCHAR explorerW[] = {'S','o','f','t','w','a','r','e','\\', 4622 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', 4623 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 4624 'E','x','p','l','o','r','e','r','\\'}; 4625 static const WCHAR shellW[] = {'S','o','f','t','w','a','r','e','\\', 4626 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', 4627 'S','h','e','l','l','\\'}; 4628 static const WCHAR shell_no_roamW[] = {'S','o','f','t','w','a','r','e','\\', 4629 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', 4630 'S','h','e','l','l','N','o','R','o','a','m','\\'}; 4631 static const WCHAR classesW[] = {'S','o','f','t','w','a','r','e','\\', 4632 'C','l','a','s','s','e','s','\\'}; 4633 4634 static const WCHAR localized_resource_nameW[] = {'L','o','c','a','l','i','z','e','d', 4635 'R','e','s','o','u','r','c','e','N','a','m','e','\\'}; 4636 static const WCHAR handlersW[] = {'H','a','n','d','l','e','r','s','\\'}; 4637 static const WCHAR associationsW[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'}; 4638 static const WCHAR volatileW[] = {'V','o','l','a','t','i','l','e','\\'}; 4639 static const WCHAR mui_cacheW[] = {'M','U','I','C','a','c','h','e','\\'}; 4640 static const WCHAR file_extsW[] = {'F','i','l','e','E','x','t','s','\\'}; 4641 4642 WCHAR *path; 4643 const WCHAR *key, *subkey; 4644 int size_key, size_subkey, size_user; 4645 HKEY hkey = NULL; 4646 4647 TRACE("(0x%08x, %s, %d)\n", flags, debugstr_w(sub_key), create); 4648 4649 /* For compatibility with Vista+ */ 4650 if(flags == 0x1ffff) 4651 flags = 0x21; 4652 4653 switch(flags&0xff0) { 4654 case SHKEY_Key_Explorer: 4655 key = explorerW; 4656 size_key = sizeof(explorerW); 4657 break; 4658 case SHKEY_Key_Shell: 4659 key = shellW; 4660 size_key = sizeof(shellW); 4661 break; 4662 case SHKEY_Key_ShellNoRoam: 4663 key = shell_no_roamW; 4664 size_key = sizeof(shell_no_roamW); 4665 break; 4666 case SHKEY_Key_Classes: 4667 key = classesW; 4668 size_key = sizeof(classesW); 4669 break; 4670 default: 4671 FIXME("unsupported flags (0x%08x)\n", flags); 4672 return NULL; 4673 } 4674 4675 switch(flags&0xff000) { 4676 case SHKEY_Subkey_Default: 4677 subkey = NULL; 4678 size_subkey = 0; 4679 break; 4680 case SHKEY_Subkey_ResourceName: 4681 subkey = localized_resource_nameW; 4682 size_subkey = sizeof(localized_resource_nameW); 4683 break; 4684 case SHKEY_Subkey_Handlers: 4685 subkey = handlersW; 4686 size_subkey = sizeof(handlersW); 4687 break; 4688 case SHKEY_Subkey_Associations: 4689 subkey = associationsW; 4690 size_subkey = sizeof(associationsW); 4691 break; 4692 case SHKEY_Subkey_Volatile: 4693 subkey = volatileW; 4694 size_subkey = sizeof(volatileW); 4695 break; 4696 case SHKEY_Subkey_MUICache: 4697 subkey = mui_cacheW; 4698 size_subkey = sizeof(mui_cacheW); 4699 break; 4700 case SHKEY_Subkey_FileExts: 4701 subkey = file_extsW; 4702 size_subkey = sizeof(file_extsW); 4703 break; 4704 default: 4705 FIXME("unsupported flags (0x%08x)\n", flags); 4706 return NULL; 4707 } 4708 4709 if(sub_key) 4710 size_user = lstrlenW(sub_key)*sizeof(WCHAR); 4711 else 4712 size_user = 0; 4713 4714 path = HeapAlloc(GetProcessHeap(), 0, size_key+size_subkey+size_user+sizeof(WCHAR)); 4715 if(!path) { 4716 ERR("Out of memory\n"); 4717 return NULL; 4718 } 4719 4720 memcpy(path, key, size_key); 4721 if(subkey) 4722 memcpy(path+size_key/sizeof(WCHAR), subkey, size_subkey); 4723 if(sub_key) 4724 memcpy(path+(size_key+size_subkey)/sizeof(WCHAR), sub_key, size_user); 4725 path[(size_key+size_subkey+size_user)/sizeof(WCHAR)] = '\0'; 4726 4727 if(create) 4728 RegCreateKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, 4729 path, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &hkey, NULL); 4730 else 4731 RegOpenKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, 4732 path, 0, MAXIMUM_ALLOWED, &hkey); 4733 4734 HeapFree(GetProcessHeap(), 0, path); 4735 return hkey; 4736 } 4737 4738 /*********************************************************************** 4739 * SHQueueUserWorkItem (SHLWAPI.@) 4740 */ 4741 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback, 4742 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag, 4743 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags) 4744 { 4745 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext, 4746 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags); 4747 4748 if(lPriority || dwTag || pdwId || pszModule || dwFlags) 4749 FIXME("Unsupported arguments\n"); 4750 4751 return QueueUserWorkItem(pfnCallback, pContext, 0); 4752 } 4753 4754 /*********************************************************************** 4755 * SHSetTimerQueueTimer (SHLWAPI.263) 4756 */ 4757 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue, 4758 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime, 4759 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags) 4760 { 4761 HANDLE hNewTimer; 4762 4763 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */ 4764 if (dwFlags & TPS_LONGEXECTIME) { 4765 dwFlags &= ~TPS_LONGEXECTIME; 4766 dwFlags |= WT_EXECUTELONGFUNCTION; 4767 } 4768 if (dwFlags & TPS_EXECUTEIO) { 4769 dwFlags &= ~TPS_EXECUTEIO; 4770 dwFlags |= WT_EXECUTEINIOTHREAD; 4771 } 4772 4773 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext, 4774 dwDueTime, dwPeriod, dwFlags)) 4775 return NULL; 4776 4777 return hNewTimer; 4778 } 4779 4780 /*********************************************************************** 4781 * IUnknown_OnFocusChangeIS (SHLWAPI.@) 4782 */ 4783 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus) 4784 { 4785 IInputObjectSite *pIOS = NULL; 4786 HRESULT hRet = E_INVALIDARG; 4787 4788 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE"); 4789 4790 if (lpUnknown) 4791 { 4792 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite, 4793 (void **)&pIOS); 4794 if (SUCCEEDED(hRet) && pIOS) 4795 { 4796 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus); 4797 IInputObjectSite_Release(pIOS); 4798 } 4799 } 4800 return hRet; 4801 } 4802 4803 /*********************************************************************** 4804 * SKAllocValueW (SHLWAPI.519) 4805 */ 4806 HRESULT WINAPI SKAllocValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type, 4807 LPVOID *data, DWORD *count) 4808 { 4809 DWORD ret, size; 4810 HKEY hkey; 4811 4812 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey), 4813 debugstr_w(value), type, data, count); 4814 4815 hkey = SHGetShellKey(flags, subkey, FALSE); 4816 if (!hkey) 4817 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 4818 4819 ret = SHQueryValueExW(hkey, value, NULL, type, NULL, &size); 4820 if (ret) { 4821 RegCloseKey(hkey); 4822 return HRESULT_FROM_WIN32(ret); 4823 } 4824 4825 size += 2; 4826 *data = LocalAlloc(0, size); 4827 if (!*data) { 4828 RegCloseKey(hkey); 4829 return E_OUTOFMEMORY; 4830 } 4831 4832 ret = SHQueryValueExW(hkey, value, NULL, type, *data, &size); 4833 if (count) 4834 *count = size; 4835 4836 RegCloseKey(hkey); 4837 return HRESULT_FROM_WIN32(ret); 4838 } 4839 4840 /*********************************************************************** 4841 * SKDeleteValueW (SHLWAPI.518) 4842 */ 4843 HRESULT WINAPI SKDeleteValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value) 4844 { 4845 DWORD ret; 4846 HKEY hkey; 4847 4848 TRACE("(0x%x, %s %s)\n", flags, debugstr_w(subkey), debugstr_w(value)); 4849 4850 hkey = SHGetShellKey(flags, subkey, FALSE); 4851 if (!hkey) 4852 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 4853 4854 ret = RegDeleteValueW(hkey, value); 4855 4856 RegCloseKey(hkey); 4857 return HRESULT_FROM_WIN32(ret); 4858 } 4859 4860 /*********************************************************************** 4861 * SKGetValueW (SHLWAPI.516) 4862 */ 4863 HRESULT WINAPI SKGetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type, 4864 void *data, DWORD *count) 4865 { 4866 DWORD ret; 4867 HKEY hkey; 4868 4869 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey), 4870 debugstr_w(value), type, data, count); 4871 4872 hkey = SHGetShellKey(flags, subkey, FALSE); 4873 if (!hkey) 4874 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 4875 4876 ret = SHQueryValueExW(hkey, value, NULL, type, data, count); 4877 4878 RegCloseKey(hkey); 4879 return HRESULT_FROM_WIN32(ret); 4880 } 4881 4882 /*********************************************************************** 4883 * SKSetValueW (SHLWAPI.516) 4884 */ 4885 HRESULT WINAPI SKSetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, 4886 DWORD type, void *data, DWORD count) 4887 { 4888 DWORD ret; 4889 HKEY hkey; 4890 4891 TRACE("(0x%x, %s, %s, %x, %p, %d)\n", flags, debugstr_w(subkey), 4892 debugstr_w(value), type, data, count); 4893 4894 hkey = SHGetShellKey(flags, subkey, TRUE); 4895 if (!hkey) 4896 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 4897 4898 ret = RegSetValueExW(hkey, value, 0, type, data, count); 4899 4900 RegCloseKey(hkey); 4901 return HRESULT_FROM_WIN32(ret); 4902 } 4903 4904 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *); 4905 4906 /*********************************************************************** 4907 * GetUIVersion (SHLWAPI.452) 4908 */ 4909 DWORD WINAPI GetUIVersion(void) 4910 { 4911 static DWORD version; 4912 4913 if (!version) 4914 { 4915 DllGetVersion_func pDllGetVersion; 4916 HMODULE dll = LoadLibraryA("shell32.dll"); 4917 if (!dll) return 0; 4918 4919 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion"); 4920 if (pDllGetVersion) 4921 { 4922 DLLVERSIONINFO dvi; 4923 dvi.cbSize = sizeof(DLLVERSIONINFO); 4924 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion; 4925 } 4926 FreeLibrary( dll ); 4927 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */ 4928 } 4929 return version; 4930 } 4931 4932 /*********************************************************************** 4933 * ShellMessageBoxWrapW [SHLWAPI.388] 4934 * 4935 * See shell32.ShellMessageBoxW 4936 * 4937 #ifndef __REACTOS__ 4938 * 4939 * NOTE: 4940 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW 4941 * because we can't forward to it in the .spec file since it's exported by 4942 * ordinal. If you change the implementation here please update the code in 4943 * shell32 as well. 4944 * 4945 #else // __REACTOS__ 4946 * 4947 * From Vista+ onwards, all the implementation of ShellMessageBoxA/W that 4948 * were existing in shell32 has been completely moved to shlwapi, so that 4949 * shell32.ShellMessageBoxA and shell32.ShellMessageBoxW are redirections 4950 * to the corresponding shlwapi functions. 4951 * 4952 * For Win2003 compatibility, if you change the implementation here please 4953 * update the code of ShellMessageBoxA in shell32 as well. 4954 * 4955 #endif 4956 */ 4957 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText, 4958 LPCWSTR lpCaption, UINT uType, ...) 4959 { 4960 WCHAR *szText = NULL, szTitle[100]; 4961 LPCWSTR pszText, pszTitle = szTitle; 4962 LPWSTR pszTemp; 4963 __ms_va_list args; 4964 int ret; 4965 4966 __ms_va_start(args, uType); 4967 4968 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType); 4969 4970 if (IS_INTRESOURCE(lpCaption)) 4971 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, ARRAY_SIZE(szTitle)); 4972 else 4973 pszTitle = lpCaption; 4974 4975 if (IS_INTRESOURCE(lpText)) 4976 { 4977 const WCHAR *ptr; 4978 UINT len = LoadStringW(hInstance, LOWORD(lpText), (LPWSTR)&ptr, 0); 4979 4980 if (len) 4981 { 4982 szText = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); 4983 if (szText) LoadStringW(hInstance, LOWORD(lpText), szText, len + 1); 4984 } 4985 pszText = szText; 4986 if (!pszText) { 4987 WARN("Failed to load id %d\n", LOWORD(lpText)); 4988 __ms_va_end(args); 4989 return 0; 4990 } 4991 } 4992 else 4993 pszText = lpText; 4994 4995 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, 4996 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args); 4997 4998 __ms_va_end(args); 4999 5000 #ifdef __REACTOS__ 5001 uType |= MB_SETFOREGROUND; 5002 #endif 5003 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType); 5004 5005 HeapFree(GetProcessHeap(), 0, szText); 5006 LocalFree(pszTemp); 5007 return ret; 5008 } 5009 5010 /*********************************************************************** 5011 * ZoneComputePaneSize [SHLWAPI.382] 5012 */ 5013 UINT WINAPI ZoneComputePaneSize(HWND hwnd) 5014 { 5015 FIXME("\n"); 5016 return 0x95; 5017 } 5018 5019 /*********************************************************************** 5020 * SHChangeNotifyWrap [SHLWAPI.394] 5021 */ 5022 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2) 5023 { 5024 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2); 5025 } 5026 5027 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */ 5028 SID_IDENTIFIER_AUTHORITY sidAuthority; 5029 DWORD dwUserGroupID; 5030 DWORD dwUserID; 5031 } SHELL_USER_SID, *PSHELL_USER_SID; 5032 5033 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */ 5034 SHELL_USER_SID susID; 5035 DWORD dwAccessType; 5036 BOOL fInherit; 5037 DWORD dwAccessMask; 5038 DWORD dwInheritMask; 5039 DWORD dwInheritAccessMask; 5040 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION; 5041 5042 /*********************************************************************** 5043 * GetShellSecurityDescriptor [SHLWAPI.475] 5044 * 5045 * prepares SECURITY_DESCRIPTOR from a set of ACEs 5046 * 5047 * PARAMS 5048 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures, 5049 * each of which describes permissions to apply 5050 * cUserPerm [I] number of entries in apUserPerm array 5051 * 5052 * RETURNS 5053 * success: pointer to SECURITY_DESCRIPTOR 5054 * failure: NULL 5055 * 5056 * NOTES 5057 * Call should free returned descriptor with LocalFree 5058 */ 5059 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(const PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm) 5060 { 5061 PSID *sidlist; 5062 PSID cur_user = NULL; 5063 BYTE tuUser[2000]; 5064 DWORD acl_size; 5065 int sid_count, i; 5066 PSECURITY_DESCRIPTOR psd = NULL; 5067 5068 TRACE("%p %d\n", apUserPerm, cUserPerm); 5069 5070 if (apUserPerm == NULL || cUserPerm <= 0) 5071 return NULL; 5072 5073 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID)); 5074 if (!sidlist) 5075 return NULL; 5076 5077 acl_size = sizeof(ACL); 5078 5079 for(sid_count = 0; sid_count < cUserPerm; sid_count++) 5080 { 5081 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0}; 5082 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count]; 5083 PSHELL_USER_SID sid = &perm->susID; 5084 PSID pSid; 5085 BOOL ret = TRUE; 5086 5087 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID))) 5088 { /* current user's SID */ 5089 if (!cur_user) 5090 { 5091 HANDLE Token; 5092 DWORD bufsize = sizeof(tuUser); 5093 5094 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token); 5095 if (ret) 5096 { 5097 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize ); 5098 if (ret) 5099 cur_user = ((PTOKEN_USER)tuUser)->User.Sid; 5100 CloseHandle(Token); 5101 } 5102 } 5103 pSid = cur_user; 5104 } else if (sid->dwUserID==0) /* one sub-authority */ 5105 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0, 5106 0, 0, 0, 0, 0, 0, &pSid); 5107 else 5108 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID, 5109 0, 0, 0, 0, 0, 0, &pSid); 5110 if (!ret) 5111 goto free_sids; 5112 5113 sidlist[sid_count] = pSid; 5114 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */ 5115 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1); 5116 } 5117 5118 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size); 5119 5120 if (psd != NULL) 5121 { 5122 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR)); 5123 5124 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)) 5125 goto error; 5126 5127 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION)) 5128 goto error; 5129 5130 for(i = 0; i < sid_count; i++) 5131 { 5132 PSHELL_USER_PERMISSION sup = apUserPerm[i]; 5133 PSID sid = sidlist[i]; 5134 5135 switch(sup->dwAccessType) 5136 { 5137 case ACCESS_ALLOWED_ACE_TYPE: 5138 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid)) 5139 goto error; 5140 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION, 5141 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid)) 5142 goto error; 5143 break; 5144 case ACCESS_DENIED_ACE_TYPE: 5145 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid)) 5146 goto error; 5147 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION, 5148 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid)) 5149 goto error; 5150 break; 5151 default: 5152 goto error; 5153 } 5154 } 5155 5156 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE)) 5157 goto error; 5158 } 5159 goto free_sids; 5160 5161 error: 5162 LocalFree(psd); 5163 psd = NULL; 5164 free_sids: 5165 for(i = 0; i < sid_count; i++) 5166 { 5167 if (!cur_user || sidlist[i] != cur_user) 5168 FreeSid(sidlist[i]); 5169 } 5170 HeapFree(GetProcessHeap(), 0, sidlist); 5171 5172 return psd; 5173 } 5174 5175 #ifndef __REACTOS__ /* See propbag.cpp */ 5176 /*********************************************************************** 5177 * SHCreatePropertyBagOnRegKey [SHLWAPI.471] 5178 * 5179 * Creates a property bag from a registry key 5180 * 5181 * PARAMS 5182 * hKey [I] Handle to the desired registry key 5183 * subkey [I] Name of desired subkey, or NULL to open hKey directly 5184 * grfMode [I] Optional flags 5185 * riid [I] IID of requested property bag interface 5186 * ppv [O] Address to receive pointer to the new interface 5187 * 5188 * RETURNS 5189 * success: 0 5190 * failure: error code 5191 * 5192 */ 5193 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey, 5194 DWORD grfMode, REFIID riid, void **ppv) 5195 { 5196 FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode, 5197 debugstr_guid(riid), ppv); 5198 5199 return E_NOTIMPL; 5200 } 5201 #endif 5202 5203 #ifndef __REACTOS__ /* See propbag.cpp */ 5204 /*********************************************************************** 5205 * SHGetViewStatePropertyBag [SHLWAPI.515] 5206 * 5207 * Retrieves a property bag in which the view state information of a folder 5208 * can be stored. 5209 * 5210 * PARAMS 5211 * pidl [I] PIDL of the folder requested 5212 * bag_name [I] Name of the property bag requested 5213 * flags [I] Optional flags 5214 * riid [I] IID of requested property bag interface 5215 * ppv [O] Address to receive pointer to the new interface 5216 * 5217 * RETURNS 5218 * success: S_OK 5219 * failure: error code 5220 * 5221 */ 5222 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name, 5223 DWORD flags, REFIID riid, void **ppv) 5224 { 5225 FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags, 5226 debugstr_guid(riid), ppv); 5227 5228 return E_NOTIMPL; 5229 } 5230 #endif 5231 5232 /*********************************************************************** 5233 * SHFormatDateTimeW [SHLWAPI.354] 5234 * 5235 * Produces a string representation of a time. 5236 * 5237 * PARAMS 5238 * fileTime [I] Pointer to FILETIME structure specifying the time 5239 * flags [I] Flags specifying the desired output 5240 * buf [O] Pointer to buffer for output 5241 * size [I] Number of characters that can be contained in buffer 5242 * 5243 * RETURNS 5244 * success: number of characters written to the buffer 5245 * failure: 0 5246 * 5247 */ 5248 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags, 5249 LPWSTR buf, UINT size) 5250 { 5251 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER) 5252 DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT; 5253 SYSTEMTIME st; 5254 FILETIME ft; 5255 INT ret = 0; 5256 5257 TRACE("%p %p %p %u\n", fileTime, flags, buf, size); 5258 5259 if (!buf || !size) 5260 return 0; 5261 5262 if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS) 5263 FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS); 5264 5265 FileTimeToLocalFileTime(fileTime, &ft); 5266 FileTimeToSystemTime(&ft, &st); 5267 5268 /* first of all date */ 5269 if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE)) 5270 { 5271 static const WCHAR sep1[] = {',',' ',0}; 5272 static const WCHAR sep2[] = {' ',0}; 5273 5274 DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE; 5275 ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size); 5276 if (ret >= size) return ret; 5277 5278 /* add separator */ 5279 if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))) 5280 { 5281 if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2)) 5282 { 5283 lstrcatW(&buf[ret-1], sep1); 5284 ret += 2; 5285 } 5286 else 5287 { 5288 lstrcatW(&buf[ret-1], sep2); 5289 ret++; 5290 } 5291 } 5292 } 5293 /* time part */ 5294 if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)) 5295 { 5296 DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS; 5297 5298 if (ret) ret--; 5299 ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret); 5300 } 5301 5302 return ret; 5303 5304 #undef SHFORMATDT_UNSUPPORTED_FLAGS 5305 } 5306 5307 /*********************************************************************** 5308 * SHFormatDateTimeA [SHLWAPI.353] 5309 * 5310 * See SHFormatDateTimeW. 5311 * 5312 */ 5313 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags, 5314 LPSTR buf, UINT size) 5315 { 5316 WCHAR *bufW; 5317 INT retval; 5318 5319 if (!buf || !size) 5320 return 0; 5321 5322 bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size); 5323 retval = SHFormatDateTimeW(fileTime, flags, bufW, size); 5324 5325 if (retval != 0) 5326 WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL); 5327 5328 HeapFree(GetProcessHeap(), 0, bufW); 5329 return retval; 5330 } 5331 5332 /*********************************************************************** 5333 * ZoneCheckUrlExW [SHLWAPI.231] 5334 * 5335 * Checks the details of the security zone for the supplied site. (?) 5336 * 5337 * PARAMS 5338 * 5339 * szURL [I] Pointer to the URL to check 5340 * 5341 * Other parameters currently unknown. 5342 * 5343 * RETURNS 5344 * unknown 5345 */ 5346 5347 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2, 5348 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6, 5349 DWORD dwUnknown7) 5350 { 5351 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2, 5352 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7); 5353 5354 return 0; 5355 } 5356 5357 /*********************************************************************** 5358 * SHVerbExistsNA [SHLWAPI.196] 5359 * 5360 * 5361 * PARAMS 5362 * 5363 * verb [I] a string, often appears to be an extension. 5364 * 5365 * Other parameters currently unknown. 5366 * 5367 * RETURNS 5368 * unknown 5369 */ 5370 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3) 5371 { 5372 FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3); 5373 return 0; 5374 } 5375 5376 /************************************************************************* 5377 * @ [SHLWAPI.538] 5378 * 5379 * Undocumented: Implementation guessed at via Name and behavior 5380 * 5381 * PARAMS 5382 * lpUnknown [I] Object to get an IServiceProvider interface from 5383 * riid [I] Function requested for QueryService call 5384 * lppOut [O] Destination for the service interface pointer 5385 * 5386 * RETURNS 5387 * Success: S_OK. lppOut contains an object providing the requested service 5388 * Failure: An HRESULT error code 5389 * 5390 * NOTES 5391 * lpUnknown is expected to support the IServiceProvider interface. 5392 */ 5393 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown, 5394 REFGUID riid, LPVOID *lppOut) 5395 { 5396 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut); 5397 return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut); 5398 } 5399 5400 #ifdef __REACTOS__ 5401 HRESULT VariantChangeTypeForRead(_Inout_ VARIANTARG *pvarg, _In_ VARTYPE vt) 5402 { 5403 HRESULT hr; 5404 VARIANTARG vargTemp; 5405 VARIANT variTemp; 5406 5407 if (V_VT(pvarg) == vt || vt == VT_EMPTY) 5408 return S_OK; 5409 5410 vargTemp = *pvarg; 5411 5412 if (V_VT(&vargTemp) != VT_BSTR || vt <= VT_NULL) 5413 goto DoDefault; 5414 5415 if (vt == VT_I1 || vt == VT_I2 || vt == VT_I4) 5416 { 5417 if (!StrToIntExW(V_BSTR(&vargTemp), STIF_SUPPORT_HEX, &V_I4(&variTemp))) 5418 goto DoDefault; 5419 5420 V_VT(&variTemp) = VT_INT; 5421 VariantInit(pvarg); 5422 hr = VariantChangeType(pvarg, &variTemp, 0, vt); 5423 VariantClear(&vargTemp); 5424 return hr; 5425 } 5426 5427 if (vt <= VT_DECIMAL) 5428 goto DoDefault; 5429 5430 if (vt == VT_UI1 || vt == VT_UI2 || vt == VT_UI4) 5431 { 5432 if (!StrToIntExW(V_BSTR(&vargTemp), STIF_SUPPORT_HEX, (LPINT)&V_UI4(&variTemp))) 5433 goto DoDefault; 5434 5435 V_VT(&variTemp) = VT_UINT; 5436 VariantInit(pvarg); 5437 hr = VariantChangeType(pvarg, &variTemp, 0, vt); 5438 VariantClear(&vargTemp); 5439 return hr; 5440 } 5441 5442 if (vt == VT_INT || vt == VT_UINT) 5443 { 5444 if (!StrToIntExW(V_BSTR(&vargTemp), STIF_SUPPORT_HEX, &V_INT(&variTemp))) 5445 goto DoDefault; 5446 5447 V_VT(&variTemp) = VT_UINT; 5448 VariantInit(pvarg); 5449 hr = VariantChangeType(pvarg, &variTemp, 0, vt); 5450 VariantClear(&vargTemp); 5451 return hr; 5452 } 5453 5454 DoDefault: 5455 VariantInit(pvarg); 5456 hr = VariantChangeType(pvarg, &vargTemp, 0, vt); 5457 VariantClear(&vargTemp); 5458 return hr; 5459 } 5460 5461 BOOL 5462 VariantArrayToBuffer( 5463 _In_ const VARIANT *pvarIn, 5464 _Out_writes_(cbSize) LPVOID pvDest, 5465 _In_ SIZE_T cbSize) 5466 { 5467 LPVOID pvData; 5468 LONG LowerBound, UpperBound; 5469 LPSAFEARRAY pArray; 5470 5471 /* Only supports byte array */ 5472 if (!pvarIn || V_VT(pvarIn) != (VT_UI1 | VT_ARRAY)) 5473 return FALSE; 5474 5475 /* Boundary check and access */ 5476 pArray = V_ARRAY(pvarIn); 5477 if (SafeArrayGetDim(pArray) == 1 && 5478 SUCCEEDED(SafeArrayGetLBound(pArray, 1, &LowerBound)) && 5479 SUCCEEDED(SafeArrayGetUBound(pArray, 1, &UpperBound)) && 5480 ((LONG)cbSize <= UpperBound - LowerBound + 1) && 5481 SUCCEEDED(SafeArrayAccessData(pArray, &pvData))) 5482 { 5483 CopyMemory(pvDest, pvData, cbSize); 5484 SafeArrayUnaccessData(pArray); 5485 return TRUE; /* Success */ 5486 } 5487 5488 return FALSE; /* Failure */ 5489 } 5490 5491 /************************************************************************** 5492 * SHPropertyBag_ReadType (SHLWAPI.493) 5493 * 5494 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readtype.htm 5495 */ 5496 HRESULT WINAPI 5497 SHPropertyBag_ReadType(IPropertyBag *ppb, LPCWSTR pszPropName, VARIANTARG *pvarg, VARTYPE vt) 5498 { 5499 HRESULT hr; 5500 5501 VariantInit(pvarg); 5502 V_VT(pvarg) = vt; 5503 5504 hr = IPropertyBag_Read(ppb, pszPropName, pvarg, NULL); 5505 if (FAILED(hr)) 5506 { 5507 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5508 VariantInit(pvarg); 5509 return hr; 5510 } 5511 5512 return VariantChangeTypeForRead(pvarg, vt); 5513 } 5514 5515 /************************************************************************** 5516 * SHPropertyBag_ReadBOOL (SHLWAPI.534) 5517 * 5518 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readbool.htm 5519 */ 5520 HRESULT WINAPI SHPropertyBag_ReadBOOL(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL *pbValue) 5521 { 5522 HRESULT hr; 5523 VARIANTARG varg; 5524 5525 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pbValue); 5526 5527 if (!ppb || !pszPropName || !pbValue) 5528 { 5529 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pbValue); 5530 return E_INVALIDARG; 5531 } 5532 5533 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_BOOL); 5534 if (SUCCEEDED(hr)) 5535 *pbValue = (V_BOOL(&varg) == VARIANT_TRUE); 5536 5537 return hr; 5538 } 5539 5540 /************************************************************************** 5541 * SHPropertyBag_ReadBOOLOld (SHLWAPI.498) 5542 * 5543 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readboolold.htm 5544 */ 5545 BOOL WINAPI SHPropertyBag_ReadBOOLOld(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL bDefValue) 5546 { 5547 VARIANTARG varg; 5548 HRESULT hr; 5549 5550 TRACE("%p %s %d\n", ppb, debugstr_w(pszPropName), bDefValue); 5551 5552 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_BOOL); 5553 if (FAILED(hr)) 5554 return bDefValue; 5555 5556 return V_BOOL(&varg) == VARIANT_TRUE; 5557 } 5558 5559 /************************************************************************** 5560 * SHPropertyBag_ReadSHORT (SHLWAPI.527) 5561 * 5562 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readshort.htm 5563 */ 5564 HRESULT WINAPI SHPropertyBag_ReadSHORT(IPropertyBag *ppb, LPCWSTR pszPropName, SHORT *psValue) 5565 { 5566 HRESULT hr; 5567 VARIANTARG varg; 5568 5569 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), psValue); 5570 5571 if (!ppb || !pszPropName || !psValue) 5572 { 5573 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), psValue); 5574 return E_INVALIDARG; 5575 } 5576 5577 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_UI2); 5578 if (SUCCEEDED(hr)) 5579 *psValue = V_UI2(&varg); 5580 5581 return hr; 5582 } 5583 #endif 5584 5585 /************************************************************************** 5586 * SHPropertyBag_ReadLONG (SHLWAPI.496) 5587 * 5588 * This function asks a property bag to read a named property as a LONG. 5589 * 5590 * PARAMS 5591 * ppb: a IPropertyBag interface 5592 * pszPropName: Unicode string that names the property 5593 * pValue: address to receive the property value as a 32-bit signed integer 5594 * 5595 * RETURNS 5596 * HRESULT codes 5597 #ifdef __REACTOS__ 5598 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readlong.htm 5599 #endif 5600 */ 5601 HRESULT WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue) 5602 { 5603 #ifdef __REACTOS__ 5604 HRESULT hr; 5605 VARIANTARG varg; 5606 5607 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pValue); 5608 5609 if (!ppb || !pszPropName || !pValue) 5610 { 5611 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pValue); 5612 return E_INVALIDARG; 5613 } 5614 5615 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_I4); 5616 if (SUCCEEDED(hr)) 5617 *pValue = V_I4(&varg); 5618 #else 5619 VARIANT var; 5620 HRESULT hr; 5621 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue); 5622 if (!pszPropName || !ppb || !pValue) 5623 return E_INVALIDARG; 5624 V_VT(&var) = VT_I4; 5625 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL); 5626 if (SUCCEEDED(hr)) 5627 { 5628 if (V_VT(&var) == VT_I4) 5629 *pValue = V_I4(&var); 5630 else 5631 hr = DISP_E_BADVARTYPE; 5632 } 5633 #endif 5634 return hr; 5635 } 5636 5637 #ifdef __REACTOS__ 5638 /************************************************************************** 5639 * SHPropertyBag_ReadDWORD (SHLWAPI.507) 5640 * 5641 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readdword.htm 5642 */ 5643 HRESULT WINAPI SHPropertyBag_ReadDWORD(IPropertyBag *ppb, LPCWSTR pszPropName, DWORD *pdwValue) 5644 { 5645 HRESULT hr; 5646 VARIANTARG varg; 5647 5648 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pdwValue); 5649 5650 if (!ppb || !pszPropName || !pdwValue) 5651 { 5652 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pdwValue); 5653 return E_INVALIDARG; 5654 } 5655 5656 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_UI4); 5657 if (SUCCEEDED(hr)) 5658 *pdwValue = V_UI4(&varg); 5659 5660 return hr; 5661 } 5662 5663 /************************************************************************** 5664 * SHPropertyBag_ReadBSTR (SHLWAPI.520) 5665 * 5666 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readbstr.htm 5667 */ 5668 HRESULT WINAPI SHPropertyBag_ReadBSTR(IPropertyBag *ppb, LPCWSTR pszPropName, BSTR *pbstr) 5669 { 5670 HRESULT hr; 5671 VARIANTARG varg; 5672 5673 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pbstr); 5674 5675 if (!ppb || !pszPropName || !pbstr) 5676 { 5677 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pbstr); 5678 return E_INVALIDARG; 5679 } 5680 5681 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_BSTR); 5682 if (FAILED(hr)) 5683 *pbstr = NULL; 5684 else 5685 *pbstr = V_BSTR(&varg); 5686 5687 return hr; 5688 } 5689 5690 /************************************************************************** 5691 * SHPropertyBag_ReadStr (SHLWAPI.494) 5692 * 5693 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readstr.htm 5694 */ 5695 HRESULT WINAPI SHPropertyBag_ReadStr(IPropertyBag *ppb, LPCWSTR pszPropName, LPWSTR pszDst, int cchMax) 5696 { 5697 HRESULT hr; 5698 VARIANTARG varg; 5699 5700 TRACE("%p %s %p %d\n", ppb, debugstr_w(pszPropName), pszDst, cchMax); 5701 5702 if (!ppb || !pszPropName || !pszDst) 5703 { 5704 ERR("%p %s %p %d\n", ppb, debugstr_w(pszPropName), pszDst, cchMax); 5705 return E_INVALIDARG; 5706 } 5707 5708 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_BSTR); 5709 if (FAILED(hr)) 5710 return E_FAIL; 5711 5712 StrCpyNW(pszDst, V_BSTR(&varg), cchMax); 5713 VariantClear(&varg); 5714 return hr; 5715 } 5716 5717 /************************************************************************** 5718 * SHPropertyBag_ReadPOINTL (SHLWAPI.521) 5719 * 5720 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readpointl.htm 5721 */ 5722 HRESULT WINAPI SHPropertyBag_ReadPOINTL(IPropertyBag *ppb, LPCWSTR pszPropName, POINTL *pptl) 5723 { 5724 HRESULT hr; 5725 int cch, cch2; 5726 WCHAR *pch, szBuff[MAX_PATH]; 5727 5728 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pptl); 5729 5730 if (!ppb || !pszPropName || !pptl) 5731 { 5732 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pptl); 5733 return E_INVALIDARG; 5734 } 5735 5736 StrCpyNW(szBuff, pszPropName, _countof(szBuff)); 5737 5738 cch = lstrlenW(szBuff); 5739 cch2 = _countof(szBuff) - cch; 5740 if (cch2 < _countof(L".x")) 5741 { 5742 ERR("%s is too long\n", debugstr_w(pszPropName)); 5743 return E_FAIL; 5744 } 5745 5746 pch = &szBuff[cch]; 5747 5748 StrCpyNW(pch, L".x", cch2); 5749 hr = SHPropertyBag_ReadLONG(ppb, szBuff, &pptl->x); 5750 if (FAILED(hr)) 5751 return hr; 5752 5753 StrCpyNW(pch, L".y", cch2); 5754 return SHPropertyBag_ReadLONG(ppb, szBuff, &pptl->y); 5755 } 5756 5757 /************************************************************************** 5758 * SHPropertyBag_ReadPOINTS (SHLWAPI.525) 5759 * 5760 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readpoints.htm 5761 */ 5762 HRESULT WINAPI SHPropertyBag_ReadPOINTS(IPropertyBag *ppb, LPCWSTR pszPropName, POINTS *ppts) 5763 { 5764 HRESULT hr; 5765 POINTL ptl; 5766 5767 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), ppts); 5768 5769 if (!ppb || !pszPropName || !ppts) 5770 { 5771 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), ppts); 5772 return E_INVALIDARG; 5773 } 5774 5775 hr = SHPropertyBag_ReadPOINTL(ppb, pszPropName, &ptl); 5776 if (FAILED(hr)) 5777 return hr; 5778 5779 ppts->x = ptl.x; 5780 ppts->y = ptl.y; 5781 return hr; 5782 } 5783 5784 /************************************************************************** 5785 * SHPropertyBag_ReadRECTL (SHLWAPI.523) 5786 * 5787 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readrectl.htm 5788 */ 5789 HRESULT WINAPI SHPropertyBag_ReadRECTL(IPropertyBag *ppb, LPCWSTR pszPropName, RECTL *prcl) 5790 { 5791 HRESULT hr; 5792 int cch, cch2; 5793 WCHAR *pch, szBuff[MAX_PATH]; 5794 5795 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), prcl); 5796 5797 if (!ppb || !pszPropName || !prcl) 5798 { 5799 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), prcl); 5800 return E_INVALIDARG; 5801 } 5802 5803 StrCpyNW(szBuff, pszPropName, _countof(szBuff)); 5804 5805 cch = lstrlenW(szBuff); 5806 cch2 = _countof(szBuff) - cch; 5807 if (cch2 < _countof(L".bottom")) 5808 { 5809 ERR("%s is too long\n", debugstr_w(pszPropName)); 5810 return E_FAIL; 5811 } 5812 5813 pch = &szBuff[cch]; 5814 5815 StrCpyNW(pch, L".left", cch2); 5816 hr = SHPropertyBag_ReadLONG(ppb, szBuff, &prcl->left); 5817 if (FAILED(hr)) 5818 return hr; 5819 5820 StrCpyNW(pch, L".top", cch2); 5821 hr = SHPropertyBag_ReadLONG(ppb, szBuff, &prcl->top); 5822 if (FAILED(hr)) 5823 return hr; 5824 5825 StrCpyNW(pch, L".right", cch2); 5826 hr = SHPropertyBag_ReadLONG(ppb, szBuff, &prcl->right); 5827 if (FAILED(hr)) 5828 return hr; 5829 5830 StrCpyNW(pch, L".bottom", cch2); 5831 return SHPropertyBag_ReadLONG(ppb, szBuff, &prcl->bottom); 5832 } 5833 5834 /************************************************************************** 5835 * SHPropertyBag_ReadGUID (SHLWAPI.505) 5836 * 5837 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readguid.htm 5838 */ 5839 HRESULT WINAPI SHPropertyBag_ReadGUID(IPropertyBag *ppb, LPCWSTR pszPropName, GUID *pguid) 5840 { 5841 HRESULT hr; 5842 BOOL bRet; 5843 VARIANT vari; 5844 5845 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 5846 5847 if (!ppb || !pszPropName || !pguid) 5848 { 5849 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 5850 return E_INVALIDARG; 5851 } 5852 5853 hr = SHPropertyBag_ReadType(ppb, pszPropName, &vari, VT_EMPTY); 5854 if (FAILED(hr)) 5855 { 5856 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 5857 return hr; 5858 } 5859 5860 if (V_VT(&vari) == (VT_UI1 | VT_ARRAY)) /* Byte Array */ 5861 bRet = VariantArrayToBuffer(&vari, pguid, sizeof(*pguid)); 5862 else if (V_VT(&vari) == VT_BSTR) 5863 bRet = GUIDFromStringW(V_BSTR(&vari), pguid); 5864 else 5865 #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) 5866 bRet = FALSE; 5867 #else 5868 bRet = TRUE; /* This is by design in WinXP/Win2k3. */ 5869 #endif 5870 5871 if (!bRet) 5872 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 5873 5874 VariantClear(&vari); 5875 return (bRet ? S_OK : E_FAIL); 5876 } 5877 5878 /************************************************************************** 5879 * SHPropertyBag_ReadStream (SHLWAPI.531) 5880 * 5881 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readstream.htm 5882 */ 5883 HRESULT WINAPI SHPropertyBag_ReadStream(IPropertyBag *ppb, LPCWSTR pszPropName, IStream **ppStream) 5884 { 5885 HRESULT hr; 5886 VARIANT vari; 5887 5888 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), ppStream); 5889 5890 if (!ppb || !pszPropName || !ppStream) 5891 { 5892 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), ppStream); 5893 return E_INVALIDARG; 5894 } 5895 5896 hr = SHPropertyBag_ReadType(ppb, pszPropName, &vari, VT_UNKNOWN); 5897 if (FAILED(hr)) 5898 return hr; 5899 5900 hr = IUnknown_QueryInterface(V_UNKNOWN(&vari), &IID_IStream, (void **)ppStream); 5901 IUnknown_Release(V_UNKNOWN(&vari)); 5902 5903 return hr; 5904 } 5905 5906 /************************************************************************** 5907 * SHPropertyBag_Delete (SHLWAPI.535) 5908 * 5909 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/delete.htm 5910 */ 5911 HRESULT WINAPI SHPropertyBag_Delete(IPropertyBag *ppb, LPCWSTR pszPropName) 5912 { 5913 VARIANT vari; 5914 5915 TRACE("%p %s\n", ppb, debugstr_w(pszPropName)); 5916 5917 if (!ppb || !pszPropName) 5918 { 5919 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5920 return E_INVALIDARG; 5921 } 5922 5923 V_VT(&vari) = VT_EMPTY; 5924 return IPropertyBag_Write(ppb, pszPropName, &vari); 5925 } 5926 5927 /************************************************************************** 5928 * SHPropertyBag_WriteBOOL (SHLWAPI.499) 5929 * 5930 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writebool.htm 5931 */ 5932 HRESULT WINAPI SHPropertyBag_WriteBOOL(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL bValue) 5933 { 5934 VARIANT vari; 5935 5936 TRACE("%p %s %d\n", ppb, debugstr_w(pszPropName), bValue); 5937 5938 if (!ppb || !pszPropName) 5939 { 5940 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5941 return E_INVALIDARG; 5942 } 5943 5944 V_VT(&vari) = VT_BOOL; 5945 V_BOOL(&vari) = (bValue ? VARIANT_TRUE : VARIANT_FALSE); /* NOTE: VARIANT_TRUE is (SHORT)-1 */ 5946 return IPropertyBag_Write(ppb, pszPropName, &vari); 5947 } 5948 5949 /************************************************************************** 5950 * SHPropertyBag_WriteSHORT (SHLWAPI.528) 5951 * 5952 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writeshort.htm 5953 */ 5954 HRESULT WINAPI SHPropertyBag_WriteSHORT(IPropertyBag *ppb, LPCWSTR pszPropName, SHORT sValue) 5955 { 5956 VARIANT vari; 5957 5958 TRACE("%p %s %d\n", ppb, debugstr_w(pszPropName), sValue); 5959 5960 if (!ppb || !pszPropName) 5961 { 5962 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5963 return E_INVALIDARG; 5964 } 5965 5966 V_VT(&vari) = VT_UI2; 5967 V_UI2(&vari) = sValue; 5968 return IPropertyBag_Write(ppb, pszPropName, &vari); 5969 } 5970 5971 /************************************************************************** 5972 * SHPropertyBag_WriteLONG (SHLWAPI.497) 5973 * 5974 * This function asks a property bag to write a named property as a LONG. 5975 * 5976 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writelong.htm 5977 */ 5978 HRESULT WINAPI SHPropertyBag_WriteLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LONG lValue) 5979 { 5980 VARIANT vari; 5981 5982 TRACE("%p %s %ld\n", ppb, debugstr_w(pszPropName), lValue); 5983 5984 if (!ppb || !pszPropName) 5985 { 5986 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5987 return E_INVALIDARG; 5988 } 5989 5990 V_VT(&vari) = VT_I4; 5991 V_I4(&vari) = lValue; 5992 return IPropertyBag_Write(ppb, pszPropName, &vari); 5993 } 5994 5995 /************************************************************************** 5996 * SHPropertyBag_WriteDWORD (SHLWAPI.508) 5997 * 5998 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writedword.htm 5999 */ 6000 HRESULT WINAPI SHPropertyBag_WriteDWORD(IPropertyBag *ppb, LPCWSTR pszPropName, DWORD dwValue) 6001 { 6002 VARIANT vari; 6003 6004 TRACE("%p %s %lu\n", ppb, debugstr_w(pszPropName), dwValue); 6005 6006 if (!ppb || !pszPropName) 6007 { 6008 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 6009 return E_INVALIDARG; 6010 } 6011 6012 V_VT(&vari) = VT_UI4; 6013 V_UI4(&vari) = dwValue; 6014 return IPropertyBag_Write(ppb, pszPropName, &vari); 6015 } 6016 6017 /************************************************************************** 6018 * SHPropertyBag_WriteStr (SHLWAPI.495) 6019 * 6020 * This function asks a property bag to write a string as the value of a named property. 6021 * 6022 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writestr.htm 6023 */ 6024 HRESULT WINAPI SHPropertyBag_WriteStr(IPropertyBag *ppb, LPCWSTR pszPropName, LPCWSTR pszValue) 6025 { 6026 HRESULT hr; 6027 VARIANT vari; 6028 6029 TRACE("%p %s %s\n", ppb, debugstr_w(pszPropName), debugstr_w(pszValue)); 6030 6031 if (!ppb || !pszPropName) 6032 { 6033 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 6034 return E_INVALIDARG; 6035 } 6036 6037 V_BSTR(&vari) = SysAllocString(pszValue); 6038 if (!V_BSTR(&vari)) 6039 return E_OUTOFMEMORY; 6040 6041 V_VT(&vari) = VT_BSTR; 6042 hr = IPropertyBag_Write(ppb, pszPropName, &vari); 6043 6044 SysFreeString(V_BSTR(&vari)); 6045 return hr; 6046 } 6047 6048 /************************************************************************** 6049 * SHPropertyBag_WriteGUID (SHLWAPI.506) 6050 * 6051 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writeguid.htm 6052 */ 6053 HRESULT WINAPI SHPropertyBag_WriteGUID(IPropertyBag *ppb, LPCWSTR pszPropName, const GUID *pguid) 6054 { 6055 WCHAR szBuff[64]; 6056 6057 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 6058 6059 if (!ppb || !pszPropName || !pguid) 6060 { 6061 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 6062 return E_INVALIDARG; 6063 } 6064 6065 SHStringFromGUIDW(pguid, szBuff, _countof(szBuff)); 6066 return SHPropertyBag_WriteStr(ppb, pszPropName, szBuff); 6067 } 6068 6069 /************************************************************************** 6070 * SHPropertyBag_WriteStream (SHLWAPI.532) 6071 * 6072 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writestream.htm 6073 */ 6074 HRESULT WINAPI SHPropertyBag_WriteStream(IPropertyBag *ppb, LPCWSTR pszPropName, IStream *pStream) 6075 { 6076 VARIANT vari; 6077 6078 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pStream); 6079 6080 if (!ppb || !pszPropName || !pStream) 6081 { 6082 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pStream); 6083 return E_INVALIDARG; 6084 } 6085 6086 V_VT(&vari) = VT_UNKNOWN; 6087 V_UNKNOWN(&vari) = (IUnknown*)pStream; 6088 return IPropertyBag_Write(ppb, pszPropName, &vari); 6089 } 6090 6091 /************************************************************************** 6092 * SHPropertyBag_WritePOINTL (SHLWAPI.522) 6093 * 6094 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writepointl.htm 6095 */ 6096 HRESULT WINAPI SHPropertyBag_WritePOINTL(IPropertyBag *ppb, LPCWSTR pszPropName, const POINTL *pptl) 6097 { 6098 HRESULT hr; 6099 int cch, cch2; 6100 WCHAR *pch, szBuff[MAX_PATH]; 6101 6102 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pptl); 6103 6104 if (!ppb || !pszPropName || !pptl) 6105 { 6106 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pptl); 6107 return E_INVALIDARG; 6108 } 6109 6110 StrCpyNW(szBuff, pszPropName, _countof(szBuff)); 6111 6112 cch = lstrlenW(szBuff); 6113 cch2 = _countof(szBuff) - cch; 6114 if (cch2 < _countof(L".x")) 6115 { 6116 ERR("%s is too long\n", debugstr_w(pszPropName)); 6117 return E_FAIL; 6118 } 6119 6120 pch = &szBuff[cch]; 6121 6122 StrCpyNW(pch, L".x", cch2); 6123 hr = SHPropertyBag_WriteLONG(ppb, szBuff, pptl->x); 6124 if (FAILED(hr)) 6125 return hr; 6126 6127 StrCpyNW(pch, L".y", cch2); 6128 hr = SHPropertyBag_WriteLONG(ppb, szBuff, pptl->y); 6129 if (FAILED(hr)) 6130 { 6131 StrCpyNW(pch, L".x", cch2); 6132 return SHPropertyBag_Delete(ppb, szBuff); 6133 } 6134 6135 return hr; 6136 } 6137 6138 /************************************************************************** 6139 * SHPropertyBag_WritePOINTS (SHLWAPI.526) 6140 * 6141 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writepoints.htm 6142 */ 6143 HRESULT WINAPI SHPropertyBag_WritePOINTS(IPropertyBag *ppb, LPCWSTR pszPropName, const POINTS *ppts) 6144 { 6145 POINTL pt; 6146 6147 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), ppts); 6148 6149 if (!ppb || !pszPropName || !ppts) 6150 { 6151 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), ppts); 6152 return E_INVALIDARG; 6153 } 6154 6155 pt.x = ppts->x; 6156 pt.y = ppts->y; 6157 return SHPropertyBag_WritePOINTL(ppb, pszPropName, &pt); 6158 } 6159 6160 /************************************************************************** 6161 * SHPropertyBag_WriteRECTL (SHLWAPI.524) 6162 * 6163 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writerectl.htm 6164 */ 6165 HRESULT WINAPI SHPropertyBag_WriteRECTL(IPropertyBag *ppb, LPCWSTR pszPropName, const RECTL *prcl) 6166 { 6167 HRESULT hr; 6168 int cch, cch2; 6169 WCHAR *pch, szBuff[MAX_PATH]; 6170 6171 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), prcl); 6172 6173 if (!ppb || !pszPropName || !prcl) 6174 { 6175 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), prcl); 6176 return E_INVALIDARG; 6177 } 6178 6179 StrCpyNW(szBuff, pszPropName, _countof(szBuff)); 6180 6181 cch = lstrlenW(szBuff); 6182 cch2 = _countof(szBuff) - cch; 6183 if (cch2 < _countof(L".bottom")) 6184 { 6185 ERR("%s is too long\n", debugstr_w(pszPropName)); 6186 return E_FAIL; 6187 } 6188 6189 pch = &szBuff[cch]; 6190 6191 StrCpyNW(pch, L".left", cch2); 6192 hr = SHPropertyBag_WriteLONG(ppb, szBuff, prcl->left); 6193 if (SUCCEEDED(hr)) 6194 { 6195 StrCpyNW(pch, L".top", cch2); 6196 hr = SHPropertyBag_WriteLONG(ppb, szBuff, prcl->top); 6197 if (SUCCEEDED(hr)) 6198 { 6199 StrCpyNW(pch, L".right", cch2); 6200 hr = SHPropertyBag_WriteLONG(ppb, szBuff, prcl->right); 6201 if (SUCCEEDED(hr)) 6202 { 6203 StrCpyNW(pch, L".bottom", cch2); 6204 hr = SHPropertyBag_WriteLONG(ppb, szBuff, prcl->bottom); 6205 if (SUCCEEDED(hr)) 6206 return hr; /* All successful */ 6207 6208 StrCpyNW(pch, L".right", cch2); 6209 hr = SHPropertyBag_Delete(ppb, szBuff); 6210 if (SUCCEEDED(hr)) 6211 return hr; 6212 } 6213 6214 StrCpyNW(pch, L".top", cch2); 6215 hr = SHPropertyBag_Delete(ppb, szBuff); 6216 if (SUCCEEDED(hr)) 6217 return hr; 6218 } 6219 6220 StrCpyNW(pch, L".left", cch2); 6221 hr = SHPropertyBag_Delete(ppb, szBuff); 6222 if (SUCCEEDED(hr)) 6223 return hr; 6224 } 6225 6226 return hr; 6227 } 6228 #endif 6229 6230 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */ 6231 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001 6232 #define OBJCOMPAT_NO_WEBVIEW 0x00000002 6233 #define OBJCOMPAT_UNBINDABLE 0x00000004 6234 #define OBJCOMPAT_PINDLL 0x00000008 6235 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010 6236 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020 6237 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040 6238 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080 6239 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100 6240 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200 6241 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400 6242 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000 6243 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000 6244 6245 /* a search table for compatibility flags */ 6246 struct objcompat_entry { 6247 const WCHAR name[30]; 6248 DWORD value; 6249 }; 6250 6251 /* expected to be sorted by name */ 6252 static const struct objcompat_entry objcompat_table[] = { 6253 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0}, 6254 OBJCOMPAT_COCREATESHELLFOLDERONLY }, 6255 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0}, 6256 OBJCOMPAT_CTXMENU_LIMITEDQI }, 6257 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0}, 6258 OBJCOMPAT_CTXMENU_LIMITEDQI }, 6259 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0}, 6260 OBJCOMPAT_CTXMENU_XPQCMFLAGS }, 6261 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0}, 6262 OBJCOMPAT_NEEDSFILESYSANCESTOR }, 6263 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0}, 6264 OBJCOMPAT_NEEDSSTORAGEANCESTOR }, 6265 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0}, 6266 OBJCOMPAT_NOIPROPERTYSTORE }, 6267 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0}, 6268 OBJCOMPAT_NOLEGACYWEBVIEW }, 6269 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0}, 6270 OBJCOMPAT_NOTAFILESYSTEM }, 6271 { {'N','O','_','W','E','B','V','I','E','W',0}, 6272 OBJCOMPAT_NO_WEBVIEW }, 6273 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0}, 6274 OBJCOMPAT_OTNEEDSSFCACHE }, 6275 { {'P','I','N','D','L','L',0}, 6276 OBJCOMPAT_PINDLL }, 6277 { {'U','N','B','I','N','D','A','B','L','E',0}, 6278 OBJCOMPAT_UNBINDABLE } 6279 }; 6280 6281 /************************************************************************** 6282 * SHGetObjectCompatFlags (SHLWAPI.476) 6283 * 6284 * Function returns an integer representation of compatibility flags stored 6285 * in registry for CLSID under ShellCompatibility subkey. 6286 * 6287 * PARAMS 6288 * pUnk: pointer to object IUnknown interface, idetifies CLSID 6289 * clsid: pointer to CLSID to retrieve data for 6290 * 6291 * RETURNS 6292 * 0 on failure, flags set on success 6293 */ 6294 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid) 6295 { 6296 static const WCHAR compatpathW[] = 6297 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', 6298 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 6299 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\', 6300 'O','b','j','e','c','t','s','\\','%','s',0}; 6301 WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */]; 6302 DWORD ret, length = sizeof(strW)/sizeof(WCHAR); 6303 OLECHAR *clsid_str; 6304 HKEY key; 6305 INT i; 6306 6307 TRACE("%p %s\n", pUnk, debugstr_guid(clsid)); 6308 6309 if (!pUnk && !clsid) return 0; 6310 6311 if (pUnk && !clsid) 6312 { 6313 FIXME("iface not handled\n"); 6314 return 0; 6315 } 6316 6317 StringFromCLSID(clsid, &clsid_str); 6318 sprintfW(strW, compatpathW, clsid_str); 6319 CoTaskMemFree(clsid_str); 6320 6321 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key); 6322 if (ret != ERROR_SUCCESS) return 0; 6323 6324 /* now collect flag values */ 6325 ret = 0; 6326 for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++) 6327 { 6328 INT left, right, res, x; 6329 6330 /* search in table */ 6331 left = 0; 6332 right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1; 6333 6334 while (right >= left) { 6335 x = (left + right) / 2; 6336 res = strcmpW(strW, objcompat_table[x].name); 6337 if (res == 0) 6338 { 6339 ret |= objcompat_table[x].value; 6340 break; 6341 } 6342 else if (res < 0) 6343 right = x - 1; 6344 else 6345 left = x + 1; 6346 } 6347 6348 length = sizeof(strW)/sizeof(WCHAR); 6349 } 6350 6351 return ret; 6352 } 6353