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