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