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