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"
48 //#include "objbase.h"
50 //#include "shdeprecated.h"
57 #include <wine/unicode.h>
58 #include <wine/debug.h>
61 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
63 /* DLL handles for late bound calls */
64 extern HINSTANCE shlwapi_hInstance
;
65 extern DWORD SHLWAPI_ThreadRef_index
;
67 HRESULT WINAPI
IUnknown_QueryService(IUnknown
*,REFGUID
,REFIID
,LPVOID
*);
68 HRESULT WINAPI
SHInvokeCommand(HWND
,IShellFolder
*,LPCITEMIDLIST
,BOOL
);
69 BOOL WINAPI
SHAboutInfoW(LPWSTR
,DWORD
);
72 NOTES: Most functions exported by ordinal seem to be superfluous.
73 The reason for these functions to be there is to provide a wrapper
74 for unicode functions to provide these functions on systems without
75 unicode functions eg. win95/win98. Since we have such functions we just
76 call these. If running Wine with native DLLs, some late bound calls may
77 fail. However, it is better to implement the functions in the forward DLL
78 and recommend the builtin rather than reimplementing the calls here!
81 /*************************************************************************
82 * SHLWAPI_DupSharedHandle
84 * Internal implementation of SHLWAPI_11.
86 static HANDLE
SHLWAPI_DupSharedHandle(HANDLE hShared
, DWORD dwDstProcId
,
87 DWORD dwSrcProcId
, DWORD dwAccess
,
91 DWORD dwMyProcId
= GetCurrentProcessId();
94 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared
, dwDstProcId
, dwSrcProcId
,
97 /* Get dest process handle */
98 if (dwDstProcId
== dwMyProcId
)
99 hDst
= GetCurrentProcess();
101 hDst
= OpenProcess(PROCESS_DUP_HANDLE
, 0, dwDstProcId
);
105 /* Get src process handle */
106 if (dwSrcProcId
== dwMyProcId
)
107 hSrc
= GetCurrentProcess();
109 hSrc
= OpenProcess(PROCESS_DUP_HANDLE
, 0, dwSrcProcId
);
113 /* Make handle available to dest process */
114 if (!DuplicateHandle(hDst
, hShared
, hSrc
, &hRet
,
115 dwAccess
, 0, dwOptions
| DUPLICATE_SAME_ACCESS
))
118 if (dwSrcProcId
!= dwMyProcId
)
122 if (dwDstProcId
!= dwMyProcId
)
126 TRACE("Returning handle %p\n", hRet
);
130 /*************************************************************************
133 * Create a block of sharable memory and initialise it with data.
136 * lpvData [I] Pointer to data to write
137 * dwSize [I] Size of data
138 * dwProcId [I] ID of process owning data
141 * Success: A shared memory handle
145 * Ordinals 7-11 provide a set of calls to create shared memory between a
146 * group of processes. The shared memory is treated opaquely in that its size
147 * is not exposed to clients who map it. This is accomplished by storing
148 * the size of the map as the first DWORD of mapped data, and then offsetting
149 * the view pointer returned by this size.
152 HANDLE WINAPI
SHAllocShared(LPCVOID lpvData
, DWORD dwSize
, DWORD dwProcId
)
158 TRACE("(%p,%d,%d)\n", lpvData
, dwSize
, dwProcId
);
160 /* Create file mapping of the correct length */
161 hMap
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, FILE_MAP_READ
, 0,
162 dwSize
+ sizeof(dwSize
), NULL
);
166 /* Get a view in our process address space */
167 pMapped
= MapViewOfFile(hMap
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
171 /* Write size of data, followed by the data, to the view */
172 *((DWORD
*)pMapped
) = dwSize
;
174 memcpy((char *) pMapped
+ sizeof(dwSize
), lpvData
, dwSize
);
176 /* Release view. All further views mapped will be opaque */
177 UnmapViewOfFile(pMapped
);
178 hRet
= SHLWAPI_DupSharedHandle(hMap
, dwProcId
,
179 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS
,
180 DUPLICATE_SAME_ACCESS
);
187 /*************************************************************************
190 * Get a pointer to a block of shared memory from a shared memory handle.
193 * hShared [I] Shared memory handle
194 * dwProcId [I] ID of process owning hShared
197 * Success: A pointer to the shared memory
201 PVOID WINAPI
SHLockShared(HANDLE hShared
, DWORD dwProcId
)
206 TRACE("(%p %d)\n", hShared
, dwProcId
);
208 /* Get handle to shared memory for current process */
209 hDup
= SHLWAPI_DupSharedHandle(hShared
, dwProcId
, GetCurrentProcessId(),
210 FILE_MAP_ALL_ACCESS
, 0);
212 pMapped
= MapViewOfFile(hDup
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
216 return (char *) pMapped
+ sizeof(DWORD
); /* Hide size */
220 /*************************************************************************
223 * Release a pointer to a block of shared memory.
226 * lpView [I] Shared memory pointer
233 BOOL WINAPI
SHUnlockShared(LPVOID lpView
)
235 TRACE("(%p)\n", lpView
);
236 return UnmapViewOfFile((char *) lpView
- sizeof(DWORD
)); /* Include size */
239 /*************************************************************************
242 * Destroy a block of sharable memory.
245 * hShared [I] Shared memory handle
246 * dwProcId [I] ID of process owning hShared
253 BOOL WINAPI
SHFreeShared(HANDLE hShared
, DWORD dwProcId
)
257 TRACE("(%p %d)\n", hShared
, dwProcId
);
259 /* Get a copy of the handle for our process, closing the source handle */
260 hClose
= SHLWAPI_DupSharedHandle(hShared
, dwProcId
, GetCurrentProcessId(),
261 FILE_MAP_ALL_ACCESS
,DUPLICATE_CLOSE_SOURCE
);
262 /* Close local copy */
263 return CloseHandle(hClose
);
266 /*************************************************************************
269 * Copy a sharable memory handle from one process to another.
272 * hShared [I] Shared memory handle to duplicate
273 * dwDstProcId [I] ID of the process wanting the duplicated handle
274 * dwSrcProcId [I] ID of the process owning hShared
275 * dwAccess [I] Desired DuplicateHandle() access
276 * dwOptions [I] Desired DuplicateHandle() options
279 * Success: A handle suitable for use by the dwDstProcId process.
280 * Failure: A NULL handle.
283 HANDLE WINAPI
SHMapHandle(HANDLE hShared
, DWORD dwDstProcId
, DWORD dwSrcProcId
,
284 DWORD dwAccess
, DWORD dwOptions
)
288 hRet
= SHLWAPI_DupSharedHandle(hShared
, dwDstProcId
, dwSrcProcId
,
289 dwAccess
, dwOptions
);
293 /*************************************************************************
296 * Create and register a clipboard enumerator for a web browser.
299 * lpBC [I] Binding context
300 * lpUnknown [I] An object exposing the IWebBrowserApp interface
304 * Failure: An HRESULT error code.
307 * The enumerator is stored as a property of the web browser. If it does not
308 * yet exist, it is created and set before being registered.
310 HRESULT WINAPI
RegisterDefaultAcceptHeaders(LPBC lpBC
, IUnknown
*lpUnknown
)
312 static const WCHAR szProperty
[] = { '{','D','0','F','C','A','4','2','0',
313 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
314 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
316 IEnumFORMATETC
* pIEnumFormatEtc
= NULL
;
319 IWebBrowserApp
* pBrowser
;
321 TRACE("(%p, %p)\n", lpBC
, lpUnknown
);
323 hr
= IUnknown_QueryService(lpUnknown
, &IID_IWebBrowserApp
, &IID_IWebBrowserApp
, (void**)&pBrowser
);
327 V_VT(&var
) = VT_EMPTY
;
329 /* The property we get is the browsers clipboard enumerator */
330 property
= SysAllocString(szProperty
);
331 hr
= IWebBrowserApp_GetProperty(pBrowser
, property
, &var
);
332 SysFreeString(property
);
333 if (FAILED(hr
)) goto exit
;
335 if (V_VT(&var
) == VT_EMPTY
)
337 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
338 char szKeyBuff
[128], szValueBuff
[128];
339 DWORD dwKeySize
, dwValueSize
, dwRet
= 0, dwCount
= 0, dwNumValues
, dwType
;
340 FORMATETC
* formatList
, *format
;
343 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
345 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\Current"
346 "Version\\Internet Settings\\Accepted Documents", &hDocs
))
352 /* Get count of values in key */
355 dwKeySize
= sizeof(szKeyBuff
);
356 dwRet
= RegEnumValueA(hDocs
,dwCount
,szKeyBuff
,&dwKeySize
,0,&dwType
,0,0);
360 dwNumValues
= dwCount
;
362 /* Note: dwCount = number of items + 1; The extra item is the end node */
363 format
= formatList
= HeapAlloc(GetProcessHeap(), 0, dwCount
* sizeof(FORMATETC
));
378 /* Register clipboard formats for the values and populate format list */
379 while(!dwRet
&& dwCount
< dwNumValues
)
381 dwKeySize
= sizeof(szKeyBuff
);
382 dwValueSize
= sizeof(szValueBuff
);
383 dwRet
= RegEnumValueA(hDocs
, dwCount
, szKeyBuff
, &dwKeySize
, 0, &dwType
,
384 (PBYTE
)szValueBuff
, &dwValueSize
);
387 HeapFree(GetProcessHeap(), 0, formatList
);
393 format
->cfFormat
= RegisterClipboardFormatA(szValueBuff
);
395 format
->dwAspect
= 1;
406 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
407 format
->cfFormat
= 0;
409 format
->dwAspect
= 1;
413 /* Create a clipboard enumerator */
414 hr
= CreateFormatEnumerator(dwNumValues
, formatList
, &pIEnumFormatEtc
);
415 HeapFree(GetProcessHeap(), 0, formatList
);
416 if (FAILED(hr
)) goto exit
;
418 /* Set our enumerator as the browsers property */
419 V_VT(&var
) = VT_UNKNOWN
;
420 V_UNKNOWN(&var
) = (IUnknown
*)pIEnumFormatEtc
;
422 property
= SysAllocString(szProperty
);
423 hr
= IWebBrowserApp_PutProperty(pBrowser
, property
, var
);
424 SysFreeString(property
);
427 IEnumFORMATETC_Release(pIEnumFormatEtc
);
432 if (V_VT(&var
) == VT_UNKNOWN
)
434 /* Our variant is holding the clipboard enumerator */
435 IUnknown
* pIUnknown
= V_UNKNOWN(&var
);
436 IEnumFORMATETC
* pClone
= NULL
;
438 TRACE("Retrieved IEnumFORMATETC property\n");
440 /* Get an IEnumFormatEtc interface from the variants value */
441 pIEnumFormatEtc
= NULL
;
442 hr
= IUnknown_QueryInterface(pIUnknown
, &IID_IEnumFORMATETC
, (void**)&pIEnumFormatEtc
);
443 if (hr
== S_OK
&& pIEnumFormatEtc
)
445 /* Clone and register the enumerator */
446 hr
= IEnumFORMATETC_Clone(pIEnumFormatEtc
, &pClone
);
447 if (hr
== S_OK
&& pClone
)
449 RegisterFormatEnumerator(lpBC
, pClone
, 0);
451 IEnumFORMATETC_Release(pClone
);
454 IUnknown_Release(pIUnknown
);
456 IUnknown_Release(V_UNKNOWN(&var
));
460 IWebBrowserApp_Release(pBrowser
);
464 /*************************************************************************
467 * Get Explorers "AcceptLanguage" setting.
470 * langbuf [O] Destination for language string
471 * buflen [I] Length of langbuf in characters
472 * [0] Success: used length of langbuf
475 * Success: S_OK. langbuf is set to the language string found.
476 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
477 * does not contain the setting.
478 * HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), If the buffer is not big enough
480 HRESULT WINAPI
GetAcceptLanguagesW( LPWSTR langbuf
, LPDWORD buflen
)
482 static const WCHAR szkeyW
[] = {
483 'S','o','f','t','w','a','r','e','\\',
484 'M','i','c','r','o','s','o','f','t','\\',
485 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
486 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
487 static const WCHAR valueW
[] = {
488 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
489 DWORD mystrlen
, mytype
;
496 TRACE("(%p, %p) *%p: %d\n", langbuf
, buflen
, buflen
, buflen
? *buflen
: -1);
498 if(!langbuf
|| !buflen
|| !*buflen
)
501 mystrlen
= (*buflen
> 20) ? *buflen
: 20 ;
502 len
= mystrlen
* sizeof(WCHAR
);
503 mystr
= HeapAlloc(GetProcessHeap(), 0, len
);
505 RegOpenKeyW(HKEY_CURRENT_USER
, szkeyW
, &mykey
);
506 lres
= RegQueryValueExW(mykey
, valueW
, 0, &mytype
, (PBYTE
)mystr
, &len
);
508 len
= lstrlenW(mystr
);
510 if (!lres
&& (*buflen
> len
)) {
511 lstrcpyW(langbuf
, mystr
);
513 HeapFree(GetProcessHeap(), 0, mystr
);
517 /* Did not find a value in the registry or the user buffer is too small */
518 mylcid
= GetUserDefaultLCID();
519 LcidToRfc1766W(mylcid
, mystr
, mystrlen
);
520 len
= lstrlenW(mystr
);
522 memcpy( langbuf
, mystr
, min(*buflen
, len
+1)*sizeof(WCHAR
) );
523 HeapFree(GetProcessHeap(), 0, mystr
);
531 return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
534 /*************************************************************************
537 * Ascii version of GetAcceptLanguagesW.
539 HRESULT WINAPI
GetAcceptLanguagesA( LPSTR langbuf
, LPDWORD buflen
)
542 DWORD buflenW
, convlen
;
545 TRACE("(%p, %p) *%p: %d\n", langbuf
, buflen
, buflen
, buflen
? *buflen
: -1);
547 if(!langbuf
|| !buflen
|| !*buflen
) return E_FAIL
;
550 langbufW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * buflenW
);
551 retval
= GetAcceptLanguagesW(langbufW
, &buflenW
);
555 convlen
= WideCharToMultiByte(CP_ACP
, 0, langbufW
, -1, langbuf
, *buflen
, NULL
, NULL
);
556 convlen
--; /* do not count the terminating 0 */
558 else /* copy partial string anyway */
560 convlen
= WideCharToMultiByte(CP_ACP
, 0, langbufW
, *buflen
, langbuf
, *buflen
, NULL
, NULL
);
561 if (convlen
< *buflen
)
563 langbuf
[convlen
] = 0;
564 convlen
--; /* do not count the terminating 0 */
571 *buflen
= buflenW
? convlen
: 0;
573 HeapFree(GetProcessHeap(), 0, langbufW
);
577 /*************************************************************************
580 * Convert a GUID to a string.
583 * guid [I] GUID to convert
584 * lpszDest [O] Destination for string
585 * cchMax [I] Length of output buffer
588 * The length of the string created.
590 INT WINAPI
SHStringFromGUIDA(REFGUID guid
, LPSTR lpszDest
, INT cchMax
)
595 TRACE("(%s,%p,%d)\n", debugstr_guid(guid
), lpszDest
, cchMax
);
597 sprintf(xguid
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
598 guid
->Data1
, guid
->Data2
, guid
->Data3
,
599 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
600 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
602 iLen
= strlen(xguid
) + 1;
606 memcpy(lpszDest
, xguid
, iLen
);
610 /*************************************************************************
613 * Convert a GUID to a string.
616 * guid [I] GUID to convert
617 * str [O] Destination for string
618 * cmax [I] Length of output buffer
621 * The length of the string created.
623 INT WINAPI
SHStringFromGUIDW(REFGUID guid
, LPWSTR lpszDest
, INT cchMax
)
627 static const WCHAR wszFormat
[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
628 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
629 'X','%','0','2','X','%','0','2','X','}',0};
631 TRACE("(%s,%p,%d)\n", debugstr_guid(guid
), lpszDest
, cchMax
);
633 sprintfW(xguid
, wszFormat
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
634 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
635 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
637 iLen
= strlenW(xguid
) + 1;
641 memcpy(lpszDest
, xguid
, iLen
*sizeof(WCHAR
));
645 /*************************************************************************
648 * Determine if a Unicode character is a blank.
651 * wc [I] Character to check.
654 * TRUE, if wc is a blank,
658 BOOL WINAPI
IsCharBlankW(WCHAR wc
)
662 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_BLANK
);
665 /*************************************************************************
668 * Determine if a Unicode character is punctuation.
671 * wc [I] Character to check.
674 * TRUE, if wc is punctuation,
677 BOOL WINAPI
IsCharPunctW(WCHAR wc
)
681 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_PUNCT
);
684 /*************************************************************************
687 * Determine if a Unicode character is a control character.
690 * wc [I] Character to check.
693 * TRUE, if wc is a control character,
696 BOOL WINAPI
IsCharCntrlW(WCHAR wc
)
700 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_CNTRL
);
703 /*************************************************************************
706 * Determine if a Unicode character is a digit.
709 * wc [I] Character to check.
712 * TRUE, if wc is a digit,
715 BOOL WINAPI
IsCharDigitW(WCHAR wc
)
719 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_DIGIT
);
722 /*************************************************************************
725 * Determine if a Unicode character is a hex digit.
728 * wc [I] Character to check.
731 * TRUE, if wc is a hex digit,
734 BOOL WINAPI
IsCharXDigitW(WCHAR wc
)
738 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_XDIGIT
);
741 /*************************************************************************
745 BOOL WINAPI
GetStringType3ExW(LPWSTR src
, INT count
, LPWORD type
)
747 return GetStringTypeW(CT_CTYPE3
, src
, count
, type
);
750 /*************************************************************************
753 * Compare two Ascii strings up to a given length.
756 * lpszSrc [I] Source string
757 * lpszCmp [I] String to compare to lpszSrc
758 * len [I] Maximum length
761 * A number greater than, less than or equal to 0 depending on whether
762 * lpszSrc is greater than, less than or equal to lpszCmp.
764 DWORD WINAPI
StrCmpNCA(LPCSTR lpszSrc
, LPCSTR lpszCmp
, INT len
)
766 return StrCmpNA(lpszSrc
, lpszCmp
, len
);
769 /*************************************************************************
772 * Unicode version of StrCmpNCA.
774 DWORD WINAPI
StrCmpNCW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
, INT len
)
776 return StrCmpNW(lpszSrc
, lpszCmp
, len
);
779 /*************************************************************************
782 * Compare two Ascii strings up to a given length, ignoring case.
785 * lpszSrc [I] Source string
786 * lpszCmp [I] String to compare to lpszSrc
787 * len [I] Maximum length
790 * A number greater than, less than or equal to 0 depending on whether
791 * lpszSrc is greater than, less than or equal to lpszCmp.
793 DWORD WINAPI
StrCmpNICA(LPCSTR lpszSrc
, LPCSTR lpszCmp
, DWORD len
)
795 return StrCmpNIA(lpszSrc
, lpszCmp
, len
);
798 /*************************************************************************
801 * Unicode version of StrCmpNICA.
803 DWORD WINAPI
StrCmpNICW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
, DWORD len
)
805 return StrCmpNIW(lpszSrc
, lpszCmp
, len
);
808 /*************************************************************************
811 * Compare two Ascii strings.
814 * lpszSrc [I] Source string
815 * lpszCmp [I] String to compare to lpszSrc
818 * A number greater than, less than or equal to 0 depending on whether
819 * lpszSrc is greater than, less than or equal to lpszCmp.
821 DWORD WINAPI
StrCmpCA(LPCSTR lpszSrc
, LPCSTR lpszCmp
)
823 return lstrcmpA(lpszSrc
, lpszCmp
);
826 /*************************************************************************
829 * Unicode version of StrCmpCA.
831 DWORD WINAPI
StrCmpCW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
)
833 return lstrcmpW(lpszSrc
, lpszCmp
);
836 /*************************************************************************
839 * Compare two Ascii strings, ignoring case.
842 * lpszSrc [I] Source string
843 * lpszCmp [I] String to compare to lpszSrc
846 * A number greater than, less than or equal to 0 depending on whether
847 * lpszSrc is greater than, less than or equal to lpszCmp.
849 DWORD WINAPI
StrCmpICA(LPCSTR lpszSrc
, LPCSTR lpszCmp
)
851 return lstrcmpiA(lpszSrc
, lpszCmp
);
854 /*************************************************************************
857 * Unicode version of StrCmpICA.
859 DWORD WINAPI
StrCmpICW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
)
861 return lstrcmpiW(lpszSrc
, lpszCmp
);
864 /*************************************************************************
867 * Get an identification string for the OS and explorer.
870 * lpszDest [O] Destination for Id string
871 * dwDestLen [I] Length of lpszDest
874 * TRUE, If the string was created successfully
877 BOOL WINAPI
SHAboutInfoA(LPSTR lpszDest
, DWORD dwDestLen
)
881 TRACE("(%p,%d)\n", lpszDest
, dwDestLen
);
883 if (lpszDest
&& SHAboutInfoW(buff
, dwDestLen
))
885 WideCharToMultiByte(CP_ACP
, 0, buff
, -1, lpszDest
, dwDestLen
, NULL
, NULL
);
891 /*************************************************************************
894 * Unicode version of SHAboutInfoA.
896 BOOL WINAPI
SHAboutInfoW(LPWSTR lpszDest
, DWORD dwDestLen
)
898 static const WCHAR szIEKey
[] = { 'S','O','F','T','W','A','R','E','\\',
899 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
900 ' ','E','x','p','l','o','r','e','r','\0' };
901 static const WCHAR szWinNtKey
[] = { 'S','O','F','T','W','A','R','E','\\',
902 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
903 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
904 static const WCHAR szWinKey
[] = { 'S','O','F','T','W','A','R','E','\\',
905 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
906 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
907 static const WCHAR szRegKey
[] = { 'S','O','F','T','W','A','R','E','\\',
908 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
909 ' ','E','x','p','l','o','r','e','r','\\',
910 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
911 static const WCHAR szVersion
[] = { 'V','e','r','s','i','o','n','\0' };
912 static const WCHAR szCustomized
[] = { 'C','u','s','t','o','m','i','z','e','d',
913 'V','e','r','s','i','o','n','\0' };
914 static const WCHAR szOwner
[] = { 'R','e','g','i','s','t','e','r','e','d',
915 'O','w','n','e','r','\0' };
916 static const WCHAR szOrg
[] = { 'R','e','g','i','s','t','e','r','e','d',
917 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
918 static const WCHAR szProduct
[] = { 'P','r','o','d','u','c','t','I','d','\0' };
919 static const WCHAR szUpdate
[] = { 'I','E','A','K',
920 'U','p','d','a','t','e','U','r','l','\0' };
921 static const WCHAR szHelp
[] = { 'I','E','A','K',
922 'H','e','l','p','S','t','r','i','n','g','\0' };
927 TRACE("(%p,%d)\n", lpszDest
, dwDestLen
);
934 /* Try the NT key first, followed by 95/98 key */
935 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szWinNtKey
, 0, KEY_READ
, &hReg
) &&
936 RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szWinKey
, 0, KEY_READ
, &hReg
))
942 if (!SHGetValueW(HKEY_LOCAL_MACHINE
, szIEKey
, szVersion
, &dwType
, buff
, &dwLen
))
944 DWORD dwStrLen
= strlenW(buff
);
945 dwLen
= 30 - dwStrLen
;
946 SHGetValueW(HKEY_LOCAL_MACHINE
, szIEKey
,
947 szCustomized
, &dwType
, buff
+dwStrLen
, &dwLen
);
949 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
951 /* ~Registered Owner */
954 if (SHGetValueW(hReg
, szOwner
, 0, &dwType
, buff
+1, &dwLen
))
956 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
958 /* ~Registered Organization */
960 if (SHGetValueW(hReg
, szOrg
, 0, &dwType
, buff
+1, &dwLen
))
962 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
964 /* FIXME: Not sure where this number comes from */
968 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
972 if (SHGetValueW(HKEY_LOCAL_MACHINE
, szRegKey
, szProduct
, &dwType
, buff
+1, &dwLen
))
974 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
978 if(SHGetValueW(HKEY_LOCAL_MACHINE
, szWinKey
, szUpdate
, &dwType
, buff
+1, &dwLen
))
980 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
982 /* ~IE Help String */
984 if(SHGetValueW(hReg
, szHelp
, 0, &dwType
, buff
+1, &dwLen
))
986 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
992 /*************************************************************************
995 * Call IOleCommandTarget_QueryStatus() on an object.
998 * lpUnknown [I] Object supporting the IOleCommandTarget interface
999 * pguidCmdGroup [I] GUID for the command group
1001 * prgCmds [O] Commands
1002 * pCmdText [O] Command text
1006 * Failure: E_FAIL, if lpUnknown is NULL.
1007 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1008 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1010 HRESULT WINAPI
IUnknown_QueryStatus(IUnknown
* lpUnknown
, REFGUID pguidCmdGroup
,
1011 ULONG cCmds
, OLECMD
*prgCmds
, OLECMDTEXT
* pCmdText
)
1013 HRESULT hRet
= E_FAIL
;
1015 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown
, pguidCmdGroup
, cCmds
, prgCmds
, pCmdText
);
1019 IOleCommandTarget
* lpOle
;
1021 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleCommandTarget
,
1024 if (SUCCEEDED(hRet
) && lpOle
)
1026 hRet
= IOleCommandTarget_QueryStatus(lpOle
, pguidCmdGroup
, cCmds
,
1028 IOleCommandTarget_Release(lpOle
);
1034 /*************************************************************************
1037 * Call IOleCommandTarget_Exec() on an object.
1040 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1041 * pguidCmdGroup [I] GUID for the command group
1045 * Failure: E_FAIL, if lpUnknown is NULL.
1046 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1047 * Otherwise, an error code from IOleCommandTarget_Exec().
1049 HRESULT WINAPI
IUnknown_Exec(IUnknown
* lpUnknown
, REFGUID pguidCmdGroup
,
1050 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
* pvaIn
,
1053 HRESULT hRet
= E_FAIL
;
1055 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown
, pguidCmdGroup
, nCmdID
,
1056 nCmdexecopt
, pvaIn
, pvaOut
);
1060 IOleCommandTarget
* lpOle
;
1062 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleCommandTarget
,
1064 if (SUCCEEDED(hRet
) && lpOle
)
1066 hRet
= IOleCommandTarget_Exec(lpOle
, pguidCmdGroup
, nCmdID
,
1067 nCmdexecopt
, pvaIn
, pvaOut
);
1068 IOleCommandTarget_Release(lpOle
);
1074 /*************************************************************************
1077 * Retrieve, modify, and re-set a value from a window.
1080 * hWnd [I] Window to get value from
1081 * offset [I] Offset of value
1082 * mask [I] Mask for flags
1083 * flags [I] Bits to set in window value
1086 * The new value as it was set, or 0 if any parameter is invalid.
1089 * Only bits specified in mask are affected - set if present in flags and
1092 LONG WINAPI
SHSetWindowBits(HWND hwnd
, INT offset
, UINT mask
, UINT flags
)
1094 LONG ret
= GetWindowLongW(hwnd
, offset
);
1095 LONG new_flags
= (flags
& mask
) | (ret
& ~mask
);
1097 TRACE("%p %d %x %x\n", hwnd
, offset
, mask
, flags
);
1099 if (new_flags
!= ret
)
1100 ret
= SetWindowLongW(hwnd
, offset
, new_flags
);
1104 /*************************************************************************
1107 * Change a window's parent.
1110 * hWnd [I] Window to change parent of
1111 * hWndParent [I] New parent window
1114 * The old parent of hWnd.
1117 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1118 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1120 HWND WINAPI
SHSetParentHwnd(HWND hWnd
, HWND hWndParent
)
1122 TRACE("%p, %p\n", hWnd
, hWndParent
);
1124 if(GetParent(hWnd
) == hWndParent
)
1128 SHSetWindowBits(hWnd
, GWL_STYLE
, WS_CHILD
| WS_POPUP
, WS_CHILD
);
1130 SHSetWindowBits(hWnd
, GWL_STYLE
, WS_CHILD
| WS_POPUP
, WS_POPUP
);
1132 return hWndParent
? SetParent(hWnd
, hWndParent
) : NULL
;
1135 /*************************************************************************
1138 * Locate and advise a connection point in an IConnectionPointContainer object.
1141 * lpUnkSink [I] Sink for the connection point advise call
1142 * riid [I] REFIID of connection point to advise
1143 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1144 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1145 * lpCookie [O] Pointer to connection point cookie
1146 * lppCP [O] Destination for the IConnectionPoint found
1149 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1150 * that was advised. The caller is responsible for releasing it.
1151 * Failure: E_FAIL, if any arguments are invalid.
1152 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1153 * Or an HRESULT error code if any call fails.
1155 HRESULT WINAPI
ConnectToConnectionPoint(IUnknown
* lpUnkSink
, REFIID riid
, BOOL fConnect
,
1156 IUnknown
* lpUnknown
, LPDWORD lpCookie
,
1157 IConnectionPoint
**lppCP
)
1160 IConnectionPointContainer
* lpContainer
;
1161 IConnectionPoint
*lpCP
;
1163 if(!lpUnknown
|| (fConnect
&& !lpUnkSink
))
1169 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IConnectionPointContainer
,
1170 (void**)&lpContainer
);
1171 if (SUCCEEDED(hRet
))
1173 hRet
= IConnectionPointContainer_FindConnectionPoint(lpContainer
, riid
, &lpCP
);
1175 if (SUCCEEDED(hRet
))
1178 hRet
= IConnectionPoint_Unadvise(lpCP
, *lpCookie
);
1180 hRet
= IConnectionPoint_Advise(lpCP
, lpUnkSink
, lpCookie
);
1185 if (lppCP
&& SUCCEEDED(hRet
))
1186 *lppCP
= lpCP
; /* Caller keeps the interface */
1188 IConnectionPoint_Release(lpCP
); /* Release it */
1191 IConnectionPointContainer_Release(lpContainer
);
1196 /*************************************************************************
1199 * Release an interface and zero a supplied pointer.
1202 * lpUnknown [I] Object to release
1207 void WINAPI
IUnknown_AtomicRelease(IUnknown
** lpUnknown
)
1209 TRACE("(%p)\n", lpUnknown
);
1211 if(!lpUnknown
|| !*lpUnknown
) return;
1213 TRACE("doing Release\n");
1215 IUnknown_Release(*lpUnknown
);
1219 /*************************************************************************
1222 * Skip '//' if present in a string.
1225 * lpszSrc [I] String to check for '//'
1228 * Success: The next character after the '//' or the string if not present
1229 * Failure: NULL, if lpszStr is NULL.
1231 LPCSTR WINAPI
PathSkipLeadingSlashesA(LPCSTR lpszSrc
)
1233 if (lpszSrc
&& lpszSrc
[0] == '/' && lpszSrc
[1] == '/')
1238 /*************************************************************************
1241 * Check if two interfaces come from the same object.
1244 * lpInt1 [I] Interface to check against lpInt2.
1245 * lpInt2 [I] Interface to check against lpInt1.
1248 * TRUE, If the interfaces come from the same object.
1251 BOOL WINAPI
SHIsSameObject(IUnknown
* lpInt1
, IUnknown
* lpInt2
)
1253 IUnknown
*lpUnknown1
, *lpUnknown2
;
1256 TRACE("(%p %p)\n", lpInt1
, lpInt2
);
1258 if (!lpInt1
|| !lpInt2
)
1261 if (lpInt1
== lpInt2
)
1264 if (IUnknown_QueryInterface(lpInt1
, &IID_IUnknown
, (void**)&lpUnknown1
) != S_OK
)
1267 if (IUnknown_QueryInterface(lpInt2
, &IID_IUnknown
, (void**)&lpUnknown2
) != S_OK
)
1269 IUnknown_Release(lpUnknown1
);
1273 ret
= lpUnknown1
== lpUnknown2
;
1275 IUnknown_Release(lpUnknown1
);
1276 IUnknown_Release(lpUnknown2
);
1281 /*************************************************************************
1284 * Get the window handle of an object.
1287 * lpUnknown [I] Object to get the window handle of
1288 * lphWnd [O] Destination for window handle
1291 * Success: S_OK. lphWnd contains the objects window handle.
1292 * Failure: An HRESULT error code.
1295 * lpUnknown is expected to support one of the following interfaces:
1296 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1298 HRESULT WINAPI
IUnknown_GetWindow(IUnknown
*lpUnknown
, HWND
*lphWnd
)
1301 HRESULT hRet
= E_FAIL
;
1303 TRACE("(%p,%p)\n", lpUnknown
, lphWnd
);
1308 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleWindow
, (void**)&lpOle
);
1312 hRet
= IUnknown_QueryInterface(lpUnknown
,&IID_IShellView
, (void**)&lpOle
);
1316 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInternetSecurityMgrSite
,
1321 if (SUCCEEDED(hRet
))
1323 /* Laziness here - Since GetWindow() is the first method for the above 3
1324 * interfaces, we use the same call for them all.
1326 hRet
= IOleWindow_GetWindow((IOleWindow
*)lpOle
, lphWnd
);
1327 IUnknown_Release(lpOle
);
1329 TRACE("Returning HWND=%p\n", *lphWnd
);
1335 /*************************************************************************
1338 * Call a SetOwner method of IShellService from specified object.
1341 * iface [I] Object that supports IShellService
1342 * pUnk [I] Argument for the SetOwner call
1345 * Corresponding return value from last call or E_FAIL for null input
1347 HRESULT WINAPI
IUnknown_SetOwner(IUnknown
*iface
, IUnknown
*pUnk
)
1349 IShellService
*service
;
1352 TRACE("(%p, %p)\n", iface
, pUnk
);
1354 if (!iface
) return E_FAIL
;
1356 hr
= IUnknown_QueryInterface(iface
, &IID_IShellService
, (void**)&service
);
1359 hr
= IShellService_SetOwner(service
, pUnk
);
1360 IShellService_Release(service
);
1366 /*************************************************************************
1369 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1373 HRESULT WINAPI
IUnknown_SetSite(
1374 IUnknown
*obj
, /* [in] OLE object */
1375 IUnknown
*site
) /* [in] Site interface */
1378 IObjectWithSite
*iobjwithsite
;
1379 IInternetSecurityManager
*isecmgr
;
1381 if (!obj
) return E_FAIL
;
1383 hr
= IUnknown_QueryInterface(obj
, &IID_IObjectWithSite
, (LPVOID
*)&iobjwithsite
);
1384 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr
, iobjwithsite
);
1387 hr
= IObjectWithSite_SetSite(iobjwithsite
, site
);
1388 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr
);
1389 IObjectWithSite_Release(iobjwithsite
);
1393 hr
= IUnknown_QueryInterface(obj
, &IID_IInternetSecurityManager
, (LPVOID
*)&isecmgr
);
1394 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr
, isecmgr
);
1395 if (FAILED(hr
)) return hr
;
1397 hr
= IInternetSecurityManager_SetSecuritySite(isecmgr
, (IInternetSecurityMgrSite
*)site
);
1398 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr
);
1399 IInternetSecurityManager_Release(isecmgr
);
1404 /*************************************************************************
1407 * Call IPersist_GetClassID() on an object.
1410 * lpUnknown [I] Object supporting the IPersist interface
1411 * lpClassId [O] Destination for Class Id
1414 * Success: S_OK. lpClassId contains the Class Id requested.
1415 * Failure: E_FAIL, If lpUnknown is NULL,
1416 * E_NOINTERFACE If lpUnknown does not support IPersist,
1417 * Or an HRESULT error code.
1419 HRESULT WINAPI
IUnknown_GetClassID(IUnknown
*lpUnknown
, CLSID
* lpClassId
)
1421 IPersist
* lpPersist
;
1422 HRESULT hRet
= E_FAIL
;
1424 TRACE("(%p,%s)\n", lpUnknown
, debugstr_guid(lpClassId
));
1428 hRet
= IUnknown_QueryInterface(lpUnknown
,&IID_IPersist
,(void**)&lpPersist
);
1429 if (SUCCEEDED(hRet
))
1431 IPersist_GetClassID(lpPersist
, lpClassId
);
1432 IPersist_Release(lpPersist
);
1438 /*************************************************************************
1441 * Retrieve a Service Interface from an object.
1444 * lpUnknown [I] Object to get an IServiceProvider interface from
1445 * sid [I] Service ID for IServiceProvider_QueryService() call
1446 * riid [I] Function requested for QueryService call
1447 * lppOut [O] Destination for the service interface pointer
1450 * Success: S_OK. lppOut contains an object providing the requested service
1451 * Failure: An HRESULT error code
1454 * lpUnknown is expected to support the IServiceProvider interface.
1456 HRESULT WINAPI
IUnknown_QueryService(IUnknown
* lpUnknown
, REFGUID sid
, REFIID riid
,
1459 IServiceProvider
* pService
= NULL
;
1470 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IServiceProvider
,
1471 (LPVOID
*)&pService
);
1473 if (hRet
== S_OK
&& pService
)
1475 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService
);
1477 /* Get a Service interface from the object */
1478 hRet
= IServiceProvider_QueryService(pService
, sid
, riid
, lppOut
);
1480 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService
, *lppOut
);
1482 IServiceProvider_Release(pService
);
1487 /*************************************************************************
1490 * Calls IOleCommandTarget::Exec() for specified service object.
1493 * lpUnknown [I] Object to get an IServiceProvider interface from
1494 * service [I] Service ID for IServiceProvider_QueryService() call
1495 * group [I] Group ID for IOleCommandTarget::Exec() call
1496 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1497 * cmdOpt [I] Options flags for command
1498 * pIn [I] Input arguments for command
1499 * pOut [O] Output arguments for command
1502 * Success: S_OK. lppOut contains an object providing the requested service
1503 * Failure: An HRESULT error code
1506 * lpUnknown is expected to support the IServiceProvider interface.
1508 HRESULT WINAPI
IUnknown_QueryServiceExec(IUnknown
*lpUnknown
, REFIID service
,
1509 const GUID
*group
, DWORD cmdId
, DWORD cmdOpt
, VARIANT
*pIn
, VARIANT
*pOut
)
1511 IOleCommandTarget
*target
;
1514 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown
, debugstr_guid(service
),
1515 debugstr_guid(group
), cmdId
, cmdOpt
, pIn
, pOut
);
1517 hr
= IUnknown_QueryService(lpUnknown
, service
, &IID_IOleCommandTarget
, (void**)&target
);
1520 hr
= IOleCommandTarget_Exec(target
, group
, cmdId
, cmdOpt
, pIn
, pOut
);
1521 IOleCommandTarget_Release(target
);
1524 TRACE("<-- hr=0x%08x\n", hr
);
1529 /*************************************************************************
1532 * Calls IProfferService methods to proffer/revoke specified service.
1535 * lpUnknown [I] Object to get an IServiceProvider interface from
1536 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1537 * pService [I] Service to proffer. If NULL ::Revoke is called
1538 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1541 * Success: S_OK. IProffer method returns S_OK
1542 * Failure: An HRESULT error code
1545 * lpUnknown is expected to support the IServiceProvider interface.
1547 HRESULT WINAPI
IUnknown_ProfferService(IUnknown
*lpUnknown
, REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
1549 IProfferService
*proffer
;
1552 TRACE("%p %s %p %p\n", lpUnknown
, debugstr_guid(service
), pService
, pCookie
);
1554 hr
= IUnknown_QueryService(lpUnknown
, &IID_IProfferService
, &IID_IProfferService
, (void**)&proffer
);
1558 hr
= IProfferService_ProfferService(proffer
, service
, pService
, pCookie
);
1561 hr
= IProfferService_RevokeService(proffer
, *pCookie
);
1565 IProfferService_Release(proffer
);
1571 /*************************************************************************
1574 * Call an object's UIActivateIO method.
1577 * unknown [I] Object to call the UIActivateIO method on
1578 * activate [I] Parameter for UIActivateIO call
1579 * msg [I] Parameter for UIActivateIO call
1582 * Success: Value of UI_ActivateIO call
1583 * Failure: An HRESULT error code
1586 * unknown is expected to support the IInputObject interface.
1588 HRESULT WINAPI
IUnknown_UIActivateIO(IUnknown
*unknown
, BOOL activate
, LPMSG msg
)
1590 IInputObject
* object
= NULL
;
1596 /* Get an IInputObject interface from the object */
1597 ret
= IUnknown_QueryInterface(unknown
, &IID_IInputObject
, (LPVOID
*) &object
);
1601 ret
= IInputObject_UIActivateIO(object
, activate
, msg
);
1602 IInputObject_Release(object
);
1608 /*************************************************************************
1611 * Loads a popup menu.
1614 * hInst [I] Instance handle
1615 * szName [I] Menu name
1621 BOOL WINAPI
SHLoadMenuPopup(HINSTANCE hInst
, LPCWSTR szName
)
1625 TRACE("%p %s\n", hInst
, debugstr_w(szName
));
1627 if ((hMenu
= LoadMenuW(hInst
, szName
)))
1629 if (GetSubMenu(hMenu
, 0))
1630 RemoveMenu(hMenu
, 0, MF_BYPOSITION
);
1638 typedef struct _enumWndData
1643 LRESULT (WINAPI
*pfnPost
)(HWND
,UINT
,WPARAM
,LPARAM
);
1646 /* Callback for SHLWAPI_178 */
1647 static BOOL CALLBACK
SHLWAPI_EnumChildProc(HWND hWnd
, LPARAM lParam
)
1649 enumWndData
*data
= (enumWndData
*)lParam
;
1651 TRACE("(%p,%p)\n", hWnd
, data
);
1652 data
->pfnPost(hWnd
, data
->uiMsgId
, data
->wParam
, data
->lParam
);
1656 /*************************************************************************
1659 * Send or post a message to every child of a window.
1662 * hWnd [I] Window whose children will get the messages
1663 * uiMsgId [I] Message Id
1664 * wParam [I] WPARAM of message
1665 * lParam [I] LPARAM of message
1666 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1672 * The appropriate ASCII or Unicode function is called for the window.
1674 void WINAPI
SHPropagateMessage(HWND hWnd
, UINT uiMsgId
, WPARAM wParam
, LPARAM lParam
, BOOL bSend
)
1678 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd
, uiMsgId
, wParam
, lParam
, bSend
);
1682 data
.uiMsgId
= uiMsgId
;
1683 data
.wParam
= wParam
;
1684 data
.lParam
= lParam
;
1687 data
.pfnPost
= IsWindowUnicode(hWnd
) ? (void*)SendMessageW
: (void*)SendMessageA
;
1689 data
.pfnPost
= IsWindowUnicode(hWnd
) ? (void*)PostMessageW
: (void*)PostMessageA
;
1691 EnumChildWindows(hWnd
, SHLWAPI_EnumChildProc
, (LPARAM
)&data
);
1695 /*************************************************************************
1698 * Remove all sub-menus from a menu.
1701 * hMenu [I] Menu to remove sub-menus from
1704 * Success: 0. All sub-menus under hMenu are removed
1705 * Failure: -1, if any parameter is invalid
1707 DWORD WINAPI
SHRemoveAllSubMenus(HMENU hMenu
)
1709 int iItemCount
= GetMenuItemCount(hMenu
) - 1;
1711 TRACE("%p\n", hMenu
);
1713 while (iItemCount
>= 0)
1715 HMENU hSubMenu
= GetSubMenu(hMenu
, iItemCount
);
1717 RemoveMenu(hMenu
, iItemCount
, MF_BYPOSITION
);
1723 /*************************************************************************
1726 * Enable or disable a menu item.
1729 * hMenu [I] Menu holding menu item
1730 * uID [I] ID of menu item to enable/disable
1731 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1734 * The return code from EnableMenuItem.
1736 UINT WINAPI
SHEnableMenuItem(HMENU hMenu
, UINT wItemID
, BOOL bEnable
)
1738 TRACE("%p, %u, %d\n", hMenu
, wItemID
, bEnable
);
1739 return EnableMenuItem(hMenu
, wItemID
, bEnable
? MF_ENABLED
: MF_GRAYED
);
1742 /*************************************************************************
1745 * Check or uncheck a menu item.
1748 * hMenu [I] Menu holding menu item
1749 * uID [I] ID of menu item to check/uncheck
1750 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1753 * The return code from CheckMenuItem.
1755 DWORD WINAPI
SHCheckMenuItem(HMENU hMenu
, UINT uID
, BOOL bCheck
)
1757 TRACE("%p, %u, %d\n", hMenu
, uID
, bCheck
);
1758 return CheckMenuItem(hMenu
, uID
, bCheck
? MF_CHECKED
: MF_UNCHECKED
);
1761 /*************************************************************************
1764 * Register a window class if it isn't already.
1767 * lpWndClass [I] Window class to register
1770 * The result of the RegisterClassA call.
1772 DWORD WINAPI
SHRegisterClassA(WNDCLASSA
*wndclass
)
1775 if (GetClassInfoA(wndclass
->hInstance
, wndclass
->lpszClassName
, &wca
))
1777 return (DWORD
)RegisterClassA(wndclass
);
1780 /*************************************************************************
1783 BOOL WINAPI
SHSimulateDrop(IDropTarget
*pDrop
, IDataObject
*pDataObj
,
1784 DWORD grfKeyState
, PPOINTL lpPt
, DWORD
* pdwEffect
)
1786 DWORD dwEffect
= DROPEFFECT_LINK
| DROPEFFECT_MOVE
| DROPEFFECT_COPY
;
1787 POINTL pt
= { 0, 0 };
1789 TRACE("%p %p 0x%08x %p %p\n", pDrop
, pDataObj
, grfKeyState
, lpPt
, pdwEffect
);
1795 pdwEffect
= &dwEffect
;
1797 IDropTarget_DragEnter(pDrop
, pDataObj
, grfKeyState
, *lpPt
, pdwEffect
);
1799 if (*pdwEffect
!= DROPEFFECT_NONE
)
1800 return IDropTarget_Drop(pDrop
, pDataObj
, grfKeyState
, *lpPt
, pdwEffect
);
1802 IDropTarget_DragLeave(pDrop
);
1806 /*************************************************************************
1809 * Call IPersistPropertyBag_Load() on an object.
1812 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1813 * lpPropBag [O] Destination for loaded IPropertyBag
1817 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1819 DWORD WINAPI
SHLoadFromPropertyBag(IUnknown
*lpUnknown
, IPropertyBag
* lpPropBag
)
1821 IPersistPropertyBag
* lpPPBag
;
1822 HRESULT hRet
= E_FAIL
;
1824 TRACE("(%p,%p)\n", lpUnknown
, lpPropBag
);
1828 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IPersistPropertyBag
,
1830 if (SUCCEEDED(hRet
) && lpPPBag
)
1832 hRet
= IPersistPropertyBag_Load(lpPPBag
, lpPropBag
, NULL
);
1833 IPersistPropertyBag_Release(lpPPBag
);
1839 /*************************************************************************
1842 * Call IOleControlSite_TranslateAccelerator() on an object.
1845 * lpUnknown [I] Object supporting the IOleControlSite interface.
1846 * lpMsg [I] Key message to be processed.
1847 * dwModifiers [I] Flags containing the state of the modifier keys.
1851 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1853 HRESULT WINAPI
IUnknown_TranslateAcceleratorOCS(IUnknown
*lpUnknown
, LPMSG lpMsg
, DWORD dwModifiers
)
1855 IOleControlSite
* lpCSite
= NULL
;
1856 HRESULT hRet
= E_INVALIDARG
;
1858 TRACE("(%p,%p,0x%08x)\n", lpUnknown
, lpMsg
, dwModifiers
);
1861 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleControlSite
,
1863 if (SUCCEEDED(hRet
) && lpCSite
)
1865 hRet
= IOleControlSite_TranslateAccelerator(lpCSite
, lpMsg
, dwModifiers
);
1866 IOleControlSite_Release(lpCSite
);
1873 /*************************************************************************
1876 * Call IOleControlSite_OnFocus() on an object.
1879 * lpUnknown [I] Object supporting the IOleControlSite interface.
1880 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1884 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1886 HRESULT WINAPI
IUnknown_OnFocusOCS(IUnknown
*lpUnknown
, BOOL fGotFocus
)
1888 IOleControlSite
* lpCSite
= NULL
;
1889 HRESULT hRet
= E_FAIL
;
1891 TRACE("(%p, %d)\n", lpUnknown
, fGotFocus
);
1894 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleControlSite
,
1896 if (SUCCEEDED(hRet
) && lpCSite
)
1898 hRet
= IOleControlSite_OnFocus(lpCSite
, fGotFocus
);
1899 IOleControlSite_Release(lpCSite
);
1905 /*************************************************************************
1908 HRESULT WINAPI
IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown
, PVOID lpArg1
,
1909 PVOID lpArg2
, PVOID lpArg3
, PVOID lpArg4
)
1911 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1912 static const DWORD service_id
[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1913 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1914 static const DWORD function_id
[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1915 HRESULT hRet
= E_INVALIDARG
;
1916 LPUNKNOWN lpUnkInner
= NULL
; /* FIXME: Real type is unknown */
1918 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown
, lpArg1
, lpArg2
, lpArg3
, lpArg4
);
1920 if (lpUnknown
&& lpArg4
)
1922 hRet
= IUnknown_QueryService(lpUnknown
, (REFGUID
)service_id
,
1923 (REFGUID
)function_id
, (void**)&lpUnkInner
);
1925 if (SUCCEEDED(hRet
) && lpUnkInner
)
1927 /* FIXME: The type of service object requested is unknown, however
1928 * testing shows that its first method is called with 4 parameters.
1929 * Fake this by using IParseDisplayName_ParseDisplayName since the
1930 * signature and position in the vtable matches our unknown object type.
1932 hRet
= IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME
)lpUnkInner
,
1933 lpArg1
, lpArg2
, lpArg3
, lpArg4
);
1934 IUnknown_Release(lpUnkInner
);
1940 /*************************************************************************
1943 * Get a sub-menu from a menu item.
1946 * hMenu [I] Menu to get sub-menu from
1947 * uID [I] ID of menu item containing sub-menu
1950 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1952 HMENU WINAPI
SHGetMenuFromID(HMENU hMenu
, UINT uID
)
1956 TRACE("(%p,%u)\n", hMenu
, uID
);
1958 mi
.cbSize
= sizeof(mi
);
1959 mi
.fMask
= MIIM_SUBMENU
;
1961 if (!GetMenuItemInfoW(hMenu
, uID
, FALSE
, &mi
))
1967 /*************************************************************************
1970 * Get the color depth of the primary display.
1976 * The color depth of the primary display.
1978 DWORD WINAPI
SHGetCurColorRes(void)
1986 ret
= GetDeviceCaps(hdc
, BITSPIXEL
) * GetDeviceCaps(hdc
, PLANES
);
1991 /*************************************************************************
1994 * Wait for a message to arrive, with a timeout.
1997 * hand [I] Handle to query
1998 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
2001 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
2002 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
2003 * message is available.
2005 DWORD WINAPI
SHWaitForSendMessageThread(HANDLE hand
, DWORD dwTimeout
)
2007 DWORD dwEndTicks
= GetTickCount() + dwTimeout
;
2010 while ((dwRet
= MsgWaitForMultipleObjectsEx(1, &hand
, dwTimeout
, QS_SENDMESSAGE
, 0)) == 1)
2014 PeekMessageW(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
2016 if (dwTimeout
!= INFINITE
)
2018 if ((int)(dwTimeout
= dwEndTicks
- GetTickCount()) <= 0)
2019 return WAIT_TIMEOUT
;
2026 /*************************************************************************
2029 * Determine if a shell folder can be expanded.
2032 * lpFolder [I] Parent folder containing the object to test.
2033 * pidl [I] Id of the object to test.
2036 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2037 * Failure: E_INVALIDARG, if any argument is invalid.
2040 * If the object to be tested does not expose the IQueryInfo() interface it
2041 * will not be identified as an expandable folder.
2043 HRESULT WINAPI
SHIsExpandableFolder(LPSHELLFOLDER lpFolder
, LPCITEMIDLIST pidl
)
2045 HRESULT hRet
= E_INVALIDARG
;
2048 if (lpFolder
&& pidl
)
2050 hRet
= IShellFolder_GetUIObjectOf(lpFolder
, NULL
, 1, &pidl
, &IID_IQueryInfo
,
2051 NULL
, (void**)&lpInfo
);
2053 hRet
= S_FALSE
; /* Doesn't expose IQueryInfo */
2058 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2059 * currently used". Really? You wouldn't be holding out on me would you?
2061 hRet
= IQueryInfo_GetInfoFlags(lpInfo
, &dwFlags
);
2063 if (SUCCEEDED(hRet
))
2065 /* 0x2 is an undocumented flag apparently indicating expandability */
2066 hRet
= dwFlags
& 0x2 ? S_OK
: S_FALSE
;
2069 IQueryInfo_Release(lpInfo
);
2075 /*************************************************************************
2078 * Blank out a region of text by drawing the background only.
2081 * hDC [I] Device context to draw in
2082 * pRect [I] Area to draw in
2083 * cRef [I] Color to draw in
2088 DWORD WINAPI
SHFillRectClr(HDC hDC
, LPCRECT pRect
, COLORREF cRef
)
2090 COLORREF cOldColor
= SetBkColor(hDC
, cRef
);
2091 ExtTextOutA(hDC
, 0, 0, ETO_OPAQUE
, pRect
, 0, 0, 0);
2092 SetBkColor(hDC
, cOldColor
);
2096 /*************************************************************************
2099 * Return the value associated with a key in a map.
2102 * lpKeys [I] A list of keys of length iLen
2103 * lpValues [I] A list of values associated with lpKeys, of length iLen
2104 * iLen [I] Length of both lpKeys and lpValues
2105 * iKey [I] The key value to look up in lpKeys
2108 * The value in lpValues associated with iKey, or -1 if iKey is not
2112 * - If two elements in the map share the same key, this function returns
2113 * the value closest to the start of the map
2114 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2116 int WINAPI
SHSearchMapInt(const int *lpKeys
, const int *lpValues
, int iLen
, int iKey
)
2118 if (lpKeys
&& lpValues
)
2124 if (lpKeys
[i
] == iKey
)
2125 return lpValues
[i
]; /* Found */
2129 return -1; /* Not found */
2133 /*************************************************************************
2136 * Copy an interface pointer
2139 * lppDest [O] Destination for copy
2140 * lpUnknown [I] Source for copy
2145 VOID WINAPI
IUnknown_Set(IUnknown
**lppDest
, IUnknown
*lpUnknown
)
2147 TRACE("(%p,%p)\n", lppDest
, lpUnknown
);
2149 IUnknown_AtomicRelease(lppDest
);
2153 IUnknown_AddRef(lpUnknown
);
2154 *lppDest
= lpUnknown
;
2158 /*************************************************************************
2162 HRESULT WINAPI
MayQSForward(IUnknown
* lpUnknown
, PVOID lpReserved
,
2163 REFGUID riidCmdGrp
, ULONG cCmds
,
2164 OLECMD
*prgCmds
, OLECMDTEXT
* pCmdText
)
2166 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2167 lpUnknown
, lpReserved
, riidCmdGrp
, cCmds
, prgCmds
, pCmdText
);
2169 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2170 return DRAGDROP_E_NOTREGISTERED
;
2173 /*************************************************************************
2177 HRESULT WINAPI
MayExecForward(IUnknown
* lpUnknown
, INT iUnk
, REFGUID pguidCmdGroup
,
2178 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
* pvaIn
,
2181 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown
, iUnk
, pguidCmdGroup
,
2182 nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2183 return DRAGDROP_E_NOTREGISTERED
;
2186 /*************************************************************************
2190 HRESULT WINAPI
IsQSForward(REFGUID pguidCmdGroup
,ULONG cCmds
, OLECMD
*prgCmds
)
2192 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup
, cCmds
, prgCmds
);
2193 return DRAGDROP_E_NOTREGISTERED
;
2196 /*************************************************************************
2199 * Determine if a window is not a child of another window.
2202 * hParent [I] Suspected parent window
2203 * hChild [I] Suspected child window
2206 * TRUE: If hChild is a child window of hParent
2207 * FALSE: If hChild is not a child window of hParent, or they are equal
2209 BOOL WINAPI
SHIsChildOrSelf(HWND hParent
, HWND hChild
)
2211 TRACE("(%p,%p)\n", hParent
, hChild
);
2213 if (!hParent
|| !hChild
)
2215 else if(hParent
== hChild
)
2217 return !IsChild(hParent
, hChild
);
2220 /*************************************************************************
2221 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2226 DWORD num_items
; /* Number of elements inserted */
2227 void *mem
; /* Ptr to array */
2228 DWORD blocks_alloced
; /* Number of elements allocated */
2229 BYTE inc
; /* Number of elements to grow by when we need to expand */
2230 BYTE block_size
; /* Size in bytes of an element */
2231 BYTE flags
; /* Flags */
2234 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2236 /*************************************************************************
2239 * Initialize an FDSA array.
2241 BOOL WINAPI
FDSA_Initialize(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
2244 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size
, inc
, info
, mem
, init_blocks
);
2250 memset(mem
, 0, block_size
* init_blocks
);
2252 info
->num_items
= 0;
2255 info
->blocks_alloced
= init_blocks
;
2256 info
->block_size
= block_size
;
2262 /*************************************************************************
2265 * Destroy an FDSA array
2267 BOOL WINAPI
FDSA_Destroy(FDSA_info
*info
)
2269 TRACE("(%p)\n", info
);
2271 if(info
->flags
& FDSA_FLAG_INTERNAL_ALLOC
)
2273 HeapFree(GetProcessHeap(), 0, info
->mem
);
2280 /*************************************************************************
2283 * Insert element into an FDSA array
2285 DWORD WINAPI
FDSA_InsertItem(FDSA_info
*info
, DWORD where
, const void *block
)
2287 TRACE("(%p 0x%08x %p)\n", info
, where
, block
);
2288 if(where
> info
->num_items
)
2289 where
= info
->num_items
;
2291 if(info
->num_items
>= info
->blocks_alloced
)
2293 DWORD size
= (info
->blocks_alloced
+ info
->inc
) * info
->block_size
;
2294 if(info
->flags
& 0x1)
2295 info
->mem
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, info
->mem
, size
);
2298 void *old_mem
= info
->mem
;
2299 info
->mem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
2300 memcpy(info
->mem
, old_mem
, info
->blocks_alloced
* info
->block_size
);
2302 info
->blocks_alloced
+= info
->inc
;
2306 if(where
< info
->num_items
)
2308 memmove((char*)info
->mem
+ (where
+ 1) * info
->block_size
,
2309 (char*)info
->mem
+ where
* info
->block_size
,
2310 (info
->num_items
- where
) * info
->block_size
);
2312 memcpy((char*)info
->mem
+ where
* info
->block_size
, block
, info
->block_size
);
2318 /*************************************************************************
2321 * Delete an element from an FDSA array.
2323 BOOL WINAPI
FDSA_DeleteItem(FDSA_info
*info
, DWORD where
)
2325 TRACE("(%p 0x%08x)\n", info
, where
);
2327 if(where
>= info
->num_items
)
2330 if(where
< info
->num_items
- 1)
2332 memmove((char*)info
->mem
+ where
* info
->block_size
,
2333 (char*)info
->mem
+ (where
+ 1) * info
->block_size
,
2334 (info
->num_items
- where
- 1) * info
->block_size
);
2336 memset((char*)info
->mem
+ (info
->num_items
- 1) * info
->block_size
,
2337 0, info
->block_size
);
2342 /*************************************************************************
2345 * Call IUnknown_QueryInterface() on a table of objects.
2349 * Failure: E_POINTER or E_NOINTERFACE.
2351 HRESULT WINAPI
QISearch(
2352 void *base
, /* [in] Table of interfaces */
2353 const QITAB
*table
, /* [in] Array of REFIIDs and indexes into the table */
2354 REFIID riid
, /* [in] REFIID to get interface for */
2355 void **ppv
) /* [out] Destination for interface pointer */
2361 TRACE("(%p %p %s %p)\n", base
, table
, debugstr_guid(riid
), ppv
);
2364 while (xmove
->piid
) {
2365 TRACE("trying (offset %d) %s\n", xmove
->dwOffset
, debugstr_guid(xmove
->piid
));
2366 if (IsEqualIID(riid
, xmove
->piid
)) {
2367 a_vtbl
= (IUnknown
*)(xmove
->dwOffset
+ (LPBYTE
)base
);
2368 TRACE("matched, returning (%p)\n", a_vtbl
);
2370 IUnknown_AddRef(a_vtbl
);
2376 if (IsEqualIID(riid
, &IID_IUnknown
)) {
2377 a_vtbl
= (IUnknown
*)(table
->dwOffset
+ (LPBYTE
)base
);
2378 TRACE("returning first for IUnknown (%p)\n", a_vtbl
);
2380 IUnknown_AddRef(a_vtbl
);
2384 ret
= E_NOINTERFACE
;
2388 TRACE("-- 0x%08x\n", ret
);
2392 /*************************************************************************
2395 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2398 * hWnd [I] Parent Window to set the property
2399 * id [I] Index of child Window to set the Font
2405 HRESULT WINAPI
SHSetDefaultDialogFont(HWND hWnd
, INT id
)
2407 FIXME("(%p, %d) stub\n", hWnd
, id
);
2411 /*************************************************************************
2414 * Remove the "PropDlgFont" property from a window.
2417 * hWnd [I] Window to remove the property from
2420 * A handle to the removed property, or NULL if it did not exist.
2422 HANDLE WINAPI
SHRemoveDefaultDialogFont(HWND hWnd
)
2426 TRACE("(%p)\n", hWnd
);
2428 hProp
= GetPropA(hWnd
, "PropDlgFont");
2432 DeleteObject(hProp
);
2433 hProp
= RemovePropA(hWnd
, "PropDlgFont");
2438 /*************************************************************************
2441 * Load the in-process server of a given GUID.
2444 * refiid [I] GUID of the server to load.
2447 * Success: A handle to the loaded server dll.
2448 * Failure: A NULL handle.
2450 HMODULE WINAPI
SHPinDllOfCLSID(REFIID refiid
)
2454 CHAR value
[MAX_PATH
], string
[MAX_PATH
];
2456 strcpy(string
, "CLSID\\");
2457 SHStringFromGUIDA(refiid
, string
+ 6, sizeof(string
)/sizeof(char) - 6);
2458 strcat(string
, "\\InProcServer32");
2461 RegOpenKeyExA(HKEY_CLASSES_ROOT
, string
, 0, 1, &newkey
);
2462 RegQueryValueExA(newkey
, 0, 0, &type
, (PBYTE
)value
, &count
);
2463 RegCloseKey(newkey
);
2464 return LoadLibraryExA(value
, 0, 0);
2467 /*************************************************************************
2470 * Unicode version of SHLWAPI_183.
2472 DWORD WINAPI
SHRegisterClassW(WNDCLASSW
* lpWndClass
)
2476 TRACE("(%p %s)\n",lpWndClass
->hInstance
, debugstr_w(lpWndClass
->lpszClassName
));
2478 if (GetClassInfoW(lpWndClass
->hInstance
, lpWndClass
->lpszClassName
, &WndClass
))
2480 return RegisterClassW(lpWndClass
);
2483 /*************************************************************************
2486 * Unregister a list of classes.
2489 * hInst [I] Application instance that registered the classes
2490 * lppClasses [I] List of class names
2491 * iCount [I] Number of names in lppClasses
2496 void WINAPI
SHUnregisterClassesA(HINSTANCE hInst
, LPCSTR
*lppClasses
, INT iCount
)
2500 TRACE("(%p,%p,%d)\n", hInst
, lppClasses
, iCount
);
2504 if (GetClassInfoA(hInst
, *lppClasses
, &WndClass
))
2505 UnregisterClassA(*lppClasses
, hInst
);
2511 /*************************************************************************
2514 * Unicode version of SHUnregisterClassesA.
2516 void WINAPI
SHUnregisterClassesW(HINSTANCE hInst
, LPCWSTR
*lppClasses
, INT iCount
)
2520 TRACE("(%p,%p,%d)\n", hInst
, lppClasses
, iCount
);
2524 if (GetClassInfoW(hInst
, *lppClasses
, &WndClass
))
2525 UnregisterClassW(*lppClasses
, hInst
);
2531 /*************************************************************************
2534 * Call The correct (Ascii/Unicode) default window procedure for a window.
2537 * hWnd [I] Window to call the default procedure for
2538 * uMessage [I] Message ID
2539 * wParam [I] WPARAM of message
2540 * lParam [I] LPARAM of message
2543 * The result of calling DefWindowProcA() or DefWindowProcW().
2545 LRESULT CALLBACK
SHDefWindowProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
2547 if (IsWindowUnicode(hWnd
))
2548 return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
2549 return DefWindowProcA(hWnd
, uMessage
, wParam
, lParam
);
2552 /*************************************************************************
2555 HRESULT WINAPI
IUnknown_GetSite(LPUNKNOWN lpUnknown
, REFIID iid
, PVOID
*lppSite
)
2557 HRESULT hRet
= E_INVALIDARG
;
2558 LPOBJECTWITHSITE lpSite
= NULL
;
2560 TRACE("(%p,%s,%p)\n", lpUnknown
, debugstr_guid(iid
), lppSite
);
2562 if (lpUnknown
&& iid
&& lppSite
)
2564 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IObjectWithSite
,
2566 if (SUCCEEDED(hRet
) && lpSite
)
2568 hRet
= IObjectWithSite_GetSite(lpSite
, iid
, lppSite
);
2569 IObjectWithSite_Release(lpSite
);
2575 /*************************************************************************
2578 * Create a worker window using CreateWindowExA().
2581 * wndProc [I] Window procedure
2582 * hWndParent [I] Parent window
2583 * dwExStyle [I] Extra style flags
2584 * dwStyle [I] Style flags
2585 * hMenu [I] Window menu
2586 * wnd_extra [I] Window extra bytes value
2589 * Success: The window handle of the newly created window.
2592 HWND WINAPI
SHCreateWorkerWindowA(LONG wndProc
, HWND hWndParent
, DWORD dwExStyle
,
2593 DWORD dwStyle
, HMENU hMenu
, LONG_PTR wnd_extra
)
2595 static const char szClass
[] = "WorkerA";
2599 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2600 wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, wnd_extra
);
2602 /* Create Window class */
2604 wc
.lpfnWndProc
= DefWindowProcA
;
2606 wc
.cbWndExtra
= sizeof(LONG_PTR
);
2607 wc
.hInstance
= shlwapi_hInstance
;
2609 wc
.hCursor
= LoadCursorA(NULL
, (LPSTR
)IDC_ARROW
);
2610 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2611 wc
.lpszMenuName
= NULL
;
2612 wc
.lpszClassName
= szClass
;
2614 SHRegisterClassA(&wc
);
2616 hWnd
= CreateWindowExA(dwExStyle
, szClass
, 0, dwStyle
, 0, 0, 0, 0,
2617 hWndParent
, hMenu
, shlwapi_hInstance
, 0);
2620 SetWindowLongPtrW(hWnd
, 0, wnd_extra
);
2622 if (wndProc
) SetWindowLongPtrA(hWnd
, GWLP_WNDPROC
, wndProc
);
2628 typedef struct tagPOLICYDATA
2630 DWORD policy
; /* flags value passed to SHRestricted */
2631 LPCWSTR appstr
; /* application str such as "Explorer" */
2632 LPCWSTR keystr
; /* name of the actual registry key / policy */
2633 } POLICYDATA
, *LPPOLICYDATA
;
2635 #define SHELL_NO_POLICY 0xffffffff
2637 /* default shell policy registry key */
2638 static const WCHAR strRegistryPolicyW
[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2639 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2640 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2641 '\\','P','o','l','i','c','i','e','s',0};
2643 /*************************************************************************
2646 * Retrieve a policy value from the registry.
2649 * lpSubKey [I] registry key name
2650 * lpSubName [I] subname of registry key
2651 * lpValue [I] value name of registry value
2654 * the value associated with the registry key or 0 if not found
2656 DWORD WINAPI
SHGetRestriction(LPCWSTR lpSubKey
, LPCWSTR lpSubName
, LPCWSTR lpValue
)
2658 DWORD retval
, datsize
= sizeof(retval
);
2662 lpSubKey
= strRegistryPolicyW
;
2664 retval
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, lpSubKey
, &hKey
);
2665 if (retval
!= ERROR_SUCCESS
)
2666 retval
= RegOpenKeyW(HKEY_CURRENT_USER
, lpSubKey
, &hKey
);
2667 if (retval
!= ERROR_SUCCESS
)
2670 SHGetValueW(hKey
, lpSubName
, lpValue
, NULL
, &retval
, &datsize
);
2675 /*************************************************************************
2678 * Helper function to retrieve the possibly cached value for a specific policy
2681 * policy [I] The policy to look for
2682 * initial [I] Main registry key to open, if NULL use default
2683 * polTable [I] Table of known policies, 0 terminated
2684 * polArr [I] Cache array of policy values
2687 * The retrieved policy value or 0 if not successful
2690 * This function is used by the native SHRestricted function to search for the
2691 * policy and cache it once retrieved. The current Wine implementation uses a
2692 * different POLICYDATA structure and implements a similar algorithm adapted to
2695 DWORD WINAPI
SHRestrictionLookup(
2698 LPPOLICYDATA polTable
,
2701 TRACE("(0x%08x %s %p %p)\n", policy
, debugstr_w(initial
), polTable
, polArr
);
2703 if (!polTable
|| !polArr
)
2706 for (;polTable
->policy
; polTable
++, polArr
++)
2708 if (policy
== polTable
->policy
)
2710 /* we have a known policy */
2712 /* check if this policy has been cached */
2713 if (*polArr
== SHELL_NO_POLICY
)
2714 *polArr
= SHGetRestriction(initial
, polTable
->appstr
, polTable
->keystr
);
2718 /* we don't know this policy, return 0 */
2719 TRACE("unknown policy: (%08x)\n", policy
);
2723 /*************************************************************************
2726 * Get an interface from an object.
2729 * Success: S_OK. ppv contains the requested interface.
2730 * Failure: An HRESULT error code.
2733 * This QueryInterface asks the inner object for an interface. In case
2734 * of aggregation this request would be forwarded by the inner to the
2735 * outer object. This function asks the inner object directly for the
2736 * interface circumventing the forwarding to the outer object.
2738 HRESULT WINAPI
SHWeakQueryInterface(
2739 IUnknown
* pUnk
, /* [in] Outer object */
2740 IUnknown
* pInner
, /* [in] Inner object */
2741 IID
* riid
, /* [in] Interface GUID to query for */
2742 LPVOID
* ppv
) /* [out] Destination for queried interface */
2744 HRESULT hret
= E_NOINTERFACE
;
2745 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk
,pInner
,debugstr_guid(riid
), ppv
);
2748 if(pUnk
&& pInner
) {
2749 hret
= IUnknown_QueryInterface(pInner
, riid
, ppv
);
2750 if (SUCCEEDED(hret
)) IUnknown_Release(pUnk
);
2752 TRACE("-- 0x%08x\n", hret
);
2756 /*************************************************************************
2759 * Move a reference from one interface to another.
2762 * lpDest [O] Destination to receive the reference
2763 * lppUnknown [O] Source to give up the reference to lpDest
2768 VOID WINAPI
SHWeakReleaseInterface(IUnknown
*lpDest
, IUnknown
**lppUnknown
)
2770 TRACE("(%p,%p)\n", lpDest
, lppUnknown
);
2775 IUnknown_AddRef(lpDest
);
2776 IUnknown_AtomicRelease(lppUnknown
); /* Release existing interface */
2780 /*************************************************************************
2783 * Convert an ASCII string of a CLSID into a CLSID.
2786 * idstr [I] String representing a CLSID in registry format
2787 * id [O] Destination for the converted CLSID
2790 * Success: TRUE. id contains the converted CLSID.
2793 BOOL WINAPI
GUIDFromStringA(LPCSTR idstr
, CLSID
*id
)
2796 MultiByteToWideChar(CP_ACP
, 0, idstr
, -1, wClsid
, sizeof(wClsid
)/sizeof(WCHAR
));
2797 return SUCCEEDED(CLSIDFromString(wClsid
, id
));
2800 /*************************************************************************
2803 * Unicode version of GUIDFromStringA.
2805 BOOL WINAPI
GUIDFromStringW(LPCWSTR idstr
, CLSID
*id
)
2807 return SUCCEEDED(CLSIDFromString((LPCOLESTR
)idstr
, id
));
2810 /*************************************************************************
2813 * Determine if the browser is integrated into the shell, and set a registry
2820 * 1, If the browser is not integrated.
2821 * 2, If the browser is integrated.
2824 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2825 * either set to TRUE, or removed depending on whether the browser is deemed
2828 DWORD WINAPI
WhichPlatform(void)
2830 static const char szIntegratedBrowser
[] = "IntegratedBrowser";
2831 static DWORD dwState
= 0;
2833 DWORD dwRet
, dwData
, dwSize
;
2839 /* If shell32 exports DllGetVersion(), the browser is integrated */
2841 hshell32
= LoadLibraryA("shell32.dll");
2844 FARPROC pDllGetVersion
;
2845 pDllGetVersion
= GetProcAddress(hshell32
, "DllGetVersion");
2846 dwState
= pDllGetVersion
? 2 : 1;
2847 FreeLibrary(hshell32
);
2850 /* Set or delete the key accordingly */
2851 dwRet
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
,
2852 "Software\\Microsoft\\Internet Explorer", 0,
2853 KEY_ALL_ACCESS
, &hKey
);
2856 dwRet
= RegQueryValueExA(hKey
, szIntegratedBrowser
, 0, 0,
2857 (LPBYTE
)&dwData
, &dwSize
);
2859 if (!dwRet
&& dwState
== 1)
2861 /* Value exists but browser is not integrated */
2862 RegDeleteValueA(hKey
, szIntegratedBrowser
);
2864 else if (dwRet
&& dwState
== 2)
2866 /* Browser is integrated but value does not exist */
2868 RegSetValueExA(hKey
, szIntegratedBrowser
, 0, REG_DWORD
,
2869 (LPBYTE
)&dwData
, sizeof(dwData
));
2876 /*************************************************************************
2879 * Unicode version of SHCreateWorkerWindowA.
2881 HWND WINAPI
SHCreateWorkerWindowW(LONG wndProc
, HWND hWndParent
, DWORD dwExStyle
,
2882 DWORD dwStyle
, HMENU hMenu
, LONG msg_result
)
2884 static const WCHAR szClass
[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
2888 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
2889 wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, msg_result
);
2891 /* If our OS is natively ANSI, use the ANSI version */
2892 if (GetVersion() & 0x80000000) /* not NT */
2894 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
2895 return SHCreateWorkerWindowA(wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, msg_result
);
2898 /* Create Window class */
2900 wc
.lpfnWndProc
= DefWindowProcW
;
2903 wc
.hInstance
= shlwapi_hInstance
;
2905 wc
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
2906 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2907 wc
.lpszMenuName
= NULL
;
2908 wc
.lpszClassName
= szClass
;
2910 SHRegisterClassW(&wc
);
2912 hWnd
= CreateWindowExW(dwExStyle
, szClass
, 0, dwStyle
, 0, 0, 0, 0,
2913 hWndParent
, hMenu
, shlwapi_hInstance
, 0);
2916 SetWindowLongPtrW(hWnd
, DWLP_MSGRESULT
, msg_result
);
2918 if (wndProc
) SetWindowLongPtrW(hWnd
, GWLP_WNDPROC
, wndProc
);
2924 /*************************************************************************
2927 * Get and show a context menu from a shell folder.
2930 * hWnd [I] Window displaying the shell folder
2931 * lpFolder [I] IShellFolder interface
2932 * lpApidl [I] Id for the particular folder desired
2936 * Failure: An HRESULT error code indicating the error.
2938 HRESULT WINAPI
SHInvokeDefaultCommand(HWND hWnd
, IShellFolder
* lpFolder
, LPCITEMIDLIST lpApidl
)
2940 TRACE("%p %p %p\n", hWnd
, lpFolder
, lpApidl
);
2941 return SHInvokeCommand(hWnd
, lpFolder
, lpApidl
, FALSE
);
2944 /*************************************************************************
2947 * _SHPackDispParamsV
2949 HRESULT WINAPI
SHPackDispParamsV(DISPPARAMS
*params
, VARIANTARG
*args
, UINT cnt
, __ms_va_list valist
)
2953 TRACE("(%p %p %u ...)\n", params
, args
, cnt
);
2955 params
->rgvarg
= args
;
2956 params
->rgdispidNamedArgs
= NULL
;
2957 params
->cArgs
= cnt
;
2958 params
->cNamedArgs
= 0;
2962 while(iter
-- > args
) {
2963 V_VT(iter
) = va_arg(valist
, enum VARENUM
);
2965 TRACE("vt=%d\n", V_VT(iter
));
2967 if(V_VT(iter
) & VT_BYREF
) {
2968 V_BYREF(iter
) = va_arg(valist
, LPVOID
);
2970 switch(V_VT(iter
)) {
2972 V_I4(iter
) = va_arg(valist
, LONG
);
2975 V_BSTR(iter
) = va_arg(valist
, BSTR
);
2978 V_DISPATCH(iter
) = va_arg(valist
, IDispatch
*);
2981 V_BOOL(iter
) = va_arg(valist
, int);
2984 V_UNKNOWN(iter
) = va_arg(valist
, IUnknown
*);
2988 V_I4(iter
) = va_arg(valist
, LONG
);
2996 /*************************************************************************
3001 HRESULT WINAPIV
SHPackDispParams(DISPPARAMS
*params
, VARIANTARG
*args
, UINT cnt
, ...)
3003 __ms_va_list valist
;
3006 __ms_va_start(valist
, cnt
);
3007 hres
= SHPackDispParamsV(params
, args
, cnt
, valist
);
3008 __ms_va_end(valist
);
3012 /*************************************************************************
3013 * SHLWAPI_InvokeByIID
3015 * This helper function calls IDispatch::Invoke for each sink
3016 * which implements given iid or IDispatch.
3019 static HRESULT
SHLWAPI_InvokeByIID(
3020 IConnectionPoint
* iCP
,
3023 DISPPARAMS
* dispParams
)
3025 IEnumConnections
*enumerator
;
3027 static DISPPARAMS empty
= {NULL
, NULL
, 0, 0};
3028 DISPPARAMS
* params
= dispParams
;
3030 HRESULT result
= IConnectionPoint_EnumConnections(iCP
, &enumerator
);
3034 /* Invoke is never happening with an NULL dispParams */
3038 while(IEnumConnections_Next(enumerator
, 1, &rgcd
, NULL
)==S_OK
)
3040 IDispatch
*dispIface
;
3041 if ((iid
&& SUCCEEDED(IUnknown_QueryInterface(rgcd
.pUnk
, iid
, (LPVOID
*)&dispIface
))) ||
3042 SUCCEEDED(IUnknown_QueryInterface(rgcd
.pUnk
, &IID_IDispatch
, (LPVOID
*)&dispIface
)))
3044 IDispatch_Invoke(dispIface
, dispId
, &IID_NULL
, 0, DISPATCH_METHOD
, params
, NULL
, NULL
, NULL
);
3045 IDispatch_Release(dispIface
);
3047 IUnknown_Release(rgcd
.pUnk
);
3050 IEnumConnections_Release(enumerator
);
3055 /*************************************************************************
3056 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3058 HRESULT WINAPI
IConnectionPoint_InvokeWithCancel( IConnectionPoint
* iCP
,
3059 DISPID dispId
, DISPPARAMS
* dispParams
,
3060 DWORD unknown1
, DWORD unknown2
)
3065 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP
, dispId
, dispParams
, unknown1
, unknown2
);
3067 result
= IConnectionPoint_GetConnectionInterface(iCP
, &iid
);
3068 if (SUCCEEDED(result
))
3069 result
= SHLWAPI_InvokeByIID(iCP
, &iid
, dispId
, dispParams
);
3071 result
= SHLWAPI_InvokeByIID(iCP
, NULL
, dispId
, dispParams
);
3077 /*************************************************************************
3080 * IConnectionPoint_SimpleInvoke
3082 HRESULT WINAPI
IConnectionPoint_SimpleInvoke(
3083 IConnectionPoint
* iCP
,
3085 DISPPARAMS
* dispParams
)
3090 TRACE("(%p)->(0x%x %p)\n",iCP
,dispId
,dispParams
);
3092 result
= IConnectionPoint_GetConnectionInterface(iCP
, &iid
);
3093 if (SUCCEEDED(result
))
3094 result
= SHLWAPI_InvokeByIID(iCP
, &iid
, dispId
, dispParams
);
3096 result
= SHLWAPI_InvokeByIID(iCP
, NULL
, dispId
, dispParams
);
3101 /*************************************************************************
3104 * Notify an IConnectionPoint object of changes.
3107 * lpCP [I] Object to notify
3112 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3113 * IConnectionPoint interface.
3115 HRESULT WINAPI
IConnectionPoint_OnChanged(IConnectionPoint
* lpCP
, DISPID dispID
)
3117 IEnumConnections
*lpEnum
;
3118 HRESULT hRet
= E_NOINTERFACE
;
3120 TRACE("(%p,0x%8X)\n", lpCP
, dispID
);
3122 /* Get an enumerator for the connections */
3124 hRet
= IConnectionPoint_EnumConnections(lpCP
, &lpEnum
);
3126 if (SUCCEEDED(hRet
))
3128 IPropertyNotifySink
*lpSink
;
3129 CONNECTDATA connData
;
3132 /* Call OnChanged() for every notify sink in the connection point */
3133 while (IEnumConnections_Next(lpEnum
, 1, &connData
, &ulFetched
) == S_OK
)
3135 if (SUCCEEDED(IUnknown_QueryInterface(connData
.pUnk
, &IID_IPropertyNotifySink
, (void**)&lpSink
)) &&
3138 IPropertyNotifySink_OnChanged(lpSink
, dispID
);
3139 IPropertyNotifySink_Release(lpSink
);
3141 IUnknown_Release(connData
.pUnk
);
3144 IEnumConnections_Release(lpEnum
);
3149 /*************************************************************************
3152 * IUnknown_CPContainerInvokeParam
3154 HRESULT WINAPIV
IUnknown_CPContainerInvokeParam(
3155 IUnknown
*container
,
3162 IConnectionPoint
*iCP
;
3163 IConnectionPointContainer
*iCPC
;
3164 DISPPARAMS dispParams
= {buffer
, NULL
, cParams
, 0};
3165 __ms_va_list valist
;
3168 return E_NOINTERFACE
;
3170 result
= IUnknown_QueryInterface(container
, &IID_IConnectionPointContainer
,(LPVOID
*) &iCPC
);
3174 result
= IConnectionPointContainer_FindConnectionPoint(iCPC
, riid
, &iCP
);
3175 IConnectionPointContainer_Release(iCPC
);
3179 __ms_va_start(valist
, cParams
);
3180 SHPackDispParamsV(&dispParams
, buffer
, cParams
, valist
);
3181 __ms_va_end(valist
);
3183 result
= SHLWAPI_InvokeByIID(iCP
, riid
, dispId
, &dispParams
);
3184 IConnectionPoint_Release(iCP
);
3189 /*************************************************************************
3192 * Notify an IConnectionPointContainer object of changes.
3195 * lpUnknown [I] Object to notify
3200 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3201 * IConnectionPointContainer interface.
3203 HRESULT WINAPI
IUnknown_CPContainerOnChanged(IUnknown
*lpUnknown
, DISPID dispID
)
3205 IConnectionPointContainer
* lpCPC
= NULL
;
3206 HRESULT hRet
= E_NOINTERFACE
;
3208 TRACE("(%p,0x%8X)\n", lpUnknown
, dispID
);
3211 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IConnectionPointContainer
, (void**)&lpCPC
);
3213 if (SUCCEEDED(hRet
))
3215 IConnectionPoint
* lpCP
;
3217 hRet
= IConnectionPointContainer_FindConnectionPoint(lpCPC
, &IID_IPropertyNotifySink
, &lpCP
);
3218 IConnectionPointContainer_Release(lpCPC
);
3220 hRet
= IConnectionPoint_OnChanged(lpCP
, dispID
);
3221 IConnectionPoint_Release(lpCP
);
3226 /*************************************************************************
3231 BOOL WINAPI
PlaySoundWrapW(LPCWSTR pszSound
, HMODULE hmod
, DWORD fdwSound
)
3233 return PlaySoundW(pszSound
, hmod
, fdwSound
);
3236 /*************************************************************************
3239 * Retrieve a key value from an INI file. See GetPrivateProfileString for
3243 * appName [I] The section in the INI file that contains the key
3244 * keyName [I] The key to be retrieved
3245 * out [O] The buffer into which the key's value will be copied
3246 * outLen [I] The length of the `out' buffer
3247 * filename [I] The location of the INI file
3250 * Length of string copied into `out'.
3252 DWORD WINAPI
SHGetIniStringW(LPCWSTR appName
, LPCWSTR keyName
, LPWSTR out
,
3253 DWORD outLen
, LPCWSTR filename
)
3258 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName
), debugstr_w(keyName
),
3259 out
, outLen
, debugstr_w(filename
));
3264 buf
= HeapAlloc(GetProcessHeap(), 0, outLen
* sizeof(WCHAR
));
3270 ret
= GetPrivateProfileStringW(appName
, keyName
, NULL
, buf
, outLen
, filename
);
3276 HeapFree(GetProcessHeap(), 0, buf
);
3278 return strlenW(out
);
3281 /*************************************************************************
3284 * Set a key value in an INI file. See WritePrivateProfileString for
3288 * appName [I] The section in the INI file that contains the key
3289 * keyName [I] The key to be set
3290 * str [O] The value of the key
3291 * filename [I] The location of the INI file
3297 BOOL WINAPI
SHSetIniStringW(LPCWSTR appName
, LPCWSTR keyName
, LPCWSTR str
,
3300 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName
), keyName
, debugstr_w(str
),
3301 debugstr_w(filename
));
3303 return WritePrivateProfileStringW(appName
, keyName
, str
, filename
);
3306 /*************************************************************************
3309 * See SHGetFileInfoW.
3311 DWORD WINAPI
SHGetFileInfoWrapW(LPCWSTR path
, DWORD dwFileAttributes
,
3312 SHFILEINFOW
*psfi
, UINT sizeofpsfi
, UINT flags
)
3314 return SHGetFileInfoW(path
, dwFileAttributes
, psfi
, sizeofpsfi
, flags
);
3317 /*************************************************************************
3320 * See DragQueryFileW.
3322 UINT WINAPI
DragQueryFileWrapW(HDROP hDrop
, UINT lFile
, LPWSTR lpszFile
, UINT lLength
)
3324 return DragQueryFileW(hDrop
, lFile
, lpszFile
, lLength
);
3327 /*************************************************************************
3330 * See SHBrowseForFolderW.
3332 LPITEMIDLIST WINAPI
SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi
)
3334 return SHBrowseForFolderW(lpBi
);
3337 /*************************************************************************
3340 * See SHGetPathFromIDListW.
3342 BOOL WINAPI
SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl
,LPWSTR pszPath
)
3344 return SHGetPathFromIDListW(pidl
, pszPath
);
3347 /*************************************************************************
3350 * See ShellExecuteExW.
3352 BOOL WINAPI
ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo
)
3354 return ShellExecuteExW(lpExecInfo
);
3357 /*************************************************************************
3360 * See SHFileOperationW.
3362 INT WINAPI
SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp
)
3364 return SHFileOperationW(lpFileOp
);
3367 /*************************************************************************
3371 PVOID WINAPI
SHInterlockedCompareExchange( PVOID
*dest
, PVOID xchg
, PVOID compare
)
3373 return InterlockedCompareExchangePointer( dest
, xchg
, compare
);
3376 /*************************************************************************
3379 * See GetFileVersionInfoSizeW.
3381 DWORD WINAPI
GetFileVersionInfoSizeWrapW( LPCWSTR filename
, LPDWORD handle
)
3383 return GetFileVersionInfoSizeW( filename
, handle
);
3386 /*************************************************************************
3389 * See GetFileVersionInfoW.
3391 BOOL WINAPI
GetFileVersionInfoWrapW( LPCWSTR filename
, DWORD handle
,
3392 DWORD datasize
, LPVOID data
)
3394 return GetFileVersionInfoW( filename
, handle
, datasize
, data
);
3397 /*************************************************************************
3400 * See VerQueryValueW.
3402 WORD WINAPI
VerQueryValueWrapW( LPVOID pBlock
, LPCWSTR lpSubBlock
,
3403 LPVOID
*lplpBuffer
, UINT
*puLen
)
3405 return VerQueryValueW( pBlock
, lpSubBlock
, lplpBuffer
, puLen
);
3408 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3409 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3410 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3412 /*************************************************************************
3415 * Change the modality of a shell object.
3418 * lpUnknown [I] Object to make modeless
3419 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3422 * Success: S_OK. The modality lpUnknown is changed.
3423 * Failure: An HRESULT error code indicating the error.
3426 * lpUnknown must support the IOleInPlaceFrame interface, the
3427 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3428 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3429 * or this call will fail.
3431 HRESULT WINAPI
IUnknown_EnableModeless(IUnknown
*lpUnknown
, BOOL bModeless
)
3436 TRACE("(%p,%d)\n", lpUnknown
, bModeless
);
3441 if (IsIface(IOleInPlaceActiveObject
))
3442 EnableModeless(IOleInPlaceActiveObject
);
3443 else if (IsIface(IOleInPlaceFrame
))
3444 EnableModeless(IOleInPlaceFrame
);
3445 else if (IsIface(IShellBrowser
))
3446 EnableModeless(IShellBrowser
);
3447 else if (IsIface(IInternetSecurityMgrSite
))
3448 EnableModeless(IInternetSecurityMgrSite
);
3449 else if (IsIface(IDocHostUIHandler
))
3450 EnableModeless(IDocHostUIHandler
);
3454 IUnknown_Release(lpObj
);
3458 /*************************************************************************
3461 * See SHGetNewLinkInfoW.
3463 BOOL WINAPI
SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo
, LPCWSTR pszDir
, LPWSTR pszName
,
3464 BOOL
*pfMustCopy
, UINT uFlags
)
3466 return SHGetNewLinkInfoW(pszLinkTo
, pszDir
, pszName
, pfMustCopy
, uFlags
);
3469 /*************************************************************************
3472 * See SHDefExtractIconW.
3474 UINT WINAPI
SHDefExtractIconWrapW(LPCWSTR pszIconFile
, int iIndex
, UINT uFlags
, HICON
* phiconLarge
,
3475 HICON
* phiconSmall
, UINT nIconSize
)
3477 return SHDefExtractIconW(pszIconFile
, iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
3480 /*************************************************************************
3483 * Get and show a context menu from a shell folder.
3486 * hWnd [I] Window displaying the shell folder
3487 * lpFolder [I] IShellFolder interface
3488 * lpApidl [I] Id for the particular folder desired
3489 * bInvokeDefault [I] Whether to invoke the default menu item
3492 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3494 * Failure: An HRESULT error code indicating the error.
3496 HRESULT WINAPI
SHInvokeCommand(HWND hWnd
, IShellFolder
* lpFolder
, LPCITEMIDLIST lpApidl
, BOOL bInvokeDefault
)
3498 IContextMenu
*iContext
;
3501 TRACE("(%p, %p, %p, %d)\n", hWnd
, lpFolder
, lpApidl
, bInvokeDefault
);
3506 /* Get the context menu from the shell folder */
3507 hRet
= IShellFolder_GetUIObjectOf(lpFolder
, hWnd
, 1, &lpApidl
,
3508 &IID_IContextMenu
, 0, (void**)&iContext
);
3509 if (SUCCEEDED(hRet
))
3512 if ((hMenu
= CreatePopupMenu()))
3515 DWORD dwDefaultId
= 0;
3517 /* Add the context menu entries to the popup */
3518 hQuery
= IContextMenu_QueryContextMenu(iContext
, hMenu
, 0, 1, 0x7FFF,
3519 bInvokeDefault
? CMF_NORMAL
: CMF_DEFAULTONLY
);
3521 if (SUCCEEDED(hQuery
))
3523 if (bInvokeDefault
&&
3524 (dwDefaultId
= GetMenuDefaultItem(hMenu
, 0, 0)) != (UINT
)-1)
3526 CMINVOKECOMMANDINFO cmIci
;
3527 /* Invoke the default item */
3528 memset(&cmIci
,0,sizeof(cmIci
));
3529 cmIci
.cbSize
= sizeof(cmIci
);
3530 cmIci
.fMask
= CMIC_MASK_ASYNCOK
;
3532 cmIci
.lpVerb
= MAKEINTRESOURCEA(dwDefaultId
);
3533 cmIci
.nShow
= SW_SCROLLCHILDREN
;
3535 hRet
= IContextMenu_InvokeCommand(iContext
, &cmIci
);
3540 IContextMenu_Release(iContext
);
3545 /*************************************************************************
3550 HICON WINAPI
ExtractIconWrapW(HINSTANCE hInstance
, LPCWSTR lpszExeFileName
,
3553 return ExtractIconW(hInstance
, lpszExeFileName
, nIconIndex
);
3556 /*************************************************************************
3559 * Load a library from the directory of a particular process.
3562 * new_mod [I] Library name
3563 * inst_hwnd [I] Module whose directory is to be used
3564 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3567 * Success: A handle to the loaded module
3568 * Failure: A NULL handle.
3570 HMODULE WINAPI
MLLoadLibraryA(LPCSTR new_mod
, HMODULE inst_hwnd
, DWORD dwCrossCodePage
)
3572 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3574 * FIXME: Native shows calls to:
3575 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3577 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3578 * RegQueryValueExA for "LPKInstalled"
3580 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3581 * RegQueryValueExA for "ResourceLocale"
3583 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3584 * RegQueryValueExA for "Locale"
3586 * and then tests the Locale ("en" for me).
3588 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3590 CHAR mod_path
[2*MAX_PATH
];
3594 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod
), inst_hwnd
, dwCrossCodePage
);
3595 len
= GetModuleFileNameA(inst_hwnd
, mod_path
, sizeof(mod_path
));
3596 if (!len
|| len
>= sizeof(mod_path
)) return NULL
;
3598 ptr
= strrchr(mod_path
, '\\');
3600 strcpy(ptr
+1, new_mod
);
3601 TRACE("loading %s\n", debugstr_a(mod_path
));
3602 return LoadLibraryA(mod_path
);
3607 /*************************************************************************
3610 * Unicode version of MLLoadLibraryA.
3612 HMODULE WINAPI
MLLoadLibraryW(LPCWSTR new_mod
, HMODULE inst_hwnd
, DWORD dwCrossCodePage
)
3614 WCHAR mod_path
[2*MAX_PATH
];
3618 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod
), inst_hwnd
, dwCrossCodePage
);
3619 len
= GetModuleFileNameW(inst_hwnd
, mod_path
, sizeof(mod_path
) / sizeof(WCHAR
));
3620 if (!len
|| len
>= sizeof(mod_path
) / sizeof(WCHAR
)) return NULL
;
3622 ptr
= strrchrW(mod_path
, '\\');
3624 strcpyW(ptr
+1, new_mod
);
3625 TRACE("loading %s\n", debugstr_w(mod_path
));
3626 return LoadLibraryW(mod_path
);
3631 /*************************************************************************
3632 * ColorAdjustLuma [SHLWAPI.@]
3634 * Adjust the luminosity of a color
3637 * cRGB [I] RGB value to convert
3638 * dwLuma [I] Luma adjustment
3639 * bUnknown [I] Unknown
3642 * The adjusted RGB color.
3644 COLORREF WINAPI
ColorAdjustLuma(COLORREF cRGB
, int dwLuma
, BOOL bUnknown
)
3646 TRACE("(0x%8x,%d,%d)\n", cRGB
, dwLuma
, bUnknown
);
3652 ColorRGBToHLS(cRGB
, &wH
, &wL
, &wS
);
3654 FIXME("Ignoring luma adjustment\n");
3656 /* FIXME: The adjustment is not linear */
3658 cRGB
= ColorHLSToRGB(wH
, wL
, wS
);
3663 /*************************************************************************
3666 * See GetSaveFileNameW.
3668 BOOL WINAPI
GetSaveFileNameWrapW(LPOPENFILENAMEW ofn
)
3670 return GetSaveFileNameW(ofn
);
3673 /*************************************************************************
3676 * See WNetRestoreConnectionW.
3678 DWORD WINAPI
WNetRestoreConnectionWrapW(HWND hwndOwner
, LPWSTR lpszDevice
)
3680 return WNetRestoreConnectionW(hwndOwner
, lpszDevice
);
3683 /*************************************************************************
3686 * See WNetGetLastErrorW.
3688 DWORD WINAPI
WNetGetLastErrorWrapW(LPDWORD lpError
, LPWSTR lpErrorBuf
, DWORD nErrorBufSize
,
3689 LPWSTR lpNameBuf
, DWORD nNameBufSize
)
3691 return WNetGetLastErrorW(lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
3694 /*************************************************************************
3697 * See PageSetupDlgW.
3699 BOOL WINAPI
PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg
)
3701 return PageSetupDlgW(pagedlg
);
3704 /*************************************************************************
3709 BOOL WINAPI
PrintDlgWrapW(LPPRINTDLGW printdlg
)
3711 return PrintDlgW(printdlg
);
3714 /*************************************************************************
3717 * See GetOpenFileNameW.
3719 BOOL WINAPI
GetOpenFileNameWrapW(LPOPENFILENAMEW ofn
)
3721 return GetOpenFileNameW(ofn
);
3724 /*************************************************************************
3727 HRESULT WINAPI
SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder
, HWND hwnd
, SHCONTF flags
, IEnumIDList
**ppenum
)
3729 /* Windows attempts to get an IPersist interface and, if that fails, an
3730 * IPersistFolder interface on the folder passed-in here. If one of those
3731 * interfaces is available, it then calls GetClassID on the folder... and
3732 * then calls IShellFolder_EnumObjects no matter what, even crashing if
3733 * lpFolder isn't actually an IShellFolder object. The purpose of getting
3734 * the ClassID is unknown, so we don't do it here.
3736 * For discussion and detailed tests, see:
3737 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated"
3738 * wine-devel mailing list, 3 Jun 2010
3741 return IShellFolder_EnumObjects(lpFolder
, hwnd
, flags
, ppenum
);
3744 /* INTERNAL: Map from HLS color space to RGB */
3745 static WORD
ConvertHue(int wHue
, WORD wMid1
, WORD wMid2
)
3747 wHue
= wHue
> 240 ? wHue
- 240 : wHue
< 0 ? wHue
+ 240 : wHue
;
3751 else if (wHue
> 120)
3756 return ((wHue
* (wMid2
- wMid1
) + 20) / 40) + wMid1
;
3759 /* Convert to RGB and scale into RGB range (0..255) */
3760 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3762 /*************************************************************************
3763 * ColorHLSToRGB [SHLWAPI.@]
3765 * Convert from hls color space into an rgb COLORREF.
3768 * wHue [I] Hue amount
3769 * wLuminosity [I] Luminosity amount
3770 * wSaturation [I] Saturation amount
3773 * A COLORREF representing the converted color.
3776 * Input hls values are constrained to the range (0..240).
3778 COLORREF WINAPI
ColorHLSToRGB(WORD wHue
, WORD wLuminosity
, WORD wSaturation
)
3784 WORD wGreen
, wBlue
, wMid1
, wMid2
;
3786 if (wLuminosity
> 120)
3787 wMid2
= wSaturation
+ wLuminosity
- (wSaturation
* wLuminosity
+ 120) / 240;
3789 wMid2
= ((wSaturation
+ 240) * wLuminosity
+ 120) / 240;
3791 wMid1
= wLuminosity
* 2 - wMid2
;
3793 wRed
= GET_RGB(wHue
+ 80);
3794 wGreen
= GET_RGB(wHue
);
3795 wBlue
= GET_RGB(wHue
- 80);
3797 return RGB(wRed
, wGreen
, wBlue
);
3800 wRed
= wLuminosity
* 255 / 240;
3801 return RGB(wRed
, wRed
, wRed
);
3804 /*************************************************************************
3807 * Get the current docking status of the system.
3810 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3813 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3816 DWORD WINAPI
SHGetMachineInfo(DWORD dwFlags
)
3818 HW_PROFILE_INFOA hwInfo
;
3820 TRACE("(0x%08x)\n", dwFlags
);
3822 GetCurrentHwProfileA(&hwInfo
);
3823 switch (hwInfo
.dwDockInfo
& (DOCKINFO_DOCKED
|DOCKINFO_UNDOCKED
))
3825 case DOCKINFO_DOCKED
:
3826 case DOCKINFO_UNDOCKED
:
3827 return hwInfo
.dwDockInfo
& (DOCKINFO_DOCKED
|DOCKINFO_UNDOCKED
);
3833 /*************************************************************************
3837 DWORD WINAPI
SHWinHelpOnDemandW(HWND hwnd
, LPCWSTR helpfile
, DWORD flags1
, VOID
*ptr1
, DWORD flags2
)
3840 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd
, debugstr_w(helpfile
), flags1
, ptr1
, flags2
);
3844 /*************************************************************************
3848 DWORD WINAPI
SHWinHelpOnDemandA(HWND hwnd
, LPCSTR helpfile
, DWORD flags1
, VOID
*ptr1
, DWORD flags2
)
3851 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd
, debugstr_a(helpfile
), flags1
, ptr1
, flags2
);
3855 /*************************************************************************
3858 * Function seems to do FreeLibrary plus other things.
3860 * FIXME native shows the following calls:
3861 * RtlEnterCriticalSection
3863 * GetProcAddress(Comctl32??, 150L)
3865 * RtlLeaveCriticalSection
3866 * followed by the FreeLibrary.
3867 * The above code may be related to .377 above.
3869 BOOL WINAPI
MLFreeLibrary(HMODULE hModule
)
3871 FIXME("(%p) semi-stub\n", hModule
);
3872 return FreeLibrary(hModule
);
3875 /*************************************************************************
3878 BOOL WINAPI
SHFlushSFCacheWrap(void) {
3883 /*************************************************************************
3885 * FIXME I have no idea what this function does or what its arguments are.
3887 BOOL WINAPI
MLIsMLHInstance(HINSTANCE hInst
)
3889 FIXME("(%p) stub\n", hInst
);
3894 /*************************************************************************
3897 DWORD WINAPI
MLSetMLHInstance(HINSTANCE hInst
, HANDLE hHeap
)
3899 FIXME("(%p,%p) stub\n", hInst
, hHeap
);
3900 return E_FAIL
; /* This is what is used if shlwapi not loaded */
3903 /*************************************************************************
3906 DWORD WINAPI
MLClearMLHInstance(DWORD x
)
3908 FIXME("(0x%08x)stub\n", x
);
3912 /*************************************************************************
3915 * See SHSendMessageBroadcastW
3918 DWORD WINAPI
SHSendMessageBroadcastA(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3920 return SendMessageTimeoutA(HWND_BROADCAST
, uMsg
, wParam
, lParam
,
3921 SMTO_ABORTIFHUNG
, 2000, NULL
);
3924 /*************************************************************************
3927 * A wrapper for sending Broadcast Messages to all top level Windows
3930 DWORD WINAPI
SHSendMessageBroadcastW(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3932 return SendMessageTimeoutW(HWND_BROADCAST
, uMsg
, wParam
, lParam
,
3933 SMTO_ABORTIFHUNG
, 2000, NULL
);
3936 /*************************************************************************
3939 * Convert a Unicode string CLSID into a CLSID.
3942 * idstr [I] string containing a CLSID in text form
3943 * id [O] CLSID extracted from the string
3946 * S_OK on success or E_INVALIDARG on failure
3948 HRESULT WINAPI
CLSIDFromStringWrap(LPCWSTR idstr
, CLSID
*id
)
3950 return CLSIDFromString((LPCOLESTR
)idstr
, id
);
3953 /*************************************************************************
3956 * Determine if the OS supports a given feature.
3959 * dwFeature [I] Feature requested (undocumented)
3962 * TRUE If the feature is available.
3963 * FALSE If the feature is not available.
3965 BOOL WINAPI
IsOS(DWORD feature
)
3967 OSVERSIONINFOA osvi
;
3968 DWORD platform
, majorv
, minorv
;
3970 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
3971 if(!GetVersionExA(&osvi
)) {
3972 ERR("GetVersionEx failed\n");
3976 majorv
= osvi
.dwMajorVersion
;
3977 minorv
= osvi
.dwMinorVersion
;
3978 platform
= osvi
.dwPlatformId
;
3980 #define ISOS_RETURN(x) \
3981 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3985 case OS_WIN32SORGREATER
:
3986 ISOS_RETURN(platform
== VER_PLATFORM_WIN32s
3987 || platform
== VER_PLATFORM_WIN32_WINDOWS
)
3989 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
3990 case OS_WIN95ORGREATER
:
3991 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
)
3992 case OS_NT4ORGREATER
:
3993 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 4)
3994 case OS_WIN2000ORGREATER_ALT
:
3995 case OS_WIN2000ORGREATER
:
3996 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5)
3997 case OS_WIN98ORGREATER
:
3998 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
>= 10)
4000 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
== 10)
4002 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5)
4003 case OS_WIN2000SERVER
:
4004 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
4005 case OS_WIN2000ADVSERVER
:
4006 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
4007 case OS_WIN2000DATACENTER
:
4008 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
4009 case OS_WIN2000TERMINAL
:
4010 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
4012 FIXME("(OS_EMBEDDED) What should we return here?\n");
4014 case OS_TERMINALCLIENT
:
4015 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
4017 case OS_TERMINALREMOTEADMIN
:
4018 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
4021 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
== 0)
4022 case OS_MEORGREATER
:
4023 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
>= 90)
4024 case OS_XPORGREATER
:
4025 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5 && minorv
>= 1)
4027 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5 && minorv
>= 1)
4028 case OS_PROFESSIONAL
:
4029 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4031 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4033 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5)
4035 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4036 case OS_TERMINALSERVER
:
4037 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4038 case OS_PERSONALTERMINALSERVER
:
4039 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& minorv
>= 1 && majorv
>= 5)
4040 case OS_FASTUSERSWITCHING
:
4041 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
4043 case OS_WELCOMELOGONUI
:
4044 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
4046 case OS_DOMAINMEMBER
:
4047 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
4050 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4054 IsWow64Process(GetCurrentProcess(), &is_wow64
);
4058 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4059 case OS_SMALLBUSINESSSERVER
:
4060 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4062 FIXME("(OS_TABLEPC) What should we return here?\n");
4064 case OS_SERVERADMINUI
:
4065 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
4067 case OS_MEDIACENTER
:
4068 FIXME("(OS_MEDIACENTER) What should we return here?\n");
4071 FIXME("(OS_APPLIANCE) What should we return here?\n");
4073 case 0x25: /*OS_VISTAORGREATER*/
4074 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 6)
4079 WARN("(0x%x) unknown parameter\n",feature
);
4084 /*************************************************************************
4087 HRESULT WINAPI
SHLoadRegUIStringW(HKEY hkey
, LPCWSTR value
, LPWSTR buf
, DWORD size
)
4089 DWORD type
, sz
= size
;
4091 if(RegQueryValueExW(hkey
, value
, NULL
, &type
, (LPBYTE
)buf
, &sz
) != ERROR_SUCCESS
)
4094 return SHLoadIndirectString(buf
, buf
, size
, NULL
);
4097 /*************************************************************************
4100 * Call IInputObject_TranslateAcceleratorIO() on an object.
4103 * lpUnknown [I] Object supporting the IInputObject interface.
4104 * lpMsg [I] Key message to be processed.
4108 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4110 HRESULT WINAPI
IUnknown_TranslateAcceleratorIO(IUnknown
*lpUnknown
, LPMSG lpMsg
)
4112 IInputObject
* lpInput
= NULL
;
4113 HRESULT hRet
= E_INVALIDARG
;
4115 TRACE("(%p,%p)\n", lpUnknown
, lpMsg
);
4118 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObject
,
4120 if (SUCCEEDED(hRet
) && lpInput
)
4122 hRet
= IInputObject_TranslateAcceleratorIO(lpInput
, lpMsg
);
4123 IInputObject_Release(lpInput
);
4129 /*************************************************************************
4132 * Call IInputObject_HasFocusIO() on an object.
4135 * lpUnknown [I] Object supporting the IInputObject interface.
4138 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4139 * or S_FALSE otherwise.
4140 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4142 HRESULT WINAPI
IUnknown_HasFocusIO(IUnknown
*lpUnknown
)
4144 IInputObject
* lpInput
= NULL
;
4145 HRESULT hRet
= E_INVALIDARG
;
4147 TRACE("(%p)\n", lpUnknown
);
4150 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObject
,
4152 if (SUCCEEDED(hRet
) && lpInput
)
4154 hRet
= IInputObject_HasFocusIO(lpInput
);
4155 IInputObject_Release(lpInput
);
4161 /*************************************************************************
4162 * ColorRGBToHLS [SHLWAPI.@]
4164 * Convert an rgb COLORREF into the hls color space.
4167 * cRGB [I] Source rgb value
4168 * pwHue [O] Destination for converted hue
4169 * pwLuminance [O] Destination for converted luminance
4170 * pwSaturation [O] Destination for converted saturation
4173 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4177 * Output HLS values are constrained to the range (0..240).
4178 * For Achromatic conversions, Hue is set to 160.
4180 VOID WINAPI
ColorRGBToHLS(COLORREF cRGB
, LPWORD pwHue
,
4181 LPWORD pwLuminance
, LPWORD pwSaturation
)
4183 int wR
, wG
, wB
, wMax
, wMin
, wHue
, wLuminosity
, wSaturation
;
4185 TRACE("(%08x,%p,%p,%p)\n", cRGB
, pwHue
, pwLuminance
, pwSaturation
);
4187 wR
= GetRValue(cRGB
);
4188 wG
= GetGValue(cRGB
);
4189 wB
= GetBValue(cRGB
);
4191 wMax
= max(wR
, max(wG
, wB
));
4192 wMin
= min(wR
, min(wG
, wB
));
4195 wLuminosity
= ((wMax
+ wMin
) * 240 + 255) / 510;
4199 /* Achromatic case */
4201 /* Hue is now unrepresentable, but this is what native returns... */
4206 /* Chromatic case */
4207 int wDelta
= wMax
- wMin
, wRNorm
, wGNorm
, wBNorm
;
4210 if (wLuminosity
<= 120)
4211 wSaturation
= ((wMax
+ wMin
)/2 + wDelta
* 240) / (wMax
+ wMin
);
4213 wSaturation
= ((510 - wMax
- wMin
)/2 + wDelta
* 240) / (510 - wMax
- wMin
);
4216 wRNorm
= (wDelta
/2 + wMax
* 40 - wR
* 40) / wDelta
;
4217 wGNorm
= (wDelta
/2 + wMax
* 40 - wG
* 40) / wDelta
;
4218 wBNorm
= (wDelta
/2 + wMax
* 40 - wB
* 40) / wDelta
;
4221 wHue
= wBNorm
- wGNorm
;
4222 else if (wG
== wMax
)
4223 wHue
= 80 + wRNorm
- wBNorm
;
4225 wHue
= 160 + wGNorm
- wRNorm
;
4228 else if (wHue
> 240)
4234 *pwLuminance
= wLuminosity
;
4236 *pwSaturation
= wSaturation
;
4239 /*************************************************************************
4240 * SHCreateShellPalette [SHLWAPI.@]
4242 HPALETTE WINAPI
SHCreateShellPalette(HDC hdc
)
4245 return CreateHalftonePalette(hdc
);
4248 /*************************************************************************
4249 * SHGetInverseCMAP (SHLWAPI.@)
4251 * Get an inverse color map table.
4254 * lpCmap [O] Destination for color map
4255 * dwSize [I] Size of memory pointed to by lpCmap
4259 * Failure: E_POINTER, If lpCmap is invalid.
4260 * E_INVALIDARG, If dwFlags is invalid
4261 * E_OUTOFMEMORY, If there is no memory available
4264 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4265 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4267 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4268 * this DLL's internal CMap.
4270 HRESULT WINAPI
SHGetInverseCMAP(LPDWORD dest
, DWORD dwSize
)
4273 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4274 *dest
= (DWORD
)0xabba1249;
4277 FIXME("(%p, %#x) stub\n", dest
, dwSize
);
4281 /*************************************************************************
4282 * SHIsLowMemoryMachine [SHLWAPI.@]
4284 * Determine if the current computer has low memory.
4290 * TRUE if the users machine has 16 Megabytes of memory or less,
4293 BOOL WINAPI
SHIsLowMemoryMachine (DWORD x
)
4295 FIXME("(0x%08x) stub\n", x
);
4299 /*************************************************************************
4300 * GetMenuPosFromID [SHLWAPI.@]
4302 * Return the position of a menu item from its Id.
4305 * hMenu [I] Menu containing the item
4306 * wID [I] Id of the menu item
4309 * Success: The index of the menu item in hMenu.
4310 * Failure: -1, If the item is not found.
4312 INT WINAPI
GetMenuPosFromID(HMENU hMenu
, UINT wID
)
4315 INT nCount
= GetMenuItemCount(hMenu
), nIter
= 0;
4317 TRACE("%p %u\n", hMenu
, wID
);
4319 while (nIter
< nCount
)
4321 mi
.cbSize
= sizeof(mi
);
4323 if (GetMenuItemInfoW(hMenu
, nIter
, TRUE
, &mi
) && mi
.wID
== wID
)
4325 TRACE("ret %d\n", nIter
);
4334 /*************************************************************************
4337 * Same as SHLWAPI.GetMenuPosFromID
4339 DWORD WINAPI
SHMenuIndexFromID(HMENU hMenu
, UINT uID
)
4341 TRACE("%p %u\n", hMenu
, uID
);
4342 return GetMenuPosFromID(hMenu
, uID
);
4346 /*************************************************************************
4349 VOID WINAPI
FixSlashesAndColonW(LPWSTR lpwstr
)
4360 /*************************************************************************
4363 DWORD WINAPI
SHGetAppCompatFlags(DWORD dwUnknown
)
4365 FIXME("(0x%08x) stub\n", dwUnknown
);
4370 /*************************************************************************
4373 HRESULT WINAPI
SHCoCreateInstanceAC(REFCLSID rclsid
, LPUNKNOWN pUnkOuter
,
4374 DWORD dwClsContext
, REFIID iid
, LPVOID
*ppv
)
4376 return CoCreateInstance(rclsid
, pUnkOuter
, dwClsContext
, iid
, ppv
);
4379 /*************************************************************************
4380 * SHSkipJunction [SHLWAPI.@]
4382 * Determine if a bind context can be bound to an object
4385 * pbc [I] Bind context to check
4386 * pclsid [I] CLSID of object to be bound to
4389 * TRUE: If it is safe to bind
4390 * FALSE: If pbc is invalid or binding would not be safe
4393 BOOL WINAPI
SHSkipJunction(IBindCtx
*pbc
, const CLSID
*pclsid
)
4395 static WCHAR szSkipBinding
[] = { 'S','k','i','p',' ',
4396 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4403 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc
, szSkipBinding
, &lpUnk
)))
4407 if (SUCCEEDED(IUnknown_GetClassID(lpUnk
, &clsid
)) &&
4408 IsEqualGUID(pclsid
, &clsid
))
4411 IUnknown_Release(lpUnk
);
4417 /***********************************************************************
4418 * SHGetShellKey (SHLWAPI.491)
4420 HKEY WINAPI
SHGetShellKey(DWORD flags
, LPCWSTR sub_key
, BOOL create
)
4422 enum _shellkey_flags
{
4423 SHKEY_Root_HKCU
= 0x1,
4424 SHKEY_Root_HKLM
= 0x2,
4425 SHKEY_Key_Explorer
= 0x00,
4426 SHKEY_Key_Shell
= 0x10,
4427 SHKEY_Key_ShellNoRoam
= 0x20,
4428 SHKEY_Key_Classes
= 0x30,
4429 SHKEY_Subkey_Default
= 0x0000,
4430 SHKEY_Subkey_ResourceName
= 0x1000,
4431 SHKEY_Subkey_Handlers
= 0x2000,
4432 SHKEY_Subkey_Associations
= 0x3000,
4433 SHKEY_Subkey_Volatile
= 0x4000,
4434 SHKEY_Subkey_MUICache
= 0x5000,
4435 SHKEY_Subkey_FileExts
= 0x6000
4438 static const WCHAR explorerW
[] = {'S','o','f','t','w','a','r','e','\\',
4439 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4440 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4441 'E','x','p','l','o','r','e','r','\\'};
4442 static const WCHAR shellW
[] = {'S','o','f','t','w','a','r','e','\\',
4443 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4444 'S','h','e','l','l','\\'};
4445 static const WCHAR shell_no_roamW
[] = {'S','o','f','t','w','a','r','e','\\',
4446 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4447 'S','h','e','l','l','N','o','R','o','a','m','\\'};
4448 static const WCHAR classesW
[] = {'S','o','f','t','w','a','r','e','\\',
4449 'C','l','a','s','s','e','s','\\'};
4451 static const WCHAR localized_resource_nameW
[] = {'L','o','c','a','l','i','z','e','d',
4452 'R','e','s','o','u','r','c','e','N','a','m','e','\\'};
4453 static const WCHAR handlersW
[] = {'H','a','n','d','l','e','r','s','\\'};
4454 static const WCHAR associationsW
[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'};
4455 static const WCHAR volatileW
[] = {'V','o','l','a','t','i','l','e','\\'};
4456 static const WCHAR mui_cacheW
[] = {'M','U','I','C','a','c','h','e','\\'};
4457 static const WCHAR file_extsW
[] = {'F','i','l','e','E','x','t','s','\\'};
4460 const WCHAR
*key
, *subkey
;
4461 int size_key
, size_subkey
, size_user
;
4464 TRACE("(0x%08x, %s, %d)\n", flags
, debugstr_w(sub_key
), create
);
4466 /* For compatibility with Vista+ */
4467 if(flags
== 0x1ffff)
4470 switch(flags
&0xff0) {
4471 case SHKEY_Key_Explorer
:
4473 size_key
= sizeof(explorerW
);
4475 case SHKEY_Key_Shell
:
4477 size_key
= sizeof(shellW
);
4479 case SHKEY_Key_ShellNoRoam
:
4480 key
= shell_no_roamW
;
4481 size_key
= sizeof(shell_no_roamW
);
4483 case SHKEY_Key_Classes
:
4485 size_key
= sizeof(classesW
);
4488 FIXME("unsupported flags (0x%08x)\n", flags
);
4492 switch(flags
&0xff000) {
4493 case SHKEY_Subkey_Default
:
4497 case SHKEY_Subkey_ResourceName
:
4498 subkey
= localized_resource_nameW
;
4499 size_subkey
= sizeof(localized_resource_nameW
);
4501 case SHKEY_Subkey_Handlers
:
4503 size_subkey
= sizeof(handlersW
);
4505 case SHKEY_Subkey_Associations
:
4506 subkey
= associationsW
;
4507 size_subkey
= sizeof(associationsW
);
4509 case SHKEY_Subkey_Volatile
:
4511 size_subkey
= sizeof(volatileW
);
4513 case SHKEY_Subkey_MUICache
:
4514 subkey
= mui_cacheW
;
4515 size_subkey
= sizeof(mui_cacheW
);
4517 case SHKEY_Subkey_FileExts
:
4518 subkey
= file_extsW
;
4519 size_subkey
= sizeof(file_extsW
);
4522 FIXME("unsupported flags (0x%08x)\n", flags
);
4527 size_user
= lstrlenW(sub_key
)*sizeof(WCHAR
);
4531 path
= HeapAlloc(GetProcessHeap(), 0, size_key
+size_subkey
+size_user
+sizeof(WCHAR
));
4533 ERR("Out of memory\n");
4537 memcpy(path
, key
, size_key
);
4539 memcpy(path
+size_key
/sizeof(WCHAR
), subkey
, size_subkey
);
4541 memcpy(path
+(size_key
+size_subkey
)/sizeof(WCHAR
), sub_key
, size_user
);
4542 path
[(size_key
+size_subkey
+size_user
)/sizeof(WCHAR
)] = '\0';
4545 RegCreateKeyExW((flags
&0xf)==SHKEY_Root_HKLM
?HKEY_LOCAL_MACHINE
:HKEY_CURRENT_USER
,
4546 path
, 0, NULL
, 0, MAXIMUM_ALLOWED
, NULL
, &hkey
, NULL
);
4548 RegOpenKeyExW((flags
&0xf)==SHKEY_Root_HKLM
?HKEY_LOCAL_MACHINE
:HKEY_CURRENT_USER
,
4549 path
, 0, MAXIMUM_ALLOWED
, &hkey
);
4551 HeapFree(GetProcessHeap(), 0, path
);
4555 /***********************************************************************
4556 * SHQueueUserWorkItem (SHLWAPI.@)
4558 BOOL WINAPI
SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback
,
4559 LPVOID pContext
, LONG lPriority
, DWORD_PTR dwTag
,
4560 DWORD_PTR
*pdwId
, LPCSTR pszModule
, DWORD dwFlags
)
4562 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback
, pContext
,
4563 lPriority
, dwTag
, pdwId
, debugstr_a(pszModule
), dwFlags
);
4565 if(lPriority
|| dwTag
|| pdwId
|| pszModule
|| dwFlags
)
4566 FIXME("Unsupported arguments\n");
4568 return QueueUserWorkItem(pfnCallback
, pContext
, 0);
4571 /***********************************************************************
4572 * SHSetTimerQueueTimer (SHLWAPI.263)
4574 HANDLE WINAPI
SHSetTimerQueueTimer(HANDLE hQueue
,
4575 WAITORTIMERCALLBACK pfnCallback
, LPVOID pContext
, DWORD dwDueTime
,
4576 DWORD dwPeriod
, LPCSTR lpszLibrary
, DWORD dwFlags
)
4580 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4581 if (dwFlags
& TPS_LONGEXECTIME
) {
4582 dwFlags
&= ~TPS_LONGEXECTIME
;
4583 dwFlags
|= WT_EXECUTELONGFUNCTION
;
4585 if (dwFlags
& TPS_EXECUTEIO
) {
4586 dwFlags
&= ~TPS_EXECUTEIO
;
4587 dwFlags
|= WT_EXECUTEINIOTHREAD
;
4590 if (!CreateTimerQueueTimer(&hNewTimer
, hQueue
, pfnCallback
, pContext
,
4591 dwDueTime
, dwPeriod
, dwFlags
))
4597 /***********************************************************************
4598 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4600 HRESULT WINAPI
IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown
, LPUNKNOWN pFocusObject
, BOOL bFocus
)
4602 IInputObjectSite
*pIOS
= NULL
;
4603 HRESULT hRet
= E_INVALIDARG
;
4605 TRACE("(%p, %p, %s)\n", lpUnknown
, pFocusObject
, bFocus
? "TRUE" : "FALSE");
4609 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObjectSite
,
4611 if (SUCCEEDED(hRet
) && pIOS
)
4613 hRet
= IInputObjectSite_OnFocusChangeIS(pIOS
, pFocusObject
, bFocus
);
4614 IInputObjectSite_Release(pIOS
);
4620 /***********************************************************************
4621 * SKAllocValueW (SHLWAPI.519)
4623 HRESULT WINAPI
SKAllocValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
, DWORD
*type
,
4624 LPVOID
*data
, DWORD
*count
)
4629 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags
, debugstr_w(subkey
),
4630 debugstr_w(value
), type
, data
, count
);
4632 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
4634 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4636 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, NULL
, &size
);
4639 return HRESULT_FROM_WIN32(ret
);
4643 *data
= LocalAlloc(0, size
);
4646 return E_OUTOFMEMORY
;
4649 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, *data
, &size
);
4654 return HRESULT_FROM_WIN32(ret
);
4657 /***********************************************************************
4658 * SKDeleteValueW (SHLWAPI.518)
4660 HRESULT WINAPI
SKDeleteValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
)
4665 TRACE("(0x%x, %s %s)\n", flags
, debugstr_w(subkey
), debugstr_w(value
));
4667 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
4669 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4671 ret
= RegDeleteValueW(hkey
, value
);
4674 return HRESULT_FROM_WIN32(ret
);
4677 /***********************************************************************
4678 * SKGetValueW (SHLWAPI.516)
4680 HRESULT WINAPI
SKGetValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
, DWORD
*type
,
4681 void *data
, DWORD
*count
)
4686 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags
, debugstr_w(subkey
),
4687 debugstr_w(value
), type
, data
, count
);
4689 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
4691 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4693 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, data
, count
);
4696 return HRESULT_FROM_WIN32(ret
);
4699 /***********************************************************************
4700 * SKSetValueW (SHLWAPI.516)
4702 HRESULT WINAPI
SKSetValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
,
4703 DWORD type
, void *data
, DWORD count
)
4708 TRACE("(0x%x, %s, %s, %x, %p, %d)\n", flags
, debugstr_w(subkey
),
4709 debugstr_w(value
), type
, data
, count
);
4711 hkey
= SHGetShellKey(flags
, subkey
, TRUE
);
4713 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4715 ret
= RegSetValueExW(hkey
, value
, 0, type
, data
, count
);
4718 return HRESULT_FROM_WIN32(ret
);
4721 typedef HRESULT (WINAPI
*DllGetVersion_func
)(DLLVERSIONINFO
*);
4723 /***********************************************************************
4724 * GetUIVersion (SHLWAPI.452)
4726 DWORD WINAPI
GetUIVersion(void)
4728 static DWORD version
;
4732 DllGetVersion_func pDllGetVersion
;
4733 HMODULE dll
= LoadLibraryA("shell32.dll");
4736 pDllGetVersion
= (DllGetVersion_func
)GetProcAddress(dll
, "DllGetVersion");
4740 dvi
.cbSize
= sizeof(DLLVERSIONINFO
);
4741 if (pDllGetVersion(&dvi
) == S_OK
) version
= dvi
.dwMajorVersion
;
4744 if (!version
) version
= 3; /* old shell dlls don't have DllGetVersion */
4749 /***********************************************************************
4750 * ShellMessageBoxWrapW [SHLWAPI.388]
4752 * See shell32.ShellMessageBoxW
4755 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4756 * because we can't forward to it in the .spec file since it's exported by
4757 * ordinal. If you change the implementation here please update the code in
4760 INT WINAPIV
ShellMessageBoxWrapW(HINSTANCE hInstance
, HWND hWnd
, LPCWSTR lpText
,
4761 LPCWSTR lpCaption
, UINT uType
, ...)
4763 WCHAR
*szText
= NULL
, szTitle
[100];
4764 LPCWSTR pszText
, pszTitle
= szTitle
;
4769 __ms_va_start(args
, uType
);
4771 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance
, hWnd
, lpText
, lpCaption
, uType
);
4773 if (IS_INTRESOURCE(lpCaption
))
4774 LoadStringW(hInstance
, LOWORD(lpCaption
), szTitle
, sizeof(szTitle
)/sizeof(szTitle
[0]));
4776 pszTitle
= lpCaption
;
4778 if (IS_INTRESOURCE(lpText
))
4781 UINT len
= LoadStringW(hInstance
, LOWORD(lpText
), (LPWSTR
)&ptr
, 0);
4785 szText
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
4786 if (szText
) LoadStringW(hInstance
, LOWORD(lpText
), szText
, len
+ 1);
4790 WARN("Failed to load id %d\n", LOWORD(lpText
));
4798 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
,
4799 pszText
, 0, 0, (LPWSTR
)&pszTemp
, 0, &args
);
4803 ret
= MessageBoxW(hWnd
, pszTemp
, pszTitle
, uType
);
4805 HeapFree(GetProcessHeap(), 0, szText
);
4810 /***********************************************************************
4811 * ZoneComputePaneSize [SHLWAPI.382]
4813 UINT WINAPI
ZoneComputePaneSize(HWND hwnd
)
4819 /***********************************************************************
4820 * SHChangeNotifyWrap [SHLWAPI.394]
4822 void WINAPI
SHChangeNotifyWrap(LONG wEventId
, UINT uFlags
, LPCVOID dwItem1
, LPCVOID dwItem2
)
4824 SHChangeNotify(wEventId
, uFlags
, dwItem1
, dwItem2
);
4827 typedef struct SHELL_USER_SID
{ /* according to MSDN this should be in shlobj.h... */
4828 SID_IDENTIFIER_AUTHORITY sidAuthority
;
4829 DWORD dwUserGroupID
;
4831 } SHELL_USER_SID
, *PSHELL_USER_SID
;
4833 typedef struct SHELL_USER_PERMISSION
{ /* ...and this should be in shlwapi.h */
4834 SHELL_USER_SID susID
;
4838 DWORD dwInheritMask
;
4839 DWORD dwInheritAccessMask
;
4840 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
4842 /***********************************************************************
4843 * GetShellSecurityDescriptor [SHLWAPI.475]
4845 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4848 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4849 * each of which describes permissions to apply
4850 * cUserPerm [I] number of entries in apUserPerm array
4853 * success: pointer to SECURITY_DESCRIPTOR
4857 * Call should free returned descriptor with LocalFree
4859 PSECURITY_DESCRIPTOR WINAPI
GetShellSecurityDescriptor(PSHELL_USER_PERMISSION
*apUserPerm
, int cUserPerm
)
4862 PSID cur_user
= NULL
;
4866 PSECURITY_DESCRIPTOR psd
= NULL
;
4868 TRACE("%p %d\n", apUserPerm
, cUserPerm
);
4870 if (apUserPerm
== NULL
|| cUserPerm
<= 0)
4873 sidlist
= HeapAlloc(GetProcessHeap(), 0, cUserPerm
* sizeof(PSID
));
4877 acl_size
= sizeof(ACL
);
4879 for(sid_count
= 0; sid_count
< cUserPerm
; sid_count
++)
4881 static SHELL_USER_SID null_sid
= {{SECURITY_NULL_SID_AUTHORITY
}, 0, 0};
4882 PSHELL_USER_PERMISSION perm
= apUserPerm
[sid_count
];
4883 PSHELL_USER_SID sid
= &perm
->susID
;
4887 if (!memcmp((void*)sid
, (void*)&null_sid
, sizeof(SHELL_USER_SID
)))
4888 { /* current user's SID */
4892 DWORD bufsize
= sizeof(tuUser
);
4894 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &Token
);
4897 ret
= GetTokenInformation(Token
, TokenUser
, (void*)tuUser
, bufsize
, &bufsize
);
4899 cur_user
= ((PTOKEN_USER
)tuUser
)->User
.Sid
;
4904 } else if (sid
->dwUserID
==0) /* one sub-authority */
4905 ret
= AllocateAndInitializeSid(&sid
->sidAuthority
, 1, sid
->dwUserGroupID
, 0,
4906 0, 0, 0, 0, 0, 0, &pSid
);
4908 ret
= AllocateAndInitializeSid(&sid
->sidAuthority
, 2, sid
->dwUserGroupID
, sid
->dwUserID
,
4909 0, 0, 0, 0, 0, 0, &pSid
);
4913 sidlist
[sid_count
] = pSid
;
4914 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4915 acl_size
+= (sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
) + GetLengthSid(pSid
)) * (perm
->fInherit
? 2 : 1);
4918 psd
= LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR
) + acl_size
);
4922 PACL pAcl
= (PACL
)(((BYTE
*)psd
)+sizeof(SECURITY_DESCRIPTOR
));
4924 if (!InitializeSecurityDescriptor(psd
, SECURITY_DESCRIPTOR_REVISION
))
4927 if (!InitializeAcl(pAcl
, acl_size
, ACL_REVISION
))
4930 for(i
= 0; i
< sid_count
; i
++)
4932 PSHELL_USER_PERMISSION sup
= apUserPerm
[i
];
4933 PSID sid
= sidlist
[i
];
4935 switch(sup
->dwAccessType
)
4937 case ACCESS_ALLOWED_ACE_TYPE
:
4938 if (!AddAccessAllowedAce(pAcl
, ACL_REVISION
, sup
->dwAccessMask
, sid
))
4940 if (sup
->fInherit
&& !AddAccessAllowedAceEx(pAcl
, ACL_REVISION
,
4941 (BYTE
)sup
->dwInheritMask
, sup
->dwInheritAccessMask
, sid
))
4944 case ACCESS_DENIED_ACE_TYPE
:
4945 if (!AddAccessDeniedAce(pAcl
, ACL_REVISION
, sup
->dwAccessMask
, sid
))
4947 if (sup
->fInherit
&& !AddAccessDeniedAceEx(pAcl
, ACL_REVISION
,
4948 (BYTE
)sup
->dwInheritMask
, sup
->dwInheritAccessMask
, sid
))
4956 if (!SetSecurityDescriptorDacl(psd
, TRUE
, pAcl
, FALSE
))
4965 for(i
= 0; i
< sid_count
; i
++)
4967 if (!cur_user
|| sidlist
[i
] != cur_user
)
4968 FreeSid(sidlist
[i
]);
4970 HeapFree(GetProcessHeap(), 0, sidlist
);
4975 /***********************************************************************
4976 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4978 * Creates a property bag from a registry key
4981 * hKey [I] Handle to the desired registry key
4982 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4983 * grfMode [I] Optional flags
4984 * riid [I] IID of requested property bag interface
4985 * ppv [O] Address to receive pointer to the new interface
4989 * failure: error code
4992 HRESULT WINAPI
SHCreatePropertyBagOnRegKey (HKEY hKey
, LPCWSTR subkey
,
4993 DWORD grfMode
, REFIID riid
, void **ppv
)
4995 FIXME("%p %s %d %s %p STUB\n", hKey
, debugstr_w(subkey
), grfMode
,
4996 debugstr_guid(riid
), ppv
);
5001 /***********************************************************************
5002 * SHGetViewStatePropertyBag [SHLWAPI.515]
5004 * Retrieves a property bag in which the view state information of a folder
5008 * pidl [I] PIDL of the folder requested
5009 * bag_name [I] Name of the property bag requested
5010 * flags [I] Optional flags
5011 * riid [I] IID of requested property bag interface
5012 * ppv [O] Address to receive pointer to the new interface
5016 * failure: error code
5019 HRESULT WINAPI
SHGetViewStatePropertyBag(LPCITEMIDLIST pidl
, LPWSTR bag_name
,
5020 DWORD flags
, REFIID riid
, void **ppv
)
5022 FIXME("%p %s %d %s %p STUB\n", pidl
, debugstr_w(bag_name
), flags
,
5023 debugstr_guid(riid
), ppv
);
5028 /***********************************************************************
5029 * SHFormatDateTimeW [SHLWAPI.354]
5031 * Produces a string representation of a time.
5034 * fileTime [I] Pointer to FILETIME structure specifying the time
5035 * flags [I] Flags specifying the desired output
5036 * buf [O] Pointer to buffer for output
5037 * size [I] Number of characters that can be contained in buffer
5040 * success: number of characters written to the buffer
5044 INT WINAPI
SHFormatDateTimeW(const FILETIME UNALIGNED
*fileTime
, DWORD
*flags
,
5045 LPWSTR buf
, UINT size
)
5047 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
5048 DWORD fmt_flags
= flags
? *flags
: FDTF_DEFAULT
;
5053 TRACE("%p %p %p %u\n", fileTime
, flags
, buf
, size
);
5058 if (fmt_flags
& SHFORMATDT_UNSUPPORTED_FLAGS
)
5059 FIXME("ignoring some flags - 0x%08x\n", fmt_flags
& SHFORMATDT_UNSUPPORTED_FLAGS
);
5061 FileTimeToLocalFileTime(fileTime
, &ft
);
5062 FileTimeToSystemTime(&ft
, &st
);
5064 /* first of all date */
5065 if (fmt_flags
& (FDTF_LONGDATE
| FDTF_SHORTDATE
))
5067 static const WCHAR sep1
[] = {',',' ',0};
5068 static const WCHAR sep2
[] = {' ',0};
5070 DWORD date
= fmt_flags
& FDTF_LONGDATE
? DATE_LONGDATE
: DATE_SHORTDATE
;
5071 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, date
, &st
, NULL
, buf
, size
);
5072 if (ret
>= size
) return ret
;
5075 if (ret
< size
&& (fmt_flags
& (FDTF_LONGTIME
| FDTF_SHORTTIME
)))
5077 if ((fmt_flags
& FDTF_LONGDATE
) && (ret
< size
+ 2))
5081 lstrcatW(&buf
[ret
-1], sep1
);
5087 lstrcatW(&buf
[ret
-1], sep2
);
5093 if (fmt_flags
& (FDTF_LONGTIME
| FDTF_SHORTTIME
))
5095 DWORD time
= fmt_flags
& FDTF_LONGTIME
? 0 : TIME_NOSECONDS
;
5098 ret
+= GetTimeFormatW(LOCALE_USER_DEFAULT
, time
, &st
, NULL
, &buf
[ret
], size
- ret
);
5103 #undef SHFORMATDT_UNSUPPORTED_FLAGS
5106 /***********************************************************************
5107 * SHFormatDateTimeA [SHLWAPI.353]
5109 * See SHFormatDateTimeW.
5112 INT WINAPI
SHFormatDateTimeA(const FILETIME UNALIGNED
*fileTime
, DWORD
*flags
,
5113 LPSTR buf
, UINT size
)
5121 bufW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * size
);
5122 retval
= SHFormatDateTimeW(fileTime
, flags
, bufW
, size
);
5125 WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, buf
, size
, NULL
, NULL
);
5127 HeapFree(GetProcessHeap(), 0, bufW
);
5131 /***********************************************************************
5132 * ZoneCheckUrlExW [SHLWAPI.231]
5134 * Checks the details of the security zone for the supplied site. (?)
5138 * szURL [I] Pointer to the URL to check
5140 * Other parameters currently unknown.
5146 INT WINAPI
ZoneCheckUrlExW(LPWSTR szURL
, PVOID pUnknown
, DWORD dwUnknown2
,
5147 DWORD dwUnknown3
, DWORD dwUnknown4
, DWORD dwUnknown5
, DWORD dwUnknown6
,
5150 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL
), pUnknown
, dwUnknown2
,
5151 dwUnknown3
, dwUnknown4
, dwUnknown5
, dwUnknown6
, dwUnknown7
);
5156 /***********************************************************************
5157 * SHVerbExistsNA [SHLWAPI.196]
5162 * verb [I] a string, often appears to be an extension.
5164 * Other parameters currently unknown.
5169 INT WINAPI
SHVerbExistsNA(LPSTR verb
, PVOID pUnknown
, PVOID pUnknown2
, DWORD dwUnknown3
)
5171 FIXME("(%s, %p, %p, %i) STUB\n",verb
, pUnknown
, pUnknown2
, dwUnknown3
);
5175 /*************************************************************************
5178 * Undocumented: Implementation guessed at via Name and behavior
5181 * lpUnknown [I] Object to get an IServiceProvider interface from
5182 * riid [I] Function requested for QueryService call
5183 * lppOut [O] Destination for the service interface pointer
5186 * Success: S_OK. lppOut contains an object providing the requested service
5187 * Failure: An HRESULT error code
5190 * lpUnknown is expected to support the IServiceProvider interface.
5192 HRESULT WINAPI
IUnknown_QueryServiceForWebBrowserApp(IUnknown
* lpUnknown
,
5193 REFGUID riid
, LPVOID
*lppOut
)
5195 FIXME("%p %s %p semi-STUB\n", lpUnknown
, debugstr_guid(riid
), lppOut
);
5196 return IUnknown_QueryService(lpUnknown
,&IID_IWebBrowserApp
,riid
,lppOut
);
5199 /**************************************************************************
5200 * SHPropertyBag_ReadLONG (SHLWAPI.496)
5202 * This function asks a property bag to read a named property as a LONG.
5205 * ppb: a IPropertyBag interface
5206 * pszPropName: Unicode string that names the property
5207 * pValue: address to receive the property value as a 32-bit signed integer
5212 BOOL WINAPI
SHPropertyBag_ReadLONG(IPropertyBag
*ppb
, LPCWSTR pszPropName
, LPLONG pValue
)
5216 TRACE("%p %s %p\n", ppb
,debugstr_w(pszPropName
),pValue
);
5217 if (!pszPropName
|| !ppb
|| !pValue
)
5218 return E_INVALIDARG
;
5220 hr
= IPropertyBag_Read(ppb
, pszPropName
, &var
, NULL
);
5223 if (V_VT(&var
) == VT_I4
)
5224 *pValue
= V_I4(&var
);
5226 hr
= DISP_E_BADVARTYPE
;
5231 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
5232 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
5233 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
5234 #define OBJCOMPAT_UNBINDABLE 0x00000004
5235 #define OBJCOMPAT_PINDLL 0x00000008
5236 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
5237 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
5238 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
5239 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
5240 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
5241 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
5242 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
5243 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
5244 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
5246 /* a search table for compatibility flags */
5247 struct objcompat_entry
{
5248 const WCHAR name
[30];
5252 /* expected to be sorted by name */
5253 static const struct objcompat_entry objcompat_table
[] = {
5254 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
5255 OBJCOMPAT_COCREATESHELLFOLDERONLY
},
5256 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
5257 OBJCOMPAT_CTXMENU_LIMITEDQI
},
5258 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
5259 OBJCOMPAT_CTXMENU_LIMITEDQI
},
5260 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
5261 OBJCOMPAT_CTXMENU_XPQCMFLAGS
},
5262 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
5263 OBJCOMPAT_NEEDSFILESYSANCESTOR
},
5264 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
5265 OBJCOMPAT_NEEDSSTORAGEANCESTOR
},
5266 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
5267 OBJCOMPAT_NOIPROPERTYSTORE
},
5268 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
5269 OBJCOMPAT_NOLEGACYWEBVIEW
},
5270 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
5271 OBJCOMPAT_NOTAFILESYSTEM
},
5272 { {'N','O','_','W','E','B','V','I','E','W',0},
5273 OBJCOMPAT_NO_WEBVIEW
},
5274 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
5275 OBJCOMPAT_OTNEEDSSFCACHE
},
5276 { {'P','I','N','D','L','L',0},
5278 { {'U','N','B','I','N','D','A','B','L','E',0},
5279 OBJCOMPAT_UNBINDABLE
}
5282 /**************************************************************************
5283 * SHGetObjectCompatFlags (SHLWAPI.476)
5285 * Function returns an integer representation of compatibility flags stored
5286 * in registry for CLSID under ShellCompatibility subkey.
5289 * pUnk: pointer to object IUnknown interface, idetifies CLSID
5290 * clsid: pointer to CLSID to retrieve data for
5293 * 0 on failure, flags set on success
5295 DWORD WINAPI
SHGetObjectCompatFlags(IUnknown
*pUnk
, const CLSID
*clsid
)
5297 static const WCHAR compatpathW
[] =
5298 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
5299 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
5300 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
5301 'O','b','j','e','c','t','s','\\','%','s',0};
5302 WCHAR strW
[sizeof(compatpathW
)/sizeof(WCHAR
) + 38 /* { CLSID } */];
5303 DWORD ret
, length
= sizeof(strW
)/sizeof(WCHAR
);
5308 TRACE("%p %s\n", pUnk
, debugstr_guid(clsid
));
5310 if (!pUnk
&& !clsid
) return 0;
5314 FIXME("iface not handled\n");
5318 StringFromCLSID(clsid
, &clsid_str
);
5319 sprintfW(strW
, compatpathW
, clsid_str
);
5320 CoTaskMemFree(clsid_str
);
5322 ret
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, strW
, &key
);
5323 if (ret
!= ERROR_SUCCESS
) return 0;
5325 /* now collect flag values */
5327 for (i
= 0; RegEnumValueW(key
, i
, strW
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; i
++)
5329 INT left
, right
, res
, x
;
5331 /* search in table */
5333 right
= sizeof(objcompat_table
) / sizeof(struct objcompat_entry
) - 1;
5335 while (right
>= left
) {
5336 x
= (left
+ right
) / 2;
5337 res
= strcmpW(strW
, objcompat_table
[x
].name
);
5340 ret
|= objcompat_table
[x
].value
;
5349 length
= sizeof(strW
)/sizeof(WCHAR
);