updated listbox control from wine 0.9.2
[reactos.git] / reactos / lib / user32 / controls / listbox.c
index 1a3cee8..9c998a5 100644 (file)
@@ -1,31 +1,26 @@
-/* $Id: listbox.c,v 1.14 2003/12/14 19:36:15 sedwards Exp $
+/*
+ * Listbox controls
  *
- * COPYRIGHT:        See COPYING in the top level directory
- * PROJECT:          ReactOS User32
- * PURPOSE:          ListBox controls
- * FILE:             lib/user32/controls/listbox.c
- * PROGRAMER:        Andrew Greenwood
- * REVISION HISTORY: 2003/08/17 Created
- * NOTES:            Adapted from Wine
+ * Copyright 1996 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <user32.h>
 #define NDEBUG
-#include <string.h>
-#include <stdlib.h>
-//#include <stdio.h>
-#include "windows.h"
-#include "controls.h"
-#include "user32/regcontrol.h"
-#include "wine/unicode.h"
-#include "wine/debug.h"
-
-/* Unimplemented yet:
- * - LBS_USETABSTOPS
- * - Locale handling
- *
- * Probably needs improvement:
- * - LBS_NOSEL
- */
+#include <debug.h>
 
 /* Start of hack section -------------------------------- */
 
@@ -40,8 +35,19 @@ BOOL is_old_app(HWND hwnd)
 #define WS_EX_DRAGDETECT    0x00000002L
 #define WM_BEGINDRAG        0x022C
 
+UINT STDCALL SetSystemTimer(HWND,UINT_PTR,UINT,TIMERPROC);
+BOOL STDCALL KillSystemTimer(HWND,UINT_PTR);
+
 /* End of hack section -------------------------------- */
 
+/* Unimplemented yet:
+ * - LBS_USETABSTOPS
+ * - Locale handling
+ *
+ * Probably needs improvement:
+ * - LBS_NOSEL
+ */
+
 /* Items array granularity */
 #define LB_ARRAY_GRANULARITY 16
 
@@ -66,6 +72,7 @@ typedef struct
 /* Listbox structure */
 typedef struct
 {
+    HWND        self;           /* Our own window handle */
     HWND        owner;          /* Owner window to send notifications to */
     UINT        style;          /* Window style */
     INT         width;          /* Window width */
@@ -83,6 +90,7 @@ typedef struct
     INT         horz_pos;       /* Horizontal position */
     INT         nb_tabs;        /* Number of tabs in array */
     INT        *tabs;           /* Array of tabs */
+    INT         avg_char_width; /* Average width of characters */
     BOOL        caret_on;       /* Is caret on? */
     BOOL        captured;       /* Is mouse captured? */
     BOOL       in_focus;
@@ -100,11 +108,12 @@ typedef struct
 
 
 #define IS_MULTISELECT(descr) \
-    ((descr)->style & LBS_MULTIPLESEL || ((descr)->style & LBS_EXTENDEDSEL))
+    ((descr)->style & (LBS_MULTIPLESEL|LBS_EXTENDEDSEL) && \
+     !((descr)->style & LBS_NOSEL))
 
-#define SEND_NOTIFICATION(hwnd,descr,code) \
+#define SEND_NOTIFICATION(descr,code) \
     (SendMessageW( (descr)->owner, WM_COMMAND, \
-     MAKEWPARAM( GetWindowLongA((hwnd),GWL_ID), (code)), (LPARAM)(hwnd) ))
+     MAKEWPARAM( GetWindowLongPtrW((descr->self),GWLP_ID), (code)), (LPARAM)(descr->self) ))
 
 #define ISWIN31 (LOWORD(GetVersion()) == 0x0a03)
 
@@ -120,8 +129,6 @@ typedef enum
 
 static TIMER_DIRECTION LISTBOX_Timer = LB_TIMER_NONE;
 
-static LRESULT WINAPI ComboLBWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
-static LRESULT WINAPI ComboLBWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
 static LRESULT WINAPI ListBoxWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
 static LRESULT WINAPI ListBoxWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
 
@@ -132,13 +139,23 @@ static LRESULT LISTBOX_GetItemRect( LB_DESCR *descr, INT index, RECT *rect );
  */
 const struct builtin_class_descr LISTBOX_builtin_class =
 {
+#ifdef __REACTOS__
     L"ListBox",            /* name */
-    CS_GLOBALCLASS | CS_DBLCLKS /*| CS_PARENTDC*/,  /* style */
+    CS_DBLCLKS /*| CS_PARENTDC*/,  /* style */
     (WNDPROC)ListBoxWndProcW,      /* procW */
     (WNDPROC)ListBoxWndProcA,      /* procA */
     sizeof(LB_DESCR *),   /* extra */
     (LPCWSTR) IDC_ARROW,           /* cursor */
     0                     /* brush */
+#else
+    "ListBox",            /* name */
+    CS_DBLCLKS /*| CS_PARENTDC*/,  /* style */
+    ListBoxWndProcA,      /* procA */
+    ListBoxWndProcW,      /* procW */
+    sizeof(LB_DESCR *),   /* extra */
+    IDC_ARROW,            /* cursor */
+    0                     /* brush */
+#endif
 };
 
 
@@ -147,16 +164,34 @@ const struct builtin_class_descr LISTBOX_builtin_class =
  */
 const struct builtin_class_descr COMBOLBOX_builtin_class =
 {
+#ifdef __REACTOS__
     L"ComboLBox",          /* name */
-    CS_GLOBALCLASS | CS_DBLCLKS | CS_SAVEBITS,  /* style */
-    (WNDPROC)ComboLBWndProcW,      /* procW */
-    (WNDPROC)ComboLBWndProcA,      /* procA */
+    CS_DBLCLKS | CS_SAVEBITS,  /* style */
+    (WNDPROC)ListBoxWndProcW,      /* procW */
+    (WNDPROC)ListBoxWndProcA,      /* procA */
     sizeof(LB_DESCR *),   /* extra */
     (LPCWSTR) IDC_ARROW,           /* cursor */
     0                     /* brush */
+#else
+    "ComboLBox",          /* name */
+    CS_DBLCLKS | CS_SAVEBITS,  /* style */
+    ListBoxWndProcA,      /* procA */
+    ListBoxWndProcW,      /* procW */
+    sizeof(LB_DESCR *),   /* extra */
+    IDC_ARROW,            /* cursor */
+    0                     /* brush */
+#endif
 };
 
-#if 0
+#ifndef __REACTOS__
+/* check whether app is a Win 3.1 app */
+inline static BOOL is_old_app( HWND hwnd )
+{
+    return (GetExpWinVer16( GetWindowLongA(hwnd,GWL_HINSTANCE) ) & 0xFF00 ) == 0x0300;
+}
+#endif
+
+
 /***********************************************************************
  *           LISTBOX_Dump
  */
@@ -172,14 +207,10 @@ void LISTBOX_Dump( HWND hwnd )
     for (i = 0, item = descr->items; i < descr->nb_items; i++, item++)
     {
         TRACE( "%4d: %-40s %d %08lx %3d\n",
-               i, 
-                          debugstr_w(item->str), 
-                          item->selected, 
-                          item->data, 
-                          item->height );
+               i, debugstr_w(item->str), item->selected, item->data, item->height );
     }
 }
-#endif
+
 
 /***********************************************************************
  *           LISTBOX_GetCurrentPageSize
@@ -236,7 +267,7 @@ static INT LISTBOX_GetMaxTopIndex( LB_DESCR *descr )
  * Update the scrollbars. Should be called whenever the content
  * of the listbox changes.
  */
-static void LISTBOX_UpdateScroll( HWND hwnd, LB_DESCR *descr )
+static void LISTBOX_UpdateScroll( LB_DESCR *descr )
 {
     SCROLLINFO info;
 
@@ -269,11 +300,11 @@ static void LISTBOX_UpdateScroll( HWND hwnd, LB_DESCR *descr )
         if (descr->style & LBS_DISABLENOSCROLL)
             info.fMask |= SIF_DISABLENOSCROLL;
         if (descr->style & WS_HSCROLL)
-            SetScrollInfo( hwnd, SB_HORZ, &info, TRUE );
+            SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
         info.nMax = 0;
         info.fMask = SIF_RANGE;
         if (descr->style & WS_VSCROLL)
-            SetScrollInfo( hwnd, SB_VERT, &info, TRUE );
+            SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
     }
     else
     {
@@ -285,7 +316,7 @@ static void LISTBOX_UpdateScroll( HWND hwnd, LB_DESCR *descr )
         if (descr->style & LBS_DISABLENOSCROLL)
             info.fMask |= SIF_DISABLENOSCROLL;
         if (descr->style & WS_VSCROLL)
-            SetScrollInfo( hwnd, SB_VERT, &info, TRUE );
+            SetScrollInfo( descr->self, SB_VERT, &info, TRUE );
 
         if (descr->horz_extent)
         {
@@ -297,7 +328,7 @@ static void LISTBOX_UpdateScroll( HWND hwnd, LB_DESCR *descr )
             if (descr->style & LBS_DISABLENOSCROLL)
                 info.fMask |= SIF_DISABLENOSCROLL;
             if (descr->style & WS_HSCROLL)
-                SetScrollInfo( hwnd, SB_HORZ, &info, TRUE );
+                SetScrollInfo( descr->self, SB_HORZ, &info, TRUE );
         }
     }
 }
@@ -308,7 +339,7 @@ static void LISTBOX_UpdateScroll( HWND hwnd, LB_DESCR *descr )
  *
  * Set the top item of the listbox, scrolling up or down if necessary.
  */
-static LRESULT LISTBOX_SetTopItem( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_SetTopItem( LB_DESCR *descr, INT index,
                                    BOOL scroll )
 {
     INT max = LISTBOX_GetMaxTopIndex( descr );
@@ -320,7 +351,7 @@ static LRESULT LISTBOX_SetTopItem( HWND hwnd, LB_DESCR *descr, INT index,
     {
         INT diff = (descr->top_item - index) / descr->page_size * descr->column_width;
         if (scroll && (abs(diff) < descr->width))
-            ScrollWindowEx( hwnd, diff, 0, NULL, NULL, 0, NULL,
+            ScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL,
                               SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
 
         else
@@ -348,14 +379,14 @@ static LRESULT LISTBOX_SetTopItem( HWND hwnd, LB_DESCR *descr, INT index,
             diff = (descr->top_item - index) * descr->item_height;
 
         if (abs(diff) < descr->height)
-            ScrollWindowEx( hwnd, 0, diff, NULL, NULL, 0, NULL,
+            ScrollWindowEx( descr->self, 0, diff, NULL, NULL, 0, NULL,
                               SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
         else
             scroll = FALSE;
     }
-    if (!scroll) InvalidateRect( hwnd, NULL, TRUE );
+    if (!scroll) InvalidateRect( descr->self, NULL, TRUE );
     descr->top_item = index;
-    LISTBOX_UpdateScroll( hwnd, descr );
+    LISTBOX_UpdateScroll( descr );
     return LB_OKAY;
 }
 
@@ -366,7 +397,7 @@ static LRESULT LISTBOX_SetTopItem( HWND hwnd, LB_DESCR *descr, INT index,
  * Update the page size. Should be called when the size of
  * the client area or the item height changes.
  */
-static void LISTBOX_UpdatePage( HWND hwnd, LB_DESCR *descr )
+static void LISTBOX_UpdatePage( LB_DESCR *descr )
 {
     INT page_size;
 
@@ -375,8 +406,8 @@ static void LISTBOX_UpdatePage( HWND hwnd, LB_DESCR *descr )
     if (page_size == descr->page_size) return;
     descr->page_size = page_size;
     if (descr->style & LBS_MULTICOLUMN)
-        InvalidateRect( hwnd, NULL, TRUE );
-    LISTBOX_SetTopItem( hwnd, descr, descr->top_item, FALSE );
+        InvalidateRect( descr->self, NULL, TRUE );
+    LISTBOX_SetTopItem( descr, descr->top_item, FALSE );
 }
 
 
@@ -386,11 +417,11 @@ static void LISTBOX_UpdatePage( HWND hwnd, LB_DESCR *descr )
  * Update the size of the listbox. Should be called when the size of
  * the client area changes.
  */
-static void LISTBOX_UpdateSize( HWND hwnd, LB_DESCR *descr )
+static void LISTBOX_UpdateSize( LB_DESCR *descr )
 {
     RECT rect;
 
-    GetClientRect( hwnd, &rect );
+    GetClientRect( descr->self, &rect );
     descr->width  = rect.right - rect.left;
     descr->height = rect.bottom - rect.top;
     if (!(descr->style & LBS_NOINTEGRALHEIGHT) && !(descr->style & LBS_OWNERDRAWVARIABLE))
@@ -398,13 +429,14 @@ static void LISTBOX_UpdateSize( HWND hwnd, LB_DESCR *descr )
         INT remaining;
         RECT rect;
 
-        GetWindowRect( hwnd, &rect );
+        GetWindowRect( descr->self, &rect );
         if(descr->item_height != 0)
             remaining = descr->height % descr->item_height;
         else
             remaining = 0;
         if ((descr->height > descr->item_height) && remaining)
         {
+#ifndef __REACTOS__
             if (is_old_app(hwnd))
             { /* give a margin for error to 16 bits programs - if we need
                  less than the height of the nonclient area, round to the
@@ -413,22 +445,23 @@ static void LISTBOX_UpdateSize( HWND hwnd, LB_DESCR *descr )
                 if ((descr->item_height - remaining) <= ncheight)
                     remaining = remaining - descr->item_height;
             }
+#endif
             TRACE("[%p]: changing height %d -> %d\n",
-                  hwnd, descr->height, descr->height - remaining );
-            SetWindowPos( hwnd, 0, 0, 0, rect.right - rect.left,
+                  descr->self, descr->height, descr->height - remaining );
+            SetWindowPos( descr->self, 0, 0, 0, rect.right - rect.left,
                             rect.bottom - rect.top - remaining,
                             SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE );
             return;
         }
     }
-    TRACE("[%p]: new size = %d,%d\n", hwnd, descr->width, descr->height );
-    LISTBOX_UpdatePage( hwnd, descr );
-    LISTBOX_UpdateScroll( hwnd, descr );
+    TRACE("[%p]: new size = %d,%d\n", descr->self, descr->width, descr->height );
+    LISTBOX_UpdatePage( descr );
+    LISTBOX_UpdateScroll( descr );
 
     /* Invalidate the focused item so it will be repainted correctly */
     if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1)
     {
-        InvalidateRect( hwnd, &rect, FALSE );
+        InvalidateRect( descr->self, &rect, FALSE );
     }
 }
 
@@ -442,7 +475,12 @@ static void LISTBOX_UpdateSize( HWND hwnd, LB_DESCR *descr )
 static LRESULT LISTBOX_GetItemRect( LB_DESCR *descr, INT index, RECT *rect )
 {
     /* Index <= 0 is legal even on empty listboxes */
-    if (index && (index >= descr->nb_items)) return -1;
+    if (index && (index >= descr->nb_items))
+    {
+        memset(rect, 0, sizeof(*rect));
+        SetLastError(ERROR_INVALID_INDEX);
+        return LB_ERR;
+    }
     SetRect( rect, 0, 0, descr->width, descr->height );
     if (descr->style & LBS_MULTICOLUMN)
     {
@@ -537,7 +575,7 @@ static INT LISTBOX_GetItemFromPoint( LB_DESCR *descr, INT x, INT y )
  *
  * Paint an item.
  */
-static void LISTBOX_PaintItem( HWND hwnd, LB_DESCR *descr, HDC hdc,
+static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc,
                                const RECT *rect, INT index, UINT action, BOOL ignoreFocus )
 {
     LB_ITEMDATA *item = NULL;
@@ -548,14 +586,13 @@ static void LISTBOX_PaintItem( HWND hwnd, LB_DESCR *descr, HDC hdc,
         DRAWITEMSTRUCT dis;
         RECT r;
         HRGN hrgn;
-        UINT id = GetWindowLongA( hwnd, GWL_ID );
 
        if (!item)
        {
            if (action == ODA_FOCUS)
                DrawFocusRect( hdc, rect );
            else
-//             FIXME("called with an out of bounds index %d(%d) in owner draw, Not good.\n",index,descr->nb_items);
+               FIXME("called with an out of bounds index %d(%d) in owner draw, Not good.\n",index,descr->nb_items);
            return;
        }
 
@@ -563,14 +600,14 @@ static void LISTBOX_PaintItem( HWND hwnd, LB_DESCR *descr, HDC hdc,
         drawing the item, *and* restore the previous region
         after they are done, so a region has better to exist
         else everything ends clipped */
-        GetClientRect(hwnd, &r);
+        GetClientRect(descr->self, &r);
         hrgn = CreateRectRgnIndirect(&r);
         SelectClipRgn( hdc, hrgn);
         DeleteObject( hrgn );
 
         dis.CtlType      = ODT_LISTBOX;
-        dis.CtlID        = id;
-        dis.hwndItem     = hwnd;
+        dis.CtlID        = GetWindowLongPtrW( descr->self, GWLP_ID );
+        dis.hwndItem     = descr->self;
         dis.itemAction   = action;
         dis.hDC          = hdc;
         dis.itemID       = index;
@@ -579,13 +616,13 @@ static void LISTBOX_PaintItem( HWND hwnd, LB_DESCR *descr, HDC hdc,
         if (!ignoreFocus && (descr->focus_item == index) &&
             (descr->caret_on) &&
             (descr->in_focus)) dis.itemState |= ODS_FOCUS;
-        if (!IsWindowEnabled(hwnd)) dis.itemState |= ODS_DISABLED;
+        if (!IsWindowEnabled(descr->self)) dis.itemState |= ODS_DISABLED;
         dis.itemData     = item ? item->data : 0;
         dis.rcItem       = *rect;
         TRACE("[%p]: drawitem %d (%s) action=%02x state=%02x rect=%ld,%ld-%ld,%ld\n",
-              hwnd, index, item ? debugstr_w(item->str) : "", action,
+              descr->self, index, item ? debugstr_w(item->str) : "", action,
               dis.itemState, rect->left, rect->top, rect->right, rect->bottom );
-        SendMessageW(descr->owner, WM_DRAWITEM, id, (LPARAM)&dis);
+        SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis);
     }
     else
     {
@@ -603,7 +640,7 @@ static void LISTBOX_PaintItem( HWND hwnd, LB_DESCR *descr, HDC hdc,
         }
 
         TRACE("[%p]: painting %d (%s) action=%02x rect=%ld,%ld-%ld,%ld\n",
-              hwnd, index, item ? debugstr_w(item->str) : "", action,
+              descr->self, index, item ? debugstr_w(item->str) : "", action,
               rect->left, rect->top, rect->right, rect->bottom );
         if (!item)
             ExtTextOutW( hdc, rect->left + 1, rect->top,
@@ -638,7 +675,7 @@ static void LISTBOX_PaintItem( HWND hwnd, LB_DESCR *descr, HDC hdc,
  *
  * Change the redraw flag.
  */
-static void LISTBOX_SetRedraw( HWND hwnd, LB_DESCR *descr, BOOL on )
+static void LISTBOX_SetRedraw( LB_DESCR *descr, BOOL on )
 {
     if (on)
     {
@@ -646,7 +683,7 @@ static void LISTBOX_SetRedraw( HWND hwnd, LB_DESCR *descr, BOOL on )
         descr->style &= ~LBS_NOREDRAW;
         if (descr->style & LBS_DISPLAYCHANGED)
         {     /* page was changed while setredraw false, refresh automatically */
-            InvalidateRect(hwnd, NULL, TRUE);
+            InvalidateRect(descr->self, NULL, TRUE);
             if ((descr->top_item + descr->page_size) > descr->nb_items)
             {      /* reset top of page if less than number of items/page */
                 descr->top_item = descr->nb_items - descr->page_size;
@@ -654,7 +691,7 @@ static void LISTBOX_SetRedraw( HWND hwnd, LB_DESCR *descr, BOOL on )
             }
             descr->style &= ~LBS_DISPLAYCHANGED;
         }
-        LISTBOX_UpdateScroll( hwnd, descr );
+        LISTBOX_UpdateScroll( descr );
     }
     else descr->style |= LBS_NOREDRAW;
 }
@@ -665,7 +702,7 @@ static void LISTBOX_SetRedraw( HWND hwnd, LB_DESCR *descr, BOOL on )
  *
  * Repaint a single item synchronously.
  */
-static void LISTBOX_RepaintItem( HWND hwnd, LB_DESCR *descr, INT index,
+static void LISTBOX_RepaintItem( LB_DESCR *descr, INT index,
                                  UINT action )
 {
     HDC hdc;
@@ -674,43 +711,50 @@ static void LISTBOX_RepaintItem( HWND hwnd, LB_DESCR *descr, INT index,
     HBRUSH hbrush, oldBrush = 0;
 
     /* Do not repaint the item if the item is not visible */
-    if (!IsWindowVisible(hwnd)) return;
+    if (!IsWindowVisible(descr->self)) return;
     if (descr->style & LBS_NOREDRAW)
     {
        descr->style |= LBS_DISPLAYCHANGED;
        return;
     }
     if (LISTBOX_GetItemRect( descr, index, &rect ) != 1) return;
-    if (!(hdc = GetDCEx( hwnd, 0, DCX_CACHE ))) return;
+    if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE ))) return;
     if (descr->font) oldFont = SelectObject( hdc, descr->font );
     hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
-                                  (WPARAM)hdc, (LPARAM)hwnd );
+                                  (WPARAM)hdc, (LPARAM)descr->self );
     if (hbrush) oldBrush = SelectObject( hdc, hbrush );
-    if (!IsWindowEnabled(hwnd))
+    if (!IsWindowEnabled(descr->self))
         SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
     SetWindowOrgEx( hdc, descr->horz_pos, 0, NULL );
-    LISTBOX_PaintItem( hwnd, descr, hdc, &rect, index, action, FALSE );
+    LISTBOX_PaintItem( descr, hdc, &rect, index, action, FALSE );
     if (oldFont) SelectObject( hdc, oldFont );
     if (oldBrush) SelectObject( hdc, oldBrush );
-    ReleaseDC( hwnd, hdc );
+    ReleaseDC( descr->self, hdc );
 }
 
 
 /***********************************************************************
  *           LISTBOX_InitStorage
  */
-static LRESULT LISTBOX_InitStorage( HWND hwnd, LB_DESCR *descr, INT nb_items )
+static LRESULT LISTBOX_InitStorage( LB_DESCR *descr, INT nb_items )
 {
     LB_ITEMDATA *item;
 
     nb_items += LB_ARRAY_GRANULARITY - 1;
     nb_items -= (nb_items % LB_ARRAY_GRANULARITY);
-    if (descr->items)
+    if (descr->items) {
         nb_items += HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(*item);
-    if (!(item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
-                              nb_items * sizeof(LB_ITEMDATA) )))
+       item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
+                              nb_items * sizeof(LB_ITEMDATA));
+    }
+    else {
+       item = HeapAlloc( GetProcessHeap(), 0,
+                              nb_items * sizeof(LB_ITEMDATA));
+    }
+
+    if (!item)
     {
-        SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
+        SEND_NOTIFICATION( descr, LBN_ERRSPACE );
         return LB_ERRSPACE;
     }
     descr->items = item;
@@ -721,20 +765,27 @@ static LRESULT LISTBOX_InitStorage( HWND hwnd, LB_DESCR *descr, INT nb_items )
 /***********************************************************************
  *           LISTBOX_SetTabStops
  */
-static BOOL LISTBOX_SetTabStops( HWND hwnd, LB_DESCR *descr, INT count,
+static BOOL LISTBOX_SetTabStops( LB_DESCR *descr, INT count,
                                    LPINT tabs, BOOL short_ints )
 {
-    if (!(descr->style & LBS_USETABSTOPS)) return TRUE;
-    if (descr->tabs) HeapFree( GetProcessHeap(), 0, descr->tabs );
+    INT i;
+
+    if (!(descr->style & LBS_USETABSTOPS))
+    {
+        SetLastError(ERROR_LB_WITHOUT_TABSTOPS);
+        return FALSE;
+    }
+
+    HeapFree( GetProcessHeap(), 0, descr->tabs );
     if (!(descr->nb_tabs = count))
     {
         descr->tabs = NULL;
         return TRUE;
     }
-    /* FIXME: count = 1 */
-    if (!(descr->tabs = (INT *)HeapAlloc( GetProcessHeap(), 0,
-                                            descr->nb_tabs * sizeof(INT) )))
+    if (!(descr->tabs = HeapAlloc( GetProcessHeap(), 0,
+                                   descr->nb_tabs * sizeof(INT) )))
         return FALSE;
+#ifndef __REACTOS__
     if (short_ints)
     {
         INT i;
@@ -748,7 +799,14 @@ static BOOL LISTBOX_SetTabStops( HWND hwnd, LB_DESCR *descr, INT count,
         if (TRACE_ON(listbox)) TRACE("\n");
     }
     else memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
-    /* FIXME: repaint the window? */
+#else
+    memcpy( descr->tabs, tabs, descr->nb_tabs * sizeof(INT) );
+#endif
+
+    /* convert into "dialog units"*/
+    for (i = 0; i < descr->nb_tabs; i++)
+        descr->tabs[i] = MulDiv(descr->tabs[i], descr->avg_char_width, 4);
+
     return TRUE;
 }
 
@@ -756,34 +814,53 @@ static BOOL LISTBOX_SetTabStops( HWND hwnd, LB_DESCR *descr, INT count,
 /***********************************************************************
  *           LISTBOX_GetText
  */
-static LRESULT LISTBOX_GetText( LB_DESCR *descr, INT index, LPARAM lParam, BOOL unicode )
+static LRESULT LISTBOX_GetText( LB_DESCR *descr, INT index, LPWSTR buffer, BOOL unicode )
 {
-    if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+    if ((index < 0) || (index >= descr->nb_items))
+    {
+        SetLastError(ERROR_INVALID_INDEX);
+        return LB_ERR;
+    }
     if (HAS_STRINGS(descr))
     {
-        if (!lParam)
-            return strlenW(descr->items[index].str);
+        if (!buffer)
+        {
+            DWORD len = strlenW(descr->items[index].str);
+            if( unicode )
+                return len;
+            return WideCharToMultiByte( CP_ACP, 0, descr->items[index].str, len,
+                                        NULL, 0, NULL, NULL );
+        }
 
        TRACE("index %d (0x%04x) %s\n", index, index, debugstr_w(descr->items[index].str));
 
         if(unicode)
         {
-            LPWSTR buffer = (LPWSTR)lParam;
             strcpyW( buffer, descr->items[index].str );
             return strlenW(buffer);
         }
         else
         {
-            LPSTR buffer = (LPSTR)lParam;
-            return WideCharToMultiByte(CP_ACP, 0, descr->items[index].str, -1, buffer, 0x7FFFFFFF, NULL, NULL) - 1;
+            return WideCharToMultiByte(CP_ACP, 0, descr->items[index].str, -1, (LPSTR)buffer, 0x7FFFFFFF, NULL, NULL) - 1;
         }
     } else {
-        if (lParam)
-            *((LPDWORD)lParam)=*(LPDWORD)(&descr->items[index].data);
+        if (buffer)
+            *((LPDWORD)buffer)=*(LPDWORD)(&descr->items[index].data);
         return sizeof(DWORD);
     }
 }
 
+static inline INT LISTBOX_lstrcmpiW( LCID lcid, LPCWSTR str1, LPCWSTR str2 )
+{
+    INT ret = CompareStringW( lcid, NORM_IGNORECASE, str1, -1, str2, -1 );
+    if (ret == CSTR_LESS_THAN)
+        return -1;
+    if (ret == CSTR_EQUAL)
+        return 0;
+    if (ret == CSTR_GREATER_THAN)
+        return 1;
+    return -1;
+}
 
 /***********************************************************************
  *           LISTBOX_FindStringPos
@@ -791,8 +868,7 @@ static LRESULT LISTBOX_GetText( LB_DESCR *descr, INT index, LPARAM lParam, BOOL
  * Find the nearest string located before a given string in sort order.
  * If 'exact' is TRUE, return an error if we don't get an exact match.
  */
-static INT LISTBOX_FindStringPos( HWND hwnd, LB_DESCR *descr, LPCWSTR str,
-                                    BOOL exact )
+static INT LISTBOX_FindStringPos( LB_DESCR *descr, LPCWSTR str, BOOL exact )
 {
     INT index, min, max, res = -1;
 
@@ -803,15 +879,15 @@ static INT LISTBOX_FindStringPos( HWND hwnd, LB_DESCR *descr, LPCWSTR str,
     {
         index = (min + max) / 2;
         if (HAS_STRINGS(descr))
-            res = lstrcmpiW( str, descr->items[index].str);
+            res = LISTBOX_lstrcmpiW( descr->locale, str, descr->items[index].str);
         else
         {
             COMPAREITEMSTRUCT cis;
-            UINT id = GetWindowLongA( hwnd, GWL_ID );
+            UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
 
             cis.CtlType    = ODT_LISTBOX;
             cis.CtlID      = id;
-            cis.hwndItem   = hwnd;
+            cis.hwndItem   = descr->self;
             /* note that some application (MetaStock) expects the second item
              * to be in the listbox */
             cis.itemID1    = -1;
@@ -828,19 +904,18 @@ static INT LISTBOX_FindStringPos( HWND hwnd, LB_DESCR *descr, LPCWSTR str,
     return exact ? -1 : max;
 }
 
-
 /***********************************************************************
  *           LISTBOX_FindFileStrPos
  *
  * Find the nearest string located before a given string in directory
  * sort order (i.e. first files, then directories, then drives).
  */
-static INT LISTBOX_FindFileStrPos( HWND hwnd, LB_DESCR *descr, LPCWSTR str )
+static INT LISTBOX_FindFileStrPos( LB_DESCR *descr, LPCWSTR str )
 {
     INT min, max, res = -1;
 
     if (!HAS_STRINGS(descr))
-        return LISTBOX_FindStringPos( hwnd, descr, str, FALSE );
+        return LISTBOX_FindStringPos( descr, str, FALSE );
     min = 0;
     max = descr->nb_items;
     while (min != max)
@@ -858,13 +933,13 @@ static INT LISTBOX_FindFileStrPos( HWND hwnd, LB_DESCR *descr, LPCWSTR str )
             else  /* directory */
             {
                 if (str[1] == '-') res = 1;
-                else res = lstrcmpiW( str, p );
+                else res = LISTBOX_lstrcmpiW( descr->locale, str, p );
             }
         }
         else  /* filename */
         {
             if (*str == '[') res = 1;
-            else res = lstrcmpiW( str, p );
+            else res = LISTBOX_lstrcmpiW( descr->locale, str, p );
         }
         if (!res) return index;
         if (res < 0) max = index;
@@ -879,8 +954,7 @@ static INT LISTBOX_FindFileStrPos( HWND hwnd, LB_DESCR *descr, LPCWSTR str )
  *
  * Find the item beginning with a given string.
  */
-static INT LISTBOX_FindString( HWND hwnd, LB_DESCR *descr, INT start,
-                                 LPCWSTR str, BOOL exact )
+static INT LISTBOX_FindString( LB_DESCR *descr, INT start, LPCWSTR str, BOOL exact )
 {
     INT i;
     LB_ITEMDATA *item;
@@ -893,9 +967,9 @@ static INT LISTBOX_FindString( HWND hwnd, LB_DESCR *descr, INT start,
         if (exact)
         {
             for (i = start + 1; i < descr->nb_items; i++, item++)
-                if (!lstrcmpiW( str, item->str )) return i;
+                if (!LISTBOX_lstrcmpiW( descr->locale, str, item->str )) return i;
             for (i = 0, item = descr->items; i <= start; i++, item++)
-                if (!lstrcmpiW( str, item->str )) return i;
+                if (!LISTBOX_lstrcmpiW( descr->locale, str, item->str )) return i;
         }
         else
         {
@@ -926,13 +1000,13 @@ static INT LISTBOX_FindString( HWND hwnd, LB_DESCR *descr, INT start,
     {
         if (exact && (descr->style & LBS_SORT))
             /* If sorted, use a WM_COMPAREITEM binary search */
-            return LISTBOX_FindStringPos( hwnd, descr, str, TRUE );
+            return LISTBOX_FindStringPos( descr, str, TRUE );
 
         /* Otherwise use a linear search */
         for (i = start + 1; i < descr->nb_items; i++, item++)
-            if (item->data == (DWORD)str) return i;
+            if (item->data == (ULONG_PTR)str) return i;
         for (i = 0, item = descr->items; i <= start; i++, item++)
-            if (item->data == (DWORD)str) return i;
+            if (item->data == (ULONG_PTR)str) return i;
     }
     return LB_ERR;
 }
@@ -946,22 +1020,42 @@ static LRESULT LISTBOX_GetSelCount( LB_DESCR *descr )
     INT i, count;
     LB_ITEMDATA *item = descr->items;
 
-    if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+    if (!(descr->style & LBS_MULTIPLESEL) ||
+        (descr->style & LBS_NOSEL))
+      return LB_ERR;
     for (i = count = 0; i < descr->nb_items; i++, item++)
         if (item->selected) count++;
     return count;
 }
 
+
+#ifndef __REACTOS__
+/***********************************************************************
+ *           LISTBOX_GetSelItems16
+ */
+static LRESULT LISTBOX_GetSelItems16( LB_DESCR *descr, INT16 max, LPINT16 array )
+{
+    INT i, count;
+    LB_ITEMDATA *item = descr->items;
+
+    if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
+    for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
+        if (item->selected) array[count++] = (INT16)i;
+    return count;
+}
+#endif
+
+
 /***********************************************************************
  *           LISTBOX_GetSelItems
  */
-static LRESULT LISTBOX_GetSelItems( LB_DESCR *descr, INT maxcount, LPINT array )
+static LRESULT LISTBOX_GetSelItems( LB_DESCR *descr, INT max, LPINT array )
 {
     INT i, count;
     LB_ITEMDATA *item = descr->items;
 
     if (!(descr->style & LBS_MULTIPLESEL)) return LB_ERR;
-    for (i = count = 0; (i < descr->nb_items) && (count < maxcount); i++, item++)
+    for (i = count = 0; (i < descr->nb_items) && (count < max); i++, item++)
         if (item->selected) array[count++] = i;
     return count;
 }
@@ -970,7 +1064,7 @@ static LRESULT LISTBOX_GetSelItems( LB_DESCR *descr, INT maxcount, LPINT array )
 /***********************************************************************
  *           LISTBOX_Paint
  */
-static LRESULT LISTBOX_Paint( HWND hwnd, LB_DESCR *descr, HDC hdc )
+static LRESULT LISTBOX_Paint( LB_DESCR *descr, HDC hdc )
 {
     INT i, col_pos = descr->page_size - 1;
     RECT rect;
@@ -991,16 +1085,18 @@ static LRESULT LISTBOX_Paint( HWND hwnd, LB_DESCR *descr, HDC hdc )
 
     if (descr->font) oldFont = SelectObject( hdc, descr->font );
     hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
-                                  (WPARAM)hdc, (LPARAM)hwnd );
+                                  (WPARAM)hdc, (LPARAM)descr->self );
     if (hbrush) oldBrush = SelectObject( hdc, hbrush );
-    if (!IsWindowEnabled(hwnd)) SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
+    if (!IsWindowEnabled(descr->self)) SetTextColor( hdc, GetSysColor( COLOR_GRAYTEXT ) );
 
     if (!descr->nb_items && (descr->focus_item != -1) && descr->caret_on &&
         (descr->in_focus))
     {
         /* Special case for empty listbox: paint focus rect */
         rect.bottom = rect.top + descr->item_height;
-        LISTBOX_PaintItem( hwnd, descr, hdc, &rect, descr->focus_item,
+        ExtTextOutW( hdc, 0, 0, ETO_OPAQUE | ETO_CLIPPED,
+                     &rect, NULL, 0, NULL );
+        LISTBOX_PaintItem( descr, hdc, &rect, descr->focus_item,
                            ODA_FOCUS, FALSE );
         rect.top = rect.bottom;
     }
@@ -1023,7 +1119,7 @@ static LRESULT LISTBOX_Paint( HWND hwnd, LB_DESCR *descr, HDC hdc )
            focusRect.top = rect.top;
            focusRect.bottom = rect.bottom;
         }
-        LISTBOX_PaintItem( hwnd, descr, hdc, &rect, i, ODA_DRAWENTIRE, TRUE );
+        LISTBOX_PaintItem( descr, hdc, &rect, i, ODA_DRAWENTIRE, TRUE );
         rect.top = rect.bottom;
 
         if ((descr->style & LBS_MULTICOLUMN) && !col_pos)
@@ -1053,8 +1149,9 @@ static LRESULT LISTBOX_Paint( HWND hwnd, LB_DESCR *descr, HDC hdc )
     }
 
     /* Paint the focus item now */
-    if (focusRect.top != focusRect.bottom && descr->caret_on)
-        LISTBOX_PaintItem( hwnd, descr, hdc, &focusRect, descr->focus_item, ODA_FOCUS, FALSE );
+    if (focusRect.top != focusRect.bottom &&
+        descr->caret_on && descr->in_focus)
+        LISTBOX_PaintItem( descr, hdc, &focusRect, descr->focus_item, ODA_FOCUS, FALSE );
 
     if (!IS_OWNERDRAW(descr))
     {
@@ -1087,7 +1184,7 @@ static LRESULT LISTBOX_Paint( HWND hwnd, LB_DESCR *descr, HDC hdc )
  * Invalidate all items from a given item. If the specified item is not
  * visible, nothing happens.
  */
-static void LISTBOX_InvalidateItems( HWND hwnd, LB_DESCR *descr, INT index )
+static void LISTBOX_InvalidateItems( LB_DESCR *descr, INT index )
 {
     RECT rect;
 
@@ -1099,18 +1196,25 @@ static void LISTBOX_InvalidateItems( HWND hwnd, LB_DESCR *descr, INT index )
             return;
         }
         rect.bottom = descr->height;
-        InvalidateRect( hwnd, &rect, TRUE );
+        InvalidateRect( descr->self, &rect, TRUE );
         if (descr->style & LBS_MULTICOLUMN)
         {
             /* Repaint the other columns */
             rect.left  = rect.right;
             rect.right = descr->width;
             rect.top   = 0;
-            InvalidateRect( hwnd, &rect, TRUE );
+            InvalidateRect( descr->self, &rect, TRUE );
         }
     }
 }
 
+static void LISTBOX_InvalidateItemRect( LB_DESCR *descr, INT index )
+{
+    RECT rect;
+
+    if (LISTBOX_GetItemRect( descr, index, &rect ) == 1)
+        InvalidateRect( descr->self, &rect, TRUE );
+}
 
 /***********************************************************************
  *           LISTBOX_GetItemHeight
@@ -1119,7 +1223,11 @@ static LRESULT LISTBOX_GetItemHeight( LB_DESCR *descr, INT index )
 {
     if (descr->style & LBS_OWNERDRAWVARIABLE)
     {
-        if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+        if ((index < 0) || (index >= descr->nb_items))
+        {
+            SetLastError(ERROR_INVALID_INDEX);
+            return LB_ERR;
+        }
         return descr->items[index].height;
     }
     else return descr->item_height;
@@ -1129,28 +1237,32 @@ static LRESULT LISTBOX_GetItemHeight( LB_DESCR *descr, INT index )
 /***********************************************************************
  *           LISTBOX_SetItemHeight
  */
-static LRESULT LISTBOX_SetItemHeight( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_SetItemHeight( LB_DESCR *descr, INT index,
                                       INT height, BOOL repaint )
 {
     if (!height) height = 1;
 
     if (descr->style & LBS_OWNERDRAWVARIABLE)
     {
-        if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
-        TRACE("[%p]: item %d height = %d\n", hwnd, index, height );
+        if ((index < 0) || (index >= descr->nb_items))
+        {
+            SetLastError(ERROR_INVALID_INDEX);
+            return LB_ERR;
+        }
+        TRACE("[%p]: item %d height = %d\n", descr->self, index, height );
         descr->items[index].height = height;
-        LISTBOX_UpdateScroll( hwnd, descr );
+        LISTBOX_UpdateScroll( descr );
        if (repaint)
-           LISTBOX_InvalidateItems( hwnd, descr, index );
+           LISTBOX_InvalidateItems( descr, index );
     }
     else if (height != descr->item_height)
     {
-        TRACE("[%p]: new height = %d\n", hwnd, height );
+        TRACE("[%p]: new height = %d\n", descr->self, height );
         descr->item_height = height;
-        LISTBOX_UpdatePage( hwnd, descr );
-        LISTBOX_UpdateScroll( hwnd, descr );
+        LISTBOX_UpdatePage( descr );
+        LISTBOX_UpdateScroll( descr );
        if (repaint)
-           InvalidateRect( hwnd, 0, TRUE );
+           InvalidateRect( descr->self, 0, TRUE );
     }
     return LB_OKAY;
 }
@@ -1159,7 +1271,7 @@ static LRESULT LISTBOX_SetItemHeight( HWND hwnd, LB_DESCR *descr, INT index,
 /***********************************************************************
  *           LISTBOX_SetHorizontalPos
  */
-static void LISTBOX_SetHorizontalPos( HWND hwnd, LB_DESCR *descr, INT pos )
+static void LISTBOX_SetHorizontalPos( LB_DESCR *descr, INT pos )
 {
     INT diff;
 
@@ -1167,33 +1279,39 @@ static void LISTBOX_SetHorizontalPos( HWND hwnd, LB_DESCR *descr, INT pos )
         pos = descr->horz_extent - descr->width;
     if (pos < 0) pos = 0;
     if (!(diff = descr->horz_pos - pos)) return;
-    TRACE("[%p]: new horz pos = %d\n", hwnd, pos );
+    TRACE("[%p]: new horz pos = %d\n", descr->self, pos );
     descr->horz_pos = pos;
-    LISTBOX_UpdateScroll( hwnd, descr );
+    LISTBOX_UpdateScroll( descr );
     if (abs(diff) < descr->width)
-        ScrollWindowEx( hwnd, diff, 0, NULL, NULL, 0, NULL,
+    {
+        RECT rect;
+        /* Invalidate the focused item so it will be repainted correctly */
+        if (LISTBOX_GetItemRect( descr, descr->focus_item, &rect ) == 1)
+            InvalidateRect( descr->self, &rect, TRUE );
+        ScrollWindowEx( descr->self, diff, 0, NULL, NULL, 0, NULL,
                           SW_INVALIDATE | SW_ERASE | SW_SCROLLCHILDREN );
+    }
     else
-        InvalidateRect( hwnd, NULL, TRUE );
+        InvalidateRect( descr->self, NULL, TRUE );
 }
 
 
 /***********************************************************************
  *           LISTBOX_SetHorizontalExtent
  */
-static LRESULT LISTBOX_SetHorizontalExtent( HWND hwnd, LB_DESCR *descr,
+static LRESULT LISTBOX_SetHorizontalExtent( LB_DESCR *descr,
                                             INT extent )
 {
     if (!descr->horz_extent || (descr->style & LBS_MULTICOLUMN))
         return LB_OKAY;
     if (extent <= 0) extent = 1;
     if (extent == descr->horz_extent) return LB_OKAY;
-    TRACE("[%p]: new horz extent = %d\n", hwnd, extent );
+    TRACE("[%p]: new horz extent = %d\n", descr->self, extent );
     descr->horz_extent = extent;
     if (descr->horz_pos > extent - descr->width)
-        LISTBOX_SetHorizontalPos( hwnd, descr, extent - descr->width );
+        LISTBOX_SetHorizontalPos( descr, extent - descr->width );
     else
-        LISTBOX_UpdateScroll( hwnd, descr );
+        LISTBOX_UpdateScroll( descr );
     return LB_OKAY;
 }
 
@@ -1201,12 +1319,12 @@ static LRESULT LISTBOX_SetHorizontalExtent( HWND hwnd, LB_DESCR *descr,
 /***********************************************************************
  *           LISTBOX_SetColumnWidth
  */
-static LRESULT LISTBOX_SetColumnWidth( HWND hwnd, LB_DESCR *descr, INT width)
+static LRESULT LISTBOX_SetColumnWidth( LB_DESCR *descr, INT width)
 {
     if (width == descr->column_width) return LB_OKAY;
-    TRACE("[%p]: new column width = %d\n", hwnd, width );
+    TRACE("[%p]: new column width = %d\n", descr->self, width );
     descr->column_width = width;
-    LISTBOX_UpdatePage( hwnd, descr );
+    LISTBOX_UpdatePage( descr );
     return LB_OKAY;
 }
 
@@ -1216,26 +1334,29 @@ static LRESULT LISTBOX_SetColumnWidth( HWND hwnd, LB_DESCR *descr, INT width)
  *
  * Returns the item height.
  */
-static INT LISTBOX_SetFont( HWND hwnd, LB_DESCR *descr, HFONT font )
+static INT LISTBOX_SetFont( LB_DESCR *descr, HFONT font )
 {
     HDC hdc;
     HFONT oldFont = 0;
-    TEXTMETRICW tm;
+    const char *alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+    SIZE sz;
 
     descr->font = font;
 
-    if (!(hdc = GetDCEx( hwnd, 0, DCX_CACHE )))
+    if (!(hdc = GetDCEx( descr->self, 0, DCX_CACHE )))
     {
         ERR("unable to get DC.\n" );
         return 16;
     }
     if (font) oldFont = SelectObject( hdc, font );
-    GetTextMetricsW( hdc, &tm );
+    GetTextExtentPointA( hdc, alphabet, 52, &sz);
     if (oldFont) SelectObject( hdc, oldFont );
-    ReleaseDC( hwnd, hdc );
+    ReleaseDC( descr->self, hdc );
+
+    descr->avg_char_width = (sz.cx / 26 + 1) / 2;
     if (!IS_OWNERDRAW(descr))
-        LISTBOX_SetItemHeight( hwnd, descr, 0, tm.tmHeight, FALSE );
-    return tm.tmHeight ;
+        LISTBOX_SetItemHeight( descr, 0, sz.cy, FALSE );
+    return sz.cy;
 }
 
 
@@ -1244,7 +1365,7 @@ static INT LISTBOX_SetFont( HWND hwnd, LB_DESCR *descr, HFONT font )
  *
  * Make sure that a given item is partially or fully visible.
  */
-static void LISTBOX_MakeItemVisible( HWND hwnd, LB_DESCR *descr, INT index,
+static void LISTBOX_MakeItemVisible( LB_DESCR *descr, INT index,
                                      BOOL fully )
 {
     INT top;
@@ -1272,7 +1393,7 @@ static void LISTBOX_MakeItemVisible( HWND hwnd, LB_DESCR *descr, INT index,
             (descr->height > (descr->page_size * descr->item_height))) return;
         top = index - descr->page_size + 1;
     }
-    LISTBOX_SetTopItem( hwnd, descr, top, TRUE );
+    LISTBOX_SetTopItem( descr, top, TRUE );
 }
 
 /***********************************************************************
@@ -1282,7 +1403,7 @@ static void LISTBOX_MakeItemVisible( HWND hwnd, LB_DESCR *descr, INT index,
  *   index must be between 0 and descr->nb_items-1, or LB_ERR is returned.
  *
  */
-static LRESULT LISTBOX_SetCaretIndex( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_SetCaretIndex( LB_DESCR *descr, INT index,
                                       BOOL fully_visible )
 {
     INT oldfocus = descr->focus_item;
@@ -1292,11 +1413,11 @@ static LRESULT LISTBOX_SetCaretIndex( HWND hwnd, LB_DESCR *descr, INT index,
     if (index == oldfocus) return LB_OKAY;
     descr->focus_item = index;
     if ((oldfocus != -1) && descr->caret_on && (descr->in_focus))
-        LISTBOX_RepaintItem( hwnd, descr, oldfocus, ODA_FOCUS );
+        LISTBOX_RepaintItem( descr, oldfocus, ODA_FOCUS );
 
-    LISTBOX_MakeItemVisible( hwnd, descr, index, fully_visible );
+    LISTBOX_MakeItemVisible( descr, index, fully_visible );
     if (descr->caret_on && (descr->in_focus))
-        LISTBOX_RepaintItem( hwnd, descr, index, ODA_FOCUS );
+        LISTBOX_RepaintItem( descr, index, ODA_FOCUS );
 
     return LB_OKAY;
 }
@@ -1307,7 +1428,7 @@ static LRESULT LISTBOX_SetCaretIndex( HWND hwnd, LB_DESCR *descr, INT index,
  *
  * Select a range of items. Should only be used on a MULTIPLESEL listbox.
  */
-static LRESULT LISTBOX_SelectItemRange( HWND hwnd, LB_DESCR *descr, INT first,
+static LRESULT LISTBOX_SelectItemRange( LB_DESCR *descr, INT first,
                                         INT last, BOOL on )
 {
     INT i;
@@ -1320,8 +1441,6 @@ static LRESULT LISTBOX_SelectItemRange( HWND hwnd, LB_DESCR *descr, INT first,
     if (last == -1) last = descr->nb_items - 1;
     if ((first < 0) || (first >= descr->nb_items)) return LB_ERR;
     if ((last < 0) || (last >= descr->nb_items)) return LB_ERR;
-    /* selected_item reflects last selected/unselected item on multiple sel */
-    descr->selected_item = last;
 
     if (on)  /* Turn selection on */
     {
@@ -1329,9 +1448,8 @@ static LRESULT LISTBOX_SelectItemRange( HWND hwnd, LB_DESCR *descr, INT first,
         {
             if (descr->items[i].selected) continue;
             descr->items[i].selected = TRUE;
-            LISTBOX_RepaintItem( hwnd, descr, i, ODA_SELECT );
+            LISTBOX_InvalidateItemRect(descr, i);
         }
-        LISTBOX_SetCaretIndex( hwnd, descr, last, TRUE );
     }
     else  /* Turn selection off */
     {
@@ -1339,7 +1457,7 @@ static LRESULT LISTBOX_SelectItemRange( HWND hwnd, LB_DESCR *descr, INT first,
         {
             if (!descr->items[i].selected) continue;
             descr->items[i].selected = FALSE;
-            LISTBOX_RepaintItem( hwnd, descr, i, ODA_SELECT );
+            LISTBOX_InvalidateItemRect(descr, i);
         }
     }
     return LB_OKAY;
@@ -1348,19 +1466,23 @@ static LRESULT LISTBOX_SelectItemRange( HWND hwnd, LB_DESCR *descr, INT first,
 /***********************************************************************
  *           LISTBOX_SetSelection
  */
-static LRESULT LISTBOX_SetSelection( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_SetSelection( LB_DESCR *descr, INT index,
                                      BOOL on, BOOL send_notify )
 {
     TRACE( "index=%d notify=%s\n", index, send_notify ? "YES" : "NO" );
 
-    if (descr->style & LBS_NOSEL) return LB_ERR;
+    if (descr->style & LBS_NOSEL)
+    {
+        descr->selected_item = index;
+        return LB_ERR;
+    }
     if ((index < -1) || (index >= descr->nb_items)) return LB_ERR;
     if (descr->style & LBS_MULTIPLESEL)
     {
         if (index == -1)  /* Select all items */
-            return LISTBOX_SelectItemRange( hwnd, descr, 0, -1, on );
+            return LISTBOX_SelectItemRange( descr, 0, -1, on );
         else  /* Only one item */
-            return LISTBOX_SelectItemRange( hwnd, descr, index, index, on );
+            return LISTBOX_SelectItemRange( descr, index, index, on );
     }
     else
     {
@@ -1369,9 +1491,9 @@ static LRESULT LISTBOX_SetSelection( HWND hwnd, LB_DESCR *descr, INT index,
         if (oldsel != -1) descr->items[oldsel].selected = FALSE;
         if (index != -1) descr->items[index].selected = TRUE;
         descr->selected_item = index;
-        if (oldsel != -1) LISTBOX_RepaintItem( hwnd, descr, oldsel, ODA_SELECT );
-        if (index != -1) LISTBOX_RepaintItem( hwnd, descr, index, ODA_SELECT );
-        if (send_notify && descr->nb_items) SEND_NOTIFICATION( hwnd, descr,
+        if (oldsel != -1) LISTBOX_RepaintItem( descr, oldsel, ODA_SELECT );
+        if (index != -1) LISTBOX_RepaintItem( descr, index, ODA_SELECT );
+        if (send_notify && descr->nb_items) SEND_NOTIFICATION( descr,
                                (index != -1) ? LBN_SELCHANGE : LBN_SELCANCEL );
        else
            if( descr->lphc ) /* set selection change flag for parent combo */
@@ -1386,7 +1508,7 @@ static LRESULT LISTBOX_SetSelection( HWND hwnd, LB_DESCR *descr, INT index,
  *
  * Change the caret position and extend the selection to the new caret.
  */
-static void LISTBOX_MoveCaret( HWND hwnd, LB_DESCR *descr, INT index,
+static void LISTBOX_MoveCaret( LB_DESCR *descr, INT index,
                                BOOL fully_visible )
 {
     INT oldfocus = descr->focus_item;
@@ -1404,7 +1526,7 @@ static void LISTBOX_MoveCaret( HWND hwnd, LB_DESCR *descr, INT index,
     /* 1. remove the focus and repaint the item */
     descr->focus_item = -1;
     if ((oldfocus != -1) && descr->caret_on && (descr->in_focus))
-        LISTBOX_RepaintItem( hwnd, descr, oldfocus, ODA_FOCUS );
+        LISTBOX_RepaintItem( descr, oldfocus, ODA_FOCUS );
 
     /* 2. then turn off the previous selection */
     /* 3. repaint the new selected item */
@@ -1415,66 +1537,54 @@ static void LISTBOX_MoveCaret( HWND hwnd, LB_DESCR *descr, INT index,
             INT first = min( index, descr->anchor_item );
             INT last  = max( index, descr->anchor_item );
             if (first > 0)
-                LISTBOX_SelectItemRange( hwnd, descr, 0, first - 1, FALSE );
-            LISTBOX_SelectItemRange( hwnd, descr, last + 1, -1, FALSE );
-            LISTBOX_SelectItemRange( hwnd, descr, first, last, TRUE );
+                LISTBOX_SelectItemRange( descr, 0, first - 1, FALSE );
+            LISTBOX_SelectItemRange( descr, last + 1, -1, FALSE );
+            LISTBOX_SelectItemRange( descr, first, last, TRUE );
         }
     }
     else if (!(descr->style & LBS_MULTIPLESEL))
     {
         /* Set selection to new caret item */
-        LISTBOX_SetSelection( hwnd, descr, index, TRUE, FALSE );
+        LISTBOX_SetSelection( descr, index, TRUE, FALSE );
     }
 
     /* 4. repaint the new item with the focus */
     descr->focus_item = index;
-    LISTBOX_MakeItemVisible( hwnd, descr, index, fully_visible );
+    LISTBOX_MakeItemVisible( descr, index, fully_visible );
     if (descr->caret_on && (descr->in_focus))
-        LISTBOX_RepaintItem( hwnd, descr, index, ODA_FOCUS );
+        LISTBOX_RepaintItem( descr, index, ODA_FOCUS );
 }
 
 
 /***********************************************************************
  *           LISTBOX_InsertItem
  */
-static LRESULT LISTBOX_InsertItem( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_InsertItem( LB_DESCR *descr, INT index,
                                    LPWSTR str, DWORD data )
 {
     LB_ITEMDATA *item;
     INT max_items;
     INT oldfocus = descr->focus_item;
 
-    if (index == -1) 
-               index = descr->nb_items;
-    else if ((index < 0) || (index > descr->nb_items)) 
-               return LB_ERR;
-
-    if (!descr->items) 
-               max_items = 0;
-    else 
-               max_items = HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(*item);
-
+    if (index == -1) index = descr->nb_items;
+    else if ((index < 0) || (index > descr->nb_items)) return LB_ERR;
+    if (!descr->items) max_items = 0;
+    else max_items = HeapSize( GetProcessHeap(), 0, descr->items ) / sizeof(*item);
     if (descr->nb_items == max_items)
     {
         /* We need to grow the array */
         max_items += LB_ARRAY_GRANULARITY;
-       
-               /* In WINE it seems to be possible to use HeapReAlloc for allocating new blocks
-               of memory. This doesn't work in Windows */
-
-               if (descr->items&&!(item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
-                                  max_items * sizeof(LB_ITEMDATA) )))
-        {
-            SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
-            return LB_ERRSPACE;
-        }
-               else if((!descr->items)&&!(item = HeapAlloc( GetProcessHeap(), 0,
-                                  max_items * sizeof(LB_ITEMDATA) )))
+       if (descr->items)
+           item = HeapReAlloc( GetProcessHeap(), 0, descr->items,
+                                  max_items * sizeof(LB_ITEMDATA) );
+       else
+           item = HeapAlloc( GetProcessHeap(), 0,
+                                  max_items * sizeof(LB_ITEMDATA) );
+        if (!item)
         {
-            SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
+            SEND_NOTIFICATION( descr, LBN_ERRSPACE );
             return LB_ERRSPACE;
         }
-
         descr->items = item;
     }
 
@@ -1495,7 +1605,7 @@ static LRESULT LISTBOX_InsertItem( HWND hwnd, LB_DESCR *descr, INT index,
     if (descr->style & LBS_OWNERDRAWVARIABLE)
     {
         MEASUREITEMSTRUCT mis;
-        UINT id = GetWindowLongA( hwnd, GWL_ID );
+        UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
 
         mis.CtlType    = ODT_LISTBOX;
         mis.CtlID      = id;
@@ -1505,23 +1615,23 @@ static LRESULT LISTBOX_InsertItem( HWND hwnd, LB_DESCR *descr, INT index,
         SendMessageW( descr->owner, WM_MEASUREITEM, id, (LPARAM)&mis );
         item->height = mis.itemHeight ? mis.itemHeight : 1;
         TRACE("[%p]: measure item %d (%s) = %d\n",
-              hwnd, index, str ? debugstr_w(str) : "", item->height );
+              descr->self, index, str ? debugstr_w(str) : "", item->height );
     }
 
     /* Repaint the items */
 
-    LISTBOX_UpdateScroll( hwnd, descr );
-    LISTBOX_InvalidateItems( hwnd, descr, index );
+    LISTBOX_UpdateScroll( descr );
+    LISTBOX_InvalidateItems( descr, index );
 
     /* Move selection and focused item */
     /* If listbox was empty, set focus to the first item */
     if (descr->nb_items == 1)
-         LISTBOX_SetCaretIndex( hwnd, descr, 0, FALSE );
+         LISTBOX_SetCaretIndex( descr, 0, FALSE );
     /* single select don't change selection index in win31 */
     else if ((ISWIN31) && !(IS_MULTISELECT(descr)))
     {
         descr->selected_item++;
-        LISTBOX_SetSelection( hwnd, descr, descr->selected_item-1, TRUE, FALSE );
+        LISTBOX_SetSelection( descr, descr->selected_item-1, TRUE, FALSE );
     }
     else
     {
@@ -1538,7 +1648,7 @@ static LRESULT LISTBOX_InsertItem( HWND hwnd, LB_DESCR *descr, INT index,
 /***********************************************************************
  *           LISTBOX_InsertString
  */
-static LRESULT LISTBOX_InsertString( HWND hwnd, LB_DESCR *descr, INT index,
+static LRESULT LISTBOX_InsertString( LB_DESCR *descr, INT index,
                                      LPCWSTR str )
 {
     LPWSTR new_str = NULL;
@@ -1551,7 +1661,7 @@ static LRESULT LISTBOX_InsertString( HWND hwnd, LB_DESCR *descr, INT index,
         if (!str) str = empty_stringW;
         if (!(new_str = HeapAlloc( GetProcessHeap(), 0, (strlenW(str) + 1) * sizeof(WCHAR) )))
         {
-            SEND_NOTIFICATION( hwnd, descr, LBN_ERRSPACE );
+            SEND_NOTIFICATION( descr, LBN_ERRSPACE );
             return LB_ERRSPACE;
         }
         strcpyW(new_str, str);
@@ -1559,14 +1669,14 @@ static LRESULT LISTBOX_InsertString( HWND hwnd, LB_DESCR *descr, INT index,
     else data = (DWORD)str;
 
     if (index == -1) index = descr->nb_items;
-    if ((ret = LISTBOX_InsertItem( hwnd, descr, index, new_str, data )) != 0)
+    if ((ret = LISTBOX_InsertItem( descr, index, new_str, data )) != 0)
     {
-        if (new_str) HeapFree( GetProcessHeap(), 0, new_str );
+        HeapFree( GetProcessHeap(), 0, new_str );
         return ret;
     }
 
     TRACE("[%p]: added item %d %s\n",
-          hwnd, index, HAS_STRINGS(descr) ? debugstr_w(new_str) : "" );
+          descr->self, index, HAS_STRINGS(descr) ? debugstr_w(new_str) : "" );
     return index;
 }
 
@@ -1576,7 +1686,7 @@ static LRESULT LISTBOX_InsertString( HWND hwnd, LB_DESCR *descr, INT index,
  *
  * Delete the content of an item. 'index' must be a valid index.
  */
-static void LISTBOX_DeleteItem( HWND hwnd, LB_DESCR *descr, INT index )
+static void LISTBOX_DeleteItem( LB_DESCR *descr, INT index )
 {
     /* Note: Win 3.1 only sends DELETEITEM on owner-draw items,
      *       while Win95 sends it for all items with user data.
@@ -1586,12 +1696,12 @@ static void LISTBOX_DeleteItem( HWND hwnd, LB_DESCR *descr, INT index )
     if (IS_OWNERDRAW(descr) || descr->items[index].data)
     {
         DELETEITEMSTRUCT dis;
-        UINT id = GetWindowLongA( hwnd, GWL_ID );
+        UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
 
         dis.CtlType  = ODT_LISTBOX;
         dis.CtlID    = id;
         dis.itemID   = index;
-        dis.hwndItem = hwnd;
+        dis.hwndItem = descr->self;
         dis.itemData = descr->items[index].data;
         SendMessageW( descr->owner, WM_DELETEITEM, id, (LPARAM)&dis );
     }
@@ -1605,18 +1715,17 @@ static void LISTBOX_DeleteItem( HWND hwnd, LB_DESCR *descr, INT index )
  *
  * Remove an item from the listbox and delete its content.
  */
-static LRESULT LISTBOX_RemoveItem( HWND hwnd, LB_DESCR *descr, INT index )
+static LRESULT LISTBOX_RemoveItem( LB_DESCR *descr, INT index )
 {
     LB_ITEMDATA *item;
     INT max_items;
 
-    if ((index == -1) && (descr->nb_items > 0)) index = descr->nb_items - 1;
-    else if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
+    if ((index < 0) || (index >= descr->nb_items)) return LB_ERR;
 
     /* We need to invalidate the original rect instead of the updated one. */
-    LISTBOX_InvalidateItems( hwnd, descr, index );
+    LISTBOX_InvalidateItems( descr, index );
 
-    LISTBOX_DeleteItem( hwnd, descr, index );
+    LISTBOX_DeleteItem( descr, index );
 
     /* Remove the item */
 
@@ -1639,11 +1748,11 @@ static LRESULT LISTBOX_RemoveItem( HWND hwnd, LB_DESCR *descr, INT index )
     }
     /* Repaint the items */
 
-    LISTBOX_UpdateScroll( hwnd, descr );
+    LISTBOX_UpdateScroll( descr );
     /* if we removed the scrollbar, reset the top of the list
       (correct for owner-drawn ???) */
     if (descr->nb_items == descr->page_size)
-        LISTBOX_SetTopItem( hwnd, descr, 0, TRUE );
+        LISTBOX_SetTopItem( descr, 0, TRUE );
 
     /* Move selection and focused item */
     if (!IS_MULTISELECT(descr))
@@ -1654,7 +1763,7 @@ static LRESULT LISTBOX_RemoveItem( HWND hwnd, LB_DESCR *descr, INT index )
     {
             descr->selected_item--;
             if (ISWIN31) /* win 31 do not change the selected item number */
-               LISTBOX_SetSelection( hwnd, descr, descr->selected_item + 1, TRUE, FALSE);
+               LISTBOX_SetSelection( descr, descr->selected_item + 1, TRUE, FALSE);
     }
     }
 
@@ -1670,12 +1779,12 @@ static LRESULT LISTBOX_RemoveItem( HWND hwnd, LB_DESCR *descr, INT index )
 /***********************************************************************
  *           LISTBOX_ResetContent
  */
-static void LISTBOX_ResetContent( HWND hwnd, LB_DESCR *descr )
+static void LISTBOX_ResetContent( LB_DESCR *descr )
 {
     INT i;
 
-    for (i = 0; i < descr->nb_items; i++) LISTBOX_DeleteItem( hwnd, descr, i );
-    if (descr->items) HeapFree( GetProcessHeap(), 0, descr->items );
+    for (i = 0; i < descr->nb_items; i++) LISTBOX_DeleteItem( descr, i );
+    HeapFree( GetProcessHeap(), 0, descr->items );
     descr->nb_items      = 0;
     descr->top_item      = 0;
     descr->selected_item = -1;
@@ -1688,22 +1797,27 @@ static void LISTBOX_ResetContent( HWND hwnd, LB_DESCR *descr )
 /***********************************************************************
  *           LISTBOX_SetCount
  */
-static LRESULT LISTBOX_SetCount( HWND hwnd, LB_DESCR *descr, INT count )
+static LRESULT LISTBOX_SetCount( LB_DESCR *descr, INT count )
 {
     LRESULT ret;
 
-    if (HAS_STRINGS(descr)) return LB_ERR;
+    if (HAS_STRINGS(descr))
+    {
+        SetLastError(ERROR_SETCOUNT_ON_BAD_LB);
+        return LB_ERR;
+    }
+
     /* FIXME: this is far from optimal... */
     if (count > descr->nb_items)
     {
         while (count > descr->nb_items)
-            if ((ret = LISTBOX_InsertString( hwnd, descr, -1, 0 )) < 0)
+            if ((ret = LISTBOX_InsertString( descr, -1, 0 )) < 0)
                 return ret;
     }
     else if (count < descr->nb_items)
     {
         while (count < descr->nb_items)
-            if ((ret = LISTBOX_RemoveItem( hwnd, descr, -1 )) < 0)
+            if ((ret = LISTBOX_RemoveItem( descr, -1 )) < 0)
                 return ret;
     }
     return LB_OKAY;
@@ -1713,7 +1827,7 @@ static LRESULT LISTBOX_SetCount( HWND hwnd, LB_DESCR *descr, INT count )
 /***********************************************************************
  *           LISTBOX_Directory
  */
-static LRESULT LISTBOX_Directory( HWND hwnd, LB_DESCR *descr, UINT attrib,
+static LRESULT LISTBOX_Directory( LB_DESCR *descr, UINT attrib,
                                   LPCWSTR filespec, BOOL long_names )
 {
     HANDLE handle;
@@ -1739,10 +1853,12 @@ static LRESULT LISTBOX_Directory( HWND hwnd, LB_DESCR *descr, UINT attrib,
                     static const WCHAR bracketW[]  = { ']',0 };
                     static const WCHAR dotW[] = { '.',0 };
                     if (!(attrib & DDL_DIRECTORY) ||
-                        !strcmpW( entry.cAlternateFileName, dotW )) continue;
+                        !strcmpW( entry.cFileName, dotW )) continue;
                     buffer[0] = '[';
-                    if (long_names) strcpyW( buffer + 1, entry.cFileName );
-                    else strcpyW( buffer + 1, entry.cAlternateFileName );
+                    if (!long_names && entry.cAlternateFileName[0])
+                        strcpyW( buffer + 1, entry.cAlternateFileName );
+                    else
+                        strcpyW( buffer + 1, entry.cFileName );
                     strcatW(buffer, bracketW);
                 }
                 else  /* not a directory */
@@ -1754,12 +1870,14 @@ static LRESULT LISTBOX_Directory( HWND hwnd, LB_DESCR *descr, UINT attrib,
                         ((attrib & ATTRIBS) != (entry.dwFileAttributes & ATTRIBS)))
                         continue;
 #undef ATTRIBS
-                    if (long_names) strcpyW( buffer, entry.cFileName );
-                    else strcpyW( buffer, entry.cAlternateFileName );
+                    if (!long_names && entry.cAlternateFileName[0])
+                        strcpyW( buffer, entry.cAlternateFileName );
+                    else
+                        strcpyW( buffer, entry.cFileName );
                 }
                 if (!long_names) CharLowerW( buffer );
-                pos = LISTBOX_FindFileStrPos( hwnd, descr, buffer );
-                if ((ret = LISTBOX_InsertString( hwnd, descr, pos, buffer )) < 0)
+                pos = LISTBOX_FindFileStrPos( descr, buffer );
+                if ((ret = LISTBOX_InsertString( descr, pos, buffer )) < 0)
                     break;
             } while (FindNextFileW( handle, &entry ));
             FindClose( handle );
@@ -1775,7 +1893,7 @@ static LRESULT LISTBOX_Directory( HWND hwnd, LB_DESCR *descr, UINT attrib,
         for (drive = 0; drive < 26; drive++, buffer[2]++, root[0]++)
         {
             if (GetDriveTypeW(root) <= DRIVE_NO_ROOT_DIR) continue;
-            if ((ret = LISTBOX_InsertString( hwnd, descr, -1, buffer )) < 0)
+            if ((ret = LISTBOX_InsertString( descr, -1, buffer )) < 0)
                 break;
         }
     }
@@ -1786,41 +1904,41 @@ static LRESULT LISTBOX_Directory( HWND hwnd, LB_DESCR *descr, UINT attrib,
 /***********************************************************************
  *           LISTBOX_HandleVScroll
  */
-static LRESULT LISTBOX_HandleVScroll( HWND hwnd, LB_DESCR *descr, WPARAM wParam )
+static LRESULT LISTBOX_HandleVScroll( LB_DESCR *descr, WORD scrollReq, WORD pos )
 {
     SCROLLINFO info;
 
     if (descr->style & LBS_MULTICOLUMN) return 0;
-    switch(LOWORD(wParam))
+    switch(scrollReq)
     {
     case SB_LINEUP:
-        LISTBOX_SetTopItem( hwnd, descr, descr->top_item - 1, TRUE );
+        LISTBOX_SetTopItem( descr, descr->top_item - 1, TRUE );
         break;
     case SB_LINEDOWN:
-        LISTBOX_SetTopItem( hwnd, descr, descr->top_item + 1, TRUE );
+        LISTBOX_SetTopItem( descr, descr->top_item + 1, TRUE );
         break;
     case SB_PAGEUP:
-        LISTBOX_SetTopItem( hwnd, descr, descr->top_item -
+        LISTBOX_SetTopItem( descr, descr->top_item -
                             LISTBOX_GetCurrentPageSize( descr ), TRUE );
         break;
     case SB_PAGEDOWN:
-        LISTBOX_SetTopItem( hwnd, descr, descr->top_item +
+        LISTBOX_SetTopItem( descr, descr->top_item +
                             LISTBOX_GetCurrentPageSize( descr ), TRUE );
         break;
     case SB_THUMBPOSITION:
-        LISTBOX_SetTopItem( hwnd, descr, HIWORD(wParam), TRUE );
+        LISTBOX_SetTopItem( descr, pos, TRUE );
         break;
     case SB_THUMBTRACK:
         info.cbSize = sizeof(info);
         info.fMask = SIF_TRACKPOS;
-        GetScrollInfo( hwnd, SB_VERT, &info );
-        LISTBOX_SetTopItem( hwnd, descr, info.nTrackPos, TRUE );
+        GetScrollInfo( descr->self, SB_VERT, &info );
+        LISTBOX_SetTopItem( descr, info.nTrackPos, TRUE );
         break;
     case SB_TOP:
-        LISTBOX_SetTopItem( hwnd, descr, 0, TRUE );
+        LISTBOX_SetTopItem( descr, 0, TRUE );
         break;
     case SB_BOTTOM:
-        LISTBOX_SetTopItem( hwnd, descr, descr->nb_items, TRUE );
+        LISTBOX_SetTopItem( descr, descr->nb_items, TRUE );
         break;
     }
     return 0;
@@ -1830,86 +1948,86 @@ static LRESULT LISTBOX_HandleVScroll( HWND hwnd, LB_DESCR *descr, WPARAM wParam
 /***********************************************************************
  *           LISTBOX_HandleHScroll
  */
-static LRESULT LISTBOX_HandleHScroll( HWND hwnd, LB_DESCR *descr, WPARAM wParam )
+static LRESULT LISTBOX_HandleHScroll( LB_DESCR *descr, WORD scrollReq, WORD pos )
 {
     SCROLLINFO info;
     INT page;
 
     if (descr->style & LBS_MULTICOLUMN)
     {
-        switch(LOWORD(wParam))
+        switch(scrollReq)
         {
         case SB_LINELEFT:
-            LISTBOX_SetTopItem( hwnd, descr, descr->top_item-descr->page_size,
+            LISTBOX_SetTopItem( descr, descr->top_item-descr->page_size,
                                 TRUE );
             break;
         case SB_LINERIGHT:
-            LISTBOX_SetTopItem( hwnd, descr, descr->top_item+descr->page_size,
+            LISTBOX_SetTopItem( descr, descr->top_item+descr->page_size,
                                 TRUE );
             break;
         case SB_PAGELEFT:
             page = descr->width / descr->column_width;
             if (page < 1) page = 1;
-            LISTBOX_SetTopItem( hwnd, descr,
+            LISTBOX_SetTopItem( descr,
                              descr->top_item - page * descr->page_size, TRUE );
             break;
         case SB_PAGERIGHT:
             page = descr->width / descr->column_width;
             if (page < 1) page = 1;
-            LISTBOX_SetTopItem( hwnd, descr,
+            LISTBOX_SetTopItem( descr,
                              descr->top_item + page * descr->page_size, TRUE );
             break;
         case SB_THUMBPOSITION:
-            LISTBOX_SetTopItem( hwnd, descr, HIWORD(wParam)*descr->page_size,
+            LISTBOX_SetTopItem( descr, pos*descr->page_size,
                                 TRUE );
             break;
         case SB_THUMBTRACK:
             info.cbSize = sizeof(info);
             info.fMask  = SIF_TRACKPOS;
-            GetScrollInfo( hwnd, SB_VERT, &info );
-            LISTBOX_SetTopItem( hwnd, descr, info.nTrackPos*descr->page_size,
+            GetScrollInfo( descr->self, SB_VERT, &info );
+            LISTBOX_SetTopItem( descr, info.nTrackPos*descr->page_size,
                                 TRUE );
             break;
         case SB_LEFT:
-            LISTBOX_SetTopItem( hwnd, descr, 0, TRUE );
+            LISTBOX_SetTopItem( descr, 0, TRUE );
             break;
         case SB_RIGHT:
-            LISTBOX_SetTopItem( hwnd, descr, descr->nb_items, TRUE );
+            LISTBOX_SetTopItem( descr, descr->nb_items, TRUE );
             break;
         }
     }
     else if (descr->horz_extent)
     {
-        switch(LOWORD(wParam))
+        switch(scrollReq)
         {
         case SB_LINELEFT:
-            LISTBOX_SetHorizontalPos( hwnd, descr, descr->horz_pos - 1 );
+            LISTBOX_SetHorizontalPos( descr, descr->horz_pos - 1 );
             break;
         case SB_LINERIGHT:
-            LISTBOX_SetHorizontalPos( hwnd, descr, descr->horz_pos + 1 );
+            LISTBOX_SetHorizontalPos( descr, descr->horz_pos + 1 );
             break;
         case SB_PAGELEFT:
-            LISTBOX_SetHorizontalPos( hwnd, descr,
+            LISTBOX_SetHorizontalPos( descr,
                                       descr->horz_pos - descr->width );
             break;
         case SB_PAGERIGHT:
-            LISTBOX_SetHorizontalPos( hwnd, descr,
+            LISTBOX_SetHorizontalPos( descr,
                                       descr->horz_pos + descr->width );
             break;
         case SB_THUMBPOSITION:
-            LISTBOX_SetHorizontalPos( hwnd, descr, HIWORD(wParam) );
+            LISTBOX_SetHorizontalPos( descr, pos );
             break;
         case SB_THUMBTRACK:
             info.cbSize = sizeof(info);
             info.fMask = SIF_TRACKPOS;
-            GetScrollInfo( hwnd, SB_HORZ, &info );
-            LISTBOX_SetHorizontalPos( hwnd, descr, info.nTrackPos );
+            GetScrollInfo( descr->self, SB_HORZ, &info );
+            LISTBOX_SetHorizontalPos( descr, info.nTrackPos );
             break;
         case SB_LEFT:
-            LISTBOX_SetHorizontalPos( hwnd, descr, 0 );
+            LISTBOX_SetHorizontalPos( descr, 0 );
             break;
         case SB_RIGHT:
-            LISTBOX_SetHorizontalPos( hwnd, descr,
+            LISTBOX_SetHorizontalPos( descr,
                                       descr->horz_extent - descr->width );
             break;
         }
@@ -1917,22 +2035,20 @@ static LRESULT LISTBOX_HandleHScroll( HWND hwnd, LB_DESCR *descr, WPARAM wParam
     return 0;
 }
 
-static LRESULT LISTBOX_HandleMouseWheel(HWND hwnd, LB_DESCR *descr, WPARAM wParam )
+static LRESULT LISTBOX_HandleMouseWheel(LB_DESCR *descr, SHORT delta )
 {
     short gcWheelDelta = 0;
     UINT pulScrollLines = 3;
-    
-#if 0
+
     SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
-#endif 
 
-    gcWheelDelta -= (short) HIWORD(wParam);
+    gcWheelDelta -= delta;
 
     if (abs(gcWheelDelta) >= WHEEL_DELTA && pulScrollLines)
     {
         int cLineScroll = (int) min((UINT) descr->page_size, pulScrollLines);
         cLineScroll *= (gcWheelDelta / WHEEL_DELTA);
-        LISTBOX_SetTopItem( hwnd, descr, descr->top_item + cLineScroll, TRUE );
+        LISTBOX_SetTopItem( descr, descr->top_item + cLineScroll, TRUE );
     }
     return 0;
 }
@@ -1940,64 +2056,79 @@ static LRESULT LISTBOX_HandleMouseWheel(HWND hwnd, LB_DESCR *descr, WPARAM wPara
 /***********************************************************************
  *           LISTBOX_HandleLButtonDown
  */
-static LRESULT LISTBOX_HandleLButtonDown( HWND hwnd, LB_DESCR *descr,
-                                          WPARAM wParam, INT x, INT y )
+static LRESULT LISTBOX_HandleLButtonDown( LB_DESCR *descr,
+                                          DWORD keys, INT x, INT y )
 {
     INT index = LISTBOX_GetItemFromPoint( descr, x, y );
-    TRACE("[%p]: lbuttondown %d,%d item %d\n", hwnd, x, y, index );
+    TRACE("[%p]: lbuttondown %d,%d item %d\n", descr->self, x, y, index );
     if (!descr->caret_on && (descr->in_focus)) return 0;
 
     if (!descr->in_focus)
     {
-        if( !descr->lphc ) SetFocus( hwnd );
+        if( !descr->lphc ) SetFocus( descr->self );
         else SetFocus( (descr->lphc->hWndEdit) ? descr->lphc->hWndEdit : descr->lphc->self );
     }
 
     if (index == -1) return 0;
 
-    if (descr->style & LBS_EXTENDEDSEL)
+    if (descr->style & (LBS_EXTENDEDSEL | LBS_MULTIPLESEL))
     {
         /* we should perhaps make sure that all items are deselected
            FIXME: needed for !LBS_EXTENDEDSEL, too ?
-           if (!(wParam & (MK_SHIFT|MK_CONTROL)))
-           LISTBOX_SetSelection( hwnd, descr, -1, FALSE, FALSE);
+           if (!(keys & (MK_SHIFT|MK_CONTROL)))
+           LISTBOX_SetSelection( descr, -1, FALSE, FALSE);
         */
 
-        if (!(wParam & MK_SHIFT)) descr->anchor_item = index;
-        if (wParam & MK_CONTROL)
+        if (!(keys & MK_SHIFT)) descr->anchor_item = index;
+        if (keys & MK_CONTROL)
         {
-            LISTBOX_SetCaretIndex( hwnd, descr, index, FALSE );
-            LISTBOX_SetSelection( hwnd, descr, index,
+            LISTBOX_SetCaretIndex( descr, index, FALSE );
+            LISTBOX_SetSelection( descr, index,
                                   !descr->items[index].selected,
                                   (descr->style & LBS_NOTIFY) != 0);
         }
-        else LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
+        else
+        {
+            LISTBOX_MoveCaret( descr, index, FALSE );
+
+            if (descr->style & LBS_EXTENDEDSEL)
+            {
+                LISTBOX_SetSelection( descr, index,
+                               descr->items[index].selected,
+                              (descr->style & LBS_NOTIFY) != 0 );
+            }
+            else
+            {
+                LISTBOX_SetSelection( descr, index,
+                               !descr->items[index].selected,
+                              (descr->style & LBS_NOTIFY) != 0 );
+            }
+        }
     }
     else
     {
-        LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
-        LISTBOX_SetSelection( hwnd, descr, index,
-                              (!(descr->style & LBS_MULTIPLESEL) ||
-                               !descr->items[index].selected),
-                              (descr->style & LBS_NOTIFY) != 0 );
+        descr->anchor_item = index;
+        LISTBOX_MoveCaret( descr, index, FALSE );
+        LISTBOX_SetSelection( descr, index,
+                              TRUE, (descr->style & LBS_NOTIFY) != 0 );
     }
 
     descr->captured = TRUE;
-    SetCapture( hwnd );
+    SetCapture( descr->self );
 
     if (!descr->lphc)
     {
         if (descr->style & LBS_NOTIFY )
             SendMessageW( descr->owner, WM_LBTRACKPOINT, index,
                             MAKELPARAM( x, y ) );
-        if (GetWindowLongA( hwnd, GWL_EXSTYLE ) & WS_EX_DRAGDETECT)
+        if (GetWindowLongW( descr->self, GWL_EXSTYLE ) & WS_EX_DRAGDETECT)
         {
             POINT pt;
 
            pt.x = x;
            pt.y = y;
 
-            if (DragDetect( hwnd, pt ))
+            if (DragDetect( descr->self, pt ))
                 SendMessageW( descr->owner, WM_BEGINDRAG, 0, 0 );
         }
     }
@@ -2024,8 +2155,8 @@ nn * PARAMS
  *  This function is only to be used when a ListBox is a ComboListBox
  */
 
-static LRESULT LISTBOX_HandleLButtonDownCombo( HWND hwnd, LB_DESCR *pDescr,
-                                               UINT msg, WPARAM wParam, INT x, INT y)
+static LRESULT LISTBOX_HandleLButtonDownCombo( LB_DESCR *pDescr,
+                                               UINT msg, DWORD keys, INT x, INT y)
 {
     RECT clientRect, screenRect;
     POINT mousePos;
@@ -2033,7 +2164,7 @@ static LRESULT LISTBOX_HandleLButtonDownCombo( HWND hwnd, LB_DESCR *pDescr,
     mousePos.x = x;
     mousePos.y = y;
 
-    GetClientRect(hwnd, &clientRect);
+    GetClientRect(pDescr->self, &clientRect);
 
     if(PtInRect(&clientRect, mousePos))
     {
@@ -2041,11 +2172,10 @@ static LRESULT LISTBOX_HandleLButtonDownCombo( HWND hwnd, LB_DESCR *pDescr,
         if (msg == WM_LBUTTONDOWN)
         {
            pDescr->lphc->droppedIndex = pDescr->nb_items ? pDescr->selected_item : -1;
-           return LISTBOX_HandleLButtonDown( hwnd, pDescr, wParam, x, y);
+           return LISTBOX_HandleLButtonDown( pDescr, keys, x, y);
         }
         else if (pDescr->style & LBS_NOTIFY)
-            SEND_NOTIFICATION( hwnd, pDescr, LBN_DBLCLK );
-        return 0;
+            SEND_NOTIFICATION( pDescr, LBN_DBLCLK );
     }
     else
     {
@@ -2056,55 +2186,47 @@ static LRESULT LISTBOX_HandleLButtonDownCombo( HWND hwnd, LB_DESCR *pDescr,
         screenMousePos = mousePos;
         hWndOldCapture = GetCapture();
         ReleaseCapture();
-        GetWindowRect(hwnd, &screenRect);
-        ClientToScreen(hwnd, &screenMousePos);
+        GetWindowRect(pDescr->self, &screenRect);
+        ClientToScreen(pDescr->self, &screenMousePos);
 
         if(!PtInRect(&screenRect, screenMousePos))
         {
-            LISTBOX_SetCaretIndex( hwnd, pDescr, pDescr->lphc->droppedIndex, FALSE );
-            LISTBOX_SetSelection( hwnd, pDescr, pDescr->lphc->droppedIndex, FALSE, FALSE );
-#if 0
+            LISTBOX_SetCaretIndex( pDescr, pDescr->lphc->droppedIndex, FALSE );
+            LISTBOX_SetSelection( pDescr, pDescr->lphc->droppedIndex, FALSE, FALSE );
             COMBO_FlipListbox( pDescr->lphc, FALSE, FALSE );
-#endif
-            return 0;
         }
         else
         {
             /* Check to see the NC is a scrollbar */
             INT nHitTestType=0;
-            LONG style = GetWindowLongA( hwnd, GWL_STYLE );
+            LONG style = GetWindowLongW( pDescr->self, GWL_STYLE );
             /* Check Vertical scroll bar */
             if (style & WS_VSCROLL)
             {
+
                 clientRect.right += GetSystemMetrics(SM_CXVSCROLL);
                 if (PtInRect( &clientRect, mousePos ))
-                {
                     nHitTestType = HTVSCROLL;
-                }
             }
               /* Check horizontal scroll bar */
             if (style & WS_HSCROLL)
             {
                 clientRect.bottom += GetSystemMetrics(SM_CYHSCROLL);
                 if (PtInRect( &clientRect, mousePos ))
-                {
                     nHitTestType = HTHSCROLL;
-                }
             }
             /* Windows sends this message when a scrollbar is clicked
              */
 
             if(nHitTestType != 0)
             {
-                SendMessageW(hwnd, WM_NCLBUTTONDOWN, nHitTestType,
+                SendMessageW(pDescr->self, WM_NCLBUTTONDOWN, nHitTestType,
                     MAKELONG(screenMousePos.x, screenMousePos.y));
             }
             /* Resume the Capture after scrolling is complete
              */
             if(hWndOldCapture != 0)
-            {
                 SetCapture(hWndOldCapture);
-            }
         }
     }
     return 0;
@@ -2113,17 +2235,17 @@ static LRESULT LISTBOX_HandleLButtonDownCombo( HWND hwnd, LB_DESCR *pDescr,
 /***********************************************************************
  *           LISTBOX_HandleLButtonUp
  */
-static LRESULT LISTBOX_HandleLButtonUp( HWND hwnd, LB_DESCR *descr )
+static LRESULT LISTBOX_HandleLButtonUp( LB_DESCR *descr )
 {
     if (LISTBOX_Timer != LB_TIMER_NONE)
-        KillSystemTimer( hwnd, LB_TIMER_ID );
+        KillSystemTimer( descr->self, LB_TIMER_ID );
     LISTBOX_Timer = LB_TIMER_NONE;
     if (descr->captured)
     {
         descr->captured = FALSE;
-        if (GetCapture() == hwnd) ReleaseCapture();
+        if (GetCapture() == descr->self) ReleaseCapture();
         if ((descr->style & LBS_NOTIFY) && descr->nb_items)
-            SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE );
+            SEND_NOTIFICATION( descr, LBN_SELCHANGE );
     }
     return 0;
 }
@@ -2135,7 +2257,7 @@ static LRESULT LISTBOX_HandleLButtonUp( HWND hwnd, LB_DESCR *descr )
  * Handle scrolling upon a timer event.
  * Return TRUE if scrolling should continue.
  */
-static LRESULT LISTBOX_HandleTimer( HWND hwnd, LB_DESCR *descr,
+static LRESULT LISTBOX_HandleTimer( LB_DESCR *descr,
                                     INT index, TIMER_DIRECTION dir )
 {
     switch(dir)
@@ -2160,7 +2282,7 @@ static LRESULT LISTBOX_HandleTimer( HWND hwnd, LB_DESCR *descr,
         break;
     }
     if (index == descr->focus_item) return FALSE;
-    LISTBOX_MoveCaret( hwnd, descr, index, FALSE );
+    LISTBOX_MoveCaret( descr, index, FALSE );
     return TRUE;
 }
 
@@ -2170,11 +2292,11 @@ static LRESULT LISTBOX_HandleTimer( HWND hwnd, LB_DESCR *descr,
  *
  * WM_SYSTIMER handler.
  */
-static LRESULT LISTBOX_HandleSystemTimer( HWND hwnd, LB_DESCR *descr )
+static LRESULT LISTBOX_HandleSystemTimer( LB_DESCR *descr )
 {
-    if (!LISTBOX_HandleTimer( hwnd, descr, descr->focus_item, LISTBOX_Timer ))
+    if (!LISTBOX_HandleTimer( descr, descr->focus_item, LISTBOX_Timer ))
     {
-        KillSystemTimer( hwnd, LB_TIMER_ID );
+        KillSystemTimer( descr->self, LB_TIMER_ID );
         LISTBOX_Timer = LB_TIMER_NONE;
     }
     return 0;
@@ -2186,7 +2308,7 @@ static LRESULT LISTBOX_HandleSystemTimer( HWND hwnd, LB_DESCR *descr )
  *
  * WM_MOUSEMOVE handler.
  */
-static void LISTBOX_HandleMouseMove( HWND hwnd, LB_DESCR *descr,
+static void LISTBOX_HandleMouseMove( LB_DESCR *descr,
                                      INT x, INT y )
 {
     INT index;
@@ -2219,14 +2341,14 @@ static void LISTBOX_HandleMouseMove( HWND hwnd, LB_DESCR *descr,
 
     index = LISTBOX_GetItemFromPoint( descr, x, y );
     if (index == -1) index = descr->focus_item;
-    if (!LISTBOX_HandleTimer( hwnd, descr, index, dir )) dir = LB_TIMER_NONE;
+    if (!LISTBOX_HandleTimer( descr, index, dir )) dir = LB_TIMER_NONE;
 
     /* Start/stop the system timer */
 
     if (dir != LB_TIMER_NONE)
-        SetSystemTimer( hwnd, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL);
+        SetSystemTimer( descr->self, LB_TIMER_ID, LB_SCROLL_TIMEOUT, NULL);
     else if (LISTBOX_Timer != LB_TIMER_NONE)
-        KillSystemTimer( hwnd, LB_TIMER_ID );
+        KillSystemTimer( descr->self, LB_TIMER_ID );
     LISTBOX_Timer = dir;
 }
 
@@ -2234,7 +2356,7 @@ static void LISTBOX_HandleMouseMove( HWND hwnd, LB_DESCR *descr,
 /***********************************************************************
  *           LISTBOX_HandleKeyDown
  */
-static LRESULT LISTBOX_HandleKeyDown( HWND hwnd, LB_DESCR *descr, WPARAM wParam )
+static LRESULT LISTBOX_HandleKeyDown( LB_DESCR *descr, DWORD key )
 {
     INT caret = -1;
     BOOL bForceSelection = TRUE; /* select item pointed to by focus_item */
@@ -2244,11 +2366,11 @@ static LRESULT LISTBOX_HandleKeyDown( HWND hwnd, LB_DESCR *descr, WPARAM wParam
     if (descr->style & LBS_WANTKEYBOARDINPUT)
     {
         caret = SendMessageW( descr->owner, WM_VKEYTOITEM,
-                                MAKEWPARAM(LOWORD(wParam), descr->focus_item),
-                                (LPARAM)hwnd );
+                                MAKEWPARAM(LOWORD(key), descr->focus_item),
+                                (LPARAM)descr->self );
         if (caret == -2) return 0;
     }
-    if (caret == -1) switch(wParam)
+    if (caret == -1) switch(key)
     {
     case VK_LEFT:
         if (descr->style & LBS_MULTICOLUMN)
@@ -2307,7 +2429,7 @@ static LRESULT LISTBOX_HandleKeyDown( HWND hwnd, LB_DESCR *descr, WPARAM wParam
         if (descr->style & LBS_EXTENDEDSEL) caret = descr->focus_item;
         else if (descr->style & LBS_MULTIPLESEL)
         {
-            LISTBOX_SetSelection( hwnd, descr, descr->focus_item,
+            LISTBOX_SetSelection( descr, descr->focus_item,
                                   !descr->items[descr->focus_item].selected,
                                   (descr->style & LBS_NOTIFY) != 0 );
         }
@@ -2319,29 +2441,35 @@ static LRESULT LISTBOX_HandleKeyDown( HWND hwnd, LB_DESCR *descr, WPARAM wParam
         caret = descr->focus_item;
     if (caret >= 0)
     {
-        if ((descr->style & LBS_EXTENDEDSEL) &&
-            !(GetKeyState( VK_SHIFT ) & 0x8000))
+        if (((descr->style & LBS_EXTENDEDSEL) &&
+            !(GetKeyState( VK_SHIFT ) & 0x8000)) ||
+            !IS_MULTISELECT(descr))
             descr->anchor_item = caret;
-        LISTBOX_MoveCaret( hwnd, descr, caret, TRUE );
-        LISTBOX_SetSelection( hwnd, descr, caret, TRUE, FALSE);
+        LISTBOX_MoveCaret( descr, caret, TRUE );
+
+        if (descr->style & LBS_MULTIPLESEL)
+            descr->selected_item = caret;
+        else
+            LISTBOX_SetSelection( descr, caret, TRUE, FALSE);
         if (descr->style & LBS_NOTIFY)
         {
-           if( descr->lphc )
+            if( descr->lphc )
             {
-               /* make sure that combo parent doesn't hide us */
-               descr->lphc->wState |= CBF_NOROLLUP;
-           }
-            if (descr->nb_items) SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE );
+                /* make sure that combo parent doesn't hide us */
+                descr->lphc->wState |= CBF_NOROLLUP;
+            }
+            if (descr->nb_items) SEND_NOTIFICATION( descr, LBN_SELCHANGE );
         }
     }
     return 0;
+
 }
 
 
 /***********************************************************************
  *           LISTBOX_HandleChar
  */
-static LRESULT LISTBOX_HandleChar( HWND hwnd, LB_DESCR *descr, WCHAR charW )
+static LRESULT LISTBOX_HandleChar( LB_DESCR *descr, WCHAR charW )
 {
     INT caret = -1;
     WCHAR str[2];
@@ -2353,18 +2481,18 @@ static LRESULT LISTBOX_HandleChar( HWND hwnd, LB_DESCR *descr, WCHAR charW )
     {
         caret = SendMessageW( descr->owner, WM_CHARTOITEM,
                                 MAKEWPARAM(charW, descr->focus_item),
-                                (LPARAM)hwnd );
+                                (LPARAM)descr->self );
         if (caret == -2) return 0;
     }
     if (caret == -1)
-        caret = LISTBOX_FindString( hwnd, descr, descr->focus_item, str, FALSE);
+        caret = LISTBOX_FindString( descr, descr->focus_item, str, FALSE);
     if (caret != -1)
     {
         if ((!IS_MULTISELECT(descr)) && descr->selected_item == -1)
-           LISTBOX_SetSelection( hwnd, descr, caret, TRUE, FALSE);
-        LISTBOX_MoveCaret( hwnd, descr, caret, TRUE );
+           LISTBOX_SetSelection( descr, caret, TRUE, FALSE);
+        LISTBOX_MoveCaret( descr, caret, TRUE );
         if ((descr->style & LBS_NOTIFY) && descr->nb_items)
-            SEND_NOTIFICATION( hwnd, descr, LBN_SELCHANGE );
+            SEND_NOTIFICATION( descr, LBN_SELCHANGE );
     }
     return 0;
 }
@@ -2383,8 +2511,9 @@ static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
         return FALSE;
 
     GetClientRect( hwnd, &rect );
-    descr->owner         = GetParent( hwnd );
-    descr->style         = GetWindowLongA( hwnd, GWL_STYLE );
+    descr->self          = hwnd;
+    descr->owner         = GetParent( descr->self );
+    descr->style         = GetWindowLongA( descr->self, GWL_STYLE );
     descr->width         = rect.right - rect.left;
     descr->height        = rect.bottom - rect.top;
     descr->items         = NULL;
@@ -2405,9 +2534,10 @@ static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
     descr->in_focus     = FALSE;
     descr->captured      = FALSE;
     descr->font          = 0;
-    descr->locale        = 0;  /* FIXME */
+    descr->locale        = GetUserDefaultLCID();
     descr->lphc                 = lphc;
 
+#ifndef __REACTOS__
     if (is_old_app(hwnd) && ( descr->style & ( WS_VSCROLL | WS_HSCROLL ) ) )
     {
        /* Win95 document "List Box Differences" from MSDN:
@@ -2417,6 +2547,7 @@ static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
        */
        descr->style |= WS_VSCROLL | WS_HSCROLL;
     }
+#endif
 
     if( lphc )
     {
@@ -2424,14 +2555,14 @@ static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
         descr->owner = lphc->self;
     }
 
-    SetWindowLongA( hwnd, 0, (LONG)descr );
+    SetWindowLongPtrW( descr->self, 0, (LONG_PTR)descr );
 
 /*    if (wnd->dwExStyle & WS_EX_NOPARENTNOTIFY) descr->style &= ~LBS_NOTIFY;
  */
     if (descr->style & LBS_EXTENDEDSEL) descr->style |= LBS_MULTIPLESEL;
     if (descr->style & LBS_MULTICOLUMN) descr->style &= ~LBS_OWNERDRAWVARIABLE;
     if (descr->style & LBS_OWNERDRAWVARIABLE) descr->style |= LBS_NOINTEGRALHEIGHT;
-    descr->item_height = LISTBOX_SetFont( hwnd, descr, 0 );
+    descr->item_height = LISTBOX_SetFont( descr, 0 );
 
     if (descr->style & LBS_OWNERDRAWFIXED)
     {
@@ -2442,7 +2573,7 @@ static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
        }
        else
        {
-            UINT id = GetWindowLongA( hwnd, GWL_ID );
+            UINT id = (UINT)GetWindowLongPtrW( descr->self, GWLP_ID );
             mis.CtlType    = ODT_LISTBOX;
             mis.CtlID      = id;
             mis.itemID     = -1;
@@ -2462,10 +2593,10 @@ static BOOL LISTBOX_Create( HWND hwnd, LPHEADCOMBO lphc )
 /***********************************************************************
  *           LISTBOX_Destroy
  */
-static BOOL LISTBOX_Destroy( HWND hwnd, LB_DESCR *descr )
+static BOOL LISTBOX_Destroy( LB_DESCR *descr )
 {
-    LISTBOX_ResetContent( hwnd, descr );
-    SetWindowLongA( hwnd, 0, 0 );
+    LISTBOX_ResetContent( descr );
+    SetWindowLongPtrW( descr->self, 0, 0 );
     HeapFree( GetProcessHeap(), 0, descr );
     return TRUE;
 }
@@ -2477,36 +2608,47 @@ static BOOL LISTBOX_Destroy( HWND hwnd, LB_DESCR *descr )
 static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
                                              WPARAM wParam, LPARAM lParam, BOOL unicode )
 {
+    LB_DESCR *descr = (LB_DESCR *)GetWindowLongPtrW( hwnd, 0 );
     LRESULT ret;
-    LB_DESCR *descr;
+    LPHEADCOMBO lphc = 0;
 
-    if (!(descr = (LB_DESCR *)GetWindowLongA( hwnd, 0 )))
+    if (!descr)
     {
+        if (!IsWindow(hwnd)) return 0;
+
         if (msg == WM_CREATE)
         {
-            if (!LISTBOX_Create( hwnd, NULL ))
+           CREATESTRUCTW *lpcs = (CREATESTRUCTW *)lParam;
+           if (lpcs->style & LBS_COMBOBOX) lphc = (LPHEADCOMBO)lpcs->lpCreateParams;
+            if (!LISTBOX_Create( hwnd, lphc ))
                 return -1;
-            TRACE("creating wnd=%p descr=%lx\n", hwnd, GetWindowLongA( hwnd, 0 ) );
+            TRACE("creating wnd=%p descr=%lx\n", hwnd, GetWindowLongPtrW( hwnd, 0 ) );
             return 0;
         }
         /* Ignore all other messages before we get a WM_CREATE */
         return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
                          DefWindowProcA( hwnd, msg, wParam, lParam );
     }
+    if (descr->style & LBS_COMBOBOX) lphc = descr->lphc;
 
-#if 0  
-  TRACE("[%p]: msg %s wp %08x lp %08lx\n",
-          hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
-#endif
-          
+    //TRACE("[%p]: msg %s wp %08x lp %08lx\n",
+      //    hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
     switch(msg)
     {
+#ifndef __REACTOS__
+    case LB_RESETCONTENT16:
+#endif
     case LB_RESETCONTENT:
-        LISTBOX_ResetContent( hwnd, descr );
-        LISTBOX_UpdateScroll( hwnd, descr );
-        InvalidateRect( hwnd, NULL, TRUE );
+        LISTBOX_ResetContent( descr );
+        LISTBOX_UpdateScroll( descr );
+        InvalidateRect( descr->self, NULL, TRUE );
         return 0;
 
+#ifndef __REACTOS__
+    case LB_ADDSTRING16:
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+        /* fall through */
+#endif
     case LB_ADDSTRING:
     {
         INT ret;
@@ -2520,13 +2662,19 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
             if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
                 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
         }
-        wParam = LISTBOX_FindStringPos( hwnd, descr, textW, FALSE );
-        ret = LISTBOX_InsertString( hwnd, descr, wParam, textW );
+        wParam = LISTBOX_FindStringPos( descr, textW, FALSE );
+        ret = LISTBOX_InsertString( descr, wParam, textW );
         if (!unicode && HAS_STRINGS(descr))
             HeapFree(GetProcessHeap(), 0, textW);
         return ret;
     }
 
+#ifndef __REACTOS__
+    case LB_INSERTSTRING16:
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+        wParam = (INT)(INT16)wParam;
+        /* fall through */
+#endif
     case LB_INSERTSTRING:
     {
         INT ret;
@@ -2540,12 +2688,17 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
             if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
                 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
         }
-        ret = LISTBOX_InsertString( hwnd, descr, wParam, textW );
+        ret = LISTBOX_InsertString( descr, wParam, textW );
         if(!unicode && HAS_STRINGS(descr))
             HeapFree(GetProcessHeap(), 0, textW);
         return ret;
     }
 
+#ifndef __REACTOS__
+    case LB_ADDFILE16:
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+        /* fall through */
+#endif
     case LB_ADDFILE:
     {
         INT ret;
@@ -2559,44 +2712,80 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
             if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
                 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
         }
-        wParam = LISTBOX_FindFileStrPos( hwnd, descr, textW );
-        ret = LISTBOX_InsertString( hwnd, descr, wParam, textW );
+        wParam = LISTBOX_FindFileStrPos( descr, textW );
+        ret = LISTBOX_InsertString( descr, wParam, textW );
         if(!unicode && HAS_STRINGS(descr))
             HeapFree(GetProcessHeap(), 0, textW);
         return ret;
     }
 
+#ifndef __REACTOS__
+    case LB_DELETESTRING16:
+#endif
     case LB_DELETESTRING:
-        if (LISTBOX_RemoveItem( hwnd, descr, wParam) != LB_ERR)
+        if (LISTBOX_RemoveItem( descr, wParam) != LB_ERR)
            return descr->nb_items;
         else
+        {
+           SetLastError(ERROR_INVALID_INDEX);
            return LB_ERR;
+        }
 
+#ifndef __REACTOS__
+    case LB_GETITEMDATA16:
+#endif
     case LB_GETITEMDATA:
         if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
+        {
+            SetLastError(ERROR_INVALID_INDEX);
             return LB_ERR;
+        }
         return descr->items[wParam].data;
 
+#ifndef __REACTOS__
+    case LB_SETITEMDATA16:
+#endif
     case LB_SETITEMDATA:
         if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
+        {
+            SetLastError(ERROR_INVALID_INDEX);
             return LB_ERR;
+        }
         descr->items[wParam].data = (DWORD)lParam;
         return LB_OKAY;
 
+#ifndef __REACTOS__
+    case LB_GETCOUNT16:
+#endif
     case LB_GETCOUNT:
         return descr->nb_items;
 
+#ifndef __REACTOS__
+    case LB_GETTEXT16:
+        lParam = (LPARAM)MapSL(lParam);
+        /* fall through */
+#endif
     case LB_GETTEXT:
-        return LISTBOX_GetText( descr, wParam, lParam, unicode );
+        return LISTBOX_GetText( descr, wParam, (LPWSTR)lParam, unicode );
 
+#ifndef __REACTOS__
+    case LB_GETTEXTLEN16:
+        /* fall through */
+#endif
     case LB_GETTEXTLEN:
         if ((INT)wParam >= descr->nb_items || (INT)wParam < 0)
+        {
+            SetLastError(ERROR_INVALID_INDEX);
             return LB_ERR;
+        }
         if (!HAS_STRINGS(descr)) return sizeof(DWORD);
         if (unicode) return strlenW( descr->items[wParam].str );
         return WideCharToMultiByte( CP_ACP, 0, descr->items[wParam].str,
                                     strlenW(descr->items[wParam].str), NULL, 0, NULL, NULL );
 
+#ifndef __REACTOS__
+    case LB_GETCURSEL16:
+#endif
     case LB_GETCURSEL:
         if (descr->nb_items==0)
          return LB_ERR;
@@ -2609,14 +2798,25 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
        return descr->focus_item;
         /* otherwise, if the user tries to move the selection with the    */
         /* arrow keys, we will give the application something to choke on */
+#ifndef __REACTOS__
+    case LB_GETTOPINDEX16:
+#endif
     case LB_GETTOPINDEX:
         return descr->top_item;
 
+#ifndef __REACTOS__
+    case LB_GETITEMHEIGHT16:
+#endif
     case LB_GETITEMHEIGHT:
         return LISTBOX_GetItemHeight( descr, wParam );
 
+#ifndef __REACTOS__
+    case LB_SETITEMHEIGHT16:
+        lParam = LOWORD(lParam);
+        /* fall through */
+#endif
     case LB_SETITEMHEIGHT:
-        return LISTBOX_SetItemHeight( hwnd, descr, wParam, lParam, TRUE );
+        return LISTBOX_SetItemHeight( descr, wParam, lParam, TRUE );
 
     case LB_ITEMFROMPOINT:
         {
@@ -2634,27 +2834,55 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
                              !PtInRect( &rect, pt ) );
         }
 
+#ifndef __REACTOS__
+    case LB_SETCARETINDEX16:
+#endif
     case LB_SETCARETINDEX:
         if ((!IS_MULTISELECT(descr)) && (descr->selected_item != -1)) return LB_ERR;
-        if (LISTBOX_SetCaretIndex( hwnd, descr, wParam, !lParam ) == LB_ERR)
+        if (LISTBOX_SetCaretIndex( descr, wParam, !lParam ) == LB_ERR)
             return LB_ERR;
         else if (ISWIN31)
              return wParam;
         else
              return LB_OKAY;
 
+#ifndef __REACTOS__
+    case LB_GETCARETINDEX16:
+#endif
     case LB_GETCARETINDEX:
         return descr->focus_item;
 
+#ifndef __REACTOS__
+    case LB_SETTOPINDEX16:
+#endif
     case LB_SETTOPINDEX:
-        return LISTBOX_SetTopItem( hwnd, descr, wParam, TRUE );
+        return LISTBOX_SetTopItem( descr, wParam, TRUE );
 
+#ifndef __REACTOS__
+    case LB_SETCOLUMNWIDTH16:
+#endif
     case LB_SETCOLUMNWIDTH:
-        return LISTBOX_SetColumnWidth( hwnd, descr, wParam );
+        return LISTBOX_SetColumnWidth( descr, wParam );
+
+#ifndef __REACTOS__
+    case LB_GETITEMRECT16:
+        {
+            RECT rect;
+            ret = LISTBOX_GetItemRect( descr, (INT16)wParam, &rect );
+            CONV_RECT32TO16( &rect, MapSL(lParam) );
+        }
+       return ret;
+#endif
 
     case LB_GETITEMRECT:
         return LISTBOX_GetItemRect( descr, wParam, (RECT *)lParam );
 
+#ifndef __REACTOS__
+    case LB_FINDSTRING16:
+        wParam = (INT)(INT16)wParam;
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+        /* fall through */
+#endif
     case LB_FINDSTRING:
     {
         INT ret;
@@ -2668,12 +2896,18 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
             if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
                 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
         }
-        ret = LISTBOX_FindString( hwnd, descr, wParam, textW, FALSE );
+        ret = LISTBOX_FindString( descr, wParam, textW, FALSE );
         if(!unicode && HAS_STRINGS(descr))
             HeapFree(GetProcessHeap(), 0, textW);
         return ret;
     }
 
+#ifndef __REACTOS__
+    case LB_FINDSTRINGEXACT16:
+        wParam = (INT)(INT16)wParam;
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+        /* fall through */
+#endif
     case LB_FINDSTRINGEXACT:
     {
         INT ret;
@@ -2687,12 +2921,18 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
             if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
                 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
         }
-        ret = LISTBOX_FindString( hwnd, descr, wParam, textW, TRUE );
+        ret = LISTBOX_FindString( descr, wParam, textW, TRUE );
         if(!unicode && HAS_STRINGS(descr))
             HeapFree(GetProcessHeap(), 0, textW);
         return ret;
     }
 
+#ifndef __REACTOS__
+    case LB_SELECTSTRING16:
+        wParam = (INT)(INT16)wParam;
+        if (HAS_STRINGS(descr)) lParam = (LPARAM)MapSL(lParam);
+        /* fall through */
+#endif
     case LB_SELECTSTRING:
     {
         INT index;
@@ -2710,65 +2950,121 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
             if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
                 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
         }
-        index = LISTBOX_FindString( hwnd, descr, wParam, textW, FALSE );
+        index = LISTBOX_FindString( descr, wParam, textW, FALSE );
         if(!unicode && HAS_STRINGS(descr))
             HeapFree(GetProcessHeap(), 0, textW);
         if (index != LB_ERR)
        {
-            LISTBOX_SetCaretIndex( hwnd, descr, index, TRUE );
-            LISTBOX_SetSelection( hwnd, descr, index, TRUE, FALSE );
+            LISTBOX_MoveCaret( descr, index, TRUE );
+            LISTBOX_SetSelection( descr, index, TRUE, FALSE );
        }
         return index;
     }
 
+#ifndef __REACTOS__
+    case LB_GETSEL16:
+        wParam = (INT)(INT16)wParam;
+        /* fall through */
+#endif
     case LB_GETSEL:
         if (((INT)wParam < 0) || ((INT)wParam >= descr->nb_items))
             return LB_ERR;
         return descr->items[wParam].selected;
 
+#ifndef __REACTOS__
+    case LB_SETSEL16:
+        lParam = (INT)(INT16)lParam;
+        /* fall through */
+#endif
     case LB_SETSEL:
-        return LISTBOX_SetSelection( hwnd, descr, lParam, wParam, FALSE );
+        return LISTBOX_SetSelection( descr, lParam, wParam, FALSE );
 
+#ifndef __REACTOS__
+    case LB_SETCURSEL16:
+        wParam = (INT)(INT16)wParam;
+        /* fall through */
+#endif
     case LB_SETCURSEL:
         if (IS_MULTISELECT(descr)) return LB_ERR;
-        LISTBOX_SetCaretIndex( hwnd, descr, wParam, TRUE );
-        return LISTBOX_SetSelection( hwnd, descr, wParam, TRUE, FALSE );
+        LISTBOX_SetCaretIndex( descr, wParam, TRUE );
+        ret = LISTBOX_SetSelection( descr, wParam, TRUE, FALSE );
+       if (lphc && ret != LB_ERR) ret = descr->selected_item;
+       return ret;
 
+#ifndef __REACTOS__
+    case LB_GETSELCOUNT16:
+#endif
     case LB_GETSELCOUNT:
         return LISTBOX_GetSelCount( descr );
 
+#ifndef __REACTOS__
+    case LB_GETSELITEMS16:
+        return LISTBOX_GetSelItems16( descr, wParam, (LPINT16)MapSL(lParam) );
+#endif
+
     case LB_GETSELITEMS:
         return LISTBOX_GetSelItems( descr, wParam, (LPINT)lParam );
 
+#ifndef __REACTOS__
+    case LB_SELITEMRANGE16:
+#endif
     case LB_SELITEMRANGE:
         if (LOWORD(lParam) <= HIWORD(lParam))
-            return LISTBOX_SelectItemRange( hwnd, descr, LOWORD(lParam),
+            return LISTBOX_SelectItemRange( descr, LOWORD(lParam),
                                             HIWORD(lParam), wParam );
         else
-            return LISTBOX_SelectItemRange( hwnd, descr, HIWORD(lParam),
+            return LISTBOX_SelectItemRange( descr, HIWORD(lParam),
                                             LOWORD(lParam), wParam );
 
+#ifndef __REACTOS__
+    case LB_SELITEMRANGEEX16:
+#endif
     case LB_SELITEMRANGEEX:
         if ((INT)lParam >= (INT)wParam)
-            return LISTBOX_SelectItemRange( hwnd, descr, wParam, lParam, TRUE );
+            return LISTBOX_SelectItemRange( descr, wParam, lParam, TRUE );
         else
-            return LISTBOX_SelectItemRange( hwnd, descr, lParam, wParam, FALSE);
+            return LISTBOX_SelectItemRange( descr, lParam, wParam, FALSE);
 
+#ifndef __REACTOS__
+    case LB_GETHORIZONTALEXTENT16:
+#endif
     case LB_GETHORIZONTALEXTENT:
         return descr->horz_extent;
 
+#ifndef __REACTOS__
+    case LB_SETHORIZONTALEXTENT16:
+#endif
     case LB_SETHORIZONTALEXTENT:
-        return LISTBOX_SetHorizontalExtent( hwnd, descr, wParam );
+        return LISTBOX_SetHorizontalExtent( descr, wParam );
 
+#ifndef __REACTOS__
+    case LB_GETANCHORINDEX16:
+#endif
     case LB_GETANCHORINDEX:
         return descr->anchor_item;
 
+#ifndef __REACTOS__
+    case LB_SETANCHORINDEX16:
+        wParam = (INT)(INT16)wParam;
+        /* fall through */
+#endif
     case LB_SETANCHORINDEX:
         if (((INT)wParam < -1) || ((INT)wParam >= descr->nb_items))
+        {
+            SetLastError(ERROR_INVALID_INDEX);
             return LB_ERR;
+        }
         descr->anchor_item = (INT)wParam;
         return LB_OKAY;
 
+#ifndef __REACTOS__
+    case LB_DIR16:
+        /* according to Win16 docs, DDL_DRIVES should make DDL_EXCLUSIVE
+         * be set automatically (this is different in Win32) */
+        if (wParam & DDL_DRIVES) wParam |= DDL_EXCLUSIVE;
+       lParam = (LPARAM)MapSL(lParam);
+        /* fall through */
+#endif
     case LB_DIR:
     {
         INT ret;
@@ -2782,7 +3078,7 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
             if((textW = HeapAlloc(GetProcessHeap(), 0, countW * sizeof(WCHAR))))
                 MultiByteToWideChar(CP_ACP, 0, textA, -1, textW, countW);
         }
-        ret = LISTBOX_Directory( hwnd, descr, wParam, textW, msg == LB_DIR );
+        ret = LISTBOX_Directory( descr, wParam, textW, msg == LB_DIR );
         if(!unicode)
             HeapFree(GetProcessHeap(), 0, textW);
         return ret;
@@ -2792,43 +3088,60 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
         return descr->locale;
 
     case LB_SETLOCALE:
-        descr->locale = (LCID)wParam;  /* FIXME: should check for valid lcid */
-        return LB_OKAY;
+    {
+        LCID ret;
+        if (!IsValidLocale((LCID)wParam, LCID_INSTALLED))
+            return LB_ERR;
+        ret = descr->locale;
+        descr->locale = (LCID)wParam;
+        return ret;
+    }
 
     case LB_INITSTORAGE:
-        return LISTBOX_InitStorage( hwnd, descr, wParam );
+        return LISTBOX_InitStorage( descr, wParam );
 
     case LB_SETCOUNT:
-        return LISTBOX_SetCount( hwnd, descr, (INT)wParam );
+        return LISTBOX_SetCount( descr, (INT)wParam );
+
+#ifndef __REACTOS__
+    case LB_SETTABSTOPS16:
+        return LISTBOX_SetTabStops( descr, (INT)(INT16)wParam, MapSL(lParam), TRUE );
+#endif
 
     case LB_SETTABSTOPS:
-        return LISTBOX_SetTabStops( hwnd, descr, wParam, (LPINT)lParam, FALSE );
+        return LISTBOX_SetTabStops( descr, wParam, (LPINT)lParam, FALSE );
 
+#ifndef __REACTOS__
+    case LB_CARETON16:
+#endif
     case LB_CARETON:
         if (descr->caret_on)
             return LB_OKAY;
         descr->caret_on = TRUE;
         if ((descr->focus_item != -1) && (descr->in_focus))
-            LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
+            LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
         return LB_OKAY;
 
+#ifndef __REACTOS__
+    case LB_CARETOFF16:
+#endif
     case LB_CARETOFF:
         if (!descr->caret_on)
             return LB_OKAY;
         descr->caret_on = FALSE;
         if ((descr->focus_item != -1) && (descr->in_focus))
-            LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
+            LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
         return LB_OKAY;
 
     case WM_DESTROY:
-        return LISTBOX_Destroy( hwnd, descr );
+        return LISTBOX_Destroy( descr );
 
     case WM_ENABLE:
         InvalidateRect( hwnd, NULL, TRUE );
         return 0;
 
     case WM_SETREDRAW:
-        LISTBOX_SetRedraw( hwnd, descr, wParam != 0 );
+        LISTBOX_SetRedraw( descr, wParam != 0 );
         return 0;
 
     case WM_GETDLGCODE:
@@ -2838,57 +3151,124 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
         {
             PAINTSTRUCT ps;
             HDC hdc = ( wParam ) ? ((HDC)wParam) :  BeginPaint( hwnd, &ps );
-            ret = LISTBOX_Paint( hwnd, descr, hdc );
+            ret = LISTBOX_Paint( descr, hdc );
             if( !wParam ) EndPaint( hwnd, &ps );
         }
         return ret;
     case WM_SIZE:
-        LISTBOX_UpdateSize( hwnd, descr );
+        LISTBOX_UpdateSize( descr );
         return 0;
     case WM_GETFONT:
         return (LRESULT)descr->font;
     case WM_SETFONT:
-        LISTBOX_SetFont( hwnd, descr, (HFONT)wParam );
+        LISTBOX_SetFont( descr, (HFONT)wParam );
         if (lParam) InvalidateRect( hwnd, 0, TRUE );
         return 0;
     case WM_SETFOCUS:
         descr->in_focus = TRUE;
         descr->caret_on = TRUE;
         if (descr->focus_item != -1)
-            LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
-        SEND_NOTIFICATION( hwnd, descr, LBN_SETFOCUS );
+            LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
+        SEND_NOTIFICATION( descr, LBN_SETFOCUS );
         return 0;
     case WM_KILLFOCUS:
         descr->in_focus = FALSE;
         if ((descr->focus_item != -1) && descr->caret_on)
-            LISTBOX_RepaintItem( hwnd, descr, descr->focus_item, ODA_FOCUS );
-        SEND_NOTIFICATION( hwnd, descr, LBN_KILLFOCUS );
+            LISTBOX_RepaintItem( descr, descr->focus_item, ODA_FOCUS );
+        SEND_NOTIFICATION( descr, LBN_KILLFOCUS );
         return 0;
     case WM_HSCROLL:
-        return LISTBOX_HandleHScroll( hwnd, descr, wParam );
+        return LISTBOX_HandleHScroll( descr, LOWORD(wParam), HIWORD(wParam) );
     case WM_VSCROLL:
-        return LISTBOX_HandleVScroll( hwnd, descr, wParam );
+        return LISTBOX_HandleVScroll( descr, LOWORD(wParam), HIWORD(wParam) );
     case WM_MOUSEWHEEL:
         if (wParam & (MK_SHIFT | MK_CONTROL))
             return DefWindowProcW( hwnd, msg, wParam, lParam );
-        return LISTBOX_HandleMouseWheel( hwnd, descr, wParam );
+        return LISTBOX_HandleMouseWheel( descr, (SHORT)HIWORD(wParam) );
     case WM_LBUTTONDOWN:
-        return LISTBOX_HandleLButtonDown( hwnd, descr, wParam,
+       if (lphc)
+            return LISTBOX_HandleLButtonDownCombo(descr, msg, wParam,
+                                                  (INT16)LOWORD(lParam),
+                                                  (INT16)HIWORD(lParam) );
+        return LISTBOX_HandleLButtonDown(descr, wParam,
                                           (INT16)LOWORD(lParam),
                                           (INT16)HIWORD(lParam) );
     case WM_LBUTTONDBLCLK:
+       if (lphc)
+            return LISTBOX_HandleLButtonDownCombo(descr, msg, wParam,
+                                                  (INT16)LOWORD(lParam),
+                                                  (INT16)HIWORD(lParam) );
         if (descr->style & LBS_NOTIFY)
-            SEND_NOTIFICATION( hwnd, descr, LBN_DBLCLK );
+            SEND_NOTIFICATION( descr, LBN_DBLCLK );
         return 0;
     case WM_MOUSEMOVE:
-        if (GetCapture() == hwnd)
-            LISTBOX_HandleMouseMove( hwnd, descr, (INT16)LOWORD(lParam),
+        if ( lphc && ((lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE) )
+        {
+            BOOL    captured = descr->captured;
+            POINT   mousePos;
+            RECT    clientRect;
+
+            mousePos.x = (INT16)LOWORD(lParam);
+            mousePos.y = (INT16)HIWORD(lParam);
+
+            /*
+             * If we are in a dropdown combobox, we simulate that
+             * the mouse is captured to show the tracking of the item.
+             */
+            if (GetClientRect(descr->self, &clientRect) && PtInRect( &clientRect, mousePos ))
+                descr->captured = TRUE;
+
+            LISTBOX_HandleMouseMove( descr, mousePos.x, mousePos.y);
+
+            descr->captured = captured;
+        } 
+        else if (GetCapture() == descr->self)
+        {
+            LISTBOX_HandleMouseMove( descr, (INT16)LOWORD(lParam),
                                      (INT16)HIWORD(lParam) );
+        }
         return 0;
     case WM_LBUTTONUP:
-        return LISTBOX_HandleLButtonUp( hwnd, descr );
+       if (lphc)
+       {
+            POINT mousePos;
+            RECT  clientRect;
+
+            /*
+             * If the mouse button "up" is not in the listbox,
+             * we make sure there is no selection by re-selecting the
+             * item that was selected when the listbox was made visible.
+             */
+            mousePos.x = (INT16)LOWORD(lParam);
+            mousePos.y = (INT16)HIWORD(lParam);
+
+            GetClientRect(hwnd, &clientRect);
+
+            /*
+             * When the user clicks outside the combobox and the focus
+             * is lost, the owning combobox will send a fake buttonup with
+             * 0xFFFFFFF as the mouse location, we must also revert the
+             * selection to the original selection.
+             */
+            if ( (lParam == (LPARAM)-1) || (!PtInRect( &clientRect, mousePos )) )
+                LISTBOX_MoveCaret( descr, lphc->droppedIndex, FALSE );
+        }
+        return LISTBOX_HandleLButtonUp( descr );
     case WM_KEYDOWN:
-        return LISTBOX_HandleKeyDown( hwnd, descr, wParam );
+        if( lphc && (lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE )
+        {
+            /* for some reason Windows makes it possible to
+             * show/hide ComboLBox by sending it WM_KEYDOWNs */
+
+            if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
+                ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
+                  && (wParam == VK_DOWN || wParam == VK_UP)) )
+            {
+                COMBO_FlipListbox( lphc, FALSE, FALSE );
+                return 0;
+            }
+        }
+        return LISTBOX_HandleKeyDown( descr, wParam );
     case WM_CHAR:
     {
         WCHAR charW;
@@ -2899,45 +3279,57 @@ static LRESULT WINAPI ListBoxWndProc_common( HWND hwnd, UINT msg,
             CHAR charA = (CHAR)wParam;
             MultiByteToWideChar(CP_ACP, 0, &charA, 1, &charW, 1);
         }
-        return LISTBOX_HandleChar( hwnd, descr, charW );
+        return LISTBOX_HandleChar( descr, charW );
     }
     case WM_SYSTIMER:
-        return LISTBOX_HandleSystemTimer( hwnd, descr );
+        return LISTBOX_HandleSystemTimer( descr );
     case WM_ERASEBKGND:
         if ((IS_OWNERDRAW(descr)) && !(descr->style & LBS_DISPLAYCHANGED))
         {
             RECT rect;
             HBRUSH hbrush = (HBRUSH)SendMessageW( descr->owner, WM_CTLCOLORLISTBOX,
-                                              wParam, (LPARAM)hwnd );
+                                              wParam, (LPARAM)descr->self );
            TRACE("hbrush = %p\n", hbrush);
            if(!hbrush)
                hbrush = GetSysColorBrush(COLOR_WINDOW);
            if(hbrush)
            {
-               GetClientRect(hwnd, &rect);
+               GetClientRect(descr->self, &rect);
                FillRect((HDC)wParam, &rect, hbrush);
            }
         }
         return 1;
     case WM_DROPFILES:
-        if( !descr->lphc )
-            return unicode ? SendMessageW( descr->owner, msg, wParam, lParam ) :
-                             SendMessageA( descr->owner, msg, wParam, lParam );
+        if( lphc ) return 0;
+        return unicode ? SendMessageW( descr->owner, msg, wParam, lParam ) :
+                         SendMessageA( descr->owner, msg, wParam, lParam );
+    case WM_NCDESTROY:
+        if( lphc && (lphc->dwStyle & CBS_DROPDOWNLIST) != CBS_SIMPLE )
+            lphc->hWndLBox = 0;
         break;
 
+    case WM_NCACTIVATE:
+        if (lphc) return 0;
+       break;
+
     default:
-        return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
-                         DefWindowProcA( hwnd, msg, wParam, lParam );
+        if ((msg >= WM_USER) && (msg < 0xc000))
+            WARN("[%p]: unknown msg %04x wp %08x lp %08lx\n",
+                 hwnd, msg, wParam, lParam );
     }
-    return 0;
+
+    return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
+                     DefWindowProcA( hwnd, msg, wParam, lParam );
 }
 
 /***********************************************************************
  *           ListBoxWndProcA
+ *
+ * This is just a wrapper for the real wndproc, it only does window locking
+ * and unlocking.
  */
 static LRESULT WINAPI ListBoxWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
 {
-    if (!IsWindow(hwnd)) return 0;
     return ListBoxWndProc_common( hwnd, msg, wParam, lParam, FALSE );
 }
 
@@ -2946,183 +3338,16 @@ static LRESULT WINAPI ListBoxWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARA
  */
 static LRESULT WINAPI ListBoxWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
 {
-    if (!IsWindow(hwnd)) return 0;
     return ListBoxWndProc_common( hwnd, msg, wParam, lParam, TRUE );
 }
 
 /***********************************************************************
- *           ComboLBWndProc_common
- *
- * The real combo listbox wndproc
+ *           GetListBoxInfo
  */
-static LRESULT WINAPI ComboLBWndProc_common( HWND hwnd, UINT msg,
-                                             WPARAM wParam, LPARAM lParam, BOOL unicode )
-{
-    LRESULT lRet = 0;
-    LB_DESCR *descr;
-    LPHEADCOMBO lphc;
-
-    if (!(descr = (LB_DESCR *)GetWindowLongA( hwnd, 0 )))
-    {
-        if (msg == WM_CREATE)
-        {
-            CREATESTRUCTA *lpcs = (CREATESTRUCTA *)lParam;
-            TRACE_(combo)("\tpassed parent handle = %p\n",lpcs->lpCreateParams);
-            lphc = (LPHEADCOMBO)(lpcs->lpCreateParams);
-            return LISTBOX_Create( hwnd, lphc );
-        }
-        /* Ignore all other messages before we get a WM_CREATE */
-        return unicode ? DefWindowProcW( hwnd, msg, wParam, lParam ) :
-                         DefWindowProcA( hwnd, msg, wParam, lParam );
-    }
-
-#if 0 
-  TRACE_(combo)("[%p]: msg %s wp %08x lp %08lx\n",
-                  hwnd, SPY_GetMsgName(msg, hwnd), wParam, lParam );
-#endif
-
-    if ((lphc = descr->lphc) != NULL)
-    {
-        switch( msg )
-        {
-        case WM_MOUSEMOVE:
-            if (CB_GETTYPE(lphc) != CBS_SIMPLE)
-            {
-                POINT   mousePos;
-                BOOL    captured;
-                RECT    clientRect;
-
-                mousePos.x = (INT16)LOWORD(lParam);
-                mousePos.y = (INT16)HIWORD(lParam);
-
-                /*
-                 * If we are in a dropdown combobox, we simulate that
-                 * the mouse is captured to show the tracking of the item.
-                 */
-                GetClientRect(hwnd, &clientRect);
-
-                if (PtInRect( &clientRect, mousePos ))
-                {
-                    captured = descr->captured;
-                    descr->captured = TRUE;
-
-                    LISTBOX_HandleMouseMove( hwnd, descr,
-                                             mousePos.x, mousePos.y);
-
-                    descr->captured = captured;
-
-                }
-                else
-                {
-                    LISTBOX_HandleMouseMove( hwnd, descr,
-                                             mousePos.x, mousePos.y);
-                }
-
-                return 0;
-
-            }
-            /* else we are in Win3.1 look, go with the default behavior. */
-            break;
-
-        case WM_LBUTTONUP:
-            {
-                POINT mousePos;
-                RECT  clientRect;
-
-                /*
-                 * If the mouse button "up" is not in the listbox,
-                 * we make sure there is no selection by re-selecting the
-                 * item that was selected when the listbox was made visible.
-                 */
-                mousePos.x = (INT16)LOWORD(lParam);
-                mousePos.y = (INT16)HIWORD(lParam);
-
-                GetClientRect(hwnd, &clientRect);
-
-                /*
-                 * When the user clicks outside the combobox and the focus
-                 * is lost, the owning combobox will send a fake buttonup with
-                 * 0xFFFFFFF as the mouse location, we must also revert the
-                 * selection to the original selection.
-                 */
-                if ( (lParam == (LPARAM)-1) ||
-                     (!PtInRect( &clientRect, mousePos )) )
-                {
-                    LISTBOX_MoveCaret( hwnd, descr, lphc->droppedIndex, FALSE );
-                }
-            }
-            return LISTBOX_HandleLButtonUp( hwnd, descr );
-        case WM_LBUTTONDBLCLK:
-        case WM_LBUTTONDOWN:
-            return LISTBOX_HandleLButtonDownCombo(hwnd, descr, msg, wParam,
-                                                  (INT16)LOWORD(lParam),
-                                                  (INT16)HIWORD(lParam) );
-        case WM_NCACTIVATE:
-            return FALSE;
-        case WM_KEYDOWN:
-            if( CB_GETTYPE(lphc) != CBS_SIMPLE )
-            {
-                /* for some reason(?) Windows makes it possible to
-                 * show/hide ComboLBox by sending it WM_KEYDOWNs */
-
-                if( (!(lphc->wState & CBF_EUI) && wParam == VK_F4) ||
-                    ( (lphc->wState & CBF_EUI) && !(lphc->wState & CBF_DROPPED)
-                      && (wParam == VK_DOWN || wParam == VK_UP)) )
-                {
-#if 0
-                    COMBO_FlipListbox( lphc, FALSE, FALSE );
-#endif
-                    return 0;
-                }
-            }
-            return LISTBOX_HandleKeyDown( hwnd, descr, wParam );
-
-        case LB_SETCURSEL:
-            lRet = unicode ? ListBoxWndProcW( hwnd, msg, wParam, lParam ) :
-                ListBoxWndProcA( hwnd, msg, wParam, lParam );
-            lRet =(lRet == LB_ERR) ? lRet : descr->selected_item;
-            return lRet;
-        case WM_NCDESTROY:
-            if( CB_GETTYPE(lphc) != CBS_SIMPLE )
-                lphc->hWndLBox = 0;
-            break;
-        }
-    }
-
-    /* default handling: call listbox wnd proc */
-    lRet = unicode ? ListBoxWndProcW( hwnd, msg, wParam, lParam ) :
-                     ListBoxWndProcA( hwnd, msg, wParam, lParam );
-
-    TRACE_(combo)("\t default on msg [%04x]\n", (UINT16)msg );
-
-    return lRet;
-}
-
-/***********************************************************************
- *           ComboLBWndProcA
- *
- *  NOTE: in Windows, winproc address of the ComboLBox is the same
- *       as that of the Listbox.
- */
-LRESULT WINAPI ComboLBWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
-{
-    if (!IsWindow(hwnd)) return 0;
-    return ComboLBWndProc_common( hwnd, msg, wParam, lParam, FALSE );
-}
-
-/***********************************************************************
- *           ComboLBWndProcW
- */
-LRESULT WINAPI ComboLBWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
-{
-    if (!IsWindow(hwnd)) return 0;
-    return ComboLBWndProc_common( hwnd, msg, wParam, lParam, TRUE );
-}
-
-
 DWORD STDCALL
 GetListBoxInfo(HWND hwnd)
 {
   UNIMPLEMENTED;
   return 0;
 }
+