ReactOS 0.4.15-dev-8191-gbc6c731
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#ifdef __REACTOS__
2444 * VOID
2445#else
2446 * Success: S_OK
2447#endif
2448 *
2449 */
2450#ifdef __REACTOS__
2452#else
2454#endif
2455{
2456#ifdef __REACTOS__
2457 HFONT hOldFont, hNewFont;
2458 LOGFONTW lfOldFont, lfNewFont;
2459 HWND hwndItem;
2460
2461 TRACE("(%p, %d)\n", hWnd, id);
2462
2463 hOldFont = (HFONT)SendMessageW(hWnd, WM_GETFONT, 0, 0);
2464 GetObjectW(hOldFont, sizeof(lfOldFont), &lfOldFont);
2465 SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lfNewFont), &lfNewFont, 0);
2466
2467 if (lfOldFont.lfCharSet == lfNewFont.lfCharSet)
2468 return;
2469
2470 hNewFont = GetPropW(hWnd, L"PropDlgFont");
2471 if (!hNewFont)
2472 {
2473 /* Create the icon-title font of the same height */
2474 lfNewFont.lfHeight = lfOldFont.lfHeight;
2475 hNewFont = CreateFontIndirectW(&lfNewFont);
2476
2477 /* If creating the font is failed, then keep the old font */
2478 if (!hNewFont)
2479 hNewFont = hOldFont;
2480
2481 /* Set "PropDlgFont" property if the font is changed */
2482 if (hOldFont != hNewFont)
2483 SetPropW(hWnd, L"PropDlgFont", hNewFont);
2484 }
2485
2486 hwndItem = GetDlgItem(hWnd, id);
2487 SendMessageW(hwndItem, WM_SETFONT, (WPARAM)hNewFont, 0);
2488#else
2489 FIXME("(%p, %d) stub\n", hWnd, id);
2490 return S_OK;
2491#endif
2492}
2493
2494/*************************************************************************
2495 * @ [SHLWAPI.221]
2496 *
2497 * Remove the "PropDlgFont" property from a window.
2498 *
2499 * PARAMS
2500 * hWnd [I] Window to remove the property from
2501 *
2502 * RETURNS
2503 * A handle to the removed property, or NULL if it did not exist.
2504 */
2506{
2507 HANDLE hProp;
2508
2509 TRACE("(%p)\n", hWnd);
2510
2511 hProp = GetPropA(hWnd, "PropDlgFont");
2512
2513 if(hProp)
2514 {
2515 DeleteObject(hProp);
2516 hProp = RemovePropA(hWnd, "PropDlgFont");
2517 }
2518 return hProp;
2519}
2520
2521/*************************************************************************
2522 * @ [SHLWAPI.236]
2523 *
2524 * Load the in-process server of a given GUID.
2525 *
2526 * PARAMS
2527 * refiid [I] GUID of the server to load.
2528 *
2529 * RETURNS
2530 * Success: A handle to the loaded server dll.
2531 * Failure: A NULL handle.
2532 */
2534{
2535 HKEY newkey;
2536 DWORD type, count;
2537 CHAR value[MAX_PATH], string[MAX_PATH];
2538
2539 strcpy(string, "CLSID\\");
2540 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2541 strcat(string, "\\InProcServer32");
2542
2543 count = MAX_PATH;
2544 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2545 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2546 RegCloseKey(newkey);
2547 return LoadLibraryExA(value, 0, 0);
2548}
2549
2550/*************************************************************************
2551 * @ [SHLWAPI.237]
2552 *
2553 * Unicode version of SHLWAPI_183.
2554 */
2556{
2558
2559 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2560
2561 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2562 return TRUE;
2563 return RegisterClassW(lpWndClass);
2564}
2565
2566/*************************************************************************
2567 * @ [SHLWAPI.238]
2568 *
2569 * Unregister a list of classes.
2570 *
2571 * PARAMS
2572 * hInst [I] Application instance that registered the classes
2573 * lppClasses [I] List of class names
2574 * iCount [I] Number of names in lppClasses
2575 *
2576 * RETURNS
2577 * Nothing.
2578 */
2580{
2582
2583 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2584
2585 while (iCount > 0)
2586 {
2587 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2588 UnregisterClassA(*lppClasses, hInst);
2589 lppClasses++;
2590 iCount--;
2591 }
2592}
2593
2594/*************************************************************************
2595 * @ [SHLWAPI.239]
2596 *
2597 * Unicode version of SHUnregisterClassesA.
2598 */
2600{
2602
2603 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2604
2605 while (iCount > 0)
2606 {
2607 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2608 UnregisterClassW(*lppClasses, hInst);
2609 lppClasses++;
2610 iCount--;
2611 }
2612}
2613
2614/*************************************************************************
2615 * @ [SHLWAPI.240]
2616 *
2617 * Call The correct (Ascii/Unicode) default window procedure for a window.
2618 *
2619 * PARAMS
2620 * hWnd [I] Window to call the default procedure for
2621 * uMessage [I] Message ID
2622 * wParam [I] WPARAM of message
2623 * lParam [I] LPARAM of message
2624 *
2625 * RETURNS
2626 * The result of calling DefWindowProcA() or DefWindowProcW().
2627 */
2629{
2630 if (IsWindowUnicode(hWnd))
2631 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2632 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2633}
2634
2635/*************************************************************************
2636 * @ [SHLWAPI.256]
2637 */
2639{
2640 HRESULT hRet = E_INVALIDARG;
2641 LPOBJECTWITHSITE lpSite = NULL;
2642
2643 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2644
2645 if (lpUnknown && iid && lppSite)
2646 {
2647 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2648 (void**)&lpSite);
2649 if (SUCCEEDED(hRet) && lpSite)
2650 {
2651 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2652 IObjectWithSite_Release(lpSite);
2653 }
2654 }
2655 return hRet;
2656}
2657
2658/*************************************************************************
2659 * @ [SHLWAPI.257]
2660 *
2661 * Create a worker window using CreateWindowExA().
2662 *
2663 * PARAMS
2664 * wndProc [I] Window procedure
2665 * hWndParent [I] Parent window
2666 * dwExStyle [I] Extra style flags
2667 * dwStyle [I] Style flags
2668 * hMenu [I] Window menu
2669 * wnd_extra [I] Window extra bytes value
2670 *
2671 * RETURNS
2672 * Success: The window handle of the newly created window.
2673 * Failure: 0.
2674 */
2676 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra)
2677{
2678 static const char szClass[] = "WorkerA";
2679 WNDCLASSA wc;
2680 HWND hWnd;
2681
2682 TRACE("(%p, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
2683 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
2684
2685 /* Create Window class */
2686 wc.style = 0;
2688 wc.cbClsExtra = 0;
2689 wc.cbWndExtra = sizeof(LONG_PTR);
2691 wc.hIcon = NULL;
2693 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2694 wc.lpszMenuName = NULL;
2695 wc.lpszClassName = szClass;
2696
2697 SHRegisterClassA(&wc);
2698
2699 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2700 hWndParent, hMenu, shlwapi_hInstance, 0);
2701 if (hWnd)
2702 {
2703 SetWindowLongPtrW(hWnd, 0, wnd_extra);
2705 }
2706
2707 return hWnd;
2708}
2709
2710#ifndef __REACTOS__ /* The followings are defined in <shlwapi_undoc.h> */
2711typedef struct tagPOLICYDATA
2712{
2713 DWORD policy; /* flags value passed to SHRestricted */
2714 LPCWSTR appstr; /* application str such as "Explorer" */
2715 LPCWSTR keystr; /* name of the actual registry key / policy */
2717
2718#define SHELL_NO_POLICY 0xffffffff
2719
2720/* default shell policy registry key */
2721static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2722 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2723 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2724 '\\','P','o','l','i','c','i','e','s',0};
2725#endif /* ndef __REACTOS__ */
2726
2727/*************************************************************************
2728 * @ [SHLWAPI.271]
2729 *
2730 * Retrieve a policy value from the registry.
2731 *
2732 * PARAMS
2733 * lpSubKey [I] registry key name
2734 * lpSubName [I] subname of registry key
2735 * lpValue [I] value name of registry value
2736 *
2737 * RETURNS
2738 * the value associated with the registry key or 0 if not found
2739 */
2741{
2742#ifdef __REACTOS__
2744 DWORD dwSize, dwValue = 0;
2745
2746 TRACE("(%s, %s, %s)\n", debugstr_w(lpSubKey), debugstr_w(lpSubName), debugstr_w(lpValue));
2747
2748 if (!lpSubKey)
2749 lpSubKey = L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies";
2750
2751 PathCombineW(szPath, lpSubKey, lpSubName);
2752
2753 dwSize = sizeof(dwValue);
2754 if (SHGetValueW(HKEY_LOCAL_MACHINE, szPath, lpValue, NULL, &dwValue, &dwSize) == ERROR_SUCCESS)
2755 return dwValue;
2756
2757 dwSize = sizeof(dwValue);
2758 SHGetValueW(HKEY_CURRENT_USER, szPath, lpValue, NULL, &dwValue, &dwSize);
2759 return dwValue;
2760#else
2761 DWORD retval, datsize = sizeof(retval);
2762 HKEY hKey;
2763
2764 if (!lpSubKey)
2765 lpSubKey = strRegistryPolicyW;
2766
2767 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2768 if (retval != ERROR_SUCCESS)
2769 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2770 if (retval != ERROR_SUCCESS)
2771 return 0;
2772
2773 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2775 return retval;
2776#endif
2777}
2778
2779/*************************************************************************
2780 * @ [SHLWAPI.266]
2781 *
2782 * Helper function to retrieve the possibly cached value for a specific policy
2783 *
2784 * PARAMS
2785 * policy [I] The policy to look for
2786 * initial [I] Main registry key to open, if NULL use default
2787 * polTable [I] Table of known policies, 0 terminated
2788 * polArr [I] Cache array of policy values
2789 *
2790 * RETURNS
2791 * The retrieved policy value or 0 if not successful
2792 *
2793 * NOTES
2794 * This function is used by the native SHRestricted function to search for the
2795 * policy and cache it once retrieved. The current Wine implementation uses a
2796 * different POLICYDATA structure and implements a similar algorithm adapted to
2797 * that structure.
2798 */
2799#ifdef __REACTOS__
2803 _In_ LPCWSTR initial,
2804 _In_ const POLICYDATA *polTable,
2805 _Inout_ LPDWORD polArr)
2806#else
2808 DWORD policy,
2809 LPCWSTR initial,
2810 LPPOLICYDATA polTable,
2811 LPDWORD polArr)
2812#endif
2813{
2814 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2815
2816#ifndef __REACTOS__
2817 if (!polTable || !polArr)
2818 return 0;
2819#endif
2820
2821#ifndef __REACTOS__
2822 for (;polTable->appstr; polTable++, polArr++)
2823#else
2824 for (;polTable->policy; polTable++, polArr++)
2825#endif
2826 {
2827 if (policy == polTable->policy)
2828 {
2829 /* we have a known policy */
2830
2831 /* check if this policy has been cached */
2832 if (*polArr == SHELL_NO_POLICY)
2833 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2834 return *polArr;
2835 }
2836 }
2837 /* we don't know this policy, return 0 */
2838 TRACE("unknown policy: (%08x)\n", policy);
2839 return 0;
2840}
2841
2842/*************************************************************************
2843 * @ [SHLWAPI.267]
2844 *
2845 * Get an interface from an object.
2846 *
2847 * RETURNS
2848 * Success: S_OK. ppv contains the requested interface.
2849 * Failure: An HRESULT error code.
2850 *
2851 * NOTES
2852 * This QueryInterface asks the inner object for an interface. In case
2853 * of aggregation this request would be forwarded by the inner to the
2854 * outer object. This function asks the inner object directly for the
2855 * interface circumventing the forwarding to the outer object.
2856 */
2858 IUnknown * pUnk, /* [in] Outer object */
2859 IUnknown * pInner, /* [in] Inner object */
2860 IID * riid, /* [in] Interface GUID to query for */
2861 LPVOID* ppv) /* [out] Destination for queried interface */
2862{
2863 HRESULT hret = E_NOINTERFACE;
2864 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2865
2866 *ppv = NULL;
2867 if(pUnk && pInner) {
2868 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2869 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2870 }
2871 TRACE("-- 0x%08x\n", hret);
2872 return hret;
2873}
2874
2875/*************************************************************************
2876 * @ [SHLWAPI.268]
2877 *
2878 * Move a reference from one interface to another.
2879 *
2880 * PARAMS
2881 * lpDest [O] Destination to receive the reference
2882 * lppUnknown [O] Source to give up the reference to lpDest
2883 *
2884 * RETURNS
2885 * Nothing.
2886 */
2888{
2889 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2890
2891 if (*lppUnknown)
2892 {
2893 /* Copy Reference*/
2894 IUnknown_AddRef(lpDest);
2895 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2896 }
2897}
2898
2899/*************************************************************************
2900 * @ [SHLWAPI.269]
2901 *
2902 * Convert an ASCII string of a CLSID into a CLSID.
2903 *
2904 * PARAMS
2905 * idstr [I] String representing a CLSID in registry format
2906 * id [O] Destination for the converted CLSID
2907 *
2908 * RETURNS
2909 * Success: TRUE. id contains the converted CLSID.
2910 * Failure: FALSE.
2911 */
2913{
2914 WCHAR wClsid[40];
2915 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2916 return SUCCEEDED(CLSIDFromString(wClsid, id));
2917}
2918
2919/*************************************************************************
2920 * @ [SHLWAPI.270]
2921 *
2922 * Unicode version of GUIDFromStringA.
2923 */
2925{
2926 return SUCCEEDED(CLSIDFromString((LPCOLESTR)idstr, id));
2927}
2928
2929/*************************************************************************
2930 * @ [SHLWAPI.276]
2931 *
2932 * Determine if the browser is integrated into the shell, and set a registry
2933 * key accordingly.
2934 *
2935 * PARAMS
2936 * None.
2937 *
2938 * RETURNS
2939 * 1, If the browser is not integrated.
2940 * 2, If the browser is integrated.
2941 *
2942 * NOTES
2943 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2944 * either set to TRUE, or removed depending on whether the browser is deemed
2945 * to be integrated.
2946 */
2948{
2949 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2950 static DWORD dwState = 0;
2951 HKEY hKey;
2952 DWORD dwRet, dwData, dwSize;
2953 HMODULE hshell32;
2954
2955 if (dwState)
2956 return dwState;
2957
2958 /* If shell32 exports DllGetVersion(), the browser is integrated */
2959 dwState = 1;
2960 hshell32 = LoadLibraryA("shell32.dll");
2961 if (hshell32)
2962 {
2963 FARPROC pDllGetVersion;
2964 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2965 dwState = pDllGetVersion ? 2 : 1;
2966 FreeLibrary(hshell32);
2967 }
2968
2969 /* Set or delete the key accordingly */
2971 "Software\\Microsoft\\Internet Explorer", 0,
2973 if (!dwRet)
2974 {
2975 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2976 (LPBYTE)&dwData, &dwSize);
2977
2978 if (!dwRet && dwState == 1)
2979 {
2980 /* Value exists but browser is not integrated */
2981 RegDeleteValueA(hKey, szIntegratedBrowser);
2982 }
2983 else if (dwRet && dwState == 2)
2984 {
2985 /* Browser is integrated but value does not exist */
2986 dwData = TRUE;
2987 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2988 (LPBYTE)&dwData, sizeof(dwData));
2989 }
2991 }
2992 return dwState;
2993}
2994
2995/*************************************************************************
2996 * @ [SHLWAPI.278]
2997 *
2998 * Unicode version of SHCreateWorkerWindowA.
2999 */
3001 DWORD dwStyle, HMENU hMenu, LONG_PTR wnd_extra)
3002{
3003 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', 0 };
3004 WNDCLASSW wc;
3005 HWND hWnd;
3006
3007 TRACE("(%p, %p, 0x%08x, 0x%08x, %p, 0x%08lx)\n",
3008 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
3009
3010 /* If our OS is natively ANSI, use the ANSI version */
3011 if (GetVersion() & 0x80000000) /* not NT */
3012 {
3013 TRACE("fallback to ANSI, ver 0x%08x\n", GetVersion());
3014 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, wnd_extra);
3015 }
3016
3017 /* Create Window class */
3018 wc.style = 0;
3020 wc.cbClsExtra = 0;
3021 wc.cbWndExtra = sizeof(LONG_PTR);
3023 wc.hIcon = NULL;
3025 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
3026 wc.lpszMenuName = NULL;
3027 wc.lpszClassName = szClass;
3028
3029 SHRegisterClassW(&wc);
3030
3031 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
3032 hWndParent, hMenu, shlwapi_hInstance, 0);
3033 if (hWnd)
3034 {
3035 SetWindowLongPtrW(hWnd, 0, wnd_extra);
3037 }
3038
3039 return hWnd;
3040}
3041
3042/*************************************************************************
3043 * @ [SHLWAPI.279]
3044 *
3045 * Get and show a context menu from a shell folder.
3046 *
3047 * PARAMS
3048 * hWnd [I] Window displaying the shell folder
3049 * lpFolder [I] IShellFolder interface
3050 * lpApidl [I] Id for the particular folder desired
3051 *
3052 * RETURNS
3053 * Success: S_OK.
3054 * Failure: An HRESULT error code indicating the error.
3055 */
3057{
3058 TRACE("%p %p %p\n", hWnd, lpFolder, lpApidl);
3059 return SHInvokeCommand(hWnd, lpFolder, lpApidl, 0);
3060}
3061
3062/*************************************************************************
3063 * @ [SHLWAPI.281]
3064 *
3065 * _SHPackDispParamsV
3066 */
3068{
3069 VARIANTARG *iter;
3070
3071 TRACE("(%p %p %u ...)\n", params, args, cnt);
3072
3073 params->rgvarg = args;
3074 params->rgdispidNamedArgs = NULL;
3075 params->cArgs = cnt;
3076 params->cNamedArgs = 0;
3077
3078 iter = args+cnt;
3079
3080 while(iter-- > args) {
3081 V_VT(iter) = va_arg(valist, enum VARENUM);
3082
3083 TRACE("vt=%d\n", V_VT(iter));
3084
3085 if(V_VT(iter) & VT_BYREF) {
3086 V_BYREF(iter) = va_arg(valist, LPVOID);
3087 } else {
3088 switch(V_VT(iter)) {
3089 case VT_I4:
3090 V_I4(iter) = va_arg(valist, LONG);
3091 break;
3092 case VT_BSTR:
3093 V_BSTR(iter) = va_arg(valist, BSTR);
3094 break;
3095 case VT_DISPATCH:
3096 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
3097 break;
3098 case VT_BOOL:
3099 V_BOOL(iter) = va_arg(valist, int);
3100 break;
3101 case VT_UNKNOWN:
3102 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
3103 break;
3104 default:
3105 V_VT(iter) = VT_I4;
3106 V_I4(iter) = va_arg(valist, LONG);
3107 }
3108 }
3109 }
3110
3111 return S_OK;
3112}
3113
3114/*************************************************************************
3115 * @ [SHLWAPI.282]
3116 *
3117 * SHPackDispParams
3118 */
3120{
3122 HRESULT hres;
3123
3124 __ms_va_start(valist, cnt);
3127 return hres;
3128}
3129
3130/*************************************************************************
3131 * SHLWAPI_InvokeByIID
3132 *
3133 * This helper function calls IDispatch::Invoke for each sink
3134 * which implements given iid or IDispatch.
3135 *
3136 */
3138 IConnectionPoint* iCP,
3139 REFIID iid,
3140 DISPID dispId,
3141 DISPPARAMS* dispParams)
3142{
3143 IEnumConnections *enumerator;
3144 CONNECTDATA rgcd;
3145 static DISPPARAMS empty = {NULL, NULL, 0, 0};
3146 DISPPARAMS* params = dispParams;
3147
3148 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
3149 if (FAILED(result))
3150 return result;
3151
3152 /* Invoke is never happening with an NULL dispParams */
3153 if (!params)
3154 params = &empty;
3155
3156 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
3157 {
3158 IDispatch *dispIface;
3159 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
3160 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
3161 {
3162 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
3163 IDispatch_Release(dispIface);
3164 }
3165 IUnknown_Release(rgcd.pUnk);
3166 }
3167
3168 IEnumConnections_Release(enumerator);
3169
3170 return S_OK;
3171}
3172
3173/*************************************************************************
3174 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
3175 */
3177 DISPID dispId, DISPPARAMS* dispParams,
3178 DWORD unknown1, DWORD unknown2 )
3179{
3180 IID iid;
3182
3183 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
3184
3185 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3186 if (SUCCEEDED(result))
3187 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3188 else
3189 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3190
3191 return result;
3192}
3193
3194
3195/*************************************************************************
3196 * @ [SHLWAPI.284]
3197 *
3198 * IConnectionPoint_SimpleInvoke
3199 */
3201 IConnectionPoint* iCP,
3202 DISPID dispId,
3203 DISPPARAMS* dispParams)
3204{
3205 IID iid;
3207
3208 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
3209
3210 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3211 if (SUCCEEDED(result))
3212 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3213 else
3214 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3215
3216 return result;
3217}
3218
3219/*************************************************************************
3220 * @ [SHLWAPI.285]
3221 *
3222 * Notify an IConnectionPoint object of changes.
3223 *
3224 * PARAMS
3225 * lpCP [I] Object to notify
3226 * dispID [I]
3227 *
3228 * RETURNS
3229 * Success: S_OK.
3230 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3231 * IConnectionPoint interface.
3232 */
3234{
3235 IEnumConnections *lpEnum;
3236 HRESULT hRet = E_NOINTERFACE;
3237
3238 TRACE("(%p,0x%8X)\n", lpCP, dispID);
3239
3240 /* Get an enumerator for the connections */
3241 if (lpCP)
3242 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
3243
3244 if (SUCCEEDED(hRet))
3245 {
3246 IPropertyNotifySink *lpSink;
3247 CONNECTDATA connData;
3248 ULONG ulFetched;
3249
3250 /* Call OnChanged() for every notify sink in the connection point */
3251 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
3252 {
3253 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
3254 lpSink)
3255 {
3256 IPropertyNotifySink_OnChanged(lpSink, dispID);
3257 IPropertyNotifySink_Release(lpSink);
3258 }
3259 IUnknown_Release(connData.pUnk);
3260 }
3261
3262 IEnumConnections_Release(lpEnum);
3263 }
3264 return hRet;
3265}
3266
3267/*************************************************************************
3268 * @ [SHLWAPI.286]
3269 *
3270 * IUnknown_CPContainerInvokeParam
3271 */
3274 REFIID riid,
3275 DISPID dispId,
3277 DWORD cParams, ...)
3278{
3280 IConnectionPoint *iCP;
3282 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3284
3285 if (!container)
3286 return E_NOINTERFACE;
3287
3288 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
3289 if (FAILED(result))
3290 return result;
3291
3292 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
3293 IConnectionPointContainer_Release(iCPC);
3294 if(FAILED(result))
3295 return result;
3296
3297 __ms_va_start(valist, cParams);
3298 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
3300
3301 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3302 IConnectionPoint_Release(iCP);
3303
3304 return result;
3305}
3306
3307/*************************************************************************
3308 * @ [SHLWAPI.287]
3309 *
3310 * Notify an IConnectionPointContainer object of changes.
3311 *
3312 * PARAMS
3313 * lpUnknown [I] Object to notify
3314 * dispID [I]
3315 *
3316 * RETURNS
3317 * Success: S_OK.
3318 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3319 * IConnectionPointContainer interface.
3320 */
3322{
3324 HRESULT hRet = E_NOINTERFACE;
3325
3326 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3327
3328 if (lpUnknown)
3329 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3330
3331 if (SUCCEEDED(hRet))
3332 {
3333 IConnectionPoint* lpCP;
3334
3335 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3336 IConnectionPointContainer_Release(lpCPC);
3337
3338 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3339 IConnectionPoint_Release(lpCP);
3340 }
3341 return hRet;
3342}
3343
3344/*************************************************************************
3345 * @ [SHLWAPI.289]
3346 *
3347 * See PlaySoundW.
3348 */
3350{
3351 return PlaySoundW(pszSound, hmod, fdwSound);
3352}
3353
3354#ifndef __REACTOS__ /* See propbag.cpp */
3355/*************************************************************************
3356 * @ [SHLWAPI.294]
3357 *
3358 * Retrieve a key value from an INI file. See GetPrivateProfileString for
3359 * more information.
3360 *
3361 * PARAMS
3362 * appName [I] The section in the INI file that contains the key
3363 * keyName [I] The key to be retrieved
3364 * out [O] The buffer into which the key's value will be copied
3365 * outLen [I] The length of the `out' buffer
3366 * filename [I] The location of the INI file
3367 *
3368 * RETURNS
3369 * Length of string copied into `out'.
3370 */
3372 DWORD outLen, LPCWSTR filename)
3373{
3374 INT ret;
3375 WCHAR *buf;
3376
3377 TRACE("(%s,%s,%p,%08x,%s)\n", debugstr_w(appName), debugstr_w(keyName),
3378 out, outLen, debugstr_w(filename));
3379
3380 if(outLen == 0)
3381 return 0;
3382
3383 buf = HeapAlloc(GetProcessHeap(), 0, outLen * sizeof(WCHAR));
3384 if(!buf){
3385 *out = 0;
3386 return 0;
3387 }
3388
3389 ret = GetPrivateProfileStringW(appName, keyName, NULL, buf, outLen, filename);
3390 if(ret)
3391 strcpyW(out, buf);
3392 else
3393 *out = 0;
3394
3396
3397 return strlenW(out);
3398}
3399#endif
3400
3401#ifndef __REACTOS__ /* See propbag.cpp */
3402/*************************************************************************
3403 * @ [SHLWAPI.295]
3404 *
3405 * Set a key value in an INI file. See WritePrivateProfileString for
3406 * more information.
3407 *
3408 * PARAMS
3409 * appName [I] The section in the INI file that contains the key
3410 * keyName [I] The key to be set
3411 * str [O] The value of the key
3412 * filename [I] The location of the INI file
3413 *
3414 * RETURNS
3415 * Success: TRUE
3416 * Failure: FALSE
3417 */
3420{
3421 TRACE("(%s, %p, %s, %s)\n", debugstr_w(appName), keyName, debugstr_w(str),
3423
3425}
3426#endif
3427
3428/*************************************************************************
3429 * @ [SHLWAPI.313]
3430 *
3431 * See SHGetFileInfoW.
3432 */
3434 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3435{
3436 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3437}
3438
3439/*************************************************************************
3440 * @ [SHLWAPI.318]
3441 *
3442 * See DragQueryFileW.
3443 */
3444UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3445{
3446 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3447}
3448
3449/*************************************************************************
3450 * @ [SHLWAPI.333]
3451 *
3452 * See SHBrowseForFolderW.
3453 */
3455{
3456 return SHBrowseForFolderW(lpBi);
3457}
3458
3459/*************************************************************************
3460 * @ [SHLWAPI.334]
3461 *
3462 * See SHGetPathFromIDListW.
3463 */
3465{
3466 return SHGetPathFromIDListW(pidl, pszPath);
3467}
3468
3469/*************************************************************************
3470 * @ [SHLWAPI.335]
3471 *
3472 * See ShellExecuteExW.
3473 */
3475{
3476 return ShellExecuteExW(lpExecInfo);
3477}
3478
3479/*************************************************************************
3480 * @ [SHLWAPI.336]
3481 *
3482 * See SHFileOperationW.
3483 */
3485{
3486 return SHFileOperationW(lpFileOp);
3487}
3488
3489/*************************************************************************
3490 * @ [SHLWAPI.342]
3491 *
3492 */
3494{
3496}
3497
3498/*************************************************************************
3499 * @ [SHLWAPI.350]
3500 *
3501 * See GetFileVersionInfoSizeW.
3502 */
3504{
3506}
3507
3508/*************************************************************************
3509 * @ [SHLWAPI.351]
3510 *
3511 * See GetFileVersionInfoW.
3512 */
3515{
3517}
3518
3519/*************************************************************************
3520 * @ [SHLWAPI.352]
3521 *
3522 * See VerQueryValueW.
3523 */
3525 LPVOID *lplpBuffer, UINT *puLen )
3526{
3527 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3528}
3529
3530#define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3531#define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3532#define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3533
3534/*************************************************************************
3535 * @ [SHLWAPI.355]
3536 *
3537 * Change the modality of a shell object.
3538 *
3539 * PARAMS
3540 * lpUnknown [I] Object to make modeless
3541 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3542 *
3543 * RETURNS
3544 * Success: S_OK. The modality lpUnknown is changed.
3545 * Failure: An HRESULT error code indicating the error.
3546 *
3547 * NOTES
3548 * lpUnknown must support the IOleInPlaceFrame interface, the
3549 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3550 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3551 * or this call will fail.
3552 */
3554{
3555 IUnknown *lpObj;
3556 HRESULT hRet;
3557
3558 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3559
3560 if (!lpUnknown)
3561 return E_FAIL;
3562
3565 else if (IsIface(IOleInPlaceFrame))
3567 else if (IsIface(IShellBrowser))
3571 else if (IsIface(IDocHostUIHandler))
3573 else
3574 return hRet;
3575
3576 IUnknown_Release(lpObj);
3577 return S_OK;
3578}
3579
3580/*************************************************************************
3581 * @ [SHLWAPI.357]
3582 *
3583 * See SHGetNewLinkInfoW.
3584 */
3587{
3588 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3589}
3590
3591/*************************************************************************
3592 * @ [SHLWAPI.358]
3593 *
3594 * See SHDefExtractIconW.
3595 */
3596UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3597 HICON* phiconSmall, UINT nIconSize)
3598{
3599 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3600}
3601
3602/*************************************************************************
3603 * @ [SHLWAPI.363]
3604 *
3605 * Get and show a context menu from a shell folder.
3606 *
3607 * PARAMS
3608 * hWnd [I] Window displaying the shell folder
3609 * lpFolder [I] IShellFolder interface
3610 * lpApidl [I] Id for the particular folder desired
3611 * dwCommandId [I] The command ID to invoke (0=invoke default)
3612 *
3613 * RETURNS
3614 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3615 * executed.
3616 * Failure: An HRESULT error code indicating the error.
3617 */
3619{
3620 IContextMenu *iContext;
3621 HRESULT hRet;
3622
3623 TRACE("(%p, %p, %p, %u)\n", hWnd, lpFolder, lpApidl, dwCommandId);
3624
3625 if (!lpFolder)
3626 return E_FAIL;
3627
3628 /* Get the context menu from the shell folder */
3629 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3630 &IID_IContextMenu, 0, (void**)&iContext);
3631 if (SUCCEEDED(hRet))
3632 {
3633 HMENU hMenu;
3634 if ((hMenu = CreatePopupMenu()))
3635 {
3636 HRESULT hQuery;
3637
3638 /* Add the context menu entries to the popup */
3639 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3640 dwCommandId ? CMF_NORMAL : CMF_DEFAULTONLY);
3641
3642 if (SUCCEEDED(hQuery))
3643 {
3644 if (!dwCommandId)
3645 dwCommandId = GetMenuDefaultItem(hMenu, 0, 0);
3646 if (dwCommandId != (UINT)-1)
3647 {
3648 CMINVOKECOMMANDINFO cmIci;
3649 /* Invoke the default item */
3650 memset(&cmIci,0,sizeof(cmIci));
3651 cmIci.cbSize = sizeof(cmIci);
3652 cmIci.fMask = CMIC_MASK_ASYNCOK;
3653 cmIci.hwnd = hWnd;
3654#ifdef __REACTOS__ /* r75561 */
3655 cmIci.lpVerb = MAKEINTRESOURCEA(dwCommandId - 1);
3656#else
3657 cmIci.lpVerb = MAKEINTRESOURCEA(dwCommandId);
3658#endif
3659 cmIci.nShow = SW_SHOWNORMAL;
3660
3661 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3662 }
3663 }
3664 DestroyMenu(hMenu);
3665 }
3666 IContextMenu_Release(iContext);
3667 }
3668 return hRet;
3669}
3670
3671/*************************************************************************
3672 * @ [SHLWAPI.370]
3673 *
3674 * See ExtractIconW.
3675 */
3677 UINT nIconIndex)
3678{
3679 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3680}
3681
3682/*************************************************************************
3683 * @ [SHLWAPI.377]
3684 *
3685 * Load a library from the directory of a particular process.
3686 *
3687 * PARAMS
3688 * new_mod [I] Library name
3689 * inst_hwnd [I] Module whose directory is to be used
3690 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3691 *
3692 * RETURNS
3693 * Success: A handle to the loaded module
3694 * Failure: A NULL handle.
3695 */
3696HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3697{
3698 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3699 * each call here.
3700 * FIXME: Native shows calls to:
3701 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3702 * CheckVersion
3703 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3704 * RegQueryValueExA for "LPKInstalled"
3705 * RegCloseKey
3706 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3707 * RegQueryValueExA for "ResourceLocale"
3708 * RegCloseKey
3709 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3710 * RegQueryValueExA for "Locale"
3711 * RegCloseKey
3712 * and then tests the Locale ("en" for me).
3713 * code below
3714 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3715 */
3716 CHAR mod_path[2*MAX_PATH];
3717 LPSTR ptr;
3718 DWORD len;
3719
3720 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3721 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3722 if (!len || len >= sizeof(mod_path)) return NULL;
3723
3724 ptr = strrchr(mod_path, '\\');
3725 if (ptr) {
3726 strcpy(ptr+1, new_mod);
3727 TRACE("loading %s\n", debugstr_a(mod_path));
3728 return LoadLibraryA(mod_path);
3729 }
3730 return NULL;
3731}
3732
3733/*************************************************************************
3734 * @ [SHLWAPI.378]
3735 *
3736 * Unicode version of MLLoadLibraryA.
3737 */
3738HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3739{
3740 WCHAR mod_path[2*MAX_PATH];
3741 LPWSTR ptr;
3742 DWORD len;
3743
3744 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3745 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3746 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3747
3748 ptr = strrchrW(mod_path, '\\');
3749 if (ptr) {
3750 strcpyW(ptr+1, new_mod);
3751 TRACE("loading %s\n", debugstr_w(mod_path));
3752 return LoadLibraryW(mod_path);
3753 }
3754 return NULL;
3755}
3756
3757/*************************************************************************
3758 * ColorAdjustLuma [SHLWAPI.@]
3759 *
3760 * Adjust the luminosity of a color
3761 *
3762 * PARAMS
3763 * cRGB [I] RGB value to convert
3764 * dwLuma [I] Luma adjustment
3765 * bUnknown [I] Unknown
3766 *
3767 * RETURNS
3768 * The adjusted RGB color.
3769 */
3770COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3771{
3772 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3773
3774 if (dwLuma)
3775 {
3776 WORD wH, wL, wS;
3777
3778 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3779
3780 FIXME("Ignoring luma adjustment\n");
3781
3782 /* FIXME: The adjustment is not linear */
3783
3784 cRGB = ColorHLSToRGB(wH, wL, wS);
3785 }
3786 return cRGB;
3787}
3788
3789/*************************************************************************
3790 * @ [SHLWAPI.389]
3791 *
3792 * See GetSaveFileNameW.
3793 */
3795{
3796 return GetSaveFileNameW(ofn);
3797}
3798
3799/*************************************************************************
3800 * @ [SHLWAPI.390]
3801 *
3802 * See WNetRestoreConnectionW.
3803 */
3805{
3806 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3807}
3808
3809/*************************************************************************
3810 * @ [SHLWAPI.391]
3811 *
3812 * See WNetGetLastErrorW.
3813 */
3814DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3815 LPWSTR lpNameBuf, DWORD nNameBufSize)
3816{
3817 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3818}
3819
3820/*************************************************************************
3821 * @ [SHLWAPI.401]
3822 *
3823 * See PageSetupDlgW.
3824 */
3826{
3827 return PageSetupDlgW(pagedlg);
3828}
3829
3830/*************************************************************************
3831 * @ [SHLWAPI.402]
3832 *
3833 * See PrintDlgW.
3834 */
3836{
3837 return PrintDlgW(printdlg);
3838}
3839
3840/*************************************************************************
3841 * @ [SHLWAPI.403]
3842 *
3843 * See GetOpenFileNameW.
3844 */
3846{
3847 return GetOpenFileNameW(ofn);
3848}
3849
3850/*************************************************************************
3851 * @ [SHLWAPI.404]
3852 */
3854{
3855 /* Windows attempts to get an IPersist interface and, if that fails, an
3856 * IPersistFolder interface on the folder passed-in here. If one of those
3857 * interfaces is available, it then calls GetClassID on the folder... and
3858 * then calls IShellFolder_EnumObjects no matter what, even crashing if
3859 * lpFolder isn't actually an IShellFolder object. The purpose of getting
3860 * the ClassID is unknown, so we don't do it here.
3861 *
3862 * For discussion and detailed tests, see:
3863 * "shlwapi: Be less strict on which type of IShellFolder can be enumerated"
3864 * wine-devel mailing list, 3 Jun 2010
3865 */
3866
3867 return IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3868}
3869
3870/* INTERNAL: Map from HLS color space to RGB */
3871static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3872{
3873 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3874
3875 if (wHue > 160)
3876 return wMid1;
3877 else if (wHue > 120)
3878 wHue = 160 - wHue;
3879 else if (wHue > 40)
3880 return wMid2;
3881
3882 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3883}
3884
3885/* Convert to RGB and scale into RGB range (0..255) */
3886#define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3887
3888/*************************************************************************
3889 * ColorHLSToRGB [SHLWAPI.@]
3890 *
3891 * Convert from hls color space into an rgb COLORREF.
3892 *
3893 * PARAMS
3894 * wHue [I] Hue amount
3895 * wLuminosity [I] Luminosity amount
3896 * wSaturation [I] Saturation amount
3897 *
3898 * RETURNS
3899 * A COLORREF representing the converted color.
3900 *
3901 * NOTES
3902 * Input hls values are constrained to the range (0..240).
3903 */
3904COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3905{
3906 WORD wRed;
3907
3908 if (wSaturation)
3909 {
3910 WORD wGreen, wBlue, wMid1, wMid2;
3911
3912 if (wLuminosity > 120)
3913 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3914 else
3915 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3916
3917 wMid1 = wLuminosity * 2 - wMid2;
3918
3919 wRed = GET_RGB(wHue + 80);
3920 wGreen = GET_RGB(wHue);
3921 wBlue = GET_RGB(wHue - 80);
3922
3923 return RGB(wRed, wGreen, wBlue);
3924 }
3925
3926 wRed = wLuminosity * 255 / 240;
3927 return RGB(wRed, wRed, wRed);
3928}
3929
3930/*************************************************************************
3931 * @ [SHLWAPI.413]
3932 *
3933 * Get the current docking status of the system.
3934 *
3935 * PARAMS
3936 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3937 *
3938 * RETURNS
3939 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3940 * a notebook.
3941 */
3943{
3944 HW_PROFILE_INFOA hwInfo;
3945
3946 TRACE("(0x%08x)\n", dwFlags);
3947
3948 GetCurrentHwProfileA(&hwInfo);
3949 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3950 {
3951 case DOCKINFO_DOCKED:
3952 case DOCKINFO_UNDOCKED:
3954 default:
3955 return 0;
3956 }
3957}
3958
3959/*************************************************************************
3960 * @ [SHLWAPI.416]
3961 *
3962 */
3964{
3965
3966 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_w(helpfile), flags1, ptr1, flags2);
3967 return 0;
3968}
3969
3970/*************************************************************************
3971 * @ [SHLWAPI.417]
3972 *
3973 */
3975{
3976
3977 FIXME("(%p, %s, 0x%x, %p, %d)\n", hwnd, debugstr_a(helpfile), flags1, ptr1, flags2);
3978 return 0;
3979}
3980
3981/*************************************************************************
3982 * @ [SHLWAPI.418]
3983 *
3984 * Function seems to do FreeLibrary plus other things.
3985 *
3986 * FIXME native shows the following calls:
3987 * RtlEnterCriticalSection
3988 * LocalFree
3989 * GetProcAddress(Comctl32??, 150L)
3990 * DPA_DeletePtr
3991 * RtlLeaveCriticalSection
3992 * followed by the FreeLibrary.
3993 * The above code may be related to .377 above.
3994 */
3996{
3997 FIXME("(%p) semi-stub\n", hModule);
3998 return FreeLibrary(hModule);
3999}
4000
4001/*************************************************************************
4002 * @ [SHLWAPI.419]
4003 */
4005 FIXME(": stub\n");
4006 return TRUE;
4007}
4008
4009/*************************************************************************
4010 * @ [SHLWAPI.429]
4011 * FIXME I have no idea what this function does or what its arguments are.
4012 */
4014{
4015 FIXME("(%p) stub\n", hInst);
4016 return FALSE;
4017}
4018
4019
4020/*************************************************************************
4021 * @ [SHLWAPI.430]
4022 */
4024{
4025 FIXME("(%p,%p) stub\n", hInst, hHeap);
4026 return E_FAIL; /* This is what is used if shlwapi not loaded */
4027}
4028
4029/*************************************************************************
4030 * @ [SHLWAPI.431]
4031 */
4033{
4034 FIXME("(0x%08x)stub\n", x);
4035 return 0xabba1247;
4036}
4037
4038/*************************************************************************
4039 * @ [SHLWAPI.432]
4040 *
4041 * See SHSendMessageBroadcastW
4042 *
4043 */
4045{
4047 SMTO_ABORTIFHUNG, 2000, NULL);
4048}
4049
4050/*************************************************************************
4051 * @ [SHLWAPI.433]
4052 *
4053 * A wrapper for sending Broadcast Messages to all top level Windows
4054 *
4055 */
4057{
4059 SMTO_ABORTIFHUNG, 2000, NULL);
4060}
4061
4062/*************************************************************************
4063 * @ [SHLWAPI.436]
4064 *
4065 * Convert a Unicode string CLSID into a CLSID.
4066 *
4067 * PARAMS
4068 * idstr [I] string containing a CLSID in text form
4069 * id [O] CLSID extracted from the string
4070 *
4071 * RETURNS
4072 * S_OK on success or E_INVALIDARG on failure
4073 */
4075{
4076 return CLSIDFromString((LPCOLESTR)idstr, id);
4077}
4078
4079/*************************************************************************
4080 * @ [SHLWAPI.437]
4081 *
4082 * Determine if the OS supports a given feature.
4083 *
4084 * PARAMS
4085 * dwFeature [I] Feature requested (undocumented)
4086 *
4087 * RETURNS
4088 * TRUE If the feature is available.
4089 * FALSE If the feature is not available.
4090 */
4092{
4094 DWORD platform, majorv, minorv;
4095
4097 if(!GetVersionExA(&osvi)) {
4098 ERR("GetVersionEx failed\n");
4099 return FALSE;
4100 }
4101
4102 majorv = osvi.dwMajorVersion;
4103 minorv = osvi.dwMinorVersion;
4105
4106#define ISOS_RETURN(x) \
4107 TRACE("(0x%x) ret=%d\n",feature,(x)); \
4108 return (x);
4109
4110 switch(feature) {
4111 case OS_WIN32SORGREATER:
4114 case OS_NT:
4116 case OS_WIN95ORGREATER:
4118 case OS_NT4ORGREATER:
4119 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
4122 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
4123 case OS_WIN98ORGREATER:
4125 case OS_WIN98_GOLD:
4127 case OS_WIN2000PRO:
4128 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
4129 case OS_WIN2000SERVER:
4130 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4132 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4134 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4135 case OS_WIN2000TERMINAL:
4136 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
4137 case OS_EMBEDDED:
4138 FIXME("(OS_EMBEDDED) What should we return here?\n");
4139 return FALSE;
4140 case OS_TERMINALCLIENT:
4141 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
4142 return FALSE;
4144 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
4145 return FALSE;
4146 case OS_WIN95_GOLD:
4148 case OS_MEORGREATER:
4150 case OS_XPORGREATER:
4151 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
4152 case OS_HOME:
4153 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
4154 case OS_PROFESSIONAL:
4156 case OS_DATACENTER:
4158 case OS_ADVSERVER:
4159 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
4160 case OS_SERVER:
4162 case OS_TERMINALSERVER:
4165 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
4167 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
4168 return TRUE;
4169 case OS_WELCOMELOGONUI:
4170 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
4171 return FALSE;
4172 case OS_DOMAINMEMBER:
4173 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
4174 return TRUE;
4175 case OS_ANYSERVER:
4177 case OS_WOW6432:
4178 {
4179 BOOL is_wow64;
4181 return is_wow64;
4182 }
4183 case OS_WEBSERVER:
4187 case OS_TABLETPC:
4188 FIXME("(OS_TABLETPC) What should we return here?\n");
4189 return FALSE;
4190 case OS_SERVERADMINUI:
4191 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
4192 return FALSE;
4193 case OS_MEDIACENTER:
4194 FIXME("(OS_MEDIACENTER) What should we return here?\n");
4195 return FALSE;
4196 case OS_APPLIANCE:
4197 FIXME("(OS_APPLIANCE) What should we return here?\n");
4198 return FALSE;
4199 case 0x25: /*OS_VISTAORGREATER*/
4200 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
4201 }
4202
4203#undef ISOS_RETURN
4204
4205 WARN("(0x%x) unknown parameter\n",feature);
4206
4207 return FALSE;
4208}
4209
4210#ifdef __REACTOS__
4211/*************************************************************************
4212 * @ [SHLWAPI.438]
4213 */
4215{
4216 WCHAR valueW[MAX_PATH], bufferW[MAX_PATH];
4217 DWORD dwSize = ARRAY_SIZE(bufferW) * sizeof(CHAR);
4218 HRESULT hr;
4219
4221 valueW[ARRAY_SIZE(valueW) - 1] = UNICODE_NULL; /* Avoid buffer overrun */
4222
4223 if (RegQueryValueExW(hkey, valueW, NULL, NULL, (LPBYTE)bufferW, &dwSize) != ERROR_SUCCESS)
4224 return E_FAIL;
4225
4226 hr = SHLoadIndirectString(bufferW, bufferW, ARRAY_SIZE(bufferW), NULL);
4227 if (FAILED(hr))
4228 return hr;
4229
4230 WideCharToMultiByte(CP_ACP, 0, bufferW, -1, buf, size, NULL, NULL);
4231 if (size > 0)
4232 buf[size - 1] = ANSI_NULL; /* Avoid buffer overrun */
4233 return S_OK;
4234}
4235#endif
4236
4237/*************************************************************************
4238 * @ [SHLWAPI.439]
4239 */
4241{
4242 DWORD type, sz = size * sizeof(WCHAR);
4243
4244 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
4245 return E_FAIL;
4246
4248}
4249
4250/*************************************************************************
4251 * @ [SHLWAPI.478]
4252 *
4253 * Call IInputObject_TranslateAcceleratorIO() on an object.
4254 *
4255 * PARAMS
4256 * lpUnknown [I] Object supporting the IInputObject interface.
4257 * lpMsg [I] Key message to be processed.
4258 *
4259 * RETURNS
4260 * Success: S_OK.
4261 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4262 */
4264{
4265 IInputObject* lpInput = NULL;
4266 HRESULT hRet = E_INVALIDARG;
4267
4268 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
4269 if (lpUnknown)
4270 {
4271 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4272 (void**)&lpInput);
4273 if (SUCCEEDED(hRet) && lpInput)
4274 {
4275 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
4276 IInputObject_Release(lpInput);
4277 }
4278 }
4279 return hRet;
4280}
4281
4282/*************************************************************************
4283 * @ [SHLWAPI.481]
4284 *
4285 * Call IInputObject_HasFocusIO() on an object.
4286 *
4287 * PARAMS
4288 * lpUnknown [I] Object supporting the IInputObject interface.
4289 *
4290 * RETURNS
4291 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4292 * or S_FALSE otherwise.
4293 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4294 */
4296{
4297 IInputObject* lpInput = NULL;
4298 HRESULT hRet = E_INVALIDARG;
4299
4300 TRACE("(%p)\n", lpUnknown);
4301 if (lpUnknown)
4302 {
4303 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4304 (void**)&lpInput);
4305 if (SUCCEEDED(hRet) && lpInput)
4306 {
4307 hRet = IInputObject_HasFocusIO(lpInput);
4308 IInputObject_Release(lpInput);
4309 }
4310 }
4311 return hRet;
4312}
4313
4314/*************************************************************************
4315 * ColorRGBToHLS [SHLWAPI.@]
4316 *
4317 * Convert an rgb COLORREF into the hls color space.
4318 *
4319 * PARAMS
4320 * cRGB [I] Source rgb value
4321 * pwHue [O] Destination for converted hue
4322 * pwLuminance [O] Destination for converted luminance
4323 * pwSaturation [O] Destination for converted saturation
4324 *
4325 * RETURNS
4326 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4327 * values.
4328 *
4329 * NOTES
4330 * Output HLS values are constrained to the range (0..240).
4331 * For Achromatic conversions, Hue is set to 160.
4332 */
4334 LPWORD pwLuminance, LPWORD pwSaturation)
4335{
4336 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4337
4338 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4339
4340 wR = GetRValue(cRGB);
4341 wG = GetGValue(cRGB);
4342 wB = GetBValue(cRGB);
4343
4344 wMax = max(wR, max(wG, wB));
4345 wMin = min(wR, min(wG, wB));
4346
4347 /* Luminosity */
4348 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4349
4350 if (wMax == wMin)
4351 {
4352 /* Achromatic case */
4353 wSaturation = 0;
4354 /* Hue is now unrepresentable, but this is what native returns... */
4355 wHue = 160;
4356 }
4357 else
4358 {
4359 /* Chromatic case */
4360 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4361
4362 /* Saturation */
4363 if (wLuminosity <= 120)
4364 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4365 else
4366 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4367
4368 /* Hue */
4369 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4370 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4371 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4372
4373 if (wR == wMax)
4374 wHue = wBNorm - wGNorm;
4375 else if (wG == wMax)
4376 wHue = 80 + wRNorm - wBNorm;
4377 else
4378 wHue = 160 + wGNorm - wRNorm;
4379 if (wHue < 0)
4380 wHue += 240;
4381 else if (wHue > 240)
4382 wHue -= 240;
4383 }
4384 if (pwHue)
4385 *pwHue = wHue;
4386 if (pwLuminance)
4387 *pwLuminance = wLuminosity;
4388 if (pwSaturation)
4389 *pwSaturation = wSaturation;
4390}
4391
4392/*************************************************************************
4393 * SHCreateShellPalette [SHLWAPI.@]
4394 */
4396{
4397 FIXME("stub\n");
4398 return CreateHalftonePalette(hdc);
4399}
4400
4401/*************************************************************************
4402 * SHGetInverseCMAP (SHLWAPI.@)
4403 *
4404 * Get an inverse color map table.
4405 *
4406 * PARAMS
4407 * lpCmap [O] Destination for color map
4408 * dwSize [I] Size of memory pointed to by lpCmap
4409 *
4410 * RETURNS
4411 * Success: S_OK.
4412 * Failure: E_POINTER, If lpCmap is invalid.
4413 * E_INVALIDARG, If dwFlags is invalid
4414 * E_OUTOFMEMORY, If there is no memory available
4415 *
4416 * NOTES
4417 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4418 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4419 * internal CMap.
4420 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4421 * this DLL's internal CMap.
4422 */
4424{
4425 if (dwSize == 4) {
4426 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4427 *dest = (DWORD)0xabba1249;
4428 return 0;
4429 }
4430 FIXME("(%p, %#x) stub\n", dest, dwSize);
4431 return 0;
4432}
4433
4434/*************************************************************************
4435 * SHIsLowMemoryMachine [SHLWAPI.@]
4436 *
4437 * Determine if the current computer has low memory.
4438 *
4439 * PARAMS
4440 * dwType [I] Zero.
4441 *
4442 * RETURNS
4443 * TRUE if the users machine has 16 Megabytes of memory or less,
4444 * FALSE otherwise.
4445 */
4447{
4448#ifdef __REACTOS__
4450 static int is_low = -1;
4451 TRACE("(0x%08x)\n", dwType);
4452 if (dwType == 0 && is_low == -1)
4453 {
4455 is_low = (status.dwTotalPhys <= 0x1000000);
4456 }
4457 return is_low;
4458#else
4459 FIXME("(0x%08x) stub\n", dwType);
4460 return FALSE;
4461#endif
4462}
4463
4464/*************************************************************************
4465 * GetMenuPosFromID [SHLWAPI.@]
4466 *
4467 * Return the position of a menu item from its Id.
4468 *
4469 * PARAMS
4470 * hMenu [I] Menu containing the item
4471 * wID [I] Id of the menu item
4472 *
4473 * RETURNS
4474 * Success: The index of the menu item in hMenu.
4475 * Failure: -1, If the item is not found.
4476 */
4478{
4480 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4481
4482 TRACE("%p %u\n", hMenu, wID);
4483
4484 while (nIter < nCount)
4485 {
4486 mi.cbSize = sizeof(mi);
4487 mi.fMask = MIIM_ID;
4488 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4489 {
4490 TRACE("ret %d\n", nIter);
4491 return nIter;
4492 }
4493 nIter++;
4494 }
4495
4496 return -1;
4497}
4498
4499/*************************************************************************
4500 * @ [SHLWAPI.179]
4501 *
4502 * Same as SHLWAPI.GetMenuPosFromID
4503 */
4505{
4506 TRACE("%p %u\n", hMenu, uID);
4507 return GetMenuPosFromID(hMenu, uID);
4508}
4509
4510
4511/*************************************************************************
4512 * @ [SHLWAPI.448]
4513 */
4515{
4516 while (*lpwstr)
4517 {
4518 if (*lpwstr == '/')
4519 *lpwstr = '\\';
4520 lpwstr++;
4521 }
4522}
4523
4524
4525/*************************************************************************
4526 * @ [SHLWAPI.461]
4527 */
4529{
4530 FIXME("(0x%08x) stub\n", dwUnknown);
4531 return 0;
4532}
4533
4534
4535/*************************************************************************
4536 * @ [SHLWAPI.549]
4537 */
4539 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4540{
4541 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4542}
4543
4544/*************************************************************************
4545 * SHSkipJunction [SHLWAPI.@]
4546 *
4547 * Determine if a bind context can be bound to an object
4548 *
4549 * PARAMS
4550 * pbc [I] Bind context to check
4551 * pclsid [I] CLSID of object to be bound to
4552 *
4553 * RETURNS
4554 * TRUE: If it is safe to bind
4555 * FALSE: If pbc is invalid or binding would not be safe
4556 *
4557 */
4559{
4560 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4561 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4562 BOOL bRet = FALSE;
4563
4564 if (pbc)
4565 {
4566 IUnknown* lpUnk;
4567
4568 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4569 {
4570 CLSID clsid;
4571
4572 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4573 IsEqualGUID(pclsid, &clsid))
4574 bRet = TRUE;
4575
4576 IUnknown_Release(lpUnk);
4577 }
4578 }
4579 return bRet;
4580}
4581
4582/***********************************************************************
4583 * SHGetShellKey (SHLWAPI.491)
4584 */
4586{
4587#ifndef __REACTOS__
4588 enum _shellkey_flags {
4589 SHKEY_Root_HKCU = 0x1,
4590 SHKEY_Root_HKLM = 0x2,
4591 SHKEY_Key_Explorer = 0x00,
4592 SHKEY_Key_Shell = 0x10,
4593 SHKEY_Key_ShellNoRoam = 0x20,
4594 SHKEY_Key_Classes = 0x30,
4595 SHKEY_Subkey_Default = 0x0000,
4597 SHKEY_Subkey_Handlers = 0x2000,
4599 SHKEY_Subkey_Volatile = 0x4000,
4600 SHKEY_Subkey_MUICache = 0x5000,
4601 SHKEY_Subkey_FileExts = 0x6000
4602 };
4603#endif
4604
4605 static const WCHAR explorerW[] = {'S','o','f','t','w','a','r','e','\\',
4606 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4607 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4608 'E','x','p','l','o','r','e','r','\\'};
4609 static const WCHAR shellW[] = {'S','o','f','t','w','a','r','e','\\',
4610 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4611 'S','h','e','l','l','\\'};
4612 static const WCHAR shell_no_roamW[] = {'S','o','f','t','w','a','r','e','\\',
4613 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
4614 'S','h','e','l','l','N','o','R','o','a','m','\\'};
4615 static const WCHAR classesW[] = {'S','o','f','t','w','a','r','e','\\',
4616 'C','l','a','s','s','e','s','\\'};
4617
4618 static const WCHAR localized_resource_nameW[] = {'L','o','c','a','l','i','z','e','d',
4619 'R','e','s','o','u','r','c','e','N','a','m','e','\\'};
4620 static const WCHAR handlersW[] = {'H','a','n','d','l','e','r','s','\\'};
4621 static const WCHAR associationsW[] = {'A','s','s','o','c','i','a','t','i','o','n','s','\\'};
4622 static const WCHAR volatileW[] = {'V','o','l','a','t','i','l','e','\\'};
4623 static const WCHAR mui_cacheW[] = {'M','U','I','C','a','c','h','e','\\'};
4624 static const WCHAR file_extsW[] = {'F','i','l','e','E','x','t','s','\\'};
4625
4626 WCHAR *path;
4627 const WCHAR *key, *subkey;
4628 int size_key, size_subkey, size_user;
4629 HKEY hkey = NULL;
4630
4631 TRACE("(0x%08x, %s, %d)\n", flags, debugstr_w(sub_key), create);
4632
4633 /* For compatibility with Vista+ */
4634 if(flags == 0x1ffff)
4635 flags = 0x21;
4636
4637 switch(flags&0xff0) {
4638 case SHKEY_Key_Explorer:
4639 key = explorerW;
4640 size_key = sizeof(explorerW);
4641 break;
4642 case SHKEY_Key_Shell:
4643 key = shellW;
4644 size_key = sizeof(shellW);
4645 break;
4647 key = shell_no_roamW;
4648 size_key = sizeof(shell_no_roamW);
4649 break;
4650 case SHKEY_Key_Classes:
4651 key = classesW;
4652 size_key = sizeof(classesW);
4653 break;
4654 default:
4655 FIXME("unsupported flags (0x%08x)\n", flags);
4656 return NULL;
4657 }
4658
4659 switch(flags&0xff000) {
4661 subkey = NULL;
4662 size_subkey = 0;
4663 break;
4665 subkey = localized_resource_nameW;
4666 size_subkey = sizeof(localized_resource_nameW);
4667 break;
4669 subkey = handlersW;
4670 size_subkey = sizeof(handlersW);
4671 break;
4673 subkey = associationsW;
4674 size_subkey = sizeof(associationsW);
4675 break;
4677 subkey = volatileW;
4678 size_subkey = sizeof(volatileW);
4679 break;
4681 subkey = mui_cacheW;
4682 size_subkey = sizeof(mui_cacheW);
4683 break;
4685 subkey = file_extsW;
4686 size_subkey = sizeof(file_extsW);
4687 break;
4688 default:
4689 FIXME("unsupported flags (0x%08x)\n", flags);
4690 return NULL;
4691 }
4692
4693 if(sub_key)
4694 size_user = lstrlenW(sub_key)*sizeof(WCHAR);
4695 else
4696 size_user = 0;
4697
4698 path = HeapAlloc(GetProcessHeap(), 0, size_key+size_subkey+size_user+sizeof(WCHAR));
4699 if(!path) {
4700 ERR("Out of memory\n");
4701 return NULL;
4702 }
4703
4704 memcpy(path, key, size_key);
4705 if(subkey)
4706 memcpy(path+size_key/sizeof(WCHAR), subkey, size_subkey);
4707 if(sub_key)
4708 memcpy(path+(size_key+size_subkey)/sizeof(WCHAR), sub_key, size_user);
4709 path[(size_key+size_subkey+size_user)/sizeof(WCHAR)] = '\0';
4710
4711 if(create)
4713 path, 0, NULL, 0, MAXIMUM_ALLOWED, NULL, &hkey, NULL);
4714 else
4716 path, 0, MAXIMUM_ALLOWED, &hkey);
4717
4719 return hkey;
4720}