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
48 #include "wine/unicode.h"
49 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(shell);
54 /* DLL handles for late bound calls */
55 extern HINSTANCE shlwapi_hInstance;
56 extern DWORD SHLWAPI_ThreadRef_index;
58 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
59 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
60 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
63 NOTES: Most functions exported by ordinal seem to be superflous.
64 The reason for these functions to be there is to provide a wrapper
65 for unicode functions to provide these functions on systems without
66 unicode functions eg. win95/win98. Since we have such functions we just
67 call these. If running Wine with native DLLs, some late bound calls may
68 fail. However, it is better to implement the functions in the forward DLL
69 and recommend the builtin rather than reimplementing the calls here!
72 /*************************************************************************
73 * SHLWAPI_DupSharedHandle
75 * Internal implemetation of SHLWAPI_11.
78 HANDLE WINAPI SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
79 DWORD dwSrcProcId, DWORD dwAccess,
83 DWORD dwMyProcId = GetCurrentProcessId();
86 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
89 /* Get dest process handle */
90 if (dwDstProcId == dwMyProcId)
91 hDst = GetCurrentProcess();
93 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
97 /* Get src process handle */
98 if (dwSrcProcId == dwMyProcId)
99 hSrc = GetCurrentProcess();
101 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
105 /* Make handle available to dest process */
106 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
107 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
110 if (dwSrcProcId != dwMyProcId)
114 if (dwDstProcId != dwMyProcId)
118 TRACE("Returning handle %p\n", hRet);
122 /*************************************************************************
125 * Create a block of sharable memory and initialise it with data.
128 * lpvData [I] Pointer to data to write
129 * dwSize [I] Size of data
130 * dwProcId [I] ID of process owning data
133 * Success: A shared memory handle
137 * Ordinals 7-11 provide a set of calls to create shared memory between a
138 * group of processes. The shared memory is treated opaquely in that its size
139 * is not exposed to clients who map it. This is accomplished by storing
140 * the size of the map as the first DWORD of mapped data, and then offsetting
141 * the view pointer returned by this size.
144 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
150 TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
152 /* Create file mapping of the correct length */
153 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
154 dwSize + sizeof(dwSize), NULL);
158 /* Get a view in our process address space */
159 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
163 /* Write size of data, followed by the data, to the view */
164 *((DWORD*)pMapped) = dwSize;
166 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
168 /* Release view. All further views mapped will be opaque */
169 UnmapViewOfFile(pMapped);
170 hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
171 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
172 DUPLICATE_SAME_ACCESS);
179 /*************************************************************************
182 * Get a pointer to a block of shared memory from a shared memory handle.
185 * hShared [I] Shared memory handle
186 * dwProcId [I] ID of process owning hShared
189 * Success: A pointer to the shared memory
193 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
198 TRACE("(%p %d)\n", hShared, dwProcId);
200 /* Get handle to shared memory for current process */
201 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
202 FILE_MAP_ALL_ACCESS, 0);
204 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
208 return (char *) pMapped + sizeof(DWORD); /* Hide size */
212 /*************************************************************************
215 * Release a pointer to a block of shared memory.
218 * lpView [I] Shared memory pointer
225 BOOL WINAPI SHUnlockShared(LPVOID lpView)
227 TRACE("(%p)\n", lpView);
228 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
231 /*************************************************************************
234 * Destroy a block of sharable memory.
237 * hShared [I] Shared memory handle
238 * dwProcId [I] ID of process owning hShared
245 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
249 TRACE("(%p %d)\n", hShared, dwProcId);
251 /* Get a copy of the handle for our process, closing the source handle */
252 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
253 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
254 /* Close local copy */
255 return CloseHandle(hClose);
258 /*************************************************************************
261 * Copy a sharable memory handle from one process to another.
264 * hShared [I] Shared memory handle to duplicate
265 * dwDstProcId [I] ID of the process wanting the duplicated handle
266 * dwSrcProcId [I] ID of the process owning hShared
267 * dwAccess [I] Desired DuplicateHandle() access
268 * dwOptions [I] Desired DuplicateHandle() options
271 * Success: A handle suitable for use by the dwDstProcId process.
272 * Failure: A NULL handle.
275 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
276 DWORD dwAccess, DWORD dwOptions)
280 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
281 dwAccess, dwOptions);
285 /*************************************************************************
288 * Create and register a clipboard enumerator for a web browser.
291 * lpBC [I] Binding context
292 * lpUnknown [I] An object exposing the IWebBrowserApp interface
296 * Failure: An HRESULT error code.
299 * The enumerator is stored as a property of the web browser. If it does not
300 * yet exist, it is created and set before being registered.
302 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
304 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
305 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
306 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
308 IEnumFORMATETC* pIEnumFormatEtc = NULL;
311 IWebBrowserApp* pBrowser = NULL;
313 TRACE("(%p, %p)\n", lpBC, lpUnknown);
315 /* Get An IWebBrowserApp interface from lpUnknown */
316 hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
317 if (FAILED(hRet) || !pBrowser)
318 return E_NOINTERFACE;
320 V_VT(&var) = VT_EMPTY;
322 /* The property we get is the browsers clipboard enumerator */
323 property = SysAllocString(szProperty);
324 hRet = IWebBrowserApp_GetProperty(pBrowser, property, &var);
325 SysFreeString(property);
329 if (V_VT(&var) == VT_EMPTY)
331 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
332 char szKeyBuff[128], szValueBuff[128];
333 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
334 FORMATETC* formatList, *format;
337 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
339 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
340 "Version\\Internet Settings\\Accepted Documents", &hDocs))
343 /* Get count of values in key */
346 dwKeySize = sizeof(szKeyBuff);
347 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
351 dwNumValues = dwCount;
353 /* Note: dwCount = number of items + 1; The extra item is the end node */
354 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
356 return E_OUTOFMEMORY;
365 /* Register clipboard formats for the values and populate format list */
366 while(!dwRet && dwCount < dwNumValues)
368 dwKeySize = sizeof(szKeyBuff);
369 dwValueSize = sizeof(szValueBuff);
370 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
371 (PBYTE)szValueBuff, &dwValueSize);
375 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
377 format->dwAspect = 1;
386 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
387 format->cfFormat = 0;
389 format->dwAspect = 1;
393 /* Create a clipboard enumerator */
394 hRet = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
396 if (FAILED(hRet) || !pIEnumFormatEtc)
399 /* Set our enumerator as the browsers property */
400 V_VT(&var) = VT_UNKNOWN;
401 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
403 hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
406 IEnumFORMATETC_Release(pIEnumFormatEtc);
407 goto RegisterDefaultAcceptHeaders_Exit;
411 if (V_VT(&var) == VT_UNKNOWN)
413 /* Our variant is holding the clipboard enumerator */
414 IUnknown* pIUnknown = V_UNKNOWN(&var);
415 IEnumFORMATETC* pClone = NULL;
417 TRACE("Retrieved IEnumFORMATETC property\n");
419 /* Get an IEnumFormatEtc interface from the variants value */
420 pIEnumFormatEtc = NULL;
421 hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
422 (PVOID)&pIEnumFormatEtc);
423 if (!hRet && pIEnumFormatEtc)
425 /* Clone and register the enumerator */
426 hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
429 RegisterFormatEnumerator(lpBC, pClone, 0);
431 IEnumFORMATETC_Release(pClone);
434 /* Release the IEnumFormatEtc interface */
435 IEnumFORMATETC_Release(pIUnknown);
437 IUnknown_Release(V_UNKNOWN(&var));
440 RegisterDefaultAcceptHeaders_Exit:
441 IWebBrowserApp_Release(pBrowser);
445 /*************************************************************************
448 * Get Explorers "AcceptLanguage" setting.
451 * langbuf [O] Destination for language string
452 * buflen [I] Length of langbuf
453 * [0] Success: used length of langbuf
456 * Success: S_OK. langbuf is set to the language string found.
457 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
458 * does not contain the setting.
459 * E_INVALIDARG, If the buffer is not big enough
461 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
463 static const WCHAR szkeyW[] = {
464 'S','o','f','t','w','a','r','e','\\',
465 'M','i','c','r','o','s','o','f','t','\\',
466 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
467 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
468 static const WCHAR valueW[] = {
469 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
470 static const WCHAR enusW[] = {'e','n','-','u','s',0};
471 DWORD mystrlen, mytype;
477 if(!langbuf || !buflen || !*buflen)
480 mystrlen = (*buflen > 20) ? *buflen : 20 ;
481 mystr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * mystrlen);
482 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
483 if(RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &mystrlen)) {
484 /* Did not find value */
485 mylcid = GetUserDefaultLCID();
486 /* somehow the mylcid translates into "en-us"
487 * this is similar to "LOCALE_SABBREVLANGNAME"
488 * which could be gotten via GetLocaleInfo.
489 * The only problem is LOCALE_SABBREVLANGUAGE" is
490 * a 3 char string (first 2 are country code and third is
491 * letter for "sublanguage", which does not come close to
494 lstrcpyW(mystr, enusW);
495 mystrlen = lstrlenW(mystr);
497 /* handle returned string */
498 FIXME("missing code\n");
500 memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
502 if(*buflen > strlenW(mystr)) {
503 *buflen = strlenW(mystr);
507 retval = E_INVALIDARG;
508 SetLastError(ERROR_INSUFFICIENT_BUFFER);
511 HeapFree(GetProcessHeap(), 0, mystr);
515 /*************************************************************************
518 * Ascii version of GetAcceptLanguagesW.
520 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
523 DWORD buflenW, convlen;
526 if(!langbuf || !buflen || !*buflen) return E_FAIL;
529 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
530 retval = GetAcceptLanguagesW(langbufW, &buflenW);
534 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
536 else /* copy partial string anyway */
538 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
539 if (convlen < *buflen) langbuf[convlen] = 0;
541 *buflen = buflenW ? convlen : 0;
543 HeapFree(GetProcessHeap(), 0, langbufW);
547 /*************************************************************************
550 * Convert a GUID to a string.
553 * guid [I] GUID to convert
554 * lpszDest [O] Destination for string
555 * cchMax [I] Length of output buffer
558 * The length of the string created.
560 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
565 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
567 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
568 guid->Data1, guid->Data2, guid->Data3,
569 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
570 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
572 iLen = strlen(xguid) + 1;
576 memcpy(lpszDest, xguid, iLen);
580 /*************************************************************************
583 * Convert a GUID to a string.
586 * guid [I] GUID to convert
587 * str [O] Destination for string
588 * cmax [I] Length of output buffer
591 * The length of the string created.
593 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
597 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
598 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
599 'X','%','0','2','X','%','0','2','X','}',0};
601 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
603 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
604 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
605 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
607 iLen = strlenW(xguid) + 1;
611 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
615 /*************************************************************************
618 * Determine if a Unicode character is a space.
621 * wc [I] Character to check.
624 * TRUE, if wc is a space,
627 BOOL WINAPI IsCharSpaceW(WCHAR wc)
631 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
634 /*************************************************************************
637 * Determine if a Unicode character is a blank.
640 * wc [I] Character to check.
643 * TRUE, if wc is a blank,
647 BOOL WINAPI IsCharBlankW(WCHAR wc)
651 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
654 /*************************************************************************
657 * Determine if a Unicode character is punctuation.
660 * wc [I] Character to check.
663 * TRUE, if wc is punctuation,
666 BOOL WINAPI IsCharPunctW(WCHAR wc)
670 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
673 /*************************************************************************
676 * Determine if a Unicode character is a control character.
679 * wc [I] Character to check.
682 * TRUE, if wc is a control character,
685 BOOL WINAPI IsCharCntrlW(WCHAR wc)
689 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
692 /*************************************************************************
695 * Determine if a Unicode character is a digit.
698 * wc [I] Character to check.
701 * TRUE, if wc is a digit,
704 BOOL WINAPI IsCharDigitW(WCHAR wc)
708 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
711 /*************************************************************************
714 * Determine if a Unicode character is a hex digit.
717 * wc [I] Character to check.
720 * TRUE, if wc is a hex digit,
723 BOOL WINAPI IsCharXDigitW(WCHAR wc)
727 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
730 /*************************************************************************
734 BOOL WINAPI GetStringType3ExW(LPWSTR lpszStr, DWORD dwLen, LPVOID p3)
736 FIXME("(%s,0x%08x,%p): stub\n", debugstr_w(lpszStr), dwLen, p3);
740 /*************************************************************************
743 * Insert a bitmap menu item at the bottom of a menu.
746 * hMenu [I] Menu to insert into
747 * flags [I] Flags for insertion
748 * id [I] Menu ID of the item
749 * str [I] Menu text for the item
752 * Success: TRUE, the item is inserted into the menu
753 * Failure: FALSE, if any parameter is invalid
755 BOOL WINAPI AppendMenuWrapW(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
757 TRACE("(%p,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));
758 return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);
761 /*************************************************************************
764 * Set the text of a given dialog item.
767 * hWnd [I] Handle of dialog
768 * iItem [I] Index of item
769 * lpszText [O] Text to set
772 * Success: TRUE. The text of the dialog is set to lpszText.
773 * Failure: FALSE, Otherwise.
775 BOOL WINAPI SetDlgItemTextWrapW(HWND hWnd, INT iItem, LPCWSTR lpszText)
777 HWND hWndItem = GetDlgItem(hWnd, iItem);
779 return SetWindowTextW(hWndItem, lpszText);
783 /*************************************************************************
786 * Compare two Ascii strings up to a given length.
789 * lpszSrc [I] Source string
790 * lpszCmp [I] String to compare to lpszSrc
791 * len [I] Maximum length
794 * A number greater than, less than or equal to 0 depending on whether
795 * lpszSrc is greater than, less than or equal to lpszCmp.
797 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
799 return strncmp(lpszSrc, lpszCmp, len);
802 /*************************************************************************
805 * Unicode version of StrCmpNCA.
807 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
809 return strncmpW(lpszSrc, lpszCmp, len);
812 /*************************************************************************
815 * Compare two Ascii strings up to a given length, ignoring case.
818 * lpszSrc [I] Source string
819 * lpszCmp [I] String to compare to lpszSrc
820 * len [I] Maximum length
823 * A number greater than, less than or equal to 0 depending on whether
824 * lpszSrc is greater than, less than or equal to lpszCmp.
826 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
828 return strncasecmp(lpszSrc, lpszCmp, len);
831 /*************************************************************************
834 * Unicode version of StrCmpNICA.
836 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
838 return strncmpiW(lpszSrc, lpszCmp, len);
841 /*************************************************************************
844 * Compare two Ascii strings.
847 * lpszSrc [I] Source string
848 * lpszCmp [I] String to compare to lpszSrc
851 * A number greater than, less than or equal to 0 depending on whether
852 * lpszSrc is greater than, less than or equal to lpszCmp.
854 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
856 return strcmp(lpszSrc, lpszCmp);
859 /*************************************************************************
862 * Unicode version of StrCmpCA.
864 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
866 return strcmpW(lpszSrc, lpszCmp);
869 /*************************************************************************
872 * Compare two Ascii strings, ignoring case.
875 * lpszSrc [I] Source string
876 * lpszCmp [I] String to compare to lpszSrc
879 * A number greater than, less than or equal to 0 depending on whether
880 * lpszSrc is greater than, less than or equal to lpszCmp.
882 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
884 return strcasecmp(lpszSrc, lpszCmp);
887 /*************************************************************************
890 * Unicode version of StrCmpICA.
892 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
894 return strcmpiW(lpszSrc, lpszCmp);
897 /*************************************************************************
900 * Get an identification string for the OS and explorer.
903 * lpszDest [O] Destination for Id string
904 * dwDestLen [I] Length of lpszDest
907 * TRUE, If the string was created successfully
910 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
914 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
916 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
918 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
924 /*************************************************************************
927 * Unicode version of SHAboutInfoA.
929 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
931 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
932 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
933 ' ','E','x','p','l','o','r','e','r','\0' };
934 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
935 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
936 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
937 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
938 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
939 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
940 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
941 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
942 ' ','E','x','p','l','o','r','e','r','\\',
943 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
944 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
945 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
946 'V','e','r','s','i','o','n','\0' };
947 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
948 'O','w','n','e','r','\0' };
949 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
950 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
951 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
952 static const WCHAR szUpdate[] = { 'I','E','A','K',
953 'U','p','d','a','t','e','U','r','l','\0' };
954 static const WCHAR szHelp[] = { 'I','E','A','K',
955 'H','e','l','p','S','t','r','i','n','g','\0' };
960 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
967 /* Try the NT key first, followed by 95/98 key */
968 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
969 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
975 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
977 DWORD dwStrLen = strlenW(buff);
978 dwLen = 30 - dwStrLen;
979 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
980 szCustomized, &dwType, buff+dwStrLen, &dwLen);
982 StrCatBuffW(lpszDest, buff, dwDestLen);
984 /* ~Registered Owner */
987 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
989 StrCatBuffW(lpszDest, buff, dwDestLen);
991 /* ~Registered Organization */
993 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
995 StrCatBuffW(lpszDest, buff, dwDestLen);
997 /* FIXME: Not sure where this number comes from */
1001 StrCatBuffW(lpszDest, buff, dwDestLen);
1005 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
1007 StrCatBuffW(lpszDest, buff, dwDestLen);
1009 /* ~IE Update Url */
1011 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
1013 StrCatBuffW(lpszDest, buff, dwDestLen);
1015 /* ~IE Help String */
1017 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
1019 StrCatBuffW(lpszDest, buff, dwDestLen);
1025 /*************************************************************************
1028 * Call IOleCommandTarget_QueryStatus() on an object.
1031 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1032 * pguidCmdGroup [I] GUID for the command group
1034 * prgCmds [O] Commands
1035 * pCmdText [O] Command text
1039 * Failure: E_FAIL, if lpUnknown is NULL.
1040 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1041 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1043 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1044 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1046 HRESULT hRet = E_FAIL;
1048 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1052 IOleCommandTarget* lpOle;
1054 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1057 if (SUCCEEDED(hRet) && lpOle)
1059 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1061 IOleCommandTarget_Release(lpOle);
1067 /*************************************************************************
1070 * Call IOleCommandTarget_Exec() on an object.
1073 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1074 * pguidCmdGroup [I] GUID for the command group
1078 * Failure: E_FAIL, if lpUnknown is NULL.
1079 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1080 * Otherwise, an error code from IOleCommandTarget_Exec().
1082 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1083 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1086 HRESULT hRet = E_FAIL;
1088 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1089 nCmdexecopt, pvaIn, pvaOut);
1093 IOleCommandTarget* lpOle;
1095 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1097 if (SUCCEEDED(hRet) && lpOle)
1099 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1100 nCmdexecopt, pvaIn, pvaOut);
1101 IOleCommandTarget_Release(lpOle);
1107 /*************************************************************************
1110 * Retrieve, modify, and re-set a value from a window.
1113 * hWnd [I] Window to get value from
1114 * offset [I] Offset of value
1115 * wMask [I] Mask for uiFlags
1116 * wFlags [I] Bits to set in window value
1119 * The new value as it was set, or 0 if any parameter is invalid.
1122 * Any bits set in uiMask are cleared from the value, then any bits set in
1123 * uiFlags are set in the value.
1125 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
1127 LONG ret = GetWindowLongA(hwnd, offset);
1128 LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);
1130 if (newFlags != ret)
1131 ret = SetWindowLongA(hwnd, offset, newFlags);
1135 /*************************************************************************
1138 * Change a window's parent.
1141 * hWnd [I] Window to change parent of
1142 * hWndParent [I] New parent window
1145 * The old parent of hWnd.
1148 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1149 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1151 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1153 TRACE("%p, %p\n", hWnd, hWndParent);
1155 if(GetParent(hWnd) == hWndParent)
1159 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1161 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1163 return SetParent(hWnd, hWndParent);
1166 /*************************************************************************
1169 * Locate and advise a connection point in an IConnectionPointContainer object.
1172 * lpUnkSink [I] Sink for the connection point advise call
1173 * riid [I] REFIID of connection point to advise
1174 * bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first
1175 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1176 * lpCookie [O] Pointer to connection point cookie
1177 * lppCP [O] Destination for the IConnectionPoint found
1180 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1181 * that was advised. The caller is responsible for releasing it.
1182 * Failure: E_FAIL, if any arguments are invalid.
1183 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1184 * Or an HRESULT error code if any call fails.
1186 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
1187 IUnknown* lpUnknown, LPDWORD lpCookie,
1188 IConnectionPoint **lppCP)
1191 IConnectionPointContainer* lpContainer;
1192 IConnectionPoint *lpCP;
1194 if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
1200 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1201 (void**)&lpContainer);
1202 if (SUCCEEDED(hRet))
1204 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1206 if (SUCCEEDED(hRet))
1209 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1210 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1215 if (lppCP && SUCCEEDED(hRet))
1216 *lppCP = lpCP; /* Caller keeps the interface */
1218 IConnectionPoint_Release(lpCP); /* Release it */
1221 IUnknown_Release(lpContainer);
1226 /*************************************************************************
1229 * Release an interface.
1232 * lpUnknown [I] Object to release
1237 DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1241 TRACE("(%p)\n",lpUnknown);
1243 if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1247 TRACE("doing Release\n");
1249 return IUnknown_Release(temp);
1252 /*************************************************************************
1255 * Skip '//' if present in a string.
1258 * lpszSrc [I] String to check for '//'
1261 * Success: The next character after the '//' or the string if not present
1262 * Failure: NULL, if lpszStr is NULL.
1264 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1266 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1271 /*************************************************************************
1274 * Check if two interfaces come from the same object.
1277 * lpInt1 [I] Interface to check against lpInt2.
1278 * lpInt2 [I] Interface to check against lpInt1.
1281 * TRUE, If the interfaces come from the same object.
1284 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1286 LPVOID lpUnknown1, lpUnknown2;
1288 TRACE("%p %p\n", lpInt1, lpInt2);
1290 if (!lpInt1 || !lpInt2)
1293 if (lpInt1 == lpInt2)
1296 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown,
1297 (LPVOID *)&lpUnknown1)))
1300 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown,
1301 (LPVOID *)&lpUnknown2)))
1304 if (lpUnknown1 == lpUnknown2)
1310 /*************************************************************************
1313 * Get the window handle of an object.
1316 * lpUnknown [I] Object to get the window handle of
1317 * lphWnd [O] Destination for window handle
1320 * Success: S_OK. lphWnd contains the objects window handle.
1321 * Failure: An HRESULT error code.
1324 * lpUnknown is expected to support one of the following interfaces:
1325 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1327 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1329 /* FIXME: Wine has no header for this object */
1330 static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,
1331 0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};
1333 HRESULT hRet = E_FAIL;
1335 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1340 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1344 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1348 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1353 if (SUCCEEDED(hRet))
1355 /* Lazyness here - Since GetWindow() is the first method for the above 3
1356 * interfaces, we use the same call for them all.
1358 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1359 IUnknown_Release(lpOle);
1361 TRACE("Returning HWND=%p\n", *lphWnd);
1367 /*************************************************************************
1370 * Call a method on as as yet unidentified object.
1373 * pUnk [I] Object supporting the unidentified interface,
1374 * arg [I] Argument for the call on the object.
1379 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1381 static const GUID guid_173 = {
1382 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1386 TRACE("(%p,%d)\n", pUnk, arg);
1388 /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1389 * We use this interface as its vtable entry is compatible with the
1390 * object in question.
1391 * FIXME: Find out what this object is and where it should be defined.
1394 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1396 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1397 IMalloc_Release(pUnk2);
1402 /*************************************************************************
1405 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1409 HRESULT WINAPI IUnknown_SetSite(
1410 IUnknown *obj, /* [in] OLE object */
1411 IUnknown *site) /* [in] Site interface */
1414 IObjectWithSite *iobjwithsite;
1415 IInternetSecurityManager *isecmgr;
1417 if (!obj) return E_FAIL;
1419 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1420 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1423 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1424 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1425 IUnknown_Release(iobjwithsite);
1429 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1430 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1431 if (FAILED(hr)) return hr;
1433 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1434 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1435 IUnknown_Release(isecmgr);
1440 /*************************************************************************
1443 * Call IPersist_GetClassID() on an object.
1446 * lpUnknown [I] Object supporting the IPersist interface
1447 * lpClassId [O] Destination for Class Id
1450 * Success: S_OK. lpClassId contains the Class Id requested.
1451 * Failure: E_FAIL, If lpUnknown is NULL,
1452 * E_NOINTERFACE If lpUnknown does not support IPersist,
1453 * Or an HRESULT error code.
1455 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1457 IPersist* lpPersist;
1458 HRESULT hRet = E_FAIL;
1460 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1464 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1465 if (SUCCEEDED(hRet))
1467 IPersist_GetClassID(lpPersist, lpClassId);
1468 IPersist_Release(lpPersist);
1474 /*************************************************************************
1477 * Retrieve a Service Interface from an object.
1480 * lpUnknown [I] Object to get an IServiceProvider interface from
1481 * sid [I] Service ID for IServiceProvider_QueryService() call
1482 * riid [I] Function requested for QueryService call
1483 * lppOut [O] Destination for the service interface pointer
1486 * Success: S_OK. lppOut contains an object providing the requested service
1487 * Failure: An HRESULT error code
1490 * lpUnknown is expected to support the IServiceProvider interface.
1492 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1495 IServiceProvider* pService = NULL;
1506 /* Get an IServiceProvider interface from the object */
1507 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1508 (LPVOID*)&pService);
1510 if (!hRet && pService)
1512 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1514 /* Get a Service interface from the object */
1515 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1517 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1519 /* Release the IServiceProvider interface */
1520 IUnknown_Release(pService);
1525 /*************************************************************************
1528 * Loads a popup menu.
1531 * hInst [I] Instance handle
1532 * szName [I] Menu name
1538 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1540 HMENU hMenu, hSubMenu;
1542 if ((hMenu = LoadMenuW(hInst, szName)))
1544 if ((hSubMenu = GetSubMenu(hMenu, 0)))
1545 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1553 typedef struct _enumWndData
1558 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1561 /* Callback for SHLWAPI_178 */
1562 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1564 enumWndData *data = (enumWndData *)lParam;
1566 TRACE("(%p,%p)\n", hWnd, data);
1567 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1571 /*************************************************************************
1574 * Send or post a message to every child of a window.
1577 * hWnd [I] Window whose children will get the messages
1578 * uiMsgId [I] Message Id
1579 * wParam [I] WPARAM of message
1580 * lParam [I] LPARAM of message
1581 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1587 * The appropriate ASCII or Unicode function is called for the window.
1589 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1593 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1597 data.uiMsgId = uiMsgId;
1598 data.wParam = wParam;
1599 data.lParam = lParam;
1602 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1604 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1606 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1610 /*************************************************************************
1613 * Remove all sub-menus from a menu.
1616 * hMenu [I] Menu to remove sub-menus from
1619 * Success: 0. All sub-menus under hMenu are removed
1620 * Failure: -1, if any parameter is invalid
1622 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1624 int iItemCount = GetMenuItemCount(hMenu) - 1;
1625 while (iItemCount >= 0)
1627 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1629 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1635 /*************************************************************************
1638 * Enable or disable a menu item.
1641 * hMenu [I] Menu holding menu item
1642 * uID [I] ID of menu item to enable/disable
1643 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1646 * The return code from EnableMenuItem.
1648 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1650 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1653 /*************************************************************************
1656 * Check or uncheck a menu item.
1659 * hMenu [I] Menu holding menu item
1660 * uID [I] ID of menu item to check/uncheck
1661 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1664 * The return code from CheckMenuItem.
1666 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1668 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1671 /*************************************************************************
1674 * Register a window class if it isn't already.
1677 * lpWndClass [I] Window class to register
1680 * The result of the RegisterClassA call.
1682 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1685 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1687 return (DWORD)RegisterClassA(wndclass);
1690 /*************************************************************************
1693 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1694 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1696 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1697 POINTL pt = { 0, 0 };
1703 pdwEffect = &dwEffect;
1705 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1708 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1710 IDropTarget_DragLeave(pDrop);
1714 /*************************************************************************
1717 * Call IPersistPropertyBag_Load() on an object.
1720 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1721 * lpPropBag [O] Destination for loaded IPropertyBag
1725 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1727 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1729 IPersistPropertyBag* lpPPBag;
1730 HRESULT hRet = E_FAIL;
1732 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1736 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1738 if (SUCCEEDED(hRet) && lpPPBag)
1740 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1741 IPersistPropertyBag_Release(lpPPBag);
1747 /*************************************************************************
1750 * Call IOleControlSite_TranslateAccelerator() on an object.
1753 * lpUnknown [I] Object supporting the IOleControlSite interface.
1754 * lpMsg [I] Key message to be processed.
1755 * dwModifiers [I] Flags containing the state of the modifier keys.
1759 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1761 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1763 IOleControlSite* lpCSite = NULL;
1764 HRESULT hRet = E_INVALIDARG;
1766 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1769 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1771 if (SUCCEEDED(hRet) && lpCSite)
1773 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1774 IOleControlSite_Release(lpCSite);
1781 /*************************************************************************
1784 * Call IOleControlSite_OnFocus() on an object.
1787 * lpUnknown [I] Object supporting the IOleControlSite interface.
1788 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1792 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1794 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
1796 IOleControlSite* lpCSite = NULL;
1797 HRESULT hRet = E_FAIL;
1799 TRACE("(%p,%s)\n", lpUnknown, fGotFocus ? "TRUE" : "FALSE");
1802 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1804 if (SUCCEEDED(hRet) && lpCSite)
1806 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1807 IOleControlSite_Release(lpCSite);
1813 /*************************************************************************
1816 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1817 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1819 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1820 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1821 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1822 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1823 HRESULT hRet = E_INVALIDARG;
1824 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1826 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1828 if (lpUnknown && lpArg4)
1830 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1831 (REFGUID)function_id, (void**)&lpUnkInner);
1833 if (SUCCEEDED(hRet) && lpUnkInner)
1835 /* FIXME: The type of service object requested is unknown, however
1836 * testing shows that its first method is called with 4 parameters.
1837 * Fake this by using IParseDisplayName_ParseDisplayName since the
1838 * signature and position in the vtable matches our unknown object type.
1840 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1841 lpArg1, lpArg2, lpArg3, lpArg4);
1842 IUnknown_Release(lpUnkInner);
1848 /*************************************************************************
1851 * Get a sub-menu from a menu item.
1854 * hMenu [I] Menu to get sub-menu from
1855 * uID [I] ID of menu item containing sub-menu
1858 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1860 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1864 TRACE("(%p,%u)\n", hMenu, uID);
1866 mi.cbSize = sizeof(mi);
1867 mi.fMask = MIIM_SUBMENU;
1869 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1875 /*************************************************************************
1878 * Get the color depth of the primary display.
1884 * The color depth of the primary display.
1886 DWORD WINAPI SHGetCurColorRes(void)
1894 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1899 /*************************************************************************
1902 * Wait for a message to arrive, with a timeout.
1905 * hand [I] Handle to query
1906 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1909 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1910 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1911 * message is available.
1913 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
1915 DWORD dwEndTicks = GetTickCount() + dwTimeout;
1918 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
1922 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
1924 if (dwTimeout != INFINITE)
1926 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
1927 return WAIT_TIMEOUT;
1934 /*************************************************************************
1937 * Determine if a shell folder can be expanded.
1940 * lpFolder [I] Parent folder containing the object to test.
1941 * pidl [I] Id of the object to test.
1944 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
1945 * Failure: E_INVALIDARG, if any argument is invalid.
1948 * If the object to be tested does not expose the IQueryInfo() interface it
1949 * will not be identified as an expandable folder.
1951 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
1953 HRESULT hRet = E_INVALIDARG;
1956 if (lpFolder && pidl)
1958 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
1959 NULL, (void**)&lpInfo);
1961 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
1966 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
1967 * currently used". Really? You wouldn't be holding out on me would you?
1969 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
1971 if (SUCCEEDED(hRet))
1973 /* 0x2 is an undocumented flag apparently indicating expandability */
1974 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
1977 IQueryInfo_Release(lpInfo);
1983 /*************************************************************************
1986 * Blank out a region of text by drawing the background only.
1989 * hDC [I] Device context to draw in
1990 * pRect [I] Area to draw in
1991 * cRef [I] Color to draw in
1996 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
1998 COLORREF cOldColor = SetBkColor(hDC, cRef);
1999 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2000 SetBkColor(hDC, cOldColor);
2004 /*************************************************************************
2007 * Return the value asociated with a key in a map.
2010 * lpKeys [I] A list of keys of length iLen
2011 * lpValues [I] A list of values associated with lpKeys, of length iLen
2012 * iLen [I] Length of both lpKeys and lpValues
2013 * iKey [I] The key value to look up in lpKeys
2016 * The value in lpValues associated with iKey, or -1 if iKey is not
2020 * - If two elements in the map share the same key, this function returns
2021 * the value closest to the start of the map
2022 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2024 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2026 if (lpKeys && lpValues)
2032 if (lpKeys[i] == iKey)
2033 return lpValues[i]; /* Found */
2037 return -1; /* Not found */
2041 /*************************************************************************
2044 * Copy an interface pointer
2047 * lppDest [O] Destination for copy
2048 * lpUnknown [I] Source for copy
2053 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2055 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2058 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2063 IUnknown_AddRef(lpUnknown);
2064 *lppDest = lpUnknown;
2068 /*************************************************************************
2072 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2073 REFGUID riidCmdGrp, ULONG cCmds,
2074 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2076 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2077 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2079 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2080 return DRAGDROP_E_NOTREGISTERED;
2083 /*************************************************************************
2087 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2088 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2091 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2092 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2093 return DRAGDROP_E_NOTREGISTERED;
2096 /*************************************************************************
2100 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2102 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2103 return DRAGDROP_E_NOTREGISTERED;
2106 /*************************************************************************
2109 * Determine if a window is not a child of another window.
2112 * hParent [I] Suspected parent window
2113 * hChild [I] Suspected child window
2116 * TRUE: If hChild is a child window of hParent
2117 * FALSE: If hChild is not a child window of hParent, or they are equal
2119 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2121 TRACE("(%p,%p)\n", hParent, hChild);
2123 if (!hParent || !hChild)
2125 else if(hParent == hChild)
2127 return !IsChild(hParent, hChild);
2130 /*************************************************************************
2131 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2136 DWORD num_items; /* Number of elements inserted */
2137 void *mem; /* Ptr to array */
2138 DWORD blocks_alloced; /* Number of elements allocated */
2139 BYTE inc; /* Number of elements to grow by when we need to expand */
2140 BYTE block_size; /* Size in bytes of an element */
2141 BYTE flags; /* Flags */
2144 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2146 /*************************************************************************
2149 * Initialize an FDSA arrary.
2151 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2154 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2160 memset(mem, 0, block_size * init_blocks);
2162 info->num_items = 0;
2165 info->blocks_alloced = init_blocks;
2166 info->block_size = block_size;
2172 /*************************************************************************
2175 * Destroy an FDSA array
2177 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2179 TRACE("(%p)\n", info);
2181 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2183 HeapFree(GetProcessHeap(), 0, info->mem);
2190 /*************************************************************************
2193 * Insert element into an FDSA array
2195 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
2197 TRACE("(%p 0x%08x %p)\n", info, where, block);
2198 if(where > info->num_items)
2199 where = info->num_items;
2201 if(info->num_items >= info->blocks_alloced)
2203 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2204 if(info->flags & 0x1)
2205 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2208 void *old_mem = info->mem;
2209 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2210 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2212 info->blocks_alloced += info->inc;
2216 if(where < info->num_items)
2218 memmove((char*)info->mem + (where + 1) * info->block_size,
2219 (char*)info->mem + where * info->block_size,
2220 (info->num_items - where) * info->block_size);
2222 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2228 /*************************************************************************
2231 * Delete an element from an FDSA array.
2233 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2235 TRACE("(%p 0x%08x)\n", info, where);
2237 if(where >= info->num_items)
2240 if(where < info->num_items - 1)
2242 memmove((char*)info->mem + where * info->block_size,
2243 (char*)info->mem + (where + 1) * info->block_size,
2244 (info->num_items - where - 1) * info->block_size);
2246 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2247 0, info->block_size);
2258 /*************************************************************************
2261 * Call IUnknown_QueryInterface() on a table of objects.
2265 * Failure: E_POINTER or E_NOINTERFACE.
2267 HRESULT WINAPI QISearch(
2268 LPVOID w, /* [in] Table of interfaces */
2269 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2270 REFIID riid, /* [in] REFIID to get interface for */
2271 LPVOID *ppv) /* [out] Destination for interface pointer */
2275 IFACE_INDEX_TBL *xmove;
2277 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2280 while (xmove->refid) {
2281 TRACE("trying (indx %d) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2282 if (IsEqualIID(riid, xmove->refid)) {
2283 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2284 TRACE("matched, returning (%p)\n", a_vtbl);
2285 *ppv = (LPVOID)a_vtbl;
2286 IUnknown_AddRef(a_vtbl);
2292 if (IsEqualIID(riid, &IID_IUnknown)) {
2293 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2294 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2295 *ppv = (LPVOID)a_vtbl;
2296 IUnknown_AddRef(a_vtbl);
2300 ret = E_NOINTERFACE;
2304 TRACE("-- 0x%08x\n", ret);
2308 /*************************************************************************
2311 * Remove the "PropDlgFont" property from a window.
2314 * hWnd [I] Window to remove the property from
2317 * A handle to the removed property, or NULL if it did not exist.
2319 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2323 TRACE("(%p)\n", hWnd);
2325 hProp = GetPropA(hWnd, "PropDlgFont");
2329 DeleteObject(hProp);
2330 hProp = RemovePropA(hWnd, "PropDlgFont");
2335 /*************************************************************************
2338 * Load the in-process server of a given GUID.
2341 * refiid [I] GUID of the server to load.
2344 * Success: A handle to the loaded server dll.
2345 * Failure: A NULL handle.
2347 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2351 CHAR value[MAX_PATH], string[MAX_PATH];
2353 strcpy(string, "CLSID\\");
2354 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2355 strcat(string, "\\InProcServer32");
2358 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2359 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2360 RegCloseKey(newkey);
2361 return LoadLibraryExA(value, 0, 0);
2364 /*************************************************************************
2367 * Unicode version of SHLWAPI_183.
2369 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2373 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2375 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2377 return RegisterClassW(lpWndClass);
2380 /*************************************************************************
2383 * Unregister a list of classes.
2386 * hInst [I] Application instance that registered the classes
2387 * lppClasses [I] List of class names
2388 * iCount [I] Number of names in lppClasses
2393 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2397 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2401 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2402 UnregisterClassA(*lppClasses, hInst);
2408 /*************************************************************************
2411 * Unicode version of SHUnregisterClassesA.
2413 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2417 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2421 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2422 UnregisterClassW(*lppClasses, hInst);
2428 /*************************************************************************
2431 * Call The correct (Ascii/Unicode) default window procedure for a window.
2434 * hWnd [I] Window to call the default procedure for
2435 * uMessage [I] Message ID
2436 * wParam [I] WPARAM of message
2437 * lParam [I] LPARAM of message
2440 * The result of calling DefWindowProcA() or DefWindowProcW().
2442 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2444 if (IsWindowUnicode(hWnd))
2445 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2446 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2449 /*************************************************************************
2452 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2454 HRESULT hRet = E_INVALIDARG;
2455 LPOBJECTWITHSITE lpSite = NULL;
2457 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2459 if (lpUnknown && iid && lppSite)
2461 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2463 if (SUCCEEDED(hRet) && lpSite)
2465 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2466 IObjectWithSite_Release(lpSite);
2472 /*************************************************************************
2475 * Create a worker window using CreateWindowExA().
2478 * wndProc [I] Window procedure
2479 * hWndParent [I] Parent window
2480 * dwExStyle [I] Extra style flags
2481 * dwStyle [I] Style flags
2482 * hMenu [I] Window menu
2486 * Success: The window handle of the newly created window.
2489 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2490 DWORD dwStyle, HMENU hMenu, LONG z)
2492 static const char szClass[] = "WorkerA";
2496 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2497 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2499 /* Create Window class */
2501 wc.lpfnWndProc = DefWindowProcA;
2504 wc.hInstance = shlwapi_hInstance;
2506 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2507 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2508 wc.lpszMenuName = NULL;
2509 wc.lpszClassName = szClass;
2511 SHRegisterClassA(&wc); /* Register class */
2513 /* FIXME: Set extra bits in dwExStyle */
2515 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2516 hWndParent, hMenu, shlwapi_hInstance, 0);
2519 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2522 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2527 typedef struct tagPOLICYDATA
2529 DWORD policy; /* flags value passed to SHRestricted */
2530 LPCWSTR appstr; /* application str such as "Explorer" */
2531 LPCWSTR keystr; /* name of the actual registry key / policy */
2532 } POLICYDATA, *LPPOLICYDATA;
2534 #define SHELL_NO_POLICY 0xffffffff
2536 /* default shell policy registry key */
2537 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2538 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2539 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2540 '\\','P','o','l','i','c','i','e','s',0};
2542 /*************************************************************************
2545 * Retrieve a policy value from the registry.
2548 * lpSubKey [I] registry key name
2549 * lpSubName [I] subname of registry key
2550 * lpValue [I] value name of registry value
2553 * the value associated with the registry key or 0 if not found
2555 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2557 DWORD retval, datsize = sizeof(retval);
2561 lpSubKey = strRegistryPolicyW;
2563 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2564 if (retval != ERROR_SUCCESS)
2565 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2566 if (retval != ERROR_SUCCESS)
2569 SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);
2574 /*************************************************************************
2577 * Helper function to retrieve the possibly cached value for a specific policy
2580 * policy [I] The policy to look for
2581 * initial [I] Main registry key to open, if NULL use default
2582 * polTable [I] Table of known policies, 0 terminated
2583 * polArr [I] Cache array of policy values
2586 * The retrieved policy value or 0 if not successful
2589 * This function is used by the native SHRestricted function to search for the
2590 * policy and cache it once retrieved. The current Wine implementation uses a
2591 * different POLICYDATA structure and implements a similar algorithme adapted to
2594 DWORD WINAPI SHRestrictionLookup(
2597 LPPOLICYDATA polTable,
2600 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2602 if (!polTable || !polArr)
2605 for (;polTable->policy; polTable++, polArr++)
2607 if (policy == polTable->policy)
2609 /* we have a known policy */
2611 /* check if this policy has been cached */
2612 if (*polArr == SHELL_NO_POLICY)
2613 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2617 /* we don't know this policy, return 0 */
2618 TRACE("unknown policy: (%08x)\n", policy);
2622 /*************************************************************************
2625 * Get an interface from an object.
2628 * Success: S_OK. ppv contains the requested interface.
2629 * Failure: An HRESULT error code.
2632 * This QueryInterface asks the inner object for an interface. In case
2633 * of aggregation this request would be forwarded by the inner to the
2634 * outer object. This function asks the inner object directly for the
2635 * interface circumventing the forwarding to the outer object.
2637 HRESULT WINAPI SHWeakQueryInterface(
2638 IUnknown * pUnk, /* [in] Outer object */
2639 IUnknown * pInner, /* [in] Inner object */
2640 IID * riid, /* [in] Interface GUID to query for */
2641 LPVOID* ppv) /* [out] Destination for queried interface */
2643 HRESULT hret = E_NOINTERFACE;
2644 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2647 if(pUnk && pInner) {
2648 hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
2649 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2651 TRACE("-- 0x%08x\n", hret);
2655 /*************************************************************************
2658 * Move a reference from one interface to another.
2661 * lpDest [O] Destination to receive the reference
2662 * lppUnknown [O] Source to give up the reference to lpDest
2667 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2669 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2674 IUnknown_AddRef(lpDest);
2675 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2679 /*************************************************************************
2682 * Convert an ASCII string of a CLSID into a CLSID.
2685 * idstr [I] String representing a CLSID in registry format
2686 * id [O] Destination for the converted CLSID
2689 * Success: TRUE. id contains the converted CLSID.
2692 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2695 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2696 return SUCCEEDED(CLSIDFromString(wClsid, id));
2699 /*************************************************************************
2702 * Unicode version of GUIDFromStringA.
2704 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2706 return SUCCEEDED(CLSIDFromString((LPOLESTR)idstr, id));
2709 /*************************************************************************
2712 * Determine if the browser is integrated into the shell, and set a registry
2719 * 1, If the browser is not integrated.
2720 * 2, If the browser is integrated.
2723 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2724 * either set to TRUE, or removed depending on whether the browser is deemed
2727 DWORD WINAPI WhichPlatform(void)
2729 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2730 static DWORD dwState = 0;
2732 DWORD dwRet, dwData, dwSize;
2738 /* If shell32 exports DllGetVersion(), the browser is integrated */
2740 hshell32 = LoadLibraryA("shell32.dll");
2743 FARPROC pDllGetVersion;
2744 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2745 dwState = pDllGetVersion ? 2 : 1;
2746 FreeLibrary(hshell32);
2749 /* Set or delete the key accordingly */
2750 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2751 "Software\\Microsoft\\Internet Explorer", 0,
2752 KEY_ALL_ACCESS, &hKey);
2755 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2756 (LPBYTE)&dwData, &dwSize);
2758 if (!dwRet && dwState == 1)
2760 /* Value exists but browser is not integrated */
2761 RegDeleteValueA(hKey, szIntegratedBrowser);
2763 else if (dwRet && dwState == 2)
2765 /* Browser is integrated but value does not exist */
2767 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2768 (LPBYTE)&dwData, sizeof(dwData));
2775 /*************************************************************************
2778 * Unicode version of SHCreateWorkerWindowA.
2780 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2781 DWORD dwStyle, HMENU hMenu, LONG z)
2783 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2787 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2788 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2790 /* If our OS is natively ASCII, use the ASCII version */
2791 if (!(GetVersion() & 0x80000000)) /* NT */
2792 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2794 /* Create Window class */
2796 wc.lpfnWndProc = DefWindowProcW;
2799 wc.hInstance = shlwapi_hInstance;
2801 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2802 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2803 wc.lpszMenuName = NULL;
2804 wc.lpszClassName = szClass;
2806 SHRegisterClassW(&wc); /* Register class */
2808 /* FIXME: Set extra bits in dwExStyle */
2810 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2811 hWndParent, hMenu, shlwapi_hInstance, 0);
2814 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2817 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2822 /*************************************************************************
2825 * Get and show a context menu from a shell folder.
2828 * hWnd [I] Window displaying the shell folder
2829 * lpFolder [I] IShellFolder interface
2830 * lpApidl [I] Id for the particular folder desired
2834 * Failure: An HRESULT error code indicating the error.
2836 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2838 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2841 /*************************************************************************
2844 * _SHPackDispParamsV
2846 HRESULT WINAPI SHPackDispParamsV(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2848 FIXME("%p %p %p %p\n",w,x,y,z);
2852 /*************************************************************************
2855 * This function seems to be a forward to SHPackDispParamsV (whatever THAT
2856 * function does...).
2858 HRESULT WINAPI SHPackDispParams(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2860 FIXME("%p %p %p %p\n", w, x, y, z);
2864 /*************************************************************************
2865 * SHLWAPI_InvokeByIID
2867 * This helper function calls IDispatch::Invoke for each sink
2868 * which implements given iid or IDispatch.
2871 static HRESULT SHLWAPI_InvokeByIID(
2872 IConnectionPoint* iCP,
2875 DISPPARAMS* dispParams)
2877 IEnumConnections *enumerator;
2880 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
2884 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
2886 IDispatch *dispIface;
2887 if (SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface)) ||
2888 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
2890 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, dispParams, NULL, NULL, NULL);
2891 IDispatch_Release(dispIface);
2895 IEnumConnections_Release(enumerator);
2900 /*************************************************************************
2903 * IConnectionPoint_SimpleInvoke
2905 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
2906 IConnectionPoint* iCP,
2908 DISPPARAMS* dispParams)
2913 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
2915 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
2916 if (SUCCEEDED(result))
2917 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
2922 /*************************************************************************
2925 * Notify an IConnectionPoint object of changes.
2928 * lpCP [I] Object to notify
2933 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
2934 * IConnectionPoint interface.
2936 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
2938 IEnumConnections *lpEnum;
2939 HRESULT hRet = E_NOINTERFACE;
2941 TRACE("(%p,0x%8X)\n", lpCP, dispID);
2943 /* Get an enumerator for the connections */
2945 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
2947 if (SUCCEEDED(hRet))
2949 IPropertyNotifySink *lpSink;
2950 CONNECTDATA connData;
2953 /* Call OnChanged() for every notify sink in the connection point */
2954 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
2956 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
2959 IPropertyNotifySink_OnChanged(lpSink, dispID);
2960 IPropertyNotifySink_Release(lpSink);
2962 IUnknown_Release(connData.pUnk);
2965 IEnumConnections_Release(lpEnum);
2970 /*************************************************************************
2973 * IUnknown_CPContainerInvokeParam
2975 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
2976 IUnknown *container,
2983 IConnectionPoint *iCP;
2984 IConnectionPointContainer *iCPC;
2987 return E_NOINTERFACE;
2989 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
2990 if (SUCCEEDED(result))
2992 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
2993 IConnectionPointContainer_Release(iCPC);
2996 if (SUCCEEDED(result))
2999 VARIANTARG *curvar = buffer+cParams-1;
3000 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3003 va_start(valist, cParams);
3004 for(cnt=cParams;cnt>0;cnt--,curvar--) /* backwards for some reason */
3006 enum VARENUM vt = va_arg(valist, enum VARENUM);
3007 memset(curvar, 0, sizeof(*curvar));
3011 V_BYREF(curvar) = va_arg(valist, LPVOID);
3017 V_BSTR(curvar) = va_arg(valist, BSTR);
3021 V_DISPATCH(curvar) = va_arg(valist, IDispatch*);
3025 V_BOOL(curvar) = va_arg(valist, int);
3029 V_UNKNOWN(curvar) = va_arg(valist, IUnknown*);
3033 V_VT(curvar) = VT_I4;
3034 V_I4(curvar) = va_arg(valist, LONG);
3040 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3041 IConnectionPoint_Release(iCP);
3047 /*************************************************************************
3050 * Notify an IConnectionPointContainer object of changes.
3053 * lpUnknown [I] Object to notify
3058 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3059 * IConnectionPointContainer interface.
3061 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3063 IConnectionPointContainer* lpCPC = NULL;
3064 HRESULT hRet = E_NOINTERFACE;
3066 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3069 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3071 if (SUCCEEDED(hRet))
3073 IConnectionPoint* lpCP;
3075 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3076 IConnectionPointContainer_Release(lpCPC);
3078 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3079 IConnectionPoint_Release(lpCP);
3084 /*************************************************************************
3089 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3091 return PlaySoundW(pszSound, hmod, fdwSound);
3094 /*************************************************************************
3097 BOOL WINAPI SHGetIniStringW(LPCWSTR str1, LPCWSTR str2, LPWSTR pStr, DWORD some_len, LPCWSTR lpStr2)
3099 FIXME("(%s,%s,%p,%08x,%s): stub!\n", debugstr_w(str1), debugstr_w(str2),
3100 pStr, some_len, debugstr_w(lpStr2));
3104 /*************************************************************************
3107 * Called by ICQ2000b install via SHDOCVW:
3108 * str1: "InternetShortcut"
3109 * x: some unknown pointer
3110 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
3111 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
3113 * In short: this one maybe creates a desktop link :-)
3115 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
3117 FIXME("(%s, %p, %s, %s), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
3121 /*************************************************************************
3124 * See SHGetFileInfoW.
3126 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3127 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3129 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3132 /*************************************************************************
3135 * See DragQueryFileW.
3137 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3139 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3142 /*************************************************************************
3145 * See SHBrowseForFolderW.
3147 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3149 return SHBrowseForFolderW(lpBi);
3152 /*************************************************************************
3155 * See SHGetPathFromIDListW.
3157 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3159 return SHGetPathFromIDListW(pidl, pszPath);
3162 /*************************************************************************
3165 * See ShellExecuteExW.
3167 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3169 return ShellExecuteExW(lpExecInfo);
3172 /*************************************************************************
3175 * See SHFileOperationW.
3177 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3179 return SHFileOperationW(lpFileOp);
3182 /*************************************************************************
3186 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
3188 return InterlockedCompareExchangePointer( dest, xchg, compare );
3191 /*************************************************************************
3194 * See GetFileVersionInfoSizeW.
3196 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
3198 return GetFileVersionInfoSizeW( filename, handle );
3201 /*************************************************************************
3204 * See GetFileVersionInfoW.
3206 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
3207 DWORD datasize, LPVOID data )
3209 return GetFileVersionInfoW( filename, handle, datasize, data );
3212 /*************************************************************************
3215 * See VerQueryValueW.
3217 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
3218 LPVOID *lplpBuffer, UINT *puLen )
3220 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3223 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3224 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3225 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3227 /*************************************************************************
3230 * Change the modality of a shell object.
3233 * lpUnknown [I] Object to make modeless
3234 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3237 * Success: S_OK. The modality lpUnknown is changed.
3238 * Failure: An HRESULT error code indicating the error.
3241 * lpUnknown must support the IOleInPlaceFrame interface, the
3242 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3243 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3244 * or this call will fail.
3246 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3251 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3256 if (IsIface(IOleInPlaceActiveObject))
3257 EnableModeless(IOleInPlaceActiveObject);
3258 else if (IsIface(IOleInPlaceFrame))
3259 EnableModeless(IOleInPlaceFrame);
3260 else if (IsIface(IShellBrowser))
3261 EnableModeless(IShellBrowser);
3263 /* FIXME: Wine has no headers for these objects yet */
3264 else if (IsIface(IInternetSecurityMgrSite))
3265 EnableModeless(IInternetSecurityMgrSite);
3266 else if (IsIface(IDocHostUIHandler))
3267 EnableModeless(IDocHostUIHandler);
3272 IUnknown_Release(lpObj);
3276 /*************************************************************************
3279 * See SHGetNewLinkInfoW.
3281 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3282 BOOL *pfMustCopy, UINT uFlags)
3284 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3287 /*************************************************************************
3290 * See SHDefExtractIconW.
3292 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3293 HICON* phiconSmall, UINT nIconSize)
3295 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3298 /*************************************************************************
3301 * Get and show a context menu from a shell folder.
3304 * hWnd [I] Window displaying the shell folder
3305 * lpFolder [I] IShellFolder interface
3306 * lpApidl [I] Id for the particular folder desired
3307 * bInvokeDefault [I] Whether to invoke the default menu item
3310 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3312 * Failure: An HRESULT error code indicating the error.
3314 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3316 IContextMenu *iContext;
3317 HRESULT hRet = E_FAIL;
3319 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3324 /* Get the context menu from the shell folder */
3325 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3326 &IID_IContextMenu, 0, (void**)&iContext);
3327 if (SUCCEEDED(hRet))
3330 if ((hMenu = CreatePopupMenu()))
3333 DWORD dwDefaultId = 0;
3335 /* Add the context menu entries to the popup */
3336 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3337 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3339 if (SUCCEEDED(hQuery))
3341 if (bInvokeDefault &&
3342 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3344 CMINVOKECOMMANDINFO cmIci;
3345 /* Invoke the default item */
3346 memset(&cmIci,0,sizeof(cmIci));
3347 cmIci.cbSize = sizeof(cmIci);
3348 cmIci.fMask = CMIC_MASK_ASYNCOK;
3350 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3351 cmIci.nShow = SW_SCROLLCHILDREN;
3353 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3358 IContextMenu_Release(iContext);
3363 /*************************************************************************
3368 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3371 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3374 /*************************************************************************
3377 * Load a library from the directory of a particular process.
3380 * new_mod [I] Library name
3381 * inst_hwnd [I] Module whose directory is to be used
3382 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3385 * Success: A handle to the loaded module
3386 * Failure: A NULL handle.
3388 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3390 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3392 * FIXME: Native shows calls to:
3393 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3395 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3396 * RegQueryValueExA for "LPKInstalled"
3398 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3399 * RegQueryValueExA for "ResourceLocale"
3401 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3402 * RegQueryValueExA for "Locale"
3404 * and then tests the Locale ("en" for me).
3406 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3408 CHAR mod_path[2*MAX_PATH];
3412 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3413 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3414 if (!len || len >= sizeof(mod_path)) return NULL;
3416 ptr = strrchr(mod_path, '\\');
3418 strcpy(ptr+1, new_mod);
3419 TRACE("loading %s\n", debugstr_a(mod_path));
3420 return LoadLibraryA(mod_path);
3425 /*************************************************************************
3428 * Unicode version of MLLoadLibraryA.
3430 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3432 WCHAR mod_path[2*MAX_PATH];
3436 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3437 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3438 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3440 ptr = strrchrW(mod_path, '\\');
3442 strcpyW(ptr+1, new_mod);
3443 TRACE("loading %s\n", debugstr_w(mod_path));
3444 return LoadLibraryW(mod_path);
3449 /*************************************************************************
3450 * ColorAdjustLuma [SHLWAPI.@]
3452 * Adjust the luminosity of a color
3455 * cRGB [I] RGB value to convert
3456 * dwLuma [I] Luma adjustment
3457 * bUnknown [I] Unknown
3460 * The adjusted RGB color.
3462 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3464 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3470 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3472 FIXME("Ignoring luma adjustment\n");
3474 /* FIXME: The ajdustment is not linear */
3476 cRGB = ColorHLSToRGB(wH, wL, wS);
3481 /*************************************************************************
3484 * See GetSaveFileNameW.
3486 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3488 return GetSaveFileNameW(ofn);
3491 /*************************************************************************
3494 * See WNetRestoreConnectionW.
3496 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3498 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3501 /*************************************************************************
3504 * See WNetGetLastErrorW.
3506 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3507 LPWSTR lpNameBuf, DWORD nNameBufSize)
3509 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3512 /*************************************************************************
3515 * See PageSetupDlgW.
3517 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3519 return PageSetupDlgW(pagedlg);
3522 /*************************************************************************
3527 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3529 return PrintDlgW(printdlg);
3532 /*************************************************************************
3535 * See GetOpenFileNameW.
3537 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3539 return GetOpenFileNameW(ofn);
3542 /*************************************************************************
3545 HRESULT WINAPI IUnknown_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3550 hr = IShellFolder_QueryInterface(lpFolder, &IID_IPersist, (LPVOID)&persist);
3554 hr = IPersist_GetClassID(persist, &clsid);
3557 if(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder))
3558 hr = IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3562 IPersist_Release(persist);
3567 /* INTERNAL: Map from HLS color space to RGB */
3568 static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3570 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3574 else if (wHue > 120)
3579 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3582 /* Convert to RGB and scale into RGB range (0..255) */
3583 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3585 /*************************************************************************
3586 * ColorHLSToRGB [SHLWAPI.@]
3588 * Convert from hls color space into an rgb COLORREF.
3591 * wHue [I] Hue amount
3592 * wLuminosity [I] Luminosity amount
3593 * wSaturation [I] Saturation amount
3596 * A COLORREF representing the converted color.
3599 * Input hls values are constrained to the range (0..240).
3601 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3607 WORD wGreen, wBlue, wMid1, wMid2;
3609 if (wLuminosity > 120)
3610 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3612 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3614 wMid1 = wLuminosity * 2 - wMid2;
3616 wRed = GET_RGB(wHue + 80);
3617 wGreen = GET_RGB(wHue);
3618 wBlue = GET_RGB(wHue - 80);
3620 return RGB(wRed, wGreen, wBlue);
3623 wRed = wLuminosity * 255 / 240;
3624 return RGB(wRed, wRed, wRed);
3627 /*************************************************************************
3630 * Get the current docking status of the system.
3633 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3636 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3639 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3641 HW_PROFILE_INFOA hwInfo;
3643 TRACE("(0x%08x)\n", dwFlags);
3645 GetCurrentHwProfileA(&hwInfo);
3646 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3648 case DOCKINFO_DOCKED:
3649 case DOCKINFO_UNDOCKED:
3650 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3656 /*************************************************************************
3659 * Function seems to do FreeLibrary plus other things.
3661 * FIXME native shows the following calls:
3662 * RtlEnterCriticalSection
3664 * GetProcAddress(Comctl32??, 150L)
3666 * RtlLeaveCriticalSection
3667 * followed by the FreeLibrary.
3668 * The above code may be related to .377 above.
3670 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3672 FIXME("(%p) semi-stub\n", hModule);
3673 return FreeLibrary(hModule);
3676 /*************************************************************************
3679 BOOL WINAPI SHFlushSFCacheWrap(void) {
3684 /*************************************************************************
3687 BOOL WINAPI DeleteMenuWrap(HMENU hmenu, UINT pos, UINT flags)
3689 /* FIXME: This should do more than simply call DeleteMenu */
3690 FIXME("%p %08x %08x): semi-stub\n", hmenu, pos, flags);
3691 return DeleteMenu(hmenu, pos, flags);
3694 /*************************************************************************
3696 * FIXME I have no idea what this function does or what its arguments are.
3698 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3700 FIXME("(%p) stub\n", hInst);
3705 /*************************************************************************
3708 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3710 FIXME("(%p,%p) stub\n", hInst, hHeap);
3711 return E_FAIL; /* This is what is used if shlwapi not loaded */
3714 /*************************************************************************
3717 DWORD WINAPI MLClearMLHInstance(DWORD x)
3719 FIXME("(0x%08x)stub\n", x);
3723 /*************************************************************************
3726 * Convert an Unicode string CLSID into a CLSID.
3729 * idstr [I] string containing a CLSID in text form
3730 * id [O] CLSID extracted from the string
3733 * S_OK on success or E_INVALIDARG on failure
3735 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3737 return CLSIDFromString((LPOLESTR)idstr, id);
3740 /*************************************************************************
3743 * Determine if the OS supports a given feature.
3746 * dwFeature [I] Feature requested (undocumented)
3749 * TRUE If the feature is available.
3750 * FALSE If the feature is not available.
3752 BOOL WINAPI IsOS(DWORD feature)
3754 OSVERSIONINFOA osvi;
3755 DWORD platform, majorv, minorv;
3757 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3758 if(!GetVersionExA(&osvi)) {
3759 ERR("GetVersionEx failed\n");
3763 majorv = osvi.dwMajorVersion;
3764 minorv = osvi.dwMinorVersion;
3765 platform = osvi.dwPlatformId;
3767 #define ISOS_RETURN(x) \
3768 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3772 case OS_WIN32SORGREATER:
3773 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3774 || platform == VER_PLATFORM_WIN32_WINDOWS)
3776 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3777 case OS_WIN95ORGREATER:
3778 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3779 case OS_NT4ORGREATER:
3780 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3781 case OS_WIN2000ORGREATER_ALT:
3782 case OS_WIN2000ORGREATER:
3783 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3784 case OS_WIN98ORGREATER:
3785 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3787 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3789 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3790 case OS_WIN2000SERVER:
3791 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3792 case OS_WIN2000ADVSERVER:
3793 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3794 case OS_WIN2000DATACENTER:
3795 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3796 case OS_WIN2000TERMINAL:
3797 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3799 FIXME("(OS_EMBEDDED) What should we return here?\n");
3801 case OS_TERMINALCLIENT:
3802 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3804 case OS_TERMINALREMOTEADMIN:
3805 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3808 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3809 case OS_MEORGREATER:
3810 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3811 case OS_XPORGREATER:
3812 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3814 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3815 case OS_PROFESSIONAL:
3816 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3818 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3820 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3822 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3823 case OS_TERMINALSERVER:
3824 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3825 case OS_PERSONALTERMINALSERVER:
3826 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3827 case OS_FASTUSERSWITCHING:
3828 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3830 case OS_WELCOMELOGONUI:
3831 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3833 case OS_DOMAINMEMBER:
3834 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3837 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3839 FIXME("(OS_WOW6432) Should we check this?\n");
3842 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3843 case OS_SMALLBUSINESSSERVER:
3844 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3846 FIXME("(OS_TABLEPC) What should we return here?\n");
3848 case OS_SERVERADMINUI:
3849 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3851 case OS_MEDIACENTER:
3852 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3855 FIXME("(OS_APPLIANCE) What should we return here?\n");
3861 WARN("(0x%x) unknown parameter\n",feature);
3866 /*************************************************************************
3869 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
3871 DWORD type, sz = size;
3873 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
3876 return SHLoadIndirectString(buf, buf, size, NULL);
3879 /*************************************************************************
3882 * Call IInputObject_TranslateAcceleratorIO() on an object.
3885 * lpUnknown [I] Object supporting the IInputObject interface.
3886 * lpMsg [I] Key message to be processed.
3890 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3892 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
3894 IInputObject* lpInput = NULL;
3895 HRESULT hRet = E_INVALIDARG;
3897 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
3900 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3902 if (SUCCEEDED(hRet) && lpInput)
3904 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
3905 IInputObject_Release(lpInput);
3911 /*************************************************************************
3914 * Call IInputObject_HasFocusIO() on an object.
3917 * lpUnknown [I] Object supporting the IInputObject interface.
3920 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
3921 * or S_FALSE otherwise.
3922 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3924 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
3926 IInputObject* lpInput = NULL;
3927 HRESULT hRet = E_INVALIDARG;
3929 TRACE("(%p)\n", lpUnknown);
3932 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3934 if (SUCCEEDED(hRet) && lpInput)
3936 hRet = IInputObject_HasFocusIO(lpInput);
3937 IInputObject_Release(lpInput);
3943 /*************************************************************************
3944 * ColorRGBToHLS [SHLWAPI.@]
3946 * Convert an rgb COLORREF into the hls color space.
3949 * cRGB [I] Source rgb value
3950 * pwHue [O] Destination for converted hue
3951 * pwLuminance [O] Destination for converted luminance
3952 * pwSaturation [O] Destination for converted saturation
3955 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
3959 * Output HLS values are constrained to the range (0..240).
3960 * For Achromatic conversions, Hue is set to 160.
3962 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
3963 LPWORD pwLuminance, LPWORD pwSaturation)
3965 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
3967 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
3969 wR = GetRValue(cRGB);
3970 wG = GetGValue(cRGB);
3971 wB = GetBValue(cRGB);
3973 wMax = max(wR, max(wG, wB));
3974 wMin = min(wR, min(wG, wB));
3977 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
3981 /* Achromatic case */
3983 /* Hue is now unrepresentable, but this is what native returns... */
3988 /* Chromatic case */
3989 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
3992 if (wLuminosity <= 120)
3993 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
3995 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
3998 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
3999 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4000 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4003 wHue = wBNorm - wGNorm;
4004 else if (wG == wMax)
4005 wHue = 80 + wRNorm - wBNorm;
4007 wHue = 160 + wGNorm - wRNorm;
4010 else if (wHue > 240)
4016 *pwLuminance = wLuminosity;
4018 *pwSaturation = wSaturation;
4021 /*************************************************************************
4022 * SHCreateShellPalette [SHLWAPI.@]
4024 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4027 return CreateHalftonePalette(hdc);
4030 /*************************************************************************
4031 * SHGetInverseCMAP (SHLWAPI.@)
4033 * Get an inverse color map table.
4036 * lpCmap [O] Destination for color map
4037 * dwSize [I] Size of memory pointed to by lpCmap
4041 * Failure: E_POINTER, If lpCmap is invalid.
4042 * E_INVALIDARG, If dwFlags is invalid
4043 * E_OUTOFMEMORY, If there is no memory available
4046 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4047 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4049 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4050 * this DLL's internal CMap.
4052 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4055 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4056 *dest = (DWORD)0xabba1249;
4059 FIXME("(%p, %#x) stub\n", dest, dwSize);
4063 /*************************************************************************
4064 * SHIsLowMemoryMachine [SHLWAPI.@]
4066 * Determine if the current computer has low memory.
4072 * TRUE if the users machine has 16 Megabytes of memory or less,
4075 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4077 FIXME("(0x%08x) stub\n", x);
4081 /*************************************************************************
4082 * GetMenuPosFromID [SHLWAPI.@]
4084 * Return the position of a menu item from its Id.
4087 * hMenu [I] Menu containing the item
4088 * wID [I] Id of the menu item
4091 * Success: The index of the menu item in hMenu.
4092 * Failure: -1, If the item is not found.
4094 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4097 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4099 while (nIter < nCount)
4101 mi.cbSize = sizeof(mi);
4103 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4110 /*************************************************************************
4113 * Same as SHLWAPI.GetMenuPosFromID
4115 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4117 return GetMenuPosFromID(hMenu, uID);
4121 /*************************************************************************
4124 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4135 /*************************************************************************
4138 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4140 FIXME("(0x%08x) stub\n", dwUnknown);
4145 /*************************************************************************
4148 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4149 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4151 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4154 /*************************************************************************
4155 * SHSkipJunction [SHLWAPI.@]
4157 * Determine if a bind context can be bound to an object
4160 * pbc [I] Bind context to check
4161 * pclsid [I] CLSID of object to be bound to
4164 * TRUE: If it is safe to bind
4165 * FALSE: If pbc is invalid or binding would not be safe
4168 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4170 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4171 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4178 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)szSkipBinding, &lpUnk)))
4182 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4183 IsEqualGUID(pclsid, &clsid))
4186 IUnknown_Release(lpUnk);
4192 /***********************************************************************
4193 * SHGetShellKey (SHLWAPI.@)
4195 DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
4197 FIXME("(%x, %x, %x): stub\n", a, b, c);
4201 /***********************************************************************
4202 * SHQueueUserWorkItem (SHLWAPI.@)
4204 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback,
4205 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4206 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4208 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4209 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4211 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4212 FIXME("Unsupported arguments\n");
4214 return QueueUserWorkItem(pfnCallback, pContext, 0);
4217 /***********************************************************************
4218 * SHSetTimerQueueTimer (SHLWAPI.263)
4220 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
4221 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4222 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4226 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4227 if (dwFlags & TPS_LONGEXECTIME) {
4228 dwFlags &= ~TPS_LONGEXECTIME;
4229 dwFlags |= WT_EXECUTELONGFUNCTION;
4231 if (dwFlags & TPS_EXECUTEIO) {
4232 dwFlags &= ~TPS_EXECUTEIO;
4233 dwFlags |= WT_EXECUTEINIOTHREAD;
4236 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4237 dwDueTime, dwPeriod, dwFlags))
4243 /***********************************************************************
4244 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4246 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4248 IInputObjectSite *pIOS = NULL;
4249 HRESULT hRet = E_INVALIDARG;
4251 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4255 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4257 if (SUCCEEDED(hRet) && pIOS)
4259 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4260 IInputObjectSite_Release(pIOS);
4266 /***********************************************************************
4267 * SHGetValueW (SHLWAPI.@)
4269 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4271 FIXME("(%x, %s, %s, %x, %x, %x): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4275 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4277 /***********************************************************************
4278 * GetUIVersion (SHLWAPI.452)
4280 DWORD WINAPI GetUIVersion(void)
4282 static DWORD version;
4286 DllGetVersion_func pDllGetVersion;
4287 HMODULE dll = LoadLibraryA("shell32.dll");
4290 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4294 dvi.cbSize = sizeof(DLLVERSIONINFO);
4295 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4298 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4303 /***********************************************************************
4304 * ShellMessageBoxWrapW [SHLWAPI.388]
4306 * See shell32.ShellMessageBoxW
4309 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4310 * because we can't forward to it in the .spec file since it's exported by
4311 * ordinal. If you change the implementation here please update the code in
4314 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
4315 LPCWSTR lpCaption, UINT uType, ...)
4317 WCHAR szText[100], szTitle[100];
4318 LPCWSTR pszText = szText, pszTitle = szTitle;
4323 va_start(args, uType);
4325 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
4327 if (IS_INTRESOURCE(lpCaption))
4328 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
4330 pszTitle = lpCaption;
4332 if (IS_INTRESOURCE(lpText))
4333 LoadStringW(hInstance, LOWORD(lpText), szText, sizeof(szText)/sizeof(szText[0]));
4337 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4338 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4342 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4343 LocalFree((HLOCAL)pszTemp);
4347 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *unk, REFIID service, REFIID clsid,
4348 DWORD x1, DWORD x2, DWORD x3, void **ppvOut)
4350 FIXME("%p %s %s %08x %08x %08x %p\n", unk,
4351 debugstr_guid(service), debugstr_guid(clsid), x1, x2, x3, ppvOut);
4355 HRESULT WINAPI IUnknown_ProfferService(IUnknown *unk, void *x0, void *x1, void *x2)
4357 FIXME("%p %p %p %p\n", unk, x0, x1, x2);
4361 /***********************************************************************
4362 * ZoneComputePaneSize [SHLWAPI.382]
4364 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4370 void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
4372 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
4375 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
4376 SID_IDENTIFIER_AUTHORITY sidAuthority;
4377 DWORD dwUserGroupID;
4379 } SHELL_USER_SID, *PSHELL_USER_SID;
4381 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
4382 SHELL_USER_SID susID;
4386 DWORD dwInheritMask;
4387 DWORD dwInheritAccessMask;
4388 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
4390 /***********************************************************************
4391 * GetShellSecurityDescriptor [SHLWAPI.475]
4393 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4396 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4397 * each of which describes permissions to apply
4398 * cUserPerm [I] number of entries in apUserPerm array
4401 * success: pointer to SECURITY_DESCRIPTOR
4405 * Call should free returned descriptor with LocalFree
4407 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4410 PSID cur_user = NULL;
4414 PSECURITY_DESCRIPTOR psd = NULL;
4416 TRACE("%p %d\n", apUserPerm, cUserPerm);
4418 if (apUserPerm == NULL || cUserPerm <= 0)
4421 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
4425 acl_size = sizeof(ACL);
4427 for(sid_count = 0; sid_count < cUserPerm; sid_count++)
4429 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
4430 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
4431 PSHELL_USER_SID sid = &perm->susID;
4435 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4436 { /* current user's SID */
4440 DWORD bufsize = sizeof(tuUser);
4442 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4445 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4447 cur_user = ((PTOKEN_USER)&tuUser)->User.Sid;
4452 } else if (sid->dwUserID==0) /* one sub-authority */
4453 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
4454 0, 0, 0, 0, 0, 0, &pSid);
4456 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4457 0, 0, 0, 0, 0, 0, &pSid);
4461 sidlist[sid_count] = pSid;
4462 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4463 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
4466 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
4470 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4472 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4475 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4478 for(i = 0; i < sid_count; i++)
4480 PSHELL_USER_PERMISSION sup = apUserPerm[i];
4481 PSID sid = sidlist[i];
4483 switch(sup->dwAccessType)
4485 case ACCESS_ALLOWED_ACE_TYPE:
4486 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4488 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4489 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4492 case ACCESS_DENIED_ACE_TYPE:
4493 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4495 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4496 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4504 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4513 for(i = 0; i < sid_count; i++)
4515 if (!cur_user || sidlist[i] != cur_user)
4516 FreeSid(sidlist[i]);
4518 HeapFree(GetProcessHeap(), 0, sidlist);