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
30 #include <shdeprecated.h>
36 /* DLL handles for late bound calls */
37 extern HINSTANCE shlwapi_hInstance
;
38 extern DWORD SHLWAPI_ThreadRef_index
;
40 HRESULT WINAPI
IUnknown_QueryService(IUnknown
*,REFGUID
,REFIID
,LPVOID
*);
41 HRESULT WINAPI
SHInvokeCommand(HWND
,IShellFolder
*,LPCITEMIDLIST
,DWORD
);
42 BOOL WINAPI
SHAboutInfoW(LPWSTR
,DWORD
);
45 NOTES: Most functions exported by ordinal seem to be superfluous.
46 The reason for these functions to be there is to provide a wrapper
47 for unicode functions to provide these functions on systems without
48 unicode functions eg. win95/win98. Since we have such functions we just
49 call these. If running Wine with native DLLs, some late bound calls may
50 fail. However, it is better to implement the functions in the forward DLL
51 and recommend the builtin rather than reimplementing the calls here!
54 /*************************************************************************
57 * Copy a sharable memory handle from one process to another.
60 * hShared [I] Shared memory handle to duplicate
61 * dwSrcProcId [I] ID of the process owning hShared
62 * dwDstProcId [I] ID of the process wanting the duplicated handle
63 * dwAccess [I] Desired DuplicateHandle() access
64 * dwOptions [I] Desired DuplicateHandle() options
67 * Success: A handle suitable for use by the dwDstProcId process.
68 * Failure: A NULL handle.
71 HANDLE WINAPI
SHMapHandle(HANDLE hShared
, DWORD dwSrcProcId
, DWORD dwDstProcId
,
72 DWORD dwAccess
, DWORD dwOptions
)
75 DWORD dwMyProcId
= GetCurrentProcessId();
78 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared
, dwDstProcId
, dwSrcProcId
,
83 TRACE("Returning handle NULL\n");
87 /* Get dest process handle */
88 if (dwDstProcId
== dwMyProcId
)
89 hDst
= GetCurrentProcess();
91 hDst
= OpenProcess(PROCESS_DUP_HANDLE
, 0, dwDstProcId
);
95 /* Get src process handle */
96 if (dwSrcProcId
== dwMyProcId
)
97 hSrc
= GetCurrentProcess();
99 hSrc
= OpenProcess(PROCESS_DUP_HANDLE
, 0, dwSrcProcId
);
103 /* Make handle available to dest process */
104 if (!DuplicateHandle(hSrc
, hShared
, hDst
, &hRet
,
105 dwAccess
, 0, dwOptions
| DUPLICATE_SAME_ACCESS
))
108 if (dwSrcProcId
!= dwMyProcId
)
112 if (dwDstProcId
!= dwMyProcId
)
116 TRACE("Returning handle %p\n", hRet
);
120 /*************************************************************************
123 * Create a block of sharable memory and initialise it with data.
126 * lpvData [I] Pointer to data to write
127 * dwSize [I] Size of data
128 * dwProcId [I] ID of process owning data
131 * Success: A shared memory handle
135 * Ordinals 7-11 provide a set of calls to create shared memory between a
136 * group of processes. The shared memory is treated opaquely in that its size
137 * is not exposed to clients who map it. This is accomplished by storing
138 * the size of the map as the first DWORD of mapped data, and then offsetting
139 * the view pointer returned by this size.
142 HANDLE WINAPI
SHAllocShared(LPCVOID lpvData
, DWORD dwSize
, DWORD dwProcId
)
148 TRACE("(%p,%d,%d)\n", lpvData
, dwSize
, dwProcId
);
150 /* Create file mapping of the correct length */
151 hMap
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, FILE_MAP_READ
, 0,
152 dwSize
+ sizeof(dwSize
), NULL
);
156 /* Get a view in our process address space */
157 pMapped
= MapViewOfFile(hMap
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
161 /* Write size of data, followed by the data, to the view */
162 *((DWORD
*)pMapped
) = dwSize
;
164 memcpy((char *) pMapped
+ sizeof(dwSize
), lpvData
, dwSize
);
166 /* Release view. All further views mapped will be opaque */
167 UnmapViewOfFile(pMapped
);
168 hRet
= SHMapHandle(hMap
, GetCurrentProcessId(), dwProcId
,
169 FILE_MAP_ALL_ACCESS
, DUPLICATE_SAME_ACCESS
);
176 /*************************************************************************
179 * Get a pointer to a block of shared memory from a shared memory handle.
182 * hShared [I] Shared memory handle
183 * dwProcId [I] ID of process owning hShared
186 * Success: A pointer to the shared memory
190 PVOID WINAPI
SHLockShared(HANDLE hShared
, DWORD dwProcId
)
195 TRACE("(%p %d)\n", hShared
, dwProcId
);
197 /* Get handle to shared memory for current process */
198 hDup
= SHMapHandle(hShared
, dwProcId
, GetCurrentProcessId(), FILE_MAP_ALL_ACCESS
, 0);
201 pMapped
= MapViewOfFile(hDup
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
205 return (char *) pMapped
+ sizeof(DWORD
); /* Hide size */
209 /*************************************************************************
212 * Release a pointer to a block of shared memory.
215 * lpView [I] Shared memory pointer
222 BOOL WINAPI
SHUnlockShared(LPVOID lpView
)
224 TRACE("(%p)\n", lpView
);
225 return UnmapViewOfFile((char *) lpView
- sizeof(DWORD
)); /* Include size */
228 /*************************************************************************
231 * Destroy a block of sharable memory.
234 * hShared [I] Shared memory handle
235 * dwProcId [I] ID of process owning hShared
242 BOOL WINAPI
SHFreeShared(HANDLE hShared
, DWORD dwProcId
)
246 TRACE("(%p %d)\n", hShared
, dwProcId
);
251 /* Get a copy of the handle for our process, closing the source handle */
252 hClose
= SHMapHandle(hShared
, dwProcId
, GetCurrentProcessId(),
253 FILE_MAP_ALL_ACCESS
,DUPLICATE_CLOSE_SOURCE
);
254 /* Close local copy */
255 return CloseHandle(hClose
);
258 /*************************************************************************
261 * Create and register a clipboard enumerator for a web browser.
264 * lpBC [I] Binding context
265 * lpUnknown [I] An object exposing the IWebBrowserApp interface
269 * Failure: An HRESULT error code.
272 * The enumerator is stored as a property of the web browser. If it does not
273 * yet exist, it is created and set before being registered.
275 HRESULT WINAPI
RegisterDefaultAcceptHeaders(LPBC lpBC
, IUnknown
*lpUnknown
)
277 static const WCHAR szProperty
[] = { '{','D','0','F','C','A','4','2','0',
278 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
279 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
281 IEnumFORMATETC
* pIEnumFormatEtc
= NULL
;
284 IWebBrowserApp
* pBrowser
;
286 TRACE("(%p, %p)\n", lpBC
, lpUnknown
);
288 hr
= IUnknown_QueryService(lpUnknown
, &IID_IWebBrowserApp
, &IID_IWebBrowserApp
, (void**)&pBrowser
);
292 V_VT(&var
) = VT_EMPTY
;
294 /* The property we get is the browsers clipboard enumerator */
295 property
= SysAllocString(szProperty
);
296 hr
= IWebBrowserApp_GetProperty(pBrowser
, property
, &var
);
297 SysFreeString(property
);
298 if (FAILED(hr
)) goto exit
;
300 if (V_VT(&var
) == VT_EMPTY
)
302 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
303 char szKeyBuff
[128], szValueBuff
[128];
304 DWORD dwKeySize
, dwValueSize
, dwRet
= 0, dwCount
= 0, dwNumValues
, dwType
;
305 FORMATETC
* formatList
, *format
;
308 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
310 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\Current"
311 "Version\\Internet Settings\\Accepted Documents", &hDocs
))
317 /* Get count of values in key */
320 dwKeySize
= sizeof(szKeyBuff
);
321 dwRet
= RegEnumValueA(hDocs
,dwCount
,szKeyBuff
,&dwKeySize
,0,&dwType
,0,0);
325 dwNumValues
= dwCount
;
327 /* Note: dwCount = number of items + 1; The extra item is the end node */
328 format
= formatList
= HeapAlloc(GetProcessHeap(), 0, dwCount
* sizeof(FORMATETC
));
343 /* Register clipboard formats for the values and populate format list */
344 while(!dwRet
&& dwCount
< dwNumValues
)
346 dwKeySize
= sizeof(szKeyBuff
);
347 dwValueSize
= sizeof(szValueBuff
);
348 dwRet
= RegEnumValueA(hDocs
, dwCount
, szKeyBuff
, &dwKeySize
, 0, &dwType
,
349 (PBYTE
)szValueBuff
, &dwValueSize
);
352 HeapFree(GetProcessHeap(), 0, formatList
);
358 format
->cfFormat
= RegisterClipboardFormatA(szValueBuff
);
360 format
->dwAspect
= 1;
371 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
372 format
->cfFormat
= 0;
374 format
->dwAspect
= 1;
378 /* Create a clipboard enumerator */
379 hr
= CreateFormatEnumerator(dwNumValues
, formatList
, &pIEnumFormatEtc
);
380 HeapFree(GetProcessHeap(), 0, formatList
);
381 if (FAILED(hr
)) goto exit
;
383 /* Set our enumerator as the browsers property */
384 V_VT(&var
) = VT_UNKNOWN
;
385 V_UNKNOWN(&var
) = (IUnknown
*)pIEnumFormatEtc
;
387 property
= SysAllocString(szProperty
);
388 hr
= IWebBrowserApp_PutProperty(pBrowser
, property
, var
);
389 SysFreeString(property
);
392 IEnumFORMATETC_Release(pIEnumFormatEtc
);
397 if (V_VT(&var
) == VT_UNKNOWN
)
399 /* Our variant is holding the clipboard enumerator */
400 IUnknown
* pIUnknown
= V_UNKNOWN(&var
);
401 IEnumFORMATETC
* pClone
= NULL
;
403 TRACE("Retrieved IEnumFORMATETC property\n");
405 /* Get an IEnumFormatEtc interface from the variants value */
406 pIEnumFormatEtc
= NULL
;
407 hr
= IUnknown_QueryInterface(pIUnknown
, &IID_IEnumFORMATETC
, (void**)&pIEnumFormatEtc
);
408 if (hr
== S_OK
&& pIEnumFormatEtc
)
410 /* Clone and register the enumerator */
411 hr
= IEnumFORMATETC_Clone(pIEnumFormatEtc
, &pClone
);
412 if (hr
== S_OK
&& pClone
)
414 RegisterFormatEnumerator(lpBC
, pClone
, 0);
416 IEnumFORMATETC_Release(pClone
);
419 IUnknown_Release(pIUnknown
);
421 IUnknown_Release(V_UNKNOWN(&var
));
425 IWebBrowserApp_Release(pBrowser
);
429 /*************************************************************************
432 * Get Explorers "AcceptLanguage" setting.
435 * langbuf [O] Destination for language string
436 * buflen [I] Length of langbuf in characters
437 * [0] Success: used length of langbuf
440 * Success: S_OK. langbuf is set to the language string found.
441 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
442 * does not contain the setting.
443 * E_NOT_SUFFICIENT_BUFFER, If the buffer is not big enough
445 HRESULT WINAPI
GetAcceptLanguagesW( LPWSTR langbuf
, LPDWORD buflen
)
447 static const WCHAR szkeyW
[] = {
448 'S','o','f','t','w','a','r','e','\\',
449 'M','i','c','r','o','s','o','f','t','\\',
450 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
451 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
452 static const WCHAR valueW
[] = {
453 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
454 DWORD mystrlen
, mytype
;
461 TRACE("(%p, %p) *%p: %d\n", langbuf
, buflen
, buflen
, buflen
? *buflen
: -1);
463 if(!langbuf
|| !buflen
|| !*buflen
)
466 mystrlen
= (*buflen
> 20) ? *buflen
: 20 ;
467 len
= mystrlen
* sizeof(WCHAR
);
468 mystr
= HeapAlloc(GetProcessHeap(), 0, len
);
470 RegOpenKeyW(HKEY_CURRENT_USER
, szkeyW
, &mykey
);
471 lres
= RegQueryValueExW(mykey
, valueW
, 0, &mytype
, (PBYTE
)mystr
, &len
);
473 len
= lstrlenW(mystr
);
475 if (!lres
&& (*buflen
> len
)) {
476 lstrcpyW(langbuf
, mystr
);
478 HeapFree(GetProcessHeap(), 0, mystr
);
482 /* Did not find a value in the registry or the user buffer is too small */
483 mylcid
= GetUserDefaultLCID();
484 LcidToRfc1766W(mylcid
, mystr
, mystrlen
);
485 len
= lstrlenW(mystr
);
487 memcpy( langbuf
, mystr
, min(*buflen
, len
+1)*sizeof(WCHAR
) );
488 HeapFree(GetProcessHeap(), 0, mystr
);
496 return E_NOT_SUFFICIENT_BUFFER
;
499 /*************************************************************************
502 * Ascii version of GetAcceptLanguagesW.
504 HRESULT WINAPI
GetAcceptLanguagesA( LPSTR langbuf
, LPDWORD buflen
)
507 DWORD buflenW
, convlen
;
510 TRACE("(%p, %p) *%p: %d\n", langbuf
, buflen
, buflen
, buflen
? *buflen
: -1);
512 if(!langbuf
|| !buflen
|| !*buflen
) return E_FAIL
;
515 langbufW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * buflenW
);
516 retval
= GetAcceptLanguagesW(langbufW
, &buflenW
);
520 convlen
= WideCharToMultiByte(CP_ACP
, 0, langbufW
, -1, langbuf
, *buflen
, NULL
, NULL
);
521 convlen
--; /* do not count the terminating 0 */
523 else /* copy partial string anyway */
525 convlen
= WideCharToMultiByte(CP_ACP
, 0, langbufW
, *buflen
, langbuf
, *buflen
, NULL
, NULL
);
526 if (convlen
< *buflen
)
528 langbuf
[convlen
] = 0;
529 convlen
--; /* do not count the terminating 0 */
536 *buflen
= buflenW
? convlen
: 0;
538 HeapFree(GetProcessHeap(), 0, langbufW
);
542 /*************************************************************************
545 * Convert a GUID to a string.
548 * guid [I] GUID to convert
549 * lpszDest [O] Destination for string
550 * cchMax [I] Length of output buffer
553 * The length of the string created.
555 INT WINAPI
SHStringFromGUIDA(REFGUID guid
, LPSTR lpszDest
, INT cchMax
)
560 TRACE("(%s,%p,%d)\n", debugstr_guid(guid
), lpszDest
, cchMax
);
562 sprintf(xguid
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
563 guid
->Data1
, guid
->Data2
, guid
->Data3
,
564 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
565 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
567 iLen
= strlen(xguid
) + 1;
571 memcpy(lpszDest
, xguid
, iLen
);
575 /*************************************************************************
578 * Convert a GUID to a string.
581 * guid [I] GUID to convert
582 * str [O] Destination for string
583 * cmax [I] Length of output buffer
586 * The length of the string created.
588 INT WINAPI
SHStringFromGUIDW(REFGUID guid
, LPWSTR lpszDest
, INT cchMax
)
592 static const WCHAR wszFormat
[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
593 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
594 'X','%','0','2','X','%','0','2','X','}',0};
596 TRACE("(%s,%p,%d)\n", debugstr_guid(guid
), lpszDest
, cchMax
);
598 sprintfW(xguid
, wszFormat
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
599 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
600 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
602 iLen
= strlenW(xguid
) + 1;
606 memcpy(lpszDest
, xguid
, iLen
*sizeof(WCHAR
));
610 /*************************************************************************
613 * Determine if a Unicode character is a blank.
616 * wc [I] Character to check.
619 * TRUE, if wc is a blank,
623 BOOL WINAPI
IsCharBlankW(WCHAR wc
)
627 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_BLANK
);
630 /*************************************************************************
633 * Determine if a Unicode character is punctuation.
636 * wc [I] Character to check.
639 * TRUE, if wc is punctuation,
642 BOOL WINAPI
IsCharPunctW(WCHAR wc
)
646 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_PUNCT
);
649 /*************************************************************************
652 * Determine if a Unicode character is a control character.
655 * wc [I] Character to check.
658 * TRUE, if wc is a control character,
661 BOOL WINAPI
IsCharCntrlW(WCHAR wc
)
665 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_CNTRL
);
668 /*************************************************************************
671 * Determine if a Unicode character is a digit.
674 * wc [I] Character to check.
677 * TRUE, if wc is a digit,
680 BOOL WINAPI
IsCharDigitW(WCHAR wc
)
684 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_DIGIT
);
687 /*************************************************************************
690 * Determine if a Unicode character is a hex digit.
693 * wc [I] Character to check.
696 * TRUE, if wc is a hex digit,
699 BOOL WINAPI
IsCharXDigitW(WCHAR wc
)
703 return GetStringTypeW(CT_CTYPE1
, &wc
, 1, &CharType
) && (CharType
& C1_XDIGIT
);
706 /*************************************************************************
710 BOOL WINAPI
GetStringType3ExW(LPWSTR src
, INT count
, LPWORD type
)
712 return GetStringTypeW(CT_CTYPE3
, src
, count
, type
);
715 /*************************************************************************
718 * Compare two Ascii strings up to a given length.
721 * lpszSrc [I] Source string
722 * lpszCmp [I] String to compare to lpszSrc
723 * len [I] Maximum length
726 * A number greater than, less than or equal to 0 depending on whether
727 * lpszSrc is greater than, less than or equal to lpszCmp.
729 DWORD WINAPI
StrCmpNCA(LPCSTR lpszSrc
, LPCSTR lpszCmp
, INT len
)
731 return StrCmpNA(lpszSrc
, lpszCmp
, len
);
734 /*************************************************************************
737 * Unicode version of StrCmpNCA.
739 DWORD WINAPI
StrCmpNCW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
, INT len
)
741 return StrCmpNW(lpszSrc
, lpszCmp
, len
);
744 /*************************************************************************
747 * Compare two Ascii strings up to a given length, ignoring case.
750 * lpszSrc [I] Source string
751 * lpszCmp [I] String to compare to lpszSrc
752 * len [I] Maximum length
755 * A number greater than, less than or equal to 0 depending on whether
756 * lpszSrc is greater than, less than or equal to lpszCmp.
758 DWORD WINAPI
StrCmpNICA(LPCSTR lpszSrc
, LPCSTR lpszCmp
, DWORD len
)
760 return StrCmpNIA(lpszSrc
, lpszCmp
, len
);
763 /*************************************************************************
766 * Unicode version of StrCmpNICA.
768 DWORD WINAPI
StrCmpNICW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
, DWORD len
)
770 return StrCmpNIW(lpszSrc
, lpszCmp
, len
);
773 /*************************************************************************
776 * Compare two Ascii strings.
779 * lpszSrc [I] Source string
780 * lpszCmp [I] String to compare to lpszSrc
783 * A number greater than, less than or equal to 0 depending on whether
784 * lpszSrc is greater than, less than or equal to lpszCmp.
786 DWORD WINAPI
StrCmpCA(LPCSTR lpszSrc
, LPCSTR lpszCmp
)
788 return lstrcmpA(lpszSrc
, lpszCmp
);
791 /*************************************************************************
794 * Unicode version of StrCmpCA.
796 DWORD WINAPI
StrCmpCW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
)
798 return lstrcmpW(lpszSrc
, lpszCmp
);
801 /*************************************************************************
804 * Compare two Ascii strings, ignoring case.
807 * lpszSrc [I] Source string
808 * lpszCmp [I] String to compare to lpszSrc
811 * A number greater than, less than or equal to 0 depending on whether
812 * lpszSrc is greater than, less than or equal to lpszCmp.
814 DWORD WINAPI
StrCmpICA(LPCSTR lpszSrc
, LPCSTR lpszCmp
)
816 return lstrcmpiA(lpszSrc
, lpszCmp
);
819 /*************************************************************************
822 * Unicode version of StrCmpICA.
824 DWORD WINAPI
StrCmpICW(LPCWSTR lpszSrc
, LPCWSTR lpszCmp
)
826 return lstrcmpiW(lpszSrc
, lpszCmp
);
829 /*************************************************************************
832 * Get an identification string for the OS and explorer.
835 * lpszDest [O] Destination for Id string
836 * dwDestLen [I] Length of lpszDest
839 * TRUE, If the string was created successfully
842 BOOL WINAPI
SHAboutInfoA(LPSTR lpszDest
, DWORD dwDestLen
)
846 TRACE("(%p,%d)\n", lpszDest
, dwDestLen
);
848 if (lpszDest
&& SHAboutInfoW(buff
, dwDestLen
))
850 WideCharToMultiByte(CP_ACP
, 0, buff
, -1, lpszDest
, dwDestLen
, NULL
, NULL
);
856 /*************************************************************************
859 * Unicode version of SHAboutInfoA.
861 BOOL WINAPI
SHAboutInfoW(LPWSTR lpszDest
, DWORD dwDestLen
)
863 static const WCHAR szIEKey
[] = { 'S','O','F','T','W','A','R','E','\\',
864 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
865 ' ','E','x','p','l','o','r','e','r','\0' };
866 static const WCHAR szWinNtKey
[] = { 'S','O','F','T','W','A','R','E','\\',
867 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
868 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
869 static const WCHAR szWinKey
[] = { 'S','O','F','T','W','A','R','E','\\',
870 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
871 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
872 static const WCHAR szRegKey
[] = { 'S','O','F','T','W','A','R','E','\\',
873 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
874 ' ','E','x','p','l','o','r','e','r','\\',
875 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
876 static const WCHAR szVersion
[] = { 'V','e','r','s','i','o','n','\0' };
877 static const WCHAR szCustomized
[] = { 'C','u','s','t','o','m','i','z','e','d',
878 'V','e','r','s','i','o','n','\0' };
879 static const WCHAR szOwner
[] = { 'R','e','g','i','s','t','e','r','e','d',
880 'O','w','n','e','r','\0' };
881 static const WCHAR szOrg
[] = { 'R','e','g','i','s','t','e','r','e','d',
882 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
883 static const WCHAR szProduct
[] = { 'P','r','o','d','u','c','t','I','d','\0' };
884 static const WCHAR szUpdate
[] = { 'I','E','A','K',
885 'U','p','d','a','t','e','U','r','l','\0' };
886 static const WCHAR szHelp
[] = { 'I','E','A','K',
887 'H','e','l','p','S','t','r','i','n','g','\0' };
892 TRACE("(%p,%d)\n", lpszDest
, dwDestLen
);
899 /* Try the NT key first, followed by 95/98 key */
900 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szWinNtKey
, 0, KEY_READ
, &hReg
) &&
901 RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szWinKey
, 0, KEY_READ
, &hReg
))
907 if (!SHGetValueW(HKEY_LOCAL_MACHINE
, szIEKey
, szVersion
, &dwType
, buff
, &dwLen
))
909 DWORD dwStrLen
= strlenW(buff
);
910 dwLen
= 30 - dwStrLen
;
911 SHGetValueW(HKEY_LOCAL_MACHINE
, szIEKey
,
912 szCustomized
, &dwType
, buff
+dwStrLen
, &dwLen
);
914 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
916 /* ~Registered Owner */
919 if (SHGetValueW(hReg
, szOwner
, 0, &dwType
, buff
+1, &dwLen
))
921 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
923 /* ~Registered Organization */
925 if (SHGetValueW(hReg
, szOrg
, 0, &dwType
, buff
+1, &dwLen
))
927 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
929 /* FIXME: Not sure where this number comes from */
933 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
937 if (SHGetValueW(HKEY_LOCAL_MACHINE
, szRegKey
, szProduct
, &dwType
, buff
+1, &dwLen
))
939 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
943 if(SHGetValueW(HKEY_LOCAL_MACHINE
, szWinKey
, szUpdate
, &dwType
, buff
+1, &dwLen
))
945 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
947 /* ~IE Help String */
949 if(SHGetValueW(hReg
, szHelp
, 0, &dwType
, buff
+1, &dwLen
))
951 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
957 /*************************************************************************
960 * Call IOleCommandTarget_QueryStatus() on an object.
963 * lpUnknown [I] Object supporting the IOleCommandTarget interface
964 * pguidCmdGroup [I] GUID for the command group
966 * prgCmds [O] Commands
967 * pCmdText [O] Command text
971 * Failure: E_FAIL, if lpUnknown is NULL.
972 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
973 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
975 HRESULT WINAPI
IUnknown_QueryStatus(IUnknown
* lpUnknown
, REFGUID pguidCmdGroup
,
976 ULONG cCmds
, OLECMD
*prgCmds
, OLECMDTEXT
* pCmdText
)
978 HRESULT hRet
= E_FAIL
;
980 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown
, pguidCmdGroup
, cCmds
, prgCmds
, pCmdText
);
984 IOleCommandTarget
* lpOle
;
986 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleCommandTarget
,
989 if (SUCCEEDED(hRet
) && lpOle
)
991 hRet
= IOleCommandTarget_QueryStatus(lpOle
, pguidCmdGroup
, cCmds
,
993 IOleCommandTarget_Release(lpOle
);
999 /*************************************************************************
1002 * Call IOleCommandTarget_Exec() on an object.
1005 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1006 * pguidCmdGroup [I] GUID for the command group
1010 * Failure: E_FAIL, if lpUnknown is NULL.
1011 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1012 * Otherwise, an error code from IOleCommandTarget_Exec().
1014 HRESULT WINAPI
IUnknown_Exec(IUnknown
* lpUnknown
, REFGUID pguidCmdGroup
,
1015 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
* pvaIn
,
1018 HRESULT hRet
= E_FAIL
;
1020 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown
, pguidCmdGroup
, nCmdID
,
1021 nCmdexecopt
, pvaIn
, pvaOut
);
1025 IOleCommandTarget
* lpOle
;
1027 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleCommandTarget
,
1029 if (SUCCEEDED(hRet
) && lpOle
)
1031 hRet
= IOleCommandTarget_Exec(lpOle
, pguidCmdGroup
, nCmdID
,
1032 nCmdexecopt
, pvaIn
, pvaOut
);
1033 IOleCommandTarget_Release(lpOle
);
1039 /*************************************************************************
1042 * Retrieve, modify, and re-set a value from a window.
1045 * hWnd [I] Window to get value from
1046 * offset [I] Offset of value
1047 * mask [I] Mask for flags
1048 * flags [I] Bits to set in window value
1051 * The new value as it was set, or 0 if any parameter is invalid.
1054 * Only bits specified in mask are affected - set if present in flags and
1057 LONG WINAPI
SHSetWindowBits(HWND hwnd
, INT offset
, UINT mask
, UINT flags
)
1059 LONG ret
= GetWindowLongW(hwnd
, offset
);
1060 LONG new_flags
= (flags
& mask
) | (ret
& ~mask
);
1062 TRACE("%p %d %x %x\n", hwnd
, offset
, mask
, flags
);
1064 if (new_flags
!= ret
)
1065 ret
= SetWindowLongW(hwnd
, offset
, new_flags
);
1069 /*************************************************************************
1072 * Change a window's parent.
1075 * hWnd [I] Window to change parent of
1076 * hWndParent [I] New parent window
1079 * The old parent of hWnd.
1082 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1083 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1085 HWND WINAPI
SHSetParentHwnd(HWND hWnd
, HWND hWndParent
)
1087 TRACE("%p, %p\n", hWnd
, hWndParent
);
1089 if(GetParent(hWnd
) == hWndParent
)
1093 SHSetWindowBits(hWnd
, GWL_STYLE
, WS_CHILD
| WS_POPUP
, WS_CHILD
);
1095 SHSetWindowBits(hWnd
, GWL_STYLE
, WS_CHILD
| WS_POPUP
, WS_POPUP
);
1097 return hWndParent
? SetParent(hWnd
, hWndParent
) : NULL
;
1100 /*************************************************************************
1103 * Locate and advise a connection point in an IConnectionPointContainer object.
1106 * lpUnkSink [I] Sink for the connection point advise call
1107 * riid [I] REFIID of connection point to advise
1108 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1109 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1110 * lpCookie [O] Pointer to connection point cookie
1111 * lppCP [O] Destination for the IConnectionPoint found
1114 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1115 * that was advised. The caller is responsible for releasing it.
1116 * Failure: E_FAIL, if any arguments are invalid.
1117 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1118 * Or an HRESULT error code if any call fails.
1120 HRESULT WINAPI
ConnectToConnectionPoint(IUnknown
* lpUnkSink
, REFIID riid
, BOOL fConnect
,
1121 IUnknown
* lpUnknown
, LPDWORD lpCookie
,
1122 IConnectionPoint
**lppCP
)
1125 IConnectionPointContainer
* lpContainer
;
1126 IConnectionPoint
*lpCP
;
1128 if(!lpUnknown
|| (fConnect
&& !lpUnkSink
))
1134 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IConnectionPointContainer
,
1135 (void**)&lpContainer
);
1136 if (SUCCEEDED(hRet
))
1138 hRet
= IConnectionPointContainer_FindConnectionPoint(lpContainer
, riid
, &lpCP
);
1140 if (SUCCEEDED(hRet
))
1143 hRet
= IConnectionPoint_Unadvise(lpCP
, *lpCookie
);
1145 hRet
= IConnectionPoint_Advise(lpCP
, lpUnkSink
, lpCookie
);
1150 if (lppCP
&& SUCCEEDED(hRet
))
1151 *lppCP
= lpCP
; /* Caller keeps the interface */
1153 IConnectionPoint_Release(lpCP
); /* Release it */
1156 IConnectionPointContainer_Release(lpContainer
);
1161 /*************************************************************************
1164 * Release an interface and zero a supplied pointer.
1167 * lpUnknown [I] Object to release
1172 void WINAPI
IUnknown_AtomicRelease(IUnknown
** lpUnknown
)
1174 TRACE("(%p)\n", lpUnknown
);
1176 if(!lpUnknown
|| !*lpUnknown
) return;
1178 TRACE("doing Release\n");
1180 IUnknown_Release(*lpUnknown
);
1184 /*************************************************************************
1187 * Skip '//' if present in a string.
1190 * lpszSrc [I] String to check for '//'
1193 * Success: The next character after the '//' or the string if not present
1194 * Failure: NULL, if lpszStr is NULL.
1196 LPCSTR WINAPI
PathSkipLeadingSlashesA(LPCSTR lpszSrc
)
1198 if (lpszSrc
&& lpszSrc
[0] == '/' && lpszSrc
[1] == '/')
1203 /*************************************************************************
1206 * Check if two interfaces come from the same object.
1209 * lpInt1 [I] Interface to check against lpInt2.
1210 * lpInt2 [I] Interface to check against lpInt1.
1213 * TRUE, If the interfaces come from the same object.
1216 BOOL WINAPI
SHIsSameObject(IUnknown
* lpInt1
, IUnknown
* lpInt2
)
1218 IUnknown
*lpUnknown1
, *lpUnknown2
;
1221 TRACE("(%p %p)\n", lpInt1
, lpInt2
);
1223 if (!lpInt1
|| !lpInt2
)
1226 if (lpInt1
== lpInt2
)
1229 if (IUnknown_QueryInterface(lpInt1
, &IID_IUnknown
, (void**)&lpUnknown1
) != S_OK
)
1232 if (IUnknown_QueryInterface(lpInt2
, &IID_IUnknown
, (void**)&lpUnknown2
) != S_OK
)
1234 IUnknown_Release(lpUnknown1
);
1238 ret
= lpUnknown1
== lpUnknown2
;
1240 IUnknown_Release(lpUnknown1
);
1241 IUnknown_Release(lpUnknown2
);
1246 /*************************************************************************
1249 * Get the window handle of an object.
1252 * lpUnknown [I] Object to get the window handle of
1253 * lphWnd [O] Destination for window handle
1256 * Success: S_OK. lphWnd contains the objects window handle.
1257 * Failure: An HRESULT error code.
1260 * lpUnknown is expected to support one of the following interfaces:
1261 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1263 HRESULT WINAPI
IUnknown_GetWindow(IUnknown
*lpUnknown
, HWND
*lphWnd
)
1266 HRESULT hRet
= E_FAIL
;
1268 TRACE("(%p,%p)\n", lpUnknown
, lphWnd
);
1273 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleWindow
, (void**)&lpOle
);
1277 hRet
= IUnknown_QueryInterface(lpUnknown
,&IID_IShellView
, (void**)&lpOle
);
1281 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInternetSecurityMgrSite
,
1286 if (SUCCEEDED(hRet
))
1288 /* Laziness here - Since GetWindow() is the first method for the above 3
1289 * interfaces, we use the same call for them all.
1291 hRet
= IOleWindow_GetWindow((IOleWindow
*)lpOle
, lphWnd
);
1292 IUnknown_Release(lpOle
);
1294 TRACE("Returning HWND=%p\n", *lphWnd
);
1300 /*************************************************************************
1303 * Call a SetOwner method of IShellService from specified object.
1306 * iface [I] Object that supports IShellService
1307 * pUnk [I] Argument for the SetOwner call
1310 * Corresponding return value from last call or E_FAIL for null input
1312 HRESULT WINAPI
IUnknown_SetOwner(IUnknown
*iface
, IUnknown
*pUnk
)
1314 IShellService
*service
;
1317 TRACE("(%p, %p)\n", iface
, pUnk
);
1319 if (!iface
) return E_FAIL
;
1321 hr
= IUnknown_QueryInterface(iface
, &IID_IShellService
, (void**)&service
);
1324 hr
= IShellService_SetOwner(service
, pUnk
);
1325 IShellService_Release(service
);
1331 /*************************************************************************
1334 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1338 HRESULT WINAPI
IUnknown_SetSite(
1339 IUnknown
*obj
, /* [in] OLE object */
1340 IUnknown
*site
) /* [in] Site interface */
1343 IObjectWithSite
*iobjwithsite
;
1344 IInternetSecurityManager
*isecmgr
;
1346 if (!obj
) return E_FAIL
;
1348 hr
= IUnknown_QueryInterface(obj
, &IID_IObjectWithSite
, (LPVOID
*)&iobjwithsite
);
1349 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr
, iobjwithsite
);
1352 hr
= IObjectWithSite_SetSite(iobjwithsite
, site
);
1353 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr
);
1354 IObjectWithSite_Release(iobjwithsite
);
1358 hr
= IUnknown_QueryInterface(obj
, &IID_IInternetSecurityManager
, (LPVOID
*)&isecmgr
);
1359 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr
, isecmgr
);
1360 if (FAILED(hr
)) return hr
;
1362 hr
= IInternetSecurityManager_SetSecuritySite(isecmgr
, (IInternetSecurityMgrSite
*)site
);
1363 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr
);
1364 IInternetSecurityManager_Release(isecmgr
);
1369 /*************************************************************************
1372 * Call IPersist_GetClassID() on an object.
1375 * lpUnknown [I] Object supporting the IPersist interface
1376 * clsid [O] Destination for Class Id
1379 * Success: S_OK. lpClassId contains the Class Id requested.
1380 * Failure: E_FAIL, If lpUnknown is NULL,
1381 * E_NOINTERFACE If lpUnknown does not support IPersist,
1382 * Or an HRESULT error code.
1384 HRESULT WINAPI
IUnknown_GetClassID(IUnknown
*lpUnknown
, CLSID
*clsid
)
1389 TRACE("(%p, %p)\n", lpUnknown
, clsid
);
1393 memset(clsid
, 0, sizeof(*clsid
));
1397 hr
= IUnknown_QueryInterface(lpUnknown
, &IID_IPersist
, (void**)&persist
);
1400 hr
= IUnknown_QueryInterface(lpUnknown
, &IID_IPersistFolder
, (void**)&persist
);
1405 hr
= IPersist_GetClassID(persist
, clsid
);
1406 IPersist_Release(persist
);
1410 /*************************************************************************
1413 * Retrieve a Service Interface from an object.
1416 * lpUnknown [I] Object to get an IServiceProvider interface from
1417 * sid [I] Service ID for IServiceProvider_QueryService() call
1418 * riid [I] Function requested for QueryService call
1419 * lppOut [O] Destination for the service interface pointer
1422 * Success: S_OK. lppOut contains an object providing the requested service
1423 * Failure: An HRESULT error code
1426 * lpUnknown is expected to support the IServiceProvider interface.
1428 HRESULT WINAPI
IUnknown_QueryService(IUnknown
* lpUnknown
, REFGUID sid
, REFIID riid
,
1431 IServiceProvider
* pService
= NULL
;
1442 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IServiceProvider
,
1443 (LPVOID
*)&pService
);
1445 if (hRet
== S_OK
&& pService
)
1447 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService
);
1449 /* Get a Service interface from the object */
1450 hRet
= IServiceProvider_QueryService(pService
, sid
, riid
, lppOut
);
1452 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService
, *lppOut
);
1454 IServiceProvider_Release(pService
);
1459 /*************************************************************************
1462 * Calls IOleCommandTarget::Exec() for specified service object.
1465 * lpUnknown [I] Object to get an IServiceProvider interface from
1466 * service [I] Service ID for IServiceProvider_QueryService() call
1467 * group [I] Group ID for IOleCommandTarget::Exec() call
1468 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1469 * cmdOpt [I] Options flags for command
1470 * pIn [I] Input arguments for command
1471 * pOut [O] Output arguments for command
1474 * Success: S_OK. lppOut contains an object providing the requested service
1475 * Failure: An HRESULT error code
1478 * lpUnknown is expected to support the IServiceProvider interface.
1480 HRESULT WINAPI
IUnknown_QueryServiceExec(IUnknown
*lpUnknown
, REFIID service
,
1481 const GUID
*group
, DWORD cmdId
, DWORD cmdOpt
, VARIANT
*pIn
, VARIANT
*pOut
)
1483 IOleCommandTarget
*target
;
1486 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown
, debugstr_guid(service
),
1487 debugstr_guid(group
), cmdId
, cmdOpt
, pIn
, pOut
);
1489 hr
= IUnknown_QueryService(lpUnknown
, service
, &IID_IOleCommandTarget
, (void**)&target
);
1492 hr
= IOleCommandTarget_Exec(target
, group
, cmdId
, cmdOpt
, pIn
, pOut
);
1493 IOleCommandTarget_Release(target
);
1496 TRACE("<-- hr=0x%08x\n", hr
);
1501 /*************************************************************************
1504 * Calls IProfferService methods to proffer/revoke specified service.
1507 * lpUnknown [I] Object to get an IServiceProvider interface from
1508 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1509 * pService [I] Service to proffer. If NULL ::Revoke is called
1510 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1513 * Success: S_OK. IProffer method returns S_OK
1514 * Failure: An HRESULT error code
1517 * lpUnknown is expected to support the IServiceProvider interface.
1519 HRESULT WINAPI
IUnknown_ProfferService(IUnknown
*lpUnknown
, REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
1521 IProfferService
*proffer
;
1524 TRACE("%p %s %p %p\n", lpUnknown
, debugstr_guid(service
), pService
, pCookie
);
1526 hr
= IUnknown_QueryService(lpUnknown
, &IID_IProfferService
, &IID_IProfferService
, (void**)&proffer
);
1530 hr
= IProfferService_ProfferService(proffer
, service
, pService
, pCookie
);
1533 hr
= IProfferService_RevokeService(proffer
, *pCookie
);
1537 IProfferService_Release(proffer
);
1543 /*************************************************************************
1546 * Call an object's UIActivateIO method.
1549 * unknown [I] Object to call the UIActivateIO method on
1550 * activate [I] Parameter for UIActivateIO call
1551 * msg [I] Parameter for UIActivateIO call
1554 * Success: Value of UI_ActivateIO call
1555 * Failure: An HRESULT error code
1558 * unknown is expected to support the IInputObject interface.
1560 HRESULT WINAPI
IUnknown_UIActivateIO(IUnknown
*unknown
, BOOL activate
, LPMSG msg
)
1562 IInputObject
* object
= NULL
;
1568 /* Get an IInputObject interface from the object */
1569 ret
= IUnknown_QueryInterface(unknown
, &IID_IInputObject
, (LPVOID
*) &object
);
1573 ret
= IInputObject_UIActivateIO(object
, activate
, msg
);
1574 IInputObject_Release(object
);
1580 /*************************************************************************
1583 * Loads a popup menu.
1586 * hInst [I] Instance handle
1587 * szName [I] Menu name
1593 BOOL WINAPI
SHLoadMenuPopup(HINSTANCE hInst
, LPCWSTR szName
)
1597 TRACE("%p %s\n", hInst
, debugstr_w(szName
));
1599 if ((hMenu
= LoadMenuW(hInst
, szName
)))
1601 if (GetSubMenu(hMenu
, 0))
1602 RemoveMenu(hMenu
, 0, MF_BYPOSITION
);
1610 typedef struct _enumWndData
1615 LRESULT (WINAPI
*pfnPost
)(HWND
,UINT
,WPARAM
,LPARAM
);
1618 /* Callback for SHLWAPI_178 */
1619 static BOOL CALLBACK
SHLWAPI_EnumChildProc(HWND hWnd
, LPARAM lParam
)
1621 enumWndData
*data
= (enumWndData
*)lParam
;
1623 TRACE("(%p,%p)\n", hWnd
, data
);
1624 data
->pfnPost(hWnd
, data
->uiMsgId
, data
->wParam
, data
->lParam
);
1628 /*************************************************************************
1631 * Send or post a message to every child of a window.
1634 * hWnd [I] Window whose children will get the messages
1635 * uiMsgId [I] Message Id
1636 * wParam [I] WPARAM of message
1637 * lParam [I] LPARAM of message
1638 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1644 * The appropriate ASCII or Unicode function is called for the window.
1646 void WINAPI
SHPropagateMessage(HWND hWnd
, UINT uiMsgId
, WPARAM wParam
, LPARAM lParam
, BOOL bSend
)
1650 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd
, uiMsgId
, wParam
, lParam
, bSend
);
1654 data
.uiMsgId
= uiMsgId
;
1655 data
.wParam
= wParam
;
1656 data
.lParam
= lParam
;
1659 data
.pfnPost
= IsWindowUnicode(hWnd
) ? (void*)SendMessageW
: (void*)SendMessageA
;
1661 data
.pfnPost
= IsWindowUnicode(hWnd
) ? (void*)PostMessageW
: (void*)PostMessageA
;
1663 EnumChildWindows(hWnd
, SHLWAPI_EnumChildProc
, (LPARAM
)&data
);
1667 /*************************************************************************
1670 * Remove all sub-menus from a menu.
1673 * hMenu [I] Menu to remove sub-menus from
1676 * Success: 0. All sub-menus under hMenu are removed
1677 * Failure: -1, if any parameter is invalid
1679 DWORD WINAPI
SHRemoveAllSubMenus(HMENU hMenu
)
1681 int iItemCount
= GetMenuItemCount(hMenu
) - 1;
1683 TRACE("%p\n", hMenu
);
1685 while (iItemCount
>= 0)
1687 HMENU hSubMenu
= GetSubMenu(hMenu
, iItemCount
);
1689 RemoveMenu(hMenu
, iItemCount
, MF_BYPOSITION
);
1695 /*************************************************************************
1698 * Enable or disable a menu item.
1701 * hMenu [I] Menu holding menu item
1702 * uID [I] ID of menu item to enable/disable
1703 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1706 * The return code from EnableMenuItem.
1708 UINT WINAPI
SHEnableMenuItem(HMENU hMenu
, UINT wItemID
, BOOL bEnable
)
1710 TRACE("%p, %u, %d\n", hMenu
, wItemID
, bEnable
);
1711 return EnableMenuItem(hMenu
, wItemID
, bEnable
? MF_ENABLED
: MF_GRAYED
);
1714 /*************************************************************************
1717 * Check or uncheck a menu item.
1720 * hMenu [I] Menu holding menu item
1721 * uID [I] ID of menu item to check/uncheck
1722 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1725 * The return code from CheckMenuItem.
1727 DWORD WINAPI
SHCheckMenuItem(HMENU hMenu
, UINT uID
, BOOL bCheck
)
1729 TRACE("%p, %u, %d\n", hMenu
, uID
, bCheck
);
1730 return CheckMenuItem(hMenu
, uID
, bCheck
? MF_CHECKED
: MF_UNCHECKED
);
1733 /*************************************************************************
1736 * Register a window class if it isn't already.
1739 * lpWndClass [I] Window class to register
1742 * The result of the RegisterClassA call.
1744 DWORD WINAPI
SHRegisterClassA(WNDCLASSA
*wndclass
)
1747 if (GetClassInfoA(wndclass
->hInstance
, wndclass
->lpszClassName
, &wca
))
1749 return (DWORD
)RegisterClassA(wndclass
);
1752 /*************************************************************************
1755 BOOL WINAPI
SHSimulateDrop(IDropTarget
*pDrop
, IDataObject
*pDataObj
,
1756 DWORD grfKeyState
, PPOINTL lpPt
, DWORD
* pdwEffect
)
1758 DWORD dwEffect
= DROPEFFECT_LINK
| DROPEFFECT_MOVE
| DROPEFFECT_COPY
;
1759 POINTL pt
= { 0, 0 };
1761 TRACE("%p %p 0x%08x %p %p\n", pDrop
, pDataObj
, grfKeyState
, lpPt
, pdwEffect
);
1767 pdwEffect
= &dwEffect
;
1769 IDropTarget_DragEnter(pDrop
, pDataObj
, grfKeyState
, *lpPt
, pdwEffect
);
1771 if (*pdwEffect
!= DROPEFFECT_NONE
)
1772 return IDropTarget_Drop(pDrop
, pDataObj
, grfKeyState
, *lpPt
, pdwEffect
);
1774 IDropTarget_DragLeave(pDrop
);
1778 /*************************************************************************
1781 * Call IPersistPropertyBag_Load() on an object.
1784 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1785 * lpPropBag [O] Destination for loaded IPropertyBag
1789 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1791 DWORD WINAPI
SHLoadFromPropertyBag(IUnknown
*lpUnknown
, IPropertyBag
* lpPropBag
)
1793 IPersistPropertyBag
* lpPPBag
;
1794 HRESULT hRet
= E_FAIL
;
1796 TRACE("(%p,%p)\n", lpUnknown
, lpPropBag
);
1800 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IPersistPropertyBag
,
1802 if (SUCCEEDED(hRet
) && lpPPBag
)
1804 hRet
= IPersistPropertyBag_Load(lpPPBag
, lpPropBag
, NULL
);
1805 IPersistPropertyBag_Release(lpPPBag
);
1811 /*************************************************************************
1814 * Call IOleControlSite_TranslateAccelerator() on an object.
1817 * lpUnknown [I] Object supporting the IOleControlSite interface.
1818 * lpMsg [I] Key message to be processed.
1819 * dwModifiers [I] Flags containing the state of the modifier keys.
1823 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1825 HRESULT WINAPI
IUnknown_TranslateAcceleratorOCS(IUnknown
*lpUnknown
, LPMSG lpMsg
, DWORD dwModifiers
)
1827 IOleControlSite
* lpCSite
= NULL
;
1828 HRESULT hRet
= E_INVALIDARG
;
1830 TRACE("(%p,%p,0x%08x)\n", lpUnknown
, lpMsg
, dwModifiers
);
1833 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleControlSite
,
1835 if (SUCCEEDED(hRet
) && lpCSite
)
1837 hRet
= IOleControlSite_TranslateAccelerator(lpCSite
, lpMsg
, dwModifiers
);
1838 IOleControlSite_Release(lpCSite
);
1845 /*************************************************************************
1848 * Call IOleControlSite_OnFocus() on an object.
1851 * lpUnknown [I] Object supporting the IOleControlSite interface.
1852 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1856 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1858 HRESULT WINAPI
IUnknown_OnFocusOCS(IUnknown
*lpUnknown
, BOOL fGotFocus
)
1860 IOleControlSite
* lpCSite
= NULL
;
1861 HRESULT hRet
= E_FAIL
;
1863 TRACE("(%p, %d)\n", lpUnknown
, fGotFocus
);
1866 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleControlSite
,
1868 if (SUCCEEDED(hRet
) && lpCSite
)
1870 hRet
= IOleControlSite_OnFocus(lpCSite
, fGotFocus
);
1871 IOleControlSite_Release(lpCSite
);
1877 /*************************************************************************
1880 HRESULT WINAPI
IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown
, PVOID lpArg1
,
1881 PVOID lpArg2
, PVOID lpArg3
, PVOID lpArg4
)
1883 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1884 static const DWORD service_id
[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1885 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1886 static const DWORD function_id
[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1887 HRESULT hRet
= E_INVALIDARG
;
1888 LPUNKNOWN lpUnkInner
= NULL
; /* FIXME: Real type is unknown */
1890 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown
, lpArg1
, lpArg2
, lpArg3
, lpArg4
);
1892 if (lpUnknown
&& lpArg4
)
1894 hRet
= IUnknown_QueryService(lpUnknown
, (REFGUID
)service_id
,
1895 (REFGUID
)function_id
, (void**)&lpUnkInner
);
1897 if (SUCCEEDED(hRet
) && lpUnkInner
)
1899 /* FIXME: The type of service object requested is unknown, however
1900 * testing shows that its first method is called with 4 parameters.
1901 * Fake this by using IParseDisplayName_ParseDisplayName since the
1902 * signature and position in the vtable matches our unknown object type.
1904 hRet
= IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME
)lpUnkInner
,
1905 lpArg1
, lpArg2
, lpArg3
, lpArg4
);
1906 IUnknown_Release(lpUnkInner
);
1912 /*************************************************************************
1915 * Get a sub-menu from a menu item.
1918 * hMenu [I] Menu to get sub-menu from
1919 * uID [I] ID of menu item containing sub-menu
1922 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1924 HMENU WINAPI
SHGetMenuFromID(HMENU hMenu
, UINT uID
)
1928 TRACE("(%p,%u)\n", hMenu
, uID
);
1930 mi
.cbSize
= sizeof(mi
);
1931 mi
.fMask
= MIIM_SUBMENU
;
1933 if (!GetMenuItemInfoW(hMenu
, uID
, FALSE
, &mi
))
1939 /*************************************************************************
1942 * Get the color depth of the primary display.
1948 * The color depth of the primary display.
1950 DWORD WINAPI
SHGetCurColorRes(void)
1958 ret
= GetDeviceCaps(hdc
, BITSPIXEL
) * GetDeviceCaps(hdc
, PLANES
);
1963 /*************************************************************************
1966 * Wait for a message to arrive, with a timeout.
1969 * hand [I] Handle to query
1970 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1973 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1974 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1975 * message is available.
1977 DWORD WINAPI
SHWaitForSendMessageThread(HANDLE hand
, DWORD dwTimeout
)
1979 DWORD dwEndTicks
= GetTickCount() + dwTimeout
;
1982 while ((dwRet
= MsgWaitForMultipleObjectsEx(1, &hand
, dwTimeout
, QS_SENDMESSAGE
, 0)) == 1)
1986 PeekMessageW(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
1988 if (dwTimeout
!= INFINITE
)
1990 if ((int)(dwTimeout
= dwEndTicks
- GetTickCount()) <= 0)
1991 return WAIT_TIMEOUT
;
1998 /*************************************************************************
2001 * Determine if a shell folder can be expanded.
2004 * lpFolder [I] Parent folder containing the object to test.
2005 * pidl [I] Id of the object to test.
2008 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2009 * Failure: E_INVALIDARG, if any argument is invalid.
2012 * If the object to be tested does not expose the IQueryInfo() interface it
2013 * will not be identified as an expandable folder.
2015 HRESULT WINAPI
SHIsExpandableFolder(LPSHELLFOLDER lpFolder
, LPCITEMIDLIST pidl
)
2017 HRESULT hRet
= E_INVALIDARG
;
2020 if (lpFolder
&& pidl
)
2022 hRet
= IShellFolder_GetUIObjectOf(lpFolder
, NULL
, 1, &pidl
, &IID_IQueryInfo
,
2023 NULL
, (void**)&lpInfo
);
2025 hRet
= S_FALSE
; /* Doesn't expose IQueryInfo */
2030 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2031 * currently used". Really? You wouldn't be holding out on me would you?
2033 hRet
= IQueryInfo_GetInfoFlags(lpInfo
, &dwFlags
);
2035 if (SUCCEEDED(hRet
))
2037 /* 0x2 is an undocumented flag apparently indicating expandability */
2038 hRet
= dwFlags
& 0x2 ? S_OK
: S_FALSE
;
2041 IQueryInfo_Release(lpInfo
);
2047 /*************************************************************************
2050 * Blank out a region of text by drawing the background only.
2053 * hDC [I] Device context to draw in
2054 * pRect [I] Area to draw in
2055 * cRef [I] Color to draw in
2060 DWORD WINAPI
SHFillRectClr(HDC hDC
, LPCRECT pRect
, COLORREF cRef
)
2062 COLORREF cOldColor
= SetBkColor(hDC
, cRef
);
2063 ExtTextOutA(hDC
, 0, 0, ETO_OPAQUE
, pRect
, 0, 0, 0);
2064 SetBkColor(hDC
, cOldColor
);
2068 /*************************************************************************
2071 * Return the value associated with a key in a map.
2074 * lpKeys [I] A list of keys of length iLen
2075 * lpValues [I] A list of values associated with lpKeys, of length iLen
2076 * iLen [I] Length of both lpKeys and lpValues
2077 * iKey [I] The key value to look up in lpKeys
2080 * The value in lpValues associated with iKey, or -1 if iKey is not
2084 * - If two elements in the map share the same key, this function returns
2085 * the value closest to the start of the map
2086 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2088 int WINAPI
SHSearchMapInt(const int *lpKeys
, const int *lpValues
, int iLen
, int iKey
)
2090 if (lpKeys
&& lpValues
)
2096 if (lpKeys
[i
] == iKey
)
2097 return lpValues
[i
]; /* Found */
2101 return -1; /* Not found */
2105 /*************************************************************************
2108 * Copy an interface pointer
2111 * lppDest [O] Destination for copy
2112 * lpUnknown [I] Source for copy
2117 VOID WINAPI
IUnknown_Set(IUnknown
**lppDest
, IUnknown
*lpUnknown
)
2119 TRACE("(%p,%p)\n", lppDest
, lpUnknown
);
2121 IUnknown_AtomicRelease(lppDest
);
2125 IUnknown_AddRef(lpUnknown
);
2126 *lppDest
= lpUnknown
;
2130 /*************************************************************************
2134 HRESULT WINAPI
MayQSForward(IUnknown
* lpUnknown
, PVOID lpReserved
,
2135 REFGUID riidCmdGrp
, ULONG cCmds
,
2136 OLECMD
*prgCmds
, OLECMDTEXT
* pCmdText
)
2138 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2139 lpUnknown
, lpReserved
, riidCmdGrp
, cCmds
, prgCmds
, pCmdText
);
2141 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2142 return DRAGDROP_E_NOTREGISTERED
;
2145 /*************************************************************************
2149 HRESULT WINAPI
MayExecForward(IUnknown
* lpUnknown
, INT iUnk
, REFGUID pguidCmdGroup
,
2150 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
* pvaIn
,
2153 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown
, iUnk
, pguidCmdGroup
,
2154 nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
2155 return DRAGDROP_E_NOTREGISTERED
;
2158 /*************************************************************************
2162 HRESULT WINAPI
IsQSForward(REFGUID pguidCmdGroup
,ULONG cCmds
, OLECMD
*prgCmds
)
2164 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup
, cCmds
, prgCmds
);
2165 return DRAGDROP_E_NOTREGISTERED
;
2168 /*************************************************************************
2171 * Determine if a window is not a child of another window.
2174 * hParent [I] Suspected parent window
2175 * hChild [I] Suspected child window
2178 * TRUE: If hChild is a child window of hParent
2179 * FALSE: If hChild is not a child window of hParent, or they are equal
2181 BOOL WINAPI
SHIsChildOrSelf(HWND hParent
, HWND hChild
)
2183 TRACE("(%p,%p)\n", hParent
, hChild
);
2185 if (!hParent
|| !hChild
)
2187 else if(hParent
== hChild
)
2189 return !IsChild(hParent
, hChild
);
2192 /*************************************************************************
2193 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2198 DWORD num_items
; /* Number of elements inserted */
2199 void *mem
; /* Ptr to array */
2200 DWORD blocks_alloced
; /* Number of elements allocated */
2201 BYTE inc
; /* Number of elements to grow by when we need to expand */
2202 BYTE block_size
; /* Size in bytes of an element */
2203 BYTE flags
; /* Flags */
2206 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2208 /*************************************************************************
2211 * Initialize an FDSA array.
2213 BOOL WINAPI
FDSA_Initialize(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
2216 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size
, inc
, info
, mem
, init_blocks
);
2222 memset(mem
, 0, block_size
* init_blocks
);
2224 info
->num_items
= 0;
2227 info
->blocks_alloced
= init_blocks
;
2228 info
->block_size
= block_size
;
2234 /*************************************************************************
2237 * Destroy an FDSA array
2239 BOOL WINAPI
FDSA_Destroy(FDSA_info
*info
)
2241 TRACE("(%p)\n", info
);
2243 if(info
->flags
& FDSA_FLAG_INTERNAL_ALLOC
)
2245 HeapFree(GetProcessHeap(), 0, info
->mem
);
2252 /*************************************************************************
2255 * Insert element into an FDSA array
2257 DWORD WINAPI
FDSA_InsertItem(FDSA_info
*info
, DWORD where
, const void *block
)
2259 TRACE("(%p 0x%08x %p)\n", info
, where
, block
);
2260 if(where
> info
->num_items
)
2261 where
= info
->num_items
;
2263 if(info
->num_items
>= info
->blocks_alloced
)
2265 DWORD size
= (info
->blocks_alloced
+ info
->inc
) * info
->block_size
;
2266 if(info
->flags
& 0x1)
2267 info
->mem
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, info
->mem
, size
);
2270 void *old_mem
= info
->mem
;
2271 info
->mem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
2272 memcpy(info
->mem
, old_mem
, info
->blocks_alloced
* info
->block_size
);
2274 info
->blocks_alloced
+= info
->inc
;
2278 if(where
< info
->num_items
)
2280 memmove((char*)info
->mem
+ (where
+ 1) * info
->block_size
,
2281 (char*)info
->mem
+ where
* info
->block_size
,
2282 (info
->num_items
- where
) * info
->block_size
);
2284 memcpy((char*)info
->mem
+ where
* info
->block_size
, block
, info
->block_size
);
2290 /*************************************************************************
2293 * Delete an element from an FDSA array.
2295 BOOL WINAPI
FDSA_DeleteItem(FDSA_info
*info
, DWORD where
)
2297 TRACE("(%p 0x%08x)\n", info
, where
);
2299 if(where
>= info
->num_items
)
2302 if(where
< info
->num_items
- 1)
2304 memmove((char*)info
->mem
+ where
* info
->block_size
,
2305 (char*)info
->mem
+ (where
+ 1) * info
->block_size
,
2306 (info
->num_items
- where
- 1) * info
->block_size
);
2308 memset((char*)info
->mem
+ (info
->num_items
- 1) * info
->block_size
,
2309 0, info
->block_size
);
2314 /*************************************************************************
2317 * Call IUnknown_QueryInterface() on a table of objects.
2321 * Failure: E_POINTER or E_NOINTERFACE.
2323 HRESULT WINAPI
QISearch(
2324 void *base
, /* [in] Table of interfaces */
2325 const QITAB
*table
, /* [in] Array of REFIIDs and indexes into the table */
2326 REFIID riid
, /* [in] REFIID to get interface for */
2327 void **ppv
) /* [out] Destination for interface pointer */
2333 TRACE("(%p %p %s %p)\n", base
, table
, debugstr_guid(riid
), ppv
);
2336 while (xmove
->piid
) {
2337 TRACE("trying (offset %d) %s\n", xmove
->dwOffset
, debugstr_guid(xmove
->piid
));
2338 if (IsEqualIID(riid
, xmove
->piid
)) {
2339 a_vtbl
= (IUnknown
*)(xmove
->dwOffset
+ (LPBYTE
)base
);
2340 TRACE("matched, returning (%p)\n", a_vtbl
);
2342 IUnknown_AddRef(a_vtbl
);
2348 if (IsEqualIID(riid
, &IID_IUnknown
)) {
2349 a_vtbl
= (IUnknown
*)(table
->dwOffset
+ (LPBYTE
)base
);
2350 TRACE("returning first for IUnknown (%p)\n", a_vtbl
);
2352 IUnknown_AddRef(a_vtbl
);
2356 ret
= E_NOINTERFACE
;
2360 TRACE("-- 0x%08x\n", ret
);
2364 /*************************************************************************
2367 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2370 * hWnd [I] Parent Window to set the property
2371 * id [I] Index of child Window to set the Font
2377 HRESULT WINAPI
SHSetDefaultDialogFont(HWND hWnd
, INT id
)
2379 FIXME("(%p, %d) stub\n", hWnd
, id
);
2383 /*************************************************************************
2386 * Remove the "PropDlgFont" property from a window.
2389 * hWnd [I] Window to remove the property from
2392 * A handle to the removed property, or NULL if it did not exist.
2394 HANDLE WINAPI
SHRemoveDefaultDialogFont(HWND hWnd
)
2398 TRACE("(%p)\n", hWnd
);
2400 hProp
= GetPropA(hWnd
, "PropDlgFont");
2404 DeleteObject(hProp
);
2405 hProp
= RemovePropA(hWnd
, "PropDlgFont");
2410 /*************************************************************************
2413 * Load the in-process server of a given GUID.
2416 * refiid [I] GUID of the server to load.
2419 * Success: A handle to the loaded server dll.
2420 * Failure: A NULL handle.
2422 HMODULE WINAPI
SHPinDllOfCLSID(REFIID refiid
)
2426 CHAR value
[MAX_PATH
], string
[MAX_PATH
];
2428 strcpy(string
, "CLSID\\");
2429 SHStringFromGUIDA(refiid
, string
+ 6, sizeof(string
)/sizeof(char) - 6);
2430 strcat(string
, "\\InProcServer32");
2433 RegOpenKeyExA(HKEY_CLASSES_ROOT
, string
, 0, 1, &newkey
);
2434 RegQueryValueExA(newkey
, 0, 0, &type
, (PBYTE
)value
, &count
);
2435 RegCloseKey(newkey
);
2436 return LoadLibraryExA(value
, 0, 0);
2439 /*************************************************************************
2442 * Unicode version of SHLWAPI_183.
2444 DWORD WINAPI
SHRegisterClassW(WNDCLASSW
* lpWndClass
)
2448 TRACE("(%p %s)\n",lpWndClass
->hInstance
, debugstr_w(lpWndClass
->lpszClassName
));
2450 if (GetClassInfoW(lpWndClass
->hInstance
, lpWndClass
->lpszClassName
, &WndClass
))
2452 return RegisterClassW(lpWndClass
);
2455 /*************************************************************************
2458 * Unregister a list of classes.
2461 * hInst [I] Application instance that registered the classes
2462 * lppClasses [I] List of class names
2463 * iCount [I] Number of names in lppClasses
2468 void WINAPI
SHUnregisterClassesA(HINSTANCE hInst
, LPCSTR
*lppClasses
, INT iCount
)
2472 TRACE("(%p,%p,%d)\n", hInst
, lppClasses
, iCount
);
2476 if (GetClassInfoA(hInst
, *lppClasses
, &WndClass
))
2477 UnregisterClassA(*lppClasses
, hInst
);
2483 /*************************************************************************
2486 * Unicode version of SHUnregisterClassesA.
2488 void WINAPI
SHUnregisterClassesW(HINSTANCE hInst
, LPCWSTR
*lppClasses
, INT iCount
)
2492 TRACE("(%p,%p,%d)\n", hInst
, lppClasses
, iCount
);
2496 if (GetClassInfoW(hInst
, *lppClasses
, &WndClass
))
2497 UnregisterClassW(*lppClasses
, hInst
);
2503 /*************************************************************************
2506 * Call The correct (Ascii/Unicode) default window procedure for a window.
2509 * hWnd [I] Window to call the default procedure for
2510 * uMessage [I] Message ID
2511 * wParam [I] WPARAM of message
2512 * lParam [I] LPARAM of message
2515 * The result of calling DefWindowProcA() or DefWindowProcW().
2517 LRESULT CALLBACK
SHDefWindowProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
2519 if (IsWindowUnicode(hWnd
))
2520 return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
2521 return DefWindowProcA(hWnd
, uMessage
, wParam
, lParam
);
2524 /*************************************************************************
2527 HRESULT WINAPI
IUnknown_GetSite(LPUNKNOWN lpUnknown
, REFIID iid
, PVOID
*lppSite
)
2529 HRESULT hRet
= E_INVALIDARG
;
2530 LPOBJECTWITHSITE lpSite
= NULL
;
2532 TRACE("(%p,%s,%p)\n", lpUnknown
, debugstr_guid(iid
), lppSite
);
2534 if (lpUnknown
&& iid
&& lppSite
)
2536 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IObjectWithSite
,
2538 if (SUCCEEDED(hRet
) && lpSite
)
2540 hRet
= IObjectWithSite_GetSite(lpSite
, iid
, lppSite
);
2541 IObjectWithSite_Release(lpSite
);
2547 /*************************************************************************
2550 * Create a worker window using CreateWindowExA().
2553 * wndProc [I] Window procedure
2554 * hWndParent [I] Parent window
2555 * dwExStyle [I] Extra style flags
2556 * dwStyle [I] Style flags
2557 * hMenu [I] Window menu
2558 * wnd_extra [I] Window extra bytes value
2561 * Success: The window handle of the newly created window.
2564 HWND WINAPI
SHCreateWorkerWindowA(LONG wndProc
, HWND hWndParent
, DWORD dwExStyle
,
2565 DWORD dwStyle
, HMENU hMenu
, LONG_PTR wnd_extra
)
2567 static const char szClass
[] = "WorkerA";
2571 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2572 wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, wnd_extra
);
2574 /* Create Window class */
2576 wc
.lpfnWndProc
= DefWindowProcA
;
2578 wc
.cbWndExtra
= sizeof(LONG_PTR
);
2579 wc
.hInstance
= shlwapi_hInstance
;
2581 wc
.hCursor
= LoadCursorA(NULL
, (LPSTR
)IDC_ARROW
);
2582 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2583 wc
.lpszMenuName
= NULL
;
2584 wc
.lpszClassName
= szClass
;
2586 SHRegisterClassA(&wc
);
2588 hWnd
= CreateWindowExA(dwExStyle
, szClass
, 0, dwStyle
, 0, 0, 0, 0,
2589 hWndParent
, hMenu
, shlwapi_hInstance
, 0);
2592 SetWindowLongPtrW(hWnd
, 0, wnd_extra
);
2594 if (wndProc
) SetWindowLongPtrA(hWnd
, GWLP_WNDPROC
, wndProc
);
2600 typedef struct tagPOLICYDATA
2602 DWORD policy
; /* flags value passed to SHRestricted */
2603 LPCWSTR appstr
; /* application str such as "Explorer" */
2604 LPCWSTR keystr
; /* name of the actual registry key / policy */
2605 } POLICYDATA
, *LPPOLICYDATA
;
2607 #define SHELL_NO_POLICY 0xffffffff
2609 /* default shell policy registry key */
2610 static const WCHAR strRegistryPolicyW
[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2611 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2612 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2613 '\\','P','o','l','i','c','i','e','s',0};
2615 /*************************************************************************
2618 * Retrieve a policy value from the registry.
2621 * lpSubKey [I] registry key name
2622 * lpSubName [I] subname of registry key
2623 * lpValue [I] value name of registry value
2626 * the value associated with the registry key or 0 if not found
2628 DWORD WINAPI
SHGetRestriction(LPCWSTR lpSubKey
, LPCWSTR lpSubName
, LPCWSTR lpValue
)
2630 DWORD retval
, datsize
= sizeof(retval
);
2634 lpSubKey
= strRegistryPolicyW
;
2636 retval
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, lpSubKey
, &hKey
);
2637 if (retval
!= ERROR_SUCCESS
)
2638 retval
= RegOpenKeyW(HKEY_CURRENT_USER
, lpSubKey
, &hKey
);
2639 if (retval
!= ERROR_SUCCESS
)
2642 SHGetValueW(hKey
, lpSubName
, lpValue
, NULL
, &retval
, &datsize
);
2647 /*************************************************************************
2650 * Helper function to retrieve the possibly cached value for a specific policy
2653 * policy [I] The policy to look for
2654 * initial [I] Main registry key to open, if NULL use default
2655 * polTable [I] Table of known policies, 0 terminated
2656 * polArr [I] Cache array of policy values
2659 * The retrieved policy value or 0 if not successful
2662 * This function is used by the native SHRestricted function to search for the
2663 * policy and cache it once retrieved. The current Wine implementation uses a
2664 * different POLICYDATA structure and implements a similar algorithm adapted to
2667 DWORD WINAPI
SHRestrictionLookup(
2670 LPPOLICYDATA polTable
,
2673 TRACE("(0x%08x %s %p %p)\n", policy
, debugstr_w(initial
), polTable
, polArr
);
2675 if (!polTable
|| !polArr
)
2678 for (;polTable
->policy
; polTable
++, polArr
++)
2680 if (policy
== polTable
->policy
)
2682 /* we have a known policy */
2684 /* check if this policy has been cached */
2685 if (*polArr
== SHELL_NO_POLICY
)
2686 *polArr
= SHGetRestriction(initial
, polTable
->appstr
, polTable
->keystr
);
2690 /* we don't know this policy, return 0 */
2691 TRACE("unknown policy: (%08x)\n", policy
);
2695 /*************************************************************************
2698 * Get an interface from an object.
2701 * Success: S_OK. ppv contains the requested interface.
2702 * Failure: An HRESULT error code.
2705 * This QueryInterface asks the inner object for an interface. In case
2706 * of aggregation this request would be forwarded by the inner to the
2707 * outer object. This function asks the inner object directly for the
2708 * interface circumventing the forwarding to the outer object.
2710 HRESULT WINAPI
SHWeakQueryInterface(
2711 IUnknown
* pUnk
, /* [in] Outer object */
2712 IUnknown
* pInner
, /* [in] Inner object */
2713 IID
* riid
, /* [in] Interface GUID to query for */
2714 LPVOID
* ppv
) /* [out] Destination for queried interface */
2716 HRESULT hret
= E_NOINTERFACE
;
2717 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk
,pInner
,debugstr_guid(riid
), ppv
);
2720 if(pUnk
&& pInner
) {
2721 hret
= IUnknown_QueryInterface(pInner
, riid
, ppv
);
2722 if (SUCCEEDED(hret
)) IUnknown_Release(pUnk
);
2724 TRACE("-- 0x%08x\n", hret
);
2728 /*************************************************************************
2731 * Move a reference from one interface to another.
2734 * lpDest [O] Destination to receive the reference
2735 * lppUnknown [O] Source to give up the reference to lpDest
2740 VOID WINAPI
SHWeakReleaseInterface(IUnknown
*lpDest
, IUnknown
**lppUnknown
)
2742 TRACE("(%p,%p)\n", lpDest
, lppUnknown
);
2747 IUnknown_AddRef(lpDest
);
2748 IUnknown_AtomicRelease(lppUnknown
); /* Release existing interface */
2752 /*************************************************************************
2755 * Convert an ASCII string of a CLSID into a CLSID.
2758 * idstr [I] String representing a CLSID in registry format
2759 * id [O] Destination for the converted CLSID
2762 * Success: TRUE. id contains the converted CLSID.
2765 BOOL WINAPI
GUIDFromStringA(LPCSTR idstr
, CLSID
*id
)
2768 MultiByteToWideChar(CP_ACP
, 0, idstr
, -1, wClsid
, sizeof(wClsid
)/sizeof(WCHAR
));
2769 return SUCCEEDED(CLSIDFromString(wClsid
, id
));
2772 /*************************************************************************
2775 * Unicode version of GUIDFromStringA.
2777 BOOL WINAPI
GUIDFromStringW(LPCWSTR idstr
, CLSID
*id
)
2779 return SUCCEEDED(CLSIDFromString((LPCOLESTR
)idstr
, id
));
2782 /*************************************************************************
2785 * Determine if the browser is integrated into the shell, and set a registry
2792 * 1, If the browser is not integrated.
2793 * 2, If the browser is integrated.
2796 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2797 * either set to TRUE, or removed depending on whether the browser is deemed
2800 DWORD WINAPI
WhichPlatform(void)
2802 static const char szIntegratedBrowser
[] = "IntegratedBrowser";
2803 static DWORD dwState
= 0;
2805 DWORD dwRet
, dwData
, dwSize
;
2811 /* If shell32 exports DllGetVersion(), the browser is integrated */
2813 hshell32
= LoadLibraryA("shell32.dll");
2816 FARPROC pDllGetVersion
;
2817 pDllGetVersion
= GetProcAddress(hshell32
, "DllGetVersion");
2818 dwState
= pDllGetVersion
? 2 : 1;
2819 FreeLibrary(hshell32
);
2822 /* Set or delete the key accordingly */
2823 dwRet
= RegOpenKeyExA(HKEY_LOCAL_MACHINE
,
2824 "Software\\Microsoft\\Internet Explorer", 0,
2825 KEY_ALL_ACCESS
, &hKey
);
2828 dwRet
= RegQueryValueExA(hKey
, szIntegratedBrowser
, 0, 0,
2829 (LPBYTE
)&dwData
, &dwSize
);
2831 if (!dwRet
&& dwState
== 1)
2833 /* Value exists but browser is not integrated */
2834 RegDeleteValueA(hKey
, szIntegratedBrowser
);
2836 else if (dwRet
&& dwState
== 2)
2838 /* Browser is integrated but value does not exist */
2840 RegSetValueExA(hKey
, szIntegratedBrowser
, 0, REG_DWORD
,
2841 (LPBYTE
)&dwData
, sizeof(dwData
));
2848 /*************************************************************************
2851 * Unicode version of SHCreateWorkerWindowA.
2853 HWND WINAPI
SHCreateWorkerWindowW(LONG wndProc
, HWND hWndParent
, DWORD dwExStyle
,
2854 DWORD dwStyle
, HMENU hMenu
, LONG msg_result
)
2856 static const WCHAR szClass
[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
2860 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
2861 wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, msg_result
);
2863 /* If our OS is natively ANSI, use the ANSI version */
2864 if (GetVersion() & 0x80000000) /* not NT */
2866 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
2867 return SHCreateWorkerWindowA(wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, msg_result
);
2870 /* Create Window class */
2872 wc
.lpfnWndProc
= DefWindowProcW
;
2875 wc
.hInstance
= shlwapi_hInstance
;
2877 wc
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
2878 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2879 wc
.lpszMenuName
= NULL
;
2880 wc
.lpszClassName
= szClass
;
2882 SHRegisterClassW(&wc
);
2884 hWnd
= CreateWindowExW(dwExStyle
, szClass
, 0, dwStyle
, 0, 0, 0, 0,
2885 hWndParent
, hMenu
, shlwapi_hInstance
, 0);
2888 SetWindowLongPtrW(hWnd
, DWLP_MSGRESULT
, msg_result
);
2890 if (wndProc
) SetWindowLongPtrW(hWnd
, GWLP_WNDPROC
, wndProc
);
2896 /*************************************************************************
2899 * Get and show a context menu from a shell folder.
2902 * hWnd [I] Window displaying the shell folder
2903 * lpFolder [I] IShellFolder interface
2904 * lpApidl [I] Id for the particular folder desired
2908 * Failure: An HRESULT error code indicating the error.
2910 HRESULT WINAPI
SHInvokeDefaultCommand(HWND hWnd
, IShellFolder
* lpFolder
, LPCITEMIDLIST lpApidl
)
2912 TRACE("%p %p %p\n", hWnd
, lpFolder
, lpApidl
);
2913 return SHInvokeCommand(hWnd
, lpFolder
, lpApidl
, 0);
2916 /*************************************************************************
2919 * _SHPackDispParamsV
2921 HRESULT WINAPI
SHPackDispParamsV(DISPPARAMS
*params
, VARIANTARG
*args
, UINT cnt
, __ms_va_list valist
)
2925 TRACE("(%p %p %u ...)\n", params
, args
, cnt
);
2927 params
->rgvarg
= args
;
2928 params
->rgdispidNamedArgs
= NULL
;
2929 params
->cArgs
= cnt
;
2930 params
->cNamedArgs
= 0;
2934 while(iter
-- > args
) {
2935 V_VT(iter
) = va_arg(valist
, enum VARENUM
);
2937 TRACE("vt=%d\n", V_VT(iter
));
2939 if(V_VT(iter
) & VT_BYREF
) {
2940 V_BYREF(iter
) = va_arg(valist
, LPVOID
);
2942 switch(V_VT(iter
)) {
2944 V_I4(iter
) = va_arg(valist
, LONG
);
2947 V_BSTR(iter
) = va_arg(valist
, BSTR
);
2950 V_DISPATCH(iter
) = va_arg(valist
, IDispatch
*);
2953 V_BOOL(iter
) = va_arg(valist
, int);
2956 V_UNKNOWN(iter
) = va_arg(valist
, IUnknown
*);
2960 V_I4(iter
) = va_arg(valist
, LONG
);
2968 /*************************************************************************
2973 HRESULT WINAPIV
SHPackDispParams(DISPPARAMS
*params
, VARIANTARG
*args
, UINT cnt
, ...)
2975 __ms_va_list valist
;
2978 __ms_va_start(valist
, cnt
);
2979 hres
= SHPackDispParamsV(params
, args
, cnt
, valist
);
2980 __ms_va_end(valist
);
2984 /*************************************************************************
2985 * SHLWAPI_InvokeByIID
2987 * This helper function calls IDispatch::Invoke for each sink
2988 * which implements given iid or IDispatch.
2991 static HRESULT
SHLWAPI_InvokeByIID(
2992 IConnectionPoint
* iCP
,
2995 DISPPARAMS
* dispParams
)
2997 IEnumConnections
*enumerator
;
2999 static DISPPARAMS empty
= {NULL
, NULL
, 0, 0};
3000 DISPPARAMS
* params
= dispParams
;
3002 HRESULT result
= IConnectionPoint_EnumConnections(iCP
, &enumerator
);
3006 /* Invoke is never happening with an NULL dispParams */
3010 while(IEnumConnections_Next(enumerator
, 1, &rgcd
, NULL
)==S_OK
)
3012 IDispatch
*dispIface
;
3013 if ((iid
&& SUCCEEDED(IUnknown_QueryInterface(rgcd
.pUnk
, iid
, (LPVOID
*)&dispIface
))) ||
3014 SUCCEEDED(IUnknown_QueryInterface(rgcd
.pUnk
, &IID_IDispatch
, (LPVOID
*)&dispIface
)))
3016 IDispatch_Invoke(dispIface
, dispId
, &IID_NULL
, 0, DISPATCH_METHOD
, params
, NULL
, NULL
, NULL
);
3017 IDispatch_Release(dispIface
);
3019 IUnknown_Release(rgcd
.pUnk
);
3022 IEnumConnections_Release(enumerator
);
3027 /*************************************************************************
3028 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3030 HRESULT WINAPI
IConnectionPoint_InvokeWithCancel( IConnectionPoint
* iCP
,
3031 DISPID dispId
, DISPPARAMS
* dispParams
,
3032 DWORD unknown1
, DWORD unknown2
)
3037 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP
, dispId
, dispParams
, unknown1
, unknown2
);
3039 result
= IConnectionPoint_GetConnectionInterface(iCP
, &iid
);
3040 if (SUCCEEDED(result
))
3041 result
= SHLWAPI_InvokeByIID(iCP
, &iid
, dispId
, dispParams
);
3043 result
= SHLWAPI_InvokeByIID(iCP
, NULL
, dispId
, dispParams
);
3049 /*************************************************************************
3052 * IConnectionPoint_SimpleInvoke
3054 HRESULT WINAPI
IConnectionPoint_SimpleInvoke(
3055 IConnectionPoint
* iCP
,
3057 DISPPARAMS
* dispParams
)
3062 TRACE("(%p)->(0x%x %p)\n",iCP
,dispId
,dispParams
);
3064 result
= IConnectionPoint_GetConnectionInterface(iCP
, &iid
);
3065 if (SUCCEEDED(result
))
3066 result
= SHLWAPI_InvokeByIID(iCP
, &iid
, dispId
, dispParams
);
3068 result
= SHLWAPI_InvokeByIID(iCP
, NULL
, dispId
, dispParams
);
3073 /*************************************************************************
3076 * Notify an IConnectionPoint object of changes.
3079 * lpCP [I] Object to notify
3084 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3085 * IConnectionPoint interface.
3087 HRESULT WINAPI
IConnectionPoint_OnChanged(IConnectionPoint
* lpCP
, DISPID dispID
)
3089 IEnumConnections
*lpEnum
;
3090 HRESULT hRet
= E_NOINTERFACE
;
3092 TRACE("(%p,0x%8X)\n", lpCP
, dispID
);
3094 /* Get an enumerator for the connections */
3096 hRet
= IConnectionPoint_EnumConnections(lpCP
, &lpEnum
);
3098 if (SUCCEEDED(hRet
))
3100 IPropertyNotifySink
*lpSink
;
3101 CONNECTDATA connData
;
3104 /* Call OnChanged() for every notify sink in the connection point */
3105 while (IEnumConnections_Next(lpEnum
, 1, &connData
, &ulFetched
) == S_OK
)
3107 if (SUCCEEDED(IUnknown_QueryInterface(connData
.pUnk
, &IID_IPropertyNotifySink
, (void**)&lpSink
)) &&
3110 IPropertyNotifySink_OnChanged(lpSink
, dispID
);
3111 IPropertyNotifySink_Release(lpSink
);
3113 IUnknown_Release(connData
.pUnk
);
3116 IEnumConnections_Release(lpEnum
);
3121 /*************************************************************************
3124 * IUnknown_CPContainerInvokeParam
3126 HRESULT WINAPIV
IUnknown_CPContainerInvokeParam(
3127 IUnknown
*container
,
3134 IConnectionPoint
*iCP
;
3135 IConnectionPointContainer
*iCPC
;
3136 DISPPARAMS dispParams
= {buffer
, NULL
, cParams
, 0};
3137 __ms_va_list valist
;
3140 return E_NOINTERFACE
;
3142 result
= IUnknown_QueryInterface(container
, &IID_IConnectionPointContainer
,(LPVOID
*) &iCPC
);
3146 result
= IConnectionPointContainer_FindConnectionPoint(iCPC
, riid
, &iCP
);
3147 IConnectionPointContainer_Release(iCPC
);
3151 __ms_va_start(valist
, cParams
);
3152 SHPackDispParamsV(&dispParams
, buffer
, cParams
, valist
);
3153 __ms_va_end(valist
);
3155 result
= SHLWAPI_InvokeByIID(iCP
, riid
, dispId
, &dispParams
);
3156 IConnectionPoint_Release(iCP
);
3161 /*************************************************************************
3164 * Notify an IConnectionPointContainer object of changes.
3167 * lpUnknown [I] Object to notify
3172 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3173 * IConnectionPointContainer interface.
3175 HRESULT WINAPI
IUnknown_CPContainerOnChanged(IUnknown
*lpUnknown
, DISPID dispID
)
3177 IConnectionPointContainer
* lpCPC
= NULL
;
3178 HRESULT hRet
= E_NOINTERFACE
;
3180 TRACE("(%p,0x%8X)\n", lpUnknown
, dispID
);
3183 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IConnectionPointContainer
, (void**)&lpCPC
);
3185 if (SUCCEEDED(hRet
))
3187 IConnectionPoint
* lpCP
;
3189 hRet
= IConnectionPointContainer_FindConnectionPoint(lpCPC
, &IID_IPropertyNotifySink
, &lpCP
);
3190 IConnectionPointContainer_Release(lpCPC
);
3192 hRet
= IConnectionPoint_OnChanged(lpCP
, dispID
);
3193 IConnectionPoint_Release(lpCP
);
3198 /*************************************************************************
3203 BOOL WINAPI
PlaySoundWrapW(LPCWSTR pszSound
, HMODULE hmod
, DWORD fdwSound
)
3205 return PlaySoundW(pszSound
, hmod
, fdwSound
);
3208 /*************************************************************************
3211 * Retrieve a key value from an INI file. See GetPrivateProfileString for
3215 * appName [I] The section in the INI file that contains the key
3216 * keyName [I] The key to be retrieved
3217 * out [O] The buffer into which the key's value will be copied
3218 * outLen [I] The length of the `out' buffer
3219 * filename [I] The location of the INI file
3222 * Length of string copied into `out'.
3224 DWORD WINAPI
SHGetIniStringW(LPCWSTR appName
, LPCWSTR keyName
, LPWSTR out
,
3225 DWORD outLen
, LPCWSTR filename
)
3230 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName
), debugstr_w(keyName
),
3231 out
, outLen
, debugstr_w(filename
));
3236 buf
= HeapAlloc(GetProcessHeap(), 0, outLen
* sizeof(WCHAR
));
3242 ret
= GetPrivateProfileStringW(appName
, keyName
, NULL
, buf
, outLen
, filename
);
3248 HeapFree(GetProcessHeap(), 0, buf
);
3250 return strlenW(out
);
3253 /*************************************************************************
3256 * Set a key value in an INI file. See WritePrivateProfileString for
3260 * appName [I] The section in the INI file that contains the key
3261 * keyName [I] The key to be set
3262 * str [O] The value of the key
3263 * filename [I] The location of the INI file
3269 BOOL WINAPI
SHSetIniStringW(LPCWSTR appName
, LPCWSTR keyName
, LPCWSTR str
,
3272 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName
), keyName
, debugstr_w(str
),
3273 debugstr_w(filename
));
3275 return WritePrivateProfileStringW(appName
, keyName
, str
, filename
);
3278 /*************************************************************************
3281 * See SHGetFileInfoW.
3283 DWORD WINAPI
SHGetFileInfoWrapW(LPCWSTR path
, DWORD dwFileAttributes
,
3284 SHFILEINFOW
*psfi
, UINT sizeofpsfi
, UINT flags
)
3286 return SHGetFileInfoW(path
, dwFileAttributes
, psfi
, sizeofpsfi
, flags
);
3289 /*************************************************************************
3292 * See DragQueryFileW.
3294 UINT WINAPI
DragQueryFileWrapW(HDROP hDrop
, UINT lFile
, LPWSTR lpszFile
, UINT lLength
)
3296 return DragQueryFileW(hDrop
, lFile
, lpszFile
, lLength
);
3299 /*************************************************************************
3302 * See SHBrowseForFolderW.
3304 LPITEMIDLIST WINAPI
SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi
)
3306 return SHBrowseForFolderW(lpBi
);
3309 /*************************************************************************
3312 * See SHGetPathFromIDListW.
3314 BOOL WINAPI
SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl
,LPWSTR pszPath
)
3316 return SHGetPathFromIDListW(pidl
, pszPath
);
3319 /*************************************************************************
3322 * See ShellExecuteExW.
3324 BOOL WINAPI
ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo
)
3326 return ShellExecuteExW(lpExecInfo
);
3329 /*************************************************************************