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
40 #include "shdeprecated.h"
47 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
52 /* DLL handles for late bound calls */
53 extern HINSTANCE shlwapi_hInstance
;
55 static HRESULT
iunknown_query_service(IUnknown
*,REFGUID
,REFIID
,LPVOID
*);
56 HRESULT WINAPI
SHInvokeCommand(HWND
,IShellFolder
*,LPCITEMIDLIST
,DWORD
);
57 BOOL WINAPI
SHAboutInfoW(LPWSTR
,DWORD
);
60 NOTES: Most functions exported by ordinal seem to be superfluous.
61 The reason for these functions to be there is to provide a wrapper
62 for unicode functions to provide these functions on systems without
63 unicode functions eg. win95/win98. Since we have such functions we just
64 call these. If running Wine with native DLLs, some late bound calls may
65 fail. However, it is better to implement the functions in the forward DLL
66 and recommend the builtin rather than reimplementing the calls here!
69 /*************************************************************************
72 * Copy a sharable memory handle from one process to another.
75 * hShared [I] Shared memory handle to duplicate
76 * dwSrcProcId [I] ID of the process owning hShared
77 * dwDstProcId [I] ID of the process wanting the duplicated handle
78 * dwAccess [I] Desired DuplicateHandle() access
79 * dwOptions [I] Desired DuplicateHandle() options
82 * Success: A handle suitable for use by the dwDstProcId process.
83 * Failure: A NULL handle.
86 HANDLE WINAPI
SHMapHandle(HANDLE hShared
, DWORD dwSrcProcId
, DWORD dwDstProcId
,
87 DWORD dwAccess
, DWORD dwOptions
)
90 DWORD dwMyProcId
= GetCurrentProcessId();
93 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared
, dwDstProcId
, dwSrcProcId
,
98 TRACE("Returning handle NULL\n");
102 /* Get dest process handle */
103 if (dwDstProcId
== dwMyProcId
)
104 hDst
= GetCurrentProcess();
106 hDst
= OpenProcess(PROCESS_DUP_HANDLE
, 0, dwDstProcId
);
110 /* Get src process handle */
111 if (dwSrcProcId
== dwMyProcId
)
112 hSrc
= GetCurrentProcess();
114 hSrc
= OpenProcess(PROCESS_DUP_HANDLE
, 0, dwSrcProcId
);
118 /* Make handle available to dest process */
119 if (!DuplicateHandle(hSrc
, hShared
, hDst
, &hRet
,
120 dwAccess
, 0, dwOptions
| DUPLICATE_SAME_ACCESS
))
123 if (dwSrcProcId
!= dwMyProcId
)
127 if (dwDstProcId
!= dwMyProcId
)
131 TRACE("Returning handle %p\n", hRet
);
135 /*************************************************************************
138 * Create a block of sharable memory and initialise it with data.
141 * lpvData [I] Pointer to data to write
142 * dwSize [I] Size of data
143 * dwProcId [I] ID of process owning data
146 * Success: A shared memory handle
150 * Ordinals 7-11 provide a set of calls to create shared memory between a
151 * group of processes. The shared memory is treated opaquely in that its size
152 * is not exposed to clients who map it. This is accomplished by storing
153 * the size of the map as the first DWORD of mapped data, and then offsetting
154 * the view pointer returned by this size.
157 HANDLE WINAPI
SHAllocShared(LPCVOID lpvData
, DWORD dwSize
, DWORD dwProcId
)
163 TRACE("(%p,%d,%d)\n", lpvData
, dwSize
, dwProcId
);
165 /* Create file mapping of the correct length */
166 hMap
= CreateFileMappingA(INVALID_HANDLE_VALUE
, NULL
, FILE_MAP_READ
, 0,
167 dwSize
+ sizeof(dwSize
), NULL
);
171 /* Get a view in our process address space */
172 pMapped
= MapViewOfFile(hMap
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
176 /* Write size of data, followed by the data, to the view */
177 *((DWORD
*)pMapped
) = dwSize
;
179 memcpy((char *) pMapped
+ sizeof(dwSize
), lpvData
, dwSize
);
181 /* Release view. All further views mapped will be opaque */
182 UnmapViewOfFile(pMapped
);
183 hRet
= SHMapHandle(hMap
, GetCurrentProcessId(), dwProcId
,
184 FILE_MAP_ALL_ACCESS
, DUPLICATE_SAME_ACCESS
);
191 /*************************************************************************
194 * Get a pointer to a block of shared memory from a shared memory handle.
197 * hShared [I] Shared memory handle
198 * dwProcId [I] ID of process owning hShared
201 * Success: A pointer to the shared memory
205 PVOID WINAPI
SHLockShared(HANDLE hShared
, DWORD dwProcId
)
210 TRACE("(%p %d)\n", hShared
, dwProcId
);
212 /* Get handle to shared memory for current process */
213 hDup
= SHMapHandle(hShared
, dwProcId
, GetCurrentProcessId(), FILE_MAP_ALL_ACCESS
, 0);
216 pMapped
= MapViewOfFile(hDup
, FILE_MAP_READ
| FILE_MAP_WRITE
, 0, 0, 0);
220 return (char *) pMapped
+ sizeof(DWORD
); /* Hide size */
224 /*************************************************************************
227 * Release a pointer to a block of shared memory.
230 * lpView [I] Shared memory pointer
237 BOOL WINAPI
SHUnlockShared(LPVOID lpView
)
239 TRACE("(%p)\n", lpView
);
240 return UnmapViewOfFile((char *) lpView
- sizeof(DWORD
)); /* Include size */
243 /*************************************************************************
246 * Destroy a block of sharable memory.
249 * hShared [I] Shared memory handle
250 * dwProcId [I] ID of process owning hShared
257 BOOL WINAPI
SHFreeShared(HANDLE hShared
, DWORD dwProcId
)
261 TRACE("(%p %d)\n", hShared
, dwProcId
);
266 /* Get a copy of the handle for our process, closing the source handle */
267 hClose
= SHMapHandle(hShared
, dwProcId
, GetCurrentProcessId(),
268 FILE_MAP_ALL_ACCESS
,DUPLICATE_CLOSE_SOURCE
);
269 /* Close local copy */
270 return CloseHandle(hClose
);
273 /*************************************************************************
276 * Create and register a clipboard enumerator for a web browser.
279 * lpBC [I] Binding context
280 * lpUnknown [I] An object exposing the IWebBrowserApp interface
284 * Failure: An HRESULT error code.
287 * The enumerator is stored as a property of the web browser. If it does not
288 * yet exist, it is created and set before being registered.
290 HRESULT WINAPI
RegisterDefaultAcceptHeaders(LPBC lpBC
, IUnknown
*lpUnknown
)
292 static const WCHAR szProperty
[] = { '{','D','0','F','C','A','4','2','0',
293 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
294 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
296 IEnumFORMATETC
* pIEnumFormatEtc
= NULL
;
299 IWebBrowserApp
* pBrowser
;
301 TRACE("(%p, %p)\n", lpBC
, lpUnknown
);
303 hr
= iunknown_query_service(lpUnknown
, &IID_IWebBrowserApp
, &IID_IWebBrowserApp
, (void**)&pBrowser
);
307 V_VT(&var
) = VT_EMPTY
;
309 /* The property we get is the browsers clipboard enumerator */
310 property
= SysAllocString(szProperty
);
311 hr
= IWebBrowserApp_GetProperty(pBrowser
, property
, &var
);
312 SysFreeString(property
);
313 if (FAILED(hr
)) goto exit
;
315 if (V_VT(&var
) == VT_EMPTY
)
317 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
318 char szKeyBuff
[128], szValueBuff
[128];
319 DWORD dwKeySize
, dwValueSize
, dwRet
= 0, dwCount
= 0, dwNumValues
, dwType
;
320 FORMATETC
* formatList
, *format
;
323 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
325 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE
, "Software\\Microsoft\\Windows\\Current"
326 "Version\\Internet Settings\\Accepted Documents", &hDocs
))
332 /* Get count of values in key */
335 dwKeySize
= sizeof(szKeyBuff
);
336 dwRet
= RegEnumValueA(hDocs
,dwCount
,szKeyBuff
,&dwKeySize
,0,&dwType
,0,0);
340 dwNumValues
= dwCount
;
342 /* Note: dwCount = number of items + 1; The extra item is the end node */
343 format
= formatList
= HeapAlloc(GetProcessHeap(), 0, dwCount
* sizeof(FORMATETC
));
358 /* Register clipboard formats for the values and populate format list */
359 while(!dwRet
&& dwCount
< dwNumValues
)
361 dwKeySize
= sizeof(szKeyBuff
);
362 dwValueSize
= sizeof(szValueBuff
);
363 dwRet
= RegEnumValueA(hDocs
, dwCount
, szKeyBuff
, &dwKeySize
, 0, &dwType
,
364 (PBYTE
)szValueBuff
, &dwValueSize
);
367 HeapFree(GetProcessHeap(), 0, formatList
);
373 format
->cfFormat
= RegisterClipboardFormatA(szValueBuff
);
375 format
->dwAspect
= 1;
386 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
387 format
->cfFormat
= 0;
389 format
->dwAspect
= 1;
393 /* Create a clipboard enumerator */
394 hr
= CreateFormatEnumerator(dwNumValues
, formatList
, &pIEnumFormatEtc
);
395 HeapFree(GetProcessHeap(), 0, formatList
);
396 if (FAILED(hr
)) goto exit
;
398 /* Set our enumerator as the browsers property */
399 V_VT(&var
) = VT_UNKNOWN
;
400 V_UNKNOWN(&var
) = (IUnknown
*)pIEnumFormatEtc
;
402 property
= SysAllocString(szProperty
);
403 hr
= IWebBrowserApp_PutProperty(pBrowser
, property
, var
);
404 SysFreeString(property
);
407 IEnumFORMATETC_Release(pIEnumFormatEtc
);
412 if (V_VT(&var
) == VT_UNKNOWN
)
414 /* Our variant is holding the clipboard enumerator */
415 IUnknown
* pIUnknown
= V_UNKNOWN(&var
);
416 IEnumFORMATETC
* pClone
= NULL
;
418 TRACE("Retrieved IEnumFORMATETC property\n");
420 /* Get an IEnumFormatEtc interface from the variants value */
421 pIEnumFormatEtc
= NULL
;
422 hr
= IUnknown_QueryInterface(pIUnknown
, &IID_IEnumFORMATETC
, (void**)&pIEnumFormatEtc
);
423 if (hr
== S_OK
&& pIEnumFormatEtc
)
425 /* Clone and register the enumerator */
426 hr
= IEnumFORMATETC_Clone(pIEnumFormatEtc
, &pClone
);
427 if (hr
== S_OK
&& pClone
)
429 RegisterFormatEnumerator(lpBC
, pClone
, 0);
431 IEnumFORMATETC_Release(pClone
);
434 IUnknown_Release(pIUnknown
);
436 IUnknown_Release(V_UNKNOWN(&var
));
440 IWebBrowserApp_Release(pBrowser
);
444 /*************************************************************************
447 * Convert a GUID to a string.
450 * guid [I] GUID to convert
451 * lpszDest [O] Destination for string
452 * cchMax [I] Length of output buffer
455 * The length of the string created.
457 INT WINAPI
SHStringFromGUIDA(REFGUID guid
, LPSTR lpszDest
, INT cchMax
)
462 TRACE("(%s,%p,%d)\n", debugstr_guid(guid
), lpszDest
, cchMax
);
464 sprintf(xguid
, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
465 guid
->Data1
, guid
->Data2
, guid
->Data3
,
466 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
467 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
469 iLen
= strlen(xguid
) + 1;
473 memcpy(lpszDest
, xguid
, iLen
);
477 /*************************************************************************
480 * Convert a GUID to a string.
483 * guid [I] GUID to convert
484 * str [O] Destination for string
485 * cmax [I] Length of output buffer
488 * The length of the string created.
490 INT WINAPI
SHStringFromGUIDW(REFGUID guid
, LPWSTR lpszDest
, INT cchMax
)
494 static const WCHAR wszFormat
[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
495 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
496 'X','%','0','2','X','%','0','2','X','}',0};
498 TRACE("(%s,%p,%d)\n", debugstr_guid(guid
), lpszDest
, cchMax
);
500 swprintf(xguid
, ARRAY_SIZE(xguid
), wszFormat
, guid
->Data1
, guid
->Data2
, guid
->Data3
,
501 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
502 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
504 iLen
= lstrlenW(xguid
) + 1;
508 memcpy(lpszDest
, xguid
, iLen
*sizeof(WCHAR
));
512 /*************************************************************************
516 BOOL WINAPI
GetStringType3ExW(LPWSTR src
, INT count
, LPWORD type
)
518 return GetStringTypeW(CT_CTYPE3
, src
, count
, type
);
521 /*************************************************************************
524 * Get an identification string for the OS and explorer.
527 * lpszDest [O] Destination for Id string
528 * dwDestLen [I] Length of lpszDest
531 * TRUE, If the string was created successfully
534 BOOL WINAPI
SHAboutInfoA(LPSTR lpszDest
, DWORD dwDestLen
)
538 TRACE("(%p,%d)\n", lpszDest
, dwDestLen
);
540 if (lpszDest
&& SHAboutInfoW(buff
, dwDestLen
))
542 WideCharToMultiByte(CP_ACP
, 0, buff
, -1, lpszDest
, dwDestLen
, NULL
, NULL
);
548 /*************************************************************************
551 * Unicode version of SHAboutInfoA.
553 BOOL WINAPI
SHAboutInfoW(LPWSTR lpszDest
, DWORD dwDestLen
)
555 static const WCHAR szIEKey
[] = { 'S','O','F','T','W','A','R','E','\\',
556 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
557 ' ','E','x','p','l','o','r','e','r','\0' };
558 static const WCHAR szWinNtKey
[] = { 'S','O','F','T','W','A','R','E','\\',
559 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
560 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
561 static const WCHAR szWinKey
[] = { 'S','O','F','T','W','A','R','E','\\',
562 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
563 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
564 static const WCHAR szRegKey
[] = { 'S','O','F','T','W','A','R','E','\\',
565 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
566 ' ','E','x','p','l','o','r','e','r','\\',
567 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
568 static const WCHAR szVersion
[] = { 'V','e','r','s','i','o','n','\0' };
569 static const WCHAR szCustomized
[] = { 'C','u','s','t','o','m','i','z','e','d',
570 'V','e','r','s','i','o','n','\0' };
571 static const WCHAR szOwner
[] = { 'R','e','g','i','s','t','e','r','e','d',
572 'O','w','n','e','r','\0' };
573 static const WCHAR szOrg
[] = { 'R','e','g','i','s','t','e','r','e','d',
574 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
575 static const WCHAR szProduct
[] = { 'P','r','o','d','u','c','t','I','d','\0' };
576 static const WCHAR szUpdate
[] = { 'I','E','A','K',
577 'U','p','d','a','t','e','U','r','l','\0' };
578 static const WCHAR szHelp
[] = { 'I','E','A','K',
579 'H','e','l','p','S','t','r','i','n','g','\0' };
584 TRACE("(%p,%d)\n", lpszDest
, dwDestLen
);
591 /* Try the NT key first, followed by 95/98 key */
592 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szWinNtKey
, 0, KEY_READ
, &hReg
) &&
593 RegOpenKeyExW(HKEY_LOCAL_MACHINE
, szWinKey
, 0, KEY_READ
, &hReg
))
599 if (!SHGetValueW(HKEY_LOCAL_MACHINE
, szIEKey
, szVersion
, &dwType
, buff
, &dwLen
))
601 DWORD dwStrLen
= lstrlenW(buff
);
602 dwLen
= 30 - dwStrLen
;
603 SHGetValueW(HKEY_LOCAL_MACHINE
, szIEKey
,
604 szCustomized
, &dwType
, buff
+dwStrLen
, &dwLen
);
606 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
608 /* ~Registered Owner */
611 if (SHGetValueW(hReg
, szOwner
, 0, &dwType
, buff
+1, &dwLen
))
613 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
615 /* ~Registered Organization */
617 if (SHGetValueW(hReg
, szOrg
, 0, &dwType
, buff
+1, &dwLen
))
619 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
621 /* FIXME: Not sure where this number comes from */
625 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
629 if (SHGetValueW(HKEY_LOCAL_MACHINE
, szRegKey
, szProduct
, &dwType
, buff
+1, &dwLen
))
631 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
635 if(SHGetValueW(HKEY_LOCAL_MACHINE
, szWinKey
, szUpdate
, &dwType
, buff
+1, &dwLen
))
637 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
639 /* ~IE Help String */
641 if(SHGetValueW(hReg
, szHelp
, 0, &dwType
, buff
+1, &dwLen
))
643 StrCatBuffW(lpszDest
, buff
, dwDestLen
);
649 /*************************************************************************
652 * Call IOleCommandTarget_QueryStatus() on an object.
655 * lpUnknown [I] Object supporting the IOleCommandTarget interface
656 * pguidCmdGroup [I] GUID for the command group
658 * prgCmds [O] Commands
659 * pCmdText [O] Command text
663 * Failure: E_FAIL, if lpUnknown is NULL.
664 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
665 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
667 HRESULT WINAPI
IUnknown_QueryStatus(IUnknown
* lpUnknown
, REFGUID pguidCmdGroup
,
668 ULONG cCmds
, OLECMD
*prgCmds
, OLECMDTEXT
* pCmdText
)
670 HRESULT hRet
= E_FAIL
;
672 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown
, pguidCmdGroup
, cCmds
, prgCmds
, pCmdText
);
676 IOleCommandTarget
* lpOle
;
678 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleCommandTarget
,
681 if (SUCCEEDED(hRet
) && lpOle
)
683 hRet
= IOleCommandTarget_QueryStatus(lpOle
, pguidCmdGroup
, cCmds
,
685 IOleCommandTarget_Release(lpOle
);
691 /*************************************************************************
694 * Call IOleCommandTarget_Exec() on an object.
697 * lpUnknown [I] Object supporting the IOleCommandTarget interface
698 * pguidCmdGroup [I] GUID for the command group
702 * Failure: E_FAIL, if lpUnknown is NULL.
703 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
704 * Otherwise, an error code from IOleCommandTarget_Exec().
706 HRESULT WINAPI
IUnknown_Exec(IUnknown
* lpUnknown
, REFGUID pguidCmdGroup
,
707 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
* pvaIn
,
710 HRESULT hRet
= E_FAIL
;
712 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown
, pguidCmdGroup
, nCmdID
,
713 nCmdexecopt
, pvaIn
, pvaOut
);
717 IOleCommandTarget
* lpOle
;
719 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleCommandTarget
,
721 if (SUCCEEDED(hRet
) && lpOle
)
723 hRet
= IOleCommandTarget_Exec(lpOle
, pguidCmdGroup
, nCmdID
,
724 nCmdexecopt
, pvaIn
, pvaOut
);
725 IOleCommandTarget_Release(lpOle
);
731 /*************************************************************************
734 * Retrieve, modify, and re-set a value from a window.
737 * hWnd [I] Window to get value from
738 * offset [I] Offset of value
739 * mask [I] Mask for flags
740 * flags [I] Bits to set in window value
743 * The new value as it was set, or 0 if any parameter is invalid.
746 * Only bits specified in mask are affected - set if present in flags and
749 LONG WINAPI
SHSetWindowBits(HWND hwnd
, INT offset
, UINT mask
, UINT flags
)
751 LONG ret
= GetWindowLongW(hwnd
, offset
);
752 LONG new_flags
= (flags
& mask
) | (ret
& ~mask
);
754 TRACE("%p %d %x %x\n", hwnd
, offset
, mask
, flags
);
756 if (new_flags
!= ret
)
757 ret
= SetWindowLongW(hwnd
, offset
, new_flags
);
761 /*************************************************************************
764 * Change a window's parent.
767 * hWnd [I] Window to change parent of
768 * hWndParent [I] New parent window
771 * The old parent of hWnd.
774 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
775 * If hWndParent is NOT NULL then we set the WS_CHILD style.
777 HWND WINAPI
SHSetParentHwnd(HWND hWnd
, HWND hWndParent
)
779 TRACE("%p, %p\n", hWnd
, hWndParent
);
781 if(GetParent(hWnd
) == hWndParent
)
785 SHSetWindowBits(hWnd
, GWL_STYLE
, WS_CHILD
| WS_POPUP
, WS_CHILD
);
787 SHSetWindowBits(hWnd
, GWL_STYLE
, WS_CHILD
| WS_POPUP
, WS_POPUP
);
789 return hWndParent
? SetParent(hWnd
, hWndParent
) : NULL
;
792 /*************************************************************************
795 * Locate and advise a connection point in an IConnectionPointContainer object.
798 * lpUnkSink [I] Sink for the connection point advise call
799 * riid [I] REFIID of connection point to advise
800 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
801 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
802 * lpCookie [O] Pointer to connection point cookie
803 * lppCP [O] Destination for the IConnectionPoint found
806 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
807 * that was advised. The caller is responsible for releasing it.
808 * Failure: E_FAIL, if any arguments are invalid.
809 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
810 * Or an HRESULT error code if any call fails.
812 HRESULT WINAPI
ConnectToConnectionPoint(IUnknown
* lpUnkSink
, REFIID riid
, BOOL fConnect
,
813 IUnknown
* lpUnknown
, LPDWORD lpCookie
,
814 IConnectionPoint
**lppCP
)
817 IConnectionPointContainer
* lpContainer
;
818 IConnectionPoint
*lpCP
;
820 if(!lpUnknown
|| (fConnect
&& !lpUnkSink
))
826 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IConnectionPointContainer
,
827 (void**)&lpContainer
);
830 hRet
= IConnectionPointContainer_FindConnectionPoint(lpContainer
, riid
, &lpCP
);
835 hRet
= IConnectionPoint_Unadvise(lpCP
, *lpCookie
);
837 hRet
= IConnectionPoint_Advise(lpCP
, lpUnkSink
, lpCookie
);
842 if (lppCP
&& SUCCEEDED(hRet
))
843 *lppCP
= lpCP
; /* Caller keeps the interface */
845 IConnectionPoint_Release(lpCP
); /* Release it */
848 IConnectionPointContainer_Release(lpContainer
);
853 /*************************************************************************
856 * Skip '//' if present in a string.
859 * lpszSrc [I] String to check for '//'
862 * Success: The next character after the '//' or the string if not present
863 * Failure: NULL, if lpszStr is NULL.
865 LPCSTR WINAPI
PathSkipLeadingSlashesA(LPCSTR lpszSrc
)
867 if (lpszSrc
&& lpszSrc
[0] == '/' && lpszSrc
[1] == '/')
872 /*************************************************************************
875 * Check if two interfaces come from the same object.
878 * lpInt1 [I] Interface to check against lpInt2.
879 * lpInt2 [I] Interface to check against lpInt1.
882 * TRUE, If the interfaces come from the same object.
885 BOOL WINAPI
SHIsSameObject(IUnknown
* lpInt1
, IUnknown
* lpInt2
)
887 IUnknown
*lpUnknown1
, *lpUnknown2
;
890 TRACE("(%p %p)\n", lpInt1
, lpInt2
);
892 if (!lpInt1
|| !lpInt2
)
895 if (lpInt1
== lpInt2
)
898 if (IUnknown_QueryInterface(lpInt1
, &IID_IUnknown
, (void**)&lpUnknown1
) != S_OK
)
901 if (IUnknown_QueryInterface(lpInt2
, &IID_IUnknown
, (void**)&lpUnknown2
) != S_OK
)
903 IUnknown_Release(lpUnknown1
);
907 ret
= lpUnknown1
== lpUnknown2
;
909 IUnknown_Release(lpUnknown1
);
910 IUnknown_Release(lpUnknown2
);
915 /*************************************************************************
918 * Get the window handle of an object.
921 * lpUnknown [I] Object to get the window handle of
922 * lphWnd [O] Destination for window handle
925 * Success: S_OK. lphWnd contains the objects window handle.
926 * Failure: An HRESULT error code.
929 * lpUnknown is expected to support one of the following interfaces:
930 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
932 HRESULT WINAPI
IUnknown_GetWindow(IUnknown
*lpUnknown
, HWND
*lphWnd
)
935 HRESULT hRet
= E_FAIL
;
937 TRACE("(%p,%p)\n", lpUnknown
, lphWnd
);
942 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleWindow
, (void**)&lpOle
);
946 hRet
= IUnknown_QueryInterface(lpUnknown
,&IID_IShellView
, (void**)&lpOle
);
950 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInternetSecurityMgrSite
,
957 /* Laziness here - Since GetWindow() is the first method for the above 3
958 * interfaces, we use the same call for them all.
960 hRet
= IOleWindow_GetWindow((IOleWindow
*)lpOle
, lphWnd
);
961 IUnknown_Release(lpOle
);
963 TRACE("Returning HWND=%p\n", *lphWnd
);
969 /*************************************************************************
972 * Call a SetOwner method of IShellService from specified object.
975 * iface [I] Object that supports IShellService
976 * pUnk [I] Argument for the SetOwner call
979 * Corresponding return value from last call or E_FAIL for null input
981 HRESULT WINAPI
IUnknown_SetOwner(IUnknown
*iface
, IUnknown
*pUnk
)
983 IShellService
*service
;
986 TRACE("(%p, %p)\n", iface
, pUnk
);
988 if (!iface
) return E_FAIL
;
990 hr
= IUnknown_QueryInterface(iface
, &IID_IShellService
, (void**)&service
);
993 hr
= IShellService_SetOwner(service
, pUnk
);
994 IShellService_Release(service
);
1000 /*************************************************************************
1003 * Call IPersist_GetClassID() on an object.
1006 * lpUnknown [I] Object supporting the IPersist interface
1007 * clsid [O] Destination for Class Id
1010 * Success: S_OK. lpClassId contains the Class Id requested.
1011 * Failure: E_FAIL, If lpUnknown is NULL,
1012 * E_NOINTERFACE If lpUnknown does not support IPersist,
1013 * Or an HRESULT error code.
1015 HRESULT WINAPI
IUnknown_GetClassID(IUnknown
*lpUnknown
, CLSID
*clsid
)
1020 TRACE("(%p, %p)\n", lpUnknown
, clsid
);
1024 memset(clsid
, 0, sizeof(*clsid
));
1028 hr
= IUnknown_QueryInterface(lpUnknown
, &IID_IPersist
, (void**)&persist
);
1031 hr
= IUnknown_QueryInterface(lpUnknown
, &IID_IPersistFolder
, (void**)&persist
);
1036 hr
= IPersist_GetClassID(persist
, clsid
);
1037 IPersist_Release(persist
);
1041 static HRESULT
iunknown_query_service(IUnknown
* lpUnknown
, REFGUID sid
, REFIID riid
, LPVOID
*lppOut
)
1043 IServiceProvider
* pService
= NULL
;
1054 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IServiceProvider
,
1055 (LPVOID
*)&pService
);
1057 if (hRet
== S_OK
&& pService
)
1059 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService
);
1061 /* Get a Service interface from the object */
1062 hRet
= IServiceProvider_QueryService(pService
, sid
, riid
, lppOut
);
1064 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService
, *lppOut
);
1066 IServiceProvider_Release(pService
);
1071 /*************************************************************************
1074 * Calls IOleCommandTarget::Exec() for specified service object.
1077 * lpUnknown [I] Object to get an IServiceProvider interface from
1078 * service [I] Service ID for IServiceProvider_QueryService() call
1079 * group [I] Group ID for IOleCommandTarget::Exec() call
1080 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1081 * cmdOpt [I] Options flags for command
1082 * pIn [I] Input arguments for command
1083 * pOut [O] Output arguments for command
1086 * Success: S_OK. lppOut contains an object providing the requested service
1087 * Failure: An HRESULT error code
1090 * lpUnknown is expected to support the IServiceProvider interface.
1092 HRESULT WINAPI
IUnknown_QueryServiceExec(IUnknown
*lpUnknown
, REFIID service
,
1093 const GUID
*group
, DWORD cmdId
, DWORD cmdOpt
, VARIANT
*pIn
, VARIANT
*pOut
)
1095 IOleCommandTarget
*target
;
1098 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown
, debugstr_guid(service
),
1099 debugstr_guid(group
), cmdId
, cmdOpt
, pIn
, pOut
);
1101 hr
= iunknown_query_service(lpUnknown
, service
, &IID_IOleCommandTarget
, (void**)&target
);
1104 hr
= IOleCommandTarget_Exec(target
, group
, cmdId
, cmdOpt
, pIn
, pOut
);
1105 IOleCommandTarget_Release(target
);
1108 TRACE("<-- hr=0x%08x\n", hr
);
1113 /*************************************************************************
1116 * Calls IProfferService methods to proffer/revoke specified service.
1119 * lpUnknown [I] Object to get an IServiceProvider interface from
1120 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1121 * pService [I] Service to proffer. If NULL ::Revoke is called
1122 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1125 * Success: S_OK. IProffer method returns S_OK
1126 * Failure: An HRESULT error code
1129 * lpUnknown is expected to support the IServiceProvider interface.
1131 HRESULT WINAPI
IUnknown_ProfferService(IUnknown
*lpUnknown
, REFGUID service
, IServiceProvider
*pService
, DWORD
*pCookie
)
1133 IProfferService
*proffer
;
1136 TRACE("%p %s %p %p\n", lpUnknown
, debugstr_guid(service
), pService
, pCookie
);
1138 hr
= iunknown_query_service(lpUnknown
, &IID_IProfferService
, &IID_IProfferService
, (void**)&proffer
);
1142 hr
= IProfferService_ProfferService(proffer
, service
, pService
, pCookie
);
1145 hr
= IProfferService_RevokeService(proffer
, *pCookie
);
1149 IProfferService_Release(proffer
);
1155 /*************************************************************************
1158 * Call an object's UIActivateIO method.
1161 * unknown [I] Object to call the UIActivateIO method on
1162 * activate [I] Parameter for UIActivateIO call
1163 * msg [I] Parameter for UIActivateIO call
1166 * Success: Value of UI_ActivateIO call
1167 * Failure: An HRESULT error code
1170 * unknown is expected to support the IInputObject interface.
1172 HRESULT WINAPI
IUnknown_UIActivateIO(IUnknown
*unknown
, BOOL activate
, LPMSG msg
)
1174 IInputObject
* object
= NULL
;
1180 /* Get an IInputObject interface from the object */
1181 ret
= IUnknown_QueryInterface(unknown
, &IID_IInputObject
, (LPVOID
*) &object
);
1185 ret
= IInputObject_UIActivateIO(object
, activate
, msg
);
1186 IInputObject_Release(object
);
1192 /*************************************************************************
1195 * Loads a popup menu.
1198 * hInst [I] Instance handle
1199 * szName [I] Menu name
1205 BOOL WINAPI
SHLoadMenuPopup(HINSTANCE hInst
, LPCWSTR szName
)
1209 TRACE("%p %s\n", hInst
, debugstr_w(szName
));
1211 if ((hMenu
= LoadMenuW(hInst
, szName
)))
1213 if (GetSubMenu(hMenu
, 0))
1214 RemoveMenu(hMenu
, 0, MF_BYPOSITION
);
1222 typedef struct _enumWndData
1227 LRESULT (WINAPI
*pfnPost
)(HWND
,UINT
,WPARAM
,LPARAM
);
1230 /* Callback for SHLWAPI_178 */
1231 static BOOL CALLBACK
SHLWAPI_EnumChildProc(HWND hWnd
, LPARAM lParam
)
1233 enumWndData
*data
= (enumWndData
*)lParam
;
1235 TRACE("(%p,%p)\n", hWnd
, data
);
1236 data
->pfnPost(hWnd
, data
->uiMsgId
, data
->wParam
, data
->lParam
);
1240 /*************************************************************************
1243 * Send or post a message to every child of a window.
1246 * hWnd [I] Window whose children will get the messages
1247 * uiMsgId [I] Message Id
1248 * wParam [I] WPARAM of message
1249 * lParam [I] LPARAM of message
1250 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1256 * The appropriate ASCII or Unicode function is called for the window.
1258 void WINAPI
SHPropagateMessage(HWND hWnd
, UINT uiMsgId
, WPARAM wParam
, LPARAM lParam
, BOOL bSend
)
1262 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd
, uiMsgId
, wParam
, lParam
, bSend
);
1266 data
.uiMsgId
= uiMsgId
;
1267 data
.wParam
= wParam
;
1268 data
.lParam
= lParam
;
1271 data
.pfnPost
= IsWindowUnicode(hWnd
) ? (void*)SendMessageW
: (void*)SendMessageA
;
1273 data
.pfnPost
= IsWindowUnicode(hWnd
) ? (void*)PostMessageW
: (void*)PostMessageA
;
1275 EnumChildWindows(hWnd
, SHLWAPI_EnumChildProc
, (LPARAM
)&data
);
1279 /*************************************************************************
1282 * Remove all sub-menus from a menu.
1285 * hMenu [I] Menu to remove sub-menus from
1288 * Success: 0. All sub-menus under hMenu are removed
1289 * Failure: -1, if any parameter is invalid
1291 DWORD WINAPI
SHRemoveAllSubMenus(HMENU hMenu
)
1293 int iItemCount
= GetMenuItemCount(hMenu
) - 1;
1295 TRACE("%p\n", hMenu
);
1297 while (iItemCount
>= 0)
1299 HMENU hSubMenu
= GetSubMenu(hMenu
, iItemCount
);
1301 RemoveMenu(hMenu
, iItemCount
, MF_BYPOSITION
);
1307 /*************************************************************************
1310 * Enable or disable a menu item.
1313 * hMenu [I] Menu holding menu item
1314 * uID [I] ID of menu item to enable/disable
1315 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1318 * The return code from EnableMenuItem.
1320 UINT WINAPI
SHEnableMenuItem(HMENU hMenu
, UINT wItemID
, BOOL bEnable
)
1322 TRACE("%p, %u, %d\n", hMenu
, wItemID
, bEnable
);
1323 return EnableMenuItem(hMenu
, wItemID
, bEnable
? MF_ENABLED
: MF_GRAYED
);
1326 /*************************************************************************
1329 * Check or uncheck a menu item.
1332 * hMenu [I] Menu holding menu item
1333 * uID [I] ID of menu item to check/uncheck
1334 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1337 * The return code from CheckMenuItem.
1339 DWORD WINAPI
SHCheckMenuItem(HMENU hMenu
, UINT uID
, BOOL bCheck
)
1341 TRACE("%p, %u, %d\n", hMenu
, uID
, bCheck
);
1342 return CheckMenuItem(hMenu
, uID
, bCheck
? MF_CHECKED
: MF_UNCHECKED
);
1345 /*************************************************************************
1348 * Register a window class if it isn't already.
1351 * lpWndClass [I] Window class to register
1354 * The result of the RegisterClassA call.
1356 DWORD WINAPI
SHRegisterClassA(WNDCLASSA
*wndclass
)
1359 if (GetClassInfoA(wndclass
->hInstance
, wndclass
->lpszClassName
, &wca
))
1361 return (DWORD
)RegisterClassA(wndclass
);
1364 /*************************************************************************
1367 BOOL WINAPI
SHSimulateDrop(IDropTarget
*pDrop
, IDataObject
*pDataObj
,
1368 DWORD grfKeyState
, PPOINTL lpPt
, DWORD
* pdwEffect
)
1370 DWORD dwEffect
= DROPEFFECT_LINK
| DROPEFFECT_MOVE
| DROPEFFECT_COPY
;
1371 POINTL pt
= { 0, 0 };
1373 TRACE("%p %p 0x%08x %p %p\n", pDrop
, pDataObj
, grfKeyState
, lpPt
, pdwEffect
);
1379 pdwEffect
= &dwEffect
;
1381 IDropTarget_DragEnter(pDrop
, pDataObj
, grfKeyState
, *lpPt
, pdwEffect
);
1383 if (*pdwEffect
!= DROPEFFECT_NONE
)
1384 return IDropTarget_Drop(pDrop
, pDataObj
, grfKeyState
, *lpPt
, pdwEffect
);
1386 IDropTarget_DragLeave(pDrop
);
1390 /*************************************************************************
1393 * Call IPersistPropertyBag_Load() on an object.
1396 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1397 * lpPropBag [O] Destination for loaded IPropertyBag
1401 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1403 DWORD WINAPI
SHLoadFromPropertyBag(IUnknown
*lpUnknown
, IPropertyBag
* lpPropBag
)
1405 IPersistPropertyBag
* lpPPBag
;
1406 HRESULT hRet
= E_FAIL
;
1408 TRACE("(%p,%p)\n", lpUnknown
, lpPropBag
);
1412 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IPersistPropertyBag
,
1414 if (SUCCEEDED(hRet
) && lpPPBag
)
1416 hRet
= IPersistPropertyBag_Load(lpPPBag
, lpPropBag
, NULL
);
1417 IPersistPropertyBag_Release(lpPPBag
);
1423 /*************************************************************************
1426 * Call IOleControlSite_TranslateAccelerator() on an object.
1429 * lpUnknown [I] Object supporting the IOleControlSite interface.
1430 * lpMsg [I] Key message to be processed.
1431 * dwModifiers [I] Flags containing the state of the modifier keys.
1435 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1437 HRESULT WINAPI
IUnknown_TranslateAcceleratorOCS(IUnknown
*lpUnknown
, LPMSG lpMsg
, DWORD dwModifiers
)
1439 IOleControlSite
* lpCSite
= NULL
;
1440 HRESULT hRet
= E_INVALIDARG
;
1442 TRACE("(%p,%p,0x%08x)\n", lpUnknown
, lpMsg
, dwModifiers
);
1445 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleControlSite
,
1447 if (SUCCEEDED(hRet
) && lpCSite
)
1449 hRet
= IOleControlSite_TranslateAccelerator(lpCSite
, lpMsg
, dwModifiers
);
1450 IOleControlSite_Release(lpCSite
);
1457 /*************************************************************************
1460 * Call IOleControlSite_OnFocus() on an object.
1463 * lpUnknown [I] Object supporting the IOleControlSite interface.
1464 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1468 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1470 HRESULT WINAPI
IUnknown_OnFocusOCS(IUnknown
*lpUnknown
, BOOL fGotFocus
)
1472 IOleControlSite
* lpCSite
= NULL
;
1473 HRESULT hRet
= E_FAIL
;
1475 TRACE("(%p, %d)\n", lpUnknown
, fGotFocus
);
1478 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IOleControlSite
,
1480 if (SUCCEEDED(hRet
) && lpCSite
)
1482 hRet
= IOleControlSite_OnFocus(lpCSite
, fGotFocus
);
1483 IOleControlSite_Release(lpCSite
);
1489 /*************************************************************************
1492 HRESULT WINAPI
IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown
, PVOID lpArg1
,
1493 PVOID lpArg2
, PVOID lpArg3
, PVOID lpArg4
)
1495 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1496 static const DWORD service_id
[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1497 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1498 static const DWORD function_id
[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1499 HRESULT hRet
= E_INVALIDARG
;
1500 LPUNKNOWN lpUnkInner
= NULL
; /* FIXME: Real type is unknown */
1502 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown
, lpArg1
, lpArg2
, lpArg3
, lpArg4
);
1504 if (lpUnknown
&& lpArg4
)
1506 hRet
= iunknown_query_service(lpUnknown
, (REFGUID
)service_id
,
1507 (REFGUID
)function_id
, (void**)&lpUnkInner
);
1509 if (SUCCEEDED(hRet
) && lpUnkInner
)
1511 /* FIXME: The type of service object requested is unknown, however
1512 * testing shows that its first method is called with 4 parameters.
1513 * Fake this by using IParseDisplayName_ParseDisplayName since the
1514 * signature and position in the vtable matches our unknown object type.
1516 hRet
= IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME
)lpUnkInner
,
1517 lpArg1
, lpArg2
, lpArg3
, lpArg4
);
1518 IUnknown_Release(lpUnkInner
);
1524 /*************************************************************************
1527 * Get a sub-menu from a menu item.
1530 * hMenu [I] Menu to get sub-menu from
1531 * uID [I] ID of menu item containing sub-menu
1534 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1536 HMENU WINAPI
SHGetMenuFromID(HMENU hMenu
, UINT uID
)
1540 TRACE("(%p,%u)\n", hMenu
, uID
);
1542 mi
.cbSize
= sizeof(mi
);
1543 mi
.fMask
= MIIM_SUBMENU
;
1545 if (!GetMenuItemInfoW(hMenu
, uID
, FALSE
, &mi
))
1551 /*************************************************************************
1554 * Get the color depth of the primary display.
1560 * The color depth of the primary display.
1562 DWORD WINAPI
SHGetCurColorRes(void)
1570 ret
= GetDeviceCaps(hdc
, BITSPIXEL
) * GetDeviceCaps(hdc
, PLANES
);
1575 /*************************************************************************
1578 * Wait for a message to arrive, with a timeout.
1581 * hand [I] Handle to query
1582 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1585 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1586 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1587 * message is available.
1589 DWORD WINAPI
SHWaitForSendMessageThread(HANDLE hand
, DWORD dwTimeout
)
1591 DWORD dwEndTicks
= GetTickCount() + dwTimeout
;
1594 while ((dwRet
= MsgWaitForMultipleObjectsEx(1, &hand
, dwTimeout
, QS_SENDMESSAGE
, 0)) == 1)
1598 PeekMessageW(&msg
, NULL
, 0, 0, PM_NOREMOVE
);
1600 if (dwTimeout
!= INFINITE
)
1602 if ((int)(dwTimeout
= dwEndTicks
- GetTickCount()) <= 0)
1603 return WAIT_TIMEOUT
;
1610 /*************************************************************************
1613 * Determine if a shell folder can be expanded.
1616 * lpFolder [I] Parent folder containing the object to test.
1617 * pidl [I] Id of the object to test.
1620 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
1621 * Failure: E_INVALIDARG, if any argument is invalid.
1624 * If the object to be tested does not expose the IQueryInfo() interface it
1625 * will not be identified as an expandable folder.
1627 HRESULT WINAPI
SHIsExpandableFolder(LPSHELLFOLDER lpFolder
, LPCITEMIDLIST pidl
)
1629 HRESULT hRet
= E_INVALIDARG
;
1632 if (lpFolder
&& pidl
)
1634 hRet
= IShellFolder_GetUIObjectOf(lpFolder
, NULL
, 1, &pidl
, &IID_IQueryInfo
,
1635 NULL
, (void**)&lpInfo
);
1637 hRet
= S_FALSE
; /* Doesn't expose IQueryInfo */
1642 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
1643 * currently used". Really? You wouldn't be holding out on me would you?
1645 hRet
= IQueryInfo_GetInfoFlags(lpInfo
, &dwFlags
);
1647 if (SUCCEEDED(hRet
))
1649 /* 0x2 is an undocumented flag apparently indicating expandability */
1650 hRet
= dwFlags
& 0x2 ? S_OK
: S_FALSE
;
1653 IQueryInfo_Release(lpInfo
);
1659 /*************************************************************************
1662 * Blank out a region of text by drawing the background only.
1665 * hDC [I] Device context to draw in
1666 * pRect [I] Area to draw in
1667 * cRef [I] Color to draw in
1672 DWORD WINAPI
SHFillRectClr(HDC hDC
, LPCRECT pRect
, COLORREF cRef
)
1674 COLORREF cOldColor
= SetBkColor(hDC
, cRef
);
1675 ExtTextOutA(hDC
, 0, 0, ETO_OPAQUE
, pRect
, 0, 0, 0);
1676 SetBkColor(hDC
, cOldColor
);
1680 /*************************************************************************
1683 * Return the value associated with a key in a map.
1686 * lpKeys [I] A list of keys of length iLen
1687 * lpValues [I] A list of values associated with lpKeys, of length iLen
1688 * iLen [I] Length of both lpKeys and lpValues
1689 * iKey [I] The key value to look up in lpKeys
1692 * The value in lpValues associated with iKey, or -1 if iKey is not
1696 * - If two elements in the map share the same key, this function returns
1697 * the value closest to the start of the map
1698 * - The native version of this function crashes if lpKeys or lpValues is NULL.
1700 int WINAPI
SHSearchMapInt(const int *lpKeys
, const int *lpValues
, int iLen
, int iKey
)
1702 if (lpKeys
&& lpValues
)
1708 if (lpKeys
[i
] == iKey
)
1709 return lpValues
[i
]; /* Found */
1713 return -1; /* Not found */
1716 /*************************************************************************
1720 HRESULT WINAPI
MayQSForward(IUnknown
* lpUnknown
, PVOID lpReserved
,
1721 REFGUID riidCmdGrp
, ULONG cCmds
,
1722 OLECMD
*prgCmds
, OLECMDTEXT
* pCmdText
)
1724 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
1725 lpUnknown
, lpReserved
, riidCmdGrp
, cCmds
, prgCmds
, pCmdText
);
1727 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
1728 return DRAGDROP_E_NOTREGISTERED
;
1731 /*************************************************************************
1735 HRESULT WINAPI
MayExecForward(IUnknown
* lpUnknown
, INT iUnk
, REFGUID pguidCmdGroup
,
1736 DWORD nCmdID
, DWORD nCmdexecopt
, VARIANT
* pvaIn
,
1739 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown
, iUnk
, pguidCmdGroup
,
1740 nCmdID
, nCmdexecopt
, pvaIn
, pvaOut
);
1741 return DRAGDROP_E_NOTREGISTERED
;
1744 /*************************************************************************
1748 HRESULT WINAPI
IsQSForward(REFGUID pguidCmdGroup
,ULONG cCmds
, OLECMD
*prgCmds
)
1750 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup
, cCmds
, prgCmds
);
1751 return DRAGDROP_E_NOTREGISTERED
;
1754 /*************************************************************************
1757 * Determine if a window is not a child of another window.
1760 * hParent [I] Suspected parent window
1761 * hChild [I] Suspected child window
1764 * TRUE: If hChild is a child window of hParent
1765 * FALSE: If hChild is not a child window of hParent, or they are equal
1767 BOOL WINAPI
SHIsChildOrSelf(HWND hParent
, HWND hChild
)
1769 TRACE("(%p,%p)\n", hParent
, hChild
);
1771 if (!hParent
|| !hChild
)
1773 else if(hParent
== hChild
)
1775 return !IsChild(hParent
, hChild
);
1778 /*************************************************************************
1779 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
1784 DWORD num_items
; /* Number of elements inserted */
1785 void *mem
; /* Ptr to array */
1786 DWORD blocks_alloced
; /* Number of elements allocated */
1787 BYTE inc
; /* Number of elements to grow by when we need to expand */
1788 BYTE block_size
; /* Size in bytes of an element */
1789 BYTE flags
; /* Flags */
1792 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
1794 /*************************************************************************
1797 * Initialize an FDSA array.
1799 BOOL WINAPI
FDSA_Initialize(DWORD block_size
, DWORD inc
, FDSA_info
*info
, void *mem
,
1802 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size
, inc
, info
, mem
, init_blocks
);
1808 memset(mem
, 0, block_size
* init_blocks
);
1810 info
->num_items
= 0;
1813 info
->blocks_alloced
= init_blocks
;
1814 info
->block_size
= block_size
;
1820 /*************************************************************************
1823 * Destroy an FDSA array
1825 BOOL WINAPI
FDSA_Destroy(FDSA_info
*info
)
1827 TRACE("(%p)\n", info
);
1829 if(info
->flags
& FDSA_FLAG_INTERNAL_ALLOC
)
1831 HeapFree(GetProcessHeap(), 0, info
->mem
);
1838 /*************************************************************************
1841 * Insert element into an FDSA array
1843 DWORD WINAPI
FDSA_InsertItem(FDSA_info
*info
, DWORD where
, const void *block
)
1845 TRACE("(%p 0x%08x %p)\n", info
, where
, block
);
1846 if(where
> info
->num_items
)
1847 where
= info
->num_items
;
1849 if(info
->num_items
>= info
->blocks_alloced
)
1851 DWORD size
= (info
->blocks_alloced
+ info
->inc
) * info
->block_size
;
1852 if(info
->flags
& 0x1)
1853 info
->mem
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, info
->mem
, size
);
1856 void *old_mem
= info
->mem
;
1857 info
->mem
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1858 memcpy(info
->mem
, old_mem
, info
->blocks_alloced
* info
->block_size
);
1860 info
->blocks_alloced
+= info
->inc
;
1864 if(where
< info
->num_items
)
1866 memmove((char*)info
->mem
+ (where
+ 1) * info
->block_size
,
1867 (char*)info
->mem
+ where
* info
->block_size
,
1868 (info
->num_items
- where
) * info
->block_size
);
1870 memcpy((char*)info
->mem
+ where
* info
->block_size
, block
, info
->block_size
);
1876 /*************************************************************************
1879 * Delete an element from an FDSA array.
1881 BOOL WINAPI
FDSA_DeleteItem(FDSA_info
*info
, DWORD where
)
1883 TRACE("(%p 0x%08x)\n", info
, where
);
1885 if(where
>= info
->num_items
)
1888 if(where
< info
->num_items
- 1)
1890 memmove((char*)info
->mem
+ where
* info
->block_size
,
1891 (char*)info
->mem
+ (where
+ 1) * info
->block_size
,
1892 (info
->num_items
- where
- 1) * info
->block_size
);
1894 memset((char*)info
->mem
+ (info
->num_items
- 1) * info
->block_size
,
1895 0, info
->block_size
);
1899 /*************************************************************************
1902 * Set the Font for a window and the "PropDlgFont" property of the parent window.
1905 * hWnd [I] Parent Window to set the property
1906 * id [I] Index of child Window to set the Font
1912 HRESULT WINAPI
SHSetDefaultDialogFont(HWND hWnd
, INT id
)
1914 FIXME("(%p, %d) stub\n", hWnd
, id
);
1918 /*************************************************************************
1921 * Remove the "PropDlgFont" property from a window.
1924 * hWnd [I] Window to remove the property from
1927 * A handle to the removed property, or NULL if it did not exist.
1929 HANDLE WINAPI
SHRemoveDefaultDialogFont(HWND hWnd
)
1933 TRACE("(%p)\n", hWnd
);
1935 hProp
= GetPropA(hWnd
, "PropDlgFont");
1939 DeleteObject(hProp
);
1940 hProp
= RemovePropA(hWnd
, "PropDlgFont");
1945 /*************************************************************************
1948 * Load the in-process server of a given GUID.
1951 * refiid [I] GUID of the server to load.
1954 * Success: A handle to the loaded server dll.
1955 * Failure: A NULL handle.
1957 HMODULE WINAPI
SHPinDllOfCLSID(REFIID refiid
)
1961 CHAR value
[MAX_PATH
], string
[MAX_PATH
];
1963 strcpy(string
, "CLSID\\");
1964 SHStringFromGUIDA(refiid
, string
+ 6, ARRAY_SIZE(string
) - 6);
1965 strcat(string
, "\\InProcServer32");
1968 RegOpenKeyExA(HKEY_CLASSES_ROOT
, string
, 0, 1, &newkey
);
1969 RegQueryValueExA(newkey
, 0, 0, &type
, (PBYTE
)value
, &count
);
1970 RegCloseKey(newkey
);
1971 return LoadLibraryExA(value
, 0, 0);
1974 /*************************************************************************
1977 * Unicode version of SHLWAPI_183.
1979 DWORD WINAPI
SHRegisterClassW(WNDCLASSW
* lpWndClass
)
1983 TRACE("(%p %s)\n",lpWndClass
->hInstance
, debugstr_w(lpWndClass
->lpszClassName
));
1985 if (GetClassInfoW(lpWndClass
->hInstance
, lpWndClass
->lpszClassName
, &WndClass
))
1987 return RegisterClassW(lpWndClass
);
1990 /*************************************************************************
1993 * Unregister a list of classes.
1996 * hInst [I] Application instance that registered the classes
1997 * lppClasses [I] List of class names
1998 * iCount [I] Number of names in lppClasses
2003 void WINAPI
SHUnregisterClassesA(HINSTANCE hInst
, LPCSTR
*lppClasses
, INT iCount
)
2007 TRACE("(%p,%p,%d)\n", hInst
, lppClasses
, iCount
);
2011 if (GetClassInfoA(hInst
, *lppClasses
, &WndClass
))
2012 UnregisterClassA(*lppClasses
, hInst
);
2018 /*************************************************************************
2021 * Unicode version of SHUnregisterClassesA.
2023 void WINAPI
SHUnregisterClassesW(HINSTANCE hInst
, LPCWSTR
*lppClasses
, INT iCount
)
2027 TRACE("(%p,%p,%d)\n", hInst
, lppClasses
, iCount
);
2031 if (GetClassInfoW(hInst
, *lppClasses
, &WndClass
))
2032 UnregisterClassW(*lppClasses
, hInst
);
2038 /*************************************************************************
2041 * Call The correct (Ascii/Unicode) default window procedure for a window.
2044 * hWnd [I] Window to call the default procedure for
2045 * uMessage [I] Message ID
2046 * wParam [I] WPARAM of message
2047 * lParam [I] LPARAM of message
2050 * The result of calling DefWindowProcA() or DefWindowProcW().
2052 LRESULT CALLBACK
SHDefWindowProc(HWND hWnd
, UINT uMessage
, WPARAM wParam
, LPARAM lParam
)
2054 if (IsWindowUnicode(hWnd
))
2055 return DefWindowProcW(hWnd
, uMessage
, wParam
, lParam
);
2056 return DefWindowProcA(hWnd
, uMessage
, wParam
, lParam
);
2059 /*************************************************************************
2062 * Create a worker window using CreateWindowExA().
2065 * wndProc [I] Window procedure
2066 * hWndParent [I] Parent window
2067 * dwExStyle [I] Extra style flags
2068 * dwStyle [I] Style flags
2069 * hMenu [I] Window menu
2070 * wnd_extra [I] Window extra bytes value
2073 * Success: The window handle of the newly created window.
2076 HWND WINAPI
SHCreateWorkerWindowA(WNDPROC wndProc
, HWND hWndParent
, DWORD dwExStyle
,
2077 DWORD dwStyle
, HMENU hMenu
, LONG_PTR wnd_extra
)
2079 static const char szClass
[] = "WorkerA";
2083 TRACE("(%p, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2084 wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, wnd_extra
);
2086 /* Create Window class */
2088 wc
.lpfnWndProc
= DefWindowProcA
;
2090 wc
.cbWndExtra
= sizeof(LONG_PTR
);
2091 wc
.hInstance
= shlwapi_hInstance
;
2093 wc
.hCursor
= LoadCursorA(NULL
, (LPSTR
)IDC_ARROW
);
2094 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2095 wc
.lpszMenuName
= NULL
;
2096 wc
.lpszClassName
= szClass
;
2098 SHRegisterClassA(&wc
);
2100 hWnd
= CreateWindowExA(dwExStyle
, szClass
, 0, dwStyle
, 0, 0, 0, 0,
2101 hWndParent
, hMenu
, shlwapi_hInstance
, 0);
2104 SetWindowLongPtrW(hWnd
, 0, wnd_extra
);
2105 if (wndProc
) SetWindowLongPtrA(hWnd
, GWLP_WNDPROC
, (LONG_PTR
)wndProc
);
2111 typedef struct tagPOLICYDATA
2113 DWORD policy
; /* flags value passed to SHRestricted */
2114 LPCWSTR appstr
; /* application str such as "Explorer" */
2115 LPCWSTR keystr
; /* name of the actual registry key / policy */
2116 } POLICYDATA
, *LPPOLICYDATA
;
2118 #define SHELL_NO_POLICY 0xffffffff
2120 /* default shell policy registry key */
2121 static const WCHAR strRegistryPolicyW
[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2122 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2123 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2124 '\\','P','o','l','i','c','i','e','s',0};
2126 /*************************************************************************
2129 * Retrieve a policy value from the registry.
2132 * lpSubKey [I] registry key name
2133 * lpSubName [I] subname of registry key
2134 * lpValue [I] value name of registry value
2137 * the value associated with the registry key or 0 if not found
2139 DWORD WINAPI
SHGetRestriction(LPCWSTR lpSubKey
, LPCWSTR lpSubName
, LPCWSTR lpValue
)
2141 DWORD retval
, datsize
= sizeof(retval
);
2145 lpSubKey
= strRegistryPolicyW
;
2147 retval
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, lpSubKey
, &hKey
);
2148 if (retval
!= ERROR_SUCCESS
)
2149 retval
= RegOpenKeyW(HKEY_CURRENT_USER
, lpSubKey
, &hKey
);
2150 if (retval
!= ERROR_SUCCESS
)
2153 SHGetValueW(hKey
, lpSubName
, lpValue
, NULL
, &retval
, &datsize
);
2158 /*************************************************************************
2161 * Helper function to retrieve the possibly cached value for a specific policy
2164 * policy [I] The policy to look for
2165 * initial [I] Main registry key to open, if NULL use default
2166 * polTable [I] Table of known policies, 0 terminated
2167 * polArr [I] Cache array of policy values
2170 * The retrieved policy value or 0 if not successful
2173 * This function is used by the native SHRestricted function to search for the
2174 * policy and cache it once retrieved. The current Wine implementation uses a
2175 * different POLICYDATA structure and implements a similar algorithm adapted to
2178 DWORD WINAPI
SHRestrictionLookup(
2181 LPPOLICYDATA polTable
,
2184 TRACE("(0x%08x %s %p %p)\n", policy
, debugstr_w(initial
), polTable
, polArr
);
2186 if (!polTable
|| !polArr
)
2189 for (;polTable
->policy
; polTable
++, polArr
++)
2191 if (policy
== polTable
->policy
)
2193 /* we have a known policy */
2195 /* check if this policy has been cached */
2196 if (*polArr
== SHELL_NO_POLICY
)
2197 *polArr
= SHGetRestriction(initial
, polTable
->appstr
, polTable
->keystr
);
2201 /* we don't know this policy, return 0 */
2202 TRACE("unknown policy: (%08x)\n", policy
);
2206 /*************************************************************************
2209 * Get an interface from an object.
2212 * Success: S_OK. ppv contains the requested interface.
2213 * Failure: An HRESULT error code.
2216 * This QueryInterface asks the inner object for an interface. In case
2217 * of aggregation this request would be forwarded by the inner to the
2218 * outer object. This function asks the inner object directly for the
2219 * interface circumventing the forwarding to the outer object.
2221 HRESULT WINAPI
SHWeakQueryInterface(
2222 IUnknown
* pUnk
, /* [in] Outer object */
2223 IUnknown
* pInner
, /* [in] Inner object */
2224 IID
* riid
, /* [in] Interface GUID to query for */
2225 LPVOID
* ppv
) /* [out] Destination for queried interface */
2227 HRESULT hret
= E_NOINTERFACE
;
2228 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk
,pInner
,debugstr_guid(riid
), ppv
);
2231 if(pUnk
&& pInner
) {
2232 hret
= IUnknown_QueryInterface(pInner
, riid
, ppv
);
2233 if (SUCCEEDED(hret
)) IUnknown_Release(pUnk
);
2235 TRACE("-- 0x%08x\n", hret
);
2239 /*************************************************************************
2242 * Move a reference from one interface to another.
2245 * lpDest [O] Destination to receive the reference
2246 * lppUnknown [O] Source to give up the reference to lpDest
2251 VOID WINAPI
SHWeakReleaseInterface(IUnknown
*lpDest
, IUnknown
**lppUnknown
)
2253 TRACE("(%p,%p)\n", lpDest
, lppUnknown
);
2258 IUnknown_AddRef(lpDest
);
2259 IUnknown_Release(*lppUnknown
); /* Release existing interface */
2264 /*************************************************************************
2267 * Convert an ASCII string of a CLSID into a CLSID.
2270 * idstr [I] String representing a CLSID in registry format
2271 * id [O] Destination for the converted CLSID
2274 * Success: TRUE. id contains the converted CLSID.
2277 BOOL WINAPI
GUIDFromStringA(LPCSTR idstr
, CLSID
*id
)
2280 MultiByteToWideChar(CP_ACP
, 0, idstr
, -1, wClsid
, ARRAY_SIZE(wClsid
));
2281 return SUCCEEDED(CLSIDFromString(wClsid
, id
));
2284 /*************************************************************************
2287 * Unicode version of GUIDFromStringA.
2289 BOOL WINAPI
GUIDFromStringW(LPCWSTR idstr
, CLSID
*id
)
2291 return SUCCEEDED(CLSIDFromString((LPCOLESTR
)idstr
, id
));
2294 /*************************************************************************
2297 * Unicode version of SHCreateWorkerWindowA.
2299 HWND WINAPI
SHCreateWorkerWindowW(WNDPROC wndProc
, HWND hWndParent
, DWORD dwExStyle
,
2300 DWORD dwStyle
, HMENU hMenu
, LONG_PTR wnd_extra
)
2302 static const WCHAR szClass
[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
2306 TRACE("(%p, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2307 wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, wnd_extra
);
2309 /* If our OS is natively ANSI, use the ANSI version */
2310 if (GetVersion() & 0x80000000) /* not NT */
2312 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
2313 return SHCreateWorkerWindowA(wndProc
, hWndParent
, dwExStyle
, dwStyle
, hMenu
, wnd_extra
);
2316 /* Create Window class */
2318 wc
.lpfnWndProc
= DefWindowProcW
;
2320 wc
.cbWndExtra
= sizeof(LONG_PTR
);
2321 wc
.hInstance
= shlwapi_hInstance
;
2323 wc
.hCursor
= LoadCursorW(NULL
, (LPWSTR
)IDC_ARROW
);
2324 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
2325 wc
.lpszMenuName
= NULL
;
2326 wc
.lpszClassName
= szClass
;
2328 SHRegisterClassW(&wc
);
2330 hWnd
= CreateWindowExW(dwExStyle
, szClass
, 0, dwStyle
, 0, 0, 0, 0,
2331 hWndParent
, hMenu
, shlwapi_hInstance
, 0);
2334 SetWindowLongPtrW(hWnd
, 0, wnd_extra
);
2335 if (wndProc
) SetWindowLongPtrW(hWnd
, GWLP_WNDPROC
, (LONG_PTR
)wndProc
);
2341 /*************************************************************************
2344 * Get and show a context menu from a shell folder.
2347 * hWnd [I] Window displaying the shell folder
2348 * lpFolder [I] IShellFolder interface
2349 * lpApidl [I] Id for the particular folder desired
2353 * Failure: An HRESULT error code indicating the error.
2355 HRESULT WINAPI
SHInvokeDefaultCommand(HWND hWnd
, IShellFolder
* lpFolder
, LPCITEMIDLIST lpApidl
)
2357 TRACE("%p %p %p\n", hWnd
, lpFolder
, lpApidl
);
2358 return SHInvokeCommand(hWnd
, lpFolder
, lpApidl
, 0);
2361 /*************************************************************************
2364 * _SHPackDispParamsV
2366 HRESULT WINAPI
SHPackDispParamsV(DISPPARAMS
*params
, VARIANTARG
*args
, UINT cnt
, __ms_va_list valist
)
2370 TRACE("(%p %p %u ...)\n", params
, args
, cnt
);
2372 params
->rgvarg
= args
;
2373 params
->rgdispidNamedArgs
= NULL
;
2374 params
->cArgs
= cnt
;
2375 params
->cNamedArgs
= 0;
2379 while(iter
-- > args
) {
2380 V_VT(iter
) = va_arg(valist
, enum VARENUM
);
2382 TRACE("vt=%d\n", V_VT(iter
));
2384 if(V_VT(iter
) & VT_BYREF
) {
2385 V_BYREF(iter
) = va_arg(valist
, LPVOID
);
2387 switch(V_VT(iter
)) {
2389 V_I4(iter
) = va_arg(valist
, LONG
);
2392 V_BSTR(iter
) = va_arg(valist
, BSTR
);
2395 V_DISPATCH(iter
) = va_arg(valist
, IDispatch
*);
2398 V_BOOL(iter
) = va_arg(valist
, int);
2401 V_UNKNOWN(iter
) = va_arg(valist
, IUnknown
*);
2405 V_I4(iter
) = va_arg(valist
, LONG
);
2413 /*************************************************************************
2418 HRESULT WINAPIV
SHPackDispParams(DISPPARAMS
*params
, VARIANTARG
*args
, UINT cnt
, ...)
2420 __ms_va_list valist
;
2423 __ms_va_start(valist
, cnt
);
2424 hres
= SHPackDispParamsV(params
, args
, cnt
, valist
);
2425 __ms_va_end(valist
);
2429 /*************************************************************************
2430 * SHLWAPI_InvokeByIID
2432 * This helper function calls IDispatch::Invoke for each sink
2433 * which implements given iid or IDispatch.
2436 static HRESULT
SHLWAPI_InvokeByIID(
2437 IConnectionPoint
* iCP
,
2440 DISPPARAMS
* dispParams
)
2442 IEnumConnections
*enumerator
;
2444 static DISPPARAMS empty
= {NULL
, NULL
, 0, 0};
2445 DISPPARAMS
* params
= dispParams
;
2447 HRESULT result
= IConnectionPoint_EnumConnections(iCP
, &enumerator
);
2451 /* Invoke is never happening with an NULL dispParams */
2455 while(IEnumConnections_Next(enumerator
, 1, &rgcd
, NULL
)==S_OK
)
2457 IDispatch
*dispIface
;
2458 if ((iid
&& SUCCEEDED(IUnknown_QueryInterface(rgcd
.pUnk
, iid
, (LPVOID
*)&dispIface
))) ||
2459 SUCCEEDED(IUnknown_QueryInterface(rgcd
.pUnk
, &IID_IDispatch
, (LPVOID
*)&dispIface
)))
2461 IDispatch_Invoke(dispIface
, dispId
, &IID_NULL
, 0, DISPATCH_METHOD
, params
, NULL
, NULL
, NULL
);
2462 IDispatch_Release(dispIface
);
2464 IUnknown_Release(rgcd
.pUnk
);
2467 IEnumConnections_Release(enumerator
);
2472 /*************************************************************************
2473 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
2475 HRESULT WINAPI
IConnectionPoint_InvokeWithCancel( IConnectionPoint
* iCP
,
2476 DISPID dispId
, DISPPARAMS
* dispParams
,
2477 DWORD unknown1
, DWORD unknown2
)
2482 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP
, dispId
, dispParams
, unknown1
, unknown2
);
2484 result
= IConnectionPoint_GetConnectionInterface(iCP
, &iid
);
2485 if (SUCCEEDED(result
))
2486 result
= SHLWAPI_InvokeByIID(iCP
, &iid
, dispId
, dispParams
);
2488 result
= SHLWAPI_InvokeByIID(iCP
, NULL
, dispId
, dispParams
);
2494 /*************************************************************************
2497 * IConnectionPoint_SimpleInvoke
2499 HRESULT WINAPI
IConnectionPoint_SimpleInvoke(
2500 IConnectionPoint
* iCP
,
2502 DISPPARAMS
* dispParams
)
2507 TRACE("(%p)->(0x%x %p)\n",iCP
,dispId
,dispParams
);
2509 result
= IConnectionPoint_GetConnectionInterface(iCP
, &iid
);
2510 if (SUCCEEDED(result
))
2511 result
= SHLWAPI_InvokeByIID(iCP
, &iid
, dispId
, dispParams
);
2513 result
= SHLWAPI_InvokeByIID(iCP
, NULL
, dispId
, dispParams
);
2518 /*************************************************************************
2521 * Notify an IConnectionPoint object of changes.
2524 * lpCP [I] Object to notify
2529 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
2530 * IConnectionPoint interface.
2532 HRESULT WINAPI
IConnectionPoint_OnChanged(IConnectionPoint
* lpCP
, DISPID dispID
)
2534 IEnumConnections
*lpEnum
;
2535 HRESULT hRet
= E_NOINTERFACE
;
2537 TRACE("(%p,0x%8X)\n", lpCP
, dispID
);
2539 /* Get an enumerator for the connections */
2541 hRet
= IConnectionPoint_EnumConnections(lpCP
, &lpEnum
);
2543 if (SUCCEEDED(hRet
))
2545 IPropertyNotifySink
*lpSink
;
2546 CONNECTDATA connData
;
2549 /* Call OnChanged() for every notify sink in the connection point */
2550 while (IEnumConnections_Next(lpEnum
, 1, &connData
, &ulFetched
) == S_OK
)
2552 if (SUCCEEDED(IUnknown_QueryInterface(connData
.pUnk
, &IID_IPropertyNotifySink
, (void**)&lpSink
)) &&
2555 IPropertyNotifySink_OnChanged(lpSink
, dispID
);
2556 IPropertyNotifySink_Release(lpSink
);
2558 IUnknown_Release(connData
.pUnk
);
2561 IEnumConnections_Release(lpEnum
);
2566 /*************************************************************************
2569 * IUnknown_CPContainerInvokeParam
2571 HRESULT WINAPIV
IUnknown_CPContainerInvokeParam(
2572 IUnknown
*container
,
2579 IConnectionPoint
*iCP
;
2580 IConnectionPointContainer
*iCPC
;
2581 DISPPARAMS dispParams
= {buffer
, NULL
, cParams
, 0};
2582 __ms_va_list valist
;
2585 return E_NOINTERFACE
;
2587 result
= IUnknown_QueryInterface(container
, &IID_IConnectionPointContainer
,(LPVOID
*) &iCPC
);
2591 result
= IConnectionPointContainer_FindConnectionPoint(iCPC
, riid
, &iCP
);
2592 IConnectionPointContainer_Release(iCPC
);
2596 __ms_va_start(valist
, cParams
);
2597 SHPackDispParamsV(&dispParams
, buffer
, cParams
, valist
);
2598 __ms_va_end(valist
);
2600 result
= SHLWAPI_InvokeByIID(iCP
, riid
, dispId
, &dispParams
);
2601 IConnectionPoint_Release(iCP
);
2606 /*************************************************************************
2609 * Notify an IConnectionPointContainer object of changes.
2612 * lpUnknown [I] Object to notify
2617 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
2618 * IConnectionPointContainer interface.
2620 HRESULT WINAPI
IUnknown_CPContainerOnChanged(IUnknown
*lpUnknown
, DISPID dispID
)
2622 IConnectionPointContainer
* lpCPC
= NULL
;
2623 HRESULT hRet
= E_NOINTERFACE
;
2625 TRACE("(%p,0x%8X)\n", lpUnknown
, dispID
);
2628 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IConnectionPointContainer
, (void**)&lpCPC
);
2630 if (SUCCEEDED(hRet
))
2632 IConnectionPoint
* lpCP
;
2634 hRet
= IConnectionPointContainer_FindConnectionPoint(lpCPC
, &IID_IPropertyNotifySink
, &lpCP
);
2635 IConnectionPointContainer_Release(lpCPC
);
2637 hRet
= IConnectionPoint_OnChanged(lpCP
, dispID
);
2638 IConnectionPoint_Release(lpCP
);
2643 /*************************************************************************
2648 BOOL WINAPI
PlaySoundWrapW(LPCWSTR pszSound
, HMODULE hmod
, DWORD fdwSound
)
2650 return PlaySoundW(pszSound
, hmod
, fdwSound
);
2653 /*************************************************************************
2656 * Retrieve a key value from an INI file. See GetPrivateProfileString for
2660 * appName [I] The section in the INI file that contains the key
2661 * keyName [I] The key to be retrieved
2662 * out [O] The buffer into which the key's value will be copied
2663 * outLen [I] The length of the `out' buffer
2664 * filename [I] The location of the INI file
2667 * Length of string copied into `out'.
2669 DWORD WINAPI
SHGetIniStringW(LPCWSTR appName
, LPCWSTR keyName
, LPWSTR out
,
2670 DWORD outLen
, LPCWSTR filename
)
2675 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName
), debugstr_w(keyName
),
2676 out
, outLen
, debugstr_w(filename
));
2681 buf
= HeapAlloc(GetProcessHeap(), 0, outLen
* sizeof(WCHAR
));
2687 ret
= GetPrivateProfileStringW(appName
, keyName
, NULL
, buf
, outLen
, filename
);
2693 HeapFree(GetProcessHeap(), 0, buf
);
2695 return lstrlenW(out
);
2698 /*************************************************************************
2701 * Set a key value in an INI file. See WritePrivateProfileString for
2705 * appName [I] The section in the INI file that contains the key
2706 * keyName [I] The key to be set
2707 * str [O] The value of the key
2708 * filename [I] The location of the INI file
2714 BOOL WINAPI
SHSetIniStringW(LPCWSTR appName
, LPCWSTR keyName
, LPCWSTR str
,
2717 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName
), keyName
, debugstr_w(str
),
2718 debugstr_w(filename
));
2720 return WritePrivateProfileStringW(appName
, keyName
, str
, filename
);
2723 /*************************************************************************
2726 * See SHGetFileInfoW.
2728 DWORD WINAPI
SHGetFileInfoWrapW(LPCWSTR path
, DWORD dwFileAttributes
,
2729 SHFILEINFOW
*psfi
, UINT sizeofpsfi
, UINT flags
)
2731 return SHGetFileInfoW(path
, dwFileAttributes
, psfi
, sizeofpsfi
, flags
);
2734 /*************************************************************************
2737 * See DragQueryFileW.
2739 UINT WINAPI
DragQueryFileWrapW(HDROP hDrop
, UINT lFile
, LPWSTR lpszFile
, UINT lLength
)
2741 return DragQueryFileW(hDrop
, lFile
, lpszFile
, lLength
);
2744 /*************************************************************************
2747 * See SHBrowseForFolderW.
2749 LPITEMIDLIST WINAPI
SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi
)
2751 return SHBrowseForFolderW(lpBi
);
2754 /*************************************************************************
2757 * See SHGetPathFromIDListW.
2759 BOOL WINAPI
SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl
,LPWSTR pszPath
)
2761 return SHGetPathFromIDListW(pidl
, pszPath
);
2764 /*************************************************************************
2767 * See ShellExecuteExW.
2769 BOOL WINAPI
ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo
)
2771 return ShellExecuteExW(lpExecInfo
);
2774 /*************************************************************************
2777 * See SHFileOperationW.
2779 INT WINAPI
SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp
)
2781 return SHFileOperationW(lpFileOp
);
2784 /*************************************************************************
2788 PVOID WINAPI
SHInterlockedCompareExchange( PVOID
*dest
, PVOID xchg
, PVOID compare
)
2790 return InterlockedCompareExchangePointer( dest
, xchg
, compare
);
2793 /*************************************************************************
2796 * See GetFileVersionInfoSizeW.
2798 DWORD WINAPI
GetFileVersionInfoSizeWrapW( LPCWSTR filename
, LPDWORD handle
)
2800 return GetFileVersionInfoSizeW( filename
, handle
);
2803 /*************************************************************************
2806 * See GetFileVersionInfoW.
2808 BOOL WINAPI
GetFileVersionInfoWrapW( LPCWSTR filename
, DWORD handle
,
2809 DWORD datasize
, LPVOID data
)
2811 return GetFileVersionInfoW( filename
, handle
, datasize
, data
);
2814 /*************************************************************************
2817 * See VerQueryValueW.
2819 WORD WINAPI
VerQueryValueWrapW( LPVOID pBlock
, LPCWSTR lpSubBlock
,
2820 LPVOID
*lplpBuffer
, UINT
*puLen
)
2822 return VerQueryValueW( pBlock
, lpSubBlock
, lplpBuffer
, puLen
);
2825 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
2826 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
2827 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
2829 /*************************************************************************
2832 * Change the modality of a shell object.
2835 * lpUnknown [I] Object to make modeless
2836 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
2839 * Success: S_OK. The modality lpUnknown is changed.
2840 * Failure: An HRESULT error code indicating the error.
2843 * lpUnknown must support the IOleInPlaceFrame interface, the
2844 * IInternetSecurityMgrSite interface, the IShellBrowser interface
2845 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
2846 * or this call will fail.
2848 HRESULT WINAPI
IUnknown_EnableModeless(IUnknown
*lpUnknown
, BOOL bModeless
)
2853 TRACE("(%p,%d)\n", lpUnknown
, bModeless
);
2858 if (IsIface(IOleInPlaceActiveObject
))
2859 EnableModeless(IOleInPlaceActiveObject
);
2860 else if (IsIface(IOleInPlaceFrame
))
2861 EnableModeless(IOleInPlaceFrame
);
2862 else if (IsIface(IShellBrowser
))
2863 EnableModeless(IShellBrowser
);
2864 else if (IsIface(IInternetSecurityMgrSite
))
2865 EnableModeless(IInternetSecurityMgrSite
);
2866 else if (IsIface(IDocHostUIHandler
))
2867 EnableModeless(IDocHostUIHandler
);
2871 IUnknown_Release(lpObj
);
2875 /*************************************************************************
2878 * See SHGetNewLinkInfoW.
2880 BOOL WINAPI
SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo
, LPCWSTR pszDir
, LPWSTR pszName
,
2881 BOOL
*pfMustCopy
, UINT uFlags
)
2883 return SHGetNewLinkInfoW(pszLinkTo
, pszDir
, pszName
, pfMustCopy
, uFlags
);
2886 /*************************************************************************
2889 * See SHDefExtractIconW.
2891 UINT WINAPI
SHDefExtractIconWrapW(LPCWSTR pszIconFile
, int iIndex
, UINT uFlags
, HICON
* phiconLarge
,
2892 HICON
* phiconSmall
, UINT nIconSize
)
2894 return SHDefExtractIconW(pszIconFile
, iIndex
, uFlags
, phiconLarge
, phiconSmall
, nIconSize
);
2897 /*************************************************************************
2900 * Get and show a context menu from a shell folder.
2903 * hWnd [I] Window displaying the shell folder
2904 * lpFolder [I] IShellFolder interface
2905 * lpApidl [I] Id for the particular folder desired
2906 * dwCommandId [I] The command ID to invoke (0=invoke default)
2909 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
2911 * Failure: An HRESULT error code indicating the error.
2913 HRESULT WINAPI
SHInvokeCommand(HWND hWnd
, IShellFolder
* lpFolder
, LPCITEMIDLIST lpApidl
, DWORD dwCommandId
)
2915 IContextMenu
*iContext
;
2918 TRACE("(%p, %p, %p, %u)\n", hWnd
, lpFolder
, lpApidl
, dwCommandId
);
2923 /* Get the context menu from the shell folder */
2924 hRet
= IShellFolder_GetUIObjectOf(lpFolder
, hWnd
, 1, &lpApidl
,
2925 &IID_IContextMenu
, 0, (void**)&iContext
);
2926 if (SUCCEEDED(hRet
))
2929 if ((hMenu
= CreatePopupMenu()))
2933 /* Add the context menu entries to the popup */
2934 hQuery
= IContextMenu_QueryContextMenu(iContext
, hMenu
, 0, 1, 0x7FFF,
2935 dwCommandId
? CMF_NORMAL
: CMF_DEFAULTONLY
);
2937 if (SUCCEEDED(hQuery
))
2940 dwCommandId
= GetMenuDefaultItem(hMenu
, 0, 0);
2941 if (dwCommandId
!= (UINT
)-1)
2943 CMINVOKECOMMANDINFO cmIci
;
2944 /* Invoke the default item */
2945 memset(&cmIci
,0,sizeof(cmIci
));
2946 cmIci
.cbSize
= sizeof(cmIci
);
2947 cmIci
.fMask
= CMIC_MASK_ASYNCOK
;
2949 cmIci
.lpVerb
= MAKEINTRESOURCEA(dwCommandId
);
2950 cmIci
.nShow
= SW_SHOWNORMAL
;
2952 hRet
= IContextMenu_InvokeCommand(iContext
, &cmIci
);
2957 IContextMenu_Release(iContext
);
2962 /*************************************************************************
2967 HICON WINAPI
ExtractIconWrapW(HINSTANCE hInstance
, LPCWSTR lpszExeFileName
,
2970 return ExtractIconW(hInstance
, lpszExeFileName
, nIconIndex
);
2973 /*************************************************************************
2976 * Load a library from the directory of a particular process.
2979 * new_mod [I] Library name
2980 * inst_hwnd [I] Module whose directory is to be used
2981 * dwCrossCodePage [I] Should be FALSE (currently ignored)
2984 * Success: A handle to the loaded module
2985 * Failure: A NULL handle.
2987 HMODULE WINAPI
MLLoadLibraryA(LPCSTR new_mod
, HMODULE inst_hwnd
, DWORD dwCrossCodePage
)
2989 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
2991 * FIXME: Native shows calls to:
2992 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
2994 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
2995 * RegQueryValueExA for "LPKInstalled"
2997 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
2998 * RegQueryValueExA for "ResourceLocale"
3000 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3001 * RegQueryValueExA for "Locale"
3003 * and then tests the Locale ("en" for me).
3005 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3007 CHAR mod_path
[2*MAX_PATH
];
3011 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod
), inst_hwnd
, dwCrossCodePage
);
3012 len
= GetModuleFileNameA(inst_hwnd
, mod_path
, sizeof(mod_path
));
3013 if (!len
|| len
>= sizeof(mod_path
)) return NULL
;
3015 ptr
= strrchr(mod_path
, '\\');
3017 strcpy(ptr
+1, new_mod
);
3018 TRACE("loading %s\n", debugstr_a(mod_path
));
3019 return LoadLibraryA(mod_path
);
3024 /*************************************************************************
3027 * Unicode version of MLLoadLibraryA.
3029 HMODULE WINAPI
MLLoadLibraryW(LPCWSTR new_mod
, HMODULE inst_hwnd
, DWORD dwCrossCodePage
)
3031 WCHAR mod_path
[2*MAX_PATH
];
3035 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod
), inst_hwnd
, dwCrossCodePage
);
3036 len
= GetModuleFileNameW(inst_hwnd
, mod_path
, ARRAY_SIZE(mod_path
));
3037 if (!len
|| len
>= ARRAY_SIZE(mod_path
)) return NULL
;
3039 ptr
= wcsrchr(mod_path
, '\\');
3041 lstrcpyW(ptr
+1, new_mod
);
3042 TRACE("loading %s\n", debugstr_w(mod_path
));
3043 return LoadLibraryW(mod_path
);
3048 /*************************************************************************
3049 * ColorAdjustLuma [SHLWAPI.@]
3051 * Adjust the luminosity of a color
3054 * cRGB [I] RGB value to convert
3055 * dwLuma [I] Luma adjustment
3056 * bUnknown [I] Unknown
3059 * The adjusted RGB color.
3061 COLORREF WINAPI
ColorAdjustLuma(COLORREF cRGB
, int dwLuma
, BOOL bUnknown
)
3063 TRACE("(0x%8x,%d,%d)\n", cRGB
, dwLuma
, bUnknown
);
3069 ColorRGBToHLS(cRGB
, &wH
, &wL
, &wS
);
3071 FIXME("Ignoring luma adjustment\n");
3073 /* FIXME: The adjustment is not linear */
3075 cRGB
= ColorHLSToRGB(wH
, wL
, wS
);
3080 /*************************************************************************
3083 * See GetSaveFileNameW.
3085 BOOL WINAPI
GetSaveFileNameWrapW(LPOPENFILENAMEW ofn
)
3087 return GetSaveFileNameW(ofn
);
3090 /*************************************************************************
3093 * See WNetRestoreConnectionW.
3095 DWORD WINAPI
WNetRestoreConnectionWrapW(HWND hwndOwner
, LPWSTR lpszDevice
)
3097 return WNetRestoreConnectionW(hwndOwner
, lpszDevice
);
3100 /*************************************************************************
3103 * See WNetGetLastErrorW.
3105 DWORD WINAPI
WNetGetLastErrorWrapW(LPDWORD lpError
, LPWSTR lpErrorBuf
, DWORD nErrorBufSize
,
3106 LPWSTR lpNameBuf
, DWORD nNameBufSize
)
3108 return WNetGetLastErrorW(lpError
, lpErrorBuf
, nErrorBufSize
, lpNameBuf
, nNameBufSize
);
3111 /*************************************************************************
3114 * See PageSetupDlgW.
3116 BOOL WINAPI
PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg
)
3118 return PageSetupDlgW(pagedlg
);
3121 /*************************************************************************
3126 BOOL WINAPI
PrintDlgWrapW(LPPRINTDLGW printdlg
)
3128 return PrintDlgW(printdlg
);
3131 /*************************************************************************
3134 * See GetOpenFileNameW.
3136 BOOL WINAPI
GetOpenFileNameWrapW(LPOPENFILENAMEW ofn
)
3138 return GetOpenFileNameW(ofn
);
3141 /*************************************************************************
3144 HRESULT WINAPI
SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder
, HWND hwnd
, SHCONTF flags
, IEnumIDList
**ppenum
)
3146 /* Windows attempts to get an IPersist interface and, if that fails, an
3147 * IPersistFolder interface on the folder passed-in here. If one of those
3148 * interfaces is available, it then calls GetClassID on the folder... and
3149 * then calls IShellFolder_EnumObjects no matter what, even crashing if
3150 * lpFolder isn't actually an IShellFolder object. The purpose of getting
3151 * the ClassID is unknown, so we don't do it here.
3153 * For discussion and detailed tests, see:
3154 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated"
3155 * wine-devel mailing list, 3 Jun 2010
3158 return IShellFolder_EnumObjects(lpFolder
, hwnd
, flags
, ppenum
);
3161 /* INTERNAL: Map from HLS color space to RGB */
3162 static WORD
ConvertHue(int wHue
, WORD wMid1
, WORD wMid2
)
3164 wHue
= wHue
> 240 ? wHue
- 240 : wHue
< 0 ? wHue
+ 240 : wHue
;
3168 else if (wHue
> 120)
3173 return ((wHue
* (wMid2
- wMid1
) + 20) / 40) + wMid1
;
3176 /* Convert to RGB and scale into RGB range (0..255) */
3177 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3179 /*************************************************************************
3180 * ColorHLSToRGB [SHLWAPI.@]
3182 * Convert from hls color space into an rgb COLORREF.
3185 * wHue [I] Hue amount
3186 * wLuminosity [I] Luminosity amount
3187 * wSaturation [I] Saturation amount
3190 * A COLORREF representing the converted color.
3193 * Input hls values are constrained to the range (0..240).
3195 COLORREF WINAPI
ColorHLSToRGB(WORD wHue
, WORD wLuminosity
, WORD wSaturation
)
3201 WORD wGreen
, wBlue
, wMid1
, wMid2
;
3203 if (wLuminosity
> 120)
3204 wMid2
= wSaturation
+ wLuminosity
- (wSaturation
* wLuminosity
+ 120) / 240;
3206 wMid2
= ((wSaturation
+ 240) * wLuminosity
+ 120) / 240;
3208 wMid1
= wLuminosity
* 2 - wMid2
;
3210 wRed
= GET_RGB(wHue
+ 80);
3211 wGreen
= GET_RGB(wHue
);
3212 wBlue
= GET_RGB(wHue
- 80);
3214 return RGB(wRed
, wGreen
, wBlue
);
3217 wRed
= wLuminosity
* 255 / 240;
3218 return RGB(wRed
, wRed
, wRed
);
3221 /*************************************************************************
3224 * Get the current docking status of the system.
3227 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3230 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3233 DWORD WINAPI
SHGetMachineInfo(DWORD dwFlags
)
3235 HW_PROFILE_INFOA hwInfo
;
3237 TRACE("(0x%08x)\n", dwFlags
);
3239 GetCurrentHwProfileA(&hwInfo
);
3240 switch (hwInfo
.dwDockInfo
& (DOCKINFO_DOCKED
|DOCKINFO_UNDOCKED
))
3242 case DOCKINFO_DOCKED
:
3243 case DOCKINFO_UNDOCKED
:
3244 return hwInfo
.dwDockInfo
& (DOCKINFO_DOCKED
|DOCKINFO_UNDOCKED
);
3250 /*************************************************************************
3254 DWORD WINAPI
SHWinHelpOnDemandW(HWND hwnd
, LPCWSTR helpfile
, DWORD flags1
, VOID
*ptr1
, DWORD flags2
)
3257 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd
, debugstr_w(helpfile
), flags1
, ptr1
, flags2
);
3261 /*************************************************************************
3265 DWORD WINAPI
SHWinHelpOnDemandA(HWND hwnd
, LPCSTR helpfile
, DWORD flags1
, VOID
*ptr1
, DWORD flags2
)
3268 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd
, debugstr_a(helpfile
), flags1
, ptr1
, flags2
);
3272 /*************************************************************************
3275 * Function seems to do FreeLibrary plus other things.
3277 * FIXME native shows the following calls:
3278 * RtlEnterCriticalSection
3280 * GetProcAddress(Comctl32??, 150L)
3282 * RtlLeaveCriticalSection
3283 * followed by the FreeLibrary.
3284 * The above code may be related to .377 above.
3286 BOOL WINAPI
MLFreeLibrary(HMODULE hModule
)
3288 FIXME("(%p) semi-stub\n", hModule
);
3289 return FreeLibrary(hModule
);
3292 /*************************************************************************
3295 BOOL WINAPI
SHFlushSFCacheWrap(void) {
3300 /*************************************************************************
3302 * FIXME I have no idea what this function does or what its arguments are.
3304 BOOL WINAPI
MLIsMLHInstance(HINSTANCE hInst
)
3306 FIXME("(%p) stub\n", hInst
);
3311 /*************************************************************************
3314 DWORD WINAPI
MLSetMLHInstance(HINSTANCE hInst
, HANDLE hHeap
)
3316 FIXME("(%p,%p) stub\n", hInst
, hHeap
);
3317 return E_FAIL
; /* This is what is used if shlwapi not loaded */
3320 /*************************************************************************
3323 DWORD WINAPI
MLClearMLHInstance(DWORD x
)
3325 FIXME("(0x%08x)stub\n", x
);
3329 /*************************************************************************
3332 * See SHSendMessageBroadcastW
3335 DWORD WINAPI
SHSendMessageBroadcastA(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3337 return SendMessageTimeoutA(HWND_BROADCAST
, uMsg
, wParam
, lParam
,
3338 SMTO_ABORTIFHUNG
, 2000, NULL
);
3341 /*************************************************************************
3344 * A wrapper for sending Broadcast Messages to all top level Windows
3347 DWORD WINAPI
SHSendMessageBroadcastW(UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3349 return SendMessageTimeoutW(HWND_BROADCAST
, uMsg
, wParam
, lParam
,
3350 SMTO_ABORTIFHUNG
, 2000, NULL
);
3353 /*************************************************************************
3356 * Convert a Unicode string CLSID into a CLSID.
3359 * idstr [I] string containing a CLSID in text form
3360 * id [O] CLSID extracted from the string
3363 * S_OK on success or E_INVALIDARG on failure
3365 HRESULT WINAPI
CLSIDFromStringWrap(LPCWSTR idstr
, CLSID
*id
)
3367 return CLSIDFromString((LPCOLESTR
)idstr
, id
);
3370 /*************************************************************************
3373 HRESULT WINAPI
SHLoadRegUIStringW(HKEY hkey
, LPCWSTR value
, LPWSTR buf
, DWORD size
)
3375 DWORD type
, sz
= size
* sizeof(WCHAR
);
3377 if(RegQueryValueExW(hkey
, value
, NULL
, &type
, (LPBYTE
)buf
, &sz
) != ERROR_SUCCESS
)
3380 return SHLoadIndirectString(buf
, buf
, size
, NULL
);
3383 /*************************************************************************
3386 * Call IInputObject_TranslateAcceleratorIO() on an object.
3389 * lpUnknown [I] Object supporting the IInputObject interface.
3390 * lpMsg [I] Key message to be processed.
3394 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3396 HRESULT WINAPI
IUnknown_TranslateAcceleratorIO(IUnknown
*lpUnknown
, LPMSG lpMsg
)
3398 IInputObject
* lpInput
= NULL
;
3399 HRESULT hRet
= E_INVALIDARG
;
3401 TRACE("(%p,%p)\n", lpUnknown
, lpMsg
);
3404 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObject
,
3406 if (SUCCEEDED(hRet
) && lpInput
)
3408 hRet
= IInputObject_TranslateAcceleratorIO(lpInput
, lpMsg
);
3409 IInputObject_Release(lpInput
);
3415 /*************************************************************************
3418 * Call IInputObject_HasFocusIO() on an object.
3421 * lpUnknown [I] Object supporting the IInputObject interface.
3424 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
3425 * or S_FALSE otherwise.
3426 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3428 HRESULT WINAPI
IUnknown_HasFocusIO(IUnknown
*lpUnknown
)
3430 IInputObject
* lpInput
= NULL
;
3431 HRESULT hRet
= E_INVALIDARG
;
3433 TRACE("(%p)\n", lpUnknown
);
3436 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObject
,
3438 if (SUCCEEDED(hRet
) && lpInput
)
3440 hRet
= IInputObject_HasFocusIO(lpInput
);
3441 IInputObject_Release(lpInput
);
3447 /*************************************************************************
3448 * ColorRGBToHLS [SHLWAPI.@]
3450 * Convert an rgb COLORREF into the hls color space.
3453 * cRGB [I] Source rgb value
3454 * pwHue [O] Destination for converted hue
3455 * pwLuminance [O] Destination for converted luminance
3456 * pwSaturation [O] Destination for converted saturation
3459 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
3463 * Output HLS values are constrained to the range (0..240).
3464 * For Achromatic conversions, Hue is set to 160.
3466 VOID WINAPI
ColorRGBToHLS(COLORREF cRGB
, LPWORD pwHue
,
3467 LPWORD pwLuminance
, LPWORD pwSaturation
)
3469 int wR
, wG
, wB
, wMax
, wMin
, wHue
, wLuminosity
, wSaturation
;
3471 TRACE("(%08x,%p,%p,%p)\n", cRGB
, pwHue
, pwLuminance
, pwSaturation
);
3473 wR
= GetRValue(cRGB
);
3474 wG
= GetGValue(cRGB
);
3475 wB
= GetBValue(cRGB
);
3477 wMax
= max(wR
, max(wG
, wB
));
3478 wMin
= min(wR
, min(wG
, wB
));
3481 wLuminosity
= ((wMax
+ wMin
) * 240 + 255) / 510;
3485 /* Achromatic case */
3487 /* Hue is now unrepresentable, but this is what native returns... */
3492 /* Chromatic case */
3493 int wDelta
= wMax
- wMin
, wRNorm
, wGNorm
, wBNorm
;
3496 if (wLuminosity
<= 120)
3497 wSaturation
= ((wMax
+ wMin
)/2 + wDelta
* 240) / (wMax
+ wMin
);
3499 wSaturation
= ((510 - wMax
- wMin
)/2 + wDelta
* 240) / (510 - wMax
- wMin
);
3502 wRNorm
= (wDelta
/2 + wMax
* 40 - wR
* 40) / wDelta
;
3503 wGNorm
= (wDelta
/2 + wMax
* 40 - wG
* 40) / wDelta
;
3504 wBNorm
= (wDelta
/2 + wMax
* 40 - wB
* 40) / wDelta
;
3507 wHue
= wBNorm
- wGNorm
;
3508 else if (wG
== wMax
)
3509 wHue
= 80 + wRNorm
- wBNorm
;
3511 wHue
= 160 + wGNorm
- wRNorm
;
3514 else if (wHue
> 240)
3520 *pwLuminance
= wLuminosity
;
3522 *pwSaturation
= wSaturation
;
3525 /*************************************************************************
3526 * SHCreateShellPalette [SHLWAPI.@]
3528 HPALETTE WINAPI
SHCreateShellPalette(HDC hdc
)
3531 return CreateHalftonePalette(hdc
);
3534 /*************************************************************************
3535 * SHGetInverseCMAP (SHLWAPI.@)
3537 * Get an inverse color map table.
3540 * lpCmap [O] Destination for color map
3541 * dwSize [I] Size of memory pointed to by lpCmap
3545 * Failure: E_POINTER, If lpCmap is invalid.
3546 * E_INVALIDARG, If dwFlags is invalid
3547 * E_OUTOFMEMORY, If there is no memory available
3550 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
3551 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
3553 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
3554 * this DLL's internal CMap.
3556 HRESULT WINAPI
SHGetInverseCMAP(LPDWORD dest
, DWORD dwSize
)
3559 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
3560 *dest
= (DWORD
)0xabba1249;
3563 FIXME("(%p, %#x) stub\n", dest
, dwSize
);
3567 /*************************************************************************
3568 * GetMenuPosFromID [SHLWAPI.@]
3570 * Return the position of a menu item from its Id.
3573 * hMenu [I] Menu containing the item
3574 * wID [I] Id of the menu item
3577 * Success: The index of the menu item in hMenu.
3578 * Failure: -1, If the item is not found.
3580 INT WINAPI
GetMenuPosFromID(HMENU hMenu
, UINT wID
)
3583 INT nCount
= GetMenuItemCount(hMenu
), nIter
= 0;
3585 TRACE("%p %u\n", hMenu
, wID
);
3587 while (nIter
< nCount
)
3589 mi
.cbSize
= sizeof(mi
);
3591 if (GetMenuItemInfoW(hMenu
, nIter
, TRUE
, &mi
) && mi
.wID
== wID
)
3593 TRACE("ret %d\n", nIter
);
3602 /*************************************************************************
3605 * Same as SHLWAPI.GetMenuPosFromID
3607 DWORD WINAPI
SHMenuIndexFromID(HMENU hMenu
, UINT uID
)
3609 TRACE("%p %u\n", hMenu
, uID
);
3610 return GetMenuPosFromID(hMenu
, uID
);
3614 /*************************************************************************
3617 VOID WINAPI
FixSlashesAndColonW(LPWSTR lpwstr
)
3628 /*************************************************************************
3631 DWORD WINAPI
SHGetAppCompatFlags(DWORD dwUnknown
)
3633 FIXME("(0x%08x) stub\n", dwUnknown
);
3638 /*************************************************************************
3641 HRESULT WINAPI
SHCoCreateInstanceAC(REFCLSID rclsid
, LPUNKNOWN pUnkOuter
,
3642 DWORD dwClsContext
, REFIID iid
, LPVOID
*ppv
)
3644 return CoCreateInstance(rclsid
, pUnkOuter
, dwClsContext
, iid
, ppv
);
3647 /*************************************************************************
3648 * SHSkipJunction [SHLWAPI.@]
3650 * Determine if a bind context can be bound to an object
3653 * pbc [I] Bind context to check
3654 * pclsid [I] CLSID of object to be bound to
3657 * TRUE: If it is safe to bind
3658 * FALSE: If pbc is invalid or binding would not be safe
3661 BOOL WINAPI
SHSkipJunction(IBindCtx
*pbc
, const CLSID
*pclsid
)
3663 static WCHAR szSkipBinding
[] = { 'S','k','i','p',' ',
3664 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
3671 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc
, szSkipBinding
, &lpUnk
)))
3675 if (SUCCEEDED(IUnknown_GetClassID(lpUnk
, &clsid
)) &&
3676 IsEqualGUID(pclsid
, &clsid
))
3679 IUnknown_Release(lpUnk
);
3685 /***********************************************************************
3686 * SHGetShellKey (SHLWAPI.491)
3688 HKEY WINAPI
SHGetShellKey(DWORD flags
, LPCWSTR sub_key
, BOOL create
)
3690 enum _shellkey_flags
{
3691 SHKEY_Root_HKCU
= 0x1,
3692 SHKEY_Root_HKLM
= 0x2,
3693 SHKEY_Key_Explorer
= 0x00,
3694 SHKEY_Key_Shell
= 0x10,
3695 SHKEY_Key_ShellNoRoam
= 0x20,
3696 SHKEY_Key_Classes
= 0x30,
3697 SHKEY_Subkey_Default
= 0x0000,
3698 SHKEY_Subkey_ResourceName
= 0x1000,
3699 SHKEY_Subkey_Handlers
= 0x2000,
3700 SHKEY_Subkey_Associations
= 0x3000,
3701 SHKEY_Subkey_Volatile
= 0x4000,
3702 SHKEY_Subkey_MUICache
= 0x5000,
3703 SHKEY_Subkey_FileExts
= 0x6000
3706 static const WCHAR explorerW
[] = {'S','o','f','t','w','a','r','e','\\',
3707 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
3708 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
3709 'E','x','p','l','o','r','e','r','\\'};
3710 static const WCHAR shellW
[] = {'S','o','f','t','w','a','r','e','\\',
3711 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
3712 'S','h','e','l','l','\\'};
3713 static const WCHAR shell_no_roamW
[] = {'S','o','f','t','w','a','r','e','\\',
3714 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
3715 'S','h','e','l','l','N','o','R','o','a','m','\\'};
3716 static const WCHAR classesW
[] = {'S','o','f','t','w','a','r','e','\\',
3717 'C','l','a','s','s','e','s','\\'};
3719 static const WCHAR localized_resource_nameW
[] = {'L','o','c','a','l','i','z','e','d',
3720 'R','e','s','o','u','r','c','e','N','a','m','e','\\'};
3721 static const WCHAR handlersW
[] = {'H','a','n','d','l','e','r','s','\\'};
3722 static const WCHAR associationsW
[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'};
3723 static const WCHAR volatileW
[] = {'V','o','l','a','t','i','l','e','\\'};
3724 static const WCHAR mui_cacheW
[] = {'M','U','I','C','a','c','h','e','\\'};
3725 static const WCHAR file_extsW
[] = {'F','i','l','e','E','x','t','s','\\'};
3728 const WCHAR
*key
, *subkey
;
3729 int size_key
, size_subkey
, size_user
;
3732 TRACE("(0x%08x, %s, %d)\n", flags
, debugstr_w(sub_key
), create
);
3734 /* For compatibility with Vista+ */
3735 if(flags
== 0x1ffff)
3738 switch(flags
&0xff0) {
3739 case SHKEY_Key_Explorer
:
3741 size_key
= sizeof(explorerW
);
3743 case SHKEY_Key_Shell
:
3745 size_key
= sizeof(shellW
);
3747 case SHKEY_Key_ShellNoRoam
:
3748 key
= shell_no_roamW
;
3749 size_key
= sizeof(shell_no_roamW
);
3751 case SHKEY_Key_Classes
:
3753 size_key
= sizeof(classesW
);
3756 FIXME("unsupported flags (0x%08x)\n", flags
);
3760 switch(flags
&0xff000) {
3761 case SHKEY_Subkey_Default
:
3765 case SHKEY_Subkey_ResourceName
:
3766 subkey
= localized_resource_nameW
;
3767 size_subkey
= sizeof(localized_resource_nameW
);
3769 case SHKEY_Subkey_Handlers
:
3771 size_subkey
= sizeof(handlersW
);
3773 case SHKEY_Subkey_Associations
:
3774 subkey
= associationsW
;
3775 size_subkey
= sizeof(associationsW
);
3777 case SHKEY_Subkey_Volatile
:
3779 size_subkey
= sizeof(volatileW
);
3781 case SHKEY_Subkey_MUICache
:
3782 subkey
= mui_cacheW
;
3783 size_subkey
= sizeof(mui_cacheW
);
3785 case SHKEY_Subkey_FileExts
:
3786 subkey
= file_extsW
;
3787 size_subkey
= sizeof(file_extsW
);
3790 FIXME("unsupported flags (0x%08x)\n", flags
);
3795 size_user
= lstrlenW(sub_key
)*sizeof(WCHAR
);
3799 path
= HeapAlloc(GetProcessHeap(), 0, size_key
+size_subkey
+size_user
+sizeof(WCHAR
));
3801 ERR("Out of memory\n");
3805 memcpy(path
, key
, size_key
);
3807 memcpy(path
+size_key
/sizeof(WCHAR
), subkey
, size_subkey
);
3809 memcpy(path
+(size_key
+size_subkey
)/sizeof(WCHAR
), sub_key
, size_user
);
3810 path
[(size_key
+size_subkey
+size_user
)/sizeof(WCHAR
)] = '\0';
3813 RegCreateKeyExW((flags
&0xf)==SHKEY_Root_HKLM
?HKEY_LOCAL_MACHINE
:HKEY_CURRENT_USER
,
3814 path
, 0, NULL
, 0, MAXIMUM_ALLOWED
, NULL
, &hkey
, NULL
);
3816 RegOpenKeyExW((flags
&0xf)==SHKEY_Root_HKLM
?HKEY_LOCAL_MACHINE
:HKEY_CURRENT_USER
,
3817 path
, 0, MAXIMUM_ALLOWED
, &hkey
);
3819 HeapFree(GetProcessHeap(), 0, path
);
3823 /***********************************************************************
3824 * SHQueueUserWorkItem (SHLWAPI.@)
3826 BOOL WINAPI
SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback
,
3827 LPVOID pContext
, LONG lPriority
, DWORD_PTR dwTag
,
3828 DWORD_PTR
*pdwId
, LPCSTR pszModule
, DWORD dwFlags
)
3830 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback
, pContext
,
3831 lPriority
, dwTag
, pdwId
, debugstr_a(pszModule
), dwFlags
);
3833 if(lPriority
|| dwTag
|| pdwId
|| pszModule
|| dwFlags
)
3834 FIXME("Unsupported arguments\n");
3836 return QueueUserWorkItem(pfnCallback
, pContext
, 0);
3839 /***********************************************************************
3840 * SHSetTimerQueueTimer (SHLWAPI.263)
3842 HANDLE WINAPI
SHSetTimerQueueTimer(HANDLE hQueue
,
3843 WAITORTIMERCALLBACK pfnCallback
, LPVOID pContext
, DWORD dwDueTime
,
3844 DWORD dwPeriod
, LPCSTR lpszLibrary
, DWORD dwFlags
)
3848 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
3849 if (dwFlags
& TPS_LONGEXECTIME
) {
3850 dwFlags
&= ~TPS_LONGEXECTIME
;
3851 dwFlags
|= WT_EXECUTELONGFUNCTION
;
3853 if (dwFlags
& TPS_EXECUTEIO
) {
3854 dwFlags
&= ~TPS_EXECUTEIO
;
3855 dwFlags
|= WT_EXECUTEINIOTHREAD
;
3858 if (!CreateTimerQueueTimer(&hNewTimer
, hQueue
, pfnCallback
, pContext
,
3859 dwDueTime
, dwPeriod
, dwFlags
))
3865 /***********************************************************************
3866 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
3868 HRESULT WINAPI
IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown
, LPUNKNOWN pFocusObject
, BOOL bFocus
)
3870 IInputObjectSite
*pIOS
= NULL
;
3871 HRESULT hRet
= E_INVALIDARG
;
3873 TRACE("(%p, %p, %s)\n", lpUnknown
, pFocusObject
, bFocus
? "TRUE" : "FALSE");
3877 hRet
= IUnknown_QueryInterface(lpUnknown
, &IID_IInputObjectSite
,
3879 if (SUCCEEDED(hRet
) && pIOS
)
3881 hRet
= IInputObjectSite_OnFocusChangeIS(pIOS
, pFocusObject
, bFocus
);
3882 IInputObjectSite_Release(pIOS
);
3888 /***********************************************************************
3889 * SKAllocValueW (SHLWAPI.519)
3891 HRESULT WINAPI
SKAllocValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
, DWORD
*type
,
3892 LPVOID
*data
, DWORD
*count
)
3897 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags
, debugstr_w(subkey
),
3898 debugstr_w(value
), type
, data
, count
);
3900 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
3902 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
3904 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, NULL
, &size
);
3907 return HRESULT_FROM_WIN32(ret
);
3911 *data
= LocalAlloc(0, size
);
3914 return E_OUTOFMEMORY
;
3917 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, *data
, &size
);
3922 return HRESULT_FROM_WIN32(ret
);
3925 /***********************************************************************
3926 * SKDeleteValueW (SHLWAPI.518)
3928 HRESULT WINAPI
SKDeleteValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
)
3933 TRACE("(0x%x, %s %s)\n", flags
, debugstr_w(subkey
), debugstr_w(value
));
3935 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
3937 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
3939 ret
= RegDeleteValueW(hkey
, value
);
3942 return HRESULT_FROM_WIN32(ret
);
3945 /***********************************************************************
3946 * SKGetValueW (SHLWAPI.516)
3948 HRESULT WINAPI
SKGetValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
, DWORD
*type
,
3949 void *data
, DWORD
*count
)
3954 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags
, debugstr_w(subkey
),
3955 debugstr_w(value
), type
, data
, count
);
3957 hkey
= SHGetShellKey(flags
, subkey
, FALSE
);
3959 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
3961 ret
= SHQueryValueExW(hkey
, value
, NULL
, type
, data
, count
);
3964 return HRESULT_FROM_WIN32(ret
);
3967 /***********************************************************************
3968 * SKSetValueW (SHLWAPI.516)
3970 HRESULT WINAPI
SKSetValueW(DWORD flags
, LPCWSTR subkey
, LPCWSTR value
,
3971 DWORD type
, void *data
, DWORD count
)
3976 TRACE("(0x%x, %s, %s, %x, %p, %d)\n", flags
, debugstr_w(subkey
),
3977 debugstr_w(value
), type
, data
, count
);
3979 hkey
= SHGetShellKey(flags
, subkey
, TRUE
);
3981 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
3983 ret
= RegSetValueExW(hkey
, value
, 0, type
, data
, count
);
3986 return HRESULT_FROM_WIN32(ret
);
3989 typedef HRESULT (WINAPI
*DllGetVersion_func
)(DLLVERSIONINFO
*);
3991 /***********************************************************************
3992 * GetUIVersion (SHLWAPI.452)
3994 DWORD WINAPI
GetUIVersion(void)
3996 static DWORD version
;
4000 DllGetVersion_func pDllGetVersion
;
4001 HMODULE dll
= LoadLibraryA("shell32.dll");
4004 pDllGetVersion
= (DllGetVersion_func
)GetProcAddress(dll
, "DllGetVersion");
4008 dvi
.cbSize
= sizeof(DLLVERSIONINFO
);
4009 if (pDllGetVersion(&dvi
) == S_OK
) version
= dvi
.dwMajorVersion
;
4012 if (!version
) version
= 3; /* old shell dlls don't have DllGetVersion */
4017 /***********************************************************************
4018 * ShellMessageBoxWrapW [SHLWAPI.388]
4020 * See shell32.ShellMessageBoxW
4023 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4024 * because we can't forward to it in the .spec file since it's exported by
4025 * ordinal. If you change the implementation here please update the code in
4028 INT WINAPIV
ShellMessageBoxWrapW(HINSTANCE hInstance
, HWND hWnd
, LPCWSTR lpText
,
4029 LPCWSTR lpCaption
, UINT uType
, ...)
4031 WCHAR
*szText
= NULL
, szTitle
[100];
4032 LPCWSTR pszText
, pszTitle
= szTitle
;
4037 __ms_va_start(args
, uType
);
4039 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance
, hWnd
, lpText
, lpCaption
, uType
);
4041 if (IS_INTRESOURCE(lpCaption
))
4042 LoadStringW(hInstance
, LOWORD(lpCaption
), szTitle
, ARRAY_SIZE(szTitle
));
4044 pszTitle
= lpCaption
;
4046 if (IS_INTRESOURCE(lpText
))
4049 UINT len
= LoadStringW(hInstance
, LOWORD(lpText
), (LPWSTR
)&ptr
, 0);
4053 szText
= HeapAlloc(GetProcessHeap(), 0, (len
+ 1) * sizeof(WCHAR
));
4054 if (szText
) LoadStringW(hInstance
, LOWORD(lpText
), szText
, len
+ 1);
4058 WARN("Failed to load id %d\n", LOWORD(lpText
));
4066 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_STRING
,
4067 pszText
, 0, 0, (LPWSTR
)&pszTemp
, 0, &args
);
4071 ret
= MessageBoxW(hWnd
, pszTemp
, pszTitle
, uType
);
4073 HeapFree(GetProcessHeap(), 0, szText
);
4078 /***********************************************************************
4079 * ZoneComputePaneSize [SHLWAPI.382]
4081 UINT WINAPI
ZoneComputePaneSize(HWND hwnd
)
4087 /***********************************************************************
4088 * SHChangeNotifyWrap [SHLWAPI.394]
4090 void WINAPI
SHChangeNotifyWrap(LONG wEventId
, UINT uFlags
, LPCVOID dwItem1
, LPCVOID dwItem2
)
4092 SHChangeNotify(wEventId
, uFlags
, dwItem1
, dwItem2
);
4095 typedef struct SHELL_USER_SID
{ /* according to MSDN this should be in shlobj.h... */
4096 SID_IDENTIFIER_AUTHORITY sidAuthority
;
4097 DWORD dwUserGroupID
;
4099 } SHELL_USER_SID
, *PSHELL_USER_SID
;
4101 typedef struct SHELL_USER_PERMISSION
{ /* ...and this should be in shlwapi.h */
4102 SHELL_USER_SID susID
;
4106 DWORD dwInheritMask
;
4107 DWORD dwInheritAccessMask
;
4108 } SHELL_USER_PERMISSION
, *PSHELL_USER_PERMISSION
;
4110 /***********************************************************************
4111 * GetShellSecurityDescriptor [SHLWAPI.475]
4113 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4116 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4117 * each of which describes permissions to apply
4118 * cUserPerm [I] number of entries in apUserPerm array
4121 * success: pointer to SECURITY_DESCRIPTOR
4125 * Call should free returned descriptor with LocalFree
4127 PSECURITY_DESCRIPTOR WINAPI
GetShellSecurityDescriptor(const PSHELL_USER_PERMISSION
*apUserPerm
, int cUserPerm
)
4130 PSID cur_user
= NULL
;
4134 PSECURITY_DESCRIPTOR psd
= NULL
;
4136 TRACE("%p %d\n", apUserPerm
, cUserPerm
);
4138 if (apUserPerm
== NULL
|| cUserPerm
<= 0)
4141 sidlist
= HeapAlloc(GetProcessHeap(), 0, cUserPerm
* sizeof(PSID
));
4145 acl_size
= sizeof(ACL
);
4147 for(sid_count
= 0; sid_count
< cUserPerm
; sid_count
++)
4149 static SHELL_USER_SID null_sid
= {{SECURITY_NULL_SID_AUTHORITY
}, 0, 0};
4150 PSHELL_USER_PERMISSION perm
= apUserPerm
[sid_count
];
4151 PSHELL_USER_SID sid
= &perm
->susID
;
4155 if (!memcmp((void*)sid
, (void*)&null_sid
, sizeof(SHELL_USER_SID
)))
4156 { /* current user's SID */
4160 DWORD bufsize
= sizeof(tuUser
);
4162 ret
= OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &Token
);
4165 ret
= GetTokenInformation(Token
, TokenUser
, (void*)tuUser
, bufsize
, &bufsize
);
4167 cur_user
= ((PTOKEN_USER
)tuUser
)->User
.Sid
;
4172 } else if (sid
->dwUserID
==0) /* one sub-authority */
4173 ret
= AllocateAndInitializeSid(&sid
->sidAuthority
, 1, sid
->dwUserGroupID
, 0,
4174 0, 0, 0, 0, 0, 0, &pSid
);
4176 ret
= AllocateAndInitializeSid(&sid
->sidAuthority
, 2, sid
->dwUserGroupID
, sid
->dwUserID
,
4177 0, 0, 0, 0, 0, 0, &pSid
);
4181 sidlist
[sid_count
] = pSid
;
4182 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4183 acl_size
+= (sizeof(ACCESS_ALLOWED_ACE
)-sizeof(DWORD
) + GetLengthSid(pSid
)) * (perm
->fInherit
? 2 : 1);
4186 psd
= LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR
) + acl_size
);
4190 PACL pAcl
= (PACL
)(((BYTE
*)psd
)+sizeof(SECURITY_DESCRIPTOR
));
4192 if (!InitializeSecurityDescriptor(psd
, SECURITY_DESCRIPTOR_REVISION
))
4195 if (!InitializeAcl(pAcl
, acl_size
, ACL_REVISION
))
4198 for(i
= 0; i
< sid_count
; i
++)
4200 PSHELL_USER_PERMISSION sup
= apUserPerm
[i
];
4201 PSID sid
= sidlist
[i
];
4203 switch(sup
->dwAccessType
)
4205 case ACCESS_ALLOWED_ACE_TYPE
:
4206 if (!AddAccessAllowedAce(pAcl
, ACL_REVISION
, sup
->dwAccessMask
, sid
))
4208 if (sup
->fInherit
&& !AddAccessAllowedAceEx(pAcl
, ACL_REVISION
,
4209 (BYTE
)sup
->dwInheritMask
, sup
->dwInheritAccessMask
, sid
))
4212 case ACCESS_DENIED_ACE_TYPE
:
4213 if (!AddAccessDeniedAce(pAcl
, ACL_REVISION
, sup
->dwAccessMask
, sid
))
4215 if (sup
->fInherit
&& !AddAccessDeniedAceEx(pAcl
, ACL_REVISION
,
4216 (BYTE
)sup
->dwInheritMask
, sup
->dwInheritAccessMask
, sid
))
4224 if (!SetSecurityDescriptorDacl(psd
, TRUE
, pAcl
, FALSE
))
4233 for(i
= 0; i
< sid_count
; i
++)
4235 if (!cur_user
|| sidlist
[i
] != cur_user
)
4236 FreeSid(sidlist
[i
]);
4238 HeapFree(GetProcessHeap(), 0, sidlist
);
4243 /***********************************************************************
4244 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4246 * Creates a property bag from a registry key
4249 * hKey [I] Handle to the desired registry key
4250 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4251 * grfMode [I] Optional flags
4252 * riid [I] IID of requested property bag interface
4253 * ppv [O] Address to receive pointer to the new interface
4257 * failure: error code
4260 HRESULT WINAPI
SHCreatePropertyBagOnRegKey (HKEY hKey
, LPCWSTR subkey
,
4261 DWORD grfMode
, REFIID riid
, void **ppv
)
4263 FIXME("%p %s %d %s %p STUB\n", hKey
, debugstr_w(subkey
), grfMode
,
4264 debugstr_guid(riid
), ppv
);
4269 /***********************************************************************
4270 * SHFormatDateTimeW [SHLWAPI.354]
4272 * Produces a string representation of a time.
4275 * fileTime [I] Pointer to FILETIME structure specifying the time
4276 * flags [I] Flags specifying the desired output
4277 * buf [O] Pointer to buffer for output
4278 * size [I] Number of characters that can be contained in buffer
4281 * success: number of characters written to the buffer
4285 INT WINAPI
SHFormatDateTimeW(const FILETIME UNALIGNED
*fileTime
, DWORD
*flags
,
4286 LPWSTR buf
, UINT size
)
4288 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
4289 DWORD fmt_flags
= flags
? *flags
: FDTF_DEFAULT
;
4294 TRACE("%p %p %p %u\n", fileTime
, flags
, buf
, size
);
4299 if (fmt_flags
& SHFORMATDT_UNSUPPORTED_FLAGS
)
4300 FIXME("ignoring some flags - 0x%08x\n", fmt_flags
& SHFORMATDT_UNSUPPORTED_FLAGS
);
4302 FileTimeToLocalFileTime(fileTime
, &ft
);
4303 FileTimeToSystemTime(&ft
, &st
);
4305 /* first of all date */
4306 if (fmt_flags
& (FDTF_LONGDATE
| FDTF_SHORTDATE
))
4308 static const WCHAR sep1
[] = {',',' ',0};
4309 static const WCHAR sep2
[] = {' ',0};
4311 DWORD date
= fmt_flags
& FDTF_LONGDATE
? DATE_LONGDATE
: DATE_SHORTDATE
;
4312 ret
= GetDateFormatW(LOCALE_USER_DEFAULT
, date
, &st
, NULL
, buf
, size
);
4313 if (ret
>= size
) return ret
;
4316 if (ret
< size
&& (fmt_flags
& (FDTF_LONGTIME
| FDTF_SHORTTIME
)))
4318 if ((fmt_flags
& FDTF_LONGDATE
) && (ret
< size
+ 2))
4320 lstrcatW(&buf
[ret
-1], sep1
);
4325 lstrcatW(&buf
[ret
-1], sep2
);
4331 if (fmt_flags
& (FDTF_LONGTIME
| FDTF_SHORTTIME
))
4333 DWORD time
= fmt_flags
& FDTF_LONGTIME
? 0 : TIME_NOSECONDS
;
4336 ret
+= GetTimeFormatW(LOCALE_USER_DEFAULT
, time
, &st
, NULL
, &buf
[ret
], size
- ret
);
4341 #undef SHFORMATDT_UNSUPPORTED_FLAGS
4344 /***********************************************************************
4345 * SHFormatDateTimeA [SHLWAPI.353]
4347 * See SHFormatDateTimeW.
4350 INT WINAPI
SHFormatDateTimeA(const FILETIME UNALIGNED
*fileTime
, DWORD
*flags
,
4351 LPSTR buf
, UINT size
)
4359 bufW
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * size
);
4360 retval
= SHFormatDateTimeW(fileTime
, flags
, bufW
, size
);
4363 WideCharToMultiByte(CP_ACP
, 0, bufW
, -1, buf
, size
, NULL
, NULL
);
4365 HeapFree(GetProcessHeap(), 0, bufW
);
4369 /***********************************************************************
4370 * ZoneCheckUrlExW [SHLWAPI.231]
4372 * Checks the details of the security zone for the supplied site. (?)
4376 * szURL [I] Pointer to the URL to check
4378 * Other parameters currently unknown.
4384 INT WINAPI
ZoneCheckUrlExW(LPWSTR szURL
, PVOID pUnknown
, DWORD dwUnknown2
,
4385 DWORD dwUnknown3
, DWORD dwUnknown4
, DWORD dwUnknown5
, DWORD dwUnknown6
,
4388 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL
), pUnknown
, dwUnknown2
,
4389 dwUnknown3
, dwUnknown4
, dwUnknown5
, dwUnknown6
, dwUnknown7
);
4394 /***********************************************************************
4395 * SHVerbExistsNA [SHLWAPI.196]
4400 * verb [I] a string, often appears to be an extension.
4402 * Other parameters currently unknown.
4407 INT WINAPI
SHVerbExistsNA(LPSTR verb
, PVOID pUnknown
, PVOID pUnknown2
, DWORD dwUnknown3
)
4409 FIXME("(%s, %p, %p, %i) STUB\n",verb
, pUnknown
, pUnknown2
, dwUnknown3
);
4413 /*************************************************************************
4416 * Undocumented: Implementation guessed at via Name and behavior
4419 * lpUnknown [I] Object to get an IServiceProvider interface from
4420 * riid [I] Function requested for QueryService call
4421 * lppOut [O] Destination for the service interface pointer
4424 * Success: S_OK. lppOut contains an object providing the requested service
4425 * Failure: An HRESULT error code
4428 * lpUnknown is expected to support the IServiceProvider interface.
4430 HRESULT WINAPI
IUnknown_QueryServiceForWebBrowserApp(IUnknown
* lpUnknown
,
4431 REFGUID riid
, LPVOID
*lppOut
)
4433 FIXME("%p %s %p semi-STUB\n", lpUnknown
, debugstr_guid(riid
), lppOut
);
4434 return iunknown_query_service(lpUnknown
,&IID_IWebBrowserApp
,riid
,lppOut
);
4437 /**************************************************************************
4438 * SHPropertyBag_ReadLONG (SHLWAPI.496)
4440 * This function asks a property bag to read a named property as a LONG.
4443 * ppb: a IPropertyBag interface
4444 * pszPropName: Unicode string that names the property
4445 * pValue: address to receive the property value as a 32-bit signed integer
4450 HRESULT WINAPI
SHPropertyBag_ReadLONG(IPropertyBag
*ppb
, LPCWSTR pszPropName
, LPLONG pValue
)
4454 TRACE("%p %s %p\n", ppb
,debugstr_w(pszPropName
),pValue
);
4455 if (!pszPropName
|| !ppb
|| !pValue
)
4456 return E_INVALIDARG
;
4458 hr
= IPropertyBag_Read(ppb
, pszPropName
, &var
, NULL
);
4461 if (V_VT(&var
) == VT_I4
)
4462 *pValue
= V_I4(&var
);
4464 hr
= DISP_E_BADVARTYPE
;
4469 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
4470 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
4471 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
4472 #define OBJCOMPAT_UNBINDABLE 0x00000004
4473 #define OBJCOMPAT_PINDLL 0x00000008
4474 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
4475 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
4476 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
4477 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
4478 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
4479 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
4480 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
4481 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
4482 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
4484 /* a search table for compatibility flags */
4485 struct objcompat_entry
{
4486 const WCHAR name
[30];
4490 /* expected to be sorted by name */
4491 static const struct objcompat_entry objcompat_table
[] = {
4492 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
4493 OBJCOMPAT_COCREATESHELLFOLDERONLY
},
4494 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
4495 OBJCOMPAT_CTXMENU_LIMITEDQI
},
4496 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
4497 OBJCOMPAT_CTXMENU_LIMITEDQI
},
4498 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
4499 OBJCOMPAT_CTXMENU_XPQCMFLAGS
},
4500 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
4501 OBJCOMPAT_NEEDSFILESYSANCESTOR
},
4502 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
4503 OBJCOMPAT_NEEDSSTORAGEANCESTOR
},
4504 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
4505 OBJCOMPAT_NOIPROPERTYSTORE
},
4506 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
4507 OBJCOMPAT_NOLEGACYWEBVIEW
},
4508 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
4509 OBJCOMPAT_NOTAFILESYSTEM
},
4510 { {'N','O','_','W','E','B','V','I','E','W',0},
4511 OBJCOMPAT_NO_WEBVIEW
},
4512 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
4513 OBJCOMPAT_OTNEEDSSFCACHE
},
4514 { {'P','I','N','D','L','L',0},
4516 { {'U','N','B','I','N','D','A','B','L','E',0},
4517 OBJCOMPAT_UNBINDABLE
}
4520 /**************************************************************************
4521 * SHGetObjectCompatFlags (SHLWAPI.476)
4523 * Function returns an integer representation of compatibility flags stored
4524 * in registry for CLSID under ShellCompatibility subkey.
4527 * pUnk: pointer to object IUnknown interface, identifies CLSID
4528 * clsid: pointer to CLSID to retrieve data for
4531 * 0 on failure, flags set on success
4533 DWORD WINAPI
SHGetObjectCompatFlags(IUnknown
*pUnk
, const CLSID
*clsid
)
4535 static const WCHAR compatpathW
[] =
4536 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4537 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4538 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
4539 'O','b','j','e','c','t','s','\\','%','s',0};
4540 WCHAR strW
[ARRAY_SIZE(compatpathW
) + 38 /* { CLSID } */];
4541 DWORD ret
, length
= ARRAY_SIZE(strW
);
4546 TRACE("%p %s\n", pUnk
, debugstr_guid(clsid
));
4548 if (!pUnk
&& !clsid
) return 0;
4552 FIXME("iface not handled\n");
4556 StringFromCLSID(clsid
, &clsid_str
);
4557 swprintf(strW
, ARRAY_SIZE(strW
), compatpathW
, clsid_str
);
4558 CoTaskMemFree(clsid_str
);
4560 ret
= RegOpenKeyW(HKEY_LOCAL_MACHINE
, strW
, &key
);
4561 if (ret
!= ERROR_SUCCESS
) return 0;
4563 /* now collect flag values */
4565 for (i
= 0; RegEnumValueW(key
, i
, strW
, &length
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
; i
++)
4567 INT left
, right
, res
, x
;
4569 /* search in table */
4571 right
= ARRAY_SIZE(objcompat_table
) - 1;
4573 while (right
>= left
) {
4574 x
= (left
+ right
) / 2;
4575 res
= wcscmp(strW
, objcompat_table
[x
].name
);
4578 ret
|= objcompat_table
[x
].value
;
4587 length
= ARRAY_SIZE(strW
);