push 87b6981010d7405c33b14cddcceec21b47729eba
[wine/hacks.git] / dlls / shlwapi / ordinal.c
blob315208c1614777e603259782508d57f138f1e6af
1 /*
2 * SHLWAPI ordinal functions
4 * Copyright 1997 Marcus Meissner
5 * 1998 Jürgen Schmied
6 * 2001-2003 Jon Griffiths
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
30 #define COBJMACROS
31 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winnls.h"
37 #include "winreg.h"
38 #include "wingdi.h"
39 #include "winuser.h"
40 #include "winver.h"
41 #include "winnetwk.h"
42 #include "mmsystem.h"
43 #include "objbase.h"
44 #include "exdisp.h"
45 #include "shlobj.h"
46 #include "shlwapi.h"
47 #include "shellapi.h"
48 #include "commdlg.h"
49 #include "mlang.h"
50 #include "mshtmhst.h"
51 #include "wine/unicode.h"
52 #include "wine/debug.h"
55 WINE_DEFAULT_DEBUG_CHANNEL(shell);
57 /* DLL handles for late bound calls */
58 extern HINSTANCE shlwapi_hInstance;
59 extern DWORD SHLWAPI_ThreadRef_index;
61 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
62 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
63 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
66 NOTES: Most functions exported by ordinal seem to be superfluous.
67 The reason for these functions to be there is to provide a wrapper
68 for unicode functions to provide these functions on systems without
69 unicode functions eg. win95/win98. Since we have such functions we just
70 call these. If running Wine with native DLLs, some late bound calls may
71 fail. However, it is better to implement the functions in the forward DLL
72 and recommend the builtin rather than reimplementing the calls here!
75 /*************************************************************************
76 * SHLWAPI_DupSharedHandle
78 * Internal implemetation of SHLWAPI_11.
80 static HANDLE SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
81 DWORD dwSrcProcId, DWORD dwAccess,
82 DWORD dwOptions)
84 HANDLE hDst, hSrc;
85 DWORD dwMyProcId = GetCurrentProcessId();
86 HANDLE hRet = NULL;
88 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
89 dwAccess, dwOptions);
91 /* Get dest process handle */
92 if (dwDstProcId == dwMyProcId)
93 hDst = GetCurrentProcess();
94 else
95 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
97 if (hDst)
99 /* Get src process handle */
100 if (dwSrcProcId == dwMyProcId)
101 hSrc = GetCurrentProcess();
102 else
103 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
105 if (hSrc)
107 /* Make handle available to dest process */
108 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
109 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
110 hRet = NULL;
112 if (dwSrcProcId != dwMyProcId)
113 CloseHandle(hSrc);
116 if (dwDstProcId != dwMyProcId)
117 CloseHandle(hDst);
120 TRACE("Returning handle %p\n", hRet);
121 return hRet;
124 /*************************************************************************
125 * @ [SHLWAPI.7]
127 * Create a block of sharable memory and initialise it with data.
129 * PARAMS
130 * lpvData [I] Pointer to data to write
131 * dwSize [I] Size of data
132 * dwProcId [I] ID of process owning data
134 * RETURNS
135 * Success: A shared memory handle
136 * Failure: NULL
138 * NOTES
139 * Ordinals 7-11 provide a set of calls to create shared memory between a
140 * group of processes. The shared memory is treated opaquely in that its size
141 * is not exposed to clients who map it. This is accomplished by storing
142 * the size of the map as the first DWORD of mapped data, and then offsetting
143 * the view pointer returned by this size.
146 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
148 HANDLE hMap;
149 LPVOID pMapped;
150 HANDLE hRet = NULL;
152 TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
154 /* Create file mapping of the correct length */
155 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
156 dwSize + sizeof(dwSize), NULL);
157 if (!hMap)
158 return hRet;
160 /* Get a view in our process address space */
161 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
163 if (pMapped)
165 /* Write size of data, followed by the data, to the view */
166 *((DWORD*)pMapped) = dwSize;
167 if (lpvData)
168 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
170 /* Release view. All further views mapped will be opaque */
171 UnmapViewOfFile(pMapped);
172 hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
173 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
174 DUPLICATE_SAME_ACCESS);
177 CloseHandle(hMap);
178 return hRet;
181 /*************************************************************************
182 * @ [SHLWAPI.8]
184 * Get a pointer to a block of shared memory from a shared memory handle.
186 * PARAMS
187 * hShared [I] Shared memory handle
188 * dwProcId [I] ID of process owning hShared
190 * RETURNS
191 * Success: A pointer to the shared memory
192 * Failure: NULL
195 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
197 HANDLE hDup;
198 LPVOID pMapped;
200 TRACE("(%p %d)\n", hShared, dwProcId);
202 /* Get handle to shared memory for current process */
203 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
204 FILE_MAP_ALL_ACCESS, 0);
205 /* Get View */
206 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
207 CloseHandle(hDup);
209 if (pMapped)
210 return (char *) pMapped + sizeof(DWORD); /* Hide size */
211 return NULL;
214 /*************************************************************************
215 * @ [SHLWAPI.9]
217 * Release a pointer to a block of shared memory.
219 * PARAMS
220 * lpView [I] Shared memory pointer
222 * RETURNS
223 * Success: TRUE
224 * Failure: FALSE
227 BOOL WINAPI SHUnlockShared(LPVOID lpView)
229 TRACE("(%p)\n", lpView);
230 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
233 /*************************************************************************
234 * @ [SHLWAPI.10]
236 * Destroy a block of sharable memory.
238 * PARAMS
239 * hShared [I] Shared memory handle
240 * dwProcId [I] ID of process owning hShared
242 * RETURNS
243 * Success: TRUE
244 * Failure: FALSE
247 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
249 HANDLE hClose;
251 TRACE("(%p %d)\n", hShared, dwProcId);
253 /* Get a copy of the handle for our process, closing the source handle */
254 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
255 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
256 /* Close local copy */
257 return CloseHandle(hClose);
260 /*************************************************************************
261 * @ [SHLWAPI.11]
263 * Copy a sharable memory handle from one process to another.
265 * PARAMS
266 * hShared [I] Shared memory handle to duplicate
267 * dwDstProcId [I] ID of the process wanting the duplicated handle
268 * dwSrcProcId [I] ID of the process owning hShared
269 * dwAccess [I] Desired DuplicateHandle() access
270 * dwOptions [I] Desired DuplicateHandle() options
272 * RETURNS
273 * Success: A handle suitable for use by the dwDstProcId process.
274 * Failure: A NULL handle.
277 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
278 DWORD dwAccess, DWORD dwOptions)
280 HANDLE hRet;
282 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
283 dwAccess, dwOptions);
284 return hRet;
287 /*************************************************************************
288 * @ [SHLWAPI.13]
290 * Create and register a clipboard enumerator for a web browser.
292 * PARAMS
293 * lpBC [I] Binding context
294 * lpUnknown [I] An object exposing the IWebBrowserApp interface
296 * RETURNS
297 * Success: S_OK.
298 * Failure: An HRESULT error code.
300 * NOTES
301 * The enumerator is stored as a property of the web browser. If it does not
302 * yet exist, it is created and set before being registered.
304 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
306 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
307 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
308 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
309 BSTR property;
310 IEnumFORMATETC* pIEnumFormatEtc = NULL;
311 VARIANTARG var;
312 HRESULT hRet;
313 IWebBrowserApp* pBrowser = NULL;
315 TRACE("(%p, %p)\n", lpBC, lpUnknown);
317 /* Get An IWebBrowserApp interface from lpUnknown */
318 hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
319 if (FAILED(hRet) || !pBrowser)
320 return E_NOINTERFACE;
322 V_VT(&var) = VT_EMPTY;
324 /* The property we get is the browsers clipboard enumerator */
325 property = SysAllocString(szProperty);
326 hRet = IWebBrowserApp_GetProperty(pBrowser, property, &var);
327 SysFreeString(property);
328 if (FAILED(hRet))
329 return hRet;
331 if (V_VT(&var) == VT_EMPTY)
333 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
334 char szKeyBuff[128], szValueBuff[128];
335 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
336 FORMATETC* formatList, *format;
337 HKEY hDocs;
339 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
341 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
342 "Version\\Internet Settings\\Accepted Documents", &hDocs))
343 return E_FAIL;
345 /* Get count of values in key */
346 while (!dwRet)
348 dwKeySize = sizeof(szKeyBuff);
349 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
350 dwCount++;
353 dwNumValues = dwCount;
355 /* Note: dwCount = number of items + 1; The extra item is the end node */
356 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
357 if (!formatList)
358 return E_OUTOFMEMORY;
360 if (dwNumValues > 1)
362 dwRet = 0;
363 dwCount = 0;
365 dwNumValues--;
367 /* Register clipboard formats for the values and populate format list */
368 while(!dwRet && dwCount < dwNumValues)
370 dwKeySize = sizeof(szKeyBuff);
371 dwValueSize = sizeof(szValueBuff);
372 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
373 (PBYTE)szValueBuff, &dwValueSize);
374 if (!dwRet)
375 return E_FAIL;
377 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
378 format->ptd = NULL;
379 format->dwAspect = 1;
380 format->lindex = 4;
381 format->tymed = -1;
383 format++;
384 dwCount++;
388 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
389 format->cfFormat = 0;
390 format->ptd = NULL;
391 format->dwAspect = 1;
392 format->lindex = 4;
393 format->tymed = -1;
395 /* Create a clipboard enumerator */
396 hRet = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
398 if (FAILED(hRet) || !pIEnumFormatEtc)
399 return hRet;
401 /* Set our enumerator as the browsers property */
402 V_VT(&var) = VT_UNKNOWN;
403 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
405 hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
406 if (FAILED(hRet))
408 IEnumFORMATETC_Release(pIEnumFormatEtc);
409 goto RegisterDefaultAcceptHeaders_Exit;
413 if (V_VT(&var) == VT_UNKNOWN)
415 /* Our variant is holding the clipboard enumerator */
416 IUnknown* pIUnknown = V_UNKNOWN(&var);
417 IEnumFORMATETC* pClone = NULL;
419 TRACE("Retrieved IEnumFORMATETC property\n");
421 /* Get an IEnumFormatEtc interface from the variants value */
422 pIEnumFormatEtc = NULL;
423 hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
424 (PVOID)&pIEnumFormatEtc);
425 if (hRet == S_OK && pIEnumFormatEtc)
427 /* Clone and register the enumerator */
428 hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
429 if (hRet == S_OK && pClone)
431 RegisterFormatEnumerator(lpBC, pClone, 0);
433 IEnumFORMATETC_Release(pClone);
436 /* Release the IEnumFormatEtc interface */
437 IEnumFORMATETC_Release(pIUnknown);
439 IUnknown_Release(V_UNKNOWN(&var));
442 RegisterDefaultAcceptHeaders_Exit:
443 IWebBrowserApp_Release(pBrowser);
444 return hRet;
447 /*************************************************************************
448 * @ [SHLWAPI.15]
450 * Get Explorers "AcceptLanguage" setting.
452 * PARAMS
453 * langbuf [O] Destination for language string
454 * buflen [I] Length of langbuf in characters
455 * [0] Success: used length of langbuf
457 * RETURNS
458 * Success: S_OK. langbuf is set to the language string found.
459 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
460 * does not contain the setting.
461 * HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), If the buffer is not big enough
463 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
465 static const WCHAR szkeyW[] = {
466 'S','o','f','t','w','a','r','e','\\',
467 'M','i','c','r','o','s','o','f','t','\\',
468 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
469 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
470 static const WCHAR valueW[] = {
471 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
472 DWORD mystrlen, mytype;
473 DWORD len;
474 HKEY mykey;
475 HRESULT retval;
476 LCID mylcid;
477 WCHAR *mystr;
478 LONG lres;
480 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
482 if(!langbuf || !buflen || !*buflen)
483 return E_FAIL;
485 mystrlen = (*buflen > 20) ? *buflen : 20 ;
486 len = mystrlen * sizeof(WCHAR);
487 mystr = HeapAlloc(GetProcessHeap(), 0, len);
488 mystr[0] = 0;
489 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
490 lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
491 RegCloseKey(mykey);
492 len = lstrlenW(mystr);
494 if (!lres && (*buflen > len)) {
495 lstrcpyW(langbuf, mystr);
496 *buflen = len;
497 HeapFree(GetProcessHeap(), 0, mystr);
498 return S_OK;
501 /* Did not find a value in the registry or the user buffer is to small */
502 mylcid = GetUserDefaultLCID();
503 retval = LcidToRfc1766W(mylcid, mystr, mystrlen);
504 len = lstrlenW(mystr);
506 memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
507 HeapFree(GetProcessHeap(), 0, mystr);
509 if (*buflen > len) {
510 *buflen = len;
511 return S_OK;
514 *buflen = 0;
515 return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
518 /*************************************************************************
519 * @ [SHLWAPI.14]
521 * Ascii version of GetAcceptLanguagesW.
523 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
525 WCHAR *langbufW;
526 DWORD buflenW, convlen;
527 HRESULT retval;
529 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
531 if(!langbuf || !buflen || !*buflen) return E_FAIL;
533 buflenW = *buflen;
534 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
535 retval = GetAcceptLanguagesW(langbufW, &buflenW);
537 if (retval == S_OK)
539 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
540 convlen--; /* do not count the terminating 0 */
542 else /* copy partial string anyway */
544 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
545 if (convlen < *buflen)
547 langbuf[convlen] = 0;
548 convlen--; /* do not count the terminating 0 */
550 else
552 convlen = *buflen;
555 *buflen = buflenW ? convlen : 0;
557 HeapFree(GetProcessHeap(), 0, langbufW);
558 return retval;
561 /*************************************************************************
562 * @ [SHLWAPI.23]
564 * Convert a GUID to a string.
566 * PARAMS
567 * guid [I] GUID to convert
568 * lpszDest [O] Destination for string
569 * cchMax [I] Length of output buffer
571 * RETURNS
572 * The length of the string created.
574 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
576 char xguid[40];
577 INT iLen;
579 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
581 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
582 guid->Data1, guid->Data2, guid->Data3,
583 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
584 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
586 iLen = strlen(xguid) + 1;
588 if (iLen > cchMax)
589 return 0;
590 memcpy(lpszDest, xguid, iLen);
591 return iLen;
594 /*************************************************************************
595 * @ [SHLWAPI.24]
597 * Convert a GUID to a string.
599 * PARAMS
600 * guid [I] GUID to convert
601 * str [O] Destination for string
602 * cmax [I] Length of output buffer
604 * RETURNS
605 * The length of the string created.
607 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
609 WCHAR xguid[40];
610 INT iLen;
611 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
612 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
613 'X','%','0','2','X','%','0','2','X','}',0};
615 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
617 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
618 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
619 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
621 iLen = strlenW(xguid) + 1;
623 if (iLen > cchMax)
624 return 0;
625 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
626 return iLen;
629 /*************************************************************************
630 * @ [SHLWAPI.29]
632 * Determine if a Unicode character is a space.
634 * PARAMS
635 * wc [I] Character to check.
637 * RETURNS
638 * TRUE, if wc is a space,
639 * FALSE otherwise.
641 BOOL WINAPI IsCharSpaceW(WCHAR wc)
643 WORD CharType;
645 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
648 /*************************************************************************
649 * @ [SHLWAPI.30]
651 * Determine if a Unicode character is a blank.
653 * PARAMS
654 * wc [I] Character to check.
656 * RETURNS
657 * TRUE, if wc is a blank,
658 * FALSE otherwise.
661 BOOL WINAPI IsCharBlankW(WCHAR wc)
663 WORD CharType;
665 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
668 /*************************************************************************
669 * @ [SHLWAPI.31]
671 * Determine if a Unicode character is punctuation.
673 * PARAMS
674 * wc [I] Character to check.
676 * RETURNS
677 * TRUE, if wc is punctuation,
678 * FALSE otherwise.
680 BOOL WINAPI IsCharPunctW(WCHAR wc)
682 WORD CharType;
684 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
687 /*************************************************************************
688 * @ [SHLWAPI.32]
690 * Determine if a Unicode character is a control character.
692 * PARAMS
693 * wc [I] Character to check.
695 * RETURNS
696 * TRUE, if wc is a control character,
697 * FALSE otherwise.
699 BOOL WINAPI IsCharCntrlW(WCHAR wc)
701 WORD CharType;
703 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
706 /*************************************************************************
707 * @ [SHLWAPI.33]
709 * Determine if a Unicode character is a digit.
711 * PARAMS
712 * wc [I] Character to check.
714 * RETURNS
715 * TRUE, if wc is a digit,
716 * FALSE otherwise.
718 BOOL WINAPI IsCharDigitW(WCHAR wc)
720 WORD CharType;
722 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
725 /*************************************************************************
726 * @ [SHLWAPI.34]
728 * Determine if a Unicode character is a hex digit.
730 * PARAMS
731 * wc [I] Character to check.
733 * RETURNS
734 * TRUE, if wc is a hex digit,
735 * FALSE otherwise.
737 BOOL WINAPI IsCharXDigitW(WCHAR wc)
739 WORD CharType;
741 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
744 /*************************************************************************
745 * @ [SHLWAPI.35]
748 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type)
750 return GetStringTypeW(CT_CTYPE3, src, count, type);
753 /*************************************************************************
754 * @ [SHLWAPI.151]
756 * Compare two Ascii strings up to a given length.
758 * PARAMS
759 * lpszSrc [I] Source string
760 * lpszCmp [I] String to compare to lpszSrc
761 * len [I] Maximum length
763 * RETURNS
764 * A number greater than, less than or equal to 0 depending on whether
765 * lpszSrc is greater than, less than or equal to lpszCmp.
767 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
769 return StrCmpNA(lpszSrc, lpszCmp, len);
772 /*************************************************************************
773 * @ [SHLWAPI.152]
775 * Unicode version of StrCmpNCA.
777 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
779 return StrCmpNW(lpszSrc, lpszCmp, len);
782 /*************************************************************************
783 * @ [SHLWAPI.153]
785 * Compare two Ascii strings up to a given length, ignoring case.
787 * PARAMS
788 * lpszSrc [I] Source string
789 * lpszCmp [I] String to compare to lpszSrc
790 * len [I] Maximum length
792 * RETURNS
793 * A number greater than, less than or equal to 0 depending on whether
794 * lpszSrc is greater than, less than or equal to lpszCmp.
796 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
798 return StrCmpNIA(lpszSrc, lpszCmp, len);
801 /*************************************************************************
802 * @ [SHLWAPI.154]
804 * Unicode version of StrCmpNICA.
806 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
808 return StrCmpNIW(lpszSrc, lpszCmp, len);
811 /*************************************************************************
812 * @ [SHLWAPI.155]
814 * Compare two Ascii strings.
816 * PARAMS
817 * lpszSrc [I] Source string
818 * lpszCmp [I] String to compare to lpszSrc
820 * RETURNS
821 * A number greater than, less than or equal to 0 depending on whether
822 * lpszSrc is greater than, less than or equal to lpszCmp.
824 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
826 return lstrcmpA(lpszSrc, lpszCmp);
829 /*************************************************************************
830 * @ [SHLWAPI.156]
832 * Unicode version of StrCmpCA.
834 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
836 return lstrcmpW(lpszSrc, lpszCmp);
839 /*************************************************************************
840 * @ [SHLWAPI.157]
842 * Compare two Ascii strings, ignoring case.
844 * PARAMS
845 * lpszSrc [I] Source string
846 * lpszCmp [I] String to compare to lpszSrc
848 * RETURNS
849 * A number greater than, less than or equal to 0 depending on whether
850 * lpszSrc is greater than, less than or equal to lpszCmp.
852 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
854 return lstrcmpiA(lpszSrc, lpszCmp);
857 /*************************************************************************
858 * @ [SHLWAPI.158]
860 * Unicode version of StrCmpICA.
862 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
864 return lstrcmpiW(lpszSrc, lpszCmp);
867 /*************************************************************************
868 * @ [SHLWAPI.160]
870 * Get an identification string for the OS and explorer.
872 * PARAMS
873 * lpszDest [O] Destination for Id string
874 * dwDestLen [I] Length of lpszDest
876 * RETURNS
877 * TRUE, If the string was created successfully
878 * FALSE, Otherwise
880 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
882 WCHAR buff[2084];
884 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
886 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
888 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
889 return TRUE;
891 return FALSE;
894 /*************************************************************************
895 * @ [SHLWAPI.161]
897 * Unicode version of SHAboutInfoA.
899 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
901 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
902 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
903 ' ','E','x','p','l','o','r','e','r','\0' };
904 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
905 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
906 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
907 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
908 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
909 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
910 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
911 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
912 ' ','E','x','p','l','o','r','e','r','\\',
913 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
914 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
915 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
916 'V','e','r','s','i','o','n','\0' };
917 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
918 'O','w','n','e','r','\0' };
919 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
920 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
921 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
922 static const WCHAR szUpdate[] = { 'I','E','A','K',
923 'U','p','d','a','t','e','U','r','l','\0' };
924 static const WCHAR szHelp[] = { 'I','E','A','K',
925 'H','e','l','p','S','t','r','i','n','g','\0' };
926 WCHAR buff[2084];
927 HKEY hReg;
928 DWORD dwType, dwLen;
930 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
932 if (!lpszDest)
933 return FALSE;
935 *lpszDest = '\0';
937 /* Try the NT key first, followed by 95/98 key */
938 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
939 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
940 return FALSE;
942 /* OS Version */
943 buff[0] = '\0';
944 dwLen = 30;
945 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
947 DWORD dwStrLen = strlenW(buff);
948 dwLen = 30 - dwStrLen;
949 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
950 szCustomized, &dwType, buff+dwStrLen, &dwLen);
952 StrCatBuffW(lpszDest, buff, dwDestLen);
954 /* ~Registered Owner */
955 buff[0] = '~';
956 dwLen = 256;
957 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
958 buff[1] = '\0';
959 StrCatBuffW(lpszDest, buff, dwDestLen);
961 /* ~Registered Organization */
962 dwLen = 256;
963 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
964 buff[1] = '\0';
965 StrCatBuffW(lpszDest, buff, dwDestLen);
967 /* FIXME: Not sure where this number comes from */
968 buff[0] = '~';
969 buff[1] = '0';
970 buff[2] = '\0';
971 StrCatBuffW(lpszDest, buff, dwDestLen);
973 /* ~Product Id */
974 dwLen = 256;
975 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
976 buff[1] = '\0';
977 StrCatBuffW(lpszDest, buff, dwDestLen);
979 /* ~IE Update Url */
980 dwLen = 2048;
981 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
982 buff[1] = '\0';
983 StrCatBuffW(lpszDest, buff, dwDestLen);
985 /* ~IE Help String */
986 dwLen = 256;
987 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
988 buff[1] = '\0';
989 StrCatBuffW(lpszDest, buff, dwDestLen);
991 RegCloseKey(hReg);
992 return TRUE;
995 /*************************************************************************
996 * @ [SHLWAPI.163]
998 * Call IOleCommandTarget_QueryStatus() on an object.
1000 * PARAMS
1001 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1002 * pguidCmdGroup [I] GUID for the command group
1003 * cCmds [I]
1004 * prgCmds [O] Commands
1005 * pCmdText [O] Command text
1007 * RETURNS
1008 * Success: S_OK.
1009 * Failure: E_FAIL, if lpUnknown is NULL.
1010 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1011 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1013 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1014 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1016 HRESULT hRet = E_FAIL;
1018 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1020 if (lpUnknown)
1022 IOleCommandTarget* lpOle;
1024 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1025 (void**)&lpOle);
1027 if (SUCCEEDED(hRet) && lpOle)
1029 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1030 prgCmds, pCmdText);
1031 IOleCommandTarget_Release(lpOle);
1034 return hRet;
1037 /*************************************************************************
1038 * @ [SHLWAPI.164]
1040 * Call IOleCommandTarget_Exec() on an object.
1042 * PARAMS
1043 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1044 * pguidCmdGroup [I] GUID for the command group
1046 * RETURNS
1047 * Success: S_OK.
1048 * Failure: E_FAIL, if lpUnknown is NULL.
1049 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1050 * Otherwise, an error code from IOleCommandTarget_Exec().
1052 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1053 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1054 VARIANT* pvaOut)
1056 HRESULT hRet = E_FAIL;
1058 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1059 nCmdexecopt, pvaIn, pvaOut);
1061 if (lpUnknown)
1063 IOleCommandTarget* lpOle;
1065 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1066 (void**)&lpOle);
1067 if (SUCCEEDED(hRet) && lpOle)
1069 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1070 nCmdexecopt, pvaIn, pvaOut);
1071 IOleCommandTarget_Release(lpOle);
1074 return hRet;
1077 /*************************************************************************
1078 * @ [SHLWAPI.165]
1080 * Retrieve, modify, and re-set a value from a window.
1082 * PARAMS
1083 * hWnd [I] Window to get value from
1084 * offset [I] Offset of value
1085 * wMask [I] Mask for uiFlags
1086 * wFlags [I] Bits to set in window value
1088 * RETURNS
1089 * The new value as it was set, or 0 if any parameter is invalid.
1091 * NOTES
1092 * Any bits set in uiMask are cleared from the value, then any bits set in
1093 * uiFlags are set in the value.
1095 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
1097 LONG ret = GetWindowLongA(hwnd, offset);
1098 LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);
1100 if (newFlags != ret)
1101 ret = SetWindowLongA(hwnd, offset, newFlags);
1102 return ret;
1105 /*************************************************************************
1106 * @ [SHLWAPI.167]
1108 * Change a window's parent.
1110 * PARAMS
1111 * hWnd [I] Window to change parent of
1112 * hWndParent [I] New parent window
1114 * RETURNS
1115 * The old parent of hWnd.
1117 * NOTES
1118 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1119 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1121 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1123 TRACE("%p, %p\n", hWnd, hWndParent);
1125 if(GetParent(hWnd) == hWndParent)
1126 return 0;
1128 if(hWndParent)
1129 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1130 else
1131 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1133 return SetParent(hWnd, hWndParent);
1136 /*************************************************************************
1137 * @ [SHLWAPI.168]
1139 * Locate and advise a connection point in an IConnectionPointContainer object.
1141 * PARAMS
1142 * lpUnkSink [I] Sink for the connection point advise call
1143 * riid [I] REFIID of connection point to advise
1144 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1145 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1146 * lpCookie [O] Pointer to connection point cookie
1147 * lppCP [O] Destination for the IConnectionPoint found
1149 * RETURNS
1150 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1151 * that was advised. The caller is responsible for releasing it.
1152 * Failure: E_FAIL, if any arguments are invalid.
1153 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1154 * Or an HRESULT error code if any call fails.
1156 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL fConnect,
1157 IUnknown* lpUnknown, LPDWORD lpCookie,
1158 IConnectionPoint **lppCP)
1160 HRESULT hRet;
1161 IConnectionPointContainer* lpContainer;
1162 IConnectionPoint *lpCP;
1164 if(!lpUnknown || (fConnect && !lpUnkSink))
1165 return E_FAIL;
1167 if(lppCP)
1168 *lppCP = NULL;
1170 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1171 (void**)&lpContainer);
1172 if (SUCCEEDED(hRet))
1174 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1176 if (SUCCEEDED(hRet))
1178 if(!fConnect)
1179 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1180 else
1181 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1183 if (FAILED(hRet))
1184 *lpCookie = 0;
1186 if (lppCP && SUCCEEDED(hRet))
1187 *lppCP = lpCP; /* Caller keeps the interface */
1188 else
1189 IConnectionPoint_Release(lpCP); /* Release it */
1192 IUnknown_Release(lpContainer);
1194 return hRet;
1197 /*************************************************************************
1198 * @ [SHLWAPI.169]
1200 * Release an interface.
1202 * PARAMS
1203 * lpUnknown [I] Object to release
1205 * RETURNS
1206 * Nothing.
1208 DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1210 IUnknown *temp;
1212 TRACE("(%p)\n",lpUnknown);
1214 if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1215 temp = *lpUnknown;
1216 *lpUnknown = NULL;
1218 TRACE("doing Release\n");
1220 return IUnknown_Release(temp);
1223 /*************************************************************************
1224 * @ [SHLWAPI.170]
1226 * Skip '//' if present in a string.
1228 * PARAMS
1229 * lpszSrc [I] String to check for '//'
1231 * RETURNS
1232 * Success: The next character after the '//' or the string if not present
1233 * Failure: NULL, if lpszStr is NULL.
1235 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1237 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1238 lpszSrc += 2;
1239 return lpszSrc;
1242 /*************************************************************************
1243 * @ [SHLWAPI.171]
1245 * Check if two interfaces come from the same object.
1247 * PARAMS
1248 * lpInt1 [I] Interface to check against lpInt2.
1249 * lpInt2 [I] Interface to check against lpInt1.
1251 * RETURNS
1252 * TRUE, If the interfaces come from the same object.
1253 * FALSE Otherwise.
1255 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1257 LPVOID lpUnknown1, lpUnknown2;
1259 TRACE("%p %p\n", lpInt1, lpInt2);
1261 if (!lpInt1 || !lpInt2)
1262 return FALSE;
1264 if (lpInt1 == lpInt2)
1265 return TRUE;
1267 if (FAILED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown, &lpUnknown1)))
1268 return FALSE;
1270 if (FAILED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown, &lpUnknown2)))
1271 return FALSE;
1273 if (lpUnknown1 == lpUnknown2)
1274 return TRUE;
1276 return FALSE;
1279 /*************************************************************************
1280 * @ [SHLWAPI.172]
1282 * Get the window handle of an object.
1284 * PARAMS
1285 * lpUnknown [I] Object to get the window handle of
1286 * lphWnd [O] Destination for window handle
1288 * RETURNS
1289 * Success: S_OK. lphWnd contains the objects window handle.
1290 * Failure: An HRESULT error code.
1292 * NOTES
1293 * lpUnknown is expected to support one of the following interfaces:
1294 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1296 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1298 IUnknown *lpOle;
1299 HRESULT hRet = E_FAIL;
1301 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1303 if (!lpUnknown)
1304 return hRet;
1306 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1308 if (FAILED(hRet))
1310 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1312 if (FAILED(hRet))
1314 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1315 (void**)&lpOle);
1319 if (SUCCEEDED(hRet))
1321 /* Lazyness here - Since GetWindow() is the first method for the above 3
1322 * interfaces, we use the same call for them all.
1324 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1325 IUnknown_Release(lpOle);
1326 if (lphWnd)
1327 TRACE("Returning HWND=%p\n", *lphWnd);
1330 return hRet;
1333 /*************************************************************************
1334 * @ [SHLWAPI.173]
1336 * Call a method on as as yet unidentified object.
1338 * PARAMS
1339 * pUnk [I] Object supporting the unidentified interface,
1340 * arg [I] Argument for the call on the object.
1342 * RETURNS
1343 * S_OK.
1345 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1347 static const GUID guid_173 = {
1348 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1350 IMalloc *pUnk2;
1352 TRACE("(%p,%d)\n", pUnk, arg);
1354 /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1355 * We use this interface as its vtable entry is compatible with the
1356 * object in question.
1357 * FIXME: Find out what this object is and where it should be defined.
1359 if (pUnk &&
1360 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1362 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1363 IMalloc_Release(pUnk2);
1365 return S_OK;
1368 /*************************************************************************
1369 * @ [SHLWAPI.174]
1371 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1372 * an object.
1375 HRESULT WINAPI IUnknown_SetSite(
1376 IUnknown *obj, /* [in] OLE object */
1377 IUnknown *site) /* [in] Site interface */
1379 HRESULT hr;
1380 IObjectWithSite *iobjwithsite;
1381 IInternetSecurityManager *isecmgr;
1383 if (!obj) return E_FAIL;
1385 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1386 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1387 if (SUCCEEDED(hr))
1389 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1390 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1391 IUnknown_Release(iobjwithsite);
1393 else
1395 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1396 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1397 if (FAILED(hr)) return hr;
1399 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1400 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1401 IUnknown_Release(isecmgr);
1403 return hr;
1406 /*************************************************************************
1407 * @ [SHLWAPI.175]
1409 * Call IPersist_GetClassID() on an object.
1411 * PARAMS
1412 * lpUnknown [I] Object supporting the IPersist interface
1413 * lpClassId [O] Destination for Class Id
1415 * RETURNS
1416 * Success: S_OK. lpClassId contains the Class Id requested.
1417 * Failure: E_FAIL, If lpUnknown is NULL,
1418 * E_NOINTERFACE If lpUnknown does not support IPersist,
1419 * Or an HRESULT error code.
1421 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1423 IPersist* lpPersist;
1424 HRESULT hRet = E_FAIL;
1426 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1428 if (lpUnknown)
1430 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1431 if (SUCCEEDED(hRet))
1433 IPersist_GetClassID(lpPersist, lpClassId);
1434 IPersist_Release(lpPersist);
1437 return hRet;
1440 /*************************************************************************
1441 * @ [SHLWAPI.176]
1443 * Retrieve a Service Interface from an object.
1445 * PARAMS
1446 * lpUnknown [I] Object to get an IServiceProvider interface from
1447 * sid [I] Service ID for IServiceProvider_QueryService() call
1448 * riid [I] Function requested for QueryService call
1449 * lppOut [O] Destination for the service interface pointer
1451 * RETURNS
1452 * Success: S_OK. lppOut contains an object providing the requested service
1453 * Failure: An HRESULT error code
1455 * NOTES
1456 * lpUnknown is expected to support the IServiceProvider interface.
1458 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1459 LPVOID *lppOut)
1461 IServiceProvider* pService = NULL;
1462 HRESULT hRet;
1464 if (!lppOut)
1465 return E_FAIL;
1467 *lppOut = NULL;
1469 if (!lpUnknown)
1470 return E_FAIL;
1472 /* Get an IServiceProvider interface from the object */
1473 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1474 (LPVOID*)&pService);
1476 if (hRet == S_OK && pService)
1478 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1480 /* Get a Service interface from the object */
1481 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1483 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1485 /* Release the IServiceProvider interface */
1486 IUnknown_Release(pService);
1488 return hRet;
1491 /*************************************************************************
1492 * @ [SHLWAPI.479]
1494 * Call an object's UIActivateIO method.
1496 * PARAMS
1497 * unknown [I] Object to call the UIActivateIO method on
1498 * activate [I] Parameter for UIActivateIO call
1499 * msg [I] Parameter for UIActivateIO call
1501 * RETURNS
1502 * Success: Value of UI_ActivateIO call
1503 * Failure: An HRESULT error code
1505 * NOTES
1506 * unknown is expected to support the IInputObject interface.
1508 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg)
1510 IInputObject* object = NULL;
1511 HRESULT ret;
1513 if (!unknown)
1514 return E_FAIL;
1516 /* Get an IInputObject interface from the object */
1517 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
1519 if (ret == S_OK)
1521 ret = IInputObject_UIActivateIO(object, activate, msg);
1522 IUnknown_Release(object);
1525 return ret;
1528 /*************************************************************************
1529 * @ [SHLWAPI.177]
1531 * Loads a popup menu.
1533 * PARAMS
1534 * hInst [I] Instance handle
1535 * szName [I] Menu name
1537 * RETURNS
1538 * Success: TRUE.
1539 * Failure: FALSE.
1541 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1543 HMENU hMenu;
1545 if ((hMenu = LoadMenuW(hInst, szName)))
1547 if (GetSubMenu(hMenu, 0))
1548 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1550 DestroyMenu(hMenu);
1551 return TRUE;
1553 return FALSE;
1556 typedef struct _enumWndData
1558 UINT uiMsgId;
1559 WPARAM wParam;
1560 LPARAM lParam;
1561 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1562 } enumWndData;
1564 /* Callback for SHLWAPI_178 */
1565 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1567 enumWndData *data = (enumWndData *)lParam;
1569 TRACE("(%p,%p)\n", hWnd, data);
1570 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1571 return TRUE;
1574 /*************************************************************************
1575 * @ [SHLWAPI.178]
1577 * Send or post a message to every child of a window.
1579 * PARAMS
1580 * hWnd [I] Window whose children will get the messages
1581 * uiMsgId [I] Message Id
1582 * wParam [I] WPARAM of message
1583 * lParam [I] LPARAM of message
1584 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1586 * RETURNS
1587 * Nothing.
1589 * NOTES
1590 * The appropriate ASCII or Unicode function is called for the window.
1592 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1594 enumWndData data;
1596 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1598 if(hWnd)
1600 data.uiMsgId = uiMsgId;
1601 data.wParam = wParam;
1602 data.lParam = lParam;
1604 if (bSend)
1605 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1606 else
1607 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1609 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1613 /*************************************************************************
1614 * @ [SHLWAPI.180]
1616 * Remove all sub-menus from a menu.
1618 * PARAMS
1619 * hMenu [I] Menu to remove sub-menus from
1621 * RETURNS
1622 * Success: 0. All sub-menus under hMenu are removed
1623 * Failure: -1, if any parameter is invalid
1625 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1627 int iItemCount = GetMenuItemCount(hMenu) - 1;
1628 while (iItemCount >= 0)
1630 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1631 if (hSubMenu)
1632 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1633 iItemCount--;
1635 return iItemCount;
1638 /*************************************************************************
1639 * @ [SHLWAPI.181]
1641 * Enable or disable a menu item.
1643 * PARAMS
1644 * hMenu [I] Menu holding menu item
1645 * uID [I] ID of menu item to enable/disable
1646 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1648 * RETURNS
1649 * The return code from EnableMenuItem.
1651 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1653 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1656 /*************************************************************************
1657 * @ [SHLWAPI.182]
1659 * Check or uncheck a menu item.
1661 * PARAMS
1662 * hMenu [I] Menu holding menu item
1663 * uID [I] ID of menu item to check/uncheck
1664 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1666 * RETURNS
1667 * The return code from CheckMenuItem.
1669 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1671 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1674 /*************************************************************************
1675 * @ [SHLWAPI.183]
1677 * Register a window class if it isn't already.
1679 * PARAMS
1680 * lpWndClass [I] Window class to register
1682 * RETURNS
1683 * The result of the RegisterClassA call.
1685 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1687 WNDCLASSA wca;
1688 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1689 return TRUE;
1690 return (DWORD)RegisterClassA(wndclass);
1693 /*************************************************************************
1694 * @ [SHLWAPI.186]
1696 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1697 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1699 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1700 POINTL pt = { 0, 0 };
1702 if (!lpPt)
1703 lpPt = &pt;
1705 if (!pdwEffect)
1706 pdwEffect = &dwEffect;
1708 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1710 if (*pdwEffect)
1711 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1713 IDropTarget_DragLeave(pDrop);
1714 return TRUE;
1717 /*************************************************************************
1718 * @ [SHLWAPI.187]
1720 * Call IPersistPropertyBag_Load() on an object.
1722 * PARAMS
1723 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1724 * lpPropBag [O] Destination for loaded IPropertyBag
1726 * RETURNS
1727 * Success: S_OK.
1728 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1730 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1732 IPersistPropertyBag* lpPPBag;
1733 HRESULT hRet = E_FAIL;
1735 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1737 if (lpUnknown)
1739 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1740 (void**)&lpPPBag);
1741 if (SUCCEEDED(hRet) && lpPPBag)
1743 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1744 IPersistPropertyBag_Release(lpPPBag);
1747 return hRet;
1750 /*************************************************************************
1751 * @ [SHLWAPI.188]
1753 * Call IOleControlSite_TranslateAccelerator() on an object.
1755 * PARAMS
1756 * lpUnknown [I] Object supporting the IOleControlSite interface.
1757 * lpMsg [I] Key message to be processed.
1758 * dwModifiers [I] Flags containing the state of the modifier keys.
1760 * RETURNS
1761 * Success: S_OK.
1762 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1764 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1766 IOleControlSite* lpCSite = NULL;
1767 HRESULT hRet = E_INVALIDARG;
1769 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1770 if (lpUnknown)
1772 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1773 (void**)&lpCSite);
1774 if (SUCCEEDED(hRet) && lpCSite)
1776 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1777 IOleControlSite_Release(lpCSite);
1780 return hRet;
1784 /*************************************************************************
1785 * @ [SHLWAPI.189]
1787 * Call IOleControlSite_OnFocus() on an object.
1789 * PARAMS
1790 * lpUnknown [I] Object supporting the IOleControlSite interface.
1791 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1793 * RETURNS
1794 * Success: S_OK.
1795 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1797 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
1799 IOleControlSite* lpCSite = NULL;
1800 HRESULT hRet = E_FAIL;
1802 TRACE("(%p,%s)\n", lpUnknown, fGotFocus ? "TRUE" : "FALSE");
1803 if (lpUnknown)
1805 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1806 (void**)&lpCSite);
1807 if (SUCCEEDED(hRet) && lpCSite)
1809 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1810 IOleControlSite_Release(lpCSite);
1813 return hRet;
1816 /*************************************************************************
1817 * @ [SHLWAPI.190]
1819 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1820 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1822 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1823 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1824 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1825 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1826 HRESULT hRet = E_INVALIDARG;
1827 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1829 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1831 if (lpUnknown && lpArg4)
1833 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1834 (REFGUID)function_id, (void**)&lpUnkInner);
1836 if (SUCCEEDED(hRet) && lpUnkInner)
1838 /* FIXME: The type of service object requested is unknown, however
1839 * testing shows that its first method is called with 4 parameters.
1840 * Fake this by using IParseDisplayName_ParseDisplayName since the
1841 * signature and position in the vtable matches our unknown object type.
1843 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1844 lpArg1, lpArg2, lpArg3, lpArg4);
1845 IUnknown_Release(lpUnkInner);
1848 return hRet;
1851 /*************************************************************************
1852 * @ [SHLWAPI.192]
1854 * Get a sub-menu from a menu item.
1856 * PARAMS
1857 * hMenu [I] Menu to get sub-menu from
1858 * uID [I] ID of menu item containing sub-menu
1860 * RETURNS
1861 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1863 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1865 MENUITEMINFOW mi;
1867 TRACE("(%p,%u)\n", hMenu, uID);
1869 mi.cbSize = sizeof(mi);
1870 mi.fMask = MIIM_SUBMENU;
1872 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1873 return NULL;
1875 return mi.hSubMenu;
1878 /*************************************************************************
1879 * @ [SHLWAPI.193]
1881 * Get the color depth of the primary display.
1883 * PARAMS
1884 * None.
1886 * RETURNS
1887 * The color depth of the primary display.
1889 DWORD WINAPI SHGetCurColorRes(void)
1891 HDC hdc;
1892 DWORD ret;
1894 TRACE("()\n");
1896 hdc = GetDC(0);
1897 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1898 ReleaseDC(0, hdc);
1899 return ret;
1902 /*************************************************************************
1903 * @ [SHLWAPI.194]
1905 * Wait for a message to arrive, with a timeout.
1907 * PARAMS
1908 * hand [I] Handle to query
1909 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1911 * RETURNS
1912 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1913 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1914 * message is available.
1916 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
1918 DWORD dwEndTicks = GetTickCount() + dwTimeout;
1919 DWORD dwRet;
1921 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
1923 MSG msg;
1925 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
1927 if (dwTimeout != INFINITE)
1929 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
1930 return WAIT_TIMEOUT;
1934 return dwRet;
1937 /*************************************************************************
1938 * @ [SHLWAPI.195]
1940 * Determine if a shell folder can be expanded.
1942 * PARAMS
1943 * lpFolder [I] Parent folder containing the object to test.
1944 * pidl [I] Id of the object to test.
1946 * RETURNS
1947 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
1948 * Failure: E_INVALIDARG, if any argument is invalid.
1950 * NOTES
1951 * If the object to be tested does not expose the IQueryInfo() interface it
1952 * will not be identified as an expandable folder.
1954 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
1956 HRESULT hRet = E_INVALIDARG;
1957 IQueryInfo *lpInfo;
1959 if (lpFolder && pidl)
1961 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
1962 NULL, (void**)&lpInfo);
1963 if (FAILED(hRet))
1964 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
1965 else
1967 DWORD dwFlags = 0;
1969 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
1970 * currently used". Really? You wouldn't be holding out on me would you?
1972 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
1974 if (SUCCEEDED(hRet))
1976 /* 0x2 is an undocumented flag apparently indicating expandability */
1977 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
1980 IQueryInfo_Release(lpInfo);
1983 return hRet;
1986 /*************************************************************************
1987 * @ [SHLWAPI.197]
1989 * Blank out a region of text by drawing the background only.
1991 * PARAMS
1992 * hDC [I] Device context to draw in
1993 * pRect [I] Area to draw in
1994 * cRef [I] Color to draw in
1996 * RETURNS
1997 * Nothing.
1999 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2001 COLORREF cOldColor = SetBkColor(hDC, cRef);
2002 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2003 SetBkColor(hDC, cOldColor);
2004 return 0;
2007 /*************************************************************************
2008 * @ [SHLWAPI.198]
2010 * Return the value associated with a key in a map.
2012 * PARAMS
2013 * lpKeys [I] A list of keys of length iLen
2014 * lpValues [I] A list of values associated with lpKeys, of length iLen
2015 * iLen [I] Length of both lpKeys and lpValues
2016 * iKey [I] The key value to look up in lpKeys
2018 * RETURNS
2019 * The value in lpValues associated with iKey, or -1 if iKey is not
2020 * found in lpKeys.
2022 * NOTES
2023 * - If two elements in the map share the same key, this function returns
2024 * the value closest to the start of the map
2025 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2027 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2029 if (lpKeys && lpValues)
2031 int i = 0;
2033 while (i < iLen)
2035 if (lpKeys[i] == iKey)
2036 return lpValues[i]; /* Found */
2037 i++;
2040 return -1; /* Not found */
2044 /*************************************************************************
2045 * @ [SHLWAPI.199]
2047 * Copy an interface pointer
2049 * PARAMS
2050 * lppDest [O] Destination for copy
2051 * lpUnknown [I] Source for copy
2053 * RETURNS
2054 * Nothing.
2056 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2058 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2060 if (lppDest)
2061 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2063 if (lpUnknown)
2065 /* Copy */
2066 IUnknown_AddRef(lpUnknown);
2067 *lppDest = lpUnknown;
2071 /*************************************************************************
2072 * @ [SHLWAPI.200]
2075 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2076 REFGUID riidCmdGrp, ULONG cCmds,
2077 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2079 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2080 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2082 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2083 return DRAGDROP_E_NOTREGISTERED;
2086 /*************************************************************************
2087 * @ [SHLWAPI.201]
2090 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2091 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2092 VARIANT* pvaOut)
2094 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2095 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2096 return DRAGDROP_E_NOTREGISTERED;
2099 /*************************************************************************
2100 * @ [SHLWAPI.202]
2103 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2105 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2106 return DRAGDROP_E_NOTREGISTERED;
2109 /*************************************************************************
2110 * @ [SHLWAPI.204]
2112 * Determine if a window is not a child of another window.
2114 * PARAMS
2115 * hParent [I] Suspected parent window
2116 * hChild [I] Suspected child window
2118 * RETURNS
2119 * TRUE: If hChild is a child window of hParent
2120 * FALSE: If hChild is not a child window of hParent, or they are equal
2122 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2124 TRACE("(%p,%p)\n", hParent, hChild);
2126 if (!hParent || !hChild)
2127 return TRUE;
2128 else if(hParent == hChild)
2129 return FALSE;
2130 return !IsChild(hParent, hChild);
2133 /*************************************************************************
2134 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2137 typedef struct
2139 DWORD num_items; /* Number of elements inserted */
2140 void *mem; /* Ptr to array */
2141 DWORD blocks_alloced; /* Number of elements allocated */
2142 BYTE inc; /* Number of elements to grow by when we need to expand */
2143 BYTE block_size; /* Size in bytes of an element */
2144 BYTE flags; /* Flags */
2145 } FDSA_info;
2147 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2149 /*************************************************************************
2150 * @ [SHLWAPI.208]
2152 * Initialize an FDSA array.
2154 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2155 DWORD init_blocks)
2157 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2159 if(inc == 0)
2160 inc = 1;
2162 if(mem)
2163 memset(mem, 0, block_size * init_blocks);
2165 info->num_items = 0;
2166 info->inc = inc;
2167 info->mem = mem;
2168 info->blocks_alloced = init_blocks;
2169 info->block_size = block_size;
2170 info->flags = 0;
2172 return TRUE;
2175 /*************************************************************************
2176 * @ [SHLWAPI.209]
2178 * Destroy an FDSA array
2180 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2182 TRACE("(%p)\n", info);
2184 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2186 HeapFree(GetProcessHeap(), 0, info->mem);
2187 return FALSE;
2190 return TRUE;
2193 /*************************************************************************
2194 * @ [SHLWAPI.210]
2196 * Insert element into an FDSA array
2198 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
2200 TRACE("(%p 0x%08x %p)\n", info, where, block);
2201 if(where > info->num_items)
2202 where = info->num_items;
2204 if(info->num_items >= info->blocks_alloced)
2206 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2207 if(info->flags & 0x1)
2208 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2209 else
2211 void *old_mem = info->mem;
2212 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2213 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2215 info->blocks_alloced += info->inc;
2216 info->flags |= 0x1;
2219 if(where < info->num_items)
2221 memmove((char*)info->mem + (where + 1) * info->block_size,
2222 (char*)info->mem + where * info->block_size,
2223 (info->num_items - where) * info->block_size);
2225 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2227 info->num_items++;
2228 return where;
2231 /*************************************************************************
2232 * @ [SHLWAPI.211]
2234 * Delete an element from an FDSA array.
2236 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2238 TRACE("(%p 0x%08x)\n", info, where);
2240 if(where >= info->num_items)
2241 return FALSE;
2243 if(where < info->num_items - 1)
2245 memmove((char*)info->mem + where * info->block_size,
2246 (char*)info->mem + (where + 1) * info->block_size,
2247 (info->num_items - where - 1) * info->block_size);
2249 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2250 0, info->block_size);
2251 info->num_items--;
2252 return TRUE;
2256 typedef struct {
2257 REFIID refid;
2258 DWORD indx;
2259 } IFACE_INDEX_TBL;
2261 /*************************************************************************
2262 * @ [SHLWAPI.219]
2264 * Call IUnknown_QueryInterface() on a table of objects.
2266 * RETURNS
2267 * Success: S_OK.
2268 * Failure: E_POINTER or E_NOINTERFACE.
2270 HRESULT WINAPI QISearch(
2271 LPVOID w, /* [in] Table of interfaces */
2272 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2273 REFIID riid, /* [in] REFIID to get interface for */
2274 LPVOID *ppv) /* [out] Destination for interface pointer */
2276 HRESULT ret;
2277 IUnknown *a_vtbl;
2278 IFACE_INDEX_TBL *xmove;
2280 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2281 if (ppv) {
2282 xmove = x;
2283 while (xmove->refid) {
2284 TRACE("trying (indx %d) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2285 if (IsEqualIID(riid, xmove->refid)) {
2286 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2287 TRACE("matched, returning (%p)\n", a_vtbl);
2288 *ppv = a_vtbl;
2289 IUnknown_AddRef(a_vtbl);
2290 return S_OK;
2292 xmove++;
2295 if (IsEqualIID(riid, &IID_IUnknown)) {
2296 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2297 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2298 *ppv = a_vtbl;
2299 IUnknown_AddRef(a_vtbl);
2300 return S_OK;
2302 *ppv = 0;
2303 ret = E_NOINTERFACE;
2304 } else
2305 ret = E_POINTER;
2307 TRACE("-- 0x%08x\n", ret);
2308 return ret;
2311 /*************************************************************************
2312 * @ [SHLWAPI.220]
2314 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2316 * PARAMS
2317 * hWnd [I] Parent Window to set the property
2318 * id [I] Index of child Window to set the Font
2320 * RETURNS
2321 * Success: S_OK
2324 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id)
2326 FIXME("(%p, %d) stub\n", hWnd, id);
2327 return S_OK;
2330 /*************************************************************************
2331 * @ [SHLWAPI.221]
2333 * Remove the "PropDlgFont" property from a window.
2335 * PARAMS
2336 * hWnd [I] Window to remove the property from
2338 * RETURNS
2339 * A handle to the removed property, or NULL if it did not exist.
2341 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2343 HANDLE hProp;
2345 TRACE("(%p)\n", hWnd);
2347 hProp = GetPropA(hWnd, "PropDlgFont");
2349 if(hProp)
2351 DeleteObject(hProp);
2352 hProp = RemovePropA(hWnd, "PropDlgFont");
2354 return hProp;
2357 /*************************************************************************
2358 * @ [SHLWAPI.236]
2360 * Load the in-process server of a given GUID.
2362 * PARAMS
2363 * refiid [I] GUID of the server to load.
2365 * RETURNS
2366 * Success: A handle to the loaded server dll.
2367 * Failure: A NULL handle.
2369 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2371 HKEY newkey;
2372 DWORD type, count;
2373 CHAR value[MAX_PATH], string[MAX_PATH];
2375 strcpy(string, "CLSID\\");
2376 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2377 strcat(string, "\\InProcServer32");
2379 count = MAX_PATH;
2380 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2381 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2382 RegCloseKey(newkey);
2383 return LoadLibraryExA(value, 0, 0);
2386 /*************************************************************************
2387 * @ [SHLWAPI.237]
2389 * Unicode version of SHLWAPI_183.
2391 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2393 WNDCLASSW WndClass;
2395 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2397 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2398 return TRUE;
2399 return RegisterClassW(lpWndClass);
2402 /*************************************************************************
2403 * @ [SHLWAPI.238]
2405 * Unregister a list of classes.
2407 * PARAMS
2408 * hInst [I] Application instance that registered the classes
2409 * lppClasses [I] List of class names
2410 * iCount [I] Number of names in lppClasses
2412 * RETURNS
2413 * Nothing.
2415 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2417 WNDCLASSA WndClass;
2419 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2421 while (iCount > 0)
2423 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2424 UnregisterClassA(*lppClasses, hInst);
2425 lppClasses++;
2426 iCount--;
2430 /*************************************************************************
2431 * @ [SHLWAPI.239]
2433 * Unicode version of SHUnregisterClassesA.
2435 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2437 WNDCLASSW WndClass;
2439 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2441 while (iCount > 0)
2443 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2444 UnregisterClassW(*lppClasses, hInst);
2445 lppClasses++;
2446 iCount--;
2450 /*************************************************************************
2451 * @ [SHLWAPI.240]
2453 * Call The correct (Ascii/Unicode) default window procedure for a window.
2455 * PARAMS
2456 * hWnd [I] Window to call the default procedure for
2457 * uMessage [I] Message ID
2458 * wParam [I] WPARAM of message
2459 * lParam [I] LPARAM of message
2461 * RETURNS
2462 * The result of calling DefWindowProcA() or DefWindowProcW().
2464 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2466 if (IsWindowUnicode(hWnd))
2467 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2468 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2471 /*************************************************************************
2472 * @ [SHLWAPI.256]
2474 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2476 HRESULT hRet = E_INVALIDARG;
2477 LPOBJECTWITHSITE lpSite = NULL;
2479 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2481 if (lpUnknown && iid && lppSite)
2483 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2484 (void**)&lpSite);
2485 if (SUCCEEDED(hRet) && lpSite)
2487 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2488 IObjectWithSite_Release(lpSite);
2491 return hRet;
2494 /*************************************************************************
2495 * @ [SHLWAPI.257]
2497 * Create a worker window using CreateWindowExA().
2499 * PARAMS
2500 * wndProc [I] Window procedure
2501 * hWndParent [I] Parent window
2502 * dwExStyle [I] Extra style flags
2503 * dwStyle [I] Style flags
2504 * hMenu [I] Window menu
2505 * z [I] Unknown
2507 * RETURNS
2508 * Success: The window handle of the newly created window.
2509 * Failure: 0.
2511 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2512 DWORD dwStyle, HMENU hMenu, LONG z)
2514 static const char szClass[] = "WorkerA";
2515 WNDCLASSA wc;
2516 HWND hWnd;
2518 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2519 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2521 /* Create Window class */
2522 wc.style = 0;
2523 wc.lpfnWndProc = DefWindowProcA;
2524 wc.cbClsExtra = 0;
2525 wc.cbWndExtra = 4;
2526 wc.hInstance = shlwapi_hInstance;
2527 wc.hIcon = NULL;
2528 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2529 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2530 wc.lpszMenuName = NULL;
2531 wc.lpszClassName = szClass;
2533 SHRegisterClassA(&wc); /* Register class */
2535 /* FIXME: Set extra bits in dwExStyle */
2537 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2538 hWndParent, hMenu, shlwapi_hInstance, 0);
2539 if (hWnd)
2541 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2543 if (wndProc)
2544 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2546 return hWnd;
2549 typedef struct tagPOLICYDATA
2551 DWORD policy; /* flags value passed to SHRestricted */
2552 LPCWSTR appstr; /* application str such as "Explorer" */
2553 LPCWSTR keystr; /* name of the actual registry key / policy */
2554 } POLICYDATA, *LPPOLICYDATA;
2556 #define SHELL_NO_POLICY 0xffffffff
2558 /* default shell policy registry key */
2559 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2560 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2561 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2562 '\\','P','o','l','i','c','i','e','s',0};
2564 /*************************************************************************
2565 * @ [SHLWAPI.271]
2567 * Retrieve a policy value from the registry.
2569 * PARAMS
2570 * lpSubKey [I] registry key name
2571 * lpSubName [I] subname of registry key
2572 * lpValue [I] value name of registry value
2574 * RETURNS
2575 * the value associated with the registry key or 0 if not found
2577 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2579 DWORD retval, datsize = sizeof(retval);
2580 HKEY hKey;
2582 if (!lpSubKey)
2583 lpSubKey = strRegistryPolicyW;
2585 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2586 if (retval != ERROR_SUCCESS)
2587 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2588 if (retval != ERROR_SUCCESS)
2589 return 0;
2591 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2592 RegCloseKey(hKey);
2593 return retval;
2596 /*************************************************************************
2597 * @ [SHLWAPI.266]
2599 * Helper function to retrieve the possibly cached value for a specific policy
2601 * PARAMS
2602 * policy [I] The policy to look for
2603 * initial [I] Main registry key to open, if NULL use default
2604 * polTable [I] Table of known policies, 0 terminated
2605 * polArr [I] Cache array of policy values
2607 * RETURNS
2608 * The retrieved policy value or 0 if not successful
2610 * NOTES
2611 * This function is used by the native SHRestricted function to search for the
2612 * policy and cache it once retrieved. The current Wine implementation uses a
2613 * different POLICYDATA structure and implements a similar algorithm adapted to
2614 * that structure.
2616 DWORD WINAPI SHRestrictionLookup(
2617 DWORD policy,
2618 LPCWSTR initial,
2619 LPPOLICYDATA polTable,
2620 LPDWORD polArr)
2622 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2624 if (!polTable || !polArr)
2625 return 0;
2627 for (;polTable->policy; polTable++, polArr++)
2629 if (policy == polTable->policy)
2631 /* we have a known policy */
2633 /* check if this policy has been cached */
2634 if (*polArr == SHELL_NO_POLICY)
2635 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2636 return *polArr;
2639 /* we don't know this policy, return 0 */
2640 TRACE("unknown policy: (%08x)\n", policy);
2641 return 0;
2644 /*************************************************************************
2645 * @ [SHLWAPI.267]
2647 * Get an interface from an object.
2649 * RETURNS
2650 * Success: S_OK. ppv contains the requested interface.
2651 * Failure: An HRESULT error code.
2653 * NOTES
2654 * This QueryInterface asks the inner object for an interface. In case
2655 * of aggregation this request would be forwarded by the inner to the
2656 * outer object. This function asks the inner object directly for the
2657 * interface circumventing the forwarding to the outer object.
2659 HRESULT WINAPI SHWeakQueryInterface(
2660 IUnknown * pUnk, /* [in] Outer object */
2661 IUnknown * pInner, /* [in] Inner object */
2662 IID * riid, /* [in] Interface GUID to query for */
2663 LPVOID* ppv) /* [out] Destination for queried interface */
2665 HRESULT hret = E_NOINTERFACE;
2666 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2668 *ppv = NULL;
2669 if(pUnk && pInner) {
2670 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2671 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2673 TRACE("-- 0x%08x\n", hret);
2674 return hret;
2677 /*************************************************************************
2678 * @ [SHLWAPI.268]
2680 * Move a reference from one interface to another.
2682 * PARAMS
2683 * lpDest [O] Destination to receive the reference
2684 * lppUnknown [O] Source to give up the reference to lpDest
2686 * RETURNS
2687 * Nothing.
2689 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2691 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2693 if (*lppUnknown)
2695 /* Copy Reference*/
2696 IUnknown_AddRef(lpDest);
2697 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2701 /*************************************************************************
2702 * @ [SHLWAPI.269]
2704 * Convert an ASCII string of a CLSID into a CLSID.
2706 * PARAMS
2707 * idstr [I] String representing a CLSID in registry format
2708 * id [O] Destination for the converted CLSID
2710 * RETURNS
2711 * Success: TRUE. id contains the converted CLSID.
2712 * Failure: FALSE.
2714 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2716 WCHAR wClsid[40];
2717 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2718 return SUCCEEDED(CLSIDFromString(wClsid, id));
2721 /*************************************************************************
2722 * @ [SHLWAPI.270]
2724 * Unicode version of GUIDFromStringA.
2726 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2728 return SUCCEEDED(CLSIDFromString((LPOLESTR)idstr, id));
2731 /*************************************************************************
2732 * @ [SHLWAPI.276]
2734 * Determine if the browser is integrated into the shell, and set a registry
2735 * key accordingly.
2737 * PARAMS
2738 * None.
2740 * RETURNS
2741 * 1, If the browser is not integrated.
2742 * 2, If the browser is integrated.
2744 * NOTES
2745 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2746 * either set to TRUE, or removed depending on whether the browser is deemed
2747 * to be integrated.
2749 DWORD WINAPI WhichPlatform(void)
2751 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2752 static DWORD dwState = 0;
2753 HKEY hKey;
2754 DWORD dwRet, dwData, dwSize;
2755 HMODULE hshell32;
2757 if (dwState)
2758 return dwState;
2760 /* If shell32 exports DllGetVersion(), the browser is integrated */
2761 dwState = 1;
2762 hshell32 = LoadLibraryA("shell32.dll");
2763 if (hshell32)
2765 FARPROC pDllGetVersion;
2766 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2767 dwState = pDllGetVersion ? 2 : 1;
2768 FreeLibrary(hshell32);
2771 /* Set or delete the key accordingly */
2772 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2773 "Software\\Microsoft\\Internet Explorer", 0,
2774 KEY_ALL_ACCESS, &hKey);
2775 if (!dwRet)
2777 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2778 (LPBYTE)&dwData, &dwSize);
2780 if (!dwRet && dwState == 1)
2782 /* Value exists but browser is not integrated */
2783 RegDeleteValueA(hKey, szIntegratedBrowser);
2785 else if (dwRet && dwState == 2)
2787 /* Browser is integrated but value does not exist */
2788 dwData = TRUE;
2789 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2790 (LPBYTE)&dwData, sizeof(dwData));
2792 RegCloseKey(hKey);
2794 return dwState;
2797 /*************************************************************************
2798 * @ [SHLWAPI.278]
2800 * Unicode version of SHCreateWorkerWindowA.
2802 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2803 DWORD dwStyle, HMENU hMenu, LONG z)
2805 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2806 WNDCLASSW wc;
2807 HWND hWnd;
2809 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2810 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2812 /* If our OS is natively ASCII, use the ASCII version */
2813 if (!(GetVersion() & 0x80000000)) /* NT */
2814 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2816 /* Create Window class */
2817 wc.style = 0;
2818 wc.lpfnWndProc = DefWindowProcW;
2819 wc.cbClsExtra = 0;
2820 wc.cbWndExtra = 4;
2821 wc.hInstance = shlwapi_hInstance;
2822 wc.hIcon = NULL;
2823 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2824 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2825 wc.lpszMenuName = NULL;
2826 wc.lpszClassName = szClass;
2828 SHRegisterClassW(&wc); /* Register class */
2830 /* FIXME: Set extra bits in dwExStyle */
2832 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2833 hWndParent, hMenu, shlwapi_hInstance, 0);
2834 if (hWnd)
2836 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2838 if (wndProc)
2839 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2841 return hWnd;
2844 /*************************************************************************
2845 * @ [SHLWAPI.279]
2847 * Get and show a context menu from a shell folder.
2849 * PARAMS
2850 * hWnd [I] Window displaying the shell folder
2851 * lpFolder [I] IShellFolder interface
2852 * lpApidl [I] Id for the particular folder desired
2854 * RETURNS
2855 * Success: S_OK.
2856 * Failure: An HRESULT error code indicating the error.
2858 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2860 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2863 /*************************************************************************
2864 * @ [SHLWAPI.281]
2866 * _SHPackDispParamsV
2868 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist)
2870 VARIANTARG *iter;
2872 TRACE("(%p %p %u ...)\n", params, args, cnt);
2874 params->rgvarg = args;
2875 params->rgdispidNamedArgs = NULL;
2876 params->cArgs = cnt;
2877 params->cNamedArgs = 0;
2879 iter = args+cnt;
2881 while(iter-- > args) {
2882 V_VT(iter) = va_arg(valist, enum VARENUM);
2884 TRACE("vt=%d\n", V_VT(iter));
2886 if(V_VT(iter) & VT_BYREF) {
2887 V_BYREF(iter) = va_arg(valist, LPVOID);
2888 } else {
2889 switch(V_VT(iter)) {
2890 case VT_I4:
2891 V_I4(iter) = va_arg(valist, LONG);
2892 break;
2893 case VT_BSTR:
2894 V_BSTR(iter) = va_arg(valist, BSTR);
2895 break;
2896 case VT_DISPATCH:
2897 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
2898 break;
2899 case VT_BOOL:
2900 V_BOOL(iter) = va_arg(valist, int);
2901 break;
2902 case VT_UNKNOWN:
2903 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
2904 break;
2905 default:
2906 V_VT(iter) = VT_I4;
2907 V_I4(iter) = va_arg(valist, LONG);
2912 return S_OK;
2915 /*************************************************************************
2916 * @ [SHLWAPI.282]
2918 * SHPackDispParams
2920 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...)
2922 __ms_va_list valist;
2923 HRESULT hres;
2925 __ms_va_start(valist, cnt);
2926 hres = SHPackDispParamsV(params, args, cnt, valist);
2927 __ms_va_end(valist);
2928 return hres;
2931 /*************************************************************************
2932 * SHLWAPI_InvokeByIID
2934 * This helper function calls IDispatch::Invoke for each sink
2935 * which implements given iid or IDispatch.
2938 static HRESULT SHLWAPI_InvokeByIID(
2939 IConnectionPoint* iCP,
2940 REFIID iid,
2941 DISPID dispId,
2942 DISPPARAMS* dispParams)
2944 IEnumConnections *enumerator;
2945 CONNECTDATA rgcd;
2946 static DISPPARAMS empty = {NULL, NULL, 0, 0};
2947 DISPPARAMS* params = dispParams;
2949 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
2950 if (FAILED(result))
2951 return result;
2953 /* Invoke is never happening with an NULL dispParams */
2954 if (!params)
2955 params = &empty;
2957 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
2959 IDispatch *dispIface;
2960 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
2961 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
2963 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
2964 IDispatch_Release(dispIface);
2966 IUnknown_Release(rgcd.pUnk);
2969 IEnumConnections_Release(enumerator);
2971 return S_OK;
2974 /*************************************************************************
2975 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
2977 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP,
2978 DISPID dispId, DISPPARAMS* dispParams,
2979 DWORD unknown1, DWORD unknown2 )
2981 IID iid;
2982 HRESULT result;
2984 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
2986 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
2987 if (SUCCEEDED(result))
2988 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
2989 else
2990 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
2992 return result;
2996 /*************************************************************************
2997 * @ [SHLWAPI.284]
2999 * IConnectionPoint_SimpleInvoke
3001 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
3002 IConnectionPoint* iCP,
3003 DISPID dispId,
3004 DISPPARAMS* dispParams)
3006 IID iid;
3007 HRESULT result;
3009 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
3011 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3012 if (SUCCEEDED(result))
3013 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3014 else
3015 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3017 return result;
3020 /*************************************************************************
3021 * @ [SHLWAPI.285]
3023 * Notify an IConnectionPoint object of changes.
3025 * PARAMS
3026 * lpCP [I] Object to notify
3027 * dispID [I]
3029 * RETURNS
3030 * Success: S_OK.
3031 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3032 * IConnectionPoint interface.
3034 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
3036 IEnumConnections *lpEnum;
3037 HRESULT hRet = E_NOINTERFACE;
3039 TRACE("(%p,0x%8X)\n", lpCP, dispID);
3041 /* Get an enumerator for the connections */
3042 if (lpCP)
3043 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
3045 if (SUCCEEDED(hRet))
3047 IPropertyNotifySink *lpSink;
3048 CONNECTDATA connData;
3049 ULONG ulFetched;
3051 /* Call OnChanged() for every notify sink in the connection point */
3052 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
3054 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
3055 lpSink)
3057 IPropertyNotifySink_OnChanged(lpSink, dispID);
3058 IPropertyNotifySink_Release(lpSink);
3060 IUnknown_Release(connData.pUnk);
3063 IEnumConnections_Release(lpEnum);
3065 return hRet;
3068 /*************************************************************************
3069 * @ [SHLWAPI.286]
3071 * IUnknown_CPContainerInvokeParam
3073 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
3074 IUnknown *container,
3075 REFIID riid,
3076 DISPID dispId,
3077 VARIANTARG* buffer,
3078 DWORD cParams, ...)
3080 HRESULT result;
3081 IConnectionPoint *iCP;
3082 IConnectionPointContainer *iCPC;
3083 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3084 __ms_va_list valist;
3086 if (!container)
3087 return E_NOINTERFACE;
3089 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
3090 if (FAILED(result))
3091 return result;
3093 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
3094 IConnectionPointContainer_Release(iCPC);
3095 if(FAILED(result))
3096 return result;
3098 __ms_va_start(valist, cParams);
3099 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
3100 __ms_va_end(valist);
3102 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3103 IConnectionPoint_Release(iCP);
3105 return result;
3108 /*************************************************************************
3109 * @ [SHLWAPI.287]
3111 * Notify an IConnectionPointContainer object of changes.
3113 * PARAMS
3114 * lpUnknown [I] Object to notify
3115 * dispID [I]
3117 * RETURNS
3118 * Success: S_OK.
3119 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3120 * IConnectionPointContainer interface.
3122 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3124 IConnectionPointContainer* lpCPC = NULL;
3125 HRESULT hRet = E_NOINTERFACE;
3127 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3129 if (lpUnknown)
3130 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3132 if (SUCCEEDED(hRet))
3134 IConnectionPoint* lpCP;
3136 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3137 IConnectionPointContainer_Release(lpCPC);
3139 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3140 IConnectionPoint_Release(lpCP);
3142 return hRet;
3145 /*************************************************************************
3146 * @ [SHLWAPI.289]
3148 * See PlaySoundW.
3150 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3152 return PlaySoundW(pszSound, hmod, fdwSound);
3155 /*************************************************************************
3156 * @ [SHLWAPI.294]
3158 BOOL WINAPI SHGetIniStringW(LPCWSTR str1, LPCWSTR str2, LPWSTR pStr, DWORD some_len, LPCWSTR lpStr2)
3160 FIXME("(%s,%s,%p,%08x,%s): stub!\n", debugstr_w(str1), debugstr_w(str2),
3161 pStr, some_len, debugstr_w(lpStr2));
3162 return TRUE;
3165 /*************************************************************************
3166 * @ [SHLWAPI.295]
3168 * Called by ICQ2000b install via SHDOCVW:
3169 * str1: "InternetShortcut"
3170 * x: some unknown pointer
3171 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
3172 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
3174 * In short: this one maybe creates a desktop link :-)
3176 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
3178 FIXME("(%s, %p, %s, %s), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
3179 return TRUE;
3182 /*************************************************************************
3183 * @ [SHLWAPI.313]
3185 * See SHGetFileInfoW.
3187 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3188 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3190 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3193 /*************************************************************************
3194 * @ [SHLWAPI.318]
3196 * See DragQueryFileW.
3198 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3200 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3203 /*************************************************************************
3204 * @ [SHLWAPI.333]
3206 * See SHBrowseForFolderW.
3208 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3210 return SHBrowseForFolderW(lpBi);
3213 /*************************************************************************
3214 * @ [SHLWAPI.334]
3216 * See SHGetPathFromIDListW.
3218 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3220 return SHGetPathFromIDListW(pidl, pszPath);
3223 /*************************************************************************
3224 * @ [SHLWAPI.335]
3226 * See ShellExecuteExW.
3228 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3230 return ShellExecuteExW(lpExecInfo);
3233 /*************************************************************************
3234 * @ [SHLWAPI.336]
3236 * See SHFileOperationW.
3238 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3240 return SHFileOperationW(lpFileOp);
3243 /*************************************************************************
3244 * @ [SHLWAPI.342]
3247 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
3249 return InterlockedCompareExchangePointer( dest, xchg, compare );
3252 /*************************************************************************
3253 * @ [SHLWAPI.350]
3255 * See GetFileVersionInfoSizeW.
3257 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
3259 return GetFileVersionInfoSizeW( filename, handle );
3262 /*************************************************************************
3263 * @ [SHLWAPI.351]
3265 * See GetFileVersionInfoW.
3267 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
3268 DWORD datasize, LPVOID data )
3270 return GetFileVersionInfoW( filename, handle, datasize, data );
3273 /*************************************************************************
3274 * @ [SHLWAPI.352]
3276 * See VerQueryValueW.
3278 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
3279 LPVOID *lplpBuffer, UINT *puLen )
3281 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3284 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3285 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3286 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3288 /*************************************************************************
3289 * @ [SHLWAPI.355]
3291 * Change the modality of a shell object.
3293 * PARAMS
3294 * lpUnknown [I] Object to make modeless
3295 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3297 * RETURNS
3298 * Success: S_OK. The modality lpUnknown is changed.
3299 * Failure: An HRESULT error code indicating the error.
3301 * NOTES
3302 * lpUnknown must support the IOleInPlaceFrame interface, the
3303 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3304 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3305 * or this call will fail.
3307 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3309 IUnknown *lpObj;
3310 HRESULT hRet;
3312 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3314 if (!lpUnknown)
3315 return E_FAIL;
3317 if (IsIface(IOleInPlaceActiveObject))
3318 EnableModeless(IOleInPlaceActiveObject);
3319 else if (IsIface(IOleInPlaceFrame))
3320 EnableModeless(IOleInPlaceFrame);
3321 else if (IsIface(IShellBrowser))
3322 EnableModeless(IShellBrowser);
3323 else if (IsIface(IInternetSecurityMgrSite))
3324 EnableModeless(IInternetSecurityMgrSite);
3325 else if (IsIface(IDocHostUIHandler))
3326 EnableModeless(IDocHostUIHandler);
3327 else
3328 return hRet;
3330 IUnknown_Release(lpObj);
3331 return S_OK;
3334 /*************************************************************************
3335 * @ [SHLWAPI.357]
3337 * See SHGetNewLinkInfoW.
3339 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3340 BOOL *pfMustCopy, UINT uFlags)
3342 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3345 /*************************************************************************
3346 * @ [SHLWAPI.358]
3348 * See SHDefExtractIconW.
3350 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3351 HICON* phiconSmall, UINT nIconSize)
3353 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3356 /*************************************************************************
3357 * @ [SHLWAPI.363]
3359 * Get and show a context menu from a shell folder.
3361 * PARAMS
3362 * hWnd [I] Window displaying the shell folder
3363 * lpFolder [I] IShellFolder interface
3364 * lpApidl [I] Id for the particular folder desired
3365 * bInvokeDefault [I] Whether to invoke the default menu item
3367 * RETURNS
3368 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3369 * executed.
3370 * Failure: An HRESULT error code indicating the error.
3372 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3374 IContextMenu *iContext;
3375 HRESULT hRet = E_FAIL;
3377 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3379 if (!lpFolder)
3380 return hRet;
3382 /* Get the context menu from the shell folder */
3383 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3384 &IID_IContextMenu, 0, (void**)&iContext);
3385 if (SUCCEEDED(hRet))
3387 HMENU hMenu;
3388 if ((hMenu = CreatePopupMenu()))
3390 HRESULT hQuery;
3391 DWORD dwDefaultId = 0;
3393 /* Add the context menu entries to the popup */
3394 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3395 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3397 if (SUCCEEDED(hQuery))
3399 if (bInvokeDefault &&
3400 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3402 CMINVOKECOMMANDINFO cmIci;
3403 /* Invoke the default item */
3404 memset(&cmIci,0,sizeof(cmIci));
3405 cmIci.cbSize = sizeof(cmIci);
3406 cmIci.fMask = CMIC_MASK_ASYNCOK;
3407 cmIci.hwnd = hWnd;
3408 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3409 cmIci.nShow = SW_SCROLLCHILDREN;
3411 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3414 DestroyMenu(hMenu);
3416 IContextMenu_Release(iContext);
3418 return hRet;
3421 /*************************************************************************
3422 * @ [SHLWAPI.370]
3424 * See ExtractIconW.
3426 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3427 UINT nIconIndex)
3429 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3432 /*************************************************************************
3433 * @ [SHLWAPI.377]
3435 * Load a library from the directory of a particular process.
3437 * PARAMS
3438 * new_mod [I] Library name
3439 * inst_hwnd [I] Module whose directory is to be used
3440 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3442 * RETURNS
3443 * Success: A handle to the loaded module
3444 * Failure: A NULL handle.
3446 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3448 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3449 * each call here.
3450 * FIXME: Native shows calls to:
3451 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3452 * CheckVersion
3453 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3454 * RegQueryValueExA for "LPKInstalled"
3455 * RegCloseKey
3456 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3457 * RegQueryValueExA for "ResourceLocale"
3458 * RegCloseKey
3459 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3460 * RegQueryValueExA for "Locale"
3461 * RegCloseKey
3462 * and then tests the Locale ("en" for me).
3463 * code below
3464 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3466 CHAR mod_path[2*MAX_PATH];
3467 LPSTR ptr;
3468 DWORD len;
3470 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3471 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3472 if (!len || len >= sizeof(mod_path)) return NULL;
3474 ptr = strrchr(mod_path, '\\');
3475 if (ptr) {
3476 strcpy(ptr+1, new_mod);
3477 TRACE("loading %s\n", debugstr_a(mod_path));
3478 return LoadLibraryA(mod_path);
3480 return NULL;
3483 /*************************************************************************
3484 * @ [SHLWAPI.378]
3486 * Unicode version of MLLoadLibraryA.
3488 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3490 WCHAR mod_path[2*MAX_PATH];
3491 LPWSTR ptr;
3492 DWORD len;
3494 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3495 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3496 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3498 ptr = strrchrW(mod_path, '\\');
3499 if (ptr) {
3500 strcpyW(ptr+1, new_mod);
3501 TRACE("loading %s\n", debugstr_w(mod_path));
3502 return LoadLibraryW(mod_path);
3504 return NULL;
3507 /*************************************************************************
3508 * ColorAdjustLuma [SHLWAPI.@]
3510 * Adjust the luminosity of a color
3512 * PARAMS
3513 * cRGB [I] RGB value to convert
3514 * dwLuma [I] Luma adjustment
3515 * bUnknown [I] Unknown
3517 * RETURNS
3518 * The adjusted RGB color.
3520 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3522 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3524 if (dwLuma)
3526 WORD wH, wL, wS;
3528 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3530 FIXME("Ignoring luma adjustment\n");
3532 /* FIXME: The adjustment is not linear */
3534 cRGB = ColorHLSToRGB(wH, wL, wS);
3536 return cRGB;
3539 /*************************************************************************
3540 * @ [SHLWAPI.389]
3542 * See GetSaveFileNameW.
3544 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3546 return GetSaveFileNameW(ofn);
3549 /*************************************************************************
3550 * @ [SHLWAPI.390]
3552 * See WNetRestoreConnectionW.
3554 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3556 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3559 /*************************************************************************
3560 * @ [SHLWAPI.391]
3562 * See WNetGetLastErrorW.
3564 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3565 LPWSTR lpNameBuf, DWORD nNameBufSize)
3567 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3570 /*************************************************************************
3571 * @ [SHLWAPI.401]
3573 * See PageSetupDlgW.
3575 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3577 return PageSetupDlgW(pagedlg);
3580 /*************************************************************************
3581 * @ [SHLWAPI.402]
3583 * See PrintDlgW.
3585 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3587 return PrintDlgW(printdlg);
3590 /*************************************************************************
3591 * @ [SHLWAPI.403]
3593 * See GetOpenFileNameW.
3595 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3597 return GetOpenFileNameW(ofn);
3600 /*************************************************************************
3601 * @ [SHLWAPI.404]
3603 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3605 IPersist *persist;
3606 HRESULT hr;
3608 hr = IShellFolder_QueryInterface(lpFolder, &IID_IPersist, (LPVOID)&persist);
3609 if(SUCCEEDED(hr))
3611 CLSID clsid;
3612 hr = IPersist_GetClassID(persist, &clsid);
3613 if(SUCCEEDED(hr))
3615 if(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder))
3616 hr = IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3617 else
3618 hr = E_FAIL;
3620 IPersist_Release(persist);
3622 return hr;
3625 /* INTERNAL: Map from HLS color space to RGB */
3626 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3628 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3630 if (wHue > 160)
3631 return wMid1;
3632 else if (wHue > 120)
3633 wHue = 160 - wHue;
3634 else if (wHue > 40)
3635 return wMid2;
3637 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3640 /* Convert to RGB and scale into RGB range (0..255) */
3641 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3643 /*************************************************************************
3644 * ColorHLSToRGB [SHLWAPI.@]
3646 * Convert from hls color space into an rgb COLORREF.
3648 * PARAMS
3649 * wHue [I] Hue amount
3650 * wLuminosity [I] Luminosity amount
3651 * wSaturation [I] Saturation amount
3653 * RETURNS
3654 * A COLORREF representing the converted color.
3656 * NOTES
3657 * Input hls values are constrained to the range (0..240).
3659 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3661 WORD wRed;
3663 if (wSaturation)
3665 WORD wGreen, wBlue, wMid1, wMid2;
3667 if (wLuminosity > 120)
3668 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3669 else
3670 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3672 wMid1 = wLuminosity * 2 - wMid2;
3674 wRed = GET_RGB(wHue + 80);
3675 wGreen = GET_RGB(wHue);
3676 wBlue = GET_RGB(wHue - 80);
3678 return RGB(wRed, wGreen, wBlue);
3681 wRed = wLuminosity * 255 / 240;
3682 return RGB(wRed, wRed, wRed);
3685 /*************************************************************************
3686 * @ [SHLWAPI.413]
3688 * Get the current docking status of the system.
3690 * PARAMS
3691 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3693 * RETURNS
3694 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3695 * a notebook.
3697 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3699 HW_PROFILE_INFOA hwInfo;
3701 TRACE("(0x%08x)\n", dwFlags);
3703 GetCurrentHwProfileA(&hwInfo);
3704 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3706 case DOCKINFO_DOCKED:
3707 case DOCKINFO_UNDOCKED:
3708 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3709 default:
3710 return 0;
3714 /*************************************************************************
3715 * @ [SHLWAPI.418]
3717 * Function seems to do FreeLibrary plus other things.
3719 * FIXME native shows the following calls:
3720 * RtlEnterCriticalSection
3721 * LocalFree
3722 * GetProcAddress(Comctl32??, 150L)
3723 * DPA_DeletePtr
3724 * RtlLeaveCriticalSection
3725 * followed by the FreeLibrary.
3726 * The above code may be related to .377 above.
3728 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3730 FIXME("(%p) semi-stub\n", hModule);
3731 return FreeLibrary(hModule);
3734 /*************************************************************************
3735 * @ [SHLWAPI.419]
3737 BOOL WINAPI SHFlushSFCacheWrap(void) {
3738 FIXME(": stub\n");
3739 return TRUE;
3742 /*************************************************************************
3743 * @ [SHLWAPI.429]
3744 * FIXME I have no idea what this function does or what its arguments are.
3746 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3748 FIXME("(%p) stub\n", hInst);
3749 return FALSE;
3753 /*************************************************************************
3754 * @ [SHLWAPI.430]
3756 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3758 FIXME("(%p,%p) stub\n", hInst, hHeap);
3759 return E_FAIL; /* This is what is used if shlwapi not loaded */
3762 /*************************************************************************
3763 * @ [SHLWAPI.431]
3765 DWORD WINAPI MLClearMLHInstance(DWORD x)
3767 FIXME("(0x%08x)stub\n", x);
3768 return 0xabba1247;
3771 /*************************************************************************
3772 * @ [SHLWAPI.432]
3774 * See SHSendMessageBroadcastW
3777 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam)
3779 return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam,
3780 SMTO_ABORTIFHUNG, 2000, NULL);
3783 /*************************************************************************
3784 * @ [SHLWAPI.433]
3786 * A wrapper for sending Broadcast Messages to all top level Windows
3789 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam)
3791 return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam,
3792 SMTO_ABORTIFHUNG, 2000, NULL);
3795 /*************************************************************************
3796 * @ [SHLWAPI.436]
3798 * Convert a Unicode string CLSID into a CLSID.
3800 * PARAMS
3801 * idstr [I] string containing a CLSID in text form
3802 * id [O] CLSID extracted from the string
3804 * RETURNS
3805 * S_OK on success or E_INVALIDARG on failure
3807 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3809 return CLSIDFromString((LPOLESTR)idstr, id);
3812 /*************************************************************************
3813 * @ [SHLWAPI.437]
3815 * Determine if the OS supports a given feature.
3817 * PARAMS
3818 * dwFeature [I] Feature requested (undocumented)
3820 * RETURNS
3821 * TRUE If the feature is available.
3822 * FALSE If the feature is not available.
3824 BOOL WINAPI IsOS(DWORD feature)
3826 OSVERSIONINFOA osvi;
3827 DWORD platform, majorv, minorv;
3829 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3830 if(!GetVersionExA(&osvi)) {
3831 ERR("GetVersionEx failed\n");
3832 return FALSE;
3835 majorv = osvi.dwMajorVersion;
3836 minorv = osvi.dwMinorVersion;
3837 platform = osvi.dwPlatformId;
3839 #define ISOS_RETURN(x) \
3840 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3841 return (x);
3843 switch(feature) {
3844 case OS_WIN32SORGREATER:
3845 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3846 || platform == VER_PLATFORM_WIN32_WINDOWS)
3847 case OS_NT:
3848 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3849 case OS_WIN95ORGREATER:
3850 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3851 case OS_NT4ORGREATER:
3852 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3853 case OS_WIN2000ORGREATER_ALT:
3854 case OS_WIN2000ORGREATER:
3855 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3856 case OS_WIN98ORGREATER:
3857 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3858 case OS_WIN98_GOLD:
3859 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3860 case OS_WIN2000PRO:
3861 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3862 case OS_WIN2000SERVER:
3863 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3864 case OS_WIN2000ADVSERVER:
3865 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3866 case OS_WIN2000DATACENTER:
3867 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3868 case OS_WIN2000TERMINAL:
3869 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3870 case OS_EMBEDDED:
3871 FIXME("(OS_EMBEDDED) What should we return here?\n");
3872 return FALSE;
3873 case OS_TERMINALCLIENT:
3874 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3875 return FALSE;
3876 case OS_TERMINALREMOTEADMIN:
3877 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3878 return FALSE;
3879 case OS_WIN95_GOLD:
3880 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3881 case OS_MEORGREATER:
3882 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3883 case OS_XPORGREATER:
3884 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3885 case OS_HOME:
3886 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3887 case OS_PROFESSIONAL:
3888 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3889 case OS_DATACENTER:
3890 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3891 case OS_ADVSERVER:
3892 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3893 case OS_SERVER:
3894 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3895 case OS_TERMINALSERVER:
3896 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3897 case OS_PERSONALTERMINALSERVER:
3898 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3899 case OS_FASTUSERSWITCHING:
3900 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3901 return TRUE;
3902 case OS_WELCOMELOGONUI:
3903 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3904 return FALSE;
3905 case OS_DOMAINMEMBER:
3906 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3907 return TRUE;
3908 case OS_ANYSERVER:
3909 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3910 case OS_WOW6432:
3911 FIXME("(OS_WOW6432) Should we check this?\n");
3912 return FALSE;
3913 case OS_WEBSERVER:
3914 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3915 case OS_SMALLBUSINESSSERVER:
3916 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3917 case OS_TABLETPC:
3918 FIXME("(OS_TABLEPC) What should we return here?\n");
3919 return FALSE;
3920 case OS_SERVERADMINUI:
3921 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3922 return FALSE;
3923 case OS_MEDIACENTER:
3924 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3925 return FALSE;
3926 case OS_APPLIANCE:
3927 FIXME("(OS_APPLIANCE) What should we return here?\n");
3928 return FALSE;
3929 case 0x25: /*OS_VISTAORGREATER*/
3930 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
3933 #undef ISOS_RETURN
3935 WARN("(0x%x) unknown parameter\n",feature);
3937 return FALSE;
3940 /*************************************************************************
3941 * @ [SHLWAPI.439]
3943 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
3945 DWORD type, sz = size;
3947 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
3948 return E_FAIL;
3950 return SHLoadIndirectString(buf, buf, size, NULL);
3953 /*************************************************************************
3954 * @ [SHLWAPI.478]
3956 * Call IInputObject_TranslateAcceleratorIO() on an object.
3958 * PARAMS
3959 * lpUnknown [I] Object supporting the IInputObject interface.
3960 * lpMsg [I] Key message to be processed.
3962 * RETURNS
3963 * Success: S_OK.
3964 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3966 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
3968 IInputObject* lpInput = NULL;
3969 HRESULT hRet = E_INVALIDARG;
3971 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
3972 if (lpUnknown)
3974 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3975 (void**)&lpInput);
3976 if (SUCCEEDED(hRet) && lpInput)
3978 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
3979 IInputObject_Release(lpInput);
3982 return hRet;
3985 /*************************************************************************
3986 * @ [SHLWAPI.481]
3988 * Call IInputObject_HasFocusIO() on an object.
3990 * PARAMS
3991 * lpUnknown [I] Object supporting the IInputObject interface.
3993 * RETURNS
3994 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
3995 * or S_FALSE otherwise.
3996 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3998 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
4000 IInputObject* lpInput = NULL;
4001 HRESULT hRet = E_INVALIDARG;
4003 TRACE("(%p)\n", lpUnknown);
4004 if (lpUnknown)
4006 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4007 (void**)&lpInput);
4008 if (SUCCEEDED(hRet) && lpInput)
4010 hRet = IInputObject_HasFocusIO(lpInput);
4011 IInputObject_Release(lpInput);
4014 return hRet;
4017 /*************************************************************************
4018 * ColorRGBToHLS [SHLWAPI.@]
4020 * Convert an rgb COLORREF into the hls color space.
4022 * PARAMS
4023 * cRGB [I] Source rgb value
4024 * pwHue [O] Destination for converted hue
4025 * pwLuminance [O] Destination for converted luminance
4026 * pwSaturation [O] Destination for converted saturation
4028 * RETURNS
4029 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4030 * values.
4032 * NOTES
4033 * Output HLS values are constrained to the range (0..240).
4034 * For Achromatic conversions, Hue is set to 160.
4036 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
4037 LPWORD pwLuminance, LPWORD pwSaturation)
4039 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4041 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4043 wR = GetRValue(cRGB);
4044 wG = GetGValue(cRGB);
4045 wB = GetBValue(cRGB);
4047 wMax = max(wR, max(wG, wB));
4048 wMin = min(wR, min(wG, wB));
4050 /* Luminosity */
4051 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4053 if (wMax == wMin)
4055 /* Achromatic case */
4056 wSaturation = 0;
4057 /* Hue is now unrepresentable, but this is what native returns... */
4058 wHue = 160;
4060 else
4062 /* Chromatic case */
4063 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4065 /* Saturation */
4066 if (wLuminosity <= 120)
4067 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4068 else
4069 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4071 /* Hue */
4072 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4073 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4074 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4076 if (wR == wMax)
4077 wHue = wBNorm - wGNorm;
4078 else if (wG == wMax)
4079 wHue = 80 + wRNorm - wBNorm;
4080 else
4081 wHue = 160 + wGNorm - wRNorm;
4082 if (wHue < 0)
4083 wHue += 240;
4084 else if (wHue > 240)
4085 wHue -= 240;
4087 if (pwHue)
4088 *pwHue = wHue;
4089 if (pwLuminance)
4090 *pwLuminance = wLuminosity;
4091 if (pwSaturation)
4092 *pwSaturation = wSaturation;
4095 /*************************************************************************
4096 * SHCreateShellPalette [SHLWAPI.@]
4098 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4100 FIXME("stub\n");
4101 return CreateHalftonePalette(hdc);
4104 /*************************************************************************
4105 * SHGetInverseCMAP (SHLWAPI.@)
4107 * Get an inverse color map table.
4109 * PARAMS
4110 * lpCmap [O] Destination for color map
4111 * dwSize [I] Size of memory pointed to by lpCmap
4113 * RETURNS
4114 * Success: S_OK.
4115 * Failure: E_POINTER, If lpCmap is invalid.
4116 * E_INVALIDARG, If dwFlags is invalid
4117 * E_OUTOFMEMORY, If there is no memory available
4119 * NOTES
4120 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4121 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4122 * internal CMap.
4123 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4124 * this DLL's internal CMap.
4126 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4128 if (dwSize == 4) {
4129 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4130 *dest = (DWORD)0xabba1249;
4131 return 0;
4133 FIXME("(%p, %#x) stub\n", dest, dwSize);
4134 return 0;
4137 /*************************************************************************
4138 * SHIsLowMemoryMachine [SHLWAPI.@]
4140 * Determine if the current computer has low memory.
4142 * PARAMS
4143 * x [I] FIXME
4145 * RETURNS
4146 * TRUE if the users machine has 16 Megabytes of memory or less,
4147 * FALSE otherwise.
4149 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4151 FIXME("(0x%08x) stub\n", x);
4152 return FALSE;
4155 /*************************************************************************
4156 * GetMenuPosFromID [SHLWAPI.@]
4158 * Return the position of a menu item from its Id.
4160 * PARAMS
4161 * hMenu [I] Menu containing the item
4162 * wID [I] Id of the menu item
4164 * RETURNS
4165 * Success: The index of the menu item in hMenu.
4166 * Failure: -1, If the item is not found.
4168 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4170 MENUITEMINFOW mi;
4171 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4173 while (nIter < nCount)
4175 mi.cbSize = sizeof(mi);
4176 mi.fMask = MIIM_ID;
4177 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4178 return nIter;
4179 nIter++;
4181 return -1;
4184 /*************************************************************************
4185 * @ [SHLWAPI.179]
4187 * Same as SHLWAPI.GetMenuPosFromID
4189 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4191 return GetMenuPosFromID(hMenu, uID);
4195 /*************************************************************************
4196 * @ [SHLWAPI.448]
4198 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4200 while (*lpwstr)
4202 if (*lpwstr == '/')
4203 *lpwstr = '\\';
4204 lpwstr++;
4209 /*************************************************************************
4210 * @ [SHLWAPI.461]
4212 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4214 FIXME("(0x%08x) stub\n", dwUnknown);
4215 return 0;
4219 /*************************************************************************
4220 * @ [SHLWAPI.549]
4222 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4223 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4225 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4228 /*************************************************************************
4229 * SHSkipJunction [SHLWAPI.@]
4231 * Determine if a bind context can be bound to an object
4233 * PARAMS
4234 * pbc [I] Bind context to check
4235 * pclsid [I] CLSID of object to be bound to
4237 * RETURNS
4238 * TRUE: If it is safe to bind
4239 * FALSE: If pbc is invalid or binding would not be safe
4242 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4244 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4245 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4246 BOOL bRet = FALSE;
4248 if (pbc)
4250 IUnknown* lpUnk;
4252 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4254 CLSID clsid;
4256 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4257 IsEqualGUID(pclsid, &clsid))
4258 bRet = TRUE;
4260 IUnknown_Release(lpUnk);
4263 return bRet;
4266 /***********************************************************************
4267 * SHGetShellKey (SHLWAPI.@)
4269 DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
4271 FIXME("(%x, %x, %x): stub\n", a, b, c);
4272 return 0x50;
4275 /***********************************************************************
4276 * SHQueueUserWorkItem (SHLWAPI.@)
4278 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback,
4279 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4280 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4282 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4283 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4285 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4286 FIXME("Unsupported arguments\n");
4288 return QueueUserWorkItem(pfnCallback, pContext, 0);
4291 /***********************************************************************
4292 * SHSetTimerQueueTimer (SHLWAPI.263)
4294 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
4295 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4296 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4298 HANDLE hNewTimer;
4300 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4301 if (dwFlags & TPS_LONGEXECTIME) {
4302 dwFlags &= ~TPS_LONGEXECTIME;
4303 dwFlags |= WT_EXECUTELONGFUNCTION;
4305 if (dwFlags & TPS_EXECUTEIO) {
4306 dwFlags &= ~TPS_EXECUTEIO;
4307 dwFlags |= WT_EXECUTEINIOTHREAD;
4310 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4311 dwDueTime, dwPeriod, dwFlags))
4312 return NULL;
4314 return hNewTimer;
4317 /***********************************************************************
4318 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4320 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4322 IInputObjectSite *pIOS = NULL;
4323 HRESULT hRet = E_INVALIDARG;
4325 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4327 if (lpUnknown)
4329 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4330 (void **)&pIOS);
4331 if (SUCCEEDED(hRet) && pIOS)
4333 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4334 IInputObjectSite_Release(pIOS);
4337 return hRet;
4340 /***********************************************************************
4341 * SHGetValueW (SHLWAPI.@)
4343 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4345 FIXME("(%x, %s, %s, %x, %x, %x): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4346 return E_FAIL;
4349 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4351 /***********************************************************************
4352 * GetUIVersion (SHLWAPI.452)
4354 DWORD WINAPI GetUIVersion(void)
4356 static DWORD version;
4358 if (!version)
4360 DllGetVersion_func pDllGetVersion;
4361 HMODULE dll = LoadLibraryA("shell32.dll");
4362 if (!dll) return 0;
4364 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4365 if (pDllGetVersion)
4367 DLLVERSIONINFO dvi;
4368 dvi.cbSize = sizeof(DLLVERSIONINFO);
4369 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4371 FreeLibrary( dll );
4372 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4374 return version;
4377 /***********************************************************************
4378 * ShellMessageBoxWrapW [SHLWAPI.388]
4380 * See shell32.ShellMessageBoxW
4382 * NOTE:
4383 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4384 * because we can't forward to it in the .spec file since it's exported by
4385 * ordinal. If you change the implementation here please update the code in
4386 * shell32 as well.
4388 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
4389 LPCWSTR lpCaption, UINT uType, ...)
4391 WCHAR szText[100], szTitle[100];
4392 LPCWSTR pszText = szText, pszTitle = szTitle;
4393 LPWSTR pszTemp;
4394 __ms_va_list args;
4395 int ret;
4397 __ms_va_start(args, uType);
4399 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
4401 if (IS_INTRESOURCE(lpCaption))
4402 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
4403 else
4404 pszTitle = lpCaption;
4406 if (IS_INTRESOURCE(lpText))
4407 LoadStringW(hInstance, LOWORD(lpText), szText, sizeof(szText)/sizeof(szText[0]));
4408 else
4409 pszText = lpText;
4411 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4412 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4414 __ms_va_end(args);
4416 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4417 LocalFree(pszTemp);
4418 return ret;
4421 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *unk, REFIID service, REFIID clsid,
4422 DWORD x1, DWORD x2, DWORD x3, void **ppvOut)
4424 FIXME("%p %s %s %08x %08x %08x %p\n", unk,
4425 debugstr_guid(service), debugstr_guid(clsid), x1, x2, x3, ppvOut);
4426 return E_NOTIMPL;
4429 HRESULT WINAPI IUnknown_ProfferService(IUnknown *unk, void *x0, void *x1, void *x2)
4431 FIXME("%p %p %p %p\n", unk, x0, x1, x2);
4432 return E_NOTIMPL;
4435 /***********************************************************************
4436 * ZoneComputePaneSize [SHLWAPI.382]
4438 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4440 FIXME("\n");
4441 return 0x95;
4444 /***********************************************************************
4445 * SHChangeNotifyWrap [SHLWAPI.394]
4447 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
4449 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
4452 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
4453 SID_IDENTIFIER_AUTHORITY sidAuthority;
4454 DWORD dwUserGroupID;
4455 DWORD dwUserID;
4456 } SHELL_USER_SID, *PSHELL_USER_SID;
4458 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
4459 SHELL_USER_SID susID;
4460 DWORD dwAccessType;
4461 BOOL fInherit;
4462 DWORD dwAccessMask;
4463 DWORD dwInheritMask;
4464 DWORD dwInheritAccessMask;
4465 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
4467 /***********************************************************************
4468 * GetShellSecurityDescriptor [SHLWAPI.475]
4470 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4472 * PARAMS
4473 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4474 * each of which describes permissions to apply
4475 * cUserPerm [I] number of entries in apUserPerm array
4477 * RETURNS
4478 * success: pointer to SECURITY_DESCRIPTOR
4479 * failure: NULL
4481 * NOTES
4482 * Call should free returned descriptor with LocalFree
4484 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4486 PSID *sidlist;
4487 PSID cur_user = NULL;
4488 BYTE tuUser[2000];
4489 DWORD acl_size;
4490 int sid_count, i;
4491 PSECURITY_DESCRIPTOR psd = NULL;
4493 TRACE("%p %d\n", apUserPerm, cUserPerm);
4495 if (apUserPerm == NULL || cUserPerm <= 0)
4496 return NULL;
4498 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
4499 if (!sidlist)
4500 return NULL;
4502 acl_size = sizeof(ACL);
4504 for(sid_count = 0; sid_count < cUserPerm; sid_count++)
4506 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
4507 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
4508 PSHELL_USER_SID sid = &perm->susID;
4509 PSID pSid;
4510 BOOL ret = TRUE;
4512 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4513 { /* current user's SID */
4514 if (!cur_user)
4516 HANDLE Token;
4517 DWORD bufsize = sizeof(tuUser);
4519 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4520 if (ret)
4522 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4523 if (ret)
4524 cur_user = ((PTOKEN_USER)tuUser)->User.Sid;
4525 CloseHandle(Token);
4528 pSid = cur_user;
4529 } else if (sid->dwUserID==0) /* one sub-authority */
4530 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
4531 0, 0, 0, 0, 0, 0, &pSid);
4532 else
4533 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4534 0, 0, 0, 0, 0, 0, &pSid);
4535 if (!ret)
4536 goto free_sids;
4538 sidlist[sid_count] = pSid;
4539 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4540 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
4543 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
4545 if (psd != NULL)
4547 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4549 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4550 goto error;
4552 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4553 goto error;
4555 for(i = 0; i < sid_count; i++)
4557 PSHELL_USER_PERMISSION sup = apUserPerm[i];
4558 PSID sid = sidlist[i];
4560 switch(sup->dwAccessType)
4562 case ACCESS_ALLOWED_ACE_TYPE:
4563 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4564 goto error;
4565 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4566 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4567 goto error;
4568 break;
4569 case ACCESS_DENIED_ACE_TYPE:
4570 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4571 goto error;
4572 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4573 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4574 goto error;
4575 break;
4576 default:
4577 goto error;
4581 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4582 goto error;
4584 goto free_sids;
4586 error:
4587 LocalFree(psd);
4588 psd = NULL;
4589 free_sids:
4590 for(i = 0; i < sid_count; i++)
4592 if (!cur_user || sidlist[i] != cur_user)
4593 FreeSid(sidlist[i]);
4595 HeapFree(GetProcessHeap(), 0, sidlist);
4597 return psd;
4600 /***********************************************************************
4601 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4603 * Creates a property bag from a registry key
4605 * PARAMS
4606 * hKey [I] Handle to the desired registry key
4607 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4608 * grfMode [I] Optional flags
4609 * riid [I] IID of requested property bag interface
4610 * ppv [O] Address to receive pointer to the new interface
4612 * RETURNS
4613 * success: 0
4614 * failure: error code
4617 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey,
4618 DWORD grfMode, REFIID riid, void **ppv)
4620 FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode,
4621 debugstr_guid(riid), ppv);
4623 return E_NOTIMPL;
4626 /***********************************************************************
4627 * SHGetViewStatePropertyBag [SHLWAPI.515]
4629 * Retrieves a property bag in which the view state information of a folder
4630 * can be stored.
4632 * PARAMS
4633 * pidl [I] PIDL of the folder requested
4634 * bag_name [I] Name of the property bag requested
4635 * flags [I] Optional flags
4636 * riid [I] IID of requested property bag interface
4637 * ppv [O] Address to receive pointer to the new interface
4639 * RETURNS
4640 * success: S_OK
4641 * failure: error code
4644 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
4645 DWORD flags, REFIID riid, void **ppv)
4647 FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags,
4648 debugstr_guid(riid), ppv);
4650 return E_NOTIMPL;
4653 /***********************************************************************
4654 * SHFormatDateTimeW [SHLWAPI.354]
4656 * Produces a string representation of a time.
4658 * PARAMS
4659 * fileTime [I] Pointer to FILETIME structure specifying the time
4660 * flags [I] Flags specifying the desired output
4661 * buf [O] Pointer to buffer for output
4662 * bufSize [I] Number of characters that can be contained in buffer
4664 * RETURNS
4665 * success: number of characters written to the buffer
4666 * failure: 0
4669 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
4670 LPWSTR buf, UINT bufSize)
4672 FIXME("%p %p %s %d STUB\n", fileTime, flags, debugstr_w(buf), bufSize);
4673 return 0;
4676 /***********************************************************************
4677 * SHFormatDateTimeA [SHLWAPI.353]
4679 * See SHFormatDateTimeW.
4682 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags,
4683 LPCSTR buf, UINT bufSize)
4685 WCHAR *bufW;
4686 DWORD buflenW, convlen;
4687 INT retval;
4689 if (!buf || !bufSize)
4690 return 0;
4692 buflenW = bufSize;
4693 bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
4694 retval = SHFormatDateTimeW(fileTime, flags, bufW, buflenW);
4696 if (retval != 0)
4697 convlen = WideCharToMultiByte(CP_ACP, 0, bufW, -1, (LPSTR) buf, bufSize, NULL, NULL);
4699 HeapFree(GetProcessHeap(), 0, bufW);
4700 return retval;
4703 /***********************************************************************
4704 * ZoneCheckUrlExW [SHLWAPI.231]
4706 * Checks the details of the security zone for the supplied site. (?)
4708 * PARAMS
4710 * szURL [I] Pointer to the URL to check
4712 * Other parameters currently unknown.
4714 * RETURNS
4715 * unknown
4718 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2,
4719 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6,
4720 DWORD dwUnknown7)
4722 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2,
4723 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7);
4725 return 0;
4728 /***********************************************************************
4729 * SHVerbExistsNA [SHLWAPI.196]
4732 * PARAMS
4734 * verb [I] a string, often appears to be an extension.
4736 * Other parameters currently unknown.
4738 * RETURNS
4739 * unknown
4741 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3)
4743 FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3);
4744 return 0;
4747 /*************************************************************************
4748 * @ [SHLWAPI.538]
4750 * Undocumented: Implementation guessed at via Name and behavior
4752 * PARAMS
4753 * lpUnknown [I] Object to get an IServiceProvider interface from
4754 * riid [I] Function requested for QueryService call
4755 * lppOut [O] Destination for the service interface pointer
4757 * RETURNS
4758 * Success: S_OK. lppOut contains an object providing the requested service
4759 * Failure: An HRESULT error code
4761 * NOTES
4762 * lpUnknown is expected to support the IServiceProvider interface.
4764 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown,
4765 REFGUID riid, LPVOID *lppOut)
4767 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut);
4768 return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut);
4771 /**************************************************************************
4772 * SHPropertyBag_ReadLONG (SHLWAPI.496)
4774 * This function asks a property bag to read a named property as a LONG.
4776 * PARAMS
4777 * ppb: a IPropertyBag interface
4778 * pszPropName: Unicode string that names the property
4779 * pValue: address to receive the property value as a 32-bit signed integer
4781 * RETURNS
4782 * 0 for Success
4784 BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue)
4786 VARIANT var;
4787 HRESULT hr;
4788 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue);
4789 if (!pszPropName || !ppb || !pValue)
4790 return E_INVALIDARG;
4791 V_VT(&var) = VT_I4;
4792 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
4793 if (SUCCEEDED(hr))
4795 if (V_VT(&var) == VT_I4)
4796 *pValue = V_I4(&var);
4797 else
4798 hr = DISP_E_BADVARTYPE;
4800 return hr;