2 * SHLWAPI ordinal functions
4 * Copyright 1997 Marcus Meissner
6 * 2001-2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
45 #include "shdeprecated.h"
52 #include "wine/unicode.h"
53 #include "wine/debug.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
58 /* DLL handles for late bound calls */
59 extern HINSTANCE shlwapi_hInstance
;
60 extern DWORD SHLWAPI_ThreadRef_index
;
62 HRESULT WINAPI
IUnknown_QueryService(IUnknown
*,REFGUID
,REFIID
,LPVOID
*);
63 HRESULT WINAPI
SHInvokeCommand(HWND
,IShellFolder
*,LPCITEMIDLIST
,DWORD
);
64 BOOL WINAPI
SHAboutInfoW(LPWSTR
,DWORD
);
67 NOTES: Most functions exported by ordinal seem to be superfluous.
68 The reason for these functions to be there is to provide a wrapper
69 for unicode functions to provide these functions on systems without
70 unicode functions eg. win95/win98. Since we have such functions we just
71 call these. If running Wine with native DLLs, some late bound calls may
72 fail. However, it is better to implement the functions in the forward DLL
73 and recommend the builtin rather than reimplementing the calls here!
76 /*************************************************************************
79 * Copy a sharable memory handle from one process to another.
82 * hShared [I] Shared memory handle to duplicate
83 * dwSrcProcId [I] ID of the process owning hShared
84 * dwDstProcId [I] ID of the process wanting the duplicated handle
85 * dwAccess [I] Desired DuplicateHandle() access
86 * dwOptions [I] Desired DuplicateHandle() options
89 * Success: A handle suitable for use by the dwDstProcId process.
90 * Failure: A NULL handle.
93 HANDLE WINAPI
SHMapHandle(HANDLE hShared
, DWORD dwSrcProcId
, DWORD dwDstProcId
,
94 DWORD dwAccess
, DWORD dwOptions
)
97 DWORD dwMyProcId
= GetCurrentProcessId();
100 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared
, dwDstProcId
, dwSrcProcId
,
101 dwAccess
, dwOptions
);
103 /* Get dest process handle */
104 if (dwDstProcId
== dwMyProcId
)
105 hDst
= GetCurrentProcess();
107 hDst
= OpenProcess(PROCESS_DUP_HANDLE
, 0, dwDstProcId
);
111 /* Get src process handle */
112 if (dwSrcProcId
== dwMyProcId
)
113 hSrc
= GetCurrentProcess();
115 hSrc
= OpenProcess(PROCESS_DUP_HANDLE
, 0, dwSrcProcId
);
119 /* Make handle available to dest process */
120 if (!DuplicateHandle(hSrc
, hShared
, hDst
, &hRet
,
121 dwAccess
, 0, dwOptions
| DUPLICATE_SAME_ACCESS
))
124 if (dwSrcProcId
!= dwMyProcId
)
128 if (dwDstProcId
!= dwMyProcId
)
132 TRACE("Returning handle %p\n", hRet
);
136 /*************************************************************************
139 * Create a block of sharable memory and initialise it with data.
142 * lpvData [I] Pointer to data to write
143 * dwSize [I] Size of data
144 * dwProcId [I] ID of process owning data
147 * Success: A shared memory handle
151 * Ordinals 7-11 provide a set of calls to create shared memory between a
152 * group of processes. The shared memory is treated opaquely in that its size
153 * is not exposed to clients who map it. This is accomplished by storing
154 * the size of the map as the first DWORD of mapped data, and then offsetting
155 * the view pointer returned by this size.
158 HANDLE WINAPI
SHAllocShared(LPCVOID lpvData
, DWORD dwSize
, DWORD dwProcId
)
164 TRACE("(%p,%d,%d)\n", lpvData
, dwSize
, dwProcId
);
166 /* Create file mapping of the correct length */
167 hMap
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, FILE_MAP_READ
, 0,
168 dwSize
+ sizeof(dwSize
), NULL
);
172 /* Get a view in our process address space */
173 pMapped
= MapViewOfFile(hMap
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
177 /* Write size of data, followed by the data, to the view */
178 *((DWORD
*)pMapped
) = dwSize
;
180 memcpy((char *) pMapped
+ sizeof(dwSize
), lpvData
, dwSize
);
182 /* Release view. All further views mapped will be opaque */
183 UnmapViewOfFile(pMapped
);
184 hRet
= SHMapHandle(hMap
, GetCurrentProcessId(), dwProcId
,
185 FILE_MAP_ALL_ACCESS
, DUPLICATE_SAME_ACCESS
);
192 /*************************************************************************
195 * Get a pointer to a block of shared memory from a shared memory handle.
198 * hShared [I] Shared memory handle
199 * dwProcId [I] ID of process owning hShared
202 * Success: A pointer to the shared memory
206 PVOID WINAPI
SHLockShared(HANDLE hShared
, DWORD dwProcId
)
211 TRACE("(%p %d)\n", hShared
, dwProcId
);
213 /* Get handle to shared memory for current process */
214 hDup
= SHMapHandle(hShared
, dwProcId
, GetCurrentProcessId(), FILE_MAP_ALL_ACCESS
, 0);
217 pMapped
= MapViewOfFile(hDup
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
221 return (char *) pMapped
+ sizeof(DWORD
); /* Hide size */
225 /*************************************************************************
228 * Release a pointer to a block of shared memory.
231 * lpView [I] Shared memory pointer
238 BOOL WINAPI
SHUnlockShared(LPVOID lpView
)
240 TRACE("(%p)\n", lpView
);
241 return UnmapViewOfFile((char *) lpView
- sizeof(DWORD
)); /* Include size */
244 /*************************************************************************
247 * Destroy a block of sharable memory.
250 * hShared [I] Shared memory handle
251 * dwProcId [I] ID of process owning hShared
258 BOOL WINAPI
SHFreeShared(HANDLE hShared
, DWORD dwProcId
)
262 TRACE("(%p %d)\n", hShared
, dwProcId
);
264 /* Get a copy of the handle for our process, closing the source handle */
265 hClose
= SHMapHandle(hShared
, dwProcId
, GetCurrentProcessId(),
266 FILE_MAP_ALL_ACCESS
,DUPLICATE_CLOSE_SOURCE
);
267 /* Close local copy */
268 return CloseHandle(hClose
);
271 /*************************************************************************
274 * Create and register a clipboard enumerator for a web browser.
277 * lpBC [I] Binding context
278 * lpUnknown [I] An object exposing the IWebBrowserApp interface
282 * Failure: An HRESULT error code.
285 * The enumerator is stored as a property of the web browser. If it does not
286 * yet exist, it is created and set before being registered.
288 HRESULT WINAPI
RegisterDefaultAcceptHeaders(LPBC lpBC
, IUnknown
*lpUnknown
)
290 static const WCHAR szProperty
[] = { '{','D','0','F','C','A','4','2','0',
291 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
292 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
294 IEnumFORMATETC
* pIEnumFormatEtc
= NULL
;
297 IWebBrowserApp
* pBrowser
;
299 TRACE("(%p, %p)\n", lpBC
, lpUnknown
);
301 hr
= IUnknown_QueryService(lpUnknown
, &IID_IWebBrowserApp
, &IID_IWebBrowserApp
, (void**)&pBrowser
);
305 V_VT(&var
) = VT_EMPTY
;
307 /* The property we get is the browsers clipboard enumerator */
308 property
= SysAllocString(szProperty
);
309 hr
= IWebBrowserApp_GetProperty(pBrowser
, property
, &var
);
310 SysFreeString(property
);
311 if (FAILED(hr
)) goto exit
;
313 if (V_VT(&var
) == VT_EMPTY
)
315 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
316 char szKeyBuff
[128], szValueBuff
[128];
317 DWORD dwKeySize
, dwValueSize
, dwRet
= 0, dwCount
= 0, dwNumValues
, dwType
;
318 FORMATETC
* formatList
, *format
;
321 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
323 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\Current"
324 "Version\\Internet Settings\\Accepted Documents", &hDocs
))
330 /* Get count of values in key */
333 dwKeySize
= sizeof(szKeyBuff
);
334 dwRet
= RegEnumValueA(hDocs
,dwCount
,szKeyBuff
,&dwKeySize
,0,&dwType
,0,0);
338 dwNumValues
= dwCount
;
340 /* Note: dwCount = number of items + 1; The extra item is the end node */
341 format
= formatList
= HeapAlloc(GetProcessHeap(), 0, dwCount
* sizeof(FORMATETC
));
356 /* Register clipboard formats for the values and populate format list */
357 while(!dwRet
&& dwCount
< dwNumValues
)
359 dwKeySize
= sizeof(szKeyBuff
);
360 dwValueSize
= sizeof(szValueBuff
);
361 dwRet
= RegEnumValueA(hDocs
, dwCount
, szKeyBuff
, &dwKeySize
, 0, &dwType
,
362 (PBYTE
)szValueBuff
, &dwValueSize
);
365 HeapFree(GetProcessHeap(), 0, formatList
);
371 format
->cfFormat
= RegisterClipboardFormatA(szValueBuff
);
373 format
->dwAspect
= 1;
384 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
385 format
->cfFormat
= 0;
387 format
->dwAspect
= 1;
391 /* Create a clipboard enumerator */
392 hr
= CreateFormatEnumerator(dwNumValues
, formatList
, &pIEnumFormatEtc
);
393 HeapFree(GetProcessHeap(), 0, formatList
);
394 if (FAILED(hr
)) goto exit
;
396 /* Set our enumerator as the browsers property */
397 V_VT(&var
) = VT_UNKNOWN
;
398 V_UNKNOWN(&var
) = (IUnknown
*)pIEnumFormatEtc
;
400 property
= SysAllocString(szProperty
);
401 hr
= IWebBrowserApp_PutProperty(pBrowser
, property
, var
);
402 SysFreeString(property
);
405 IEnumFORMATETC_Release(pIEnumFormatEtc
);
410 if (V_VT(&var
) == VT_UNKNOWN
)
412 /* Our variant is holding the clipboard enumerator */
413 IUnknown
* pIUnknown
= V_UNKNOWN(&var
);
414 IEnumFORMATETC
* pClone
= NULL
;
416 TRACE("Retrieved IEnumFORMATETC property\n");
418 /* Get an IEnumFormatEtc interface from the variants value */
419 pIEnumFormatEtc
= NULL
;
420 hr
= IUnknown_QueryInterface(pIUnknown
, &IID_IEnumFORMATETC
, (void**)&pIEnumFormatEtc
);
421 if (hr
== S_OK
&& pIEnumFormatEtc
)
423 /* Clone and register the enumerator */
424 hr
= IEnumFORMATETC_Clone(pIEnumFormatEtc
, &pClone
);
425 if (hr
== S_OK
&& pClone
)
427 RegisterFormatEnumerator(lpBC
, pClone
, 0);
429 IEnumFORMATETC_Release(pClone
);
432 IUnknown_Release(pIUnknown
);
434 IUnknown_Release(V_UNKNOWN(&var
));
438 IWebBrowserApp_Release(pBrowser
);
442 /*************************************************************************
445 * Get Explorers "AcceptLanguage" setting.
448 * langbuf [O] Destination for language string
449 * buflen [I] Length of langbuf in characters
450 * [0] Success: used length of langbuf
453 * Success: S_OK. langbuf is set to the language string found.
454 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
455 * does not contain the setting.
456 * E_NOT_SUFFICIENT_BUFFER, If the buffer is not big enough
458 HRESULT WINAPI
GetAcceptLanguagesW( LPWSTR langbuf
, LPDWORD buflen
)
460 static const WCHAR szkeyW
[] = {
461 'S','o','f','t','w','a','r','e','\\',
462 'M','i','c','r','o','s','o','f','t','\\',
463 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
464 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
465 static const WCHAR valueW
[] = {
466 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
467 DWORD mystrlen
, mytype
;
474 TRACE("(%p, %p) *%p: %d\n", langbuf
, buflen
, buflen
, buflen
? *buflen
: -1);
476 if(!langbuf
|| !buflen
|| !*buflen
)
479 mystrlen
= (*buflen
> 20) ? *buflen
: 20 ;
480 len
= mystrlen
* sizeof(WCHAR
);
481 mystr
= HeapAlloc(GetProcessHeap(), 0, len
);
483 RegOpenKeyW(HKEY_CURRENT_USER
, szkeyW
, &mykey
);
484 lres
= RegQueryValueExW(mykey
, valueW
, 0, &mytype
, (PBYTE
)mystr
, &len
);
486 len
= lstrlenW(mystr
);
488 if (!lres
&& (*buflen
> len
)) {
489 lstrcpyW(langbuf
, mystr
);
491 HeapFree(GetProcessHeap(), 0, mystr
);
495 /* Did not find a value in the registry or the user buffer is too small */
496 mylcid
= GetUserDefaultLCID();
497 LcidToRfc1766W(mylcid
, mystr
, mystrlen
);
498 len
= lstrlenW(mystr
);
500 memcpy( langbuf
, mystr
, min(*buflen
, len
+1)*sizeof(WCHAR
) );
501 HeapFree(GetProcessHeap(), 0, mystr
);
509 return E_NOT_SUFFICIENT_BUFFER
;
512 /*************************************************************************
515 * Ascii version of GetAcceptLanguagesW.
517 HRESULT WINAPI
GetAcceptLanguagesA( LPSTR langbuf
, LPDWORD buflen
)
520 DWORD buflenW
, convlen
;
523 TRACE("(%p, %p) *%p: %d\n", langbuf
, buflen
, buflen
, buflen
? *buflen
: -1);
525 if(!langbuf
|| !buflen
|| !*buflen
) return E_FAIL
;
528 langbufW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * buflenW
);
529 retval
= GetAcceptLanguagesW(langbufW
, &buflenW
);
533 convlen
= WideCharToMultiByte(CP_ACP
, 0, langbufW
, -1, langbuf
, *buflen
, NULL
, NULL
);
534 convlen
--; /* do not count the terminating 0 */
536 else /* copy partial string anyway */
538 convlen
= WideCharToMultiByte(CP_ACP
, 0, langbufW
, *buflen
, langbuf
, *buflen
, NULL
, NULL
);
539 if (convlen
< *buflen
)
541 langbuf
[convlen
] = 0;
542 convlen
--; /* do not count the terminating 0 */
549 *buflen
= buflenW
? convlen
: 0;
551 HeapFree(GetProcessHeap(), 0, langbufW
);
555 /*************************************************************************
558 * Convert a GUID to a string.
561 * guid [I] GUID to convert
562 * lpszDest [O] Destination for string
563 * cchMax [I] Length of output buffer
566 * The length of the string created.
568 INT WINAPI
SHStringFromGUIDA(REFGUID guid
, LPSTR lpszDest
, INT cchMax
)
573 TRACE("(%s,%p,%d)\n", debugstr_guid(guid
), lpszDest
, cchMax
);
575 sprintf(xguid
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
576 guid
->Data1
, guid
->Data2
, guid
->Data3
,
577 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
578 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
580 iLen
= strlen(xguid
) + 1;
584 memcpy(lpszDest
, xguid
, iLen
);
588 /*************************************************************************
591 * Convert a GUID to a string.
594 * guid [I] GUID to convert
595 * str [O] Destination for string
596 * cmax [I] Length of output buffer
599 * The length of the string created.
601 INT WINAPI
SHStringFromGUIDW(REFGUID guid
, LPWSTR lpszDest
, INT cchMax
)
605 static const WCHAR wszFormat
[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
606 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
607 'X','%','0','2','X','%','0','2','X','}',0};
609 TRACE("(%s,%p,%d)\n", debugstr_guid(guid
), lpszDest
, cchMax
);
611 sprintfW(xguid
, wszFormat
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
612 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
613 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
615 iLen
= strlenW(xguid
) + 1;
619 memcpy(lpszDest
, xguid
, iLen
*sizeof(WCHAR
));
623 /*************************************************************************
626 * Determine if a Unicode character is a blank.
629 * wc [I] Character to check.
632 * TRUE, if wc is a blank,
636 BOOL WINAPI
IsCharBlankW(WCHAR wc
)
640 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_BLANK
);
643 /*************************************************************************
646 * Determine if a Unicode character is punctuation.
649 * wc [I] Character to check.
652 * TRUE, if wc is punctuation,
655 BOOL WINAPI
IsCharPunctW(WCHAR wc
)
659 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_PUNCT
);
662 /*************************************************************************
665 * Determine if a Unicode character is a control character.
668 * wc [I] Character to check.
671 * TRUE, if wc is a control character,
674 BOOL WINAPI
IsCharCntrlW(WCHAR wc
)
678 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_CNTRL
);
681 /*************************************************************************
684 * Determine if a Unicode character is a digit.
687 * wc [I] Character to check.
690 * TRUE, if wc is a digit,
693 BOOL WINAPI
IsCharDigitW(WCHAR wc
)
697 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_DIGIT
);
700 /*************************************************************************
703 * Determine if a Unicode character is a hex digit.
706 * wc [I] Character to check.
709 * TRUE, if wc is a hex digit,
712 BOOL WINAPI
IsCharXDigitW(WCHAR wc
)
716 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_XDIGIT
);
719 /*************************************************************************
723 BOOL WINAPI
GetStringType3ExW(LPWSTR src
, INT count
, LPWORD type
)
725 return GetStringTypeW(CT_CTYPE3
, src
, count
, type
);
728 /*************************************************************************
731 * Compare two Ascii strings up to a given length.
734 * lpszSrc [I] Source string
735 * lpszCmp [I] String to compare to lpszSrc
736 * len [I] Maximum length
739 * A number greater than, less than or equal to 0 depending on whether
740 * lpszSrc is greater than, less than or equal to lpszCmp.
742 DWORD WINAPI
StrCmpNCA(LPCSTR lpszSrc
, LPCSTR lpszCmp
, INT len
)
744 return StrCmpNA(lpszSrc
, lpszCmp
, len
);
747 /*************************************************************************
750 * Unicode version of StrCmpNCA.
752 DWORD WINAPI
StrCmpNCW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
, INT len
)
754 return StrCmpNW(lpszSrc
, lpszCmp
, len
);
757 /*************************************************************************
760 * Compare two Ascii strings up to a given length, ignoring case.
763 * lpszSrc [I] Source string
764 * lpszCmp [I] String to compare to lpszSrc
765 * len [I] Maximum length
768 * A number greater than, less than or equal to 0 depending on whether
769 * lpszSrc is greater than, less than or equal to lpszCmp.
771 DWORD WINAPI
StrCmpNICA(LPCSTR lpszSrc
, LPCSTR lpszCmp
, DWORD len
)
773 return StrCmpNIA(lpszSrc
, lpszCmp
, len
);
776 /*************************************************************************
779 * Unicode version of StrCmpNICA.
781 DWORD WINAPI
StrCmpNICW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
, DWORD len
)
783 return StrCmpNIW(lpszSrc
, lpszCmp
, len
);
786 /*************************************************************************
789 * Compare two Ascii strings.
792 * lpszSrc [I] Source string
793 * lpszCmp [I] String to compare to lpszSrc
796 * A number greater than, less than or equal to 0 depending on whether
797 * lpszSrc is greater than, less than or equal to lpszCmp.
799 DWORD WINAPI
StrCmpCA(LPCSTR lpszSrc
, LPCSTR lpszCmp
)
801 return lstrcmpA(lpszSrc
, lpszCmp
);
804 /*************************************************************************
807 * Unicode version of StrCmpCA.
809 DWORD WINAPI
StrCmpCW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
)
811 return lstrcmpW(lpszSrc
, lpszCmp
);
814 /*************************************************************************
817 * Compare two Ascii strings, ignoring case.
820 * lpszSrc [I] Source string
821 * lpszCmp [I] String to compare to lpszSrc
824 * A number greater than, less than or equal to 0 depending on whether
825 * lpszSrc is greater than, less than or equal to lpszCmp.
827 DWORD WINAPI
StrCmpICA(LPCSTR lpszSrc
, LPCSTR lpszCmp
)
829 return lstrcmpiA(lpszSrc
, lpszCmp
);
832 /*************************************************************************
835 * Unicode version of StrCmpICA.
837 DWORD WINAPI
StrCmpICW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
)
839 return lstrcmpiW(lpszSrc
, lpszCmp
);
842 /*************************************************************************
845 * Get an identification string for the OS and explorer.
848 * lpszDest [O] Destination for Id string
849 * dwDestLen [I] Length of lpszDest
852 * TRUE, If the string was created successfully
855 BOOL WINAPI
SHAboutInfoA(LPSTR lpszDest
, DWORD dwDestLen
)
859 TRACE("(%p,%d)\n", lpszDest
, dwDestLen
);
861 if (lpszDest
&& SHAboutInfoW(buff
, dwDestLen
))
863 WideCharToMultiByte(CP_ACP
, 0, buff
, -1, lpszDest
, dwDestLen
, NULL
, NULL
);
869 /*************************************************************************
872 * Unicode version of SHAboutInfoA.
874 BOOL WINAPI
SHAboutInfoW(LPWSTR lpszDest
, DWORD dwDestLen
)
876 static const WCHAR szIEKey
[] = { 'S','O','F','T','W','A','R','E','\\',
877 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
878 ' ','E','x','p','l','o','r','e','r','\0' };
879 static const WCHAR szWinNtKey
[] = { 'S','O','F','T','W','A','R','E','\\',
880 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
881 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
882 static const WCHAR szWinKey
[] = { 'S','O','F','T','W','A','R','E','\\',
883 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
884 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
885 static const WCHAR szRegKey
[] = { 'S','O','F','T','W','A','R','E','\\',
886 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
887 ' ','E','x','p','l','o','r','e','r','\\',
888 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
889 static const WCHAR szVersion
[] = { 'V','e','r','s','i','o','n','\0' };
890 static const WCHAR szCustomized
[] = { 'C','u','s','t','o','m','i','z','e','d',
891 'V','e','r','s','i','o','n','\0' };
892 static const WCHAR szOwner
[] = { 'R','e','g','i','s','t','e','r','e','d',
893 'O','w','n','e','r','\0' };
894 static const WCHAR szOrg
[] = { 'R','e','g','i','s','t','e','r','e','d',
895 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
896 static const WCHAR szProduct
[] = { 'P','r','o','d','u','c','t','I','d','\0' };
897 static const WCHAR szUpdate
[] = { 'I','E','A','K',
898 'U','p','d','a','t','e','U','r','l','\0' };
899 static const WCHAR szHelp
[] = { 'I','E','A','K',
900 'H','e','l','p','S','t','r','i','n','g','\0' };
905 TRACE("(%p,%d)\n", lpszDest
, dwDestLen
);
912 /* Try the NT key first, followed by 95/98 key */
913 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szWinNtKey
, 0, KEY_READ
, &hReg
) &&
914 RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szWinKey
, 0, KEY_READ
, &hReg
))
920 if (!SHGetValueW(HKEY_LOCAL_MACHINE
, szIEKey
, szVersion
, &dwType
, buff
, &dwLen
))
922 DWORD dwStrLen
= strlenW(buff
);
923 dwLen
= 30 - dwStrLen
;
924 SHGetValueW(HKEY_LOCAL_MACHINE
, szIEKey
,
925 szCustomized
, &dwType
, buff
+dwStrLen
, &dwLen
);
927 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
929 /* ~Registered Owner */
932 if (SHGetValueW(hReg
, szOwner
, 0, &dwType
, buff
+1, &dwLen
))
934 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
936 /* ~Registered Organization */
938 if (SHGetValueW(hReg
, szOrg
, 0, &dwType
, buff
+1, &dwLen
))
940 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
942 /* FIXME: Not sure where this number comes from */
946 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
950 if (SHGetValueW(HKEY_LOCAL_MACHINE
, szRegKey
, szProduct
, &dwType
, buff
+1, &dwLen
))
952 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
956 if(SHGetValueW(HKEY_LOCAL_MACHINE
, szWinKey
, szUpdate
, &dwType
, buff
+1, &dwLen
))
958 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
960 /* ~IE Help String */
962 if(SHGetValueW(hReg
, szHelp
, 0, &dwType
, buff
+1, &dwLen
))
964 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
970 /*************************************************************************
973 * Call IOleCommandTarget_QueryStatus() on an object.
976 * lpUnknown [I] Object supporting the IOleCommandTarget interface
977 * pguidCmdGroup [I] GUID for the command group
979 * prgCmds [O] Commands
980 * pCmdText [O] Command text
984 * Failure: E_FAIL, if lpUnknown is NULL.
985 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
986 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
988 HRESULT WINAPI
IUnknown_QueryStatus(IUnknown
* lpUnknown
, REFGUID pguidCmdGroup
,
989 ULONG cCmds
, OLECMD
*prgCmds
, OLECMDTEXT
* pCmdText
)
991 HRESULT hRet
= E_FAIL
;
993 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown
, pguidCmdGroup
, cCmds
, prgCmds
, pCmdText
);
997 IOleCommandTarget
* lpOle
;
999 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleCommandTarget
,
1002 if (SUCCEEDED(hRet
) && lpOle
)
1004 hRet
= IOleCommandTarget_QueryStatus(lpOle
, pguidCmdGroup
, cCmds
,
1006 IOleCommandTarget_Release(lpOle
);
1012 /*************************************************************************
1015 * Call IOleCommandTarget_Exec() on an object.
1018 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1019 * pguidCmdGroup [I] GUID for the command group
1023 * Failure: E_FAIL, if lpUnknown is NULL.
1024 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1025 * Otherwise, an error code from IOleCommandTarget_Exec().
1027 HRESULT WINAPI
IUnknown_Exec(IUnknown
* lpUnknown
, REFGUID pguidCmdGroup
,
1028 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
* pvaIn
,
1031 HRESULT hRet
= E_FAIL
;
1033 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown
, pguidCmdGroup
, nCmdID
,
1034 nCmdexecopt
, pvaIn
, pvaOut
);
1038 IOleCommandTarget
* lpOle
;
1040 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleCommandTarget
,
1042 if (SUCCEEDED(hRet
) && lpOle
)
1044 hRet
= IOleCommandTarget_Exec(lpOle
, pguidCmdGroup
, nCmdID
,
1045 nCmdexecopt
, pvaIn
, pvaOut
);
1046 IOleCommandTarget_Release(lpOle
);
1052 /*************************************************************************
1055 * Retrieve, modify, and re-set a value from a window.
1058 * hWnd [I] Window to get value from
1059 * offset [I] Offset of value
1060 * mask [I] Mask for flags
1061 * flags [I] Bits to set in window value
1064 * The new value as it was set, or 0 if any parameter is invalid.
1067 * Only bits specified in mask are affected - set if present in flags and
1070 LONG WINAPI
SHSetWindowBits(HWND hwnd
, INT offset
, UINT mask
, UINT flags
)
1072 LONG ret
= GetWindowLongW(hwnd
, offset
);
1073 LONG new_flags
= (flags
& mask
) | (ret
& ~mask
);
1075 TRACE("%p %d %x %x\n", hwnd
, offset
, mask
, flags
);
1077 if (new_flags
!= ret
)
1078 ret
= SetWindowLongW(hwnd
, offset
, new_flags
);
1082 /*************************************************************************
1085 * Change a window's parent.
1088 * hWnd [I] Window to change parent of
1089 * hWndParent [I] New parent window
1092 * The old parent of hWnd.
1095 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1096 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1098 HWND WINAPI
SHSetParentHwnd(HWND hWnd
, HWND hWndParent
)
1100 TRACE("%p, %p\n", hWnd
, hWndParent
);
1102 if(GetParent(hWnd
) == hWndParent
)
1106 SHSetWindowBits(hWnd
, GWL_STYLE
, WS_CHILD
| WS_POPUP
, WS_CHILD
);
1108 SHSetWindowBits(hWnd
, GWL_STYLE
, WS_CHILD
| WS_POPUP
, WS_POPUP
);
1110 return hWndParent
? SetParent(hWnd
, hWndParent
) : NULL
;
1113 /*************************************************************************
1116 * Locate and advise a connection point in an IConnectionPointContainer object.
1119 * lpUnkSink [I] Sink for the connection point advise call
1120 * riid [I] REFIID of connection point to advise
1121 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1122 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1123 * lpCookie [O] Pointer to connection point cookie
1124 * lppCP [O] Destination for the IConnectionPoint found
1127 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1128 * that was advised. The caller is responsible for releasing it.
1129 * Failure: E_FAIL, if any arguments are invalid.
1130 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1131 * Or an HRESULT error code if any call fails.
1133 HRESULT WINAPI
ConnectToConnectionPoint(IUnknown
* lpUnkSink
, REFIID riid
, BOOL fConnect
,
1134 IUnknown
* lpUnknown
, LPDWORD lpCookie
,
1135 IConnectionPoint
**lppCP
)
1138 IConnectionPointContainer
* lpContainer
;
1139 IConnectionPoint
*lpCP
;
1141 if(!lpUnknown
|| (fConnect
&& !lpUnkSink
))
1147 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IConnectionPointContainer
,
1148 (void**)&lpContainer
);
1149 if (SUCCEEDED(hRet
))
1151 hRet
= IConnectionPointContainer_FindConnectionPoint(lpContainer
, riid
, &lpCP
);
1153 if (SUCCEEDED(hRet
))
1156 hRet
= IConnectionPoint_Unadvise(lpCP
, *lpCookie
);
1158 hRet
= IConnectionPoint_Advise(lpCP
, lpUnkSink
, lpCookie
);
1163 if (lppCP
&& SUCCEEDED(hRet
))
1164 *lppCP
= lpCP
; /* Caller keeps the interface */
1166 IConnectionPoint_Release(lpCP
); /* Release it */
1169 IConnectionPointContainer_Release(lpContainer
);
1174 /*************************************************************************
1177 * Release an interface and zero a supplied pointer.
1180 * lpUnknown [I] Object to release
1185 void WINAPI
IUnknown_AtomicRelease(IUnknown
** lpUnknown
)
1187 TRACE("(%p)\n", lpUnknown
);
1189 if(!lpUnknown
|| !*lpUnknown
) return;
1191 TRACE("doing Release\n");
1193 IUnknown_Release(*lpUnknown
);
1197 /*************************************************************************
1200 * Skip '//' if present in a string.
1203 * lpszSrc [I] String to check for '//'
1206 * Success: The next character after the '//' or the string if not present
1207 * Failure: NULL, if lpszStr is NULL.
1209 LPCSTR WINAPI
PathSkipLeadingSlashesA(LPCSTR lpszSrc
)
1211 if (lpszSrc
&& lpszSrc
[0] == '/' && lpszSrc
[1] == '/')
1216 /*************************************************************************
1219 * Check if two interfaces come from the same object.
1222 * lpInt1 [I] Interface to check against lpInt2.
1223 * lpInt2 [I] Interface to check against lpInt1.
1226 * TRUE, If the interfaces come from the same object.
1229 BOOL WINAPI
SHIsSameObject(IUnknown
* lpInt1
, IUnknown
* lpInt2
)
1231 IUnknown
*lpUnknown1
, *lpUnknown2
;
1234 TRACE("(%p %p)\n", lpInt1
, lpInt2
);
1236 if (!lpInt1
|| !lpInt2
)
1239 if (lpInt1
== lpInt2
)
1242 if (IUnknown_QueryInterface(lpInt1
, &IID_IUnknown
, (void**)&lpUnknown1
) != S_OK
)
1245 if (IUnknown_QueryInterface(lpInt2
, &IID_IUnknown
, (void**)&lpUnknown2
) != S_OK
)
1247 IUnknown_Release(lpUnknown1
);
1251 ret
= lpUnknown1
== lpUnknown2
;
1253 IUnknown_Release(lpUnknown1
);
1254 IUnknown_Release(lpUnknown2
);
1259 /*************************************************************************
1262 * Get the window handle of an object.
1265 * lpUnknown [I] Object to get the window handle of
1266 * lphWnd [O] Destination for window handle
1269 * Success: S_OK. lphWnd contains the objects window handle.
1270 * Failure: An HRESULT error code.
1273 * lpUnknown is expected to support one of the following interfaces:
1274 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1276 HRESULT WINAPI
IUnknown_GetWindow(IUnknown
*lpUnknown
, HWND
*lphWnd
)
1279 HRESULT hRet
= E_FAIL
;
1281 TRACE("(%p,%p)\n", lpUnknown
, lphWnd
);
1286 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleWindow
, (void**)&lpOle
);
1290 hRet
= IUnknown_QueryInterface(lpUnknown
,&IID_IShellView
, (void**)&lpOle
);
1294 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInternetSecurityMgrSite
,
1299 if (SUCCEEDED(hRet
))
1301 /* Laziness here - Since GetWindow() is the first method for the above 3
1302 * interfaces, we use the same call for them all.
1304 hRet
= IOleWindow_GetWindow((IOleWindow
*)lpOle
, lphWnd
);
1305 IUnknown_Release(lpOle
);
1307 TRACE("Returning HWND=%p\n", *lphWnd
);
1313 /*************************************************************************
1316 * Call a SetOwner method of IShellService from specified object.
1319 * iface [I] Object that supports IShellService
1320 * pUnk [I] Argument for the SetOwner call
1323 * Corresponding return value from last call or E_FAIL for null input
1325 HRESULT WINAPI
IUnknown_SetOwner(IUnknown
*iface
, IUnknown
*pUnk
)
1327 IShellService
*service
;
1330 TRACE("(%p, %p)\n", iface
, pUnk
);
1332 if (!iface
) return E_FAIL
;
1334 hr
= IUnknown_QueryInterface(iface
, &IID_IShellService
, (void**)&service
);
1337 hr
= IShellService_SetOwner(service
, pUnk
);
1338 IShellService_Release(service
);
1344 /*************************************************************************
1347 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1351 HRESULT WINAPI
IUnknown_SetSite(
1352 IUnknown
*obj
, /* [in] OLE object */
1353 IUnknown
*site
) /* [in] Site interface */
1356 IObjectWithSite
*iobjwithsite
;
1357 IInternetSecurityManager
*isecmgr
;
1359 if (!obj
) return E_FAIL
;
1361 hr
= IUnknown_QueryInterface(obj
, &IID_IObjectWithSite
, (LPVOID
*)&iobjwithsite
);
1362 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr
, iobjwithsite
);
1365 hr
= IObjectWithSite_SetSite(iobjwithsite
, site
);
1366 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr
);
1367 IObjectWithSite_Release(iobjwithsite
);
1371 hr
= IUnknown_QueryInterface(obj
, &IID_IInternetSecurityManager
, (LPVOID
*)&isecmgr
);
1372 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr
, isecmgr
);
1373 if (FAILED(hr
)) return hr
;
1375 hr
= IInternetSecurityManager_SetSecuritySite(isecmgr
, (IInternetSecurityMgrSite
*)site
);
1376 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr
);
1377 IInternetSecurityManager_Release(isecmgr
);
1382 /*************************************************************************
1385 * Call IPersist_GetClassID() on an object.
1388 * lpUnknown [I] Object supporting the IPersist interface
1389 * lpClassId [O] Destination for Class Id
1392 * Success: S_OK. lpClassId contains the Class Id requested.
1393 * Failure: E_FAIL, If lpUnknown is NULL,
1394 * E_NOINTERFACE If lpUnknown does not support IPersist,
1395 * Or an HRESULT error code.
1397 HRESULT WINAPI
IUnknown_GetClassID(IUnknown
*lpUnknown
, CLSID
* lpClassId
)
1399 IPersist
* lpPersist
;
1400 HRESULT hRet
= E_FAIL
;
1402 TRACE("(%p,%s)\n", lpUnknown
, debugstr_guid(lpClassId
));
1406 hRet
= IUnknown_QueryInterface(lpUnknown
,&IID_IPersist
,(void**)&lpPersist
);
1407 if (SUCCEEDED(hRet
))
1409 IPersist_GetClassID(lpPersist
, lpClassId
);
1410 IPersist_Release(lpPersist
);
1416 /*************************************************************************
1419 * Retrieve a Service Interface from an object.
1422 * lpUnknown [I] Object to get an IServiceProvider interface from
1423 * sid [I] Service ID for IServiceProvider_QueryService() call
1424 * riid [I] Function requested for QueryService call
1425 * lppOut [O] Destination for the service interface pointer
1428 * Success: S_OK. lppOut contains an object providing the requested service
1429 * Failure: An HRESULT error code
1432 * lpUnknown is expected to support the IServiceProvider interface.
1434 HRESULT WINAPI
IUnknown_QueryService(IUnknown
* lpUnknown
, REFGUID sid
, REFIID riid
,
1437 IServiceProvider
* pService
= NULL
;
1448 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IServiceProvider
,
1449 (LPVOID
*)&pService
);
1451 if (hRet
== S_OK
&& pService
)
1453 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService
);
1455 /* Get a Service interface from the object */
1456 hRet
= IServiceProvider_QueryService(pService
, sid
, riid
, lppOut
);
1458 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService
, *lppOut
);
1460 IServiceProvider_Release(pService
);
1465 /*************************************************************************
1468 * Calls IOleCommandTarget::Exec() for specified service object.
1471 * lpUnknown [I] Object to get an IServiceProvider interface from
1472 * service [I] Service ID for IServiceProvider_QueryService() call
1473 * group [I] Group ID for IOleCommandTarget::Exec() call
1474 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1475 * cmdOpt [I] Options flags for command
1476 * pIn [I] Input arguments for command
1477 * pOut [O] Output arguments for command
1480 * Success: S_OK. lppOut contains an object providing the requested service
1481 * Failure: An HRESULT error code
1484 * lpUnknown is expected to support the IServiceProvider interface.
1486 HRESULT WINAPI
IUnknown_QueryServiceExec(IUnknown
*lpUnknown
, REFIID service
,
1487 const GUID
*group
, DWORD cmdId
, DWORD cmdOpt
, VARIANT
*pIn
, VARIANT
*pOut
)
1489 IOleCommandTarget
*target
;
1492 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown
, debugstr_guid(service
),
1493 debugstr_guid(group
), cmdId
, cmdOpt
, pIn
, pOut
);
1495 hr
= IUnknown_QueryService(lpUnknown
, service
, &IID_IOleCommandTarget
, (void**)&target
);
1498 hr
= IOleCommandTarget_Exec(target
, group
, cmdId
, cmdOpt
, pIn
, pOut
);
1499 IOleCommandTarget_Release(target
);
1502 TRACE("<-- hr=0x%08x\n", hr
);
1507 /*************************************************************************
1510 * Calls IProfferService methods to proffer/revoke specified service.
1513 * lpUnknown [I] Object to get an IServiceProvider interface from
1514 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1515 * pService [I] Service to proffer. If NULL ::Revoke is called
1516 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1519 * Success: S_OK. IProffer method returns S_OK
1520 * Failure: An HRESULT error code
1523 * lpUnknown is expected to support the IServiceProvider interface.
1525 HRESULT WINAPI
IUnknown_ProfferService(IUnknown
*lpUnknown
, REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
1527 IProfferService
*proffer
;
1530 TRACE("%p %s %p %p\n", lpUnknown
, debugstr_guid(service
), pService
, pCookie
);
1532 hr
= IUnknown_QueryService(lpUnknown
, &IID_IProfferService
, &IID_IProfferService
, (void**)&proffer
);
1536 hr
= IProfferService_ProfferService(proffer
, service
, pService
, pCookie
);
1539 hr
= IProfferService_RevokeService(proffer
, *pCookie
);
1543 IProfferService_Release(proffer
);
1549 /*************************************************************************
1552 * Call an object's UIActivateIO method.
1555 * unknown [I] Object to call the UIActivateIO method on
1556 * activate [I] Parameter for UIActivateIO call
1557 * msg [I] Parameter for UIActivateIO call
1560 * Success: Value of UI_ActivateIO call
1561 * Failure: An HRESULT error code
1564 * unknown is expected to support the IInputObject interface.
1566 HRESULT WINAPI
IUnknown_UIActivateIO(IUnknown
*unknown
, BOOL activate
, LPMSG msg
)
1568 IInputObject
* object
= NULL
;
1574 /* Get an IInputObject interface from the object */
1575 ret
= IUnknown_QueryInterface(unknown
, &IID_IInputObject
, (LPVOID
*) &object
);
1579 ret
= IInputObject_UIActivateIO(object
, activate
, msg
);
1580 IInputObject_Release(object
);
1586 /*************************************************************************
1589 * Loads a popup menu.
1592 * hInst [I] Instance handle
1593 * szName [I] Menu name
1599 BOOL WINAPI
SHLoadMenuPopup(HINSTANCE hInst
, LPCWSTR szName
)
1603 TRACE("%p %s\n", hInst
, debugstr_w(szName
));
1605 if ((hMenu
= LoadMenuW(hInst
, szName
)))
1607 if (GetSubMenu(hMenu
, 0))
1608 RemoveMenu(hMenu
, 0, MF_BYPOSITION
);
1616 typedef struct _enumWndData
1621 LRESULT (WINAPI
*pfnPost
)(HWND
,UINT
,WPARAM
,LPARAM
);
1624 /* Callback for SHLWAPI_178 */
1625 static BOOL CALLBACK
SHLWAPI_EnumChildProc(HWND hWnd
, LPARAM lParam
)
1627 enumWndData
*data
= (enumWndData
*)lParam
;
1629 TRACE("(%p,%p)\n", hWnd
, data
);
1630 data
->pfnPost(hWnd
, data
->uiMsgId
, data
->wParam
, data
->lParam
);
1634 /*************************************************************************
1637 * Send or post a message to every child of a window.
1640 * hWnd [I] Window whose children will get the messages
1641 * uiMsgId [I] Message Id
1642 * wParam [I] WPARAM of message
1643 * lParam [I] LPARAM of message
1644 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1650 * The appropriate ASCII or Unicode function is called for the window.
1652 void WINAPI
SHPropagateMessage(HWND hWnd
, UINT uiMsgId
, WPARAM wParam
, LPARAM lParam
, BOOL bSend
)
1656 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd
, uiMsgId
, wParam
, lParam
, bSend
);
1660 data
.uiMsgId
= uiMsgId
;
1661 data
.wParam
= wParam
;
1662 data
.lParam
= lParam
;
1665 data
.pfnPost
= IsWindowUnicode(hWnd
) ? (void*)SendMessageW
: (void*)SendMessageA
;
1667 data
.pfnPost
= IsWindowUnicode(hWnd
) ? (void*)PostMessageW
: (void*)PostMessageA
;
1669 EnumChildWindows(hWnd
, SHLWAPI_EnumChildProc
, (LPARAM
)&data
);
1673 /*************************************************************************
1676 * Remove all sub-menus from a menu.
1679 * hMenu [I] Menu to remove sub-menus from
1682 * Success: 0. All sub-menus under hMenu are removed
1683 * Failure: -1, if any parameter is invalid
1685 DWORD WINAPI
SHRemoveAllSubMenus(HMENU hMenu
)
1687 int iItemCount
= GetMenuItemCount(hMenu
) - 1;
1689 TRACE("%p\n", hMenu
);
1691 while (iItemCount
>= 0)
1693 HMENU hSubMenu
= GetSubMenu(hMenu
, iItemCount
);
1695 RemoveMenu(hMenu
, iItemCount
, MF_BYPOSITION
);
1701 /*************************************************************************
1704 * Enable or disable a menu item.
1707 * hMenu [I] Menu holding menu item
1708 * uID [I] ID of menu item to enable/disable
1709 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1712 * The return code from EnableMenuItem.
1714 UINT WINAPI
SHEnableMenuItem(HMENU hMenu
, UINT wItemID
, BOOL bEnable
)
1716 TRACE("%p, %u, %d\n", hMenu
, wItemID
, bEnable
);
1717 return EnableMenuItem(hMenu
, wItemID
, bEnable
? MF_ENABLED
: MF_GRAYED
);
1720 /*************************************************************************
1723 * Check or uncheck a menu item.
1726 * hMenu [I] Menu holding menu item
1727 * uID [I] ID of menu item to check/uncheck
1728 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1731 * The return code from CheckMenuItem.
1733 DWORD WINAPI
SHCheckMenuItem(HMENU hMenu
, UINT uID
, BOOL bCheck
)
1735 TRACE("%p, %u, %d\n", hMenu
, uID
, bCheck
);
1736 return CheckMenuItem(hMenu
, uID
, bCheck
? MF_CHECKED
: MF_UNCHECKED
);
1739 /*************************************************************************
1742 * Register a window class if it isn't already.
1745 * lpWndClass [I] Window class to register
1748 * The result of the RegisterClassA call.
1750 DWORD WINAPI
SHRegisterClassA(WNDCLASSA
*wndclass
)
1753 if (GetClassInfoA(wndclass
->hInstance
, wndclass
->lpszClassName
, &wca
))
1755 return (DWORD
)RegisterClassA(wndclass
);
1758 /*************************************************************************
1761 BOOL WINAPI
SHSimulateDrop(IDropTarget
*pDrop
, IDataObject
*pDataObj
,
1762 DWORD grfKeyState
, PPOINTL lpPt
, DWORD
* pdwEffect
)
1764 DWORD dwEffect
= DROPEFFECT_LINK
| DROPEFFECT_MOVE
| DROPEFFECT_COPY
;
1765 POINTL pt
= { 0, 0 };
1767 TRACE("%p %p 0x%08x %p %p\n", pDrop
, pDataObj
, grfKeyState
, lpPt
, pdwEffect
);
1773 pdwEffect
= &dwEffect
;
1775 IDropTarget_DragEnter(pDrop
, pDataObj
, grfKeyState
, *lpPt
, pdwEffect
);
1777 if (*pdwEffect
!= DROPEFFECT_NONE
)
1778 return IDropTarget_Drop(pDrop
, pDataObj
, grfKeyState
, *lpPt
, pdwEffect
);
1780 IDropTarget_DragLeave(pDrop
);
1784 /*************************************************************************
1787 * Call IPersistPropertyBag_Load() on an object.
1790 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1791 * lpPropBag [O] Destination for loaded IPropertyBag
1795 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1797 DWORD WINAPI
SHLoadFromPropertyBag(IUnknown
*lpUnknown
, IPropertyBag
* lpPropBag
)
1799 IPersistPropertyBag
* lpPPBag
;
1800 HRESULT hRet
= E_FAIL
;
1802 TRACE("(%p,%p)\n", lpUnknown
, lpPropBag
);
1806 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IPersistPropertyBag
,
1808 if (SUCCEEDED(hRet
) && lpPPBag
)
1810 hRet
= IPersistPropertyBag_Load(lpPPBag
, lpPropBag
, NULL
);
1811 IPersistPropertyBag_Release(lpPPBag
);
1817 /*************************************************************************
1820 * Call IOleControlSite_TranslateAccelerator() on an object.
1823 * lpUnknown [I] Object supporting the IOleControlSite interface.
1824 * lpMsg [I] Key message to be processed.
1825 * dwModifiers [I] Flags containing the state of the modifier keys.
1829 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1831 HRESULT WINAPI
IUnknown_TranslateAcceleratorOCS(IUnknown
*lpUnknown
, LPMSG lpMsg
, DWORD dwModifiers
)
1833 IOleControlSite
* lpCSite
= NULL
;
1834 HRESULT hRet
= E_INVALIDARG
;
1836 TRACE("(%p,%p,0x%08x)\n", lpUnknown
, lpMsg
, dwModifiers
);
1839 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleControlSite
,
1841 if (SUCCEEDED(hRet
) && lpCSite
)
1843 hRet
= IOleControlSite_TranslateAccelerator(lpCSite
, lpMsg
, dwModifiers
);
1844 IOleControlSite_Release(lpCSite
);
1851 /*************************************************************************
1854 * Call IOleControlSite_OnFocus() on an object.
1857 * lpUnknown [I] Object supporting the IOleControlSite interface.
1858 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1862 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1864 HRESULT WINAPI
IUnknown_OnFocusOCS(IUnknown
*lpUnknown
, BOOL fGotFocus
)
1866 IOleControlSite
* lpCSite
= NULL
;
1867 HRESULT hRet
= E_FAIL
;
1869 TRACE("(%p, %d)\n", lpUnknown
, fGotFocus
);
1872 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleControlSite
,
1874 if (SUCCEEDED(hRet
) && lpCSite
)
1876 hRet
= IOleControlSite_OnFocus(lpCSite
, fGotFocus
);
1877 IOleControlSite_Release(lpCSite
);
1883 /*************************************************************************
1886 HRESULT WINAPI
IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown
, PVOID lpArg1
,
1887 PVOID lpArg2
, PVOID lpArg3
, PVOID lpArg4
)
1889 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1890 static const DWORD service_id
[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1891 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1892 static const DWORD function_id
[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1893 HRESULT hRet
= E_INVALIDARG
;
1894 LPUNKNOWN lpUnkInner
= NULL
; /* FIXME: Real type is unknown */
1896 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown
, lpArg1
, lpArg2
, lpArg3
, lpArg4
);
1898 if (lpUnknown
&& lpArg4
)
1900 hRet
= IUnknown_QueryService(lpUnknown
, (REFGUID
)service_id
,
1901 (REFGUID
)function_id
, (void**)&lpUnkInner
);
1903 if (SUCCEEDED(hRet
) && lpUnkInner
)
1905 /* FIXME: The type of service object requested is unknown, however
1906 * testing shows that its first method is called with 4 parameters.
1907 * Fake this by using IParseDisplayName_ParseDisplayName since the
1908 * signature and position in the vtable matches our unknown object type.
1910 hRet
= IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME
)lpUnkInner
,
1911 lpArg1
, lpArg2
, lpArg3
, lpArg4
);
1912 IUnknown_Release(lpUnkInner
);
1918 /*************************************************************************
1921 * Get a sub-menu from a menu item.
1924 * hMenu [I] Menu to get sub-menu from
1925 * uID [I] ID of menu item containing sub-menu
1928 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1930 HMENU WINAPI
SHGetMenuFromID(HMENU hMenu
, UINT uID
)
1934 TRACE("(%p,%u)\n", hMenu
, uID
);
1936 mi
.cbSize
= sizeof(mi
);
1937 mi
.fMask
= MIIM_SUBMENU
;
1939 if (!GetMenuItemInfoW(hMenu
, uID
, FALSE
, &mi
))
1945 /*************************************************************************
1948 * Get the color depth of the primary display.
1954 * The color depth of the primary display.
1956 DWORD WINAPI
SHGetCurColorRes(void)
1964 ret
= GetDeviceCaps(hdc
, BITSPIXEL
) * GetDeviceCaps(hdc
, PLANES
);
1969 /*************************************************************************
1972 * Wait for a message to arrive, with a timeout.
1975 * hand [I] Handle to query
1976 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1979 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1980 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1981 * message is available.
1983 DWORD WINAPI
SHWaitForSendMessageThread(HANDLE hand
, DWORD dwTimeout
)
1985 DWORD dwEndTicks
= GetTickCount() + dwTimeout
;
1988 while ((dwRet
= MsgWaitForMultipleObjectsEx(1, &hand
, dwTimeout
, QS_SENDMESSAGE
, 0)) == 1)
1992 PeekMessageW(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
1994 if (dwTimeout
!= INFINITE
)
1996 if ((int)(dwTimeout
= dwEndTicks
- GetTickCount()) <= 0)
1997 return WAIT_TIMEOUT
;
2004 /*************************************************************************
2007 * Determine if a shell folder can be expanded.
2010 * lpFolder [I] Parent folder containing the object to test.
2011 * pidl [I] Id of the object to test.
2014 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2015 * Failure: E_INVALIDARG, if any argument is invalid.
2018 * If the object to be tested does not expose the IQueryInfo() interface it
2019 * will not be identified as an expandable folder.
2021 HRESULT WINAPI
SHIsExpandableFolder(LPSHELLFOLDER lpFolder
, LPCITEMIDLIST pidl
)
2023 HRESULT hRet
= E_INVALIDARG
;
2026 if (lpFolder
&& pidl
)
2028 hRet
= IShellFolder_GetUIObjectOf(lpFolder
, NULL
, 1, &pidl
, &IID_IQueryInfo
,
2029 NULL
, (void**)&lpInfo
);
2031 hRet
= S_FALSE
; /* Doesn't expose IQueryInfo */
2036 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2037 * currently used". Really? You wouldn't be holding out on me would you?
2039 hRet
= IQueryInfo_GetInfoFlags(lpInfo
, &dwFlags
);
2041 if (SUCCEEDED(hRet
))
2043 /* 0x2 is an undocumented flag apparently indicating expandability */
2044 hRet
= dwFlags
& 0x2 ? S_OK
: S_FALSE
;
2047 IQueryInfo_Release(lpInfo
);
2053 /*************************************************************************
2056 * Blank out a region of text by drawing the background only.
2059 * hDC [I] Device context to draw in
2060 * pRect [I] Area to draw in
2061 * cRef [I] Color to draw in
2066 DWORD WINAPI
SHFillRectClr(HDC hDC
, LPCRECT pRect
, COLORREF cRef
)
2068 COLORREF cOldColor
= SetBkColor(hDC
, cRef
);
2069 ExtTextOutA(hDC
, 0, 0, ETO_OPAQUE
, pRect
, 0, 0, 0);
2070 SetBkColor(hDC
, cOldColor
);
2074 /*************************************************************************
2077 * Return the value associated with a key in a map.
2080 * lpKeys [I] A list of keys of length iLen
2081 * lpValues [I] A list of values associated with lpKeys, of length iLen
2082 * iLen [I] Length of both lpKeys and lpValues
2083 * iKey [I] The key value to look up in lpKeys
2086 * The value in lpValues associated with iKey, or -1 if iKey is not
2090 * - If two elements in the map share the same key, this function returns
2091 * the value closest to the start of the map
2092 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2094 int WINAPI
SHSearchMapInt(const int *lpKeys
, const int *lpValues
, int iLen
, int iKey
)
2096 if (lpKeys
&& lpValues
)
2102 if (lpKeys
[i
] == iKey
)
2103 return lpValues
[i
]; /* Found */
2107 return -1; /* Not found */
2111 /*************************************************************************
2114 * Copy an interface pointer
2117 * lppDest [O] Destination for copy
2118 * lpUnknown [I] Source for copy
2123 VOID WINAPI
IUnknown_Set(IUnknown
**lppDest
, IUnknown
*lpUnknown
)
2125 TRACE("(%p,%p)\n", lppDest
, lpUnknown
);
2127 IUnknown_AtomicRelease(lppDest
);
2131 IUnknown_AddRef(lpUnknown
);
2132 *lppDest
= lpUnknown
;
2136 /*************************************************************************
2140 HRESULT WINAPI
MayQSForward(IUnknown
* lpUnknown
, PVOID lpReserved
,
2141 REFGUID riidCmdGrp
, ULONG cCmds
,
2142 OLECMD
*prgCmds
, OLECMDTEXT
* pCmdText
)
2144 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2145 lpUnknown
, lpReserved
, riidCmdGrp
, cCmds
, prgCmds
, pCmdText
);
2147 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2148 return DRAGDROP_E_NOTREGISTERED
;
2151 /*************************************************************************
2155 HRESULT WINAPI
MayExecForward(IUnknown
* lpUnknown
, INT iUnk
, REFGUID pguidCmdGroup
,
2156 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
* pvaIn
,
2159 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown
, iUnk
, pguidCmdGroup
,
2160 nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2161 return DRAGDROP_E_NOTREGISTERED
;
2164 /*************************************************************************
2168 HRESULT WINAPI
IsQSForward(REFGUID pguidCmdGroup
,ULONG cCmds
, OLECMD
*prgCmds
)
2170 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup
, cCmds
, prgCmds
);
2171 return DRAGDROP_E_NOTREGISTERED
;
2174 /*************************************************************************
2177 * Determine if a window is not a child of another window.
2180 * hParent [I] Suspected parent window
2181 * hChild [I] Suspected child window
2184 * TRUE: If hChild is a child window of hParent
2185 * FALSE: If hChild is not a child window of hParent, or they are equal
2187 BOOL WINAPI
SHIsChildOrSelf(HWND hParent
, HWND hChild
)
2189 TRACE("(%p,%p)\n", hParent
, hChild
);
2191 if (!hParent
|| !hChild
)
2193 else if(hParent
== hChild
)
2195 return !IsChild(hParent
, hChild
);
2198 /*************************************************************************
2199 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2204 DWORD num_items
; /* Number of elements inserted */
2205 void *mem
; /* Ptr to array */
2206 DWORD blocks_alloced
; /* Number of elements allocated */
2207 BYTE inc
; /* Number of elements to grow by when we need to expand */
2208 BYTE block_size
; /* Size in bytes of an element */
2209 BYTE flags
; /* Flags */
2212 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2214 /*************************************************************************
2217 * Initialize an FDSA array.
2219 BOOL WINAPI
FDSA_Initialize(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
2222 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size
, inc
, info
, mem
, init_blocks
);
2228 memset(mem
, 0, block_size
* init_blocks
);
2230 info
->num_items
= 0;
2233 info
->blocks_alloced
= init_blocks
;
2234 info
->block_size
= block_size
;
2240 /*************************************************************************
2243 * Destroy an FDSA array
2245 BOOL WINAPI
FDSA_Destroy(FDSA_info
*info
)
2247 TRACE("(%p)\n", info
);
2249 if(info
->flags
& FDSA_FLAG_INTERNAL_ALLOC
)
2251 HeapFree(GetProcessHeap(), 0, info
->mem
);
2258 /*************************************************************************
2261 * Insert element into an FDSA array
2263 DWORD WINAPI
FDSA_InsertItem(FDSA_info
*info
, DWORD where
, const void *block
)
2265 TRACE("(%p 0x%08x %p)\n", info
, where
, block
);
2266 if(where
> info
->num_items
)
2267 where
= info
->num_items
;
2269 if(info
->num_items
>= info
->blocks_alloced
)
2271 DWORD size
= (info
->blocks_alloced
+ info
->inc
) * info
->block_size
;
2272 if(info
->flags
& 0x1)
2273 info
->mem
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, info
->mem
, size
);
2276 void *old_mem
= info
->mem
;
2277 info
->mem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
2278 memcpy(info
->mem
, old_mem
, info
->blocks_alloced
* info
->block_size
);
2280 info
->blocks_alloced
+= info
->inc
;
2284 if(where
< info
->num_items
)
2286 memmove((char*)info
->mem
+ (where
+ 1) * info
->block_size
,
2287 (char*)info
->mem
+ where
* info
->block_size
,
2288 (info
->num_items
- where
) * info
->block_size
);
2290 memcpy((char*)info
->mem
+ where
* info
->block_size
, block
, info
->block_size
);
2296 /*************************************************************************
2299 * Delete an element from an FDSA array.
2301 BOOL WINAPI
FDSA_DeleteItem(FDSA_info
*info
, DWORD where
)
2303 TRACE("(%p 0x%08x)\n", info
, where
);
2305 if(where
>= info
->num_items
)
2308 if(where
< info
->num_items
- 1)
2310 memmove((char*)info
->mem
+ where
* info
->block_size
,
2311 (char*)info
->mem
+ (where
+ 1) * info
->block_size
,
2312 (info
->num_items
- where
- 1) * info
->block_size
);
2314 memset((char*)info
->mem
+ (info
->num_items
- 1) * info
->block_size
,
2315 0, info
->block_size
);
2320 /*************************************************************************
2323 * Call IUnknown_QueryInterface() on a table of objects.
2327 * Failure: E_POINTER or E_NOINTERFACE.
2329 HRESULT WINAPI
QISearch(
2330 void *base
, /* [in] Table of interfaces */
2331 const QITAB
*table
, /* [in] Array of REFIIDs and indexes into the table */
2332 REFIID riid
, /* [in] REFIID to get interface for */
2333 void **ppv
) /* [out] Destination for interface pointer */
2339 TRACE("(%p %p %s %p)\n", base
, table
, debugstr_guid(riid
), ppv
);
2342 while (xmove
->piid
) {
2343 TRACE("trying (offset %d) %s\n", xmove
->dwOffset
, debugstr_guid(xmove
->piid
));
2344 if (IsEqualIID(riid
, xmove
->piid
)) {
2345 a_vtbl
= (IUnknown
*)(xmove
->dwOffset
+ (LPBYTE
)base
);
2346 TRACE("matched, returning (%p)\n", a_vtbl
);
2348 IUnknown_AddRef(a_vtbl
);
2354 if (IsEqualIID(riid
, &IID_IUnknown
)) {
2355 a_vtbl
= (IUnknown
*)(table
->dwOffset
+ (LPBYTE
)base
);
2356 TRACE("returning first for IUnknown (%p)\n", a_vtbl
);
2358 IUnknown_AddRef(a_vtbl
);
2362 ret
= E_NOINTERFACE
;
2366 TRACE("-- 0x%08x\n", ret
);
2370 /*************************************************************************
2373 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2376 * hWnd [I] Parent Window to set the property
2377 * id [I] Index of child Window to set the Font
2383 HRESULT WINAPI
SHSetDefaultDialogFont(HWND hWnd
, INT id
)
2385 FIXME("(%p, %d) stub\n", hWnd
, id
);
2389 /*************************************************************************
2392 * Remove the "PropDlgFont" property from a window.
2395 * hWnd [I] Window to remove the property from
2398 * A handle to the removed property, or NULL if it did not exist.
2400 HANDLE WINAPI
SHRemoveDefaultDialogFont(HWND hWnd
)
2404 TRACE("(%p)\n", hWnd
);
2406 hProp
= GetPropA(hWnd
, "PropDlgFont");
2410 DeleteObject(hProp
);
2411 hProp
= RemovePropA(hWnd
, "PropDlgFont");
2416 /*************************************************************************
2419 * Load the in-process server of a given GUID.
2422 * refiid [I] GUID of the server to load.
2425 * Success: A handle to the loaded server dll.
2426 * Failure: A NULL handle.
2428 HMODULE WINAPI
SHPinDllOfCLSID(REFIID refiid
)
2432 CHAR value
[MAX_PATH
], string
[MAX_PATH
];
2434 strcpy(string
, "CLSID\\");
2435 SHStringFromGUIDA(refiid
, string
+ 6, sizeof(string
)/sizeof(char) - 6);
2436 strcat(string
, "\\InProcServer32");
2439 RegOpenKeyExA(HKEY_CLASSES_ROOT
, string
, 0, 1, &newkey
);
2440 RegQueryValueExA(newkey
, 0, 0, &type
, (PBYTE
)value
, &count
);
2441 RegCloseKey(newkey
);
2442 return LoadLibraryExA(value
, 0, 0);
2445 /*************************************************************************
2448 * Unicode version of SHLWAPI_183.
2450 DWORD WINAPI
SHRegisterClassW(WNDCLASSW
* lpWndClass
)
2454 TRACE("(%p %s)\n",lpWndClass
->hInstance
, debugstr_w(lpWndClass
->lpszClassName
));
2456 if (GetClassInfoW(lpWndClass
->hInstance
, lpWndClass
->lpszClassName
, &WndClass
))
2458 return RegisterClassW(lpWndClass
);
2461 /*************************************************************************
2464 * Unregister a list of classes.
2467 * hInst [I] Application instance that registered the classes
2468 * lppClasses [I] List of class names
2469 * iCount [I] Number of names in lppClasses
2474 void WINAPI
SHUnregisterClassesA(HINSTANCE hInst
, LPCSTR
*lppClasses
, INT iCount
)
2478 TRACE("(%p,%p,%d)\n", hInst
, lppClasses
, iCount
);
2482 if (GetClassInfoA(hInst
, *lppClasses
, &WndClass
))
2483 UnregisterClassA(*lppClasses
, hInst
);
2489 /*************************************************************************
2492 * Unicode version of SHUnregisterClassesA.
2494 void WINAPI
SHUnregisterClassesW(HINSTANCE hInst
, LPCWSTR
*lppClasses
, INT iCount
)
2498 TRACE("(%p,%p,%d)\n", hInst
, lppClasses
, iCount
);
2502 if (GetClassInfoW(hInst
, *lppClasses
, &WndClass
))
2503 UnregisterClassW(*lppClasses
, hInst
);
2509 /*************************************************************************
2512 * Call The correct (Ascii/Unicode) default window procedure for a window.
2515 * hWnd [I] Window to call the default procedure for
2516 * uMessage [I] Message ID
2517 * wParam [I] WPARAM of message
2518 * lParam [I] LPARAM of message
2521 * The result of calling DefWindowProcA() or DefWindowProcW().
2523 LRESULT CALLBACK
SHDefWindowProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
2525 if (IsWindowUnicode(hWnd
))
2526 return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
2527 return DefWindowProcA(hWnd
, uMessage
, wParam
, lParam
);
2530 /*************************************************************************
2533 HRESULT WINAPI
IUnknown_GetSite(LPUNKNOWN lpUnknown
, REFIID iid
, PVOID
*lppSite
)
2535 HRESULT hRet
= E_INVALIDARG
;
2536 LPOBJECTWITHSITE lpSite
= NULL
;
2538 TRACE("(%p,%s,%p)\n", lpUnknown
, debugstr_guid(iid
), lppSite
);
2540 if (lpUnknown
&& iid
&& lppSite
)
2542 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IObjectWithSite
,
2544 if (SUCCEEDED(hRet
) && lpSite
)
2546 hRet
= IObjectWithSite_GetSite(lpSite
, iid
, lppSite
);
2547 IObjectWithSite_Release(lpSite
);
2553 /*************************************************************************
2556 * Create a worker window using CreateWindowExA().
2559 * wndProc [I] Window procedure
2560 * hWndParent [I] Parent window
2561 * dwExStyle [I] Extra style flags
2562 * dwStyle [I] Style flags
2563 * hMenu [I] Window menu
2564 * wnd_extra [I] Window extra bytes value
2567 * Success: The window handle of the newly created window.
2570 HWND WINAPI
SHCreateWorkerWindowA(LONG wndProc
, HWND hWndParent
, DWORD dwExStyle
,
2571 DWORD dwStyle
, HMENU hMenu
, LONG_PTR wnd_extra
)
2573 static const char szClass
[] = "WorkerA";
2577 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2578 wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, wnd_extra
);
2580 /* Create Window class */
2582 wc
.lpfnWndProc
= DefWindowProcA
;
2584 wc
.cbWndExtra
= sizeof(LONG_PTR
);
2585 wc
.hInstance
= shlwapi_hInstance
;
2587 wc
.hCursor
= LoadCursorA(NULL
, (LPSTR
)IDC_ARROW
);
2588 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2589 wc
.lpszMenuName
= NULL
;
2590 wc
.lpszClassName
= szClass
;
2592 SHRegisterClassA(&wc
);
2594 hWnd
= CreateWindowExA(dwExStyle
, szClass
, 0, dwStyle
, 0, 0, 0, 0,
2595 hWndParent
, hMenu
, shlwapi_hInstance
, 0);
2598 SetWindowLongPtrW(hWnd
, 0, wnd_extra
);
2600 if (wndProc
) SetWindowLongPtrA(hWnd
, GWLP_WNDPROC
, wndProc
);
2606 typedef struct tagPOLICYDATA
2608 DWORD policy
; /* flags value passed to SHRestricted */
2609 LPCWSTR appstr
; /* application str such as "Explorer" */
2610 LPCWSTR keystr
; /* name of the actual registry key / policy */
2611 } POLICYDATA
, *LPPOLICYDATA
;
2613 #define SHELL_NO_POLICY 0xffffffff
2615 /* default shell policy registry key */
2616 static const WCHAR strRegistryPolicyW
[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2617 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2618 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2619 '\\','P','o','l','i','c','i','e','s',0};
2621 /*************************************************************************
2624 * Retrieve a policy value from the registry.
2627 * lpSubKey [I] registry key name
2628 * lpSubName [I] subname of registry key
2629 * lpValue [I] value name of registry value
2632 * the value associated with the registry key or 0 if not found
2634 DWORD WINAPI
SHGetRestriction(LPCWSTR lpSubKey
, LPCWSTR lpSubName
, LPCWSTR lpValue
)
2636 DWORD retval
, datsize
= sizeof(retval
);
2640 lpSubKey
= strRegistryPolicyW
;
2642 retval
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, lpSubKey
, &hKey
);
2643 if (retval
!= ERROR_SUCCESS
)
2644 retval
= RegOpenKeyW(HKEY_CURRENT_USER
, lpSubKey
, &hKey
);
2645 if (retval
!= ERROR_SUCCESS
)
2648 SHGetValueW(hKey
, lpSubName
, lpValue
, NULL
, &retval
, &datsize
);
2653 /*************************************************************************
2656 * Helper function to retrieve the possibly cached value for a specific policy
2659 * policy [I] The policy to look for
2660 * initial [I] Main registry key to open, if NULL use default
2661 * polTable [I] Table of known policies, 0 terminated
2662 * polArr [I] Cache array of policy values
2665 * The retrieved policy value or 0 if not successful
2668 * This function is used by the native SHRestricted function to search for the
2669 * policy and cache it once retrieved. The current Wine implementation uses a
2670 * different POLICYDATA structure and implements a similar algorithm adapted to
2673 DWORD WINAPI
SHRestrictionLookup(
2676 LPPOLICYDATA polTable
,
2679 TRACE("(0x%08x %s %p %p)\n", policy
, debugstr_w(initial
), polTable
, polArr
);
2681 if (!polTable
|| !polArr
)
2684 for (;polTable
->policy
; polTable
++, polArr
++)
2686 if (policy
== polTable
->policy
)
2688 /* we have a known policy */
2690 /* check if this policy has been cached */
2691 if (*polArr
== SHELL_NO_POLICY
)
2692 *polArr
= SHGetRestriction(initial
, polTable
->appstr
, polTable
->keystr
);
2696 /* we don't know this policy, return 0 */
2697 TRACE("unknown policy: (%08x)\n", policy
);
2701 /*************************************************************************
2704 * Get an interface from an object.
2707 * Success: S_OK. ppv contains the requested interface.
2708 * Failure: An HRESULT error code.
2711 * This QueryInterface asks the inner object for an interface. In case
2712 * of aggregation this request would be forwarded by the inner to the
2713 * outer object. This function asks the inner object directly for the
2714 * interface circumventing the forwarding to the outer object.
2716 HRESULT WINAPI
SHWeakQueryInterface(
2717 IUnknown
* pUnk
, /* [in] Outer object */
2718 IUnknown
* pInner
, /* [in] Inner object */
2719 IID
* riid
, /* [in] Interface GUID to query for */
2720 LPVOID
* ppv
) /* [out] Destination for queried interface */
2722 HRESULT hret
= E_NOINTERFACE
;
2723 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk
,pInner
,debugstr_guid(riid
), ppv
);
2726 if(pUnk
&& pInner
) {
2727 hret
= IUnknown_QueryInterface(pInner
, riid
, ppv
);
2728 if (SUCCEEDED(hret
)) IUnknown_Release(pUnk
);
2730 TRACE("-- 0x%08x\n", hret
);
2734 /*************************************************************************
2737 * Move a reference from one interface to another.
2740 * lpDest [O] Destination to receive the reference
2741 * lppUnknown [O] Source to give up the reference to lpDest
2746 VOID WINAPI
SHWeakReleaseInterface(IUnknown
*lpDest
, IUnknown
**lppUnknown
)
2748 TRACE("(%p,%p)\n", lpDest
, lppUnknown
);
2753 IUnknown_AddRef(lpDest
);
2754 IUnknown_AtomicRelease(lppUnknown
); /* Release existing interface */
2758 /*************************************************************************
2761 * Convert an ASCII string of a CLSID into a CLSID.
2764 * idstr [I] String representing a CLSID in registry format
2765 * id [O] Destination for the converted CLSID
2768 * Success: TRUE. id contains the converted CLSID.
2771 BOOL WINAPI
GUIDFromStringA(LPCSTR idstr
, CLSID
*id
)
2774 MultiByteToWideChar(CP_ACP
, 0, idstr
, -1, wClsid
, sizeof(wClsid
)/sizeof(WCHAR
));
2775 return SUCCEEDED(CLSIDFromString(wClsid
, id
));
2778 /*************************************************************************
2781 * Unicode version of GUIDFromStringA.
2783 BOOL WINAPI
GUIDFromStringW(LPCWSTR idstr
, CLSID
*id
)
2785 return SUCCEEDED(CLSIDFromString((LPCOLESTR
)idstr
, id
));
2788 /*************************************************************************
2791 * Determine if the browser is integrated into the shell, and set a registry
2798 * 1, If the browser is not integrated.
2799 * 2, If the browser is integrated.
2802 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2803 * either set to TRUE, or removed depending on whether the browser is deemed
2806 DWORD WINAPI
WhichPlatform(void)
2808 static const char szIntegratedBrowser
[] = "IntegratedBrowser";
2809 static DWORD dwState
= 0;
2811 DWORD dwRet
, dwData
, dwSize
;
2817 /* If shell32 exports DllGetVersion(), the browser is integrated */
2819 hshell32
= LoadLibraryA("shell32.dll");
2822 FARPROC pDllGetVersion
;
2823 pDllGetVersion
= GetProcAddress(hshell32
, "DllGetVersion");
2824 dwState
= pDllGetVersion
? 2 : 1;
2825 FreeLibrary(hshell32
);
2828 /* Set or delete the key accordingly */
2829 dwRet
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
,
2830 "Software\\Microsoft\\Internet Explorer", 0,
2831 KEY_ALL_ACCESS
, &hKey
);
2834 dwRet
= RegQueryValueExA(hKey
, szIntegratedBrowser
, 0, 0,
2835 (LPBYTE
)&dwData
, &dwSize
);
2837 if (!dwRet
&& dwState
== 1)
2839 /* Value exists but browser is not integrated */
2840 RegDeleteValueA(hKey
, szIntegratedBrowser
);
2842 else if (dwRet
&& dwState
== 2)
2844 /* Browser is integrated but value does not exist */
2846 RegSetValueExA(hKey
, szIntegratedBrowser
, 0, REG_DWORD
,
2847 (LPBYTE
)&dwData
, sizeof(dwData
));
2854 /*************************************************************************
2857 * Unicode version of SHCreateWorkerWindowA.
2859 HWND WINAPI
SHCreateWorkerWindowW(LONG wndProc
, HWND hWndParent
, DWORD dwExStyle
,
2860 DWORD dwStyle
, HMENU hMenu
, LONG msg_result
)
2862 static const WCHAR szClass
[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
2866 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
2867 wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, msg_result
);
2869 /* If our OS is natively ANSI, use the ANSI version */
2870 if (GetVersion() & 0x80000000) /* not NT */
2872 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
2873 return SHCreateWorkerWindowA(wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, msg_result
);
2876 /* Create Window class */
2878 wc
.lpfnWndProc
= DefWindowProcW
;
2881 wc
.hInstance
= shlwapi_hInstance
;
2883 wc
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
2884 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2885 wc
.lpszMenuName
= NULL
;
2886 wc
.lpszClassName
= szClass
;
2888 SHRegisterClassW(&wc
);
2890 hWnd
= CreateWindowExW(dwExStyle
, szClass
, 0, dwStyle
, 0, 0, 0, 0,
2891 hWndParent
, hMenu
, shlwapi_hInstance
, 0);
2894 SetWindowLongPtrW(hWnd
, DWLP_MSGRESULT
, msg_result
);
2896 if (wndProc
) SetWindowLongPtrW(hWnd
, GWLP_WNDPROC
, wndProc
);
2902 /*************************************************************************
2905 * Get and show a context menu from a shell folder.
2908 * hWnd [I] Window displaying the shell folder
2909 * lpFolder [I] IShellFolder interface
2910 * lpApidl [I] Id for the particular folder desired
2914 * Failure: An HRESULT error code indicating the error.
2916 HRESULT WINAPI
SHInvokeDefaultCommand(HWND hWnd
, IShellFolder
* lpFolder
, LPCITEMIDLIST lpApidl
)
2918 TRACE("%p %p %p\n", hWnd
, lpFolder
, lpApidl
);
2919 return SHInvokeCommand(hWnd
, lpFolder
, lpApidl
, 0);
2922 /*************************************************************************
2925 * _SHPackDispParamsV
2927 HRESULT WINAPI
SHPackDispParamsV(DISPPARAMS
*params
, VARIANTARG
*args
, UINT cnt
, __ms_va_list valist
)
2931 TRACE("(%p %p %u ...)\n", params
, args
, cnt
);
2933 params
->rgvarg
= args
;
2934 params
->rgdispidNamedArgs
= NULL
;
2935 params
->cArgs
= cnt
;
2936 params
->cNamedArgs
= 0;
2940 while(iter
-- > args
) {
2941 V_VT(iter
) = va_arg(valist
, enum VARENUM
);
2943 TRACE("vt=%d\n", V_VT(iter
));
2945 if(V_VT(iter
) & VT_BYREF
) {
2946 V_BYREF(iter
) = va_arg(valist
, LPVOID
);
2948 switch(V_VT(iter
)) {
2950 V_I4(iter
) = va_arg(valist
, LONG
);
2953 V_BSTR(iter
) = va_arg(valist
, BSTR
);
2956 V_DISPATCH(iter
) = va_arg(valist
, IDispatch
*);
2959 V_BOOL(iter
) = va_arg(valist
, int);
2962 V_UNKNOWN(iter
) = va_arg(valist
, IUnknown
*);
2966 V_I4(iter
) = va_arg(valist
, LONG
);
2974 /*************************************************************************
2979 HRESULT WINAPIV
SHPackDispParams(DISPPARAMS
*params
, VARIANTARG
*args
, UINT cnt
, ...)
2981 __ms_va_list valist
;
2984 __ms_va_start(valist
, cnt
);
2985 hres
= SHPackDispParamsV(params
, args
, cnt
, valist
);
2986 __ms_va_end(valist
);
2990 /*************************************************************************
2991 * SHLWAPI_InvokeByIID
2993 * This helper function calls IDispatch::Invoke for each sink
2994 * which implements given iid or IDispatch.
2997 static HRESULT
SHLWAPI_InvokeByIID(
2998 IConnectionPoint
* iCP
,
3001 DISPPARAMS
* dispParams
)
3003 IEnumConnections
*enumerator
;
3005 static DISPPARAMS empty
= {NULL
, NULL
, 0, 0};
3006 DISPPARAMS
* params
= dispParams
;
3008 HRESULT result
= IConnectionPoint_EnumConnections(iCP
, &enumerator
);
3012 /* Invoke is never happening with an NULL dispParams */
3016 while(IEnumConnections_Next(enumerator
, 1, &rgcd
, NULL
)==S_OK
)
3018 IDispatch
*dispIface
;
3019 if ((iid
&& SUCCEEDED(IUnknown_QueryInterface(rgcd
.pUnk
, iid
, (LPVOID
*)&dispIface
))) ||
3020 SUCCEEDED(IUnknown_QueryInterface(rgcd
.pUnk
, &IID_IDispatch
, (LPVOID
*)&dispIface
)))
3022 IDispatch_Invoke(dispIface
, dispId
, &IID_NULL
, 0, DISPATCH_METHOD
, params
, NULL
, NULL
, NULL
);
3023 IDispatch_Release(dispIface
);
3025 IUnknown_Release(rgcd
.pUnk
);
3028 IEnumConnections_Release(enumerator
);
3033 /*************************************************************************
3034 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3036 HRESULT WINAPI
IConnectionPoint_InvokeWithCancel( IConnectionPoint
* iCP
,
3037 DISPID dispId
, DISPPARAMS
* dispParams
,
3038 DWORD unknown1
, DWORD unknown2
)
3043 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP
, dispId
, dispParams
, unknown1
, unknown2
);
3045 result
= IConnectionPoint_GetConnectionInterface(iCP
, &iid
);
3046 if (SUCCEEDED(result
))
3047 result
= SHLWAPI_InvokeByIID(iCP
, &iid
, dispId
, dispParams
);
3049 result
= SHLWAPI_InvokeByIID(iCP
, NULL
, dispId
, dispParams
);
3055 /*************************************************************************
3058 * IConnectionPoint_SimpleInvoke
3060 HRESULT WINAPI
IConnectionPoint_SimpleInvoke(
3061 IConnectionPoint
* iCP
,
3063 DISPPARAMS
* dispParams
)
3068 TRACE("(%p)->(0x%x %p)\n",iCP
,dispId
,dispParams
);
3070 result
= IConnectionPoint_GetConnectionInterface(iCP
, &iid
);
3071 if (SUCCEEDED(result
))
3072 result
= SHLWAPI_InvokeByIID(iCP
, &iid
, dispId
, dispParams
);
3074 result
= SHLWAPI_InvokeByIID(iCP
, NULL
, dispId
, dispParams
);
3079 /*************************************************************************
3082 * Notify an IConnectionPoint object of changes.
3085 * lpCP [I] Object to notify
3090 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3091 * IConnectionPoint interface.
3093 HRESULT WINAPI
IConnectionPoint_OnChanged(IConnectionPoint
* lpCP
, DISPID dispID
)
3095 IEnumConnections
*lpEnum
;
3096 HRESULT hRet
= E_NOINTERFACE
;
3098 TRACE("(%p,0x%8X)\n", lpCP
, dispID
);
3100 /* Get an enumerator for the connections */
3102 hRet
= IConnectionPoint_EnumConnections(lpCP
, &lpEnum
);
3104 if (SUCCEEDED(hRet
))
3106 IPropertyNotifySink
*lpSink
;
3107 CONNECTDATA connData
;
3110 /* Call OnChanged() for every notify sink in the connection point */
3111 while (IEnumConnections_Next(lpEnum
, 1, &connData
, &ulFetched
) == S_OK
)
3113 if (SUCCEEDED(IUnknown_QueryInterface(connData
.pUnk
, &IID_IPropertyNotifySink
, (void**)&lpSink
)) &&
3116 IPropertyNotifySink_OnChanged(lpSink
, dispID
);
3117 IPropertyNotifySink_Release(lpSink
);
3119 IUnknown_Release(connData
.pUnk
);
3122 IEnumConnections_Release(lpEnum
);
3127 /*************************************************************************
3130 * IUnknown_CPContainerInvokeParam
3132 HRESULT WINAPIV
IUnknown_CPContainerInvokeParam(
3133 IUnknown
*container
,
3140 IConnectionPoint
*iCP
;
3141 IConnectionPointContainer
*iCPC
;
3142 DISPPARAMS dispParams
= {buffer
, NULL
, cParams
, 0};
3143 __ms_va_list valist
;
3146 return E_NOINTERFACE
;
3148 result
= IUnknown_QueryInterface(container
, &IID_IConnectionPointContainer
,(LPVOID
*) &iCPC
);
3152 result
= IConnectionPointContainer_FindConnectionPoint(iCPC
, riid
, &iCP
);
3153 IConnectionPointContainer_Release(iCPC
);
3157 __ms_va_start(valist
, cParams
);
3158 SHPackDispParamsV(&dispParams
, buffer
, cParams
, valist
);
3159 __ms_va_end(valist
);
3161 result
= SHLWAPI_InvokeByIID(iCP
, riid
, dispId
, &dispParams
);
3162 IConnectionPoint_Release(iCP
);
3167 /*************************************************************************
3170 * Notify an IConnectionPointContainer object of changes.
3173 * lpUnknown [I] Object to notify
3178 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3179 * IConnectionPointContainer interface.
3181 HRESULT WINAPI
IUnknown_CPContainerOnChanged(IUnknown
*lpUnknown
, DISPID dispID
)
3183 IConnectionPointContainer
* lpCPC
= NULL
;
3184 HRESULT hRet
= E_NOINTERFACE
;
3186 TRACE("(%p,0x%8X)\n", lpUnknown
, dispID
);
3189 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IConnectionPointContainer
, (void**)&lpCPC
);
3191 if (SUCCEEDED(hRet
))
3193 IConnectionPoint
* lpCP
;
3195 hRet
= IConnectionPointContainer_FindConnectionPoint(lpCPC
, &IID_IPropertyNotifySink
, &lpCP
);
3196 IConnectionPointContainer_Release(lpCPC
);
3198 hRet
= IConnectionPoint_OnChanged(lpCP
, dispID
);
3199 IConnectionPoint_Release(lpCP
);
3204 /*************************************************************************
3209 BOOL WINAPI
PlaySoundWrapW(LPCWSTR pszSound
, HMODULE hmod
, DWORD fdwSound
)
3211 return PlaySoundW(pszSound
, hmod
, fdwSound
);
3214 /*************************************************************************
3217 * Retrieve a key value from an INI file. See GetPrivateProfileString for
3221 * appName [I] The section in the INI file that contains the key
3222 * keyName [I] The key to be retrieved
3223 * out [O] The buffer into which the key's value will be copied
3224 * outLen [I] The length of the `out' buffer
3225 * filename [I] The location of the INI file
3228 * Length of string copied into `out'.
3230 DWORD WINAPI
SHGetIniStringW(LPCWSTR appName
, LPCWSTR keyName
, LPWSTR out
,
3231 DWORD outLen
, LPCWSTR filename
)
3236 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName
), debugstr_w(keyName
),
3237 out
, outLen
, debugstr_w(filename
));
3242 buf
= HeapAlloc(GetProcessHeap(), 0, outLen
* sizeof(WCHAR
));
3248 ret
= GetPrivateProfileStringW(appName
, keyName
, NULL
, buf
, outLen
, filename
);
3254 HeapFree(GetProcessHeap(), 0, buf
);
3256 return strlenW(out
);
3259 /*************************************************************************
3262 * Set a key value in an INI file. See WritePrivateProfileString for
3266 * appName [I] The section in the INI file that contains the key
3267 * keyName [I] The key to be set
3268 * str [O] The value of the key
3269 * filename [I] The location of the INI file
3275 BOOL WINAPI
SHSetIniStringW(LPCWSTR appName
, LPCWSTR keyName
, LPCWSTR str
,
3278 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName
), keyName
, debugstr_w(str
),
3279 debugstr_w(filename
));
3281 return WritePrivateProfileStringW(appName
, keyName
, str
, filename
);
3284 /*************************************************************************
3287 * See SHGetFileInfoW.
3289 DWORD WINAPI
SHGetFileInfoWrapW(LPCWSTR path
, DWORD dwFileAttributes
,
3290 SHFILEINFOW
*psfi
, UINT sizeofpsfi
, UINT flags
)
3292 return SHGetFileInfoW(path
, dwFileAttributes
, psfi
, sizeofpsfi
, flags
);
3295 /*************************************************************************
3298 * See DragQueryFileW.
3300 UINT WINAPI
DragQueryFileWrapW(HDROP hDrop
, UINT lFile
, LPWSTR lpszFile
, UINT lLength
)
3302 return DragQueryFileW(hDrop
, lFile
, lpszFile
, lLength
);
3305 /*************************************************************************
3308 * See SHBrowseForFolderW.
3310 LPITEMIDLIST WINAPI
SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi
)
3312 return SHBrowseForFolderW(lpBi
);
3315 /*************************************************************************
3318 * See SHGetPathFromIDListW.
3320 BOOL WINAPI
SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl
,LPWSTR pszPath
)
3322 return SHGetPathFromIDListW(pidl
, pszPath
);
3325 /*************************************************************************
3328 * See ShellExecuteExW.
3330 BOOL WINAPI
ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo
)
3332 return ShellExecuteExW(lpExecInfo
);
3335 /*************************************************************************
3338 * See SHFileOperationW.
3340 INT WINAPI
SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp
)
3342 return SHFileOperationW(lpFileOp
);
3345 /*************************************************************************
3349 PVOID WINAPI
SHInterlockedCompareExchange( PVOID
*dest
, PVOID xchg
, PVOID compare
)
3351 return InterlockedCompareExchangePointer( dest
, xchg
, compare
);
3354 /*************************************************************************
3357 * See GetFileVersionInfoSizeW.
3359 DWORD WINAPI
GetFileVersionInfoSizeWrapW( LPCWSTR filename
, LPDWORD handle
)
3361 return GetFileVersionInfoSizeW( filename
, handle
);
3364 /*************************************************************************
3367 * See GetFileVersionInfoW.
3369 BOOL WINAPI
GetFileVersionInfoWrapW( LPCWSTR filename
, DWORD handle
,
3370 DWORD datasize
, LPVOID data
)
3372 return GetFileVersionInfoW( filename
, handle
, datasize
, data
);
3375 /*************************************************************************
3378 * See VerQueryValueW.
3380 WORD WINAPI
VerQueryValueWrapW( LPVOID pBlock
, LPCWSTR lpSubBlock
,
3381 LPVOID
*lplpBuffer
, UINT
*puLen
)
3383 return VerQueryValueW( pBlock
, lpSubBlock
, lplpBuffer
, puLen
);
3386 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3387 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3388 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3390 /*************************************************************************
3393 * Change the modality of a shell object.
3396 * lpUnknown [I] Object to make modeless
3397 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3400 * Success: S_OK. The modality lpUnknown is changed.
3401 * Failure: An HRESULT error code indicating the error.
3404 * lpUnknown must support the IOleInPlaceFrame interface, the
3405 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3406 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3407 * or this call will fail.
3409 HRESULT WINAPI
IUnknown_EnableModeless(IUnknown
*lpUnknown
, BOOL bModeless
)
3414 TRACE("(%p,%d)\n", lpUnknown
, bModeless
);
3419 if (IsIface(IOleInPlaceActiveObject
))
3420 EnableModeless(IOleInPlaceActiveObject
);
3421 else if (IsIface(IOleInPlaceFrame
))
3422 EnableModeless(IOleInPlaceFrame
);
3423 else if (IsIface(IShellBrowser
))
3424 EnableModeless(IShellBrowser
);
3425 else if (IsIface(IInternetSecurityMgrSite
))
3426 EnableModeless(IInternetSecurityMgrSite
);
3427 else if (IsIface(IDocHostUIHandler
))
3428 EnableModeless(IDocHostUIHandler
);
3432 IUnknown_Release(lpObj
);
3436 /*************************************************************************
3439 * See SHGetNewLinkInfoW.
3441 BOOL WINAPI
SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo
, LPCWSTR pszDir
, LPWSTR pszName
,
3442 BOOL
*pfMustCopy
, UINT uFlags
)
3444 return SHGetNewLinkInfoW(pszLinkTo
, pszDir
, pszName
, pfMustCopy
, uFlags
);
3447 /*************************************************************************
3450 * See SHDefExtractIconW.
3452 UINT WINAPI
SHDefExtractIconWrapW(LPCWSTR pszIconFile
, int iIndex
, UINT uFlags
, HICON
* phiconLarge
,
3453 HICON
* phiconSmall
, UINT nIconSize
)
3455 return SHDefExtractIconW(pszIconFile
, iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
3458 /*************************************************************************
3461 * Get and show a context menu from a shell folder.
3464 * hWnd [I] Window displaying the shell folder
3465 * lpFolder [I] IShellFolder interface
3466 * lpApidl [I] Id for the particular folder desired
3467 * dwCommandId [I] The command ID to invoke (0=invoke default)
3470 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3472 * Failure: An HRESULT error code indicating the error.
3474 HRESULT WINAPI
SHInvokeCommand(HWND hWnd
, IShellFolder
* lpFolder
, LPCITEMIDLIST lpApidl
, DWORD dwCommandId
)
3476 IContextMenu
*iContext
;
3479 TRACE("(%p, %p, %p, %u)\n", hWnd
, lpFolder
, lpApidl
, dwCommandId
);
3484 /* Get the context menu from the shell folder */
3485 hRet
= IShellFolder_GetUIObjectOf(lpFolder
, hWnd
, 1, &lpApidl
,
3486 &IID_IContextMenu
, 0, (void**)&iContext
);
3487 if (SUCCEEDED(hRet
))
3490 if ((hMenu
= CreatePopupMenu()))
3494 /* Add the context menu entries to the popup */
3495 hQuery
= IContextMenu_QueryContextMenu(iContext
, hMenu
, 0, 1, 0x7FFF,
3496 dwCommandId
? CMF_NORMAL
: CMF_DEFAULTONLY
);
3498 if (SUCCEEDED(hQuery
))
3501 dwCommandId
= GetMenuDefaultItem(hMenu
, 0, 0);
3502 if (dwCommandId
!= (UINT
)-1)
3504 CMINVOKECOMMANDINFO cmIci
;
3505 /* Invoke the default item */
3506 memset(&cmIci
,0,sizeof(cmIci
));
3507 cmIci
.cbSize
= sizeof(cmIci
);
3508 cmIci
.fMask
= CMIC_MASK_ASYNCOK
;
3510 cmIci
.lpVerb
= MAKEINTRESOURCEA(dwCommandId
);
3511 cmIci
.nShow
= SW_SHOWNORMAL
;
3513 hRet
= IContextMenu_InvokeCommand(iContext
, &cmIci
);
3518 IContextMenu_Release(iContext
);
3523 /*************************************************************************
3528 HICON WINAPI
ExtractIconWrapW(HINSTANCE hInstance
, LPCWSTR lpszExeFileName
,
3531 return ExtractIconW(hInstance
, lpszExeFileName
, nIconIndex
);
3534 /*************************************************************************
3537 * Load a library from the directory of a particular process.
3540 * new_mod [I] Library name
3541 * inst_hwnd [I] Module whose directory is to be used
3542 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3545 * Success: A handle to the loaded module
3546 * Failure: A NULL handle.
3548 HMODULE WINAPI
MLLoadLibraryA(LPCSTR new_mod
, HMODULE inst_hwnd
, DWORD dwCrossCodePage
)
3550 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3552 * FIXME: Native shows calls to:
3553 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3555 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3556 * RegQueryValueExA for "LPKInstalled"
3558 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3559 * RegQueryValueExA for "ResourceLocale"
3561 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3562 * RegQueryValueExA for "Locale"
3564 * and then tests the Locale ("en" for me).
3566 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3568 CHAR mod_path
[2*MAX_PATH
];
3572 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod
), inst_hwnd
, dwCrossCodePage
);
3573 len
= GetModuleFileNameA(inst_hwnd
, mod_path
, sizeof(mod_path
));
3574 if (!len
|| len
>= sizeof(mod_path
)) return NULL
;
3576 ptr
= strrchr(mod_path
, '\\');
3578 strcpy(ptr
+1, new_mod
);
3579 TRACE("loading %s\n", debugstr_a(mod_path
));
3580 return LoadLibraryA(mod_path
);
3585 /*************************************************************************
3588 * Unicode version of MLLoadLibraryA.
3590 HMODULE WINAPI
MLLoadLibraryW(LPCWSTR new_mod
, HMODULE inst_hwnd
, DWORD dwCrossCodePage
)
3592 WCHAR mod_path
[2*MAX_PATH
];
3596 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod
), inst_hwnd
, dwCrossCodePage
);
3597 len
= GetModuleFileNameW(inst_hwnd
, mod_path
, sizeof(mod_path
) / sizeof(WCHAR
));
3598 if (!len
|| len
>= sizeof(mod_path
) / sizeof(WCHAR
)) return NULL
;
3600 ptr
= strrchrW(mod_path
, '\\');
3602 strcpyW(ptr
+1, new_mod
);
3603 TRACE("loading %s\n", debugstr_w(mod_path
));
3604 return LoadLibraryW(mod_path
);
3609 /*************************************************************************
3610 * ColorAdjustLuma [SHLWAPI.@]
3612 * Adjust the luminosity of a color
3615 * cRGB [I] RGB value to convert
3616 * dwLuma [I] Luma adjustment
3617 * bUnknown [I] Unknown
3620 * The adjusted RGB color.
3622 COLORREF WINAPI
ColorAdjustLuma(COLORREF cRGB
, int dwLuma
, BOOL bUnknown
)
3624 TRACE("(0x%8x,%d,%d)\n", cRGB
, dwLuma
, bUnknown
);
3630 ColorRGBToHLS(cRGB
, &wH
, &wL
, &wS
);
3632 FIXME("Ignoring luma adjustment\n");
3634 /* FIXME: The adjustment is not linear */
3636 cRGB
= ColorHLSToRGB(wH
, wL
, wS
);
3641 /*************************************************************************
3644 * See GetSaveFileNameW.
3646 BOOL WINAPI
GetSaveFileNameWrapW(LPOPENFILENAMEW ofn
)
3648 return GetSaveFileNameW(ofn
);
3651 /*************************************************************************
3654 * See WNetRestoreConnectionW.
3656 DWORD WINAPI
WNetRestoreConnectionWrapW(HWND hwndOwner
, LPWSTR lpszDevice
)
3658 return WNetRestoreConnectionW(hwndOwner
, lpszDevice
);
3661 /*************************************************************************
3664 * See WNetGetLastErrorW.
3666 DWORD WINAPI
WNetGetLastErrorWrapW(LPDWORD lpError
, LPWSTR lpErrorBuf
, DWORD nErrorBufSize
,
3667 LPWSTR lpNameBuf
, DWORD nNameBufSize
)
3669 return WNetGetLastErrorW(lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
3672 /*************************************************************************
3675 * See PageSetupDlgW.
3677 BOOL WINAPI
PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg
)
3679 return PageSetupDlgW(pagedlg
);
3682 /*************************************************************************
3687 BOOL WINAPI
PrintDlgWrapW(LPPRINTDLGW printdlg
)
3689 return PrintDlgW(printdlg
);
3692 /*************************************************************************
3695 * See GetOpenFileNameW.
3697 BOOL WINAPI
GetOpenFileNameWrapW(LPOPENFILENAMEW ofn
)
3699 return GetOpenFileNameW(ofn
);
3702 /*************************************************************************
3705 HRESULT WINAPI
SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder
, HWND hwnd
, SHCONTF flags
, IEnumIDList
**ppenum
)
3707 /* Windows attempts to get an IPersist interface and, if that fails, an
3708 * IPersistFolder interface on the folder passed-in here. If one of those
3709 * interfaces is available, it then calls GetClassID on the folder... and
3710 * then calls IShellFolder_EnumObjects no matter what, even crashing if
3711 * lpFolder isn't actually an IShellFolder object. The purpose of getting
3712 * the ClassID is unknown, so we don't do it here.
3714 * For discussion and detailed tests, see:
3715 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated"
3716 * wine-devel mailing list, 3 Jun 2010
3719 return IShellFolder_EnumObjects(lpFolder
, hwnd
, flags
, ppenum
);
3722 /* INTERNAL: Map from HLS color space to RGB */
3723 static WORD
ConvertHue(int wHue
, WORD wMid1
, WORD wMid2
)
3725 wHue
= wHue
> 240 ? wHue
- 240 : wHue
< 0 ? wHue
+ 240 : wHue
;
3729 else if (wHue
> 120)
3734 return ((wHue
* (wMid2
- wMid1
) + 20) / 40) + wMid1
;
3737 /* Convert to RGB and scale into RGB range (0..255) */
3738 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3740 /*************************************************************************
3741 * ColorHLSToRGB [SHLWAPI.@]
3743 * Convert from hls color space into an rgb COLORREF.
3746 * wHue [I] Hue amount
3747 * wLuminosity [I] Luminosity amount
3748 * wSaturation [I] Saturation amount
3751 * A COLORREF representing the converted color.
3754 * Input hls values are constrained to the range (0..240).
3756 COLORREF WINAPI
ColorHLSToRGB(WORD wHue
, WORD wLuminosity
, WORD wSaturation
)
3762 WORD wGreen
, wBlue
, wMid1
, wMid2
;
3764 if (wLuminosity
> 120)
3765 wMid2
= wSaturation
+ wLuminosity
- (wSaturation
* wLuminosity
+ 120) / 240;
3767 wMid2
= ((wSaturation
+ 240) * wLuminosity
+ 120) / 240;
3769 wMid1
= wLuminosity
* 2 - wMid2
;
3771 wRed
= GET_RGB(wHue
+ 80);
3772 wGreen
= GET_RGB(wHue
);
3773 wBlue
= GET_RGB(wHue
- 80);
3775 return RGB(wRed
, wGreen
, wBlue
);
3778 wRed
= wLuminosity
* 255 / 240;
3779 return RGB(wRed
, wRed
, wRed
);
3782 /*************************************************************************
3785 * Get the current docking status of the system.
3788 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3791 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3794 DWORD WINAPI
SHGetMachineInfo(DWORD dwFlags
)
3796 HW_PROFILE_INFOA hwInfo
;
3798 TRACE("(0x%08x)\n", dwFlags
);
3800 GetCurrentHwProfileA(&hwInfo
);
3801 switch (hwInfo
.dwDockInfo
& (DOCKINFO_DOCKED
|DOCKINFO_UNDOCKED
))
3803 case DOCKINFO_DOCKED
:
3804 case DOCKINFO_UNDOCKED
:
3805 return hwInfo
.dwDockInfo
& (DOCKINFO_DOCKED
|DOCKINFO_UNDOCKED
);
3811 /*************************************************************************
3815 DWORD WINAPI
SHWinHelpOnDemandW(HWND hwnd
, LPCWSTR helpfile
, DWORD flags1
, VOID
*ptr1
, DWORD flags2
)
3818 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd
, debugstr_w(helpfile
), flags1
, ptr1
, flags2
);
3822 /*************************************************************************
3826 DWORD WINAPI
SHWinHelpOnDemandA(HWND hwnd
, LPCSTR helpfile
, DWORD flags1
, VOID
*ptr1
, DWORD flags2
)
3829 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd
, debugstr_a(helpfile
), flags1
, ptr1
, flags2
);
3833 /*************************************************************************
3836 * Function seems to do FreeLibrary plus other things.
3838 * FIXME native shows the following calls:
3839 * RtlEnterCriticalSection
3841 * GetProcAddress(Comctl32??, 150L)
3843 * RtlLeaveCriticalSection
3844 * followed by the FreeLibrary.
3845 * The above code may be related to .377 above.
3847 BOOL WINAPI
MLFreeLibrary(HMODULE hModule
)
3849 FIXME("(%p) semi-stub\n", hModule
);
3850 return FreeLibrary(hModule
);
3853 /*************************************************************************
3856 BOOL WINAPI
SHFlushSFCacheWrap(void) {
3861 /*************************************************************************
3863 * FIXME I have no idea what this function does or what its arguments are.
3865 BOOL WINAPI
MLIsMLHInstance(HINSTANCE hInst
)
3867 FIXME("(%p) stub\n", hInst
);
3872 /*************************************************************************
3875 DWORD WINAPI
MLSetMLHInstance(HINSTANCE hInst
, HANDLE hHeap
)
3877 FIXME("(%p,%p) stub\n", hInst
, hHeap
);
3878 return E_FAIL
; /* This is what is used if shlwapi not loaded */
3881 /*************************************************************************
3884 DWORD WINAPI
MLClearMLHInstance(DWORD x
)
3886 FIXME("(0x%08x)stub\n", x
);
3890 /*************************************************************************
3893 * See SHSendMessageBroadcastW
3896 DWORD WINAPI
SHSendMessageBroadcastA(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3898 return SendMessageTimeoutA(HWND_BROADCAST
, uMsg
, wParam
, lParam
,
3899 SMTO_ABORTIFHUNG
, 2000, NULL
);
3902 /*************************************************************************
3905 * A wrapper for sending Broadcast Messages to all top level Windows
3908 DWORD WINAPI
SHSendMessageBroadcastW(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3910 return SendMessageTimeoutW(HWND_BROADCAST
, uMsg
, wParam
, lParam
,
3911 SMTO_ABORTIFHUNG
, 2000, NULL
);
3914 /*************************************************************************
3917 * Convert a Unicode string CLSID into a CLSID.
3920 * idstr [I] string containing a CLSID in text form
3921 * id [O] CLSID extracted from the string
3924 * S_OK on success or E_INVALIDARG on failure
3926 HRESULT WINAPI
CLSIDFromStringWrap(LPCWSTR idstr
, CLSID
*id
)
3928 return CLSIDFromString((LPCOLESTR
)idstr
, id
);
3931 /*************************************************************************
3934 * Determine if the OS supports a given feature.
3937 * dwFeature [I] Feature requested (undocumented)
3940 * TRUE If the feature is available.
3941 * FALSE If the feature is not available.
3943 BOOL WINAPI
IsOS(DWORD feature
)
3945 OSVERSIONINFOA osvi
;
3946 DWORD platform
, majorv
, minorv
;
3948 osvi
.dwOSVersionInfoSize
= sizeof(OSVERSIONINFOA
);
3949 if(!GetVersionExA(&osvi
)) {
3950 ERR("GetVersionEx failed\n");
3954 majorv
= osvi
.dwMajorVersion
;
3955 minorv
= osvi
.dwMinorVersion
;
3956 platform
= osvi
.dwPlatformId
;
3958 #define ISOS_RETURN(x) \
3959 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3963 case OS_WIN32SORGREATER
:
3964 ISOS_RETURN(platform
== VER_PLATFORM_WIN32s
3965 || platform
== VER_PLATFORM_WIN32_WINDOWS
)
3967 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
3968 case OS_WIN95ORGREATER
:
3969 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
)
3970 case OS_NT4ORGREATER
:
3971 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 4)
3972 case OS_WIN2000ORGREATER_ALT
:
3973 case OS_WIN2000ORGREATER
:
3974 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5)
3975 case OS_WIN98ORGREATER
:
3976 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
>= 10)
3978 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
== 10)
3980 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5)
3981 case OS_WIN2000SERVER
:
3982 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
3983 case OS_WIN2000ADVSERVER
:
3984 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
3985 case OS_WIN2000DATACENTER
:
3986 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
3987 case OS_WIN2000TERMINAL
:
3988 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& (minorv
== 0 || minorv
== 1))
3990 FIXME("(OS_EMBEDDED) What should we return here?\n");
3992 case OS_TERMINALCLIENT
:
3993 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3995 case OS_TERMINALREMOTEADMIN
:
3996 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3999 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
== 0)
4000 case OS_MEORGREATER
:
4001 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_WINDOWS
&& minorv
>= 90)
4002 case OS_XPORGREATER
:
4003 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5 && minorv
>= 1)
4005 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5 && minorv
>= 1)
4006 case OS_PROFESSIONAL
:
4007 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4009 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4011 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 5)
4013 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4014 case OS_TERMINALSERVER
:
4015 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4016 case OS_PERSONALTERMINALSERVER
:
4017 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& minorv
>= 1 && majorv
>= 5)
4018 case OS_FASTUSERSWITCHING
:
4019 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
4021 case OS_WELCOMELOGONUI
:
4022 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
4024 case OS_DOMAINMEMBER
:
4025 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
4028 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4032 IsWow64Process(GetCurrentProcess(), &is_wow64
);
4036 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4037 case OS_SMALLBUSINESSSERVER
:
4038 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
)
4040 FIXME("(OS_TABLEPC) What should we return here?\n");
4042 case OS_SERVERADMINUI
:
4043 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
4045 case OS_MEDIACENTER
:
4046 FIXME("(OS_MEDIACENTER) What should we return here?\n");
4049 FIXME("(OS_APPLIANCE) What should we return here?\n");
4051 case 0x25: /*OS_VISTAORGREATER*/
4052 ISOS_RETURN(platform
== VER_PLATFORM_WIN32_NT
&& majorv
>= 6)
4057 WARN("(0x%x) unknown parameter\n",feature
);
4062 /*************************************************************************
4065 HRESULT WINAPI
SHLoadRegUIStringW(HKEY hkey
, LPCWSTR value
, LPWSTR buf
, DWORD size
)
4067 DWORD type
, sz
= size
;
4069 if(RegQueryValueExW(hkey
, value
, NULL
, &type
, (LPBYTE
)buf
, &sz
) != ERROR_SUCCESS
)
4072 return SHLoadIndirectString(buf
, buf
, size
, NULL
);
4075 /*************************************************************************
4078 * Call IInputObject_TranslateAcceleratorIO() on an object.
4081 * lpUnknown [I] Object supporting the IInputObject interface.
4082 * lpMsg [I] Key message to be processed.
4086 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4088 HRESULT WINAPI
IUnknown_TranslateAcceleratorIO(IUnknown
*lpUnknown
, LPMSG lpMsg
)
4090 IInputObject
* lpInput
= NULL
;
4091 HRESULT hRet
= E_INVALIDARG
;
4093 TRACE("(%p,%p)\n", lpUnknown
, lpMsg
);
4096 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObject
,
4098 if (SUCCEEDED(hRet
) && lpInput
)
4100 hRet
= IInputObject_TranslateAcceleratorIO(lpInput
, lpMsg
);
4101 IInputObject_Release(lpInput
);
4107 /*************************************************************************
4110 * Call IInputObject_HasFocusIO() on an object.
4113 * lpUnknown [I] Object supporting the IInputObject interface.
4116 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4117 * or S_FALSE otherwise.
4118 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4120 HRESULT WINAPI
IUnknown_HasFocusIO(IUnknown
*lpUnknown
)
4122 IInputObject
* lpInput
= NULL
;
4123 HRESULT hRet
= E_INVALIDARG
;
4125 TRACE("(%p)\n", lpUnknown
);
4128 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObject
,
4130 if (SUCCEEDED(hRet
) && lpInput
)
4132 hRet
= IInputObject_HasFocusIO(lpInput
);
4133 IInputObject_Release(lpInput
);
4139 /*************************************************************************
4140 * ColorRGBToHLS [SHLWAPI.@]
4142 * Convert an rgb COLORREF into the hls color space.
4145 * cRGB [I] Source rgb value
4146 * pwHue [O] Destination for converted hue
4147 * pwLuminance [O] Destination for converted luminance
4148 * pwSaturation [O] Destination for converted saturation
4151 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4155 * Output HLS values are constrained to the range (0..240).
4156 * For Achromatic conversions, Hue is set to 160.
4158 VOID WINAPI
ColorRGBToHLS(COLORREF cRGB
, LPWORD pwHue
,
4159 LPWORD pwLuminance
, LPWORD pwSaturation
)
4161 int wR
, wG
, wB
, wMax
, wMin
, wHue
, wLuminosity
, wSaturation
;
4163 TRACE("(%08x,%p,%p,%p)\n", cRGB
, pwHue
, pwLuminance
, pwSaturation
);
4165 wR
= GetRValue(cRGB
);
4166 wG
= GetGValue(cRGB
);
4167 wB
= GetBValue(cRGB
);
4169 wMax
= max(wR
, max(wG
, wB
));
4170 wMin
= min(wR
, min(wG
, wB
));
4173 wLuminosity
= ((wMax
+ wMin
) * 240 + 255) / 510;
4177 /* Achromatic case */
4179 /* Hue is now unrepresentable, but this is what native returns... */
4184 /* Chromatic case */
4185 int wDelta
= wMax
- wMin
, wRNorm
, wGNorm
, wBNorm
;
4188 if (wLuminosity
<= 120)
4189 wSaturation
= ((wMax
+ wMin
)/2 + wDelta
* 240) / (wMax
+ wMin
);
4191 wSaturation
= ((510 - wMax
- wMin
)/2 + wDelta
* 240) / (510 - wMax
- wMin
);
4194 wRNorm
= (wDelta
/2 + wMax
* 40 - wR
* 40) / wDelta
;
4195 wGNorm
= (wDelta
/2 + wMax
* 40 - wG
* 40) / wDelta
;
4196 wBNorm
= (wDelta
/2 + wMax
* 40 - wB
* 40) / wDelta
;
4199 wHue
= wBNorm
- wGNorm
;
4200 else if (wG
== wMax
)
4201 wHue
= 80 + wRNorm
- wBNorm
;
4203 wHue
= 160 + wGNorm
- wRNorm
;
4206 else if (wHue
> 240)
4212 *pwLuminance
= wLuminosity
;
4214 *pwSaturation
= wSaturation
;
4217 /*************************************************************************
4218 * SHCreateShellPalette [SHLWAPI.@]
4220 HPALETTE WINAPI
SHCreateShellPalette(HDC hdc
)
4223 return CreateHalftonePalette(hdc
);
4226 /*************************************************************************
4227 * SHGetInverseCMAP (SHLWAPI.@)
4229 * Get an inverse color map table.
4232 * lpCmap [O] Destination for color map
4233 * dwSize [I] Size of memory pointed to by lpCmap
4237 * Failure: E_POINTER, If lpCmap is invalid.
4238 * E_INVALIDARG, If dwFlags is invalid
4239 * E_OUTOFMEMORY, If there is no memory available
4242 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4243 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4245 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4246 * this DLL's internal CMap.
4248 HRESULT WINAPI
SHGetInverseCMAP(LPDWORD dest
, DWORD dwSize
)
4251 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4252 *dest
= (DWORD
)0xabba1249;
4255 FIXME("(%p, %#x) stub\n", dest
, dwSize
);
4259 /*************************************************************************
4260 * SHIsLowMemoryMachine [SHLWAPI.@]
4262 * Determine if the current computer has low memory.
4268 * TRUE if the users machine has 16 Megabytes of memory or less,
4271 BOOL WINAPI
SHIsLowMemoryMachine (DWORD x
)
4273 FIXME("(0x%08x) stub\n", x
);
4277 /*************************************************************************
4278 * GetMenuPosFromID [SHLWAPI.@]
4280 * Return the position of a menu item from its Id.
4283 * hMenu [I] Menu containing the item
4284 * wID [I] Id of the menu item
4287 * Success: The index of the menu item in hMenu.
4288 * Failure: -1, If the item is not found.
4290 INT WINAPI
GetMenuPosFromID(HMENU hMenu
, UINT wID
)
4293 INT nCount
= GetMenuItemCount(hMenu
), nIter
= 0;
4295 TRACE("%p %u\n", hMenu
, wID
);
4297 while (nIter
< nCount
)
4299 mi
.cbSize
= sizeof(mi
);
4301 if (GetMenuItemInfoW(hMenu
, nIter
, TRUE
, &mi
) && mi
.wID
== wID
)
4303 TRACE("ret %d\n", nIter
);
4312 /*************************************************************************
4315 * Same as SHLWAPI.GetMenuPosFromID
4317 DWORD WINAPI
SHMenuIndexFromID(HMENU hMenu
, UINT uID
)
4319 TRACE("%p %u\n", hMenu
, uID
);
4320 return GetMenuPosFromID(hMenu
, uID
);
4324 /*************************************************************************
4327 VOID WINAPI
FixSlashesAndColonW(LPWSTR lpwstr
)
4338 /*************************************************************************
4341 DWORD WINAPI
SHGetAppCompatFlags(DWORD dwUnknown
)
4343 FIXME("(0x%08x) stub\n", dwUnknown
);
4348 /*************************************************************************
4351 HRESULT WINAPI
SHCoCreateInstanceAC(REFCLSID rclsid
, LPUNKNOWN pUnkOuter
,
4352 DWORD dwClsContext
, REFIID iid
, LPVOID
*ppv
)
4354 return CoCreateInstance(rclsid
, pUnkOuter
, dwClsContext
, iid
, ppv
);
4357 /*************************************************************************
4358 * SHSkipJunction [SHLWAPI.@]
4360 * Determine if a bind context can be bound to an object
4363 * pbc [I] Bind context to check
4364 * pclsid [I] CLSID of object to be bound to
4367 * TRUE: If it is safe to bind
4368 * FALSE: If pbc is invalid or binding would not be safe
4371 BOOL WINAPI
SHSkipJunction(IBindCtx
*pbc
, const CLSID
*pclsid
)
4373 static WCHAR szSkipBinding
[] = { 'S','k','i','p',' ',
4374 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4381 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc
, szSkipBinding
, &lpUnk
)))
4385 if (SUCCEEDED(IUnknown_GetClassID(lpUnk
, &clsid
)) &&
4386 IsEqualGUID(pclsid
, &clsid
))
4389 IUnknown_Release(lpUnk
);
4395 /***********************************************************************
4396 * SHGetShellKey (SHLWAPI.491)
4398 HKEY WINAPI
SHGetShellKey(DWORD flags
, LPCWSTR sub_key
, BOOL create
)
4400 enum _shellkey_flags
{
4401 SHKEY_Root_HKCU
= 0x1,
4402 SHKEY_Root_HKLM
= 0x2,
4403 SHKEY_Key_Explorer
= 0x00,
4404 SHKEY_Key_Shell
= 0x10,
4405 SHKEY_Key_ShellNoRoam
= 0x20,
4406 SHKEY_Key_Classes
= 0x30,
4407 SHKEY_Subkey_Default
= 0x0000,
4408 SHKEY_Subkey_ResourceName
= 0x1000,
4409 SHKEY_Subkey_Handlers
= 0x2000,
4410 SHKEY_Subkey_Associations
= 0x3000,
4411 SHKEY_Subkey_Volatile
= 0x4000,
4412 SHKEY_Subkey_MUICache
= 0x5000,
4413 SHKEY_Subkey_FileExts
= 0x6000
4416 static const WCHAR explorerW
[] = {'S','o','f','t','w','a','r','e','\\',
4417 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4418 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4419 'E','x','p','l','o','r','e','r','\\'};
4420 static const WCHAR shellW
[] = {'S','o','f','t','w','a','r','e','\\',
4421 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4422 'S','h','e','l','l','\\'};
4423 static const WCHAR shell_no_roamW
[] = {'S','o','f','t','w','a','r','e','\\',
4424 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4425 'S','h','e','l','l','N','o','R','o','a','m','\\'};
4426 static const WCHAR classesW
[] = {'S','o','f','t','w','a','r','e','\\',
4427 'C','l','a','s','s','e','s','\\'};
4429 static const WCHAR localized_resource_nameW
[] = {'L','o','c','a','l','i','z','e','d',
4430 'R','e','s','o','u','r','c','e','N','a','m','e','\\'};
4431 static const WCHAR handlersW
[] = {'H','a','n','d','l','e','r','s','\\'};
4432 static const WCHAR associationsW
[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'};
4433 static const WCHAR volatileW
[] = {'V','o','l','a','t','i','l','e','\\'};
4434 static const WCHAR mui_cacheW
[] = {'M','U','I','C','a','c','h','e','\\'};
4435 static const WCHAR file_extsW
[] = {'F','i','l','e','E','x','t','s','\\'};
4438 const WCHAR
*key
, *subkey
;
4439 int size_key
, size_subkey
, size_user
;
4442 TRACE("(0x%08x, %s, %d)\n", flags
, debugstr_w(sub_key
), create
);
4444 /* For compatibility with Vista+ */
4445 if(flags
== 0x1ffff)
4448 switch(flags
&0xff0) {
4449 case SHKEY_Key_Explorer
:
4451 size_key
= sizeof(explorerW
);
4453 case SHKEY_Key_Shell
:
4455 size_key
= sizeof(shellW
);
4457 case SHKEY_Key_ShellNoRoam
:
4458 key
= shell_no_roamW
;
4459 size_key
= sizeof(shell_no_roamW
);
4461 case SHKEY_Key_Classes
:
4463 size_key
= sizeof(classesW
);
4466 FIXME("unsupported flags (0x%08x)\n", flags
);
4470 switch(flags
&0xff000) {
4471 case SHKEY_Subkey_Default
:
4475 case SHKEY_Subkey_ResourceName
:
4476 subkey
= localized_resource_nameW
;
4477 size_subkey
= sizeof(localized_resource_nameW
);
4479 case SHKEY_Subkey_Handlers
:
4481 size_subkey
= sizeof(handlersW
);
4483 case SHKEY_Subkey_Associations
:
4484 subkey
= associationsW
;
4485 size_subkey
= sizeof(associationsW
);
4487 case SHKEY_Subkey_Volatile
:
4489 size_subkey
= sizeof(volatileW
);
4491 case SHKEY_Subkey_MUICache
:
4492 subkey
= mui_cacheW
;
4493 size_subkey
= sizeof(mui_cacheW
);
4495 case SHKEY_Subkey_FileExts
:
4496 subkey
= file_extsW
;
4497 size_subkey
= sizeof(file_extsW
);
4500 FIXME("unsupported flags (0x%08x)\n", flags
);
4505 size_user
= lstrlenW(sub_key
)*sizeof(WCHAR
);
4509 path
= HeapAlloc(GetProcessHeap(), 0, size_key
+size_subkey
+size_user
+sizeof(WCHAR
));
4511 ERR("Out of memory\n");
4515 memcpy(path
, key
, size_key
);
4517 memcpy(path
+size_key
/sizeof(WCHAR
), subkey
, size_subkey
);
4519 memcpy(path
+(size_key
+size_subkey
)/sizeof(WCHAR
), sub_key
, size_user
);
4520 path
[(size_key
+size_subkey
+size_user
)/sizeof(WCHAR
)] = '\0';
4523 RegCreateKeyExW((flags
&0xf)==SHKEY_Root_HKLM
?HKEY_LOCAL_MACHINE
:HKEY_CURRENT_USER
,
4524 path
, 0, NULL
, 0, MAXIMUM_ALLOWED
, NULL
, &hkey
, NULL
);
4526 RegOpenKeyExW((flags
&0xf)==SHKEY_Root_HKLM
?HKEY_LOCAL_MACHINE
:HKEY_CURRENT_USER
,
4527 path
, 0, MAXIMUM_ALLOWED
, &hkey
);
4529 HeapFree(GetProcessHeap(), 0, path
);
4533 /***********************************************************************
4534 * SHQueueUserWorkItem (SHLWAPI.@)
4536 BOOL WINAPI
SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback
,
4537 LPVOID pContext
, LONG lPriority
, DWORD_PTR dwTag
,
4538 DWORD_PTR
*pdwId
, LPCSTR pszModule
, DWORD dwFlags
)
4540 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback
, pContext
,
4541 lPriority
, dwTag
, pdwId
, debugstr_a(pszModule
), dwFlags
);
4543 if(lPriority
|| dwTag
|| pdwId
|| pszModule
|| dwFlags
)
4544 FIXME("Unsupported arguments\n");
4546 return QueueUserWorkItem(pfnCallback
, pContext
, 0);
4549 /***********************************************************************
4550 * SHSetTimerQueueTimer (SHLWAPI.263)
4552 HANDLE WINAPI
SHSetTimerQueueTimer(HANDLE hQueue
,
4553 WAITORTIMERCALLBACK pfnCallback
, LPVOID pContext
, DWORD dwDueTime
,
4554 DWORD dwPeriod
, LPCSTR lpszLibrary
, DWORD dwFlags
)
4558 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4559 if (dwFlags
& TPS_LONGEXECTIME
) {
4560 dwFlags
&= ~TPS_LONGEXECTIME
;
4561 dwFlags
|= WT_EXECUTELONGFUNCTION
;
4563 if (dwFlags
& TPS_EXECUTEIO
) {
4564 dwFlags
&= ~TPS_EXECUTEIO
;
4565 dwFlags
|= WT_EXECUTEINIOTHREAD
;
4568 if (!CreateTimerQueueTimer(&hNewTimer
, hQueue
, pfnCallback
, pContext
,
4569 dwDueTime
, dwPeriod
, dwFlags
))
4575 /***********************************************************************
4576 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4578 HRESULT WINAPI
IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown
, LPUNKNOWN pFocusObject
, BOOL bFocus
)
4580 IInputObjectSite
*pIOS
= NULL
;
4581 HRESULT hRet
= E_INVALIDARG
;
4583 TRACE("(%p, %p, %s)\n", lpUnknown
, pFocusObject
, bFocus
? "TRUE" : "FALSE");
4587 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObjectSite
,
4589 if (SUCCEEDED(hRet
) && pIOS
)
4591 hRet
= IInputObjectSite_OnFocusChangeIS(pIOS
, pFocusObject
, bFocus
);
4592 IInputObjectSite_Release(pIOS
);
4598 /***********************************************************************
4599 * SKAllocValueW (SHLWAPI.519)
4601 HRESULT WINAPI
SKAllocValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
, DWORD
*type
,
4602 LPVOID
*data
, DWORD
*count
)
4607 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags
, debugstr_w(subkey
),
4608 debugstr_w(value
), type
, data
, count
);
4610 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
4612 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4614 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, NULL
, &size
);
4617 return HRESULT_FROM_WIN32(ret
);
4621 *data
= LocalAlloc(0, size
);
4624 return E_OUTOFMEMORY
;
4627 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, *data
, &size
);
4632 return HRESULT_FROM_WIN32(ret
);
4635 /***********************************************************************
4636 * SKDeleteValueW (SHLWAPI.518)
4638 HRESULT WINAPI
SKDeleteValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
)
4643 TRACE("(0x%x, %s %s)\n", flags
, debugstr_w(subkey
), debugstr_w(value
));
4645 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
4647 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4649 ret
= RegDeleteValueW(hkey
, value
);
4652 return HRESULT_FROM_WIN32(ret
);
4655 /***********************************************************************
4656 * SKGetValueW (SHLWAPI.516)
4658 HRESULT WINAPI
SKGetValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
, DWORD
*type
,
4659 void *data
, DWORD
*count
)
4664 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags
, debugstr_w(subkey
),
4665 debugstr_w(value
), type
, data
, count
);
4667 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
4669 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4671 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, data
, count
);
4674 return HRESULT_FROM_WIN32(ret
);
4677 /***********************************************************************
4678 * SKSetValueW (SHLWAPI.516)
4680 HRESULT WINAPI
SKSetValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
,
4681 DWORD type
, void *data
, DWORD count
)
4686 TRACE("(0x%x, %s, %s, %x, %p, %d)\n", flags
, debugstr_w(subkey
),
4687 debugstr_w(value
), type
, data
, count
);
4689 hkey
= SHGetShellKey(flags
, subkey
, TRUE
);
4691 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
4693 ret
= RegSetValueExW(hkey
, value
, 0, type
, data
, count
);
4696 return HRESULT_FROM_WIN32(ret
);
4699 typedef HRESULT (WINAPI
*DllGetVersion_func
)(DLLVERSIONINFO
*);
4701 /***********************************************************************
4702 * GetUIVersion (SHLWAPI.452)
4704 DWORD WINAPI
GetUIVersion(void)
4706 static DWORD version
;
4710 DllGetVersion_func pDllGetVersion
;
4711 HMODULE dll
= LoadLibraryA("shell32.dll");
4714 pDllGetVersion
= (DllGetVersion_func
)GetProcAddress(dll
, "DllGetVersion");
4718 dvi
.cbSize
= sizeof(DLLVERSIONINFO
);
4719 if (pDllGetVersion(&dvi
) == S_OK
) version
= dvi
.dwMajorVersion
;
4722 if (!version
) version
= 3; /* old shell dlls don't have DllGetVersion */
4727 /***********************************************************************
4728 * ShellMessageBoxWrapW [SHLWAPI.388]
4730 * See shell32.ShellMessageBoxW
4733 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4734 * because we can't forward to it in the .spec file since it's exported by
4735 * ordinal. If you change the implementation here please update the code in
4738 INT WINAPIV
ShellMessageBoxWrapW(HINSTANCE hInstance
, HWND hWnd
, LPCWSTR lpText
,
4739 LPCWSTR lpCaption
, UINT uType
, ...)
4741 WCHAR
*szText
= NULL
, szTitle
[100];
4742 LPCWSTR pszText
, pszTitle
= szTitle
;
4747 __ms_va_start(args
, uType
);
4749 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance
, hWnd
, lpText
, lpCaption
, uType
);
4751 if (IS_INTRESOURCE(lpCaption
))
4752 LoadStringW(hInstance
, LOWORD(lpCaption
), szTitle
, sizeof(szTitle
)/sizeof(szTitle
[0]));
4754 pszTitle
= lpCaption
;
4756 if (IS_INTRESOURCE(lpText
))
4759 UINT len
= LoadStringW(hInstance
, LOWORD(lpText
), (LPWSTR
)&ptr
, 0);
4763 szText
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
4764 if (szText
) LoadStringW(hInstance
, LOWORD(lpText
), szText
, len
+ 1);
4768 WARN("Failed to load id %d\n", LOWORD(lpText
));
4776 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
,
4777 pszText
, 0, 0, (LPWSTR
)&pszTemp
, 0, &args
);
4781 ret
= MessageBoxW(hWnd
, pszTemp
, pszTitle
, uType
);
4783 HeapFree(GetProcessHeap(), 0, szText
);
4788 /***********************************************************************
4789 * ZoneComputePaneSize [SHLWAPI.382]
4791 UINT WINAPI
ZoneComputePaneSize(HWND hwnd
)
4797 /***********************************************************************
4798 * SHChangeNotifyWrap [SHLWAPI.394]
4800 void WINAPI
SHChangeNotifyWrap(LONG wEventId
, UINT uFlags
, LPCVOID dwItem1
, LPCVOID dwItem2
)
4802 SHChangeNotify(wEventId
, uFlags
, dwItem1
, dwItem2
);
4805 typedef struct SHELL_USER_SID
{ /* according to MSDN this should be in shlobj.h... */
4806 SID_IDENTIFIER_AUTHORITY sidAuthority
;
4807 DWORD dwUserGroupID
;
4809 } SHELL_USER_SID
, *PSHELL_USER_SID
;
4811 typedef struct SHELL_USER_PERMISSION
{ /* ...and this should be in shlwapi.h */
4812 SHELL_USER_SID susID
;
4816 DWORD dwInheritMask
;
4817 DWORD dwInheritAccessMask
;
4818 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
4820 /***********************************************************************
4821 * GetShellSecurityDescriptor [SHLWAPI.475]
4823 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4826 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4827 * each of which describes permissions to apply
4828 * cUserPerm [I] number of entries in apUserPerm array
4831 * success: pointer to SECURITY_DESCRIPTOR
4835 * Call should free returned descriptor with LocalFree
4837 PSECURITY_DESCRIPTOR WINAPI
GetShellSecurityDescriptor(PSHELL_USER_PERMISSION
*apUserPerm
, int cUserPerm
)
4840 PSID cur_user
= NULL
;
4844 PSECURITY_DESCRIPTOR psd
= NULL
;
4846 TRACE("%p %d\n", apUserPerm
, cUserPerm
);
4848 if (apUserPerm
== NULL
|| cUserPerm
<= 0)
4851 sidlist
= HeapAlloc(GetProcessHeap(), 0, cUserPerm
* sizeof(PSID
));
4855 acl_size
= sizeof(ACL
);
4857 for(sid_count
= 0; sid_count
< cUserPerm
; sid_count
++)
4859 static SHELL_USER_SID null_sid
= {{SECURITY_NULL_SID_AUTHORITY
}, 0, 0};
4860 PSHELL_USER_PERMISSION perm
= apUserPerm
[sid_count
];
4861 PSHELL_USER_SID sid
= &perm
->susID
;
4865 if (!memcmp((void*)sid
, (void*)&null_sid
, sizeof(SHELL_USER_SID
)))
4866 { /* current user's SID */
4870 DWORD bufsize
= sizeof(tuUser
);
4872 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &Token
);
4875 ret
= GetTokenInformation(Token
, TokenUser
, (void*)tuUser
, bufsize
, &bufsize
);
4877 cur_user
= ((PTOKEN_USER
)tuUser
)->User
.Sid
;
4882 } else if (sid
->dwUserID
==0) /* one sub-authority */
4883 ret
= AllocateAndInitializeSid(&sid
->sidAuthority
, 1, sid
->dwUserGroupID
, 0,
4884 0, 0, 0, 0, 0, 0, &pSid
);
4886 ret
= AllocateAndInitializeSid(&sid
->sidAuthority
, 2, sid
->dwUserGroupID
, sid
->dwUserID
,
4887 0, 0, 0, 0, 0, 0, &pSid
);
4891 sidlist
[sid_count
] = pSid
;
4892 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4893 acl_size
+= (sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
) + GetLengthSid(pSid
)) * (perm
->fInherit
? 2 : 1);
4896 psd
= LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR
) + acl_size
);
4900 PACL pAcl
= (PACL
)(((BYTE
*)psd
)+sizeof(SECURITY_DESCRIPTOR
));
4902 if (!InitializeSecurityDescriptor(psd
, SECURITY_DESCRIPTOR_REVISION
))
4905 if (!InitializeAcl(pAcl
, acl_size
, ACL_REVISION
))
4908 for(i
= 0; i
< sid_count
; i
++)
4910 PSHELL_USER_PERMISSION sup
= apUserPerm
[i
];
4911 PSID sid
= sidlist
[i
];
4913 switch(sup
->dwAccessType
)
4915 case ACCESS_ALLOWED_ACE_TYPE
:
4916 if (!AddAccessAllowedAce(pAcl
, ACL_REVISION
, sup
->dwAccessMask
, sid
))
4918 if (sup
->fInherit
&& !AddAccessAllowedAceEx(pAcl
, ACL_REVISION
,
4919 (BYTE
)sup
->dwInheritMask
, sup
->dwInheritAccessMask
, sid
))
4922 case ACCESS_DENIED_ACE_TYPE
:
4923 if (!AddAccessDeniedAce(pAcl
, ACL_REVISION
, sup
->dwAccessMask
, sid
))
4925 if (sup
->fInherit
&& !AddAccessDeniedAceEx(pAcl
, ACL_REVISION
,
4926 (BYTE
)sup
->dwInheritMask
, sup
->dwInheritAccessMask
, sid
))
4934 if (!SetSecurityDescriptorDacl(psd
, TRUE
, pAcl
, FALSE
))
4943 for(i
= 0; i
< sid_count
; i
++)
4945 if (!cur_user
|| sidlist
[i
] != cur_user
)
4946 FreeSid(sidlist
[i
]);
4948 HeapFree(GetProcessHeap(), 0, sidlist
);
4953 /***********************************************************************
4954 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4956 * Creates a property bag from a registry key
4959 * hKey [I] Handle to the desired registry key
4960 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4961 * grfMode [I] Optional flags
4962 * riid [I] IID of requested property bag interface
4963 * ppv [O] Address to receive pointer to the new interface
4967 * failure: error code
4970 HRESULT WINAPI
SHCreatePropertyBagOnRegKey (HKEY hKey
, LPCWSTR subkey
,
4971 DWORD grfMode
, REFIID riid
, void **ppv
)
4973 FIXME("%p %s %d %s %p STUB\n", hKey
, debugstr_w(subkey
), grfMode
,
4974 debugstr_guid(riid
), ppv
);
4979 /***********************************************************************
4980 * SHGetViewStatePropertyBag [SHLWAPI.515]
4982 * Retrieves a property bag in which the view state information of a folder
4986 * pidl [I] PIDL of the folder requested
4987 * bag_name [I] Name of the property bag requested
4988 * flags [I] Optional flags
4989 * riid [I] IID of requested property bag interface
4990 * ppv [O] Address to receive pointer to the new interface
4994 * failure: error code
4997 HRESULT WINAPI
SHGetViewStatePropertyBag(LPCITEMIDLIST pidl
, LPWSTR bag_name
,
4998 DWORD flags
, REFIID riid
, void **ppv
)
5000 FIXME("%p %s %d %s %p STUB\n", pidl
, debugstr_w(bag_name
), flags
,
5001 debugstr_guid(riid
), ppv
);
5006 /***********************************************************************
5007 * SHFormatDateTimeW [SHLWAPI.354]
5009 * Produces a string representation of a time.
5012 * fileTime [I] Pointer to FILETIME structure specifying the time
5013 * flags [I] Flags specifying the desired output
5014 * buf [O] Pointer to buffer for output
5015 * size [I] Number of characters that can be contained in buffer
5018 * success: number of characters written to the buffer
5022 INT WINAPI
SHFormatDateTimeW(const FILETIME UNALIGNED
*fileTime
, DWORD
*flags
,
5023 LPWSTR buf
, UINT size
)
5025 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
5026 DWORD fmt_flags
= flags
? *flags
: FDTF_DEFAULT
;
5031 TRACE("%p %p %p %u\n", fileTime
, flags
, buf
, size
);
5036 if (fmt_flags
& SHFORMATDT_UNSUPPORTED_FLAGS
)
5037 FIXME("ignoring some flags - 0x%08x\n", fmt_flags
& SHFORMATDT_UNSUPPORTED_FLAGS
);
5039 FileTimeToLocalFileTime(fileTime
, &ft
);
5040 FileTimeToSystemTime(&ft
, &st
);
5042 /* first of all date */
5043 if (fmt_flags
& (FDTF_LONGDATE
| FDTF_SHORTDATE
))
5045 static const WCHAR sep1
[] = {',',' ',0};
5046 static const WCHAR sep2
[] = {' ',0};
5048 DWORD date
= fmt_flags
& FDTF_LONGDATE
? DATE_LONGDATE
: DATE_SHORTDATE
;
5049 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, date
, &st
, NULL
, buf
, size
);
5050 if (ret
>= size
) return ret
;
5053 if (ret
< size
&& (fmt_flags
& (FDTF_LONGTIME
| FDTF_SHORTTIME
)))
5055 if ((fmt_flags
& FDTF_LONGDATE
) && (ret
< size
+ 2))
5057 lstrcatW(&buf
[ret
-1], sep1
);
5062 lstrcatW(&buf
[ret
-1], sep2
);
5068 if (fmt_flags
& (FDTF_LONGTIME
| FDTF_SHORTTIME
))
5070 DWORD time
= fmt_flags
& FDTF_LONGTIME
? 0 : TIME_NOSECONDS
;
5073 ret
+= GetTimeFormatW(LOCALE_USER_DEFAULT
, time
, &st
, NULL
, &buf
[ret
], size
- ret
);
5078 #undef SHFORMATDT_UNSUPPORTED_FLAGS
5081 /***********************************************************************
5082 * SHFormatDateTimeA [SHLWAPI.353]
5084 * See SHFormatDateTimeW.
5087 INT WINAPI
SHFormatDateTimeA(const FILETIME UNALIGNED
*fileTime
, DWORD
*flags
,
5088 LPSTR buf
, UINT size
)
5096 bufW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * size
);
5097 retval
= SHFormatDateTimeW(fileTime
, flags
, bufW
, size
);
5100 WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, buf
, size
, NULL
, NULL
);
5102 HeapFree(GetProcessHeap(), 0, bufW
);
5106 /***********************************************************************
5107 * ZoneCheckUrlExW [SHLWAPI.231]
5109 * Checks the details of the security zone for the supplied site. (?)
5113 * szURL [I] Pointer to the URL to check
5115 * Other parameters currently unknown.
5121 INT WINAPI
ZoneCheckUrlExW(LPWSTR szURL
, PVOID pUnknown
, DWORD dwUnknown2
,
5122 DWORD dwUnknown3
, DWORD dwUnknown4
, DWORD dwUnknown5
, DWORD dwUnknown6
,
5125 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL
), pUnknown
, dwUnknown2
,
5126 dwUnknown3
, dwUnknown4
, dwUnknown5
, dwUnknown6
, dwUnknown7
);
5131 /***********************************************************************
5132 * SHVerbExistsNA [SHLWAPI.196]
5137 * verb [I] a string, often appears to be an extension.
5139 * Other parameters currently unknown.
5144 INT WINAPI
SHVerbExistsNA(LPSTR verb
, PVOID pUnknown
, PVOID pUnknown2
, DWORD dwUnknown3
)
5146 FIXME("(%s, %p, %p, %i) STUB\n",verb
, pUnknown
, pUnknown2
, dwUnknown3
);
5150 /*************************************************************************
5153 * Undocumented: Implementation guessed at via Name and behavior
5156 * lpUnknown [I] Object to get an IServiceProvider interface from
5157 * riid [I] Function requested for QueryService call
5158 * lppOut [O] Destination for the service interface pointer
5161 * Success: S_OK. lppOut contains an object providing the requested service
5162 * Failure: An HRESULT error code
5165 * lpUnknown is expected to support the IServiceProvider interface.
5167 HRESULT WINAPI
IUnknown_QueryServiceForWebBrowserApp(IUnknown
* lpUnknown
,
5168 REFGUID riid
, LPVOID
*lppOut
)
5170 FIXME("%p %s %p semi-STUB\n", lpUnknown
, debugstr_guid(riid
), lppOut
);
5171 return IUnknown_QueryService(lpUnknown
,&IID_IWebBrowserApp
,riid
,lppOut
);
5174 /**************************************************************************
5175 * SHPropertyBag_ReadLONG (SHLWAPI.496)
5177 * This function asks a property bag to read a named property as a LONG.
5180 * ppb: a IPropertyBag interface
5181 * pszPropName: Unicode string that names the property
5182 * pValue: address to receive the property value as a 32-bit signed integer
5187 BOOL WINAPI
SHPropertyBag_ReadLONG(IPropertyBag
*ppb
, LPCWSTR pszPropName
, LPLONG pValue
)
5191 TRACE("%p %s %p\n", ppb
,debugstr_w(pszPropName
),pValue
);
5192 if (!pszPropName
|| !ppb
|| !pValue
)
5193 return E_INVALIDARG
;
5195 hr
= IPropertyBag_Read(ppb
, pszPropName
, &var
, NULL
);
5198 if (V_VT(&var
) == VT_I4
)
5199 *pValue
= V_I4(&var
);
5201 hr
= DISP_E_BADVARTYPE
;
5206 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
5207 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
5208 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
5209 #define OBJCOMPAT_UNBINDABLE 0x00000004
5210 #define OBJCOMPAT_PINDLL 0x00000008
5211 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
5212 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
5213 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
5214 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
5215 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
5216 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
5217 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
5218 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
5219 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
5221 /* a search table for compatibility flags */
5222 struct objcompat_entry
{
5223 const WCHAR name
[30];
5227 /* expected to be sorted by name */
5228 static const struct objcompat_entry objcompat_table
[] = {
5229 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
5230 OBJCOMPAT_COCREATESHELLFOLDERONLY
},
5231 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
5232 OBJCOMPAT_CTXMENU_LIMITEDQI
},
5233 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
5234 OBJCOMPAT_CTXMENU_LIMITEDQI
},
5235 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
5236 OBJCOMPAT_CTXMENU_XPQCMFLAGS
},
5237 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
5238 OBJCOMPAT_NEEDSFILESYSANCESTOR
},
5239 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
5240 OBJCOMPAT_NEEDSSTORAGEANCESTOR
},
5241 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
5242 OBJCOMPAT_NOIPROPERTYSTORE
},
5243 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
5244 OBJCOMPAT_NOLEGACYWEBVIEW
},
5245 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
5246 OBJCOMPAT_NOTAFILESYSTEM
},
5247 { {'N','O','_','W','E','B','V','I','E','W',0},
5248 OBJCOMPAT_NO_WEBVIEW
},
5249 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
5250 OBJCOMPAT_OTNEEDSSFCACHE
},
5251 { {'P','I','N','D','L','L',0},
5253 { {'U','N','B','I','N','D','A','B','L','E',0},
5254 OBJCOMPAT_UNBINDABLE
}
5257 /**************************************************************************
5258 * SHGetObjectCompatFlags (SHLWAPI.476)
5260 * Function returns an integer representation of compatibility flags stored
5261 * in registry for CLSID under ShellCompatibility subkey.
5264 * pUnk: pointer to object IUnknown interface, idetifies CLSID
5265 * clsid: pointer to CLSID to retrieve data for
5268 * 0 on failure, flags set on success
5270 DWORD WINAPI
SHGetObjectCompatFlags(IUnknown
*pUnk
, const CLSID
*clsid
)
5272 static const WCHAR compatpathW
[] =
5273 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
5274 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
5275 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
5276 'O','b','j','e','c','t','s','\\','%','s',0};
5277 WCHAR strW
[sizeof(compatpathW
)/sizeof(WCHAR
) + 38 /* { CLSID } */];
5278 DWORD ret
, length
= sizeof(strW
)/sizeof(WCHAR
);
5283 TRACE("%p %s\n", pUnk
, debugstr_guid(clsid
));
5285 if (!pUnk
&& !clsid
) return 0;
5289 FIXME("iface not handled\n");
5293 StringFromCLSID(clsid
, &clsid_str
);
5294 sprintfW(strW
, compatpathW
, clsid_str
);
5295 CoTaskMemFree(clsid_str
);
5297 ret
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, strW
, &key
);
5298 if (ret
!= ERROR_SUCCESS
) return 0;
5300 /* now collect flag values */
5302 for (i
= 0; RegEnumValueW(key
, i
, strW
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; i
++)
5304 INT left
, right
, res
, x
;
5306 /* search in table */
5308 right
= sizeof(objcompat_table
) / sizeof(struct objcompat_entry
) - 1;
5310 while (right
>= left
) {
5311 x
= (left
+ right
) / 2;
5312 res
= strcmpW(strW
, objcompat_table
[x
].name
);
5315 ret
|= objcompat_table
[x
].value
;
5324 length
= sizeof(strW
)/sizeof(WCHAR
);