https://git.reactos.org/?p=reactos.git;a=commitdiff;h=245513e7eceb3cb445c51a989769c967260d4882

commit 245513e7eceb3cb445c51a989769c967260d4882
Author:     Justin Miller <justin.mil...@reactos.org>
AuthorDate: Wed Jan 29 02:08:11 2025 -0800
Commit:     Justin Miller <justinmiller...@gmail.com>
CommitDate: Sun Mar 9 04:07:55 2025 -0700

    [USER32_VISTA] Import input.c misc.c win.c from wine-10.0
---
 win32ss/user/user32_vista/wine/input.c |  889 ++++++++++++++++
 win32ss/user/user32_vista/wine/misc.c  |  545 ++++++++++
 win32ss/user/user32_vista/wine/win.c   | 1731 ++++++++++++++++++++++++++++++++
 3 files changed, 3165 insertions(+)

diff --git a/win32ss/user/user32_vista/wine/input.c 
b/win32ss/user/user32_vista/wine/input.c
new file mode 100644
index 00000000000..38c44d7d831
--- /dev/null
+++ b/win32ss/user/user32_vista/wine/input.c
@@ -0,0 +1,889 @@
+/*
+ * USER Input processing
+ *
+ * Copyright 1993 Bob Amstadt
+ * Copyright 1996 Albrecht Kleine
+ * Copyright 1997 David Faure
+ * Copyright 1998 Morten Welinder
+ * Copyright 1998 Ulrich Weigand
+ * Copyright 2012 Henri Verbeet
+ * Copyright 2018 Zebediah Figura for CodeWeavers
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "user_private.h"
+#include "dbt.h"
+#include "wine/debug.h"
+#include "wine/plugplay.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(win);
+WINE_DECLARE_DEBUG_CHANNEL(keyboard);
+
+/***********************************************************************
+ *           get_locale_kbd_layout
+ */
+static HKL get_locale_kbd_layout(void)
+{
+    ULONG_PTR layout;
+
+    /* FIXME:
+     *
+     * layout = main_key_tab[kbd_layout].lcid;
+     *
+     * Winword uses return value of GetKeyboardLayout as a codepage
+     * to translate ANSI keyboard messages to unicode. But we have
+     * a problem with it: for instance Polish keyboard layout is
+     * identical to the US one, and therefore instead of the Polish
+     * locale id we return the US one.
+     */
+
+    layout = GetUserDefaultLCID();
+    layout = MAKELONG( layout, layout );
+    return (HKL)layout;
+}
+
+
+/***********************************************************************
+ *             keybd_event (USER32.@)
+ */
+void WINAPI keybd_event( BYTE bVk, BYTE bScan,
+                         DWORD dwFlags, ULONG_PTR dwExtraInfo )
+{
+    INPUT input;
+
+    input.type = INPUT_KEYBOARD;
+    input.ki.wVk = bVk;
+    input.ki.wScan = bScan;
+    input.ki.dwFlags = dwFlags;
+    input.ki.time = 0;
+    input.ki.dwExtraInfo = dwExtraInfo;
+    NtUserSendInput( 1, &input, sizeof(input) );
+}
+
+
+/***********************************************************************
+ *             mouse_event (USER32.@)
+ */
+void WINAPI mouse_event( DWORD dwFlags, DWORD dx, DWORD dy,
+                         DWORD dwData, ULONG_PTR dwExtraInfo )
+{
+    INPUT input;
+
+    input.type = INPUT_MOUSE;
+    input.mi.dx = dx;
+    input.mi.dy = dy;
+    input.mi.mouseData = dwData;
+    input.mi.dwFlags = dwFlags;
+    input.mi.time = 0;
+    input.mi.dwExtraInfo = dwExtraInfo;
+    NtUserSendInput( 1, &input, sizeof(input) );
+}
+
+
+/***********************************************************************
+ *             GetCursorPos (USER32.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH GetCursorPos( POINT *pt )
+{
+    return NtUserGetCursorPos( pt );
+}
+
+
+/**********************************************************************
+ *             ReleaseCapture (USER32.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH ReleaseCapture(void)
+{
+    return NtUserReleaseCapture();
+}
+
+
+/**********************************************************************
+ *             GetCapture (USER32.@)
+ */
+HWND WINAPI GetCapture(void)
+{
+    GUITHREADINFO info;
+    info.cbSize = sizeof(info);
+    return NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ) ? 
info.hwndCapture : 0;
+}
+
+
+/*****************************************************************
+ *             DestroyCaret (USER32.@)
+ */
+BOOL WINAPI DestroyCaret(void)
+{
+    return NtUserDestroyCaret();
+}
+
+
+/*****************************************************************
+ *             SetCaretPos (USER32.@)
+ */
+BOOL WINAPI SetCaretPos( int x, int y )
+{
+    return NtUserSetCaretPos( x, y );
+}
+
+
+/*****************************************************************
+ *             SetCaretBlinkTime (USER32.@)
+ */
+BOOL WINAPI SetCaretBlinkTime( unsigned int time )
+{
+    return NtUserSetCaretBlinkTime( time );
+}
+
+
+/***********************************************************************
+ *             GetInputState   (USER32.@)
+ */
+BOOL WINAPI GetInputState(void)
+{
+    return NtUserGetInputState();
+}
+
+
+/******************************************************************
+ *              GetLastInputInfo (USER32.@)
+ */
+BOOL WINAPI GetLastInputInfo(PLASTINPUTINFO plii)
+{
+    TRACE("%p\n", plii);
+
+    if (plii->cbSize != sizeof (*plii) )
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    plii->dwTime = NtUserGetLastInputTime();
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *             VkKeyScanA (USER32.@)
+ *
+ * VkKeyScan translates an ANSI character to a virtual-key and shift code
+ * for the current keyboard.
+ * high-order byte yields :
+ *     0       Unshifted
+ *     1       Shift
+ *     2       Ctrl
+ *     3-5     Shift-key combinations that are not used for characters
+ *     6       Ctrl-Alt
+ *     7       Ctrl-Alt-Shift
+ *     I.e. :  Shift = 1, Ctrl = 2, Alt = 4.
+ * FIXME : works ok except for dead chars :
+ * VkKeyScan '^'(0x5e, 94) ... got keycode 00 ... returning 00
+ * VkKeyScan '`'(0x60, 96) ... got keycode 00 ... returning 00
+ */
+SHORT WINAPI VkKeyScanA(CHAR cChar)
+{
+    WCHAR wChar;
+
+    if (IsDBCSLeadByte(cChar)) return -1;
+
+    MultiByteToWideChar(CP_ACP, 0, &cChar, 1, &wChar, 1);
+    return VkKeyScanW(wChar);
+}
+
+/******************************************************************************
+ *             VkKeyScanW (USER32.@)
+ */
+SHORT WINAPI VkKeyScanW(WCHAR cChar)
+{
+    return NtUserVkKeyScanEx( cChar, NtUserGetKeyboardLayout(0) );
+}
+
+/**********************************************************************
+ *             VkKeyScanExA (USER32.@)
+ */
+WORD WINAPI VkKeyScanExA(CHAR cChar, HKL dwhkl)
+{
+    WCHAR wChar;
+
+    if (IsDBCSLeadByte(cChar)) return -1;
+
+    MultiByteToWideChar(CP_ACP, 0, &cChar, 1, &wChar, 1);
+    return NtUserVkKeyScanEx( wChar, dwhkl );
+}
+
+/**********************************************************************
+ *             OemKeyScan (USER32.@)
+ */
+DWORD WINAPI OemKeyScan( WORD oem )
+{
+    WCHAR wchr;
+    DWORD vkey, scan;
+    char oem_char = LOBYTE( oem );
+
+    if (!OemToCharBuffW( &oem_char, &wchr, 1 ))
+        return -1;
+
+    vkey = VkKeyScanW( wchr );
+    scan = MapVirtualKeyW( LOBYTE( vkey ), MAPVK_VK_TO_VSC );
+    if (!scan) return -1;
+
+    vkey &= 0xff00;
+    vkey <<= 8;
+    return vkey | scan;
+}
+
+/******************************************************************************
+ *             GetKeyboardType (USER32.@)
+ */
+INT WINAPI GetKeyboardType(INT nTypeFlag)
+{
+    TRACE_(keyboard)("(%d)\n", nTypeFlag);
+    if (LOWORD(NtUserGetKeyboardLayout(0)) == MAKELANGID(LANG_JAPANESE, 
SUBLANG_JAPANESE_JAPAN))
+    {
+        /* scan code for `_', the key left of r-shift, in Japanese 106 
keyboard */
+        const UINT JP106_VSC_USCORE = 0x73;
+
+        switch(nTypeFlag)
+        {
+        case 0:      /* Keyboard type */
+            return 7;    /* Japanese keyboard */
+        case 1:      /* Keyboard Subtype */
+            /* Test keyboard mappings to detect Japanese keyboard */
+            if (MapVirtualKeyW(VK_OEM_102, MAPVK_VK_TO_VSC) == JP106_VSC_USCORE
+                && MapVirtualKeyW(JP106_VSC_USCORE, MAPVK_VSC_TO_VK) == 
VK_OEM_102)
+                return 2;    /* Japanese 106 */
+            else
+                return 0;    /* AT-101 */
+        case 2:      /* Number of F-keys */
+            return 12;   /* It has 12 F-keys */
+        }
+    }
+    else
+    {
+        switch(nTypeFlag)
+        {
+        case 0:      /* Keyboard type */
+            return 4;    /* AT-101 */
+        case 1:      /* Keyboard Subtype */
+            return 0;    /* There are no defined subtypes */
+        case 2:      /* Number of F-keys */
+            return 12;   /* We're doing an 101 for now, so return 12 F-keys */
+        }
+    }
+    WARN_(keyboard)("Unknown type\n");
+    return 0;    /* The book says 0 here, so 0 */
+}
+
+/******************************************************************************
+ *             MapVirtualKeyA (USER32.@)
+ */
+UINT WINAPI MapVirtualKeyA(UINT code, UINT maptype)
+{
+    return MapVirtualKeyExA( code, maptype, NtUserGetKeyboardLayout(0) );
+}
+
+/******************************************************************************
+ *             MapVirtualKeyW (USER32.@)
+ */
+UINT WINAPI MapVirtualKeyW(UINT code, UINT maptype)
+{
+    return NtUserMapVirtualKeyEx( code, maptype, NtUserGetKeyboardLayout(0) );
+}
+
+/******************************************************************************
+ *             MapVirtualKeyExA (USER32.@)
+ */
+UINT WINAPI MapVirtualKeyExA(UINT code, UINT maptype, HKL hkl)
+{
+    UINT ret;
+
+    ret = NtUserMapVirtualKeyEx( code, maptype, hkl );
+    if (maptype == MAPVK_VK_TO_CHAR)
+    {
+        BYTE ch = 0;
+        WCHAR wch = ret;
+
+        WideCharToMultiByte( CP_ACP, 0, &wch, 1, (LPSTR)&ch, 1, NULL, NULL );
+        ret = ch;
+    }
+    return ret;
+}
+
+/****************************************************************************
+ *             GetKBCodePage (USER32.@)
+ */
+UINT WINAPI GetKBCodePage(void)
+{
+    return GetOEMCP();
+}
+
+/****************************************************************************
+ *             GetKeyboardLayoutNameA (USER32.@)
+ */
+BOOL WINAPI GetKeyboardLayoutNameA(LPSTR pszKLID)
+{
+    WCHAR buf[KL_NAMELENGTH];
+
+    if (NtUserGetKeyboardLayoutName( buf ))
+        return WideCharToMultiByte( CP_ACP, 0, buf, -1, pszKLID, 
KL_NAMELENGTH, NULL, NULL ) != 0;
+    return FALSE;
+}
+
+/****************************************************************************
+ *             GetKeyNameTextA (USER32.@)
+ */
+INT WINAPI GetKeyNameTextA(LONG lParam, LPSTR lpBuffer, INT nSize)
+{
+    WCHAR buf[256];
+    INT ret;
+
+    if (!nSize || !NtUserGetKeyNameText( lParam, buf, ARRAYSIZE(buf) ))
+    {
+        lpBuffer[0] = 0;
+        return 0;
+    }
+    ret = WideCharToMultiByte(CP_ACP, 0, buf, -1, lpBuffer, nSize, NULL, NULL);
+    if (!ret && nSize)
+    {
+        ret = nSize - 1;
+        lpBuffer[ret] = 0;
+    }
+    else ret--;
+
+    return ret;
+}
+
+/****************************************************************************
+ *             ToUnicode (USER32.@)
+ */
+INT WINAPI ToUnicode( UINT virt, UINT scan, const BYTE *state, LPWSTR str, int 
size, UINT flags )
+{
+    return NtUserToUnicodeEx( virt, scan, state, str, size, flags, 
NtUserGetKeyboardLayout(0) );
+}
+
+/****************************************************************************
+ *             ToAscii (USER32.@)
+ */
+INT WINAPI ToAscii( UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
+                    LPWORD lpChar, UINT flags )
+{
+    return ToAsciiEx( virtKey, scanCode, lpKeyState, lpChar, flags,
+                      NtUserGetKeyboardLayout(0) );
+}
+
+/****************************************************************************
+ *             ToAsciiEx (USER32.@)
+ */
+INT WINAPI ToAsciiEx( UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
+                      LPWORD lpChar, UINT flags, HKL dwhkl )
+{
+    WCHAR uni_chars[2];
+    INT ret, n_ret;
+
+    ret = NtUserToUnicodeEx( virtKey, scanCode, lpKeyState, uni_chars, 2, 
flags, dwhkl );
+    if (ret < 0) n_ret = 1; /* FIXME: make ToUnicode return 2 for dead chars */
+    else n_ret = ret;
+    WideCharToMultiByte(CP_ACP, 0, uni_chars, n_ret, (LPSTR)lpChar, 2, NULL, 
NULL);
+    return ret;
+}
+
+/**********************************************************************
+ *             BlockInput (USER32.@)
+ */
+BOOL WINAPI BlockInput(BOOL fBlockIt)
+{
+    FIXME_(keyboard)("(%d): stub\n", fBlockIt);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *             LoadKeyboardLayoutW (USER32.@)
+ */
+HKL WINAPI LoadKeyboardLayoutW( const WCHAR *name, UINT flags )
+{
+    WCHAR layout_path[MAX_PATH], value[5];
+    LCID locale = GetUserDefaultLCID();
+    DWORD id, value_size, tmp;
+    HKEY hkey;
+    HKL layout;
+
+    FIXME_(keyboard)( "name %s, flags %x, semi-stub!\n", debugstr_w( name ), 
flags );
+
+    tmp = wcstoul( name, NULL, 16 );
+    if (HIWORD( tmp )) layout = UlongToHandle( tmp );
+    else layout = UlongToHandle( MAKELONG( LOWORD( tmp ), LOWORD( tmp ) ) );
+
+    if (!((UINT_PTR)layout >> 28)) id = LOWORD( tmp );
+    else id = HIWORD( layout ); /* IME or aliased layout */
+
+    wcscpy( layout_path, L"System\\CurrentControlSet\\Control\\Keyboard 
Layouts\\" );
+    wcscat( layout_path, name );
+
+    if (!RegOpenKeyW( HKEY_LOCAL_MACHINE, layout_path, &hkey ))
+    {
+        value_size = sizeof(value);
+        if (!RegGetValueW( hkey, NULL, L"Layout Id", RRF_RT_REG_SZ, NULL, 
(void *)&value, &value_size ))
+            id = 0xf000 | (wcstoul( value, NULL, 16 ) & 0xfff);
+
+        RegCloseKey( hkey );
+    }
+
+    layout = UlongToHandle( MAKELONG( locale, id ) );
+    if ((flags & KLF_ACTIVATE) && NtUserActivateKeyboardLayout( layout, 0 )) 
return layout;
+
+    /* FIXME: semi-stub: returning default layout */
+    return get_locale_kbd_layout();
+}
+
+/***********************************************************************
+ *             LoadKeyboardLayoutA (USER32.@)
+ */
+HKL WINAPI LoadKeyboardLayoutA(LPCSTR pwszKLID, UINT Flags)
+{
+    HKL ret;
+    UNICODE_STRING pwszKLIDW;
+
+    if (pwszKLID) RtlCreateUnicodeStringFromAsciiz(&pwszKLIDW, pwszKLID);
+    else pwszKLIDW.Buffer = NULL;
+
+    ret = LoadKeyboardLayoutW(pwszKLIDW.Buffer, Flags);
+    RtlFreeUnicodeString(&pwszKLIDW);
+    return ret;
+}
+
+
+/***********************************************************************
+ *             LoadKeyboardLayoutEx (USER32.@)
+ */
+HKL WINAPI LoadKeyboardLayoutEx( HKL layout, const WCHAR *name, UINT flags )
+{
+    FIXME_(keyboard)( "layout %p, name %s, flags %x, semi-stub!\n", layout, 
debugstr_w( name ), flags );
+
+    if (!layout) return NULL;
+    return LoadKeyboardLayoutW( name, flags );
+}
+
+/***********************************************************************
+ *             UnloadKeyboardLayout (USER32.@)
+ */
+BOOL WINAPI UnloadKeyboardLayout( HKL layout )
+{
+    FIXME_(keyboard)( "layout %p, stub!\n", layout );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return FALSE;
+}
+
+
+static DWORD CALLBACK devnotify_window_callbackW(HANDLE handle, DWORD flags, 
DEV_BROADCAST_HDR *header)
+{
+    SendMessageTimeoutW(handle, WM_DEVICECHANGE, flags, (LPARAM)header, 
SMTO_ABORTIFHUNG, 2000, NULL);
+    return 0;
+}
+
+static DWORD CALLBACK devnotify_window_callbackA(HANDLE handle, DWORD flags, 
DEV_BROADCAST_HDR *header)
+{
+    if (flags & 0x8000)
+    {
+        switch (header->dbch_devicetype)
+        {
+        case DBT_DEVTYP_DEVICEINTERFACE:
+        {
+            const DEV_BROADCAST_DEVICEINTERFACE_W *ifaceW = (const 
DEV_BROADCAST_DEVICEINTERFACE_W *)header;
+            size_t lenW = wcslen( ifaceW->dbcc_name );
+            DEV_BROADCAST_DEVICEINTERFACE_A *ifaceA;
+            DWORD lenA;
+
+            if (!(ifaceA = malloc( offsetof(DEV_BROADCAST_DEVICEINTERFACE_A, 
dbcc_name[lenW * 3 + 1]) )))
+                return 0;
+            lenA = WideCharToMultiByte( CP_ACP, 0, ifaceW->dbcc_name, lenW + 1,
+                                        ifaceA->dbcc_name, lenW * 3 + 1, NULL, 
NULL );
+
+            ifaceA->dbcc_size = offsetof(DEV_BROADCAST_DEVICEINTERFACE_A, 
dbcc_name[lenA + 1]);
+            ifaceA->dbcc_devicetype = ifaceW->dbcc_devicetype;
+            ifaceA->dbcc_reserved = ifaceW->dbcc_reserved;
+            ifaceA->dbcc_classguid = ifaceW->dbcc_classguid;
+            SendMessageTimeoutA( handle, WM_DEVICECHANGE, flags, 
(LPARAM)ifaceA, SMTO_ABORTIFHUNG, 2000, NULL );
+            free( ifaceA );
+            return 0;
+        }
+
+        case DBT_DEVTYP_HANDLE:
+        {
+            const DEV_BROADCAST_HANDLE *handleW = (const DEV_BROADCAST_HANDLE 
*)header;
+            UINT sizeW = handleW->dbch_size - offsetof(DEV_BROADCAST_HANDLE, 
dbch_data[0]), len, offset;
+            DEV_BROADCAST_HANDLE *handleA;
+
+            if (!(handleA = malloc( offsetof(DEV_BROADCAST_HANDLE, 
dbch_data[sizeW * 3 + 1]) ))) return 0;
+            memcpy( handleA, handleW, offsetof(DEV_BROADCAST_HANDLE, 
dbch_data[0]) );
+            offset = min( sizeW, handleW->dbch_nameoffset );
+
+            memcpy( handleA->dbch_data, handleW->dbch_data, offset );
+            len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(handleW->dbch_data 
+ offset), (sizeW - offset) / sizeof(WCHAR),
+                                       (char *)handleA->dbch_data + offset, 
sizeW * 3 + 1 - offset, NULL, NULL );
+            handleA->dbch_size = offsetof(DEV_BROADCAST_HANDLE, 
dbch_data[offset + len + 1]);
+
+            SendMessageTimeoutA( handle, WM_DEVICECHANGE, flags, 
(LPARAM)handleA, SMTO_ABORTIFHUNG, 2000, NULL );
+            free( handleA );
+            return 0;
+        }
+
+        case DBT_DEVTYP_OEM:
+            break;
+        default:
+            FIXME( "unimplemented W to A mapping for %#lx\n", 
header->dbch_devicetype );
+        }
+    }
+
+    SendMessageTimeoutA( handle, WM_DEVICECHANGE, flags, (LPARAM)header, 
SMTO_ABORTIFHUNG, 2000, NULL );
+    return 0;
+}
+
+static DWORD CALLBACK devnotify_service_callback(HANDLE handle, DWORD flags, 
DEV_BROADCAST_HDR *header)
+{
+    FIXME("Support for service handles is not yet implemented!\n");
+    return 0;
+}
+
+/***********************************************************************
+ *             RegisterDeviceNotificationA (USER32.@)
+ *
+ * See RegisterDeviceNotificationW.
+ */
+HDEVNOTIFY WINAPI RegisterDeviceNotificationA( HANDLE handle, void *filter, 
DWORD flags )
+{
+    return RegisterDeviceNotificationW( handle, filter, flags );
+}
+
+/***********************************************************************
+ *             RegisterDeviceNotificationW (USER32.@)
+ */
+HDEVNOTIFY WINAPI RegisterDeviceNotificationW( HANDLE handle, void *filter, 
DWORD flags )
+{
+    DEV_BROADCAST_HDR *header = filter;
+    device_notify_callback callback;
+
+    TRACE("handle %p, filter %p, flags %#lx\n", handle, filter, flags);
+
+    if (flags & ~(DEVICE_NOTIFY_SERVICE_HANDLE | 
DEVICE_NOTIFY_ALL_INTERFACE_CLASSES))
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return NULL;
+    }
+
+    if (!(flags & DEVICE_NOTIFY_SERVICE_HANDLE) && !IsWindow( handle ))
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return NULL;
+    }
+
+    if (flags & DEVICE_NOTIFY_SERVICE_HANDLE)
+        callback = devnotify_service_callback;
+    else if (IsWindowUnicode( handle ))
+        callback = devnotify_window_callbackW;
+    else
+        callback = devnotify_window_callbackA;
+
+    if (!header)
+    {
+        DEV_BROADCAST_HDR dummy = {0};
+        return I_ScRegisterDeviceNotification( handle, &dummy, callback );
+    }
+    if (header->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
+    {
+        DEV_BROADCAST_DEVICEINTERFACE_W iface = 
*(DEV_BROADCAST_DEVICEINTERFACE_W *)header;
+
+        if (flags & DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)
+            iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, 
dbcc_classguid );
+        else
+            iface.dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, 
dbcc_name );
+
+        return I_ScRegisterDeviceNotification( handle, (DEV_BROADCAST_HDR 
*)&iface, callback );
+    }
+    if (header->dbch_devicetype == DBT_DEVTYP_HANDLE)
+    {
+        FIXME( "DBT_DEVTYP_HANDLE not implemented\n" );
+        return I_ScRegisterDeviceNotification( handle, header, callback );
+    }
+
+    FIXME( "type %#lx not implemented\n", header->dbch_devicetype );
+    SetLastError( ERROR_INVALID_DATA );
+    return NULL;
+}
+
+/***********************************************************************
+ *             UnregisterDeviceNotification (USER32.@)
+ */
+BOOL WINAPI UnregisterDeviceNotification( HDEVNOTIFY handle )
+{
+    TRACE("%p\n", handle);
+
+    return I_ScUnregisterDeviceNotification( handle );
+}
+
+/***********************************************************************
+ *              GetRawInputDeviceInfoA   (USER32.@)
+ */
+UINT WINAPI GetRawInputDeviceInfoA( HANDLE device, UINT command, void *data, 
UINT *size )
+{
+    TRACE( "device %p, command %#x, data %p, size %p.\n", device, command, 
data, size );
+
+    /* RIDI_DEVICENAME size is in chars, not bytes */
+    if (command == RIDI_DEVICENAME)
+    {
+        WCHAR *nameW;
+        UINT ret, sizeW;
+
+        if (!size) return ~0U;
+
+        sizeW = *size;
+
+        if (data && sizeW > 0)
+            nameW = HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR) * sizeW );
+        else
+            nameW = NULL;
+
+        ret = NtUserGetRawInputDeviceInfo( device, command, nameW, &sizeW );
+
+        if (ret && ret != ~0U)
+            WideCharToMultiByte( CP_ACP, 0, nameW, -1, data, *size, NULL, NULL 
);
+
+        *size = sizeW;
+
+        HeapFree( GetProcessHeap(), 0, nameW );
+
+        return ret;
+    }
+
+    return NtUserGetRawInputDeviceInfo( device, command, data, size );
+}
+
+/***********************************************************************
+ *              DefRawInputProc   (USER32.@)
+ */
+LRESULT WINAPI DefRawInputProc( RAWINPUT **data, INT data_count, UINT 
header_size )
+{
+    TRACE( "data %p, data_count %d, header_size %u.\n", data, data_count, 
header_size );
+
+    return header_size == sizeof(RAWINPUTHEADER) ? 0 : -1;
+}
+
+/*****************************************************************************
+ * CloseTouchInputHandle (USER32.@)
+ */
+BOOL WINAPI CloseTouchInputHandle( HTOUCHINPUT handle )
+{
+    FIXME( "handle %p stub!\n", handle );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return FALSE;
+}
+
+/*****************************************************************************
+ * GetTouchInputInfo (USER32.@)
+ */
+BOOL WINAPI GetTouchInputInfo( HTOUCHINPUT handle, UINT count, TOUCHINPUT 
*ptr, int size )
+{
+    FIXME( "handle %p, count %u, ptr %p, size %u stub!\n", handle, count, ptr, 
size );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return FALSE;
+}
+
+/**********************************************************************
+ * IsTouchWindow (USER32.@)
+ */
+BOOL WINAPI IsTouchWindow( HWND hwnd, ULONG *flags )
+{
+    FIXME( "hwnd %p, flags %p stub!\n", hwnd, flags );
+    return FALSE;
+}
+
+/*****************************************************************************
+ * RegisterTouchWindow (USER32.@)
+ */
+BOOL WINAPI RegisterTouchWindow( HWND hwnd, ULONG flags )
+{
+    FIXME( "hwnd %p, flags %#lx stub!\n", hwnd, flags );
+    return TRUE;
+}
+
+/*****************************************************************************
+ * UnregisterTouchWindow (USER32.@)
+ */
+BOOL WINAPI UnregisterTouchWindow( HWND hwnd )
+{
+    FIXME( "hwnd %p stub!\n", hwnd );
+    return TRUE;
+}
+
+/*****************************************************************************
+ * GetGestureInfo (USER32.@)
+ */
+BOOL WINAPI CloseGestureInfoHandle( HGESTUREINFO handle )
+{
+    FIXME( "handle %p stub!\n", handle );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return FALSE;
+}
+
+/*****************************************************************************
+ * GetGestureInfo (USER32.@)
+ */
+BOOL WINAPI GetGestureExtraArgs( HGESTUREINFO handle, UINT count, BYTE *args )
+{
+    FIXME( "handle %p, count %u, args %p stub!\n", handle, count, args );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return FALSE;
+}
+
+/*****************************************************************************
+ * GetGestureInfo (USER32.@)
+ */
+BOOL WINAPI GetGestureInfo( HGESTUREINFO handle, GESTUREINFO *ptr )
+{
+    FIXME( "handle %p, ptr %p stub!\n", handle, ptr );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return FALSE;
+}
+
+/*****************************************************************************
+ * GetGestureConfig (USER32.@)
+ */
+BOOL WINAPI GetGestureConfig( HWND hwnd, DWORD reserved, DWORD flags, UINT 
*count,
+                              GESTURECONFIG *config, UINT size )
+{
+    FIXME( "handle %p, reserved %#lx, flags %#lx, count %p, config %p, size %u 
stub!\n",
+           hwnd, reserved, flags, count, config, size );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return FALSE;
+}
+
+/**********************************************************************
+ * SetGestureConfig (USER32.@)
+ */
+BOOL WINAPI SetGestureConfig( HWND hwnd, DWORD reserved, UINT count,
+                              GESTURECONFIG *config, UINT size )
+{
+    FIXME( "handle %p, reserved %#lx, count %u, config %p, size %u stub!\n",
+           hwnd, reserved, count, config, size );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return FALSE;
+}
+
+BOOL WINAPI GetPointerTouchInfo( UINT32 id, POINTER_TOUCH_INFO *info )
+{
+    FIXME( "id %u, info %p stub!\n", id, info );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return FALSE;
+}
+
+BOOL WINAPI GetPointerTouchInfoHistory( UINT32 id, UINT32 *count, 
POINTER_TOUCH_INFO *info )
+{
+    FIXME( "id %u, count %p, info %p stub!\n", id, count, info );
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return FALSE;
+}
+
+
+/*******************************************************************
+ *           SetForegroundWindow  (USER32.@)
+ */
+BOOL WINAPI SetForegroundWindow( HWND hwnd )
+{
+    return NtUserSetForegroundWindow( hwnd );
+}
+
+
+/*******************************************************************
+ *           GetActiveWindow  (USER32.@)
+ */
+HWND WINAPI GetActiveWindow(void)
+{
+    GUITHREADINFO info;
+    info.cbSize = sizeof(info);
+    return NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ) ? 
info.hwndActive : 0;
+}
+
+
+/*****************************************************************
+ *           GetFocus  (USER32.@)
+ */
+HWND WINAPI GetFocus(void)
+{
+    GUITHREADINFO info;
+    info.cbSize = sizeof(info);
+    return NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ) ? 
info.hwndFocus : 0;
+}
+
+
+/*******************************************************************
+ *           SetShellWindow (USER32.@)
+ */
+BOOL WINAPI SetShellWindow( HWND hwnd )
+{
+    return NtUserSetShellWindowEx( hwnd, hwnd );
+}
+
+
+/*******************************************************************
+ *           GetShellWindow (USER32.@)
+ */
+HWND WINAPI GetShellWindow(void)
+{
+    return NtUserGetShellWindow();
+}
+
+
+/***********************************************************************
+ *           SetProgmanWindow (USER32.@)
+ */
+HWND WINAPI SetProgmanWindow( HWND hwnd )
+{
+    return NtUserSetProgmanWindow( hwnd );
+}
+
+
+/***********************************************************************
+ *           GetProgmanWindow (USER32.@)
+ */
+HWND WINAPI GetProgmanWindow(void)
+{
+    return NtUserGetProgmanWindow();
+}
+
+
+/***********************************************************************
+ *           SetTaskmanWindow (USER32.@)
+ */
+HWND WINAPI SetTaskmanWindow( HWND hwnd )
+{
+    return NtUserSetTaskmanWindow( hwnd );
+}
+
+/***********************************************************************
+ *           GetTaskmanWindow (USER32.@)
+ */
+HWND WINAPI GetTaskmanWindow(void)
+{
+    return NtUserGetTaskmanWindow();
+}
+
+HSYNTHETICPOINTERDEVICE WINAPI CreateSyntheticPointerDevice(POINTER_INPUT_TYPE 
type, ULONG max_count, POINTER_FEEDBACK_MODE mode)
+{
+    FIXME( "type %ld, max_count %ld, mode %d stub!\n", type, max_count, mode);
+    SetLastError( ERROR_CALL_NOT_IMPLEMENTED );
+    return NULL;
+}
diff --git a/win32ss/user/user32_vista/wine/misc.c 
b/win32ss/user/user32_vista/wine/misc.c
new file mode 100644
index 00000000000..6333fcb48b4
--- /dev/null
+++ b/win32ss/user/user32_vista/wine/misc.c
@@ -0,0 +1,545 @@
+/*
+ * Misc USER functions
+ *
+ * Copyright 1995 Thomas Sandford
+ * Copyright 1997 Marcus Meissner
+ * Copyright 1998 Turchanov Sergey
+ * Copyright 2019 Micah N Gorrell for CodeWeavers
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "wine/windef16.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "controls.h"
+#include "imm.h"
+#include "user_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(win);
+
+BOOL WINAPI ImmSetActiveContext(HWND, HIMC, BOOL);
+
+#define IMM_INIT_MAGIC 0x19650412
+static LRESULT (WINAPI *imm_ime_wnd_proc)( HWND hwnd, UINT msg, WPARAM wparam, 
LPARAM lparam, BOOL ansi);
+
+/* USER signal proc flags and codes */
+/* See UserSignalProc for comments */
+#define USIG_FLAGS_WIN32          0x0001
+#define USIG_FLAGS_GUI            0x0002
+#define USIG_FLAGS_FEEDBACK       0x0004
+#define USIG_FLAGS_FAULT          0x0008
+
+#define USIG_DLL_UNLOAD_WIN16     0x0001
+#define USIG_DLL_UNLOAD_WIN32     0x0002
+#define USIG_FAULT_DIALOG_PUSH    0x0003
+#define USIG_FAULT_DIALOG_POP     0x0004
+#define USIG_DLL_UNLOAD_ORPHANS   0x0005
+#define USIG_THREAD_INIT          0x0010
+#define USIG_THREAD_EXIT          0x0020
+#define USIG_PROCESS_CREATE       0x0100
+#define USIG_PROCESS_INIT         0x0200
+#define USIG_PROCESS_EXIT         0x0300
+#define USIG_PROCESS_DESTROY      0x0400
+#define USIG_PROCESS_RUNNING      0x0500
+#define USIG_PROCESS_LOADED       0x0600
+
+/***********************************************************************
+ *             SignalProc32 (USER.391)
+ *             UserSignalProc (USER32.@)
+ *
+ * The exact meaning of the USER signals is undocumented, but this
+ * should cover the basic idea:
+ *
+ * USIG_DLL_UNLOAD_WIN16
+ *     This is sent when a 16-bit module is unloaded.
+ *
+ * USIG_DLL_UNLOAD_WIN32
+ *     This is sent when a 32-bit module is unloaded.
+ *
+ * USIG_DLL_UNLOAD_ORPHANS
+ *     This is sent after the last Win3.1 module is unloaded,
+ *     to allow removal of orphaned menus.
+ *
+ * USIG_FAULT_DIALOG_PUSH
+ * USIG_FAULT_DIALOG_POP
+ *     These are called to allow USER to prepare for displaying a
+ *     fault dialog, even though the fault might have happened while
+ *     inside a USER critical section.
+ *
+ * USIG_THREAD_INIT
+ *     This is called from the context of a new thread, as soon as it
+ *     has started to run.
+ *
+ * USIG_THREAD_EXIT
+ *     This is called, still in its context, just before a thread is
+ *     about to terminate.
+ *
+ * USIG_PROCESS_CREATE
+ *     This is called, in the parent process context, after a new process
+ *     has been created.
+ *
+ * USIG_PROCESS_INIT
+ *     This is called in the new process context, just after the main thread
+ *     has started execution (after the main thread's USIG_THREAD_INIT has
+ *     been sent).
+ *
+ * USIG_PROCESS_LOADED
+ *     This is called after the executable file has been loaded into the
+ *     new process context.
+ *
+ * USIG_PROCESS_RUNNING
+ *     This is called immediately before the main entry point is called.
+ *
+ * USIG_PROCESS_EXIT
+ *     This is called in the context of a process that is about to
+ *     terminate (but before the last thread's USIG_THREAD_EXIT has
+ *     been sent).
+ *
+ * USIG_PROCESS_DESTROY
+ *     This is called after a process has terminated.
+ *
+ *
+ * The meaning of the dwFlags bits is as follows:
+ *
+ * USIG_FLAGS_WIN32
+ *     Current process is 32-bit.
+ *
+ * USIG_FLAGS_GUI
+ *     Current process is a (Win32) GUI process.
+ *
+ * USIG_FLAGS_FEEDBACK
+ *     Current process needs 'feedback' (determined from the STARTUPINFO
+ *     flags STARTF_FORCEONFEEDBACK / STARTF_FORCEOFFFEEDBACK).
+ *
+ * USIG_FLAGS_FAULT
+ *     The signal is being sent due to a fault.
+ */
+WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
+                            DWORD dwFlags, HMODULE16 hModule )
+{
+    FIXME("(%04x, %08lx, %04lx, %04x)\n",
+          uCode, dwThreadOrProcessID, dwFlags, hModule );
+    /* FIXME: Should chain to GdiSignalProc now. */
+    return 0;
+}
+
+
+/**********************************************************************
+ * SetLastErrorEx [USER32.@]
+ *
+ * Sets the last-error code.
+ *
+ * RETURNS
+ *    None.
+ */
+void WINAPI SetLastErrorEx(
+    DWORD error, /* [in] Per-thread error code */
+    DWORD type)  /* [in] Error type */
+{
+    TRACE("(0x%08lx, 0x%08lx)\n", error,type);
+    switch(type) {
+        case 0:
+            break;
+        case SLE_ERROR:
+        case SLE_MINORERROR:
+        case SLE_WARNING:
+            /* Fall through for now */
+        default:
+            FIXME("(error=%08lx, type=%08lx): Unhandled type\n", error,type);
+            break;
+    }
+    SetLastError( error );
+}
+
+/******************************************************************************
+ * GetAltTabInfoA [USER32.@]
+ */
+BOOL WINAPI GetAltTabInfoA(HWND hwnd, int iItem, PALTTABINFO pati, LPSTR 
pszItemText, UINT cchItemText)
+{
+    FIXME("(%p, 0x%08x, %p, %p, 0x%08x)\n", hwnd, iItem, pati, pszItemText, 
cchItemText);
+    return FALSE;
+}
+
+/******************************************************************************
+ * GetAltTabInfoW [USER32.@]
+ */
+BOOL WINAPI GetAltTabInfoW(HWND hwnd, int iItem, PALTTABINFO pati, LPWSTR 
pszItemText, UINT cchItemText)
+{
+    FIXME("(%p, 0x%08x, %p, %p, 0x%08x)\n", hwnd, iItem, pati, pszItemText, 
cchItemText);
+    return FALSE;
+}
+
+/******************************************************************************
+ * SetDebugErrorLevel [USER32.@]
+ * Sets the minimum error level for generating debugging events
+ *
+ * PARAMS
+ *    dwLevel [I] Debugging error level
+ *
+ * RETURNS
+ *    Nothing.
+ */
+VOID WINAPI SetDebugErrorLevel( DWORD dwLevel )
+{
+    FIXME("(%ld): stub\n", dwLevel);
+}
+
+
+/***********************************************************************
+ *             SetWindowStationUser (USER32.@)
+ */
+DWORD WINAPI SetWindowStationUser(DWORD x1,DWORD x2)
+{
+    FIXME("(0x%08lx,0x%08lx),stub!\n",x1,x2);
+    return 1;
+}
+
+/***********************************************************************
+ *             RegisterLogonProcess (USER32.@)
+ */
+DWORD WINAPI RegisterLogonProcess(HANDLE hprocess,BOOL x)
+{
+    FIXME("(%p,%d),stub!\n",hprocess,x);
+    return 1;
+}
+
+/***********************************************************************
+ *             SetLogonNotifyWindow (USER32.@)
+ */
+DWORD WINAPI SetLogonNotifyWindow(HWINSTA hwinsta,HWND hwnd)
+{
+    FIXME("(%p,%p),stub!\n",hwinsta,hwnd);
+    return 1;
+}
+
+/***********************************************************************
+ *             RegisterSystemThread (USER32.@)
+ */
+void WINAPI RegisterSystemThread(DWORD flags, DWORD reserved)
+{
+    FIXME("(%08lx, %08lx)\n", flags, reserved);
+}
+
+/***********************************************************************
+ *           RegisterShellHookWindow                   [USER32.@]
+ */
+BOOL WINAPI RegisterShellHookWindow(HWND hWnd)
+{
+    FIXME("(%p): stub\n", hWnd);
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           DeregisterShellHookWindow                 [USER32.@]
+ */
+BOOL WINAPI DeregisterShellHookWindow(HWND hWnd)
+{
+    FIXME("(%p): stub\n", hWnd);
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *           RegisterTasklist                          [USER32.@]
+ */
+DWORD WINAPI RegisterTasklist (DWORD x)
+{
+    FIXME("0x%08lx\n",x);
+    return TRUE;
+}
+
+/***********************************************************************
+ *           GetAppCompatFlags   (USER32.@)
+ */
+DWORD WINAPI GetAppCompatFlags( HTASK hTask )
+{
+    FIXME("(%p) stub\n", hTask);
+    return 0;
+}
+
+/***********************************************************************
+ *           GetAppCompatFlags2   (USER32.@)
+ */
+DWORD WINAPI GetAppCompatFlags2( HTASK hTask )
+{
+    FIXME("(%p) stub\n", hTask);
+    return 0;
+}
+
+
+/***********************************************************************
+ *           AlignRects   (USER32.@)
+ */
+BOOL WINAPI AlignRects(LPRECT rect, DWORD b, DWORD c, DWORD d)
+{
+    FIXME("(%p, %ld, %ld, %ld): stub\n", rect, b, c, d);
+    if (rect)
+        FIXME("rect: %s\n", wine_dbgstr_rect(rect));
+    /* Calls OffsetRect */
+    return FALSE;
+}
+
+
+/***********************************************************************
+ *             LoadLocalFonts (USER32.@)
+ */
+VOID WINAPI LoadLocalFonts(VOID)
+{
+    /* are loaded. */
+    return;
+}
+
+
+/***********************************************************************
+ *             User32InitializeImmEntryTable
+ */
+BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
+{
+    HMODULE imm32 = GetModuleHandleW(L"imm32.dll");
+
+    TRACE("(%lx)\n", magic);
+
+    if (!imm32 || magic != IMM_INIT_MAGIC)
+        return FALSE;
+
+    if (imm_ime_wnd_proc)
+        return TRUE;
+
+    /* this part is not compatible with native imm32.dll */
+    imm_ime_wnd_proc = (void*)GetProcAddress(imm32, "__wine_ime_wnd_proc");
+    if (!imm_ime_wnd_proc)
+        FIXME("native imm32.dll not supported\n");
+    return TRUE;
+}
+
+/**********************************************************************
+ * WINNLSGetIMEHotkey [USER32.@]
+ *
+ */
+UINT WINAPI WINNLSGetIMEHotkey(HWND hwnd)
+{
+    FIXME("hwnd %p: stub!\n", hwnd);
+    return 0; /* unknown */
+}
+
+/**********************************************************************
+ * WINNLSEnableIME [USER32.@]
+ *
+ */
+BOOL WINAPI WINNLSEnableIME(HWND hwnd, BOOL enable)
+{
+    FIXME("hwnd %p enable %d: stub!\n", hwnd, enable);
+    return TRUE; /* success (?) */
+}
+
+/**********************************************************************
+ * WINNLSGetEnableStatus [USER32.@]
+ *
+ */
+BOOL WINAPI WINNLSGetEnableStatus(HWND hwnd)
+{
+    FIXME("hwnd %p: stub!\n", hwnd);
+    return TRUE; /* success (?) */
+}
+
+/**********************************************************************
+ * SendIMEMessageExA [USER32.@]
+ *
+ */
+LRESULT WINAPI SendIMEMessageExA(HWND hwnd, LPARAM lparam)
+{
+  FIXME("(%p,%Ix): stub\n", hwnd, lparam);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return 0;
+}
+
+/**********************************************************************
+ * SendIMEMessageExW [USER32.@]
+ *
+ */
+LRESULT WINAPI SendIMEMessageExW(HWND hwnd, LPARAM lparam)
+{
+  FIXME("(%p,%Ix): stub\n", hwnd, lparam);
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return 0;
+}
+
+/**********************************************************************
+ * DisableProcessWindowsGhosting [USER32.@]
+ *
+ */
+VOID WINAPI DisableProcessWindowsGhosting(VOID)
+{
+  FIXME(": stub\n");
+  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+  return;
+}
+
+/**********************************************************************
+ * UserHandleGrantAccess [USER32.@]
+ *
+ */
+BOOL WINAPI UserHandleGrantAccess(HANDLE handle, HANDLE job, BOOL grant)
+{
+    FIXME("(%p,%p,%d): stub\n", handle, job, grant);
+    return TRUE;
+}
+
+/**********************************************************************
+ * RegisterPowerSettingNotification [USER32.@]
+ */
+HPOWERNOTIFY WINAPI RegisterPowerSettingNotification(HANDLE recipient, const 
GUID *guid, DWORD flags)
+{
+    FIXME("(%p,%s,%lx): stub\n", recipient, debugstr_guid(guid), flags);
+    return (HPOWERNOTIFY)0xdeadbeef;
+}
+
+/**********************************************************************
+ * UnregisterPowerSettingNotification [USER32.@]
+ */
+BOOL WINAPI UnregisterPowerSettingNotification(HPOWERNOTIFY handle)
+{
+    FIXME("(%p): stub\n", handle);
+    return TRUE;
+}
+
+/**********************************************************************
+ * RegisterSuspendResumeNotification (USER32.@)
+ */
+HPOWERNOTIFY WINAPI RegisterSuspendResumeNotification(HANDLE recipient, DWORD 
flags)
+{
+    FIXME("%p, %#lx: stub.\n", recipient, flags);
+    return (HPOWERNOTIFY)0xdeadbeef;
+}
+
+/**********************************************************************
+ * UnregisterSuspendResumeNotification (USER32.@)
+ */
+BOOL WINAPI UnregisterSuspendResumeNotification(HPOWERNOTIFY handle)
+{
+    FIXME("%p: stub.\n", handle);
+    return TRUE;
+}
+
+/**********************************************************************
+ * IsWindowRedirectedForPrint [USER32.@]
+ */
+BOOL WINAPI IsWindowRedirectedForPrint( HWND hwnd )
+{
+    FIXME("(%p): stub\n", hwnd);
+    return FALSE;
+}
+
+/**********************************************************************
+ * RegisterPointerDeviceNotifications [USER32.@]
+ */
+BOOL WINAPI RegisterPointerDeviceNotifications(HWND hwnd, BOOL notifyrange)
+{
+    FIXME("(%p %d): stub\n", hwnd, notifyrange);
+    return TRUE;
+}
+
+/**********************************************************************
+ * GetPointerDevices [USER32.@]
+ */
+BOOL WINAPI GetPointerDevices(UINT32 *device_count, POINTER_DEVICE_INFO 
*devices)
+{
+    FIXME("(%p %p): partial stub\n", device_count, devices);
+
+    if (!device_count)
+        return FALSE;
+
+    if (devices)
+        return FALSE;
+
+    *device_count = 0;
+    return TRUE;
+}
+
+/**********************************************************************
+ * RegisterTouchHitTestingWindow [USER32.@]
+ */
+BOOL WINAPI RegisterTouchHitTestingWindow(HWND hwnd, ULONG value)
+{
+    FIXME("(%p %ld): stub\n", hwnd, value);
+    return TRUE;
+}
+
+/**********************************************************************
+ * EvaluateProximityToRect [USER32.@]
+ */
+BOOL WINAPI EvaluateProximityToRect(const RECT *box,
+                                    const TOUCH_HIT_TESTING_INPUT *input,
+                                    TOUCH_HIT_TESTING_PROXIMITY_EVALUATION 
*proximity)
+{
+    FIXME("(%p,%p,%p): stub\n", box, input, proximity);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+/**********************************************************************
+ * PackTouchHitTestingProximityEvaluation [USER32.@]
+ */
+LRESULT WINAPI PackTouchHitTestingProximityEvaluation(const 
TOUCH_HIT_TESTING_INPUT *input,
+                                                      const 
TOUCH_HIT_TESTING_PROXIMITY_EVALUATION *proximity)
+{
+    FIXME("(%p,%p): stub\n", input, proximity);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return 0;
+}
+
+/**********************************************************************
+ * GetPointerType [USER32.@]
+ */
+BOOL WINAPI GetPointerType(UINT32 id, POINTER_INPUT_TYPE *type)
+{
+    FIXME("(%d %p): stub\n", id, type);
+
+    if(!id || !type)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    *type = PT_MOUSE;
+    return TRUE;
+}
+
+BOOL WINAPI GetPointerInfo(UINT32 id, POINTER_INFO *info)
+{
+    FIXME("(%d %p): stub\n", id, info);
+
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return FALSE;
+}
+
+LRESULT WINAPI ImeWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
+{
+    if (!imm_ime_wnd_proc) return DefWindowProcA(hwnd, msg, wParam, lParam);
+    return imm_ime_wnd_proc( hwnd, msg, wParam, lParam, TRUE );
+}
+
+LRESULT WINAPI ImeWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
+{
+    if (!imm_ime_wnd_proc) return DefWindowProcW(hwnd, msg, wParam, lParam);
+    return imm_ime_wnd_proc( hwnd, msg, wParam, lParam, FALSE );
+}
diff --git a/win32ss/user/user32_vista/wine/win.c 
b/win32ss/user/user32_vista/wine/win.c
new file mode 100644
index 00000000000..99f681a3f9c
--- /dev/null
+++ b/win32ss/user/user32_vista/wine/win.c
@@ -0,0 +1,1731 @@
+/*
+ * Window related functions
+ *
+ * Copyright 1993, 1994 Alexandre Julliard
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "user_private.h"
+#include "controls.h"
+#include "winver.h"
+#include "wine/asm.h"
+#include "wine/exception.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(win);
+
+
+#ifdef __i386__
+/* Some apps pass a non-stdcall proc to EnumChildWindows,
+ * so we need a small assembly wrapper to call the proc.
+ */
+extern LRESULT enum_callback_wrapper( WNDENUMPROC proc, HWND hwnd, LPARAM 
lparam );
+__ASM_GLOBAL_FUNC( enum_callback_wrapper,
+    "pushl %ebp\n\t"
+    __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
+    __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
+    "movl %esp,%ebp\n\t"
+    __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
+    "pushl 16(%ebp)\n\t"
+    "pushl 12(%ebp)\n\t"
+    "call *8(%ebp)\n\t"
+    "leave\n\t"
+    __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
+    __ASM_CFI(".cfi_same_value %ebp\n\t")
+    "ret" )
+#else
+static inline LRESULT enum_callback_wrapper( WNDENUMPROC proc, HWND hwnd, 
LPARAM lparam )
+{
+    return proc( hwnd, lparam );
+}
+#endif /* __i386__ */
+
+/*******************************************************************
+ *           enum_windows
+ */
+static BOOL enum_windows( HDESK desktop, HWND hwnd, DWORD tid, BOOL children,
+                          WNDENUMPROC proc, LPARAM param )
+{
+    HWND *list;
+    ULONG i, size = 128;
+    BOOL ret = !children;  /* EnumChildWindows returns FALSE on empty list, 
the others TRUE */
+    NTSTATUS status;
+
+    for (;;)
+    {
+        if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) 
return FALSE;
+        status = NtUserBuildHwndList( desktop, hwnd, children, TRUE, tid, 
size, list, &size );
+        if (!status) break;
+        HeapFree( GetProcessHeap(), 0, list );
+        if (status != STATUS_BUFFER_TOO_SMALL) return FALSE;
+    }
+    for (i = 0; i < size && list[i] != HWND_BOTTOM; i++)
+    {
+        if (!IsWindow( list[i] )) continue;
+        if (!(ret = enum_callback_wrapper( proc, list[i], param ))) break;
+    }
+    HeapFree( GetProcessHeap(), 0, list );
+    return ret;
+}
+
+
+/*******************************************************************
+ *           is_desktop_window
+ *
+ * Check if window is the desktop or the HWND_MESSAGE top parent.
+ */
+BOOL is_desktop_window( HWND hwnd )
+{
+    struct ntuser_thread_info *thread_info = NtUserGetThreadInfo();
+
+    if (!hwnd) return FALSE;
+    if (hwnd == UlongToHandle( thread_info->top_window )) return TRUE;
+    if (hwnd == UlongToHandle( thread_info->msg_window )) return TRUE;
+
+    if (!HIWORD(hwnd) || HIWORD(hwnd) == 0xffff)
+    {
+        if (LOWORD(thread_info->top_window) == LOWORD(hwnd)) return TRUE;
+        if (LOWORD(thread_info->msg_window) == LOWORD(hwnd)) return TRUE;
+    }
+    return FALSE;
+}
+
+
+/* check if hwnd is a broadcast magic handle */
+static inline BOOL is_broadcast( HWND hwnd )
+{
+    return hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST;
+}
+
+
+/***********************************************************************
+ *           WIN_IsCurrentProcess
+ *
+ * Check whether a given window belongs to the current process (and return the 
full handle).
+ */
+HWND WIN_IsCurrentProcess( HWND hwnd )
+{
+    return UlongToHandle( NtUserCallHwnd( hwnd, NtUserIsCurrentProcessWindow 
));
+}
+
+
+/***********************************************************************
+ *           WIN_IsCurrentThread
+ *
+ * Check whether a given window belongs to the current thread (and return the 
full handle).
+ */
+HWND WIN_IsCurrentThread( HWND hwnd )
+{
+    return UlongToHandle( NtUserCallHwnd( hwnd, NtUserIsCurrentThreadWindow ));
+}
+
+
+/***********************************************************************
+ *           WIN_GetFullHandle
+ *
+ * Convert a possibly truncated window handle to a full 32-bit handle.
+ */
+HWND WIN_GetFullHandle( HWND hwnd )
+{
+    return UlongToHandle( NtUserCallHwnd( hwnd, NtUserGetFullWindowHandle ));
+}
+
+
+/***********************************************************************
+ *           WIN_SetStyle
+ *
+ * Change the style of a window.
+ */
+ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
+{
+    /* FIXME: Use SetWindowLong or move callers to win32u instead.
+     * We use STYLESTRUCT to pass params, but meaning of its field does not 
match our usage. */
+    STYLESTRUCT style = { .styleNew = set_bits, .styleOld = clear_bits };
+    return NtUserCallHwndParam( hwnd, (UINT_PTR)&style, NtUserSetWindowStyle );
+}
+
+
+/***********************************************************************
+ *           dump_window_styles
+ */
+static void dump_window_styles( DWORD style, DWORD exstyle )
+{
+    TRACE( "style:" );
+    if(style & WS_POPUP) TRACE(" WS_POPUP");
+    if(style & WS_CHILD) TRACE(" WS_CHILD");
+    if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
+    if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
+    if(style & WS_DISABLED) TRACE(" WS_DISABLED");
+    if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
+    if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
+    if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
+    if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
+    else
+    {
+        if(style & WS_BORDER) TRACE(" WS_BORDER");
+        if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
+    }
+    if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
+    if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
+    if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
+    if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
+    if (style & WS_CHILD)
+    {
+        if(style & WS_GROUP) TRACE(" WS_GROUP");
+        if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
+    }
+    else
+    {
+        if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
+        if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
+    }
+
+    /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
+#define DUMPED_STYLES \
+    ((DWORD)(WS_POPUP | \
+     WS_CHILD | \
+     WS_MINIMIZE | \
+     WS_VISIBLE | \
+     WS_DISABLED | \
+     WS_CLIPSIBLINGS | \
+     WS_CLIPCHILDREN | \
+     WS_MAXIMIZE | \
+     WS_BORDER | \
+     WS_DLGFRAME | \
+     WS_VSCROLL | \
+     WS_HSCROLL | \
+     WS_SYSMENU | \
+     WS_THICKFRAME | \
+     WS_GROUP | \
+     WS_TABSTOP | \
+     WS_MINIMIZEBOX | \
+     WS_MAXIMIZEBOX))
+
+    if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
+    TRACE("\n");
+#undef DUMPED_STYLES
+
+    TRACE( "exstyle:" );
+    if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
+    if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
+    if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
+    if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
+    if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
+    if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
+    if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
+    if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
+    if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
+    if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
+    if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
+    if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
+    if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
+    if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
+    if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
+    if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
+    if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
+    if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
+    if(exstyle & WS_EX_NOINHERITLAYOUT) TRACE(" WS_EX_NOINHERITLAYOUT");
+    if(exstyle & WS_EX_LAYOUTRTL) TRACE(" WS_EX_LAYOUTRTL");
+    if(exstyle & WS_EX_COMPOSITED) TRACE(" WS_EX_COMPOSITED");
+    if(exstyle & WS_EX_NOACTIVATE) TRACE(" WS_EX_NOACTIVATE");
+
+#define DUMPED_EX_STYLES \
+    ((DWORD)(WS_EX_DLGMODALFRAME | \
+     WS_EX_DRAGDETECT | \
+     WS_EX_NOPARENTNOTIFY | \
+     WS_EX_TOPMOST | \
+     WS_EX_ACCEPTFILES | \
+     WS_EX_TRANSPARENT | \
+     WS_EX_MDICHILD | \
+     WS_EX_TOOLWINDOW | \
+     WS_EX_WINDOWEDGE | \
+     WS_EX_CLIENTEDGE | \
+     WS_EX_CONTEXTHELP | \
+     WS_EX_RIGHT | \
+     WS_EX_RTLREADING | \
+     WS_EX_LEFTSCROLLBAR | \
+     WS_EX_CONTROLPARENT | \
+     WS_EX_STATICEDGE | \
+     WS_EX_APPWINDOW | \
+     WS_EX_LAYERED | \
+     WS_EX_NOINHERITLAYOUT | \
+     WS_EX_LAYOUTRTL | \
+     WS_EX_COMPOSITED |\
+     WS_EX_NOACTIVATE))
+
+    if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & 
~DUMPED_EX_STYLES);
+    TRACE("\n");
+#undef DUMPED_EX_STYLES
+}
+
+static BOOL is_default_coord( int x )
+{
+    return x == CW_USEDEFAULT || x == 0x8000;
+}
+
+/***********************************************************************
+ *           WIN_CreateWindowEx
+ *
+ * Implementation of CreateWindowEx().
+ */
+HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE 
module, BOOL unicode )
+{
+    UNICODE_STRING class, window_name = {0};
+    HWND hwnd, top_child = 0;
+    MDICREATESTRUCTW mdi_cs;
+    WNDCLASSEXW info;
+    WCHAR name_buf[8];
+    HMENU menu;
+
+    if (!get_class_info( module, className, &info, &class, FALSE )) return 
FALSE;
+
+    TRACE("%s %s%s%s ex=%08lx style=%08lx %d,%d %dx%d parent=%p menu=%p 
inst=%p params=%p\n",
+          unicode ? debugstr_w(cs->lpszName) : 
debugstr_a((LPCSTR)cs->lpszName),
+          debugstr_w(className), class.Buffer != className ? "->" : "",
+          class.Buffer != className ? debugstr_wn(class.Buffer, class.Length / 
sizeof(WCHAR)) : "",
+          cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
+          cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
+    if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
+
+    /* Fix the styles for MDI children */
+    if (cs->dwExStyle & WS_EX_MDICHILD)
+    {
+        POINT pos[2];
+        UINT id = 0;
+
+        if (!NtUserGetMDIClientInfo( cs->hwndParent ))
+        {
+            WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", 
cs->hwndParent);
+            return 0;
+        }
+
+        /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
+         * MDICREATESTRUCT members have the originally passed values.
+         *
+         * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
+         * have the same layout.
+         */
+        mdi_cs.szClass = cs->lpszClass;
+        mdi_cs.szTitle = cs->lpszName;
+        mdi_cs.hOwner = cs->hInstance;
+        mdi_cs.x = cs->x;
+        mdi_cs.y = cs->y;
+        mdi_cs.cx = cs->cx;
+        mdi_cs.cy = cs->cy;
+        mdi_cs.style = cs->style;
+        mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
+
+        cs->lpCreateParams = &mdi_cs;
+
+        if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
+        {
+            if (cs->style & WS_POPUP)
+            {
+                TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
+                return 0;
+            }
+            cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
+        }
+        else
+        {
+            cs->style &= ~WS_POPUP;
+            cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
+                WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
+        }
+
+        top_child = GetWindow(cs->hwndParent, GW_CHILD);
+
+        if (top_child)
+        {
+            /* Restore current maximized child */
+            if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
+            {
+                TRACE("Restoring current maximized child %p\n", top_child);
+                if (cs->style & WS_MAXIMIZE)
+                {
+                    /* if the new window is maximized don't bother repainting 
*/
+                    SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
+                    NtUserShowWindow( top_child, SW_SHOWNORMAL );
+                    SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
+                }
+                else NtUserShowWindow( top_child, SW_SHOWNORMAL );
+            }
+        }
+
+        MDI_CalcDefaultChildPos( cs->hwndParent, -1, pos, 0, &id );
+        if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
+
+        TRACE( "MDI child id %04x\n", id );
+
+        if (cs->style & (WS_CHILD | WS_POPUP))
+        {
+            if (is_default_coord( cs->x ))
+            {
+                cs->x = pos[0].x;
+                cs->y = pos[0].y;
+            }
+            if (is_default_coord( cs->cx ) || !cs->cx) cs->cx = pos[1].x;
+            if (is_default_coord( cs->cy ) || !cs->cy) cs->cy = pos[1].y;
+        }
+    }
+
+    if (!unicode && cs->lpszName)
+    {
+        const char *nameA = (const char *)cs->lpszName;
+        /* resource ID string is a special case */
+        if (nameA[0] == '\xff')
+        {
+            name_buf[0] = 0xffff;
+            name_buf[1] = MAKEWORD( nameA[1], nameA[2] );
+            name_buf[2] = 0;
+            RtlInitUnicodeString( &window_name, name_buf );
+        }
+        else if (!RtlCreateUnicodeStringFromAsciiz( &window_name, (const char 
*)cs->lpszName ))
+            return 0;
+    }
+    else RtlInitUnicodeString( &window_name, cs->lpszName );
+
+    menu = cs->hMenu;
+    if (!menu && info.lpszMenuName && (cs->style & (WS_CHILD | WS_POPUP)) != 
WS_CHILD)
+        menu = LoadMenuW( cs->hInstance, info.lpszMenuName );
+
+    hwnd = NtUserCreateWindowEx( cs->dwExStyle, &class, NULL, &window_name, 
cs->style,
+                                 cs->x, cs->y, cs->cx, cs->cy, cs->hwndParent, 
menu, module,
+                                 cs->lpCreateParams, 0, cs->hInstance, 0, 
!unicode );
+    if (!hwnd && menu && menu != cs->hMenu) NtUserDestroyMenu( menu );
+    if (!unicode && window_name.Buffer != name_buf) RtlFreeUnicodeString( 
&window_name );
+    return hwnd;
+}
+
+
+/***********************************************************************
+ *             CreateWindowExA (USER32.@)
+ */
+HWND WINAPI DECLSPEC_HOTPATCH CreateWindowExA( DWORD exStyle, LPCSTR className,
+                                 LPCSTR windowName, DWORD style, INT x,
+                                 INT y, INT width, INT height,
+                                 HWND parent, HMENU menu,
+                                 HINSTANCE instance, LPVOID data )
+{
+    CREATESTRUCTA cs;
+
+    cs.lpCreateParams = data;
+    cs.hInstance      = instance;
+    cs.hMenu          = menu;
+    cs.hwndParent     = parent;
+    cs.x              = x;
+    cs.y              = y;
+    cs.cx             = width;
+    cs.cy             = height;
+    cs.style          = style;
+    cs.lpszName       = windowName;
+    cs.lpszClass      = className;
+    cs.dwExStyle      = exStyle;
+
+    if (!IS_INTRESOURCE(className))
+    {
+        WCHAR bufferW[256];
+        if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, 
ARRAY_SIZE( bufferW )))
+            return 0;
+        return wow_handlers.create_window( (CREATESTRUCTW *)&cs, bufferW, 
instance, FALSE );
+    }
+    /* Note: we rely on the fact that CREATESTRUCTA and */
+    /* CREATESTRUCTW have the same layout. */
+    return wow_handlers.create_window( (CREATESTRUCTW *)&cs, 
(LPCWSTR)className, instance, FALSE );
+}
+
+
+/***********************************************************************
+ *             CreateWindowExW (USER32.@)
+ */
+HWND WINAPI DECLSPEC_HOTPATCH CreateWindowExW( DWORD exStyle, LPCWSTR 
className,
+                                 LPCWSTR windowName, DWORD style, INT x,
+                                 INT y, INT width, INT height,
+                                 HWND parent, HMENU menu,
+                                 HINSTANCE instance, LPVOID data )
+{
+    CREATESTRUCTW cs;
+
+    cs.lpCreateParams = data;
+    cs.hInstance      = instance;
+    cs.hMenu          = menu;
+    cs.hwndParent     = parent;
+    cs.x              = x;
+    cs.y              = y;
+    cs.cx             = width;
+    cs.cy             = height;
+    cs.style          = style;
+    cs.lpszName       = windowName;
+    cs.lpszClass      = className;
+    cs.dwExStyle      = exStyle;
+
+    return wow_handlers.create_window( &cs, className, instance, TRUE );
+}
+
+
+/***********************************************************************
+ *             CloseWindow (USER32.@)
+ */
+BOOL WINAPI CloseWindow( HWND hwnd )
+{
+    if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
+    NtUserShowWindow( hwnd, SW_MINIMIZE );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *             OpenIcon (USER32.@)
+ */
+BOOL WINAPI OpenIcon( HWND hwnd )
+{
+    if (!IsIconic( hwnd )) return FALSE;
+    NtUserShowWindow( hwnd, SW_SHOWNORMAL );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *             FindWindowExW (USER32.@)
+ */
+HWND WINAPI FindWindowExW( HWND parent, HWND child, const WCHAR *class, const 
WCHAR *title )
+{
+    UNICODE_STRING class_str, title_str;
+
+    if (title) RtlInitUnicodeString( &title_str, title );
+
+    if (class)
+    {
+        if (IS_INTRESOURCE(class))
+        {
+            class_str.Buffer = (WCHAR *)class;
+            class_str.Length = class_str.MaximumLength = 0;
+        }
+        else RtlInitUnicodeString( &class_str, class );
+    }
+
+    return NtUserFindWindowEx( parent, child, class ? &class_str : NULL,
+                               title ? &title_str : NULL, 0 );
+}
+
+
+
+/***********************************************************************
+ *             FindWindowA (USER32.@)
+ */
+HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
+{
+    HWND ret = FindWindowExA( 0, 0, className, title );
+    if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
+    return ret;
+}
+
+
+/***********************************************************************
+ *             FindWindowExA (USER32.@)
+ */
+HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR 
title )
+{
+    LPWSTR titleW = NULL;
+    HWND hwnd = 0;
+
+    if (title)
+    {
+        DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
+        if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) 
return 0;
+        MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
+    }
+
+    if (!IS_INTRESOURCE(className))
+    {
+        WCHAR classW[256];
+        if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, ARRAY_SIZE( 
classW )))
+            hwnd = FindWindowExW( parent, child, classW, titleW );
+    }
+    else
+    {
+        hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
+    }
+
+    HeapFree( GetProcessHeap(), 0, titleW );
+    return hwnd;
+}
+
+
+/***********************************************************************
+ *             FindWindowW (USER32.@)
+ */
+HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
+{
+    return FindWindowExW( 0, 0, className, title );
+}
+
+
+/**********************************************************************
+ *             GetDesktopWindow (USER32.@)
+ */
+HWND WINAPI GetDesktopWindow(void)
+{
+    struct ntuser_thread_info *thread_info = NtUserGetThreadInfo();
+
+    if (thread_info->top_window) return UlongToHandle( thread_info->top_window 
);
+    return NtUserGetDesktopWindow();
+}
+
+
+/*******************************************************************
+ *             EnableWindow (USER32.@)
+ */
+BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
+{
+    return NtUserEnableWindow( hwnd, enable );
+}
+
+
+/***********************************************************************
+ *             IsWindowEnabled (USER32.@)
+ */
+BOOL WINAPI IsWindowEnabled( HWND hwnd )
+{
+    return NtUserIsWindowEnabled( hwnd );
+}
+
+/***********************************************************************
+ *             IsWindowUnicode (USER32.@)
+ */
+BOOL WINAPI IsWindowUnicode( HWND hwnd )
+{
+    return NtUserIsWindowUnicode( hwnd );
+}
+
+
+/***********************************************************************
+ *             GetWindowDpiAwarenessContext  (USER32.@)
+ */
+DPI_AWARENESS_CONTEXT WINAPI GetWindowDpiAwarenessContext( HWND hwnd )
+{
+    return LongToHandle( NtUserGetWindowDpiAwarenessContext( hwnd ) );
+}
+
+/***********************************************************************
+ *             GetDpiAwarenessContextForProcess  (USER32.@)
+ */
+DPI_AWARENESS_CONTEXT WINAPI GetDpiAwarenessContextForProcess(HANDLE process)
+{
+    return LongToHandle( NtUserGetProcessDpiAwarenessContext( process ) );
+}
+
+/***********************************************************************
+ *             GetWindowDpiHostingBehavior  (USER32.@)
+ */
+DPI_HOSTING_BEHAVIOR WINAPI GetWindowDpiHostingBehavior( HWND hwnd )
+{
+    FIXME("(%p): stub\n", hwnd);
+    return DPI_HOSTING_BEHAVIOR_DEFAULT;
+}
+
+
+static LONG_PTR get_window_long_ptr( HWND hwnd, int offset, LONG_PTR ret, BOOL 
ansi )
+{
+    if (offset == DWLP_DLGPROC && NtUserGetDialogInfo( hwnd ))
+    {
+        DLGPROC proc = NtUserGetDialogProc( (DLGPROC)ret, ansi );
+        if (proc && proc != WINPROC_PROC16) return (LONG_PTR)proc;
+    }
+    return ret;
+}
+
+
+static LONG_PTR set_dialog_proc( HWND hwnd, LONG_PTR newval, BOOL ansi )
+{
+    DLGPROC proc;
+    LONG_PTR ret;
+    newval = NtUserCallTwoParam( newval, ansi, NtUserAllocWinProc );
+    ret = NtUserSetWindowLongPtr( hwnd, DWLP_DLGPROC, newval, ansi );
+    proc = NtUserGetDialogProc( (DLGPROC)ret, ansi );
+    if (proc) ret = (UINT_PTR)proc;
+    return ret;
+}
+
+
+/***********************************************************************
+ *              GetDpiForWindow   (USER32.@)
+ */
+UINT WINAPI GetDpiForWindow( HWND hwnd )
+{
+    return NtUserGetDpiForWindow( hwnd );
+}
+
+
+/***********************************************************************
+ *           SwitchToThisWindow (USER32.@)
+ */
+void WINAPI SwitchToThisWindow( HWND hwnd, BOOL alt_tab )
+{
+    if (IsIconic( hwnd )) NtUserShowWindow( hwnd, SW_RESTORE );
+    else BringWindowToTop( hwnd );
+}
+
+
+/***********************************************************************
+ *           GetWindowRect (USER32.@)
+ */
+BOOL WINAPI GetWindowRect( HWND hwnd, RECT *rect )
+{
+    UINT dpi = NTUSER_DPI_CONTEXT_GET_DPI( 
(UINT_PTR)GetThreadDpiAwarenessContext() );
+    BOOL ret = NtUserGetWindowRect( hwnd, rect, dpi );
+    if (ret) TRACE( "hwnd %p %s\n", hwnd, wine_dbgstr_rect(rect) );
+    return ret;
+}
+
+
+/***********************************************************************
+ *           GetWindowRgn (USER32.@)
+ */
+int WINAPI GetWindowRgn( HWND hwnd, HRGN hrgn )
+{
+    return NtUserGetWindowRgnEx( hwnd, hrgn, 0 );
+}
+
+
+/***********************************************************************
+ *           GetWindowRgnBox (USER32.@)
+ */
+int WINAPI GetWindowRgnBox( HWND hwnd, RECT *rect )
+{
+    int ret = ERROR;
+    HRGN hrgn;
+
+    if (!rect)
+        return ERROR;
+
+    if ((hrgn = CreateRectRgn( 0, 0, 0, 0 )))
+    {
+        if ((ret = GetWindowRgn( hwnd, hrgn )) != ERROR )
+            ret = GetRgnBox( hrgn, rect );
+        DeleteObject( hrgn );
+    }
+
+    return ret;
+}
+
+
+/***********************************************************************
+ *           GetClientRect (USER32.@)
+ */
+BOOL WINAPI GetClientRect( HWND hwnd, RECT *rect )
+{
+    UINT dpi = NTUSER_DPI_CONTEXT_GET_DPI( 
(UINT_PTR)GetThreadDpiAwarenessContext() );
+    return NtUserGetClientRect( hwnd, rect, dpi );
+}
+
+
+/*******************************************************************
+ *           WindowFromPoint (USER32.@)
+ */
+HWND WINAPI WindowFromPoint( POINT pt )
+{
+    return NtUserWindowFromPoint( pt.x, pt.y );
+}
+
+
+/*******************************************************************
+ *           ChildWindowFromPoint (USER32.@)
+ */
+HWND WINAPI ChildWindowFromPoint( HWND parent, POINT pt )
+{
+    return NtUserChildWindowFromPointEx( parent, pt.x, pt.y, CWP_ALL );
+}
+
+/*******************************************************************
+ *           RealChildWindowFromPoint (USER32.@)
+ */
+HWND WINAPI RealChildWindowFromPoint( HWND parent, POINT pt )
+{
+    return NtUserRealChildWindowFromPoint( parent, pt.x, pt.y );
+}
+
+/*******************************************************************
+ *           ChildWindowFromPointEx (USER32.@)
+ */
+HWND WINAPI ChildWindowFromPointEx( HWND parent, POINT pt, UINT flags )
+{
+    return NtUserChildWindowFromPointEx( parent, pt.x, pt.y, flags );
+}
+
+
+/*******************************************************************
+ *           MapWindowPoints (USER32.@)
+ */
+INT WINAPI MapWindowPoints( HWND hwnd_from, HWND hwnd_to, POINT *points, UINT 
count )
+{
+    UINT dpi = NTUSER_DPI_CONTEXT_GET_DPI( 
(UINT_PTR)GetThreadDpiAwarenessContext() );
+    return NtUserMapWindowPoints( hwnd_from, hwnd_to, points, count, dpi );
+}
+
+
+/*******************************************************************
+ *           ClientToScreen (USER32.@)
+ */
+BOOL WINAPI ClientToScreen( HWND hwnd, POINT *pt )
+{
+    return NtUserClientToScreen( hwnd, pt );
+}
+
+
+/*******************************************************************
+ *           ScreenToClient (USER32.@)
+ */
+BOOL WINAPI ScreenToClient( HWND hwnd, POINT *pt )
+{
+    return NtUserScreenToClient( hwnd, pt );
+}
+
+
+/***********************************************************************
+ *           IsIconic (USER32.@)
+ */
+BOOL WINAPI IsIconic( HWND hwnd )
+{
+    return (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
+}
+
+
+/***********************************************************************
+ *           IsZoomed (USER32.@)
+ */
+BOOL WINAPI IsZoomed( HWND hwnd )
+{
+    return (GetWindowLongW( hwnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
+}
+
+
+/*******************************************************************
+ *           AllowSetForegroundWindow (USER32.@)
+ */
+BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
+{
+    /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
+     * implemented, then fix this function. */
+    return TRUE;
+}
+
+
+/*******************************************************************
+ *           LockSetForegroundWindow (USER32.@)
+ */
+BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
+{
+    /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
+     * implemented, then fix this function. */
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           BringWindowToTop (USER32.@)
+ */
+BOOL WINAPI BringWindowToTop( HWND hwnd )
+{
+    return NtUserSetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | 
SWP_NOSIZE );
+}
+
+
+/***********************************************************************
+ *           AnimateWindow (USER32.@)
+ */
+BOOL WINAPI AnimateWindow( HWND hwnd, DWORD time, DWORD flags )
+{
+    FIXME( "partial stub\n" );
+
+    /* If trying to show/hide and it's already shown/hidden or invalid window,
+     * fail with invalid parameter. */
+    if (!IsWindow( hwnd ) || (!(flags & AW_HIDE)) == IsWindowVisible( hwnd ))
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    NtUserShowWindow( hwnd, (flags & AW_HIDE) ? SW_HIDE : ((flags & 
AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA) );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           BeginDeferWindowPos (USER32.@)
+ */
+HDWP WINAPI BeginDeferWindowPos( INT count )
+{
+    return NtUserBeginDeferWindowPos( count );
+}
+
+
+/***********************************************************************
+ *           DeferWindowPos (USER32.@)
+ */
+HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND after, INT x, INT y,
+                            INT cx, INT cy, UINT flags )
+{
+    return NtUserDeferWindowPosAndBand( hdwp, hwnd, after, x, y, cx, cy, 
flags, 0, 0 );
+}
+
+
+/***********************************************************************
+ *           EndDeferWindowPos (USER32.@)
+ */
+BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
+{
+    return NtUserEndDeferWindowPosEx( hdwp, FALSE );
+}
+
+
+/***********************************************************************
+ *           ArrangeIconicWindows (USER32.@)
+ */
+UINT WINAPI ArrangeIconicWindows( HWND parent )
+{
+    return NtUserArrangeIconicWindows( parent );
+}
+
+
+/**********************************************************************
+ *             GetWindowWord (USER32.@)
+ */
+WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
+{
+    return NtUserGetWindowWord( hwnd, offset );
+}
+
+
+/**********************************************************************
+ *             GetWindowLongA (USER32.@)
+ */
+
+#ifdef __i386__
+
+/* This wrapper is here to workaround a ntlea quirk. First of all, ntlea
+ * checks whether GetWindowLongA starts with the Win32 hotpatchable prologue,
+ * if it can find that, it will use a hooking strategy more difficult for us
+ * to deal with. Secondly, it assumes what follows the prologue is a `pushl 
$-2`,
+ * and will try to skip over this instruction when calling `GetWindowLongA`,
+ * (i.e. it tries to jump to `GetWindowLongA + 7`, 5 bytes for the prologue, 2
+ * bytes for the `pushl`.). We have to anticipate that and make sure the result
+ * of doing this won't be a messed up stack, or a desynced PC.
+ */
+__ASM_STDCALL_FUNC( GetWindowLongA, 8,
+        ".byte 0x8b, 0xff, 0x55, 0x8b, 0xec\n" /* Win32 hotpatchable prologue. 
*/
+        "pushl $-2\n"
+        "addl $4, %esp\n"
+        "popl %ebp\n"
+        "jmp " __ASM_STDCALL("get_window_longA", 8) )
+LONG WINAPI get_window_longA( HWND hwnd, INT offset )
+#else
+LONG WINAPI DECLSPEC_HOTPATCH GetWindowLongA( HWND hwnd, INT offset )
+#endif
+{
+    switch (offset)
+    {
+#ifdef _WIN64
+    case GWLP_WNDPROC:
+    case GWLP_HINSTANCE:
+    case GWLP_HWNDPARENT:
+        WARN( "Invalid offset %d\n", offset );
+        SetLastError( ERROR_INVALID_INDEX );
+        return 0;
+#endif
+    default:
+        if (sizeof(void *) == sizeof(LONG))
+        {
+            LONG_PTR ret = NtUserGetWindowLongA( hwnd, offset );
+            return get_window_long_ptr( hwnd, offset, ret, TRUE );
+        }
+        return NtUserGetWindowLongA( hwnd, offset );
+    }
+}
+
+
+/**********************************************************************
+ *             GetWindowLongW (USER32.@)
+ */
+LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
+{
+    switch (offset)
+    {
+#ifdef _WIN64
+    case GWLP_WNDPROC:
+    case GWLP_HINSTANCE:
+    case GWLP_HWNDPARENT:
+        WARN( "Invalid offset %d\n", offset );
+        SetLastError( ERROR_INVALID_INDEX );
+        return 0;
+#endif
+    default:
+        if (sizeof(void *) == sizeof(LONG))
+        {
+            LONG_PTR ret = NtUserGetWindowLongW( hwnd, offset );
+            return get_window_long_ptr( hwnd, offset, ret, FALSE );
+        }
+        return NtUserGetWindowLongW( hwnd, offset );
+    }
+}
+
+
+/**********************************************************************
+ *             SetWindowLongA (USER32.@)
+ *
+ * See SetWindowLongW.
+ */
+LONG WINAPI DECLSPEC_HOTPATCH SetWindowLongA( HWND hwnd, INT offset, LONG 
newval )
+{
+    switch (offset)
+    {
+#ifdef _WIN64
+    case GWLP_WNDPROC:
+    case GWLP_HINSTANCE:
+    case GWLP_HWNDPARENT:
+        WARN( "Invalid offset %d\n", offset );
+        SetLastError( ERROR_INVALID_INDEX );
+        return 0;
+#else
+    case DWLP_DLGPROC:
+        if (NtUserGetDialogInfo( hwnd )) return set_dialog_proc( hwnd, newval, 
TRUE );
+        /* fall through */
+#endif
+    default:
+        return NtUserSetWindowLong( hwnd, offset, newval, TRUE );
+    }
+}
+
+
+/**********************************************************************
+ *             SetWindowLongW (USER32.@) Set window attribute
+ *
+ * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
+ * value in a window's extra memory.
+ *
+ * The _hwnd_ parameter specifies the handle to a window that
+ * has extra memory. The _newval_ parameter contains the new
+ * attribute or extra memory value.  If positive, the _offset_
+ * parameter is the byte-addressed location in the window's extra
+ * memory to set.  If negative, _offset_ specifies the window
+ * attribute to set, and should be one of the following values:
+ *
+ * GWL_EXSTYLE      The window's extended window style
+ *
+ * GWL_STYLE        The window's window style.
+ *
+ * GWLP_WNDPROC     Pointer to the window's window procedure.
+ *
+ * GWLP_HINSTANCE   The window's application instance handle.
+ *
+ * GWLP_ID          The window's identifier.
+ *
+ * GWLP_USERDATA    The window's user-specified data.
+ *
+ * If the window is a dialog box, the _offset_ parameter can be one of
+ * the following values:
+ *
+ * DWLP_DLGPROC     The address of the window's dialog box procedure.
+ *
+ * DWLP_MSGRESULT   The return value of a message
+ *                  that the dialog box procedure processed.
+ *
+ * DWLP_USER        Application specific information.
+ *
+ * RETURNS
+ *
+ * If successful, returns the previous value located at _offset_. Otherwise,
+ * returns 0.
+ *
+ * NOTES
+ *
+ * Extra memory for a window class is specified by a nonzero cbWndExtra
+ * parameter of the WNDCLASS structure passed to RegisterClass() at the
+ * time of class creation.
+ *
+ * Using GWL_WNDPROC to set a new window procedure effectively creates
+ * a window subclass. Use CallWindowProc() in the new windows procedure
+ * to pass messages to the superclass's window procedure.
+ *
+ * The user data is reserved for use by the application which created
+ * the window.
+ *
+ * Do not use GWL_STYLE to change the window's WS_DISABLED style;
+ * instead, call the EnableWindow() function to change the window's
+ * disabled state.
+ *
+ * Do not use GWL_HWNDPARENT to reset the window's parent, use
+ * SetParent() instead.
+ *
+ * Win95:
+ * When offset is GWL_STYLE and the calling app's ver is 4.0,
+ * it sends WM_STYLECHANGING before changing the settings
+ * and WM_STYLECHANGED afterwards.
+ * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
+ */
+LONG WINAPI DECLSPEC_HOTPATCH SetWindowLongW(
+    HWND hwnd,  /* [in] window to alter */
+    INT offset, /* [in] offset, in bytes, of location to alter */
+    LONG newval /* [in] new value of location */
+)
+{
+    switch (offset)
+    {
+#ifdef _WIN64
+    case GWLP_WNDPROC:
+    case GWLP_HINSTANCE:
+    case GWLP_HWNDPARENT:
+        WARN("Invalid offset %d\n", offset );
+        SetLastError( ERROR_INVALID_INDEX );
+        return 0;
+#else
+    case DWLP_DLGPROC:
+        if (NtUserGetDialogInfo( hwnd )) return set_dialog_proc( hwnd, newval, 
FALSE );
+        /* fall through */
+#endif
+    default:
+        return NtUserSetWindowLong( hwnd, offset, newval, FALSE );
+    }
+}
+
+
+/*******************************************************************
+ *             GetWindowTextA (USER32.@)
+ */
+INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
+{
+    WCHAR *buffer;
+    int ret = 0;
+
+    if (!lpString || nMaxCount <= 0) return 0;
+
+    __TRY
+    {
+        lpString[0] = 0;
+
+        if (WIN_IsCurrentProcess( hwnd ))
+        {
+            ret = (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, 
(LPARAM)lpString );
+        }
+        else if ((buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * 
sizeof(WCHAR) )))
+        {
+            /* when window belongs to other process, don't send a message */
+            NtUserInternalGetWindowText( hwnd, buffer, nMaxCount );
+            if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, 
nMaxCount, NULL, NULL ))
+                lpString[nMaxCount-1] = 0;
+            HeapFree( GetProcessHeap(), 0, buffer );
+            ret = strlen(lpString);
+        }
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        ret = 0;
+    }
+    __ENDTRY
+
+    return ret;
+}
+
+
+/*******************************************************************
+ *             GetWindowTextW (USER32.@)
+ */
+INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
+{
+    int ret;
+
+    if (!lpString || nMaxCount <= 0) return 0;
+
+    __TRY
+    {
+        lpString[0] = 0;
+
+        if (WIN_IsCurrentProcess( hwnd ))
+        {
+            ret = (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, 
(LPARAM)lpString );
+        }
+        else
+        {
+            /* when window belongs to other process, don't send a message */
+            ret = NtUserInternalGetWindowText( hwnd, lpString, nMaxCount );
+        }
+    }
+    __EXCEPT_PAGE_FAULT
+    {
+        ret = 0;
+    }
+    __ENDTRY
+
+    return ret;
+}
+
+
+/*******************************************************************
+ *             SetWindowTextA (USER32.@)
+ *             SetWindowText  (USER32.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH SetWindowTextA( HWND hwnd, LPCSTR lpString )
+{
+    if (is_broadcast(hwnd))
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+    if (!WIN_IsCurrentProcess( hwnd ))
+        WARN( "setting text %s of other process window %p should not use 
SendMessage\n",
+               debugstr_a(lpString), hwnd );
+    return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
+}
+
+
+/*******************************************************************
+ *             SetWindowTextW (USER32.@)
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH SetWindowTextW( HWND hwnd, LPCWSTR lpString )
+{
+    if (is_broadcast(hwnd))
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+    if (!WIN_IsCurrentProcess( hwnd ))
+        WARN( "setting text %s of other process window %p should not use 
SendMessage\n",
+               debugstr_w(lpString), hwnd );
+    return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
+}
+
+
+/*******************************************************************
+ *             GetWindowTextLengthA (USER32.@)
+ */
+INT WINAPI GetWindowTextLengthA( HWND hwnd )
+{
+    CPINFO info;
+
+    if (WIN_IsCurrentProcess( hwnd )) return SendMessageA( hwnd, 
WM_GETTEXTLENGTH, 0, 0 );
+
+    /* when window belongs to other process, don't send a message */
+    GetCPInfo( CP_ACP, &info );
+    return NtUserGetWindowTextLength( hwnd ) * info.MaxCharSize;
+}
+
+/*******************************************************************
+ *             GetWindowTextLengthW (USER32.@)
+ */
+INT WINAPI GetWindowTextLengthW( HWND hwnd )
+{
+    if (WIN_IsCurrentProcess( hwnd )) return SendMessageW( hwnd, 
WM_GETTEXTLENGTH, 0, 0 );
+
+    /* when window belongs to other process, don't send a message */
+    return NtUserGetWindowTextLength( hwnd );
+}
+
+
+/*******************************************************************
+ *             IsWindow (USER32.@)
+ */
+BOOL WINAPI IsWindow( HWND hwnd )
+{
+    return NtUserIsWindow( hwnd );
+}
+
+
+/***********************************************************************
+ *             GetWindowThreadProcessId (USER32.@)
+ */
+DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
+{
+    return NtUserGetWindowThread( hwnd, process );
+}
+
+
+/*****************************************************************
+ *             GetParent (USER32.@)
+ */
+HWND WINAPI GetParent( HWND hwnd )
+{
+    return NtUserGetParent( hwnd );
+}
+
+
+/*******************************************************************
+ *             IsChild (USER32.@)
+ */
+BOOL WINAPI IsChild( HWND parent, HWND child )
+{
+    return NtUserIsChild( parent, child );
+}
+
+
+/***********************************************************************
+ *             IsWindowVisible (USER32.@)
+ */
+BOOL WINAPI IsWindowVisible( HWND hwnd )
+{
+    return NtUserIsWindowVisible( hwnd );
+}
+
+
+/*******************************************************************
+ *             GetTopWindow (USER32.@)
+ */
+HWND WINAPI GetTopWindow( HWND hwnd )
+{
+    if (!hwnd) hwnd = GetDesktopWindow();
+    return GetWindow( hwnd, GW_CHILD );
+}
+
+
+/*******************************************************************
+ *             GetWindow (USER32.@)
+ */
+HWND WINAPI GetWindow( HWND hwnd, UINT rel )
+{
+    return NtUserGetWindowRelative( hwnd, rel );
+}
+
+
+/*******************************************************************
+ *             ShowOwnedPopups (USER32.@)
+ */
+BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL show )
+{
+    return NtUserShowOwnedPopups( owner, show );
+}
+
+
+/*******************************************************************
+ *             GetLastActivePopup (USER32.@)
+ */
+HWND WINAPI GetLastActivePopup( HWND hwnd )
+{
+    return NtUserGetLastActivePopup( hwnd );
+}
+
+
+/*******************************************************************
+ *           WIN_ListChildren
+ *
+ * Build an array of the children of a given window. The array must be
+ * freed with HeapFree. Returns NULL when no windows are found.
+ */
+HWND *WIN_ListChildren( HWND hwnd )
+{
+    HWND *list;
+    ULONG size = 128;
+    NTSTATUS status;
+
+    if (!(hwnd = GetWindow( hwnd, GW_CHILD ))) return NULL;
+
+    for (;;)
+    {
+        if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) 
return NULL;
+        status = NtUserBuildHwndList( 0, hwnd, FALSE, TRUE, 0, size, list, 
&size );
+        if (!status && size > 1) break;
+        HeapFree( GetProcessHeap(), 0, list );
+        if (status != STATUS_BUFFER_TOO_SMALL) return NULL;
+    }
+    list[size - 1] = 0;
+    return list;
+}
+
+
+/*******************************************************************
+ *             EnumWindows (USER32.@)
+ */
+BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
+{
+    return enum_windows( 0, 0, 0, FALSE, lpEnumFunc, lParam );
+}
+
+
+/**********************************************************************
+ *             EnumThreadWindows (USER32.@)
+ */
+BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
+{
+    return enum_windows( 0, 0, id, FALSE, func, lParam );
+}
+
+
+/***********************************************************************
+ *              EnumDesktopWindows   (USER32.@)
+ */
+BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam 
)
+{
+    return enum_windows( desktop, 0, 0, FALSE, func, lparam );
+}
+
+
+/**********************************************************************
+ *             EnumChildWindows (USER32.@)
+ */
+BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
+{
+    return enum_windows( 0, parent, 0, TRUE, func, lParam );
+}
+
+
+/*******************************************************************
+ *             AnyPopup (USER32.@)
+ */
+BOOL WINAPI AnyPopup(void)
+{
+    int i;
+    BOOL retvalue;
+    HWND *list = WIN_ListChildren( GetDesktopWindow() );
+
+    if (!list) return FALSE;
+    for (i = 0; list[i]; i++)
+    {
+        if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) 
break;
+    }
+    retvalue = (list[i] != 0);
+    HeapFree( GetProcessHeap(), 0, list );
+    return retvalue;
+}
+
+
+/*******************************************************************
+ *             FlashWindow (USER32.@)
+ */
+BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
+{
+    FLASHWINFO finfo;
+
+    finfo.cbSize = sizeof(FLASHWINFO);
+    finfo.dwFlags = bInvert ? FLASHW_ALL : FLASHW_STOP;
+    finfo.uCount = 1;
+    finfo.dwTimeout = 0;
+    finfo.hwnd = hWnd;
+    return NtUserFlashWindowEx( &finfo );
+}
+
+
+/*******************************************************************
+ *             GetWindowContextHelpId (USER32.@)
+ */
+DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
+{
+    return NtUserGetWindowContextHelpId( hwnd );
+}
+
+
+/*******************************************************************
+ *             SetWindowContextHelpId (USER32.@)
+ */
+BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
+{
+    return NtUserSetWindowContextHelpId( hwnd, id );
+}
+
+
+/*******************************************************************
+ *             DragDetect (USER32.@)
+ */
+BOOL WINAPI DragDetect( HWND hwnd, POINT pt )
+{
+    return NtUserDragDetect( hwnd, pt.x, pt.y );
+}
+
+/******************************************************************************
+ *             GetWindowModuleFileNameA (USER32.@)
+ */
+UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
+{
+    HINSTANCE hinst;
+
+    TRACE( "%p, %p, %u\n", hwnd, module, size );
+
+    if (!WIN_IsCurrentProcess( hwnd ))
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+
+    hinst = (HINSTANCE)GetWindowLongPtrA( hwnd, GWLP_HINSTANCE );
+    return GetModuleFileNameA( hinst, module, size );
+}
+
+/******************************************************************************
+ *             GetWindowModuleFileNameW (USER32.@)
+ */
+UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
+{
+    HINSTANCE hinst;
+
+    TRACE( "%p, %p, %u\n", hwnd, module, size );
+
+    if (!WIN_IsCurrentProcess( hwnd ))
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return 0;
+    }
+
+    hinst = (HINSTANCE)GetWindowLongPtrW( hwnd, GWLP_HINSTANCE );
+    return GetModuleFileNameW( hinst, module, size );
+}
+
+/******************************************************************************
+ *              GetWindowInfo (USER32.@)
+ *
+ * Note: tests show that Windows doesn't check cbSize of the structure.
+ */
+BOOL WINAPI DECLSPEC_HOTPATCH GetWindowInfo( HWND hwnd, WINDOWINFO *info )
+{
+    return NtUserGetWindowInfo( hwnd, info );
+}
+
+/*****************************************************************************
+ *              UpdateLayeredWindowIndirect  (USER32.@)
+ */
+BOOL WINAPI UpdateLayeredWindowIndirect( HWND hwnd, const 
UPDATELAYEREDWINDOWINFO *info )
+{
+    if (!info || info->cbSize != sizeof(*info))
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+
+    return NtUserUpdateLayeredWindow( hwnd, info->hdcDst, info->pptDst, 
info->psize,
+                                      info->hdcSrc, info->pptSrc, info->crKey,
+                                      info->pblend, info->dwFlags, 
info->prcDirty );
+}
+
+
+/*****************************************************************************
+ *              UpdateLayeredWindow (USER32.@)
+ */
+BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE 
*psize,
+                                 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, 
BLENDFUNCTION *pblend,
+                                 DWORD flags)
+{
+    UPDATELAYEREDWINDOWINFO info;
+
+    if (flags & ULW_EX_NORESIZE)  /* only valid for 
UpdateLayeredWindowIndirect */
+    {
+        SetLastError( ERROR_INVALID_PARAMETER );
+        return FALSE;
+    }
+    info.cbSize   = sizeof(info);
+    info.hdcDst   = hdcDst;
+    info.pptDst   = pptDst;
+    info.psize    = psize;
+    info.hdcSrc   = hdcSrc;
+    info.pptSrc   = pptSrc;
+    info.crKey    = crKey;
+    info.pblend   = pblend;
+    info.dwFlags  = flags;
+    info.prcDirty = NULL;
+    return UpdateLayeredWindowIndirect( hwnd, &info );
+}
+
+
+/******************************************************************************
+ *                    GetProcessDefaultLayout [USER32.@]
+ *
+ * Gets the default layout for parentless windows.
+ */
+BOOL WINAPI GetProcessDefaultLayout( DWORD *layout )
+{
+    if (!layout)
+    {
+        SetLastError( ERROR_NOACCESS );
+        return FALSE;
+    }
+    *layout = NtUserGetProcessDefaultLayout();
+    if (*layout == ~0u)
+    {
+        WCHAR *str, buffer[MAX_PATH];
+        DWORD i, version_layout = 0;
+        UINT len;
+        DWORD user_lang = GetUserDefaultLangID();
+        DWORD *languages;
+        void *data = NULL;
+
+        GetModuleFileNameW( 0, buffer, MAX_PATH );
+        if (!(len = GetFileVersionInfoSizeW( buffer, NULL ))) goto done;
+        if (!(data = HeapAlloc( GetProcessHeap(), 0, len ))) goto done;
+        if (!GetFileVersionInfoW( buffer, 0, len, data )) goto done;
+        if (!VerQueryValueW( data, L"\\VarFileInfo\\Translation", (void 
**)&languages, &len ) || !len) goto done;
+
+        len /= sizeof(DWORD);
+        for (i = 0; i < len; i++) if (LOWORD(languages[i]) == user_lang) break;
+        if (i == len)  /* try neutral language */
+            for (i = 0; i < len; i++)
+                if (LOWORD(languages[i]) == MAKELANGID( 
PRIMARYLANGID(user_lang), SUBLANG_NEUTRAL )) break;
+        if (i == len) i = 0;  /* default to the first one */
+
+        swprintf( buffer, ARRAY_SIZE(buffer), 
L"\\StringFileInfo\\%04x%04x\\FileDescription",
+                  LOWORD(languages[i]), HIWORD(languages[i]) );
+        if (!VerQueryValueW( data, buffer, (void **)&str, &len )) goto done;
+        TRACE( "found description %s\n", debugstr_w( str ));
+        if (str[0] == 0x200e && str[1] == 0x200e) version_layout = LAYOUT_RTL;
+
+    done:
+        HeapFree( GetProcessHeap(), 0, data );
+        NtUserSetProcessDefaultLayout( *layout = version_layout );
+    }
+    return TRUE;
+}
+
+
+/******************************************************************************
+ *                    SetProcessDefaultLayout [USER32.@]
+ *
+ * Sets the default layout for parentless windows.
+ */
+BOOL WINAPI SetProcessDefaultLayout( DWORD layout )
+{
+    return NtUserSetProcessDefaultLayout( layout );
+}
+
+
+/***********************************************************************
+ *           UpdateWindow (USER32.@)
+ */
+BOOL WINAPI UpdateWindow( HWND hwnd )
+{
+    if (!hwnd)
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return FALSE;
+    }
+
+    return NtUserRedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_ALLCHILDREN 
);
+}
+
+
+/***********************************************************************
+ *           ValidateRgn (USER32.@)
+ */
+BOOL WINAPI ValidateRgn( HWND hwnd, HRGN hrgn )
+{
+    if (!hwnd)
+    {
+        SetLastError( ERROR_INVALID_WINDOW_HANDLE );
+        return FALSE;
+    }
+
+    return NtUserRedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE );
+}
+
+
+/*************************************************************************
+ *           ScrollWindow (USER32.@)
+ */
+BOOL WINAPI ScrollWindow( HWND hwnd, INT dx, INT dy, const RECT *rect, const 
RECT *clip_rect )
+{
+    UINT flags = SW_INVALIDATE | SW_ERASE | (rect ? 0 : SW_SCROLLCHILDREN) | 
SW_NODCCACHE;
+    return NtUserScrollWindowEx( hwnd, dx, dy, rect, clip_rect, 0, NULL, flags 
);
+}
+
+#ifdef _WIN64
+
+/* 64bit versions */
+
+#undef GetWindowLongPtrW
+#undef GetWindowLongPtrA
+#undef SetWindowLongPtrW
+#undef SetWindowLongPtrA
+
+/*****************************************************************************
+ *              GetWindowLongPtrW (USER32.@)
+ */
+LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
+{
+    LONG_PTR ret = NtUserGetWindowLongPtrW( hwnd, offset );
+    return get_window_long_ptr( hwnd, offset, ret, FALSE );
+}
+
+/*****************************************************************************
+ *              GetWindowLongPtrA (USER32.@)
+ */
+LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
+{
+    LONG_PTR ret = NtUserGetWindowLongPtrA( hwnd, offset );
+    return get_window_long_ptr( hwnd, offset, ret, TRUE );
+}
+
+/*****************************************************************************
+ *              SetWindowLongPtrW (USER32.@)
+ */
+LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
+{
+    if (offset == DWLP_DLGPROC && NtUserGetDialogInfo( hwnd ))
+        return set_dialog_proc( hwnd, newval, FALSE );
+
+    return NtUserSetWindowLongPtr( hwnd, offset, newval, FALSE );
+}
+
+/*****************************************************************************
+ *              SetWindowLongPtrA (USER32.@)
+ */
+LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
+{
+    if (offset == DWLP_DLGPROC && NtUserGetDialogInfo( hwnd ))
+        return set_dialog_proc( hwnd, newval, TRUE );
+
+    return NtUserSetWindowLongPtr( hwnd, offset, newval, TRUE );
+}
+
+#endif /* _WIN64 */
+
+/*****************************************************************************
+ *              GetWindowDisplayAffinity (USER32.@)
+ */
+BOOL WINAPI GetWindowDisplayAffinity(HWND hwnd, DWORD *affinity)
+{
+    FIXME("(%p, %p): stub\n", hwnd, affinity);
+
+    if (!hwnd || !affinity)
+    {
+        SetLastError(hwnd ? ERROR_NOACCESS : ERROR_INVALID_WINDOW_HANDLE);
+        return FALSE;
+    }
+
+    *affinity = WDA_NONE;
+    return TRUE;
+}
+
+/*****************************************************************************
+ *              SetWindowDisplayAffinity (USER32.@)
+ */
+BOOL WINAPI SetWindowDisplayAffinity(HWND hwnd, DWORD affinity)
+{
+    FIXME("(%p, %lu): stub\n", hwnd, affinity);
+
+    if (!hwnd)
+    {
+        SetLastError(ERROR_INVALID_WINDOW_HANDLE);
+        return FALSE;
+    }
+
+    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    return FALSE;
+}
+
+/**********************************************************************
+ *              SetWindowCompositionAttribute (USER32.@)
+ */
+BOOL WINAPI SetWindowCompositionAttribute(HWND hwnd, void *data)
+{
+    FIXME("(%p, %p): stub\n", hwnd, data);
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}

Reply via email to