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