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