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