SHGetAppCompatFlags takes 4 bytes of parameters.
[wine/hacks.git] / dlls / shlwapi / ordinal.c
blob981fe7e8898d0cc538114908aca05ff756d0a7a2
1 /*
2 * SHLWAPI ordinal functions
4 * Copyright 1997 Marcus Meissner
5 * 1998 Jürgen Schmied
6 * 2001-2003 Jon Griffiths
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.
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.
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
23 #define COM_NO_WINDOWS_H
24 #include "config.h"
25 #include "wine/port.h"
27 #include <stdarg.h>
28 #include <stdio.h>
29 #include <string.h>
31 #define COBJMACROS
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
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"
56 WINE_DEFAULT_DEBUG_CHANNEL(shell);
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)
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;
78 extern DWORD SHLWAPI_ThreadRef_index;
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};
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;
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);
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!
150 /*************************************************************************
151 * SHLWAPI_DupSharedHandle
153 * Internal implemetation of SHLWAPI_11.
155 static
156 HANDLE WINAPI SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
157 DWORD dwSrcProcId, DWORD dwAccess,
158 DWORD dwOptions)
160 HANDLE hDst, hSrc;
161 DWORD dwMyProcId = GetCurrentProcessId();
162 HANDLE hRet = NULL;
164 TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", hShared, dwDstProcId, dwSrcProcId,
165 dwAccess, dwOptions);
167 /* Get dest process handle */
168 if (dwDstProcId == dwMyProcId)
169 hDst = GetCurrentProcess();
170 else
171 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
173 if (hDst)
175 /* Get src process handle */
176 if (dwSrcProcId == dwMyProcId)
177 hSrc = GetCurrentProcess();
178 else
179 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
181 if (hSrc)
183 /* Make handle available to dest process */
184 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
185 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
186 hRet = NULL;
188 if (dwSrcProcId != dwMyProcId)
189 CloseHandle(hSrc);
192 if (dwDstProcId != dwMyProcId)
193 CloseHandle(hDst);
196 TRACE("Returning handle %p\n", hRet);
197 return hRet;
200 /*************************************************************************
201 * @ [SHLWAPI.7]
203 * Create a block of sharable memory and initialise it with data.
205 * PARAMS
206 * lpvData [I] Pointer to data to write
207 * dwSize [I] Size of data
208 * dwProcId [I] ID of process owning data
210 * RETURNS
211 * Success: A shared memory handle
212 * Failure: NULL
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.
222 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
224 HANDLE hMap;
225 LPVOID pMapped;
226 HANDLE hRet = NULL;
228 TRACE("(%p,%ld,%ld)\n", lpvData, dwSize, dwProcId);
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;
236 /* Get a view in our process address space */
237 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
239 if (pMapped)
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);
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);
253 CloseHandle(hMap);
254 return hRet;
257 /*************************************************************************
258 * @ [SHLWAPI.8]
260 * Get a pointer to a block of shared memory from a shared memory handle.
262 * PARAMS
263 * hShared [I] Shared memory handle
264 * dwProcId [I] ID of process owning hShared
266 * RETURNS
267 * Success: A pointer to the shared memory
268 * Failure: NULL
271 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
273 HANDLE hDup;
274 LPVOID pMapped;
276 TRACE("(%p %ld)\n", hShared, dwProcId);
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);
285 if (pMapped)
286 return (char *) pMapped + sizeof(DWORD); /* Hide size */
287 return NULL;
290 /*************************************************************************
291 * @ [SHLWAPI.9]
293 * Release a pointer to a block of shared memory.
295 * PARAMS
296 * lpView [I] Shared memory pointer
298 * RETURNS
299 * Success: TRUE
300 * Failure: FALSE
303 BOOL WINAPI SHUnlockShared(LPVOID lpView)
305 TRACE("(%p)\n", lpView);
306 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
309 /*************************************************************************
310 * @ [SHLWAPI.10]
312 * Destroy a block of sharable memory.
314 * PARAMS
315 * hShared [I] Shared memory handle
316 * dwProcId [I] ID of process owning hShared
318 * RETURNS
319 * Success: TRUE
320 * Failure: FALSE
323 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
325 HANDLE hClose;
327 TRACE("(%p %ld)\n", hShared, dwProcId);
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);
336 /*************************************************************************
337 * @ [SHLWAPI.11]
339 * Copy a sharable memory handle from one process to another.
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
348 * RETURNS
349 * Success: A handle suitable for use by the dwDstProcId process.
350 * Failure: A NULL handle.
353 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
354 DWORD dwAccess, DWORD dwOptions)
356 HANDLE hRet;
358 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
359 dwAccess, dwOptions);
360 return hRet;
363 /*************************************************************************
364 * @ [SHLWAPI.13]
366 * Create and register a clipboard enumerator for a web browser.
368 * PARAMS
369 * lpBC [I] Binding context
370 * lpUnknown [I] An object exposing the IWebBrowserApp interface
372 * RETURNS
373 * Success: S_OK.
374 * Failure: An HRESULT error code.
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.
380 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
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;
390 TRACE("(%p, %p)\n", lpBC, lpUnknown);
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;
397 V_VT(&var) = VT_EMPTY;
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;
404 if (V_VT(&var) == VT_EMPTY)
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;
412 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
414 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
415 "Version\\Internet Settings\\Accepted Documents", &hDocs))
416 return E_FAIL;
418 /* Get count of values in key */
419 while (!dwRet)
421 dwKeySize = sizeof(szKeyBuff);
422 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
423 dwCount++;
426 dwNumValues = dwCount;
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;
433 if (dwNumValues > 1)
435 dwRet = 0;
436 dwCount = 0;
438 dwNumValues--;
440 /* Register clipboard formats for the values and populate format list */
441 while(!dwRet && dwCount < dwNumValues)
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;
450 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
451 format->ptd = NULL;
452 format->dwAspect = 1;
453 format->lindex = 4;
454 format->tymed = -1;
456 format++;
457 dwCount++;
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;
468 /* Create a clipboard enumerator */
469 GET_FUNC(pCreateFormatEnumerator, urlmon, "CreateFormatEnumerator", E_FAIL);
470 hRet = pCreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
472 if (FAILED(hRet) || !pIEnumFormatEtc)
473 return hRet;
475 /* Set our enumerator as the browsers property */
476 V_VT(&var) = VT_UNKNOWN;
477 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
479 hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
480 if (FAILED(hRet))
482 IEnumFORMATETC_Release(pIEnumFormatEtc);
483 goto RegisterDefaultAcceptHeaders_Exit;
487 if (V_VT(&var) == VT_UNKNOWN)
489 /* Our variant is holding the clipboard enumerator */
490 IUnknown* pIUnknown = V_UNKNOWN(&var);
491 IEnumFORMATETC* pClone = NULL;
493 TRACE("Retrieved IEnumFORMATETC property\n");
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)
501 /* Clone and register the enumerator */
502 hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
503 if (!hRet && pClone)
505 GET_FUNC(pRegisterFormatEnumerator, urlmon, "RegisterFormatEnumerator", E_FAIL);
506 pRegisterFormatEnumerator(lpBC, pClone, 0);
508 IEnumFORMATETC_Release(pClone);
511 /* Release the IEnumFormatEtc interface */
512 IEnumFORMATETC_Release(pIUnknown);
514 IUnknown_Release(V_UNKNOWN(&var));
517 RegisterDefaultAcceptHeaders_Exit:
518 IWebBrowserApp_Release(pBrowser);
519 return hRet;
522 /*************************************************************************
523 * @ [SHLWAPI.15]
525 * Get Explorers "AcceptLanguage" setting.
527 * PARAMS
528 * langbuf [O] Destination for language string
529 * buflen [I] Length of langbuf
530 * [0] Success: used length of langbuf
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
538 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
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;
554 if(!langbuf || !buflen || !*buflen)
555 return E_FAIL;
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"
571 lstrcpyW(mystr, enusW);
572 mystrlen = lstrlenW(mystr);
573 } else {
574 /* handle returned string */
575 FIXME("missing code\n");
577 memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
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);
587 RegCloseKey(mykey);
588 HeapFree(GetProcessHeap(), 0, mystr);
589 return retval;
592 /*************************************************************************
593 * @ [SHLWAPI.14]
595 * Ascii version of GetAcceptLanguagesW.
597 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
599 WCHAR *langbufW;
600 DWORD buflenW, convlen;
601 HRESULT retval;
603 if(!langbuf || !buflen || !*buflen) return E_FAIL;
605 buflenW = *buflen;
606 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
607 retval = GetAcceptLanguagesW(langbufW, &buflenW);
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;
614 if(langbufW) HeapFree(GetProcessHeap(), 0, langbufW);
615 return retval;
618 /*************************************************************************
619 * @ [SHLWAPI.23]
621 * Convert a GUID to a string.
623 * PARAMS
624 * guid [I] GUID to convert
625 * str [O] Destination for string
626 * cmax [I] Length of output buffer
628 * RETURNS
629 * The length of the string created.
631 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
633 char xguid[40];
634 INT iLen;
636 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
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]);
643 iLen = strlen(xguid) + 1;
645 if (iLen > cchMax)
646 return 0;
647 memcpy(lpszDest, xguid, iLen);
648 return iLen;
651 /*************************************************************************
652 * @ [SHLWAPI.24]
654 * Unicode version of SHStringFromGUIDA.
656 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
658 char xguid[40];
659 INT iLen = SHStringFromGUIDA(guid, xguid, cchMax);
661 if (iLen)
662 MultiByteToWideChar(CP_ACP, 0, xguid, -1, lpszDest, cchMax);
663 return iLen;
666 /*************************************************************************
667 * @ [SHLWAPI.25]
669 * Determine if a Unicode character is alphabetic.
671 * PARAMS
672 * wc [I] Character to check.
674 * RETURNS
675 * TRUE, if wc is alphabetic,
676 * FALSE otherwise.
678 BOOL WINAPI IsCharAlphaWrapW(WCHAR wc)
680 return (get_char_typeW(wc) & C1_ALPHA) != 0;
683 /*************************************************************************
684 * @ [SHLWAPI.26]
686 * Determine if a Unicode character is upper-case.
688 * PARAMS
689 * wc [I] Character to check.
691 * RETURNS
692 * TRUE, if wc is upper-case,
693 * FALSE otherwise.
695 BOOL WINAPI IsCharUpperWrapW(WCHAR wc)
697 return (get_char_typeW(wc) & C1_UPPER) != 0;
700 /*************************************************************************
701 * @ [SHLWAPI.27]
703 * Determine if a Unicode character is lower-case.
705 * PARAMS
706 * wc [I] Character to check.
708 * RETURNS
709 * TRUE, if wc is lower-case,
710 * FALSE otherwise.
712 BOOL WINAPI IsCharLowerWrapW(WCHAR wc)
714 return (get_char_typeW(wc) & C1_LOWER) != 0;
717 /*************************************************************************
718 * @ [SHLWAPI.28]
720 * Determine if a Unicode character is alphabetic or a digit.
722 * PARAMS
723 * wc [I] Character to check.
725 * RETURNS
726 * TRUE, if wc is alphabetic or a digit,
727 * FALSE otherwise.
729 BOOL WINAPI IsCharAlphaNumericWrapW(WCHAR wc)
731 return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
734 /*************************************************************************
735 * @ [SHLWAPI.29]
737 * Determine if a Unicode character is a space.
739 * PARAMS
740 * wc [I] Character to check.
742 * RETURNS
743 * TRUE, if wc is a space,
744 * FALSE otherwise.
746 BOOL WINAPI IsCharSpaceW(WCHAR wc)
748 return (get_char_typeW(wc) & C1_SPACE) != 0;
751 /*************************************************************************
752 * @ [SHLWAPI.30]
754 * Determine if a Unicode character is a blank.
756 * PARAMS
757 * wc [I] Character to check.
759 * RETURNS
760 * TRUE, if wc is a blank,
761 * FALSE otherwise.
764 BOOL WINAPI IsCharBlankW(WCHAR wc)
766 return (get_char_typeW(wc) & C1_BLANK) != 0;
769 /*************************************************************************
770 * @ [SHLWAPI.31]
772 * Determine if a Unicode character is punctuation.
774 * PARAMS
775 * wc [I] Character to check.
777 * RETURNS
778 * TRUE, if wc is punctuation,
779 * FALSE otherwise.
781 BOOL WINAPI IsCharPunctW(WCHAR wc)
783 return (get_char_typeW(wc) & C1_PUNCT) != 0;
786 /*************************************************************************
787 * @ [SHLWAPI.32]
789 * Determine if a Unicode character is a control character.
791 * PARAMS
792 * wc [I] Character to check.
794 * RETURNS
795 * TRUE, if wc is a control character,
796 * FALSE otherwise.
798 BOOL WINAPI IsCharCntrlW(WCHAR wc)
800 return (get_char_typeW(wc) & C1_CNTRL) != 0;
803 /*************************************************************************
804 * @ [SHLWAPI.33]
806 * Determine if a Unicode character is a digit.
808 * PARAMS
809 * wc [I] Character to check.
811 * RETURNS
812 * TRUE, if wc is a digit,
813 * FALSE otherwise.
815 BOOL WINAPI IsCharDigitW(WCHAR wc)
817 return (get_char_typeW(wc) & C1_DIGIT) != 0;
820 /*************************************************************************
821 * @ [SHLWAPI.34]
823 * Determine if a Unicode character is a hex digit.
825 * PARAMS
826 * wc [I] Character to check.
828 * RETURNS
829 * TRUE, if wc is a hex digit,
830 * FALSE otherwise.
832 BOOL WINAPI IsCharXDigitW(WCHAR wc)
834 return (get_char_typeW(wc) & C1_XDIGIT) != 0;
837 /*************************************************************************
838 * @ [SHLWAPI.35]
841 BOOL WINAPI GetStringType3ExW(LPWSTR lpszStr, DWORD dwLen, LPVOID p3)
843 FIXME("(%s,0x%08lx,%p): stub\n", debugstr_w(lpszStr), dwLen, p3);
844 return TRUE;
847 /*************************************************************************
848 * @ [SHLWAPI.36]
850 * Insert a bitmap menu item at the bottom of a menu.
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
858 * RETURNS
859 * Success: TRUE, the item is inserted into the menu
860 * Failure: FALSE, if any parameter is invalid
862 BOOL WINAPI AppendMenuWrapW(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
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);
868 /*************************************************************************
869 * @ [SHLWAPI.74]
871 * Get the text from a given dialog item.
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.
879 * RETURNS
880 * Success: The length of the returned text.
881 * Failure: 0.
883 INT WINAPI GetDlgItemTextWrapW(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
885 HWND hItem = GetDlgItem(hWnd, nItem);
887 if (hItem)
888 return GetWindowTextW(hItem, lpsDest, nDestLen);
889 if (nDestLen)
890 *lpsDest = (WCHAR)'\0';
891 return 0;
894 /*************************************************************************
895 * @ [SHLWAPI.138]
897 * Set the text of a given dialog item.
899 * PARAMS
900 * hWnd [I] Handle of dialog
901 * iItem [I] Index of item
902 * lpszText [O] Text to set
904 * RETURNS
905 * Success: TRUE. The text of the dialog is set to lpszText.
906 * Failure: FALSE, Otherwise.
908 BOOL WINAPI SetDlgItemTextWrapW(HWND hWnd, INT iItem, LPCWSTR lpszText)
910 HWND hWndItem = GetDlgItem(hWnd, iItem);
911 if (hWndItem)
912 return SetWindowTextW(hWndItem, lpszText);
913 return FALSE;
916 /*************************************************************************
917 * @ [SHLWAPI.151]
919 * Compare two Ascii strings up to a given length.
921 * PARAMS
922 * lpszSrc [I] Source string
923 * lpszCmp [I] String to compare to lpszSrc
924 * len [I] Maximum length
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.
930 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
932 return strncmp(lpszSrc, lpszCmp, len);
935 /*************************************************************************
936 * @ [SHLWAPI.152]
938 * Unicode version of StrCmpNCA.
940 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
942 return strncmpW(lpszSrc, lpszCmp, len);
945 /*************************************************************************
946 * @ [SHLWAPI.153]
948 * Compare two Ascii strings up to a given length, ignoring case.
950 * PARAMS
951 * lpszSrc [I] Source string
952 * lpszCmp [I] String to compare to lpszSrc
953 * len [I] Maximum length
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.
959 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
961 return strncasecmp(lpszSrc, lpszCmp, len);
964 /*************************************************************************
965 * @ [SHLWAPI.154]
967 * Unicode version of StrCmpNICA.
969 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
971 return strncmpiW(lpszSrc, lpszCmp, len);
974 /*************************************************************************
975 * @ [SHLWAPI.155]
977 * Compare two Ascii strings.
979 * PARAMS
980 * lpszSrc [I] Source string
981 * lpszCmp [I] String to compare to lpszSrc
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.
987 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
989 return strcmp(lpszSrc, lpszCmp);
992 /*************************************************************************
993 * @ [SHLWAPI.156]
995 * Unicode version of StrCmpCA.
997 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
999 return strcmpW(lpszSrc, lpszCmp);
1002 /*************************************************************************
1003 * @ [SHLWAPI.157]
1005 * Compare two Ascii strings, ignoring case.
1007 * PARAMS
1008 * lpszSrc [I] Source string
1009 * lpszCmp [I] String to compare to lpszSrc
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.
1015 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
1017 return strcasecmp(lpszSrc, lpszCmp);
1020 /*************************************************************************
1021 * @ [SHLWAPI.158]
1023 * Unicode version of StrCmpICA.
1025 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
1027 return strcmpiW(lpszSrc, lpszCmp);
1030 /*************************************************************************
1031 * @ [SHLWAPI.160]
1033 * Get an identification string for the OS and explorer.
1035 * PARAMS
1036 * lpszDest [O] Destination for Id string
1037 * dwDestLen [I] Length of lpszDest
1039 * RETURNS
1040 * TRUE, If the string was created successfully
1041 * FALSE, Otherwise
1043 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
1045 WCHAR buff[2084];
1047 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
1049 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
1051 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
1052 return TRUE;
1054 return FALSE;
1057 /*************************************************************************
1058 * @ [SHLWAPI.161]
1060 * Unicode version of SHAboutInfoA.
1062 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
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;
1093 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
1095 if (!lpszDest)
1096 return FALSE;
1098 *lpszDest = '\0';
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;
1105 /* OS Version */
1106 buff[0] = '\0';
1107 dwLen = 30;
1108 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
1110 DWORD dwStrLen = strlenW(buff);
1111 dwLen = 30 - dwStrLen;
1112 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
1113 szCustomized, &dwType, buff+dwStrLen, &dwLen);
1115 StrCatBuffW(lpszDest, buff, dwDestLen);
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);
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);
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);
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);
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);
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);
1154 RegCloseKey(hReg);
1155 return TRUE;
1158 /*************************************************************************
1159 * @ [SHLWAPI.163]
1161 * Call IOleCommandTarget_QueryStatus() on an object.
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
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().
1176 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1177 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1179 HRESULT hRet = E_FAIL;
1181 TRACE("(%p,%p,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1183 if (lpUnknown)
1185 IOleCommandTarget* lpOle;
1187 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1188 (void**)&lpOle);
1190 if (SUCCEEDED(hRet) && lpOle)
1192 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1193 prgCmds, pCmdText);
1194 IOleCommandTarget_Release(lpOle);
1197 return hRet;
1200 /*************************************************************************
1201 * @ [SHLWAPI.164]
1203 * Call IOleCommandTarget_Exec() on an object.
1205 * PARAMS
1206 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1207 * pguidCmdGroup [I] GUID for the command group
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().
1215 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1216 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1217 VARIANT* pvaOut)
1219 HRESULT hRet = E_FAIL;
1221 TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1222 nCmdexecopt, pvaIn, pvaOut);
1224 if (lpUnknown)
1226 IOleCommandTarget* lpOle;
1228 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1229 (void**)&lpOle);
1230 if (SUCCEEDED(hRet) && lpOle)
1232 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1233 nCmdexecopt, pvaIn, pvaOut);
1234 IOleCommandTarget_Release(lpOle);
1237 return hRet;
1240 /*************************************************************************
1241 * @ [SHLWAPI.165]
1243 * Retrieve, modify, and re-set a value from a window.
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
1251 * RETURNS
1252 * The new value as it was set, or 0 if any parameter is invalid.
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.
1258 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
1260 LONG ret = GetWindowLongA(hwnd, offset);
1261 LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);
1263 if (newFlags != ret)
1264 ret = SetWindowLongA(hwnd, offset, newFlags);
1265 return ret;
1268 /*************************************************************************
1269 * @ [SHLWAPI.167]
1271 * Change a window's parent.
1273 * PARAMS
1274 * hWnd [I] Window to change parent of
1275 * hWndParent [I] New parent window
1277 * RETURNS
1278 * The old parent of hWnd.
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.
1284 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1286 TRACE("%p, %p\n", hWnd, hWndParent);
1288 if(GetParent(hWnd) == hWndParent)
1289 return 0;
1291 if(hWndParent)
1292 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1293 else
1294 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1296 return SetParent(hWnd, hWndParent);
1299 /*************************************************************************
1300 * @ [SHLWAPI.168]
1302 * Locate and advise a connection point in an IConnectionPointContainer object.
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
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.
1319 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
1320 IUnknown* lpUnknown, LPDWORD lpCookie,
1321 IConnectionPoint **lppCP)
1323 HRESULT hRet;
1324 IConnectionPointContainer* lpContainer;
1325 IConnectionPoint *lpCP;
1327 if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
1328 return E_FAIL;
1330 if(lppCP)
1331 *lppCP = NULL;
1333 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1334 (void**)&lpContainer);
1335 if (SUCCEEDED(hRet))
1337 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1339 if (SUCCEEDED(hRet))
1341 if(!bAdviseOnly)
1342 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1343 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1345 if (FAILED(hRet))
1346 *lpCookie = 0;
1348 if (lppCP && SUCCEEDED(hRet))
1349 *lppCP = lpCP; /* Caller keeps the interface */
1350 else
1351 IConnectionPoint_Release(lpCP); /* Release it */
1354 IUnknown_Release(lpContainer);
1356 return hRet;
1359 /*************************************************************************
1360 * @ [SHLWAPI.169]
1362 * Release an interface.
1364 * PARAMS
1365 * lpUnknown [I] Object to release
1367 * RETURNS
1368 * Nothing.
1370 DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1372 IUnknown *temp;
1374 TRACE("(%p)\n",lpUnknown);
1376 if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1377 temp = *lpUnknown;
1378 *lpUnknown = NULL;
1380 TRACE("doing Release\n");
1382 return IUnknown_Release(temp);
1385 /*************************************************************************
1386 * @ [SHLWAPI.170]
1388 * Skip '//' if present in a string.
1390 * PARAMS
1391 * lpszSrc [I] String to check for '//'
1393 * RETURNS
1394 * Success: The next character after the '//' or the string if not present
1395 * Failure: NULL, if lpszStr is NULL.
1397 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1399 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1400 lpszSrc += 2;
1401 return lpszSrc;
1404 /*************************************************************************
1405 * @ [SHLWAPI.171]
1407 * Check if two interfaces come from the same object.
1409 * PARAMS
1410 * lpInt1 [I] Interface to check against lpInt2.
1411 * lpInt2 [I] Interface to check against lpInt1.
1413 * RETURNS
1414 * TRUE, If the interfaces come from the same object.
1415 * FALSE Otherwise.
1417 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1419 LPVOID lpUnknown1, lpUnknown2;
1421 TRACE("%p %p\n", lpInt1, lpInt2);
1423 if (!lpInt1 || !lpInt2)
1424 return FALSE;
1426 if (lpInt1 == lpInt2)
1427 return TRUE;
1429 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown,
1430 (LPVOID *)&lpUnknown1)))
1431 return FALSE;
1433 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown,
1434 (LPVOID *)&lpUnknown2)))
1435 return FALSE;
1437 if (lpUnknown1 == lpUnknown2)
1438 return TRUE;
1440 return FALSE;
1443 /*************************************************************************
1444 * @ [SHLWAPI.172]
1446 * Get the window handle of an object.
1448 * PARAMS
1449 * lpUnknown [I] Object to get the window handle of
1450 * lphWnd [O] Destination for window handle
1452 * RETURNS
1453 * Success: S_OK. lphWnd contains the objects window handle.
1454 * Failure: An HRESULT error code.
1456 * NOTES
1457 * lpUnknown is expected to support one of the following interfaces:
1458 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1460 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
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;
1468 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1470 if (!lpUnknown)
1471 return hRet;
1473 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1475 if (FAILED(hRet))
1477 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1479 if (FAILED(hRet))
1481 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1482 (void**)&lpOle);
1486 if (SUCCEEDED(hRet))
1488 /* Lazyness here - Since GetWindow() is the first method for the above 3
1489 * interfaces, we use the same call for them all.
1491 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1492 IUnknown_Release(lpOle);
1493 if (lphWnd)
1494 TRACE("Returning HWND=%p\n", *lphWnd);
1497 return hRet;
1500 /*************************************************************************
1501 * @ [SHLWAPI.173]
1503 * Call a method on as as yet unidentified object.
1505 * PARAMS
1506 * pUnk [I] Object supporting the unidentified interface,
1507 * arg [I] Argument for the call on the object.
1509 * RETURNS
1510 * S_OK.
1512 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1514 static const GUID guid_173 = {
1515 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1517 IMalloc *pUnk2;
1519 TRACE("(%p,%ld)\n", pUnk, arg);
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.
1526 if (pUnk &&
1527 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1529 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1530 IMalloc_Release(pUnk2);
1532 return S_OK;
1535 /*************************************************************************
1536 * @ [SHLWAPI.174]
1538 * Call either IObjectWithSite_SetSite() or IPersistMoniker_GetClassID() on
1539 * an interface.
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.
1547 DWORD WINAPI IUnknown_SetSite(
1548 IUnknown *p1, /* [in] OLE object */
1549 LPVOID *p2) /* [out] ptr for call results */
1551 DWORD ret, aa;
1553 if (!p1) return E_FAIL;
1555 /* see if SetSite interface exists for IObjectWithSite object */
1556 ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&p1);
1557 TRACE("first IU_QI ret=%08lx, p1=%p\n", ret, p1);
1558 if (ret) {
1560 /* see if GetClassId interface exists for IPersistMoniker object */
1561 ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id2, (LPVOID *)&aa);
1562 TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
1563 if (ret) return ret;
1565 /* fake a GetClassId call */
1566 ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
1567 TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1568 *(LPDWORD)p2);
1569 IUnknown_Release((IUnknown *)aa);
1571 else {
1572 /* fake a SetSite call */
1573 ret = IOleWindow_GetWindow((IOleWindow *)p1, (HWND*)p2);
1574 TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
1575 *(LPDWORD)p2);
1576 IUnknown_Release((IUnknown *)p1);
1578 return ret;
1581 /*************************************************************************
1582 * @ [SHLWAPI.175]
1584 * Call IPersist_GetClassID() on an object.
1586 * PARAMS
1587 * lpUnknown [I] Object supporting the IPersist interface
1588 * lpClassId [O] Destination for Class Id
1590 * RETURNS
1591 * Success: S_OK. lpClassId contains the Class Id requested.
1592 * Failure: E_FAIL, If lpUnknown is NULL,
1593 * E_NOINTERFACE If lpUnknown does not support IPersist,
1594 * Or an HRESULT error code.
1596 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1598 IPersist* lpPersist;
1599 HRESULT hRet = E_FAIL;
1601 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1603 if (lpUnknown)
1605 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1606 if (SUCCEEDED(hRet))
1608 IPersist_GetClassID(lpPersist, lpClassId);
1609 IPersist_Release(lpPersist);
1612 return hRet;
1615 /*************************************************************************
1616 * @ [SHLWAPI.176]
1618 * Retrieve a Service Interface from an object.
1620 * PARAMS
1621 * lpUnknown [I] Object to get an IServiceProvider interface from
1622 * sid [I] Service ID for IServiceProvider_QueryService() call
1623 * riid [I] Function requested for QueryService call
1624 * lppOut [O] Destination for the service interface pointer
1626 * RETURNS
1627 * Success: S_OK. lppOut contains an object providing the requested service
1628 * Failure: An HRESULT error code
1630 * NOTES
1631 * lpUnknown is expected to support the IServiceProvider interface.
1633 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1634 LPVOID *lppOut)
1636 IServiceProvider* pService = NULL;
1637 HRESULT hRet;
1639 if (!lppOut)
1640 return E_FAIL;
1642 *lppOut = NULL;
1644 if (!lpUnknown)
1645 return E_FAIL;
1647 /* Get an IServiceProvider interface from the object */
1648 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1649 (LPVOID*)&pService);
1651 if (!hRet && pService)
1653 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1655 /* Get a Service interface from the object */
1656 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1658 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1660 /* Release the IServiceProvider interface */
1661 IUnknown_Release(pService);
1663 return hRet;
1666 /*************************************************************************
1667 * @ [SHLWAPI.177]
1669 * Loads a popup menu.
1671 * PARAMS
1672 * hInst [I] Instance handle
1673 * szName [I] Menu name
1675 * RETURNS
1676 * Success: TRUE.
1677 * Failure: FALSE.
1679 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1681 HMENU hMenu, hSubMenu;
1683 if ((hMenu = LoadMenuW(hInst, szName)))
1685 if ((hSubMenu = GetSubMenu(hMenu, 0)))
1686 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1688 DestroyMenu(hMenu);
1689 return TRUE;
1691 return FALSE;
1694 typedef struct _enumWndData
1696 UINT uiMsgId;
1697 WPARAM wParam;
1698 LPARAM lParam;
1699 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1700 } enumWndData;
1702 /* Callback for SHLWAPI_178 */
1703 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1705 enumWndData *data = (enumWndData *)lParam;
1707 TRACE("(%p,%p)\n", hWnd, data);
1708 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1709 return TRUE;
1712 /*************************************************************************
1713 * @ [SHLWAPI.178]
1715 * Send or post a message to every child of a window.
1717 * PARAMS
1718 * hWnd [I] Window whose children will get the messages
1719 * uiMsgId [I] Message Id
1720 * wParam [I] WPARAM of message
1721 * lParam [I] LPARAM of message
1722 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1724 * RETURNS
1725 * Nothing.
1727 * NOTES
1728 * The appropriate ASCII or Unicode function is called for the window.
1730 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1732 enumWndData data;
1734 TRACE("(%p,%u,%d,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1736 if(hWnd)
1738 data.uiMsgId = uiMsgId;
1739 data.wParam = wParam;
1740 data.lParam = lParam;
1742 if (bSend)
1743 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1744 else
1745 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1747 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1751 /*************************************************************************
1752 * @ [SHLWAPI.180]
1754 * Remove all sub-menus from a menu.
1756 * PARAMS
1757 * hMenu [I] Menu to remove sub-menus from
1759 * RETURNS
1760 * Success: 0. All sub-menus under hMenu are removed
1761 * Failure: -1, if any parameter is invalid
1763 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1765 int iItemCount = GetMenuItemCount(hMenu) - 1;
1766 while (iItemCount >= 0)
1768 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1769 if (hSubMenu)
1770 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1771 iItemCount--;
1773 return iItemCount;
1776 /*************************************************************************
1777 * @ [SHLWAPI.181]
1779 * Enable or disable a menu item.
1781 * PARAMS
1782 * hMenu [I] Menu holding menu item
1783 * uID [I] ID of menu item to enable/disable
1784 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1786 * RETURNS
1787 * The return code from EnableMenuItem.
1789 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1791 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1794 /*************************************************************************
1795 * @ [SHLWAPI.182]
1797 * Check or uncheck a menu item.
1799 * PARAMS
1800 * hMenu [I] Menu holding menu item
1801 * uID [I] ID of menu item to check/uncheck
1802 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1804 * RETURNS
1805 * The return code from CheckMenuItem.
1807 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1809 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1812 /*************************************************************************
1813 * @ [SHLWAPI.183]
1815 * Register a window class if it isn't already.
1817 * PARAMS
1818 * lpWndClass [I] Window class to register
1820 * RETURNS
1821 * The result of the RegisterClassA call.
1823 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1825 WNDCLASSA wca;
1826 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1827 return TRUE;
1828 return (DWORD)RegisterClassA(wndclass);
1831 /*************************************************************************
1832 * @ [SHLWAPI.186]
1834 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1835 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1837 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1838 POINTL pt = { 0, 0 };
1840 if (!lpPt)
1841 lpPt = &pt;
1843 if (!pdwEffect)
1844 pdwEffect = &dwEffect;
1846 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1848 if (*pdwEffect)
1849 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1851 IDropTarget_DragLeave(pDrop);
1852 return TRUE;
1855 /*************************************************************************
1856 * @ [SHLWAPI.187]
1858 * Call IPersistPropertyBag_Load() on an object.
1860 * PARAMS
1861 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1862 * lpPropBag [O] Destination for loaded IPropertyBag
1864 * RETURNS
1865 * Success: S_OK.
1866 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1868 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1870 IPersistPropertyBag* lpPPBag;
1871 HRESULT hRet = E_FAIL;
1873 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1875 if (lpUnknown)
1877 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1878 (void**)&lpPPBag);
1879 if (SUCCEEDED(hRet) && lpPPBag)
1881 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1882 IPersistPropertyBag_Release(lpPPBag);
1885 return hRet;
1888 /*************************************************************************
1889 * @ [SHLWAPI.189]
1891 * Call IOleControlSite_GetExtendedControl() on an object.
1893 * PARAMS
1894 * lpUnknown [I] Object supporting the IOleControlSite interface
1895 * lppDisp [O] Destination for resulting IDispatch.
1897 * RETURNS
1898 * Success: S_OK.
1899 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1901 DWORD WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, IDispatch** lppDisp)
1903 IOleControlSite* lpCSite;
1904 HRESULT hRet = E_FAIL;
1906 TRACE("(%p,%p)\n", lpUnknown, lppDisp);
1907 if (lpUnknown)
1909 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1910 (void**)&lpCSite);
1911 if (SUCCEEDED(hRet) && lpCSite)
1913 hRet = IOleControlSite_GetExtendedControl(lpCSite, lppDisp);
1914 IOleControlSite_Release(lpCSite);
1917 return hRet;
1920 /*************************************************************************
1921 * @ [SHLWAPI.192]
1923 * Get a sub-menu from a menu item.
1925 * PARAMS
1926 * hMenu [I] Menu to get sub-menu from
1927 * uID [I] ID of menu item containing sub-menu
1929 * RETURNS
1930 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1932 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1934 MENUITEMINFOA mi;
1936 TRACE("(%p,%uld)\n", hMenu, uID);
1938 mi.cbSize = sizeof(MENUITEMINFOA);
1939 mi.fMask = MIIM_SUBMENU;
1941 if (!GetMenuItemInfoA(hMenu, uID, 0, &mi))
1942 return (HMENU)NULL;
1944 return mi.hSubMenu;
1947 /*************************************************************************
1948 * @ [SHLWAPI.193]
1950 * Get the color depth of the primary display.
1952 * PARAMS
1953 * None.
1955 * RETURNS
1956 * The color depth of the primary display.
1958 DWORD WINAPI SHGetCurColorRes()
1960 HDC hdc;
1961 DWORD ret;
1963 TRACE("()\n");
1965 hdc = GetDC(0);
1966 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1967 ReleaseDC(0, hdc);
1968 return ret;
1971 /*************************************************************************
1972 * @ [SHLWAPI.194]
1974 * Wait for a message to arrive, with a timeout.
1976 * PARAMS
1977 * hand [I] Handle to query
1978 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1980 * RETURNS
1981 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1982 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
1983 * message is available.
1985 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
1987 DWORD dwEndTicks = GetTickCount() + dwTimeout;
1988 DWORD dwRet;
1990 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
1992 MSG msg;
1994 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
1996 if (dwTimeout != INFINITE)
1998 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
1999 return WAIT_TIMEOUT;
2003 return dwRet;
2006 /*************************************************************************
2007 * @ [SHLWAPI.197]
2009 * Blank out a region of text by drawing the background only.
2011 * PARAMS
2012 * hDC [I] Device context to draw in
2013 * pRect [I] Area to draw in
2014 * cRef [I] Color to draw in
2016 * RETURNS
2017 * Nothing.
2019 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2021 COLORREF cOldColor = SetBkColor(hDC, cRef);
2022 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2023 SetBkColor(hDC, cOldColor);
2024 return 0;
2027 /*************************************************************************
2028 * @ [SHLWAPI.198]
2030 * Return the value asociated with a key in a map.
2032 * PARAMS
2033 * lpKeys [I] A list of keys of length iLen
2034 * lpValues [I] A list of values associated with lpKeys, of length iLen
2035 * iLen [I] Length of both lpKeys and lpValues
2036 * iKey [I] The key value to look up in lpKeys
2038 * RETURNS
2039 * The value in lpValues associated with iKey, or -1 if iKey is not
2040 * found in lpKeys.
2042 * NOTES
2043 * - If two elements in the map share the same key, this function returns
2044 * the value closest to the start of the map
2045 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2047 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2049 if (lpKeys && lpValues)
2051 int i = 0;
2053 while (i < iLen)
2055 if (lpKeys[i] == iKey)
2056 return lpValues[i]; /* Found */
2057 i++;
2060 return -1; /* Not found */
2064 /*************************************************************************
2065 * @ [SHLWAPI.199]
2067 * Copy an interface pointer
2069 * PARAMS
2070 * lppDest [O] Destination for copy
2071 * lpUnknown [I] Source for copy
2073 * RETURNS
2074 * Nothing.
2076 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2078 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2080 if (lppDest)
2081 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2083 if (lpUnknown)
2085 /* Copy */
2086 IUnknown_AddRef(lpUnknown);
2087 *lppDest = lpUnknown;
2091 /*************************************************************************
2092 * @ [SHLWAPI.201]
2095 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2096 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2097 VARIANT* pvaOut)
2099 FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2100 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2101 return DRAGDROP_E_NOTREGISTERED;
2104 /*************************************************************************
2105 * @ [SHLWAPI.202]
2108 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2110 FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2111 return DRAGDROP_E_NOTREGISTERED;
2114 /*************************************************************************
2115 * @ [SHLWAPI.204]
2117 * Determine if a window is not a child of another window.
2119 * PARAMS
2120 * hParent [I] Suspected parent window
2121 * hChild [I] Suspected child window
2123 * RETURNS
2124 * TRUE: If hChild is a child window of hParent
2125 * FALSE: If hChild is not a child window of hParent, or they are equal
2127 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2129 TRACE("(%p,%p)\n", hParent, hChild);
2131 if (!hParent || !hChild)
2132 return TRUE;
2133 else if(hParent == hChild)
2134 return FALSE;
2135 return !IsChild(hParent, hChild);
2138 /*************************************************************************
2139 * @ [SHLWAPI.208]
2141 * Some sort of memory management process.
2143 DWORD WINAPI FDSA_Initialize(
2144 DWORD a,
2145 DWORD b,
2146 LPVOID c,
2147 LPVOID d,
2148 DWORD e)
2150 FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
2151 a, b, c, d, e);
2152 return 1;
2155 /*************************************************************************
2156 * @ [SHLWAPI.209]
2158 * Some sort of memory management process.
2160 DWORD WINAPI FDSA_Destroy(
2161 LPVOID a)
2163 FIXME("(%p) stub\n",
2165 return 1;
2168 /*************************************************************************
2169 * @ [SHLWAPI.210]
2171 * Some sort of memory management process.
2173 DWORD WINAPI FDSA_InsertItem(
2174 LPVOID a,
2175 DWORD b,
2176 LPVOID c)
2178 FIXME("(%p 0x%08lx %p) stub\n",
2179 a, b, c);
2180 return 0;
2183 /*************************************************************************
2184 * @ [SHLWAPI.211]
2186 DWORD WINAPI FDSA_DeleteItem(
2187 LPVOID a,
2188 DWORD b)
2190 FIXME("(%p 0x%08lx) stub\n",
2191 a, b);
2192 return 1;
2195 typedef struct {
2196 REFIID refid;
2197 DWORD indx;
2198 } IFACE_INDEX_TBL;
2200 /*************************************************************************
2201 * @ [SHLWAPI.219]
2203 * Call IUnknown_QueryInterface() on a table of objects.
2205 * RETURNS
2206 * Success: S_OK.
2207 * Failure: E_POINTER or E_NOINTERFACE.
2209 HRESULT WINAPI QISearch(
2210 LPVOID w, /* [in] Table of interfaces */
2211 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2212 REFIID riid, /* [in] REFIID to get interface for */
2213 LPVOID *ppv) /* [out] Destination for interface pointer */
2215 HRESULT ret;
2216 IUnknown *a_vtbl;
2217 IFACE_INDEX_TBL *xmove;
2219 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2220 if (ppv) {
2221 xmove = x;
2222 while (xmove->refid) {
2223 TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2224 if (IsEqualIID(riid, xmove->refid)) {
2225 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2226 TRACE("matched, returning (%p)\n", a_vtbl);
2227 *ppv = (LPVOID)a_vtbl;
2228 IUnknown_AddRef(a_vtbl);
2229 return S_OK;
2231 xmove++;
2234 if (IsEqualIID(riid, &IID_IUnknown)) {
2235 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2236 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2237 *ppv = (LPVOID)a_vtbl;
2238 IUnknown_AddRef(a_vtbl);
2239 return S_OK;
2241 *ppv = 0;
2242 ret = E_NOINTERFACE;
2243 } else
2244 ret = E_POINTER;
2246 TRACE("-- 0x%08lx\n", ret);
2247 return ret;
2250 /*************************************************************************
2251 * @ [SHLWAPI.221]
2253 * Remove the "PropDlgFont" property from a window.
2255 * PARAMS
2256 * hWnd [I] Window to remove the property from
2258 * RETURNS
2259 * A handle to the removed property, or NULL if it did not exist.
2261 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2263 HANDLE hProp;
2265 TRACE("(%p)\n", hWnd);
2267 hProp = GetPropA(hWnd, "PropDlgFont");
2269 if(hProp)
2271 DeleteObject(hProp);
2272 hProp = RemovePropA(hWnd, "PropDlgFont");
2274 return hProp;
2277 /*************************************************************************
2278 * @ [SHLWAPI.236]
2280 * Load the in-process server of a given GUID.
2282 * PARAMS
2283 * refiid [I] GUID of the server to load.
2285 * RETURNS
2286 * Success: A handle to the loaded server dll.
2287 * Failure: A NULL handle.
2289 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2291 HKEY newkey;
2292 DWORD type, count;
2293 CHAR value[MAX_PATH], string[MAX_PATH];
2295 strcpy(string, "CLSID\\");
2296 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2297 strcat(string, "\\InProcServer32");
2299 count = MAX_PATH;
2300 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2301 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2302 RegCloseKey(newkey);
2303 return LoadLibraryExA(value, 0, 0);
2306 /*************************************************************************
2307 * @ [SHLWAPI.237]
2309 * Unicode version of SHLWAPI_183.
2311 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2313 WNDCLASSW WndClass;
2315 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2317 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2318 return TRUE;
2319 return RegisterClassW(lpWndClass);
2322 /*************************************************************************
2323 * @ [SHLWAPI.238]
2325 * Unregister a list of classes.
2327 * PARAMS
2328 * hInst [I] Application instance that registered the classes
2329 * lppClasses [I] List of class names
2330 * iCount [I] Number of names in lppClasses
2332 * RETURNS
2333 * Nothing.
2335 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2337 WNDCLASSA WndClass;
2339 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2341 while (iCount > 0)
2343 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2344 UnregisterClassA(*lppClasses, hInst);
2345 lppClasses++;
2346 iCount--;
2350 /*************************************************************************
2351 * @ [SHLWAPI.239]
2353 * Unicode version of SHUnregisterClassesA.
2355 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2357 WNDCLASSW WndClass;
2359 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2361 while (iCount > 0)
2363 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2364 UnregisterClassW(*lppClasses, hInst);
2365 lppClasses++;
2366 iCount--;
2370 /*************************************************************************
2371 * @ [SHLWAPI.240]
2373 * Call The correct (Ascii/Unicode) default window procedure for a window.
2375 * PARAMS
2376 * hWnd [I] Window to call the default procedure for
2377 * uMessage [I] Message ID
2378 * wParam [I] WPARAM of message
2379 * lParam [I] LPARAM of message
2381 * RETURNS
2382 * The result of calling DefWindowProcA() or DefWindowProcW().
2384 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2386 if (IsWindowUnicode(hWnd))
2387 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2388 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2391 /*************************************************************************
2392 * @ [SHLWAPI.257]
2394 * Create a worker window using CreateWindowExA().
2396 * PARAMS
2397 * wndProc [I] Window procedure
2398 * hWndParent [I] Parent window
2399 * dwExStyle [I] Extra style flags
2400 * dwStyle [I] Style flags
2401 * hMenu [I] Window menu
2402 * z [I] Unknown
2404 * RETURNS
2405 * Success: The window handle of the newly created window.
2406 * Failure: 0.
2408 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2409 DWORD dwStyle, HMENU hMenu, LONG z)
2411 static const char* szClass = "WorkerA";
2412 WNDCLASSA wc;
2413 HWND hWnd;
2415 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2416 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2418 /* Create Window class */
2419 wc.style = 0;
2420 wc.lpfnWndProc = DefWindowProcA;
2421 wc.cbClsExtra = 0;
2422 wc.cbWndExtra = 4;
2423 wc.hInstance = shlwapi_hInstance;
2424 wc.hIcon = (HICON)0;
2425 wc.hCursor = LoadCursorA((HINSTANCE)0, (LPSTR)IDC_ARROW);
2426 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2427 wc.lpszMenuName = NULL;
2428 wc.lpszClassName = szClass;
2430 SHRegisterClassA(&wc); /* Register class */
2432 /* FIXME: Set extra bits in dwExStyle */
2434 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2435 hWndParent, hMenu, shlwapi_hInstance, 0);
2436 if (hWnd)
2438 SetWindowLongA(hWnd, DWL_MSGRESULT, z);
2440 if (wndProc)
2441 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2443 return hWnd;
2446 typedef struct tagPOLICYDATA
2448 DWORD policy; /* flags value passed to SHRestricted */
2449 LPCWSTR appstr; /* application str such as "Explorer" */
2450 LPCWSTR keystr; /* name of the actual registry key / policy */
2451 } POLICYDATA, *LPPOLICYDATA;
2453 #define SHELL_NO_POLICY 0xffffffff
2455 /* default shell policy registry key */
2456 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2457 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2458 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2459 '\\','P','o','l','i','c','i','e','s',0};
2461 /*************************************************************************
2462 * @ [SHLWAPI.271]
2464 * Retrieve a policy value from the registry.
2466 * PARAMS
2467 * lpSubKey [I] registry key name
2468 * lpSubName [I] subname of registry key
2469 * lpValue [I] value name of registry value
2471 * RETURNS
2472 * the value associated with the registry key or 0 if not found
2474 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2476 DWORD retval, datsize = sizeof(retval);
2477 HKEY hKey;
2479 if (!lpSubKey)
2480 lpSubKey = strRegistryPolicyW;
2482 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2483 if (retval != ERROR_SUCCESS)
2484 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2485 if (retval != ERROR_SUCCESS)
2486 return 0;
2488 SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);
2489 RegCloseKey(hKey);
2490 return retval;
2493 /*************************************************************************
2494 * @ [SHLWAPI.266]
2496 * Helper function to retrieve the possibly cached value for a specific policy
2498 * PARAMS
2499 * policy [I] The policy to look for
2500 * initial [I] Main registry key to open, if NULL use default
2501 * polTable [I] Table of known policies, 0 terminated
2502 * polArr [I] Cache array of policy values
2504 * RETURNS
2505 * The retrieved policy value or 0 if not successful
2507 * NOTES
2508 * This function is used by the native SHRestricted function to search for the
2509 * policy and cache it once retrieved. The current Wine implementation uses a
2510 * different POLICYDATA structure and implements a similar algorithme adapted to
2511 * that structure.
2513 DWORD WINAPI SHRestrictionLookup(
2514 DWORD policy,
2515 LPCWSTR initial,
2516 LPPOLICYDATA polTable,
2517 LPDWORD polArr)
2519 TRACE("(0x%08lx %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2521 if (!polTable || !polArr)
2522 return 0;
2524 for (;polTable->policy; polTable++, polArr++)
2526 if (policy == polTable->policy)
2528 /* we have a known policy */
2530 /* check if this policy has been cached */
2531 if (*polArr == SHELL_NO_POLICY)
2532 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2533 return *polArr;
2536 /* we don't know this policy, return 0 */
2537 TRACE("unknown policy: (%08lx)\n", policy);
2538 return 0;
2541 /*************************************************************************
2542 * @ [SHLWAPI.267]
2544 * Get an interface from an object.
2546 * RETURNS
2547 * Success: S_OK. ppv contains the requested interface.
2548 * Failure: An HRESULT error code.
2550 * NOTES
2551 * This QueryInterface asks the inner object for a interface. In case
2552 * of aggregation this request would be forwarded by the inner to the
2553 * outer object. This function asks the inner object directly for the
2554 * interface circumventing the forwarding to the outer object.
2556 HRESULT WINAPI SHWeakQueryInterface(
2557 IUnknown * pUnk, /* [in] Outer object */
2558 IUnknown * pInner, /* [in] Inner object */
2559 IID * riid, /* [in] Interface GUID to query for */
2560 LPVOID* ppv) /* [out] Destination for queried interface */
2562 HRESULT hret = E_NOINTERFACE;
2563 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2565 *ppv = NULL;
2566 if(pUnk && pInner) {
2567 hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
2568 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2570 TRACE("-- 0x%08lx\n", hret);
2571 return hret;
2574 /*************************************************************************
2575 * @ [SHLWAPI.268]
2577 * Move a reference from one interface to another.
2579 * PARAMS
2580 * lpDest [O] Destination to receive the reference
2581 * lppUnknown [O] Source to give up the reference to lpDest
2583 * RETURNS
2584 * Nothing.
2586 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2588 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2590 if (*lppUnknown)
2592 /* Copy Reference*/
2593 IUnknown_AddRef(lpDest);
2594 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2598 /*************************************************************************
2599 * @ [SHLWAPI.269]
2601 * Convert an ASCII string of a CLSID into a CLSID.
2603 * PARAMS
2604 * idstr [I] String representing a CLSID in registry format
2605 * id [O] Destination for the converted CLSID
2607 * RETURNS
2608 * Success: TRUE. id contains the converted CLSID.
2609 * Failure: FALSE.
2611 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2613 WCHAR wClsid[40];
2614 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2615 return SUCCEEDED(CLSIDFromStringWrap(wClsid, id));
2618 /*************************************************************************
2619 * @ [SHLWAPI.270]
2621 * Unicode version of GUIDFromStringA.
2623 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2625 return SUCCEEDED(CLSIDFromStringWrap(idstr, id));
2628 /*************************************************************************
2629 * @ [SHLWAPI.276]
2631 * Determine if the browser is integrated into the shell, and set a registry
2632 * key accordingly.
2634 * PARAMS
2635 * None.
2637 * RETURNS
2638 * 1, If the browser is not integrated.
2639 * 2, If the browser is integrated.
2641 * NOTES
2642 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2643 * either set to TRUE, or removed depending on whether the browser is deemed
2644 * to be integrated.
2646 DWORD WINAPI WhichPlatform()
2648 static LPCSTR szIntegratedBrowser = "IntegratedBrowser";
2649 static DWORD dwState = 0;
2650 HKEY hKey;
2651 DWORD dwRet, dwData, dwSize;
2653 if (dwState)
2654 return dwState;
2656 /* If shell32 exports DllGetVersion(), the browser is integrated */
2657 GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);
2658 dwState = pDllGetVersion ? 2 : 1;
2660 /* Set or delete the key accordingly */
2661 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2662 "Software\\Microsoft\\Internet Explorer", 0,
2663 KEY_ALL_ACCESS, &hKey);
2664 if (!dwRet)
2666 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2667 (LPBYTE)&dwData, &dwSize);
2669 if (!dwRet && dwState == 1)
2671 /* Value exists but browser is not integrated */
2672 RegDeleteValueA(hKey, szIntegratedBrowser);
2674 else if (dwRet && dwState == 2)
2676 /* Browser is integrated but value does not exist */
2677 dwData = TRUE;
2678 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2679 (LPBYTE)&dwData, sizeof(dwData));
2681 RegCloseKey(hKey);
2683 return dwState;
2686 /*************************************************************************
2687 * @ [SHLWAPI.278]
2689 * Unicode version of SHCreateWorkerWindowA.
2691 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2692 DWORD dwStyle, HMENU hMenu, LONG z)
2694 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2695 WNDCLASSW wc;
2696 HWND hWnd;
2698 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2699 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2701 /* If our OS is natively ASCII, use the ASCII version */
2702 if (!(GetVersion() & 0x80000000)) /* NT */
2703 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2705 /* Create Window class */
2706 wc.style = 0;
2707 wc.lpfnWndProc = DefWindowProcW;
2708 wc.cbClsExtra = 0;
2709 wc.cbWndExtra = 4;
2710 wc.hInstance = shlwapi_hInstance;
2711 wc.hIcon = (HICON)0;
2712 wc.hCursor = LoadCursorA((HINSTANCE)0, (LPSTR)IDC_ARROW);
2713 wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
2714 wc.lpszMenuName = NULL;
2715 wc.lpszClassName = szClass;
2717 SHRegisterClassW(&wc); /* Register class */
2719 /* FIXME: Set extra bits in dwExStyle */
2721 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2722 hWndParent, hMenu, shlwapi_hInstance, 0);
2723 if (hWnd)
2725 SetWindowLongA(hWnd, DWL_MSGRESULT, z);
2727 if (wndProc)
2728 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2730 return hWnd;
2733 /*************************************************************************
2734 * @ [SHLWAPI.279]
2736 * Get and show a context menu from a shell folder.
2738 * PARAMS
2739 * hWnd [I] Window displaying the shell folder
2740 * lpFolder [I] IShellFolder interface
2741 * lpApidl [I] Id for the particular folder desired
2743 * RETURNS
2744 * Success: S_OK.
2745 * Failure: An HRESULT error code indicating the error.
2747 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2749 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2752 /*************************************************************************
2753 * @ [SHLWAPI.281]
2755 * _SHPackDispParamsV
2757 HRESULT WINAPI SHPackDispParamsV(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2759 FIXME("%p %p %p %p\n",w,x,y,z);
2760 return E_FAIL;
2763 /*************************************************************************
2764 * @ [SHLWAPI.282]
2766 * This function seems to be a forward to SHPackDispParamsV (whatever THAT
2767 * function does...).
2769 HRESULT WINAPI SHPackDispParams(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2771 FIXME("%p %p %p %p\n", w, x, y, z);
2772 return E_FAIL;
2775 /*************************************************************************
2776 * @ [SHLWAPI.284]
2778 * _IConnectionPoint_SimpleInvoke
2780 DWORD WINAPI IConnectionPoint_SimpleInvoke(
2781 LPVOID x,
2782 LPVOID y,
2783 LPVOID z)
2785 FIXME("(%p %p %p) stub\n",x,y,z);
2786 return 0;
2789 /*************************************************************************
2790 * @ [SHLWAPI.285]
2792 * Notify an IConnectionPoint object of changes.
2794 * PARAMS
2795 * lpCP [I] Object to notify
2796 * dispID [I]
2798 * RETURNS
2799 * Success: S_OK.
2800 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
2801 * IConnectionPoint interface.
2803 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
2805 IEnumConnections *lpEnum;
2806 HRESULT hRet = E_NOINTERFACE;
2808 TRACE("(%p,0x%8lX)\n", lpCP, dispID);
2810 /* Get an enumerator for the connections */
2811 if (lpCP)
2812 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
2814 if (SUCCEEDED(hRet))
2816 IPropertyNotifySink *lpSink;
2817 CONNECTDATA connData;
2818 ULONG ulFetched;
2820 /* Call OnChanged() for every notify sink in the connection point */
2821 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
2823 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
2824 lpSink)
2826 IPropertyNotifySink_OnChanged(lpSink, dispID);
2827 IPropertyNotifySink_Release(lpSink);
2829 IUnknown_Release(connData.pUnk);
2832 IEnumConnections_Release(lpEnum);
2834 return hRet;
2837 /*************************************************************************
2838 * @ [SHLWAPI.287]
2840 * Notify an IConnectionPointContainer object of changes.
2842 * PARAMS
2843 * lpUnknown [I] Object to notify
2844 * dispID [I]
2846 * RETURNS
2847 * Success: S_OK.
2848 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
2849 * IConnectionPointContainer interface.
2851 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
2853 IConnectionPointContainer* lpCPC = NULL;
2854 HRESULT hRet = E_NOINTERFACE;
2856 TRACE("(%p,0x%8lX)\n", lpUnknown, dispID);
2858 if (lpUnknown)
2859 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
2861 if (SUCCEEDED(hRet))
2863 IConnectionPoint* lpCP;
2865 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
2866 IConnectionPointContainer_Release(lpCPC);
2868 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
2869 IConnectionPoint_Release(lpCP);
2871 return hRet;
2874 /*************************************************************************
2875 * @ [SHLWAPI.289]
2877 * See PlaySoundW.
2879 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
2881 GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
2882 return pPlaySoundW(pszSound, hmod, fdwSound);
2885 /*************************************************************************
2886 * @ [SHLWAPI.294]
2888 BOOL WINAPI SHGetIniStringW(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len, LPCSTR lpStr2)
2891 * str1: "I" "I" pushl esp+0x20
2892 * str2: "U" "I" pushl 0x77c93810
2893 * (is "I" and "U" "integer" and "unsigned" ??)
2895 * pStr: "" "" pushl eax
2896 * some_len: 0x824 0x104 pushl 0x824
2897 * lpStr2: "%l" "%l" pushl esp+0xc
2899 * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
2900 * LocalAlloc(0x00, some_len) -> irrelevant_var
2901 * LocalAlloc(0x40, irrelevant_len) -> pStr
2902 * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
2903 * shlwapi.PathRemoveBlanksW(pStr);
2905 FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
2906 return TRUE;
2909 /*************************************************************************
2910 * @ [SHLWAPI.295]
2912 * Called by ICQ2000b install via SHDOCVW:
2913 * str1: "InternetShortcut"
2914 * x: some unknown pointer
2915 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
2916 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
2918 * In short: this one maybe creates a desktop link :-)
2920 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
2922 FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
2923 return TRUE;
2926 /*************************************************************************
2927 * @ [SHLWAPI.299]
2929 * See COMCTL32_417.
2931 BOOL WINAPI ExtTextOutWrapW(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
2932 LPCWSTR str, UINT count, const INT *lpDx)
2934 GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);
2935 return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);
2938 /*************************************************************************
2939 * @ [SHLWAPI.313]
2941 * See SHGetFileInfoW.
2943 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
2944 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
2946 GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
2947 return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
2950 /*************************************************************************
2951 * @ [SHLWAPI.318]
2953 * See DragQueryFileW.
2955 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
2957 GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
2958 return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
2961 /*************************************************************************
2962 * @ [SHLWAPI.333]
2964 * See SHBrowseForFolderW.
2966 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
2968 GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
2969 return pSHBrowseForFolderW(lpBi);
2972 /*************************************************************************
2973 * @ [SHLWAPI.334]
2975 * See SHGetPathFromIDListW.
2977 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
2979 GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
2980 return pSHGetPathFromIDListW(pidl, pszPath);
2983 /*************************************************************************
2984 * @ [SHLWAPI.335]
2986 * See ShellExecuteExW.
2988 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
2990 GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
2991 return pShellExecuteExW(lpExecInfo);
2994 /*************************************************************************
2995 * @ [SHLWAPI.336]
2997 * See SHFileOperationW.
2999 HICON WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3001 GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
3002 return pSHFileOperationW(lpFileOp);
3005 /*************************************************************************
3006 * @ [SHLWAPI.337]
3008 * See ExtractIconExW.
3010 UINT WINAPI ExtractIconExWrapW(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
3011 HICON *phiconSmall, UINT nIcons)
3013 GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", 0);
3014 return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
3017 /*************************************************************************
3018 * @ [SHLWAPI.342]
3021 LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
3023 return InterlockedCompareExchange(dest, xchg, compare);
3026 /*************************************************************************
3027 * @ [SHLWAPI.350]
3029 * See GetFileVersionInfoSizeW.
3031 DWORD WINAPI GetFileVersionInfoSizeWrapW(
3032 LPWSTR x,
3033 LPVOID y)
3035 DWORD ret;
3037 GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
3038 ret = pGetFileVersionInfoSizeW(x, y);
3039 return 0x208 + ret;
3042 /*************************************************************************
3043 * @ [SHLWAPI.351]
3045 * See GetFileVersionInfoW.
3047 BOOL WINAPI GetFileVersionInfoWrapW(
3048 LPWSTR w, /* [in] path to dll */
3049 DWORD x, /* [in] parm 2 to GetFileVersionInfoA */
3050 DWORD y, /* [in] return value from SHLWAPI_350() - assume length */
3051 LPVOID z) /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA()) */
3053 GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
3054 return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);
3057 /*************************************************************************
3058 * @ [SHLWAPI.352]
3060 * See VerQueryValueW.
3062 WORD WINAPI VerQueryValueWrapW(
3063 LPVOID w, /* [in] Buffer from SHLWAPI_351() */
3064 LPWSTR x, /* [in] Value to retrieve - converted and passed to VerQueryValueA() as #2 */
3065 LPVOID y, /* [out] Ver buffer - passed to VerQueryValueA as #3 */
3066 UINT* z) /* [in] Ver length - passed to VerQueryValueA as #4 */
3068 GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
3069 return pVerQueryValueW((char*)w+0x208, x, y, z);
3072 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3073 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3074 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3076 /*************************************************************************
3077 * @ [SHLWAPI.355]
3079 * Change the modality of a shell object.
3081 * PARAMS
3082 * lpUnknown [I] Object to make modeless
3083 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3085 * RETURNS
3086 * Success: S_OK. The modality lpUnknown is changed.
3087 * Failure: An HRESULT error code indicating the error.
3089 * NOTES
3090 * lpUnknown must support the IOleInPlaceFrame interface, the
3091 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3092 * or the IDocHostUIHandler interface, or this call fails.
3094 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3096 IUnknown *lpObj;
3097 HRESULT hRet;
3099 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3101 if (!lpUnknown)
3102 return E_FAIL;
3104 if (IsIface(IOleInPlaceFrame))
3105 EnableModeless(IOleInPlaceFrame);
3106 else if (IsIface(IShellBrowser))
3107 EnableModeless(IShellBrowser);
3108 #if 0
3109 /* FIXME: Wine has no headers for these objects yet */
3110 else if (IsIface(IInternetSecurityMgrSite))
3111 EnableModeless(IInternetSecurityMgrSite);
3112 else if (IsIface(IDocHostUIHandler))
3113 EnableModeless(IDocHostUIHandler);
3114 #endif
3115 else
3116 return hRet;
3118 IUnknown_Release(lpObj);
3119 return S_OK;
3122 /*************************************************************************
3123 * @ [SHLWAPI.357]
3125 * See SHGetNewLinkInfoW.
3127 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3128 BOOL *pfMustCopy, UINT uFlags)
3130 GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
3131 return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3134 /*************************************************************************
3135 * @ [SHLWAPI.358]
3137 * See SHDefExtractIconW.
3139 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3140 HICON* phiconSmall, UINT nIconSize)
3142 GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
3143 return pSHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3146 /*************************************************************************
3147 * @ [SHLWAPI.363]
3149 * Get and show a context menu from a shell folder.
3151 * PARAMS
3152 * hWnd [I] Window displaying the shell folder
3153 * lpFolder [I] IShellFolder interface
3154 * lpApidl [I] Id for the particular folder desired
3155 * bInvokeDefault [I] Whether to invoke the default menu item
3157 * RETURNS
3158 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3159 * executed.
3160 * Failure: An HRESULT error code indicating the error.
3162 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3164 IContextMenu *iContext;
3165 HRESULT hRet = E_FAIL;
3167 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3169 if (!lpFolder)
3170 return hRet;
3172 /* Get the context menu from the shell folder */
3173 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3174 &IID_IContextMenu, 0, (void**)&iContext);
3175 if (SUCCEEDED(hRet))
3177 HMENU hMenu;
3178 if ((hMenu = CreatePopupMenu()))
3180 HRESULT hQuery;
3181 DWORD dwDefaultId = 0;
3183 /* Add the context menu entries to the popup */
3184 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3185 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3187 if (SUCCEEDED(hQuery))
3189 if (bInvokeDefault &&
3190 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3192 CMINVOKECOMMANDINFO cmIci;
3193 /* Invoke the default item */
3194 memset(&cmIci,0,sizeof(cmIci));
3195 cmIci.cbSize = sizeof(cmIci);
3196 cmIci.fMask = CMIC_MASK_ASYNCOK;
3197 cmIci.hwnd = hWnd;
3198 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3199 cmIci.nShow = SW_SCROLLCHILDREN;
3201 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3204 DestroyMenu(hMenu);
3206 IContextMenu_Release(iContext);
3208 return hRet;
3211 /*************************************************************************
3212 * @ [SHLWAPI.370]
3214 * See ExtractIconW.
3216 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3217 UINT nIconIndex)
3219 GET_FUNC(pExtractIconW, shell32, "ExtractIconW", NULL);
3220 return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3223 /*************************************************************************
3224 * @ [SHLWAPI.376]
3226 LANGID WINAPI MLGetUILanguage()
3228 FIXME("() stub\n");
3229 /* FIXME: This should be a forward in the .spec file to the win2k function
3230 * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
3232 return GetUserDefaultLangID();
3235 /*************************************************************************
3236 * @ [SHLWAPI.377]
3238 * Load a library from the directory of a particular process.
3240 * PARAMS
3241 * new_mod [I] Library name
3242 * inst_hwnd [I] Module whose directory is to be used
3243 * dwFlags [I] Flags controlling the load
3245 * RETURNS
3246 * Success: A handle to the loaded module
3247 * Failure: A NULL handle.
3249 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3251 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3252 * each call here.
3253 * FIXME: Native shows calls to:
3254 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3255 * CheckVersion
3256 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3257 * RegQueryValueExA for "LPKInstalled"
3258 * RegCloseKey
3259 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3260 * RegQueryValueExA for "ResourceLocale"
3261 * RegCloseKey
3262 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3263 * RegQueryValueExA for "Locale"
3264 * RegCloseKey
3265 * and then tests the Locale ("en" for me).
3266 * code below
3267 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3269 CHAR mod_path[2*MAX_PATH];
3270 LPSTR ptr;
3271 DWORD len;
3273 FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwFlags);
3274 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3275 if (!len || len >= sizeof(mod_path)) return NULL;
3277 ptr = strrchr(mod_path, '\\');
3278 if (ptr) {
3279 strcpy(ptr+1, new_mod);
3280 TRACE("loading %s\n", debugstr_a(mod_path));
3281 return LoadLibraryA(mod_path);
3283 return NULL;
3286 /*************************************************************************
3287 * @ [SHLWAPI.378]
3289 * Unicode version of MLLoadLibraryA.
3291 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
3293 WCHAR mod_path[2*MAX_PATH];
3294 LPWSTR ptr;
3295 DWORD len;
3297 FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwFlags);
3298 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3299 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3301 ptr = strrchrW(mod_path, '\\');
3302 if (ptr) {
3303 strcpyW(ptr+1, new_mod);
3304 TRACE("loading %s\n", debugstr_w(mod_path));
3305 return LoadLibraryW(mod_path);
3307 return NULL;
3310 /*************************************************************************
3311 * ColorAdjustLuma [SHLWAPI.@]
3313 * Adjust the luminosity of a color
3315 * PARAMS
3316 * cRGB [I] RGB value to convert
3317 * dwLuma [I] Luma adjustment
3318 * bUnknown [I] Unknown
3320 * RETURNS
3321 * The adjusted RGB color.
3323 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3325 TRACE("(0x%8lx,%d,%d)\n", cRGB, dwLuma, bUnknown);
3327 if (dwLuma)
3329 WORD wH, wL, wS;
3331 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3333 FIXME("Ignoring luma adjustment\n");
3335 /* FIXME: The ajdustment is not linear */
3337 cRGB = ColorHLSToRGB(wH, wL, wS);
3339 return cRGB;
3342 /*************************************************************************
3343 * @ [SHLWAPI.389]
3345 * See GetSaveFileNameW.
3347 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3349 GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
3350 return pGetSaveFileNameW(ofn);
3353 /*************************************************************************
3354 * @ [SHLWAPI.390]
3356 * See WNetRestoreConnectionW.
3358 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3360 GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
3361 return pWNetRestoreConnectionW(hwndOwner, lpszDevice);
3364 /*************************************************************************
3365 * @ [SHLWAPI.391]
3367 * See WNetGetLastErrorW.
3369 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3370 LPWSTR lpNameBuf, DWORD nNameBufSize)
3372 GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
3373 return pWNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3376 /*************************************************************************
3377 * @ [SHLWAPI.401]
3379 * See PageSetupDlgW.
3381 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3383 GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
3384 return pPageSetupDlgW(pagedlg);
3387 /*************************************************************************
3388 * @ [SHLWAPI.402]
3390 * See PrintDlgW.
3392 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3394 GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
3395 return pPrintDlgW(printdlg);
3398 /*************************************************************************
3399 * @ [SHLWAPI.403]
3401 * See GetOpenFileNameW.
3403 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3405 GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
3406 return pGetOpenFileNameW(ofn);
3409 /* INTERNAL: Map from HLS color space to RGB */
3410 static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3412 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3414 if (wHue > 160)
3415 return wMid1;
3416 else if (wHue > 120)
3417 wHue = 160 - wHue;
3418 else if (wHue > 40)
3419 return wMid2;
3421 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3424 /* Convert to RGB and scale into RGB range (0..255) */
3425 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3427 /*************************************************************************
3428 * ColorHLSToRGB [SHLWAPI.@]
3430 * Convert from hls color space into an rgb COLORREF.
3432 * PARAMS
3433 * wHue [I] Hue amount
3434 * wLuminosity [I] Luminosity amount
3435 * wSaturation [I] Saturation amount
3437 * RETURNS
3438 * A COLORREF representing the converted color.
3440 * NOTES
3441 * Input hls values are constrained to the range (0..240).
3443 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3445 WORD wRed;
3447 if (wSaturation)
3449 WORD wGreen, wBlue, wMid1, wMid2;
3451 if (wLuminosity > 120)
3452 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3453 else
3454 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3456 wMid1 = wLuminosity * 2 - wMid2;
3458 wRed = GET_RGB(wHue + 80);
3459 wGreen = GET_RGB(wHue);
3460 wBlue = GET_RGB(wHue - 80);
3462 return RGB(wRed, wGreen, wBlue);
3465 wRed = wLuminosity * 255 / 240;
3466 return RGB(wRed, wRed, wRed);
3469 /*************************************************************************
3470 * @ [SHLWAPI.413]
3472 * Get the current docking status of the system.
3474 * PARAMS
3475 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3477 * RETURNS
3478 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3479 * a notebook.
3481 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3483 HW_PROFILE_INFOA hwInfo;
3485 TRACE("(0x%08lx)\n", dwFlags);
3487 GetCurrentHwProfileA(&hwInfo);
3488 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3490 case DOCKINFO_DOCKED:
3491 case DOCKINFO_UNDOCKED:
3492 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3493 default:
3494 return 0;
3498 /*************************************************************************
3499 * @ [SHLWAPI.418]
3501 * Function seems to do FreeLibrary plus other things.
3503 * FIXME native shows the following calls:
3504 * RtlEnterCriticalSection
3505 * LocalFree
3506 * GetProcAddress(Comctl32??, 150L)
3507 * DPA_DeletePtr
3508 * RtlLeaveCriticalSection
3509 * followed by the FreeLibrary.
3510 * The above code may be related to .377 above.
3512 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3514 FIXME("(%p) semi-stub\n", hModule);
3515 return FreeLibrary(hModule);
3518 /*************************************************************************
3519 * @ [SHLWAPI.419]
3521 BOOL WINAPI SHFlushSFCacheWrap(void) {
3522 FIXME(": stub\n");
3523 return TRUE;
3526 /*************************************************************************
3527 * @ [SHLWAPI.429]
3528 * FIXME I have no idea what this function does or what its arguments are.
3530 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3532 FIXME("(%p) stub\n", hInst);
3533 return FALSE;
3537 /*************************************************************************
3538 * @ [SHLWAPI.430]
3540 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3542 FIXME("(%p,%p) stub\n", hInst, hHeap);
3543 return E_FAIL; /* This is what is used if shlwapi not loaded */
3546 /*************************************************************************
3547 * @ [SHLWAPI.431]
3549 DWORD WINAPI MLClearMLHInstance(DWORD x)
3551 FIXME("(0x%08lx)stub\n", x);
3552 return 0xabba1247;
3555 /*************************************************************************
3556 * @ [SHLWAPI.436]
3558 * Convert an Unicode string CLSID into a CLSID.
3560 * PARAMS
3561 * idstr [I] string containing a CLSID in text form
3562 * id [O] CLSID extracted from the string
3564 * RETURNS
3565 * S_OK on success or E_INVALIDARG on failure
3567 * NOTES
3568 * This is really CLSIDFromString() which is exported by ole32.dll,
3569 * however the native shlwapi.dll does *not* import ole32. Nor does
3570 * ole32.dll import this ordinal from shlwapi. Therefore we must conclude
3571 * that MS duplicated the code for CLSIDFromString(), and yes they did, only
3572 * it returns an E_INVALIDARG error code on failure.
3573 * This is a duplicate (with changes for Unicode) of CLSIDFromString16()
3574 * in "dlls/ole32/compobj.c".
3576 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3578 LPCWSTR s = idstr;
3579 BYTE *p;
3580 INT i;
3581 WCHAR table[256];
3583 if (!s) {
3584 memset(id, 0, sizeof(CLSID));
3585 return S_OK;
3587 else { /* validate the CLSID string */
3589 if (strlenW(s) != 38)
3590 return E_INVALIDARG;
3592 if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
3593 return E_INVALIDARG;
3595 for (i=1; i<37; i++)
3597 if ((i == 9)||(i == 14)||(i == 19)||(i == 24))
3598 continue;
3599 if (!(((s[i] >= L'0') && (s[i] <= L'9')) ||
3600 ((s[i] >= L'a') && (s[i] <= L'f')) ||
3601 ((s[i] >= L'A') && (s[i] <= L'F')))
3603 return E_INVALIDARG;
3607 TRACE("%s -> %p\n", debugstr_w(s), id);
3609 /* quick lookup table */
3610 memset(table, 0, 256*sizeof(WCHAR));
3612 for (i = 0; i < 10; i++) {
3613 table['0' + i] = i;
3615 for (i = 0; i < 6; i++) {
3616 table['A' + i] = i+10;
3617 table['a' + i] = i+10;
3620 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
3622 p = (BYTE *) id;
3624 s++; /* skip leading brace */
3625 for (i = 0; i < 4; i++) {
3626 p[3 - i] = table[*s]<<4 | table[*(s+1)];
3627 s += 2;
3629 p += 4;
3630 s++; /* skip - */
3632 for (i = 0; i < 2; i++) {
3633 p[1-i] = table[*s]<<4 | table[*(s+1)];
3634 s += 2;
3636 p += 2;
3637 s++; /* skip - */
3639 for (i = 0; i < 2; i++) {
3640 p[1-i] = table[*s]<<4 | table[*(s+1)];
3641 s += 2;
3643 p += 2;
3644 s++; /* skip - */
3646 /* these are just sequential bytes */
3647 for (i = 0; i < 2; i++) {
3648 *p++ = table[*s]<<4 | table[*(s+1)];
3649 s += 2;
3651 s++; /* skip - */
3653 for (i = 0; i < 6; i++) {
3654 *p++ = table[*s]<<4 | table[*(s+1)];
3655 s += 2;
3658 return S_OK;
3661 /*************************************************************************
3662 * @ [SHLWAPI.437]
3664 * Determine if the OS supports a given feature.
3666 * PARAMS
3667 * dwFeature [I] Feature requested (undocumented)
3669 * RETURNS
3670 * TRUE If the feature is available.
3671 * FALSE If the feature is not available.
3673 BOOL WINAPI IsOS(DWORD feature)
3675 OSVERSIONINFOA osvi;
3676 DWORD platform, majorv, minorv;
3678 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3679 if(!GetVersionExA(&osvi)) {
3680 ERR("GetVersionEx failed");
3681 return FALSE;
3684 majorv = osvi.dwMajorVersion;
3685 minorv = osvi.dwMinorVersion;
3686 platform = osvi.dwPlatformId;
3688 #define ISOS_RETURN(x) \
3689 TRACE("(0x%lx) ret=%d\n",feature,(x)); \
3690 return (x);
3692 switch(feature) {
3693 case OS_WIN32SORGREATER:
3694 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3695 || platform == VER_PLATFORM_WIN32_WINDOWS)
3696 case OS_NT:
3697 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3698 case OS_WIN95ORGREATER:
3699 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3700 case OS_NT4ORGREATER:
3701 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3702 case OS_WIN2000ORGREATER_ALT:
3703 case OS_WIN2000ORGREATER:
3704 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3705 case OS_WIN98ORGREATER:
3706 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3707 case OS_WIN98_GOLD:
3708 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3709 case OS_WIN2000PRO:
3710 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3711 case OS_WIN2000SERVER:
3712 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3713 case OS_WIN2000ADVSERVER:
3714 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3715 case OS_WIN2000DATACENTER:
3716 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3717 case OS_WIN2000TERMINAL:
3718 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3719 case OS_EMBEDDED:
3720 FIXME("(OS_EMBEDDED) What should we return here?\n");
3721 return FALSE;
3722 case OS_TERMINALCLIENT:
3723 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3724 return FALSE;
3725 case OS_TERMINALREMOTEADMIN:
3726 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3727 return FALSE;
3728 case OS_WIN95_GOLD:
3729 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3730 case OS_MEORGREATER:
3731 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3732 case OS_XPORGREATER:
3733 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3734 case OS_HOME:
3735 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3736 case OS_PROFESSIONAL:
3737 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3738 case OS_DATACENTER:
3739 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3740 case OS_ADVSERVER:
3741 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3742 case OS_SERVER:
3743 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3744 case OS_TERMINALSERVER:
3745 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3746 case OS_PERSONALTERMINALSERVER:
3747 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3748 case OS_FASTUSERSWITCHING:
3749 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3750 return TRUE;
3751 case OS_WELCOMELOGONUI:
3752 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3753 return FALSE;
3754 case OS_DOMAINMEMBER:
3755 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3756 return TRUE;
3757 case OS_ANYSERVER:
3758 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3759 case OS_WOW6432:
3760 FIXME("(OS_WOW6432) Should we check this?\n");
3761 return FALSE;
3762 case OS_WEBSERVER:
3763 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3764 case OS_SMALLBUSINESSSERVER:
3765 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3766 case OS_TABLETPC:
3767 FIXME("(OS_TABLEPC) What should we return here?\n");
3768 return FALSE;
3769 case OS_SERVERADMINUI:
3770 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3771 return FALSE;
3772 case OS_MEDIACENTER:
3773 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3774 return FALSE;
3775 case OS_APPLIANCE:
3776 FIXME("(OS_APPLIANCE) What should we return here?\n");
3777 return FALSE;
3780 #undef ISOS_RETURN
3782 WARN("(0x%lx) unknown parameter\n",feature);
3784 return FALSE;
3787 /*************************************************************************
3788 * ColorRGBToHLS [SHLWAPI.@]
3790 * Convert an rgb COLORREF into the hls color space.
3792 * PARAMS
3793 * cRGB [I] Source rgb value
3794 * pwHue [O] Destination for converted hue
3795 * pwLuminance [O] Destination for converted luminance
3796 * pwSaturation [O] Destination for converted saturation
3798 * RETURNS
3799 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
3800 * values.
3802 * NOTES
3803 * Output HLS values are constrained to the range (0..240).
3804 * For Achromatic conversions, Hue is set to 160.
3806 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
3807 LPWORD pwLuminance, LPWORD pwSaturation)
3809 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
3811 TRACE("(%08lx,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
3813 wR = GetRValue(cRGB);
3814 wG = GetGValue(cRGB);
3815 wB = GetBValue(cRGB);
3817 wMax = max(wR, max(wG, wB));
3818 wMin = min(wR, min(wG, wB));
3820 /* Luminosity */
3821 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
3823 if (wMax == wMin)
3825 /* Achromatic case */
3826 wSaturation = 0;
3827 /* Hue is now unrepresentable, but this is what native returns... */
3828 wHue = 160;
3830 else
3832 /* Chromatic case */
3833 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
3835 /* Saturation */
3836 if (wLuminosity <= 120)
3837 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
3838 else
3839 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
3841 /* Hue */
3842 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
3843 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
3844 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
3846 if (wR == wMax)
3847 wHue = wBNorm - wGNorm;
3848 else if (wG == wMax)
3849 wHue = 80 + wRNorm - wBNorm;
3850 else
3851 wHue = 160 + wGNorm - wRNorm;
3852 if (wHue < 0)
3853 wHue += 240;
3854 else if (wHue > 240)
3855 wHue -= 240;
3857 if (pwHue)
3858 *pwHue = wHue;
3859 if (pwLuminance)
3860 *pwLuminance = wLuminosity;
3861 if (pwSaturation)
3862 *pwSaturation = wSaturation;
3865 /*************************************************************************
3866 * SHCreateShellPalette [SHLWAPI.@]
3868 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
3870 FIXME("stub\n");
3871 return CreateHalftonePalette(hdc);
3874 /*************************************************************************
3875 * SHGetInverseCMAP (SHLWAPI.@)
3877 * Get an inverse color map table.
3879 * PARAMS
3880 * lpCmap [O] Destination for color map
3881 * dwSize [I] Size of memory pointed to by lpCmap
3883 * RETURNS
3884 * Success: S_OK.
3885 * Failure: E_POINTER, If lpCmap is invalid.
3886 * E_INVALIDARG, If dwFlags is invalid
3887 * E_OUTOFMEMORY, If there is no memory available
3889 * NOTES
3890 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
3891 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
3892 * internal CMap.
3893 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
3894 * this DLL's internal CMap.
3896 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
3898 if (dwSize == 4) {
3899 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
3900 *dest = (DWORD)0xabba1249;
3901 return 0;
3903 FIXME("(%p, %#lx) stub\n", dest, dwSize);
3904 return 0;
3907 /*************************************************************************
3908 * SHIsLowMemoryMachine [SHLWAPI.@]
3910 * Determine if the current computer has low memory.
3912 * PARAMS
3913 * x [I] FIXME
3915 * RETURNS
3916 * TRUE if the users machine has 16 Megabytes of memory or less,
3917 * FALSE otherwise.
3919 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
3921 FIXME("(0x%08lx) stub\n", x);
3922 return FALSE;
3925 /*************************************************************************
3926 * GetMenuPosFromID [SHLWAPI.@]
3928 * Return the position of a menu item from its Id.
3930 * PARAMS
3931 * hMenu [I] Menu containing the item
3932 * wID [I] Id of the menu item
3934 * RETURNS
3935 * Success: The index of the menu item in hMenu.
3936 * Failure: -1, If the item is not found.
3938 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
3940 MENUITEMINFOA mi;
3941 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
3943 while (nIter < nCount)
3945 mi.wID = 0;
3946 if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
3947 return nIter;
3948 nIter++;
3950 return -1;
3953 /*************************************************************************
3954 * @ [SHLWAPI.179]
3956 * Same as SHLWAPI.GetMenuPosFromID
3958 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
3960 return GetMenuPosFromID(hMenu, uID);
3964 /*************************************************************************
3965 * @ [SHLWAPI.448]
3967 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
3969 while (*lpwstr)
3971 if (*lpwstr == '/')
3972 *lpwstr = '\\';
3973 lpwstr++;
3978 /*************************************************************************
3979 * @ [SHLWAPI.461]
3981 DWORD WINAPI SHGetAppCompatFlags(DWORD Unknown)
3983 FIXME("stub\n");
3984 return 0;
3988 /*************************************************************************
3989 * @ [SHLWAPI.549]
3991 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
3992 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
3994 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
3997 /*************************************************************************
3998 * SHSkipJunction [SHLWAPI.@]
4000 * Determine if a bind context can be bound to an object
4002 * PARAMS
4003 * pbc [I] Bind context to check
4004 * pclsid [I] CLSID of object to be bound to
4006 * RETURNS
4007 * TRUE: If it is safe to bind
4008 * FALSE: If pbc is invalid or binding would not be safe
4011 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4013 static const WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4014 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4015 BOOL bRet = FALSE;
4017 if (pbc)
4019 IUnknown* lpUnk;
4021 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)szSkipBinding, &lpUnk)))
4023 CLSID clsid;
4025 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4026 IsEqualGUID(pclsid, &clsid))
4027 bRet = TRUE;
4029 IUnknown_Release(lpUnk);
4032 return bRet;
4035 /***********************************************************************
4036 * SHGetShellKey (SHLWAPI.@)
4038 DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
4040 FIXME("(%lx, %lx, %lx): stub\n", a, b, c);
4041 return 0x50;
4044 /***********************************************************************
4045 * SHQueueUserWorkItem (SHLWAPI.@)
4047 HRESULT WINAPI SHQueueUserWorkItem(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f, DWORD g)
4049 FIXME("(%lx, %lx, %lx, %lx, %lx, %lx, %lx): stub\n", a, b, c, d, e, f, g);
4050 return E_FAIL;
4053 /***********************************************************************
4054 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4056 DWORD WINAPI IUnknown_OnFocusChangeIS(IUnknown * pUnk, IUnknown * pFocusObject, BOOL bChange)
4058 FIXME("(%p, %p, %s)\n", pUnk, pFocusObject, bChange ? "TRUE" : "FALSE");
4061 IInputObjectSite * pIOS = NULL;
4062 if (SUCCEEDED(IUnknown_QueryInterface(pUnk, &IID_IInputObjectSite, (void **)&pIOS))
4063 IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bChange);
4066 return 0;
4069 /***********************************************************************
4070 * SHGetValueW (SHLWAPI.@)
4072 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4074 FIXME("(%lx, %s, %s, %lx, %lx, %lx): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4075 return E_FAIL;
4078 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4080 /***********************************************************************
4081 * GetUIVersion (SHLWAPI.452)
4083 DWORD WINAPI GetUIVersion(void)
4085 static DWORD version;
4087 if (!version)
4089 DllGetVersion_func pDllGetVersion;
4090 HMODULE dll = LoadLibraryA("shell32.dll");
4091 if (!dll) return 0;
4093 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4094 if (pDllGetVersion)
4096 DLLVERSIONINFO dvi;
4097 dvi.cbSize = sizeof(DLLVERSIONINFO);
4098 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4100 FreeLibrary( dll );
4101 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4103 return version;