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