112c124fbcb22dac10106a45678c90a64b9ef54f
[reactos.git] / reactos / lib / 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #define COM_NO_WINDOWS_H
24 #include "config.h"
25 #include "wine/port.h"
26
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #define COBJMACROS
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
34
35 #include "windef.h"
36 #include "winbase.h"
37 #include "winuser.h"
38 #include "winnls.h"
39 #include "objbase.h"
40 #include "docobj.h"
41 #include "exdisp.h"
42 #include "shlguid.h"
43 #include "wingdi.h"
44 #include "shlobj.h"
45 #include "shellapi.h"
46 #include "commdlg.h"
47 #include "wine/unicode.h"
48 #include "winreg.h"
49 #include "wine/debug.h"
50 #include "shlwapi.h"
51
52
53 WINE_DEFAULT_DEBUG_CHANNEL(shell);
54
55 /* Get a function pointer from a DLL handle */
56 #define GET_FUNC(func, module, name, fail) \
57 do { \
58 if (!func) { \
59 if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
60 func = (fn##func)GetProcAddress(SHLWAPI_h##module, name); \
61 if (!func) return fail; \
62 } \
63 } while (0)
64
65 /* DLL handles for late bound calls */
66 extern HINSTANCE shlwapi_hInstance;
67 extern HMODULE SHLWAPI_hshell32;
68 extern HMODULE SHLWAPI_hwinmm;
69 extern HMODULE SHLWAPI_hcomdlg32;
70 extern HMODULE SHLWAPI_hcomctl32;
71 extern HMODULE SHLWAPI_hmpr;
72 extern HMODULE SHLWAPI_hurlmon;
73 extern HMODULE SHLWAPI_hversion;
74
75 extern DWORD SHLWAPI_ThreadRef_index;
76
77 /* following is GUID for IObjectWithSite::SetSite -- see _174 */
78 static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
79 /* following is GUID for IPersistMoniker::GetClassID -- see _174 */
80 static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
81
82 /* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
83 typedef LPITEMIDLIST (WINAPI *fnpSHBrowseForFolderW)(LPBROWSEINFOW);
84 static fnpSHBrowseForFolderW pSHBrowseForFolderW;
85 typedef BOOL (WINAPI *fnpPlaySoundW)(LPCWSTR, HMODULE, DWORD);
86 static fnpPlaySoundW pPlaySoundW;
87 typedef DWORD (WINAPI *fnpSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);
88 static fnpSHGetFileInfoW pSHGetFileInfoW;
89 typedef UINT (WINAPI *fnpDragQueryFileW)(HDROP, UINT, LPWSTR, UINT);
90 static fnpDragQueryFileW pDragQueryFileW;
91 typedef BOOL (WINAPI *fnpSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR);
92 static fnpSHGetPathFromIDListW pSHGetPathFromIDListW;
93 typedef BOOL (WINAPI *fnpShellExecuteExW)(LPSHELLEXECUTEINFOW);
94 static fnpShellExecuteExW pShellExecuteExW;
95 typedef HICON (WINAPI *fnpSHFileOperationW)(LPSHFILEOPSTRUCTW);
96 static fnpSHFileOperationW pSHFileOperationW;
97 typedef UINT (WINAPI *fnpExtractIconExW)(LPCWSTR, INT,HICON *,HICON *, UINT);
98 static fnpExtractIconExW pExtractIconExW;
99 typedef BOOL (WINAPI *fnpSHGetNewLinkInfoW)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT);
100 static fnpSHGetNewLinkInfoW pSHGetNewLinkInfoW;
101 typedef HRESULT (WINAPI *fnpSHDefExtractIconW)(LPCWSTR, int, UINT, HICON*, HICON*, UINT);
102 static fnpSHDefExtractIconW pSHDefExtractIconW;
103 typedef HICON (WINAPI *fnpExtractIconW)(HINSTANCE, LPCWSTR, UINT);
104 static fnpExtractIconW pExtractIconW;
105 typedef BOOL (WINAPI *fnpGetSaveFileNameW)(LPOPENFILENAMEW);
106 static fnpGetSaveFileNameW pGetSaveFileNameW;
107 typedef DWORD (WINAPI *fnpWNetRestoreConnectionW)(HWND, LPWSTR);
108 static fnpWNetRestoreConnectionW pWNetRestoreConnectionW;
109 typedef DWORD (WINAPI *fnpWNetGetLastErrorW)(LPDWORD, LPWSTR, DWORD, LPWSTR, DWORD);
110 static fnpWNetGetLastErrorW pWNetGetLastErrorW;
111 typedef BOOL (WINAPI *fnpPageSetupDlgW)(LPPAGESETUPDLGW);
112 static fnpPageSetupDlgW pPageSetupDlgW;
113 typedef BOOL (WINAPI *fnpPrintDlgW)(LPPRINTDLGW);
114 static fnpPrintDlgW pPrintDlgW;
115 typedef BOOL (WINAPI *fnpGetOpenFileNameW)(LPOPENFILENAMEW);
116 static fnpGetOpenFileNameW pGetOpenFileNameW;
117 typedef DWORD (WINAPI *fnpGetFileVersionInfoSizeW)(LPCWSTR,LPDWORD);
118 static fnpGetFileVersionInfoSizeW pGetFileVersionInfoSizeW;
119 typedef BOOL (WINAPI *fnpGetFileVersionInfoW)(LPCWSTR,DWORD,DWORD,LPVOID);
120 static fnpGetFileVersionInfoW pGetFileVersionInfoW;
121 typedef WORD (WINAPI *fnpVerQueryValueW)(LPVOID,LPCWSTR,LPVOID*,UINT*);
122 static fnpVerQueryValueW pVerQueryValueW;
123 typedef BOOL (WINAPI *fnpCOMCTL32_417)(HDC,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
124 static fnpCOMCTL32_417 pCOMCTL32_417;
125 typedef HRESULT (WINAPI *fnpDllGetVersion)(DLLVERSIONINFO*);
126 static fnpDllGetVersion pDllGetVersion;
127 typedef HRESULT (WINAPI *fnpCreateFormatEnumerator)(UINT,FORMATETC*,IEnumFORMATETC**);
128 static fnpCreateFormatEnumerator pCreateFormatEnumerator;
129 typedef HRESULT (WINAPI *fnpRegisterFormatEnumerator)(LPBC,IEnumFORMATETC*,DWORD);
130 static fnpRegisterFormatEnumerator pRegisterFormatEnumerator;
131
132 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
133 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
134 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR,CLSID*);
135 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
136
137 /*
138 NOTES: Most functions exported by ordinal seem to be superflous.
139 The reason for these functions to be there is to provide a wrapper
140 for unicode functions to provide these functions on systems without
141 unicode functions eg. win95/win98. Since we have such functions we just
142 call these. If running Wine with native DLL's, some late bound calls may
143 fail. However, it is better to implement the functions in the forward DLL
144 and recommend the builtin rather than reimplementing the calls here!
145 */
146
147 /*************************************************************************
148 * SHLWAPI_DupSharedHandle
149 *
150 * Internal implemetation of SHLWAPI_11.
151 */
152 static
153 HANDLE WINAPI SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
154 DWORD dwSrcProcId, DWORD dwAccess,
155 DWORD dwOptions)
156 {
157 HANDLE hDst, hSrc;
158 DWORD dwMyProcId = GetCurrentProcessId();
159 HANDLE hRet = NULL;
160
161 TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", hShared, dwDstProcId, dwSrcProcId,
162 dwAccess, dwOptions);
163
164 /* Get dest process handle */
165 if (dwDstProcId == dwMyProcId)
166 hDst = GetCurrentProcess();
167 else
168 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
169
170 if (hDst)
171 {
172 /* Get src process handle */
173 if (dwSrcProcId == dwMyProcId)
174 hSrc = GetCurrentProcess();
175 else
176 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
177
178 if (hSrc)
179 {
180 /* Make handle available to dest process */
181 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
182 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
183 hRet = NULL;
184
185 if (dwSrcProcId != dwMyProcId)
186 CloseHandle(hSrc);
187 }
188
189 if (dwDstProcId != dwMyProcId)
190 CloseHandle(hDst);
191 }
192
193 TRACE("Returning handle %p\n", hRet);
194 return hRet;
195 }
196
197 /*************************************************************************
198 * @ [SHLWAPI.7]
199 *
200 * Create a block of sharable memory and initialise it with data.
201 *
202 * PARAMS
203 * lpvData [I] Pointer to data to write
204 * dwSize [I] Size of data
205 * dwProcId [I] ID of process owning data
206 *
207 * RETURNS
208 * Success: A shared memory handle
209 * Failure: NULL
210 *
211 * NOTES
212 * Ordinals 7-11 provide a set of calls to create shared memory between a
213 * group of processes. The shared memory is treated opaquely in that its size
214 * is not exposed to clients who map it. This is accomplished by storing
215 * the size of the map as the first DWORD of mapped data, and then offsetting
216 * the view pointer returned by this size.
217 *
218 */
219 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
220 {
221 HANDLE hMap;
222 LPVOID pMapped;
223 HANDLE hRet = NULL;
224
225 TRACE("(%p,%ld,%ld)\n", lpvData, dwSize, dwProcId);
226
227 /* Create file mapping of the correct length */
228 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
229 dwSize + sizeof(dwSize), NULL);
230 if (!hMap)
231 return hRet;
232
233 /* Get a view in our process address space */
234 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
235
236 if (pMapped)
237 {
238 /* Write size of data, followed by the data, to the view */
239 *((DWORD*)pMapped) = dwSize;
240 if (lpvData)
241 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
242
243 /* Release view. All further views mapped will be opaque */
244 UnmapViewOfFile(pMapped);
245 hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
246 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
247 DUPLICATE_SAME_ACCESS);
248 }
249
250 CloseHandle(hMap);
251 return hRet;
252 }
253
254 /*************************************************************************
255 * @ [SHLWAPI.8]
256 *
257 * Get a pointer to a block of shared memory from a shared memory handle.
258 *
259 * PARAMS
260 * hShared [I] Shared memory handle
261 * dwProcId [I] ID of process owning hShared
262 *
263 * RETURNS
264 * Success: A pointer to the shared memory
265 * Failure: NULL
266 *
267 */
268 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
269 {
270 HANDLE hDup;
271 LPVOID pMapped;
272
273 TRACE("(%p %ld)\n", hShared, dwProcId);
274
275 /* Get handle to shared memory for current process */
276 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
277 FILE_MAP_ALL_ACCESS, 0);
278 /* Get View */
279 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
280 CloseHandle(hDup);
281
282 if (pMapped)
283 return (char *) pMapped + sizeof(DWORD); /* Hide size */
284 return NULL;
285 }
286
287 /*************************************************************************
288 * @ [SHLWAPI.9]
289 *
290 * Release a pointer to a block of shared memory.
291 *
292 * PARAMS
293 * lpView [I] Shared memory pointer
294 *
295 * RETURNS
296 * Success: TRUE
297 * Failure: FALSE
298 *
299 */
300 BOOL WINAPI SHUnlockShared(LPVOID lpView)
301 {
302 TRACE("(%p)\n", lpView);
303 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
304 }
305
306 /*************************************************************************
307 * @ [SHLWAPI.10]
308 *
309 * Destroy a block of sharable memory.
310 *
311 * PARAMS
312 * hShared [I] Shared memory handle
313 * dwProcId [I] ID of process owning hShared
314 *
315 * RETURNS
316 * Success: TRUE
317 * Failure: FALSE
318 *
319 */
320 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
321 {
322 HANDLE hClose;
323
324 TRACE("(%p %ld)\n", hShared, dwProcId);
325
326 /* Get a copy of the handle for our process, closing the source handle */
327 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
328 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
329 /* Close local copy */
330 return CloseHandle(hClose);
331 }
332
333 /*************************************************************************
334 * @ [SHLWAPI.11]
335 *
336 * Copy a sharable memory handle from one process to another.
337 *
338 * PARAMS
339 * hShared [I] Shared memory handle to duplicate
340 * dwDstProcId [I] ID of the process wanting the duplicated handle
341 * dwSrcProcId [I] ID of the process owning hShared
342 * dwAccess [I] Desired DuplicateHandle() access
343 * dwOptions [I] Desired DuplicateHandle() options
344 *
345 * RETURNS
346 * Success: A handle suitable for use by the dwDstProcId process.
347 * Failure: A NULL handle.
348 *
349 */
350 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
351 DWORD dwAccess, DWORD dwOptions)
352 {
353 HANDLE hRet;
354
355 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
356 dwAccess, dwOptions);
357 return hRet;
358 }
359
360 /*************************************************************************
361 * @ [SHLWAPI.13]
362 *
363 * Create and register a clipboard enumerator for a web browser.
364 *
365 * PARAMS
366 * lpBC [I] Binding context
367 * lpUnknown [I] An object exposing the IWebBrowserApp interface
368 *
369 * RETURNS
370 * Success: S_OK.
371 * Failure: An HRESULT error code.
372 *
373 * NOTES
374 * The enumerator is stored as a property of the web browser. If it does not
375 * yet exist, it is created and set before being registered.
376 */
377 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
378 {
379 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
380 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
381 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
382 IEnumFORMATETC* pIEnumFormatEtc = NULL;
383 VARIANTARG var;
384 HRESULT hRet;
385 IWebBrowserApp* pBrowser = NULL;
386
387 TRACE("(%p, %p)\n", lpBC, lpUnknown);
388
389 /* Get An IWebBrowserApp interface from lpUnknown */
390 hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
391 if (FAILED(hRet) || !pBrowser)
392 return E_NOINTERFACE;
393
394 V_VT(&var) = VT_EMPTY;
395
396 /* The property we get is the browsers clipboard enumerator */
397 hRet = IWebBrowserApp_GetProperty(pBrowser, (BSTR)szProperty, &var);
398 if (FAILED(hRet))
399 return hRet;
400
401 if (V_VT(&var) == VT_EMPTY)
402 {
403 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
404 char szKeyBuff[128], szValueBuff[128];
405 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
406 FORMATETC* formatList, *format;
407 HKEY hDocs;
408
409 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
410
411 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
412 "Version\\Internet Settings\\Accepted Documents", &hDocs))
413 return E_FAIL;
414
415 /* Get count of values in key */
416 while (!dwRet)
417 {
418 dwKeySize = sizeof(szKeyBuff);
419 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
420 dwCount++;
421 }
422
423 dwNumValues = dwCount;
424
425 /* Note: dwCount = number of items + 1; The extra item is the end node */
426 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
427 if (!formatList)
428 return E_OUTOFMEMORY;
429
430 if (dwNumValues > 1)
431 {
432 dwRet = 0;
433 dwCount = 0;
434
435 dwNumValues--;
436
437 /* Register clipboard formats for the values and populate format list */
438 while(!dwRet && dwCount < dwNumValues)
439 {
440 dwKeySize = sizeof(szKeyBuff);
441 dwValueSize = sizeof(szValueBuff);
442 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
443 (PBYTE)szValueBuff, &dwValueSize);
444 if (!dwRet)
445 return E_FAIL;
446
447 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
448 format->ptd = NULL;
449 format->dwAspect = 1;
450 format->lindex = 4;
451 format->tymed = -1;
452
453 format++;
454 dwCount++;
455 }
456 }
457
458 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
459 format->cfFormat = 0;
460 format->ptd = NULL;
461 format->dwAspect = 1;
462 format->lindex = 4;
463 format->tymed = -1;
464
465 /* Create a clipboard enumerator */
466 GET_FUNC(pCreateFormatEnumerator, urlmon, "CreateFormatEnumerator", E_FAIL);
467 hRet = pCreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
468
469 if (FAILED(hRet) || !pIEnumFormatEtc)
470 return hRet;
471
472 /* Set our enumerator as the browsers property */
473 V_VT(&var) = VT_UNKNOWN;
474 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
475
476 hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
477 if (FAILED(hRet))
478 {
479 IEnumFORMATETC_Release(pIEnumFormatEtc);
480 goto RegisterDefaultAcceptHeaders_Exit;
481 }
482 }
483
484 if (V_VT(&var) == VT_UNKNOWN)
485 {
486 /* Our variant is holding the clipboard enumerator */
487 IUnknown* pIUnknown = V_UNKNOWN(&var);
488 IEnumFORMATETC* pClone = NULL;
489
490 TRACE("Retrieved IEnumFORMATETC property\n");
491
492 /* Get an IEnumFormatEtc interface from the variants value */
493 pIEnumFormatEtc = NULL;
494 hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
495 (PVOID)&pIEnumFormatEtc);
496 if (!hRet && pIEnumFormatEtc)
497 {
498 /* Clone and register the enumerator */
499 hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
500 if (!hRet && pClone)
501 {
502 GET_FUNC(pRegisterFormatEnumerator, urlmon, "RegisterFormatEnumerator", E_FAIL);
503 pRegisterFormatEnumerator(lpBC, pClone, 0);
504
505 IEnumFORMATETC_Release(pClone);
506 }
507
508 /* Release the IEnumFormatEtc interface */
509 IEnumFORMATETC_Release(pIUnknown);
510 }
511 IUnknown_Release(V_UNKNOWN(&var));
512 }
513
514 RegisterDefaultAcceptHeaders_Exit:
515 IWebBrowserApp_Release(pBrowser);
516 return hRet;
517 }
518
519 /*************************************************************************
520 * @ [SHLWAPI.15]
521 *
522 * Get Explorers "AcceptLanguage" setting.
523 *
524 * PARAMS
525 * langbuf [O] Destination for language string
526 * buflen [I] Length of langbuf
527 * [0] Success: used length of langbuf
528 *
529 * RETURNS
530 * Success: S_OK. langbuf is set to the language string found.
531 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
532 * does not contain the setting.
533 * E_INVALIDARG, If the buffer is not big enough
534 */
535 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
536 {
537 static const WCHAR szkeyW[] = {
538 'S','o','f','t','w','a','r','e','\\',
539 'M','i','c','r','o','s','o','f','t','\\',
540 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
541 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
542 static const WCHAR valueW[] = {
543 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
544 static const WCHAR enusW[] = {'e','n','-','u','s',0};
545 DWORD mystrlen, mytype;
546 HKEY mykey;
547 HRESULT retval;
548 LCID mylcid;
549 WCHAR *mystr;
550
551 if(!langbuf || !buflen || !*buflen)
552 return E_FAIL;
553
554 mystrlen = (*buflen > 20) ? *buflen : 20 ;
555 mystr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * mystrlen);
556 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
557 if(RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &mystrlen)) {
558 /* Did not find value */
559 mylcid = GetUserDefaultLCID();
560 /* somehow the mylcid translates into "en-us"
561 * this is similar to "LOCALE_SABBREVLANGNAME"
562 * which could be gotten via GetLocaleInfo.
563 * The only problem is LOCALE_SABBREVLANGUAGE" is
564 * a 3 char string (first 2 are country code and third is
565 * letter for "sublanguage", which does not come close to
566 * "en-us"
567 */
568 lstrcpyW(mystr, enusW);
569 mystrlen = lstrlenW(mystr);
570 } else {
571 /* handle returned string */
572 FIXME("missing code\n");
573 }
574 memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
575
576 if(*buflen > strlenW(mystr)) {
577 *buflen = strlenW(mystr);
578 retval = S_OK;
579 } else {
580 *buflen = 0;
581 retval = E_INVALIDARG;
582 SetLastError(ERROR_INSUFFICIENT_BUFFER);
583 }
584 RegCloseKey(mykey);
585 HeapFree(GetProcessHeap(), 0, mystr);
586 return retval;
587 }
588
589 /*************************************************************************
590 * @ [SHLWAPI.14]
591 *
592 * Ascii version of GetAcceptLanguagesW.
593 */
594 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
595 {
596 WCHAR *langbufW;
597 DWORD buflenW, convlen;
598 HRESULT retval;
599
600 if(!langbuf || !buflen || !*buflen) return E_FAIL;
601
602 buflenW = *buflen;
603 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
604 retval = GetAcceptLanguagesW(langbufW, &buflenW);
605
606 /* FIXME: this is wrong, the string may not be null-terminated */
607 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf,
608 *buflen, NULL, NULL);
609 *buflen = buflenW ? convlen : 0;
610
611 HeapFree(GetProcessHeap(), 0, langbufW);
612 return retval;
613 }
614
615 /*************************************************************************
616 * @ [SHLWAPI.23]
617 *
618 * Convert a GUID to a string.
619 *
620 * PARAMS
621 * guid [I] GUID to convert
622 * lpszDest [O] Destination for string
623 * cchMax [I] Length of output buffer
624 *
625 * RETURNS
626 * The length of the string created.
627 */
628 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
629 {
630 char xguid[40];
631 INT iLen;
632
633 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
634
635 sprintf(xguid, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
636 guid->Data1, guid->Data2, guid->Data3,
637 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
638 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
639
640 iLen = strlen(xguid) + 1;
641
642 if (iLen > cchMax)
643 return 0;
644 memcpy(lpszDest, xguid, iLen);
645 return iLen;
646 }
647
648 /*************************************************************************
649 * @ [SHLWAPI.24]
650 *
651 * Convert a GUID to a string.
652 *
653 * PARAMS
654 * guid [I] GUID to convert
655 * str [O] Destination for string
656 * cmax [I] Length of output buffer
657 *
658 * RETURNS
659 * The length of the string created.
660 */
661 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
662 {
663 WCHAR xguid[40];
664 INT iLen;
665 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
666 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
667 'X','%','0','2','X','%','0','2','X','}',0};
668
669 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
670
671 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
672 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
673 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
674
675 iLen = strlenW(xguid) + 1;
676
677 if (iLen > cchMax)
678 return 0;
679 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
680 return iLen;
681 }
682
683 /*************************************************************************
684 * @ [SHLWAPI.29]
685 *
686 * Determine if a Unicode character is a space.
687 *
688 * PARAMS
689 * wc [I] Character to check.
690 *
691 * RETURNS
692 * TRUE, if wc is a space,
693 * FALSE otherwise.
694 */
695 BOOL WINAPI IsCharSpaceW(WCHAR wc)
696 {
697 WORD CharType;
698
699 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
700 }
701
702 /*************************************************************************
703 * @ [SHLWAPI.30]
704 *
705 * Determine if a Unicode character is a blank.
706 *
707 * PARAMS
708 * wc [I] Character to check.
709 *
710 * RETURNS
711 * TRUE, if wc is a blank,
712 * FALSE otherwise.
713 *
714 */
715 BOOL WINAPI IsCharBlankW(WCHAR wc)
716 {
717 WORD CharType;
718
719 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
720 }
721
722 /*************************************************************************
723 * @ [SHLWAPI.31]
724 *
725 * Determine if a Unicode character is punctuation.
726 *
727 * PARAMS
728 * wc [I] Character to check.
729 *
730 * RETURNS
731 * TRUE, if wc is punctuation,
732 * FALSE otherwise.
733 */
734 BOOL WINAPI IsCharPunctW(WCHAR wc)
735 {
736 WORD CharType;
737
738 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
739 }
740
741 /*************************************************************************
742 * @ [SHLWAPI.32]
743 *
744 * Determine if a Unicode character is a control character.
745 *
746 * PARAMS
747 * wc [I] Character to check.
748 *
749 * RETURNS
750 * TRUE, if wc is a control character,
751 * FALSE otherwise.
752 */
753 BOOL WINAPI IsCharCntrlW(WCHAR wc)
754 {
755 WORD CharType;
756
757 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
758 }
759
760 /*************************************************************************
761 * @ [SHLWAPI.33]
762 *
763 * Determine if a Unicode character is a digit.
764 *
765 * PARAMS
766 * wc [I] Character to check.
767 *
768 * RETURNS
769 * TRUE, if wc is a digit,
770 * FALSE otherwise.
771 */
772 BOOL WINAPI IsCharDigitW(WCHAR wc)
773 {
774 WORD CharType;
775
776 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
777 }
778
779 /*************************************************************************
780 * @ [SHLWAPI.34]
781 *
782 * Determine if a Unicode character is a hex digit.
783 *
784 * PARAMS
785 * wc [I] Character to check.
786 *
787 * RETURNS
788 * TRUE, if wc is a hex digit,
789 * FALSE otherwise.
790 */
791 BOOL WINAPI IsCharXDigitW(WCHAR wc)
792 {
793 WORD CharType;
794
795 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
796 }
797
798 /*************************************************************************
799 * @ [SHLWAPI.35]
800 *
801 */
802 BOOL WINAPI GetStringType3ExW(LPWSTR lpszStr, DWORD dwLen, LPVOID p3)
803 {
804 FIXME("(%s,0x%08lx,%p): stub\n", debugstr_w(lpszStr), dwLen, p3);
805 return TRUE;
806 }
807
808 /*************************************************************************
809 * @ [SHLWAPI.36]
810 *
811 * Insert a bitmap menu item at the bottom of a menu.
812 *
813 * PARAMS
814 * hMenu [I] Menu to insert into
815 * flags [I] Flags for insertion
816 * id [I] Menu ID of the item
817 * str [I] Menu text for the item
818 *
819 * RETURNS
820 * Success: TRUE, the item is inserted into the menu
821 * Failure: FALSE, if any parameter is invalid
822 */
823 BOOL WINAPI AppendMenuWrapW(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
824 {
825 TRACE("(%p,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));
826 return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);
827 }
828
829 /*************************************************************************
830 * @ [SHLWAPI.74]
831 *
832 * Get the text from a given dialog item.
833 *
834 * PARAMS
835 * hWnd [I] Handle of dialog
836 * nItem [I] Index of item
837 * lpsDest [O] Buffer for receiving window text
838 * nDestLen [I] Length of buffer.
839 *
840 * RETURNS
841 * Success: The length of the returned text.
842 * Failure: 0.
843 */
844 INT WINAPI GetDlgItemTextWrapW(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
845 {
846 HWND hItem = GetDlgItem(hWnd, nItem);
847
848 if (hItem)
849 return GetWindowTextW(hItem, lpsDest, nDestLen);
850 if (nDestLen)
851 *lpsDest = (WCHAR)'\0';
852 return 0;
853 }
854
855 /*************************************************************************
856 * @ [SHLWAPI.138]
857 *
858 * Set the text of a given dialog item.
859 *
860 * PARAMS
861 * hWnd [I] Handle of dialog
862 * iItem [I] Index of item
863 * lpszText [O] Text to set
864 *
865 * RETURNS
866 * Success: TRUE. The text of the dialog is set to lpszText.
867 * Failure: FALSE, Otherwise.
868 */
869 BOOL WINAPI SetDlgItemTextWrapW(HWND hWnd, INT iItem, LPCWSTR lpszText)
870 {
871 HWND hWndItem = GetDlgItem(hWnd, iItem);
872 if (hWndItem)
873 return SetWindowTextW(hWndItem, lpszText);
874 return FALSE;
875 }
876
877 /*************************************************************************
878 * @ [SHLWAPI.151]
879 *
880 * Compare two Ascii strings up to a given length.
881 *
882 * PARAMS
883 * lpszSrc [I] Source string
884 * lpszCmp [I] String to compare to lpszSrc
885 * len [I] Maximum length
886 *
887 * RETURNS
888 * A number greater than, less than or equal to 0 depending on whether
889 * lpszSrc is greater than, less than or equal to lpszCmp.
890 */
891 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
892 {
893 return strncmp(lpszSrc, lpszCmp, len);
894 }
895
896 /*************************************************************************
897 * @ [SHLWAPI.152]
898 *
899 * Unicode version of StrCmpNCA.
900 */
901 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
902 {
903 return strncmpW(lpszSrc, lpszCmp, len);
904 }
905
906 /*************************************************************************
907 * @ [SHLWAPI.153]
908 *
909 * Compare two Ascii strings up to a given length, ignoring case.
910 *
911 * PARAMS
912 * lpszSrc [I] Source string
913 * lpszCmp [I] String to compare to lpszSrc
914 * len [I] Maximum length
915 *
916 * RETURNS
917 * A number greater than, less than or equal to 0 depending on whether
918 * lpszSrc is greater than, less than or equal to lpszCmp.
919 */
920 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
921 {
922 return strncasecmp(lpszSrc, lpszCmp, len);
923 }
924
925 /*************************************************************************
926 * @ [SHLWAPI.154]
927 *
928 * Unicode version of StrCmpNICA.
929 */
930 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
931 {
932 return strncmpiW(lpszSrc, lpszCmp, len);
933 }
934
935 /*************************************************************************
936 * @ [SHLWAPI.155]
937 *
938 * Compare two Ascii strings.
939 *
940 * PARAMS
941 * lpszSrc [I] Source string
942 * lpszCmp [I] String to compare to lpszSrc
943 *
944 * RETURNS
945 * A number greater than, less than or equal to 0 depending on whether
946 * lpszSrc is greater than, less than or equal to lpszCmp.
947 */
948 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
949 {
950 return strcmp(lpszSrc, lpszCmp);
951 }
952
953 /*************************************************************************
954 * @ [SHLWAPI.156]
955 *
956 * Unicode version of StrCmpCA.
957 */
958 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
959 {
960 return strcmpW(lpszSrc, lpszCmp);
961 }
962
963 /*************************************************************************
964 * @ [SHLWAPI.157]
965 *
966 * Compare two Ascii strings, ignoring case.
967 *
968 * PARAMS
969 * lpszSrc [I] Source string
970 * lpszCmp [I] String to compare to lpszSrc
971 *
972 * RETURNS
973 * A number greater than, less than or equal to 0 depending on whether
974 * lpszSrc is greater than, less than or equal to lpszCmp.
975 */
976 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
977 {
978 return strcasecmp(lpszSrc, lpszCmp);
979 }
980
981 /*************************************************************************
982 * @ [SHLWAPI.158]
983 *
984 * Unicode version of StrCmpICA.
985 */
986 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
987 {
988 return strcmpiW(lpszSrc, lpszCmp);
989 }
990
991 /*************************************************************************
992 * @ [SHLWAPI.160]
993 *
994 * Get an identification string for the OS and explorer.
995 *
996 * PARAMS
997 * lpszDest [O] Destination for Id string
998 * dwDestLen [I] Length of lpszDest
999 *
1000 * RETURNS
1001 * TRUE, If the string was created successfully
1002 * FALSE, Otherwise
1003 */
1004 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
1005 {
1006 WCHAR buff[2084];
1007
1008 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
1009
1010 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
1011 {
1012 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
1013 return TRUE;
1014 }
1015 return FALSE;
1016 }
1017
1018 /*************************************************************************
1019 * @ [SHLWAPI.161]
1020 *
1021 * Unicode version of SHAboutInfoA.
1022 */
1023 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
1024 {
1025 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
1026 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
1027 ' ','E','x','p','l','o','r','e','r','\0' };
1028 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
1029 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
1030 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
1031 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
1032 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1033 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
1034 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
1035 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
1036 ' ','E','x','p','l','o','r','e','r','\\',
1037 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
1038 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
1039 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
1040 'V','e','r','s','i','o','n','\0' };
1041 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
1042 'O','w','n','e','r','\0' };
1043 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
1044 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
1045 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
1046 static const WCHAR szUpdate[] = { 'I','E','A','K',
1047 'U','p','d','a','t','e','U','r','l','\0' };
1048 static const WCHAR szHelp[] = { 'I','E','A','K',
1049 'H','e','l','p','S','t','r','i','n','g','\0' };
1050 WCHAR buff[2084];
1051 HKEY hReg;
1052 DWORD dwType, dwLen;
1053
1054 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
1055
1056 if (!lpszDest)
1057 return FALSE;
1058
1059 *lpszDest = '\0';
1060
1061 /* Try the NT key first, followed by 95/98 key */
1062 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
1063 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
1064 return FALSE;
1065
1066 /* OS Version */
1067 buff[0] = '\0';
1068 dwLen = 30;
1069 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
1070 {
1071 DWORD dwStrLen = strlenW(buff);
1072 dwLen = 30 - dwStrLen;
1073 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
1074 szCustomized, &dwType, buff+dwStrLen, &dwLen);
1075 }
1076 StrCatBuffW(lpszDest, buff, dwDestLen);
1077
1078 /* ~Registered Owner */
1079 buff[0] = '~';
1080 dwLen = 256;
1081 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
1082 buff[1] = '\0';
1083 StrCatBuffW(lpszDest, buff, dwDestLen);
1084
1085 /* ~Registered Organization */
1086 dwLen = 256;
1087 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
1088 buff[1] = '\0';
1089 StrCatBuffW(lpszDest, buff, dwDestLen);
1090
1091 /* FIXME: Not sure where this number comes from */
1092 buff[0] = '~';
1093 buff[1] = '0';
1094 buff[2] = '\0';
1095 StrCatBuffW(lpszDest, buff, dwDestLen);
1096
1097 /* ~Product Id */
1098 dwLen = 256;
1099 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
1100 buff[1] = '\0';
1101 StrCatBuffW(lpszDest, buff, dwDestLen);
1102
1103 /* ~IE Update Url */
1104 dwLen = 2048;
1105 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
1106 buff[1] = '\0';
1107 StrCatBuffW(lpszDest, buff, dwDestLen);
1108
1109 /* ~IE Help String */
1110 dwLen = 256;
1111 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
1112 buff[1] = '\0';
1113 StrCatBuffW(lpszDest, buff, dwDestLen);
1114
1115 RegCloseKey(hReg);
1116 return TRUE;
1117 }
1118
1119 /*************************************************************************
1120 * @ [SHLWAPI.163]
1121 *
1122 * Call IOleCommandTarget_QueryStatus() on an object.
1123 *
1124 * PARAMS
1125 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1126 * pguidCmdGroup [I] GUID for the command group
1127 * cCmds [I]
1128 * prgCmds [O] Commands
1129 * pCmdText [O] Command text
1130 *
1131 * RETURNS
1132 * Success: S_OK.
1133 * Failure: E_FAIL, if lpUnknown is NULL.
1134 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1135 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1136 */
1137 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1138 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1139 {
1140 HRESULT hRet = E_FAIL;
1141
1142 TRACE("(%p,%p,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1143
1144 if (lpUnknown)
1145 {
1146 IOleCommandTarget* lpOle;
1147
1148 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1149 (void**)&lpOle);
1150
1151 if (SUCCEEDED(hRet) && lpOle)
1152 {
1153 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1154 prgCmds, pCmdText);
1155 IOleCommandTarget_Release(lpOle);
1156 }
1157 }
1158 return hRet;
1159 }
1160
1161 /*************************************************************************
1162 * @ [SHLWAPI.164]
1163 *
1164 * Call IOleCommandTarget_Exec() on an object.
1165 *
1166 * PARAMS
1167 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1168 * pguidCmdGroup [I] GUID for the command group
1169 *
1170 * RETURNS
1171 * Success: S_OK.
1172 * Failure: E_FAIL, if lpUnknown is NULL.
1173 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1174 * Otherwise, an error code from IOleCommandTarget_Exec().
1175 */
1176 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1177 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1178 VARIANT* pvaOut)
1179 {
1180 HRESULT hRet = E_FAIL;
1181
1182 TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1183 nCmdexecopt, pvaIn, pvaOut);
1184
1185 if (lpUnknown)
1186 {
1187 IOleCommandTarget* lpOle;
1188
1189 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1190 (void**)&lpOle);
1191 if (SUCCEEDED(hRet) && lpOle)
1192 {
1193 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1194 nCmdexecopt, pvaIn, pvaOut);
1195 IOleCommandTarget_Release(lpOle);
1196 }
1197 }
1198 return hRet;
1199 }
1200
1201 /*************************************************************************
1202 * @ [SHLWAPI.165]
1203 *
1204 * Retrieve, modify, and re-set a value from a window.
1205 *
1206 * PARAMS
1207 * hWnd [I] Window to get value from
1208 * offset [I] Offset of value
1209 * wMask [I] Mask for uiFlags
1210 * wFlags [I] Bits to set in window value
1211 *
1212 * RETURNS
1213 * The new value as it was set, or 0 if any parameter is invalid.
1214 *
1215 * NOTES
1216 * Any bits set in uiMask are cleared from the value, then any bits set in
1217 * uiFlags are set in the value.
1218 */
1219 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
1220 {
1221 LONG ret = GetWindowLongA(hwnd, offset);
1222 LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);
1223
1224 if (newFlags != ret)
1225 ret = SetWindowLongA(hwnd, offset, newFlags);
1226 return ret;
1227 }
1228
1229 /*************************************************************************
1230 * @ [SHLWAPI.167]
1231 *
1232 * Change a window's parent.
1233 *
1234 * PARAMS
1235 * hWnd [I] Window to change parent of
1236 * hWndParent [I] New parent window
1237 *
1238 * RETURNS
1239 * The old parent of hWnd.
1240 *
1241 * NOTES
1242 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1243 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1244 */
1245 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1246 {
1247 TRACE("%p, %p\n", hWnd, hWndParent);
1248
1249 if(GetParent(hWnd) == hWndParent)
1250 return 0;
1251
1252 if(hWndParent)
1253 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1254 else
1255 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1256
1257 return SetParent(hWnd, hWndParent);
1258 }
1259
1260 /*************************************************************************
1261 * @ [SHLWAPI.168]
1262 *
1263 * Locate and advise a connection point in an IConnectionPointContainer object.
1264 *
1265 * PARAMS
1266 * lpUnkSink [I] Sink for the connection point advise call
1267 * riid [I] REFIID of connection point to advise
1268 * bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first
1269 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1270 * lpCookie [O] Pointer to connection point cookie
1271 * lppCP [O] Destination for the IConnectionPoint found
1272 *
1273 * RETURNS
1274 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1275 * that was advised. The caller is responsable for releasing it.
1276 * Failure: E_FAIL, if any arguments are invalid.
1277 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1278 * Or an HRESULT error code if any call fails.
1279 */
1280 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
1281 IUnknown* lpUnknown, LPDWORD lpCookie,
1282 IConnectionPoint **lppCP)
1283 {
1284 HRESULT hRet;
1285 IConnectionPointContainer* lpContainer;
1286 IConnectionPoint *lpCP;
1287
1288 if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
1289 return E_FAIL;
1290
1291 if(lppCP)
1292 *lppCP = NULL;
1293
1294 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1295 (void**)&lpContainer);
1296 if (SUCCEEDED(hRet))
1297 {
1298 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1299
1300 if (SUCCEEDED(hRet))
1301 {
1302 if(!bAdviseOnly)
1303 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1304 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1305
1306 if (FAILED(hRet))
1307 *lpCookie = 0;
1308
1309 if (lppCP && SUCCEEDED(hRet))
1310 *lppCP = lpCP; /* Caller keeps the interface */
1311 else
1312 IConnectionPoint_Release(lpCP); /* Release it */
1313 }
1314
1315 IUnknown_Release(lpContainer);
1316 }
1317 return hRet;
1318 }
1319
1320 /*************************************************************************
1321 * @ [SHLWAPI.169]
1322 *
1323 * Release an interface.
1324 *
1325 * PARAMS
1326 * lpUnknown [I] Object to release
1327 *
1328 * RETURNS
1329 * Nothing.
1330 */
1331 DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1332 {
1333 IUnknown *temp;
1334
1335 TRACE("(%p)\n",lpUnknown);
1336
1337 if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1338 temp = *lpUnknown;
1339 *lpUnknown = NULL;
1340
1341 TRACE("doing Release\n");
1342
1343 return IUnknown_Release(temp);
1344 }
1345
1346 /*************************************************************************
1347 * @ [SHLWAPI.170]
1348 *
1349 * Skip '//' if present in a string.
1350 *
1351 * PARAMS
1352 * lpszSrc [I] String to check for '//'
1353 *
1354 * RETURNS
1355 * Success: The next character after the '//' or the string if not present
1356 * Failure: NULL, if lpszStr is NULL.
1357 */
1358 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1359 {
1360 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1361 lpszSrc += 2;
1362 return lpszSrc;
1363 }
1364
1365 /*************************************************************************
1366 * @ [SHLWAPI.171]
1367 *
1368 * Check if two interfaces come from the same object.
1369 *
1370 * PARAMS
1371 * lpInt1 [I] Interface to check against lpInt2.
1372 * lpInt2 [I] Interface to check against lpInt1.
1373 *
1374 * RETURNS
1375 * TRUE, If the interfaces come from the same object.
1376 * FALSE Otherwise.
1377 */
1378 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1379 {
1380 LPVOID lpUnknown1, lpUnknown2;
1381
1382 TRACE("%p %p\n", lpInt1, lpInt2);
1383
1384 if (!lpInt1 || !lpInt2)
1385 return FALSE;
1386
1387 if (lpInt1 == lpInt2)
1388 return TRUE;
1389
1390 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown,
1391 (LPVOID *)&lpUnknown1)))
1392 return FALSE;
1393
1394 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown,
1395 (LPVOID *)&lpUnknown2)))
1396 return FALSE;
1397
1398 if (lpUnknown1 == lpUnknown2)
1399 return TRUE;
1400
1401 return FALSE;
1402 }
1403
1404 /*************************************************************************
1405 * @ [SHLWAPI.172]
1406 *
1407 * Get the window handle of an object.
1408 *
1409 * PARAMS
1410 * lpUnknown [I] Object to get the window handle of
1411 * lphWnd [O] Destination for window handle
1412 *
1413 * RETURNS
1414 * Success: S_OK. lphWnd contains the objects window handle.
1415 * Failure: An HRESULT error code.
1416 *
1417 * NOTES
1418 * lpUnknown is expected to support one of the following interfaces:
1419 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1420 */
1421 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1422 {
1423 /* FIXME: Wine has no header for this object */
1424 static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,
1425 0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};
1426 IUnknown *lpOle;
1427 HRESULT hRet = E_FAIL;
1428
1429 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1430
1431 if (!lpUnknown)
1432 return hRet;
1433
1434 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1435
1436 if (FAILED(hRet))
1437 {
1438 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1439
1440 if (FAILED(hRet))
1441 {
1442 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1443 (void**)&lpOle);
1444 }
1445 }
1446
1447 if (SUCCEEDED(hRet))
1448 {
1449 /* Lazyness here - Since GetWindow() is the first method for the above 3
1450 * interfaces, we use the same call for them all.
1451 */
1452 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1453 IUnknown_Release(lpOle);
1454 if (lphWnd)
1455 TRACE("Returning HWND=%p\n", *lphWnd);
1456 }
1457
1458 return hRet;
1459 }
1460
1461 /*************************************************************************
1462 * @ [SHLWAPI.173]
1463 *
1464 * Call a method on as as yet unidentified object.
1465 *
1466 * PARAMS
1467 * pUnk [I] Object supporting the unidentified interface,
1468 * arg [I] Argument for the call on the object.
1469 *
1470 * RETURNS
1471 * S_OK.
1472 */
1473 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1474 {
1475 static const GUID guid_173 = {
1476 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1477 };
1478 IMalloc *pUnk2;
1479
1480 TRACE("(%p,%ld)\n", pUnk, arg);
1481
1482 /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1483 * We use this interface as its vtable entry is compatible with the
1484 * object in question.
1485 * FIXME: Find out what this object is and where it should be defined.
1486 */
1487 if (pUnk &&
1488 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1489 {
1490 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1491 IMalloc_Release(pUnk2);
1492 }
1493 return S_OK;
1494 }
1495
1496 /*************************************************************************
1497 * @ [SHLWAPI.174]
1498 *
1499 * Call either IObjectWithSite_SetSite() or IPersistMoniker_GetClassID() on
1500 * an interface.
1501 *
1502 * RETURNS
1503 * Success: S_OK.
1504 * Failure: E_FAIL, if p1 is NULL.
1505 * E_NOINTERFACE If p1 does not support the IPersist interface,
1506 * Or an HRESULT error code.
1507 */
1508 DWORD WINAPI IUnknown_SetSite(
1509 IUnknown *p1, /* [in] OLE object */
1510 LPVOID *p2) /* [out] ptr for call results */
1511 {
1512 DWORD ret, aa;
1513 IUnknown *iobjectwithsite;
1514
1515 if (!p1) return E_FAIL;
1516
1517 /* see if SetSite interface exists for IObjectWithSite object */
1518 ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&iobjectwithsite);
1519 TRACE("first IU_QI ret=%08lx, iobjectwithsite=%p\n", ret, iobjectwithsite);
1520 if (ret) {
1521
1522 /* see if GetClassId interface exists for IPersistMoniker object */
1523 ret = IUnknown_QueryInterface(p1, (REFIID)id2, (LPVOID *)&aa);
1524 TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
1525 if (ret) return ret;
1526
1527 /* fake a GetClassId call */
1528 ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
1529 TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1530 *(LPDWORD)p2);
1531 IUnknown_Release((IUnknown *)aa);
1532 }
1533 else {
1534 /* fake a SetSite call */
1535 ret = IOleWindow_GetWindow((IOleWindow *)iobjectwithsite, (HWND*)p2);
1536 TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1537 *(LPDWORD)p2);
1538 IUnknown_Release((IUnknown *)iobjectwithsite);
1539 }
1540 return ret;
1541 }
1542
1543 /*************************************************************************
1544 * @ [SHLWAPI.175]
1545 *
1546 * Call IPersist_GetClassID() on an object.
1547 *
1548 * PARAMS
1549 * lpUnknown [I] Object supporting the IPersist interface
1550 * lpClassId [O] Destination for Class Id
1551 *
1552 * RETURNS
1553 * Success: S_OK. lpClassId contains the Class Id requested.
1554 * Failure: E_FAIL, If lpUnknown is NULL,
1555 * E_NOINTERFACE If lpUnknown does not support IPersist,
1556 * Or an HRESULT error code.
1557 */
1558 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1559 {
1560 IPersist* lpPersist;
1561 HRESULT hRet = E_FAIL;
1562
1563 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1564
1565 if (lpUnknown)
1566 {
1567 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1568 if (SUCCEEDED(hRet))
1569 {
1570 IPersist_GetClassID(lpPersist, lpClassId);
1571 IPersist_Release(lpPersist);
1572 }
1573 }
1574 return hRet;
1575 }
1576
1577 /*************************************************************************
1578 * @ [SHLWAPI.176]
1579 *
1580 * Retrieve a Service Interface from an object.
1581 *
1582 * PARAMS
1583 * lpUnknown [I] Object to get an IServiceProvider interface from
1584 * sid [I] Service ID for IServiceProvider_QueryService() call
1585 * riid [I] Function requested for QueryService call
1586 * lppOut [O] Destination for the service interface pointer
1587 *
1588 * RETURNS
1589 * Success: S_OK. lppOut contains an object providing the requested service
1590 * Failure: An HRESULT error code
1591 *
1592 * NOTES
1593 * lpUnknown is expected to support the IServiceProvider interface.
1594 */
1595 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1596 LPVOID *lppOut)
1597 {
1598 IServiceProvider* pService = NULL;
1599 HRESULT hRet;
1600
1601 if (!lppOut)
1602 return E_FAIL;
1603
1604 *lppOut = NULL;
1605
1606 if (!lpUnknown)
1607 return E_FAIL;
1608
1609 /* Get an IServiceProvider interface from the object */
1610 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1611 (LPVOID*)&pService);
1612
1613 if (!hRet && pService)
1614 {
1615 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1616
1617 /* Get a Service interface from the object */
1618 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1619
1620 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1621
1622 /* Release the IServiceProvider interface */
1623 IUnknown_Release(pService);
1624 }
1625 return hRet;
1626 }
1627
1628 /*************************************************************************
1629 * @ [SHLWAPI.177]
1630 *
1631 * Loads a popup menu.
1632 *
1633 * PARAMS
1634 * hInst [I] Instance handle
1635 * szName [I] Menu name
1636 *
1637 * RETURNS
1638 * Success: TRUE.
1639 * Failure: FALSE.
1640 */
1641 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1642 {
1643 HMENU hMenu, hSubMenu;
1644
1645 if ((hMenu = LoadMenuW(hInst, szName)))
1646 {
1647 if ((hSubMenu = GetSubMenu(hMenu, 0)))
1648 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1649
1650 DestroyMenu(hMenu);
1651 return TRUE;
1652 }
1653 return FALSE;
1654 }
1655
1656 typedef struct _enumWndData
1657 {
1658 UINT uiMsgId;
1659 WPARAM wParam;
1660 LPARAM lParam;
1661 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1662 } enumWndData;
1663
1664 /* Callback for SHLWAPI_178 */
1665 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1666 {
1667 enumWndData *data = (enumWndData *)lParam;
1668
1669 TRACE("(%p,%p)\n", hWnd, data);
1670 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1671 return TRUE;
1672 }
1673
1674 /*************************************************************************
1675 * @ [SHLWAPI.178]
1676 *
1677 * Send or post a message to every child of a window.
1678 *
1679 * PARAMS
1680 * hWnd [I] Window whose children will get the messages
1681 * uiMsgId [I] Message Id
1682 * wParam [I] WPARAM of message
1683 * lParam [I] LPARAM of message
1684 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1685 *
1686 * RETURNS
1687 * Nothing.
1688 *
1689 * NOTES
1690 * The appropriate ASCII or Unicode function is called for the window.
1691 */
1692 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1693 {
1694 enumWndData data;
1695
1696 TRACE("(%p,%u,%d,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1697
1698 if(hWnd)
1699 {
1700 data.uiMsgId = uiMsgId;
1701 data.wParam = wParam;
1702 data.lParam = lParam;
1703
1704 if (bSend)
1705 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1706 else
1707 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1708
1709 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1710 }
1711 }
1712
1713 /*************************************************************************
1714 * @ [SHLWAPI.180]
1715 *
1716 * Remove all sub-menus from a menu.
1717 *
1718 * PARAMS
1719 * hMenu [I] Menu to remove sub-menus from
1720 *
1721 * RETURNS
1722 * Success: 0. All sub-menus under hMenu are removed
1723 * Failure: -1, if any parameter is invalid
1724 */
1725 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1726 {
1727 int iItemCount = GetMenuItemCount(hMenu) - 1;
1728 while (iItemCount >= 0)
1729 {
1730 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1731 if (hSubMenu)
1732 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1733 iItemCount--;
1734 }
1735 return iItemCount;
1736 }
1737
1738 /*************************************************************************
1739 * @ [SHLWAPI.181]
1740 *
1741 * Enable or disable a menu item.
1742 *
1743 * PARAMS
1744 * hMenu [I] Menu holding menu item
1745 * uID [I] ID of menu item to enable/disable
1746 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1747 *
1748 * RETURNS
1749 * The return code from EnableMenuItem.
1750 */
1751 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1752 {
1753 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1754 }
1755
1756 /*************************************************************************
1757 * @ [SHLWAPI.182]
1758 *
1759 * Check or uncheck a menu item.
1760 *
1761 * PARAMS
1762 * hMenu [I] Menu holding menu item
1763 * uID [I] ID of menu item to check/uncheck
1764 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1765 *
1766 * RETURNS
1767 * The return code from CheckMenuItem.
1768 */
1769 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1770 {
1771 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1772 }
1773
1774 /*************************************************************************
1775 * @ [SHLWAPI.183]
1776 *
1777 * Register a window class if it isn't already.
1778 *
1779 * PARAMS
1780 * lpWndClass [I] Window class to register
1781 *
1782 * RETURNS
1783 * The result of the RegisterClassA call.
1784 */
1785 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1786 {
1787 WNDCLASSA wca;
1788 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1789 return TRUE;
1790 return (DWORD)RegisterClassA(wndclass);
1791 }
1792
1793 /*************************************************************************
1794 * @ [SHLWAPI.186]
1795 */
1796 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1797 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1798 {
1799 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1800 POINTL pt = { 0, 0 };
1801
1802 if (!lpPt)
1803 lpPt = &pt;
1804
1805 if (!pdwEffect)
1806 pdwEffect = &dwEffect;
1807
1808 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1809
1810 if (*pdwEffect)
1811 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1812
1813 IDropTarget_DragLeave(pDrop);
1814 return TRUE;
1815 }
1816
1817 /*************************************************************************
1818 * @ [SHLWAPI.187]
1819 *
1820 * Call IPersistPropertyBag_Load() on an object.
1821 *
1822 * PARAMS
1823 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1824 * lpPropBag [O] Destination for loaded IPropertyBag
1825 *
1826 * RETURNS
1827 * Success: S_OK.
1828 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1829 */
1830 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1831 {
1832 IPersistPropertyBag* lpPPBag;
1833 HRESULT hRet = E_FAIL;
1834
1835 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1836
1837 if (lpUnknown)
1838 {
1839 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1840 (void**)&lpPPBag);
1841 if (SUCCEEDED(hRet) && lpPPBag)
1842 {
1843 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1844 IPersistPropertyBag_Release(lpPPBag);
1845 }
1846 }
1847 return hRet;
1848 }
1849
1850 /*************************************************************************
1851 * @ [SHLWAPI.189]
1852 *
1853 * Call IOleControlSite_GetExtendedControl() on an object.
1854 *
1855 * PARAMS
1856 * lpUnknown [I] Object supporting the IOleControlSite interface
1857 * lppDisp [O] Destination for resulting IDispatch.
1858 *
1859 * RETURNS
1860 * Success: S_OK.
1861 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1862 */
1863 DWORD WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, IDispatch** lppDisp)
1864 {
1865 IOleControlSite* lpCSite;
1866 HRESULT hRet = E_FAIL;
1867
1868 TRACE("(%p,%p)\n", lpUnknown, lppDisp);
1869 if (lpUnknown)
1870 {
1871 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1872 (void**)&lpCSite);
1873 if (SUCCEEDED(hRet) && lpCSite)
1874 {
1875 hRet = IOleControlSite_GetExtendedControl(lpCSite, lppDisp);
1876 IOleControlSite_Release(lpCSite);
1877 }
1878 }
1879 return hRet;
1880 }
1881
1882 /*************************************************************************
1883 * @ [SHLWAPI.192]
1884 *
1885 * Get a sub-menu from a menu item.
1886 *
1887 * PARAMS
1888 * hMenu [I] Menu to get sub-menu from
1889 * uID [I] ID of menu item containing sub-menu
1890 *
1891 * RETURNS
1892 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1893 */
1894 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1895 {
1896 MENUITEMINFOA mi;
1897
1898 TRACE("(%p,%uld)\n", hMenu, uID);
1899
1900 mi.cbSize = sizeof(MENUITEMINFOA);
1901 mi.fMask = MIIM_SUBMENU;
1902
1903 if (!GetMenuItemInfoA(hMenu, uID, 0, &mi))
1904 return NULL;
1905
1906 return mi.hSubMenu;
1907 }
1908
1909 /*************************************************************************
1910 * @ [SHLWAPI.193]
1911 *
1912 * Get the color depth of the primary display.
1913 *
1914 * PARAMS
1915 * None.
1916 *
1917 * RETURNS
1918 * The color depth of the primary display.
1919 */
1920 DWORD WINAPI SHGetCurColorRes()
1921 {
1922 HDC hdc;
1923 DWORD ret;
1924
1925 TRACE("()\n");
1926
1927 hdc = GetDC(0);
1928 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1929 ReleaseDC(0, hdc);
1930 return ret;
1931 }
1932
1933 /*************************************************************************
1934 * @ [SHLWAPI.194]
1935 *
1936 * Wait for a message to arrive, with a timeout.
1937 *
1938 * PARAMS
1939 * hand [I] Handle to query
1940 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1941 *
1942 * RETURNS
1943 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1944 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1945 * message is available.
1946 */
1947 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
1948 {
1949 DWORD dwEndTicks = GetTickCount() + dwTimeout;
1950 DWORD dwRet;
1951
1952 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
1953 {
1954 MSG msg;
1955
1956 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
1957
1958 if (dwTimeout != INFINITE)
1959 {
1960 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
1961 return WAIT_TIMEOUT;
1962 }
1963 }
1964
1965 return dwRet;
1966 }
1967
1968 /*************************************************************************
1969 * @ [SHLWAPI.197]
1970 *
1971 * Blank out a region of text by drawing the background only.
1972 *
1973 * PARAMS
1974 * hDC [I] Device context to draw in
1975 * pRect [I] Area to draw in
1976 * cRef [I] Color to draw in
1977 *
1978 * RETURNS
1979 * Nothing.
1980 */
1981 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
1982 {
1983 COLORREF cOldColor = SetBkColor(hDC, cRef);
1984 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
1985 SetBkColor(hDC, cOldColor);
1986 return 0;
1987 }
1988
1989 /*************************************************************************
1990 * @ [SHLWAPI.198]
1991 *
1992 * Return the value asociated with a key in a map.
1993 *
1994 * PARAMS
1995 * lpKeys [I] A list of keys of length iLen
1996 * lpValues [I] A list of values associated with lpKeys, of length iLen
1997 * iLen [I] Length of both lpKeys and lpValues
1998 * iKey [I] The key value to look up in lpKeys
1999 *
2000 * RETURNS
2001 * The value in lpValues associated with iKey, or -1 if iKey is not
2002 * found in lpKeys.
2003 *
2004 * NOTES
2005 * - If two elements in the map share the same key, this function returns
2006 * the value closest to the start of the map
2007 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2008 */
2009 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2010 {
2011 if (lpKeys && lpValues)
2012 {
2013 int i = 0;
2014
2015 while (i < iLen)
2016 {
2017 if (lpKeys[i] == iKey)
2018 return lpValues[i]; /* Found */
2019 i++;
2020 }
2021 }
2022 return -1; /* Not found */
2023 }
2024
2025
2026 /*************************************************************************
2027 * @ [SHLWAPI.199]
2028 *
2029 * Copy an interface pointer
2030 *
2031 * PARAMS
2032 * lppDest [O] Destination for copy
2033 * lpUnknown [I] Source for copy
2034 *
2035 * RETURNS
2036 * Nothing.
2037 */
2038 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2039 {
2040 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2041
2042 if (lppDest)
2043 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2044
2045 if (lpUnknown)
2046 {
2047 /* Copy */
2048 IUnknown_AddRef(lpUnknown);
2049 *lppDest = lpUnknown;
2050 }
2051 }
2052
2053 /*************************************************************************
2054 * @ [SHLWAPI.201]
2055 *
2056 */
2057 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2058 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2059 VARIANT* pvaOut)
2060 {
2061 FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2062 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2063 return DRAGDROP_E_NOTREGISTERED;
2064 }
2065
2066 /*************************************************************************
2067 * @ [SHLWAPI.202]
2068 *
2069 */
2070 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2071 {
2072 FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2073 return DRAGDROP_E_NOTREGISTERED;
2074 }
2075
2076 /*************************************************************************
2077 * @ [SHLWAPI.204]
2078 *
2079 * Determine if a window is not a child of another window.
2080 *
2081 * PARAMS
2082 * hParent [I] Suspected parent window
2083 * hChild [I] Suspected child window
2084 *
2085 * RETURNS
2086 * TRUE: If hChild is a child window of hParent
2087 * FALSE: If hChild is not a child window of hParent, or they are equal
2088 */
2089 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2090 {
2091 TRACE("(%p,%p)\n", hParent, hChild);
2092
2093 if (!hParent || !hChild)
2094 return TRUE;
2095 else if(hParent == hChild)
2096 return FALSE;
2097 return !IsChild(hParent, hChild);
2098 }
2099
2100 /*************************************************************************
2101 * @ [SHLWAPI.208]
2102 *
2103 * Some sort of memory management process.
2104 */
2105 DWORD WINAPI FDSA_Initialize(
2106 DWORD a,
2107 DWORD b,
2108 LPVOID c,
2109 LPVOID d,
2110 DWORD e)
2111 {
2112 FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
2113 a, b, c, d, e);
2114 return 1;
2115 }
2116
2117 /*************************************************************************
2118 * @ [SHLWAPI.209]
2119 *
2120 * Some sort of memory management process.
2121 */
2122 DWORD WINAPI FDSA_Destroy(
2123 LPVOID a)
2124 {
2125 FIXME("(%p) stub\n",
2126 a);
2127 return 1;
2128 }
2129
2130 /*************************************************************************
2131 * @ [SHLWAPI.210]
2132 *
2133 * Some sort of memory management process.
2134 */
2135 DWORD WINAPI FDSA_InsertItem(
2136 LPVOID a,
2137 DWORD b,
2138 LPVOID c)
2139 {
2140 FIXME("(%p 0x%08lx %p) stub\n",
2141 a, b, c);
2142 return 0;
2143 }
2144
2145 /*************************************************************************
2146 * @ [SHLWAPI.211]
2147 */
2148 DWORD WINAPI FDSA_DeleteItem(
2149 LPVOID a,
2150 DWORD b)
2151 {
2152 FIXME("(%p 0x%08lx) stub\n",
2153 a, b);
2154 return 1;
2155 }
2156
2157 typedef struct {
2158 REFIID refid;
2159 DWORD indx;
2160 } IFACE_INDEX_TBL;
2161
2162 /*************************************************************************
2163 * @ [SHLWAPI.219]
2164 *
2165 * Call IUnknown_QueryInterface() on a table of objects.
2166 *
2167 * RETURNS
2168 * Success: S_OK.
2169 * Failure: E_POINTER or E_NOINTERFACE.
2170 */
2171 HRESULT WINAPI QISearch(
2172 LPVOID w, /* [in] Table of interfaces */
2173 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2174 REFIID riid, /* [in] REFIID to get interface for */
2175 LPVOID *ppv) /* [out] Destination for interface pointer */
2176 {
2177 HRESULT ret;
2178 IUnknown *a_vtbl;
2179 IFACE_INDEX_TBL *xmove;
2180
2181 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2182 if (ppv) {
2183 xmove = x;
2184 while (xmove->refid) {
2185 TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2186 if (IsEqualIID(riid, xmove->refid)) {
2187 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2188 TRACE("matched, returning (%p)\n", a_vtbl);
2189 *ppv = (LPVOID)a_vtbl;
2190 IUnknown_AddRef(a_vtbl);
2191 return S_OK;
2192 }
2193 xmove++;
2194 }
2195
2196 if (IsEqualIID(riid, &IID_IUnknown)) {
2197 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2198 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2199 *ppv = (LPVOID)a_vtbl;
2200 IUnknown_AddRef(a_vtbl);
2201 return S_OK;
2202 }
2203 *ppv = 0;
2204 ret = E_NOINTERFACE;
2205 } else
2206 ret = E_POINTER;
2207
2208 TRACE("-- 0x%08lx\n", ret);
2209 return ret;
2210 }
2211
2212 /*************************************************************************
2213 * @ [SHLWAPI.221]
2214 *
2215 * Remove the "PropDlgFont" property from a window.
2216 *
2217 * PARAMS
2218 * hWnd [I] Window to remove the property from
2219 *
2220 * RETURNS
2221 * A handle to the removed property, or NULL if it did not exist.
2222 */
2223 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2224 {
2225 HANDLE hProp;
2226
2227 TRACE("(%p)\n", hWnd);
2228
2229 hProp = GetPropA(hWnd, "PropDlgFont");
2230
2231 if(hProp)
2232 {
2233 DeleteObject(hProp);
2234 hProp = RemovePropA(hWnd, "PropDlgFont");
2235 }
2236 return hProp;
2237 }
2238
2239 /*************************************************************************
2240 * @ [SHLWAPI.236]
2241 *
2242 * Load the in-process server of a given GUID.
2243 *
2244 * PARAMS
2245 * refiid [I] GUID of the server to load.
2246 *
2247 * RETURNS
2248 * Success: A handle to the loaded server dll.
2249 * Failure: A NULL handle.
2250 */
2251 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2252 {
2253 HKEY newkey;
2254 DWORD type, count;
2255 CHAR value[MAX_PATH], string[MAX_PATH];
2256
2257 strcpy(string, "CLSID\\");
2258 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2259 strcat(string, "\\InProcServer32");
2260
2261 count = MAX_PATH;
2262 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2263 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2264 RegCloseKey(newkey);
2265 return LoadLibraryExA(value, 0, 0);
2266 }
2267
2268 /*************************************************************************
2269 * @ [SHLWAPI.237]
2270 *
2271 * Unicode version of SHLWAPI_183.
2272 */
2273 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2274 {
2275 WNDCLASSW WndClass;
2276
2277 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2278
2279 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2280 return TRUE;
2281 return RegisterClassW(lpWndClass);
2282 }
2283
2284 /*************************************************************************
2285 * @ [SHLWAPI.238]
2286 *
2287 * Unregister a list of classes.
2288 *
2289 * PARAMS
2290 * hInst [I] Application instance that registered the classes
2291 * lppClasses [I] List of class names
2292 * iCount [I] Number of names in lppClasses
2293 *
2294 * RETURNS
2295 * Nothing.
2296 */
2297 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2298 {
2299 WNDCLASSA WndClass;
2300
2301 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2302
2303 while (iCount > 0)
2304 {
2305 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2306 UnregisterClassA(*lppClasses, hInst);
2307 lppClasses++;
2308 iCount--;
2309 }
2310 }
2311
2312 /*************************************************************************
2313 * @ [SHLWAPI.239]
2314 *
2315 * Unicode version of SHUnregisterClassesA.
2316 */
2317 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2318 {
2319 WNDCLASSW WndClass;
2320
2321 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2322
2323 while (iCount > 0)
2324 {
2325 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2326 UnregisterClassW(*lppClasses, hInst);
2327 lppClasses++;
2328 iCount--;
2329 }
2330 }
2331
2332 /*************************************************************************
2333 * @ [SHLWAPI.240]
2334 *
2335 * Call The correct (Ascii/Unicode) default window procedure for a window.
2336 *
2337 * PARAMS
2338 * hWnd [I] Window to call the default procedure for
2339 * uMessage [I] Message ID
2340 * wParam [I] WPARAM of message
2341 * lParam [I] LPARAM of message
2342 *
2343 * RETURNS
2344 * The result of calling DefWindowProcA() or DefWindowProcW().
2345 */
2346 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2347 {
2348 if (IsWindowUnicode(hWnd))
2349 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2350 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2351 }
2352
2353 /*************************************************************************
2354 * @ [SHLWAPI.257]
2355 *
2356 * Create a worker window using CreateWindowExA().
2357 *
2358 * PARAMS
2359 * wndProc [I] Window procedure
2360 * hWndParent [I] Parent window
2361 * dwExStyle [I] Extra style flags
2362 * dwStyle [I] Style flags
2363 * hMenu [I] Window menu
2364 * z [I] Unknown
2365 *
2366 * RETURNS
2367 * Success: The window handle of the newly created window.
2368 * Failure: 0.
2369 */
2370 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2371 DWORD dwStyle, HMENU hMenu, LONG z)
2372 {
2373 static const char* szClass = "WorkerA";
2374 WNDCLASSA wc;
2375 HWND hWnd;
2376
2377 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2378 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2379
2380 /* Create Window class */
2381 wc.style = 0;
2382 wc.lpfnWndProc = DefWindowProcA;
2383 wc.cbClsExtra = 0;
2384 wc.cbWndExtra = 4;
2385 wc.hInstance = shlwapi_hInstance;
2386 wc.hIcon = NULL;
2387 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2388 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2389 wc.lpszMenuName = NULL;
2390 wc.lpszClassName = szClass;
2391
2392 SHRegisterClassA(&wc); /* Register class */
2393
2394 /* FIXME: Set extra bits in dwExStyle */
2395
2396 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2397 hWndParent, hMenu, shlwapi_hInstance, 0);
2398 if (hWnd)
2399 {
2400 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2401
2402 if (wndProc)
2403 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2404 }
2405 return hWnd;
2406 }
2407
2408 typedef struct tagPOLICYDATA
2409 {
2410 DWORD policy; /* flags value passed to SHRestricted */
2411 LPCWSTR appstr; /* application str such as "Explorer" */
2412 LPCWSTR keystr; /* name of the actual registry key / policy */
2413 } POLICYDATA, *LPPOLICYDATA;
2414
2415 #define SHELL_NO_POLICY 0xffffffff
2416
2417 /* default shell policy registry key */
2418 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2419 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2420 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2421 '\\','P','o','l','i','c','i','e','s',0};
2422
2423 /*************************************************************************
2424 * @ [SHLWAPI.271]
2425 *
2426 * Retrieve a policy value from the registry.
2427 *
2428 * PARAMS
2429 * lpSubKey [I] registry key name
2430 * lpSubName [I] subname of registry key
2431 * lpValue [I] value name of registry value
2432 *
2433 * RETURNS
2434 * the value associated with the registry key or 0 if not found
2435 */
2436 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2437 {
2438 DWORD retval, datsize = sizeof(retval);
2439 HKEY hKey;
2440
2441 if (!lpSubKey)
2442 lpSubKey = strRegistryPolicyW;
2443
2444 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2445 if (retval != ERROR_SUCCESS)
2446 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2447 if (retval != ERROR_SUCCESS)
2448 return 0;
2449
2450 SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);
2451 RegCloseKey(hKey);
2452 return retval;
2453 }
2454
2455 /*************************************************************************
2456 * @ [SHLWAPI.266]
2457 *
2458 * Helper function to retrieve the possibly cached value for a specific policy
2459 *
2460 * PARAMS
2461 * policy [I] The policy to look for
2462 * initial [I] Main registry key to open, if NULL use default
2463 * polTable [I] Table of known policies, 0 terminated
2464 * polArr [I] Cache array of policy values
2465 *
2466 * RETURNS
2467 * The retrieved policy value or 0 if not successful
2468 *
2469 * NOTES
2470 * This function is used by the native SHRestricted function to search for the
2471 * policy and cache it once retrieved. The current Wine implementation uses a
2472 * different POLICYDATA structure and implements a similar algorithme adapted to
2473 * that structure.
2474 */
2475 DWORD WINAPI SHRestrictionLookup(
2476 DWORD policy,
2477 LPCWSTR initial,
2478 LPPOLICYDATA polTable,
2479 LPDWORD polArr)
2480 {
2481 TRACE("(0x%08lx %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2482
2483 if (!polTable || !polArr)
2484 return 0;
2485
2486 for (;polTable->policy; polTable++, polArr++)
2487 {
2488 if (policy == polTable->policy)
2489 {
2490 /* we have a known policy */
2491
2492 /* check if this policy has been cached */
2493 if (*polArr == SHELL_NO_POLICY)
2494 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2495 return *polArr;
2496 }
2497 }
2498 /* we don't know this policy, return 0 */
2499 TRACE("unknown policy: (%08lx)\n", policy);
2500 return 0;
2501 }
2502
2503 /*************************************************************************
2504 * @ [SHLWAPI.267]
2505 *
2506 * Get an interface from an object.
2507 *
2508 * RETURNS
2509 * Success: S_OK. ppv contains the requested interface.
2510 * Failure: An HRESULT error code.
2511 *
2512 * NOTES
2513 * This QueryInterface asks the inner object for a interface. In case
2514 * of aggregation this request would be forwarded by the inner to the
2515 * outer object. This function asks the inner object directly for the
2516 * interface circumventing the forwarding to the outer object.
2517 */
2518 HRESULT WINAPI SHWeakQueryInterface(
2519 IUnknown * pUnk, /* [in] Outer object */
2520 IUnknown * pInner, /* [in] Inner object */
2521 IID * riid, /* [in] Interface GUID to query for */
2522 LPVOID* ppv) /* [out] Destination for queried interface */
2523 {
2524 HRESULT hret = E_NOINTERFACE;
2525 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2526
2527 *ppv = NULL;
2528 if(pUnk && pInner) {
2529 hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
2530 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2531 }
2532 TRACE("-- 0x%08lx\n", hret);
2533 return hret;
2534 }
2535
2536 /*************************************************************************
2537 * @ [SHLWAPI.268]
2538 *
2539 * Move a reference from one interface to another.
2540 *
2541 * PARAMS
2542 * lpDest [O] Destination to receive the reference
2543 * lppUnknown [O] Source to give up the reference to lpDest
2544 *
2545 * RETURNS
2546 * Nothing.
2547 */
2548 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2549 {
2550 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2551
2552 if (*lppUnknown)
2553 {
2554 /* Copy Reference*/
2555 IUnknown_AddRef(lpDest);
2556 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2557 }
2558 }
2559
2560 /*************************************************************************
2561 * @ [SHLWAPI.269]
2562 *
2563 * Convert an ASCII string of a CLSID into a CLSID.
2564 *
2565 * PARAMS
2566 * idstr [I] String representing a CLSID in registry format
2567 * id [O] Destination for the converted CLSID
2568 *
2569 * RETURNS
2570 * Success: TRUE. id contains the converted CLSID.
2571 * Failure: FALSE.
2572 */
2573 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2574 {
2575 WCHAR wClsid[40];
2576 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2577 return SUCCEEDED(CLSIDFromStringWrap(wClsid, id));
2578 }
2579
2580 /*************************************************************************
2581 * @ [SHLWAPI.270]
2582 *
2583 * Unicode version of GUIDFromStringA.
2584 */
2585 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2586 {
2587 return SUCCEEDED(CLSIDFromStringWrap(idstr, id));
2588 }
2589
2590 /*************************************************************************
2591 * @ [SHLWAPI.276]
2592 *
2593 * Determine if the browser is integrated into the shell, and set a registry
2594 * key accordingly.
2595 *
2596 * PARAMS
2597 * None.
2598 *
2599 * RETURNS
2600 * 1, If the browser is not integrated.
2601 * 2, If the browser is integrated.
2602 *
2603 * NOTES
2604 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2605 * either set to TRUE, or removed depending on whether the browser is deemed
2606 * to be integrated.
2607 */
2608 DWORD WINAPI WhichPlatform()
2609 {
2610 static LPCSTR szIntegratedBrowser = "IntegratedBrowser";
2611 static DWORD dwState = 0;
2612 HKEY hKey;
2613 DWORD dwRet, dwData, dwSize;
2614
2615 if (dwState)
2616 return dwState;
2617
2618 /* If shell32 exports DllGetVersion(), the browser is integrated */
2619 GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);
2620 dwState = pDllGetVersion ? 2 : 1;
2621
2622 /* Set or delete the key accordingly */
2623 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2624 "Software\\Microsoft\\Internet Explorer", 0,
2625 KEY_ALL_ACCESS, &hKey);
2626 if (!dwRet)
2627 {
2628 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2629 (LPBYTE)&dwData, &dwSize);
2630
2631 if (!dwRet && dwState == 1)
2632 {
2633 /* Value exists but browser is not integrated */
2634 RegDeleteValueA(hKey, szIntegratedBrowser);
2635 }
2636 else if (dwRet && dwState == 2)
2637 {
2638 /* Browser is integrated but value does not exist */
2639 dwData = TRUE;
2640 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2641 (LPBYTE)&dwData, sizeof(dwData));
2642 }
2643 RegCloseKey(hKey);
2644 }
2645 return dwState;
2646 }
2647
2648 /*************************************************************************
2649 * @ [SHLWAPI.278]
2650 *
2651 * Unicode version of SHCreateWorkerWindowA.
2652 */
2653 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2654 DWORD dwStyle, HMENU hMenu, LONG z)
2655 {
2656 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2657 WNDCLASSW wc;
2658 HWND hWnd;
2659
2660 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2661 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2662
2663 /* If our OS is natively ASCII, use the ASCII version */
2664 if (!(GetVersion() & 0x80000000)) /* NT */
2665 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2666
2667 /* Create Window class */
2668 wc.style = 0;
2669 wc.lpfnWndProc = DefWindowProcW;
2670 wc.cbClsExtra = 0;
2671 wc.cbWndExtra = 4;
2672 wc.hInstance = shlwapi_hInstance;
2673 wc.hIcon = NULL;
2674 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2675 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2676 wc.lpszMenuName = NULL;
2677 wc.lpszClassName = szClass;
2678
2679 SHRegisterClassW(&wc); /* Register class */
2680
2681 /* FIXME: Set extra bits in dwExStyle */
2682
2683 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2684 hWndParent, hMenu, shlwapi_hInstance, 0);
2685 if (hWnd)
2686 {
2687 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2688
2689 if (wndProc)
2690 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2691 }
2692 return hWnd;
2693 }
2694
2695 /*************************************************************************
2696 * @ [SHLWAPI.279]
2697 *
2698 * Get and show a context menu from a shell folder.
2699 *
2700 * PARAMS
2701 * hWnd [I] Window displaying the shell folder
2702 * lpFolder [I] IShellFolder interface
2703 * lpApidl [I] Id for the particular folder desired
2704 *
2705 * RETURNS
2706 * Success: S_OK.
2707 * Failure: An HRESULT error code indicating the error.
2708 */
2709 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2710 {
2711 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2712 }
2713
2714 /*************************************************************************
2715 * @ [SHLWAPI.281]
2716 *
2717 * _SHPackDispParamsV
2718 */
2719 HRESULT WINAPI SHPackDispParamsV(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2720 {
2721 FIXME("%p %p %p %p\n",w,x,y,z);
2722 return E_FAIL;
2723 }
2724
2725 /*************************************************************************
2726 * @ [SHLWAPI.282]
2727 *
2728 * This function seems to be a forward to SHPackDispParamsV (whatever THAT
2729 * function does...).
2730 */
2731 HRESULT WINAPI SHPackDispParams(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2732 {
2733 FIXME("%p %p %p %p\n", w, x, y, z);
2734 return E_FAIL;
2735 }
2736
2737 /*************************************************************************
2738 * @ [SHLWAPI.284]
2739 *
2740 * _IConnectionPoint_SimpleInvoke
2741 */
2742 DWORD WINAPI IConnectionPoint_SimpleInvoke(
2743 LPVOID x,
2744 LPVOID y,
2745 LPVOID z)
2746 {
2747 FIXME("(%p %p %p) stub\n",x,y,z);
2748 return 0;
2749 }
2750
2751 /*************************************************************************
2752 * @ [SHLWAPI.285]
2753 *
2754 * Notify an IConnectionPoint object of changes.
2755 *
2756 * PARAMS
2757 * lpCP [I] Object to notify
2758 * dispID [I]
2759 *
2760 * RETURNS
2761 * Success: S_OK.
2762 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
2763 * IConnectionPoint interface.
2764 */
2765 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
2766 {
2767 IEnumConnections *lpEnum;
2768 HRESULT hRet = E_NOINTERFACE;
2769
2770 TRACE("(%p,0x%8lX)\n", lpCP, dispID);
2771
2772 /* Get an enumerator for the connections */
2773 if (lpCP)
2774 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
2775
2776 if (SUCCEEDED(hRet))
2777 {
2778 IPropertyNotifySink *lpSink;
2779 CONNECTDATA connData;
2780 ULONG ulFetched;
2781
2782 /* Call OnChanged() for every notify sink in the connection point */
2783 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
2784 {
2785 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
2786 lpSink)
2787 {
2788 IPropertyNotifySink_OnChanged(lpSink, dispID);
2789 IPropertyNotifySink_Release(lpSink);
2790 }
2791 IUnknown_Release(connData.pUnk);
2792 }
2793
2794 IEnumConnections_Release(lpEnum);
2795 }
2796 return hRet;
2797 }
2798
2799 /*************************************************************************
2800 * @ [SHLWAPI.287]
2801 *
2802 * Notify an IConnectionPointContainer object of changes.
2803 *
2804 * PARAMS
2805 * lpUnknown [I] Object to notify
2806 * dispID [I]
2807 *
2808 * RETURNS
2809 * Success: S_OK.
2810 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
2811 * IConnectionPointContainer interface.
2812 */
2813 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
2814 {
2815 IConnectionPointContainer* lpCPC = NULL;
2816 HRESULT hRet = E_NOINTERFACE;
2817
2818 TRACE("(%p,0x%8lX)\n", lpUnknown, dispID);
2819
2820 if (lpUnknown)
2821 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
2822
2823 if (SUCCEEDED(hRet))
2824 {
2825 IConnectionPoint* lpCP;
2826
2827 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
2828 IConnectionPointContainer_Release(lpCPC);
2829
2830 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
2831 IConnectionPoint_Release(lpCP);
2832 }
2833 return hRet;
2834 }
2835
2836 /*************************************************************************
2837 * @ [SHLWAPI.289]
2838 *
2839 * See PlaySoundW.
2840 */
2841 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
2842 {
2843 GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
2844 return pPlaySoundW(pszSound, hmod, fdwSound);
2845 }
2846
2847 /*************************************************************************
2848 * @ [SHLWAPI.294]
2849 */
2850 BOOL WINAPI SHGetIniStringW(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len, LPCSTR lpStr2)
2851 {
2852 /*
2853 * str1: "I" "I" pushl esp+0x20
2854 * str2: "U" "I" pushl 0x77c93810
2855 * (is "I" and "U" "integer" and "unsigned" ??)
2856 *
2857 * pStr: "" "" pushl eax
2858 * some_len: 0x824 0x104 pushl 0x824
2859 * lpStr2: "%l" "%l" pushl esp+0xc
2860 *
2861 * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
2862 * LocalAlloc(0x00, some_len) -> irrelevant_var
2863 * LocalAlloc(0x40, irrelevant_len) -> pStr
2864 * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
2865 * shlwapi.PathRemoveBlanksW(pStr);
2866 */
2867 FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
2868 return TRUE;
2869 }
2870
2871 /*************************************************************************
2872 * @ [SHLWAPI.295]
2873 *
2874 * Called by ICQ2000b install via SHDOCVW:
2875 * str1: "InternetShortcut"
2876 * x: some unknown pointer
2877 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
2878 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
2879 *
2880 * In short: this one maybe creates a desktop link :-)
2881 */
2882 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
2883 {
2884 FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
2885 return TRUE;
2886 }
2887
2888 /*************************************************************************
2889 * @ [SHLWAPI.299]
2890 *
2891 * See COMCTL32_417.
2892 */
2893 BOOL WINAPI ExtTextOutWrapW(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
2894 LPCWSTR str, UINT count, const INT *lpDx)
2895 {
2896 GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);
2897 return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);
2898 }
2899
2900 /*************************************************************************
2901 * @ [SHLWAPI.313]
2902 *
2903 * See SHGetFileInfoW.
2904 */
2905 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
2906 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
2907 {
2908 GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
2909 return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
2910 }
2911
2912 /*************************************************************************
2913 * @ [SHLWAPI.318]
2914 *
2915 * See DragQueryFileW.
2916 */
2917 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
2918 {
2919 GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
2920 return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
2921 }
2922
2923 /*************************************************************************
2924 * @ [SHLWAPI.333]
2925 *
2926 * See SHBrowseForFolderW.
2927 */
2928 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
2929 {
2930 GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
2931 return pSHBrowseForFolderW(lpBi);
2932 }
2933
2934 /*************************************************************************
2935 * @ [SHLWAPI.334]
2936 *
2937 * See SHGetPathFromIDListW.
2938 */
2939 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
2940 {
2941 GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
2942 return pSHGetPathFromIDListW(pidl, pszPath);
2943 }
2944
2945 /*************************************************************************
2946 * @ [SHLWAPI.335]
2947 *
2948 * See ShellExecuteExW.
2949 */
2950 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
2951 {
2952 GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
2953 return pShellExecuteExW(lpExecInfo);
2954 }
2955
2956 /*************************************************************************
2957 * @ [SHLWAPI.336]
2958 *
2959 * See SHFileOperationW.
2960 */
2961 HICON WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
2962 {
2963 GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
2964 return pSHFileOperationW(lpFileOp);
2965 }
2966
2967 /*************************************************************************
2968 * @ [SHLWAPI.337]
2969 *
2970 * See ExtractIconExW.
2971 */
2972 UINT WINAPI ExtractIconExWrapW(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
2973 HICON *phiconSmall, UINT nIcons)
2974 {
2975 GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", 0);
2976 return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
2977 }
2978
2979 /*************************************************************************
2980 * @ [SHLWAPI.342]
2981 *
2982 */
2983 LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
2984 {
2985 return InterlockedCompareExchange(dest, xchg, compare);
2986 }
2987
2988 /*************************************************************************
2989 * @ [SHLWAPI.350]
2990 *
2991 * See GetFileVersionInfoSizeW.
2992 */
2993 DWORD WINAPI GetFileVersionInfoSizeWrapW(
2994 LPWSTR x,
2995 LPVOID y)
2996 {
2997 DWORD ret;
2998
2999 GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
3000 ret = pGetFileVersionInfoSizeW(x, y);
3001 return 0x208 + ret;
3002 }
3003
3004 /*************************************************************************
3005 * @ [SHLWAPI.351]
3006 *
3007 * See GetFileVersionInfoW.
3008 */
3009 BOOL WINAPI GetFileVersionInfoWrapW(
3010 LPWSTR w, /* [in] path to dll */
3011 DWORD x, /* [in] parm 2 to GetFileVersionInfoA */
3012 DWORD y, /* [in] return value from SHLWAPI_350() - assume length */
3013 LPVOID z) /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA()) */
3014 {
3015 GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
3016 return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);
3017 }
3018
3019 /*************************************************************************
3020 * @ [SHLWAPI.352]
3021 *
3022 * See VerQueryValueW.
3023 */
3024 WORD WINAPI VerQueryValueWrapW(
3025 LPVOID w, /* [in] Buffer from SHLWAPI_351() */
3026 LPWSTR x, /* [in] Value to retrieve - converted and passed to VerQueryValueA() as #2 */
3027 LPVOID y, /* [out] Ver buffer - passed to VerQueryValueA as #3 */
3028 UINT* z) /* [in] Ver length - passed to VerQueryValueA as #4 */
3029 {
3030 GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
3031 return pVerQueryValueW((char*)w+0x208, x, y, z);
3032 }
3033
3034 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3035 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3036 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3037
3038 /*************************************************************************
3039 * @ [SHLWAPI.355]
3040 *
3041 * Change the modality of a shell object.
3042 *
3043 * PARAMS
3044 * lpUnknown [I] Object to make modeless
3045 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3046 *
3047 * RETURNS
3048 * Success: S_OK. The modality lpUnknown is changed.
3049 * Failure: An HRESULT error code indicating the error.
3050 *
3051 * NOTES
3052 * lpUnknown must support the IOleInPlaceFrame interface, the
3053 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3054 * or the IDocHostUIHandler interface, or this call fails.
3055 */
3056 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3057 {
3058 IUnknown *lpObj;
3059 HRESULT hRet;
3060
3061 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3062
3063 if (!lpUnknown)
3064 return E_FAIL;
3065
3066 if (IsIface(IOleInPlaceFrame))
3067 EnableModeless(IOleInPlaceFrame);
3068 else if (IsIface(IShellBrowser))
3069 EnableModeless(IShellBrowser);
3070 #if 0
3071 /* FIXME: Wine has no headers for these objects yet */
3072 else if (IsIface(IInternetSecurityMgrSite))
3073 EnableModeless(IInternetSecurityMgrSite);
3074 else if (IsIface(IDocHostUIHandler))
3075 EnableModeless(IDocHostUIHandler);
3076 #endif
3077 else
3078 return hRet;
3079
3080 IUnknown_Release(lpObj);
3081 return S_OK;
3082 }
3083
3084 /*************************************************************************
3085 * @ [SHLWAPI.357]
3086 *
3087 * See SHGetNewLinkInfoW.
3088 */
3089 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3090 BOOL *pfMustCopy, UINT uFlags)
3091 {
3092 GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
3093 return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3094 }
3095
3096 /*************************************************************************
3097 * @ [SHLWAPI.358]
3098 *
3099 * See SHDefExtractIconW.
3100 */
3101 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3102 HICON* phiconSmall, UINT nIconSize)
3103 {
3104 GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
3105 return pSHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3106 }
3107
3108 /*************************************************************************
3109 * @ [SHLWAPI.363]
3110 *
3111 * Get and show a context menu from a shell folder.
3112 *
3113 * PARAMS
3114 * hWnd [I] Window displaying the shell folder
3115 * lpFolder [I] IShellFolder interface
3116 * lpApidl [I] Id for the particular folder desired
3117 * bInvokeDefault [I] Whether to invoke the default menu item
3118 *
3119 * RETURNS
3120 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3121 * executed.
3122 * Failure: An HRESULT error code indicating the error.
3123 */
3124 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3125 {
3126 IContextMenu *iContext;
3127 HRESULT hRet = E_FAIL;
3128
3129 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3130
3131 if (!lpFolder)
3132 return hRet;
3133
3134 /* Get the context menu from the shell folder */
3135 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3136 &IID_IContextMenu, 0, (void**)&iContext);
3137 if (SUCCEEDED(hRet))
3138 {
3139 HMENU hMenu;
3140 if ((hMenu = CreatePopupMenu()))
3141 {
3142 HRESULT hQuery;
3143 DWORD dwDefaultId = 0;
3144
3145 /* Add the context menu entries to the popup */
3146 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3147 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3148
3149 if (SUCCEEDED(hQuery))
3150 {
3151 if (bInvokeDefault &&
3152 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3153 {
3154 CMINVOKECOMMANDINFO cmIci;
3155 /* Invoke the default item */
3156 memset(&cmIci,0,sizeof(cmIci));
3157 cmIci.cbSize = sizeof(cmIci);
3158 cmIci.fMask = CMIC_MASK_ASYNCOK;
3159 cmIci.hwnd = hWnd;
3160 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3161 cmIci.nShow = SW_SCROLLCHILDREN;
3162
3163 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3164 }
3165 }
3166 DestroyMenu(hMenu);
3167 }
3168 IContextMenu_Release(iContext);
3169 }
3170 return hRet;
3171 }
3172
3173 /*************************************************************************
3174 * @ [SHLWAPI.370]
3175 *
3176 * See ExtractIconW.
3177 */
3178 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3179 UINT nIconIndex)
3180 {
3181 GET_FUNC(pExtractIconW, shell32, "ExtractIconW", NULL);
3182 return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3183 }
3184
3185 /*************************************************************************
3186 * @ [SHLWAPI.376]
3187 */
3188 LANGID WINAPI MLGetUILanguage()
3189 {
3190 FIXME("() stub\n");
3191 /* FIXME: This should be a forward in the .spec file to the win2k function
3192 * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
3193 */
3194 return GetUserDefaultLangID();
3195 }
3196
3197 /*************************************************************************
3198 * @ [SHLWAPI.377]
3199 *
3200 * Load a library from the directory of a particular process.
3201 *
3202 * PARAMS
3203 * new_mod [I] Library name
3204 * inst_hwnd [I] Module whose directory is to be used
3205 * dwFlags [I] Flags controlling the load
3206 *
3207 * RETURNS
3208 * Success: A handle to the loaded module
3209 * Failure: A NULL handle.
3210 */
3211 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3212 {
3213 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3214 * each call here.
3215 * FIXME: Native shows calls to:
3216 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3217 * CheckVersion
3218 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3219 * RegQueryValueExA for "LPKInstalled"
3220 * RegCloseKey
3221 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3222 * RegQueryValueExA for "ResourceLocale"
3223 * RegCloseKey
3224 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3225 * RegQueryValueExA for "Locale"
3226 * RegCloseKey
3227 * and then tests the Locale ("en" for me).
3228 * code below
3229 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3230 */
3231 CHAR mod_path[2*MAX_PATH];
3232 LPSTR ptr;
3233 DWORD len;
3234
3235 FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwFlags);
3236 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3237 if (!len || len >= sizeof(mod_path)) return NULL;
3238
3239 ptr = strrchr(mod_path, '\\');
3240 if (ptr) {
3241 strcpy(ptr+1, new_mod);
3242 TRACE("loading %s\n", debugstr_a(mod_path));
3243 return LoadLibraryA(mod_path);
3244 }
3245 return NULL;
3246 }
3247
3248 /*************************************************************************
3249 * @ [SHLWAPI.378]
3250 *
3251 * Unicode version of MLLoadLibraryA.
3252 */
3253 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3254 {
3255 WCHAR mod_path[2*MAX_PATH];
3256 LPWSTR ptr;
3257 DWORD len;
3258
3259 FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwFlags);
3260 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3261 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3262
3263 ptr = strrchrW(mod_path, '\\');
3264 if (ptr) {
3265 strcpyW(ptr+1, new_mod);
3266 TRACE("loading %s\n", debugstr_w(mod_path));
3267 return LoadLibraryW(mod_path);
3268 }
3269 return NULL;
3270 }
3271
3272 /*************************************************************************
3273 * ColorAdjustLuma [SHLWAPI.@]
3274 *
3275 * Adjust the luminosity of a color
3276 *
3277 * PARAMS
3278 * cRGB [I] RGB value to convert
3279 * dwLuma [I] Luma adjustment
3280 * bUnknown [I] Unknown
3281 *
3282 * RETURNS
3283 * The adjusted RGB color.
3284 */
3285 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3286 {
3287 TRACE("(0x%8lx,%d,%d)\n", cRGB, dwLuma, bUnknown);
3288
3289 if (dwLuma)
3290 {
3291 WORD wH, wL, wS;
3292
3293 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3294
3295 FIXME("Ignoring luma adjustment\n");
3296
3297 /* FIXME: The ajdustment is not linear */
3298
3299 cRGB = ColorHLSToRGB(wH, wL, wS);
3300 }
3301 return cRGB;
3302 }
3303
3304 /*************************************************************************
3305 * @ [SHLWAPI.389]
3306 *
3307 * See GetSaveFileNameW.
3308 */
3309 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3310 {
3311 GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
3312 return pGetSaveFileNameW(ofn);
3313 }
3314
3315 /*************************************************************************
3316 * @ [SHLWAPI.390]
3317 *
3318 * See WNetRestoreConnectionW.
3319 */
3320 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3321 {
3322 GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
3323 return pWNetRestoreConnectionW(hwndOwner, lpszDevice);
3324 }
3325
3326 /*************************************************************************
3327 * @ [SHLWAPI.391]
3328 *
3329 * See WNetGetLastErrorW.
3330 */
3331 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3332 LPWSTR lpNameBuf, DWORD nNameBufSize)
3333 {
3334 GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
3335 return pWNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3336 }
3337
3338 /*************************************************************************
3339 * @ [SHLWAPI.401]
3340 *
3341 * See PageSetupDlgW.
3342 */
3343 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3344 {
3345 GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
3346 return pPageSetupDlgW(pagedlg);
3347 }
3348
3349 /*************************************************************************
3350 * @ [SHLWAPI.402]
3351 *
3352 * See PrintDlgW.
3353 */
3354 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3355 {
3356 GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
3357 return pPrintDlgW(printdlg);
3358 }
3359
3360 /*************************************************************************
3361 * @ [SHLWAPI.403]
3362 *
3363 * See GetOpenFileNameW.
3364 */
3365 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3366 {
3367 GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
3368 return pGetOpenFileNameW(ofn);
3369 }
3370
3371 /* INTERNAL: Map from HLS color space to RGB */
3372 static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3373 {
3374 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3375
3376 if (wHue > 160)
3377 return wMid1;
3378 else if (wHue > 120)
3379 wHue = 160 - wHue;
3380 else if (wHue > 40)
3381 return wMid2;
3382
3383 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3384 }
3385
3386 /* Convert to RGB and scale into RGB range (0..255) */
3387 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3388
3389 /*************************************************************************
3390 * ColorHLSToRGB [SHLWAPI.@]
3391 *
3392 * Convert from hls color space into an rgb COLORREF.
3393 *
3394 * PARAMS
3395 * wHue [I] Hue amount
3396 * wLuminosity [I] Luminosity amount
3397 * wSaturation [I] Saturation amount
3398 *
3399 * RETURNS
3400 * A COLORREF representing the converted color.
3401 *
3402 * NOTES
3403 * Input hls values are constrained to the range (0..240).
3404 */
3405 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3406 {
3407 WORD wRed;
3408
3409 if (wSaturation)
3410 {
3411 WORD wGreen, wBlue, wMid1, wMid2;
3412
3413 if (wLuminosity > 120)
3414 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3415 else
3416 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3417
3418 wMid1 = wLuminosity * 2 - wMid2;
3419
3420 wRed = GET_RGB(wHue + 80);
3421 wGreen = GET_RGB(wHue);
3422 wBlue = GET_RGB(wHue - 80);
3423
3424 return RGB(wRed, wGreen, wBlue);
3425 }
3426
3427 wRed = wLuminosity * 255 / 240;
3428 return RGB(wRed, wRed, wRed);
3429 }
3430
3431 /*************************************************************************
3432 * @ [SHLWAPI.413]
3433 *
3434 * Get the current docking status of the system.
3435 *
3436 * PARAMS
3437 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3438 *
3439 * RETURNS
3440 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3441 * a notebook.
3442 */
3443 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3444 {
3445 HW_PROFILE_INFOA hwInfo;
3446
3447 TRACE("(0x%08lx)\n", dwFlags);
3448
3449 GetCurrentHwProfileA(&hwInfo);
3450 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3451 {
3452 case DOCKINFO_DOCKED:
3453 case DOCKINFO_UNDOCKED:
3454 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3455 default:
3456 return 0;
3457 }
3458 }
3459
3460 /*************************************************************************
3461 * @ [SHLWAPI.418]
3462 *
3463 * Function seems to do FreeLibrary plus other things.
3464 *
3465 * FIXME native shows the following calls:
3466 * RtlEnterCriticalSection
3467 * LocalFree
3468 * GetProcAddress(Comctl32??, 150L)
3469 * DPA_DeletePtr
3470 * RtlLeaveCriticalSection
3471 * followed by the FreeLibrary.
3472 * The above code may be related to .377 above.
3473 */
3474 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3475 {
3476 FIXME("(%p) semi-stub\n", hModule);
3477 return FreeLibrary(hModule);
3478 }
3479
3480 /*************************************************************************
3481 * @ [SHLWAPI.419]
3482 */
3483 BOOL WINAPI SHFlushSFCacheWrap(void) {
3484 FIXME(": stub\n");
3485 return TRUE;
3486 }
3487
3488 /*************************************************************************
3489 * @ [SHLWAPI.429]
3490 * FIXME I have no idea what this function does or what its arguments are.
3491 */
3492 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3493 {
3494 FIXME("(%p) stub\n", hInst);
3495 return FALSE;
3496 }
3497
3498
3499 /*************************************************************************
3500 * @ [SHLWAPI.430]
3501 */
3502 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3503 {
3504 FIXME("(%p,%p) stub\n", hInst, hHeap);
3505 return E_FAIL; /* This is what is used if shlwapi not loaded */
3506 }
3507
3508 /*************************************************************************
3509 * @ [SHLWAPI.431]
3510 */
3511 DWORD WINAPI MLClearMLHInstance(DWORD x)
3512 {
3513 FIXME("(0x%08lx)stub\n", x);
3514 return 0xabba1247;
3515 }
3516
3517 /*************************************************************************
3518 * @ [SHLWAPI.436]
3519 *
3520 * Convert an Unicode string CLSID into a CLSID.
3521 *
3522 * PARAMS
3523 * idstr [I] string containing a CLSID in text form
3524 * id [O] CLSID extracted from the string
3525 *
3526 * RETURNS
3527 * S_OK on success or E_INVALIDARG on failure
3528 *
3529 * NOTES
3530 * This is really CLSIDFromString() which is exported by ole32.dll,
3531 * however the native shlwapi.dll does *not* import ole32. Nor does
3532 * ole32.dll import this ordinal from shlwapi. Therefore we must conclude
3533 * that MS duplicated the code for CLSIDFromString(), and yes they did, only
3534 * it returns an E_INVALIDARG error code on failure.
3535 * This is a duplicate (with changes for Unicode) of CLSIDFromString16()
3536 * in "dlls/ole32/compobj.c".
3537 */
3538 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3539 {
3540 LPCWSTR s = idstr;
3541 BYTE *p;
3542 INT i;
3543 WCHAR table[256];
3544
3545 if (!s) {
3546 memset(id, 0, sizeof(CLSID));
3547 return S_OK;
3548 }
3549 else { /* validate the CLSID string */
3550
3551 if (strlenW(s) != 38)
3552 return E_INVALIDARG;
3553
3554 if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
3555 return E_INVALIDARG;
3556
3557 for (i=1; i<37; i++)
3558 {
3559 if ((i == 9)||(i == 14)||(i == 19)||(i == 24))
3560 continue;
3561 if (!(((s[i] >= L'0') && (s[i] <= L'9')) ||
3562 ((s[i] >= L'a') && (s[i] <= L'f')) ||
3563 ((s[i] >= L'A') && (s[i] <= L'F')))
3564 )
3565 return E_INVALIDARG;
3566 }
3567 }
3568
3569 TRACE("%s -> %p\n", debugstr_w(s), id);
3570
3571 /* quick lookup table */
3572 memset(table, 0, 256*sizeof(WCHAR));
3573
3574 for (i = 0; i < 10; i++) {
3575 table['0' + i] = i;
3576 }
3577 for (i = 0; i < 6; i++) {
3578 table['A' + i] = i+10;
3579 table['a' + i] = i+10;
3580 }
3581
3582 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
3583
3584 p = (BYTE *) id;
3585
3586 s++; /* skip leading brace */
3587 for (i = 0; i < 4; i++) {
3588 p[3 - i] = table[*s]<<4 | table[*(s+1)];
3589 s += 2;
3590 }
3591 p += 4;
3592 s++; /* skip - */
3593
3594 for (i = 0; i < 2; i++) {
3595 p[1-i] = table[*s]<<4 | table[*(s+1)];
3596 s += 2;
3597 }
3598 p += 2;
3599 s++; /* skip - */
3600
3601 for (i = 0; i < 2; i++) {
3602 p[1-i] = table[*s]<<4 | table[*(s+1)];
3603 s += 2;
3604 }
3605 p += 2;
3606 s++; /* skip - */
3607
3608 /* these are just sequential bytes */
3609 for (i = 0; i < 2; i++) {
3610 *p++ = table[*s]<<4 | table[*(s+1)];
3611 s += 2;
3612 }
3613 s++; /* skip - */
3614
3615 for (i = 0; i < 6; i++) {
3616 *p++ = table[*s]<<4 | table[*(s+1)];
3617 s += 2;
3618 }
3619
3620 return S_OK;
3621 }
3622
3623 /*************************************************************************
3624 * @ [SHLWAPI.437]
3625 *
3626 * Determine if the OS supports a given feature.
3627 *
3628 * PARAMS
3629 * dwFeature [I] Feature requested (undocumented)
3630 *
3631 * RETURNS
3632 * TRUE If the feature is available.
3633 * FALSE If the feature is not available.
3634 */
3635 BOOL WINAPI IsOS(DWORD feature)
3636 {
3637 OSVERSIONINFOA osvi;
3638 DWORD platform, majorv, minorv;
3639
3640 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3641 if(!GetVersionExA(&osvi)) {
3642 ERR("GetVersionEx failed");
3643 return FALSE;
3644 }
3645
3646 majorv = osvi.dwMajorVersion;
3647 minorv = osvi.dwMinorVersion;
3648 platform = osvi.dwPlatformId;
3649
3650 #define ISOS_RETURN(x) \
3651 TRACE("(0x%lx) ret=%d\n",feature,(x)); \
3652 return (x);
3653
3654 switch(feature) {
3655 case OS_WIN32SORGREATER:
3656 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3657 || platform == VER_PLATFORM_WIN32_WINDOWS)
3658 case OS_NT:
3659 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3660 case OS_WIN95ORGREATER:
3661 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3662 case OS_NT4ORGREATER:
3663 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3664 case OS_WIN2000ORGREATER_ALT:
3665 case OS_WIN2000ORGREATER:
3666 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3667 case OS_WIN98ORGREATER:
3668 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3669 case OS_WIN98_GOLD:
3670 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3671 case OS_WIN2000PRO:
3672 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3673 case OS_WIN2000SERVER:
3674 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3675 case OS_WIN2000ADVSERVER:
3676 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3677 case OS_WIN2000DATACENTER:
3678 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3679 case OS_WIN2000TERMINAL:
3680 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3681 case OS_EMBEDDED:
3682 FIXME("(OS_EMBEDDED) What should we return here?\n");
3683 return FALSE;
3684 case OS_TERMINALCLIENT:
3685 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3686 return FALSE;
3687 case OS_TERMINALREMOTEADMIN:
3688 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3689 return FALSE;
3690 case OS_WIN95_GOLD:
3691 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3692 case OS_MEORGREATER:
3693 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3694 case OS_XPORGREATER:
3695 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3696 case OS_HOME:
3697 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3698 case OS_PROFESSIONAL:
3699 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3700 case OS_DATACENTER:
3701 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3702 case OS_ADVSERVER:
3703 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3704 case OS_SERVER:
3705 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3706 case OS_TERMINALSERVER:
3707 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3708 case OS_PERSONALTERMINALSERVER:
3709 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3710 case OS_FASTUSERSWITCHING:
3711 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3712 return TRUE;
3713 case OS_WELCOMELOGONUI:
3714 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3715 return FALSE;
3716 case OS_DOMAINMEMBER:
3717 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3718 return TRUE;
3719 case OS_ANYSERVER:
3720 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3721 case OS_WOW6432:
3722 FIXME("(OS_WOW6432) Should we check this?\n");
3723 return FALSE;
3724 case OS_WEBSERVER:
3725 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3726 case OS_SMALLBUSINESSSERVER:
3727 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3728 case OS_TABLETPC:
3729 FIXME("(OS_TABLEPC) What should we return here?\n");
3730 return FALSE;
3731 case OS_SERVERADMINUI:
3732 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3733 return FALSE;
3734 case OS_MEDIACENTER:
3735 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3736 return FALSE;
3737 case OS_APPLIANCE:
3738 FIXME("(OS_APPLIANCE) What should we return here?\n");
3739 return FALSE;
3740 }
3741
3742 #undef ISOS_RETURN
3743
3744 WARN("(0x%lx) unknown parameter\n",feature);
3745
3746 return FALSE;
3747 }
3748
3749 /*************************************************************************
3750 * ColorRGBToHLS [SHLWAPI.@]
3751 *
3752 * Convert an rgb COLORREF into the hls color space.
3753 *
3754 * PARAMS
3755 * cRGB [I] Source rgb value
3756 * pwHue [O] Destination for converted hue
3757 * pwLuminance [O] Destination for converted luminance
3758 * pwSaturation [O] Destination for converted saturation
3759 *
3760 * RETURNS
3761 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
3762 * values.
3763 *
3764 * NOTES
3765 * Output HLS values are constrained to the range (0..240).
3766 * For Achromatic conversions, Hue is set to 160.
3767 */
3768 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
3769 LPWORD pwLuminance, LPWORD pwSaturation)
3770 {
3771 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
3772
3773 TRACE("(%08lx,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
3774
3775 wR = GetRValue(cRGB);
3776 wG = GetGValue(cRGB);
3777 wB = GetBValue(cRGB);
3778
3779 wMax = max(wR, max(wG, wB));
3780 wMin = min(wR, min(wG, wB));
3781
3782 /* Luminosity */
3783 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
3784
3785 if (wMax == wMin)
3786 {
3787 /* Achromatic case */
3788 wSaturation = 0;
3789 /* Hue is now unrepresentable, but this is what native returns... */
3790 wHue = 160;
3791 }
3792 else
3793 {
3794 /* Chromatic case */
3795 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
3796
3797 /* Saturation */
3798 if (wLuminosity <= 120)
3799 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
3800 else
3801 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
3802
3803 /* Hue */
3804 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
3805 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
3806 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
3807
3808 if (wR == wMax)
3809 wHue = wBNorm - wGNorm;
3810 else if (wG == wMax)
3811 wHue = 80 + wRNorm - wBNorm;
3812 else
3813 wHue = 160 + wGNorm - wRNorm;
3814 if (wHue < 0)
3815 wHue += 240;
3816 else if (wHue > 240)
3817 wHue -= 240;
3818 }
3819 if (pwHue)
3820 *pwHue = wHue;
3821 if (pwLuminance)
3822 *pwLuminance = wLuminosity;
3823 if (pwSaturation)
3824 *pwSaturation = wSaturation;
3825 }