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 * Success: S_OK 2444 * 2445 */ 2446 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id) 2447 { 2448 FIXME("(%p, %d) stub\n", hWnd, id); 2449 return S_OK; 2450 } 2451 2452 /************************************************************************* 2453 * @ [SHLWAPI.221] 2454 * 2455 * Remove the "PropDlgFont" property from a window. 2456 * 2457 * PARAMS 2458 * hWnd [I] Window to remove the property from 2459 * 2460 * RETURNS 2461 * A handle to the removed property, or NULL if it did not exist. 2462 */ 2463 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd) 2464 { 2465 HANDLE hProp; 2466 2467 TRACE("(%p)\n", hWnd); 2468 2469 hProp = GetPropA(hWnd, "PropDlgFont"); 2470 2471 if(hProp) 2472 { 2473 DeleteObject(hProp); 2474 hProp = RemovePropA(hWnd, "PropDlgFont"); 2475 } 2476 return hProp; 2477 } 2478 2479 /************************************************************************* 2480 * @ [SHLWAPI.236] 2481 * 2482 * Load the in-process server of a given GUID. 2483 * 2484 * PARAMS 2485 * refiid [I] GUID of the server to load. 2486 * 2487 * RETURNS 2488 * Success: A handle to the loaded server dll. 2489 * Failure: A NULL handle. 2490 */ 2491 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid) 2492 { 2493 HKEY newkey; 2494 DWORD type, count; 2495 CHAR value[MAX_PATH], string[MAX_PATH]; 2496 2497 strcpy(string, "CLSID\\"); 2498 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6); 2499 strcat(string, "\\InProcServer32"); 2500 2501 count = MAX_PATH; 2502 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey); 2503 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count); 2504 RegCloseKey(newkey); 2505 return LoadLibraryExA(value, 0, 0); 2506 } 2507 2508 /************************************************************************* 2509 * @ [SHLWAPI.237] 2510 * 2511 * Unicode version of SHLWAPI_183. 2512 */ 2513 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass) 2514 { 2515 WNDCLASSW WndClass; 2516 2517 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName)); 2518 2519 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass)) 2520 return TRUE; 2521 return RegisterClassW(lpWndClass); 2522 } 2523 2524 /************************************************************************* 2525 * @ [SHLWAPI.238] 2526 * 2527 * Unregister a list of classes. 2528 * 2529 * PARAMS 2530 * hInst [I] Application instance that registered the classes 2531 * lppClasses [I] List of class names 2532 * iCount [I] Number of names in lppClasses 2533 * 2534 * RETURNS 2535 * Nothing. 2536 */ 2537 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount) 2538 { 2539 WNDCLASSA WndClass; 2540 2541 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount); 2542 2543 while (iCount > 0) 2544 { 2545 if (GetClassInfoA(hInst, *lppClasses, &WndClass)) 2546 UnregisterClassA(*lppClasses, hInst); 2547 lppClasses++; 2548 iCount--; 2549 } 2550 } 2551 2552 /************************************************************************* 2553 * @ [SHLWAPI.239] 2554 * 2555 * Unicode version of SHUnregisterClassesA. 2556 */ 2557 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount) 2558 { 2559 WNDCLASSW WndClass; 2560 2561 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount); 2562 2563 while (iCount > 0) 2564 { 2565 if (GetClassInfoW(hInst, *lppClasses, &WndClass)) 2566 UnregisterClassW(*lppClasses, hInst); 2567 lppClasses++; 2568 iCount--; 2569 } 2570 } 2571 2572 /************************************************************************* 2573 * @ [SHLWAPI.240] 2574 * 2575 * Call The correct (Ascii/Unicode) default window procedure for a window. 2576 * 2577 * PARAMS 2578 * hWnd [I] Window to call the default procedure for 2579 * uMessage [I] Message ID 2580 * wParam [I] WPARAM of message 2581 * lParam [I] LPARAM of message 2582 * 2583 * RETURNS 2584 * The result of calling DefWindowProcA() or DefWindowProcW(). 2585 */ 2586 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam) 2587 { 2588 if (IsWindowUnicode(hWnd)) 2589 return DefWindowProcW(hWnd, uMessage, wParam, lParam); 2590 return DefWindowProcA(hWnd, uMessage, wParam, lParam); 2591 } 2592 2593 /************************************************************************* 2594 * @ [SHLWAPI.256] 2595 */ 2596 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite) 2597 { 2598 HRESULT hRet = E_INVALIDARG; 2599 LPOBJECTWITHSITE lpSite = NULL; 2600 2601 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite); 2602 2603 if (lpUnknown && iid && lppSite) 2604 { 2605 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite, 2606 (void**)&lpSite); 2607 if (SUCCEEDED(hRet) && lpSite) 2608 { 2609 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite); 2610 IObjectWithSite_Release(lpSite); 2611 } 2612 } 2613 return hRet; 2614 } 2615 2616 /************************************************************************* 2617 * @ [SHLWAPI.257] 2618 * 2619 * Create a worker window using CreateWindowExA(). 2620 * 2621 * PARAMS 2622 * wndProc [I] Window procedure 2623 * hWndParent [I] Parent window 2624 * dwExStyle [I] Extra style flags 2625 * dwStyle [I] Style flags 2626 * hMenu [I] Window menu 2627 * wnd_extra [I] Window extra bytes value 2628 * 2629 * RETURNS 2630 * Success: The window handle of the newly created window. 2631 * Failure: 0. 2632 */ 2633 HWND WINAPI SHCreateWorkerWindowA(WNDPROC wndProc, HWND hWndParent, DWORD dwExStyle, 2634 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra) 2635 { 2636 static const char szClass[] = "WorkerA"; 2637 WNDCLASSA wc; 2638 HWND hWnd; 2639 2640 TRACE("(%p, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n", 2641 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra); 2642 2643 /* Create Window class */ 2644 wc.style = 0; 2645 wc.lpfnWndProc = DefWindowProcA; 2646 wc.cbClsExtra = 0; 2647 wc.cbWndExtra = sizeof(LONG_PTR); 2648 wc.hInstance = shlwapi_hInstance; 2649 wc.hIcon = NULL; 2650 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW); 2651 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); 2652 wc.lpszMenuName = NULL; 2653 wc.lpszClassName = szClass; 2654 2655 SHRegisterClassA(&wc); 2656 2657 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0, 2658 hWndParent, hMenu, shlwapi_hInstance, 0); 2659 if (hWnd) 2660 { 2661 SetWindowLongPtrW(hWnd, 0, wnd_extra); 2662 if (wndProc) SetWindowLongPtrA(hWnd, GWLP_WNDPROC, (LONG_PTR)wndProc); 2663 } 2664 2665 return hWnd; 2666 } 2667 2668 typedef struct tagPOLICYDATA 2669 { 2670 DWORD policy; /* flags value passed to SHRestricted */ 2671 LPCWSTR appstr; /* application str such as "Explorer" */ 2672 LPCWSTR keystr; /* name of the actual registry key / policy */ 2673 } POLICYDATA, *LPPOLICYDATA; 2674 2675 #define SHELL_NO_POLICY 0xffffffff 2676 2677 /* default shell policy registry key */ 2678 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o', 2679 's','o','f','t','\\','W','i','n','d','o','w','s','\\', 2680 'C','u','r','r','e','n','t','V','e','r','s','i','o','n', 2681 '\\','P','o','l','i','c','i','e','s',0}; 2682 2683 /************************************************************************* 2684 * @ [SHLWAPI.271] 2685 * 2686 * Retrieve a policy value from the registry. 2687 * 2688 * PARAMS 2689 * lpSubKey [I] registry key name 2690 * lpSubName [I] subname of registry key 2691 * lpValue [I] value name of registry value 2692 * 2693 * RETURNS 2694 * the value associated with the registry key or 0 if not found 2695 */ 2696 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue) 2697 { 2698 DWORD retval, datsize = sizeof(retval); 2699 HKEY hKey; 2700 2701 if (!lpSubKey) 2702 lpSubKey = strRegistryPolicyW; 2703 2704 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey); 2705 if (retval != ERROR_SUCCESS) 2706 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey); 2707 if (retval != ERROR_SUCCESS) 2708 return 0; 2709 2710 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize); 2711 RegCloseKey(hKey); 2712 return retval; 2713 } 2714 2715 /************************************************************************* 2716 * @ [SHLWAPI.266] 2717 * 2718 * Helper function to retrieve the possibly cached value for a specific policy 2719 * 2720 * PARAMS 2721 * policy [I] The policy to look for 2722 * initial [I] Main registry key to open, if NULL use default 2723 * polTable [I] Table of known policies, 0 terminated 2724 * polArr [I] Cache array of policy values 2725 * 2726 * RETURNS 2727 * The retrieved policy value or 0 if not successful 2728 * 2729 * NOTES 2730 * This function is used by the native SHRestricted function to search for the 2731 * policy and cache it once retrieved. The current Wine implementation uses a 2732 * different POLICYDATA structure and implements a similar algorithm adapted to 2733 * that structure. 2734 */ 2735 DWORD WINAPI SHRestrictionLookup( 2736 DWORD policy, 2737 LPCWSTR initial, 2738 LPPOLICYDATA polTable, 2739 LPDWORD polArr) 2740 { 2741 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr); 2742 2743 if (!polTable || !polArr) 2744 return 0; 2745 2746 for (;polTable->policy; polTable++, polArr++) 2747 { 2748 if (policy == polTable->policy) 2749 { 2750 /* we have a known policy */ 2751 2752 /* check if this policy has been cached */ 2753 if (*polArr == SHELL_NO_POLICY) 2754 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr); 2755 return *polArr; 2756 } 2757 } 2758 /* we don't know this policy, return 0 */ 2759 TRACE("unknown policy: (%08x)\n", policy); 2760 return 0; 2761 } 2762 2763 /************************************************************************* 2764 * @ [SHLWAPI.267] 2765 * 2766 * Get an interface from an object. 2767 * 2768 * RETURNS 2769 * Success: S_OK. ppv contains the requested interface. 2770 * Failure: An HRESULT error code. 2771 * 2772 * NOTES 2773 * This QueryInterface asks the inner object for an interface. In case 2774 * of aggregation this request would be forwarded by the inner to the 2775 * outer object. This function asks the inner object directly for the 2776 * interface circumventing the forwarding to the outer object. 2777 */ 2778 HRESULT WINAPI SHWeakQueryInterface( 2779 IUnknown * pUnk, /* [in] Outer object */ 2780 IUnknown * pInner, /* [in] Inner object */ 2781 IID * riid, /* [in] Interface GUID to query for */ 2782 LPVOID* ppv) /* [out] Destination for queried interface */ 2783 { 2784 HRESULT hret = E_NOINTERFACE; 2785 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv); 2786 2787 *ppv = NULL; 2788 if(pUnk && pInner) { 2789 hret = IUnknown_QueryInterface(pInner, riid, ppv); 2790 if (SUCCEEDED(hret)) IUnknown_Release(pUnk); 2791 } 2792 TRACE("-- 0x%08x\n", hret); 2793 return hret; 2794 } 2795 2796 /************************************************************************* 2797 * @ [SHLWAPI.268] 2798 * 2799 * Move a reference from one interface to another. 2800 * 2801 * PARAMS 2802 * lpDest [O] Destination to receive the reference 2803 * lppUnknown [O] Source to give up the reference to lpDest 2804 * 2805 * RETURNS 2806 * Nothing. 2807 */ 2808 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown) 2809 { 2810 TRACE("(%p,%p)\n", lpDest, lppUnknown); 2811 2812 if (*lppUnknown) 2813 { 2814 /* Copy Reference*/ 2815 IUnknown_AddRef(lpDest); 2816 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */ 2817 } 2818 } 2819 2820 /************************************************************************* 2821 * @ [SHLWAPI.269] 2822 * 2823 * Convert an ASCII string of a CLSID into a CLSID. 2824 * 2825 * PARAMS 2826 * idstr [I] String representing a CLSID in registry format 2827 * id [O] Destination for the converted CLSID 2828 * 2829 * RETURNS 2830 * Success: TRUE. id contains the converted CLSID. 2831 * Failure: FALSE. 2832 */ 2833 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id) 2834 { 2835 WCHAR wClsid[40]; 2836 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR)); 2837 return SUCCEEDED(CLSIDFromString(wClsid, id)); 2838 } 2839 2840 /************************************************************************* 2841 * @ [SHLWAPI.270] 2842 * 2843 * Unicode version of GUIDFromStringA. 2844 */ 2845 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id) 2846 { 2847 return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id)); 2848 } 2849 2850 /************************************************************************* 2851 * @ [SHLWAPI.276] 2852 * 2853 * Determine if the browser is integrated into the shell, and set a registry 2854 * key accordingly. 2855 * 2856 * PARAMS 2857 * None. 2858 * 2859 * RETURNS 2860 * 1, If the browser is not integrated. 2861 * 2, If the browser is integrated. 2862 * 2863 * NOTES 2864 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is 2865 * either set to TRUE, or removed depending on whether the browser is deemed 2866 * to be integrated. 2867 */ 2868 DWORD WINAPI WhichPlatform(void) 2869 { 2870 static const char szIntegratedBrowser[] = "IntegratedBrowser"; 2871 static DWORD dwState = 0; 2872 HKEY hKey; 2873 DWORD dwRet, dwData, dwSize; 2874 HMODULE hshell32; 2875 2876 if (dwState) 2877 return dwState; 2878 2879 /* If shell32 exports DllGetVersion(), the browser is integrated */ 2880 dwState = 1; 2881 hshell32 = LoadLibraryA("shell32.dll"); 2882 if (hshell32) 2883 { 2884 FARPROC pDllGetVersion; 2885 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion"); 2886 dwState = pDllGetVersion ? 2 : 1; 2887 FreeLibrary(hshell32); 2888 } 2889 2890 /* Set or delete the key accordingly */ 2891 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE, 2892 "Software\\Microsoft\\Internet Explorer", 0, 2893 KEY_ALL_ACCESS, &hKey); 2894 if (!dwRet) 2895 { 2896 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0, 2897 (LPBYTE)&dwData, &dwSize); 2898 2899 if (!dwRet && dwState == 1) 2900 { 2901 /* Value exists but browser is not integrated */ 2902 RegDeleteValueA(hKey, szIntegratedBrowser); 2903 } 2904 else if (dwRet && dwState == 2) 2905 { 2906 /* Browser is integrated but value does not exist */ 2907 dwData = TRUE; 2908 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD, 2909 (LPBYTE)&dwData, sizeof(dwData)); 2910 } 2911 RegCloseKey(hKey); 2912 } 2913 return dwState; 2914 } 2915 2916 /************************************************************************* 2917 * @ [SHLWAPI.278] 2918 * 2919 * Unicode version of SHCreateWorkerWindowA. 2920 */ 2921 HWND WINAPI SHCreateWorkerWindowW(WNDPROC wndProc, HWND hWndParent, DWORD dwExStyle, 2922 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra) 2923 { 2924 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 }; 2925 WNDCLASSW wc; 2926 HWND hWnd; 2927 2928 TRACE("(%p, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n", 2929 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra); 2930 2931 /* If our OS is natively ANSI, use the ANSI version */ 2932 if (GetVersion() & 0x80000000) /* not NT */ 2933 { 2934 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion()); 2935 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra); 2936 } 2937 2938 /* Create Window class */ 2939 wc.style = 0; 2940 wc.lpfnWndProc = DefWindowProcW; 2941 wc.cbClsExtra = 0; 2942 wc.cbWndExtra = sizeof(LONG_PTR); 2943 wc.hInstance = shlwapi_hInstance; 2944 wc.hIcon = NULL; 2945 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW); 2946 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1); 2947 wc.lpszMenuName = NULL; 2948 wc.lpszClassName = szClass; 2949 2950 SHRegisterClassW(&wc); 2951 2952 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0, 2953 hWndParent, hMenu, shlwapi_hInstance, 0); 2954 if (hWnd) 2955 { 2956 SetWindowLongPtrW(hWnd, 0, wnd_extra); 2957 if (wndProc) SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)wndProc); 2958 } 2959 2960 return hWnd; 2961 } 2962 2963 /************************************************************************* 2964 * @ [SHLWAPI.279] 2965 * 2966 * Get and show a context menu from a shell folder. 2967 * 2968 * PARAMS 2969 * hWnd [I] Window displaying the shell folder 2970 * lpFolder [I] IShellFolder interface 2971 * lpApidl [I] Id for the particular folder desired 2972 * 2973 * RETURNS 2974 * Success: S_OK. 2975 * Failure: An HRESULT error code indicating the error. 2976 */ 2977 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl) 2978 { 2979 TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl); 2980 return SHInvokeCommand(hWnd, lpFolder, lpApidl, 0); 2981 } 2982 2983 /************************************************************************* 2984 * @ [SHLWAPI.281] 2985 * 2986 * _SHPackDispParamsV 2987 */ 2988 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist) 2989 { 2990 VARIANTARG *iter; 2991 2992 TRACE("(%p %p %u ...)\n", params, args, cnt); 2993 2994 params->rgvarg = args; 2995 params->rgdispidNamedArgs = NULL; 2996 params->cArgs = cnt; 2997 params->cNamedArgs = 0; 2998 2999 iter = args+cnt; 3000 3001 while(iter-- > args) { 3002 V_VT(iter) = va_arg(valist, enum VARENUM); 3003 3004 TRACE("vt=%d\n", V_VT(iter)); 3005 3006 if(V_VT(iter) & VT_BYREF) { 3007 V_BYREF(iter) = va_arg(valist, LPVOID); 3008 } else { 3009 switch(V_VT(iter)) { 3010 case VT_I4: 3011 V_I4(iter) = va_arg(valist, LONG); 3012 break; 3013 case VT_BSTR: 3014 V_BSTR(iter) = va_arg(valist, BSTR); 3015 break; 3016 case VT_DISPATCH: 3017 V_DISPATCH(iter) = va_arg(valist, IDispatch*); 3018 break; 3019 case VT_BOOL: 3020 V_BOOL(iter) = va_arg(valist, int); 3021 break; 3022 case VT_UNKNOWN: 3023 V_UNKNOWN(iter) = va_arg(valist, IUnknown*); 3024 break; 3025 default: 3026 V_VT(iter) = VT_I4; 3027 V_I4(iter) = va_arg(valist, LONG); 3028 } 3029 } 3030 } 3031 3032 return S_OK; 3033 } 3034 3035 /************************************************************************* 3036 * @ [SHLWAPI.282] 3037 * 3038 * SHPackDispParams 3039 */ 3040 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...) 3041 { 3042 __ms_va_list valist; 3043 HRESULT hres; 3044 3045 __ms_va_start(valist, cnt); 3046 hres = SHPackDispParamsV(params, args, cnt, valist); 3047 __ms_va_end(valist); 3048 return hres; 3049 } 3050 3051 /************************************************************************* 3052 * SHLWAPI_InvokeByIID 3053 * 3054 * This helper function calls IDispatch::Invoke for each sink 3055 * which implements given iid or IDispatch. 3056 * 3057 */ 3058 static HRESULT SHLWAPI_InvokeByIID( 3059 IConnectionPoint* iCP, 3060 REFIID iid, 3061 DISPID dispId, 3062 DISPPARAMS* dispParams) 3063 { 3064 IEnumConnections *enumerator; 3065 CONNECTDATA rgcd; 3066 static DISPPARAMS empty = {NULL, NULL, 0, 0}; 3067 DISPPARAMS* params = dispParams; 3068 3069 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator); 3070 if (FAILED(result)) 3071 return result; 3072 3073 /* Invoke is never happening with an NULL dispParams */ 3074 if (!params) 3075 params = ∅ 3076 3077 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK) 3078 { 3079 IDispatch *dispIface; 3080 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) || 3081 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface))) 3082 { 3083 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL); 3084 IDispatch_Release(dispIface); 3085 } 3086 IUnknown_Release(rgcd.pUnk); 3087 } 3088 3089 IEnumConnections_Release(enumerator); 3090 3091 return S_OK; 3092 } 3093 3094 /************************************************************************* 3095 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283] 3096 */ 3097 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP, 3098 DISPID dispId, DISPPARAMS* dispParams, 3099 DWORD unknown1, DWORD unknown2 ) 3100 { 3101 IID iid; 3102 HRESULT result; 3103 3104 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2); 3105 3106 result = IConnectionPoint_GetConnectionInterface(iCP, &iid); 3107 if (SUCCEEDED(result)) 3108 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams); 3109 else 3110 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams); 3111 3112 return result; 3113 } 3114 3115 3116 /************************************************************************* 3117 * @ [SHLWAPI.284] 3118 * 3119 * IConnectionPoint_SimpleInvoke 3120 */ 3121 HRESULT WINAPI IConnectionPoint_SimpleInvoke( 3122 IConnectionPoint* iCP, 3123 DISPID dispId, 3124 DISPPARAMS* dispParams) 3125 { 3126 IID iid; 3127 HRESULT result; 3128 3129 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams); 3130 3131 result = IConnectionPoint_GetConnectionInterface(iCP, &iid); 3132 if (SUCCEEDED(result)) 3133 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams); 3134 else 3135 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams); 3136 3137 return result; 3138 } 3139 3140 /************************************************************************* 3141 * @ [SHLWAPI.285] 3142 * 3143 * Notify an IConnectionPoint object of changes. 3144 * 3145 * PARAMS 3146 * lpCP [I] Object to notify 3147 * dispID [I] 3148 * 3149 * RETURNS 3150 * Success: S_OK. 3151 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the 3152 * IConnectionPoint interface. 3153 */ 3154 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID) 3155 { 3156 IEnumConnections *lpEnum; 3157 HRESULT hRet = E_NOINTERFACE; 3158 3159 TRACE("(%p,0x%8X)\n", lpCP, dispID); 3160 3161 /* Get an enumerator for the connections */ 3162 if (lpCP) 3163 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum); 3164 3165 if (SUCCEEDED(hRet)) 3166 { 3167 IPropertyNotifySink *lpSink; 3168 CONNECTDATA connData; 3169 ULONG ulFetched; 3170 3171 /* Call OnChanged() for every notify sink in the connection point */ 3172 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK) 3173 { 3174 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) && 3175 lpSink) 3176 { 3177 IPropertyNotifySink_OnChanged(lpSink, dispID); 3178 IPropertyNotifySink_Release(lpSink); 3179 } 3180 IUnknown_Release(connData.pUnk); 3181 } 3182 3183 IEnumConnections_Release(lpEnum); 3184 } 3185 return hRet; 3186 } 3187 3188 /************************************************************************* 3189 * @ [SHLWAPI.286] 3190 * 3191 * IUnknown_CPContainerInvokeParam 3192 */ 3193 HRESULT WINAPIV IUnknown_CPContainerInvokeParam( 3194 IUnknown *container, 3195 REFIID riid, 3196 DISPID dispId, 3197 VARIANTARG* buffer, 3198 DWORD cParams, ...) 3199 { 3200 HRESULT result; 3201 IConnectionPoint *iCP; 3202 IConnectionPointContainer *iCPC; 3203 DISPPARAMS dispParams = {buffer, NULL, cParams, 0}; 3204 __ms_va_list valist; 3205 3206 if (!container) 3207 return E_NOINTERFACE; 3208 3209 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC); 3210 if (FAILED(result)) 3211 return result; 3212 3213 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP); 3214 IConnectionPointContainer_Release(iCPC); 3215 if(FAILED(result)) 3216 return result; 3217 3218 __ms_va_start(valist, cParams); 3219 SHPackDispParamsV(&dispParams, buffer, cParams, valist); 3220 __ms_va_end(valist); 3221 3222 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams); 3223 IConnectionPoint_Release(iCP); 3224 3225 return result; 3226 } 3227 3228 /************************************************************************* 3229 * @ [SHLWAPI.287] 3230 * 3231 * Notify an IConnectionPointContainer object of changes. 3232 * 3233 * PARAMS 3234 * lpUnknown [I] Object to notify 3235 * dispID [I] 3236 * 3237 * RETURNS 3238 * Success: S_OK. 3239 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the 3240 * IConnectionPointContainer interface. 3241 */ 3242 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID) 3243 { 3244 IConnectionPointContainer* lpCPC = NULL; 3245 HRESULT hRet = E_NOINTERFACE; 3246 3247 TRACE("(%p,0x%8X)\n", lpUnknown, dispID); 3248 3249 if (lpUnknown) 3250 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC); 3251 3252 if (SUCCEEDED(hRet)) 3253 { 3254 IConnectionPoint* lpCP; 3255 3256 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP); 3257 IConnectionPointContainer_Release(lpCPC); 3258 3259 hRet = IConnectionPoint_OnChanged(lpCP, dispID); 3260 IConnectionPoint_Release(lpCP); 3261 } 3262 return hRet; 3263 } 3264 3265 /************************************************************************* 3266 * @ [SHLWAPI.289] 3267 * 3268 * See PlaySoundW. 3269 */ 3270 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound) 3271 { 3272 return PlaySoundW(pszSound, hmod, fdwSound); 3273 } 3274 3275 #ifndef __REACTOS__ /* See propbag.cpp */ 3276 /************************************************************************* 3277 * @ [SHLWAPI.294] 3278 * 3279 * Retrieve a key value from an INI file. See GetPrivateProfileString for 3280 * more information. 3281 * 3282 * PARAMS 3283 * appName [I] The section in the INI file that contains the key 3284 * keyName [I] The key to be retrieved 3285 * out [O] The buffer into which the key's value will be copied 3286 * outLen [I] The length of the `out' buffer 3287 * filename [I] The location of the INI file 3288 * 3289 * RETURNS 3290 * Length of string copied into `out'. 3291 */ 3292 DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out, 3293 DWORD outLen, LPCWSTR filename) 3294 { 3295 INT ret; 3296 WCHAR *buf; 3297 3298 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName), debugstr_w(keyName), 3299 out, outLen, debugstr_w(filename)); 3300 3301 if(outLen == 0) 3302 return 0; 3303 3304 buf = HeapAlloc(GetProcessHeap(), 0, outLen * sizeof(WCHAR)); 3305 if(!buf){ 3306 *out = 0; 3307 return 0; 3308 } 3309 3310 ret = GetPrivateProfileStringW(appName, keyName, NULL, buf, outLen, filename); 3311 if(ret) 3312 strcpyW(out, buf); 3313 else 3314 *out = 0; 3315 3316 HeapFree(GetProcessHeap(), 0, buf); 3317 3318 return strlenW(out); 3319 } 3320 #endif 3321 3322 #ifndef __REACTOS__ /* See propbag.cpp */ 3323 /************************************************************************* 3324 * @ [SHLWAPI.295] 3325 * 3326 * Set a key value in an INI file. See WritePrivateProfileString for 3327 * more information. 3328 * 3329 * PARAMS 3330 * appName [I] The section in the INI file that contains the key 3331 * keyName [I] The key to be set 3332 * str [O] The value of the key 3333 * filename [I] The location of the INI file 3334 * 3335 * RETURNS 3336 * Success: TRUE 3337 * Failure: FALSE 3338 */ 3339 BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str, 3340 LPCWSTR filename) 3341 { 3342 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str), 3343 debugstr_w(filename)); 3344 3345 return WritePrivateProfileStringW(appName, keyName, str, filename); 3346 } 3347 #endif 3348 3349 /************************************************************************* 3350 * @ [SHLWAPI.313] 3351 * 3352 * See SHGetFileInfoW. 3353 */ 3354 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes, 3355 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags) 3356 { 3357 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags); 3358 } 3359 3360 /************************************************************************* 3361 * @ [SHLWAPI.318] 3362 * 3363 * See DragQueryFileW. 3364 */ 3365 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength) 3366 { 3367 return DragQueryFileW(hDrop, lFile, lpszFile, lLength); 3368 } 3369 3370 /************************************************************************* 3371 * @ [SHLWAPI.333] 3372 * 3373 * See SHBrowseForFolderW. 3374 */ 3375 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi) 3376 { 3377 return SHBrowseForFolderW(lpBi); 3378 } 3379 3380 /************************************************************************* 3381 * @ [SHLWAPI.334] 3382 * 3383 * See SHGetPathFromIDListW. 3384 */ 3385 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath) 3386 { 3387 return SHGetPathFromIDListW(pidl, pszPath); 3388 } 3389 3390 /************************************************************************* 3391 * @ [SHLWAPI.335] 3392 * 3393 * See ShellExecuteExW. 3394 */ 3395 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo) 3396 { 3397 return ShellExecuteExW(lpExecInfo); 3398 } 3399 3400 /************************************************************************* 3401 * @ [SHLWAPI.336] 3402 * 3403 * See SHFileOperationW. 3404 */ 3405 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp) 3406 { 3407 return SHFileOperationW(lpFileOp); 3408 } 3409 3410 /************************************************************************* 3411 * @ [SHLWAPI.342] 3412 * 3413 */ 3414 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare ) 3415 { 3416 return InterlockedCompareExchangePointer( dest, xchg, compare ); 3417 } 3418 3419 /************************************************************************* 3420 * @ [SHLWAPI.350] 3421 * 3422 * See GetFileVersionInfoSizeW. 3423 */ 3424 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle ) 3425 { 3426 return GetFileVersionInfoSizeW( filename, handle ); 3427 } 3428 3429 /************************************************************************* 3430 * @ [SHLWAPI.351] 3431 * 3432 * See GetFileVersionInfoW. 3433 */ 3434 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle, 3435 DWORD datasize, LPVOID data ) 3436 { 3437 return GetFileVersionInfoW( filename, handle, datasize, data ); 3438 } 3439 3440 /************************************************************************* 3441 * @ [SHLWAPI.352] 3442 * 3443 * See VerQueryValueW. 3444 */ 3445 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock, 3446 LPVOID *lplpBuffer, UINT *puLen ) 3447 { 3448 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen ); 3449 } 3450 3451 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj))) 3452 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB 3453 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless) 3454 3455 /************************************************************************* 3456 * @ [SHLWAPI.355] 3457 * 3458 * Change the modality of a shell object. 3459 * 3460 * PARAMS 3461 * lpUnknown [I] Object to make modeless 3462 * bModeless [I] TRUE=Make modeless, FALSE=Make modal 3463 * 3464 * RETURNS 3465 * Success: S_OK. The modality lpUnknown is changed. 3466 * Failure: An HRESULT error code indicating the error. 3467 * 3468 * NOTES 3469 * lpUnknown must support the IOleInPlaceFrame interface, the 3470 * IInternetSecurityMgrSite interface, the IShellBrowser interface 3471 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface, 3472 * or this call will fail. 3473 */ 3474 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless) 3475 { 3476 IUnknown *lpObj; 3477 HRESULT hRet; 3478 3479 TRACE("(%p,%d)\n", lpUnknown, bModeless); 3480 3481 if (!lpUnknown) 3482 return E_FAIL; 3483 3484 if (IsIface(IOleInPlaceActiveObject)) 3485 EnableModeless(IOleInPlaceActiveObject); 3486 else if (IsIface(IOleInPlaceFrame)) 3487 EnableModeless(IOleInPlaceFrame); 3488 else if (IsIface(IShellBrowser)) 3489 EnableModeless(IShellBrowser); 3490 else if (IsIface(IInternetSecurityMgrSite)) 3491 EnableModeless(IInternetSecurityMgrSite); 3492 else if (IsIface(IDocHostUIHandler)) 3493 EnableModeless(IDocHostUIHandler); 3494 else 3495 return hRet; 3496 3497 IUnknown_Release(lpObj); 3498 return S_OK; 3499 } 3500 3501 /************************************************************************* 3502 * @ [SHLWAPI.357] 3503 * 3504 * See SHGetNewLinkInfoW. 3505 */ 3506 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName, 3507 BOOL *pfMustCopy, UINT uFlags) 3508 { 3509 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags); 3510 } 3511 3512 /************************************************************************* 3513 * @ [SHLWAPI.358] 3514 * 3515 * See SHDefExtractIconW. 3516 */ 3517 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge, 3518 HICON* phiconSmall, UINT nIconSize) 3519 { 3520 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize); 3521 } 3522 3523 /************************************************************************* 3524 * @ [SHLWAPI.363] 3525 * 3526 * Get and show a context menu from a shell folder. 3527 * 3528 * PARAMS 3529 * hWnd [I] Window displaying the shell folder 3530 * lpFolder [I] IShellFolder interface 3531 * lpApidl [I] Id for the particular folder desired 3532 * dwCommandId [I] The command ID to invoke (0=invoke default) 3533 * 3534 * RETURNS 3535 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was 3536 * executed. 3537 * Failure: An HRESULT error code indicating the error. 3538 */ 3539 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, DWORD dwCommandId) 3540 { 3541 IContextMenu *iContext; 3542 HRESULT hRet; 3543 3544 TRACE("(%p, %p, %p, %u)\n", hWnd, lpFolder, lpApidl, dwCommandId); 3545 3546 if (!lpFolder) 3547 return E_FAIL; 3548 3549 /* Get the context menu from the shell folder */ 3550 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl, 3551 &IID_IContextMenu, 0, (void**)&iContext); 3552 if (SUCCEEDED(hRet)) 3553 { 3554 HMENU hMenu; 3555 if ((hMenu = CreatePopupMenu())) 3556 { 3557 HRESULT hQuery; 3558 3559 /* Add the context menu entries to the popup */ 3560 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF, 3561 dwCommandId ? CMF_NORMAL : CMF_DEFAULTONLY); 3562 3563 if (SUCCEEDED(hQuery)) 3564 { 3565 if (!dwCommandId) 3566 dwCommandId = GetMenuDefaultItem(hMenu, 0, 0); 3567 if (dwCommandId != (UINT)-1) 3568 { 3569 CMINVOKECOMMANDINFO cmIci; 3570 /* Invoke the default item */ 3571 memset(&cmIci,0,sizeof(cmIci)); 3572 cmIci.cbSize = sizeof(cmIci); 3573 cmIci.fMask = CMIC_MASK_ASYNCOK; 3574 cmIci.hwnd = hWnd; 3575 #ifdef __REACTOS__ /* r75561 */ 3576 cmIci.lpVerb = MAKEINTRESOURCEA(dwCommandId - 1); 3577 #else 3578 cmIci.lpVerb = MAKEINTRESOURCEA(dwCommandId); 3579 #endif 3580 cmIci.nShow = SW_SHOWNORMAL; 3581 3582 hRet = IContextMenu_InvokeCommand(iContext, &cmIci); 3583 } 3584 } 3585 DestroyMenu(hMenu); 3586 } 3587 IContextMenu_Release(iContext); 3588 } 3589 return hRet; 3590 } 3591 3592 /************************************************************************* 3593 * @ [SHLWAPI.370] 3594 * 3595 * See ExtractIconW. 3596 */ 3597 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName, 3598 UINT nIconIndex) 3599 { 3600 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex); 3601 } 3602 3603 /************************************************************************* 3604 * @ [SHLWAPI.377] 3605 * 3606 * Load a library from the directory of a particular process. 3607 * 3608 * PARAMS 3609 * new_mod [I] Library name 3610 * inst_hwnd [I] Module whose directory is to be used 3611 * dwCrossCodePage [I] Should be FALSE (currently ignored) 3612 * 3613 * RETURNS 3614 * Success: A handle to the loaded module 3615 * Failure: A NULL handle. 3616 */ 3617 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage) 3618 { 3619 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for 3620 * each call here. 3621 * FIXME: Native shows calls to: 3622 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International" 3623 * CheckVersion 3624 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer" 3625 * RegQueryValueExA for "LPKInstalled" 3626 * RegCloseKey 3627 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International" 3628 * RegQueryValueExA for "ResourceLocale" 3629 * RegCloseKey 3630 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}" 3631 * RegQueryValueExA for "Locale" 3632 * RegCloseKey 3633 * and then tests the Locale ("en" for me). 3634 * code below 3635 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done. 3636 */ 3637 CHAR mod_path[2*MAX_PATH]; 3638 LPSTR ptr; 3639 DWORD len; 3640 3641 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage); 3642 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path)); 3643 if (!len || len >= sizeof(mod_path)) return NULL; 3644 3645 ptr = strrchr(mod_path, '\\'); 3646 if (ptr) { 3647 strcpy(ptr+1, new_mod); 3648 TRACE("loading %s\n", debugstr_a(mod_path)); 3649 return LoadLibraryA(mod_path); 3650 } 3651 return NULL; 3652 } 3653 3654 /************************************************************************* 3655 * @ [SHLWAPI.378] 3656 * 3657 * Unicode version of MLLoadLibraryA. 3658 */ 3659 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage) 3660 { 3661 WCHAR mod_path[2*MAX_PATH]; 3662 LPWSTR ptr; 3663 DWORD len; 3664 3665 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage); 3666 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR)); 3667 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL; 3668 3669 ptr = strrchrW(mod_path, '\\'); 3670 if (ptr) { 3671 strcpyW(ptr+1, new_mod); 3672 TRACE("loading %s\n", debugstr_w(mod_path)); 3673 return LoadLibraryW(mod_path); 3674 } 3675 return NULL; 3676 } 3677 3678 /************************************************************************* 3679 * ColorAdjustLuma [SHLWAPI.@] 3680 * 3681 * Adjust the luminosity of a color 3682 * 3683 * PARAMS 3684 * cRGB [I] RGB value to convert 3685 * dwLuma [I] Luma adjustment 3686 * bUnknown [I] Unknown 3687 * 3688 * RETURNS 3689 * The adjusted RGB color. 3690 */ 3691 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown) 3692 { 3693 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown); 3694 3695 if (dwLuma) 3696 { 3697 WORD wH, wL, wS; 3698 3699 ColorRGBToHLS(cRGB, &wH, &wL, &wS); 3700 3701 FIXME("Ignoring luma adjustment\n"); 3702 3703 /* FIXME: The adjustment is not linear */ 3704 3705 cRGB = ColorHLSToRGB(wH, wL, wS); 3706 } 3707 return cRGB; 3708 } 3709 3710 /************************************************************************* 3711 * @ [SHLWAPI.389] 3712 * 3713 * See GetSaveFileNameW. 3714 */ 3715 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn) 3716 { 3717 return GetSaveFileNameW(ofn); 3718 } 3719 3720 /************************************************************************* 3721 * @ [SHLWAPI.390] 3722 * 3723 * See WNetRestoreConnectionW. 3724 */ 3725 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice) 3726 { 3727 return WNetRestoreConnectionW(hwndOwner, lpszDevice); 3728 } 3729 3730 /************************************************************************* 3731 * @ [SHLWAPI.391] 3732 * 3733 * See WNetGetLastErrorW. 3734 */ 3735 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize, 3736 LPWSTR lpNameBuf, DWORD nNameBufSize) 3737 { 3738 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize); 3739 } 3740 3741 /************************************************************************* 3742 * @ [SHLWAPI.401] 3743 * 3744 * See PageSetupDlgW. 3745 */ 3746 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg) 3747 { 3748 return PageSetupDlgW(pagedlg); 3749 } 3750 3751 /************************************************************************* 3752 * @ [SHLWAPI.402] 3753 * 3754 * See PrintDlgW. 3755 */ 3756 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg) 3757 { 3758 return PrintDlgW(printdlg); 3759 } 3760 3761 /************************************************************************* 3762 * @ [SHLWAPI.403] 3763 * 3764 * See GetOpenFileNameW. 3765 */ 3766 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn) 3767 { 3768 return GetOpenFileNameW(ofn); 3769 } 3770 3771 /************************************************************************* 3772 * @ [SHLWAPI.404] 3773 */ 3774 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum) 3775 { 3776 /* Windows attempts to get an IPersist interface and, if that fails, an 3777 * IPersistFolder interface on the folder passed-in here. If one of those 3778 * interfaces is available, it then calls GetClassID on the folder... and 3779 * then calls IShellFolder_EnumObjects no matter what, even crashing if 3780 * lpFolder isn't actually an IShellFolder object. The purpose of getting 3781 * the ClassID is unknown, so we don't do it here. 3782 * 3783 * For discussion and detailed tests, see: 3784 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated" 3785 * wine-devel mailing list, 3 Jun 2010 3786 */ 3787 3788 return IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum); 3789 } 3790 3791 /* INTERNAL: Map from HLS color space to RGB */ 3792 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2) 3793 { 3794 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue; 3795 3796 if (wHue > 160) 3797 return wMid1; 3798 else if (wHue > 120) 3799 wHue = 160 - wHue; 3800 else if (wHue > 40) 3801 return wMid2; 3802 3803 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1; 3804 } 3805 3806 /* Convert to RGB and scale into RGB range (0..255) */ 3807 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240 3808 3809 /************************************************************************* 3810 * ColorHLSToRGB [SHLWAPI.@] 3811 * 3812 * Convert from hls color space into an rgb COLORREF. 3813 * 3814 * PARAMS 3815 * wHue [I] Hue amount 3816 * wLuminosity [I] Luminosity amount 3817 * wSaturation [I] Saturation amount 3818 * 3819 * RETURNS 3820 * A COLORREF representing the converted color. 3821 * 3822 * NOTES 3823 * Input hls values are constrained to the range (0..240). 3824 */ 3825 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation) 3826 { 3827 WORD wRed; 3828 3829 if (wSaturation) 3830 { 3831 WORD wGreen, wBlue, wMid1, wMid2; 3832 3833 if (wLuminosity > 120) 3834 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240; 3835 else 3836 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240; 3837 3838 wMid1 = wLuminosity * 2 - wMid2; 3839 3840 wRed = GET_RGB(wHue + 80); 3841 wGreen = GET_RGB(wHue); 3842 wBlue = GET_RGB(wHue - 80); 3843 3844 return RGB(wRed, wGreen, wBlue); 3845 } 3846 3847 wRed = wLuminosity * 255 / 240; 3848 return RGB(wRed, wRed, wRed); 3849 } 3850 3851 /************************************************************************* 3852 * @ [SHLWAPI.413] 3853 * 3854 * Get the current docking status of the system. 3855 * 3856 * PARAMS 3857 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused 3858 * 3859 * RETURNS 3860 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not 3861 * a notebook. 3862 */ 3863 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags) 3864 { 3865 HW_PROFILE_INFOA hwInfo; 3866 3867 TRACE("(0x%08x)\n", dwFlags); 3868 3869 GetCurrentHwProfileA(&hwInfo); 3870 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED)) 3871 { 3872 case DOCKINFO_DOCKED: 3873 case DOCKINFO_UNDOCKED: 3874 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED); 3875 default: 3876 return 0; 3877 } 3878 } 3879 3880 /************************************************************************* 3881 * @ [SHLWAPI.416] 3882 * 3883 */ 3884 DWORD WINAPI SHWinHelpOnDemandW(HWND hwnd, LPCWSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2) 3885 { 3886 3887 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_w(helpfile), flags1, ptr1, flags2); 3888 return 0; 3889 } 3890 3891 /************************************************************************* 3892 * @ [SHLWAPI.417] 3893 * 3894 */ 3895 DWORD WINAPI SHWinHelpOnDemandA(HWND hwnd, LPCSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2) 3896 { 3897 3898 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_a(helpfile), flags1, ptr1, flags2); 3899 return 0; 3900 } 3901 3902 /************************************************************************* 3903 * @ [SHLWAPI.418] 3904 * 3905 * Function seems to do FreeLibrary plus other things. 3906 * 3907 * FIXME native shows the following calls: 3908 * RtlEnterCriticalSection 3909 * LocalFree 3910 * GetProcAddress(Comctl32??, 150L) 3911 * DPA_DeletePtr 3912 * RtlLeaveCriticalSection 3913 * followed by the FreeLibrary. 3914 * The above code may be related to .377 above. 3915 */ 3916 BOOL WINAPI MLFreeLibrary(HMODULE hModule) 3917 { 3918 FIXME("(%p) semi-stub\n", hModule); 3919 return FreeLibrary(hModule); 3920 } 3921 3922 /************************************************************************* 3923 * @ [SHLWAPI.419] 3924 */ 3925 BOOL WINAPI SHFlushSFCacheWrap(void) { 3926 FIXME(": stub\n"); 3927 return TRUE; 3928 } 3929 3930 /************************************************************************* 3931 * @ [SHLWAPI.429] 3932 * FIXME I have no idea what this function does or what its arguments are. 3933 */ 3934 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst) 3935 { 3936 FIXME("(%p) stub\n", hInst); 3937 return FALSE; 3938 } 3939 3940 3941 /************************************************************************* 3942 * @ [SHLWAPI.430] 3943 */ 3944 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap) 3945 { 3946 FIXME("(%p,%p) stub\n", hInst, hHeap); 3947 return E_FAIL; /* This is what is used if shlwapi not loaded */ 3948 } 3949 3950 /************************************************************************* 3951 * @ [SHLWAPI.431] 3952 */ 3953 DWORD WINAPI MLClearMLHInstance(DWORD x) 3954 { 3955 FIXME("(0x%08x)stub\n", x); 3956 return 0xabba1247; 3957 } 3958 3959 /************************************************************************* 3960 * @ [SHLWAPI.432] 3961 * 3962 * See SHSendMessageBroadcastW 3963 * 3964 */ 3965 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam) 3966 { 3967 return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam, 3968 SMTO_ABORTIFHUNG, 2000, NULL); 3969 } 3970 3971 /************************************************************************* 3972 * @ [SHLWAPI.433] 3973 * 3974 * A wrapper for sending Broadcast Messages to all top level Windows 3975 * 3976 */ 3977 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam) 3978 { 3979 return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam, 3980 SMTO_ABORTIFHUNG, 2000, NULL); 3981 } 3982 3983 /************************************************************************* 3984 * @ [SHLWAPI.436] 3985 * 3986 * Convert a Unicode string CLSID into a CLSID. 3987 * 3988 * PARAMS 3989 * idstr [I] string containing a CLSID in text form 3990 * id [O] CLSID extracted from the string 3991 * 3992 * RETURNS 3993 * S_OK on success or E_INVALIDARG on failure 3994 */ 3995 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id) 3996 { 3997 return CLSIDFromString((LPCOLESTR)idstr, id); 3998 } 3999 4000 /************************************************************************* 4001 * @ [SHLWAPI.437] 4002 * 4003 * Determine if the OS supports a given feature. 4004 * 4005 * PARAMS 4006 * dwFeature [I] Feature requested (undocumented) 4007 * 4008 * RETURNS 4009 * TRUE If the feature is available. 4010 * FALSE If the feature is not available. 4011 */ 4012 BOOL WINAPI IsOS(DWORD feature) 4013 { 4014 OSVERSIONINFOA osvi; 4015 DWORD platform, majorv, minorv; 4016 4017 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); 4018 if(!GetVersionExA(&osvi)) { 4019 ERR("GetVersionEx failed\n"); 4020 return FALSE; 4021 } 4022 4023 majorv = osvi.dwMajorVersion; 4024 minorv = osvi.dwMinorVersion; 4025 platform = osvi.dwPlatformId; 4026 4027 #define ISOS_RETURN(x) \ 4028 TRACE("(0x%x) ret=%d\n",feature,(x)); \ 4029 return (x); 4030 4031 switch(feature) { 4032 case OS_WIN32SORGREATER: 4033 ISOS_RETURN(platform == VER_PLATFORM_WIN32s 4034 || platform == VER_PLATFORM_WIN32_WINDOWS) 4035 case OS_NT: 4036 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4037 case OS_WIN95ORGREATER: 4038 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS) 4039 case OS_NT4ORGREATER: 4040 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4) 4041 case OS_WIN2000ORGREATER_ALT: 4042 case OS_WIN2000ORGREATER: 4043 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5) 4044 case OS_WIN98ORGREATER: 4045 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10) 4046 case OS_WIN98_GOLD: 4047 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10) 4048 case OS_WIN2000PRO: 4049 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5) 4050 case OS_WIN2000SERVER: 4051 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1)) 4052 case OS_WIN2000ADVSERVER: 4053 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1)) 4054 case OS_WIN2000DATACENTER: 4055 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1)) 4056 case OS_WIN2000TERMINAL: 4057 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1)) 4058 case OS_EMBEDDED: 4059 FIXME("(OS_EMBEDDED) What should we return here?\n"); 4060 return FALSE; 4061 case OS_TERMINALCLIENT: 4062 FIXME("(OS_TERMINALCLIENT) What should we return here?\n"); 4063 return FALSE; 4064 case OS_TERMINALREMOTEADMIN: 4065 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n"); 4066 return FALSE; 4067 case OS_WIN95_GOLD: 4068 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0) 4069 case OS_MEORGREATER: 4070 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90) 4071 case OS_XPORGREATER: 4072 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1) 4073 case OS_HOME: 4074 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1) 4075 case OS_PROFESSIONAL: 4076 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4077 case OS_DATACENTER: 4078 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4079 case OS_ADVSERVER: 4080 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5) 4081 case OS_SERVER: 4082 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4083 case OS_TERMINALSERVER: 4084 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4085 case OS_PERSONALTERMINALSERVER: 4086 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5) 4087 case OS_FASTUSERSWITCHING: 4088 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n"); 4089 return TRUE; 4090 case OS_WELCOMELOGONUI: 4091 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n"); 4092 return FALSE; 4093 case OS_DOMAINMEMBER: 4094 FIXME("(OS_DOMAINMEMBER) What should we return here?\n"); 4095 return TRUE; 4096 case OS_ANYSERVER: 4097 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4098 case OS_WOW6432: 4099 { 4100 BOOL is_wow64; 4101 IsWow64Process(GetCurrentProcess(), &is_wow64); 4102 return is_wow64; 4103 } 4104 case OS_WEBSERVER: 4105 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4106 case OS_SMALLBUSINESSSERVER: 4107 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 4108 case OS_TABLETPC: 4109 FIXME("(OS_TABLETPC) What should we return here?\n"); 4110 return FALSE; 4111 case OS_SERVERADMINUI: 4112 FIXME("(OS_SERVERADMINUI) What should we return here?\n"); 4113 return FALSE; 4114 case OS_MEDIACENTER: 4115 FIXME("(OS_MEDIACENTER) What should we return here?\n"); 4116 return FALSE; 4117 case OS_APPLIANCE: 4118 FIXME("(OS_APPLIANCE) What should we return here?\n"); 4119 return FALSE; 4120 case 0x25: /*OS_VISTAORGREATER*/ 4121 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6) 4122 } 4123 4124 #undef ISOS_RETURN 4125 4126 WARN("(0x%x) unknown parameter\n",feature); 4127 4128 return FALSE; 4129 } 4130 4131 #ifdef __REACTOS__ 4132 /************************************************************************* 4133 * @ [SHLWAPI.438] 4134 */ 4135 HRESULT WINAPI SHLoadRegUIStringA(HKEY hkey, LPCSTR value, LPSTR buf, DWORD size) 4136 { 4137 WCHAR valueW[MAX_PATH], bufferW[MAX_PATH]; 4138 DWORD dwSize = ARRAY_SIZE(bufferW) * sizeof(CHAR); 4139 HRESULT hr; 4140 4141 MultiByteToWideChar(CP_ACP, 0, value, -1, valueW, ARRAY_SIZE(valueW)); 4142 valueW[ARRAY_SIZE(valueW) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ 4143 4144 if (RegQueryValueExW(hkey, valueW, NULL, NULL, (LPBYTE)bufferW, &dwSize) != ERROR_SUCCESS) 4145 return E_FAIL; 4146 4147 hr = SHLoadIndirectString(bufferW, bufferW, ARRAY_SIZE(bufferW), NULL); 4148 if (FAILED(hr)) 4149 return hr; 4150 4151 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buf, size, NULL, NULL); 4152 if (size > 0) 4153 buf[size - 1] = ANSI_NULL; /* Avoid buffer overrun */ 4154 return S_OK; 4155 } 4156 #endif 4157 4158 /************************************************************************* 4159 * @ [SHLWAPI.439] 4160 */ 4161 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size) 4162 { 4163 DWORD type, sz = size * sizeof(WCHAR); 4164 4165 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS) 4166 return E_FAIL; 4167 4168 return SHLoadIndirectString(buf, buf, size, NULL); 4169 } 4170 4171 /************************************************************************* 4172 * @ [SHLWAPI.478] 4173 * 4174 * Call IInputObject_TranslateAcceleratorIO() on an object. 4175 * 4176 * PARAMS 4177 * lpUnknown [I] Object supporting the IInputObject interface. 4178 * lpMsg [I] Key message to be processed. 4179 * 4180 * RETURNS 4181 * Success: S_OK. 4182 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL. 4183 */ 4184 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg) 4185 { 4186 IInputObject* lpInput = NULL; 4187 HRESULT hRet = E_INVALIDARG; 4188 4189 TRACE("(%p,%p)\n", lpUnknown, lpMsg); 4190 if (lpUnknown) 4191 { 4192 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject, 4193 (void**)&lpInput); 4194 if (SUCCEEDED(hRet) && lpInput) 4195 { 4196 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg); 4197 IInputObject_Release(lpInput); 4198 } 4199 } 4200 return hRet; 4201 } 4202 4203 /************************************************************************* 4204 * @ [SHLWAPI.481] 4205 * 4206 * Call IInputObject_HasFocusIO() on an object. 4207 * 4208 * PARAMS 4209 * lpUnknown [I] Object supporting the IInputObject interface. 4210 * 4211 * RETURNS 4212 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus, 4213 * or S_FALSE otherwise. 4214 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL. 4215 */ 4216 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown) 4217 { 4218 IInputObject* lpInput = NULL; 4219 HRESULT hRet = E_INVALIDARG; 4220 4221 TRACE("(%p)\n", lpUnknown); 4222 if (lpUnknown) 4223 { 4224 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject, 4225 (void**)&lpInput); 4226 if (SUCCEEDED(hRet) && lpInput) 4227 { 4228 hRet = IInputObject_HasFocusIO(lpInput); 4229 IInputObject_Release(lpInput); 4230 } 4231 } 4232 return hRet; 4233 } 4234 4235 /************************************************************************* 4236 * ColorRGBToHLS [SHLWAPI.@] 4237 * 4238 * Convert an rgb COLORREF into the hls color space. 4239 * 4240 * PARAMS 4241 * cRGB [I] Source rgb value 4242 * pwHue [O] Destination for converted hue 4243 * pwLuminance [O] Destination for converted luminance 4244 * pwSaturation [O] Destination for converted saturation 4245 * 4246 * RETURNS 4247 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted 4248 * values. 4249 * 4250 * NOTES 4251 * Output HLS values are constrained to the range (0..240). 4252 * For Achromatic conversions, Hue is set to 160. 4253 */ 4254 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue, 4255 LPWORD pwLuminance, LPWORD pwSaturation) 4256 { 4257 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation; 4258 4259 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation); 4260 4261 wR = GetRValue(cRGB); 4262 wG = GetGValue(cRGB); 4263 wB = GetBValue(cRGB); 4264 4265 wMax = max(wR, max(wG, wB)); 4266 wMin = min(wR, min(wG, wB)); 4267 4268 /* Luminosity */ 4269 wLuminosity = ((wMax + wMin) * 240 + 255) / 510; 4270 4271 if (wMax == wMin) 4272 { 4273 /* Achromatic case */ 4274 wSaturation = 0; 4275 /* Hue is now unrepresentable, but this is what native returns... */ 4276 wHue = 160; 4277 } 4278 else 4279 { 4280 /* Chromatic case */ 4281 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm; 4282 4283 /* Saturation */ 4284 if (wLuminosity <= 120) 4285 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin); 4286 else 4287 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin); 4288 4289 /* Hue */ 4290 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta; 4291 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta; 4292 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta; 4293 4294 if (wR == wMax) 4295 wHue = wBNorm - wGNorm; 4296 else if (wG == wMax) 4297 wHue = 80 + wRNorm - wBNorm; 4298 else 4299 wHue = 160 + wGNorm - wRNorm; 4300 if (wHue < 0) 4301 wHue += 240; 4302 else if (wHue > 240) 4303 wHue -= 240; 4304 } 4305 if (pwHue) 4306 *pwHue = wHue; 4307 if (pwLuminance) 4308 *pwLuminance = wLuminosity; 4309 if (pwSaturation) 4310 *pwSaturation = wSaturation; 4311 } 4312 4313 /************************************************************************* 4314 * SHCreateShellPalette [SHLWAPI.@] 4315 */ 4316 HPALETTE WINAPI SHCreateShellPalette(HDC hdc) 4317 { 4318 FIXME("stub\n"); 4319 return CreateHalftonePalette(hdc); 4320 } 4321 4322 /************************************************************************* 4323 * SHGetInverseCMAP (SHLWAPI.@) 4324 * 4325 * Get an inverse color map table. 4326 * 4327 * PARAMS 4328 * lpCmap [O] Destination for color map 4329 * dwSize [I] Size of memory pointed to by lpCmap 4330 * 4331 * RETURNS 4332 * Success: S_OK. 4333 * Failure: E_POINTER, If lpCmap is invalid. 4334 * E_INVALIDARG, If dwFlags is invalid 4335 * E_OUTOFMEMORY, If there is no memory available 4336 * 4337 * NOTES 4338 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192). 4339 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's 4340 * internal CMap. 4341 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from 4342 * this DLL's internal CMap. 4343 */ 4344 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize) 4345 { 4346 if (dwSize == 4) { 4347 FIXME(" - returning bogus address for SHGetInverseCMAP\n"); 4348 *dest = (DWORD)0xabba1249; 4349 return 0; 4350 } 4351 FIXME("(%p, %#x) stub\n", dest, dwSize); 4352 return 0; 4353 } 4354 4355 /************************************************************************* 4356 * SHIsLowMemoryMachine [SHLWAPI.@] 4357 * 4358 * Determine if the current computer has low memory. 4359 * 4360 * PARAMS 4361 * dwType [I] Zero. 4362 * 4363 * RETURNS 4364 * TRUE if the users machine has 16 Megabytes of memory or less, 4365 * FALSE otherwise. 4366 */ 4367 BOOL WINAPI SHIsLowMemoryMachine(DWORD dwType) 4368 { 4369 #ifdef __REACTOS__ 4370 MEMORYSTATUS status; 4371 static int is_low = -1; 4372 TRACE("(0x%08x)\n", dwType); 4373 if (dwType == 0 && is_low == -1) 4374 { 4375 GlobalMemoryStatus(&status); 4376 is_low = (status.dwTotalPhys <= 0x1000000); 4377 } 4378 return is_low; 4379 #else 4380 FIXME("(0x%08x) stub\n", dwType); 4381 return FALSE; 4382 #endif 4383 } 4384 4385 /************************************************************************* 4386 * GetMenuPosFromID [SHLWAPI.@] 4387 * 4388 * Return the position of a menu item from its Id. 4389 * 4390 * PARAMS 4391 * hMenu [I] Menu containing the item 4392 * wID [I] Id of the menu item 4393 * 4394 * RETURNS 4395 * Success: The index of the menu item in hMenu. 4396 * Failure: -1, If the item is not found. 4397 */ 4398 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID) 4399 { 4400 MENUITEMINFOW mi; 4401 INT nCount = GetMenuItemCount(hMenu), nIter = 0; 4402 4403 TRACE("%p %u\n", hMenu, wID); 4404 4405 while (nIter < nCount) 4406 { 4407 mi.cbSize = sizeof(mi); 4408 mi.fMask = MIIM_ID; 4409 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID) 4410 { 4411 TRACE("ret %d\n", nIter); 4412 return nIter; 4413 } 4414 nIter++; 4415 } 4416 4417 return -1; 4418 } 4419 4420 /************************************************************************* 4421 * @ [SHLWAPI.179] 4422 * 4423 * Same as SHLWAPI.GetMenuPosFromID 4424 */ 4425 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID) 4426 { 4427 TRACE("%p %u\n", hMenu, uID); 4428 return GetMenuPosFromID(hMenu, uID); 4429 } 4430 4431 4432 /************************************************************************* 4433 * @ [SHLWAPI.448] 4434 */ 4435 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr) 4436 { 4437 while (*lpwstr) 4438 { 4439 if (*lpwstr == '/') 4440 *lpwstr = '\\'; 4441 lpwstr++; 4442 } 4443 } 4444 4445 4446 /************************************************************************* 4447 * @ [SHLWAPI.461] 4448 */ 4449 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown) 4450 { 4451 FIXME("(0x%08x) stub\n", dwUnknown); 4452 return 0; 4453 } 4454 4455 4456 /************************************************************************* 4457 * @ [SHLWAPI.549] 4458 */ 4459 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter, 4460 DWORD dwClsContext, REFIID iid, LPVOID *ppv) 4461 { 4462 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv); 4463 } 4464 4465 /************************************************************************* 4466 * SHSkipJunction [SHLWAPI.@] 4467 * 4468 * Determine if a bind context can be bound to an object 4469 * 4470 * PARAMS 4471 * pbc [I] Bind context to check 4472 * pclsid [I] CLSID of object to be bound to 4473 * 4474 * RETURNS 4475 * TRUE: If it is safe to bind 4476 * FALSE: If pbc is invalid or binding would not be safe 4477 * 4478 */ 4479 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid) 4480 { 4481 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ', 4482 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' }; 4483 BOOL bRet = FALSE; 4484 4485 if (pbc) 4486 { 4487 IUnknown* lpUnk; 4488 4489 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk))) 4490 { 4491 CLSID clsid; 4492 4493 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) && 4494 IsEqualGUID(pclsid, &clsid)) 4495 bRet = TRUE; 4496 4497 IUnknown_Release(lpUnk); 4498 } 4499 } 4500 return bRet; 4501 } 4502 4503 /*********************************************************************** 4504 * SHGetShellKey (SHLWAPI.491) 4505 */ 4506 HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create) 4507 { 4508 #ifndef __REACTOS__ 4509 enum _shellkey_flags { 4510 SHKEY_Root_HKCU = 0x1, 4511 SHKEY_Root_HKLM = 0x2, 4512 SHKEY_Key_Explorer = 0x00, 4513 SHKEY_Key_Shell = 0x10, 4514 SHKEY_Key_ShellNoRoam = 0x20, 4515 SHKEY_Key_Classes = 0x30, 4516 SHKEY_Subkey_Default = 0x0000, 4517 SHKEY_Subkey_ResourceName = 0x1000, 4518 SHKEY_Subkey_Handlers = 0x2000, 4519 SHKEY_Subkey_Associations = 0x3000, 4520 SHKEY_Subkey_Volatile = 0x4000, 4521 SHKEY_Subkey_MUICache = 0x5000, 4522 SHKEY_Subkey_FileExts = 0x6000 4523 }; 4524 #endif 4525 4526 static const WCHAR explorerW[] = {'S','o','f','t','w','a','r','e','\\', 4527 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', 4528 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 4529 'E','x','p','l','o','r','e','r','\\'}; 4530 static const WCHAR shellW[] = {'S','o','f','t','w','a','r','e','\\', 4531 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', 4532 'S','h','e','l','l','\\'}; 4533 static const WCHAR shell_no_roamW[] = {'S','o','f','t','w','a','r','e','\\', 4534 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\', 4535 'S','h','e','l','l','N','o','R','o','a','m','\\'}; 4536 static const WCHAR classesW[] = {'S','o','f','t','w','a','r','e','\\', 4537 'C','l','a','s','s','e','s','\\'}; 4538 4539 static const WCHAR localized_resource_nameW[] = {'L','o','c','a','l','i','z','e','d', 4540 'R','e','s','o','u','r','c','e','N','a','m','e','\\'}; 4541 static const WCHAR handlersW[] = {'H','a','n','d','l','e','r','s','\\'}; 4542 static const WCHAR associationsW[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'}; 4543 static const WCHAR volatileW[] = {'V','o','l','a','t','i','l','e','\\'}; 4544 static const WCHAR mui_cacheW[] = {'M','U','I','C','a','c','h','e','\\'}; 4545 static const WCHAR file_extsW[] = {'F','i','l','e','E','x','t','s','\\'}; 4546 4547 WCHAR *path; 4548 const WCHAR *key, *subkey; 4549 int size_key, size_subkey, size_user; 4550 HKEY hkey = NULL; 4551 4552 TRACE("(0x%08x, %s, %d)\n", flags, debugstr_w(sub_key), create); 4553 4554 /* For compatibility with Vista+ */ 4555 if(flags == 0x1ffff) 4556 flags = 0x21; 4557 4558 switch(flags&0xff0) { 4559 case SHKEY_Key_Explorer: 4560 key = explorerW; 4561 size_key = sizeof(explorerW); 4562 break; 4563 case SHKEY_Key_Shell: 4564 key = shellW; 4565 size_key = sizeof(shellW); 4566 break; 4567 case SHKEY_Key_ShellNoRoam: 4568 key = shell_no_roamW; 4569 size_key = sizeof(shell_no_roamW); 4570 break; 4571 case SHKEY_Key_Classes: 4572 key = classesW; 4573 size_key = sizeof(classesW); 4574 break; 4575 default: 4576 FIXME("unsupported flags (0x%08x)\n", flags); 4577 return NULL; 4578 } 4579 4580 switch(flags&0xff000) { 4581 case SHKEY_Subkey_Default: 4582 subkey = NULL; 4583 size_subkey = 0; 4584 break; 4585 case SHKEY_Subkey_ResourceName: 4586 subkey = localized_resource_nameW; 4587 size_subkey = sizeof(localized_resource_nameW); 4588 break; 4589 case SHKEY_Subkey_Handlers: 4590 subkey = handlersW; 4591 size_subkey = sizeof(handlersW); 4592 break; 4593 case SHKEY_Subkey_Associations: 4594 subkey = associationsW; 4595 size_subkey = sizeof(associationsW); 4596 break; 4597 case SHKEY_Subkey_Volatile: 4598 subkey = volatileW; 4599 size_subkey = sizeof(volatileW); 4600 break; 4601 case SHKEY_Subkey_MUICache: 4602 subkey = mui_cacheW; 4603 size_subkey = sizeof(mui_cacheW); 4604 break; 4605 case SHKEY_Subkey_FileExts: 4606 subkey = file_extsW; 4607 size_subkey = sizeof(file_extsW); 4608 break; 4609 default: 4610 FIXME("unsupported flags (0x%08x)\n", flags); 4611 return NULL; 4612 } 4613 4614 if(sub_key) 4615 size_user = lstrlenW(sub_key)*sizeof(WCHAR); 4616 else 4617 size_user = 0; 4618 4619 path = HeapAlloc(GetProcessHeap(), 0, size_key+size_subkey+size_user+sizeof(WCHAR)); 4620 if(!path) { 4621 ERR("Out of memory\n"); 4622 return NULL; 4623 } 4624 4625 memcpy(path, key, size_key); 4626 if(subkey) 4627 memcpy(path+size_key/sizeof(WCHAR), subkey, size_subkey); 4628 if(sub_key) 4629 memcpy(path+(size_key+size_subkey)/sizeof(WCHAR), sub_key, size_user); 4630 path[(size_key+size_subkey+size_user)/sizeof(WCHAR)] = '\0'; 4631 4632 if(create) 4633 RegCreateKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, 4634 path, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &hkey, NULL); 4635 else 4636 RegOpenKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, 4637 path, 0, MAXIMUM_ALLOWED, &hkey); 4638 4639 HeapFree(GetProcessHeap(), 0, path); 4640 return hkey; 4641 } 4642 4643 /*********************************************************************** 4644 * SHQueueUserWorkItem (SHLWAPI.@) 4645 */ 4646 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback, 4647 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag, 4648 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags) 4649 { 4650 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext, 4651 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags); 4652 4653 if(lPriority || dwTag || pdwId || pszModule || dwFlags) 4654 FIXME("Unsupported arguments\n"); 4655 4656 return QueueUserWorkItem(pfnCallback, pContext, 0); 4657 } 4658 4659 /*********************************************************************** 4660 * SHSetTimerQueueTimer (SHLWAPI.263) 4661 */ 4662 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue, 4663 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime, 4664 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags) 4665 { 4666 HANDLE hNewTimer; 4667 4668 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */ 4669 if (dwFlags & TPS_LONGEXECTIME) { 4670 dwFlags &= ~TPS_LONGEXECTIME; 4671 dwFlags |= WT_EXECUTELONGFUNCTION; 4672 } 4673 if (dwFlags & TPS_EXECUTEIO) { 4674 dwFlags &= ~TPS_EXECUTEIO; 4675 dwFlags |= WT_EXECUTEINIOTHREAD; 4676 } 4677 4678 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext, 4679 dwDueTime, dwPeriod, dwFlags)) 4680 return NULL; 4681 4682 return hNewTimer; 4683 } 4684 4685 /*********************************************************************** 4686 * IUnknown_OnFocusChangeIS (SHLWAPI.@) 4687 */ 4688 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus) 4689 { 4690 IInputObjectSite *pIOS = NULL; 4691 HRESULT hRet = E_INVALIDARG; 4692 4693 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE"); 4694 4695 if (lpUnknown) 4696 { 4697 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite, 4698 (void **)&pIOS); 4699 if (SUCCEEDED(hRet) && pIOS) 4700 { 4701 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus); 4702 IInputObjectSite_Release(pIOS); 4703 } 4704 } 4705 return hRet; 4706 } 4707 4708 /*********************************************************************** 4709 * SKAllocValueW (SHLWAPI.519) 4710 */ 4711 HRESULT WINAPI SKAllocValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type, 4712 LPVOID *data, DWORD *count) 4713 { 4714 DWORD ret, size; 4715 HKEY hkey; 4716 4717 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey), 4718 debugstr_w(value), type, data, count); 4719 4720 hkey = SHGetShellKey(flags, subkey, FALSE); 4721 if (!hkey) 4722 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 4723 4724 ret = SHQueryValueExW(hkey, value, NULL, type, NULL, &size); 4725 if (ret) { 4726 RegCloseKey(hkey); 4727 return HRESULT_FROM_WIN32(ret); 4728 } 4729 4730 size += 2; 4731 *data = LocalAlloc(0, size); 4732 if (!*data) { 4733 RegCloseKey(hkey); 4734 return E_OUTOFMEMORY; 4735 } 4736 4737 ret = SHQueryValueExW(hkey, value, NULL, type, *data, &size); 4738 if (count) 4739 *count = size; 4740 4741 RegCloseKey(hkey); 4742 return HRESULT_FROM_WIN32(ret); 4743 } 4744 4745 /*********************************************************************** 4746 * SKDeleteValueW (SHLWAPI.518) 4747 */ 4748 HRESULT WINAPI SKDeleteValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value) 4749 { 4750 DWORD ret; 4751 HKEY hkey; 4752 4753 TRACE("(0x%x, %s %s)\n", flags, debugstr_w(subkey), debugstr_w(value)); 4754 4755 hkey = SHGetShellKey(flags, subkey, FALSE); 4756 if (!hkey) 4757 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 4758 4759 ret = RegDeleteValueW(hkey, value); 4760 4761 RegCloseKey(hkey); 4762 return HRESULT_FROM_WIN32(ret); 4763 } 4764 4765 /*********************************************************************** 4766 * SKGetValueW (SHLWAPI.516) 4767 */ 4768 HRESULT WINAPI SKGetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type, 4769 void *data, DWORD *count) 4770 { 4771 DWORD ret; 4772 HKEY hkey; 4773 4774 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey), 4775 debugstr_w(value), type, data, count); 4776 4777 hkey = SHGetShellKey(flags, subkey, FALSE); 4778 if (!hkey) 4779 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 4780 4781 ret = SHQueryValueExW(hkey, value, NULL, type, data, count); 4782 4783 RegCloseKey(hkey); 4784 return HRESULT_FROM_WIN32(ret); 4785 } 4786 4787 /*********************************************************************** 4788 * SKSetValueW (SHLWAPI.516) 4789 */ 4790 HRESULT WINAPI SKSetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, 4791 DWORD type, void *data, DWORD count) 4792 { 4793 DWORD ret; 4794 HKEY hkey; 4795 4796 TRACE("(0x%x, %s, %s, %x, %p, %d)\n", flags, debugstr_w(subkey), 4797 debugstr_w(value), type, data, count); 4798 4799 hkey = SHGetShellKey(flags, subkey, TRUE); 4800 if (!hkey) 4801 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); 4802 4803 ret = RegSetValueExW(hkey, value, 0, type, data, count); 4804 4805 RegCloseKey(hkey); 4806 return HRESULT_FROM_WIN32(ret); 4807 } 4808 4809 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *); 4810 4811 /*********************************************************************** 4812 * GetUIVersion (SHLWAPI.452) 4813 */ 4814 DWORD WINAPI GetUIVersion(void) 4815 { 4816 static DWORD version; 4817 4818 if (!version) 4819 { 4820 DllGetVersion_func pDllGetVersion; 4821 HMODULE dll = LoadLibraryA("shell32.dll"); 4822 if (!dll) return 0; 4823 4824 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion"); 4825 if (pDllGetVersion) 4826 { 4827 DLLVERSIONINFO dvi; 4828 dvi.cbSize = sizeof(DLLVERSIONINFO); 4829 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion; 4830 } 4831 FreeLibrary( dll ); 4832 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */ 4833 } 4834 return version; 4835 } 4836 4837 /*********************************************************************** 4838 * ShellMessageBoxWrapW [SHLWAPI.388] 4839 * 4840 * See shell32.ShellMessageBoxW 4841 * 4842 #ifndef __REACTOS__ 4843 * 4844 * NOTE: 4845 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW 4846 * because we can't forward to it in the .spec file since it's exported by 4847 * ordinal. If you change the implementation here please update the code in 4848 * shell32 as well. 4849 * 4850 #else // __REACTOS__ 4851 * 4852 * From Vista+ onwards, all the implementation of ShellMessageBoxA/W that 4853 * were existing in shell32 has been completely moved to shlwapi, so that 4854 * shell32.ShellMessageBoxA and shell32.ShellMessageBoxW are redirections 4855 * to the corresponding shlwapi functions. 4856 * 4857 * For Win2003 compatibility, if you change the implementation here please 4858 * update the code of ShellMessageBoxA in shell32 as well. 4859 * 4860 #endif 4861 */ 4862 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText, 4863 LPCWSTR lpCaption, UINT uType, ...) 4864 { 4865 WCHAR *szText = NULL, szTitle[100]; 4866 LPCWSTR pszText, pszTitle = szTitle; 4867 LPWSTR pszTemp; 4868 __ms_va_list args; 4869 int ret; 4870 4871 __ms_va_start(args, uType); 4872 4873 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType); 4874 4875 if (IS_INTRESOURCE(lpCaption)) 4876 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, ARRAY_SIZE(szTitle)); 4877 else 4878 pszTitle = lpCaption; 4879 4880 if (IS_INTRESOURCE(lpText)) 4881 { 4882 const WCHAR *ptr; 4883 UINT len = LoadStringW(hInstance, LOWORD(lpText), (LPWSTR)&ptr, 0); 4884 4885 if (len) 4886 { 4887 szText = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR)); 4888 if (szText) LoadStringW(hInstance, LOWORD(lpText), szText, len + 1); 4889 } 4890 pszText = szText; 4891 if (!pszText) { 4892 WARN("Failed to load id %d\n", LOWORD(lpText)); 4893 __ms_va_end(args); 4894 return 0; 4895 } 4896 } 4897 else 4898 pszText = lpText; 4899 4900 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, 4901 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args); 4902 4903 __ms_va_end(args); 4904 4905 #ifdef __REACTOS__ 4906 uType |= MB_SETFOREGROUND; 4907 #endif 4908 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType); 4909 4910 HeapFree(GetProcessHeap(), 0, szText); 4911 LocalFree(pszTemp); 4912 return ret; 4913 } 4914 4915 /*********************************************************************** 4916 * ZoneComputePaneSize [SHLWAPI.382] 4917 */ 4918 UINT WINAPI ZoneComputePaneSize(HWND hwnd) 4919 { 4920 FIXME("\n"); 4921 return 0x95; 4922 } 4923 4924 /*********************************************************************** 4925 * SHChangeNotifyWrap [SHLWAPI.394] 4926 */ 4927 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2) 4928 { 4929 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2); 4930 } 4931 4932 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */ 4933 SID_IDENTIFIER_AUTHORITY sidAuthority; 4934 DWORD dwUserGroupID; 4935 DWORD dwUserID; 4936 } SHELL_USER_SID, *PSHELL_USER_SID; 4937 4938 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */ 4939 SHELL_USER_SID susID; 4940 DWORD dwAccessType; 4941 BOOL fInherit; 4942 DWORD dwAccessMask; 4943 DWORD dwInheritMask; 4944 DWORD dwInheritAccessMask; 4945 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION; 4946 4947 /*********************************************************************** 4948 * GetShellSecurityDescriptor [SHLWAPI.475] 4949 * 4950 * prepares SECURITY_DESCRIPTOR from a set of ACEs 4951 * 4952 * PARAMS 4953 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures, 4954 * each of which describes permissions to apply 4955 * cUserPerm [I] number of entries in apUserPerm array 4956 * 4957 * RETURNS 4958 * success: pointer to SECURITY_DESCRIPTOR 4959 * failure: NULL 4960 * 4961 * NOTES 4962 * Call should free returned descriptor with LocalFree 4963 */ 4964 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(const PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm) 4965 { 4966 PSID *sidlist; 4967 PSID cur_user = NULL; 4968 BYTE tuUser[2000]; 4969 DWORD acl_size; 4970 int sid_count, i; 4971 PSECURITY_DESCRIPTOR psd = NULL; 4972 4973 TRACE("%p %d\n", apUserPerm, cUserPerm); 4974 4975 if (apUserPerm == NULL || cUserPerm <= 0) 4976 return NULL; 4977 4978 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID)); 4979 if (!sidlist) 4980 return NULL; 4981 4982 acl_size = sizeof(ACL); 4983 4984 for(sid_count = 0; sid_count < cUserPerm; sid_count++) 4985 { 4986 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0}; 4987 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count]; 4988 PSHELL_USER_SID sid = &perm->susID; 4989 PSID pSid; 4990 BOOL ret = TRUE; 4991 4992 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID))) 4993 { /* current user's SID */ 4994 if (!cur_user) 4995 { 4996 HANDLE Token; 4997 DWORD bufsize = sizeof(tuUser); 4998 4999 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token); 5000 if (ret) 5001 { 5002 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize ); 5003 if (ret) 5004 cur_user = ((PTOKEN_USER)tuUser)->User.Sid; 5005 CloseHandle(Token); 5006 } 5007 } 5008 pSid = cur_user; 5009 } else if (sid->dwUserID==0) /* one sub-authority */ 5010 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0, 5011 0, 0, 0, 0, 0, 0, &pSid); 5012 else 5013 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID, 5014 0, 0, 0, 0, 0, 0, &pSid); 5015 if (!ret) 5016 goto free_sids; 5017 5018 sidlist[sid_count] = pSid; 5019 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */ 5020 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1); 5021 } 5022 5023 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size); 5024 5025 if (psd != NULL) 5026 { 5027 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR)); 5028 5029 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)) 5030 goto error; 5031 5032 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION)) 5033 goto error; 5034 5035 for(i = 0; i < sid_count; i++) 5036 { 5037 PSHELL_USER_PERMISSION sup = apUserPerm[i]; 5038 PSID sid = sidlist[i]; 5039 5040 switch(sup->dwAccessType) 5041 { 5042 case ACCESS_ALLOWED_ACE_TYPE: 5043 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid)) 5044 goto error; 5045 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION, 5046 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid)) 5047 goto error; 5048 break; 5049 case ACCESS_DENIED_ACE_TYPE: 5050 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid)) 5051 goto error; 5052 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION, 5053 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid)) 5054 goto error; 5055 break; 5056 default: 5057 goto error; 5058 } 5059 } 5060 5061 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE)) 5062 goto error; 5063 } 5064 goto free_sids; 5065 5066 error: 5067 LocalFree(psd); 5068 psd = NULL; 5069 free_sids: 5070 for(i = 0; i < sid_count; i++) 5071 { 5072 if (!cur_user || sidlist[i] != cur_user) 5073 FreeSid(sidlist[i]); 5074 } 5075 HeapFree(GetProcessHeap(), 0, sidlist); 5076 5077 return psd; 5078 } 5079 5080 #ifndef __REACTOS__ /* See propbag.cpp */ 5081 /*********************************************************************** 5082 * SHCreatePropertyBagOnRegKey [SHLWAPI.471] 5083 * 5084 * Creates a property bag from a registry key 5085 * 5086 * PARAMS 5087 * hKey [I] Handle to the desired registry key 5088 * subkey [I] Name of desired subkey, or NULL to open hKey directly 5089 * grfMode [I] Optional flags 5090 * riid [I] IID of requested property bag interface 5091 * ppv [O] Address to receive pointer to the new interface 5092 * 5093 * RETURNS 5094 * success: 0 5095 * failure: error code 5096 * 5097 */ 5098 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey, 5099 DWORD grfMode, REFIID riid, void **ppv) 5100 { 5101 FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode, 5102 debugstr_guid(riid), ppv); 5103 5104 return E_NOTIMPL; 5105 } 5106 #endif 5107 5108 #ifndef __REACTOS__ /* See propbag.cpp */ 5109 /*********************************************************************** 5110 * SHGetViewStatePropertyBag [SHLWAPI.515] 5111 * 5112 * Retrieves a property bag in which the view state information of a folder 5113 * can be stored. 5114 * 5115 * PARAMS 5116 * pidl [I] PIDL of the folder requested 5117 * bag_name [I] Name of the property bag requested 5118 * flags [I] Optional flags 5119 * riid [I] IID of requested property bag interface 5120 * ppv [O] Address to receive pointer to the new interface 5121 * 5122 * RETURNS 5123 * success: S_OK 5124 * failure: error code 5125 * 5126 */ 5127 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name, 5128 DWORD flags, REFIID riid, void **ppv) 5129 { 5130 FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags, 5131 debugstr_guid(riid), ppv); 5132 5133 return E_NOTIMPL; 5134 } 5135 #endif 5136 5137 /*********************************************************************** 5138 * SHFormatDateTimeW [SHLWAPI.354] 5139 * 5140 * Produces a string representation of a time. 5141 * 5142 * PARAMS 5143 * fileTime [I] Pointer to FILETIME structure specifying the time 5144 * flags [I] Flags specifying the desired output 5145 * buf [O] Pointer to buffer for output 5146 * size [I] Number of characters that can be contained in buffer 5147 * 5148 * RETURNS 5149 * success: number of characters written to the buffer 5150 * failure: 0 5151 * 5152 */ 5153 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags, 5154 LPWSTR buf, UINT size) 5155 { 5156 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER) 5157 DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT; 5158 SYSTEMTIME st; 5159 FILETIME ft; 5160 INT ret = 0; 5161 5162 TRACE("%p %p %p %u\n", fileTime, flags, buf, size); 5163 5164 if (!buf || !size) 5165 return 0; 5166 5167 if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS) 5168 FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS); 5169 5170 FileTimeToLocalFileTime(fileTime, &ft); 5171 FileTimeToSystemTime(&ft, &st); 5172 5173 /* first of all date */ 5174 if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE)) 5175 { 5176 static const WCHAR sep1[] = {',',' ',0}; 5177 static const WCHAR sep2[] = {' ',0}; 5178 5179 DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE; 5180 ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size); 5181 if (ret >= size) return ret; 5182 5183 /* add separator */ 5184 if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))) 5185 { 5186 if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2)) 5187 { 5188 lstrcatW(&buf[ret-1], sep1); 5189 ret += 2; 5190 } 5191 else 5192 { 5193 lstrcatW(&buf[ret-1], sep2); 5194 ret++; 5195 } 5196 } 5197 } 5198 /* time part */ 5199 if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)) 5200 { 5201 DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS; 5202 5203 if (ret) ret--; 5204 ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret); 5205 } 5206 5207 return ret; 5208 5209 #undef SHFORMATDT_UNSUPPORTED_FLAGS 5210 } 5211 5212 /*********************************************************************** 5213 * SHFormatDateTimeA [SHLWAPI.353] 5214 * 5215 * See SHFormatDateTimeW. 5216 * 5217 */ 5218 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags, 5219 LPSTR buf, UINT size) 5220 { 5221 WCHAR *bufW; 5222 INT retval; 5223 5224 if (!buf || !size) 5225 return 0; 5226 5227 bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size); 5228 retval = SHFormatDateTimeW(fileTime, flags, bufW, size); 5229 5230 if (retval != 0) 5231 WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL); 5232 5233 HeapFree(GetProcessHeap(), 0, bufW); 5234 return retval; 5235 } 5236 5237 /*********************************************************************** 5238 * ZoneCheckUrlExW [SHLWAPI.231] 5239 * 5240 * Checks the details of the security zone for the supplied site. (?) 5241 * 5242 * PARAMS 5243 * 5244 * szURL [I] Pointer to the URL to check 5245 * 5246 * Other parameters currently unknown. 5247 * 5248 * RETURNS 5249 * unknown 5250 */ 5251 5252 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2, 5253 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6, 5254 DWORD dwUnknown7) 5255 { 5256 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2, 5257 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7); 5258 5259 return 0; 5260 } 5261 5262 /*********************************************************************** 5263 * SHVerbExistsNA [SHLWAPI.196] 5264 * 5265 * 5266 * PARAMS 5267 * 5268 * verb [I] a string, often appears to be an extension. 5269 * 5270 * Other parameters currently unknown. 5271 * 5272 * RETURNS 5273 * unknown 5274 */ 5275 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3) 5276 { 5277 FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3); 5278 return 0; 5279 } 5280 5281 /************************************************************************* 5282 * @ [SHLWAPI.538] 5283 * 5284 * Undocumented: Implementation guessed at via Name and behavior 5285 * 5286 * PARAMS 5287 * lpUnknown [I] Object to get an IServiceProvider interface from 5288 * riid [I] Function requested for QueryService call 5289 * lppOut [O] Destination for the service interface pointer 5290 * 5291 * RETURNS 5292 * Success: S_OK. lppOut contains an object providing the requested service 5293 * Failure: An HRESULT error code 5294 * 5295 * NOTES 5296 * lpUnknown is expected to support the IServiceProvider interface. 5297 */ 5298 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown, 5299 REFGUID riid, LPVOID *lppOut) 5300 { 5301 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut); 5302 return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut); 5303 } 5304 5305 #ifdef __REACTOS__ 5306 HRESULT VariantChangeTypeForRead(_Inout_ VARIANTARG *pvarg, _In_ VARTYPE vt) 5307 { 5308 HRESULT hr; 5309 VARIANTARG vargTemp; 5310 VARIANT variTemp; 5311 5312 if (V_VT(pvarg) == vt || vt == VT_EMPTY) 5313 return S_OK; 5314 5315 vargTemp = *pvarg; 5316 5317 if (V_VT(&vargTemp) != VT_BSTR || vt <= VT_NULL) 5318 goto DoDefault; 5319 5320 if (vt == VT_I1 || vt == VT_I2 || vt == VT_I4) 5321 { 5322 if (!StrToIntExW(V_BSTR(&vargTemp), STIF_SUPPORT_HEX, &V_I4(&variTemp))) 5323 goto DoDefault; 5324 5325 V_VT(&variTemp) = VT_INT; 5326 VariantInit(pvarg); 5327 hr = VariantChangeType(pvarg, &variTemp, 0, vt); 5328 VariantClear(&vargTemp); 5329 return hr; 5330 } 5331 5332 if (vt <= VT_DECIMAL) 5333 goto DoDefault; 5334 5335 if (vt == VT_UI1 || vt == VT_UI2 || vt == VT_UI4) 5336 { 5337 if (!StrToIntExW(V_BSTR(&vargTemp), STIF_SUPPORT_HEX, (LPINT)&V_UI4(&variTemp))) 5338 goto DoDefault; 5339 5340 V_VT(&variTemp) = VT_UINT; 5341 VariantInit(pvarg); 5342 hr = VariantChangeType(pvarg, &variTemp, 0, vt); 5343 VariantClear(&vargTemp); 5344 return hr; 5345 } 5346 5347 if (vt == VT_INT || vt == VT_UINT) 5348 { 5349 if (!StrToIntExW(V_BSTR(&vargTemp), STIF_SUPPORT_HEX, &V_INT(&variTemp))) 5350 goto DoDefault; 5351 5352 V_VT(&variTemp) = VT_UINT; 5353 VariantInit(pvarg); 5354 hr = VariantChangeType(pvarg, &variTemp, 0, vt); 5355 VariantClear(&vargTemp); 5356 return hr; 5357 } 5358 5359 DoDefault: 5360 VariantInit(pvarg); 5361 hr = VariantChangeType(pvarg, &vargTemp, 0, vt); 5362 VariantClear(&vargTemp); 5363 return hr; 5364 } 5365 5366 BOOL 5367 VariantArrayToBuffer( 5368 _In_ const VARIANT *pvarIn, 5369 _Out_writes_(cbSize) LPVOID pvDest, 5370 _In_ SIZE_T cbSize) 5371 { 5372 LPVOID pvData; 5373 LONG LowerBound, UpperBound; 5374 LPSAFEARRAY pArray; 5375 5376 /* Only supports byte array */ 5377 if (!pvarIn || V_VT(pvarIn) != (VT_UI1 | VT_ARRAY)) 5378 return FALSE; 5379 5380 /* Boundary check and access */ 5381 pArray = V_ARRAY(pvarIn); 5382 if (SafeArrayGetDim(pArray) == 1 && 5383 SUCCEEDED(SafeArrayGetLBound(pArray, 1, &LowerBound)) && 5384 SUCCEEDED(SafeArrayGetUBound(pArray, 1, &UpperBound)) && 5385 ((LONG)cbSize <= UpperBound - LowerBound + 1) && 5386 SUCCEEDED(SafeArrayAccessData(pArray, &pvData))) 5387 { 5388 CopyMemory(pvDest, pvData, cbSize); 5389 SafeArrayUnaccessData(pArray); 5390 return TRUE; /* Success */ 5391 } 5392 5393 return FALSE; /* Failure */ 5394 } 5395 5396 /************************************************************************** 5397 * SHPropertyBag_ReadType (SHLWAPI.493) 5398 * 5399 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readtype.htm 5400 */ 5401 HRESULT WINAPI 5402 SHPropertyBag_ReadType(IPropertyBag *ppb, LPCWSTR pszPropName, VARIANTARG *pvarg, VARTYPE vt) 5403 { 5404 HRESULT hr; 5405 5406 VariantInit(pvarg); 5407 V_VT(pvarg) = vt; 5408 5409 hr = IPropertyBag_Read(ppb, pszPropName, pvarg, NULL); 5410 if (FAILED(hr)) 5411 { 5412 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5413 VariantInit(pvarg); 5414 return hr; 5415 } 5416 5417 return VariantChangeTypeForRead(pvarg, vt); 5418 } 5419 5420 /************************************************************************** 5421 * SHPropertyBag_ReadBOOL (SHLWAPI.534) 5422 * 5423 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readbool.htm 5424 */ 5425 HRESULT WINAPI SHPropertyBag_ReadBOOL(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL *pbValue) 5426 { 5427 HRESULT hr; 5428 VARIANTARG varg; 5429 5430 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pbValue); 5431 5432 if (!ppb || !pszPropName || !pbValue) 5433 { 5434 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pbValue); 5435 return E_INVALIDARG; 5436 } 5437 5438 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_BOOL); 5439 if (SUCCEEDED(hr)) 5440 *pbValue = (V_BOOL(&varg) == VARIANT_TRUE); 5441 5442 return hr; 5443 } 5444 5445 /************************************************************************** 5446 * SHPropertyBag_ReadBOOLOld (SHLWAPI.498) 5447 * 5448 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readboolold.htm 5449 */ 5450 BOOL WINAPI SHPropertyBag_ReadBOOLOld(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL bDefValue) 5451 { 5452 VARIANTARG varg; 5453 HRESULT hr; 5454 5455 TRACE("%p %s %d\n", ppb, debugstr_w(pszPropName), bDefValue); 5456 5457 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_BOOL); 5458 if (FAILED(hr)) 5459 return bDefValue; 5460 5461 return V_BOOL(&varg) == VARIANT_TRUE; 5462 } 5463 5464 /************************************************************************** 5465 * SHPropertyBag_ReadSHORT (SHLWAPI.527) 5466 * 5467 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readshort.htm 5468 */ 5469 HRESULT WINAPI SHPropertyBag_ReadSHORT(IPropertyBag *ppb, LPCWSTR pszPropName, SHORT *psValue) 5470 { 5471 HRESULT hr; 5472 VARIANTARG varg; 5473 5474 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), psValue); 5475 5476 if (!ppb || !pszPropName || !psValue) 5477 { 5478 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), psValue); 5479 return E_INVALIDARG; 5480 } 5481 5482 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_UI2); 5483 if (SUCCEEDED(hr)) 5484 *psValue = V_UI2(&varg); 5485 5486 return hr; 5487 } 5488 #endif 5489 5490 /************************************************************************** 5491 * SHPropertyBag_ReadLONG (SHLWAPI.496) 5492 * 5493 * This function asks a property bag to read a named property as a LONG. 5494 * 5495 * PARAMS 5496 * ppb: a IPropertyBag interface 5497 * pszPropName: Unicode string that names the property 5498 * pValue: address to receive the property value as a 32-bit signed integer 5499 * 5500 * RETURNS 5501 * HRESULT codes 5502 #ifdef __REACTOS__ 5503 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readlong.htm 5504 #endif 5505 */ 5506 HRESULT WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue) 5507 { 5508 #ifdef __REACTOS__ 5509 HRESULT hr; 5510 VARIANTARG varg; 5511 5512 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pValue); 5513 5514 if (!ppb || !pszPropName || !pValue) 5515 { 5516 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pValue); 5517 return E_INVALIDARG; 5518 } 5519 5520 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_I4); 5521 if (SUCCEEDED(hr)) 5522 *pValue = V_I4(&varg); 5523 #else 5524 VARIANT var; 5525 HRESULT hr; 5526 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue); 5527 if (!pszPropName || !ppb || !pValue) 5528 return E_INVALIDARG; 5529 V_VT(&var) = VT_I4; 5530 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL); 5531 if (SUCCEEDED(hr)) 5532 { 5533 if (V_VT(&var) == VT_I4) 5534 *pValue = V_I4(&var); 5535 else 5536 hr = DISP_E_BADVARTYPE; 5537 } 5538 #endif 5539 return hr; 5540 } 5541 5542 #ifdef __REACTOS__ 5543 /************************************************************************** 5544 * SHPropertyBag_ReadDWORD (SHLWAPI.507) 5545 * 5546 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readdword.htm 5547 */ 5548 HRESULT WINAPI SHPropertyBag_ReadDWORD(IPropertyBag *ppb, LPCWSTR pszPropName, DWORD *pdwValue) 5549 { 5550 HRESULT hr; 5551 VARIANTARG varg; 5552 5553 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pdwValue); 5554 5555 if (!ppb || !pszPropName || !pdwValue) 5556 { 5557 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pdwValue); 5558 return E_INVALIDARG; 5559 } 5560 5561 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_UI4); 5562 if (SUCCEEDED(hr)) 5563 *pdwValue = V_UI4(&varg); 5564 5565 return hr; 5566 } 5567 5568 /************************************************************************** 5569 * SHPropertyBag_ReadBSTR (SHLWAPI.520) 5570 * 5571 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readbstr.htm 5572 */ 5573 HRESULT WINAPI SHPropertyBag_ReadBSTR(IPropertyBag *ppb, LPCWSTR pszPropName, BSTR *pbstr) 5574 { 5575 HRESULT hr; 5576 VARIANTARG varg; 5577 5578 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pbstr); 5579 5580 if (!ppb || !pszPropName || !pbstr) 5581 { 5582 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pbstr); 5583 return E_INVALIDARG; 5584 } 5585 5586 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_BSTR); 5587 if (FAILED(hr)) 5588 *pbstr = NULL; 5589 else 5590 *pbstr = V_BSTR(&varg); 5591 5592 return hr; 5593 } 5594 5595 /************************************************************************** 5596 * SHPropertyBag_ReadStr (SHLWAPI.494) 5597 * 5598 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readstr.htm 5599 */ 5600 HRESULT WINAPI SHPropertyBag_ReadStr(IPropertyBag *ppb, LPCWSTR pszPropName, LPWSTR pszDst, int cchMax) 5601 { 5602 HRESULT hr; 5603 VARIANTARG varg; 5604 5605 TRACE("%p %s %p %d\n", ppb, debugstr_w(pszPropName), pszDst, cchMax); 5606 5607 if (!ppb || !pszPropName || !pszDst) 5608 { 5609 ERR("%p %s %p %d\n", ppb, debugstr_w(pszPropName), pszDst, cchMax); 5610 return E_INVALIDARG; 5611 } 5612 5613 hr = SHPropertyBag_ReadType(ppb, pszPropName, &varg, VT_BSTR); 5614 if (FAILED(hr)) 5615 return E_FAIL; 5616 5617 StrCpyNW(pszDst, V_BSTR(&varg), cchMax); 5618 VariantClear(&varg); 5619 return hr; 5620 } 5621 5622 /************************************************************************** 5623 * SHPropertyBag_ReadPOINTL (SHLWAPI.521) 5624 * 5625 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readpointl.htm 5626 */ 5627 HRESULT WINAPI SHPropertyBag_ReadPOINTL(IPropertyBag *ppb, LPCWSTR pszPropName, POINTL *pptl) 5628 { 5629 HRESULT hr; 5630 int cch, cch2; 5631 WCHAR *pch, szBuff[MAX_PATH]; 5632 5633 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pptl); 5634 5635 if (!ppb || !pszPropName || !pptl) 5636 { 5637 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pptl); 5638 return E_INVALIDARG; 5639 } 5640 5641 StrCpyNW(szBuff, pszPropName, _countof(szBuff)); 5642 5643 cch = lstrlenW(szBuff); 5644 cch2 = _countof(szBuff) - cch; 5645 if (cch2 < _countof(L".x")) 5646 { 5647 ERR("%s is too long\n", debugstr_w(pszPropName)); 5648 return E_FAIL; 5649 } 5650 5651 pch = &szBuff[cch]; 5652 5653 StrCpyNW(pch, L".x", cch2); 5654 hr = SHPropertyBag_ReadLONG(ppb, szBuff, &pptl->x); 5655 if (FAILED(hr)) 5656 return hr; 5657 5658 StrCpyNW(pch, L".y", cch2); 5659 return SHPropertyBag_ReadLONG(ppb, szBuff, &pptl->y); 5660 } 5661 5662 /************************************************************************** 5663 * SHPropertyBag_ReadPOINTS (SHLWAPI.525) 5664 * 5665 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readpoints.htm 5666 */ 5667 HRESULT WINAPI SHPropertyBag_ReadPOINTS(IPropertyBag *ppb, LPCWSTR pszPropName, POINTS *ppts) 5668 { 5669 HRESULT hr; 5670 POINTL ptl; 5671 5672 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), ppts); 5673 5674 if (!ppb || !pszPropName || !ppts) 5675 { 5676 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), ppts); 5677 return E_INVALIDARG; 5678 } 5679 5680 hr = SHPropertyBag_ReadPOINTL(ppb, pszPropName, &ptl); 5681 if (FAILED(hr)) 5682 return hr; 5683 5684 ppts->x = ptl.x; 5685 ppts->y = ptl.y; 5686 return hr; 5687 } 5688 5689 /************************************************************************** 5690 * SHPropertyBag_ReadRECTL (SHLWAPI.523) 5691 * 5692 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readrectl.htm 5693 */ 5694 HRESULT WINAPI SHPropertyBag_ReadRECTL(IPropertyBag *ppb, LPCWSTR pszPropName, RECTL *prcl) 5695 { 5696 HRESULT hr; 5697 int cch, cch2; 5698 WCHAR *pch, szBuff[MAX_PATH]; 5699 5700 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), prcl); 5701 5702 if (!ppb || !pszPropName || !prcl) 5703 { 5704 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), prcl); 5705 return E_INVALIDARG; 5706 } 5707 5708 StrCpyNW(szBuff, pszPropName, _countof(szBuff)); 5709 5710 cch = lstrlenW(szBuff); 5711 cch2 = _countof(szBuff) - cch; 5712 if (cch2 < _countof(L".bottom")) 5713 { 5714 ERR("%s is too long\n", debugstr_w(pszPropName)); 5715 return E_FAIL; 5716 } 5717 5718 pch = &szBuff[cch]; 5719 5720 StrCpyNW(pch, L".left", cch2); 5721 hr = SHPropertyBag_ReadLONG(ppb, szBuff, &prcl->left); 5722 if (FAILED(hr)) 5723 return hr; 5724 5725 StrCpyNW(pch, L".top", cch2); 5726 hr = SHPropertyBag_ReadLONG(ppb, szBuff, &prcl->top); 5727 if (FAILED(hr)) 5728 return hr; 5729 5730 StrCpyNW(pch, L".right", cch2); 5731 hr = SHPropertyBag_ReadLONG(ppb, szBuff, &prcl->right); 5732 if (FAILED(hr)) 5733 return hr; 5734 5735 StrCpyNW(pch, L".bottom", cch2); 5736 return SHPropertyBag_ReadLONG(ppb, szBuff, &prcl->bottom); 5737 } 5738 5739 /************************************************************************** 5740 * SHPropertyBag_ReadGUID (SHLWAPI.505) 5741 * 5742 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readguid.htm 5743 */ 5744 HRESULT WINAPI SHPropertyBag_ReadGUID(IPropertyBag *ppb, LPCWSTR pszPropName, GUID *pguid) 5745 { 5746 HRESULT hr; 5747 BOOL bRet; 5748 VARIANT vari; 5749 5750 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 5751 5752 if (!ppb || !pszPropName || !pguid) 5753 { 5754 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 5755 return E_INVALIDARG; 5756 } 5757 5758 hr = SHPropertyBag_ReadType(ppb, pszPropName, &vari, VT_EMPTY); 5759 if (FAILED(hr)) 5760 { 5761 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 5762 return hr; 5763 } 5764 5765 if (V_VT(&vari) == (VT_UI1 | VT_ARRAY)) /* Byte Array */ 5766 bRet = VariantArrayToBuffer(&vari, pguid, sizeof(*pguid)); 5767 else if (V_VT(&vari) == VT_BSTR) 5768 bRet = GUIDFromStringW(V_BSTR(&vari), pguid); 5769 else 5770 #if (_WIN32_WINNT >= _WIN32_WINNT_VISTA) 5771 bRet = FALSE; 5772 #else 5773 bRet = TRUE; /* This is by design in WinXP/Win2k3. */ 5774 #endif 5775 5776 if (!bRet) 5777 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 5778 5779 VariantClear(&vari); 5780 return (bRet ? S_OK : E_FAIL); 5781 } 5782 5783 /************************************************************************** 5784 * SHPropertyBag_ReadStream (SHLWAPI.531) 5785 * 5786 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/readstream.htm 5787 */ 5788 HRESULT WINAPI SHPropertyBag_ReadStream(IPropertyBag *ppb, LPCWSTR pszPropName, IStream **ppStream) 5789 { 5790 HRESULT hr; 5791 VARIANT vari; 5792 5793 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), ppStream); 5794 5795 if (!ppb || !pszPropName || !ppStream) 5796 { 5797 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), ppStream); 5798 return E_INVALIDARG; 5799 } 5800 5801 hr = SHPropertyBag_ReadType(ppb, pszPropName, &vari, VT_UNKNOWN); 5802 if (FAILED(hr)) 5803 return hr; 5804 5805 hr = IUnknown_QueryInterface(V_UNKNOWN(&vari), &IID_IStream, (void **)ppStream); 5806 IUnknown_Release(V_UNKNOWN(&vari)); 5807 5808 return hr; 5809 } 5810 5811 /************************************************************************** 5812 * SHPropertyBag_Delete (SHLWAPI.535) 5813 * 5814 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/delete.htm 5815 */ 5816 HRESULT WINAPI SHPropertyBag_Delete(IPropertyBag *ppb, LPCWSTR pszPropName) 5817 { 5818 VARIANT vari; 5819 5820 TRACE("%p %s\n", ppb, debugstr_w(pszPropName)); 5821 5822 if (!ppb || !pszPropName) 5823 { 5824 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5825 return E_INVALIDARG; 5826 } 5827 5828 V_VT(&vari) = VT_EMPTY; 5829 return IPropertyBag_Write(ppb, pszPropName, &vari); 5830 } 5831 5832 /************************************************************************** 5833 * SHPropertyBag_WriteBOOL (SHLWAPI.499) 5834 * 5835 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writebool.htm 5836 */ 5837 HRESULT WINAPI SHPropertyBag_WriteBOOL(IPropertyBag *ppb, LPCWSTR pszPropName, BOOL bValue) 5838 { 5839 VARIANT vari; 5840 5841 TRACE("%p %s %d\n", ppb, debugstr_w(pszPropName), bValue); 5842 5843 if (!ppb || !pszPropName) 5844 { 5845 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5846 return E_INVALIDARG; 5847 } 5848 5849 V_VT(&vari) = VT_BOOL; 5850 V_BOOL(&vari) = (bValue ? VARIANT_TRUE : VARIANT_FALSE); /* NOTE: VARIANT_TRUE is (SHORT)-1 */ 5851 return IPropertyBag_Write(ppb, pszPropName, &vari); 5852 } 5853 5854 /************************************************************************** 5855 * SHPropertyBag_WriteSHORT (SHLWAPI.528) 5856 * 5857 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writeshort.htm 5858 */ 5859 HRESULT WINAPI SHPropertyBag_WriteSHORT(IPropertyBag *ppb, LPCWSTR pszPropName, SHORT sValue) 5860 { 5861 VARIANT vari; 5862 5863 TRACE("%p %s %d\n", ppb, debugstr_w(pszPropName), sValue); 5864 5865 if (!ppb || !pszPropName) 5866 { 5867 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5868 return E_INVALIDARG; 5869 } 5870 5871 V_VT(&vari) = VT_UI2; 5872 V_UI2(&vari) = sValue; 5873 return IPropertyBag_Write(ppb, pszPropName, &vari); 5874 } 5875 5876 /************************************************************************** 5877 * SHPropertyBag_WriteLONG (SHLWAPI.497) 5878 * 5879 * This function asks a property bag to write a named property as a LONG. 5880 * 5881 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writelong.htm 5882 */ 5883 HRESULT WINAPI SHPropertyBag_WriteLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LONG lValue) 5884 { 5885 VARIANT vari; 5886 5887 TRACE("%p %s %ld\n", ppb, debugstr_w(pszPropName), lValue); 5888 5889 if (!ppb || !pszPropName) 5890 { 5891 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5892 return E_INVALIDARG; 5893 } 5894 5895 V_VT(&vari) = VT_I4; 5896 V_I4(&vari) = lValue; 5897 return IPropertyBag_Write(ppb, pszPropName, &vari); 5898 } 5899 5900 /************************************************************************** 5901 * SHPropertyBag_WriteDWORD (SHLWAPI.508) 5902 * 5903 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writedword.htm 5904 */ 5905 HRESULT WINAPI SHPropertyBag_WriteDWORD(IPropertyBag *ppb, LPCWSTR pszPropName, DWORD dwValue) 5906 { 5907 VARIANT vari; 5908 5909 TRACE("%p %s %lu\n", ppb, debugstr_w(pszPropName), dwValue); 5910 5911 if (!ppb || !pszPropName) 5912 { 5913 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5914 return E_INVALIDARG; 5915 } 5916 5917 V_VT(&vari) = VT_UI4; 5918 V_UI4(&vari) = dwValue; 5919 return IPropertyBag_Write(ppb, pszPropName, &vari); 5920 } 5921 5922 /************************************************************************** 5923 * SHPropertyBag_WriteStr (SHLWAPI.495) 5924 * 5925 * This function asks a property bag to write a string as the value of a named property. 5926 * 5927 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writestr.htm 5928 */ 5929 HRESULT WINAPI SHPropertyBag_WriteStr(IPropertyBag *ppb, LPCWSTR pszPropName, LPCWSTR pszValue) 5930 { 5931 HRESULT hr; 5932 VARIANT vari; 5933 5934 TRACE("%p %s %s\n", ppb, debugstr_w(pszPropName), debugstr_w(pszValue)); 5935 5936 if (!ppb || !pszPropName) 5937 { 5938 ERR("%p %s\n", ppb, debugstr_w(pszPropName)); 5939 return E_INVALIDARG; 5940 } 5941 5942 V_BSTR(&vari) = SysAllocString(pszValue); 5943 if (!V_BSTR(&vari)) 5944 return E_OUTOFMEMORY; 5945 5946 V_VT(&vari) = VT_BSTR; 5947 hr = IPropertyBag_Write(ppb, pszPropName, &vari); 5948 5949 SysFreeString(V_BSTR(&vari)); 5950 return hr; 5951 } 5952 5953 /************************************************************************** 5954 * SHPropertyBag_WriteGUID (SHLWAPI.506) 5955 * 5956 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writeguid.htm 5957 */ 5958 HRESULT WINAPI SHPropertyBag_WriteGUID(IPropertyBag *ppb, LPCWSTR pszPropName, const GUID *pguid) 5959 { 5960 WCHAR szBuff[64]; 5961 5962 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 5963 5964 if (!ppb || !pszPropName || !pguid) 5965 { 5966 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pguid); 5967 return E_INVALIDARG; 5968 } 5969 5970 SHStringFromGUIDW(pguid, szBuff, _countof(szBuff)); 5971 return SHPropertyBag_WriteStr(ppb, pszPropName, szBuff); 5972 } 5973 5974 /************************************************************************** 5975 * SHPropertyBag_WriteStream (SHLWAPI.532) 5976 * 5977 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writestream.htm 5978 */ 5979 HRESULT WINAPI SHPropertyBag_WriteStream(IPropertyBag *ppb, LPCWSTR pszPropName, IStream *pStream) 5980 { 5981 VARIANT vari; 5982 5983 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pStream); 5984 5985 if (!ppb || !pszPropName || !pStream) 5986 { 5987 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pStream); 5988 return E_INVALIDARG; 5989 } 5990 5991 V_VT(&vari) = VT_UNKNOWN; 5992 V_UNKNOWN(&vari) = (IUnknown*)pStream; 5993 return IPropertyBag_Write(ppb, pszPropName, &vari); 5994 } 5995 5996 /************************************************************************** 5997 * SHPropertyBag_WritePOINTL (SHLWAPI.522) 5998 * 5999 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writepointl.htm 6000 */ 6001 HRESULT WINAPI SHPropertyBag_WritePOINTL(IPropertyBag *ppb, LPCWSTR pszPropName, const POINTL *pptl) 6002 { 6003 HRESULT hr; 6004 int cch, cch2; 6005 WCHAR *pch, szBuff[MAX_PATH]; 6006 6007 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), pptl); 6008 6009 if (!ppb || !pszPropName || !pptl) 6010 { 6011 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), pptl); 6012 return E_INVALIDARG; 6013 } 6014 6015 StrCpyNW(szBuff, pszPropName, _countof(szBuff)); 6016 6017 cch = lstrlenW(szBuff); 6018 cch2 = _countof(szBuff) - cch; 6019 if (cch2 < _countof(L".x")) 6020 { 6021 ERR("%s is too long\n", debugstr_w(pszPropName)); 6022 return E_FAIL; 6023 } 6024 6025 pch = &szBuff[cch]; 6026 6027 StrCpyNW(pch, L".x", cch2); 6028 hr = SHPropertyBag_WriteLONG(ppb, szBuff, pptl->x); 6029 if (FAILED(hr)) 6030 return hr; 6031 6032 StrCpyNW(pch, L".y", cch2); 6033 hr = SHPropertyBag_WriteLONG(ppb, szBuff, pptl->y); 6034 if (FAILED(hr)) 6035 { 6036 StrCpyNW(pch, L".x", cch2); 6037 return SHPropertyBag_Delete(ppb, szBuff); 6038 } 6039 6040 return hr; 6041 } 6042 6043 /************************************************************************** 6044 * SHPropertyBag_WritePOINTS (SHLWAPI.526) 6045 * 6046 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writepoints.htm 6047 */ 6048 HRESULT WINAPI SHPropertyBag_WritePOINTS(IPropertyBag *ppb, LPCWSTR pszPropName, const POINTS *ppts) 6049 { 6050 POINTL pt; 6051 6052 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), ppts); 6053 6054 if (!ppb || !pszPropName || !ppts) 6055 { 6056 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), ppts); 6057 return E_INVALIDARG; 6058 } 6059 6060 pt.x = ppts->x; 6061 pt.y = ppts->y; 6062 return SHPropertyBag_WritePOINTL(ppb, pszPropName, &pt); 6063 } 6064 6065 /************************************************************************** 6066 * SHPropertyBag_WriteRECTL (SHLWAPI.524) 6067 * 6068 * @see https://www.geoffchappell.com/studies/windows/shell/shlwapi/api/propbag/writerectl.htm 6069 */ 6070 HRESULT WINAPI SHPropertyBag_WriteRECTL(IPropertyBag *ppb, LPCWSTR pszPropName, const RECTL *prcl) 6071 { 6072 HRESULT hr; 6073 int cch, cch2; 6074 WCHAR *pch, szBuff[MAX_PATH]; 6075 6076 TRACE("%p %s %p\n", ppb, debugstr_w(pszPropName), prcl); 6077 6078 if (!ppb || !pszPropName || !prcl) 6079 { 6080 ERR("%p %s %p\n", ppb, debugstr_w(pszPropName), prcl); 6081 return E_INVALIDARG; 6082 } 6083 6084 StrCpyNW(szBuff, pszPropName, _countof(szBuff)); 6085 6086 cch = lstrlenW(szBuff); 6087 cch2 = _countof(szBuff) - cch; 6088 if (cch2 < _countof(L".bottom")) 6089 { 6090 ERR("%s is too long\n", debugstr_w(pszPropName)); 6091 return E_FAIL; 6092 } 6093 6094 pch = &szBuff[cch]; 6095 6096 StrCpyNW(pch, L".left", cch2); 6097 hr = SHPropertyBag_WriteLONG(ppb, szBuff, prcl->left); 6098 if (SUCCEEDED(hr)) 6099 { 6100 StrCpyNW(pch, L".top", cch2); 6101 hr = SHPropertyBag_WriteLONG(ppb, szBuff, prcl->top); 6102 if (SUCCEEDED(hr)) 6103 { 6104 StrCpyNW(pch, L".right", cch2); 6105 hr = SHPropertyBag_WriteLONG(ppb, szBuff, prcl->right); 6106 if (SUCCEEDED(hr)) 6107 { 6108 StrCpyNW(pch, L".bottom", cch2); 6109 hr = SHPropertyBag_WriteLONG(ppb, szBuff, prcl->bottom); 6110 if (SUCCEEDED(hr)) 6111 return hr; /* All successful */ 6112 6113 StrCpyNW(pch, L".right", cch2); 6114 hr = SHPropertyBag_Delete(ppb, szBuff); 6115 if (SUCCEEDED(hr)) 6116 return hr; 6117 } 6118 6119 StrCpyNW(pch, L".top", cch2); 6120 hr = SHPropertyBag_Delete(ppb, szBuff); 6121 if (SUCCEEDED(hr)) 6122 return hr; 6123 } 6124 6125 StrCpyNW(pch, L".left", cch2); 6126 hr = SHPropertyBag_Delete(ppb, szBuff); 6127 if (SUCCEEDED(hr)) 6128 return hr; 6129 } 6130 6131 return hr; 6132 } 6133 #endif 6134 6135 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */ 6136 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001 6137 #define OBJCOMPAT_NO_WEBVIEW 0x00000002 6138 #define OBJCOMPAT_UNBINDABLE 0x00000004 6139 #define OBJCOMPAT_PINDLL 0x00000008 6140 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010 6141 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020 6142 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040 6143 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080 6144 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100 6145 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200 6146 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400 6147 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000 6148 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000 6149 6150 /* a search table for compatibility flags */ 6151 struct objcompat_entry { 6152 const WCHAR name[30]; 6153 DWORD value; 6154 }; 6155 6156 /* expected to be sorted by name */ 6157 static const struct objcompat_entry objcompat_table[] = { 6158 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0}, 6159 OBJCOMPAT_COCREATESHELLFOLDERONLY }, 6160 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0}, 6161 OBJCOMPAT_CTXMENU_LIMITEDQI }, 6162 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0}, 6163 OBJCOMPAT_CTXMENU_LIMITEDQI }, 6164 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0}, 6165 OBJCOMPAT_CTXMENU_XPQCMFLAGS }, 6166 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0}, 6167 OBJCOMPAT_NEEDSFILESYSANCESTOR }, 6168 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0}, 6169 OBJCOMPAT_NEEDSSTORAGEANCESTOR }, 6170 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0}, 6171 OBJCOMPAT_NOIPROPERTYSTORE }, 6172 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0}, 6173 OBJCOMPAT_NOLEGACYWEBVIEW }, 6174 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0}, 6175 OBJCOMPAT_NOTAFILESYSTEM }, 6176 { {'N','O','_','W','E','B','V','I','E','W',0}, 6177 OBJCOMPAT_NO_WEBVIEW }, 6178 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0}, 6179 OBJCOMPAT_OTNEEDSSFCACHE }, 6180 { {'P','I','N','D','L','L',0}, 6181 OBJCOMPAT_PINDLL }, 6182 { {'U','N','B','I','N','D','A','B','L','E',0}, 6183 OBJCOMPAT_UNBINDABLE } 6184 }; 6185 6186 /************************************************************************** 6187 * SHGetObjectCompatFlags (SHLWAPI.476) 6188 * 6189 * Function returns an integer representation of compatibility flags stored 6190 * in registry for CLSID under ShellCompatibility subkey. 6191 * 6192 * PARAMS 6193 * pUnk: pointer to object IUnknown interface, idetifies CLSID 6194 * clsid: pointer to CLSID to retrieve data for 6195 * 6196 * RETURNS 6197 * 0 on failure, flags set on success 6198 */ 6199 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid) 6200 { 6201 static const WCHAR compatpathW[] = 6202 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', 6203 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 6204 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\', 6205 'O','b','j','e','c','t','s','\\','%','s',0}; 6206 WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */]; 6207 DWORD ret, length = sizeof(strW)/sizeof(WCHAR); 6208 OLECHAR *clsid_str; 6209 HKEY key; 6210 INT i; 6211 6212 TRACE("%p %s\n", pUnk, debugstr_guid(clsid)); 6213 6214 if (!pUnk && !clsid) return 0; 6215 6216 if (pUnk && !clsid) 6217 { 6218 FIXME("iface not handled\n"); 6219 return 0; 6220 } 6221 6222 StringFromCLSID(clsid, &clsid_str); 6223 sprintfW(strW, compatpathW, clsid_str); 6224 CoTaskMemFree(clsid_str); 6225 6226 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key); 6227 if (ret != ERROR_SUCCESS) return 0; 6228 6229 /* now collect flag values */ 6230 ret = 0; 6231 for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++) 6232 { 6233 INT left, right, res, x; 6234 6235 /* search in table */ 6236 left = 0; 6237 right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1; 6238 6239 while (right >= left) { 6240 x = (left + right) / 2; 6241 res = strcmpW(strW, objcompat_table[x].name); 6242 if (res == 0) 6243 { 6244 ret |= objcompat_table[x].value; 6245 break; 6246 } 6247 else if (res < 0) 6248 right = x - 1; 6249 else 6250 left = x + 1; 6251 } 6252 6253 length = sizeof(strW)/sizeof(WCHAR); 6254 } 6255 6256 return ret; 6257 } 6258