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