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