Sync to Wine-20050725:
[reactos.git] / reactos / lib / shlwapi / ordinal.c
index ba15832..530b57c 100644 (file)
 #include "shlguid.h"
 #include "wingdi.h"
 #include "shlobj.h"
-#include "olectl.h"
 #include "shellapi.h"
 #include "commdlg.h"
 #include "wine/unicode.h"
-#include "servprov.h"
 #include "winreg.h"
 #include "wine/debug.h"
 #include "shlwapi.h"
-#include "winnt.h"
 
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
@@ -142,7 +139,7 @@ BOOL    WINAPI SHAboutInfoW(LPWSTR,DWORD);
  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 DLL's, some late bound calls may
+ 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!
 */
@@ -576,8 +573,8 @@ HRESULT WINAPI GetAcceptLanguagesW( LPWSTR langbuf, LPDWORD buflen)
     }
     memcpy( langbuf, mystr, min(*buflen,strlenW(mystr)+1)*sizeof(WCHAR) );
 
-    if(*buflen > lstrlenW(mystr)) {
-       *buflen = lstrlenW(mystr);
+    if(*buflen > strlenW(mystr)) {
+       *buflen = strlenW(mystr);
        retval = S_OK;
     } else {
        *buflen = 0;
@@ -611,7 +608,7 @@ HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
                                   *buflen, NULL, NULL);
     *buflen = buflenW ? convlen : 0;
 
-    if(langbufW) HeapFree(GetProcessHeap(), 0, langbufW);
+    HeapFree(GetProcessHeap(), 0, langbufW);
     return retval;
 }
 
@@ -621,9 +618,9 @@ HRESULT WINAPI GetAcceptLanguagesA( LPSTR langbuf, LPDWORD buflen)
  * Convert a GUID to a string.
  *
  * PARAMS
- *  guid [I] GUID to convert
- *  str  [O] Destination for string
- *  cmax [I] Length of output buffer
+ *  guid     [I] GUID to convert
+ *  lpszDest [O] Destination for string
+ *  cchMax   [I] Length of output buffer
  *
  * RETURNS
  *  The length of the string created.
@@ -651,84 +648,36 @@ INT WINAPI SHStringFromGUIDA(REFGUID guid, LPSTR lpszDest, INT cchMax)
 /*************************************************************************
  *      @      [SHLWAPI.24]
  *
- * Unicode version of SHStringFromGUIDA.
- */
-INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
-{
-  char xguid[40];
-  INT iLen = SHStringFromGUIDA(guid, xguid, cchMax);
-
-  if (iLen)
-    MultiByteToWideChar(CP_ACP, 0, xguid, -1, lpszDest, cchMax);
-  return iLen;
-}
-
-/*************************************************************************
- *      @      [SHLWAPI.25]
- *
- * Determine if a Unicode character is alphabetic.
+ * Convert a GUID to a string.
  *
  * PARAMS
- *  wc [I] Character to check.
+ *  guid [I] GUID to convert
+ *  str  [O] Destination for string
+ *  cmax [I] Length of output buffer
  *
  * RETURNS
- *  TRUE, if wc is alphabetic,
- *  FALSE otherwise.
+ *  The length of the string created.
  */
-BOOL WINAPI IsCharAlphaWrapW(WCHAR wc)
+INT WINAPI SHStringFromGUIDW(REFGUID guid, LPWSTR lpszDest, INT cchMax)
 {
-    return (get_char_typeW(wc) & C1_ALPHA) != 0;
-}
+  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};
 
-/*************************************************************************
- *      @      [SHLWAPI.26]
- *
- * Determine if a Unicode character is upper-case.
- *
- * PARAMS
- *  wc [I] Character to check.
- *
- * RETURNS
- *  TRUE, if wc is upper-case,
- *  FALSE otherwise.
- */
-BOOL WINAPI IsCharUpperWrapW(WCHAR wc)
-{
-    return (get_char_typeW(wc) & C1_UPPER) != 0;
-}
+  TRACE("(%s,%p,%d)\n", debugstr_guid(guid), lpszDest, cchMax);
 
-/*************************************************************************
- *      @      [SHLWAPI.27]
- *
- * Determine if a Unicode character is lower-case.
- *
- * PARAMS
- *  wc [I] Character to check.
- *
- * RETURNS
- *  TRUE, if wc is lower-case,
- *  FALSE otherwise.
- */
-BOOL WINAPI IsCharLowerWrapW(WCHAR wc)
-{
-    return (get_char_typeW(wc) & C1_LOWER) != 0;
-}
+  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]);
 
-/*************************************************************************
- *      @      [SHLWAPI.28]
- *
- * Determine if a Unicode character is alphabetic or a digit.
- *
- * PARAMS
- *  wc [I] Character to check.
- *
- * RETURNS
- *  TRUE, if wc is alphabetic or a digit,
- *  FALSE otherwise.
- */
-BOOL WINAPI IsCharAlphaNumericWrapW(WCHAR wc)
-{
-    return (get_char_typeW(wc) & (C1_ALPHA|C1_DIGIT)) != 0;
+  iLen = strlenW(xguid) + 1;
+
+  if (iLen > cchMax)
+    return 0;
+  memcpy(lpszDest, xguid, iLen*sizeof(WCHAR));
+  return iLen;
 }
 
 /*************************************************************************
@@ -745,7 +694,9 @@ BOOL WINAPI IsCharAlphaNumericWrapW(WCHAR wc)
  */
 BOOL WINAPI IsCharSpaceW(WCHAR wc)
 {
-    return (get_char_typeW(wc) & C1_SPACE) != 0;
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_SPACE);
 }
 
 /*************************************************************************
@@ -763,7 +714,9 @@ BOOL WINAPI IsCharSpaceW(WCHAR wc)
  */
 BOOL WINAPI IsCharBlankW(WCHAR wc)
 {
-    return (get_char_typeW(wc) & C1_BLANK) != 0;
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_BLANK);
 }
 
 /*************************************************************************
@@ -780,7 +733,9 @@ BOOL WINAPI IsCharBlankW(WCHAR wc)
  */
 BOOL WINAPI IsCharPunctW(WCHAR wc)
 {
-    return (get_char_typeW(wc) & C1_PUNCT) != 0;
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_PUNCT);
 }
 
 /*************************************************************************
@@ -797,7 +752,9 @@ BOOL WINAPI IsCharPunctW(WCHAR wc)
  */
 BOOL WINAPI IsCharCntrlW(WCHAR wc)
 {
-    return (get_char_typeW(wc) & C1_CNTRL) != 0;
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_CNTRL);
 }
 
 /*************************************************************************
@@ -814,7 +771,9 @@ BOOL WINAPI IsCharCntrlW(WCHAR wc)
  */
 BOOL WINAPI IsCharDigitW(WCHAR wc)
 {
-    return (get_char_typeW(wc) & C1_DIGIT) != 0;
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_DIGIT);
 }
 
 /*************************************************************************
@@ -831,7 +790,9 @@ BOOL WINAPI IsCharDigitW(WCHAR wc)
  */
 BOOL WINAPI IsCharXDigitW(WCHAR wc)
 {
-    return (get_char_typeW(wc) & C1_XDIGIT) != 0;
+    WORD CharType;
+
+    return GetStringTypeW(CT_CTYPE1, &wc, 1, &CharType) && (CharType & C1_XDIGIT);
 }
 
 /*************************************************************************
@@ -1378,7 +1339,7 @@ DWORD WINAPI IUnknown_AtomicRelease(IUnknown ** lpUnknown)
     *lpUnknown = NULL;
 
     TRACE("doing Release\n");
-    
+
     return IUnknown_Release(temp);
 }
 
@@ -1436,7 +1397,7 @@ BOOL WINAPI SHIsSameObject(IUnknown* lpInt1, IUnknown* lpInt2)
 
   if (lpUnknown1 == lpUnknown2)
     return TRUE;
-  
+
   return FALSE;
 }
 
@@ -1886,13 +1847,47 @@ DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
   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
+ *  lpUnknown [I] Object supporting the IOleControlSite interface.
  *  lppDisp   [O] Destination for resulting IDispatch.
  *
  * RETURNS
@@ -1901,7 +1896,7 @@ DWORD WINAPI SHLoadFromPropertyBag(IUnknown *lpUnknown, IPropertyBag* lpPropBag)
  */
 DWORD WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, IDispatch** lppDisp)
 {
-  IOleControlSite* lpCSite;
+  IOleControlSite* lpCSite = NULL;
   HRESULT hRet = E_FAIL;
 
   TRACE("(%p,%p)\n", lpUnknown, lppDisp);
@@ -1918,6 +1913,41 @@ DWORD WINAPI IUnknown_OnFocusOCS(IUnknown *lpUnknown, IDispatch** lppDisp)
   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]
  *
@@ -1940,7 +1970,7 @@ HMENU WINAPI SHGetMenuFromID(HMENU hMenu, UINT uID)
   mi.fMask = MIIM_SUBMENU;
 
   if (!GetMenuItemInfoA(hMenu, uID, 0, &mi))
-    return (HMENU)NULL;
+    return NULL;
 
   return mi.hSubMenu;
 }
@@ -2004,6 +2034,55 @@ DWORD WINAPI SHWaitForSendMessageThread(HANDLE hand, DWORD dwTimeout)
   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]
  *
@@ -2089,6 +2168,21 @@ VOID WINAPI IUnknown_Set(IUnknown **lppDest, IUnknown *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]
  *
@@ -2389,6 +2483,29 @@ LRESULT CALLBACK SHDefWindowProc(HWND hWnd, UINT uMessage, WPARAM 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]
  *
@@ -2422,8 +2539,8 @@ HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle
   wc.cbClsExtra    = 0;
   wc.cbWndExtra    = 4;
   wc.hInstance     = shlwapi_hInstance;
-  wc.hIcon         = (HICON)0;
-  wc.hCursor       = LoadCursorA((HINSTANCE)0, (LPSTR)IDC_ARROW);
+  wc.hIcon         = NULL;
+  wc.hCursor       = LoadCursorA(NULL, (LPSTR)IDC_ARROW);
   wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
   wc.lpszMenuName  = NULL;
   wc.lpszClassName = szClass;
@@ -2436,10 +2553,10 @@ HWND WINAPI SHCreateWorkerWindowA(LONG wndProc, HWND hWndParent, DWORD dwExStyle
                          hWndParent, hMenu, shlwapi_hInstance, 0);
   if (hWnd)
   {
-    SetWindowLongA(hWnd, DWL_MSGRESULT, z);
+    SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
 
     if (wndProc)
-      SetWindowLongA(hWnd, GWL_WNDPROC, wndProc);
+      SetWindowLongPtrA(hWnd, GWLP_WNDPROC, wndProc);
   }
   return hWnd;
 }
@@ -2549,7 +2666,7 @@ DWORD WINAPI SHRestrictionLookup(
  *  Failure: An HRESULT error code.
  *
  * NOTES
- *   This QueryInterface asks the inner object for a interface. In case
+ *   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.
@@ -2709,8 +2826,8 @@ HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle
   wc.cbClsExtra    = 0;
   wc.cbWndExtra    = 4;
   wc.hInstance     = shlwapi_hInstance;
-  wc.hIcon         = (HICON)0;
-  wc.hCursor       = LoadCursorA((HINSTANCE)0, (LPSTR)IDC_ARROW);
+  wc.hIcon         = NULL;
+  wc.hCursor       = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
   wc.hbrBackground = (HBRUSH)COLOR_BTNSHADOW;
   wc.lpszMenuName  = NULL;
   wc.lpszClassName = szClass;
@@ -2723,10 +2840,10 @@ HWND WINAPI SHCreateWorkerWindowW(LONG wndProc, HWND hWndParent, DWORD dwExStyle
                          hWndParent, hMenu, shlwapi_hInstance, 0);
   if (hWnd)
   {
-    SetWindowLongA(hWnd, DWL_MSGRESULT, z);
+    SetWindowLongPtrW(hWnd, DWLP_MSGRESULT, z);
 
     if (wndProc)
-      SetWindowLongA(hWnd, GWL_WNDPROC, wndProc);
+      SetWindowLongPtrW(hWnd, GWLP_WNDPROC, wndProc);
   }
   return hWnd;
 }
@@ -3090,7 +3207,8 @@ WORD WINAPI VerQueryValueWrapW(
  * NOTES
  *  lpUnknown must support the IOleInPlaceFrame interface, the
  *  IInternetSecurityMgrSite interface, the IShellBrowser interface
- *  or the IDocHostUIHandler interface, or this call fails.
+ *  the IDocHostUIHandler interface, or the IOleInPlaceActiveObject interface,
+ *  or this call will fail.
  */
 HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
 {
@@ -3102,7 +3220,9 @@ HRESULT WINAPI IUnknown_EnableModeless(IUnknown *lpUnknown, BOOL bModeless)
   if (!lpUnknown)
     return E_FAIL;
 
-  if (IsIface(IOleInPlaceFrame))
+  if (IsIface(IOleInPlaceActiveObject))
+    EnableModeless(IOleInPlaceActiveObject);
+  else if (IsIface(IOleInPlaceFrame))
     EnableModeless(IOleInPlaceFrame);
   else if (IsIface(IShellBrowser))
     EnableModeless(IShellBrowser);
@@ -3735,7 +3855,7 @@ BOOL WINAPI IsOS(DWORD feature)
     case OS_HOME:
         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT && majorv >= 5 && minorv >= 1)
     case OS_PROFESSIONAL:
-        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT) 
+        ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
     case OS_DATACENTER:
         ISOS_RETURN(platform == VER_PLATFORM_WIN32_NT)
     case OS_ADVSERVER:
@@ -3785,6 +3905,70 @@ BOOL WINAPI IsOS(DWORD 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.@]
  *
@@ -3979,9 +4163,9 @@ VOID WINAPI FixSlashesAndColonW(LPWSTR lpwstr)
 /*************************************************************************
  *      @      [SHLWAPI.461]
  */
-DWORD WINAPI SHGetAppCompatFlags(DWORD Unknown)
+DWORD WINAPI SHGetAppCompatFlags(DWORD dwUnknown)
 {
-  FIXME("stub\n");
+  FIXME("(0x%08lx) stub\n", dwUnknown);
   return 0;
 }
 
@@ -4054,17 +4238,24 @@ HRESULT WINAPI SHQueueUserWorkItem(DWORD a, DWORD b, DWORD c, DWORD d, DWORD e,
 /***********************************************************************
  *             IUnknown_OnFocusChangeIS (SHLWAPI.@)
  */
-DWORD WINAPI IUnknown_OnFocusChangeIS(IUnknown * pUnk, IUnknown * pFocusObject, BOOL bChange)
+HRESULT WINAPI IUnknown_OnFocusChangeIS(LPUNKNOWN lpUnknown, LPUNKNOWN pFocusObject, BOOL bFocus)
 {
-    FIXME("(%p, %p, %s)\n", pUnk, pFocusObject, bChange ? "TRUE" : "FALSE");
+    IInputObjectSite *pIOS = NULL;
+    HRESULT hRet = E_INVALIDARG;
 
-/*
-    IInputObjectSite * pIOS = NULL;
-    if (SUCCEEDED(IUnknown_QueryInterface(pUnk, &IID_IInputObjectSite, (void **)&pIOS))
-        IInputObjectSite_OnFocusChangeIS(pIOS, pFocusObject, bChange);
-*/
+    TRACE("(%p, %p, %s)\n", lpUnknown, pFocusObject, bFocus ? "TRUE" : "FALSE");
 
-    return 0;
+    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;
 }
 
 /***********************************************************************