ReactOS 0.4.15-dev-6054-gbddd8b0
ordinal.c
Go to the documentation of this file.
1/*
2 * SHLWAPI ordinal functions
3 *
4 * Copyright 1997 Marcus Meissner
5 * 1998 Jürgen Schmied
6 * 2001-2003 Jon Griffiths
7 *
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.
12 *
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.
17 *
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
21 */
22
23#include "config.h"
24#include "wine/port.h"
25
26#include <stdarg.h>
27#include <stdio.h>
28#include <string.h>
29
30#define COBJMACROS
31
32#include "windef.h"
33#include "winbase.h"
34#include "winnls.h"
35#include "winreg.h"
36#include "wingdi.h"
37#include "winuser.h"
38#include "winver.h"
39#include "winnetwk.h"
40#include "mmsystem.h"
41#include "objbase.h"
42#include "exdisp.h"
43#include "shdeprecated.h"
44#include "shlobj.h"
45#include "shlwapi.h"
46#include "shellapi.h"
47#include "commdlg.h"
48#include "mlang.h"
49#include "mshtmhst.h"
50#include "wine/unicode.h"
51#include "wine/debug.h"
52
53
55
56/* DLL handles for late bound calls */
59
63
64/*
65 NOTES: Most functions exported by ordinal seem to be superfluous.
66 The reason for these functions to be there is to provide a wrapper
67 for unicode functions to provide these functions on systems without
68 unicode functions eg. win95/win98. Since we have such functions we just
69 call these. If running Wine with native DLLs, some late bound calls may
70 fail. However, it is better to implement the functions in the forward DLL
71 and recommend the builtin rather than reimplementing the calls here!
72*/
73
74/*************************************************************************
75 * @ [SHLWAPI.11]
76 *
77 * Copy a sharable memory handle from one process to another.
78 *
79 * PARAMS
80 * hShared [I] Shared memory handle to duplicate
81 * dwSrcProcId [I] ID of the process owning hShared
82 * dwDstProcId [I] ID of the process wanting the duplicated handle
83 * dwAccess [I] Desired DuplicateHandle() access
84 * dwOptions [I] Desired DuplicateHandle() options
85 *
86 * RETURNS
87 * Success: A handle suitable for use by the dwDstProcId process.
88 * Failure: A NULL handle.
89 *
90 */
91HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwSrcProcId, DWORD dwDstProcId,
92 DWORD dwAccess, DWORD dwOptions)
93{
94 HANDLE hDst, hSrc;
95 DWORD dwMyProcId = GetCurrentProcessId();
96 HANDLE hRet = NULL;
97
98 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
99 dwAccess, dwOptions);
100
101 if (!hShared)
102 {
103 TRACE("Returning handle NULL\n");
104 return NULL;
105 }
106
107 /* Get dest process handle */
108 if (dwDstProcId == dwMyProcId)
109 hDst = GetCurrentProcess();
110 else
111 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
112
113 if (hDst)
114 {
115 /* Get src process handle */
116 if (dwSrcProcId == dwMyProcId)
117 hSrc = GetCurrentProcess();
118 else
119 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
120
121 if (hSrc)
122 {
123 /* Make handle available to dest process */
124 if (!DuplicateHandle(hSrc, hShared, hDst, &hRet,
125 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
126 hRet = NULL;
127
128 if (dwSrcProcId != dwMyProcId)
129 CloseHandle(hSrc);
130 }
131
132 if (dwDstProcId != dwMyProcId)
133 CloseHandle(hDst);
134 }
135
136 TRACE("Returning handle %p\n", hRet);
137 return hRet;
138}
139
140/*************************************************************************
141 * @ [SHLWAPI.7]
142 *
143 * Create a block of sharable memory and initialise it with data.
144 *
145 * PARAMS
146 * lpvData [I] Pointer to data to write
147 * dwSize [I] Size of data
148 * dwProcId [I] ID of process owning data
149 *
150 * RETURNS
151 * Success: A shared memory handle
152 * Failure: NULL
153 *
154 * NOTES
155 * Ordinals 7-11 provide a set of calls to create shared memory between a
156 * group of processes. The shared memory is treated opaquely in that its size
157 * is not exposed to clients who map it. This is accomplished by storing
158 * the size of the map as the first DWORD of mapped data, and then offsetting
159 * the view pointer returned by this size.
160 *
161 */
163{
164 HANDLE hMap;
165 LPVOID pMapped;
166 HANDLE hRet = NULL;
167
168 TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
169
170 /* Create file mapping of the correct length */
172 dwSize + sizeof(dwSize), NULL);
173 if (!hMap)
174 return hRet;
175
176 /* Get a view in our process address space */
177 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
178
179 if (pMapped)
180 {
181 /* Write size of data, followed by the data, to the view */
182 *((DWORD*)pMapped) = dwSize;
183 if (lpvData)
184 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
185
186 /* Release view. All further views mapped will be opaque */
187 UnmapViewOfFile(pMapped);
188 hRet = SHMapHandle(hMap, GetCurrentProcessId(), dwProcId,
190 }
191
192 CloseHandle(hMap);
193 return hRet;
194}
195
196#ifdef __REACTOS__
197/*************************************************************************
198 * @ [SHLWAPI.510]
199 *
200 * Get a pointer to a block of shared memory from a shared memory handle,
201 * with specified access rights.
202 *
203 * PARAMS
204 * hShared [I] Shared memory handle
205 * dwProcId [I] ID of process owning hShared
206 * bWriteAccess [I] TRUE to get a writable block,
207 * FALSE to get a read-only block
208 *
209 * RETURNS
210 * Success: A pointer to the shared memory
211 * Failure: NULL
212 */
214SHLockSharedEx(HANDLE hShared, DWORD dwProcId, BOOL bWriteAccess)
215{
216 HANDLE hDup;
217 LPVOID pMapped;
218 DWORD dwAccess;
219
220 TRACE("(%p %d %d)\n", hShared, dwProcId, bWriteAccess);
221
222 /* Get handle to shared memory for current process */
223 hDup = SHMapHandle(hShared, dwProcId, GetCurrentProcessId(), FILE_MAP_ALL_ACCESS, 0);
224 if (hDup == NULL)
225 return NULL;
226
227 /* Get View */
228 dwAccess = (FILE_MAP_READ | (bWriteAccess ? FILE_MAP_WRITE : 0));
229 pMapped = MapViewOfFile(hDup, dwAccess, 0, 0, 0);
230 CloseHandle(hDup);
231
232 if (pMapped)
233 return (char *) pMapped + sizeof(DWORD); /* Hide size */
234 return NULL;
235}
236
237#endif
238/*************************************************************************
239 * @ [SHLWAPI.8]
240 *
241 * Get a pointer to a block of shared memory from a shared memory handle.
242 *
243 * PARAMS
244 * hShared [I] Shared memory handle
245 * dwProcId [I] ID of process owning hShared
246 *
247 * RETURNS
248 * Success: A pointer to the shared memory
249 * Failure: NULL
250 *
251 */
253{
254#ifdef __REACTOS__
255 return SHLockSharedEx(hShared, dwProcId, TRUE);
256#else
257 HANDLE hDup;
258 LPVOID pMapped;
259
260 TRACE("(%p %d)\n", hShared, dwProcId);
261
262 /* Get handle to shared memory for current process */
263 hDup = SHMapHandle(hShared, dwProcId, GetCurrentProcessId(), FILE_MAP_ALL_ACCESS, 0);
264
265 /* Get View */
266 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
267 CloseHandle(hDup);
268
269 if (pMapped)
270 return (char *) pMapped + sizeof(DWORD); /* Hide size */
271 return NULL;
272#endif
273}
274
275/*************************************************************************
276 * @ [SHLWAPI.9]
277 *
278 * Release a pointer to a block of shared memory.
279 *
280 * PARAMS
281 * lpView [I] Shared memory pointer
282 *
283 * RETURNS
284 * Success: TRUE
285 * Failure: FALSE
286 *
287 */
289{
290 TRACE("(%p)\n", lpView);
291 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
292}
293
294/*************************************************************************
295 * @ [SHLWAPI.10]
296 *
297 * Destroy a block of sharable memory.
298 *
299 * PARAMS
300 * hShared [I] Shared memory handle
301 * dwProcId [I] ID of process owning hShared
302 *
303 * RETURNS
304 * Success: TRUE
305 * Failure: FALSE
306 *
307 */
309{
310 HANDLE hClose;
311
312 TRACE("(%p %d)\n", hShared, dwProcId);
313
314 if (!hShared)
315 return TRUE;
316
317 /* Get a copy of the handle for our process, closing the source handle */
318 hClose = SHMapHandle(hShared, dwProcId, GetCurrentProcessId(),
320 /* Close local copy */
321 return CloseHandle(hClose);
322}
323
324/*************************************************************************
325 * @ [SHLWAPI.13]
326 *
327 * Create and register a clipboard enumerator for a web browser.
328 *
329 * PARAMS
330 * lpBC [I] Binding context
331 * lpUnknown [I] An object exposing the IWebBrowserApp interface
332 *
333 * RETURNS
334 * Success: S_OK.
335 * Failure: An HRESULT error code.
336 *
337 * NOTES
338 * The enumerator is stored as a property of the web browser. If it does not
339 * yet exist, it is created and set before being registered.
340 */
342{
343 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
344 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
345 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
347 IEnumFORMATETC* pIEnumFormatEtc = NULL;
349 HRESULT hr;
350 IWebBrowserApp* pBrowser;
351
352 TRACE("(%p, %p)\n", lpBC, lpUnknown);
353
354 hr = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (void**)&pBrowser);
355 if (FAILED(hr))
356 return hr;
357
358 V_VT(&var) = VT_EMPTY;
359
360 /* The property we get is the browsers clipboard enumerator */
361 property = SysAllocString(szProperty);
362 hr = IWebBrowserApp_GetProperty(pBrowser, property, &var);
364 if (FAILED(hr)) goto exit;
365
366 if (V_VT(&var) == VT_EMPTY)
367 {
368 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
369 char szKeyBuff[128], szValueBuff[128];
370 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
371 FORMATETC* formatList, *format;
372 HKEY hDocs;
373
374 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
375
376 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
377 "Version\\Internet Settings\\Accepted Documents", &hDocs))
378 {
379 hr = E_FAIL;
380 goto exit;
381 }
382
383 /* Get count of values in key */
384 while (!dwRet)
385 {
386 dwKeySize = sizeof(szKeyBuff);
387 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
388 dwCount++;
389 }
390
391 dwNumValues = dwCount;
392
393 /* Note: dwCount = number of items + 1; The extra item is the end node */
394 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
395 if (!formatList)
396 {
397 RegCloseKey(hDocs);
399 goto exit;
400 }
401
402 if (dwNumValues > 1)
403 {
404 dwRet = 0;
405 dwCount = 0;
406
407 dwNumValues--;
408
409 /* Register clipboard formats for the values and populate format list */
410 while(!dwRet && dwCount < dwNumValues)
411 {
412 dwKeySize = sizeof(szKeyBuff);
413 dwValueSize = sizeof(szValueBuff);
414 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
415 (PBYTE)szValueBuff, &dwValueSize);
416 if (!dwRet)
417 {
418 HeapFree(GetProcessHeap(), 0, formatList);
419 RegCloseKey(hDocs);
420 hr = E_FAIL;
421 goto exit;
422 }
423
424 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
425 format->ptd = NULL;
426 format->dwAspect = 1;
427 format->lindex = 4;
428 format->tymed = -1;
429
430 format++;
431 dwCount++;
432 }
433 }
434
435 RegCloseKey(hDocs);
436
437 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
438 format->cfFormat = 0;
439 format->ptd = NULL;
440 format->dwAspect = 1;
441 format->lindex = 4;
442 format->tymed = -1;
443
444 /* Create a clipboard enumerator */
445 hr = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
446 HeapFree(GetProcessHeap(), 0, formatList);
447 if (FAILED(hr)) goto exit;
448
449 /* Set our enumerator as the browsers property */
450 V_VT(&var) = VT_UNKNOWN;
451 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
452
453 property = SysAllocString(szProperty);
454 hr = IWebBrowserApp_PutProperty(pBrowser, property, var);
456 if (FAILED(hr))
457 {
458 IEnumFORMATETC_Release(pIEnumFormatEtc);
459 goto exit;
460 }
461 }
462
463 if (V_VT(&var) == VT_UNKNOWN)
464 {
465 /* Our variant is holding the clipboard enumerator */
466 IUnknown* pIUnknown = V_UNKNOWN(&var);
467 IEnumFORMATETC* pClone = NULL;
468
469 TRACE("Retrieved IEnumFORMATETC property\n");
470
471 /* Get an IEnumFormatEtc interface from the variants value */
472 pIEnumFormatEtc = NULL;
473 hr = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC, (void**)&pIEnumFormatEtc);
474 if (hr == S_OK && pIEnumFormatEtc)
475 {
476 /* Clone and register the enumerator */
477 hr = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
478 if (hr == S_OK && pClone)
479 {
480 RegisterFormatEnumerator(lpBC, pClone, 0);
481
482 IEnumFORMATETC_Release(pClone);
483 }
484
485 IUnknown_Release(pIUnknown);
486 }
487 IUnknown_Release(V_UNKNOWN(&var));
488 }
489
490exit:
491 IWebBrowserApp_Release(pBrowser);
492 return hr;
493}
494
495/*************************************************************************
496 * @ [SHLWAPI.15]
497 *
498 * Get Explorers "AcceptLanguage" setting.
499 *
500 * PARAMS
501 * langbuf [O] Destination for language string
502 * buflen [I] Length of langbuf in characters
503 * [0] Success: used length of langbuf
504 *
505 * RETURNS
506 * Success: S_OK. langbuf is set to the language string found.
507 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
508 * does not contain the setting.
509 * E_NOT_SUFFICIENT_BUFFER, If the buffer is not big enough
510 */
512{
513 static const WCHAR szkeyW[] = {
514 'S','o','f','t','w','a','r','e','\\',
515 'M','i','c','r','o','s','o','f','t','\\',
516 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
517 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
518 static const WCHAR valueW[] = {
519 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
520 DWORD mystrlen, mytype;
521 DWORD len;
522 HKEY mykey;
523 LCID mylcid;
524 WCHAR *mystr;
525 LONG lres;
526
527 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
528
529 if(!langbuf || !buflen || !*buflen)
530 return E_FAIL;
531
532 mystrlen = (*buflen > 20) ? *buflen : 20 ;
533 len = mystrlen * sizeof(WCHAR);
534 mystr = HeapAlloc(GetProcessHeap(), 0, len);
535 mystr[0] = 0;
536 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
537 lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
538 RegCloseKey(mykey);
539 len = lstrlenW(mystr);
540
541 if (!lres && (*buflen > len)) {
542 lstrcpyW(langbuf, mystr);
543 *buflen = len;
544 HeapFree(GetProcessHeap(), 0, mystr);
545 return S_OK;
546 }
547
548 /* Did not find a value in the registry or the user buffer is too small */
549 mylcid = GetUserDefaultLCID();
550 LcidToRfc1766W(mylcid, mystr, mystrlen);
551 len = lstrlenW(mystr);
552
553 memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
554 HeapFree(GetProcessHeap(), 0, mystr);
555
556 if (*buflen > len) {
557 *buflen = len;
558 return S_OK;
559 }
560
561 *buflen = 0;
563}
564
565/*************************************************************************
566 * @ [SHLWAPI.14]
567 *
568 * Ascii version of GetAcceptLanguagesW.
569 */
571{
572 WCHAR *langbufW;
573 DWORD buflenW, convlen;
574 HRESULT retval;
575
576 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
577
578 if(!langbuf || !buflen || !*buflen) return E_FAIL;
579
580 buflenW = *buflen;
581 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
582 retval = GetAcceptLanguagesW(langbufW, &buflenW);
583
584 if (retval == S_OK)
585 {
586 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
587 convlen--; /* do not count the terminating 0 */
588 }
589 else /* copy partial string anyway */
590 {
591 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
592 if (convlen < *buflen)
593 {
594 langbuf[convlen] = 0;
595 convlen--; /* do not count the terminating 0 */
596 }
597 else
598 {
599 convlen = *buflen;
600 }
601 }
602 *buflen = buflenW ? convlen : 0;
603
604 HeapFree(GetProcessHeap(), 0, langbufW);
605 return retval;
606}
607
608/*************************************************************************
609 * @ [SHLWAPI.23]
610 *
611 * Convert a GUID to a string.
612 *
613 * PARAMS
614 * guid [I] GUID to convert
615 * lpszDest [O] Destination for string
616 * cchMax [I] Length of output buffer
617 *
618 * RETURNS
619 * The length of the string created.
620 */
622{
623 char xguid[40];
624 INT iLen;
625
626 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
627
628 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
629 guid->Data1, guid->Data2, guid->Data3,
630 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
631 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
632
633 iLen = strlen(xguid) + 1;
634
635 if (iLen > cchMax)
636 return 0;
637 memcpy(lpszDest, xguid, iLen);
638 return iLen;
639}
640
641/*************************************************************************
642 * @ [SHLWAPI.24]
643 *
644 * Convert a GUID to a string.
645 *
646 * PARAMS
647 * guid [I] GUID to convert
648 * str [O] Destination for string
649 * cmax [I] Length of output buffer
650 *
651 * RETURNS
652 * The length of the string created.
653 */
655{
656 WCHAR xguid[40];
657 INT iLen;
658 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
659 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
660 'X','%','0','2','X','%','0','2','X','}',0};
661
662 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
663
664 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
665 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
666 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
667
668 iLen = strlenW(xguid) + 1;
669
670 if (iLen > cchMax)
671 return 0;
672 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
673 return iLen;
674}
675
676/*************************************************************************
677 * @ [SHLWAPI.30]
678 *
679 * Determine if a Unicode character is a blank.
680 *
681 * PARAMS
682 * wc [I] Character to check.
683 *
684 * RETURNS
685 * TRUE, if wc is a blank,
686 * FALSE otherwise.
687 *
688 */
690{
691 WORD CharType;
692
693 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
694}
695
696/*************************************************************************
697 * @ [SHLWAPI.31]
698 *
699 * Determine if a Unicode character is punctuation.
700 *
701 * PARAMS
702 * wc [I] Character to check.
703 *
704 * RETURNS
705 * TRUE, if wc is punctuation,
706 * FALSE otherwise.
707 */
709{
710 WORD CharType;
711
712 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
713}
714
715/*************************************************************************
716 * @ [SHLWAPI.32]
717 *
718 * Determine if a Unicode character is a control character.
719 *
720 * PARAMS
721 * wc [I] Character to check.
722 *
723 * RETURNS
724 * TRUE, if wc is a control character,
725 * FALSE otherwise.
726 */
728{
729 WORD CharType;
730
731 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
732}
733
734/*************************************************************************
735 * @ [SHLWAPI.33]
736 *
737 * Determine if a Unicode character is a digit.
738 *
739 * PARAMS
740 * wc [I] Character to check.
741 *
742 * RETURNS
743 * TRUE, if wc is a digit,
744 * FALSE otherwise.
745 */
747{
748 WORD CharType;
749
750 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
751}
752
753/*************************************************************************
754 * @ [SHLWAPI.34]
755 *
756 * Determine if a Unicode character is a hex digit.
757 *
758 * PARAMS
759 * wc [I] Character to check.
760 *
761 * RETURNS
762 * TRUE, if wc is a hex digit,
763 * FALSE otherwise.
764 */
766{
767 WORD CharType;
768
769 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
770}
771
772/*************************************************************************
773 * @ [SHLWAPI.35]
774 *
775 */
777{
779}
780
781/*************************************************************************
782 * @ [SHLWAPI.151]
783 *
784 * Compare two Ascii strings up to a given length.
785 *
786 * PARAMS
787 * lpszSrc [I] Source string
788 * lpszCmp [I] String to compare to lpszSrc
789 * len [I] Maximum length
790 *
791 * RETURNS
792 * A number greater than, less than or equal to 0 depending on whether
793 * lpszSrc is greater than, less than or equal to lpszCmp.
794 */
796{
797 return StrCmpNA(lpszSrc, lpszCmp, len);
798}
799
800/*************************************************************************
801 * @ [SHLWAPI.152]
802 *
803 * Unicode version of StrCmpNCA.
804 */
806{
807 return StrCmpNW(lpszSrc, lpszCmp, len);
808}
809
810/*************************************************************************
811 * @ [SHLWAPI.153]
812 *
813 * Compare two Ascii strings up to a given length, ignoring case.
814 *
815 * PARAMS
816 * lpszSrc [I] Source string
817 * lpszCmp [I] String to compare to lpszSrc
818 * len [I] Maximum length
819 *
820 * RETURNS
821 * A number greater than, less than or equal to 0 depending on whether
822 * lpszSrc is greater than, less than or equal to lpszCmp.
823 */
825{
826 return StrCmpNIA(lpszSrc, lpszCmp, len);
827}
828
829/*************************************************************************
830 * @ [SHLWAPI.154]
831 *
832 * Unicode version of StrCmpNICA.
833 */
835{
836 return StrCmpNIW(lpszSrc, lpszCmp, len);
837}
838
839/*************************************************************************
840 * @ [SHLWAPI.155]
841 *
842 * Compare two Ascii strings.
843 *
844 * PARAMS
845 * lpszSrc [I] Source string
846 * lpszCmp [I] String to compare to lpszSrc
847 *
848 * RETURNS
849 * A number greater than, less than or equal to 0 depending on whether
850 * lpszSrc is greater than, less than or equal to lpszCmp.
851 */
853{
854 return lstrcmpA(lpszSrc, lpszCmp);
855}
856
857/*************************************************************************
858 * @ [SHLWAPI.156]
859 *
860 * Unicode version of StrCmpCA.
861 */
863{
864 return lstrcmpW(lpszSrc, lpszCmp);
865}
866
867/*************************************************************************
868 * @ [SHLWAPI.157]
869 *
870 * Compare two Ascii strings, ignoring case.
871 *
872 * PARAMS
873 * lpszSrc [I] Source string
874 * lpszCmp [I] String to compare to lpszSrc
875 *
876 * RETURNS
877 * A number greater than, less than or equal to 0 depending on whether
878 * lpszSrc is greater than, less than or equal to lpszCmp.
879 */
881{
882 return lstrcmpiA(lpszSrc, lpszCmp);
883}
884
885/*************************************************************************
886 * @ [SHLWAPI.158]
887 *
888 * Unicode version of StrCmpICA.
889 */
891{
892 return lstrcmpiW(lpszSrc, lpszCmp);
893}
894
895/*************************************************************************
896 * @ [SHLWAPI.160]
897 *
898 * Get an identification string for the OS and explorer.
899 *
900 * PARAMS
901 * lpszDest [O] Destination for Id string
902 * dwDestLen [I] Length of lpszDest
903 *
904 * RETURNS
905 * TRUE, If the string was created successfully
906 * FALSE, Otherwise
907 */
909{
910 WCHAR buff[2084];
911
912 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
913
914 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
915 {
916 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
917 return TRUE;
918 }
919 return FALSE;
920}
921
922/*************************************************************************
923 * @ [SHLWAPI.161]
924 *
925 * Unicode version of SHAboutInfoA.
926 */
928{
929 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
930 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
931 ' ','E','x','p','l','o','r','e','r','\0' };
932 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
933 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
934 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
935 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
936 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
937 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
938 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
939 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
940 ' ','E','x','p','l','o','r','e','r','\\',
941 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
942 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
943 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
944 'V','e','r','s','i','o','n','\0' };
945 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
946 'O','w','n','e','r','\0' };
947 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
948 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
949 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
950 static const WCHAR szUpdate[] = { 'I','E','A','K',
951 'U','p','d','a','t','e','U','r','l','\0' };
952 static const WCHAR szHelp[] = { 'I','E','A','K',
953 'H','e','l','p','S','t','r','i','n','g','\0' };
954 WCHAR buff[2084];
955 HKEY hReg;
956 DWORD dwType, dwLen;
957
958 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
959
960 if (!lpszDest)
961 return FALSE;
962
963 *lpszDest = '\0';
964
965 /* Try the NT key first, followed by 95/98 key */
966 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
967 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
968 return FALSE;
969
970 /* OS Version */
971 buff[0] = '\0';
972 dwLen = 30;
973 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
974 {
975 DWORD dwStrLen = strlenW(buff);
976 dwLen = 30 - dwStrLen;
978 szCustomized, &dwType, buff+dwStrLen, &dwLen);
979 }
980 StrCatBuffW(lpszDest, buff, dwDestLen);
981
982 /* ~Registered Owner */
983 buff[0] = '~';
984 dwLen = 256;
985 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
986 buff[1] = '\0';
987 StrCatBuffW(lpszDest, buff, dwDestLen);
988
989 /* ~Registered Organization */
990 dwLen = 256;
991 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
992 buff[1] = '\0';
993 StrCatBuffW(lpszDest, buff, dwDestLen);
994
995 /* FIXME: Not sure where this number comes from */
996 buff[0] = '~';
997 buff[1] = '0';
998 buff[2] = '\0';
999 StrCatBuffW(lpszDest, buff, dwDestLen);
1000
1001 /* ~Product Id */
1002 dwLen = 256;
1003 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
1004 buff[1] = '\0';
1005 StrCatBuffW(lpszDest, buff, dwDestLen);
1006
1007 /* ~IE Update Url */
1008 dwLen = 2048;
1009 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
1010 buff[1] = '\0';
1011 StrCatBuffW(lpszDest, buff, dwDestLen);
1012
1013 /* ~IE Help String */
1014 dwLen = 256;
1015 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
1016 buff[1] = '\0';
1017 StrCatBuffW(lpszDest, buff, dwDestLen);
1018
1019 RegCloseKey(hReg);
1020 return TRUE;
1021}
1022
1023/*************************************************************************
1024 * @ [SHLWAPI.163]
1025 *
1026 * Call IOleCommandTarget_QueryStatus() on an object.
1027 *
1028 * PARAMS
1029 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1030 * pguidCmdGroup [I] GUID for the command group
1031 * cCmds [I]
1032 * prgCmds [O] Commands
1033 * pCmdText [O] Command text
1034 *
1035 * RETURNS
1036 * Success: S_OK.
1037 * Failure: E_FAIL, if lpUnknown is NULL.
1038 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1039 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1040 */
1042 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1043{
1044 HRESULT hRet = E_FAIL;
1045
1046 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1047
1048 if (lpUnknown)
1049 {
1050 IOleCommandTarget* lpOle;
1051
1052 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1053 (void**)&lpOle);
1054
1055 if (SUCCEEDED(hRet) && lpOle)
1056 {
1057 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1058 prgCmds, pCmdText);
1059 IOleCommandTarget_Release(lpOle);
1060 }
1061 }
1062 return hRet;
1063}
1064
1065/*************************************************************************
1066 * @ [SHLWAPI.164]
1067 *
1068 * Call IOleCommandTarget_Exec() on an object.
1069 *
1070 * PARAMS
1071 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1072 * pguidCmdGroup [I] GUID for the command group
1073 *
1074 * RETURNS
1075 * Success: S_OK.
1076 * Failure: E_FAIL, if lpUnknown is NULL.
1077 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1078 * Otherwise, an error code from IOleCommandTarget_Exec().
1079 */
1080HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1081 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1082 VARIANT* pvaOut)
1083{
1084 HRESULT hRet = E_FAIL;
1085
1086 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1087 nCmdexecopt, pvaIn, pvaOut);
1088
1089 if (lpUnknown)
1090 {
1091 IOleCommandTarget* lpOle;
1092
1093 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1094 (void**)&lpOle);
1095 if (SUCCEEDED(hRet) && lpOle)
1096 {
1097 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1098 nCmdexecopt, pvaIn, pvaOut);
1099 IOleCommandTarget_Release(lpOle);
1100 }
1101 }
1102 return hRet;
1103}
1104
1105/*************************************************************************
1106 * @ [SHLWAPI.165]
1107 *
1108 * Retrieve, modify, and re-set a value from a window.
1109 *
1110 * PARAMS
1111 * hWnd [I] Window to get value from
1112 * offset [I] Offset of value
1113 * mask [I] Mask for flags
1114 * flags [I] Bits to set in window value
1115 *
1116 * RETURNS
1117 * The new value as it was set, or 0 if any parameter is invalid.
1118 *
1119 * NOTES
1120 * Only bits specified in mask are affected - set if present in flags and
1121 * reset otherwise.
1122 */
1124{
1126 LONG new_flags = (flags & mask) | (ret & ~mask);
1127
1128 TRACE("%p %d %x %x\n", hwnd, offset, mask, flags);
1129
1130 if (new_flags != ret)
1131 ret = SetWindowLongW(hwnd, offset, new_flags);
1132 return ret;
1133}
1134
1135/*************************************************************************
1136 * @ [SHLWAPI.167]
1137 *
1138 * Change a window's parent.
1139 *
1140 * PARAMS
1141 * hWnd [I] Window to change parent of
1142 * hWndParent [I] New parent window
1143 *
1144 * RETURNS
1145 * The old parent of hWnd.
1146 *
1147 * NOTES
1148 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1149 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1150 */
1152{
1153 TRACE("%p, %p\n", hWnd, hWndParent);
1154
1155 if(GetParent(hWnd) == hWndParent)
1156 return NULL;
1157
1158 if(hWndParent)
1160 else
1162
1164}
1165
1166/*************************************************************************
1167 * @ [SHLWAPI.168]
1168 *
1169 * Locate and advise a connection point in an IConnectionPointContainer object.
1170 *
1171 * PARAMS
1172 * lpUnkSink [I] Sink for the connection point advise call
1173 * riid [I] REFIID of connection point to advise
1174 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1175 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1176 * lpCookie [O] Pointer to connection point cookie
1177 * lppCP [O] Destination for the IConnectionPoint found
1178 *
1179 * RETURNS
1180 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1181 * that was advised. The caller is responsible for releasing it.
1182 * Failure: E_FAIL, if any arguments are invalid.
1183 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1184 * Or an HRESULT error code if any call fails.
1185 */
1187 IUnknown* lpUnknown, LPDWORD lpCookie,
1188 IConnectionPoint **lppCP)
1189{
1190 HRESULT hRet;
1191 IConnectionPointContainer* lpContainer;
1192 IConnectionPoint *lpCP;
1193
1194 if(!lpUnknown || (fConnect && !lpUnkSink))
1195 return E_FAIL;
1196
1197 if(lppCP)
1198 *lppCP = NULL;
1199
1200 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1201 (void**)&lpContainer);
1202 if (SUCCEEDED(hRet))
1203 {
1204 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1205
1206 if (SUCCEEDED(hRet))
1207 {
1208 if(!fConnect)
1209 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1210 else
1211 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1212
1213 if (FAILED(hRet))
1214 *lpCookie = 0;
1215
1216 if (lppCP && SUCCEEDED(hRet))
1217 *lppCP = lpCP; /* Caller keeps the interface */
1218 else
1219 IConnectionPoint_Release(lpCP); /* Release it */
1220 }
1221
1222 IConnectionPointContainer_Release(lpContainer);
1223 }
1224 return hRet;
1225}
1226
1227/*************************************************************************
1228 * @ [SHLWAPI.169]
1229 *
1230 * Release an interface and zero a supplied pointer.
1231 *
1232 * PARAMS
1233 * lpUnknown [I] Object to release
1234 *
1235 * RETURNS
1236 * Nothing.
1237 */
1239{
1240 TRACE("(%p)\n", lpUnknown);
1241
1242 if(!lpUnknown || !*lpUnknown) return;
1243
1244 TRACE("doing Release\n");
1245
1246 IUnknown_Release(*lpUnknown);
1247 *lpUnknown = NULL;
1248}
1249
1250/*************************************************************************
1251 * @ [SHLWAPI.170]
1252 *
1253 * Skip '//' if present in a string.
1254 *
1255 * PARAMS
1256 * lpszSrc [I] String to check for '//'
1257 *
1258 * RETURNS
1259 * Success: The next character after the '//' or the string if not present
1260 * Failure: NULL, if lpszStr is NULL.
1261 */
1263{
1264 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1265 lpszSrc += 2;
1266 return lpszSrc;
1267}
1268
1269/*************************************************************************
1270 * @ [SHLWAPI.171]
1271 *
1272 * Check if two interfaces come from the same object.
1273 *
1274 * PARAMS
1275 * lpInt1 [I] Interface to check against lpInt2.
1276 * lpInt2 [I] Interface to check against lpInt1.
1277 *
1278 * RETURNS
1279 * TRUE, If the interfaces come from the same object.
1280 * FALSE Otherwise.
1281 */
1283{
1284 IUnknown *lpUnknown1, *lpUnknown2;
1285 BOOL ret;
1286
1287 TRACE("(%p %p)\n", lpInt1, lpInt2);
1288
1289 if (!lpInt1 || !lpInt2)
1290 return FALSE;
1291
1292 if (lpInt1 == lpInt2)
1293 return TRUE;
1294
1295 if (IUnknown_QueryInterface(lpInt1, &IID_IUnknown, (void**)&lpUnknown1) != S_OK)
1296 return FALSE;
1297
1298 if (IUnknown_QueryInterface(lpInt2, &IID_IUnknown, (void**)&lpUnknown2) != S_OK)
1299 {
1300 IUnknown_Release(lpUnknown1);
1301 return FALSE;
1302 }
1303
1304 ret = lpUnknown1 == lpUnknown2;
1305
1306 IUnknown_Release(lpUnknown1);
1307 IUnknown_Release(lpUnknown2);
1308
1309 return ret;
1310}
1311
1312/*************************************************************************
1313 * @ [SHLWAPI.172]
1314 *
1315 * Get the window handle of an object.
1316 *
1317 * PARAMS
1318 * lpUnknown [I] Object to get the window handle of
1319 * lphWnd [O] Destination for window handle
1320 *
1321 * RETURNS
1322 * Success: S_OK. lphWnd contains the objects window handle.
1323 * Failure: An HRESULT error code.
1324 *
1325 * NOTES
1326 * lpUnknown is expected to support one of the following interfaces:
1327 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1328 */
1330{
1331 IUnknown *lpOle;
1332 HRESULT hRet = E_FAIL;
1333
1334 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1335
1336 if (!lpUnknown)
1337 return hRet;
1338
1339 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1340
1341 if (FAILED(hRet))
1342 {
1343 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1344
1345 if (FAILED(hRet))
1346 {
1347 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1348 (void**)&lpOle);
1349 }
1350 }
1351
1352 if (SUCCEEDED(hRet))
1353 {
1354 /* Laziness here - Since GetWindow() is the first method for the above 3
1355 * interfaces, we use the same call for them all.
1356 */
1357 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1358 IUnknown_Release(lpOle);
1359 if (lphWnd)
1360 TRACE("Returning HWND=%p\n", *lphWnd);
1361 }
1362
1363 return hRet;
1364}
1365
1366/*************************************************************************
1367 * @ [SHLWAPI.173]
1368 *
1369 * Call a SetOwner method of IShellService from specified object.
1370 *
1371 * PARAMS
1372 * iface [I] Object that supports IShellService
1373 * pUnk [I] Argument for the SetOwner call
1374 *
1375 * RETURNS
1376 * Corresponding return value from last call or E_FAIL for null input
1377 */
1379{
1380 IShellService *service;
1381 HRESULT hr;
1382
1383 TRACE("(%p, %p)\n", iface, pUnk);
1384
1385 if (!iface) return E_FAIL;
1386
1387 hr = IUnknown_QueryInterface(iface, &IID_IShellService, (void**)&service);
1388 if (hr == S_OK)
1389 {
1390 hr = IShellService_SetOwner(service, pUnk);
1391 IShellService_Release(service);
1392 }
1393
1394 return hr;
1395}
1396
1397/*************************************************************************
1398 * @ [SHLWAPI.174]
1399 *
1400 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1401 * an object.
1402 *
1403 */
1405 IUnknown *obj, /* [in] OLE object */
1406 IUnknown *site) /* [in] Site interface */
1407{
1408 HRESULT hr;
1409 IObjectWithSite *iobjwithsite;
1410 IInternetSecurityManager *isecmgr;
1411
1412 if (!obj) return E_FAIL;
1413
1414 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1415 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1416 if (SUCCEEDED(hr))
1417 {
1418 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1419 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1420 IObjectWithSite_Release(iobjwithsite);
1421 }
1422 else
1423 {
1424 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1425 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1426 if (FAILED(hr)) return hr;
1427
1428 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1429 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1430 IInternetSecurityManager_Release(isecmgr);
1431 }
1432 return hr;
1433}
1434
1435/*************************************************************************
1436 * @ [SHLWAPI.175]
1437 *
1438 * Call IPersist_GetClassID() on an object.
1439 *
1440 * PARAMS
1441 * lpUnknown [I] Object supporting the IPersist interface
1442 * clsid [O] Destination for Class Id
1443 *
1444 * RETURNS
1445 * Success: S_OK. lpClassId contains the Class Id requested.
1446 * Failure: E_FAIL, If lpUnknown is NULL,
1447 * E_NOINTERFACE If lpUnknown does not support IPersist,
1448 * Or an HRESULT error code.
1449 */
1451{
1452 IPersist *persist;
1453 HRESULT hr;
1454
1455 TRACE("(%p, %p)\n", lpUnknown, clsid);
1456
1457 if (!lpUnknown)
1458 {
1459 memset(clsid, 0, sizeof(*clsid));
1460 return E_FAIL;
1461 }
1462
1463 hr = IUnknown_QueryInterface(lpUnknown, &IID_IPersist, (void**)&persist);
1464 if (hr != S_OK)
1465 {
1466 hr = IUnknown_QueryInterface(lpUnknown, &IID_IPersistFolder, (void**)&persist);
1467 if (hr != S_OK)
1468 return hr;
1469 }
1470
1471 hr = IPersist_GetClassID(persist, clsid);
1472 IPersist_Release(persist);
1473 return hr;
1474}
1475
1476/*************************************************************************
1477 * @ [SHLWAPI.176]
1478 *
1479 * Retrieve a Service Interface from an object.
1480 *
1481 * PARAMS
1482 * lpUnknown [I] Object to get an IServiceProvider interface from
1483 * sid [I] Service ID for IServiceProvider_QueryService() call
1484 * riid [I] Function requested for QueryService call
1485 * lppOut [O] Destination for the service interface pointer
1486 *
1487 * RETURNS
1488 * Success: S_OK. lppOut contains an object providing the requested service
1489 * Failure: An HRESULT error code
1490 *
1491 * NOTES
1492 * lpUnknown is expected to support the IServiceProvider interface.
1493 */
1495 LPVOID *lppOut)
1496{
1497 IServiceProvider* pService = NULL;
1498 HRESULT hRet;
1499
1500 if (!lppOut)
1501 return E_FAIL;
1502
1503 *lppOut = NULL;
1504
1505 if (!lpUnknown)
1506 return E_FAIL;
1507
1508 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1509 (LPVOID*)&pService);
1510
1511 if (hRet == S_OK && pService)
1512 {
1513 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1514
1515 /* Get a Service interface from the object */
1516 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1517
1518 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1519
1520 IServiceProvider_Release(pService);
1521 }
1522 return hRet;
1523}
1524
1525/*************************************************************************
1526 * @ [SHLWAPI.484]
1527 *
1528 * Calls IOleCommandTarget::Exec() for specified service object.
1529 *
1530 * PARAMS
1531 * lpUnknown [I] Object to get an IServiceProvider interface from
1532 * service [I] Service ID for IServiceProvider_QueryService() call
1533 * group [I] Group ID for IOleCommandTarget::Exec() call
1534 * cmdId [I] Command ID for IOleCommandTarget::Exec() call
1535 * cmdOpt [I] Options flags for command
1536 * pIn [I] Input arguments for command
1537 * pOut [O] Output arguments for command
1538 *
1539 * RETURNS
1540 * Success: S_OK. lppOut contains an object providing the requested service
1541 * Failure: An HRESULT error code
1542 *
1543 * NOTES
1544 * lpUnknown is expected to support the IServiceProvider interface.
1545 */
1547 const GUID *group, DWORD cmdId, DWORD cmdOpt, VARIANT *pIn, VARIANT *pOut)
1548{
1550 HRESULT hr;
1551
1552 TRACE("%p %s %s %d %08x %p %p\n", lpUnknown, debugstr_guid(service),
1553 debugstr_guid(group), cmdId, cmdOpt, pIn, pOut);
1554
1555 hr = IUnknown_QueryService(lpUnknown, service, &IID_IOleCommandTarget, (void**)&target);
1556 if (hr == S_OK)
1557 {
1558 hr = IOleCommandTarget_Exec(target, group, cmdId, cmdOpt, pIn, pOut);
1559 IOleCommandTarget_Release(target);
1560 }
1561
1562 TRACE("<-- hr=0x%08x\n", hr);
1563
1564 return hr;
1565}
1566
1567/*************************************************************************
1568 * @ [SHLWAPI.514]
1569 *
1570 * Calls IProfferService methods to proffer/revoke specified service.
1571 *
1572 * PARAMS
1573 * lpUnknown [I] Object to get an IServiceProvider interface from
1574 * service [I] Service ID for IProfferService::Proffer/Revoke calls
1575 * pService [I] Service to proffer. If NULL ::Revoke is called
1576 * pCookie [IO] Group ID for IOleCommandTarget::Exec() call
1577 *
1578 * RETURNS
1579 * Success: S_OK. IProffer method returns S_OK
1580 * Failure: An HRESULT error code
1581 *
1582 * NOTES
1583 * lpUnknown is expected to support the IServiceProvider interface.
1584 */
1586{
1587 IProfferService *proffer;
1588 HRESULT hr;
1589
1590 TRACE("%p %s %p %p\n", lpUnknown, debugstr_guid(service), pService, pCookie);
1591
1592 hr = IUnknown_QueryService(lpUnknown, &IID_IProfferService, &IID_IProfferService, (void**)&proffer);
1593 if (hr == S_OK)
1594 {
1595 if (pService)
1596 hr = IProfferService_ProfferService(proffer, service, pService, pCookie);
1597 else
1598 {
1599 hr = IProfferService_RevokeService(proffer, *pCookie);
1600 *pCookie = 0;
1601 }
1602
1603 IProfferService_Release(proffer);
1604 }
1605
1606 return hr;
1607}
1608
1609/*************************************************************************
1610 * @ [SHLWAPI.479]
1611 *
1612 * Call an object's UIActivateIO method.
1613 *
1614 * PARAMS
1615 * unknown [I] Object to call the UIActivateIO method on
1616 * activate [I] Parameter for UIActivateIO call
1617 * msg [I] Parameter for UIActivateIO call
1618 *
1619 * RETURNS
1620 * Success: Value of UI_ActivateIO call
1621 * Failure: An HRESULT error code
1622 *
1623 * NOTES
1624 * unknown is expected to support the IInputObject interface.
1625 */
1627{
1628 IInputObject* object = NULL;
1629 HRESULT ret;
1630
1631 if (!unknown)
1632 return E_FAIL;
1633
1634 /* Get an IInputObject interface from the object */
1635 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
1636
1637 if (ret == S_OK)
1638 {
1639 ret = IInputObject_UIActivateIO(object, activate, msg);
1640 IInputObject_Release(object);
1641 }
1642
1643 return ret;
1644}
1645
1646/*************************************************************************
1647 * @ [SHLWAPI.177]
1648 *
1649 * Loads a popup menu.
1650 *
1651 * PARAMS
1652 * hInst [I] Instance handle
1653 * szName [I] Menu name
1654 *
1655 * RETURNS
1656 * Success: TRUE.
1657 * Failure: FALSE.
1658 */
1660{
1661 HMENU hMenu;
1662
1663 TRACE("%p %s\n", hInst, debugstr_w(szName));
1664
1665 if ((hMenu = LoadMenuW(hInst, szName)))
1666 {
1667 if (GetSubMenu(hMenu, 0))
1668 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1669
1670 DestroyMenu(hMenu);
1671 return TRUE;
1672 }
1673 return FALSE;
1674}
1675
1676typedef struct _enumWndData
1677{
1683
1684/* Callback for SHLWAPI_178 */
1686{
1688
1689 TRACE("(%p,%p)\n", hWnd, data);
1690 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1691 return TRUE;
1692}
1693
1694/*************************************************************************
1695 * @ [SHLWAPI.178]
1696 *
1697 * Send or post a message to every child of a window.
1698 *
1699 * PARAMS
1700 * hWnd [I] Window whose children will get the messages
1701 * uiMsgId [I] Message Id
1702 * wParam [I] WPARAM of message
1703 * lParam [I] LPARAM of message
1704 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1705 *
1706 * RETURNS
1707 * Nothing.
1708 *
1709 * NOTES
1710 * The appropriate ASCII or Unicode function is called for the window.
1711 */
1713{
1715
1716 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1717
1718 if(hWnd)
1719 {
1720 data.uiMsgId = uiMsgId;
1721 data.wParam = wParam;
1722 data.lParam = lParam;
1723
1724 if (bSend)
1725 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1726 else
1727 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1728
1730 }
1731}
1732
1733/*************************************************************************
1734 * @ [SHLWAPI.180]
1735 *
1736 * Remove all sub-menus from a menu.
1737 *
1738 * PARAMS
1739 * hMenu [I] Menu to remove sub-menus from
1740 *
1741 * RETURNS
1742 * Success: 0. All sub-menus under hMenu are removed
1743 * Failure: -1, if any parameter is invalid
1744 */
1746{
1747 int iItemCount = GetMenuItemCount(hMenu) - 1;
1748
1749 TRACE("%p\n", hMenu);
1750
1751 while (iItemCount >= 0)
1752 {
1753 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1754 if (hSubMenu)
1755 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1756 iItemCount--;
1757 }
1758 return iItemCount;
1759}
1760
1761/*************************************************************************
1762 * @ [SHLWAPI.181]
1763 *
1764 * Enable or disable a menu item.
1765 *
1766 * PARAMS
1767 * hMenu [I] Menu holding menu item
1768 * uID [I] ID of menu item to enable/disable
1769 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1770 *
1771 * RETURNS
1772 * The return code from EnableMenuItem.
1773 */
1775{
1776 TRACE("%p, %u, %d\n", hMenu, wItemID, bEnable);
1777 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1778}
1779
1780/*************************************************************************
1781 * @ [SHLWAPI.182]
1782 *
1783 * Check or uncheck a menu item.
1784 *
1785 * PARAMS
1786 * hMenu [I] Menu holding menu item
1787 * uID [I] ID of menu item to check/uncheck
1788 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1789 *
1790 * RETURNS
1791 * The return code from CheckMenuItem.
1792 */
1794{
1795 TRACE("%p, %u, %d\n", hMenu, uID, bCheck);
1796 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1797}
1798
1799/*************************************************************************
1800 * @ [SHLWAPI.183]
1801 *
1802 * Register a window class if it isn't already.
1803 *
1804 * PARAMS
1805 * lpWndClass [I] Window class to register
1806 *
1807 * RETURNS
1808 * The result of the RegisterClassA call.
1809 */
1811{
1812 WNDCLASSA wca;
1813 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1814 return TRUE;
1815 return (DWORD)RegisterClassA(wndclass);
1816}
1817
1818/*************************************************************************
1819 * @ [SHLWAPI.186]
1820 */
1822 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1823{
1824 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1825 POINTL pt = { 0, 0 };
1826
1827 TRACE("%p %p 0x%08x %p %p\n", pDrop, pDataObj, grfKeyState, lpPt, pdwEffect);
1828
1829 if (!lpPt)
1830 lpPt = &pt;
1831
1832 if (!pdwEffect)
1833 pdwEffect = &dwEffect;
1834
1835 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1836
1837 if (*pdwEffect != DROPEFFECT_NONE)
1838 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1839
1840 IDropTarget_DragLeave(pDrop);
1841 return TRUE;
1842}
1843
1844/*************************************************************************
1845 * @ [SHLWAPI.187]
1846 *
1847 * Call IPersistPropertyBag_Load() on an object.
1848 *
1849 * PARAMS
1850 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1851 * lpPropBag [O] Destination for loaded IPropertyBag
1852 *
1853 * RETURNS
1854 * Success: S_OK.
1855 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1856 */
1858{
1859 IPersistPropertyBag* lpPPBag;
1860 HRESULT hRet = E_FAIL;
1861
1862 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1863
1864 if (lpUnknown)
1865 {
1866 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1867 (void**)&lpPPBag);
1868 if (SUCCEEDED(hRet) && lpPPBag)
1869 {
1870 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1871 IPersistPropertyBag_Release(lpPPBag);
1872 }
1873 }
1874 return hRet;
1875}
1876
1877/*************************************************************************
1878 * @ [SHLWAPI.188]
1879 *
1880 * Call IOleControlSite_TranslateAccelerator() on an object.
1881 *
1882 * PARAMS
1883 * lpUnknown [I] Object supporting the IOleControlSite interface.
1884 * lpMsg [I] Key message to be processed.
1885 * dwModifiers [I] Flags containing the state of the modifier keys.
1886 *
1887 * RETURNS
1888 * Success: S_OK.
1889 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1890 */
1892{
1893 IOleControlSite* lpCSite = NULL;
1894 HRESULT hRet = E_INVALIDARG;
1895
1896 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1897 if (lpUnknown)
1898 {
1899 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1900 (void**)&lpCSite);
1901 if (SUCCEEDED(hRet) && lpCSite)
1902 {
1903 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1904 IOleControlSite_Release(lpCSite);
1905 }
1906 }
1907 return hRet;
1908}
1909
1910
1911/*************************************************************************
1912 * @ [SHLWAPI.189]
1913 *
1914 * Call IOleControlSite_OnFocus() on an object.
1915 *
1916 * PARAMS
1917 * lpUnknown [I] Object supporting the IOleControlSite interface.
1918 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1919 *
1920 * RETURNS
1921 * Success: S_OK.
1922 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1923 */
1925{
1926 IOleControlSite* lpCSite = NULL;
1927 HRESULT hRet = E_FAIL;
1928
1929 TRACE("(%p, %d)\n", lpUnknown, fGotFocus);
1930 if (lpUnknown)
1931 {
1932 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1933 (void**)&lpCSite);
1934 if (SUCCEEDED(hRet) && lpCSite)
1935 {
1936 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1937 IOleControlSite_Release(lpCSite);
1938 }
1939 }
1940 return hRet;
1941}
1942
1943/*************************************************************************
1944 * @ [SHLWAPI.190]
1945 */
1947 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1948{
1949 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1950 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1951 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1952 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1953 HRESULT hRet = E_INVALIDARG;
1954 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1955
1956 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1957
1958 if (lpUnknown && lpArg4)
1959 {
1960 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1961 (REFGUID)function_id, (void**)&lpUnkInner);
1962
1963 if (SUCCEEDED(hRet) && lpUnkInner)
1964 {
1965 /* FIXME: The type of service object requested is unknown, however
1966 * testing shows that its first method is called with 4 parameters.
1967 * Fake this by using IParseDisplayName_ParseDisplayName since the
1968 * signature and position in the vtable matches our unknown object type.
1969 */
1970 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1971 lpArg1, lpArg2, lpArg3, lpArg4);
1972 IUnknown_Release(lpUnkInner);
1973 }
1974 }
1975 return hRet;
1976}
1977
1978/*************************************************************************
1979 * @ [SHLWAPI.192]
1980 *
1981 * Get a sub-menu from a menu item.
1982 *
1983 * PARAMS
1984 * hMenu [I] Menu to get sub-menu from
1985 * uID [I] ID of menu item containing sub-menu
1986 *
1987 * RETURNS
1988 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1989 */
1991{
1993
1994 TRACE("(%p,%u)\n", hMenu, uID);
1995
1996 mi.cbSize = sizeof(mi);
1997 mi.fMask = MIIM_SUBMENU;
1998
1999 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
2000 return NULL;
2001
2002 return mi.hSubMenu;
2003}
2004
2005/*************************************************************************
2006 * @ [SHLWAPI.193]
2007 *
2008 * Get the color depth of the primary display.
2009 *
2010 * PARAMS
2011 * None.
2012 *
2013 * RETURNS
2014 * The color depth of the primary display.
2015 */
2017{
2018 HDC hdc;
2019 DWORD ret;
2020
2021 TRACE("()\n");
2022
2023 hdc = GetDC(0);
2025 ReleaseDC(0, hdc);
2026 return ret;
2027}
2028
2029/*************************************************************************
2030 * @ [SHLWAPI.194]
2031 *
2032 * Wait for a message to arrive, with a timeout.
2033 *
2034 * PARAMS
2035 * hand [I] Handle to query
2036 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
2037 *
2038 * RETURNS
2039 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
2040 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
2041 * message is available.
2042 */
2044{
2045 DWORD dwEndTicks = GetTickCount() + dwTimeout;
2046 DWORD dwRet;
2047
2048 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
2049 {
2050 MSG msg;
2051
2052 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
2053
2054 if (dwTimeout != INFINITE)
2055 {
2056 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
2057 return WAIT_TIMEOUT;
2058 }
2059 }
2060
2061 return dwRet;
2062}
2063
2064/*************************************************************************
2065 * @ [SHLWAPI.195]
2066 *
2067 * Determine if a shell folder can be expanded.
2068 *
2069 * PARAMS
2070 * lpFolder [I] Parent folder containing the object to test.
2071 * pidl [I] Id of the object to test.
2072 *
2073 * RETURNS
2074 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2075 * Failure: E_INVALIDARG, if any argument is invalid.
2076 *
2077 * NOTES
2078 * If the object to be tested does not expose the IQueryInfo() interface it
2079 * will not be identified as an expandable folder.
2080 */
2082{
2083 HRESULT hRet = E_INVALIDARG;
2084 IQueryInfo *lpInfo;
2085
2086 if (lpFolder && pidl)
2087 {
2088 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
2089 NULL, (void**)&lpInfo);
2090 if (FAILED(hRet))
2091 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
2092 else
2093 {
2094 DWORD dwFlags = 0;
2095
2096 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2097 * currently used". Really? You wouldn't be holding out on me would you?
2098 */
2099 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
2100
2101 if (SUCCEEDED(hRet))
2102 {
2103 /* 0x2 is an undocumented flag apparently indicating expandability */
2104 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
2105 }
2106
2107 IQueryInfo_Release(lpInfo);
2108 }
2109 }
2110 return hRet;
2111}
2112
2113/*************************************************************************
2114 * @ [SHLWAPI.197]
2115 *
2116 * Blank out a region of text by drawing the background only.
2117 *
2118 * PARAMS
2119 * hDC [I] Device context to draw in
2120 * pRect [I] Area to draw in
2121 * cRef [I] Color to draw in
2122 *
2123 * RETURNS
2124 * Nothing.
2125 */
2127{
2128 COLORREF cOldColor = SetBkColor(hDC, cRef);
2129 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2130 SetBkColor(hDC, cOldColor);
2131 return 0;
2132}
2133
2134/*************************************************************************
2135 * @ [SHLWAPI.198]
2136 *
2137 * Return the value associated with a key in a map.
2138 *
2139 * PARAMS
2140 * lpKeys [I] A list of keys of length iLen
2141 * lpValues [I] A list of values associated with lpKeys, of length iLen
2142 * iLen [I] Length of both lpKeys and lpValues
2143 * iKey [I] The key value to look up in lpKeys
2144 *
2145 * RETURNS
2146 * The value in lpValues associated with iKey, or -1 if iKey is not
2147 * found in lpKeys.
2148 *
2149 * NOTES
2150 * - If two elements in the map share the same key, this function returns
2151 * the value closest to the start of the map
2152 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2153 */
2154int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2155{
2156 if (lpKeys && lpValues)
2157 {
2158 int i = 0;
2159
2160 while (i < iLen)
2161 {
2162 if (lpKeys[i] == iKey)
2163 return lpValues[i]; /* Found */
2164 i++;
2165 }
2166 }
2167 return -1; /* Not found */
2168}
2169
2170
2171/*************************************************************************
2172 * @ [SHLWAPI.199]
2173 *
2174 * Copy an interface pointer
2175 *
2176 * PARAMS
2177 * lppDest [O] Destination for copy
2178 * lpUnknown [I] Source for copy
2179 *
2180 * RETURNS
2181 * Nothing.
2182 */
2184{
2185 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2186
2187 IUnknown_AtomicRelease(lppDest);
2188
2189 if (lpUnknown)
2190 {
2191 IUnknown_AddRef(lpUnknown);
2192 *lppDest = lpUnknown;
2193 }
2194}
2195
2196/*************************************************************************
2197 * @ [SHLWAPI.200]
2198 *
2199 */
2201 REFGUID riidCmdGrp, ULONG cCmds,
2202 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2203{
2204 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2205 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2206
2207 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2209}
2210
2211/*************************************************************************
2212 * @ [SHLWAPI.201]
2213 *
2214 */
2215HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2216 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2217 VARIANT* pvaOut)
2218{
2219 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2220 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2222}
2223
2224/*************************************************************************
2225 * @ [SHLWAPI.202]
2226 *
2227 */
2228HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2229{
2230 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2232}
2233
2234/*************************************************************************
2235 * @ [SHLWAPI.204]
2236 *
2237 * Determine if a window is not a child of another window.
2238 *
2239 * PARAMS
2240 * hParent [I] Suspected parent window
2241 * hChild [I] Suspected child window
2242 *
2243 * RETURNS
2244 * TRUE: If hChild is a child window of hParent
2245 * FALSE: If hChild is not a child window of hParent, or they are equal
2246 */
2248{
2249 TRACE("(%p,%p)\n", hParent, hChild);
2250
2251 if (!hParent || !hChild)
2252 return TRUE;
2253 else if(hParent == hChild)
2254 return FALSE;
2255 return !IsChild(hParent, hChild);
2256}
2257
2258/*************************************************************************
2259 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2260 */
2261
2262typedef struct
2263{
2264 DWORD num_items; /* Number of elements inserted */
2265 void *mem; /* Ptr to array */
2266 DWORD blocks_alloced; /* Number of elements allocated */
2267 BYTE inc; /* Number of elements to grow by when we need to expand */
2268 BYTE block_size; /* Size in bytes of an element */
2269 BYTE flags; /* Flags */
2270} FDSA_info;
2271
2272#define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2273
2274/*************************************************************************
2275 * @ [SHLWAPI.208]
2276 *
2277 * Initialize an FDSA array.
2278 */
2280 DWORD init_blocks)
2281{
2282 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2283
2284 if(inc == 0)
2285 inc = 1;
2286
2287 if(mem)
2288 memset(mem, 0, block_size * init_blocks);
2289
2290 info->num_items = 0;
2291 info->inc = inc;
2292 info->mem = mem;
2293 info->blocks_alloced = init_blocks;
2294 info->block_size = block_size;
2295 info->flags = 0;
2296
2297 return TRUE;
2298}
2299
2300/*************************************************************************
2301 * @ [SHLWAPI.209]
2302 *
2303 * Destroy an FDSA array
2304 */
2306{
2307 TRACE("(%p)\n", info);
2308
2309 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2310 {
2311 HeapFree(GetProcessHeap(), 0, info->mem);
2312 return FALSE;
2313 }
2314
2315 return TRUE;
2316}
2317
2318/*************************************************************************
2319 * @ [SHLWAPI.210]
2320 *
2321 * Insert element into an FDSA array
2322 */
2324{
2325 TRACE("(%p 0x%08x %p)\n", info, where, block);
2326 if(where > info->num_items)
2327 where = info->num_items;
2328
2329 if(info->num_items >= info->blocks_alloced)
2330 {
2331 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2332 if(info->flags & 0x1)
2334 else
2335 {
2336 void *old_mem = info->mem;
2338 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2339 }
2340 info->blocks_alloced += info->inc;
2341 info->flags |= 0x1;
2342 }
2343
2344 if(where < info->num_items)
2345 {
2346 memmove((char*)info->mem + (where + 1) * info->block_size,
2347 (char*)info->mem + where * info->block_size,
2348 (info->num_items - where) * info->block_size);
2349 }
2350 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2351
2352 info->num_items++;
2353 return where;
2354}
2355
2356/*************************************************************************
2357 * @ [SHLWAPI.211]
2358 *
2359 * Delete an element from an FDSA array.
2360 */
2362{
2363 TRACE("(%p 0x%08x)\n", info, where);
2364
2365 if(where >= info->num_items)
2366 return FALSE;
2367
2368 if(where < info->num_items - 1)
2369 {
2370 memmove((char*)info->mem + where * info->block_size,
2371 (char*)info->mem + (where + 1) * info->block_size,
2372 (info->num_items - where - 1) * info->block_size);
2373 }
2374 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2375 0, info->block_size);
2376 info->num_items--;
2377 return TRUE;
2378}
2379
2380/*************************************************************************
2381 * @ [SHLWAPI.219]
2382 *
2383 * Call IUnknown_QueryInterface() on a table of objects.
2384 *
2385 * RETURNS
2386 * Success: S_OK.
2387 * Failure: E_POINTER or E_NOINTERFACE.
2388 */
2390 void *base, /* [in] Table of interfaces */
2391 const QITAB *table, /* [in] Array of REFIIDs and indexes into the table */
2392 REFIID riid, /* [in] REFIID to get interface for */
2393 void **ppv) /* [out] Destination for interface pointer */
2394{
2395 HRESULT ret;
2396 IUnknown *a_vtbl;
2397 const QITAB *xmove;
2398
2399 TRACE("(%p %p %s %p)\n", base, table, debugstr_guid(riid), ppv);
2400 if (ppv) {
2401 xmove = table;
2402 while (xmove->piid) {
2403 TRACE("trying (offset %d) %s\n", xmove->dwOffset, debugstr_guid(xmove->piid));
2404 if (IsEqualIID(riid, xmove->piid)) {
2405 a_vtbl = (IUnknown*)(xmove->dwOffset + (LPBYTE)base);
2406 TRACE("matched, returning (%p)\n", a_vtbl);
2407 *ppv = a_vtbl;
2408 IUnknown_AddRef(a_vtbl);
2409 return S_OK;
2410 }
2411 xmove++;
2412 }
2413
2414 if (IsEqualIID(riid, &IID_IUnknown)) {
2415 a_vtbl = (IUnknown*)(table->dwOffset + (LPBYTE)base);
2416 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2417 *ppv = a_vtbl;
2418 IUnknown_AddRef(a_vtbl);
2419 return S_OK;
2420 }
2421 *ppv = 0;
2423 } else
2424 ret = E_POINTER;
2425
2426 TRACE("-- 0x%08x\n", ret);
2427 return ret;
2428}
2429
2430/*************************************************************************
2431 * @ [SHLWAPI.220]
2432 *
2433 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2434 *
2435 * PARAMS
2436 * hWnd [I] Parent Window to set the property
2437 * id [I] Index of child Window to set the Font
2438 *
2439 * RETURNS
2440 * Success: S_OK
2441 *
2442 */
2444{
2445 FIXME("(%p, %d) stub\n", hWnd, id);
2446 return S_OK;
2447}
2448
2449/*************************************************************************
2450 * @ [SHLWAPI.221]
2451 *
2452 * Remove the "PropDlgFont" property from a window.
2453 *
2454 * PARAMS
2455 * hWnd [I] Window to remove the property from
2456 *
2457 * RETURNS
2458 * A handle to the removed property, or NULL if it did not exist.
2459 */
2461{
2462 HANDLE hProp;
2463
2464 TRACE("(%p)\n", hWnd);
2465
2466 hProp = GetPropA(hWnd, "PropDlgFont");
2467
2468 if(hProp)
2469 {
2470 DeleteObject(hProp);
2471 hProp = RemovePropA(hWnd, "PropDlgFont");
2472 }
2473 return hProp;
2474}
2475
2476/*************************************************************************
2477 * @ [SHLWAPI.236]
2478 *
2479 * Load the in-process server of a given GUID.
2480 *
2481 * PARAMS
2482 * refiid [I] GUID of the server to load.
2483 *
2484 * RETURNS
2485 * Success: A handle to the loaded server dll.
2486 * Failure: A NULL handle.
2487 */
2489{
2490 HKEY newkey;
2491 DWORD type, count;
2492 CHAR value[MAX_PATH], string[MAX_PATH];
2493
2494 strcpy(string, "CLSID\\");
2495 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2496 strcat(string, "\\InProcServer32");
2497
2498 count = MAX_PATH;
2499 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2500 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2501 RegCloseKey(newkey);
2502 return LoadLibraryExA(value, 0, 0);
2503}
2504
2505/*************************************************************************
2506 * @ [SHLWAPI.237]
2507 *
2508 * Unicode version of SHLWAPI_183.
2509 */
2511{
2513
2514 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2515
2516 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2517 return TRUE;
2518 return RegisterClassW(lpWndClass);
2519}
2520
2521/*************************************************************************
2522 * @ [SHLWAPI.238]
2523 *
2524 * Unregister a list of classes.
2525 *
2526 * PARAMS
2527 * hInst [I] Application instance that registered the classes
2528 * lppClasses [I] List of class names
2529 * iCount [I] Number of names in lppClasses
2530 *
2531 * RETURNS
2532 * Nothing.
2533 */
2535{
2537
2538 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2539
2540 while (iCount > 0)
2541 {
2542 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2543 UnregisterClassA(*lppClasses, hInst);
2544 lppClasses++;
2545 iCount--;
2546 }
2547}
2548
2549/*************************************************************************
2550 * @ [SHLWAPI.239]
2551 *
2552 * Unicode version of SHUnregisterClassesA.
2553 */
2555{
2557
2558 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2559
2560 while (iCount > 0)
2561 {
2562 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2563 UnregisterClassW(*lppClasses, hInst);
2564 lppClasses++;
2565 iCount--;
2566 }
2567}
2568
2569/*************************************************************************
2570 * @ [SHLWAPI.240]
2571 *
2572 * Call The correct (Ascii/Unicode) default window procedure for a window.
2573 *
2574 * PARAMS
2575 * hWnd [I] Window to call the default procedure for
2576 * uMessage [I] Message ID
2577 * wParam [I] WPARAM of message
2578 * lParam [I] LPARAM of message
2579 *
2580 * RETURNS
2581 * The result of calling DefWindowProcA() or DefWindowProcW().
2582 */
2584{
2585 if (IsWindowUnicode(hWnd))
2586 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2587 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2588}
2589
2590/*************************************************************************
2591 * @ [SHLWAPI.256]
2592 */
2594{
2595 HRESULT hRet = E_INVALIDARG;
2596 LPOBJECTWITHSITE lpSite = NULL;
2597
2598 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2599
2600 if (lpUnknown && iid && lppSite)
2601 {
2602 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2603 (void**)&lpSite);
2604 if (SUCCEEDED(hRet) && lpSite)
2605 {
2606 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2607 IObjectWithSite_Release(lpSite);
2608 }
2609 }
2610 return hRet;
2611}
2612
2613/*************************************************************************
2614 * @ [SHLWAPI.257]
2615 *
2616 * Create a worker window using CreateWindowExA().
2617 *
2618 * PARAMS
2619 * wndProc [I] Window procedure
2620 * hWndParent [I] Parent window
2621 * dwExStyle [I] Extra style flags
2622 * dwStyle [I] Style flags
2623 * hMenu [I] Window menu
2624 * wnd_extra [I] Window extra bytes value
2625 *
2626 * RETURNS
2627 * Success: The window handle of the newly created window.
2628 * Failure: 0.
2629 */
2631 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra)
2632{
2633 static const char szClass[] = "WorkerA";
2634 WNDCLASSA wc;
2635 HWND hWnd;
2636
2637 TRACE("(%p, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2638 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
2639
2640 /* Create Window class */
2641 wc.style = 0;
2643 wc.cbClsExtra = 0;
2644 wc.cbWndExtra = sizeof(LONG_PTR);
2646 wc.hIcon = NULL;
2648 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2649 wc.lpszMenuName = NULL;
2650 wc.lpszClassName = szClass;
2651
2652 SHRegisterClassA(&wc);
2653
2654 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2655 hWndParent, hMenu, shlwapi_hInstance, 0);
2656 if (hWnd)
2657 {
2658 SetWindowLongPtrW(hWnd, 0, wnd_extra);
2660 }
2661
2662 return hWnd;
2663}
2664
2665typedef struct tagPOLICYDATA
2666{
2667 DWORD policy; /* flags value passed to SHRestricted */
2668 LPCWSTR appstr; /* application str such as "Explorer" */
2669 LPCWSTR keystr; /* name of the actual registry key / policy */
2671
2672#define SHELL_NO_POLICY 0xffffffff
2673
2674/* default shell policy registry key */
2675static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2676 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2677 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2678 '\\','P','o','l','i','c','i','e','s',0};
2679
2680/*************************************************************************
2681 * @ [SHLWAPI.271]
2682 *
2683 * Retrieve a policy value from the registry.
2684 *
2685 * PARAMS
2686 * lpSubKey [I] registry key name
2687 * lpSubName [I] subname of registry key
2688 * lpValue [I] value name of registry value
2689 *
2690 * RETURNS
2691 * the value associated with the registry key or 0 if not found
2692 */
2694{
2695 DWORD retval, datsize = sizeof(retval);
2696 HKEY hKey;
2697
2698 if (!lpSubKey)
2699 lpSubKey = strRegistryPolicyW;
2700
2701 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2702 if (retval != ERROR_SUCCESS)
2703 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2704 if (retval != ERROR_SUCCESS)
2705 return 0;
2706
2707 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2709 return retval;
2710}
2711
2712/*************************************************************************
2713 * @ [SHLWAPI.266]
2714 *
2715 * Helper function to retrieve the possibly cached value for a specific policy
2716 *
2717 * PARAMS
2718 * policy [I] The policy to look for
2719 * initial [I] Main registry key to open, if NULL use default
2720 * polTable [I] Table of known policies, 0 terminated
2721 * polArr [I] Cache array of policy values
2722 *
2723 * RETURNS
2724 * The retrieved policy value or 0 if not successful
2725 *
2726 * NOTES
2727 * This function is used by the native SHRestricted function to search for the
2728 * policy and cache it once retrieved. The current Wine implementation uses a
2729 * different POLICYDATA structure and implements a similar algorithm adapted to
2730 * that structure.
2731 */
2733 DWORD policy,
2734 LPCWSTR initial,
2735 LPPOLICYDATA polTable,
2736 LPDWORD polArr)
2737{
2738 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2739
2740 if (!polTable || !polArr)
2741 return 0;
2742
2743 for (;polTable->policy; polTable++, polArr++)
2744 {
2745 if (policy == polTable->policy)
2746 {
2747 /* we have a known policy */
2748
2749 /* check if this policy has been cached */
2750 if (*polArr == SHELL_NO_POLICY)
2751 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2752 return *polArr;
2753 }
2754 }
2755 /* we don't know this policy, return 0 */
2756 TRACE("unknown policy: (%08x)\n", policy);
2757 return 0;
2758}
2759
2760/*************************************************************************
2761 * @ [SHLWAPI.267]
2762 *
2763 * Get an interface from an object.
2764 *
2765 * RETURNS
2766 * Success: S_OK. ppv contains the requested interface.
2767 * Failure: An HRESULT error code.
2768 *
2769 * NOTES
2770 * This QueryInterface asks the inner object for an interface. In case
2771 * of aggregation this request would be forwarded by the inner to the
2772 * outer object. This function asks the inner object directly for the
2773 * interface circumventing the forwarding to the outer object.
2774 */
2776 IUnknown * pUnk, /* [in] Outer object */
2777 IUnknown * pInner, /* [in] Inner object */
2778 IID * riid, /* [in] Interface GUID to query for */
2779 LPVOID* ppv) /* [out] Destination for queried interface */
2780{
2781 HRESULT hret = E_NOINTERFACE;
2782 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2783
2784 *ppv = NULL;
2785 if(pUnk && pInner) {
2786 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2787 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2788 }
2789 TRACE("-- 0x%08x\n", hret);
2790 return hret;
2791}
2792
2793/*************************************************************************
2794 * @ [SHLWAPI.268]
2795 *
2796 * Move a reference from one interface to another.
2797 *
2798 * PARAMS
2799 * lpDest [O] Destination to receive the reference
2800 * lppUnknown [O] Source to give up the reference to lpDest
2801 *
2802 * RETURNS
2803 * Nothing.
2804 */
2806{
2807 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2808
2809 if (*lppUnknown)
2810 {
2811 /* Copy Reference*/
2812 IUnknown_AddRef(lpDest);
2813 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2814 }
2815}
2816
2817/*************************************************************************
2818 * @ [SHLWAPI.269]
2819 *
2820 * Convert an ASCII string of a CLSID into a CLSID.
2821 *
2822 * PARAMS
2823 * idstr [I] String representing a CLSID in registry format
2824 * id [O] Destination for the converted CLSID
2825 *
2826 * RETURNS
2827 * Success: TRUE. id contains the converted CLSID.
2828 * Failure: FALSE.
2829 */
2831{
2832 WCHAR wClsid[40];
2833 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2834 return SUCCEEDED(CLSIDFromString(wClsid, id));
2835}
2836
2837/*************************************************************************
2838 * @ [SHLWAPI.270]
2839 *
2840 * Unicode version of GUIDFromStringA.
2841 */
2843{
2844 return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id));
2845}
2846
2847/*************************************************************************
2848 * @ [SHLWAPI.276]
2849 *
2850 * Determine if the browser is integrated into the shell, and set a registry
2851 * key accordingly.
2852 *
2853 * PARAMS
2854 * None.
2855 *
2856 * RETURNS
2857 * 1, If the browser is not integrated.
2858 * 2, If the browser is integrated.
2859 *
2860 * NOTES
2861 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2862 * either set to TRUE, or removed depending on whether the browser is deemed
2863 * to be integrated.
2864 */
2866{
2867 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2868 static DWORD dwState = 0;
2869 HKEY hKey;
2870 DWORD dwRet, dwData, dwSize;
2871 HMODULE hshell32;
2872
2873 if (dwState)
2874 return dwState;
2875
2876 /* If shell32 exports DllGetVersion(), the browser is integrated */
2877 dwState = 1;
2878 hshell32 = LoadLibraryA("shell32.dll");
2879 if (hshell32)
2880 {
2881 FARPROC pDllGetVersion;
2882 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2883 dwState = pDllGetVersion ? 2 : 1;
2884 FreeLibrary(hshell32);
2885 }
2886
2887 /* Set or delete the key accordingly */
2889 "Software\\Microsoft\\Internet Explorer", 0,
2891 if (!dwRet)
2892 {
2893 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2894 (LPBYTE)&dwData, &dwSize);
2895
2896 if (!dwRet && dwState == 1)
2897 {
2898 /* Value exists but browser is not integrated */
2899 RegDeleteValueA(hKey, szIntegratedBrowser);
2900 }
2901 else if (dwRet && dwState == 2)
2902 {
2903 /* Browser is integrated but value does not exist */
2904 dwData = TRUE;
2905 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2906 (LPBYTE)&dwData, sizeof(dwData));
2907 }
2909 }
2910 return dwState;
2911}
2912
2913/*************************************************************************
2914 * @ [SHLWAPI.278]
2915 *
2916 * Unicode version of SHCreateWorkerWindowA.
2917 */
2919 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra)
2920{
2921 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
2922 WNDCLASSW wc;
2923 HWND hWnd;
2924
2925 TRACE("(%p, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2926 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
2927
2928 /* If our OS is natively ANSI, use the ANSI version */
2929 if (GetVersion() & 0x80000000) /* not NT */
2930 {
2931 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
2932 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
2933 }
2934
2935 /* Create Window class */
2936 wc.style = 0;
2938 wc.cbClsExtra = 0;
2939 wc.cbWndExtra = sizeof(LONG_PTR);
2941 wc.hIcon = NULL;
2943 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2944 wc.lpszMenuName = NULL;
2945 wc.lpszClassName = szClass;
2946
2947 SHRegisterClassW(&wc);
2948
2949 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2950 hWndParent, hMenu, shlwapi_hInstance, 0);
2951 if (hWnd)
2952 {
2953 SetWindowLongPtrW(hWnd, 0, wnd_extra);
2955 }
2956
2957 return hWnd;
2958}
2959
2960/*************************************************************************
2961 * @ [SHLWAPI.279]
2962 *
2963 * Get and show a context menu from a shell folder.
2964 *
2965 * PARAMS
2966 * hWnd [I] Window displaying the shell folder
2967 * lpFolder [I] IShellFolder interface
2968 * lpApidl [I] Id for the particular folder desired
2969 *
2970 * RETURNS
2971 * Success: S_OK.
2972 * Failure: An HRESULT error code indicating the error.
2973 */
2975{
2976 TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl);
2977 return SHInvokeCommand(hWnd, lpFolder, lpApidl, 0);
2978}
2979
2980/*************************************************************************
2981 * @ [SHLWAPI.281]
2982 *
2983 * _SHPackDispParamsV
2984 */
2986{
2987 VARIANTARG *iter;
2988
2989 TRACE("(%p %p %u ...)\n", params, args, cnt);
2990
2991 params->rgvarg = args;
2992 params->rgdispidNamedArgs = NULL;
2993 params->cArgs = cnt;
2994 params->cNamedArgs = 0;
2995
2996 iter = args+cnt;
2997
2998 while(iter-- > args) {
2999 V_VT(iter) = va_arg(valist, enum VARENUM);
3000
3001 TRACE("vt=%d\n", V_VT(iter));
3002
3003 if(V_VT(iter) & VT_BYREF) {
3004 V_BYREF(iter) = va_arg(valist, LPVOID);
3005 } else {
3006 switch(V_VT(iter)) {
3007 case VT_I4:
3008 V_I4(iter) = va_arg(valist, LONG);
3009 break;
3010 case VT_BSTR:
3011 V_BSTR(iter) = va_arg(valist, BSTR);
3012 break;
3013 case VT_DISPATCH:
3014 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
3015 break;
3016 case VT_BOOL:
3017 V_BOOL(iter) = va_arg(valist, int);
3018 break;
3019 case VT_UNKNOWN:
3020 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
3021 break;
3022 default:
3023 V_VT(iter) = VT_I4;
3024 V_I4(iter) = va_arg(valist, LONG);
3025 }
3026 }
3027 }
3028
3029 return S_OK;
3030}
3031
3032/*************************************************************************
3033 * @ [SHLWAPI.282]
3034 *
3035 * SHPackDispParams
3036 */
3038{
3040 HRESULT hres;
3041
3042 __ms_va_start(valist, cnt);
3045 return hres;
3046}
3047
3048/*************************************************************************
3049 * SHLWAPI_InvokeByIID
3050 *
3051 * This helper function calls IDispatch::Invoke for each sink
3052 * which implements given iid or IDispatch.
3053 *
3054 */
3056 IConnectionPoint* iCP,
3057 REFIID iid,
3058 DISPID dispId,
3059 DISPPARAMS* dispParams)
3060{
3061 IEnumConnections *enumerator;
3062 CONNECTDATA rgcd;
3063 static DISPPARAMS empty = {NULL, NULL, 0, 0};
3064 DISPPARAMS* params = dispParams;
3065
3066 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
3067 if (FAILED(result))
3068 return result;
3069
3070 /* Invoke is never happening with an NULL dispParams */
3071 if (!params)
3072 params = &empty;
3073
3074 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
3075 {
3076 IDispatch *dispIface;
3077 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
3078 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
3079 {
3080 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
3081 IDispatch_Release(dispIface);
3082 }
3083 IUnknown_Release(rgcd.pUnk);
3084 }
3085
3086 IEnumConnections_Release(enumerator);
3087
3088 return S_OK;
3089}
3090
3091/*************************************************************************
3092 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3093 */
3095 DISPID dispId, DISPPARAMS* dispParams,
3096 DWORD unknown1, DWORD unknown2 )
3097{
3098 IID iid;
3100
3101 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
3102
3103 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3104 if (SUCCEEDED(result))
3105 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3106 else
3107 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3108
3109 return result;
3110}
3111
3112
3113/*************************************************************************
3114 * @ [SHLWAPI.284]
3115 *
3116 * IConnectionPoint_SimpleInvoke
3117 */
3119 IConnectionPoint* iCP,
3120 DISPID dispId,
3121 DISPPARAMS* dispParams)
3122{
3123 IID iid;
3125
3126 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
3127
3128 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3129 if (SUCCEEDED(result))
3130 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3131 else
3132 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3133
3134 return result;
3135}
3136
3137/*************************************************************************
3138 * @ [SHLWAPI.285]
3139 *
3140 * Notify an IConnectionPoint object of changes.
3141 *
3142 * PARAMS
3143 * lpCP [I] Object to notify
3144 * dispID [I]
3145 *
3146 * RETURNS
3147 * Success: S_OK.
3148 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3149 * IConnectionPoint interface.
3150 */
3152{
3153 IEnumConnections *lpEnum;
3154 HRESULT hRet = E_NOINTERFACE;
3155
3156 TRACE("(%p,0x%8X)\n", lpCP, dispID);
3157
3158 /* Get an enumerator for the connections */
3159 if (lpCP)
3160 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
3161
3162 if (SUCCEEDED(hRet))
3163 {
3164 IPropertyNotifySink *lpSink;
3165 CONNECTDATA connData;
3166 ULONG ulFetched;
3167
3168 /* Call OnChanged() for every notify sink in the connection point */
3169 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
3170 {
3171 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
3172 lpSink)
3173 {
3174 IPropertyNotifySink_OnChanged(lpSink, dispID);
3175 IPropertyNotifySink_Release(lpSink);
3176 }
3177 IUnknown_Release(connData.pUnk);
3178 }
3179
3180 IEnumConnections_Release(lpEnum);
3181 }
3182 return hRet;
3183}
3184
3185/*************************************************************************
3186 * @ [SHLWAPI.286]
3187 *
3188 * IUnknown_CPContainerInvokeParam
3189 */
3192 REFIID riid,
3193 DISPID dispId,
3195 DWORD cParams, ...)
3196{
3198 IConnectionPoint *iCP;
3200 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3202
3203 if (!container)
3204 return E_NOINTERFACE;
3205
3206 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
3207 if (FAILED(result))
3208 return result;
3209
3210 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
3211 IConnectionPointContainer_Release(iCPC);
3212 if(FAILED(result))
3213 return result;
3214
3215 __ms_va_start(valist, cParams);
3216 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
3218
3219 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3220 IConnectionPoint_Release(iCP);
3221
3222 return result;
3223}
3224
3225/*************************************************************************
3226 * @ [SHLWAPI.287]
3227 *
3228 * Notify an IConnectionPointContainer object of changes.
3229 *
3230 * PARAMS
3231 * lpUnknown [I] Object to notify
3232 * dispID [I]
3233 *
3234 * RETURNS
3235 * Success: S_OK.
3236 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3237 * IConnectionPointContainer interface.
3238 */
3240{
3242 HRESULT hRet = E_NOINTERFACE;
3243
3244 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3245
3246 if (lpUnknown)
3247 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3248
3249 if (SUCCEEDED(hRet))
3250 {
3251 IConnectionPoint* lpCP;
3252
3253 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3254 IConnectionPointContainer_Release(lpCPC);
3255
3256 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3257 IConnectionPoint_Release(lpCP);
3258 }
3259 return hRet;
3260}
3261
3262/*************************************************************************
3263 * @ [SHLWAPI.289]
3264 *
3265 * See PlaySoundW.
3266 */
3268{
3269 return PlaySoundW(pszSound, hmod, fdwSound);
3270}
3271
3272/*************************************************************************
3273 * @ [SHLWAPI.294]
3274 *
3275 * Retrieve a key value from an INI file. See GetPrivateProfileString for
3276 * more information.
3277 *
3278 * PARAMS
3279 * appName [I] The section in the INI file that contains the key
3280 * keyName [I] The key to be retrieved
3281 * out [O] The buffer into which the key's value will be copied
3282 * outLen [I] The length of the `out' buffer
3283 * filename [I] The location of the INI file
3284 *
3285 * RETURNS
3286 * Length of string copied into `out'.
3287 */
3289 DWORD outLen, LPCWSTR filename)
3290{
3291 INT ret;
3292 WCHAR *buf;
3293
3294 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName), debugstr_w(keyName),
3295 out, outLen, debugstr_w(filename));
3296
3297 if(outLen == 0)
3298 return 0;
3299
3300 buf = HeapAlloc(GetProcessHeap(), 0, outLen * sizeof(WCHAR));
3301 if(!buf){
3302 *out = 0;
3303 return 0;
3304 }
3305
3306 ret = GetPrivateProfileStringW(appName, keyName, NULL, buf, outLen, filename);
3307 if(ret)
3308 strcpyW(out, buf);
3309 else
3310 *out = 0;
3311
3313
3314 return strlenW(out);
3315}
3316
3317/*************************************************************************
3318 * @ [SHLWAPI.295]
3319 *
3320 * Set a key value in an INI file. See WritePrivateProfileString for
3321 * more information.
3322 *
3323 * PARAMS
3324 * appName [I] The section in the INI file that contains the key
3325 * keyName [I] The key to be set
3326 * str [O] The value of the key
3327 * filename [I] The location of the INI file
3328 *
3329 * RETURNS
3330 * Success: TRUE
3331 * Failure: FALSE
3332 */
3335{
3336 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
3338
3340}
3341
3342/*************************************************************************
3343 * @ [SHLWAPI.313]
3344 *
3345 * See SHGetFileInfoW.
3346 */
3348 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3349{
3350 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3351}
3352
3353/*************************************************************************
3354 * @ [SHLWAPI.318]
3355 *
3356 * See DragQueryFileW.
3357 */
3358UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3359{
3360 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3361}
3362
3363/*************************************************************************
3364 * @ [SHLWAPI.333]
3365 *
3366 * See SHBrowseForFolderW.
3367 */
3369{
3370 return SHBrowseForFolderW(lpBi);
3371}
3372
3373/*************************************************************************
3374 * @ [SHLWAPI.334]
3375 *
3376 * See SHGetPathFromIDListW.
3377 */
3379{
3380 return SHGetPathFromIDListW(pidl, pszPath);
3381}
3382
3383/*************************************************************************
3384 * @ [SHLWAPI.335]
3385 *
3386 * See ShellExecuteExW.
3387 */
3389{
3390 return ShellExecuteExW(lpExecInfo);
3391}
3392
3393/*************************************************************************
3394 * @ [SHLWAPI.336]
3395 *
3396 * See SHFileOperationW.
3397 */
3399{
3400 return SHFileOperationW(lpFileOp);
3401}
3402
3403/*************************************************************************
3404 * @ [SHLWAPI.342]
3405 *
3406 */
3408{
3410}
3411
3412/*************************************************************************
3413 * @ [SHLWAPI.350]
3414 *
3415 * See GetFileVersionInfoSizeW.
3416 */
3418{
3420}
3421
3422/*************************************************************************
3423 * @ [SHLWAPI.351]
3424 *
3425 * See GetFileVersionInfoW.
3426 */
3429{
3431}
3432
3433/*************************************************************************
3434 * @ [SHLWAPI.352]
3435 *
3436 * See VerQueryValueW.
3437 */
3439 LPVOID *lplpBuffer, UINT *puLen )
3440{
3441 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3442}
3443
3444#define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3445#define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3446#define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3447
3448/*************************************************************************
3449 * @ [SHLWAPI.355]
3450 *
3451 * Change the modality of a shell object.
3452 *
3453 * PARAMS
3454 * lpUnknown [I] Object to make modeless
3455 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3456 *
3457 * RETURNS
3458 * Success: S_OK. The modality lpUnknown is changed.
3459 * Failure: An HRESULT error code indicating the error.
3460 *
3461 * NOTES
3462 * lpUnknown must support the IOleInPlaceFrame interface, the
3463 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3464 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3465 * or this call will fail.
3466 */
3468{
3469 IUnknown *lpObj;
3470 HRESULT hRet;
3471
3472 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3473
3474 if (!lpUnknown)
3475 return E_FAIL;
3476
3479 else if (IsIface(IOleInPlaceFrame))
3481 else if (IsIface(IShellBrowser))
3485 else if (IsIface(IDocHostUIHandler))
3487 else
3488 return hRet;
3489
3490 IUnknown_Release(lpObj);
3491 return S_OK;
3492}
3493
3494/*************************************************************************
3495 * @ [SHLWAPI.357]
3496 *
3497 * See SHGetNewLinkInfoW.
3498 */
3501{
3502 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3503}
3504
3505/*************************************************************************
3506 * @ [SHLWAPI.358]
3507 *
3508 * See SHDefExtractIconW.
3509 */
3510UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3511 HICON* phiconSmall, UINT nIconSize)
3512{
3513 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3514}
3515
3516/*************************************************************************
3517 * @ [SHLWAPI.363]
3518 *
3519 * Get and show a context menu from a shell folder.
3520 *
3521 * PARAMS
3522 * hWnd [I] Window displaying the shell folder
3523 * lpFolder [I] IShellFolder interface
3524 * lpApidl [I] Id for the particular folder desired
3525 * dwCommandId [I] The command ID to invoke (0=invoke default)
3526 *
3527 * RETURNS
3528 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3529 * executed.
3530 * Failure: An HRESULT error code indicating the error.
3531 */
3533{
3534 IContextMenu *iContext;
3535 HRESULT hRet;
3536
3537 TRACE("(%p, %p, %p, %u)\n", hWnd, lpFolder, lpApidl, dwCommandId);
3538
3539 if (!lpFolder)
3540 return E_FAIL;
3541
3542 /* Get the context menu from the shell folder */
3543 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3544 &IID_IContextMenu, 0, (void**)&iContext);
3545 if (SUCCEEDED(hRet))
3546 {
3547 HMENU hMenu;
3548 if ((hMenu = CreatePopupMenu()))
3549 {
3550 HRESULT hQuery;
3551
3552 /* Add the context menu entries to the popup */
3553 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3554 dwCommandId ? CMF_NORMAL : CMF_DEFAULTONLY);
3555
3556 if (SUCCEEDED(hQuery))
3557 {
3558 if (!dwCommandId)
3559 dwCommandId = GetMenuDefaultItem(hMenu, 0, 0);
3560 if (dwCommandId != (UINT)-1)
3561 {
3562 CMINVOKECOMMANDINFO cmIci;
3563 /* Invoke the default item */
3564 memset(&cmIci,0,sizeof(cmIci));
3565 cmIci.cbSize = sizeof(cmIci);
3566 cmIci.fMask = CMIC_MASK_ASYNCOK;
3567 cmIci.hwnd = hWnd;
3568#ifdef __REACTOS__ /* r75561 */
3569 cmIci.lpVerb = MAKEINTRESOURCEA(dwCommandId - 1);
3570#else
3571 cmIci.lpVerb = MAKEINTRESOURCEA(dwCommandId);
3572#endif
3573 cmIci.nShow = SW_SHOWNORMAL;
3574
3575 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3576 }
3577 }
3578 DestroyMenu(hMenu);
3579 }
3580 IContextMenu_Release(iContext);
3581 }
3582 return hRet;
3583}
3584
3585/*************************************************************************
3586 * @ [SHLWAPI.370]
3587 *
3588 * See ExtractIconW.
3589 */
3591 UINT nIconIndex)
3592{
3593 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3594}
3595
3596/*************************************************************************
3597 * @ [SHLWAPI.377]
3598 *
3599 * Load a library from the directory of a particular process.
3600 *
3601 * PARAMS
3602 * new_mod [I] Library name
3603 * inst_hwnd [I] Module whose directory is to be used
3604 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3605 *
3606 * RETURNS
3607 * Success: A handle to the loaded module
3608 * Failure: A NULL handle.
3609 */
3610HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3611{
3612 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3613 * each call here.
3614 * FIXME: Native shows calls to:
3615 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3616 * CheckVersion
3617 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3618 * RegQueryValueExA for "LPKInstalled"
3619 * RegCloseKey
3620 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3621 * RegQueryValueExA for "ResourceLocale"
3622 * RegCloseKey
3623 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3624 * RegQueryValueExA for "Locale"
3625 * RegCloseKey
3626 * and then tests the Locale ("en" for me).
3627 * code below
3628 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3629 */
3630 CHAR mod_path[2*MAX_PATH];
3631 LPSTR ptr;
3632 DWORD len;
3633
3634 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3635 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3636 if (!len || len >= sizeof(mod_path)) return NULL;
3637
3638 ptr = strrchr(mod_path, '\\');
3639 if (ptr) {
3640 strcpy(ptr+1, new_mod);
3641 TRACE("loading %s\n", debugstr_a(mod_path));
3642 return LoadLibraryA(mod_path);
3643 }
3644 return NULL;
3645}
3646
3647/*************************************************************************
3648 * @ [SHLWAPI.378]
3649 *
3650 * Unicode version of MLLoadLibraryA.
3651 */
3652HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3653{
3654 WCHAR mod_path[2*MAX_PATH];
3655 LPWSTR ptr;
3656 DWORD len;
3657
3658 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3659 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3660 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3661
3662 ptr = strrchrW(mod_path, '\\');
3663 if (ptr) {
3664 strcpyW(ptr+1, new_mod);
3665 TRACE("loading %s\n", debugstr_w(mod_path));
3666 return LoadLibraryW(mod_path);
3667 }
3668 return NULL;
3669}
3670
3671/*************************************************************************
3672 * ColorAdjustLuma [SHLWAPI.@]
3673 *
3674 * Adjust the luminosity of a color
3675 *
3676 * PARAMS
3677 * cRGB [I] RGB value to convert
3678 * dwLuma [I] Luma adjustment
3679 * bUnknown [I] Unknown
3680 *
3681 * RETURNS
3682 * The adjusted RGB color.
3683 */
3684COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3685{
3686 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3687
3688 if (dwLuma)
3689 {
3690 WORD wH, wL, wS;
3691
3692 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3693
3694 FIXME("Ignoring luma adjustment\n");
3695
3696 /* FIXME: The adjustment is not linear */
3697
3698 cRGB = ColorHLSToRGB(wH, wL, wS);
3699 }
3700 return cRGB;
3701}
3702
3703/*************************************************************************
3704 * @ [SHLWAPI.389]
3705 *
3706 * See GetSaveFileNameW.
3707 */
3709{
3710 return GetSaveFileNameW(ofn);
3711}
3712
3713/*************************************************************************
3714 * @ [SHLWAPI.390]
3715 *
3716 * See WNetRestoreConnectionW.
3717 */
3719{
3720 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3721}
3722
3723/*************************************************************************
3724 * @ [SHLWAPI.391]
3725 *
3726 * See WNetGetLastErrorW.
3727 */
3728DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3729 LPWSTR lpNameBuf, DWORD nNameBufSize)
3730{
3731 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3732}
3733
3734/*************************************************************************
3735 * @ [SHLWAPI.401]
3736 *
3737 * See PageSetupDlgW.
3738 */
3740{
3741 return PageSetupDlgW(pagedlg);
3742}
3743
3744/*************************************************************************
3745 * @ [SHLWAPI.402]
3746 *
3747 * See PrintDlgW.
3748 */
3750{
3751 return PrintDlgW(printdlg);
3752}
3753
3754/*************************************************************************
3755 * @ [SHLWAPI.403]
3756 *
3757 * See GetOpenFileNameW.
3758 */
3760{
3761 return GetOpenFileNameW(ofn);
3762}
3763
3764/*************************************************************************
3765 * @ [SHLWAPI.404]
3766 */
3768{
3769 /* Windows attempts to get an IPersist interface and, if that fails, an
3770 * IPersistFolder interface on the folder passed-in here. If one of those
3771 * interfaces is available, it then calls GetClassID on the folder... and
3772 * then calls IShellFolder_EnumObjects no matter what, even crashing if
3773 * lpFolder isn't actually an IShellFolder object. The purpose of getting
3774 * the ClassID is unknown, so we don't do it here.
3775 *
3776 * For discussion and detailed tests, see:
3777 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated"
3778 * wine-devel mailing list, 3 Jun 2010
3779 */
3780
3781 return IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3782}
3783
3784/* INTERNAL: Map from HLS color space to RGB */
3785static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3786{
3787 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3788
3789 if (wHue > 160)
3790 return wMid1;
3791 else if (wHue > 120)
3792 wHue = 160 - wHue;
3793 else if (wHue > 40)
3794 return wMid2;
3795
3796 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3797}
3798
3799/* Convert to RGB and scale into RGB range (0..255) */
3800#define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3801
3802/*************************************************************************
3803 * ColorHLSToRGB [SHLWAPI.@]
3804 *
3805 * Convert from hls color space into an rgb COLORREF.
3806 *
3807 * PARAMS
3808 * wHue [I] Hue amount
3809 * wLuminosity [I] Luminosity amount
3810 * wSaturation [I] Saturation amount
3811 *
3812 * RETURNS
3813 * A COLORREF representing the converted color.
3814 *
3815 * NOTES
3816 * Input hls values are constrained to the range (0..240).
3817 */
3818COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3819{
3820 WORD wRed;
3821
3822 if (wSaturation)
3823 {
3824 WORD wGreen, wBlue, wMid1, wMid2;
3825
3826 if (wLuminosity > 120)
3827 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3828 else
3829 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3830
3831 wMid1 = wLuminosity * 2 - wMid2;
3832
3833 wRed = GET_RGB(wHue + 80);
3834 wGreen = GET_RGB(wHue);
3835 wBlue = GET_RGB(wHue - 80);
3836
3837 return RGB(wRed, wGreen, wBlue);
3838 }
3839
3840 wRed = wLuminosity * 255 / 240;
3841 return RGB(wRed, wRed, wRed);
3842}
3843
3844/*************************************************************************
3845 * @ [SHLWAPI.413]
3846 *
3847 * Get the current docking status of the system.
3848 *
3849 * PARAMS
3850 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3851 *
3852 * RETURNS
3853 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3854 * a notebook.
3855 */
3857{
3858 HW_PROFILE_INFOA hwInfo;
3859
3860 TRACE("(0x%08x)\n", dwFlags);
3861
3862 GetCurrentHwProfileA(&hwInfo);
3863 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3864 {
3865 case DOCKINFO_DOCKED:
3866 case DOCKINFO_UNDOCKED:
3868 default:
3869 return 0;
3870 }
3871}
3872
3873/*************************************************************************
3874 * @ [SHLWAPI.416]
3875 *
3876 */
3878{
3879
3880 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_w(helpfile), flags1, ptr1, flags2);
3881 return 0;
3882}
3883
3884/*************************************************************************
3885 * @ [SHLWAPI.417]
3886 *
3887 */
3889{
3890
3891 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_a(helpfile), flags1, ptr1, flags2);
3892 return 0;
3893}
3894
3895/*************************************************************************
3896 * @ [SHLWAPI.418]
3897 *
3898 * Function seems to do FreeLibrary plus other things.
3899 *
3900 * FIXME native shows the following calls:
3901 * RtlEnterCriticalSection
3902 * LocalFree
3903 * GetProcAddress(Comctl32??, 150L)
3904 * DPA_DeletePtr
3905 * RtlLeaveCriticalSection
3906 * followed by the FreeLibrary.
3907 * The above code may be related to .377 above.
3908 */
3910{
3911 FIXME("(%p) semi-stub\n", hModule);
3912 return FreeLibrary(hModule);
3913}
3914
3915/*************************************************************************
3916 * @ [SHLWAPI.419]
3917 */
3919 FIXME(": stub\n");
3920 return TRUE;
3921}
3922
3923/*************************************************************************
3924 * @ [SHLWAPI.429]
3925 * FIXME I have no idea what this function does or what its arguments are.
3926 */
3928{
3929 FIXME("(%p) stub\n", hInst);
3930 return FALSE;
3931}
3932
3933
3934/*************************************************************************
3935 * @ [SHLWAPI.430]
3936 */
3938{
3939 FIXME("(%p,%p) stub\n", hInst, hHeap);
3940 return E_FAIL; /* This is what is used if shlwapi not loaded */
3941}
3942
3943/*************************************************************************
3944 * @ [SHLWAPI.431]
3945 */
3947{
3948 FIXME("(0x%08x)stub\n", x);
3949 return 0xabba1247;
3950}
3951
3952/*************************************************************************
3953 * @ [SHLWAPI.432]
3954 *
3955 * See SHSendMessageBroadcastW
3956 *
3957 */
3959{
3961 SMTO_ABORTIFHUNG, 2000, NULL);
3962}
3963
3964/*************************************************************************
3965 * @ [SHLWAPI.433]
3966 *
3967 * A wrapper for sending Broadcast Messages to all top level Windows
3968 *
3969 */
3971{
3973 SMTO_ABORTIFHUNG, 2000, NULL);
3974}
3975
3976/*************************************************************************
3977 * @ [SHLWAPI.436]
3978 *
3979 * Convert a Unicode string CLSID into a CLSID.
3980 *
3981 * PARAMS
3982 * idstr [I] string containing a CLSID in text form
3983 * id [O] CLSID extracted from the string
3984 *
3985 * RETURNS
3986 * S_OK on success or E_INVALIDARG on failure
3987 */
3989{
3990 return CLSIDFromString((LPCOLESTR)idstr, id);
3991}
3992
3993/*************************************************************************
3994 * @ [SHLWAPI.437]
3995 *
3996 * Determine if the OS supports a given feature.
3997 *
3998 * PARAMS
3999 * dwFeature [I] Feature requested (undocumented)
4000 *
4001 * RETURNS
4002 * TRUE If the feature is available.
4003 * FALSE If the feature is not available.
4004 */
4006{
4008 DWORD platform, majorv, minorv;
4009
4011 if(!GetVersionExA(&osvi)) {
4012 ERR("GetVersionEx failed\n");
4013 return FALSE;
4014 }
4015
4016 majorv = osvi.dwMajorVersion;
4017 minorv = osvi.dwMinorVersion;
4019
4020#define ISOS_RETURN(x) \
4021 TRACE("(0x%x) ret=%d\n",feature,(x)); \
4022 return (x);
4023
4024 switch(feature) {
4025 case OS_WIN32SORGREATER:
4028 case OS_NT:
4030 case OS_WIN95ORGREATER:
4032 case OS_NT4ORGREATER:
4033 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
4036 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
4037 case OS_WIN98ORGREATER:
4039 case OS_WIN98_GOLD:
4041 case OS_WIN2000PRO:
4042 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
4043 case OS_WIN2000SERVER:
4044 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4046 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4048 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4049 case OS_WIN2000TERMINAL:
4050 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4051 case OS_EMBEDDED:
4052 FIXME("(OS_EMBEDDED) What should we return here?\n");
4053 return FALSE;
4054 case OS_TERMINALCLIENT:
4055 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
4056 return FALSE;
4058 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
4059 return FALSE;
4060 case OS_WIN95_GOLD:
4062 case OS_MEORGREATER:
4064 case OS_XPORGREATER:
4065 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
4066 case OS_HOME:
4067 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
4068 case OS_PROFESSIONAL:
4070 case OS_DATACENTER:
4072 case OS_ADVSERVER:
4073 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
4074 case OS_SERVER:
4076 case OS_TERMINALSERVER:
4079 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
4081 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
4082 return TRUE;
4083 case OS_WELCOMELOGONUI:
4084 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
4085 return FALSE;
4086 case OS_DOMAINMEMBER:
4087 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
4088 return TRUE;
4089 case OS_ANYSERVER:
4091 case OS_WOW6432:
4092 {
4093 BOOL is_wow64;
4095 return is_wow64;
4096 }
4097 case OS_WEBSERVER:
4101 case OS_TABLETPC:
4102 FIXME("(OS_TABLETPC) What should we return here?\n");
4103 return FALSE;
4104 case OS_SERVERADMINUI:
4105 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
4106 return FALSE;
4107 case OS_MEDIACENTER:
4108 FIXME("(OS_MEDIACENTER) What should we return here?\n");
4109 return FALSE;
4110 case OS_APPLIANCE:
4111 FIXME("(OS_APPLIANCE) What should we return here?\n");
4112 return FALSE;
4113 case 0x25: /*OS_VISTAORGREATER*/
4114 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
4115 }
4116
4117#undef ISOS_RETURN
4118
4119 WARN("(0x%x) unknown parameter\n",feature);
4120
4121 return FALSE;
4122}
4123
4124#ifdef __REACTOS__
4125/*************************************************************************
4126 * @ [SHLWAPI.438]
4127 */
4129{
4130 WCHAR valueW[MAX_PATH], bufferW[MAX_PATH];
4131 DWORD dwSize = ARRAY_SIZE(bufferW) * sizeof(CHAR);
4132 HRESULT hr;
4133
4135 valueW[ARRAY_SIZE(valueW) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
4136
4137 if (RegQueryValueExW(hkey, valueW, NULL, NULL, (LPBYTE)bufferW, &dwSize) != ERROR_SUCCESS)
4138 return E_FAIL;
4139
4140 hr = SHLoadIndirectString(bufferW, bufferW, ARRAY_SIZE(bufferW), NULL);
4141 if (FAILED(hr))
4142 return hr;
4143
4144 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buf, size, NULL, NULL);
4145 if (size > 0)
4146 buf[size - 1] = ANSI_NULL; /* Avoid buffer overrun */
4147 return S_OK;
4148}
4149#endif
4150
4151/*************************************************************************
4152 * @ [SHLWAPI.439]
4153 */
4155{
4156 DWORD type, sz = size * sizeof(WCHAR);
4157
4158 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
4159 return E_FAIL;
4160
4162}
4163
4164/*************************************************************************
4165 * @ [SHLWAPI.478]
4166 *
4167 * Call IInputObject_TranslateAcceleratorIO() on an object.
4168 *
4169 * PARAMS
4170 * lpUnknown [I] Object supporting the IInputObject interface.
4171 * lpMsg [I] Key message to be processed.
4172 *
4173 * RETURNS
4174 * Success: S_OK.
4175 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4176 */
4178{
4179 IInputObject* lpInput = NULL;
4180 HRESULT hRet = E_INVALIDARG;
4181
4182 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
4183 if (lpUnknown)
4184 {
4185 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4186 (void**)&lpInput);
4187 if (SUCCEEDED(hRet) && lpInput)
4188 {
4189 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
4190 IInputObject_Release(lpInput);
4191 }
4192 }
4193 return hRet;
4194}
4195
4196/*************************************************************************
4197 * @ [SHLWAPI.481]
4198 *
4199 * Call IInputObject_HasFocusIO() on an object.
4200 *
4201 * PARAMS
4202 * lpUnknown [I] Object supporting the IInputObject interface.
4203 *
4204 * RETURNS
4205 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4206 * or S_FALSE otherwise.
4207 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4208 */
4210{
4211 IInputObject* lpInput = NULL;
4212 HRESULT hRet = E_INVALIDARG;
4213
4214 TRACE("(%p)\n", lpUnknown);
4215 if (lpUnknown)
4216 {
4217 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4218 (void**)&lpInput);
4219 if (SUCCEEDED(hRet) && lpInput)
4220 {
4221 hRet = IInputObject_HasFocusIO(lpInput);
4222 IInputObject_Release(lpInput);
4223 }
4224 }
4225 return hRet;
4226}
4227
4228/*************************************************************************
4229 * ColorRGBToHLS [SHLWAPI.@]
4230 *
4231 * Convert an rgb COLORREF into the hls color space.
4232 *
4233 * PARAMS
4234 * cRGB [I] Source rgb value
4235 * pwHue [O] Destination for converted hue
4236 * pwLuminance [O] Destination for converted luminance
4237 * pwSaturation [O] Destination for converted saturation
4238 *
4239 * RETURNS
4240 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4241 * values.
4242 *
4243 * NOTES
4244 * Output HLS values are constrained to the range (0..240).
4245 * For Achromatic conversions, Hue is set to 160.
4246 */
4248 LPWORD pwLuminance, LPWORD pwSaturation)
4249{
4250 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4251
4252 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4253
4254 wR = GetRValue(cRGB);
4255 wG = GetGValue(cRGB);
4256 wB = GetBValue(cRGB);
4257
4258 wMax = max(wR, max(wG, wB));
4259 wMin = min(wR, min(wG, wB));
4260
4261 /* Luminosity */
4262 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4263
4264 if (wMax == wMin)
4265 {
4266 /* Achromatic case */
4267 wSaturation = 0;
4268 /* Hue is now unrepresentable, but this is what native returns... */
4269 wHue = 160;
4270 }
4271 else
4272 {
4273 /* Chromatic case */
4274 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4275
4276 /* Saturation */
4277 if (wLuminosity <= 120)
4278 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4279 else
4280 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4281
4282 /* Hue */
4283 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4284 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4285 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4286
4287 if (wR == wMax)
4288 wHue = wBNorm - wGNorm;
4289 else if (wG == wMax)
4290 wHue = 80 + wRNorm - wBNorm;
4291 else
4292 wHue = 160 + wGNorm - wRNorm;
4293 if (wHue < 0)
4294 wHue += 240;
4295 else if (wHue > 240)
4296 wHue -= 240;
4297 }
4298 if (pwHue)
4299 *pwHue = wHue;
4300 if (pwLuminance)
4301 *pwLuminance = wLuminosity;
4302 if (pwSaturation)
4303 *pwSaturation = wSaturation;
4304}
4305
4306/*************************************************************************
4307 * SHCreateShellPalette [SHLWAPI.@]
4308 */
4310{
4311 FIXME("stub\n");
4312 return CreateHalftonePalette(hdc);
4313}
4314
4315/*************************************************************************
4316 * SHGetInverseCMAP (SHLWAPI.@)
4317 *
4318 * Get an inverse color map table.
4319 *
4320 * PARAMS
4321 * lpCmap [O] Destination for color map
4322 * dwSize [I] Size of memory pointed to by lpCmap
4323 *
4324 * RETURNS
4325 * Success: S_OK.
4326 * Failure: E_POINTER, If lpCmap is invalid.
4327 * E_INVALIDARG, If dwFlags is invalid
4328 * E_OUTOFMEMORY, If there is no memory available
4329 *
4330 * NOTES
4331 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4332 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4333 * internal CMap.
4334 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4335 * this DLL's internal CMap.
4336 */
4338{
4339 if (dwSize == 4) {
4340 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4341 *dest = (DWORD)0xabba1249;
4342 return 0;
4343 }
4344 FIXME("(%p, %#x) stub\n", dest, dwSize);
4345 return 0;
4346}
4347
4348/*************************************************************************
4349 * SHIsLowMemoryMachine [SHLWAPI.@]
4350 *
4351 * Determine if the current computer has low memory.
4352 *
4353 * PARAMS
4354 * dwType [I] Zero.
4355 *
4356 * RETURNS
4357 * TRUE if the users machine has 16 Megabytes of memory or less,
4358 * FALSE otherwise.
4359 */
4361{
4362#ifdef __REACTOS__
4364 static int is_low = -1;
4365 TRACE("(0x%08x)\n", dwType);
4366 if (dwType == 0 && is_low == -1)
4367 {
4369 is_low = (status.dwTotalPhys <= 0x1000000);
4370 }
4371 return is_low;
4372#else
4373 FIXME("(0x%08x) stub\n", dwType);
4374 return FALSE;
4375#endif
4376}
4377
4378/*************************************************************************
4379 * GetMenuPosFromID [SHLWAPI.@]
4380 *
4381 * Return the position of a menu item from its Id.
4382 *
4383 * PARAMS
4384 * hMenu [I] Menu containing the item
4385 * wID [I] Id of the menu item
4386 *
4387 * RETURNS
4388 * Success: The index of the menu item in hMenu.
4389 * Failure: -1, If the item is not found.
4390 */
4392{
4394 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4395
4396 TRACE("%p %u\n", hMenu, wID);
4397
4398 while (nIter < nCount)
4399 {
4400 mi.cbSize = sizeof(mi);
4401 mi.fMask = MIIM_ID;
4402 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4403 {
4404 TRACE("ret %d\n", nIter);
4405 return nIter;
4406 }
4407 nIter++;
4408 }
4409
4410 return -1;
4411}
4412
4413/*************************************************************************
4414 * @ [SHLWAPI.179]
4415 *
4416 * Same as SHLWAPI.GetMenuPosFromID
4417 */
4419{
4420 TRACE("%p %u\n", hMenu, uID);
4421 return GetMenuPosFromID(hMenu, uID);
4422}
4423
4424
4425/*************************************************************************
4426 * @ [SHLWAPI.448]
4427 */
4429{
4430 while (*lpwstr)
4431 {
4432 if (*lpwstr == '/')
4433 *lpwstr = '\\';
4434 lpwstr++;
4435 }
4436}
4437
4438
4439/*************************************************************************
4440 * @ [SHLWAPI.461]
4441 */
4443{
4444 FIXME("(0x%08x) stub\n", dwUnknown);
4445 return 0;
4446}
4447
4448
4449/*************************************************************************
4450 * @ [SHLWAPI.549]
4451 */
4453 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4454{
4455 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4456}
4457
4458/*************************************************************************
4459 * SHSkipJunction [SHLWAPI.@]
4460 *
4461 * Determine if a bind context can be bound to an object
4462 *
4463 * PARAMS
4464 * pbc [I] Bind context to check
4465 * pclsid [I] CLSID of object to be bound to
4466 *
4467 * RETURNS
4468 * TRUE: If it is safe to bind
4469 * FALSE: If pbc is invalid or binding would not be safe
4470 *
4471 */
4473{
4474 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4475 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4476 BOOL bRet = FALSE;
4477
4478 if (pbc)
4479 {
4480 IUnknown* lpUnk;
4481
4482 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4483 {
4484 CLSID clsid;
4485
4486 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4487 IsEqualGUID(pclsid, &clsid))
4488 bRet = TRUE;
4489
4490 IUnknown_Release(lpUnk);
4491 }
4492 }
4493 return bRet;
4494}
4495
4496/***********************************************************************
4497 * SHGetShellKey (SHLWAPI.491)
4498 */
4500{
4501 enum _shellkey_flags {
4502 SHKEY_Root_HKCU = 0x1,
4503 SHKEY_Root_HKLM = 0x2,
4504 SHKEY_Key_Explorer = 0x00,
4505 SHKEY_Key_Shell = 0x10,
4506 SHKEY_Key_ShellNoRoam = 0x20,
4507 SHKEY_Key_Classes = 0x30,
4508 SHKEY_Subkey_Default = 0x0000,
4510 SHKEY_Subkey_Handlers = 0x2000,
4512 SHKEY_Subkey_Volatile = 0x4000,
4513 SHKEY_Subkey_MUICache = 0x5000,
4514 SHKEY_Subkey_FileExts = 0x6000
4515 };
4516
4517 static const WCHAR explorerW[] = {'S','o','f','t','w','a','r','e','\\',
4518 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4519 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4520 'E','x','p','l','o','r','e','r','\\'};
4521 static const WCHAR shellW[] = {'S','o','f','t','w','a','r','e','\\',
4522 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4523 'S','h','e','l','l','\\'};
4524 static const WCHAR shell_no_roamW[] = {'S','o','f','t','w','a','r','e','\\',
4525 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4526 'S','h','e','l','l','N','o','R','o','a','m','\\'};
4527 static const WCHAR classesW[] = {'S','o','f','t','w','a','r','e','\\',
4528 'C','l','a','s','s','e','s','\\'};
4529
4530 static const WCHAR localized_resource_nameW[] = {'L','o','c','a','l','i','z','e','d',
4531 'R','e','s','o','u','r','c','e','N','a','m','e','\\'};
4532 static const WCHAR handlersW[] = {'H','a','n','d','l','e','r','s','\\'};
4533 static const WCHAR associationsW[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'};
4534 static const WCHAR volatileW[] = {'V','o','l','a','t','i','l','e','\\'};
4535 static const WCHAR mui_cacheW[] = {'M','U','I','C','a','c','h','e','\\'};
4536 static const WCHAR file_extsW[] = {'F','i','l','e','E','x','t','s','\\'};
4537
4538 WCHAR *path;
4539 const WCHAR *key, *subkey;
4540 int size_key, size_subkey, size_user;
4541 HKEY hkey = NULL;
4542
4543 TRACE("(0x%08x, %s, %d)\n", flags, debugstr_w(sub_key), create);
4544
4545 /* For compatibility with Vista+ */
4546 if(flags == 0x1ffff)
4547 flags = 0x21;
4548
4549 switch(flags&0xff0) {
4550 case SHKEY_Key_Explorer:
4551 key = explorerW;
4552 size_key = sizeof(explorerW);
4553 break;
4554 case SHKEY_Key_Shell:
4555 key = shellW;
4556 size_key = sizeof(shellW);
4557 break;
4559 key = shell_no_roamW;
4560 size_key = sizeof(shell_no_roamW);
4561 break;
4562 case SHKEY_Key_Classes:
4563 key = classesW;
4564 size_key = sizeof(classesW);
4565 break;
4566 default:
4567 FIXME("unsupported flags (0x%08x)\n", flags);
4568 return NULL;
4569 }
4570
4571 switch(flags&0xff000) {
4573 subkey = NULL;
4574 size_subkey = 0;
4575 break;
4577 subkey = localized_resource_nameW;
4578 size_subkey = sizeof(localized_resource_nameW);
4579 break;
4581 subkey = handlersW;
4582 size_subkey = sizeof(handlersW);
4583 break;
4585 subkey = associationsW;
4586 size_subkey = sizeof(associationsW);
4587 break;
4589 subkey = volatileW;
4590 size_subkey = sizeof(volatileW);
4591 break;
4593 subkey = mui_cacheW;
4594 size_subkey = sizeof(mui_cacheW);
4595 break;
4597 subkey = file_extsW;
4598 size_subkey = sizeof(file_extsW);
4599 break;
4600 default:
4601 FIXME("unsupported flags (0x%08x)\n", flags);
4602 return NULL;
4603 }
4604
4605 if(sub_key)
4606 size_user = lstrlenW(sub_key)*sizeof(WCHAR);
4607 else
4608 size_user = 0;
4609
4610 path = HeapAlloc(GetProcessHeap(), 0, size_key+size_subkey+size_user+sizeof(WCHAR));
4611 if(!path) {
4612 ERR("Out of memory\n");
4613 return NULL;
4614 }
4615
4616 memcpy(path, key, size_key);
4617 if(subkey)
4618 memcpy(path+size_key/sizeof(WCHAR), subkey, size_subkey);
4619 if(sub_key)
4620 memcpy(path+(size_key+size_subkey)/sizeof(WCHAR), sub_key, size_user);
4621 path[(size_key+size_subkey+size_user)/sizeof(WCHAR)] = '\0';
4622
4623 if(create)
4625 path, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &hkey, NULL);
4626 else
4628 path, 0, MAXIMUM_ALLOWED, &hkey);
4629
4631 return hkey;
4632}
4633
4634/***********************************************************************
4635 * SHQueueUserWorkItem (SHLWAPI.@)
4636 */
4638 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4639 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4640{
4641 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4642 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4643
4644 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4645 FIXME("Unsupported arguments\n");
4646
4647 return QueueUserWorkItem(pfnCallback, pContext, 0);
4648}
4649
4650/***********************************************************************
4651 * SHSetTimerQueueTimer (SHLWAPI.263)
4652 */
4654 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4655 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4656{
4657 HANDLE hNewTimer;
4658
4659 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4660 if (dwFlags & TPS_LONGEXECTIME) {
4661 dwFlags &= ~TPS_LONGEXECTIME;
4663 }
4664 if (dwFlags & TPS_EXECUTEIO) {
4665 dwFlags &= ~TPS_EXECUTEIO;
4667 }
4668
4669 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4670 dwDueTime, dwPeriod, dwFlags))
4671 return NULL;
4672
4673 return hNewTimer;
4674}
4675
4676/***********************************************************************
4677 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4678 */
4680{
4681 IInputObjectSite *pIOS = NULL;
4682 HRESULT hRet = E_INVALIDARG;
4683
4684 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4685
4686 if (lpUnknown)
4687 {
4688 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4689 (void **)&pIOS);
4690 if (SUCCEEDED(hRet) && pIOS)
4691 {
4692 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4694 }
4695 }
4696 return hRet;
4697}
4698
4699/***********************************************************************
4700 * SKAllocValueW (SHLWAPI.519)
4701 */
4704{
4705 DWORD ret, size;
4706 HKEY hkey;
4707
4708 TRACE("(0x%x, %s, %s, %p, %p, %p)\n", flags, debugstr_w(subkey),
4710
4711 hkey = SHGetShellKey(flags, subkey, FALSE);
4712 if (!hkey)
4714
4715 ret = SHQueryValueExW(hkey