364bbfe8af8fe3d9e0cd2b43a0675ab2a86fc711
[reactos.git] / reactos / 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 }
3337
3338 /*************************************************************************
3339 * @ [SHLWAPI.357]
3340 *
3341 * See SHGetNewLinkInfoW.
3342 */
3343 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3344 BOOL *pfMustCopy, UINT uFlags)
3345 {
3346 return SHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3347 }
3348
3349 /*************************************************************************
3350 * @ [SHLWAPI.358]
3351 *
3352 * See SHDefExtractIconW.
3353 */
3354 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3355 HICON* phiconSmall, UINT nIconSize)
3356 {
3357 return SHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3358 }
3359
3360 /*************************************************************************
3361 * @ [SHLWAPI.363]
3362 *
3363 * Get and show a context menu from a shell folder.
3364 *
3365 * PARAMS
3366 * hWnd [I] Window displaying the shell folder
3367 * lpFolder [I] IShellFolder interface
3368 * lpApidl [I] Id for the particular folder desired
3369 * bInvokeDefault [I] Whether to invoke the default menu item
3370 *
3371 * RETURNS
3372 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3373 * executed.
3374 * Failure: An HRESULT error code indicating the error.
3375 */
3376 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3377 {
3378 IContextMenu *iContext;
3379 HRESULT hRet = E_FAIL;
3380
3381 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3382
3383 if (!lpFolder)
3384 return hRet;
3385
3386 /* Get the context menu from the shell folder */
3387 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3388 &IID_IContextMenu, 0, (void**)&iContext);
3389 if (SUCCEEDED(hRet))
3390 {
3391 HMENU hMenu;
3392 if ((hMenu = CreatePopupMenu()))
3393 {
3394 HRESULT hQuery;
3395 DWORD dwDefaultId = 0;
3396
3397 /* Add the context menu entries to the popup */
3398 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3399 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3400
3401 if (SUCCEEDED(hQuery))
3402 {
3403 if (bInvokeDefault &&
3404 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3405 {
3406 CMINVOKECOMMANDINFO cmIci;
3407 /* Invoke the default item */
3408 memset(&cmIci,0,sizeof(cmIci));
3409 cmIci.cbSize = sizeof(cmIci);
3410 cmIci.fMask = CMIC_MASK_ASYNCOK;
3411 cmIci.hwnd = hWnd;
3412 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3413 cmIci.nShow = SW_SCROLLCHILDREN;
3414
3415 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3416 }
3417 }
3418 DestroyMenu(hMenu);
3419 }
3420 IContextMenu_Release(iContext);
3421 }
3422 return hRet;
3423 }
3424
3425 /*************************************************************************
3426 * @ [SHLWAPI.370]
3427 *
3428 * See ExtractIconW.
3429 */
3430 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3431 UINT nIconIndex)
3432 {
3433 return ExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3434 }
3435
3436 /*************************************************************************
3437 * @ [SHLWAPI.377]
3438 *
3439 * Load a library from the directory of a particular process.
3440 *
3441 * PARAMS
3442 * new_mod [I] Library name
3443 * inst_hwnd [I] Module whose directory is to be used
3444 * dwCrossCodePage [I] Should be FALSE (currently ignored)
3445 *
3446 * RETURNS
3447 * Success: A handle to the loaded module
3448 * Failure: A NULL handle.
3449 */
3450 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3451 {
3452 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3453 * each call here.
3454 * FIXME: Native shows calls to:
3455 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3456 * CheckVersion
3457 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3458 * RegQueryValueExA for "LPKInstalled"
3459 * RegCloseKey
3460 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3461 * RegQueryValueExA for "ResourceLocale"
3462 * RegCloseKey
3463 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3464 * RegQueryValueExA for "Locale"
3465 * RegCloseKey
3466 * and then tests the Locale ("en" for me).
3467 * code below
3468 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3469 */
3470 CHAR mod_path[2*MAX_PATH];
3471 LPSTR ptr;
3472 DWORD len;
3473
3474 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwCrossCodePage);
3475 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3476 if (!len || len >= sizeof(mod_path)) return NULL;
3477
3478 ptr = strrchr(mod_path, '\\');
3479 if (ptr) {
3480 strcpy(ptr+1, new_mod);
3481 TRACE("loading %s\n", debugstr_a(mod_path));
3482 return LoadLibraryA(mod_path);
3483 }
3484 return NULL;
3485 }
3486
3487 /*************************************************************************
3488 * @ [SHLWAPI.378]
3489 *
3490 * Unicode version of MLLoadLibraryA.
3491 */
3492 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwCrossCodePage)
3493 {
3494 WCHAR mod_path[2*MAX_PATH];
3495 LPWSTR ptr;
3496 DWORD len;
3497
3498 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwCrossCodePage);
3499 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3500 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3501
3502 ptr = strrchrW(mod_path, '\\');
3503 if (ptr) {
3504 strcpyW(ptr+1, new_mod);
3505 TRACE("loading %s\n", debugstr_w(mod_path));
3506 return LoadLibraryW(mod_path);
3507 }
3508 return NULL;
3509 }
3510
3511 /*************************************************************************
3512 * ColorAdjustLuma [SHLWAPI.@]
3513 *
3514 * Adjust the luminosity of a color
3515 *
3516 * PARAMS
3517 * cRGB [I] RGB value to convert
3518 * dwLuma [I] Luma adjustment
3519 * bUnknown [I] Unknown
3520 *
3521 * RETURNS
3522 * The adjusted RGB color.
3523 */
3524 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3525 {
3526 TRACE("(0x%8x,%d,%d)\n", cRGB, dwLuma, bUnknown);
3527
3528 if (dwLuma)
3529 {
3530 WORD wH, wL, wS;
3531
3532 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3533
3534 FIXME("Ignoring luma adjustment\n");
3535
3536 /* FIXME: The adjustment is not linear */
3537
3538 cRGB = ColorHLSToRGB(wH, wL, wS);
3539 }
3540 return cRGB;
3541 }
3542
3543 /*************************************************************************
3544 * @ [SHLWAPI.389]
3545 *
3546 * See GetSaveFileNameW.
3547 */
3548 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3549 {
3550 return GetSaveFileNameW(ofn);
3551 }
3552
3553 /*************************************************************************
3554 * @ [SHLWAPI.390]
3555 *
3556 * See WNetRestoreConnectionW.
3557 */
3558 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3559 {
3560 return WNetRestoreConnectionW(hwndOwner, lpszDevice);
3561 }
3562
3563 /*************************************************************************
3564 * @ [SHLWAPI.391]
3565 *
3566 * See WNetGetLastErrorW.
3567 */
3568 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3569 LPWSTR lpNameBuf, DWORD nNameBufSize)
3570 {
3571 return WNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3572 }
3573
3574 /*************************************************************************
3575 * @ [SHLWAPI.401]
3576 *
3577 * See PageSetupDlgW.
3578 */
3579 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3580 {
3581 return PageSetupDlgW(pagedlg);
3582 }
3583
3584 /*************************************************************************
3585 * @ [SHLWAPI.402]
3586 *
3587 * See PrintDlgW.
3588 */
3589 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3590 {
3591 return PrintDlgW(printdlg);
3592 }
3593
3594 /*************************************************************************
3595 * @ [SHLWAPI.403]
3596 *
3597 * See GetOpenFileNameW.
3598 */
3599 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3600 {
3601 return GetOpenFileNameW(ofn);
3602 }
3603
3604 /*************************************************************************
3605 * @ [SHLWAPI.404]
3606 */
3607 HRESULT WINAPI SHIShellFolder_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3608 {
3609 IPersist *persist;
3610 HRESULT hr;
3611
3612 hr = IShellFolder_QueryInterface(lpFolder, &IID_IPersist, (LPVOID)&persist);
3613 if(SUCCEEDED(hr))
3614 {
3615 CLSID clsid;
3616 hr = IPersist_GetClassID(persist, &clsid);
3617 if(SUCCEEDED(hr))
3618 {
3619 if(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder))
3620 hr = IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3621 else
3622 hr = E_FAIL;
3623 }
3624 IPersist_Release(persist);
3625 }
3626 return hr;
3627 }
3628
3629 /* INTERNAL: Map from HLS color space to RGB */
3630 static WORD ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3631 {
3632 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3633
3634 if (wHue > 160)
3635 return wMid1;
3636 else if (wHue > 120)
3637 wHue = 160 - wHue;
3638 else if (wHue > 40)
3639 return wMid2;
3640
3641 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3642 }
3643
3644 /* Convert to RGB and scale into RGB range (0..255) */
3645 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3646
3647 /*************************************************************************
3648 * ColorHLSToRGB [SHLWAPI.@]
3649 *
3650 * Convert from hls color space into an rgb COLORREF.
3651 *
3652 * PARAMS
3653 * wHue [I] Hue amount
3654 * wLuminosity [I] Luminosity amount
3655 * wSaturation [I] Saturation amount
3656 *
3657 * RETURNS
3658 * A COLORREF representing the converted color.
3659 *
3660 * NOTES
3661 * Input hls values are constrained to the range (0..240).
3662 */
3663 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3664 {
3665 WORD wRed;
3666
3667 if (wSaturation)
3668 {
3669 WORD wGreen, wBlue, wMid1, wMid2;
3670
3671 if (wLuminosity > 120)
3672 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3673 else
3674 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3675
3676 wMid1 = wLuminosity * 2 - wMid2;
3677
3678 wRed = GET_RGB(wHue + 80);
3679 wGreen = GET_RGB(wHue);
3680 wBlue = GET_RGB(wHue - 80);
3681
3682 return RGB(wRed, wGreen, wBlue);
3683 }
3684
3685 wRed = wLuminosity * 255 / 240;
3686 return RGB(wRed, wRed, wRed);
3687 }
3688
3689 /*************************************************************************
3690 * @ [SHLWAPI.413]
3691 *
3692 * Get the current docking status of the system.
3693 *
3694 * PARAMS
3695 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3696 *
3697 * RETURNS
3698 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3699 * a notebook.
3700 */
3701 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3702 {
3703 HW_PROFILE_INFOA hwInfo;
3704
3705 TRACE("(0x%08x)\n", dwFlags);
3706
3707 GetCurrentHwProfileA(&hwInfo);
3708 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3709 {
3710 case DOCKINFO_DOCKED:
3711 case DOCKINFO_UNDOCKED:
3712 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3713 default:
3714 return 0;
3715 }
3716 }
3717
3718 /*************************************************************************
3719 * @ [SHLWAPI.418]
3720 *
3721 * Function seems to do FreeLibrary plus other things.
3722 *
3723 * FIXME native shows the following calls:
3724 * RtlEnterCriticalSection
3725 * LocalFree
3726 * GetProcAddress(Comctl32??, 150L)
3727 * DPA_DeletePtr
3728 * RtlLeaveCriticalSection
3729 * followed by the FreeLibrary.
3730 * The above code may be related to .377 above.
3731 */
3732 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3733 {
3734 FIXME("(%p) semi-stub\n", hModule);
3735 return FreeLibrary(hModule);
3736 }
3737
3738 /*************************************************************************
3739 * @ [SHLWAPI.419]
3740 */
3741 BOOL WINAPI SHFlushSFCacheWrap(void) {
3742 FIXME(": stub\n");
3743 return TRUE;
3744 }
3745
3746 /*************************************************************************
3747 * @ [SHLWAPI.429]
3748 * FIXME I have no idea what this function does or what its arguments are.
3749 */
3750 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3751 {
3752 FIXME("(%p) stub\n", hInst);
3753 return FALSE;
3754 }
3755
3756
3757 /*************************************************************************
3758 * @ [SHLWAPI.430]
3759 */
3760 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3761 {
3762 FIXME("(%p,%p) stub\n", hInst, hHeap);
3763 return E_FAIL; /* This is what is used if shlwapi not loaded */
3764 }
3765
3766 /*************************************************************************
3767 * @ [SHLWAPI.431]
3768 */
3769 DWORD WINAPI MLClearMLHInstance(DWORD x)
3770 {
3771 FIXME("(0x%08x)stub\n", x);
3772 return 0xabba1247;
3773 }
3774
3775 /*************************************************************************
3776 * @ [SHLWAPI.432]
3777 *
3778 * See SHSendMessageBroadcastW
3779 *
3780 */
3781 DWORD WINAPI SHSendMessageBroadcastA(UINT uMsg, WPARAM wParam, LPARAM lParam)
3782 {
3783 return SendMessageTimeoutA(HWND_BROADCAST, uMsg, wParam, lParam,
3784 SMTO_ABORTIFHUNG, 2000, NULL);
3785 }
3786
3787 /*************************************************************************
3788 * @ [SHLWAPI.433]
3789 *
3790 * A wrapper for sending Broadcast Messages to all top level Windows
3791 *
3792 */
3793 DWORD WINAPI SHSendMessageBroadcastW(UINT uMsg, WPARAM wParam, LPARAM lParam)
3794 {
3795 return SendMessageTimeoutW(HWND_BROADCAST, uMsg, wParam, lParam,
3796 SMTO_ABORTIFHUNG, 2000, NULL);
3797 }
3798
3799 /*************************************************************************
3800 * @ [SHLWAPI.436]
3801 *
3802 * Convert a Unicode string CLSID into a CLSID.
3803 *
3804 * PARAMS
3805 * idstr [I] string containing a CLSID in text form
3806 * id [O] CLSID extracted from the string
3807 *
3808 * RETURNS
3809 * S_OK on success or E_INVALIDARG on failure
3810 */
3811 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3812 {
3813 return CLSIDFromString((LPOLESTR)idstr, id);
3814 }
3815
3816 /*************************************************************************
3817 * @ [SHLWAPI.437]
3818 *
3819 * Determine if the OS supports a given feature.
3820 *
3821 * PARAMS
3822 * dwFeature [I] Feature requested (undocumented)
3823 *
3824 * RETURNS
3825 * TRUE If the feature is available.
3826 * FALSE If the feature is not available.
3827 */
3828 BOOL WINAPI IsOS(DWORD feature)
3829 {
3830 OSVERSIONINFOA osvi;
3831 DWORD platform, majorv, minorv;
3832
3833 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3834 if(!GetVersionExA(&osvi)) {
3835 ERR("GetVersionEx failed\n");
3836 return FALSE;
3837 }
3838
3839 majorv = osvi.dwMajorVersion;
3840 minorv = osvi.dwMinorVersion;
3841 platform = osvi.dwPlatformId;
3842
3843 #define ISOS_RETURN(x) \
3844 TRACE("(0x%x) ret=%d\n",feature,(x)); \
3845 return (x);
3846
3847 switch(feature) {
3848 case OS_WIN32SORGREATER:
3849 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3850 || platform == VER_PLATFORM_WIN32_WINDOWS)
3851 case OS_NT:
3852 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3853 case OS_WIN95ORGREATER:
3854 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3855 case OS_NT4ORGREATER:
3856 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3857 case OS_WIN2000ORGREATER_ALT:
3858 case OS_WIN2000ORGREATER:
3859 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3860 case OS_WIN98ORGREATER:
3861 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3862 case OS_WIN98_GOLD:
3863 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3864 case OS_WIN2000PRO:
3865 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3866 case OS_WIN2000SERVER:
3867 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3868 case OS_WIN2000ADVSERVER:
3869 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3870 case OS_WIN2000DATACENTER:
3871 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3872 case OS_WIN2000TERMINAL:
3873 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3874 case OS_EMBEDDED:
3875 FIXME("(OS_EMBEDDED) What should we return here?\n");
3876 return FALSE;
3877 case OS_TERMINALCLIENT:
3878 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3879 return FALSE;
3880 case OS_TERMINALREMOTEADMIN:
3881 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3882 return FALSE;
3883 case OS_WIN95_GOLD:
3884 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3885 case OS_MEORGREATER:
3886 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3887 case OS_XPORGREATER:
3888 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3889 case OS_HOME:
3890 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3891 case OS_PROFESSIONAL:
3892 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3893 case OS_DATACENTER:
3894 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3895 case OS_ADVSERVER:
3896 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3897 case OS_SERVER:
3898 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3899 case OS_TERMINALSERVER:
3900 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3901 case OS_PERSONALTERMINALSERVER:
3902 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3903 case OS_FASTUSERSWITCHING:
3904 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3905 return TRUE;
3906 case OS_WELCOMELOGONUI:
3907 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3908 return FALSE;
3909 case OS_DOMAINMEMBER:
3910 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3911 return TRUE;
3912 case OS_ANYSERVER:
3913 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3914 case OS_WOW6432:
3915 FIXME("(OS_WOW6432) Should we check this?\n");
3916 return FALSE;
3917 case OS_WEBSERVER:
3918 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3919 case OS_SMALLBUSINESSSERVER:
3920 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3921 case OS_TABLETPC:
3922 FIXME("(OS_TABLEPC) What should we return here?\n");
3923 return FALSE;
3924 case OS_SERVERADMINUI:
3925 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3926 return FALSE;
3927 case OS_MEDIACENTER:
3928 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3929 return FALSE;
3930 case OS_APPLIANCE:
3931 FIXME("(OS_APPLIANCE) What should we return here?\n");
3932 return FALSE;
3933 case 0x25: /*OS_VISTAORGREATER*/
3934 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 6)
3935 }
3936
3937 #undef ISOS_RETURN
3938
3939 WARN("(0x%x) unknown parameter\n",feature);
3940
3941 return FALSE;
3942 }
3943
3944 /*************************************************************************
3945 * @ [SHLWAPI.439]
3946 */
3947 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
3948 {
3949 DWORD type, sz = size;
3950
3951 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
3952 return E_FAIL;
3953
3954 return SHLoadIndirectString(buf, buf, size, NULL);
3955 }
3956
3957 /*************************************************************************
3958 * @ [SHLWAPI.478]
3959 *
3960 * Call IInputObject_TranslateAcceleratorIO() on an object.
3961 *
3962 * PARAMS
3963 * lpUnknown [I] Object supporting the IInputObject interface.
3964 * lpMsg [I] Key message to be processed.
3965 *
3966 * RETURNS
3967 * Success: S_OK.
3968 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3969 */
3970 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
3971 {
3972 IInputObject* lpInput = NULL;
3973 HRESULT hRet = E_INVALIDARG;
3974
3975 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
3976 if (lpUnknown)
3977 {
3978 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3979 (void**)&lpInput);
3980 if (SUCCEEDED(hRet) && lpInput)
3981 {
3982 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
3983 IInputObject_Release(lpInput);
3984 }
3985 }
3986 return hRet;
3987 }
3988
3989 /*************************************************************************
3990 * @ [SHLWAPI.481]
3991 *
3992 * Call IInputObject_HasFocusIO() on an object.
3993 *
3994 * PARAMS
3995 * lpUnknown [I] Object supporting the IInputObject interface.
3996 *
3997 * RETURNS
3998 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
3999 * or S_FALSE otherwise.
4000 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4001 */
4002 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
4003 {
4004 IInputObject* lpInput = NULL;
4005 HRESULT hRet = E_INVALIDARG;
4006
4007 TRACE("(%p)\n", lpUnknown);
4008 if (lpUnknown)
4009 {
4010 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4011 (void**)&lpInput);
4012 if (SUCCEEDED(hRet) && lpInput)
4013 {
4014 hRet = IInputObject_HasFocusIO(lpInput);
4015 IInputObject_Release(lpInput);
4016 }
4017 }
4018 return hRet;
4019 }
4020
4021 /*************************************************************************
4022 * ColorRGBToHLS [SHLWAPI.@]
4023 *
4024 * Convert an rgb COLORREF into the hls color space.
4025 *
4026 * PARAMS
4027 * cRGB [I] Source rgb value
4028 * pwHue [O] Destination for converted hue
4029 * pwLuminance [O] Destination for converted luminance
4030 * pwSaturation [O] Destination for converted saturation
4031 *
4032 * RETURNS
4033 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4034 * values.
4035 *
4036 * NOTES
4037 * Output HLS values are constrained to the range (0..240).
4038 * For Achromatic conversions, Hue is set to 160.
4039 */
4040 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
4041 LPWORD pwLuminance, LPWORD pwSaturation)
4042 {
4043 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4044
4045 TRACE("(%08x,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4046
4047 wR = GetRValue(cRGB);
4048 wG = GetGValue(cRGB);
4049 wB = GetBValue(cRGB);
4050
4051 wMax = max(wR, max(wG, wB));
4052 wMin = min(wR, min(wG, wB));
4053
4054 /* Luminosity */
4055 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4056
4057 if (wMax == wMin)
4058 {
4059 /* Achromatic case */
4060 wSaturation = 0;
4061 /* Hue is now unrepresentable, but this is what native returns... */
4062 wHue = 160;
4063 }
4064 else
4065 {
4066 /* Chromatic case */
4067 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4068
4069 /* Saturation */
4070 if (wLuminosity <= 120)
4071 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4072 else
4073 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4074
4075 /* Hue */
4076 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4077 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4078 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4079
4080 if (wR == wMax)
4081 wHue = wBNorm - wGNorm;
4082 else if (wG == wMax)
4083 wHue = 80 + wRNorm - wBNorm;
4084 else
4085 wHue = 160 + wGNorm - wRNorm;
4086 if (wHue < 0)
4087 wHue += 240;
4088 else if (wHue > 240)
4089 wHue -= 240;
4090 }
4091 if (pwHue)
4092 *pwHue = wHue;
4093 if (pwLuminance)
4094 *pwLuminance = wLuminosity;
4095 if (pwSaturation)
4096 *pwSaturation = wSaturation;
4097 }
4098
4099 /*************************************************************************
4100 * SHCreateShellPalette [SHLWAPI.@]
4101 */
4102 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4103 {
4104 FIXME("stub\n");
4105 return CreateHalftonePalette(hdc);
4106 }
4107
4108 /*************************************************************************
4109 * SHGetInverseCMAP (SHLWAPI.@)
4110 *
4111 * Get an inverse color map table.
4112 *
4113 * PARAMS
4114 * lpCmap [O] Destination for color map
4115 * dwSize [I] Size of memory pointed to by lpCmap
4116 *
4117 * RETURNS
4118 * Success: S_OK.
4119 * Failure: E_POINTER, If lpCmap is invalid.
4120 * E_INVALIDARG, If dwFlags is invalid
4121 * E_OUTOFMEMORY, If there is no memory available
4122 *
4123 * NOTES
4124 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4125 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4126 * internal CMap.
4127 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4128 * this DLL's internal CMap.
4129 */
4130 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4131 {
4132 if (dwSize == 4) {
4133 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4134 *dest = (DWORD)0xabba1249;
4135 return 0;
4136 }
4137 FIXME("(%p, %#x) stub\n", dest, dwSize);
4138 return 0;
4139 }
4140
4141 /*************************************************************************
4142 * SHIsLowMemoryMachine [SHLWAPI.@]
4143 *
4144 * Determine if the current computer has low memory.
4145 *
4146 * PARAMS
4147 * x [I] FIXME
4148 *
4149 * RETURNS
4150 * TRUE if the users machine has 16 Megabytes of memory or less,
4151 * FALSE otherwise.
4152 */
4153 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4154 {
4155 FIXME("(0x%08x) stub\n", x);
4156 return FALSE;
4157 }
4158
4159 /*************************************************************************
4160 * GetMenuPosFromID [SHLWAPI.@]
4161 *
4162 * Return the position of a menu item from its Id.
4163 *
4164 * PARAMS
4165 * hMenu [I] Menu containing the item
4166 * wID [I] Id of the menu item
4167 *
4168 * RETURNS
4169 * Success: The index of the menu item in hMenu.
4170 * Failure: -1, If the item is not found.
4171 */
4172 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4173 {
4174 MENUITEMINFOW mi;
4175 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4176
4177 while (nIter < nCount)
4178 {
4179 mi.cbSize = sizeof(mi);
4180 mi.fMask = MIIM_ID;
4181 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4182 return nIter;
4183 nIter++;
4184 }
4185 return -1;
4186 }
4187
4188 /*************************************************************************
4189 * @ [SHLWAPI.179]
4190 *
4191 * Same as SHLWAPI.GetMenuPosFromID
4192 */
4193 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4194 {
4195 return GetMenuPosFromID(hMenu, uID);
4196 }
4197
4198
4199 /*************************************************************************
4200 * @ [SHLWAPI.448]
4201 */
4202 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4203 {
4204 while (*lpwstr)
4205 {
4206 if (*lpwstr == '/')
4207 *lpwstr = '\\';
4208 lpwstr++;
4209 }
4210 }
4211
4212
4213 /*************************************************************************
4214 * @ [SHLWAPI.461]
4215 */
4216 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4217 {
4218 FIXME("(0x%08x) stub\n", dwUnknown);
4219 return 0;
4220 }
4221
4222
4223 /*************************************************************************
4224 * @ [SHLWAPI.549]
4225 */
4226 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4227 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4228 {
4229 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4230 }
4231
4232 /*************************************************************************
4233 * SHSkipJunction [SHLWAPI.@]
4234 *
4235 * Determine if a bind context can be bound to an object
4236 *
4237 * PARAMS
4238 * pbc [I] Bind context to check
4239 * pclsid [I] CLSID of object to be bound to
4240 *
4241 * RETURNS
4242 * TRUE: If it is safe to bind
4243 * FALSE: If pbc is invalid or binding would not be safe
4244 *
4245 */
4246 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4247 {
4248 static WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4249 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4250 BOOL bRet = FALSE;
4251
4252 if (pbc)
4253 {
4254 IUnknown* lpUnk;
4255
4256 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, szSkipBinding, &lpUnk)))
4257 {
4258 CLSID clsid;
4259
4260 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4261 IsEqualGUID(pclsid, &clsid))
4262 bRet = TRUE;
4263
4264 IUnknown_Release(lpUnk);
4265 }
4266 }
4267 return bRet;
4268 }
4269
4270 /***********************************************************************
4271 * SHGetShellKey (SHLWAPI.@)
4272 */
4273 DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
4274 {
4275 FIXME("(%x, %x, %x): stub\n", a, b, c);
4276 return 0x50;
4277 }
4278
4279 /***********************************************************************
4280 * SHQueueUserWorkItem (SHLWAPI.@)
4281 */
4282 BOOL WINAPI SHQueueUserWorkItem(LPTHREAD_START_ROUTINE pfnCallback,
4283 LPVOID pContext, LONG lPriority, DWORD_PTR dwTag,
4284 DWORD_PTR *pdwId, LPCSTR pszModule, DWORD dwFlags)
4285 {
4286 TRACE("(%p, %p, %d, %lx, %p, %s, %08x)\n", pfnCallback, pContext,
4287 lPriority, dwTag, pdwId, debugstr_a(pszModule), dwFlags);
4288
4289 if(lPriority || dwTag || pdwId || pszModule || dwFlags)
4290 FIXME("Unsupported arguments\n");
4291
4292 return QueueUserWorkItem(pfnCallback, pContext, 0);
4293 }
4294
4295 /***********************************************************************
4296 * SHSetTimerQueueTimer (SHLWAPI.263)
4297 */
4298 HANDLE WINAPI SHSetTimerQueueTimer(HANDLE hQueue,
4299 WAITORTIMERCALLBACK pfnCallback, LPVOID pContext, DWORD dwDueTime,
4300 DWORD dwPeriod, LPCSTR lpszLibrary, DWORD dwFlags)
4301 {
4302 HANDLE hNewTimer;
4303
4304 /* SHSetTimerQueueTimer flags -> CreateTimerQueueTimer flags */
4305 if (dwFlags & TPS_LONGEXECTIME) {
4306 dwFlags &= ~TPS_LONGEXECTIME;
4307 dwFlags |= WT_EXECUTELONGFUNCTION;
4308 }
4309 if (dwFlags & TPS_EXECUTEIO) {
4310 dwFlags &= ~TPS_EXECUTEIO;
4311 dwFlags |= WT_EXECUTEINIOTHREAD;
4312 }
4313
4314 if (!CreateTimerQueueTimer(&hNewTimer, hQueue, pfnCallback, pContext,
4315 dwDueTime, dwPeriod, dwFlags))
4316 return NULL;
4317
4318 return hNewTimer;
4319 }
4320
4321 /***********************************************************************
4322 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4323 */
4324 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4325 {
4326 IInputObjectSite *pIOS = NULL;
4327 HRESULT hRet = E_INVALIDARG;
4328
4329 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4330
4331 if (lpUnknown)
4332 {
4333 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4334 (void **)&pIOS);
4335 if (SUCCEEDED(hRet) && pIOS)
4336 {
4337 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4338 IInputObjectSite_Release(pIOS);
4339 }
4340 }
4341 return hRet;
4342 }
4343
4344 /***********************************************************************
4345 * SHGetValueW (SHLWAPI.@)
4346 */
4347 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4348 {
4349 FIXME("(%x, %s, %s, %x, %x, %x): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4350 return E_FAIL;
4351 }
4352
4353 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4354
4355 /***********************************************************************
4356 * GetUIVersion (SHLWAPI.452)
4357 */
4358 DWORD WINAPI GetUIVersion(void)
4359 {
4360 static DWORD version;
4361
4362 if (!version)
4363 {
4364 DllGetVersion_func pDllGetVersion;
4365 HMODULE dll = LoadLibraryA("shell32.dll");
4366 if (!dll) return 0;
4367
4368 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4369 if (pDllGetVersion)
4370 {
4371 DLLVERSIONINFO dvi;
4372 dvi.cbSize = sizeof(DLLVERSIONINFO);
4373 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4374 }
4375 FreeLibrary( dll );
4376 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4377 }
4378 return version;
4379 }
4380
4381 /***********************************************************************
4382 * ShellMessageBoxWrapW [SHLWAPI.388]
4383 *
4384 * See shell32.ShellMessageBoxW
4385 *
4386 * NOTE:
4387 * shlwapi.ShellMessageBoxWrapW is a duplicate of shell32.ShellMessageBoxW
4388 * because we can't forward to it in the .spec file since it's exported by
4389 * ordinal. If you change the implementation here please update the code in
4390 * shell32 as well.
4391 */
4392 INT WINAPIV ShellMessageBoxWrapW(HINSTANCE hInstance, HWND hWnd, LPCWSTR lpText,
4393 LPCWSTR lpCaption, UINT uType, ...)
4394 {
4395 WCHAR szText[100], szTitle[100];
4396 LPCWSTR pszText = szText, pszTitle = szTitle;
4397 LPWSTR pszTemp;
4398 __ms_va_list args;
4399 int ret;
4400
4401 __ms_va_start(args, uType);
4402
4403 TRACE("(%p,%p,%p,%p,%08x)\n", hInstance, hWnd, lpText, lpCaption, uType);
4404
4405 if (IS_INTRESOURCE(lpCaption))
4406 LoadStringW(hInstance, LOWORD(lpCaption), szTitle, sizeof(szTitle)/sizeof(szTitle[0]));
4407 else
4408 pszTitle = lpCaption;
4409
4410 if (IS_INTRESOURCE(lpText))
4411 LoadStringW(hInstance, LOWORD(lpText), szText, sizeof(szText)/sizeof(szText[0]));
4412 else
4413 pszText = lpText;
4414
4415 FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
4416 pszText, 0, 0, (LPWSTR)&pszTemp, 0, &args);
4417
4418 __ms_va_end(args);
4419
4420 ret = MessageBoxW(hWnd, pszTemp, pszTitle, uType);
4421 LocalFree(pszTemp);
4422 return ret;
4423 }
4424
4425 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *unk, REFIID service, REFIID clsid,
4426 DWORD x1, DWORD x2, DWORD x3, void **ppvOut)
4427 {
4428 FIXME("%p %s %s %08x %08x %08x %p\n", unk,
4429 debugstr_guid(service), debugstr_guid(clsid), x1, x2, x3, ppvOut);
4430 return E_NOTIMPL;
4431 }
4432
4433 HRESULT WINAPI IUnknown_ProfferService(IUnknown *unk, void *x0, void *x1, void *x2)
4434 {
4435 FIXME("%p %p %p %p\n", unk, x0, x1, x2);
4436 return E_NOTIMPL;
4437 }
4438
4439 /***********************************************************************
4440 * ZoneComputePaneSize [SHLWAPI.382]
4441 */
4442 UINT WINAPI ZoneComputePaneSize(HWND hwnd)
4443 {
4444 FIXME("\n");
4445 return 0x95;
4446 }
4447
4448 /***********************************************************************
4449 * SHChangeNotifyWrap [SHLWAPI.394]
4450 */
4451 void WINAPI SHChangeNotifyWrap(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
4452 {
4453 SHChangeNotify(wEventId, uFlags, dwItem1, dwItem2);
4454 }
4455
4456 typedef struct SHELL_USER_SID { /* according to MSDN this should be in shlobj.h... */
4457 SID_IDENTIFIER_AUTHORITY sidAuthority;
4458 DWORD dwUserGroupID;
4459 DWORD dwUserID;
4460 } SHELL_USER_SID, *PSHELL_USER_SID;
4461
4462 typedef struct SHELL_USER_PERMISSION { /* ...and this should be in shlwapi.h */
4463 SHELL_USER_SID susID;
4464 DWORD dwAccessType;
4465 BOOL fInherit;
4466 DWORD dwAccessMask;
4467 DWORD dwInheritMask;
4468 DWORD dwInheritAccessMask;
4469 } SHELL_USER_PERMISSION, *PSHELL_USER_PERMISSION;
4470
4471 /***********************************************************************
4472 * GetShellSecurityDescriptor [SHLWAPI.475]
4473 *
4474 * prepares SECURITY_DESCRIPTOR from a set of ACEs
4475 *
4476 * PARAMS
4477 * apUserPerm [I] array of pointers to SHELL_USER_PERMISSION structures,
4478 * each of which describes permissions to apply
4479 * cUserPerm [I] number of entries in apUserPerm array
4480 *
4481 * RETURNS
4482 * success: pointer to SECURITY_DESCRIPTOR
4483 * failure: NULL
4484 *
4485 * NOTES
4486 * Call should free returned descriptor with LocalFree
4487 */
4488 PSECURITY_DESCRIPTOR WINAPI GetShellSecurityDescriptor(PSHELL_USER_PERMISSION *apUserPerm, int cUserPerm)
4489 {
4490 PSID *sidlist;
4491 PSID cur_user = NULL;
4492 BYTE tuUser[2000];
4493 DWORD acl_size;
4494 int sid_count, i;
4495 PSECURITY_DESCRIPTOR psd = NULL;
4496
4497 TRACE("%p %d\n", apUserPerm, cUserPerm);
4498
4499 if (apUserPerm == NULL || cUserPerm <= 0)
4500 return NULL;
4501
4502 sidlist = HeapAlloc(GetProcessHeap(), 0, cUserPerm * sizeof(PSID));
4503 if (!sidlist)
4504 return NULL;
4505
4506 acl_size = sizeof(ACL);
4507
4508 for(sid_count = 0; sid_count < cUserPerm; sid_count++)
4509 {
4510 static SHELL_USER_SID null_sid = {{SECURITY_NULL_SID_AUTHORITY}, 0, 0};
4511 PSHELL_USER_PERMISSION perm = apUserPerm[sid_count];
4512 PSHELL_USER_SID sid = &perm->susID;
4513 PSID pSid;
4514 BOOL ret = TRUE;
4515
4516 if (!memcmp((void*)sid, (void*)&null_sid, sizeof(SHELL_USER_SID)))
4517 { /* current user's SID */
4518 if (!cur_user)
4519 {
4520 HANDLE Token;
4521 DWORD bufsize = sizeof(tuUser);
4522
4523 ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &Token);
4524 if (ret)
4525 {
4526 ret = GetTokenInformation(Token, TokenUser, (void*)tuUser, bufsize, &bufsize );
4527 if (ret)
4528 cur_user = ((PTOKEN_USER)tuUser)->User.Sid;
4529 CloseHandle(Token);
4530 }
4531 }
4532 pSid = cur_user;
4533 } else if (sid->dwUserID==0) /* one sub-authority */
4534 ret = AllocateAndInitializeSid(&sid->sidAuthority, 1, sid->dwUserGroupID, 0,
4535 0, 0, 0, 0, 0, 0, &pSid);
4536 else
4537 ret = AllocateAndInitializeSid(&sid->sidAuthority, 2, sid->dwUserGroupID, sid->dwUserID,
4538 0, 0, 0, 0, 0, 0, &pSid);
4539 if (!ret)
4540 goto free_sids;
4541
4542 sidlist[sid_count] = pSid;
4543 /* increment acl_size (1 ACE for non-inheritable and 2 ACEs for inheritable records */
4544 acl_size += (sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + GetLengthSid(pSid)) * (perm->fInherit ? 2 : 1);
4545 }
4546
4547 psd = LocalAlloc(0, sizeof(SECURITY_DESCRIPTOR) + acl_size);
4548
4549 if (psd != NULL)
4550 {
4551 PACL pAcl = (PACL)(((BYTE*)psd)+sizeof(SECURITY_DESCRIPTOR));
4552
4553 if (!InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION))
4554 goto error;
4555
4556 if (!InitializeAcl(pAcl, acl_size, ACL_REVISION))
4557 goto error;
4558
4559 for(i = 0; i < sid_count; i++)
4560 {
4561 PSHELL_USER_PERMISSION sup = apUserPerm[i];
4562 PSID sid = sidlist[i];
4563
4564 switch(sup->dwAccessType)
4565 {
4566 case ACCESS_ALLOWED_ACE_TYPE:
4567 if (!AddAccessAllowedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4568 goto error;
4569 if (sup->fInherit && !AddAccessAllowedAceEx(pAcl, ACL_REVISION,
4570 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4571 goto error;
4572 break;
4573 case ACCESS_DENIED_ACE_TYPE:
4574 if (!AddAccessDeniedAce(pAcl, ACL_REVISION, sup->dwAccessMask, sid))
4575 goto error;
4576 if (sup->fInherit && !AddAccessDeniedAceEx(pAcl, ACL_REVISION,
4577 (BYTE)sup->dwInheritMask, sup->dwInheritAccessMask, sid))
4578 goto error;
4579 break;
4580 default:
4581 goto error;
4582 }
4583 }
4584
4585 if (!SetSecurityDescriptorDacl(psd, TRUE, pAcl, FALSE))
4586 goto error;
4587 }
4588 goto free_sids;
4589
4590 error:
4591 LocalFree(psd);
4592 psd = NULL;
4593 free_sids:
4594 for(i = 0; i < sid_count; i++)
4595 {
4596 if (!cur_user || sidlist[i] != cur_user)
4597 FreeSid(sidlist[i]);
4598 }
4599 HeapFree(GetProcessHeap(), 0, sidlist);
4600
4601 return psd;
4602 }
4603
4604 /***********************************************************************
4605 * SHCreatePropertyBagOnRegKey [SHLWAPI.471]
4606 *
4607 * Creates a property bag from a registry key
4608 *
4609 * PARAMS
4610 * hKey [I] Handle to the desired registry key
4611 * subkey [I] Name of desired subkey, or NULL to open hKey directly
4612 * grfMode [I] Optional flags
4613 * riid [I] IID of requested property bag interface
4614 * ppv [O] Address to receive pointer to the new interface
4615 *
4616 * RETURNS
4617 * success: 0
4618 * failure: error code
4619 *
4620 */
4621 HRESULT WINAPI SHCreatePropertyBagOnRegKey (HKEY hKey, LPCWSTR subkey,
4622 DWORD grfMode, REFIID riid, void **ppv)
4623 {
4624 FIXME("%p %s %d %s %p STUB\n", hKey, debugstr_w(subkey), grfMode,
4625 debugstr_guid(riid), ppv);
4626
4627 return E_NOTIMPL;
4628 }
4629
4630 /***********************************************************************
4631 * SHGetViewStatePropertyBag [SHLWAPI.515]
4632 *
4633 * Retrieves a property bag in which the view state information of a folder
4634 * can be stored.
4635 *
4636 * PARAMS
4637 * pidl [I] PIDL of the folder requested
4638 * bag_name [I] Name of the property bag requested
4639 * flags [I] Optional flags
4640 * riid [I] IID of requested property bag interface
4641 * ppv [O] Address to receive pointer to the new interface
4642 *
4643 * RETURNS
4644 * success: S_OK
4645 * failure: error code
4646 *
4647 */
4648 HRESULT WINAPI SHGetViewStatePropertyBag(LPCITEMIDLIST pidl, LPWSTR bag_name,
4649 DWORD flags, REFIID riid, void **ppv)
4650 {
4651 FIXME("%p %s %d %s %p STUB\n", pidl, debugstr_w(bag_name), flags,
4652 debugstr_guid(riid), ppv);
4653
4654 return E_NOTIMPL;
4655 }
4656
4657 /***********************************************************************
4658 * SHFormatDateTimeW [SHLWAPI.354]
4659 *
4660 * Produces a string representation of a time.
4661 *
4662 * PARAMS
4663 * fileTime [I] Pointer to FILETIME structure specifying the time
4664 * flags [I] Flags specifying the desired output
4665 * buf [O] Pointer to buffer for output
4666 * size [I] Number of characters that can be contained in buffer
4667 *
4668 * RETURNS
4669 * success: number of characters written to the buffer
4670 * failure: 0
4671 *
4672 */
4673 INT WINAPI SHFormatDateTimeW(const FILETIME UNALIGNED *fileTime, DWORD *flags,
4674 LPWSTR buf, UINT size)
4675 {
4676 #define SHFORMATDT_UNSUPPORTED_FLAGS (FDTF_RELATIVE | FDTF_LTRDATE | FDTF_RTLDATE | FDTF_NOAUTOREADINGORDER)
4677 DWORD fmt_flags = flags ? *flags : FDTF_DEFAULT;
4678 SYSTEMTIME st;
4679 FILETIME ft;
4680 INT ret = 0;
4681
4682 TRACE("%p %p %p %u\n", fileTime, flags, buf, size);
4683
4684 if (!buf || !size)
4685 return 0;
4686
4687 if (fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS)
4688 FIXME("ignoring some flags - 0x%08x\n", fmt_flags & SHFORMATDT_UNSUPPORTED_FLAGS);
4689
4690 FileTimeToLocalFileTime(fileTime, &ft);
4691 FileTimeToSystemTime(&ft, &st);
4692
4693 /* first of all date */
4694 if (fmt_flags & (FDTF_LONGDATE | FDTF_SHORTDATE))
4695 {
4696 static const WCHAR sep1[] = {',',' ',0};
4697 static const WCHAR sep2[] = {' ',0};
4698
4699 DWORD date = fmt_flags & FDTF_LONGDATE ? DATE_LONGDATE : DATE_SHORTDATE;
4700 ret = GetDateFormatW(LOCALE_USER_DEFAULT, date, &st, NULL, buf, size);
4701 if (ret >= size) return ret;
4702
4703 /* add separator */
4704 if (ret < size && (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME)))
4705 {
4706 if ((fmt_flags & FDTF_LONGDATE) && (ret < size + 2))
4707 {
4708 if (ret < size + 2)
4709 {
4710 lstrcatW(&buf[ret-1], sep1);
4711 ret += 2;
4712 }
4713 }
4714 else
4715 {
4716 lstrcatW(&buf[ret-1], sep2);
4717 ret++;
4718 }
4719 }
4720 }
4721 /* time part */
4722 if (fmt_flags & (FDTF_LONGTIME | FDTF_SHORTTIME))
4723 {
4724 DWORD time = fmt_flags & FDTF_LONGTIME ? 0 : TIME_NOSECONDS;
4725
4726 if (ret) ret--;
4727 ret += GetTimeFormatW(LOCALE_USER_DEFAULT, time, &st, NULL, &buf[ret], size - ret);
4728 }
4729
4730 return ret;
4731
4732 #undef SHFORMATDT_UNSUPPORTED_FLAGS
4733 }
4734
4735 /***********************************************************************
4736 * SHFormatDateTimeA [SHLWAPI.353]
4737 *
4738 * See SHFormatDateTimeW.
4739 *
4740 */
4741 INT WINAPI SHFormatDateTimeA(const FILETIME UNALIGNED *fileTime, DWORD *flags,
4742 LPSTR buf, UINT size)
4743 {
4744 WCHAR *bufW;
4745 INT retval;
4746
4747 if (!buf || !size)
4748 return 0;
4749
4750 bufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
4751 retval = SHFormatDateTimeW(fileTime, flags, bufW, size);
4752
4753 if (retval != 0)
4754 WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, size, NULL, NULL);
4755
4756 HeapFree(GetProcessHeap(), 0, bufW);
4757 return retval;
4758 }
4759
4760 /***********************************************************************
4761 * ZoneCheckUrlExW [SHLWAPI.231]
4762 *
4763 * Checks the details of the security zone for the supplied site. (?)
4764 *
4765 * PARAMS
4766 *
4767 * szURL [I] Pointer to the URL to check
4768 *
4769 * Other parameters currently unknown.
4770 *
4771 * RETURNS
4772 * unknown
4773 */
4774
4775 INT WINAPI ZoneCheckUrlExW(LPWSTR szURL, PVOID pUnknown, DWORD dwUnknown2,
4776 DWORD dwUnknown3, DWORD dwUnknown4, DWORD dwUnknown5, DWORD dwUnknown6,
4777 DWORD dwUnknown7)
4778 {
4779 FIXME("(%s,%p,%x,%x,%x,%x,%x,%x) STUB\n", debugstr_w(szURL), pUnknown, dwUnknown2,
4780 dwUnknown3, dwUnknown4, dwUnknown5, dwUnknown6, dwUnknown7);
4781
4782 return 0;
4783 }
4784
4785 /***********************************************************************
4786 * SHVerbExistsNA [SHLWAPI.196]
4787 *
4788 *
4789 * PARAMS
4790 *
4791 * verb [I] a string, often appears to be an extension.
4792 *
4793 * Other parameters currently unknown.
4794 *
4795 * RETURNS
4796 * unknown
4797 */
4798 INT WINAPI SHVerbExistsNA(LPSTR verb, PVOID pUnknown, PVOID pUnknown2, DWORD dwUnknown3)
4799 {
4800 FIXME("(%s, %p, %p, %i) STUB\n",verb, pUnknown, pUnknown2, dwUnknown3);
4801 return 0;
4802 }
4803
4804 /*************************************************************************
4805 * @ [SHLWAPI.538]
4806 *
4807 * Undocumented: Implementation guessed at via Name and behavior
4808 *
4809 * PARAMS
4810 * lpUnknown [I] Object to get an IServiceProvider interface from
4811 * riid [I] Function requested for QueryService call
4812 * lppOut [O] Destination for the service interface pointer
4813 *
4814 * RETURNS
4815 * Success: S_OK. lppOut contains an object providing the requested service
4816 * Failure: An HRESULT error code
4817 *
4818 * NOTES
4819 * lpUnknown is expected to support the IServiceProvider interface.
4820 */
4821 HRESULT WINAPI IUnknown_QueryServiceForWebBrowserApp(IUnknown* lpUnknown,
4822 REFGUID riid, LPVOID *lppOut)
4823 {
4824 FIXME("%p %s %p semi-STUB\n", lpUnknown, debugstr_guid(riid), lppOut);
4825 return IUnknown_QueryService(lpUnknown,&IID_IWebBrowserApp,riid,lppOut);
4826 }
4827
4828 /**************************************************************************
4829 * SHPropertyBag_ReadLONG (SHLWAPI.496)
4830 *
4831 * This function asks a property bag to read a named property as a LONG.
4832 *
4833 * PARAMS
4834 * ppb: a IPropertyBag interface
4835 * pszPropName: Unicode string that names the property
4836 * pValue: address to receive the property value as a 32-bit signed integer
4837 *
4838 * RETURNS
4839 * 0 for Success
4840 */
4841 BOOL WINAPI SHPropertyBag_ReadLONG(IPropertyBag *ppb, LPCWSTR pszPropName, LPLONG pValue)
4842 {
4843 VARIANT var;
4844 HRESULT hr;
4845 TRACE("%p %s %p\n", ppb,debugstr_w(pszPropName),pValue);
4846 if (!pszPropName || !ppb || !pValue)
4847 return E_INVALIDARG;
4848 V_VT(&var) = VT_I4;
4849 hr = IPropertyBag_Read(ppb, pszPropName, &var, NULL);
4850 if (SUCCEEDED(hr))
4851 {
4852 if (V_VT(&var) == VT_I4)
4853 *pValue = V_I4(&var);
4854 else
4855 hr = DISP_E_BADVARTYPE;
4856 }
4857 return hr;
4858 }
4859
4860 /* return flags for SHGetObjectCompatFlags, names derived from registry value names */
4861 #define OBJCOMPAT_OTNEEDSSFCACHE 0x00000001
4862 #define OBJCOMPAT_NO_WEBVIEW 0x00000002
4863 #define OBJCOMPAT_UNBINDABLE 0x00000004
4864 #define OBJCOMPAT_PINDLL 0x00000008
4865 #define OBJCOMPAT_NEEDSFILESYSANCESTOR 0x00000010
4866 #define OBJCOMPAT_NOTAFILESYSTEM 0x00000020
4867 #define OBJCOMPAT_CTXMENU_NOVERBS 0x00000040
4868 #define OBJCOMPAT_CTXMENU_LIMITEDQI 0x00000080
4869 #define OBJCOMPAT_COCREATESHELLFOLDERONLY 0x00000100
4870 #define OBJCOMPAT_NEEDSSTORAGEANCESTOR 0x00000200
4871 #define OBJCOMPAT_NOLEGACYWEBVIEW 0x00000400
4872 #define OBJCOMPAT_CTXMENU_XPQCMFLAGS 0x00001000
4873 #define OBJCOMPAT_NOIPROPERTYSTORE 0x00002000
4874
4875 /* a search table for compatibility flags */
4876 struct objcompat_entry {
4877 const WCHAR name[30];
4878 DWORD value;
4879 };
4880
4881 /* expected to be sorted by name */
4882 static const struct objcompat_entry objcompat_table[] = {
4883 { {'C','O','C','R','E','A','T','E','S','H','E','L','L','F','O','L','D','E','R','O','N','L','Y',0},
4884 OBJCOMPAT_COCREATESHELLFOLDERONLY },
4885 { {'C','T','X','M','E','N','U','_','L','I','M','I','T','E','D','Q','I',0},
4886 OBJCOMPAT_CTXMENU_LIMITEDQI },
4887 { {'C','T','X','M','E','N','U','_','N','O','V','E','R','B','S',0},
4888 OBJCOMPAT_CTXMENU_LIMITEDQI },
4889 { {'C','T','X','M','E','N','U','_','X','P','Q','C','M','F','L','A','G','S',0},
4890 OBJCOMPAT_CTXMENU_XPQCMFLAGS },
4891 { {'N','E','E','D','S','F','I','L','E','S','Y','S','A','N','C','E','S','T','O','R',0},
4892 OBJCOMPAT_NEEDSFILESYSANCESTOR },
4893 { {'N','E','E','D','S','S','T','O','R','A','G','E','A','N','C','E','S','T','O','R',0},
4894 OBJCOMPAT_NEEDSSTORAGEANCESTOR },
4895 { {'N','O','I','P','R','O','P','E','R','T','Y','S','T','O','R','E',0},
4896 OBJCOMPAT_NOIPROPERTYSTORE },
4897 { {'N','O','L','E','G','A','C','Y','W','E','B','V','I','E','W',0},
4898 OBJCOMPAT_NOLEGACYWEBVIEW },
4899 { {'N','O','T','A','F','I','L','E','S','Y','S','T','E','M',0},
4900 OBJCOMPAT_NOTAFILESYSTEM },
4901 { {'N','O','_','W','E','B','V','I','E','W',0},
4902 OBJCOMPAT_NO_WEBVIEW },
4903 { {'O','T','N','E','E','D','S','S','F','C','A','C','H','E',0},
4904 OBJCOMPAT_OTNEEDSSFCACHE },
4905 { {'P','I','N','D','L','L',0},
4906 OBJCOMPAT_PINDLL },
4907 { {'U','N','B','I','N','D','A','B','L','E',0},
4908 OBJCOMPAT_UNBINDABLE }
4909 };
4910
4911 /**************************************************************************
4912 * SHGetObjectCompatFlags (SHLWAPI.476)
4913 *
4914 * Function returns an integer representation of compatibility flags stored
4915 * in registry for CLSID under ShellCompatibility subkey.
4916 *
4917 * PARAMS
4918 * pUnk: pointer to object IUnknown interface, idetifies CLSID
4919 * clsid: pointer to CLSID to retrieve data for
4920 *
4921 * RETURNS
4922 * 0 on failure, flags set on success
4923 */
4924 DWORD WINAPI SHGetObjectCompatFlags(IUnknown *pUnk, const CLSID *clsid)
4925 {
4926 static const WCHAR compatpathW[] =
4927 {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
4928 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
4929 'S','h','e','l','l','C','o','m','p','a','t','i','b','i','l','i','t','y','\\',
4930 'O','b','j','e','c','t','s','\\','%','s',0};
4931 WCHAR strW[sizeof(compatpathW)/sizeof(WCHAR) + 38 /* { CLSID } */];
4932 DWORD ret, length = sizeof(strW)/sizeof(WCHAR);
4933 OLECHAR *clsid_str;
4934 HKEY key;
4935 INT i;
4936
4937 TRACE("%p %s\n", pUnk, debugstr_guid(clsid));
4938
4939 if (!pUnk && !clsid) return 0;
4940
4941 if (pUnk && !clsid)
4942 {
4943 FIXME("iface not handled\n");
4944 return 0;
4945 }
4946
4947 StringFromCLSID(clsid, &clsid_str);
4948 sprintfW(strW, compatpathW, clsid_str);
4949 CoTaskMemFree(clsid_str);
4950
4951 ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, strW, &key);
4952 if (ret != ERROR_SUCCESS) return 0;
4953
4954 /* now collect flag values */
4955 ret = 0;
4956 for (i = 0; RegEnumValueW(key, i, strW, &length, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; i++)
4957 {
4958 INT left, right, res, x;
4959
4960 /* search in table */
4961 left = 0;
4962 right = sizeof(objcompat_table) / sizeof(struct objcompat_entry) - 1;
4963
4964 while (right >= left) {
4965 x = (left + right) / 2;
4966 res = strcmpW(strW, objcompat_table[x].name);
4967 if (res == 0)
4968 {
4969 ret |= objcompat_table[x].value;
4970 break;
4971 }
4972 else if (res < 0)
4973 right = x - 1;
4974 else
4975 left = x + 1;
4976 }
4977
4978 length = sizeof(strW)/sizeof(WCHAR);
4979 }
4980
4981 return ret;
4982 }