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