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