pop b0283e26815279d45d201d5585820bb1d1997663
[wine/hacks.git] / dlls / shlwapi / ordinal.c
blob364bbfe8af8fe3d9e0cd2b43a0675ab2a86fc711
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 "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
30 #define COBJMACROS
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winnls.h"
37 #include "winreg.h"
38 #include "wingdi.h"
39 #include "winuser.h"
40 #include "winver.h"
41 #include "winnetwk.h"
42 #include "mmsystem.h"
43 #include "objbase.h"
44 #include "exdisp.h"
45 #include "shlobj.h"
46 #include "shlwapi.h"
47 #include "shellapi.h"
48 #include "commdlg.h"
49 #include "mlang.h"
50 #include "mshtmhst.h"
51 #include "wine/unicode.h"
52 #include "wine/debug.h"
55 WINE_DEFAULT_DEBUG_CHANNEL(shell);
57 /* DLL handles for late bound calls */
58 extern HINSTANCE shlwapi_hInstance;
59 extern DWORD SHLWAPI_ThreadRef_index;
61 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
62 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
63 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
66 NOTES: Most functions exported by ordinal seem to be superfluous.
67 The reason for these functions to be there is to provide a wrapper
68 for unicode functions to provide these functions on systems without
69 unicode functions eg. win95/win98. Since we have such functions we just
70 call these. If running Wine with native DLLs, some late bound calls may
71 fail. However, it is better to implement the functions in the forward DLL
72 and recommend the builtin rather than reimplementing the calls here!
75 /*************************************************************************
76 * SHLWAPI_DupSharedHandle
78 * Internal implemetation of SHLWAPI_11.
80 static HANDLE SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
81 DWORD dwSrcProcId, DWORD dwAccess,
82 DWORD dwOptions)
84 HANDLE hDst, hSrc;
85 DWORD dwMyProcId = GetCurrentProcessId();
86 HANDLE hRet = NULL;
88 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
89 dwAccess, dwOptions);
91 /* Get dest process handle */
92 if (dwDstProcId == dwMyProcId)
93 hDst = GetCurrentProcess();
94 else
95 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
97 if (hDst)
99 /* Get src process handle */
100 if (dwSrcProcId == dwMyProcId)
101 hSrc = GetCurrentProcess();
102 else
103 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
105 if (hSrc)
107 /* Make handle available to dest process */
108 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
109 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
110 hRet = NULL;
112 if (dwSrcProcId != dwMyProcId)
113 CloseHandle(hSrc);
116 if (dwDstProcId != dwMyProcId)
117 CloseHandle(hDst);
120 TRACE("Returning handle %p\n", hRet);
121 return hRet;
124 /*************************************************************************
125 * @ [SHLWAPI.7]
127 * Create a block of sharable memory and initialise it with data.
129 * PARAMS
130 * lpvData [I] Pointer to data to write
131 * dwSize [I] Size of data
132 * dwProcId [I] ID of process owning data
134 * RETURNS
135 * Success: A shared memory handle
136 * Failure: NULL
138 * NOTES
139 * Ordinals 7-11 provide a set of calls to create shared memory between a
140 * group of processes. The shared memory is treated opaquely in that its size
141 * is not exposed to clients who map it. This is accomplished by storing
142 * the size of the map as the first DWORD of mapped data, and then offsetting
143 * the view pointer returned by this size.
146 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
148 HANDLE hMap;
149 LPVOID pMapped;
150 HANDLE hRet = NULL;
152 TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
154 /* Create file mapping of the correct length */
155 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
156 dwSize + sizeof(dwSize), NULL);
157 if (!hMap)
158 return hRet;
160 /* Get a view in our process address space */
161 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
163 if (pMapped)
165 /* Write size of data, followed by the data, to the view */
166 *((DWORD*)pMapped) = dwSize;
167 if (lpvData)
168 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
170 /* Release view. All further views mapped will be opaque */
171 UnmapViewOfFile(pMapped);
172 hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
173 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
174 DUPLICATE_SAME_ACCESS);
177 CloseHandle(hMap);
178 return hRet;
181 /*************************************************************************
182 * @ [SHLWAPI.8]
184 * Get a pointer to a block of shared memory from a shared memory handle.
186 * PARAMS
187 * hShared [I] Shared memory handle
188 * dwProcId [I] ID of process owning hShared
190 * RETURNS
191 * Success: A pointer to the shared memory
192 * Failure: NULL
195 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
197 HANDLE hDup;
198 LPVOID pMapped;
200 TRACE("(%p %d)\n", hShared, dwProcId);
202 /* Get handle to shared memory for current process */
203 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
204 FILE_MAP_ALL_ACCESS, 0);
205 /* Get View */
206 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
207 CloseHandle(hDup);
209 if (pMapped)
210 return (char *) pMapped + sizeof(DWORD); /* Hide size */
211 return NULL;
214 /*************************************************************************
215 * @ [SHLWAPI.9]
217 * Release a pointer to a block of shared memory.
219 * PARAMS
220 * lpView [I] Shared memory pointer
222 * RETURNS
223 * Success: TRUE
224 * Failure: FALSE
227 BOOL WINAPI SHUnlockShared(LPVOID lpView)
229 TRACE("(%p)\n", lpView);
230 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
233 /*************************************************************************
234 * @ [SHLWAPI.10]
236 * Destroy a block of sharable memory.
238 * PARAMS
239 * hShared [I] Shared memory handle
240 * dwProcId [I] ID of process owning hShared
242 * RETURNS
243 * Success: TRUE
244 * Failure: FALSE
247 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
249 HANDLE hClose;
251 TRACE("(%p %d)\n", hShared, dwProcId);
253 /* Get a copy of the handle for our process, closing the source handle */
254 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
255 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
256 /* Close local copy */
257 return CloseHandle(hClose);
260 /*************************************************************************
261 * @ [SHLWAPI.11]
263 * Copy a sharable memory handle from one process to another.
265 * PARAMS
266 * hShared [I] Shared memory handle to duplicate
267 * dwDstProcId [I] ID of the process wanting the duplicated handle
268 * dwSrcProcId [I] ID of the process owning hShared
269 * dwAccess [I] Desired DuplicateHandle() access
270 * dwOptions [I] Desired DuplicateHandle() options
272 * RETURNS
273 * Success: A handle suitable for use by the dwDstProcId process.
274 * Failure: A NULL handle.
277 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
278 DWORD dwAccess, DWORD dwOptions)
280 HANDLE hRet;
282 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
283 dwAccess, dwOptions);
284 return hRet;
287 /*************************************************************************
288 * @ [SHLWAPI.13]
290 * Create and register a clipboard enumerator for a web browser.
292 * PARAMS
293 * lpBC [I] Binding context
294 * lpUnknown [I] An object exposing the IWebBrowserApp interface
296 * RETURNS
297 * Success: S_OK.
298 * Failure: An HRESULT error code.
300 * NOTES
301 * The enumerator is stored as a property of the web browser. If it does not
302 * yet exist, it is created and set before being registered.
304 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
306 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
307 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
308 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
309 BSTR property;
310 IEnumFORMATETC* pIEnumFormatEtc = NULL;
311 VARIANTARG var;
312 HRESULT hRet;
313 IWebBrowserApp* pBrowser = NULL;
315 TRACE("(%p, %p)\n", lpBC, lpUnknown);
317 /* Get An IWebBrowserApp interface from lpUnknown */
318 hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
319 if (FAILED(hRet) || !pBrowser)
320 return E_NOINTERFACE;
322 V_VT(&var) = VT_EMPTY;
324 /* The property we get is the browsers clipboard enumerator */
325 property = SysAllocString(szProperty);
326 hRet = IWebBrowserApp_GetProperty(pBrowser, property, &var);
327 SysFreeString(property);
328 if (FAILED(hRet))
329 return hRet;
331 if (V_VT(&var) == VT_EMPTY)
333 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
334 char szKeyBuff[128], szValueBuff[128];
335 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
336 FORMATETC* formatList, *format;
337 HKEY hDocs;
339 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
341 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
342 "Version\\Internet Settings\\Accepted Documents", &hDocs))
343 return E_FAIL;
345 /* Get count of values in key */
346 while (!dwRet)
348 dwKeySize = sizeof(szKeyBuff);
349 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
350 dwCount++;
353 dwNumValues = dwCount;
355 /* Note: dwCount = number of items + 1; The extra item is the end node */
356 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
357 if (!formatList)
358 return E_OUTOFMEMORY;
360 if (dwNumValues > 1)
362 dwRet = 0;
363 dwCount = 0;
365 dwNumValues--;
367 /* Register clipboard formats for the values and populate format list */
368 while(!dwRet && dwCount < dwNumValues)
370 dwKeySize = sizeof(szKeyBuff);
371 dwValueSize = sizeof(szValueBuff);
372 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
373 (PBYTE)szValueBuff, &dwValueSize);
374 if (!dwRet)
375 return E_FAIL;
377 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
378 format->ptd = NULL;
379 format->dwAspect = 1;
380 format->lindex = 4;
381 format->tymed = -1;
383 format++;
384 dwCount++;
388 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
389 format->cfFormat = 0;
390 format->ptd = NULL;
391 format->dwAspect = 1;
392 format->lindex = 4;
393 format->tymed = -1;
395 /* Create a clipboard enumerator */
396 hRet = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
398 if (FAILED(hRet) || !pIEnumFormatEtc)
399 return hRet;
401 /* Set our enumerator as the browsers property */
402 V_VT(&var) = VT_UNKNOWN;
403 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
405 property = SysAllocString(szProperty);
406 hRet = IWebBrowserApp_PutProperty(pBrowser, property, var);
407 SysFreeString(property);
408 if (FAILED(hRet))
410 IEnumFORMATETC_Release(pIEnumFormatEtc);
411 goto RegisterDefaultAcceptHeaders_Exit;
415 if (V_VT(&var) == VT_UNKNOWN)
417 /* Our variant is holding the clipboard enumerator */
418 IUnknown* pIUnknown = V_UNKNOWN(&var);
419 IEnumFORMATETC* pClone = NULL;
421 TRACE("Retrieved IEnumFORMATETC property\n");
423 /* Get an IEnumFormatEtc interface from the variants value */
424 pIEnumFormatEtc = NULL;
425 hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
426 (PVOID)&pIEnumFormatEtc);
427 if (hRet == S_OK && pIEnumFormatEtc)
429 /* Clone and register the enumerator */
430 hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
431 if (hRet == S_OK && pClone)
433 RegisterFormatEnumerator(lpBC, pClone, 0);
435 IEnumFORMATETC_Release(pClone);
438 /* Release the IEnumFormatEtc interface */
439 IEnumFORMATETC_Release(pIUnknown);
441 IUnknown_Release(V_UNKNOWN(&var));
444 RegisterDefaultAcceptHeaders_Exit:
445 IWebBrowserApp_Release(pBrowser);
446 return hRet;
449 /*************************************************************************
450 * @ [SHLWAPI.15]
452 * Get Explorers "AcceptLanguage" setting.
454 * PARAMS
455 * langbuf [O] Destination for language string
456 * buflen [I] Length of langbuf in characters
457 * [0] Success: used length of langbuf
459 * RETURNS
460 * Success: S_OK. langbuf is set to the language string found.
461 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
462 * does not contain the setting.
463 * HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), If the buffer is not big enough
465 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
467 static const WCHAR szkeyW[] = {
468 'S','o','f','t','w','a','r','e','\\',
469 'M','i','c','r','o','s','o','f','t','\\',
470 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
471 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
472 static const WCHAR valueW[] = {
473 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
474 DWORD mystrlen, mytype;
475 DWORD len;
476 HKEY mykey;
477 HRESULT retval;
478 LCID mylcid;
479 WCHAR *mystr;
480 LONG lres;
482 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
484 if(!langbuf || !buflen || !*buflen)
485 return E_FAIL;
487 mystrlen = (*buflen > 20) ? *buflen : 20 ;
488 len = mystrlen * sizeof(WCHAR);
489 mystr = HeapAlloc(GetProcessHeap(), 0, len);
490 mystr[0] = 0;
491 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
492 lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
493 RegCloseKey(mykey);
494 len = lstrlenW(mystr);
496 if (!lres && (*buflen > len)) {
497 lstrcpyW(langbuf, mystr);
498 *buflen = len;
499 HeapFree(GetProcessHeap(), 0, mystr);
500 return S_OK;
503 /* Did not find a value in the registry or the user buffer is to small */
504 mylcid = GetUserDefaultLCID();
505 retval = LcidToRfc1766W(mylcid, mystr, mystrlen);
506 len = lstrlenW(mystr);
508 memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
509 HeapFree(GetProcessHeap(), 0, mystr);
511 if (*buflen > len) {
512 *buflen = len;
513 return S_OK;
516 *buflen = 0;
517 return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
520 /*************************************************************************
521 * @ [SHLWAPI.14]
523 * Ascii version of GetAcceptLanguagesW.
525 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
527 WCHAR *langbufW;
528 DWORD buflenW, convlen;
529 HRESULT retval;
531 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
533 if(!langbuf || !buflen || !*buflen) return E_FAIL;
535 buflenW = *buflen;
536 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
537 retval = GetAcceptLanguagesW(langbufW, &buflenW);
539 if (retval == S_OK)
541 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
542 convlen--; /* do not count the terminating 0 */
544 else /* copy partial string anyway */
546 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
547 if (convlen < *buflen)
549 langbuf[convlen] = 0;
550 convlen--; /* do not count the terminating 0 */
552 else
554 convlen = *buflen;
557 *buflen = buflenW ? convlen : 0;
559 HeapFree(GetProcessHeap(), 0, langbufW);
560 return retval;
563 /*************************************************************************
564 * @ [SHLWAPI.23]
566 * Convert a GUID to a string.
568 * PARAMS
569 * guid [I] GUID to convert
570 * lpszDest [O] Destination for string
571 * cchMax [I] Length of output buffer
573 * RETURNS
574 * The length of the string created.
576 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
578 char xguid[40];
579 INT iLen;
581 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
583 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
584 guid->Data1, guid->Data2, guid->Data3,
585 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
586 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
588 iLen = strlen(xguid) + 1;
590 if (iLen > cchMax)
591 return 0;
592 memcpy(lpszDest, xguid, iLen);
593 return iLen;
596 /*************************************************************************
597 * @ [SHLWAPI.24]
599 * Convert a GUID to a string.
601 * PARAMS
602 * guid [I] GUID to convert
603 * str [O] Destination for string
604 * cmax [I] Length of output buffer
606 * RETURNS
607 * The length of the string created.
609 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
611 WCHAR xguid[40];
612 INT iLen;
613 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
614 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
615 'X','%','0','2','X','%','0','2','X','}',0};
617 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
619 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
620 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
621 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
623 iLen = strlenW(xguid) + 1;
625 if (iLen > cchMax)
626 return 0;
627 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
628 return iLen;
631 /*************************************************************************
632 * @ [SHLWAPI.29]
634 * Determine if a Unicode character is a space.
636 * PARAMS
637 * wc [I] Character to check.
639 * RETURNS
640 * TRUE, if wc is a space,
641 * FALSE otherwise.
643 BOOL WINAPI IsCharSpaceW(WCHAR wc)
645 WORD CharType;
647 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
650 /*************************************************************************
651 * @ [SHLWAPI.30]
653 * Determine if a Unicode character is a blank.
655 * PARAMS
656 * wc [I] Character to check.
658 * RETURNS
659 * TRUE, if wc is a blank,
660 * FALSE otherwise.
663 BOOL WINAPI IsCharBlankW(WCHAR wc)
665 WORD CharType;
667 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
670 /*************************************************************************
671 * @ [SHLWAPI.31]
673 * Determine if a Unicode character is punctuation.
675 * PARAMS
676 * wc [I] Character to check.
678 * RETURNS
679 * TRUE, if wc is punctuation,
680 * FALSE otherwise.
682 BOOL WINAPI IsCharPunctW(WCHAR wc)
684 WORD CharType;
686 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
689 /*************************************************************************
690 * @ [SHLWAPI.32]
692 * Determine if a Unicode character is a control character.
694 * PARAMS
695 * wc [I] Character to check.
697 * RETURNS
698 * TRUE, if wc is a control character,
699 * FALSE otherwise.
701 BOOL WINAPI IsCharCntrlW(WCHAR wc)
703 WORD CharType;
705 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
708 /*************************************************************************
709 * @ [SHLWAPI.33]
711 * Determine if a Unicode character is a digit.
713 * PARAMS
714 * wc [I] Character to check.
716 * RETURNS
717 * TRUE, if wc is a digit,
718 * FALSE otherwise.
720 BOOL WINAPI IsCharDigitW(WCHAR wc)
722 WORD CharType;
724 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
727 /*************************************************************************
728 * @ [SHLWAPI.34]
730 * Determine if a Unicode character is a hex digit.
732 * PARAMS
733 * wc [I] Character to check.
735 * RETURNS
736 * TRUE, if wc is a hex digit,
737 * FALSE otherwise.
739 BOOL WINAPI IsCharXDigitW(WCHAR wc)
741 WORD CharType;
743 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
746 /*************************************************************************
747 * @ [SHLWAPI.35]
750 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type)
752 return GetStringTypeW(CT_CTYPE3, src, count, type);
755 /*************************************************************************
756 * @ [SHLWAPI.151]
758 * Compare two Ascii strings up to a given length.
760 * PARAMS
761 * lpszSrc [I] Source string
762 * lpszCmp [I] String to compare to lpszSrc
763 * len [I] Maximum length
765 * RETURNS
766 * A number greater than, less than or equal to 0 depending on whether
767 * lpszSrc is greater than, less than or equal to lpszCmp.
769 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
771 return StrCmpNA(lpszSrc, lpszCmp, len);
774 /*************************************************************************
775 * @ [SHLWAPI.152]
777 * Unicode version of StrCmpNCA.
779 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
781 return StrCmpNW(lpszSrc, lpszCmp, len);
784 /*************************************************************************
785 * @ [SHLWAPI.153]
787 * Compare two Ascii strings up to a given length, ignoring case.
789 * PARAMS
790 * lpszSrc [I] Source string
791 * lpszCmp [I] String to compare to lpszSrc
792 * len [I] Maximum length
794 * RETURNS
795 * A number greater than, less than or equal to 0 depending on whether
796 * lpszSrc is greater than, less than or equal to lpszCmp.
798 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
800 return StrCmpNIA(lpszSrc, lpszCmp, len);
803 /*************************************************************************
804 * @ [SHLWAPI.154]
806 * Unicode version of StrCmpNICA.
808 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
810 return StrCmpNIW(lpszSrc, lpszCmp, len);
813 /*************************************************************************
814 * @ [SHLWAPI.155]
816 * Compare two Ascii strings.
818 * PARAMS
819 * lpszSrc [I] Source string
820 * lpszCmp [I] String to compare to lpszSrc
822 * RETURNS
823 * A number greater than, less than or equal to 0 depending on whether
824 * lpszSrc is greater than, less than or equal to lpszCmp.
826 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
828 return lstrcmpA(lpszSrc, lpszCmp);
831 /*************************************************************************
832 * @ [SHLWAPI.156]
834 * Unicode version of StrCmpCA.
836 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
838 return lstrcmpW(lpszSrc, lpszCmp);
841 /*************************************************************************
842 * @ [SHLWAPI.157]
844 * Compare two Ascii strings, ignoring case.
846 * PARAMS
847 * lpszSrc [I] Source string
848 * lpszCmp [I] String to compare to lpszSrc
850 * RETURNS
851 * A number greater than, less than or equal to 0 depending on whether
852 * lpszSrc is greater than, less than or equal to lpszCmp.
854 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
856 return lstrcmpiA(lpszSrc, lpszCmp);
859 /*************************************************************************
860 * @ [SHLWAPI.158]
862 * Unicode version of StrCmpICA.
864 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
866 return lstrcmpiW(lpszSrc, lpszCmp);
869 /*************************************************************************
870 * @ [SHLWAPI.160]
872 * Get an identification string for the OS and explorer.
874 * PARAMS
875 * lpszDest [O] Destination for Id string
876 * dwDestLen [I] Length of lpszDest
878 * RETURNS
879 * TRUE, If the string was created successfully
880 * FALSE, Otherwise
882 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
884 WCHAR buff[2084];
886 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
888 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
890 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
891 return TRUE;
893 return FALSE;
896 /*************************************************************************
897 * @ [SHLWAPI.161]
899 * Unicode version of SHAboutInfoA.
901 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
903 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
904 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
905 ' ','E','x','p','l','o','r','e','r','\0' };
906 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
907 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
908 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
909 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
910 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
911 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
912 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
913 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
914 ' ','E','x','p','l','o','r','e','r','\\',
915 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
916 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
917 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
918 'V','e','r','s','i','o','n','\0' };
919 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
920 'O','w','n','e','r','\0' };
921 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
922 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
923 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
924 static const WCHAR szUpdate[] = { 'I','E','A','K',
925 'U','p','d','a','t','e','U','r','l','\0' };
926 static const WCHAR szHelp[] = { 'I','E','A','K',
927 'H','e','l','p','S','t','r','i','n','g','\0' };
928 WCHAR buff[2084];
929 HKEY hReg;
930 DWORD dwType, dwLen;
932 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
934 if (!lpszDest)
935 return FALSE;
937 *lpszDest = '\0';
939 /* Try the NT key first, followed by 95/98 key */
940 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
941 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
942 return FALSE;
944 /* OS Version */
945 buff[0] = '\0';
946 dwLen = 30;
947 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
949 DWORD dwStrLen = strlenW(buff);
950 dwLen = 30 - dwStrLen;
951 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
952 szCustomized, &dwType, buff+dwStrLen, &dwLen);
954 StrCatBuffW(lpszDest, buff, dwDestLen);
956 /* ~Registered Owner */
957 buff[0] = '~';
958 dwLen = 256;
959 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
960 buff[1] = '\0';
961 StrCatBuffW(lpszDest, buff, dwDestLen);
963 /* ~Registered Organization */
964 dwLen = 256;
965 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
966 buff[1] = '\0';
967 StrCatBuffW(lpszDest, buff, dwDestLen);
969 /* FIXME: Not sure where this number comes from */
970 buff[0] = '~';
971 buff[1] = '0';
972 buff[2] = '\0';
973 StrCatBuffW(lpszDest, buff, dwDestLen);
975 /* ~Product Id */
976 dwLen = 256;
977 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
978 buff[1] = '\0';
979 StrCatBuffW(lpszDest, buff, dwDestLen);
981 /* ~IE Update Url */
982 dwLen = 2048;
983 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
984 buff[1] = '\0';
985 StrCatBuffW(lpszDest, buff, dwDestLen);
987 /* ~IE Help String */
988 dwLen = 256;
989 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
990 buff[1] = '\0';
991 StrCatBuffW(lpszDest, buff, dwDestLen);
993 RegCloseKey(hReg);
994 return TRUE;
997 /*************************************************************************
998 * @ [SHLWAPI.163]
1000 * Call IOleCommandTarget_QueryStatus() on an object.
1002 * PARAMS
1003 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1004 * pguidCmdGroup [I] GUID for the command group
1005 * cCmds [I]
1006 * prgCmds [O] Commands
1007 * pCmdText [O] Command text
1009 * RETURNS
1010 * Success: S_OK.
1011 * Failure: E_FAIL, if lpUnknown is NULL.
1012 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1013 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1015 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1016 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1018 HRESULT hRet = E_FAIL;
1020 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1022 if (lpUnknown)
1024 IOleCommandTarget* lpOle;
1026 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1027 (void**)&lpOle);
1029 if (SUCCEEDED(hRet) && lpOle)
1031 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1032 prgCmds, pCmdText);
1033 IOleCommandTarget_Release(lpOle);
1036 return hRet;
1039 /*************************************************************************
1040 * @ [SHLWAPI.164]
1042 * Call IOleCommandTarget_Exec() on an object.
1044 * PARAMS
1045 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1046 * pguidCmdGroup [I] GUID for the command group
1048 * RETURNS
1049 * Success: S_OK.
1050 * Failure: E_FAIL, if lpUnknown is NULL.
1051 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1052 * Otherwise, an error code from IOleCommandTarget_Exec().
1054 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1055 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1056 VARIANT* pvaOut)
1058 HRESULT hRet = E_FAIL;
1060 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1061 nCmdexecopt, pvaIn, pvaOut);
1063 if (lpUnknown)
1065 IOleCommandTarget* lpOle;
1067 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1068 (void**)&lpOle);
1069 if (SUCCEEDED(hRet) && lpOle)
1071 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1072 nCmdexecopt, pvaIn, pvaOut);
1073 IOleCommandTarget_Release(lpOle);
1076 return hRet;
1079 /*************************************************************************
1080 * @ [SHLWAPI.165]
1082 * Retrieve, modify, and re-set a value from a window.
1084 * PARAMS
1085 * hWnd [I] Window to get value from
1086 * offset [I] Offset of value
1087 * mask [I] Mask for flags
1088 * flags [I] Bits to set in window value
1090 * RETURNS
1091 * The new value as it was set, or 0 if any parameter is invalid.
1093 * NOTES
1094 * Only bits specified in mask are affected - set if present in flags and
1095 * reset otherwise.
1097 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT mask, UINT flags)
1099 LONG ret = GetWindowLongW(hwnd, offset);
1100 LONG new_flags = (flags & mask) | (ret & ~mask);
1102 TRACE("%p %d %x %x\n", hwnd, offset, mask, flags);
1104 if (new_flags != ret)
1105 ret = SetWindowLongW(hwnd, offset, new_flags);
1106 return ret;
1109 /*************************************************************************
1110 * @ [SHLWAPI.167]
1112 * Change a window's parent.
1114 * PARAMS
1115 * hWnd [I] Window to change parent of
1116 * hWndParent [I] New parent window
1118 * RETURNS
1119 * The old parent of hWnd.
1121 * NOTES
1122 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1123 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1125 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1127 TRACE("%p, %p\n", hWnd, hWndParent);
1129 if(GetParent(hWnd) == hWndParent)
1130 return 0;
1132 if(hWndParent)
1133 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1134 else
1135 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1137 return SetParent(hWnd, hWndParent);
1140 /*************************************************************************
1141 * @ [SHLWAPI.168]
1143 * Locate and advise a connection point in an IConnectionPointContainer object.
1145 * PARAMS
1146 * lpUnkSink [I] Sink for the connection point advise call
1147 * riid [I] REFIID of connection point to advise
1148 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1149 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1150 * lpCookie [O] Pointer to connection point cookie
1151 * lppCP [O] Destination for the IConnectionPoint found
1153 * RETURNS
1154 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1155 * that was advised. The caller is responsible for releasing it.
1156 * Failure: E_FAIL, if any arguments are invalid.
1157 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1158 * Or an HRESULT error code if any call fails.
1160 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL fConnect,
1161 IUnknown* lpUnknown, LPDWORD lpCookie,
1162 IConnectionPoint **lppCP)
1164 HRESULT hRet;
1165 IConnectionPointContainer* lpContainer;
1166 IConnectionPoint *lpCP;
1168 if(!lpUnknown || (fConnect && !lpUnkSink))
1169 return E_FAIL;
1171 if(lppCP)
1172 *lppCP = NULL;
1174 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1175 (void**)&lpContainer);
1176 if (SUCCEEDED(hRet))
1178 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1180 if (SUCCEEDED(hRet))
1182 if(!fConnect)
1183 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1184 else
1185 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1187 if (FAILED(hRet))
1188 *lpCookie = 0;
1190 if (lppCP && SUCCEEDED(hRet))
1191 *lppCP = lpCP; /* Caller keeps the interface */
1192 else
1193 IConnectionPoint_Release(lpCP); /* Release it */
1196 IUnknown_Release(lpContainer);
1198 return hRet;
1201 /*************************************************************************
1202 * @ [SHLWAPI.169]
1204 * Release an interface.
1206 * PARAMS
1207 * lpUnknown [I] Object to release
1209 * RETURNS
1210 * Nothing.
1212 DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1214 IUnknown *temp;
1216 TRACE("(%p)\n",lpUnknown);
1218 if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1219 temp = *lpUnknown;
1220 *lpUnknown = NULL;
1222 TRACE("doing Release\n");
1224 return IUnknown_Release(temp);
1227 /*************************************************************************
1228 * @ [SHLWAPI.170]
1230 * Skip '//' if present in a string.
1232 * PARAMS
1233 * lpszSrc [I] String to check for '//'
1235 * RETURNS
1236 * Success: The next character after the '//' or the string if not present
1237 * Failure: NULL, if lpszStr is NULL.
1239 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1241 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1242 lpszSrc += 2;
1243 return lpszSrc;
1246 /*************************************************************************
1247 * @ [SHLWAPI.171]
1249 * Check if two interfaces come from the same object.
1251 * PARAMS
1252 * lpInt1 [I] Interface to check against lpInt2.
1253 * lpInt2 [I] Interface to check against lpInt1.
1255 * RETURNS
1256 * TRUE, If the interfaces come from the same object.
1257 * FALSE Otherwise.
1259 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1261 LPVOID lpUnknown1, lpUnknown2;
1263 TRACE("%p %p\n", lpInt1, lpInt2);
1265 if (!lpInt1 || !lpInt2)
1266 return FALSE;
1268 if (lpInt1 == lpInt2)
1269 return TRUE;
1271 if (FAILED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown, &lpUnknown1)))
1272 return FALSE;
1274 if (FAILED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown, &lpUnknown2)))
1275 return FALSE;
1277 if (lpUnknown1 == lpUnknown2)
1278 return TRUE;
1280 return FALSE;
1283 /*************************************************************************
1284 * @ [SHLWAPI.172]
1286 * Get the window handle of an object.
1288 * PARAMS
1289 * lpUnknown [I] Object to get the window handle of
1290 * lphWnd [O] Destination for window handle
1292 * RETURNS
1293 * Success: S_OK. lphWnd contains the objects window handle.
1294 * Failure: An HRESULT error code.
1296 * NOTES
1297 * lpUnknown is expected to support one of the following interfaces:
1298 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1300 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1302 IUnknown *lpOle;
1303 HRESULT hRet = E_FAIL;
1305 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1307 if (!lpUnknown)
1308 return hRet;
1310 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1312 if (FAILED(hRet))
1314 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1316 if (FAILED(hRet))
1318 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1319 (void**)&lpOle);
1323 if (SUCCEEDED(hRet))
1325 /* Lazyness here - Since GetWindow() is the first method for the above 3
1326 * interfaces, we use the same call for them all.
1328 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1329 IUnknown_Release(lpOle);
1330 if (lphWnd)
1331 TRACE("Returning HWND=%p\n", *lphWnd);
1334 return hRet;
1337 /*************************************************************************
1338 * @ [SHLWAPI.173]
1340 * Call a method on as as yet unidentified object.
1342 * PARAMS
1343 * pUnk [I] Object supporting the unidentified interface,
1344 * arg [I] Argument for the call on the object.
1346 * RETURNS
1347 * S_OK.
1349 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1351 static const GUID guid_173 = {
1352 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1354 IMalloc *pUnk2;
1356 TRACE("(%p,%d)\n", pUnk, arg);
1358 /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1359 * We use this interface as its vtable entry is compatible with the
1360 * object in question.
1361 * FIXME: Find out what this object is and where it should be defined.
1363 if (pUnk &&
1364 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1366 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1367 IMalloc_Release(pUnk2);
1369 return S_OK;
1372 /*************************************************************************
1373 * @ [SHLWAPI.174]
1375 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1376 * an object.
1379 HRESULT WINAPI IUnknown_SetSite(
1380 IUnknown *obj, /* [in] OLE object */
1381 IUnknown *site) /* [in] Site interface */
1383 HRESULT hr;
1384 IObjectWithSite *iobjwithsite;
1385 IInternetSecurityManager *isecmgr;
1387 if (!obj) return E_FAIL;
1389 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1390 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1391 if (SUCCEEDED(hr))
1393 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1394 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1395 IUnknown_Release(iobjwithsite);
1397 else
1399 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1400 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1401 if (FAILED(hr)) return hr;
1403 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1404 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1405 IUnknown_Release(isecmgr);
1407 return hr;
1410 /*************************************************************************
1411 * @ [SHLWAPI.175]
1413 * Call IPersist_GetClassID() on an object.
1415 * PARAMS
1416 * lpUnknown [I] Object supporting the IPersist interface
1417 * lpClassId [O] Destination for Class Id
1419 * RETURNS
1420 * Success: S_OK. lpClassId contains the Class Id requested.
1421 * Failure: E_FAIL, If lpUnknown is NULL,
1422 * E_NOINTERFACE If lpUnknown does not support IPersist,
1423 * Or an HRESULT error code.
1425 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1427 IPersist* lpPersist;
1428 HRESULT hRet = E_FAIL;
1430 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1432 if (lpUnknown)
1434 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1435 if (SUCCEEDED(hRet))
1437 IPersist_GetClassID(lpPersist, lpClassId);
1438 IPersist_Release(lpPersist);
1441 return hRet;
1444 /*************************************************************************
1445 * @ [SHLWAPI.176]
1447 * Retrieve a Service Interface from an object.
1449 * PARAMS
1450 * lpUnknown [I] Object to get an IServiceProvider interface from
1451 * sid [I] Service ID for IServiceProvider_QueryService() call
1452 * riid [I] Function requested for QueryService call
1453 * lppOut [O] Destination for the service interface pointer
1455 * RETURNS
1456 * Success: S_OK. lppOut contains an object providing the requested service
1457 * Failure: An HRESULT error code
1459 * NOTES
1460 * lpUnknown is expected to support the IServiceProvider interface.
1462 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1463 LPVOID *lppOut)
1465 IServiceProvider* pService = NULL;
1466 HRESULT hRet;
1468 if (!lppOut)
1469 return E_FAIL;
1471 *lppOut = NULL;
1473 if (!lpUnknown)
1474 return E_FAIL;
1476 /* Get an IServiceProvider interface from the object */
1477 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1478 (LPVOID*)&pService);
1480 if (hRet == S_OK && pService)
1482 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1484 /* Get a Service interface from the object */
1485 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1487 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1489 /* Release the IServiceProvider interface */
1490 IUnknown_Release(pService);
1492 return hRet;
1495 /*************************************************************************
1496 * @ [SHLWAPI.479]
1498 * Call an object's UIActivateIO method.
1500 * PARAMS
1501 * unknown [I] Object to call the UIActivateIO method on
1502 * activate [I] Parameter for UIActivateIO call
1503 * msg [I] Parameter for UIActivateIO call
1505 * RETURNS
1506 * Success: Value of UI_ActivateIO call
1507 * Failure: An HRESULT error code
1509 * NOTES
1510 * unknown is expected to support the IInputObject interface.
1512 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg)
1514 IInputObject* object = NULL;
1515 HRESULT ret;
1517 if (!unknown)
1518 return E_FAIL;
1520 /* Get an IInputObject interface from the object */
1521 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
1523 if (ret == S_OK)
1525 ret = IInputObject_UIActivateIO(object, activate, msg);
1526 IUnknown_Release(object);
1529 return ret;
1532 /*************************************************************************
1533 * @ [SHLWAPI.177]
1535 * Loads a popup menu.
1537 * PARAMS
1538 * hInst [I] Instance handle
1539 * szName [I] Menu name
1541 * RETURNS
1542 * Success: TRUE.
1543 * Failure: FALSE.
1545 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1547 HMENU hMenu;
1549 if ((hMenu = LoadMenuW(hInst, szName)))
1551 if (GetSubMenu(hMenu, 0))
1552 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1554 DestroyMenu(hMenu);
1555 return TRUE;
1557 return FALSE;
1560 typedef struct _enumWndData
1562 UINT uiMsgId;
1563 WPARAM wParam;
1564 LPARAM lParam;
1565 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1566 } enumWndData;
1568 /* Callback for SHLWAPI_178 */
1569 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1571 enumWndData *data = (enumWndData *)lParam;
1573 TRACE("(%p,%p)\n", hWnd, data);
1574 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1575 return TRUE;
1578 /*************************************************************************
1579 * @ [SHLWAPI.178]
1581 * Send or post a message to every child of a window.
1583 * PARAMS
1584 * hWnd [I] Window whose children will get the messages
1585 * uiMsgId [I] Message Id
1586 * wParam [I] WPARAM of message
1587 * lParam [I] LPARAM of message
1588 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1590 * RETURNS
1591 * Nothing.
1593 * NOTES
1594 * The appropriate ASCII or Unicode function is called for the window.
1596 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1598 enumWndData data;
1600 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1602 if(hWnd)
1604 data.uiMsgId = uiMsgId;
1605 data.wParam = wParam;
1606 data.lParam = lParam;
1608 if (bSend)
1609 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1610 else
1611 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1613 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1617 /*************************************************************************
1618 * @ [SHLWAPI.180]
1620 * Remove all sub-menus from a menu.
1622 * PARAMS
1623 * hMenu [I] Menu to remove sub-menus from
1625 * RETURNS
1626 * Success: 0. All sub-menus under hMenu are removed
1627 * Failure: -1, if any parameter is invalid
1629 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1631 int iItemCount = GetMenuItemCount(hMenu) - 1;
1632 while (iItemCount >= 0)
1634 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1635 if (hSubMenu)
1636 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1637 iItemCount--;
1639 return iItemCount;
1642 /*************************************************************************
1643 * @ [SHLWAPI.181]
1645 * Enable or disable a menu item.
1647 * PARAMS
1648 * hMenu [I] Menu holding menu item
1649 * uID [I] ID of menu item to enable/disable
1650 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1652 * RETURNS
1653 * The return code from EnableMenuItem.
1655 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1657 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1660 /*************************************************************************
1661 * @ [SHLWAPI.182]
1663 * Check or uncheck a menu item.
1665 * PARAMS
1666 * hMenu [I] Menu holding menu item
1667 * uID [I] ID of menu item to check/uncheck
1668 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1670 * RETURNS
1671 * The return code from CheckMenuItem.
1673 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1675 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1678 /*************************************************************************
1679 * @ [SHLWAPI.183]
1681 * Register a window class if it isn't already.
1683 * PARAMS
1684 * lpWndClass [I] Window class to register
1686 * RETURNS
1687 * The result of the RegisterClassA call.
1689 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1691 WNDCLASSA wca;
1692 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1693 return TRUE;
1694 return (DWORD)RegisterClassA(wndclass);
1697 /*************************************************************************
1698 * @ [SHLWAPI.186]
1700 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1701 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1703 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1704 POINTL pt = { 0, 0 };
1706 if (!lpPt)
1707 lpPt = &pt;
1709 if (!pdwEffect)
1710 pdwEffect = &dwEffect;
1712 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1714 if (*pdwEffect)
1715 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1717 IDropTarget_DragLeave(pDrop);
1718 return TRUE;
1721 /*************************************************************************
1722 * @ [SHLWAPI.187]
1724 * Call IPersistPropertyBag_Load() on an object.
1726 * PARAMS
1727 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1728 * lpPropBag [O] Destination for loaded IPropertyBag
1730 * RETURNS
1731 * Success: S_OK.
1732 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1734 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1736 IPersistPropertyBag* lpPPBag;
1737 HRESULT hRet = E_FAIL;
1739 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1741 if (lpUnknown)
1743 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1744 (void**)&lpPPBag);
1745 if (SUCCEEDED(hRet) && lpPPBag)
1747 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1748 IPersistPropertyBag_Release(lpPPBag);
1751 return hRet;
1754 /*************************************************************************
1755 * @ [SHLWAPI.188]
1757 * Call IOleControlSite_TranslateAccelerator() on an object.
1759 * PARAMS
1760 * lpUnknown [I] Object supporting the IOleControlSite interface.
1761 * lpMsg [I] Key message to be processed.
1762 * dwModifiers [I] Flags containing the state of the modifier keys.
1764 * RETURNS
1765 * Success: S_OK.
1766 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1768 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1770 IOleControlSite* lpCSite = NULL;
1771 HRESULT hRet = E_INVALIDARG;
1773 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1774 if (lpUnknown)
1776 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1777 (void**)&lpCSite);
1778 if (SUCCEEDED(hRet) && lpCSite)
1780 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1781 IOleControlSite_Release(lpCSite);
1784 return hRet;
1788 /*************************************************************************
1789 * @ [SHLWAPI.189]
1791 * Call IOleControlSite_OnFocus() on an object.
1793 * PARAMS
1794 * lpUnknown [I] Object supporting the IOleControlSite interface.
1795 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1797 * RETURNS
1798 * Success: S_OK.
1799 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1801 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
1803 IOleControlSite* lpCSite = NULL;
1804 HRESULT hRet = E_FAIL;
1806 TRACE("(%p,%s)\n", lpUnknown, fGotFocus ? "TRUE" : "FALSE");
1807 if (lpUnknown)
1809 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1810 (void**)&lpCSite);
1811 if (SUCCEEDED(hRet) && lpCSite)
1813 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1814 IOleControlSite_Release(lpCSite);
1817 return hRet;
1820 /*************************************************************************
1821 * @ [SHLWAPI.190]
1823 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1824 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1826 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1827 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1828 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1829 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1830 HRESULT hRet = E_INVALIDARG;
1831 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1833 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1835 if (lpUnknown && lpArg4)
1837 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1838 (REFGUID)function_id, (void**)&lpUnkInner);
1840 if (SUCCEEDED(hRet) && lpUnkInner)
1842 /* FIXME: The type of service object requested is unknown, however
1843 * testing shows that its first method is called with 4 parameters.
1844 * Fake this by using IParseDisplayName_ParseDisplayName since the
1845 * signature and position in the vtable matches our unknown object type.
1847 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1848 lpArg1, lpArg2, lpArg3, lpArg4);
1849 IUnknown_Release(lpUnkInner);
1852 return hRet;
1855 /*************************************************************************
1856 * @ [SHLWAPI.192]
1858 * Get a sub-menu from a menu item.
1860 * PARAMS
1861 * hMenu [I] Menu to get sub-menu from
1862 * uID [I] ID of menu item containing sub-menu
1864 * RETURNS
1865 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1867 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1869 MENUITEMINFOW mi;
1871 TRACE("(%p,%u)\n", hMenu, uID);
1873 mi.cbSize = sizeof(mi);
1874 mi.fMask = MIIM_SUBMENU;
1876 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1877 return NULL;
1879 return mi.hSubMenu;
1882 /*************************************************************************
1883 * @ [SHLWAPI.193]
1885 * Get the color depth of the primary display.
1887 * PARAMS
1888 * None.
1890 * RETURNS
1891 * The color depth of the primary display.
1893 DWORD WINAPI SHGetCurColorRes(void)
1895 HDC hdc;
1896 DWORD ret;
1898 TRACE("()\n");
1900 hdc = GetDC(0);
1901 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1902 ReleaseDC(0, hdc);
1903 return ret;
1906 /*************************************************************************
1907 * @ [SHLWAPI.194]
1909 * Wait for a message to arrive, with a timeout.
1911 * PARAMS
1912 * hand [I] Handle to query
1913 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1915 * RETURNS
1916 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1917 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1918 * message is available.
1920 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
1922 DWORD dwEndTicks = GetTickCount() + dwTimeout;
1923 DWORD dwRet;
1925 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
1927 MSG msg;
1929 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
1931 if (dwTimeout != INFINITE)
1933 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
1934 return WAIT_TIMEOUT;
1938 return dwRet;
1941 /*************************************************************************
1942 * @ [SHLWAPI.195]
1944 * Determine if a shell folder can be expanded.
1946 * PARAMS
1947 * lpFolder [I] Parent folder containing the object to test.
1948 * pidl [I] Id of the object to test.
1950 * RETURNS
1951 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
1952 * Failure: E_INVALIDARG, if any argument is invalid.
1954 * NOTES
1955 * If the object to be tested does not expose the IQueryInfo() interface it
1956 * will not be identified as an expandable folder.
1958 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
1960 HRESULT hRet = E_INVALIDARG;
1961 IQueryInfo *lpInfo;
1963 if (lpFolder && pidl)
1965 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
1966 NULL, (void**)&lpInfo);
1967 if (FAILED(hRet))
1968 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
1969 else
1971 DWORD dwFlags = 0;
1973 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
1974 * currently used". Really? You wouldn't be holding out on me would you?
1976 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
1978 if (SUCCEEDED(hRet))
1980 /* 0x2 is an undocumented flag apparently indicating expandability */
1981 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
1984 IQueryInfo_Release(lpInfo);
1987 return hRet;
1990 /*************************************************************************
1991 * @ [SHLWAPI.197]
1993 * Blank out a region of text by drawing the background only.
1995 * PARAMS
1996 * hDC [I] Device context to draw in
1997 * pRect [I] Area to draw in
1998 * cRef [I] Color to draw in
2000 * RETURNS
2001 * Nothing.
2003 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2005 COLORREF cOldColor = SetBkColor(hDC, cRef);
2006 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2007 SetBkColor(hDC, cOldColor);
2008 return 0;
2011 /*************************************************************************
2012 * @ [SHLWAPI.198]
2014 * Return the value associated with a key in a map.
2016 * PARAMS
2017 * lpKeys [I] A list of keys of length iLen
2018 * lpValues [I] A list of values associated with lpKeys, of length iLen
2019 * iLen [I] Length of both lpKeys and lpValues
2020 * iKey [I] The key value to look up in lpKeys
2022 * RETURNS
2023 * The value in lpValues associated with iKey, or -1 if iKey is not
2024 * found in lpKeys.
2026 * NOTES
2027 * - If two elements in the map share the same key, this function returns
2028 * the value closest to the start of the map
2029 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2031 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2033 if (lpKeys && lpValues)
2035 int i = 0;
2037 while (i < iLen)
2039 if (lpKeys[i] == iKey)
2040 return lpValues[i]; /* Found */
2041 i++;
2044 return -1; /* Not found */
2048 /*************************************************************************
2049 * @ [SHLWAPI.199]
2051 * Copy an interface pointer
2053 * PARAMS
2054 * lppDest [O] Destination for copy
2055 * lpUnknown [I] Source for copy
2057 * RETURNS
2058 * Nothing.
2060 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2062 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2064 if (lppDest)
2065 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2067 if (lpUnknown)
2069 /* Copy */
2070 IUnknown_AddRef(lpUnknown);
2071 *lppDest = lpUnknown;
2075 /*************************************************************************
2076 * @ [SHLWAPI.200]
2079 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2080 REFGUID riidCmdGrp, ULONG cCmds,
2081 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2083 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2084 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2086 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2087 return DRAGDROP_E_NOTREGISTERED;
2090 /*************************************************************************
2091 * @ [SHLWAPI.201]
2094 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2095 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2096 VARIANT* pvaOut)
2098 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2099 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2100 return DRAGDROP_E_NOTREGISTERED;
2103 /*************************************************************************
2104 * @ [SHLWAPI.202]
2107 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2109 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2110 return DRAGDROP_E_NOTREGISTERED;
2113 /*************************************************************************
2114 * @ [SHLWAPI.204]
2116 * Determine if a window is not a child of another window.
2118 * PARAMS
2119 * hParent [I] Suspected parent window
2120 * hChild [I] Suspected child window
2122 * RETURNS
2123 * TRUE: If hChild is a child window of hParent
2124 * FALSE: If hChild is not a child window of hParent, or they are equal
2126 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2128 TRACE("(%p,%p)\n", hParent, hChild);
2130 if (!hParent || !hChild)
2131 return TRUE;
2132 else if(hParent == hChild)
2133 return FALSE;
2134 return !IsChild(hParent, hChild);
2137 /*************************************************************************
2138 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2141 typedef struct
2143 DWORD num_items; /* Number of elements inserted */
2144 void *mem; /* Ptr to array */
2145 DWORD blocks_alloced; /* Number of elements allocated */
2146 BYTE inc; /* Number of elements to grow by when we need to expand */
2147 BYTE block_size; /* Size in bytes of an element */
2148 BYTE flags; /* Flags */
2149 } FDSA_info;
2151 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2153 /*************************************************************************
2154 * @ [SHLWAPI.208]
2156 * Initialize an FDSA array.
2158 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2159 DWORD init_blocks)
2161 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2163 if(inc == 0)
2164 inc = 1;
2166 if(mem)
2167 memset(mem, 0, block_size * init_blocks);
2169 info->num_items = 0;
2170 info->inc = inc;
2171 info->mem = mem;
2172 info->blocks_alloced = init_blocks;
2173 info->block_size = block_size;
2174 info->flags = 0;
2176 return TRUE;
2179 /*************************************************************************
2180 * @ [SHLWAPI.209]
2182 * Destroy an FDSA array
2184 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2186 TRACE("(%p)\n", info);
2188 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2190 HeapFree(GetProcessHeap(), 0, info->mem);
2191 return FALSE;
2194 return TRUE;
2197 /*************************************************************************
2198 * @ [SHLWAPI.210]
2200 * Insert element into an FDSA array
2202 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
2204 TRACE("(%p 0x%08x %p)\n", info, where, block);
2205 if(where > info->num_items)
2206 where = info->num_items;
2208 if(info->num_items >= info->blocks_alloced)
2210 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2211 if(info->flags & 0x1)
2212 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2213 else
2215 void *old_mem = info->mem;
2216 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2217 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2219 info->blocks_alloced += info->inc;
2220 info->flags |= 0x1;
2223 if(where < info->num_items)
2225 memmove((char*)info->mem + (where + 1) * info->block_size,
2226 (char*)info->mem + where * info->block_size,
2227 (info->num_items - where) * info->block_size);
2229 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2231 info->num_items++;
2232 return where;
2235 /*************************************************************************
2236 * @ [SHLWAPI.211]
2238 * Delete an element from an FDSA array.
2240 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2242 TRACE("(%p 0x%08x)\n", info, where);
2244 if(where >= info->num_items)
2245 return FALSE;
2247 if(where < info->num_items - 1)
2249 memmove((char*)info->mem + where * info->block_size,
2250 (char*)info->mem + (where + 1) * info->block_size,
2251 (info->num_items - where - 1) * info->block_size);
2253 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2254 0, info->block_size);
2255 info->num_items--;
2256 return TRUE;
2260 typedef struct {
2261 REFIID refid;
2262 DWORD indx;
2263 } IFACE_INDEX_TBL;
2265 /*************************************************************************
2266 * @ [SHLWAPI.219]
2268 * Call IUnknown_QueryInterface() on a table of objects.
2270 * RETURNS
2271 * Success: S_OK.
2272 * Failure: E_POINTER or E_NOINTERFACE.
2274 HRESULT WINAPI QISearch(
2275 LPVOID w, /* [in] Table of interfaces */
2276 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2277 REFIID riid, /* [in] REFIID to get interface for */
2278 LPVOID *ppv) /* [out] Destination for interface pointer */
2280 HRESULT ret;
2281 IUnknown *a_vtbl;
2282 IFACE_INDEX_TBL *xmove;
2284 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2285 if (ppv) {
2286 xmove = x;
2287 while (xmove->refid) {
2288 TRACE("trying (indx %d) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2289 if (IsEqualIID(riid, xmove->refid)) {
2290 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2291 TRACE("matched, returning (%p)\n", a_vtbl);
2292 *ppv = a_vtbl;
2293 IUnknown_AddRef(a_vtbl);
2294 return S_OK;
2296 xmove++;
2299 if (IsEqualIID(riid, &IID_IUnknown)) {
2300 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2301 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2302 *ppv = a_vtbl;
2303 IUnknown_AddRef(a_vtbl);
2304 return S_OK;
2306 *ppv = 0;
2307 ret = E_NOINTERFACE;
2308 } else
2309 ret = E_POINTER;
2311 TRACE("-- 0x%08x\n", ret);
2312 return ret;
2315 /*************************************************************************
2316 * @ [SHLWAPI.220]
2318 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2320 * PARAMS
2321 * hWnd [I] Parent Window to set the property
2322 * id [I] Index of child Window to set the Font
2324 * RETURNS
2325 * Success: S_OK
2328 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id)
2330 FIXME("(%p, %d) stub\n", hWnd, id);
2331 return S_OK;
2334 /*************************************************************************
2335 * @ [SHLWAPI.221]
2337 * Remove the "PropDlgFont" property from a window.
2339 * PARAMS
2340 * hWnd [I] Window to remove the property from
2342 * RETURNS
2343 * A handle to the removed property, or NULL if it did not exist.
2345 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2347 HANDLE hProp;
2349 TRACE("(%p)\n", hWnd);
2351 hProp = GetPropA(hWnd, "PropDlgFont");
2353 if(hProp)
2355 DeleteObject(hProp);
2356 hProp = RemovePropA(hWnd, "PropDlgFont");
2358 return hProp;
2361 /*************************************************************************
2362 * @ [SHLWAPI.236]
2364 * Load the in-process server of a given GUID.
2366 * PARAMS
2367 * refiid [I] GUID of the server to load.
2369 * RETURNS
2370 * Success: A handle to the loaded server dll.
2371 * Failure: A NULL handle.
2373 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2375 HKEY newkey;
2376 DWORD type, count;
2377 CHAR value[MAX_PATH], string[MAX_PATH];
2379 strcpy(string, "CLSID\\");
2380 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2381 strcat(string, "\\InProcServer32");
2383 count = MAX_PATH;
2384 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2385 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2386 RegCloseKey(newkey);
2387 return LoadLibraryExA(value, 0, 0);
2390 /*************************************************************************
2391 * @ [SHLWAPI.237]
2393 * Unicode version of SHLWAPI_183.
2395 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2397 WNDCLASSW WndClass;
2399 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2401 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2402 return TRUE;
2403 return RegisterClassW(lpWndClass);
2406 /*************************************************************************
2407 * @ [SHLWAPI.238]
2409 * Unregister a list of classes.
2411 * PARAMS
2412 * hInst [I] Application instance that registered the classes
2413 * lppClasses [I] List of class names
2414 * iCount [I] Number of names in lppClasses
2416 * RETURNS
2417 * Nothing.
2419 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2421 WNDCLASSA WndClass;
2423 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2425 while (iCount > 0)
2427 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2428 UnregisterClassA(*lppClasses, hInst);
2429 lppClasses++;
2430 iCount--;
2434 /*************************************************************************
2435 * @ [SHLWAPI.239]
2437 * Unicode version of SHUnregisterClassesA.
2439 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2441 WNDCLASSW WndClass;
2443 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2445 while (iCount > 0)
2447 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2448 UnregisterClassW(*lppClasses, hInst);
2449 lppClasses++;
2450 iCount--;
2454 /*************************************************************************
2455 * @ [SHLWAPI.240]
2457 * Call The correct (Ascii/Unicode) default window procedure for a window.
2459 * PARAMS
2460 * hWnd [I] Window to call the default procedure for
2461 * uMessage [I] Message ID
2462 * wParam [I] WPARAM of message
2463 * lParam [I] LPARAM of message
2465 * RETURNS
2466 * The result of calling DefWindowProcA() or DefWindowProcW().
2468 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2470 if (IsWindowUnicode(hWnd))
2471 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2472 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2475 /*************************************************************************
2476 * @ [SHLWAPI.256]
2478 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2480 HRESULT hRet = E_INVALIDARG;
2481 LPOBJECTWITHSITE lpSite = NULL;
2483 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2485 if (lpUnknown && iid && lppSite)
2487 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2488 (void**)&lpSite);
2489 if (SUCCEEDED(hRet) && lpSite)
2491 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2492 IObjectWithSite_Release(lpSite);
2495 return hRet;
2498 /*************************************************************************
2499 * @ [SHLWAPI.257]
2501 * Create a worker window using CreateWindowExA().
2503 * PARAMS
2504 * wndProc [I] Window procedure
2505 * hWndParent [I] Parent window
2506 * dwExStyle [I] Extra style flags
2507 * dwStyle [I] Style flags
2508 * hMenu [I] Window menu
2509 * z [I] Unknown
2511 * RETURNS
2512 * Success: The window handle of the newly created window.
2513 * Failure: 0.
2515 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2516 DWORD dwStyle, HMENU hMenu, LONG z)
2518 static const char szClass[] = "WorkerA";
2519 WNDCLASSA wc;
2520 HWND hWnd;
2522 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2523 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2525 /* Create Window class */
2526 wc.style = 0;
2527 wc.lpfnWndProc = DefWindowProcA;
2528 wc.cbClsExtra = 0;
2529 wc.cbWndExtra = 4;
2530 wc.hInstance = shlwapi_hInstance;
2531 wc.hIcon = NULL;
2532 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2533 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2534 wc.lpszMenuName = NULL;
2535 wc.lpszClassName = szClass;
2537 SHRegisterClassA(&wc); /* Register class */
2539 /* FIXME: Set extra bits in dwExStyle */
2541 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2542 hWndParent, hMenu, shlwapi_hInstance, 0);
2543 if (hWnd)
2545 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2547 if (wndProc)
2548 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2550 return hWnd;
2553 typedef struct tagPOLICYDATA
2555 DWORD policy; /* flags value passed to SHRestricted */
2556 LPCWSTR appstr; /* application str such as "Explorer" */
2557 LPCWSTR keystr; /* name of the actual registry key / policy */
2558 } POLICYDATA, *LPPOLICYDATA;
2560 #define SHELL_NO_POLICY 0xffffffff
2562 /* default shell policy registry key */
2563 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2564 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2565 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2566 '\\','P','o','l','i','c','i','e','s',0};
2568 /*************************************************************************
2569 * @ [SHLWAPI.271]
2571 * Retrieve a policy value from the registry.
2573 * PARAMS
2574 * lpSubKey [I] registry key name
2575 * lpSubName [I] subname of registry key
2576 * lpValue [I] value name of registry value
2578 * RETURNS
2579 * the value associated with the registry key or 0 if not found
2581 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2583 DWORD retval, datsize = sizeof(retval);
2584 HKEY hKey;
2586 if (!lpSubKey)
2587 lpSubKey = strRegistryPolicyW;
2589 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2590 if (retval != ERROR_SUCCESS)
2591 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2592 if (retval != ERROR_SUCCESS)
2593 return 0;
2595 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2596 RegCloseKey(hKey);
2597 return retval;
2600 /*************************************************************************
2601 * @ [SHLWAPI.266]
2603 * Helper function to retrieve the possibly cached value for a specific policy
2605 * PARAMS
2606 * policy [I] The policy to look for
2607 * initial [I] Main registry key to open, if NULL use default
2608 * polTable [I] Table of known policies, 0 terminated
2609 * polArr [I] Cache array of policy values
2611 * RETURNS
2612 * The retrieved policy value or 0 if not successful
2614 * NOTES
2615 * This function is used by the native SHRestricted function to search for the
2616 * policy and cache it once retrieved. The current Wine implementation uses a
2617 * different POLICYDATA structure and implements a similar algorithm adapted to
2618 * that structure.
2620 DWORD WINAPI SHRestrictionLookup(
2621 DWORD policy,
2622 LPCWSTR initial,
2623 LPPOLICYDATA polTable,
2624 LPDWORD polArr)
2626 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2628 if (!polTable || !polArr)
2629 return 0;
2631 for (;polTable->policy; polTable++, polArr++)
2633 if (policy == polTable->policy)
2635 /* we have a known policy */
2637 /* check if this policy has been cached */
2638 if (*polArr == SHELL_NO_POLICY)
2639 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2640 return *polArr;
2643 /* we don't know this policy, return 0 */
2644 TRACE("unknown policy: (%08x)\n", policy);
2645 return 0;
2648 /*************************************************************************
2649 * @ [SHLWAPI.267]
2651 * Get an interface from an object.
2653 * RETURNS
2654 * Success: S_OK. ppv contains the requested interface.
2655 * Failure: An HRESULT error code.
2657 * NOTES
2658 * This QueryInterface asks the inner object for an interface. In case
2659 * of aggregation this request would be forwarded by the inner to the
2660 * outer object. This function asks the inner object directly for the
2661 * interface circumventing the forwarding to the outer object.
2663 HRESULT WINAPI SHWeakQueryInterface(
2664 IUnknown * pUnk, /* [in] Outer object */
2665 IUnknown * pInner, /* [in] Inner object */
2666 IID * riid, /* [in] Interface GUID to query for */
2667 LPVOID* ppv) /* [out] Destination for queried interface */
2669 HRESULT hret = E_NOINTERFACE;
2670 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2672 *ppv = NULL;
2673 if(pUnk && pInner) {
2674 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2675 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2677 TRACE("-- 0x%08x\n", hret);
2678 return hret;
2681 /*************************************************************************
2682 * @ [SHLWAPI.268]
2684 * Move a reference from one interface to another.
2686 * PARAMS
2687 * lpDest [O] Destination to receive the reference
2688 * lppUnknown [O] Source to give up the reference to lpDest
2690 * RETURNS
2691 * Nothing.
2693 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2695 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2697 if (*lppUnknown)
2699 /* Copy Reference*/
2700 IUnknown_AddRef(lpDest);
2701 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2705 /*************************************************************************
2706 * @ [SHLWAPI.269]
2708 * Convert an ASCII string of a CLSID into a CLSID.
2710 * PARAMS
2711 * idstr [I] String representing a CLSID in registry format
2712 * id [O] Destination for the converted CLSID
2714 * RETURNS
2715 * Success: TRUE. id contains the converted CLSID.
2716 * Failure: FALSE.
2718 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2720 WCHAR wClsid[40];
2721 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2722 return SUCCEEDED(CLSIDFromString(wClsid, id));
2725 /*************************************************************************
2726 * @ [SHLWAPI.270]
2728 * Unicode version of GUIDFromStringA.
2730 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2732 return SUCCEEDED(CLSIDFromString((LPOLESTR)idstr, id));
2735 /*************************************************************************
2736 * @ [SHLWAPI.276]
2738 * Determine if the browser is integrated into the shell, and set a registry
2739 * key accordingly.
2741 * PARAMS
2742 * None.
2744 * RETURNS
2745 * 1, If the browser is not integrated.
2746 * 2, If the browser is integrated.
2748 * NOTES
2749 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2750 * either set to TRUE, or removed depending on whether the browser is deemed
2751 * to be integrated.
2753 DWORD WINAPI WhichPlatform(void)
2755 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2756 static DWORD dwState = 0;
2757 HKEY hKey;
2758 DWORD dwRet, dwData, dwSize;
2759 HMODULE hshell32;
2761 if (dwState)
2762 return dwState;
2764 /* If shell32 exports DllGetVersion(), the browser is integrated */
2765 dwState = 1;
2766 hshell32 = LoadLibraryA("shell32.dll");
2767 if (hshell32)
2769 FARPROC pDllGetVersion;
2770 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2771 dwState = pDllGetVersion ? 2 : 1;
2772 FreeLibrary(hshell32);
2775 /* Set or delete the key accordingly */
2776 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2777 "Software\\Microsoft\\Internet Explorer", 0,
2778 KEY_ALL_ACCESS, &hKey);
2779 if (!dwRet)
2781 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2782 (LPBYTE)&dwData, &dwSize);
2784 if (!dwRet && dwState == 1)
2786 /* Value exists but browser is not integrated */
2787 RegDeleteValueA(hKey, szIntegratedBrowser);
2789 else if (dwRet && dwState == 2)
2791 /* Browser is integrated but value does not exist */
2792 dwData = TRUE;
2793 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2794 (LPBYTE)&dwData, sizeof(dwData));
2796 RegCloseKey(hKey);
2798 return dwState;
2801 /*************************************************************************
2802 * @ [SHLWAPI.278]
2804 * Unicode version of SHCreateWorkerWindowA.
2806 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2807 DWORD dwStyle, HMENU hMenu, LONG z)
2809 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2810 WNDCLASSW wc;
2811 HWND hWnd;
2813 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2814 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2816 /* If our OS is natively ASCII, use the ASCII version */
2817 if (!(GetVersion() & 0x80000000)) /* NT */
2818 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2820 /* Create Window class */
2821 wc.style = 0;
2822 wc.lpfnWndProc = DefWindowProcW;
2823 wc.cbClsExtra = 0;
2824 wc.cbWndExtra = 4;
2825 wc.hInstance = shlwapi_hInstance;
2826 wc.hIcon = NULL;
2827 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2828 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2829 wc.lpszMenuName = NULL;
2830 wc.lpszClassName = szClass;
2832 SHRegisterClassW(&wc); /* Register class */
2834 /* FIXME: Set extra bits in dwExStyle */
2836 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2837 hWndParent, hMenu, shlwapi_hInstance, 0);
2838 if (hWnd)
2840 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2842 if (wndProc)
2843 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2845 return hWnd;
2848 /*************************************************************************
2849 * @ [SHLWAPI.279]
2851 * Get and show a context menu from a shell folder.
2853 * PARAMS
2854 * hWnd [I] Window displaying the shell folder
2855 * lpFolder [I] IShellFolder interface
2856 * lpApidl [I] Id for the particular folder desired
2858 * RETURNS
2859 * Success: S_OK.
2860 * Failure: An HRESULT error code indicating the error.
2862 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2864 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2867 /*************************************************************************
2868 * @ [SHLWAPI.281]
2870 * _SHPackDispParamsV
2872 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist)
2874 VARIANTARG *iter;
2876 TRACE("(%p %p %u ...)\n", params, args, cnt);
2878 params->rgvarg = args;
2879 params->rgdispidNamedArgs = NULL;
2880 params->cArgs = cnt;
2881 params->cNamedArgs = 0;
2883 iter = args+cnt;
2885 while(iter-- > args) {
2886 V_VT(iter) = va_arg(valist, enum VARENUM);
2888 TRACE("vt=%d\n", V_VT(iter));
2890 if(V_VT(iter) & VT_BYREF) {
2891 V_BYREF(iter) = va_arg(valist, LPVOID);
2892 } else {
2893 switch(V_VT(iter)) {
2894 case VT_I4:
2895 V_I4(iter) = va_arg(valist, LONG);
2896 break;
2897 case VT_BSTR:
2898 V_BSTR(iter) = va_arg(valist, BSTR);
2899 break;
2900 case VT_DISPATCH:
2901 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
2902 break;
2903 case VT_BOOL:
2904 V_BOOL(iter) = va_arg(valist, int);
2905 break;
2906 case VT_UNKNOWN:
2907 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
2908 break;
2909 default:
2910 V_VT(iter) = VT_I4;
2911 V_I4(iter) = va_arg(valist, LONG);
2916 return S_OK;
2919 /*************************************************************************
2920 * @ [SHLWAPI.282]
2922 * SHPackDispParams
2924 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...)
2926 __ms_va_list valist;
2927 HRESULT hres;
2929 __ms_va_start(valist, cnt);
2930 hres = SHPackDispParamsV(params, args, cnt, valist);
2931 __ms_va_end(valist);
2932 return hres;
2935 /*************************************************************************
2936 * SHLWAPI_InvokeByIID
2938 * This helper function calls IDispatch::Invoke for each sink
2939 * which implements given iid or IDispatch.
2942 static HRESULT SHLWAPI_InvokeByIID(
2943 IConnectionPoint* iCP,
2944 REFIID iid,
2945 DISPID dispId,
2946 DISPPARAMS* dispParams)
2948 IEnumConnections *enumerator;
2949 CONNECTDATA rgcd;
2950 static DISPPARAMS empty = {NULL, NULL, 0, 0};
2951 DISPPARAMS* params = dispParams;
2953 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
2954 if (FAILED(result))
2955 return result;
2957 /* Invoke is never happening with an NULL dispParams */
2958 if (!params)
2959 params = &empty;
2961 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
2963 IDispatch *dispIface;
2964 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
2965 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
2967 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
2968 IDispatch_Release(dispIface);
2970 IUnknown_Release(rgcd.pUnk);
2973 IEnumConnections_Release(enumerator);
2975 return S_OK;
2978 /*************************************************************************
2979 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
2981 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP,
2982 DISPID dispId, DISPPARAMS* dispParams,
2983 DWORD unknown1, DWORD unknown2 )
2985 IID iid;
2986 HRESULT result;
2988 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
2990 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
2991 if (SUCCEEDED(result))
2992 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
2993 else
2994 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
2996 return result;
3000 /*************************************************************************
3001 * @ [SHLWAPI.284]
3003 * IConnectionPoint_SimpleInvoke
3005 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
3006 IConnectionPoint* iCP,
3007 DISPID dispId,
3008 DISPPARAMS* dispParams)
3010 IID iid;
3011 HRESULT result;
3013 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
3015 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3016 if (SUCCEEDED(result))
3017 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3018 else
3019 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3021 return result;
3024 /*************************************************************************
3025 * @ [SHLWAPI.285]
3027 * Notify an IConnectionPoint object of changes.
3029 * PARAMS
3030 * lpCP [I] Object to notify
3031 * dispID [I]
3033 * RETURNS
3034 * Success: S_OK.
3035 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3036 * IConnectionPoint interface.
3038 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
3040 IEnumConnections *lpEnum;
3041 HRESULT hRet = E_NOINTERFACE;
3043 TRACE("(%p,0x%8X)\n", lpCP, dispID);
3045 /* Get an enumerator for the connections */
3046 if (lpCP)
3047 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
3049 if (SUCCEEDED(hRet))
3051 IPropertyNotifySink *lpSink;
3052 CONNECTDATA connData;
3053 ULONG ulFetched;
3055 /* Call OnChanged() for every notify sink in the connection point */
3056 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
3058 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
3059 lpSink)
3061 IPropertyNotifySink_OnChanged(lpSink, dispID);
3062 IPropertyNotifySink_Release(lpSink);
3064 IUnknown_Release(connData.pUnk);
3067 IEnumConnections_Release(lpEnum);
3069 return hRet;
3072 /*************************************************************************
3073 * @ [SHLWAPI.286]
3075 * IUnknown_CPContainerInvokeParam
3077 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
3078 IUnknown *container,
3079 REFIID riid,
3080 DISPID dispId,
3081 VARIANTARG* buffer,
3082 DWORD cParams, ...)
3084 HRESULT result;
3085 IConnectionPoint *iCP;
3086 IConnectionPointContainer *iCPC;
3087 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3088 __ms_va_list valist;
3090 if (!container)
3091 return E_NOINTERFACE;
3093 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
3094 if (FAILED(result))
3095 return result;
3097 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
3098 IConnectionPointContainer_Release(iCPC);
3099 if(FAILED(result))
3100 return result;
3102 __ms_va_start(valist, cParams);
3103 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
3104 __ms_va_end(valist);
3106 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3107 IConnectionPoint_Release(iCP);
3109 return result;
3112 /*************************************************************************
3113 * @ [SHLWAPI.287]
3115 * Notify an IConnectionPointContainer object of changes.
3117 * PARAMS
3118 * lpUnknown [I] Object to notify
3119 * dispID [I]
3121 * RETURNS
3122 * Success: S_OK.
3123 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3124 * IConnectionPointContainer interface.
3126 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3128 IConnectionPointContainer* lpCPC = NULL;
3129 HRESULT hRet = E_NOINTERFACE;
3131 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3133 if (lpUnknown)
3134 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3136 if (SUCCEEDED(hRet))
3138 IConnectionPoint* lpCP;
3140 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3141 IConnectionPointContainer_Release(lpCPC);
3143 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3144 IConnectionPoint_Release(lpCP);
3146 return hRet;
3149 /*************************************************************************
3150 * @ [SHLWAPI.289]
3152 * See PlaySoundW.
3154 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3156 return PlaySoundW(pszSound, hmod, fdwSound);
3159 /*************************************************************************
3160 * @ [SHLWAPI.294]
3162 BOOL WINAPI SHGetIniStringW(LPCWSTR str1, LPCWSTR str2, LPWSTR pStr, DWORD some_len, LPCWSTR lpStr2)
3164 FIXME("(%s,%s,%p,%08x,%s): stub!\n", debugstr_w(str1), debugstr_w(str2),
3165 pStr, some_len, debugstr_w(lpStr2));
3166 return TRUE;
3169 /*************************************************************************
3170 * @ [SHLWAPI.295]
3172 * Called by ICQ2000b install via SHDOCVW:
3173 * str1: "InternetShortcut"
3174 * x: some unknown pointer
3175 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
3176 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
3178 * In short: this one maybe creates a desktop link :-)
3180 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
3182 FIXME("(%s, %p, %s, %s), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
3183 return TRUE;
3186 /*************************************************************************
3187 * @ [SHLWAPI.313]
3189 * See SHGetFileInfoW.
3191 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3192 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3194 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3197 /*************************************************************************
3198 * @ [SHLWAPI.318]
3200 * See DragQueryFileW.
3202 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3204 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3207 /*************************************************************************
3208 * @ [SHLWAPI.333]
3210 * See SHBrowseForFolderW.
3212 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3214 return SHBrowseForFolderW(lpBi);
3217 /*************************************************************************
3218 * @ [SHLWAPI.334]
3220 * See SHGetPathFromIDListW.
3222 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3224 return SHGetPathFromIDListW(pidl, pszPath);
3227 /*************************************************************************
3228 * @ [SHLWAPI.335]
3230 * See ShellExecuteExW.
3232 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3234 return ShellExecuteExW(lpExecInfo);
3237 /*************************************************************************
3238 * @ [SHLWAPI.336]
3240 * See SHFileOperationW.
3242 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3244 return SHFileOperationW(lpFileOp);
3247 /*************************************************************************
3248 * @ [SHLWAPI.342]
3251 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
3253 return InterlockedCompareExchangePointer( dest, xchg, compare );
3256 /*************************************************************************
3257 * @ [SHLWAPI.350]
3259 * See GetFileVersionInfoSizeW.
3261 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
3263 return GetFileVersionInfoSizeW( filename, handle );
3266 /*************************************************************************
3267 * @ [SHLWAPI.351]
3269 * See GetFileVersionInfoW.
3271 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
3272 DWORD datasize, LPVOID data )
3274 return GetFileVersionInfoW( filename, handle, datasize, data );
3277 /*************************************************************************
3278 * @ [SHLWAPI.352]
3280 * See VerQueryValueW.
3282 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
3283 LPVOID *lplpBuffer, UINT *puLen )
3285 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3288 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3289 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3290 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3292 /*************************************************************************
3293 * @ [SHLWAPI.355]
3295 * Change the modality of a shell object.
3297 * PARAMS
3298 * lpUnknown [I] Object to make modeless
3299 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3301 * RETURNS
3302 * Success: S_OK. The modality lpUnknown is changed.
3303 * Failure: An HRESULT error code indicating the error.
3305 * NOTES
3306 * lpUnknown must support the IOleInPlaceFrame interface, the
3307 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3308 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3309 * or this call will fail.
3311 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3313 IUnknown *lpObj;
3314 HRESULT hRet;
3316 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3318 if (!lpUnknown)
3319 return E_FAIL;
3321 if (IsIface(IOleInPlaceActiveObject))
3322 EnableModeless(IOleInPlaceActiveObject);
3323 else if (IsIface(IOleInPlaceFrame))
3324 EnableModeless(IOleInPlaceFrame);
3325 else if (IsIface(IShellBrowser))
3326 EnableModeless(IShellBrowser);
3327 else if (IsIface(IInternetSecurityMgrSite))
3328 EnableModeless(IInternetSecurityMgrSite);
3329 else if (IsIface(IDocHostUIHandler))
3330 EnableModeless(IDocHostUIHandler);
3331 else
3332 return hRet;
3334 IUnknown_Release(lpObj);
3335 return S_OK;
3338 /*************************************************************************
3339 * @ [SHLWAPI.357]
3341 * See SHGetNewLinkInfoW.
3343 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3344 BOOL *pfMustCopy, UINT uFlags)
3346 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3349 /*************************************************************************
3350 * @ [SHLWAPI.358]
3352 * See SHDefExtractIconW.
3354 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3355 HICON* phiconSmall, UINT nIconSize)
3357 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3360 /*************************************************************************
3361 * @ [SHLWAPI.363]
3363 * Get and show a context menu from a shell folder.
3365 * PARAMS
3366 * hWnd [I] Window displaying the shell folder
3367 * lpFolder [I] IShellFolder interface
3368 * lpApidl [I] Id for the particular folder desired
3369 * bInvokeDefault [I] Whether to invoke the default menu item
3371 * RETURNS
3372 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3373 * executed.
3374 * Failure: An HRESULT error code indicating the error.
3376 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3378 IContextMenu *iContext;
3379 HRESULT hRet = E_FAIL;
3381 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3383 if (!lpFolder)
3384 return hRet;
3386 /* Get the context menu from the shell folder */
3387 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3388 &IID_IContextMenu, 0, (void**)&iContext);
3389 if (SUCCEEDED(hRet))
3391 HMENU hMenu;
3392 if ((hMenu = CreatePopupMenu()))
3394 HRESULT hQuery;
3395 DWORD dwDefaultId = 0;
3397 /* Add the context menu entries to the popup */
3398 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3399 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3401 if (SUCCEEDED(hQuery))
3403 if (bInvokeDefault &&
3404 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3406 CMINVOKECOMMANDINFO cmIci;
3407 /* Invoke the default item */
3408 memset(&cmIci,0,sizeof(cmIci));
3409 cmIci.cbSize = sizeof(cmIci);
3410 cmIci.fMask = CMIC_MASK_ASYNCOK;
3411 cmIci.hwnd = hWnd;
3412 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3413 cmIci.nShow = SW_SCROLLCHILDREN;
3415 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3418 DestroyMenu(hMenu);
3420 IContextMenu_Release(iContext);
3422 return hRet;
3425 /*************************************************************************
3426 * @ [SHLWAPI.370]
3428 * See ExtractIconW.
3430 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3431 UINT nIconIndex)
3433 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3436 /*************************************************************************
3437 * @ [SHLWAPI.377]
3439 * Load a library from the directory of a particular process.
3441 * PARAMS
3442 * new_mod [I] Library name
3443 * inst_hwnd [I] Module whose directory is to be used
3444 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3446 * RETURNS
3447 * Success: A handle to the loaded module
3448 * Failure: A NULL handle.
3450 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3452 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3453 * each call here.
3454 * FIXME: Native shows calls to:
3455 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3456 * CheckVersion
3457 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3458 * RegQueryValueExA for "LPKInstalled"
3459 * RegCloseKey
3460 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3461 * RegQueryValueExA for "ResourceLocale"
3462 * RegCloseKey
3463 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3464 * RegQueryValueExA for "Locale"
3465 * RegCloseKey
3466 * and then tests the Locale ("en" for me).
3467 * code below
3468 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3470 CHAR mod_path[2*MAX_PATH];
3471 LPSTR ptr;
3472 DWORD len;
3474 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3475 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3476 if (!len || len >= sizeof(mod_path)) return NULL;
3478 ptr = strrchr(mod_path, '\\');
3479 if (ptr) {
3480 strcpy(ptr+1, new_mod);
3481 TRACE("loading %s\n", debugstr_a(mod_path));
3482 return LoadLibraryA(mod_path);
3484 return NULL;
3487 /*************************************************************************
3488 * @ [SHLWAPI.378]
3490 * Unicode version of MLLoadLibraryA.
3492 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3494 WCHAR mod_path[2*MAX_PATH];
3495 LPWSTR ptr;
3496 DWORD len;
3498 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3499 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3500 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3502 ptr = strrchrW(mod_path, '\\');
3503 if (ptr) {
3504 strcpyW(ptr+1, new_mod);
3505 TRACE("loading %s\n", debugstr_w(mod_path));
3506 return LoadLibraryW(mod_path);
3508 return NULL;
3511 /*************************************************************************
3512 * ColorAdjustLuma [SHLWAPI.@]
3514 * Adjust the luminosity of a color
3516 * PARAMS
3517 * cRGB [I] RGB value to convert
3518 * dwLuma [I] Luma adjustment
3519 * bUnknown [I] Unknown
3521 * RETURNS
3522 * The adjusted RGB color.
3524 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3526 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3528 if (dwLuma)
3530 WORD wH, wL, wS;
3532 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3534 FIXME("Ignoring luma adjustment\n");
3536 /* FIXME: The adjustment is not linear */
3538 cRGB = ColorHLSToRGB(wH, wL, wS);
3540 return cRGB;
3543 /*************************************************************************
3544 * @ [SHLWAPI.389]
3546 * See GetSaveFileNameW.
3548 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3550 return GetSaveFileNameW(ofn);
3553 /*************************************************************************
3554 * @ [SHLWAPI.390]
3556 * See WNetRestoreConnectionW.
3558 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3560 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3563 /*************************************************************************
3564 * @ [SHLWAPI.391]
3566 * See WNetGetLastErrorW.
3568 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3569 LPWSTR lpNameBuf, DWORD nNameBufSize)
3571 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3574 /*************************************************************************
3575 * @ [SHLWAPI.401]
3577 * See PageSetupDlgW.
3579 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3581 return PageSetupDlgW(pagedlg);
3584 /*************************************************************************
3585 * @ [SHLWAPI.402]
3587 * See PrintDlgW.
3589 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3591 return PrintDlgW(printdlg);
3594 /*************************************************************************
3595 * @ [SHLWAPI.403]
3597 * See GetOpenFileNameW.
3599 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3601 return GetOpenFileNameW(ofn);
3604 /*************************************************************************
3605 * @ [SHLWAPI.404]
3607 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3609 IPersist *persist;
3610 HRESULT hr;
3612 hr = IShellFolder_QueryInterface(lpFolder, &IID_IPersist, (LPVOID)&persist);
3613 if(SUCCEEDED(hr))
3615 CLSID clsid;
3616 hr = IPersist_GetClassID(persist, &clsid);
3617 if(SUCCEEDED(hr))
3619 if(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder))
3620 hr = IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3621 else
3622 hr = E_FAIL;
3624 IPersist_Release(persist);
3626 return hr;
3629 /* INTERNAL: Map from HLS color space to RGB */
3630 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3632 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3634 if (wHue > 160)
3635 return wMid1;
3636 else if (wHue > 120)
3637 wHue = 160 - wHue;
3638 else if (wHue > 40)
3639 return wMid2;
3641 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3644 /* Convert to RGB and scale into RGB range (0..255) */
3645 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3647 /*************************************************************************
3648 * ColorHLSToRGB [SHLWAPI.@]
3650 * Convert from hls color space into an rgb COLORREF.
3652 * PARAMS
3653 * wHue [I] Hue amount
3654 * wLuminosity [I] Luminosity amount
3655 * wSaturation [I] Saturation amount
3657 * RETURNS
3658 * A COLORREF representing the converted color.
3660 * NOTES
3661 * Input hls values are constrained to the range (0..240).
3663 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3665 WORD wRed;
3667 if (wSaturation)
3669 WORD wGreen, wBlue, wMid1, wMid2;
3671 if (wLuminosity > 120)
3672 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3673 else
3674 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3676 wMid1 = wLuminosity * 2 - wMid2;
3678 wRed = GET_RGB(wHue + 80);
3679 wGreen = GET_RGB(wHue);
3680 wBlue = GET_RGB(wHue - 80);
3682 return RGB(wRed, wGreen, wBlue);
3685 wRed = wLuminosity * 255 / 240;
3686 return RGB(wRed, wRed, wRed);
3689 /*************************************************************************
3690 * @ [SHLWAPI.413]
3692 * Get the current docking status of the system.
3694 * PARAMS
3695 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3697 * RETURNS
3698 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3699 * a notebook.
3701 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3703 HW_PROFILE_INFOA hwInfo;
3705 TRACE("(0x%08x)\n", dwFlags);
3707 GetCurrentHwProfileA(&hwInfo);
3708 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3710 case DOCKINFO_DOCKED:
3711 case DOCKINFO_UNDOCKED:
3712 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3713 default:
3714 return 0;
3718 /*************************************************************************
3719 * @ [SHLWAPI.418]
3721 * Function seems to do FreeLibrary plus other things.
3723 * FIXME native shows the following calls:
3724 * RtlEnterCriticalSection
3725 * LocalFree
3726 * GetProcAddress(Comctl32??, 150L)
3727 * DPA_DeletePtr
3728 * RtlLeaveCriticalSection
3729 * followed by the FreeLibrary.
3730 * The above code may be related to .377 above.
3732 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3734 FIXME("(%p) semi-stub\n", hModule);
3735 return FreeLibrary(hModule);
3738 /*************************************************************************
3739 * @ [SHLWAPI.419]
3741 BOOL WINAPI SHFlushSFCacheWrap(void) {
3742 FIXME(": stub\n");
3743 return TRUE;
3746 /*************************************************************************
3747 * @ [SHLWAPI.429]
3748 * FIXME I have no idea what this function does or what its arguments are.
3750 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3752 FIXME("(%p) stub\n", hInst);
3753 return FALSE;
3757 /*************************************************************************
3758 * @ [SHLWAPI.430]
3760 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3762 FIXME("(%p,%p) stub\n", hInst, hHeap);
3763 return E_FAIL; /* This is what is used if shlwapi not loaded */
3766 /*************************************************************************
3767 * @ [SHLWAPI.431]
3769 DWORD WINAPI MLClearMLHInstance(DWORD x)
3771 FIXME("(0x%08x)stub\n", x);
3772 return 0xabba1247;
3775 /*************************************************************************
3776 * @ [SHLWAPI.432]
3778 * See SHSendMessageBroadcastW
3781 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam)
3783 return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam,
3784 SMTO_ABORTIFHUNG, 2000, NULL);
3787 /*************************************************************************
3788 * @ [SHLWAPI.433]
3790 * A wrapper for sending Broadcast Messages to all top level Windows
3793 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam)
3795 return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam,
3796 SMTO_ABORTIFHUNG, 2000, NULL);
3799 /*************************************************************************
3800 * @ [SHLWAPI.436]
3802 * Convert a Unicode string CLSID into a CLSID.
3804 * PARAMS
3805 * idstr [I] string containing a CLSID in text form
3806 * id [O] CLSID extracted from the string
3808 * RETURNS
3809 * S_OK on success or E_INVALIDARG on failure
3811 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3813 return CLSIDFromString((LPOLESTR)idstr, id);
3816 /*************************************************************************
3817 * @ [SHLWAPI.437]
3819 * Determine if the OS supports a given feature.
3821 * PARAMS
3822 * dwFeature [I] Feature requested (undocumented)
3824 * RETURNS
3825 * TRUE If the feature is available.
3826 * FALSE If the feature is not available.
3828 BOOL WINAPI IsOS(DWORD feature)
3830 OSVERSIONINFOA osvi;
3831 DWORD platform, majorv, minorv;
3833 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3834 if(!GetVersionExA(&osvi)) {
3835 ERR("GetVersionEx failed\n");
3836 return FALSE;
3839 majorv = osvi.dwMajorVersion;
3840 minorv = osvi.dwMinorVersion;
3841 platform = osvi.dwPlatformId;
3843 #define ISOS_RETURN(x) \
3844 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3845 return (x);
3847 switch(feature) {
3848 case OS_WIN32SORGREATER:
3849 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3850 || platform == VER_PLATFORM_WIN32_WINDOWS)
3851 case OS_NT:
3852 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3853 case OS_WIN95ORGREATER:
3854 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3855 case OS_NT4ORGREATER:
3856 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3857 case OS_WIN2000ORGREATER_ALT:
3858 case OS_WIN2000ORGREATER:
3859 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3860 case OS_WIN98ORGREATER:
3861 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3862 case OS_WIN98_GOLD:
3863 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3864 case OS_WIN2000PRO:
3865 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3866 case OS_WIN2000SERVER:
3867 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3868 case OS_WIN2000ADVSERVER:
3869 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3870 case OS_WIN2000DATACENTER:
3871 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3872 case OS_WIN2000TERMINAL:
3873 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3874 case OS_EMBEDDED:
3875 FIXME("(OS_EMBEDDED) What should we return here?\n");
3876 return FALSE;
3877 case OS_TERMINALCLIENT:
3878 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3879 return FALSE;
3880 case OS_TERMINALREMOTEADMIN:
3881 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3882 return FALSE;
3883 case OS_WIN95_GOLD:
3884 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3885 case OS_MEORGREATER:
3886 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3887 case OS_XPORGREATER:
3888 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3889 case OS_HOME:
3890 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3891 case OS_PROFESSIONAL:
3892 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3893 case OS_DATACENTER:
3894 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3895 case OS_ADVSERVER:
3896 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3897 case OS_SERVER:
3898 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3899 case OS_TERMINALSERVER:
3900 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3901 case OS_PERSONALTERMINALSERVER:
3902 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3903 case OS_FASTUSERSWITCHING:
3904 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3905 return TRUE;
3906 case OS_WELCOMELOGONUI:
3907 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3908 return FALSE;
3909 case OS_DOMAINMEMBER:
3910 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3911 return TRUE;
3912 case OS_ANYSERVER:
3913 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3914 case OS_WOW6432:
3915 FIXME("(OS_WOW6432) Should we check this?\n");
3916 return FALSE;
3917 case OS_WEBSERVER:
3918 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3919 case OS_SMALLBUSINESSSERVER:
3920 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3921 case OS_TABLETPC:
3922 FIXME("(OS_TABLEPC) What should we return here?\n");
3923 return FALSE;
3924 case OS_SERVERADMINUI:
3925 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3926 return FALSE;
3927 case OS_MEDIACENTER:
3928 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3929 return FALSE;
3930 case OS_APPLIANCE:
3931 FIXME("(OS_APPLIANCE) What should we return here?\n");
3932 return FALSE;
3933 case 0x25: /*OS_VISTAORGREATER*/
3934 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
3937 #undef ISOS_RETURN
3939 WARN("(0x%x) unknown parameter\n",feature);
3941 return FALSE;
3944 /*************************************************************************
3945 * @ [SHLWAPI.439]
3947 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
3949 DWORD type, sz = size;
3951 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
3952 return E_FAIL;
3954 return SHLoadIndirectString(buf, buf, size, NULL);
3957 /*************************************************************************
3958 * @ [SHLWAPI.478]
3960 * Call IInputObject_TranslateAcceleratorIO() on an object.
3962 * PARAMS
3963 * lpUnknown [I] Object supporting the IInputObject interface.
3964 * lpMsg [I] Key message to be processed.
3966 * RETURNS
3967 * Success: S_OK.
3968 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3970 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
3972 IInputObject* lpInput = NULL;
3973 HRESULT hRet = E_INVALIDARG;
3975 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
3976 if (lpUnknown)
3978 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3979 (void**)&lpInput);
3980 if (SUCCEEDED(hRet) && lpInput)
3982 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
3983 IInputObject_Release(lpInput);
3986 return hRet;
3989 /*************************************************************************
3990 * @ [SHLWAPI.481]
3992 * Call IInputObject_HasFocusIO() on an object.
3994 * PARAMS
3995 * lpUnknown [I] Object supporting the IInputObject interface.
3997 * RETURNS
3998 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
3999 * or S_FALSE otherwise.
4000 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4002 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
4004 IInputObject* lpInput = NULL;
4005 HRESULT hRet = E_INVALIDARG;
4007 TRACE("(%p)\n", lpUnknown);
4008 if (lpUnknown)
4010 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4011 (void**)&lpInput);
4012 if (SUCCEEDED(hRet) && lpInput)
4014 hRet = IInputObject_HasFocusIO(lpInput);
4015 IInputObject_Release(lpInput);
4018 return hRet;
4021 /*************************************************************************
4022 * ColorRGBToHLS [SHLWAPI.@]
4024 * Convert an rgb COLORREF into the hls color space.
4026 * PARAMS
4027 * cRGB [I] Source rgb value
4028 * pwHue [O] Destination for converted hue
4029 * pwLuminance [O] Destination for converted luminance
4030 * pwSaturation [O] Destination for converted saturation
4032 * RETURNS
4033 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4034 * values.
4036 * NOTES
4037 * Output HLS values are constrained to the range (0..240).
4038 * For Achromatic conversions, Hue is set to 160.
4040 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
4041 LPWORD pwLuminance, LPWORD pwSaturation)
4043 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4045 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4047 wR = GetRValue(cRGB);
4048 wG = GetGValue(cRGB);
4049 wB = GetBValue(cRGB);
4051 wMax = max(wR, max(wG, wB));
4052 wMin = min(wR, min(wG, wB));
4054 /* Luminosity */
4055 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4057 if (wMax == wMin)
4059 /* Achromatic case */
4060 wSaturation = 0;
4061 /* Hue is now unrepresentable, but this is what native returns... */
4062 wHue = 160;
4064 else
4066 /* Chromatic case */
4067 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4069 /* Saturation */
4070 if (wLuminosity <= 120)
4071 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4072 else
4073 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4075 /* Hue */
4076 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4077 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4078 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4080 if (wR == wMax)
4081 wHue = wBNorm - wGNorm;
4082 else if (wG == wMax)
4083 wHue = 80 + wRNorm - wBNorm;
4084 else
4085 wHue = 160 + wGNorm - wRNorm;
4086 if (wHue < 0)
4087 wHue += 240;
4088 else if (wHue > 240)
4089 wHue -= 240;
4091 if (pwHue)
4092 *pwHue = wHue;
4093 if (pwLuminance)
4094 *pwLuminance = wLuminosity;
4095 if (pwSaturation)
4096 *pwSaturation = wSaturation;
4099 /*************************************************************************
4100 * SHCreateShellPalette [SHLWAPI.@]
4102 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4104 FIXME("stub\n");
4105 return CreateHalftonePalette(hdc);
4108 /*************************************************************************
4109 * SHGetInverseCMAP (SHLWAPI.@)
4111 * Get an inverse color map table.
4113 * PARAMS
4114 * lpCmap [O] Destination for color map
4115 * dwSize [I] Size of memory pointed to by lpCmap
4117 * RETURNS
4118 * Success: S_OK.
4119 * Failure: E_POINTER, If lpCmap is invalid.
4120 * E_INVALIDARG, If dwFlags is invalid
4121 * E_OUTOFMEMORY, If there is no memory available
4123 * NOTES
4124 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4125 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4126 * internal CMap.
4127 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4128 * this DLL's internal CMap.
4130 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4132 if (dwSize == 4) {
4133 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4134 *dest = (DWORD)0xabba1249;
4135 return 0;
4137 FIXME("(%p, %#x) stub\n", dest, dwSize);
4138 return 0;
4141 /*************************************************************************
4142 * SHIsLowMemoryMachine [SHLWAPI.@]
4144 * Determine if the current computer has low memory.
4146 * PARAMS
4147 * x [I] FIXME
4149 * RETURNS
4150 * TRUE if the users machine has 16 Megabytes of memory or less,
4151 * FALSE otherwise.
4153 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4155 FIXME("(0x%08x) stub\n", x);
4156 return FALSE;
4159 /*************************************************************************
4160 * GetMenuPosFromID [SHLWAPI.@]
4162 * Return the position of a menu item from its Id.
4164 * PARAMS
4165 * hMenu [I] Menu containing the item
4166 * wID [I] Id of the menu item
4168 * RETURNS
4169 * Success: The index of the menu item in hMenu.
4170 * Failure: -1, If the item is not found.
4172 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4174 MENUITEMINFOW mi;
4175 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4177 while (nIter < nCount)
4179 mi.cbSize = sizeof(mi);
4180 mi.fMask = MIIM_ID;
4181 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4182 return nIter;
4183 nIter++;
4185 return -1;
4188 /*************************************************************************
4189 * @ [SHLWAPI.179]
4191 * Same as SHLWAPI.GetMenuPosFromID
4193 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4195 return GetMenuPosFromID(hMenu, uID);
4199 /*************************************************************************
4200 * @ [SHLWAPI.448]
4202 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4204 while (*lpwstr)
4206 if (*lpwstr == '/')
4207 *lpwstr = '\\';
4208 lpwstr++;
4213 /*************************************************************************
4214 * @ [SHLWAPI.461]
4216 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4218 FIXME("(0x%08x) stub\n", dwUnknown);
4219 return 0;
4223 /*************************************************************************
4224 * @ [SHLWAPI.549]
4226 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4227 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4229 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4232 /*************************************************************************
4233 * SHSkipJunction [SHLWAPI.@]
4235 * Determine if a bind context can be bound to an object
4237 * PARAMS
4238 * pbc [I] Bind context to check
4239 * pclsid [I] CLSID of object to be bound to
4241 * RETURNS
4242 * TRUE: If it is safe to bind
4243 * FALSE: If pbc is invalid or binding would not be safe
4246 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4248 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4249 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4250 BOOL bRet = FALSE;
4252 if (pbc)
4254 IUnknown* lpUnk;
4256 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4258 CLSID clsid;
4260 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4261 IsEqualGUID(pclsid, &clsid))
4262 bRet = TRUE;
4264 IUnknown_Release(lpUnk);
4267 return bRet;
4270 /***********************************************************************
4271 * SHGetShellKey (SHLWAPI.@)
4273 DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
4275 FIXME("(%x, %x, %x): stub\n", a, b, c);
4276 return 0x50;
4279 /***********************************************************************
4280 * SHQueueUserWorkItem (SHLWAPI.@)
4282 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback,
4283 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4284 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4286 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4287 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4289 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4290 FIXME("Unsupported arguments\n");
4292 return QueueUserWorkItem(pfnCallback, pContext, 0);
4295 /***********************************************************************
4296 * SHSetTimerQueueTimer (SHLWAPI.263)
4298 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
4299 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4300 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4302 HANDLE hNewTimer;
4304 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4305 if (dwFlags & TPS_LONGEXECTIME) {
4306 dwFlags &= ~TPS_LONGEXECTIME;
4307 dwFlags |= WT_EXECUTELONGFUNCTION;
4309 if (dwFlags & TPS_EXECUTEIO) {
4310 dwFlags &= ~TPS_EXECUTEIO;
4311 dwFlags |= WT_EXECUTEINIOTHREAD;
4314 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4315 dwDueTime, dwPeriod, dwFlags))
4316 return NULL;
4318 return hNewTimer;
4321 /***********************************************************************
4322 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4324 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4326 IInputObjectSite *pIOS = NULL;
4327 HRESULT hRet = E_INVALIDARG;
4329 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4331 if (lpUnknown)
4333 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4334 (void **)&pIOS);
4335 if (SUCCEEDED(hRet) && pIOS)
4337 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4338 IInputObjectSite_Release(pIOS);
4341 return hRet;
4344 /***********************************************************************
4345 * SHGetValueW (SHLWAPI.@)
4347 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4349 FIXME("(%x, %s, %s, %x, %x, %x): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4350 return E_FAIL;
4353 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4355 /***********************************************************************
4356 * GetUIVersion (SHLWAPI.452)
4358 DWORD WINAPI GetUIVersion(void)
4360 static DWORD version;
4362 if (!version)
4364 DllGetVersion_func pDllGetVersion;
4365 HMODULE dll = LoadLibraryA("shell32.dll");
4366 if (!dll) return 0;
4368 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4369 if (pDllGetVersion)
4371 DLLVERSIONINFO dvi;
4372 dvi.cbSize = sizeof(DLLVERSIONINFO);
4373 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4375 FreeLibrary( dll );
4376 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4378 return version;
4381 /***********************************************************************
4382 * ShellMessageBoxWrapW [SHLWAPI.388]
4384 * See shell32.ShellMessageBoxW
4386 * NOTE:
4387 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4388 * because we can't forward to it in the .spec file since it's exported by
4389 * ordinal. If you change the implementation here please update the code in
4390 * shell32 as well.
4392 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
4393 LPCWSTR lpCaption, UINT uType, ...)
4395 WCHAR szText[100], szTitle[100];
4396 LPCWSTR pszText = szText, pszTitle = szTitle;
4397 LPWSTR pszTemp;
4398 __ms_va_list args;
4399 int ret;
4401 __ms_va_start(args, uType);
4403 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
4405 if (IS_INTRESOURCE(lpCaption))
4406 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
4407 else
4408 pszTitle = lpCaption;
4410 if (IS_INTRESOURCE(lpText))
4411 LoadStringW(hInstance, LOWORD(lpText), szText, sizeof(szText)/sizeof(szText[0]));
4412 else
4413 pszText = lpText;
4415 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4416 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4418 __ms_va_end(args);
4420 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4421 LocalFree(pszTemp);
4422 return ret;
4425 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *unk, REFIID service, REFIID clsid,
4426 DWORD x1, DWORD x2, DWORD x3, void **ppvOut)
4428 FIXME("%p %s %s %08x %08x %08x %p\n", unk,
4429 debugstr_guid(service), debugstr_guid(clsid), x1, x2, x3, ppvOut);
4430 return E_NOTIMPL;
4433 HRESULT WINAPI IUnknown_ProfferService(IUnknown *unk, void *x0, void *x1, void *x2)
4435 FIXME("%p %p %p %p\n", unk, x0, x1, x2);
4436 return E_NOTIMPL;
4439 /***********************************************************************
4440 * ZoneComputePaneSize [SHLWAPI.382]
4442 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4444 FIXME("\n");
4445 return 0x95;
4448 /***********************************************************************
4449 * SHChangeNotifyWrap [SHLWAPI.394]
4451 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
4453 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
4456 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
4457 SID_IDENTIFIER_AUTHORITY sidAuthority;
4458 DWORD dwUserGroupID;
4459 DWORD dwUserID;
4460 } SHELL_USER_SID, *PSHELL_USER_SID;
4462 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
4463 SHELL_USER_SID susID;
4464 DWORD dwAccessType;
4465 BOOL fInherit;
4466 DWORD dwAccessMask;
4467 DWORD dwInheritMask;
4468 DWORD dwInheritAccessMask;
4469 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
4471 /***********************************************************************
4472 * GetShellSecurityDescriptor [SHLWAPI.475]
4474 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4476 * PARAMS
4477 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4478 * each of which describes permissions to apply
4479 * cUserPerm [I] number of entries in apUserPerm array
4481 * RETURNS
4482 * success: pointer to SECURITY_DESCRIPTOR
4483 * failure: NULL
4485 * NOTES
4486 * Call should free returned descriptor with LocalFree
4488 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4490 PSID *sidlist;
4491 PSID cur_user = NULL;
4492 BYTE tuUser[2000];
4493 DWORD acl_size;
4494 int sid_count, i;
4495 PSECURITY_DESCRIPTOR psd = NULL;
4497 TRACE("%p %d\n", apUserPerm, cUserPerm);
4499 if (apUserPerm == NULL || cUserPerm <= 0)
4500 return NULL;
4502 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
4503 if (!sidlist)
4504 return NULL;
4506 acl_size = sizeof(ACL);
4508 for(sid_count = 0; sid_count < cUserPerm; sid_count++)
4510 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
4511 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
4512 PSHELL_USER_SID sid = &perm->susID;
4513 PSID pSid;
4514 BOOL ret = TRUE;
4516 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4517 { /* current user's SID */
4518 if (!cur_user)
4520 HANDLE Token;
4521 DWORD bufsize = sizeof(tuUser);
4523 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4524 if (ret)
4526 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4527 if (ret)
4528 cur_user = ((PTOKEN_USER)tuUser)->User.Sid;
4529 CloseHandle(Token);
4532 pSid = cur_user;
4533 } else if (sid->dwUserID==0) /* one sub-authority */
4534 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
4535 0, 0, 0, 0, 0, 0, &pSid);
4536 else
4537 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4538 0, 0, 0, 0, 0, 0, &pSid);
4539 if (!ret)
4540 goto free_sids;
4542 sidlist[sid_count] = pSid;
4543 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4544 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
4547 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
4549 if (psd != NULL)
4551 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4553 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4554 goto error;
4556 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4557 goto error;
4559 for(i = 0; i < sid_count; i++)
4561 PSHELL_USER_PERMISSION sup = apUserPerm[i];
4562 PSID sid = sidlist[i];
4564 switch(sup->dwAccessType)
4566 case ACCESS_ALLOWED_ACE_TYPE:
4567 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4568 goto error;
4569 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4570 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4571 goto error;
4572 break;
4573 case ACCESS_DENIED_ACE_TYPE:
4574 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4575 goto error;
4576 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4577 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4578 goto error;
4579 break;
4580 default:
4581 goto error;
4585 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4586 goto error;
4588 goto free_sids;
4590 error:
4591 LocalFree(psd);
4592 psd = NULL;
4593 free_sids:
4594 for(i = 0; i < sid_count; i++)
4596 if (!cur_user || sidlist[i] != cur_user)
4597 FreeSid(sidlist[i]);
4599 HeapFree(GetProcessHeap(), 0, sidlist);
4601 return psd;
4604 /***********************************************************************
4605 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4607 * Creates a property bag from a registry key
4609 * PARAMS
4610 * hKey [I] Handle to the desired registry key
4611 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4612 * grfMode [I] Optional flags
4613 * riid [I] IID of requested property bag interface
4614 * ppv [O] Address to receive pointer to the new interface
4616 * RETURNS
4617 * success: 0
4618 * failure: error code
4621 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey,
4622 DWORD grfMode, REFIID riid, void **ppv)
4624 FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode,
4625 debugstr_guid(riid), ppv);
4627 return E_NOTIMPL;
4630 /***********************************************************************
4631 * SHGetViewStatePropertyBag [SHLWAPI.515]
4633 * Retrieves a property bag in which the view state information of a folder
4634 * can be stored.
4636 * PARAMS
4637 * pidl [I] PIDL of the folder requested
4638 * bag_name [I] Name of the property bag requested
4639 * flags [I] Optional flags
4640 * riid [I] IID of requested property bag interface
4641 * ppv [O] Address to receive pointer to the new interface
4643 * RETURNS
4644 * success: S_OK
4645 * failure: error code
4648 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
4649 DWORD flags, REFIID riid, void **ppv)
4651 FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags,
4652 debugstr_guid(riid), ppv);
4654 return E_NOTIMPL;
4657 /***********************************************************************
4658 * SHFormatDateTimeW [SHLWAPI.354]
4660 * Produces a string representation of a time.
4662 * PARAMS
4663 * fileTime [I] Pointer to FILETIME structure specifying the time
4664 * flags [I] Flags specifying the desired output
4665 * buf [O] Pointer to buffer for output
4666 * size [I] Number of characters that can be contained in buffer
4668 * RETURNS
4669 * success: number of characters written to the buffer
4670 * failure: 0
4673 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
4674 LPWSTR buf, UINT size)
4676 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
4677 DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT;
4678 SYSTEMTIME st;
4679 FILETIME ft;
4680 INT ret = 0;
4682 TRACE("%p %p %p %u\n", fileTime, flags, buf, size);
4684 if (!buf || !size)
4685 return 0;
4687 if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS)
4688 FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS);
4690 FileTimeToLocalFileTime(fileTime, &ft);
4691 FileTimeToSystemTime(&ft, &st);
4693 /* first of all date */
4694 if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE))
4696 static const WCHAR sep1[] = {',',' ',0};
4697 static const WCHAR sep2[] = {' ',0};
4699 DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE;
4700 ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size);
4701 if (ret >= size) return ret;
4703 /* add separator */
4704 if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)))
4706 if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2))
4708 if (ret < size + 2)
4710 lstrcatW(&buf[ret-1], sep1);
4711 ret += 2;
4714 else
4716 lstrcatW(&buf[ret-1], sep2);
4717 ret++;
4721 /* time part */
4722 if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))
4724 DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS;
4726 if (ret) ret--;
4727 ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret);
4730 return ret;
4732 #undef SHFORMATDT_UNSUPPORTED_FLAGS
4735 /***********************************************************************
4736 * SHFormatDateTimeA [SHLWAPI.353]
4738 * See SHFormatDateTimeW.
4741 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags,
4742 LPSTR buf, UINT size)
4744 WCHAR *bufW;
4745 INT retval;
4747 if (!buf || !size)
4748 return 0;
4750 bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
4751 retval = SHFormatDateTimeW(fileTime, flags, bufW, size);
4753 if (retval != 0)
4754 WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL);
4756 HeapFree(GetProcessHeap(), 0, bufW);
4757 return retval;
4760 /***********************************************************************
4761 * ZoneCheckUrlExW [SHLWAPI.231]
4763 * Checks the details of the security zone for the supplied site. (?)
4765 * PARAMS
4767 * szURL [I] Pointer to the URL to check
4769 * Other parameters currently unknown.
4771 * RETURNS
4772 * unknown
4775 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2,
4776 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6,
4777 DWORD dwUnknown7)
4779 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2,
4780 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7);
4782 return 0;
4785 /***********************************************************************
4786 * SHVerbExistsNA [SHLWAPI.196]
4789 * PARAMS
4791 * verb [I] a string, often appears to be an extension.
4793 * Other parameters currently unknown.
4795 * RETURNS
4796 * unknown
4798 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3)
4800 FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3);
4801 return 0;
4804 /*************************************************************************
4805 * @ [SHLWAPI.538]
4807 * Undocumented: Implementation guessed at via Name and behavior
4809 * PARAMS
4810 * lpUnknown [I] Object to get an IServiceProvider interface from
4811 * riid [I] Function requested for QueryService call
4812 * lppOut [O] Destination for the service interface pointer
4814 * RETURNS
4815 * Success: S_OK. lppOut contains an object providing the requested service
4816 * Failure: An HRESULT error code
4818 * NOTES
4819 * lpUnknown is expected to support the IServiceProvider interface.
4821 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown,
4822 REFGUID riid, LPVOID *lppOut)
4824 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut);
4825 return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut);
4828 /**************************************************************************
4829 * SHPropertyBag_ReadLONG (SHLWAPI.496)
4831 * This function asks a property bag to read a named property as a LONG.
4833 * PARAMS
4834 * ppb: a IPropertyBag interface
4835 * pszPropName: Unicode string that names the property
4836 * pValue: address to receive the property value as a 32-bit signed integer
4838 * RETURNS
4839 * 0 for Success
4841 BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue)
4843 VARIANT var;
4844 HRESULT hr;
4845 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue);
4846 if (!pszPropName || !ppb || !pValue)
4847 return E_INVALIDARG;
4848 V_VT(&var) = VT_I4;
4849 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
4850 if (SUCCEEDED(hr))
4852 if (V_VT(&var) == VT_I4)
4853 *pValue = V_I4(&var);
4854 else
4855 hr = DISP_E_BADVARTYPE;
4857 return hr;
4860 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
4861 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
4862 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
4863 #define OBJCOMPAT_UNBINDABLE 0x00000004
4864 #define OBJCOMPAT_PINDLL 0x00000008
4865 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
4866 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
4867 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
4868 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
4869 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
4870 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
4871 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
4872 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
4873 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
4875 /* a search table for compatibility flags */
4876 struct objcompat_entry {
4877 const WCHAR name[30];
4878 DWORD value;
4881 /* expected to be sorted by name */
4882 static const struct objcompat_entry objcompat_table[] = {
4883 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
4884 OBJCOMPAT_COCREATESHELLFOLDERONLY },
4885 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
4886 OBJCOMPAT_CTXMENU_LIMITEDQI },
4887 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
4888 OBJCOMPAT_CTXMENU_LIMITEDQI },
4889 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
4890 OBJCOMPAT_CTXMENU_XPQCMFLAGS },
4891 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
4892 OBJCOMPAT_NEEDSFILESYSANCESTOR },
4893 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
4894 OBJCOMPAT_NEEDSSTORAGEANCESTOR },
4895 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
4896 OBJCOMPAT_NOIPROPERTYSTORE },
4897 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
4898 OBJCOMPAT_NOLEGACYWEBVIEW },
4899 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
4900 OBJCOMPAT_NOTAFILESYSTEM },
4901 { {'N','O','_','W','E','B','V','I','E','W',0},
4902 OBJCOMPAT_NO_WEBVIEW },
4903 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
4904 OBJCOMPAT_OTNEEDSSFCACHE },
4905 { {'P','I','N','D','L','L',0},
4906 OBJCOMPAT_PINDLL },
4907 { {'U','N','B','I','N','D','A','B','L','E',0},
4908 OBJCOMPAT_UNBINDABLE }
4911 /**************************************************************************
4912 * SHGetObjectCompatFlags (SHLWAPI.476)
4914 * Function returns an integer representation of compatibility flags stored
4915 * in registry for CLSID under ShellCompatibility subkey.
4917 * PARAMS
4918 * pUnk: pointer to object IUnknown interface, idetifies CLSID
4919 * clsid: pointer to CLSID to retrieve data for
4921 * RETURNS
4922 * 0 on failure, flags set on success
4924 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid)
4926 static const WCHAR compatpathW[] =
4927 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4928 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4929 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
4930 'O','b','j','e','c','t','s','\\','%','s',0};
4931 WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */];
4932 DWORD ret, length = sizeof(strW)/sizeof(WCHAR);
4933 OLECHAR *clsid_str;
4934 HKEY key;
4935 INT i;
4937 TRACE("%p %s\n", pUnk, debugstr_guid(clsid));
4939 if (!pUnk && !clsid) return 0;
4941 if (pUnk && !clsid)
4943 FIXME("iface not handled\n");
4944 return 0;
4947 StringFromCLSID(clsid, &clsid_str);
4948 sprintfW(strW, compatpathW, clsid_str);
4949 CoTaskMemFree(clsid_str);
4951 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key);
4952 if (ret != ERROR_SUCCESS) return 0;
4954 /* now collect flag values */
4955 ret = 0;
4956 for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++)
4958 INT left, right, res, x;
4960 /* search in table */
4961 left = 0;
4962 right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1;
4964 while (right >= left) {
4965 x = (left + right) / 2;
4966 res = strcmpW(strW, objcompat_table[x].name);
4967 if (res == 0)
4969 ret |= objcompat_table[x].value;
4970 break;
4972 else if (res < 0)
4973 right = x - 1;
4974 else
4975 left = x + 1;
4978 length = sizeof(strW)/sizeof(WCHAR);
4981 return ret;