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