sync with trunk r46493
[reactos.git] / dll / win32 / shlwapi / ordinal.c
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 #define NONAMELESSUNION
32 #define NONAMELESSSTRUCT
33
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winnls.h"
37 #include "winreg.h"
38 #include "wingdi.h"
39 #include "winuser.h"
40 #include "winver.h"
41 #include "winnetwk.h"
42 #include "mmsystem.h"
43 #include "objbase.h"
44 #include "exdisp.h"
45 #include "shlobj.h"
46 #include "shlwapi.h"
47 #include "shellapi.h"
48 #include "commdlg.h"
49 #include "mlang.h"
50 #include "mshtmhst.h"
51 #include "wine/unicode.h"
52 #include "wine/debug.h"
53
54
55 WINE_DEFAULT_DEBUG_CHANNEL(shell);
56
57 /* DLL handles for late bound calls */
58 extern HINSTANCE shlwapi_hInstance;
59 extern DWORD SHLWAPI_ThreadRef_index;
60
61 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
62 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
63 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
64
65 /*
66 NOTES: Most functions exported by ordinal seem to be superfluous.
67 The reason for these functions to be there is to provide a wrapper
68 for unicode functions to provide these functions on systems without
69 unicode functions eg. win95/win98. Since we have such functions we just
70 call these. If running Wine with native DLLs, some late bound calls may
71 fail. However, it is better to implement the functions in the forward DLL
72 and recommend the builtin rather than reimplementing the calls here!
73 */
74
75 /*************************************************************************
76 * SHLWAPI_DupSharedHandle
77 *
78 * Internal implemetation of SHLWAPI_11.
79 */
80 static HANDLE SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
81 DWORD dwSrcProcId, DWORD dwAccess,
82 DWORD dwOptions)
83 {
84 HANDLE hDst, hSrc;
85 DWORD dwMyProcId = GetCurrentProcessId();
86 HANDLE hRet = NULL;
87
88 TRACE("(%p,%d,%d,%08x,%08x)\n", hShared, dwDstProcId, dwSrcProcId,
89 dwAccess, dwOptions);
90
91 /* Get dest process handle */
92 if (dwDstProcId == dwMyProcId)
93 hDst = GetCurrentProcess();
94 else
95 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
96
97 if (hDst)
98 {
99 /* Get src process handle */
100 if (dwSrcProcId == dwMyProcId)
101 hSrc = GetCurrentProcess();
102 else
103 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
104
105 if (hSrc)
106 {
107 /* Make handle available to dest process */
108 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
109 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
110 hRet = NULL;
111
112 if (dwSrcProcId != dwMyProcId)
113 CloseHandle(hSrc);
114 }
115
116 if (dwDstProcId != dwMyProcId)
117 CloseHandle(hDst);
118 }
119
120 TRACE("Returning handle %p\n", hRet);
121 return hRet;
122 }
123
124 /*************************************************************************
125 * @ [SHLWAPI.7]
126 *
127 * Create a block of sharable memory and initialise it with data.
128 *
129 * PARAMS
130 * lpvData [I] Pointer to data to write
131 * dwSize [I] Size of data
132 * dwProcId [I] ID of process owning data
133 *
134 * RETURNS
135 * Success: A shared memory handle
136 * Failure: NULL
137 *
138 * NOTES
139 * Ordinals 7-11 provide a set of calls to create shared memory between a
140 * group of processes. The shared memory is treated opaquely in that its size
141 * is not exposed to clients who map it. This is accomplished by storing
142 * the size of the map as the first DWORD of mapped data, and then offsetting
143 * the view pointer returned by this size.
144 *
145 */
146 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
147 {
148 HANDLE hMap;
149 LPVOID pMapped;
150 HANDLE hRet = NULL;
151
152 TRACE("(%p,%d,%d)\n", lpvData, dwSize, dwProcId);
153
154 /* Create file mapping of the correct length */
155 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
156 dwSize + sizeof(dwSize), NULL);
157 if (!hMap)
158 return hRet;
159
160 /* Get a view in our process address space */
161 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
162
163 if (pMapped)
164 {
165 /* Write size of data, followed by the data, to the view */
166 *((DWORD*)pMapped) = dwSize;
167 if (lpvData)
168 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
169
170 /* Release view. All further views mapped will be opaque */
171 UnmapViewOfFile(pMapped);
172 hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
173 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
174 DUPLICATE_SAME_ACCESS);
175 }
176
177 CloseHandle(hMap);
178 return hRet;
179 }
180
181 /*************************************************************************
182 * @ [SHLWAPI.8]
183 *
184 * Get a pointer to a block of shared memory from a shared memory handle.
185 *
186 * PARAMS
187 * hShared [I] Shared memory handle
188 * dwProcId [I] ID of process owning hShared
189 *
190 * RETURNS
191 * Success: A pointer to the shared memory
192 * Failure: NULL
193 *
194 */
195 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
196 {
197 HANDLE hDup;
198 LPVOID pMapped;
199
200 TRACE("(%p %d)\n", hShared, dwProcId);
201
202 /* Get handle to shared memory for current process */
203 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
204 FILE_MAP_ALL_ACCESS, 0);
205 /* Get View */
206 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
207 CloseHandle(hDup);
208
209 if (pMapped)
210 return (char *) pMapped + sizeof(DWORD); /* Hide size */
211 return NULL;
212 }
213
214 /*************************************************************************
215 * @ [SHLWAPI.9]
216 *
217 * Release a pointer to a block of shared memory.
218 *
219 * PARAMS
220 * lpView [I] Shared memory pointer
221 *
222 * RETURNS
223 * Success: TRUE
224 * Failure: FALSE
225 *
226 */
227 BOOL WINAPI SHUnlockShared(LPVOID lpView)
228 {
229 TRACE("(%p)\n", lpView);
230 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
231 }
232
233 /*************************************************************************
234 * @ [SHLWAPI.10]
235 *
236 * Destroy a block of sharable memory.
237 *
238 * PARAMS
239 * hShared [I] Shared memory handle
240 * dwProcId [I] ID of process owning hShared
241 *
242 * RETURNS
243 * Success: TRUE
244 * Failure: FALSE
245 *
246 */
247 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
248 {
249 HANDLE hClose;
250
251 TRACE("(%p %d)\n", hShared, dwProcId);
252
253 /* Get a copy of the handle for our process, closing the source handle */
254 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
255 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
256 /* Close local copy */
257 return CloseHandle(hClose);
258 }
259
260 /*************************************************************************
261 * @ [SHLWAPI.11]
262 *
263 * Copy a sharable memory handle from one process to another.
264 *
265 * PARAMS
266 * hShared [I] Shared memory handle to duplicate
267 * dwDstProcId [I] ID of the process wanting the duplicated handle
268 * dwSrcProcId [I] ID of the process owning hShared
269 * dwAccess [I] Desired DuplicateHandle() access
270 * dwOptions [I] Desired DuplicateHandle() options
271 *
272 * RETURNS
273 * Success: A handle suitable for use by the dwDstProcId process.
274 * Failure: A NULL handle.
275 *
276 */
277 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
278 DWORD dwAccess, DWORD dwOptions)
279 {
280 HANDLE hRet;
281
282 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
283 dwAccess, dwOptions);
284 return hRet;
285 }
286
287 /*************************************************************************
288 * @ [SHLWAPI.13]
289 *
290 * Create and register a clipboard enumerator for a web browser.
291 *
292 * PARAMS
293 * lpBC [I] Binding context
294 * lpUnknown [I] An object exposing the IWebBrowserApp interface
295 *
296 * RETURNS
297 * Success: S_OK.
298 * Failure: An HRESULT error code.
299 *
300 * NOTES
301 * The enumerator is stored as a property of the web browser. If it does not
302 * yet exist, it is created and set before being registered.
303 */
304 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
305 {
306 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
307 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
308 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
309 BSTR property;
310 IEnumFORMATETC* pIEnumFormatEtc = NULL;
311 VARIANTARG var;
312 HRESULT hRet;
313 IWebBrowserApp* pBrowser = NULL;
314
315 TRACE("(%p, %p)\n", lpBC, lpUnknown);
316
317 /* Get An IWebBrowserApp interface from lpUnknown */
318 hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
319 if (FAILED(hRet) || !pBrowser)
320 return E_NOINTERFACE;
321
322 V_VT(&var) = VT_EMPTY;
323
324 /* The property we get is the browsers clipboard enumerator */
325 property = SysAllocString(szProperty);
326 hRet = IWebBrowserApp_GetProperty(pBrowser, property, &var);
327 SysFreeString(property);
328 if (FAILED(hRet))
329 return hRet;
330
331 if (V_VT(&var) == VT_EMPTY)
332 {
333 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
334 char szKeyBuff[128], szValueBuff[128];
335 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
336 FORMATETC* formatList, *format;
337 HKEY hDocs;
338
339 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
340
341 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
342 "Version\\Internet Settings\\Accepted Documents", &hDocs))
343 return E_FAIL;
344
345 /* Get count of values in key */
346 while (!dwRet)
347 {
348 dwKeySize = sizeof(szKeyBuff);
349 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
350 dwCount++;
351 }
352
353 dwNumValues = dwCount;
354
355 /* Note: dwCount = number of items + 1; The extra item is the end node */
356 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
357 if (!formatList)
358 return E_OUTOFMEMORY;
359
360 if (dwNumValues > 1)
361 {
362 dwRet = 0;
363 dwCount = 0;
364
365 dwNumValues--;
366
367 /* Register clipboard formats for the values and populate format list */
368 while(!dwRet && dwCount < dwNumValues)
369 {
370 dwKeySize = sizeof(szKeyBuff);
371 dwValueSize = sizeof(szValueBuff);
372 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
373 (PBYTE)szValueBuff, &dwValueSize);
374 if (!dwRet)
375 return E_FAIL;
376
377 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
378 format->ptd = NULL;
379 format->dwAspect = 1;
380 format->lindex = 4;
381 format->tymed = -1;
382
383 format++;
384 dwCount++;
385 }
386 }
387
388 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
389 format->cfFormat = 0;
390 format->ptd = NULL;
391 format->dwAspect = 1;
392 format->lindex = 4;
393 format->tymed = -1;
394
395 /* Create a clipboard enumerator */
396 hRet = CreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
397
398 if (FAILED(hRet) || !pIEnumFormatEtc)
399 return hRet;
400
401 /* Set our enumerator as the browsers property */
402 V_VT(&var) = VT_UNKNOWN;
403 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
404
405 property = SysAllocString(szProperty);
406 hRet = IWebBrowserApp_PutProperty(pBrowser, property, var);
407 SysFreeString(property);
408 if (FAILED(hRet))
409 {
410 IEnumFORMATETC_Release(pIEnumFormatEtc);
411 goto RegisterDefaultAcceptHeaders_Exit;
412 }
413 }
414
415 if (V_VT(&var) == VT_UNKNOWN)
416 {
417 /* Our variant is holding the clipboard enumerator */
418 IUnknown* pIUnknown = V_UNKNOWN(&var);
419 IEnumFORMATETC* pClone = NULL;
420
421 TRACE("Retrieved IEnumFORMATETC property\n");
422
423 /* Get an IEnumFormatEtc interface from the variants value */
424 pIEnumFormatEtc = NULL;
425 hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
426 (PVOID)&pIEnumFormatEtc);
427 if (hRet == S_OK && pIEnumFormatEtc)
428 {
429 /* Clone and register the enumerator */
430 hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
431 if (hRet == S_OK && pClone)
432 {
433 RegisterFormatEnumerator(lpBC, pClone, 0);
434
435 IEnumFORMATETC_Release(pClone);
436 }
437
438 /* Release the IEnumFormatEtc interface */
439 IEnumFORMATETC_Release(pIUnknown);
440 }
441 IUnknown_Release(V_UNKNOWN(&var));
442 }
443
444 RegisterDefaultAcceptHeaders_Exit:
445 IWebBrowserApp_Release(pBrowser);
446 return hRet;
447 }
448
449 /*************************************************************************
450 * @ [SHLWAPI.15]
451 *
452 * Get Explorers "AcceptLanguage" setting.
453 *
454 * PARAMS
455 * langbuf [O] Destination for language string
456 * buflen [I] Length of langbuf in characters
457 * [0] Success: used length of langbuf
458 *
459 * RETURNS
460 * Success: S_OK. langbuf is set to the language string found.
461 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
462 * does not contain the setting.
463 * HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), If the buffer is not big enough
464 */
465 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
466 {
467 static const WCHAR szkeyW[] = {
468 'S','o','f','t','w','a','r','e','\\',
469 'M','i','c','r','o','s','o','f','t','\\',
470 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
471 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
472 static const WCHAR valueW[] = {
473 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
474 DWORD mystrlen, mytype;
475 DWORD len;
476 HKEY mykey;
477 HRESULT retval;
478 LCID mylcid;
479 WCHAR *mystr;
480 LONG lres;
481
482 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
483
484 if(!langbuf || !buflen || !*buflen)
485 return E_FAIL;
486
487 mystrlen = (*buflen > 20) ? *buflen : 20 ;
488 len = mystrlen * sizeof(WCHAR);
489 mystr = HeapAlloc(GetProcessHeap(), 0, len);
490 mystr[0] = 0;
491 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
492 lres = RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &len);
493 RegCloseKey(mykey);
494 len = lstrlenW(mystr);
495
496 if (!lres && (*buflen > len)) {
497 lstrcpyW(langbuf, mystr);
498 *buflen = len;
499 HeapFree(GetProcessHeap(), 0, mystr);
500 return S_OK;
501 }
502
503 /* Did not find a value in the registry or the user buffer is to small */
504 mylcid = GetUserDefaultLCID();
505 retval = LcidToRfc1766W(mylcid, mystr, mystrlen);
506 len = lstrlenW(mystr);
507
508 memcpy( langbuf, mystr, min(*buflen, len+1)*sizeof(WCHAR) );
509 HeapFree(GetProcessHeap(), 0, mystr);
510
511 if (*buflen > len) {
512 *buflen = len;
513 return S_OK;
514 }
515
516 *buflen = 0;
517 return __HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
518 }
519
520 /*************************************************************************
521 * @ [SHLWAPI.14]
522 *
523 * Ascii version of GetAcceptLanguagesW.
524 */
525 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
526 {
527 WCHAR *langbufW;
528 DWORD buflenW, convlen;
529 HRESULT retval;
530
531 TRACE("(%p, %p) *%p: %d\n", langbuf, buflen, buflen, buflen ? *buflen : -1);
532
533 if(!langbuf || !buflen || !*buflen) return E_FAIL;
534
535 buflenW = *buflen;
536 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
537 retval = GetAcceptLanguagesW(langbufW, &buflenW);
538
539 if (retval == S_OK)
540 {
541 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf, *buflen, NULL, NULL);
542 convlen--; /* do not count the terminating 0 */
543 }
544 else /* copy partial string anyway */
545 {
546 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, *buflen, langbuf, *buflen, NULL, NULL);
547 if (convlen < *buflen)
548 {
549 langbuf[convlen] = 0;
550 convlen--; /* do not count the terminating 0 */
551 }
552 else
553 {
554 convlen = *buflen;
555 }
556 }
557 *buflen = buflenW ? convlen : 0;
558
559 HeapFree(GetProcessHeap(), 0, langbufW);
560 return retval;
561 }
562
563 /*************************************************************************
564 * @ [SHLWAPI.23]
565 *
566 * Convert a GUID to a string.
567 *
568 * PARAMS
569 * guid [I] GUID to convert
570 * lpszDest [O] Destination for string
571 * cchMax [I] Length of output buffer
572 *
573 * RETURNS
574 * The length of the string created.
575 */
576 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
577 {
578 char xguid[40];
579 INT iLen;
580
581 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
582
583 sprintf(xguid, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
584 guid->Data1, guid->Data2, guid->Data3,
585 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
586 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
587
588 iLen = strlen(xguid) + 1;
589
590 if (iLen > cchMax)
591 return 0;
592 memcpy(lpszDest, xguid, iLen);
593 return iLen;
594 }
595
596 /*************************************************************************
597 * @ [SHLWAPI.24]
598 *
599 * Convert a GUID to a string.
600 *
601 * PARAMS
602 * guid [I] GUID to convert
603 * str [O] Destination for string
604 * cmax [I] Length of output buffer
605 *
606 * RETURNS
607 * The length of the string created.
608 */
609 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
610 {
611 WCHAR xguid[40];
612 INT iLen;
613 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
614 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
615 'X','%','0','2','X','%','0','2','X','}',0};
616
617 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
618
619 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
620 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
621 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
622
623 iLen = strlenW(xguid) + 1;
624
625 if (iLen > cchMax)
626 return 0;
627 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
628 return iLen;
629 }
630
631 /*************************************************************************
632 * @ [SHLWAPI.29]
633 *
634 * Determine if a Unicode character is a space.
635 *
636 * PARAMS
637 * wc [I] Character to check.
638 *
639 * RETURNS
640 * TRUE, if wc is a space,
641 * FALSE otherwise.
642 */
643 BOOL WINAPI IsCharSpaceW(WCHAR wc)
644 {
645 WORD CharType;
646
647 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
648 }
649
650 /*************************************************************************
651 * @ [SHLWAPI.30]
652 *
653 * Determine if a Unicode character is a blank.
654 *
655 * PARAMS
656 * wc [I] Character to check.
657 *
658 * RETURNS
659 * TRUE, if wc is a blank,
660 * FALSE otherwise.
661 *
662 */
663 BOOL WINAPI IsCharBlankW(WCHAR wc)
664 {
665 WORD CharType;
666
667 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
668 }
669
670 /*************************************************************************
671 * @ [SHLWAPI.31]
672 *
673 * Determine if a Unicode character is punctuation.
674 *
675 * PARAMS
676 * wc [I] Character to check.
677 *
678 * RETURNS
679 * TRUE, if wc is punctuation,
680 * FALSE otherwise.
681 */
682 BOOL WINAPI IsCharPunctW(WCHAR wc)
683 {
684 WORD CharType;
685
686 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
687 }
688
689 /*************************************************************************
690 * @ [SHLWAPI.32]
691 *
692 * Determine if a Unicode character is a control character.
693 *
694 * PARAMS
695 * wc [I] Character to check.
696 *
697 * RETURNS
698 * TRUE, if wc is a control character,
699 * FALSE otherwise.
700 */
701 BOOL WINAPI IsCharCntrlW(WCHAR wc)
702 {
703 WORD CharType;
704
705 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
706 }
707
708 /*************************************************************************
709 * @ [SHLWAPI.33]
710 *
711 * Determine if a Unicode character is a digit.
712 *
713 * PARAMS
714 * wc [I] Character to check.
715 *
716 * RETURNS
717 * TRUE, if wc is a digit,
718 * FALSE otherwise.
719 */
720 BOOL WINAPI IsCharDigitW(WCHAR wc)
721 {
722 WORD CharType;
723
724 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
725 }
726
727 /*************************************************************************
728 * @ [SHLWAPI.34]
729 *
730 * Determine if a Unicode character is a hex digit.
731 *
732 * PARAMS
733 * wc [I] Character to check.
734 *
735 * RETURNS
736 * TRUE, if wc is a hex digit,
737 * FALSE otherwise.
738 */
739 BOOL WINAPI IsCharXDigitW(WCHAR wc)
740 {
741 WORD CharType;
742
743 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
744 }
745
746 /*************************************************************************
747 * @ [SHLWAPI.35]
748 *
749 */
750 BOOL WINAPI GetStringType3ExW(LPWSTR src, INT count, LPWORD type)
751 {
752 return GetStringTypeW(CT_CTYPE3, src, count, type);
753 }
754
755 /*************************************************************************
756 * @ [SHLWAPI.151]
757 *
758 * Compare two Ascii strings up to a given length.
759 *
760 * PARAMS
761 * lpszSrc [I] Source string
762 * lpszCmp [I] String to compare to lpszSrc
763 * len [I] Maximum length
764 *
765 * RETURNS
766 * A number greater than, less than or equal to 0 depending on whether
767 * lpszSrc is greater than, less than or equal to lpszCmp.
768 */
769 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
770 {
771 return StrCmpNA(lpszSrc, lpszCmp, len);
772 }
773
774 /*************************************************************************
775 * @ [SHLWAPI.152]
776 *
777 * Unicode version of StrCmpNCA.
778 */
779 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
780 {
781 return StrCmpNW(lpszSrc, lpszCmp, len);
782 }
783
784 /*************************************************************************
785 * @ [SHLWAPI.153]
786 *
787 * Compare two Ascii strings up to a given length, ignoring case.
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 */
798 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
799 {
800 return StrCmpNIA(lpszSrc, lpszCmp, len);
801 }
802
803 /*************************************************************************
804 * @ [SHLWAPI.154]
805 *
806 * Unicode version of StrCmpNICA.
807 */
808 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
809 {
810 return StrCmpNIW(lpszSrc, lpszCmp, len);
811 }
812
813 /*************************************************************************
814 * @ [SHLWAPI.155]
815 *
816 * Compare two Ascii strings.
817 *
818 * PARAMS
819 * lpszSrc [I] Source string
820 * lpszCmp [I] String to compare to lpszSrc
821 *
822 * RETURNS
823 * A number greater than, less than or equal to 0 depending on whether
824 * lpszSrc is greater than, less than or equal to lpszCmp.
825 */
826 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
827 {
828 return lstrcmpA(lpszSrc, lpszCmp);
829 }
830
831 /*************************************************************************
832 * @ [SHLWAPI.156]
833 *
834 * Unicode version of StrCmpCA.
835 */
836 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
837 {
838 return lstrcmpW(lpszSrc, lpszCmp);
839 }
840
841 /*************************************************************************
842 * @ [SHLWAPI.157]
843 *
844 * Compare two Ascii strings, ignoring case.
845 *
846 * PARAMS
847 * lpszSrc [I] Source string
848 * lpszCmp [I] String to compare to lpszSrc
849 *
850 * RETURNS
851 * A number greater than, less than or equal to 0 depending on whether
852 * lpszSrc is greater than, less than or equal to lpszCmp.
853 */
854 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
855 {
856 return lstrcmpiA(lpszSrc, lpszCmp);
857 }
858
859 /*************************************************************************
860 * @ [SHLWAPI.158]
861 *
862 * Unicode version of StrCmpICA.
863 */
864 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
865 {
866 return lstrcmpiW(lpszSrc, lpszCmp);
867 }
868
869 /*************************************************************************
870 * @ [SHLWAPI.160]
871 *
872 * Get an identification string for the OS and explorer.
873 *
874 * PARAMS
875 * lpszDest [O] Destination for Id string
876 * dwDestLen [I] Length of lpszDest
877 *
878 * RETURNS
879 * TRUE, If the string was created successfully
880 * FALSE, Otherwise
881 */
882 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
883 {
884 WCHAR buff[2084];
885
886 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
887
888 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
889 {
890 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
891 return TRUE;
892 }
893 return FALSE;
894 }
895
896 /*************************************************************************
897 * @ [SHLWAPI.161]
898 *
899 * Unicode version of SHAboutInfoA.
900 */
901 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
902 {
903 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
904 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
905 ' ','E','x','p','l','o','r','e','r','\0' };
906 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
907 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
908 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
909 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
910 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
911 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
912 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
913 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
914 ' ','E','x','p','l','o','r','e','r','\\',
915 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
916 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
917 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
918 'V','e','r','s','i','o','n','\0' };
919 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
920 'O','w','n','e','r','\0' };
921 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
922 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
923 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
924 static const WCHAR szUpdate[] = { 'I','E','A','K',
925 'U','p','d','a','t','e','U','r','l','\0' };
926 static const WCHAR szHelp[] = { 'I','E','A','K',
927 'H','e','l','p','S','t','r','i','n','g','\0' };
928 WCHAR buff[2084];
929 HKEY hReg;
930 DWORD dwType, dwLen;
931
932 TRACE("(%p,%d)\n", lpszDest, dwDestLen);
933
934 if (!lpszDest)
935 return FALSE;
936
937 *lpszDest = '\0';
938
939 /* Try the NT key first, followed by 95/98 key */
940 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
941 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
942 return FALSE;
943
944 /* OS Version */
945 buff[0] = '\0';
946 dwLen = 30;
947 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
948 {
949 DWORD dwStrLen = strlenW(buff);
950 dwLen = 30 - dwStrLen;
951 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
952 szCustomized, &dwType, buff+dwStrLen, &dwLen);
953 }
954 StrCatBuffW(lpszDest, buff, dwDestLen);
955
956 /* ~Registered Owner */
957 buff[0] = '~';
958 dwLen = 256;
959 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
960 buff[1] = '\0';
961 StrCatBuffW(lpszDest, buff, dwDestLen);
962
963 /* ~Registered Organization */
964 dwLen = 256;
965 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
966 buff[1] = '\0';
967 StrCatBuffW(lpszDest, buff, dwDestLen);
968
969 /* FIXME: Not sure where this number comes from */
970 buff[0] = '~';
971 buff[1] = '0';
972 buff[2] = '\0';
973 StrCatBuffW(lpszDest, buff, dwDestLen);
974
975 /* ~Product Id */
976 dwLen = 256;
977 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
978 buff[1] = '\0';
979 StrCatBuffW(lpszDest, buff, dwDestLen);
980
981 /* ~IE Update Url */
982 dwLen = 2048;
983 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
984 buff[1] = '\0';
985 StrCatBuffW(lpszDest, buff, dwDestLen);
986
987 /* ~IE Help String */
988 dwLen = 256;
989 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
990 buff[1] = '\0';
991 StrCatBuffW(lpszDest, buff, dwDestLen);
992
993 RegCloseKey(hReg);
994 return TRUE;
995 }
996
997 /*************************************************************************
998 * @ [SHLWAPI.163]
999 *
1000 * Call IOleCommandTarget_QueryStatus() on an object.
1001 *
1002 * PARAMS
1003 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1004 * pguidCmdGroup [I] GUID for the command group
1005 * cCmds [I]
1006 * prgCmds [O] Commands
1007 * pCmdText [O] Command text
1008 *
1009 * RETURNS
1010 * Success: S_OK.
1011 * Failure: E_FAIL, if lpUnknown is NULL.
1012 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1013 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1014 */
1015 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1016 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1017 {
1018 HRESULT hRet = E_FAIL;
1019
1020 TRACE("(%p,%p,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1021
1022 if (lpUnknown)
1023 {
1024 IOleCommandTarget* lpOle;
1025
1026 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1027 (void**)&lpOle);
1028
1029 if (SUCCEEDED(hRet) && lpOle)
1030 {
1031 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1032 prgCmds, pCmdText);
1033 IOleCommandTarget_Release(lpOle);
1034 }
1035 }
1036 return hRet;
1037 }
1038
1039 /*************************************************************************
1040 * @ [SHLWAPI.164]
1041 *
1042 * Call IOleCommandTarget_Exec() on an object.
1043 *
1044 * PARAMS
1045 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1046 * pguidCmdGroup [I] GUID for the command group
1047 *
1048 * RETURNS
1049 * Success: S_OK.
1050 * Failure: E_FAIL, if lpUnknown is NULL.
1051 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1052 * Otherwise, an error code from IOleCommandTarget_Exec().
1053 */
1054 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1055 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1056 VARIANT* pvaOut)
1057 {
1058 HRESULT hRet = E_FAIL;
1059
1060 TRACE("(%p,%p,%d,%d,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1061 nCmdexecopt, pvaIn, pvaOut);
1062
1063 if (lpUnknown)
1064 {
1065 IOleCommandTarget* lpOle;
1066
1067 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1068 (void**)&lpOle);
1069 if (SUCCEEDED(hRet) && lpOle)
1070 {
1071 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1072 nCmdexecopt, pvaIn, pvaOut);
1073 IOleCommandTarget_Release(lpOle);
1074 }
1075 }
1076 return hRet;
1077 }
1078
1079 /*************************************************************************
1080 * @ [SHLWAPI.165]
1081 *
1082 * Retrieve, modify, and re-set a value from a window.
1083 *
1084 * PARAMS
1085 * hWnd [I] Window to get value from
1086 * offset [I] Offset of value
1087 * mask [I] Mask for flags
1088 * flags [I] Bits to set in window value
1089 *
1090 * RETURNS
1091 * The new value as it was set, or 0 if any parameter is invalid.
1092 *
1093 * NOTES
1094 * Only bits specified in mask are affected - set if present in flags and
1095 * reset otherwise.
1096 */
1097 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT mask, UINT flags)
1098 {
1099 LONG ret = GetWindowLongW(hwnd, offset);
1100 LONG new_flags = (flags & mask) | (ret & ~mask);
1101
1102 TRACE("%p %d %x %x\n", hwnd, offset, mask, flags);
1103
1104 if (new_flags != ret)
1105 ret = SetWindowLongW(hwnd, offset, new_flags);
1106 return ret;
1107 }
1108
1109 /*************************************************************************
1110 * @ [SHLWAPI.167]
1111 *
1112 * Change a window's parent.
1113 *
1114 * PARAMS
1115 * hWnd [I] Window to change parent of
1116 * hWndParent [I] New parent window
1117 *
1118 * RETURNS
1119 * The old parent of hWnd.
1120 *
1121 * NOTES
1122 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1123 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1124 */
1125 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1126 {
1127 TRACE("%p, %p\n", hWnd, hWndParent);
1128
1129 if(GetParent(hWnd) == hWndParent)
1130 return 0;
1131
1132 if(hWndParent)
1133 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1134 else
1135 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1136
1137 return SetParent(hWnd, hWndParent);
1138 }
1139
1140 /*************************************************************************
1141 * @ [SHLWAPI.168]
1142 *
1143 * Locate and advise a connection point in an IConnectionPointContainer object.
1144 *
1145 * PARAMS
1146 * lpUnkSink [I] Sink for the connection point advise call
1147 * riid [I] REFIID of connection point to advise
1148 * fConnect [I] TRUE = Connection being establisted, FALSE = broken
1149 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1150 * lpCookie [O] Pointer to connection point cookie
1151 * lppCP [O] Destination for the IConnectionPoint found
1152 *
1153 * RETURNS
1154 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1155 * that was advised. The caller is responsible for releasing it.
1156 * Failure: E_FAIL, if any arguments are invalid.
1157 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1158 * Or an HRESULT error code if any call fails.
1159 */
1160 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL fConnect,
1161 IUnknown* lpUnknown, LPDWORD lpCookie,
1162 IConnectionPoint **lppCP)
1163 {
1164 HRESULT hRet;
1165 IConnectionPointContainer* lpContainer;
1166 IConnectionPoint *lpCP;
1167
1168 if(!lpUnknown || (fConnect && !lpUnkSink))
1169 return E_FAIL;
1170
1171 if(lppCP)
1172 *lppCP = NULL;
1173
1174 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1175 (void**)&lpContainer);
1176 if (SUCCEEDED(hRet))
1177 {
1178 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1179
1180 if (SUCCEEDED(hRet))
1181 {
1182 if(!fConnect)
1183 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1184 else
1185 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1186
1187 if (FAILED(hRet))
1188 *lpCookie = 0;
1189
1190 if (lppCP && SUCCEEDED(hRet))
1191 *lppCP = lpCP; /* Caller keeps the interface */
1192 else
1193 IConnectionPoint_Release(lpCP); /* Release it */
1194 }
1195
1196 IUnknown_Release(lpContainer);
1197 }
1198 return hRet;
1199 }
1200
1201 /*************************************************************************
1202 * @ [SHLWAPI.169]
1203 *
1204 * Release an interface.
1205 *
1206 * PARAMS
1207 * lpUnknown [I] Object to release
1208 *
1209 * RETURNS
1210 * Nothing.
1211 */
1212 DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1213 {
1214 IUnknown *temp;
1215
1216 TRACE("(%p)\n",lpUnknown);
1217
1218 if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1219 temp = *lpUnknown;
1220 *lpUnknown = NULL;
1221
1222 TRACE("doing Release\n");
1223
1224 return IUnknown_Release(temp);
1225 }
1226
1227 /*************************************************************************
1228 * @ [SHLWAPI.170]
1229 *
1230 * Skip '//' if present in a string.
1231 *
1232 * PARAMS
1233 * lpszSrc [I] String to check for '//'
1234 *
1235 * RETURNS
1236 * Success: The next character after the '//' or the string if not present
1237 * Failure: NULL, if lpszStr is NULL.
1238 */
1239 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1240 {
1241 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1242 lpszSrc += 2;
1243 return lpszSrc;
1244 }
1245
1246 /*************************************************************************
1247 * @ [SHLWAPI.171]
1248 *
1249 * Check if two interfaces come from the same object.
1250 *
1251 * PARAMS
1252 * lpInt1 [I] Interface to check against lpInt2.
1253 * lpInt2 [I] Interface to check against lpInt1.
1254 *
1255 * RETURNS
1256 * TRUE, If the interfaces come from the same object.
1257 * FALSE Otherwise.
1258 */
1259 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1260 {
1261 LPVOID lpUnknown1, lpUnknown2;
1262
1263 TRACE("%p %p\n", lpInt1, lpInt2);
1264
1265 if (!lpInt1 || !lpInt2)
1266 return FALSE;
1267
1268 if (lpInt1 == lpInt2)
1269 return TRUE;
1270
1271 if (FAILED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown, &lpUnknown1)))
1272 return FALSE;
1273
1274 if (FAILED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown, &lpUnknown2)))
1275 return FALSE;
1276
1277 if (lpUnknown1 == lpUnknown2)
1278 return TRUE;
1279
1280 return FALSE;
1281 }
1282
1283 /*************************************************************************
1284 * @ [SHLWAPI.172]
1285 *
1286 * Get the window handle of an object.
1287 *
1288 * PARAMS
1289 * lpUnknown [I] Object to get the window handle of
1290 * lphWnd [O] Destination for window handle
1291 *
1292 * RETURNS
1293 * Success: S_OK. lphWnd contains the objects window handle.
1294 * Failure: An HRESULT error code.
1295 *
1296 * NOTES
1297 * lpUnknown is expected to support one of the following interfaces:
1298 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1299 */
1300 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1301 {
1302 IUnknown *lpOle;
1303 HRESULT hRet = E_FAIL;
1304
1305 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1306
1307 if (!lpUnknown)
1308 return hRet;
1309
1310 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1311
1312 if (FAILED(hRet))
1313 {
1314 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1315
1316 if (FAILED(hRet))
1317 {
1318 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1319 (void**)&lpOle);
1320 }
1321 }
1322
1323 if (SUCCEEDED(hRet))
1324 {
1325 /* Lazyness here - Since GetWindow() is the first method for the above 3
1326 * interfaces, we use the same call for them all.
1327 */
1328 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1329 IUnknown_Release(lpOle);
1330 if (lphWnd)
1331 TRACE("Returning HWND=%p\n", *lphWnd);
1332 }
1333
1334 return hRet;
1335 }
1336
1337 /*************************************************************************
1338 * @ [SHLWAPI.173]
1339 *
1340 * Call a method on as as yet unidentified object.
1341 *
1342 * PARAMS
1343 * pUnk [I] Object supporting the unidentified interface,
1344 * arg [I] Argument for the call on the object.
1345 *
1346 * RETURNS
1347 * S_OK.
1348 */
1349 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1350 {
1351 static const GUID guid_173 = {
1352 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1353 };
1354 IMalloc *pUnk2;
1355
1356 TRACE("(%p,%d)\n", pUnk, arg);
1357
1358 /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1359 * We use this interface as its vtable entry is compatible with the
1360 * object in question.
1361 * FIXME: Find out what this object is and where it should be defined.
1362 */
1363 if (pUnk &&
1364 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1365 {
1366 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1367 IMalloc_Release(pUnk2);
1368 }
1369 return S_OK;
1370 }
1371
1372 /*************************************************************************
1373 * @ [SHLWAPI.174]
1374 *
1375 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1376 * an object.
1377 *
1378 */
1379 HRESULT WINAPI IUnknown_SetSite(
1380 IUnknown *obj, /* [in] OLE object */
1381 IUnknown *site) /* [in] Site interface */
1382 {
1383 HRESULT hr;
1384 IObjectWithSite *iobjwithsite;
1385 IInternetSecurityManager *isecmgr;
1386
1387 if (!obj) return E_FAIL;
1388
1389 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1390 TRACE("IID_IObjectWithSite QI ret=%08x, %p\n", hr, iobjwithsite);
1391 if (SUCCEEDED(hr))
1392 {
1393 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1394 TRACE("done IObjectWithSite_SetSite ret=%08x\n", hr);
1395 IUnknown_Release(iobjwithsite);
1396 }
1397 else
1398 {
1399 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1400 TRACE("IID_IInternetSecurityManager QI ret=%08x, %p\n", hr, isecmgr);
1401 if (FAILED(hr)) return hr;
1402
1403 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1404 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08x\n", hr);
1405 IUnknown_Release(isecmgr);
1406 }
1407 return hr;
1408 }
1409
1410 /*************************************************************************
1411 * @ [SHLWAPI.175]
1412 *
1413 * Call IPersist_GetClassID() on an object.
1414 *
1415 * PARAMS
1416 * lpUnknown [I] Object supporting the IPersist interface
1417 * lpClassId [O] Destination for Class Id
1418 *
1419 * RETURNS
1420 * Success: S_OK. lpClassId contains the Class Id requested.
1421 * Failure: E_FAIL, If lpUnknown is NULL,
1422 * E_NOINTERFACE If lpUnknown does not support IPersist,
1423 * Or an HRESULT error code.
1424 */
1425 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1426 {
1427 IPersist* lpPersist;
1428 HRESULT hRet = E_FAIL;
1429
1430 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1431
1432 if (lpUnknown)
1433 {
1434 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1435 if (SUCCEEDED(hRet))
1436 {
1437 IPersist_GetClassID(lpPersist, lpClassId);
1438 IPersist_Release(lpPersist);
1439 }
1440 }
1441 return hRet;
1442 }
1443
1444 /*************************************************************************
1445 * @ [SHLWAPI.176]
1446 *
1447 * Retrieve a Service Interface from an object.
1448 *
1449 * PARAMS
1450 * lpUnknown [I] Object to get an IServiceProvider interface from
1451 * sid [I] Service ID for IServiceProvider_QueryService() call
1452 * riid [I] Function requested for QueryService call
1453 * lppOut [O] Destination for the service interface pointer
1454 *
1455 * RETURNS
1456 * Success: S_OK. lppOut contains an object providing the requested service
1457 * Failure: An HRESULT error code
1458 *
1459 * NOTES
1460 * lpUnknown is expected to support the IServiceProvider interface.
1461 */
1462 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1463 LPVOID *lppOut)
1464 {
1465 IServiceProvider* pService = NULL;
1466 HRESULT hRet;
1467
1468 if (!lppOut)
1469 return E_FAIL;
1470
1471 *lppOut = NULL;
1472
1473 if (!lpUnknown)
1474 return E_FAIL;
1475
1476 /* Get an IServiceProvider interface from the object */
1477 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1478 (LPVOID*)&pService);
1479
1480 if (hRet == S_OK && pService)
1481 {
1482 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1483
1484 /* Get a Service interface from the object */
1485 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1486
1487 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1488
1489 /* Release the IServiceProvider interface */
1490 IUnknown_Release(pService);
1491 }
1492 return hRet;
1493 }
1494
1495 /*************************************************************************
1496 * @ [SHLWAPI.479]
1497 *
1498 * Call an object's UIActivateIO method.
1499 *
1500 * PARAMS
1501 * unknown [I] Object to call the UIActivateIO method on
1502 * activate [I] Parameter for UIActivateIO call
1503 * msg [I] Parameter for UIActivateIO call
1504 *
1505 * RETURNS
1506 * Success: Value of UI_ActivateIO call
1507 * Failure: An HRESULT error code
1508 *
1509 * NOTES
1510 * unknown is expected to support the IInputObject interface.
1511 */
1512 HRESULT WINAPI IUnknown_UIActivateIO(IUnknown *unknown, BOOL activate, LPMSG msg)
1513 {
1514 IInputObject* object = NULL;
1515 HRESULT ret;
1516
1517 if (!unknown)
1518 return E_FAIL;
1519
1520 /* Get an IInputObject interface from the object */
1521 ret = IUnknown_QueryInterface(unknown, &IID_IInputObject, (LPVOID*) &object);
1522
1523 if (ret == S_OK)
1524 {
1525 ret = IInputObject_UIActivateIO(object, activate, msg);
1526 IUnknown_Release(object);
1527 }
1528
1529 return ret;
1530 }
1531
1532 /*************************************************************************
1533 * @ [SHLWAPI.177]
1534 *
1535 * Loads a popup menu.
1536 *
1537 * PARAMS
1538 * hInst [I] Instance handle
1539 * szName [I] Menu name
1540 *
1541 * RETURNS
1542 * Success: TRUE.
1543 * Failure: FALSE.
1544 */
1545 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1546 {
1547 HMENU hMenu;
1548
1549 if ((hMenu = LoadMenuW(hInst, szName)))
1550 {
1551 if (GetSubMenu(hMenu, 0))
1552 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1553
1554 DestroyMenu(hMenu);
1555 return TRUE;
1556 }
1557 return FALSE;
1558 }
1559
1560 typedef struct _enumWndData
1561 {
1562 UINT uiMsgId;
1563 WPARAM wParam;
1564 LPARAM lParam;
1565 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1566 } enumWndData;
1567
1568 /* Callback for SHLWAPI_178 */
1569 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1570 {
1571 enumWndData *data = (enumWndData *)lParam;
1572
1573 TRACE("(%p,%p)\n", hWnd, data);
1574 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1575 return TRUE;
1576 }
1577
1578 /*************************************************************************
1579 * @ [SHLWAPI.178]
1580 *
1581 * Send or post a message to every child of a window.
1582 *
1583 * PARAMS
1584 * hWnd [I] Window whose children will get the messages
1585 * uiMsgId [I] Message Id
1586 * wParam [I] WPARAM of message
1587 * lParam [I] LPARAM of message
1588 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1589 *
1590 * RETURNS
1591 * Nothing.
1592 *
1593 * NOTES
1594 * The appropriate ASCII or Unicode function is called for the window.
1595 */
1596 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1597 {
1598 enumWndData data;
1599
1600 TRACE("(%p,%u,%ld,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1601
1602 if(hWnd)
1603 {
1604 data.uiMsgId = uiMsgId;
1605 data.wParam = wParam;
1606 data.lParam = lParam;
1607
1608 if (bSend)
1609 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1610 else
1611 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1612
1613 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1614 }
1615 }
1616
1617 /*************************************************************************
1618 * @ [SHLWAPI.180]
1619 *
1620 * Remove all sub-menus from a menu.
1621 *
1622 * PARAMS
1623 * hMenu [I] Menu to remove sub-menus from
1624 *
1625 * RETURNS
1626 * Success: 0. All sub-menus under hMenu are removed
1627 * Failure: -1, if any parameter is invalid
1628 */
1629 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1630 {
1631 int iItemCount = GetMenuItemCount(hMenu) - 1;
1632 while (iItemCount >= 0)
1633 {
1634 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1635 if (hSubMenu)
1636 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1637 iItemCount--;
1638 }
1639 return iItemCount;
1640 }
1641
1642 /*************************************************************************
1643 * @ [SHLWAPI.181]
1644 *
1645 * Enable or disable a menu item.
1646 *
1647 * PARAMS
1648 * hMenu [I] Menu holding menu item
1649 * uID [I] ID of menu item to enable/disable
1650 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1651 *
1652 * RETURNS
1653 * The return code from EnableMenuItem.
1654 */
1655 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1656 {
1657 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1658 }
1659
1660 /*************************************************************************
1661 * @ [SHLWAPI.182]
1662 *
1663 * Check or uncheck a menu item.
1664 *
1665 * PARAMS
1666 * hMenu [I] Menu holding menu item
1667 * uID [I] ID of menu item to check/uncheck
1668 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1669 *
1670 * RETURNS
1671 * The return code from CheckMenuItem.
1672 */
1673 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1674 {
1675 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1676 }
1677
1678 /*************************************************************************
1679 * @ [SHLWAPI.183]
1680 *
1681 * Register a window class if it isn't already.
1682 *
1683 * PARAMS
1684 * lpWndClass [I] Window class to register
1685 *
1686 * RETURNS
1687 * The result of the RegisterClassA call.
1688 */
1689 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1690 {
1691 WNDCLASSA wca;
1692 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1693 return TRUE;
1694 return (DWORD)RegisterClassA(wndclass);
1695 }
1696
1697 /*************************************************************************
1698 * @ [SHLWAPI.186]
1699 */
1700 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1701 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1702 {
1703 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1704 POINTL pt = { 0, 0 };
1705
1706 if (!lpPt)
1707 lpPt = &pt;
1708
1709 if (!pdwEffect)
1710 pdwEffect = &dwEffect;
1711
1712 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1713
1714 if (*pdwEffect)
1715 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1716
1717 IDropTarget_DragLeave(pDrop);
1718 return TRUE;
1719 }
1720
1721 /*************************************************************************
1722 * @ [SHLWAPI.187]
1723 *
1724 * Call IPersistPropertyBag_Load() on an object.
1725 *
1726 * PARAMS
1727 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1728 * lpPropBag [O] Destination for loaded IPropertyBag
1729 *
1730 * RETURNS
1731 * Success: S_OK.
1732 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1733 */
1734 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1735 {
1736 IPersistPropertyBag* lpPPBag;
1737 HRESULT hRet = E_FAIL;
1738
1739 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1740
1741 if (lpUnknown)
1742 {
1743 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1744 (void**)&lpPPBag);
1745 if (SUCCEEDED(hRet) && lpPPBag)
1746 {
1747 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1748 IPersistPropertyBag_Release(lpPPBag);
1749 }
1750 }
1751 return hRet;
1752 }
1753
1754 /*************************************************************************
1755 * @ [SHLWAPI.188]
1756 *
1757 * Call IOleControlSite_TranslateAccelerator() on an object.
1758 *
1759 * PARAMS
1760 * lpUnknown [I] Object supporting the IOleControlSite interface.
1761 * lpMsg [I] Key message to be processed.
1762 * dwModifiers [I] Flags containing the state of the modifier keys.
1763 *
1764 * RETURNS
1765 * Success: S_OK.
1766 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1767 */
1768 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1769 {
1770 IOleControlSite* lpCSite = NULL;
1771 HRESULT hRet = E_INVALIDARG;
1772
1773 TRACE("(%p,%p,0x%08x)\n", lpUnknown, lpMsg, dwModifiers);
1774 if (lpUnknown)
1775 {
1776 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1777 (void**)&lpCSite);
1778 if (SUCCEEDED(hRet) && lpCSite)
1779 {
1780 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1781 IOleControlSite_Release(lpCSite);
1782 }
1783 }
1784 return hRet;
1785 }
1786
1787
1788 /*************************************************************************
1789 * @ [SHLWAPI.189]
1790 *
1791 * Call IOleControlSite_OnFocus() on an object.
1792 *
1793 * PARAMS
1794 * lpUnknown [I] Object supporting the IOleControlSite interface.
1795 * fGotFocus [I] Whether focus was gained (TRUE) or lost (FALSE).
1796 *
1797 * RETURNS
1798 * Success: S_OK.
1799 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1800 */
1801 HRESULT WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, BOOL fGotFocus)
1802 {
1803 IOleControlSite* lpCSite = NULL;
1804 HRESULT hRet = E_FAIL;
1805
1806 TRACE("(%p,%s)\n", lpUnknown, fGotFocus ? "TRUE" : "FALSE");
1807 if (lpUnknown)
1808 {
1809 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1810 (void**)&lpCSite);
1811 if (SUCCEEDED(hRet) && lpCSite)
1812 {
1813 hRet = IOleControlSite_OnFocus(lpCSite, fGotFocus);
1814 IOleControlSite_Release(lpCSite);
1815 }
1816 }
1817 return hRet;
1818 }
1819
1820 /*************************************************************************
1821 * @ [SHLWAPI.190]
1822 */
1823 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1824 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1825 {
1826 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1827 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1828 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1829 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1830 HRESULT hRet = E_INVALIDARG;
1831 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1832
1833 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1834
1835 if (lpUnknown && lpArg4)
1836 {
1837 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1838 (REFGUID)function_id, (void**)&lpUnkInner);
1839
1840 if (SUCCEEDED(hRet) && lpUnkInner)
1841 {
1842 /* FIXME: The type of service object requested is unknown, however
1843 * testing shows that its first method is called with 4 parameters.
1844 * Fake this by using IParseDisplayName_ParseDisplayName since the
1845 * signature and position in the vtable matches our unknown object type.
1846 */
1847 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1848 lpArg1, lpArg2, lpArg3, lpArg4);
1849 IUnknown_Release(lpUnkInner);
1850 }
1851 }
1852 return hRet;
1853 }
1854
1855 /*************************************************************************
1856 * @ [SHLWAPI.192]
1857 *
1858 * Get a sub-menu from a menu item.
1859 *
1860 * PARAMS
1861 * hMenu [I] Menu to get sub-menu from
1862 * uID [I] ID of menu item containing sub-menu
1863 *
1864 * RETURNS
1865 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1866 */
1867 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1868 {
1869 MENUITEMINFOW mi;
1870
1871 TRACE("(%p,%u)\n", hMenu, uID);
1872
1873 mi.cbSize = sizeof(mi);
1874 mi.fMask = MIIM_SUBMENU;
1875
1876 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1877 return NULL;
1878
1879 return mi.hSubMenu;
1880 }
1881
1882 /*************************************************************************
1883 * @ [SHLWAPI.193]
1884 *
1885 * Get the color depth of the primary display.
1886 *
1887 * PARAMS
1888 * None.
1889 *
1890 * RETURNS
1891 * The color depth of the primary display.
1892 */
1893 DWORD WINAPI SHGetCurColorRes(void)
1894 {
1895 HDC hdc;
1896 DWORD ret;
1897
1898 TRACE("()\n");
1899
1900 hdc = GetDC(0);
1901 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1902 ReleaseDC(0, hdc);
1903 return ret;
1904 }
1905
1906 /*************************************************************************
1907 * @ [SHLWAPI.194]
1908 *
1909 * Wait for a message to arrive, with a timeout.
1910 *
1911 * PARAMS
1912 * hand [I] Handle to query
1913 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1914 *
1915 * RETURNS
1916 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1917 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1918 * message is available.
1919 */
1920 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
1921 {
1922 DWORD dwEndTicks = GetTickCount() + dwTimeout;
1923 DWORD dwRet;
1924
1925 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
1926 {
1927 MSG msg;
1928
1929 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
1930
1931 if (dwTimeout != INFINITE)
1932 {
1933 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
1934 return WAIT_TIMEOUT;
1935 }
1936 }
1937
1938 return dwRet;
1939 }
1940
1941 /*************************************************************************
1942 * @ [SHLWAPI.195]
1943 *
1944 * Determine if a shell folder can be expanded.
1945 *
1946 * PARAMS
1947 * lpFolder [I] Parent folder containing the object to test.
1948 * pidl [I] Id of the object to test.
1949 *
1950 * RETURNS
1951 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
1952 * Failure: E_INVALIDARG, if any argument is invalid.
1953 *
1954 * NOTES
1955 * If the object to be tested does not expose the IQueryInfo() interface it
1956 * will not be identified as an expandable folder.
1957 */
1958 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
1959 {
1960 HRESULT hRet = E_INVALIDARG;
1961 IQueryInfo *lpInfo;
1962
1963 if (lpFolder && pidl)
1964 {
1965 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
1966 NULL, (void**)&lpInfo);
1967 if (FAILED(hRet))
1968 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
1969 else
1970 {
1971 DWORD dwFlags = 0;
1972
1973 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
1974 * currently used". Really? You wouldn't be holding out on me would you?
1975 */
1976 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
1977
1978 if (SUCCEEDED(hRet))
1979 {
1980 /* 0x2 is an undocumented flag apparently indicating expandability */
1981 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
1982 }
1983
1984 IQueryInfo_Release(lpInfo);
1985 }
1986 }
1987 return hRet;
1988 }
1989
1990 /*************************************************************************
1991 * @ [SHLWAPI.197]
1992 *
1993 * Blank out a region of text by drawing the background only.
1994 *
1995 * PARAMS
1996 * hDC [I] Device context to draw in
1997 * pRect [I] Area to draw in
1998 * cRef [I] Color to draw in
1999 *
2000 * RETURNS
2001 * Nothing.
2002 */
2003 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2004 {
2005 COLORREF cOldColor = SetBkColor(hDC, cRef);
2006 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2007 SetBkColor(hDC, cOldColor);
2008 return 0;
2009 }
2010
2011 /*************************************************************************
2012 * @ [SHLWAPI.198]
2013 *
2014 * Return the value associated with a key in a map.
2015 *
2016 * PARAMS
2017 * lpKeys [I] A list of keys of length iLen
2018 * lpValues [I] A list of values associated with lpKeys, of length iLen
2019 * iLen [I] Length of both lpKeys and lpValues
2020 * iKey [I] The key value to look up in lpKeys
2021 *
2022 * RETURNS
2023 * The value in lpValues associated with iKey, or -1 if iKey is not
2024 * found in lpKeys.
2025 *
2026 * NOTES
2027 * - If two elements in the map share the same key, this function returns
2028 * the value closest to the start of the map
2029 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2030 */
2031 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2032 {
2033 if (lpKeys && lpValues)
2034 {
2035 int i = 0;
2036
2037 while (i < iLen)
2038 {
2039 if (lpKeys[i] == iKey)
2040 return lpValues[i]; /* Found */
2041 i++;
2042 }
2043 }
2044 return -1; /* Not found */
2045 }
2046
2047
2048 /*************************************************************************
2049 * @ [SHLWAPI.199]
2050 *
2051 * Copy an interface pointer
2052 *
2053 * PARAMS
2054 * lppDest [O] Destination for copy
2055 * lpUnknown [I] Source for copy
2056 *
2057 * RETURNS
2058 * Nothing.
2059 */
2060 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2061 {
2062 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2063
2064 if (lppDest)
2065 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2066
2067 if (lpUnknown)
2068 {
2069 /* Copy */
2070 IUnknown_AddRef(lpUnknown);
2071 *lppDest = lpUnknown;
2072 }
2073 }
2074
2075 /*************************************************************************
2076 * @ [SHLWAPI.200]
2077 *
2078 */
2079 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2080 REFGUID riidCmdGrp, ULONG cCmds,
2081 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2082 {
2083 FIXME("(%p,%p,%p,%d,%p,%p) - stub\n",
2084 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2085
2086 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2087 return DRAGDROP_E_NOTREGISTERED;
2088 }
2089
2090 /*************************************************************************
2091 * @ [SHLWAPI.201]
2092 *
2093 */
2094 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2095 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2096 VARIANT* pvaOut)
2097 {
2098 FIXME("(%p,%d,%p,%d,%d,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2099 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2100 return DRAGDROP_E_NOTREGISTERED;
2101 }
2102
2103 /*************************************************************************
2104 * @ [SHLWAPI.202]
2105 *
2106 */
2107 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2108 {
2109 FIXME("(%p,%d,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2110 return DRAGDROP_E_NOTREGISTERED;
2111 }
2112
2113 /*************************************************************************
2114 * @ [SHLWAPI.204]
2115 *
2116 * Determine if a window is not a child of another window.
2117 *
2118 * PARAMS
2119 * hParent [I] Suspected parent window
2120 * hChild [I] Suspected child window
2121 *
2122 * RETURNS
2123 * TRUE: If hChild is a child window of hParent
2124 * FALSE: If hChild is not a child window of hParent, or they are equal
2125 */
2126 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2127 {
2128 TRACE("(%p,%p)\n", hParent, hChild);
2129
2130 if (!hParent || !hChild)
2131 return TRUE;
2132 else if(hParent == hChild)
2133 return FALSE;
2134 return !IsChild(hParent, hChild);
2135 }
2136
2137 /*************************************************************************
2138 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2139 */
2140
2141 typedef struct
2142 {
2143 DWORD num_items; /* Number of elements inserted */
2144 void *mem; /* Ptr to array */
2145 DWORD blocks_alloced; /* Number of elements allocated */
2146 BYTE inc; /* Number of elements to grow by when we need to expand */
2147 BYTE block_size; /* Size in bytes of an element */
2148 BYTE flags; /* Flags */
2149 } FDSA_info;
2150
2151 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2152
2153 /*************************************************************************
2154 * @ [SHLWAPI.208]
2155 *
2156 * Initialize an FDSA array.
2157 */
2158 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2159 DWORD init_blocks)
2160 {
2161 TRACE("(0x%08x 0x%08x %p %p 0x%08x)\n", block_size, inc, info, mem, init_blocks);
2162
2163 if(inc == 0)
2164 inc = 1;
2165
2166 if(mem)
2167 memset(mem, 0, block_size * init_blocks);
2168
2169 info->num_items = 0;
2170 info->inc = inc;
2171 info->mem = mem;
2172 info->blocks_alloced = init_blocks;
2173 info->block_size = block_size;
2174 info->flags = 0;
2175
2176 return TRUE;
2177 }
2178
2179 /*************************************************************************
2180 * @ [SHLWAPI.209]
2181 *
2182 * Destroy an FDSA array
2183 */
2184 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2185 {
2186 TRACE("(%p)\n", info);
2187
2188 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2189 {
2190 HeapFree(GetProcessHeap(), 0, info->mem);
2191 return FALSE;
2192 }
2193
2194 return TRUE;
2195 }
2196
2197 /*************************************************************************
2198 * @ [SHLWAPI.210]
2199 *
2200 * Insert element into an FDSA array
2201 */
2202 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, const void *block)
2203 {
2204 TRACE("(%p 0x%08x %p)\n", info, where, block);
2205 if(where > info->num_items)
2206 where = info->num_items;
2207
2208 if(info->num_items >= info->blocks_alloced)
2209 {
2210 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2211 if(info->flags & 0x1)
2212 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2213 else
2214 {
2215 void *old_mem = info->mem;
2216 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2217 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2218 }
2219 info->blocks_alloced += info->inc;
2220 info->flags |= 0x1;
2221 }
2222
2223 if(where < info->num_items)
2224 {
2225 memmove((char*)info->mem + (where + 1) * info->block_size,
2226 (char*)info->mem + where * info->block_size,
2227 (info->num_items - where) * info->block_size);
2228 }
2229 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2230
2231 info->num_items++;
2232 return where;
2233 }
2234
2235 /*************************************************************************
2236 * @ [SHLWAPI.211]
2237 *
2238 * Delete an element from an FDSA array.
2239 */
2240 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2241 {
2242 TRACE("(%p 0x%08x)\n", info, where);
2243
2244 if(where >= info->num_items)
2245 return FALSE;
2246
2247 if(where < info->num_items - 1)
2248 {
2249 memmove((char*)info->mem + where * info->block_size,
2250 (char*)info->mem + (where + 1) * info->block_size,
2251 (info->num_items - where - 1) * info->block_size);
2252 }
2253 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2254 0, info->block_size);
2255 info->num_items--;
2256 return TRUE;
2257 }
2258
2259
2260 typedef struct {
2261 REFIID refid;
2262 DWORD indx;
2263 } IFACE_INDEX_TBL;
2264
2265 /*************************************************************************
2266 * @ [SHLWAPI.219]
2267 *
2268 * Call IUnknown_QueryInterface() on a table of objects.
2269 *
2270 * RETURNS
2271 * Success: S_OK.
2272 * Failure: E_POINTER or E_NOINTERFACE.
2273 */
2274 HRESULT WINAPI QISearch(
2275 LPVOID w, /* [in] Table of interfaces */
2276 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2277 REFIID riid, /* [in] REFIID to get interface for */
2278 LPVOID *ppv) /* [out] Destination for interface pointer */
2279 {
2280 HRESULT ret;
2281 IUnknown *a_vtbl;
2282 IFACE_INDEX_TBL *xmove;
2283
2284 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2285 if (ppv) {
2286 xmove = x;
2287 while (xmove->refid) {
2288 TRACE("trying (indx %d) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2289 if (IsEqualIID(riid, xmove->refid)) {
2290 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2291 TRACE("matched, returning (%p)\n", a_vtbl);
2292 *ppv = a_vtbl;
2293 IUnknown_AddRef(a_vtbl);
2294 return S_OK;
2295 }
2296 xmove++;
2297 }
2298
2299 if (IsEqualIID(riid, &IID_IUnknown)) {
2300 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2301 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2302 *ppv = a_vtbl;
2303 IUnknown_AddRef(a_vtbl);
2304 return S_OK;
2305 }
2306 *ppv = 0;
2307 ret = E_NOINTERFACE;
2308 } else
2309 ret = E_POINTER;
2310
2311 TRACE("-- 0x%08x\n", ret);
2312 return ret;
2313 }
2314
2315 /*************************************************************************
2316 * @ [SHLWAPI.220]
2317 *
2318 * Set the Font for a window and the "PropDlgFont" property of the parent window.
2319 *
2320 * PARAMS
2321 * hWnd [I] Parent Window to set the property
2322 * id [I] Index of child Window to set the Font
2323 *
2324 * RETURNS
2325 * Success: S_OK
2326 *
2327 */
2328 HRESULT WINAPI SHSetDefaultDialogFont(HWND hWnd, INT id)
2329 {
2330 FIXME("(%p, %d) stub\n", hWnd, id);
2331 return S_OK;
2332 }
2333
2334 /*************************************************************************
2335 * @ [SHLWAPI.221]
2336 *
2337 * Remove the "PropDlgFont" property from a window.
2338 *
2339 * PARAMS
2340 * hWnd [I] Window to remove the property from
2341 *
2342 * RETURNS
2343 * A handle to the removed property, or NULL if it did not exist.
2344 */
2345 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2346 {
2347 HANDLE hProp;
2348
2349 TRACE("(%p)\n", hWnd);
2350
2351 hProp = GetPropA(hWnd, "PropDlgFont");
2352
2353 if(hProp)
2354 {
2355 DeleteObject(hProp);
2356 hProp = RemovePropA(hWnd, "PropDlgFont");
2357 }
2358 return hProp;
2359 }
2360
2361 /*************************************************************************
2362 * @ [SHLWAPI.236]
2363 *
2364 * Load the in-process server of a given GUID.
2365 *
2366 * PARAMS
2367 * refiid [I] GUID of the server to load.
2368 *
2369 * RETURNS
2370 * Success: A handle to the loaded server dll.
2371 * Failure: A NULL handle.
2372 */
2373 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2374 {
2375 HKEY newkey;
2376 DWORD type, count;
2377 CHAR value[MAX_PATH], string[MAX_PATH];
2378
2379 strcpy(string, "CLSID\\");
2380 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2381 strcat(string, "\\InProcServer32");
2382
2383 count = MAX_PATH;
2384 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2385 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2386 RegCloseKey(newkey);
2387 return LoadLibraryExA(value, 0, 0);
2388 }
2389
2390 /*************************************************************************
2391 * @ [SHLWAPI.237]
2392 *
2393 * Unicode version of SHLWAPI_183.
2394 */
2395 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2396 {
2397 WNDCLASSW WndClass;
2398
2399 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2400
2401 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2402 return TRUE;
2403 return RegisterClassW(lpWndClass);
2404 }
2405
2406 /*************************************************************************
2407 * @ [SHLWAPI.238]
2408 *
2409 * Unregister a list of classes.
2410 *
2411 * PARAMS
2412 * hInst [I] Application instance that registered the classes
2413 * lppClasses [I] List of class names
2414 * iCount [I] Number of names in lppClasses
2415 *
2416 * RETURNS
2417 * Nothing.
2418 */
2419 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2420 {
2421 WNDCLASSA WndClass;
2422
2423 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2424
2425 while (iCount > 0)
2426 {
2427 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2428 UnregisterClassA(*lppClasses, hInst);
2429 lppClasses++;
2430 iCount--;
2431 }
2432 }
2433
2434 /*************************************************************************
2435 * @ [SHLWAPI.239]
2436 *
2437 * Unicode version of SHUnregisterClassesA.
2438 */
2439 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2440 {
2441 WNDCLASSW WndClass;
2442
2443 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2444
2445 while (iCount > 0)
2446 {
2447 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2448 UnregisterClassW(*lppClasses, hInst);
2449 lppClasses++;
2450 iCount--;
2451 }
2452 }
2453
2454 /*************************************************************************
2455 * @ [SHLWAPI.240]
2456 *
2457 * Call The correct (Ascii/Unicode) default window procedure for a window.
2458 *
2459 * PARAMS
2460 * hWnd [I] Window to call the default procedure for
2461 * uMessage [I] Message ID
2462 * wParam [I] WPARAM of message
2463 * lParam [I] LPARAM of message
2464 *
2465 * RETURNS
2466 * The result of calling DefWindowProcA() or DefWindowProcW().
2467 */
2468 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2469 {
2470 if (IsWindowUnicode(hWnd))
2471 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2472 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2473 }
2474
2475 /*************************************************************************
2476 * @ [SHLWAPI.256]
2477 */
2478 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2479 {
2480 HRESULT hRet = E_INVALIDARG;
2481 LPOBJECTWITHSITE lpSite = NULL;
2482
2483 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2484
2485 if (lpUnknown && iid && lppSite)
2486 {
2487 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2488 (void**)&lpSite);
2489 if (SUCCEEDED(hRet) && lpSite)
2490 {
2491 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2492 IObjectWithSite_Release(lpSite);
2493 }
2494 }
2495 return hRet;
2496 }
2497
2498 /*************************************************************************
2499 * @ [SHLWAPI.257]
2500 *
2501 * Create a worker window using CreateWindowExA().
2502 *
2503 * PARAMS
2504 * wndProc [I] Window procedure
2505 * hWndParent [I] Parent window
2506 * dwExStyle [I] Extra style flags
2507 * dwStyle [I] Style flags
2508 * hMenu [I] Window menu
2509 * z [I] Unknown
2510 *
2511 * RETURNS
2512 * Success: The window handle of the newly created window.
2513 * Failure: 0.
2514 */
2515 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2516 DWORD dwStyle, HMENU hMenu, LONG z)
2517 {
2518 static const char szClass[] = "WorkerA";
2519 WNDCLASSA wc;
2520 HWND hWnd;
2521
2522 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2523 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2524
2525 /* Create Window class */
2526 wc.style = 0;
2527 wc.lpfnWndProc = DefWindowProcA;
2528 wc.cbClsExtra = 0;
2529 wc.cbWndExtra = 4;
2530 wc.hInstance = shlwapi_hInstance;
2531 wc.hIcon = NULL;
2532 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2533 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2534 wc.lpszMenuName = NULL;
2535 wc.lpszClassName = szClass;
2536
2537 SHRegisterClassA(&wc); /* Register class */
2538
2539 /* FIXME: Set extra bits in dwExStyle */
2540
2541 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2542 hWndParent, hMenu, shlwapi_hInstance, 0);
2543 if (hWnd)
2544 {
2545 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2546
2547 if (wndProc)
2548 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2549 }
2550 return hWnd;
2551 }
2552
2553 typedef struct tagPOLICYDATA
2554 {
2555 DWORD policy; /* flags value passed to SHRestricted */
2556 LPCWSTR appstr; /* application str such as "Explorer" */
2557 LPCWSTR keystr; /* name of the actual registry key / policy */
2558 } POLICYDATA, *LPPOLICYDATA;
2559
2560 #define SHELL_NO_POLICY 0xffffffff
2561
2562 /* default shell policy registry key */
2563 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2564 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2565 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2566 '\\','P','o','l','i','c','i','e','s',0};
2567
2568 /*************************************************************************
2569 * @ [SHLWAPI.271]
2570 *
2571 * Retrieve a policy value from the registry.
2572 *
2573 * PARAMS
2574 * lpSubKey [I] registry key name
2575 * lpSubName [I] subname of registry key
2576 * lpValue [I] value name of registry value
2577 *
2578 * RETURNS
2579 * the value associated with the registry key or 0 if not found
2580 */
2581 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2582 {
2583 DWORD retval, datsize = sizeof(retval);
2584 HKEY hKey;
2585
2586 if (!lpSubKey)
2587 lpSubKey = strRegistryPolicyW;
2588
2589 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2590 if (retval != ERROR_SUCCESS)
2591 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2592 if (retval != ERROR_SUCCESS)
2593 return 0;
2594
2595 SHGetValueW(hKey, lpSubName, lpValue, NULL, &retval, &datsize);
2596 RegCloseKey(hKey);
2597 return retval;
2598 }
2599
2600 /*************************************************************************
2601 * @ [SHLWAPI.266]
2602 *
2603 * Helper function to retrieve the possibly cached value for a specific policy
2604 *
2605 * PARAMS
2606 * policy [I] The policy to look for
2607 * initial [I] Main registry key to open, if NULL use default
2608 * polTable [I] Table of known policies, 0 terminated
2609 * polArr [I] Cache array of policy values
2610 *
2611 * RETURNS
2612 * The retrieved policy value or 0 if not successful
2613 *
2614 * NOTES
2615 * This function is used by the native SHRestricted function to search for the
2616 * policy and cache it once retrieved. The current Wine implementation uses a
2617 * different POLICYDATA structure and implements a similar algorithm adapted to
2618 * that structure.
2619 */
2620 DWORD WINAPI SHRestrictionLookup(
2621 DWORD policy,
2622 LPCWSTR initial,
2623 LPPOLICYDATA polTable,
2624 LPDWORD polArr)
2625 {
2626 TRACE("(0x%08x %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2627
2628 if (!polTable || !polArr)
2629 return 0;
2630
2631 for (;polTable->policy; polTable++, polArr++)
2632 {
2633 if (policy == polTable->policy)
2634 {
2635 /* we have a known policy */
2636
2637 /* check if this policy has been cached */
2638 if (*polArr == SHELL_NO_POLICY)
2639 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2640 return *polArr;
2641 }
2642 }
2643 /* we don't know this policy, return 0 */
2644 TRACE("unknown policy: (%08x)\n", policy);
2645 return 0;
2646 }
2647
2648 /*************************************************************************
2649 * @ [SHLWAPI.267]
2650 *
2651 * Get an interface from an object.
2652 *
2653 * RETURNS
2654 * Success: S_OK. ppv contains the requested interface.
2655 * Failure: An HRESULT error code.
2656 *
2657 * NOTES
2658 * This QueryInterface asks the inner object for an interface. In case
2659 * of aggregation this request would be forwarded by the inner to the
2660 * outer object. This function asks the inner object directly for the
2661 * interface circumventing the forwarding to the outer object.
2662 */
2663 HRESULT WINAPI SHWeakQueryInterface(
2664 IUnknown * pUnk, /* [in] Outer object */
2665 IUnknown * pInner, /* [in] Inner object */
2666 IID * riid, /* [in] Interface GUID to query for */
2667 LPVOID* ppv) /* [out] Destination for queried interface */
2668 {
2669 HRESULT hret = E_NOINTERFACE;
2670 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2671
2672 *ppv = NULL;
2673 if(pUnk && pInner) {
2674 hret = IUnknown_QueryInterface(pInner, riid, ppv);
2675 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2676 }
2677 TRACE("-- 0x%08x\n", hret);
2678 return hret;
2679 }
2680
2681 /*************************************************************************
2682 * @ [SHLWAPI.268]
2683 *
2684 * Move a reference from one interface to another.
2685 *
2686 * PARAMS
2687 * lpDest [O] Destination to receive the reference
2688 * lppUnknown [O] Source to give up the reference to lpDest
2689 *
2690 * RETURNS
2691 * Nothing.
2692 */
2693 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2694 {
2695 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2696
2697 if (*lppUnknown)
2698 {
2699 /* Copy Reference*/
2700 IUnknown_AddRef(lpDest);
2701 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2702 }
2703 }
2704
2705 /*************************************************************************
2706 * @ [SHLWAPI.269]
2707 *
2708 * Convert an ASCII string of a CLSID into a CLSID.
2709 *
2710 * PARAMS
2711 * idstr [I] String representing a CLSID in registry format
2712 * id [O] Destination for the converted CLSID
2713 *
2714 * RETURNS
2715 * Success: TRUE. id contains the converted CLSID.
2716 * Failure: FALSE.
2717 */
2718 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2719 {
2720 WCHAR wClsid[40];
2721 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2722 return SUCCEEDED(CLSIDFromString(wClsid, id));
2723 }
2724
2725 /*************************************************************************
2726 * @ [SHLWAPI.270]
2727 *
2728 * Unicode version of GUIDFromStringA.
2729 */
2730 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2731 {
2732 return SUCCEEDED(CLSIDFromString((LPOLESTR)idstr, id));
2733 }
2734
2735 /*************************************************************************
2736 * @ [SHLWAPI.276]
2737 *
2738 * Determine if the browser is integrated into the shell, and set a registry
2739 * key accordingly.
2740 *
2741 * PARAMS
2742 * None.
2743 *
2744 * RETURNS
2745 * 1, If the browser is not integrated.
2746 * 2, If the browser is integrated.
2747 *
2748 * NOTES
2749 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2750 * either set to TRUE, or removed depending on whether the browser is deemed
2751 * to be integrated.
2752 */
2753 DWORD WINAPI WhichPlatform(void)
2754 {
2755 static const char szIntegratedBrowser[] = "IntegratedBrowser";
2756 static DWORD dwState = 0;
2757 HKEY hKey;
2758 DWORD dwRet, dwData, dwSize;
2759 HMODULE hshell32;
2760
2761 if (dwState)
2762 return dwState;
2763
2764 /* If shell32 exports DllGetVersion(), the browser is integrated */
2765 dwState = 1;
2766 hshell32 = LoadLibraryA("shell32.dll");
2767 if (hshell32)
2768 {
2769 FARPROC pDllGetVersion;
2770 pDllGetVersion = GetProcAddress(hshell32, "DllGetVersion");
2771 dwState = pDllGetVersion ? 2 : 1;
2772 FreeLibrary(hshell32);
2773 }
2774
2775 /* Set or delete the key accordingly */
2776 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2777 "Software\\Microsoft\\Internet Explorer", 0,
2778 KEY_ALL_ACCESS, &hKey);
2779 if (!dwRet)
2780 {
2781 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2782 (LPBYTE)&dwData, &dwSize);
2783
2784 if (!dwRet && dwState == 1)
2785 {
2786 /* Value exists but browser is not integrated */
2787 RegDeleteValueA(hKey, szIntegratedBrowser);
2788 }
2789 else if (dwRet && dwState == 2)
2790 {
2791 /* Browser is integrated but value does not exist */
2792 dwData = TRUE;
2793 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2794 (LPBYTE)&dwData, sizeof(dwData));
2795 }
2796 RegCloseKey(hKey);
2797 }
2798 return dwState;
2799 }
2800
2801 /*************************************************************************
2802 * @ [SHLWAPI.278]
2803 *
2804 * Unicode version of SHCreateWorkerWindowA.
2805 */
2806 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2807 DWORD dwStyle, HMENU hMenu, LONG z)
2808 {
2809 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2810 WNDCLASSW wc;
2811 HWND hWnd;
2812
2813 TRACE("(0x%08x,%p,0x%08x,0x%08x,%p,0x%08x)\n",
2814 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2815
2816 /* If our OS is natively ASCII, use the ASCII version */
2817 if (!(GetVersion() & 0x80000000)) /* NT */
2818 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2819
2820 /* Create Window class */
2821 wc.style = 0;
2822 wc.lpfnWndProc = DefWindowProcW;
2823 wc.cbClsExtra = 0;
2824 wc.cbWndExtra = 4;
2825 wc.hInstance = shlwapi_hInstance;
2826 wc.hIcon = NULL;
2827 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2828 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2829 wc.lpszMenuName = NULL;
2830 wc.lpszClassName = szClass;
2831
2832 SHRegisterClassW(&wc); /* Register class */
2833
2834 /* FIXME: Set extra bits in dwExStyle */
2835
2836 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2837 hWndParent, hMenu, shlwapi_hInstance, 0);
2838 if (hWnd)
2839 {
2840 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2841
2842 if (wndProc)
2843 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2844 }
2845 return hWnd;
2846 }
2847
2848 /*************************************************************************
2849 * @ [SHLWAPI.279]
2850 *
2851 * Get and show a context menu from a shell folder.
2852 *
2853 * PARAMS
2854 * hWnd [I] Window displaying the shell folder
2855 * lpFolder [I] IShellFolder interface
2856 * lpApidl [I] Id for the particular folder desired
2857 *
2858 * RETURNS
2859 * Success: S_OK.
2860 * Failure: An HRESULT error code indicating the error.
2861 */
2862 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2863 {
2864 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2865 }
2866
2867 /*************************************************************************
2868 * @ [SHLWAPI.281]
2869 *
2870 * _SHPackDispParamsV
2871 */
2872 HRESULT WINAPI SHPackDispParamsV(DISPPARAMS *params, VARIANTARG *args, UINT cnt, __ms_va_list valist)
2873 {
2874 VARIANTARG *iter;
2875
2876 TRACE("(%p %p %u ...)\n", params, args, cnt);
2877
2878 params->rgvarg = args;
2879 params->rgdispidNamedArgs = NULL;
2880 params->cArgs = cnt;
2881 params->cNamedArgs = 0;
2882
2883 iter = args+cnt;
2884
2885 while(iter-- > args) {
2886 V_VT(iter) = va_arg(valist, enum VARENUM);
2887
2888 TRACE("vt=%d\n", V_VT(iter));
2889
2890 if(V_VT(iter) & VT_BYREF) {
2891 V_BYREF(iter) = va_arg(valist, LPVOID);
2892 } else {
2893 switch(V_VT(iter)) {
2894 case VT_I4:
2895 V_I4(iter) = va_arg(valist, LONG);
2896 break;
2897 case VT_BSTR:
2898 V_BSTR(iter) = va_arg(valist, BSTR);
2899 break;
2900 case VT_DISPATCH:
2901 V_DISPATCH(iter) = va_arg(valist, IDispatch*);
2902 break;
2903 case VT_BOOL:
2904 V_BOOL(iter) = va_arg(valist, int);
2905 break;
2906 case VT_UNKNOWN:
2907 V_UNKNOWN(iter) = va_arg(valist, IUnknown*);
2908 break;
2909 default:
2910 V_VT(iter) = VT_I4;
2911 V_I4(iter) = va_arg(valist, LONG);
2912 }
2913 }
2914 }
2915
2916 return S_OK;
2917 }
2918
2919 /*************************************************************************
2920 * @ [SHLWAPI.282]
2921 *
2922 * SHPackDispParams
2923 */
2924 HRESULT WINAPIV SHPackDispParams(DISPPARAMS *params, VARIANTARG *args, UINT cnt, ...)
2925 {
2926 __ms_va_list valist;
2927 HRESULT hres;
2928
2929 __ms_va_start(valist, cnt);
2930 hres = SHPackDispParamsV(params, args, cnt, valist);
2931 __ms_va_end(valist);
2932 return hres;
2933 }
2934
2935 /*************************************************************************
2936 * SHLWAPI_InvokeByIID
2937 *
2938 * This helper function calls IDispatch::Invoke for each sink
2939 * which implements given iid or IDispatch.
2940 *
2941 */
2942 static HRESULT SHLWAPI_InvokeByIID(
2943 IConnectionPoint* iCP,
2944 REFIID iid,
2945 DISPID dispId,
2946 DISPPARAMS* dispParams)
2947 {
2948 IEnumConnections *enumerator;
2949 CONNECTDATA rgcd;
2950 static DISPPARAMS empty = {NULL, NULL, 0, 0};
2951 DISPPARAMS* params = dispParams;
2952
2953 HRESULT result = IConnectionPoint_EnumConnections(iCP, &enumerator);
2954 if (FAILED(result))
2955 return result;
2956
2957 /* Invoke is never happening with an NULL dispParams */
2958 if (!params)
2959 params = &empty;
2960
2961 while(IEnumConnections_Next(enumerator, 1, &rgcd, NULL)==S_OK)
2962 {
2963 IDispatch *dispIface;
2964 if ((iid && SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, iid, (LPVOID*)&dispIface))) ||
2965 SUCCEEDED(IUnknown_QueryInterface(rgcd.pUnk, &IID_IDispatch, (LPVOID*)&dispIface)))
2966 {
2967 IDispatch_Invoke(dispIface, dispId, &IID_NULL, 0, DISPATCH_METHOD, params, NULL, NULL, NULL);
2968 IDispatch_Release(dispIface);
2969 }
2970 IUnknown_Release(rgcd.pUnk);
2971 }
2972
2973 IEnumConnections_Release(enumerator);
2974
2975 return S_OK;
2976 }
2977
2978 /*************************************************************************
2979 * IConnectionPoint_InvokeWithCancel [SHLWAPI.283]
2980 */
2981 HRESULT WINAPI IConnectionPoint_InvokeWithCancel( IConnectionPoint* iCP,
2982 DISPID dispId, DISPPARAMS* dispParams,
2983 DWORD unknown1, DWORD unknown2 )
2984 {
2985 IID iid;
2986 HRESULT result;
2987
2988 FIXME("(%p)->(0x%x %p %x %x) partial stub\n", iCP, dispId, dispParams, unknown1, unknown2);
2989
2990 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
2991 if (SUCCEEDED(result))
2992 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
2993 else
2994 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
2995
2996 return result;
2997 }
2998
2999
3000 /*************************************************************************
3001 * @ [SHLWAPI.284]
3002 *
3003 * IConnectionPoint_SimpleInvoke
3004 */
3005 HRESULT WINAPI IConnectionPoint_SimpleInvoke(
3006 IConnectionPoint* iCP,
3007 DISPID dispId,
3008 DISPPARAMS* dispParams)
3009 {
3010 IID iid;
3011 HRESULT result;
3012
3013 TRACE("(%p)->(0x%x %p)\n",iCP,dispId,dispParams);
3014
3015 result = IConnectionPoint_GetConnectionInterface(iCP, &iid);
3016 if (SUCCEEDED(result))
3017 result = SHLWAPI_InvokeByIID(iCP, &iid, dispId, dispParams);
3018 else
3019 result = SHLWAPI_InvokeByIID(iCP, NULL, dispId, dispParams);
3020
3021 return result;
3022 }
3023
3024 /*************************************************************************
3025 * @ [SHLWAPI.285]
3026 *
3027 * Notify an IConnectionPoint object of changes.
3028 *
3029 * PARAMS
3030 * lpCP [I] Object to notify
3031 * dispID [I]
3032 *
3033 * RETURNS
3034 * Success: S_OK.
3035 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
3036 * IConnectionPoint interface.
3037 */
3038 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
3039 {
3040 IEnumConnections *lpEnum;
3041 HRESULT hRet = E_NOINTERFACE;
3042
3043 TRACE("(%p,0x%8X)\n", lpCP, dispID);
3044
3045 /* Get an enumerator for the connections */
3046 if (lpCP)
3047 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
3048
3049 if (SUCCEEDED(hRet))
3050 {
3051 IPropertyNotifySink *lpSink;
3052 CONNECTDATA connData;
3053 ULONG ulFetched;
3054
3055 /* Call OnChanged() for every notify sink in the connection point */
3056 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
3057 {
3058 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
3059 lpSink)
3060 {
3061 IPropertyNotifySink_OnChanged(lpSink, dispID);
3062 IPropertyNotifySink_Release(lpSink);
3063 }
3064 IUnknown_Release(connData.pUnk);
3065 }
3066
3067 IEnumConnections_Release(lpEnum);
3068 }
3069 return hRet;
3070 }
3071
3072 /*************************************************************************
3073 * @ [SHLWAPI.286]
3074 *
3075 * IUnknown_CPContainerInvokeParam
3076 */
3077 HRESULT WINAPIV IUnknown_CPContainerInvokeParam(
3078 IUnknown *container,
3079 REFIID riid,
3080 DISPID dispId,
3081 VARIANTARG* buffer,
3082 DWORD cParams, ...)
3083 {
3084 HRESULT result;
3085 IConnectionPoint *iCP;
3086 IConnectionPointContainer *iCPC;
3087 DISPPARAMS dispParams = {buffer, NULL, cParams, 0};
3088 __ms_va_list valist;
3089
3090 if (!container)
3091 return E_NOINTERFACE;
3092
3093 result = IUnknown_QueryInterface(container, &IID_IConnectionPointContainer,(LPVOID*) &iCPC);
3094 if (FAILED(result))
3095 return result;
3096
3097 result = IConnectionPointContainer_FindConnectionPoint(iCPC, riid, &iCP);
3098 IConnectionPointContainer_Release(iCPC);
3099 if(FAILED(result))
3100 return result;
3101
3102 __ms_va_start(valist, cParams);
3103 SHPackDispParamsV(&dispParams, buffer, cParams, valist);
3104 __ms_va_end(valist);
3105
3106 result = SHLWAPI_InvokeByIID(iCP, riid, dispId, &dispParams);
3107 IConnectionPoint_Release(iCP);
3108
3109 return result;
3110 }
3111
3112 /*************************************************************************
3113 * @ [SHLWAPI.287]
3114 *
3115 * Notify an IConnectionPointContainer object of changes.
3116 *
3117 * PARAMS
3118 * lpUnknown [I] Object to notify
3119 * dispID [I]
3120 *
3121 * RETURNS
3122 * Success: S_OK.
3123 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3124 * IConnectionPointContainer interface.
3125 */
3126 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3127 {
3128 IConnectionPointContainer* lpCPC = NULL;
3129 HRESULT hRet = E_NOINTERFACE;
3130
3131 TRACE("(%p,0x%8X)\n", lpUnknown, dispID);
3132
3133 if (lpUnknown)
3134 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3135
3136 if (SUCCEEDED(hRet))
3137 {
3138 IConnectionPoint* lpCP;
3139
3140 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3141 IConnectionPointContainer_Release(lpCPC);
3142
3143 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3144 IConnectionPoint_Release(lpCP);
3145 }
3146 return hRet;
3147 }
3148
3149 /*************************************************************************
3150 * @ [SHLWAPI.289]
3151 *
3152 * See PlaySoundW.
3153 */
3154 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3155 {
3156 return PlaySoundW(pszSound, hmod, fdwSound);
3157 }
3158
3159 /*************************************************************************
3160 * @ [SHLWAPI.294]
3161 */
3162 BOOL WINAPI SHGetIniStringW(LPCWSTR str1, LPCWSTR str2, LPWSTR pStr, DWORD some_len, LPCWSTR lpStr2)
3163 {
3164 FIXME("(%s,%s,%p,%08x,%s): stub!\n", debugstr_w(str1), debugstr_w(str2),
3165 pStr, some_len, debugstr_w(lpStr2));
3166 return TRUE;
3167 }
3168
3169 /*************************************************************************
3170 * @ [SHLWAPI.295]
3171 *
3172 * Called by ICQ2000b install via SHDOCVW:
3173 * str1: "InternetShortcut"
3174 * x: some unknown pointer
3175 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
3176 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
3177 *
3178 * In short: this one maybe creates a desktop link :-)
3179 */
3180 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
3181 {
3182 FIXME("(%s, %p, %s, %s), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
3183 return TRUE;
3184 }
3185
3186 /*************************************************************************
3187 * @ [SHLWAPI.313]
3188 *
3189 * See SHGetFileInfoW.
3190 */
3191 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3192 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3193 {
3194 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3195 }
3196
3197 /*************************************************************************
3198 * @ [SHLWAPI.318]
3199 *
3200 * See DragQueryFileW.
3201 */
3202 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3203 {
3204 return DragQueryFileW(hDrop, lFile, lpszFile, lLength);
3205 }
3206
3207 /*************************************************************************
3208 * @ [SHLWAPI.333]
3209 *
3210 * See SHBrowseForFolderW.
3211 */
3212 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3213 {
3214 return SHBrowseForFolderW(lpBi);
3215 }
3216
3217 /*************************************************************************
3218 * @ [SHLWAPI.334]
3219 *
3220 * See SHGetPathFromIDListW.
3221 */
3222 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3223 {
3224 return SHGetPathFromIDListW(pidl, pszPath);
3225 }
3226
3227 /*************************************************************************
3228 * @ [SHLWAPI.335]
3229 *
3230 * See ShellExecuteExW.
3231 */
3232 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3233 {
3234 return ShellExecuteExW(lpExecInfo);
3235 }
3236
3237 /*************************************************************************
3238 * @ [SHLWAPI.336]
3239 *
3240 * See SHFileOperationW.
3241 */
3242 INT WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3243 {
3244 return SHFileOperationW(lpFileOp);
3245 }
3246
3247 /*************************************************************************
3248 * @ [SHLWAPI.342]
3249 *
3250 */
3251 PVOID WINAPI SHInterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare )
3252 {
3253 return InterlockedCompareExchangePointer( dest, xchg, compare );
3254 }
3255
3256 /*************************************************************************
3257 * @ [SHLWAPI.350]
3258 *
3259 * See GetFileVersionInfoSizeW.
3260 */
3261 DWORD WINAPI GetFileVersionInfoSizeWrapW( LPCWSTR filename, LPDWORD handle )
3262 {
3263 return GetFileVersionInfoSizeW( filename, handle );
3264 }
3265
3266 /*************************************************************************
3267 * @ [SHLWAPI.351]
3268 *
3269 * See GetFileVersionInfoW.
3270 */
3271 BOOL WINAPI GetFileVersionInfoWrapW( LPCWSTR filename, DWORD handle,
3272 DWORD datasize, LPVOID data )
3273 {
3274 return GetFileVersionInfoW( filename, handle, datasize, data );
3275 }
3276
3277 /*************************************************************************
3278 * @ [SHLWAPI.352]
3279 *
3280 * See VerQueryValueW.
3281 */
3282 WORD WINAPI VerQueryValueWrapW( LPVOID pBlock, LPCWSTR lpSubBlock,
3283 LPVOID *lplpBuffer, UINT *puLen )
3284 {
3285 return VerQueryValueW( pBlock, lpSubBlock, lplpBuffer, puLen );
3286 }
3287
3288 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3289 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3290 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3291
3292 /*************************************************************************
3293 * @ [SHLWAPI.355]
3294 *
3295 * Change the modality of a shell object.
3296 *
3297 * PARAMS
3298 * lpUnknown [I] Object to make modeless
3299 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3300 *
3301 * RETURNS
3302 * Success: S_OK. The modality lpUnknown is changed.
3303 * Failure: An HRESULT error code indicating the error.
3304 *
3305 * NOTES
3306 * lpUnknown must support the IOleInPlaceFrame interface, the
3307 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3308 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3309 * or this call will fail.
3310 */
3311 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3312 {
3313 IUnknown *lpObj;
3314 HRESULT hRet;
3315
3316 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3317
3318 if (!lpUnknown)
3319 return E_FAIL;
3320
3321 if (IsIface(IOleInPlaceActiveObject))
3322 EnableModeless(IOleInPlaceActiveObject);
3323 else if (IsIface(IOleInPlaceFrame))
3324 EnableModeless(IOleInPlaceFrame);
3325 else if (IsIface(IShellBrowser))
3326 EnableModeless(IShellBrowser);
3327 else if (IsIface(IInternetSecurityMgrSite))
3328 EnableModeless(IInternetSecurityMgrSite);
3329 else if (IsIface(IDocHostUIHandler))
3330 EnableModeless(IDocHostUIHandler);
3331 else
3332 return hRet;
3333
3334 IUnknown_Release(lpObj);
3335 return S_OK;
3336 }