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
23 #define WIN32_NO_STATUS
25 #define COM_NO_WINDOWS_H
28 //#include "wine/port.h"
35 #define NONAMELESSUNION
36 #define NONAMELESSSTRUCT
43 //#include "winuser.h"
47 //#include "objbase.h"
49 //#include "shdeprecated.h"
56 #include <wine/unicode.h>
57 #include <wine/debug.h>
60 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
62 /* DLL handles for late bound calls */
63 extern HINSTANCE shlwapi_hInstance
;
64 extern DWORD SHLWAPI_ThreadRef_index
;
66 HRESULT WINAPI
IUnknown_QueryService(IUnknown
*,REFGUID
,REFIID
,LPVOID
*);
67 HRESULT WINAPI
SHInvokeCommand(HWND
,IShellFolder
*,LPCITEMIDLIST
,BOOL
);
68 BOOL WINAPI
SHAboutInfoW(LPWSTR
,DWORD
);
71 NOTES: Most functions exported by ordinal seem to be superfluous.
72 The reason for these functions to be there is to provide a wrapper
73 for unicode functions to provide these functions on systems without
74 unicode functions eg. win95/win98. Since we have such functions we just
75 call these. If running Wine with native DLLs, some late bound calls may
76 fail. However, it is better to implement the functions in the forward DLL
77 and recommend the builtin rather than reimplementing the calls here!
80 /*************************************************************************
81 * SHLWAPI_DupSharedHandle
83 * Internal implementation of SHLWAPI_11.
85 static HANDLE
SHLWAPI_DupSharedHandle(HANDLE hShared
, DWORD dwDstProcId
,
86 DWORD dwSrcProcId
, DWORD dwAccess
,
90 DWORD dwMyProcId
= GetCurrentProcessId();
93 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared
, dwDstProcId
, dwSrcProcId
,
96 /* Get dest process handle */
97 if (dwDstProcId
== dwMyProcId
)
98 hDst
= GetCurrentProcess();
100 hDst
= OpenProcess(PROCESS_DUP_HANDLE
, 0, dwDstProcId
);
104 /* Get src process handle */
105 if (dwSrcProcId
== dwMyProcId
)
106 hSrc
= GetCurrentProcess();
108 hSrc
= OpenProcess(PROCESS_DUP_HANDLE
, 0, dwSrcProcId
);
112 /* Make handle available to dest process */
113 if (!DuplicateHandle(hDst
, hShared
, hSrc
, &hRet
,
114 dwAccess
, 0, dwOptions
| DUPLICATE_SAME_ACCESS
))
117 if (dwSrcProcId
!= dwMyProcId
)
121 if (dwDstProcId
!= dwMyProcId
)
125 TRACE("Returning handle %p\n", hRet
);
129 /*************************************************************************
132 * Create a block of sharable memory and initialise it with data.
135 * lpvData [I] Pointer to data to write
136 * dwSize [I] Size of data
137 * dwProcId [I] ID of process owning data
140 * Success: A shared memory handle
144 * Ordinals 7-11 provide a set of calls to create shared memory between a
145 * group of processes. The shared memory is treated opaquely in that its size
146 * is not exposed to clients who map it. This is accomplished by storing
147 * the size of the map as the first DWORD of mapped data, and then offsetting
148 * the view pointer returned by this size.
151 HANDLE WINAPI
SHAllocShared(LPCVOID lpvData
, DWORD dwSize
, DWORD dwProcId
)
157 TRACE("(%p,%d,%d)\n", lpvData
, dwSize
, dwProcId
);
159 /* Create file mapping of the correct length */
160 hMap
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, FILE_MAP_READ
, 0,
161 dwSize
+ sizeof(dwSize
), NULL
);
165 /* Get a view in our process address space */
166 pMapped
= MapViewOfFile(hMap
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
170 /* Write size of data, followed by the data, to the view */
171 *((DWORD
*)pMapped
) = dwSize
;
173 memcpy((char *) pMapped
+ sizeof(dwSize
), lpvData
, dwSize
);
175 /* Release view. All further views mapped will be opaque */
176 UnmapViewOfFile(pMapped
);
177 hRet
= SHLWAPI_DupSharedHandle(hMap
, dwProcId
,
178 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS
,
179 DUPLICATE_SAME_ACCESS
);
186 /*************************************************************************
189 * Get a pointer to a block of shared memory from a shared memory handle.
192 * hShared [I] Shared memory handle
193 * dwProcId [I] ID of process owning hShared
196 * Success: A pointer to the shared memory
200 PVOID WINAPI
SHLockShared(HANDLE hShared
, DWORD dwProcId
)
205 TRACE("(%p %d)\n", hShared
, dwProcId
);
207 /* Get handle to shared memory for current process */
208 hDup
= SHLWAPI_DupSharedHandle(hShared
, dwProcId
, GetCurrentProcessId(),
209 FILE_MAP_ALL_ACCESS
, 0);
211 pMapped
= MapViewOfFile(hDup
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
215 return (char *) pMapped
+ sizeof(DWORD
); /* Hide size */
219 /*************************************************************************
222 * Release a pointer to a block of shared memory.
225 * lpView [I] Shared memory pointer
232 BOOL WINAPI
SHUnlockShared(LPVOID lpView
)
234 TRACE("(%p)\n", lpView
);
235 return UnmapViewOfFile((char *) lpView
- sizeof(DWORD
)); /* Include size */
238 /*************************************************************************
241 * Destroy a block of sharable memory.
244 * hShared [I] Shared memory handle
245 * dwProcId [I] ID of process owning hShared
252 BOOL WINAPI
SHFreeShared(HANDLE hShared
, DWORD dwProcId
)
256 TRACE("(%p %d)\n", hShared
, dwProcId
);
258 /* Get a copy of the handle for our process, closing the source handle */
259 hClose
= SHLWAPI_DupSharedHandle(hShared
, dwProcId
, GetCurrentProcessId(),
260 FILE_MAP_ALL_ACCESS
,DUPLICATE_CLOSE_SOURCE
);
261 /* Close local copy */
262 return CloseHandle(hClose
);
265 /*************************************************************************
268 * Copy a sharable memory handle from one process to another.
271 * hShared [I] Shared memory handle to duplicate
272 * dwDstProcId [I] ID of the process wanting the duplicated handle
273 * dwSrcProcId [I] ID of the process owning hShared
274 * dwAccess [I] Desired DuplicateHandle() access
275 * dwOptions [I] Desired DuplicateHandle() options
278 * Success: A handle suitable for use by the dwDstProcId process.
279 * Failure: A NULL handle.
282 HANDLE WINAPI
SHMapHandle(HANDLE hShared
, DWORD dwDstProcId
, DWORD dwSrcProcId
,
283 DWORD dwAccess
, DWORD dwOptions
)
287 hRet
= SHLWAPI_DupSharedHandle(hShared
, dwDstProcId
, dwSrcProcId
,
288 dwAccess
, dwOptions
);
292 /*************************************************************************
295 * Create and register a clipboard enumerator for a web browser.
298 * lpBC [I] Binding context
299 * lpUnknown [I] An object exposing the IWebBrowserApp interface
303 * Failure: An HRESULT error code.
306 * The enumerator is stored as a property of the web browser. If it does not
307 * yet exist, it is created and set before being registered.
309 HRESULT WINAPI
RegisterDefaultAcceptHeaders(LPBC lpBC
, IUnknown
*lpUnknown
)
311 static const WCHAR szProperty
[] = { '{','D','0','F','C','A','4','2','0',
312 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
313 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
315 IEnumFORMATETC
* pIEnumFormatEtc
= NULL
;
318 IWebBrowserApp
* pBrowser
;
320 TRACE("(%p, %p)\n", lpBC
, lpUnknown
);
322 hr
= IUnknown_QueryService(lpUnknown
, &IID_IWebBrowserApp
, &IID_IWebBrowserApp
, (void**)&pBrowser
);
326 V_VT(&var
) = VT_EMPTY
;
328 /* The property we get is the browsers clipboard enumerator */
329 property
= SysAllocString(szProperty
);
330 hr
= IWebBrowserApp_GetProperty(pBrowser
, property
, &var
);
331 SysFreeString(property
);
332 if (FAILED(hr
)) goto exit
;
334 if (V_VT(&var
) == VT_EMPTY
)
336 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
337 char szKeyBuff
[128], szValueBuff
[128];
338 DWORD dwKeySize
, dwValueSize
, dwRet
= 0, dwCount
= 0, dwNumValues
, dwType
;
339 FORMATETC
* formatList
, *format
;
342 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
344 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\Current"
345 "Version\\Internet Settings\\Accepted Documents", &hDocs
))
351 /* Get count of values in key */
354 dwKeySize
= sizeof(szKeyBuff
);
355 dwRet
= RegEnumValueA(hDocs
,dwCount
,szKeyBuff
,&dwKeySize
,0,&dwType
,0,0);
359 dwNumValues
= dwCount
;
361 /* Note: dwCount = number of items + 1; The extra item is the end node */
362 format
= formatList
= HeapAlloc(GetProcessHeap(), 0, dwCount
* sizeof(FORMATETC
));
377 /* Register clipboard formats for the values and populate format list */
378 while(!dwRet
&& dwCount
< dwNumValues
)
380 dwKeySize
= sizeof(szKeyBuff
);
381 dwValueSize
= sizeof(szValueBuff
);
382 dwRet
= RegEnumValueA(hDocs
, dwCount
, szKeyBuff
, &dwKeySize
, 0, &dwType
,
383 (PBYTE
)szValueBuff
, &dwValueSize
);
386 HeapFree(GetProcessHeap(), 0, formatList
);
392 format
->cfFormat
= RegisterClipboardFormatA(szValueBuff
);
394 format
->dwAspect
= 1;
405 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
406 format
->cfFormat
= 0;
408 format
->dwAspect
= 1;
412 /* Create a clipboard enumerator */
413 hr
= CreateFormatEnumerator(dwNumValues
, formatList
, &pIEnumFormatEtc
);
414 HeapFree(GetProcessHeap(), 0, formatList
);
415 if (FAILED(hr
)) goto exit
;
417 /* Set our enumerator as the browsers property */
418 V_VT(&var
) = VT_UNKNOWN
;
419 V_UNKNOWN(&var
) = (IUnknown
*)pIEnumFormatEtc
;
421 property
= SysAllocString(szProperty
);
422 hr
= IWebBrowserApp_PutProperty(pBrowser
, property
, var
);
423 SysFreeString(property
);
426 IEnumFORMATETC_Release(pIEnumFormatEtc
);
431 if (V_VT(&var
) == VT_UNKNOWN
)
433 /* Our variant is holding the clipboard enumerator */
434 IUnknown
* pIUnknown
= V_UNKNOWN(&var
);
435 IEnumFORMATETC
* pClone
= NULL
;
437 TRACE("Retrieved IEnumFORMATETC property\n");
439 /* Get an IEnumFormatEtc interface from the variants value */
440 pIEnumFormatEtc
= NULL
;
441 hr
= IUnknown_QueryInterface(pIUnknown
, &IID_IEnumFORMATETC
, (void**)&pIEnumFormatEtc
);
442 if (hr
== S_OK
&& pIEnumFormatEtc
)
444 /* Clone and register the enumerator */
445 hr
= IEnumFORMATETC_Clone(pIEnumFormatEtc
, &pClone
);
446 if (hr
== S_OK
&& pClone
)
448 RegisterFormatEnumerator(lpBC
, pClone
, 0);
450 IEnumFORMATETC_Release(pClone
);
453 IUnknown_Release(pIUnknown
);
455 IUnknown_Release(V_UNKNOWN(&var
));
459 IWebBrowserApp_Release(pBrowser
);
463 /*************************************************************************
466 * Get Explorers "AcceptLanguage" setting.
469 * langbuf [O] Destination for language string
470 * buflen [I] Length of langbuf in characters
471 * [0] Success: used length of langbuf
474 * Success: S_OK. langbuf is set to the language string found.
475 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
476 * does not contain the setting.
477 * HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), If the buffer is not big enough
479 HRESULT WINAPI
GetAcceptLanguagesW( LPWSTR langbuf
, LPDWORD buflen
)
481 static const WCHAR szkeyW
[] = {
482 'S','o','f','t','w','a','r','e','\\',
483 'M','i','c','r','o','s','o','f','t','\\',
484 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
485 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
486 static const WCHAR valueW
[] = {
487 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
488 DWORD mystrlen
, mytype
;
495 TRACE("(%p, %p) *%p: %d\n", langbuf
, buflen
, buflen
, buflen
? *buflen
: -1);
497 if(!langbuf
|| !buflen
|| !*buflen
)
500 mystrlen
= (*buflen
> 20) ? *buflen
: 20 ;
501 len
= mystrlen
* sizeof(WCHAR
);
502 mystr
= HeapAlloc(GetProcessHeap(), 0, len
);
504 RegOpenKeyW(HKEY_CURRENT_USER
, szkeyW
, &mykey
);
505 lres
= RegQueryValueExW(mykey
, valueW
, 0, &mytype
, (PBYTE
)mystr
, &len
);
507 len
= lstrlenW(mystr
);
509 if (!lres
&& (*buflen
> len
)) {
510 lstrcpyW(langbuf
, mystr
);
512 HeapFree(GetProcessHeap(), 0, mystr
);
516 /* Did not find a value in the registry or the user buffer is too small */
517 mylcid
= GetUserDefaultLCID();
518 LcidToRfc1766W(mylcid
, mystr
, mystrlen
);
519 len
= lstrlenW(mystr
);
521 memcpy( langbuf
, mystr
, min(*buflen
, len
+1)*sizeof(WCHAR
) );
522 HeapFree(GetProcessHeap(), 0, mystr
);
530 return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
533 /*************************************************************************
536 * Ascii version of GetAcceptLanguagesW.
538 HRESULT WINAPI
GetAcceptLanguagesA( LPSTR langbuf
, LPDWORD buflen
)
541 DWORD buflenW
, convlen
;
544 TRACE("(%p, %p) *%p: %d\n", langbuf
, buflen
, buflen
, buflen
? *buflen
: -1);
546 if(!langbuf
|| !buflen
|| !*buflen
) return E_FAIL
;
549 langbufW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * buflenW
);
550 retval
= GetAcceptLanguagesW(langbufW
, &buflenW
);
554 convlen
= WideCharToMultiByte(CP_ACP
, 0, langbufW
, -1, langbuf
, *buflen
, NULL
, NULL
);
555 convlen
--; /* do not count the terminating 0 */
557 else /* copy partial string anyway */
559 convlen
= WideCharToMultiByte(CP_ACP
, 0, langbufW
, *buflen
, langbuf
, *buflen
, NULL
, NULL
);
560 if (convlen
< *buflen
)
562 langbuf
[convlen
] = 0;
563 convlen
--; /* do not count the terminating 0 */
570 *buflen
= buflenW
? convlen
: 0;
572 HeapFree(GetProcessHeap(), 0, langbufW
);
576 /*************************************************************************
579 * Convert a GUID to a string.
582 * guid [I] GUID to convert
583 * lpszDest [O] Destination for string
584 * cchMax [I] Length of output buffer
587 * The length of the string created.
589 INT WINAPI
SHStringFromGUIDA(REFGUID guid
, LPSTR lpszDest
, INT cchMax
)
594 TRACE("(%s,%p,%d)\n", debugstr_guid(guid
), lpszDest
, cchMax
);
596 sprintf(xguid
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
597 guid
->Data1
, guid
->Data2
, guid
->Data3
,
598 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
599 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
601 iLen
= strlen(xguid
) + 1;
605 memcpy(lpszDest
, xguid
, iLen
);
609 /*************************************************************************
612 * Convert a GUID to a string.
615 * guid [I] GUID to convert
616 * str [O] Destination for string
617 * cmax [I] Length of output buffer
620 * The length of the string created.
622 INT WINAPI
SHStringFromGUIDW(REFGUID guid
, LPWSTR lpszDest
, INT cchMax
)
626 static const WCHAR wszFormat
[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
627 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
628 'X','%','0','2','X','%','0','2','X','}',0};
630 TRACE("(%s,%p,%d)\n", debugstr_guid(guid
), lpszDest
, cchMax
);
632 sprintfW(xguid
, wszFormat
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
633 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
634 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
636 iLen
= strlenW(xguid
) + 1;
640 memcpy(lpszDest
, xguid
, iLen
*sizeof(WCHAR
));
644 /*************************************************************************
647 * Determine if a Unicode character is a blank.
650 * wc [I] Character to check.
653 * TRUE, if wc is a blank,
657 BOOL WINAPI
IsCharBlankW(WCHAR wc
)
661 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_BLANK
);
664 /*************************************************************************
667 * Determine if a Unicode character is punctuation.
670 * wc [I] Character to check.
673 * TRUE, if wc is punctuation,
676 BOOL WINAPI
IsCharPunctW(WCHAR wc
)
680 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_PUNCT
);
683 /*************************************************************************
686 * Determine if a Unicode character is a control character.
689 * wc [I] Character to check.
692 * TRUE, if wc is a control character,
695 BOOL WINAPI
IsCharCntrlW(WCHAR wc
)
699 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_CNTRL
);
702 /*************************************************************************
705 * Determine if a Unicode character is a digit.
708 * wc [I] Character to check.
711 * TRUE, if wc is a digit,
714 BOOL WINAPI
IsCharDigitW(WCHAR wc
)
718 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_DIGIT
);
721 /*************************************************************************
724 * Determine if a Unicode character is a hex digit.
727 * wc [I] Character to check.
730 * TRUE, if wc is a hex digit,
733 BOOL WINAPI
IsCharXDigitW(WCHAR wc
)
737 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_XDIGIT
);
740 /*************************************************************************
744 BOOL WINAPI
GetStringType3ExW(LPWSTR src
, INT count
, LPWORD type
)
746 return GetStringTypeW(CT_CTYPE3
, src
, count
, type
);
749 /*************************************************************************
752 * Compare two Ascii strings up to a given length.
755 * lpszSrc [I] Source string
756 * lpszCmp [I] String to compare to lpszSrc
757 * len [I] Maximum length
760 * A number greater than, less than or equal to 0 depending on whether
761 * lpszSrc is greater than, less than or equal to lpszCmp.
763 DWORD WINAPI
StrCmpNCA(LPCSTR lpszSrc
, LPCSTR lpszCmp
, INT len
)
765 return StrCmpNA(lpszSrc
, lpszCmp
, len
);
768 /*************************************************************************
771 * Unicode version of StrCmpNCA.
773 DWORD WINAPI
StrCmpNCW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
, INT len
)
775 return StrCmpNW(lpszSrc
, lpszCmp
, len
);
778 /*************************************************************************
781 * Compare two Ascii strings up to a given length, ignoring case.
784 * lpszSrc [I] Source string
785 * lpszCmp [I] String to compare to lpszSrc
786 * len [I] Maximum length
789 * A number greater than, less than or equal to 0 depending on whether
790 * lpszSrc is greater than, less than or equal to lpszCmp.
792 DWORD WINAPI
StrCmpNICA(LPCSTR lpszSrc
, LPCSTR lpszCmp
, DWORD len
)
794 return StrCmpNIA(lpszSrc
, lpszCmp
, len
);
797 /*************************************************************************
800 * Unicode version of StrCmpNICA.
802 DWORD WINAPI
StrCmpNICW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
, DWORD len
)
804 return StrCmpNIW(lpszSrc
, lpszCmp
, len
);
807 /*************************************************************************
810 * Compare two Ascii strings.
813 * lpszSrc [I] Source string
814 * lpszCmp [I] String to compare to lpszSrc
817 * A number greater than, less than or equal to 0 depending on whether
818 * lpszSrc is greater than, less than or equal to lpszCmp.
820 DWORD WINAPI
StrCmpCA(LPCSTR lpszSrc
, LPCSTR lpszCmp
)
822 return lstrcmpA(lpszSrc
, lpszCmp
);
825 /*************************************************************************
828 * Unicode version of StrCmpCA.
830 DWORD WINAPI
StrCmpCW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
)
832 return lstrcmpW(lpszSrc
, lpszCmp
);
835 /*************************************************************************
838 * Compare two Ascii strings, ignoring case.
841 * lpszSrc [I] Source string
842 * lpszCmp [I] String to compare to lpszSrc
845 * A number greater than, less than or equal to 0 depending on whether
846 * lpszSrc is greater than, less than or equal to lpszCmp.
848 DWORD WINAPI
StrCmpICA(LPCSTR lpszSrc
, LPCSTR lpszCmp
)
850 return lstrcmpiA(lpszSrc
, lpszCmp
);
853 /*************************************************************************
856 * Unicode version of StrCmpICA.
858 DWORD WINAPI
StrCmpICW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
)
860 return lstrcmpiW(lpszSrc
, lpszCmp
);
863 /*************************************************************************
866 * Get an identification string for the OS and explorer.
869 * lpszDest [O] Destination for Id string
870 * dwDestLen [I] Length of lpszDest
873 * TRUE, If the string was created successfully
876 BOOL WINAPI
SHAboutInfoA(LPSTR lpszDest
, DWORD dwDestLen
)
880 TRACE("(%p,%d)\n", lpszDest
, dwDestLen
);
882 if (lpszDest
&& SHAboutInfoW(buff
, dwDestLen
))
884 WideCharToMultiByte(CP_ACP
, 0, buff
, -1, lpszDest
, dwDestLen
, NULL
, NULL
);
890 /*************************************************************************
893 * Unicode version of SHAboutInfoA.
895 BOOL WINAPI
SHAboutInfoW(LPWSTR lpszDest
, DWORD dwDestLen
)
897 static const WCHAR szIEKey
[] = { 'S','O','F','T','W','A','R','E','\\',
898 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
899 ' ','E','x','p','l','o','r','e','r','\0' };
900 static const WCHAR szWinNtKey
[] = { 'S','O','F','T','W','A','R','E','\\',
901 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
902 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
903 static const WCHAR szWinKey
[] = { 'S','O','F','T','W','A','R','E','\\',
904 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
905 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
906 static const WCHAR szRegKey
[] = { 'S','O','F','T','W','A','R','E','\\',
907 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
908 ' ','E','x','p','l','o','r','e','r','\\',
909 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
910 static const WCHAR szVersion
[] = { 'V','e','r','s','i','o','n','\0' };
911 static const WCHAR szCustomized
[] = { 'C','u','s','t','o','m','i','z','e','d',
912 'V','e','r','s','i','o','n','\0' };
913 static const WCHAR szOwner
[] = { 'R','e','g','i','s','t','e','r','e','d',
914 'O','w','n','e','r','\0' };
915 static const WCHAR szOrg
[] = { 'R','e','g','i','s','t','e','r','e','d',
916 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
917 static const WCHAR szProduct
[] = { 'P','r','o','d','u','c','t','I','d','\0' };
918 static const WCHAR szUpdate
[] = { 'I','E','A','K',
919 'U','p','d','a','t','e','U','r','l','\0' };
920 static const WCHAR szHelp
[] = { 'I','E','A','K',
921 'H','e','l','p','S','t','r','i','n','g','\0' };
926 TRACE("(%p,%d)\n", lpszDest
, dwDestLen
);
933 /* Try the NT key first, followed by 95/98 key */
934 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szWinNtKey
, 0, KEY_READ
, &hReg
) &&
935 RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szWinKey
, 0, KEY_READ
, &hReg
))
941 if (!SHGetValueW(HKEY_LOCAL_MACHINE
, szIEKey
, szVersion
, &dwType
, buff
, &dwLen
))
943 DWORD dwStrLen
= strlenW(buff
);
944 dwLen
= 30 - dwStrLen
;
945 SHGetValueW(HKEY_LOCAL_MACHINE
, szIEKey
,
946 szCustomized
, &dwType
, buff
+dwStrLen
, &dwLen
);
948 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
950 /* ~Registered Owner */
953 if (SHGetValueW(hReg
, szOwner
, 0, &dwType
, buff
+1, &dwLen
))
955 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
957 /* ~Registered Organization */
959 if (SHGetValueW(hReg
, szOrg
, 0, &dwType
, buff
+1, &dwLen
))
961 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
963 /* FIXME: Not sure where this number comes from */
967 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
971 if (SHGetValueW(HKEY_LOCAL_MACHINE
, szRegKey
, szProduct
, &dwType
, buff
+1, &dwLen
))
973 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
977 if(SHGetValueW(HKEY_LOCAL_MACHINE
, szWinKey
, szUpdate
, &dwType
, buff
+1, &dwLen
))
979 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
981 /* ~IE Help String */
983 if(SHGetValueW(hReg
, szHelp
, 0, &dwType
, buff
+1, &dwLen
))
985 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
991 /*************************************************************************
994 * Call IOleCommandTarget_QueryStatus() on an object.
997 * lpUnknown [I] Object supporting the IOleCommandTarget interface
998 * pguidCmdGroup [I] GUID for the command group
1000 * prgCmds [O] Commands
1001 * pCmdText [O] Command text
1005 * Failure: E_FAIL, if lpUnknown is NULL.
1006 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1007 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1009 HRESULT WINAPI
IUnknown_QueryStatus(IUnknown
* lpUnknown
, REFGUID pguidCmdGroup
,
1010 ULONG cCmds
, OLECMD
*prgCmds
, OLECMDTEXT
* pCmdText
)
1012 HRESULT hRet
= E_FAIL
;
1014 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown
, pguidCmdGroup
, cCmds
, prgCmds
, pCmdText
);
1018 IOleCommandTarget
* lpOle
;
1020 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleCommandTarget
,
1023 if (SUCCEEDED(hRet
) && lpOle
)
1025 hRet
= IOleCommandTarget_QueryStatus(lpOle
, pguidCmdGroup
, cCmds
,
1027 IOleCommandTarget_Release(lpOle
);
1033 /*************************************************************************
1036 * Call IOleCommandTarget_Exec() on an object.
1039 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1040 * pguidCmdGroup [I] GUID for the command group
1044 * Failure: E_FAIL, if lpUnknown is NULL.
1045 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1046 * Otherwise, an error code from IOleCommandTarget_Exec().
1048 HRESULT WINAPI
IUnknown_Exec(IUnknown
* lpUnknown
, REFGUID pguidCmdGroup
,
1049 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
* pvaIn
,
1052 HRESULT hRet
= E_FAIL
;
1054 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown
, pguidCmdGroup
, nCmdID
,
1055 nCmdexecopt
, pvaIn
, pvaOut
);
1059 IOleCommandTarget
* lpOle
;
1061 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleCommandTarget
,
1063 if (SUCCEEDED(hRet
) && lpOle
)
1065 hRet
= IOleCommandTarget_Exec(lpOle
, pguidCmdGroup
, nCmdID
,
1066 nCmdexecopt
, pvaIn
, pvaOut
);
1067 IOleCommandTarget_Release(lpOle
);
1073 /*************************************************************************
1076 * Retrieve, modify, and re-set a value from a window.
1079 * hWnd [I] Window to get value from
1080 * offset [I] Offset of value
1081 * mask [I] Mask for flags
1082 * flags [I] Bits to set in window value
1085 * The new value as it was set, or 0 if any parameter is invalid.
1088 * Only bits specified in mask are affected - set if present in flags and
1091 LONG WINAPI
SHSetWindowBits(HWND hwnd
, INT offset
, UINT mask
, UINT flags
)
1093 LONG ret
= GetWindowLongW(hwnd
, offset
);
1094 LONG new_flags
= (flags
& mask
) | (ret
& ~mask
);
1096 TRACE("%p %d %x %x\n", hwnd
, offset
, mask
, flags
);
1098 if (new_flags
!= ret
)
1099 ret
= SetWindowLongW(hwnd
, offset
, new_flags
);
1103 /*************************************************************************
1106 * Change a window's parent.
1109 * hWnd [I] Window to change parent of
1110 * hWndParent [I] New parent window
1113 * The old parent of hWnd.
1116 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1117 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1119 HWND WINAPI
SHSetParentHwnd(HWND hWnd
, HWND hWndParent
)
1121 TRACE("%p, %p\n", hWnd
, hWndParent
);
1123 if(GetParent(hWnd
) == hWndParent
)
1127 SHSetWindowBits(hWnd
, GWL_STYLE
, WS_CHILD
| WS_POPUP
, WS_CHILD
);
1129 SHSetWindowBits(hWnd
, GWL_STYLE
, WS_CHILD
| WS_POPUP
, WS_POPUP
);
1131 return hWndParent
? SetParent(hWnd
, hWndParent
) : NULL
;
1134 /*************************************************************************
1137 * Locate and advise a connection point in an IConnectionPointContainer object.
1140 * lpUnkSink [I] Sink for the connection point advise call
1141 * riid [I] REFIID of connection point to advise
1142 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1143 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1144 * lpCookie [O] Pointer to connection point cookie
1145 * lppCP [O] Destination for the IConnectionPoint found
1148 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1149 * that was advised. The caller is responsible for releasing it.
1150 * Failure: E_FAIL, if any arguments are invalid.
1151 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1152 * Or an HRESULT error code if any call fails.
1154 HRESULT WINAPI
ConnectToConnectionPoint(IUnknown
* lpUnkSink
, REFIID riid
, BOOL fConnect
,
1155 IUnknown
* lpUnknown
, LPDWORD lpCookie
,
1156 IConnectionPoint
**lppCP
)
1159 IConnectionPointContainer
* lpContainer
;
1160 IConnectionPoint
*lpCP
;
1162 if(!lpUnknown
|| (fConnect
&& !lpUnkSink
))
1168 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IConnectionPointContainer
,
1169 (void**)&lpContainer
);
1170 if (SUCCEEDED(hRet
))
1172 hRet
= IConnectionPointContainer_FindConnectionPoint(lpContainer
, riid
, &lpCP
);
1174 if (SUCCEEDED(hRet
))
1177 hRet
= IConnectionPoint_Unadvise(lpCP
, *lpCookie
);
1179 hRet
= IConnectionPoint_Advise(lpCP
, lpUnkSink
, lpCookie
);
1184 if (lppCP
&& SUCCEEDED(hRet
))
1185 *lppCP
= lpCP
; /* Caller keeps the interface */
1187 IConnectionPoint_Release(lpCP
); /* Release it */
1190 IConnectionPointContainer_Release(lpContainer
);
1195 /*************************************************************************
1198 * Release an interface and zero a supplied pointer.
1201 * lpUnknown [I] Object to release
1206 void WINAPI
IUnknown_AtomicRelease(IUnknown
** lpUnknown
)
1208 TRACE("(%p)\n", lpUnknown
);
1210 if(!lpUnknown
|| !*lpUnknown
) return;
1212 TRACE("doing Release\n");
1214 IUnknown_Release(*lpUnknown
);
1218 /*************************************************************************
1221 * Skip '//' if present in a string.
1224 * lpszSrc [I] String to check for '//'
1227 * Success: The next character after the '//' or the string if not present
1228 * Failure: NULL, if lpszStr is NULL.
1230 LPCSTR WINAPI
PathSkipLeadingSlashesA(LPCSTR lpszSrc
)
1232 if (lpszSrc
&& lpszSrc
[0] == '/' && lpszSrc
[1] == '/')
1237 /*************************************************************************
1240 * Check if two interfaces come from the same object.
1243 * lpInt1 [I] Interface to check against lpInt2.
1244 * lpInt2 [I] Interface to check against lpInt1.
1247 * TRUE, If the interfaces come from the same object.
1250 BOOL WINAPI
SHIsSameObject(IUnknown
* lpInt1
, IUnknown
* lpInt2
)
1252 IUnknown
*lpUnknown1
, *lpUnknown2
;
1255 TRACE("(%p %p)\n", lpInt1
, lpInt2
);
1257 if (!lpInt1
|| !lpInt2
)
1260 if (lpInt1
== lpInt2
)
1263 if (IUnknown_QueryInterface(lpInt1
, &IID_IUnknown
, (void**)&lpUnknown1
) != S_OK
)
1266 if (IUnknown_QueryInterface(lpInt2
, &IID_IUnknown
, (void**)&lpUnknown2
) != S_OK
)
1268 IUnknown_Release(lpUnknown1
);
1272 ret
= lpUnknown1
== lpUnknown2
;
1274 IUnknown_Release(lpUnknown1
);
1275 IUnknown_Release(lpUnknown2
);
1280 /*************************************************************************
1283 * Get the window handle of an object.
1286 * lpUnknown [I] Object to get the window handle of
1287 * lphWnd [O] Destination for window handle
1290 * Success: S_OK. lphWnd contains the objects window handle.
1291 * Failure: An HRESULT error code.
1294 * lpUnknown is expected to support one of the following interfaces:
1295 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1297 HRESULT WINAPI
IUnknown_GetWindow(IUnknown
*lpUnknown
, HWND
*lphWnd
)
1300 HRESULT hRet
= E_FAIL
;
1302 TRACE("(%p,%p)\n", lpUnknown
, lphWnd
);
1307 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleWindow
, (void**)&lpOle
);
1311 hRet
= IUnknown_QueryInterface(lpUnknown
,&IID_IShellView
, (void**)&lpOle
);
1315 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInternetSecurityMgrSite
,
1320 if (SUCCEEDED(hRet
))
1322 /* Laziness here - Since GetWindow() is the first method for the above 3
1323 * interfaces, we use the same call for them all.
1325 hRet
= IOleWindow_GetWindow((IOleWindow
*)lpOle
, lphWnd
);
1326 IUnknown_Release(lpOle
);
1328 TRACE("Returning HWND=%p\n", *lphWnd
);
1334 /*************************************************************************
1337 * Call a SetOwner method of IShellService from specified object.
1340 * iface [I] Object that supports IShellService
1341 * pUnk [I] Argument for the SetOwner call
1344 * Corresponding return value from last call or E_FAIL for null input
1346 HRESULT WINAPI
IUnknown_SetOwner(IUnknown
*iface
, IUnknown
*pUnk
)
1348 IShellService
*service
;
1351 TRACE("(%p, %p)\n", iface
, pUnk
);
1353 if (!iface
) return E_FAIL
;
1355 hr
= IUnknown_QueryInterface(iface
, &IID_IShellService
, (void**)&service
);
1358 hr
= IShellService_SetOwner(service
, pUnk
);
1359 IShellService_Release(service
);
1365 /*************************************************************************
1368 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1372 HRESULT WINAPI
IUnknown_SetSite(
1373 IUnknown
*obj
, /* [in] OLE object */
1374 IUnknown
*site
) /* [in] Site interface */
1377 IObjectWithSite
*iobjwithsite
;
1378 IInternetSecurityManager
*isecmgr
;
1380 if (!obj
) return E_FAIL
;
1382 hr
= IUnknown_QueryInterface(obj
, &IID_IObjectWithSite
, (LPVOID
*)&iobjwithsite
);
1383 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr
, iobjwithsite
);
1386 hr
= IObjectWithSite_SetSite(iobjwithsite
, site
);
1387 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr
);
1388 IObjectWithSite_Release(iobjwithsite
);
1392 hr
= IUnknown_QueryInterface(obj
, &IID_IInternetSecurityManager
, (LPVOID
*)&isecmgr
);
1393 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr
, isecmgr
);
1394 if (FAILED(hr
)) return hr
;
1396 hr
= IInternetSecurityManager_SetSecuritySite(isecmgr
, (IInternetSecurityMgrSite
*)site
);
1397 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr
);
1398 IInternetSecurityManager_Release(isecmgr
);
1403 /*************************************************************************
1406 * Call IPersist_GetClassID() on an object.
1409 * lpUnknown [I] Object supporting the IPersist interface
1410 * lpClassId [O] Destination for Class Id
1413 * Success: S_OK. lpClassId contains the Class Id requested.
1414 * Failure: E_FAIL, If lpUnknown is NULL,
1415 * E_NOINTERFACE If lpUnknown does not support IPersist,
1416 * Or an HRESULT error code.
1418 HRESULT WINAPI
IUnknown_GetClassID(IUnknown
*lpUnknown
, CLSID
* lpClassId
)
1420 IPersist
* lpPersist
;
1421 HRESULT hRet
= E_FAIL
;
1423 TRACE("(%p,%s)\n", lpUnknown
, debugstr_guid(lpClassId
));
1427 hRet
= IUnknown_QueryInterface(lpUnknown
,&IID_IPersist
,(void**)&lpPersist
);
1428 if (SUCCEEDED(hRet
))
1430 IPersist_GetClassID(lpPersist
, lpClassId
);
1431 IPersist_Release(lpPersist
);
1437 /*************************************************************************
1440 * Retrieve a Service Interface from an object.
1443 * lpUnknown [I] Object to get an IServiceProvider interface from
1444 * sid [I] Service ID for IServiceProvider_QueryService() call
1445 * riid [I] Function requested for QueryService call
1446 * lppOut [O] Destination for the service interface pointer
1449 * Success: S_OK. lppOut contains an object providing the requested service
1450 * Failure: An HRESULT error code
1453 * lpUnknown is expected to support the IServiceProvider interface.
1455 HRESULT WINAPI
IUnknown_QueryService(IUnknown
* lpUnknown
, REFGUID sid
, REFIID riid
,
1458 IServiceProvider
* pService
= NULL
;
1469 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IServiceProvider
,
1470 (LPVOID
*)&pService
);
1472 if (hRet
== S_OK
&& pService
)
1474 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService
);
1476 /* Get a Service interface from the object */
1477 hRet
= IServiceProvider_QueryService(pService
, sid
, riid
, lppOut
);
1479 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService
, *lppOut
);
1481 IServiceProvider_Release(pService
);
1486 /*************************************************************************
1489 * Calls IOleCommandTarget::Exec() for specified service object.
1492 * lpUnknown [I] Object to get an IServiceProvider interface from
1493 * service [I] Service ID for IServiceProvider_QueryService() call
1494 * group [I] Group ID for IOleCommandTarget::Exec() call
1495 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1496 * cmdOpt [I] Options flags for command
1497 * pIn [I] Input arguments for command
1498 * pOut [O] Output arguments for command
1501 * Success: S_OK. lppOut contains an object providing the requested service
1502 * Failure: An HRESULT error code
1505 * lpUnknown is expected to support the IServiceProvider interface.
1507 HRESULT WINAPI
IUnknown_QueryServiceExec(IUnknown
*lpUnknown
, REFIID service
,
1508 const GUID
*group
, DWORD cmdId
, DWORD cmdOpt
, VARIANT
*pIn
, VARIANT
*pOut
)
1510 IOleCommandTarget
*target
;
1513 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown
, debugstr_guid(service
),
1514 debugstr_guid(group
), cmdId
, cmdOpt
, pIn
, pOut
);
1516 hr
= IUnknown_QueryService(lpUnknown
, service
, &IID_IOleCommandTarget
, (void**)&target
);
1519 hr
= IOleCommandTarget_Exec(target
, group
, cmdId
, cmdOpt
, pIn
, pOut
);
1520 IOleCommandTarget_Release(target
);
1523 TRACE("<-- hr=0x%08x\n", hr
);
1528 /*************************************************************************
1531 * Calls IProfferService methods to proffer/revoke specified service.
1534 * lpUnknown [I] Object to get an IServiceProvider interface from
1535 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1536 * pService [I] Service to proffer. If NULL ::Revoke is called
1537 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1540 * Success: S_OK. IProffer method returns S_OK
1541 * Failure: An HRESULT error code
1544 * lpUnknown is expected to support the IServiceProvider interface.
1546 HRESULT WINAPI
IUnknown_ProfferService(IUnknown
*lpUnknown
, REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
1548 IProfferService
*proffer
;
1551 TRACE("%p %s %p %p\n", lpUnknown
, debugstr_guid(service
), pService
, pCookie
);
1553 hr
= IUnknown_QueryService(lpUnknown
, &IID_IProfferService
, &IID_IProfferService
, (void**)&proffer
);
1557 hr
= IProfferService_ProfferService(proffer
, service
, pService
, pCookie
);
1560 hr
= IProfferService_RevokeService(proffer
, *pCookie
);
1564 IProfferService_Release(proffer
);
1570 /*************************************************************************
1573 * Call an object's UIActivateIO method.
1576 * unknown [I] Object to call the UIActivateIO method on
1577 * activate [I] Parameter for UIActivateIO call
1578 * msg [I] Parameter for UIActivateIO call
1581 * Success: Value of UI_ActivateIO call
1582 * Failure: An HRESULT error code
1585 * unknown is expected to support the IInputObject interface.
1587 HRESULT WINAPI
IUnknown_UIActivateIO(IUnknown
*unknown
, BOOL activate
, LPMSG msg
)
1589 IInputObject
* object
= NULL
;
1595 /* Get an IInputObject interface from the object */
1596 ret
= IUnknown_QueryInterface(unknown
, &IID_IInputObject
, (LPVOID
*) &object
);
1600 ret
= IInputObject_UIActivateIO(object
, activate
, msg
);
1601 IInputObject_Release(object
);
1607 /*************************************************************************
1610 * Loads a popup menu.
1613 * hInst [I] Instance handle
1614 * szName [I] Menu name
1620 BOOL WINAPI
SHLoadMenuPopup(HINSTANCE hInst
, LPCWSTR szName
)
1624 TRACE("%p %s\n", hInst
, debugstr_w(szName
));
1626 if ((hMenu
= LoadMenuW(hInst
, szName
)))
1628 if (GetSubMenu(hMenu
, 0))
1629 RemoveMenu(hMenu
, 0, MF_BYPOSITION
);
1637 typedef struct _enumWndData
1642 LRESULT (WINAPI
*pfnPost
)(HWND
,UINT
,WPARAM
,LPARAM
);
1645 /* Callback for SHLWAPI_178 */
1646 static BOOL CALLBACK
SHLWAPI_EnumChildProc(HWND hWnd
, LPARAM lParam
)
1648 enumWndData
*data
= (enumWndData
*)lParam
;
1650 TRACE("(%p,%p)\n", hWnd
, data
);
1651 data
->pfnPost(hWnd
, data
->uiMsgId
, data
->wParam
, data
->lParam
);
1655 /*************************************************************************
1658 * Send or post a message to every child of a window.
1661 * hWnd [I] Window whose children will get the messages
1662 * uiMsgId [I] Message Id
1663 * wParam [I] WPARAM of message
1664 * lParam [I] LPARAM of message
1665 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1671 * The appropriate ASCII or Unicode function is called for the window.
1673 void WINAPI
SHPropagateMessage(HWND hWnd
, UINT uiMsgId
, WPARAM wParam
, LPARAM lParam
, BOOL bSend
)
1677 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd
, uiMsgId
, wParam
, lParam
, bSend
);
1681 data
.uiMsgId
= uiMsgId
;
1682 data
.wParam
= wParam
;
1683 data
.lParam
= lParam
;
1686 data
.pfnPost
= IsWindowUnicode(hWnd
) ? (void*)SendMessageW
: (void*)SendMessageA
;
1688 data
.pfnPost
= IsWindowUnicode(hWnd
) ? (void*)PostMessageW
: (void*)PostMessageA
;
1690 EnumChildWindows(hWnd
, SHLWAPI_EnumChildProc
, (LPARAM
)&data
);
1694 /*************************************************************************
1697 * Remove all sub-menus from a menu.
1700 * hMenu [I] Menu to remove sub-menus from
1703 * Success: 0. All sub-menus under hMenu are removed
1704 * Failure: -1, if any parameter is invalid
1706 DWORD WINAPI
SHRemoveAllSubMenus(HMENU hMenu
)
1708 int iItemCount
= GetMenuItemCount(hMenu
) - 1;
1710 TRACE("%p\n", hMenu
);
1712 while (iItemCount
>= 0)
1714 HMENU hSubMenu
= GetSubMenu(hMenu
, iItemCount
);
1716 RemoveMenu(hMenu
, iItemCount
, MF_BYPOSITION
);
1722 /*************************************************************************
1725 * Enable or disable a menu item.
1728 * hMenu [I] Menu holding menu item
1729 * uID [I] ID of menu item to enable/disable
1730 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1733 * The return code from EnableMenuItem.
1735 UINT WINAPI
SHEnableMenuItem(HMENU hMenu
, UINT wItemID
, BOOL bEnable
)
1737 TRACE("%p, %u, %d\n", hMenu
, wItemID
, bEnable
);
1738 return EnableMenuItem(hMenu
, wItemID
, bEnable
? MF_ENABLED
: MF_GRAYED
);
1741 /*************************************************************************
1744 * Check or uncheck a menu item.
1747 * hMenu [I] Menu holding menu item
1748 * uID [I] ID of menu item to check/uncheck
1749 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1752 * The return code from CheckMenuItem.
1754 DWORD WINAPI
SHCheckMenuItem(HMENU hMenu
, UINT uID
, BOOL bCheck
)
1756 TRACE("%p, %u, %d\n", hMenu
, uID
, bCheck
);
1757 return CheckMenuItem(hMenu
, uID
, bCheck
? MF_CHECKED
: MF_UNCHECKED
);
1760 /*************************************************************************
1763 * Register a window class if it isn't already.
1766 * lpWndClass [I] Window class to register
1769 * The result of the RegisterClassA call.
1771 DWORD WINAPI
SHRegisterClassA(WNDCLASSA
*wndclass
)
1774 if (GetClassInfoA(wndclass
->hInstance
, wndclass
->lpszClassName
, &wca
))
1776 return (DWORD
)RegisterClassA(wndclass
);
1779 /*************************************************************************
1782 BOOL WINAPI
SHSimulateDrop(IDropTarget
*pDrop
, IDataObject
*pDataObj
,
1783 DWORD grfKeyState
, PPOINTL lpPt
, DWORD
* pdwEffect
)
1785 DWORD dwEffect
= DROPEFFECT_LINK
| DROPEFFECT_MOVE
| DROPEFFECT_COPY
;
1786 POINTL pt
= { 0, 0 };
1788 TRACE("%p %p 0x%08x %p %p\n", pDrop
, pDataObj
, grfKeyState
, lpPt
, pdwEffect
);
1794 pdwEffect
= &dwEffect
;
1796 IDropTarget_DragEnter(pDrop
, pDataObj
, grfKeyState
, *lpPt
, pdwEffect
);
1798 if (*pdwEffect
!= DROPEFFECT_NONE
)
1799 return IDropTarget_Drop(pDrop
, pDataObj
, grfKeyState
, *lpPt
, pdwEffect
);
1801 IDropTarget_DragLeave(pDrop
);
1805 /*************************************************************************
1808 * Call IPersistPropertyBag_Load() on an object.
1811 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1812 * lpPropBag [O] Destination for loaded IPropertyBag
1816 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1818 DWORD WINAPI
SHLoadFromPropertyBag(IUnknown
*lpUnknown
, IPropertyBag
* lpPropBag
)
1820 IPersistPropertyBag
* lpPPBag
;
1821 HRESULT hRet
= E_FAIL
;
1823 TRACE("(%p,%p)\n", lpUnknown
, lpPropBag
);
1827 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IPersistPropertyBag
,
1829 if (SUCCEEDED(hRet
) && lpPPBag
)
1831 hRet
= IPersistPropertyBag_Load(lpPPBag
, lpPropBag
, NULL
);
1832 IPersistPropertyBag_Release(lpPPBag
);
1838 /*************************************************************************
1841 * Call IOleControlSite_TranslateAccelerator() on an object.
1844 * lpUnknown [I] Object supporting the IOleControlSite interface.
1845 * lpMsg [I] Key message to be processed.
1846 * dwModifiers [I] Flags containing the state of the modifier keys.
1850 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1852 HRESULT WINAPI
IUnknown_TranslateAcceleratorOCS(IUnknown
*lpUnknown
, LPMSG lpMsg
, DWORD dwModifiers
)
1854 IOleControlSite
* lpCSite
= NULL
;
1855 HRESULT hRet
= E_INVALIDARG
;
1857 TRACE("(%p,%p,0x%08x)\n", lpUnknown
, lpMsg
, dwModifiers
);
1860 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleControlSite
,
1862 if (SUCCEEDED(hRet
) && lpCSite
)
1864 hRet
= IOleControlSite_TranslateAccelerator(lpCSite
, lpMsg
, dwModifiers
);
1865 IOleControlSite_Release(lpCSite
);
1872 /*************************************************************************
1875 * Call IOleControlSite_OnFocus() on an object.
1878 * lpUnknown [I] Object supporting the IOleControlSite interface.
1879 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1883 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1885 HRESULT WINAPI
IUnknown_OnFocusOCS(IUnknown
*lpUnknown
, BOOL fGotFocus
)
1887 IOleControlSite
* lpCSite
= NULL
;
1888 HRESULT hRet
= E_FAIL
;
1890 TRACE("(%p, %d)\n", lpUnknown
, fGotFocus
);
1893 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleControlSite
,
1895 if (SUCCEEDED(hRet
) && lpCSite
)
1897 hRet
= IOleControlSite_OnFocus(lpCSite
, fGotFocus
);
1898 IOleControlSite_Release(lpCSite
);
1904 /*************************************************************************
1907 HRESULT WINAPI
IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown
, PVOID lpArg1
,
1908 PVOID lpArg2
, PVOID lpArg3
, PVOID lpArg4
)
1910 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1911 static const DWORD service_id
[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1912 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1913 static const DWORD function_id
[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1914 HRESULT hRet
= E_INVALIDARG
;
1915 LPUNKNOWN lpUnkInner
= NULL
; /* FIXME: Real type is unknown */
1917 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown
, lpArg1
, lpArg2
, lpArg3
, lpArg4
);
1919 if (lpUnknown
&& lpArg4
)
1921 hRet
= IUnknown_QueryService(lpUnknown
, (REFGUID
)service_id
,
1922 (REFGUID
)function_id
, (void**)&lpUnkInner
);
1924 if (SUCCEEDED(hRet
) && lpUnkInner
)
1926 /* FIXME: The type of service object requested is unknown, however
1927 * testing shows that its first method is called with 4 parameters.
1928 * Fake this by using IParseDisplayName_ParseDisplayName since the
1929 * signature and position in the vtable matches our unknown object type.
1931 hRet
= IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME
)lpUnkInner
,
1932 lpArg1
, lpArg2
, lpArg3
, lpArg4
);
1933 IUnknown_Release(lpUnkInner
);
1939 /*************************************************************************
1942 * Get a sub-menu from a menu item.
1945 * hMenu [I] Menu to get sub-menu from
1946 * uID [I] ID of menu item containing sub-menu
1949 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1951 HMENU WINAPI
SHGetMenuFromID(HMENU hMenu
, UINT uID
)
1955 TRACE("(%p,%u)\n", hMenu
, uID
);
1957 mi
.cbSize
= sizeof(mi
);
1958 mi
.fMask
= MIIM_SUBMENU
;
1960 if (!GetMenuItemInfoW(hMenu
, uID
, FALSE
, &mi
))
1966 /*************************************************************************
1969 * Get the color depth of the primary display.
1975 * The color depth of the primary display.
1977 DWORD WINAPI
SHGetCurColorRes(void)
1985 ret
= GetDeviceCaps(hdc
, BITSPIXEL
) * GetDeviceCaps(hdc
, PLANES
);
1990 /*************************************************************************
1993 * Wait for a message to arrive, with a timeout.
1996 * hand [I] Handle to query
1997 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
2000 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
2001 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
2002 * message is available.
2004 DWORD WINAPI
SHWaitForSendMessageThread(HANDLE hand
, DWORD dwTimeout
)
2006 DWORD dwEndTicks
= GetTickCount() + dwTimeout
;
2009 while ((dwRet
= MsgWaitForMultipleObjectsEx(1, &hand
, dwTimeout
, QS_SENDMESSAGE
, 0)) == 1)
2013 PeekMessageW(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
2015 if (dwTimeout
!= INFINITE
)
2017 if ((int)(dwTimeout
= dwEndTicks
- GetTickCount()) <= 0)
2018 return WAIT_TIMEOUT
;
2025 /*************************************************************************
2028 * Determine if a shell folder can be expanded.
2031 * lpFolder [I] Parent folder containing the object to test.
2032 * pidl [I] Id of the object to test.
2035 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2036 * Failure: E_INVALIDARG, if any argument is invalid.
2039 * If the object to be tested does not expose the IQueryInfo() interface it
2040 * will not be identified as an expandable folder.
2042 HRESULT WINAPI
SHIsExpandableFolder(LPSHELLFOLDER lpFolder
, LPCITEMIDLIST pidl
)
2044 HRESULT hRet
= E_INVALIDARG
;
2047 if (lpFolder
&& pidl
)
2049 hRet
= IShellFolder_GetUIObjectOf(lpFolder
, NULL
, 1, &pidl
, &IID_IQueryInfo
,
2050 NULL
, (void**)&lpInfo
);
2052 hRet
= S_FALSE
; /* Doesn't expose IQueryInfo */
2057 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2058 * currently used". Really? You wouldn't be holding out on me would you?
2060 hRet
= IQueryInfo_GetInfoFlags(lpInfo
, &dwFlags
);
2062 if (SUCCEEDED(hRet
))
2064 /* 0x2 is an undocumented flag apparently indicating expandability */
2065 hRet
= dwFlags
& 0x2 ? S_OK
: S_FALSE
;
2068 IQueryInfo_Release(lpInfo
);
2074 /*************************************************************************
2077 * Blank out a region of text by drawing the background only.
2080 * hDC [I] Device context to draw in
2081 * pRect [I] Area to draw in
2082 * cRef [I] Color to draw in
2087 DWORD WINAPI
SHFillRectClr(HDC hDC
, LPCRECT pRect
, COLORREF cRef
)
2089 COLORREF cOldColor
= SetBkColor(hDC
, cRef
);
2090 ExtTextOutA(hDC
, 0, 0, ETO_OPAQUE
, pRect
, 0, 0, 0);
2091 SetBkColor(hDC
, cOldColor
);
2095 /*************************************************************************
2098 * Return the value associated with a key in a map.
2101 * lpKeys [I] A list of keys of length iLen
2102 * lpValues [I] A list of values associated with lpKeys, of length iLen
2103 * iLen [I] Length of both lpKeys and lpValues
2104 * iKey [I] The key value to look up in lpKeys
2107 * The value in lpValues associated with iKey, or -1 if iKey is not
2111 * - If two elements in the map share the same key, this function returns
2112 * the value closest to the start of the map
2113 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2115 int WINAPI
SHSearchMapInt(const int *lpKeys
, const int *lpValues
, int iLen
, int iKey
)
2117 if (lpKeys
&& lpValues
)
2123 if (lpKeys
[i
] == iKey
)
2124 return lpValues
[i
]; /* Found */
2128 return -1; /* Not found */
2132 /*************************************************************************
2135 * Copy an interface pointer
2138 * lppDest [O] Destination for copy
2139 * lpUnknown [I] Source for copy
2144 VOID WINAPI
IUnknown_Set(IUnknown
**lppDest
, IUnknown
*lpUnknown
)
2146 TRACE("(%p,%p)\n", lppDest
, lpUnknown
);
2148 IUnknown_AtomicRelease(lppDest
);
2152 IUnknown_AddRef(lpUnknown
);
2153 *lppDest
= lpUnknown
;
2157 /*************************************************************************
2161 HRESULT WINAPI
MayQSForward(IUnknown
* lpUnknown
, PVOID lpReserved
,
2162 REFGUID riidCmdGrp
, ULONG cCmds
,
2163 OLECMD
*prgCmds
, OLECMDTEXT
* pCmdText
)
2165 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2166 lpUnknown
, lpReserved
, riidCmdGrp
, cCmds
, prgCmds
, pCmdText
);
2168 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2169 return DRAGDROP_E_NOTREGISTERED
;
2172 /*************************************************************************
2176 HRESULT WINAPI
MayExecForward(IUnknown
* lpUnknown
, INT iUnk
, REFGUID pguidCmdGroup
,
2177 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
* pvaIn
,
2180 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown
, iUnk
, pguidCmdGroup
,
2181 nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2182 return DRAGDROP_E_NOTREGISTERED
;
2185 /*************************************************************************
2189 HRESULT WINAPI
IsQSForward(REFGUID pguidCmdGroup
,ULONG cCmds
, OLECMD
*prgCmds
)
2191 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup
, cCmds
, prgCmds
);
2192 return DRAGDROP_E_NOTREGISTERED
;
2195 /*************************************************************************
2198 * Determine if a window is not a child of another window.
2201 * hParent [I] Suspected parent window
2202 * hChild [I] Suspected child window
2205 * TRUE: If hChild is a child window of hParent
2206 * FALSE: If hChild is not a child window of hParent, or they are equal
2208 BOOL WINAPI
SHIsChildOrSelf(HWND hParent
, HWND hChild
)
2210 TRACE("(%p,%p)\n", hParent
, hChild
);
2212 if (!hParent
|| !hChild
)
2214 else if(hParent
== hChild
)
2216 return !IsChild(hParent
, hChild
);
2219 /*************************************************************************
2220 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2225 DWORD num_items
; /* Number of elements inserted */
2226 void *mem
; /* Ptr to array */
2227 DWORD blocks_alloced
; /* Number of elements allocated */
2228 BYTE inc
; /* Number of elements to grow by when we need to expand */
2229 BYTE block_size
; /* Size in bytes of an element */
2230 BYTE flags
; /* Flags */
2233 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2235 /*************************************************************************
2238 * Initialize an FDSA array.
2240 BOOL WINAPI
FDSA_Initialize(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
2243 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size
, inc
, info
, mem
, init_blocks
);
2249 memset(mem
, 0, block_size
* init_blocks
);
2251 info
->num_items
= 0;
2254 info
->blocks_alloced
= init_blocks
;
2255 info
->block_size
= block_size
;
2261 /*************************************************************************
2264 * Destroy an FDSA array
2266 BOOL WINAPI
FDSA_Destroy(FDSA_info
*info
)
2268 TRACE("(%p)\n", info
);
2270 if(info
->flags
& FDSA_FLAG_INTERNAL_ALLOC
)
2272 HeapFree(GetProcessHeap(), 0, info
->mem
);
2279 /*************************************************************************
2282 * Insert element into an FDSA array
2284 DWORD WINAPI
FDSA_InsertItem(FDSA_info
*info
, DWORD where
, const void *block
)
2286 TRACE("(%p 0x%08x %p)\n", info
, where
, block
);
2287 if(where
> info
->num_items
)
2288 where
= info
->num_items
;
2290 if(info
->num_items
>= info
->blocks_alloced
)
2292 DWORD size
= (info
->blocks_alloced
+ info
->inc
) * info
->block_size
;
2293 if(info
->flags
& 0x1)
2294 info
->mem
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, info
->mem
, size
);
2297 void *old_mem
= info
->mem
;
2298 info
->mem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
2299 memcpy(info
->mem
, old_mem
, info
->blocks_alloced
* info
->block_size
);
2301 info
->blocks_alloced
+= info
->inc
;
2305 if(where
< info
->num_items
)
2307 memmove((char*)info
->mem
+ (where
+ 1) * info
->block_size
,
2308 (char*)info
->mem
+ where
* info
->block_size
,
2309 (info
->num_items
- where
) * info
->block_size
);
2311 memcpy((char*)info
->mem
+ where
* info
->block_size
, block
, info
->block_size
);
2317 /*************************************************************************
2320 * Delete an element from an FDSA array.
2322 BOOL WINAPI
FDSA_DeleteItem(FDSA_info
*info
, DWORD where
)
2324 TRACE("(%p 0x%08x)\n", info
, where
);
2326 if(where
>= info
->num_items
)
2329 if(where
< info
->num_items
- 1)
2331 memmove((char*)info
->mem
+ where
* info
->block_size
,
2332 (char*)info
->mem
+ (where
+ 1) * info
->block_size
,
2333 (info
->num_items
- where
- 1) * info
->block_size
);
2335 memset((char*)info
->mem
+ (info
->num_items
- 1) * info
->block_size
,
2336 0, info
->block_size
);
2341 /*************************************************************************
2344 * Call IUnknown_QueryInterface() on a table of objects.
2348 * Failure: E_POINTER or E_NOINTERFACE.
2350 HRESULT WINAPI
QISearch(
2351 void *base
, /* [in] Table of interfaces */
2352 const QITAB
*table
, /* [in] Array of REFIIDs and indexes into the table */
2353 REFIID riid
, /* [in] REFIID to get interface for */
2354 void **ppv
) /* [out] Destination for interface pointer */
2360 TRACE("(%p %p %s %p)\n", base
, table
, debugstr_guid(riid
), ppv
);
2363 while (xmove
->piid
) {
2364 TRACE("trying (offset %d) %s\n", xmove
->dwOffset
, debugstr_guid(xmove
->piid
));
2365 if (IsEqualIID(riid
, xmove
->piid
)) {
2366 a_vtbl
= (IUnknown
*)(xmove
->dwOffset
+ (LPBYTE
)base
);
2367 TRACE("matched, returning (%p)\n", a_vtbl
);
2369 IUnknown_AddRef(a_vtbl
);
2375 if (IsEqualIID(riid
, &IID_IUnknown
)) {
2376 a_vtbl
= (IUnknown
*)(table
->dwOffset
+ (LPBYTE
)base
);
2377 TRACE("returning first for IUnknown (%p)\n", a_vtbl
);
2379 IUnknown_AddRef(a_vtbl
);
2383 ret
= E_NOINTERFACE
;
2387 TRACE("-- 0x%08x\n", ret
);
2391 /*************************************************************************
2394 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2397 * hWnd [I] Parent Window to set the property
2398 * id [I] Index of child Window to set the Font
2404 HRESULT WINAPI
SHSetDefaultDialogFont(HWND hWnd
, INT id
)
2406 FIXME("(%p, %d) stub\n", hWnd
, id
);
2410 /*************************************************************************
2413 * Remove the "PropDlgFont" property from a window.
2416 * hWnd [I] Window to remove the property from
2419 * A handle to the removed property, or NULL if it did not exist.
2421 HANDLE WINAPI
SHRemoveDefaultDialogFont(HWND hWnd
)
2425 TRACE("(%p)\n", hWnd
);
2427 hProp
= GetPropA(hWnd
, "PropDlgFont");
2431 DeleteObject(hProp
);
2432 hProp
= RemovePropA(hWnd
, "PropDlgFont");
2437 /*************************************************************************
2440 * Load the in-process server of a given GUID.
2443 * refiid [I] GUID of the server to load.
2446 * Success: A handle to the loaded server dll.
2447 * Failure: A NULL handle.
2449 HMODULE WINAPI
SHPinDllOfCLSID(REFIID refiid
)
2453 CHAR value
[MAX_PATH
], string
[MAX_PATH
];
2455 strcpy(string
, "CLSID\\");
2456 SHStringFromGUIDA(refiid
, string
+ 6, sizeof(string
)/sizeof(char) - 6);
2457 strcat(string
, "\\InProcServer32");
2460 RegOpenKeyExA(HKEY_CLASSES_ROOT
, string
, 0, 1, &newkey
);
2461 RegQueryValueExA(newkey
, 0, 0, &type
, (PBYTE
)value
, &count
);
2462 RegCloseKey(newkey
);
2463 return LoadLibraryExA(value
, 0, 0);
2466 /*************************************************************************
2469 * Unicode version of SHLWAPI_183.
2471 DWORD WINAPI
SHRegisterClassW(WNDCLASSW
* lpWndClass
)
2475 TRACE("(%p %s)\n",lpWndClass
->hInstance
, debugstr_w(lpWndClass
->lpszClassName
));
2477 if (GetClassInfoW(lpWndClass
->hInstance
, lpWndClass
->lpszClassName
, &WndClass
))
2479 return RegisterClassW(lpWndClass
);
2482 /*************************************************************************
2485 * Unregister a list of classes.
2488 * hInst [I] Application instance that registered the classes
2489 * lppClasses [I] List of class names
2490 * iCount [I] Number of names in lppClasses
2495 void WINAPI
SHUnregisterClassesA(HINSTANCE hInst
, LPCSTR
*lppClasses
, INT iCount
)
2499 TRACE("(%p,%p,%d)\n", hInst
, lppClasses
, iCount
);
2503 if (GetClassInfoA(hInst
, *lppClasses
, &WndClass
))
2504 UnregisterClassA(*lppClasses
, hInst
);
2510 /*************************************************************************
2513 * Unicode version of SHUnregisterClassesA.
2515 void WINAPI
SHUnregisterClassesW(HINSTANCE hInst
, LPCWSTR
*lppClasses
, INT iCount
)
2519 TRACE("(%p,%p,%d)\n", hInst
, lppClasses
, iCount
);
2523 if (GetClassInfoW(hInst
, *lppClasses
, &WndClass
))
2524 UnregisterClassW(*lppClasses
, hInst
);
2530 /*************************************************************************
2533 * Call The correct (Ascii/Unicode) default window procedure for a window.
2536 * hWnd [I] Window to call the default procedure for
2537 * uMessage [I] Message ID
2538 * wParam [I] WPARAM of message
2539 * lParam [I] LPARAM of message
2542 * The result of calling DefWindowProcA() or DefWindowProcW().
2544 LRESULT CALLBACK
SHDefWindowProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
2546 if (IsWindowUnicode(hWnd
))
2547 return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
2548 return DefWindowProcA(hWnd
, uMessage
, wParam
, lParam
);
2551 /*************************************************************************
2554 HRESULT WINAPI
IUnknown_GetSite(LPUNKNOWN lpUnknown
, REFIID iid
, PVOID
*lppSite
)
2556 HRESULT hRet
= E_INVALIDARG
;
2557 LPOBJECTWITHSITE lpSite
= NULL
;
2559 TRACE("(%p,%s,%p)\n", lpUnknown
, debugstr_guid(iid
), lppSite
);
2561 if (lpUnknown
&& iid
&& lppSite
)
2563 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IObjectWithSite
,
2565 if (SUCCEEDED(hRet
) && lpSite
)
2567 hRet
= IObjectWithSite_GetSite(lpSite
, iid
, lppSite
);
2568 IObjectWithSite_Release(lpSite
);
2574 /*************************************************************************
2577 * Create a worker window using CreateWindowExA().
2580 * wndProc [I] Window procedure
2581 * hWndParent [I] Parent window
2582 * dwExStyle [I] Extra style flags
2583 * dwStyle [I] Style flags
2584 * hMenu [I] Window menu
2585 * wnd_extra [I] Window extra bytes value
2588 * Success: The window handle of the newly created window.
2591 HWND WINAPI
SHCreateWorkerWindowA(LONG wndProc
, HWND hWndParent
, DWORD dwExStyle
,
2592 DWORD dwStyle
, HMENU hMenu
, LONG_PTR wnd_extra
)
2594 static const char szClass
[] = "WorkerA";
2598 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2599 wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, wnd_extra
);
2601 /* Create Window class */
2603 wc
.lpfnWndProc
= DefWindowProcA
;
2605 wc
.cbWndExtra
= sizeof(LONG_PTR
);
2606 wc
.hInstance
= shlwapi_hInstance
;
2608 wc
.hCursor
= LoadCursorA(NULL
, (LPSTR
)IDC_ARROW
);
2609 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2610 wc
.lpszMenuName
= NULL
;
2611 wc
.lpszClassName
= szClass
;
2613 SHRegisterClassA(&wc
);
2615 hWnd
= CreateWindowExA(dwExStyle
, szClass
, 0, dwStyle
, 0, 0, 0, 0,
2616 hWndParent
, hMenu
, shlwapi_hInstance
, 0);
2619 SetWindowLongPtrW(hWnd
, 0, wnd_extra
);
2621 if (wndProc
) SetWindowLongPtrA(hWnd
, GWLP_WNDPROC
, wndProc
);
2627 typedef struct tagPOLICYDATA
2629 DWORD policy
; /* flags value passed to SHRestricted */
2630 LPCWSTR appstr
; /* application str such as "Explorer" */
2631 LPCWSTR keystr
; /* name of the actual registry key / policy */
2632 } POLICYDATA
, *LPPOLICYDATA
;
2634 #define SHELL_NO_POLICY 0xffffffff
2636 /* default shell policy registry key */
2637 static const WCHAR strRegistryPolicyW
[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2638 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2639 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2640 '\\','P','o','l','i','c','i','e','s',0};
2642 /*************************************************************************
2645 * Retrieve a policy value from the registry.
2648 * lpSubKey [I] registry key name
2649 * lpSubName [I] subname of registry key
2650 * lpValue [I] value name of registry value
2653 * the value associated with the registry key or 0 if not found
2655 DWORD WINAPI
SHGetRestriction(LPCWSTR lpSubKey
, LPCWSTR lpSubName
, LPCWSTR lpValue
)
2657 DWORD retval
, datsize
= sizeof(retval
);
2661 lpSubKey
= strRegistryPolicyW
;
2663 retval
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, lpSubKey
, &hKey
);
2664 if (retval
!= ERROR_SUCCESS
)
2665 retval
= RegOpenKeyW(HKEY_CURRENT_USER
, lpSubKey
, &hKey
);
2666 if (retval
!= ERROR_SUCCESS
)
2669 SHGetValueW(hKey
, lpSubName
, lpValue
, NULL
, &retval
, &datsize
);
2674 /*************************************************************************
2677 * Helper function to retrieve the possibly cached value for a specific policy
2680 * policy [I] The policy to look for
2681 * initial [I] Main registry key to open, if NULL use default
2682 * polTable [I] Table of known policies, 0 terminated
2683 * polArr [I] Cache array of policy values
2686 * The retrieved policy value or 0 if not successful
2689 * This function is used by the native SHRestricted function to search for the
2690 * policy and cache it once retrieved. The current Wine implementation uses a
2691 * different POLICYDATA structure and implements a similar algorithm adapted to
2694 DWORD WINAPI
SHRestrictionLookup(
2697 LPPOLICYDATA polTable
,
2700 TRACE("(0x%08x %s %p %p)\n", policy
, debugstr_w(initial
), polTable
, polArr
);
2702 if (!polTable
|| !polArr
)
2705 for (;polTable
->policy
; polTable
++, polArr
++)
2707 if (policy
== polTable
->policy
)
2709 /* we have a known policy */
2711 /* check if this policy has been cached */
2712 if (*polArr
== SHELL_NO_POLICY
)
2713 *polArr
= SHGetRestriction(initial
, polTable
->appstr
, polTable
->keystr
);
2717 /* we don't know this policy, return 0 */
2718 TRACE("unknown policy: (%08x)\n", policy
);
2722 /*************************************************************************
2725 * Get an interface from an object.
2728 * Success: S_OK. ppv contains the requested interface.
2729 * Failure: An HRESULT error code.
2732 * This QueryInterface asks the inner object for an interface. In case
2733 * of aggregation this request would be forwarded by the inner to the
2734 * outer object. This function asks the inner object directly for the
2735 * interface circumventing the forwarding to the outer object.
2737 HRESULT WINAPI
SHWeakQueryInterface(
2738 IUnknown
* pUnk
, /* [in] Outer object */
2739 IUnknown
* pInner
, /* [in] Inner object */
2740 IID
* riid
, /* [in] Interface GUID to query for */
2741 LPVOID
* ppv
) /* [out] Destination for queried interface */
2743 HRESULT hret
= E_NOINTERFACE
;
2744 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk
,pInner
,debugstr_guid(riid
), ppv
);
2747 if(pUnk
&& pInner
) {
2748 hret
= IUnknown_QueryInterface(pInner
, riid
, ppv
);
2749 if (SUCCEEDED(hret
)) IUnknown_Release(pUnk
);
2751 TRACE("-- 0x%08x\n", hret
);
2755 /*************************************************************************
2758 * Move a reference from one interface to another.
2761 * lpDest [O] Destination to receive the reference
2762 * lppUnknown [O] Source to give up the reference to lpDest
2767 VOID WINAPI
SHWeakReleaseInterface(IUnknown
*lpDest
, IUnknown
**lppUnknown
)
2769 TRACE("(%p,%p)\n", lpDest
, lppUnknown
);
2774 IUnknown_AddRef(lpDest
);
2775 IUnknown_AtomicRelease(lppUnknown
); /* Release existing interface */
2779 /*************************************************************************
2782 * Convert an ASCII string of a CLSID into a CLSID.
2785 * idstr [I] String representing a CLSID in registry format
2786 * id [O] Destination for the converted CLSID
2789 * Success: TRUE. id contains the converted CLSID.
2792 BOOL WINAPI
GUIDFromStringA(LPCSTR idstr
, CLSID
*id
)
2795 MultiByteToWideChar(CP_ACP
, 0, idstr
, -1, wClsid
, sizeof(wClsid
)/sizeof(WCHAR
));
2796 return SUCCEEDED(CLSIDFromString(wClsid
, id
));
2799 /*************************************************************************
2802 * Unicode version of GUIDFromStringA.
2804 BOOL WINAPI
GUIDFromStringW(LPCWSTR idstr
, CLSID
*id
)
2806 return SUCCEEDED(CLSIDFromString((LPCOLESTR
)idstr
, id
));
2809 /*************************************************************************
2812 * Determine if the browser is integrated into the shell, and set a registry
2819 * 1, If the browser is not integrated.
2820 * 2, If the browser is integrated.
2823 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2824 * either set to TRUE, or removed depending on whether the browser is deemed
2827 DWORD WINAPI
WhichPlatform(void)
2829 static const char szIntegratedBrowser
[] = "IntegratedBrowser";
2830 static DWORD dwState
= 0;
2832 DWORD dwRet
, dwData
, dwSize
;
2838 /* If shell32 exports DllGetVersion(), the browser is integrated */
2840 hshell32
= LoadLibraryA("shell32.dll");
2843 FARPROC pDllGetVersion
;
2844 pDllGetVersion
= GetProcAddress(hshell32
, "DllGetVersion");
2845 dwState
= pDllGetVersion
? 2 : 1;
2846 FreeLibrary(hshell32
);
2849 /* Set or delete the key accordingly */
2850 dwRet
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
,
2851 "Software\\Microsoft\\Internet Explorer", 0,
2852 KEY_ALL_ACCESS
, &hKey
);
2855 dwRet
= RegQueryValueExA(hKey
, szIntegratedBrowser
, 0, 0,
2856 (LPBYTE
)&dwData
, &dwSize
);
2858 if (!dwRet
&& dwState
== 1)
2860 /* Value exists but browser is not integrated */
2861 RegDeleteValueA(hKey
, szIntegratedBrowser
);
2863 else if (dwRet
&& dwState
== 2)
2865 /* Browser is integrated but value does not exist */
2867 RegSetValueExA(hKey
, szIntegratedBrowser
, 0, REG_DWORD
,
2868 (LPBYTE
)&dwData
, sizeof(dwData
));
2875 /*************************************************************************
2878 * Unicode version of SHCreateWorkerWindowA.
2880 HWND WINAPI
SHCreateWorkerWindowW(LONG wndProc
, HWND hWndParent
, DWORD dwExStyle
,
2881 DWORD dwStyle
, HMENU hMenu
, LONG msg_result
)
2883 static const WCHAR szClass
[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
2887 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
2888 wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, msg_result
);
2890 /* If our OS is natively ANSI, use the ANSI version */
2891 if (GetVersion() & 0x80000000) /* not NT */
2893 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
2894 return SHCreateWorkerWindowA(wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, msg_result
);
2897 /* Create Window class */
2899 wc
.lpfnWndProc
= DefWindowProcW
;
2902 wc
.hInstance
= shlwapi_hInstance
;
2904 wc
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
2905 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2906 wc
.lpszMenuName
= NULL
;
2907 wc
.lpszClassName
= szClass
;
2909 SHRegisterClassW(&wc
);
2911 hWnd
= CreateWindowExW(dwExStyle
, szClass
, 0, dwStyle
, 0, 0, 0, 0,
2912 hWndParent
, hMenu
, shlwapi_hInstance
, 0);
2915 SetWindowLongPtrW(hWnd
, DWLP_MSGRESULT
, msg_result
);
2917 if (wndProc
) SetWindowLongPtrW(hWnd
, GWLP_WNDPROC
, wndProc
);
2923 /*************************************************************************
2926 * Get and show a context menu from a shell folder.
2929 * hWnd [I] Window displaying the shell folder
2930 * lpFolder [I] IShellFolder interface
2931 * lpApidl [I] Id for the particular folder desired
2935 * Failure: An HRESULT error code indicating the error.
2937 HRESULT WINAPI
SHInvokeDefaultCommand(HWND hWnd
, IShellFolder
* lpFolder
, LPCITEMIDLIST lpApidl
)
2939 TRACE("%p %p %p\n", hWnd
, lpFolder
, lpApidl
);
2940 return SHInvokeCommand(hWnd
, lpFolder
, lpApidl
, FALSE
);
2943 /*************************************************************************
2946 * _SHPackDispParamsV
2948 HRESULT WINAPI
SHPackDispParamsV(DISPPARAMS
*params
, VARIANTARG
*args
, UINT cnt
, __ms_va_list valist
)
2952 TRACE("(%p %p %u ...)\n", params
, args
, cnt
);
2954 params
->rgvarg
= args
;
2955 params
->rgdispidNamedArgs
= NULL
;
2956 params
->cArgs
= cnt
;
2957 params
->cNamedArgs
= 0;
2961 while(iter
-- > args
) {
2962 V_VT(iter
) = va_arg(valist
, enum VARENUM
);
2964 TRACE("vt=%d\n", V_VT(iter
));
2966 if(V_VT(iter
) & VT_BYREF
) {
2967 V_BYREF(iter
) = va_arg(valist
, LPVOID
);
2969 switch(V_VT(iter
)) {
2971 V_I4(iter
) = va_arg(valist
, LONG
);
2974 V_BSTR(iter
) = va_arg(valist
, BSTR
);
2977 V_DISPATCH(iter
) = va_arg(valist
, IDispatch
*);
2980 V_BOOL(iter
) = va_arg(valist
, int);
2983 V_UNKNOWN(iter
) = va_arg(valist
, IUnknown
*);
2987 V_I4(iter
) = va_arg(valist
, LONG
);
2995 /*************************************************************************
3000 HRESULT WINAPIV
SHPackDispParams(DISPPARAMS
*params
, VARIANTARG
*args
, UINT cnt
, ...)
3002 __ms_va_list valist
;
3005 __ms_va_start(valist
, cnt
);
3006 hres
= SHPackDispParamsV(params
, args
, cnt
, valist
);
3007 __ms_va_end(valist
);
3011 /*************************************************************************
3012 * SHLWAPI_InvokeByIID
3014 * This helper function calls IDispatch::Invoke for each sink
3015 * which implements given iid or IDispatch.
3018 static HRESULT
SHLWAPI_InvokeByIID(
3019 IConnectionPoint
* iCP
,
3022 DISPPARAMS
* dispParams
)
3024 IEnumConnections
*enumerator
;
3026 static DISPPARAMS empty
= {NULL
, NULL
, 0, 0};
3027 DISPPARAMS
* params
= dispParams
;
3029 HRESULT result
= IConnectionPoint_EnumConnections(iCP
, &enumerator
);
3033 /* Invoke is never happening with an NULL dispParams */
3037 while(IEnumConnections_Next(enumerator
, 1, &rgcd
, NULL
)==S_OK
)
3039 IDispatch
*dispIface
;
3040 if ((iid
&& SUCCEEDED(IUnknown_QueryInterface(rgcd
.pUnk
, iid
, (LPVOID
*)&dispIface
))) ||
3041 SUCCEEDED(IUnknown_QueryInterface(rgcd
.pUnk
, &IID_IDispatch
, (LPVOID
*)&dispIface
)))
3043 IDispatch_Invoke(dispIface
, dispId
, &IID_NULL
, 0, DISPATCH_METHOD
, params
, NULL
, NULL
, NULL
);
3044 IDispatch_Release(dispIface
);
3046 IUnknown_Release(rgcd
.pUnk
);
3049 IEnumConnections_Release(enumerator
);
3054 /*************************************************************************
3055 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3057 HRESULT WINAPI
IConnectionPoint_InvokeWithCancel( IConnectionPoint
* iCP
,
3058 DISPID dispId
, DISPPARAMS
* dispParams
,
3059 DWORD unknown1
, DWORD unknown2
)
3064 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP
, dispId
, dispParams
, unknown1
, unknown2
);
3066 result
= IConnectionPoint_GetConnectionInterface(iCP
, &iid
);
3067 if (SUCCEEDED(result
))
3068 result
= SHLWAPI_InvokeByIID(iCP
, &iid
, dispId
, dispParams
);
3070 result
= SHLWAPI_InvokeByIID(iCP
, NULL
, dispId
, dispParams
);
3076 /*************************************************************************
3079 * IConnectionPoint_SimpleInvoke
3081 HRESULT WINAPI
IConnectionPoint_SimpleInvoke(
3082 IConnectionPoint
* iCP
,
3084 DISPPARAMS
* dispParams
)
3089 TRACE("(%p)->(0x%x %p)\n",iCP
,dispId
,dispParams
);
3091 result
= IConnectionPoint_GetConnectionInterface(iCP
, &iid
);
3092 if (SUCCEEDED(result
))
3093 result
= SHLWAPI_InvokeByIID(iCP
, &iid
, dispId
, dispParams
);
3095 result
= SHLWAPI_InvokeByIID(iCP
, NULL
, dispId
, dispParams
);
3100 /*************************************************************************
3103 * Notify an IConnectionPoint object of changes.
3106 * lpCP [I] Object to notify
3111 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3112 * IConnectionPoint interface.
3114 HRESULT WINAPI
IConnectionPoint_OnChanged(IConnectionPoint
* lpCP
, DISPID dispID
)
3116 IEnumConnections
*lpEnum
;
3117 HRESULT hRet
= E_NOINTERFACE
;
3119 TRACE("(%p,0x%8X)\n", lpCP
, dispID
);
3121 /* Get an enumerator for the connections */
3123 hRet
= IConnectionPoint_EnumConnections(lpCP
, &lpEnum
);
3125 if (SUCCEEDED(hRet
))
3127 IPropertyNotifySink
*lpSink
;
3128 CONNECTDATA connData
;
3131 /* Call OnChanged() for every notify sink in the connection point */
3132 while (IEnumConnections_Next(lpEnum
, 1, &connData
, &ulFetched
) == S_OK
)
3134 if (SUCCEEDED(IUnknown_QueryInterface(connData
.pUnk
, &IID_IPropertyNotifySink
, (void**)&lpSink
)) &&
3137 IPropertyNotifySink_OnChanged(lpSink
, dispID
);
3138 IPropertyNotifySink_Release(lpSink
);
3140 IUnknown_Release(connData
.pUnk
);
3143 IEnumConnections_Release(lpEnum
);
3148 /*************************************************************************
3151 * IUnknown_CPContainerInvokeParam
3153 HRESULT WINAPIV
IUnknown_CPContainerInvokeParam(
3154 IUnknown
*container
,
3161 IConnectionPoint
*iCP
;
3162 IConnectionPointContainer
*iCPC
;
3163 DISPPARAMS dispParams
= {buffer
, NULL
, cParams
, 0};
3164 __ms_va_list valist
;
3167 return E_NOINTERFACE
;
3169 result
= IUnknown_QueryInterface(container
, &IID_IConnectionPointContainer
,(LPVOID
*) &iCPC
);
3173 result
= IConnectionPointContainer_FindConnectionPoint(iCPC
, riid
, &iCP
);
3174 IConnectionPointContainer_Release(iCPC
);
3178 __ms_va_start(valist
, cParams
);
3179 SHPackDispParamsV(&dispParams
, buffer
, cParams
, valist
);
3180 __ms_va_end(valist
);
3182 result
= SHLWAPI_InvokeByIID(iCP
, riid
, dispId
, &dispParams
);
3183 IConnectionPoint_Release(iCP
);
3188 /*************************************************************************
3191 * Notify an IConnectionPointContainer object of changes.
3194 * lpUnknown [I] Object to notify
3199 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3200 * IConnectionPointContainer interface.
3202 HRESULT WINAPI
IUnknown_CPContainerOnChanged(IUnknown
*lpUnknown
, DISPID dispID
)
3204 IConnectionPointContainer
* lpCPC
= NULL
;
3205 HRESULT hRet
= E_NOINTERFACE
;
3207 TRACE("(%p,0x%8X)\n", lpUnknown
, dispID
);
3210 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IConnectionPointContainer
, (void**)&lpCPC
);
3212 if (SUCCEEDED(hRet
))
3214 IConnectionPoint
* lpCP
;
3216 hRet
= IConnectionPointContainer_FindConnectionPoint(lpCPC
, &IID_IPropertyNotifySink
, &lpCP
);
3217 IConnectionPointContainer_Release(lpCPC
);
3219 hRet
= IConnectionPoint_OnChanged(lpCP
, dispID
);
3220 IConnectionPoint_Release(lpCP
);
3225 /*************************************************************************
3230 BOOL WINAPI
PlaySoundWrapW(LPCWSTR pszSound
, HMODULE hmod
, DWORD fdwSound
)
3232 return PlaySoundW(pszSound
, hmod
, fdwSound
);
3235 /*************************************************************************
3238 * Retrieve a key value from an INI file. See GetPrivateProfileString for
3242 * appName [I] The section in the INI file that contains the key
3243 * keyName [I] The key to be retrieved
3244 * out [O] The buffer into which the key's value will be copied
3245 * outLen [I] The length of the `out' buffer
3246 * filename [I] The location of the INI file
3249 * Length of string copied into `out'.
3251 DWORD WINAPI
SHGetIniStringW(LPCWSTR appName
, LPCWSTR keyName
, LPWSTR out
,
3252 DWORD outLen
, LPCWSTR filename
)
3257 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName
), debugstr_w(keyName
),
3258 out
, outLen
, debugstr_w(filename
));
3263 buf
= HeapAlloc(GetProcessHeap(), 0, outLen
* sizeof(WCHAR
));
3269 ret
= GetPrivateProfileStringW(appName
, keyName
, NULL
, buf
, outLen
, filename
);
3275 HeapFree(GetProcessHeap(), 0, buf
);
3277 return strlenW(out
);
3280 /*************************************************************************
3283 * Set a key value in an INI file. See WritePrivateProfileString for
3287 * appName [I] The section in the INI file that contains the key
3288 * keyName [I] The key to be set
3289 * str [O] The value of the key
3290 * filename [I] The location of the INI file
3296 BOOL WINAPI
SHSetIniStringW(LPCWSTR appName
, LPCWSTR keyName
, LPCWSTR str
,
3299 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName
), keyName
, debugstr_w(str
),
3300 debugstr_w(filename
));
3302 return WritePrivateProfileStringW(appName
, keyName
, str
, filename
);
3305 /*************************************************************************
3308 * See SHGetFileInfoW.
3310 DWORD WINAPI
SHGetFileInfoWrapW(LPCWSTR path
, DWORD dwFileAttributes
,
3311 SHFILEINFOW
*psfi
, UINT sizeofpsfi
, UINT flags
)
3313 return SHGetFileInfoW(path
, dwFileAttributes
, psfi
, sizeofpsfi
, flags
);
3316 /*************************************************************************
3319 * See DragQueryFileW.
3321 UINT WINAPI
DragQueryFileWrapW(HDROP hDrop
, UINT lFile
, LPWSTR lpszFile
, UINT lLength
)
3323 return DragQueryFileW(hDrop
, lFile
, lpszFile
, lLength
);
3326 /*************************************************************************
3329 * See SHBrowseForFolderW.
3331 LPITEMIDLIST WINAPI
SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi
)
3333 return SHBrowseForFolderW(lpBi
);
3336 /*************************************************************************
3339 * See SHGetPathFromIDListW.
3341 BOOL WINAPI
SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl
,LPWSTR pszPath
)
3343 return SHGetPathFromIDListW(pidl
, pszPath
);
3346 /*************************************************************************
3349 * See ShellExecuteExW.
3351 BOOL WINAPI
ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo
)
3353 return ShellExecuteExW(lpExecInfo
);
3356 /*************************************************************************
3359 * See SHFileOperationW.
3361 INT WINAPI
SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp
)
3363 return SHFileOperationW(lpFileOp
);
3366 /*************************************************************************
3370 PVOID WINAPI
SHInterlockedCompareExchange( PVOID
*dest
, PVOID xchg
, PVOID compare
)
3372 return InterlockedCompareExchangePointer( dest
, xchg
, compare
);
3375 /*************************************************************************
3378 * See GetFileVersionInfoSizeW.
3380 DWORD WINAPI
GetFileVersionInfoSizeWrapW( LPCWSTR filename
, LPDWORD handle
)
3382 return GetFileVersionInfoSizeW( filename
, handle
);
3385 /*************************************************************************
3388 * See GetFileVersionInfoW.
3390 BOOL WINAPI
GetFileVersionInfoWrapW( LPCWSTR filename
, DWORD handle
,
3391 DWORD datasize
, LPVOID data
)
3393 return GetFileVersionInfoW( filename
, handle
, datasize
, data
);
3396 /*************************************************************************
3399 * See VerQueryValueW.
3401 WORD WINAPI
VerQueryValueWrapW( LPVOID pBlock
, LPCWSTR lpSubBlock
,
3402 LPVOID
*lplpBuffer
, UINT
*puLen
)
3404 return VerQueryValueW( pBlock
, lpSubBlock
, lplpBuffer
, puLen
);
3407 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3408 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3409 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3411 /*************************************************************************
3414 * Change the modality of a shell object.
3417 * lpUnknown [I] Object to make modeless
3418 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3421 * Success: S_OK. The modality lpUnknown is changed.
3422 * Failure: An HRESULT error code indicating the error.
3425 * lpUnknown must support the IOleInPlaceFrame interface, the
3426 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3427 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3428 * or this call will fail.
3430 HRESULT WINAPI
IUnknown_EnableModeless(IUnknown
*lpUnknown
, BOOL bModeless
)
3435 TRACE("(%p,%d)\n", lpUnknown
, bModeless
);
3440 if (IsIface(IOleInPlaceActiveObject
))
3441 EnableModeless(IOleInPlaceActiveObject
);
3442 else if (IsIface(IOleInPlaceFrame
))
3443 EnableModeless(IOleInPlaceFrame
);
3444 else if (IsIface(IShellBrowser
))
3445 EnableModeless(IShellBrowser
);
3446 else if (IsIface(IInternetSecurityMgrSite
))
3447 EnableModeless(IInternetSecurityMgrSite
);
3448 else if (IsIface(IDocHostUIHandler
))
3449 EnableModeless(IDocHostUIHandler
);
3453 IUnknown_Release(lpObj
);
3457 /*************************************************************************
3460 * See SHGetNewLinkInfoW.
3462 BOOL WINAPI
SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo
, LPCWSTR pszDir
, LPWSTR pszName
,
3463 BOOL
*pfMustCopy
, UINT uFlags
)
3465 return SHGetNewLinkInfoW(pszLinkTo
, pszDir
, pszName
, pfMustCopy
, uFlags
);
3468 /*************************************************************************
3471 * See SHDefExtractIconW.
3473 UINT WINAPI
SHDefExtractIconWrapW(LPCWSTR pszIconFile
, int iIndex
, UINT uFlags
, HICON
* phiconLarge
,
3474 HICON
* phiconSmall
, UINT nIconSize
)
3476 return SHDefExtractIconW(pszIconFile
, iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
3479 /*************************************************************************
3482 * Get and show a context menu from a shell folder.
3485 * hWnd [I] Window displaying the shell folder
3486 * lpFolder [I] IShellFolder interface
3487 * lpApidl [I] Id for the particular folder desired
3488 * bInvokeDefault [I] Whether to invoke the default menu item
3491 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3493 * Failure: An HRESULT error code indicating the error.
3495 HRESULT WINAPI
SHInvokeCommand(HWND hWnd
, IShellFolder
* lpFolder
, LPCITEMIDLIST lpApidl
, BOOL bInvokeDefault
)
3497 IContextMenu
*iContext
;
3500 TRACE("(%p, %p, %p, %d)\n", hWnd
, lpFolder
, lpApidl
, bInvokeDefault
);
3505 /* Get the context menu from the shell folder */
3506 hRet
= IShellFolder_GetUIObjectOf(lpFolder
, hWnd
, 1, &lpApidl
,
3507 &IID_IContextMenu
, 0, (void**)&iContext
);
3508 if (SUCCEEDED(hRet
))
3511 if ((hMenu
= CreatePopupMenu()))
3514 DWORD dwDefaultId
= 0;
3516 /* Add the context menu entries to the popup */
3517 hQuery
= IContextMenu_QueryContextMenu(iContext
, hMenu
, 0, 1, 0x7FFF,
3518 bInvokeDefault
? CMF_NORMAL
: CMF_DEFAULTONLY
);
3520 if (SUCCEEDED(hQuery
))
3522 if (bInvokeDefault
&&
3523 (dwDefaultId
= GetMenuDefaultItem(hMenu
, 0, 0)) != (UINT
)-1)
3525 CMINVOKECOMMANDINFO cmIci
;
3526 /* Invoke the default item */
3527 memset(&cmIci
,0,sizeof(cmIci
));
3528 cmIci
.cbSize
= sizeof(cmIci
);
3529 cmIci
.fMask
= CMIC_MASK_ASYNCOK
;
3531 cmIci
.lpVerb
= MAKEINTRESOURCEA(dwDefaultId
);
3532 cmIci
.nShow
= SW_SCROLLCHILDREN
;
3534 hRet
= IContextMenu_InvokeCommand(iContext
, &cmIci
);
3539 IContextMenu_Release(iContext
);
3544 /*************************************************************************
3549 HICON WINAPI
ExtractIconWrapW(HINSTANCE hInstance
, LPCWSTR lpszExeFileName
,
3552 return ExtractIconW(hInstance
, lpszExeFileName
, nIconIndex
);
3555 /*************************************************************************
3558 * Load a library from the directory of a particular process.
3561 * new_mod [I] Library name
3562 * inst_hwnd [I] Module whose directory is to be used
3563 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3566 * Success: A handle to the loaded module
3567 * Failure: A NULL handle.
3569 HMODULE WINAPI
MLLoadLibraryA(LPCSTR new_mod
, HMODULE inst_hwnd
, DWORD dwCrossCodePage
)
3571 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3573 * FIXME: Native shows calls to:
3574 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3576 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3577 * RegQueryValueExA for "LPKInstalled"
3579 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3580 * RegQueryValueExA for "ResourceLocale"
3582 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3583 * RegQueryValueExA for "Locale"
3585 * and then tests the Locale ("en" for me).
3587 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3589 CHAR mod_path
[2*MAX_PATH
];
3593 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod
), inst_hwnd
, dwCrossCodePage
);
3594 len
= GetModuleFileNameA(inst_hwnd
, mod_path
, sizeof(mod_path
));
3595 if (!len
|| len
>= sizeof(mod_path
)) return NULL
;
3597 ptr
= strrchr(mod_path
, '\\');
3599 strcpy(ptr
+1, new_mod
);
3600 TRACE("loading %s\n", debugstr_a(mod_path
));
3601 return LoadLibraryA(mod_path
);
3606 /*************************************************************************
3609 * Unicode version of MLLoadLibraryA.
3611 HMODULE WINAPI
MLLoadLibraryW(LPCWSTR new_mod
, HMODULE inst_hwnd
, DWORD dwCrossCodePage
)
3613 WCHAR mod_path
[2*MAX_PATH
];
3617 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod
), inst_hwnd
, dwCrossCodePage
);
3618 len
= GetModuleFileNameW(inst_hwnd
, mod_path
, sizeof(mod_path
) / sizeof(WCHAR
));
3619 if (!len
|| len
>= sizeof(mod_path
) / sizeof(WCHAR
)) return NULL
;
3621 ptr
= strrchrW(mod_path
, '\\');
3623 strcpyW(ptr
+1, new_mod
);
3624 TRACE("loading %s\n", debugstr_w(mod_path
));
3625 return LoadLibraryW(mod_path
);
3630 /*************************************************************************
3631 * ColorAdjustLuma [SHLWAPI.@]
3633 * Adjust the luminosity of a color
3636 * cRGB [I] RGB value to convert
3637 * dwLuma [I] Luma adjustment
3638 * bUnknown [I] Unknown
3641 * The adjusted RGB color.
3643 COLORREF WINAPI
ColorAdjustLuma(COLORREF cRGB
, int dwLuma
, BOOL bUnknown
)
3645 TRACE("(0x%8x,%d,%d)\n", cRGB
, dwLuma
, bUnknown
);
3651 ColorRGBToHLS(cRGB
, &wH
, &wL
, &wS
);
3653 FIXME("Ignoring luma adjustment\n");
3655 /* FIXME: The adjustment is not linear */
3657 cRGB
= ColorHLSToRGB(wH
, wL
, wS
);
3662 /*************************************************************************
3665 * See GetSaveFileNameW.
3667 BOOL WINAPI
GetSaveFileNameWrapW(LPOPENFILENAMEW ofn
)
3669 return GetSaveFileNameW(ofn
);
3672 /*************************************************************************
3675 * See WNetRestoreConnectionW.
3677 DWORD WINAPI
WNetRestoreConnectionWrapW(HWND hwndOwner
, LPWSTR lpszDevice
)
3679 return WNetRestoreConnectionW(hwndOwner
, lpszDevice
);
3682 /*************************************************************************
3685 * See WNetGetLastErrorW.
3687 DWORD WINAPI
WNetGetLastErrorWrapW(LPDWORD lpError
, LPWSTR lpErrorBuf
, DWORD nErrorBufSize
,
3688 LPWSTR lpNameBuf
, DWORD nNameBufSize
)
3690 return WNetGetLastErrorW(lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
3693 /*************************************************************************
3696 * See PageSetupDlgW.
3698 BOOL WINAPI
PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg
)
3700 return PageSetupDlgW(pagedlg
);
3703 /*************************************************************************
3708 BOOL WINAPI
PrintDlgWrapW(LPPRINTDLGW printdlg
)
3710 return PrintDlgW(printdlg
);
3713 /*************************************************************************
3716 * See GetOpenFileNameW.
3718 BOOL WINAPI
GetOpenFileNameWrapW(LPOPENFILENAMEW ofn
)
3720 return GetOpenFileNameW(ofn
);
3723 /*************************************************************************
3726 HRESULT WINAPI
SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder
, HWND hwnd
, SHCONTF flags
, IEnumIDList
**ppenum
)
3728 /* Windows attempts to get an IPersist interface and, if that fails, an
3729 * IPersistFolder interface on the folder passed-in here. If one of those
3730 * interfaces is available, it then calls GetClassID on the folder... and
3731 * then calls IShellFolder_EnumObjects no matter what, even crashing if
3732 * lpFolder isn't actually an IShellFolder object. The purpose of getting
3733 * the ClassID is unknown, so we don't do it here.
3735 * For discussion and detailed tests, see:
3736 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated"
3737 * wine-devel mailing list, 3 Jun 2010
3740 return IShellFolder_EnumObjects(lpFolder
, hwnd
, flags
, ppenum
);
3743 /* INTERNAL: Map from HLS color space to RGB */
3744 static WORD
ConvertHue(int wHue
, WORD wMid1
, WORD wMid2
)
3746 wHue
= wHue
> 240 ? wHue
- 240 : wHue
< 0 ? wHue
+ 240 : wHue
;
3750 else if (wHue
> 120)
3755 return ((wHue
* (wMid2
- wMid1
) + 20) / 40) + wMid1
;
3758 /* Convert to RGB and scale into RGB range (0..255) */
3759 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3761 /*************************************************************************
3762 * ColorHLSToRGB [SHLWAPI.@]
3764 * Convert from hls color space into an rgb COLORREF.
3767 * wHue [I] Hue amount
3768 * wLuminosity [I] Luminosity amount
3769 * wSaturation [I] Saturation amount
3772 * A COLORREF representing the converted color.
3775 * Input hls values are constrained to the range (0..240).
3777 COLORREF WINAPI
ColorHLSToRGB(WORD wHue
, WORD wLuminosity
, WORD wSaturation
)
3783 WORD wGreen
, wBlue
, wMid1
, wMid2
;
3785 if (wLuminosity
> 120)
3786 wMid2
= wSaturation
+ wLuminosity
- (wSaturation
* wLuminosity
+ 120) / 240;
3788 wMid2
= ((wSaturation
+ 240) * wLuminosity
+ 120) / 240;
3790 wMid1
= wLuminosity
* 2 - wMid2
;
3792 wRed
= GET_RGB(wHue
+ 80);
3793 wGreen
= GET_RGB(wHue
);
3794 wBlue
= GET_RGB(wHue
- 80);
3796 return RGB(wRed
, wGreen
, wBlue
);
3799 wRed
= wLuminosity
* 255 / 240;
3800 return RGB(wRed
, wRed
, wRed
);
3803 /*************************************************************************
3806 * Get the current docking status of the system.
3809 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3812 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3815 DWORD WINAPI
SHGetMachineInfo(DWORD dwFlags
)
3817 HW_PROFILE_INFOA hwInfo
;
3819 TRACE("(0x%08x)\n", dwFlags
);
3821 GetCurrentHwProfileA(&hwInfo
);
3822 switch (hwInfo
.dwDockInfo
& (DOCKINFO_DOCKED
|DOCKINFO_UNDOCKED
))
3824 case DOCKINFO_DOCKED
:
3825 case DOCKINFO_UNDOCKED
:
3826 return hwInfo
.dwDockInfo
& (DOCKINFO_DOCKED
|DOCKINFO_UNDOCKED
);
3832 /*************************************************************************
3836 DWORD WINAPI
SHWinHelpOnDemandW(HWND hwnd
, LPCWSTR helpfile
, DWORD flags1
, VOID
*ptr1
, DWORD flags2
)
3839 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd
, debugstr_w(helpfile
), flags1
, ptr1
, flags2
);
3843 /*************************************************************************
3847 DWORD WINAPI
SHWinHelpOnDemandA(HWND hwnd
, LPCSTR helpfile
, DWORD flags1
, VOID
*ptr1
, DWORD flags2
)
3850 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd
, debugstr_a(helpfile
), flags1
, ptr1
, flags2
);
3854 /*************************************************************************
3857 * Function seems to do FreeLibrary plus other things.
3859 * FIXME native shows the following calls:
3860 * RtlEnterCriticalSection
3862 * GetProcAddress(Comctl32??, 150L)
3864 * RtlLeaveCriticalSection
3865 * followed by the FreeLibrary.
3866 * The above code may be related to .377 above.
3868 BOOL WINAPI
MLFreeLibrary(HMODULE hModule
)
3870 FIXME("(%p) semi-stub\n", hModule
);
3871 return FreeLibrary(hModule
);
3874 /*************************************************************************
3877 BOOL WINAPI
SHFlushSFCacheWrap(void) {
3882 /*************************************************************************
3884 * FIXME I have no idea what this function does or what its arguments are.
3886 BOOL WINAPI
MLIsMLHInstance(HINSTANCE hInst
)
3888 FIXME("(%p) stub\n", hInst
);
3893 /*************************************************************************
3896 DWORD WINAPI
MLSetMLHInstance(HINSTANCE hInst
, HANDLE hHeap
)
3898 FIXME("(%p,%p) stub\n", hInst
, hHeap
);
3899 return E_FAIL
; /* This is what is used if shlwapi not loaded */
3902 /*************************************************************************
3905 DWORD WINAPI
MLClearMLHInstance(DWORD x
)
3907 FIXME("(0x%08x)stub\n", x
);
3911 /*************************************************************************
3914 * See SHSendMessageBroadcastW
3917 DWORD WINAPI
SHSendMessageBroadcastA(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3919 return SendMessageTimeoutA(HWND_BROADCAST
, uMsg
, wParam
, lParam
,
3920 SMTO_ABORTIFHUNG
, 2000, NULL
);
3923 /*************************************************************************
3926 * A wrapper for sending Broadcast Messages to all top level Windows
3929 DWORD WINAPI
SHSendMessageBroadcastW(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3931 return SendMessageTimeoutW(HWND_BROADCAST
, uMsg
, wParam
, lParam
,
3932 SMTO_ABORTIFHUNG
, 2000, NULL
);
3935 /*************************************************************************
3938 * Convert a Unicode string CLSID into a CLSID.
3941 * idstr [I] string containing a CLSID in text form
3942 * id [O] CLSID extracted from the string
3945 * S_OK on success or E_INVALIDARG on failure
3947 HRESULT WINAPI
CLSIDFromStringWrap(LPCWSTR idstr
, CLSID
*id
)
3949 return CLSIDFromString((LPCOLESTR
)idstr
, id
);
3952 /*************************************************************************
3955 * Determine if the OS supports a given feature.
3958 * dwFeature [I] Feature requested (undocumented)
3961 * TRUE If the feature is available.
3962 * FALSE If the feature is not available.
3964 BOOL WINAPI
IsOS(DWORD feature
)
3966 OSVERSIONINFOA osvi
;
3967 DWORD platform
, majorv
, minorv
;
3969 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
3970 if(!GetVersionExA(&osvi
)) {
3971 ERR("GetVersionEx failed\n");
3975 majorv
= osvi
.dwMajorVersion
;
3976 minorv
= osvi
.dwMinorVersion
;
3977 platform
= osvi
.dwPlatformId
;
3979 #define ISOS_RETURN(x) \
3980 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3984 case OS_WIN32SORGREATER
:
3985 ISOS_RETURN(platform
== VER_PLATFORM_WIN32s
3986 || platform
== VER_PLATFORM_WIN32_WINDOWS
)
3988 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
3989 case OS_WIN95ORGREATER
:
3990 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
)
3991 case OS_NT4ORGREATER
:
3992 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 4)
3993 case OS_WIN2000ORGREATER_ALT
:
3994 case OS_WIN2000ORGREATER
:
3995 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5)
3996 case OS_WIN98ORGREATER
:
3997 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
>= 10)
3999 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
== 10)
4001 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5)
4002 case OS_WIN2000SERVER
:
4003 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
4004 case OS_WIN2000ADVSERVER
:
4005 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
4006 case OS_WIN2000DATACENTER
:
4007 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
4008 case OS_WIN2000TERMINAL
:
4009 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
4011 FIXME("(OS_EMBEDDED) What should we return here?\n");
4013 case OS_TERMINALCLIENT
:
4014 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
4016 case OS_TERMINALREMOTEADMIN
:
4017 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
4020 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
== 0)
4021 case OS_MEORGREATER
:
4022 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
>= 90)
4023 case OS_XPORGREATER
:
4024 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5 && minorv
>= 1)
4026 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5 && minorv
>= 1)
4027 case OS_PROFESSIONAL
:
4028 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4030 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4032 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5)
4034 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4035 case OS_TERMINALSERVER
:
4036 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4037 case OS_PERSONALTERMINALSERVER
:
4038 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& minorv
>= 1 && majorv
>= 5)
4039 case OS_FASTUSERSWITCHING
:
4040 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
4042 case OS_WELCOMELOGONUI
:
4043 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
4045 case OS_DOMAINMEMBER
:
4046 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
4049 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4053 IsWow64Process(GetCurrentProcess(), &is_wow64
);
4057 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4058 case OS_SMALLBUSINESSSERVER
:
4059 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4061 FIXME("(OS_TABLEPC) What should we return here?\n");
4063 case OS_SERVERADMINUI
:
4064 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
4066 case OS_MEDIACENTER
:
4067 FIXME("(OS_MEDIACENTER) What should we return here?\n");
4070 FIXME("(OS_APPLIANCE) What should we return here?\n");
4072 case 0x25: /*OS_VISTAORGREATER*/
4073 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 6)
4078 WARN("(0x%x) unknown parameter\n",feature
);
4083 /*************************************************************************
4086 HRESULT WINAPI
SHLoadRegUIStringW(HKEY hkey
, LPCWSTR value
, LPWSTR buf
, DWORD size
)
4088 DWORD type
, sz
= size
;
4090 if(RegQueryValueExW(hkey
, value
, NULL
, &type
, (LPBYTE
)buf
, &sz
) != ERROR_SUCCESS
)
4093 return SHLoadIndirectString(buf
, buf
, size
, NULL
);
4096 /*************************************************************************
4099 * Call IInputObject_TranslateAcceleratorIO() on an object.
4102 * lpUnknown [I] Object supporting the IInputObject interface.
4103 * lpMsg [I] Key message to be processed.
4107 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4109 HRESULT WINAPI
IUnknown_TranslateAcceleratorIO(IUnknown
*lpUnknown
, LPMSG lpMsg
)
4111 IInputObject
* lpInput
= NULL
;
4112 HRESULT hRet
= E_INVALIDARG
;
4114 TRACE("(%p,%p)\n", lpUnknown
, lpMsg
);
4117 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObject
,
4119 if (SUCCEEDED(hRet
) && lpInput
)
4121 hRet
= IInputObject_TranslateAcceleratorIO(lpInput
, lpMsg
);
4122 IInputObject_Release(lpInput
);
4128 /*************************************************************************
4131 * Call IInputObject_HasFocusIO() on an object.
4134 * lpUnknown [I] Object supporting the IInputObject interface.
4137 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4138 * or S_FALSE otherwise.
4139 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4141 HRESULT WINAPI
IUnknown_HasFocusIO(IUnknown
*lpUnknown
)
4143 IInputObject
* lpInput
= NULL
;
4144 HRESULT hRet
= E_INVALIDARG
;
4146 TRACE("(%p)\n", lpUnknown
);
4149 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObject
,
4151 if (SUCCEEDED(hRet
) && lpInput
)
4153 hRet
= IInputObject_HasFocusIO(lpInput
);
4154 IInputObject_Release(lpInput
);
4160 /*************************************************************************
4161 * ColorRGBToHLS [SHLWAPI.@]
4163 * Convert an rgb COLORREF into the hls color space.
4166 * cRGB [I] Source rgb value
4167 * pwHue [O] Destination for converted hue
4168 * pwLuminance [O] Destination for converted luminance
4169 * pwSaturation [O] Destination for converted saturation
4172 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4176 * Output HLS values are constrained to the range (0..240).
4177 * For Achromatic conversions, Hue is set to 160.
4179 VOID WINAPI
ColorRGBToHLS(COLORREF cRGB
, LPWORD pwHue
,
4180 LPWORD pwLuminance
, LPWORD pwSaturation
)
4182 int wR
, wG
, wB
, wMax
, wMin
, wHue
, wLuminosity
, wSaturation
;
4184 TRACE("(%08x,%p,%p,%p)\n", cRGB
, pwHue
, pwLuminance
, pwSaturation
);
4186 wR
= GetRValue(cRGB
);
4187 wG
= GetGValue(cRGB
);
4188 wB
= GetBValue(cRGB
);
4190 wMax
= max(wR
, max(wG
, wB
));
4191 wMin
= min(wR
, min(wG
, wB
));
4194 wLuminosity
= ((wMax
+ wMin
) * 240 + 255) / 510;
4198 /* Achromatic case */
4200 /* Hue is now unrepresentable, but this is what native returns... */
4205 /* Chromatic case */
4206 int wDelta
= wMax
- wMin
, wRNorm
, wGNorm
, wBNorm
;
4209 if (wLuminosity
<= 120)
4210 wSaturation
= ((wMax
+ wMin
)/2 + wDelta
* 240) / (wMax
+ wMin
);
4212 wSaturation
= ((510 - wMax
- wMin
)/2 + wDelta
* 240) / (510 - wMax
- wMin
);
4215 wRNorm
= (wDelta
/2 + wMax
* 40 - wR
* 40) / wDelta
;
4216 wGNorm
= (wDelta
/2 + wMax
* 40 - wG
* 40) / wDelta
;
4217 wBNorm
= (wDelta
/2 + wMax
* 40 - wB
* 40) / wDelta
;
4220 wHue
= wBNorm
- wGNorm
;
4221 else if (wG
== wMax
)
4222 wHue
= 80 + wRNorm
- wBNorm
;
4224 wHue
= 160 + wGNorm
- wRNorm
;
4227 else if (wHue
> 240)
4233 *pwLuminance
= wLuminosity
;
4235 *pwSaturation
= wSaturation
;
4238 /*************************************************************************
4239 * SHCreateShellPalette [SHLWAPI.@]
4241 HPALETTE WINAPI
SHCreateShellPalette(HDC hdc
)
4244 return CreateHalftonePalette(hdc
);
4247 /*************************************************************************
4248 * SHGetInverseCMAP (SHLWAPI.@)
4250 * Get an inverse color map table.
4253 * lpCmap [O] Destination for color map
4254 * dwSize [I] Size of memory pointed to by lpCmap
4258 * Failure: E_POINTER, If lpCmap is invalid.
4259 * E_INVALIDARG, If dwFlags is invalid
4260 * E_OUTOFMEMORY, If there is no memory available
4263 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4264 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4266 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4267 * this DLL's internal CMap.
4269 HRESULT WINAPI
SHGetInverseCMAP(LPDWORD dest
, DWORD dwSize
)
4272 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4273 *dest
= (DWORD
)0xabba1249;
4276 FIXME("(%p, %#x) stub\n", dest
, dwSize
);
4280 /*************************************************************************
4281 * SHIsLowMemoryMachine [SHLWAPI.@]
4283 * Determine if the current computer has low memory.
4289 * TRUE if the users machine has 16 Megabytes of memory or less,
4292 BOOL WINAPI
SHIsLowMemoryMachine (DWORD x
)
4294 FIXME("(0x%08x) stub\n", x
);
4298 /*************************************************************************
4299 * GetMenuPosFromID [SHLWAPI.@]
4301 * Return the position of a menu item from its Id.
4304 * hMenu [I] Menu containing the item
4305 * wID [I] Id of the menu item
4308 * Success: The index of the menu item in hMenu.
4309 * Failure: -1, If the item is not found.
4311 INT WINAPI
GetMenuPosFromID(HMENU hMenu
, UINT wID
)
4314 INT nCount
= GetMenuItemCount(hMenu
), nIter
= 0;
4316 TRACE("%p %u\n", hMenu
, wID
);
4318 while (nIter
< nCount
)
4320 mi
.cbSize
= sizeof(mi
);
4322 if (GetMenuItemInfoW(hMenu
, nIter
, TRUE
, &mi
) && mi
.wID
== wID
)
4324 TRACE("ret %d\n", nIter
);
4333 /*************************************************************************
4336 * Same as SHLWAPI.GetMenuPosFromID
4338 DWORD WINAPI
SHMenuIndexFromID(HMENU hMenu
, UINT uID
)
4340 TRACE("%p %u\n", hMenu
, uID
);
4341 return GetMenuPosFromID(hMenu
, uID
);
4345 /*************************************************************************
4348 VOID WINAPI
FixSlashesAndColonW(LPWSTR lpwstr
)
4359 /*************************************************************************
4362 DWORD WINAPI
SHGetAppCompatFlags(DWORD dwUnknown
)
4364 FIXME("(0x%08x) stub\n", dwUnknown
);
4369 /*************************************************************************
4372 HRESULT WINAPI
SHCoCreateInstanceAC(REFCLSID rclsid
, LPUNKNOWN pUnkOuter
,
4373 DWORD dwClsContext
, REFIID iid
, LPVOID
*ppv
)
4375 return CoCreateInstance(rclsid
, pUnkOuter
, dwClsContext
, iid
, ppv
);
4378 /*************************************************************************
4379 * SHSkipJunction [SHLWAPI.@]
4381 * Determine if a bind context can be bound to an object
4384 * pbc [I] Bind context to check
4385 * pclsid [I] CLSID of object to be bound to
4388 * TRUE: If it is safe to bind
4389 * FALSE: If pbc is invalid or binding would not be safe
4392 BOOL WINAPI
SHSkipJunction(IBindCtx
*pbc
, const CLSID
*pclsid
)
4394 static WCHAR szSkipBinding
[] = { 'S','k','i','p',' ',
4395 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4402 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc
, szSkipBinding
, &lpUnk
)))
4406 if (SUCCEEDED(IUnknown_GetClassID(lpUnk
, &clsid
)) &&
4407 IsEqualGUID(pclsid
, &clsid
))
4410 IUnknown_Release(lpUnk
);
4416 /***********************************************************************
4417 * SHGetShellKey (SHLWAPI.491)
4419 HKEY WINAPI
SHGetShellKey(DWORD flags
, LPCWSTR sub_key
, BOOL create
)
4421 enum _shellkey_flags
{
4422 SHKEY_Root_HKCU
= 0x1,
4423 SHKEY_Root_HKLM
= 0x2,
4424 SHKEY_Key_Explorer
= 0x00,
4425 SHKEY_Key_Shell
= 0x10,
4426 SHKEY_Key_ShellNoRoam
= 0x20,
4427 SHKEY_Key_Classes
= 0x30,
4428 SHKEY_Subkey_Default
= 0x0000,
4429 SHKEY_Subkey_ResourceName
= 0x1000,
4430 SHKEY_Subkey_Handlers
= 0x2000,
4431 SHKEY_Subkey_Associations
= 0x3000,
4432 SHKEY_Subkey_Volatile
= 0x4000,
4433 SHKEY_Subkey_MUICache
= 0x5000,
4434 SHKEY_Subkey_FileExts
= 0x6000
4437 static const WCHAR explorerW
[] = {'S','o','f','t','w','a','r','e','\\',
4438 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4439 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4440 'E','x','p','l','o','r','e','r','\\'};
4441 static const WCHAR shellW
[] = {'S','o','f','t','w','a','r','e','\\',
4442 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4443 'S','h','e','l','l','\\'};
4444 static const WCHAR shell_no_roamW
[] = {'S','o','f','t','w','a','r','e','\\',
4445 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4446 'S','h','e','l','l','N','o','R','o','a','m','\\'};
4447 static const WCHAR classesW
[] = {'S','o','f','t','w','a','r','e','\\',
4448 'C','l','a','s','s','e','s','\\'};
4450 static const WCHAR localized_resource_nameW
[] = {'L','o','c','a','l','i','z','e','d',
4451 'R','e','s','o','u','r','c','e','N','a','m','e','\\'};
4452 static const WCHAR handlersW
[] = {'H','a','n','d','l','e','r','s','\\'};
4453 static const WCHAR associationsW
[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'};
4454 static const WCHAR volatileW
[] = {'V','o','l','a','t','i','l','e','\\'};
4455 static const WCHAR mui_cacheW
[] = {'M','U','I','C','a','c','h','e','\\'};
4456 static const WCHAR file_extsW
[] = {'F','i','l','e','E','x','t','s','\\'};
4459 const WCHAR
*key
, *subkey
;
4460 int size_key
, size_subkey
, size_user
;
4463 TRACE("(0x%08x, %s, %d)\n", flags
, debugstr_w(sub_key
), create
);
4465 /* For compatibility with Vista+ */
4466 if(flags
== 0x1ffff)
4469 switch(flags
&0xff0) {
4470 case SHKEY_Key_Explorer
:
4472 size_key
= sizeof(explorerW
);
4474 case SHKEY_Key_Shell
:
4476 size_key
= sizeof(shellW
);
4478 case SHKEY_Key_ShellNoRoam
:
4479 key
= shell_no_roamW
;
4480 size_key
= sizeof(shell_no_roamW
);
4482 case SHKEY_Key_Classes
:
4484 size_key
= sizeof(classesW
);
4487 FIXME("unsupported flags (0x%08x)\n", flags
);
4491 switch(flags
&0xff000) {
4492 case SHKEY_Subkey_Default
:
4496 case SHKEY_Subkey_ResourceName
:
4497 subkey
= localized_resource_nameW
;
4498 size_subkey
= sizeof(localized_resource_nameW
);
4500 case SHKEY_Subkey_Handlers
:
4502 size_subkey
= sizeof(handlersW
);
4504 case SHKEY_Subkey_Associations
:
4505 subkey
= associationsW
;
4506 size_subkey
= sizeof(associationsW
);
4508 case SHKEY_Subkey_Volatile
:
4510 size_subkey
= sizeof(volatileW
);
4512 case SHKEY_Subkey_MUICache
:
4513 subkey
= mui_cacheW
;
4514 size_subkey
= sizeof(mui_cacheW
);
4516 case SHKEY_Subkey_FileExts
:
4517 subkey
= file_extsW
;
4518 size_subkey
= sizeof(file_extsW
);
4521 FIXME("unsupported flags (0x%08x)\n", flags
);
4526 size_user
= lstrlenW(sub_key
)*sizeof(WCHAR
);
4530 path
= HeapAlloc(GetProcessHeap(), 0, size_key
+size_subkey
+size_user
+sizeof(WCHAR
));
4532 ERR("Out of memory\n");
4536 memcpy(path
, key
, size_key
);
4538 memcpy(path
+size_key
/sizeof(WCHAR
), subkey
, size_subkey
);
4540 memcpy(path
+(size_key
+size_subkey
)/sizeof(WCHAR
), sub_key
, size_user
);
4541 path
[(size_key
+size_subkey
+size_user
)/sizeof(WCHAR
)] = '\0';
4544 RegCreateKeyExW((flags
&0xf)==SHKEY_Root_HKLM
?HKEY_LOCAL_MACHINE
:HKEY_CURRENT_USER
,
4545 path
, 0, NULL
, 0, MAXIMUM_ALLOWED
, NULL
, &hkey
, NULL
);
4547 RegOpenKeyExW((flags
&0xf)==SHKEY_Root_HKLM
?HKEY_LOCAL_MACHINE
:HKEY_CURRENT_USER
,
4548 path
, 0, MAXIMUM_ALLOWED
, &hkey
);
4550 HeapFree(GetProcessHeap(), 0, path
);
4554 /***********************************************************************
4555 * SHQueueUserWorkItem (SHLWAPI.@)
4557 BOOL WINAPI
SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback
,
4558 LPVOID pContext
, LONG lPriority
, DWORD_PTR dwTag
,
4559 DWORD_PTR
*pdwId
, LPCSTR pszModule
, DWORD dwFlags
)
4561 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback
, pContext
,
4562 lPriority
, dwTag
, pdwId
, debugstr_a(pszModule
), dwFlags
);
4564 if(lPriority
|| dwTag
|| pdwId
|| pszModule
|| dwFlags
)
4565 FIXME("Unsupported arguments\n");
4567 return QueueUserWorkItem(pfnCallback
, pContext
, 0);
4570 /***********************************************************************
4571 * SHSetTimerQueueTimer (SHLWAPI.263)
4573 HANDLE WINAPI
SHSetTimerQueueTimer(HANDLE hQueue
,
4574 WAITORTIMERCALLBACK pfnCallback
, LPVOID pContext
, DWORD dwDueTime
,
4575 DWORD dwPeriod
, LPCSTR lpszLibrary
, DWORD dwFlags
)
4579 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4580 if (dwFlags
& TPS_LONGEXECTIME
) {
4581 dwFlags
&= ~TPS_LONGEXECTIME
;
4582 dwFlags
|= WT_EXECUTELONGFUNCTION
;
4584 if (dwFlags
& TPS_EXECUTEIO
) {
4585 dwFlags
&= ~TPS_EXECUTEIO
;
4586 dwFlags
|= WT_EXECUTEINIOTHREAD
;
4589 if (!CreateTimerQueueTimer(&hNewTimer
, hQueue
, pfnCallback
, pContext
,
4590 dwDueTime
, dwPeriod
, dwFlags
))
4596 /***********************************************************************
4597 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4599 HRESULT WINAPI
IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown
, LPUNKNOWN pFocusObject
, BOOL bFocus
)
4601 IInputObjectSite
*pIOS
= NULL
;
4602 HRESULT hRet
= E_INVALIDARG
;
4604 TRACE("(%p, %p, %s)\n", lpUnknown
, pFocusObject
, bFocus
? "TRUE" : "FALSE");
4608 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObjectSite
,
4610 if (SUCCEEDED(hRet
) && pIOS
)
4612 hRet
= IInputObjectSite_OnFocusChangeIS(pIOS
, pFocusObject
, bFocus
);
4613 IInputObjectSite_Release(pIOS
);
4619 /***********************************************************************
4620 * SKAllocValueW (SHLWAPI.519)
4622 HRESULT WINAPI
SKAllocValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
, DWORD
*type
,
4623 LPVOID
*data
, DWORD
*count
)
4628 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags
, debugstr_w(subkey
),
4629 debugstr_w(value
), type
, data
, count
);
4631 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
4633 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4635 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, NULL
, &size
);
4638 return HRESULT_FROM_WIN32(ret
);
4642 *data
= LocalAlloc(0, size
);
4645 return E_OUTOFMEMORY
;
4648 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, *data
, &size
);
4653 return HRESULT_FROM_WIN32(ret
);
4656 /***********************************************************************
4657 * SKDeleteValueW (SHLWAPI.518)
4659 HRESULT WINAPI
SKDeleteValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
)
4664 TRACE("(0x%x, %s %s)\n", flags
, debugstr_w(subkey
), debugstr_w(value
));
4666 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
4668 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4670 ret
= RegDeleteValueW(hkey
, value
);
4673 return HRESULT_FROM_WIN32(ret
);
4676 /***********************************************************************
4677 * SKGetValueW (SHLWAPI.516)
4679 HRESULT WINAPI
SKGetValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
, DWORD
*type
,
4680 void *data
, DWORD
*count
)
4685 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags
, debugstr_w(subkey
),
4686 debugstr_w(value
), type
, data
, count
);
4688 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
4690 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4692 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, data
, count
);
4695 return HRESULT_FROM_WIN32(ret
);
4698 /***********************************************************************
4699 * SKSetValueW (SHLWAPI.516)
4701 HRESULT WINAPI
SKSetValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
,
4702 DWORD type
, void *data
, DWORD count
)
4707 TRACE("(0x%x, %s, %s, %x, %p, %d)\n", flags
, debugstr_w(subkey
),
4708 debugstr_w(value
), type
, data
, count
);
4710 hkey
= SHGetShellKey(flags
, subkey
, TRUE
);
4712 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4714 ret
= RegSetValueExW(hkey
, value
, 0, type
, data
, count
);
4717 return HRESULT_FROM_WIN32(ret
);
4720 typedef HRESULT (WINAPI
*DllGetVersion_func
)(DLLVERSIONINFO
*);
4722 /***********************************************************************
4723 * GetUIVersion (SHLWAPI.452)
4725 DWORD WINAPI
GetUIVersion(void)
4727 static DWORD version
;
4731 DllGetVersion_func pDllGetVersion
;
4732 HMODULE dll
= LoadLibraryA("shell32.dll");
4735 pDllGetVersion
= (DllGetVersion_func
)GetProcAddress(dll
, "DllGetVersion");
4739 dvi
.cbSize
= sizeof(DLLVERSIONINFO
);
4740 if (pDllGetVersion(&dvi
) == S_OK
) version
= dvi
.dwMajorVersion
;
4743 if (!version
) version
= 3; /* old shell dlls don't have DllGetVersion */
4748 /***********************************************************************
4749 * ShellMessageBoxWrapW [SHLWAPI.388]
4751 * See shell32.ShellMessageBoxW
4754 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4755 * because we can't forward to it in the .spec file since it's exported by
4756 * ordinal. If you change the implementation here please update the code in
4759 INT WINAPIV
ShellMessageBoxWrapW(HINSTANCE hInstance
, HWND hWnd
, LPCWSTR lpText
,
4760 LPCWSTR lpCaption
, UINT uType
, ...)
4762 WCHAR
*szText
= NULL
, szTitle
[100];
4763 LPCWSTR pszText
, pszTitle
= szTitle
;
4768 __ms_va_start(args
, uType
);
4770 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance
, hWnd
, lpText
, lpCaption
, uType
);
4772 if (IS_INTRESOURCE(lpCaption
))
4773 LoadStringW(hInstance
, LOWORD(lpCaption
), szTitle
, sizeof(szTitle
)/sizeof(szTitle
[0]));
4775 pszTitle
= lpCaption
;
4777 if (IS_INTRESOURCE(lpText
))
4780 UINT len
= LoadStringW(hInstance
, LOWORD(lpText
), (LPWSTR
)&ptr
, 0);
4784 szText
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
4785 if (szText
) LoadStringW(hInstance
, LOWORD(lpText
), szText
, len
+ 1);
4789 WARN("Failed to load id %d\n", LOWORD(lpText
));
4797 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
,
4798 pszText
, 0, 0, (LPWSTR
)&pszTemp
, 0, &args
);
4802 ret
= MessageBoxW(hWnd
, pszTemp
, pszTitle
, uType
);
4804 HeapFree(GetProcessHeap(), 0, szText
);
4809 /***********************************************************************
4810 * ZoneComputePaneSize [SHLWAPI.382]
4812 UINT WINAPI
ZoneComputePaneSize(HWND hwnd
)
4818 /***********************************************************************
4819 * SHChangeNotifyWrap [SHLWAPI.394]
4821 void WINAPI
SHChangeNotifyWrap(LONG wEventId
, UINT uFlags
, LPCVOID dwItem1
, LPCVOID dwItem2
)
4823 SHChangeNotify(wEventId
, uFlags
, dwItem1
, dwItem2
);
4826 typedef struct SHELL_USER_SID
{ /* according to MSDN this should be in shlobj.h... */
4827 SID_IDENTIFIER_AUTHORITY sidAuthority
;
4828 DWORD dwUserGroupID
;
4830 } SHELL_USER_SID
, *PSHELL_USER_SID
;
4832 typedef struct SHELL_USER_PERMISSION
{ /* ...and this should be in shlwapi.h */
4833 SHELL_USER_SID susID
;
4837 DWORD dwInheritMask
;
4838 DWORD dwInheritAccessMask
;
4839 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
4841 /***********************************************************************
4842 * GetShellSecurityDescriptor [SHLWAPI.475]
4844 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4847 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4848 * each of which describes permissions to apply
4849 * cUserPerm [I] number of entries in apUserPerm array
4852 * success: pointer to SECURITY_DESCRIPTOR
4856 * Call should free returned descriptor with LocalFree
4858 PSECURITY_DESCRIPTOR WINAPI
GetShellSecurityDescriptor(PSHELL_USER_PERMISSION
*apUserPerm
, int cUserPerm
)
4861 PSID cur_user
= NULL
;
4865 PSECURITY_DESCRIPTOR psd
= NULL
;
4867 TRACE("%p %d\n", apUserPerm
, cUserPerm
);
4869 if (apUserPerm
== NULL
|| cUserPerm
<= 0)
4872 sidlist
= HeapAlloc(GetProcessHeap(), 0, cUserPerm
* sizeof(PSID
));
4876 acl_size
= sizeof(ACL
);
4878 for(sid_count
= 0; sid_count
< cUserPerm
; sid_count
++)
4880 static SHELL_USER_SID null_sid
= {{SECURITY_NULL_SID_AUTHORITY
}, 0, 0};
4881 PSHELL_USER_PERMISSION perm
= apUserPerm
[sid_count
];
4882 PSHELL_USER_SID sid
= &perm
->susID
;
4886 if (!memcmp((void*)sid
, (void*)&null_sid
, sizeof(SHELL_USER_SID
)))
4887 { /* current user's SID */
4891 DWORD bufsize
= sizeof(tuUser
);
4893 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &Token
);
4896 ret
= GetTokenInformation(Token
, TokenUser
, (void*)tuUser
, bufsize
, &bufsize
);
4898 cur_user
= ((PTOKEN_USER
)tuUser
)->User
.Sid
;
4903 } else if (sid
->dwUserID
==0) /* one sub-authority */
4904 ret
= AllocateAndInitializeSid(&sid
->sidAuthority
, 1, sid
->dwUserGroupID
, 0,
4905 0, 0, 0, 0, 0, 0, &pSid
);
4907 ret
= AllocateAndInitializeSid(&sid
->sidAuthority
, 2, sid
->dwUserGroupID
, sid
->dwUserID
,
4908 0, 0, 0, 0, 0, 0, &pSid
);
4912 sidlist
[sid_count
] = pSid
;
4913 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4914 acl_size
+= (sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
) + GetLengthSid(pSid
)) * (perm
->fInherit
? 2 : 1);
4917 psd
= LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR
) + acl_size
);
4921 PACL pAcl
= (PACL
)(((BYTE
*)psd
)+sizeof(SECURITY_DESCRIPTOR
));
4923 if (!InitializeSecurityDescriptor(psd
, SECURITY_DESCRIPTOR_REVISION
))
4926 if (!InitializeAcl(pAcl
, acl_size
, ACL_REVISION
))
4929 for(i
= 0; i
< sid_count
; i
++)
4931 PSHELL_USER_PERMISSION sup
= apUserPerm
[i
];
4932 PSID sid
= sidlist
[i
];
4934 switch(sup
->dwAccessType
)
4936 case ACCESS_ALLOWED_ACE_TYPE
:
4937 if (!AddAccessAllowedAce(pAcl
, ACL_REVISION
, sup
->dwAccessMask
, sid
))
4939 if (sup
->fInherit
&& !AddAccessAllowedAceEx(pAcl
, ACL_REVISION
,
4940 (BYTE
)sup
->dwInheritMask
, sup
->dwInheritAccessMask
, sid
))
4943 case ACCESS_DENIED_ACE_TYPE
:
4944 if (!AddAccessDeniedAce(pAcl
, ACL_REVISION
, sup
->dwAccessMask
, sid
))
4946 if (sup
->fInherit
&& !AddAccessDeniedAceEx(pAcl
, ACL_REVISION
,
4947 (BYTE
)sup
->dwInheritMask
, sup
->dwInheritAccessMask
, sid
))
4955 if (!SetSecurityDescriptorDacl(psd
, TRUE
, pAcl
, FALSE
))
4964 for(i
= 0; i
< sid_count
; i
++)
4966 if (!cur_user
|| sidlist
[i
] != cur_user
)
4967 FreeSid(sidlist
[i
]);
4969 HeapFree(GetProcessHeap(), 0, sidlist
);
4974 /***********************************************************************
4975 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4977 * Creates a property bag from a registry key
4980 * hKey [I] Handle to the desired registry key
4981 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4982 * grfMode [I] Optional flags
4983 * riid [I] IID of requested property bag interface
4984 * ppv [O] Address to receive pointer to the new interface
4988 * failure: error code
4991 HRESULT WINAPI
SHCreatePropertyBagOnRegKey (HKEY hKey
, LPCWSTR subkey
,
4992 DWORD grfMode
, REFIID riid
, void **ppv
)
4994 FIXME("%p %s %d %s %p STUB\n", hKey
, debugstr_w(subkey
), grfMode
,
4995 debugstr_guid(riid
), ppv
);
5000 /***********************************************************************
5001 * SHGetViewStatePropertyBag [SHLWAPI.515]
5003 * Retrieves a property bag in which the view state information of a folder
5007 * pidl [I] PIDL of the folder requested
5008 * bag_name [I] Name of the property bag requested
5009 * flags [I] Optional flags
5010 * riid [I] IID of requested property bag interface
5011 * ppv [O] Address to receive pointer to the new interface
5015 * failure: error code
5018 HRESULT WINAPI
SHGetViewStatePropertyBag(LPCITEMIDLIST pidl
, LPWSTR bag_name
,
5019 DWORD flags
, REFIID riid
, void **ppv
)
5021 FIXME("%p %s %d %s %p STUB\n", pidl
, debugstr_w(bag_name
), flags
,
5022 debugstr_guid(riid
), ppv
);
5027 /***********************************************************************
5028 * SHFormatDateTimeW [SHLWAPI.354]
5030 * Produces a string representation of a time.
5033 * fileTime [I] Pointer to FILETIME structure specifying the time
5034 * flags [I] Flags specifying the desired output
5035 * buf [O] Pointer to buffer for output
5036 * size [I] Number of characters that can be contained in buffer
5039 * success: number of characters written to the buffer
5043 INT WINAPI
SHFormatDateTimeW(const FILETIME UNALIGNED
*fileTime
, DWORD
*flags
,
5044 LPWSTR buf
, UINT size
)
5046 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
5047 DWORD fmt_flags
= flags
? *flags
: FDTF_DEFAULT
;
5052 TRACE("%p %p %p %u\n", fileTime
, flags
, buf
, size
);
5057 if (fmt_flags
& SHFORMATDT_UNSUPPORTED_FLAGS
)
5058 FIXME("ignoring some flags - 0x%08x\n", fmt_flags
& SHFORMATDT_UNSUPPORTED_FLAGS
);
5060 FileTimeToLocalFileTime(fileTime
, &ft
);
5061 FileTimeToSystemTime(&ft
, &st
);
5063 /* first of all date */
5064 if (fmt_flags
& (FDTF_LONGDATE
| FDTF_SHORTDATE
))
5066 static const WCHAR sep1
[] = {',',' ',0};
5067 static const WCHAR sep2
[] = {' ',0};
5069 DWORD date
= fmt_flags
& FDTF_LONGDATE
? DATE_LONGDATE
: DATE_SHORTDATE
;
5070 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, date
, &st
, NULL
, buf
, size
);
5071 if (ret
>= size
) return ret
;
5074 if (ret
< size
&& (fmt_flags
& (FDTF_LONGTIME
| FDTF_SHORTTIME
)))
5076 if ((fmt_flags
& FDTF_LONGDATE
) && (ret
< size
+ 2))
5080 lstrcatW(&buf
[ret
-1], sep1
);
5086 lstrcatW(&buf
[ret
-1], sep2
);
5092 if (fmt_flags
& (FDTF_LONGTIME
| FDTF_SHORTTIME
))
5094 DWORD time
= fmt_flags
& FDTF_LONGTIME
? 0 : TIME_NOSECONDS
;
5097 ret
+= GetTimeFormatW(LOCALE_USER_DEFAULT
, time
, &st
, NULL
, &buf
[ret
], size
- ret
);
5102 #undef SHFORMATDT_UNSUPPORTED_FLAGS
5105 /***********************************************************************
5106 * SHFormatDateTimeA [SHLWAPI.353]
5108 * See SHFormatDateTimeW.
5111 INT WINAPI
SHFormatDateTimeA(const FILETIME UNALIGNED
*fileTime
, DWORD
*flags
,
5112 LPSTR buf
, UINT size
)
5120 bufW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * size
);
5121 retval
= SHFormatDateTimeW(fileTime
, flags
, bufW
, size
);
5124 WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, buf
, size
, NULL
, NULL
);
5126 HeapFree(GetProcessHeap(), 0, bufW
);
5130 /***********************************************************************
5131 * ZoneCheckUrlExW [SHLWAPI.231]
5133 * Checks the details of the security zone for the supplied site. (?)
5137 * szURL [I] Pointer to the URL to check
5139 * Other parameters currently unknown.
5145 INT WINAPI
ZoneCheckUrlExW(LPWSTR szURL
, PVOID pUnknown
, DWORD dwUnknown2
,
5146 DWORD dwUnknown3
, DWORD dwUnknown4
, DWORD dwUnknown5
, DWORD dwUnknown6
,
5149 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL
), pUnknown
, dwUnknown2
,
5150 dwUnknown3
, dwUnknown4
, dwUnknown5
, dwUnknown6
, dwUnknown7
);
5155 /***********************************************************************
5156 * SHVerbExistsNA [SHLWAPI.196]
5161 * verb [I] a string, often appears to be an extension.
5163 * Other parameters currently unknown.
5168 INT WINAPI
SHVerbExistsNA(LPSTR verb
, PVOID pUnknown
, PVOID pUnknown2
, DWORD dwUnknown3
)
5170 FIXME("(%s, %p, %p, %i) STUB\n",verb
, pUnknown
, pUnknown2
, dwUnknown3
);
5174 /*************************************************************************
5177 * Undocumented: Implementation guessed at via Name and behavior
5180 * lpUnknown [I] Object to get an IServiceProvider interface from
5181 * riid [I] Function requested for QueryService call
5182 * lppOut [O] Destination for the service interface pointer
5185 * Success: S_OK. lppOut contains an object providing the requested service
5186 * Failure: An HRESULT error code
5189 * lpUnknown is expected to support the IServiceProvider interface.
5191 HRESULT WINAPI
IUnknown_QueryServiceForWebBrowserApp(IUnknown
* lpUnknown
,
5192 REFGUID riid
, LPVOID
*lppOut
)
5194 FIXME("%p %s %p semi-STUB\n", lpUnknown
, debugstr_guid(riid
), lppOut
);
5195 return IUnknown_QueryService(lpUnknown
,&IID_IWebBrowserApp
,riid
,lppOut
);
5198 /**************************************************************************
5199 * SHPropertyBag_ReadLONG (SHLWAPI.496)
5201 * This function asks a property bag to read a named property as a LONG.
5204 * ppb: a IPropertyBag interface
5205 * pszPropName: Unicode string that names the property
5206 * pValue: address to receive the property value as a 32-bit signed integer
5211 BOOL WINAPI
SHPropertyBag_ReadLONG(IPropertyBag
*ppb
, LPCWSTR pszPropName
, LPLONG pValue
)
5215 TRACE("%p %s %p\n", ppb
,debugstr_w(pszPropName
),pValue
);
5216 if (!pszPropName
|| !ppb
|| !pValue
)
5217 return E_INVALIDARG
;
5219 hr
= IPropertyBag_Read(ppb
, pszPropName
, &var
, NULL
);
5222 if (V_VT(&var
) == VT_I4
)
5223 *pValue
= V_I4(&var
);
5225 hr
= DISP_E_BADVARTYPE
;
5230 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
5231 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
5232 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
5233 #define OBJCOMPAT_UNBINDABLE 0x00000004
5234 #define OBJCOMPAT_PINDLL 0x00000008
5235 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
5236 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
5237 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
5238 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
5239 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
5240 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
5241 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
5242 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
5243 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
5245 /* a search table for compatibility flags */
5246 struct objcompat_entry
{
5247 const WCHAR name
[30];
5251 /* expected to be sorted by name */
5252 static const struct objcompat_entry objcompat_table
[] = {
5253 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
5254 OBJCOMPAT_COCREATESHELLFOLDERONLY
},
5255 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
5256 OBJCOMPAT_CTXMENU_LIMITEDQI
},
5257 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
5258 OBJCOMPAT_CTXMENU_LIMITEDQI
},
5259 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
5260 OBJCOMPAT_CTXMENU_XPQCMFLAGS
},
5261 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
5262 OBJCOMPAT_NEEDSFILESYSANCESTOR
},
5263 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
5264 OBJCOMPAT_NEEDSSTORAGEANCESTOR
},
5265 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
5266 OBJCOMPAT_NOIPROPERTYSTORE
},
5267 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
5268 OBJCOMPAT_NOLEGACYWEBVIEW
},
5269 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
5270 OBJCOMPAT_NOTAFILESYSTEM
},
5271 { {'N','O','_','W','E','B','V','I','E','W',0},
5272 OBJCOMPAT_NO_WEBVIEW
},
5273 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
5274 OBJCOMPAT_OTNEEDSSFCACHE
},
5275 { {'P','I','N','D','L','L',0},
5277 { {'U','N','B','I','N','D','A','B','L','E',0},
5278 OBJCOMPAT_UNBINDABLE
}
5281 /**************************************************************************
5282 * SHGetObjectCompatFlags (SHLWAPI.476)
5284 * Function returns an integer representation of compatibility flags stored
5285 * in registry for CLSID under ShellCompatibility subkey.
5288 * pUnk: pointer to object IUnknown interface, idetifies CLSID
5289 * clsid: pointer to CLSID to retrieve data for
5292 * 0 on failure, flags set on success
5294 DWORD WINAPI
SHGetObjectCompatFlags(IUnknown
*pUnk
, const CLSID
*clsid
)
5296 static const WCHAR compatpathW
[] =
5297 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
5298 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
5299 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
5300 'O','b','j','e','c','t','s','\\','%','s',0};
5301 WCHAR strW
[sizeof(compatpathW
)/sizeof(WCHAR
) + 38 /* { CLSID } */];
5302 DWORD ret
, length
= sizeof(strW
)/sizeof(WCHAR
);
5307 TRACE("%p %s\n", pUnk
, debugstr_guid(clsid
));
5309 if (!pUnk
&& !clsid
) return 0;
5313 FIXME("iface not handled\n");
5317 StringFromCLSID(clsid
, &clsid_str
);
5318 sprintfW(strW
, compatpathW
, clsid_str
);
5319 CoTaskMemFree(clsid_str
);
5321 ret
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, strW
, &key
);
5322 if (ret
!= ERROR_SUCCESS
) return 0;
5324 /* now collect flag values */
5326 for (i
= 0; RegEnumValueW(key
, i
, strW
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; i
++)
5328 INT left
, right
, res
, x
;
5330 /* search in table */
5332 right
= sizeof(objcompat_table
) / sizeof(struct objcompat_entry
) - 1;
5334 while (right
>= left
) {
5335 x
= (left
+ right
) / 2;
5336 res
= strcmpW(strW
, objcompat_table
[x
].name
);
5339 ret
|= objcompat_table
[x
].value
;
5348 length
= sizeof(strW
)/sizeof(WCHAR
);