ntdll/tests: Remove an unneeded NONAMELESSSTRUCT directive.
[wine.git] / dlls / shlwapi / ordinal.c
blob0ea235cf2db0b654d4950c29d37b5c1a453e15a8
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 "shdeprecated.h"
46 #include "shlobj.h"
47 #include "shlwapi.h"
48 #include "shellapi.h"
49 #include "commdlg.h"
50 #include "mlang.h"
51 #include "mshtmhst.h"
52 #include "wine/unicode.h"
53 #include "wine/debug.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(shell);
58 /* DLL handles for late bound calls */
59 extern HINSTANCE shlwapi_hInstance;
60 extern DWORD SHLWAPI_ThreadRef_index;
62 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
63 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,DWORD);
64 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
67 NOTES: Most functions exported by ordinal seem to be superfluous.
68 The reason for these functions to be there is to provide a wrapper
69 for unicode functions to provide these functions on systems without
70 unicode functions eg. win95/win98. Since we have such functions we just
71 call these. If running Wine with native DLLs, some late bound calls may
72 fail. However, it is better to implement the functions in the forward DLL
73 and recommend the builtin rather than reimplementing the calls here!
76 /*************************************************************************
77 * @ [SHLWAPI.11]
79 * Copy a sharable memory handle from one process to another.
81 * PARAMS
82 * hShared [I] Shared memory handle to duplicate
83 * dwSrcProcId [I] ID of the process owning hShared
84 * dwDstProcId [I] ID of the process wanting the duplicated handle
85 * dwAccess [I] Desired DuplicateHandle() access
86 * dwOptions [I] Desired DuplicateHandle() options
88 * RETURNS
89 * Success: A handle suitable for use by the dwDstProcId process.
90 * Failure: A NULL handle.
93 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwSrcProcId, DWORD dwDstProcId,
94 DWORD dwAccess, DWORD dwOptions)
96 HANDLE hDst, hSrc;
97 DWORD dwMyProcId = GetCurrentProcessId();
98 HANDLE hRet = NULL;
100 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
101 dwAccess, dwOptions);
103 /* Get dest process handle */
104 if (dwDstProcId == dwMyProcId)
105 hDst = GetCurrentProcess();
106 else
107 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
109 if (hDst)
111 /* Get src process handle */
112 if (dwSrcProcId == dwMyProcId)
113 hSrc = GetCurrentProcess();
114 else
115 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
117 if (hSrc)
119 /* Make handle available to dest process */
120 if (!DuplicateHandle(hSrc, hShared, hDst, &hRet,
121 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
122 hRet = NULL;
124 if (dwSrcProcId != dwMyProcId)
125 CloseHandle(hSrc);
128 if (dwDstProcId != dwMyProcId)
129 CloseHandle(hDst);
132 TRACE("Returning handle %p\n", hRet);
133 return hRet;
136 /*************************************************************************
137 * @ [SHLWAPI.7]
139 * Create a block of sharable memory and initialise it with data.
141 * PARAMS
142 * lpvData [I] Pointer to data to write
143 * dwSize [I] Size of data
144 * dwProcId [I] ID of process owning data
146 * RETURNS
147 * Success: A shared memory handle
148 * Failure: NULL
150 * NOTES
151 * Ordinals 7-11 provide a set of calls to create shared memory between a
152 * group of processes. The shared memory is treated opaquely in that its size
153 * is not exposed to clients who map it. This is accomplished by storing
154 * the size of the map as the first DWORD of mapped data, and then offsetting
155 * the view pointer returned by this size.
158 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
160 HANDLE hMap;
161 LPVOID pMapped;
162 HANDLE hRet = NULL;
164 TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
166 /* Create file mapping of the correct length */
167 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
168 dwSize + sizeof(dwSize), NULL);
169 if (!hMap)
170 return hRet;
172 /* Get a view in our process address space */
173 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
175 if (pMapped)
177 /* Write size of data, followed by the data, to the view */
178 *((DWORD*)pMapped) = dwSize;
179 if (lpvData)
180 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
182 /* Release view. All further views mapped will be opaque */
183 UnmapViewOfFile(pMapped);
184 hRet = SHMapHandle(hMap, GetCurrentProcessId(), dwProcId,
185 FILE_MAP_ALL_ACCESS, DUPLICATE_SAME_ACCESS);
188 CloseHandle(hMap);
189 return hRet;
192 /*************************************************************************
193 * @ [SHLWAPI.8]
195 * Get a pointer to a block of shared memory from a shared memory handle.
197 * PARAMS
198 * hShared [I] Shared memory handle
199 * dwProcId [I] ID of process owning hShared
201 * RETURNS
202 * Success: A pointer to the shared memory
203 * Failure: NULL
206 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
208 HANDLE hDup;
209 LPVOID pMapped;
211 TRACE("(%p %d)\n", hShared, dwProcId);
213 /* Get handle to shared memory for current process */
214 hDup = SHMapHandle(hShared, dwProcId, GetCurrentProcessId(), FILE_MAP_ALL_ACCESS, 0);
216 /* Get View */
217 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
218 CloseHandle(hDup);
220 if (pMapped)
221 return (char *) pMapped + sizeof(DWORD); /* Hide size */
222 return NULL;
225 /*************************************************************************
226 * @ [SHLWAPI.9]
228 * Release a pointer to a block of shared memory.
230 * PARAMS
231 * lpView [I] Shared memory pointer
233 * RETURNS
234 * Success: TRUE
235 * Failure: FALSE
238 BOOL WINAPI SHUnlockShared(LPVOID lpView)
240 TRACE("(%p)\n", lpView);
241 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
244 /*************************************************************************
245 * @ [SHLWAPI.10]
247 * Destroy a block of sharable memory.
249 * PARAMS
250 * hShared [I] Shared memory handle
251 * dwProcId [I] ID of process owning hShared
253 * RETURNS
254 * Success: TRUE
255 * Failure: FALSE
258 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
260 HANDLE hClose;
262 TRACE("(%p %d)\n", hShared, dwProcId);
264 /* Get a copy of the handle for our process, closing the source handle */
265 hClose = SHMapHandle(hShared, dwProcId, GetCurrentProcessId(),
266 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
267 /* Close local copy */
268 return CloseHandle(hClose);
271 /*************************************************************************
272 * @ [SHLWAPI.13]
274 * Create and register a clipboard enumerator for a web browser.
276 * PARAMS
277 * lpBC [I] Binding context
278 * lpUnknown [I] An object exposing the IWebBrowserApp interface
280 * RETURNS
281 * Success: S_OK.
282 * Failure: An HRESULT error code.
284 * NOTES
285 * The enumerator is stored as a property of the web browser. If it does not
286 * yet exist, it is created and set before being registered.
288 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
290 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
291 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
292 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
293 BSTR property;
294 IEnumFORMATETC* pIEnumFormatEtc = NULL;
295 VARIANTARG var;
296 HRESULT hr;
297 IWebBrowserApp* pBrowser;
299 TRACE("(%p, %p)\n", lpBC, lpUnknown);
301 hr = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (void**)&pBrowser);
302 if (FAILED(hr))
303 return hr;
305 V_VT(&var) = VT_EMPTY;
307 /* The property we get is the browsers clipboard enumerator */
308 property = SysAllocString(szProperty);
309 hr = IWebBrowserApp_GetProperty(pBrowser, property, &var);
310 SysFreeString(property);
311 if (FAILED(hr)) goto exit;
313 if (V_VT(&var) == VT_EMPTY)
315 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
316 char szKeyBuff[128], szValueBuff[128];
317 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
318 FORMATETC* formatList, *format;
319 HKEY hDocs;
321 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
323 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
324 "Version\\Internet Settings\\Accepted Documents", &hDocs))
326 hr = E_FAIL;
327 goto exit;
330 /* Get count of values in key */
331 while (!dwRet)
333 dwKeySize = sizeof(szKeyBuff);
334 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
335 dwCount++;
338 dwNumValues = dwCount;
340 /* Note: dwCount = number of items + 1; The extra item is the end node */
341 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
342 if (!formatList)
344 RegCloseKey(hDocs);
345 hr = E_OUTOFMEMORY;
346 goto exit;
349 if (dwNumValues > 1)
351 dwRet = 0;
352 dwCount = 0;
354 dwNumValues--;
356 /* Register clipboard formats for the values and populate format list */
357 while(!dwRet && dwCount < dwNumValues)
359 dwKeySize = sizeof(szKeyBuff);
360 dwValueSize = sizeof(szValueBuff);
361 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
362 (PBYTE)szValueBuff, &dwValueSize);
363 if (!dwRet)
365 HeapFree(GetProcessHeap(), 0, formatList);
366 RegCloseKey(hDocs);
367 hr = E_FAIL;
368 goto exit;
371 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
372 format->ptd = NULL;
373 format->dwAspect = 1;
374 format->lindex = 4;
375 format->tymed = -1;
377 format++;
378 dwCount++;
382 RegCloseKey(hDocs);
384 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
385 format->cfFormat = 0;
386 format->ptd = NULL;
387 format->dwAspect = 1;
388 format->lindex = 4;
389 format->tymed = -1;
391 /* Create a clipboard enumerator */
392 hr = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
393 HeapFree(GetProcessHeap(), 0, formatList);
394 if (FAILED(hr)) goto exit;
396 /* Set our enumerator as the browsers property */
397 V_VT(&var) = VT_UNKNOWN;
398 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
400 property = SysAllocString(szProperty);
401 hr = IWebBrowserApp_PutProperty(pBrowser, property, var);
402 SysFreeString(property);
403 if (FAILED(hr))
405 IEnumFORMATETC_Release(pIEnumFormatEtc);
406 goto exit;
410 if (V_VT(&var) == VT_UNKNOWN)
412 /* Our variant is holding the clipboard enumerator */
413 IUnknown* pIUnknown = V_UNKNOWN(&var);
414 IEnumFORMATETC* pClone = NULL;
416 TRACE("Retrieved IEnumFORMATETC property\n");
418 /* Get an IEnumFormatEtc interface from the variants value */
419 pIEnumFormatEtc = NULL;
420 hr = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC, (void**)&pIEnumFormatEtc);
421 if (hr == S_OK && pIEnumFormatEtc)
423 /* Clone and register the enumerator */
424 hr = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
425 if (hr == S_OK && pClone)
427 RegisterFormatEnumerator(lpBC, pClone, 0);
429 IEnumFORMATETC_Release(pClone);
432 IUnknown_Release(pIUnknown);
434 IUnknown_Release(V_UNKNOWN(&var));
437 exit:
438 IWebBrowserApp_Release(pBrowser);
439 return hr;
442 /*************************************************************************
443 * @ [SHLWAPI.15]
445 * Get Explorers "AcceptLanguage" setting.
447 * PARAMS
448 * langbuf [O] Destination for language string
449 * buflen [I] Length of langbuf in characters
450 * [0] Success: used length of langbuf
452 * RETURNS
453 * Success: S_OK. langbuf is set to the language string found.
454 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
455 * does not contain the setting.
456 * E_NOT_SUFFICIENT_BUFFER, If the buffer is not big enough
458 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
460 static const WCHAR szkeyW[] = {
461 'S','o','f','t','w','a','r','e','\\',
462 'M','i','c','r','o','s','o','f','t','\\',
463 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
464 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
465 static const WCHAR valueW[] = {
466 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
467 DWORD mystrlen, mytype;
468 DWORD len;
469 HKEY mykey;
470 LCID mylcid;
471 WCHAR *mystr;
472 LONG lres;
474 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
476 if(!langbuf || !buflen || !*buflen)
477 return E_FAIL;
479 mystrlen = (*buflen > 20) ? *buflen : 20 ;
480 len = mystrlen * sizeof(WCHAR);
481 mystr = HeapAlloc(GetProcessHeap(), 0, len);
482 mystr[0] = 0;
483 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
484 lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
485 RegCloseKey(mykey);
486 len = lstrlenW(mystr);
488 if (!lres && (*buflen > len)) {
489 lstrcpyW(langbuf, mystr);
490 *buflen = len;
491 HeapFree(GetProcessHeap(), 0, mystr);
492 return S_OK;
495 /* Did not find a value in the registry or the user buffer is too small */
496 mylcid = GetUserDefaultLCID();
497 LcidToRfc1766W(mylcid, mystr, mystrlen);
498 len = lstrlenW(mystr);
500 memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
501 HeapFree(GetProcessHeap(), 0, mystr);
503 if (*buflen > len) {
504 *buflen = len;
505 return S_OK;
508 *buflen = 0;
509 return E_NOT_SUFFICIENT_BUFFER;
512 /*************************************************************************
513 * @ [SHLWAPI.14]
515 * Ascii version of GetAcceptLanguagesW.
517 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
519 WCHAR *langbufW;
520 DWORD buflenW, convlen;
521 HRESULT retval;
523 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
525 if(!langbuf || !buflen || !*buflen) return E_FAIL;
527 buflenW = *buflen;
528 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
529 retval = GetAcceptLanguagesW(langbufW, &buflenW);
531 if (retval == S_OK)
533 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
534 convlen--; /* do not count the terminating 0 */
536 else /* copy partial string anyway */
538 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
539 if (convlen < *buflen)
541 langbuf[convlen] = 0;
542 convlen--; /* do not count the terminating 0 */
544 else
546 convlen = *buflen;
549 *buflen = buflenW ? convlen : 0;
551 HeapFree(GetProcessHeap(), 0, langbufW);
552 return retval;
555 /*************************************************************************
556 * @ [SHLWAPI.23]
558 * Convert a GUID to a string.
560 * PARAMS
561 * guid [I] GUID to convert
562 * lpszDest [O] Destination for string
563 * cchMax [I] Length of output buffer
565 * RETURNS
566 * The length of the string created.
568 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
570 char xguid[40];
571 INT iLen;
573 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
575 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
576 guid->Data1, guid->Data2, guid->Data3,
577 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
578 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
580 iLen = strlen(xguid) + 1;
582 if (iLen > cchMax)
583 return 0;
584 memcpy(lpszDest, xguid, iLen);
585 return iLen;
588 /*************************************************************************
589 * @ [SHLWAPI.24]
591 * Convert a GUID to a string.
593 * PARAMS
594 * guid [I] GUID to convert
595 * str [O] Destination for string
596 * cmax [I] Length of output buffer
598 * RETURNS
599 * The length of the string created.
601 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
603 WCHAR xguid[40];
604 INT iLen;
605 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
606 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
607 'X','%','0','2','X','%','0','2','X','}',0};
609 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
611 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
612 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
613 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
615 iLen = strlenW(xguid) + 1;
617 if (iLen > cchMax)
618 return 0;
619 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
620 return iLen;
623 /*************************************************************************
624 * @ [SHLWAPI.30]
626 * Determine if a Unicode character is a blank.
628 * PARAMS
629 * wc [I] Character to check.
631 * RETURNS
632 * TRUE, if wc is a blank,
633 * FALSE otherwise.
636 BOOL WINAPI IsCharBlankW(WCHAR wc)
638 WORD CharType;
640 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
643 /*************************************************************************
644 * @ [SHLWAPI.31]
646 * Determine if a Unicode character is punctuation.
648 * PARAMS
649 * wc [I] Character to check.
651 * RETURNS
652 * TRUE, if wc is punctuation,
653 * FALSE otherwise.
655 BOOL WINAPI IsCharPunctW(WCHAR wc)
657 WORD CharType;
659 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
662 /*************************************************************************
663 * @ [SHLWAPI.32]
665 * Determine if a Unicode character is a control character.
667 * PARAMS
668 * wc [I] Character to check.
670 * RETURNS
671 * TRUE, if wc is a control character,
672 * FALSE otherwise.
674 BOOL WINAPI IsCharCntrlW(WCHAR wc)
676 WORD CharType;
678 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
681 /*************************************************************************
682 * @ [SHLWAPI.33]
684 * Determine if a Unicode character is a digit.
686 * PARAMS
687 * wc [I] Character to check.
689 * RETURNS
690 * TRUE, if wc is a digit,
691 * FALSE otherwise.
693 BOOL WINAPI IsCharDigitW(WCHAR wc)
695 WORD CharType;
697 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
700 /*************************************************************************
701 * @ [SHLWAPI.34]
703 * Determine if a Unicode character is a hex digit.
705 * PARAMS
706 * wc [I] Character to check.
708 * RETURNS
709 * TRUE, if wc is a hex digit,
710 * FALSE otherwise.
712 BOOL WINAPI IsCharXDigitW(WCHAR wc)
714 WORD CharType;
716 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
719 /*************************************************************************
720 * @ [SHLWAPI.35]
723 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type)
725 return GetStringTypeW(CT_CTYPE3, src, count, type);
728 /*************************************************************************
729 * @ [SHLWAPI.151]
731 * Compare two Ascii strings up to a given length.
733 * PARAMS
734 * lpszSrc [I] Source string
735 * lpszCmp [I] String to compare to lpszSrc
736 * len [I] Maximum length
738 * RETURNS
739 * A number greater than, less than or equal to 0 depending on whether
740 * lpszSrc is greater than, less than or equal to lpszCmp.
742 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
744 return StrCmpNA(lpszSrc, lpszCmp, len);
747 /*************************************************************************
748 * @ [SHLWAPI.152]
750 * Unicode version of StrCmpNCA.
752 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
754 return StrCmpNW(lpszSrc, lpszCmp, len);
757 /*************************************************************************
758 * @ [SHLWAPI.153]
760 * Compare two Ascii strings up to a given length, ignoring case.
762 * PARAMS
763 * lpszSrc [I] Source string
764 * lpszCmp [I] String to compare to lpszSrc
765 * len [I] Maximum length
767 * RETURNS
768 * A number greater than, less than or equal to 0 depending on whether
769 * lpszSrc is greater than, less than or equal to lpszCmp.
771 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
773 return StrCmpNIA(lpszSrc, lpszCmp, len);
776 /*************************************************************************
777 * @ [SHLWAPI.154]
779 * Unicode version of StrCmpNICA.
781 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
783 return StrCmpNIW(lpszSrc, lpszCmp, len);
786 /*************************************************************************
787 * @ [SHLWAPI.155]
789 * Compare two Ascii strings.
791 * PARAMS
792 * lpszSrc [I] Source string
793 * lpszCmp [I] String to compare to lpszSrc
795 * RETURNS
796 * A number greater than, less than or equal to 0 depending on whether
797 * lpszSrc is greater than, less than or equal to lpszCmp.
799 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
801 return lstrcmpA(lpszSrc, lpszCmp);
804 /*************************************************************************
805 * @ [SHLWAPI.156]
807 * Unicode version of StrCmpCA.
809 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
811 return lstrcmpW(lpszSrc, lpszCmp);
814 /*************************************************************************
815 * @ [SHLWAPI.157]
817 * Compare two Ascii strings, ignoring case.
819 * PARAMS
820 * lpszSrc [I] Source string
821 * lpszCmp [I] String to compare to lpszSrc
823 * RETURNS
824 * A number greater than, less than or equal to 0 depending on whether
825 * lpszSrc is greater than, less than or equal to lpszCmp.
827 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
829 return lstrcmpiA(lpszSrc, lpszCmp);
832 /*************************************************************************
833 * @ [SHLWAPI.158]
835 * Unicode version of StrCmpICA.
837 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
839 return lstrcmpiW(lpszSrc, lpszCmp);
842 /*************************************************************************
843 * @ [SHLWAPI.160]
845 * Get an identification string for the OS and explorer.
847 * PARAMS
848 * lpszDest [O] Destination for Id string
849 * dwDestLen [I] Length of lpszDest
851 * RETURNS
852 * TRUE, If the string was created successfully
853 * FALSE, Otherwise
855 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
857 WCHAR buff[2084];
859 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
861 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
863 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
864 return TRUE;
866 return FALSE;
869 /*************************************************************************
870 * @ [SHLWAPI.161]
872 * Unicode version of SHAboutInfoA.
874 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
876 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
877 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
878 ' ','E','x','p','l','o','r','e','r','\0' };
879 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
880 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
881 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
882 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
883 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
884 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
885 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
886 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
887 ' ','E','x','p','l','o','r','e','r','\\',
888 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
889 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
890 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
891 'V','e','r','s','i','o','n','\0' };
892 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
893 'O','w','n','e','r','\0' };
894 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
895 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
896 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
897 static const WCHAR szUpdate[] = { 'I','E','A','K',
898 'U','p','d','a','t','e','U','r','l','\0' };
899 static const WCHAR szHelp[] = { 'I','E','A','K',
900 'H','e','l','p','S','t','r','i','n','g','\0' };
901 WCHAR buff[2084];
902 HKEY hReg;
903 DWORD dwType, dwLen;
905 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
907 if (!lpszDest)
908 return FALSE;
910 *lpszDest = '\0';
912 /* Try the NT key first, followed by 95/98 key */
913 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
914 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
915 return FALSE;
917 /* OS Version */
918 buff[0] = '\0';
919 dwLen = 30;
920 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
922 DWORD dwStrLen = strlenW(buff);
923 dwLen = 30 - dwStrLen;
924 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
925 szCustomized, &dwType, buff+dwStrLen, &dwLen);
927 StrCatBuffW(lpszDest, buff, dwDestLen);
929 /* ~Registered Owner */
930 buff[0] = '~';
931 dwLen = 256;
932 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
933 buff[1] = '\0';
934 StrCatBuffW(lpszDest, buff, dwDestLen);
936 /* ~Registered Organization */
937 dwLen = 256;
938 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
939 buff[1] = '\0';
940 StrCatBuffW(lpszDest, buff, dwDestLen);
942 /* FIXME: Not sure where this number comes from */
943 buff[0] = '~';
944 buff[1] = '0';
945 buff[2] = '\0';
946 StrCatBuffW(lpszDest, buff, dwDestLen);
948 /* ~Product Id */
949 dwLen = 256;
950 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
951 buff[1] = '\0';
952 StrCatBuffW(lpszDest, buff, dwDestLen);
954 /* ~IE Update Url */
955 dwLen = 2048;
956 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
957 buff[1] = '\0';
958 StrCatBuffW(lpszDest, buff, dwDestLen);
960 /* ~IE Help String */
961 dwLen = 256;
962 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
963 buff[1] = '\0';
964 StrCatBuffW(lpszDest, buff, dwDestLen);
966 RegCloseKey(hReg);
967 return TRUE;
970 /*************************************************************************
971 * @ [SHLWAPI.163]
973 * Call IOleCommandTarget_QueryStatus() on an object.
975 * PARAMS
976 * lpUnknown [I] Object supporting the IOleCommandTarget interface
977 * pguidCmdGroup [I] GUID for the command group
978 * cCmds [I]
979 * prgCmds [O] Commands
980 * pCmdText [O] Command text
982 * RETURNS
983 * Success: S_OK.
984 * Failure: E_FAIL, if lpUnknown is NULL.
985 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
986 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
988 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
989 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
991 HRESULT hRet = E_FAIL;
993 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
995 if (lpUnknown)
997 IOleCommandTarget* lpOle;
999 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1000 (void**)&lpOle);
1002 if (SUCCEEDED(hRet) && lpOle)
1004 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1005 prgCmds, pCmdText);
1006 IOleCommandTarget_Release(lpOle);
1009 return hRet;
1012 /*************************************************************************
1013 * @ [SHLWAPI.164]
1015 * Call IOleCommandTarget_Exec() on an object.
1017 * PARAMS
1018 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1019 * pguidCmdGroup [I] GUID for the command group
1021 * RETURNS
1022 * Success: S_OK.
1023 * Failure: E_FAIL, if lpUnknown is NULL.
1024 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1025 * Otherwise, an error code from IOleCommandTarget_Exec().
1027 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1028 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1029 VARIANT* pvaOut)
1031 HRESULT hRet = E_FAIL;
1033 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1034 nCmdexecopt, pvaIn, pvaOut);
1036 if (lpUnknown)
1038 IOleCommandTarget* lpOle;
1040 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1041 (void**)&lpOle);
1042 if (SUCCEEDED(hRet) && lpOle)
1044 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1045 nCmdexecopt, pvaIn, pvaOut);
1046 IOleCommandTarget_Release(lpOle);
1049 return hRet;
1052 /*************************************************************************
1053 * @ [SHLWAPI.165]
1055 * Retrieve, modify, and re-set a value from a window.
1057 * PARAMS
1058 * hWnd [I] Window to get value from
1059 * offset [I] Offset of value
1060 * mask [I] Mask for flags
1061 * flags [I] Bits to set in window value
1063 * RETURNS
1064 * The new value as it was set, or 0 if any parameter is invalid.
1066 * NOTES
1067 * Only bits specified in mask are affected - set if present in flags and
1068 * reset otherwise.
1070 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT mask, UINT flags)
1072 LONG ret = GetWindowLongW(hwnd, offset);
1073 LONG new_flags = (flags & mask) | (ret & ~mask);
1075 TRACE("%p %d %x %x\n", hwnd, offset, mask, flags);
1077 if (new_flags != ret)
1078 ret = SetWindowLongW(hwnd, offset, new_flags);
1079 return ret;
1082 /*************************************************************************
1083 * @ [SHLWAPI.167]
1085 * Change a window's parent.
1087 * PARAMS
1088 * hWnd [I] Window to change parent of
1089 * hWndParent [I] New parent window
1091 * RETURNS
1092 * The old parent of hWnd.
1094 * NOTES
1095 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1096 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1098 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1100 TRACE("%p, %p\n", hWnd, hWndParent);
1102 if(GetParent(hWnd) == hWndParent)
1103 return NULL;
1105 if(hWndParent)
1106 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD | WS_POPUP, WS_CHILD);
1107 else
1108 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD | WS_POPUP, WS_POPUP);
1110 return hWndParent ? SetParent(hWnd, hWndParent) : NULL;
1113 /*************************************************************************
1114 * @ [SHLWAPI.168]
1116 * Locate and advise a connection point in an IConnectionPointContainer object.
1118 * PARAMS
1119 * lpUnkSink [I] Sink for the connection point advise call
1120 * riid [I] REFIID of connection point to advise
1121 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1122 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1123 * lpCookie [O] Pointer to connection point cookie
1124 * lppCP [O] Destination for the IConnectionPoint found
1126 * RETURNS
1127 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1128 * that was advised. The caller is responsible for releasing it.
1129 * Failure: E_FAIL, if any arguments are invalid.
1130 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1131 * Or an HRESULT error code if any call fails.
1133 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL fConnect,
1134 IUnknown* lpUnknown, LPDWORD lpCookie,
1135 IConnectionPoint **lppCP)
1137 HRESULT hRet;
1138 IConnectionPointContainer* lpContainer;
1139 IConnectionPoint *lpCP;
1141 if(!lpUnknown || (fConnect && !lpUnkSink))
1142 return E_FAIL;
1144 if(lppCP)
1145 *lppCP = NULL;
1147 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1148 (void**)&lpContainer);
1149 if (SUCCEEDED(hRet))
1151 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1153 if (SUCCEEDED(hRet))
1155 if(!fConnect)
1156 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1157 else
1158 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1160 if (FAILED(hRet))
1161 *lpCookie = 0;
1163 if (lppCP && SUCCEEDED(hRet))
1164 *lppCP = lpCP; /* Caller keeps the interface */
1165 else
1166 IConnectionPoint_Release(lpCP); /* Release it */
1169 IConnectionPointContainer_Release(lpContainer);
1171 return hRet;
1174 /*************************************************************************
1175 * @ [SHLWAPI.169]
1177 * Release an interface and zero a supplied pointer.
1179 * PARAMS
1180 * lpUnknown [I] Object to release
1182 * RETURNS
1183 * Nothing.
1185 void WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1187 TRACE("(%p)\n", lpUnknown);
1189 if(!lpUnknown || !*lpUnknown) return;
1191 TRACE("doing Release\n");
1193 IUnknown_Release(*lpUnknown);
1194 *lpUnknown = NULL;
1197 /*************************************************************************
1198 * @ [SHLWAPI.170]
1200 * Skip '//' if present in a string.
1202 * PARAMS
1203 * lpszSrc [I] String to check for '//'
1205 * RETURNS
1206 * Success: The next character after the '//' or the string if not present
1207 * Failure: NULL, if lpszStr is NULL.
1209 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1211 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1212 lpszSrc += 2;
1213 return lpszSrc;
1216 /*************************************************************************
1217 * @ [SHLWAPI.171]
1219 * Check if two interfaces come from the same object.
1221 * PARAMS
1222 * lpInt1 [I] Interface to check against lpInt2.
1223 * lpInt2 [I] Interface to check against lpInt1.
1225 * RETURNS
1226 * TRUE, If the interfaces come from the same object.
1227 * FALSE Otherwise.
1229 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1231 IUnknown *lpUnknown1, *lpUnknown2;
1232 BOOL ret;
1234 TRACE("(%p %p)\n", lpInt1, lpInt2);
1236 if (!lpInt1 || !lpInt2)
1237 return FALSE;
1239 if (lpInt1 == lpInt2)
1240 return TRUE;
1242 if (IUnknown_QueryInterface(lpInt1, &IID_IUnknown, (void**)&lpUnknown1) != S_OK)
1243 return FALSE;
1245 if (IUnknown_QueryInterface(lpInt2, &IID_IUnknown, (void**)&lpUnknown2) != S_OK)
1247 IUnknown_Release(lpUnknown1);
1248 return FALSE;
1251 ret = lpUnknown1 == lpUnknown2;
1253 IUnknown_Release(lpUnknown1);
1254 IUnknown_Release(lpUnknown2);
1256 return ret;
1259 /*************************************************************************
1260 * @ [SHLWAPI.172]
1262 * Get the window handle of an object.
1264 * PARAMS
1265 * lpUnknown [I] Object to get the window handle of
1266 * lphWnd [O] Destination for window handle
1268 * RETURNS
1269 * Success: S_OK. lphWnd contains the objects window handle.
1270 * Failure: An HRESULT error code.
1272 * NOTES
1273 * lpUnknown is expected to support one of the following interfaces:
1274 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1276 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1278 IUnknown *lpOle;
1279 HRESULT hRet = E_FAIL;
1281 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1283 if (!lpUnknown)
1284 return hRet;
1286 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1288 if (FAILED(hRet))
1290 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1292 if (FAILED(hRet))
1294 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1295 (void**)&lpOle);
1299 if (SUCCEEDED(hRet))
1301 /* Laziness here - Since GetWindow() is the first method for the above 3
1302 * interfaces, we use the same call for them all.
1304 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1305 IUnknown_Release(lpOle);
1306 if (lphWnd)
1307 TRACE("Returning HWND=%p\n", *lphWnd);
1310 return hRet;
1313 /*************************************************************************
1314 * @ [SHLWAPI.173]
1316 * Call a SetOwner method of IShellService from specified object.
1318 * PARAMS
1319 * iface [I] Object that supports IShellService
1320 * pUnk [I] Argument for the SetOwner call
1322 * RETURNS
1323 * Corresponding return value from last call or E_FAIL for null input
1325 HRESULT WINAPI IUnknown_SetOwner(IUnknown *iface, IUnknown *pUnk)
1327 IShellService *service;
1328 HRESULT hr;
1330 TRACE("(%p, %p)\n", iface, pUnk);
1332 if (!iface) return E_FAIL;
1334 hr = IUnknown_QueryInterface(iface, &IID_IShellService, (void**)&service);
1335 if (hr == S_OK)
1337 hr = IShellService_SetOwner(service, pUnk);
1338 IShellService_Release(service);
1341 return hr;
1344 /*************************************************************************
1345 * @ [SHLWAPI.174]
1347 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1348 * an object.
1351 HRESULT WINAPI IUnknown_SetSite(
1352 IUnknown *obj, /* [in] OLE object */
1353 IUnknown *site) /* [in] Site interface */
1355 HRESULT hr;
1356 IObjectWithSite *iobjwithsite;
1357 IInternetSecurityManager *isecmgr;
1359 if (!obj) return E_FAIL;
1361 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1362 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1363 if (SUCCEEDED(hr))
1365 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1366 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1367 IObjectWithSite_Release(iobjwithsite);
1369 else
1371 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1372 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1373 if (FAILED(hr)) return hr;
1375 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1376 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1377 IInternetSecurityManager_Release(isecmgr);
1379 return hr;
1382 /*************************************************************************
1383 * @ [SHLWAPI.175]
1385 * Call IPersist_GetClassID() on an object.
1387 * PARAMS
1388 * lpUnknown [I] Object supporting the IPersist interface
1389 * lpClassId [O] Destination for Class Id
1391 * RETURNS
1392 * Success: S_OK. lpClassId contains the Class Id requested.
1393 * Failure: E_FAIL, If lpUnknown is NULL,
1394 * E_NOINTERFACE If lpUnknown does not support IPersist,
1395 * Or an HRESULT error code.
1397 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1399 IPersist* lpPersist;
1400 HRESULT hRet = E_FAIL;
1402 TRACE("(%p,%s)\n", lpUnknown, debugstr_guid(lpClassId));
1404 if (lpUnknown)
1406 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1407 if (SUCCEEDED(hRet))
1409 IPersist_GetClassID(lpPersist, lpClassId);
1410 IPersist_Release(lpPersist);
1413 return hRet;
1416 /*************************************************************************
1417 * @ [SHLWAPI.176]
1419 * Retrieve a Service Interface from an object.
1421 * PARAMS
1422 * lpUnknown [I] Object to get an IServiceProvider interface from
1423 * sid [I] Service ID for IServiceProvider_QueryService() call
1424 * riid [I] Function requested for QueryService call
1425 * lppOut [O] Destination for the service interface pointer
1427 * RETURNS
1428 * Success: S_OK. lppOut contains an object providing the requested service
1429 * Failure: An HRESULT error code
1431 * NOTES
1432 * lpUnknown is expected to support the IServiceProvider interface.
1434 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1435 LPVOID *lppOut)
1437 IServiceProvider* pService = NULL;
1438 HRESULT hRet;
1440 if (!lppOut)
1441 return E_FAIL;
1443 *lppOut = NULL;
1445 if (!lpUnknown)
1446 return E_FAIL;
1448 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1449 (LPVOID*)&pService);
1451 if (hRet == S_OK && pService)
1453 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1455 /* Get a Service interface from the object */
1456 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1458 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1460 IServiceProvider_Release(pService);
1462 return hRet;
1465 /*************************************************************************
1466 * @ [SHLWAPI.484]
1468 * Calls IOleCommandTarget::Exec() for specified service object.
1470 * PARAMS
1471 * lpUnknown [I] Object to get an IServiceProvider interface from
1472 * service [I] Service ID for IServiceProvider_QueryService() call
1473 * group [I] Group ID for IOleCommandTarget::Exec() call
1474 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1475 * cmdOpt [I] Options flags for command
1476 * pIn [I] Input arguments for command
1477 * pOut [O] Output arguments for command
1479 * RETURNS
1480 * Success: S_OK. lppOut contains an object providing the requested service
1481 * Failure: An HRESULT error code
1483 * NOTES
1484 * lpUnknown is expected to support the IServiceProvider interface.
1486 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *lpUnknown, REFIID service,
1487 const GUID *group, DWORD cmdId, DWORD cmdOpt, VARIANT *pIn, VARIANT *pOut)
1489 IOleCommandTarget *target;
1490 HRESULT hr;
1492 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown, debugstr_guid(service),
1493 debugstr_guid(group), cmdId, cmdOpt, pIn, pOut);
1495 hr = IUnknown_QueryService(lpUnknown, service, &IID_IOleCommandTarget, (void**)&target);
1496 if (hr == S_OK)
1498 hr = IOleCommandTarget_Exec(target, group, cmdId, cmdOpt, pIn, pOut);
1499 IOleCommandTarget_Release(target);
1502 TRACE("<-- hr=0x%08x\n", hr);
1504 return hr;
1507 /*************************************************************************
1508 * @ [SHLWAPI.514]
1510 * Calls IProfferService methods to proffer/revoke specified service.
1512 * PARAMS
1513 * lpUnknown [I] Object to get an IServiceProvider interface from
1514 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1515 * pService [I] Service to proffer. If NULL ::Revoke is called
1516 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1518 * RETURNS
1519 * Success: S_OK. IProffer method returns S_OK
1520 * Failure: An HRESULT error code
1522 * NOTES
1523 * lpUnknown is expected to support the IServiceProvider interface.
1525 HRESULT WINAPI IUnknown_ProfferService(IUnknown *lpUnknown, REFGUID service, IServiceProvider *pService, DWORD *pCookie)
1527 IProfferService *proffer;
1528 HRESULT hr;
1530 TRACE("%p %s %p %p\n", lpUnknown, debugstr_guid(service), pService, pCookie);
1532 hr = IUnknown_QueryService(lpUnknown, &IID_IProfferService, &IID_IProfferService, (void**)&proffer);
1533 if (hr == S_OK)
1535 if (pService)
1536 hr = IProfferService_ProfferService(proffer, service, pService, pCookie);
1537 else
1539 hr = IProfferService_RevokeService(proffer, *pCookie);
1540 *pCookie = 0;
1543 IProfferService_Release(proffer);
1546 return hr;
1549 /*************************************************************************
1550 * @ [SHLWAPI.479]
1552 * Call an object's UIActivateIO method.
1554 * PARAMS
1555 * unknown [I] Object to call the UIActivateIO method on
1556 * activate [I] Parameter for UIActivateIO call
1557 * msg [I] Parameter for UIActivateIO call
1559 * RETURNS
1560 * Success: Value of UI_ActivateIO call
1561 * Failure: An HRESULT error code
1563 * NOTES
1564 * unknown is expected to support the IInputObject interface.
1566 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg)
1568 IInputObject* object = NULL;
1569 HRESULT ret;
1571 if (!unknown)
1572 return E_FAIL;
1574 /* Get an IInputObject interface from the object */
1575 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
1577 if (ret == S_OK)
1579 ret = IInputObject_UIActivateIO(object, activate, msg);
1580 IInputObject_Release(object);
1583 return ret;
1586 /*************************************************************************
1587 * @ [SHLWAPI.177]
1589 * Loads a popup menu.
1591 * PARAMS
1592 * hInst [I] Instance handle
1593 * szName [I] Menu name
1595 * RETURNS
1596 * Success: TRUE.
1597 * Failure: FALSE.
1599 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1601 HMENU hMenu;
1603 TRACE("%p %s\n", hInst, debugstr_w(szName));
1605 if ((hMenu = LoadMenuW(hInst, szName)))
1607 if (GetSubMenu(hMenu, 0))
1608 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1610 DestroyMenu(hMenu);
1611 return TRUE;
1613 return FALSE;
1616 typedef struct _enumWndData
1618 UINT uiMsgId;
1619 WPARAM wParam;
1620 LPARAM lParam;
1621 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1622 } enumWndData;
1624 /* Callback for SHLWAPI_178 */
1625 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1627 enumWndData *data = (enumWndData *)lParam;
1629 TRACE("(%p,%p)\n", hWnd, data);
1630 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1631 return TRUE;
1634 /*************************************************************************
1635 * @ [SHLWAPI.178]
1637 * Send or post a message to every child of a window.
1639 * PARAMS
1640 * hWnd [I] Window whose children will get the messages
1641 * uiMsgId [I] Message Id
1642 * wParam [I] WPARAM of message
1643 * lParam [I] LPARAM of message
1644 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1646 * RETURNS
1647 * Nothing.
1649 * NOTES
1650 * The appropriate ASCII or Unicode function is called for the window.
1652 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1654 enumWndData data;
1656 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1658 if(hWnd)
1660 data.uiMsgId = uiMsgId;
1661 data.wParam = wParam;
1662 data.lParam = lParam;
1664 if (bSend)
1665 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1666 else
1667 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1669 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1673 /*************************************************************************
1674 * @ [SHLWAPI.180]
1676 * Remove all sub-menus from a menu.
1678 * PARAMS
1679 * hMenu [I] Menu to remove sub-menus from
1681 * RETURNS
1682 * Success: 0. All sub-menus under hMenu are removed
1683 * Failure: -1, if any parameter is invalid
1685 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1687 int iItemCount = GetMenuItemCount(hMenu) - 1;
1689 TRACE("%p\n", hMenu);
1691 while (iItemCount >= 0)
1693 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1694 if (hSubMenu)
1695 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1696 iItemCount--;
1698 return iItemCount;
1701 /*************************************************************************
1702 * @ [SHLWAPI.181]
1704 * Enable or disable a menu item.
1706 * PARAMS
1707 * hMenu [I] Menu holding menu item
1708 * uID [I] ID of menu item to enable/disable
1709 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1711 * RETURNS
1712 * The return code from EnableMenuItem.
1714 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1716 TRACE("%p, %u, %d\n", hMenu, wItemID, bEnable);
1717 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1720 /*************************************************************************
1721 * @ [SHLWAPI.182]
1723 * Check or uncheck a menu item.
1725 * PARAMS
1726 * hMenu [I] Menu holding menu item
1727 * uID [I] ID of menu item to check/uncheck
1728 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1730 * RETURNS
1731 * The return code from CheckMenuItem.
1733 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1735 TRACE("%p, %u, %d\n", hMenu, uID, bCheck);
1736 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1739 /*************************************************************************
1740 * @ [SHLWAPI.183]
1742 * Register a window class if it isn't already.
1744 * PARAMS
1745 * lpWndClass [I] Window class to register
1747 * RETURNS
1748 * The result of the RegisterClassA call.
1750 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1752 WNDCLASSA wca;
1753 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1754 return TRUE;
1755 return (DWORD)RegisterClassA(wndclass);
1758 /*************************************************************************
1759 * @ [SHLWAPI.186]
1761 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1762 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1764 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1765 POINTL pt = { 0, 0 };
1767 TRACE("%p %p 0x%08x %p %p\n", pDrop, pDataObj, grfKeyState, lpPt, pdwEffect);
1769 if (!lpPt)
1770 lpPt = &pt;
1772 if (!pdwEffect)
1773 pdwEffect = &dwEffect;
1775 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1777 if (*pdwEffect != DROPEFFECT_NONE)
1778 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1780 IDropTarget_DragLeave(pDrop);
1781 return TRUE;
1784 /*************************************************************************
1785 * @ [SHLWAPI.187]
1787 * Call IPersistPropertyBag_Load() on an object.
1789 * PARAMS
1790 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1791 * lpPropBag [O] Destination for loaded IPropertyBag
1793 * RETURNS
1794 * Success: S_OK.
1795 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1797 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1799 IPersistPropertyBag* lpPPBag;
1800 HRESULT hRet = E_FAIL;
1802 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1804 if (lpUnknown)
1806 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1807 (void**)&lpPPBag);
1808 if (SUCCEEDED(hRet) && lpPPBag)
1810 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1811 IPersistPropertyBag_Release(lpPPBag);
1814 return hRet;
1817 /*************************************************************************
1818 * @ [SHLWAPI.188]
1820 * Call IOleControlSite_TranslateAccelerator() on an object.
1822 * PARAMS
1823 * lpUnknown [I] Object supporting the IOleControlSite interface.
1824 * lpMsg [I] Key message to be processed.
1825 * dwModifiers [I] Flags containing the state of the modifier keys.
1827 * RETURNS
1828 * Success: S_OK.
1829 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1831 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1833 IOleControlSite* lpCSite = NULL;
1834 HRESULT hRet = E_INVALIDARG;
1836 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1837 if (lpUnknown)
1839 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1840 (void**)&lpCSite);
1841 if (SUCCEEDED(hRet) && lpCSite)
1843 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1844 IOleControlSite_Release(lpCSite);
1847 return hRet;
1851 /*************************************************************************
1852 * @ [SHLWAPI.189]
1854 * Call IOleControlSite_OnFocus() on an object.
1856 * PARAMS
1857 * lpUnknown [I] Object supporting the IOleControlSite interface.
1858 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1860 * RETURNS
1861 * Success: S_OK.
1862 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1864 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
1866 IOleControlSite* lpCSite = NULL;
1867 HRESULT hRet = E_FAIL;
1869 TRACE("(%p, %d)\n", lpUnknown, fGotFocus);
1870 if (lpUnknown)
1872 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1873 (void**)&lpCSite);
1874 if (SUCCEEDED(hRet) && lpCSite)
1876 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1877 IOleControlSite_Release(lpCSite);
1880 return hRet;
1883 /*************************************************************************
1884 * @ [SHLWAPI.190]
1886 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1887 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1889 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1890 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1891 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1892 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1893 HRESULT hRet = E_INVALIDARG;
1894 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1896 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1898 if (lpUnknown && lpArg4)
1900 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1901 (REFGUID)function_id, (void**)&lpUnkInner);
1903 if (SUCCEEDED(hRet) && lpUnkInner)
1905 /* FIXME: The type of service object requested is unknown, however
1906 * testing shows that its first method is called with 4 parameters.
1907 * Fake this by using IParseDisplayName_ParseDisplayName since the
1908 * signature and position in the vtable matches our unknown object type.
1910 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1911 lpArg1, lpArg2, lpArg3, lpArg4);
1912 IUnknown_Release(lpUnkInner);
1915 return hRet;
1918 /*************************************************************************
1919 * @ [SHLWAPI.192]
1921 * Get a sub-menu from a menu item.
1923 * PARAMS
1924 * hMenu [I] Menu to get sub-menu from
1925 * uID [I] ID of menu item containing sub-menu
1927 * RETURNS
1928 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1930 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1932 MENUITEMINFOW mi;
1934 TRACE("(%p,%u)\n", hMenu, uID);
1936 mi.cbSize = sizeof(mi);
1937 mi.fMask = MIIM_SUBMENU;
1939 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1940 return NULL;
1942 return mi.hSubMenu;
1945 /*************************************************************************
1946 * @ [SHLWAPI.193]
1948 * Get the color depth of the primary display.
1950 * PARAMS
1951 * None.
1953 * RETURNS
1954 * The color depth of the primary display.
1956 DWORD WINAPI SHGetCurColorRes(void)
1958 HDC hdc;
1959 DWORD ret;
1961 TRACE("()\n");
1963 hdc = GetDC(0);
1964 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1965 ReleaseDC(0, hdc);
1966 return ret;
1969 /*************************************************************************
1970 * @ [SHLWAPI.194]
1972 * Wait for a message to arrive, with a timeout.
1974 * PARAMS
1975 * hand [I] Handle to query
1976 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1978 * RETURNS
1979 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1980 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1981 * message is available.
1983 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
1985 DWORD dwEndTicks = GetTickCount() + dwTimeout;
1986 DWORD dwRet;
1988 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
1990 MSG msg;
1992 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
1994 if (dwTimeout != INFINITE)
1996 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
1997 return WAIT_TIMEOUT;
2001 return dwRet;
2004 /*************************************************************************
2005 * @ [SHLWAPI.195]
2007 * Determine if a shell folder can be expanded.
2009 * PARAMS
2010 * lpFolder [I] Parent folder containing the object to test.
2011 * pidl [I] Id of the object to test.
2013 * RETURNS
2014 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2015 * Failure: E_INVALIDARG, if any argument is invalid.
2017 * NOTES
2018 * If the object to be tested does not expose the IQueryInfo() interface it
2019 * will not be identified as an expandable folder.
2021 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
2023 HRESULT hRet = E_INVALIDARG;
2024 IQueryInfo *lpInfo;
2026 if (lpFolder && pidl)
2028 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
2029 NULL, (void**)&lpInfo);
2030 if (FAILED(hRet))
2031 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
2032 else
2034 DWORD dwFlags = 0;
2036 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2037 * currently used". Really? You wouldn't be holding out on me would you?
2039 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
2041 if (SUCCEEDED(hRet))
2043 /* 0x2 is an undocumented flag apparently indicating expandability */
2044 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
2047 IQueryInfo_Release(lpInfo);
2050 return hRet;
2053 /*************************************************************************
2054 * @ [SHLWAPI.197]
2056 * Blank out a region of text by drawing the background only.
2058 * PARAMS
2059 * hDC [I] Device context to draw in
2060 * pRect [I] Area to draw in
2061 * cRef [I] Color to draw in
2063 * RETURNS
2064 * Nothing.
2066 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2068 COLORREF cOldColor = SetBkColor(hDC, cRef);
2069 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2070 SetBkColor(hDC, cOldColor);
2071 return 0;
2074 /*************************************************************************
2075 * @ [SHLWAPI.198]
2077 * Return the value associated with a key in a map.
2079 * PARAMS
2080 * lpKeys [I] A list of keys of length iLen
2081 * lpValues [I] A list of values associated with lpKeys, of length iLen
2082 * iLen [I] Length of both lpKeys and lpValues
2083 * iKey [I] The key value to look up in lpKeys
2085 * RETURNS
2086 * The value in lpValues associated with iKey, or -1 if iKey is not
2087 * found in lpKeys.
2089 * NOTES
2090 * - If two elements in the map share the same key, this function returns
2091 * the value closest to the start of the map
2092 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2094 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2096 if (lpKeys && lpValues)
2098 int i = 0;
2100 while (i < iLen)
2102 if (lpKeys[i] == iKey)
2103 return lpValues[i]; /* Found */
2104 i++;
2107 return -1; /* Not found */
2111 /*************************************************************************
2112 * @ [SHLWAPI.199]
2114 * Copy an interface pointer
2116 * PARAMS
2117 * lppDest [O] Destination for copy
2118 * lpUnknown [I] Source for copy
2120 * RETURNS
2121 * Nothing.
2123 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2125 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2127 IUnknown_AtomicRelease(lppDest);
2129 if (lpUnknown)
2131 IUnknown_AddRef(lpUnknown);
2132 *lppDest = lpUnknown;
2136 /*************************************************************************
2137 * @ [SHLWAPI.200]
2140 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2141 REFGUID riidCmdGrp, ULONG cCmds,
2142 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2144 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2145 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2147 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2148 return DRAGDROP_E_NOTREGISTERED;
2151 /*************************************************************************
2152 * @ [SHLWAPI.201]
2155 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2156 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2157 VARIANT* pvaOut)
2159 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2160 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2161 return DRAGDROP_E_NOTREGISTERED;
2164 /*************************************************************************
2165 * @ [SHLWAPI.202]
2168 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2170 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2171 return DRAGDROP_E_NOTREGISTERED;
2174 /*************************************************************************
2175 * @ [SHLWAPI.204]
2177 * Determine if a window is not a child of another window.
2179 * PARAMS
2180 * hParent [I] Suspected parent window
2181 * hChild [I] Suspected child window
2183 * RETURNS
2184 * TRUE: If hChild is a child window of hParent
2185 * FALSE: If hChild is not a child window of hParent, or they are equal
2187 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2189 TRACE("(%p,%p)\n", hParent, hChild);
2191 if (!hParent || !hChild)
2192 return TRUE;
2193 else if(hParent == hChild)
2194 return FALSE;
2195 return !IsChild(hParent, hChild);
2198 /*************************************************************************
2199 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2202 typedef struct
2204 DWORD num_items; /* Number of elements inserted */
2205 void *mem; /* Ptr to array */
2206 DWORD blocks_alloced; /* Number of elements allocated */
2207 BYTE inc; /* Number of elements to grow by when we need to expand */
2208 BYTE block_size; /* Size in bytes of an element */
2209 BYTE flags; /* Flags */
2210 } FDSA_info;
2212 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2214 /*************************************************************************
2215 * @ [SHLWAPI.208]
2217 * Initialize an FDSA array.
2219 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2220 DWORD init_blocks)
2222 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2224 if(inc == 0)
2225 inc = 1;
2227 if(mem)
2228 memset(mem, 0, block_size * init_blocks);
2230 info->num_items = 0;
2231 info->inc = inc;
2232 info->mem = mem;
2233 info->blocks_alloced = init_blocks;
2234 info->block_size = block_size;
2235 info->flags = 0;
2237 return TRUE;
2240 /*************************************************************************
2241 * @ [SHLWAPI.209]
2243 * Destroy an FDSA array
2245 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2247 TRACE("(%p)\n", info);
2249 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2251 HeapFree(GetProcessHeap(), 0, info->mem);
2252 return FALSE;
2255 return TRUE;
2258 /*************************************************************************
2259 * @ [SHLWAPI.210]
2261 * Insert element into an FDSA array
2263 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
2265 TRACE("(%p 0x%08x %p)\n", info, where, block);
2266 if(where > info->num_items)
2267 where = info->num_items;
2269 if(info->num_items >= info->blocks_alloced)
2271 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2272 if(info->flags & 0x1)
2273 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2274 else
2276 void *old_mem = info->mem;
2277 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2278 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2280 info->blocks_alloced += info->inc;
2281 info->flags |= 0x1;
2284 if(where < info->num_items)
2286 memmove((char*)info->mem + (where + 1) * info->block_size,
2287 (char*)info->mem + where * info->block_size,
2288 (info->num_items - where) * info->block_size);
2290 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2292 info->num_items++;
2293 return where;
2296 /*************************************************************************
2297 * @ [SHLWAPI.211]
2299 * Delete an element from an FDSA array.
2301 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2303 TRACE("(%p 0x%08x)\n", info, where);
2305 if(where >= info->num_items)
2306 return FALSE;
2308 if(where < info->num_items - 1)
2310 memmove((char*)info->mem + where * info->block_size,
2311 (char*)info->mem + (where + 1) * info->block_size,
2312 (info->num_items - where - 1) * info->block_size);
2314 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2315 0, info->block_size);
2316 info->num_items--;
2317 return TRUE;
2320 /*************************************************************************
2321 * @ [SHLWAPI.219]
2323 * Call IUnknown_QueryInterface() on a table of objects.
2325 * RETURNS
2326 * Success: S_OK.
2327 * Failure: E_POINTER or E_NOINTERFACE.
2329 HRESULT WINAPI QISearch(
2330 void *base, /* [in] Table of interfaces */
2331 const QITAB *table, /* [in] Array of REFIIDs and indexes into the table */
2332 REFIID riid, /* [in] REFIID to get interface for */
2333 void **ppv) /* [out] Destination for interface pointer */
2335 HRESULT ret;
2336 IUnknown *a_vtbl;
2337 const QITAB *xmove;
2339 TRACE("(%p %p %s %p)\n", base, table, debugstr_guid(riid), ppv);
2340 if (ppv) {
2341 xmove = table;
2342 while (xmove->piid) {
2343 TRACE("trying (offset %d) %s\n", xmove->dwOffset, debugstr_guid(xmove->piid));
2344 if (IsEqualIID(riid, xmove->piid)) {
2345 a_vtbl = (IUnknown*)(xmove->dwOffset + (LPBYTE)base);
2346 TRACE("matched, returning (%p)\n", a_vtbl);
2347 *ppv = a_vtbl;
2348 IUnknown_AddRef(a_vtbl);
2349 return S_OK;
2351 xmove++;
2354 if (IsEqualIID(riid, &IID_IUnknown)) {
2355 a_vtbl = (IUnknown*)(table->dwOffset + (LPBYTE)base);
2356 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2357 *ppv = a_vtbl;
2358 IUnknown_AddRef(a_vtbl);
2359 return S_OK;
2361 *ppv = 0;
2362 ret = E_NOINTERFACE;
2363 } else
2364 ret = E_POINTER;
2366 TRACE("-- 0x%08x\n", ret);
2367 return ret;
2370 /*************************************************************************
2371 * @ [SHLWAPI.220]
2373 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2375 * PARAMS
2376 * hWnd [I] Parent Window to set the property
2377 * id [I] Index of child Window to set the Font
2379 * RETURNS
2380 * Success: S_OK
2383 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id)
2385 FIXME("(%p, %d) stub\n", hWnd, id);
2386 return S_OK;
2389 /*************************************************************************
2390 * @ [SHLWAPI.221]
2392 * Remove the "PropDlgFont" property from a window.
2394 * PARAMS
2395 * hWnd [I] Window to remove the property from
2397 * RETURNS
2398 * A handle to the removed property, or NULL if it did not exist.
2400 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2402 HANDLE hProp;
2404 TRACE("(%p)\n", hWnd);
2406 hProp = GetPropA(hWnd, "PropDlgFont");
2408 if(hProp)
2410 DeleteObject(hProp);
2411 hProp = RemovePropA(hWnd, "PropDlgFont");
2413 return hProp;
2416 /*************************************************************************
2417 * @ [SHLWAPI.236]
2419 * Load the in-process server of a given GUID.
2421 * PARAMS
2422 * refiid [I] GUID of the server to load.
2424 * RETURNS
2425 * Success: A handle to the loaded server dll.
2426 * Failure: A NULL handle.
2428 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2430 HKEY newkey;
2431 DWORD type, count;
2432 CHAR value[MAX_PATH], string[MAX_PATH];
2434 strcpy(string, "CLSID\\");
2435 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2436 strcat(string, "\\InProcServer32");
2438 count = MAX_PATH;
2439 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2440 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2441 RegCloseKey(newkey);
2442 return LoadLibraryExA(value, 0, 0);
2445 /*************************************************************************
2446 * @ [SHLWAPI.237]
2448 * Unicode version of SHLWAPI_183.
2450 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2452 WNDCLASSW WndClass;
2454 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2456 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2457 return TRUE;
2458 return RegisterClassW(lpWndClass);
2461 /*************************************************************************
2462 * @ [SHLWAPI.238]
2464 * Unregister a list of classes.
2466 * PARAMS
2467 * hInst [I] Application instance that registered the classes
2468 * lppClasses [I] List of class names
2469 * iCount [I] Number of names in lppClasses
2471 * RETURNS
2472 * Nothing.
2474 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2476 WNDCLASSA WndClass;
2478 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2480 while (iCount > 0)
2482 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2483 UnregisterClassA(*lppClasses, hInst);
2484 lppClasses++;
2485 iCount--;
2489 /*************************************************************************
2490 * @ [SHLWAPI.239]
2492 * Unicode version of SHUnregisterClassesA.
2494 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2496 WNDCLASSW WndClass;
2498 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2500 while (iCount > 0)
2502 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2503 UnregisterClassW(*lppClasses, hInst);
2504 lppClasses++;
2505 iCount--;
2509 /*************************************************************************
2510 * @ [SHLWAPI.240]
2512 * Call The correct (Ascii/Unicode) default window procedure for a window.
2514 * PARAMS
2515 * hWnd [I] Window to call the default procedure for
2516 * uMessage [I] Message ID
2517 * wParam [I] WPARAM of message
2518 * lParam [I] LPARAM of message
2520 * RETURNS
2521 * The result of calling DefWindowProcA() or DefWindowProcW().
2523 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2525 if (IsWindowUnicode(hWnd))
2526 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2527 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2530 /*************************************************************************
2531 * @ [SHLWAPI.256]
2533 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2535 HRESULT hRet = E_INVALIDARG;
2536 LPOBJECTWITHSITE lpSite = NULL;
2538 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2540 if (lpUnknown && iid && lppSite)
2542 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2543 (void**)&lpSite);
2544 if (SUCCEEDED(hRet) && lpSite)
2546 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2547 IObjectWithSite_Release(lpSite);
2550 return hRet;
2553 /*************************************************************************
2554 * @ [SHLWAPI.257]
2556 * Create a worker window using CreateWindowExA().
2558 * PARAMS
2559 * wndProc [I] Window procedure
2560 * hWndParent [I] Parent window
2561 * dwExStyle [I] Extra style flags
2562 * dwStyle [I] Style flags
2563 * hMenu [I] Window menu
2564 * wnd_extra [I] Window extra bytes value
2566 * RETURNS
2567 * Success: The window handle of the newly created window.
2568 * Failure: 0.
2570 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2571 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra)
2573 static const char szClass[] = "WorkerA";
2574 WNDCLASSA wc;
2575 HWND hWnd;
2577 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2578 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
2580 /* Create Window class */
2581 wc.style = 0;
2582 wc.lpfnWndProc = DefWindowProcA;
2583 wc.cbClsExtra = 0;
2584 wc.cbWndExtra = sizeof(LONG_PTR);
2585 wc.hInstance = shlwapi_hInstance;
2586 wc.hIcon = NULL;
2587 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2588 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2589 wc.lpszMenuName = NULL;
2590 wc.lpszClassName = szClass;
2592 SHRegisterClassA(&wc);
2594 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2595 hWndParent, hMenu, shlwapi_hInstance, 0);
2596 if (hWnd)
2598 SetWindowLongPtrW(hWnd, 0, wnd_extra);
2600 if (wndProc) SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2603 return hWnd;
2606 typedef struct tagPOLICYDATA
2608 DWORD policy; /* flags value passed to SHRestricted */
2609 LPCWSTR appstr; /* application str such as "Explorer" */
2610 LPCWSTR keystr; /* name of the actual registry key / policy */
2611 } POLICYDATA, *LPPOLICYDATA;
2613 #define SHELL_NO_POLICY 0xffffffff
2615 /* default shell policy registry key */
2616 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2617 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2618 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2619 '\\','P','o','l','i','c','i','e','s',0};
2621 /*************************************************************************
2622 * @ [SHLWAPI.271]
2624 * Retrieve a policy value from the registry.
2626 * PARAMS
2627 * lpSubKey [I] registry key name
2628 * lpSubName [I] subname of registry key
2629 * lpValue [I] value name of registry value
2631 * RETURNS
2632 * the value associated with the registry key or 0 if not found
2634 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2636 DWORD retval, datsize = sizeof(retval);
2637 HKEY hKey;
2639 if (!lpSubKey)
2640 lpSubKey = strRegistryPolicyW;
2642 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2643 if (retval != ERROR_SUCCESS)
2644 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2645 if (retval != ERROR_SUCCESS)
2646 return 0;
2648 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2649 RegCloseKey(hKey);
2650 return retval;
2653 /*************************************************************************
2654 * @ [SHLWAPI.266]
2656 * Helper function to retrieve the possibly cached value for a specific policy
2658 * PARAMS
2659 * policy [I] The policy to look for
2660 * initial [I] Main registry key to open, if NULL use default
2661 * polTable [I] Table of known policies, 0 terminated
2662 * polArr [I] Cache array of policy values
2664 * RETURNS
2665 * The retrieved policy value or 0 if not successful
2667 * NOTES
2668 * This function is used by the native SHRestricted function to search for the
2669 * policy and cache it once retrieved. The current Wine implementation uses a
2670 * different POLICYDATA structure and implements a similar algorithm adapted to
2671 * that structure.
2673 DWORD WINAPI SHRestrictionLookup(
2674 DWORD policy,
2675 LPCWSTR initial,
2676 LPPOLICYDATA polTable,
2677 LPDWORD polArr)
2679 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2681 if (!polTable || !polArr)
2682 return 0;
2684 for (;polTable->policy; polTable++, polArr++)
2686 if (policy == polTable->policy)
2688 /* we have a known policy */
2690 /* check if this policy has been cached */
2691 if (*polArr == SHELL_NO_POLICY)
2692 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2693 return *polArr;
2696 /* we don't know this policy, return 0 */
2697 TRACE("unknown policy: (%08x)\n", policy);
2698 return 0;
2701 /*************************************************************************
2702 * @ [SHLWAPI.267]
2704 * Get an interface from an object.
2706 * RETURNS
2707 * Success: S_OK. ppv contains the requested interface.
2708 * Failure: An HRESULT error code.
2710 * NOTES
2711 * This QueryInterface asks the inner object for an interface. In case
2712 * of aggregation this request would be forwarded by the inner to the
2713 * outer object. This function asks the inner object directly for the
2714 * interface circumventing the forwarding to the outer object.
2716 HRESULT WINAPI SHWeakQueryInterface(
2717 IUnknown * pUnk, /* [in] Outer object */
2718 IUnknown * pInner, /* [in] Inner object */
2719 IID * riid, /* [in] Interface GUID to query for */
2720 LPVOID* ppv) /* [out] Destination for queried interface */
2722 HRESULT hret = E_NOINTERFACE;
2723 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2725 *ppv = NULL;
2726 if(pUnk && pInner) {
2727 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2728 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2730 TRACE("-- 0x%08x\n", hret);
2731 return hret;
2734 /*************************************************************************
2735 * @ [SHLWAPI.268]
2737 * Move a reference from one interface to another.
2739 * PARAMS
2740 * lpDest [O] Destination to receive the reference
2741 * lppUnknown [O] Source to give up the reference to lpDest
2743 * RETURNS
2744 * Nothing.
2746 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2748 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2750 if (*lppUnknown)
2752 /* Copy Reference*/
2753 IUnknown_AddRef(lpDest);
2754 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2758 /*************************************************************************
2759 * @ [SHLWAPI.269]
2761 * Convert an ASCII string of a CLSID into a CLSID.
2763 * PARAMS
2764 * idstr [I] String representing a CLSID in registry format
2765 * id [O] Destination for the converted CLSID
2767 * RETURNS
2768 * Success: TRUE. id contains the converted CLSID.
2769 * Failure: FALSE.
2771 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2773 WCHAR wClsid[40];
2774 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2775 return SUCCEEDED(CLSIDFromString(wClsid, id));
2778 /*************************************************************************
2779 * @ [SHLWAPI.270]
2781 * Unicode version of GUIDFromStringA.
2783 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2785 return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id));
2788 /*************************************************************************
2789 * @ [SHLWAPI.276]
2791 * Determine if the browser is integrated into the shell, and set a registry
2792 * key accordingly.
2794 * PARAMS
2795 * None.
2797 * RETURNS
2798 * 1, If the browser is not integrated.
2799 * 2, If the browser is integrated.
2801 * NOTES
2802 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2803 * either set to TRUE, or removed depending on whether the browser is deemed
2804 * to be integrated.
2806 DWORD WINAPI WhichPlatform(void)
2808 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2809 static DWORD dwState = 0;
2810 HKEY hKey;
2811 DWORD dwRet, dwData, dwSize;
2812 HMODULE hshell32;
2814 if (dwState)
2815 return dwState;
2817 /* If shell32 exports DllGetVersion(), the browser is integrated */
2818 dwState = 1;
2819 hshell32 = LoadLibraryA("shell32.dll");
2820 if (hshell32)
2822 FARPROC pDllGetVersion;
2823 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2824 dwState = pDllGetVersion ? 2 : 1;
2825 FreeLibrary(hshell32);
2828 /* Set or delete the key accordingly */
2829 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2830 "Software\\Microsoft\\Internet Explorer", 0,
2831 KEY_ALL_ACCESS, &hKey);
2832 if (!dwRet)
2834 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2835 (LPBYTE)&dwData, &dwSize);
2837 if (!dwRet && dwState == 1)
2839 /* Value exists but browser is not integrated */
2840 RegDeleteValueA(hKey, szIntegratedBrowser);
2842 else if (dwRet && dwState == 2)
2844 /* Browser is integrated but value does not exist */
2845 dwData = TRUE;
2846 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2847 (LPBYTE)&dwData, sizeof(dwData));
2849 RegCloseKey(hKey);
2851 return dwState;
2854 /*************************************************************************
2855 * @ [SHLWAPI.278]
2857 * Unicode version of SHCreateWorkerWindowA.
2859 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2860 DWORD dwStyle, HMENU hMenu, LONG msg_result)
2862 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
2863 WNDCLASSW wc;
2864 HWND hWnd;
2866 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
2867 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
2869 /* If our OS is natively ANSI, use the ANSI version */
2870 if (GetVersion() & 0x80000000) /* not NT */
2872 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
2873 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
2876 /* Create Window class */
2877 wc.style = 0;
2878 wc.lpfnWndProc = DefWindowProcW;
2879 wc.cbClsExtra = 0;
2880 wc.cbWndExtra = 4;
2881 wc.hInstance = shlwapi_hInstance;
2882 wc.hIcon = NULL;
2883 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2884 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2885 wc.lpszMenuName = NULL;
2886 wc.lpszClassName = szClass;
2888 SHRegisterClassW(&wc);
2890 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2891 hWndParent, hMenu, shlwapi_hInstance, 0);
2892 if (hWnd)
2894 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, msg_result);
2896 if (wndProc) SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2899 return hWnd;
2902 /*************************************************************************
2903 * @ [SHLWAPI.279]
2905 * Get and show a context menu from a shell folder.
2907 * PARAMS
2908 * hWnd [I] Window displaying the shell folder
2909 * lpFolder [I] IShellFolder interface
2910 * lpApidl [I] Id for the particular folder desired
2912 * RETURNS
2913 * Success: S_OK.
2914 * Failure: An HRESULT error code indicating the error.
2916 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2918 TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl);
2919 return SHInvokeCommand(hWnd, lpFolder, lpApidl, 0);
2922 /*************************************************************************
2923 * @ [SHLWAPI.281]
2925 * _SHPackDispParamsV
2927 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist)
2929 VARIANTARG *iter;
2931 TRACE("(%p %p %u ...)\n", params, args, cnt);
2933 params->rgvarg = args;
2934 params->rgdispidNamedArgs = NULL;
2935 params->cArgs = cnt;
2936 params->cNamedArgs = 0;
2938 iter = args+cnt;
2940 while(iter-- > args) {
2941 V_VT(iter) = va_arg(valist, enum VARENUM);
2943 TRACE("vt=%d\n", V_VT(iter));
2945 if(V_VT(iter) & VT_BYREF) {
2946 V_BYREF(iter) = va_arg(valist, LPVOID);
2947 } else {
2948 switch(V_VT(iter)) {
2949 case VT_I4:
2950 V_I4(iter) = va_arg(valist, LONG);
2951 break;
2952 case VT_BSTR:
2953 V_BSTR(iter) = va_arg(valist, BSTR);
2954 break;
2955 case VT_DISPATCH:
2956 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
2957 break;
2958 case VT_BOOL:
2959 V_BOOL(iter) = va_arg(valist, int);
2960 break;
2961 case VT_UNKNOWN:
2962 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
2963 break;
2964 default:
2965 V_VT(iter) = VT_I4;
2966 V_I4(iter) = va_arg(valist, LONG);
2971 return S_OK;
2974 /*************************************************************************
2975 * @ [SHLWAPI.282]
2977 * SHPackDispParams
2979 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...)
2981 __ms_va_list valist;
2982 HRESULT hres;
2984 __ms_va_start(valist, cnt);
2985 hres = SHPackDispParamsV(params, args, cnt, valist);
2986 __ms_va_end(valist);
2987 return hres;
2990 /*************************************************************************
2991 * SHLWAPI_InvokeByIID
2993 * This helper function calls IDispatch::Invoke for each sink
2994 * which implements given iid or IDispatch.
2997 static HRESULT SHLWAPI_InvokeByIID(
2998 IConnectionPoint* iCP,
2999 REFIID iid,
3000 DISPID dispId,
3001 DISPPARAMS* dispParams)
3003 IEnumConnections *enumerator;
3004 CONNECTDATA rgcd;
3005 static DISPPARAMS empty = {NULL, NULL, 0, 0};
3006 DISPPARAMS* params = dispParams;
3008 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
3009 if (FAILED(result))
3010 return result;
3012 /* Invoke is never happening with an NULL dispParams */
3013 if (!params)
3014 params = &empty;
3016 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
3018 IDispatch *dispIface;
3019 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
3020 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
3022 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
3023 IDispatch_Release(dispIface);
3025 IUnknown_Release(rgcd.pUnk);
3028 IEnumConnections_Release(enumerator);
3030 return S_OK;
3033 /*************************************************************************
3034 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3036 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP,
3037 DISPID dispId, DISPPARAMS* dispParams,
3038 DWORD unknown1, DWORD unknown2 )
3040 IID iid;
3041 HRESULT result;
3043 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
3045 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3046 if (SUCCEEDED(result))
3047 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3048 else
3049 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3051 return result;
3055 /*************************************************************************
3056 * @ [SHLWAPI.284]
3058 * IConnectionPoint_SimpleInvoke
3060 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
3061 IConnectionPoint* iCP,
3062 DISPID dispId,
3063 DISPPARAMS* dispParams)
3065 IID iid;
3066 HRESULT result;
3068 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
3070 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3071 if (SUCCEEDED(result))
3072 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3073 else
3074 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3076 return result;
3079 /*************************************************************************
3080 * @ [SHLWAPI.285]
3082 * Notify an IConnectionPoint object of changes.
3084 * PARAMS
3085 * lpCP [I] Object to notify
3086 * dispID [I]
3088 * RETURNS
3089 * Success: S_OK.
3090 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3091 * IConnectionPoint interface.
3093 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
3095 IEnumConnections *lpEnum;
3096 HRESULT hRet = E_NOINTERFACE;
3098 TRACE("(%p,0x%8X)\n", lpCP, dispID);
3100 /* Get an enumerator for the connections */
3101 if (lpCP)
3102 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
3104 if (SUCCEEDED(hRet))
3106 IPropertyNotifySink *lpSink;
3107 CONNECTDATA connData;
3108 ULONG ulFetched;
3110 /* Call OnChanged() for every notify sink in the connection point */
3111 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
3113 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
3114 lpSink)
3116 IPropertyNotifySink_OnChanged(lpSink, dispID);
3117 IPropertyNotifySink_Release(lpSink);
3119 IUnknown_Release(connData.pUnk);
3122 IEnumConnections_Release(lpEnum);
3124 return hRet;
3127 /*************************************************************************
3128 * @ [SHLWAPI.286]
3130 * IUnknown_CPContainerInvokeParam
3132 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
3133 IUnknown *container,
3134 REFIID riid,
3135 DISPID dispId,
3136 VARIANTARG* buffer,
3137 DWORD cParams, ...)
3139 HRESULT result;
3140 IConnectionPoint *iCP;
3141 IConnectionPointContainer *iCPC;
3142 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3143 __ms_va_list valist;
3145 if (!container)
3146 return E_NOINTERFACE;
3148 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
3149 if (FAILED(result))
3150 return result;
3152 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
3153 IConnectionPointContainer_Release(iCPC);
3154 if(FAILED(result))
3155 return result;
3157 __ms_va_start(valist, cParams);
3158 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
3159 __ms_va_end(valist);
3161 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3162 IConnectionPoint_Release(iCP);
3164 return result;
3167 /*************************************************************************
3168 * @ [SHLWAPI.287]
3170 * Notify an IConnectionPointContainer object of changes.
3172 * PARAMS
3173 * lpUnknown [I] Object to notify
3174 * dispID [I]
3176 * RETURNS
3177 * Success: S_OK.
3178 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3179 * IConnectionPointContainer interface.
3181 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3183 IConnectionPointContainer* lpCPC = NULL;
3184 HRESULT hRet = E_NOINTERFACE;
3186 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3188 if (lpUnknown)
3189 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3191 if (SUCCEEDED(hRet))
3193 IConnectionPoint* lpCP;
3195 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3196 IConnectionPointContainer_Release(lpCPC);
3198 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3199 IConnectionPoint_Release(lpCP);
3201 return hRet;
3204 /*************************************************************************
3205 * @ [SHLWAPI.289]
3207 * See PlaySoundW.
3209 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3211 return PlaySoundW(pszSound, hmod, fdwSound);
3214 /*************************************************************************
3215 * @ [SHLWAPI.294]
3217 * Retrieve a key value from an INI file. See GetPrivateProfileString for
3218 * more information.
3220 * PARAMS
3221 * appName [I] The section in the INI file that contains the key
3222 * keyName [I] The key to be retrieved
3223 * out [O] The buffer into which the key's value will be copied
3224 * outLen [I] The length of the `out' buffer
3225 * filename [I] The location of the INI file
3227 * RETURNS
3228 * Length of string copied into `out'.
3230 DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
3231 DWORD outLen, LPCWSTR filename)
3233 INT ret;
3234 WCHAR *buf;
3236 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName), debugstr_w(keyName),
3237 out, outLen, debugstr_w(filename));
3239 if(outLen == 0)
3240 return 0;
3242 buf = HeapAlloc(GetProcessHeap(), 0, outLen * sizeof(WCHAR));
3243 if(!buf){
3244 *out = 0;
3245 return 0;
3248 ret = GetPrivateProfileStringW(appName, keyName, NULL, buf, outLen, filename);
3249 if(ret)
3250 strcpyW(out, buf);
3251 else
3252 *out = 0;
3254 HeapFree(GetProcessHeap(), 0, buf);
3256 return strlenW(out);
3259 /*************************************************************************
3260 * @ [SHLWAPI.295]
3262 * Set a key value in an INI file. See WritePrivateProfileString for
3263 * more information.
3265 * PARAMS
3266 * appName [I] The section in the INI file that contains the key
3267 * keyName [I] The key to be set
3268 * str [O] The value of the key
3269 * filename [I] The location of the INI file
3271 * RETURNS
3272 * Success: TRUE
3273 * Failure: FALSE
3275 BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str,
3276 LPCWSTR filename)
3278 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
3279 debugstr_w(filename));
3281 return WritePrivateProfileStringW(appName, keyName, str, filename);
3284 /*************************************************************************
3285 * @ [SHLWAPI.313]
3287 * See SHGetFileInfoW.
3289 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3290 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3292 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3295 /*************************************************************************
3296 * @ [SHLWAPI.318]
3298 * See DragQueryFileW.
3300 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3302 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3305 /*************************************************************************
3306 * @ [SHLWAPI.333]
3308 * See SHBrowseForFolderW.
3310 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3312 return SHBrowseForFolderW(lpBi);
3315 /*************************************************************************
3316 * @ [SHLWAPI.334]
3318 * See SHGetPathFromIDListW.
3320 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3322 return SHGetPathFromIDListW(pidl, pszPath);
3325 /*************************************************************************
3326 * @ [SHLWAPI.335]
3328 * See ShellExecuteExW.
3330 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3332 return ShellExecuteExW(lpExecInfo);
3335 /*************************************************************************
3336 * @ [SHLWAPI.336]
3338 * See SHFileOperationW.
3340 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3342 return SHFileOperationW(lpFileOp);
3345 /*************************************************************************
3346 * @ [SHLWAPI.342]
3349 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
3351 return InterlockedCompareExchangePointer( dest, xchg, compare );
3354 /*************************************************************************
3355 * @ [SHLWAPI.350]
3357 * See GetFileVersionInfoSizeW.
3359 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
3361 return GetFileVersionInfoSizeW( filename, handle );
3364 /*************************************************************************
3365 * @ [SHLWAPI.351]
3367 * See GetFileVersionInfoW.
3369 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
3370 DWORD datasize, LPVOID data )
3372 return GetFileVersionInfoW( filename, handle, datasize, data );
3375 /*************************************************************************
3376 * @ [SHLWAPI.352]
3378 * See VerQueryValueW.
3380 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
3381 LPVOID *lplpBuffer, UINT *puLen )
3383 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3386 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3387 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3388 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3390 /*************************************************************************
3391 * @ [SHLWAPI.355]
3393 * Change the modality of a shell object.
3395 * PARAMS
3396 * lpUnknown [I] Object to make modeless
3397 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3399 * RETURNS
3400 * Success: S_OK. The modality lpUnknown is changed.
3401 * Failure: An HRESULT error code indicating the error.
3403 * NOTES
3404 * lpUnknown must support the IOleInPlaceFrame interface, the
3405 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3406 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3407 * or this call will fail.
3409 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3411 IUnknown *lpObj;
3412 HRESULT hRet;
3414 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3416 if (!lpUnknown)
3417 return E_FAIL;
3419 if (IsIface(IOleInPlaceActiveObject))
3420 EnableModeless(IOleInPlaceActiveObject);
3421 else if (IsIface(IOleInPlaceFrame))
3422 EnableModeless(IOleInPlaceFrame);
3423 else if (IsIface(IShellBrowser))
3424 EnableModeless(IShellBrowser);
3425 else if (IsIface(IInternetSecurityMgrSite))
3426 EnableModeless(IInternetSecurityMgrSite);
3427 else if (IsIface(IDocHostUIHandler))
3428 EnableModeless(IDocHostUIHandler);
3429 else
3430 return hRet;
3432 IUnknown_Release(lpObj);
3433 return S_OK;
3436 /*************************************************************************
3437 * @ [SHLWAPI.357]
3439 * See SHGetNewLinkInfoW.
3441 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3442 BOOL *pfMustCopy, UINT uFlags)
3444 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3447 /*************************************************************************
3448 * @ [SHLWAPI.358]
3450 * See SHDefExtractIconW.
3452 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3453 HICON* phiconSmall, UINT nIconSize)
3455 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3458 /*************************************************************************
3459 * @ [SHLWAPI.363]
3461 * Get and show a context menu from a shell folder.
3463 * PARAMS
3464 * hWnd [I] Window displaying the shell folder
3465 * lpFolder [I] IShellFolder interface
3466 * lpApidl [I] Id for the particular folder desired
3467 * dwCommandId [I] The command ID to invoke (0=invoke default)
3469 * RETURNS
3470 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3471 * executed.
3472 * Failure: An HRESULT error code indicating the error.
3474 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, DWORD dwCommandId)
3476 IContextMenu *iContext;
3477 HRESULT hRet;
3479 TRACE("(%p, %p, %p, %u)\n", hWnd, lpFolder, lpApidl, dwCommandId);
3481 if (!lpFolder)
3482 return E_FAIL;
3484 /* Get the context menu from the shell folder */
3485 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3486 &IID_IContextMenu, 0, (void**)&iContext);
3487 if (SUCCEEDED(hRet))
3489 HMENU hMenu;
3490 if ((hMenu = CreatePopupMenu()))
3492 HRESULT hQuery;
3494 /* Add the context menu entries to the popup */
3495 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3496 dwCommandId ? CMF_NORMAL : CMF_DEFAULTONLY);
3498 if (SUCCEEDED(hQuery))
3500 if (!dwCommandId)
3501 dwCommandId = GetMenuDefaultItem(hMenu, 0, 0);
3502 if (dwCommandId != (UINT)-1)
3504 CMINVOKECOMMANDINFO cmIci;
3505 /* Invoke the default item */
3506 memset(&cmIci,0,sizeof(cmIci));
3507 cmIci.cbSize = sizeof(cmIci);
3508 cmIci.fMask = CMIC_MASK_ASYNCOK;
3509 cmIci.hwnd = hWnd;
3510 cmIci.lpVerb = MAKEINTRESOURCEA(dwCommandId);
3511 cmIci.nShow = SW_SHOWNORMAL;
3513 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3516 DestroyMenu(hMenu);
3518 IContextMenu_Release(iContext);
3520 return hRet;
3523 /*************************************************************************
3524 * @ [SHLWAPI.370]
3526 * See ExtractIconW.
3528 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3529 UINT nIconIndex)
3531 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3534 /*************************************************************************
3535 * @ [SHLWAPI.377]
3537 * Load a library from the directory of a particular process.
3539 * PARAMS
3540 * new_mod [I] Library name
3541 * inst_hwnd [I] Module whose directory is to be used
3542 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3544 * RETURNS
3545 * Success: A handle to the loaded module
3546 * Failure: A NULL handle.
3548 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3550 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3551 * each call here.
3552 * FIXME: Native shows calls to:
3553 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3554 * CheckVersion
3555 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3556 * RegQueryValueExA for "LPKInstalled"
3557 * RegCloseKey
3558 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3559 * RegQueryValueExA for "ResourceLocale"
3560 * RegCloseKey
3561 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3562 * RegQueryValueExA for "Locale"
3563 * RegCloseKey
3564 * and then tests the Locale ("en" for me).
3565 * code below
3566 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3568 CHAR mod_path[2*MAX_PATH];
3569 LPSTR ptr;
3570 DWORD len;
3572 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3573 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3574 if (!len || len >= sizeof(mod_path)) return NULL;
3576 ptr = strrchr(mod_path, '\\');
3577 if (ptr) {
3578 strcpy(ptr+1, new_mod);
3579 TRACE("loading %s\n", debugstr_a(mod_path));
3580 return LoadLibraryA(mod_path);
3582 return NULL;
3585 /*************************************************************************
3586 * @ [SHLWAPI.378]
3588 * Unicode version of MLLoadLibraryA.
3590 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3592 WCHAR mod_path[2*MAX_PATH];
3593 LPWSTR ptr;
3594 DWORD len;
3596 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3597 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3598 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3600 ptr = strrchrW(mod_path, '\\');
3601 if (ptr) {
3602 strcpyW(ptr+1, new_mod);
3603 TRACE("loading %s\n", debugstr_w(mod_path));
3604 return LoadLibraryW(mod_path);
3606 return NULL;
3609 /*************************************************************************
3610 * ColorAdjustLuma [SHLWAPI.@]
3612 * Adjust the luminosity of a color
3614 * PARAMS
3615 * cRGB [I] RGB value to convert
3616 * dwLuma [I] Luma adjustment
3617 * bUnknown [I] Unknown
3619 * RETURNS
3620 * The adjusted RGB color.
3622 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3624 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3626 if (dwLuma)
3628 WORD wH, wL, wS;
3630 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3632 FIXME("Ignoring luma adjustment\n");
3634 /* FIXME: The adjustment is not linear */
3636 cRGB = ColorHLSToRGB(wH, wL, wS);
3638 return cRGB;
3641 /*************************************************************************
3642 * @ [SHLWAPI.389]
3644 * See GetSaveFileNameW.
3646 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3648 return GetSaveFileNameW(ofn);
3651 /*************************************************************************
3652 * @ [SHLWAPI.390]
3654 * See WNetRestoreConnectionW.
3656 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3658 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3661 /*************************************************************************
3662 * @ [SHLWAPI.391]
3664 * See WNetGetLastErrorW.
3666 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3667 LPWSTR lpNameBuf, DWORD nNameBufSize)
3669 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3672 /*************************************************************************
3673 * @ [SHLWAPI.401]
3675 * See PageSetupDlgW.
3677 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3679 return PageSetupDlgW(pagedlg);
3682 /*************************************************************************
3683 * @ [SHLWAPI.402]
3685 * See PrintDlgW.
3687 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3689 return PrintDlgW(printdlg);
3692 /*************************************************************************
3693 * @ [SHLWAPI.403]
3695 * See GetOpenFileNameW.
3697 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3699 return GetOpenFileNameW(ofn);
3702 /*************************************************************************
3703 * @ [SHLWAPI.404]
3705 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3707 /* Windows attempts to get an IPersist interface and, if that fails, an
3708 * IPersistFolder interface on the folder passed-in here. If one of those
3709 * interfaces is available, it then calls GetClassID on the folder... and
3710 * then calls IShellFolder_EnumObjects no matter what, even crashing if
3711 * lpFolder isn't actually an IShellFolder object. The purpose of getting
3712 * the ClassID is unknown, so we don't do it here.
3714 * For discussion and detailed tests, see:
3715 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated"
3716 * wine-devel mailing list, 3 Jun 2010
3719 return IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3722 /* INTERNAL: Map from HLS color space to RGB */
3723 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3725 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3727 if (wHue > 160)
3728 return wMid1;
3729 else if (wHue > 120)
3730 wHue = 160 - wHue;
3731 else if (wHue > 40)
3732 return wMid2;
3734 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3737 /* Convert to RGB and scale into RGB range (0..255) */
3738 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3740 /*************************************************************************
3741 * ColorHLSToRGB [SHLWAPI.@]
3743 * Convert from hls color space into an rgb COLORREF.
3745 * PARAMS
3746 * wHue [I] Hue amount
3747 * wLuminosity [I] Luminosity amount
3748 * wSaturation [I] Saturation amount
3750 * RETURNS
3751 * A COLORREF representing the converted color.
3753 * NOTES
3754 * Input hls values are constrained to the range (0..240).
3756 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3758 WORD wRed;
3760 if (wSaturation)
3762 WORD wGreen, wBlue, wMid1, wMid2;
3764 if (wLuminosity > 120)
3765 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3766 else
3767 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3769 wMid1 = wLuminosity * 2 - wMid2;
3771 wRed = GET_RGB(wHue + 80);
3772 wGreen = GET_RGB(wHue);
3773 wBlue = GET_RGB(wHue - 80);
3775 return RGB(wRed, wGreen, wBlue);
3778 wRed = wLuminosity * 255 / 240;
3779 return RGB(wRed, wRed, wRed);
3782 /*************************************************************************
3783 * @ [SHLWAPI.413]
3785 * Get the current docking status of the system.
3787 * PARAMS
3788 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3790 * RETURNS
3791 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3792 * a notebook.
3794 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3796 HW_PROFILE_INFOA hwInfo;
3798 TRACE("(0x%08x)\n", dwFlags);
3800 GetCurrentHwProfileA(&hwInfo);
3801 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3803 case DOCKINFO_DOCKED:
3804 case DOCKINFO_UNDOCKED:
3805 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3806 default:
3807 return 0;
3811 /*************************************************************************
3812 * @ [SHLWAPI.416]
3815 DWORD WINAPI SHWinHelpOnDemandW(HWND hwnd, LPCWSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2)
3818 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_w(helpfile), flags1, ptr1, flags2);
3819 return 0;
3822 /*************************************************************************
3823 * @ [SHLWAPI.417]
3826 DWORD WINAPI SHWinHelpOnDemandA(HWND hwnd, LPCSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2)
3829 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_a(helpfile), flags1, ptr1, flags2);
3830 return 0;
3833 /*************************************************************************
3834 * @ [SHLWAPI.418]
3836 * Function seems to do FreeLibrary plus other things.
3838 * FIXME native shows the following calls:
3839 * RtlEnterCriticalSection
3840 * LocalFree
3841 * GetProcAddress(Comctl32??, 150L)
3842 * DPA_DeletePtr
3843 * RtlLeaveCriticalSection
3844 * followed by the FreeLibrary.
3845 * The above code may be related to .377 above.
3847 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3849 FIXME("(%p) semi-stub\n", hModule);
3850 return FreeLibrary(hModule);
3853 /*************************************************************************
3854 * @ [SHLWAPI.419]
3856 BOOL WINAPI SHFlushSFCacheWrap(void) {
3857 FIXME(": stub\n");
3858 return TRUE;
3861 /*************************************************************************
3862 * @ [SHLWAPI.429]
3863 * FIXME I have no idea what this function does or what its arguments are.
3865 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3867 FIXME("(%p) stub\n", hInst);
3868 return FALSE;
3872 /*************************************************************************
3873 * @ [SHLWAPI.430]
3875 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3877 FIXME("(%p,%p) stub\n", hInst, hHeap);
3878 return E_FAIL; /* This is what is used if shlwapi not loaded */
3881 /*************************************************************************
3882 * @ [SHLWAPI.431]
3884 DWORD WINAPI MLClearMLHInstance(DWORD x)
3886 FIXME("(0x%08x)stub\n", x);
3887 return 0xabba1247;
3890 /*************************************************************************
3891 * @ [SHLWAPI.432]
3893 * See SHSendMessageBroadcastW
3896 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam)
3898 return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam,
3899 SMTO_ABORTIFHUNG, 2000, NULL);
3902 /*************************************************************************
3903 * @ [SHLWAPI.433]
3905 * A wrapper for sending Broadcast Messages to all top level Windows
3908 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam)
3910 return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam,
3911 SMTO_ABORTIFHUNG, 2000, NULL);
3914 /*************************************************************************
3915 * @ [SHLWAPI.436]
3917 * Convert a Unicode string CLSID into a CLSID.
3919 * PARAMS
3920 * idstr [I] string containing a CLSID in text form
3921 * id [O] CLSID extracted from the string
3923 * RETURNS
3924 * S_OK on success or E_INVALIDARG on failure
3926 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3928 return CLSIDFromString((LPCOLESTR)idstr, id);
3931 /*************************************************************************
3932 * @ [SHLWAPI.437]
3934 * Determine if the OS supports a given feature.
3936 * PARAMS
3937 * dwFeature [I] Feature requested (undocumented)
3939 * RETURNS
3940 * TRUE If the feature is available.
3941 * FALSE If the feature is not available.
3943 BOOL WINAPI IsOS(DWORD feature)
3945 OSVERSIONINFOA osvi;
3946 DWORD platform, majorv, minorv;
3948 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3949 if(!GetVersionExA(&osvi)) {
3950 ERR("GetVersionEx failed\n");
3951 return FALSE;
3954 majorv = osvi.dwMajorVersion;
3955 minorv = osvi.dwMinorVersion;
3956 platform = osvi.dwPlatformId;
3958 #define ISOS_RETURN(x) \
3959 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3960 return (x);
3962 switch(feature) {
3963 case OS_WIN32SORGREATER:
3964 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3965 || platform == VER_PLATFORM_WIN32_WINDOWS)
3966 case OS_NT:
3967 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3968 case OS_WIN95ORGREATER:
3969 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3970 case OS_NT4ORGREATER:
3971 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3972 case OS_WIN2000ORGREATER_ALT:
3973 case OS_WIN2000ORGREATER:
3974 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3975 case OS_WIN98ORGREATER:
3976 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3977 case OS_WIN98_GOLD:
3978 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3979 case OS_WIN2000PRO:
3980 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3981 case OS_WIN2000SERVER:
3982 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3983 case OS_WIN2000ADVSERVER:
3984 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3985 case OS_WIN2000DATACENTER:
3986 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3987 case OS_WIN2000TERMINAL:
3988 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3989 case OS_EMBEDDED:
3990 FIXME("(OS_EMBEDDED) What should we return here?\n");
3991 return FALSE;
3992 case OS_TERMINALCLIENT:
3993 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3994 return FALSE;
3995 case OS_TERMINALREMOTEADMIN:
3996 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3997 return FALSE;
3998 case OS_WIN95_GOLD:
3999 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
4000 case OS_MEORGREATER:
4001 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
4002 case OS_XPORGREATER:
4003 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
4004 case OS_HOME:
4005 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
4006 case OS_PROFESSIONAL:
4007 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4008 case OS_DATACENTER:
4009 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4010 case OS_ADVSERVER:
4011 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
4012 case OS_SERVER:
4013 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4014 case OS_TERMINALSERVER:
4015 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4016 case OS_PERSONALTERMINALSERVER:
4017 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
4018 case OS_FASTUSERSWITCHING:
4019 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
4020 return TRUE;
4021 case OS_WELCOMELOGONUI:
4022 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
4023 return FALSE;
4024 case OS_DOMAINMEMBER:
4025 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
4026 return TRUE;
4027 case OS_ANYSERVER:
4028 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4029 case OS_WOW6432:
4031 BOOL is_wow64;
4032 IsWow64Process(GetCurrentProcess(), &is_wow64);
4033 return is_wow64;
4035 case OS_WEBSERVER:
4036 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4037 case OS_SMALLBUSINESSSERVER:
4038 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4039 case OS_TABLETPC:
4040 FIXME("(OS_TABLEPC) What should we return here?\n");
4041 return FALSE;
4042 case OS_SERVERADMINUI:
4043 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
4044 return FALSE;
4045 case OS_MEDIACENTER:
4046 FIXME("(OS_MEDIACENTER) What should we return here?\n");
4047 return FALSE;
4048 case OS_APPLIANCE:
4049 FIXME("(OS_APPLIANCE) What should we return here?\n");
4050 return FALSE;
4051 case 0x25: /*OS_VISTAORGREATER*/
4052 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
4055 #undef ISOS_RETURN
4057 WARN("(0x%x) unknown parameter\n",feature);
4059 return FALSE;
4062 /*************************************************************************
4063 * @ [SHLWAPI.439]
4065 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
4067 DWORD type, sz = size;
4069 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
4070 return E_FAIL;
4072 return SHLoadIndirectString(buf, buf, size, NULL);
4075 /*************************************************************************
4076 * @ [SHLWAPI.478]
4078 * Call IInputObject_TranslateAcceleratorIO() on an object.
4080 * PARAMS
4081 * lpUnknown [I] Object supporting the IInputObject interface.
4082 * lpMsg [I] Key message to be processed.
4084 * RETURNS
4085 * Success: S_OK.
4086 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4088 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
4090 IInputObject* lpInput = NULL;
4091 HRESULT hRet = E_INVALIDARG;
4093 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
4094 if (lpUnknown)
4096 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4097 (void**)&lpInput);
4098 if (SUCCEEDED(hRet) && lpInput)
4100 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
4101 IInputObject_Release(lpInput);
4104 return hRet;
4107 /*************************************************************************
4108 * @ [SHLWAPI.481]
4110 * Call IInputObject_HasFocusIO() on an object.
4112 * PARAMS
4113 * lpUnknown [I] Object supporting the IInputObject interface.
4115 * RETURNS
4116 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4117 * or S_FALSE otherwise.
4118 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4120 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
4122 IInputObject* lpInput = NULL;
4123 HRESULT hRet = E_INVALIDARG;
4125 TRACE("(%p)\n", lpUnknown);
4126 if (lpUnknown)
4128 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4129 (void**)&lpInput);
4130 if (SUCCEEDED(hRet) && lpInput)
4132 hRet = IInputObject_HasFocusIO(lpInput);
4133 IInputObject_Release(lpInput);
4136 return hRet;
4139 /*************************************************************************
4140 * ColorRGBToHLS [SHLWAPI.@]
4142 * Convert an rgb COLORREF into the hls color space.
4144 * PARAMS
4145 * cRGB [I] Source rgb value
4146 * pwHue [O] Destination for converted hue
4147 * pwLuminance [O] Destination for converted luminance
4148 * pwSaturation [O] Destination for converted saturation
4150 * RETURNS
4151 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4152 * values.
4154 * NOTES
4155 * Output HLS values are constrained to the range (0..240).
4156 * For Achromatic conversions, Hue is set to 160.
4158 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
4159 LPWORD pwLuminance, LPWORD pwSaturation)
4161 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4163 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4165 wR = GetRValue(cRGB);
4166 wG = GetGValue(cRGB);
4167 wB = GetBValue(cRGB);
4169 wMax = max(wR, max(wG, wB));
4170 wMin = min(wR, min(wG, wB));
4172 /* Luminosity */
4173 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4175 if (wMax == wMin)
4177 /* Achromatic case */
4178 wSaturation = 0;
4179 /* Hue is now unrepresentable, but this is what native returns... */
4180 wHue = 160;
4182 else
4184 /* Chromatic case */
4185 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4187 /* Saturation */
4188 if (wLuminosity <= 120)
4189 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4190 else
4191 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4193 /* Hue */
4194 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4195 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4196 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4198 if (wR == wMax)
4199 wHue = wBNorm - wGNorm;
4200 else if (wG == wMax)
4201 wHue = 80 + wRNorm - wBNorm;
4202 else
4203 wHue = 160 + wGNorm - wRNorm;
4204 if (wHue < 0)
4205 wHue += 240;
4206 else if (wHue > 240)
4207 wHue -= 240;
4209 if (pwHue)
4210 *pwHue = wHue;
4211 if (pwLuminance)
4212 *pwLuminance = wLuminosity;
4213 if (pwSaturation)
4214 *pwSaturation = wSaturation;
4217 /*************************************************************************
4218 * SHCreateShellPalette [SHLWAPI.@]
4220 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4222 FIXME("stub\n");
4223 return CreateHalftonePalette(hdc);
4226 /*************************************************************************
4227 * SHGetInverseCMAP (SHLWAPI.@)
4229 * Get an inverse color map table.
4231 * PARAMS
4232 * lpCmap [O] Destination for color map
4233 * dwSize [I] Size of memory pointed to by lpCmap
4235 * RETURNS
4236 * Success: S_OK.
4237 * Failure: E_POINTER, If lpCmap is invalid.
4238 * E_INVALIDARG, If dwFlags is invalid
4239 * E_OUTOFMEMORY, If there is no memory available
4241 * NOTES
4242 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4243 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4244 * internal CMap.
4245 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4246 * this DLL's internal CMap.
4248 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4250 if (dwSize == 4) {
4251 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4252 *dest = (DWORD)0xabba1249;
4253 return 0;
4255 FIXME("(%p, %#x) stub\n", dest, dwSize);
4256 return 0;
4259 /*************************************************************************
4260 * SHIsLowMemoryMachine [SHLWAPI.@]
4262 * Determine if the current computer has low memory.
4264 * PARAMS
4265 * x [I] FIXME
4267 * RETURNS
4268 * TRUE if the users machine has 16 Megabytes of memory or less,
4269 * FALSE otherwise.
4271 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4273 FIXME("(0x%08x) stub\n", x);
4274 return FALSE;
4277 /*************************************************************************
4278 * GetMenuPosFromID [SHLWAPI.@]
4280 * Return the position of a menu item from its Id.
4282 * PARAMS
4283 * hMenu [I] Menu containing the item
4284 * wID [I] Id of the menu item
4286 * RETURNS
4287 * Success: The index of the menu item in hMenu.
4288 * Failure: -1, If the item is not found.
4290 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4292 MENUITEMINFOW mi;
4293 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4295 TRACE("%p %u\n", hMenu, wID);
4297 while (nIter < nCount)
4299 mi.cbSize = sizeof(mi);
4300 mi.fMask = MIIM_ID;
4301 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4303 TRACE("ret %d\n", nIter);
4304 return nIter;
4306 nIter++;
4309 return -1;
4312 /*************************************************************************
4313 * @ [SHLWAPI.179]
4315 * Same as SHLWAPI.GetMenuPosFromID
4317 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4319 TRACE("%p %u\n", hMenu, uID);
4320 return GetMenuPosFromID(hMenu, uID);
4324 /*************************************************************************
4325 * @ [SHLWAPI.448]
4327 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4329 while (*lpwstr)
4331 if (*lpwstr == '/')
4332 *lpwstr = '\\';
4333 lpwstr++;
4338 /*************************************************************************
4339 * @ [SHLWAPI.461]
4341 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4343 FIXME("(0x%08x) stub\n", dwUnknown);
4344 return 0;
4348 /*************************************************************************
4349 * @ [SHLWAPI.549]
4351 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4352 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4354 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4357 /*************************************************************************
4358 * SHSkipJunction [SHLWAPI.@]
4360 * Determine if a bind context can be bound to an object
4362 * PARAMS
4363 * pbc [I] Bind context to check
4364 * pclsid [I] CLSID of object to be bound to
4366 * RETURNS
4367 * TRUE: If it is safe to bind
4368 * FALSE: If pbc is invalid or binding would not be safe
4371 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4373 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4374 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4375 BOOL bRet = FALSE;
4377 if (pbc)
4379 IUnknown* lpUnk;
4381 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4383 CLSID clsid;
4385 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4386 IsEqualGUID(pclsid, &clsid))
4387 bRet = TRUE;
4389 IUnknown_Release(lpUnk);
4392 return bRet;
4395 /***********************************************************************
4396 * SHGetShellKey (SHLWAPI.491)
4398 HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create)
4400 enum _shellkey_flags {
4401 SHKEY_Root_HKCU = 0x1,
4402 SHKEY_Root_HKLM = 0x2,
4403 SHKEY_Key_Explorer = 0x00,
4404 SHKEY_Key_Shell = 0x10,
4405 SHKEY_Key_ShellNoRoam = 0x20,
4406 SHKEY_Key_Classes = 0x30,
4407 SHKEY_Subkey_Default = 0x0000,
4408 SHKEY_Subkey_ResourceName = 0x1000,
4409 SHKEY_Subkey_Handlers = 0x2000,
4410 SHKEY_Subkey_Associations = 0x3000,
4411 SHKEY_Subkey_Volatile = 0x4000,
4412 SHKEY_Subkey_MUICache = 0x5000,
4413 SHKEY_Subkey_FileExts = 0x6000
4416 static const WCHAR explorerW[] = {'S','o','f','t','w','a','r','e','\\',
4417 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4418 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4419 'E','x','p','l','o','r','e','r','\\'};
4420 static const WCHAR shellW[] = {'S','o','f','t','w','a','r','e','\\',
4421 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4422 'S','h','e','l','l','\\'};
4423 static const WCHAR shell_no_roamW[] = {'S','o','f','t','w','a','r','e','\\',
4424 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4425 'S','h','e','l','l','N','o','R','o','a','m','\\'};
4426 static const WCHAR classesW[] = {'S','o','f','t','w','a','r','e','\\',
4427 'C','l','a','s','s','e','s','\\'};
4429 static const WCHAR localized_resource_nameW[] = {'L','o','c','a','l','i','z','e','d',
4430 'R','e','s','o','u','r','c','e','N','a','m','e','\\'};
4431 static const WCHAR handlersW[] = {'H','a','n','d','l','e','r','s','\\'};
4432 static const WCHAR associationsW[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'};
4433 static const WCHAR volatileW[] = {'V','o','l','a','t','i','l','e','\\'};
4434 static const WCHAR mui_cacheW[] = {'M','U','I','C','a','c','h','e','\\'};
4435 static const WCHAR file_extsW[] = {'F','i','l','e','E','x','t','s','\\'};
4437 WCHAR *path;
4438 const WCHAR *key, *subkey;
4439 int size_key, size_subkey, size_user;
4440 HKEY hkey = NULL;
4442 TRACE("(0x%08x, %s, %d)\n", flags, debugstr_w(sub_key), create);
4444 /* For compatibility with Vista+ */
4445 if(flags == 0x1ffff)
4446 flags = 0x21;
4448 switch(flags&0xff0) {
4449 case SHKEY_Key_Explorer:
4450 key = explorerW;
4451 size_key = sizeof(explorerW);
4452 break;
4453 case SHKEY_Key_Shell:
4454 key = shellW;
4455 size_key = sizeof(shellW);
4456 break;
4457 case SHKEY_Key_ShellNoRoam:
4458 key = shell_no_roamW;
4459 size_key = sizeof(shell_no_roamW);
4460 break;
4461 case SHKEY_Key_Classes:
4462 key = classesW;
4463 size_key = sizeof(classesW);
4464 break;
4465 default:
4466 FIXME("unsupported flags (0x%08x)\n", flags);
4467 return NULL;
4470 switch(flags&0xff000) {
4471 case SHKEY_Subkey_Default:
4472 subkey = NULL;
4473 size_subkey = 0;
4474 break;
4475 case SHKEY_Subkey_ResourceName:
4476 subkey = localized_resource_nameW;
4477 size_subkey = sizeof(localized_resource_nameW);
4478 break;
4479 case SHKEY_Subkey_Handlers:
4480 subkey = handlersW;
4481 size_subkey = sizeof(handlersW);
4482 break;
4483 case SHKEY_Subkey_Associations:
4484 subkey = associationsW;
4485 size_subkey = sizeof(associationsW);
4486 break;
4487 case SHKEY_Subkey_Volatile:
4488 subkey = volatileW;
4489 size_subkey = sizeof(volatileW);
4490 break;
4491 case SHKEY_Subkey_MUICache:
4492 subkey = mui_cacheW;
4493 size_subkey = sizeof(mui_cacheW);
4494 break;
4495 case SHKEY_Subkey_FileExts:
4496 subkey = file_extsW;
4497 size_subkey = sizeof(file_extsW);
4498 break;
4499 default:
4500 FIXME("unsupported flags (0x%08x)\n", flags);
4501 return NULL;
4504 if(sub_key)
4505 size_user = lstrlenW(sub_key)*sizeof(WCHAR);
4506 else
4507 size_user = 0;
4509 path = HeapAlloc(GetProcessHeap(), 0, size_key+size_subkey+size_user+sizeof(WCHAR));
4510 if(!path) {
4511 ERR("Out of memory\n");
4512 return NULL;
4515 memcpy(path, key, size_key);
4516 if(subkey)
4517 memcpy(path+size_key/sizeof(WCHAR), subkey, size_subkey);
4518 if(sub_key)
4519 memcpy(path+(size_key+size_subkey)/sizeof(WCHAR), sub_key, size_user);
4520 path[(size_key+size_subkey+size_user)/sizeof(WCHAR)] = '\0';
4522 if(create)
4523 RegCreateKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
4524 path, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &hkey, NULL);
4525 else
4526 RegOpenKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
4527 path, 0, MAXIMUM_ALLOWED, &hkey);
4529 HeapFree(GetProcessHeap(), 0, path);
4530 return hkey;
4533 /***********************************************************************
4534 * SHQueueUserWorkItem (SHLWAPI.@)
4536 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback,
4537 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4538 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4540 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4541 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4543 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4544 FIXME("Unsupported arguments\n");
4546 return QueueUserWorkItem(pfnCallback, pContext, 0);
4549 /***********************************************************************
4550 * SHSetTimerQueueTimer (SHLWAPI.263)
4552 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
4553 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4554 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4556 HANDLE hNewTimer;
4558 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4559 if (dwFlags & TPS_LONGEXECTIME) {
4560 dwFlags &= ~TPS_LONGEXECTIME;
4561 dwFlags |= WT_EXECUTELONGFUNCTION;
4563 if (dwFlags & TPS_EXECUTEIO) {
4564 dwFlags &= ~TPS_EXECUTEIO;
4565 dwFlags |= WT_EXECUTEINIOTHREAD;
4568 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4569 dwDueTime, dwPeriod, dwFlags))
4570 return NULL;
4572 return hNewTimer;
4575 /***********************************************************************
4576 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4578 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4580 IInputObjectSite *pIOS = NULL;
4581 HRESULT hRet = E_INVALIDARG;
4583 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4585 if (lpUnknown)
4587 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4588 (void **)&pIOS);
4589 if (SUCCEEDED(hRet) && pIOS)
4591 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4592 IInputObjectSite_Release(pIOS);
4595 return hRet;
4598 /***********************************************************************
4599 * SKAllocValueW (SHLWAPI.519)
4601 HRESULT WINAPI SKAllocValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type,
4602 LPVOID *data, DWORD *count)
4604 DWORD ret, size;
4605 HKEY hkey;
4607 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey),
4608 debugstr_w(value), type, data, count);
4610 hkey = SHGetShellKey(flags, subkey, FALSE);
4611 if (!hkey)
4612 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4614 ret = SHQueryValueExW(hkey, value, NULL, type, NULL, &size);
4615 if (ret) {
4616 RegCloseKey(hkey);
4617 return HRESULT_FROM_WIN32(ret);
4620 size += 2;
4621 *data = LocalAlloc(0, size);
4622 if (!*data) {
4623 RegCloseKey(hkey);
4624 return E_OUTOFMEMORY;
4627 ret = SHQueryValueExW(hkey, value, NULL, type, *data, &size);
4628 if (count)
4629 *count = size;
4631 RegCloseKey(hkey);
4632 return HRESULT_FROM_WIN32(ret);
4635 /***********************************************************************
4636 * SKDeleteValueW (SHLWAPI.518)
4638 HRESULT WINAPI SKDeleteValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value)
4640 DWORD ret;
4641 HKEY hkey;
4643 TRACE("(0x%x, %s %s)\n", flags, debugstr_w(subkey), debugstr_w(value));
4645 hkey = SHGetShellKey(flags, subkey, FALSE);
4646 if (!hkey)
4647 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4649 ret = RegDeleteValueW(hkey, value);
4651 RegCloseKey(hkey);
4652 return HRESULT_FROM_WIN32(ret);
4655 /***********************************************************************
4656 * SKGetValueW (SHLWAPI.516)
4658 HRESULT WINAPI SKGetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type,
4659 void *data, DWORD *count)
4661 DWORD ret;
4662 HKEY hkey;
4664 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey),
4665 debugstr_w(value), type, data, count);
4667 hkey = SHGetShellKey(flags, subkey, FALSE);
4668 if (!hkey)
4669 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4671 ret = SHQueryValueExW(hkey, value, NULL, type, data, count);
4673 RegCloseKey(hkey);
4674 return HRESULT_FROM_WIN32(ret);
4677 /***********************************************************************
4678 * SKSetValueW (SHLWAPI.516)
4680 HRESULT WINAPI SKSetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value,
4681 DWORD type, void *data, DWORD count)
4683 DWORD ret;
4684 HKEY hkey;
4686 TRACE("(0x%x, %s, %s, %x, %p, %d)\n", flags, debugstr_w(subkey),
4687 debugstr_w(value), type, data, count);
4689 hkey = SHGetShellKey(flags, subkey, TRUE);
4690 if (!hkey)
4691 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4693 ret = RegSetValueExW(hkey, value, 0, type, data, count);
4695 RegCloseKey(hkey);
4696 return HRESULT_FROM_WIN32(ret);
4699 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4701 /***********************************************************************
4702 * GetUIVersion (SHLWAPI.452)
4704 DWORD WINAPI GetUIVersion(void)
4706 static DWORD version;
4708 if (!version)
4710 DllGetVersion_func pDllGetVersion;
4711 HMODULE dll = LoadLibraryA("shell32.dll");
4712 if (!dll) return 0;
4714 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4715 if (pDllGetVersion)
4717 DLLVERSIONINFO dvi;
4718 dvi.cbSize = sizeof(DLLVERSIONINFO);
4719 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4721 FreeLibrary( dll );
4722 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4724 return version;
4727 /***********************************************************************
4728 * ShellMessageBoxWrapW [SHLWAPI.388]
4730 * See shell32.ShellMessageBoxW
4732 * NOTE:
4733 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4734 * because we can't forward to it in the .spec file since it's exported by
4735 * ordinal. If you change the implementation here please update the code in
4736 * shell32 as well.
4738 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
4739 LPCWSTR lpCaption, UINT uType, ...)
4741 WCHAR *szText = NULL, szTitle[100];
4742 LPCWSTR pszText, pszTitle = szTitle;
4743 LPWSTR pszTemp;
4744 __ms_va_list args;
4745 int ret;
4747 __ms_va_start(args, uType);
4749 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
4751 if (IS_INTRESOURCE(lpCaption))
4752 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
4753 else
4754 pszTitle = lpCaption;
4756 if (IS_INTRESOURCE(lpText))
4758 const WCHAR *ptr;
4759 UINT len = LoadStringW(hInstance, LOWORD(lpText), (LPWSTR)&ptr, 0);
4761 if (len)
4763 szText = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
4764 if (szText) LoadStringW(hInstance, LOWORD(lpText), szText, len + 1);
4766 pszText = szText;
4767 if (!pszText) {
4768 WARN("Failed to load id %d\n", LOWORD(lpText));
4769 __ms_va_end(args);
4770 return 0;
4773 else
4774 pszText = lpText;
4776 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4777 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4779 __ms_va_end(args);
4781 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4783 HeapFree(GetProcessHeap(), 0, szText);
4784 LocalFree(pszTemp);
4785 return ret;
4788 /***********************************************************************
4789 * ZoneComputePaneSize [SHLWAPI.382]
4791 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4793 FIXME("\n");
4794 return 0x95;
4797 /***********************************************************************
4798 * SHChangeNotifyWrap [SHLWAPI.394]
4800 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
4802 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
4805 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
4806 SID_IDENTIFIER_AUTHORITY sidAuthority;
4807 DWORD dwUserGroupID;
4808 DWORD dwUserID;
4809 } SHELL_USER_SID, *PSHELL_USER_SID;
4811 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
4812 SHELL_USER_SID susID;
4813 DWORD dwAccessType;
4814 BOOL fInherit;
4815 DWORD dwAccessMask;
4816 DWORD dwInheritMask;
4817 DWORD dwInheritAccessMask;
4818 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
4820 /***********************************************************************
4821 * GetShellSecurityDescriptor [SHLWAPI.475]
4823 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4825 * PARAMS
4826 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4827 * each of which describes permissions to apply
4828 * cUserPerm [I] number of entries in apUserPerm array
4830 * RETURNS
4831 * success: pointer to SECURITY_DESCRIPTOR
4832 * failure: NULL
4834 * NOTES
4835 * Call should free returned descriptor with LocalFree
4837 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4839 PSID *sidlist;
4840 PSID cur_user = NULL;
4841 BYTE tuUser[2000];
4842 DWORD acl_size;
4843 int sid_count, i;
4844 PSECURITY_DESCRIPTOR psd = NULL;
4846 TRACE("%p %d\n", apUserPerm, cUserPerm);
4848 if (apUserPerm == NULL || cUserPerm <= 0)
4849 return NULL;
4851 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
4852 if (!sidlist)
4853 return NULL;
4855 acl_size = sizeof(ACL);
4857 for(sid_count = 0; sid_count < cUserPerm; sid_count++)
4859 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
4860 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
4861 PSHELL_USER_SID sid = &perm->susID;
4862 PSID pSid;
4863 BOOL ret = TRUE;
4865 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4866 { /* current user's SID */
4867 if (!cur_user)
4869 HANDLE Token;
4870 DWORD bufsize = sizeof(tuUser);
4872 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4873 if (ret)
4875 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4876 if (ret)
4877 cur_user = ((PTOKEN_USER)tuUser)->User.Sid;
4878 CloseHandle(Token);
4881 pSid = cur_user;
4882 } else if (sid->dwUserID==0) /* one sub-authority */
4883 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
4884 0, 0, 0, 0, 0, 0, &pSid);
4885 else
4886 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4887 0, 0, 0, 0, 0, 0, &pSid);
4888 if (!ret)
4889 goto free_sids;
4891 sidlist[sid_count] = pSid;
4892 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4893 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
4896 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
4898 if (psd != NULL)
4900 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4902 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4903 goto error;
4905 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4906 goto error;
4908 for(i = 0; i < sid_count; i++)
4910 PSHELL_USER_PERMISSION sup = apUserPerm[i];
4911 PSID sid = sidlist[i];
4913 switch(sup->dwAccessType)
4915 case ACCESS_ALLOWED_ACE_TYPE:
4916 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4917 goto error;
4918 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4919 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4920 goto error;
4921 break;
4922 case ACCESS_DENIED_ACE_TYPE:
4923 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4924 goto error;
4925 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4926 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4927 goto error;
4928 break;
4929 default:
4930 goto error;
4934 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4935 goto error;
4937 goto free_sids;
4939 error:
4940 LocalFree(psd);
4941 psd = NULL;
4942 free_sids:
4943 for(i = 0; i < sid_count; i++)
4945 if (!cur_user || sidlist[i] != cur_user)
4946 FreeSid(sidlist[i]);
4948 HeapFree(GetProcessHeap(), 0, sidlist);
4950 return psd;
4953 /***********************************************************************
4954 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4956 * Creates a property bag from a registry key
4958 * PARAMS
4959 * hKey [I] Handle to the desired registry key
4960 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4961 * grfMode [I] Optional flags
4962 * riid [I] IID of requested property bag interface
4963 * ppv [O] Address to receive pointer to the new interface
4965 * RETURNS
4966 * success: 0
4967 * failure: error code
4970 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey,
4971 DWORD grfMode, REFIID riid, void **ppv)
4973 FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode,
4974 debugstr_guid(riid), ppv);
4976 return E_NOTIMPL;
4979 /***********************************************************************
4980 * SHGetViewStatePropertyBag [SHLWAPI.515]
4982 * Retrieves a property bag in which the view state information of a folder
4983 * can be stored.
4985 * PARAMS
4986 * pidl [I] PIDL of the folder requested
4987 * bag_name [I] Name of the property bag requested
4988 * flags [I] Optional flags
4989 * riid [I] IID of requested property bag interface
4990 * ppv [O] Address to receive pointer to the new interface
4992 * RETURNS
4993 * success: S_OK
4994 * failure: error code
4997 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
4998 DWORD flags, REFIID riid, void **ppv)
5000 FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags,
5001 debugstr_guid(riid), ppv);
5003 return E_NOTIMPL;
5006 /***********************************************************************
5007 * SHFormatDateTimeW [SHLWAPI.354]
5009 * Produces a string representation of a time.
5011 * PARAMS
5012 * fileTime [I] Pointer to FILETIME structure specifying the time
5013 * flags [I] Flags specifying the desired output
5014 * buf [O] Pointer to buffer for output
5015 * size [I] Number of characters that can be contained in buffer
5017 * RETURNS
5018 * success: number of characters written to the buffer
5019 * failure: 0
5022 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
5023 LPWSTR buf, UINT size)
5025 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
5026 DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT;
5027 SYSTEMTIME st;
5028 FILETIME ft;
5029 INT ret = 0;
5031 TRACE("%p %p %p %u\n", fileTime, flags, buf, size);
5033 if (!buf || !size)
5034 return 0;
5036 if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS)
5037 FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS);
5039 FileTimeToLocalFileTime(fileTime, &ft);
5040 FileTimeToSystemTime(&ft, &st);
5042 /* first of all date */
5043 if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE))
5045 static const WCHAR sep1[] = {',',' ',0};
5046 static const WCHAR sep2[] = {' ',0};
5048 DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE;
5049 ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size);
5050 if (ret >= size) return ret;
5052 /* add separator */
5053 if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)))
5055 if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2))
5057 lstrcatW(&buf[ret-1], sep1);
5058 ret += 2;
5060 else
5062 lstrcatW(&buf[ret-1], sep2);
5063 ret++;
5067 /* time part */
5068 if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))
5070 DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS;
5072 if (ret) ret--;
5073 ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret);
5076 return ret;
5078 #undef SHFORMATDT_UNSUPPORTED_FLAGS
5081 /***********************************************************************
5082 * SHFormatDateTimeA [SHLWAPI.353]
5084 * See SHFormatDateTimeW.
5087 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags,
5088 LPSTR buf, UINT size)
5090 WCHAR *bufW;
5091 INT retval;
5093 if (!buf || !size)
5094 return 0;
5096 bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
5097 retval = SHFormatDateTimeW(fileTime, flags, bufW, size);
5099 if (retval != 0)
5100 WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL);
5102 HeapFree(GetProcessHeap(), 0, bufW);
5103 return retval;
5106 /***********************************************************************
5107 * ZoneCheckUrlExW [SHLWAPI.231]
5109 * Checks the details of the security zone for the supplied site. (?)
5111 * PARAMS
5113 * szURL [I] Pointer to the URL to check
5115 * Other parameters currently unknown.
5117 * RETURNS
5118 * unknown
5121 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2,
5122 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6,
5123 DWORD dwUnknown7)
5125 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2,
5126 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7);
5128 return 0;
5131 /***********************************************************************
5132 * SHVerbExistsNA [SHLWAPI.196]
5135 * PARAMS
5137 * verb [I] a string, often appears to be an extension.
5139 * Other parameters currently unknown.
5141 * RETURNS
5142 * unknown
5144 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3)
5146 FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3);
5147 return 0;
5150 /*************************************************************************
5151 * @ [SHLWAPI.538]
5153 * Undocumented: Implementation guessed at via Name and behavior
5155 * PARAMS
5156 * lpUnknown [I] Object to get an IServiceProvider interface from
5157 * riid [I] Function requested for QueryService call
5158 * lppOut [O] Destination for the service interface pointer
5160 * RETURNS
5161 * Success: S_OK. lppOut contains an object providing the requested service
5162 * Failure: An HRESULT error code
5164 * NOTES
5165 * lpUnknown is expected to support the IServiceProvider interface.
5167 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown,
5168 REFGUID riid, LPVOID *lppOut)
5170 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut);
5171 return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut);
5174 /**************************************************************************
5175 * SHPropertyBag_ReadLONG (SHLWAPI.496)
5177 * This function asks a property bag to read a named property as a LONG.
5179 * PARAMS
5180 * ppb: a IPropertyBag interface
5181 * pszPropName: Unicode string that names the property
5182 * pValue: address to receive the property value as a 32-bit signed integer
5184 * RETURNS
5185 * 0 for Success
5187 BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue)
5189 VARIANT var;
5190 HRESULT hr;
5191 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue);
5192 if (!pszPropName || !ppb || !pValue)
5193 return E_INVALIDARG;
5194 V_VT(&var) = VT_I4;
5195 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
5196 if (SUCCEEDED(hr))
5198 if (V_VT(&var) == VT_I4)
5199 *pValue = V_I4(&var);
5200 else
5201 hr = DISP_E_BADVARTYPE;
5203 return hr;
5206 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
5207 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
5208 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
5209 #define OBJCOMPAT_UNBINDABLE 0x00000004
5210 #define OBJCOMPAT_PINDLL 0x00000008
5211 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
5212 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
5213 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
5214 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
5215 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
5216 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
5217 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
5218 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
5219 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
5221 /* a search table for compatibility flags */
5222 struct objcompat_entry {
5223 const WCHAR name[30];
5224 DWORD value;
5227 /* expected to be sorted by name */
5228 static const struct objcompat_entry objcompat_table[] = {
5229 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
5230 OBJCOMPAT_COCREATESHELLFOLDERONLY },
5231 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
5232 OBJCOMPAT_CTXMENU_LIMITEDQI },
5233 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
5234 OBJCOMPAT_CTXMENU_LIMITEDQI },
5235 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
5236 OBJCOMPAT_CTXMENU_XPQCMFLAGS },
5237 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
5238 OBJCOMPAT_NEEDSFILESYSANCESTOR },
5239 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
5240 OBJCOMPAT_NEEDSSTORAGEANCESTOR },
5241 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
5242 OBJCOMPAT_NOIPROPERTYSTORE },
5243 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
5244 OBJCOMPAT_NOLEGACYWEBVIEW },
5245 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
5246 OBJCOMPAT_NOTAFILESYSTEM },
5247 { {'N','O','_','W','E','B','V','I','E','W',0},
5248 OBJCOMPAT_NO_WEBVIEW },
5249 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
5250 OBJCOMPAT_OTNEEDSSFCACHE },
5251 { {'P','I','N','D','L','L',0},
5252 OBJCOMPAT_PINDLL },
5253 { {'U','N','B','I','N','D','A','B','L','E',0},
5254 OBJCOMPAT_UNBINDABLE }
5257 /**************************************************************************
5258 * SHGetObjectCompatFlags (SHLWAPI.476)
5260 * Function returns an integer representation of compatibility flags stored
5261 * in registry for CLSID under ShellCompatibility subkey.
5263 * PARAMS
5264 * pUnk: pointer to object IUnknown interface, idetifies CLSID
5265 * clsid: pointer to CLSID to retrieve data for
5267 * RETURNS
5268 * 0 on failure, flags set on success
5270 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid)
5272 static const WCHAR compatpathW[] =
5273 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
5274 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
5275 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
5276 'O','b','j','e','c','t','s','\\','%','s',0};
5277 WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */];
5278 DWORD ret, length = sizeof(strW)/sizeof(WCHAR);
5279 OLECHAR *clsid_str;
5280 HKEY key;
5281 INT i;
5283 TRACE("%p %s\n", pUnk, debugstr_guid(clsid));
5285 if (!pUnk && !clsid) return 0;
5287 if (pUnk && !clsid)
5289 FIXME("iface not handled\n");
5290 return 0;
5293 StringFromCLSID(clsid, &clsid_str);
5294 sprintfW(strW, compatpathW, clsid_str);
5295 CoTaskMemFree(clsid_str);
5297 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key);
5298 if (ret != ERROR_SUCCESS) return 0;
5300 /* now collect flag values */
5301 ret = 0;
5302 for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++)
5304 INT left, right, res, x;
5306 /* search in table */
5307 left = 0;
5308 right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1;
5310 while (right >= left) {
5311 x = (left + right) / 2;
5312 res = strcmpW(strW, objcompat_table[x].name);
5313 if (res == 0)
5315 ret |= objcompat_table[x].value;
5316 break;
5318 else if (res < 0)
5319 right = x - 1;
5320 else
5321 left = x + 1;
5324 length = sizeof(strW)/sizeof(WCHAR);
5327 return ret;