Sync to Wine-20050725:
[reactos.git] / reactos / lib / shlwapi / ordinal.c
index 112c124..530b57c 100644 (file)
-/*\r
- * SHLWAPI ordinal functions\r
- *\r
- * Copyright 1997 Marcus Meissner\r
- *           1998 Jürgen Schmied\r
- *           2001-2003 Jon Griffiths\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
- */\r
-\r
-#define COM_NO_WINDOWS_H\r
-#include "config.h"\r
-#include "wine/port.h"\r
-\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-\r
-#define COBJMACROS\r
-#define NONAMELESSUNION\r
-#define NONAMELESSSTRUCT\r
-\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "winuser.h"\r
-#include "winnls.h"\r
-#include "objbase.h"\r
-#include "docobj.h"\r
-#include "exdisp.h"\r
-#include "shlguid.h"\r
-#include "wingdi.h"\r
-#include "shlobj.h"\r
-#include "shellapi.h"\r
-#include "commdlg.h"\r
-#include "wine/unicode.h"\r
-#include "winreg.h"\r
-#include "wine/debug.h"\r
-#include "shlwapi.h"\r
-\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(shell);\r
-\r
-/* Get a function pointer from a DLL handle */\r
-#define GET_FUNC(func, module, name, fail) \\r
-  do { \\r
-    if (!func) { \\r
-      if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \\r
-      func = (fn##func)GetProcAddress(SHLWAPI_h##module, name); \\r
-      if (!func) return fail; \\r
-    } \\r
-  } while (0)\r
-\r
-/* DLL handles for late bound calls */\r
-extern HINSTANCE shlwapi_hInstance;\r
-extern HMODULE SHLWAPI_hshell32;\r
-extern HMODULE SHLWAPI_hwinmm;\r
-extern HMODULE SHLWAPI_hcomdlg32;\r
-extern HMODULE SHLWAPI_hcomctl32;\r
-extern HMODULE SHLWAPI_hmpr;\r
-extern HMODULE SHLWAPI_hurlmon;\r
-extern HMODULE SHLWAPI_hversion;\r
-\r
-extern DWORD SHLWAPI_ThreadRef_index;\r
-\r
-/* following is GUID for IObjectWithSite::SetSite  -- see _174           */\r
-static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};\r
-/* following is GUID for IPersistMoniker::GetClassID  -- see _174        */\r
-static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};\r
-\r
-/* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */\r
-typedef LPITEMIDLIST (WINAPI *fnpSHBrowseForFolderW)(LPBROWSEINFOW);\r
-static  fnpSHBrowseForFolderW pSHBrowseForFolderW;\r
-typedef BOOL    (WINAPI *fnpPlaySoundW)(LPCWSTR, HMODULE, DWORD);\r
-static  fnpPlaySoundW pPlaySoundW;\r
-typedef DWORD   (WINAPI *fnpSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);\r
-static  fnpSHGetFileInfoW pSHGetFileInfoW;\r
-typedef UINT    (WINAPI *fnpDragQueryFileW)(HDROP, UINT, LPWSTR, UINT);\r
-static  fnpDragQueryFileW pDragQueryFileW;\r
-typedef BOOL    (WINAPI *fnpSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR);\r
-static  fnpSHGetPathFromIDListW pSHGetPathFromIDListW;\r
-typedef BOOL    (WINAPI *fnpShellExecuteExW)(LPSHELLEXECUTEINFOW);\r
-static  fnpShellExecuteExW pShellExecuteExW;\r
-typedef HICON   (WINAPI *fnpSHFileOperationW)(LPSHFILEOPSTRUCTW);\r
-static  fnpSHFileOperationW pSHFileOperationW;\r
-typedef UINT    (WINAPI *fnpExtractIconExW)(LPCWSTR, INT,HICON *,HICON *, UINT);\r
-static  fnpExtractIconExW pExtractIconExW;\r
-typedef BOOL    (WINAPI *fnpSHGetNewLinkInfoW)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT);\r
-static  fnpSHGetNewLinkInfoW pSHGetNewLinkInfoW;\r
-typedef HRESULT (WINAPI *fnpSHDefExtractIconW)(LPCWSTR, int, UINT, HICON*, HICON*, UINT);\r
-static  fnpSHDefExtractIconW pSHDefExtractIconW;\r
-typedef HICON   (WINAPI *fnpExtractIconW)(HINSTANCE, LPCWSTR, UINT);\r
-static  fnpExtractIconW pExtractIconW;\r
-typedef BOOL    (WINAPI *fnpGetSaveFileNameW)(LPOPENFILENAMEW);\r
-static  fnpGetSaveFileNameW pGetSaveFileNameW;\r
-typedef DWORD   (WINAPI *fnpWNetRestoreConnectionW)(HWND, LPWSTR);\r
-static  fnpWNetRestoreConnectionW pWNetRestoreConnectionW;\r
-typedef DWORD   (WINAPI *fnpWNetGetLastErrorW)(LPDWORD, LPWSTR, DWORD, LPWSTR, DWORD);\r
-static  fnpWNetGetLastErrorW pWNetGetLastErrorW;\r
-typedef BOOL    (WINAPI *fnpPageSetupDlgW)(LPPAGESETUPDLGW);\r
-static  fnpPageSetupDlgW pPageSetupDlgW;\r
-typedef BOOL    (WINAPI *fnpPrintDlgW)(LPPRINTDLGW);\r
-static  fnpPrintDlgW pPrintDlgW;\r
-typedef BOOL    (WINAPI *fnpGetOpenFileNameW)(LPOPENFILENAMEW);\r
-static  fnpGetOpenFileNameW pGetOpenFileNameW;\r
-typedef DWORD   (WINAPI *fnpGetFileVersionInfoSizeW)(LPCWSTR,LPDWORD);\r
-static  fnpGetFileVersionInfoSizeW pGetFileVersionInfoSizeW;\r
-typedef BOOL    (WINAPI *fnpGetFileVersionInfoW)(LPCWSTR,DWORD,DWORD,LPVOID);\r
-static  fnpGetFileVersionInfoW pGetFileVersionInfoW;\r
-typedef WORD    (WINAPI *fnpVerQueryValueW)(LPVOID,LPCWSTR,LPVOID*,UINT*);\r
-static  fnpVerQueryValueW pVerQueryValueW;\r
-typedef BOOL    (WINAPI *fnpCOMCTL32_417)(HDC,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);\r
-static  fnpCOMCTL32_417 pCOMCTL32_417;\r
-typedef HRESULT (WINAPI *fnpDllGetVersion)(DLLVERSIONINFO*);\r
-static  fnpDllGetVersion pDllGetVersion;\r
-typedef HRESULT (WINAPI *fnpCreateFormatEnumerator)(UINT,FORMATETC*,IEnumFORMATETC**);\r
-static fnpCreateFormatEnumerator pCreateFormatEnumerator;\r
-typedef HRESULT (WINAPI *fnpRegisterFormatEnumerator)(LPBC,IEnumFORMATETC*,DWORD);\r
-static fnpRegisterFormatEnumerator pRegisterFormatEnumerator;\r
-\r
-HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);\r
-HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);\r
-HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR,CLSID*);\r
-BOOL    WINAPI SHAboutInfoW(LPWSTR,DWORD);\r
-\r
-/*\r
- NOTES: Most functions exported by ordinal seem to be superflous.\r
- The reason for these functions to be there is to provide a wrapper\r
- for unicode functions to provide these functions on systems without\r
- unicode functions eg. win95/win98. Since we have such functions we just\r
- call these. If running Wine with native DLL's, some late bound calls may\r
- fail. However, it is better to implement the functions in the forward DLL\r
- and recommend the builtin rather than reimplementing the calls here!\r
-*/\r
-\r
-/*************************************************************************\r
- * SHLWAPI_DupSharedHandle\r
- *\r
- * Internal implemetation of SHLWAPI_11.\r
- */\r
-static\r
-HANDLE WINAPI SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,\r
-                                       DWORD dwSrcProcId, DWORD dwAccess,\r
-                                       DWORD dwOptions)\r
-{\r
-  HANDLE hDst, hSrc;\r
-  DWORD dwMyProcId = GetCurrentProcessId();\r
-  HANDLE hRet = NULL;\r
-\r
-  TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", hShared, dwDstProcId, dwSrcProcId,\r
-        dwAccess, dwOptions);\r
-\r
-  /* Get dest process handle */\r
-  if (dwDstProcId == dwMyProcId)\r
-    hDst = GetCurrentProcess();\r
-  else\r
-    hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);\r
-\r
-  if (hDst)\r
-  {\r
-    /* Get src process handle */\r
-    if (dwSrcProcId == dwMyProcId)\r
-      hSrc = GetCurrentProcess();\r
-    else\r
-      hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);\r
-\r
-    if (hSrc)\r
-    {\r
-      /* Make handle available to dest process */\r
-      if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,\r
-                           dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))\r
-        hRet = NULL;\r
-\r
-      if (dwSrcProcId != dwMyProcId)\r
-        CloseHandle(hSrc);\r
-    }\r
-\r
-    if (dwDstProcId != dwMyProcId)\r
-      CloseHandle(hDst);\r
-  }\r
-\r
-  TRACE("Returning handle %p\n", hRet);\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- * @  [SHLWAPI.7]\r
- *\r
- * Create a block of sharable memory and initialise it with data.\r
- *\r
- * PARAMS\r
- * lpvData  [I] Pointer to data to write\r
- * dwSize   [I] Size of data\r
- * dwProcId [I] ID of process owning data\r
- *\r
- * RETURNS\r
- * Success: A shared memory handle\r
- * Failure: NULL\r
- *\r
- * NOTES\r
- * Ordinals 7-11 provide a set of calls to create shared memory between a\r
- * group of processes. The shared memory is treated opaquely in that its size\r
- * is not exposed to clients who map it. This is accomplished by storing\r
- * the size of the map as the first DWORD of mapped data, and then offsetting\r
- * the view pointer returned by this size.\r
- *\r
- */\r
-HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)\r
-{\r
-  HANDLE hMap;\r
-  LPVOID pMapped;\r
-  HANDLE hRet = NULL;\r
-\r
-  TRACE("(%p,%ld,%ld)\n", lpvData, dwSize, dwProcId);\r
-\r
-  /* Create file mapping of the correct length */\r
-  hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,\r
-                            dwSize + sizeof(dwSize), NULL);\r
-  if (!hMap)\r
-    return hRet;\r
-\r
-  /* Get a view in our process address space */\r
-  pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);\r
-\r
-  if (pMapped)\r
-  {\r
-    /* Write size of data, followed by the data, to the view */\r
-    *((DWORD*)pMapped) = dwSize;\r
-    if (lpvData)\r
-      memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);\r
-\r
-    /* Release view. All further views mapped will be opaque */\r
-    UnmapViewOfFile(pMapped);\r
-    hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,\r
-                                   GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,\r
-                                   DUPLICATE_SAME_ACCESS);\r
-  }\r
-\r
-  CloseHandle(hMap);\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- * @ [SHLWAPI.8]\r
- *\r
- * Get a pointer to a block of shared memory from a shared memory handle.\r
- *\r
- * PARAMS\r
- * hShared  [I] Shared memory handle\r
- * dwProcId [I] ID of process owning hShared\r
- *\r
- * RETURNS\r
- * Success: A pointer to the shared memory\r
- * Failure: NULL\r
- *\r
- */\r
-PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)\r
-{\r
-  HANDLE hDup;\r
-  LPVOID pMapped;\r
-\r
-  TRACE("(%p %ld)\n", hShared, dwProcId);\r
-\r
-  /* Get handle to shared memory for current process */\r
-  hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),\r
-                                 FILE_MAP_ALL_ACCESS, 0);\r
-  /* Get View */\r
-  pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);\r
-  CloseHandle(hDup);\r
-\r
-  if (pMapped)\r
-    return (char *) pMapped + sizeof(DWORD); /* Hide size */\r
-  return NULL;\r
-}\r
-\r
-/*************************************************************************\r
- * @ [SHLWAPI.9]\r
- *\r
- * Release a pointer to a block of shared memory.\r
- *\r
- * PARAMS\r
- * lpView [I] Shared memory pointer\r
- *\r
- * RETURNS\r
- * Success: TRUE\r
- * Failure: FALSE\r
- *\r
- */\r
-BOOL WINAPI SHUnlockShared(LPVOID lpView)\r
-{\r
-  TRACE("(%p)\n", lpView);\r
-  return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */\r
-}\r
-\r
-/*************************************************************************\r
- * @ [SHLWAPI.10]\r
- *\r
- * Destroy a block of sharable memory.\r
- *\r
- * PARAMS\r
- * hShared  [I] Shared memory handle\r
- * dwProcId [I] ID of process owning hShared\r
- *\r
- * RETURNS\r
- * Success: TRUE\r
- * Failure: FALSE\r
- *\r
- */\r
-BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)\r
-{\r
-  HANDLE hClose;\r
-\r
-  TRACE("(%p %ld)\n", hShared, dwProcId);\r
-\r
-  /* Get a copy of the handle for our process, closing the source handle */\r
-  hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),\r
-                                   FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);\r
-  /* Close local copy */\r
-  return CloseHandle(hClose);\r
-}\r
-\r
-/*************************************************************************\r
- * @   [SHLWAPI.11]\r
- *\r
- * Copy a sharable memory handle from one process to another.\r
- *\r
- * PARAMS\r
- * hShared     [I] Shared memory handle to duplicate\r
- * dwDstProcId [I] ID of the process wanting the duplicated handle\r
- * dwSrcProcId [I] ID of the process owning hShared\r
- * dwAccess    [I] Desired DuplicateHandle() access\r
- * dwOptions   [I] Desired DuplicateHandle() options\r
- *\r
- * RETURNS\r
- * Success: A handle suitable for use by the dwDstProcId process.\r
- * Failure: A NULL handle.\r
- *\r
- */\r
-HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,\r
-                          DWORD dwAccess, DWORD dwOptions)\r
-{\r
-  HANDLE hRet;\r
-\r
-  hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,\r
-                                 dwAccess, dwOptions);\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.13]\r
- *\r
- * Create and register a clipboard enumerator for a web browser.\r
- *\r
- * PARAMS\r
- *  lpBC      [I] Binding context\r
- *  lpUnknown [I] An object exposing the IWebBrowserApp interface\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: An HRESULT error code.\r
- *\r
- * NOTES\r
- *  The enumerator is stored as a property of the web browser. If it does not\r
- *  yet exist, it is created and set before being registered.\r
- */\r
-HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)\r
-{\r
-  static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',\r
-      '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',\r
-      '0','A','A','0','0','4','A','E','8','3','7','}','\0' };\r
-  IEnumFORMATETC* pIEnumFormatEtc = NULL;\r
-  VARIANTARG var;\r
-  HRESULT hRet;\r
-  IWebBrowserApp* pBrowser = NULL;\r
-\r
-  TRACE("(%p, %p)\n", lpBC, lpUnknown);\r
-\r
-  /* Get An IWebBrowserApp interface from  lpUnknown */\r
-  hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);\r
-  if (FAILED(hRet) || !pBrowser)\r
-    return E_NOINTERFACE;\r
-\r
-  V_VT(&var) = VT_EMPTY;\r
-\r
-  /* The property we get is the browsers clipboard enumerator */\r
-  hRet = IWebBrowserApp_GetProperty(pBrowser, (BSTR)szProperty, &var);\r
-  if (FAILED(hRet))\r
-    return hRet;\r
-\r
-  if (V_VT(&var) == VT_EMPTY)\r
-  {\r
-    /* Iterate through accepted documents and RegisterClipBoardFormatA() them */\r
-    char szKeyBuff[128], szValueBuff[128];\r
-    DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;\r
-    FORMATETC* formatList, *format;\r
-    HKEY hDocs;\r
-\r
-    TRACE("Registering formats and creating IEnumFORMATETC instance\n");\r
-\r
-    if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"\r
-                     "Version\\Internet Settings\\Accepted Documents", &hDocs))\r
-      return E_FAIL;\r
-\r
-    /* Get count of values in key */\r
-    while (!dwRet)\r
-    {\r
-      dwKeySize = sizeof(szKeyBuff);\r
-      dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);\r
-      dwCount++;\r
-    }\r
-\r
-    dwNumValues = dwCount;\r
-\r
-    /* Note: dwCount = number of items + 1; The extra item is the end node */\r
-    format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));\r
-    if (!formatList)\r
-      return E_OUTOFMEMORY;\r
-\r
-    if (dwNumValues > 1)\r
-    {\r
-      dwRet = 0;\r
-      dwCount = 0;\r
-\r
-      dwNumValues--;\r
-\r
-      /* Register clipboard formats for the values and populate format list */\r
-      while(!dwRet && dwCount < dwNumValues)\r
-      {\r
-        dwKeySize = sizeof(szKeyBuff);\r
-        dwValueSize = sizeof(szValueBuff);\r
-        dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,\r
-                              (PBYTE)szValueBuff, &dwValueSize);\r
-        if (!dwRet)\r
-          return E_FAIL;\r
-\r
-        format->cfFormat = RegisterClipboardFormatA(szValueBuff);\r
-        format->ptd = NULL;\r
-        format->dwAspect = 1;\r
-        format->lindex = 4;\r
-        format->tymed = -1;\r
-\r
-        format++;\r
-        dwCount++;\r
-      }\r
-    }\r
-\r
-    /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */\r
-    format->cfFormat = 0;\r
-    format->ptd = NULL;\r
-    format->dwAspect = 1;\r
-    format->lindex = 4;\r
-    format->tymed = -1;\r
-\r
-    /* Create a clipboard enumerator */\r
-    GET_FUNC(pCreateFormatEnumerator, urlmon, "CreateFormatEnumerator", E_FAIL);\r
-    hRet = pCreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);\r
-\r
-    if (FAILED(hRet) || !pIEnumFormatEtc)\r
-      return hRet;\r
-\r
-    /* Set our enumerator as the browsers property */\r
-    V_VT(&var) = VT_UNKNOWN;\r
-    V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;\r
-\r
-    hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);\r
-    if (FAILED(hRet))\r
-    {\r
-       IEnumFORMATETC_Release(pIEnumFormatEtc);\r
-       goto RegisterDefaultAcceptHeaders_Exit;\r
-    }\r
-  }\r
-\r
-  if (V_VT(&var) == VT_UNKNOWN)\r
-  {\r
-    /* Our variant is holding the clipboard enumerator */\r
-    IUnknown* pIUnknown = V_UNKNOWN(&var);\r
-    IEnumFORMATETC* pClone = NULL;\r
-\r
-    TRACE("Retrieved IEnumFORMATETC property\n");\r
-\r
-    /* Get an IEnumFormatEtc interface from the variants value */\r
-    pIEnumFormatEtc = NULL;\r
-    hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,\r
-                                   (PVOID)&pIEnumFormatEtc);\r
-    if (!hRet && pIEnumFormatEtc)\r
-    {\r
-      /* Clone and register the enumerator */\r
-      hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);\r
-      if (!hRet && pClone)\r
-      {\r
-        GET_FUNC(pRegisterFormatEnumerator, urlmon, "RegisterFormatEnumerator", E_FAIL);\r
-        pRegisterFormatEnumerator(lpBC, pClone, 0);\r
-\r
-        IEnumFORMATETC_Release(pClone);\r
-      }\r
-\r
-      /* Release the IEnumFormatEtc interface */\r
-      IEnumFORMATETC_Release(pIUnknown);\r
-    }\r
-    IUnknown_Release(V_UNKNOWN(&var));\r
-  }\r
-\r
-RegisterDefaultAcceptHeaders_Exit:\r
-  IWebBrowserApp_Release(pBrowser);\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.15]\r
- *\r
- * Get Explorers "AcceptLanguage" setting.\r
- *\r
- * PARAMS\r
- *  langbuf [O] Destination for language string\r
- *  buflen  [I] Length of langbuf\r
- *          [0] Success: used length of langbuf\r
- *\r
- * RETURNS\r
- *  Success: S_OK.   langbuf is set to the language string found.\r
- *  Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer\r
- *           does not contain the setting.\r
- *           E_INVALIDARG, If the buffer is not big enough\r
- */\r
-HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)\r
-{\r
-    static const WCHAR szkeyW[] = {\r
-       'S','o','f','t','w','a','r','e','\\',\r
-       'M','i','c','r','o','s','o','f','t','\\',\r
-       'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',\r
-       'I','n','t','e','r','n','a','t','i','o','n','a','l',0};\r
-    static const WCHAR valueW[] = {\r
-       'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};\r
-    static const WCHAR enusW[] = {'e','n','-','u','s',0};\r
-    DWORD mystrlen, mytype;\r
-    HKEY mykey;\r
-    HRESULT retval;\r
-    LCID mylcid;\r
-    WCHAR *mystr;\r
-\r
-    if(!langbuf || !buflen || !*buflen)\r
-       return E_FAIL;\r
-\r
-    mystrlen = (*buflen > 20) ? *buflen : 20 ;\r
-    mystr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * mystrlen);\r
-    RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);\r
-    if(RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &mystrlen)) {\r
-        /* Did not find value */\r
-        mylcid = GetUserDefaultLCID();\r
-        /* somehow the mylcid translates into "en-us"\r
-         *  this is similar to "LOCALE_SABBREVLANGNAME"\r
-         *  which could be gotten via GetLocaleInfo.\r
-         *  The only problem is LOCALE_SABBREVLANGUAGE" is\r
-         *  a 3 char string (first 2 are country code and third is\r
-         *  letter for "sublanguage", which does not come close to\r
-         *  "en-us"\r
-         */\r
-        lstrcpyW(mystr, enusW);\r
-        mystrlen = lstrlenW(mystr);\r
-    } else {\r
-        /* handle returned string */\r
-        FIXME("missing code\n");\r
-    }\r
-    memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );\r
-\r
-    if(*buflen > strlenW(mystr)) {\r
-       *buflen = strlenW(mystr);\r
-       retval = S_OK;\r
-    } else {\r
-       *buflen = 0;\r
-       retval = E_INVALIDARG;\r
-       SetLastError(ERROR_INSUFFICIENT_BUFFER);\r
-    }\r
-    RegCloseKey(mykey);\r
-    HeapFree(GetProcessHeap(), 0, mystr);\r
-    return retval;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.14]\r
- *\r
- * Ascii version of GetAcceptLanguagesW.\r
- */\r
-HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)\r
-{\r
-    WCHAR *langbufW;\r
-    DWORD buflenW, convlen;\r
-    HRESULT retval;\r
-\r
-    if(!langbuf || !buflen || !*buflen) return E_FAIL;\r
-\r
-    buflenW = *buflen;\r
-    langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);\r
-    retval = GetAcceptLanguagesW(langbufW, &buflenW);\r
-\r
-    /* FIXME: this is wrong, the string may not be null-terminated */\r
-    convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf,\r
-                                  *buflen, NULL, NULL);\r
-    *buflen = buflenW ? convlen : 0;\r
-\r
-    HeapFree(GetProcessHeap(), 0, langbufW);\r
-    return retval;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.23]\r
- *\r
- * Convert a GUID to a string.\r
- *\r
- * PARAMS\r
- *  guid     [I] GUID to convert\r
- *  lpszDest [O] Destination for string\r
- *  cchMax   [I] Length of output buffer\r
- *\r
- * RETURNS\r
- *  The length of the string created.\r
- */\r
-INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)\r
-{\r
-  char xguid[40];\r
-  INT iLen;\r
-\r
-  TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);\r
-\r
-  sprintf(xguid, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",\r
-          guid->Data1, guid->Data2, guid->Data3,\r
-          guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],\r
-          guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);\r
-\r
-  iLen = strlen(xguid) + 1;\r
-\r
-  if (iLen > cchMax)\r
-    return 0;\r
-  memcpy(lpszDest, xguid, iLen);\r
-  return iLen;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.24]\r
- *\r
- * Convert a GUID to a string.\r
- *\r
- * PARAMS\r
- *  guid [I] GUID to convert\r
- *  str  [O] Destination for string\r
- *  cmax [I] Length of output buffer\r
- *\r
- * RETURNS\r
- *  The length of the string created.\r
- */\r
-INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)\r
-{\r
-  WCHAR xguid[40];\r
-  INT iLen;\r
-  static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',\r
-      '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',\r
-      'X','%','0','2','X','%','0','2','X','}',0};\r
-\r
-  TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);\r
-\r
-  sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,\r
-          guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],\r
-          guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);\r
-\r
-  iLen = strlenW(xguid) + 1;\r
-\r
-  if (iLen > cchMax)\r
-    return 0;\r
-  memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));\r
-  return iLen;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.29]\r
- *\r
- * Determine if a Unicode character is a space.\r
- *\r
- * PARAMS\r
- *  wc [I] Character to check.\r
- *\r
- * RETURNS\r
- *  TRUE, if wc is a space,\r
- *  FALSE otherwise.\r
- */\r
-BOOL WINAPI IsCharSpaceW(WCHAR wc)\r
-{\r
-    WORD CharType;\r
-\r
-    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.30]\r
- *\r
- * Determine if a Unicode character is a blank.\r
- *\r
- * PARAMS\r
- *  wc [I] Character to check.\r
- *\r
- * RETURNS\r
- *  TRUE, if wc is a blank,\r
- *  FALSE otherwise.\r
- *\r
- */\r
-BOOL WINAPI IsCharBlankW(WCHAR wc)\r
-{\r
-    WORD CharType;\r
-\r
-    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.31]\r
- *\r
- * Determine if a Unicode character is punctuation.\r
- *\r
- * PARAMS\r
- *  wc [I] Character to check.\r
- *\r
- * RETURNS\r
- *  TRUE, if wc is punctuation,\r
- *  FALSE otherwise.\r
- */\r
-BOOL WINAPI IsCharPunctW(WCHAR wc)\r
-{\r
-    WORD CharType;\r
-\r
-    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.32]\r
- *\r
- * Determine if a Unicode character is a control character.\r
- *\r
- * PARAMS\r
- *  wc [I] Character to check.\r
- *\r
- * RETURNS\r
- *  TRUE, if wc is a control character,\r
- *  FALSE otherwise.\r
- */\r
-BOOL WINAPI IsCharCntrlW(WCHAR wc)\r
-{\r
-    WORD CharType;\r
-\r
-    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.33]\r
- *\r
- * Determine if a Unicode character is a digit.\r
- *\r
- * PARAMS\r
- *  wc [I] Character to check.\r
- *\r
- * RETURNS\r
- *  TRUE, if wc is a digit,\r
- *  FALSE otherwise.\r
- */\r
-BOOL WINAPI IsCharDigitW(WCHAR wc)\r
-{\r
-    WORD CharType;\r
-\r
-    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.34]\r
- *\r
- * Determine if a Unicode character is a hex digit.\r
- *\r
- * PARAMS\r
- *  wc [I] Character to check.\r
- *\r
- * RETURNS\r
- *  TRUE, if wc is a hex digit,\r
- *  FALSE otherwise.\r
- */\r
-BOOL WINAPI IsCharXDigitW(WCHAR wc)\r
-{\r
-    WORD CharType;\r
-\r
-    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.35]\r
- *\r
- */\r
-BOOL WINAPI GetStringType3ExW(LPWSTR lpszStr, DWORD dwLen, LPVOID p3)\r
-{\r
-    FIXME("(%s,0x%08lx,%p): stub\n", debugstr_w(lpszStr), dwLen, p3);\r
-    return TRUE;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.36]\r
- *\r
- * Insert a bitmap menu item at the bottom of a menu.\r
- *\r
- * PARAMS\r
- *  hMenu [I] Menu to insert into\r
- *  flags [I] Flags for insertion\r
- *  id    [I] Menu ID of the item\r
- *  str   [I] Menu text for the item\r
- *\r
- * RETURNS\r
- *  Success: TRUE,  the item is inserted into the menu\r
- *  Failure: FALSE, if any parameter is invalid\r
- */\r
-BOOL WINAPI AppendMenuWrapW(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)\r
-{\r
-    TRACE("(%p,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));\r
-    return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.74]\r
- *\r
- * Get the text from a given dialog item.\r
- *\r
- * PARAMS\r
- *  hWnd     [I] Handle of dialog\r
- *  nItem    [I] Index of item\r
- *  lpsDest  [O] Buffer for receiving window text\r
- *  nDestLen [I] Length of buffer.\r
- *\r
- * RETURNS\r
- *  Success: The length of the returned text.\r
- *  Failure: 0.\r
- */\r
-INT WINAPI GetDlgItemTextWrapW(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)\r
-{\r
-  HWND hItem = GetDlgItem(hWnd, nItem);\r
-\r
-  if (hItem)\r
-    return GetWindowTextW(hItem, lpsDest, nDestLen);\r
-  if (nDestLen)\r
-    *lpsDest = (WCHAR)'\0';\r
-  return 0;\r
-}\r
-\r
-/*************************************************************************\r
- *      @   [SHLWAPI.138]\r
- *\r
- * Set the text of a given dialog item.\r
- *\r
- * PARAMS\r
- *  hWnd     [I] Handle of dialog\r
- *  iItem    [I] Index of item\r
- *  lpszText [O] Text to set\r
- *\r
- * RETURNS\r
- *  Success: TRUE.  The text of the dialog is set to lpszText.\r
- *  Failure: FALSE, Otherwise.\r
- */\r
-BOOL WINAPI SetDlgItemTextWrapW(HWND hWnd, INT iItem, LPCWSTR lpszText)\r
-{\r
-    HWND hWndItem = GetDlgItem(hWnd, iItem);\r
-    if (hWndItem)\r
-        return SetWindowTextW(hWndItem, lpszText);\r
-    return FALSE;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.151]\r
- *\r
- * Compare two Ascii strings up to a given length.\r
- *\r
- * PARAMS\r
- *  lpszSrc [I] Source string\r
- *  lpszCmp [I] String to compare to lpszSrc\r
- *  len     [I] Maximum length\r
- *\r
- * RETURNS\r
- *  A number greater than, less than or equal to 0 depending on whether\r
- *  lpszSrc is greater than, less than or equal to lpszCmp.\r
- */\r
-DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)\r
-{\r
-    return strncmp(lpszSrc, lpszCmp, len);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.152]\r
- *\r
- * Unicode version of StrCmpNCA.\r
- */\r
-DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)\r
-{\r
-    return strncmpW(lpszSrc, lpszCmp, len);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.153]\r
- *\r
- * Compare two Ascii strings up to a given length, ignoring case.\r
- *\r
- * PARAMS\r
- *  lpszSrc [I] Source string\r
- *  lpszCmp [I] String to compare to lpszSrc\r
- *  len     [I] Maximum length\r
- *\r
- * RETURNS\r
- *  A number greater than, less than or equal to 0 depending on whether\r
- *  lpszSrc is greater than, less than or equal to lpszCmp.\r
- */\r
-DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)\r
-{\r
-    return strncasecmp(lpszSrc, lpszCmp, len);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.154]\r
- *\r
- * Unicode version of StrCmpNICA.\r
- */\r
-DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)\r
-{\r
-    return strncmpiW(lpszSrc, lpszCmp, len);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.155]\r
- *\r
- * Compare two Ascii strings.\r
- *\r
- * PARAMS\r
- *  lpszSrc [I] Source string\r
- *  lpszCmp [I] String to compare to lpszSrc\r
- *\r
- * RETURNS\r
- *  A number greater than, less than or equal to 0 depending on whether\r
- *  lpszSrc is greater than, less than or equal to lpszCmp.\r
- */\r
-DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)\r
-{\r
-    return strcmp(lpszSrc, lpszCmp);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.156]\r
- *\r
- * Unicode version of StrCmpCA.\r
- */\r
-DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)\r
-{\r
-    return strcmpW(lpszSrc, lpszCmp);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.157]\r
- *\r
- * Compare two Ascii strings, ignoring case.\r
- *\r
- * PARAMS\r
- *  lpszSrc [I] Source string\r
- *  lpszCmp [I] String to compare to lpszSrc\r
- *\r
- * RETURNS\r
- *  A number greater than, less than or equal to 0 depending on whether\r
- *  lpszSrc is greater than, less than or equal to lpszCmp.\r
- */\r
-DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)\r
-{\r
-    return strcasecmp(lpszSrc, lpszCmp);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.158]\r
- *\r
- * Unicode version of StrCmpICA.\r
- */\r
-DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)\r
-{\r
-    return strcmpiW(lpszSrc, lpszCmp);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.160]\r
- *\r
- * Get an identification string for the OS and explorer.\r
- *\r
- * PARAMS\r
- *  lpszDest  [O] Destination for Id string\r
- *  dwDestLen [I] Length of lpszDest\r
- *\r
- * RETURNS\r
- *  TRUE,  If the string was created successfully\r
- *  FALSE, Otherwise\r
- */\r
-BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)\r
-{\r
-  WCHAR buff[2084];\r
-\r
-  TRACE("(%p,%ld)\n", lpszDest, dwDestLen);\r
-\r
-  if (lpszDest && SHAboutInfoW(buff, dwDestLen))\r
-  {\r
-    WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);\r
-    return TRUE;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.161]\r
- *\r
- * Unicode version of SHAboutInfoA.\r
- */\r
-BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)\r
-{\r
-  static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',\r
-    'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',\r
-    ' ','E','x','p','l','o','r','e','r','\0' };\r
-  static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',\r
-    'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',\r
-    'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };\r
-  static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',\r
-    'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',\r
-    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };\r
-  static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',\r
-    'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',\r
-    ' ','E','x','p','l','o','r','e','r','\\',\r
-    'R','e','g','i','s','t','r','a','t','i','o','n','\0' };\r
-  static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };\r
-  static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',\r
-    'V','e','r','s','i','o','n','\0' };\r
-  static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',\r
-    'O','w','n','e','r','\0' };\r
-  static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',\r
-    'O','r','g','a','n','i','z','a','t','i','o','n','\0' };\r
-  static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };\r
-  static const WCHAR szUpdate[] = { 'I','E','A','K',\r
-    'U','p','d','a','t','e','U','r','l','\0' };\r
-  static const WCHAR szHelp[] = { 'I','E','A','K',\r
-    'H','e','l','p','S','t','r','i','n','g','\0' };\r
-  WCHAR buff[2084];\r
-  HKEY hReg;\r
-  DWORD dwType, dwLen;\r
-\r
-  TRACE("(%p,%ld)\n", lpszDest, dwDestLen);\r
-\r
-  if (!lpszDest)\r
-    return FALSE;\r
-\r
-  *lpszDest = '\0';\r
-\r
-  /* Try the NT key first, followed by 95/98 key */\r
-  if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&\r
-      RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))\r
-    return FALSE;\r
-\r
-  /* OS Version */\r
-  buff[0] = '\0';\r
-  dwLen = 30;\r
-  if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))\r
-  {\r
-    DWORD dwStrLen = strlenW(buff);\r
-    dwLen = 30 - dwStrLen;\r
-    SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,\r
-                szCustomized, &dwType, buff+dwStrLen, &dwLen);\r
-  }\r
-  StrCatBuffW(lpszDest, buff, dwDestLen);\r
-\r
-  /* ~Registered Owner */\r
-  buff[0] = '~';\r
-  dwLen = 256;\r
-  if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))\r
-    buff[1] = '\0';\r
-  StrCatBuffW(lpszDest, buff, dwDestLen);\r
-\r
-  /* ~Registered Organization */\r
-  dwLen = 256;\r
-  if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))\r
-    buff[1] = '\0';\r
-  StrCatBuffW(lpszDest, buff, dwDestLen);\r
-\r
-  /* FIXME: Not sure where this number comes from  */\r
-  buff[0] = '~';\r
-  buff[1] = '0';\r
-  buff[2] = '\0';\r
-  StrCatBuffW(lpszDest, buff, dwDestLen);\r
-\r
-  /* ~Product Id */\r
-  dwLen = 256;\r
-  if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))\r
-    buff[1] = '\0';\r
-  StrCatBuffW(lpszDest, buff, dwDestLen);\r
-\r
-  /* ~IE Update Url */\r
-  dwLen = 2048;\r
-  if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))\r
-    buff[1] = '\0';\r
-  StrCatBuffW(lpszDest, buff, dwDestLen);\r
-\r
-  /* ~IE Help String */\r
-  dwLen = 256;\r
-  if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))\r
-    buff[1] = '\0';\r
-  StrCatBuffW(lpszDest, buff, dwDestLen);\r
-\r
-  RegCloseKey(hReg);\r
-  return TRUE;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.163]\r
- *\r
- * Call IOleCommandTarget_QueryStatus() on an object.\r
- *\r
- * PARAMS\r
- *  lpUnknown     [I] Object supporting the IOleCommandTarget interface\r
- *  pguidCmdGroup [I] GUID for the command group\r
- *  cCmds         [I]\r
- *  prgCmds       [O] Commands\r
- *  pCmdText      [O] Command text\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: E_FAIL, if lpUnknown is NULL.\r
- *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.\r
- *           Otherwise, an error code from IOleCommandTarget_QueryStatus().\r
- */\r
-HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,\r
-                           ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)\r
-{\r
-  HRESULT hRet = E_FAIL;\r
-\r
-  TRACE("(%p,%p,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);\r
-\r
-  if (lpUnknown)\r
-  {\r
-    IOleCommandTarget* lpOle;\r
-\r
-    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,\r
-                                   (void**)&lpOle);\r
-\r
-    if (SUCCEEDED(hRet) && lpOle)\r
-    {\r
-      hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,\r
-                                           prgCmds, pCmdText);\r
-      IOleCommandTarget_Release(lpOle);\r
-    }\r
-  }\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @              [SHLWAPI.164]\r
- *\r
- * Call IOleCommandTarget_Exec() on an object.\r
- *\r
- * PARAMS\r
- *  lpUnknown     [I] Object supporting the IOleCommandTarget interface\r
- *  pguidCmdGroup [I] GUID for the command group\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: E_FAIL, if lpUnknown is NULL.\r
- *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.\r
- *           Otherwise, an error code from IOleCommandTarget_Exec().\r
- */\r
-HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,\r
-                           DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,\r
-                           VARIANT* pvaOut)\r
-{\r
-  HRESULT hRet = E_FAIL;\r
-\r
-  TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,\r
-        nCmdexecopt, pvaIn, pvaOut);\r
-\r
-  if (lpUnknown)\r
-  {\r
-    IOleCommandTarget* lpOle;\r
-\r
-    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,\r
-                                   (void**)&lpOle);\r
-    if (SUCCEEDED(hRet) && lpOle)\r
-    {\r
-      hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,\r
-                                    nCmdexecopt, pvaIn, pvaOut);\r
-      IOleCommandTarget_Release(lpOle);\r
-    }\r
-  }\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.165]\r
- *\r
- * Retrieve, modify, and re-set a value from a window.\r
- *\r
- * PARAMS\r
- *  hWnd   [I] Window to get value from\r
- *  offset [I] Offset of value\r
- *  wMask  [I] Mask for uiFlags\r
- *  wFlags [I] Bits to set in window value\r
- *\r
- * RETURNS\r
- *  The new value as it was set, or 0 if any parameter is invalid.\r
- *\r
- * NOTES\r
- *  Any bits set in uiMask are cleared from the value, then any bits set in\r
- *  uiFlags are set in the value.\r
- */\r
-LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags)\r
-{\r
-  LONG ret = GetWindowLongA(hwnd, offset);\r
-  LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);\r
-\r
-  if (newFlags != ret)\r
-    ret = SetWindowLongA(hwnd, offset, newFlags);\r
-  return ret;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.167]\r
- *\r
- * Change a window's parent.\r
- *\r
- * PARAMS\r
- *  hWnd       [I] Window to change parent of\r
- *  hWndParent [I] New parent window\r
- *\r
- * RETURNS\r
- *  The old parent of hWnd.\r
- *\r
- * NOTES\r
- *  If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.\r
- *  If hWndParent is NOT NULL then we set the WS_CHILD style.\r
- */\r
-HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)\r
-{\r
-  TRACE("%p, %p\n", hWnd, hWndParent);\r
-\r
-  if(GetParent(hWnd) == hWndParent)\r
-    return 0;\r
-\r
-  if(hWndParent)\r
-    SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);\r
-  else\r
-    SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);\r
-\r
-  return SetParent(hWnd, hWndParent);\r
-}\r
-\r
-/*************************************************************************\r
- *      @       [SHLWAPI.168]\r
- *\r
- * Locate and advise a connection point in an IConnectionPointContainer object.\r
- *\r
- * PARAMS\r
- *  lpUnkSink   [I] Sink for the connection point advise call\r
- *  riid        [I] REFIID of connection point to advise\r
- *  bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first\r
- *  lpUnknown   [I] Object supporting the IConnectionPointContainer interface\r
- *  lpCookie    [O] Pointer to connection point cookie\r
- *  lppCP       [O] Destination for the IConnectionPoint found\r
- *\r
- * RETURNS\r
- *  Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint\r
- *           that was advised. The caller is responsable for releasing it.\r
- *  Failure: E_FAIL, if any arguments are invalid.\r
- *           E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,\r
- *           Or an HRESULT error code if any call fails.\r
- */\r
-HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,\r
-                           IUnknown* lpUnknown, LPDWORD lpCookie,\r
-                           IConnectionPoint **lppCP)\r
-{\r
-  HRESULT hRet;\r
-  IConnectionPointContainer* lpContainer;\r
-  IConnectionPoint *lpCP;\r
-\r
-  if(!lpUnknown || (bAdviseOnly && !lpUnkSink))\r
-    return E_FAIL;\r
-\r
-  if(lppCP)\r
-    *lppCP = NULL;\r
-\r
-  hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,\r
-                                 (void**)&lpContainer);\r
-  if (SUCCEEDED(hRet))\r
-  {\r
-    hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);\r
-\r
-    if (SUCCEEDED(hRet))\r
-    {\r
-      if(!bAdviseOnly)\r
-        hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);\r
-      hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);\r
-\r
-      if (FAILED(hRet))\r
-        *lpCookie = 0;\r
-\r
-      if (lppCP && SUCCEEDED(hRet))\r
-        *lppCP = lpCP; /* Caller keeps the interface */\r
-      else\r
-        IConnectionPoint_Release(lpCP); /* Release it */\r
-    }\r
-\r
-    IUnknown_Release(lpContainer);\r
-  }\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *     @       [SHLWAPI.169]\r
- *\r
- * Release an interface.\r
- *\r
- * PARAMS\r
- *  lpUnknown [I] Object to release\r
- *\r
- * RETURNS\r
- *  Nothing.\r
- */\r
-DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)\r
-{\r
-    IUnknown *temp;\r
-\r
-    TRACE("(%p)\n",lpUnknown);\r
-\r
-    if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;\r
-    temp = *lpUnknown;\r
-    *lpUnknown = NULL;\r
-\r
-    TRACE("doing Release\n");\r
-    \r
-    return IUnknown_Release(temp);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.170]\r
- *\r
- * Skip '//' if present in a string.\r
- *\r
- * PARAMS\r
- *  lpszSrc [I] String to check for '//'\r
- *\r
- * RETURNS\r
- *  Success: The next character after the '//' or the string if not present\r
- *  Failure: NULL, if lpszStr is NULL.\r
- */\r
-LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)\r
-{\r
-  if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')\r
-    lpszSrc += 2;\r
-  return lpszSrc;\r
-}\r
-\r
-/*************************************************************************\r
- *      @              [SHLWAPI.171]\r
- *\r
- * Check if two interfaces come from the same object.\r
- *\r
- * PARAMS\r
- *   lpInt1 [I] Interface to check against lpInt2.\r
- *   lpInt2 [I] Interface to check against lpInt1.\r
- *\r
- * RETURNS\r
- *   TRUE, If the interfaces come from the same object.\r
- *   FALSE Otherwise.\r
- */\r
-BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)\r
-{\r
-  LPVOID lpUnknown1, lpUnknown2;\r
-\r
-  TRACE("%p %p\n", lpInt1, lpInt2);\r
-\r
-  if (!lpInt1 || !lpInt2)\r
-    return FALSE;\r
-\r
-  if (lpInt1 == lpInt2)\r
-    return TRUE;\r
-\r
-  if (!SUCCEEDED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown,\r
-                                       (LPVOID *)&lpUnknown1)))\r
-    return FALSE;\r
-\r
-  if (!SUCCEEDED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown,\r
-                                       (LPVOID *)&lpUnknown2)))\r
-    return FALSE;\r
-\r
-  if (lpUnknown1 == lpUnknown2)\r
-    return TRUE;\r
-  \r
-  return FALSE;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.172]\r
- *\r
- * Get the window handle of an object.\r
- *\r
- * PARAMS\r
- *  lpUnknown [I] Object to get the window handle of\r
- *  lphWnd    [O] Destination for window handle\r
- *\r
- * RETURNS\r
- *  Success: S_OK. lphWnd contains the objects window handle.\r
- *  Failure: An HRESULT error code.\r
- *\r
- * NOTES\r
- *  lpUnknown is expected to support one of the following interfaces:\r
- *  IOleWindow(), IInternetSecurityMgrSite(), or IShellView().\r
- */\r
-HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)\r
-{\r
-  /* FIXME: Wine has no header for this object */\r
-  static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,\r
-    0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};\r
-  IUnknown *lpOle;\r
-  HRESULT hRet = E_FAIL;\r
-\r
-  TRACE("(%p,%p)\n", lpUnknown, lphWnd);\r
-\r
-  if (!lpUnknown)\r
-    return hRet;\r
-\r
-  hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);\r
-\r
-  if (FAILED(hRet))\r
-  {\r
-    hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);\r
-\r
-    if (FAILED(hRet))\r
-    {\r
-      hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,\r
-                                      (void**)&lpOle);\r
-    }\r
-  }\r
-\r
-  if (SUCCEEDED(hRet))\r
-  {\r
-    /* Lazyness here - Since GetWindow() is the first method for the above 3\r
-     * interfaces, we use the same call for them all.\r
-     */\r
-    hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);\r
-    IUnknown_Release(lpOle);\r
-    if (lphWnd)\r
-      TRACE("Returning HWND=%p\n", *lphWnd);\r
-  }\r
-\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.173]\r
- *\r
- * Call a method on as as yet unidentified object.\r
- *\r
- * PARAMS\r
- *  pUnk [I] Object supporting the unidentified interface,\r
- *  arg  [I] Argument for the call on the object.\r
- *\r
- * RETURNS\r
- *  S_OK.\r
- */\r
-HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)\r
-{\r
-  static const GUID guid_173 = {\r
-    0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }\r
-  };\r
-  IMalloc *pUnk2;\r
-\r
-  TRACE("(%p,%ld)\n", pUnk, arg);\r
-\r
-  /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -\r
-   *       We use this interface as its vtable entry is compatible with the\r
-   *       object in question.\r
-   * FIXME: Find out what this object is and where it should be defined.\r
-   */\r
-  if (pUnk &&\r
-      SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))\r
-  {\r
-    IMalloc_Alloc(pUnk2, arg); /* Faked call!! */\r
-    IMalloc_Release(pUnk2);\r
-  }\r
-  return S_OK;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.174]\r
- *\r
- * Call either IObjectWithSite_SetSite() or IPersistMoniker_GetClassID() on\r
- * an interface.\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: E_FAIL, if p1 is NULL.\r
- *           E_NOINTERFACE If p1 does not support the IPersist interface,\r
- *           Or an HRESULT error code.\r
- */\r
-DWORD WINAPI IUnknown_SetSite(\r
-        IUnknown *p1,     /* [in]   OLE object                          */\r
-        LPVOID *p2)       /* [out]  ptr for call results */\r
-{\r
-    DWORD ret, aa;\r
-    IUnknown *iobjectwithsite;\r
-\r
-    if (!p1) return E_FAIL;\r
-\r
-    /* see if SetSite interface exists for IObjectWithSite object */\r
-    ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&iobjectwithsite);\r
-    TRACE("first IU_QI ret=%08lx, iobjectwithsite=%p\n", ret, iobjectwithsite);\r
-    if (ret) {\r
-\r
-       /* see if GetClassId interface exists for IPersistMoniker object */\r
-       ret = IUnknown_QueryInterface(p1, (REFIID)id2, (LPVOID *)&aa);\r
-       TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);\r
-       if (ret) return ret;\r
-\r
-       /* fake a GetClassId call */\r
-       ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);\r
-       TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,\r
-             *(LPDWORD)p2);\r
-       IUnknown_Release((IUnknown *)aa);\r
-    }\r
-    else {\r
-       /* fake a SetSite call */\r
-       ret = IOleWindow_GetWindow((IOleWindow *)iobjectwithsite, (HWND*)p2);\r
-       TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,\r
-             *(LPDWORD)p2);\r
-       IUnknown_Release((IUnknown *)iobjectwithsite);\r
-    }\r
-    return ret;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.175]\r
- *\r
- * Call IPersist_GetClassID() on an object.\r
- *\r
- * PARAMS\r
- *  lpUnknown [I] Object supporting the IPersist interface\r
- *  lpClassId [O] Destination for Class Id\r
- *\r
- * RETURNS\r
- *  Success: S_OK. lpClassId contains the Class Id requested.\r
- *  Failure: E_FAIL, If lpUnknown is NULL,\r
- *           E_NOINTERFACE If lpUnknown does not support IPersist,\r
- *           Or an HRESULT error code.\r
- */\r
-HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)\r
-{\r
-  IPersist* lpPersist;\r
-  HRESULT hRet = E_FAIL;\r
-\r
-  TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));\r
-\r
-  if (lpUnknown)\r
-  {\r
-    hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);\r
-    if (SUCCEEDED(hRet))\r
-    {\r
-      IPersist_GetClassID(lpPersist, lpClassId);\r
-      IPersist_Release(lpPersist);\r
-    }\r
-  }\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.176]\r
- *\r
- * Retrieve a Service Interface from an object.\r
- *\r
- * PARAMS\r
- *  lpUnknown [I] Object to get an IServiceProvider interface from\r
- *  sid       [I] Service ID for IServiceProvider_QueryService() call\r
- *  riid      [I] Function requested for QueryService call\r
- *  lppOut    [O] Destination for the service interface pointer\r
- *\r
- * RETURNS\r
- *  Success: S_OK. lppOut contains an object providing the requested service\r
- *  Failure: An HRESULT error code\r
- *\r
- * NOTES\r
- *  lpUnknown is expected to support the IServiceProvider interface.\r
- */\r
-HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,\r
-                           LPVOID *lppOut)\r
-{\r
-  IServiceProvider* pService = NULL;\r
-  HRESULT hRet;\r
-\r
-  if (!lppOut)\r
-    return E_FAIL;\r
-\r
-  *lppOut = NULL;\r
-\r
-  if (!lpUnknown)\r
-    return E_FAIL;\r
-\r
-  /* Get an IServiceProvider interface from the object */\r
-  hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,\r
-                                 (LPVOID*)&pService);\r
-\r
-  if (!hRet && pService)\r
-  {\r
-    TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);\r
-\r
-    /* Get a Service interface from the object */\r
-    hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);\r
-\r
-    TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);\r
-\r
-    /* Release the IServiceProvider interface */\r
-    IUnknown_Release(pService);\r
-  }\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.177]\r
- *\r
- * Loads a popup menu.\r
- *\r
- * PARAMS\r
- *  hInst  [I] Instance handle\r
- *  szName [I] Menu name\r
- *\r
- * RETURNS\r
- *  Success: TRUE.\r
- *  Failure: FALSE.\r
- */\r
-BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)\r
-{\r
-  HMENU hMenu, hSubMenu;\r
-\r
-  if ((hMenu = LoadMenuW(hInst, szName)))\r
-  {\r
-    if ((hSubMenu = GetSubMenu(hMenu, 0)))\r
-      RemoveMenu(hMenu, 0, MF_BYPOSITION);\r
-\r
-    DestroyMenu(hMenu);\r
-    return TRUE;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-typedef struct _enumWndData\r
-{\r
-  UINT   uiMsgId;\r
-  WPARAM wParam;\r
-  LPARAM lParam;\r
-  LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);\r
-} enumWndData;\r
-\r
-/* Callback for SHLWAPI_178 */\r
-static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)\r
-{\r
-  enumWndData *data = (enumWndData *)lParam;\r
-\r
-  TRACE("(%p,%p)\n", hWnd, data);\r
-  data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);\r
-  return TRUE;\r
-}\r
-\r
-/*************************************************************************\r
- * @  [SHLWAPI.178]\r
- *\r
- * Send or post a message to every child of a window.\r
- *\r
- * PARAMS\r
- *  hWnd    [I] Window whose children will get the messages\r
- *  uiMsgId [I] Message Id\r
- *  wParam  [I] WPARAM of message\r
- *  lParam  [I] LPARAM of message\r
- *  bSend   [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()\r
- *\r
- * RETURNS\r
- *  Nothing.\r
- *\r
- * NOTES\r
- *  The appropriate ASCII or Unicode function is called for the window.\r
- */\r
-void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)\r
-{\r
-  enumWndData data;\r
-\r
-  TRACE("(%p,%u,%d,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);\r
-\r
-  if(hWnd)\r
-  {\r
-    data.uiMsgId = uiMsgId;\r
-    data.wParam  = wParam;\r
-    data.lParam  = lParam;\r
-\r
-    if (bSend)\r
-      data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;\r
-    else\r
-      data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;\r
-\r
-    EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);\r
-  }\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.180]\r
- *\r
- * Remove all sub-menus from a menu.\r
- *\r
- * PARAMS\r
- *  hMenu [I] Menu to remove sub-menus from\r
- *\r
- * RETURNS\r
- *  Success: 0.  All sub-menus under hMenu are removed\r
- *  Failure: -1, if any parameter is invalid\r
- */\r
-DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)\r
-{\r
-  int iItemCount = GetMenuItemCount(hMenu) - 1;\r
-  while (iItemCount >= 0)\r
-  {\r
-    HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);\r
-    if (hSubMenu)\r
-      RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);\r
-    iItemCount--;\r
-  }\r
-  return iItemCount;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.181]\r
- *\r
- * Enable or disable a menu item.\r
- *\r
- * PARAMS\r
- *  hMenu   [I] Menu holding menu item\r
- *  uID     [I] ID of menu item to enable/disable\r
- *  bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.\r
- *\r
- * RETURNS\r
- *  The return code from EnableMenuItem.\r
- */\r
-UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)\r
-{\r
-  return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);\r
-}\r
-\r
-/*************************************************************************\r
- * @   [SHLWAPI.182]\r
- *\r
- * Check or uncheck a menu item.\r
- *\r
- * PARAMS\r
- *  hMenu  [I] Menu holding menu item\r
- *  uID    [I] ID of menu item to check/uncheck\r
- *  bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.\r
- *\r
- * RETURNS\r
- *  The return code from CheckMenuItem.\r
- */\r
-DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)\r
-{\r
-  return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.183]\r
- *\r
- * Register a window class if it isn't already.\r
- *\r
- * PARAMS\r
- *  lpWndClass [I] Window class to register\r
- *\r
- * RETURNS\r
- *  The result of the RegisterClassA call.\r
- */\r
-DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)\r
-{\r
-  WNDCLASSA wca;\r
-  if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))\r
-    return TRUE;\r
-  return (DWORD)RegisterClassA(wndclass);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.186]\r
- */\r
-BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,\r
-                           DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)\r
-{\r
-  DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;\r
-  POINTL pt = { 0, 0 };\r
-\r
-  if (!lpPt)\r
-    lpPt = &pt;\r
-\r
-  if (!pdwEffect)\r
-    pdwEffect = &dwEffect;\r
-\r
-  IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);\r
-\r
-  if (*pdwEffect)\r
-    return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);\r
-\r
-  IDropTarget_DragLeave(pDrop);\r
-  return TRUE;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.187]\r
- *\r
- * Call IPersistPropertyBag_Load() on an object.\r
- *\r
- * PARAMS\r
- *  lpUnknown [I] Object supporting the IPersistPropertyBag interface\r
- *  lpPropBag [O] Destination for loaded IPropertyBag\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.\r
- */\r
-DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)\r
-{\r
-  IPersistPropertyBag* lpPPBag;\r
-  HRESULT hRet = E_FAIL;\r
-\r
-  TRACE("(%p,%p)\n", lpUnknown, lpPropBag);\r
-\r
-  if (lpUnknown)\r
-  {\r
-    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,\r
-                                   (void**)&lpPPBag);\r
-    if (SUCCEEDED(hRet) && lpPPBag)\r
-    {\r
-      hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);\r
-      IPersistPropertyBag_Release(lpPPBag);\r
-    }\r
-  }\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- * @  [SHLWAPI.189]\r
- *\r
- * Call IOleControlSite_GetExtendedControl() on an object.\r
- *\r
- * PARAMS\r
- *  lpUnknown [I] Object supporting the IOleControlSite interface\r
- *  lppDisp   [O] Destination for resulting IDispatch.\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.\r
- */\r
-DWORD WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, IDispatch** lppDisp)\r
-{\r
-  IOleControlSite* lpCSite;\r
-  HRESULT hRet = E_FAIL;\r
-\r
-  TRACE("(%p,%p)\n", lpUnknown, lppDisp);\r
-  if (lpUnknown)\r
-  {\r
-    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,\r
-                                   (void**)&lpCSite);\r
-    if (SUCCEEDED(hRet) && lpCSite)\r
-    {\r
-      hRet = IOleControlSite_GetExtendedControl(lpCSite, lppDisp);\r
-      IOleControlSite_Release(lpCSite);\r
-    }\r
-  }\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- * @    [SHLWAPI.192]\r
- *\r
- * Get a sub-menu from a menu item.\r
- *\r
- * PARAMS\r
- *  hMenu [I] Menu to get sub-menu from\r
- *  uID   [I] ID of menu item containing sub-menu\r
- *\r
- * RETURNS\r
- *  The sub-menu of the item, or a NULL handle if any parameters are invalid.\r
- */\r
-HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)\r
-{\r
-  MENUITEMINFOA mi;\r
-\r
-  TRACE("(%p,%uld)\n", hMenu, uID);\r
-\r
-  mi.cbSize = sizeof(MENUITEMINFOA);\r
-  mi.fMask = MIIM_SUBMENU;\r
-\r
-  if (!GetMenuItemInfoA(hMenu, uID, 0, &mi))\r
-    return NULL;\r
-\r
-  return mi.hSubMenu;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.193]\r
- *\r
- * Get the color depth of the primary display.\r
- *\r
- * PARAMS\r
- *  None.\r
- *\r
- * RETURNS\r
- *  The color depth of the primary display.\r
- */\r
-DWORD WINAPI SHGetCurColorRes()\r
-{\r
-    HDC hdc;\r
-    DWORD ret;\r
-\r
-    TRACE("()\n");\r
-\r
-    hdc = GetDC(0);\r
-    ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);\r
-    ReleaseDC(0, hdc);\r
-    return ret;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.194]\r
- *\r
- * Wait for a message to arrive, with a timeout.\r
- *\r
- * PARAMS\r
- *  hand      [I] Handle to query\r
- *  dwTimeout [I] Timeout in ticks or INFINITE to never timeout\r
- *\r
- * RETURNS\r
- *  STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.\r
- *  Otherwise returns the value from MsgWaitForMultipleObjectsEx when a\r
- *  message is available.\r
- */\r
-DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)\r
-{\r
-  DWORD dwEndTicks = GetTickCount() + dwTimeout;\r
-  DWORD dwRet;\r
-\r
-  while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)\r
-  {\r
-    MSG msg;\r
-\r
-    PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);\r
-\r
-    if (dwTimeout != INFINITE)\r
-    {\r
-        if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)\r
-            return WAIT_TIMEOUT;\r
-    }\r
-  }\r
-\r
-  return dwRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @       [SHLWAPI.197]\r
- *\r
- * Blank out a region of text by drawing the background only.\r
- *\r
- * PARAMS\r
- *  hDC   [I] Device context to draw in\r
- *  pRect [I] Area to draw in\r
- *  cRef  [I] Color to draw in\r
- *\r
- * RETURNS\r
- *  Nothing.\r
- */\r
-DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)\r
-{\r
-    COLORREF cOldColor = SetBkColor(hDC, cRef);\r
-    ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);\r
-    SetBkColor(hDC, cOldColor);\r
-    return 0;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.198]\r
- *\r
- * Return the value asociated with a key in a map.\r
- *\r
- * PARAMS\r
- *  lpKeys   [I] A list of keys of length iLen\r
- *  lpValues [I] A list of values associated with lpKeys, of length iLen\r
- *  iLen     [I] Length of both lpKeys and lpValues\r
- *  iKey     [I] The key value to look up in lpKeys\r
- *\r
- * RETURNS\r
- *  The value in lpValues associated with iKey, or -1 if iKey is not\r
- *  found in lpKeys.\r
- *\r
- * NOTES\r
- *  - If two elements in the map share the same key, this function returns\r
- *    the value closest to the start of the map\r
- *  - The native version of this function crashes if lpKeys or lpValues is NULL.\r
- */\r
-int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)\r
-{\r
-  if (lpKeys && lpValues)\r
-  {\r
-    int i = 0;\r
-\r
-    while (i < iLen)\r
-    {\r
-      if (lpKeys[i] == iKey)\r
-        return lpValues[i]; /* Found */\r
-      i++;\r
-    }\r
-  }\r
-  return -1; /* Not found */\r
-}\r
-\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.199]\r
- *\r
- * Copy an interface pointer\r
- *\r
- * PARAMS\r
- *   lppDest   [O] Destination for copy\r
- *   lpUnknown [I] Source for copy\r
- *\r
- * RETURNS\r
- *  Nothing.\r
- */\r
-VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)\r
-{\r
-  TRACE("(%p,%p)\n", lppDest, lpUnknown);\r
-\r
-  if (lppDest)\r
-    IUnknown_AtomicRelease(lppDest); /* Release existing interface */\r
-\r
-  if (lpUnknown)\r
-  {\r
-    /* Copy */\r
-    IUnknown_AddRef(lpUnknown);\r
-    *lppDest = lpUnknown;\r
-  }\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.201]\r
- *\r
- */\r
-HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,\r
-                           DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,\r
-                           VARIANT* pvaOut)\r
-{\r
-  FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,\r
-        nCmdID, nCmdexecopt, pvaIn, pvaOut);\r
-  return DRAGDROP_E_NOTREGISTERED;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.202]\r
- *\r
- */\r
-HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)\r
-{\r
-  FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);\r
-  return DRAGDROP_E_NOTREGISTERED;\r
-}\r
-\r
-/*************************************************************************\r
- * @   [SHLWAPI.204]\r
- *\r
- * Determine if a window is not a child of another window.\r
- *\r
- * PARAMS\r
- * hParent [I] Suspected parent window\r
- * hChild  [I] Suspected child window\r
- *\r
- * RETURNS\r
- * TRUE:  If hChild is a child window of hParent\r
- * FALSE: If hChild is not a child window of hParent, or they are equal\r
- */\r
-BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)\r
-{\r
-  TRACE("(%p,%p)\n", hParent, hChild);\r
-\r
-  if (!hParent || !hChild)\r
-    return TRUE;\r
-  else if(hParent == hChild)\r
-    return FALSE;\r
-  return !IsChild(hParent, hChild);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.208]\r
- *\r
- * Some sort of memory management process.\r
- */\r
-DWORD WINAPI FDSA_Initialize(\r
-       DWORD    a,\r
-       DWORD    b,\r
-       LPVOID   c,\r
-       LPVOID   d,\r
-       DWORD    e)\r
-{\r
-    FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",\r
-         a, b, c, d, e);\r
-    return 1;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.209]\r
- *\r
- * Some sort of memory management process.\r
- */\r
-DWORD WINAPI FDSA_Destroy(\r
-       LPVOID   a)\r
-{\r
-    FIXME("(%p) stub\n",\r
-         a);\r
-    return 1;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.210]\r
- *\r
- * Some sort of memory management process.\r
- */\r
-DWORD WINAPI FDSA_InsertItem(\r
-       LPVOID   a,\r
-       DWORD    b,\r
-       LPVOID   c)\r
-{\r
-    FIXME("(%p 0x%08lx %p) stub\n",\r
-         a, b, c);\r
-    return 0;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.211]\r
- */\r
-DWORD WINAPI FDSA_DeleteItem(\r
-       LPVOID   a,\r
-       DWORD    b)\r
-{\r
-    FIXME("(%p 0x%08lx) stub\n",\r
-         a, b);\r
-    return 1;\r
-}\r
-\r
-typedef struct {\r
-    REFIID   refid;\r
-    DWORD    indx;\r
-} IFACE_INDEX_TBL;\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.219]\r
- *\r
- * Call IUnknown_QueryInterface() on a table of objects.\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: E_POINTER or E_NOINTERFACE.\r
- */\r
-HRESULT WINAPI QISearch(\r
-       LPVOID w,           /* [in]   Table of interfaces */\r
-       IFACE_INDEX_TBL *x, /* [in]   Array of REFIIDs and indexes into the table */\r
-       REFIID riid,        /* [in]   REFIID to get interface for */\r
-       LPVOID *ppv)          /* [out]  Destination for interface pointer */\r
-{\r
-       HRESULT ret;\r
-       IUnknown *a_vtbl;\r
-       IFACE_INDEX_TBL *xmove;\r
-\r
-       TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);\r
-       if (ppv) {\r
-           xmove = x;\r
-           while (xmove->refid) {\r
-               TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));\r
-               if (IsEqualIID(riid, xmove->refid)) {\r
-                   a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);\r
-                   TRACE("matched, returning (%p)\n", a_vtbl);\r
-                   *ppv = (LPVOID)a_vtbl;\r
-                   IUnknown_AddRef(a_vtbl);\r
-                   return S_OK;\r
-               }\r
-               xmove++;\r
-           }\r
-\r
-           if (IsEqualIID(riid, &IID_IUnknown)) {\r
-               a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);\r
-               TRACE("returning first for IUnknown (%p)\n", a_vtbl);\r
-               *ppv = (LPVOID)a_vtbl;\r
-               IUnknown_AddRef(a_vtbl);\r
-               return S_OK;\r
-           }\r
-           *ppv = 0;\r
-           ret = E_NOINTERFACE;\r
-       } else\r
-           ret = E_POINTER;\r
-\r
-       TRACE("-- 0x%08lx\n", ret);\r
-       return ret;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.221]\r
- *\r
- * Remove the "PropDlgFont" property from a window.\r
- *\r
- * PARAMS\r
- *  hWnd [I] Window to remove the property from\r
- *\r
- * RETURNS\r
- *  A handle to the removed property, or NULL if it did not exist.\r
- */\r
-HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)\r
-{\r
-  HANDLE hProp;\r
-\r
-  TRACE("(%p)\n", hWnd);\r
-\r
-  hProp = GetPropA(hWnd, "PropDlgFont");\r
-\r
-  if(hProp)\r
-  {\r
-    DeleteObject(hProp);\r
-    hProp = RemovePropA(hWnd, "PropDlgFont");\r
-  }\r
-  return hProp;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.236]\r
- *\r
- * Load the in-process server of a given GUID.\r
- *\r
- * PARAMS\r
- *  refiid [I] GUID of the server to load.\r
- *\r
- * RETURNS\r
- *  Success: A handle to the loaded server dll.\r
- *  Failure: A NULL handle.\r
- */\r
-HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)\r
-{\r
-    HKEY newkey;\r
-    DWORD type, count;\r
-    CHAR value[MAX_PATH], string[MAX_PATH];\r
-\r
-    strcpy(string, "CLSID\\");\r
-    SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);\r
-    strcat(string, "\\InProcServer32");\r
-\r
-    count = MAX_PATH;\r
-    RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);\r
-    RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);\r
-    RegCloseKey(newkey);\r
-    return LoadLibraryExA(value, 0, 0);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.237]\r
- *\r
- * Unicode version of SHLWAPI_183.\r
- */\r
-DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)\r
-{\r
-       WNDCLASSW WndClass;\r
-\r
-       TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));\r
-\r
-       if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))\r
-               return TRUE;\r
-       return RegisterClassW(lpWndClass);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.238]\r
- *\r
- * Unregister a list of classes.\r
- *\r
- * PARAMS\r
- *  hInst      [I] Application instance that registered the classes\r
- *  lppClasses [I] List of class names\r
- *  iCount     [I] Number of names in lppClasses\r
- *\r
- * RETURNS\r
- *  Nothing.\r
- */\r
-void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)\r
-{\r
-  WNDCLASSA WndClass;\r
-\r
-  TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);\r
-\r
-  while (iCount > 0)\r
-  {\r
-    if (GetClassInfoA(hInst, *lppClasses, &WndClass))\r
-      UnregisterClassA(*lppClasses, hInst);\r
-    lppClasses++;\r
-    iCount--;\r
-  }\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.239]\r
- *\r
- * Unicode version of SHUnregisterClassesA.\r
- */\r
-void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)\r
-{\r
-  WNDCLASSW WndClass;\r
-\r
-  TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);\r
-\r
-  while (iCount > 0)\r
-  {\r
-    if (GetClassInfoW(hInst, *lppClasses, &WndClass))\r
-      UnregisterClassW(*lppClasses, hInst);\r
-    lppClasses++;\r
-    iCount--;\r
-  }\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.240]\r
- *\r
- * Call The correct (Ascii/Unicode) default window procedure for a window.\r
- *\r
- * PARAMS\r
- *  hWnd     [I] Window to call the default procedure for\r
- *  uMessage [I] Message ID\r
- *  wParam   [I] WPARAM of message\r
- *  lParam   [I] LPARAM of message\r
- *\r
- * RETURNS\r
- *  The result of calling DefWindowProcA() or DefWindowProcW().\r
- */\r
-LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)\r
-{\r
-       if (IsWindowUnicode(hWnd))\r
-               return DefWindowProcW(hWnd, uMessage, wParam, lParam);\r
-       return DefWindowProcA(hWnd, uMessage, wParam, lParam);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.257]\r
- *\r
- * Create a worker window using CreateWindowExA().\r
- *\r
- * PARAMS\r
- *  wndProc    [I] Window procedure\r
- *  hWndParent [I] Parent window\r
- *  dwExStyle  [I] Extra style flags\r
- *  dwStyle    [I] Style flags\r
- *  hMenu      [I] Window menu\r
- *  z          [I] Unknown\r
- *\r
- * RETURNS\r
- *  Success: The window handle of the newly created window.\r
- *  Failure: 0.\r
- */\r
-HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,\r
-                        DWORD dwStyle, HMENU hMenu, LONG z)\r
-{\r
-  static const char* szClass = "WorkerA";\r
-  WNDCLASSA wc;\r
-  HWND hWnd;\r
-\r
-  TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",\r
-         wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);\r
-\r
-  /* Create Window class */\r
-  wc.style         = 0;\r
-  wc.lpfnWndProc   = DefWindowProcA;\r
-  wc.cbClsExtra    = 0;\r
-  wc.cbWndExtra    = 4;\r
-  wc.hInstance     = shlwapi_hInstance;\r
-  wc.hIcon         = NULL;\r
-  wc.hCursor       = LoadCursorA(NULL, (LPSTR)IDC_ARROW);\r
-  wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;\r
-  wc.lpszMenuName  = NULL;\r
-  wc.lpszClassName = szClass;\r
-\r
-  SHRegisterClassA(&wc); /* Register class */\r
-\r
-  /* FIXME: Set extra bits in dwExStyle */\r
-\r
-  hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,\r
-                         hWndParent, hMenu, shlwapi_hInstance, 0);\r
-  if (hWnd)\r
-  {\r
-    SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);\r
-\r
-    if (wndProc)\r
-      SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);\r
-  }\r
-  return hWnd;\r
-}\r
-\r
-typedef struct tagPOLICYDATA\r
-{\r
-  DWORD policy;        /* flags value passed to SHRestricted */\r
-  LPCWSTR appstr;      /* application str such as "Explorer" */\r
-  LPCWSTR keystr;      /* name of the actual registry key / policy */\r
-} POLICYDATA, *LPPOLICYDATA;\r
-\r
-#define SHELL_NO_POLICY 0xffffffff\r
-\r
-/* default shell policy registry key */\r
-static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',\r
-                                      's','o','f','t','\\','W','i','n','d','o','w','s','\\',\r
-                                      'C','u','r','r','e','n','t','V','e','r','s','i','o','n',\r
-                                      '\\','P','o','l','i','c','i','e','s',0};\r
-\r
-/*************************************************************************\r
- * @                          [SHLWAPI.271]\r
- *\r
- * Retrieve a policy value from the registry.\r
- *\r
- * PARAMS\r
- *  lpSubKey   [I]   registry key name\r
- *  lpSubName  [I]   subname of registry key\r
- *  lpValue    [I]   value name of registry value\r
- *\r
- * RETURNS\r
- *  the value associated with the registry key or 0 if not found\r
- */\r
-DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)\r
-{\r
-       DWORD retval, datsize = sizeof(retval);\r
-       HKEY hKey;\r
-\r
-       if (!lpSubKey)\r
-         lpSubKey = strRegistryPolicyW;\r
-\r
-       retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);\r
-    if (retval != ERROR_SUCCESS)\r
-         retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);\r
-       if (retval != ERROR_SUCCESS)\r
-         return 0;\r
-\r
-       SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);\r
-       RegCloseKey(hKey);\r
-       return retval;\r
-}\r
-\r
-/*************************************************************************\r
- * @                         [SHLWAPI.266]\r
- *\r
- * Helper function to retrieve the possibly cached value for a specific policy\r
- *\r
- * PARAMS\r
- *  policy     [I]   The policy to look for\r
- *  initial    [I]   Main registry key to open, if NULL use default\r
- *  polTable   [I]   Table of known policies, 0 terminated\r
- *  polArr     [I]   Cache array of policy values\r
- *\r
- * RETURNS\r
- *  The retrieved policy value or 0 if not successful\r
- *\r
- * NOTES\r
- *  This function is used by the native SHRestricted function to search for the\r
- *  policy and cache it once retrieved. The current Wine implementation uses a\r
- *  different POLICYDATA structure and implements a similar algorithme adapted to\r
- *  that structure.\r
- */\r
-DWORD WINAPI SHRestrictionLookup(\r
-       DWORD policy,\r
-       LPCWSTR initial,\r
-       LPPOLICYDATA polTable,\r
-       LPDWORD polArr)\r
-{\r
-       TRACE("(0x%08lx %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);\r
-\r
-       if (!polTable || !polArr)\r
-         return 0;\r
-\r
-       for (;polTable->policy; polTable++, polArr++)\r
-       {\r
-         if (policy == polTable->policy)\r
-         {\r
-           /* we have a known policy */\r
-\r
-           /* check if this policy has been cached */\r
-               if (*polArr == SHELL_NO_POLICY)\r
-             *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);\r
-           return *polArr;\r
-         }\r
-       }\r
-       /* we don't know this policy, return 0 */\r
-       TRACE("unknown policy: (%08lx)\n", policy);\r
-       return 0;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.267]\r
- *\r
- * Get an interface from an object.\r
- *\r
- * RETURNS\r
- *  Success: S_OK. ppv contains the requested interface.\r
- *  Failure: An HRESULT error code.\r
- *\r
- * NOTES\r
- *   This QueryInterface asks the inner object for a interface. In case\r
- *   of aggregation this request would be forwarded by the inner to the\r
- *   outer object. This function asks the inner object directly for the\r
- *   interface circumventing the forwarding to the outer object.\r
- */\r
-HRESULT WINAPI SHWeakQueryInterface(\r
-       IUnknown * pUnk,   /* [in] Outer object */\r
-       IUnknown * pInner, /* [in] Inner object */\r
-       IID * riid, /* [in] Interface GUID to query for */\r
-       LPVOID* ppv) /* [out] Destination for queried interface */\r
-{\r
-       HRESULT hret = E_NOINTERFACE;\r
-       TRACE("(pUnk=%p pInner=%p\n\tIID:  %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);\r
-\r
-       *ppv = NULL;\r
-       if(pUnk && pInner) {\r
-           hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);\r
-           if (SUCCEEDED(hret)) IUnknown_Release(pUnk);\r
-       }\r
-       TRACE("-- 0x%08lx\n", hret);\r
-       return hret;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.268]\r
- *\r
- * Move a reference from one interface to another.\r
- *\r
- * PARAMS\r
- *   lpDest     [O] Destination to receive the reference\r
- *   lppUnknown [O] Source to give up the reference to lpDest\r
- *\r
- * RETURNS\r
- *  Nothing.\r
- */\r
-VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)\r
-{\r
-  TRACE("(%p,%p)\n", lpDest, lppUnknown);\r
-\r
-  if (*lppUnknown)\r
-  {\r
-    /* Copy Reference*/\r
-    IUnknown_AddRef(lpDest);\r
-    IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */\r
-  }\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.269]\r
- *\r
- * Convert an ASCII string of a CLSID into a CLSID.\r
- *\r
- * PARAMS\r
- *  idstr [I] String representing a CLSID in registry format\r
- *  id    [O] Destination for the converted CLSID\r
- *\r
- * RETURNS\r
- *  Success: TRUE. id contains the converted CLSID.\r
- *  Failure: FALSE.\r
- */\r
-BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)\r
-{\r
-  WCHAR wClsid[40];\r
-  MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));\r
-  return SUCCEEDED(CLSIDFromStringWrap(wClsid, id));\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.270]\r
- *\r
- * Unicode version of GUIDFromStringA.\r
- */\r
-BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)\r
-{\r
-  return SUCCEEDED(CLSIDFromStringWrap(idstr, id));\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.276]\r
- *\r
- * Determine if the browser is integrated into the shell, and set a registry\r
- * key accordingly.\r
- *\r
- * PARAMS\r
- *  None.\r
- *\r
- * RETURNS\r
- *  1, If the browser is not integrated.\r
- *  2, If the browser is integrated.\r
- *\r
- * NOTES\r
- *  The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is\r
- *  either set to TRUE, or removed depending on whether the browser is deemed\r
- *  to be integrated.\r
- */\r
-DWORD WINAPI WhichPlatform()\r
-{\r
-  static LPCSTR szIntegratedBrowser = "IntegratedBrowser";\r
-  static DWORD dwState = 0;\r
-  HKEY hKey;\r
-  DWORD dwRet, dwData, dwSize;\r
-\r
-  if (dwState)\r
-    return dwState;\r
-\r
-  /* If shell32 exports DllGetVersion(), the browser is integrated */\r
-  GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);\r
-  dwState = pDllGetVersion ? 2 : 1;\r
-\r
-  /* Set or delete the key accordingly */\r
-  dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,\r
-                        "Software\\Microsoft\\Internet Explorer", 0,\r
-                         KEY_ALL_ACCESS, &hKey);\r
-  if (!dwRet)\r
-  {\r
-    dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,\r
-                             (LPBYTE)&dwData, &dwSize);\r
-\r
-    if (!dwRet && dwState == 1)\r
-    {\r
-      /* Value exists but browser is not integrated */\r
-      RegDeleteValueA(hKey, szIntegratedBrowser);\r
-    }\r
-    else if (dwRet && dwState == 2)\r
-    {\r
-      /* Browser is integrated but value does not exist */\r
-      dwData = TRUE;\r
-      RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,\r
-                     (LPBYTE)&dwData, sizeof(dwData));\r
-    }\r
-    RegCloseKey(hKey);\r
-  }\r
-  return dwState;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.278]\r
- *\r
- * Unicode version of SHCreateWorkerWindowA.\r
- */\r
-HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,\r
-                        DWORD dwStyle, HMENU hMenu, LONG z)\r
-{\r
-  static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };\r
-  WNDCLASSW wc;\r
-  HWND hWnd;\r
-\r
-  TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",\r
-         wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);\r
-\r
-  /* If our OS is natively ASCII, use the ASCII version */\r
-  if (!(GetVersion() & 0x80000000))  /* NT */\r
-    return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);\r
-\r
-  /* Create Window class */\r
-  wc.style         = 0;\r
-  wc.lpfnWndProc   = DefWindowProcW;\r
-  wc.cbClsExtra    = 0;\r
-  wc.cbWndExtra    = 4;\r
-  wc.hInstance     = shlwapi_hInstance;\r
-  wc.hIcon         = NULL;\r
-  wc.hCursor       = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);\r
-  wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;\r
-  wc.lpszMenuName  = NULL;\r
-  wc.lpszClassName = szClass;\r
-\r
-  SHRegisterClassW(&wc); /* Register class */\r
-\r
-  /* FIXME: Set extra bits in dwExStyle */\r
-\r
-  hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,\r
-                         hWndParent, hMenu, shlwapi_hInstance, 0);\r
-  if (hWnd)\r
-  {\r
-    SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);\r
-\r
-    if (wndProc)\r
-      SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);\r
-  }\r
-  return hWnd;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.279]\r
- *\r
- * Get and show a context menu from a shell folder.\r
- *\r
- * PARAMS\r
- *  hWnd           [I] Window displaying the shell folder\r
- *  lpFolder       [I] IShellFolder interface\r
- *  lpApidl        [I] Id for the particular folder desired\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: An HRESULT error code indicating the error.\r
- */\r
-HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)\r
-{\r
-  return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.281]\r
- *\r
- * _SHPackDispParamsV\r
- */\r
-HRESULT WINAPI SHPackDispParamsV(LPVOID w, LPVOID x, LPVOID y, LPVOID z)\r
-{\r
-       FIXME("%p %p %p %p\n",w,x,y,z);\r
-       return E_FAIL;\r
-}\r
-\r
-/*************************************************************************\r
- *      @       [SHLWAPI.282]\r
- *\r
- * This function seems to be a forward to SHPackDispParamsV (whatever THAT\r
- * function does...).\r
- */\r
-HRESULT WINAPI SHPackDispParams(LPVOID w, LPVOID x, LPVOID y, LPVOID z)\r
-{\r
-  FIXME("%p %p %p %p\n", w, x, y, z);\r
-  return E_FAIL;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.284]\r
- *\r
- * _IConnectionPoint_SimpleInvoke\r
- */\r
-DWORD WINAPI IConnectionPoint_SimpleInvoke(\r
-       LPVOID x,\r
-       LPVOID y,\r
-       LPVOID z)\r
-{\r
-        FIXME("(%p %p %p) stub\n",x,y,z);\r
-       return 0;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.285]\r
- *\r
- * Notify an IConnectionPoint object of changes.\r
- *\r
- * PARAMS\r
- *  lpCP   [I] Object to notify\r
- *  dispID [I]\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: E_NOINTERFACE, if lpCP is NULL or does not support the\r
- *           IConnectionPoint interface.\r
- */\r
-HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)\r
-{\r
-  IEnumConnections *lpEnum;\r
-  HRESULT hRet = E_NOINTERFACE;\r
-\r
-  TRACE("(%p,0x%8lX)\n", lpCP, dispID);\r
-\r
-  /* Get an enumerator for the connections */\r
-  if (lpCP)\r
-    hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);\r
-\r
-  if (SUCCEEDED(hRet))\r
-  {\r
-    IPropertyNotifySink *lpSink;\r
-    CONNECTDATA connData;\r
-    ULONG ulFetched;\r
-\r
-    /* Call OnChanged() for every notify sink in the connection point */\r
-    while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)\r
-    {\r
-      if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&\r
-          lpSink)\r
-      {\r
-        IPropertyNotifySink_OnChanged(lpSink, dispID);\r
-        IPropertyNotifySink_Release(lpSink);\r
-      }\r
-      IUnknown_Release(connData.pUnk);\r
-    }\r
-\r
-    IEnumConnections_Release(lpEnum);\r
-  }\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.287]\r
- *\r
- * Notify an IConnectionPointContainer object of changes.\r
- *\r
- * PARAMS\r
- *  lpUnknown [I] Object to notify\r
- *  dispID    [I]\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the\r
- *           IConnectionPointContainer interface.\r
- */\r
-HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)\r
-{\r
-  IConnectionPointContainer* lpCPC = NULL;\r
-  HRESULT hRet = E_NOINTERFACE;\r
-\r
-  TRACE("(%p,0x%8lX)\n", lpUnknown, dispID);\r
-\r
-  if (lpUnknown)\r
-    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);\r
-\r
-  if (SUCCEEDED(hRet))\r
-  {\r
-    IConnectionPoint* lpCP;\r
-\r
-    hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);\r
-    IConnectionPointContainer_Release(lpCPC);\r
-\r
-    hRet = IConnectionPoint_OnChanged(lpCP, dispID);\r
-    IConnectionPoint_Release(lpCP);\r
-  }\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.289]\r
- *\r
- * See PlaySoundW.\r
- */\r
-BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)\r
-{\r
-  GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);\r
-  return pPlaySoundW(pszSound, hmod, fdwSound);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.294]\r
- */\r
-BOOL WINAPI SHGetIniStringW(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len,  LPCSTR lpStr2)\r
-{\r
-    /*\r
-     * str1:           "I"     "I"     pushl esp+0x20\r
-     * str2:           "U"     "I"     pushl 0x77c93810\r
-     * (is "I" and "U" "integer" and "unsigned" ??)\r
-     *\r
-     * pStr:           ""      ""      pushl eax\r
-     * some_len:       0x824   0x104   pushl 0x824\r
-     * lpStr2:         "%l"    "%l"    pushl esp+0xc\r
-     *\r
-     * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);\r
-     * LocalAlloc(0x00, some_len) -> irrelevant_var\r
-     * LocalAlloc(0x40, irrelevant_len) -> pStr\r
-     * shlwapi.294(str1, str2, pStr, some_len, lpStr2);\r
-     * shlwapi.PathRemoveBlanksW(pStr);\r
-     */\r
-    FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);\r
-    return TRUE;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.295]\r
- *\r
- * Called by ICQ2000b install via SHDOCVW:\r
- * str1: "InternetShortcut"\r
- * x: some unknown pointer\r
- * str2: "http://free.aol.com/tryaolfree/index.adp?139269"\r
- * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"\r
- *\r
- * In short: this one maybe creates a desktop link :-)\r
- */\r
-BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)\r
-{\r
-    FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));\r
-    return TRUE;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.299]\r
- *\r
- * See COMCTL32_417.\r
- */\r
-BOOL WINAPI ExtTextOutWrapW(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,\r
-                         LPCWSTR str, UINT count, const INT *lpDx)\r
-{\r
-    GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);\r
-    return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.313]\r
- *\r
- * See SHGetFileInfoW.\r
- */\r
-DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,\r
-                         SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)\r
-{\r
-  GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);\r
-  return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.318]\r
- *\r
- * See DragQueryFileW.\r
- */\r
-UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)\r
-{\r
-  GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);\r
-  return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.333]\r
- *\r
- * See SHBrowseForFolderW.\r
- */\r
-LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)\r
-{\r
-  GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);\r
-  return pSHBrowseForFolderW(lpBi);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.334]\r
- *\r
- * See SHGetPathFromIDListW.\r
- */\r
-BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)\r
-{\r
-  GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);\r
-  return pSHGetPathFromIDListW(pidl, pszPath);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.335]\r
- *\r
- * See ShellExecuteExW.\r
- */\r
-BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)\r
-{\r
-  GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);\r
-  return pShellExecuteExW(lpExecInfo);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.336]\r
- *\r
- * See SHFileOperationW.\r
- */\r
-HICON WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)\r
-{\r
-  GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);\r
-  return pSHFileOperationW(lpFileOp);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.337]\r
- *\r
- * See ExtractIconExW.\r
- */\r
-UINT WINAPI ExtractIconExWrapW(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,\r
-                         HICON *phiconSmall, UINT nIcons)\r
-{\r
-  GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", 0);\r
-  return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.342]\r
- *\r
- */\r
-LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)\r
-{\r
-        return InterlockedCompareExchange(dest, xchg, compare);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.350]\r
- *\r
- * See GetFileVersionInfoSizeW.\r
- */\r
-DWORD WINAPI GetFileVersionInfoSizeWrapW(\r
-       LPWSTR x,\r
-       LPVOID y)\r
-{\r
-        DWORD ret;\r
-\r
-       GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);\r
-       ret = pGetFileVersionInfoSizeW(x, y);\r
-       return 0x208 + ret;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.351]\r
- *\r
- * See GetFileVersionInfoW.\r
- */\r
-BOOL  WINAPI GetFileVersionInfoWrapW(\r
-       LPWSTR w,   /* [in] path to dll */\r
-       DWORD  x,   /* [in] parm 2 to GetFileVersionInfoA */\r
-       DWORD  y,   /* [in] return value from SHLWAPI_350() - assume length */\r
-       LPVOID z)   /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA()) */\r
-{\r
-    GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);\r
-    return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.352]\r
- *\r
- * See VerQueryValueW.\r
- */\r
-WORD WINAPI VerQueryValueWrapW(\r
-       LPVOID w,   /* [in] Buffer from SHLWAPI_351() */\r
-       LPWSTR x,   /* [in]   Value to retrieve - converted and passed to VerQueryValueA() as #2 */\r
-       LPVOID y,   /* [out]  Ver buffer - passed to VerQueryValueA as #3 */\r
-       UINT*  z)   /* [in]   Ver length - passed to VerQueryValueA as #4 */\r
-{\r
-    GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);\r
-    return pVerQueryValueW((char*)w+0x208, x, y, z);\r
-}\r
-\r
-#define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))\r
-#define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB\r
-#define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.355]\r
- *\r
- * Change the modality of a shell object.\r
- *\r
- * PARAMS\r
- *  lpUnknown [I] Object to make modeless\r
- *  bModeless [I] TRUE=Make modeless, FALSE=Make modal\r
- *\r
- * RETURNS\r
- *  Success: S_OK. The modality lpUnknown is changed.\r
- *  Failure: An HRESULT error code indicating the error.\r
- *\r
- * NOTES\r
- *  lpUnknown must support the IOleInPlaceFrame interface, the\r
- *  IInternetSecurityMgrSite interface, the IShellBrowser interface\r
- *  or the IDocHostUIHandler interface, or this call fails.\r
- */\r
-HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)\r
-{\r
-  IUnknown *lpObj;\r
-  HRESULT hRet;\r
-\r
-  TRACE("(%p,%d)\n", lpUnknown, bModeless);\r
-\r
-  if (!lpUnknown)\r
-    return E_FAIL;\r
-\r
-  if (IsIface(IOleInPlaceFrame))\r
-    EnableModeless(IOleInPlaceFrame);\r
-  else if (IsIface(IShellBrowser))\r
-    EnableModeless(IShellBrowser);\r
-#if 0\r
-  /* FIXME: Wine has no headers for these objects yet */\r
-  else if (IsIface(IInternetSecurityMgrSite))\r
-    EnableModeless(IInternetSecurityMgrSite);\r
-  else if (IsIface(IDocHostUIHandler))\r
-    EnableModeless(IDocHostUIHandler);\r
-#endif\r
-  else\r
-    return hRet;\r
-\r
-  IUnknown_Release(lpObj);\r
-  return S_OK;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.357]\r
- *\r
- * See SHGetNewLinkInfoW.\r
- */\r
-BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,\r
-                        BOOL *pfMustCopy, UINT uFlags)\r
-{\r
-  GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);\r
-  return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.358]\r
- *\r
- * See SHDefExtractIconW.\r
- */\r
-UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,\r
-                         HICON* phiconSmall, UINT nIconSize)\r
-{\r
-  GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);\r
-  return pSHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.363]\r
- *\r
- * Get and show a context menu from a shell folder.\r
- *\r
- * PARAMS\r
- *  hWnd           [I] Window displaying the shell folder\r
- *  lpFolder       [I] IShellFolder interface\r
- *  lpApidl        [I] Id for the particular folder desired\r
- *  bInvokeDefault [I] Whether to invoke the default menu item\r
- *\r
- * RETURNS\r
- *  Success: S_OK. If bInvokeDefault is TRUE, the default menu action was\r
- *           executed.\r
- *  Failure: An HRESULT error code indicating the error.\r
- */\r
-HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)\r
-{\r
-  IContextMenu *iContext;\r
-  HRESULT hRet = E_FAIL;\r
-\r
-  TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);\r
-\r
-  if (!lpFolder)\r
-    return hRet;\r
-\r
-  /* Get the context menu from the shell folder */\r
-  hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,\r
-                                    &IID_IContextMenu, 0, (void**)&iContext);\r
-  if (SUCCEEDED(hRet))\r
-  {\r
-    HMENU hMenu;\r
-    if ((hMenu = CreatePopupMenu()))\r
-    {\r
-      HRESULT hQuery;\r
-      DWORD dwDefaultId = 0;\r
-\r
-      /* Add the context menu entries to the popup */\r
-      hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,\r
-                                             bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);\r
-\r
-      if (SUCCEEDED(hQuery))\r
-      {\r
-        if (bInvokeDefault &&\r
-            (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)\r
-        {\r
-          CMINVOKECOMMANDINFO cmIci;\r
-          /* Invoke the default item */\r
-          memset(&cmIci,0,sizeof(cmIci));\r
-          cmIci.cbSize = sizeof(cmIci);\r
-          cmIci.fMask = CMIC_MASK_ASYNCOK;\r
-          cmIci.hwnd = hWnd;\r
-          cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);\r
-          cmIci.nShow = SW_SCROLLCHILDREN;\r
-\r
-          hRet = IContextMenu_InvokeCommand(iContext, &cmIci);\r
-        }\r
-      }\r
-      DestroyMenu(hMenu);\r
-    }\r
-    IContextMenu_Release(iContext);\r
-  }\r
-  return hRet;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.370]\r
- *\r
- * See ExtractIconW.\r
- */\r
-HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,\r
-                         UINT nIconIndex)\r
-{\r
-  GET_FUNC(pExtractIconW, shell32, "ExtractIconW", NULL);\r
-  return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.376]\r
- */\r
-LANGID WINAPI MLGetUILanguage()\r
-{\r
-    FIXME("() stub\n");\r
-    /* FIXME: This should be a forward in the .spec file to the win2k function\r
-     * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.\r
-     */\r
-    return GetUserDefaultLangID();\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.377]\r
- *\r
- * Load a library from the directory of a particular process.\r
- *\r
- * PARAMS\r
- *  new_mod   [I] Library name\r
- *  inst_hwnd [I] Module whose directory is to be used\r
- *  dwFlags   [I] Flags controlling the load\r
- *\r
- * RETURNS\r
- *  Success: A handle to the loaded module\r
- *  Failure: A NULL handle.\r
- */\r
-HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)\r
-{\r
-  /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for\r
-   *        each call here.\r
-   * FIXME: Native shows calls to:\r
-   *  SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"\r
-   *                      CheckVersion\r
-   *  RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"\r
-   *  RegQueryValueExA for "LPKInstalled"\r
-   *  RegCloseKey\r
-   *  RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"\r
-   *  RegQueryValueExA for "ResourceLocale"\r
-   *  RegCloseKey\r
-   *  RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"\r
-   *  RegQueryValueExA for "Locale"\r
-   *  RegCloseKey\r
-   *  and then tests the Locale ("en" for me).\r
-   *     code below\r
-   *  after the code then a DPA_Create (first time) and DPA_InsertPtr are done.\r
-   */\r
-    CHAR mod_path[2*MAX_PATH];\r
-    LPSTR ptr;\r
-    DWORD len;\r
-\r
-    FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwFlags);\r
-    len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));\r
-    if (!len || len >= sizeof(mod_path)) return NULL;\r
-\r
-    ptr = strrchr(mod_path, '\\');\r
-    if (ptr) {\r
-       strcpy(ptr+1, new_mod);\r
-       TRACE("loading %s\n", debugstr_a(mod_path));\r
-       return LoadLibraryA(mod_path);\r
-    }\r
-    return NULL;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.378]\r
- *\r
- * Unicode version of MLLoadLibraryA.\r
- */\r
-HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)\r
-{\r
-    WCHAR mod_path[2*MAX_PATH];\r
-    LPWSTR ptr;\r
-    DWORD len;\r
-\r
-    FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwFlags);\r
-    len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));\r
-    if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;\r
-\r
-    ptr = strrchrW(mod_path, '\\');\r
-    if (ptr) {\r
-       strcpyW(ptr+1, new_mod);\r
-       TRACE("loading %s\n", debugstr_w(mod_path));\r
-       return LoadLibraryW(mod_path);\r
-    }\r
-    return NULL;\r
-}\r
-\r
-/*************************************************************************\r
- * ColorAdjustLuma      [SHLWAPI.@]\r
- *\r
- * Adjust the luminosity of a color\r
- *\r
- * PARAMS\r
- *  cRGB         [I] RGB value to convert\r
- *  dwLuma       [I] Luma adjustment\r
- *  bUnknown     [I] Unknown\r
- *\r
- * RETURNS\r
- *  The adjusted RGB color.\r
- */\r
-COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)\r
-{\r
-  TRACE("(0x%8lx,%d,%d)\n", cRGB, dwLuma, bUnknown);\r
-\r
-  if (dwLuma)\r
-  {\r
-    WORD wH, wL, wS;\r
-\r
-    ColorRGBToHLS(cRGB, &wH, &wL, &wS);\r
-\r
-    FIXME("Ignoring luma adjustment\n");\r
-\r
-    /* FIXME: The ajdustment is not linear */\r
-\r
-    cRGB = ColorHLSToRGB(wH, wL, wS);\r
-  }\r
-  return cRGB;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.389]\r
- *\r
- * See GetSaveFileNameW.\r
- */\r
-BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)\r
-{\r
-  GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);\r
-  return pGetSaveFileNameW(ofn);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.390]\r
- *\r
- * See WNetRestoreConnectionW.\r
- */\r
-DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)\r
-{\r
-  GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);\r
-  return pWNetRestoreConnectionW(hwndOwner, lpszDevice);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.391]\r
- *\r
- * See WNetGetLastErrorW.\r
- */\r
-DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,\r
-                         LPWSTR lpNameBuf, DWORD nNameBufSize)\r
-{\r
-  GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);\r
-  return pWNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.401]\r
- *\r
- * See PageSetupDlgW.\r
- */\r
-BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)\r
-{\r
-  GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);\r
-  return pPageSetupDlgW(pagedlg);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.402]\r
- *\r
- * See PrintDlgW.\r
- */\r
-BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)\r
-{\r
-  GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);\r
-  return pPrintDlgW(printdlg);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.403]\r
- *\r
- * See GetOpenFileNameW.\r
- */\r
-BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)\r
-{\r
-  GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);\r
-  return pGetOpenFileNameW(ofn);\r
-}\r
-\r
-/* INTERNAL: Map from HLS color space to RGB */\r
-static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)\r
-{\r
-  wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;\r
-\r
-  if (wHue > 160)\r
-    return wMid1;\r
-  else if (wHue > 120)\r
-    wHue = 160 - wHue;\r
-  else if (wHue > 40)\r
-    return wMid2;\r
-\r
-  return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;\r
-}\r
-\r
-/* Convert to RGB and scale into RGB range (0..255) */\r
-#define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240\r
-\r
-/*************************************************************************\r
- *      ColorHLSToRGB  [SHLWAPI.@]\r
- *\r
- * Convert from hls color space into an rgb COLORREF.\r
- *\r
- * PARAMS\r
- *  wHue        [I] Hue amount\r
- *  wLuminosity [I] Luminosity amount\r
- *  wSaturation [I] Saturation amount\r
- *\r
- * RETURNS\r
- *  A COLORREF representing the converted color.\r
- *\r
- * NOTES\r
- *  Input hls values are constrained to the range (0..240).\r
- */\r
-COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)\r
-{\r
-  WORD wRed;\r
-\r
-  if (wSaturation)\r
-  {\r
-    WORD wGreen, wBlue, wMid1, wMid2;\r
-\r
-    if (wLuminosity > 120)\r
-      wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;\r
-    else\r
-      wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;\r
-\r
-    wMid1 = wLuminosity * 2 - wMid2;\r
-\r
-    wRed   = GET_RGB(wHue + 80);\r
-    wGreen = GET_RGB(wHue);\r
-    wBlue  = GET_RGB(wHue - 80);\r
-\r
-    return RGB(wRed, wGreen, wBlue);\r
-  }\r
-\r
-  wRed = wLuminosity * 255 / 240;\r
-  return RGB(wRed, wRed, wRed);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.413]\r
- *\r
- * Get the current docking status of the system.\r
- *\r
- * PARAMS\r
- *  dwFlags [I] DOCKINFO_ flags from "winbase.h", unused\r
- *\r
- * RETURNS\r
- *  One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not\r
- *  a notebook.\r
- */\r
-DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)\r
-{\r
-  HW_PROFILE_INFOA hwInfo;\r
-\r
-  TRACE("(0x%08lx)\n", dwFlags);\r
-\r
-  GetCurrentHwProfileA(&hwInfo);\r
-  switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))\r
-  {\r
-  case DOCKINFO_DOCKED:\r
-  case DOCKINFO_UNDOCKED:\r
-    return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);\r
-  default:\r
-    return 0;\r
-  }\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.418]\r
- *\r
- * Function seems to do FreeLibrary plus other things.\r
- *\r
- * FIXME native shows the following calls:\r
- *   RtlEnterCriticalSection\r
- *   LocalFree\r
- *   GetProcAddress(Comctl32??, 150L)\r
- *   DPA_DeletePtr\r
- *   RtlLeaveCriticalSection\r
- *  followed by the FreeLibrary.\r
- *  The above code may be related to .377 above.\r
- */\r
-BOOL WINAPI MLFreeLibrary(HMODULE hModule)\r
-{\r
-       FIXME("(%p) semi-stub\n", hModule);\r
-       return FreeLibrary(hModule);\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.419]\r
- */\r
-BOOL WINAPI SHFlushSFCacheWrap(void) {\r
-  FIXME(": stub\n");\r
-  return TRUE;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.429]\r
- * FIXME I have no idea what this function does or what its arguments are.\r
- */\r
-BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)\r
-{\r
-       FIXME("(%p) stub\n", hInst);\r
-       return FALSE;\r
-}\r
-\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.430]\r
- */\r
-DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)\r
-{\r
-       FIXME("(%p,%p) stub\n", hInst, hHeap);\r
-       return E_FAIL;   /* This is what is used if shlwapi not loaded */\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.431]\r
- */\r
-DWORD WINAPI MLClearMLHInstance(DWORD x)\r
-{\r
-       FIXME("(0x%08lx)stub\n", x);\r
-       return 0xabba1247;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.436]\r
- *\r
- * Convert an Unicode string CLSID into a CLSID.\r
- *\r
- * PARAMS\r
- *  idstr      [I]   string containing a CLSID in text form\r
- *  id         [O]   CLSID extracted from the string\r
- *\r
- * RETURNS\r
- *  S_OK on success or E_INVALIDARG on failure\r
- *\r
- * NOTES\r
- *  This is really CLSIDFromString() which is exported by ole32.dll,\r
- *  however the native shlwapi.dll does *not* import ole32. Nor does\r
- *  ole32.dll import this ordinal from shlwapi. Therefore we must conclude\r
- *  that MS duplicated the code for CLSIDFromString(), and yes they did, only\r
- *  it returns an E_INVALIDARG error code on failure.\r
- *  This is a duplicate (with changes for Unicode) of CLSIDFromString16()\r
- *  in "dlls/ole32/compobj.c".\r
- */\r
-HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)\r
-{\r
-       LPCWSTR s = idstr;\r
-       BYTE *p;\r
-       INT i;\r
-       WCHAR table[256];\r
-\r
-       if (!s) {\r
-         memset(id, 0, sizeof(CLSID));\r
-         return S_OK;\r
-       }\r
-       else {  /* validate the CLSID string */\r
-\r
-         if (strlenW(s) != 38)\r
-           return E_INVALIDARG;\r
-\r
-         if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))\r
-           return E_INVALIDARG;\r
-\r
-         for (i=1; i<37; i++)\r
-         {\r
-           if ((i == 9)||(i == 14)||(i == 19)||(i == 24))\r
-             continue;\r
-           if (!(((s[i] >= L'0') && (s[i] <= L'9'))  ||\r
-               ((s[i] >= L'a') && (s[i] <= L'f'))  ||\r
-               ((s[i] >= L'A') && (s[i] <= L'F')))\r
-              )\r
-             return E_INVALIDARG;\r
-         }\r
-       }\r
-\r
-    TRACE("%s -> %p\n", debugstr_w(s), id);\r
-\r
-  /* quick lookup table */\r
-    memset(table, 0, 256*sizeof(WCHAR));\r
-\r
-    for (i = 0; i < 10; i++) {\r
-       table['0' + i] = i;\r
-    }\r
-    for (i = 0; i < 6; i++) {\r
-       table['A' + i] = i+10;\r
-       table['a' + i] = i+10;\r
-    }\r
-\r
-    /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */\r
-\r
-    p = (BYTE *) id;\r
-\r
-    s++;       /* skip leading brace  */\r
-    for (i = 0; i < 4; i++) {\r
-       p[3 - i] = table[*s]<<4 | table[*(s+1)];\r
-       s += 2;\r
-    }\r
-    p += 4;\r
-    s++;       /* skip - */\r
-\r
-    for (i = 0; i < 2; i++) {\r
-       p[1-i] = table[*s]<<4 | table[*(s+1)];\r
-       s += 2;\r
-    }\r
-    p += 2;\r
-    s++;       /* skip - */\r
-\r
-    for (i = 0; i < 2; i++) {\r
-       p[1-i] = table[*s]<<4 | table[*(s+1)];\r
-       s += 2;\r
-    }\r
-    p += 2;\r
-    s++;       /* skip - */\r
-\r
-    /* these are just sequential bytes */\r
-    for (i = 0; i < 2; i++) {\r
-       *p++ = table[*s]<<4 | table[*(s+1)];\r
-       s += 2;\r
-    }\r
-    s++;       /* skip - */\r
-\r
-    for (i = 0; i < 6; i++) {\r
-       *p++ = table[*s]<<4 | table[*(s+1)];\r
-       s += 2;\r
-    }\r
-\r
-    return S_OK;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.437]\r
- *\r
- * Determine if the OS supports a given feature.\r
- *\r
- * PARAMS\r
- *  dwFeature [I] Feature requested (undocumented)\r
- *\r
- * RETURNS\r
- *  TRUE  If the feature is available.\r
- *  FALSE If the feature is not available.\r
- */\r
-BOOL WINAPI IsOS(DWORD feature)\r
-{\r
-    OSVERSIONINFOA osvi;\r
-    DWORD platform, majorv, minorv;\r
-\r
-    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);\r
-    if(!GetVersionExA(&osvi))  {\r
-        ERR("GetVersionEx failed");\r
-        return FALSE;\r
-    }\r
-\r
-    majorv = osvi.dwMajorVersion;\r
-    minorv = osvi.dwMinorVersion;\r
-    platform = osvi.dwPlatformId;\r
-\r
-#define ISOS_RETURN(x) \\r
-    TRACE("(0x%lx) ret=%d\n",feature,(x)); \\r
-    return (x);\r
-\r
-    switch(feature)  {\r
-    case OS_WIN32SORGREATER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32s\r
-                 || platform == VER_PLATFORM_WIN32_WINDOWS)\r
-    case OS_NT:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)\r
-    case OS_WIN95ORGREATER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)\r
-    case OS_NT4ORGREATER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)\r
-    case OS_WIN2000ORGREATER_ALT:\r
-    case OS_WIN2000ORGREATER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)\r
-    case OS_WIN98ORGREATER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)\r
-    case OS_WIN98_GOLD:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)\r
-    case OS_WIN2000PRO:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)\r
-    case OS_WIN2000SERVER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))\r
-    case OS_WIN2000ADVSERVER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))\r
-    case OS_WIN2000DATACENTER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))\r
-    case OS_WIN2000TERMINAL:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))\r
-    case OS_EMBEDDED:\r
-        FIXME("(OS_EMBEDDED) What should we return here?\n");\r
-        return FALSE;\r
-    case OS_TERMINALCLIENT:\r
-        FIXME("(OS_TERMINALCLIENT) What should we return here?\n");\r
-        return FALSE;\r
-    case OS_TERMINALREMOTEADMIN:\r
-        FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");\r
-        return FALSE;\r
-    case OS_WIN95_GOLD:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)\r
-    case OS_MEORGREATER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)\r
-    case OS_XPORGREATER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)\r
-    case OS_HOME:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)\r
-    case OS_PROFESSIONAL:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) \r
-    case OS_DATACENTER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)\r
-    case OS_ADVSERVER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)\r
-    case OS_SERVER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)\r
-    case OS_TERMINALSERVER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)\r
-    case OS_PERSONALTERMINALSERVER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)\r
-    case OS_FASTUSERSWITCHING:\r
-        FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");\r
-        return TRUE;\r
-    case OS_WELCOMELOGONUI:\r
-        FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");\r
-        return FALSE;\r
-    case OS_DOMAINMEMBER:\r
-        FIXME("(OS_DOMAINMEMBER) What should we return here?\n");\r
-        return TRUE;\r
-    case OS_ANYSERVER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)\r
-    case OS_WOW6432:\r
-        FIXME("(OS_WOW6432) Should we check this?\n");\r
-        return FALSE;\r
-    case OS_WEBSERVER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)\r
-    case OS_SMALLBUSINESSSERVER:\r
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)\r
-    case OS_TABLETPC:\r
-        FIXME("(OS_TABLEPC) What should we return here?\n");\r
-        return FALSE;\r
-    case OS_SERVERADMINUI:\r
-        FIXME("(OS_SERVERADMINUI) What should we return here?\n");\r
-        return FALSE;\r
-    case OS_MEDIACENTER:\r
-        FIXME("(OS_MEDIACENTER) What should we return here?\n");\r
-        return FALSE;\r
-    case OS_APPLIANCE:\r
-        FIXME("(OS_APPLIANCE) What should we return here?\n");\r
-        return FALSE;\r
-    }\r
-\r
-#undef ISOS_RETURN\r
-\r
-    WARN("(0x%lx) unknown parameter\n",feature);\r
-\r
-    return FALSE;\r
-}\r
-\r
-/*************************************************************************\r
- *      ColorRGBToHLS  [SHLWAPI.@]\r
- *\r
- * Convert an rgb COLORREF into the hls color space.\r
- *\r
- * PARAMS\r
- *  cRGB         [I] Source rgb value\r
- *  pwHue        [O] Destination for converted hue\r
- *  pwLuminance  [O] Destination for converted luminance\r
- *  pwSaturation [O] Destination for converted saturation\r
- *\r
- * RETURNS\r
- *  Nothing. pwHue, pwLuminance and pwSaturation are set to the converted\r
- *  values.\r
- *\r
- * NOTES\r
- *  Output HLS values are constrained to the range (0..240).\r
- *  For Achromatic conversions, Hue is set to 160.\r
- */\r
-VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,\r
-                         LPWORD pwLuminance, LPWORD pwSaturation)\r
-{\r
-  int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;\r
-\r
-  TRACE("(%08lx,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);\r
-\r
-  wR = GetRValue(cRGB);\r
-  wG = GetGValue(cRGB);\r
-  wB = GetBValue(cRGB);\r
-\r
-  wMax = max(wR, max(wG, wB));\r
-  wMin = min(wR, min(wG, wB));\r
-\r
-  /* Luminosity */\r
-  wLuminosity = ((wMax + wMin) * 240 + 255) / 510;\r
-\r
-  if (wMax == wMin)\r
-  {\r
-    /* Achromatic case */\r
-    wSaturation = 0;\r
-    /* Hue is now unrepresentable, but this is what native returns... */\r
-    wHue = 160;\r
-  }\r
-  else\r
-  {\r
-    /* Chromatic case */\r
-    int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;\r
-\r
-    /* Saturation */\r
-    if (wLuminosity <= 120)\r
-      wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);\r
-    else\r
-      wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);\r
-\r
-    /* Hue */\r
-    wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;\r
-    wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;\r
-    wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;\r
-\r
-    if (wR == wMax)\r
-      wHue = wBNorm - wGNorm;\r
-    else if (wG == wMax)\r
-      wHue = 80 + wRNorm - wBNorm;\r
-    else\r
-      wHue = 160 + wGNorm - wRNorm;\r
-    if (wHue < 0)\r
-      wHue += 240;\r
-    else if (wHue > 240)\r
-      wHue -= 240;\r
-  }\r
-  if (pwHue)\r
-    *pwHue = wHue;\r
-  if (pwLuminance)\r
-    *pwLuminance = wLuminosity;\r
-  if (pwSaturation)\r
-    *pwSaturation = wSaturation;\r
-}\r
-\r
-/*************************************************************************\r
- *      SHCreateShellPalette   [SHLWAPI.@]\r
- */\r
-HPALETTE WINAPI SHCreateShellPalette(HDC hdc)\r
-{\r
-       FIXME("stub\n");\r
-       return CreateHalftonePalette(hdc);\r
-}\r
-\r
-/*************************************************************************\r
- *     SHGetInverseCMAP (SHLWAPI.@)\r
- *\r
- * Get an inverse color map table.\r
- *\r
- * PARAMS\r
- *  lpCmap  [O] Destination for color map\r
- *  dwSize  [I] Size of memory pointed to by lpCmap\r
- *\r
- * RETURNS\r
- *  Success: S_OK.\r
- *  Failure: E_POINTER,    If lpCmap is invalid.\r
- *           E_INVALIDARG, If dwFlags is invalid\r
- *           E_OUTOFMEMORY, If there is no memory available\r
- *\r
- * NOTES\r
- *  dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).\r
- *  If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's\r
- *  internal CMap.\r
- *  If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from\r
- *  this DLL's internal CMap.\r
- */\r
-HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)\r
-{\r
-    if (dwSize == 4) {\r
-       FIXME(" - returning bogus address for SHGetInverseCMAP\n");\r
-       *dest = (DWORD)0xabba1249;\r
-       return 0;\r
-    }\r
-    FIXME("(%p, %#lx) stub\n", dest, dwSize);\r
-    return 0;\r
-}\r
-\r
-/*************************************************************************\r
- *      SHIsLowMemoryMachine   [SHLWAPI.@]\r
- *\r
- * Determine if the current computer has low memory.\r
- *\r
- * PARAMS\r
- *  x [I] FIXME\r
- *\r
- * RETURNS\r
- *  TRUE if the users machine has 16 Megabytes of memory or less,\r
- *  FALSE otherwise.\r
- */\r
-BOOL WINAPI SHIsLowMemoryMachine (DWORD x)\r
-{\r
-  FIXME("(0x%08lx) stub\n", x);\r
-  return FALSE;\r
-}\r
-\r
-/*************************************************************************\r
- *      GetMenuPosFromID       [SHLWAPI.@]\r
- *\r
- * Return the position of a menu item from its Id.\r
- *\r
- * PARAMS\r
- *   hMenu [I] Menu containing the item\r
- *   wID   [I] Id of the menu item\r
- *\r
- * RETURNS\r
- *  Success: The index of the menu item in hMenu.\r
- *  Failure: -1, If the item is not found.\r
- */\r
-INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)\r
-{\r
- MENUITEMINFOA mi;\r
- INT nCount = GetMenuItemCount(hMenu), nIter = 0;\r
-\r
- while (nIter < nCount)\r
- {\r
-   mi.wID = 0;\r
-   if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)\r
-     return nIter;\r
-   nIter++;\r
- }\r
- return -1;\r
-}\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.179]\r
- *\r
- * Same as SHLWAPI.GetMenuPosFromID\r
- */\r
-DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)\r
-{\r
-    return GetMenuPosFromID(hMenu, uID);\r
-}\r
-\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.448]\r
- */\r
-VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)\r
-{\r
-    while (*lpwstr)\r
-    {\r
-        if (*lpwstr == '/')\r
-            *lpwstr = '\\';\r
-        lpwstr++;\r
-    }\r
-}\r
-\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.461]\r
- */\r
-DWORD WINAPI SHGetAppCompatFlags(DWORD Unknown)\r
-{\r
-  FIXME("stub\n");\r
-  return 0;\r
-}\r
-\r
-\r
-/*************************************************************************\r
- *      @      [SHLWAPI.549]\r
- */\r
-HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,\r
-                                    DWORD dwClsContext, REFIID iid, LPVOID *ppv)\r
-{\r
-    return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);\r
-}\r
-\r
-/*************************************************************************\r
- * SHSkipJunction      [SHLWAPI.@]\r
- *\r
- * Determine if a bind context can be bound to an object\r
- *\r
- * PARAMS\r
- *  pbc    [I] Bind context to check\r
- *  pclsid [I] CLSID of object to be bound to\r
- *\r
- * RETURNS\r
- *  TRUE: If it is safe to bind\r
- *  FALSE: If pbc is invalid or binding would not be safe\r
- *\r
- */\r
-BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)\r
-{\r
-  static const WCHAR szSkipBinding[] = { 'S','k','i','p',' ',\r
-    'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };\r
-  BOOL bRet = FALSE;\r
-\r
-  if (pbc)\r
-  {\r
-    IUnknown* lpUnk;\r
-\r
-    if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)szSkipBinding, &lpUnk)))\r
-    {\r
-      CLSID clsid;\r
-\r
-      if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&\r
-          IsEqualGUID(pclsid, &clsid))\r
-        bRet = TRUE;\r
-\r
-      IUnknown_Release(lpUnk);\r
-    }\r
-  }\r
-  return bRet;\r
-}\r
-\r
-/***********************************************************************\r
- *             SHGetShellKey (SHLWAPI.@)\r
- */\r
-DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)\r
-{\r
-    FIXME("(%lx, %lx, %lx): stub\n", a, b, c);\r
-    return 0x50;\r
-}\r
-\r
-/***********************************************************************\r
- *             SHQueueUserWorkItem (SHLWAPI.@)\r
- */\r
-HRESULT WINAPI SHQueueUserWorkItem(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f, DWORD g)\r
-{\r
-    FIXME("(%lx, %lx, %lx, %lx, %lx, %lx, %lx): stub\n", a, b, c, d, e, f, g);\r
-    return E_FAIL;\r
-}\r
-\r
-/***********************************************************************\r
- *             IUnknown_OnFocusChangeIS (SHLWAPI.@)\r
- */\r
-DWORD WINAPI IUnknown_OnFocusChangeIS(IUnknown * pUnk, IUnknown * pFocusObject, BOOL bChange)\r
-{\r
-    FIXME("(%p, %p, %s)\n", pUnk, pFocusObject, bChange ? "TRUE" : "FALSE");\r
-\r
-/*\r
-    IInputObjectSite * pIOS = NULL;\r
-    if (SUCCEEDED(IUnknown_QueryInterface(pUnk, &IID_IInputObjectSite, (void **)&pIOS))\r
-        IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bChange);\r
-*/\r
-\r
-    return 0;\r
-}\r
-\r
-/***********************************************************************\r
- *             SHGetValueW (SHLWAPI.@)\r
- */\r
-HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)\r
-{\r
-    FIXME("(%lx, %s, %s, %lx, %lx, %lx): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);\r
-    return E_FAIL;\r
-}\r
-\r
-typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);\r
-\r
-/***********************************************************************\r
- *              GetUIVersion (SHLWAPI.452)\r
- */\r
-DWORD WINAPI GetUIVersion(void)\r
-{\r
-    static DWORD version;\r
-\r
-    if (!version)\r
-    {\r
-        DllGetVersion_func pDllGetVersion;\r
-        HMODULE dll = LoadLibraryA("shell32.dll");\r
-        if (!dll) return 0;\r
-\r
-        pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");\r
-        if (pDllGetVersion)\r
-        {\r
-            DLLVERSIONINFO dvi;\r
-            dvi.cbSize = sizeof(DLLVERSIONINFO);\r
-            if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;\r
-        }\r
-        FreeLibrary( dll );\r
-        if (!version) version = 3;  /* old shell dlls don't have DllGetVersion */\r
-    }\r
-    return version;\r
-}\r
+/*
+ * SHLWAPI ordinal functions
+ *
+ * Copyright 1997 Marcus Meissner
+ *           1998 Jürgen Schmied
+ *           2001-2003 Jon Griffiths
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define COM_NO_WINDOWS_H
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#define COBJMACROS
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "objbase.h"
+#include "docobj.h"
+#include "exdisp.h"
+#include "shlguid.h"
+#include "wingdi.h"
+#include "shlobj.h"
+#include "shellapi.h"
+#include "commdlg.h"
+#include "wine/unicode.h"
+#include "winreg.h"
+#include "wine/debug.h"
+#include "shlwapi.h"
+
+
+WINE_DEFAULT_DEBUG_CHANNEL(shell);
+
+/* Get a function pointer from a DLL handle */
+#define GET_FUNC(func, module, name, fail) \
+  do { \
+    if (!func) { \
+      if (!SHLWAPI_h##module && !(SHLWAPI_h##module = LoadLibraryA(#module ".dll"))) return fail; \
+      func = (fn##func)GetProcAddress(SHLWAPI_h##module, name); \
+      if (!func) return fail; \
+    } \
+  } while (0)
+
+/* DLL handles for late bound calls */
+extern HINSTANCE shlwapi_hInstance;
+extern HMODULE SHLWAPI_hshell32;
+extern HMODULE SHLWAPI_hwinmm;
+extern HMODULE SHLWAPI_hcomdlg32;
+extern HMODULE SHLWAPI_hcomctl32;
+extern HMODULE SHLWAPI_hmpr;
+extern HMODULE SHLWAPI_hurlmon;
+extern HMODULE SHLWAPI_hversion;
+
+extern DWORD SHLWAPI_ThreadRef_index;
+
+/* following is GUID for IObjectWithSite::SetSite  -- see _174           */
+static DWORD id1[4] = {0xfc4801a3, 0x11cf2ba9, 0xaa0029a2, 0x52733d00};
+/* following is GUID for IPersistMoniker::GetClassID  -- see _174        */
+static DWORD id2[4] = {0x79eac9ee, 0x11cebaf9, 0xaa00828c, 0x0ba94b00};
+
+/* Function pointers for GET_FUNC macro; these need to be global because of gcc bug */
+typedef LPITEMIDLIST (WINAPI *fnpSHBrowseForFolderW)(LPBROWSEINFOW);
+static  fnpSHBrowseForFolderW pSHBrowseForFolderW;
+typedef BOOL    (WINAPI *fnpPlaySoundW)(LPCWSTR, HMODULE, DWORD);
+static  fnpPlaySoundW pPlaySoundW;
+typedef DWORD   (WINAPI *fnpSHGetFileInfoW)(LPCWSTR,DWORD,SHFILEINFOW*,UINT,UINT);
+static  fnpSHGetFileInfoW pSHGetFileInfoW;
+typedef UINT    (WINAPI *fnpDragQueryFileW)(HDROP, UINT, LPWSTR, UINT);
+static  fnpDragQueryFileW pDragQueryFileW;
+typedef BOOL    (WINAPI *fnpSHGetPathFromIDListW)(LPCITEMIDLIST, LPWSTR);
+static  fnpSHGetPathFromIDListW pSHGetPathFromIDListW;
+typedef BOOL    (WINAPI *fnpShellExecuteExW)(LPSHELLEXECUTEINFOW);
+static  fnpShellExecuteExW pShellExecuteExW;
+typedef HICON   (WINAPI *fnpSHFileOperationW)(LPSHFILEOPSTRUCTW);
+static  fnpSHFileOperationW pSHFileOperationW;
+typedef UINT    (WINAPI *fnpExtractIconExW)(LPCWSTR, INT,HICON *,HICON *, UINT);
+static  fnpExtractIconExW pExtractIconExW;
+typedef BOOL    (WINAPI *fnpSHGetNewLinkInfoW)(LPCWSTR, LPCWSTR, LPCWSTR, BOOL*, UINT);
+static  fnpSHGetNewLinkInfoW pSHGetNewLinkInfoW;
+typedef HRESULT (WINAPI *fnpSHDefExtractIconW)(LPCWSTR, int, UINT, HICON*, HICON*, UINT);
+static  fnpSHDefExtractIconW pSHDefExtractIconW;
+typedef HICON   (WINAPI *fnpExtractIconW)(HINSTANCE, LPCWSTR, UINT);
+static  fnpExtractIconW pExtractIconW;
+typedef BOOL    (WINAPI *fnpGetSaveFileNameW)(LPOPENFILENAMEW);
+static  fnpGetSaveFileNameW pGetSaveFileNameW;
+typedef DWORD   (WINAPI *fnpWNetRestoreConnectionW)(HWND, LPWSTR);
+static  fnpWNetRestoreConnectionW pWNetRestoreConnectionW;
+typedef DWORD   (WINAPI *fnpWNetGetLastErrorW)(LPDWORD, LPWSTR, DWORD, LPWSTR, DWORD);
+static  fnpWNetGetLastErrorW pWNetGetLastErrorW;
+typedef BOOL    (WINAPI *fnpPageSetupDlgW)(LPPAGESETUPDLGW);
+static  fnpPageSetupDlgW pPageSetupDlgW;
+typedef BOOL    (WINAPI *fnpPrintDlgW)(LPPRINTDLGW);
+static  fnpPrintDlgW pPrintDlgW;
+typedef BOOL    (WINAPI *fnpGetOpenFileNameW)(LPOPENFILENAMEW);
+static  fnpGetOpenFileNameW pGetOpenFileNameW;
+typedef DWORD   (WINAPI *fnpGetFileVersionInfoSizeW)(LPCWSTR,LPDWORD);
+static  fnpGetFileVersionInfoSizeW pGetFileVersionInfoSizeW;
+typedef BOOL    (WINAPI *fnpGetFileVersionInfoW)(LPCWSTR,DWORD,DWORD,LPVOID);
+static  fnpGetFileVersionInfoW pGetFileVersionInfoW;
+typedef WORD    (WINAPI *fnpVerQueryValueW)(LPVOID,LPCWSTR,LPVOID*,UINT*);
+static  fnpVerQueryValueW pVerQueryValueW;
+typedef BOOL    (WINAPI *fnpCOMCTL32_417)(HDC,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
+static  fnpCOMCTL32_417 pCOMCTL32_417;
+typedef HRESULT (WINAPI *fnpDllGetVersion)(DLLVERSIONINFO*);
+static  fnpDllGetVersion pDllGetVersion;
+typedef HRESULT (WINAPI *fnpCreateFormatEnumerator)(UINT,FORMATETC*,IEnumFORMATETC**);
+static fnpCreateFormatEnumerator pCreateFormatEnumerator;
+typedef HRESULT (WINAPI *fnpRegisterFormatEnumerator)(LPBC,IEnumFORMATETC*,DWORD);
+static fnpRegisterFormatEnumerator pRegisterFormatEnumerator;
+
+HRESULT WINAPI IUnknown_QueryService(IUnknown*,REFGUID,REFIID,LPVOID*);
+HRESULT WINAPI SHInvokeCommand(HWND,IShellFolder*,LPCITEMIDLIST,BOOL);
+HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR,CLSID*);
+BOOL    WINAPI SHAboutInfoW(LPWSTR,DWORD);
+
+/*
+ NOTES: Most functions exported by ordinal seem to be superflous.
+ The reason for these functions to be there is to provide a wrapper
+ for unicode functions to provide these functions on systems without
+ unicode functions eg. win95/win98. Since we have such functions we just
+ call these. If running Wine with native DLLs, some late bound calls may
+ fail. However, it is better to implement the functions in the forward DLL
+ and recommend the builtin rather than reimplementing the calls here!
+*/
+
+/*************************************************************************
+ * SHLWAPI_DupSharedHandle
+ *
+ * Internal implemetation of SHLWAPI_11.
+ */
+static
+HANDLE WINAPI SHLWAPI_DupSharedHandle(HANDLE hShared, DWORD dwDstProcId,
+                                       DWORD dwSrcProcId, DWORD dwAccess,
+                                       DWORD dwOptions)
+{
+  HANDLE hDst, hSrc;
+  DWORD dwMyProcId = GetCurrentProcessId();
+  HANDLE hRet = NULL;
+
+  TRACE("(%p,%ld,%ld,%08lx,%08lx)\n", hShared, dwDstProcId, dwSrcProcId,
+        dwAccess, dwOptions);
+
+  /* Get dest process handle */
+  if (dwDstProcId == dwMyProcId)
+    hDst = GetCurrentProcess();
+  else
+    hDst = OpenProcess(PROCESS_DUP_HANDLE, 0, dwDstProcId);
+
+  if (hDst)
+  {
+    /* Get src process handle */
+    if (dwSrcProcId == dwMyProcId)
+      hSrc = GetCurrentProcess();
+    else
+      hSrc = OpenProcess(PROCESS_DUP_HANDLE, 0, dwSrcProcId);
+
+    if (hSrc)
+    {
+      /* Make handle available to dest process */
+      if (!DuplicateHandle(hDst, hShared, hSrc, &hRet,
+                           dwAccess, 0, dwOptions | DUPLICATE_SAME_ACCESS))
+        hRet = NULL;
+
+      if (dwSrcProcId != dwMyProcId)
+        CloseHandle(hSrc);
+    }
+
+    if (dwDstProcId != dwMyProcId)
+      CloseHandle(hDst);
+  }
+
+  TRACE("Returning handle %p\n", hRet);
+  return hRet;
+}
+
+/*************************************************************************
+ * @  [SHLWAPI.7]
+ *
+ * Create a block of sharable memory and initialise it with data.
+ *
+ * PARAMS
+ * lpvData  [I] Pointer to data to write
+ * dwSize   [I] Size of data
+ * dwProcId [I] ID of process owning data
+ *
+ * RETURNS
+ * Success: A shared memory handle
+ * Failure: NULL
+ *
+ * NOTES
+ * Ordinals 7-11 provide a set of calls to create shared memory between a
+ * group of processes. The shared memory is treated opaquely in that its size
+ * is not exposed to clients who map it. This is accomplished by storing
+ * the size of the map as the first DWORD of mapped data, and then offsetting
+ * the view pointer returned by this size.
+ *
+ */
+HANDLE WINAPI SHAllocShared(LPCVOID lpvData, DWORD dwSize, DWORD dwProcId)
+{
+  HANDLE hMap;
+  LPVOID pMapped;
+  HANDLE hRet = NULL;
+
+  TRACE("(%p,%ld,%ld)\n", lpvData, dwSize, dwProcId);
+
+  /* Create file mapping of the correct length */
+  hMap = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, FILE_MAP_READ, 0,
+                            dwSize + sizeof(dwSize), NULL);
+  if (!hMap)
+    return hRet;
+
+  /* Get a view in our process address space */
+  pMapped = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
+
+  if (pMapped)
+  {
+    /* Write size of data, followed by the data, to the view */
+    *((DWORD*)pMapped) = dwSize;
+    if (lpvData)
+      memcpy((char *) pMapped + sizeof(dwSize), lpvData, dwSize);
+
+    /* Release view. All further views mapped will be opaque */
+    UnmapViewOfFile(pMapped);
+    hRet = SHLWAPI_DupSharedHandle(hMap, dwProcId,
+                                   GetCurrentProcessId(), FILE_MAP_ALL_ACCESS,
+                                   DUPLICATE_SAME_ACCESS);
+  }
+
+  CloseHandle(hMap);
+  return hRet;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.8]
+ *
+ * Get a pointer to a block of shared memory from a shared memory handle.
+ *
+ * PARAMS
+ * hShared  [I] Shared memory handle
+ * dwProcId [I] ID of process owning hShared
+ *
+ * RETURNS
+ * Success: A pointer to the shared memory
+ * Failure: NULL
+ *
+ */
+PVOID WINAPI SHLockShared(HANDLE hShared, DWORD dwProcId)
+{
+  HANDLE hDup;
+  LPVOID pMapped;
+
+  TRACE("(%p %ld)\n", hShared, dwProcId);
+
+  /* Get handle to shared memory for current process */
+  hDup = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
+                                 FILE_MAP_ALL_ACCESS, 0);
+  /* Get View */
+  pMapped = MapViewOfFile(hDup, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
+  CloseHandle(hDup);
+
+  if (pMapped)
+    return (char *) pMapped + sizeof(DWORD); /* Hide size */
+  return NULL;
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.9]
+ *
+ * Release a pointer to a block of shared memory.
+ *
+ * PARAMS
+ * lpView [I] Shared memory pointer
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ */
+BOOL WINAPI SHUnlockShared(LPVOID lpView)
+{
+  TRACE("(%p)\n", lpView);
+  return UnmapViewOfFile((char *) lpView - sizeof(DWORD)); /* Include size */
+}
+
+/*************************************************************************
+ * @ [SHLWAPI.10]
+ *
+ * Destroy a block of sharable memory.
+ *
+ * PARAMS
+ * hShared  [I] Shared memory handle
+ * dwProcId [I] ID of process owning hShared
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ */
+BOOL WINAPI SHFreeShared(HANDLE hShared, DWORD dwProcId)
+{
+  HANDLE hClose;
+
+  TRACE("(%p %ld)\n", hShared, dwProcId);
+
+  /* Get a copy of the handle for our process, closing the source handle */
+  hClose = SHLWAPI_DupSharedHandle(hShared, dwProcId, GetCurrentProcessId(),
+                                   FILE_MAP_ALL_ACCESS,DUPLICATE_CLOSE_SOURCE);
+  /* Close local copy */
+  return CloseHandle(hClose);
+}
+
+/*************************************************************************
+ * @   [SHLWAPI.11]
+ *
+ * Copy a sharable memory handle from one process to another.
+ *
+ * PARAMS
+ * hShared     [I] Shared memory handle to duplicate
+ * dwDstProcId [I] ID of the process wanting the duplicated handle
+ * dwSrcProcId [I] ID of the process owning hShared
+ * dwAccess    [I] Desired DuplicateHandle() access
+ * dwOptions   [I] Desired DuplicateHandle() options
+ *
+ * RETURNS
+ * Success: A handle suitable for use by the dwDstProcId process.
+ * Failure: A NULL handle.
+ *
+ */
+HANDLE WINAPI SHMapHandle(HANDLE hShared, DWORD dwDstProcId, DWORD dwSrcProcId,
+                          DWORD dwAccess, DWORD dwOptions)
+{
+  HANDLE hRet;
+
+  hRet = SHLWAPI_DupSharedHandle(hShared, dwDstProcId, dwSrcProcId,
+                                 dwAccess, dwOptions);
+  return hRet;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.13]
+ *
+ * Create and register a clipboard enumerator for a web browser.
+ *
+ * PARAMS
+ *  lpBC      [I] Binding context
+ *  lpUnknown [I] An object exposing the IWebBrowserApp interface
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: An HRESULT error code.
+ *
+ * NOTES
+ *  The enumerator is stored as a property of the web browser. If it does not
+ *  yet exist, it is created and set before being registered.
+ */
+HRESULT WINAPI RegisterDefaultAcceptHeaders(LPBC lpBC, IUnknown *lpUnknown)
+{
+  static const WCHAR szProperty[] = { '{','D','0','F','C','A','4','2','0',
+      '-','D','3','F','5','-','1','1','C','F', '-','B','2','1','1','-','0',
+      '0','A','A','0','0','4','A','E','8','3','7','}','\0' };
+  IEnumFORMATETC* pIEnumFormatEtc = NULL;
+  VARIANTARG var;
+  HRESULT hRet;
+  IWebBrowserApp* pBrowser = NULL;
+
+  TRACE("(%p, %p)\n", lpBC, lpUnknown);
+
+  /* Get An IWebBrowserApp interface from  lpUnknown */
+  hRet = IUnknown_QueryService(lpUnknown, &IID_IWebBrowserApp, &IID_IWebBrowserApp, (PVOID)&pBrowser);
+  if (FAILED(hRet) || !pBrowser)
+    return E_NOINTERFACE;
+
+  V_VT(&var) = VT_EMPTY;
+
+  /* The property we get is the browsers clipboard enumerator */
+  hRet = IWebBrowserApp_GetProperty(pBrowser, (BSTR)szProperty, &var);
+  if (FAILED(hRet))
+    return hRet;
+
+  if (V_VT(&var) == VT_EMPTY)
+  {
+    /* Iterate through accepted documents and RegisterClipBoardFormatA() them */
+    char szKeyBuff[128], szValueBuff[128];
+    DWORD dwKeySize, dwValueSize, dwRet = 0, dwCount = 0, dwNumValues, dwType;
+    FORMATETC* formatList, *format;
+    HKEY hDocs;
+
+    TRACE("Registering formats and creating IEnumFORMATETC instance\n");
+
+    if (!RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\Current"
+                     "Version\\Internet Settings\\Accepted Documents", &hDocs))
+      return E_FAIL;
+
+    /* Get count of values in key */
+    while (!dwRet)
+    {
+      dwKeySize = sizeof(szKeyBuff);
+      dwRet = RegEnumValueA(hDocs,dwCount,szKeyBuff,&dwKeySize,0,&dwType,0,0);
+      dwCount++;
+    }
+
+    dwNumValues = dwCount;
+
+    /* Note: dwCount = number of items + 1; The extra item is the end node */
+    format = formatList = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(FORMATETC));
+    if (!formatList)
+      return E_OUTOFMEMORY;
+
+    if (dwNumValues > 1)
+    {
+      dwRet = 0;
+      dwCount = 0;
+
+      dwNumValues--;
+
+      /* Register clipboard formats for the values and populate format list */
+      while(!dwRet && dwCount < dwNumValues)
+      {
+        dwKeySize = sizeof(szKeyBuff);
+        dwValueSize = sizeof(szValueBuff);
+        dwRet = RegEnumValueA(hDocs, dwCount, szKeyBuff, &dwKeySize, 0, &dwType,
+                              (PBYTE)szValueBuff, &dwValueSize);
+        if (!dwRet)
+          return E_FAIL;
+
+        format->cfFormat = RegisterClipboardFormatA(szValueBuff);
+        format->ptd = NULL;
+        format->dwAspect = 1;
+        format->lindex = 4;
+        format->tymed = -1;
+
+        format++;
+        dwCount++;
+      }
+    }
+
+    /* Terminate the (maybe empty) list, last entry has a cfFormat of 0 */
+    format->cfFormat = 0;
+    format->ptd = NULL;
+    format->dwAspect = 1;
+    format->lindex = 4;
+    format->tymed = -1;
+
+    /* Create a clipboard enumerator */
+    GET_FUNC(pCreateFormatEnumerator, urlmon, "CreateFormatEnumerator", E_FAIL);
+    hRet = pCreateFormatEnumerator(dwNumValues, formatList, &pIEnumFormatEtc);
+
+    if (FAILED(hRet) || !pIEnumFormatEtc)
+      return hRet;
+
+    /* Set our enumerator as the browsers property */
+    V_VT(&var) = VT_UNKNOWN;
+    V_UNKNOWN(&var) = (IUnknown*)pIEnumFormatEtc;
+
+    hRet = IWebBrowserApp_PutProperty(pBrowser, (BSTR)szProperty, var);
+    if (FAILED(hRet))
+    {
+       IEnumFORMATETC_Release(pIEnumFormatEtc);
+       goto RegisterDefaultAcceptHeaders_Exit;
+    }
+  }
+
+  if (V_VT(&var) == VT_UNKNOWN)
+  {
+    /* Our variant is holding the clipboard enumerator */
+    IUnknown* pIUnknown = V_UNKNOWN(&var);
+    IEnumFORMATETC* pClone = NULL;
+
+    TRACE("Retrieved IEnumFORMATETC property\n");
+
+    /* Get an IEnumFormatEtc interface from the variants value */
+    pIEnumFormatEtc = NULL;
+    hRet = IUnknown_QueryInterface(pIUnknown, &IID_IEnumFORMATETC,
+                                   (PVOID)&pIEnumFormatEtc);
+    if (!hRet && pIEnumFormatEtc)
+    {
+      /* Clone and register the enumerator */
+      hRet = IEnumFORMATETC_Clone(pIEnumFormatEtc, &pClone);
+      if (!hRet && pClone)
+      {
+        GET_FUNC(pRegisterFormatEnumerator, urlmon, "RegisterFormatEnumerator", E_FAIL);
+        pRegisterFormatEnumerator(lpBC, pClone, 0);
+
+        IEnumFORMATETC_Release(pClone);
+      }
+
+      /* Release the IEnumFormatEtc interface */
+      IEnumFORMATETC_Release(pIUnknown);
+    }
+    IUnknown_Release(V_UNKNOWN(&var));
+  }
+
+RegisterDefaultAcceptHeaders_Exit:
+  IWebBrowserApp_Release(pBrowser);
+  return hRet;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.15]
+ *
+ * Get Explorers "AcceptLanguage" setting.
+ *
+ * PARAMS
+ *  langbuf [O] Destination for language string
+ *  buflen  [I] Length of langbuf
+ *          [0] Success: used length of langbuf
+ *
+ * RETURNS
+ *  Success: S_OK.   langbuf is set to the language string found.
+ *  Failure: E_FAIL, If any arguments are invalid, error occurred, or Explorer
+ *           does not contain the setting.
+ *           E_INVALIDARG, If the buffer is not big enough
+ */
+HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
+{
+    static const WCHAR szkeyW[] = {
+       'S','o','f','t','w','a','r','e','\\',
+       'M','i','c','r','o','s','o','f','t','\\',
+       'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
+       'I','n','t','e','r','n','a','t','i','o','n','a','l',0};
+    static const WCHAR valueW[] = {
+       'A','c','c','e','p','t','L','a','n','g','u','a','g','e',0};
+    static const WCHAR enusW[] = {'e','n','-','u','s',0};
+    DWORD mystrlen, mytype;
+    HKEY mykey;
+    HRESULT retval;
+    LCID mylcid;
+    WCHAR *mystr;
+
+    if(!langbuf || !buflen || !*buflen)
+       return E_FAIL;
+
+    mystrlen = (*buflen > 20) ? *buflen : 20 ;
+    mystr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * mystrlen);
+    RegOpenKeyW(HKEY_CURRENT_USER, szkeyW, &mykey);
+    if(RegQueryValueExW(mykey, valueW, 0, &mytype, (PBYTE)mystr, &mystrlen)) {
+        /* Did not find value */
+        mylcid = GetUserDefaultLCID();
+        /* somehow the mylcid translates into "en-us"
+         *  this is similar to "LOCALE_SABBREVLANGNAME"
+         *  which could be gotten via GetLocaleInfo.
+         *  The only problem is LOCALE_SABBREVLANGUAGE" is
+         *  a 3 char string (first 2 are country code and third is
+         *  letter for "sublanguage", which does not come close to
+         *  "en-us"
+         */
+        lstrcpyW(mystr, enusW);
+        mystrlen = lstrlenW(mystr);
+    } else {
+        /* handle returned string */
+        FIXME("missing code\n");
+    }
+    memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
+
+    if(*buflen > strlenW(mystr)) {
+       *buflen = strlenW(mystr);
+       retval = S_OK;
+    } else {
+       *buflen = 0;
+       retval = E_INVALIDARG;
+       SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    }
+    RegCloseKey(mykey);
+    HeapFree(GetProcessHeap(), 0, mystr);
+    return retval;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.14]
+ *
+ * Ascii version of GetAcceptLanguagesW.
+ */
+HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
+{
+    WCHAR *langbufW;
+    DWORD buflenW, convlen;
+    HRESULT retval;
+
+    if(!langbuf || !buflen || !*buflen) return E_FAIL;
+
+    buflenW = *buflen;
+    langbufW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * buflenW);
+    retval = GetAcceptLanguagesW(langbufW, &buflenW);
+
+    /* FIXME: this is wrong, the string may not be null-terminated */
+    convlen = WideCharToMultiByte(CP_ACP, 0, langbufW, -1, langbuf,
+                                  *buflen, NULL, NULL);
+    *buflen = buflenW ? convlen : 0;
+
+    HeapFree(GetProcessHeap(), 0, langbufW);
+    return retval;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.23]
+ *
+ * Convert a GUID to a string.
+ *
+ * PARAMS
+ *  guid     [I] GUID to convert
+ *  lpszDest [O] Destination for string
+ *  cchMax   [I] Length of output buffer
+ *
+ * RETURNS
+ *  The length of the string created.
+ */
+INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
+{
+  char xguid[40];
+  INT iLen;
+
+  TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
+
+  sprintf(xguid, "{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+          guid->Data1, guid->Data2, guid->Data3,
+          guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+          guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+
+  iLen = strlen(xguid) + 1;
+
+  if (iLen > cchMax)
+    return 0;
+  memcpy(lpszDest, xguid, iLen);
+  return iLen;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.24]
+ *
+ * Convert a GUID to a string.
+ *
+ * PARAMS
+ *  guid [I] GUID to convert
+ *  str  [O] Destination for string
+ *  cmax [I] Length of output buffer
+ *
+ * RETURNS
+ *  The length of the string created.
+ */
+INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
+{
+  WCHAR xguid[40];
+  INT iLen;
+  static const WCHAR wszFormat[] = {'{','%','0','8','l','X','-','%','0','4','X','-','%','0','4','X','-',
+      '%','0','2','X','%','0','2','X','-','%','0','2','X','%','0','2','X','%','0','2','X','%','0','2',
+      'X','%','0','2','X','%','0','2','X','}',0};
+
+  TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
+
+  sprintfW(xguid, wszFormat, guid->Data1, guid->Data2, guid->Data3,
+          guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
+          guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
+
+  iLen = strlenW(xguid) + 1;
+
+  if (iLen > cchMax)
+    return 0;
+  memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
+  return iLen;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.29]
+ *
+ * Determine if a Unicode character is a space.
+ *
+ * PARAMS
+ *  wc [I] Character to check.
+ *
+ * RETURNS
+ *  TRUE, if wc is a space,
+ *  FALSE otherwise.
+ */
+BOOL WINAPI IsCharSpaceW(WCHAR wc)
+{
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.30]
+ *
+ * Determine if a Unicode character is a blank.
+ *
+ * PARAMS
+ *  wc [I] Character to check.
+ *
+ * RETURNS
+ *  TRUE, if wc is a blank,
+ *  FALSE otherwise.
+ *
+ */
+BOOL WINAPI IsCharBlankW(WCHAR wc)
+{
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.31]
+ *
+ * Determine if a Unicode character is punctuation.
+ *
+ * PARAMS
+ *  wc [I] Character to check.
+ *
+ * RETURNS
+ *  TRUE, if wc is punctuation,
+ *  FALSE otherwise.
+ */
+BOOL WINAPI IsCharPunctW(WCHAR wc)
+{
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.32]
+ *
+ * Determine if a Unicode character is a control character.
+ *
+ * PARAMS
+ *  wc [I] Character to check.
+ *
+ * RETURNS
+ *  TRUE, if wc is a control character,
+ *  FALSE otherwise.
+ */
+BOOL WINAPI IsCharCntrlW(WCHAR wc)
+{
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.33]
+ *
+ * Determine if a Unicode character is a digit.
+ *
+ * PARAMS
+ *  wc [I] Character to check.
+ *
+ * RETURNS
+ *  TRUE, if wc is a digit,
+ *  FALSE otherwise.
+ */
+BOOL WINAPI IsCharDigitW(WCHAR wc)
+{
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.34]
+ *
+ * Determine if a Unicode character is a hex digit.
+ *
+ * PARAMS
+ *  wc [I] Character to check.
+ *
+ * RETURNS
+ *  TRUE, if wc is a hex digit,
+ *  FALSE otherwise.
+ */
+BOOL WINAPI IsCharXDigitW(WCHAR wc)
+{
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.35]
+ *
+ */
+BOOL WINAPI GetStringType3ExW(LPWSTR lpszStr, DWORD dwLen, LPVOID p3)
+{
+    FIXME("(%s,0x%08lx,%p): stub\n", debugstr_w(lpszStr), dwLen, p3);
+    return TRUE;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.36]
+ *
+ * Insert a bitmap menu item at the bottom of a menu.
+ *
+ * PARAMS
+ *  hMenu [I] Menu to insert into
+ *  flags [I] Flags for insertion
+ *  id    [I] Menu ID of the item
+ *  str   [I] Menu text for the item
+ *
+ * RETURNS
+ *  Success: TRUE,  the item is inserted into the menu
+ *  Failure: FALSE, if any parameter is invalid
+ */
+BOOL WINAPI AppendMenuWrapW(HMENU hMenu, UINT flags, UINT id, LPCWSTR str)
+{
+    TRACE("(%p,0x%08x,0x%08x,%s)\n",hMenu, flags, id, debugstr_w(str));
+    return InsertMenuW(hMenu, -1, flags | MF_BITMAP, id, str);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.74]
+ *
+ * Get the text from a given dialog item.
+ *
+ * PARAMS
+ *  hWnd     [I] Handle of dialog
+ *  nItem    [I] Index of item
+ *  lpsDest  [O] Buffer for receiving window text
+ *  nDestLen [I] Length of buffer.
+ *
+ * RETURNS
+ *  Success: The length of the returned text.
+ *  Failure: 0.
+ */
+INT WINAPI GetDlgItemTextWrapW(HWND hWnd, INT nItem, LPWSTR lpsDest,INT nDestLen)
+{
+  HWND hItem = GetDlgItem(hWnd, nItem);
+
+  if (hItem)
+    return GetWindowTextW(hItem, lpsDest, nDestLen);
+  if (nDestLen)
+    *lpsDest = (WCHAR)'\0';
+  return 0;
+}
+
+/*************************************************************************
+ *      @   [SHLWAPI.138]
+ *
+ * Set the text of a given dialog item.
+ *
+ * PARAMS
+ *  hWnd     [I] Handle of dialog
+ *  iItem    [I] Index of item
+ *  lpszText [O] Text to set
+ *
+ * RETURNS
+ *  Success: TRUE.  The text of the dialog is set to lpszText.
+ *  Failure: FALSE, Otherwise.
+ */
+BOOL WINAPI SetDlgItemTextWrapW(HWND hWnd, INT iItem, LPCWSTR lpszText)
+{
+    HWND hWndItem = GetDlgItem(hWnd, iItem);
+    if (hWndItem)
+        return SetWindowTextW(hWndItem, lpszText);
+    return FALSE;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.151]
+ *
+ * Compare two Ascii strings up to a given length.
+ *
+ * PARAMS
+ *  lpszSrc [I] Source string
+ *  lpszCmp [I] String to compare to lpszSrc
+ *  len     [I] Maximum length
+ *
+ * RETURNS
+ *  A number greater than, less than or equal to 0 depending on whether
+ *  lpszSrc is greater than, less than or equal to lpszCmp.
+ */
+DWORD WINAPI StrCmpNCA(LPCSTR lpszSrc, LPCSTR lpszCmp, INT len)
+{
+    return strncmp(lpszSrc, lpszCmp, len);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.152]
+ *
+ * Unicode version of StrCmpNCA.
+ */
+DWORD WINAPI StrCmpNCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, INT len)
+{
+    return strncmpW(lpszSrc, lpszCmp, len);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.153]
+ *
+ * Compare two Ascii strings up to a given length, ignoring case.
+ *
+ * PARAMS
+ *  lpszSrc [I] Source string
+ *  lpszCmp [I] String to compare to lpszSrc
+ *  len     [I] Maximum length
+ *
+ * RETURNS
+ *  A number greater than, less than or equal to 0 depending on whether
+ *  lpszSrc is greater than, less than or equal to lpszCmp.
+ */
+DWORD WINAPI StrCmpNICA(LPCSTR lpszSrc, LPCSTR lpszCmp, DWORD len)
+{
+    return strncasecmp(lpszSrc, lpszCmp, len);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.154]
+ *
+ * Unicode version of StrCmpNICA.
+ */
+DWORD WINAPI StrCmpNICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp, DWORD len)
+{
+    return strncmpiW(lpszSrc, lpszCmp, len);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.155]
+ *
+ * Compare two Ascii strings.
+ *
+ * PARAMS
+ *  lpszSrc [I] Source string
+ *  lpszCmp [I] String to compare to lpszSrc
+ *
+ * RETURNS
+ *  A number greater than, less than or equal to 0 depending on whether
+ *  lpszSrc is greater than, less than or equal to lpszCmp.
+ */
+DWORD WINAPI StrCmpCA(LPCSTR lpszSrc, LPCSTR lpszCmp)
+{
+    return strcmp(lpszSrc, lpszCmp);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.156]
+ *
+ * Unicode version of StrCmpCA.
+ */
+DWORD WINAPI StrCmpCW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
+{
+    return strcmpW(lpszSrc, lpszCmp);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.157]
+ *
+ * Compare two Ascii strings, ignoring case.
+ *
+ * PARAMS
+ *  lpszSrc [I] Source string
+ *  lpszCmp [I] String to compare to lpszSrc
+ *
+ * RETURNS
+ *  A number greater than, less than or equal to 0 depending on whether
+ *  lpszSrc is greater than, less than or equal to lpszCmp.
+ */
+DWORD WINAPI StrCmpICA(LPCSTR lpszSrc, LPCSTR lpszCmp)
+{
+    return strcasecmp(lpszSrc, lpszCmp);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.158]
+ *
+ * Unicode version of StrCmpICA.
+ */
+DWORD WINAPI StrCmpICW(LPCWSTR lpszSrc, LPCWSTR lpszCmp)
+{
+    return strcmpiW(lpszSrc, lpszCmp);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.160]
+ *
+ * Get an identification string for the OS and explorer.
+ *
+ * PARAMS
+ *  lpszDest  [O] Destination for Id string
+ *  dwDestLen [I] Length of lpszDest
+ *
+ * RETURNS
+ *  TRUE,  If the string was created successfully
+ *  FALSE, Otherwise
+ */
+BOOL WINAPI SHAboutInfoA(LPSTR lpszDest, DWORD dwDestLen)
+{
+  WCHAR buff[2084];
+
+  TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
+
+  if (lpszDest && SHAboutInfoW(buff, dwDestLen))
+  {
+    WideCharToMultiByte(CP_ACP, 0, buff, -1, lpszDest, dwDestLen, NULL, NULL);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.161]
+ *
+ * Unicode version of SHAboutInfoA.
+ */
+BOOL WINAPI SHAboutInfoW(LPWSTR lpszDest, DWORD dwDestLen)
+{
+  static const WCHAR szIEKey[] = { 'S','O','F','T','W','A','R','E','\\',
+    'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
+    ' ','E','x','p','l','o','r','e','r','\0' };
+  static const WCHAR szWinNtKey[] = { 'S','O','F','T','W','A','R','E','\\',
+    'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',' ',
+    'N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
+  static const WCHAR szWinKey[] = { 'S','O','F','T','W','A','R','E','\\',
+    'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
+    'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\0' };
+  static const WCHAR szRegKey[] = { 'S','O','F','T','W','A','R','E','\\',
+    'M','i','c','r','o','s','o','f','t','\\','I','n','t','e','r','n','e','t',
+    ' ','E','x','p','l','o','r','e','r','\\',
+    'R','e','g','i','s','t','r','a','t','i','o','n','\0' };
+  static const WCHAR szVersion[] = { 'V','e','r','s','i','o','n','\0' };
+  static const WCHAR szCustomized[] = { 'C','u','s','t','o','m','i','z','e','d',
+    'V','e','r','s','i','o','n','\0' };
+  static const WCHAR szOwner[] = { 'R','e','g','i','s','t','e','r','e','d',
+    'O','w','n','e','r','\0' };
+  static const WCHAR szOrg[] = { 'R','e','g','i','s','t','e','r','e','d',
+    'O','r','g','a','n','i','z','a','t','i','o','n','\0' };
+  static const WCHAR szProduct[] = { 'P','r','o','d','u','c','t','I','d','\0' };
+  static const WCHAR szUpdate[] = { 'I','E','A','K',
+    'U','p','d','a','t','e','U','r','l','\0' };
+  static const WCHAR szHelp[] = { 'I','E','A','K',
+    'H','e','l','p','S','t','r','i','n','g','\0' };
+  WCHAR buff[2084];
+  HKEY hReg;
+  DWORD dwType, dwLen;
+
+  TRACE("(%p,%ld)\n", lpszDest, dwDestLen);
+
+  if (!lpszDest)
+    return FALSE;
+
+  *lpszDest = '\0';
+
+  /* Try the NT key first, followed by 95/98 key */
+  if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinNtKey, 0, KEY_READ, &hReg) &&
+      RegOpenKeyExW(HKEY_LOCAL_MACHINE, szWinKey, 0, KEY_READ, &hReg))
+    return FALSE;
+
+  /* OS Version */
+  buff[0] = '\0';
+  dwLen = 30;
+  if (!SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey, szVersion, &dwType, buff, &dwLen))
+  {
+    DWORD dwStrLen = strlenW(buff);
+    dwLen = 30 - dwStrLen;
+    SHGetValueW(HKEY_LOCAL_MACHINE, szIEKey,
+                szCustomized, &dwType, buff+dwStrLen, &dwLen);
+  }
+  StrCatBuffW(lpszDest, buff, dwDestLen);
+
+  /* ~Registered Owner */
+  buff[0] = '~';
+  dwLen = 256;
+  if (SHGetValueW(hReg, szOwner, 0, &dwType, buff+1, &dwLen))
+    buff[1] = '\0';
+  StrCatBuffW(lpszDest, buff, dwDestLen);
+
+  /* ~Registered Organization */
+  dwLen = 256;
+  if (SHGetValueW(hReg, szOrg, 0, &dwType, buff+1, &dwLen))
+    buff[1] = '\0';
+  StrCatBuffW(lpszDest, buff, dwDestLen);
+
+  /* FIXME: Not sure where this number comes from  */
+  buff[0] = '~';
+  buff[1] = '0';
+  buff[2] = '\0';
+  StrCatBuffW(lpszDest, buff, dwDestLen);
+
+  /* ~Product Id */
+  dwLen = 256;
+  if (SHGetValueW(HKEY_LOCAL_MACHINE, szRegKey, szProduct, &dwType, buff+1, &dwLen))
+    buff[1] = '\0';
+  StrCatBuffW(lpszDest, buff, dwDestLen);
+
+  /* ~IE Update Url */
+  dwLen = 2048;
+  if(SHGetValueW(HKEY_LOCAL_MACHINE, szWinKey, szUpdate, &dwType, buff+1, &dwLen))
+    buff[1] = '\0';
+  StrCatBuffW(lpszDest, buff, dwDestLen);
+
+  /* ~IE Help String */
+  dwLen = 256;
+  if(SHGetValueW(hReg, szHelp, 0, &dwType, buff+1, &dwLen))
+    buff[1] = '\0';
+  StrCatBuffW(lpszDest, buff, dwDestLen);
+
+  RegCloseKey(hReg);
+  return TRUE;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.163]
+ *
+ * Call IOleCommandTarget_QueryStatus() on an object.
+ *
+ * PARAMS
+ *  lpUnknown     [I] Object supporting the IOleCommandTarget interface
+ *  pguidCmdGroup [I] GUID for the command group
+ *  cCmds         [I]
+ *  prgCmds       [O] Commands
+ *  pCmdText      [O] Command text
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: E_FAIL, if lpUnknown is NULL.
+ *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
+ *           Otherwise, an error code from IOleCommandTarget_QueryStatus().
+ */
+HRESULT WINAPI IUnknown_QueryStatus(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
+                           ULONG cCmds, OLECMD *prgCmds, OLECMDTEXT* pCmdText)
+{
+  HRESULT hRet = E_FAIL;
+
+  TRACE("(%p,%p,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, cCmds, prgCmds, pCmdText);
+
+  if (lpUnknown)
+  {
+    IOleCommandTarget* lpOle;
+
+    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
+                                   (void**)&lpOle);
+
+    if (SUCCEEDED(hRet) && lpOle)
+    {
+      hRet = IOleCommandTarget_QueryStatus(lpOle, pguidCmdGroup, cCmds,
+                                           prgCmds, pCmdText);
+      IOleCommandTarget_Release(lpOle);
+    }
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *      @              [SHLWAPI.164]
+ *
+ * Call IOleCommandTarget_Exec() on an object.
+ *
+ * PARAMS
+ *  lpUnknown     [I] Object supporting the IOleCommandTarget interface
+ *  pguidCmdGroup [I] GUID for the command group
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: E_FAIL, if lpUnknown is NULL.
+ *           E_NOINTERFACE, if lpUnknown does not support IOleCommandTarget.
+ *           Otherwise, an error code from IOleCommandTarget_Exec().
+ */
+HRESULT WINAPI IUnknown_Exec(IUnknown* lpUnknown, REFGUID pguidCmdGroup,
+                           DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
+                           VARIANT* pvaOut)
+{
+  HRESULT hRet = E_FAIL;
+
+  TRACE("(%p,%p,%ld,%ld,%p,%p)\n",lpUnknown, pguidCmdGroup, nCmdID,
+        nCmdexecopt, pvaIn, pvaOut);
+
+  if (lpUnknown)
+  {
+    IOleCommandTarget* lpOle;
+
+    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleCommandTarget,
+                                   (void**)&lpOle);
+    if (SUCCEEDED(hRet) && lpOle)
+    {
+      hRet = IOleCommandTarget_Exec(lpOle, pguidCmdGroup, nCmdID,
+                                    nCmdexecopt, pvaIn, pvaOut);
+      IOleCommandTarget_Release(lpOle);
+    }
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.165]
+ *
+ * Retrieve, modify, and re-set a value from a window.
+ *
+ * PARAMS
+ *  hWnd   [I] Window to get value from
+ *  offset [I] Offset of value
+ *  wMask  [I] Mask for uiFlags
+ *  wFlags [I] Bits to set in window value
+ *
+ * RETURNS
+ *  The new value as it was set, or 0 if any parameter is invalid.
+ *
+ * NOTES
+ *  Any bits set in uiMask are cleared from the value, then any bits set in
+ *  uiFlags are set in the value.
+ */
+LONG WINAPI SHSetWindowBits(HWND hwnd, INT offset, UINT wMask, UINT wFlags)
+{
+  LONG ret = GetWindowLongA(hwnd, offset);
+  LONG newFlags = (wFlags & wMask) | (ret & ~wFlags);
+
+  if (newFlags != ret)
+    ret = SetWindowLongA(hwnd, offset, newFlags);
+  return ret;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.167]
+ *
+ * Change a window's parent.
+ *
+ * PARAMS
+ *  hWnd       [I] Window to change parent of
+ *  hWndParent [I] New parent window
+ *
+ * RETURNS
+ *  The old parent of hWnd.
+ *
+ * NOTES
+ *  If hWndParent is NULL (desktop), the window style is changed to WS_POPUP.
+ *  If hWndParent is NOT NULL then we set the WS_CHILD style.
+ */
+HWND WINAPI SHSetParentHwnd(HWND hWnd, HWND hWndParent)
+{
+  TRACE("%p, %p\n", hWnd, hWndParent);
+
+  if(GetParent(hWnd) == hWndParent)
+    return 0;
+
+  if(hWndParent)
+    SHSetWindowBits(hWnd, GWL_STYLE, WS_CHILD, WS_CHILD);
+  else
+    SHSetWindowBits(hWnd, GWL_STYLE, WS_POPUP, WS_POPUP);
+
+  return SetParent(hWnd, hWndParent);
+}
+
+/*************************************************************************
+ *      @       [SHLWAPI.168]
+ *
+ * Locate and advise a connection point in an IConnectionPointContainer object.
+ *
+ * PARAMS
+ *  lpUnkSink   [I] Sink for the connection point advise call
+ *  riid        [I] REFIID of connection point to advise
+ *  bAdviseOnly [I] TRUE = Advise only, FALSE = Unadvise first
+ *  lpUnknown   [I] Object supporting the IConnectionPointContainer interface
+ *  lpCookie    [O] Pointer to connection point cookie
+ *  lppCP       [O] Destination for the IConnectionPoint found
+ *
+ * RETURNS
+ *  Success: S_OK. If lppCP is non-NULL, it is filled with the IConnectionPoint
+ *           that was advised. The caller is responsable for releasing it.
+ *  Failure: E_FAIL, if any arguments are invalid.
+ *           E_NOINTERFACE, if lpUnknown isn't an IConnectionPointContainer,
+ *           Or an HRESULT error code if any call fails.
+ */
+HRESULT WINAPI ConnectToConnectionPoint(IUnknown* lpUnkSink, REFIID riid, BOOL bAdviseOnly,
+                           IUnknown* lpUnknown, LPDWORD lpCookie,
+                           IConnectionPoint **lppCP)
+{
+  HRESULT hRet;
+  IConnectionPointContainer* lpContainer;
+  IConnectionPoint *lpCP;
+
+  if(!lpUnknown || (bAdviseOnly && !lpUnkSink))
+    return E_FAIL;
+
+  if(lppCP)
+    *lppCP = NULL;
+
+  hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer,
+                                 (void**)&lpContainer);
+  if (SUCCEEDED(hRet))
+  {
+    hRet = IConnectionPointContainer_FindConnectionPoint(lpContainer, riid, &lpCP);
+
+    if (SUCCEEDED(hRet))
+    {
+      if(!bAdviseOnly)
+        hRet = IConnectionPoint_Unadvise(lpCP, *lpCookie);
+      hRet = IConnectionPoint_Advise(lpCP, lpUnkSink, lpCookie);
+
+      if (FAILED(hRet))
+        *lpCookie = 0;
+
+      if (lppCP && SUCCEEDED(hRet))
+        *lppCP = lpCP; /* Caller keeps the interface */
+      else
+        IConnectionPoint_Release(lpCP); /* Release it */
+    }
+
+    IUnknown_Release(lpContainer);
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *     @       [SHLWAPI.169]
+ *
+ * Release an interface.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object to release
+ *
+ * RETURNS
+ *  Nothing.
+ */
+DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
+{
+    IUnknown *temp;
+
+    TRACE("(%p)\n",lpUnknown);
+
+    if(!lpUnknown || !*((LPDWORD)lpUnknown)) return 0;
+    temp = *lpUnknown;
+    *lpUnknown = NULL;
+
+    TRACE("doing Release\n");
+
+    return IUnknown_Release(temp);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.170]
+ *
+ * Skip '//' if present in a string.
+ *
+ * PARAMS
+ *  lpszSrc [I] String to check for '//'
+ *
+ * RETURNS
+ *  Success: The next character after the '//' or the string if not present
+ *  Failure: NULL, if lpszStr is NULL.
+ */
+LPCSTR WINAPI PathSkipLeadingSlashesA(LPCSTR lpszSrc)
+{
+  if (lpszSrc && lpszSrc[0] == '/' && lpszSrc[1] == '/')
+    lpszSrc += 2;
+  return lpszSrc;
+}
+
+/*************************************************************************
+ *      @              [SHLWAPI.171]
+ *
+ * Check if two interfaces come from the same object.
+ *
+ * PARAMS
+ *   lpInt1 [I] Interface to check against lpInt2.
+ *   lpInt2 [I] Interface to check against lpInt1.
+ *
+ * RETURNS
+ *   TRUE, If the interfaces come from the same object.
+ *   FALSE Otherwise.
+ */
+BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
+{
+  LPVOID lpUnknown1, lpUnknown2;
+
+  TRACE("%p %p\n", lpInt1, lpInt2);
+
+  if (!lpInt1 || !lpInt2)
+    return FALSE;
+
+  if (lpInt1 == lpInt2)
+    return TRUE;
+
+  if (!SUCCEEDED(IUnknown_QueryInterface(lpInt1, &IID_IUnknown,
+                                       (LPVOID *)&lpUnknown1)))
+    return FALSE;
+
+  if (!SUCCEEDED(IUnknown_QueryInterface(lpInt2, &IID_IUnknown,
+                                       (LPVOID *)&lpUnknown2)))
+    return FALSE;
+
+  if (lpUnknown1 == lpUnknown2)
+    return TRUE;
+
+  return FALSE;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.172]
+ *
+ * Get the window handle of an object.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object to get the window handle of
+ *  lphWnd    [O] Destination for window handle
+ *
+ * RETURNS
+ *  Success: S_OK. lphWnd contains the objects window handle.
+ *  Failure: An HRESULT error code.
+ *
+ * NOTES
+ *  lpUnknown is expected to support one of the following interfaces:
+ *  IOleWindow(), IInternetSecurityMgrSite(), or IShellView().
+ */
+HRESULT WINAPI IUnknown_GetWindow(IUnknown *lpUnknown, HWND *lphWnd)
+{
+  /* FIXME: Wine has no header for this object */
+  static const GUID IID_IInternetSecurityMgrSite = { 0x79eac9ed,
+    0xbaf9, 0x11ce, { 0x8c, 0x82, 0x00, 0xaa, 0x00, 0x4b, 0xa9, 0x0b }};
+  IUnknown *lpOle;
+  HRESULT hRet = E_FAIL;
+
+  TRACE("(%p,%p)\n", lpUnknown, lphWnd);
+
+  if (!lpUnknown)
+    return hRet;
+
+  hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleWindow, (void**)&lpOle);
+
+  if (FAILED(hRet))
+  {
+    hRet = IUnknown_QueryInterface(lpUnknown,&IID_IShellView, (void**)&lpOle);
+
+    if (FAILED(hRet))
+    {
+      hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInternetSecurityMgrSite,
+                                      (void**)&lpOle);
+    }
+  }
+
+  if (SUCCEEDED(hRet))
+  {
+    /* Lazyness here - Since GetWindow() is the first method for the above 3
+     * interfaces, we use the same call for them all.
+     */
+    hRet = IOleWindow_GetWindow((IOleWindow*)lpOle, lphWnd);
+    IUnknown_Release(lpOle);
+    if (lphWnd)
+      TRACE("Returning HWND=%p\n", *lphWnd);
+  }
+
+  return hRet;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.173]
+ *
+ * Call a method on as as yet unidentified object.
+ *
+ * PARAMS
+ *  pUnk [I] Object supporting the unidentified interface,
+ *  arg  [I] Argument for the call on the object.
+ *
+ * RETURNS
+ *  S_OK.
+ */
+HRESULT WINAPI IUnknown_SetOwner(IUnknown *pUnk, ULONG arg)
+{
+  static const GUID guid_173 = {
+    0x5836fb00, 0x8187, 0x11cf, { 0xa1,0x2b,0x00,0xaa,0x00,0x4a,0xe8,0x37 }
+  };
+  IMalloc *pUnk2;
+
+  TRACE("(%p,%ld)\n", pUnk, arg);
+
+  /* Note: arg may not be a ULONG and pUnk2 is for sure not an IMalloc -
+   *       We use this interface as its vtable entry is compatible with the
+   *       object in question.
+   * FIXME: Find out what this object is and where it should be defined.
+   */
+  if (pUnk &&
+      SUCCEEDED(IUnknown_QueryInterface(pUnk, &guid_173, (void**)&pUnk2)))
+  {
+    IMalloc_Alloc(pUnk2, arg); /* Faked call!! */
+    IMalloc_Release(pUnk2);
+  }
+  return S_OK;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.174]
+ *
+ * Call either IObjectWithSite_SetSite() or IPersistMoniker_GetClassID() on
+ * an interface.
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: E_FAIL, if p1 is NULL.
+ *           E_NOINTERFACE If p1 does not support the IPersist interface,
+ *           Or an HRESULT error code.
+ */
+DWORD WINAPI IUnknown_SetSite(
+        IUnknown *p1,     /* [in]   OLE object                          */
+        LPVOID *p2)       /* [out]  ptr for call results */
+{
+    DWORD ret, aa;
+    IUnknown *iobjectwithsite;
+
+    if (!p1) return E_FAIL;
+
+    /* see if SetSite interface exists for IObjectWithSite object */
+    ret = IUnknown_QueryInterface((IUnknown *)p1, (REFIID)id1, (LPVOID *)&iobjectwithsite);
+    TRACE("first IU_QI ret=%08lx, iobjectwithsite=%p\n", ret, iobjectwithsite);
+    if (ret) {
+
+       /* see if GetClassId interface exists for IPersistMoniker object */
+       ret = IUnknown_QueryInterface(p1, (REFIID)id2, (LPVOID *)&aa);
+       TRACE("second IU_QI ret=%08lx, aa=%08lx\n", ret, aa);
+       if (ret) return ret;
+
+       /* fake a GetClassId call */
+       ret = IOleWindow_GetWindow((IOleWindow *)aa, (HWND*)p2);
+       TRACE("second IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
+             *(LPDWORD)p2);
+       IUnknown_Release((IUnknown *)aa);
+    }
+    else {
+       /* fake a SetSite call */
+       ret = IOleWindow_GetWindow((IOleWindow *)iobjectwithsite, (HWND*)p2);
+       TRACE("first IU_QI doing 0x0c ret=%08lx, *p2=%08lx\n", ret,
+             *(LPDWORD)p2);
+       IUnknown_Release((IUnknown *)iobjectwithsite);
+    }
+    return ret;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.175]
+ *
+ * Call IPersist_GetClassID() on an object.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object supporting the IPersist interface
+ *  lpClassId [O] Destination for Class Id
+ *
+ * RETURNS
+ *  Success: S_OK. lpClassId contains the Class Id requested.
+ *  Failure: E_FAIL, If lpUnknown is NULL,
+ *           E_NOINTERFACE If lpUnknown does not support IPersist,
+ *           Or an HRESULT error code.
+ */
+HRESULT WINAPI IUnknown_GetClassID(IUnknown *lpUnknown, CLSID* lpClassId)
+{
+  IPersist* lpPersist;
+  HRESULT hRet = E_FAIL;
+
+  TRACE("(%p,%p)\n", lpUnknown, debugstr_guid(lpClassId));
+
+  if (lpUnknown)
+  {
+    hRet = IUnknown_QueryInterface(lpUnknown,&IID_IPersist,(void**)&lpPersist);
+    if (SUCCEEDED(hRet))
+    {
+      IPersist_GetClassID(lpPersist, lpClassId);
+      IPersist_Release(lpPersist);
+    }
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.176]
+ *
+ * Retrieve a Service Interface from an object.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object to get an IServiceProvider interface from
+ *  sid       [I] Service ID for IServiceProvider_QueryService() call
+ *  riid      [I] Function requested for QueryService call
+ *  lppOut    [O] Destination for the service interface pointer
+ *
+ * RETURNS
+ *  Success: S_OK. lppOut contains an object providing the requested service
+ *  Failure: An HRESULT error code
+ *
+ * NOTES
+ *  lpUnknown is expected to support the IServiceProvider interface.
+ */
+HRESULT WINAPI IUnknown_QueryService(IUnknown* lpUnknown, REFGUID sid, REFIID riid,
+                           LPVOID *lppOut)
+{
+  IServiceProvider* pService = NULL;
+  HRESULT hRet;
+
+  if (!lppOut)
+    return E_FAIL;
+
+  *lppOut = NULL;
+
+  if (!lpUnknown)
+    return E_FAIL;
+
+  /* Get an IServiceProvider interface from the object */
+  hRet = IUnknown_QueryInterface(lpUnknown, &IID_IServiceProvider,
+                                 (LPVOID*)&pService);
+
+  if (!hRet && pService)
+  {
+    TRACE("QueryInterface returned (IServiceProvider*)%p\n", pService);
+
+    /* Get a Service interface from the object */
+    hRet = IServiceProvider_QueryService(pService, sid, riid, lppOut);
+
+    TRACE("(IServiceProvider*)%p returned (IUnknown*)%p\n", pService, *lppOut);
+
+    /* Release the IServiceProvider interface */
+    IUnknown_Release(pService);
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.177]
+ *
+ * Loads a popup menu.
+ *
+ * PARAMS
+ *  hInst  [I] Instance handle
+ *  szName [I] Menu name
+ *
+ * RETURNS
+ *  Success: TRUE.
+ *  Failure: FALSE.
+ */
+BOOL WINAPI SHLoadMenuPopup(HINSTANCE hInst, LPCWSTR szName)
+{
+  HMENU hMenu, hSubMenu;
+
+  if ((hMenu = LoadMenuW(hInst, szName)))
+  {
+    if ((hSubMenu = GetSubMenu(hMenu, 0)))
+      RemoveMenu(hMenu, 0, MF_BYPOSITION);
+
+    DestroyMenu(hMenu);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+typedef struct _enumWndData
+{
+  UINT   uiMsgId;
+  WPARAM wParam;
+  LPARAM lParam;
+  LRESULT (WINAPI *pfnPost)(HWND,UINT,WPARAM,LPARAM);
+} enumWndData;
+
+/* Callback for SHLWAPI_178 */
+static BOOL CALLBACK SHLWAPI_EnumChildProc(HWND hWnd, LPARAM lParam)
+{
+  enumWndData *data = (enumWndData *)lParam;
+
+  TRACE("(%p,%p)\n", hWnd, data);
+  data->pfnPost(hWnd, data->uiMsgId, data->wParam, data->lParam);
+  return TRUE;
+}
+
+/*************************************************************************
+ * @  [SHLWAPI.178]
+ *
+ * Send or post a message to every child of a window.
+ *
+ * PARAMS
+ *  hWnd    [I] Window whose children will get the messages
+ *  uiMsgId [I] Message Id
+ *  wParam  [I] WPARAM of message
+ *  lParam  [I] LPARAM of message
+ *  bSend   [I] TRUE = Use SendMessageA(), FALSE = Use PostMessageA()
+ *
+ * RETURNS
+ *  Nothing.
+ *
+ * NOTES
+ *  The appropriate ASCII or Unicode function is called for the window.
+ */
+void WINAPI SHPropagateMessage(HWND hWnd, UINT uiMsgId, WPARAM wParam, LPARAM lParam, BOOL bSend)
+{
+  enumWndData data;
+
+  TRACE("(%p,%u,%d,%ld,%d)\n", hWnd, uiMsgId, wParam, lParam, bSend);
+
+  if(hWnd)
+  {
+    data.uiMsgId = uiMsgId;
+    data.wParam  = wParam;
+    data.lParam  = lParam;
+
+    if (bSend)
+      data.pfnPost = IsWindowUnicode(hWnd) ? (void*)SendMessageW : (void*)SendMessageA;
+    else
+      data.pfnPost = IsWindowUnicode(hWnd) ? (void*)PostMessageW : (void*)PostMessageA;
+
+    EnumChildWindows(hWnd, SHLWAPI_EnumChildProc, (LPARAM)&data);
+  }
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.180]
+ *
+ * Remove all sub-menus from a menu.
+ *
+ * PARAMS
+ *  hMenu [I] Menu to remove sub-menus from
+ *
+ * RETURNS
+ *  Success: 0.  All sub-menus under hMenu are removed
+ *  Failure: -1, if any parameter is invalid
+ */
+DWORD WINAPI SHRemoveAllSubMenus(HMENU hMenu)
+{
+  int iItemCount = GetMenuItemCount(hMenu) - 1;
+  while (iItemCount >= 0)
+  {
+    HMENU hSubMenu = GetSubMenu(hMenu, iItemCount);
+    if (hSubMenu)
+      RemoveMenu(hMenu, iItemCount, MF_BYPOSITION);
+    iItemCount--;
+  }
+  return iItemCount;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.181]
+ *
+ * Enable or disable a menu item.
+ *
+ * PARAMS
+ *  hMenu   [I] Menu holding menu item
+ *  uID     [I] ID of menu item to enable/disable
+ *  bEnable [I] Whether to enable (TRUE) or disable (FALSE) the item.
+ *
+ * RETURNS
+ *  The return code from EnableMenuItem.
+ */
+UINT WINAPI SHEnableMenuItem(HMENU hMenu, UINT wItemID, BOOL bEnable)
+{
+  return EnableMenuItem(hMenu, wItemID, bEnable ? MF_ENABLED : MF_GRAYED);
+}
+
+/*************************************************************************
+ * @   [SHLWAPI.182]
+ *
+ * Check or uncheck a menu item.
+ *
+ * PARAMS
+ *  hMenu  [I] Menu holding menu item
+ *  uID    [I] ID of menu item to check/uncheck
+ *  bCheck [I] Whether to check (TRUE) or uncheck (FALSE) the item.
+ *
+ * RETURNS
+ *  The return code from CheckMenuItem.
+ */
+DWORD WINAPI SHCheckMenuItem(HMENU hMenu, UINT uID, BOOL bCheck)
+{
+  return CheckMenuItem(hMenu, uID, bCheck ? MF_CHECKED : MF_UNCHECKED);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.183]
+ *
+ * Register a window class if it isn't already.
+ *
+ * PARAMS
+ *  lpWndClass [I] Window class to register
+ *
+ * RETURNS
+ *  The result of the RegisterClassA call.
+ */
+DWORD WINAPI SHRegisterClassA(WNDCLASSA *wndclass)
+{
+  WNDCLASSA wca;
+  if (GetClassInfoA(wndclass->hInstance, wndclass->lpszClassName, &wca))
+    return TRUE;
+  return (DWORD)RegisterClassA(wndclass);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.186]
+ */
+BOOL WINAPI SHSimulateDrop(IDropTarget *pDrop, IDataObject *pDataObj,
+                           DWORD grfKeyState, PPOINTL lpPt, DWORD* pdwEffect)
+{
+  DWORD dwEffect = DROPEFFECT_LINK | DROPEFFECT_MOVE | DROPEFFECT_COPY;
+  POINTL pt = { 0, 0 };
+
+  if (!lpPt)
+    lpPt = &pt;
+
+  if (!pdwEffect)
+    pdwEffect = &dwEffect;
+
+  IDropTarget_DragEnter(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
+
+  if (*pdwEffect)
+    return IDropTarget_Drop(pDrop, pDataObj, grfKeyState, *lpPt, pdwEffect);
+
+  IDropTarget_DragLeave(pDrop);
+  return TRUE;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.187]
+ *
+ * Call IPersistPropertyBag_Load() on an object.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object supporting the IPersistPropertyBag interface
+ *  lpPropBag [O] Destination for loaded IPropertyBag
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
+ */
+DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
+{
+  IPersistPropertyBag* lpPPBag;
+  HRESULT hRet = E_FAIL;
+
+  TRACE("(%p,%p)\n", lpUnknown, lpPropBag);
+
+  if (lpUnknown)
+  {
+    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IPersistPropertyBag,
+                                   (void**)&lpPPBag);
+    if (SUCCEEDED(hRet) && lpPPBag)
+    {
+      hRet = IPersistPropertyBag_Load(lpPPBag, lpPropBag, NULL);
+      IPersistPropertyBag_Release(lpPPBag);
+    }
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ * @  [SHLWAPI.188]
+ *
+ * Call IOleControlSite_TranslateAccelerator()  on an object.
+ *
+ * PARAMS
+ *  lpUnknown   [I] Object supporting the IOleControlSite interface.
+ *  lpMsg       [I] Key message to be processed.
+ *  dwModifiers [I] Flags containing the state of the modifier keys.
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
+ */
+HRESULT WINAPI IUnknown_TranslateAcceleratorOCS(IUnknown *lpUnknown, LPMSG lpMsg, DWORD dwModifiers)
+{
+  IOleControlSite* lpCSite = NULL;
+  HRESULT hRet = E_INVALIDARG;
+
+  TRACE("(%p,%p,0x%08lx)\n", lpUnknown, lpMsg, dwModifiers);
+  if (lpUnknown)
+  {
+    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
+                                   (void**)&lpCSite);
+    if (SUCCEEDED(hRet) && lpCSite)
+    {
+      hRet = IOleControlSite_TranslateAccelerator(lpCSite, lpMsg, dwModifiers);
+      IOleControlSite_Release(lpCSite);
+    }
+  }
+  return hRet;
+}
+
+
+/*************************************************************************
+ * @  [SHLWAPI.189]
+ *
+ * Call IOleControlSite_GetExtendedControl() on an object.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object supporting the IOleControlSite interface.
+ *  lppDisp   [O] Destination for resulting IDispatch.
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: An HRESULT error code, or E_FAIL if lpUnknown is NULL.
+ */
+DWORD WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, IDispatch** lppDisp)
+{
+  IOleControlSite* lpCSite = NULL;
+  HRESULT hRet = E_FAIL;
+
+  TRACE("(%p,%p)\n", lpUnknown, lppDisp);
+  if (lpUnknown)
+  {
+    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IOleControlSite,
+                                   (void**)&lpCSite);
+    if (SUCCEEDED(hRet) && lpCSite)
+    {
+      hRet = IOleControlSite_GetExtendedControl(lpCSite, lppDisp);
+      IOleControlSite_Release(lpCSite);
+    }
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ * @    [SHLWAPI.190]
+ */
+HRESULT WINAPI IUnknown_HandleIRestrict(LPUNKNOWN lpUnknown, PVOID lpArg1,
+                                        PVOID lpArg2, PVOID lpArg3, PVOID lpArg4)
+{
+  /* FIXME: {D12F26B2-D90A-11D0-830D-00AA005B4383} - What object does this represent? */
+  static const DWORD service_id[] = { 0xd12f26b2, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
+  /* FIXME: {D12F26B1-D90A-11D0-830D-00AA005B4383} - Also Unknown/undocumented */
+  static const DWORD function_id[] = { 0xd12f26b1, 0x11d0d90a, 0xaa000d83, 0x83435b00 };
+  HRESULT hRet = E_INVALIDARG;
+  LPUNKNOWN lpUnkInner = NULL; /* FIXME: Real type is unknown */
+
+  TRACE("(%p,%p,%p,%p,%p)\n", lpUnknown, lpArg1, lpArg2, lpArg3, lpArg4);
+
+  if (lpUnknown && lpArg4)
+  {
+     hRet = IUnknown_QueryService(lpUnknown, (REFGUID)service_id,
+                                  (REFGUID)function_id, (void**)&lpUnkInner);
+
+     if (SUCCEEDED(hRet) && lpUnkInner)
+     {
+       /* FIXME: The type of service object requested is unknown, however
+       * testing shows that its first method is called with 4 parameters.
+       * Fake this by using IParseDisplayName_ParseDisplayName since the
+       * signature and position in the vtable matches our unknown object type.
+       */
+       hRet = IParseDisplayName_ParseDisplayName((LPPARSEDISPLAYNAME)lpUnkInner,
+                                                 lpArg1, lpArg2, lpArg3, lpArg4);
+       IUnknown_Release(lpUnkInner);
+     }
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ * @    [SHLWAPI.192]
+ *
+ * Get a sub-menu from a menu item.
+ *
+ * PARAMS
+ *  hMenu [I] Menu to get sub-menu from
+ *  uID   [I] ID of menu item containing sub-menu
+ *
+ * RETURNS
+ *  The sub-menu of the item, or a NULL handle if any parameters are invalid.
+ */
+HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
+{
+  MENUITEMINFOA mi;
+
+  TRACE("(%p,%uld)\n", hMenu, uID);
+
+  mi.cbSize = sizeof(MENUITEMINFOA);
+  mi.fMask = MIIM_SUBMENU;
+
+  if (!GetMenuItemInfoA(hMenu, uID, 0, &mi))
+    return NULL;
+
+  return mi.hSubMenu;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.193]
+ *
+ * Get the color depth of the primary display.
+ *
+ * PARAMS
+ *  None.
+ *
+ * RETURNS
+ *  The color depth of the primary display.
+ */
+DWORD WINAPI SHGetCurColorRes()
+{
+    HDC hdc;
+    DWORD ret;
+
+    TRACE("()\n");
+
+    hdc = GetDC(0);
+    ret = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
+    ReleaseDC(0, hdc);
+    return ret;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.194]
+ *
+ * Wait for a message to arrive, with a timeout.
+ *
+ * PARAMS
+ *  hand      [I] Handle to query
+ *  dwTimeout [I] Timeout in ticks or INFINITE to never timeout
+ *
+ * RETURNS
+ *  STATUS_TIMEOUT if no message is received before dwTimeout ticks passes.
+ *  Otherwise returns the value from MsgWaitForMultipleObjectsEx when a
+ *  message is available.
+ */
+DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
+{
+  DWORD dwEndTicks = GetTickCount() + dwTimeout;
+  DWORD dwRet;
+
+  while ((dwRet = MsgWaitForMultipleObjectsEx(1, &hand, dwTimeout, QS_SENDMESSAGE, 0)) == 1)
+  {
+    MSG msg;
+
+    PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE);
+
+    if (dwTimeout != INFINITE)
+    {
+        if ((int)(dwTimeout = dwEndTicks - GetTickCount()) <= 0)
+            return WAIT_TIMEOUT;
+    }
+  }
+
+  return dwRet;
+}
+
+/*************************************************************************
+ *      @       [SHLWAPI.195]
+ *
+ * Determine if a shell folder can be expanded.
+ *
+ * PARAMS
+ *  lpFolder [I] Parent folder containing the object to test.
+ *  pidl     [I] Id of the object to test.
+ *
+ * RETURNS
+ *  Success: S_OK, if the object is expandable, S_FALSE otherwise.
+ *  Failure: E_INVALIDARG, if any argument is invalid.
+ *
+ * NOTES
+ *  If the object to be tested does not expose the IQueryInfo() interface it
+ *  will not be identified as an expandable folder.
+ */
+HRESULT WINAPI SHIsExpandableFolder(LPSHELLFOLDER lpFolder, LPCITEMIDLIST pidl)
+{
+  HRESULT hRet = E_INVALIDARG;
+  IQueryInfo *lpInfo;
+
+  if (lpFolder && pidl)
+  {
+    hRet = IShellFolder_GetUIObjectOf(lpFolder, NULL, 1, &pidl, &IID_IQueryInfo,
+                                      NULL, (void**)&lpInfo);
+    if (FAILED(hRet))
+      hRet = S_FALSE; /* Doesn't expose IQueryInfo */
+    else
+    {
+      DWORD dwFlags = 0;
+
+      /* MSDN states of IQueryInfo_GetInfoFlags() that "This method is not
+       * currently used". Really? You wouldn't be holding out on me would you?
+       */
+      hRet = IQueryInfo_GetInfoFlags(lpInfo, &dwFlags);
+
+      if (SUCCEEDED(hRet))
+      {
+        /* 0x2 is an undocumented flag apparently indicating expandability */
+        hRet = dwFlags & 0x2 ? S_OK : S_FALSE;
+      }
+
+      IQueryInfo_Release(lpInfo);
+    }
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *      @       [SHLWAPI.197]
+ *
+ * Blank out a region of text by drawing the background only.
+ *
+ * PARAMS
+ *  hDC   [I] Device context to draw in
+ *  pRect [I] Area to draw in
+ *  cRef  [I] Color to draw in
+ *
+ * RETURNS
+ *  Nothing.
+ */
+DWORD WINAPI SHFillRectClr(HDC hDC, LPCRECT pRect, COLORREF cRef)
+{
+    COLORREF cOldColor = SetBkColor(hDC, cRef);
+    ExtTextOutA(hDC, 0, 0, ETO_OPAQUE, pRect, 0, 0, 0);
+    SetBkColor(hDC, cOldColor);
+    return 0;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.198]
+ *
+ * Return the value asociated with a key in a map.
+ *
+ * PARAMS
+ *  lpKeys   [I] A list of keys of length iLen
+ *  lpValues [I] A list of values associated with lpKeys, of length iLen
+ *  iLen     [I] Length of both lpKeys and lpValues
+ *  iKey     [I] The key value to look up in lpKeys
+ *
+ * RETURNS
+ *  The value in lpValues associated with iKey, or -1 if iKey is not
+ *  found in lpKeys.
+ *
+ * NOTES
+ *  - If two elements in the map share the same key, this function returns
+ *    the value closest to the start of the map
+ *  - The native version of this function crashes if lpKeys or lpValues is NULL.
+ */
+int WINAPI SHSearchMapInt(const int *lpKeys, const int *lpValues, int iLen, int iKey)
+{
+  if (lpKeys && lpValues)
+  {
+    int i = 0;
+
+    while (i < iLen)
+    {
+      if (lpKeys[i] == iKey)
+        return lpValues[i]; /* Found */
+      i++;
+    }
+  }
+  return -1; /* Not found */
+}
+
+
+/*************************************************************************
+ *      @      [SHLWAPI.199]
+ *
+ * Copy an interface pointer
+ *
+ * PARAMS
+ *   lppDest   [O] Destination for copy
+ *   lpUnknown [I] Source for copy
+ *
+ * RETURNS
+ *  Nothing.
+ */
+VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *lpUnknown)
+{
+  TRACE("(%p,%p)\n", lppDest, lpUnknown);
+
+  if (lppDest)
+    IUnknown_AtomicRelease(lppDest); /* Release existing interface */
+
+  if (lpUnknown)
+  {
+    /* Copy */
+    IUnknown_AddRef(lpUnknown);
+    *lppDest = lpUnknown;
+  }
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.200]
+ *
+ */
+HRESULT WINAPI MayQSForward(IUnknown* lpUnknown, PVOID lpReserved,
+                            REFGUID riidCmdGrp, ULONG cCmds,
+                            OLECMD *prgCmds, OLECMDTEXT* pCmdText)
+{
+  FIXME("(%p,%p,%p,%ld,%p,%p) - stub\n",
+        lpUnknown, lpReserved, riidCmdGrp, cCmds, prgCmds, pCmdText);
+
+  /* FIXME: Calls IsQSForward & IUnknown_QueryStatus */
+  return DRAGDROP_E_NOTREGISTERED;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.201]
+ *
+ */
+HRESULT WINAPI MayExecForward(IUnknown* lpUnknown, INT iUnk, REFGUID pguidCmdGroup,
+                           DWORD nCmdID, DWORD nCmdexecopt, VARIANT* pvaIn,
+                           VARIANT* pvaOut)
+{
+  FIXME("(%p,%d,%p,%ld,%ld,%p,%p) - stub!\n", lpUnknown, iUnk, pguidCmdGroup,
+        nCmdID, nCmdexecopt, pvaIn, pvaOut);
+  return DRAGDROP_E_NOTREGISTERED;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.202]
+ *
+ */
+HRESULT WINAPI IsQSForward(REFGUID pguidCmdGroup,ULONG cCmds, OLECMD *prgCmds)
+{
+  FIXME("(%p,%ld,%p) - stub!\n", pguidCmdGroup, cCmds, prgCmds);
+  return DRAGDROP_E_NOTREGISTERED;
+}
+
+/*************************************************************************
+ * @   [SHLWAPI.204]
+ *
+ * Determine if a window is not a child of another window.
+ *
+ * PARAMS
+ * hParent [I] Suspected parent window
+ * hChild  [I] Suspected child window
+ *
+ * RETURNS
+ * TRUE:  If hChild is a child window of hParent
+ * FALSE: If hChild is not a child window of hParent, or they are equal
+ */
+BOOL WINAPI SHIsChildOrSelf(HWND hParent, HWND hChild)
+{
+  TRACE("(%p,%p)\n", hParent, hChild);
+
+  if (!hParent || !hChild)
+    return TRUE;
+  else if(hParent == hChild)
+    return FALSE;
+  return !IsChild(hParent, hChild);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.208]
+ *
+ * Some sort of memory management process.
+ */
+DWORD WINAPI FDSA_Initialize(
+       DWORD    a,
+       DWORD    b,
+       LPVOID   c,
+       LPVOID   d,
+       DWORD    e)
+{
+    FIXME("(0x%08lx 0x%08lx %p %p 0x%08lx) stub\n",
+         a, b, c, d, e);
+    return 1;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.209]
+ *
+ * Some sort of memory management process.
+ */
+DWORD WINAPI FDSA_Destroy(
+       LPVOID   a)
+{
+    FIXME("(%p) stub\n",
+         a);
+    return 1;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.210]
+ *
+ * Some sort of memory management process.
+ */
+DWORD WINAPI FDSA_InsertItem(
+       LPVOID   a,
+       DWORD    b,
+       LPVOID   c)
+{
+    FIXME("(%p 0x%08lx %p) stub\n",
+         a, b, c);
+    return 0;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.211]
+ */
+DWORD WINAPI FDSA_DeleteItem(
+       LPVOID   a,
+       DWORD    b)
+{
+    FIXME("(%p 0x%08lx) stub\n",
+         a, b);
+    return 1;
+}
+
+typedef struct {
+    REFIID   refid;
+    DWORD    indx;
+} IFACE_INDEX_TBL;
+
+/*************************************************************************
+ *      @      [SHLWAPI.219]
+ *
+ * Call IUnknown_QueryInterface() on a table of objects.
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: E_POINTER or E_NOINTERFACE.
+ */
+HRESULT WINAPI QISearch(
+       LPVOID w,           /* [in]   Table of interfaces */
+       IFACE_INDEX_TBL *x, /* [in]   Array of REFIIDs and indexes into the table */
+       REFIID riid,        /* [in]   REFIID to get interface for */
+       LPVOID *ppv)          /* [out]  Destination for interface pointer */
+{
+       HRESULT ret;
+       IUnknown *a_vtbl;
+       IFACE_INDEX_TBL *xmove;
+
+       TRACE("(%p %p %s %p)\n", w,x,debugstr_guid(riid),ppv);
+       if (ppv) {
+           xmove = x;
+           while (xmove->refid) {
+               TRACE("trying (indx %ld) %s\n", xmove->indx, debugstr_guid(xmove->refid));
+               if (IsEqualIID(riid, xmove->refid)) {
+                   a_vtbl = (IUnknown*)(xmove->indx + (LPBYTE)w);
+                   TRACE("matched, returning (%p)\n", a_vtbl);
+                   *ppv = (LPVOID)a_vtbl;
+                   IUnknown_AddRef(a_vtbl);
+                   return S_OK;
+               }
+               xmove++;
+           }
+
+           if (IsEqualIID(riid, &IID_IUnknown)) {
+               a_vtbl = (IUnknown*)(x->indx + (LPBYTE)w);
+               TRACE("returning first for IUnknown (%p)\n", a_vtbl);
+               *ppv = (LPVOID)a_vtbl;
+               IUnknown_AddRef(a_vtbl);
+               return S_OK;
+           }
+           *ppv = 0;
+           ret = E_NOINTERFACE;
+       } else
+           ret = E_POINTER;
+
+       TRACE("-- 0x%08lx\n", ret);
+       return ret;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.221]
+ *
+ * Remove the "PropDlgFont" property from a window.
+ *
+ * PARAMS
+ *  hWnd [I] Window to remove the property from
+ *
+ * RETURNS
+ *  A handle to the removed property, or NULL if it did not exist.
+ */
+HANDLE WINAPI SHRemoveDefaultDialogFont(HWND hWnd)
+{
+  HANDLE hProp;
+
+  TRACE("(%p)\n", hWnd);
+
+  hProp = GetPropA(hWnd, "PropDlgFont");
+
+  if(hProp)
+  {
+    DeleteObject(hProp);
+    hProp = RemovePropA(hWnd, "PropDlgFont");
+  }
+  return hProp;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.236]
+ *
+ * Load the in-process server of a given GUID.
+ *
+ * PARAMS
+ *  refiid [I] GUID of the server to load.
+ *
+ * RETURNS
+ *  Success: A handle to the loaded server dll.
+ *  Failure: A NULL handle.
+ */
+HMODULE WINAPI SHPinDllOfCLSID(REFIID refiid)
+{
+    HKEY newkey;
+    DWORD type, count;
+    CHAR value[MAX_PATH], string[MAX_PATH];
+
+    strcpy(string, "CLSID\\");
+    SHStringFromGUIDA(refiid, string + 6, sizeof(string)/sizeof(char) - 6);
+    strcat(string, "\\InProcServer32");
+
+    count = MAX_PATH;
+    RegOpenKeyExA(HKEY_CLASSES_ROOT, string, 0, 1, &newkey);
+    RegQueryValueExA(newkey, 0, 0, &type, (PBYTE)value, &count);
+    RegCloseKey(newkey);
+    return LoadLibraryExA(value, 0, 0);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.237]
+ *
+ * Unicode version of SHLWAPI_183.
+ */
+DWORD WINAPI SHRegisterClassW(WNDCLASSW * lpWndClass)
+{
+       WNDCLASSW WndClass;
+
+       TRACE("(%p %s)\n",lpWndClass->hInstance, debugstr_w(lpWndClass->lpszClassName));
+
+       if (GetClassInfoW(lpWndClass->hInstance, lpWndClass->lpszClassName, &WndClass))
+               return TRUE;
+       return RegisterClassW(lpWndClass);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.238]
+ *
+ * Unregister a list of classes.
+ *
+ * PARAMS
+ *  hInst      [I] Application instance that registered the classes
+ *  lppClasses [I] List of class names
+ *  iCount     [I] Number of names in lppClasses
+ *
+ * RETURNS
+ *  Nothing.
+ */
+void WINAPI SHUnregisterClassesA(HINSTANCE hInst, LPCSTR *lppClasses, INT iCount)
+{
+  WNDCLASSA WndClass;
+
+  TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
+
+  while (iCount > 0)
+  {
+    if (GetClassInfoA(hInst, *lppClasses, &WndClass))
+      UnregisterClassA(*lppClasses, hInst);
+    lppClasses++;
+    iCount--;
+  }
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.239]
+ *
+ * Unicode version of SHUnregisterClassesA.
+ */
+void WINAPI SHUnregisterClassesW(HINSTANCE hInst, LPCWSTR *lppClasses, INT iCount)
+{
+  WNDCLASSW WndClass;
+
+  TRACE("(%p,%p,%d)\n", hInst, lppClasses, iCount);
+
+  while (iCount > 0)
+  {
+    if (GetClassInfoW(hInst, *lppClasses, &WndClass))
+      UnregisterClassW(*lppClasses, hInst);
+    lppClasses++;
+    iCount--;
+  }
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.240]
+ *
+ * Call The correct (Ascii/Unicode) default window procedure for a window.
+ *
+ * PARAMS
+ *  hWnd     [I] Window to call the default procedure for
+ *  uMessage [I] Message ID
+ *  wParam   [I] WPARAM of message
+ *  lParam   [I] LPARAM of message
+ *
+ * RETURNS
+ *  The result of calling DefWindowProcA() or DefWindowProcW().
+ */
+LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM wParam, LPARAM lParam)
+{
+       if (IsWindowUnicode(hWnd))
+               return DefWindowProcW(hWnd, uMessage, wParam, lParam);
+       return DefWindowProcA(hWnd, uMessage, wParam, lParam);
+}
+
+/*************************************************************************
+ *      @       [SHLWAPI.256]
+ */
+HRESULT WINAPI IUnknown_GetSite(LPUNKNOWN lpUnknown, REFIID iid, PVOID *lppSite)
+{
+  HRESULT hRet = E_INVALIDARG;
+  LPOBJECTWITHSITE lpSite = NULL;
+
+  TRACE("(%p,%s,%p)\n", lpUnknown, debugstr_guid(iid), lppSite);
+
+  if (lpUnknown && iid && lppSite)
+  {
+    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IObjectWithSite,
+                                   (void**)&lpSite);
+    if (SUCCEEDED(hRet) && lpSite)
+    {
+      hRet = IObjectWithSite_GetSite(lpSite, iid, lppSite);
+      IObjectWithSite_Release(lpSite);
+    }
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.257]
+ *
+ * Create a worker window using CreateWindowExA().
+ *
+ * PARAMS
+ *  wndProc    [I] Window procedure
+ *  hWndParent [I] Parent window
+ *  dwExStyle  [I] Extra style flags
+ *  dwStyle    [I] Style flags
+ *  hMenu      [I] Window menu
+ *  z          [I] Unknown
+ *
+ * RETURNS
+ *  Success: The window handle of the newly created window.
+ *  Failure: 0.
+ */
+HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
+                        DWORD dwStyle, HMENU hMenu, LONG z)
+{
+  static const char* szClass = "WorkerA";
+  WNDCLASSA wc;
+  HWND hWnd;
+
+  TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
+         wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
+
+  /* Create Window class */
+  wc.style         = 0;
+  wc.lpfnWndProc   = DefWindowProcA;
+  wc.cbClsExtra    = 0;
+  wc.cbWndExtra    = 4;
+  wc.hInstance     = shlwapi_hInstance;
+  wc.hIcon         = NULL;
+  wc.hCursor       = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
+  wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
+  wc.lpszMenuName  = NULL;
+  wc.lpszClassName = szClass;
+
+  SHRegisterClassA(&wc); /* Register class */
+
+  /* FIXME: Set extra bits in dwExStyle */
+
+  hWnd = CreateWindowExA(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
+                         hWndParent, hMenu, shlwapi_hInstance, 0);
+  if (hWnd)
+  {
+    SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
+
+    if (wndProc)
+      SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
+  }
+  return hWnd;
+}
+
+typedef struct tagPOLICYDATA
+{
+  DWORD policy;        /* flags value passed to SHRestricted */
+  LPCWSTR appstr;      /* application str such as "Explorer" */
+  LPCWSTR keystr;      /* name of the actual registry key / policy */
+} POLICYDATA, *LPPOLICYDATA;
+
+#define SHELL_NO_POLICY 0xffffffff
+
+/* default shell policy registry key */
+static const WCHAR strRegistryPolicyW[] = {'S','o','f','t','w','a','r','e','\\','M','i','c','r','o',
+                                      's','o','f','t','\\','W','i','n','d','o','w','s','\\',
+                                      'C','u','r','r','e','n','t','V','e','r','s','i','o','n',
+                                      '\\','P','o','l','i','c','i','e','s',0};
+
+/*************************************************************************
+ * @                          [SHLWAPI.271]
+ *
+ * Retrieve a policy value from the registry.
+ *
+ * PARAMS
+ *  lpSubKey   [I]   registry key name
+ *  lpSubName  [I]   subname of registry key
+ *  lpValue    [I]   value name of registry value
+ *
+ * RETURNS
+ *  the value associated with the registry key or 0 if not found
+ */
+DWORD WINAPI SHGetRestriction(LPCWSTR lpSubKey, LPCWSTR lpSubName, LPCWSTR lpValue)
+{
+       DWORD retval, datsize = sizeof(retval);
+       HKEY hKey;
+
+       if (!lpSubKey)
+         lpSubKey = strRegistryPolicyW;
+
+       retval = RegOpenKeyW(HKEY_LOCAL_MACHINE, lpSubKey, &hKey);
+    if (retval != ERROR_SUCCESS)
+         retval = RegOpenKeyW(HKEY_CURRENT_USER, lpSubKey, &hKey);
+       if (retval != ERROR_SUCCESS)
+         return 0;
+
+       SHGetValueW(hKey, lpSubName, lpValue, NULL, (LPBYTE)&retval, &datsize);
+       RegCloseKey(hKey);
+       return retval;
+}
+
+/*************************************************************************
+ * @                         [SHLWAPI.266]
+ *
+ * Helper function to retrieve the possibly cached value for a specific policy
+ *
+ * PARAMS
+ *  policy     [I]   The policy to look for
+ *  initial    [I]   Main registry key to open, if NULL use default
+ *  polTable   [I]   Table of known policies, 0 terminated
+ *  polArr     [I]   Cache array of policy values
+ *
+ * RETURNS
+ *  The retrieved policy value or 0 if not successful
+ *
+ * NOTES
+ *  This function is used by the native SHRestricted function to search for the
+ *  policy and cache it once retrieved. The current Wine implementation uses a
+ *  different POLICYDATA structure and implements a similar algorithme adapted to
+ *  that structure.
+ */
+DWORD WINAPI SHRestrictionLookup(
+       DWORD policy,
+       LPCWSTR initial,
+       LPPOLICYDATA polTable,
+       LPDWORD polArr)
+{
+       TRACE("(0x%08lx %s %p %p)\n", policy, debugstr_w(initial), polTable, polArr);
+
+       if (!polTable || !polArr)
+         return 0;
+
+       for (;polTable->policy; polTable++, polArr++)
+       {
+         if (policy == polTable->policy)
+         {
+           /* we have a known policy */
+
+           /* check if this policy has been cached */
+               if (*polArr == SHELL_NO_POLICY)
+             *polArr = SHGetRestriction(initial, polTable->appstr, polTable->keystr);
+           return *polArr;
+         }
+       }
+       /* we don't know this policy, return 0 */
+       TRACE("unknown policy: (%08lx)\n", policy);
+       return 0;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.267]
+ *
+ * Get an interface from an object.
+ *
+ * RETURNS
+ *  Success: S_OK. ppv contains the requested interface.
+ *  Failure: An HRESULT error code.
+ *
+ * NOTES
+ *   This QueryInterface asks the inner object for an interface. In case
+ *   of aggregation this request would be forwarded by the inner to the
+ *   outer object. This function asks the inner object directly for the
+ *   interface circumventing the forwarding to the outer object.
+ */
+HRESULT WINAPI SHWeakQueryInterface(
+       IUnknown * pUnk,   /* [in] Outer object */
+       IUnknown * pInner, /* [in] Inner object */
+       IID * riid, /* [in] Interface GUID to query for */
+       LPVOID* ppv) /* [out] Destination for queried interface */
+{
+       HRESULT hret = E_NOINTERFACE;
+       TRACE("(pUnk=%p pInner=%p\n\tIID:  %s %p)\n",pUnk,pInner,debugstr_guid(riid), ppv);
+
+       *ppv = NULL;
+       if(pUnk && pInner) {
+           hret = IUnknown_QueryInterface(pInner, riid, (LPVOID*)ppv);
+           if (SUCCEEDED(hret)) IUnknown_Release(pUnk);
+       }
+       TRACE("-- 0x%08lx\n", hret);
+       return hret;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.268]
+ *
+ * Move a reference from one interface to another.
+ *
+ * PARAMS
+ *   lpDest     [O] Destination to receive the reference
+ *   lppUnknown [O] Source to give up the reference to lpDest
+ *
+ * RETURNS
+ *  Nothing.
+ */
+VOID WINAPI SHWeakReleaseInterface(IUnknown *lpDest, IUnknown **lppUnknown)
+{
+  TRACE("(%p,%p)\n", lpDest, lppUnknown);
+
+  if (*lppUnknown)
+  {
+    /* Copy Reference*/
+    IUnknown_AddRef(lpDest);
+    IUnknown_AtomicRelease(lppUnknown); /* Release existing interface */
+  }
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.269]
+ *
+ * Convert an ASCII string of a CLSID into a CLSID.
+ *
+ * PARAMS
+ *  idstr [I] String representing a CLSID in registry format
+ *  id    [O] Destination for the converted CLSID
+ *
+ * RETURNS
+ *  Success: TRUE. id contains the converted CLSID.
+ *  Failure: FALSE.
+ */
+BOOL WINAPI GUIDFromStringA(LPCSTR idstr, CLSID *id)
+{
+  WCHAR wClsid[40];
+  MultiByteToWideChar(CP_ACP, 0, idstr, -1, wClsid, sizeof(wClsid)/sizeof(WCHAR));
+  return SUCCEEDED(CLSIDFromStringWrap(wClsid, id));
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.270]
+ *
+ * Unicode version of GUIDFromStringA.
+ */
+BOOL WINAPI GUIDFromStringW(LPCWSTR idstr, CLSID *id)
+{
+  return SUCCEEDED(CLSIDFromStringWrap(idstr, id));
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.276]
+ *
+ * Determine if the browser is integrated into the shell, and set a registry
+ * key accordingly.
+ *
+ * PARAMS
+ *  None.
+ *
+ * RETURNS
+ *  1, If the browser is not integrated.
+ *  2, If the browser is integrated.
+ *
+ * NOTES
+ *  The key "HKLM\Software\Microsoft\Internet Explorer\IntegratedBrowser" is
+ *  either set to TRUE, or removed depending on whether the browser is deemed
+ *  to be integrated.
+ */
+DWORD WINAPI WhichPlatform()
+{
+  static LPCSTR szIntegratedBrowser = "IntegratedBrowser";
+  static DWORD dwState = 0;
+  HKEY hKey;
+  DWORD dwRet, dwData, dwSize;
+
+  if (dwState)
+    return dwState;
+
+  /* If shell32 exports DllGetVersion(), the browser is integrated */
+  GET_FUNC(pDllGetVersion, shell32, "DllGetVersion", 1);
+  dwState = pDllGetVersion ? 2 : 1;
+
+  /* Set or delete the key accordingly */
+  dwRet = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
+                        "Software\\Microsoft\\Internet Explorer", 0,
+                         KEY_ALL_ACCESS, &hKey);
+  if (!dwRet)
+  {
+    dwRet = RegQueryValueExA(hKey, szIntegratedBrowser, 0, 0,
+                             (LPBYTE)&dwData, &dwSize);
+
+    if (!dwRet && dwState == 1)
+    {
+      /* Value exists but browser is not integrated */
+      RegDeleteValueA(hKey, szIntegratedBrowser);
+    }
+    else if (dwRet && dwState == 2)
+    {
+      /* Browser is integrated but value does not exist */
+      dwData = TRUE;
+      RegSetValueExA(hKey, szIntegratedBrowser, 0, REG_DWORD,
+                     (LPBYTE)&dwData, sizeof(dwData));
+    }
+    RegCloseKey(hKey);
+  }
+  return dwState;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.278]
+ *
+ * Unicode version of SHCreateWorkerWindowA.
+ */
+HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle,
+                        DWORD dwStyle, HMENU hMenu, LONG z)
+{
+  static const WCHAR szClass[] = { 'W', 'o', 'r', 'k', 'e', 'r', 'W', '\0' };
+  WNDCLASSW wc;
+  HWND hWnd;
+
+  TRACE("(0x%08lx,%p,0x%08lx,0x%08lx,%p,0x%08lx)\n",
+         wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
+
+  /* If our OS is natively ASCII, use the ASCII version */
+  if (!(GetVersion() & 0x80000000))  /* NT */
+    return SHCreateWorkerWindowA(wndProc, hWndParent, dwExStyle, dwStyle, hMenu, z);
+
+  /* Create Window class */
+  wc.style         = 0;
+  wc.lpfnWndProc   = DefWindowProcW;
+  wc.cbClsExtra    = 0;
+  wc.cbWndExtra    = 4;
+  wc.hInstance     = shlwapi_hInstance;
+  wc.hIcon         = NULL;
+  wc.hCursor       = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
+  wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
+  wc.lpszMenuName  = NULL;
+  wc.lpszClassName = szClass;
+
+  SHRegisterClassW(&wc); /* Register class */
+
+  /* FIXME: Set extra bits in dwExStyle */
+
+  hWnd = CreateWindowExW(dwExStyle, szClass, 0, dwStyle, 0, 0, 0, 0,
+                         hWndParent, hMenu, shlwapi_hInstance, 0);
+  if (hWnd)
+  {
+    SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
+
+    if (wndProc)
+      SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
+  }
+  return hWnd;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.279]
+ *
+ * Get and show a context menu from a shell folder.
+ *
+ * PARAMS
+ *  hWnd           [I] Window displaying the shell folder
+ *  lpFolder       [I] IShellFolder interface
+ *  lpApidl        [I] Id for the particular folder desired
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: An HRESULT error code indicating the error.
+ */
+HRESULT WINAPI SHInvokeDefaultCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl)
+{
+  return SHInvokeCommand(hWnd, lpFolder, lpApidl, FALSE);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.281]
+ *
+ * _SHPackDispParamsV
+ */
+HRESULT WINAPI SHPackDispParamsV(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
+{
+       FIXME("%p %p %p %p\n",w,x,y,z);
+       return E_FAIL;
+}
+
+/*************************************************************************
+ *      @       [SHLWAPI.282]
+ *
+ * This function seems to be a forward to SHPackDispParamsV (whatever THAT
+ * function does...).
+ */
+HRESULT WINAPI SHPackDispParams(LPVOID w, LPVOID x, LPVOID y, LPVOID z)
+{
+  FIXME("%p %p %p %p\n", w, x, y, z);
+  return E_FAIL;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.284]
+ *
+ * _IConnectionPoint_SimpleInvoke
+ */
+DWORD WINAPI IConnectionPoint_SimpleInvoke(
+       LPVOID x,
+       LPVOID y,
+       LPVOID z)
+{
+        FIXME("(%p %p %p) stub\n",x,y,z);
+       return 0;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.285]
+ *
+ * Notify an IConnectionPoint object of changes.
+ *
+ * PARAMS
+ *  lpCP   [I] Object to notify
+ *  dispID [I]
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: E_NOINTERFACE, if lpCP is NULL or does not support the
+ *           IConnectionPoint interface.
+ */
+HRESULT WINAPI IConnectionPoint_OnChanged(IConnectionPoint* lpCP, DISPID dispID)
+{
+  IEnumConnections *lpEnum;
+  HRESULT hRet = E_NOINTERFACE;
+
+  TRACE("(%p,0x%8lX)\n", lpCP, dispID);
+
+  /* Get an enumerator for the connections */
+  if (lpCP)
+    hRet = IConnectionPoint_EnumConnections(lpCP, &lpEnum);
+
+  if (SUCCEEDED(hRet))
+  {
+    IPropertyNotifySink *lpSink;
+    CONNECTDATA connData;
+    ULONG ulFetched;
+
+    /* Call OnChanged() for every notify sink in the connection point */
+    while (IEnumConnections_Next(lpEnum, 1, &connData, &ulFetched) == S_OK)
+    {
+      if (SUCCEEDED(IUnknown_QueryInterface(connData.pUnk, &IID_IPropertyNotifySink, (void**)&lpSink)) &&
+          lpSink)
+      {
+        IPropertyNotifySink_OnChanged(lpSink, dispID);
+        IPropertyNotifySink_Release(lpSink);
+      }
+      IUnknown_Release(connData.pUnk);
+    }
+
+    IEnumConnections_Release(lpEnum);
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.287]
+ *
+ * Notify an IConnectionPointContainer object of changes.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object to notify
+ *  dispID    [I]
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: E_NOINTERFACE, if lpUnknown is NULL or does not support the
+ *           IConnectionPointContainer interface.
+ */
+HRESULT WINAPI IUnknown_CPContainerOnChanged(IUnknown *lpUnknown, DISPID dispID)
+{
+  IConnectionPointContainer* lpCPC = NULL;
+  HRESULT hRet = E_NOINTERFACE;
+
+  TRACE("(%p,0x%8lX)\n", lpUnknown, dispID);
+
+  if (lpUnknown)
+    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IConnectionPointContainer, (void**)&lpCPC);
+
+  if (SUCCEEDED(hRet))
+  {
+    IConnectionPoint* lpCP;
+
+    hRet = IConnectionPointContainer_FindConnectionPoint(lpCPC, &IID_IPropertyNotifySink, &lpCP);
+    IConnectionPointContainer_Release(lpCPC);
+
+    hRet = IConnectionPoint_OnChanged(lpCP, dispID);
+    IConnectionPoint_Release(lpCP);
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.289]
+ *
+ * See PlaySoundW.
+ */
+BOOL WINAPI PlaySoundWrapW(LPCWSTR pszSound, HMODULE hmod, DWORD fdwSound)
+{
+  GET_FUNC(pPlaySoundW, winmm, "PlaySoundW", FALSE);
+  return pPlaySoundW(pszSound, hmod, fdwSound);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.294]
+ */
+BOOL WINAPI SHGetIniStringW(LPSTR str1, LPSTR str2, LPSTR pStr, DWORD some_len,  LPCSTR lpStr2)
+{
+    /*
+     * str1:           "I"     "I"     pushl esp+0x20
+     * str2:           "U"     "I"     pushl 0x77c93810
+     * (is "I" and "U" "integer" and "unsigned" ??)
+     *
+     * pStr:           ""      ""      pushl eax
+     * some_len:       0x824   0x104   pushl 0x824
+     * lpStr2:         "%l"    "%l"    pushl esp+0xc
+     *
+     * shlwapi. StrCpyNW(lpStr2, irrelevant_var, 0x104);
+     * LocalAlloc(0x00, some_len) -> irrelevant_var
+     * LocalAlloc(0x40, irrelevant_len) -> pStr
+     * shlwapi.294(str1, str2, pStr, some_len, lpStr2);
+     * shlwapi.PathRemoveBlanksW(pStr);
+     */
+    FIXME("('%s', '%s', '%s', %08lx, '%s'): stub!\n", str1, str2, pStr, some_len, lpStr2);
+    return TRUE;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.295]
+ *
+ * Called by ICQ2000b install via SHDOCVW:
+ * str1: "InternetShortcut"
+ * x: some unknown pointer
+ * str2: "http://free.aol.com/tryaolfree/index.adp?139269"
+ * str3: "C:\\WINDOWS\\Desktop.new2\\Free AOL & Unlimited Internet.url"
+ *
+ * In short: this one maybe creates a desktop link :-)
+ */
+BOOL WINAPI SHSetIniStringW(LPWSTR str1, LPVOID x, LPWSTR str2, LPWSTR str3)
+{
+    FIXME("('%s', %p, '%s', '%s'), stub.\n", debugstr_w(str1), x, debugstr_w(str2), debugstr_w(str3));
+    return TRUE;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.299]
+ *
+ * See COMCTL32_417.
+ */
+BOOL WINAPI ExtTextOutWrapW(HDC hdc, INT x, INT y, UINT flags, const RECT *lprect,
+                         LPCWSTR str, UINT count, const INT *lpDx)
+{
+    GET_FUNC(pCOMCTL32_417, comctl32, (LPCSTR)417, FALSE);
+    return pCOMCTL32_417(hdc, x, y, flags, lprect, str, count, lpDx);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.313]
+ *
+ * See SHGetFileInfoW.
+ */
+DWORD WINAPI SHGetFileInfoWrapW(LPCWSTR path, DWORD dwFileAttributes,
+                         SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
+{
+  GET_FUNC(pSHGetFileInfoW, shell32, "SHGetFileInfoW", 0);
+  return pSHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.318]
+ *
+ * See DragQueryFileW.
+ */
+UINT WINAPI DragQueryFileWrapW(HDROP hDrop, UINT lFile, LPWSTR lpszFile, UINT lLength)
+{
+  GET_FUNC(pDragQueryFileW, shell32, "DragQueryFileW", 0);
+  return pDragQueryFileW(hDrop, lFile, lpszFile, lLength);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.333]
+ *
+ * See SHBrowseForFolderW.
+ */
+LPITEMIDLIST WINAPI SHBrowseForFolderWrapW(LPBROWSEINFOW lpBi)
+{
+  GET_FUNC(pSHBrowseForFolderW, shell32, "SHBrowseForFolderW", NULL);
+  return pSHBrowseForFolderW(lpBi);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.334]
+ *
+ * See SHGetPathFromIDListW.
+ */
+BOOL WINAPI SHGetPathFromIDListWrapW(LPCITEMIDLIST pidl,LPWSTR pszPath)
+{
+  GET_FUNC(pSHGetPathFromIDListW, shell32, "SHGetPathFromIDListW", 0);
+  return pSHGetPathFromIDListW(pidl, pszPath);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.335]
+ *
+ * See ShellExecuteExW.
+ */
+BOOL WINAPI ShellExecuteExWrapW(LPSHELLEXECUTEINFOW lpExecInfo)
+{
+  GET_FUNC(pShellExecuteExW, shell32, "ShellExecuteExW", FALSE);
+  return pShellExecuteExW(lpExecInfo);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.336]
+ *
+ * See SHFileOperationW.
+ */
+HICON WINAPI SHFileOperationWrapW(LPSHFILEOPSTRUCTW lpFileOp)
+{
+  GET_FUNC(pSHFileOperationW, shell32, "SHFileOperationW", 0);
+  return pSHFileOperationW(lpFileOp);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.337]
+ *
+ * See ExtractIconExW.
+ */
+UINT WINAPI ExtractIconExWrapW(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge,
+                         HICON *phiconSmall, UINT nIcons)
+{
+  GET_FUNC(pExtractIconExW, shell32, "ExtractIconExW", 0);
+  return pExtractIconExW(lpszFile, nIconIndex, phiconLarge, phiconSmall, nIcons);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.342]
+ *
+ */
+LONG WINAPI SHInterlockedCompareExchange( PLONG dest, LONG xchg, LONG compare)
+{
+        return InterlockedCompareExchange(dest, xchg, compare);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.350]
+ *
+ * See GetFileVersionInfoSizeW.
+ */
+DWORD WINAPI GetFileVersionInfoSizeWrapW(
+       LPWSTR x,
+       LPVOID y)
+{
+        DWORD ret;
+
+       GET_FUNC(pGetFileVersionInfoSizeW, version, "GetFileVersionInfoSizeW", 0);
+       ret = pGetFileVersionInfoSizeW(x, y);
+       return 0x208 + ret;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.351]
+ *
+ * See GetFileVersionInfoW.
+ */
+BOOL  WINAPI GetFileVersionInfoWrapW(
+       LPWSTR w,   /* [in] path to dll */
+       DWORD  x,   /* [in] parm 2 to GetFileVersionInfoA */
+       DWORD  y,   /* [in] return value from SHLWAPI_350() - assume length */
+       LPVOID z)   /* [in/out] buffer (+0x208 sent to GetFileVersionInfoA()) */
+{
+    GET_FUNC(pGetFileVersionInfoW, version, "GetFileVersionInfoW", 0);
+    return pGetFileVersionInfoW(w, x, y-0x208, (char*)z+0x208);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.352]
+ *
+ * See VerQueryValueW.
+ */
+WORD WINAPI VerQueryValueWrapW(
+       LPVOID w,   /* [in] Buffer from SHLWAPI_351() */
+       LPWSTR x,   /* [in]   Value to retrieve - converted and passed to VerQueryValueA() as #2 */
+       LPVOID y,   /* [out]  Ver buffer - passed to VerQueryValueA as #3 */
+       UINT*  z)   /* [in]   Ver length - passed to VerQueryValueA as #4 */
+{
+    GET_FUNC(pVerQueryValueW, version, "VerQueryValueW", 0);
+    return pVerQueryValueW((char*)w+0x208, x, y, z);
+}
+
+#define IsIface(type) SUCCEEDED((hRet = IUnknown_QueryInterface(lpUnknown, &IID_##type, (void**)&lpObj)))
+#define IShellBrowser_EnableModeless IShellBrowser_EnableModelessSB
+#define EnableModeless(type) type##_EnableModeless((type*)lpObj, bModeless)
+
+/*************************************************************************
+ *      @      [SHLWAPI.355]
+ *
+ * Change the modality of a shell object.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object to make modeless
+ *  bModeless [I] TRUE=Make modeless, FALSE=Make modal
+ *
+ * RETURNS
+ *  Success: S_OK. The modality lpUnknown is changed.
+ *  Failure: An HRESULT error code indicating the error.
+ *
+ * NOTES
+ *  lpUnknown must support the IOleInPlaceFrame interface, the
+ *  IInternetSecurityMgrSite interface, the IShellBrowser interface
+ *  the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
+ *  or this call will fail.
+ */
+HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
+{
+  IUnknown *lpObj;
+  HRESULT hRet;
+
+  TRACE("(%p,%d)\n", lpUnknown, bModeless);
+
+  if (!lpUnknown)
+    return E_FAIL;
+
+  if (IsIface(IOleInPlaceActiveObject))
+    EnableModeless(IOleInPlaceActiveObject);
+  else if (IsIface(IOleInPlaceFrame))
+    EnableModeless(IOleInPlaceFrame);
+  else if (IsIface(IShellBrowser))
+    EnableModeless(IShellBrowser);
+#if 0
+  /* FIXME: Wine has no headers for these objects yet */
+  else if (IsIface(IInternetSecurityMgrSite))
+    EnableModeless(IInternetSecurityMgrSite);
+  else if (IsIface(IDocHostUIHandler))
+    EnableModeless(IDocHostUIHandler);
+#endif
+  else
+    return hRet;
+
+  IUnknown_Release(lpObj);
+  return S_OK;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.357]
+ *
+ * See SHGetNewLinkInfoW.
+ */
+BOOL WINAPI SHGetNewLinkInfoWrapW(LPCWSTR pszLinkTo, LPCWSTR pszDir, LPWSTR pszName,
+                        BOOL *pfMustCopy, UINT uFlags)
+{
+  GET_FUNC(pSHGetNewLinkInfoW, shell32, "SHGetNewLinkInfoW", FALSE);
+  return pSHGetNewLinkInfoW(pszLinkTo, pszDir, pszName, pfMustCopy, uFlags);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.358]
+ *
+ * See SHDefExtractIconW.
+ */
+UINT WINAPI SHDefExtractIconWrapW(LPCWSTR pszIconFile, int iIndex, UINT uFlags, HICON* phiconLarge,
+                         HICON* phiconSmall, UINT nIconSize)
+{
+  GET_FUNC(pSHDefExtractIconW, shell32, "SHDefExtractIconW", 0);
+  return pSHDefExtractIconW(pszIconFile, iIndex, uFlags, phiconLarge, phiconSmall, nIconSize);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.363]
+ *
+ * Get and show a context menu from a shell folder.
+ *
+ * PARAMS
+ *  hWnd           [I] Window displaying the shell folder
+ *  lpFolder       [I] IShellFolder interface
+ *  lpApidl        [I] Id for the particular folder desired
+ *  bInvokeDefault [I] Whether to invoke the default menu item
+ *
+ * RETURNS
+ *  Success: S_OK. If bInvokeDefault is TRUE, the default menu action was
+ *           executed.
+ *  Failure: An HRESULT error code indicating the error.
+ */
+HRESULT WINAPI SHInvokeCommand(HWND hWnd, IShellFolder* lpFolder, LPCITEMIDLIST lpApidl, BOOL bInvokeDefault)
+{
+  IContextMenu *iContext;
+  HRESULT hRet = E_FAIL;
+
+  TRACE("(%p,%p,%p,%d)\n", hWnd, lpFolder, lpApidl, bInvokeDefault);
+
+  if (!lpFolder)
+    return hRet;
+
+  /* Get the context menu from the shell folder */
+  hRet = IShellFolder_GetUIObjectOf(lpFolder, hWnd, 1, &lpApidl,
+                                    &IID_IContextMenu, 0, (void**)&iContext);
+  if (SUCCEEDED(hRet))
+  {
+    HMENU hMenu;
+    if ((hMenu = CreatePopupMenu()))
+    {
+      HRESULT hQuery;
+      DWORD dwDefaultId = 0;
+
+      /* Add the context menu entries to the popup */
+      hQuery = IContextMenu_QueryContextMenu(iContext, hMenu, 0, 1, 0x7FFF,
+                                             bInvokeDefault ? CMF_NORMAL : CMF_DEFAULTONLY);
+
+      if (SUCCEEDED(hQuery))
+      {
+        if (bInvokeDefault &&
+            (dwDefaultId = GetMenuDefaultItem(hMenu, 0, 0)) != 0xFFFFFFFF)
+        {
+          CMINVOKECOMMANDINFO cmIci;
+          /* Invoke the default item */
+          memset(&cmIci,0,sizeof(cmIci));
+          cmIci.cbSize = sizeof(cmIci);
+          cmIci.fMask = CMIC_MASK_ASYNCOK;
+          cmIci.hwnd = hWnd;
+          cmIci.lpVerb = MAKEINTRESOURCEA(dwDefaultId);
+          cmIci.nShow = SW_SCROLLCHILDREN;
+
+          hRet = IContextMenu_InvokeCommand(iContext, &cmIci);
+        }
+      }
+      DestroyMenu(hMenu);
+    }
+    IContextMenu_Release(iContext);
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.370]
+ *
+ * See ExtractIconW.
+ */
+HICON WINAPI ExtractIconWrapW(HINSTANCE hInstance, LPCWSTR lpszExeFileName,
+                         UINT nIconIndex)
+{
+  GET_FUNC(pExtractIconW, shell32, "ExtractIconW", NULL);
+  return pExtractIconW(hInstance, lpszExeFileName, nIconIndex);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.376]
+ */
+LANGID WINAPI MLGetUILanguage()
+{
+    FIXME("() stub\n");
+    /* FIXME: This should be a forward in the .spec file to the win2k function
+     * kernel32.GetUserDefaultUILanguage, however that function isn't there yet.
+     */
+    return GetUserDefaultLangID();
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.377]
+ *
+ * Load a library from the directory of a particular process.
+ *
+ * PARAMS
+ *  new_mod   [I] Library name
+ *  inst_hwnd [I] Module whose directory is to be used
+ *  dwFlags   [I] Flags controlling the load
+ *
+ * RETURNS
+ *  Success: A handle to the loaded module
+ *  Failure: A NULL handle.
+ */
+HMODULE WINAPI MLLoadLibraryA(LPCSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
+{
+  /* FIXME: Native appears to do DPA_Create and a DPA_InsertPtr for
+   *        each call here.
+   * FIXME: Native shows calls to:
+   *  SHRegGetUSValue for "Software\Microsoft\Internet Explorer\International"
+   *                      CheckVersion
+   *  RegOpenKeyExA for "HKLM\Software\Microsoft\Internet Explorer"
+   *  RegQueryValueExA for "LPKInstalled"
+   *  RegCloseKey
+   *  RegOpenKeyExA for "HKCU\Software\Microsoft\Internet Explorer\International"
+   *  RegQueryValueExA for "ResourceLocale"
+   *  RegCloseKey
+   *  RegOpenKeyExA for "HKLM\Software\Microsoft\Active Setup\Installed Components\{guid}"
+   *  RegQueryValueExA for "Locale"
+   *  RegCloseKey
+   *  and then tests the Locale ("en" for me).
+   *     code below
+   *  after the code then a DPA_Create (first time) and DPA_InsertPtr are done.
+   */
+    CHAR mod_path[2*MAX_PATH];
+    LPSTR ptr;
+    DWORD len;
+
+    FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_a(new_mod), inst_hwnd, dwFlags);
+    len = GetModuleFileNameA(inst_hwnd, mod_path, sizeof(mod_path));
+    if (!len || len >= sizeof(mod_path)) return NULL;
+
+    ptr = strrchr(mod_path, '\\');
+    if (ptr) {
+       strcpy(ptr+1, new_mod);
+       TRACE("loading %s\n", debugstr_a(mod_path));
+       return LoadLibraryA(mod_path);
+    }
+    return NULL;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.378]
+ *
+ * Unicode version of MLLoadLibraryA.
+ */
+HMODULE WINAPI MLLoadLibraryW(LPCWSTR new_mod, HMODULE inst_hwnd, DWORD dwFlags)
+{
+    WCHAR mod_path[2*MAX_PATH];
+    LPWSTR ptr;
+    DWORD len;
+
+    FIXME("(%s,%p,0x%08lx) semi-stub!\n", debugstr_w(new_mod), inst_hwnd, dwFlags);
+    len = GetModuleFileNameW(inst_hwnd, mod_path, sizeof(mod_path) / sizeof(WCHAR));
+    if (!len || len >= sizeof(mod_path) / sizeof(WCHAR)) return NULL;
+
+    ptr = strrchrW(mod_path, '\\');
+    if (ptr) {
+       strcpyW(ptr+1, new_mod);
+       TRACE("loading %s\n", debugstr_w(mod_path));
+       return LoadLibraryW(mod_path);
+    }
+    return NULL;
+}
+
+/*************************************************************************
+ * ColorAdjustLuma      [SHLWAPI.@]
+ *
+ * Adjust the luminosity of a color
+ *
+ * PARAMS
+ *  cRGB         [I] RGB value to convert
+ *  dwLuma       [I] Luma adjustment
+ *  bUnknown     [I] Unknown
+ *
+ * RETURNS
+ *  The adjusted RGB color.
+ */
+COLORREF WINAPI ColorAdjustLuma(COLORREF cRGB, int dwLuma, BOOL bUnknown)
+{
+  TRACE("(0x%8lx,%d,%d)\n", cRGB, dwLuma, bUnknown);
+
+  if (dwLuma)
+  {
+    WORD wH, wL, wS;
+
+    ColorRGBToHLS(cRGB, &wH, &wL, &wS);
+
+    FIXME("Ignoring luma adjustment\n");
+
+    /* FIXME: The ajdustment is not linear */
+
+    cRGB = ColorHLSToRGB(wH, wL, wS);
+  }
+  return cRGB;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.389]
+ *
+ * See GetSaveFileNameW.
+ */
+BOOL WINAPI GetSaveFileNameWrapW(LPOPENFILENAMEW ofn)
+{
+  GET_FUNC(pGetSaveFileNameW, comdlg32, "GetSaveFileNameW", FALSE);
+  return pGetSaveFileNameW(ofn);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.390]
+ *
+ * See WNetRestoreConnectionW.
+ */
+DWORD WINAPI WNetRestoreConnectionWrapW(HWND hwndOwner, LPWSTR lpszDevice)
+{
+  GET_FUNC(pWNetRestoreConnectionW, mpr, "WNetRestoreConnectionW", 0);
+  return pWNetRestoreConnectionW(hwndOwner, lpszDevice);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.391]
+ *
+ * See WNetGetLastErrorW.
+ */
+DWORD WINAPI WNetGetLastErrorWrapW(LPDWORD lpError, LPWSTR lpErrorBuf, DWORD nErrorBufSize,
+                         LPWSTR lpNameBuf, DWORD nNameBufSize)
+{
+  GET_FUNC(pWNetGetLastErrorW, mpr, "WNetGetLastErrorW", 0);
+  return pWNetGetLastErrorW(lpError, lpErrorBuf, nErrorBufSize, lpNameBuf, nNameBufSize);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.401]
+ *
+ * See PageSetupDlgW.
+ */
+BOOL WINAPI PageSetupDlgWrapW(LPPAGESETUPDLGW pagedlg)
+{
+  GET_FUNC(pPageSetupDlgW, comdlg32, "PageSetupDlgW", FALSE);
+  return pPageSetupDlgW(pagedlg);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.402]
+ *
+ * See PrintDlgW.
+ */
+BOOL WINAPI PrintDlgWrapW(LPPRINTDLGW printdlg)
+{
+  GET_FUNC(pPrintDlgW, comdlg32, "PrintDlgW", FALSE);
+  return pPrintDlgW(printdlg);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.403]
+ *
+ * See GetOpenFileNameW.
+ */
+BOOL WINAPI GetOpenFileNameWrapW(LPOPENFILENAMEW ofn)
+{
+  GET_FUNC(pGetOpenFileNameW, comdlg32, "GetOpenFileNameW", FALSE);
+  return pGetOpenFileNameW(ofn);
+}
+
+/* INTERNAL: Map from HLS color space to RGB */
+static WORD WINAPI ConvertHue(int wHue, WORD wMid1, WORD wMid2)
+{
+  wHue = wHue > 240 ? wHue - 240 : wHue < 0 ? wHue + 240 : wHue;
+
+  if (wHue > 160)
+    return wMid1;
+  else if (wHue > 120)
+    wHue = 160 - wHue;
+  else if (wHue > 40)
+    return wMid2;
+
+  return ((wHue * (wMid2 - wMid1) + 20) / 40) + wMid1;
+}
+
+/* Convert to RGB and scale into RGB range (0..255) */
+#define GET_RGB(h) (ConvertHue(h, wMid1, wMid2) * 255 + 120) / 240
+
+/*************************************************************************
+ *      ColorHLSToRGB  [SHLWAPI.@]
+ *
+ * Convert from hls color space into an rgb COLORREF.
+ *
+ * PARAMS
+ *  wHue        [I] Hue amount
+ *  wLuminosity [I] Luminosity amount
+ *  wSaturation [I] Saturation amount
+ *
+ * RETURNS
+ *  A COLORREF representing the converted color.
+ *
+ * NOTES
+ *  Input hls values are constrained to the range (0..240).
+ */
+COLORREF WINAPI ColorHLSToRGB(WORD wHue, WORD wLuminosity, WORD wSaturation)
+{
+  WORD wRed;
+
+  if (wSaturation)
+  {
+    WORD wGreen, wBlue, wMid1, wMid2;
+
+    if (wLuminosity > 120)
+      wMid2 = wSaturation + wLuminosity - (wSaturation * wLuminosity + 120) / 240;
+    else
+      wMid2 = ((wSaturation + 240) * wLuminosity + 120) / 240;
+
+    wMid1 = wLuminosity * 2 - wMid2;
+
+    wRed   = GET_RGB(wHue + 80);
+    wGreen = GET_RGB(wHue);
+    wBlue  = GET_RGB(wHue - 80);
+
+    return RGB(wRed, wGreen, wBlue);
+  }
+
+  wRed = wLuminosity * 255 / 240;
+  return RGB(wRed, wRed, wRed);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.413]
+ *
+ * Get the current docking status of the system.
+ *
+ * PARAMS
+ *  dwFlags [I] DOCKINFO_ flags from "winbase.h", unused
+ *
+ * RETURNS
+ *  One of DOCKINFO_UNDOCKED, DOCKINFO_UNDOCKED, or 0 if the system is not
+ *  a notebook.
+ */
+DWORD WINAPI SHGetMachineInfo(DWORD dwFlags)
+{
+  HW_PROFILE_INFOA hwInfo;
+
+  TRACE("(0x%08lx)\n", dwFlags);
+
+  GetCurrentHwProfileA(&hwInfo);
+  switch (hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED))
+  {
+  case DOCKINFO_DOCKED:
+  case DOCKINFO_UNDOCKED:
+    return hwInfo.dwDockInfo & (DOCKINFO_DOCKED|DOCKINFO_UNDOCKED);
+  default:
+    return 0;
+  }
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.418]
+ *
+ * Function seems to do FreeLibrary plus other things.
+ *
+ * FIXME native shows the following calls:
+ *   RtlEnterCriticalSection
+ *   LocalFree
+ *   GetProcAddress(Comctl32??, 150L)
+ *   DPA_DeletePtr
+ *   RtlLeaveCriticalSection
+ *  followed by the FreeLibrary.
+ *  The above code may be related to .377 above.
+ */
+BOOL WINAPI MLFreeLibrary(HMODULE hModule)
+{
+       FIXME("(%p) semi-stub\n", hModule);
+       return FreeLibrary(hModule);
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.419]
+ */
+BOOL WINAPI SHFlushSFCacheWrap(void) {
+  FIXME(": stub\n");
+  return TRUE;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.429]
+ * FIXME I have no idea what this function does or what its arguments are.
+ */
+BOOL WINAPI MLIsMLHInstance(HINSTANCE hInst)
+{
+       FIXME("(%p) stub\n", hInst);
+       return FALSE;
+}
+
+
+/*************************************************************************
+ *      @      [SHLWAPI.430]
+ */
+DWORD WINAPI MLSetMLHInstance(HINSTANCE hInst, HANDLE hHeap)
+{
+       FIXME("(%p,%p) stub\n", hInst, hHeap);
+       return E_FAIL;   /* This is what is used if shlwapi not loaded */
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.431]
+ */
+DWORD WINAPI MLClearMLHInstance(DWORD x)
+{
+       FIXME("(0x%08lx)stub\n", x);
+       return 0xabba1247;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.436]
+ *
+ * Convert an Unicode string CLSID into a CLSID.
+ *
+ * PARAMS
+ *  idstr      [I]   string containing a CLSID in text form
+ *  id         [O]   CLSID extracted from the string
+ *
+ * RETURNS
+ *  S_OK on success or E_INVALIDARG on failure
+ *
+ * NOTES
+ *  This is really CLSIDFromString() which is exported by ole32.dll,
+ *  however the native shlwapi.dll does *not* import ole32. Nor does
+ *  ole32.dll import this ordinal from shlwapi. Therefore we must conclude
+ *  that MS duplicated the code for CLSIDFromString(), and yes they did, only
+ *  it returns an E_INVALIDARG error code on failure.
+ *  This is a duplicate (with changes for Unicode) of CLSIDFromString16()
+ *  in "dlls/ole32/compobj.c".
+ */
+HRESULT WINAPI CLSIDFromStringWrap(LPCWSTR idstr, CLSID *id)
+{
+       LPCWSTR s = idstr;
+       BYTE *p;
+       INT i;
+       WCHAR table[256];
+
+       if (!s) {
+         memset(id, 0, sizeof(CLSID));
+         return S_OK;
+       }
+       else {  /* validate the CLSID string */
+
+         if (strlenW(s) != 38)
+           return E_INVALIDARG;
+
+         if ((s[0]!=L'{') || (s[9]!=L'-') || (s[14]!=L'-') || (s[19]!=L'-') || (s[24]!=L'-') || (s[37]!=L'}'))
+           return E_INVALIDARG;
+
+         for (i=1; i<37; i++)
+         {
+           if ((i == 9)||(i == 14)||(i == 19)||(i == 24))
+             continue;
+           if (!(((s[i] >= L'0') && (s[i] <= L'9'))  ||
+               ((s[i] >= L'a') && (s[i] <= L'f'))  ||
+               ((s[i] >= L'A') && (s[i] <= L'F')))
+              )
+             return E_INVALIDARG;
+         }
+       }
+
+    TRACE("%s -> %p\n", debugstr_w(s), id);
+
+  /* quick lookup table */
+    memset(table, 0, 256*sizeof(WCHAR));
+
+    for (i = 0; i < 10; i++) {
+       table['0' + i] = i;
+    }
+    for (i = 0; i < 6; i++) {
+       table['A' + i] = i+10;
+       table['a' + i] = i+10;
+    }
+
+    /* in form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
+
+    p = (BYTE *) id;
+
+    s++;       /* skip leading brace  */
+    for (i = 0; i < 4; i++) {
+       p[3 - i] = table[*s]<<4 | table[*(s+1)];
+       s += 2;
+    }
+    p += 4;
+    s++;       /* skip - */
+
+    for (i = 0; i < 2; i++) {
+       p[1-i] = table[*s]<<4 | table[*(s+1)];
+       s += 2;
+    }
+    p += 2;
+    s++;       /* skip - */
+
+    for (i = 0; i < 2; i++) {
+       p[1-i] = table[*s]<<4 | table[*(s+1)];
+       s += 2;
+    }
+    p += 2;
+    s++;       /* skip - */
+
+    /* these are just sequential bytes */
+    for (i = 0; i < 2; i++) {
+       *p++ = table[*s]<<4 | table[*(s+1)];
+       s += 2;
+    }
+    s++;       /* skip - */
+
+    for (i = 0; i < 6; i++) {
+       *p++ = table[*s]<<4 | table[*(s+1)];
+       s += 2;
+    }
+
+    return S_OK;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.437]
+ *
+ * Determine if the OS supports a given feature.
+ *
+ * PARAMS
+ *  dwFeature [I] Feature requested (undocumented)
+ *
+ * RETURNS
+ *  TRUE  If the feature is available.
+ *  FALSE If the feature is not available.
+ */
+BOOL WINAPI IsOS(DWORD feature)
+{
+    OSVERSIONINFOA osvi;
+    DWORD platform, majorv, minorv;
+
+    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
+    if(!GetVersionExA(&osvi))  {
+        ERR("GetVersionEx failed");
+        return FALSE;
+    }
+
+    majorv = osvi.dwMajorVersion;
+    minorv = osvi.dwMinorVersion;
+    platform = osvi.dwPlatformId;
+
+#define ISOS_RETURN(x) \
+    TRACE("(0x%lx) ret=%d\n",feature,(x)); \
+    return (x);
+
+    switch(feature)  {
+    case OS_WIN32SORGREATER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32s
+                 || platform == VER_PLATFORM_WIN32_WINDOWS)
+    case OS_NT:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
+    case OS_WIN95ORGREATER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS)
+    case OS_NT4ORGREATER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 4)
+    case OS_WIN2000ORGREATER_ALT:
+    case OS_WIN2000ORGREATER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
+    case OS_WIN98ORGREATER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 10)
+    case OS_WIN98_GOLD:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 10)
+    case OS_WIN2000PRO:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
+    case OS_WIN2000SERVER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
+    case OS_WIN2000ADVSERVER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
+    case OS_WIN2000DATACENTER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
+    case OS_WIN2000TERMINAL:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && (minorv == 0 || minorv == 1))
+    case OS_EMBEDDED:
+        FIXME("(OS_EMBEDDED) What should we return here?\n");
+        return FALSE;
+    case OS_TERMINALCLIENT:
+        FIXME("(OS_TERMINALCLIENT) What should we return here?\n");
+        return FALSE;
+    case OS_TERMINALREMOTEADMIN:
+        FIXME("(OS_TERMINALREMOTEADMIN) What should we return here?\n");
+        return FALSE;
+    case OS_WIN95_GOLD:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv == 0)
+    case OS_MEORGREATER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_WINDOWS && minorv >= 90)
+    case OS_XPORGREATER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
+    case OS_HOME:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
+    case OS_PROFESSIONAL:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
+    case OS_DATACENTER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
+    case OS_ADVSERVER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5)
+    case OS_SERVER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
+    case OS_TERMINALSERVER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
+    case OS_PERSONALTERMINALSERVER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && minorv >= 1 && majorv >= 5)
+    case OS_FASTUSERSWITCHING:
+        FIXME("(OS_FASTUSERSWITCHING) What should we return here?\n");
+        return TRUE;
+    case OS_WELCOMELOGONUI:
+        FIXME("(OS_WELCOMELOGONUI) What should we return here?\n");
+        return FALSE;
+    case OS_DOMAINMEMBER:
+        FIXME("(OS_DOMAINMEMBER) What should we return here?\n");
+        return TRUE;
+    case OS_ANYSERVER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
+    case OS_WOW6432:
+        FIXME("(OS_WOW6432) Should we check this?\n");
+        return FALSE;
+    case OS_WEBSERVER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
+    case OS_SMALLBUSINESSSERVER:
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
+    case OS_TABLETPC:
+        FIXME("(OS_TABLEPC) What should we return here?\n");
+        return FALSE;
+    case OS_SERVERADMINUI:
+        FIXME("(OS_SERVERADMINUI) What should we return here?\n");
+        return FALSE;
+    case OS_MEDIACENTER:
+        FIXME("(OS_MEDIACENTER) What should we return here?\n");
+        return FALSE;
+    case OS_APPLIANCE:
+        FIXME("(OS_APPLIANCE) What should we return here?\n");
+        return FALSE;
+    }
+
+#undef ISOS_RETURN
+
+    WARN("(0x%lx) unknown parameter\n",feature);
+
+    return FALSE;
+}
+
+/*************************************************************************
+ * @  [SHLWAPI.478]
+ *
+ * Call IInputObject_TranslateAcceleratorIO() on an object.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object supporting the IInputObject interface.
+ *  lpMsg     [I] Key message to be processed.
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
+ */
+HRESULT WINAPI IUnknown_TranslateAcceleratorIO(IUnknown *lpUnknown, LPMSG lpMsg)
+{
+  IInputObject* lpInput = NULL;
+  HRESULT hRet = E_INVALIDARG;
+
+  TRACE("(%p,%p)\n", lpUnknown, lpMsg);
+  if (lpUnknown)
+  {
+    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
+                                   (void**)&lpInput);
+    if (SUCCEEDED(hRet) && lpInput)
+    {
+      hRet = IInputObject_TranslateAcceleratorIO(lpInput, lpMsg);
+      IInputObject_Release(lpInput);
+    }
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ * @  [SHLWAPI.481]
+ *
+ * Call IInputObject_HasFocusIO() on an object.
+ *
+ * PARAMS
+ *  lpUnknown [I] Object supporting the IInputObject interface.
+ *
+ * RETURNS
+ *  Success: S_OK, if lpUnknown is an IInputObject object and has the focus,
+ *           or S_FALSE otherwise.
+ *  Failure: An HRESULT error code, or E_INVALIDARG if lpUnknown is NULL.
+ */
+HRESULT WINAPI IUnknown_HasFocusIO(IUnknown *lpUnknown)
+{
+  IInputObject* lpInput = NULL;
+  HRESULT hRet = E_INVALIDARG;
+
+  TRACE("(%p)\n", lpUnknown);
+  if (lpUnknown)
+  {
+    hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObject,
+                                   (void**)&lpInput);
+    if (SUCCEEDED(hRet) && lpInput)
+    {
+      hRet = IInputObject_HasFocusIO(lpInput);
+      IInputObject_Release(lpInput);
+    }
+  }
+  return hRet;
+}
+
+/*************************************************************************
+ *      ColorRGBToHLS  [SHLWAPI.@]
+ *
+ * Convert an rgb COLORREF into the hls color space.
+ *
+ * PARAMS
+ *  cRGB         [I] Source rgb value
+ *  pwHue        [O] Destination for converted hue
+ *  pwLuminance  [O] Destination for converted luminance
+ *  pwSaturation [O] Destination for converted saturation
+ *
+ * RETURNS
+ *  Nothing. pwHue, pwLuminance and pwSaturation are set to the converted
+ *  values.
+ *
+ * NOTES
+ *  Output HLS values are constrained to the range (0..240).
+ *  For Achromatic conversions, Hue is set to 160.
+ */
+VOID WINAPI ColorRGBToHLS(COLORREF cRGB, LPWORD pwHue,
+                         LPWORD pwLuminance, LPWORD pwSaturation)
+{
+  int wR, wG, wB, wMax, wMin, wHue, wLuminosity, wSaturation;
+
+  TRACE("(%08lx,%p,%p,%p)\n", cRGB, pwHue, pwLuminance, pwSaturation);
+
+  wR = GetRValue(cRGB);
+  wG = GetGValue(cRGB);
+  wB = GetBValue(cRGB);
+
+  wMax = max(wR, max(wG, wB));
+  wMin = min(wR, min(wG, wB));
+
+  /* Luminosity */
+  wLuminosity = ((wMax + wMin) * 240 + 255) / 510;
+
+  if (wMax == wMin)
+  {
+    /* Achromatic case */
+    wSaturation = 0;
+    /* Hue is now unrepresentable, but this is what native returns... */
+    wHue = 160;
+  }
+  else
+  {
+    /* Chromatic case */
+    int wDelta = wMax - wMin, wRNorm, wGNorm, wBNorm;
+
+    /* Saturation */
+    if (wLuminosity <= 120)
+      wSaturation = ((wMax + wMin)/2 + wDelta * 240) / (wMax + wMin);
+    else
+      wSaturation = ((510 - wMax - wMin)/2 + wDelta * 240) / (510 - wMax - wMin);
+
+    /* Hue */
+    wRNorm = (wDelta/2 + wMax * 40 - wR * 40) / wDelta;
+    wGNorm = (wDelta/2 + wMax * 40 - wG * 40) / wDelta;
+    wBNorm = (wDelta/2 + wMax * 40 - wB * 40) / wDelta;
+
+    if (wR == wMax)
+      wHue = wBNorm - wGNorm;
+    else if (wG == wMax)
+      wHue = 80 + wRNorm - wBNorm;
+    else
+      wHue = 160 + wGNorm - wRNorm;
+    if (wHue < 0)
+      wHue += 240;
+    else if (wHue > 240)
+      wHue -= 240;
+  }
+  if (pwHue)
+    *pwHue = wHue;
+  if (pwLuminance)
+    *pwLuminance = wLuminosity;
+  if (pwSaturation)
+    *pwSaturation = wSaturation;
+}
+
+/*************************************************************************
+ *      SHCreateShellPalette   [SHLWAPI.@]
+ */
+HPALETTE WINAPI SHCreateShellPalette(HDC hdc)
+{
+       FIXME("stub\n");
+       return CreateHalftonePalette(hdc);
+}
+
+/*************************************************************************
+ *     SHGetInverseCMAP (SHLWAPI.@)
+ *
+ * Get an inverse color map table.
+ *
+ * PARAMS
+ *  lpCmap  [O] Destination for color map
+ *  dwSize  [I] Size of memory pointed to by lpCmap
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: E_POINTER,    If lpCmap is invalid.
+ *           E_INVALIDARG, If dwFlags is invalid
+ *           E_OUTOFMEMORY, If there is no memory available
+ *
+ * NOTES
+ *  dwSize may only be CMAP_PTR_SIZE (4) or CMAP_SIZE (8192).
+ *  If dwSize = CMAP_PTR_SIZE, *lpCmap is set to the address of this DLL's
+ *  internal CMap.
+ *  If dwSize = CMAP_SIZE, lpCmap is filled with a copy of the data from
+ *  this DLL's internal CMap.
+ */
+HRESULT WINAPI SHGetInverseCMAP(LPDWORD dest, DWORD dwSize)
+{
+    if (dwSize == 4) {
+       FIXME(" - returning bogus address for SHGetInverseCMAP\n");
+       *dest = (DWORD)0xabba1249;
+       return 0;
+    }
+    FIXME("(%p, %#lx) stub\n", dest, dwSize);
+    return 0;
+}
+
+/*************************************************************************
+ *      SHIsLowMemoryMachine   [SHLWAPI.@]
+ *
+ * Determine if the current computer has low memory.
+ *
+ * PARAMS
+ *  x [I] FIXME
+ *
+ * RETURNS
+ *  TRUE if the users machine has 16 Megabytes of memory or less,
+ *  FALSE otherwise.
+ */
+BOOL WINAPI SHIsLowMemoryMachine (DWORD x)
+{
+  FIXME("(0x%08lx) stub\n", x);
+  return FALSE;
+}
+
+/*************************************************************************
+ *      GetMenuPosFromID       [SHLWAPI.@]
+ *
+ * Return the position of a menu item from its Id.
+ *
+ * PARAMS
+ *   hMenu [I] Menu containing the item
+ *   wID   [I] Id of the menu item
+ *
+ * RETURNS
+ *  Success: The index of the menu item in hMenu.
+ *  Failure: -1, If the item is not found.
+ */
+INT WINAPI GetMenuPosFromID(HMENU hMenu, UINT wID)
+{
+ MENUITEMINFOA mi;
+ INT nCount = GetMenuItemCount(hMenu), nIter = 0;
+
+ while (nIter < nCount)
+ {
+   mi.wID = 0;
+   if (!GetMenuItemInfoA(hMenu, nIter, TRUE, &mi) && mi.wID == wID)
+     return nIter;
+   nIter++;
+ }
+ return -1;
+}
+
+/*************************************************************************
+ *      @      [SHLWAPI.179]
+ *
+ * Same as SHLWAPI.GetMenuPosFromID
+ */
+DWORD WINAPI SHMenuIndexFromID(HMENU hMenu, UINT uID)
+{
+    return GetMenuPosFromID(hMenu, uID);
+}
+
+
+/*************************************************************************
+ *      @      [SHLWAPI.448]
+ */
+VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
+{
+    while (*lpwstr)
+    {
+        if (*lpwstr == '/')
+            *lpwstr = '\\';
+        lpwstr++;
+    }
+}
+
+
+/*************************************************************************
+ *      @      [SHLWAPI.461]
+ */
+DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
+{
+  FIXME("(0x%08lx) stub\n", dwUnknown);
+  return 0;
+}
+
+
+/*************************************************************************
+ *      @      [SHLWAPI.549]
+ */
+HRESULT WINAPI SHCoCreateInstanceAC(REFCLSID rclsid, LPUNKNOWN pUnkOuter,
+                                    DWORD dwClsContext, REFIID iid, LPVOID *ppv)
+{
+    return CoCreateInstance(rclsid, pUnkOuter, dwClsContext, iid, ppv);
+}
+
+/*************************************************************************
+ * SHSkipJunction      [SHLWAPI.@]
+ *
+ * Determine if a bind context can be bound to an object
+ *
+ * PARAMS
+ *  pbc    [I] Bind context to check
+ *  pclsid [I] CLSID of object to be bound to
+ *
+ * RETURNS
+ *  TRUE: If it is safe to bind
+ *  FALSE: If pbc is invalid or binding would not be safe
+ *
+ */
+BOOL WINAPI SHSkipJunction(IBindCtx *pbc, const CLSID *pclsid)
+{
+  static const WCHAR szSkipBinding[] = { 'S','k','i','p',' ',
+    'B','i','n','d','i','n','g',' ','C','L','S','I','D','\0' };
+  BOOL bRet = FALSE;
+
+  if (pbc)
+  {
+    IUnknown* lpUnk;
+
+    if (SUCCEEDED(IBindCtx_GetObjectParam(pbc, (LPOLESTR)szSkipBinding, &lpUnk)))
+    {
+      CLSID clsid;
+
+      if (SUCCEEDED(IUnknown_GetClassID(lpUnk, &clsid)) &&
+          IsEqualGUID(pclsid, &clsid))
+        bRet = TRUE;
+
+      IUnknown_Release(lpUnk);
+    }
+  }
+  return bRet;
+}
+
+/***********************************************************************
+ *             SHGetShellKey (SHLWAPI.@)
+ */
+DWORD WINAPI SHGetShellKey(DWORD a, DWORD b, DWORD c)
+{
+    FIXME("(%lx, %lx, %lx): stub\n", a, b, c);
+    return 0x50;
+}
+
+/***********************************************************************
+ *             SHQueueUserWorkItem (SHLWAPI.@)
+ */
+HRESULT WINAPI SHQueueUserWorkItem(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e, DWORD f, DWORD g)
+{
+    FIXME("(%lx, %lx, %lx, %lx, %lx, %lx, %lx): stub\n", a, b, c, d, e, f, g);
+    return E_FAIL;
+}
+
+/***********************************************************************
+ *             IUnknown_OnFocusChangeIS (SHLWAPI.@)
+ */
+HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
+{
+    IInputObjectSite *pIOS = NULL;
+    HRESULT hRet = E_INVALIDARG;
+
+    TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
+
+    if (lpUnknown)
+    {
+        hRet = IUnknown_QueryInterface(lpUnknown, &IID_IInputObjectSite,
+                                       (void **)&pIOS);
+        if (SUCCEEDED(hRet) && pIOS)
+        {
+            hRet = IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bFocus);
+            IInputObjectSite_Release(pIOS);
+        }
+    }
+    return hRet;
+}
+
+/***********************************************************************
+ *             SHGetValueW (SHLWAPI.@)
+ */
+HRESULT WINAPI SKGetValueW(DWORD a, LPWSTR b, LPWSTR c, DWORD d, DWORD e, DWORD f)
+{
+    FIXME("(%lx, %s, %s, %lx, %lx, %lx): stub\n", a, debugstr_w(b), debugstr_w(c), d, e, f);
+    return E_FAIL;
+}
+
+typedef HRESULT (WINAPI *DllGetVersion_func)(DLLVERSIONINFO *);
+
+/***********************************************************************
+ *              GetUIVersion (SHLWAPI.452)
+ */
+DWORD WINAPI GetUIVersion(void)
+{
+    static DWORD version;
+
+    if (!version)
+    {
+        DllGetVersion_func pDllGetVersion;
+        HMODULE dll = LoadLibraryA("shell32.dll");
+        if (!dll) return 0;
+
+        pDllGetVersion = (DllGetVersion_func)GetProcAddress(dll, "DllGetVersion");
+        if (pDllGetVersion)
+        {
+            DLLVERSIONINFO dvi;
+            dvi.cbSize = sizeof(DLLVERSIONINFO);
+            if (pDllGetVersion(&dvi) == S_OK) version = dvi.dwMajorVersion;
+        }
+        FreeLibrary( dll );
+        if (!version) version = 3;  /* old shell dlls don't have DllGetVersion */
+    }
+    return version;
+}