win32u: Use the dummy surface for empty layered window surfaces.
[wine.git] / dlls / shlwapi / ordinal.c
blobf99dbf795ff5910771c491bb8163211c41956abe
1 /*
2 * SHLWAPI ordinal functions
4 * Copyright 1997 Marcus Meissner
5 * 1998 Jürgen Schmied
6 * 2001-2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <stdarg.h>
24 #include <stdio.h>
25 #include <string.h>
27 #define COBJMACROS
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winnls.h"
32 #include "winreg.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35 #include "winver.h"
36 #include "winnetwk.h"
37 #include "mmsystem.h"
38 #include "objbase.h"
39 #include "exdisp.h"
40 #include "shdeprecated.h"
41 #include "shlobj.h"
42 #include "shlwapi.h"
43 #include "shellapi.h"
44 #include "commdlg.h"
45 #include "mlang.h"
46 #include "mshtmhst.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 /*************************************************************************
70 * @ [SHLWAPI.11]
72 * Copy a sharable memory handle from one process to another.
74 * PARAMS
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
81 * RETURNS
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)
89 HANDLE hDst, hSrc;
90 DWORD dwMyProcId = GetCurrentProcessId();
91 HANDLE hRet = NULL;
93 TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", hShared, dwDstProcId, dwSrcProcId,
94 dwAccess, dwOptions);
96 if (!hShared)
98 TRACE("Returning handle NULL\n");
99 return NULL;
102 /* Get dest process handle */
103 if (dwDstProcId == dwMyProcId)
104 hDst = GetCurrentProcess();
105 else
106 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
108 if (hDst)
110 /* Get src process handle */
111 if (dwSrcProcId == dwMyProcId)
112 hSrc = GetCurrentProcess();
113 else
114 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
116 if (hSrc)
118 /* Make handle available to dest process */
119 if (!DuplicateHandle(hSrc, hShared, hDst, &hRet,
120 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
121 hRet = NULL;
123 if (dwSrcProcId != dwMyProcId)
124 CloseHandle(hSrc);
127 if (dwDstProcId != dwMyProcId)
128 CloseHandle(hDst);
131 TRACE("Returning handle %p\n", hRet);
132 return hRet;
135 /*************************************************************************
136 * @ [SHLWAPI.7]
138 * Create a block of sharable memory and initialise it with data.
140 * PARAMS
141 * lpvData [I] Pointer to data to write
142 * dwSize [I] Size of data
143 * dwProcId [I] ID of process owning data
145 * RETURNS
146 * Success: A shared memory handle
147 * Failure: NULL
149 * NOTES
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)
159 HANDLE hMap;
160 LPVOID pMapped;
161 HANDLE hRet = NULL;
163 TRACE("(%p,%ld,%ld)\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);
168 if (!hMap)
169 return hRet;
171 /* Get a view in our process address space */
172 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
174 if (pMapped)
176 /* Write size of data, followed by the data, to the view */
177 *((DWORD*)pMapped) = dwSize;
178 if (lpvData)
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);
187 CloseHandle(hMap);
188 return hRet;
191 /*************************************************************************
192 * @ [SHLWAPI.8]
194 * Get a pointer to a block of shared memory from a shared memory handle.
196 * PARAMS
197 * hShared [I] Shared memory handle
198 * dwProcId [I] ID of process owning hShared
200 * RETURNS
201 * Success: A pointer to the shared memory
202 * Failure: NULL
205 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
207 HANDLE hDup;
208 LPVOID pMapped;
210 TRACE("(%p %ld)\n", hShared, dwProcId);
212 /* Get handle to shared memory for current process */
213 hDup = SHMapHandle(hShared, dwProcId, GetCurrentProcessId(), FILE_MAP_ALL_ACCESS, 0);
215 /* Get View */
216 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
217 CloseHandle(hDup);
219 if (pMapped)
220 return (char *) pMapped + sizeof(DWORD); /* Hide size */
221 return NULL;
224 /*************************************************************************
225 * @ [SHLWAPI.9]
227 * Release a pointer to a block of shared memory.
229 * PARAMS
230 * lpView [I] Shared memory pointer
232 * RETURNS
233 * Success: TRUE
234 * Failure: FALSE
237 BOOL WINAPI SHUnlockShared(LPVOID lpView)
239 TRACE("(%p)\n", lpView);
240 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
243 /*************************************************************************
244 * @ [SHLWAPI.10]
246 * Destroy a block of sharable memory.
248 * PARAMS
249 * hShared [I] Shared memory handle
250 * dwProcId [I] ID of process owning hShared
252 * RETURNS
253 * Success: TRUE
254 * Failure: FALSE
257 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
259 HANDLE hClose;
261 TRACE("(%p %ld)\n", hShared, dwProcId);
263 if (!hShared)
264 return TRUE;
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 /*************************************************************************
274 * @ [SHLWAPI.13]
276 * Create and register a clipboard enumerator for a web browser.
278 * PARAMS
279 * lpBC [I] Binding context
280 * lpUnknown [I] An object exposing the IWebBrowserApp interface
282 * RETURNS
283 * Success: S_OK.
284 * Failure: An HRESULT error code.
286 * NOTES
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' };
295 BSTR property;
296 IEnumFORMATETC* pIEnumFormatEtc = NULL;
297 VARIANTARG var;
298 HRESULT hr;
299 IWebBrowserApp* pBrowser;
301 TRACE("(%p, %p)\n", lpBC, lpUnknown);
303 hr = iunknown_query_service(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (void**)&pBrowser);
304 if (FAILED(hr))
305 return hr;
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;
321 HKEY hDocs;
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))
328 hr = E_FAIL;
329 goto exit;
332 /* Get count of values in key */
333 while (!dwRet)
335 dwKeySize = sizeof(szKeyBuff);
336 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
337 dwCount++;
340 dwNumValues = dwCount;
342 /* Note: dwCount = number of items + 1; The extra item is the end node */
343 format = formatList = malloc(dwCount * sizeof(FORMATETC));
344 if (!formatList)
346 RegCloseKey(hDocs);
347 hr = E_OUTOFMEMORY;
348 goto exit;
351 if (dwNumValues > 1)
353 dwRet = 0;
354 dwCount = 0;
356 dwNumValues--;
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);
365 if (!dwRet)
367 free(formatList);
368 RegCloseKey(hDocs);
369 hr = E_FAIL;
370 goto exit;
373 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
374 format->ptd = NULL;
375 format->dwAspect = 1;
376 format->lindex = 4;
377 format->tymed = -1;
379 format++;
380 dwCount++;
384 RegCloseKey(hDocs);
386 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
387 format->cfFormat = 0;
388 format->ptd = NULL;
389 format->dwAspect = 1;
390 format->lindex = 4;
391 format->tymed = -1;
393 /* Create a clipboard enumerator */
394 hr = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
395 free(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);
405 if (FAILED(hr))
407 IEnumFORMATETC_Release(pIEnumFormatEtc);
408 goto exit;
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));
439 exit:
440 IWebBrowserApp_Release(pBrowser);
441 return hr;
444 /*************************************************************************
445 * @ [SHLWAPI.23]
447 * Convert a GUID to a string.
449 * PARAMS
450 * guid [I] GUID to convert
451 * lpszDest [O] Destination for string
452 * cchMax [I] Length of output buffer
454 * RETURNS
455 * The length of the string created.
457 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
459 char xguid[40];
460 INT iLen;
462 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
464 sprintf(xguid, "{%08lX-%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;
471 if (iLen > cchMax)
472 return 0;
473 memcpy(lpszDest, xguid, iLen);
474 return iLen;
477 /*************************************************************************
478 * @ [SHLWAPI.24]
480 * Convert a GUID to a string.
482 * PARAMS
483 * guid [I] GUID to convert
484 * str [O] Destination for string
485 * cmax [I] Length of output buffer
487 * RETURNS
488 * The length of the string created.
490 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
492 WCHAR xguid[40];
493 INT iLen;
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;
506 if (iLen > cchMax)
507 return 0;
508 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
509 return iLen;
512 /*************************************************************************
513 * @ [SHLWAPI.35]
516 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type)
518 return GetStringTypeW(CT_CTYPE3, src, count, type);
521 /*************************************************************************
522 * @ [SHLWAPI.160]
524 * Get an identification string for the OS and explorer.
526 * PARAMS
527 * lpszDest [O] Destination for Id string
528 * dwDestLen [I] Length of lpszDest
530 * RETURNS
531 * TRUE, If the string was created successfully
532 * FALSE, Otherwise
534 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
536 WCHAR buff[2084];
538 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
540 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
542 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
543 return TRUE;
545 return FALSE;
548 /*************************************************************************
549 * @ [SHLWAPI.161]
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' };
580 WCHAR buff[2084];
581 HKEY hReg;
582 DWORD dwType, dwLen;
584 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
586 if (!lpszDest)
587 return FALSE;
589 *lpszDest = '\0';
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))
594 return FALSE;
596 /* OS Version */
597 buff[0] = '\0';
598 dwLen = 30;
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 */
609 buff[0] = '~';
610 dwLen = 256;
611 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
612 buff[1] = '\0';
613 StrCatBuffW(lpszDest, buff, dwDestLen);
615 /* ~Registered Organization */
616 dwLen = 256;
617 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
618 buff[1] = '\0';
619 StrCatBuffW(lpszDest, buff, dwDestLen);
621 /* FIXME: Not sure where this number comes from */
622 buff[0] = '~';
623 buff[1] = '0';
624 buff[2] = '\0';
625 StrCatBuffW(lpszDest, buff, dwDestLen);
627 /* ~Product Id */
628 dwLen = 256;
629 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
630 buff[1] = '\0';
631 StrCatBuffW(lpszDest, buff, dwDestLen);
633 /* ~IE Update Url */
634 dwLen = 2048;
635 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
636 buff[1] = '\0';
637 StrCatBuffW(lpszDest, buff, dwDestLen);
639 /* ~IE Help String */
640 dwLen = 256;
641 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
642 buff[1] = '\0';
643 StrCatBuffW(lpszDest, buff, dwDestLen);
645 RegCloseKey(hReg);
646 return TRUE;
649 /*************************************************************************
650 * @ [SHLWAPI.163]
652 * Call IOleCommandTarget_QueryStatus() on an object.
654 * PARAMS
655 * lpUnknown [I] Object supporting the IOleCommandTarget interface
656 * pguidCmdGroup [I] GUID for the command group
657 * cCmds [I]
658 * prgCmds [O] Commands
659 * pCmdText [O] Command text
661 * RETURNS
662 * Success: S_OK.
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,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
674 if (lpUnknown)
676 IOleCommandTarget* lpOle;
678 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
679 (void**)&lpOle);
681 if (SUCCEEDED(hRet) && lpOle)
683 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
684 prgCmds, pCmdText);
685 IOleCommandTarget_Release(lpOle);
688 return hRet;
691 /*************************************************************************
692 * @ [SHLWAPI.164]
694 * Call IOleCommandTarget_Exec() on an object.
696 * PARAMS
697 * lpUnknown [I] Object supporting the IOleCommandTarget interface
698 * pguidCmdGroup [I] GUID for the command group
700 * RETURNS
701 * Success: S_OK.
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,
708 VARIANT* pvaOut)
710 HRESULT hRet = E_FAIL;
712 TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
713 nCmdexecopt, pvaIn, pvaOut);
715 if (lpUnknown)
717 IOleCommandTarget* lpOle;
719 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
720 (void**)&lpOle);
721 if (SUCCEEDED(hRet) && lpOle)
723 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
724 nCmdexecopt, pvaIn, pvaOut);
725 IOleCommandTarget_Release(lpOle);
728 return hRet;
731 /*************************************************************************
732 * @ [SHLWAPI.165]
734 * Retrieve, modify, and re-set a value from a window.
736 * PARAMS
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
742 * RETURNS
743 * The new value as it was set, or 0 if any parameter is invalid.
745 * NOTES
746 * Only bits specified in mask are affected - set if present in flags and
747 * reset otherwise.
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);
758 return ret;
761 /*************************************************************************
762 * @ [SHLWAPI.167]
764 * Change a window's parent.
766 * PARAMS
767 * hWnd [I] Window to change parent of
768 * hWndParent [I] New parent window
770 * RETURNS
771 * The old parent of hWnd.
773 * NOTES
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)
782 return NULL;
784 if(hWndParent)
785 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD | WS_POPUP, WS_CHILD);
786 else
787 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD | WS_POPUP, WS_POPUP);
789 return hWndParent ? SetParent(hWnd, hWndParent) : NULL;
792 /*************************************************************************
793 * @ [SHLWAPI.168]
795 * Locate and advise a connection point in an IConnectionPointContainer object.
797 * PARAMS
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
805 * RETURNS
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)
816 HRESULT hRet;
817 IConnectionPointContainer* lpContainer;
818 IConnectionPoint *lpCP;
820 if(!lpUnknown || (fConnect && !lpUnkSink))
821 return E_FAIL;
823 if(lppCP)
824 *lppCP = NULL;
826 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
827 (void**)&lpContainer);
828 if (SUCCEEDED(hRet))
830 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
832 if (SUCCEEDED(hRet))
834 if(!fConnect)
835 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
836 else
837 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
839 if (FAILED(hRet))
840 *lpCookie = 0;
842 if (lppCP && SUCCEEDED(hRet))
843 *lppCP = lpCP; /* Caller keeps the interface */
844 else
845 IConnectionPoint_Release(lpCP); /* Release it */
848 IConnectionPointContainer_Release(lpContainer);
850 return hRet;
853 /*************************************************************************
854 * @ [SHLWAPI.170]
856 * Skip '//' if present in a string.
858 * PARAMS
859 * lpszSrc [I] String to check for '//'
861 * RETURNS
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] == '/')
868 lpszSrc += 2;
869 return lpszSrc;
872 /*************************************************************************
873 * @ [SHLWAPI.171]
875 * Check if two interfaces come from the same object.
877 * PARAMS
878 * lpInt1 [I] Interface to check against lpInt2.
879 * lpInt2 [I] Interface to check against lpInt1.
881 * RETURNS
882 * TRUE, If the interfaces come from the same object.
883 * FALSE Otherwise.
885 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
887 IUnknown *lpUnknown1, *lpUnknown2;
888 BOOL ret;
890 TRACE("(%p %p)\n", lpInt1, lpInt2);
892 if (!lpInt1 || !lpInt2)
893 return FALSE;
895 if (lpInt1 == lpInt2)
896 return TRUE;
898 if (IUnknown_QueryInterface(lpInt1, &IID_IUnknown, (void**)&lpUnknown1) != S_OK)
899 return FALSE;
901 if (IUnknown_QueryInterface(lpInt2, &IID_IUnknown, (void**)&lpUnknown2) != S_OK)
903 IUnknown_Release(lpUnknown1);
904 return FALSE;
907 ret = lpUnknown1 == lpUnknown2;
909 IUnknown_Release(lpUnknown1);
910 IUnknown_Release(lpUnknown2);
912 return ret;
915 /*************************************************************************
916 * @ [SHLWAPI.172]
918 * Get the window handle of an object.
920 * PARAMS
921 * lpUnknown [I] Object to get the window handle of
922 * lphWnd [O] Destination for window handle
924 * RETURNS
925 * Success: S_OK. lphWnd contains the objects window handle.
926 * Failure: An HRESULT error code.
928 * NOTES
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)
934 IUnknown *lpOle;
935 HRESULT hRet = E_FAIL;
937 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
939 if (!lpUnknown)
940 return hRet;
942 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
944 if (FAILED(hRet))
946 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
948 if (FAILED(hRet))
950 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
951 (void**)&lpOle);
955 if (SUCCEEDED(hRet))
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);
962 if (lphWnd)
963 TRACE("Returning HWND=%p\n", *lphWnd);
966 return hRet;
969 /*************************************************************************
970 * @ [SHLWAPI.173]
972 * Call a SetOwner method of IShellService from specified object.
974 * PARAMS
975 * iface [I] Object that supports IShellService
976 * pUnk [I] Argument for the SetOwner call
978 * RETURNS
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;
984 HRESULT hr;
986 TRACE("(%p, %p)\n", iface, pUnk);
988 if (!iface) return E_FAIL;
990 hr = IUnknown_QueryInterface(iface, &IID_IShellService, (void**)&service);
991 if (hr == S_OK)
993 hr = IShellService_SetOwner(service, pUnk);
994 IShellService_Release(service);
997 return hr;
1000 /*************************************************************************
1001 * @ [SHLWAPI.175]
1003 * Call IPersist_GetClassID() on an object.
1005 * PARAMS
1006 * lpUnknown [I] Object supporting the IPersist interface
1007 * clsid [O] Destination for Class Id
1009 * RETURNS
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)
1017 IPersist *persist;
1018 HRESULT hr;
1020 TRACE("(%p, %p)\n", lpUnknown, clsid);
1022 if (!lpUnknown)
1024 memset(clsid, 0, sizeof(*clsid));
1025 return E_FAIL;
1028 hr = IUnknown_QueryInterface(lpUnknown, &IID_IPersist, (void**)&persist);
1029 if (hr != S_OK)
1031 hr = IUnknown_QueryInterface(lpUnknown, &IID_IPersistFolder, (void**)&persist);
1032 if (hr != S_OK)
1033 return hr;
1036 hr = IPersist_GetClassID(persist, clsid);
1037 IPersist_Release(persist);
1038 return hr;
1041 static HRESULT iunknown_query_service(IUnknown* lpUnknown, REFGUID sid, REFIID riid, LPVOID *lppOut)
1043 IServiceProvider* pService = NULL;
1044 HRESULT hRet;
1046 if (!lppOut)
1047 return E_FAIL;
1049 *lppOut = NULL;
1051 if (!lpUnknown)
1052 return E_FAIL;
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);
1068 return hRet;
1071 /*************************************************************************
1072 * @ [SHLWAPI.484]
1074 * Calls IOleCommandTarget::Exec() for specified service object.
1076 * PARAMS
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
1085 * RETURNS
1086 * Success: S_OK. lppOut contains an object providing the requested service
1087 * Failure: An HRESULT error code
1089 * NOTES
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;
1096 HRESULT hr;
1098 TRACE("%p %s %s %ld %08lx %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);
1102 if (hr == S_OK)
1104 hr = IOleCommandTarget_Exec(target, group, cmdId, cmdOpt, pIn, pOut);
1105 IOleCommandTarget_Release(target);
1108 TRACE("<-- hr=0x%08lx\n", hr);
1110 return hr;
1113 /*************************************************************************
1114 * @ [SHLWAPI.514]
1116 * Calls IProfferService methods to proffer/revoke specified service.
1118 * PARAMS
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
1124 * RETURNS
1125 * Success: S_OK. IProffer method returns S_OK
1126 * Failure: An HRESULT error code
1128 * NOTES
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;
1134 HRESULT hr;
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);
1139 if (hr == S_OK)
1141 if (pService)
1142 hr = IProfferService_ProfferService(proffer, service, pService, pCookie);
1143 else
1145 hr = IProfferService_RevokeService(proffer, *pCookie);
1146 *pCookie = 0;
1149 IProfferService_Release(proffer);
1152 return hr;
1155 /*************************************************************************
1156 * @ [SHLWAPI.479]
1158 * Call an object's UIActivateIO method.
1160 * PARAMS
1161 * unknown [I] Object to call the UIActivateIO method on
1162 * activate [I] Parameter for UIActivateIO call
1163 * msg [I] Parameter for UIActivateIO call
1165 * RETURNS
1166 * Success: Value of UI_ActivateIO call
1167 * Failure: An HRESULT error code
1169 * NOTES
1170 * unknown is expected to support the IInputObject interface.
1172 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg)
1174 IInputObject* object = NULL;
1175 HRESULT ret;
1177 if (!unknown)
1178 return E_FAIL;
1180 /* Get an IInputObject interface from the object */
1181 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
1183 if (ret == S_OK)
1185 ret = IInputObject_UIActivateIO(object, activate, msg);
1186 IInputObject_Release(object);
1189 return ret;
1192 /*************************************************************************
1193 * @ [SHLWAPI.177]
1195 * Loads a popup menu.
1197 * PARAMS
1198 * hInst [I] Instance handle
1199 * szName [I] Menu name
1201 * RETURNS
1202 * Success: TRUE.
1203 * Failure: FALSE.
1205 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1207 HMENU hMenu;
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);
1216 DestroyMenu(hMenu);
1217 return TRUE;
1219 return FALSE;
1222 typedef struct _enumWndData
1224 UINT uiMsgId;
1225 WPARAM wParam;
1226 LPARAM lParam;
1227 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1228 } enumWndData;
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);
1237 return TRUE;
1240 /*************************************************************************
1241 * @ [SHLWAPI.178]
1243 * Send or post a message to every child of a window.
1245 * PARAMS
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()
1252 * RETURNS
1253 * Nothing.
1255 * NOTES
1256 * The appropriate ANSI or Unicode function is called for the window.
1258 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1260 enumWndData data;
1262 TRACE("(%p,%u,%Id,%Id,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1264 if(hWnd)
1266 data.uiMsgId = uiMsgId;
1267 data.wParam = wParam;
1268 data.lParam = lParam;
1270 if (bSend)
1271 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1272 else
1273 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1275 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1279 /*************************************************************************
1280 * @ [SHLWAPI.180]
1282 * Remove all sub-menus from a menu.
1284 * PARAMS
1285 * hMenu [I] Menu to remove sub-menus from
1287 * RETURNS
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);
1300 if (hSubMenu)
1301 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1302 iItemCount--;
1304 return iItemCount;
1307 /*************************************************************************
1308 * @ [SHLWAPI.181]
1310 * Enable or disable a menu item.
1312 * PARAMS
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.
1317 * RETURNS
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 /*************************************************************************
1327 * @ [SHLWAPI.182]
1329 * Check or uncheck a menu item.
1331 * PARAMS
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.
1336 * RETURNS
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 /*************************************************************************
1346 * @ [SHLWAPI.183]
1348 * Register a window class if it isn't already.
1350 * PARAMS
1351 * lpWndClass [I] Window class to register
1353 * RETURNS
1354 * The result of the RegisterClassA call.
1356 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1358 WNDCLASSA wca;
1359 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1360 return TRUE;
1361 return (DWORD)RegisterClassA(wndclass);
1364 /*************************************************************************
1365 * @ [SHLWAPI.186]
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%08lx %p %p\n", pDrop, pDataObj, grfKeyState, lpPt, pdwEffect);
1375 if (!lpPt)
1376 lpPt = &pt;
1378 if (!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);
1387 return TRUE;
1390 /*************************************************************************
1391 * @ [SHLWAPI.187]
1393 * Call IPersistPropertyBag_Load() on an object.
1395 * PARAMS
1396 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1397 * lpPropBag [O] Destination for loaded IPropertyBag
1399 * RETURNS
1400 * Success: S_OK.
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);
1410 if (lpUnknown)
1412 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1413 (void**)&lpPPBag);
1414 if (SUCCEEDED(hRet) && lpPPBag)
1416 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1417 IPersistPropertyBag_Release(lpPPBag);
1420 return hRet;
1423 /*************************************************************************
1424 * @ [SHLWAPI.188]
1426 * Call IOleControlSite_TranslateAccelerator() on an object.
1428 * PARAMS
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.
1433 * RETURNS
1434 * Success: S_OK.
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%08lx)\n", lpUnknown, lpMsg, dwModifiers);
1443 if (lpUnknown)
1445 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1446 (void**)&lpCSite);
1447 if (SUCCEEDED(hRet) && lpCSite)
1449 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1450 IOleControlSite_Release(lpCSite);
1453 return hRet;
1457 /*************************************************************************
1458 * @ [SHLWAPI.189]
1460 * Call IOleControlSite_OnFocus() on an object.
1462 * PARAMS
1463 * lpUnknown [I] Object supporting the IOleControlSite interface.
1464 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1466 * RETURNS
1467 * Success: S_OK.
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);
1476 if (lpUnknown)
1478 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1479 (void**)&lpCSite);
1480 if (SUCCEEDED(hRet) && lpCSite)
1482 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1483 IOleControlSite_Release(lpCSite);
1486 return hRet;
1489 /*************************************************************************
1490 * @ [SHLWAPI.190]
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);
1521 return hRet;
1524 /*************************************************************************
1525 * @ [SHLWAPI.192]
1527 * Get a sub-menu from a menu item.
1529 * PARAMS
1530 * hMenu [I] Menu to get sub-menu from
1531 * uID [I] ID of menu item containing sub-menu
1533 * RETURNS
1534 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1536 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1538 MENUITEMINFOW mi;
1540 TRACE("(%p,%u)\n", hMenu, uID);
1542 mi.cbSize = sizeof(mi);
1543 mi.fMask = MIIM_SUBMENU;
1545 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1546 return NULL;
1548 return mi.hSubMenu;
1551 /*************************************************************************
1552 * @ [SHLWAPI.193]
1554 * Get the color depth of the primary display.
1556 * PARAMS
1557 * None.
1559 * RETURNS
1560 * The color depth of the primary display.
1562 DWORD WINAPI SHGetCurColorRes(void)
1564 HDC hdc;
1565 DWORD ret;
1567 TRACE("()\n");
1569 hdc = GetDC(0);
1570 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1571 ReleaseDC(0, hdc);
1572 return ret;
1575 /*************************************************************************
1576 * @ [SHLWAPI.194]
1578 * Wait for a message to arrive, with a timeout.
1580 * PARAMS
1581 * hand [I] Handle to query
1582 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1584 * RETURNS
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;
1592 DWORD dwRet;
1594 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
1596 MSG msg;
1598 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
1600 if (dwTimeout != INFINITE)
1602 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
1603 return WAIT_TIMEOUT;
1607 return dwRet;
1610 /*************************************************************************
1611 * @ [SHLWAPI.195]
1613 * Determine if a shell folder can be expanded.
1615 * PARAMS
1616 * lpFolder [I] Parent folder containing the object to test.
1617 * pidl [I] Id of the object to test.
1619 * RETURNS
1620 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
1621 * Failure: E_INVALIDARG, if any argument is invalid.
1623 * NOTES
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;
1630 IQueryInfo *lpInfo;
1632 if (lpFolder && pidl)
1634 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
1635 NULL, (void**)&lpInfo);
1636 if (FAILED(hRet))
1637 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
1638 else
1640 DWORD dwFlags = 0;
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);
1656 return hRet;
1659 /*************************************************************************
1660 * @ [SHLWAPI.197]
1662 * Blank out a region of text by drawing the background only.
1664 * PARAMS
1665 * hDC [I] Device context to draw in
1666 * pRect [I] Area to draw in
1667 * cRef [I] Color to draw in
1669 * RETURNS
1670 * Nothing.
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);
1677 return 0;
1680 /*************************************************************************
1681 * @ [SHLWAPI.198]
1683 * Return the value associated with a key in a map.
1685 * PARAMS
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
1691 * RETURNS
1692 * The value in lpValues associated with iKey, or -1 if iKey is not
1693 * found in lpKeys.
1695 * NOTES
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)
1704 int i = 0;
1706 while (i < iLen)
1708 if (lpKeys[i] == iKey)
1709 return lpValues[i]; /* Found */
1710 i++;
1713 return -1; /* Not found */
1716 /*************************************************************************
1717 * @ [SHLWAPI.200]
1720 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
1721 REFGUID riidCmdGrp, ULONG cCmds,
1722 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1724 FIXME("(%p,%p,%p,%ld,%p,%p) - stub\n",
1725 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
1727 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
1728 return DRAGDROP_E_NOTREGISTERED;
1731 /*************************************************************************
1732 * @ [SHLWAPI.201]
1735 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
1736 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1737 VARIANT* pvaOut)
1739 FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
1740 nCmdID, nCmdexecopt, pvaIn, pvaOut);
1741 return DRAGDROP_E_NOTREGISTERED;
1744 /*************************************************************************
1745 * @ [SHLWAPI.202]
1748 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
1750 FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
1751 return DRAGDROP_E_NOTREGISTERED;
1754 /*************************************************************************
1755 * @ [SHLWAPI.204]
1757 * Determine if a window is not a child of another window.
1759 * PARAMS
1760 * hParent [I] Suspected parent window
1761 * hChild [I] Suspected child window
1763 * RETURNS
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)
1772 return TRUE;
1773 else if(hParent == hChild)
1774 return FALSE;
1775 return !IsChild(hParent, hChild);
1778 /*************************************************************************
1779 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
1782 typedef struct
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 */
1790 } FDSA_info;
1792 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
1794 /*************************************************************************
1795 * @ [SHLWAPI.208]
1797 * Initialize an FDSA array.
1799 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
1800 DWORD init_blocks)
1802 TRACE("(0x%08lx 0x%08lx %p %p 0x%08lx)\n", block_size, inc, info, mem, init_blocks);
1804 if(inc == 0)
1805 inc = 1;
1807 if(mem)
1808 memset(mem, 0, block_size * init_blocks);
1810 info->num_items = 0;
1811 info->inc = inc;
1812 info->mem = mem;
1813 info->blocks_alloced = init_blocks;
1814 info->block_size = block_size;
1815 info->flags = 0;
1817 return TRUE;
1820 /*************************************************************************
1821 * @ [SHLWAPI.209]
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 free(info->mem);
1832 return FALSE;
1835 return TRUE;
1838 /*************************************************************************
1839 * @ [SHLWAPI.210]
1841 * Insert element into an FDSA array
1843 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
1845 TRACE("(%p 0x%08lx %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 = _recalloc(info->mem, 1, size);
1854 else
1856 void *old_mem = info->mem;
1857 info->mem = calloc(1, size);
1858 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
1860 info->blocks_alloced += info->inc;
1861 info->flags |= 0x1;
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);
1872 info->num_items++;
1873 return where;
1876 /*************************************************************************
1877 * @ [SHLWAPI.211]
1879 * Delete an element from an FDSA array.
1881 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
1883 TRACE("(%p 0x%08lx)\n", info, where);
1885 if(where >= info->num_items)
1886 return FALSE;
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);
1896 info->num_items--;
1897 return TRUE;
1899 /*************************************************************************
1900 * @ [SHLWAPI.220]
1902 * Set the Font for a window and the "PropDlgFont" property of the parent window.
1904 * PARAMS
1905 * hWnd [I] Parent Window to set the property
1906 * id [I] Index of child Window to set the Font
1908 * RETURNS
1909 * Success: S_OK
1912 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id)
1914 FIXME("(%p, %d) stub\n", hWnd, id);
1915 return S_OK;
1918 /*************************************************************************
1919 * @ [SHLWAPI.221]
1921 * Remove the "PropDlgFont" property from a window.
1923 * PARAMS
1924 * hWnd [I] Window to remove the property from
1926 * RETURNS
1927 * A handle to the removed property, or NULL if it did not exist.
1929 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
1931 HANDLE hProp;
1933 TRACE("(%p)\n", hWnd);
1935 hProp = GetPropA(hWnd, "PropDlgFont");
1937 if(hProp)
1939 DeleteObject(hProp);
1940 hProp = RemovePropA(hWnd, "PropDlgFont");
1942 return hProp;
1945 /*************************************************************************
1946 * @ [SHLWAPI.236]
1948 * Load the in-process server of a given GUID.
1950 * PARAMS
1951 * refiid [I] GUID of the server to load.
1953 * RETURNS
1954 * Success: A handle to the loaded server dll.
1955 * Failure: A NULL handle.
1957 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
1959 HKEY newkey;
1960 DWORD type, count;
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");
1967 count = MAX_PATH;
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 /*************************************************************************
1975 * @ [SHLWAPI.237]
1977 * Unicode version of SHLWAPI_183.
1979 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
1981 WNDCLASSW WndClass;
1983 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
1985 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
1986 return TRUE;
1987 return RegisterClassW(lpWndClass);
1990 /*************************************************************************
1991 * @ [SHLWAPI.238]
1993 * Unregister a list of classes.
1995 * PARAMS
1996 * hInst [I] Application instance that registered the classes
1997 * lppClasses [I] List of class names
1998 * iCount [I] Number of names in lppClasses
2000 * RETURNS
2001 * Nothing.
2003 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2005 WNDCLASSA WndClass;
2007 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2009 while (iCount > 0)
2011 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2012 UnregisterClassA(*lppClasses, hInst);
2013 lppClasses++;
2014 iCount--;
2018 /*************************************************************************
2019 * @ [SHLWAPI.239]
2021 * Unicode version of SHUnregisterClassesA.
2023 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2025 WNDCLASSW WndClass;
2027 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2029 while (iCount > 0)
2031 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2032 UnregisterClassW(*lppClasses, hInst);
2033 lppClasses++;
2034 iCount--;
2038 /*************************************************************************
2039 * @ [SHLWAPI.240]
2041 * Call The correct (ANSI/Unicode) default window procedure for a window.
2043 * PARAMS
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
2049 * RETURNS
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 /*************************************************************************
2060 * @ [SHLWAPI.257]
2062 * Create a worker window using CreateWindowExA().
2064 * PARAMS
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
2072 * RETURNS
2073 * Success: The window handle of the newly created window.
2074 * Failure: 0.
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";
2080 WNDCLASSA wc;
2081 HWND hWnd;
2083 TRACE("(%p, %p, 0x%08lx, 0x%08lx, %p, 0x%08Ix)\n",
2084 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
2086 /* Create Window class */
2087 wc.style = 0;
2088 wc.lpfnWndProc = DefWindowProcA;
2089 wc.cbClsExtra = 0;
2090 wc.cbWndExtra = sizeof(LONG_PTR);
2091 wc.hInstance = shlwapi_hInstance;
2092 wc.hIcon = NULL;
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);
2102 if (hWnd)
2104 SetWindowLongPtrW(hWnd, 0, wnd_extra);
2105 if (wndProc) SetWindowLongPtrA(hWnd, GWLP_WNDPROC, (LONG_PTR)wndProc);
2108 return hWnd;
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 /*************************************************************************
2127 * @ [SHLWAPI.271]
2129 * Retrieve a policy value from the registry.
2131 * PARAMS
2132 * lpSubKey [I] registry key name
2133 * lpSubName [I] subname of registry key
2134 * lpValue [I] value name of registry value
2136 * RETURNS
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);
2142 HKEY hKey;
2144 if (!lpSubKey)
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)
2151 return 0;
2153 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2154 RegCloseKey(hKey);
2155 return retval;
2158 /*************************************************************************
2159 * @ [SHLWAPI.266]
2161 * Helper function to retrieve the possibly cached value for a specific policy
2163 * PARAMS
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
2169 * RETURNS
2170 * The retrieved policy value or 0 if not successful
2172 * NOTES
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
2176 * that structure.
2178 DWORD WINAPI SHRestrictionLookup(
2179 DWORD policy,
2180 LPCWSTR initial,
2181 LPPOLICYDATA polTable,
2182 LPDWORD polArr)
2184 TRACE("(0x%08lx %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2186 if (!polTable || !polArr)
2187 return 0;
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);
2198 return *polArr;
2201 /* we don't know this policy, return 0 */
2202 TRACE("unknown policy: (%08lx)\n", policy);
2203 return 0;
2206 /*************************************************************************
2207 * @ [SHLWAPI.267]
2209 * Get an interface from an object.
2211 * RETURNS
2212 * Success: S_OK. ppv contains the requested interface.
2213 * Failure: An HRESULT error code.
2215 * NOTES
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);
2230 *ppv = NULL;
2231 if(pUnk && pInner) {
2232 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2233 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2235 TRACE("-- 0x%08lx\n", hret);
2236 return hret;
2239 /*************************************************************************
2240 * @ [SHLWAPI.268]
2242 * Move a reference from one interface to another.
2244 * PARAMS
2245 * lpDest [O] Destination to receive the reference
2246 * lppUnknown [O] Source to give up the reference to lpDest
2248 * RETURNS
2249 * Nothing.
2251 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2253 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2255 if (*lppUnknown)
2257 /* Copy Reference*/
2258 IUnknown_AddRef(lpDest);
2259 IUnknown_Release(*lppUnknown); /* Release existing interface */
2260 *lppUnknown = NULL;
2264 /*************************************************************************
2265 * @ [SHLWAPI.269]
2267 * Convert an ANSI string of a CLSID into a CLSID.
2269 * PARAMS
2270 * idstr [I] String representing a CLSID in registry format
2271 * id [O] Destination for the converted CLSID
2273 * RETURNS
2274 * Success: TRUE. id contains the converted CLSID.
2275 * Failure: FALSE.
2277 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2279 WCHAR wClsid[40];
2280 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, ARRAY_SIZE(wClsid));
2281 return SUCCEEDED(CLSIDFromString(wClsid, id));
2284 /*************************************************************************
2285 * @ [SHLWAPI.270]
2287 * Unicode version of GUIDFromStringA.
2289 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2291 return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id));
2294 /*************************************************************************
2295 * @ [SHLWAPI.278]
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 };
2303 WNDCLASSW wc;
2304 HWND hWnd;
2306 TRACE("(%p, %p, 0x%08lx, 0x%08lx, %p, 0x%08Ix)\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%08lx\n", GetVersion());
2313 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
2316 /* Create Window class */
2317 wc.style = 0;
2318 wc.lpfnWndProc = DefWindowProcW;
2319 wc.cbClsExtra = 0;
2320 wc.cbWndExtra = sizeof(LONG_PTR);
2321 wc.hInstance = shlwapi_hInstance;
2322 wc.hIcon = NULL;
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);
2332 if (hWnd)
2334 SetWindowLongPtrW(hWnd, 0, wnd_extra);
2335 if (wndProc) SetWindowLongPtrW(hWnd, GWLP_WNDPROC, (LONG_PTR)wndProc);
2338 return hWnd;
2341 /*************************************************************************
2342 * @ [SHLWAPI.279]
2344 * Get and show a context menu from a shell folder.
2346 * PARAMS
2347 * hWnd [I] Window displaying the shell folder
2348 * lpFolder [I] IShellFolder interface
2349 * lpApidl [I] Id for the particular folder desired
2351 * RETURNS
2352 * Success: S_OK.
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 /*************************************************************************
2362 * @ [SHLWAPI.281]
2364 * _SHPackDispParamsV
2366 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, va_list valist)
2368 VARIANTARG *iter;
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;
2377 iter = args+cnt;
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);
2386 } else {
2387 switch(V_VT(iter)) {
2388 case VT_I4:
2389 V_I4(iter) = va_arg(valist, LONG);
2390 break;
2391 case VT_BSTR:
2392 V_BSTR(iter) = va_arg(valist, BSTR);
2393 break;
2394 case VT_DISPATCH:
2395 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
2396 break;
2397 case VT_BOOL:
2398 V_BOOL(iter) = va_arg(valist, int);
2399 break;
2400 case VT_UNKNOWN:
2401 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
2402 break;
2403 default:
2404 V_VT(iter) = VT_I4;
2405 V_I4(iter) = va_arg(valist, LONG);
2410 return S_OK;
2413 /*************************************************************************
2414 * @ [SHLWAPI.282]
2416 * SHPackDispParams
2418 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...)
2420 va_list valist;
2421 HRESULT hres;
2423 va_start(valist, cnt);
2424 hres = SHPackDispParamsV(params, args, cnt, valist);
2425 va_end(valist);
2426 return hres;
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,
2438 REFIID iid,
2439 DISPID dispId,
2440 DISPPARAMS* dispParams)
2442 IEnumConnections *enumerator;
2443 CONNECTDATA rgcd;
2444 static DISPPARAMS empty = {NULL, NULL, 0, 0};
2445 DISPPARAMS* params = dispParams;
2447 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
2448 if (FAILED(result))
2449 return result;
2451 /* Invoke is never happening with an NULL dispParams */
2452 if (!params)
2453 params = &empty;
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);
2469 return S_OK;
2472 /*************************************************************************
2473 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
2475 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP,
2476 DISPID dispId, DISPPARAMS* dispParams,
2477 DWORD unknown1, DWORD unknown2 )
2479 IID iid;
2480 HRESULT result;
2482 FIXME("(%p)->(0x%lx %p %lx %lx) 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);
2487 else
2488 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
2490 return result;
2494 /*************************************************************************
2495 * @ [SHLWAPI.284]
2497 * IConnectionPoint_SimpleInvoke
2499 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
2500 IConnectionPoint* iCP,
2501 DISPID dispId,
2502 DISPPARAMS* dispParams)
2504 IID iid;
2505 HRESULT result;
2507 TRACE("(%p)->(0x%lx %p)\n",iCP,dispId,dispParams);
2509 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
2510 if (SUCCEEDED(result))
2511 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
2512 else
2513 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
2515 return result;
2518 /*************************************************************************
2519 * @ [SHLWAPI.285]
2521 * Notify an IConnectionPoint object of changes.
2523 * PARAMS
2524 * lpCP [I] Object to notify
2525 * dispID [I]
2527 * RETURNS
2528 * Success: S_OK.
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%8lX)\n", lpCP, dispID);
2539 /* Get an enumerator for the connections */
2540 if (lpCP)
2541 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
2543 if (SUCCEEDED(hRet))
2545 IPropertyNotifySink *lpSink;
2546 CONNECTDATA connData;
2547 ULONG ulFetched;
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)) &&
2553 lpSink)
2555 IPropertyNotifySink_OnChanged(lpSink, dispID);
2556 IPropertyNotifySink_Release(lpSink);
2558 IUnknown_Release(connData.pUnk);
2561 IEnumConnections_Release(lpEnum);
2563 return hRet;
2566 /*************************************************************************
2567 * @ [SHLWAPI.286]
2569 * IUnknown_CPContainerInvokeParam
2571 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
2572 IUnknown *container,
2573 REFIID riid,
2574 DISPID dispId,
2575 VARIANTARG* buffer,
2576 DWORD cParams, ...)
2578 HRESULT result;
2579 IConnectionPoint *iCP;
2580 IConnectionPointContainer *iCPC;
2581 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
2582 va_list valist;
2584 if (!container)
2585 return E_NOINTERFACE;
2587 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
2588 if (FAILED(result))
2589 return result;
2591 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
2592 IConnectionPointContainer_Release(iCPC);
2593 if(FAILED(result))
2594 return result;
2596 va_start(valist, cParams);
2597 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
2598 va_end(valist);
2600 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
2601 IConnectionPoint_Release(iCP);
2603 return result;
2606 /*************************************************************************
2607 * @ [SHLWAPI.287]
2609 * Notify an IConnectionPointContainer object of changes.
2611 * PARAMS
2612 * lpUnknown [I] Object to notify
2613 * dispID [I]
2615 * RETURNS
2616 * Success: S_OK.
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%8lX)\n", lpUnknown, dispID);
2627 if (lpUnknown)
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);
2640 return hRet;
2643 /*************************************************************************
2644 * @ [SHLWAPI.289]
2646 * See PlaySoundW.
2648 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
2650 return PlaySoundW(pszSound, hmod, fdwSound);
2653 /*************************************************************************
2654 * @ [SHLWAPI.294]
2656 * Retrieve a key value from an INI file. See GetPrivateProfileString for
2657 * more information.
2659 * PARAMS
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
2666 * RETURNS
2667 * Length of string copied into `out'.
2669 DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
2670 DWORD outLen, LPCWSTR filename)
2672 INT ret;
2673 WCHAR *buf;
2675 TRACE("(%s,%s,%p,%08lx,%s)\n", debugstr_w(appName), debugstr_w(keyName),
2676 out, outLen, debugstr_w(filename));
2678 if(outLen == 0)
2679 return 0;
2681 buf = malloc(outLen * sizeof(WCHAR));
2682 if(!buf){
2683 *out = 0;
2684 return 0;
2687 ret = GetPrivateProfileStringW(appName, keyName, NULL, buf, outLen, filename);
2688 if(ret)
2689 lstrcpyW(out, buf);
2690 else
2691 *out = 0;
2693 free(buf);
2695 return lstrlenW(out);
2698 /*************************************************************************
2699 * @ [SHLWAPI.295]
2701 * Set a key value in an INI file. See WritePrivateProfileString for
2702 * more information.
2704 * PARAMS
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
2710 * RETURNS
2711 * Success: TRUE
2712 * Failure: FALSE
2714 BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str,
2715 LPCWSTR filename)
2717 TRACE("(%s, %s, %s, %s)\n", debugstr_w(appName), debugstr_w(keyName), debugstr_w(str),
2718 debugstr_w(filename));
2720 return WritePrivateProfileStringW(appName, keyName, str, filename);
2723 /*************************************************************************
2724 * @ [SHLWAPI.313]
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 /*************************************************************************
2735 * @ [SHLWAPI.318]
2737 * See DragQueryFileW.
2739 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
2741 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
2744 /*************************************************************************
2745 * @ [SHLWAPI.333]
2747 * See SHBrowseForFolderW.
2749 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
2751 return SHBrowseForFolderW(lpBi);
2754 /*************************************************************************
2755 * @ [SHLWAPI.334]
2757 * See SHGetPathFromIDListW.
2759 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
2761 return SHGetPathFromIDListW(pidl, pszPath);
2764 /*************************************************************************
2765 * @ [SHLWAPI.335]
2767 * See ShellExecuteExW.
2769 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
2771 return ShellExecuteExW(lpExecInfo);
2774 /*************************************************************************
2775 * @ [SHLWAPI.336]
2777 * See SHFileOperationW.
2779 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
2781 return SHFileOperationW(lpFileOp);
2784 /*************************************************************************
2785 * @ [SHLWAPI.342]
2788 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
2790 return InterlockedCompareExchangePointer( dest, xchg, compare );
2793 /*************************************************************************
2794 * @ [SHLWAPI.350]
2796 * See GetFileVersionInfoSizeW.
2798 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
2800 return GetFileVersionInfoSizeW( filename, handle );
2803 /*************************************************************************
2804 * @ [SHLWAPI.351]
2806 * See GetFileVersionInfoW.
2808 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
2809 DWORD datasize, LPVOID data )
2811 return GetFileVersionInfoW( filename, handle, datasize, data );
2814 /*************************************************************************
2815 * @ [SHLWAPI.352]
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 /*************************************************************************
2830 * @ [SHLWAPI.355]
2832 * Change the modality of a shell object.
2834 * PARAMS
2835 * lpUnknown [I] Object to make modeless
2836 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
2838 * RETURNS
2839 * Success: S_OK. The modality lpUnknown is changed.
2840 * Failure: An HRESULT error code indicating the error.
2842 * NOTES
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)
2850 IUnknown *lpObj;
2851 HRESULT hRet;
2853 TRACE("(%p,%d)\n", lpUnknown, bModeless);
2855 if (!lpUnknown)
2856 return E_FAIL;
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);
2868 else
2869 return hRet;
2871 IUnknown_Release(lpObj);
2872 return S_OK;
2875 /*************************************************************************
2876 * @ [SHLWAPI.357]
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 /*************************************************************************
2887 * @ [SHLWAPI.358]
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 /*************************************************************************
2898 * @ [SHLWAPI.363]
2900 * Get and show a context menu from a shell folder.
2902 * PARAMS
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)
2908 * RETURNS
2909 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
2910 * executed.
2911 * Failure: An HRESULT error code indicating the error.
2913 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, DWORD dwCommandId)
2915 IContextMenu *iContext;
2916 HRESULT hRet;
2918 TRACE("(%p, %p, %p, %lu)\n", hWnd, lpFolder, lpApidl, dwCommandId);
2920 if (!lpFolder)
2921 return E_FAIL;
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))
2928 HMENU hMenu;
2929 if ((hMenu = CreatePopupMenu()))
2931 HRESULT hQuery;
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))
2939 if (!dwCommandId)
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;
2948 cmIci.hwnd = hWnd;
2949 cmIci.lpVerb = MAKEINTRESOURCEA(dwCommandId);
2950 cmIci.nShow = SW_SHOWNORMAL;
2952 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
2955 DestroyMenu(hMenu);
2957 IContextMenu_Release(iContext);
2959 return hRet;
2962 /*************************************************************************
2963 * @ [SHLWAPI.370]
2965 * See ExtractIconW.
2967 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
2968 UINT nIconIndex)
2970 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
2973 /*************************************************************************
2974 * @ [SHLWAPI.377]
2976 * Load a library from the directory of a particular process.
2978 * PARAMS
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)
2983 * RETURNS
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
2990 * each call here.
2991 * FIXME: Native shows calls to:
2992 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
2993 * CheckVersion
2994 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
2995 * RegQueryValueExA for "LPKInstalled"
2996 * RegCloseKey
2997 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
2998 * RegQueryValueExA for "ResourceLocale"
2999 * RegCloseKey
3000 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3001 * RegQueryValueExA for "Locale"
3002 * RegCloseKey
3003 * and then tests the Locale ("en" for me).
3004 * code below
3005 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3007 CHAR mod_path[2*MAX_PATH];
3008 LPSTR ptr;
3009 DWORD len;
3011 FIXME("(%s,%p,%ld) 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, '\\');
3016 if (ptr) {
3017 strcpy(ptr+1, new_mod);
3018 TRACE("loading %s\n", debugstr_a(mod_path));
3019 return LoadLibraryA(mod_path);
3021 return NULL;
3024 /*************************************************************************
3025 * @ [SHLWAPI.378]
3027 * Unicode version of MLLoadLibraryA.
3029 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3031 WCHAR mod_path[2*MAX_PATH];
3032 LPWSTR ptr;
3033 DWORD len;
3035 FIXME("(%s,%p,%ld) 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, '\\');
3040 if (ptr) {
3041 lstrcpyW(ptr+1, new_mod);
3042 TRACE("loading %s\n", debugstr_w(mod_path));
3043 return LoadLibraryW(mod_path);
3045 return NULL;
3048 /*************************************************************************
3049 * ColorAdjustLuma [SHLWAPI.@]
3051 * Adjust the luminosity of a color
3053 * PARAMS
3054 * cRGB [I] RGB value to convert
3055 * dwLuma [I] Luma adjustment
3056 * bUnknown [I] Unknown
3058 * RETURNS
3059 * The adjusted RGB color.
3061 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3063 TRACE("(0x%8lx,%d,%d)\n", cRGB, dwLuma, bUnknown);
3065 if (dwLuma)
3067 WORD wH, wL, wS;
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);
3077 return cRGB;
3080 /*************************************************************************
3081 * @ [SHLWAPI.389]
3083 * See GetSaveFileNameW.
3085 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3087 return GetSaveFileNameW(ofn);
3090 /*************************************************************************
3091 * @ [SHLWAPI.390]
3093 * See WNetRestoreConnectionW.
3095 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3097 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3100 /*************************************************************************
3101 * @ [SHLWAPI.391]
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 /*************************************************************************
3112 * @ [SHLWAPI.401]
3114 * See PageSetupDlgW.
3116 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3118 return PageSetupDlgW(pagedlg);
3121 /*************************************************************************
3122 * @ [SHLWAPI.402]
3124 * See PrintDlgW.
3126 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3128 return PrintDlgW(printdlg);
3131 /*************************************************************************
3132 * @ [SHLWAPI.403]
3134 * See GetOpenFileNameW.
3136 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3138 return GetOpenFileNameW(ofn);
3141 /*************************************************************************
3142 * @ [SHLWAPI.404]
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;
3166 if (wHue > 160)
3167 return wMid1;
3168 else if (wHue > 120)
3169 wHue = 160 - wHue;
3170 else if (wHue > 40)
3171 return wMid2;
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.
3184 * PARAMS
3185 * wHue [I] Hue amount
3186 * wLuminosity [I] Luminosity amount
3187 * wSaturation [I] Saturation amount
3189 * RETURNS
3190 * A COLORREF representing the converted color.
3192 * NOTES
3193 * Input hls values are constrained to the range (0..240).
3195 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3197 WORD wRed;
3199 if (wSaturation)
3201 WORD wGreen, wBlue, wMid1, wMid2;
3203 if (wLuminosity > 120)
3204 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3205 else
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 /*************************************************************************
3222 * @ [SHLWAPI.413]
3224 * Get the current docking status of the system.
3226 * PARAMS
3227 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3229 * RETURNS
3230 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3231 * a notebook.
3233 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3235 HW_PROFILE_INFOA hwInfo;
3237 TRACE("(0x%08lx)\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);
3245 default:
3246 return 0;
3250 /*************************************************************************
3251 * @ [SHLWAPI.416]
3254 DWORD WINAPI SHWinHelpOnDemandW(HWND hwnd, LPCWSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2)
3257 FIXME("(%p, %s, 0x%lx, %p, %ld)\n", hwnd, debugstr_w(helpfile), flags1, ptr1, flags2);
3258 return 0;
3261 /*************************************************************************
3262 * @ [SHLWAPI.417]
3265 DWORD WINAPI SHWinHelpOnDemandA(HWND hwnd, LPCSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2)
3268 FIXME("(%p, %s, 0x%lx, %p, %ld)\n", hwnd, debugstr_a(helpfile), flags1, ptr1, flags2);
3269 return 0;
3272 /*************************************************************************
3273 * @ [SHLWAPI.418]
3275 * Function seems to do FreeLibrary plus other things.
3277 * FIXME native shows the following calls:
3278 * RtlEnterCriticalSection
3279 * LocalFree
3280 * GetProcAddress(Comctl32??, 150L)
3281 * DPA_DeletePtr
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 /*************************************************************************
3293 * @ [SHLWAPI.419]
3295 BOOL WINAPI SHFlushSFCacheWrap(void) {
3296 FIXME(": stub\n");
3297 return TRUE;
3300 /*************************************************************************
3301 * @ [SHLWAPI.429]
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);
3307 return FALSE;
3311 /*************************************************************************
3312 * @ [SHLWAPI.430]
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 /*************************************************************************
3321 * @ [SHLWAPI.431]
3323 DWORD WINAPI MLClearMLHInstance(DWORD x)
3325 FIXME("(0x%08lx)stub\n", x);
3326 return 0xabba1247;
3329 /*************************************************************************
3330 * @ [SHLWAPI.432]
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 /*************************************************************************
3342 * @ [SHLWAPI.433]
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 /*************************************************************************
3354 * @ [SHLWAPI.436]
3356 * Convert a Unicode string CLSID into a CLSID.
3358 * PARAMS
3359 * idstr [I] string containing a CLSID in text form
3360 * id [O] CLSID extracted from the string
3362 * RETURNS
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 /*************************************************************************
3371 * @ [SHLWAPI.439]
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)
3378 return E_FAIL;
3380 return SHLoadIndirectString(buf, buf, size, NULL);
3383 /*************************************************************************
3384 * @ [SHLWAPI.478]
3386 * Call IInputObject_TranslateAcceleratorIO() on an object.
3388 * PARAMS
3389 * lpUnknown [I] Object supporting the IInputObject interface.
3390 * lpMsg [I] Key message to be processed.
3392 * RETURNS
3393 * Success: S_OK.
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);
3402 if (lpUnknown)
3404 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3405 (void**)&lpInput);
3406 if (SUCCEEDED(hRet) && lpInput)
3408 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
3409 IInputObject_Release(lpInput);
3412 return hRet;
3415 /*************************************************************************
3416 * @ [SHLWAPI.481]
3418 * Call IInputObject_HasFocusIO() on an object.
3420 * PARAMS
3421 * lpUnknown [I] Object supporting the IInputObject interface.
3423 * RETURNS
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);
3434 if (lpUnknown)
3436 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3437 (void**)&lpInput);
3438 if (SUCCEEDED(hRet) && lpInput)
3440 hRet = IInputObject_HasFocusIO(lpInput);
3441 IInputObject_Release(lpInput);
3444 return hRet;
3447 /*************************************************************************
3448 * ColorRGBToHLS [SHLWAPI.@]
3450 * Convert an rgb COLORREF into the hls color space.
3452 * PARAMS
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
3458 * RETURNS
3459 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
3460 * values.
3462 * NOTES
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("(%08lx,%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));
3480 /* Luminosity */
3481 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
3483 if (wMax == wMin)
3485 /* Achromatic case */
3486 wSaturation = 0;
3487 /* Hue is now unrepresentable, but this is what native returns... */
3488 wHue = 160;
3490 else
3492 /* Chromatic case */
3493 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
3495 /* Saturation */
3496 if (wLuminosity <= 120)
3497 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
3498 else
3499 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
3501 /* Hue */
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;
3506 if (wR == wMax)
3507 wHue = wBNorm - wGNorm;
3508 else if (wG == wMax)
3509 wHue = 80 + wRNorm - wBNorm;
3510 else
3511 wHue = 160 + wGNorm - wRNorm;
3512 if (wHue < 0)
3513 wHue += 240;
3514 else if (wHue > 240)
3515 wHue -= 240;
3517 if (pwHue)
3518 *pwHue = wHue;
3519 if (pwLuminance)
3520 *pwLuminance = wLuminosity;
3521 if (pwSaturation)
3522 *pwSaturation = wSaturation;
3525 /*************************************************************************
3526 * SHCreateShellPalette [SHLWAPI.@]
3528 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
3530 FIXME("stub\n");
3531 return CreateHalftonePalette(hdc);
3534 /*************************************************************************
3535 * SHGetInverseCMAP (SHLWAPI.@)
3537 * Get an inverse color map table.
3539 * PARAMS
3540 * lpCmap [O] Destination for color map
3541 * dwSize [I] Size of memory pointed to by lpCmap
3543 * RETURNS
3544 * Success: S_OK.
3545 * Failure: E_POINTER, If lpCmap is invalid.
3546 * E_INVALIDARG, If dwFlags is invalid
3547 * E_OUTOFMEMORY, If there is no memory available
3549 * NOTES
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
3552 * internal CMap.
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)
3558 if (dwSize == 4) {
3559 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
3560 *dest = (DWORD)0xabba1249;
3561 return 0;
3563 FIXME("(%p, %#lx) stub\n", dest, dwSize);
3564 return 0;
3567 /*************************************************************************
3568 * GetMenuPosFromID [SHLWAPI.@]
3570 * Return the position of a menu item from its Id.
3572 * PARAMS
3573 * hMenu [I] Menu containing the item
3574 * wID [I] Id of the menu item
3576 * RETURNS
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)
3582 MENUITEMINFOW mi;
3583 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
3585 TRACE("%p %u\n", hMenu, wID);
3587 while (nIter < nCount)
3589 mi.cbSize = sizeof(mi);
3590 mi.fMask = MIIM_ID;
3591 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
3593 TRACE("ret %d\n", nIter);
3594 return nIter;
3596 nIter++;
3599 return -1;
3602 /*************************************************************************
3603 * @ [SHLWAPI.179]
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 /*************************************************************************
3615 * @ [SHLWAPI.448]
3617 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
3619 while (*lpwstr)
3621 if (*lpwstr == '/')
3622 *lpwstr = '\\';
3623 lpwstr++;
3628 /*************************************************************************
3629 * @ [SHLWAPI.461]
3631 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
3633 FIXME("(0x%08lx) stub\n", dwUnknown);
3634 return 0;
3638 /*************************************************************************
3639 * @ [SHLWAPI.549]
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
3652 * PARAMS
3653 * pbc [I] Bind context to check
3654 * pclsid [I] CLSID of object to be bound to
3656 * RETURNS
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' };
3665 BOOL bRet = FALSE;
3667 if (pbc)
3669 IUnknown* lpUnk;
3671 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
3673 CLSID clsid;
3675 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
3676 IsEqualGUID(pclsid, &clsid))
3677 bRet = TRUE;
3679 IUnknown_Release(lpUnk);
3682 return bRet;
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','\\'};
3727 WCHAR *path;
3728 const WCHAR *key, *subkey;
3729 int size_key, size_subkey, size_user;
3730 HKEY hkey = NULL;
3732 TRACE("(0x%08lx, %s, %d)\n", flags, debugstr_w(sub_key), create);
3734 /* For compatibility with Vista+ */
3735 if(flags == 0x1ffff)
3736 flags = 0x21;
3738 switch(flags&0xff0) {
3739 case SHKEY_Key_Explorer:
3740 key = explorerW;
3741 size_key = sizeof(explorerW);
3742 break;
3743 case SHKEY_Key_Shell:
3744 key = shellW;
3745 size_key = sizeof(shellW);
3746 break;
3747 case SHKEY_Key_ShellNoRoam:
3748 key = shell_no_roamW;
3749 size_key = sizeof(shell_no_roamW);
3750 break;
3751 case SHKEY_Key_Classes:
3752 key = classesW;
3753 size_key = sizeof(classesW);
3754 break;
3755 default:
3756 FIXME("unsupported flags (0x%08lx)\n", flags);
3757 return NULL;
3760 switch(flags&0xff000) {
3761 case SHKEY_Subkey_Default:
3762 subkey = NULL;
3763 size_subkey = 0;
3764 break;
3765 case SHKEY_Subkey_ResourceName:
3766 subkey = localized_resource_nameW;
3767 size_subkey = sizeof(localized_resource_nameW);
3768 break;
3769 case SHKEY_Subkey_Handlers:
3770 subkey = handlersW;
3771 size_subkey = sizeof(handlersW);
3772 break;
3773 case SHKEY_Subkey_Associations:
3774 subkey = associationsW;
3775 size_subkey = sizeof(associationsW);
3776 break;
3777 case SHKEY_Subkey_Volatile:
3778 subkey = volatileW;
3779 size_subkey = sizeof(volatileW);
3780 break;
3781 case SHKEY_Subkey_MUICache:
3782 subkey = mui_cacheW;
3783 size_subkey = sizeof(mui_cacheW);
3784 break;
3785 case SHKEY_Subkey_FileExts:
3786 subkey = file_extsW;
3787 size_subkey = sizeof(file_extsW);
3788 break;
3789 default:
3790 FIXME("unsupported flags (0x%08lx)\n", flags);
3791 return NULL;
3794 if(sub_key)
3795 size_user = lstrlenW(sub_key)*sizeof(WCHAR);
3796 else
3797 size_user = 0;
3799 path = malloc(size_key + size_subkey + size_user + sizeof(WCHAR));
3800 if(!path) {
3801 ERR("Out of memory\n");
3802 return NULL;
3805 memcpy(path, key, size_key);
3806 if(subkey)
3807 memcpy(path+size_key/sizeof(WCHAR), subkey, size_subkey);
3808 if(sub_key)
3809 memcpy(path+(size_key+size_subkey)/sizeof(WCHAR), sub_key, size_user);
3810 path[(size_key+size_subkey+size_user)/sizeof(WCHAR)] = '\0';
3812 if(create)
3813 RegCreateKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
3814 path, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &hkey, NULL);
3815 else
3816 RegOpenKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
3817 path, 0, MAXIMUM_ALLOWED, &hkey);
3819 free(path);
3820 return hkey;
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, %ld, %Ix, %p, %s, %08lx)\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)
3846 HANDLE hNewTimer;
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))
3860 return NULL;
3862 return hNewTimer;
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");
3875 if (lpUnknown)
3877 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
3878 (void **)&pIOS);
3879 if (SUCCEEDED(hRet) && pIOS)
3881 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
3882 IInputObjectSite_Release(pIOS);
3885 return hRet;
3888 /***********************************************************************
3889 * SKAllocValueW (SHLWAPI.519)
3891 HRESULT WINAPI SKAllocValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type,
3892 LPVOID *data, DWORD *count)
3894 DWORD ret, size;
3895 HKEY hkey;
3897 TRACE("(0x%lx, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey),
3898 debugstr_w(value), type, data, count);
3900 hkey = SHGetShellKey(flags, subkey, FALSE);
3901 if (!hkey)
3902 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
3904 ret = SHQueryValueExW(hkey, value, NULL, type, NULL, &size);
3905 if (ret) {
3906 RegCloseKey(hkey);
3907 return HRESULT_FROM_WIN32(ret);
3910 size += 2;
3911 *data = LocalAlloc(0, size);
3912 if (!*data) {
3913 RegCloseKey(hkey);
3914 return E_OUTOFMEMORY;
3917 ret = SHQueryValueExW(hkey, value, NULL, type, *data, &size);
3918 if (count)
3919 *count = size;
3921 RegCloseKey(hkey);
3922 return HRESULT_FROM_WIN32(ret);
3925 /***********************************************************************
3926 * SKDeleteValueW (SHLWAPI.518)
3928 HRESULT WINAPI SKDeleteValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value)
3930 DWORD ret;
3931 HKEY hkey;
3933 TRACE("(0x%lx, %s %s)\n", flags, debugstr_w(subkey), debugstr_w(value));
3935 hkey = SHGetShellKey(flags, subkey, FALSE);
3936 if (!hkey)
3937 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
3939 ret = RegDeleteValueW(hkey, value);
3941 RegCloseKey(hkey);
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)
3951 DWORD ret;
3952 HKEY hkey;
3954 TRACE("(0x%lx, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey),
3955 debugstr_w(value), type, data, count);
3957 hkey = SHGetShellKey(flags, subkey, FALSE);
3958 if (!hkey)
3959 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
3961 ret = SHQueryValueExW(hkey, value, NULL, type, data, count);
3963 RegCloseKey(hkey);
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)
3973 DWORD ret;
3974 HKEY hkey;
3976 TRACE("(0x%lx, %s, %s, %lx, %p, %ld)\n", flags, debugstr_w(subkey),
3977 debugstr_w(value), type, data, count);
3979 hkey = SHGetShellKey(flags, subkey, TRUE);
3980 if (!hkey)
3981 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
3983 ret = RegSetValueExW(hkey, value, 0, type, data, count);
3985 RegCloseKey(hkey);
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;
3998 if (!version)
4000 DllGetVersion_func pDllGetVersion;
4001 HMODULE dll = LoadLibraryA("shell32.dll");
4002 if (!dll) return 0;
4004 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4005 if (pDllGetVersion)
4007 DLLVERSIONINFO dvi;
4008 dvi.cbSize = sizeof(DLLVERSIONINFO);
4009 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4011 FreeLibrary( dll );
4012 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4014 return version;
4017 /***********************************************************************
4018 * ShellMessageBoxWrapW [SHLWAPI.388]
4020 * See shell32.ShellMessageBoxW
4022 * NOTE:
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
4026 * shell32 as well.
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;
4033 LPWSTR pszTemp;
4034 va_list args;
4035 int ret;
4037 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));
4043 else
4044 pszTitle = lpCaption;
4046 if (IS_INTRESOURCE(lpText))
4048 const WCHAR *ptr;
4049 UINT len = LoadStringW(hInstance, LOWORD(lpText), (LPWSTR)&ptr, 0);
4051 if (len)
4053 szText = malloc((len + 1) * sizeof(WCHAR));
4054 if (szText) LoadStringW(hInstance, LOWORD(lpText), szText, len + 1);
4056 pszText = szText;
4057 if (!pszText) {
4058 WARN("Failed to load id %d\n", LOWORD(lpText));
4059 va_end(args);
4060 return 0;
4063 else
4064 pszText = lpText;
4066 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4067 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4069 va_end(args);
4071 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4073 free(szText);
4074 LocalFree(pszTemp);
4075 return ret;
4078 /***********************************************************************
4079 * ZoneComputePaneSize [SHLWAPI.382]
4081 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4083 FIXME("\n");
4084 return 0x95;
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;
4098 DWORD dwUserID;
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;
4103 DWORD dwAccessType;
4104 BOOL fInherit;
4105 DWORD dwAccessMask;
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
4115 * PARAMS
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
4120 * RETURNS
4121 * success: pointer to SECURITY_DESCRIPTOR
4122 * failure: NULL
4124 * NOTES
4125 * Call should free returned descriptor with LocalFree
4127 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(const PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4129 PSID *sidlist;
4130 PSID cur_user = NULL;
4131 BYTE tuUser[2000];
4132 DWORD acl_size;
4133 int sid_count, i;
4134 PSECURITY_DESCRIPTOR psd = NULL;
4136 TRACE("%p %d\n", apUserPerm, cUserPerm);
4138 if (apUserPerm == NULL || cUserPerm <= 0)
4139 return NULL;
4141 sidlist = malloc(cUserPerm * sizeof(PSID));
4142 if (!sidlist)
4143 return NULL;
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;
4152 PSID pSid;
4153 BOOL ret = TRUE;
4155 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4156 { /* current user's SID */
4157 if (!cur_user)
4159 HANDLE Token;
4160 DWORD bufsize = sizeof(tuUser);
4162 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4163 if (ret)
4165 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4166 if (ret)
4167 cur_user = ((PTOKEN_USER)tuUser)->User.Sid;
4168 CloseHandle(Token);
4171 pSid = cur_user;
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);
4175 else
4176 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4177 0, 0, 0, 0, 0, 0, &pSid);
4178 if (!ret)
4179 goto free_sids;
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);
4188 if (psd != NULL)
4190 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4192 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4193 goto error;
4195 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4196 goto error;
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))
4207 goto error;
4208 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4209 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4210 goto error;
4211 break;
4212 case ACCESS_DENIED_ACE_TYPE:
4213 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4214 goto error;
4215 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4216 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4217 goto error;
4218 break;
4219 default:
4220 goto error;
4224 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4225 goto error;
4227 goto free_sids;
4229 error:
4230 LocalFree(psd);
4231 psd = NULL;
4232 free_sids:
4233 for(i = 0; i < sid_count; i++)
4235 if (!cur_user || sidlist[i] != cur_user)
4236 FreeSid(sidlist[i]);
4238 free(sidlist);
4240 return psd;
4243 /***********************************************************************
4244 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4246 * Creates a property bag from a registry key
4248 * PARAMS
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
4255 * RETURNS
4256 * success: 0
4257 * failure: error code
4260 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey,
4261 DWORD grfMode, REFIID riid, void **ppv)
4263 FIXME("%p %s %ld %s %p STUB\n", hKey, debugstr_w(subkey), grfMode,
4264 debugstr_guid(riid), ppv);
4266 return E_NOTIMPL;
4269 /***********************************************************************
4270 * SHFormatDateTimeW [SHLWAPI.354]
4272 * Produces a string representation of a time.
4274 * PARAMS
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
4280 * RETURNS
4281 * success: number of characters written to the buffer
4282 * failure: 0
4285 INT WINAPI SHFormatDateTimeW(const FILETIME *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;
4290 SYSTEMTIME st;
4291 INT ret = 0;
4293 TRACE("%p %p %p %u\n", fileTime, flags, buf, size);
4295 if (!buf || !size)
4296 return 0;
4298 if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS)
4299 FIXME("ignoring some flags - 0x%08lx\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS);
4301 FileTimeToSystemTime(fileTime, &st);
4302 SystemTimeToTzSpecificLocalTime(NULL, &st, &st);
4304 /* first of all date */
4305 if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE))
4307 static const WCHAR sep1[] = {',',' ',0};
4308 static const WCHAR sep2[] = {' ',0};
4310 DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE;
4311 ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size);
4312 if (ret >= size) return ret;
4314 /* add separator */
4315 if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)))
4317 if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2))
4319 lstrcatW(&buf[ret-1], sep1);
4320 ret += 2;
4322 else
4324 lstrcatW(&buf[ret-1], sep2);
4325 ret++;
4329 /* time part */
4330 if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))
4332 DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS;
4334 if (ret) ret--;
4335 ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret);
4338 return ret;
4340 #undef SHFORMATDT_UNSUPPORTED_FLAGS
4343 /***********************************************************************
4344 * SHFormatDateTimeA [SHLWAPI.353]
4346 * See SHFormatDateTimeW.
4349 INT WINAPI SHFormatDateTimeA(const FILETIME *fileTime, DWORD *flags,
4350 LPSTR buf, UINT size)
4352 WCHAR *bufW;
4353 INT retval;
4355 if (!buf || !size)
4356 return 0;
4358 bufW = malloc(sizeof(WCHAR) * size);
4359 retval = SHFormatDateTimeW(fileTime, flags, bufW, size);
4361 if (retval != 0)
4362 retval = WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL);
4364 free(bufW);
4365 return retval;
4368 /***********************************************************************
4369 * ZoneCheckUrlExW [SHLWAPI.231]
4371 * Checks the details of the security zone for the supplied site. (?)
4373 * PARAMS
4375 * szURL [I] Pointer to the URL to check
4377 * Other parameters currently unknown.
4379 * RETURNS
4380 * unknown
4383 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2,
4384 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6,
4385 DWORD dwUnknown7)
4387 FIXME("(%s,%p,%lx,%lx,%lx,%lx,%lx,%lx) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2,
4388 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7);
4390 return 0;
4393 /***********************************************************************
4394 * SHVerbExistsNA [SHLWAPI.196]
4397 * PARAMS
4399 * verb [I] a string, often appears to be an extension.
4401 * Other parameters currently unknown.
4403 * RETURNS
4404 * unknown
4406 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3)
4408 FIXME("(%s, %p, %p, %li) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3);
4409 return 0;
4412 /*************************************************************************
4413 * @ [SHLWAPI.538]
4415 * Undocumented: Implementation guessed at via Name and behavior
4417 * PARAMS
4418 * lpUnknown [I] Object to get an IServiceProvider interface from
4419 * riid [I] Function requested for QueryService call
4420 * lppOut [O] Destination for the service interface pointer
4422 * RETURNS
4423 * Success: S_OK. lppOut contains an object providing the requested service
4424 * Failure: An HRESULT error code
4426 * NOTES
4427 * lpUnknown is expected to support the IServiceProvider interface.
4429 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown,
4430 REFGUID riid, LPVOID *lppOut)
4432 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut);
4433 return iunknown_query_service(lpUnknown,&IID_IWebBrowserApp,riid,lppOut);
4436 /**************************************************************************
4437 * SHPropertyBag_ReadLONG (SHLWAPI.496)
4439 * This function asks a property bag to read a named property as a LONG.
4441 * PARAMS
4442 * ppb: a IPropertyBag interface
4443 * pszPropName: Unicode string that names the property
4444 * pValue: address to receive the property value as a 32-bit signed integer
4446 * RETURNS
4447 * HRESULT codes
4449 HRESULT WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue)
4451 VARIANT var;
4452 HRESULT hr;
4453 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue);
4454 if (!pszPropName || !ppb || !pValue)
4455 return E_INVALIDARG;
4456 V_VT(&var) = VT_I4;
4457 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
4458 if (SUCCEEDED(hr))
4460 if (V_VT(&var) == VT_I4)
4461 *pValue = V_I4(&var);
4462 else
4463 hr = DISP_E_BADVARTYPE;
4465 return hr;
4468 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
4469 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
4470 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
4471 #define OBJCOMPAT_UNBINDABLE 0x00000004
4472 #define OBJCOMPAT_PINDLL 0x00000008
4473 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
4474 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
4475 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
4476 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
4477 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
4478 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
4479 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
4480 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
4481 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
4483 /* a search table for compatibility flags */
4484 struct objcompat_entry {
4485 const WCHAR name[30];
4486 DWORD value;
4489 /* expected to be sorted by name */
4490 static const struct objcompat_entry objcompat_table[] = {
4491 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
4492 OBJCOMPAT_COCREATESHELLFOLDERONLY },
4493 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
4494 OBJCOMPAT_CTXMENU_LIMITEDQI },
4495 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
4496 OBJCOMPAT_CTXMENU_LIMITEDQI },
4497 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
4498 OBJCOMPAT_CTXMENU_XPQCMFLAGS },
4499 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
4500 OBJCOMPAT_NEEDSFILESYSANCESTOR },
4501 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
4502 OBJCOMPAT_NEEDSSTORAGEANCESTOR },
4503 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
4504 OBJCOMPAT_NOIPROPERTYSTORE },
4505 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
4506 OBJCOMPAT_NOLEGACYWEBVIEW },
4507 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
4508 OBJCOMPAT_NOTAFILESYSTEM },
4509 { {'N','O','_','W','E','B','V','I','E','W',0},
4510 OBJCOMPAT_NO_WEBVIEW },
4511 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
4512 OBJCOMPAT_OTNEEDSSFCACHE },
4513 { {'P','I','N','D','L','L',0},
4514 OBJCOMPAT_PINDLL },
4515 { {'U','N','B','I','N','D','A','B','L','E',0},
4516 OBJCOMPAT_UNBINDABLE }
4519 /**************************************************************************
4520 * SHGetObjectCompatFlags (SHLWAPI.476)
4522 * Function returns an integer representation of compatibility flags stored
4523 * in registry for CLSID under ShellCompatibility subkey.
4525 * PARAMS
4526 * pUnk: pointer to object IUnknown interface, identifies CLSID
4527 * clsid: pointer to CLSID to retrieve data for
4529 * RETURNS
4530 * 0 on failure, flags set on success
4532 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid)
4534 static const WCHAR compatpathW[] =
4535 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4536 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4537 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
4538 'O','b','j','e','c','t','s','\\','%','s',0};
4539 WCHAR strW[ARRAY_SIZE(compatpathW) + 38 /* { CLSID } */];
4540 DWORD ret, length = ARRAY_SIZE(strW);
4541 OLECHAR *clsid_str;
4542 HKEY key;
4543 INT i;
4545 TRACE("%p %s\n", pUnk, debugstr_guid(clsid));
4547 if (!pUnk && !clsid) return 0;
4549 if (pUnk && !clsid)
4551 FIXME("iface not handled\n");
4552 return 0;
4555 StringFromCLSID(clsid, &clsid_str);
4556 swprintf(strW, ARRAY_SIZE(strW), compatpathW, clsid_str);
4557 CoTaskMemFree(clsid_str);
4559 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key);
4560 if (ret != ERROR_SUCCESS) return 0;
4562 /* now collect flag values */
4563 ret = 0;
4564 for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++)
4566 INT left, right, res, x;
4568 /* search in table */
4569 left = 0;
4570 right = ARRAY_SIZE(objcompat_table) - 1;
4572 while (right >= left) {
4573 x = (left + right) / 2;
4574 res = wcscmp(strW, objcompat_table[x].name);
4575 if (res == 0)
4577 ret |= objcompat_table[x].value;
4578 break;
4580 else if (res < 0)
4581 right = x - 1;
4582 else
4583 left = x + 1;
4586 length = ARRAY_SIZE(strW);
4589 return ret;