ccc95b6348262a01350467ce886c21ad9f6ae282
[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.188]
1852 *
1853 * Call IOleControlSite_TranslateAccelerator() on an object.
1854 *
1855 * PARAMS
1856 * lpUnknown [I] Object supporting the IOleControlSite interface.
1857 * lpMsg [I] Key message to be processed.
1858 * dwModifiers [I] Flags containing the state of the modifier keys.
1859 *
1860 * RETURNS
1861 * Success: S_OK.
1862 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1863 */
1864 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1865 {
1866 IOleControlSite* lpCSite = NULL;
1867 HRESULT hRet = E_INVALIDARG;
1868
1869 TRACE("(%p,%p,0x%08lx)\n", lpUnknown, lpMsg, dwModifiers);
1870 if (lpUnknown)
1871 {
1872 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1873 (void**)&lpCSite);
1874 if (SUCCEEDED(hRet) && lpCSite)
1875 {
1876 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1877 IOleControlSite_Release(lpCSite);
1878 }
1879 }
1880 return hRet;
1881 }
1882
1883
1884 /*************************************************************************
1885 * @ [SHLWAPI.189]
1886 *
1887 * Call IOleControlSite_GetExtendedControl() on an object.
1888 *
1889 * PARAMS
1890 * lpUnknown [I] Object supporting the IOleControlSite interface.
1891 * lppDisp [O] Destination for resulting IDispatch.
1892 *
1893 * RETURNS
1894 * Success: S_OK.
1895 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1896 */
1897 DWORD WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, IDispatch** lppDisp)
1898 {
1899 IOleControlSite* lpCSite = NULL;
1900 HRESULT hRet = E_FAIL;
1901
1902 TRACE("(%p,%p)\n", lpUnknown, lppDisp);
1903 if (lpUnknown)
1904 {
1905 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1906 (void**)&lpCSite);
1907 if (SUCCEEDED(hRet) && lpCSite)
1908 {
1909 hRet = IOleControlSite_GetExtendedControl(lpCSite, lppDisp);
1910 IOleControlSite_Release(lpCSite);
1911 }
1912 }
1913 return hRet;
1914 }
1915
1916 /*************************************************************************
1917 * @ [SHLWAPI.190]
1918 */
1919 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1920 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1921 {
1922 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1923 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1924 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1925 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1926 HRESULT hRet = E_INVALIDARG;
1927 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1928
1929 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1930
1931 if (lpUnknown && lpArg4)
1932 {
1933 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1934 (REFGUID)function_id, (void**)&lpUnkInner);
1935
1936 if (SUCCEEDED(hRet) && lpUnkInner)
1937 {
1938 /* FIXME: The type of service object requested is unknown, however
1939 * testing shows that its first method is called with 4 parameters.
1940 * Fake this by using IParseDisplayName_ParseDisplayName since the
1941 * signature and position in the vtable matches our unknown object type.
1942 */
1943 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1944 lpArg1, lpArg2, lpArg3, lpArg4);
1945 IUnknown_Release(lpUnkInner);
1946 }
1947 }
1948 return hRet;
1949 }
1950
1951 /*************************************************************************
1952 * @ [SHLWAPI.192]
1953 *
1954 * Get a sub-menu from a menu item.
1955 *
1956 * PARAMS
1957 * hMenu [I] Menu to get sub-menu from
1958 * uID [I] ID of menu item containing sub-menu
1959 *
1960 * RETURNS
1961 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1962 */
1963 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1964 {
1965 MENUITEMINFOA mi;
1966
1967 TRACE("(%p,%uld)\n", hMenu, uID);
1968
1969 mi.cbSize = sizeof(MENUITEMINFOA);
1970 mi.fMask = MIIM_SUBMENU;
1971
1972 if (!GetMenuItemInfoA(hMenu, uID, 0, &mi))
1973 return NULL;
1974
1975 return mi.hSubMenu;
1976 }
1977
1978 /*************************************************************************
1979 * @ [SHLWAPI.193]
1980 *
1981 * Get the color depth of the primary display.
1982 *
1983 * PARAMS
1984 * None.
1985 *
1986 * RETURNS
1987 * The color depth of the primary display.
1988 */
1989 DWORD WINAPI SHGetCurColorRes()
1990 {
1991 HDC hdc;
1992 DWORD ret;
1993
1994 TRACE("()\n");
1995
1996 hdc = GetDC(0);
1997 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1998 ReleaseDC(0, hdc);
1999 return ret;
2000 }
2001
2002 /*************************************************************************
2003 * @ [SHLWAPI.194]
2004 *
2005 * Wait for a message to arrive, with a timeout.
2006 *
2007 * PARAMS
2008 * hand [I] Handle to query
2009 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
2010 *
2011 * RETURNS
2012 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
2013 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
2014 * message is available.
2015 */
2016 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
2017 {
2018 DWORD dwEndTicks = GetTickCount() + dwTimeout;
2019 DWORD dwRet;
2020
2021 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
2022 {
2023 MSG msg;
2024
2025 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
2026
2027 if (dwTimeout != INFINITE)
2028 {
2029 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
2030 return WAIT_TIMEOUT;
2031 }
2032 }
2033
2034 return dwRet;
2035 }
2036
2037 /*************************************************************************
2038 * @ [SHLWAPI.195]
2039 *
2040 * Determine if a shell folder can be expanded.
2041 *
2042 * PARAMS
2043 * lpFolder [I] Parent folder containing the object to test.
2044 * pidl [I] Id of the object to test.
2045 *
2046 * RETURNS
2047 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2048 * Failure: E_INVALIDARG, if any argument is invalid.
2049 *
2050 * NOTES
2051 * If the object to be tested does not expose the IQueryInfo() interface it
2052 * will not be identified as an expandable folder.
2053 */
2054 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
2055 {
2056 HRESULT hRet = E_INVALIDARG;
2057 IQueryInfo *lpInfo;
2058
2059 if (lpFolder && pidl)
2060 {
2061 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
2062 NULL, (void**)&lpInfo);
2063 if (FAILED(hRet))
2064 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
2065 else
2066 {
2067 DWORD dwFlags = 0;
2068
2069 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2070 * currently used". Really? You wouldn't be holding out on me would you?
2071 */
2072 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
2073
2074 if (SUCCEEDED(hRet))
2075 {
2076 /* 0x2 is an undocumented flag apparently indicating expandability */
2077 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
2078 }
2079
2080 IQueryInfo_Release(lpInfo);
2081 }
2082 }
2083 return hRet;
2084 }
2085
2086 /*************************************************************************
2087 * @ [SHLWAPI.197]
2088 *
2089 * Blank out a region of text by drawing the background only.
2090 *
2091 * PARAMS
2092 * hDC [I] Device context to draw in
2093 * pRect [I] Area to draw in
2094 * cRef [I] Color to draw in
2095 *
2096 * RETURNS
2097 * Nothing.
2098 */
2099 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2100 {
2101 COLORREF cOldColor = SetBkColor(hDC, cRef);
2102 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2103 SetBkColor(hDC, cOldColor);
2104 return 0;
2105 }
2106
2107 /*************************************************************************
2108 * @ [SHLWAPI.198]
2109 *
2110 * Return the value asociated with a key in a map.
2111 *
2112 * PARAMS
2113 * lpKeys [I] A list of keys of length iLen
2114 * lpValues [I] A list of values associated with lpKeys, of length iLen
2115 * iLen [I] Length of both lpKeys and lpValues
2116 * iKey [I] The key value to look up in lpKeys
2117 *
2118 * RETURNS
2119 * The value in lpValues associated with iKey, or -1 if iKey is not
2120 * found in lpKeys.
2121 *
2122 * NOTES
2123 * - If two elements in the map share the same key, this function returns
2124 * the value closest to the start of the map
2125 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2126 */
2127 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2128 {
2129 if (lpKeys && lpValues)
2130 {
2131 int i = 0;
2132
2133 while (i < iLen)
2134 {
2135 if (lpKeys[i] == iKey)
2136 return lpValues[i]; /* Found */
2137 i++;
2138 }
2139 }
2140 return -1; /* Not found */
2141 }
2142
2143
2144 /*************************************************************************
2145 * @ [SHLWAPI.199]
2146 *
2147 * Copy an interface pointer
2148 *
2149 * PARAMS
2150 * lppDest [O] Destination for copy
2151 * lpUnknown [I] Source for copy
2152 *
2153 * RETURNS
2154 * Nothing.
2155 */
2156 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2157 {
2158 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2159
2160 if (lppDest)
2161 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2162
2163 if (lpUnknown)
2164 {
2165 /* Copy */
2166 IUnknown_AddRef(lpUnknown);
2167 *lppDest = lpUnknown;
2168 }
2169 }
2170
2171 /*************************************************************************
2172 * @ [SHLWAPI.200]
2173 *
2174 */
2175 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2176 REFGUID riidCmdGrp, ULONG cCmds,
2177 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2178 {
2179 FIXME("(%p,%p,%p,%ld,%p,%p) - stub\n",
2180 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2181
2182 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2183 return DRAGDROP_E_NOTREGISTERED;
2184 }
2185
2186 /*************************************************************************
2187 * @ [SHLWAPI.201]
2188 *
2189 */
2190 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2191 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2192 VARIANT* pvaOut)
2193 {
2194 FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2195 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2196 return DRAGDROP_E_NOTREGISTERED;
2197 }
2198
2199 /*************************************************************************
2200 * @ [SHLWAPI.202]
2201 *
2202 */
2203 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2204 {
2205 FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2206 return DRAGDROP_E_NOTREGISTERED;
2207 }
2208
2209 /*************************************************************************
2210 * @ [SHLWAPI.204]
2211 *
2212 * Determine if a window is not a child of another window.
2213 *
2214 * PARAMS
2215 * hParent [I] Suspected parent window
2216 * hChild [I] Suspected child window
2217 *
2218 * RETURNS
2219 * TRUE: If hChild is a child window of hParent
2220 * FALSE: If hChild is not a child window of hParent, or they are equal
2221 */
2222 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2223 {
2224 TRACE("(%p,%p)\n", hParent, hChild);
2225
2226 if (!hParent || !hChild)
2227 return TRUE;
2228 else if(hParent == hChild)
2229 return FALSE;
2230 return !IsChild(hParent, hChild);
2231 }
2232
2233 /*************************************************************************
2234 * @ [SHLWAPI.208]
2235 *
2236 * Some sort of memory management process.
2237 */
2238 DWORD WINAPI FDSA_Initialize(
2239 DWORD a,
2240 DWORD b,
2241 LPVOID c,
2242 LPVOID d,
2243 DWORD e)
2244 {
2245 FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
2246 a, b, c, d, e);
2247 return 1;
2248 }
2249
2250 /*************************************************************************
2251 * @ [SHLWAPI.209]
2252 *
2253 * Some sort of memory management process.
2254 */
2255 DWORD WINAPI FDSA_Destroy(
2256 LPVOID a)
2257 {
2258 FIXME("(%p) stub\n",
2259 a);
2260 return 1;
2261 }
2262
2263 /*************************************************************************
2264 * @ [SHLWAPI.210]
2265 *
2266 * Some sort of memory management process.
2267 */
2268 DWORD WINAPI FDSA_InsertItem(
2269 LPVOID a,
2270 DWORD b,
2271 LPVOID c)
2272 {
2273 FIXME("(%p 0x%08lx %p) stub\n",
2274 a, b, c);
2275 return 0;
2276 }
2277
2278 /*************************************************************************
2279 * @ [SHLWAPI.211]
2280 */
2281 DWORD WINAPI FDSA_DeleteItem(
2282 LPVOID a,
2283 DWORD b)
2284 {
2285 FIXME("(%p 0x%08lx) stub\n",
2286 a, b);
2287 return 1;
2288 }
2289
2290 typedef struct {
2291 REFIID refid;
2292 DWORD indx;
2293 } IFACE_INDEX_TBL;
2294
2295 /*************************************************************************
2296 * @ [SHLWAPI.219]
2297 *
2298 * Call IUnknown_QueryInterface() on a table of objects.
2299 *
2300 * RETURNS
2301 * Success: S_OK.
2302 * Failure: E_POINTER or E_NOINTERFACE.
2303 */
2304 HRESULT WINAPI QISearch(
2305 LPVOID w, /* [in] Table of interfaces */
2306 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2307 REFIID riid, /* [in] REFIID to get interface for */
2308 LPVOID *ppv) /* [out] Destination for interface pointer */
2309 {
2310 HRESULT ret;
2311 IUnknown *a_vtbl;
2312 IFACE_INDEX_TBL *xmove;
2313
2314 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2315 if (ppv) {
2316 xmove = x;
2317 while (xmove->refid) {
2318 TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2319 if (IsEqualIID(riid, xmove->refid)) {
2320 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2321 TRACE("matched, returning (%p)\n", a_vtbl);
2322 *ppv = (LPVOID)a_vtbl;
2323 IUnknown_AddRef(a_vtbl);
2324 return S_OK;
2325 }
2326 xmove++;
2327 }
2328
2329 if (IsEqualIID(riid, &IID_IUnknown)) {
2330 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2331 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2332 *ppv = (LPVOID)a_vtbl;
2333 IUnknown_AddRef(a_vtbl);
2334 return S_OK;
2335 }
2336 *ppv = 0;
2337 ret = E_NOINTERFACE;
2338 } else
2339 ret = E_POINTER;
2340
2341 TRACE("-- 0x%08lx\n", ret);
2342 return ret;
2343 }
2344
2345 /*************************************************************************
2346 * @ [SHLWAPI.221]
2347 *
2348 * Remove the "PropDlgFont" property from a window.
2349 *
2350 * PARAMS
2351 * hWnd [I] Window to remove the property from
2352 *
2353 * RETURNS
2354 * A handle to the removed property, or NULL if it did not exist.
2355 */
2356 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2357 {
2358 HANDLE hProp;
2359
2360 TRACE("(%p)\n", hWnd);
2361
2362 hProp = GetPropA(hWnd, "PropDlgFont");
2363
2364 if(hProp)
2365 {
2366 DeleteObject(hProp);
2367 hProp = RemovePropA(hWnd, "PropDlgFont");
2368 }
2369 return hProp;
2370 }
2371
2372 /*************************************************************************
2373 * @ [SHLWAPI.236]
2374 *
2375 * Load the in-process server of a given GUID.
2376 *
2377 * PARAMS
2378 * refiid [I] GUID of the server to load.
2379 *
2380 * RETURNS
2381 * Success: A handle to the loaded server dll.
2382 * Failure: A NULL handle.
2383 */
2384 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2385 {
2386 HKEY newkey;
2387 DWORD type, count;
2388 CHAR value[MAX_PATH], string[MAX_PATH];
2389
2390 strcpy(string, "CLSID\\");
2391 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2392 strcat(string, "\\InProcServer32");
2393
2394 count = MAX_PATH;
2395 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2396 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2397 RegCloseKey(newkey);
2398 return LoadLibraryExA(value, 0, 0);
2399 }
2400
2401 /*************************************************************************
2402 * @ [SHLWAPI.237]
2403 *
2404 * Unicode version of SHLWAPI_183.
2405 */
2406 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2407 {
2408 WNDCLASSW WndClass;
2409
2410 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2411
2412 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2413 return TRUE;
2414 return RegisterClassW(lpWndClass);
2415 }
2416
2417 /*************************************************************************
2418 * @ [SHLWAPI.238]
2419 *
2420 * Unregister a list of classes.
2421 *
2422 * PARAMS
2423 * hInst [I] Application instance that registered the classes
2424 * lppClasses [I] List of class names
2425 * iCount [I] Number of names in lppClasses
2426 *
2427 * RETURNS
2428 * Nothing.
2429 */
2430 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2431 {
2432 WNDCLASSA WndClass;
2433
2434 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2435
2436 while (iCount > 0)
2437 {
2438 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2439 UnregisterClassA(*lppClasses, hInst);
2440 lppClasses++;
2441 iCount--;
2442 }
2443 }
2444
2445 /*************************************************************************
2446 * @ [SHLWAPI.239]
2447 *
2448 * Unicode version of SHUnregisterClassesA.
2449 */
2450 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2451 {
2452 WNDCLASSW WndClass;
2453
2454 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2455
2456 while (iCount > 0)
2457 {
2458 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2459 UnregisterClassW(*lppClasses, hInst);
2460 lppClasses++;
2461 iCount--;
2462 }
2463 }
2464
2465 /*************************************************************************
2466 * @ [SHLWAPI.240]
2467 *
2468 * Call The correct (Ascii/Unicode) default window procedure for a window.
2469 *
2470 * PARAMS
2471 * hWnd [I] Window to call the default procedure for
2472 * uMessage [I] Message ID
2473 * wParam [I] WPARAM of message
2474 * lParam [I] LPARAM of message
2475 *
2476 * RETURNS
2477 * The result of calling DefWindowProcA() or DefWindowProcW().
2478 */
2479 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2480 {
2481 if (IsWindowUnicode(hWnd))
2482 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2483 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2484 }
2485
2486 /*************************************************************************
2487 * @ [SHLWAPI.256]
2488 */
2489 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2490 {
2491 HRESULT hRet = E_INVALIDARG;
2492 LPOBJECTWITHSITE lpSite = NULL;
2493
2494 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2495
2496 if (lpUnknown && iid && lppSite)
2497 {
2498 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2499 (void**)&lpSite);
2500 if (SUCCEEDED(hRet) && lpSite)
2501 {
2502 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2503 IObjectWithSite_Release(lpSite);
2504 }
2505 }
2506 return hRet;
2507 }
2508
2509 /*************************************************************************
2510 * @ [SHLWAPI.257]
2511 *
2512 * Create a worker window using CreateWindowExA().
2513 *
2514 * PARAMS
2515 * wndProc [I] Window procedure
2516 * hWndParent [I] Parent window
2517 * dwExStyle [I] Extra style flags
2518 * dwStyle [I] Style flags
2519 * hMenu [I] Window menu
2520 * z [I] Unknown
2521 *
2522 * RETURNS
2523 * Success: The window handle of the newly created window.
2524 * Failure: 0.
2525 */
2526 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2527 DWORD dwStyle, HMENU hMenu, LONG z)
2528 {
2529 static const char* szClass = "WorkerA";
2530 WNDCLASSA wc;
2531 HWND hWnd;
2532
2533 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2534 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2535
2536 /* Create Window class */
2537 wc.style = 0;
2538 wc.lpfnWndProc = DefWindowProcA;
2539 wc.cbClsExtra = 0;
2540 wc.cbWndExtra = 4;
2541 wc.hInstance = shlwapi_hInstance;
2542 wc.hIcon = NULL;
2543 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2544 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2545 wc.lpszMenuName = NULL;
2546 wc.lpszClassName = szClass;
2547
2548 SHRegisterClassA(&wc); /* Register class */
2549
2550 /* FIXME: Set extra bits in dwExStyle */
2551
2552 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2553 hWndParent, hMenu, shlwapi_hInstance, 0);
2554 if (hWnd)
2555 {
2556 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2557
2558 if (wndProc)
2559 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2560 }
2561 return hWnd;
2562 }
2563
2564 typedef struct tagPOLICYDATA
2565 {
2566 DWORD policy; /* flags value passed to SHRestricted */
2567 LPCWSTR appstr; /* application str such as "Explorer" */
2568 LPCWSTR keystr; /* name of the actual registry key / policy */
2569 } POLICYDATA, *LPPOLICYDATA;
2570
2571 #define SHELL_NO_POLICY 0xffffffff
2572
2573 /* default shell policy registry key */
2574 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2575 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2576 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2577 '\\','P','o','l','i','c','i','e','s',0};
2578
2579 /*************************************************************************
2580 * @ [SHLWAPI.271]
2581 *
2582 * Retrieve a policy value from the registry.
2583 *
2584 * PARAMS
2585 * lpSubKey [I] registry key name
2586 * lpSubName [I] subname of registry key
2587 * lpValue [I] value name of registry value
2588 *
2589 * RETURNS
2590 * the value associated with the registry key or 0 if not found
2591 */
2592 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2593 {
2594 DWORD retval, datsize = sizeof(retval);
2595 HKEY hKey;
2596
2597 if (!lpSubKey)
2598 lpSubKey = strRegistryPolicyW;
2599
2600 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2601 if (retval != ERROR_SUCCESS)
2602 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2603 if (retval != ERROR_SUCCESS)
2604 return 0;
2605
2606 SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);
2607 RegCloseKey(hKey);
2608 return retval;
2609 }
2610
2611 /*************************************************************************
2612 * @ [SHLWAPI.266]
2613 *
2614 * Helper function to retrieve the possibly cached value for a specific policy
2615 *
2616 * PARAMS
2617 * policy [I] The policy to look for
2618 * initial [I] Main registry key to open, if NULL use default
2619 * polTable [I] Table of known policies, 0 terminated
2620 * polArr [I] Cache array of policy values
2621 *
2622 * RETURNS
2623 * The retrieved policy value or 0 if not successful
2624 *
2625 * NOTES
2626 * This function is used by the native SHRestricted function to search for the
2627 * policy and cache it once retrieved. The current Wine implementation uses a
2628 * different POLICYDATA structure and implements a similar algorithme adapted to
2629 * that structure.
2630 */
2631 DWORD WINAPI SHRestrictionLookup(
2632 DWORD policy,
2633 LPCWSTR initial,
2634 LPPOLICYDATA polTable,
2635 LPDWORD polArr)
2636 {
2637 TRACE("(0x%08lx %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2638
2639 if (!polTable || !polArr)
2640 return 0;
2641
2642 for (;polTable->policy; polTable++, polArr++)
2643 {
2644 if (policy == polTable->policy)
2645 {
2646 /* we have a known policy */
2647
2648 /* check if this policy has been cached */
2649 if (*polArr == SHELL_NO_POLICY)
2650 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2651 return *polArr;
2652 }
2653 }
2654 /* we don't know this policy, return 0 */
2655 TRACE("unknown policy: (%08lx)\n", policy);
2656 return 0;
2657 }
2658
2659 /*************************************************************************
2660 * @ [SHLWAPI.267]
2661 *
2662 * Get an interface from an object.
2663 *
2664 * RETURNS
2665 * Success: S_OK. ppv contains the requested interface.
2666 * Failure: An HRESULT error code.
2667 *
2668 * NOTES
2669 * This QueryInterface asks the inner object for an interface. In case
2670 * of aggregation this request would be forwarded by the inner to the
2671 * outer object. This function asks the inner object directly for the
2672 * interface circumventing the forwarding to the outer object.
2673 */
2674 HRESULT WINAPI SHWeakQueryInterface(
2675 IUnknown * pUnk, /* [in] Outer object */
2676 IUnknown * pInner, /* [in] Inner object */
2677 IID * riid, /* [in] Interface GUID to query for */
2678 LPVOID* ppv) /* [out] Destination for queried interface */
2679 {
2680 HRESULT hret = E_NOINTERFACE;
2681 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2682
2683 *ppv = NULL;
2684 if(pUnk && pInner) {
2685 hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
2686 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2687 }
2688 TRACE("-- 0x%08lx\n", hret);
2689 return hret;
2690 }
2691
2692 /*************************************************************************
2693 * @ [SHLWAPI.268]
2694 *
2695 * Move a reference from one interface to another.
2696 *
2697 * PARAMS
2698 * lpDest [O] Destination to receive the reference
2699 * lppUnknown [O] Source to give up the reference to lpDest
2700 *
2701 * RETURNS
2702 * Nothing.
2703 */
2704 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2705 {
2706 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2707
2708 if (*lppUnknown)
2709 {
2710 /* Copy Reference*/
2711 IUnknown_AddRef(lpDest);
2712 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2713 }
2714 }
2715
2716 /*************************************************************************
2717 * @ [SHLWAPI.269]
2718 *
2719 * Convert an ASCII string of a CLSID into a CLSID.
2720 *
2721 * PARAMS
2722 * idstr [I] String representing a CLSID in registry format
2723 * id [O] Destination for the converted CLSID
2724 *
2725 * RETURNS
2726 * Success: TRUE. id contains the converted CLSID.
2727 * Failure: FALSE.
2728 */
2729 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2730 {
2731 WCHAR wClsid[40];
2732 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2733 return SUCCEEDED(CLSIDFromStringWrap(wClsid, id));
2734 }
2735
2736 /*************************************************************************
2737 * @ [SHLWAPI.270]
2738 *
2739 * Unicode version of GUIDFromStringA.
2740 */
2741 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2742 {
2743 return SUCCEEDED(CLSIDFromStringWrap(idstr, id));
2744 }
2745
2746 /*************************************************************************
2747 * @ [SHLWAPI.276]
2748 *
2749 * Determine if the browser is integrated into the shell, and set a registry
2750 * key accordingly.
2751 *
2752 * PARAMS
2753 * None.
2754 *
2755 * RETURNS
2756 * 1, If the browser is not integrated.
2757 * 2, If the browser is integrated.
2758 *
2759 * NOTES
2760 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2761 * either set to TRUE, or removed depending on whether the browser is deemed
2762 * to be integrated.
2763 */
2764 DWORD WINAPI WhichPlatform()
2765 {
2766 static LPCSTR szIntegratedBrowser = "IntegratedBrowser";
2767 static DWORD dwState = 0;
2768 HKEY hKey;
2769 DWORD dwRet, dwData, dwSize;
2770
2771 if (dwState)
2772 return dwState;
2773
2774 /* If shell32 exports DllGetVersion(), the browser is integrated */
2775 GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);
2776 dwState = pDllGetVersion ? 2 : 1;
2777
2778 /* Set or delete the key accordingly */
2779 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2780 "Software\\Microsoft\\Internet Explorer", 0,
2781 KEY_ALL_ACCESS, &hKey);
2782 if (!dwRet)
2783 {
2784 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2785 (LPBYTE)&dwData, &dwSize);
2786
2787 if (!dwRet && dwState == 1)
2788 {
2789 /* Value exists but browser is not integrated */
2790 RegDeleteValueA(hKey, szIntegratedBrowser);
2791 }
2792 else if (dwRet && dwState == 2)
2793 {
2794 /* Browser is integrated but value does not exist */
2795 dwData = TRUE;
2796 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2797 (LPBYTE)&dwData, sizeof(dwData));
2798 }
2799 RegCloseKey(hKey);
2800 }
2801 return dwState;
2802 }
2803
2804 /*************************************************************************
2805 * @ [SHLWAPI.278]
2806 *
2807 * Unicode version of SHCreateWorkerWindowA.
2808 */
2809 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2810 DWORD dwStyle, HMENU hMenu, LONG z)
2811 {
2812 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2813 WNDCLASSW wc;
2814 HWND hWnd;
2815
2816 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2817 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2818
2819 /* If our OS is natively ASCII, use the ASCII version */
2820 if (!(GetVersion() & 0x80000000)) /* NT */
2821 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2822
2823 /* Create Window class */
2824 wc.style = 0;
2825 wc.lpfnWndProc = DefWindowProcW;
2826 wc.cbClsExtra = 0;
2827 wc.cbWndExtra = 4;
2828 wc.hInstance = shlwapi_hInstance;
2829 wc.hIcon = NULL;
2830 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2831 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2832 wc.lpszMenuName = NULL;
2833 wc.lpszClassName = szClass;
2834
2835 SHRegisterClassW(&wc); /* Register class */
2836
2837 /* FIXME: Set extra bits in dwExStyle */
2838
2839 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2840 hWndParent, hMenu, shlwapi_hInstance, 0);
2841 if (hWnd)
2842 {
2843 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2844
2845 if (wndProc)
2846 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2847 }
2848 return hWnd;
2849 }
2850
2851 /*************************************************************************
2852 * @ [SHLWAPI.279]
2853 *
2854 * Get and show a context menu from a shell folder.
2855 *
2856 * PARAMS
2857 * hWnd [I] Window displaying the shell folder
2858 * lpFolder [I] IShellFolder interface
2859 * lpApidl [I] Id for the particular folder desired
2860 *
2861 * RETURNS
2862 * Success: S_OK.
2863 * Failure: An HRESULT error code indicating the error.
2864 */
2865 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2866 {
2867 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2868 }
2869
2870 /*************************************************************************
2871 * @ [SHLWAPI.281]
2872 *
2873 * _SHPackDispParamsV
2874 */
2875 HRESULT WINAPI SHPackDispParamsV(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2876 {
2877 FIXME("%p %p %p %p\n",w,x,y,z);
2878 return E_FAIL;
2879 }
2880
2881 /*************************************************************************
2882 * @ [SHLWAPI.282]
2883 *
2884 * This function seems to be a forward to SHPackDispParamsV (whatever THAT
2885 * function does...).
2886 */
2887 HRESULT WINAPI SHPackDispParams(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2888 {
2889 FIXME("%p %p %p %p\n", w, x, y, z);
2890 return E_FAIL;
2891 }
2892
2893 /*************************************************************************
2894 * @ [SHLWAPI.284]
2895 *
2896 * _IConnectionPoint_SimpleInvoke
2897 */
2898 DWORD WINAPI IConnectionPoint_SimpleInvoke(
2899 LPVOID x,
2900 LPVOID y,
2901 LPVOID z)
2902 {
2903 FIXME("(%p %p %p) stub\n",x,y,z);
2904 return 0;
2905 }
2906
2907 /*************************************************************************
2908 * @ [SHLWAPI.285]
2909 *
2910 * Notify an IConnectionPoint object of changes.
2911 *
2912 * PARAMS
2913 * lpCP [I] Object to notify
2914 * dispID [I]
2915 *
2916 * RETURNS
2917 * Success: S_OK.
2918 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
2919 * IConnectionPoint interface.
2920 */
2921 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
2922 {
2923 IEnumConnections *lpEnum;
2924 HRESULT hRet = E_NOINTERFACE;
2925
2926 TRACE("(%p,0x%8lX)\n", lpCP, dispID);
2927
2928 /* Get an enumerator for the connections */
2929 if (lpCP)
2930 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
2931
2932 if (SUCCEEDED(hRet))
2933 {
2934 IPropertyNotifySink *lpSink;
2935 CONNECTDATA connData;
2936 ULONG ulFetched;
2937
2938 /* Call OnChanged() for every notify sink in the connection point */
2939 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
2940 {
2941 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
2942 lpSink)
2943 {
2944 IPropertyNotifySink_OnChanged(lpSink, dispID);
2945 IPropertyNotifySink_Release(lpSink);
2946 }
2947 IUnknown_Release(connData.pUnk);
2948 }
2949
2950 IEnumConnections_Release(lpEnum);
2951 }
2952 return hRet;
2953 }
2954
2955 /*************************************************************************
2956 * @ [SHLWAPI.287]
2957 *
2958 * Notify an IConnectionPointContainer object of changes.
2959 *
2960 * PARAMS
2961 * lpUnknown [I] Object to notify
2962 * dispID [I]
2963 *
2964 * RETURNS
2965 * Success: S_OK.
2966 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
2967 * IConnectionPointContainer interface.
2968 */
2969 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
2970 {
2971 IConnectionPointContainer* lpCPC = NULL;
2972 HRESULT hRet = E_NOINTERFACE;
2973
2974 TRACE("(%p,0x%8lX)\n", lpUnknown, dispID);
2975
2976 if (lpUnknown)
2977 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
2978
2979 if (SUCCEEDED(hRet))
2980 {
2981 IConnectionPoint* lpCP;
2982
2983 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
2984 IConnectionPointContainer_Release(lpCPC);
2985
2986 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
2987 IConnectionPoint_Release(lpCP);
2988 }
2989 return hRet;
2990 }
2991
2992 /*************************************************************************
2993 * @ [SHLWAPI.289]
2994 *
2995 * See PlaySoundW.
2996 */
2997 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
2998 {
2999 GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
3000 return pPlaySoundW(pszSound, hmod, fdwSound);
3001 }
3002
3003 /*************************************************************************
3004 * @ [SHLWAPI.294]
3005 */
3006 BOOL WINAPI SHGetIniStringW(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len, LPCSTR lpStr2)
3007 {
3008 /*
3009 * str1: "I" "I" pushl esp+0x20
3010 * str2: "U" "I" pushl 0x77c93810
3011 * (is "I" and "U" "integer" and "unsigned" ??)
3012 *
3013 * pStr: "" "" pushl eax
3014 * some_len: 0x824 0x104 pushl 0x824
3015 * lpStr2: "%l" "%l" pushl esp+0xc
3016 *
3017 * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
3018 * LocalAlloc(0x00, some_len) -> irrelevant_var
3019 * LocalAlloc(0x40, irrelevant_len) -> pStr
3020 * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
3021 * shlwapi.PathRemoveBlanksW(pStr);
3022 */
3023 FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
3024 return TRUE;
3025 }
3026
3027 /*************************************************************************
3028 * @ [SHLWAPI.295]
3029 *
3030 * Called by ICQ2000b install via SHDOCVW:
3031 * str1: "InternetShortcut"
3032 * x: some unknown pointer
3033 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
3034 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
3035 *
3036 * In short: this one maybe creates a desktop link :-)
3037 */
3038 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
3039 {
3040 FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
3041 return TRUE;
3042 }
3043
3044 /*************************************************************************
3045 * @ [SHLWAPI.299]
3046 *
3047 * See COMCTL32_417.
3048 */
3049 BOOL WINAPI ExtTextOutWrapW(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
3050 LPCWSTR str, UINT count, const INT *lpDx)
3051 {
3052 GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);
3053 return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);
3054 }
3055
3056 /*************************************************************************
3057 * @ [SHLWAPI.313]
3058 *
3059 * See SHGetFileInfoW.
3060 */
3061 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3062 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3063 {
3064 GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
3065 return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3066 }
3067
3068 /*************************************************************************
3069 * @ [SHLWAPI.318]
3070 *
3071 * See DragQueryFileW.
3072 */
3073 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3074 {
3075 GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
3076 return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
3077 }
3078
3079 /*************************************************************************
3080 * @ [SHLWAPI.333]
3081 *
3082 * See SHBrowseForFolderW.
3083 */
3084 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3085 {
3086 GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
3087 return pSHBrowseForFolderW(lpBi);
3088 }
3089
3090 /*************************************************************************
3091 * @ [SHLWAPI.334]
3092 *
3093 * See SHGetPathFromIDListW.
3094 */
3095 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3096 {
3097 GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
3098 return pSHGetPathFromIDListW(pidl, pszPath);
3099 }
3100
3101 /*************************************************************************
3102 * @ [SHLWAPI.335]
3103 *
3104 * See ShellExecuteExW.
3105 */
3106 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3107 {
3108 GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
3109 return pShellExecuteExW(lpExecInfo);
3110 }
3111
3112 /*************************************************************************
3113 * @ [SHLWAPI.336]
3114 *
3115 * See SHFileOperationW.
3116 */
3117 HICON WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3118 {
3119 GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
3120 return pSHFileOperationW(lpFileOp);
3121 }
3122
3123 /*************************************************************************
3124 * @ [SHLWAPI.337]
3125 *
3126 * See ExtractIconExW.
3127 */
3128 UINT WINAPI ExtractIconExWrapW(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
3129 HICON *phiconSmall, UINT nIcons)
3130 {
3131 GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", 0);
3132 return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
3133 }
3134
3135 /*************************************************************************
3136 * @ [SHLWAPI.342]
3137 *
3138 */
3139 LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
3140 {
3141 return InterlockedCompareExchange(dest, xchg, compare);
3142 }
3143
3144 /*************************************************************************
3145 * @ [SHLWAPI.350]
3146 *
3147 * See GetFileVersionInfoSizeW.
3148 */
3149 DWORD WINAPI GetFileVersionInfoSizeWrapW(
3150 LPWSTR x,
3151 LPVOID y)
3152 {
3153 DWORD ret;
3154
3155 GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
3156 ret = pGetFileVersionInfoSizeW(x, y);
3157 return 0x208 + ret;
3158 }
3159
3160 /*************************************************************************
3161 * @ [SHLWAPI.351]
3162 *
3163 * See GetFileVersionInfoW.
3164 */
3165 BOOL WINAPI GetFileVersionInfoWrapW(
3166 LPWSTR w, /* [in] path to dll */
3167 DWORD x, /* [in] parm 2 to GetFileVersionInfoA */
3168 DWORD y, /* [in] return value from SHLWAPI_350() - assume length */
3169 LPVOID z) /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA()) */
3170 {
3171 GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
3172 return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);
3173 }
3174
3175 /*************************************************************************
3176 * @ [SHLWAPI.352]
3177 *
3178 * See VerQueryValueW.
3179 */
3180 WORD WINAPI VerQueryValueWrapW(
3181 LPVOID w, /* [in] Buffer from SHLWAPI_351() */
3182 LPWSTR x, /* [in] Value to retrieve - converted and passed to VerQueryValueA() as #2 */
3183 LPVOID y, /* [out] Ver buffer - passed to VerQueryValueA as #3 */
3184 UINT* z) /* [in] Ver length - passed to VerQueryValueA as #4 */
3185 {
3186 GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
3187 return pVerQueryValueW((char*)w+0x208, x, y, z);
3188 }
3189
3190 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3191 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3192 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3193
3194 /*************************************************************************
3195 * @ [SHLWAPI.355]
3196 *
3197 * Change the modality of a shell object.
3198 *
3199 * PARAMS
3200 * lpUnknown [I] Object to make modeless
3201 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3202 *
3203 * RETURNS
3204 * Success: S_OK. The modality lpUnknown is changed.
3205 * Failure: An HRESULT error code indicating the error.
3206 *
3207 * NOTES
3208 * lpUnknown must support the IOleInPlaceFrame interface, the
3209 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3210 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3211 * or this call will fail.
3212 */
3213 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3214 {
3215 IUnknown *lpObj;
3216 HRESULT hRet;
3217
3218 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3219
3220 if (!lpUnknown)
3221 return E_FAIL;
3222
3223 if (IsIface(IOleInPlaceActiveObject))
3224 EnableModeless(IOleInPlaceActiveObject);
3225 else if (IsIface(IOleInPlaceFrame))
3226 EnableModeless(IOleInPlaceFrame);
3227 else if (IsIface(IShellBrowser))
3228 EnableModeless(IShellBrowser);
3229 #if 0
3230 /* FIXME: Wine has no headers for these objects yet */
3231 else if (IsIface(IInternetSecurityMgrSite))
3232 EnableModeless(IInternetSecurityMgrSite);
3233 else if (IsIface(IDocHostUIHandler))
3234 EnableModeless(IDocHostUIHandler);
3235 #endif
3236 else
3237 return hRet;
3238
3239 IUnknown_Release(lpObj);
3240 return S_OK;
3241 }
3242
3243 /*************************************************************************
3244 * @ [SHLWAPI.357]
3245 *
3246 * See SHGetNewLinkInfoW.
3247 */
3248 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3249 BOOL *pfMustCopy, UINT uFlags)
3250 {
3251 GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
3252 return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3253 }
3254
3255 /*************************************************************************
3256 * @ [SHLWAPI.358]
3257 *
3258 * See SHDefExtractIconW.
3259 */
3260 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3261 HICON* phiconSmall, UINT nIconSize)
3262 {
3263 GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
3264 return pSHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3265 }
3266
3267 /*************************************************************************
3268 * @ [SHLWAPI.363]
3269 *
3270 * Get and show a context menu from a shell folder.
3271 *
3272 * PARAMS
3273 * hWnd [I] Window displaying the shell folder
3274 * lpFolder [I] IShellFolder interface
3275 * lpApidl [I] Id for the particular folder desired
3276 * bInvokeDefault [I] Whether to invoke the default menu item
3277 *
3278 * RETURNS
3279 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3280 * executed.
3281 * Failure: An HRESULT error code indicating the error.
3282 */
3283 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3284 {
3285 IContextMenu *iContext;
3286 HRESULT hRet = E_FAIL;
3287
3288 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3289
3290 if (!lpFolder)
3291 return hRet;
3292
3293 /* Get the context menu from the shell folder */
3294 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3295 &IID_IContextMenu, 0, (void**)&iContext);
3296 if (SUCCEEDED(hRet))
3297 {
3298 HMENU hMenu;
3299 if ((hMenu = CreatePopupMenu()))
3300 {
3301 HRESULT hQuery;
3302 DWORD dwDefaultId = 0;
3303
3304 /* Add the context menu entries to the popup */
3305 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3306 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3307
3308 if (SUCCEEDED(hQuery))
3309 {
3310 if (bInvokeDefault &&
3311 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3312 {
3313 CMINVOKECOMMANDINFO cmIci;
3314 /* Invoke the default item */
3315 memset(&cmIci,0,sizeof(cmIci));
3316 cmIci.cbSize = sizeof(cmIci);
3317 cmIci.fMask = CMIC_MASK_ASYNCOK;
3318 cmIci.hwnd = hWnd;
3319 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3320 cmIci.nShow = SW_SCROLLCHILDREN;
3321
3322 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3323 }
3324 }
3325 DestroyMenu(hMenu);
3326 }
3327 IContextMenu_Release(iContext);
3328 }
3329 return hRet;
3330 }
3331
3332 /*************************************************************************
3333 * @ [SHLWAPI.370]
3334 *
3335 * See ExtractIconW.
3336 */
3337 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3338 UINT nIconIndex)
3339 {
3340 GET_FUNC(pExtractIconW, shell32, "ExtractIconW", NULL);
3341 return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3342 }
3343
3344 /*************************************************************************
3345 * @ [SHLWAPI.376]
3346 */
3347 LANGID WINAPI MLGetUILanguage()
3348 {
3349 FIXME("() stub\n");
3350 /* FIXME: This should be a forward in the .spec file to the win2k function
3351 * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
3352 */
3353 return GetUserDefaultLangID();
3354 }
3355
3356 /*************************************************************************
3357 * @ [SHLWAPI.377]
3358 *
3359 * Load a library from the directory of a particular process.
3360 *
3361 * PARAMS
3362 * new_mod [I] Library name
3363 * inst_hwnd [I] Module whose directory is to be used
3364 * dwFlags [I] Flags controlling the load
3365 *
3366 * RETURNS
3367 * Success: A handle to the loaded module
3368 * Failure: A NULL handle.
3369 */
3370 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3371 {
3372 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3373 * each call here.
3374 * FIXME: Native shows calls to:
3375 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3376 * CheckVersion
3377 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3378 * RegQueryValueExA for "LPKInstalled"
3379 * RegCloseKey
3380 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3381 * RegQueryValueExA for "ResourceLocale"
3382 * RegCloseKey
3383 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3384 * RegQueryValueExA for "Locale"
3385 * RegCloseKey
3386 * and then tests the Locale ("en" for me).
3387 * code below
3388 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3389 */
3390 CHAR mod_path[2*MAX_PATH];
3391 LPSTR ptr;
3392 DWORD len;
3393
3394 FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwFlags);
3395 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3396 if (!len || len >= sizeof(mod_path)) return NULL;
3397
3398 ptr = strrchr(mod_path, '\\');
3399 if (ptr) {
3400 strcpy(ptr+1, new_mod);
3401 TRACE("loading %s\n", debugstr_a(mod_path));
3402 return LoadLibraryA(mod_path);
3403 }
3404 return NULL;
3405 }
3406
3407 /*************************************************************************
3408 * @ [SHLWAPI.378]
3409 *
3410 * Unicode version of MLLoadLibraryA.
3411 */
3412 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3413 {
3414 WCHAR mod_path[2*MAX_PATH];
3415 LPWSTR ptr;
3416 DWORD len;
3417
3418 FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwFlags);
3419 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3420 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3421
3422 ptr = strrchrW(mod_path, '\\');
3423 if (ptr) {
3424 strcpyW(ptr+1, new_mod);
3425 TRACE("loading %s\n", debugstr_w(mod_path));
3426 return LoadLibraryW(mod_path);
3427 }
3428 return NULL;
3429 }
3430
3431 /*************************************************************************
3432 * ColorAdjustLuma [SHLWAPI.@]
3433 *
3434 * Adjust the luminosity of a color
3435 *
3436 * PARAMS
3437 * cRGB [I] RGB value to convert
3438 * dwLuma [I] Luma adjustment
3439 * bUnknown [I] Unknown
3440 *
3441 * RETURNS
3442 * The adjusted RGB color.
3443 */
3444 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3445 {
3446 TRACE("(0x%8lx,%d,%d)\n", cRGB, dwLuma, bUnknown);
3447
3448 if (dwLuma)
3449 {
3450 WORD wH, wL, wS;
3451
3452 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3453
3454 FIXME("Ignoring luma adjustment\n");
3455
3456 /* FIXME: The ajdustment is not linear */
3457
3458 cRGB = ColorHLSToRGB(wH, wL, wS);
3459 }
3460 return cRGB;
3461 }
3462
3463 /*************************************************************************
3464 * @ [SHLWAPI.389]
3465 *
3466 * See GetSaveFileNameW.
3467 */
3468 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3469 {
3470 GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
3471 return pGetSaveFileNameW(ofn);
3472 }
3473
3474 /*************************************************************************
3475 * @ [SHLWAPI.390]
3476 *
3477 * See WNetRestoreConnectionW.
3478 */
3479 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3480 {
3481 GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
3482 return pWNetRestoreConnectionW(hwndOwner, lpszDevice);
3483 }
3484
3485 /*************************************************************************
3486 * @ [SHLWAPI.391]
3487 *
3488 * See WNetGetLastErrorW.
3489 */
3490 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3491 LPWSTR lpNameBuf, DWORD nNameBufSize)
3492 {
3493 GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
3494 return pWNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3495 }
3496
3497 /*************************************************************************
3498 * @ [SHLWAPI.401]
3499 *
3500 * See PageSetupDlgW.
3501 */
3502 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3503 {
3504 GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
3505 return pPageSetupDlgW(pagedlg);
3506 }
3507
3508 /*************************************************************************
3509 * @ [SHLWAPI.402]
3510 *
3511 * See PrintDlgW.
3512 */
3513 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3514 {
3515 GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
3516 return pPrintDlgW(printdlg);
3517 }
3518
3519 /*************************************************************************
3520 * @ [SHLWAPI.403]
3521 *
3522 * See GetOpenFileNameW.
3523 */
3524 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3525 {
3526 GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
3527 return pGetOpenFileNameW(ofn);
3528 }
3529
3530 /* INTERNAL: Map from HLS color space to RGB */
3531 static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3532 {
3533 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3534
3535 if (wHue > 160)
3536 return wMid1;
3537 else if (wHue > 120)
3538 wHue = 160 - wHue;
3539 else if (wHue > 40)
3540 return wMid2;
3541
3542 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3543 }
3544
3545 /* Convert to RGB and scale into RGB range (0..255) */
3546 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3547
3548 /*************************************************************************
3549 * ColorHLSToRGB [SHLWAPI.@]
3550 *
3551 * Convert from hls color space into an rgb COLORREF.
3552 *
3553 * PARAMS
3554 * wHue [I] Hue amount
3555 * wLuminosity [I] Luminosity amount
3556 * wSaturation [I] Saturation amount
3557 *
3558 * RETURNS
3559 * A COLORREF representing the converted color.
3560 *
3561 * NOTES
3562 * Input hls values are constrained to the range (0..240).
3563 */
3564 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3565 {
3566 WORD wRed;
3567
3568 if (wSaturation)
3569 {
3570 WORD wGreen, wBlue, wMid1, wMid2;
3571
3572 if (wLuminosity > 120)
3573 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3574 else
3575 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3576
3577 wMid1 = wLuminosity * 2 - wMid2;
3578
3579 wRed = GET_RGB(wHue + 80);
3580 wGreen = GET_RGB(wHue);
3581 wBlue = GET_RGB(wHue - 80);
3582
3583 return RGB(wRed, wGreen, wBlue);
3584 }
3585
3586 wRed = wLuminosity * 255 / 240;
3587 return RGB(wRed, wRed, wRed);
3588 }
3589
3590 /*************************************************************************
3591 * @ [SHLWAPI.413]
3592 *
3593 * Get the current docking status of the system.
3594 *
3595 * PARAMS
3596 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3597 *
3598 * RETURNS
3599 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3600 * a notebook.
3601 */
3602 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3603 {
3604 HW_PROFILE_INFOA hwInfo;
3605
3606 TRACE("(0x%08lx)\n", dwFlags);
3607
3608 GetCurrentHwProfileA(&hwInfo);
3609 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3610 {
3611 case DOCKINFO_DOCKED:
3612 case DOCKINFO_UNDOCKED:
3613 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3614 default:
3615 return 0;
3616 }
3617 }
3618
3619 /*************************************************************************
3620 * @ [SHLWAPI.418]
3621 *
3622 * Function seems to do FreeLibrary plus other things.
3623 *
3624 * FIXME native shows the following calls:
3625 * RtlEnterCriticalSection
3626 * LocalFree
3627 * GetProcAddress(Comctl32??, 150L)
3628 * DPA_DeletePtr
3629 * RtlLeaveCriticalSection
3630 * followed by the FreeLibrary.
3631 * The above code may be related to .377 above.
3632 */
3633 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3634 {
3635 FIXME("(%p) semi-stub\n", hModule);
3636 return FreeLibrary(hModule);
3637 }
3638
3639 /*************************************************************************
3640 * @ [SHLWAPI.419]
3641 */
3642 BOOL WINAPI SHFlushSFCacheWrap(void) {
3643 FIXME(": stub\n");
3644 return TRUE;
3645 }
3646
3647 /*************************************************************************
3648 * @ [SHLWAPI.429]
3649 * FIXME I have no idea what this function does or what its arguments are.
3650 */
3651 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3652 {
3653 FIXME("(%p) stub\n", hInst);
3654 return FALSE;
3655 }
3656
3657
3658 /*************************************************************************
3659 * @ [SHLWAPI.430]
3660 */
3661 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3662 {
3663 FIXME("(%p,%p) stub\n", hInst, hHeap);
3664 return E_FAIL; /* This is what is used if shlwapi not loaded */
3665 }
3666
3667 /*************************************************************************
3668 * @ [SHLWAPI.431]
3669 */
3670 DWORD WINAPI MLClearMLHInstance(DWORD x)
3671 {
3672 FIXME("(0x%08lx)stub\n", x);
3673 return 0xabba1247;
3674 }
3675
3676 /*************************************************************************
3677 * @ [SHLWAPI.436]
3678 *
3679 * Convert an Unicode string CLSID into a CLSID.
3680 *
3681 * PARAMS
3682 * idstr [I] string containing a CLSID in text form
3683 * id [O] CLSID extracted from the string
3684 *
3685 * RETURNS
3686 * S_OK on success or E_INVALIDARG on failure
3687 *
3688 * NOTES
3689 * This is really CLSIDFromString() which is exported by ole32.dll,
3690 * however the native shlwapi.dll does *not* import ole32. Nor does
3691 * ole32.dll import this ordinal from shlwapi. Therefore we must conclude
3692 * that MS duplicated the code for CLSIDFromString(), and yes they did, only
3693 * it returns an E_INVALIDARG error code on failure.
3694 * This is a duplicate (with changes for Unicode) of CLSIDFromString16()
3695 * in "dlls/ole32/compobj.c".
3696 */
3697 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3698 {
3699 LPCWSTR s = idstr;
3700 BYTE *p;
3701 INT i;
3702 WCHAR table[256];
3703
3704 if (!s) {
3705 memset(id, 0, sizeof(CLSID));
3706 return S_OK;
3707 }
3708 else { /* validate the CLSID string */
3709
3710 if (strlenW(s) != 38)
3711 return E_INVALIDARG;
3712
3713 if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
3714 return E_INVALIDARG;
3715
3716 for (i=1; i<37; i++)
3717 {
3718 if ((i == 9)||(i == 14)||(i == 19)||(i == 24))
3719 continue;
3720 if (!(((s[i] >= L'0') && (s[i] <= L'9')) ||
3721 ((s[i] >= L'a') && (s[i] <= L'f')) ||
3722 ((s[i] >= L'A') && (s[i] <= L'F')))
3723 )
3724 return E_INVALIDARG;
3725 }
3726 }
3727
3728 TRACE("%s -> %p\n", debugstr_w(s), id);
3729
3730 /* quick lookup table */
3731 memset(table, 0, 256*sizeof(WCHAR));
3732
3733 for (i = 0; i < 10; i++) {
3734 table['0' + i] = i;
3735 }
3736 for (i = 0; i < 6; i++) {
3737 table['A' + i] = i+10;
3738 table['a' + i] = i+10;
3739 }
3740
3741 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
3742
3743 p = (BYTE *) id;
3744
3745 s++; /* skip leading brace */
3746 for (i = 0; i < 4; i++) {
3747 p[3 - i] = table[*s]<<4 | table[*(s+1)];
3748 s += 2;
3749 }
3750 p += 4;
3751 s++; /* skip - */
3752
3753 for (i = 0; i < 2; i++) {
3754 p[1-i] = table[*s]<<4 | table[*(s+1)];
3755 s += 2;
3756 }
3757 p += 2;
3758 s++; /* skip - */
3759
3760 for (i = 0; i < 2; i++) {
3761 p[1-i] = table[*s]<<4 | table[*(s+1)];
3762 s += 2;
3763 }
3764 p += 2;
3765 s++; /* skip - */
3766
3767 /* these are just sequential bytes */
3768 for (i = 0; i < 2; i++) {
3769 *p++ = table[*s]<<4 | table[*(s+1)];
3770 s += 2;
3771 }
3772 s++; /* skip - */
3773
3774 for (i = 0; i < 6; i++) {
3775 *p++ = table[*s]<<4 | table[*(s+1)];
3776 s += 2;
3777 }
3778
3779 return S_OK;
3780 }
3781
3782 /*************************************************************************
3783 * @ [SHLWAPI.437]
3784 *
3785 * Determine if the OS supports a given feature.
3786 *
3787 * PARAMS
3788 * dwFeature [I] Feature requested (undocumented)
3789 *
3790 * RETURNS
3791 * TRUE If the feature is available.
3792 * FALSE If the feature is not available.
3793 */
3794 BOOL WINAPI IsOS(DWORD feature)
3795 {
3796 OSVERSIONINFOA osvi;
3797 DWORD platform, majorv, minorv;
3798
3799 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3800 if(!GetVersionExA(&osvi)) {
3801 ERR("GetVersionEx failed");
3802 return FALSE;
3803 }
3804
3805 majorv = osvi.dwMajorVersion;
3806 minorv = osvi.dwMinorVersion;
3807 platform = osvi.dwPlatformId;
3808
3809 #define ISOS_RETURN(x) \
3810 TRACE("(0x%lx) ret=%d\n",feature,(x)); \
3811 return (x);
3812
3813 switch(feature) {
3814 case OS_WIN32SORGREATER:
3815 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3816 || platform == VER_PLATFORM_WIN32_WINDOWS)
3817 case OS_NT:
3818 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3819 case OS_WIN95ORGREATER:
3820 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3821 case OS_NT4ORGREATER:
3822 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3823 case OS_WIN2000ORGREATER_ALT:
3824 case OS_WIN2000ORGREATER:
3825 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3826 case OS_WIN98ORGREATER:
3827 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3828 case OS_WIN98_GOLD:
3829 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3830 case OS_WIN2000PRO:
3831 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3832 case OS_WIN2000SERVER:
3833 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3834 case OS_WIN2000ADVSERVER:
3835 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3836 case OS_WIN2000DATACENTER:
3837 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3838 case OS_WIN2000TERMINAL:
3839 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3840 case OS_EMBEDDED:
3841 FIXME("(OS_EMBEDDED) What should we return here?\n");
3842 return FALSE;
3843 case OS_TERMINALCLIENT:
3844 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3845 return FALSE;
3846 case OS_TERMINALREMOTEADMIN:
3847 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3848 return FALSE;
3849 case OS_WIN95_GOLD:
3850 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3851 case OS_MEORGREATER:
3852 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3853 case OS_XPORGREATER:
3854 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3855 case OS_HOME:
3856 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3857 case OS_PROFESSIONAL:
3858 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3859 case OS_DATACENTER:
3860 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3861 case OS_ADVSERVER:
3862 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3863 case OS_SERVER:
3864 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3865 case OS_TERMINALSERVER:
3866 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3867 case OS_PERSONALTERMINALSERVER:
3868 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3869 case OS_FASTUSERSWITCHING:
3870 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3871 return TRUE;
3872 case OS_WELCOMELOGONUI:
3873 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3874 return FALSE;
3875 case OS_DOMAINMEMBER:
3876 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3877 return TRUE;
3878 case OS_ANYSERVER:
3879 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3880 case OS_WOW6432:
3881 FIXME("(OS_WOW6432) Should we check this?\n");
3882 return FALSE;
3883 case OS_WEBSERVER:
3884 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3885 case OS_SMALLBUSINESSSERVER:
3886 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3887 case OS_TABLETPC:
3888 FIXME("(OS_TABLEPC) What should we return here?\n");
3889 return FALSE;
3890 case OS_SERVERADMINUI:
3891 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3892 return FALSE;
3893 case OS_MEDIACENTER:
3894 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3895 return FALSE;
3896 case OS_APPLIANCE:
3897 FIXME("(OS_APPLIANCE) What should we return here?\n");
3898 return FALSE;
3899 }
3900
3901 #undef ISOS_RETURN
3902
3903 WARN("(0x%lx) unknown parameter\n",feature);
3904
3905 return FALSE;
3906 }
3907
3908 /*************************************************************************
3909 * @ [SHLWAPI.478]
3910 *
3911 * Call IInputObject_TranslateAcceleratorIO() on an object.
3912 *
3913 * PARAMS
3914 * lpUnknown [I] Object supporting the IInputObject interface.
3915 * lpMsg [I] Key message to be processed.
3916 *
3917 * RETURNS
3918 * Success: S_OK.
3919 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3920 */
3921 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
3922 {
3923 IInputObject* lpInput = NULL;
3924 HRESULT hRet = E_INVALIDARG;
3925
3926 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
3927 if (lpUnknown)
3928 {
3929 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3930 (void**)&lpInput);
3931 if (SUCCEEDED(hRet) && lpInput)
3932 {
3933 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
3934 IInputObject_Release(lpInput);
3935 }
3936 }
3937 return hRet;
3938 }
3939
3940 /*************************************************************************
3941 * @ [SHLWAPI.481]
3942 *
3943 * Call IInputObject_HasFocusIO() on an object.
3944 *
3945 * PARAMS
3946 * lpUnknown [I] Object supporting the IInputObject interface.
3947 *
3948 * RETURNS
3949 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
3950 * or S_FALSE otherwise.
3951 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
3952 */
3953 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
3954 {
3955 IInputObject* lpInput = NULL;
3956 HRESULT hRet = E_INVALIDARG;
3957
3958 TRACE("(%p)\n", lpUnknown);
3959 if (lpUnknown)
3960 {
3961 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
3962 (void**)&lpInput);
3963 if (SUCCEEDED(hRet) && lpInput)
3964 {
3965 hRet = IInputObject_HasFocusIO(lpInput);
3966 IInputObject_Release(lpInput);
3967 }
3968 }
3969 return hRet;
3970 }
3971
3972 /*************************************************************************
3973 * ColorRGBToHLS [SHLWAPI.@]
3974 *
3975 * Convert an rgb COLORREF into the hls color space.
3976 *
3977 * PARAMS
3978 * cRGB [I] Source rgb value
3979 * pwHue [O] Destination for converted hue
3980 * pwLuminance [O] Destination for converted luminance
3981 * pwSaturation [O] Destination for converted saturation
3982 *
3983 * RETURNS
3984 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
3985 * values.
3986 *
3987 * NOTES
3988 * Output HLS values are constrained to the range (0..240).
3989 * For Achromatic conversions, Hue is set to 160.
3990 */
3991 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
3992 LPWORD pwLuminance, LPWORD pwSaturation)
3993 {
3994 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
3995
3996 TRACE("(%08lx,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
3997
3998 wR = GetRValue(cRGB);
3999 wG = GetGValue(cRGB);
4000 wB = GetBValue(cRGB);
4001
4002 wMax = max(wR, max(wG, wB));
4003 wMin = min(wR, min(wG, wB));
4004
4005 /* Luminosity */
4006 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4007
4008 if (wMax == wMin)
4009 {
4010 /* Achromatic case */
4011 wSaturation = 0;
4012 /* Hue is now unrepresentable, but this is what native returns... */
4013 wHue = 160;
4014 }
4015 else
4016 {
4017 /* Chromatic case */
4018 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4019
4020 /* Saturation */
4021 if (wLuminosity <= 120)
4022 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4023 else
4024 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4025
4026 /* Hue */
4027 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4028 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4029 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4030
4031 if (wR == wMax)
4032 wHue = wBNorm - wGNorm;
4033 else if (wG == wMax)
4034 wHue = 80 + wRNorm - wBNorm;
4035 else
4036 wHue = 160 + wGNorm - wRNorm;
4037 if (wHue < 0)
4038 wHue += 240;
4039 else if (wHue > 240)
4040 wHue -= 240;
4041 }
4042 if (pwHue)
4043 *pwHue = wHue;
4044 if (pwLuminance)
4045 *pwLuminance = wLuminosity;
4046 if (pwSaturation)
4047 *pwSaturation = wSaturation;
4048 }
4049
4050 /*************************************************************************
4051 * SHCreateShellPalette [SHLWAPI.@]
4052 */
4053 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4054 {
4055 FIXME("stub\n");
4056 return CreateHalftonePalette(hdc);
4057 }
4058
4059 /*************************************************************************
4060 * SHGetInverseCMAP (SHLWAPI.@)
4061 *
4062 * Get an inverse color map table.
4063 *
4064 * PARAMS
4065 * lpCmap [O] Destination for color map
4066 * dwSize [I] Size of memory pointed to by lpCmap
4067 *
4068 * RETURNS
4069 * Success: S_OK.
4070 * Failure: E_POINTER, If lpCmap is invalid.
4071 * E_INVALIDARG, If dwFlags is invalid
4072 * E_OUTOFMEMORY, If there is no memory available
4073 *
4074 * NOTES
4075 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4076 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4077 * internal CMap.
4078 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4079 * this DLL's internal CMap.
4080 */
4081 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4082 {
4083 if (dwSize == 4) {
4084 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4085 *dest = (DWORD)0xabba1249;
4086 return 0;
4087 }
4088 FIXME("(%p, %#lx) stub\n", dest, dwSize);
4089 return 0;
4090 }
4091
4092 /*************************************************************************
4093 * SHIsLowMemoryMachine [SHLWAPI.@]
4094 *
4095 * Determine if the current computer has low memory.
4096 *
4097 * PARAMS
4098 * x [I] FIXME
4099 *
4100 * RETURNS
4101 * TRUE if the users machine has 16 Megabytes of memory or less,
4102 * FALSE otherwise.
4103 */
4104 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4105 {
4106 FIXME("(0x%08lx) stub\n", x);
4107 return FALSE;
4108 }
4109
4110 /*************************************************************************
4111 * GetMenuPosFromID [SHLWAPI.@]
4112 *
4113 * Return the position of a menu item from its Id.
4114 *
4115 * PARAMS
4116 * hMenu [I] Menu containing the item
4117 * wID [I] Id of the menu item
4118 *
4119 * RETURNS
4120 * Success: The index of the menu item in hMenu.
4121 * Failure: -1, If the item is not found.
4122 */
4123 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4124 {
4125 MENUITEMINFOA mi;
4126 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4127
4128 while (nIter < nCount)
4129 {
4130 mi.wID = 0;
4131 if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4132 return nIter;
4133 nIter++;
4134 }
4135 return -1;
4136 }
4137
4138 /*************************************************************************
4139 * @ [SHLWAPI.179]
4140 *
4141 * Same as SHLWAPI.GetMenuPosFromID
4142 */
4143 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4144 {
4145 return GetMenuPosFromID(hMenu, uID);
4146 }
4147
4148
4149 /*************************************************************************
4150 * @ [SHLWAPI.448]
4151 */
4152 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4153 {
4154 while (*lpwstr)
4155 {
4156 if (*lpwstr == '/')
4157 *lpwstr = '\\';
4158 lpwstr++;
4159 }
4160 }
4161
4162
4163 /*************************************************************************
4164 * @ [SHLWAPI.461]
4165 */
4166 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4167 {
4168 FIXME("(0x%08lx) stub\n", dwUnknown);
4169 return 0;
4170 }
4171
4172
4173 /*************************************************************************
4174 * @ [SHLWAPI.549]
4175 */
4176 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4177 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4178 {
4179 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4180 }
4181
4182 /*************************************************************************
4183 * SHSkipJunction [SHLWAPI.@]
4184 *
4185 * Determine if a bind context can be bound to an object
4186 *
4187 * PARAMS
4188 * pbc [I] Bind context to check
4189 * pclsid [I] CLSID of object to be bound to
4190 *
4191 * RETURNS
4192 * TRUE: If it is safe to bind
4193 * FALSE: If pbc is invalid or binding would not be safe
4194 *
4195 */
4196 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4197 {
4198 static const WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4199 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4200 BOOL bRet = FALSE;
4201
4202 if (pbc)
4203 {
4204 IUnknown* lpUnk;
4205
4206 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)szSkipBinding, &lpUnk)))
4207 {
4208 CLSID clsid;
4209
4210 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4211 IsEqualGUID(pclsid, &clsid))
4212 bRet = TRUE;
4213
4214 IUnknown_Release(lpUnk);
4215 }
4216 }
4217 return bRet;
4218 }
4219
4220 /***********************************************************************
4221 * SHGetShellKey (SHLWAPI.@)
4222 */
4223 DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
4224 {
4225 FIXME("(%lx, %lx, %lx): stub\n", a, b, c);
4226 return 0x50;
4227 }
4228
4229 /***********************************************************************
4230 * SHQueueUserWorkItem (SHLWAPI.@)
4231 */
4232 HRESULT WINAPI SHQueueUserWorkItem(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f, DWORD g)
4233 {
4234 FIXME("(%lx, %lx, %lx, %lx, %lx, %lx, %lx): stub\n", a, b, c, d, e, f, g);
4235 return E_FAIL;
4236 }
4237
4238 /***********************************************************************
4239 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4240 */
4241 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4242 {
4243 IInputObjectSite *pIOS = NULL;
4244 HRESULT hRet = E_INVALIDARG;
4245
4246 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4247
4248 if (lpUnknown)
4249 {
4250 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4251 (void **)&pIOS);
4252 if (SUCCEEDED(hRet) && pIOS)
4253 {
4254 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4255 IInputObjectSite_Release(pIOS);
4256 }
4257 }
4258 return hRet;
4259 }
4260
4261 /***********************************************************************
4262 * SHGetValueW (SHLWAPI.@)
4263 */
4264 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4265 {
4266 FIXME("(%lx, %s, %s, %lx, %lx, %lx): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4267 return E_FAIL;
4268 }
4269
4270 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4271
4272 /***********************************************************************
4273 * GetUIVersion (SHLWAPI.452)
4274 */
4275 DWORD WINAPI GetUIVersion(void)
4276 {
4277 static DWORD version;
4278
4279 if (!version)
4280 {
4281 DllGetVersion_func pDllGetVersion;
4282 HMODULE dll = LoadLibraryA("shell32.dll");
4283 if (!dll) return 0;
4284
4285 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4286 if (pDllGetVersion)
4287 {
4288 DLLVERSIONINFO dvi;
4289 dvi.cbSize = sizeof(DLLVERSIONINFO);
4290 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4291 }
4292 FreeLibrary( dll );
4293 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4294 }
4295 return version;
4296 }