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