wine.inf: We should not override existing associations.
[wine/hacks.git] / dlls / shlwapi / ordinal.c
blob669cff02bf1ab540112ac2e0e9f50bd7ab77001b
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "shellapi.h"
46 #include "commdlg.h"
47 #include "wine/unicode.h"
48 #include "winreg.h"
49 #include "wine/debug.h"
50 #include "shlwapi.h"
53 WINE_DEFAULT_DEBUG_CHANNEL(shell);
55 /* Get a function pointer from a DLL handle */
56 #define GET_FUNC(func, module, name, fail) \
57 do { \
58 if (!func) { \
59 if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
60 func = (fn##func)GetProcAddress(SHLWAPI_h##module, name); \
61 if (!func) return fail; \
62 } \
63 } while (0)
65 /* DLL handles for late bound calls */
66 extern HINSTANCE shlwapi_hInstance;
67 extern HMODULE SHLWAPI_hshell32;
68 extern HMODULE SHLWAPI_hwinmm;
69 extern HMODULE SHLWAPI_hcomdlg32;
70 extern HMODULE SHLWAPI_hcomctl32;
71 extern HMODULE SHLWAPI_hmpr;
72 extern HMODULE SHLWAPI_hurlmon;
73 extern HMODULE SHLWAPI_hversion;
75 extern DWORD SHLWAPI_ThreadRef_index;
77 /* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
78 typedef LPITEMIDLIST (WINAPI *fnpSHBrowseForFolderW)(LPBROWSEINFOW);
79 static fnpSHBrowseForFolderW pSHBrowseForFolderW;
80 typedef BOOL (WINAPI *fnpPlaySoundW)(LPCWSTR, HMODULE, DWORD);
81 static fnpPlaySoundW pPlaySoundW;
82 typedef DWORD (WINAPI *fnpSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);
83 static fnpSHGetFileInfoW pSHGetFileInfoW;
84 typedef UINT (WINAPI *fnpDragQueryFileW)(HDROP, UINT, LPWSTR, UINT);
85 static fnpDragQueryFileW pDragQueryFileW;
86 typedef BOOL (WINAPI *fnpSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR);
87 static fnpSHGetPathFromIDListW pSHGetPathFromIDListW;
88 typedef BOOL (WINAPI *fnpShellExecuteExW)(LPSHELLEXECUTEINFOW);
89 static fnpShellExecuteExW pShellExecuteExW;
90 typedef HICON (WINAPI *fnpSHFileOperationW)(LPSHFILEOPSTRUCTW);
91 static fnpSHFileOperationW pSHFileOperationW;
92 typedef UINT (WINAPI *fnpExtractIconExW)(LPCWSTR, INT,HICON *,HICON *, UINT);
93 static fnpExtractIconExW pExtractIconExW;
94 typedef BOOL (WINAPI *fnpSHGetNewLinkInfoW)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT);
95 static fnpSHGetNewLinkInfoW pSHGetNewLinkInfoW;
96 typedef HRESULT (WINAPI *fnpSHDefExtractIconW)(LPCWSTR, int, UINT, HICON*, HICON*, UINT);
97 static fnpSHDefExtractIconW pSHDefExtractIconW;
98 typedef HICON (WINAPI *fnpExtractIconW)(HINSTANCE, LPCWSTR, UINT);
99 static fnpExtractIconW pExtractIconW;
100 typedef BOOL (WINAPI *fnpGetSaveFileNameW)(LPOPENFILENAMEW);
101 static fnpGetSaveFileNameW pGetSaveFileNameW;
102 typedef DWORD (WINAPI *fnpWNetRestoreConnectionW)(HWND, LPWSTR);
103 static fnpWNetRestoreConnectionW pWNetRestoreConnectionW;
104 typedef DWORD (WINAPI *fnpWNetGetLastErrorW)(LPDWORD, LPWSTR, DWORD, LPWSTR, DWORD);
105 static fnpWNetGetLastErrorW pWNetGetLastErrorW;
106 typedef BOOL (WINAPI *fnpPageSetupDlgW)(LPPAGESETUPDLGW);
107 static fnpPageSetupDlgW pPageSetupDlgW;
108 typedef BOOL (WINAPI *fnpPrintDlgW)(LPPRINTDLGW);
109 static fnpPrintDlgW pPrintDlgW;
110 typedef BOOL (WINAPI *fnpGetOpenFileNameW)(LPOPENFILENAMEW);
111 static fnpGetOpenFileNameW pGetOpenFileNameW;
112 typedef DWORD (WINAPI *fnpGetFileVersionInfoSizeW)(LPCWSTR,LPDWORD);
113 static fnpGetFileVersionInfoSizeW pGetFileVersionInfoSizeW;
114 typedef BOOL (WINAPI *fnpGetFileVersionInfoW)(LPCWSTR,DWORD,DWORD,LPVOID);
115 static fnpGetFileVersionInfoW pGetFileVersionInfoW;
116 typedef WORD (WINAPI *fnpVerQueryValueW)(LPVOID,LPCWSTR,LPVOID*,UINT*);
117 static fnpVerQueryValueW pVerQueryValueW;
118 typedef BOOL (WINAPI *fnpCOMCTL32_417)(HDC,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
119 static fnpCOMCTL32_417 pCOMCTL32_417;
120 typedef HRESULT (WINAPI *fnpDllGetVersion)(DLLVERSIONINFO*);
121 static fnpDllGetVersion pDllGetVersion;
122 typedef HRESULT (WINAPI *fnpCreateFormatEnumerator)(UINT,FORMATETC*,IEnumFORMATETC**);
123 static fnpCreateFormatEnumerator pCreateFormatEnumerator;
124 typedef HRESULT (WINAPI *fnpRegisterFormatEnumerator)(LPBC,IEnumFORMATETC*,DWORD);
125 static fnpRegisterFormatEnumerator pRegisterFormatEnumerator;
127 HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
128 HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
129 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR,CLSID*);
130 BOOL WINAPI SHAboutInfoW(LPWSTR,DWORD);
133 NOTES: Most functions exported by ordinal seem to be superflous.
134 The reason for these functions to be there is to provide a wrapper
135 for unicode functions to provide these functions on systems without
136 unicode functions eg. win95/win98. Since we have such functions we just
137 call these. If running Wine with native DLLs, some late bound calls may
138 fail. However, it is better to implement the functions in the forward DLL
139 and recommend the builtin rather than reimplementing the calls here!
142 /*************************************************************************
143 * SHLWAPI_DupSharedHandle
145 * Internal implemetation of SHLWAPI_11.
147 static
148 HANDLE WINAPI SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
149 DWORD dwSrcProcId, DWORD dwAccess,
150 DWORD dwOptions)
152 HANDLE hDst, hSrc;
153 DWORD dwMyProcId = GetCurrentProcessId();
154 HANDLE hRet = NULL;
156 TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", hShared, dwDstProcId, dwSrcProcId,
157 dwAccess, dwOptions);
159 /* Get dest process handle */
160 if (dwDstProcId == dwMyProcId)
161 hDst = GetCurrentProcess();
162 else
163 hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
165 if (hDst)
167 /* Get src process handle */
168 if (dwSrcProcId == dwMyProcId)
169 hSrc = GetCurrentProcess();
170 else
171 hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
173 if (hSrc)
175 /* Make handle available to dest process */
176 if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
177 dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
178 hRet = NULL;
180 if (dwSrcProcId != dwMyProcId)
181 CloseHandle(hSrc);
184 if (dwDstProcId != dwMyProcId)
185 CloseHandle(hDst);
188 TRACE("Returning handle %p\n", hRet);
189 return hRet;
192 /*************************************************************************
193 * @ [SHLWAPI.7]
195 * Create a block of sharable memory and initialise it with data.
197 * PARAMS
198 * lpvData [I] Pointer to data to write
199 * dwSize [I] Size of data
200 * dwProcId [I] ID of process owning data
202 * RETURNS
203 * Success: A shared memory handle
204 * Failure: NULL
206 * NOTES
207 * Ordinals 7-11 provide a set of calls to create shared memory between a
208 * group of processes. The shared memory is treated opaquely in that its size
209 * is not exposed to clients who map it. This is accomplished by storing
210 * the size of the map as the first DWORD of mapped data, and then offsetting
211 * the view pointer returned by this size.
214 HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
216 HANDLE hMap;
217 LPVOID pMapped;
218 HANDLE hRet = NULL;
220 TRACE("(%p,%ld,%ld)\n", lpvData, dwSize, dwProcId);
222 /* Create file mapping of the correct length */
223 hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
224 dwSize + sizeof(dwSize), NULL);
225 if (!hMap)
226 return hRet;
228 /* Get a view in our process address space */
229 pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
231 if (pMapped)
233 /* Write size of data, followed by the data, to the view */
234 *((DWORD*)pMapped) = dwSize;
235 if (lpvData)
236 memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
238 /* Release view. All further views mapped will be opaque */
239 UnmapViewOfFile(pMapped);
240 hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
241 GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
242 DUPLICATE_SAME_ACCESS);
245 CloseHandle(hMap);
246 return hRet;
249 /*************************************************************************
250 * @ [SHLWAPI.8]
252 * Get a pointer to a block of shared memory from a shared memory handle.
254 * PARAMS
255 * hShared [I] Shared memory handle
256 * dwProcId [I] ID of process owning hShared
258 * RETURNS
259 * Success: A pointer to the shared memory
260 * Failure: NULL
263 PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
265 HANDLE hDup;
266 LPVOID pMapped;
268 TRACE("(%p %ld)\n", hShared, dwProcId);
270 /* Get handle to shared memory for current process */
271 hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
272 FILE_MAP_ALL_ACCESS, 0);
273 /* Get View */
274 pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
275 CloseHandle(hDup);
277 if (pMapped)
278 return (char *) pMapped + sizeof(DWORD); /* Hide size */
279 return NULL;
282 /*************************************************************************
283 * @ [SHLWAPI.9]
285 * Release a pointer to a block of shared memory.
287 * PARAMS
288 * lpView [I] Shared memory pointer
290 * RETURNS
291 * Success: TRUE
292 * Failure: FALSE
295 BOOL WINAPI SHUnlockShared(LPVOID lpView)
297 TRACE("(%p)\n", lpView);
298 return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
301 /*************************************************************************
302 * @ [SHLWAPI.10]
304 * Destroy a block of sharable memory.
306 * PARAMS
307 * hShared [I] Shared memory handle
308 * dwProcId [I] ID of process owning hShared
310 * RETURNS
311 * Success: TRUE
312 * Failure: FALSE
315 BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
317 HANDLE hClose;
319 TRACE("(%p %ld)\n", hShared, dwProcId);
321 /* Get a copy of the handle for our process, closing the source handle */
322 hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
323 FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
324 /* Close local copy */
325 return CloseHandle(hClose);
328 /*************************************************************************
329 * @ [SHLWAPI.11]
331 * Copy a sharable memory handle from one process to another.
333 * PARAMS
334 * hShared [I] Shared memory handle to duplicate
335 * dwDstProcId [I] ID of the process wanting the duplicated handle
336 * dwSrcProcId [I] ID of the process owning hShared
337 * dwAccess [I] Desired DuplicateHandle() access
338 * dwOptions [I] Desired DuplicateHandle() options
340 * RETURNS
341 * Success: A handle suitable for use by the dwDstProcId process.
342 * Failure: A NULL handle.
345 HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
346 DWORD dwAccess, DWORD dwOptions)
348 HANDLE hRet;
350 hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
351 dwAccess, dwOptions);
352 return hRet;
355 /*************************************************************************
356 * @ [SHLWAPI.13]
358 * Create and register a clipboard enumerator for a web browser.
360 * PARAMS
361 * lpBC [I] Binding context
362 * lpUnknown [I] An object exposing the IWebBrowserApp interface
364 * RETURNS
365 * Success: S_OK.
366 * Failure: An HRESULT error code.
368 * NOTES
369 * The enumerator is stored as a property of the web browser. If it does not
370 * yet exist, it is created and set before being registered.
372 HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
374 static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
375 '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
376 '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
377 IEnumFORMATETC* pIEnumFormatEtc = NULL;
378 VARIANTARG var;
379 HRESULT hRet;
380 IWebBrowserApp* pBrowser = NULL;
382 TRACE("(%p, %p)\n", lpBC, lpUnknown);
384 /* Get An IWebBrowserApp interface from lpUnknown */
385 hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
386 if (FAILED(hRet) || !pBrowser)
387 return E_NOINTERFACE;
389 V_VT(&var) = VT_EMPTY;
391 /* The property we get is the browsers clipboard enumerator */
392 hRet = IWebBrowserApp_GetProperty(pBrowser, (BSTR)szProperty, &var);
393 if (FAILED(hRet))
394 return hRet;
396 if (V_VT(&var) == VT_EMPTY)
398 /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
399 char szKeyBuff[128], szValueBuff[128];
400 DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
401 FORMATETC* formatList, *format;
402 HKEY hDocs;
404 TRACE("Registering formats and creating IEnumFORMATETC instance\n");
406 if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
407 "Version\\Internet Settings\\Accepted Documents", &hDocs))
408 return E_FAIL;
410 /* Get count of values in key */
411 while (!dwRet)
413 dwKeySize = sizeof(szKeyBuff);
414 dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
415 dwCount++;
418 dwNumValues = dwCount;
420 /* Note: dwCount = number of items + 1; The extra item is the end node */
421 format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
422 if (!formatList)
423 return E_OUTOFMEMORY;
425 if (dwNumValues > 1)
427 dwRet = 0;
428 dwCount = 0;
430 dwNumValues--;
432 /* Register clipboard formats for the values and populate format list */
433 while(!dwRet && dwCount < dwNumValues)
435 dwKeySize = sizeof(szKeyBuff);
436 dwValueSize = sizeof(szValueBuff);
437 dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
438 (PBYTE)szValueBuff, &dwValueSize);
439 if (!dwRet)
440 return E_FAIL;
442 format->cfFormat = RegisterClipboardFormatA(szValueBuff);
443 format->ptd = NULL;
444 format->dwAspect = 1;
445 format->lindex = 4;
446 format->tymed = -1;
448 format++;
449 dwCount++;
453 /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
454 format->cfFormat = 0;
455 format->ptd = NULL;
456 format->dwAspect = 1;
457 format->lindex = 4;
458 format->tymed = -1;
460 /* Create a clipboard enumerator */
461 GET_FUNC(pCreateFormatEnumerator, urlmon, "CreateFormatEnumerator", E_FAIL);
462 hRet = pCreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
464 if (FAILED(hRet) || !pIEnumFormatEtc)
465 return hRet;
467 /* Set our enumerator as the browsers property */
468 V_VT(&var) = VT_UNKNOWN;
469 V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
471 hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
472 if (FAILED(hRet))
474 IEnumFORMATETC_Release(pIEnumFormatEtc);
475 goto RegisterDefaultAcceptHeaders_Exit;
479 if (V_VT(&var) == VT_UNKNOWN)
481 /* Our variant is holding the clipboard enumerator */
482 IUnknown* pIUnknown = V_UNKNOWN(&var);
483 IEnumFORMATETC* pClone = NULL;
485 TRACE("Retrieved IEnumFORMATETC property\n");
487 /* Get an IEnumFormatEtc interface from the variants value */
488 pIEnumFormatEtc = NULL;
489 hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
490 (PVOID)&pIEnumFormatEtc);
491 if (!hRet && pIEnumFormatEtc)
493 /* Clone and register the enumerator */
494 hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
495 if (!hRet && pClone)
497 GET_FUNC(pRegisterFormatEnumerator, urlmon, "RegisterFormatEnumerator", E_FAIL);
498 pRegisterFormatEnumerator(lpBC, pClone, 0);
500 IEnumFORMATETC_Release(pClone);
503 /* Release the IEnumFormatEtc interface */
504 IEnumFORMATETC_Release(pIUnknown);
506 IUnknown_Release(V_UNKNOWN(&var));
509 RegisterDefaultAcceptHeaders_Exit:
510 IWebBrowserApp_Release(pBrowser);
511 return hRet;
514 /*************************************************************************
515 * @ [SHLWAPI.15]
517 * Get Explorers "AcceptLanguage" setting.
519 * PARAMS
520 * langbuf [O] Destination for language string
521 * buflen [I] Length of langbuf
522 * [0] Success: used length of langbuf
524 * RETURNS
525 * Success: S_OK. langbuf is set to the language string found.
526 * Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
527 * does not contain the setting.
528 * E_INVALIDARG, If the buffer is not big enough
530 HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
532 static const WCHAR szkeyW[] = {
533 'S','o','f','t','w','a','r','e','\\',
534 'M','i','c','r','o','s','o','f','t','\\',
535 'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
536 'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
537 static const WCHAR valueW[] = {
538 'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
539 static const WCHAR enusW[] = {'e','n','-','u','s',0};
540 DWORD mystrlen, mytype;
541 HKEY mykey;
542 HRESULT retval;
543 LCID mylcid;
544 WCHAR *mystr;
546 if(!langbuf || !buflen || !*buflen)
547 return E_FAIL;
549 mystrlen = (*buflen > 20) ? *buflen : 20 ;
550 mystr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * mystrlen);
551 RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
552 if(RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &mystrlen)) {
553 /* Did not find value */
554 mylcid = GetUserDefaultLCID();
555 /* somehow the mylcid translates into "en-us"
556 * this is similar to "LOCALE_SABBREVLANGNAME"
557 * which could be gotten via GetLocaleInfo.
558 * The only problem is LOCALE_SABBREVLANGUAGE" is
559 * a 3 char string (first 2 are country code and third is
560 * letter for "sublanguage", which does not come close to
561 * "en-us"
563 lstrcpyW(mystr, enusW);
564 mystrlen = lstrlenW(mystr);
565 } else {
566 /* handle returned string */
567 FIXME("missing code\n");
569 memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
571 if(*buflen > strlenW(mystr)) {
572 *buflen = strlenW(mystr);
573 retval = S_OK;
574 } else {
575 *buflen = 0;
576 retval = E_INVALIDARG;
577 SetLastError(ERROR_INSUFFICIENT_BUFFER);
579 RegCloseKey(mykey);
580 HeapFree(GetProcessHeap(), 0, mystr);
581 return retval;
584 /*************************************************************************
585 * @ [SHLWAPI.14]
587 * Ascii version of GetAcceptLanguagesW.
589 HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
591 WCHAR *langbufW;
592 DWORD buflenW, convlen;
593 HRESULT retval;
595 if(!langbuf || !buflen || !*buflen) return E_FAIL;
597 buflenW = *buflen;
598 langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
599 retval = GetAcceptLanguagesW(langbufW, &buflenW);
601 /* FIXME: this is wrong, the string may not be null-terminated */
602 convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf,
603 *buflen, NULL, NULL);
604 *buflen = buflenW ? convlen : 0;
606 HeapFree(GetProcessHeap(), 0, langbufW);
607 return retval;
610 /*************************************************************************
611 * @ [SHLWAPI.23]
613 * Convert a GUID to a string.
615 * PARAMS
616 * guid [I] GUID to convert
617 * lpszDest [O] Destination for string
618 * cchMax [I] Length of output buffer
620 * RETURNS
621 * The length of the string created.
623 INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
625 char xguid[40];
626 INT iLen;
628 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
630 sprintf(xguid, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
631 guid->Data1, guid->Data2, guid->Data3,
632 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
633 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
635 iLen = strlen(xguid) + 1;
637 if (iLen > cchMax)
638 return 0;
639 memcpy(lpszDest, xguid, iLen);
640 return iLen;
643 /*************************************************************************
644 * @ [SHLWAPI.24]
646 * Convert a GUID to a string.
648 * PARAMS
649 * guid [I] GUID to convert
650 * str [O] Destination for string
651 * cmax [I] Length of output buffer
653 * RETURNS
654 * The length of the string created.
656 INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
658 WCHAR xguid[40];
659 INT iLen;
660 static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
661 '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
662 'X','%','0','2','X','%','0','2','X','}',0};
664 TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
666 sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
667 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
668 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
670 iLen = strlenW(xguid) + 1;
672 if (iLen > cchMax)
673 return 0;
674 memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
675 return iLen;
678 /*************************************************************************
679 * @ [SHLWAPI.29]
681 * Determine if a Unicode character is a space.
683 * PARAMS
684 * wc [I] Character to check.
686 * RETURNS
687 * TRUE, if wc is a space,
688 * FALSE otherwise.
690 BOOL WINAPI IsCharSpaceW(WCHAR wc)
692 WORD CharType;
694 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
697 /*************************************************************************
698 * @ [SHLWAPI.30]
700 * Determine if a Unicode character is a blank.
702 * PARAMS
703 * wc [I] Character to check.
705 * RETURNS
706 * TRUE, if wc is a blank,
707 * FALSE otherwise.
710 BOOL WINAPI IsCharBlankW(WCHAR wc)
712 WORD CharType;
714 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
717 /*************************************************************************
718 * @ [SHLWAPI.31]
720 * Determine if a Unicode character is punctuation.
722 * PARAMS
723 * wc [I] Character to check.
725 * RETURNS
726 * TRUE, if wc is punctuation,
727 * FALSE otherwise.
729 BOOL WINAPI IsCharPunctW(WCHAR wc)
731 WORD CharType;
733 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
736 /*************************************************************************
737 * @ [SHLWAPI.32]
739 * Determine if a Unicode character is a control character.
741 * PARAMS
742 * wc [I] Character to check.
744 * RETURNS
745 * TRUE, if wc is a control character,
746 * FALSE otherwise.
748 BOOL WINAPI IsCharCntrlW(WCHAR wc)
750 WORD CharType;
752 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
755 /*************************************************************************
756 * @ [SHLWAPI.33]
758 * Determine if a Unicode character is a digit.
760 * PARAMS
761 * wc [I] Character to check.
763 * RETURNS
764 * TRUE, if wc is a digit,
765 * FALSE otherwise.
767 BOOL WINAPI IsCharDigitW(WCHAR wc)
769 WORD CharType;
771 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
774 /*************************************************************************
775 * @ [SHLWAPI.34]
777 * Determine if a Unicode character is a hex digit.
779 * PARAMS
780 * wc [I] Character to check.
782 * RETURNS
783 * TRUE, if wc is a hex digit,
784 * FALSE otherwise.
786 BOOL WINAPI IsCharXDigitW(WCHAR wc)
788 WORD CharType;
790 return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
793 /*************************************************************************
794 * @ [SHLWAPI.35]
797 BOOL WINAPI GetStringType3ExW(LPWSTR lpszStr, DWORD dwLen, LPVOID p3)
799 FIXME("(%s,0x%08lx,%p): stub\n", debugstr_w(lpszStr), dwLen, p3);
800 return TRUE;
803 /*************************************************************************
804 * @ [SHLWAPI.36]
806 * Insert a bitmap menu item at the bottom of a menu.
808 * PARAMS
809 * hMenu [I] Menu to insert into
810 * flags [I] Flags for insertion
811 * id [I] Menu ID of the item
812 * str [I] Menu text for the item
814 * RETURNS
815 * Success: TRUE, the item is inserted into the menu
816 * Failure: FALSE, if any parameter is invalid
818 BOOL WINAPI AppendMenuWrapW(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
820 TRACE("(%p,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));
821 return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);
824 /*************************************************************************
825 * @ [SHLWAPI.74]
827 * Get the text from a given dialog item.
829 * PARAMS
830 * hWnd [I] Handle of dialog
831 * nItem [I] Index of item
832 * lpsDest [O] Buffer for receiving window text
833 * nDestLen [I] Length of buffer.
835 * RETURNS
836 * Success: The length of the returned text.
837 * Failure: 0.
839 INT WINAPI GetDlgItemTextWrapW(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
841 HWND hItem = GetDlgItem(hWnd, nItem);
843 if (hItem)
844 return GetWindowTextW(hItem, lpsDest, nDestLen);
845 if (nDestLen)
846 *lpsDest = (WCHAR)'\0';
847 return 0;
850 /*************************************************************************
851 * @ [SHLWAPI.138]
853 * Set the text of a given dialog item.
855 * PARAMS
856 * hWnd [I] Handle of dialog
857 * iItem [I] Index of item
858 * lpszText [O] Text to set
860 * RETURNS
861 * Success: TRUE. The text of the dialog is set to lpszText.
862 * Failure: FALSE, Otherwise.
864 BOOL WINAPI SetDlgItemTextWrapW(HWND hWnd, INT iItem, LPCWSTR lpszText)
866 HWND hWndItem = GetDlgItem(hWnd, iItem);
867 if (hWndItem)
868 return SetWindowTextW(hWndItem, lpszText);
869 return FALSE;
872 /*************************************************************************
873 * @ [SHLWAPI.151]
875 * Compare two Ascii strings up to a given length.
877 * PARAMS
878 * lpszSrc [I] Source string
879 * lpszCmp [I] String to compare to lpszSrc
880 * len [I] Maximum length
882 * RETURNS
883 * A number greater than, less than or equal to 0 depending on whether
884 * lpszSrc is greater than, less than or equal to lpszCmp.
886 DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
888 return strncmp(lpszSrc, lpszCmp, len);
891 /*************************************************************************
892 * @ [SHLWAPI.152]
894 * Unicode version of StrCmpNCA.
896 DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
898 return strncmpW(lpszSrc, lpszCmp, len);
901 /*************************************************************************
902 * @ [SHLWAPI.153]
904 * Compare two Ascii strings up to a given length, ignoring case.
906 * PARAMS
907 * lpszSrc [I] Source string
908 * lpszCmp [I] String to compare to lpszSrc
909 * len [I] Maximum length
911 * RETURNS
912 * A number greater than, less than or equal to 0 depending on whether
913 * lpszSrc is greater than, less than or equal to lpszCmp.
915 DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
917 return strncasecmp(lpszSrc, lpszCmp, len);
920 /*************************************************************************
921 * @ [SHLWAPI.154]
923 * Unicode version of StrCmpNICA.
925 DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
927 return strncmpiW(lpszSrc, lpszCmp, len);
930 /*************************************************************************
931 * @ [SHLWAPI.155]
933 * Compare two Ascii strings.
935 * PARAMS
936 * lpszSrc [I] Source string
937 * lpszCmp [I] String to compare to lpszSrc
939 * RETURNS
940 * A number greater than, less than or equal to 0 depending on whether
941 * lpszSrc is greater than, less than or equal to lpszCmp.
943 DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
945 return strcmp(lpszSrc, lpszCmp);
948 /*************************************************************************
949 * @ [SHLWAPI.156]
951 * Unicode version of StrCmpCA.
953 DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
955 return strcmpW(lpszSrc, lpszCmp);
958 /*************************************************************************
959 * @ [SHLWAPI.157]
961 * Compare two Ascii strings, ignoring case.
963 * PARAMS
964 * lpszSrc [I] Source string
965 * lpszCmp [I] String to compare to lpszSrc
967 * RETURNS
968 * A number greater than, less than or equal to 0 depending on whether
969 * lpszSrc is greater than, less than or equal to lpszCmp.
971 DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
973 return strcasecmp(lpszSrc, lpszCmp);
976 /*************************************************************************
977 * @ [SHLWAPI.158]
979 * Unicode version of StrCmpICA.
981 DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
983 return strcmpiW(lpszSrc, lpszCmp);
986 /*************************************************************************
987 * @ [SHLWAPI.160]
989 * Get an identification string for the OS and explorer.
991 * PARAMS
992 * lpszDest [O] Destination for Id string
993 * dwDestLen [I] Length of lpszDest
995 * RETURNS
996 * TRUE, If the string was created successfully
997 * FALSE, Otherwise
999 BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
1001 WCHAR buff[2084];
1003 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
1005 if (lpszDest && SHAboutInfoW(buff, dwDestLen))
1007 WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
1008 return TRUE;
1010 return FALSE;
1013 /*************************************************************************
1014 * @ [SHLWAPI.161]
1016 * Unicode version of SHAboutInfoA.
1018 BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
1020 static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
1021 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
1022 ' ','E','x','p','l','o','r','e','r','\0' };
1023 static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
1024 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
1025 'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
1026 static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
1027 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
1028 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
1029 static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
1030 'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
1031 ' ','E','x','p','l','o','r','e','r','\\',
1032 'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
1033 static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
1034 static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
1035 'V','e','r','s','i','o','n','\0' };
1036 static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
1037 'O','w','n','e','r','\0' };
1038 static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
1039 'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
1040 static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
1041 static const WCHAR szUpdate[] = { 'I','E','A','K',
1042 'U','p','d','a','t','e','U','r','l','\0' };
1043 static const WCHAR szHelp[] = { 'I','E','A','K',
1044 'H','e','l','p','S','t','r','i','n','g','\0' };
1045 WCHAR buff[2084];
1046 HKEY hReg;
1047 DWORD dwType, dwLen;
1049 TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
1051 if (!lpszDest)
1052 return FALSE;
1054 *lpszDest = '\0';
1056 /* Try the NT key first, followed by 95/98 key */
1057 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
1058 RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
1059 return FALSE;
1061 /* OS Version */
1062 buff[0] = '\0';
1063 dwLen = 30;
1064 if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
1066 DWORD dwStrLen = strlenW(buff);
1067 dwLen = 30 - dwStrLen;
1068 SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
1069 szCustomized, &dwType, buff+dwStrLen, &dwLen);
1071 StrCatBuffW(lpszDest, buff, dwDestLen);
1073 /* ~Registered Owner */
1074 buff[0] = '~';
1075 dwLen = 256;
1076 if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
1077 buff[1] = '\0';
1078 StrCatBuffW(lpszDest, buff, dwDestLen);
1080 /* ~Registered Organization */
1081 dwLen = 256;
1082 if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
1083 buff[1] = '\0';
1084 StrCatBuffW(lpszDest, buff, dwDestLen);
1086 /* FIXME: Not sure where this number comes from */
1087 buff[0] = '~';
1088 buff[1] = '0';
1089 buff[2] = '\0';
1090 StrCatBuffW(lpszDest, buff, dwDestLen);
1092 /* ~Product Id */
1093 dwLen = 256;
1094 if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
1095 buff[1] = '\0';
1096 StrCatBuffW(lpszDest, buff, dwDestLen);
1098 /* ~IE Update Url */
1099 dwLen = 2048;
1100 if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
1101 buff[1] = '\0';
1102 StrCatBuffW(lpszDest, buff, dwDestLen);
1104 /* ~IE Help String */
1105 dwLen = 256;
1106 if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
1107 buff[1] = '\0';
1108 StrCatBuffW(lpszDest, buff, dwDestLen);
1110 RegCloseKey(hReg);
1111 return TRUE;
1114 /*************************************************************************
1115 * @ [SHLWAPI.163]
1117 * Call IOleCommandTarget_QueryStatus() on an object.
1119 * PARAMS
1120 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1121 * pguidCmdGroup [I] GUID for the command group
1122 * cCmds [I]
1123 * prgCmds [O] Commands
1124 * pCmdText [O] Command text
1126 * RETURNS
1127 * Success: S_OK.
1128 * Failure: E_FAIL, if lpUnknown is NULL.
1129 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1130 * Otherwise, an error code from IOleCommandTarget_QueryStatus().
1132 HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1133 ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
1135 HRESULT hRet = E_FAIL;
1137 TRACE("(%p,%p,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
1139 if (lpUnknown)
1141 IOleCommandTarget* lpOle;
1143 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1144 (void**)&lpOle);
1146 if (SUCCEEDED(hRet) && lpOle)
1148 hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
1149 prgCmds, pCmdText);
1150 IOleCommandTarget_Release(lpOle);
1153 return hRet;
1156 /*************************************************************************
1157 * @ [SHLWAPI.164]
1159 * Call IOleCommandTarget_Exec() on an object.
1161 * PARAMS
1162 * lpUnknown [I] Object supporting the IOleCommandTarget interface
1163 * pguidCmdGroup [I] GUID for the command group
1165 * RETURNS
1166 * Success: S_OK.
1167 * Failure: E_FAIL, if lpUnknown is NULL.
1168 * E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
1169 * Otherwise, an error code from IOleCommandTarget_Exec().
1171 HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
1172 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
1173 VARIANT* pvaOut)
1175 HRESULT hRet = E_FAIL;
1177 TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
1178 nCmdexecopt, pvaIn, pvaOut);
1180 if (lpUnknown)
1182 IOleCommandTarget* lpOle;
1184 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
1185 (void**)&lpOle);
1186 if (SUCCEEDED(hRet) && lpOle)
1188 hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
1189 nCmdexecopt, pvaIn, pvaOut);
1190 IOleCommandTarget_Release(lpOle);
1193 return hRet;
1196 /*************************************************************************
1197 * @ [SHLWAPI.165]
1199 * Retrieve, modify, and re-set a value from a window.
1201 * PARAMS
1202 * hWnd [I] Window to get value from
1203 * offset [I] Offset of value
1204 * wMask [I] Mask for uiFlags
1205 * wFlags [I] Bits to set in window value
1207 * RETURNS
1208 * The new value as it was set, or 0 if any parameter is invalid.
1210 * NOTES
1211 * Any bits set in uiMask are cleared from the value, then any bits set in
1212 * uiFlags are set in the value.
1214 LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
1216 LONG ret = GetWindowLongA(hwnd, offset);
1217 LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);
1219 if (newFlags != ret)
1220 ret = SetWindowLongA(hwnd, offset, newFlags);
1221 return ret;
1224 /*************************************************************************
1225 * @ [SHLWAPI.167]
1227 * Change a window's parent.
1229 * PARAMS
1230 * hWnd [I] Window to change parent of
1231 * hWndParent [I] New parent window
1233 * RETURNS
1234 * The old parent of hWnd.
1236 * NOTES
1237 * If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
1238 * If hWndParent is NOT NULL then we set the WS_CHILD style.
1240 HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
1242 TRACE("%p, %p\n", hWnd, hWndParent);
1244 if(GetParent(hWnd) == hWndParent)
1245 return 0;
1247 if(hWndParent)
1248 SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
1249 else
1250 SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
1252 return SetParent(hWnd, hWndParent);
1255 /*************************************************************************
1256 * @ [SHLWAPI.168]
1258 * Locate and advise a connection point in an IConnectionPointContainer object.
1260 * PARAMS
1261 * lpUnkSink [I] Sink for the connection point advise call
1262 * riid [I] REFIID of connection point to advise
1263 * bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first
1264 * lpUnknown [I] Object supporting the IConnectionPointContainer interface
1265 * lpCookie [O] Pointer to connection point cookie
1266 * lppCP [O] Destination for the IConnectionPoint found
1268 * RETURNS
1269 * Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
1270 * that was advised. The caller is responsible for releasing it.
1271 * Failure: E_FAIL, if any arguments are invalid.
1272 * E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
1273 * Or an HRESULT error code if any call fails.
1275 HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
1276 IUnknown* lpUnknown, LPDWORD lpCookie,
1277 IConnectionPoint **lppCP)
1279 HRESULT hRet;
1280 IConnectionPointContainer* lpContainer;
1281 IConnectionPoint *lpCP;
1283 if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
1284 return E_FAIL;
1286 if(lppCP)
1287 *lppCP = NULL;
1289 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
1290 (void**)&lpContainer);
1291 if (SUCCEEDED(hRet))
1293 hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
1295 if (SUCCEEDED(hRet))
1297 if(!bAdviseOnly)
1298 hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
1299 hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
1301 if (FAILED(hRet))
1302 *lpCookie = 0;
1304 if (lppCP && SUCCEEDED(hRet))
1305 *lppCP = lpCP; /* Caller keeps the interface */
1306 else
1307 IConnectionPoint_Release(lpCP); /* Release it */
1310 IUnknown_Release(lpContainer);
1312 return hRet;
1315 /*************************************************************************
1316 * @ [SHLWAPI.169]
1318 * Release an interface.
1320 * PARAMS
1321 * lpUnknown [I] Object to release
1323 * RETURNS
1324 * Nothing.
1326 DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
1328 IUnknown *temp;
1330 TRACE("(%p)\n",lpUnknown);
1332 if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
1333 temp = *lpUnknown;
1334 *lpUnknown = NULL;
1336 TRACE("doing Release\n");
1338 return IUnknown_Release(temp);
1341 /*************************************************************************
1342 * @ [SHLWAPI.170]
1344 * Skip '//' if present in a string.
1346 * PARAMS
1347 * lpszSrc [I] String to check for '//'
1349 * RETURNS
1350 * Success: The next character after the '//' or the string if not present
1351 * Failure: NULL, if lpszStr is NULL.
1353 LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
1355 if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
1356 lpszSrc += 2;
1357 return lpszSrc;
1360 /*************************************************************************
1361 * @ [SHLWAPI.171]
1363 * Check if two interfaces come from the same object.
1365 * PARAMS
1366 * lpInt1 [I] Interface to check against lpInt2.
1367 * lpInt2 [I] Interface to check against lpInt1.
1369 * RETURNS
1370 * TRUE, If the interfaces come from the same object.
1371 * FALSE Otherwise.
1373 BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
1375 LPVOID lpUnknown1, lpUnknown2;
1377 TRACE("%p %p\n", lpInt1, lpInt2);
1379 if (!lpInt1 || !lpInt2)
1380 return FALSE;
1382 if (lpInt1 == lpInt2)
1383 return TRUE;
1385 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown,
1386 (LPVOID *)&lpUnknown1)))
1387 return FALSE;
1389 if (!SUCCEEDED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown,
1390 (LPVOID *)&lpUnknown2)))
1391 return FALSE;
1393 if (lpUnknown1 == lpUnknown2)
1394 return TRUE;
1396 return FALSE;
1399 /*************************************************************************
1400 * @ [SHLWAPI.172]
1402 * Get the window handle of an object.
1404 * PARAMS
1405 * lpUnknown [I] Object to get the window handle of
1406 * lphWnd [O] Destination for window handle
1408 * RETURNS
1409 * Success: S_OK. lphWnd contains the objects window handle.
1410 * Failure: An HRESULT error code.
1412 * NOTES
1413 * lpUnknown is expected to support one of the following interfaces:
1414 * IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
1416 HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
1418 /* FIXME: Wine has no header for this object */
1419 static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,
1420 0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};
1421 IUnknown *lpOle;
1422 HRESULT hRet = E_FAIL;
1424 TRACE("(%p,%p)\n", lpUnknown, lphWnd);
1426 if (!lpUnknown)
1427 return hRet;
1429 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
1431 if (FAILED(hRet))
1433 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
1435 if (FAILED(hRet))
1437 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
1438 (void**)&lpOle);
1442 if (SUCCEEDED(hRet))
1444 /* Lazyness here - Since GetWindow() is the first method for the above 3
1445 * interfaces, we use the same call for them all.
1447 hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
1448 IUnknown_Release(lpOle);
1449 if (lphWnd)
1450 TRACE("Returning HWND=%p\n", *lphWnd);
1453 return hRet;
1456 /*************************************************************************
1457 * @ [SHLWAPI.173]
1459 * Call a method on as as yet unidentified object.
1461 * PARAMS
1462 * pUnk [I] Object supporting the unidentified interface,
1463 * arg [I] Argument for the call on the object.
1465 * RETURNS
1466 * S_OK.
1468 HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
1470 static const GUID guid_173 = {
1471 0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
1473 IMalloc *pUnk2;
1475 TRACE("(%p,%ld)\n", pUnk, arg);
1477 /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
1478 * We use this interface as its vtable entry is compatible with the
1479 * object in question.
1480 * FIXME: Find out what this object is and where it should be defined.
1482 if (pUnk &&
1483 SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
1485 IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
1486 IMalloc_Release(pUnk2);
1488 return S_OK;
1491 /*************************************************************************
1492 * @ [SHLWAPI.174]
1494 * Call either IObjectWithSite_SetSite() or IInternetSecurityManager_SetSecuritySite() on
1495 * an object.
1498 HRESULT WINAPI IUnknown_SetSite(
1499 IUnknown *obj, /* [in] OLE object */
1500 IUnknown *site) /* [in] Site interface */
1502 HRESULT hr;
1503 IObjectWithSite *iobjwithsite;
1504 IInternetSecurityManager *isecmgr;
1506 if (!obj) return E_FAIL;
1508 hr = IUnknown_QueryInterface(obj, &IID_IObjectWithSite, (LPVOID *)&iobjwithsite);
1509 TRACE("IID_IObjectWithSite QI ret=%08lx, %p\n", hr, iobjwithsite);
1510 if (SUCCEEDED(hr))
1512 hr = IObjectWithSite_SetSite(iobjwithsite, site);
1513 TRACE("done IObjectWithSite_SetSite ret=%08lx\n", hr);
1514 IUnknown_Release(iobjwithsite);
1516 else
1518 hr = IUnknown_QueryInterface(obj, &IID_IInternetSecurityManager, (LPVOID *)&isecmgr);
1519 TRACE("IID_IInternetSecurityManager QI ret=%08lx, %p\n", hr, isecmgr);
1520 if (FAILED(hr)) return hr;
1522 hr = IInternetSecurityManager_SetSecuritySite(isecmgr, (IInternetSecurityMgrSite *)site);
1523 TRACE("done IInternetSecurityManager_SetSecuritySite ret=%08lx\n", hr);
1524 IUnknown_Release(isecmgr);
1526 return hr;
1529 /*************************************************************************
1530 * @ [SHLWAPI.175]
1532 * Call IPersist_GetClassID() on an object.
1534 * PARAMS
1535 * lpUnknown [I] Object supporting the IPersist interface
1536 * lpClassId [O] Destination for Class Id
1538 * RETURNS
1539 * Success: S_OK. lpClassId contains the Class Id requested.
1540 * Failure: E_FAIL, If lpUnknown is NULL,
1541 * E_NOINTERFACE If lpUnknown does not support IPersist,
1542 * Or an HRESULT error code.
1544 HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
1546 IPersist* lpPersist;
1547 HRESULT hRet = E_FAIL;
1549 TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
1551 if (lpUnknown)
1553 hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
1554 if (SUCCEEDED(hRet))
1556 IPersist_GetClassID(lpPersist, lpClassId);
1557 IPersist_Release(lpPersist);
1560 return hRet;
1563 /*************************************************************************
1564 * @ [SHLWAPI.176]
1566 * Retrieve a Service Interface from an object.
1568 * PARAMS
1569 * lpUnknown [I] Object to get an IServiceProvider interface from
1570 * sid [I] Service ID for IServiceProvider_QueryService() call
1571 * riid [I] Function requested for QueryService call
1572 * lppOut [O] Destination for the service interface pointer
1574 * RETURNS
1575 * Success: S_OK. lppOut contains an object providing the requested service
1576 * Failure: An HRESULT error code
1578 * NOTES
1579 * lpUnknown is expected to support the IServiceProvider interface.
1581 HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
1582 LPVOID *lppOut)
1584 IServiceProvider* pService = NULL;
1585 HRESULT hRet;
1587 if (!lppOut)
1588 return E_FAIL;
1590 *lppOut = NULL;
1592 if (!lpUnknown)
1593 return E_FAIL;
1595 /* Get an IServiceProvider interface from the object */
1596 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
1597 (LPVOID*)&pService);
1599 if (!hRet && pService)
1601 TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
1603 /* Get a Service interface from the object */
1604 hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
1606 TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
1608 /* Release the IServiceProvider interface */
1609 IUnknown_Release(pService);
1611 return hRet;
1614 /*************************************************************************
1615 * @ [SHLWAPI.177]
1617 * Loads a popup menu.
1619 * PARAMS
1620 * hInst [I] Instance handle
1621 * szName [I] Menu name
1623 * RETURNS
1624 * Success: TRUE.
1625 * Failure: FALSE.
1627 BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
1629 HMENU hMenu, hSubMenu;
1631 if ((hMenu = LoadMenuW(hInst, szName)))
1633 if ((hSubMenu = GetSubMenu(hMenu, 0)))
1634 RemoveMenu(hMenu, 0, MF_BYPOSITION);
1636 DestroyMenu(hMenu);
1637 return TRUE;
1639 return FALSE;
1642 typedef struct _enumWndData
1644 UINT uiMsgId;
1645 WPARAM wParam;
1646 LPARAM lParam;
1647 LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
1648 } enumWndData;
1650 /* Callback for SHLWAPI_178 */
1651 static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
1653 enumWndData *data = (enumWndData *)lParam;
1655 TRACE("(%p,%p)\n", hWnd, data);
1656 data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
1657 return TRUE;
1660 /*************************************************************************
1661 * @ [SHLWAPI.178]
1663 * Send or post a message to every child of a window.
1665 * PARAMS
1666 * hWnd [I] Window whose children will get the messages
1667 * uiMsgId [I] Message Id
1668 * wParam [I] WPARAM of message
1669 * lParam [I] LPARAM of message
1670 * bSend [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
1672 * RETURNS
1673 * Nothing.
1675 * NOTES
1676 * The appropriate ASCII or Unicode function is called for the window.
1678 void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
1680 enumWndData data;
1682 TRACE("(%p,%u,%d,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
1684 if(hWnd)
1686 data.uiMsgId = uiMsgId;
1687 data.wParam = wParam;
1688 data.lParam = lParam;
1690 if (bSend)
1691 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
1692 else
1693 data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
1695 EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
1699 /*************************************************************************
1700 * @ [SHLWAPI.180]
1702 * Remove all sub-menus from a menu.
1704 * PARAMS
1705 * hMenu [I] Menu to remove sub-menus from
1707 * RETURNS
1708 * Success: 0. All sub-menus under hMenu are removed
1709 * Failure: -1, if any parameter is invalid
1711 DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
1713 int iItemCount = GetMenuItemCount(hMenu) - 1;
1714 while (iItemCount >= 0)
1716 HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
1717 if (hSubMenu)
1718 RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
1719 iItemCount--;
1721 return iItemCount;
1724 /*************************************************************************
1725 * @ [SHLWAPI.181]
1727 * Enable or disable a menu item.
1729 * PARAMS
1730 * hMenu [I] Menu holding menu item
1731 * uID [I] ID of menu item to enable/disable
1732 * bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
1734 * RETURNS
1735 * The return code from EnableMenuItem.
1737 UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
1739 return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
1742 /*************************************************************************
1743 * @ [SHLWAPI.182]
1745 * Check or uncheck a menu item.
1747 * PARAMS
1748 * hMenu [I] Menu holding menu item
1749 * uID [I] ID of menu item to check/uncheck
1750 * bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
1752 * RETURNS
1753 * The return code from CheckMenuItem.
1755 DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
1757 return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
1760 /*************************************************************************
1761 * @ [SHLWAPI.183]
1763 * Register a window class if it isn't already.
1765 * PARAMS
1766 * lpWndClass [I] Window class to register
1768 * RETURNS
1769 * The result of the RegisterClassA call.
1771 DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
1773 WNDCLASSA wca;
1774 if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
1775 return TRUE;
1776 return (DWORD)RegisterClassA(wndclass);
1779 /*************************************************************************
1780 * @ [SHLWAPI.186]
1782 BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
1783 DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
1785 DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
1786 POINTL pt = { 0, 0 };
1788 if (!lpPt)
1789 lpPt = &pt;
1791 if (!pdwEffect)
1792 pdwEffect = &dwEffect;
1794 IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1796 if (*pdwEffect)
1797 return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
1799 IDropTarget_DragLeave(pDrop);
1800 return TRUE;
1803 /*************************************************************************
1804 * @ [SHLWAPI.187]
1806 * Call IPersistPropertyBag_Load() on an object.
1808 * PARAMS
1809 * lpUnknown [I] Object supporting the IPersistPropertyBag interface
1810 * lpPropBag [O] Destination for loaded IPropertyBag
1812 * RETURNS
1813 * Success: S_OK.
1814 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1816 DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
1818 IPersistPropertyBag* lpPPBag;
1819 HRESULT hRet = E_FAIL;
1821 TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
1823 if (lpUnknown)
1825 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
1826 (void**)&lpPPBag);
1827 if (SUCCEEDED(hRet) && lpPPBag)
1829 hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
1830 IPersistPropertyBag_Release(lpPPBag);
1833 return hRet;
1836 /*************************************************************************
1837 * @ [SHLWAPI.188]
1839 * Call IOleControlSite_TranslateAccelerator() on an object.
1841 * PARAMS
1842 * lpUnknown [I] Object supporting the IOleControlSite interface.
1843 * lpMsg [I] Key message to be processed.
1844 * dwModifiers [I] Flags containing the state of the modifier keys.
1846 * RETURNS
1847 * Success: S_OK.
1848 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
1850 HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
1852 IOleControlSite* lpCSite = NULL;
1853 HRESULT hRet = E_INVALIDARG;
1855 TRACE("(%p,%p,0x%08lx)\n", lpUnknown, lpMsg, dwModifiers);
1856 if (lpUnknown)
1858 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1859 (void**)&lpCSite);
1860 if (SUCCEEDED(hRet) && lpCSite)
1862 hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
1863 IOleControlSite_Release(lpCSite);
1866 return hRet;
1870 /*************************************************************************
1871 * @ [SHLWAPI.189]
1873 * Call IOleControlSite_GetExtendedControl() on an object.
1875 * PARAMS
1876 * lpUnknown [I] Object supporting the IOleControlSite interface.
1877 * lppDisp [O] Destination for resulting IDispatch.
1879 * RETURNS
1880 * Success: S_OK.
1881 * Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
1883 DWORD WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, IDispatch** lppDisp)
1885 IOleControlSite* lpCSite = NULL;
1886 HRESULT hRet = E_FAIL;
1888 TRACE("(%p,%p)\n", lpUnknown, lppDisp);
1889 if (lpUnknown)
1891 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
1892 (void**)&lpCSite);
1893 if (SUCCEEDED(hRet) && lpCSite)
1895 hRet = IOleControlSite_GetExtendedControl(lpCSite, lppDisp);
1896 IOleControlSite_Release(lpCSite);
1899 return hRet;
1902 /*************************************************************************
1903 * @ [SHLWAPI.190]
1905 HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
1906 PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
1908 /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
1909 static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1910 /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
1911 static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
1912 HRESULT hRet = E_INVALIDARG;
1913 LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
1915 TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
1917 if (lpUnknown && lpArg4)
1919 hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
1920 (REFGUID)function_id, (void**)&lpUnkInner);
1922 if (SUCCEEDED(hRet) && lpUnkInner)
1924 /* FIXME: The type of service object requested is unknown, however
1925 * testing shows that its first method is called with 4 parameters.
1926 * Fake this by using IParseDisplayName_ParseDisplayName since the
1927 * signature and position in the vtable matches our unknown object type.
1929 hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
1930 lpArg1, lpArg2, lpArg3, lpArg4);
1931 IUnknown_Release(lpUnkInner);
1934 return hRet;
1937 /*************************************************************************
1938 * @ [SHLWAPI.192]
1940 * Get a sub-menu from a menu item.
1942 * PARAMS
1943 * hMenu [I] Menu to get sub-menu from
1944 * uID [I] ID of menu item containing sub-menu
1946 * RETURNS
1947 * The sub-menu of the item, or a NULL handle if any parameters are invalid.
1949 HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
1951 MENUITEMINFOW mi;
1953 TRACE("(%p,%u)\n", hMenu, uID);
1955 mi.cbSize = sizeof(mi);
1956 mi.fMask = MIIM_SUBMENU;
1958 if (!GetMenuItemInfoW(hMenu, uID, FALSE, &mi))
1959 return NULL;
1961 return mi.hSubMenu;
1964 /*************************************************************************
1965 * @ [SHLWAPI.193]
1967 * Get the color depth of the primary display.
1969 * PARAMS
1970 * None.
1972 * RETURNS
1973 * The color depth of the primary display.
1975 DWORD WINAPI SHGetCurColorRes(void)
1977 HDC hdc;
1978 DWORD ret;
1980 TRACE("()\n");
1982 hdc = GetDC(0);
1983 ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
1984 ReleaseDC(0, hdc);
1985 return ret;
1988 /*************************************************************************
1989 * @ [SHLWAPI.194]
1991 * Wait for a message to arrive, with a timeout.
1993 * PARAMS
1994 * hand [I] Handle to query
1995 * dwTimeout [I] Timeout in ticks or INFINITE to never timeout
1997 * RETURNS
1998 * STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
1999 * Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
2000 * message is available.
2002 DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
2004 DWORD dwEndTicks = GetTickCount() + dwTimeout;
2005 DWORD dwRet;
2007 while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
2009 MSG msg;
2011 PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
2013 if (dwTimeout != INFINITE)
2015 if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
2016 return WAIT_TIMEOUT;
2020 return dwRet;
2023 /*************************************************************************
2024 * @ [SHLWAPI.195]
2026 * Determine if a shell folder can be expanded.
2028 * PARAMS
2029 * lpFolder [I] Parent folder containing the object to test.
2030 * pidl [I] Id of the object to test.
2032 * RETURNS
2033 * Success: S_OK, if the object is expandable, S_FALSE otherwise.
2034 * Failure: E_INVALIDARG, if any argument is invalid.
2036 * NOTES
2037 * If the object to be tested does not expose the IQueryInfo() interface it
2038 * will not be identified as an expandable folder.
2040 HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
2042 HRESULT hRet = E_INVALIDARG;
2043 IQueryInfo *lpInfo;
2045 if (lpFolder && pidl)
2047 hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
2048 NULL, (void**)&lpInfo);
2049 if (FAILED(hRet))
2050 hRet = S_FALSE; /* Doesn't expose IQueryInfo */
2051 else
2053 DWORD dwFlags = 0;
2055 /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
2056 * currently used". Really? You wouldn't be holding out on me would you?
2058 hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
2060 if (SUCCEEDED(hRet))
2062 /* 0x2 is an undocumented flag apparently indicating expandability */
2063 hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
2066 IQueryInfo_Release(lpInfo);
2069 return hRet;
2072 /*************************************************************************
2073 * @ [SHLWAPI.197]
2075 * Blank out a region of text by drawing the background only.
2077 * PARAMS
2078 * hDC [I] Device context to draw in
2079 * pRect [I] Area to draw in
2080 * cRef [I] Color to draw in
2082 * RETURNS
2083 * Nothing.
2085 DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
2087 COLORREF cOldColor = SetBkColor(hDC, cRef);
2088 ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
2089 SetBkColor(hDC, cOldColor);
2090 return 0;
2093 /*************************************************************************
2094 * @ [SHLWAPI.198]
2096 * Return the value asociated with a key in a map.
2098 * PARAMS
2099 * lpKeys [I] A list of keys of length iLen
2100 * lpValues [I] A list of values associated with lpKeys, of length iLen
2101 * iLen [I] Length of both lpKeys and lpValues
2102 * iKey [I] The key value to look up in lpKeys
2104 * RETURNS
2105 * The value in lpValues associated with iKey, or -1 if iKey is not
2106 * found in lpKeys.
2108 * NOTES
2109 * - If two elements in the map share the same key, this function returns
2110 * the value closest to the start of the map
2111 * - The native version of this function crashes if lpKeys or lpValues is NULL.
2113 int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
2115 if (lpKeys && lpValues)
2117 int i = 0;
2119 while (i < iLen)
2121 if (lpKeys[i] == iKey)
2122 return lpValues[i]; /* Found */
2123 i++;
2126 return -1; /* Not found */
2130 /*************************************************************************
2131 * @ [SHLWAPI.199]
2133 * Copy an interface pointer
2135 * PARAMS
2136 * lppDest [O] Destination for copy
2137 * lpUnknown [I] Source for copy
2139 * RETURNS
2140 * Nothing.
2142 VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
2144 TRACE("(%p,%p)\n", lppDest, lpUnknown);
2146 if (lppDest)
2147 IUnknown_AtomicRelease(lppDest); /* Release existing interface */
2149 if (lpUnknown)
2151 /* Copy */
2152 IUnknown_AddRef(lpUnknown);
2153 *lppDest = lpUnknown;
2157 /*************************************************************************
2158 * @ [SHLWAPI.200]
2161 HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
2162 REFGUID riidCmdGrp, ULONG cCmds,
2163 OLECMD *prgCmds, OLECMDTEXT* pCmdText)
2165 FIXME("(%p,%p,%p,%ld,%p,%p) - stub\n",
2166 lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
2168 /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
2169 return DRAGDROP_E_NOTREGISTERED;
2172 /*************************************************************************
2173 * @ [SHLWAPI.201]
2176 HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
2177 DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
2178 VARIANT* pvaOut)
2180 FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
2181 nCmdID, nCmdexecopt, pvaIn, pvaOut);
2182 return DRAGDROP_E_NOTREGISTERED;
2185 /*************************************************************************
2186 * @ [SHLWAPI.202]
2189 HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
2191 FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
2192 return DRAGDROP_E_NOTREGISTERED;
2195 /*************************************************************************
2196 * @ [SHLWAPI.204]
2198 * Determine if a window is not a child of another window.
2200 * PARAMS
2201 * hParent [I] Suspected parent window
2202 * hChild [I] Suspected child window
2204 * RETURNS
2205 * TRUE: If hChild is a child window of hParent
2206 * FALSE: If hChild is not a child window of hParent, or they are equal
2208 BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
2210 TRACE("(%p,%p)\n", hParent, hChild);
2212 if (!hParent || !hChild)
2213 return TRUE;
2214 else if(hParent == hChild)
2215 return FALSE;
2216 return !IsChild(hParent, hChild);
2219 /*************************************************************************
2220 * FDSA functions. Manage a dynamic array of fixed size memory blocks.
2223 typedef struct
2225 DWORD num_items; /* Number of elements inserted */
2226 void *mem; /* Ptr to array */
2227 DWORD blocks_alloced; /* Number of elements allocated */
2228 BYTE inc; /* Number of elements to grow by when we need to expand */
2229 BYTE block_size; /* Size in bytes of an element */
2230 BYTE flags; /* Flags */
2231 } FDSA_info;
2233 #define FDSA_FLAG_INTERNAL_ALLOC 0x01 /* When set we have allocated mem internally */
2235 /*************************************************************************
2236 * @ [SHLWAPI.208]
2238 * Initialize an FDSA arrary.
2240 BOOL WINAPI FDSA_Initialize(DWORD block_size, DWORD inc, FDSA_info *info, void *mem,
2241 DWORD init_blocks)
2243 TRACE("(0x%08lx 0x%08lx %p %p 0x%08lx)\n", block_size, inc, info, mem, init_blocks);
2245 if(inc == 0)
2246 inc = 1;
2248 if(mem)
2249 memset(mem, 0, block_size * init_blocks);
2251 info->num_items = 0;
2252 info->inc = inc;
2253 info->mem = mem;
2254 info->blocks_alloced = init_blocks;
2255 info->block_size = block_size;
2256 info->flags = 0;
2258 return TRUE;
2261 /*************************************************************************
2262 * @ [SHLWAPI.209]
2264 * Destroy an FDSA array
2266 BOOL WINAPI FDSA_Destroy(FDSA_info *info)
2268 TRACE("(%p)\n", info);
2270 if(info->flags & FDSA_FLAG_INTERNAL_ALLOC)
2272 HeapFree(GetProcessHeap(), 0, info->mem);
2273 return FALSE;
2276 return TRUE;
2279 /*************************************************************************
2280 * @ [SHLWAPI.210]
2282 * Insert element into an FDSA array
2284 DWORD WINAPI FDSA_InsertItem(FDSA_info *info, DWORD where, void *block)
2286 TRACE("(%p 0x%08lx %p)\n", info, where, block);
2287 if(where > info->num_items)
2288 where = info->num_items;
2290 if(info->num_items >= info->blocks_alloced)
2292 DWORD size = (info->blocks_alloced + info->inc) * info->block_size;
2293 if(info->flags & 0x1)
2294 info->mem = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->mem, size);
2295 else
2297 void *old_mem = info->mem;
2298 info->mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
2299 memcpy(info->mem, old_mem, info->blocks_alloced * info->block_size);
2301 info->blocks_alloced += info->inc;
2302 info->flags |= 0x1;
2305 if(where < info->num_items)
2307 memmove((char*)info->mem + (where + 1) * info->block_size,
2308 (char*)info->mem + where * info->block_size,
2309 (info->num_items - where) * info->block_size);
2311 memcpy((char*)info->mem + where * info->block_size, block, info->block_size);
2313 info->num_items++;
2314 return where;
2317 /*************************************************************************
2318 * @ [SHLWAPI.211]
2320 * Delete an element from an FDSA array.
2322 BOOL WINAPI FDSA_DeleteItem(FDSA_info *info, DWORD where)
2324 TRACE("(%p 0x%08lx)\n", info, where);
2326 if(where >= info->num_items)
2327 return FALSE;
2329 if(where < info->num_items - 1)
2331 memmove((char*)info->mem + where * info->block_size,
2332 (char*)info->mem + (where + 1) * info->block_size,
2333 (info->num_items - where - 1) * info->block_size);
2335 memset((char*)info->mem + (info->num_items - 1) * info->block_size,
2336 0, info->block_size);
2337 info->num_items--;
2338 return TRUE;
2342 typedef struct {
2343 REFIID refid;
2344 DWORD indx;
2345 } IFACE_INDEX_TBL;
2347 /*************************************************************************
2348 * @ [SHLWAPI.219]
2350 * Call IUnknown_QueryInterface() on a table of objects.
2352 * RETURNS
2353 * Success: S_OK.
2354 * Failure: E_POINTER or E_NOINTERFACE.
2356 HRESULT WINAPI QISearch(
2357 LPVOID w, /* [in] Table of interfaces */
2358 IFACE_INDEX_TBL *x, /* [in] Array of REFIIDs and indexes into the table */
2359 REFIID riid, /* [in] REFIID to get interface for */
2360 LPVOID *ppv) /* [out] Destination for interface pointer */
2362 HRESULT ret;
2363 IUnknown *a_vtbl;
2364 IFACE_INDEX_TBL *xmove;
2366 TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
2367 if (ppv) {
2368 xmove = x;
2369 while (xmove->refid) {
2370 TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));
2371 if (IsEqualIID(riid, xmove->refid)) {
2372 a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
2373 TRACE("matched, returning (%p)\n", a_vtbl);
2374 *ppv = (LPVOID)a_vtbl;
2375 IUnknown_AddRef(a_vtbl);
2376 return S_OK;
2378 xmove++;
2381 if (IsEqualIID(riid, &IID_IUnknown)) {
2382 a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
2383 TRACE("returning first for IUnknown (%p)\n", a_vtbl);
2384 *ppv = (LPVOID)a_vtbl;
2385 IUnknown_AddRef(a_vtbl);
2386 return S_OK;
2388 *ppv = 0;
2389 ret = E_NOINTERFACE;
2390 } else
2391 ret = E_POINTER;
2393 TRACE("-- 0x%08lx\n", ret);
2394 return ret;
2397 /*************************************************************************
2398 * @ [SHLWAPI.221]
2400 * Remove the "PropDlgFont" property from a window.
2402 * PARAMS
2403 * hWnd [I] Window to remove the property from
2405 * RETURNS
2406 * A handle to the removed property, or NULL if it did not exist.
2408 HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
2410 HANDLE hProp;
2412 TRACE("(%p)\n", hWnd);
2414 hProp = GetPropA(hWnd, "PropDlgFont");
2416 if(hProp)
2418 DeleteObject(hProp);
2419 hProp = RemovePropA(hWnd, "PropDlgFont");
2421 return hProp;
2424 /*************************************************************************
2425 * @ [SHLWAPI.236]
2427 * Load the in-process server of a given GUID.
2429 * PARAMS
2430 * refiid [I] GUID of the server to load.
2432 * RETURNS
2433 * Success: A handle to the loaded server dll.
2434 * Failure: A NULL handle.
2436 HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
2438 HKEY newkey;
2439 DWORD type, count;
2440 CHAR value[MAX_PATH], string[MAX_PATH];
2442 strcpy(string, "CLSID\\");
2443 SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
2444 strcat(string, "\\InProcServer32");
2446 count = MAX_PATH;
2447 RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
2448 RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
2449 RegCloseKey(newkey);
2450 return LoadLibraryExA(value, 0, 0);
2453 /*************************************************************************
2454 * @ [SHLWAPI.237]
2456 * Unicode version of SHLWAPI_183.
2458 DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
2460 WNDCLASSW WndClass;
2462 TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
2464 if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
2465 return TRUE;
2466 return RegisterClassW(lpWndClass);
2469 /*************************************************************************
2470 * @ [SHLWAPI.238]
2472 * Unregister a list of classes.
2474 * PARAMS
2475 * hInst [I] Application instance that registered the classes
2476 * lppClasses [I] List of class names
2477 * iCount [I] Number of names in lppClasses
2479 * RETURNS
2480 * Nothing.
2482 void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
2484 WNDCLASSA WndClass;
2486 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2488 while (iCount > 0)
2490 if (GetClassInfoA(hInst, *lppClasses, &WndClass))
2491 UnregisterClassA(*lppClasses, hInst);
2492 lppClasses++;
2493 iCount--;
2497 /*************************************************************************
2498 * @ [SHLWAPI.239]
2500 * Unicode version of SHUnregisterClassesA.
2502 void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
2504 WNDCLASSW WndClass;
2506 TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
2508 while (iCount > 0)
2510 if (GetClassInfoW(hInst, *lppClasses, &WndClass))
2511 UnregisterClassW(*lppClasses, hInst);
2512 lppClasses++;
2513 iCount--;
2517 /*************************************************************************
2518 * @ [SHLWAPI.240]
2520 * Call The correct (Ascii/Unicode) default window procedure for a window.
2522 * PARAMS
2523 * hWnd [I] Window to call the default procedure for
2524 * uMessage [I] Message ID
2525 * wParam [I] WPARAM of message
2526 * lParam [I] LPARAM of message
2528 * RETURNS
2529 * The result of calling DefWindowProcA() or DefWindowProcW().
2531 LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
2533 if (IsWindowUnicode(hWnd))
2534 return DefWindowProcW(hWnd, uMessage, wParam, lParam);
2535 return DefWindowProcA(hWnd, uMessage, wParam, lParam);
2538 /*************************************************************************
2539 * @ [SHLWAPI.256]
2541 HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
2543 HRESULT hRet = E_INVALIDARG;
2544 LPOBJECTWITHSITE lpSite = NULL;
2546 TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
2548 if (lpUnknown && iid && lppSite)
2550 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
2551 (void**)&lpSite);
2552 if (SUCCEEDED(hRet) && lpSite)
2554 hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
2555 IObjectWithSite_Release(lpSite);
2558 return hRet;
2561 /*************************************************************************
2562 * @ [SHLWAPI.257]
2564 * Create a worker window using CreateWindowExA().
2566 * PARAMS
2567 * wndProc [I] Window procedure
2568 * hWndParent [I] Parent window
2569 * dwExStyle [I] Extra style flags
2570 * dwStyle [I] Style flags
2571 * hMenu [I] Window menu
2572 * z [I] Unknown
2574 * RETURNS
2575 * Success: The window handle of the newly created window.
2576 * Failure: 0.
2578 HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2579 DWORD dwStyle, HMENU hMenu, LONG z)
2581 static const char* szClass = "WorkerA";
2582 WNDCLASSA wc;
2583 HWND hWnd;
2585 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2586 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2588 /* Create Window class */
2589 wc.style = 0;
2590 wc.lpfnWndProc = DefWindowProcA;
2591 wc.cbClsExtra = 0;
2592 wc.cbWndExtra = 4;
2593 wc.hInstance = shlwapi_hInstance;
2594 wc.hIcon = NULL;
2595 wc.hCursor = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
2596 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2597 wc.lpszMenuName = NULL;
2598 wc.lpszClassName = szClass;
2600 SHRegisterClassA(&wc); /* Register class */
2602 /* FIXME: Set extra bits in dwExStyle */
2604 hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2605 hWndParent, hMenu, shlwapi_hInstance, 0);
2606 if (hWnd)
2608 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2610 if (wndProc)
2611 SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
2613 return hWnd;
2616 typedef struct tagPOLICYDATA
2618 DWORD policy; /* flags value passed to SHRestricted */
2619 LPCWSTR appstr; /* application str such as "Explorer" */
2620 LPCWSTR keystr; /* name of the actual registry key / policy */
2621 } POLICYDATA, *LPPOLICYDATA;
2623 #define SHELL_NO_POLICY 0xffffffff
2625 /* default shell policy registry key */
2626 static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
2627 's','o','f','t','\\','W','i','n','d','o','w','s','\\',
2628 'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
2629 '\\','P','o','l','i','c','i','e','s',0};
2631 /*************************************************************************
2632 * @ [SHLWAPI.271]
2634 * Retrieve a policy value from the registry.
2636 * PARAMS
2637 * lpSubKey [I] registry key name
2638 * lpSubName [I] subname of registry key
2639 * lpValue [I] value name of registry value
2641 * RETURNS
2642 * the value associated with the registry key or 0 if not found
2644 DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
2646 DWORD retval, datsize = sizeof(retval);
2647 HKEY hKey;
2649 if (!lpSubKey)
2650 lpSubKey = strRegistryPolicyW;
2652 retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
2653 if (retval != ERROR_SUCCESS)
2654 retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
2655 if (retval != ERROR_SUCCESS)
2656 return 0;
2658 SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);
2659 RegCloseKey(hKey);
2660 return retval;
2663 /*************************************************************************
2664 * @ [SHLWAPI.266]
2666 * Helper function to retrieve the possibly cached value for a specific policy
2668 * PARAMS
2669 * policy [I] The policy to look for
2670 * initial [I] Main registry key to open, if NULL use default
2671 * polTable [I] Table of known policies, 0 terminated
2672 * polArr [I] Cache array of policy values
2674 * RETURNS
2675 * The retrieved policy value or 0 if not successful
2677 * NOTES
2678 * This function is used by the native SHRestricted function to search for the
2679 * policy and cache it once retrieved. The current Wine implementation uses a
2680 * different POLICYDATA structure and implements a similar algorithme adapted to
2681 * that structure.
2683 DWORD WINAPI SHRestrictionLookup(
2684 DWORD policy,
2685 LPCWSTR initial,
2686 LPPOLICYDATA polTable,
2687 LPDWORD polArr)
2689 TRACE("(0x%08lx %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
2691 if (!polTable || !polArr)
2692 return 0;
2694 for (;polTable->policy; polTable++, polArr++)
2696 if (policy == polTable->policy)
2698 /* we have a known policy */
2700 /* check if this policy has been cached */
2701 if (*polArr == SHELL_NO_POLICY)
2702 *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
2703 return *polArr;
2706 /* we don't know this policy, return 0 */
2707 TRACE("unknown policy: (%08lx)\n", policy);
2708 return 0;
2711 /*************************************************************************
2712 * @ [SHLWAPI.267]
2714 * Get an interface from an object.
2716 * RETURNS
2717 * Success: S_OK. ppv contains the requested interface.
2718 * Failure: An HRESULT error code.
2720 * NOTES
2721 * This QueryInterface asks the inner object for an interface. In case
2722 * of aggregation this request would be forwarded by the inner to the
2723 * outer object. This function asks the inner object directly for the
2724 * interface circumventing the forwarding to the outer object.
2726 HRESULT WINAPI SHWeakQueryInterface(
2727 IUnknown * pUnk, /* [in] Outer object */
2728 IUnknown * pInner, /* [in] Inner object */
2729 IID * riid, /* [in] Interface GUID to query for */
2730 LPVOID* ppv) /* [out] Destination for queried interface */
2732 HRESULT hret = E_NOINTERFACE;
2733 TRACE("(pUnk=%p pInner=%p\n\tIID: %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
2735 *ppv = NULL;
2736 if(pUnk && pInner) {
2737 hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
2738 if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
2740 TRACE("-- 0x%08lx\n", hret);
2741 return hret;
2744 /*************************************************************************
2745 * @ [SHLWAPI.268]
2747 * Move a reference from one interface to another.
2749 * PARAMS
2750 * lpDest [O] Destination to receive the reference
2751 * lppUnknown [O] Source to give up the reference to lpDest
2753 * RETURNS
2754 * Nothing.
2756 VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
2758 TRACE("(%p,%p)\n", lpDest, lppUnknown);
2760 if (*lppUnknown)
2762 /* Copy Reference*/
2763 IUnknown_AddRef(lpDest);
2764 IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
2768 /*************************************************************************
2769 * @ [SHLWAPI.269]
2771 * Convert an ASCII string of a CLSID into a CLSID.
2773 * PARAMS
2774 * idstr [I] String representing a CLSID in registry format
2775 * id [O] Destination for the converted CLSID
2777 * RETURNS
2778 * Success: TRUE. id contains the converted CLSID.
2779 * Failure: FALSE.
2781 BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
2783 WCHAR wClsid[40];
2784 MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
2785 return SUCCEEDED(CLSIDFromStringWrap(wClsid, id));
2788 /*************************************************************************
2789 * @ [SHLWAPI.270]
2791 * Unicode version of GUIDFromStringA.
2793 BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
2795 return SUCCEEDED(CLSIDFromStringWrap(idstr, id));
2798 /*************************************************************************
2799 * @ [SHLWAPI.276]
2801 * Determine if the browser is integrated into the shell, and set a registry
2802 * key accordingly.
2804 * PARAMS
2805 * None.
2807 * RETURNS
2808 * 1, If the browser is not integrated.
2809 * 2, If the browser is integrated.
2811 * NOTES
2812 * The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
2813 * either set to TRUE, or removed depending on whether the browser is deemed
2814 * to be integrated.
2816 DWORD WINAPI WhichPlatform(void)
2818 static LPCSTR szIntegratedBrowser = "IntegratedBrowser";
2819 static DWORD dwState = 0;
2820 HKEY hKey;
2821 DWORD dwRet, dwData, dwSize;
2823 if (dwState)
2824 return dwState;
2826 /* If shell32 exports DllGetVersion(), the browser is integrated */
2827 GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);
2828 dwState = pDllGetVersion ? 2 : 1;
2830 /* Set or delete the key accordingly */
2831 dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
2832 "Software\\Microsoft\\Internet Explorer", 0,
2833 KEY_ALL_ACCESS, &hKey);
2834 if (!dwRet)
2836 dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
2837 (LPBYTE)&dwData, &dwSize);
2839 if (!dwRet && dwState == 1)
2841 /* Value exists but browser is not integrated */
2842 RegDeleteValueA(hKey, szIntegratedBrowser);
2844 else if (dwRet && dwState == 2)
2846 /* Browser is integrated but value does not exist */
2847 dwData = TRUE;
2848 RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
2849 (LPBYTE)&dwData, sizeof(dwData));
2851 RegCloseKey(hKey);
2853 return dwState;
2856 /*************************************************************************
2857 * @ [SHLWAPI.278]
2859 * Unicode version of SHCreateWorkerWindowA.
2861 HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
2862 DWORD dwStyle, HMENU hMenu, LONG z)
2864 static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
2865 WNDCLASSW wc;
2866 HWND hWnd;
2868 TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
2869 wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2871 /* If our OS is natively ASCII, use the ASCII version */
2872 if (!(GetVersion() & 0x80000000)) /* NT */
2873 return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
2875 /* Create Window class */
2876 wc.style = 0;
2877 wc.lpfnWndProc = DefWindowProcW;
2878 wc.cbClsExtra = 0;
2879 wc.cbWndExtra = 4;
2880 wc.hInstance = shlwapi_hInstance;
2881 wc.hIcon = NULL;
2882 wc.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
2883 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
2884 wc.lpszMenuName = NULL;
2885 wc.lpszClassName = szClass;
2887 SHRegisterClassW(&wc); /* Register class */
2889 /* FIXME: Set extra bits in dwExStyle */
2891 hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
2892 hWndParent, hMenu, shlwapi_hInstance, 0);
2893 if (hWnd)
2895 SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
2897 if (wndProc)
2898 SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
2900 return hWnd;
2903 /*************************************************************************
2904 * @ [SHLWAPI.279]
2906 * Get and show a context menu from a shell folder.
2908 * PARAMS
2909 * hWnd [I] Window displaying the shell folder
2910 * lpFolder [I] IShellFolder interface
2911 * lpApidl [I] Id for the particular folder desired
2913 * RETURNS
2914 * Success: S_OK.
2915 * Failure: An HRESULT error code indicating the error.
2917 HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
2919 return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
2922 /*************************************************************************
2923 * @ [SHLWAPI.281]
2925 * _SHPackDispParamsV
2927 HRESULT WINAPI SHPackDispParamsV(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2929 FIXME("%p %p %p %p\n",w,x,y,z);
2930 return E_FAIL;
2933 /*************************************************************************
2934 * @ [SHLWAPI.282]
2936 * This function seems to be a forward to SHPackDispParamsV (whatever THAT
2937 * function does...).
2939 HRESULT WINAPI SHPackDispParams(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
2941 FIXME("%p %p %p %p\n", w, x, y, z);
2942 return E_FAIL;
2945 /*************************************************************************
2946 * @ [SHLWAPI.284]
2948 * _IConnectionPoint_SimpleInvoke
2950 DWORD WINAPI IConnectionPoint_SimpleInvoke(
2951 LPVOID x,
2952 LPVOID y,
2953 LPVOID z)
2955 FIXME("(%p %p %p) stub\n",x,y,z);
2956 return 0;
2959 /*************************************************************************
2960 * @ [SHLWAPI.285]
2962 * Notify an IConnectionPoint object of changes.
2964 * PARAMS
2965 * lpCP [I] Object to notify
2966 * dispID [I]
2968 * RETURNS
2969 * Success: S_OK.
2970 * Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
2971 * IConnectionPoint interface.
2973 HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
2975 IEnumConnections *lpEnum;
2976 HRESULT hRet = E_NOINTERFACE;
2978 TRACE("(%p,0x%8lX)\n", lpCP, dispID);
2980 /* Get an enumerator for the connections */
2981 if (lpCP)
2982 hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
2984 if (SUCCEEDED(hRet))
2986 IPropertyNotifySink *lpSink;
2987 CONNECTDATA connData;
2988 ULONG ulFetched;
2990 /* Call OnChanged() for every notify sink in the connection point */
2991 while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
2993 if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
2994 lpSink)
2996 IPropertyNotifySink_OnChanged(lpSink, dispID);
2997 IPropertyNotifySink_Release(lpSink);
2999 IUnknown_Release(connData.pUnk);
3002 IEnumConnections_Release(lpEnum);
3004 return hRet;
3007 /*************************************************************************
3008 * @ [SHLWAPI.287]
3010 * Notify an IConnectionPointContainer object of changes.
3012 * PARAMS
3013 * lpUnknown [I] Object to notify
3014 * dispID [I]
3016 * RETURNS
3017 * Success: S_OK.
3018 * Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
3019 * IConnectionPointContainer interface.
3021 HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
3023 IConnectionPointContainer* lpCPC = NULL;
3024 HRESULT hRet = E_NOINTERFACE;
3026 TRACE("(%p,0x%8lX)\n", lpUnknown, dispID);
3028 if (lpUnknown)
3029 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
3031 if (SUCCEEDED(hRet))
3033 IConnectionPoint* lpCP;
3035 hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
3036 IConnectionPointContainer_Release(lpCPC);
3038 hRet = IConnectionPoint_OnChanged(lpCP, dispID);
3039 IConnectionPoint_Release(lpCP);
3041 return hRet;
3044 /*************************************************************************
3045 * @ [SHLWAPI.289]
3047 * See PlaySoundW.
3049 BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
3051 GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
3052 return pPlaySoundW(pszSound, hmod, fdwSound);
3055 /*************************************************************************
3056 * @ [SHLWAPI.294]
3058 BOOL WINAPI SHGetIniStringW(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len, LPCSTR lpStr2)
3061 * str1: "I" "I" pushl esp+0x20
3062 * str2: "U" "I" pushl 0x77c93810
3063 * (is "I" and "U" "integer" and "unsigned" ??)
3065 * pStr: "" "" pushl eax
3066 * some_len: 0x824 0x104 pushl 0x824
3067 * lpStr2: "%l" "%l" pushl esp+0xc
3069 * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
3070 * LocalAlloc(0x00, some_len) -> irrelevant_var
3071 * LocalAlloc(0x40, irrelevant_len) -> pStr
3072 * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
3073 * shlwapi.PathRemoveBlanksW(pStr);
3075 FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
3076 return TRUE;
3079 /*************************************************************************
3080 * @ [SHLWAPI.295]
3082 * Called by ICQ2000b install via SHDOCVW:
3083 * str1: "InternetShortcut"
3084 * x: some unknown pointer
3085 * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
3086 * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
3088 * In short: this one maybe creates a desktop link :-)
3090 BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
3092 FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
3093 return TRUE;
3096 /*************************************************************************
3097 * @ [SHLWAPI.299]
3099 * See COMCTL32_417.
3101 BOOL WINAPI ExtTextOutWrapW(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
3102 LPCWSTR str, UINT count, const INT *lpDx)
3104 GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);
3105 return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);
3108 /*************************************************************************
3109 * @ [SHLWAPI.313]
3111 * See SHGetFileInfoW.
3113 DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
3114 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
3116 GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
3117 return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
3120 /*************************************************************************
3121 * @ [SHLWAPI.318]
3123 * See DragQueryFileW.
3125 UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
3127 GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
3128 return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
3131 /*************************************************************************
3132 * @ [SHLWAPI.333]
3134 * See SHBrowseForFolderW.
3136 LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
3138 GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
3139 return pSHBrowseForFolderW(lpBi);
3142 /*************************************************************************
3143 * @ [SHLWAPI.334]
3145 * See SHGetPathFromIDListW.
3147 BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
3149 GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
3150 return pSHGetPathFromIDListW(pidl, pszPath);
3153 /*************************************************************************
3154 * @ [SHLWAPI.335]
3156 * See ShellExecuteExW.
3158 BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
3160 GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
3161 return pShellExecuteExW(lpExecInfo);
3164 /*************************************************************************
3165 * @ [SHLWAPI.336]
3167 * See SHFileOperationW.
3169 HICON WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
3171 GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
3172 return pSHFileOperationW(lpFileOp);
3175 /*************************************************************************
3176 * @ [SHLWAPI.337]
3178 * See ExtractIconExW.
3180 UINT WINAPI ExtractIconExWrapW(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
3181 HICON *phiconSmall, UINT nIcons)
3183 GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", 0);
3184 return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
3187 /*************************************************************************
3188 * @ [SHLWAPI.342]
3191 LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
3193 return InterlockedCompareExchange(dest, xchg, compare);
3196 /*************************************************************************
3197 * @ [SHLWAPI.350]
3199 * See GetFileVersionInfoSizeW.
3201 DWORD WINAPI GetFileVersionInfoSizeWrapW(
3202 LPWSTR x,
3203 LPVOID y)
3205 DWORD ret;
3207 GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
3208 ret = pGetFileVersionInfoSizeW(x, y);
3209 return 0x208 + ret;
3212 /*************************************************************************
3213 * @ [SHLWAPI.351]
3215 * See GetFileVersionInfoW.
3217 BOOL WINAPI GetFileVersionInfoWrapW(
3218 LPWSTR w, /* [in] path to dll */
3219 DWORD x, /* [in] parm 2 to GetFileVersionInfoA */
3220 DWORD y, /* [in] return value from SHLWAPI_350() - assume length */
3221 LPVOID z) /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA()) */
3223 GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
3224 return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);
3227 /*************************************************************************
3228 * @ [SHLWAPI.352]
3230 * See VerQueryValueW.
3232 WORD WINAPI VerQueryValueWrapW(
3233 LPVOID w, /* [in] Buffer from SHLWAPI_351() */
3234 LPWSTR x, /* [in] Value to retrieve - converted and passed to VerQueryValueA() as #2 */
3235 LPVOID y, /* [out] Ver buffer - passed to VerQueryValueA as #3 */
3236 UINT* z) /* [in] Ver length - passed to VerQueryValueA as #4 */
3238 GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
3239 return pVerQueryValueW((char*)w+0x208, x, y, z);
3242 #define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
3243 #define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
3244 #define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
3246 /*************************************************************************
3247 * @ [SHLWAPI.355]
3249 * Change the modality of a shell object.
3251 * PARAMS
3252 * lpUnknown [I] Object to make modeless
3253 * bModeless [I] TRUE=Make modeless, FALSE=Make modal
3255 * RETURNS
3256 * Success: S_OK. The modality lpUnknown is changed.
3257 * Failure: An HRESULT error code indicating the error.
3259 * NOTES
3260 * lpUnknown must support the IOleInPlaceFrame interface, the
3261 * IInternetSecurityMgrSite interface, the IShellBrowser interface
3262 * the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
3263 * or this call will fail.
3265 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
3267 IUnknown *lpObj;
3268 HRESULT hRet;
3270 TRACE("(%p,%d)\n", lpUnknown, bModeless);
3272 if (!lpUnknown)
3273 return E_FAIL;
3275 if (IsIface(IOleInPlaceActiveObject))
3276 EnableModeless(IOleInPlaceActiveObject);
3277 else if (IsIface(IOleInPlaceFrame))
3278 EnableModeless(IOleInPlaceFrame);
3279 else if (IsIface(IShellBrowser))
3280 EnableModeless(IShellBrowser);
3281 #if 0
3282 /* FIXME: Wine has no headers for these objects yet */
3283 else if (IsIface(IInternetSecurityMgrSite))
3284 EnableModeless(IInternetSecurityMgrSite);
3285 else if (IsIface(IDocHostUIHandler))
3286 EnableModeless(IDocHostUIHandler);
3287 #endif
3288 else
3289 return hRet;
3291 IUnknown_Release(lpObj);
3292 return S_OK;
3295 /*************************************************************************
3296 * @ [SHLWAPI.357]
3298 * See SHGetNewLinkInfoW.
3300 BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
3301 BOOL *pfMustCopy, UINT uFlags)
3303 GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
3304 return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
3307 /*************************************************************************
3308 * @ [SHLWAPI.358]
3310 * See SHDefExtractIconW.
3312 UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
3313 HICON* phiconSmall, UINT nIconSize)
3315 GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
3316 return pSHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
3319 /*************************************************************************
3320 * @ [SHLWAPI.363]
3322 * Get and show a context menu from a shell folder.
3324 * PARAMS
3325 * hWnd [I] Window displaying the shell folder
3326 * lpFolder [I] IShellFolder interface
3327 * lpApidl [I] Id for the particular folder desired
3328 * bInvokeDefault [I] Whether to invoke the default menu item
3330 * RETURNS
3331 * Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
3332 * executed.
3333 * Failure: An HRESULT error code indicating the error.
3335 HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
3337 IContextMenu *iContext;
3338 HRESULT hRet = E_FAIL;
3340 TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
3342 if (!lpFolder)
3343 return hRet;
3345 /* Get the context menu from the shell folder */
3346 hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
3347 &IID_IContextMenu, 0, (void**)&iContext);
3348 if (SUCCEEDED(hRet))
3350 HMENU hMenu;
3351 if ((hMenu = CreatePopupMenu()))
3353 HRESULT hQuery;
3354 DWORD dwDefaultId = 0;
3356 /* Add the context menu entries to the popup */
3357 hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
3358 bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
3360 if (SUCCEEDED(hQuery))
3362 if (bInvokeDefault &&
3363 (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
3365 CMINVOKECOMMANDINFO cmIci;
3366 /* Invoke the default item */
3367 memset(&cmIci,0,sizeof(cmIci));
3368 cmIci.cbSize = sizeof(cmIci);
3369 cmIci.fMask = CMIC_MASK_ASYNCOK;
3370 cmIci.hwnd = hWnd;
3371 cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
3372 cmIci.nShow = SW_SCROLLCHILDREN;
3374 hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
3377 DestroyMenu(hMenu);
3379 IContextMenu_Release(iContext);
3381 return hRet;
3384 /*************************************************************************
3385 * @ [SHLWAPI.370]
3387 * See ExtractIconW.
3389 HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
3390 UINT nIconIndex)
3392 GET_FUNC(pExtractIconW, shell32, "ExtractIconW", NULL);
3393 return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
3396 /*************************************************************************
3397 * @ [SHLWAPI.377]
3399 * Load a library from the directory of a particular process.
3401 * PARAMS
3402 * new_mod [I] Library name
3403 * inst_hwnd [I] Module whose directory is to be used
3404 * bCrossCodePage [I] Should be FALSE (currently ignored)
3406 * RETURNS
3407 * Success: A handle to the loaded module
3408 * Failure: A NULL handle.
3410 HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, BOOL bCrossCodePage)
3412 /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
3413 * each call here.
3414 * FIXME: Native shows calls to:
3415 * SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
3416 * CheckVersion
3417 * RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
3418 * RegQueryValueExA for "LPKInstalled"
3419 * RegCloseKey
3420 * RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
3421 * RegQueryValueExA for "ResourceLocale"
3422 * RegCloseKey
3423 * RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
3424 * RegQueryValueExA for "Locale"
3425 * RegCloseKey
3426 * and then tests the Locale ("en" for me).
3427 * code below
3428 * after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
3430 CHAR mod_path[2*MAX_PATH];
3431 LPSTR ptr;
3432 DWORD len;
3434 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, bCrossCodePage);
3435 len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
3436 if (!len || len >= sizeof(mod_path)) return NULL;
3438 ptr = strrchr(mod_path, '\\');
3439 if (ptr) {
3440 strcpy(ptr+1, new_mod);
3441 TRACE("loading %s\n", debugstr_a(mod_path));
3442 return LoadLibraryA(mod_path);
3444 return NULL;
3447 /*************************************************************************
3448 * @ [SHLWAPI.378]
3450 * Unicode version of MLLoadLibraryA.
3452 HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, BOOL bCrossCodePage)
3454 WCHAR mod_path[2*MAX_PATH];
3455 LPWSTR ptr;
3456 DWORD len;
3458 FIXME("(%s,%p,%d) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, bCrossCodePage);
3459 len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
3460 if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
3462 ptr = strrchrW(mod_path, '\\');
3463 if (ptr) {
3464 strcpyW(ptr+1, new_mod);
3465 TRACE("loading %s\n", debugstr_w(mod_path));
3466 return LoadLibraryW(mod_path);
3468 return NULL;
3471 /*************************************************************************
3472 * ColorAdjustLuma [SHLWAPI.@]
3474 * Adjust the luminosity of a color
3476 * PARAMS
3477 * cRGB [I] RGB value to convert
3478 * dwLuma [I] Luma adjustment
3479 * bUnknown [I] Unknown
3481 * RETURNS
3482 * The adjusted RGB color.
3484 COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
3486 TRACE("(0x%8lx,%d,%d)\n", cRGB, dwLuma, bUnknown);
3488 if (dwLuma)
3490 WORD wH, wL, wS;
3492 ColorRGBToHLS(cRGB, &wH, &wL, &wS);
3494 FIXME("Ignoring luma adjustment\n");
3496 /* FIXME: The ajdustment is not linear */
3498 cRGB = ColorHLSToRGB(wH, wL, wS);
3500 return cRGB;
3503 /*************************************************************************
3504 * @ [SHLWAPI.389]
3506 * See GetSaveFileNameW.
3508 BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
3510 GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
3511 return pGetSaveFileNameW(ofn);
3514 /*************************************************************************
3515 * @ [SHLWAPI.390]
3517 * See WNetRestoreConnectionW.
3519 DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
3521 GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
3522 return pWNetRestoreConnectionW(hwndOwner, lpszDevice);
3525 /*************************************************************************
3526 * @ [SHLWAPI.391]
3528 * See WNetGetLastErrorW.
3530 DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
3531 LPWSTR lpNameBuf, DWORD nNameBufSize)
3533 GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
3534 return pWNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
3537 /*************************************************************************
3538 * @ [SHLWAPI.401]
3540 * See PageSetupDlgW.
3542 BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
3544 GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
3545 return pPageSetupDlgW(pagedlg);
3548 /*************************************************************************
3549 * @ [SHLWAPI.402]
3551 * See PrintDlgW.
3553 BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
3555 GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
3556 return pPrintDlgW(printdlg);
3559 /*************************************************************************
3560 * @ [SHLWAPI.403]
3562 * See GetOpenFileNameW.
3564 BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
3566 GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
3567 return pGetOpenFileNameW(ofn);
3570 /*************************************************************************
3571 * @ [SHLWAPI.404]
3573 HRESULT WINAPI IUnknown_EnumObjects(LPSHELLFOLDER lpFolder, HWND hwnd, SHCONTF flags, IEnumIDList **ppenum)
3575 IPersist *persist;
3576 HRESULT hr;
3578 hr = IShellFolder_QueryInterface(lpFolder, &IID_IPersist, (LPVOID)&persist);
3579 if(SUCCEEDED(hr))
3581 CLSID clsid;
3582 hr = IPersist_GetClassID(persist, &clsid);
3583 if(SUCCEEDED(hr))
3585 if(IsEqualCLSID(&clsid, &CLSID_ShellFSFolder))
3586 hr = IShellFolder_EnumObjects(lpFolder, hwnd, flags, ppenum);
3587 else
3588 hr = E_FAIL;
3590 IPersist_Release(persist);
3592 return hr;
3595 /* INTERNAL: Map from HLS color space to RGB */
3596 static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
3598 wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
3600 if (wHue > 160)
3601 return wMid1;
3602 else if (wHue > 120)
3603 wHue = 160 - wHue;
3604 else if (wHue > 40)
3605 return wMid2;
3607 return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
3610 /* Convert to RGB and scale into RGB range (0..255) */
3611 #define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
3613 /*************************************************************************
3614 * ColorHLSToRGB [SHLWAPI.@]
3616 * Convert from hls color space into an rgb COLORREF.
3618 * PARAMS
3619 * wHue [I] Hue amount
3620 * wLuminosity [I] Luminosity amount
3621 * wSaturation [I] Saturation amount
3623 * RETURNS
3624 * A COLORREF representing the converted color.
3626 * NOTES
3627 * Input hls values are constrained to the range (0..240).
3629 COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
3631 WORD wRed;
3633 if (wSaturation)
3635 WORD wGreen, wBlue, wMid1, wMid2;
3637 if (wLuminosity > 120)
3638 wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
3639 else
3640 wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
3642 wMid1 = wLuminosity * 2 - wMid2;
3644 wRed = GET_RGB(wHue + 80);
3645 wGreen = GET_RGB(wHue);
3646 wBlue = GET_RGB(wHue - 80);
3648 return RGB(wRed, wGreen, wBlue);
3651 wRed = wLuminosity * 255 / 240;
3652 return RGB(wRed, wRed, wRed);
3655 /*************************************************************************
3656 * @ [SHLWAPI.413]
3658 * Get the current docking status of the system.
3660 * PARAMS
3661 * dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
3663 * RETURNS
3664 * One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
3665 * a notebook.
3667 DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
3669 HW_PROFILE_INFOA hwInfo;
3671 TRACE("(0x%08lx)\n", dwFlags);
3673 GetCurrentHwProfileA(&hwInfo);
3674 switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
3676 case DOCKINFO_DOCKED:
3677 case DOCKINFO_UNDOCKED:
3678 return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
3679 default:
3680 return 0;
3684 /*************************************************************************
3685 * @ [SHLWAPI.418]
3687 * Function seems to do FreeLibrary plus other things.
3689 * FIXME native shows the following calls:
3690 * RtlEnterCriticalSection
3691 * LocalFree
3692 * GetProcAddress(Comctl32??, 150L)
3693 * DPA_DeletePtr
3694 * RtlLeaveCriticalSection
3695 * followed by the FreeLibrary.
3696 * The above code may be related to .377 above.
3698 BOOL WINAPI MLFreeLibrary(HMODULE hModule)
3700 FIXME("(%p) semi-stub\n", hModule);
3701 return FreeLibrary(hModule);
3704 /*************************************************************************
3705 * @ [SHLWAPI.419]
3707 BOOL WINAPI SHFlushSFCacheWrap(void) {
3708 FIXME(": stub\n");
3709 return TRUE;
3712 /*************************************************************************
3713 * @ [SHLWAPI.425]
3715 BOOL WINAPI DeleteMenuWrap(HMENU hmenu, UINT pos, UINT flags)
3717 /* FIXME: This should do more than simply call DeleteMenu */
3718 FIXME("%p %08x %08x): semi-stub\n", hmenu, pos, flags);
3719 return DeleteMenu(hmenu, pos, flags);
3722 /*************************************************************************
3723 * @ [SHLWAPI.429]
3724 * FIXME I have no idea what this function does or what its arguments are.
3726 BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
3728 FIXME("(%p) stub\n", hInst);
3729 return FALSE;
3733 /*************************************************************************
3734 * @ [SHLWAPI.430]
3736 DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
3738 FIXME("(%p,%p) stub\n", hInst, hHeap);
3739 return E_FAIL; /* This is what is used if shlwapi not loaded */
3742 /*************************************************************************
3743 * @ [SHLWAPI.431]
3745 DWORD WINAPI MLClearMLHInstance(DWORD x)
3747 FIXME("(0x%08lx)stub\n", x);
3748 return 0xabba1247;
3751 /*************************************************************************
3752 * @ [SHLWAPI.436]
3754 * Convert an Unicode string CLSID into a CLSID.
3756 * PARAMS
3757 * idstr [I] string containing a CLSID in text form
3758 * id [O] CLSID extracted from the string
3760 * RETURNS
3761 * S_OK on success or E_INVALIDARG on failure
3763 * NOTES
3764 * This is really CLSIDFromString() which is exported by ole32.dll,
3765 * however the native shlwapi.dll does *not* import ole32. Nor does
3766 * ole32.dll import this ordinal from shlwapi. Therefore we must conclude
3767 * that MS duplicated the code for CLSIDFromString(), and yes they did, only
3768 * it returns an E_INVALIDARG error code on failure.
3769 * This is a duplicate (with changes for Unicode) of CLSIDFromString16()
3770 * in "dlls/ole32/compobj.c".
3772 HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
3774 LPCWSTR s = idstr;
3775 BYTE *p;
3776 INT i;
3777 WCHAR table[256];
3779 if (!s) {
3780 memset(id, 0, sizeof(CLSID));
3781 return S_OK;
3783 else { /* validate the CLSID string */
3785 if (strlenW(s) != 38)
3786 return E_INVALIDARG;
3788 if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
3789 return E_INVALIDARG;
3791 for (i=1; i<37; i++)
3793 if ((i == 9)||(i == 14)||(i == 19)||(i == 24))
3794 continue;
3795 if (!(((s[i] >= L'0') && (s[i] <= L'9')) ||
3796 ((s[i] >= L'a') && (s[i] <= L'f')) ||
3797 ((s[i] >= L'A') && (s[i] <= L'F')))
3799 return E_INVALIDARG;
3803 TRACE("%s -> %p\n", debugstr_w(s), id);
3805 /* quick lookup table */
3806 memset(table, 0, 256*sizeof(WCHAR));
3808 for (i = 0; i < 10; i++) {
3809 table['0' + i] = i;
3811 for (i = 0; i < 6; i++) {
3812 table['A' + i] = i+10;
3813 table['a' + i] = i+10;
3816 /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
3818 p = (BYTE *) id;
3820 s++; /* skip leading brace */
3821 for (i = 0; i < 4; i++) {
3822 p[3 - i] = table[*s]<<4 | table[*(s+1)];
3823 s += 2;
3825 p += 4;
3826 s++; /* skip - */
3828 for (i = 0; i < 2; i++) {
3829 p[1-i] = table[*s]<<4 | table[*(s+1)];
3830 s += 2;
3832 p += 2;
3833 s++; /* skip - */
3835 for (i = 0; i < 2; i++) {
3836 p[1-i] = table[*s]<<4 | table[*(s+1)];
3837 s += 2;
3839 p += 2;
3840 s++; /* skip - */
3842 /* these are just sequential bytes */
3843 for (i = 0; i < 2; i++) {
3844 *p++ = table[*s]<<4 | table[*(s+1)];
3845 s += 2;
3847 s++; /* skip - */
3849 for (i = 0; i < 6; i++) {
3850 *p++ = table[*s]<<4 | table[*(s+1)];
3851 s += 2;
3854 return S_OK;
3857 /*************************************************************************
3858 * @ [SHLWAPI.437]
3860 * Determine if the OS supports a given feature.
3862 * PARAMS
3863 * dwFeature [I] Feature requested (undocumented)
3865 * RETURNS
3866 * TRUE If the feature is available.
3867 * FALSE If the feature is not available.
3869 BOOL WINAPI IsOS(DWORD feature)
3871 OSVERSIONINFOA osvi;
3872 DWORD platform, majorv, minorv;
3874 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
3875 if(!GetVersionExA(&osvi)) {
3876 ERR("GetVersionEx failed");
3877 return FALSE;
3880 majorv = osvi.dwMajorVersion;
3881 minorv = osvi.dwMinorVersion;
3882 platform = osvi.dwPlatformId;
3884 #define ISOS_RETURN(x) \
3885 TRACE("(0x%lx) ret=%d\n",feature,(x)); \
3886 return (x);
3888 switch(feature) {
3889 case OS_WIN32SORGREATER:
3890 ISOS_RETURN(platform == VER_PLATFORM_WIN32s
3891 || platform == VER_PLATFORM_WIN32_WINDOWS)
3892 case OS_NT:
3893 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3894 case OS_WIN95ORGREATER:
3895 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
3896 case OS_NT4ORGREATER:
3897 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
3898 case OS_WIN2000ORGREATER_ALT:
3899 case OS_WIN2000ORGREATER:
3900 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3901 case OS_WIN98ORGREATER:
3902 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
3903 case OS_WIN98_GOLD:
3904 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
3905 case OS_WIN2000PRO:
3906 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3907 case OS_WIN2000SERVER:
3908 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3909 case OS_WIN2000ADVSERVER:
3910 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3911 case OS_WIN2000DATACENTER:
3912 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3913 case OS_WIN2000TERMINAL:
3914 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
3915 case OS_EMBEDDED:
3916 FIXME("(OS_EMBEDDED) What should we return here?\n");
3917 return FALSE;
3918 case OS_TERMINALCLIENT:
3919 FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
3920 return FALSE;
3921 case OS_TERMINALREMOTEADMIN:
3922 FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
3923 return FALSE;
3924 case OS_WIN95_GOLD:
3925 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
3926 case OS_MEORGREATER:
3927 ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
3928 case OS_XPORGREATER:
3929 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3930 case OS_HOME:
3931 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
3932 case OS_PROFESSIONAL:
3933 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3934 case OS_DATACENTER:
3935 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3936 case OS_ADVSERVER:
3937 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
3938 case OS_SERVER:
3939 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3940 case OS_TERMINALSERVER:
3941 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3942 case OS_PERSONALTERMINALSERVER:
3943 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
3944 case OS_FASTUSERSWITCHING:
3945 FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
3946 return TRUE;
3947 case OS_WELCOMELOGONUI:
3948 FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
3949 return FALSE;
3950 case OS_DOMAINMEMBER:
3951 FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
3952 return TRUE;
3953 case OS_ANYSERVER:
3954 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3955 case OS_WOW6432:
3956 FIXME("(OS_WOW6432) Should we check this?\n");
3957 return FALSE;
3958 case OS_WEBSERVER:
3959 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3960 case OS_SMALLBUSINESSSERVER:
3961 ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
3962 case OS_TABLETPC:
3963 FIXME("(OS_TABLEPC) What should we return here?\n");
3964 return FALSE;
3965 case OS_SERVERADMINUI:
3966 FIXME("(OS_SERVERADMINUI) What should we return here?\n");
3967 return FALSE;
3968 case OS_MEDIACENTER:
3969 FIXME("(OS_MEDIACENTER) What should we return here?\n");
3970 return FALSE;
3971 case OS_APPLIANCE:
3972 FIXME("(OS_APPLIANCE) What should we return here?\n");
3973 return FALSE;
3976 #undef ISOS_RETURN
3978 WARN("(0x%lx) unknown parameter\n",feature);
3980 return FALSE;
3983 /*************************************************************************
3984 * @ [SHLWAPI.439]
3986 HRESULT WINAPI SHLoadRegUIStringW(HKEY hkey, LPCWSTR value, LPWSTR buf, DWORD size)
3988 DWORD type, sz = size;
3990 if(RegQueryValueExW(hkey, value, NULL, &type, (LPBYTE)buf, &sz) != ERROR_SUCCESS)
3991 return E_FAIL;
3993 return SHLoadIndirectString(buf, buf, size, NULL);
3996 /*************************************************************************
3997 * @ [SHLWAPI.478]
3999 * Call IInputObject_TranslateAcceleratorIO() on an object.
4001 * PARAMS
4002 * lpUnknown [I] Object supporting the IInputObject interface.
4003 * lpMsg [I] Key message to be processed.
4005 * RETURNS
4006 * Success: S_OK.
4007 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4009 HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
4011 IInputObject* lpInput = NULL;
4012 HRESULT hRet = E_INVALIDARG;
4014 TRACE("(%p,%p)\n", lpUnknown, lpMsg);
4015 if (lpUnknown)
4017 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4018 (void**)&lpInput);
4019 if (SUCCEEDED(hRet) && lpInput)
4021 hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
4022 IInputObject_Release(lpInput);
4025 return hRet;
4028 /*************************************************************************
4029 * @ [SHLWAPI.481]
4031 * Call IInputObject_HasFocusIO() on an object.
4033 * PARAMS
4034 * lpUnknown [I] Object supporting the IInputObject interface.
4036 * RETURNS
4037 * Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
4038 * or S_FALSE otherwise.
4039 * Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
4041 HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
4043 IInputObject* lpInput = NULL;
4044 HRESULT hRet = E_INVALIDARG;
4046 TRACE("(%p)\n", lpUnknown);
4047 if (lpUnknown)
4049 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
4050 (void**)&lpInput);
4051 if (SUCCEEDED(hRet) && lpInput)
4053 hRet = IInputObject_HasFocusIO(lpInput);
4054 IInputObject_Release(lpInput);
4057 return hRet;
4060 /*************************************************************************
4061 * ColorRGBToHLS [SHLWAPI.@]
4063 * Convert an rgb COLORREF into the hls color space.
4065 * PARAMS
4066 * cRGB [I] Source rgb value
4067 * pwHue [O] Destination for converted hue
4068 * pwLuminance [O] Destination for converted luminance
4069 * pwSaturation [O] Destination for converted saturation
4071 * RETURNS
4072 * Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
4073 * values.
4075 * NOTES
4076 * Output HLS values are constrained to the range (0..240).
4077 * For Achromatic conversions, Hue is set to 160.
4079 VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
4080 LPWORD pwLuminance, LPWORD pwSaturation)
4082 int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
4084 TRACE("(%08lx,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
4086 wR = GetRValue(cRGB);
4087 wG = GetGValue(cRGB);
4088 wB = GetBValue(cRGB);
4090 wMax = max(wR, max(wG, wB));
4091 wMin = min(wR, min(wG, wB));
4093 /* Luminosity */
4094 wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
4096 if (wMax == wMin)
4098 /* Achromatic case */
4099 wSaturation = 0;
4100 /* Hue is now unrepresentable, but this is what native returns... */
4101 wHue = 160;
4103 else
4105 /* Chromatic case */
4106 int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
4108 /* Saturation */
4109 if (wLuminosity <= 120)
4110 wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
4111 else
4112 wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
4114 /* Hue */
4115 wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
4116 wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
4117 wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
4119 if (wR == wMax)
4120 wHue = wBNorm - wGNorm;
4121 else if (wG == wMax)
4122 wHue = 80 + wRNorm - wBNorm;
4123 else
4124 wHue = 160 + wGNorm - wRNorm;
4125 if (wHue < 0)
4126 wHue += 240;
4127 else if (wHue > 240)
4128 wHue -= 240;
4130 if (pwHue)
4131 *pwHue = wHue;
4132 if (pwLuminance)
4133 *pwLuminance = wLuminosity;
4134 if (pwSaturation)
4135 *pwSaturation = wSaturation;
4138 /*************************************************************************
4139 * SHCreateShellPalette [SHLWAPI.@]
4141 HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
4143 FIXME("stub\n");
4144 return CreateHalftonePalette(hdc);
4147 /*************************************************************************
4148 * SHGetInverseCMAP (SHLWAPI.@)
4150 * Get an inverse color map table.
4152 * PARAMS
4153 * lpCmap [O] Destination for color map
4154 * dwSize [I] Size of memory pointed to by lpCmap
4156 * RETURNS
4157 * Success: S_OK.
4158 * Failure: E_POINTER, If lpCmap is invalid.
4159 * E_INVALIDARG, If dwFlags is invalid
4160 * E_OUTOFMEMORY, If there is no memory available
4162 * NOTES
4163 * dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
4164 * If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
4165 * internal CMap.
4166 * If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
4167 * this DLL's internal CMap.
4169 HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
4171 if (dwSize == 4) {
4172 FIXME(" - returning bogus address for SHGetInverseCMAP\n");
4173 *dest = (DWORD)0xabba1249;
4174 return 0;
4176 FIXME("(%p, %#lx) stub\n", dest, dwSize);
4177 return 0;
4180 /*************************************************************************
4181 * SHIsLowMemoryMachine [SHLWAPI.@]
4183 * Determine if the current computer has low memory.
4185 * PARAMS
4186 * x [I] FIXME
4188 * RETURNS
4189 * TRUE if the users machine has 16 Megabytes of memory or less,
4190 * FALSE otherwise.
4192 BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
4194 FIXME("(0x%08lx) stub\n", x);
4195 return FALSE;
4198 /*************************************************************************
4199 * GetMenuPosFromID [SHLWAPI.@]
4201 * Return the position of a menu item from its Id.
4203 * PARAMS
4204 * hMenu [I] Menu containing the item
4205 * wID [I] Id of the menu item
4207 * RETURNS
4208 * Success: The index of the menu item in hMenu.
4209 * Failure: -1, If the item is not found.
4211 INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
4213 MENUITEMINFOW mi;
4214 INT nCount = GetMenuItemCount(hMenu), nIter = 0;
4216 while (nIter < nCount)
4218 mi.cbSize = sizeof(mi);
4219 mi.fMask = MIIM_ID;
4220 if (GetMenuItemInfoW(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
4221 return nIter;
4222 nIter++;
4224 return -1;
4227 /*************************************************************************
4228 * @ [SHLWAPI.179]
4230 * Same as SHLWAPI.GetMenuPosFromID
4232 DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
4234 return GetMenuPosFromID(hMenu, uID);
4238 /*************************************************************************
4239 * @ [SHLWAPI.448]
4241 VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
4243 while (*lpwstr)
4245 if (*lpwstr == '/')
4246 *lpwstr = '\\';
4247 lpwstr++;
4252 /*************************************************************************
4253 * @ [SHLWAPI.461]
4255 DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
4257 FIXME("(0x%08lx) stub\n", dwUnknown);
4258 return 0;
4262 /*************************************************************************
4263 * @ [SHLWAPI.549]
4265 HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
4266 DWORD dwClsContext, REFIID iid, LPVOID *ppv)
4268 return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
4271 /*************************************************************************
4272 * SHSkipJunction [SHLWAPI.@]
4274 * Determine if a bind context can be bound to an object
4276 * PARAMS
4277 * pbc [I] Bind context to check
4278 * pclsid [I] CLSID of object to be bound to
4280 * RETURNS
4281 * TRUE: If it is safe to bind
4282 * FALSE: If pbc is invalid or binding would not be safe
4285 BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
4287 static const WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
4288 'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
4289 BOOL bRet = FALSE;
4291 if (pbc)
4293 IUnknown* lpUnk;
4295 if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)szSkipBinding, &lpUnk)))
4297 CLSID clsid;
4299 if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
4300 IsEqualGUID(pclsid, &clsid))
4301 bRet = TRUE;
4303 IUnknown_Release(lpUnk);
4306 return bRet;
4309 /***********************************************************************
4310 * SHGetShellKey (SHLWAPI.@)
4312 DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
4314 FIXME("(%lx, %lx, %lx): stub\n", a, b, c);
4315 return 0x50;
4318 /***********************************************************************
4319 * SHQueueUserWorkItem (SHLWAPI.@)
4321 HRESULT WINAPI SHQueueUserWorkItem(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f, DWORD g)
4323 FIXME("(%lx, %lx, %lx, %lx, %lx, %lx, %lx): stub\n", a, b, c, d, e, f, g);
4324 return E_FAIL;
4327 /***********************************************************************
4328 * IUnknown_OnFocusChangeIS (SHLWAPI.@)
4330 HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
4332 IInputObjectSite *pIOS = NULL;
4333 HRESULT hRet = E_INVALIDARG;
4335 TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
4337 if (lpUnknown)
4339 hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
4340 (void **)&pIOS);
4341 if (SUCCEEDED(hRet) && pIOS)
4343 hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
4344 IInputObjectSite_Release(pIOS);
4347 return hRet;
4350 /***********************************************************************
4351 * SHGetValueW (SHLWAPI.@)
4353 HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
4355 FIXME("(%lx, %s, %s, %lx, %lx, %lx): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
4356 return E_FAIL;
4359 typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
4361 /***********************************************************************
4362 * GetUIVersion (SHLWAPI.452)
4364 DWORD WINAPI GetUIVersion(void)
4366 static DWORD version;
4368 if (!version)
4370 DllGetVersion_func pDllGetVersion;
4371 HMODULE dll = LoadLibraryA("shell32.dll");
4372 if (!dll) return 0;
4374 pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
4375 if (pDllGetVersion)
4377 DLLVERSIONINFO dvi;
4378 dvi.cbSize = sizeof(DLLVERSIONINFO);
4379 if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
4381 FreeLibrary( dll );
4382 if (!version) version = 3; /* old shell dlls don't have DllGetVersion */
4384 return version;
4387 /***********************************************************************
4388 * ShellMessageBoxWrapW [SHLWAPI.388]
4390 * loads a string resource for a module, displays the string in a
4391 * message box and writes it into the logfile
4393 * PARAMS
4394 * mod [I] the module containing the string resource
4395 * unknown1 [I] FIXME
4396 * uId [I] the id of the string resource
4397 * title [I] the title of the message box
4398 * unknown2 [I] FIXME
4399 * filename [I] name of the logfile
4401 * RETURNS
4402 * FIXME
4404 BOOL WINAPI ShellMessageBoxWrapW(HMODULE mod, DWORD unknown1, UINT uId,
4405 LPCWSTR title, DWORD unknown2, LPCWSTR filename)
4407 FIXME("%p %lx %d %s %lx %s\n",
4408 mod, unknown1, uId, debugstr_w(title), unknown2, debugstr_w(filename));
4409 return TRUE;
4412 HRESULT WINAPI IUnknown_QueryServiceExec(IUnknown *unk, REFIID service, REFIID clsid,
4413 DWORD x1, DWORD x2, DWORD x3, void **ppvOut)
4415 FIXME("%p %s %s %08lx %08lx %08lx %p\n", unk,
4416 debugstr_guid(service), debugstr_guid(clsid), x1, x2, x3, ppvOut);
4417 return E_NOTIMPL;
4420 HRESULT WINAPI IUnknown_ProfferService(IUnknown *unk, void *x0, void *x1, void *x2)
4422 FIXME("%p %p %p %p\n", unk, x0, x1, x2);
4423 return E_NOTIMPL;