2 * SHLWAPI ordinal functions
4 * Copyright 1997 Marcus Meissner
6 * 2001-2003 Jon Griffiths
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.
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.
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
24 #include "wine/port.h"
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
45 #include "shdeprecated.h"
52 #include "wine/unicode.h"
53 #include "wine/debug.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(shell);
58 /* DLL handles for late bound calls */
59 extern HINSTANCE shlwapi_hInstance;
60 extern DWORD SHLWAPI_ThreadRef_index;
62 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
63 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
64 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
67 NOTES: Most functions exported by ordinal seem to be superfluous.
68 The reason for these functions to be there is to provide a wrapper
69 for unicode functions to provide these functions on systems without
70 unicode functions eg. win95/win98. Since we have such functions we just
71 call these. If running Wine with native DLLs, some late bound calls may
72 fail. However, it is better to implement the functions in the forward DLL
73 and recommend the builtin rather than reimplementing the calls here!
76 /*************************************************************************
77 * SHLWAPI_DupSharedHandle
79 * Internal implemetation of SHLWAPI_11.
81 static HANDLE SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
82 DWORD dwSrcProcId, DWORD dwAccess,
86 DWORD dwMyProcId = GetCurrentProcessId();
89 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
92 /* Get dest process handle */
93 if (dwDstProcId == dwMyProcId)
94 hDst = GetCurrentProcess();
96 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
100 /* Get src process handle */
101 if (dwSrcProcId == dwMyProcId)
102 hSrc = GetCurrentProcess();
104 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
108 /* Make handle available to dest process */
109 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
110 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
113 if (dwSrcProcId != dwMyProcId)
117 if (dwDstProcId != dwMyProcId)
121 TRACE("Returning handle %p\n", hRet);
125 /*************************************************************************
128 * Create a block of sharable memory and initialise it with data.
131 * lpvData [I] Pointer to data to write
132 * dwSize [I] Size of data
133 * dwProcId [I] ID of process owning data
136 * Success: A shared memory handle
140 * Ordinals 7-11 provide a set of calls to create shared memory between a
141 * group of processes. The shared memory is treated opaquely in that its size
142 * is not exposed to clients who map it. This is accomplished by storing
143 * the size of the map as the first DWORD of mapped data, and then offsetting
144 * the view pointer returned by this size.
147 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
153 TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
155 /* Create file mapping of the correct length */
156 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
157 dwSize + sizeof(dwSize), NULL);
161 /* Get a view in our process address space */
162 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
166 /* Write size of data, followed by the data, to the view */
167 *((DWORD*)pMapped) = dwSize;
169 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
171 /* Release view. All further views mapped will be opaque */
172 UnmapViewOfFile(pMapped);
173 hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
174 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
175 DUPLICATE_SAME_ACCESS);
182 /*************************************************************************
185 * Get a pointer to a block of shared memory from a shared memory handle.
188 * hShared [I] Shared memory handle
189 * dwProcId [I] ID of process owning hShared
192 * Success: A pointer to the shared memory
196 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
201 TRACE("(%p %d)\n", hShared, dwProcId);
203 /* Get handle to shared memory for current process */
204 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
205 FILE_MAP_ALL_ACCESS, 0);
207 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
211 return (char *) pMapped + sizeof(DWORD); /* Hide size */
215 /*************************************************************************
218 * Release a pointer to a block of shared memory.
221 * lpView [I] Shared memory pointer
228 BOOL WINAPI SHUnlockShared(LPVOID lpView)
230 TRACE("(%p)\n", lpView);
231 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
234 /*************************************************************************
237 * Destroy a block of sharable memory.
240 * hShared [I] Shared memory handle
241 * dwProcId [I] ID of process owning hShared
248 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
252 TRACE("(%p %d)\n", hShared, dwProcId);
254 /* Get a copy of the handle for our process, closing the source handle */
255 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
256 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
257 /* Close local copy */
258 return CloseHandle(hClose);
261 /*************************************************************************
264 * Copy a sharable memory handle from one process to another.
267 * hShared [I] Shared memory handle to duplicate
268 * dwDstProcId [I] ID of the process wanting the duplicated handle
269 * dwSrcProcId [I] ID of the process owning hShared
270 * dwAccess [I] Desired DuplicateHandle() access
271 * dwOptions [I] Desired DuplicateHandle() options
274 * Success: A handle suitable for use by the dwDstProcId process.
275 * Failure: A NULL handle.
278 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
279 DWORD dwAccess, DWORD dwOptions)
283 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
284 dwAccess, dwOptions);
288 /*************************************************************************
291 * Create and register a clipboard enumerator for a web browser.
294 * lpBC [I] Binding context
295 * lpUnknown [I] An object exposing the IWebBrowserApp interface
299 * Failure: An HRESULT error code.
302 * The enumerator is stored as a property of the web browser. If it does not
303 * yet exist, it is created and set before being registered.
305 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
307 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
308 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
309 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
311 IEnumFORMATETC* pIEnumFormatEtc = NULL;
314 IWebBrowserApp* pBrowser;
316 TRACE("(%p, %p)\n", lpBC, lpUnknown);
318 hr = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (void**)&pBrowser);
322 V_VT(&var) = VT_EMPTY;
324 /* The property we get is the browsers clipboard enumerator */
325 property = SysAllocString(szProperty);
326 hr = IWebBrowserApp_GetProperty(pBrowser, property, &var);
327 SysFreeString(property);
328 if (FAILED(hr)) goto exit;
330 if (V_VT(&var) == VT_EMPTY)
332 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
333 char szKeyBuff[128], szValueBuff[128];
334 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
335 FORMATETC* formatList, *format;
338 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
340 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
341 "Version\\Internet Settings\\Accepted Documents", &hDocs))
347 /* Get count of values in key */
350 dwKeySize = sizeof(szKeyBuff);
351 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
355 dwNumValues = dwCount;
357 /* Note: dwCount = number of items + 1; The extra item is the end node */
358 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
373 /* Register clipboard formats for the values and populate format list */
374 while(!dwRet && dwCount < dwNumValues)
376 dwKeySize = sizeof(szKeyBuff);
377 dwValueSize = sizeof(szValueBuff);
378 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
379 (PBYTE)szValueBuff, &dwValueSize);
382 HeapFree(GetProcessHeap(), 0, formatList);
388 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
390 format->dwAspect = 1;
401 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
402 format->cfFormat = 0;
404 format->dwAspect = 1;
408 /* Create a clipboard enumerator */
409 hr = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
410 HeapFree(GetProcessHeap(), 0, formatList);
411 if (FAILED(hr)) goto exit;
413 /* Set our enumerator as the browsers property */
414 V_VT(&var) = VT_UNKNOWN;
415 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
417 property = SysAllocString(szProperty);
418 hr = IWebBrowserApp_PutProperty(pBrowser, property, var);
419 SysFreeString(property);
422 IEnumFORMATETC_Release(pIEnumFormatEtc);
427 if (V_VT(&var) == VT_UNKNOWN)
429 /* Our variant is holding the clipboard enumerator */
430 IUnknown* pIUnknown = V_UNKNOWN(&var);
431 IEnumFORMATETC* pClone = NULL;
433 TRACE("Retrieved IEnumFORMATETC property\n");
435 /* Get an IEnumFormatEtc interface from the variants value */
436 pIEnumFormatEtc = NULL;
437 hr = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC, (void**)&pIEnumFormatEtc);
438 if (hr == S_OK && pIEnumFormatEtc)
440 /* Clone and register the enumerator */
441 hr = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
442 if (hr == S_OK && pClone)
444 RegisterFormatEnumerator(lpBC, pClone, 0);
446 IEnumFORMATETC_Release(pClone);
449 IEnumFORMATETC_Release(pIUnknown);
451 IUnknown_Release(V_UNKNOWN(&var));
455 IWebBrowserApp_Release(pBrowser);
459 /*************************************************************************
462 * Get Explorers "AcceptLanguage" setting.
465 * langbuf [O] Destination for language string
466 * buflen [I] Length of langbuf in characters
467 * [0] Success: used length of langbuf
470 * Success: S_OK. langbuf is set to the language string found.
471 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
472 * does not contain the setting.
473 * HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), If the buffer is not big enough
475 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
477 static const WCHAR szkeyW[] = {
478 'S','o','f','t','w','a','r','e','\\',
479 'M','i','c','r','o','s','o','f','t','\\',
480 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
481 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
482 static const WCHAR valueW[] = {
483 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
484 DWORD mystrlen, mytype;
492 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
494 if(!langbuf || !buflen || !*buflen)
497 mystrlen = (*buflen > 20) ? *buflen : 20 ;
498 len = mystrlen * sizeof(WCHAR);
499 mystr = HeapAlloc(GetProcessHeap(), 0, len);
501 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
502 lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
504 len = lstrlenW(mystr);
506 if (!lres && (*buflen > len)) {
507 lstrcpyW(langbuf, mystr);
509 HeapFree(GetProcessHeap(), 0, mystr);
513 /* Did not find a value in the registry or the user buffer is too small */
514 mylcid = GetUserDefaultLCID();
515 retval = LcidToRfc1766W(mylcid, mystr, mystrlen);
516 len = lstrlenW(mystr);
518 memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
519 HeapFree(GetProcessHeap(), 0, mystr);
527 return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
530 /*************************************************************************
533 * Ascii version of GetAcceptLanguagesW.
535 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
538 DWORD buflenW, convlen;
541 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
543 if(!langbuf || !buflen || !*buflen) return E_FAIL;
546 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
547 retval = GetAcceptLanguagesW(langbufW, &buflenW);
551 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
552 convlen--; /* do not count the terminating 0 */
554 else /* copy partial string anyway */
556 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
557 if (convlen < *buflen)
559 langbuf[convlen] = 0;
560 convlen--; /* do not count the terminating 0 */
567 *buflen = buflenW ? convlen : 0;
569 HeapFree(GetProcessHeap(), 0, langbufW);
573 /*************************************************************************
576 * Convert a GUID to a string.
579 * guid [I] GUID to convert
580 * lpszDest [O] Destination for string
581 * cchMax [I] Length of output buffer
584 * The length of the string created.
586 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
591 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
593 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
594 guid->Data1, guid->Data2, guid->Data3,
595 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
596 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
598 iLen = strlen(xguid) + 1;
602 memcpy(lpszDest, xguid, iLen);
606 /*************************************************************************
609 * Convert a GUID to a string.
612 * guid [I] GUID to convert
613 * str [O] Destination for string
614 * cmax [I] Length of output buffer
617 * The length of the string created.
619 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
623 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
624 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
625 'X','%','0','2','X','%','0','2','X','}',0};
627 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
629 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
630 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
631 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
633 iLen = strlenW(xguid) + 1;
637 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
641 /*************************************************************************
644 * Determine if a Unicode character is a space.
647 * wc [I] Character to check.
650 * TRUE, if wc is a space,
653 BOOL WINAPI IsCharSpaceW(WCHAR wc)
657 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
660 /*************************************************************************
663 * Determine if a Unicode character is a blank.
666 * wc [I] Character to check.
669 * TRUE, if wc is a blank,
673 BOOL WINAPI IsCharBlankW(WCHAR wc)
677 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
680 /*************************************************************************
683 * Determine if a Unicode character is punctuation.
686 * wc [I] Character to check.
689 * TRUE, if wc is punctuation,
692 BOOL WINAPI IsCharPunctW(WCHAR wc)
696 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
699 /*************************************************************************
702 * Determine if a Unicode character is a control character.
705 * wc [I] Character to check.
708 * TRUE, if wc is a control character,
711 BOOL WINAPI IsCharCntrlW(WCHAR wc)
715 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
718 /*************************************************************************
721 * Determine if a Unicode character is a digit.
724 * wc [I] Character to check.
727 * TRUE, if wc is a digit,
730 BOOL WINAPI IsCharDigitW(WCHAR wc)
734 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
737 /*************************************************************************
740 * Determine if a Unicode character is a hex digit.
743 * wc [I] Character to check.
746 * TRUE, if wc is a hex digit,
749 BOOL WINAPI IsCharXDigitW(WCHAR wc)
753 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
756 /*************************************************************************
760 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type)
762 return GetStringTypeW(CT_CTYPE3, src, count, type);
765 /*************************************************************************
768 * Compare two Ascii strings up to a given length.
771 * lpszSrc [I] Source string
772 * lpszCmp [I] String to compare to lpszSrc
773 * len [I] Maximum length
776 * A number greater than, less than or equal to 0 depending on whether
777 * lpszSrc is greater than, less than or equal to lpszCmp.
779 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
781 return StrCmpNA(lpszSrc, lpszCmp, len);
784 /*************************************************************************
787 * Unicode version of StrCmpNCA.
789 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
791 return StrCmpNW(lpszSrc, lpszCmp, len);
794 /*************************************************************************
797 * Compare two Ascii strings up to a given length, ignoring case.
800 * lpszSrc [I] Source string
801 * lpszCmp [I] String to compare to lpszSrc
802 * len [I] Maximum length
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.
808 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
810 return StrCmpNIA(lpszSrc, lpszCmp, len);
813 /*************************************************************************
816 * Unicode version of StrCmpNICA.
818 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
820 return StrCmpNIW(lpszSrc, lpszCmp, len);
823 /*************************************************************************
826 * Compare two Ascii strings.
829 * lpszSrc [I] Source string
830 * lpszCmp [I] String to compare to lpszSrc
833 * A number greater than, less than or equal to 0 depending on whether
834 * lpszSrc is greater than, less than or equal to lpszCmp.
836 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
838 return lstrcmpA(lpszSrc, lpszCmp);
841 /*************************************************************************
844 * Unicode version of StrCmpCA.
846 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
848 return lstrcmpW(lpszSrc, lpszCmp);
851 /*************************************************************************
854 * Compare two Ascii strings, ignoring case.
857 * lpszSrc [I] Source string
858 * lpszCmp [I] String to compare to lpszSrc
861 * A number greater than, less than or equal to 0 depending on whether
862 * lpszSrc is greater than, less than or equal to lpszCmp.
864 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
866 return lstrcmpiA(lpszSrc, lpszCmp);
869 /*************************************************************************
872 * Unicode version of StrCmpICA.
874 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
876 return lstrcmpiW(lpszSrc, lpszCmp);
879 /*************************************************************************
882 * Get an identification string for the OS and explorer.
885 * lpszDest [O] Destination for Id string
886 * dwDestLen [I] Length of lpszDest
889 * TRUE, If the string was created successfully
892 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
896 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
898 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
900 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
906 /*************************************************************************
909 * Unicode version of SHAboutInfoA.
911 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
913 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
914 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
915 ' ','E','x','p','l','o','r','e','r','\0' };
916 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
917 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
918 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
919 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
920 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
921 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
922 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
923 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
924 ' ','E','x','p','l','o','r','e','r','\\',
925 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
926 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
927 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
928 'V','e','r','s','i','o','n','\0' };
929 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
930 'O','w','n','e','r','\0' };
931 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
932 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
933 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
934 static const WCHAR szUpdate[] = { 'I','E','A','K',
935 'U','p','d','a','t','e','U','r','l','\0' };
936 static const WCHAR szHelp[] = { 'I','E','A','K',
937 'H','e','l','p','S','t','r','i','n','g','\0' };
942 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
949 /* Try the NT key first, followed by 95/98 key */
950 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
951 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
957 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
959 DWORD dwStrLen = strlenW(buff);
960 dwLen = 30 - dwStrLen;
961 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
962 szCustomized, &dwType, buff+dwStrLen, &dwLen);
964 StrCatBuffW(lpszDest, buff, dwDestLen);
966 /* ~Registered Owner */
969 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
971 StrCatBuffW(lpszDest, buff, dwDestLen);
973 /* ~Registered Organization */
975 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
977 StrCatBuffW(lpszDest, buff, dwDestLen);
979 /* FIXME: Not sure where this number comes from */
983 StrCatBuffW(lpszDest, buff, dwDestLen);
987 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
989 StrCatBuffW(lpszDest, buff, dwDestLen);
993 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
995 StrCatBuffW(lpszDest, buff, dwDestLen);
997 /* ~IE Help String */
999 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
1001 StrCatBuffW(lpszDest, buff, dwDestLen);
1007 /*************************************************************************
1010 * Call IOleCommandTarget_QueryStatus() on an object.
1013 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1014 * pguidCmdGroup [I] GUID for the command group
1016 * prgCmds [O] Commands
1017 * pCmdText [O] Command text
1021 * Failure: E_FAIL, if lpUnknown is NULL.
1022 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1023 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1025 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1026 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1028 HRESULT hRet = E_FAIL;
1030 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1034 IOleCommandTarget* lpOle;
1036 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1039 if (SUCCEEDED(hRet) && lpOle)
1041 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1043 IOleCommandTarget_Release(lpOle);
1049 /*************************************************************************
1052 * Call IOleCommandTarget_Exec() on an object.
1055 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1056 * pguidCmdGroup [I] GUID for the command group
1060 * Failure: E_FAIL, if lpUnknown is NULL.
1061 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1062 * Otherwise, an error code from IOleCommandTarget_Exec().
1064 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1065 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1068 HRESULT hRet = E_FAIL;
1070 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1071 nCmdexecopt, pvaIn, pvaOut);
1075 IOleCommandTarget* lpOle;
1077 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1079 if (SUCCEEDED(hRet) && lpOle)
1081 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1082 nCmdexecopt, pvaIn, pvaOut);
1083 IOleCommandTarget_Release(lpOle);
1089 /*************************************************************************
1092 * Retrieve, modify, and re-set a value from a window.
1095 * hWnd [I] Window to get value from
1096 * offset [I] Offset of value
1097 * mask [I] Mask for flags
1098 * flags [I] Bits to set in window value
1101 * The new value as it was set, or 0 if any parameter is invalid.
1104 * Only bits specified in mask are affected - set if present in flags and
1107 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT mask, UINT flags)
1109 LONG ret = GetWindowLongW(hwnd, offset);
1110 LONG new_flags = (flags & mask) | (ret & ~mask);
1112 TRACE("%p %d %x %x\n", hwnd, offset, mask, flags);
1114 if (new_flags != ret)
1115 ret = SetWindowLongW(hwnd, offset, new_flags);
1119 /*************************************************************************
1122 * Change a window's parent.
1125 * hWnd [I] Window to change parent of
1126 * hWndParent [I] New parent window
1129 * The old parent of hWnd.
1132 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1133 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1135 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1137 TRACE("%p, %p\n", hWnd, hWndParent);
1139 if(GetParent(hWnd) == hWndParent)
1143 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1145 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1147 return SetParent(hWnd, hWndParent);
1150 /*************************************************************************
1153 * Locate and advise a connection point in an IConnectionPointContainer object.
1156 * lpUnkSink [I] Sink for the connection point advise call
1157 * riid [I] REFIID of connection point to advise
1158 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1159 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1160 * lpCookie [O] Pointer to connection point cookie
1161 * lppCP [O] Destination for the IConnectionPoint found
1164 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1165 * that was advised. The caller is responsible for releasing it.
1166 * Failure: E_FAIL, if any arguments are invalid.
1167 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1168 * Or an HRESULT error code if any call fails.
1170 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL fConnect,
1171 IUnknown* lpUnknown, LPDWORD lpCookie,
1172 IConnectionPoint **lppCP)
1175 IConnectionPointContainer* lpContainer;
1176 IConnectionPoint *lpCP;
1178 if(!lpUnknown || (fConnect && !lpUnkSink))
1184 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1185 (void**)&lpContainer);
1186 if (SUCCEEDED(hRet))
1188 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1190 if (SUCCEEDED(hRet))
1193 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1195 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1200 if (lppCP && SUCCEEDED(hRet))
1201 *lppCP = lpCP; /* Caller keeps the interface */
1203 IConnectionPoint_Release(lpCP); /* Release it */
1206 IUnknown_Release(lpContainer);
1211 /*************************************************************************
1214 * Release an interface and zero a supplied pointer.
1217 * lpUnknown [I] Object to release
1222 void WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1224 TRACE("(%p)\n", lpUnknown);
1226 if(!lpUnknown || !*lpUnknown) return;
1228 TRACE("doing Release\n");
1230 IUnknown_Release(*lpUnknown);
1234 /*************************************************************************
1237 * Skip '//' if present in a string.
1240 * lpszSrc [I] String to check for '//'
1243 * Success: The next character after the '//' or the string if not present
1244 * Failure: NULL, if lpszStr is NULL.
1246 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1248 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1253 /*************************************************************************
1256 * Check if two interfaces come from the same object.
1259 * lpInt1 [I] Interface to check against lpInt2.
1260 * lpInt2 [I] Interface to check against lpInt1.
1263 * TRUE, If the interfaces come from the same object.
1266 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1268 IUnknown *lpUnknown1, *lpUnknown2;
1271 TRACE("(%p %p)\n", lpInt1, lpInt2);
1273 if (!lpInt1 || !lpInt2)
1276 if (lpInt1 == lpInt2)
1279 if (IUnknown_QueryInterface(lpInt1, &IID_IUnknown, (void**)&lpUnknown1) != S_OK)
1282 if (IUnknown_QueryInterface(lpInt2, &IID_IUnknown, (void**)&lpUnknown2) != S_OK)
1284 IUnknown_Release(lpUnknown1);
1288 ret = lpUnknown1 == lpUnknown2;
1290 IUnknown_Release(lpUnknown1);
1291 IUnknown_Release(lpUnknown2);
1296 /*************************************************************************
1299 * Get the window handle of an object.
1302 * lpUnknown [I] Object to get the window handle of
1303 * lphWnd [O] Destination for window handle
1306 * Success: S_OK. lphWnd contains the objects window handle.
1307 * Failure: An HRESULT error code.
1310 * lpUnknown is expected to support one of the following interfaces:
1311 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1313 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1316 HRESULT hRet = E_FAIL;
1318 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1323 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1327 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1331 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1336 if (SUCCEEDED(hRet))
1338 /* Lazyness here - Since GetWindow() is the first method for the above 3
1339 * interfaces, we use the same call for them all.
1341 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1342 IUnknown_Release(lpOle);
1344 TRACE("Returning HWND=%p\n", *lphWnd);
1350 /*************************************************************************
1353 * Call a SetOwner method of IShellService from specified object.
1356 * iface [I] Object that supports IShellService
1357 * pUnk [I] Argument for the SetOwner call
1360 * Corresponding return value from last call or E_FAIL for null input
1362 HRESULT WINAPI IUnknown_SetOwner(IUnknown *iface, IUnknown *pUnk)
1364 IShellService *service;
1367 TRACE("(%p, %p)\n", iface, pUnk);
1369 if (!iface) return E_FAIL;
1371 hr = IUnknown_QueryInterface(iface, &IID_IShellService, (void**)&service);
1374 hr = IShellService_SetOwner(service, pUnk);
1375 IShellService_Release(service);
1381 /*************************************************************************
1384 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1388 HRESULT WINAPI IUnknown_SetSite(
1389 IUnknown *obj, /* [in] OLE object */
1390 IUnknown *site) /* [in] Site interface */
1393 IObjectWithSite *iobjwithsite;
1394 IInternetSecurityManager *isecmgr;
1396 if (!obj) return E_FAIL;
1398 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1399 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1402 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1403 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1404 IUnknown_Release(iobjwithsite);
1408 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1409 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1410 if (FAILED(hr)) return hr;
1412 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1413 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1414 IUnknown_Release(isecmgr);
1419 /*************************************************************************
1422 * Call IPersist_GetClassID() on an object.
1425 * lpUnknown [I] Object supporting the IPersist interface
1426 * lpClassId [O] Destination for Class Id
1429 * Success: S_OK. lpClassId contains the Class Id requested.
1430 * Failure: E_FAIL, If lpUnknown is NULL,
1431 * E_NOINTERFACE If lpUnknown does not support IPersist,
1432 * Or an HRESULT error code.
1434 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1436 IPersist* lpPersist;
1437 HRESULT hRet = E_FAIL;
1439 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1443 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1444 if (SUCCEEDED(hRet))
1446 IPersist_GetClassID(lpPersist, lpClassId);
1447 IPersist_Release(lpPersist);
1453 /*************************************************************************
1456 * Retrieve a Service Interface from an object.
1459 * lpUnknown [I] Object to get an IServiceProvider interface from
1460 * sid [I] Service ID for IServiceProvider_QueryService() call
1461 * riid [I] Function requested for QueryService call
1462 * lppOut [O] Destination for the service interface pointer
1465 * Success: S_OK. lppOut contains an object providing the requested service
1466 * Failure: An HRESULT error code
1469 * lpUnknown is expected to support the IServiceProvider interface.
1471 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1474 IServiceProvider* pService = NULL;
1485 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1486 (LPVOID*)&pService);
1488 if (hRet == S_OK && pService)
1490 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1492 /* Get a Service interface from the object */
1493 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1495 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1497 IUnknown_Release(pService);
1502 /*************************************************************************
1505 * Calls IOleCommandTarget::Exec() for specified service object.
1508 * lpUnknown [I] Object to get an IServiceProvider interface from
1509 * service [I] Service ID for IServiceProvider_QueryService() call
1510 * group [I] Group ID for IOleCommandTarget::Exec() call
1511 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1512 * cmdOpt [I] Options flags for command
1513 * pIn [I] Input arguments for command
1514 * pOut [O] Output arguments for command
1517 * Success: S_OK. lppOut contains an object providing the requested service
1518 * Failure: An HRESULT error code
1521 * lpUnknown is expected to support the IServiceProvider interface.
1523 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *lpUnknown, REFIID service,
1524 const GUID *group, DWORD cmdId, DWORD cmdOpt, VARIANT *pIn, VARIANT *pOut)
1526 IOleCommandTarget *target;
1529 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown, debugstr_guid(service),
1530 debugstr_guid(group), cmdId, cmdOpt, pIn, pOut);
1532 hr = IUnknown_QueryService(lpUnknown, service, &IID_IOleCommandTarget, (void**)&target);
1535 hr = IOleCommandTarget_Exec(target, group, cmdId, cmdOpt, pIn, pOut);
1536 IOleCommandTarget_Release(target);
1539 TRACE("<-- hr=0x%08x\n", hr);
1544 /*************************************************************************
1547 * Calls IProfferService methods to proffer/revoke specified service.
1550 * lpUnknown [I] Object to get an IServiceProvider interface from
1551 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1552 * pService [I] Service to proffer. If NULL ::Revoke is called
1553 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1556 * Success: S_OK. IProffer method returns S_OK
1557 * Failure: An HRESULT error code
1560 * lpUnknown is expected to support the IServiceProvider interface.
1562 HRESULT WINAPI IUnknown_ProfferService(IUnknown *lpUnknown, REFGUID service, IServiceProvider *pService, DWORD *pCookie)
1564 IProfferService *proffer;
1567 TRACE("%p %s %p %p\n", lpUnknown, debugstr_guid(service), pService, pCookie);
1569 hr = IUnknown_QueryService(lpUnknown, &IID_IProfferService, &IID_IProfferService, (void**)&proffer);
1573 hr = IProfferService_ProfferService(proffer, service, pService, pCookie);
1575 hr = IProfferService_RevokeService(proffer, *pCookie);
1577 IProfferService_Release(proffer);
1583 /*************************************************************************
1586 * Call an object's UIActivateIO method.
1589 * unknown [I] Object to call the UIActivateIO method on
1590 * activate [I] Parameter for UIActivateIO call
1591 * msg [I] Parameter for UIActivateIO call
1594 * Success: Value of UI_ActivateIO call
1595 * Failure: An HRESULT error code
1598 * unknown is expected to support the IInputObject interface.
1600 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg)
1602 IInputObject* object = NULL;
1608 /* Get an IInputObject interface from the object */
1609 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
1613 ret = IInputObject_UIActivateIO(object, activate, msg);
1614 IUnknown_Release(object);
1620 /*************************************************************************
1623 * Loads a popup menu.
1626 * hInst [I] Instance handle
1627 * szName [I] Menu name
1633 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1637 TRACE("%p %s\n", hInst, debugstr_w(szName));
1639 if ((hMenu = LoadMenuW(hInst, szName)))
1641 if (GetSubMenu(hMenu, 0))
1642 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1650 typedef struct _enumWndData
1655 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1658 /* Callback for SHLWAPI_178 */
1659 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1661 enumWndData *data = (enumWndData *)lParam;
1663 TRACE("(%p,%p)\n", hWnd, data);
1664 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1668 /*************************************************************************
1671 * Send or post a message to every child of a window.
1674 * hWnd [I] Window whose children will get the messages
1675 * uiMsgId [I] Message Id
1676 * wParam [I] WPARAM of message
1677 * lParam [I] LPARAM of message
1678 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1684 * The appropriate ASCII or Unicode function is called for the window.
1686 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1690 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1694 data.uiMsgId = uiMsgId;
1695 data.wParam = wParam;
1696 data.lParam = lParam;
1699 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1701 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1703 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1707 /*************************************************************************
1710 * Remove all sub-menus from a menu.
1713 * hMenu [I] Menu to remove sub-menus from
1716 * Success: 0. All sub-menus under hMenu are removed
1717 * Failure: -1, if any parameter is invalid
1719 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1721 int iItemCount = GetMenuItemCount(hMenu) - 1;
1723 TRACE("%p\n", hMenu);
1725 while (iItemCount >= 0)
1727 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1729 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1735 /*************************************************************************
1738 * Enable or disable a menu item.
1741 * hMenu [I] Menu holding menu item
1742 * uID [I] ID of menu item to enable/disable
1743 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1746 * The return code from EnableMenuItem.
1748 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1750 TRACE("%p, %u, %d\n", hMenu, wItemID, bEnable);
1751 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1754 /*************************************************************************
1757 * Check or uncheck a menu item.
1760 * hMenu [I] Menu holding menu item
1761 * uID [I] ID of menu item to check/uncheck
1762 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1765 * The return code from CheckMenuItem.
1767 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1769 TRACE("%p, %u, %d\n", hMenu, uID, bCheck);
1770 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1773 /*************************************************************************
1776 * Register a window class if it isn't already.
1779 * lpWndClass [I] Window class to register
1782 * The result of the RegisterClassA call.
1784 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1787 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1789 return (DWORD)RegisterClassA(wndclass);
1792 /*************************************************************************
1795 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1796 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1798 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1799 POINTL pt = { 0, 0 };
1801 TRACE("%p %p 0x%08x %p %p\n", pDrop, pDataObj, grfKeyState, lpPt, pdwEffect);
1807 pdwEffect = &dwEffect;
1809 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1811 if (*pdwEffect != DROPEFFECT_NONE)
1812 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1814 IDropTarget_DragLeave(pDrop);
1818 /*************************************************************************
1821 * Call IPersistPropertyBag_Load() on an object.
1824 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1825 * lpPropBag [O] Destination for loaded IPropertyBag
1829 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1831 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1833 IPersistPropertyBag* lpPPBag;
1834 HRESULT hRet = E_FAIL;
1836 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1840 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1842 if (SUCCEEDED(hRet) && lpPPBag)
1844 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1845 IPersistPropertyBag_Release(lpPPBag);
1851 /*************************************************************************
1854 * Call IOleControlSite_TranslateAccelerator() on an object.
1857 * lpUnknown [I] Object supporting the IOleControlSite interface.
1858 * lpMsg [I] Key message to be processed.
1859 * dwModifiers [I] Flags containing the state of the modifier keys.
1863 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1865 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1867 IOleControlSite* lpCSite = NULL;
1868 HRESULT hRet = E_INVALIDARG;
1870 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1873 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1875 if (SUCCEEDED(hRet) && lpCSite)
1877 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1878 IOleControlSite_Release(lpCSite);
1885 /*************************************************************************
1888 * Call IOleControlSite_OnFocus() on an object.
1891 * lpUnknown [I] Object supporting the IOleControlSite interface.
1892 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1896 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1898 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
1900 IOleControlSite* lpCSite = NULL;
1901 HRESULT hRet = E_FAIL;
1903 TRACE("(%p, %d)\n", lpUnknown, fGotFocus);
1906 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1908 if (SUCCEEDED(hRet) && lpCSite)
1910 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1911 IOleControlSite_Release(lpCSite);
1917 /*************************************************************************
1920 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1921 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1923 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1924 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1925 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1926 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1927 HRESULT hRet = E_INVALIDARG;
1928 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1930 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1932 if (lpUnknown && lpArg4)
1934 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1935 (REFGUID)function_id, (void**)&lpUnkInner);
1937 if (SUCCEEDED(hRet) && lpUnkInner)
1939 /* FIXME: The type of service object requested is unknown, however
1940 * testing shows that its first method is called with 4 parameters.
1941 * Fake this by using IParseDisplayName_ParseDisplayName since the
1942 * signature and position in the vtable matches our unknown object type.
1944 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1945 lpArg1, lpArg2, lpArg3, lpArg4);
1946 IUnknown_Release(lpUnkInner);
1952 /*************************************************************************
1955 * Get a sub-menu from a menu item.
1958 * hMenu [I] Menu to get sub-menu from
1959 * uID [I] ID of menu item containing sub-menu
1962 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1964 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1968 TRACE("(%p,%u)\n", hMenu, uID);
1970 mi.cbSize = sizeof(mi);
1971 mi.fMask = MIIM_SUBMENU;
1973 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1979 /*************************************************************************
1982 * Get the color depth of the primary display.
1988 * The color depth of the primary display.
1990 DWORD WINAPI SHGetCurColorRes(void)
1998 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
2003 /*************************************************************************
2006 * Wait for a message to arrive, with a timeout.
2009 * hand [I] Handle to query
2010 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
2013 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
2014 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
2015 * message is available.
2017 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
2019 DWORD dwEndTicks = GetTickCount() + dwTimeout;
2022 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
2026 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
2028 if (dwTimeout != INFINITE)
2030 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
2031 return WAIT_TIMEOUT;
2038 /*************************************************************************
2041 * Determine if a shell folder can be expanded.
2044 * lpFolder [I] Parent folder containing the object to test.
2045 * pidl [I] Id of the object to test.
2048 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2049 * Failure: E_INVALIDARG, if any argument is invalid.
2052 * If the object to be tested does not expose the IQueryInfo() interface it
2053 * will not be identified as an expandable folder.
2055 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
2057 HRESULT hRet = E_INVALIDARG;
2060 if (lpFolder && pidl)
2062 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
2063 NULL, (void**)&lpInfo);
2065 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
2070 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2071 * currently used". Really? You wouldn't be holding out on me would you?
2073 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
2075 if (SUCCEEDED(hRet))
2077 /* 0x2 is an undocumented flag apparently indicating expandability */
2078 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
2081 IQueryInfo_Release(lpInfo);
2087 /*************************************************************************
2090 * Blank out a region of text by drawing the background only.
2093 * hDC [I] Device context to draw in
2094 * pRect [I] Area to draw in
2095 * cRef [I] Color to draw in
2100 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2102 COLORREF cOldColor = SetBkColor(hDC, cRef);
2103 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2104 SetBkColor(hDC, cOldColor);
2108 /*************************************************************************
2111 * Return the value associated with a key in a map.
2114 * lpKeys [I] A list of keys of length iLen
2115 * lpValues [I] A list of values associated with lpKeys, of length iLen
2116 * iLen [I] Length of both lpKeys and lpValues
2117 * iKey [I] The key value to look up in lpKeys
2120 * The value in lpValues associated with iKey, or -1 if iKey is not
2124 * - If two elements in the map share the same key, this function returns
2125 * the value closest to the start of the map
2126 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2128 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2130 if (lpKeys && lpValues)
2136 if (lpKeys[i] == iKey)
2137 return lpValues[i]; /* Found */
2141 return -1; /* Not found */
2145 /*************************************************************************
2148 * Copy an interface pointer
2151 * lppDest [O] Destination for copy
2152 * lpUnknown [I] Source for copy
2157 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2159 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2161 IUnknown_AtomicRelease(lppDest);
2165 IUnknown_AddRef(lpUnknown);
2166 *lppDest = lpUnknown;
2170 /*************************************************************************
2174 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2175 REFGUID riidCmdGrp, ULONG cCmds,
2176 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2178 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2179 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2181 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2182 return DRAGDROP_E_NOTREGISTERED;
2185 /*************************************************************************
2189 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2190 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2193 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2194 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2195 return DRAGDROP_E_NOTREGISTERED;
2198 /*************************************************************************
2202 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2204 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2205 return DRAGDROP_E_NOTREGISTERED;
2208 /*************************************************************************
2211 * Determine if a window is not a child of another window.
2214 * hParent [I] Suspected parent window
2215 * hChild [I] Suspected child window
2218 * TRUE: If hChild is a child window of hParent
2219 * FALSE: If hChild is not a child window of hParent, or they are equal
2221 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2223 TRACE("(%p,%p)\n", hParent, hChild);
2225 if (!hParent || !hChild)
2227 else if(hParent == hChild)
2229 return !IsChild(hParent, hChild);
2232 /*************************************************************************
2233 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2238 DWORD num_items; /* Number of elements inserted */
2239 void *mem; /* Ptr to array */
2240 DWORD blocks_alloced; /* Number of elements allocated */
2241 BYTE inc; /* Number of elements to grow by when we need to expand */
2242 BYTE block_size; /* Size in bytes of an element */
2243 BYTE flags; /* Flags */
2246 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2248 /*************************************************************************
2251 * Initialize an FDSA array.
2253 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2256 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2262 memset(mem, 0, block_size * init_blocks);
2264 info->num_items = 0;
2267 info->blocks_alloced = init_blocks;
2268 info->block_size = block_size;
2274 /*************************************************************************
2277 * Destroy an FDSA array
2279 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2281 TRACE("(%p)\n", info);
2283 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2285 HeapFree(GetProcessHeap(), 0, info->mem);
2292 /*************************************************************************
2295 * Insert element into an FDSA array
2297 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
2299 TRACE("(%p 0x%08x %p)\n", info, where, block);
2300 if(where > info->num_items)
2301 where = info->num_items;
2303 if(info->num_items >= info->blocks_alloced)
2305 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2306 if(info->flags & 0x1)
2307 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2310 void *old_mem = info->mem;
2311 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2312 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2314 info->blocks_alloced += info->inc;
2318 if(where < info->num_items)
2320 memmove((char*)info->mem + (where + 1) * info->block_size,
2321 (char*)info->mem + where * info->block_size,
2322 (info->num_items - where) * info->block_size);
2324 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2330 /*************************************************************************
2333 * Delete an element from an FDSA array.
2335 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2337 TRACE("(%p 0x%08x)\n", info, where);
2339 if(where >= info->num_items)
2342 if(where < info->num_items - 1)
2344 memmove((char*)info->mem + where * info->block_size,
2345 (char*)info->mem + (where + 1) * info->block_size,
2346 (info->num_items - where - 1) * info->block_size);
2348 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2349 0, info->block_size);
2354 /*************************************************************************
2357 * Call IUnknown_QueryInterface() on a table of objects.
2361 * Failure: E_POINTER or E_NOINTERFACE.
2363 HRESULT WINAPI QISearch(
2364 void *base, /* [in] Table of interfaces */
2365 const QITAB *table, /* [in] Array of REFIIDs and indexes into the table */
2366 REFIID riid, /* [in] REFIID to get interface for */
2367 void **ppv) /* [out] Destination for interface pointer */
2373 TRACE("(%p %p %s %p)\n", base, table, debugstr_guid(riid), ppv);
2376 while (xmove->piid) {
2377 TRACE("trying (offset %d) %s\n", xmove->dwOffset, debugstr_guid(xmove->piid));
2378 if (IsEqualIID(riid, xmove->piid)) {
2379 a_vtbl = (IUnknown*)(xmove->dwOffset + (LPBYTE)base);
2380 TRACE("matched, returning (%p)\n", a_vtbl);
2382 IUnknown_AddRef(a_vtbl);
2388 if (IsEqualIID(riid, &IID_IUnknown)) {
2389 a_vtbl = (IUnknown*)(table->dwOffset + (LPBYTE)base);
2390 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2392 IUnknown_AddRef(a_vtbl);
2396 ret = E_NOINTERFACE;
2400 TRACE("-- 0x%08x\n", ret);
2404 /*************************************************************************
2407 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2410 * hWnd [I] Parent Window to set the property
2411 * id [I] Index of child Window to set the Font
2417 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id)
2419 FIXME("(%p, %d) stub\n", hWnd, id);
2423 /*************************************************************************
2426 * Remove the "PropDlgFont" property from a window.
2429 * hWnd [I] Window to remove the property from
2432 * A handle to the removed property, or NULL if it did not exist.
2434 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2438 TRACE("(%p)\n", hWnd);
2440 hProp = GetPropA(hWnd, "PropDlgFont");
2444 DeleteObject(hProp);
2445 hProp = RemovePropA(hWnd, "PropDlgFont");
2450 /*************************************************************************
2453 * Load the in-process server of a given GUID.
2456 * refiid [I] GUID of the server to load.
2459 * Success: A handle to the loaded server dll.
2460 * Failure: A NULL handle.
2462 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2466 CHAR value[MAX_PATH], string[MAX_PATH];
2468 strcpy(string, "CLSID\\");
2469 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2470 strcat(string, "\\InProcServer32");
2473 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2474 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2475 RegCloseKey(newkey);
2476 return LoadLibraryExA(value, 0, 0);
2479 /*************************************************************************
2482 * Unicode version of SHLWAPI_183.
2484 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2488 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2490 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2492 return RegisterClassW(lpWndClass);
2495 /*************************************************************************
2498 * Unregister a list of classes.
2501 * hInst [I] Application instance that registered the classes
2502 * lppClasses [I] List of class names
2503 * iCount [I] Number of names in lppClasses
2508 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2512 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2516 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2517 UnregisterClassA(*lppClasses, hInst);
2523 /*************************************************************************
2526 * Unicode version of SHUnregisterClassesA.
2528 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2532 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2536 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2537 UnregisterClassW(*lppClasses, hInst);
2543 /*************************************************************************
2546 * Call The correct (Ascii/Unicode) default window procedure for a window.
2549 * hWnd [I] Window to call the default procedure for
2550 * uMessage [I] Message ID
2551 * wParam [I] WPARAM of message
2552 * lParam [I] LPARAM of message
2555 * The result of calling DefWindowProcA() or DefWindowProcW().
2557 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2559 if (IsWindowUnicode(hWnd))
2560 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2561 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2564 /*************************************************************************
2567 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2569 HRESULT hRet = E_INVALIDARG;
2570 LPOBJECTWITHSITE lpSite = NULL;
2572 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2574 if (lpUnknown && iid && lppSite)
2576 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2578 if (SUCCEEDED(hRet) && lpSite)
2580 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2581 IObjectWithSite_Release(lpSite);
2587 /*************************************************************************
2590 * Create a worker window using CreateWindowExA().
2593 * wndProc [I] Window procedure
2594 * hWndParent [I] Parent window
2595 * dwExStyle [I] Extra style flags
2596 * dwStyle [I] Style flags
2597 * hMenu [I] Window menu
2598 * wnd_extra [I] Window extra bytes value
2601 * Success: The window handle of the newly created window.
2604 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2605 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra)
2607 static const char szClass[] = "WorkerA";
2611 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2612 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
2614 /* Create Window class */
2616 wc.lpfnWndProc = DefWindowProcA;
2618 wc.cbWndExtra = sizeof(LONG_PTR);
2619 wc.hInstance = shlwapi_hInstance;
2621 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2622 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2623 wc.lpszMenuName = NULL;
2624 wc.lpszClassName = szClass;
2626 SHRegisterClassA(&wc);
2628 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2629 hWndParent, hMenu, shlwapi_hInstance, 0);
2632 SetWindowLongPtrW(hWnd, 0, wnd_extra);
2634 if (wndProc) SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2640 typedef struct tagPOLICYDATA
2642 DWORD policy; /* flags value passed to SHRestricted */
2643 LPCWSTR appstr; /* application str such as "Explorer" */
2644 LPCWSTR keystr; /* name of the actual registry key / policy */
2645 } POLICYDATA, *LPPOLICYDATA;
2647 #define SHELL_NO_POLICY 0xffffffff
2649 /* default shell policy registry key */
2650 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2651 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2652 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2653 '\\','P','o','l','i','c','i','e','s',0};
2655 /*************************************************************************
2658 * Retrieve a policy value from the registry.
2661 * lpSubKey [I] registry key name
2662 * lpSubName [I] subname of registry key
2663 * lpValue [I] value name of registry value
2666 * the value associated with the registry key or 0 if not found
2668 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2670 DWORD retval, datsize = sizeof(retval);
2674 lpSubKey = strRegistryPolicyW;
2676 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2677 if (retval != ERROR_SUCCESS)
2678 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2679 if (retval != ERROR_SUCCESS)
2682 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2687 /*************************************************************************
2690 * Helper function to retrieve the possibly cached value for a specific policy
2693 * policy [I] The policy to look for
2694 * initial [I] Main registry key to open, if NULL use default
2695 * polTable [I] Table of known policies, 0 terminated
2696 * polArr [I] Cache array of policy values
2699 * The retrieved policy value or 0 if not successful
2702 * This function is used by the native SHRestricted function to search for the
2703 * policy and cache it once retrieved. The current Wine implementation uses a
2704 * different POLICYDATA structure and implements a similar algorithm adapted to
2707 DWORD WINAPI SHRestrictionLookup(
2710 LPPOLICYDATA polTable,
2713 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2715 if (!polTable || !polArr)
2718 for (;polTable->policy; polTable++, polArr++)
2720 if (policy == polTable->policy)
2722 /* we have a known policy */
2724 /* check if this policy has been cached */
2725 if (*polArr == SHELL_NO_POLICY)
2726 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2730 /* we don't know this policy, return 0 */
2731 TRACE("unknown policy: (%08x)\n", policy);
2735 /*************************************************************************
2738 * Get an interface from an object.
2741 * Success: S_OK. ppv contains the requested interface.
2742 * Failure: An HRESULT error code.
2745 * This QueryInterface asks the inner object for an interface. In case
2746 * of aggregation this request would be forwarded by the inner to the
2747 * outer object. This function asks the inner object directly for the
2748 * interface circumventing the forwarding to the outer object.
2750 HRESULT WINAPI SHWeakQueryInterface(
2751 IUnknown * pUnk, /* [in] Outer object */
2752 IUnknown * pInner, /* [in] Inner object */
2753 IID * riid, /* [in] Interface GUID to query for */
2754 LPVOID* ppv) /* [out] Destination for queried interface */
2756 HRESULT hret = E_NOINTERFACE;
2757 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2760 if(pUnk && pInner) {
2761 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2762 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2764 TRACE("-- 0x%08x\n", hret);
2768 /*************************************************************************
2771 * Move a reference from one interface to another.
2774 * lpDest [O] Destination to receive the reference
2775 * lppUnknown [O] Source to give up the reference to lpDest
2780 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2782 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2787 IUnknown_AddRef(lpDest);
2788 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2792 /*************************************************************************
2795 * Convert an ASCII string of a CLSID into a CLSID.
2798 * idstr [I] String representing a CLSID in registry format
2799 * id [O] Destination for the converted CLSID
2802 * Success: TRUE. id contains the converted CLSID.
2805 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2808 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2809 return SUCCEEDED(CLSIDFromString(wClsid, id));
2812 /*************************************************************************
2815 * Unicode version of GUIDFromStringA.
2817 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2819 return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id));
2822 /*************************************************************************
2825 * Determine if the browser is integrated into the shell, and set a registry
2832 * 1, If the browser is not integrated.
2833 * 2, If the browser is integrated.
2836 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2837 * either set to TRUE, or removed depending on whether the browser is deemed
2840 DWORD WINAPI WhichPlatform(void)
2842 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2843 static DWORD dwState = 0;
2845 DWORD dwRet, dwData, dwSize;
2851 /* If shell32 exports DllGetVersion(), the browser is integrated */
2853 hshell32 = LoadLibraryA("shell32.dll");
2856 FARPROC pDllGetVersion;
2857 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2858 dwState = pDllGetVersion ? 2 : 1;
2859 FreeLibrary(hshell32);
2862 /* Set or delete the key accordingly */
2863 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2864 "Software\\Microsoft\\Internet Explorer", 0,
2865 KEY_ALL_ACCESS, &hKey);
2868 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2869 (LPBYTE)&dwData, &dwSize);
2871 if (!dwRet && dwState == 1)
2873 /* Value exists but browser is not integrated */
2874 RegDeleteValueA(hKey, szIntegratedBrowser);
2876 else if (dwRet && dwState == 2)
2878 /* Browser is integrated but value does not exist */
2880 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2881 (LPBYTE)&dwData, sizeof(dwData));
2888 /*************************************************************************
2891 * Unicode version of SHCreateWorkerWindowA.
2893 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2894 DWORD dwStyle, HMENU hMenu, LONG msg_result)
2896 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
2900 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
2901 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
2903 /* If our OS is natively ANSI, use the ANSI version */
2904 if (GetVersion() & 0x80000000) /* not NT */
2906 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
2907 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
2910 /* Create Window class */
2912 wc.lpfnWndProc = DefWindowProcW;
2915 wc.hInstance = shlwapi_hInstance;
2917 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2918 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2919 wc.lpszMenuName = NULL;
2920 wc.lpszClassName = szClass;
2922 SHRegisterClassW(&wc);
2924 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2925 hWndParent, hMenu, shlwapi_hInstance, 0);
2928 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, msg_result);
2930 if (wndProc) SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2936 /*************************************************************************
2939 * Get and show a context menu from a shell folder.
2942 * hWnd [I] Window displaying the shell folder
2943 * lpFolder [I] IShellFolder interface
2944 * lpApidl [I] Id for the particular folder desired
2948 * Failure: An HRESULT error code indicating the error.
2950 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2952 TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl);
2953 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2956 /*************************************************************************
2959 * _SHPackDispParamsV
2961 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist)
2965 TRACE("(%p %p %u ...)\n", params, args, cnt);
2967 params->rgvarg = args;
2968 params->rgdispidNamedArgs = NULL;
2969 params->cArgs = cnt;
2970 params->cNamedArgs = 0;
2974 while(iter-- > args) {
2975 V_VT(iter) = va_arg(valist, enum VARENUM);
2977 TRACE("vt=%d\n", V_VT(iter));
2979 if(V_VT(iter) & VT_BYREF) {
2980 V_BYREF(iter) = va_arg(valist, LPVOID);
2982 switch(V_VT(iter)) {
2984 V_I4(iter) = va_arg(valist, LONG);
2987 V_BSTR(iter) = va_arg(valist, BSTR);
2990 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
2993 V_BOOL(iter) = va_arg(valist, int);
2996 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
3000 V_I4(iter) = va_arg(valist, LONG);
3008 /*************************************************************************
3013 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...)
3015 __ms_va_list valist;
3018 __ms_va_start(valist, cnt);
3019 hres = SHPackDispParamsV(params, args, cnt, valist);
3020 __ms_va_end(valist);
3024 /*************************************************************************
3025 * SHLWAPI_InvokeByIID
3027 * This helper function calls IDispatch::Invoke for each sink
3028 * which implements given iid or IDispatch.
3031 static HRESULT SHLWAPI_InvokeByIID(
3032 IConnectionPoint* iCP,
3035 DISPPARAMS* dispParams)
3037 IEnumConnections *enumerator;
3039 static DISPPARAMS empty = {NULL, NULL, 0, 0};
3040 DISPPARAMS* params = dispParams;
3042 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
3046 /* Invoke is never happening with an NULL dispParams */
3050 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
3052 IDispatch *dispIface;
3053 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
3054 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
3056 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
3057 IDispatch_Release(dispIface);
3059 IUnknown_Release(rgcd.pUnk);
3062 IEnumConnections_Release(enumerator);
3067 /*************************************************************************
3068 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3070 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP,
3071 DISPID dispId, DISPPARAMS* dispParams,
3072 DWORD unknown1, DWORD unknown2 )
3077 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
3079 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3080 if (SUCCEEDED(result))
3081 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3083 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3089 /*************************************************************************
3092 * IConnectionPoint_SimpleInvoke
3094 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
3095 IConnectionPoint* iCP,
3097 DISPPARAMS* dispParams)
3102 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
3104 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3105 if (SUCCEEDED(result))
3106 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3108 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3113 /*************************************************************************
3116 * Notify an IConnectionPoint object of changes.
3119 * lpCP [I] Object to notify
3124 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3125 * IConnectionPoint interface.
3127 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
3129 IEnumConnections *lpEnum;
3130 HRESULT hRet = E_NOINTERFACE;
3132 TRACE("(%p,0x%8X)\n", lpCP, dispID);
3134 /* Get an enumerator for the connections */
3136 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
3138 if (SUCCEEDED(hRet))
3140 IPropertyNotifySink *lpSink;
3141 CONNECTDATA connData;
3144 /* Call OnChanged() for every notify sink in the connection point */
3145 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
3147 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
3150 IPropertyNotifySink_OnChanged(lpSink, dispID);
3151 IPropertyNotifySink_Release(lpSink);
3153 IUnknown_Release(connData.pUnk);
3156 IEnumConnections_Release(lpEnum);
3161 /*************************************************************************
3164 * IUnknown_CPContainerInvokeParam
3166 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
3167 IUnknown *container,
3174 IConnectionPoint *iCP;
3175 IConnectionPointContainer *iCPC;
3176 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3177 __ms_va_list valist;
3180 return E_NOINTERFACE;
3182 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
3186 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
3187 IConnectionPointContainer_Release(iCPC);
3191 __ms_va_start(valist, cParams);
3192 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
3193 __ms_va_end(valist);
3195 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3196 IConnectionPoint_Release(iCP);
3201 /*************************************************************************
3204 * Notify an IConnectionPointContainer object of changes.
3207 * lpUnknown [I] Object to notify
3212 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3213 * IConnectionPointContainer interface.
3215 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3217 IConnectionPointContainer* lpCPC = NULL;
3218 HRESULT hRet = E_NOINTERFACE;
3220 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3223 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3225 if (SUCCEEDED(hRet))
3227 IConnectionPoint* lpCP;
3229 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3230 IConnectionPointContainer_Release(lpCPC);
3232 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3233 IConnectionPoint_Release(lpCP);
3238 /*************************************************************************
3243 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3245 return PlaySoundW(pszSound, hmod, fdwSound);
3248 /*************************************************************************
3251 BOOL WINAPI SHGetIniStringW(LPCWSTR str1, LPCWSTR str2, LPWSTR pStr, DWORD some_len, LPCWSTR lpStr2)
3253 FIXME("(%s,%s,%p,%08x,%s): stub!\n", debugstr_w(str1), debugstr_w(str2),
3254 pStr, some_len, debugstr_w(lpStr2));
3258 /*************************************************************************
3261 * Called by ICQ2000b install via SHDOCVW:
3262 * str1: "InternetShortcut"
3263 * x: some unknown pointer
3264 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
3265 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
3267 * In short: this one maybe creates a desktop link :-)
3269 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
3271 FIXME("(%s, %p, %s, %s), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
3275 /*************************************************************************
3278 * See SHGetFileInfoW.
3280 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3281 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3283 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3286 /*************************************************************************
3289 * See DragQueryFileW.
3291 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3293 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3296 /*************************************************************************
3299 * See SHBrowseForFolderW.
3301 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3303 return SHBrowseForFolderW(lpBi);
3306 /*************************************************************************
3309 * See SHGetPathFromIDListW.
3311 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3313 return SHGetPathFromIDListW(pidl, pszPath);
3316 /*************************************************************************
3319 * See ShellExecuteExW.
3321 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3323 return ShellExecuteExW(lpExecInfo);
3326 /*************************************************************************
3329 * See SHFileOperationW.
3331 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3333 return SHFileOperationW(lpFileOp);
3336 /*************************************************************************
3340 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
3342 return InterlockedCompareExchangePointer( dest, xchg, compare );
3345 /*************************************************************************
3348 * See GetFileVersionInfoSizeW.
3350 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
3352 return GetFileVersionInfoSizeW( filename, handle );
3355 /*************************************************************************
3358 * See GetFileVersionInfoW.
3360 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
3361 DWORD datasize, LPVOID data )
3363 return GetFileVersionInfoW( filename, handle, datasize, data );
3366 /*************************************************************************
3369 * See VerQueryValueW.
3371 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
3372 LPVOID *lplpBuffer, UINT *puLen )
3374 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3377 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3378 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3379 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3381 /*************************************************************************
3384 * Change the modality of a shell object.
3387 * lpUnknown [I] Object to make modeless
3388 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3391 * Success: S_OK. The modality lpUnknown is changed.
3392 * Failure: An HRESULT error code indicating the error.
3395 * lpUnknown must support the IOleInPlaceFrame interface, the
3396 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3397 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3398 * or this call will fail.
3400 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3405 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3410 if (IsIface(IOleInPlaceActiveObject))
3411 EnableModeless(IOleInPlaceActiveObject);
3412 else if (IsIface(IOleInPlaceFrame))
3413 EnableModeless(IOleInPlaceFrame);
3414 else if (IsIface(IShellBrowser))
3415 EnableModeless(IShellBrowser);
3416 else if (IsIface(IInternetSecurityMgrSite))
3417 EnableModeless(IInternetSecurityMgrSite);
3418 else if (IsIface(IDocHostUIHandler))
3419 EnableModeless(IDocHostUIHandler);
3423 IUnknown_Release(lpObj);
3427 /*************************************************************************
3430 * See SHGetNewLinkInfoW.
3432 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3433 BOOL *pfMustCopy, UINT uFlags)
3435 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3438 /*************************************************************************
3441 * See SHDefExtractIconW.
3443 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3444 HICON* phiconSmall, UINT nIconSize)
3446 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3449 /*************************************************************************
3452 * Get and show a context menu from a shell folder.
3455 * hWnd [I] Window displaying the shell folder
3456 * lpFolder [I] IShellFolder interface
3457 * lpApidl [I] Id for the particular folder desired
3458 * bInvokeDefault [I] Whether to invoke the default menu item
3461 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3463 * Failure: An HRESULT error code indicating the error.
3465 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3467 IContextMenu *iContext;
3470 TRACE("(%p, %p, %p, %d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3475 /* Get the context menu from the shell folder */
3476 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3477 &IID_IContextMenu, 0, (void**)&iContext);
3478 if (SUCCEEDED(hRet))
3481 if ((hMenu = CreatePopupMenu()))
3484 DWORD dwDefaultId = 0;
3486 /* Add the context menu entries to the popup */
3487 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3488 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3490 if (SUCCEEDED(hQuery))
3492 if (bInvokeDefault &&
3493 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != (UINT)-1)
3495 CMINVOKECOMMANDINFO cmIci;
3496 /* Invoke the default item */
3497 memset(&cmIci,0,sizeof(cmIci));
3498 cmIci.cbSize = sizeof(cmIci);
3499 cmIci.fMask = CMIC_MASK_ASYNCOK;
3501 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3502 cmIci.nShow = SW_SCROLLCHILDREN;
3504 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3509 IContextMenu_Release(iContext);
3514 /*************************************************************************
3519 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3522 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3525 /*************************************************************************
3528 * Load a library from the directory of a particular process.
3531 * new_mod [I] Library name
3532 * inst_hwnd [I] Module whose directory is to be used
3533 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3536 * Success: A handle to the loaded module
3537 * Failure: A NULL handle.
3539 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3541 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3543 * FIXME: Native shows calls to:
3544 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3546 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3547 * RegQueryValueExA for "LPKInstalled"
3549 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3550 * RegQueryValueExA for "ResourceLocale"
3552 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3553 * RegQueryValueExA for "Locale"
3555 * and then tests the Locale ("en" for me).
3557 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3559 CHAR mod_path[2*MAX_PATH];
3563 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3564 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3565 if (!len || len >= sizeof(mod_path)) return NULL;
3567 ptr = strrchr(mod_path, '\\');
3569 strcpy(ptr+1, new_mod);
3570 TRACE("loading %s\n", debugstr_a(mod_path));
3571 return LoadLibraryA(mod_path);
3576 /*************************************************************************
3579 * Unicode version of MLLoadLibraryA.
3581 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3583 WCHAR mod_path[2*MAX_PATH];
3587 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3588 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3589 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3591 ptr = strrchrW(mod_path, '\\');
3593 strcpyW(ptr+1, new_mod);
3594 TRACE("loading %s\n", debugstr_w(mod_path));
3595 return LoadLibraryW(mod_path);
3600 /*************************************************************************
3601 * ColorAdjustLuma [SHLWAPI.@]
3603 * Adjust the luminosity of a color
3606 * cRGB [I] RGB value to convert
3607 * dwLuma [I] Luma adjustment
3608 * bUnknown [I] Unknown
3611 * The adjusted RGB color.
3613 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3615 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3621 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3623 FIXME("Ignoring luma adjustment\n");
3625 /* FIXME: The adjustment is not linear */
3627 cRGB = ColorHLSToRGB(wH, wL, wS);
3632 /*************************************************************************
3635 * See GetSaveFileNameW.
3637 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3639 return GetSaveFileNameW(ofn);
3642 /*************************************************************************
3645 * See WNetRestoreConnectionW.
3647 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3649 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3652 /*************************************************************************
3655 * See WNetGetLastErrorW.
3657 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3658 LPWSTR lpNameBuf, DWORD nNameBufSize)
3660 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3663 /*************************************************************************
3666 * See PageSetupDlgW.
3668 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3670 return PageSetupDlgW(pagedlg);
3673 /*************************************************************************
3678 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3680 return PrintDlgW(printdlg);
3683 /*************************************************************************
3686 * See GetOpenFileNameW.
3688 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3690 return GetOpenFileNameW(ofn);
3693 /*************************************************************************
3696 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3701 hr = IShellFolder_QueryInterface(lpFolder, &IID_IPersist, (LPVOID)&persist);
3705 hr = IPersist_GetClassID(persist, &clsid);
3708 if(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder))
3709 hr = IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3713 IPersist_Release(persist);
3718 /* INTERNAL: Map from HLS color space to RGB */
3719 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3721 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3725 else if (wHue > 120)
3730 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3733 /* Convert to RGB and scale into RGB range (0..255) */
3734 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3736 /*************************************************************************
3737 * ColorHLSToRGB [SHLWAPI.@]
3739 * Convert from hls color space into an rgb COLORREF.
3742 * wHue [I] Hue amount
3743 * wLuminosity [I] Luminosity amount
3744 * wSaturation [I] Saturation amount
3747 * A COLORREF representing the converted color.
3750 * Input hls values are constrained to the range (0..240).
3752 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3758 WORD wGreen, wBlue, wMid1, wMid2;
3760 if (wLuminosity > 120)
3761 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3763 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3765 wMid1 = wLuminosity * 2 - wMid2;
3767 wRed = GET_RGB(wHue + 80);
3768 wGreen = GET_RGB(wHue);
3769 wBlue = GET_RGB(wHue - 80);
3771 return RGB(wRed, wGreen, wBlue);
3774 wRed = wLuminosity * 255 / 240;
3775 return RGB(wRed, wRed, wRed);
3778 /*************************************************************************
3781 * Get the current docking status of the system.
3784 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3787 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3790 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3792 HW_PROFILE_INFOA hwInfo;
3794 TRACE("(0x%08x)\n", dwFlags);
3796 GetCurrentHwProfileA(&hwInfo);
3797 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3799 case DOCKINFO_DOCKED:
3800 case DOCKINFO_UNDOCKED:
3801 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3807 /*************************************************************************
3810 * Function seems to do FreeLibrary plus other things.
3812 * FIXME native shows the following calls:
3813 * RtlEnterCriticalSection
3815 * GetProcAddress(Comctl32??, 150L)
3817 * RtlLeaveCriticalSection
3818 * followed by the FreeLibrary.
3819 * The above code may be related to .377 above.
3821 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3823 FIXME("(%p) semi-stub\n", hModule);
3824 return FreeLibrary(hModule);
3827 /*************************************************************************
3830 BOOL WINAPI SHFlushSFCacheWrap(void) {
3835 /*************************************************************************
3837 * FIXME I have no idea what this function does or what its arguments are.
3839 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3841 FIXME("(%p) stub\n", hInst);
3846 /*************************************************************************
3849 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3851 FIXME("(%p,%p) stub\n", hInst, hHeap);
3852 return E_FAIL; /* This is what is used if shlwapi not loaded */
3855 /*************************************************************************
3858 DWORD WINAPI MLClearMLHInstance(DWORD x)
3860 FIXME("(0x%08x)stub\n", x);
3864 /*************************************************************************
3867 * See SHSendMessageBroadcastW
3870 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam)
3872 return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam,
3873 SMTO_ABORTIFHUNG, 2000, NULL);
3876 /*************************************************************************
3879 * A wrapper for sending Broadcast Messages to all top level Windows
3882 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam)
3884 return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam,
3885 SMTO_ABORTIFHUNG, 2000, NULL);
3888 /*************************************************************************
3891 * Convert a Unicode string CLSID into a CLSID.
3894 * idstr [I] string containing a CLSID in text form
3895 * id [O] CLSID extracted from the string
3898 * S_OK on success or E_INVALIDARG on failure
3900 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3902 return CLSIDFromString((LPCOLESTR)idstr, id);
3905 /*************************************************************************
3908 * Determine if the OS supports a given feature.
3911 * dwFeature [I] Feature requested (undocumented)
3914 * TRUE If the feature is available.
3915 * FALSE If the feature is not available.
3917 BOOL WINAPI IsOS(DWORD feature)
3919 OSVERSIONINFOA osvi;
3920 DWORD platform, majorv, minorv;
3922 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3923 if(!GetVersionExA(&osvi)) {
3924 ERR("GetVersionEx failed\n");
3928 majorv = osvi.dwMajorVersion;
3929 minorv = osvi.dwMinorVersion;
3930 platform = osvi.dwPlatformId;
3932 #define ISOS_RETURN(x) \
3933 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3937 case OS_WIN32SORGREATER:
3938 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3939 || platform == VER_PLATFORM_WIN32_WINDOWS)
3941 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3942 case OS_WIN95ORGREATER:
3943 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3944 case OS_NT4ORGREATER:
3945 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3946 case OS_WIN2000ORGREATER_ALT:
3947 case OS_WIN2000ORGREATER:
3948 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3949 case OS_WIN98ORGREATER:
3950 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3952 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3954 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3955 case OS_WIN2000SERVER:
3956 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3957 case OS_WIN2000ADVSERVER:
3958 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3959 case OS_WIN2000DATACENTER:
3960 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3961 case OS_WIN2000TERMINAL:
3962 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3964 FIXME("(OS_EMBEDDED) What should we return here?\n");
3966 case OS_TERMINALCLIENT:
3967 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3969 case OS_TERMINALREMOTEADMIN:
3970 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3973 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3974 case OS_MEORGREATER:
3975 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3976 case OS_XPORGREATER:
3977 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3979 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3980 case OS_PROFESSIONAL:
3981 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3983 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3985 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3987 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3988 case OS_TERMINALSERVER:
3989 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3990 case OS_PERSONALTERMINALSERVER:
3991 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3992 case OS_FASTUSERSWITCHING:
3993 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3995 case OS_WELCOMELOGONUI:
3996 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3998 case OS_DOMAINMEMBER:
3999 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
4002 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4004 FIXME("(OS_WOW6432) Should we check this?\n");
4007 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4008 case OS_SMALLBUSINESSSERVER:
4009 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4011 FIXME("(OS_TABLEPC) What should we return here?\n");
4013 case OS_SERVERADMINUI:
4014 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
4016 case OS_MEDIACENTER:
4017 FIXME("(OS_MEDIACENTER) What should we return here?\n");
4020 FIXME("(OS_APPLIANCE) What should we return here?\n");
4022 case 0x25: /*OS_VISTAORGREATER*/
4023 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
4028 WARN("(0x%x) unknown parameter\n",feature);
4033 /*************************************************************************
4036 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
4038 DWORD type, sz = size;
4040 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
4043 return SHLoadIndirectString(buf, buf, size, NULL);
4046 /*************************************************************************
4049 * Call IInputObject_TranslateAcceleratorIO() on an object.
4052 * lpUnknown [I] Object supporting the IInputObject interface.
4053 * lpMsg [I] Key message to be processed.
4057 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4059 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
4061 IInputObject* lpInput = NULL;
4062 HRESULT hRet = E_INVALIDARG;
4064 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
4067 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4069 if (SUCCEEDED(hRet) && lpInput)
4071 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
4072 IInputObject_Release(lpInput);
4078 /*************************************************************************
4081 * Call IInputObject_HasFocusIO() on an object.
4084 * lpUnknown [I] Object supporting the IInputObject interface.
4087 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4088 * or S_FALSE otherwise.
4089 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4091 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
4093 IInputObject* lpInput = NULL;
4094 HRESULT hRet = E_INVALIDARG;
4096 TRACE("(%p)\n", lpUnknown);
4099 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4101 if (SUCCEEDED(hRet) && lpInput)
4103 hRet = IInputObject_HasFocusIO(lpInput);
4104 IInputObject_Release(lpInput);
4110 /*************************************************************************
4111 * ColorRGBToHLS [SHLWAPI.@]
4113 * Convert an rgb COLORREF into the hls color space.
4116 * cRGB [I] Source rgb value
4117 * pwHue [O] Destination for converted hue
4118 * pwLuminance [O] Destination for converted luminance
4119 * pwSaturation [O] Destination for converted saturation
4122 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4126 * Output HLS values are constrained to the range (0..240).
4127 * For Achromatic conversions, Hue is set to 160.
4129 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
4130 LPWORD pwLuminance, LPWORD pwSaturation)
4132 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4134 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4136 wR = GetRValue(cRGB);
4137 wG = GetGValue(cRGB);
4138 wB = GetBValue(cRGB);
4140 wMax = max(wR, max(wG, wB));
4141 wMin = min(wR, min(wG, wB));
4144 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4148 /* Achromatic case */
4150 /* Hue is now unrepresentable, but this is what native returns... */
4155 /* Chromatic case */
4156 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4159 if (wLuminosity <= 120)
4160 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4162 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4165 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4166 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4167 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4170 wHue = wBNorm - wGNorm;
4171 else if (wG == wMax)
4172 wHue = 80 + wRNorm - wBNorm;
4174 wHue = 160 + wGNorm - wRNorm;
4177 else if (wHue > 240)
4183 *pwLuminance = wLuminosity;
4185 *pwSaturation = wSaturation;
4188 /*************************************************************************
4189 * SHCreateShellPalette [SHLWAPI.@]
4191 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4194 return CreateHalftonePalette(hdc);
4197 /*************************************************************************
4198 * SHGetInverseCMAP (SHLWAPI.@)
4200 * Get an inverse color map table.
4203 * lpCmap [O] Destination for color map
4204 * dwSize [I] Size of memory pointed to by lpCmap
4208 * Failure: E_POINTER, If lpCmap is invalid.
4209 * E_INVALIDARG, If dwFlags is invalid
4210 * E_OUTOFMEMORY, If there is no memory available
4213 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4214 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4216 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4217 * this DLL's internal CMap.
4219 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4222 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4223 *dest = (DWORD)0xabba1249;
4226 FIXME("(%p, %#x) stub\n", dest, dwSize);
4230 /*************************************************************************
4231 * SHIsLowMemoryMachine [SHLWAPI.@]
4233 * Determine if the current computer has low memory.
4239 * TRUE if the users machine has 16 Megabytes of memory or less,
4242 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4244 FIXME("(0x%08x) stub\n", x);
4248 /*************************************************************************
4249 * GetMenuPosFromID [SHLWAPI.@]
4251 * Return the position of a menu item from its Id.
4254 * hMenu [I] Menu containing the item
4255 * wID [I] Id of the menu item
4258 * Success: The index of the menu item in hMenu.
4259 * Failure: -1, If the item is not found.
4261 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4264 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4266 TRACE("%p %u\n", hMenu, wID);
4268 while (nIter < nCount)
4270 mi.cbSize = sizeof(mi);
4272 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4274 TRACE("ret %d\n", nIter);
4283 /*************************************************************************
4286 * Same as SHLWAPI.GetMenuPosFromID
4288 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4290 TRACE("%p %u\n", hMenu, uID);
4291 return GetMenuPosFromID(hMenu, uID);
4295 /*************************************************************************
4298 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4309 /*************************************************************************
4312 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4314 FIXME("(0x%08x) stub\n", dwUnknown);
4319 /*************************************************************************
4322 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4323 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4325 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4328 /*************************************************************************
4329 * SHSkipJunction [SHLWAPI.@]
4331 * Determine if a bind context can be bound to an object
4334 * pbc [I] Bind context to check
4335 * pclsid [I] CLSID of object to be bound to
4338 * TRUE: If it is safe to bind
4339 * FALSE: If pbc is invalid or binding would not be safe
4342 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4344 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4345 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4352 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4356 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4357 IsEqualGUID(pclsid, &clsid))
4360 IUnknown_Release(lpUnk);
4366 /***********************************************************************
4367 * SHGetShellKey (SHLWAPI.@)
4369 HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create)
4371 FIXME("(0x%08x, %s, %d): stub\n", flags, debugstr_w(sub_key), create);
4375 /***********************************************************************
4376 * SHQueueUserWorkItem (SHLWAPI.@)
4378 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback,
4379 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4380 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4382 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4383 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4385 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4386 FIXME("Unsupported arguments\n");
4388 return QueueUserWorkItem(pfnCallback, pContext, 0);
4391 /***********************************************************************
4392 * SHSetTimerQueueTimer (SHLWAPI.263)
4394 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
4395 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4396 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4400 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4401 if (dwFlags & TPS_LONGEXECTIME) {
4402 dwFlags &= ~TPS_LONGEXECTIME;
4403 dwFlags |= WT_EXECUTELONGFUNCTION;
4405 if (dwFlags & TPS_EXECUTEIO) {
4406 dwFlags &= ~TPS_EXECUTEIO;
4407 dwFlags |= WT_EXECUTEINIOTHREAD;
4410 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4411 dwDueTime, dwPeriod, dwFlags))
4417 /***********************************************************************
4418 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4420 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4422 IInputObjectSite *pIOS = NULL;
4423 HRESULT hRet = E_INVALIDARG;
4425 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4429 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4431 if (SUCCEEDED(hRet) && pIOS)
4433 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4434 IInputObjectSite_Release(pIOS);
4440 /***********************************************************************
4441 * SHGetValueW (SHLWAPI.@)
4443 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4445 FIXME("(%x, %s, %s, %x, %x, %x): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4449 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4451 /***********************************************************************
4452 * GetUIVersion (SHLWAPI.452)
4454 DWORD WINAPI GetUIVersion(void)
4456 static DWORD version;
4460 DllGetVersion_func pDllGetVersion;
4461 HMODULE dll = LoadLibraryA("shell32.dll");
4464 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4468 dvi.cbSize = sizeof(DLLVERSIONINFO);
4469 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4472 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4477 /***********************************************************************
4478 * ShellMessageBoxWrapW [SHLWAPI.388]
4480 * See shell32.ShellMessageBoxW
4483 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4484 * because we can't forward to it in the .spec file since it's exported by
4485 * ordinal. If you change the implementation here please update the code in
4488 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
4489 LPCWSTR lpCaption, UINT uType, ...)
4491 WCHAR szText[100], szTitle[100];
4492 LPCWSTR pszText = szText, pszTitle = szTitle;
4497 __ms_va_start(args, uType);
4499 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
4501 if (IS_INTRESOURCE(lpCaption))
4502 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
4504 pszTitle = lpCaption;
4506 if (IS_INTRESOURCE(lpText))
4507 LoadStringW(hInstance, LOWORD(lpText), szText, sizeof(szText)/sizeof(szText[0]));
4511 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4512 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4516 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4521 /***********************************************************************
4522 * ZoneComputePaneSize [SHLWAPI.382]
4524 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4530 /***********************************************************************
4531 * SHChangeNotifyWrap [SHLWAPI.394]
4533 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
4535 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
4538 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
4539 SID_IDENTIFIER_AUTHORITY sidAuthority;
4540 DWORD dwUserGroupID;
4542 } SHELL_USER_SID, *PSHELL_USER_SID;
4544 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
4545 SHELL_USER_SID susID;
4549 DWORD dwInheritMask;
4550 DWORD dwInheritAccessMask;
4551 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
4553 /***********************************************************************
4554 * GetShellSecurityDescriptor [SHLWAPI.475]
4556 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4559 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4560 * each of which describes permissions to apply
4561 * cUserPerm [I] number of entries in apUserPerm array
4564 * success: pointer to SECURITY_DESCRIPTOR
4568 * Call should free returned descriptor with LocalFree
4570 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4573 PSID cur_user = NULL;
4577 PSECURITY_DESCRIPTOR psd = NULL;
4579 TRACE("%p %d\n", apUserPerm, cUserPerm);
4581 if (apUserPerm == NULL || cUserPerm <= 0)
4584 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
4588 acl_size = sizeof(ACL);
4590 for(sid_count = 0; sid_count < cUserPerm; sid_count++)
4592 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
4593 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
4594 PSHELL_USER_SID sid = &perm->susID;
4598 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4599 { /* current user's SID */
4603 DWORD bufsize = sizeof(tuUser);
4605 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4608 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4610 cur_user = ((PTOKEN_USER)tuUser)->User.Sid;
4615 } else if (sid->dwUserID==0) /* one sub-authority */
4616 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
4617 0, 0, 0, 0, 0, 0, &pSid);
4619 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4620 0, 0, 0, 0, 0, 0, &pSid);
4624 sidlist[sid_count] = pSid;
4625 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4626 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
4629 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
4633 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4635 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4638 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4641 for(i = 0; i < sid_count; i++)
4643 PSHELL_USER_PERMISSION sup = apUserPerm[i];
4644 PSID sid = sidlist[i];
4646 switch(sup->dwAccessType)
4648 case ACCESS_ALLOWED_ACE_TYPE:
4649 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4651 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4652 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4655 case ACCESS_DENIED_ACE_TYPE:
4656 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4658 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4659 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4667 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4676 for(i = 0; i < sid_count; i++)
4678 if (!cur_user || sidlist[i] != cur_user)
4679 FreeSid(sidlist[i]);
4681 HeapFree(GetProcessHeap(), 0, sidlist);
4686 /***********************************************************************
4687 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4689 * Creates a property bag from a registry key
4692 * hKey [I] Handle to the desired registry key
4693 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4694 * grfMode [I] Optional flags
4695 * riid [I] IID of requested property bag interface
4696 * ppv [O] Address to receive pointer to the new interface
4700 * failure: error code
4703 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey,
4704 DWORD grfMode, REFIID riid, void **ppv)
4706 FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode,
4707 debugstr_guid(riid), ppv);
4712 /***********************************************************************
4713 * SHGetViewStatePropertyBag [SHLWAPI.515]
4715 * Retrieves a property bag in which the view state information of a folder
4719 * pidl [I] PIDL of the folder requested
4720 * bag_name [I] Name of the property bag requested
4721 * flags [I] Optional flags
4722 * riid [I] IID of requested property bag interface
4723 * ppv [O] Address to receive pointer to the new interface
4727 * failure: error code
4730 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
4731 DWORD flags, REFIID riid, void **ppv)
4733 FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags,
4734 debugstr_guid(riid), ppv);
4739 /***********************************************************************
4740 * SHFormatDateTimeW [SHLWAPI.354]
4742 * Produces a string representation of a time.
4745 * fileTime [I] Pointer to FILETIME structure specifying the time
4746 * flags [I] Flags specifying the desired output
4747 * buf [O] Pointer to buffer for output
4748 * size [I] Number of characters that can be contained in buffer
4751 * success: number of characters written to the buffer
4755 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
4756 LPWSTR buf, UINT size)
4758 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
4759 DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT;
4764 TRACE("%p %p %p %u\n", fileTime, flags, buf, size);
4769 if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS)
4770 FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS);
4772 FileTimeToLocalFileTime(fileTime, &ft);
4773 FileTimeToSystemTime(&ft, &st);
4775 /* first of all date */
4776 if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE))
4778 static const WCHAR sep1[] = {',',' ',0};
4779 static const WCHAR sep2[] = {' ',0};
4781 DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE;
4782 ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size);
4783 if (ret >= size) return ret;
4786 if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)))
4788 if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2))
4792 lstrcatW(&buf[ret-1], sep1);
4798 lstrcatW(&buf[ret-1], sep2);
4804 if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))
4806 DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS;
4809 ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret);
4814 #undef SHFORMATDT_UNSUPPORTED_FLAGS
4817 /***********************************************************************
4818 * SHFormatDateTimeA [SHLWAPI.353]
4820 * See SHFormatDateTimeW.
4823 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags,
4824 LPSTR buf, UINT size)
4832 bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
4833 retval = SHFormatDateTimeW(fileTime, flags, bufW, size);
4836 WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL);
4838 HeapFree(GetProcessHeap(), 0, bufW);
4842 /***********************************************************************
4843 * ZoneCheckUrlExW [SHLWAPI.231]
4845 * Checks the details of the security zone for the supplied site. (?)
4849 * szURL [I] Pointer to the URL to check
4851 * Other parameters currently unknown.
4857 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2,
4858 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6,
4861 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2,
4862 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7);
4867 /***********************************************************************
4868 * SHVerbExistsNA [SHLWAPI.196]
4873 * verb [I] a string, often appears to be an extension.
4875 * Other parameters currently unknown.
4880 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3)
4882 FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3);
4886 /*************************************************************************
4889 * Undocumented: Implementation guessed at via Name and behavior
4892 * lpUnknown [I] Object to get an IServiceProvider interface from
4893 * riid [I] Function requested for QueryService call
4894 * lppOut [O] Destination for the service interface pointer
4897 * Success: S_OK. lppOut contains an object providing the requested service
4898 * Failure: An HRESULT error code
4901 * lpUnknown is expected to support the IServiceProvider interface.
4903 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown,
4904 REFGUID riid, LPVOID *lppOut)
4906 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut);
4907 return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut);
4910 /**************************************************************************
4911 * SHPropertyBag_ReadLONG (SHLWAPI.496)
4913 * This function asks a property bag to read a named property as a LONG.
4916 * ppb: a IPropertyBag interface
4917 * pszPropName: Unicode string that names the property
4918 * pValue: address to receive the property value as a 32-bit signed integer
4923 BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue)
4927 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue);
4928 if (!pszPropName || !ppb || !pValue)
4929 return E_INVALIDARG;
4931 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
4934 if (V_VT(&var) == VT_I4)
4935 *pValue = V_I4(&var);
4937 hr = DISP_E_BADVARTYPE;
4942 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
4943 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
4944 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
4945 #define OBJCOMPAT_UNBINDABLE 0x00000004
4946 #define OBJCOMPAT_PINDLL 0x00000008
4947 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
4948 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
4949 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
4950 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
4951 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
4952 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
4953 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
4954 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
4955 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
4957 /* a search table for compatibility flags */
4958 struct objcompat_entry {
4959 const WCHAR name[30];
4963 /* expected to be sorted by name */
4964 static const struct objcompat_entry objcompat_table[] = {
4965 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
4966 OBJCOMPAT_COCREATESHELLFOLDERONLY },
4967 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
4968 OBJCOMPAT_CTXMENU_LIMITEDQI },
4969 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
4970 OBJCOMPAT_CTXMENU_LIMITEDQI },
4971 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
4972 OBJCOMPAT_CTXMENU_XPQCMFLAGS },
4973 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
4974 OBJCOMPAT_NEEDSFILESYSANCESTOR },
4975 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
4976 OBJCOMPAT_NEEDSSTORAGEANCESTOR },
4977 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
4978 OBJCOMPAT_NOIPROPERTYSTORE },
4979 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
4980 OBJCOMPAT_NOLEGACYWEBVIEW },
4981 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
4982 OBJCOMPAT_NOTAFILESYSTEM },
4983 { {'N','O','_','W','E','B','V','I','E','W',0},
4984 OBJCOMPAT_NO_WEBVIEW },
4985 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
4986 OBJCOMPAT_OTNEEDSSFCACHE },
4987 { {'P','I','N','D','L','L',0},
4989 { {'U','N','B','I','N','D','A','B','L','E',0},
4990 OBJCOMPAT_UNBINDABLE }
4993 /**************************************************************************
4994 * SHGetObjectCompatFlags (SHLWAPI.476)
4996 * Function returns an integer representation of compatibility flags stored
4997 * in registry for CLSID under ShellCompatibility subkey.
5000 * pUnk: pointer to object IUnknown interface, idetifies CLSID
5001 * clsid: pointer to CLSID to retrieve data for
5004 * 0 on failure, flags set on success
5006 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid)
5008 static const WCHAR compatpathW[] =
5009 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
5010 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
5011 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
5012 'O','b','j','e','c','t','s','\\','%','s',0};
5013 WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */];
5014 DWORD ret, length = sizeof(strW)/sizeof(WCHAR);
5019 TRACE("%p %s\n", pUnk, debugstr_guid(clsid));
5021 if (!pUnk && !clsid) return 0;
5025 FIXME("iface not handled\n");
5029 StringFromCLSID(clsid, &clsid_str);
5030 sprintfW(strW, compatpathW, clsid_str);
5031 CoTaskMemFree(clsid_str);
5033 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key);
5034 if (ret != ERROR_SUCCESS) return 0;
5036 /* now collect flag values */
5038 for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++)
5040 INT left, right, res, x;
5042 /* search in table */
5044 right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1;
5046 while (right >= left) {
5047 x = (left + right) / 2;
5048 res = strcmpW(strW, objcompat_table[x].name);
5051 ret |= objcompat_table[x].value;
5060 length = sizeof(strW)/sizeof(WCHAR);