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 implementation 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 IUnknown_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;
491 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
493 if(!langbuf || !buflen || !*buflen)
496 mystrlen = (*buflen > 20) ? *buflen : 20 ;
497 len = mystrlen * sizeof(WCHAR);
498 mystr = HeapAlloc(GetProcessHeap(), 0, len);
500 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
501 lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
503 len = lstrlenW(mystr);
505 if (!lres && (*buflen > len)) {
506 lstrcpyW(langbuf, mystr);
508 HeapFree(GetProcessHeap(), 0, mystr);
512 /* Did not find a value in the registry or the user buffer is too small */
513 mylcid = GetUserDefaultLCID();
514 LcidToRfc1766W(mylcid, mystr, mystrlen);
515 len = lstrlenW(mystr);
517 memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
518 HeapFree(GetProcessHeap(), 0, mystr);
526 return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
529 /*************************************************************************
532 * Ascii version of GetAcceptLanguagesW.
534 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
537 DWORD buflenW, convlen;
540 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
542 if(!langbuf || !buflen || !*buflen) return E_FAIL;
545 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
546 retval = GetAcceptLanguagesW(langbufW, &buflenW);
550 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
551 convlen--; /* do not count the terminating 0 */
553 else /* copy partial string anyway */
555 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
556 if (convlen < *buflen)
558 langbuf[convlen] = 0;
559 convlen--; /* do not count the terminating 0 */
566 *buflen = buflenW ? convlen : 0;
568 HeapFree(GetProcessHeap(), 0, langbufW);
572 /*************************************************************************
575 * Convert a GUID to a string.
578 * guid [I] GUID to convert
579 * lpszDest [O] Destination for string
580 * cchMax [I] Length of output buffer
583 * The length of the string created.
585 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
590 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
592 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
593 guid->Data1, guid->Data2, guid->Data3,
594 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
595 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
597 iLen = strlen(xguid) + 1;
601 memcpy(lpszDest, xguid, iLen);
605 /*************************************************************************
608 * Convert a GUID to a string.
611 * guid [I] GUID to convert
612 * str [O] Destination for string
613 * cmax [I] Length of output buffer
616 * The length of the string created.
618 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
622 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
623 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
624 'X','%','0','2','X','%','0','2','X','}',0};
626 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
628 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
629 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
630 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
632 iLen = strlenW(xguid) + 1;
636 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
640 /*************************************************************************
643 * Determine if a Unicode character is a blank.
646 * wc [I] Character to check.
649 * TRUE, if wc is a blank,
653 BOOL WINAPI IsCharBlankW(WCHAR wc)
657 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
660 /*************************************************************************
663 * Determine if a Unicode character is punctuation.
666 * wc [I] Character to check.
669 * TRUE, if wc is punctuation,
672 BOOL WINAPI IsCharPunctW(WCHAR wc)
676 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
679 /*************************************************************************
682 * Determine if a Unicode character is a control character.
685 * wc [I] Character to check.
688 * TRUE, if wc is a control character,
691 BOOL WINAPI IsCharCntrlW(WCHAR wc)
695 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
698 /*************************************************************************
701 * Determine if a Unicode character is a digit.
704 * wc [I] Character to check.
707 * TRUE, if wc is a digit,
710 BOOL WINAPI IsCharDigitW(WCHAR wc)
714 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
717 /*************************************************************************
720 * Determine if a Unicode character is a hex digit.
723 * wc [I] Character to check.
726 * TRUE, if wc is a hex digit,
729 BOOL WINAPI IsCharXDigitW(WCHAR wc)
733 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
736 /*************************************************************************
740 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type)
742 return GetStringTypeW(CT_CTYPE3, src, count, type);
745 /*************************************************************************
748 * Compare two Ascii strings up to a given length.
751 * lpszSrc [I] Source string
752 * lpszCmp [I] String to compare to lpszSrc
753 * len [I] Maximum length
756 * A number greater than, less than or equal to 0 depending on whether
757 * lpszSrc is greater than, less than or equal to lpszCmp.
759 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
761 return StrCmpNA(lpszSrc, lpszCmp, len);
764 /*************************************************************************
767 * Unicode version of StrCmpNCA.
769 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
771 return StrCmpNW(lpszSrc, lpszCmp, len);
774 /*************************************************************************
777 * Compare two Ascii strings up to a given length, ignoring case.
780 * lpszSrc [I] Source string
781 * lpszCmp [I] String to compare to lpszSrc
782 * len [I] Maximum length
785 * A number greater than, less than or equal to 0 depending on whether
786 * lpszSrc is greater than, less than or equal to lpszCmp.
788 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
790 return StrCmpNIA(lpszSrc, lpszCmp, len);
793 /*************************************************************************
796 * Unicode version of StrCmpNICA.
798 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
800 return StrCmpNIW(lpszSrc, lpszCmp, len);
803 /*************************************************************************
806 * Compare two Ascii strings.
809 * lpszSrc [I] Source string
810 * lpszCmp [I] String to compare to lpszSrc
813 * A number greater than, less than or equal to 0 depending on whether
814 * lpszSrc is greater than, less than or equal to lpszCmp.
816 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
818 return lstrcmpA(lpszSrc, lpszCmp);
821 /*************************************************************************
824 * Unicode version of StrCmpCA.
826 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
828 return lstrcmpW(lpszSrc, lpszCmp);
831 /*************************************************************************
834 * Compare two Ascii strings, ignoring case.
837 * lpszSrc [I] Source string
838 * lpszCmp [I] String to compare to lpszSrc
841 * A number greater than, less than or equal to 0 depending on whether
842 * lpszSrc is greater than, less than or equal to lpszCmp.
844 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
846 return lstrcmpiA(lpszSrc, lpszCmp);
849 /*************************************************************************
852 * Unicode version of StrCmpICA.
854 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
856 return lstrcmpiW(lpszSrc, lpszCmp);
859 /*************************************************************************
862 * Get an identification string for the OS and explorer.
865 * lpszDest [O] Destination for Id string
866 * dwDestLen [I] Length of lpszDest
869 * TRUE, If the string was created successfully
872 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
876 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
878 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
880 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
886 /*************************************************************************
889 * Unicode version of SHAboutInfoA.
891 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
893 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
894 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
895 ' ','E','x','p','l','o','r','e','r','\0' };
896 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
897 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
898 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
899 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
900 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
901 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
902 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
903 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
904 ' ','E','x','p','l','o','r','e','r','\\',
905 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
906 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
907 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
908 'V','e','r','s','i','o','n','\0' };
909 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
910 'O','w','n','e','r','\0' };
911 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
912 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
913 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
914 static const WCHAR szUpdate[] = { 'I','E','A','K',
915 'U','p','d','a','t','e','U','r','l','\0' };
916 static const WCHAR szHelp[] = { 'I','E','A','K',
917 'H','e','l','p','S','t','r','i','n','g','\0' };
922 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
929 /* Try the NT key first, followed by 95/98 key */
930 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
931 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
937 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
939 DWORD dwStrLen = strlenW(buff);
940 dwLen = 30 - dwStrLen;
941 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
942 szCustomized, &dwType, buff+dwStrLen, &dwLen);
944 StrCatBuffW(lpszDest, buff, dwDestLen);
946 /* ~Registered Owner */
949 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
951 StrCatBuffW(lpszDest, buff, dwDestLen);
953 /* ~Registered Organization */
955 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
957 StrCatBuffW(lpszDest, buff, dwDestLen);
959 /* FIXME: Not sure where this number comes from */
963 StrCatBuffW(lpszDest, buff, dwDestLen);
967 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
969 StrCatBuffW(lpszDest, buff, dwDestLen);
973 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
975 StrCatBuffW(lpszDest, buff, dwDestLen);
977 /* ~IE Help String */
979 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
981 StrCatBuffW(lpszDest, buff, dwDestLen);
987 /*************************************************************************
990 * Call IOleCommandTarget_QueryStatus() on an object.
993 * lpUnknown [I] Object supporting the IOleCommandTarget interface
994 * pguidCmdGroup [I] GUID for the command group
996 * prgCmds [O] Commands
997 * pCmdText [O] Command text
1001 * Failure: E_FAIL, if lpUnknown is NULL.
1002 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1003 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1005 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1006 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1008 HRESULT hRet = E_FAIL;
1010 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1014 IOleCommandTarget* lpOle;
1016 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1019 if (SUCCEEDED(hRet) && lpOle)
1021 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1023 IOleCommandTarget_Release(lpOle);
1029 /*************************************************************************
1032 * Call IOleCommandTarget_Exec() on an object.
1035 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1036 * pguidCmdGroup [I] GUID for the command group
1040 * Failure: E_FAIL, if lpUnknown is NULL.
1041 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1042 * Otherwise, an error code from IOleCommandTarget_Exec().
1044 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1045 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1048 HRESULT hRet = E_FAIL;
1050 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1051 nCmdexecopt, pvaIn, pvaOut);
1055 IOleCommandTarget* lpOle;
1057 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1059 if (SUCCEEDED(hRet) && lpOle)
1061 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1062 nCmdexecopt, pvaIn, pvaOut);
1063 IOleCommandTarget_Release(lpOle);
1069 /*************************************************************************
1072 * Retrieve, modify, and re-set a value from a window.
1075 * hWnd [I] Window to get value from
1076 * offset [I] Offset of value
1077 * mask [I] Mask for flags
1078 * flags [I] Bits to set in window value
1081 * The new value as it was set, or 0 if any parameter is invalid.
1084 * Only bits specified in mask are affected - set if present in flags and
1087 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT mask, UINT flags)
1089 LONG ret = GetWindowLongW(hwnd, offset);
1090 LONG new_flags = (flags & mask) | (ret & ~mask);
1092 TRACE("%p %d %x %x\n", hwnd, offset, mask, flags);
1094 if (new_flags != ret)
1095 ret = SetWindowLongW(hwnd, offset, new_flags);
1099 /*************************************************************************
1102 * Change a window's parent.
1105 * hWnd [I] Window to change parent of
1106 * hWndParent [I] New parent window
1109 * The old parent of hWnd.
1112 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1113 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1115 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1117 TRACE("%p, %p\n", hWnd, hWndParent);
1119 if(GetParent(hWnd) == hWndParent)
1123 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD | WS_POPUP, WS_CHILD);
1125 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD | WS_POPUP, WS_POPUP);
1127 return hWndParent ? SetParent(hWnd, hWndParent) : NULL;
1130 /*************************************************************************
1133 * Locate and advise a connection point in an IConnectionPointContainer object.
1136 * lpUnkSink [I] Sink for the connection point advise call
1137 * riid [I] REFIID of connection point to advise
1138 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1139 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1140 * lpCookie [O] Pointer to connection point cookie
1141 * lppCP [O] Destination for the IConnectionPoint found
1144 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1145 * that was advised. The caller is responsible for releasing it.
1146 * Failure: E_FAIL, if any arguments are invalid.
1147 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1148 * Or an HRESULT error code if any call fails.
1150 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL fConnect,
1151 IUnknown* lpUnknown, LPDWORD lpCookie,
1152 IConnectionPoint **lppCP)
1155 IConnectionPointContainer* lpContainer;
1156 IConnectionPoint *lpCP;
1158 if(!lpUnknown || (fConnect && !lpUnkSink))
1164 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1165 (void**)&lpContainer);
1166 if (SUCCEEDED(hRet))
1168 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1170 if (SUCCEEDED(hRet))
1173 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1175 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1180 if (lppCP && SUCCEEDED(hRet))
1181 *lppCP = lpCP; /* Caller keeps the interface */
1183 IConnectionPoint_Release(lpCP); /* Release it */
1186 IConnectionPointContainer_Release(lpContainer);
1191 /*************************************************************************
1194 * Release an interface and zero a supplied pointer.
1197 * lpUnknown [I] Object to release
1202 void WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1204 TRACE("(%p)\n", lpUnknown);
1206 if(!lpUnknown || !*lpUnknown) return;
1208 TRACE("doing Release\n");
1210 IUnknown_Release(*lpUnknown);
1214 /*************************************************************************
1217 * Skip '//' if present in a string.
1220 * lpszSrc [I] String to check for '//'
1223 * Success: The next character after the '//' or the string if not present
1224 * Failure: NULL, if lpszStr is NULL.
1226 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1228 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1233 /*************************************************************************
1236 * Check if two interfaces come from the same object.
1239 * lpInt1 [I] Interface to check against lpInt2.
1240 * lpInt2 [I] Interface to check against lpInt1.
1243 * TRUE, If the interfaces come from the same object.
1246 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1248 IUnknown *lpUnknown1, *lpUnknown2;
1251 TRACE("(%p %p)\n", lpInt1, lpInt2);
1253 if (!lpInt1 || !lpInt2)
1256 if (lpInt1 == lpInt2)
1259 if (IUnknown_QueryInterface(lpInt1, &IID_IUnknown, (void**)&lpUnknown1) != S_OK)
1262 if (IUnknown_QueryInterface(lpInt2, &IID_IUnknown, (void**)&lpUnknown2) != S_OK)
1264 IUnknown_Release(lpUnknown1);
1268 ret = lpUnknown1 == lpUnknown2;
1270 IUnknown_Release(lpUnknown1);
1271 IUnknown_Release(lpUnknown2);
1276 /*************************************************************************
1279 * Get the window handle of an object.
1282 * lpUnknown [I] Object to get the window handle of
1283 * lphWnd [O] Destination for window handle
1286 * Success: S_OK. lphWnd contains the objects window handle.
1287 * Failure: An HRESULT error code.
1290 * lpUnknown is expected to support one of the following interfaces:
1291 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1293 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1296 HRESULT hRet = E_FAIL;
1298 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1303 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1307 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1311 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1316 if (SUCCEEDED(hRet))
1318 /* Laziness here - Since GetWindow() is the first method for the above 3
1319 * interfaces, we use the same call for them all.
1321 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1322 IUnknown_Release(lpOle);
1324 TRACE("Returning HWND=%p\n", *lphWnd);
1330 /*************************************************************************
1333 * Call a SetOwner method of IShellService from specified object.
1336 * iface [I] Object that supports IShellService
1337 * pUnk [I] Argument for the SetOwner call
1340 * Corresponding return value from last call or E_FAIL for null input
1342 HRESULT WINAPI IUnknown_SetOwner(IUnknown *iface, IUnknown *pUnk)
1344 IShellService *service;
1347 TRACE("(%p, %p)\n", iface, pUnk);
1349 if (!iface) return E_FAIL;
1351 hr = IUnknown_QueryInterface(iface, &IID_IShellService, (void**)&service);
1354 hr = IShellService_SetOwner(service, pUnk);
1355 IShellService_Release(service);
1361 /*************************************************************************
1364 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1368 HRESULT WINAPI IUnknown_SetSite(
1369 IUnknown *obj, /* [in] OLE object */
1370 IUnknown *site) /* [in] Site interface */
1373 IObjectWithSite *iobjwithsite;
1374 IInternetSecurityManager *isecmgr;
1376 if (!obj) return E_FAIL;
1378 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1379 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1382 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1383 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1384 IObjectWithSite_Release(iobjwithsite);
1388 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1389 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1390 if (FAILED(hr)) return hr;
1392 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1393 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1394 IInternetSecurityManager_Release(isecmgr);
1399 /*************************************************************************
1402 * Call IPersist_GetClassID() on an object.
1405 * lpUnknown [I] Object supporting the IPersist interface
1406 * lpClassId [O] Destination for Class Id
1409 * Success: S_OK. lpClassId contains the Class Id requested.
1410 * Failure: E_FAIL, If lpUnknown is NULL,
1411 * E_NOINTERFACE If lpUnknown does not support IPersist,
1412 * Or an HRESULT error code.
1414 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1416 IPersist* lpPersist;
1417 HRESULT hRet = E_FAIL;
1419 TRACE("(%p,%s)\n", lpUnknown, debugstr_guid(lpClassId));
1423 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1424 if (SUCCEEDED(hRet))
1426 IPersist_GetClassID(lpPersist, lpClassId);
1427 IPersist_Release(lpPersist);
1433 /*************************************************************************
1436 * Retrieve a Service Interface from an object.
1439 * lpUnknown [I] Object to get an IServiceProvider interface from
1440 * sid [I] Service ID for IServiceProvider_QueryService() call
1441 * riid [I] Function requested for QueryService call
1442 * lppOut [O] Destination for the service interface pointer
1445 * Success: S_OK. lppOut contains an object providing the requested service
1446 * Failure: An HRESULT error code
1449 * lpUnknown is expected to support the IServiceProvider interface.
1451 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1454 IServiceProvider* pService = NULL;
1465 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1466 (LPVOID*)&pService);
1468 if (hRet == S_OK && pService)
1470 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1472 /* Get a Service interface from the object */
1473 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1475 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1477 IServiceProvider_Release(pService);
1482 /*************************************************************************
1485 * Calls IOleCommandTarget::Exec() for specified service object.
1488 * lpUnknown [I] Object to get an IServiceProvider interface from
1489 * service [I] Service ID for IServiceProvider_QueryService() call
1490 * group [I] Group ID for IOleCommandTarget::Exec() call
1491 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1492 * cmdOpt [I] Options flags for command
1493 * pIn [I] Input arguments for command
1494 * pOut [O] Output arguments for command
1497 * Success: S_OK. lppOut contains an object providing the requested service
1498 * Failure: An HRESULT error code
1501 * lpUnknown is expected to support the IServiceProvider interface.
1503 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *lpUnknown, REFIID service,
1504 const GUID *group, DWORD cmdId, DWORD cmdOpt, VARIANT *pIn, VARIANT *pOut)
1506 IOleCommandTarget *target;
1509 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown, debugstr_guid(service),
1510 debugstr_guid(group), cmdId, cmdOpt, pIn, pOut);
1512 hr = IUnknown_QueryService(lpUnknown, service, &IID_IOleCommandTarget, (void**)&target);
1515 hr = IOleCommandTarget_Exec(target, group, cmdId, cmdOpt, pIn, pOut);
1516 IOleCommandTarget_Release(target);
1519 TRACE("<-- hr=0x%08x\n", hr);
1524 /*************************************************************************
1527 * Calls IProfferService methods to proffer/revoke specified service.
1530 * lpUnknown [I] Object to get an IServiceProvider interface from
1531 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1532 * pService [I] Service to proffer. If NULL ::Revoke is called
1533 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1536 * Success: S_OK. IProffer method returns S_OK
1537 * Failure: An HRESULT error code
1540 * lpUnknown is expected to support the IServiceProvider interface.
1542 HRESULT WINAPI IUnknown_ProfferService(IUnknown *lpUnknown, REFGUID service, IServiceProvider *pService, DWORD *pCookie)
1544 IProfferService *proffer;
1547 TRACE("%p %s %p %p\n", lpUnknown, debugstr_guid(service), pService, pCookie);
1549 hr = IUnknown_QueryService(lpUnknown, &IID_IProfferService, &IID_IProfferService, (void**)&proffer);
1553 hr = IProfferService_ProfferService(proffer, service, pService, pCookie);
1556 hr = IProfferService_RevokeService(proffer, *pCookie);
1560 IProfferService_Release(proffer);
1566 /*************************************************************************
1569 * Call an object's UIActivateIO method.
1572 * unknown [I] Object to call the UIActivateIO method on
1573 * activate [I] Parameter for UIActivateIO call
1574 * msg [I] Parameter for UIActivateIO call
1577 * Success: Value of UI_ActivateIO call
1578 * Failure: An HRESULT error code
1581 * unknown is expected to support the IInputObject interface.
1583 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg)
1585 IInputObject* object = NULL;
1591 /* Get an IInputObject interface from the object */
1592 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
1596 ret = IInputObject_UIActivateIO(object, activate, msg);
1597 IInputObject_Release(object);
1603 /*************************************************************************
1606 * Loads a popup menu.
1609 * hInst [I] Instance handle
1610 * szName [I] Menu name
1616 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1620 TRACE("%p %s\n", hInst, debugstr_w(szName));
1622 if ((hMenu = LoadMenuW(hInst, szName)))
1624 if (GetSubMenu(hMenu, 0))
1625 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1633 typedef struct _enumWndData
1638 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1641 /* Callback for SHLWAPI_178 */
1642 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1644 enumWndData *data = (enumWndData *)lParam;
1646 TRACE("(%p,%p)\n", hWnd, data);
1647 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1651 /*************************************************************************
1654 * Send or post a message to every child of a window.
1657 * hWnd [I] Window whose children will get the messages
1658 * uiMsgId [I] Message Id
1659 * wParam [I] WPARAM of message
1660 * lParam [I] LPARAM of message
1661 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1667 * The appropriate ASCII or Unicode function is called for the window.
1669 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1673 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1677 data.uiMsgId = uiMsgId;
1678 data.wParam = wParam;
1679 data.lParam = lParam;
1682 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1684 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1686 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1690 /*************************************************************************
1693 * Remove all sub-menus from a menu.
1696 * hMenu [I] Menu to remove sub-menus from
1699 * Success: 0. All sub-menus under hMenu are removed
1700 * Failure: -1, if any parameter is invalid
1702 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1704 int iItemCount = GetMenuItemCount(hMenu) - 1;
1706 TRACE("%p\n", hMenu);
1708 while (iItemCount >= 0)
1710 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1712 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1718 /*************************************************************************
1721 * Enable or disable a menu item.
1724 * hMenu [I] Menu holding menu item
1725 * uID [I] ID of menu item to enable/disable
1726 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1729 * The return code from EnableMenuItem.
1731 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1733 TRACE("%p, %u, %d\n", hMenu, wItemID, bEnable);
1734 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1737 /*************************************************************************
1740 * Check or uncheck a menu item.
1743 * hMenu [I] Menu holding menu item
1744 * uID [I] ID of menu item to check/uncheck
1745 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1748 * The return code from CheckMenuItem.
1750 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1752 TRACE("%p, %u, %d\n", hMenu, uID, bCheck);
1753 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1756 /*************************************************************************
1759 * Register a window class if it isn't already.
1762 * lpWndClass [I] Window class to register
1765 * The result of the RegisterClassA call.
1767 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1770 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1772 return (DWORD)RegisterClassA(wndclass);
1775 /*************************************************************************
1778 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1779 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1781 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1782 POINTL pt = { 0, 0 };
1784 TRACE("%p %p 0x%08x %p %p\n", pDrop, pDataObj, grfKeyState, lpPt, pdwEffect);
1790 pdwEffect = &dwEffect;
1792 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1794 if (*pdwEffect != DROPEFFECT_NONE)
1795 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1797 IDropTarget_DragLeave(pDrop);
1801 /*************************************************************************
1804 * Call IPersistPropertyBag_Load() on an object.
1807 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1808 * lpPropBag [O] Destination for loaded IPropertyBag
1812 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1814 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1816 IPersistPropertyBag* lpPPBag;
1817 HRESULT hRet = E_FAIL;
1819 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1823 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1825 if (SUCCEEDED(hRet) && lpPPBag)
1827 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1828 IPersistPropertyBag_Release(lpPPBag);
1834 /*************************************************************************
1837 * Call IOleControlSite_TranslateAccelerator() on an object.
1840 * lpUnknown [I] Object supporting the IOleControlSite interface.
1841 * lpMsg [I] Key message to be processed.
1842 * dwModifiers [I] Flags containing the state of the modifier keys.
1846 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1848 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1850 IOleControlSite* lpCSite = NULL;
1851 HRESULT hRet = E_INVALIDARG;
1853 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1856 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1858 if (SUCCEEDED(hRet) && lpCSite)
1860 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1861 IOleControlSite_Release(lpCSite);
1868 /*************************************************************************
1871 * Call IOleControlSite_OnFocus() on an object.
1874 * lpUnknown [I] Object supporting the IOleControlSite interface.
1875 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1879 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1881 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
1883 IOleControlSite* lpCSite = NULL;
1884 HRESULT hRet = E_FAIL;
1886 TRACE("(%p, %d)\n", lpUnknown, fGotFocus);
1889 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1891 if (SUCCEEDED(hRet) && lpCSite)
1893 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1894 IOleControlSite_Release(lpCSite);
1900 /*************************************************************************
1903 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1904 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1906 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1907 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1908 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1909 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1910 HRESULT hRet = E_INVALIDARG;
1911 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1913 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1915 if (lpUnknown && lpArg4)
1917 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1918 (REFGUID)function_id, (void**)&lpUnkInner);
1920 if (SUCCEEDED(hRet) && lpUnkInner)
1922 /* FIXME: The type of service object requested is unknown, however
1923 * testing shows that its first method is called with 4 parameters.
1924 * Fake this by using IParseDisplayName_ParseDisplayName since the
1925 * signature and position in the vtable matches our unknown object type.
1927 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1928 lpArg1, lpArg2, lpArg3, lpArg4);
1929 IUnknown_Release(lpUnkInner);
1935 /*************************************************************************
1938 * Get a sub-menu from a menu item.
1941 * hMenu [I] Menu to get sub-menu from
1942 * uID [I] ID of menu item containing sub-menu
1945 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1947 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1951 TRACE("(%p,%u)\n", hMenu, uID);
1953 mi.cbSize = sizeof(mi);
1954 mi.fMask = MIIM_SUBMENU;
1956 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1962 /*************************************************************************
1965 * Get the color depth of the primary display.
1971 * The color depth of the primary display.
1973 DWORD WINAPI SHGetCurColorRes(void)
1981 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1986 /*************************************************************************
1989 * Wait for a message to arrive, with a timeout.
1992 * hand [I] Handle to query
1993 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1996 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1997 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1998 * message is available.
2000 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
2002 DWORD dwEndTicks = GetTickCount() + dwTimeout;
2005 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
2009 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
2011 if (dwTimeout != INFINITE)
2013 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
2014 return WAIT_TIMEOUT;
2021 /*************************************************************************
2024 * Determine if a shell folder can be expanded.
2027 * lpFolder [I] Parent folder containing the object to test.
2028 * pidl [I] Id of the object to test.
2031 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2032 * Failure: E_INVALIDARG, if any argument is invalid.
2035 * If the object to be tested does not expose the IQueryInfo() interface it
2036 * will not be identified as an expandable folder.
2038 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
2040 HRESULT hRet = E_INVALIDARG;
2043 if (lpFolder && pidl)
2045 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
2046 NULL, (void**)&lpInfo);
2048 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
2053 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2054 * currently used". Really? You wouldn't be holding out on me would you?
2056 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
2058 if (SUCCEEDED(hRet))
2060 /* 0x2 is an undocumented flag apparently indicating expandability */
2061 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
2064 IQueryInfo_Release(lpInfo);
2070 /*************************************************************************
2073 * Blank out a region of text by drawing the background only.
2076 * hDC [I] Device context to draw in
2077 * pRect [I] Area to draw in
2078 * cRef [I] Color to draw in
2083 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2085 COLORREF cOldColor = SetBkColor(hDC, cRef);
2086 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2087 SetBkColor(hDC, cOldColor);
2091 /*************************************************************************
2094 * Return the value associated with a key in a map.
2097 * lpKeys [I] A list of keys of length iLen
2098 * lpValues [I] A list of values associated with lpKeys, of length iLen
2099 * iLen [I] Length of both lpKeys and lpValues
2100 * iKey [I] The key value to look up in lpKeys
2103 * The value in lpValues associated with iKey, or -1 if iKey is not
2107 * - If two elements in the map share the same key, this function returns
2108 * the value closest to the start of the map
2109 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2111 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2113 if (lpKeys && lpValues)
2119 if (lpKeys[i] == iKey)
2120 return lpValues[i]; /* Found */
2124 return -1; /* Not found */
2128 /*************************************************************************
2131 * Copy an interface pointer
2134 * lppDest [O] Destination for copy
2135 * lpUnknown [I] Source for copy
2140 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2142 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2144 IUnknown_AtomicRelease(lppDest);
2148 IUnknown_AddRef(lpUnknown);
2149 *lppDest = lpUnknown;
2153 /*************************************************************************
2157 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2158 REFGUID riidCmdGrp, ULONG cCmds,
2159 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2161 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2162 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2164 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2165 return DRAGDROP_E_NOTREGISTERED;
2168 /*************************************************************************
2172 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2173 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2176 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2177 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2178 return DRAGDROP_E_NOTREGISTERED;
2181 /*************************************************************************
2185 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2187 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2188 return DRAGDROP_E_NOTREGISTERED;
2191 /*************************************************************************
2194 * Determine if a window is not a child of another window.
2197 * hParent [I] Suspected parent window
2198 * hChild [I] Suspected child window
2201 * TRUE: If hChild is a child window of hParent
2202 * FALSE: If hChild is not a child window of hParent, or they are equal
2204 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2206 TRACE("(%p,%p)\n", hParent, hChild);
2208 if (!hParent || !hChild)
2210 else if(hParent == hChild)
2212 return !IsChild(hParent, hChild);
2215 /*************************************************************************
2216 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2221 DWORD num_items; /* Number of elements inserted */
2222 void *mem; /* Ptr to array */
2223 DWORD blocks_alloced; /* Number of elements allocated */
2224 BYTE inc; /* Number of elements to grow by when we need to expand */
2225 BYTE block_size; /* Size in bytes of an element */
2226 BYTE flags; /* Flags */
2229 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2231 /*************************************************************************
2234 * Initialize an FDSA array.
2236 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2239 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2245 memset(mem, 0, block_size * init_blocks);
2247 info->num_items = 0;
2250 info->blocks_alloced = init_blocks;
2251 info->block_size = block_size;
2257 /*************************************************************************
2260 * Destroy an FDSA array
2262 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2264 TRACE("(%p)\n", info);
2266 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2268 HeapFree(GetProcessHeap(), 0, info->mem);
2275 /*************************************************************************
2278 * Insert element into an FDSA array
2280 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
2282 TRACE("(%p 0x%08x %p)\n", info, where, block);
2283 if(where > info->num_items)
2284 where = info->num_items;
2286 if(info->num_items >= info->blocks_alloced)
2288 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2289 if(info->flags & 0x1)
2290 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2293 void *old_mem = info->mem;
2294 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2295 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2297 info->blocks_alloced += info->inc;
2301 if(where < info->num_items)
2303 memmove((char*)info->mem + (where + 1) * info->block_size,
2304 (char*)info->mem + where * info->block_size,
2305 (info->num_items - where) * info->block_size);
2307 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2313 /*************************************************************************
2316 * Delete an element from an FDSA array.
2318 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2320 TRACE("(%p 0x%08x)\n", info, where);
2322 if(where >= info->num_items)
2325 if(where < info->num_items - 1)
2327 memmove((char*)info->mem + where * info->block_size,
2328 (char*)info->mem + (where + 1) * info->block_size,
2329 (info->num_items - where - 1) * info->block_size);
2331 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2332 0, info->block_size);
2337 /*************************************************************************
2340 * Call IUnknown_QueryInterface() on a table of objects.
2344 * Failure: E_POINTER or E_NOINTERFACE.
2346 HRESULT WINAPI QISearch(
2347 void *base, /* [in] Table of interfaces */
2348 const QITAB *table, /* [in] Array of REFIIDs and indexes into the table */
2349 REFIID riid, /* [in] REFIID to get interface for */
2350 void **ppv) /* [out] Destination for interface pointer */
2356 TRACE("(%p %p %s %p)\n", base, table, debugstr_guid(riid), ppv);
2359 while (xmove->piid) {
2360 TRACE("trying (offset %d) %s\n", xmove->dwOffset, debugstr_guid(xmove->piid));
2361 if (IsEqualIID(riid, xmove->piid)) {
2362 a_vtbl = (IUnknown*)(xmove->dwOffset + (LPBYTE)base);
2363 TRACE("matched, returning (%p)\n", a_vtbl);
2365 IUnknown_AddRef(a_vtbl);
2371 if (IsEqualIID(riid, &IID_IUnknown)) {
2372 a_vtbl = (IUnknown*)(table->dwOffset + (LPBYTE)base);
2373 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2375 IUnknown_AddRef(a_vtbl);
2379 ret = E_NOINTERFACE;
2383 TRACE("-- 0x%08x\n", ret);
2387 /*************************************************************************
2390 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2393 * hWnd [I] Parent Window to set the property
2394 * id [I] Index of child Window to set the Font
2400 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id)
2402 FIXME("(%p, %d) stub\n", hWnd, id);
2406 /*************************************************************************
2409 * Remove the "PropDlgFont" property from a window.
2412 * hWnd [I] Window to remove the property from
2415 * A handle to the removed property, or NULL if it did not exist.
2417 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2421 TRACE("(%p)\n", hWnd);
2423 hProp = GetPropA(hWnd, "PropDlgFont");
2427 DeleteObject(hProp);
2428 hProp = RemovePropA(hWnd, "PropDlgFont");
2433 /*************************************************************************
2436 * Load the in-process server of a given GUID.
2439 * refiid [I] GUID of the server to load.
2442 * Success: A handle to the loaded server dll.
2443 * Failure: A NULL handle.
2445 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2449 CHAR value[MAX_PATH], string[MAX_PATH];
2451 strcpy(string, "CLSID\\");
2452 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2453 strcat(string, "\\InProcServer32");
2456 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2457 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2458 RegCloseKey(newkey);
2459 return LoadLibraryExA(value, 0, 0);
2462 /*************************************************************************
2465 * Unicode version of SHLWAPI_183.
2467 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2471 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2473 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2475 return RegisterClassW(lpWndClass);
2478 /*************************************************************************
2481 * Unregister a list of classes.
2484 * hInst [I] Application instance that registered the classes
2485 * lppClasses [I] List of class names
2486 * iCount [I] Number of names in lppClasses
2491 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2495 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2499 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2500 UnregisterClassA(*lppClasses, hInst);
2506 /*************************************************************************
2509 * Unicode version of SHUnregisterClassesA.
2511 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2515 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2519 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2520 UnregisterClassW(*lppClasses, hInst);
2526 /*************************************************************************
2529 * Call The correct (Ascii/Unicode) default window procedure for a window.
2532 * hWnd [I] Window to call the default procedure for
2533 * uMessage [I] Message ID
2534 * wParam [I] WPARAM of message
2535 * lParam [I] LPARAM of message
2538 * The result of calling DefWindowProcA() or DefWindowProcW().
2540 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2542 if (IsWindowUnicode(hWnd))
2543 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2544 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2547 /*************************************************************************
2550 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2552 HRESULT hRet = E_INVALIDARG;
2553 LPOBJECTWITHSITE lpSite = NULL;
2555 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2557 if (lpUnknown && iid && lppSite)
2559 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2561 if (SUCCEEDED(hRet) && lpSite)
2563 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2564 IObjectWithSite_Release(lpSite);
2570 /*************************************************************************
2573 * Create a worker window using CreateWindowExA().
2576 * wndProc [I] Window procedure
2577 * hWndParent [I] Parent window
2578 * dwExStyle [I] Extra style flags
2579 * dwStyle [I] Style flags
2580 * hMenu [I] Window menu
2581 * wnd_extra [I] Window extra bytes value
2584 * Success: The window handle of the newly created window.
2587 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2588 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra)
2590 static const char szClass[] = "WorkerA";
2594 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2595 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
2597 /* Create Window class */
2599 wc.lpfnWndProc = DefWindowProcA;
2601 wc.cbWndExtra = sizeof(LONG_PTR);
2602 wc.hInstance = shlwapi_hInstance;
2604 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2605 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2606 wc.lpszMenuName = NULL;
2607 wc.lpszClassName = szClass;
2609 SHRegisterClassA(&wc);
2611 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2612 hWndParent, hMenu, shlwapi_hInstance, 0);
2615 SetWindowLongPtrW(hWnd, 0, wnd_extra);
2617 if (wndProc) SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2623 typedef struct tagPOLICYDATA
2625 DWORD policy; /* flags value passed to SHRestricted */
2626 LPCWSTR appstr; /* application str such as "Explorer" */
2627 LPCWSTR keystr; /* name of the actual registry key / policy */
2628 } POLICYDATA, *LPPOLICYDATA;
2630 #define SHELL_NO_POLICY 0xffffffff
2632 /* default shell policy registry key */
2633 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2634 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2635 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2636 '\\','P','o','l','i','c','i','e','s',0};
2638 /*************************************************************************
2641 * Retrieve a policy value from the registry.
2644 * lpSubKey [I] registry key name
2645 * lpSubName [I] subname of registry key
2646 * lpValue [I] value name of registry value
2649 * the value associated with the registry key or 0 if not found
2651 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2653 DWORD retval, datsize = sizeof(retval);
2657 lpSubKey = strRegistryPolicyW;
2659 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2660 if (retval != ERROR_SUCCESS)
2661 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2662 if (retval != ERROR_SUCCESS)
2665 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2670 /*************************************************************************
2673 * Helper function to retrieve the possibly cached value for a specific policy
2676 * policy [I] The policy to look for
2677 * initial [I] Main registry key to open, if NULL use default
2678 * polTable [I] Table of known policies, 0 terminated
2679 * polArr [I] Cache array of policy values
2682 * The retrieved policy value or 0 if not successful
2685 * This function is used by the native SHRestricted function to search for the
2686 * policy and cache it once retrieved. The current Wine implementation uses a
2687 * different POLICYDATA structure and implements a similar algorithm adapted to
2690 DWORD WINAPI SHRestrictionLookup(
2693 LPPOLICYDATA polTable,
2696 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2698 if (!polTable || !polArr)
2701 for (;polTable->policy; polTable++, polArr++)
2703 if (policy == polTable->policy)
2705 /* we have a known policy */
2707 /* check if this policy has been cached */
2708 if (*polArr == SHELL_NO_POLICY)
2709 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2713 /* we don't know this policy, return 0 */
2714 TRACE("unknown policy: (%08x)\n", policy);
2718 /*************************************************************************
2721 * Get an interface from an object.
2724 * Success: S_OK. ppv contains the requested interface.
2725 * Failure: An HRESULT error code.
2728 * This QueryInterface asks the inner object for an interface. In case
2729 * of aggregation this request would be forwarded by the inner to the
2730 * outer object. This function asks the inner object directly for the
2731 * interface circumventing the forwarding to the outer object.
2733 HRESULT WINAPI SHWeakQueryInterface(
2734 IUnknown * pUnk, /* [in] Outer object */
2735 IUnknown * pInner, /* [in] Inner object */
2736 IID * riid, /* [in] Interface GUID to query for */
2737 LPVOID* ppv) /* [out] Destination for queried interface */
2739 HRESULT hret = E_NOINTERFACE;
2740 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2743 if(pUnk && pInner) {
2744 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2745 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2747 TRACE("-- 0x%08x\n", hret);
2751 /*************************************************************************
2754 * Move a reference from one interface to another.
2757 * lpDest [O] Destination to receive the reference
2758 * lppUnknown [O] Source to give up the reference to lpDest
2763 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2765 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2770 IUnknown_AddRef(lpDest);
2771 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2775 /*************************************************************************
2778 * Convert an ASCII string of a CLSID into a CLSID.
2781 * idstr [I] String representing a CLSID in registry format
2782 * id [O] Destination for the converted CLSID
2785 * Success: TRUE. id contains the converted CLSID.
2788 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2791 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2792 return SUCCEEDED(CLSIDFromString(wClsid, id));
2795 /*************************************************************************
2798 * Unicode version of GUIDFromStringA.
2800 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2802 return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id));
2805 /*************************************************************************
2808 * Determine if the browser is integrated into the shell, and set a registry
2815 * 1, If the browser is not integrated.
2816 * 2, If the browser is integrated.
2819 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2820 * either set to TRUE, or removed depending on whether the browser is deemed
2823 DWORD WINAPI WhichPlatform(void)
2825 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2826 static DWORD dwState = 0;
2828 DWORD dwRet, dwData, dwSize;
2834 /* If shell32 exports DllGetVersion(), the browser is integrated */
2836 hshell32 = LoadLibraryA("shell32.dll");
2839 FARPROC pDllGetVersion;
2840 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2841 dwState = pDllGetVersion ? 2 : 1;
2842 FreeLibrary(hshell32);
2845 /* Set or delete the key accordingly */
2846 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2847 "Software\\Microsoft\\Internet Explorer", 0,
2848 KEY_ALL_ACCESS, &hKey);
2851 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2852 (LPBYTE)&dwData, &dwSize);
2854 if (!dwRet && dwState == 1)
2856 /* Value exists but browser is not integrated */
2857 RegDeleteValueA(hKey, szIntegratedBrowser);
2859 else if (dwRet && dwState == 2)
2861 /* Browser is integrated but value does not exist */
2863 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2864 (LPBYTE)&dwData, sizeof(dwData));
2871 /*************************************************************************
2874 * Unicode version of SHCreateWorkerWindowA.
2876 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2877 DWORD dwStyle, HMENU hMenu, LONG msg_result)
2879 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
2883 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
2884 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
2886 /* If our OS is natively ANSI, use the ANSI version */
2887 if (GetVersion() & 0x80000000) /* not NT */
2889 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
2890 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
2893 /* Create Window class */
2895 wc.lpfnWndProc = DefWindowProcW;
2898 wc.hInstance = shlwapi_hInstance;
2900 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2901 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2902 wc.lpszMenuName = NULL;
2903 wc.lpszClassName = szClass;
2905 SHRegisterClassW(&wc);
2907 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2908 hWndParent, hMenu, shlwapi_hInstance, 0);
2911 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, msg_result);
2913 if (wndProc) SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2919 /*************************************************************************
2922 * Get and show a context menu from a shell folder.
2925 * hWnd [I] Window displaying the shell folder
2926 * lpFolder [I] IShellFolder interface
2927 * lpApidl [I] Id for the particular folder desired
2931 * Failure: An HRESULT error code indicating the error.
2933 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2935 TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl);
2936 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2939 /*************************************************************************
2942 * _SHPackDispParamsV
2944 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist)
2948 TRACE("(%p %p %u ...)\n", params, args, cnt);
2950 params->rgvarg = args;
2951 params->rgdispidNamedArgs = NULL;
2952 params->cArgs = cnt;
2953 params->cNamedArgs = 0;
2957 while(iter-- > args) {
2958 V_VT(iter) = va_arg(valist, enum VARENUM);
2960 TRACE("vt=%d\n", V_VT(iter));
2962 if(V_VT(iter) & VT_BYREF) {
2963 V_BYREF(iter) = va_arg(valist, LPVOID);
2965 switch(V_VT(iter)) {
2967 V_I4(iter) = va_arg(valist, LONG);
2970 V_BSTR(iter) = va_arg(valist, BSTR);
2973 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
2976 V_BOOL(iter) = va_arg(valist, int);
2979 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
2983 V_I4(iter) = va_arg(valist, LONG);
2991 /*************************************************************************
2996 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...)
2998 __ms_va_list valist;
3001 __ms_va_start(valist, cnt);
3002 hres = SHPackDispParamsV(params, args, cnt, valist);
3003 __ms_va_end(valist);
3007 /*************************************************************************
3008 * SHLWAPI_InvokeByIID
3010 * This helper function calls IDispatch::Invoke for each sink
3011 * which implements given iid or IDispatch.
3014 static HRESULT SHLWAPI_InvokeByIID(
3015 IConnectionPoint* iCP,
3018 DISPPARAMS* dispParams)
3020 IEnumConnections *enumerator;
3022 static DISPPARAMS empty = {NULL, NULL, 0, 0};
3023 DISPPARAMS* params = dispParams;
3025 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
3029 /* Invoke is never happening with an NULL dispParams */
3033 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
3035 IDispatch *dispIface;
3036 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
3037 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
3039 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
3040 IDispatch_Release(dispIface);
3042 IUnknown_Release(rgcd.pUnk);
3045 IEnumConnections_Release(enumerator);
3050 /*************************************************************************
3051 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3053 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP,
3054 DISPID dispId, DISPPARAMS* dispParams,
3055 DWORD unknown1, DWORD unknown2 )
3060 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
3062 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3063 if (SUCCEEDED(result))
3064 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3066 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3072 /*************************************************************************
3075 * IConnectionPoint_SimpleInvoke
3077 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
3078 IConnectionPoint* iCP,
3080 DISPPARAMS* dispParams)
3085 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
3087 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3088 if (SUCCEEDED(result))
3089 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3091 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3096 /*************************************************************************
3099 * Notify an IConnectionPoint object of changes.
3102 * lpCP [I] Object to notify
3107 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3108 * IConnectionPoint interface.
3110 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
3112 IEnumConnections *lpEnum;
3113 HRESULT hRet = E_NOINTERFACE;
3115 TRACE("(%p,0x%8X)\n", lpCP, dispID);
3117 /* Get an enumerator for the connections */
3119 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
3121 if (SUCCEEDED(hRet))
3123 IPropertyNotifySink *lpSink;
3124 CONNECTDATA connData;
3127 /* Call OnChanged() for every notify sink in the connection point */
3128 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
3130 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
3133 IPropertyNotifySink_OnChanged(lpSink, dispID);
3134 IPropertyNotifySink_Release(lpSink);
3136 IUnknown_Release(connData.pUnk);
3139 IEnumConnections_Release(lpEnum);
3144 /*************************************************************************
3147 * IUnknown_CPContainerInvokeParam
3149 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
3150 IUnknown *container,
3157 IConnectionPoint *iCP;
3158 IConnectionPointContainer *iCPC;
3159 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3160 __ms_va_list valist;
3163 return E_NOINTERFACE;
3165 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
3169 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
3170 IConnectionPointContainer_Release(iCPC);
3174 __ms_va_start(valist, cParams);
3175 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
3176 __ms_va_end(valist);
3178 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3179 IConnectionPoint_Release(iCP);
3184 /*************************************************************************
3187 * Notify an IConnectionPointContainer object of changes.
3190 * lpUnknown [I] Object to notify
3195 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3196 * IConnectionPointContainer interface.
3198 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3200 IConnectionPointContainer* lpCPC = NULL;
3201 HRESULT hRet = E_NOINTERFACE;
3203 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3206 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3208 if (SUCCEEDED(hRet))
3210 IConnectionPoint* lpCP;
3212 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3213 IConnectionPointContainer_Release(lpCPC);
3215 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3216 IConnectionPoint_Release(lpCP);
3221 /*************************************************************************
3226 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3228 return PlaySoundW(pszSound, hmod, fdwSound);
3231 /*************************************************************************
3234 * Retrieve a key value from an INI file. See GetPrivateProfileString for
3238 * appName [I] The section in the INI file that contains the key
3239 * keyName [I] The key to be retrieved
3240 * out [O] The buffer into which the key's value will be copied
3241 * outLen [I] The length of the `out' buffer
3242 * filename [I] The location of the INI file
3245 * Length of string copied into `out'.
3247 DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
3248 DWORD outLen, LPCWSTR filename)
3253 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName), debugstr_w(keyName),
3254 out, outLen, debugstr_w(filename));
3259 buf = HeapAlloc(GetProcessHeap(), 0, outLen * sizeof(WCHAR));
3265 ret = GetPrivateProfileStringW(appName, keyName, NULL, buf, outLen, filename);
3271 HeapFree(GetProcessHeap(), 0, buf);
3273 return strlenW(out);
3276 /*************************************************************************
3279 * Set a key value in an INI file. See WritePrivateProfileString for
3283 * appName [I] The section in the INI file that contains the key
3284 * keyName [I] The key to be set
3285 * str [O] The value of the key
3286 * filename [I] The location of the INI file
3292 BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str,
3295 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
3296 debugstr_w(filename));
3298 return WritePrivateProfileStringW(appName, keyName, str, filename);
3301 /*************************************************************************
3304 * See SHGetFileInfoW.
3306 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3307 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3309 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3312 /*************************************************************************
3315 * See DragQueryFileW.
3317 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3319 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3322 /*************************************************************************
3325 * See SHBrowseForFolderW.
3327 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3329 return SHBrowseForFolderW(lpBi);
3332 /*************************************************************************
3335 * See SHGetPathFromIDListW.
3337 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3339 return SHGetPathFromIDListW(pidl, pszPath);
3342 /*************************************************************************
3345 * See ShellExecuteExW.
3347 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3349 return ShellExecuteExW(lpExecInfo);
3352 /*************************************************************************
3355 * See SHFileOperationW.
3357 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3359 return SHFileOperationW(lpFileOp);
3362 /*************************************************************************
3366 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
3368 return InterlockedCompareExchangePointer( dest, xchg, compare );
3371 /*************************************************************************
3374 * See GetFileVersionInfoSizeW.
3376 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
3378 return GetFileVersionInfoSizeW( filename, handle );
3381 /*************************************************************************
3384 * See GetFileVersionInfoW.
3386 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
3387 DWORD datasize, LPVOID data )
3389 return GetFileVersionInfoW( filename, handle, datasize, data );
3392 /*************************************************************************
3395 * See VerQueryValueW.
3397 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
3398 LPVOID *lplpBuffer, UINT *puLen )
3400 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3403 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3404 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3405 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3407 /*************************************************************************
3410 * Change the modality of a shell object.
3413 * lpUnknown [I] Object to make modeless
3414 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3417 * Success: S_OK. The modality lpUnknown is changed.
3418 * Failure: An HRESULT error code indicating the error.
3421 * lpUnknown must support the IOleInPlaceFrame interface, the
3422 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3423 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3424 * or this call will fail.
3426 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3431 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3436 if (IsIface(IOleInPlaceActiveObject))
3437 EnableModeless(IOleInPlaceActiveObject);
3438 else if (IsIface(IOleInPlaceFrame))
3439 EnableModeless(IOleInPlaceFrame);
3440 else if (IsIface(IShellBrowser))
3441 EnableModeless(IShellBrowser);
3442 else if (IsIface(IInternetSecurityMgrSite))
3443 EnableModeless(IInternetSecurityMgrSite);
3444 else if (IsIface(IDocHostUIHandler))
3445 EnableModeless(IDocHostUIHandler);
3449 IUnknown_Release(lpObj);
3453 /*************************************************************************
3456 * See SHGetNewLinkInfoW.
3458 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3459 BOOL *pfMustCopy, UINT uFlags)
3461 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3464 /*************************************************************************
3467 * See SHDefExtractIconW.
3469 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3470 HICON* phiconSmall, UINT nIconSize)
3472 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3475 /*************************************************************************
3478 * Get and show a context menu from a shell folder.
3481 * hWnd [I] Window displaying the shell folder
3482 * lpFolder [I] IShellFolder interface
3483 * lpApidl [I] Id for the particular folder desired
3484 * bInvokeDefault [I] Whether to invoke the default menu item
3487 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3489 * Failure: An HRESULT error code indicating the error.
3491 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3493 IContextMenu *iContext;
3496 TRACE("(%p, %p, %p, %d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3501 /* Get the context menu from the shell folder */
3502 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3503 &IID_IContextMenu, 0, (void**)&iContext);
3504 if (SUCCEEDED(hRet))
3507 if ((hMenu = CreatePopupMenu()))
3510 DWORD dwDefaultId = 0;
3512 /* Add the context menu entries to the popup */
3513 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3514 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3516 if (SUCCEEDED(hQuery))
3518 if (bInvokeDefault &&
3519 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != (UINT)-1)
3521 CMINVOKECOMMANDINFO cmIci;
3522 /* Invoke the default item */
3523 memset(&cmIci,0,sizeof(cmIci));
3524 cmIci.cbSize = sizeof(cmIci);
3525 cmIci.fMask = CMIC_MASK_ASYNCOK;
3527 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3528 cmIci.nShow = SW_SCROLLCHILDREN;
3530 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3535 IContextMenu_Release(iContext);
3540 /*************************************************************************
3545 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3548 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3551 /*************************************************************************
3554 * Load a library from the directory of a particular process.
3557 * new_mod [I] Library name
3558 * inst_hwnd [I] Module whose directory is to be used
3559 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3562 * Success: A handle to the loaded module
3563 * Failure: A NULL handle.
3565 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3567 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3569 * FIXME: Native shows calls to:
3570 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3572 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3573 * RegQueryValueExA for "LPKInstalled"
3575 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3576 * RegQueryValueExA for "ResourceLocale"
3578 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3579 * RegQueryValueExA for "Locale"
3581 * and then tests the Locale ("en" for me).
3583 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3585 CHAR mod_path[2*MAX_PATH];
3589 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3590 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3591 if (!len || len >= sizeof(mod_path)) return NULL;
3593 ptr = strrchr(mod_path, '\\');
3595 strcpy(ptr+1, new_mod);
3596 TRACE("loading %s\n", debugstr_a(mod_path));
3597 return LoadLibraryA(mod_path);
3602 /*************************************************************************
3605 * Unicode version of MLLoadLibraryA.
3607 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3609 WCHAR mod_path[2*MAX_PATH];
3613 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3614 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3615 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3617 ptr = strrchrW(mod_path, '\\');
3619 strcpyW(ptr+1, new_mod);
3620 TRACE("loading %s\n", debugstr_w(mod_path));
3621 return LoadLibraryW(mod_path);
3626 /*************************************************************************
3627 * ColorAdjustLuma [SHLWAPI.@]
3629 * Adjust the luminosity of a color
3632 * cRGB [I] RGB value to convert
3633 * dwLuma [I] Luma adjustment
3634 * bUnknown [I] Unknown
3637 * The adjusted RGB color.
3639 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3641 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3647 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3649 FIXME("Ignoring luma adjustment\n");
3651 /* FIXME: The adjustment is not linear */
3653 cRGB = ColorHLSToRGB(wH, wL, wS);
3658 /*************************************************************************
3661 * See GetSaveFileNameW.
3663 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3665 return GetSaveFileNameW(ofn);
3668 /*************************************************************************
3671 * See WNetRestoreConnectionW.
3673 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3675 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3678 /*************************************************************************
3681 * See WNetGetLastErrorW.
3683 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3684 LPWSTR lpNameBuf, DWORD nNameBufSize)
3686 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3689 /*************************************************************************
3692 * See PageSetupDlgW.
3694 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3696 return PageSetupDlgW(pagedlg);
3699 /*************************************************************************
3704 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3706 return PrintDlgW(printdlg);
3709 /*************************************************************************
3712 * See GetOpenFileNameW.
3714 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3716 return GetOpenFileNameW(ofn);
3719 /*************************************************************************
3722 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3724 /* Windows attempts to get an IPersist interface and, if that fails, an
3725 * IPersistFolder interface on the folder passed-in here. If one of those
3726 * interfaces is available, it then calls GetClassID on the folder... and
3727 * then calls IShellFolder_EnumObjects no matter what, even crashing if
3728 * lpFolder isn't actually an IShellFolder object. The purpose of getting
3729 * the ClassID is unknown, so we don't do it here.
3731 * For discussion and detailed tests, see:
3732 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated"
3733 * wine-devel mailing list, 3 Jun 2010
3736 return IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3739 /* INTERNAL: Map from HLS color space to RGB */
3740 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3742 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3746 else if (wHue > 120)
3751 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3754 /* Convert to RGB and scale into RGB range (0..255) */
3755 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3757 /*************************************************************************
3758 * ColorHLSToRGB [SHLWAPI.@]
3760 * Convert from hls color space into an rgb COLORREF.
3763 * wHue [I] Hue amount
3764 * wLuminosity [I] Luminosity amount
3765 * wSaturation [I] Saturation amount
3768 * A COLORREF representing the converted color.
3771 * Input hls values are constrained to the range (0..240).
3773 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3779 WORD wGreen, wBlue, wMid1, wMid2;
3781 if (wLuminosity > 120)
3782 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3784 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3786 wMid1 = wLuminosity * 2 - wMid2;
3788 wRed = GET_RGB(wHue + 80);
3789 wGreen = GET_RGB(wHue);
3790 wBlue = GET_RGB(wHue - 80);
3792 return RGB(wRed, wGreen, wBlue);
3795 wRed = wLuminosity * 255 / 240;
3796 return RGB(wRed, wRed, wRed);
3799 /*************************************************************************
3802 * Get the current docking status of the system.
3805 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3808 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3811 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3813 HW_PROFILE_INFOA hwInfo;
3815 TRACE("(0x%08x)\n", dwFlags);
3817 GetCurrentHwProfileA(&hwInfo);
3818 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3820 case DOCKINFO_DOCKED:
3821 case DOCKINFO_UNDOCKED:
3822 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3828 /*************************************************************************
3832 DWORD WINAPI SHWinHelpOnDemandW(HWND hwnd, LPCWSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2)
3835 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_w(helpfile), flags1, ptr1, flags2);
3839 /*************************************************************************
3843 DWORD WINAPI SHWinHelpOnDemandA(HWND hwnd, LPCSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2)
3846 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_a(helpfile), flags1, ptr1, flags2);
3850 /*************************************************************************
3853 * Function seems to do FreeLibrary plus other things.
3855 * FIXME native shows the following calls:
3856 * RtlEnterCriticalSection
3858 * GetProcAddress(Comctl32??, 150L)
3860 * RtlLeaveCriticalSection
3861 * followed by the FreeLibrary.
3862 * The above code may be related to .377 above.
3864 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3866 FIXME("(%p) semi-stub\n", hModule);
3867 return FreeLibrary(hModule);
3870 /*************************************************************************
3873 BOOL WINAPI SHFlushSFCacheWrap(void) {
3878 /*************************************************************************
3880 * FIXME I have no idea what this function does or what its arguments are.
3882 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3884 FIXME("(%p) stub\n", hInst);
3889 /*************************************************************************
3892 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3894 FIXME("(%p,%p) stub\n", hInst, hHeap);
3895 return E_FAIL; /* This is what is used if shlwapi not loaded */
3898 /*************************************************************************
3901 DWORD WINAPI MLClearMLHInstance(DWORD x)
3903 FIXME("(0x%08x)stub\n", x);
3907 /*************************************************************************
3910 * See SHSendMessageBroadcastW
3913 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam)
3915 return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam,
3916 SMTO_ABORTIFHUNG, 2000, NULL);
3919 /*************************************************************************
3922 * A wrapper for sending Broadcast Messages to all top level Windows
3925 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam)
3927 return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam,
3928 SMTO_ABORTIFHUNG, 2000, NULL);
3931 /*************************************************************************
3934 * Convert a Unicode string CLSID into a CLSID.
3937 * idstr [I] string containing a CLSID in text form
3938 * id [O] CLSID extracted from the string
3941 * S_OK on success or E_INVALIDARG on failure
3943 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3945 return CLSIDFromString((LPCOLESTR)idstr, id);
3948 /*************************************************************************
3951 * Determine if the OS supports a given feature.
3954 * dwFeature [I] Feature requested (undocumented)
3957 * TRUE If the feature is available.
3958 * FALSE If the feature is not available.
3960 BOOL WINAPI IsOS(DWORD feature)
3962 OSVERSIONINFOA osvi;
3963 DWORD platform, majorv, minorv;
3965 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3966 if(!GetVersionExA(&osvi)) {
3967 ERR("GetVersionEx failed\n");
3971 majorv = osvi.dwMajorVersion;
3972 minorv = osvi.dwMinorVersion;
3973 platform = osvi.dwPlatformId;
3975 #define ISOS_RETURN(x) \
3976 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3980 case OS_WIN32SORGREATER:
3981 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3982 || platform == VER_PLATFORM_WIN32_WINDOWS)
3984 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3985 case OS_WIN95ORGREATER:
3986 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3987 case OS_NT4ORGREATER:
3988 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3989 case OS_WIN2000ORGREATER_ALT:
3990 case OS_WIN2000ORGREATER:
3991 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3992 case OS_WIN98ORGREATER:
3993 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3995 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3997 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3998 case OS_WIN2000SERVER:
3999 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4000 case OS_WIN2000ADVSERVER:
4001 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4002 case OS_WIN2000DATACENTER:
4003 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4004 case OS_WIN2000TERMINAL:
4005 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4007 FIXME("(OS_EMBEDDED) What should we return here?\n");
4009 case OS_TERMINALCLIENT:
4010 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
4012 case OS_TERMINALREMOTEADMIN:
4013 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
4016 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
4017 case OS_MEORGREATER:
4018 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
4019 case OS_XPORGREATER:
4020 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
4022 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
4023 case OS_PROFESSIONAL:
4024 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4026 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4028 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
4030 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4031 case OS_TERMINALSERVER:
4032 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4033 case OS_PERSONALTERMINALSERVER:
4034 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
4035 case OS_FASTUSERSWITCHING:
4036 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
4038 case OS_WELCOMELOGONUI:
4039 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
4041 case OS_DOMAINMEMBER:
4042 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
4045 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4049 IsWow64Process(GetCurrentProcess(), &is_wow64);
4053 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4054 case OS_SMALLBUSINESSSERVER:
4055 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4057 FIXME("(OS_TABLEPC) What should we return here?\n");
4059 case OS_SERVERADMINUI:
4060 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
4062 case OS_MEDIACENTER:
4063 FIXME("(OS_MEDIACENTER) What should we return here?\n");
4066 FIXME("(OS_APPLIANCE) What should we return here?\n");
4068 case 0x25: /*OS_VISTAORGREATER*/
4069 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
4074 WARN("(0x%x) unknown parameter\n",feature);
4079 /*************************************************************************
4082 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
4084 DWORD type, sz = size;
4086 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
4089 return SHLoadIndirectString(buf, buf, size, NULL);
4092 /*************************************************************************
4095 * Call IInputObject_TranslateAcceleratorIO() on an object.
4098 * lpUnknown [I] Object supporting the IInputObject interface.
4099 * lpMsg [I] Key message to be processed.
4103 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4105 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
4107 IInputObject* lpInput = NULL;
4108 HRESULT hRet = E_INVALIDARG;
4110 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
4113 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4115 if (SUCCEEDED(hRet) && lpInput)
4117 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
4118 IInputObject_Release(lpInput);
4124 /*************************************************************************
4127 * Call IInputObject_HasFocusIO() on an object.
4130 * lpUnknown [I] Object supporting the IInputObject interface.
4133 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4134 * or S_FALSE otherwise.
4135 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4137 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
4139 IInputObject* lpInput = NULL;
4140 HRESULT hRet = E_INVALIDARG;
4142 TRACE("(%p)\n", lpUnknown);
4145 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4147 if (SUCCEEDED(hRet) && lpInput)
4149 hRet = IInputObject_HasFocusIO(lpInput);
4150 IInputObject_Release(lpInput);
4156 /*************************************************************************
4157 * ColorRGBToHLS [SHLWAPI.@]
4159 * Convert an rgb COLORREF into the hls color space.
4162 * cRGB [I] Source rgb value
4163 * pwHue [O] Destination for converted hue
4164 * pwLuminance [O] Destination for converted luminance
4165 * pwSaturation [O] Destination for converted saturation
4168 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4172 * Output HLS values are constrained to the range (0..240).
4173 * For Achromatic conversions, Hue is set to 160.
4175 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
4176 LPWORD pwLuminance, LPWORD pwSaturation)
4178 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4180 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4182 wR = GetRValue(cRGB);
4183 wG = GetGValue(cRGB);
4184 wB = GetBValue(cRGB);
4186 wMax = max(wR, max(wG, wB));
4187 wMin = min(wR, min(wG, wB));
4190 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4194 /* Achromatic case */
4196 /* Hue is now unrepresentable, but this is what native returns... */
4201 /* Chromatic case */
4202 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4205 if (wLuminosity <= 120)
4206 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4208 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4211 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4212 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4213 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4216 wHue = wBNorm - wGNorm;
4217 else if (wG == wMax)
4218 wHue = 80 + wRNorm - wBNorm;
4220 wHue = 160 + wGNorm - wRNorm;
4223 else if (wHue > 240)
4229 *pwLuminance = wLuminosity;
4231 *pwSaturation = wSaturation;
4234 /*************************************************************************
4235 * SHCreateShellPalette [SHLWAPI.@]
4237 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4240 return CreateHalftonePalette(hdc);
4243 /*************************************************************************
4244 * SHGetInverseCMAP (SHLWAPI.@)
4246 * Get an inverse color map table.
4249 * lpCmap [O] Destination for color map
4250 * dwSize [I] Size of memory pointed to by lpCmap
4254 * Failure: E_POINTER, If lpCmap is invalid.
4255 * E_INVALIDARG, If dwFlags is invalid
4256 * E_OUTOFMEMORY, If there is no memory available
4259 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4260 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4262 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4263 * this DLL's internal CMap.
4265 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4268 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4269 *dest = (DWORD)0xabba1249;
4272 FIXME("(%p, %#x) stub\n", dest, dwSize);
4276 /*************************************************************************
4277 * SHIsLowMemoryMachine [SHLWAPI.@]
4279 * Determine if the current computer has low memory.
4285 * TRUE if the users machine has 16 Megabytes of memory or less,
4288 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4290 FIXME("(0x%08x) stub\n", x);
4294 /*************************************************************************
4295 * GetMenuPosFromID [SHLWAPI.@]
4297 * Return the position of a menu item from its Id.
4300 * hMenu [I] Menu containing the item
4301 * wID [I] Id of the menu item
4304 * Success: The index of the menu item in hMenu.
4305 * Failure: -1, If the item is not found.
4307 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4310 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4312 TRACE("%p %u\n", hMenu, wID);
4314 while (nIter < nCount)
4316 mi.cbSize = sizeof(mi);
4318 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4320 TRACE("ret %d\n", nIter);
4329 /*************************************************************************
4332 * Same as SHLWAPI.GetMenuPosFromID
4334 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4336 TRACE("%p %u\n", hMenu, uID);
4337 return GetMenuPosFromID(hMenu, uID);
4341 /*************************************************************************
4344 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4355 /*************************************************************************
4358 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4360 FIXME("(0x%08x) stub\n", dwUnknown);
4365 /*************************************************************************
4368 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4369 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4371 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4374 /*************************************************************************
4375 * SHSkipJunction [SHLWAPI.@]
4377 * Determine if a bind context can be bound to an object
4380 * pbc [I] Bind context to check
4381 * pclsid [I] CLSID of object to be bound to
4384 * TRUE: If it is safe to bind
4385 * FALSE: If pbc is invalid or binding would not be safe
4388 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4390 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4391 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4398 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4402 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4403 IsEqualGUID(pclsid, &clsid))
4406 IUnknown_Release(lpUnk);
4412 /***********************************************************************
4413 * SHGetShellKey (SHLWAPI.491)
4415 HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create)
4417 enum _shellkey_flags {
4418 SHKEY_Root_HKCU = 0x1,
4419 SHKEY_Root_HKLM = 0x2,
4420 SHKEY_Key_Explorer = 0x00,
4421 SHKEY_Key_Shell = 0x10,
4422 SHKEY_Key_ShellNoRoam = 0x20,
4423 SHKEY_Key_Classes = 0x30,
4424 SHKEY_Subkey_Default = 0x0000,
4425 SHKEY_Subkey_ResourceName = 0x1000,
4426 SHKEY_Subkey_Handlers = 0x2000,
4427 SHKEY_Subkey_Associations = 0x3000,
4428 SHKEY_Subkey_Volatile = 0x4000,
4429 SHKEY_Subkey_MUICache = 0x5000,
4430 SHKEY_Subkey_FileExts = 0x6000
4433 static const WCHAR explorerW[] = {'S','o','f','t','w','a','r','e','\\',
4434 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4435 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4436 'E','x','p','l','o','r','e','r','\\'};
4437 static const WCHAR shellW[] = {'S','o','f','t','w','a','r','e','\\',
4438 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4439 'S','h','e','l','l','\\'};
4440 static const WCHAR shell_no_roamW[] = {'S','o','f','t','w','a','r','e','\\',
4441 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4442 'S','h','e','l','l','N','o','R','o','a','m','\\'};
4443 static const WCHAR classesW[] = {'S','o','f','t','w','a','r','e','\\',
4444 'C','l','a','s','s','e','s','\\'};
4446 static const WCHAR localized_resource_nameW[] = {'L','o','c','a','l','i','z','e','d',
4447 'R','e','s','o','u','r','c','e','N','a','m','e','\\'};
4448 static const WCHAR handlersW[] = {'H','a','n','d','l','e','r','s','\\'};
4449 static const WCHAR associationsW[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'};
4450 static const WCHAR volatileW[] = {'V','o','l','a','t','i','l','e','\\'};
4451 static const WCHAR mui_cacheW[] = {'M','U','I','C','a','c','h','e','\\'};
4452 static const WCHAR file_extsW[] = {'F','i','l','e','E','x','t','s','\\'};
4455 const WCHAR *key, *subkey;
4456 int size_key, size_subkey, size_user;
4459 TRACE("(0x%08x, %s, %d)\n", flags, debugstr_w(sub_key), create);
4461 /* For compatibility with Vista+ */
4462 if(flags == 0x1ffff)
4465 switch(flags&0xff0) {
4466 case SHKEY_Key_Explorer:
4468 size_key = sizeof(explorerW);
4470 case SHKEY_Key_Shell:
4472 size_key = sizeof(shellW);
4474 case SHKEY_Key_ShellNoRoam:
4475 key = shell_no_roamW;
4476 size_key = sizeof(shell_no_roamW);
4478 case SHKEY_Key_Classes:
4480 size_key = sizeof(classesW);
4483 FIXME("unsupported flags (0x%08x)\n", flags);
4487 switch(flags&0xff000) {
4488 case SHKEY_Subkey_Default:
4492 case SHKEY_Subkey_ResourceName:
4493 subkey = localized_resource_nameW;
4494 size_subkey = sizeof(localized_resource_nameW);
4496 case SHKEY_Subkey_Handlers:
4498 size_subkey = sizeof(handlersW);
4500 case SHKEY_Subkey_Associations:
4501 subkey = associationsW;
4502 size_subkey = sizeof(associationsW);
4504 case SHKEY_Subkey_Volatile:
4506 size_subkey = sizeof(volatileW);
4508 case SHKEY_Subkey_MUICache:
4509 subkey = mui_cacheW;
4510 size_subkey = sizeof(mui_cacheW);
4512 case SHKEY_Subkey_FileExts:
4513 subkey = file_extsW;
4514 size_subkey = sizeof(file_extsW);
4517 FIXME("unsupported flags (0x%08x)\n", flags);
4522 size_user = lstrlenW(sub_key)*sizeof(WCHAR);
4526 path = HeapAlloc(GetProcessHeap(), 0, size_key+size_subkey+size_user+sizeof(WCHAR));
4528 ERR("Out of memory\n");
4532 memcpy(path, key, size_key);
4534 memcpy(path+size_key/sizeof(WCHAR), subkey, size_subkey);
4536 memcpy(path+(size_key+size_subkey)/sizeof(WCHAR), sub_key, size_user);
4537 path[(size_key+size_subkey+size_user)/sizeof(WCHAR)] = '\0';
4540 RegCreateKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
4541 path, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &hkey, NULL);
4543 RegOpenKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
4544 path, 0, MAXIMUM_ALLOWED, &hkey);
4546 HeapFree(GetProcessHeap(), 0, path);
4550 /***********************************************************************
4551 * SHQueueUserWorkItem (SHLWAPI.@)
4553 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback,
4554 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4555 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4557 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4558 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4560 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4561 FIXME("Unsupported arguments\n");
4563 return QueueUserWorkItem(pfnCallback, pContext, 0);
4566 /***********************************************************************
4567 * SHSetTimerQueueTimer (SHLWAPI.263)
4569 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
4570 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4571 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4575 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4576 if (dwFlags & TPS_LONGEXECTIME) {
4577 dwFlags &= ~TPS_LONGEXECTIME;
4578 dwFlags |= WT_EXECUTELONGFUNCTION;
4580 if (dwFlags & TPS_EXECUTEIO) {
4581 dwFlags &= ~TPS_EXECUTEIO;
4582 dwFlags |= WT_EXECUTEINIOTHREAD;
4585 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4586 dwDueTime, dwPeriod, dwFlags))
4592 /***********************************************************************
4593 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4595 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4597 IInputObjectSite *pIOS = NULL;
4598 HRESULT hRet = E_INVALIDARG;
4600 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4604 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4606 if (SUCCEEDED(hRet) && pIOS)
4608 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4609 IInputObjectSite_Release(pIOS);
4615 /***********************************************************************
4616 * SKAllocValueW (SHLWAPI.519)
4618 HRESULT WINAPI SKAllocValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type,
4619 LPVOID *data, DWORD *count)
4624 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey),
4625 debugstr_w(value), type, data, count);
4627 hkey = SHGetShellKey(flags, subkey, FALSE);
4629 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4631 ret = SHQueryValueExW(hkey, value, NULL, type, NULL, &size);
4634 return HRESULT_FROM_WIN32(ret);
4638 *data = LocalAlloc(0, size);
4641 return E_OUTOFMEMORY;
4644 ret = SHQueryValueExW(hkey, value, NULL, type, *data, &size);
4649 return HRESULT_FROM_WIN32(ret);
4652 /***********************************************************************
4653 * SKDeleteValueW (SHLWAPI.518)
4655 HRESULT WINAPI SKDeleteValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value)
4660 TRACE("(0x%x, %s %s)\n", flags, debugstr_w(subkey), debugstr_w(value));
4662 hkey = SHGetShellKey(flags, subkey, FALSE);
4664 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4666 ret = RegDeleteValueW(hkey, value);
4669 return HRESULT_FROM_WIN32(ret);
4672 /***********************************************************************
4673 * SKGetValueW (SHLWAPI.516)
4675 HRESULT WINAPI SKGetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type,
4676 void *data, DWORD *count)
4681 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey),
4682 debugstr_w(value), type, data, count);
4684 hkey = SHGetShellKey(flags, subkey, FALSE);
4686 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4688 ret = SHQueryValueExW(hkey, value, NULL, type, data, count);
4691 return HRESULT_FROM_WIN32(ret);
4694 /***********************************************************************
4695 * SKSetValueW (SHLWAPI.516)
4697 HRESULT WINAPI SKSetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value,
4698 DWORD type, void *data, DWORD count)
4703 TRACE("(0x%x, %s, %s, %x, %p, %d)\n", flags, debugstr_w(subkey),
4704 debugstr_w(value), type, data, count);
4706 hkey = SHGetShellKey(flags, subkey, TRUE);
4708 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4710 ret = RegSetValueExW(hkey, value, 0, type, data, count);
4713 return HRESULT_FROM_WIN32(ret);
4716 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4718 /***********************************************************************
4719 * GetUIVersion (SHLWAPI.452)
4721 DWORD WINAPI GetUIVersion(void)
4723 static DWORD version;
4727 DllGetVersion_func pDllGetVersion;
4728 HMODULE dll = LoadLibraryA("shell32.dll");
4731 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4735 dvi.cbSize = sizeof(DLLVERSIONINFO);
4736 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4739 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4744 /***********************************************************************
4745 * ShellMessageBoxWrapW [SHLWAPI.388]
4747 * See shell32.ShellMessageBoxW
4750 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4751 * because we can't forward to it in the .spec file since it's exported by
4752 * ordinal. If you change the implementation here please update the code in
4755 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
4756 LPCWSTR lpCaption, UINT uType, ...)
4758 WCHAR *szText = NULL, szTitle[100];
4759 LPCWSTR pszText, pszTitle = szTitle;
4764 __ms_va_start(args, uType);
4766 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
4768 if (IS_INTRESOURCE(lpCaption))
4769 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
4771 pszTitle = lpCaption;
4773 if (IS_INTRESOURCE(lpText))
4776 UINT len = LoadStringW(hInstance, LOWORD(lpText), (LPWSTR)&ptr, 0);
4780 szText = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
4781 if (szText) LoadStringW(hInstance, LOWORD(lpText), szText, len + 1);
4785 WARN("Failed to load id %d\n", LOWORD(lpText));
4793 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4794 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4798 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4800 HeapFree(GetProcessHeap(), 0, szText);
4805 /***********************************************************************
4806 * ZoneComputePaneSize [SHLWAPI.382]
4808 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4814 /***********************************************************************
4815 * SHChangeNotifyWrap [SHLWAPI.394]
4817 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
4819 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
4822 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
4823 SID_IDENTIFIER_AUTHORITY sidAuthority;
4824 DWORD dwUserGroupID;
4826 } SHELL_USER_SID, *PSHELL_USER_SID;
4828 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
4829 SHELL_USER_SID susID;
4833 DWORD dwInheritMask;
4834 DWORD dwInheritAccessMask;
4835 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
4837 /***********************************************************************
4838 * GetShellSecurityDescriptor [SHLWAPI.475]
4840 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4843 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4844 * each of which describes permissions to apply
4845 * cUserPerm [I] number of entries in apUserPerm array
4848 * success: pointer to SECURITY_DESCRIPTOR
4852 * Call should free returned descriptor with LocalFree
4854 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4857 PSID cur_user = NULL;
4861 PSECURITY_DESCRIPTOR psd = NULL;
4863 TRACE("%p %d\n", apUserPerm, cUserPerm);
4865 if (apUserPerm == NULL || cUserPerm <= 0)
4868 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
4872 acl_size = sizeof(ACL);
4874 for(sid_count = 0; sid_count < cUserPerm; sid_count++)
4876 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
4877 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
4878 PSHELL_USER_SID sid = &perm->susID;
4882 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4883 { /* current user's SID */
4887 DWORD bufsize = sizeof(tuUser);
4889 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4892 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4894 cur_user = ((PTOKEN_USER)tuUser)->User.Sid;
4899 } else if (sid->dwUserID==0) /* one sub-authority */
4900 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
4901 0, 0, 0, 0, 0, 0, &pSid);
4903 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4904 0, 0, 0, 0, 0, 0, &pSid);
4908 sidlist[sid_count] = pSid;
4909 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4910 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
4913 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
4917 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4919 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4922 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4925 for(i = 0; i < sid_count; i++)
4927 PSHELL_USER_PERMISSION sup = apUserPerm[i];
4928 PSID sid = sidlist[i];
4930 switch(sup->dwAccessType)
4932 case ACCESS_ALLOWED_ACE_TYPE:
4933 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4935 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4936 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4939 case ACCESS_DENIED_ACE_TYPE:
4940 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4942 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4943 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4951 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4960 for(i = 0; i < sid_count; i++)
4962 if (!cur_user || sidlist[i] != cur_user)
4963 FreeSid(sidlist[i]);
4965 HeapFree(GetProcessHeap(), 0, sidlist);
4970 /***********************************************************************
4971 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4973 * Creates a property bag from a registry key
4976 * hKey [I] Handle to the desired registry key
4977 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4978 * grfMode [I] Optional flags
4979 * riid [I] IID of requested property bag interface
4980 * ppv [O] Address to receive pointer to the new interface
4984 * failure: error code
4987 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey,
4988 DWORD grfMode, REFIID riid, void **ppv)
4990 FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode,
4991 debugstr_guid(riid), ppv);
4996 /***********************************************************************
4997 * SHGetViewStatePropertyBag [SHLWAPI.515]
4999 * Retrieves a property bag in which the view state information of a folder
5003 * pidl [I] PIDL of the folder requested
5004 * bag_name [I] Name of the property bag requested
5005 * flags [I] Optional flags
5006 * riid [I] IID of requested property bag interface
5007 * ppv [O] Address to receive pointer to the new interface
5011 * failure: error code
5014 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
5015 DWORD flags, REFIID riid, void **ppv)
5017 FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags,
5018 debugstr_guid(riid), ppv);
5023 /***********************************************************************
5024 * SHFormatDateTimeW [SHLWAPI.354]
5026 * Produces a string representation of a time.
5029 * fileTime [I] Pointer to FILETIME structure specifying the time
5030 * flags [I] Flags specifying the desired output
5031 * buf [O] Pointer to buffer for output
5032 * size [I] Number of characters that can be contained in buffer
5035 * success: number of characters written to the buffer
5039 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
5040 LPWSTR buf, UINT size)
5042 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
5043 DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT;
5048 TRACE("%p %p %p %u\n", fileTime, flags, buf, size);
5053 if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS)
5054 FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS);
5056 FileTimeToLocalFileTime(fileTime, &ft);
5057 FileTimeToSystemTime(&ft, &st);
5059 /* first of all date */
5060 if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE))
5062 static const WCHAR sep1[] = {',',' ',0};
5063 static const WCHAR sep2[] = {' ',0};
5065 DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE;
5066 ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size);
5067 if (ret >= size) return ret;
5070 if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)))
5072 if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2))
5076 lstrcatW(&buf[ret-1], sep1);
5082 lstrcatW(&buf[ret-1], sep2);
5088 if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))
5090 DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS;
5093 ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret);
5098 #undef SHFORMATDT_UNSUPPORTED_FLAGS
5101 /***********************************************************************
5102 * SHFormatDateTimeA [SHLWAPI.353]
5104 * See SHFormatDateTimeW.
5107 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags,
5108 LPSTR buf, UINT size)
5116 bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
5117 retval = SHFormatDateTimeW(fileTime, flags, bufW, size);
5120 WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL);
5122 HeapFree(GetProcessHeap(), 0, bufW);
5126 /***********************************************************************
5127 * ZoneCheckUrlExW [SHLWAPI.231]
5129 * Checks the details of the security zone for the supplied site. (?)
5133 * szURL [I] Pointer to the URL to check
5135 * Other parameters currently unknown.
5141 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2,
5142 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6,
5145 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2,
5146 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7);
5151 /***********************************************************************
5152 * SHVerbExistsNA [SHLWAPI.196]
5157 * verb [I] a string, often appears to be an extension.
5159 * Other parameters currently unknown.
5164 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3)
5166 FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3);
5170 /*************************************************************************
5173 * Undocumented: Implementation guessed at via Name and behavior
5176 * lpUnknown [I] Object to get an IServiceProvider interface from
5177 * riid [I] Function requested for QueryService call
5178 * lppOut [O] Destination for the service interface pointer
5181 * Success: S_OK. lppOut contains an object providing the requested service
5182 * Failure: An HRESULT error code
5185 * lpUnknown is expected to support the IServiceProvider interface.
5187 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown,
5188 REFGUID riid, LPVOID *lppOut)
5190 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut);
5191 return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut);
5194 /**************************************************************************
5195 * SHPropertyBag_ReadLONG (SHLWAPI.496)
5197 * This function asks a property bag to read a named property as a LONG.
5200 * ppb: a IPropertyBag interface
5201 * pszPropName: Unicode string that names the property
5202 * pValue: address to receive the property value as a 32-bit signed integer
5207 BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue)
5211 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue);
5212 if (!pszPropName || !ppb || !pValue)
5213 return E_INVALIDARG;
5215 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
5218 if (V_VT(&var) == VT_I4)
5219 *pValue = V_I4(&var);
5221 hr = DISP_E_BADVARTYPE;
5226 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
5227 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
5228 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
5229 #define OBJCOMPAT_UNBINDABLE 0x00000004
5230 #define OBJCOMPAT_PINDLL 0x00000008
5231 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
5232 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
5233 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
5234 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
5235 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
5236 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
5237 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
5238 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
5239 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
5241 /* a search table for compatibility flags */
5242 struct objcompat_entry {
5243 const WCHAR name[30];
5247 /* expected to be sorted by name */
5248 static const struct objcompat_entry objcompat_table[] = {
5249 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
5250 OBJCOMPAT_COCREATESHELLFOLDERONLY },
5251 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
5252 OBJCOMPAT_CTXMENU_LIMITEDQI },
5253 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
5254 OBJCOMPAT_CTXMENU_LIMITEDQI },
5255 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
5256 OBJCOMPAT_CTXMENU_XPQCMFLAGS },
5257 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
5258 OBJCOMPAT_NEEDSFILESYSANCESTOR },
5259 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
5260 OBJCOMPAT_NEEDSSTORAGEANCESTOR },
5261 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
5262 OBJCOMPAT_NOIPROPERTYSTORE },
5263 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
5264 OBJCOMPAT_NOLEGACYWEBVIEW },
5265 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
5266 OBJCOMPAT_NOTAFILESYSTEM },
5267 { {'N','O','_','W','E','B','V','I','E','W',0},
5268 OBJCOMPAT_NO_WEBVIEW },
5269 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
5270 OBJCOMPAT_OTNEEDSSFCACHE },
5271 { {'P','I','N','D','L','L',0},
5273 { {'U','N','B','I','N','D','A','B','L','E',0},
5274 OBJCOMPAT_UNBINDABLE }
5277 /**************************************************************************
5278 * SHGetObjectCompatFlags (SHLWAPI.476)
5280 * Function returns an integer representation of compatibility flags stored
5281 * in registry for CLSID under ShellCompatibility subkey.
5284 * pUnk: pointer to object IUnknown interface, idetifies CLSID
5285 * clsid: pointer to CLSID to retrieve data for
5288 * 0 on failure, flags set on success
5290 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid)
5292 static const WCHAR compatpathW[] =
5293 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
5294 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
5295 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
5296 'O','b','j','e','c','t','s','\\','%','s',0};
5297 WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */];
5298 DWORD ret, length = sizeof(strW)/sizeof(WCHAR);
5303 TRACE("%p %s\n", pUnk, debugstr_guid(clsid));
5305 if (!pUnk && !clsid) return 0;
5309 FIXME("iface not handled\n");
5313 StringFromCLSID(clsid, &clsid_str);
5314 sprintfW(strW, compatpathW, clsid_str);
5315 CoTaskMemFree(clsid_str);
5317 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key);
5318 if (ret != ERROR_SUCCESS) return 0;
5320 /* now collect flag values */
5322 for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++)
5324 INT left, right, res, x;
5326 /* search in table */
5328 right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1;
5330 while (right >= left) {
5331 x = (left + right) / 2;
5332 res = strcmpW(strW, objcompat_table[x].name);
5335 ret |= objcompat_table[x].value;
5344 length = sizeof(strW)/sizeof(WCHAR);