msvcp90: Return last index in string::find_last_not_of_cstr_substr if input is empty.
[wine/multimedia.git] / dlls / shlwapi / ordinal.c
blobcc2c6a90870c5b7544bdadf6ec2867bd2bdbf0a2
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,BOOL);
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_DupSharedHandle
79 * Internal implementation of SHLWAPI_11.
81 static HANDLE SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
82 DWORD dwSrcProcId, DWORD dwAccess,
83 DWORD dwOptions)
85 HANDLE hDst, hSrc;
86 DWORD dwMyProcId = GetCurrentProcessId();
87 HANDLE hRet = NULL;
89 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
90 dwAccess, dwOptions);
92 /* Get dest process handle */
93 if (dwDstProcId == dwMyProcId)
94 hDst = GetCurrentProcess();
95 else
96 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
98 if (hDst)
100 /* Get src process handle */
101 if (dwSrcProcId == dwMyProcId)
102 hSrc = GetCurrentProcess();
103 else
104 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
106 if (hSrc)
108 /* Make handle available to dest process */
109 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
110 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
111 hRet = NULL;
113 if (dwSrcProcId != dwMyProcId)
114 CloseHandle(hSrc);
117 if (dwDstProcId != dwMyProcId)
118 CloseHandle(hDst);
121 TRACE("Returning handle %p\n", hRet);
122 return hRet;
125 /*************************************************************************
126 * @ [SHLWAPI.7]
128 * Create a block of sharable memory and initialise it with data.
130 * PARAMS
131 * lpvData [I] Pointer to data to write
132 * dwSize [I] Size of data
133 * dwProcId [I] ID of process owning data
135 * RETURNS
136 * Success: A shared memory handle
137 * Failure: NULL
139 * NOTES
140 * Ordinals 7-11 provide a set of calls to create shared memory between a
141 * group of processes. The shared memory is treated opaquely in that its size
142 * is not exposed to clients who map it. This is accomplished by storing
143 * the size of the map as the first DWORD of mapped data, and then offsetting
144 * the view pointer returned by this size.
147 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
149 HANDLE hMap;
150 LPVOID pMapped;
151 HANDLE hRet = NULL;
153 TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
155 /* Create file mapping of the correct length */
156 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
157 dwSize + sizeof(dwSize), NULL);
158 if (!hMap)
159 return hRet;
161 /* Get a view in our process address space */
162 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
164 if (pMapped)
166 /* Write size of data, followed by the data, to the view */
167 *((DWORD*)pMapped) = dwSize;
168 if (lpvData)
169 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
171 /* Release view. All further views mapped will be opaque */
172 UnmapViewOfFile(pMapped);
173 hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
174 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
175 DUPLICATE_SAME_ACCESS);
178 CloseHandle(hMap);
179 return hRet;
182 /*************************************************************************
183 * @ [SHLWAPI.8]
185 * Get a pointer to a block of shared memory from a shared memory handle.
187 * PARAMS
188 * hShared [I] Shared memory handle
189 * dwProcId [I] ID of process owning hShared
191 * RETURNS
192 * Success: A pointer to the shared memory
193 * Failure: NULL
196 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
198 HANDLE hDup;
199 LPVOID pMapped;
201 TRACE("(%p %d)\n", hShared, dwProcId);
203 /* Get handle to shared memory for current process */
204 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
205 FILE_MAP_ALL_ACCESS, 0);
206 /* Get View */
207 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
208 CloseHandle(hDup);
210 if (pMapped)
211 return (char *) pMapped + sizeof(DWORD); /* Hide size */
212 return NULL;
215 /*************************************************************************
216 * @ [SHLWAPI.9]
218 * Release a pointer to a block of shared memory.
220 * PARAMS
221 * lpView [I] Shared memory pointer
223 * RETURNS
224 * Success: TRUE
225 * Failure: FALSE
228 BOOL WINAPI SHUnlockShared(LPVOID lpView)
230 TRACE("(%p)\n", lpView);
231 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
234 /*************************************************************************
235 * @ [SHLWAPI.10]
237 * Destroy a block of sharable memory.
239 * PARAMS
240 * hShared [I] Shared memory handle
241 * dwProcId [I] ID of process owning hShared
243 * RETURNS
244 * Success: TRUE
245 * Failure: FALSE
248 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
250 HANDLE hClose;
252 TRACE("(%p %d)\n", hShared, dwProcId);
254 /* Get a copy of the handle for our process, closing the source handle */
255 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
256 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
257 /* Close local copy */
258 return CloseHandle(hClose);
261 /*************************************************************************
262 * @ [SHLWAPI.11]
264 * Copy a sharable memory handle from one process to another.
266 * PARAMS
267 * hShared [I] Shared memory handle to duplicate
268 * dwDstProcId [I] ID of the process wanting the duplicated handle
269 * dwSrcProcId [I] ID of the process owning hShared
270 * dwAccess [I] Desired DuplicateHandle() access
271 * dwOptions [I] Desired DuplicateHandle() options
273 * RETURNS
274 * Success: A handle suitable for use by the dwDstProcId process.
275 * Failure: A NULL handle.
278 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
279 DWORD dwAccess, DWORD dwOptions)
281 HANDLE hRet;
283 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
284 dwAccess, dwOptions);
285 return hRet;
288 /*************************************************************************
289 * @ [SHLWAPI.13]
291 * Create and register a clipboard enumerator for a web browser.
293 * PARAMS
294 * lpBC [I] Binding context
295 * lpUnknown [I] An object exposing the IWebBrowserApp interface
297 * RETURNS
298 * Success: S_OK.
299 * Failure: An HRESULT error code.
301 * NOTES
302 * The enumerator is stored as a property of the web browser. If it does not
303 * yet exist, it is created and set before being registered.
305 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
307 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
308 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
309 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
310 BSTR property;
311 IEnumFORMATETC* pIEnumFormatEtc = NULL;
312 VARIANTARG var;
313 HRESULT hr;
314 IWebBrowserApp* pBrowser;
316 TRACE("(%p, %p)\n", lpBC, lpUnknown);
318 hr = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (void**)&pBrowser);
319 if (FAILED(hr))
320 return hr;
322 V_VT(&var) = VT_EMPTY;
324 /* The property we get is the browsers clipboard enumerator */
325 property = SysAllocString(szProperty);
326 hr = IWebBrowserApp_GetProperty(pBrowser, property, &var);
327 SysFreeString(property);
328 if (FAILED(hr)) goto exit;
330 if (V_VT(&var) == VT_EMPTY)
332 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
333 char szKeyBuff[128], szValueBuff[128];
334 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
335 FORMATETC* formatList, *format;
336 HKEY hDocs;
338 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
340 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
341 "Version\\Internet Settings\\Accepted Documents", &hDocs))
343 hr = E_FAIL;
344 goto exit;
347 /* Get count of values in key */
348 while (!dwRet)
350 dwKeySize = sizeof(szKeyBuff);
351 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
352 dwCount++;
355 dwNumValues = dwCount;
357 /* Note: dwCount = number of items + 1; The extra item is the end node */
358 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
359 if (!formatList)
361 RegCloseKey(hDocs);
362 hr = E_OUTOFMEMORY;
363 goto exit;
366 if (dwNumValues > 1)
368 dwRet = 0;
369 dwCount = 0;
371 dwNumValues--;
373 /* Register clipboard formats for the values and populate format list */
374 while(!dwRet && dwCount < dwNumValues)
376 dwKeySize = sizeof(szKeyBuff);
377 dwValueSize = sizeof(szValueBuff);
378 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
379 (PBYTE)szValueBuff, &dwValueSize);
380 if (!dwRet)
382 HeapFree(GetProcessHeap(), 0, formatList);
383 RegCloseKey(hDocs);
384 hr = E_FAIL;
385 goto exit;
388 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
389 format->ptd = NULL;
390 format->dwAspect = 1;
391 format->lindex = 4;
392 format->tymed = -1;
394 format++;
395 dwCount++;
399 RegCloseKey(hDocs);
401 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
402 format->cfFormat = 0;
403 format->ptd = NULL;
404 format->dwAspect = 1;
405 format->lindex = 4;
406 format->tymed = -1;
408 /* Create a clipboard enumerator */
409 hr = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
410 HeapFree(GetProcessHeap(), 0, formatList);
411 if (FAILED(hr)) goto exit;
413 /* Set our enumerator as the browsers property */
414 V_VT(&var) = VT_UNKNOWN;
415 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
417 property = SysAllocString(szProperty);
418 hr = IWebBrowserApp_PutProperty(pBrowser, property, var);
419 SysFreeString(property);
420 if (FAILED(hr))
422 IEnumFORMATETC_Release(pIEnumFormatEtc);
423 goto exit;
427 if (V_VT(&var) == VT_UNKNOWN)
429 /* Our variant is holding the clipboard enumerator */
430 IUnknown* pIUnknown = V_UNKNOWN(&var);
431 IEnumFORMATETC* pClone = NULL;
433 TRACE("Retrieved IEnumFORMATETC property\n");
435 /* Get an IEnumFormatEtc interface from the variants value */
436 pIEnumFormatEtc = NULL;
437 hr = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC, (void**)&pIEnumFormatEtc);
438 if (hr == S_OK && pIEnumFormatEtc)
440 /* Clone and register the enumerator */
441 hr = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
442 if (hr == S_OK && pClone)
444 RegisterFormatEnumerator(lpBC, pClone, 0);
446 IEnumFORMATETC_Release(pClone);
449 IUnknown_Release(pIUnknown);
451 IUnknown_Release(V_UNKNOWN(&var));
454 exit:
455 IWebBrowserApp_Release(pBrowser);
456 return hr;
459 /*************************************************************************
460 * @ [SHLWAPI.15]
462 * Get Explorers "AcceptLanguage" setting.
464 * PARAMS
465 * langbuf [O] Destination for language string
466 * buflen [I] Length of langbuf in characters
467 * [0] Success: used length of langbuf
469 * RETURNS
470 * Success: S_OK. langbuf is set to the language string found.
471 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
472 * does not contain the setting.
473 * HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), If the buffer is not big enough
475 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
477 static const WCHAR szkeyW[] = {
478 'S','o','f','t','w','a','r','e','\\',
479 'M','i','c','r','o','s','o','f','t','\\',
480 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
481 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
482 static const WCHAR valueW[] = {
483 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
484 DWORD mystrlen, mytype;
485 DWORD len;
486 HKEY mykey;
487 LCID mylcid;
488 WCHAR *mystr;
489 LONG lres;
491 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
493 if(!langbuf || !buflen || !*buflen)
494 return E_FAIL;
496 mystrlen = (*buflen > 20) ? *buflen : 20 ;
497 len = mystrlen * sizeof(WCHAR);
498 mystr = HeapAlloc(GetProcessHeap(), 0, len);
499 mystr[0] = 0;
500 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
501 lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
502 RegCloseKey(mykey);
503 len = lstrlenW(mystr);
505 if (!lres && (*buflen > len)) {
506 lstrcpyW(langbuf, mystr);
507 *buflen = len;
508 HeapFree(GetProcessHeap(), 0, mystr);
509 return S_OK;
512 /* Did not find a value in the registry or the user buffer is too small */
513 mylcid = GetUserDefaultLCID();
514 LcidToRfc1766W(mylcid, mystr, mystrlen);
515 len = lstrlenW(mystr);
517 memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
518 HeapFree(GetProcessHeap(), 0, mystr);
520 if (*buflen > len) {
521 *buflen = len;
522 return S_OK;
525 *buflen = 0;
526 return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
529 /*************************************************************************
530 * @ [SHLWAPI.14]
532 * Ascii version of GetAcceptLanguagesW.
534 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
536 WCHAR *langbufW;
537 DWORD buflenW, convlen;
538 HRESULT retval;
540 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
542 if(!langbuf || !buflen || !*buflen) return E_FAIL;
544 buflenW = *buflen;
545 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
546 retval = GetAcceptLanguagesW(langbufW, &buflenW);
548 if (retval == S_OK)
550 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
551 convlen--; /* do not count the terminating 0 */
553 else /* copy partial string anyway */
555 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
556 if (convlen < *buflen)
558 langbuf[convlen] = 0;
559 convlen--; /* do not count the terminating 0 */
561 else
563 convlen = *buflen;
566 *buflen = buflenW ? convlen : 0;
568 HeapFree(GetProcessHeap(), 0, langbufW);
569 return retval;
572 /*************************************************************************
573 * @ [SHLWAPI.23]
575 * Convert a GUID to a string.
577 * PARAMS
578 * guid [I] GUID to convert
579 * lpszDest [O] Destination for string
580 * cchMax [I] Length of output buffer
582 * RETURNS
583 * The length of the string created.
585 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
587 char xguid[40];
588 INT iLen;
590 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
592 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
593 guid->Data1, guid->Data2, guid->Data3,
594 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
595 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
597 iLen = strlen(xguid) + 1;
599 if (iLen > cchMax)
600 return 0;
601 memcpy(lpszDest, xguid, iLen);
602 return iLen;
605 /*************************************************************************
606 * @ [SHLWAPI.24]
608 * Convert a GUID to a string.
610 * PARAMS
611 * guid [I] GUID to convert
612 * str [O] Destination for string
613 * cmax [I] Length of output buffer
615 * RETURNS
616 * The length of the string created.
618 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
620 WCHAR xguid[40];
621 INT iLen;
622 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
623 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
624 'X','%','0','2','X','%','0','2','X','}',0};
626 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
628 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
629 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
630 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
632 iLen = strlenW(xguid) + 1;
634 if (iLen > cchMax)
635 return 0;
636 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
637 return iLen;
640 /*************************************************************************
641 * @ [SHLWAPI.30]
643 * Determine if a Unicode character is a blank.
645 * PARAMS
646 * wc [I] Character to check.
648 * RETURNS
649 * TRUE, if wc is a blank,
650 * FALSE otherwise.
653 BOOL WINAPI IsCharBlankW(WCHAR wc)
655 WORD CharType;
657 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
660 /*************************************************************************
661 * @ [SHLWAPI.31]
663 * Determine if a Unicode character is punctuation.
665 * PARAMS
666 * wc [I] Character to check.
668 * RETURNS
669 * TRUE, if wc is punctuation,
670 * FALSE otherwise.
672 BOOL WINAPI IsCharPunctW(WCHAR wc)
674 WORD CharType;
676 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
679 /*************************************************************************
680 * @ [SHLWAPI.32]
682 * Determine if a Unicode character is a control character.
684 * PARAMS
685 * wc [I] Character to check.
687 * RETURNS
688 * TRUE, if wc is a control character,
689 * FALSE otherwise.
691 BOOL WINAPI IsCharCntrlW(WCHAR wc)
693 WORD CharType;
695 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
698 /*************************************************************************
699 * @ [SHLWAPI.33]
701 * Determine if a Unicode character is a digit.
703 * PARAMS
704 * wc [I] Character to check.
706 * RETURNS
707 * TRUE, if wc is a digit,
708 * FALSE otherwise.
710 BOOL WINAPI IsCharDigitW(WCHAR wc)
712 WORD CharType;
714 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
717 /*************************************************************************
718 * @ [SHLWAPI.34]
720 * Determine if a Unicode character is a hex digit.
722 * PARAMS
723 * wc [I] Character to check.
725 * RETURNS
726 * TRUE, if wc is a hex digit,
727 * FALSE otherwise.
729 BOOL WINAPI IsCharXDigitW(WCHAR wc)
731 WORD CharType;
733 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
736 /*************************************************************************
737 * @ [SHLWAPI.35]
740 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type)
742 return GetStringTypeW(CT_CTYPE3, src, count, type);
745 /*************************************************************************
746 * @ [SHLWAPI.151]
748 * Compare two Ascii strings up to a given length.
750 * PARAMS
751 * lpszSrc [I] Source string
752 * lpszCmp [I] String to compare to lpszSrc
753 * len [I] Maximum length
755 * RETURNS
756 * A number greater than, less than or equal to 0 depending on whether
757 * lpszSrc is greater than, less than or equal to lpszCmp.
759 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
761 return StrCmpNA(lpszSrc, lpszCmp, len);
764 /*************************************************************************
765 * @ [SHLWAPI.152]
767 * Unicode version of StrCmpNCA.
769 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
771 return StrCmpNW(lpszSrc, lpszCmp, len);
774 /*************************************************************************
775 * @ [SHLWAPI.153]
777 * Compare two Ascii strings up to a given length, ignoring case.
779 * PARAMS
780 * lpszSrc [I] Source string
781 * lpszCmp [I] String to compare to lpszSrc
782 * len [I] Maximum length
784 * RETURNS
785 * A number greater than, less than or equal to 0 depending on whether
786 * lpszSrc is greater than, less than or equal to lpszCmp.
788 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
790 return StrCmpNIA(lpszSrc, lpszCmp, len);
793 /*************************************************************************
794 * @ [SHLWAPI.154]
796 * Unicode version of StrCmpNICA.
798 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
800 return StrCmpNIW(lpszSrc, lpszCmp, len);
803 /*************************************************************************
804 * @ [SHLWAPI.155]
806 * Compare two Ascii strings.
808 * PARAMS
809 * lpszSrc [I] Source string
810 * lpszCmp [I] String to compare to lpszSrc
812 * RETURNS
813 * A number greater than, less than or equal to 0 depending on whether
814 * lpszSrc is greater than, less than or equal to lpszCmp.
816 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
818 return lstrcmpA(lpszSrc, lpszCmp);
821 /*************************************************************************
822 * @ [SHLWAPI.156]
824 * Unicode version of StrCmpCA.
826 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
828 return lstrcmpW(lpszSrc, lpszCmp);
831 /*************************************************************************
832 * @ [SHLWAPI.157]
834 * Compare two Ascii strings, ignoring case.
836 * PARAMS
837 * lpszSrc [I] Source string
838 * lpszCmp [I] String to compare to lpszSrc
840 * RETURNS
841 * A number greater than, less than or equal to 0 depending on whether
842 * lpszSrc is greater than, less than or equal to lpszCmp.
844 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
846 return lstrcmpiA(lpszSrc, lpszCmp);
849 /*************************************************************************
850 * @ [SHLWAPI.158]
852 * Unicode version of StrCmpICA.
854 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
856 return lstrcmpiW(lpszSrc, lpszCmp);
859 /*************************************************************************
860 * @ [SHLWAPI.160]
862 * Get an identification string for the OS and explorer.
864 * PARAMS
865 * lpszDest [O] Destination for Id string
866 * dwDestLen [I] Length of lpszDest
868 * RETURNS
869 * TRUE, If the string was created successfully
870 * FALSE, Otherwise
872 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
874 WCHAR buff[2084];
876 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
878 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
880 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
881 return TRUE;
883 return FALSE;
886 /*************************************************************************
887 * @ [SHLWAPI.161]
889 * Unicode version of SHAboutInfoA.
891 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
893 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
894 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
895 ' ','E','x','p','l','o','r','e','r','\0' };
896 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
897 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
898 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
899 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
900 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
901 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
902 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
903 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
904 ' ','E','x','p','l','o','r','e','r','\\',
905 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
906 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
907 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
908 'V','e','r','s','i','o','n','\0' };
909 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
910 'O','w','n','e','r','\0' };
911 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
912 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
913 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
914 static const WCHAR szUpdate[] = { 'I','E','A','K',
915 'U','p','d','a','t','e','U','r','l','\0' };
916 static const WCHAR szHelp[] = { 'I','E','A','K',
917 'H','e','l','p','S','t','r','i','n','g','\0' };
918 WCHAR buff[2084];
919 HKEY hReg;
920 DWORD dwType, dwLen;
922 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
924 if (!lpszDest)
925 return FALSE;
927 *lpszDest = '\0';
929 /* Try the NT key first, followed by 95/98 key */
930 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
931 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
932 return FALSE;
934 /* OS Version */
935 buff[0] = '\0';
936 dwLen = 30;
937 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
939 DWORD dwStrLen = strlenW(buff);
940 dwLen = 30 - dwStrLen;
941 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
942 szCustomized, &dwType, buff+dwStrLen, &dwLen);
944 StrCatBuffW(lpszDest, buff, dwDestLen);
946 /* ~Registered Owner */
947 buff[0] = '~';
948 dwLen = 256;
949 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
950 buff[1] = '\0';
951 StrCatBuffW(lpszDest, buff, dwDestLen);
953 /* ~Registered Organization */
954 dwLen = 256;
955 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
956 buff[1] = '\0';
957 StrCatBuffW(lpszDest, buff, dwDestLen);
959 /* FIXME: Not sure where this number comes from */
960 buff[0] = '~';
961 buff[1] = '0';
962 buff[2] = '\0';
963 StrCatBuffW(lpszDest, buff, dwDestLen);
965 /* ~Product Id */
966 dwLen = 256;
967 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
968 buff[1] = '\0';
969 StrCatBuffW(lpszDest, buff, dwDestLen);
971 /* ~IE Update Url */
972 dwLen = 2048;
973 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
974 buff[1] = '\0';
975 StrCatBuffW(lpszDest, buff, dwDestLen);
977 /* ~IE Help String */
978 dwLen = 256;
979 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
980 buff[1] = '\0';
981 StrCatBuffW(lpszDest, buff, dwDestLen);
983 RegCloseKey(hReg);
984 return TRUE;
987 /*************************************************************************
988 * @ [SHLWAPI.163]
990 * Call IOleCommandTarget_QueryStatus() on an object.
992 * PARAMS
993 * lpUnknown [I] Object supporting the IOleCommandTarget interface
994 * pguidCmdGroup [I] GUID for the command group
995 * cCmds [I]
996 * prgCmds [O] Commands
997 * pCmdText [O] Command text
999 * RETURNS
1000 * Success: S_OK.
1001 * Failure: E_FAIL, if lpUnknown is NULL.
1002 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1003 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1005 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1006 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1008 HRESULT hRet = E_FAIL;
1010 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1012 if (lpUnknown)
1014 IOleCommandTarget* lpOle;
1016 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1017 (void**)&lpOle);
1019 if (SUCCEEDED(hRet) && lpOle)
1021 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1022 prgCmds, pCmdText);
1023 IOleCommandTarget_Release(lpOle);
1026 return hRet;
1029 /*************************************************************************
1030 * @ [SHLWAPI.164]
1032 * Call IOleCommandTarget_Exec() on an object.
1034 * PARAMS
1035 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1036 * pguidCmdGroup [I] GUID for the command group
1038 * RETURNS
1039 * Success: S_OK.
1040 * Failure: E_FAIL, if lpUnknown is NULL.
1041 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1042 * Otherwise, an error code from IOleCommandTarget_Exec().
1044 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1045 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1046 VARIANT* pvaOut)
1048 HRESULT hRet = E_FAIL;
1050 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1051 nCmdexecopt, pvaIn, pvaOut);
1053 if (lpUnknown)
1055 IOleCommandTarget* lpOle;
1057 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1058 (void**)&lpOle);
1059 if (SUCCEEDED(hRet) && lpOle)
1061 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1062 nCmdexecopt, pvaIn, pvaOut);
1063 IOleCommandTarget_Release(lpOle);
1066 return hRet;
1069 /*************************************************************************
1070 * @ [SHLWAPI.165]
1072 * Retrieve, modify, and re-set a value from a window.
1074 * PARAMS
1075 * hWnd [I] Window to get value from
1076 * offset [I] Offset of value
1077 * mask [I] Mask for flags
1078 * flags [I] Bits to set in window value
1080 * RETURNS
1081 * The new value as it was set, or 0 if any parameter is invalid.
1083 * NOTES
1084 * Only bits specified in mask are affected - set if present in flags and
1085 * reset otherwise.
1087 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT mask, UINT flags)
1089 LONG ret = GetWindowLongW(hwnd, offset);
1090 LONG new_flags = (flags & mask) | (ret & ~mask);
1092 TRACE("%p %d %x %x\n", hwnd, offset, mask, flags);
1094 if (new_flags != ret)
1095 ret = SetWindowLongW(hwnd, offset, new_flags);
1096 return ret;
1099 /*************************************************************************
1100 * @ [SHLWAPI.167]
1102 * Change a window's parent.
1104 * PARAMS
1105 * hWnd [I] Window to change parent of
1106 * hWndParent [I] New parent window
1108 * RETURNS
1109 * The old parent of hWnd.
1111 * NOTES
1112 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1113 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1115 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1117 TRACE("%p, %p\n", hWnd, hWndParent);
1119 if(GetParent(hWnd) == hWndParent)
1120 return NULL;
1122 if(hWndParent)
1123 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD | WS_POPUP, WS_CHILD);
1124 else
1125 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD | WS_POPUP, WS_POPUP);
1127 return hWndParent ? SetParent(hWnd, hWndParent) : NULL;
1130 /*************************************************************************
1131 * @ [SHLWAPI.168]
1133 * Locate and advise a connection point in an IConnectionPointContainer object.
1135 * PARAMS
1136 * lpUnkSink [I] Sink for the connection point advise call
1137 * riid [I] REFIID of connection point to advise
1138 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1139 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1140 * lpCookie [O] Pointer to connection point cookie
1141 * lppCP [O] Destination for the IConnectionPoint found
1143 * RETURNS
1144 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1145 * that was advised. The caller is responsible for releasing it.
1146 * Failure: E_FAIL, if any arguments are invalid.
1147 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1148 * Or an HRESULT error code if any call fails.
1150 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL fConnect,
1151 IUnknown* lpUnknown, LPDWORD lpCookie,
1152 IConnectionPoint **lppCP)
1154 HRESULT hRet;
1155 IConnectionPointContainer* lpContainer;
1156 IConnectionPoint *lpCP;
1158 if(!lpUnknown || (fConnect && !lpUnkSink))
1159 return E_FAIL;
1161 if(lppCP)
1162 *lppCP = NULL;
1164 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1165 (void**)&lpContainer);
1166 if (SUCCEEDED(hRet))
1168 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1170 if (SUCCEEDED(hRet))
1172 if(!fConnect)
1173 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1174 else
1175 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1177 if (FAILED(hRet))
1178 *lpCookie = 0;
1180 if (lppCP && SUCCEEDED(hRet))
1181 *lppCP = lpCP; /* Caller keeps the interface */
1182 else
1183 IConnectionPoint_Release(lpCP); /* Release it */
1186 IConnectionPointContainer_Release(lpContainer);
1188 return hRet;
1191 /*************************************************************************
1192 * @ [SHLWAPI.169]
1194 * Release an interface and zero a supplied pointer.
1196 * PARAMS
1197 * lpUnknown [I] Object to release
1199 * RETURNS
1200 * Nothing.
1202 void WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1204 TRACE("(%p)\n", lpUnknown);
1206 if(!lpUnknown || !*lpUnknown) return;
1208 TRACE("doing Release\n");
1210 IUnknown_Release(*lpUnknown);
1211 *lpUnknown = NULL;
1214 /*************************************************************************
1215 * @ [SHLWAPI.170]
1217 * Skip '//' if present in a string.
1219 * PARAMS
1220 * lpszSrc [I] String to check for '//'
1222 * RETURNS
1223 * Success: The next character after the '//' or the string if not present
1224 * Failure: NULL, if lpszStr is NULL.
1226 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1228 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1229 lpszSrc += 2;
1230 return lpszSrc;
1233 /*************************************************************************
1234 * @ [SHLWAPI.171]
1236 * Check if two interfaces come from the same object.
1238 * PARAMS
1239 * lpInt1 [I] Interface to check against lpInt2.
1240 * lpInt2 [I] Interface to check against lpInt1.
1242 * RETURNS
1243 * TRUE, If the interfaces come from the same object.
1244 * FALSE Otherwise.
1246 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1248 IUnknown *lpUnknown1, *lpUnknown2;
1249 BOOL ret;
1251 TRACE("(%p %p)\n", lpInt1, lpInt2);
1253 if (!lpInt1 || !lpInt2)
1254 return FALSE;
1256 if (lpInt1 == lpInt2)
1257 return TRUE;
1259 if (IUnknown_QueryInterface(lpInt1, &IID_IUnknown, (void**)&lpUnknown1) != S_OK)
1260 return FALSE;
1262 if (IUnknown_QueryInterface(lpInt2, &IID_IUnknown, (void**)&lpUnknown2) != S_OK)
1264 IUnknown_Release(lpUnknown1);
1265 return FALSE;
1268 ret = lpUnknown1 == lpUnknown2;
1270 IUnknown_Release(lpUnknown1);
1271 IUnknown_Release(lpUnknown2);
1273 return ret;
1276 /*************************************************************************
1277 * @ [SHLWAPI.172]
1279 * Get the window handle of an object.
1281 * PARAMS
1282 * lpUnknown [I] Object to get the window handle of
1283 * lphWnd [O] Destination for window handle
1285 * RETURNS
1286 * Success: S_OK. lphWnd contains the objects window handle.
1287 * Failure: An HRESULT error code.
1289 * NOTES
1290 * lpUnknown is expected to support one of the following interfaces:
1291 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1293 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1295 IUnknown *lpOle;
1296 HRESULT hRet = E_FAIL;
1298 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1300 if (!lpUnknown)
1301 return hRet;
1303 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1305 if (FAILED(hRet))
1307 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1309 if (FAILED(hRet))
1311 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1312 (void**)&lpOle);
1316 if (SUCCEEDED(hRet))
1318 /* Laziness here - Since GetWindow() is the first method for the above 3
1319 * interfaces, we use the same call for them all.
1321 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1322 IUnknown_Release(lpOle);
1323 if (lphWnd)
1324 TRACE("Returning HWND=%p\n", *lphWnd);
1327 return hRet;
1330 /*************************************************************************
1331 * @ [SHLWAPI.173]
1333 * Call a SetOwner method of IShellService from specified object.
1335 * PARAMS
1336 * iface [I] Object that supports IShellService
1337 * pUnk [I] Argument for the SetOwner call
1339 * RETURNS
1340 * Corresponding return value from last call or E_FAIL for null input
1342 HRESULT WINAPI IUnknown_SetOwner(IUnknown *iface, IUnknown *pUnk)
1344 IShellService *service;
1345 HRESULT hr;
1347 TRACE("(%p, %p)\n", iface, pUnk);
1349 if (!iface) return E_FAIL;
1351 hr = IUnknown_QueryInterface(iface, &IID_IShellService, (void**)&service);
1352 if (hr == S_OK)
1354 hr = IShellService_SetOwner(service, pUnk);
1355 IShellService_Release(service);
1358 return hr;
1361 /*************************************************************************
1362 * @ [SHLWAPI.174]
1364 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1365 * an object.
1368 HRESULT WINAPI IUnknown_SetSite(
1369 IUnknown *obj, /* [in] OLE object */
1370 IUnknown *site) /* [in] Site interface */
1372 HRESULT hr;
1373 IObjectWithSite *iobjwithsite;
1374 IInternetSecurityManager *isecmgr;
1376 if (!obj) return E_FAIL;
1378 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1379 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1380 if (SUCCEEDED(hr))
1382 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1383 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1384 IObjectWithSite_Release(iobjwithsite);
1386 else
1388 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1389 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1390 if (FAILED(hr)) return hr;
1392 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1393 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1394 IInternetSecurityManager_Release(isecmgr);
1396 return hr;
1399 /*************************************************************************
1400 * @ [SHLWAPI.175]
1402 * Call IPersist_GetClassID() on an object.
1404 * PARAMS
1405 * lpUnknown [I] Object supporting the IPersist interface
1406 * lpClassId [O] Destination for Class Id
1408 * RETURNS
1409 * Success: S_OK. lpClassId contains the Class Id requested.
1410 * Failure: E_FAIL, If lpUnknown is NULL,
1411 * E_NOINTERFACE If lpUnknown does not support IPersist,
1412 * Or an HRESULT error code.
1414 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1416 IPersist* lpPersist;
1417 HRESULT hRet = E_FAIL;
1419 TRACE("(%p,%s)\n", lpUnknown, debugstr_guid(lpClassId));
1421 if (lpUnknown)
1423 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1424 if (SUCCEEDED(hRet))
1426 IPersist_GetClassID(lpPersist, lpClassId);
1427 IPersist_Release(lpPersist);
1430 return hRet;
1433 /*************************************************************************
1434 * @ [SHLWAPI.176]
1436 * Retrieve a Service Interface from an object.
1438 * PARAMS
1439 * lpUnknown [I] Object to get an IServiceProvider interface from
1440 * sid [I] Service ID for IServiceProvider_QueryService() call
1441 * riid [I] Function requested for QueryService call
1442 * lppOut [O] Destination for the service interface pointer
1444 * RETURNS
1445 * Success: S_OK. lppOut contains an object providing the requested service
1446 * Failure: An HRESULT error code
1448 * NOTES
1449 * lpUnknown is expected to support the IServiceProvider interface.
1451 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1452 LPVOID *lppOut)
1454 IServiceProvider* pService = NULL;
1455 HRESULT hRet;
1457 if (!lppOut)
1458 return E_FAIL;
1460 *lppOut = NULL;
1462 if (!lpUnknown)
1463 return E_FAIL;
1465 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1466 (LPVOID*)&pService);
1468 if (hRet == S_OK && pService)
1470 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1472 /* Get a Service interface from the object */
1473 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1475 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1477 IServiceProvider_Release(pService);
1479 return hRet;
1482 /*************************************************************************
1483 * @ [SHLWAPI.484]
1485 * Calls IOleCommandTarget::Exec() for specified service object.
1487 * PARAMS
1488 * lpUnknown [I] Object to get an IServiceProvider interface from
1489 * service [I] Service ID for IServiceProvider_QueryService() call
1490 * group [I] Group ID for IOleCommandTarget::Exec() call
1491 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1492 * cmdOpt [I] Options flags for command
1493 * pIn [I] Input arguments for command
1494 * pOut [O] Output arguments for command
1496 * RETURNS
1497 * Success: S_OK. lppOut contains an object providing the requested service
1498 * Failure: An HRESULT error code
1500 * NOTES
1501 * lpUnknown is expected to support the IServiceProvider interface.
1503 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *lpUnknown, REFIID service,
1504 const GUID *group, DWORD cmdId, DWORD cmdOpt, VARIANT *pIn, VARIANT *pOut)
1506 IOleCommandTarget *target;
1507 HRESULT hr;
1509 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown, debugstr_guid(service),
1510 debugstr_guid(group), cmdId, cmdOpt, pIn, pOut);
1512 hr = IUnknown_QueryService(lpUnknown, service, &IID_IOleCommandTarget, (void**)&target);
1513 if (hr == S_OK)
1515 hr = IOleCommandTarget_Exec(target, group, cmdId, cmdOpt, pIn, pOut);
1516 IOleCommandTarget_Release(target);
1519 TRACE("<-- hr=0x%08x\n", hr);
1521 return hr;
1524 /*************************************************************************
1525 * @ [SHLWAPI.514]
1527 * Calls IProfferService methods to proffer/revoke specified service.
1529 * PARAMS
1530 * lpUnknown [I] Object to get an IServiceProvider interface from
1531 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1532 * pService [I] Service to proffer. If NULL ::Revoke is called
1533 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1535 * RETURNS
1536 * Success: S_OK. IProffer method returns S_OK
1537 * Failure: An HRESULT error code
1539 * NOTES
1540 * lpUnknown is expected to support the IServiceProvider interface.
1542 HRESULT WINAPI IUnknown_ProfferService(IUnknown *lpUnknown, REFGUID service, IServiceProvider *pService, DWORD *pCookie)
1544 IProfferService *proffer;
1545 HRESULT hr;
1547 TRACE("%p %s %p %p\n", lpUnknown, debugstr_guid(service), pService, pCookie);
1549 hr = IUnknown_QueryService(lpUnknown, &IID_IProfferService, &IID_IProfferService, (void**)&proffer);
1550 if (hr == S_OK)
1552 if (pService)
1553 hr = IProfferService_ProfferService(proffer, service, pService, pCookie);
1554 else
1556 hr = IProfferService_RevokeService(proffer, *pCookie);
1557 *pCookie = 0;
1560 IProfferService_Release(proffer);
1563 return hr;
1566 /*************************************************************************
1567 * @ [SHLWAPI.479]
1569 * Call an object's UIActivateIO method.
1571 * PARAMS
1572 * unknown [I] Object to call the UIActivateIO method on
1573 * activate [I] Parameter for UIActivateIO call
1574 * msg [I] Parameter for UIActivateIO call
1576 * RETURNS
1577 * Success: Value of UI_ActivateIO call
1578 * Failure: An HRESULT error code
1580 * NOTES
1581 * unknown is expected to support the IInputObject interface.
1583 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg)
1585 IInputObject* object = NULL;
1586 HRESULT ret;
1588 if (!unknown)
1589 return E_FAIL;
1591 /* Get an IInputObject interface from the object */
1592 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
1594 if (ret == S_OK)
1596 ret = IInputObject_UIActivateIO(object, activate, msg);
1597 IInputObject_Release(object);
1600 return ret;
1603 /*************************************************************************
1604 * @ [SHLWAPI.177]
1606 * Loads a popup menu.
1608 * PARAMS
1609 * hInst [I] Instance handle
1610 * szName [I] Menu name
1612 * RETURNS
1613 * Success: TRUE.
1614 * Failure: FALSE.
1616 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1618 HMENU hMenu;
1620 TRACE("%p %s\n", hInst, debugstr_w(szName));
1622 if ((hMenu = LoadMenuW(hInst, szName)))
1624 if (GetSubMenu(hMenu, 0))
1625 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1627 DestroyMenu(hMenu);
1628 return TRUE;
1630 return FALSE;
1633 typedef struct _enumWndData
1635 UINT uiMsgId;
1636 WPARAM wParam;
1637 LPARAM lParam;
1638 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1639 } enumWndData;
1641 /* Callback for SHLWAPI_178 */
1642 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1644 enumWndData *data = (enumWndData *)lParam;
1646 TRACE("(%p,%p)\n", hWnd, data);
1647 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1648 return TRUE;
1651 /*************************************************************************
1652 * @ [SHLWAPI.178]
1654 * Send or post a message to every child of a window.
1656 * PARAMS
1657 * hWnd [I] Window whose children will get the messages
1658 * uiMsgId [I] Message Id
1659 * wParam [I] WPARAM of message
1660 * lParam [I] LPARAM of message
1661 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1663 * RETURNS
1664 * Nothing.
1666 * NOTES
1667 * The appropriate ASCII or Unicode function is called for the window.
1669 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1671 enumWndData data;
1673 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1675 if(hWnd)
1677 data.uiMsgId = uiMsgId;
1678 data.wParam = wParam;
1679 data.lParam = lParam;
1681 if (bSend)
1682 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1683 else
1684 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1686 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1690 /*************************************************************************
1691 * @ [SHLWAPI.180]
1693 * Remove all sub-menus from a menu.
1695 * PARAMS
1696 * hMenu [I] Menu to remove sub-menus from
1698 * RETURNS
1699 * Success: 0. All sub-menus under hMenu are removed
1700 * Failure: -1, if any parameter is invalid
1702 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1704 int iItemCount = GetMenuItemCount(hMenu) - 1;
1706 TRACE("%p\n", hMenu);
1708 while (iItemCount >= 0)
1710 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1711 if (hSubMenu)
1712 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1713 iItemCount--;
1715 return iItemCount;
1718 /*************************************************************************
1719 * @ [SHLWAPI.181]
1721 * Enable or disable a menu item.
1723 * PARAMS
1724 * hMenu [I] Menu holding menu item
1725 * uID [I] ID of menu item to enable/disable
1726 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1728 * RETURNS
1729 * The return code from EnableMenuItem.
1731 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1733 TRACE("%p, %u, %d\n", hMenu, wItemID, bEnable);
1734 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1737 /*************************************************************************
1738 * @ [SHLWAPI.182]
1740 * Check or uncheck a menu item.
1742 * PARAMS
1743 * hMenu [I] Menu holding menu item
1744 * uID [I] ID of menu item to check/uncheck
1745 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1747 * RETURNS
1748 * The return code from CheckMenuItem.
1750 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1752 TRACE("%p, %u, %d\n", hMenu, uID, bCheck);
1753 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1756 /*************************************************************************
1757 * @ [SHLWAPI.183]
1759 * Register a window class if it isn't already.
1761 * PARAMS
1762 * lpWndClass [I] Window class to register
1764 * RETURNS
1765 * The result of the RegisterClassA call.
1767 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1769 WNDCLASSA wca;
1770 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1771 return TRUE;
1772 return (DWORD)RegisterClassA(wndclass);
1775 /*************************************************************************
1776 * @ [SHLWAPI.186]
1778 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1779 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1781 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1782 POINTL pt = { 0, 0 };
1784 TRACE("%p %p 0x%08x %p %p\n", pDrop, pDataObj, grfKeyState, lpPt, pdwEffect);
1786 if (!lpPt)
1787 lpPt = &pt;
1789 if (!pdwEffect)
1790 pdwEffect = &dwEffect;
1792 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1794 if (*pdwEffect != DROPEFFECT_NONE)
1795 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1797 IDropTarget_DragLeave(pDrop);
1798 return TRUE;
1801 /*************************************************************************
1802 * @ [SHLWAPI.187]
1804 * Call IPersistPropertyBag_Load() on an object.
1806 * PARAMS
1807 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1808 * lpPropBag [O] Destination for loaded IPropertyBag
1810 * RETURNS
1811 * Success: S_OK.
1812 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1814 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1816 IPersistPropertyBag* lpPPBag;
1817 HRESULT hRet = E_FAIL;
1819 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1821 if (lpUnknown)
1823 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1824 (void**)&lpPPBag);
1825 if (SUCCEEDED(hRet) && lpPPBag)
1827 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1828 IPersistPropertyBag_Release(lpPPBag);
1831 return hRet;
1834 /*************************************************************************
1835 * @ [SHLWAPI.188]
1837 * Call IOleControlSite_TranslateAccelerator() on an object.
1839 * PARAMS
1840 * lpUnknown [I] Object supporting the IOleControlSite interface.
1841 * lpMsg [I] Key message to be processed.
1842 * dwModifiers [I] Flags containing the state of the modifier keys.
1844 * RETURNS
1845 * Success: S_OK.
1846 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1848 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1850 IOleControlSite* lpCSite = NULL;
1851 HRESULT hRet = E_INVALIDARG;
1853 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1854 if (lpUnknown)
1856 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1857 (void**)&lpCSite);
1858 if (SUCCEEDED(hRet) && lpCSite)
1860 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1861 IOleControlSite_Release(lpCSite);
1864 return hRet;
1868 /*************************************************************************
1869 * @ [SHLWAPI.189]
1871 * Call IOleControlSite_OnFocus() on an object.
1873 * PARAMS
1874 * lpUnknown [I] Object supporting the IOleControlSite interface.
1875 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1877 * RETURNS
1878 * Success: S_OK.
1879 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1881 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
1883 IOleControlSite* lpCSite = NULL;
1884 HRESULT hRet = E_FAIL;
1886 TRACE("(%p, %d)\n", lpUnknown, fGotFocus);
1887 if (lpUnknown)
1889 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1890 (void**)&lpCSite);
1891 if (SUCCEEDED(hRet) && lpCSite)
1893 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1894 IOleControlSite_Release(lpCSite);
1897 return hRet;
1900 /*************************************************************************
1901 * @ [SHLWAPI.190]
1903 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1904 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1906 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1907 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1908 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1909 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1910 HRESULT hRet = E_INVALIDARG;
1911 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1913 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1915 if (lpUnknown && lpArg4)
1917 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1918 (REFGUID)function_id, (void**)&lpUnkInner);
1920 if (SUCCEEDED(hRet) && lpUnkInner)
1922 /* FIXME: The type of service object requested is unknown, however
1923 * testing shows that its first method is called with 4 parameters.
1924 * Fake this by using IParseDisplayName_ParseDisplayName since the
1925 * signature and position in the vtable matches our unknown object type.
1927 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1928 lpArg1, lpArg2, lpArg3, lpArg4);
1929 IUnknown_Release(lpUnkInner);
1932 return hRet;
1935 /*************************************************************************
1936 * @ [SHLWAPI.192]
1938 * Get a sub-menu from a menu item.
1940 * PARAMS
1941 * hMenu [I] Menu to get sub-menu from
1942 * uID [I] ID of menu item containing sub-menu
1944 * RETURNS
1945 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1947 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1949 MENUITEMINFOW mi;
1951 TRACE("(%p,%u)\n", hMenu, uID);
1953 mi.cbSize = sizeof(mi);
1954 mi.fMask = MIIM_SUBMENU;
1956 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1957 return NULL;
1959 return mi.hSubMenu;
1962 /*************************************************************************
1963 * @ [SHLWAPI.193]
1965 * Get the color depth of the primary display.
1967 * PARAMS
1968 * None.
1970 * RETURNS
1971 * The color depth of the primary display.
1973 DWORD WINAPI SHGetCurColorRes(void)
1975 HDC hdc;
1976 DWORD ret;
1978 TRACE("()\n");
1980 hdc = GetDC(0);
1981 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1982 ReleaseDC(0, hdc);
1983 return ret;
1986 /*************************************************************************
1987 * @ [SHLWAPI.194]
1989 * Wait for a message to arrive, with a timeout.
1991 * PARAMS
1992 * hand [I] Handle to query
1993 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1995 * RETURNS
1996 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1997 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1998 * message is available.
2000 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
2002 DWORD dwEndTicks = GetTickCount() + dwTimeout;
2003 DWORD dwRet;
2005 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
2007 MSG msg;
2009 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
2011 if (dwTimeout != INFINITE)
2013 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
2014 return WAIT_TIMEOUT;
2018 return dwRet;
2021 /*************************************************************************
2022 * @ [SHLWAPI.195]
2024 * Determine if a shell folder can be expanded.
2026 * PARAMS
2027 * lpFolder [I] Parent folder containing the object to test.
2028 * pidl [I] Id of the object to test.
2030 * RETURNS
2031 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2032 * Failure: E_INVALIDARG, if any argument is invalid.
2034 * NOTES
2035 * If the object to be tested does not expose the IQueryInfo() interface it
2036 * will not be identified as an expandable folder.
2038 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
2040 HRESULT hRet = E_INVALIDARG;
2041 IQueryInfo *lpInfo;
2043 if (lpFolder && pidl)
2045 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
2046 NULL, (void**)&lpInfo);
2047 if (FAILED(hRet))
2048 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
2049 else
2051 DWORD dwFlags = 0;
2053 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2054 * currently used". Really? You wouldn't be holding out on me would you?
2056 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
2058 if (SUCCEEDED(hRet))
2060 /* 0x2 is an undocumented flag apparently indicating expandability */
2061 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
2064 IQueryInfo_Release(lpInfo);
2067 return hRet;
2070 /*************************************************************************
2071 * @ [SHLWAPI.197]
2073 * Blank out a region of text by drawing the background only.
2075 * PARAMS
2076 * hDC [I] Device context to draw in
2077 * pRect [I] Area to draw in
2078 * cRef [I] Color to draw in
2080 * RETURNS
2081 * Nothing.
2083 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2085 COLORREF cOldColor = SetBkColor(hDC, cRef);
2086 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2087 SetBkColor(hDC, cOldColor);
2088 return 0;
2091 /*************************************************************************
2092 * @ [SHLWAPI.198]
2094 * Return the value associated with a key in a map.
2096 * PARAMS
2097 * lpKeys [I] A list of keys of length iLen
2098 * lpValues [I] A list of values associated with lpKeys, of length iLen
2099 * iLen [I] Length of both lpKeys and lpValues
2100 * iKey [I] The key value to look up in lpKeys
2102 * RETURNS
2103 * The value in lpValues associated with iKey, or -1 if iKey is not
2104 * found in lpKeys.
2106 * NOTES
2107 * - If two elements in the map share the same key, this function returns
2108 * the value closest to the start of the map
2109 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2111 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2113 if (lpKeys && lpValues)
2115 int i = 0;
2117 while (i < iLen)
2119 if (lpKeys[i] == iKey)
2120 return lpValues[i]; /* Found */
2121 i++;
2124 return -1; /* Not found */
2128 /*************************************************************************
2129 * @ [SHLWAPI.199]
2131 * Copy an interface pointer
2133 * PARAMS
2134 * lppDest [O] Destination for copy
2135 * lpUnknown [I] Source for copy
2137 * RETURNS
2138 * Nothing.
2140 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2142 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2144 IUnknown_AtomicRelease(lppDest);
2146 if (lpUnknown)
2148 IUnknown_AddRef(lpUnknown);
2149 *lppDest = lpUnknown;
2153 /*************************************************************************
2154 * @ [SHLWAPI.200]
2157 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2158 REFGUID riidCmdGrp, ULONG cCmds,
2159 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2161 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2162 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2164 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2165 return DRAGDROP_E_NOTREGISTERED;
2168 /*************************************************************************
2169 * @ [SHLWAPI.201]
2172 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2173 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2174 VARIANT* pvaOut)
2176 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2177 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2178 return DRAGDROP_E_NOTREGISTERED;
2181 /*************************************************************************
2182 * @ [SHLWAPI.202]
2185 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2187 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2188 return DRAGDROP_E_NOTREGISTERED;
2191 /*************************************************************************
2192 * @ [SHLWAPI.204]
2194 * Determine if a window is not a child of another window.
2196 * PARAMS
2197 * hParent [I] Suspected parent window
2198 * hChild [I] Suspected child window
2200 * RETURNS
2201 * TRUE: If hChild is a child window of hParent
2202 * FALSE: If hChild is not a child window of hParent, or they are equal
2204 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2206 TRACE("(%p,%p)\n", hParent, hChild);
2208 if (!hParent || !hChild)
2209 return TRUE;
2210 else if(hParent == hChild)
2211 return FALSE;
2212 return !IsChild(hParent, hChild);
2215 /*************************************************************************
2216 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2219 typedef struct
2221 DWORD num_items; /* Number of elements inserted */
2222 void *mem; /* Ptr to array */
2223 DWORD blocks_alloced; /* Number of elements allocated */
2224 BYTE inc; /* Number of elements to grow by when we need to expand */
2225 BYTE block_size; /* Size in bytes of an element */
2226 BYTE flags; /* Flags */
2227 } FDSA_info;
2229 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2231 /*************************************************************************
2232 * @ [SHLWAPI.208]
2234 * Initialize an FDSA array.
2236 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2237 DWORD init_blocks)
2239 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2241 if(inc == 0)
2242 inc = 1;
2244 if(mem)
2245 memset(mem, 0, block_size * init_blocks);
2247 info->num_items = 0;
2248 info->inc = inc;
2249 info->mem = mem;
2250 info->blocks_alloced = init_blocks;
2251 info->block_size = block_size;
2252 info->flags = 0;
2254 return TRUE;
2257 /*************************************************************************
2258 * @ [SHLWAPI.209]
2260 * Destroy an FDSA array
2262 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2264 TRACE("(%p)\n", info);
2266 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2268 HeapFree(GetProcessHeap(), 0, info->mem);
2269 return FALSE;
2272 return TRUE;
2275 /*************************************************************************
2276 * @ [SHLWAPI.210]
2278 * Insert element into an FDSA array
2280 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
2282 TRACE("(%p 0x%08x %p)\n", info, where, block);
2283 if(where > info->num_items)
2284 where = info->num_items;
2286 if(info->num_items >= info->blocks_alloced)
2288 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2289 if(info->flags & 0x1)
2290 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2291 else
2293 void *old_mem = info->mem;
2294 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2295 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2297 info->blocks_alloced += info->inc;
2298 info->flags |= 0x1;
2301 if(where < info->num_items)
2303 memmove((char*)info->mem + (where + 1) * info->block_size,
2304 (char*)info->mem + where * info->block_size,
2305 (info->num_items - where) * info->block_size);
2307 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2309 info->num_items++;
2310 return where;
2313 /*************************************************************************
2314 * @ [SHLWAPI.211]
2316 * Delete an element from an FDSA array.
2318 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2320 TRACE("(%p 0x%08x)\n", info, where);
2322 if(where >= info->num_items)
2323 return FALSE;
2325 if(where < info->num_items - 1)
2327 memmove((char*)info->mem + where * info->block_size,
2328 (char*)info->mem + (where + 1) * info->block_size,
2329 (info->num_items - where - 1) * info->block_size);
2331 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2332 0, info->block_size);
2333 info->num_items--;
2334 return TRUE;
2337 /*************************************************************************
2338 * @ [SHLWAPI.219]
2340 * Call IUnknown_QueryInterface() on a table of objects.
2342 * RETURNS
2343 * Success: S_OK.
2344 * Failure: E_POINTER or E_NOINTERFACE.
2346 HRESULT WINAPI QISearch(
2347 void *base, /* [in] Table of interfaces */
2348 const QITAB *table, /* [in] Array of REFIIDs and indexes into the table */
2349 REFIID riid, /* [in] REFIID to get interface for */
2350 void **ppv) /* [out] Destination for interface pointer */
2352 HRESULT ret;
2353 IUnknown *a_vtbl;
2354 const QITAB *xmove;
2356 TRACE("(%p %p %s %p)\n", base, table, debugstr_guid(riid), ppv);
2357 if (ppv) {
2358 xmove = table;
2359 while (xmove->piid) {
2360 TRACE("trying (offset %d) %s\n", xmove->dwOffset, debugstr_guid(xmove->piid));
2361 if (IsEqualIID(riid, xmove->piid)) {
2362 a_vtbl = (IUnknown*)(xmove->dwOffset + (LPBYTE)base);
2363 TRACE("matched, returning (%p)\n", a_vtbl);
2364 *ppv = a_vtbl;
2365 IUnknown_AddRef(a_vtbl);
2366 return S_OK;
2368 xmove++;
2371 if (IsEqualIID(riid, &IID_IUnknown)) {
2372 a_vtbl = (IUnknown*)(table->dwOffset + (LPBYTE)base);
2373 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2374 *ppv = a_vtbl;
2375 IUnknown_AddRef(a_vtbl);
2376 return S_OK;
2378 *ppv = 0;
2379 ret = E_NOINTERFACE;
2380 } else
2381 ret = E_POINTER;
2383 TRACE("-- 0x%08x\n", ret);
2384 return ret;
2387 /*************************************************************************
2388 * @ [SHLWAPI.220]
2390 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2392 * PARAMS
2393 * hWnd [I] Parent Window to set the property
2394 * id [I] Index of child Window to set the Font
2396 * RETURNS
2397 * Success: S_OK
2400 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id)
2402 FIXME("(%p, %d) stub\n", hWnd, id);
2403 return S_OK;
2406 /*************************************************************************
2407 * @ [SHLWAPI.221]
2409 * Remove the "PropDlgFont" property from a window.
2411 * PARAMS
2412 * hWnd [I] Window to remove the property from
2414 * RETURNS
2415 * A handle to the removed property, or NULL if it did not exist.
2417 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2419 HANDLE hProp;
2421 TRACE("(%p)\n", hWnd);
2423 hProp = GetPropA(hWnd, "PropDlgFont");
2425 if(hProp)
2427 DeleteObject(hProp);
2428 hProp = RemovePropA(hWnd, "PropDlgFont");
2430 return hProp;
2433 /*************************************************************************
2434 * @ [SHLWAPI.236]
2436 * Load the in-process server of a given GUID.
2438 * PARAMS
2439 * refiid [I] GUID of the server to load.
2441 * RETURNS
2442 * Success: A handle to the loaded server dll.
2443 * Failure: A NULL handle.
2445 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2447 HKEY newkey;
2448 DWORD type, count;
2449 CHAR value[MAX_PATH], string[MAX_PATH];
2451 strcpy(string, "CLSID\\");
2452 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2453 strcat(string, "\\InProcServer32");
2455 count = MAX_PATH;
2456 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2457 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2458 RegCloseKey(newkey);
2459 return LoadLibraryExA(value, 0, 0);
2462 /*************************************************************************
2463 * @ [SHLWAPI.237]
2465 * Unicode version of SHLWAPI_183.
2467 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2469 WNDCLASSW WndClass;
2471 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2473 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2474 return TRUE;
2475 return RegisterClassW(lpWndClass);
2478 /*************************************************************************
2479 * @ [SHLWAPI.238]
2481 * Unregister a list of classes.
2483 * PARAMS
2484 * hInst [I] Application instance that registered the classes
2485 * lppClasses [I] List of class names
2486 * iCount [I] Number of names in lppClasses
2488 * RETURNS
2489 * Nothing.
2491 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2493 WNDCLASSA WndClass;
2495 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2497 while (iCount > 0)
2499 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2500 UnregisterClassA(*lppClasses, hInst);
2501 lppClasses++;
2502 iCount--;
2506 /*************************************************************************
2507 * @ [SHLWAPI.239]
2509 * Unicode version of SHUnregisterClassesA.
2511 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2513 WNDCLASSW WndClass;
2515 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2517 while (iCount > 0)
2519 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2520 UnregisterClassW(*lppClasses, hInst);
2521 lppClasses++;
2522 iCount--;
2526 /*************************************************************************
2527 * @ [SHLWAPI.240]
2529 * Call The correct (Ascii/Unicode) default window procedure for a window.
2531 * PARAMS
2532 * hWnd [I] Window to call the default procedure for
2533 * uMessage [I] Message ID
2534 * wParam [I] WPARAM of message
2535 * lParam [I] LPARAM of message
2537 * RETURNS
2538 * The result of calling DefWindowProcA() or DefWindowProcW().
2540 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2542 if (IsWindowUnicode(hWnd))
2543 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2544 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2547 /*************************************************************************
2548 * @ [SHLWAPI.256]
2550 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2552 HRESULT hRet = E_INVALIDARG;
2553 LPOBJECTWITHSITE lpSite = NULL;
2555 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2557 if (lpUnknown && iid && lppSite)
2559 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2560 (void**)&lpSite);
2561 if (SUCCEEDED(hRet) && lpSite)
2563 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2564 IObjectWithSite_Release(lpSite);
2567 return hRet;
2570 /*************************************************************************
2571 * @ [SHLWAPI.257]
2573 * Create a worker window using CreateWindowExA().
2575 * PARAMS
2576 * wndProc [I] Window procedure
2577 * hWndParent [I] Parent window
2578 * dwExStyle [I] Extra style flags
2579 * dwStyle [I] Style flags
2580 * hMenu [I] Window menu
2581 * wnd_extra [I] Window extra bytes value
2583 * RETURNS
2584 * Success: The window handle of the newly created window.
2585 * Failure: 0.
2587 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2588 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra)
2590 static const char szClass[] = "WorkerA";
2591 WNDCLASSA wc;
2592 HWND hWnd;
2594 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2595 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
2597 /* Create Window class */
2598 wc.style = 0;
2599 wc.lpfnWndProc = DefWindowProcA;
2600 wc.cbClsExtra = 0;
2601 wc.cbWndExtra = sizeof(LONG_PTR);
2602 wc.hInstance = shlwapi_hInstance;
2603 wc.hIcon = NULL;
2604 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2605 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2606 wc.lpszMenuName = NULL;
2607 wc.lpszClassName = szClass;
2609 SHRegisterClassA(&wc);
2611 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2612 hWndParent, hMenu, shlwapi_hInstance, 0);
2613 if (hWnd)
2615 SetWindowLongPtrW(hWnd, 0, wnd_extra);
2617 if (wndProc) SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2620 return hWnd;
2623 typedef struct tagPOLICYDATA
2625 DWORD policy; /* flags value passed to SHRestricted */
2626 LPCWSTR appstr; /* application str such as "Explorer" */
2627 LPCWSTR keystr; /* name of the actual registry key / policy */
2628 } POLICYDATA, *LPPOLICYDATA;
2630 #define SHELL_NO_POLICY 0xffffffff
2632 /* default shell policy registry key */
2633 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2634 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2635 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2636 '\\','P','o','l','i','c','i','e','s',0};
2638 /*************************************************************************
2639 * @ [SHLWAPI.271]
2641 * Retrieve a policy value from the registry.
2643 * PARAMS
2644 * lpSubKey [I] registry key name
2645 * lpSubName [I] subname of registry key
2646 * lpValue [I] value name of registry value
2648 * RETURNS
2649 * the value associated with the registry key or 0 if not found
2651 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2653 DWORD retval, datsize = sizeof(retval);
2654 HKEY hKey;
2656 if (!lpSubKey)
2657 lpSubKey = strRegistryPolicyW;
2659 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2660 if (retval != ERROR_SUCCESS)
2661 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2662 if (retval != ERROR_SUCCESS)
2663 return 0;
2665 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2666 RegCloseKey(hKey);
2667 return retval;
2670 /*************************************************************************
2671 * @ [SHLWAPI.266]
2673 * Helper function to retrieve the possibly cached value for a specific policy
2675 * PARAMS
2676 * policy [I] The policy to look for
2677 * initial [I] Main registry key to open, if NULL use default
2678 * polTable [I] Table of known policies, 0 terminated
2679 * polArr [I] Cache array of policy values
2681 * RETURNS
2682 * The retrieved policy value or 0 if not successful
2684 * NOTES
2685 * This function is used by the native SHRestricted function to search for the
2686 * policy and cache it once retrieved. The current Wine implementation uses a
2687 * different POLICYDATA structure and implements a similar algorithm adapted to
2688 * that structure.
2690 DWORD WINAPI SHRestrictionLookup(
2691 DWORD policy,
2692 LPCWSTR initial,
2693 LPPOLICYDATA polTable,
2694 LPDWORD polArr)
2696 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2698 if (!polTable || !polArr)
2699 return 0;
2701 for (;polTable->policy; polTable++, polArr++)
2703 if (policy == polTable->policy)
2705 /* we have a known policy */
2707 /* check if this policy has been cached */
2708 if (*polArr == SHELL_NO_POLICY)
2709 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2710 return *polArr;
2713 /* we don't know this policy, return 0 */
2714 TRACE("unknown policy: (%08x)\n", policy);
2715 return 0;
2718 /*************************************************************************
2719 * @ [SHLWAPI.267]
2721 * Get an interface from an object.
2723 * RETURNS
2724 * Success: S_OK. ppv contains the requested interface.
2725 * Failure: An HRESULT error code.
2727 * NOTES
2728 * This QueryInterface asks the inner object for an interface. In case
2729 * of aggregation this request would be forwarded by the inner to the
2730 * outer object. This function asks the inner object directly for the
2731 * interface circumventing the forwarding to the outer object.
2733 HRESULT WINAPI SHWeakQueryInterface(
2734 IUnknown * pUnk, /* [in] Outer object */
2735 IUnknown * pInner, /* [in] Inner object */
2736 IID * riid, /* [in] Interface GUID to query for */
2737 LPVOID* ppv) /* [out] Destination for queried interface */
2739 HRESULT hret = E_NOINTERFACE;
2740 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2742 *ppv = NULL;
2743 if(pUnk && pInner) {
2744 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2745 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2747 TRACE("-- 0x%08x\n", hret);
2748 return hret;
2751 /*************************************************************************
2752 * @ [SHLWAPI.268]
2754 * Move a reference from one interface to another.
2756 * PARAMS
2757 * lpDest [O] Destination to receive the reference
2758 * lppUnknown [O] Source to give up the reference to lpDest
2760 * RETURNS
2761 * Nothing.
2763 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2765 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2767 if (*lppUnknown)
2769 /* Copy Reference*/
2770 IUnknown_AddRef(lpDest);
2771 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2775 /*************************************************************************
2776 * @ [SHLWAPI.269]
2778 * Convert an ASCII string of a CLSID into a CLSID.
2780 * PARAMS
2781 * idstr [I] String representing a CLSID in registry format
2782 * id [O] Destination for the converted CLSID
2784 * RETURNS
2785 * Success: TRUE. id contains the converted CLSID.
2786 * Failure: FALSE.
2788 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2790 WCHAR wClsid[40];
2791 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2792 return SUCCEEDED(CLSIDFromString(wClsid, id));
2795 /*************************************************************************
2796 * @ [SHLWAPI.270]
2798 * Unicode version of GUIDFromStringA.
2800 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2802 return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id));
2805 /*************************************************************************
2806 * @ [SHLWAPI.276]
2808 * Determine if the browser is integrated into the shell, and set a registry
2809 * key accordingly.
2811 * PARAMS
2812 * None.
2814 * RETURNS
2815 * 1, If the browser is not integrated.
2816 * 2, If the browser is integrated.
2818 * NOTES
2819 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2820 * either set to TRUE, or removed depending on whether the browser is deemed
2821 * to be integrated.
2823 DWORD WINAPI WhichPlatform(void)
2825 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2826 static DWORD dwState = 0;
2827 HKEY hKey;
2828 DWORD dwRet, dwData, dwSize;
2829 HMODULE hshell32;
2831 if (dwState)
2832 return dwState;
2834 /* If shell32 exports DllGetVersion(), the browser is integrated */
2835 dwState = 1;
2836 hshell32 = LoadLibraryA("shell32.dll");
2837 if (hshell32)
2839 FARPROC pDllGetVersion;
2840 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2841 dwState = pDllGetVersion ? 2 : 1;
2842 FreeLibrary(hshell32);
2845 /* Set or delete the key accordingly */
2846 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2847 "Software\\Microsoft\\Internet Explorer", 0,
2848 KEY_ALL_ACCESS, &hKey);
2849 if (!dwRet)
2851 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2852 (LPBYTE)&dwData, &dwSize);
2854 if (!dwRet && dwState == 1)
2856 /* Value exists but browser is not integrated */
2857 RegDeleteValueA(hKey, szIntegratedBrowser);
2859 else if (dwRet && dwState == 2)
2861 /* Browser is integrated but value does not exist */
2862 dwData = TRUE;
2863 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2864 (LPBYTE)&dwData, sizeof(dwData));
2866 RegCloseKey(hKey);
2868 return dwState;
2871 /*************************************************************************
2872 * @ [SHLWAPI.278]
2874 * Unicode version of SHCreateWorkerWindowA.
2876 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2877 DWORD dwStyle, HMENU hMenu, LONG msg_result)
2879 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
2880 WNDCLASSW wc;
2881 HWND hWnd;
2883 TRACE("(0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x)\n",
2884 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
2886 /* If our OS is natively ANSI, use the ANSI version */
2887 if (GetVersion() & 0x80000000) /* not NT */
2889 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
2890 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, msg_result);
2893 /* Create Window class */
2894 wc.style = 0;
2895 wc.lpfnWndProc = DefWindowProcW;
2896 wc.cbClsExtra = 0;
2897 wc.cbWndExtra = 4;
2898 wc.hInstance = shlwapi_hInstance;
2899 wc.hIcon = NULL;
2900 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2901 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2902 wc.lpszMenuName = NULL;
2903 wc.lpszClassName = szClass;
2905 SHRegisterClassW(&wc);
2907 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2908 hWndParent, hMenu, shlwapi_hInstance, 0);
2909 if (hWnd)
2911 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, msg_result);
2913 if (wndProc) SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2916 return hWnd;
2919 /*************************************************************************
2920 * @ [SHLWAPI.279]
2922 * Get and show a context menu from a shell folder.
2924 * PARAMS
2925 * hWnd [I] Window displaying the shell folder
2926 * lpFolder [I] IShellFolder interface
2927 * lpApidl [I] Id for the particular folder desired
2929 * RETURNS
2930 * Success: S_OK.
2931 * Failure: An HRESULT error code indicating the error.
2933 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2935 TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl);
2936 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2939 /*************************************************************************
2940 * @ [SHLWAPI.281]
2942 * _SHPackDispParamsV
2944 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist)
2946 VARIANTARG *iter;
2948 TRACE("(%p %p %u ...)\n", params, args, cnt);
2950 params->rgvarg = args;
2951 params->rgdispidNamedArgs = NULL;
2952 params->cArgs = cnt;
2953 params->cNamedArgs = 0;
2955 iter = args+cnt;
2957 while(iter-- > args) {
2958 V_VT(iter) = va_arg(valist, enum VARENUM);
2960 TRACE("vt=%d\n", V_VT(iter));
2962 if(V_VT(iter) & VT_BYREF) {
2963 V_BYREF(iter) = va_arg(valist, LPVOID);
2964 } else {
2965 switch(V_VT(iter)) {
2966 case VT_I4:
2967 V_I4(iter) = va_arg(valist, LONG);
2968 break;
2969 case VT_BSTR:
2970 V_BSTR(iter) = va_arg(valist, BSTR);
2971 break;
2972 case VT_DISPATCH:
2973 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
2974 break;
2975 case VT_BOOL:
2976 V_BOOL(iter) = va_arg(valist, int);
2977 break;
2978 case VT_UNKNOWN:
2979 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
2980 break;
2981 default:
2982 V_VT(iter) = VT_I4;
2983 V_I4(iter) = va_arg(valist, LONG);
2988 return S_OK;
2991 /*************************************************************************
2992 * @ [SHLWAPI.282]
2994 * SHPackDispParams
2996 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...)
2998 __ms_va_list valist;
2999 HRESULT hres;
3001 __ms_va_start(valist, cnt);
3002 hres = SHPackDispParamsV(params, args, cnt, valist);
3003 __ms_va_end(valist);
3004 return hres;
3007 /*************************************************************************
3008 * SHLWAPI_InvokeByIID
3010 * This helper function calls IDispatch::Invoke for each sink
3011 * which implements given iid or IDispatch.
3014 static HRESULT SHLWAPI_InvokeByIID(
3015 IConnectionPoint* iCP,
3016 REFIID iid,
3017 DISPID dispId,
3018 DISPPARAMS* dispParams)
3020 IEnumConnections *enumerator;
3021 CONNECTDATA rgcd;
3022 static DISPPARAMS empty = {NULL, NULL, 0, 0};
3023 DISPPARAMS* params = dispParams;
3025 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
3026 if (FAILED(result))
3027 return result;
3029 /* Invoke is never happening with an NULL dispParams */
3030 if (!params)
3031 params = &empty;
3033 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
3035 IDispatch *dispIface;
3036 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
3037 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
3039 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
3040 IDispatch_Release(dispIface);
3042 IUnknown_Release(rgcd.pUnk);
3045 IEnumConnections_Release(enumerator);
3047 return S_OK;
3050 /*************************************************************************
3051 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3053 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP,
3054 DISPID dispId, DISPPARAMS* dispParams,
3055 DWORD unknown1, DWORD unknown2 )
3057 IID iid;
3058 HRESULT result;
3060 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
3062 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3063 if (SUCCEEDED(result))
3064 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3065 else
3066 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3068 return result;
3072 /*************************************************************************
3073 * @ [SHLWAPI.284]
3075 * IConnectionPoint_SimpleInvoke
3077 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
3078 IConnectionPoint* iCP,
3079 DISPID dispId,
3080 DISPPARAMS* dispParams)
3082 IID iid;
3083 HRESULT result;
3085 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
3087 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3088 if (SUCCEEDED(result))
3089 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3090 else
3091 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3093 return result;
3096 /*************************************************************************
3097 * @ [SHLWAPI.285]
3099 * Notify an IConnectionPoint object of changes.
3101 * PARAMS
3102 * lpCP [I] Object to notify
3103 * dispID [I]
3105 * RETURNS
3106 * Success: S_OK.
3107 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3108 * IConnectionPoint interface.
3110 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
3112 IEnumConnections *lpEnum;
3113 HRESULT hRet = E_NOINTERFACE;
3115 TRACE("(%p,0x%8X)\n", lpCP, dispID);
3117 /* Get an enumerator for the connections */
3118 if (lpCP)
3119 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
3121 if (SUCCEEDED(hRet))
3123 IPropertyNotifySink *lpSink;
3124 CONNECTDATA connData;
3125 ULONG ulFetched;
3127 /* Call OnChanged() for every notify sink in the connection point */
3128 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
3130 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
3131 lpSink)
3133 IPropertyNotifySink_OnChanged(lpSink, dispID);
3134 IPropertyNotifySink_Release(lpSink);
3136 IUnknown_Release(connData.pUnk);
3139 IEnumConnections_Release(lpEnum);
3141 return hRet;
3144 /*************************************************************************
3145 * @ [SHLWAPI.286]
3147 * IUnknown_CPContainerInvokeParam
3149 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
3150 IUnknown *container,
3151 REFIID riid,
3152 DISPID dispId,
3153 VARIANTARG* buffer,
3154 DWORD cParams, ...)
3156 HRESULT result;
3157 IConnectionPoint *iCP;
3158 IConnectionPointContainer *iCPC;
3159 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3160 __ms_va_list valist;
3162 if (!container)
3163 return E_NOINTERFACE;
3165 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
3166 if (FAILED(result))
3167 return result;
3169 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
3170 IConnectionPointContainer_Release(iCPC);
3171 if(FAILED(result))
3172 return result;
3174 __ms_va_start(valist, cParams);
3175 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
3176 __ms_va_end(valist);
3178 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3179 IConnectionPoint_Release(iCP);
3181 return result;
3184 /*************************************************************************
3185 * @ [SHLWAPI.287]
3187 * Notify an IConnectionPointContainer object of changes.
3189 * PARAMS
3190 * lpUnknown [I] Object to notify
3191 * dispID [I]
3193 * RETURNS
3194 * Success: S_OK.
3195 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3196 * IConnectionPointContainer interface.
3198 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3200 IConnectionPointContainer* lpCPC = NULL;
3201 HRESULT hRet = E_NOINTERFACE;
3203 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3205 if (lpUnknown)
3206 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3208 if (SUCCEEDED(hRet))
3210 IConnectionPoint* lpCP;
3212 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3213 IConnectionPointContainer_Release(lpCPC);
3215 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3216 IConnectionPoint_Release(lpCP);
3218 return hRet;
3221 /*************************************************************************
3222 * @ [SHLWAPI.289]
3224 * See PlaySoundW.
3226 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3228 return PlaySoundW(pszSound, hmod, fdwSound);
3231 /*************************************************************************
3232 * @ [SHLWAPI.294]
3234 * Retrieve a key value from an INI file. See GetPrivateProfileString for
3235 * more information.
3237 * PARAMS
3238 * appName [I] The section in the INI file that contains the key
3239 * keyName [I] The key to be retrieved
3240 * out [O] The buffer into which the key's value will be copied
3241 * outLen [I] The length of the `out' buffer
3242 * filename [I] The location of the INI file
3244 * RETURNS
3245 * Length of string copied into `out'.
3247 DWORD WINAPI SHGetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPWSTR out,
3248 DWORD outLen, LPCWSTR filename)
3250 INT ret;
3251 WCHAR *buf;
3253 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName), debugstr_w(keyName),
3254 out, outLen, debugstr_w(filename));
3256 if(outLen == 0)
3257 return 0;
3259 buf = HeapAlloc(GetProcessHeap(), 0, outLen * sizeof(WCHAR));
3260 if(!buf){
3261 *out = 0;
3262 return 0;
3265 ret = GetPrivateProfileStringW(appName, keyName, NULL, buf, outLen, filename);
3266 if(ret)
3267 strcpyW(out, buf);
3268 else
3269 *out = 0;
3271 HeapFree(GetProcessHeap(), 0, buf);
3273 return strlenW(out);
3276 /*************************************************************************
3277 * @ [SHLWAPI.295]
3279 * Set a key value in an INI file. See WritePrivateProfileString for
3280 * more information.
3282 * PARAMS
3283 * appName [I] The section in the INI file that contains the key
3284 * keyName [I] The key to be set
3285 * str [O] The value of the key
3286 * filename [I] The location of the INI file
3288 * RETURNS
3289 * Success: TRUE
3290 * Failure: FALSE
3292 BOOL WINAPI SHSetIniStringW(LPCWSTR appName, LPCWSTR keyName, LPCWSTR str,
3293 LPCWSTR filename)
3295 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
3296 debugstr_w(filename));
3298 return WritePrivateProfileStringW(appName, keyName, str, filename);
3301 /*************************************************************************
3302 * @ [SHLWAPI.313]
3304 * See SHGetFileInfoW.
3306 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3307 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3309 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3312 /*************************************************************************
3313 * @ [SHLWAPI.318]
3315 * See DragQueryFileW.
3317 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3319 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3322 /*************************************************************************
3323 * @ [SHLWAPI.333]
3325 * See SHBrowseForFolderW.
3327 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3329 return SHBrowseForFolderW(lpBi);
3332 /*************************************************************************
3333 * @ [SHLWAPI.334]
3335 * See SHGetPathFromIDListW.
3337 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3339 return SHGetPathFromIDListW(pidl, pszPath);
3342 /*************************************************************************
3343 * @ [SHLWAPI.335]
3345 * See ShellExecuteExW.
3347 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3349 return ShellExecuteExW(lpExecInfo);
3352 /*************************************************************************
3353 * @ [SHLWAPI.336]
3355 * See SHFileOperationW.
3357 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3359 return SHFileOperationW(lpFileOp);
3362 /*************************************************************************
3363 * @ [SHLWAPI.342]
3366 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
3368 return InterlockedCompareExchangePointer( dest, xchg, compare );
3371 /*************************************************************************
3372 * @ [SHLWAPI.350]
3374 * See GetFileVersionInfoSizeW.
3376 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
3378 return GetFileVersionInfoSizeW( filename, handle );
3381 /*************************************************************************
3382 * @ [SHLWAPI.351]
3384 * See GetFileVersionInfoW.
3386 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
3387 DWORD datasize, LPVOID data )
3389 return GetFileVersionInfoW( filename, handle, datasize, data );
3392 /*************************************************************************
3393 * @ [SHLWAPI.352]
3395 * See VerQueryValueW.
3397 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
3398 LPVOID *lplpBuffer, UINT *puLen )
3400 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3403 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3404 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3405 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3407 /*************************************************************************
3408 * @ [SHLWAPI.355]
3410 * Change the modality of a shell object.
3412 * PARAMS
3413 * lpUnknown [I] Object to make modeless
3414 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3416 * RETURNS
3417 * Success: S_OK. The modality lpUnknown is changed.
3418 * Failure: An HRESULT error code indicating the error.
3420 * NOTES
3421 * lpUnknown must support the IOleInPlaceFrame interface, the
3422 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3423 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3424 * or this call will fail.
3426 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3428 IUnknown *lpObj;
3429 HRESULT hRet;
3431 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3433 if (!lpUnknown)
3434 return E_FAIL;
3436 if (IsIface(IOleInPlaceActiveObject))
3437 EnableModeless(IOleInPlaceActiveObject);
3438 else if (IsIface(IOleInPlaceFrame))
3439 EnableModeless(IOleInPlaceFrame);
3440 else if (IsIface(IShellBrowser))
3441 EnableModeless(IShellBrowser);
3442 else if (IsIface(IInternetSecurityMgrSite))
3443 EnableModeless(IInternetSecurityMgrSite);
3444 else if (IsIface(IDocHostUIHandler))
3445 EnableModeless(IDocHostUIHandler);
3446 else
3447 return hRet;
3449 IUnknown_Release(lpObj);
3450 return S_OK;
3453 /*************************************************************************
3454 * @ [SHLWAPI.357]
3456 * See SHGetNewLinkInfoW.
3458 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3459 BOOL *pfMustCopy, UINT uFlags)
3461 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3464 /*************************************************************************
3465 * @ [SHLWAPI.358]
3467 * See SHDefExtractIconW.
3469 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3470 HICON* phiconSmall, UINT nIconSize)
3472 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3475 /*************************************************************************
3476 * @ [SHLWAPI.363]
3478 * Get and show a context menu from a shell folder.
3480 * PARAMS
3481 * hWnd [I] Window displaying the shell folder
3482 * lpFolder [I] IShellFolder interface
3483 * lpApidl [I] Id for the particular folder desired
3484 * bInvokeDefault [I] Whether to invoke the default menu item
3486 * RETURNS
3487 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3488 * executed.
3489 * Failure: An HRESULT error code indicating the error.
3491 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3493 IContextMenu *iContext;
3494 HRESULT hRet;
3496 TRACE("(%p, %p, %p, %d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3498 if (!lpFolder)
3499 return E_FAIL;
3501 /* Get the context menu from the shell folder */
3502 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3503 &IID_IContextMenu, 0, (void**)&iContext);
3504 if (SUCCEEDED(hRet))
3506 HMENU hMenu;
3507 if ((hMenu = CreatePopupMenu()))
3509 HRESULT hQuery;
3510 DWORD dwDefaultId = 0;
3512 /* Add the context menu entries to the popup */
3513 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3514 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3516 if (SUCCEEDED(hQuery))
3518 if (bInvokeDefault &&
3519 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != (UINT)-1)
3521 CMINVOKECOMMANDINFO cmIci;
3522 /* Invoke the default item */
3523 memset(&cmIci,0,sizeof(cmIci));
3524 cmIci.cbSize = sizeof(cmIci);
3525 cmIci.fMask = CMIC_MASK_ASYNCOK;
3526 cmIci.hwnd = hWnd;
3527 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3528 cmIci.nShow = SW_SCROLLCHILDREN;
3530 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3533 DestroyMenu(hMenu);
3535 IContextMenu_Release(iContext);
3537 return hRet;
3540 /*************************************************************************
3541 * @ [SHLWAPI.370]
3543 * See ExtractIconW.
3545 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3546 UINT nIconIndex)
3548 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3551 /*************************************************************************
3552 * @ [SHLWAPI.377]
3554 * Load a library from the directory of a particular process.
3556 * PARAMS
3557 * new_mod [I] Library name
3558 * inst_hwnd [I] Module whose directory is to be used
3559 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3561 * RETURNS
3562 * Success: A handle to the loaded module
3563 * Failure: A NULL handle.
3565 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3567 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3568 * each call here.
3569 * FIXME: Native shows calls to:
3570 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3571 * CheckVersion
3572 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3573 * RegQueryValueExA for "LPKInstalled"
3574 * RegCloseKey
3575 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3576 * RegQueryValueExA for "ResourceLocale"
3577 * RegCloseKey
3578 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3579 * RegQueryValueExA for "Locale"
3580 * RegCloseKey
3581 * and then tests the Locale ("en" for me).
3582 * code below
3583 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3585 CHAR mod_path[2*MAX_PATH];
3586 LPSTR ptr;
3587 DWORD len;
3589 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3590 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3591 if (!len || len >= sizeof(mod_path)) return NULL;
3593 ptr = strrchr(mod_path, '\\');
3594 if (ptr) {
3595 strcpy(ptr+1, new_mod);
3596 TRACE("loading %s\n", debugstr_a(mod_path));
3597 return LoadLibraryA(mod_path);
3599 return NULL;
3602 /*************************************************************************
3603 * @ [SHLWAPI.378]
3605 * Unicode version of MLLoadLibraryA.
3607 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3609 WCHAR mod_path[2*MAX_PATH];
3610 LPWSTR ptr;
3611 DWORD len;
3613 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3614 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3615 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3617 ptr = strrchrW(mod_path, '\\');
3618 if (ptr) {
3619 strcpyW(ptr+1, new_mod);
3620 TRACE("loading %s\n", debugstr_w(mod_path));
3621 return LoadLibraryW(mod_path);
3623 return NULL;
3626 /*************************************************************************
3627 * ColorAdjustLuma [SHLWAPI.@]
3629 * Adjust the luminosity of a color
3631 * PARAMS
3632 * cRGB [I] RGB value to convert
3633 * dwLuma [I] Luma adjustment
3634 * bUnknown [I] Unknown
3636 * RETURNS
3637 * The adjusted RGB color.
3639 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3641 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3643 if (dwLuma)
3645 WORD wH, wL, wS;
3647 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3649 FIXME("Ignoring luma adjustment\n");
3651 /* FIXME: The adjustment is not linear */
3653 cRGB = ColorHLSToRGB(wH, wL, wS);
3655 return cRGB;
3658 /*************************************************************************
3659 * @ [SHLWAPI.389]
3661 * See GetSaveFileNameW.
3663 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3665 return GetSaveFileNameW(ofn);
3668 /*************************************************************************
3669 * @ [SHLWAPI.390]
3671 * See WNetRestoreConnectionW.
3673 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3675 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3678 /*************************************************************************
3679 * @ [SHLWAPI.391]
3681 * See WNetGetLastErrorW.
3683 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3684 LPWSTR lpNameBuf, DWORD nNameBufSize)
3686 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3689 /*************************************************************************
3690 * @ [SHLWAPI.401]
3692 * See PageSetupDlgW.
3694 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3696 return PageSetupDlgW(pagedlg);
3699 /*************************************************************************
3700 * @ [SHLWAPI.402]
3702 * See PrintDlgW.
3704 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3706 return PrintDlgW(printdlg);
3709 /*************************************************************************
3710 * @ [SHLWAPI.403]
3712 * See GetOpenFileNameW.
3714 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3716 return GetOpenFileNameW(ofn);
3719 /*************************************************************************
3720 * @ [SHLWAPI.404]
3722 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3724 /* Windows attempts to get an IPersist interface and, if that fails, an
3725 * IPersistFolder interface on the folder passed-in here. If one of those
3726 * interfaces is available, it then calls GetClassID on the folder... and
3727 * then calls IShellFolder_EnumObjects no matter what, even crashing if
3728 * lpFolder isn't actually an IShellFolder object. The purpose of getting
3729 * the ClassID is unknown, so we don't do it here.
3731 * For discussion and detailed tests, see:
3732 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated"
3733 * wine-devel mailing list, 3 Jun 2010
3736 return IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3739 /* INTERNAL: Map from HLS color space to RGB */
3740 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3742 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3744 if (wHue > 160)
3745 return wMid1;
3746 else if (wHue > 120)
3747 wHue = 160 - wHue;
3748 else if (wHue > 40)
3749 return wMid2;
3751 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3754 /* Convert to RGB and scale into RGB range (0..255) */
3755 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3757 /*************************************************************************
3758 * ColorHLSToRGB [SHLWAPI.@]
3760 * Convert from hls color space into an rgb COLORREF.
3762 * PARAMS
3763 * wHue [I] Hue amount
3764 * wLuminosity [I] Luminosity amount
3765 * wSaturation [I] Saturation amount
3767 * RETURNS
3768 * A COLORREF representing the converted color.
3770 * NOTES
3771 * Input hls values are constrained to the range (0..240).
3773 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3775 WORD wRed;
3777 if (wSaturation)
3779 WORD wGreen, wBlue, wMid1, wMid2;
3781 if (wLuminosity > 120)
3782 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3783 else
3784 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3786 wMid1 = wLuminosity * 2 - wMid2;
3788 wRed = GET_RGB(wHue + 80);
3789 wGreen = GET_RGB(wHue);
3790 wBlue = GET_RGB(wHue - 80);
3792 return RGB(wRed, wGreen, wBlue);
3795 wRed = wLuminosity * 255 / 240;
3796 return RGB(wRed, wRed, wRed);
3799 /*************************************************************************
3800 * @ [SHLWAPI.413]
3802 * Get the current docking status of the system.
3804 * PARAMS
3805 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3807 * RETURNS
3808 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3809 * a notebook.
3811 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3813 HW_PROFILE_INFOA hwInfo;
3815 TRACE("(0x%08x)\n", dwFlags);
3817 GetCurrentHwProfileA(&hwInfo);
3818 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3820 case DOCKINFO_DOCKED:
3821 case DOCKINFO_UNDOCKED:
3822 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3823 default:
3824 return 0;
3828 /*************************************************************************
3829 * @ [SHLWAPI.416]
3832 DWORD WINAPI SHWinHelpOnDemandW(HWND hwnd, LPCWSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2)
3835 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_w(helpfile), flags1, ptr1, flags2);
3836 return 0;
3839 /*************************************************************************
3840 * @ [SHLWAPI.417]
3843 DWORD WINAPI SHWinHelpOnDemandA(HWND hwnd, LPCSTR helpfile, DWORD flags1, VOID *ptr1, DWORD flags2)
3846 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_a(helpfile), flags1, ptr1, flags2);
3847 return 0;
3850 /*************************************************************************
3851 * @ [SHLWAPI.418]
3853 * Function seems to do FreeLibrary plus other things.
3855 * FIXME native shows the following calls:
3856 * RtlEnterCriticalSection
3857 * LocalFree
3858 * GetProcAddress(Comctl32??, 150L)
3859 * DPA_DeletePtr
3860 * RtlLeaveCriticalSection
3861 * followed by the FreeLibrary.
3862 * The above code may be related to .377 above.
3864 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3866 FIXME("(%p) semi-stub\n", hModule);
3867 return FreeLibrary(hModule);
3870 /*************************************************************************
3871 * @ [SHLWAPI.419]
3873 BOOL WINAPI SHFlushSFCacheWrap(void) {
3874 FIXME(": stub\n");
3875 return TRUE;
3878 /*************************************************************************
3879 * @ [SHLWAPI.429]
3880 * FIXME I have no idea what this function does or what its arguments are.
3882 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3884 FIXME("(%p) stub\n", hInst);
3885 return FALSE;
3889 /*************************************************************************
3890 * @ [SHLWAPI.430]
3892 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3894 FIXME("(%p,%p) stub\n", hInst, hHeap);
3895 return E_FAIL; /* This is what is used if shlwapi not loaded */
3898 /*************************************************************************
3899 * @ [SHLWAPI.431]
3901 DWORD WINAPI MLClearMLHInstance(DWORD x)
3903 FIXME("(0x%08x)stub\n", x);
3904 return 0xabba1247;
3907 /*************************************************************************
3908 * @ [SHLWAPI.432]
3910 * See SHSendMessageBroadcastW
3913 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam)
3915 return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam,
3916 SMTO_ABORTIFHUNG, 2000, NULL);
3919 /*************************************************************************
3920 * @ [SHLWAPI.433]
3922 * A wrapper for sending Broadcast Messages to all top level Windows
3925 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam)
3927 return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam,
3928 SMTO_ABORTIFHUNG, 2000, NULL);
3931 /*************************************************************************
3932 * @ [SHLWAPI.436]
3934 * Convert a Unicode string CLSID into a CLSID.
3936 * PARAMS
3937 * idstr [I] string containing a CLSID in text form
3938 * id [O] CLSID extracted from the string
3940 * RETURNS
3941 * S_OK on success or E_INVALIDARG on failure
3943 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3945 return CLSIDFromString((LPCOLESTR)idstr, id);
3948 /*************************************************************************
3949 * @ [SHLWAPI.437]
3951 * Determine if the OS supports a given feature.
3953 * PARAMS
3954 * dwFeature [I] Feature requested (undocumented)
3956 * RETURNS
3957 * TRUE If the feature is available.
3958 * FALSE If the feature is not available.
3960 BOOL WINAPI IsOS(DWORD feature)
3962 OSVERSIONINFOA osvi;
3963 DWORD platform, majorv, minorv;
3965 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3966 if(!GetVersionExA(&osvi)) {
3967 ERR("GetVersionEx failed\n");
3968 return FALSE;
3971 majorv = osvi.dwMajorVersion;
3972 minorv = osvi.dwMinorVersion;
3973 platform = osvi.dwPlatformId;
3975 #define ISOS_RETURN(x) \
3976 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3977 return (x);
3979 switch(feature) {
3980 case OS_WIN32SORGREATER:
3981 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3982 || platform == VER_PLATFORM_WIN32_WINDOWS)
3983 case OS_NT:
3984 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3985 case OS_WIN95ORGREATER:
3986 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3987 case OS_NT4ORGREATER:
3988 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3989 case OS_WIN2000ORGREATER_ALT:
3990 case OS_WIN2000ORGREATER:
3991 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3992 case OS_WIN98ORGREATER:
3993 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3994 case OS_WIN98_GOLD:
3995 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3996 case OS_WIN2000PRO:
3997 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3998 case OS_WIN2000SERVER:
3999 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4000 case OS_WIN2000ADVSERVER:
4001 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4002 case OS_WIN2000DATACENTER:
4003 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4004 case OS_WIN2000TERMINAL:
4005 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4006 case OS_EMBEDDED:
4007 FIXME("(OS_EMBEDDED) What should we return here?\n");
4008 return FALSE;
4009 case OS_TERMINALCLIENT:
4010 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
4011 return FALSE;
4012 case OS_TERMINALREMOTEADMIN:
4013 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
4014 return FALSE;
4015 case OS_WIN95_GOLD:
4016 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
4017 case OS_MEORGREATER:
4018 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
4019 case OS_XPORGREATER:
4020 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
4021 case OS_HOME:
4022 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
4023 case OS_PROFESSIONAL:
4024 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4025 case OS_DATACENTER:
4026 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4027 case OS_ADVSERVER:
4028 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
4029 case OS_SERVER:
4030 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4031 case OS_TERMINALSERVER:
4032 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4033 case OS_PERSONALTERMINALSERVER:
4034 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
4035 case OS_FASTUSERSWITCHING:
4036 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
4037 return TRUE;
4038 case OS_WELCOMELOGONUI:
4039 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
4040 return FALSE;
4041 case OS_DOMAINMEMBER:
4042 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
4043 return TRUE;
4044 case OS_ANYSERVER:
4045 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4046 case OS_WOW6432:
4048 BOOL is_wow64;
4049 IsWow64Process(GetCurrentProcess(), &is_wow64);
4050 return is_wow64;
4052 case OS_WEBSERVER:
4053 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4054 case OS_SMALLBUSINESSSERVER:
4055 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
4056 case OS_TABLETPC:
4057 FIXME("(OS_TABLEPC) What should we return here?\n");
4058 return FALSE;
4059 case OS_SERVERADMINUI:
4060 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
4061 return FALSE;
4062 case OS_MEDIACENTER:
4063 FIXME("(OS_MEDIACENTER) What should we return here?\n");
4064 return FALSE;
4065 case OS_APPLIANCE:
4066 FIXME("(OS_APPLIANCE) What should we return here?\n");
4067 return FALSE;
4068 case 0x25: /*OS_VISTAORGREATER*/
4069 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
4072 #undef ISOS_RETURN
4074 WARN("(0x%x) unknown parameter\n",feature);
4076 return FALSE;
4079 /*************************************************************************
4080 * @ [SHLWAPI.439]
4082 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
4084 DWORD type, sz = size;
4086 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
4087 return E_FAIL;
4089 return SHLoadIndirectString(buf, buf, size, NULL);
4092 /*************************************************************************
4093 * @ [SHLWAPI.478]
4095 * Call IInputObject_TranslateAcceleratorIO() on an object.
4097 * PARAMS
4098 * lpUnknown [I] Object supporting the IInputObject interface.
4099 * lpMsg [I] Key message to be processed.
4101 * RETURNS
4102 * Success: S_OK.
4103 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4105 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
4107 IInputObject* lpInput = NULL;
4108 HRESULT hRet = E_INVALIDARG;
4110 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
4111 if (lpUnknown)
4113 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4114 (void**)&lpInput);
4115 if (SUCCEEDED(hRet) && lpInput)
4117 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
4118 IInputObject_Release(lpInput);
4121 return hRet;
4124 /*************************************************************************
4125 * @ [SHLWAPI.481]
4127 * Call IInputObject_HasFocusIO() on an object.
4129 * PARAMS
4130 * lpUnknown [I] Object supporting the IInputObject interface.
4132 * RETURNS
4133 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4134 * or S_FALSE otherwise.
4135 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4137 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
4139 IInputObject* lpInput = NULL;
4140 HRESULT hRet = E_INVALIDARG;
4142 TRACE("(%p)\n", lpUnknown);
4143 if (lpUnknown)
4145 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4146 (void**)&lpInput);
4147 if (SUCCEEDED(hRet) && lpInput)
4149 hRet = IInputObject_HasFocusIO(lpInput);
4150 IInputObject_Release(lpInput);
4153 return hRet;
4156 /*************************************************************************
4157 * ColorRGBToHLS [SHLWAPI.@]
4159 * Convert an rgb COLORREF into the hls color space.
4161 * PARAMS
4162 * cRGB [I] Source rgb value
4163 * pwHue [O] Destination for converted hue
4164 * pwLuminance [O] Destination for converted luminance
4165 * pwSaturation [O] Destination for converted saturation
4167 * RETURNS
4168 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4169 * values.
4171 * NOTES
4172 * Output HLS values are constrained to the range (0..240).
4173 * For Achromatic conversions, Hue is set to 160.
4175 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
4176 LPWORD pwLuminance, LPWORD pwSaturation)
4178 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4180 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4182 wR = GetRValue(cRGB);
4183 wG = GetGValue(cRGB);
4184 wB = GetBValue(cRGB);
4186 wMax = max(wR, max(wG, wB));
4187 wMin = min(wR, min(wG, wB));
4189 /* Luminosity */
4190 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4192 if (wMax == wMin)
4194 /* Achromatic case */
4195 wSaturation = 0;
4196 /* Hue is now unrepresentable, but this is what native returns... */
4197 wHue = 160;
4199 else
4201 /* Chromatic case */
4202 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4204 /* Saturation */
4205 if (wLuminosity <= 120)
4206 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4207 else
4208 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4210 /* Hue */
4211 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4212 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4213 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4215 if (wR == wMax)
4216 wHue = wBNorm - wGNorm;
4217 else if (wG == wMax)
4218 wHue = 80 + wRNorm - wBNorm;
4219 else
4220 wHue = 160 + wGNorm - wRNorm;
4221 if (wHue < 0)
4222 wHue += 240;
4223 else if (wHue > 240)
4224 wHue -= 240;
4226 if (pwHue)
4227 *pwHue = wHue;
4228 if (pwLuminance)
4229 *pwLuminance = wLuminosity;
4230 if (pwSaturation)
4231 *pwSaturation = wSaturation;
4234 /*************************************************************************
4235 * SHCreateShellPalette [SHLWAPI.@]
4237 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4239 FIXME("stub\n");
4240 return CreateHalftonePalette(hdc);
4243 /*************************************************************************
4244 * SHGetInverseCMAP (SHLWAPI.@)
4246 * Get an inverse color map table.
4248 * PARAMS
4249 * lpCmap [O] Destination for color map
4250 * dwSize [I] Size of memory pointed to by lpCmap
4252 * RETURNS
4253 * Success: S_OK.
4254 * Failure: E_POINTER, If lpCmap is invalid.
4255 * E_INVALIDARG, If dwFlags is invalid
4256 * E_OUTOFMEMORY, If there is no memory available
4258 * NOTES
4259 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4260 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4261 * internal CMap.
4262 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4263 * this DLL's internal CMap.
4265 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4267 if (dwSize == 4) {
4268 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4269 *dest = (DWORD)0xabba1249;
4270 return 0;
4272 FIXME("(%p, %#x) stub\n", dest, dwSize);
4273 return 0;
4276 /*************************************************************************
4277 * SHIsLowMemoryMachine [SHLWAPI.@]
4279 * Determine if the current computer has low memory.
4281 * PARAMS
4282 * x [I] FIXME
4284 * RETURNS
4285 * TRUE if the users machine has 16 Megabytes of memory or less,
4286 * FALSE otherwise.
4288 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4290 FIXME("(0x%08x) stub\n", x);
4291 return FALSE;
4294 /*************************************************************************
4295 * GetMenuPosFromID [SHLWAPI.@]
4297 * Return the position of a menu item from its Id.
4299 * PARAMS
4300 * hMenu [I] Menu containing the item
4301 * wID [I] Id of the menu item
4303 * RETURNS
4304 * Success: The index of the menu item in hMenu.
4305 * Failure: -1, If the item is not found.
4307 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4309 MENUITEMINFOW mi;
4310 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4312 TRACE("%p %u\n", hMenu, wID);
4314 while (nIter < nCount)
4316 mi.cbSize = sizeof(mi);
4317 mi.fMask = MIIM_ID;
4318 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4320 TRACE("ret %d\n", nIter);
4321 return nIter;
4323 nIter++;
4326 return -1;
4329 /*************************************************************************
4330 * @ [SHLWAPI.179]
4332 * Same as SHLWAPI.GetMenuPosFromID
4334 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4336 TRACE("%p %u\n", hMenu, uID);
4337 return GetMenuPosFromID(hMenu, uID);
4341 /*************************************************************************
4342 * @ [SHLWAPI.448]
4344 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4346 while (*lpwstr)
4348 if (*lpwstr == '/')
4349 *lpwstr = '\\';
4350 lpwstr++;
4355 /*************************************************************************
4356 * @ [SHLWAPI.461]
4358 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4360 FIXME("(0x%08x) stub\n", dwUnknown);
4361 return 0;
4365 /*************************************************************************
4366 * @ [SHLWAPI.549]
4368 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4369 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4371 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4374 /*************************************************************************
4375 * SHSkipJunction [SHLWAPI.@]
4377 * Determine if a bind context can be bound to an object
4379 * PARAMS
4380 * pbc [I] Bind context to check
4381 * pclsid [I] CLSID of object to be bound to
4383 * RETURNS
4384 * TRUE: If it is safe to bind
4385 * FALSE: If pbc is invalid or binding would not be safe
4388 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4390 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4391 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4392 BOOL bRet = FALSE;
4394 if (pbc)
4396 IUnknown* lpUnk;
4398 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4400 CLSID clsid;
4402 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4403 IsEqualGUID(pclsid, &clsid))
4404 bRet = TRUE;
4406 IUnknown_Release(lpUnk);
4409 return bRet;
4412 /***********************************************************************
4413 * SHGetShellKey (SHLWAPI.491)
4415 HKEY WINAPI SHGetShellKey(DWORD flags, LPCWSTR sub_key, BOOL create)
4417 enum _shellkey_flags {
4418 SHKEY_Root_HKCU = 0x1,
4419 SHKEY_Root_HKLM = 0x2,
4420 SHKEY_Key_Explorer = 0x00,
4421 SHKEY_Key_Shell = 0x10,
4422 SHKEY_Key_ShellNoRoam = 0x20,
4423 SHKEY_Key_Classes = 0x30,
4424 SHKEY_Subkey_Default = 0x0000,
4425 SHKEY_Subkey_ResourceName = 0x1000,
4426 SHKEY_Subkey_Handlers = 0x2000,
4427 SHKEY_Subkey_Associations = 0x3000,
4428 SHKEY_Subkey_Volatile = 0x4000,
4429 SHKEY_Subkey_MUICache = 0x5000,
4430 SHKEY_Subkey_FileExts = 0x6000
4433 static const WCHAR explorerW[] = {'S','o','f','t','w','a','r','e','\\',
4434 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4435 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4436 'E','x','p','l','o','r','e','r','\\'};
4437 static const WCHAR shellW[] = {'S','o','f','t','w','a','r','e','\\',
4438 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4439 'S','h','e','l','l','\\'};
4440 static const WCHAR shell_no_roamW[] = {'S','o','f','t','w','a','r','e','\\',
4441 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4442 'S','h','e','l','l','N','o','R','o','a','m','\\'};
4443 static const WCHAR classesW[] = {'S','o','f','t','w','a','r','e','\\',
4444 'C','l','a','s','s','e','s','\\'};
4446 static const WCHAR localized_resource_nameW[] = {'L','o','c','a','l','i','z','e','d',
4447 'R','e','s','o','u','r','c','e','N','a','m','e','\\'};
4448 static const WCHAR handlersW[] = {'H','a','n','d','l','e','r','s','\\'};
4449 static const WCHAR associationsW[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'};
4450 static const WCHAR volatileW[] = {'V','o','l','a','t','i','l','e','\\'};
4451 static const WCHAR mui_cacheW[] = {'M','U','I','C','a','c','h','e','\\'};
4452 static const WCHAR file_extsW[] = {'F','i','l','e','E','x','t','s','\\'};
4454 WCHAR *path;
4455 const WCHAR *key, *subkey;
4456 int size_key, size_subkey, size_user;
4457 HKEY hkey = NULL;
4459 TRACE("(0x%08x, %s, %d)\n", flags, debugstr_w(sub_key), create);
4461 /* For compatibility with Vista+ */
4462 if(flags == 0x1ffff)
4463 flags = 0x21;
4465 switch(flags&0xff0) {
4466 case SHKEY_Key_Explorer:
4467 key = explorerW;
4468 size_key = sizeof(explorerW);
4469 break;
4470 case SHKEY_Key_Shell:
4471 key = shellW;
4472 size_key = sizeof(shellW);
4473 break;
4474 case SHKEY_Key_ShellNoRoam:
4475 key = shell_no_roamW;
4476 size_key = sizeof(shell_no_roamW);
4477 break;
4478 case SHKEY_Key_Classes:
4479 key = classesW;
4480 size_key = sizeof(classesW);
4481 break;
4482 default:
4483 FIXME("unsupported flags (0x%08x)\n", flags);
4484 return NULL;
4487 switch(flags&0xff000) {
4488 case SHKEY_Subkey_Default:
4489 subkey = NULL;
4490 size_subkey = 0;
4491 break;
4492 case SHKEY_Subkey_ResourceName:
4493 subkey = localized_resource_nameW;
4494 size_subkey = sizeof(localized_resource_nameW);
4495 break;
4496 case SHKEY_Subkey_Handlers:
4497 subkey = handlersW;
4498 size_subkey = sizeof(handlersW);
4499 break;
4500 case SHKEY_Subkey_Associations:
4501 subkey = associationsW;
4502 size_subkey = sizeof(associationsW);
4503 break;
4504 case SHKEY_Subkey_Volatile:
4505 subkey = volatileW;
4506 size_subkey = sizeof(volatileW);
4507 break;
4508 case SHKEY_Subkey_MUICache:
4509 subkey = mui_cacheW;
4510 size_subkey = sizeof(mui_cacheW);
4511 break;
4512 case SHKEY_Subkey_FileExts:
4513 subkey = file_extsW;
4514 size_subkey = sizeof(file_extsW);
4515 break;
4516 default:
4517 FIXME("unsupported flags (0x%08x)\n", flags);
4518 return NULL;
4521 if(sub_key)
4522 size_user = lstrlenW(sub_key)*sizeof(WCHAR);
4523 else
4524 size_user = 0;
4526 path = HeapAlloc(GetProcessHeap(), 0, size_key+size_subkey+size_user+sizeof(WCHAR));
4527 if(!path) {
4528 ERR("Out of memory\n");
4529 return NULL;
4532 memcpy(path, key, size_key);
4533 if(subkey)
4534 memcpy(path+size_key/sizeof(WCHAR), subkey, size_subkey);
4535 if(sub_key)
4536 memcpy(path+(size_key+size_subkey)/sizeof(WCHAR), sub_key, size_user);
4537 path[(size_key+size_subkey+size_user)/sizeof(WCHAR)] = '\0';
4539 if(create)
4540 RegCreateKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
4541 path, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &hkey, NULL);
4542 else
4543 RegOpenKeyExW((flags&0xf)==SHKEY_Root_HKLM?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER,
4544 path, 0, MAXIMUM_ALLOWED, &hkey);
4546 HeapFree(GetProcessHeap(), 0, path);
4547 return hkey;
4550 /***********************************************************************
4551 * SHQueueUserWorkItem (SHLWAPI.@)
4553 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback,
4554 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4555 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4557 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4558 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4560 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4561 FIXME("Unsupported arguments\n");
4563 return QueueUserWorkItem(pfnCallback, pContext, 0);
4566 /***********************************************************************
4567 * SHSetTimerQueueTimer (SHLWAPI.263)
4569 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
4570 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4571 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4573 HANDLE hNewTimer;
4575 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4576 if (dwFlags & TPS_LONGEXECTIME) {
4577 dwFlags &= ~TPS_LONGEXECTIME;
4578 dwFlags |= WT_EXECUTELONGFUNCTION;
4580 if (dwFlags & TPS_EXECUTEIO) {
4581 dwFlags &= ~TPS_EXECUTEIO;
4582 dwFlags |= WT_EXECUTEINIOTHREAD;
4585 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4586 dwDueTime, dwPeriod, dwFlags))
4587 return NULL;
4589 return hNewTimer;
4592 /***********************************************************************
4593 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4595 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4597 IInputObjectSite *pIOS = NULL;
4598 HRESULT hRet = E_INVALIDARG;
4600 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4602 if (lpUnknown)
4604 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4605 (void **)&pIOS);
4606 if (SUCCEEDED(hRet) && pIOS)
4608 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4609 IInputObjectSite_Release(pIOS);
4612 return hRet;
4615 /***********************************************************************
4616 * SKAllocValueW (SHLWAPI.519)
4618 HRESULT WINAPI SKAllocValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type,
4619 LPVOID *data, DWORD *count)
4621 DWORD ret, size;
4622 HKEY hkey;
4624 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey),
4625 debugstr_w(value), type, data, count);
4627 hkey = SHGetShellKey(flags, subkey, FALSE);
4628 if (!hkey)
4629 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4631 ret = SHQueryValueExW(hkey, value, NULL, type, NULL, &size);
4632 if (ret) {
4633 RegCloseKey(hkey);
4634 return HRESULT_FROM_WIN32(ret);
4637 size += 2;
4638 *data = LocalAlloc(0, size);
4639 if (!*data) {
4640 RegCloseKey(hkey);
4641 return E_OUTOFMEMORY;
4644 ret = SHQueryValueExW(hkey, value, NULL, type, *data, &size);
4645 if (count)
4646 *count = size;
4648 RegCloseKey(hkey);
4649 return HRESULT_FROM_WIN32(ret);
4652 /***********************************************************************
4653 * SKDeleteValueW (SHLWAPI.518)
4655 HRESULT WINAPI SKDeleteValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value)
4657 DWORD ret;
4658 HKEY hkey;
4660 TRACE("(0x%x, %s %s)\n", flags, debugstr_w(subkey), debugstr_w(value));
4662 hkey = SHGetShellKey(flags, subkey, FALSE);
4663 if (!hkey)
4664 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4666 ret = RegDeleteValueW(hkey, value);
4668 RegCloseKey(hkey);
4669 return HRESULT_FROM_WIN32(ret);
4672 /***********************************************************************
4673 * SKGetValueW (SHLWAPI.516)
4675 HRESULT WINAPI SKGetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value, DWORD *type,
4676 void *data, DWORD *count)
4678 DWORD ret;
4679 HKEY hkey;
4681 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey),
4682 debugstr_w(value), type, data, count);
4684 hkey = SHGetShellKey(flags, subkey, FALSE);
4685 if (!hkey)
4686 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4688 ret = SHQueryValueExW(hkey, value, NULL, type, data, count);
4690 RegCloseKey(hkey);
4691 return HRESULT_FROM_WIN32(ret);
4694 /***********************************************************************
4695 * SKSetValueW (SHLWAPI.516)
4697 HRESULT WINAPI SKSetValueW(DWORD flags, LPCWSTR subkey, LPCWSTR value,
4698 DWORD type, void *data, DWORD count)
4700 DWORD ret;
4701 HKEY hkey;
4703 TRACE("(0x%x, %s, %s, %x, %p, %d)\n", flags, debugstr_w(subkey),
4704 debugstr_w(value), type, data, count);
4706 hkey = SHGetShellKey(flags, subkey, TRUE);
4707 if (!hkey)
4708 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
4710 ret = RegSetValueExW(hkey, value, 0, type, data, count);
4712 RegCloseKey(hkey);
4713 return HRESULT_FROM_WIN32(ret);
4716 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4718 /***********************************************************************
4719 * GetUIVersion (SHLWAPI.452)
4721 DWORD WINAPI GetUIVersion(void)
4723 static DWORD version;
4725 if (!version)
4727 DllGetVersion_func pDllGetVersion;
4728 HMODULE dll = LoadLibraryA("shell32.dll");
4729 if (!dll) return 0;
4731 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4732 if (pDllGetVersion)
4734 DLLVERSIONINFO dvi;
4735 dvi.cbSize = sizeof(DLLVERSIONINFO);
4736 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4738 FreeLibrary( dll );
4739 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4741 return version;
4744 /***********************************************************************
4745 * ShellMessageBoxWrapW [SHLWAPI.388]
4747 * See shell32.ShellMessageBoxW
4749 * NOTE:
4750 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4751 * because we can't forward to it in the .spec file since it's exported by
4752 * ordinal. If you change the implementation here please update the code in
4753 * shell32 as well.
4755 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
4756 LPCWSTR lpCaption, UINT uType, ...)
4758 WCHAR *szText = NULL, szTitle[100];
4759 LPCWSTR pszText, pszTitle = szTitle;
4760 LPWSTR pszTemp;
4761 __ms_va_list args;
4762 int ret;
4764 __ms_va_start(args, uType);
4766 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
4768 if (IS_INTRESOURCE(lpCaption))
4769 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
4770 else
4771 pszTitle = lpCaption;
4773 if (IS_INTRESOURCE(lpText))
4775 const WCHAR *ptr;
4776 UINT len = LoadStringW(hInstance, LOWORD(lpText), (LPWSTR)&ptr, 0);
4778 if (len)
4780 szText = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
4781 if (szText) LoadStringW(hInstance, LOWORD(lpText), szText, len + 1);
4783 pszText = szText;
4784 if (!pszText) {
4785 WARN("Failed to load id %d\n", LOWORD(lpText));
4786 __ms_va_end(args);
4787 return 0;
4790 else
4791 pszText = lpText;
4793 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4794 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4796 __ms_va_end(args);
4798 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4800 HeapFree(GetProcessHeap(), 0, szText);
4801 LocalFree(pszTemp);
4802 return ret;
4805 /***********************************************************************
4806 * ZoneComputePaneSize [SHLWAPI.382]
4808 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4810 FIXME("\n");
4811 return 0x95;
4814 /***********************************************************************
4815 * SHChangeNotifyWrap [SHLWAPI.394]
4817 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
4819 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
4822 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
4823 SID_IDENTIFIER_AUTHORITY sidAuthority;
4824 DWORD dwUserGroupID;
4825 DWORD dwUserID;
4826 } SHELL_USER_SID, *PSHELL_USER_SID;
4828 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
4829 SHELL_USER_SID susID;
4830 DWORD dwAccessType;
4831 BOOL fInherit;
4832 DWORD dwAccessMask;
4833 DWORD dwInheritMask;
4834 DWORD dwInheritAccessMask;
4835 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
4837 /***********************************************************************
4838 * GetShellSecurityDescriptor [SHLWAPI.475]
4840 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4842 * PARAMS
4843 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4844 * each of which describes permissions to apply
4845 * cUserPerm [I] number of entries in apUserPerm array
4847 * RETURNS
4848 * success: pointer to SECURITY_DESCRIPTOR
4849 * failure: NULL
4851 * NOTES
4852 * Call should free returned descriptor with LocalFree
4854 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4856 PSID *sidlist;
4857 PSID cur_user = NULL;
4858 BYTE tuUser[2000];
4859 DWORD acl_size;
4860 int sid_count, i;
4861 PSECURITY_DESCRIPTOR psd = NULL;
4863 TRACE("%p %d\n", apUserPerm, cUserPerm);
4865 if (apUserPerm == NULL || cUserPerm <= 0)
4866 return NULL;
4868 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
4869 if (!sidlist)
4870 return NULL;
4872 acl_size = sizeof(ACL);
4874 for(sid_count = 0; sid_count < cUserPerm; sid_count++)
4876 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
4877 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
4878 PSHELL_USER_SID sid = &perm->susID;
4879 PSID pSid;
4880 BOOL ret = TRUE;
4882 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4883 { /* current user's SID */
4884 if (!cur_user)
4886 HANDLE Token;
4887 DWORD bufsize = sizeof(tuUser);
4889 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4890 if (ret)
4892 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4893 if (ret)
4894 cur_user = ((PTOKEN_USER)tuUser)->User.Sid;
4895 CloseHandle(Token);
4898 pSid = cur_user;
4899 } else if (sid->dwUserID==0) /* one sub-authority */
4900 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
4901 0, 0, 0, 0, 0, 0, &pSid);
4902 else
4903 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4904 0, 0, 0, 0, 0, 0, &pSid);
4905 if (!ret)
4906 goto free_sids;
4908 sidlist[sid_count] = pSid;
4909 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4910 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
4913 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
4915 if (psd != NULL)
4917 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4919 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4920 goto error;
4922 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4923 goto error;
4925 for(i = 0; i < sid_count; i++)
4927 PSHELL_USER_PERMISSION sup = apUserPerm[i];
4928 PSID sid = sidlist[i];
4930 switch(sup->dwAccessType)
4932 case ACCESS_ALLOWED_ACE_TYPE:
4933 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4934 goto error;
4935 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4936 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4937 goto error;
4938 break;
4939 case ACCESS_DENIED_ACE_TYPE:
4940 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4941 goto error;
4942 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4943 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4944 goto error;
4945 break;
4946 default:
4947 goto error;
4951 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4952 goto error;
4954 goto free_sids;
4956 error:
4957 LocalFree(psd);
4958 psd = NULL;
4959 free_sids:
4960 for(i = 0; i < sid_count; i++)
4962 if (!cur_user || sidlist[i] != cur_user)
4963 FreeSid(sidlist[i]);
4965 HeapFree(GetProcessHeap(), 0, sidlist);
4967 return psd;
4970 /***********************************************************************
4971 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4973 * Creates a property bag from a registry key
4975 * PARAMS
4976 * hKey [I] Handle to the desired registry key
4977 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4978 * grfMode [I] Optional flags
4979 * riid [I] IID of requested property bag interface
4980 * ppv [O] Address to receive pointer to the new interface
4982 * RETURNS
4983 * success: 0
4984 * failure: error code
4987 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey,
4988 DWORD grfMode, REFIID riid, void **ppv)
4990 FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode,
4991 debugstr_guid(riid), ppv);
4993 return E_NOTIMPL;
4996 /***********************************************************************
4997 * SHGetViewStatePropertyBag [SHLWAPI.515]
4999 * Retrieves a property bag in which the view state information of a folder
5000 * can be stored.
5002 * PARAMS
5003 * pidl [I] PIDL of the folder requested
5004 * bag_name [I] Name of the property bag requested
5005 * flags [I] Optional flags
5006 * riid [I] IID of requested property bag interface
5007 * ppv [O] Address to receive pointer to the new interface
5009 * RETURNS
5010 * success: S_OK
5011 * failure: error code
5014 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
5015 DWORD flags, REFIID riid, void **ppv)
5017 FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags,
5018 debugstr_guid(riid), ppv);
5020 return E_NOTIMPL;
5023 /***********************************************************************
5024 * SHFormatDateTimeW [SHLWAPI.354]
5026 * Produces a string representation of a time.
5028 * PARAMS
5029 * fileTime [I] Pointer to FILETIME structure specifying the time
5030 * flags [I] Flags specifying the desired output
5031 * buf [O] Pointer to buffer for output
5032 * size [I] Number of characters that can be contained in buffer
5034 * RETURNS
5035 * success: number of characters written to the buffer
5036 * failure: 0
5039 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
5040 LPWSTR buf, UINT size)
5042 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
5043 DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT;
5044 SYSTEMTIME st;
5045 FILETIME ft;
5046 INT ret = 0;
5048 TRACE("%p %p %p %u\n", fileTime, flags, buf, size);
5050 if (!buf || !size)
5051 return 0;
5053 if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS)
5054 FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS);
5056 FileTimeToLocalFileTime(fileTime, &ft);
5057 FileTimeToSystemTime(&ft, &st);
5059 /* first of all date */
5060 if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE))
5062 static const WCHAR sep1[] = {',',' ',0};
5063 static const WCHAR sep2[] = {' ',0};
5065 DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE;
5066 ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size);
5067 if (ret >= size) return ret;
5069 /* add separator */
5070 if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)))
5072 if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2))
5074 if (ret < size + 2)
5076 lstrcatW(&buf[ret-1], sep1);
5077 ret += 2;
5080 else
5082 lstrcatW(&buf[ret-1], sep2);
5083 ret++;
5087 /* time part */
5088 if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))
5090 DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS;
5092 if (ret) ret--;
5093 ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret);
5096 return ret;
5098 #undef SHFORMATDT_UNSUPPORTED_FLAGS
5101 /***********************************************************************
5102 * SHFormatDateTimeA [SHLWAPI.353]
5104 * See SHFormatDateTimeW.
5107 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags,
5108 LPSTR buf, UINT size)
5110 WCHAR *bufW;
5111 INT retval;
5113 if (!buf || !size)
5114 return 0;
5116 bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
5117 retval = SHFormatDateTimeW(fileTime, flags, bufW, size);
5119 if (retval != 0)
5120 WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL);
5122 HeapFree(GetProcessHeap(), 0, bufW);
5123 return retval;
5126 /***********************************************************************
5127 * ZoneCheckUrlExW [SHLWAPI.231]
5129 * Checks the details of the security zone for the supplied site. (?)
5131 * PARAMS
5133 * szURL [I] Pointer to the URL to check
5135 * Other parameters currently unknown.
5137 * RETURNS
5138 * unknown
5141 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2,
5142 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6,
5143 DWORD dwUnknown7)
5145 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2,
5146 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7);
5148 return 0;
5151 /***********************************************************************
5152 * SHVerbExistsNA [SHLWAPI.196]
5155 * PARAMS
5157 * verb [I] a string, often appears to be an extension.
5159 * Other parameters currently unknown.
5161 * RETURNS
5162 * unknown
5164 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3)
5166 FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3);
5167 return 0;
5170 /*************************************************************************
5171 * @ [SHLWAPI.538]
5173 * Undocumented: Implementation guessed at via Name and behavior
5175 * PARAMS
5176 * lpUnknown [I] Object to get an IServiceProvider interface from
5177 * riid [I] Function requested for QueryService call
5178 * lppOut [O] Destination for the service interface pointer
5180 * RETURNS
5181 * Success: S_OK. lppOut contains an object providing the requested service
5182 * Failure: An HRESULT error code
5184 * NOTES
5185 * lpUnknown is expected to support the IServiceProvider interface.
5187 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown,
5188 REFGUID riid, LPVOID *lppOut)
5190 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut);
5191 return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut);
5194 /**************************************************************************
5195 * SHPropertyBag_ReadLONG (SHLWAPI.496)
5197 * This function asks a property bag to read a named property as a LONG.
5199 * PARAMS
5200 * ppb: a IPropertyBag interface
5201 * pszPropName: Unicode string that names the property
5202 * pValue: address to receive the property value as a 32-bit signed integer
5204 * RETURNS
5205 * 0 for Success
5207 BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue)
5209 VARIANT var;
5210 HRESULT hr;
5211 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue);
5212 if (!pszPropName || !ppb || !pValue)
5213 return E_INVALIDARG;
5214 V_VT(&var) = VT_I4;
5215 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
5216 if (SUCCEEDED(hr))
5218 if (V_VT(&var) == VT_I4)
5219 *pValue = V_I4(&var);
5220 else
5221 hr = DISP_E_BADVARTYPE;
5223 return hr;
5226 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
5227 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
5228 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
5229 #define OBJCOMPAT_UNBINDABLE 0x00000004
5230 #define OBJCOMPAT_PINDLL 0x00000008
5231 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
5232 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
5233 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
5234 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
5235 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
5236 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
5237 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
5238 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
5239 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
5241 /* a search table for compatibility flags */
5242 struct objcompat_entry {
5243 const WCHAR name[30];
5244 DWORD value;
5247 /* expected to be sorted by name */
5248 static const struct objcompat_entry objcompat_table[] = {
5249 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
5250 OBJCOMPAT_COCREATESHELLFOLDERONLY },
5251 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
5252 OBJCOMPAT_CTXMENU_LIMITEDQI },
5253 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
5254 OBJCOMPAT_CTXMENU_LIMITEDQI },
5255 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
5256 OBJCOMPAT_CTXMENU_XPQCMFLAGS },
5257 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
5258 OBJCOMPAT_NEEDSFILESYSANCESTOR },
5259 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
5260 OBJCOMPAT_NEEDSSTORAGEANCESTOR },
5261 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
5262 OBJCOMPAT_NOIPROPERTYSTORE },
5263 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
5264 OBJCOMPAT_NOLEGACYWEBVIEW },
5265 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
5266 OBJCOMPAT_NOTAFILESYSTEM },
5267 { {'N','O','_','W','E','B','V','I','E','W',0},
5268 OBJCOMPAT_NO_WEBVIEW },
5269 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
5270 OBJCOMPAT_OTNEEDSSFCACHE },
5271 { {'P','I','N','D','L','L',0},
5272 OBJCOMPAT_PINDLL },
5273 { {'U','N','B','I','N','D','A','B','L','E',0},
5274 OBJCOMPAT_UNBINDABLE }
5277 /**************************************************************************
5278 * SHGetObjectCompatFlags (SHLWAPI.476)
5280 * Function returns an integer representation of compatibility flags stored
5281 * in registry for CLSID under ShellCompatibility subkey.
5283 * PARAMS
5284 * pUnk: pointer to object IUnknown interface, idetifies CLSID
5285 * clsid: pointer to CLSID to retrieve data for
5287 * RETURNS
5288 * 0 on failure, flags set on success
5290 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid)
5292 static const WCHAR compatpathW[] =
5293 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
5294 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
5295 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
5296 'O','b','j','e','c','t','s','\\','%','s',0};
5297 WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */];
5298 DWORD ret, length = sizeof(strW)/sizeof(WCHAR);
5299 OLECHAR *clsid_str;
5300 HKEY key;
5301 INT i;
5303 TRACE("%p %s\n", pUnk, debugstr_guid(clsid));
5305 if (!pUnk && !clsid) return 0;
5307 if (pUnk && !clsid)
5309 FIXME("iface not handled\n");
5310 return 0;
5313 StringFromCLSID(clsid, &clsid_str);
5314 sprintfW(strW, compatpathW, clsid_str);
5315 CoTaskMemFree(clsid_str);
5317 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key);
5318 if (ret != ERROR_SUCCESS) return 0;
5320 /* now collect flag values */
5321 ret = 0;
5322 for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++)
5324 INT left, right, res, x;
5326 /* search in table */
5327 left = 0;
5328 right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1;
5330 while (right >= left) {
5331 x = (left + right) / 2;
5332 res = strcmpW(strW, objcompat_table[x].name);
5333 if (res == 0)
5335 ret |= objcompat_table[x].value;
5336 break;
5338 else if (res < 0)
5339 right = x - 1;
5340 else
5341 left = x + 1;
5344 length = sizeof(strW)/sizeof(WCHAR);
5347 return ret;