shlwapi: Fix interface leaks in SHIsSameObject.
[wine/multimedia.git] / dlls / shlwapi / ordinal.c
blob70c32856d00b8e062ae0996a48ba4f28c72afeff
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 hr;
313 IWebBrowserApp* pBrowser;
315 TRACE("(%p, %p)\n", lpBC, lpUnknown);
317 hr = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (void**)&pBrowser);
318 if (FAILED(hr))
319 return hr;
321 V_VT(&var) = VT_EMPTY;
323 /* The property we get is the browsers clipboard enumerator */
324 property = SysAllocString(szProperty);
325 hr = IWebBrowserApp_GetProperty(pBrowser, property, &var);
326 SysFreeString(property);
327 if (FAILED(hr)) goto exit;
329 if (V_VT(&var) == VT_EMPTY)
331 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
332 char szKeyBuff[128], szValueBuff[128];
333 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
334 FORMATETC* formatList, *format;
335 HKEY hDocs;
337 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
339 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
340 "Version\\Internet Settings\\Accepted Documents", &hDocs))
342 hr = E_FAIL;
343 goto exit;
346 /* Get count of values in key */
347 while (!dwRet)
349 dwKeySize = sizeof(szKeyBuff);
350 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
351 dwCount++;
354 dwNumValues = dwCount;
356 /* Note: dwCount = number of items + 1; The extra item is the end node */
357 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
358 if (!formatList)
360 RegCloseKey(hDocs);
361 hr = E_OUTOFMEMORY;
362 goto exit;
365 if (dwNumValues > 1)
367 dwRet = 0;
368 dwCount = 0;
370 dwNumValues--;
372 /* Register clipboard formats for the values and populate format list */
373 while(!dwRet && dwCount < dwNumValues)
375 dwKeySize = sizeof(szKeyBuff);
376 dwValueSize = sizeof(szValueBuff);
377 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
378 (PBYTE)szValueBuff, &dwValueSize);
379 if (!dwRet)
381 HeapFree(GetProcessHeap(), 0, formatList);
382 RegCloseKey(hDocs);
383 hr = E_FAIL;
384 goto exit;
387 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
388 format->ptd = NULL;
389 format->dwAspect = 1;
390 format->lindex = 4;
391 format->tymed = -1;
393 format++;
394 dwCount++;
398 RegCloseKey(hDocs);
400 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
401 format->cfFormat = 0;
402 format->ptd = NULL;
403 format->dwAspect = 1;
404 format->lindex = 4;
405 format->tymed = -1;
407 /* Create a clipboard enumerator */
408 hr = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
409 HeapFree(GetProcessHeap(), 0, formatList);
410 if (FAILED(hr)) goto exit;
412 /* Set our enumerator as the browsers property */
413 V_VT(&var) = VT_UNKNOWN;
414 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
416 property = SysAllocString(szProperty);
417 hr = IWebBrowserApp_PutProperty(pBrowser, property, var);
418 SysFreeString(property);
419 if (FAILED(hr))
421 IEnumFORMATETC_Release(pIEnumFormatEtc);
422 goto exit;
426 if (V_VT(&var) == VT_UNKNOWN)
428 /* Our variant is holding the clipboard enumerator */
429 IUnknown* pIUnknown = V_UNKNOWN(&var);
430 IEnumFORMATETC* pClone = NULL;
432 TRACE("Retrieved IEnumFORMATETC property\n");
434 /* Get an IEnumFormatEtc interface from the variants value */
435 pIEnumFormatEtc = NULL;
436 hr = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC, (void**)&pIEnumFormatEtc);
437 if (hr == S_OK && pIEnumFormatEtc)
439 /* Clone and register the enumerator */
440 hr = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
441 if (hr == S_OK && pClone)
443 RegisterFormatEnumerator(lpBC, pClone, 0);
445 IEnumFORMATETC_Release(pClone);
448 IEnumFORMATETC_Release(pIUnknown);
450 IUnknown_Release(V_UNKNOWN(&var));
453 exit:
454 IWebBrowserApp_Release(pBrowser);
455 return hr;
458 /*************************************************************************
459 * @ [SHLWAPI.15]
461 * Get Explorers "AcceptLanguage" setting.
463 * PARAMS
464 * langbuf [O] Destination for language string
465 * buflen [I] Length of langbuf in characters
466 * [0] Success: used length of langbuf
468 * RETURNS
469 * Success: S_OK. langbuf is set to the language string found.
470 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
471 * does not contain the setting.
472 * HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), If the buffer is not big enough
474 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
476 static const WCHAR szkeyW[] = {
477 'S','o','f','t','w','a','r','e','\\',
478 'M','i','c','r','o','s','o','f','t','\\',
479 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
480 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
481 static const WCHAR valueW[] = {
482 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
483 DWORD mystrlen, mytype;
484 DWORD len;
485 HKEY mykey;
486 HRESULT retval;
487 LCID mylcid;
488 WCHAR *mystr;
489 LONG lres;
491 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
493 if(!langbuf || !buflen || !*buflen)
494 return E_FAIL;
496 mystrlen = (*buflen > 20) ? *buflen : 20 ;
497 len = mystrlen * sizeof(WCHAR);
498 mystr = HeapAlloc(GetProcessHeap(), 0, len);
499 mystr[0] = 0;
500 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
501 lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
502 RegCloseKey(mykey);
503 len = lstrlenW(mystr);
505 if (!lres && (*buflen > len)) {
506 lstrcpyW(langbuf, mystr);
507 *buflen = len;
508 HeapFree(GetProcessHeap(), 0, mystr);
509 return S_OK;
512 /* Did not find a value in the registry or the user buffer is too small */
513 mylcid = GetUserDefaultLCID();
514 retval = LcidToRfc1766W(mylcid, mystr, mystrlen);
515 len = lstrlenW(mystr);
517 memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
518 HeapFree(GetProcessHeap(), 0, mystr);
520 if (*buflen > len) {
521 *buflen = len;
522 return S_OK;
525 *buflen = 0;
526 return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
529 /*************************************************************************
530 * @ [SHLWAPI.14]
532 * Ascii version of GetAcceptLanguagesW.
534 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
536 WCHAR *langbufW;
537 DWORD buflenW, convlen;
538 HRESULT retval;
540 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
542 if(!langbuf || !buflen || !*buflen) return E_FAIL;
544 buflenW = *buflen;
545 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
546 retval = GetAcceptLanguagesW(langbufW, &buflenW);
548 if (retval == S_OK)
550 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
551 convlen--; /* do not count the terminating 0 */
553 else /* copy partial string anyway */
555 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
556 if (convlen < *buflen)
558 langbuf[convlen] = 0;
559 convlen--; /* do not count the terminating 0 */
561 else
563 convlen = *buflen;
566 *buflen = buflenW ? convlen : 0;
568 HeapFree(GetProcessHeap(), 0, langbufW);
569 return retval;
572 /*************************************************************************
573 * @ [SHLWAPI.23]
575 * Convert a GUID to a string.
577 * PARAMS
578 * guid [I] GUID to convert
579 * lpszDest [O] Destination for string
580 * cchMax [I] Length of output buffer
582 * RETURNS
583 * The length of the string created.
585 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
587 char xguid[40];
588 INT iLen;
590 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
592 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
593 guid->Data1, guid->Data2, guid->Data3,
594 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
595 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
597 iLen = strlen(xguid) + 1;
599 if (iLen > cchMax)
600 return 0;
601 memcpy(lpszDest, xguid, iLen);
602 return iLen;
605 /*************************************************************************
606 * @ [SHLWAPI.24]
608 * Convert a GUID to a string.
610 * PARAMS
611 * guid [I] GUID to convert
612 * str [O] Destination for string
613 * cmax [I] Length of output buffer
615 * RETURNS
616 * The length of the string created.
618 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
620 WCHAR xguid[40];
621 INT iLen;
622 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
623 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
624 'X','%','0','2','X','%','0','2','X','}',0};
626 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
628 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
629 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
630 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
632 iLen = strlenW(xguid) + 1;
634 if (iLen > cchMax)
635 return 0;
636 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
637 return iLen;
640 /*************************************************************************
641 * @ [SHLWAPI.29]
643 * Determine if a Unicode character is a space.
645 * PARAMS
646 * wc [I] Character to check.
648 * RETURNS
649 * TRUE, if wc is a space,
650 * FALSE otherwise.
652 BOOL WINAPI IsCharSpaceW(WCHAR wc)
654 WORD CharType;
656 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
659 /*************************************************************************
660 * @ [SHLWAPI.30]
662 * Determine if a Unicode character is a blank.
664 * PARAMS
665 * wc [I] Character to check.
667 * RETURNS
668 * TRUE, if wc is a blank,
669 * FALSE otherwise.
672 BOOL WINAPI IsCharBlankW(WCHAR wc)
674 WORD CharType;
676 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
679 /*************************************************************************
680 * @ [SHLWAPI.31]
682 * Determine if a Unicode character is punctuation.
684 * PARAMS
685 * wc [I] Character to check.
687 * RETURNS
688 * TRUE, if wc is punctuation,
689 * FALSE otherwise.
691 BOOL WINAPI IsCharPunctW(WCHAR wc)
693 WORD CharType;
695 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
698 /*************************************************************************
699 * @ [SHLWAPI.32]
701 * Determine if a Unicode character is a control character.
703 * PARAMS
704 * wc [I] Character to check.
706 * RETURNS
707 * TRUE, if wc is a control character,
708 * FALSE otherwise.
710 BOOL WINAPI IsCharCntrlW(WCHAR wc)
712 WORD CharType;
714 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
717 /*************************************************************************
718 * @ [SHLWAPI.33]
720 * Determine if a Unicode character is a digit.
722 * PARAMS
723 * wc [I] Character to check.
725 * RETURNS
726 * TRUE, if wc is a digit,
727 * FALSE otherwise.
729 BOOL WINAPI IsCharDigitW(WCHAR wc)
731 WORD CharType;
733 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
736 /*************************************************************************
737 * @ [SHLWAPI.34]
739 * Determine if a Unicode character is a hex digit.
741 * PARAMS
742 * wc [I] Character to check.
744 * RETURNS
745 * TRUE, if wc is a hex digit,
746 * FALSE otherwise.
748 BOOL WINAPI IsCharXDigitW(WCHAR wc)
750 WORD CharType;
752 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
755 /*************************************************************************
756 * @ [SHLWAPI.35]
759 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type)
761 return GetStringTypeW(CT_CTYPE3, src, count, type);
764 /*************************************************************************
765 * @ [SHLWAPI.151]
767 * Compare two Ascii strings up to a given length.
769 * PARAMS
770 * lpszSrc [I] Source string
771 * lpszCmp [I] String to compare to lpszSrc
772 * len [I] Maximum length
774 * RETURNS
775 * A number greater than, less than or equal to 0 depending on whether
776 * lpszSrc is greater than, less than or equal to lpszCmp.
778 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
780 return StrCmpNA(lpszSrc, lpszCmp, len);
783 /*************************************************************************
784 * @ [SHLWAPI.152]
786 * Unicode version of StrCmpNCA.
788 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
790 return StrCmpNW(lpszSrc, lpszCmp, len);
793 /*************************************************************************
794 * @ [SHLWAPI.153]
796 * Compare two Ascii strings up to a given length, ignoring case.
798 * PARAMS
799 * lpszSrc [I] Source string
800 * lpszCmp [I] String to compare to lpszSrc
801 * len [I] Maximum length
803 * RETURNS
804 * A number greater than, less than or equal to 0 depending on whether
805 * lpszSrc is greater than, less than or equal to lpszCmp.
807 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
809 return StrCmpNIA(lpszSrc, lpszCmp, len);
812 /*************************************************************************
813 * @ [SHLWAPI.154]
815 * Unicode version of StrCmpNICA.
817 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
819 return StrCmpNIW(lpszSrc, lpszCmp, len);
822 /*************************************************************************
823 * @ [SHLWAPI.155]
825 * Compare two Ascii strings.
827 * PARAMS
828 * lpszSrc [I] Source string
829 * lpszCmp [I] String to compare to lpszSrc
831 * RETURNS
832 * A number greater than, less than or equal to 0 depending on whether
833 * lpszSrc is greater than, less than or equal to lpszCmp.
835 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
837 return lstrcmpA(lpszSrc, lpszCmp);
840 /*************************************************************************
841 * @ [SHLWAPI.156]
843 * Unicode version of StrCmpCA.
845 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
847 return lstrcmpW(lpszSrc, lpszCmp);
850 /*************************************************************************
851 * @ [SHLWAPI.157]
853 * Compare two Ascii strings, ignoring case.
855 * PARAMS
856 * lpszSrc [I] Source string
857 * lpszCmp [I] String to compare to lpszSrc
859 * RETURNS
860 * A number greater than, less than or equal to 0 depending on whether
861 * lpszSrc is greater than, less than or equal to lpszCmp.
863 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
865 return lstrcmpiA(lpszSrc, lpszCmp);
868 /*************************************************************************
869 * @ [SHLWAPI.158]
871 * Unicode version of StrCmpICA.
873 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
875 return lstrcmpiW(lpszSrc, lpszCmp);
878 /*************************************************************************
879 * @ [SHLWAPI.160]
881 * Get an identification string for the OS and explorer.
883 * PARAMS
884 * lpszDest [O] Destination for Id string
885 * dwDestLen [I] Length of lpszDest
887 * RETURNS
888 * TRUE, If the string was created successfully
889 * FALSE, Otherwise
891 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
893 WCHAR buff[2084];
895 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
897 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
899 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
900 return TRUE;
902 return FALSE;
905 /*************************************************************************
906 * @ [SHLWAPI.161]
908 * Unicode version of SHAboutInfoA.
910 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
912 static const WCHAR szIEKey[] = { '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','\0' };
915 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
916 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
917 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
918 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
919 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
920 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
921 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
922 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
923 ' ','E','x','p','l','o','r','e','r','\\',
924 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
925 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
926 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
927 'V','e','r','s','i','o','n','\0' };
928 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
929 'O','w','n','e','r','\0' };
930 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
931 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
932 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
933 static const WCHAR szUpdate[] = { 'I','E','A','K',
934 'U','p','d','a','t','e','U','r','l','\0' };
935 static const WCHAR szHelp[] = { 'I','E','A','K',
936 'H','e','l','p','S','t','r','i','n','g','\0' };
937 WCHAR buff[2084];
938 HKEY hReg;
939 DWORD dwType, dwLen;
941 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
943 if (!lpszDest)
944 return FALSE;
946 *lpszDest = '\0';
948 /* Try the NT key first, followed by 95/98 key */
949 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
950 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
951 return FALSE;
953 /* OS Version */
954 buff[0] = '\0';
955 dwLen = 30;
956 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
958 DWORD dwStrLen = strlenW(buff);
959 dwLen = 30 - dwStrLen;
960 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
961 szCustomized, &dwType, buff+dwStrLen, &dwLen);
963 StrCatBuffW(lpszDest, buff, dwDestLen);
965 /* ~Registered Owner */
966 buff[0] = '~';
967 dwLen = 256;
968 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
969 buff[1] = '\0';
970 StrCatBuffW(lpszDest, buff, dwDestLen);
972 /* ~Registered Organization */
973 dwLen = 256;
974 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
975 buff[1] = '\0';
976 StrCatBuffW(lpszDest, buff, dwDestLen);
978 /* FIXME: Not sure where this number comes from */
979 buff[0] = '~';
980 buff[1] = '0';
981 buff[2] = '\0';
982 StrCatBuffW(lpszDest, buff, dwDestLen);
984 /* ~Product Id */
985 dwLen = 256;
986 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
987 buff[1] = '\0';
988 StrCatBuffW(lpszDest, buff, dwDestLen);
990 /* ~IE Update Url */
991 dwLen = 2048;
992 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
993 buff[1] = '\0';
994 StrCatBuffW(lpszDest, buff, dwDestLen);
996 /* ~IE Help String */
997 dwLen = 256;
998 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
999 buff[1] = '\0';
1000 StrCatBuffW(lpszDest, buff, dwDestLen);
1002 RegCloseKey(hReg);
1003 return TRUE;
1006 /*************************************************************************
1007 * @ [SHLWAPI.163]
1009 * Call IOleCommandTarget_QueryStatus() on an object.
1011 * PARAMS
1012 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1013 * pguidCmdGroup [I] GUID for the command group
1014 * cCmds [I]
1015 * prgCmds [O] Commands
1016 * pCmdText [O] Command text
1018 * RETURNS
1019 * Success: S_OK.
1020 * Failure: E_FAIL, if lpUnknown is NULL.
1021 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1022 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1024 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1025 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1027 HRESULT hRet = E_FAIL;
1029 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1031 if (lpUnknown)
1033 IOleCommandTarget* lpOle;
1035 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1036 (void**)&lpOle);
1038 if (SUCCEEDED(hRet) && lpOle)
1040 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1041 prgCmds, pCmdText);
1042 IOleCommandTarget_Release(lpOle);
1045 return hRet;
1048 /*************************************************************************
1049 * @ [SHLWAPI.164]
1051 * Call IOleCommandTarget_Exec() on an object.
1053 * PARAMS
1054 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1055 * pguidCmdGroup [I] GUID for the command group
1057 * RETURNS
1058 * Success: S_OK.
1059 * Failure: E_FAIL, if lpUnknown is NULL.
1060 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1061 * Otherwise, an error code from IOleCommandTarget_Exec().
1063 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1064 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1065 VARIANT* pvaOut)
1067 HRESULT hRet = E_FAIL;
1069 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1070 nCmdexecopt, pvaIn, pvaOut);
1072 if (lpUnknown)
1074 IOleCommandTarget* lpOle;
1076 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1077 (void**)&lpOle);
1078 if (SUCCEEDED(hRet) && lpOle)
1080 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1081 nCmdexecopt, pvaIn, pvaOut);
1082 IOleCommandTarget_Release(lpOle);
1085 return hRet;
1088 /*************************************************************************
1089 * @ [SHLWAPI.165]
1091 * Retrieve, modify, and re-set a value from a window.
1093 * PARAMS
1094 * hWnd [I] Window to get value from
1095 * offset [I] Offset of value
1096 * mask [I] Mask for flags
1097 * flags [I] Bits to set in window value
1099 * RETURNS
1100 * The new value as it was set, or 0 if any parameter is invalid.
1102 * NOTES
1103 * Only bits specified in mask are affected - set if present in flags and
1104 * reset otherwise.
1106 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT mask, UINT flags)
1108 LONG ret = GetWindowLongW(hwnd, offset);
1109 LONG new_flags = (flags & mask) | (ret & ~mask);
1111 TRACE("%p %d %x %x\n", hwnd, offset, mask, flags);
1113 if (new_flags != ret)
1114 ret = SetWindowLongW(hwnd, offset, new_flags);
1115 return ret;
1118 /*************************************************************************
1119 * @ [SHLWAPI.167]
1121 * Change a window's parent.
1123 * PARAMS
1124 * hWnd [I] Window to change parent of
1125 * hWndParent [I] New parent window
1127 * RETURNS
1128 * The old parent of hWnd.
1130 * NOTES
1131 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1132 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1134 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1136 TRACE("%p, %p\n", hWnd, hWndParent);
1138 if(GetParent(hWnd) == hWndParent)
1139 return 0;
1141 if(hWndParent)
1142 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1143 else
1144 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1146 return SetParent(hWnd, hWndParent);
1149 /*************************************************************************
1150 * @ [SHLWAPI.168]
1152 * Locate and advise a connection point in an IConnectionPointContainer object.
1154 * PARAMS
1155 * lpUnkSink [I] Sink for the connection point advise call
1156 * riid [I] REFIID of connection point to advise
1157 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1158 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1159 * lpCookie [O] Pointer to connection point cookie
1160 * lppCP [O] Destination for the IConnectionPoint found
1162 * RETURNS
1163 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1164 * that was advised. The caller is responsible for releasing it.
1165 * Failure: E_FAIL, if any arguments are invalid.
1166 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1167 * Or an HRESULT error code if any call fails.
1169 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL fConnect,
1170 IUnknown* lpUnknown, LPDWORD lpCookie,
1171 IConnectionPoint **lppCP)
1173 HRESULT hRet;
1174 IConnectionPointContainer* lpContainer;
1175 IConnectionPoint *lpCP;
1177 if(!lpUnknown || (fConnect && !lpUnkSink))
1178 return E_FAIL;
1180 if(lppCP)
1181 *lppCP = NULL;
1183 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1184 (void**)&lpContainer);
1185 if (SUCCEEDED(hRet))
1187 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1189 if (SUCCEEDED(hRet))
1191 if(!fConnect)
1192 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1193 else
1194 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1196 if (FAILED(hRet))
1197 *lpCookie = 0;
1199 if (lppCP && SUCCEEDED(hRet))
1200 *lppCP = lpCP; /* Caller keeps the interface */
1201 else
1202 IConnectionPoint_Release(lpCP); /* Release it */
1205 IUnknown_Release(lpContainer);
1207 return hRet;
1210 /*************************************************************************
1211 * @ [SHLWAPI.169]
1213 * Release an interface and zero a supplied pointer.
1215 * PARAMS
1216 * lpUnknown [I] Object to release
1218 * RETURNS
1219 * Nothing.
1221 void WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1223 TRACE("(%p)\n", lpUnknown);
1225 if(!lpUnknown || !*lpUnknown) return;
1227 TRACE("doing Release\n");
1229 IUnknown_Release(*lpUnknown);
1230 *lpUnknown = NULL;
1233 /*************************************************************************
1234 * @ [SHLWAPI.170]
1236 * Skip '//' if present in a string.
1238 * PARAMS
1239 * lpszSrc [I] String to check for '//'
1241 * RETURNS
1242 * Success: The next character after the '//' or the string if not present
1243 * Failure: NULL, if lpszStr is NULL.
1245 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1247 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1248 lpszSrc += 2;
1249 return lpszSrc;
1252 /*************************************************************************
1253 * @ [SHLWAPI.171]
1255 * Check if two interfaces come from the same object.
1257 * PARAMS
1258 * lpInt1 [I] Interface to check against lpInt2.
1259 * lpInt2 [I] Interface to check against lpInt1.
1261 * RETURNS
1262 * TRUE, If the interfaces come from the same object.
1263 * FALSE Otherwise.
1265 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1267 IUnknown *lpUnknown1, *lpUnknown2;
1268 BOOL ret;
1270 TRACE("(%p %p)\n", lpInt1, lpInt2);
1272 if (!lpInt1 || !lpInt2)
1273 return FALSE;
1275 if (lpInt1 == lpInt2)
1276 return TRUE;
1278 if (IUnknown_QueryInterface(lpInt1, &IID_IUnknown, (void**)&lpUnknown1) != S_OK)
1279 return FALSE;
1281 if (IUnknown_QueryInterface(lpInt2, &IID_IUnknown, (void**)&lpUnknown2) != S_OK)
1283 IUnknown_Release(lpUnknown1);
1284 return FALSE;
1287 ret = lpUnknown1 == lpUnknown2;
1289 IUnknown_Release(lpUnknown1);
1290 IUnknown_Release(lpUnknown2);
1292 return ret;
1295 /*************************************************************************
1296 * @ [SHLWAPI.172]
1298 * Get the window handle of an object.
1300 * PARAMS
1301 * lpUnknown [I] Object to get the window handle of
1302 * lphWnd [O] Destination for window handle
1304 * RETURNS
1305 * Success: S_OK. lphWnd contains the objects window handle.
1306 * Failure: An HRESULT error code.
1308 * NOTES
1309 * lpUnknown is expected to support one of the following interfaces:
1310 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1312 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1314 IUnknown *lpOle;
1315 HRESULT hRet = E_FAIL;
1317 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1319 if (!lpUnknown)
1320 return hRet;
1322 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1324 if (FAILED(hRet))
1326 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1328 if (FAILED(hRet))
1330 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1331 (void**)&lpOle);
1335 if (SUCCEEDED(hRet))
1337 /* Lazyness here - Since GetWindow() is the first method for the above 3
1338 * interfaces, we use the same call for them all.
1340 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1341 IUnknown_Release(lpOle);
1342 if (lphWnd)
1343 TRACE("Returning HWND=%p\n", *lphWnd);
1346 return hRet;
1349 /*************************************************************************
1350 * @ [SHLWAPI.173]
1352 * Call a method on as as yet unidentified object.
1354 * PARAMS
1355 * pUnk [I] Object supporting the unidentified interface,
1356 * arg [I] Argument for the call on the object.
1358 * RETURNS
1359 * S_OK.
1361 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1363 static const GUID guid_173 = {
1364 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1366 IMalloc *pUnk2;
1368 TRACE("(%p,%d)\n", pUnk, arg);
1370 /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1371 * We use this interface as its vtable entry is compatible with the
1372 * object in question.
1373 * FIXME: Find out what this object is and where it should be defined.
1375 if (pUnk &&
1376 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1378 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1379 IMalloc_Release(pUnk2);
1381 return S_OK;
1384 /*************************************************************************
1385 * @ [SHLWAPI.174]
1387 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1388 * an object.
1391 HRESULT WINAPI IUnknown_SetSite(
1392 IUnknown *obj, /* [in] OLE object */
1393 IUnknown *site) /* [in] Site interface */
1395 HRESULT hr;
1396 IObjectWithSite *iobjwithsite;
1397 IInternetSecurityManager *isecmgr;
1399 if (!obj) return E_FAIL;
1401 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1402 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1403 if (SUCCEEDED(hr))
1405 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1406 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1407 IUnknown_Release(iobjwithsite);
1409 else
1411 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1412 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1413 if (FAILED(hr)) return hr;
1415 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1416 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1417 IUnknown_Release(isecmgr);
1419 return hr;
1422 /*************************************************************************
1423 * @ [SHLWAPI.175]
1425 * Call IPersist_GetClassID() on an object.
1427 * PARAMS
1428 * lpUnknown [I] Object supporting the IPersist interface
1429 * lpClassId [O] Destination for Class Id
1431 * RETURNS
1432 * Success: S_OK. lpClassId contains the Class Id requested.
1433 * Failure: E_FAIL, If lpUnknown is NULL,
1434 * E_NOINTERFACE If lpUnknown does not support IPersist,
1435 * Or an HRESULT error code.
1437 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1439 IPersist* lpPersist;
1440 HRESULT hRet = E_FAIL;
1442 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1444 if (lpUnknown)
1446 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1447 if (SUCCEEDED(hRet))
1449 IPersist_GetClassID(lpPersist, lpClassId);
1450 IPersist_Release(lpPersist);
1453 return hRet;
1456 /*************************************************************************
1457 * @ [SHLWAPI.176]
1459 * Retrieve a Service Interface from an object.
1461 * PARAMS
1462 * lpUnknown [I] Object to get an IServiceProvider interface from
1463 * sid [I] Service ID for IServiceProvider_QueryService() call
1464 * riid [I] Function requested for QueryService call
1465 * lppOut [O] Destination for the service interface pointer
1467 * RETURNS
1468 * Success: S_OK. lppOut contains an object providing the requested service
1469 * Failure: An HRESULT error code
1471 * NOTES
1472 * lpUnknown is expected to support the IServiceProvider interface.
1474 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1475 LPVOID *lppOut)
1477 IServiceProvider* pService = NULL;
1478 HRESULT hRet;
1480 if (!lppOut)
1481 return E_FAIL;
1483 *lppOut = NULL;
1485 if (!lpUnknown)
1486 return E_FAIL;
1488 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1489 (LPVOID*)&pService);
1491 if (hRet == S_OK && pService)
1493 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1495 /* Get a Service interface from the object */
1496 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1498 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1500 IUnknown_Release(pService);
1502 return hRet;
1505 /*************************************************************************
1506 * @ [SHLWAPI.484]
1508 * Calls IOleCommandTarget::Exec() for specified service object.
1510 * PARAMS
1511 * lpUnknown [I] Object to get an IServiceProvider interface from
1512 * service [I] Service ID for IServiceProvider_QueryService() call
1513 * group [I] Group ID for IOleCommandTarget::Exec() call
1514 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1515 * cmdOpt [I] Options flags for command
1516 * pIn [I] Input arguments for command
1517 * pOut [O] Output arguments for command
1519 * RETURNS
1520 * Success: S_OK. lppOut contains an object providing the requested service
1521 * Failure: An HRESULT error code
1523 * NOTES
1524 * lpUnknown is expected to support the IServiceProvider interface.
1526 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *lpUnknown, REFIID service,
1527 const GUID *group, DWORD cmdId, DWORD cmdOpt, VARIANT *pIn, VARIANT *pOut)
1529 IOleCommandTarget *target;
1530 HRESULT hr;
1532 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown, debugstr_guid(service),
1533 debugstr_guid(group), cmdId, cmdOpt, pIn, pOut);
1535 hr = IUnknown_QueryService(lpUnknown, service, &IID_IOleCommandTarget, (void**)&target);
1536 if (hr == S_OK)
1538 hr = IOleCommandTarget_Exec(target, group, cmdId, cmdOpt, pIn, pOut);
1539 IOleCommandTarget_Release(target);
1542 TRACE("<-- hr=0x%08x\n", hr);
1544 return hr;
1547 /*************************************************************************
1548 * @ [SHLWAPI.514]
1550 * Calls IProfferService methods to proffer/revoke specified service.
1552 * PARAMS
1553 * lpUnknown [I] Object to get an IServiceProvider interface from
1554 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1555 * pService [I] Service to proffer. If NULL ::Revoke is called
1556 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1558 * RETURNS
1559 * Success: S_OK. IProffer method returns S_OK
1560 * Failure: An HRESULT error code
1562 * NOTES
1563 * lpUnknown is expected to support the IServiceProvider interface.
1565 HRESULT WINAPI IUnknown_ProfferService(IUnknown *lpUnknown, REFGUID service, IServiceProvider *pService, DWORD *pCookie)
1567 IProfferService *proffer;
1568 HRESULT hr;
1570 TRACE("%p %s %p %p\n", lpUnknown, debugstr_guid(service), pService, pCookie);
1572 hr = IUnknown_QueryService(lpUnknown, &IID_IProfferService, &IID_IProfferService, (void**)&proffer);
1573 if (hr == S_OK)
1575 if (pService)
1576 hr = IProfferService_ProfferService(proffer, service, pService, pCookie);
1577 else
1578 hr = IProfferService_RevokeService(proffer, *pCookie);
1580 IProfferService_Release(proffer);
1583 return hr;
1586 /*************************************************************************
1587 * @ [SHLWAPI.479]
1589 * Call an object's UIActivateIO method.
1591 * PARAMS
1592 * unknown [I] Object to call the UIActivateIO method on
1593 * activate [I] Parameter for UIActivateIO call
1594 * msg [I] Parameter for UIActivateIO call
1596 * RETURNS
1597 * Success: Value of UI_ActivateIO call
1598 * Failure: An HRESULT error code
1600 * NOTES
1601 * unknown is expected to support the IInputObject interface.
1603 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg)
1605 IInputObject* object = NULL;
1606 HRESULT ret;
1608 if (!unknown)
1609 return E_FAIL;
1611 /* Get an IInputObject interface from the object */
1612 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
1614 if (ret == S_OK)
1616 ret = IInputObject_UIActivateIO(object, activate, msg);
1617 IUnknown_Release(object);
1620 return ret;
1623 /*************************************************************************
1624 * @ [SHLWAPI.177]
1626 * Loads a popup menu.
1628 * PARAMS
1629 * hInst [I] Instance handle
1630 * szName [I] Menu name
1632 * RETURNS
1633 * Success: TRUE.
1634 * Failure: FALSE.
1636 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1638 HMENU hMenu;
1640 if ((hMenu = LoadMenuW(hInst, szName)))
1642 if (GetSubMenu(hMenu, 0))
1643 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1645 DestroyMenu(hMenu);
1646 return TRUE;
1648 return FALSE;
1651 typedef struct _enumWndData
1653 UINT uiMsgId;
1654 WPARAM wParam;
1655 LPARAM lParam;
1656 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1657 } enumWndData;
1659 /* Callback for SHLWAPI_178 */
1660 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1662 enumWndData *data = (enumWndData *)lParam;
1664 TRACE("(%p,%p)\n", hWnd, data);
1665 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1666 return TRUE;
1669 /*************************************************************************
1670 * @ [SHLWAPI.178]
1672 * Send or post a message to every child of a window.
1674 * PARAMS
1675 * hWnd [I] Window whose children will get the messages
1676 * uiMsgId [I] Message Id
1677 * wParam [I] WPARAM of message
1678 * lParam [I] LPARAM of message
1679 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1681 * RETURNS
1682 * Nothing.
1684 * NOTES
1685 * The appropriate ASCII or Unicode function is called for the window.
1687 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1689 enumWndData data;
1691 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1693 if(hWnd)
1695 data.uiMsgId = uiMsgId;
1696 data.wParam = wParam;
1697 data.lParam = lParam;
1699 if (bSend)
1700 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1701 else
1702 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1704 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1708 /*************************************************************************
1709 * @ [SHLWAPI.180]
1711 * Remove all sub-menus from a menu.
1713 * PARAMS
1714 * hMenu [I] Menu to remove sub-menus from
1716 * RETURNS
1717 * Success: 0. All sub-menus under hMenu are removed
1718 * Failure: -1, if any parameter is invalid
1720 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1722 int iItemCount = GetMenuItemCount(hMenu) - 1;
1723 while (iItemCount >= 0)
1725 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1726 if (hSubMenu)
1727 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1728 iItemCount--;
1730 return iItemCount;
1733 /*************************************************************************
1734 * @ [SHLWAPI.181]
1736 * Enable or disable a menu item.
1738 * PARAMS
1739 * hMenu [I] Menu holding menu item
1740 * uID [I] ID of menu item to enable/disable
1741 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1743 * RETURNS
1744 * The return code from EnableMenuItem.
1746 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1748 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1751 /*************************************************************************
1752 * @ [SHLWAPI.182]
1754 * Check or uncheck a menu item.
1756 * PARAMS
1757 * hMenu [I] Menu holding menu item
1758 * uID [I] ID of menu item to check/uncheck
1759 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1761 * RETURNS
1762 * The return code from CheckMenuItem.
1764 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1766 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1769 /*************************************************************************
1770 * @ [SHLWAPI.183]
1772 * Register a window class if it isn't already.
1774 * PARAMS
1775 * lpWndClass [I] Window class to register
1777 * RETURNS
1778 * The result of the RegisterClassA call.
1780 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1782 WNDCLASSA wca;
1783 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1784 return TRUE;
1785 return (DWORD)RegisterClassA(wndclass);
1788 /*************************************************************************
1789 * @ [SHLWAPI.186]
1791 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1792 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1794 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1795 POINTL pt = { 0, 0 };
1797 if (!lpPt)
1798 lpPt = &pt;
1800 if (!pdwEffect)
1801 pdwEffect = &dwEffect;
1803 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1805 if (*pdwEffect)
1806 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1808 IDropTarget_DragLeave(pDrop);
1809 return TRUE;
1812 /*************************************************************************
1813 * @ [SHLWAPI.187]
1815 * Call IPersistPropertyBag_Load() on an object.
1817 * PARAMS
1818 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1819 * lpPropBag [O] Destination for loaded IPropertyBag
1821 * RETURNS
1822 * Success: S_OK.
1823 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1825 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1827 IPersistPropertyBag* lpPPBag;
1828 HRESULT hRet = E_FAIL;
1830 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1832 if (lpUnknown)
1834 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1835 (void**)&lpPPBag);
1836 if (SUCCEEDED(hRet) && lpPPBag)
1838 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1839 IPersistPropertyBag_Release(lpPPBag);
1842 return hRet;
1845 /*************************************************************************
1846 * @ [SHLWAPI.188]
1848 * Call IOleControlSite_TranslateAccelerator() on an object.
1850 * PARAMS
1851 * lpUnknown [I] Object supporting the IOleControlSite interface.
1852 * lpMsg [I] Key message to be processed.
1853 * dwModifiers [I] Flags containing the state of the modifier keys.
1855 * RETURNS
1856 * Success: S_OK.
1857 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1859 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1861 IOleControlSite* lpCSite = NULL;
1862 HRESULT hRet = E_INVALIDARG;
1864 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1865 if (lpUnknown)
1867 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1868 (void**)&lpCSite);
1869 if (SUCCEEDED(hRet) && lpCSite)
1871 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1872 IOleControlSite_Release(lpCSite);
1875 return hRet;
1879 /*************************************************************************
1880 * @ [SHLWAPI.189]
1882 * Call IOleControlSite_OnFocus() on an object.
1884 * PARAMS
1885 * lpUnknown [I] Object supporting the IOleControlSite interface.
1886 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1888 * RETURNS
1889 * Success: S_OK.
1890 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1892 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
1894 IOleControlSite* lpCSite = NULL;
1895 HRESULT hRet = E_FAIL;
1897 TRACE("(%p,%s)\n", lpUnknown, fGotFocus ? "TRUE" : "FALSE");
1898 if (lpUnknown)
1900 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1901 (void**)&lpCSite);
1902 if (SUCCEEDED(hRet) && lpCSite)
1904 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1905 IOleControlSite_Release(lpCSite);
1908 return hRet;
1911 /*************************************************************************
1912 * @ [SHLWAPI.190]
1914 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1915 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1917 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1918 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1919 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1920 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1921 HRESULT hRet = E_INVALIDARG;
1922 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1924 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1926 if (lpUnknown && lpArg4)
1928 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1929 (REFGUID)function_id, (void**)&lpUnkInner);
1931 if (SUCCEEDED(hRet) && lpUnkInner)
1933 /* FIXME: The type of service object requested is unknown, however
1934 * testing shows that its first method is called with 4 parameters.
1935 * Fake this by using IParseDisplayName_ParseDisplayName since the
1936 * signature and position in the vtable matches our unknown object type.
1938 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1939 lpArg1, lpArg2, lpArg3, lpArg4);
1940 IUnknown_Release(lpUnkInner);
1943 return hRet;
1946 /*************************************************************************
1947 * @ [SHLWAPI.192]
1949 * Get a sub-menu from a menu item.
1951 * PARAMS
1952 * hMenu [I] Menu to get sub-menu from
1953 * uID [I] ID of menu item containing sub-menu
1955 * RETURNS
1956 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1958 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1960 MENUITEMINFOW mi;
1962 TRACE("(%p,%u)\n", hMenu, uID);
1964 mi.cbSize = sizeof(mi);
1965 mi.fMask = MIIM_SUBMENU;
1967 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1968 return NULL;
1970 return mi.hSubMenu;
1973 /*************************************************************************
1974 * @ [SHLWAPI.193]
1976 * Get the color depth of the primary display.
1978 * PARAMS
1979 * None.
1981 * RETURNS
1982 * The color depth of the primary display.
1984 DWORD WINAPI SHGetCurColorRes(void)
1986 HDC hdc;
1987 DWORD ret;
1989 TRACE("()\n");
1991 hdc = GetDC(0);
1992 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1993 ReleaseDC(0, hdc);
1994 return ret;
1997 /*************************************************************************
1998 * @ [SHLWAPI.194]
2000 * Wait for a message to arrive, with a timeout.
2002 * PARAMS
2003 * hand [I] Handle to query
2004 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
2006 * RETURNS
2007 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
2008 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
2009 * message is available.
2011 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
2013 DWORD dwEndTicks = GetTickCount() + dwTimeout;
2014 DWORD dwRet;
2016 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
2018 MSG msg;
2020 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
2022 if (dwTimeout != INFINITE)
2024 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
2025 return WAIT_TIMEOUT;
2029 return dwRet;
2032 /*************************************************************************
2033 * @ [SHLWAPI.195]
2035 * Determine if a shell folder can be expanded.
2037 * PARAMS
2038 * lpFolder [I] Parent folder containing the object to test.
2039 * pidl [I] Id of the object to test.
2041 * RETURNS
2042 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2043 * Failure: E_INVALIDARG, if any argument is invalid.
2045 * NOTES
2046 * If the object to be tested does not expose the IQueryInfo() interface it
2047 * will not be identified as an expandable folder.
2049 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
2051 HRESULT hRet = E_INVALIDARG;
2052 IQueryInfo *lpInfo;
2054 if (lpFolder && pidl)
2056 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
2057 NULL, (void**)&lpInfo);
2058 if (FAILED(hRet))
2059 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
2060 else
2062 DWORD dwFlags = 0;
2064 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2065 * currently used". Really? You wouldn't be holding out on me would you?
2067 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
2069 if (SUCCEEDED(hRet))
2071 /* 0x2 is an undocumented flag apparently indicating expandability */
2072 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
2075 IQueryInfo_Release(lpInfo);
2078 return hRet;
2081 /*************************************************************************
2082 * @ [SHLWAPI.197]
2084 * Blank out a region of text by drawing the background only.
2086 * PARAMS
2087 * hDC [I] Device context to draw in
2088 * pRect [I] Area to draw in
2089 * cRef [I] Color to draw in
2091 * RETURNS
2092 * Nothing.
2094 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2096 COLORREF cOldColor = SetBkColor(hDC, cRef);
2097 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2098 SetBkColor(hDC, cOldColor);
2099 return 0;
2102 /*************************************************************************
2103 * @ [SHLWAPI.198]
2105 * Return the value associated with a key in a map.
2107 * PARAMS
2108 * lpKeys [I] A list of keys of length iLen
2109 * lpValues [I] A list of values associated with lpKeys, of length iLen
2110 * iLen [I] Length of both lpKeys and lpValues
2111 * iKey [I] The key value to look up in lpKeys
2113 * RETURNS
2114 * The value in lpValues associated with iKey, or -1 if iKey is not
2115 * found in lpKeys.
2117 * NOTES
2118 * - If two elements in the map share the same key, this function returns
2119 * the value closest to the start of the map
2120 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2122 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2124 if (lpKeys && lpValues)
2126 int i = 0;
2128 while (i < iLen)
2130 if (lpKeys[i] == iKey)
2131 return lpValues[i]; /* Found */
2132 i++;
2135 return -1; /* Not found */
2139 /*************************************************************************
2140 * @ [SHLWAPI.199]
2142 * Copy an interface pointer
2144 * PARAMS
2145 * lppDest [O] Destination for copy
2146 * lpUnknown [I] Source for copy
2148 * RETURNS
2149 * Nothing.
2151 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2153 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2155 if (lppDest)
2156 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2158 if (lpUnknown)
2160 /* Copy */
2161 IUnknown_AddRef(lpUnknown);
2162 *lppDest = lpUnknown;
2166 /*************************************************************************
2167 * @ [SHLWAPI.200]
2170 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2171 REFGUID riidCmdGrp, ULONG cCmds,
2172 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2174 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2175 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2177 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2178 return DRAGDROP_E_NOTREGISTERED;
2181 /*************************************************************************
2182 * @ [SHLWAPI.201]
2185 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2186 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2187 VARIANT* pvaOut)
2189 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2190 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2191 return DRAGDROP_E_NOTREGISTERED;
2194 /*************************************************************************
2195 * @ [SHLWAPI.202]
2198 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2200 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2201 return DRAGDROP_E_NOTREGISTERED;
2204 /*************************************************************************
2205 * @ [SHLWAPI.204]
2207 * Determine if a window is not a child of another window.
2209 * PARAMS
2210 * hParent [I] Suspected parent window
2211 * hChild [I] Suspected child window
2213 * RETURNS
2214 * TRUE: If hChild is a child window of hParent
2215 * FALSE: If hChild is not a child window of hParent, or they are equal
2217 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2219 TRACE("(%p,%p)\n", hParent, hChild);
2221 if (!hParent || !hChild)
2222 return TRUE;
2223 else if(hParent == hChild)
2224 return FALSE;
2225 return !IsChild(hParent, hChild);
2228 /*************************************************************************
2229 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2232 typedef struct
2234 DWORD num_items; /* Number of elements inserted */
2235 void *mem; /* Ptr to array */
2236 DWORD blocks_alloced; /* Number of elements allocated */
2237 BYTE inc; /* Number of elements to grow by when we need to expand */
2238 BYTE block_size; /* Size in bytes of an element */
2239 BYTE flags; /* Flags */
2240 } FDSA_info;
2242 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2244 /*************************************************************************
2245 * @ [SHLWAPI.208]
2247 * Initialize an FDSA array.
2249 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2250 DWORD init_blocks)
2252 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2254 if(inc == 0)
2255 inc = 1;
2257 if(mem)
2258 memset(mem, 0, block_size * init_blocks);
2260 info->num_items = 0;
2261 info->inc = inc;
2262 info->mem = mem;
2263 info->blocks_alloced = init_blocks;
2264 info->block_size = block_size;
2265 info->flags = 0;
2267 return TRUE;
2270 /*************************************************************************
2271 * @ [SHLWAPI.209]
2273 * Destroy an FDSA array
2275 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2277 TRACE("(%p)\n", info);
2279 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2281 HeapFree(GetProcessHeap(), 0, info->mem);
2282 return FALSE;
2285 return TRUE;
2288 /*************************************************************************
2289 * @ [SHLWAPI.210]
2291 * Insert element into an FDSA array
2293 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
2295 TRACE("(%p 0x%08x %p)\n", info, where, block);
2296 if(where > info->num_items)
2297 where = info->num_items;
2299 if(info->num_items >= info->blocks_alloced)
2301 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2302 if(info->flags & 0x1)
2303 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2304 else
2306 void *old_mem = info->mem;
2307 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2308 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2310 info->blocks_alloced += info->inc;
2311 info->flags |= 0x1;
2314 if(where < info->num_items)
2316 memmove((char*)info->mem + (where + 1) * info->block_size,
2317 (char*)info->mem + where * info->block_size,
2318 (info->num_items - where) * info->block_size);
2320 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2322 info->num_items++;
2323 return where;
2326 /*************************************************************************
2327 * @ [SHLWAPI.211]
2329 * Delete an element from an FDSA array.
2331 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2333 TRACE("(%p 0x%08x)\n", info, where);
2335 if(where >= info->num_items)
2336 return FALSE;
2338 if(where < info->num_items - 1)
2340 memmove((char*)info->mem + where * info->block_size,
2341 (char*)info->mem + (where + 1) * info->block_size,
2342 (info->num_items - where - 1) * info->block_size);
2344 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2345 0, info->block_size);
2346 info->num_items--;
2347 return TRUE;
2351 typedef struct {
2352 REFIID refid;
2353 DWORD indx;
2354 } IFACE_INDEX_TBL;
2356 /*************************************************************************
2357 * @ [SHLWAPI.219]
2359 * Call IUnknown_QueryInterface() on a table of objects.
2361 * RETURNS
2362 * Success: S_OK.
2363 * Failure: E_POINTER or E_NOINTERFACE.
2365 HRESULT WINAPI QISearch(
2366 LPVOID w, /* [in] Table of interfaces */
2367 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2368 REFIID riid, /* [in] REFIID to get interface for */
2369 LPVOID *ppv) /* [out] Destination for interface pointer */
2371 HRESULT ret;
2372 IUnknown *a_vtbl;
2373 IFACE_INDEX_TBL *xmove;
2375 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2376 if (ppv) {
2377 xmove = x;
2378 while (xmove->refid) {
2379 TRACE("trying (indx %d) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2380 if (IsEqualIID(riid, xmove->refid)) {
2381 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2382 TRACE("matched, returning (%p)\n", a_vtbl);
2383 *ppv = a_vtbl;
2384 IUnknown_AddRef(a_vtbl);
2385 return S_OK;
2387 xmove++;
2390 if (IsEqualIID(riid, &IID_IUnknown)) {
2391 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2392 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2393 *ppv = a_vtbl;
2394 IUnknown_AddRef(a_vtbl);
2395 return S_OK;
2397 *ppv = 0;
2398 ret = E_NOINTERFACE;
2399 } else
2400 ret = E_POINTER;
2402 TRACE("-- 0x%08x\n", ret);
2403 return ret;
2406 /*************************************************************************
2407 * @ [SHLWAPI.220]
2409 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2411 * PARAMS
2412 * hWnd [I] Parent Window to set the property
2413 * id [I] Index of child Window to set the Font
2415 * RETURNS
2416 * Success: S_OK
2419 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id)
2421 FIXME("(%p, %d) stub\n", hWnd, id);
2422 return S_OK;
2425 /*************************************************************************
2426 * @ [SHLWAPI.221]
2428 * Remove the "PropDlgFont" property from a window.
2430 * PARAMS
2431 * hWnd [I] Window to remove the property from
2433 * RETURNS
2434 * A handle to the removed property, or NULL if it did not exist.
2436 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2438 HANDLE hProp;
2440 TRACE("(%p)\n", hWnd);
2442 hProp = GetPropA(hWnd, "PropDlgFont");
2444 if(hProp)
2446 DeleteObject(hProp);
2447 hProp = RemovePropA(hWnd, "PropDlgFont");
2449 return hProp;
2452 /*************************************************************************
2453 * @ [SHLWAPI.236]
2455 * Load the in-process server of a given GUID.
2457 * PARAMS
2458 * refiid [I] GUID of the server to load.
2460 * RETURNS
2461 * Success: A handle to the loaded server dll.
2462 * Failure: A NULL handle.
2464 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2466 HKEY newkey;
2467 DWORD type, count;
2468 CHAR value[MAX_PATH], string[MAX_PATH];
2470 strcpy(string, "CLSID\\");
2471 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2472 strcat(string, "\\InProcServer32");
2474 count = MAX_PATH;
2475 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2476 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2477 RegCloseKey(newkey);
2478 return LoadLibraryExA(value, 0, 0);
2481 /*************************************************************************
2482 * @ [SHLWAPI.237]
2484 * Unicode version of SHLWAPI_183.
2486 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2488 WNDCLASSW WndClass;
2490 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2492 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2493 return TRUE;
2494 return RegisterClassW(lpWndClass);
2497 /*************************************************************************
2498 * @ [SHLWAPI.238]
2500 * Unregister a list of classes.
2502 * PARAMS
2503 * hInst [I] Application instance that registered the classes
2504 * lppClasses [I] List of class names
2505 * iCount [I] Number of names in lppClasses
2507 * RETURNS
2508 * Nothing.
2510 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2512 WNDCLASSA WndClass;
2514 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2516 while (iCount > 0)
2518 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2519 UnregisterClassA(*lppClasses, hInst);
2520 lppClasses++;
2521 iCount--;
2525 /*************************************************************************
2526 * @ [SHLWAPI.239]
2528 * Unicode version of SHUnregisterClassesA.
2530 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2532 WNDCLASSW WndClass;
2534 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2536 while (iCount > 0)
2538 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2539 UnregisterClassW(*lppClasses, hInst);
2540 lppClasses++;
2541 iCount--;
2545 /*************************************************************************
2546 * @ [SHLWAPI.240]
2548 * Call The correct (Ascii/Unicode) default window procedure for a window.
2550 * PARAMS
2551 * hWnd [I] Window to call the default procedure for
2552 * uMessage [I] Message ID
2553 * wParam [I] WPARAM of message
2554 * lParam [I] LPARAM of message
2556 * RETURNS
2557 * The result of calling DefWindowProcA() or DefWindowProcW().
2559 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2561 if (IsWindowUnicode(hWnd))
2562 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2563 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2566 /*************************************************************************
2567 * @ [SHLWAPI.256]
2569 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2571 HRESULT hRet = E_INVALIDARG;
2572 LPOBJECTWITHSITE lpSite = NULL;
2574 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2576 if (lpUnknown && iid && lppSite)
2578 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2579 (void**)&lpSite);
2580 if (SUCCEEDED(hRet) && lpSite)
2582 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2583 IObjectWithSite_Release(lpSite);
2586 return hRet;
2589 /*************************************************************************
2590 * @ [SHLWAPI.257]
2592 * Create a worker window using CreateWindowExA().
2594 * PARAMS
2595 * wndProc [I] Window procedure
2596 * hWndParent [I] Parent window
2597 * dwExStyle [I] Extra style flags
2598 * dwStyle [I] Style flags
2599 * hMenu [I] Window menu
2600 * z [I] Unknown
2602 * RETURNS
2603 * Success: The window handle of the newly created window.
2604 * Failure: 0.
2606 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2607 DWORD dwStyle, HMENU hMenu, LONG z)
2609 static const char szClass[] = "WorkerA";
2610 WNDCLASSA wc;
2611 HWND hWnd;
2613 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2614 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2616 /* Create Window class */
2617 wc.style = 0;
2618 wc.lpfnWndProc = DefWindowProcA;
2619 wc.cbClsExtra = 0;
2620 wc.cbWndExtra = 4;
2621 wc.hInstance = shlwapi_hInstance;
2622 wc.hIcon = NULL;
2623 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2624 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2625 wc.lpszMenuName = NULL;
2626 wc.lpszClassName = szClass;
2628 SHRegisterClassA(&wc); /* Register class */
2630 /* FIXME: Set extra bits in dwExStyle */
2632 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2633 hWndParent, hMenu, shlwapi_hInstance, 0);
2634 if (hWnd)
2636 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2638 if (wndProc)
2639 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2641 return hWnd;
2644 typedef struct tagPOLICYDATA
2646 DWORD policy; /* flags value passed to SHRestricted */
2647 LPCWSTR appstr; /* application str such as "Explorer" */
2648 LPCWSTR keystr; /* name of the actual registry key / policy */
2649 } POLICYDATA, *LPPOLICYDATA;
2651 #define SHELL_NO_POLICY 0xffffffff
2653 /* default shell policy registry key */
2654 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2655 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2656 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2657 '\\','P','o','l','i','c','i','e','s',0};
2659 /*************************************************************************
2660 * @ [SHLWAPI.271]
2662 * Retrieve a policy value from the registry.
2664 * PARAMS
2665 * lpSubKey [I] registry key name
2666 * lpSubName [I] subname of registry key
2667 * lpValue [I] value name of registry value
2669 * RETURNS
2670 * the value associated with the registry key or 0 if not found
2672 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2674 DWORD retval, datsize = sizeof(retval);
2675 HKEY hKey;
2677 if (!lpSubKey)
2678 lpSubKey = strRegistryPolicyW;
2680 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2681 if (retval != ERROR_SUCCESS)
2682 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2683 if (retval != ERROR_SUCCESS)
2684 return 0;
2686 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2687 RegCloseKey(hKey);
2688 return retval;
2691 /*************************************************************************
2692 * @ [SHLWAPI.266]
2694 * Helper function to retrieve the possibly cached value for a specific policy
2696 * PARAMS
2697 * policy [I] The policy to look for
2698 * initial [I] Main registry key to open, if NULL use default
2699 * polTable [I] Table of known policies, 0 terminated
2700 * polArr [I] Cache array of policy values
2702 * RETURNS
2703 * The retrieved policy value or 0 if not successful
2705 * NOTES
2706 * This function is used by the native SHRestricted function to search for the
2707 * policy and cache it once retrieved. The current Wine implementation uses a
2708 * different POLICYDATA structure and implements a similar algorithm adapted to
2709 * that structure.
2711 DWORD WINAPI SHRestrictionLookup(
2712 DWORD policy,
2713 LPCWSTR initial,
2714 LPPOLICYDATA polTable,
2715 LPDWORD polArr)
2717 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2719 if (!polTable || !polArr)
2720 return 0;
2722 for (;polTable->policy; polTable++, polArr++)
2724 if (policy == polTable->policy)
2726 /* we have a known policy */
2728 /* check if this policy has been cached */
2729 if (*polArr == SHELL_NO_POLICY)
2730 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2731 return *polArr;
2734 /* we don't know this policy, return 0 */
2735 TRACE("unknown policy: (%08x)\n", policy);
2736 return 0;
2739 /*************************************************************************
2740 * @ [SHLWAPI.267]
2742 * Get an interface from an object.
2744 * RETURNS
2745 * Success: S_OK. ppv contains the requested interface.
2746 * Failure: An HRESULT error code.
2748 * NOTES
2749 * This QueryInterface asks the inner object for an interface. In case
2750 * of aggregation this request would be forwarded by the inner to the
2751 * outer object. This function asks the inner object directly for the
2752 * interface circumventing the forwarding to the outer object.
2754 HRESULT WINAPI SHWeakQueryInterface(
2755 IUnknown * pUnk, /* [in] Outer object */
2756 IUnknown * pInner, /* [in] Inner object */
2757 IID * riid, /* [in] Interface GUID to query for */
2758 LPVOID* ppv) /* [out] Destination for queried interface */
2760 HRESULT hret = E_NOINTERFACE;
2761 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2763 *ppv = NULL;
2764 if(pUnk && pInner) {
2765 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2766 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2768 TRACE("-- 0x%08x\n", hret);
2769 return hret;
2772 /*************************************************************************
2773 * @ [SHLWAPI.268]
2775 * Move a reference from one interface to another.
2777 * PARAMS
2778 * lpDest [O] Destination to receive the reference
2779 * lppUnknown [O] Source to give up the reference to lpDest
2781 * RETURNS
2782 * Nothing.
2784 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2786 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2788 if (*lppUnknown)
2790 /* Copy Reference*/
2791 IUnknown_AddRef(lpDest);
2792 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2796 /*************************************************************************
2797 * @ [SHLWAPI.269]
2799 * Convert an ASCII string of a CLSID into a CLSID.
2801 * PARAMS
2802 * idstr [I] String representing a CLSID in registry format
2803 * id [O] Destination for the converted CLSID
2805 * RETURNS
2806 * Success: TRUE. id contains the converted CLSID.
2807 * Failure: FALSE.
2809 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2811 WCHAR wClsid[40];
2812 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2813 return SUCCEEDED(CLSIDFromString(wClsid, id));
2816 /*************************************************************************
2817 * @ [SHLWAPI.270]
2819 * Unicode version of GUIDFromStringA.
2821 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2823 return SUCCEEDED(CLSIDFromString((LPOLESTR)idstr, id));
2826 /*************************************************************************
2827 * @ [SHLWAPI.276]
2829 * Determine if the browser is integrated into the shell, and set a registry
2830 * key accordingly.
2832 * PARAMS
2833 * None.
2835 * RETURNS
2836 * 1, If the browser is not integrated.
2837 * 2, If the browser is integrated.
2839 * NOTES
2840 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2841 * either set to TRUE, or removed depending on whether the browser is deemed
2842 * to be integrated.
2844 DWORD WINAPI WhichPlatform(void)
2846 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2847 static DWORD dwState = 0;
2848 HKEY hKey;
2849 DWORD dwRet, dwData, dwSize;
2850 HMODULE hshell32;
2852 if (dwState)
2853 return dwState;
2855 /* If shell32 exports DllGetVersion(), the browser is integrated */
2856 dwState = 1;
2857 hshell32 = LoadLibraryA("shell32.dll");
2858 if (hshell32)
2860 FARPROC pDllGetVersion;
2861 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2862 dwState = pDllGetVersion ? 2 : 1;
2863 FreeLibrary(hshell32);
2866 /* Set or delete the key accordingly */
2867 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2868 "Software\\Microsoft\\Internet Explorer", 0,
2869 KEY_ALL_ACCESS, &hKey);
2870 if (!dwRet)
2872 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2873 (LPBYTE)&dwData, &dwSize);
2875 if (!dwRet && dwState == 1)
2877 /* Value exists but browser is not integrated */
2878 RegDeleteValueA(hKey, szIntegratedBrowser);
2880 else if (dwRet && dwState == 2)
2882 /* Browser is integrated but value does not exist */
2883 dwData = TRUE;
2884 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2885 (LPBYTE)&dwData, sizeof(dwData));
2887 RegCloseKey(hKey);
2889 return dwState;
2892 /*************************************************************************
2893 * @ [SHLWAPI.278]
2895 * Unicode version of SHCreateWorkerWindowA.
2897 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2898 DWORD dwStyle, HMENU hMenu, LONG z)
2900 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2901 WNDCLASSW wc;
2902 HWND hWnd;
2904 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2905 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2907 /* If our OS is natively ASCII, use the ASCII version */
2908 if (!(GetVersion() & 0x80000000)) /* NT */
2909 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2911 /* Create Window class */
2912 wc.style = 0;
2913 wc.lpfnWndProc = DefWindowProcW;
2914 wc.cbClsExtra = 0;
2915 wc.cbWndExtra = 4;
2916 wc.hInstance = shlwapi_hInstance;
2917 wc.hIcon = NULL;
2918 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2919 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2920 wc.lpszMenuName = NULL;
2921 wc.lpszClassName = szClass;
2923 SHRegisterClassW(&wc); /* Register class */
2925 /* FIXME: Set extra bits in dwExStyle */
2927 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2928 hWndParent, hMenu, shlwapi_hInstance, 0);
2929 if (hWnd)
2931 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2933 if (wndProc)
2934 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2936 return hWnd;
2939 /*************************************************************************
2940 * @ [SHLWAPI.279]
2942 * Get and show a context menu from a shell folder.
2944 * PARAMS
2945 * hWnd [I] Window displaying the shell folder
2946 * lpFolder [I] IShellFolder interface
2947 * lpApidl [I] Id for the particular folder desired
2949 * RETURNS
2950 * Success: S_OK.
2951 * Failure: An HRESULT error code indicating the error.
2953 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2955 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2958 /*************************************************************************
2959 * @ [SHLWAPI.281]
2961 * _SHPackDispParamsV
2963 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist)
2965 VARIANTARG *iter;
2967 TRACE("(%p %p %u ...)\n", params, args, cnt);
2969 params->rgvarg = args;
2970 params->rgdispidNamedArgs = NULL;
2971 params->cArgs = cnt;
2972 params->cNamedArgs = 0;
2974 iter = args+cnt;
2976 while(iter-- > args) {
2977 V_VT(iter) = va_arg(valist, enum VARENUM);
2979 TRACE("vt=%d\n", V_VT(iter));
2981 if(V_VT(iter) & VT_BYREF) {
2982 V_BYREF(iter) = va_arg(valist, LPVOID);
2983 } else {
2984 switch(V_VT(iter)) {
2985 case VT_I4:
2986 V_I4(iter) = va_arg(valist, LONG);
2987 break;
2988 case VT_BSTR:
2989 V_BSTR(iter) = va_arg(valist, BSTR);
2990 break;
2991 case VT_DISPATCH:
2992 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
2993 break;
2994 case VT_BOOL:
2995 V_BOOL(iter) = va_arg(valist, int);
2996 break;
2997 case VT_UNKNOWN:
2998 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
2999 break;
3000 default:
3001 V_VT(iter) = VT_I4;
3002 V_I4(iter) = va_arg(valist, LONG);
3007 return S_OK;
3010 /*************************************************************************
3011 * @ [SHLWAPI.282]
3013 * SHPackDispParams
3015 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...)
3017 __ms_va_list valist;
3018 HRESULT hres;
3020 __ms_va_start(valist, cnt);
3021 hres = SHPackDispParamsV(params, args, cnt, valist);
3022 __ms_va_end(valist);
3023 return hres;
3026 /*************************************************************************
3027 * SHLWAPI_InvokeByIID
3029 * This helper function calls IDispatch::Invoke for each sink
3030 * which implements given iid or IDispatch.
3033 static HRESULT SHLWAPI_InvokeByIID(
3034 IConnectionPoint* iCP,
3035 REFIID iid,
3036 DISPID dispId,
3037 DISPPARAMS* dispParams)
3039 IEnumConnections *enumerator;
3040 CONNECTDATA rgcd;
3041 static DISPPARAMS empty = {NULL, NULL, 0, 0};
3042 DISPPARAMS* params = dispParams;
3044 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
3045 if (FAILED(result))
3046 return result;
3048 /* Invoke is never happening with an NULL dispParams */
3049 if (!params)
3050 params = &empty;
3052 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
3054 IDispatch *dispIface;
3055 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
3056 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
3058 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
3059 IDispatch_Release(dispIface);
3061 IUnknown_Release(rgcd.pUnk);
3064 IEnumConnections_Release(enumerator);
3066 return S_OK;
3069 /*************************************************************************
3070 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3072 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP,
3073 DISPID dispId, DISPPARAMS* dispParams,
3074 DWORD unknown1, DWORD unknown2 )
3076 IID iid;
3077 HRESULT result;
3079 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
3081 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3082 if (SUCCEEDED(result))
3083 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3084 else
3085 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3087 return result;
3091 /*************************************************************************
3092 * @ [SHLWAPI.284]
3094 * IConnectionPoint_SimpleInvoke
3096 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
3097 IConnectionPoint* iCP,
3098 DISPID dispId,
3099 DISPPARAMS* dispParams)
3101 IID iid;
3102 HRESULT result;
3104 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
3106 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3107 if (SUCCEEDED(result))
3108 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3109 else
3110 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3112 return result;
3115 /*************************************************************************
3116 * @ [SHLWAPI.285]
3118 * Notify an IConnectionPoint object of changes.
3120 * PARAMS
3121 * lpCP [I] Object to notify
3122 * dispID [I]
3124 * RETURNS
3125 * Success: S_OK.
3126 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3127 * IConnectionPoint interface.
3129 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
3131 IEnumConnections *lpEnum;
3132 HRESULT hRet = E_NOINTERFACE;
3134 TRACE("(%p,0x%8X)\n", lpCP, dispID);
3136 /* Get an enumerator for the connections */
3137 if (lpCP)
3138 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
3140 if (SUCCEEDED(hRet))
3142 IPropertyNotifySink *lpSink;
3143 CONNECTDATA connData;
3144 ULONG ulFetched;
3146 /* Call OnChanged() for every notify sink in the connection point */
3147 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
3149 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
3150 lpSink)
3152 IPropertyNotifySink_OnChanged(lpSink, dispID);
3153 IPropertyNotifySink_Release(lpSink);
3155 IUnknown_Release(connData.pUnk);
3158 IEnumConnections_Release(lpEnum);
3160 return hRet;
3163 /*************************************************************************
3164 * @ [SHLWAPI.286]
3166 * IUnknown_CPContainerInvokeParam
3168 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
3169 IUnknown *container,
3170 REFIID riid,
3171 DISPID dispId,
3172 VARIANTARG* buffer,
3173 DWORD cParams, ...)
3175 HRESULT result;
3176 IConnectionPoint *iCP;
3177 IConnectionPointContainer *iCPC;
3178 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3179 __ms_va_list valist;
3181 if (!container)
3182 return E_NOINTERFACE;
3184 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
3185 if (FAILED(result))
3186 return result;
3188 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
3189 IConnectionPointContainer_Release(iCPC);
3190 if(FAILED(result))
3191 return result;
3193 __ms_va_start(valist, cParams);
3194 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
3195 __ms_va_end(valist);
3197 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3198 IConnectionPoint_Release(iCP);
3200 return result;
3203 /*************************************************************************
3204 * @ [SHLWAPI.287]
3206 * Notify an IConnectionPointContainer object of changes.
3208 * PARAMS
3209 * lpUnknown [I] Object to notify
3210 * dispID [I]
3212 * RETURNS
3213 * Success: S_OK.
3214 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3215 * IConnectionPointContainer interface.
3217 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3219 IConnectionPointContainer* lpCPC = NULL;
3220 HRESULT hRet = E_NOINTERFACE;
3222 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3224 if (lpUnknown)
3225 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3227 if (SUCCEEDED(hRet))
3229 IConnectionPoint* lpCP;
3231 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3232 IConnectionPointContainer_Release(lpCPC);
3234 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3235 IConnectionPoint_Release(lpCP);
3237 return hRet;
3240 /*************************************************************************
3241 * @ [SHLWAPI.289]
3243 * See PlaySoundW.
3245 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3247 return PlaySoundW(pszSound, hmod, fdwSound);
3250 /*************************************************************************
3251 * @ [SHLWAPI.294]
3253 BOOL WINAPI SHGetIniStringW(LPCWSTR str1, LPCWSTR str2, LPWSTR pStr, DWORD some_len, LPCWSTR lpStr2)
3255 FIXME("(%s,%s,%p,%08x,%s): stub!\n", debugstr_w(str1), debugstr_w(str2),
3256 pStr, some_len, debugstr_w(lpStr2));
3257 return TRUE;
3260 /*************************************************************************
3261 * @ [SHLWAPI.295]
3263 * Called by ICQ2000b install via SHDOCVW:
3264 * str1: "InternetShortcut"
3265 * x: some unknown pointer
3266 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
3267 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
3269 * In short: this one maybe creates a desktop link :-)
3271 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
3273 FIXME("(%s, %p, %s, %s), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
3274 return TRUE;
3277 /*************************************************************************
3278 * @ [SHLWAPI.313]
3280 * See SHGetFileInfoW.
3282 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3283 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3285 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3288 /*************************************************************************
3289 * @ [SHLWAPI.318]
3291 * See DragQueryFileW.
3293 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3295 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3298 /*************************************************************************
3299 * @ [SHLWAPI.333]
3301 * See SHBrowseForFolderW.
3303 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3305 return SHBrowseForFolderW(lpBi);
3308 /*************************************************************************
3309 * @ [SHLWAPI.334]
3311 * See SHGetPathFromIDListW.
3313 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3315 return SHGetPathFromIDListW(pidl, pszPath);
3318 /*************************************************************************
3319 * @ [SHLWAPI.335]
3321 * See ShellExecuteExW.
3323 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3325 return ShellExecuteExW(lpExecInfo);
3328 /*************************************************************************
3329 * @ [SHLWAPI.336]
3331 * See SHFileOperationW.
3333 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3335 return SHFileOperationW(lpFileOp);
3338 /*************************************************************************
3339 * @ [SHLWAPI.342]
3342 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
3344 return InterlockedCompareExchangePointer( dest, xchg, compare );
3347 /*************************************************************************
3348 * @ [SHLWAPI.350]
3350 * See GetFileVersionInfoSizeW.
3352 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
3354 return GetFileVersionInfoSizeW( filename, handle );
3357 /*************************************************************************
3358 * @ [SHLWAPI.351]
3360 * See GetFileVersionInfoW.
3362 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
3363 DWORD datasize, LPVOID data )
3365 return GetFileVersionInfoW( filename, handle, datasize, data );
3368 /*************************************************************************
3369 * @ [SHLWAPI.352]
3371 * See VerQueryValueW.
3373 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
3374 LPVOID *lplpBuffer, UINT *puLen )
3376 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3379 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3380 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3381 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3383 /*************************************************************************
3384 * @ [SHLWAPI.355]
3386 * Change the modality of a shell object.
3388 * PARAMS
3389 * lpUnknown [I] Object to make modeless
3390 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3392 * RETURNS
3393 * Success: S_OK. The modality lpUnknown is changed.
3394 * Failure: An HRESULT error code indicating the error.
3396 * NOTES
3397 * lpUnknown must support the IOleInPlaceFrame interface, the
3398 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3399 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3400 * or this call will fail.
3402 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3404 IUnknown *lpObj;
3405 HRESULT hRet;
3407 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3409 if (!lpUnknown)
3410 return E_FAIL;
3412 if (IsIface(IOleInPlaceActiveObject))
3413 EnableModeless(IOleInPlaceActiveObject);
3414 else if (IsIface(IOleInPlaceFrame))
3415 EnableModeless(IOleInPlaceFrame);
3416 else if (IsIface(IShellBrowser))
3417 EnableModeless(IShellBrowser);
3418 else if (IsIface(IInternetSecurityMgrSite))
3419 EnableModeless(IInternetSecurityMgrSite);
3420 else if (IsIface(IDocHostUIHandler))
3421 EnableModeless(IDocHostUIHandler);
3422 else
3423 return hRet;
3425 IUnknown_Release(lpObj);
3426 return S_OK;
3429 /*************************************************************************
3430 * @ [SHLWAPI.357]
3432 * See SHGetNewLinkInfoW.
3434 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3435 BOOL *pfMustCopy, UINT uFlags)
3437 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3440 /*************************************************************************
3441 * @ [SHLWAPI.358]
3443 * See SHDefExtractIconW.
3445 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3446 HICON* phiconSmall, UINT nIconSize)
3448 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3451 /*************************************************************************
3452 * @ [SHLWAPI.363]
3454 * Get and show a context menu from a shell folder.
3456 * PARAMS
3457 * hWnd [I] Window displaying the shell folder
3458 * lpFolder [I] IShellFolder interface
3459 * lpApidl [I] Id for the particular folder desired
3460 * bInvokeDefault [I] Whether to invoke the default menu item
3462 * RETURNS
3463 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3464 * executed.
3465 * Failure: An HRESULT error code indicating the error.
3467 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3469 IContextMenu *iContext;
3470 HRESULT hRet = E_FAIL;
3472 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3474 if (!lpFolder)
3475 return hRet;
3477 /* Get the context menu from the shell folder */
3478 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3479 &IID_IContextMenu, 0, (void**)&iContext);
3480 if (SUCCEEDED(hRet))
3482 HMENU hMenu;
3483 if ((hMenu = CreatePopupMenu()))
3485 HRESULT hQuery;
3486 DWORD dwDefaultId = 0;
3488 /* Add the context menu entries to the popup */
3489 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3490 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3492 if (SUCCEEDED(hQuery))
3494 if (bInvokeDefault &&
3495 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3497 CMINVOKECOMMANDINFO cmIci;
3498 /* Invoke the default item */
3499 memset(&cmIci,0,sizeof(cmIci));
3500 cmIci.cbSize = sizeof(cmIci);
3501 cmIci.fMask = CMIC_MASK_ASYNCOK;
3502 cmIci.hwnd = hWnd;
3503 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3504 cmIci.nShow = SW_SCROLLCHILDREN;
3506 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3509 DestroyMenu(hMenu);
3511 IContextMenu_Release(iContext);
3513 return hRet;
3516 /*************************************************************************
3517 * @ [SHLWAPI.370]
3519 * See ExtractIconW.
3521 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3522 UINT nIconIndex)
3524 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3527 /*************************************************************************
3528 * @ [SHLWAPI.377]
3530 * Load a library from the directory of a particular process.
3532 * PARAMS
3533 * new_mod [I] Library name
3534 * inst_hwnd [I] Module whose directory is to be used
3535 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3537 * RETURNS
3538 * Success: A handle to the loaded module
3539 * Failure: A NULL handle.
3541 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3543 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3544 * each call here.
3545 * FIXME: Native shows calls to:
3546 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3547 * CheckVersion
3548 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3549 * RegQueryValueExA for "LPKInstalled"
3550 * RegCloseKey
3551 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3552 * RegQueryValueExA for "ResourceLocale"
3553 * RegCloseKey
3554 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3555 * RegQueryValueExA for "Locale"
3556 * RegCloseKey
3557 * and then tests the Locale ("en" for me).
3558 * code below
3559 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3561 CHAR mod_path[2*MAX_PATH];
3562 LPSTR ptr;
3563 DWORD len;
3565 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3566 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3567 if (!len || len >= sizeof(mod_path)) return NULL;
3569 ptr = strrchr(mod_path, '\\');
3570 if (ptr) {
3571 strcpy(ptr+1, new_mod);
3572 TRACE("loading %s\n", debugstr_a(mod_path));
3573 return LoadLibraryA(mod_path);
3575 return NULL;
3578 /*************************************************************************
3579 * @ [SHLWAPI.378]
3581 * Unicode version of MLLoadLibraryA.
3583 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3585 WCHAR mod_path[2*MAX_PATH];
3586 LPWSTR ptr;
3587 DWORD len;
3589 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3590 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3591 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3593 ptr = strrchrW(mod_path, '\\');
3594 if (ptr) {
3595 strcpyW(ptr+1, new_mod);
3596 TRACE("loading %s\n", debugstr_w(mod_path));
3597 return LoadLibraryW(mod_path);
3599 return NULL;
3602 /*************************************************************************
3603 * ColorAdjustLuma [SHLWAPI.@]
3605 * Adjust the luminosity of a color
3607 * PARAMS
3608 * cRGB [I] RGB value to convert
3609 * dwLuma [I] Luma adjustment
3610 * bUnknown [I] Unknown
3612 * RETURNS
3613 * The adjusted RGB color.
3615 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3617 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3619 if (dwLuma)
3621 WORD wH, wL, wS;
3623 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3625 FIXME("Ignoring luma adjustment\n");
3627 /* FIXME: The adjustment is not linear */
3629 cRGB = ColorHLSToRGB(wH, wL, wS);
3631 return cRGB;
3634 /*************************************************************************
3635 * @ [SHLWAPI.389]
3637 * See GetSaveFileNameW.
3639 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3641 return GetSaveFileNameW(ofn);
3644 /*************************************************************************
3645 * @ [SHLWAPI.390]
3647 * See WNetRestoreConnectionW.
3649 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3651 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3654 /*************************************************************************
3655 * @ [SHLWAPI.391]
3657 * See WNetGetLastErrorW.
3659 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3660 LPWSTR lpNameBuf, DWORD nNameBufSize)
3662 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3665 /*************************************************************************
3666 * @ [SHLWAPI.401]
3668 * See PageSetupDlgW.
3670 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3672 return PageSetupDlgW(pagedlg);
3675 /*************************************************************************
3676 * @ [SHLWAPI.402]
3678 * See PrintDlgW.
3680 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3682 return PrintDlgW(printdlg);
3685 /*************************************************************************
3686 * @ [SHLWAPI.403]
3688 * See GetOpenFileNameW.
3690 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3692 return GetOpenFileNameW(ofn);
3695 /*************************************************************************
3696 * @ [SHLWAPI.404]
3698 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3700 IPersist *persist;
3701 HRESULT hr;
3703 hr = IShellFolder_QueryInterface(lpFolder, &IID_IPersist, (LPVOID)&persist);
3704 if(SUCCEEDED(hr))
3706 CLSID clsid;
3707 hr = IPersist_GetClassID(persist, &clsid);
3708 if(SUCCEEDED(hr))
3710 if(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder))
3711 hr = IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3712 else
3713 hr = E_FAIL;
3715 IPersist_Release(persist);
3717 return hr;
3720 /* INTERNAL: Map from HLS color space to RGB */
3721 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3723 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3725 if (wHue > 160)
3726 return wMid1;
3727 else if (wHue > 120)
3728 wHue = 160 - wHue;
3729 else if (wHue > 40)
3730 return wMid2;
3732 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3735 /* Convert to RGB and scale into RGB range (0..255) */
3736 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3738 /*************************************************************************
3739 * ColorHLSToRGB [SHLWAPI.@]
3741 * Convert from hls color space into an rgb COLORREF.
3743 * PARAMS
3744 * wHue [I] Hue amount
3745 * wLuminosity [I] Luminosity amount
3746 * wSaturation [I] Saturation amount
3748 * RETURNS
3749 * A COLORREF representing the converted color.
3751 * NOTES
3752 * Input hls values are constrained to the range (0..240).
3754 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3756 WORD wRed;
3758 if (wSaturation)
3760 WORD wGreen, wBlue, wMid1, wMid2;
3762 if (wLuminosity > 120)
3763 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3764 else
3765 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3767 wMid1 = wLuminosity * 2 - wMid2;
3769 wRed = GET_RGB(wHue + 80);
3770 wGreen = GET_RGB(wHue);
3771 wBlue = GET_RGB(wHue - 80);
3773 return RGB(wRed, wGreen, wBlue);
3776 wRed = wLuminosity * 255 / 240;
3777 return RGB(wRed, wRed, wRed);
3780 /*************************************************************************
3781 * @ [SHLWAPI.413]
3783 * Get the current docking status of the system.
3785 * PARAMS
3786 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3788 * RETURNS
3789 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3790 * a notebook.
3792 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3794 HW_PROFILE_INFOA hwInfo;
3796 TRACE("(0x%08x)\n", dwFlags);
3798 GetCurrentHwProfileA(&hwInfo);
3799 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3801 case DOCKINFO_DOCKED:
3802 case DOCKINFO_UNDOCKED:
3803 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3804 default:
3805 return 0;
3809 /*************************************************************************
3810 * @ [SHLWAPI.418]
3812 * Function seems to do FreeLibrary plus other things.
3814 * FIXME native shows the following calls:
3815 * RtlEnterCriticalSection
3816 * LocalFree
3817 * GetProcAddress(Comctl32??, 150L)
3818 * DPA_DeletePtr
3819 * RtlLeaveCriticalSection
3820 * followed by the FreeLibrary.
3821 * The above code may be related to .377 above.
3823 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3825 FIXME("(%p) semi-stub\n", hModule);
3826 return FreeLibrary(hModule);
3829 /*************************************************************************
3830 * @ [SHLWAPI.419]
3832 BOOL WINAPI SHFlushSFCacheWrap(void) {
3833 FIXME(": stub\n");
3834 return TRUE;
3837 /*************************************************************************
3838 * @ [SHLWAPI.429]
3839 * FIXME I have no idea what this function does or what its arguments are.
3841 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3843 FIXME("(%p) stub\n", hInst);
3844 return FALSE;
3848 /*************************************************************************
3849 * @ [SHLWAPI.430]
3851 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3853 FIXME("(%p,%p) stub\n", hInst, hHeap);
3854 return E_FAIL; /* This is what is used if shlwapi not loaded */
3857 /*************************************************************************
3858 * @ [SHLWAPI.431]
3860 DWORD WINAPI MLClearMLHInstance(DWORD x)
3862 FIXME("(0x%08x)stub\n", x);
3863 return 0xabba1247;
3866 /*************************************************************************
3867 * @ [SHLWAPI.432]
3869 * See SHSendMessageBroadcastW
3872 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam)
3874 return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam,
3875 SMTO_ABORTIFHUNG, 2000, NULL);
3878 /*************************************************************************
3879 * @ [SHLWAPI.433]
3881 * A wrapper for sending Broadcast Messages to all top level Windows
3884 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam)
3886 return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam,
3887 SMTO_ABORTIFHUNG, 2000, NULL);
3890 /*************************************************************************
3891 * @ [SHLWAPI.436]
3893 * Convert a Unicode string CLSID into a CLSID.
3895 * PARAMS
3896 * idstr [I] string containing a CLSID in text form
3897 * id [O] CLSID extracted from the string
3899 * RETURNS
3900 * S_OK on success or E_INVALIDARG on failure
3902 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3904 return CLSIDFromString((LPOLESTR)idstr, id);
3907 /*************************************************************************
3908 * @ [SHLWAPI.437]
3910 * Determine if the OS supports a given feature.
3912 * PARAMS
3913 * dwFeature [I] Feature requested (undocumented)
3915 * RETURNS
3916 * TRUE If the feature is available.
3917 * FALSE If the feature is not available.
3919 BOOL WINAPI IsOS(DWORD feature)
3921 OSVERSIONINFOA osvi;
3922 DWORD platform, majorv, minorv;
3924 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3925 if(!GetVersionExA(&osvi)) {
3926 ERR("GetVersionEx failed\n");
3927 return FALSE;
3930 majorv = osvi.dwMajorVersion;
3931 minorv = osvi.dwMinorVersion;
3932 platform = osvi.dwPlatformId;
3934 #define ISOS_RETURN(x) \
3935 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3936 return (x);
3938 switch(feature) {
3939 case OS_WIN32SORGREATER:
3940 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3941 || platform == VER_PLATFORM_WIN32_WINDOWS)
3942 case OS_NT:
3943 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3944 case OS_WIN95ORGREATER:
3945 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3946 case OS_NT4ORGREATER:
3947 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3948 case OS_WIN2000ORGREATER_ALT:
3949 case OS_WIN2000ORGREATER:
3950 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3951 case OS_WIN98ORGREATER:
3952 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3953 case OS_WIN98_GOLD:
3954 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3955 case OS_WIN2000PRO:
3956 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3957 case OS_WIN2000SERVER:
3958 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3959 case OS_WIN2000ADVSERVER:
3960 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3961 case OS_WIN2000DATACENTER:
3962 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3963 case OS_WIN2000TERMINAL:
3964 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3965 case OS_EMBEDDED:
3966 FIXME("(OS_EMBEDDED) What should we return here?\n");
3967 return FALSE;
3968 case OS_TERMINALCLIENT:
3969 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3970 return FALSE;
3971 case OS_TERMINALREMOTEADMIN:
3972 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3973 return FALSE;
3974 case OS_WIN95_GOLD:
3975 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3976 case OS_MEORGREATER:
3977 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3978 case OS_XPORGREATER:
3979 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3980 case OS_HOME:
3981 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3982 case OS_PROFESSIONAL:
3983 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3984 case OS_DATACENTER:
3985 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3986 case OS_ADVSERVER:
3987 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3988 case OS_SERVER:
3989 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3990 case OS_TERMINALSERVER:
3991 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3992 case OS_PERSONALTERMINALSERVER:
3993 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3994 case OS_FASTUSERSWITCHING:
3995 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3996 return TRUE;
3997 case OS_WELCOMELOGONUI:
3998 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3999 return FALSE;
4000 case OS_DOMAINMEMBER:
4001 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
4002 return TRUE;
4003 case OS_ANYSERVER:
4004 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4005 case OS_WOW6432:
4006 FIXME("(OS_WOW6432) Should we check this?\n");
4007 return FALSE;
4008 case OS_WEBSERVER:
4009 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4010 case OS_SMALLBUSINESSSERVER:
4011 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4012 case OS_TABLETPC:
4013 FIXME("(OS_TABLEPC) What should we return here?\n");
4014 return FALSE;
4015 case OS_SERVERADMINUI:
4016 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
4017 return FALSE;
4018 case OS_MEDIACENTER:
4019 FIXME("(OS_MEDIACENTER) What should we return here?\n");
4020 return FALSE;
4021 case OS_APPLIANCE:
4022 FIXME("(OS_APPLIANCE) What should we return here?\n");
4023 return FALSE;
4024 case 0x25: /*OS_VISTAORGREATER*/
4025 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
4028 #undef ISOS_RETURN
4030 WARN("(0x%x) unknown parameter\n",feature);
4032 return FALSE;
4035 /*************************************************************************
4036 * @ [SHLWAPI.439]
4038 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
4040 DWORD type, sz = size;
4042 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
4043 return E_FAIL;
4045 return SHLoadIndirectString(buf, buf, size, NULL);
4048 /*************************************************************************
4049 * @ [SHLWAPI.478]
4051 * Call IInputObject_TranslateAcceleratorIO() on an object.
4053 * PARAMS
4054 * lpUnknown [I] Object supporting the IInputObject interface.
4055 * lpMsg [I] Key message to be processed.
4057 * RETURNS
4058 * Success: S_OK.
4059 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4061 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
4063 IInputObject* lpInput = NULL;
4064 HRESULT hRet = E_INVALIDARG;
4066 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
4067 if (lpUnknown)
4069 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4070 (void**)&lpInput);
4071 if (SUCCEEDED(hRet) && lpInput)
4073 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
4074 IInputObject_Release(lpInput);
4077 return hRet;
4080 /*************************************************************************
4081 * @ [SHLWAPI.481]
4083 * Call IInputObject_HasFocusIO() on an object.
4085 * PARAMS
4086 * lpUnknown [I] Object supporting the IInputObject interface.
4088 * RETURNS
4089 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4090 * or S_FALSE otherwise.
4091 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4093 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
4095 IInputObject* lpInput = NULL;
4096 HRESULT hRet = E_INVALIDARG;
4098 TRACE("(%p)\n", lpUnknown);
4099 if (lpUnknown)
4101 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4102 (void**)&lpInput);
4103 if (SUCCEEDED(hRet) && lpInput)
4105 hRet = IInputObject_HasFocusIO(lpInput);
4106 IInputObject_Release(lpInput);
4109 return hRet;
4112 /*************************************************************************
4113 * ColorRGBToHLS [SHLWAPI.@]
4115 * Convert an rgb COLORREF into the hls color space.
4117 * PARAMS
4118 * cRGB [I] Source rgb value
4119 * pwHue [O] Destination for converted hue
4120 * pwLuminance [O] Destination for converted luminance
4121 * pwSaturation [O] Destination for converted saturation
4123 * RETURNS
4124 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4125 * values.
4127 * NOTES
4128 * Output HLS values are constrained to the range (0..240).
4129 * For Achromatic conversions, Hue is set to 160.
4131 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
4132 LPWORD pwLuminance, LPWORD pwSaturation)
4134 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4136 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4138 wR = GetRValue(cRGB);
4139 wG = GetGValue(cRGB);
4140 wB = GetBValue(cRGB);
4142 wMax = max(wR, max(wG, wB));
4143 wMin = min(wR, min(wG, wB));
4145 /* Luminosity */
4146 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4148 if (wMax == wMin)
4150 /* Achromatic case */
4151 wSaturation = 0;
4152 /* Hue is now unrepresentable, but this is what native returns... */
4153 wHue = 160;
4155 else
4157 /* Chromatic case */
4158 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4160 /* Saturation */
4161 if (wLuminosity <= 120)
4162 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4163 else
4164 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4166 /* Hue */
4167 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4168 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4169 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4171 if (wR == wMax)
4172 wHue = wBNorm - wGNorm;
4173 else if (wG == wMax)
4174 wHue = 80 + wRNorm - wBNorm;
4175 else
4176 wHue = 160 + wGNorm - wRNorm;
4177 if (wHue < 0)
4178 wHue += 240;
4179 else if (wHue > 240)
4180 wHue -= 240;
4182 if (pwHue)
4183 *pwHue = wHue;
4184 if (pwLuminance)
4185 *pwLuminance = wLuminosity;
4186 if (pwSaturation)
4187 *pwSaturation = wSaturation;
4190 /*************************************************************************
4191 * SHCreateShellPalette [SHLWAPI.@]
4193 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4195 FIXME("stub\n");
4196 return CreateHalftonePalette(hdc);
4199 /*************************************************************************
4200 * SHGetInverseCMAP (SHLWAPI.@)
4202 * Get an inverse color map table.
4204 * PARAMS
4205 * lpCmap [O] Destination for color map
4206 * dwSize [I] Size of memory pointed to by lpCmap
4208 * RETURNS
4209 * Success: S_OK.
4210 * Failure: E_POINTER, If lpCmap is invalid.
4211 * E_INVALIDARG, If dwFlags is invalid
4212 * E_OUTOFMEMORY, If there is no memory available
4214 * NOTES
4215 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4216 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4217 * internal CMap.
4218 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4219 * this DLL's internal CMap.
4221 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4223 if (dwSize == 4) {
4224 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4225 *dest = (DWORD)0xabba1249;
4226 return 0;
4228 FIXME("(%p, %#x) stub\n", dest, dwSize);
4229 return 0;
4232 /*************************************************************************
4233 * SHIsLowMemoryMachine [SHLWAPI.@]
4235 * Determine if the current computer has low memory.
4237 * PARAMS
4238 * x [I] FIXME
4240 * RETURNS
4241 * TRUE if the users machine has 16 Megabytes of memory or less,
4242 * FALSE otherwise.
4244 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4246 FIXME("(0x%08x) stub\n", x);
4247 return FALSE;
4250 /*************************************************************************
4251 * GetMenuPosFromID [SHLWAPI.@]
4253 * Return the position of a menu item from its Id.
4255 * PARAMS
4256 * hMenu [I] Menu containing the item
4257 * wID [I] Id of the menu item
4259 * RETURNS
4260 * Success: The index of the menu item in hMenu.
4261 * Failure: -1, If the item is not found.
4263 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4265 MENUITEMINFOW mi;
4266 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4268 while (nIter < nCount)
4270 mi.cbSize = sizeof(mi);
4271 mi.fMask = MIIM_ID;
4272 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4273 return nIter;
4274 nIter++;
4276 return -1;
4279 /*************************************************************************
4280 * @ [SHLWAPI.179]
4282 * Same as SHLWAPI.GetMenuPosFromID
4284 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4286 return GetMenuPosFromID(hMenu, uID);
4290 /*************************************************************************
4291 * @ [SHLWAPI.448]
4293 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4295 while (*lpwstr)
4297 if (*lpwstr == '/')
4298 *lpwstr = '\\';
4299 lpwstr++;
4304 /*************************************************************************
4305 * @ [SHLWAPI.461]
4307 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4309 FIXME("(0x%08x) stub\n", dwUnknown);
4310 return 0;
4314 /*************************************************************************
4315 * @ [SHLWAPI.549]
4317 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4318 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4320 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4323 /*************************************************************************
4324 * SHSkipJunction [SHLWAPI.@]
4326 * Determine if a bind context can be bound to an object
4328 * PARAMS
4329 * pbc [I] Bind context to check
4330 * pclsid [I] CLSID of object to be bound to
4332 * RETURNS
4333 * TRUE: If it is safe to bind
4334 * FALSE: If pbc is invalid or binding would not be safe
4337 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4339 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4340 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4341 BOOL bRet = FALSE;
4343 if (pbc)
4345 IUnknown* lpUnk;
4347 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4349 CLSID clsid;
4351 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4352 IsEqualGUID(pclsid, &clsid))
4353 bRet = TRUE;
4355 IUnknown_Release(lpUnk);
4358 return bRet;
4361 /***********************************************************************
4362 * SHGetShellKey (SHLWAPI.@)
4364 HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create)
4366 FIXME("(0x%08x, %s, %d): stub\n", flags, debugstr_w(sub_key), create);
4367 return (HKEY)0x50;
4370 /***********************************************************************
4371 * SHQueueUserWorkItem (SHLWAPI.@)
4373 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback,
4374 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4375 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4377 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4378 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4380 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4381 FIXME("Unsupported arguments\n");
4383 return QueueUserWorkItem(pfnCallback, pContext, 0);
4386 /***********************************************************************
4387 * SHSetTimerQueueTimer (SHLWAPI.263)
4389 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
4390 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4391 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4393 HANDLE hNewTimer;
4395 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4396 if (dwFlags & TPS_LONGEXECTIME) {
4397 dwFlags &= ~TPS_LONGEXECTIME;
4398 dwFlags |= WT_EXECUTELONGFUNCTION;
4400 if (dwFlags & TPS_EXECUTEIO) {
4401 dwFlags &= ~TPS_EXECUTEIO;
4402 dwFlags |= WT_EXECUTEINIOTHREAD;
4405 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4406 dwDueTime, dwPeriod, dwFlags))
4407 return NULL;
4409 return hNewTimer;
4412 /***********************************************************************
4413 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4415 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4417 IInputObjectSite *pIOS = NULL;
4418 HRESULT hRet = E_INVALIDARG;
4420 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4422 if (lpUnknown)
4424 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4425 (void **)&pIOS);
4426 if (SUCCEEDED(hRet) && pIOS)
4428 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4429 IInputObjectSite_Release(pIOS);
4432 return hRet;
4435 /***********************************************************************
4436 * SHGetValueW (SHLWAPI.@)
4438 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4440 FIXME("(%x, %s, %s, %x, %x, %x): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4441 return E_FAIL;
4444 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4446 /***********************************************************************
4447 * GetUIVersion (SHLWAPI.452)
4449 DWORD WINAPI GetUIVersion(void)
4451 static DWORD version;
4453 if (!version)
4455 DllGetVersion_func pDllGetVersion;
4456 HMODULE dll = LoadLibraryA("shell32.dll");
4457 if (!dll) return 0;
4459 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4460 if (pDllGetVersion)
4462 DLLVERSIONINFO dvi;
4463 dvi.cbSize = sizeof(DLLVERSIONINFO);
4464 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4466 FreeLibrary( dll );
4467 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4469 return version;
4472 /***********************************************************************
4473 * ShellMessageBoxWrapW [SHLWAPI.388]
4475 * See shell32.ShellMessageBoxW
4477 * NOTE:
4478 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4479 * because we can't forward to it in the .spec file since it's exported by
4480 * ordinal. If you change the implementation here please update the code in
4481 * shell32 as well.
4483 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
4484 LPCWSTR lpCaption, UINT uType, ...)
4486 WCHAR szText[100], szTitle[100];
4487 LPCWSTR pszText = szText, pszTitle = szTitle;
4488 LPWSTR pszTemp;
4489 __ms_va_list args;
4490 int ret;
4492 __ms_va_start(args, uType);
4494 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
4496 if (IS_INTRESOURCE(lpCaption))
4497 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
4498 else
4499 pszTitle = lpCaption;
4501 if (IS_INTRESOURCE(lpText))
4502 LoadStringW(hInstance, LOWORD(lpText), szText, sizeof(szText)/sizeof(szText[0]));
4503 else
4504 pszText = lpText;
4506 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4507 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4509 __ms_va_end(args);
4511 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4512 LocalFree(pszTemp);
4513 return ret;
4516 /***********************************************************************
4517 * ZoneComputePaneSize [SHLWAPI.382]
4519 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4521 FIXME("\n");
4522 return 0x95;
4525 /***********************************************************************
4526 * SHChangeNotifyWrap [SHLWAPI.394]
4528 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
4530 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
4533 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
4534 SID_IDENTIFIER_AUTHORITY sidAuthority;
4535 DWORD dwUserGroupID;
4536 DWORD dwUserID;
4537 } SHELL_USER_SID, *PSHELL_USER_SID;
4539 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
4540 SHELL_USER_SID susID;
4541 DWORD dwAccessType;
4542 BOOL fInherit;
4543 DWORD dwAccessMask;
4544 DWORD dwInheritMask;
4545 DWORD dwInheritAccessMask;
4546 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
4548 /***********************************************************************
4549 * GetShellSecurityDescriptor [SHLWAPI.475]
4551 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4553 * PARAMS
4554 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4555 * each of which describes permissions to apply
4556 * cUserPerm [I] number of entries in apUserPerm array
4558 * RETURNS
4559 * success: pointer to SECURITY_DESCRIPTOR
4560 * failure: NULL
4562 * NOTES
4563 * Call should free returned descriptor with LocalFree
4565 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4567 PSID *sidlist;
4568 PSID cur_user = NULL;
4569 BYTE tuUser[2000];
4570 DWORD acl_size;
4571 int sid_count, i;
4572 PSECURITY_DESCRIPTOR psd = NULL;
4574 TRACE("%p %d\n", apUserPerm, cUserPerm);
4576 if (apUserPerm == NULL || cUserPerm <= 0)
4577 return NULL;
4579 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
4580 if (!sidlist)
4581 return NULL;
4583 acl_size = sizeof(ACL);
4585 for(sid_count = 0; sid_count < cUserPerm; sid_count++)
4587 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
4588 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
4589 PSHELL_USER_SID sid = &perm->susID;
4590 PSID pSid;
4591 BOOL ret = TRUE;
4593 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4594 { /* current user's SID */
4595 if (!cur_user)
4597 HANDLE Token;
4598 DWORD bufsize = sizeof(tuUser);
4600 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4601 if (ret)
4603 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4604 if (ret)
4605 cur_user = ((PTOKEN_USER)tuUser)->User.Sid;
4606 CloseHandle(Token);
4609 pSid = cur_user;
4610 } else if (sid->dwUserID==0) /* one sub-authority */
4611 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
4612 0, 0, 0, 0, 0, 0, &pSid);
4613 else
4614 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4615 0, 0, 0, 0, 0, 0, &pSid);
4616 if (!ret)
4617 goto free_sids;
4619 sidlist[sid_count] = pSid;
4620 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4621 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
4624 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
4626 if (psd != NULL)
4628 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4630 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4631 goto error;
4633 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4634 goto error;
4636 for(i = 0; i < sid_count; i++)
4638 PSHELL_USER_PERMISSION sup = apUserPerm[i];
4639 PSID sid = sidlist[i];
4641 switch(sup->dwAccessType)
4643 case ACCESS_ALLOWED_ACE_TYPE:
4644 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4645 goto error;
4646 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4647 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4648 goto error;
4649 break;
4650 case ACCESS_DENIED_ACE_TYPE:
4651 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4652 goto error;
4653 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4654 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4655 goto error;
4656 break;
4657 default:
4658 goto error;
4662 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4663 goto error;
4665 goto free_sids;
4667 error:
4668 LocalFree(psd);
4669 psd = NULL;
4670 free_sids:
4671 for(i = 0; i < sid_count; i++)
4673 if (!cur_user || sidlist[i] != cur_user)
4674 FreeSid(sidlist[i]);
4676 HeapFree(GetProcessHeap(), 0, sidlist);
4678 return psd;
4681 /***********************************************************************
4682 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4684 * Creates a property bag from a registry key
4686 * PARAMS
4687 * hKey [I] Handle to the desired registry key
4688 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4689 * grfMode [I] Optional flags
4690 * riid [I] IID of requested property bag interface
4691 * ppv [O] Address to receive pointer to the new interface
4693 * RETURNS
4694 * success: 0
4695 * failure: error code
4698 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey,
4699 DWORD grfMode, REFIID riid, void **ppv)
4701 FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode,
4702 debugstr_guid(riid), ppv);
4704 return E_NOTIMPL;
4707 /***********************************************************************
4708 * SHGetViewStatePropertyBag [SHLWAPI.515]
4710 * Retrieves a property bag in which the view state information of a folder
4711 * can be stored.
4713 * PARAMS
4714 * pidl [I] PIDL of the folder requested
4715 * bag_name [I] Name of the property bag requested
4716 * flags [I] Optional flags
4717 * riid [I] IID of requested property bag interface
4718 * ppv [O] Address to receive pointer to the new interface
4720 * RETURNS
4721 * success: S_OK
4722 * failure: error code
4725 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
4726 DWORD flags, REFIID riid, void **ppv)
4728 FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags,
4729 debugstr_guid(riid), ppv);
4731 return E_NOTIMPL;
4734 /***********************************************************************
4735 * SHFormatDateTimeW [SHLWAPI.354]
4737 * Produces a string representation of a time.
4739 * PARAMS
4740 * fileTime [I] Pointer to FILETIME structure specifying the time
4741 * flags [I] Flags specifying the desired output
4742 * buf [O] Pointer to buffer for output
4743 * size [I] Number of characters that can be contained in buffer
4745 * RETURNS
4746 * success: number of characters written to the buffer
4747 * failure: 0
4750 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
4751 LPWSTR buf, UINT size)
4753 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
4754 DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT;
4755 SYSTEMTIME st;
4756 FILETIME ft;
4757 INT ret = 0;
4759 TRACE("%p %p %p %u\n", fileTime, flags, buf, size);
4761 if (!buf || !size)
4762 return 0;
4764 if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS)
4765 FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS);
4767 FileTimeToLocalFileTime(fileTime, &ft);
4768 FileTimeToSystemTime(&ft, &st);
4770 /* first of all date */
4771 if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE))
4773 static const WCHAR sep1[] = {',',' ',0};
4774 static const WCHAR sep2[] = {' ',0};
4776 DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE;
4777 ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size);
4778 if (ret >= size) return ret;
4780 /* add separator */
4781 if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)))
4783 if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2))
4785 if (ret < size + 2)
4787 lstrcatW(&buf[ret-1], sep1);
4788 ret += 2;
4791 else
4793 lstrcatW(&buf[ret-1], sep2);
4794 ret++;
4798 /* time part */
4799 if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))
4801 DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS;
4803 if (ret) ret--;
4804 ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret);
4807 return ret;
4809 #undef SHFORMATDT_UNSUPPORTED_FLAGS
4812 /***********************************************************************
4813 * SHFormatDateTimeA [SHLWAPI.353]
4815 * See SHFormatDateTimeW.
4818 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags,
4819 LPSTR buf, UINT size)
4821 WCHAR *bufW;
4822 INT retval;
4824 if (!buf || !size)
4825 return 0;
4827 bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
4828 retval = SHFormatDateTimeW(fileTime, flags, bufW, size);
4830 if (retval != 0)
4831 WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL);
4833 HeapFree(GetProcessHeap(), 0, bufW);
4834 return retval;
4837 /***********************************************************************
4838 * ZoneCheckUrlExW [SHLWAPI.231]
4840 * Checks the details of the security zone for the supplied site. (?)
4842 * PARAMS
4844 * szURL [I] Pointer to the URL to check
4846 * Other parameters currently unknown.
4848 * RETURNS
4849 * unknown
4852 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2,
4853 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6,
4854 DWORD dwUnknown7)
4856 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2,
4857 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7);
4859 return 0;
4862 /***********************************************************************
4863 * SHVerbExistsNA [SHLWAPI.196]
4866 * PARAMS
4868 * verb [I] a string, often appears to be an extension.
4870 * Other parameters currently unknown.
4872 * RETURNS
4873 * unknown
4875 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3)
4877 FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3);
4878 return 0;
4881 /*************************************************************************
4882 * @ [SHLWAPI.538]
4884 * Undocumented: Implementation guessed at via Name and behavior
4886 * PARAMS
4887 * lpUnknown [I] Object to get an IServiceProvider interface from
4888 * riid [I] Function requested for QueryService call
4889 * lppOut [O] Destination for the service interface pointer
4891 * RETURNS
4892 * Success: S_OK. lppOut contains an object providing the requested service
4893 * Failure: An HRESULT error code
4895 * NOTES
4896 * lpUnknown is expected to support the IServiceProvider interface.
4898 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown,
4899 REFGUID riid, LPVOID *lppOut)
4901 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut);
4902 return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut);
4905 /**************************************************************************
4906 * SHPropertyBag_ReadLONG (SHLWAPI.496)
4908 * This function asks a property bag to read a named property as a LONG.
4910 * PARAMS
4911 * ppb: a IPropertyBag interface
4912 * pszPropName: Unicode string that names the property
4913 * pValue: address to receive the property value as a 32-bit signed integer
4915 * RETURNS
4916 * 0 for Success
4918 BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue)
4920 VARIANT var;
4921 HRESULT hr;
4922 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue);
4923 if (!pszPropName || !ppb || !pValue)
4924 return E_INVALIDARG;
4925 V_VT(&var) = VT_I4;
4926 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
4927 if (SUCCEEDED(hr))
4929 if (V_VT(&var) == VT_I4)
4930 *pValue = V_I4(&var);
4931 else
4932 hr = DISP_E_BADVARTYPE;
4934 return hr;
4937 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
4938 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
4939 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
4940 #define OBJCOMPAT_UNBINDABLE 0x00000004
4941 #define OBJCOMPAT_PINDLL 0x00000008
4942 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
4943 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
4944 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
4945 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
4946 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
4947 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
4948 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
4949 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
4950 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
4952 /* a search table for compatibility flags */
4953 struct objcompat_entry {
4954 const WCHAR name[30];
4955 DWORD value;
4958 /* expected to be sorted by name */
4959 static const struct objcompat_entry objcompat_table[] = {
4960 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
4961 OBJCOMPAT_COCREATESHELLFOLDERONLY },
4962 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
4963 OBJCOMPAT_CTXMENU_LIMITEDQI },
4964 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
4965 OBJCOMPAT_CTXMENU_LIMITEDQI },
4966 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
4967 OBJCOMPAT_CTXMENU_XPQCMFLAGS },
4968 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
4969 OBJCOMPAT_NEEDSFILESYSANCESTOR },
4970 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
4971 OBJCOMPAT_NEEDSSTORAGEANCESTOR },
4972 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
4973 OBJCOMPAT_NOIPROPERTYSTORE },
4974 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
4975 OBJCOMPAT_NOLEGACYWEBVIEW },
4976 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
4977 OBJCOMPAT_NOTAFILESYSTEM },
4978 { {'N','O','_','W','E','B','V','I','E','W',0},
4979 OBJCOMPAT_NO_WEBVIEW },
4980 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
4981 OBJCOMPAT_OTNEEDSSFCACHE },
4982 { {'P','I','N','D','L','L',0},
4983 OBJCOMPAT_PINDLL },
4984 { {'U','N','B','I','N','D','A','B','L','E',0},
4985 OBJCOMPAT_UNBINDABLE }
4988 /**************************************************************************
4989 * SHGetObjectCompatFlags (SHLWAPI.476)
4991 * Function returns an integer representation of compatibility flags stored
4992 * in registry for CLSID under ShellCompatibility subkey.
4994 * PARAMS
4995 * pUnk: pointer to object IUnknown interface, idetifies CLSID
4996 * clsid: pointer to CLSID to retrieve data for
4998 * RETURNS
4999 * 0 on failure, flags set on success
5001 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid)
5003 static const WCHAR compatpathW[] =
5004 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
5005 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
5006 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
5007 'O','b','j','e','c','t','s','\\','%','s',0};
5008 WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */];
5009 DWORD ret, length = sizeof(strW)/sizeof(WCHAR);
5010 OLECHAR *clsid_str;
5011 HKEY key;
5012 INT i;
5014 TRACE("%p %s\n", pUnk, debugstr_guid(clsid));
5016 if (!pUnk && !clsid) return 0;
5018 if (pUnk && !clsid)
5020 FIXME("iface not handled\n");
5021 return 0;
5024 StringFromCLSID(clsid, &clsid_str);
5025 sprintfW(strW, compatpathW, clsid_str);
5026 CoTaskMemFree(clsid_str);
5028 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key);
5029 if (ret != ERROR_SUCCESS) return 0;
5031 /* now collect flag values */
5032 ret = 0;
5033 for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++)
5035 INT left, right, res, x;
5037 /* search in table */
5038 left = 0;
5039 right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1;
5041 while (right >= left) {
5042 x = (left + right) / 2;
5043 res = strcmpW(strW, objcompat_table[x].name);
5044 if (res == 0)
5046 ret |= objcompat_table[x].value;
5047 break;
5049 else if (res < 0)
5050 right = x - 1;
5051 else
5052 left = x + 1;
5055 length = sizeof(strW)/sizeof(WCHAR);
5058 return ret;