Release 980927

Sun Sep 27 14:25:38 1998  Petter Reinholdtsen <pere@td.org.uit.no>

	* [files/drive.c]
	Make sure GetDriveType32A() handles param NULL.  Added some
	doc on function.

Sun Sep 27 14:07:26 1998  Huw D M Davies <daviesh@abacus.physics.ox.ac.uk>

	* [controls/edit.c] [windows/win.c]
	Don't call SetWindowLong() in EDIT_WM_NCREATE.
	Fix SetWindowLong(GWL_[EX]STYLE) to work for 16bit windows. Remove
	UpdateWindow() call. 

Sun Sep 27 13:41:22 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [scheduler/*.c] [server/event.c] [server/mutex.c]
	  [server/semaphore.c]
	Implemented server-side synchronisation objects.

Sun Sep 27 01:13:35 1998  Alex Priem <alexp@sci.kun.nl>

	* [dlls/comctl32/treeview.c] [include/treeview.h] [include/comctl.h]
	Treeview implementation.

	* [dlls/comctl32/trackbar.c] [include/trackbar.h] 
	Trackbar implementation.

Sat Sep 26 20:49:13 1998  Ulrich Weigand <weigand@informatik.uni-erlangen.de>

	* [if1632/thunk.c] [tools/build.c] [win32/kernel32.c]
	Bugfix: several problems with flat thunks fixed.

	* [memory/selector.c]
	Bugfix: IsBad...Ptr16 didn't work for limit_in_pages segments.

	* [scheduler/thread.c]
	Bugfix: CreateThread: Allow id parameter == NULL.

	* [objects/gdiobj.c]
	Bugfix: IsGDIObject: Return correct object type for stock objects.

	* [msdos/dpmi.c]
	Bugfix: fixed typo in INT_DoRealModeInt.

	* [msdos/int21.c]
	Bugfix: int21 READ *must* use WIN16_hread, not _hread16.

	* [if1632/kernel.spec] [if1632/dummy.c] [if1632/thunk.c]
	  [loader/ne/module.c] [scheduler/event.c] [scheduler/synchro.c]
	  [scheduler/thread.c] [win32/kernel32.c] [win32/ordinals.c]
	Added names/stubs for all undocumented KERNEL routines (Win95).
	Added the following undoc. 16-bit equivalents to Win32 routines:
	KERNEL.441-443,449-453,456-462,471-476,479-486,488.
	Added stubs for some other KERNEL routines.

	* [memory/heap.c] [memory/global.c] [include/global.h]
	Implemented Local32... 32-bit local heap routines (KERNEL.208-215, 229).

	* [miscemu/instr.c] [loader/module.c] [include/module.h]
	Implemented __GP fault handling and HasGPHandler (KERNEL.338).

	* [misc/error.c]
	Implemented LogParamErrorRegs (KERNEL.327).

	* [loader/task.c] [include/windows.h]
	Implemented GetCodeInfo (KERNEL.104).

	* [loader/task.c] [scheduler/thread.c] [include/thread.h]
	Implemented [GS]etThreadQueue and [GS]etFastQueue (KERNEL.463/4, 624/5).

	* [if1632/gdi.spec] [objects/dc.c] [objects/dib.c]
	  [objects/bitmap.c] [include/windows.h]
	Bugfix: fixed wrong parameter for CreateDIBSection16.
	Added [GS]etDIBColorTable16, stub for GetBoundsRect16.
	Partially implemented BITMAP_GetObject16 for DIBs.

	* [if1632/gdi.spec] [relay32/gdi32.spec] [objects/palette.c]
	Added some GDI stubs.

	* [if1632/Makefile.in] [if1632/display.spec] [if1632/mouse.spec]
	  [if1632/keyboard.spec] [if1632/builtin.c] [windows/keyboard.c]
	Added some stubs for Win16 drivers: KEYBOARD, MOUSE, DISPLAY.

	* [if1632/wprocs.spec] [msdos/vxd.c]
	Added some stubs for VxDs: VMM, ConfigMG, TimerAPI.

	* [msdos/int2f.c]
	Added some stubs for real-mode network drivers.

Sat Sep 26 18:18:18 1998  Marcus Meissner <marcus@jet.franken.de>

	* [configure.in]
	Merged in some more of the FreeBSD ports/emulators/wine patches. 
	(Maintainer(s) of this port: You can just submit these
	patches to Alexandre directly.)

	 * [loader/pe_image.c]
	Check filesize of image against size derived from header
	to spot truncated executeables without crashing.

	* [files/directory.c]
	Set envvar "COMSPEC". One win32(!!) program crashes without it.

	* [multimedia/mmio.c]
	Added mmioSetInfo32.

	* [include/file.h]
	Return STD_ERROR_HANDLE for AUX and PRT dos handles.

	* [loader/module.c]
	Handle executeables with spaces in their names a bit better in
	CreateProcess.

	* [relay32/msvfw32.spec][if1632/msvideo.spec][multimedia/msvideo.c][include/vfw.h]
	Started on MS Video support (can load Win32 ICMs).

	* [tools/testrun]
	A bit smarter use of ps.

	* [memory/virtual.c]
	Report PAGE_GUARDed pages as PAGE_PROTECTED (AutoCAD LT R17 fails
	without that check (since Win95 doesn't know about PAGE_GUARD)).

Sat Sep 26 15:04:05 1998  Ove Kaaven <ovek@arcticnet.no>

	* [include/miscemu.h] [if1632/builtin.c] [loader/task.c]
	  [miscemu/instr.c] [msdos/dpmi.c] [msdos/int21.c]
	  [msdos/interrupts.c] [windows/user.c]
	INT_[S|G]etHandler was renamed to INT_[S|G]etPMHandler.
	Added handlers to deal with real-mode interrupts; DOS
	programs are now able to hook real-mode interrupts.

	* [loader/dos/module.c] [msdos/dosmem.c] [msdos/int21.c]
	Moved real-mode interrupt table initialization to
	msdos/dosmem.c, and made new V86 tasks get a full copy
	of the existing "system memory" instead of almost empty
	space. Misc fixes.

	* [include/dosexe.h] [loader/dos/module.c] [msdos/dpmi.c]
	  [msdos/int2f.c]
	First shot at letting DOS programs start up DPMI (but DPMI
	is still disabled for DOS programs, for pkunzip's sake).

	* [include/debugger.h] [debugger/break.c] [debugger/dbg.y]
	  [debugger/registers.c] [debugger/memory.c] [debugger/info.c]
	  [loader/dos/dosvm.c]
	First shot at making Wine's debugger work for DOS programs.
	The -debug flag works, as do "nexti" and "stepi".

Sat Sep 26 13:13:13 1998  Juergen Schmied <juergen.schmied@metronet.de>

	* [dlls/shell32/dataobject.c]
	New classes IEnumFORMATETC implemented, IDataObject stubs.
	
	* [dlls/shell32/*.*][relay32/shell32.spec]
	Bugfixes.
	New: ICM_InsertItem(), ILCreateFromPath().
	Implemented: ILCloneFirst().
	Stubs: ILIsEqual(), ILFindChild(), SHLogILFromFSIL(),
	  PathMatchSpec(), PathIsExe().
	Changed: ILGetSize(), _ILIsDesktop(), PathCombine().

	* [include/shlobj.h]
	New SHLGUID's
	New structures: DVTARGETDEVICE32, STGMEDIUM32, FORMATETC32,
	CLIPFORMAT32.
	New interfaces: IEnumFORMATETC, IDataObject, ICommDlgBrowser
	IDockingWindowFrame, IServiceProvider.

	* [dlls/shell32/folders.c]
	Stubs for IShellLink.

	* [loader/resource.c]
	Small fixes.

	* [misc/crtdll.c][relay32/crtdll.spec]
	New __dllonexit().

	* [windows/message.c]
	SendNotifyMessageA, SendMessageCallBack32A half implemented.

	* [controls/edit.c]
	EDIT_WM_SetText set EF_UPDATE flag not for ES_MULTILINE.

	* [files/file.c]
	Handling of fileposition fixed.

Fri Sep 25 18:13:30 1998  Patrik Stridvall <ps@leissner.se>

	* [include/windows.h] [include/wintypes.h]
	  [ole/ole2nls.h] [relay32/kernel32.spec]
	Implemented EnumDateFormats and EnumTimeFormats.
	Only adds US English support.

	* [Makefile.in] [configure.in] 
	  [dlls/Makefile.in] [dlls/psapi/Makefile.in] 
	  [dlls/psapi/psapi_main.c] 
	New files to implement stubs for PSAPI.DLL (NT only).

	* [relay32/Makefile.in] [relay32/builtin32.c] 
	  [relay32/psapi.spec]
	New spec file for PSAPI.DLL (NT only).

	* [scheduler/handle.c]
	HANDLE_GetObjPtr should only interpret the pseudo handles as the
	current thread or the current process if a thread or a process is
	requested.

	* [include/winversion.h] [misc/version.c]
	Adds the global function VERSION_GetVersion() so functions can
	have different behavior depending on the -winver flag.

	* [include/oledlg.h] [ole/oledlg.c]
	Minor fixes. 

	* [windows/winproc.c]
	Minor changes.

	* [include/imm.h] [misc/imm.c]
	Now returns correct values under both Windows 95 and NT 4.0.

Thu Sep 24 22:11:44 1998  Kristian Nielsen  <kristian.nielsen@risoe.dk>

	* [configure.in] [include/acconfig.h] [include/thread.h]
	  [scheduler/sysdeps.c]
	Autoconfig test for non-reentrant libc.

Wed Sep 23 19:52:12 1998  Matthew Becker <mbecker@glasscity.net>

	* [*/*.c]
	Miscellaneous documentation updates and debugging output 
	standardizations.

	* [objects/clipping.c]
	Added ExtSelectClipRgn.

Wed Sep 23 00:03:28 EDT 1998  Pete Ratzlaff <pratzlaff@cfa.harvard.edu>

	* [include/windows.h] [if1632/user.spec] [relay32/user32.spec]
	  [windows/keyboard.c]
	Added, marginally implemented, GetKeyboardLayoutName().
	Only returns US English keyboard name.

Tue Sep 22 16:32:41 1998  Marcel Baur <mbaur@iiic.ethz.ch>

	* [programs/control/*]
	New Winelib application.

Mon Sep 21 00:29:18 1998  Peter Hunnisett <hunnise@nortel.ca>

	* [include/dplay.h][multimedia/dplay.c][ole/compobj.c]
	Added all DirectPlayLobby interfaces and enhanced DirectPlay
	and DirectPlayLobby support. Still not all that much. Useful
	enough if you just need to start a program, don't try any
	real dplay/lobby stuff.

	* [documentation/status/directplay]
	Added a very little bit.

	* [graphics/ddraw.c]
	- Call to SetWindowLong32A wasn't working because there was no
	  memory set aside when the window class was registered.
	- Fixed some xlib reference counting and change the behaviour
	  of DirectDrawSurface3_SetPalette to mimic observed behaviour
	  (palette is associated will all backbuffers)
	- Also stored all palette colour fields and spit back our saved
	  colour fields rather than query X for them.
	- Added plenty of AddRef and Release traces.
	- Added Xlib support for using -desktop option.
	- Fixed Xlib message handling. Messages weren't being passed to
	  the application. Fixes mouse movements in some xlib DDraw games.
	- Added a few stubs.

	* [windows/win.c][include/winerror.h]
	Fixed up some error handling in WIN_SetWindowLong. SetLastError
	wasn't being used. Could cause problems with 0 return codes.
	Added new error in winerror (1400).

	* [AUTHORS] [include/authors.h]
	Added myself as a Wine author.

Sun Sep 20 21:22:44 1998  Alexander Larsson  <alla@lysator.liu.se>

	* [loader/module.c]
	Changed GetModuleFileName32A so that is returns the
	long version of the filename. Note that just the name
	is long, not the directories.

Sat Sep 19 20:05:30 1998 Per Ångström <pang@mind.nu> 

	* [controls/menu.c]
	Made a couple of fixes to make life easier for applications that alter
	their menus at runtime.

	* [windows/defdlg.c]
	Removed the cast of the return value from dialog procedures to a 16-bit
	bool. The return value needs to retain all its 32 bits, since it is not 
	always a bool, such as when responding to the WM_NCHITTEST message.

Fri Sep 18 11:30:38 1998  Sergey Turchanov <turchanov@usa.net>

	* [loader/resource.c]
	Fixed very funny bug (though gravely affecting further excecution)
	with FindResource[Ex]32 functions.

	* [include/multimon.h] [windows/multimon.c] [relay32/user32.spec]
	  [include/windows.h] [windows/sysmetrics.c]
	Default implementation for Multimonitor API.

	* [include/windows.h] [windows/winpos.c]
	Fixed incorrect declaration (and behaviour) of GetWindowRect32.

Wed Sep 16 10:21:15 1998  Gerard Patel <G.Patel@Wanadoo.fr>

	* [controls/edit.c]
	Fixed EDIT_EM_GetLine to use correctly length of lines.

Tue Sep 15 20:40:16 1998  Eric Kohl <ekohl@abo.rhein-zeitung.de>

	* [misc/tweak.c][include/tweak.h][controls/menu.c]
	Replaced the tweak graphic routines by calls to DrawEdge32().

	* [misc/tweak.c][include/tweak.h][documentation/win95look]
	  [wine.ini][*/*]
	Changed "look and feel" selection. Allows Win3.1, Win95 and
	Win98 (no GUI code implemented) look and feel.

	* [dlls/comctl32/header.c][include/header.h][include/commctrl.h]
	Started callback item support and did some minor improvements.

	* [dlls/comctl32/imagelist.c]
	Fixed bug in transparent image display.
	ImageList_GetIcon is still buggy :-(

	* [dlls/comctl32/toolbar.c]
	Fixed button drawing (partial hack).

	* [dlls/comctl32/commctrl.c]
	Fixed MenuHelp().

	* [controls/button.c]
	Added 3d effect for groupbox.

	* [windows/msgbox.c]
	Added font support for message boxes.

	* [windows/nonclient.c]
	Fixed window moving bug.

	* [dlls/comctl32/*.c]
	Various improvements.

	* [dlls/comctl32/listview.c][dlls/comctl32/rebar.c]
	  [include/commctrl.h]
	More messages.

	* [windows/syscolor.c][include/windows.h]
	Introduced new Win98 system colors.

Tue Sep 15 18:29:45 1998 Wesley Filardo <eightknots@aol.com>

	* [files/profile.c]
	Added support in PROFILE_LoadWineIni for -config option

	* [misc/main.c] [include/options.h]
	Added -config option.

Tue Sep 15 18:22:26 1998  Petter Reinholdtsen <pere@td.org.uit.no>

	* [documentation/Makefile.in]
	Make sure directory exists before installing into it.

Tue Sep 15 01:47:33 1998  Pablo Saratxaga <pablo.sarachaga@ping.be>

	* [ole/nls/*] [ole/ole2nls.c] [include/winnls.h]
	Fixed a few errors and completed some NLS files.

Mon Sep 14 01:23:45 1998  Joseph Pranevich <knight@baltimore.wwaves.com>

	* [include/miscemu.h] [msdos/interrupts.c]
	Removed a compilation warning, added INT 25 to the list of interrupts
	callable from DOS applications, added a debug message when unsupported
	interrupts are used.

Sun Sep 13 19:55:22 1998  Lawson Whitney <lawson_whitney@juno.com>

	* [if1632/relay.c]
	CallProcEx32W should not reverse arguments.

Sun Aug 17 21:18:12 1998  Eric Pouech  <eric.pouech@lemel.fr>

	* [multimedia/midi.c] [multimedia/init.c] [multimedia/mmsys.c] 
	  [include/multimedia.h] [include/mmsystem.h] 
	  [multimedia/Makefile.in] [multimedia/midipatch.c]
	  [if1632/multimedia.spec]
	Made MIDI input and output functional on OSS capable systems.

	* [multimedia/timer.c]
	Changes to trigger callbacks at the accurate pace even when
	fake timers are used.
diff --git a/dlls/Makefile.in b/dlls/Makefile.in
index 67e3a95..ea8bc46 100644
--- a/dlls/Makefile.in
+++ b/dlls/Makefile.in
@@ -1,6 +1,9 @@
 SUBDIRS = \
 	comctl32 \
-	shell32
+	psapi \
+	shell32 \
+	winaspi \
+	wnaspi32
 
 all: $(SUBDIRS)
 
diff --git a/dlls/comctl32/animate.c b/dlls/comctl32/animate.c
index 9303711..9c2fc19 100644
--- a/dlls/comctl32/animate.c
+++ b/dlls/comctl32/animate.c
@@ -14,6 +14,8 @@
  */
 
 #include "windows.h"
+#include "winnt.h"
+#include "winbase.h"
 #include "commctrl.h"
 #include "animate.h"
 #include "win.h"
@@ -23,34 +25,136 @@
 #define ANIMATE_GetInfoPtr(wndPtr) ((ANIMATE_INFO *)wndPtr->wExtra[0])
 
 
+static BOOL32
+ANIMATE_LoadRes32A (ANIMATE_INFO *infoPtr, HINSTANCE32 hInst, LPSTR lpName)
+{
+    HRSRC32 hrsrc;
+    HGLOBAL32 handle;
+
+    hrsrc = FindResource32A (hInst, lpName, "AVI");
+    if (!hrsrc)
+	return FALSE;
+
+    handle = LoadResource32 (hInst, hrsrc);
+    if (!handle)
+	return FALSE;
+
+    infoPtr->lpAvi = LockResource32 (handle);
+    if (!infoPtr->lpAvi)
+	return FALSE;
+
+    return TRUE;
+}
+
+
+static BOOL32
+ANIMATE_LoadFile32A (ANIMATE_INFO *infoPtr, LPSTR lpName)
+{
+    HANDLE32 handle;
+
+    infoPtr->hFile =
+	CreateFile32A (lpName, GENERIC_READ, 0, NULL, OPEN_EXISTING,
+		       FILE_ATTRIBUTE_NORMAL, 0);
+    if (!infoPtr->hFile)
+	return FALSE;
+
+    handle =
+	CreateFileMapping32A (infoPtr->hFile, NULL, PAGE_READONLY | SEC_COMMIT,
+			      0, 0, NULL);
+    if (!handle) {
+	CloseHandle (infoPtr->hFile);
+	infoPtr->hFile = 0;
+	return FALSE;
+    }
+
+    infoPtr->lpAvi = MapViewOfFile (handle, FILE_MAP_READ, 0, 0, 0);
+    if (!infoPtr->lpAvi) {
+	CloseHandle (infoPtr->hFile);
+	infoPtr->hFile = 0;
+	return FALSE;
+    }
+
+    return TRUE;
+}
+
+
+static VOID
+ANIMATE_Free (ANIMATE_INFO *infoPtr)
+{
+    if (infoPtr->hFile) {
+	UnmapViewOfFile (infoPtr->lpAvi);
+	CloseHandle (infoPtr->hFile);
+	infoPtr->lpAvi = NULL;
+    }
+    else {
+	GlobalFree32 (infoPtr->lpAvi);
+	infoPtr->lpAvi = NULL;
+    }
+}
+
+
+static VOID
+ANIMATE_GetAviInfo (infoPtr)
+{
+
+
+}
+
+
 static LRESULT
 ANIMATE_Open32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(wndPtr);
+    HINSTANCE32 hInstance = (HINSTANCE32)wParam;
+
+    ANIMATE_Free (infoPtr);
 
     if (!lParam) {
-
-	FIXME (animate, "close avi: empty stub!\n");
-
+	TRACE (animate, "closing avi!\n");
 	return TRUE;
     }
     
     if (HIWORD(lParam)) {
-
 	FIXME (animate, "(\"%s\") empty stub!\n", (LPSTR)lParam);
 
+	if (ANIMATE_LoadRes32A (infoPtr, hInstance, (LPSTR)lParam)) {
+
+	    FIXME (animate, "AVI resource found!\n");
+
+	}
+	else {
+	    FIXME (animate, "No AVI resource found!\n");
+	    if (ANIMATE_LoadFile32A (infoPtr, (LPSTR)lParam)) {
+		FIXME (animate, "AVI file found!\n");
+	    }
+	    else {
+		FIXME (animate, "No AVI file found!\n");
+		return FALSE;
+	    }
+	}
     }
     else {
-
 	FIXME (animate, "(%u) empty stub!\n", (WORD)LOWORD(lParam));
 
+	if (ANIMATE_LoadRes32A (infoPtr, hInstance,
+				MAKEINTRESOURCE32A((INT32)lParam))) {
+	    FIXME (animate, "AVI resource found!\n");
+	}
+	else {
+	    FIXME (animate, "No AVI resource found!\n");
+	    return FALSE;
+	}
     }
 
+    ANIMATE_GetAviInfo (infoPtr);
 
     return TRUE;
 }
 
 
+// << ANIMATE_Open32W >>
+
+
 static LRESULT
 ANIMATE_Play (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
@@ -131,7 +235,8 @@
     ANIMATE_INFO *infoPtr = ANIMATE_GetInfoPtr(wndPtr);
 
 
-
+    /* free avi data */
+    ANIMATE_Free (infoPtr);
 
     /* free animate info data */
     COMCTL32_Free (infoPtr);
diff --git a/dlls/comctl32/comctl32undoc.c b/dlls/comctl32/comctl32undoc.c
index e45f77f..430dd67 100644
--- a/dlls/comctl32/comctl32undoc.c
+++ b/dlls/comctl32/comctl32undoc.c
@@ -10,7 +10,8 @@
  *     COMCTL32.DLL (internally).
  *
  * TODO
- *     - Write documentation.
+ *     - Add more functions.
+ *     - Write some documentation.
  */
 
 #include <string.h>
@@ -27,6 +28,22 @@
 
 
 /**************************************************************************
+ * COMCTL32_11 [COMCTL32.11]
+ */
+
+DWORD WINAPI
+COMCTL32_11 (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3,
+	     DWORD dwParam4, DWORD dwParam5, DWORD dwParam6)
+{
+
+    FIXME (commctrl, "(%08lx, %08lx, %08lx, %08lx, %08lx, %08lx): empty stub\n",
+	   dwParam1, dwParam2, dwParam3, dwParam4, dwParam5, dwParam6);
+
+    return 0;
+}
+
+
+/**************************************************************************
  * Alloc [COMCTL32.71]
  *
  * Allocates memory block from the dll's local heap
@@ -153,6 +170,25 @@
 
 
 /**************************************************************************
+ * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
+ * lists.
+ *
+ *
+ */
+
+typedef struct tagMRUINFO
+{
+    DWORD  dwParam1;
+    DWORD  dwParam2;
+    DWORD  dwParam3;
+    HKEY   hkeyMain;
+    LPCSTR lpszSubKey;
+    DWORD  dwParam6;
+} MRUINFO, *LPMRUINFO;
+ 
+
+
+/**************************************************************************
  * CreateMRUListA [COMCTL32.151]
  *
  * PARAMS
@@ -161,54 +197,233 @@
  * RETURNS
  */
 
-DWORD WINAPI
-CreateMRUList32A (DWORD dwParam)
+LPVOID WINAPI
+CreateMRUListEx32A (LPMRUINFO lpmi, DWORD dwParam2,
+		    DWORD dwParam3, DWORD dwParam4);
+
+LPVOID WINAPI
+CreateMRUList32A (LPMRUINFO lpmi)
 {
-
-    FIXME (commctrl, "(%lx)\n", dwParam);
-
-    return 1;
+     return CreateMRUListEx32A (lpmi, 0, 0, 0);
 }
 
 
 
+DWORD WINAPI
+FreeMRUList32A (LPVOID ptr)
+{
+    FIXME (commctrl, "(%p) empty stub!\n", ptr);
+
+    COMCTL32_Free (ptr);
+
+    return TRUE;
+}
+
+
+
+
+
+
+LPVOID WINAPI
+CreateMRUListEx32A (LPMRUINFO lpmi, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
+{
+    DWORD  dwLocal1;
+    HKEY   hkeyResult;
+    DWORD  dwLocal3;
+    LPVOID lMRU;
+    DWORD  dwLocal5;
+    DWORD  dwLocal6;
+    DWORD  dwLocal7;
+    DWORD  dwDisposition;
+
+    /* internal variables */
+    LPVOID ptr;
+
+    FIXME (commctrl, "(%p) empty stub!\n", lpmi);
+
+    if (lpmi) {
+	FIXME (commctrl, "(%lx %lx %lx %lx \"%s\" %lx)\n",
+	       lpmi->dwParam1, lpmi->dwParam2, lpmi->dwParam3,
+	       lpmi->hkeyMain, lpmi->lpszSubKey, lpmi->dwParam6);
+    }
+
+    /* dummy pointer creation */
+    ptr = COMCTL32_Alloc (32);
+
+    FIXME (commctrl, "-- ret = %p\n", ptr);
+
+    return ptr;
+}
+
+
+
+DWORD WINAPI
+AddMRUData (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{
+
+    FIXME (commctrl, "(%lx %lx %lx) empty stub!\n",
+	   dwParam1, dwParam2, dwParam3);
+
+    return 0;
+}
+
+
+DWORD WINAPI
+FindMRUData (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
+{
+
+    FIXME (commctrl, "(%lx %lx %lx %lx) empty stub!\n",
+	   dwParam1, dwParam2, dwParam3, dwParam4);
+
+    return -1;
+}
+
+
+
+/**************************************************************************
+ * Str_GetPtrA [COMCTL32.233]
+ *
+ * PARAMS
+ *     lpSrc   [I]
+ *     lpDest  [O]
+ *     nMaxLen [I]
+ *
+ * RETURNS
+ */
+
+INT32 WINAPI
+Str_GetPtr32A (LPCSTR lpSrc, LPSTR lpDest, INT32 nMaxLen)
+{
+    INT32 len;
+
+    TRACE (commctrl, "(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
+
+    if (!lpDest && lpSrc)
+	return lstrlen32A (lpSrc);
+
+    if (nMaxLen == 0)
+	return 0;
+
+    if (lpSrc == NULL) {
+	lpDest[0] = '\0';
+	return 0;
+    }
+
+    len = lstrlen32A (lpSrc);
+    if (len >= nMaxLen)
+	len = nMaxLen - 1;
+
+    RtlMoveMemory (lpDest, lpSrc, len);
+    lpDest[len] = '\0';
+
+    return len;
+}
+
 
 /**************************************************************************
  * Str_SetPtrA [COMCTL32.234]
  *
  * PARAMS
- *     dwParam1 [I]
- *     dwParam2 [I]
+ *     lppDest [O]
+ *     lpSrc   [I]
  *
  * RETURNS
  */
 
 BOOL32 WINAPI
-COMCTL32_Str_SetPtrA (LPSTR lpStr, LPVOID *lpPtr)
+Str_SetPtr32A (LPSTR *lppDest, LPCSTR lpSrc)
+{
+    TRACE (commctrl, "(%p %p)\n", lppDest, lpSrc);
+ 
+    if (lpSrc) {
+	LPSTR ptr = COMCTL32_ReAlloc (lppDest, lstrlen32A (lpSrc) + 1);
+	if (!ptr)
+	    return FALSE;
+	lstrcpy32A (ptr, lpSrc);
+	*lppDest = ptr;
+    }
+    else {
+	if (*lppDest) {
+	    COMCTL32_Free (*lppDest);
+	    *lppDest = NULL;
+	}
+    }
+
+    return TRUE;
+}
+
+
+/**************************************************************************
+ * Str_GetPtrW [COMCTL32.235]
+ *
+ * PARAMS
+ *     lpSrc   [I]
+ *     lpDest  [O]
+ *     nMaxLen [I]
+ *
+ * RETURNS
+ */
+
+INT32 WINAPI
+Str_GetPtr32W (LPCWSTR lpSrc, LPWSTR lpDest, INT32 nMaxLen)
 {
     INT32 len;
-    LPSTR ptr;
 
-    TRACE (commctrl, "(%p %p)\n", lpStr, lpPtr);
+    TRACE (commctrl, "(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
+
+    if (!lpDest && lpSrc)
+	return lstrlen32W (lpSrc);
+
+    if (nMaxLen == 0)
+	return 0;
+
+    if (lpSrc == NULL) {
+	lpDest[0] = L'\0';
+	return 0;
+    }
+
+    len = lstrlen32W (lpSrc);
+    if (len >= nMaxLen)
+	len = nMaxLen - 1;
+
+    RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
+    lpDest[len] = L'\0';
+
+    return len;
+}
+
+
+/**************************************************************************
+ * Str_SetPtrW [COMCTL32.236]
+ *
+ * PARAMS
+ *     lpDest [O]
+ *     lpSrc  [I]
+ *
+ * RETURNS
+ */
+
+BOOL32 WINAPI
+Str_SetPtr32W (LPWSTR *lppDest, LPCWSTR lpSrc)
+{
+    TRACE (commctrl, "(%p %p)\n", lppDest, lpSrc);
  
-    if (lpStr) {
-	len = lstrlen32A (lpStr);
-	ptr = COMCTL32_ReAlloc (lpPtr, len + 1);
-	if (!(ptr))
+    if (lpSrc) {
+	INT32 len = lstrlen32W (lpSrc) + 1;
+	LPWSTR ptr = COMCTL32_ReAlloc (lppDest, len * sizeof(WCHAR));
+	if (!ptr)
 	    return FALSE;
-	lstrcpy32A (ptr, lpStr);
-	if (!lpPtr)
-	    return FALSE;
-	*lpPtr = ptr;
-	return TRUE;
+	lstrcpy32W (ptr, lpSrc);
+	*lppDest = ptr;
+    }
+    else {
+	if (*lppDest) {
+	    COMCTL32_Free (*lppDest);
+	    *lppDest = NULL;
+	}
     }
 
-    if (*lpPtr) {
-	COMCTL32_Free (*lpPtr);
-	return TRUE;
-    }
-
-    return FALSE;
+    return TRUE;
 }
 
 
@@ -636,7 +851,7 @@
 BOOL32 WINAPI
 DPA_Grow (const HDPA hdpa, INT32 nGrow)
 {
-    FIXME (commctrl, "(%p %d) stub!\n", hdpa, nGrow);
+    TRACE (commctrl, "(%p %d)\n", hdpa, nGrow);
 
     if (!hdpa)
 	return FALSE;
@@ -676,7 +891,7 @@
     if (!hdpa)
 	return NULL;
 
-    FIXME (commctrl, "(%p %p) stub!\n", hdpa, hdpaNew);
+    TRACE (commctrl, "(%p %p)\n", hdpa, hdpaNew);
 
     if (!hdpaNew) {
 	/* create a new DPA */
@@ -1019,7 +1234,7 @@
     LPVOID t, v;
     INT32  i, j;
 
-    if (l > r) {
+    if (r > l) {
 	v = lpPtrs[r];
 	i = l - 1;
 	j = r;
@@ -1064,7 +1279,9 @@
 
     TRACE (commctrl, "(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
 
-    DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1, pfnCompare, lParam);
+    if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
+	DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
+		       pfnCompare, lParam);
 
     return TRUE;
 }
@@ -1107,6 +1324,8 @@
 	INT32 l, r, x, n;
 	LPVOID *lpPtr;
 
+	TRACE (commctrl, "binary search\n");
+
 	l = (nStart == -1) ? 0 : nStart;
 	r = hdpa->nItemCount - 1;
 	lpPtr = hdpa->ptrs;
@@ -1138,7 +1357,7 @@
 	LPVOID *lpPtr;
 	INT32  nIndex;
 
-	FIXME (commctrl, "linear search\n");
+	TRACE (commctrl, "linear search\n");
 	
 	nIndex = (nStart == -1)? 0 : nStart;
 	lpPtr = hdpa->ptrs;
@@ -1267,3 +1486,63 @@
     return atoi(lpString);
 }
 
+
+/**************************************************************************
+ * COMCTL32_385 [COMCTL32.385]
+ */
+
+DWORD WINAPI
+COMCTL32_385 (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{
+
+    FIXME (commctrl, "(%08lx, %08lx, %08lx): empty stub\n",
+	   dwParam1, dwParam2, dwParam3);
+
+    return 0;
+}
+
+
+/**************************************************************************
+ * COMCTL32_386 [COMCTL32.386]
+ */
+
+DWORD WINAPI
+COMCTL32_386 (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{
+
+    FIXME (commctrl, "(%08lx, %08lx, %08lx): empty stub\n",
+	   dwParam1, dwParam2, dwParam3);
+
+    return 0;
+}
+
+
+/**************************************************************************
+ * COMCTL32_387 [COMCTL32.387]
+ */
+
+DWORD WINAPI
+COMCTL32_387 (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{
+
+    FIXME (commctrl, "(%08lx, %08lx, %08lx): empty stub\n",
+	   dwParam1, dwParam2, dwParam3);
+
+    return 0;
+}
+
+
+/**************************************************************************
+ * COMCTL32_388 [COMCTL32.388]
+ */
+
+DWORD WINAPI
+COMCTL32_388 (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
+{
+
+    FIXME (commctrl, "(%08lx, %08lx, %08lx): empty stub\n",
+	   dwParam1, dwParam2, dwParam3);
+
+    return 0;
+}
+
diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c
index 0c6f00e..b0b5c7c 100644
--- a/dlls/comctl32/commctrl.c
+++ b/dlls/comctl32/commctrl.c
@@ -32,10 +32,13 @@
  * ComCtl32LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
  *
  * PARAMS
- *     hinstDLL    [I]
+ *     hinstDLL    [I] handle to the 'dlls' instance
  *     fdwReason   [I]
  *     lpvReserved [I]
  *
+ * RETURNS
+ *     Success: TRUE
+ *     Failure: FALSE
  */
 
 BOOL32 WINAPI
@@ -68,59 +71,64 @@
  * MenuHelp [COMCTL32.2]
  *
  * PARAMS
- *     uMsg
- *     wParam
- *     lParam
- *     hMainMenu
- *     hInst
- *     hwndStatus
- *     lpwIDs
+ *     uMsg       [I]
+ *     wParam     [I]
+ *     lParam     [I]
+ *     hMainMenu  [I] handle to the applications main menu
+ *     hInst      [I]
+ *     hwndStatus [I] handle to the status bar window
+ *     lpwIDs     [I] pointer to an array of intergers (see NOTES)
  *
  * RETURNS
- *     None
+ *     No return value
  *
  * NOTES
- *     Some features are still missing because of incomplete WM_MENUSELECT
- *     messages (16->32 bit conversion).
+ *     The official documentation is incomplete!
  */
 
 VOID WINAPI
 MenuHelp (UINT32 uMsg, WPARAM32 wParam, LPARAM lParam, HMENU32 hMainMenu,
 	  HINSTANCE32 hInst, HWND32 hwndStatus, LPUINT32 lpwIDs)
 {
-    char szStatusText[128];
+    UINT32 uMenuID = 0;
 
-    if (!IsWindow32 (hwndStatus)) return;
+    if (!IsWindow32 (hwndStatus))
+	return;
 
     switch (uMsg) {
 	case WM_MENUSELECT:
-            TRACE (commctrl, "WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
-                   wParam, lParam);
+	    TRACE (commctrl, "WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
+		   wParam, lParam);
 
             if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
                 /* menu was closed */
+		TRACE (commctrl, "menu was closed!\n");
                 SendMessage32A (hwndStatus, SB_SIMPLE, FALSE, 0);
             }
-            else {
-                if (HIWORD(wParam) & MF_POPUP) {
-		    FIXME (commctrl, "popup 0x%08x 0x%08lx\n", wParam, lParam);
+	    else {
+		/* menu item was selected */
+		if (HIWORD(wParam) & MF_POPUP)
+		    uMenuID = (UINT32)*(lpwIDs+1);
+		else
+		    uMenuID = (UINT32)LOWORD(wParam);
+		TRACE (commctrl, "uMenuID = %u\n", uMenuID);
 
-                    szStatusText[0] = 0;
-                }
-                else {
-                    TRACE (commctrl, "menu item selected!\n");
-                    if (!LoadString32A (hInst, LOWORD(wParam), szStatusText, 128))
-                        szStatusText[0] = 0;
-                }
-                SendMessage32A (hwndStatus, SB_SETTEXT32A, 255 | SBT_NOBORDERS,
-                                (LPARAM)szStatusText);
-                SendMessage32A (hwndStatus, SB_SIMPLE, TRUE, 0);
-            }
-            break;
+		if (uMenuID) {
+		    CHAR szText[256];
 
-        default:
-            WARN (commctrl, "Invalid Message!\n");
-            break;
+		    if (!LoadString32A (hInst, uMenuID, szText, 256))
+			szText[0] = 0;
+
+		    SendMessage32A (hwndStatus, SB_SETTEXT32A,
+				    255 | SBT_NOBORDERS, (LPARAM)szText);
+		    SendMessage32A (hwndStatus, SB_SIMPLE, TRUE, 0);
+		}
+	    }
+	    break;
+
+	default:
+	    WARN (commctrl, "Invalid Message!\n");
+	    break;
     }
 }
 
@@ -198,10 +206,10 @@
  *     lpInfo [I] pointer to an array of integers
  *
  * RETURNS
- *     None.
+ *     No return value.
  *
  * NOTES
- *
+ *     The official documentation is incomplete!
  */
 
 VOID WINAPI
@@ -244,6 +252,9 @@
  *     lprc  [I] pointer to a rectangle
  *     text  [I] pointer to the text
  *     style [I] 
+ *
+ * RETURNS
+ *     No return value.
  */
 
 VOID WINAPI
@@ -281,6 +292,9 @@
  *     lprc  [I] pointer to a rectangle
  *     text  [I] pointer to the text
  *     style [I] 
+ *
+ * RETURNS
+ *     No return value.
  */
 
 VOID WINAPI
@@ -293,8 +307,19 @@
 
 
 /***********************************************************************
- * CreateStatusWindow32A [COMCTL32.6][COMCTL32.21]
+ * CreateStatusWindow32A [COMCTL32.6][COMCTL32.21] Creates a status bar
+ *
+ * PARAMS
+ *     style  [I]
+ *     text   [I]
+ *     parent [I] handle to the parent window
+ *     wid    [I]
+ *
+ * RETURNS
+ *     Success: handle to the control
+ *     Failure: 0
  */
+
 HWND32 WINAPI
 CreateStatusWindow32A (INT32 style, LPCSTR text, HWND32 parent, UINT32 wid)
 {
@@ -306,20 +331,51 @@
 
 
 /***********************************************************************
- *           CreateStatusWindow32W   (COMCTL32.22)
+ * CreateStatusWindow32W [COMCTL32.22] Creates a status bar control
+ *
+ * PARAMS
+ *     style  [I]
+ *     text   [I]
+ *     parent [I]
+ *     wid    [I]
+ *
+ * RETURNS
+ *     Success: handle to the control
+ *     Failure: 0
  */
-HWND32 WINAPI CreateStatusWindow32W( INT32 style, LPCWSTR text, HWND32 parent,
-                                     UINT32 wid )
+
+HWND32 WINAPI
+CreateStatusWindow32W (INT32 style, LPCWSTR text, HWND32 parent, UINT32 wid)
 {
-    return CreateWindow32W((LPCWSTR)STATUSCLASSNAME32W, text, style, 
+    return CreateWindow32W((LPCWSTR)STATUSCLASSNAME32W, text, style,
 			   CW_USEDEFAULT32, CW_USEDEFAULT32,
-			   CW_USEDEFAULT32, CW_USEDEFAULT32, 
+			   CW_USEDEFAULT32, CW_USEDEFAULT32,
 			   parent, wid, 0, 0);
 }
 
+
 /***********************************************************************
- *           CreateUpDownControl  (COMCTL32.16)
+ * CreateUpDownControl [COMCTL32.16] Creates an Up-Down control
+ *
+ * PARAMS
+ *     style
+ *     x
+ *     y
+ *     cx
+ *     cy
+ *     parent
+ *     id
+ *     inst
+ *     buddy
+ *     maxVal [I]
+ *     minVal [I]
+ *     curVal [I]
+ *
+ * RETURNS
+ *     Success: handle to the control
+ *     Failure: 0
  */
+
 HWND32 WINAPI
 CreateUpDownControl (DWORD style, INT32 x, INT32 y, INT32 cx, INT32 cy,
 		     HWND32 parent, INT32 id, HINSTANCE32 inst,
@@ -344,7 +400,10 @@
  * Registers the common controls.
  *
  * PARAMS
- *     None.
+ *     No parameters.
+ *
+ * RETURNS
+ *     No return values.
  *
  * NOTES
  *     This function is just a dummy.
@@ -364,7 +423,11 @@
  * Registers the common controls.
  *
  * PARAMS
- *     lpInitCtrls [I] pointer to a INITCOMMONCONTROLS structure.
+ *     lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
+ *
+ * RETURNS
+ *     Success: TRUE
+ *     Failure: FALSE
  *
  * NOTES
  *     Only the additinal common controls are registered by this function.
@@ -399,37 +462,36 @@
 	    case ICC_HOTKEY_CLASS:
 		break;
 
-      /* advanced classes - not included in Win95 */
-      case ICC_DATE_CLASSES:
-        TRACE (commctrl, "No month calendar class implemented!\n");
-        TRACE (commctrl, "No date picker class implemented!\n");
-        TRACE (commctrl, "No time picker class implemented!\n");
-        UPDOWN_Register ();
-        break;
+	    /* advanced classes - not included in Win95 */
+	    case ICC_DATE_CLASSES:
+		FIXME (commctrl, "No month calendar class implemented!\n");
+		FIXME (commctrl, "No date picker class implemented!\n");
+		FIXME (commctrl, "No time picker class implemented!\n");
+		break;
 
-      case ICC_USEREX_CLASSES:
-	COMBOEX_Register ();
-        break;
+	    case ICC_USEREX_CLASSES:
+		COMBOEX_Register ();
+		break;
 
-      case ICC_COOL_CLASSES:
-	REBAR_Register ();
-        break;
+	    case ICC_COOL_CLASSES:
+		REBAR_Register ();
+		break;
 
-      case ICC_INTERNET_CLASSES:
-        TRACE (commctrl, "No IPAddress class implemented!\n");
-        break;
+	    case ICC_INTERNET_CLASSES:
+		FIXME (commctrl, "No IPAddress class implemented!\n");
+		break;
 
-      case ICC_PAGESCROLLER_CLASS:
-	PAGER_Register ();
-        break;
+	    case ICC_PAGESCROLLER_CLASS:
+		PAGER_Register ();
+		break;
 
-      case ICC_NATIVEFNTCTL_CLASS:
-        TRACE (commctrl, "No native font class implemented!\n");
-        break;
+	    case ICC_NATIVEFNTCTL_CLASS:
+		FIXME (commctrl, "No native font class implemented!\n");
+		break;
 
-      default:
-        WARN (commctrl, "Unknown class! dwICC=0x%lX\n", dwMask);
-        break;
+	    default:
+		WARN (commctrl, "Unknown class! dwICC=0x%lX\n", dwMask);
+		break;
 	}
     }
 
@@ -438,10 +500,26 @@
 
 
 /***********************************************************************
- * CreateToolbarEx [COMCTL32.32]
+ * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
  *
+ * PARAMS
+ *     hwnd
+ *     style
+ *     wID
+ *     nBitmaps
+ *     hBMInst
+ *     wBMID
+ *     lpButtons
+ *     iNumButtons
+ *     dxButton
+ *     dyButton
+ *     dxBitmap
+ *     dyBitmap
+ *     uStructSize
  *
- *
+ * RETURNS
+ *     Success: handle to the tool bar control
+ *     Failure: 0
  */
 
 HWND32 WINAPI
@@ -600,10 +678,24 @@
 
 
 /***********************************************************************
- * CreateToolbar [COMCTL32.7]
+ * CreateToolbar [COMCTL32.7] Creates a tool bar control
  *
+ * PARAMS
+ *     hwnd
+ *     style
+ *     wID
+ *     nBitmaps
+ *     hBMInst
+ *     wBMID
+ *     lpButtons
+ *     iNumButtons
  *
+ * RETURNS
+ *     Success: handle to the tool bar control
+ *     Failure: 0
  *
+ * NOTES
+ *     Do not use this functions anymore. Use CreateToolbarEx instead.
  */
 
 HWND32 WINAPI
@@ -625,22 +717,25 @@
  * PARAMS
  *     pdvi [O] pointer to version information structure.
  *
- * REURNS
+ * RETURNS
  *     Success: S_OK
  *     Failure: E_INVALIDARG
+ *
+ * NOTES
+ *     Returns version of a comctl32.dll from IE4.01 SP1.
  */
 
 HRESULT WINAPI
 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
 {
     if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
-        WARN(ver, "wrong DLLVERSIONINFO size from app");
+        WARN (commctrl, "wrong DLLVERSIONINFO size from app");
 	return E_INVALIDARG;
     }
 
     pdvi->dwMajorVersion = 4;
     pdvi->dwMinorVersion = 72;
-    pdvi->dwBuildNumber = 2106;
+    pdvi->dwBuildNumber = 3110;
     pdvi->dwPlatformID = 1;
 
     TRACE (commctrl, "%lu.%lu.%lu.%lu\n",
diff --git a/dlls/comctl32/header.c b/dlls/comctl32/header.c
index 813512c..a2d86fc 100644
--- a/dlls/comctl32/header.c
+++ b/dlls/comctl32/header.c
@@ -5,7 +5,7 @@
  *
  *  TODO:
  *   - Imagelist support (partially).
- *   - Callback items.
+ *   - Callback items (under construction).
  *   - Order list support.
  *   - Control specific cursors (over dividers).
  *   - Hottrack support (partially).
@@ -22,7 +22,6 @@
 #include "windows.h"
 #include "commctrl.h"
 #include "header.h"
-#include "heap.h"
 #include "win.h"
 #include "debug.h"
 
@@ -446,7 +445,7 @@
 HEADER_SendHeaderNotify (WND *wndPtr, UINT32 code, INT32 iItem)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);   
-    NMHEADERA nmhdr;
+    NMHEADER32A nmhdr;
     HDITEM32A nmitem;
 
     nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
@@ -455,11 +454,13 @@
     nmhdr.iItem = iItem;
     nmhdr.iButton = 0;
     nmhdr.pitem = &nmitem;
-    nmitem.mask = infoPtr->items[iItem].mask;
+    nmitem.mask = 0;
     nmitem.cxy = infoPtr->items[iItem].cxy;
     nmitem.hbm = infoPtr->items[iItem].hbm;
-    nmitem.pszText = infoPtr->items[iItem].pszText;
-    nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax;
+    nmitem.pszText = NULL;
+    nmitem.cchTextMax = 0;
+//    nmitem.pszText = infoPtr->items[iItem].pszText;
+//    nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax;
     nmitem.fmt = infoPtr->items[iItem].fmt;
     nmitem.lParam = infoPtr->items[iItem].lParam;
     nmitem.iOrder = infoPtr->items[iItem].iOrder;
@@ -473,7 +474,7 @@
 static BOOL32
 HEADER_SendClickNotify (WND *wndPtr, UINT32 code, INT32 iItem)
 {
-    NMHEADERA nmhdr;
+    NMHEADER32A nmhdr;
 
     nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
     nmhdr.hdr.idFrom = wndPtr->wIDmenu;
@@ -499,21 +500,19 @@
 HEADER_DeleteItem (WND *wndPtr, WPARAM32 wParam)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
+    INT32 iItem = (INT32)wParam;
     HDC32 hdc;
-    INT32 iItem;
-
-    iItem = (INT32)wParam;
 
     TRACE(header, "[iItem=%d]\n", iItem);
     
-    if ((iItem < 0) || (iItem > infoPtr->uNumItem - 1))
+    if ((iItem < 0) || (iItem >= (INT32)infoPtr->uNumItem))
         return FALSE;
 
     if (infoPtr->uNumItem == 1) {
         TRACE(header, "Simple delete!\n");
         if (infoPtr->items[0].pszText)
-            HeapFree (GetProcessHeap (), 0, infoPtr->items[0].pszText);
-        HeapFree (GetProcessHeap (), 0, infoPtr->items);
+            COMCTL32_Free (infoPtr->items[0].pszText);
+        COMCTL32_Free (infoPtr->items);
         infoPtr->items = 0;
         infoPtr->uNumItem = 0;
     }
@@ -522,11 +521,10 @@
         TRACE(header, "Complex delete! [iItem=%d]\n", iItem);
 
         if (infoPtr->items[iItem].pszText)
-            HeapFree (GetProcessHeap (), 0, infoPtr->items[iItem].pszText);
+            COMCTL32_Free (infoPtr->items[iItem].pszText);
 
         infoPtr->uNumItem--;
-        infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                    sizeof (HEADER_ITEM) * infoPtr->uNumItem);
+        infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
         /* pre delete copy */
         if (iItem > 0) {
             memcpy (&infoPtr->items[0], &oldItems[0],
@@ -539,7 +537,7 @@
                     (infoPtr->uNumItem - iItem) * sizeof(HEADER_ITEM));
         }
 
-        HeapFree (GetProcessHeap (), 0, oldItems);
+        COMCTL32_Free (oldItems);
     }
 
     HEADER_SetItemBounds (wndPtr);
@@ -565,60 +563,45 @@
 HEADER_GetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
-    HDITEM32A *phdi;
-    INT32     iItem;
-    UINT32    uMask;
+    HDITEM32A   *phdi = (HDITEM32A*)lParam;
+    INT32       nItem = (INT32)wParam;
+    HEADER_ITEM *lpItem;
 
-    phdi = (HDITEM32A*)lParam;
-    iItem = (INT32)wParam;
-
-    if (phdi == NULL)
+    if (!phdi)
 	return FALSE;
-    if ((iItem < 0) || (iItem > infoPtr->uNumItem - 1))
+    if ((nItem < 0) || (nItem >= (INT32)infoPtr->uNumItem))
         return FALSE;
 
-    TRACE (header, "[iItem=%d]\n", iItem);
+    TRACE (header, "[nItem=%d]\n", nItem);
 
-    uMask = phdi->mask;
-    if (uMask == 0)
+    if (phdi->mask == 0)
 	return TRUE;
-    phdi->mask = 0;
 
-    if (uMask & infoPtr->items[iItem].mask & HDI_BITMAP) {
-	phdi->hbm = infoPtr->items[iItem].hbm;
-        phdi->mask |= HDI_BITMAP;
+    lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
+    if (phdi->mask & HDI_BITMAP)
+	phdi->hbm = lpItem->hbm;
+
+    if (phdi->mask & HDI_FORMAT)
+	phdi->fmt = lpItem->fmt;
+
+    if (phdi->mask & HDI_WIDTH)
+	phdi->cxy = lpItem->cxy;
+
+    if (phdi->mask & HDI_LPARAM)
+	phdi->lParam = lpItem->lParam;
+
+    if (phdi->mask & HDI_TEXT) {
+	if (lpItem->pszText != LPSTR_TEXTCALLBACK32A)
+	    lstrcpyn32A (phdi->pszText, lpItem->pszText, phdi->cchTextMax);
+	else
+	    phdi->pszText = LPSTR_TEXTCALLBACK32A;
     }
 
-    if (uMask & infoPtr->items[iItem].mask & HDI_FORMAT) {
-	phdi->fmt = infoPtr->items[iItem].fmt;
-        phdi->mask |= HDI_FORMAT;
-    }
+    if (phdi->mask & HDI_IMAGE)
+	phdi->iImage = lpItem->iImage;
 
-    if (uMask & infoPtr->items[iItem].mask & HDI_WIDTH) {
-	phdi->cxy = infoPtr->items[iItem].cxy;
-        phdi->mask |= HDI_WIDTH;
-    }
-
-    if (uMask & infoPtr->items[iItem].mask & HDI_LPARAM) {
-	phdi->lParam = infoPtr->items[iItem].lParam;
-        phdi->mask |= HDI_LPARAM;
-    }
-
-    if (uMask & infoPtr->items[iItem].mask & HDI_TEXT) {
-	phdi->pszText = infoPtr->items[iItem].pszText;
-	phdi->cchTextMax = infoPtr->items[iItem].cchTextMax;
-        phdi->mask |= HDI_TEXT;
-    }
-
-    if (uMask & infoPtr->items[iItem].mask & HDI_IMAGE) {
-	phdi->iImage = infoPtr->items[iItem].iImage;
-        phdi->mask |= HDI_IMAGE;
-    }
-
-    if (uMask & infoPtr->items[iItem].mask & HDI_ORDER) {
-	phdi->iOrder = infoPtr->items[iItem].iOrder;
-        phdi->mask |= HDI_ORDER;
-    }
+    if (phdi->mask & HDI_ORDER)
+	phdi->iOrder = lpItem->iOrder;
 
     return TRUE;
 }
@@ -637,13 +620,10 @@
 HEADER_GetItemRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
-    INT32 iItem;
-    LPRECT32 lpRect;
+    INT32 iItem = (INT32)wParam;
+    LPRECT32 lpRect = (LPRECT32)lParam;
 
-    iItem = (INT32)wParam;
-    lpRect = (LPRECT32)lParam;
-
-    if ((iItem < 0) || (iItem > infoPtr->uNumItem - 1))
+    if ((iItem < 0) || (iItem >= (INT32)infoPtr->uNumItem))
         return FALSE;
 
     lpRect->left   = infoPtr->items[iItem].rect.left;
@@ -670,70 +650,72 @@
 HEADER_InsertItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
-    HDITEM32A *phdi = (HDITEM32A*)lParam;
-    INT32     iItem = (INT32)wParam;
-    HDC32     hdc;
-    INT32     len;
+    HDITEM32A   *phdi = (HDITEM32A*)lParam;
+    INT32       nItem = (INT32)wParam;
+    HEADER_ITEM *lpItem;
+    HDC32       hdc;
+    INT32       len;
 
-    if (phdi == NULL) return -1;
-    if (iItem < 0) return -1;
-    if (iItem > infoPtr->uNumItem)
-        iItem = infoPtr->uNumItem;
+    if ((phdi == NULL) || (nItem < 0))
+	return -1;
+
+    if (nItem > infoPtr->uNumItem)
+        nItem = infoPtr->uNumItem;
 
     if (infoPtr->uNumItem == 0) {
-        infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                    sizeof (HEADER_ITEM));
+        infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM));
         infoPtr->uNumItem++;
     }
     else {
         HEADER_ITEM *oldItems = infoPtr->items;
 
         infoPtr->uNumItem++;
-        infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                    sizeof (HEADER_ITEM) * infoPtr->uNumItem);
+        infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
         /* pre insert copy */
-        if (iItem > 0) {
+        if (nItem > 0) {
             memcpy (&infoPtr->items[0], &oldItems[0],
-                    iItem * sizeof(HEADER_ITEM));
+                    nItem * sizeof(HEADER_ITEM));
         }
 
         /* post insert copy */
-        if (iItem < infoPtr->uNumItem - 1) {
-            memcpy (&infoPtr->items[iItem+1], &oldItems[iItem],
-                    (infoPtr->uNumItem - iItem) * sizeof(HEADER_ITEM));
+        if (nItem < infoPtr->uNumItem - 1) {
+            memcpy (&infoPtr->items[nItem+1], &oldItems[nItem],
+                    (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM));
         }
 
-        HeapFree (GetProcessHeap (), 0, oldItems);
+	COMCTL32_Free (oldItems);
     }
 
-    infoPtr->items[iItem].bDown = FALSE;
+    lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
+    lpItem->bDown = FALSE;
 
-    infoPtr->items[iItem].mask = phdi->mask;
     if (phdi->mask & HDI_WIDTH)
-        infoPtr->items[iItem].cxy = phdi->cxy;
+	lpItem->cxy = phdi->cxy;
 
     if (phdi->mask & HDI_TEXT) {
-        len = lstrlen32A (phdi->pszText);
-        infoPtr->items[iItem].pszText =
-            HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len+1);
-        lstrcpy32A (infoPtr->items[iItem].pszText, phdi->pszText);
-        infoPtr->items[iItem].cchTextMax = phdi->cchTextMax;
+	if (phdi->pszText != LPSTR_TEXTCALLBACK32A) {
+	    len = lstrlen32A (phdi->pszText);
+	    lpItem->pszText = COMCTL32_Alloc (len+1);
+	    lstrcpy32A (lpItem->pszText, phdi->pszText);
+	}
+	else
+	    lpItem->pszText = LPSTR_TEXTCALLBACK32A;
     }
 
     if (phdi->mask & HDI_FORMAT)
-        infoPtr->items[iItem].fmt = phdi->fmt;
+	lpItem->fmt = phdi->fmt;
 
     if (phdi->mask & HDI_BITMAP)
-        infoPtr->items[iItem].hbm = phdi->hbm;
+        lpItem->hbm = phdi->hbm;
 
     if (phdi->mask & HDI_LPARAM)
-        infoPtr->items[iItem].lParam = phdi->lParam;
+        lpItem->lParam = phdi->lParam;
 
     if (phdi->mask & HDI_IMAGE)
-        infoPtr->items[iItem].iImage = phdi->iImage;
+        lpItem->iImage = phdi->iImage;
 
     if (phdi->mask & HDI_ORDER)
-        infoPtr->items[iItem].iOrder = phdi->iOrder;
+        lpItem->iOrder = phdi->iOrder;
 
     HEADER_SetItemBounds (wndPtr);
 
@@ -741,7 +723,7 @@
     HEADER_Refresh (wndPtr, hdc);
     ReleaseDC32 (wndPtr->hwndSelf, hdc);
 
-    return iItem;
+    return nItem;
 }
 
 
@@ -798,60 +780,52 @@
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
     HDITEM32A *phdi = (HDITEM32A*)lParam;
-    INT32 iItem = (INT32)wParam;
+    INT32 nItem = (INT32)wParam;
+    HEADER_ITEM *lpItem;
     HDC32 hdc;
 
     if (phdi == NULL)
 	return FALSE;
-    if ((iItem < 0) || (iItem > infoPtr->uNumItem - 1))
+    if ((nItem < 0) || (nItem >= (INT32)infoPtr->uNumItem))
         return FALSE;
 
-    TRACE (header, "[iItem=%d]\n", iItem);
+    TRACE (header, "[nItem=%d]\n", nItem);
 
-    if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, iItem))
+    if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, nItem))
 	return FALSE;
 
-    if (phdi->mask & HDI_BITMAP) {
-	infoPtr->items[iItem].hbm = phdi->hbm;
-	infoPtr->items[iItem].mask  |= HDI_BITMAP;
-    }
+    lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
+    if (phdi->mask & HDI_BITMAP)
+	lpItem->hbm = phdi->hbm;
 
-    if (phdi->mask & HDI_FORMAT) {
-	infoPtr->items[iItem].fmt = phdi->fmt;
-	infoPtr->items[iItem].mask  |= HDI_FORMAT;
-    }
+    if (phdi->mask & HDI_FORMAT)
+	lpItem->fmt = phdi->fmt;
 
-    if (phdi->mask & HDI_LPARAM) {
-	infoPtr->items[iItem].lParam = phdi->lParam;
-	infoPtr->items[iItem].mask  |= HDI_LPARAM;
-    }
+    if (phdi->mask & HDI_LPARAM)
+	lpItem->lParam = phdi->lParam;
 
     if (phdi->mask & HDI_TEXT) {
-        INT32 len = lstrlen32A (phdi->pszText);
-        if (infoPtr->items[iItem].pszText)
-	    HeapFree (GetProcessHeap (), 0, infoPtr->items[iItem].pszText);
-        infoPtr->items[iItem].pszText =
-            HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len+1);
-        lstrcpy32A (infoPtr->items[iItem].pszText, phdi->pszText);
-        infoPtr->items[iItem].cchTextMax = phdi->cchTextMax;
+	if (phdi->pszText != LPSTR_TEXTCALLBACK32A) {
+	    INT32 len = lstrlen32A (phdi->pszText);
+	    if (lpItem->pszText)
+		COMCTL32_Free (lpItem->pszText);
+	    lpItem->pszText = COMCTL32_Alloc (len+1);
+	    lstrcpy32A (lpItem->pszText, phdi->pszText);
+	}
+	else
+	    lpItem->pszText = LPSTR_TEXTCALLBACK32A;
     }
 
-    if (phdi->mask & HDI_WIDTH) {
-	infoPtr->items[iItem].cxy = phdi->cxy;
-	infoPtr->items[iItem].mask  |= HDI_WIDTH;
-    }
+    if (phdi->mask & HDI_WIDTH)
+	lpItem->cxy = phdi->cxy;
 
-    if (phdi->mask & HDI_IMAGE) {
-	infoPtr->items[iItem].iImage = phdi->iImage;
-	infoPtr->items[iItem].mask  |= HDI_IMAGE;
-    }
+    if (phdi->mask & HDI_IMAGE)
+	lpItem->iImage = phdi->iImage;
 
-    if (phdi->mask & HDI_ORDER) {
-	infoPtr->items[iItem].iOrder = phdi->iOrder;
-	infoPtr->items[iItem].mask  |= HDI_ORDER;
-    }
+    if (phdi->mask & HDI_ORDER)
+	lpItem->iOrder = phdi->iOrder;
 
-    HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A, iItem);
+    HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGED32A, nItem);
 
     HEADER_SetItemBounds (wndPtr);
     hdc = GetDC32 (wndPtr->hwndSelf);
@@ -870,8 +844,7 @@
     HFONT32 hOldFont;
     HDC32   hdc;
 
-    infoPtr = (HEADER_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                        sizeof(HEADER_INFO));
+    infoPtr = (HEADER_INFO *)COMCTL32_Alloc (sizeof(HEADER_INFO));
     wndPtr->wExtra[0] = (DWORD)infoPtr;
 
     infoPtr->uNumItem = 0;
@@ -902,26 +875,28 @@
 HEADER_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
-    INT32 iItem;
+    HEADER_ITEM *lpItem;
+    INT32 nItem;
 
     if (infoPtr->items) {
-        for (iItem = 0; iItem < infoPtr->uNumItem; iItem++) {
-            if (infoPtr->items[iItem].pszText)
-                HeapFree (GetProcessHeap (), 0, infoPtr->items[iItem].pszText);
+	lpItem = (HEADER_ITEM*)infoPtr->items;
+        for (nItem = 0; nItem < infoPtr->uNumItem; nItem++, lpItem++) {
+	    if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACK32A))
+		COMCTL32_Free (lpItem->pszText);
         }
-        HeapFree (GetProcessHeap (), 0, infoPtr->items);
+        COMCTL32_Free (infoPtr->items);
     }
 
     if (infoPtr->himl)
 	ImageList_Destroy (infoPtr->himl);
 
-    HeapFree (GetProcessHeap (), 0, infoPtr);
+    COMCTL32_Free (infoPtr);
 
     return 0;
 }
 
 
-static LRESULT
+static __inline__ LRESULT
 HEADER_GetFont (WND *wndPtr)
 {
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
@@ -935,16 +910,16 @@
 {
     POINT32 pt;
     UINT32  flags;
-    INT32   iItem;
+    INT32   nItem;
 
     pt.x = (INT32)LOWORD(lParam); 
     pt.y = (INT32)HIWORD(lParam);
-    HEADER_InternalHitTest (wndPtr, &pt, &flags, &iItem);
+    HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
 
     if ((wndPtr->dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER))
-	HEADER_SendHeaderNotify (wndPtr, HDN_ITEMDBLCLICK32A, iItem);
+	HEADER_SendHeaderNotify (wndPtr, HDN_ITEMDBLCLICK32A, nItem);
     else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
-	HEADER_SendHeaderNotify (wndPtr, HDN_DIVIDERDBLCLICK32A, iItem);
+	HEADER_SendHeaderNotify (wndPtr, HDN_DIVIDERDBLCLICK32A, nItem);
 
     return 0;
 }
@@ -956,45 +931,45 @@
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
     POINT32 pt;
     UINT32  flags;
-    INT32   iItem;
+    INT32   nItem;
     HDC32   hdc;
 
     pt.x = (INT32)LOWORD(lParam); 
     pt.y = (INT32)HIWORD(lParam);
-    HEADER_InternalHitTest (wndPtr, &pt, &flags, &iItem);
+    HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
 
     if ((wndPtr->dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER)) {
 	SetCapture32 (wndPtr->hwndSelf);
 	infoPtr->bCaptured = TRUE;   
 	infoPtr->bPressed  = TRUE;
-	infoPtr->iMoveItem = iItem;
+	infoPtr->iMoveItem = nItem;
 
-	infoPtr->items[iItem].bDown = TRUE;
+	infoPtr->items[nItem].bDown = TRUE;
 
 	/* Send WM_CUSTOMDRAW */
 	hdc = GetDC32 (wndPtr->hwndSelf);
-	HEADER_RefreshItem (wndPtr, hdc, iItem);
+	HEADER_RefreshItem (wndPtr, hdc, nItem);
 	ReleaseDC32 (wndPtr->hwndSelf, hdc);
 
-	TRACE (header, "Pressed item %d!\n", iItem);
+	TRACE (header, "Pressed item %d!\n", nItem);
     } 
     else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN)) {
-	if (!(HEADER_SendHeaderNotify (wndPtr, HDN_BEGINTRACK32A, iItem))) {
+	if (!(HEADER_SendHeaderNotify (wndPtr, HDN_BEGINTRACK32A, nItem))) {
 	    SetCapture32 (wndPtr->hwndSelf);
 	    infoPtr->bCaptured = TRUE;   
 	    infoPtr->bTracking = TRUE;
-	    infoPtr->iMoveItem = iItem;
-	    infoPtr->nOldWidth = infoPtr->items[iItem].cxy;
-	    infoPtr->xTrackOffset = infoPtr->items[iItem].rect.right - pt.x;
+	    infoPtr->iMoveItem = nItem;
+	    infoPtr->nOldWidth = infoPtr->items[nItem].cxy;
+	    infoPtr->xTrackOffset = infoPtr->items[nItem].rect.right - pt.x;
 
 	    if (!(wndPtr->dwStyle & HDS_FULLDRAG)) {
-		infoPtr->xOldTrack = infoPtr->items[iItem].rect.right;
+		infoPtr->xOldTrack = infoPtr->items[nItem].rect.right;
 		hdc = GetDC32 (wndPtr->hwndSelf);
 		HEADER_DrawTrackLine (wndPtr, hdc, infoPtr->xOldTrack);
 		ReleaseDC32 (wndPtr->hwndSelf, hdc);
 	    }
 
-	    TRACE (header, "Begin tracking item %d!\n", iItem);
+	    TRACE (header, "Begin tracking item %d!\n", nItem);
 	}
     }
 
@@ -1008,15 +983,15 @@
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
     POINT32 pt;
     UINT32  flags;
-    INT32   iItem, nWidth;
+    INT32   nItem, nWidth;
     HDC32   hdc;
 
     pt.x = (INT32)LOWORD(lParam);
     pt.y = (INT32)HIWORD(lParam);
-    HEADER_InternalHitTest (wndPtr, &pt, &flags, &iItem);
+    HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
 
     if (infoPtr->bPressed) {
-	if ((iItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER)) {
+	if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER)) {
 	    infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
 	    hdc = GetDC32 (wndPtr->hwndSelf);
 	    HEADER_RefreshItem (wndPtr, hdc, infoPtr->iMoveItem);
@@ -1040,8 +1015,7 @@
 	    if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, infoPtr->iMoveItem))
 		infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
 	    else {
-		nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left +
-		infoPtr->xTrackOffset;
+		nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
 		if (nWidth < 0)
 		    nWidth = 0;
 		infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
@@ -1071,16 +1045,16 @@
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
     POINT32 pt;
     UINT32  flags;
-    INT32   iItem, nWidth;
+    INT32   nItem, nWidth;
     HDC32   hdc;
 
     pt.x = (INT32)LOWORD(lParam);
     pt.y = (INT32)HIWORD(lParam);
-    HEADER_InternalHitTest (wndPtr, &pt, &flags, &iItem);
+    HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
 
     if ((wndPtr->dwStyle & HDS_BUTTONS) && (wndPtr->dwStyle & HDS_HOTTRACK)) {
 	if (flags & (HHT_ONHEADER | HHT_ONDIVIDER | HHT_ONDIVOPEN))
-	    infoPtr->iHotItem = iItem;
+	    infoPtr->iHotItem = nItem;
 	else
 	    infoPtr->iHotItem = -1;
 	hdc = GetDC32 (wndPtr->hwndSelf);
@@ -1090,7 +1064,7 @@
 
     if (infoPtr->bCaptured) {
 	if (infoPtr->bPressed) {
-	    if ((iItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER))
+	    if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER))
 		infoPtr->items[infoPtr->iMoveItem].bDown = TRUE;
 	    else
 		infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
@@ -1105,8 +1079,7 @@
 		if (HEADER_SendHeaderNotify (wndPtr, HDN_ITEMCHANGING32A, infoPtr->iMoveItem))
 		    infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
 		else {
-		    nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left +
-		    infoPtr->xTrackOffset;
+		    nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
 		    if (nWidth < 0)
 			nWidth = 0;
 		    infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
@@ -1170,14 +1143,14 @@
     HEADER_INFO *infoPtr = HEADER_GetInfoPtr(wndPtr);
     POINT32 pt;
     UINT32  flags;
-    INT32   iItem;
+    INT32   nItem;
 
     TRACE (header, "code=0x%X  id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
 
     GetCursorPos32 (&pt);
     ScreenToClient32 (wndPtr->hwndSelf, &pt);
 
-    HEADER_InternalHitTest (wndPtr, &pt, &flags, &iItem);
+    HEADER_InternalHitTest (wndPtr, &pt, &flags, &nItem);
 
     if (flags == HHT_ONDIVIDER)
         SetCursor32 (infoPtr->hcurDivider);
@@ -1238,18 +1211,25 @@
 	case HDM_GETITEM32A:
 	    return HEADER_GetItem32A (wndPtr, wParam, lParam);
 
+//	case HDM_GETITEM32W:
+
 	case HDM_GETITEMCOUNT:
 	    return HEADER_GetItemCount (wndPtr);
 
 	case HDM_GETITEMRECT:
 	    return HEADER_GetItemRect (wndPtr, wParam, lParam);
 
+//	case HDM_GETORDERARRAY:
+//	case HDM_GETUNICODEFORMAT:
+
 	case HDM_HITTEST:
 	    return HEADER_HitTest (wndPtr, wParam, lParam);
 
 	case HDM_INSERTITEM32A:
 	    return HEADER_InsertItem32A (wndPtr, wParam, lParam);
 
+//	case HDM_INSERTITEM32W:
+
 	case HDM_LAYOUT:
 	    return HEADER_Layout (wndPtr, wParam, lParam);
 
@@ -1259,6 +1239,10 @@
 	case HDM_SETITEM32A:
 	    return HEADER_SetItem32A (wndPtr, wParam, lParam);
 
+//	case HDM_SETITEM32W:
+//	case HDM_SETORDERARRAY:
+//	case HDM_SETUNICODEFORMAT:
+
 
         case WM_CREATE:
             return HEADER_Create (wndPtr, wParam, lParam);
diff --git a/dlls/comctl32/imagelist.c b/dlls/comctl32/imagelist.c
index 6fbbd33..0aec07d 100644
--- a/dlls/comctl32/imagelist.c
+++ b/dlls/comctl32/imagelist.c
@@ -5,9 +5,7 @@
  *
  *  TODO:
  *    - Fix xBitmap and yBitmap in ImageList_DrawIndirect.
- *    - Fix ILD_TRANSPARENT error in ImageList_DrawIndirect.
- *    - Fix ImageList_GetIcon (might be a result of the
- *      ILD_TRANSPARENT error in ImageList_DrawIndirect).
+ *    - Fix ImageList_GetIcon.
  *    - Fix drag functions.
  *    - Fix ImageList_Read and ImageList_Write.
  *    - Fix ImageList_SetFilter (undocumented).
@@ -146,11 +144,11 @@
 {
     HDC32    hdcSrc, hdcDst;
     INT32    nFirstIndex, nImageCount;
-    INT32    nStartX, nRunX, nRunY;
+    INT32    nStartX;
     BITMAP32 bmp;
 
-    if (himl == NULL) return (-1);
-    if (hbmImage == 0) return (-1);
+    if (!himl || !hbmImage)
+	return -1;
 
     GetObject32A (hbmImage, sizeof(BITMAP32), (LPVOID)&bmp);
     nImageCount = bmp.bmWidth / himl->cx;
@@ -158,56 +156,33 @@
     if (himl->cCurImage + nImageCount >= himl->cMaxImage)
         IMAGELIST_InternalExpandBitmaps (himl, nImageCount);
 
+    nStartX = himl->cCurImage * himl->cx;
+
     hdcSrc = CreateCompatibleDC32 (0);
     hdcDst = CreateCompatibleDC32 (0);
 
+    /* copy image bitmap */
     SelectObject32 (hdcDst, himl->hbmImage);
     SelectObject32 (hdcSrc, hbmImage);
-
     BitBlt32 (hdcDst, himl->cCurImage * himl->cx, 0,
               bmp.bmWidth, himl->cy, hdcSrc, 0, 0, SRCCOPY);
           
     if (himl->hbmMask) {
         if (hbmMask) {
+	    /* copy mask bitmap */
             SelectObject32 (hdcDst, himl->hbmMask);
             SelectObject32 (hdcSrc, hbmMask);
-            BitBlt32 (hdcDst, himl->cCurImage * himl->cx, 0,
-                      bmp.bmWidth, himl->cy, hdcSrc, 0, 0, SRCCOPY);
-
-            /* fix transparent areas of the image bitmap*/
-            SelectObject32 (hdcSrc, himl->hbmMask);
-            SelectObject32 (hdcDst, himl->hbmImage);
-            nStartX = himl->cCurImage * himl->cx;
-
-            for (nRunY = 0; nRunY < himl->cy; nRunY++) {
-                for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++) {
-                    if (GetPixel32 (hdcSrc, nStartX + nRunX, nRunY) !=
-                        RGB(0, 0, 0))
-                        SetPixel32 (hdcDst, nStartX + nRunX, nRunY, 
-                                    RGB(0, 0, 0));
-                }
-            }
+            BitBlt32 (hdcDst, nStartX, 0, bmp.bmWidth, himl->cy,
+		      hdcSrc, 0, 0, SRCCOPY);
         }
         else {
-            /* create mask from the imagelist's background color */
+	    /* copy monochrome image to the mask bitmap */
             SelectObject32 (hdcDst, himl->hbmMask);
-            SelectObject32 (hdcSrc, himl->hbmImage);
-            nStartX = himl->cCurImage * himl->cx;
-            for (nRunY = 0; nRunY < himl->cy; nRunY++) {
-                for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++) {
-                    if (GetPixel32 (hdcSrc, nStartX + nRunX, nRunY) ==
-                        himl->clrBk)
-                    {
-                        SetPixel32 (hdcSrc, nStartX + nRunX, nRunY, 
-                                    RGB(0, 0, 0));
-                        SetPixel32 (hdcDst, nStartX + nRunX, nRunY, 
-                                    RGB(255, 255, 255));
-                    }
-                    else
-                        SetPixel32 (hdcDst, nStartX + nRunX, nRunY, 
-                                    RGB(0, 0, 0));        
-                }
-            }
+            SelectObject32 (hdcSrc, hbmImage);
+	    SetBkColor32 (hdcSrc, GetNearestColor32 (hdcSrc,
+			  GetPixel32 (hdcSrc, 0, 0)));
+	    BitBlt32 (hdcDst, nStartX, 0, bmp.bmWidth, himl->cy,
+		      hdcSrc, nStartX, 0, SRCCOPY);
         }
     }
 
@@ -217,7 +192,7 @@
     nFirstIndex = himl->cCurImage;
     himl->cCurImage += nImageCount;
 
-    return (nFirstIndex);
+    return nFirstIndex;
 }
 
 
@@ -249,9 +224,9 @@
  * specified bitmap using the mask color.
  *
  * PARAMS
- *     himl     [I] image list handle.
- *     hbmImage [I] image bitmap handle.
- *     clrMask  [I] mask color.
+ *     himl    [I] handle to image list.
+ *     hBitmap [I] handle to bitmap
+ *     clrMask [I] mask color.
  *
  * RETURNS
  *     Success: Index of the first new image.
@@ -259,20 +234,18 @@
  */
 
 INT32 WINAPI
-ImageList_AddMasked (HIMAGELIST himl, HBITMAP32 hbmImage, COLORREF clrMask)
+ImageList_AddMasked (HIMAGELIST himl, HBITMAP32 hBitmap, COLORREF clrMask)
 {
-    HDC32    hdcImageList, hdcImage, hdcMask;
+    HDC32    hdcImage, hdcMask, hdcBitmap;
     INT32    nIndex, nImageCount;
     BITMAP32 bmp;
-    INT32    nStartX, nRunX, nRunY;
-    COLORREF bkColor;
 
     if (himl == NULL)
-	return (-1);
+	return -1;
 
-    bkColor = (clrMask == CLR_NONE) ? himl->clrBk : clrMask;
+    if (!GetObject32A (hBitmap, sizeof(BITMAP32), &bmp))
+	return -1;
 
-    GetObject32A (hbmImage, sizeof(BITMAP32), &bmp);
     nImageCount = bmp.bmWidth / himl->cx;
 
     if (himl->cCurImage + nImageCount >= himl->cMaxImage)
@@ -281,39 +254,34 @@
     nIndex = himl->cCurImage;
     himl->cCurImage += nImageCount;
 
-    hdcImageList = CreateCompatibleDC32 (0);
-    hdcImage = CreateCompatibleDC32 (0);
+    hdcImage  = CreateCompatibleDC32 (0);
+    hdcBitmap = CreateCompatibleDC32 (0);
 
-    SelectObject32 (hdcImageList, himl->hbmImage);
-    SelectObject32 (hdcImage, hbmImage);
-    BitBlt32 (hdcImageList, nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
-              hdcImage, 0, 0, SRCCOPY);
+    SelectObject32 (hdcBitmap, hBitmap);
+    SelectObject32 (hdcImage, himl->hbmImage);
+    BitBlt32 (hdcImage, nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
+              hdcBitmap, 0, 0, SRCCOPY);
 
     if (himl->hbmMask) {
-        /* create Mask */
+	COLORREF bkColor = (clrMask != CLR_DEFAULT) ? clrMask :
+	    GetNearestColor32 (hdcBitmap, GetPixel32 (hdcBitmap, 0, 0));
+
+	/* create mask from image */
         hdcMask = CreateCompatibleDC32 (0);
         SelectObject32 (hdcMask, himl->hbmMask);
-        nStartX = nIndex * himl->cx;
-        for (nRunY = 0; nRunY < himl->cy; nRunY++) {
-            for (nRunX = 0; nRunX < bmp.bmWidth; nRunX++) {
-                if (GetPixel32 (hdcImageList, nStartX + nRunX, nRunY) ==
-                    bkColor) {
-                    SetPixel32 (hdcImageList, nStartX + nRunX, nRunY,
-                                RGB(0, 0, 0));
-                    SetPixel32 (hdcMask, nStartX + nRunX, nRunY,
-                                RGB(255, 255, 255));
-                }
-                else
-                    SetPixel32 (hdcMask, nStartX + nRunX, nRunY, RGB(0, 0, 0));
-            }
-        }
+
+	/* create monochrome image to the mask bitmap */
+	SetBkColor32 (hdcBitmap, bkColor);
+	BitBlt32 (hdcMask, nIndex * himl->cx, 0, bmp.bmWidth, himl->cy,
+		  hdcBitmap, 0, 0, SRCCOPY);
+
         DeleteDC32 (hdcMask);
     }
 
-    DeleteDC32 (hdcImageList);
     DeleteDC32 (hdcImage);
+    DeleteDC32 (hdcBitmap);
   
-    return (nIndex);
+    return nIndex;
 }
 
 
@@ -969,6 +937,8 @@
     {
 	/* draw the mask */
 	SelectObject32 (hdcImageList, himlLocal->hbmMask);
+	SetBkColor32 (hdcImageList, RGB(255, 255, 255));
+	SetTextColor32 (hdcImageList, RGB(0, 0, 0));
 	BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
 		  hdcImageList, himlLocal->cx * pimldp->i, 0,
 		  bMaskTrans ? SRCAND : SRCCOPY);
@@ -989,8 +959,7 @@
         }
 
         BitBlt32 (pimldp->hdcDst, pimldp->x, pimldp->y, cx, cy,
-                  hdcImageList, himlLocal->cx * pimldp->i, 0,
-                  SRCPAINT);
+                  hdcImageList, himlLocal->cx * pimldp->i, 0, SRCPAINT);
 
         if (bBlend25 || bBlend50)
         {
@@ -1225,7 +1194,7 @@
 {
     ICONINFO ii;
     HICON32  hIcon;
-    HDC32    hdc;
+    HDC32    hdcSrc, hdcDst;
     INT32    nWidth, nHeight;
 
     if (himl == NULL) return 0;
@@ -1234,27 +1203,36 @@
     nWidth = GetSystemMetrics32 (SM_CXICON);
     nHeight = GetSystemMetrics32 (SM_CYICON);
 
+    hdcSrc = CreateCompatibleDC32(0);
+    hdcDst = CreateCompatibleDC32(0);
+
     ii.fIcon = TRUE;
     ii.xHotspot = 0;
     ii.yHotspot = 0;
-    ii.hbmMask  = CreateBitmap32 (nWidth, nHeight, 1, 1, NULL);
-    ii.hbmColor = CreateBitmap32 (nWidth, nHeight, 1, himl->uBitsPixel, NULL);
+    ii.hbmMask  = CreateCompatibleBitmap32 (hdcDst, nWidth, nHeight);
+    ii.hbmColor = CreateCompatibleBitmap32 (hdcDst, nWidth, nHeight);
 
-    hdc = CreateCompatibleDC32(0);
-
-    /* draw image*/
-    SelectObject32 (hdc, ii.hbmColor);
-    PatBlt32 (hdc, 0, 0, nWidth, nHeight, BLACKNESS);
-    ImageList_Draw (himl, i, hdc, 0, 0, fStyle | ILD_TRANSPARENT);
 
     /* draw mask*/
-    SelectObject32 (hdc, ii.hbmMask);
-    PatBlt32 (hdc, 0, 0, nWidth, nHeight, WHITENESS);
-    ImageList_Draw (himl, i, hdc, 0, 0, fStyle | ILD_MASK);
+    SelectObject32 (hdcDst, ii.hbmMask);
+    if (himl->hbmMask) {
+	SelectObject32 (hdcSrc, himl->hbmMask);
+	BitBlt32 (hdcDst, 0, 0, nWidth, nHeight,
+		  hdcSrc, i * himl->cx, 0, SRCCOPY);
+    }
+    else
+	PatBlt32 (hdcDst, 0, 0, nWidth, nHeight, BLACKNESS);
+
+    /* draw image*/
+    SelectObject32 (hdcDst, ii.hbmColor);
+    SelectObject32 (hdcSrc, himl->hbmImage);
+    BitBlt32 (hdcDst, 0, 0, nWidth, nHeight,
+	      hdcSrc, i * himl->cx, 0, SRCCOPY);
 
     hIcon = CreateIconIndirect (&ii);    
 
-    DeleteDC32 (hdc);
+    DeleteDC32 (hdcSrc);
+    DeleteDC32 (hdcDst);
     DeleteObject32 (ii.hbmMask);
     DeleteObject32 (ii.hbmColor);
 
@@ -2040,7 +2018,7 @@
  * Sets the image size of the bitmap and deletes all images.
  *
  * PARAMS
- *     himl [I] image list handle
+ *     himl [I] handle to image list
  *     cx   [I] image width
  *     cy   [I] image height
  *
@@ -2054,7 +2032,8 @@
 {
     INT32 nCount;
 
-    if (himl == NULL) return (FALSE);
+    if (!himl)
+	return FALSE;
 
     /* remove all images*/
     himl->cMaxImage  = himl->cInitial + himl->cGrow;
@@ -2088,7 +2067,7 @@
  * Resizes an image list to the specified number of images.
  *
  * PARAMS
- *     himl        [I] image list handle
+ *     himl        [I] handle to image list
  *     iImageCount [I] number of images in the image list
  *
  * RETURNS
@@ -2103,9 +2082,12 @@
     HBITMAP32 hbmNewBitmap;
     INT32     nNewCount, nCopyCount;
 
-    if (himl == NULL) return (FALSE);
-    if (himl->cCurImage <= iImageCount) return (FALSE);
-    if (himl->cMaxImage > iImageCount) return (TRUE);
+    if (!himl)
+	return FALSE;
+    if (himl->cCurImage <= iImageCount)
+	return FALSE;
+    if (himl->cMaxImage > iImageCount)
+	return TRUE;
 
     nNewCount = iImageCount + himl->cGrow;
     nCopyCount = _MIN(himl->cCurImage, iImageCount);
@@ -2126,7 +2108,7 @@
     }
     else
     {
-        WARN (imagelist, "Could not create new image bitmap !\n");
+        ERR (imagelist, "Could not create new image bitmap !\n");
     }
 
     if (himl->hbmMask)
@@ -2144,7 +2126,7 @@
         }
         else
         {
-            WARN (imagelist, "Could not create new mask bitmap!\n");
+            ERR (imagelist, "Could not create new mask bitmap!\n");
         }
     }
 
@@ -2156,7 +2138,7 @@
     if (himl->cCurImage > nCopyCount)
         himl->cCurImage = nCopyCount;
 
-    return (TRUE);
+    return TRUE;
 }
 
 
@@ -2178,8 +2160,12 @@
 BOOL32 WINAPI
 ImageList_SetOverlayImage (HIMAGELIST himl, INT32 iImage, INT32 iOverlay)
 {
-    if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE)) return (FALSE);
-    if ((iImage < 0) || (iImage > himl->cCurImage)) return (FALSE);
+    if (!himl)
+	return FALSE;
+    if ((iOverlay < 1) || (iOverlay > MAX_OVERLAYIMAGE))
+	return FALSE;
+    if ((iImage < 0) || (iImage > himl->cCurImage))
+	return FALSE;
     
     himl->nOvlIdx[iOverlay - 1] = iImage;
     return TRUE;
@@ -2210,9 +2196,10 @@
 BOOL32 WINAPI
 ImageList_Write (HIMAGELIST himl, LPSTREAM32 pstm)
 {
-    FIXME (imagelist, "empty stub!\n");
+    if (!himl)
+	return FALSE;
 
-    if (himl == NULL) return (FALSE);
+    FIXME (imagelist, "empty stub!\n");
 
     return FALSE;
 }
diff --git a/dlls/comctl32/listview.c b/dlls/comctl32/listview.c
index 91fe4cb..0c24d9c 100644
--- a/dlls/comctl32/listview.c
+++ b/dlls/comctl32/listview.c
@@ -9,8 +9,8 @@
  *     Eric <ekohl@abo.rhein-zeitung.de>
  *
  * TODO:
- *   - All messages.
- *   - All notifications.
+ *   - Most messages.
+ *   - Most notifications.
  */
 
 #include "windows.h"
@@ -26,7 +26,7 @@
 static VOID
 LISTVIEW_Refresh (WND *wndPtr, HDC32 hdc)
 {
-    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+//    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
 
 
 
@@ -34,6 +34,124 @@
 
 
 
+// << LISTVIEW_ApproximateViewRect >>
+// << LISTVIEW_Arrange >>
+// << LISTVIEW_CreateDragImage >>
+
+
+static LRESULT
+LISTVIEW_DeleteAllItems (WND *wndPtr)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    INT32 nItem;
+    LISTVIEW_ITEM *lpItem;
+    NMLISTVIEW nmlv;
+    BOOL32 bNotify;
+
+    if (infoPtr->nItemCount == 0)
+	return TRUE;
+
+    TRACE (listview, "\n");
+
+    /* send LVN_DELETEALLITEMS notification */
+    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code     = LVN_DELETEALLITEMS;
+    nmlv.iItem        = -1;
+    bNotify =
+	!(BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+				 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    nmlv.hdr.code     = LVN_DELETEITEM;
+
+    for (nItem = 0; nItem < infoPtr->nItemCount; nItem++) {
+	/* send notification */
+	if (bNotify) {
+	    nmlv.iItem = nItem;
+	    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+			    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+	}
+
+	/* get item pointer */
+	lpItem = (LISTVIEW_ITEM*)DPA_GetPtr (infoPtr->hdpaItems, nItem);
+
+	/* delete item strings */
+	if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACK32A))
+	    COMCTL32_Free (lpItem->pszText);
+
+	/* free item data */
+	COMCTL32_Free (lpItem);
+    }
+
+    DPA_DeleteAllPtrs (infoPtr->hdpaItems);
+    infoPtr->nItemCount = 0;
+
+    return TRUE;
+}
+
+
+static LRESULT
+LISTVIEW_DeleteColumn (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    INT32 nColumn = (INT32)wParam;
+
+    /* FIXME ??? */
+    if (infoPtr->nItemCount > 0)
+	return FALSE;
+
+    if (!SendMessage32A (infoPtr->hwndHeader, HDM_DELETEITEM, wParam, 0))
+	return FALSE;
+
+    infoPtr->nColumnCount--;
+
+    FIXME (listview, "semi stub!\n");
+
+    return TRUE;
+}
+
+
+static LRESULT
+LISTVIEW_DeleteItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    INT32 nItem = (INT32)wParam;
+    LISTVIEW_ITEM *lpItem;
+    NMLISTVIEW nmlv;
+
+    if ((nItem < 0) || (nItem >= infoPtr->nItemCount))
+	return FALSE;
+
+    TRACE (listview, "(%d)\n", nItem);
+
+    /* send notification */
+    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code     = LVN_DELETEITEM;
+    nmlv.iItem        = nItem;
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    /* remove from item array */
+    lpItem = (LISTVIEW_ITEM*)DPA_DeletePtr (infoPtr->hdpaItems, nItem);
+
+    /* delete item strings */
+    if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACK32A))
+	COMCTL32_Free (lpItem->pszText);
+
+    /* free item data */
+    COMCTL32_Free (lpItem);
+
+    infoPtr->nItemCount--;
+
+    return TRUE;
+}
+
+
+// << LISTVIEW_EditLabel >>
+// << LISTVIEW_EnsureVisible >>
 // << LISTVIEW_FindItem >>
 
 
@@ -47,6 +165,75 @@
 
 
 // << LISTVIEW_GetBkImage >>
+// << LISTVIEW_GetCallbackMask >>
+
+
+static LRESULT
+LISTVIEW_GetColumn32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVCOLUMN32A lpcol = (LPLVCOLUMN32A)lParam;
+    INT32 nIndex = (INT32)wParam;
+    HDITEM32A hdi;
+
+    if (!lpcol)
+	return FALSE;
+
+    TRACE (listview, "(%d %p)\n", nIndex, lpcol);
+
+    ZeroMemory (&hdi, sizeof(HDITEM32A));
+
+    if (lpcol->mask & LVCF_FMT)
+	hdi.mask |= HDI_FORMAT;
+
+    if (lpcol->mask & LVCF_WIDTH)
+        hdi.mask |= HDI_WIDTH;
+
+    if (lpcol->mask & LVCF_TEXT)
+        hdi.mask |= (HDI_TEXT | HDI_FORMAT);
+
+    if (lpcol->mask & LVCF_IMAGE)
+        hdi.mask |= HDI_IMAGE;
+
+    if (lpcol->mask & LVCF_ORDER)
+        hdi.mask |= HDI_ORDER;
+
+    if (!SendMessage32A (infoPtr->hwndHeader, HDM_GETITEM32A,
+		    wParam, (LPARAM)&hdi))
+	return FALSE;
+
+    if (lpcol->mask & LVCF_FMT) {
+	lpcol->fmt = 0;
+
+	if (hdi.fmt & HDF_LEFT)
+	    lpcol->fmt |= LVCFMT_LEFT;
+	else if (hdi.fmt & HDF_RIGHT)
+	    lpcol->fmt |= LVCFMT_RIGHT;
+	else if (hdi.fmt & HDF_CENTER)
+	    lpcol->fmt |= LVCFMT_CENTER;
+
+	if (hdi.fmt & HDF_IMAGE)
+	    lpcol->fmt |= LVCFMT_COL_HAS_IMAGES;
+    }
+
+    if (lpcol->mask & LVCF_WIDTH)
+	lpcol->cx = hdi.cxy;
+
+    if ((lpcol->mask & LVCF_TEXT) && (lpcol->pszText))
+	lstrcpyn32A (lpcol->pszText, hdi.pszText, lpcol->cchTextMax);
+
+    if (lpcol->mask & LVCF_IMAGE)
+	lpcol->iImage = hdi.iImage;
+
+    if (lpcol->mask & LVCF_ORDER)
+	lpcol->iOrder = hdi.iOrder;
+
+    return TRUE;
+}
+
+
+// << LISTVIEW_GetColumn32W >>
+// << LISTVIEW_GetColumnOrderArray >>
 
 
 __inline__ static LRESULT
@@ -64,6 +251,9 @@
 }
 
 
+// << LISTVIEW_GetCountPerPage >>
+// << LISTVIEW_GetEditControl >>
+// << LISTVIEW_GetExtendedListviewStyle >>
 
 
 __inline__ static LRESULT
@@ -75,6 +265,11 @@
 }
 
 
+// << LISTVIEW_GetHotCursor >>
+// << LISTVIEW_GetHotItem >>
+// << LISTVIEW_GetHoverTime >>
+
+
 static LRESULT
 LISTVIEW_GetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
@@ -97,19 +292,62 @@
 }
 
 
+// << LISTVIEW_GetISearchString >>
+
+
 static LRESULT
 LISTVIEW_GetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVITEM32A lpItem = (LPLVITEM32A)lParam;
+    LISTVIEW_ITEM *lpRow, *lpSubItem;
 
-    FIXME (listview, "(0x%08x) empty stub!\n", wParam);
+    if (!lpItem)
+	return FALSE;
 
+    if ((lpItem->iItem < 0) || (lpItem->iItem >= infoPtr->nItemCount))
+	return FALSE;
 
+    if ((lpItem->iSubItem < 0) || (lpItem->iSubItem >= infoPtr->nColumnCount))
+	return FALSE;
+
+    FIXME (listview, "(%d %d %p)\n",
+	   lpItem->iItem, lpItem->iSubItem, lpItem);
+
+    lpRow = DPA_GetPtr (infoPtr->hdpaItems, lpItem->iItem);
+    if (!lpRow)
+	return FALSE;
+
+    lpSubItem = &lpRow[lpItem->iSubItem];
+    if (!lpSubItem)
+	return FALSE;
+
+    if (lpItem->mask & LVIF_STATE)
+	lpItem->state = lpSubItem->state & lpItem->stateMask;
+
+    if (lpItem->mask & LVIF_TEXT) {
+	if (lpSubItem->pszText == LPSTR_TEXTCALLBACK32A)
+	    lpItem->pszText = LPSTR_TEXTCALLBACK32A;
+	else
+	    Str_GetPtr32A (lpSubItem->pszText, lpItem->pszText,
+			   lpItem->cchTextMax);
+    }
+
+    if (lpItem->mask & LVIF_IMAGE)
+	 lpItem->iImage = lpSubItem->iImage;
+
+    if (lpItem->mask & LVIF_PARAM)
+	lpItem->lParam = lpSubItem->lParam;
+
+    if (lpItem->mask & LVIF_INDENT)
+	lpItem->iIndent = lpSubItem->iIndent;
 
     return TRUE;
 }
 
 
+// << LISTVIEW_GetItem32W >>
+
 
 __inline__ static LRESULT
 LISTVIEW_GetItemCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
@@ -119,6 +357,93 @@
 }
 
 
+static LRESULT
+LISTVIEW_GetItemPosition (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPPOINT32 lpPt = (LPPOINT32)lParam;
+    INT32 nIndex = (INT32)wParam;
+
+    if (!lpPt)
+	return FALSE;
+    if ((nIndex < 0) || (nIndex >= infoPtr->nItemCount))
+	return FALSE;
+
+    FIXME (listview, "returning position [0,0]!\n");
+    lpPt->x = 0;
+    lpPt->y = 0;
+
+    return TRUE;
+}
+
+
+// << LISTVIEW_GetItemRect >>
+// << LISTVIEW_GetItemSpacing >>
+// << LISTVIEW_GetItemState >>
+
+
+static LRESULT
+LISTVIEW_GetItemText32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVITEM32A lpItem = (LPLVITEM32A)lParam;
+    INT32 nItem = (INT32)wParam;
+    LISTVIEW_ITEM *lpRow, *lpSubItem;
+
+    TRACE (listview, "(%d %p)\n", nItem, lpItem);
+
+    lpRow = DPA_GetPtr (infoPtr->hdpaItems, lpItem->iItem);
+    if (!lpRow)
+	return 0;
+
+    lpSubItem = &lpRow[lpItem->iSubItem];
+    if (!lpSubItem)
+	return 0;
+
+    if (lpSubItem->pszText == LPSTR_TEXTCALLBACK32A) {
+	lpItem->pszText = LPSTR_TEXTCALLBACK32A;
+	return 0;
+    }
+    else
+	return Str_GetPtr32A (lpSubItem->pszText, lpItem->pszText,
+			      lpItem->cchTextMax);
+}
+
+
+// << LISTVIEW_GetItemText32A >>
+
+
+static LRESULT
+LISTVIEW_GetNextItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    INT32 nStart = (INT32)wParam;
+    UINT32 uFlags = (UINT32)LOWORD(lParam);
+
+    FIXME (listview, "(%d, 0x%x); empty stub!\n", nStart, uFlags);
+
+
+    return -1;
+}
+
+
+// << LISTVIEW_GetNumberOfWorkAreas >>
+// << LISTVIEW_GetOrigin >>
+
+
+static LRESULT
+LISTVIEW_GetSelectedCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    TRACE (listview, ": empty stub (returns 0)!\n");
+
+    return 0;
+}
+
+
+// << LISTVIEW_GetSelectionMark >>
+
 
 static LRESULT
 LISTVIEW_GetStringWidth32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
@@ -132,7 +457,7 @@
     if (!lpsz)
 	return 0;
 
-    TRACE (listview, "(%s) empty stub!\n", lpsz);
+    TRACE (listview, "(%s)\n", lpsz);
 
     hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (SYSTEM_FONT);
     hdc = GetDC32 (0);
@@ -149,22 +474,42 @@
 
 
 
+__inline__ static LRESULT
+LISTVIEW_GetTextBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    return infoPtr->clrTextBk;
+}
+
+
+__inline__ static LRESULT
+LISTVIEW_GetTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    return infoPtr->clrText;
+}
+
+
 static LRESULT
 LISTVIEW_InsertColumn32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
     LPLVCOLUMN32A lpcol = (LPLVCOLUMN32A)lParam;
+    INT32 nIndex = (INT32)wParam;
     HDITEM32A hdi;
+    INT32 nResult;
 
-    if (!lpcol)
+    if ((!lpcol) || (infoPtr->nItemCount > 0))
 	return -1;
 
-    TRACE (listview, "(%d %p) empty stub!\n", (INT32)wParam, lpcol);
+    FIXME (listview, "(%d %p): semi stub!\n", nIndex, lpcol);
 
     ZeroMemory (&hdi, sizeof(HDITEM32A));
 
     if (lpcol->mask & LVCF_FMT) {
-	if (wParam == 0)
+	if (nIndex == 0)
 	    hdi.fmt |= HDF_LEFT;
 	else if (lpcol->fmt & LVCFMT_LEFT)
 	    hdi.fmt |= HDF_LEFT;
@@ -200,11 +545,90 @@
 	hdi.iOrder = lpcol->iOrder;
     }
 
-    return (LRESULT)SendMessage32A (infoPtr->hwndHeader, HDM_INSERTITEM32A,
-				    wParam, (LPARAM)&hdi);
+    nResult = SendMessage32A (infoPtr->hwndHeader, HDM_INSERTITEM32A,
+			      wParam, (LPARAM)&hdi);
+    if (nResult == -1)
+	return -1;
+
+    infoPtr->nColumnCount++;
+
+    return nResult;
 }
 
 
+// << LISTVIEW_InsertColumn32W >>
+
+
+static LRESULT
+LISTVIEW_InsertItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVITEM32A lpItem = (LPLVITEM32A)lParam;
+    LISTVIEW_ITEM *lpListItem;
+    INT32 nIndex;
+    NMLISTVIEW nmlv;
+
+    if (!lpItem)
+	return -1;
+
+    if ((!infoPtr->nColumnCount) || (lpItem->iSubItem))
+	return -1;
+
+    FIXME (listview, "(%d %p)\n", lpItem->iItem, lpItem);
+
+    lpListItem = (LISTVIEW_ITEM*)COMCTL32_Alloc (infoPtr->nColumnCount * sizeof(LISTVIEW_ITEM));
+    nIndex = DPA_InsertPtr (infoPtr->hdpaItems, lpItem->iItem, lpListItem);
+    if (nIndex == -1)
+	return -1;
+
+    if (lpItem->mask & LVIF_STATE)
+	lpListItem[0].state = lpItem->state;
+
+    if (lpItem->mask & LVIF_TEXT) {
+	if (lpItem->pszText == LPSTR_TEXTCALLBACK32A)
+	    lpListItem[0].pszText = LPSTR_TEXTCALLBACK32A;
+	else
+	    Str_SetPtr32A (&lpListItem[0].pszText, lpItem->pszText);
+    }
+
+    if (lpItem->mask & LVIF_IMAGE)
+	lpListItem[0].iImage = lpItem->iImage;
+
+    if (lpItem->mask & LVIF_PARAM)
+	lpListItem[0].lParam = lpItem->lParam;
+
+    if (lpItem->mask & LVIF_INDENT)
+	lpListItem[0].iIndent = lpItem->iIndent;
+
+    infoPtr->nItemCount++;
+
+    /* send notification */
+    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code     = LVN_INSERTITEM;
+    nmlv.iItem        = nIndex;
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    return nIndex;
+}
+
+
+// << LISTVIEW_InsertItem32W >>
+
+
+static LRESULT
+LISTVIEW_RedrawItems (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+//    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    FIXME (listview, "(%d - %d): empty stub!\n",
+	   (INT32)wParam, (INT32)lParam);
+
+    return TRUE;
+}
+
 
 
 static LRESULT
@@ -212,10 +636,11 @@
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
 
-    if (!(infoPtr)) return FALSE;
+    if (!infoPtr)
+	return FALSE;
 
     /* set background color */
-    TRACE (listview, "0x%06x\n", (COLORREF)lParam);
+    TRACE (listview, "0x%06lx\n", (COLORREF)lParam);
     infoPtr->clrBk = (COLORREF)lParam;
 
     return TRUE;
@@ -223,6 +648,65 @@
 
 
 static LRESULT
+LISTVIEW_SetColumn32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVCOLUMN32A lpcol = (LPLVCOLUMN32A)lParam;
+    INT32 nIndex = (INT32)wParam;
+    HDITEM32A hdi;
+
+    if (!lpcol)
+	return -1;
+
+    FIXME (listview, "(%d %p): semi stub!\n", nIndex, lpcol);
+
+    ZeroMemory (&hdi, sizeof(HDITEM32A));
+
+    if (lpcol->mask & LVCF_FMT) {
+	if (nIndex == 0)
+	    hdi.fmt |= HDF_LEFT;
+	else if (lpcol->fmt & LVCFMT_LEFT)
+	    hdi.fmt |= HDF_LEFT;
+	else if (lpcol->fmt & LVCFMT_RIGHT)
+	    hdi.fmt |= HDF_RIGHT;
+	else if (lpcol->fmt & LVCFMT_CENTER)
+	    hdi.fmt |= HDF_CENTER;
+
+	if (lpcol->fmt & LVCFMT_COL_HAS_IMAGES)
+	    hdi.fmt |= HDF_IMAGE;
+	    
+	hdi.mask |= HDI_FORMAT;
+    }
+
+    if (lpcol->mask & LVCF_WIDTH) {
+        hdi.mask |= HDI_WIDTH;
+	hdi.cxy = lpcol->cx;
+    }
+    
+    if (lpcol->mask & LVCF_TEXT) {
+        hdi.mask |= (HDI_TEXT | HDI_FORMAT);
+	hdi.pszText = lpcol->pszText;
+	hdi.fmt |= HDF_STRING;
+    }
+
+    if (lpcol->mask & LVCF_IMAGE) {
+        hdi.mask |= HDI_IMAGE;
+	hdi.iImage = lpcol->iImage;
+    }
+
+    if (lpcol->mask & LVCF_ORDER) {
+        hdi.mask |= HDI_ORDER;
+	hdi.iOrder = lpcol->iOrder;
+    }
+
+    return (LRESULT)SendMessage32A (infoPtr->hwndHeader, HDM_SETITEM32A,
+				    wParam, (LPARAM)&hdi);
+}
+
+
+
+
+static LRESULT
 LISTVIEW_SetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
@@ -252,6 +736,150 @@
 
 
 
+static LRESULT
+LISTVIEW_SetItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPLVITEM32A lpItem = (LPLVITEM32A)lParam;
+    LISTVIEW_ITEM *lpRow, *lpSubItem;
+    NMLISTVIEW nmlv;
+
+    if (!lpItem)
+	return FALSE;
+
+    if ((lpItem->iItem < 0) || (lpItem->iItem >= infoPtr->nItemCount))
+	return FALSE;
+
+    if ((lpItem->iSubItem < 0) || (lpItem->iSubItem >= infoPtr->nColumnCount))
+	return FALSE;
+
+    /* send LVN_ITEMCHANGING notification */
+    ZeroMemory (&nmlv, sizeof (NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code     = LVN_ITEMCHANGING;
+    nmlv.iItem        = lpItem->iItem;
+    nmlv.iSubItem     = lpItem->iSubItem;
+    nmlv.uChanged     = lpItem->mask;
+
+    if (!SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+			 (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv))
+	return FALSE;
+
+    TRACE (listview, "(%d %d %p)\n",
+	   lpItem->iItem, lpItem->iSubItem, lpItem);
+
+    lpRow = DPA_GetPtr (infoPtr->hdpaItems, lpItem->iItem);
+    if (!lpRow)
+	return FALSE;
+
+    lpSubItem = &lpRow[lpItem->iSubItem];
+    if (!lpSubItem)
+	return FALSE;
+
+    if (lpItem->mask & LVIF_STATE)
+	lpSubItem->state = (lpSubItem->state & lpItem->stateMask) | lpItem->state;
+
+    if (lpItem->mask & LVIF_TEXT) {
+	if (lpItem->pszText == LPSTR_TEXTCALLBACK32A) {
+	    if ((lpSubItem->pszText) &&
+		(lpSubItem->pszText != LPSTR_TEXTCALLBACK32A))
+		COMCTL32_Free (lpSubItem->pszText);
+	    lpSubItem->pszText = LPSTR_TEXTCALLBACK32A;
+	}
+	else {
+	    if (lpSubItem->pszText == LPSTR_TEXTCALLBACK32A)
+		lpSubItem->pszText = NULL;
+	    Str_SetPtr32A (&lpSubItem->pszText, lpItem->pszText);
+	}
+    }
+
+    if (lpItem->mask & LVIF_IMAGE)
+	lpSubItem->iImage = lpItem->iImage;
+
+    if (lpItem->mask & LVIF_PARAM)
+	lpSubItem->lParam = lpItem->lParam;
+
+    if (lpItem->mask & LVIF_INDENT)
+	lpSubItem->iIndent = lpItem->iIndent;
+
+    /* send LVN_ITEMCHANGED notification */
+    nmlv.hdr.code = LVN_ITEMCHANGED;
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    return TRUE;
+}
+
+
+// << LISTVIEW_SetItem32W >>
+// << LISTVIEW_SetItemCount >>
+
+
+static LRESULT
+LISTVIEW_SetItemPosition (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    INT32 nIndex = (INT32)wParam;
+
+    if ((nIndex < 0) || (nIndex >= infoPtr->nItemCount))
+	return FALSE;
+
+    FIXME (listview, "setting position [%d, %d]!\n",
+	   (INT32)LOWORD(lParam), (INT32)HIWORD(lParam));
+
+    /* FIXME: set position */
+
+    return TRUE;
+}
+
+
+static LRESULT
+LISTVIEW_SetTextBkColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    if (!infoPtr)
+	return FALSE;
+
+    /* set text background color */
+    TRACE (listview, "0x%06lx\n", (COLORREF)lParam);
+    infoPtr->clrTextBk = (COLORREF)lParam;
+
+    return TRUE;
+}
+
+
+static LRESULT
+LISTVIEW_SetTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    if (!infoPtr)
+	return FALSE;
+
+    /* set text color */
+    TRACE (listview, "0x%06lx\n", (COLORREF)lParam);
+    infoPtr->clrText = (COLORREF)lParam;
+
+    return TRUE;
+}
+
+
+
+static LRESULT
+LISTVIEW_SortItems (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+//    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+
+    FIXME (listview, "empty stub!\n");
+
+    /* fake success */
+    return TRUE;
+}
+
+
+
 
 static LRESULT
 LISTVIEW_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
@@ -261,9 +889,13 @@
     LOGFONT32A logFont;
     DWORD dwStyle = WS_CHILD | WS_VISIBLE; 
 
+    TRACE (listview, "styles 0x%08lx 0x%08lx\n",
+	   wndPtr->dwStyle, wndPtr->dwExStyle);
 
     /* initialize info structure */
     infoPtr->clrBk = CLR_NONE;
+    infoPtr->clrText = RGB(0, 0, 0); /* preliminary */
+    infoPtr->clrTextBk = RGB(255, 255, 255); /* preliminary */
 
     if (!(wndPtr->dwStyle & LVS_REPORT) ||
 	 (wndPtr->dwStyle & LVS_NOCOLUMNHEADER))
@@ -286,8 +918,7 @@
     SendMessage32A (infoPtr->hwndHeader, WM_SETFONT,
 		    (WPARAM32)infoPtr->hFont, (LPARAM)TRUE);
 
-
-    infoPtr->hdsaItems = DSA_Create (sizeof(LISTVIEW_ITEM), 10);
+    infoPtr->hdpaItems = DPA_Create (10);
 
     return 0;
 }
@@ -298,7 +929,11 @@
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
 
-    DSA_Destroy (infoPtr->hdsaItems);
+    /* delete all items */
+    LISTVIEW_DeleteAllItems (wndPtr);
+
+    /* destroy dpa */
+    DPA_Destroy (infoPtr->hdpaItems);
 
     /* destroy header */
     if (infoPtr->hwndHeader)
@@ -330,7 +965,8 @@
 	DeleteObject32 (hBrush);
 	return FALSE;
     }
-    return FALSE;
+
+    return TRUE;
 }
 
 
@@ -345,7 +981,78 @@
 
 // << LISTVIEW_HScroll >>
 // << LISTVIEW_KeyDown >>
-// << LISTVIEW_KillFocus >>
+
+
+static LRESULT
+LISTVIEW_KillFocus (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMHDR nmh;
+
+    FIXME (listview, "semi stub!\n");
+
+    nmh.hwndFrom = wndPtr->hwndSelf;
+    nmh.idFrom   = wndPtr->wIDmenu;
+    nmh.code = NM_KILLFOCUS;
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmh);
+
+    infoPtr->bFocus = FALSE;
+
+    return 0;
+}
+
+
+static LRESULT
+LISTVIEW_LButtonDblClk (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMLISTVIEW nmlv;
+
+    FIXME (listview, "semi stub!\n");
+
+    ZeroMemory (&nmlv, sizeof(NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code = NM_DBLCLK;
+    nmlv.iItem    = -1;
+    nmlv.iSubItem = 0;
+    nmlv.ptAction.x = (INT32)LOWORD(lParam);
+    nmlv.ptAction.y = (INT32)HIWORD(lParam);
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    return 0;
+}
+
+
+static LRESULT
+LISTVIEW_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMLISTVIEW nmlv;
+
+    FIXME (listview, "semi stub!\n");
+
+    ZeroMemory (&nmlv, sizeof(NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code = NM_CLICK;
+    nmlv.iItem    = -1;
+    nmlv.iSubItem = 0;
+    nmlv.ptAction.x = (INT32)LOWORD(lParam);
+    nmlv.ptAction.y = (INT32)HIWORD(lParam);
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    if (!infoPtr->bFocus)
+	SetFocus32 (wndPtr->hwndSelf);
+
+    return 0;
+}
 
 
 static LRESULT
@@ -387,6 +1094,25 @@
 
 
 static LRESULT
+LISTVIEW_Notify (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    LPNMHDR lpnmh = (LPNMHDR)lParam;
+
+    if (lpnmh->hwndFrom == infoPtr->hwndHeader) {
+
+	FIXME (listview, "WM_NOTIFY from header!\n");
+    }
+    else {
+
+	FIXME (listview, "WM_NOTIFY from unknown source!\n");
+    }
+
+    return 0;
+}
+
+
+static LRESULT
 LISTVIEW_Paint (WND *wndPtr, WPARAM32 wParam)
 {
     HDC32 hdc;
@@ -400,6 +1126,73 @@
 }
 
 
+static LRESULT
+LISTVIEW_RButtonDblClk (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMLISTVIEW nmlv;
+
+    FIXME (listview, "semi stub!\n");
+
+    ZeroMemory (&nmlv, sizeof(NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code = NM_RDBLCLK;
+    nmlv.iItem    = -1;
+    nmlv.iSubItem = 0;
+    nmlv.ptAction.x = (INT32)LOWORD(lParam);
+    nmlv.ptAction.y = (INT32)HIWORD(lParam);
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    return 0;
+}
+
+
+static LRESULT
+LISTVIEW_RButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMLISTVIEW nmlv;
+
+    FIXME (listview, "semi stub!\n");
+
+    ZeroMemory (&nmlv, sizeof(NMLISTVIEW));
+    nmlv.hdr.hwndFrom = wndPtr->hwndSelf;
+    nmlv.hdr.idFrom   = wndPtr->wIDmenu;
+    nmlv.hdr.code = NM_RCLICK;
+    nmlv.iItem    = -1;
+    nmlv.iSubItem = 0;
+    nmlv.ptAction.x = (INT32)LOWORD(lParam);
+    nmlv.ptAction.y = (INT32)HIWORD(lParam);
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmlv);
+
+    return 0;
+}
+
+
+static LRESULT
+LISTVIEW_SetFocus (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
+    NMHDR nmh;
+
+    FIXME (listview, "semi stub!\n");
+
+    nmh.hwndFrom = wndPtr->hwndSelf;
+    nmh.idFrom   = wndPtr->wIDmenu;
+    nmh.code = NM_SETFOCUS;
+
+    SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+		    (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmh);
+
+    infoPtr->bFocus = TRUE;
+
+    return 0;
+}
 
 
 static LRESULT
@@ -433,24 +1226,28 @@
 LISTVIEW_Size (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     LISTVIEW_INFO *infoPtr = LISTVIEW_GetInfoPtr(wndPtr);
-    HDLAYOUT hl;
-    WINDOWPOS32 wp;
-    RECT32 rc;
-
-    rc.top = 0;
-    rc.left = 0;
-    rc.right = LOWORD(lParam);
-    rc.bottom = HIWORD(lParam);
-
-    hl.prc = &rc;
-    hl.pwpos = &wp;
-    SendMessage32A (infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl);
-
-    SetWindowPos32 (infoPtr->hwndHeader, wndPtr->hwndSelf,
-		    wp.x, wp.y, wp.cx, wp.cy, wp.flags);
 
     GetClientRect32 (wndPtr->hwndSelf, &infoPtr->rcList);
-    infoPtr->rcList.top += wp.cy;
+
+    if (wndPtr->dwStyle & LVS_REPORT) {
+	HDLAYOUT hl;
+	WINDOWPOS32 wp;
+	RECT32 rc;
+
+	rc.top = 0;
+	rc.left = 0;
+	rc.right = LOWORD(lParam);
+	rc.bottom = HIWORD(lParam);
+
+	hl.prc = &rc;
+	hl.pwpos = &wp;
+	SendMessage32A (infoPtr->hwndHeader, HDM_LAYOUT, 0, (LPARAM)&hl);
+
+	SetWindowPos32 (infoPtr->hwndHeader, wndPtr->hwndSelf,
+			wp.x, wp.y, wp.cx, wp.cy, wp.flags);
+
+	infoPtr->rcList.top += wp.cy;
+    }
 
     return 0;
 }
@@ -463,24 +1260,54 @@
 
     switch (uMsg)
     {
-//	case LVM_DELETEALLITEMS:
+//	case LVM_APPROXIMATEVIEWRECT:
+//	case LVM_ARRANGE:
+//	case LVM_CREATEDRAGIMAGE:
 
-        case LVM_GETBKCOLOR:
+	case LVM_DELETEALLITEMS:
+	    return LISTVIEW_DeleteAllItems (wndPtr);
+
+	case LVM_DELETECOLUMN:
+	    return LISTVIEW_DeleteColumn (wndPtr, wParam, lParam);
+
+	case LVM_DELETEITEM:
+	    return LISTVIEW_DeleteItem (wndPtr, wParam, lParam);
+
+//	case LVM_EDITLABEL:
+//	case LVM_ENSUREVISIBLE:
+//	case LVM_FINDITEM:
+
+	case LVM_GETBKCOLOR:
 	    return LISTVIEW_GetBkColor (wndPtr, wParam, lParam);
 
+//	case LVM_GETBKIMAGE:
+//	case LVM_GETCALLBACKMASK:
 
-        case LVM_GETCOLUMNWIDTH:
+	case LVM_GETCOLUMN32A:
+	    return LISTVIEW_GetColumn32A (wndPtr, wParam, lParam);
+
+//	case LVM_GETCOLUMN32W:
+//	case LVM_GETCOLUMNORDERARRAY:
+
+	case LVM_GETCOLUMNWIDTH:
 	    return LISTVIEW_GetColumnWidth (wndPtr, wParam, lParam);
 
+//	case LVM_GETCOUNTPERPAGE:
+//	case LVM_GETEDITCONTROL:
+//	case LVM_GETEXTENDEDLISTVIEWSTYLE:
 
-        case LVM_GETHEADER:
+	case LVM_GETHEADER:
 	    return LISTVIEW_GetHeader (wndPtr, wParam, lParam);
 
-//	case LVM_GETISEARCHSTRING:
+//	case LVM_GETHOTCURSOR:
+//	case LVM_GETHOTITEM:
+//	case LVM_GETHOVERTIME:
 
 	case LVM_GETIMAGELIST:
 	    return LISTVIEW_GetImageList (wndPtr, wParam, lParam);
 
+//	case LVM_GETISEARCHSTRING:
+
 	case LVM_GETITEM32A:
 	    return LISTVIEW_GetItem32A (wndPtr, wParam, lParam);
 
@@ -489,7 +1316,28 @@
 	case LVM_GETITEMCOUNT:
 	    return LISTVIEW_GetItemCount (wndPtr, wParam, lParam);
 
-//	case LVM_GETSELECTEDCOUNT:
+	case LVM_GETITEMPOSITION:
+	    return LISTVIEW_GetItemPosition (wndPtr, wParam, lParam);
+
+//	case LVM_GETITEMRECT:
+//	case LVM_GETITEMSPACING:
+//	case LVM_GETITEMSTATE:
+
+	case LVM_GETITEMTEXT32A:
+	    return LISTVIEW_GetItemText32A (wndPtr, wParam, lParam);
+
+//	case LVM_GETITEMTEXT32W:
+
+	case LVM_GETNEXTITEM:
+	    return LISTVIEW_GetNextItem (wndPtr, wParam, lParam);
+
+//	case LVM_GETNUMBEROFWORKAREAS:
+//	case LVM_GETORIGIN:
+
+	case LVM_GETSELECTEDCOUNT:
+	    return LISTVIEW_GetSelectedCount (wndPtr, wParam, lParam);
+
+//	case LVM_GETSELECTIONMARK:
 
 	case LVM_GETSTRINGWIDTH32A:
 	    return LISTVIEW_GetStringWidth32A (wndPtr, wParam, lParam);
@@ -497,26 +1345,85 @@
 //	case LVM_GETSTRINGWIDTH32W:
 //	case LVM_GETSUBITEMRECT:
 
+	case LVM_GETTEXTBKCOLOR:
+	    return LISTVIEW_GetTextBkColor (wndPtr, wParam, lParam);
+
+	case LVM_GETTEXTCOLOR:
+	    return LISTVIEW_GetTextColor (wndPtr, wParam, lParam);
+
+//	case LVM_GETTOOLTIPS:
+//	case LVM_GETTOPINDEX:
+//	case LVM_GETUNICODEFORMAT:
+//	case LVM_GETVIEWRECT:
+//	case LVM_GETWORKAREAS:
+//	case LVM_HITTEST:
+
 	case LVM_INSERTCOLUMN32A:
 	    return LISTVIEW_InsertColumn32A (wndPtr, wParam, lParam);
 
-
 //	case LVM_INSERTCOLUMN32W:
 
-//	case LVM_INSERTITEM32A:
+	case LVM_INSERTITEM32A:
+	    return LISTVIEW_InsertItem32A (wndPtr, wParam, lParam);
+
 //	case LVM_INSERTITEM32W:
 
+	case LVM_REDRAWITEMS:
+	    return LISTVIEW_RedrawItems (wndPtr, wParam, lParam);
+
+//	case LVM_SCROLL:
 
 	case LVM_SETBKCOLOR:
 	    return LISTVIEW_SetBkColor (wndPtr, wParam, lParam);
 
+//	case LVM_SETBKIMAGE:
+//	case LVM_SETCALLBACKMASK:
+
+	case LVM_SETCOLUMN32A:
+	    return LISTVIEW_SetColumn32A (wndPtr, wParam, lParam);
+
+//	case LVM_SETCOLUMN32W:
+//	case LVM_SETCOLUMNORDERARRAY:
+//	case LVM_SETCOLUMNWIDTH:
+//	case LVM_SETEXTENDEDLISTVIEWSTYLE:
+//	case LVM_SETHOTCURSOR:
+//	case LVM_SETHOTITEM:
+//	case LVM_SETHOVERTIME:
+//	case LVM_SETICONSPACING:
 	
 	case LVM_SETIMAGELIST:
 	    return LISTVIEW_SetImageList (wndPtr, wParam, lParam);
 
-//	case LVM_SETITEMPOSITION:
+	case LVM_SETITEM32A:
+	    return LISTVIEW_SetItem32A (wndPtr, wParam, lParam);
 
-//	case LVM_SORTITEMS:
+//	case LVM_SETITEM32W:
+//	case LVM_SETITEMCOUNT:
+
+	case LVM_SETITEMPOSITION:
+	    return LISTVIEW_SetItemPosition (wndPtr, wParam, lParam);
+
+//	case LVM_SETITEMPOSITION32:
+//	case LVM_SETITEMSTATE:
+//	case LVM_SETITEMTEXT:
+//	case LVM_SETSELECTIONMARK:
+
+	case LVM_SETTEXTBKCOLOR:
+	    return LISTVIEW_SetTextBkColor (wndPtr, wParam, lParam);
+
+	case LVM_SETTEXTCOLOR:
+	    return LISTVIEW_SetTextColor (wndPtr, wParam, lParam);
+
+//	case LVM_SETTOOLTIPS:
+//	case LVM_SETUNICODEFORMAT:
+//	case LVM_SETWORKAREAS:
+
+	case LVM_SORTITEMS:
+	    return LISTVIEW_SortItems (wndPtr, wParam, lParam);
+
+//	case LVM_SUBITEMHITTEST:
+//	case LVM_UPDATE:
+
 
 
 //	case WM_CHAR:
@@ -538,6 +1445,16 @@
 	    return LISTVIEW_GetFont (wndPtr, wParam, lParam);
 
 //	case WM_HSCROLL:
+//	case WM_KEYDOWN:
+
+	case WM_KILLFOCUS:
+	    return LISTVIEW_KillFocus (wndPtr, wParam, lParam);
+
+	case WM_LBUTTONDBLCLK:
+	    return LISTVIEW_LButtonDblClk (wndPtr, wParam, lParam);
+
+	case WM_LBUTTONDOWN:
+	    return LISTVIEW_LButtonDown (wndPtr, wParam, lParam);
 
 //	case WM_MOUSEMOVE:
 //	    return LISTVIEW_MouseMove (wndPtr, wParam, lParam);
@@ -548,13 +1465,20 @@
 	case WM_NCDESTROY:
 	    return LISTVIEW_NCDestroy (wndPtr, wParam, lParam);
 
-//	case WM_NOTIFY:
+	case WM_NOTIFY:
+	    return LISTVIEW_Notify (wndPtr, wParam, lParam);
 
 	case WM_PAINT:
 	    return LISTVIEW_Paint (wndPtr, wParam);
 
-//	case WM_RBUTTONDOWN:
-//	case WM_SETFOCUS:
+	case WM_RBUTTONDBLCLK:
+	    return LISTVIEW_RButtonDblClk (wndPtr, wParam, lParam);
+
+	case WM_RBUTTONDOWN:
+	    return LISTVIEW_RButtonDown (wndPtr, wParam, lParam);
+
+	case WM_SETFOCUS:
+	    return LISTVIEW_SetFocus (wndPtr, wParam, lParam);
 
 	case WM_SETFONT:
 	    return LISTVIEW_SetFont (wndPtr, wParam, lParam);
diff --git a/dlls/comctl32/pager.c b/dlls/comctl32/pager.c
index e5c231e..815a55f 100644
--- a/dlls/comctl32/pager.c
+++ b/dlls/comctl32/pager.c
@@ -169,7 +169,7 @@
     SetParent32 (infoPtr->hwndChild, wndPtr->hwndSelf);
     SetWindowPos32 (infoPtr->hwndChild, wndPtr->hwndSelf,
 		    0, 0, 40, 40, SWP_SHOWWINDOW);
-    RedrawWindow32 (wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE);
+    RedrawWindow32 (wndPtr->hwndSelf, NULL, NULL, RDW_INVALIDATE);
 
     return 0;
 }
diff --git a/dlls/comctl32/progress.c b/dlls/comctl32/progress.c
index 3acb294..ad08872 100644
--- a/dlls/comctl32/progress.c
+++ b/dlls/comctl32/progress.c
@@ -8,9 +8,8 @@
  */
 
 #include "windows.h"
-#include "progress.h"
 #include "commctrl.h"
-#include "heap.h"
+#include "progress.h"
 #include "win.h"
 #include "debug.h"
 
@@ -185,8 +184,7 @@
     case WM_CREATE:
       /* allocate memory for info struct */
       infoPtr = 
-	(PROGRESS_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                    sizeof(PROGRESS_INFO));
+	(PROGRESS_INFO *)COMCTL32_Alloc (sizeof(PROGRESS_INFO));
       wndPtr->wExtra[0] = (DWORD)infoPtr;
 
       /* initialize the info struct */
@@ -200,8 +198,8 @@
       break;
     
     case WM_DESTROY:
-      TRACE(progress, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
-      HeapFree (GetProcessHeap (), 0, infoPtr);
+      TRACE (progress, "Progress Ctrl destruction, hwnd=%04x\n", hwnd);
+      COMCTL32_Free (infoPtr);
       break;
 
     case WM_ERASEBKGND:
@@ -328,11 +326,12 @@
 
 
 /***********************************************************************
- *           PROGRESS_Register [Internal]
+ * PROGRESS_Register [Internal]
  *
  * Registers the progress bar window class.
  * 
  */
+
 void 
 PROGRESS_Register(void)
 {
diff --git a/dlls/comctl32/rebar.c b/dlls/comctl32/rebar.c
index b27b5f5..2936d96 100644
--- a/dlls/comctl32/rebar.c
+++ b/dlls/comctl32/rebar.c
@@ -16,7 +16,6 @@
 #include "windows.h"
 #include "commctrl.h"
 #include "rebar.h"
-#include "heap.h"
 #include "win.h"
 #include "debug.h"
 
@@ -42,10 +41,24 @@
 
 
 
-
-
 // << REBAR_BeginDrag >>
-// << REBAR_DeleteBand >>
+
+
+static LRESULT
+REBAR_DeleteBand (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    REBAR_INFO *infoPtr = REBAR_GetInfoPtr (wndPtr);
+    UINT32 uBand = (UINT32)wParam;
+
+    if (uBand >= infoPtr->uNumBands)
+	return FALSE;
+
+    FIXME (rebar, "deleting band %u!\n", uBand);
+
+    return TRUE;
+}
+
+
 // << REBAR_DragMove >>
 // << REBAR_EndDrag >>
 // << REBAR_GetBandBorders >>
@@ -246,16 +259,13 @@
     TRACE (rebar, "insert band at %u!\n", uIndex);
 
     if (infoPtr->uNumBands == 0) {
-	infoPtr->bands =
-	    (REBAR_BAND *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-				     sizeof (REBAR_BAND));
+	infoPtr->bands = (REBAR_BAND *)COMCTL32_Alloc (sizeof (REBAR_BAND));
 	uIndex = 0;
     }
     else {
 	REBAR_BAND *oldBands = infoPtr->bands;
 	infoPtr->bands =
-	    (REBAR_BAND *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-				     (infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
+	    (REBAR_BAND *)COMCTL32_Alloc ((infoPtr->uNumBands+1)*sizeof(REBAR_BAND));
 	if (((INT32)uIndex == -1) || (uIndex > infoPtr->uNumBands))
 	    uIndex = infoPtr->uNumBands;
 
@@ -271,7 +281,7 @@
 		    (infoPtr->uNumBands - uIndex - 1) * sizeof(REBAR_BAND));
 	}
 
-	HeapFree (GetProcessHeap (), 0, &oldBands);
+	COMCTL32_Free (&oldBands);
     }
 
     infoPtr->uNumBands++;
@@ -292,8 +302,7 @@
     if ((lprbbi->fMask & RBBIM_TEXT) && (lprbbi->lpText)) {
 	INT32 len = lstrlen32A (lprbbi->lpText);
 	if (len > 0) {
-	    lpBand->lpText = 
-		(LPSTR)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
+	    lpBand->lpText = (LPSTR)COMCTL32_Alloc (len + 1);
 	    lstrcpy32A (lpBand->lpText, lprbbi->lpText);
 	}
     }
@@ -377,8 +386,7 @@
 /*
 	INT32 len = lstrlen32A (lprbbi->lpText);
 	if (len > 0) {
-	    lpBand->lpText = 
-		(LPSTR)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
+	    lpBand->lpText = (LPSTR)COMCTL32_Alloc (len + 1);
 	    lstrcpy32A (lpBand->lpText, lprbbi->lpText);
 	}
 */
@@ -566,13 +574,13 @@
 
 	    /* delete text strings */
 	    if (lpBand->lpText) {
-		HeapFree (GetProcessHeap (), 0, lpBand->lpText);
+		COMCTL32_Free (lpBand->lpText);
 		lpBand->lpText = NULL;
 	    }
 	}
 
 	/* free band array */
-	HeapFree (GetProcessHeap (), 0, infoPtr->bands);
+	COMCTL32_Free (infoPtr->bands);
 	infoPtr->bands = NULL;
     }
 
@@ -608,7 +616,10 @@
     switch (uMsg)
     {
 //	case RB_BEGINDRAG:
-//	case RB_DELETEBAND:
+
+	case RB_DELETEBAND:
+	    return REBAR_DeleteBand (wndPtr, wParam, lParam);
+
 //	case RB_DRAGMOVE:
 //	case RB_ENDDRAG:
 //	case RB_GETBANDBORDERS:
@@ -621,7 +632,6 @@
 	case RB_GETBANDINFO32A:
 	    return REBAR_GetBandInfo32A (wndPtr, wParam, lParam);
 
-
 //	case RB_GETBANDINFO32W:
 
 	case RB_GETBARHEIGHT:
diff --git a/dlls/comctl32/status.c b/dlls/comctl32/status.c
index 6536fa9..a2c710e 100644
--- a/dlls/comctl32/status.c
+++ b/dlls/comctl32/status.c
@@ -6,9 +6,8 @@
  */
 
 #include "windows.h"
-#include "status.h"
 #include "commctrl.h"
-#include "heap.h"
+#include "status.h"
 #include "win.h"
 #include "debug.h"
 
@@ -528,17 +527,16 @@
     if (oldNumParts > self->numParts) {
 	for (i = self->numParts ; i < oldNumParts; i++) {
 	    if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
-		HeapFree(GetProcessHeap (), 0, self->parts[i].text);
+		COMCTL32_Free (self->parts[i].text);
 	}
     }
     else if (oldNumParts < self->numParts) {
-	tmp = HeapAlloc(GetProcessHeap (), HEAP_ZERO_MEMORY,
-			sizeof(STATUSWINDOWPART) * self->numParts);
+	tmp = COMCTL32_Alloc (sizeof(STATUSWINDOWPART) * self->numParts);
 	for (i = 0; i < oldNumParts; i++) {
 	    tmp[i] = self->parts[i];
 	}
 	if (self->parts)
-	    HeapFree(GetProcessHeap (), 0, self->parts);
+	    COMCTL32_Free (self->parts);
 	self->parts = tmp;
     }
     
@@ -614,10 +612,10 @@
     else {
 	/* duplicate string */
 	if (part->text)
-	    HeapFree (GetProcessHeap (), 0, part->text);
+	    COMCTL32_Free (part->text);
 	part->text = 0;
 	if (text && (len = lstrlen32A(text))) {
-	    part->text = HeapAlloc (GetProcessHeap (), 0, len+1);
+	    part->text = COMCTL32_Alloc (len+1);
 	    lstrcpy32A(part->text, text);
 	}
     }
@@ -694,8 +692,7 @@
     HDC32	hdc;
     STATUSWINDOWINFO *self;
 
-    self = (STATUSWINDOWINFO*)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-					 sizeof(STATUSWINDOWINFO));
+    self = (STATUSWINDOWINFO*)COMCTL32_Alloc (sizeof(STATUSWINDOWINFO));
     wndPtr->wExtra[0] = (DWORD)self;
 
     self->numParts = 1;
@@ -717,8 +714,7 @@
     self->part0.hIcon = 0;
 
     /* initialize first part */
-    self->parts = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-			     sizeof(STATUSWINDOWPART));
+    self->parts = COMCTL32_Alloc (sizeof(STATUSWINDOWPART));
     self->parts[0].bound = rect;
     self->parts[0].text = 0;
     self->parts[0].x = -1;
@@ -726,7 +722,7 @@
     self->parts[0].hIcon = 0;
 
     if ((len = lstrlen32A (lpCreate->lpszName))) {
-        self->parts[0].text = HeapAlloc (GetProcessHeap (), 0, len + 1);
+        self->parts[0].text = COMCTL32_Alloc (len + 1);
         lstrcpy32A (self->parts[0].text, lpCreate->lpszName);
     }
 
@@ -781,11 +777,11 @@
 
     for (i = 0; i < self->numParts; i++) {
 	if (self->parts[i].text && (self->parts[i].style != SBT_OWNERDRAW))
-	    HeapFree(GetProcessHeap (), 0, self->parts[i].text);
+	    COMCTL32_Free (self->parts[i].text);
     }
     if (self->part0.text && (self->part0.style != SBT_OWNERDRAW))
-	HeapFree(GetProcessHeap (), 0, self->part0.text);
-    HeapFree(GetProcessHeap (), 0, self->parts);
+	COMCTL32_Free (self->part0.text);
+    COMCTL32_Free (self->parts);
 
     /* delete default font */
     if (self->hDefaultFont)
@@ -795,7 +791,7 @@
     if (self->hwndToolTip)
 	DestroyWindow32 (self->hwndToolTip);
 
-    HeapFree(GetProcessHeap (), 0, self);
+    COMCTL32_Free (self);
 
     return 0;
 }
@@ -939,10 +935,10 @@
     part = &self->parts[0];
     /* duplicate string */
     if (part->text)
-        HeapFree(GetProcessHeap (), 0, part->text);
+        COMCTL32_Free (part->text);
     part->text = 0;
     if (lParam && (len = lstrlen32A((LPCSTR)lParam))) {
-        part->text = HeapAlloc (GetProcessHeap (), 0, len+1);
+        part->text = COMCTL32_Alloc (len+1);
         lstrcpy32A (part->text, (LPCSTR)lParam);
     }
 
diff --git a/dlls/comctl32/toolbar.c b/dlls/comctl32/toolbar.c
index a1ac4e3..2a89d4b 100644
--- a/dlls/comctl32/toolbar.c
+++ b/dlls/comctl32/toolbar.c
@@ -4,11 +4,9 @@
  * Copyright 1998 Eric Kohl
  *
  * TODO:
- *   - Bitmap drawing.
  *   - Button wrapping.
  *   - Messages.
  *   - Notifications.
- *   - Fix TB_GETBITMAPFLAGS.
  *   - Fix TB_GETROWS and TB_SETROWS.
  *   - Tooltip support (almost complete).
  *   - Unicode suppport.
@@ -27,11 +25,10 @@
  */
 
 #include "windows.h"
-#include "sysmetrics.h"
 #include "commctrl.h"
+#include "sysmetrics.h"
 #include "cache.h"
 #include "toolbar.h"
-#include "heap.h"
 #include "win.h"
 #include "debug.h"
 
@@ -67,13 +64,13 @@
 TOOLBAR_DrawString (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
 		    HDC32 hdc, INT32 nState)
 {
-    RECT32 rcText = btnPtr->rect;
-    HFONT32 hOldFont;
-    INT32   nOldBkMode;
+    RECT32   rcText = btnPtr->rect;
+    HFONT32  hOldFont;
+    INT32    nOldBkMode;
+    COLORREF clrOld;
 
     /* draw text */
     if ((btnPtr->iString > -1) && (btnPtr->iString < infoPtr->nNumStrings)) {
-
 	InflateRect32 (&rcText, -3, -3);
 	rcText.top += infoPtr->nBitmapHeight;
 	if (nState & (TBSTATE_PRESSED | TBSTATE_CHECKED))
@@ -82,28 +79,27 @@
 	hOldFont = SelectObject32 (hdc, infoPtr->hFont);
 	nOldBkMode = SetBkMode32 (hdc, TRANSPARENT);
 	if (!(nState & TBSTATE_ENABLED)) {
-	    COLORREF clrOld = 
-		SetTextColor32 (hdc, GetSysColor32 (COLOR_3DHILIGHT));
+	    clrOld = SetTextColor32 (hdc, GetSysColor32 (COLOR_3DHILIGHT));
 	    OffsetRect32 (&rcText, 1, 1);
-	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1, &rcText,
-			 DT_CENTER);
+	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1,
+			 &rcText, infoPtr->dwDTFlags);
 	    SetTextColor32 (hdc, GetSysColor32 (COLOR_3DSHADOW));
 	    OffsetRect32 (&rcText, -1, -1);
-	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1, &rcText,
-			 DT_CENTER);
-	    SetTextColor32 (hdc, clrOld);
+	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1,
+			 &rcText, infoPtr->dwDTFlags);
 	}
 	else if (nState & TBSTATE_INDETERMINATE) {
-	    COLORREF clrOld = 
-		SetTextColor32 (hdc, GetSysColor32 (COLOR_3DSHADOW));
-	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1, &rcText,
-			 DT_CENTER);
-	    SetTextColor32 (hdc, clrOld);
+	    clrOld = SetTextColor32 (hdc, GetSysColor32 (COLOR_3DSHADOW));
+	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1,
+			 &rcText, infoPtr->dwDTFlags);
 	}
-	else
-	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1, &rcText,
-			 DT_CENTER);
+	else {
+	    clrOld = SetTextColor32 (hdc, GetSysColor32 (COLOR_BTNTEXT));
+	    DrawText32A (hdc, infoPtr->strings[btnPtr->iString], -1,
+			 &rcText, infoPtr->dwDTFlags);
+	}
 
+	SetTextColor32 (hdc, clrOld);
 	SelectObject32 (hdc, hOldFont);
 	if (nOldBkMode != TRANSPARENT)
 	    SetBkMode32 (hdc, nOldBkMode);
@@ -112,6 +108,46 @@
 
 
 static void
+TOOLBAR_DrawPattern (HDC32 hdc, LPRECT32 lpRect)
+{
+    HBRUSH32 hbr = SelectObject32 (hdc, CACHE_GetPattern55AABrush ());
+    INT32 cx = lpRect->right - lpRect->left;
+    INT32 cy = lpRect->bottom - lpRect->top;
+    PatBlt32 (hdc, lpRect->left, lpRect->top, cx, cy, 0x00FA0089);
+    SelectObject32 (hdc, hbr);
+}
+
+
+static void
+TOOLBAR_DrawMasked (TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr,
+		    HDC32 hdc, INT32 x, INT32 y)
+{
+    /* FIXME: this function is a hack since it uses image list
+	      internals directly */
+
+    HDC32 hdcImageList = CreateCompatibleDC32 (0);
+    HIMAGELIST himl = infoPtr->himlDef;
+
+    /* draw the mask */
+    SelectObject32 (hdcImageList, himl->hbmMask);
+    SetBkColor32 (hdcImageList, RGB(255, 255, 255));
+    SetTextColor32 (hdcImageList, RGB(0, 0, 0));
+
+    SelectObject32 (hdc, GetSysColorBrush32 (COLOR_3DHILIGHT));
+    BitBlt32 (hdc, x+1, y+1, himl->cx, himl->cy,
+	      hdcImageList, himl->cx * btnPtr->iBitmap, 0,
+		  0xB8074A);
+
+    SelectObject32 (hdc, GetSysColorBrush32 (COLOR_3DSHADOW));
+    BitBlt32 (hdc, x, y, himl->cx, himl->cy,
+	      hdcImageList, himl->cx * btnPtr->iBitmap, 0,
+		  0xB8074A);
+
+    DeleteDC32 (hdcImageList);
+}
+
+
+static void
 TOOLBAR_DrawButton (WND *wndPtr, TBUTTON_INFO *btnPtr, HDC32 hdc)
 {
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
@@ -129,12 +165,11 @@
 
     /* disabled */
     if (!(btnPtr->fsState & TBSTATE_ENABLED)) {
-	HICON32 hIcon;
 	DrawEdge32 (hdc, &rc, EDGE_RAISED,
 		    BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
 
-//	ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
-//			rc.left+1, rc.top+1, ILD_NORMAL);
+	TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
+
 	TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState);
 	return;
     }
@@ -152,7 +187,6 @@
     /* checked TBSTYLE_CHECK*/
     if ((btnPtr->fsStyle & TBSTYLE_CHECK) &&
 	(btnPtr->fsState & TBSTATE_CHECKED)) {
-	HBRUSH32 hbr;
 	if (bFlat)
 	    DrawEdge32 (hdc, &rc, BDR_SUNKENOUTER,
 			BF_RECT | BF_MIDDLE | BF_ADJUST);
@@ -160,10 +194,7 @@
 	    DrawEdge32 (hdc, &rc, EDGE_SUNKEN,
 			BF_RECT | BF_MIDDLE | BF_ADJUST);
 
-	hbr = SelectObject32 (hdc, CACHE_GetPattern55AABrush ());
-	PatBlt32 (hdc, rc.left, rc.top, rc.right - rc.left,
-		  rc.bottom - rc.top, 0x00FA0089);
-	SelectObject32 (hdc, hbr);
+	TOOLBAR_DrawPattern (hdc, &rc);
 	ImageList_Draw (infoPtr->himlDef, btnPtr->iBitmap, hdc,
 			rc.left+2, rc.top+2, ILD_NORMAL);
 	TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState);
@@ -172,16 +203,11 @@
 
     /* indeterminate */	
     if (btnPtr->fsState & TBSTATE_INDETERMINATE) {
-	HBRUSH32 hbr;
 	DrawEdge32 (hdc, &rc, EDGE_RAISED,
 		    BF_SOFT | BF_RECT | BF_MIDDLE | BF_ADJUST);
 
-	hbr = SelectObject32 (hdc, CACHE_GetPattern55AABrush ());
-	PatBlt32 (hdc, rc.left, rc.top, rc.right - rc.left,
-		  rc.bottom - rc.top, 0x00FA0089);
-	SelectObject32 (hdc, hbr);
-//	ImageList_Draw (infoPtr->himlDis, btnPtr->iBitmap, hdc,
-//			rc.left+1, rc.top+1, ILD_NORMAL);
+	TOOLBAR_DrawPattern (hdc, &rc);
+	TOOLBAR_DrawMasked (infoPtr, btnPtr, hdc, rc.left+1, rc.top+1);
 	TOOLBAR_DrawString (infoPtr, btnPtr, hdc, btnPtr->fsState);
 	return;
     }
@@ -495,7 +521,7 @@
     if (lpAddBmp->hInst == (HINSTANCE32)0) {
 	nIndex = 
 	    ImageList_AddMasked (infoPtr->himlDef, (HBITMAP32)lpAddBmp->nID,
-				 GetSysColor32 (COLOR_3DFACE));
+				 CLR_DEFAULT);
     }
     else if (lpAddBmp->hInst == HINST_COMMCTRL) {
 	/* add internal bitmaps */
@@ -510,7 +536,7 @@
 	HBITMAP32 hBmp =
 	    LoadBitmap32A (lpAddBmp->hInst, (LPSTR)lpAddBmp->nID);
 
-	nIndex = ImageList_Add (infoPtr->himlDef, hBmp, (HBITMAP32)0);
+	nIndex = ImageList_AddMasked (infoPtr->himlDef, hBmp, CLR_DEFAULT);
 
 	DeleteObject32 (hBmp); 
     }
@@ -538,17 +564,15 @@
 
     if (infoPtr->nNumButtons == 0) {
 	infoPtr->buttons =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-		       sizeof (TBUTTON_INFO) * nNewButtons);
+	    COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
     }
     else {
 	TBUTTON_INFO *oldButtons = infoPtr->buttons;
 	infoPtr->buttons =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-		       sizeof (TBUTTON_INFO) * nNewButtons);
+	    COMCTL32_Alloc (sizeof(TBUTTON_INFO) * nNewButtons);
 	memcpy (&infoPtr->buttons[0], &oldButtons[0],
 		nOldButtons * sizeof(TBUTTON_INFO));
-        HeapFree (GetProcessHeap (), 0, oldButtons);
+        COMCTL32_Free (oldButtons);
     }
 
     infoPtr->nNumButtons = nNewButtons;
@@ -609,20 +633,19 @@
 	nIndex = infoPtr->nNumStrings;
 	if (infoPtr->nNumStrings == 0) {
 	    infoPtr->strings =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(char *));
+		COMCTL32_Alloc (sizeof(char *));
 	}
 	else {
 	    char **oldStrings = infoPtr->strings;
 	    infoPtr->strings =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-			   sizeof(char *) * (infoPtr->nNumStrings + 1));
+		COMCTL32_Alloc (sizeof(char *) * (infoPtr->nNumStrings + 1));
 	    memcpy (&infoPtr->strings[0], &oldStrings[0],
 		    sizeof(char *) * infoPtr->nNumStrings);
-	    HeapFree (GetProcessHeap (), 0, oldStrings);
+	    COMCTL32_Free (oldStrings);
 	}
 
 	infoPtr->strings[infoPtr->nNumStrings] =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(char)*(len+1));
+	    COMCTL32_Alloc (sizeof(char)*(len+1));
 	lstrcpy32A (infoPtr->strings[infoPtr->nNumStrings], szString);
 	infoPtr->nNumStrings++;
     }
@@ -639,20 +662,19 @@
 
 	    if (infoPtr->nNumStrings == 0) {
 		infoPtr->strings =
-		    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(char *));
+		    COMCTL32_Alloc (sizeof(char *));
 	    }
 	    else {
 		char **oldStrings = infoPtr->strings;
 		infoPtr->strings =
-		    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-			       sizeof(char *) * (infoPtr->nNumStrings + 1));
+		    COMCTL32_Alloc (sizeof(char *) * (infoPtr->nNumStrings + 1));
 		memcpy (&infoPtr->strings[0], &oldStrings[0],
 			sizeof(char *) * infoPtr->nNumStrings);
-		HeapFree (GetProcessHeap (), 0, oldStrings);
+		COMCTL32_Free (oldStrings);
 	    }
 
 	    infoPtr->strings[infoPtr->nNumStrings] =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(char)*(len+1));
+		COMCTL32_Alloc (sizeof(char)*(len+1));
 	    lstrcpy32A (infoPtr->strings[infoPtr->nNumStrings], p);
 	    infoPtr->nNumStrings++;
 
@@ -841,7 +863,7 @@
 
     if (infoPtr->nNumButtons == 1) {
 	TRACE (toolbar, " simple delete!\n");
-	HeapFree (GetProcessHeap (), 0, infoPtr->buttons);
+	COMCTL32_Free (infoPtr->buttons);
 	infoPtr->buttons = NULL;
 	infoPtr->nNumButtons = 0;
     }
@@ -850,8 +872,7 @@
         TRACE(toolbar, "complex delete! [nIndex=%d]\n", nIndex);
 
 	infoPtr->nNumButtons--;
-	infoPtr->buttons = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-				      sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
+	infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
         if (nIndex > 0) {
             memcpy (&infoPtr->buttons[0], &oldButtons[0],
                     nIndex * sizeof(TBUTTON_INFO));
@@ -862,7 +883,7 @@
                     (infoPtr->nNumButtons - nIndex) * sizeof(TBUTTON_INFO));
         }
 
-        HeapFree (GetProcessHeap (), 0, oldButtons);
+	COMCTL32_Free (oldButtons);
     }
 
     TOOLBAR_CalcToolbar (wndPtr);
@@ -911,17 +932,16 @@
 
     nIndex = TOOLBAR_GetButtonIndex (infoPtr, (INT32)wParam);
     if (nIndex == -1)
-	return 0;
+	return -1;
 
     return infoPtr->buttons[nIndex].iBitmap;
 }
 
 
-static LRESULT
+static __inline__ LRESULT
 TOOLBAR_GetBitmapFlags (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-    FIXME (toolbar, "stub!\n");
-    return 0;
+    return (GetDeviceCaps32 (0, LOGPIXELSX) >= 120) ? TBBF_LARGE : 0;
 }
 
 
@@ -1312,8 +1332,7 @@
 
     oldButtons = infoPtr->buttons;
     infoPtr->nNumButtons++;
-    infoPtr->buttons = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-				  sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
+    infoPtr->buttons = COMCTL32_Alloc (sizeof (TBUTTON_INFO) * infoPtr->nNumButtons);
     /* pre insert copy */
     if (nIndex > 0) {
 	memcpy (&infoPtr->buttons[0], &oldButtons[0],
@@ -1348,7 +1367,7 @@
 		(infoPtr->nNumButtons - nIndex - 1) * sizeof(TBUTTON_INFO));
     }
 
-    HeapFree (GetProcessHeap (), 0, oldButtons);
+    COMCTL32_Free (oldButtons);
 
     TOOLBAR_CalcToolbar (wndPtr);
 
@@ -1486,6 +1505,7 @@
 static LRESULT
 TOOLBAR_SaveRestore32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
+#if 0
     TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
     LPTBSAVEPARAMS32A lpSave = (LPTBSAVEPARAMS32A)lParam;
 
@@ -1506,6 +1526,7 @@
 
 
     }
+#endif
 
     return 0;
 }
@@ -1565,13 +1586,13 @@
 	if ((btnPtr->iString >= 0) || 
 	    (btnPtr->iString < infoPtr->nNumStrings)) {
 #if 0
-	    CHAR *lpString = infoPtr->strings[btnPtr->iString];
+	    CHAR **lpString = &infoPtr->strings[btnPtr->iString];
 	    INT32 len = lstrlen32A (lptbbi->pszText);
-
-	    lpString = HeapReAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, sizeof(char)*(len+1));
-
+	    *lpString = COMCTL32_ReAlloc (lpString, sizeof(char)*(len+1));
 #endif
 
+	    /* this is the ultimate sollution */
+//	    Str_SetPtrA (&infoPtr->strings[btnPtr->iString], lptbbi->pszText);
 	}
     }
 
@@ -1654,7 +1675,18 @@
 }
 
 
-// << TOOLBAR_SetDrawTextFlags >>
+static LRESULT
+TOOLBAR_SetDrawTextFlags (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TOOLBAR_INFO *infoPtr = TOOLBAR_GetInfoPtr(wndPtr);
+    DWORD dwTemp;
+
+    dwTemp = infoPtr->dwDTFlags;
+    infoPtr->dwDTFlags =
+	(infoPtr->dwDTFlags & (DWORD)wParam) | (DWORD)lParam;
+
+    return (LRESULT)dwTemp;
+}
 
 
 static LRESULT
@@ -1910,6 +1942,7 @@
     infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
     infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
     infoPtr->nHotItem = -1;
+    infoPtr->dwDTFlags = DT_CENTER;
 
     SystemParametersInfo32A (SPI_GETICONTITLELOGFONT, 0, &logFont, 0);
     infoPtr->hFont = CreateFontIndirect32A (&logFont);
@@ -1951,16 +1984,16 @@
 
     /* delete button data */
     if (infoPtr->buttons)
-	HeapFree (GetProcessHeap (), 0, infoPtr->buttons);
+	COMCTL32_Free (infoPtr->buttons);
 
     /* delete strings */
     if (infoPtr->strings) {
 	INT32 i;
 	for (i = 0; i < infoPtr->nNumStrings; i++)
 	    if (infoPtr->strings[i])
-		HeapFree (GetProcessHeap (), 0, infoPtr->strings[i]);
+		COMCTL32_Free (infoPtr->strings[i]);
 
-	HeapFree (GetProcessHeap (), 0, infoPtr->strings);
+	COMCTL32_Free (infoPtr->strings);
     }
 
     /* destroy default image list */
@@ -1980,7 +2013,7 @@
 	DeleteObject32 (infoPtr->hFont);
 
     /* free toolbar info data */
-    HeapFree (GetProcessHeap (), 0, infoPtr);
+    COMCTL32_Free (infoPtr);
 
     return 0;
 }
@@ -2178,7 +2211,15 @@
 }
 
 
-// << TOOLBAR_NCActivate >>
+__inline__ static LRESULT
+TOOLBAR_NCActivate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+//    if (wndPtr->dwStyle & CCS_NODIVIDER)
+	return DefWindowProc32A (wndPtr->hwndSelf, WM_NCACTIVATE,
+				 wParam, lParam);
+//    else
+//	return TOOLBAR_NCPaint (wndPtr, wParam, lParam);
+}
 
 
 __inline__ static LRESULT
@@ -2197,8 +2238,7 @@
     TOOLBAR_INFO *infoPtr;
 
     /* allocate memory for info structure */
-    infoPtr = (TOOLBAR_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                   sizeof(TOOLBAR_INFO));
+    infoPtr = (TOOLBAR_INFO *)COMCTL32_Alloc (sizeof(TOOLBAR_INFO));
     wndPtr->wExtra[0] = (DWORD)infoPtr;
 
     if (infoPtr == NULL) {
@@ -2568,7 +2608,8 @@
 	case TB_SETDISABLEDIMAGELIST:
 	    return TOOLBAR_SetDisabledImageList (wndPtr, wParam, lParam);
 
-//	case TB_SETDRAWTEXTFLAGS:		/* 4.71 */
+	case TB_SETDRAWTEXTFLAGS:
+	    return TOOLBAR_SetDrawTextFlags (wndPtr, wParam, lParam);
 
 	case TB_SETEXTENDEDSTYLE:
 	    return TOOLBAR_SetExtendedStyle (wndPtr, wParam, lParam);
@@ -2640,8 +2681,8 @@
 	case WM_MOUSEMOVE:
 	    return TOOLBAR_MouseMove (wndPtr, wParam, lParam);
 
-//	case WM_NCACTIVATE:
-//	    return TOOLBAR_NCActivate (wndPtr, wParam, lParam);
+	case WM_NCACTIVATE:
+	    return TOOLBAR_NCActivate (wndPtr, wParam, lParam);
 
 	case WM_NCCALCSIZE:
 	    return TOOLBAR_NCCalcSize (wndPtr, wParam, lParam);
diff --git a/dlls/comctl32/tooltips.c b/dlls/comctl32/tooltips.c
index 93ea5f3..419f605 100644
--- a/dlls/comctl32/tooltips.c
+++ b/dlls/comctl32/tooltips.c
@@ -21,7 +21,6 @@
 #include "windows.h"
 #include "commctrl.h"
 #include "tooltips.h"
-#include "heap.h"
 #include "win.h"
 #include "debug.h"
 
@@ -108,8 +107,7 @@
 		if (ttnmdi.uFlags & TTF_DI_SETITEM) {
 		    INT32 len = lstrlen32A (ttnmdi.szText) + 1;
 		    toolPtr->hinst = 0;
-		    toolPtr->lpszText =	
-			HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len);
+		    toolPtr->lpszText =	COMCTL32_Alloc (len);
 		    lstrcpy32A (toolPtr->lpszText, ttnmdi.szText);
 		}
 	    }
@@ -124,8 +122,7 @@
 		if (ttnmdi.uFlags & TTF_DI_SETITEM) {
 		    INT32 len = lstrlen32A (ttnmdi.lpszText) + 1;
 		    toolPtr->hinst = 0;
-		    toolPtr->lpszText =	
-			HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len);
+		    toolPtr->lpszText =	COMCTL32_Alloc (len);
 		    lstrcpy32A (toolPtr->lpszText, ttnmdi.lpszText);
 		}
 	    }
@@ -177,7 +174,7 @@
 TOOLTIPS_Show (WND *wndPtr, TOOLTIPS_INFO *infoPtr)
 {
     TTTOOL_INFO *toolPtr;
-    POINT32 pt;
+    RECT32 rect;
     SIZE32 size;
     NMHDR hdr;
 
@@ -212,31 +209,37 @@
     TRACE (tooltips, "size %d - %d\n", size.cx, size.cy);
 
     if ((toolPtr->uFlags & TTF_TRACK) && (toolPtr->uFlags & TTF_ABSOLUTE)) {
-	pt.x = infoPtr->xTrackPos;
-	pt.y = infoPtr->yTrackPos;
+	rect.left = infoPtr->xTrackPos;
+	rect.top  = infoPtr->yTrackPos;
     }
     else if (toolPtr->uFlags & TTF_CENTERTIP) {
-	RECT32 rect;
+	RECT32 rc;
 
 	if (toolPtr->uFlags & TTF_IDISHWND)
-	    GetWindowRect32 ((HWND32)toolPtr->uId, &rect);
+	    GetWindowRect32 ((HWND32)toolPtr->uId, &rc);
 	else {
-	    rect = toolPtr->rect;
-	    MapWindowPoints32 (toolPtr->hwnd, (HWND32)0, (LPPOINT32)&rect, 2);
+	    rc = toolPtr->rect;
+	    MapWindowPoints32 (toolPtr->hwnd, (HWND32)0, (LPPOINT32)&rc, 2);
 	}
-	pt.x = (rect.left + rect.right - size.cx) / 2;
-	pt.y = rect.bottom + 2;
+	rect.left = (rc.left + rc.right - size.cx) / 2;
+	rect.top  = rc.bottom + 2;
     }
     else {
-	GetCursorPos32 (&pt);
-	pt.y += 20;
+	GetCursorPos32 ((LPPOINT32)&rect);
+	rect.top += 20;
     }
 
-    TRACE (tooltips, "pos %d - %d\n", pt.x, pt.y);
+    TRACE (tooltips, "pos %d - %d\n", rect.left, rect.top);
+
+    rect.right = rect.left + size.cx;
+    rect.bottom = rect.top + size.cy;
+
+    AdjustWindowRectEx32 (&rect, wndPtr->dwStyle, FALSE, wndPtr->dwExStyle);
 
 //    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 1, 1,
-    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, pt.x, pt.y,
-		    size.cx, size.cy, SWP_SHOWWINDOW);
+    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, rect.left, rect.top,
+		    rect.right - rect.left, rect.bottom - rect.top,
+		    SWP_SHOWWINDOW);
 
     SetTimer32 (wndPtr->hwndSelf, ID_TIMER2, infoPtr->nAutoPopTime, 0);
 }
@@ -263,7 +266,8 @@
 
     infoPtr->nCurrentTool = -1;
 
-    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0, SWP_HIDEWINDOW);
+    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0,
+		    SWP_NOZORDER | SWP_HIDEWINDOW);
 }
 
 
@@ -406,19 +410,16 @@
 	   (lpToolInfo->uFlags & TTF_IDISHWND) ? " TTF_IDISHWND" : "");
 
     if (infoPtr->uNumTools == 0) {
-	infoPtr->tools =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-		       sizeof(TTTOOL_INFO));
+	infoPtr->tools = COMCTL32_Alloc (sizeof(TTTOOL_INFO));
 	toolPtr = infoPtr->tools;
     }
     else {
 	TTTOOL_INFO *oldTools = infoPtr->tools;
 	infoPtr->tools =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-		       sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
+	    COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools + 1));
 	memcpy (infoPtr->tools, oldTools,
 		infoPtr->uNumTools * sizeof(TTTOOL_INFO));
-	HeapFree (GetProcessHeap (), 0, oldTools);
+	COMCTL32_Free (oldTools);
 	toolPtr = &infoPtr->tools[infoPtr->uNumTools];
     }
 
@@ -443,8 +444,7 @@
 	else {
 	    INT32 len = lstrlen32A (lpToolInfo->lpszText);
 	    TRACE (tooltips, "add text \"%s\"!\n", lpToolInfo->lpszText);
-	    toolPtr->lpszText =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
+	    toolPtr->lpszText =	COMCTL32_Alloc (len + 1);
 	    lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
 	}
     }
@@ -458,8 +458,8 @@
 	    LPTT_SUBCLASS_INFO lpttsi =
 		(LPTT_SUBCLASS_INFO)GetProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
 	    if (lpttsi == NULL) {
-		lpttsi = (LPTT_SUBCLASS_INFO)HeapAlloc (GetProcessHeap(),
-		    HEAP_ZERO_MEMORY, sizeof(TT_SUBCLASS_INFO));
+		lpttsi =
+		    (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
 		lpttsi->wpOrigProc = 
 		    (WNDPROC32)SetWindowLong32A ((HWND32)toolPtr->uId,
 		    GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
@@ -475,8 +475,8 @@
 	    LPTT_SUBCLASS_INFO lpttsi =
 		(LPTT_SUBCLASS_INFO)GetProp32A (toolPtr->hwnd, TT_SUBCLASS_PROP);
 	    if (lpttsi == NULL) {
-		lpttsi = (LPTT_SUBCLASS_INFO)HeapAlloc (GetProcessHeap(),
-		    HEAP_ZERO_MEMORY, sizeof(TT_SUBCLASS_INFO));
+		lpttsi =
+		    (LPTT_SUBCLASS_INFO)COMCTL32_Alloc (sizeof(TT_SUBCLASS_INFO));
 		lpttsi->wpOrigProc = 
 		    (WNDPROC32)SetWindowLong32A (toolPtr->hwnd,
 		    GWL_WNDPROC,(LONG)TOOLTIPS_SubclassProc);
@@ -521,7 +521,7 @@
     toolPtr = &infoPtr->tools[nTool]; 
     if ((toolPtr->hinst) && (toolPtr->lpszText)) {
 	if (toolPtr->lpszText != LPSTR_TEXTCALLBACK32A)
-	    HeapFree (GetProcessHeap (), 0, toolPtr->lpszText);
+	    COMCTL32_Free (toolPtr->lpszText);
     }
 
     /* remove subclassing */
@@ -533,7 +533,7 @@
 		SetWindowLong32A ((HWND32)toolPtr->uId, GWL_WNDPROC,
 				  (LONG)lpttsi->wpOrigProc);
 		RemoveProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
-		HeapFree (GetProcessHeap(), 0, &lpttsi);
+		COMCTL32_Free (&lpttsi);
 	    }
 	    else
 		ERR (tooltips, "Invalid data handle!\n");
@@ -546,7 +546,7 @@
 		    SetWindowLong32A ((HWND32)toolPtr->uId, GWL_WNDPROC,
 				      (LONG)lpttsi->wpOrigProc);
 		    RemoveProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
-		    HeapFree (GetProcessHeap(), 0, &lpttsi);
+		    COMCTL32_Free (&lpttsi);
 		}
 		else
 		    lpttsi->uRefCount--;
@@ -558,14 +558,13 @@
 
     /* delete tool from tool list */
     if (infoPtr->uNumTools == 1) {
-	HeapFree (GetProcessHeap (), 0, infoPtr->tools);
+	COMCTL32_Free (infoPtr->tools);
 	infoPtr->tools = NULL;
     }
     else {
 	TTTOOL_INFO *oldTools = infoPtr->tools;
 	infoPtr->tools =
-	    HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-		       sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
+	    COMCTL32_Alloc (sizeof(TTTOOL_INFO) * (infoPtr->uNumTools - 1));
 
 	if (nTool > 0)
 	    memcpy (&infoPtr->tools[0], &oldTools[0],
@@ -575,7 +574,7 @@
 	    memcpy (&infoPtr->tools[nTool], &oldTools[nTool + 1],
 		    (infoPtr->uNumTools - nTool - 1) * sizeof(TTTOOL_INFO));
 
-	HeapFree (GetProcessHeap (), 0, oldTools);
+	COMCTL32_Free (oldTools);
     }
 
     infoPtr->uNumTools--;
@@ -1051,9 +1050,8 @@
 	    toolPtr->lpszText = lpToolInfo->lpszText;
 	else {
 	    INT32 len = lstrlen32A (lpToolInfo->lpszText);
-	    HeapFree (GetProcessHeap (), 0, toolPtr->lpszText);
-	    toolPtr->lpszText =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
+	    COMCTL32_Free (toolPtr->lpszText);
+	    toolPtr->lpszText =	COMCTL32_Alloc (len + 1);
 	    lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
 	}
     }
@@ -1160,9 +1158,8 @@
 	    toolPtr->lpszText = lpToolInfo->lpszText;
 	else {
 	    INT32 len = lstrlen32A (lpToolInfo->lpszText);
-	    HeapFree (GetProcessHeap (), 0, toolPtr->lpszText);
-	    toolPtr->lpszText =
-		HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len + 1);
+	    COMCTL32_Free (toolPtr->lpszText);
+	    toolPtr->lpszText =	COMCTL32_Alloc (len + 1);
 	    lstrcpy32A (toolPtr->lpszText, lpToolInfo->lpszText);
 	}
     }
@@ -1189,8 +1186,7 @@
     NONCLIENTMETRICS32A nclm;
 
     /* allocate memory for info structure */
-    infoPtr = (TOOLTIPS_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-					  sizeof(TOOLTIPS_INFO));
+    infoPtr = (TOOLTIPS_INFO *)COMCTL32_Alloc (sizeof(TOOLTIPS_INFO));
     wndPtr->wExtra[0] = (DWORD)infoPtr;
 
     if (infoPtr == NULL) {
@@ -1219,7 +1215,8 @@
     infoPtr->nAutoPopTime   = 5000;
     infoPtr->nInitialTime   = 500;
 
-    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0, SWP_HIDEWINDOW);
+    SetWindowPos32 (wndPtr->hwndSelf, HWND_TOP, 0, 0, 0, 0,
+		    SWP_NOZORDER | SWP_HIDEWINDOW);
 
     return 0;
 }
@@ -1230,15 +1227,15 @@
 {
     TOOLTIPS_INFO *infoPtr = TOOLTIPS_GetInfoPtr(wndPtr);
     TTTOOL_INFO *toolPtr;
+    INT32 i;
 
     /* free tools */
     if (infoPtr->tools) {
-	INT32 i;
 	for (i = 0; i < infoPtr->uNumTools; i++) {
 	    toolPtr = &infoPtr->tools[i];
 	    if ((toolPtr->hinst) && (toolPtr->lpszText)) {
 		if (toolPtr->lpszText != LPSTR_TEXTCALLBACK32A)
-		    HeapFree (GetProcessHeap (), 0, toolPtr->lpszText);
+		    COMCTL32_Free (toolPtr->lpszText);
 	    }
 
 	    /* remove subclassing */
@@ -1254,18 +1251,18 @@
 		    SetWindowLong32A ((HWND32)toolPtr->uId, GWL_WNDPROC,
 				      (LONG)lpttsi->wpOrigProc);
 		    RemoveProp32A ((HWND32)toolPtr->uId, TT_SUBCLASS_PROP);
-		    HeapFree (GetProcessHeap(), 0, &lpttsi);
+		    COMCTL32_Free (&lpttsi);
 		}
 	    }
 	}
-	HeapFree (GetProcessHeap (), 0, infoPtr->tools);
+	COMCTL32_Free (infoPtr->tools);
     }
 
     /* delete font */
     DeleteObject32 (infoPtr->hFont);
 
     /* free tool tips info data */
-    HeapFree (GetProcessHeap (), 0, infoPtr);
+    COMCTL32_Free (infoPtr);
 
     return 0;
 }
@@ -1327,7 +1324,10 @@
 TOOLTIPS_NcCreate (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     wndPtr->dwStyle &= 0x0000FFFF;
-    wndPtr->dwStyle |= (WS_POPUP | WS_BORDER);
+    wndPtr->dwStyle |= (WS_POPUP | WS_BORDER | WS_CLIPSIBLINGS);
+
+//    FIXME (tooltips, "style 0x%08x\n", wndPtr->dwStyle);
+//    SetParent32 (wndPtr->hwndSelf, NULL);
 
     return TRUE;
 }
diff --git a/dlls/comctl32/trackbar.c b/dlls/comctl32/trackbar.c
index f80f433..6470916 100644
--- a/dlls/comctl32/trackbar.c
+++ b/dlls/comctl32/trackbar.c
@@ -1,21 +1,31 @@
 /*
  * Trackbar control
  *
- * Copyright 1998 Eric Kohl
+ * Copyright 1998 Eric Kohli <ekohl@abo.rhein-zeitung.de>
+ * Copyright 1998 Alex Priem <alexp@sci.kun.nl>
  *
  * NOTES
- *   Development in progress. Author needed! Any volunteers?
- *   I will only improve this control once in a while.
- *     Eric <ekohl@abo.rhein-zeitung.de>
+
  *
  * TODO:
  *   - Some messages.
- *   - display code.
- *   - user interaction.
- *   - tic handling.
- *   - All notifications.
+ *   - more display code.
+ *   - dragging slider
+ *   - better tic handling.
+ *   - more notifications.
+ *   - tooltips
  */
 
+/* known bugs:
+
+	-TBM_SETRANGEMAX & TBM_SETRANGEMIN should only change the view of the
+   trackbar, not the actual amount of tics in the list.
+	-TBM_GETTIC & TBM_GETTICPOS shouldn't rely on infoPtr->tics being sorted.
+  	-code currently only handles horizontal trackbars correct.
+*/
+
+
+
 #include "windows.h"
 #include "commctrl.h"
 #include "trackbar.h"
@@ -27,88 +37,303 @@
 #define TRACKBAR_GetInfoPtr(wndPtr) ((TRACKBAR_INFO *)wndPtr->wExtra[0])
 
 
-static VOID
-TRACKBAR_Refresh (WND *wndPtr, HDC32 hdc)
+/* Used by TRACKBAR_Refresh to find out which parts of the control 
+	need to be recalculated */
+
+#define TB_THUMBCHANGED 	1
+#define TB_SELECTIONCHANGED 2
+
+
+
+static BOOL32 TRACKBAR_SendNotify (WND *wndPtr, UINT32 code);
+
+void TRACKBAR_RecalculateTics (TRACKBAR_INFO *infoPtr)
+
 {
-    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
-    RECT32 rcClient, rcChannel;
+    int i,tic,nrTics;
 
-    GetClientRect32 (wndPtr->hwndSelf, &rcClient);
+	if (infoPtr->uTicFreq) 
+    	nrTics=(infoPtr->nRangeMax - infoPtr->nRangeMin)/infoPtr->uTicFreq;
+	else {
+		nrTics=0;
+		HeapFree (SystemHeap,0,infoPtr->tics);
+		infoPtr->tics=NULL;
+		infoPtr->uNumTics=0;
+		return;
+	}
 
-    /* draw channel */
-    rcChannel = infoPtr->rcChannel;
-    DrawEdge32 (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
-    if (wndPtr->dwStyle & TBS_ENABLESELRANGE) {
-	/* fill the channel */
-	HBRUSH32 hbr = CreateSolidBrush32 (RGB(255,255,255));
-	FillRect32 (hdc, &rcChannel, hbr);
-	DeleteObject32 (hbr);
+    if (nrTics!=infoPtr->uNumTics) {
+    	infoPtr->tics=HeapReAlloc( SystemHeap, 0, infoPtr->tics,
+                           (nrTics+1)*sizeof (DWORD));
+    	infoPtr->uNumTics=nrTics;
     }
-
-    /* draw ticks */
-    if (!(wndPtr->dwStyle & TBS_NOTICKS)) {
-
-    }
-
-    /* draw thumb */
-    if (!(wndPtr->dwStyle & TBS_NOTHUMB)) {
-
-    }
-
-    if (infoPtr->bFocus)
-	DrawFocusRect32 (hdc, &rcClient);
+	infoPtr->uNumTics=nrTics;
+    tic=infoPtr->nRangeMin+infoPtr->uTicFreq;
+    for (i=0; i<nrTics; i++,tic+=infoPtr->uTicFreq)
+               infoPtr->tics[i]=tic;
 }
 
 
+
+static INT32
+TRACKBAR_ConvertPositionToTic (WND *wndPtr, TRACKBAR_INFO *infoPtr, POINT32 pt) 
+{
+	double newpos,newtic;
+    int i,range,width,delta,currentdelta,currenttic;
+
+/* buggy */
+
+    range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+    width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+	
+	newpos=(pt.x-infoPtr->rcChannel.left) / (double) width;
+
+	newtic=infoPtr->nRangeMin+newpos*range;
+	currenttic=0;
+	currentdelta=currenttic-infoPtr->nRangeMin;
+	for (i=0; i<infoPtr->uNumTics; i++) {
+		delta=newtic-infoPtr->tics[i];
+		if ((delta>0) && (delta<currentdelta)) {
+			currentdelta=delta;
+			currenttic=i;
+		}
+	}
+	return (INT32) currenttic;
+}
+
 static VOID
-TRACKBAR_Calc (WND *wndPtr, TRACKBAR_INFO *infoPtr, LPRECT32 lpRect)
+TRACKBAR_Calc (WND *wndPtr, TRACKBAR_INFO *infoPtr)
 {
     INT32 cyChannel;
+	RECT32 lpRect,*channel = & infoPtr->rcChannel;
+
+    GetClientRect32 (wndPtr->hwndSelf, &lpRect);
 
     if (wndPtr->dwStyle & TBS_ENABLESELRANGE)
-	cyChannel = MAX(infoPtr->uThumbLen - 8, 4);
+		cyChannel = MAX(infoPtr->uThumbLen - 8, 4);
     else
-	cyChannel = 4;
+		cyChannel = 4;
 
     /* calculate channel rect */
     if (wndPtr->dwStyle & TBS_VERT) {
-	infoPtr->rcChannel.top = lpRect->top + 8;
-	infoPtr->rcChannel.bottom = lpRect->bottom - 8;
+		channel->top    = lpRect.top + 8;
+		channel->bottom = lpRect.bottom - 8;
 
-	if (wndPtr->dwStyle & TBS_BOTH) {
-	    infoPtr->rcChannel.left = (lpRect->bottom - cyChannel ) / 2;
-	    infoPtr->rcChannel.right = (lpRect->bottom + cyChannel) / 2;
+			if (wndPtr->dwStyle & TBS_BOTH) {
+	    		channel->left  = (lpRect.bottom - cyChannel) / 2;
+	    		channel->right = (lpRect.bottom + cyChannel) / 2;
+			}
+			else if (wndPtr->dwStyle & TBS_LEFT) {
+	    			channel->left  = lpRect.left + 10;
+	    			channel->right = channel->left + cyChannel;
+				}
+				else { /* TBS_RIGHT */
+	    			channel->right = lpRect.right - 10;
+	    			channel->left  = channel->right - cyChannel;
+				}
+   	}
+   	else {
+			channel->left = lpRect.left + 8;
+			channel->right = lpRect.right - 8;
+			if (wndPtr->dwStyle & TBS_BOTH) {
+	    		channel->top		= (lpRect.bottom - cyChannel) / 2;
+	    		channel->bottom 	= (lpRect.bottom + cyChannel) / 2;
+			}
+			else if (wndPtr->dwStyle & TBS_TOP) {
+	    			channel->top    = lpRect.top + 10;
+	    			channel->bottom = channel->top + cyChannel;
+				}
+				else { /* TBS_BOTTOM */
+	    			channel->bottom = lpRect.bottom - 10;
+	    			channel->top    = channel->bottom - cyChannel;
+				}
 	}
-	else if (wndPtr->dwStyle & TBS_LEFT) {
-	    infoPtr->rcChannel.left = lpRect->left + 10;
-	    infoPtr->rcChannel.right = infoPtr->rcChannel.left + cyChannel;
-	}
-	else {
-	    /* TBS_RIGHT */
-	    infoPtr->rcChannel.right = lpRect->right - 10;
-	    infoPtr->rcChannel.left = infoPtr->rcChannel.right - cyChannel;
-	}
-    }
-    else {
-	infoPtr->rcChannel.left = lpRect->left + 8;
-	infoPtr->rcChannel.right = lpRect->right - 8;
-
-	if (wndPtr->dwStyle & TBS_BOTH) {
-	    infoPtr->rcChannel.top = (lpRect->bottom - cyChannel ) / 2;
-	    infoPtr->rcChannel.bottom = (lpRect->bottom + cyChannel) / 2;
-	}
-	else if (wndPtr->dwStyle & TBS_TOP) {
-	    infoPtr->rcChannel.top = lpRect->top + 10;
-	    infoPtr->rcChannel.bottom = infoPtr->rcChannel.top + cyChannel;
-	}
-	else {
-	    /* TBS_BOTTOM */
-	    infoPtr->rcChannel.bottom = lpRect->bottom - 10;
-	    infoPtr->rcChannel.top = infoPtr->rcChannel.bottom - cyChannel;
-	}
-    }
 }
 
+static VOID
+TRACKBAR_CalcThumb (WND *wndPtr, TRACKBAR_INFO *infoPtr)
+
+{
+	RECT32 *thumb;
+	int range, width;
+	
+	thumb=&infoPtr->rcThumb;
+	range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+    width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+
+	thumb->left  = infoPtr->rcChannel.left +
+					width*(65536*infoPtr->nPos/range)/65536 - 5;
+	thumb->right  = thumb->left + 10;
+	thumb->top	  = infoPtr->rcChannel.top - 1;
+	thumb->bottom = infoPtr->rcChannel.top + infoPtr->uThumbLen - 8;
+}
+
+static VOID
+TRACKBAR_CalcSelection (WND *wndPtr, TRACKBAR_INFO *infoPtr)
+{
+	RECT32 *selection;
+	int range, width;
+
+	selection= & infoPtr->rcSelection;
+	range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+    width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+	
+	selection->left   = infoPtr->rcChannel.left +
+						width*(65536*infoPtr->nSelMin/range)/65536;
+	selection->right  = infoPtr->rcChannel.left +
+						width*(65536*infoPtr->nSelMax/range)/65536;
+	selection->top    = infoPtr->rcChannel.top + 2;
+    selection->bottom = infoPtr->rcChannel.bottom - 2;
+}
+
+
+
+static VOID
+TRACKBAR_Refresh (WND *wndPtr, HDC32 hdc)
+{
+	TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+	RECT32 rcClient, rcChannel, rcSelection;
+	HBRUSH32 hBrush = CreateSolidBrush32 (infoPtr->clrBk);
+	INT32 x,y,tic;
+	int i,range,width;
+
+    GetClientRect32 (wndPtr->hwndSelf, &rcClient);
+	hBrush = CreateSolidBrush32 (infoPtr->clrBk);
+	FillRect32 (hdc, &rcClient, hBrush);
+    DeleteObject32 (hBrush);
+
+	
+	
+	if (infoPtr->flags & TB_THUMBCHANGED) 
+		TRACKBAR_CalcThumb	(wndPtr, infoPtr);
+	if (infoPtr->flags & TB_SELECTIONCHANGED)
+		TRACKBAR_CalcSelection (wndPtr, infoPtr);
+	infoPtr->flags &= ~ (TB_THUMBCHANGED | TB_SELECTIONCHANGED);
+
+    /* draw channel */
+
+    rcChannel = infoPtr->rcChannel;
+    rcSelection= infoPtr->rcSelection;
+    DrawEdge32 (hdc, &rcChannel, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
+
+    if (wndPtr->dwStyle & TBS_ENABLESELRANGE) {		 /* fill the channel */
+		HBRUSH32 hbr = CreateSolidBrush32 (RGB(255,255,255));
+		FillRect32 (hdc, &rcChannel, hbr);
+		if (rcSelection.left!=rcSelection.right) {
+			hbr=CreateSolidBrush32 (COLOR_HIGHLIGHT); 
+			FillRect32 (hdc, &rcSelection, hbr);
+		}
+		DeleteObject32 (hbr);
+    }
+
+
+    /* draw tics */
+
+    if (!(wndPtr->dwStyle & TBS_NOTICKS)) {
+		COLORREF clrTic=GetSysColor32 (COLOR_3DDKSHADOW);
+
+    	x=rcChannel.left;
+    	y=rcChannel.bottom+2;
+		range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+		width=rcChannel.right - rcChannel.left;
+    	if (wndPtr->dwStyle & TBS_VERT) { /* swap x/y */
+        }
+
+    if ((wndPtr->dwStyle & TBS_TOP) || (wndPtr->dwStyle & TBS_BOTH)) {
+        /* draw upper tics */
+     }
+
+//    if (!((wndPtr->dwStyle & TBS_TOP) || (!(wndPtr->dwStyle & TBS_BOTH)))) 
+        /* draw lower tics */
+//    if (wndPtr->dwStyle & TBS_AUTOTICKS) 
+        for (i=0; i<infoPtr->uNumTics; i++) {
+			tic=infoPtr->tics[i];
+			if ((tic>infoPtr->nRangeMin) && (tic<infoPtr->nRangeMax)) {
+            	x=rcChannel.left + width*(65536*tic/range)/65536;
+            	SetPixel32 (hdc, x,y+5, clrTic);
+            	SetPixel32 (hdc, x,y+6, clrTic);
+            	SetPixel32 (hdc, x,y+7, clrTic);
+			}
+          }
+	   if ((wndPtr->dwStyle & TBS_ENABLESELRANGE) && 
+		   (rcSelection.left!=rcSelection.right)) {
+			x=rcChannel.left + width*(65536*infoPtr->nSelMin/range)/65536 - 1;
+           	SetPixel32 (hdc, x,y+6, clrTic);
+           	SetPixel32 (hdc, x,y+7, clrTic);
+			x=rcChannel.left + width*(65536*infoPtr->nSelMax/range)/65536 + 1; 
+           	SetPixel32 (hdc, x,y+6, clrTic);
+           	SetPixel32 (hdc, x,y+7, clrTic);
+		}
+		
+	   x=rcChannel.left;
+       SetPixel32 (hdc, x,y+5, clrTic);
+       SetPixel32 (hdc, x,y+6, clrTic);
+       SetPixel32 (hdc, x,y+7, clrTic);
+       SetPixel32 (hdc, x,y+8, clrTic);
+	   x=rcChannel.right;
+       SetPixel32 (hdc, x,y+5, clrTic);
+       SetPixel32 (hdc, x,y+6, clrTic);
+       SetPixel32 (hdc, x,y+7, clrTic);
+       SetPixel32 (hdc, x,y+8, clrTic);
+//     }
+    }
+
+ 
+     /* draw thumb */
+
+     if (!(wndPtr->dwStyle & TBS_NOTHUMB)) {
+        HBRUSH32 hbr = CreateSolidBrush32 (COLOR_BACKGROUND);
+		RECT32 thumb = infoPtr->rcThumb;
+
+		SelectObject32 (hdc, hbr);
+		
+		if (wndPtr->dwStyle & TBS_BOTH) {
+        	FillRect32 (hdc, &thumb, hbr);
+  			DrawEdge32 (hdc, &thumb, EDGE_RAISED, BF_TOPLEFT);
+		} else {
+
+		POINT32 points[6];
+		RECT32 triangle;	/* for correct shadows of thumb */
+
+ 			/* first, fill the thumb */
+		
+		SetPolyFillMode32 (hdc,WINDING);
+		points[0].x=thumb.left;
+		points[0].y=thumb.top;
+		points[1].x=thumb.right - 1;
+		points[1].y=thumb.top;
+		points[2].x=thumb.right - 1;
+		points[2].y=thumb.bottom -2;
+		points[3].x=(thumb.right + thumb.left-1)/2;
+		points[3].y=thumb.bottom+4;
+		points[4].x=thumb.left;
+		points[4].y=thumb.bottom -2;
+		points[5].x=points[0].x;
+		points[5].y=points[0].y;
+		Polygon32 (hdc, points, 6);
+		DrawEdge32 (hdc, &thumb, EDGE_RAISED, BF_TOPLEFT);
+//		DrawEdge32 (hdc, &thumb, EDGE_SUNKEN, BF_BOTTOMRIGHT);
+
+			/* draw notch */
+
+		triangle.right = thumb.right+5;
+		triangle.left  = points[3].x+5;
+		triangle.top   = thumb.bottom +5;
+		triangle.bottom= thumb.bottom +1;
+		DrawEdge32 (hdc, &triangle, EDGE_SUNKEN, BF_DIAGONAL | BF_TOP | BF_RIGHT);
+		triangle.left  = thumb.left+6;
+		triangle.right = points[3].x+6;
+		DrawEdge32 (hdc, &triangle, EDGE_RAISED, BF_DIAGONAL | BF_TOP | BF_LEFT);
+		}
+		DeleteObject32 (hbr);
+     }
+
+    if (infoPtr->bFocus)
+		DrawFocusRect32 (hdc, &rcClient);
+}
+
+
+
 
 static VOID
 TRACKBAR_AlignBuddies (WND *wndPtr, TRACKBAR_INFO *infoPtr)
@@ -169,11 +394,12 @@
 
     infoPtr->nSelMin = 0;
     infoPtr->nSelMax = 0;
+	infoPtr->flags |=TB_SELECTIONCHANGED;
 
     if ((BOOL32)wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -186,16 +412,15 @@
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
     if (infoPtr->tics) {
-	FIXME (trackbar, "is this correct??\n");
-	HeapFree (GetProcessHeap (), 0, infoPtr->tics);
-	infoPtr->tics = NULL;
-	infoPtr->uNumTics = 2;
+		HeapFree (GetProcessHeap (), 0, infoPtr->tics);
+		infoPtr->tics = NULL;
+		infoPtr->uNumTics = 0;
     }
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -207,9 +432,8 @@
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
-    if (wParam)
-	/* buddy is left or above */
-	return (LRESULT)infoPtr->hwndBuddyLA;
+    if (wParam)		 /* buddy is left or above */
+		return (LRESULT)infoPtr->hwndBuddyLA;
 
     /* buddy is right or below */
     return (LRESULT) infoPtr->hwndBuddyRB;
@@ -223,7 +447,7 @@
     LPRECT32 lprc = (LPRECT32)lParam;
 
     if (lprc == NULL)
-	return 0;
+		return 0;
 
     lprc->left   = infoPtr->rcChannel.left;
     lprc->right  = infoPtr->rcChannel.right;
@@ -249,9 +473,9 @@
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
     if (wndPtr->dwStyle & TBS_NOTICKS)
-	return 0;
+		return 0;
 
-    return infoPtr->uNumTics;
+    return infoPtr->uNumTics+2;
 }
 
 
@@ -273,7 +497,6 @@
 }
 
 
-// << TRACKBAR_GetPTics >>
 
 
 static LRESULT
@@ -320,20 +543,78 @@
     return infoPtr->uThumbLen;
 }
 
+static LRESULT
+TRACKBAR_GetPTics (WND *wndPtr)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+    
+   return (LRESULT) infoPtr->tics;
+}
+
+static LRESULT
+TRACKBAR_GetThumbRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+    LPRECT32 lprc = (LPRECT32)lParam;
+    
+    if (lprc == NULL)
+   		return 0; 
+   
+    lprc->left   = infoPtr->rcThumb.left;
+    lprc->right  = infoPtr->rcThumb.right;
+    lprc->bottom = infoPtr->rcThumb.bottom;
+    lprc->top    = infoPtr->rcThumb.top;
+   
+    return 0;
+}  
 
 
-// << TRACKBAR_GetThumbRect >>
-//	case TBM_GETTIC:
-//	case TBM_GETTICPOS:
 
 
+
+static LRESULT
+TRACKBAR_GetTic (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+
+{
+ TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+ INT32 iTic;
+
+ iTic=(INT32) wParam;
+ if ((iTic<0) || (iTic>infoPtr->uNumTics)) 
+	return -1;
+
+ return (LRESULT) infoPtr->tics[iTic];
+
+}
+
+
+static LRESULT
+TRACKBAR_GetTicPos (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+
+{
+ TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+ INT32 iTic, range, width, pos;
+ 
+
+ iTic=(INT32 ) wParam;
+ if ((iTic<0) || (iTic>infoPtr->uNumTics)) 
+	return -1;
+
+ range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+ width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+ pos=infoPtr->rcChannel.left + width*(65536*infoPtr->tics[iTic]/range)/65536;
+
+
+ return (LRESULT) pos;
+}
+
 static LRESULT
 TRACKBAR_GetToolTips (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
     if (wndPtr->dwStyle & TBS_TOOLTIPS)
-	return (LRESULT)infoPtr->hwndToolTip;
+		return (LRESULT)infoPtr->hwndToolTip;
     return 0;
 }
 
@@ -355,11 +636,11 @@
 	FIXME (trackbar, "move buddy!\n");
     }
     else {
-	/* buddy is right or below */
-	hwndTemp = infoPtr->hwndBuddyRB;
-	infoPtr->hwndBuddyRB = (HWND32)lParam;
+		/* buddy is right or below */
+		hwndTemp = infoPtr->hwndBuddyRB;
+		infoPtr->hwndBuddyRB = (HWND32)lParam;
 
-	FIXME (trackbar, "move buddy!\n");
+		FIXME (trackbar, "move buddy!\n");
     }
 
     TRACKBAR_AlignBuddies (wndPtr, infoPtr);
@@ -404,11 +685,12 @@
 
     if (infoPtr->nPos > infoPtr->nRangeMax)
 	infoPtr->nPos = infoPtr->nRangeMax;
+	infoPtr->flags |=TB_THUMBCHANGED;
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -419,20 +701,26 @@
 TRACKBAR_SetRange (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
-
     infoPtr->nRangeMin = (INT32)LOWORD(lParam);
     infoPtr->nRangeMax = (INT32)HIWORD(lParam);
 
-    if (infoPtr->nPos < infoPtr->nRangeMin)
-	infoPtr->nPos = infoPtr->nRangeMin;
+    if (infoPtr->nPos < infoPtr->nRangeMin) {
+		infoPtr->nPos = infoPtr->nRangeMin;
+		infoPtr->flags |=TB_THUMBCHANGED;
+	}
 
-    if (infoPtr->nPos > infoPtr->nRangeMax)
-	infoPtr->nPos = infoPtr->nRangeMax;
+    if (infoPtr->nPos > infoPtr->nRangeMax) {
+		infoPtr->nPos = infoPtr->nRangeMax;
+		infoPtr->flags |=TB_THUMBCHANGED;
+	}
+
+	infoPtr->nPageSize=(infoPtr->nRangeMax -  infoPtr->nRangeMin)/5;
+	TRACKBAR_RecalculateTics (infoPtr);
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -445,13 +733,18 @@
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
     infoPtr->nRangeMax = (INT32)lParam;
-    if (infoPtr->nPos > infoPtr->nRangeMax)
-	infoPtr->nPos = infoPtr->nRangeMax;
+    if (infoPtr->nPos > infoPtr->nRangeMax) {
+		infoPtr->nPos = infoPtr->nRangeMax;
+		infoPtr->flags |=TB_THUMBCHANGED;
+	}
+
+	infoPtr->nPageSize=(infoPtr->nRangeMax -  infoPtr->nRangeMin)/5;
+	TRACKBAR_RecalculateTics (infoPtr);
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -464,39 +757,62 @@
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
     infoPtr->nRangeMin = (INT32)lParam;
-    if (infoPtr->nPos < infoPtr->nRangeMin)
-	infoPtr->nPos = infoPtr->nRangeMin;
+    if (infoPtr->nPos < infoPtr->nRangeMin) {
+		infoPtr->nPos = infoPtr->nRangeMin;
+		infoPtr->flags |=TB_THUMBCHANGED;
+	}
+
+	infoPtr->nPageSize=(infoPtr->nRangeMax -  infoPtr->nRangeMin)/5;
+	TRACKBAR_RecalculateTics (infoPtr);
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
 }
 
+static LRESULT
+TRACKBAR_SetTicFreq (WND *wndPtr, WPARAM32 wParam)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+	HDC32 hdc;
+	
+    if (wndPtr->dwStyle & TBS_AUTOTICKS) 
+           	infoPtr->uTicFreq=(UINT32) wParam; 
+	
+	TRACKBAR_RecalculateTics (infoPtr);
+
+	hdc = GetDC32 (wndPtr->hwndSelf);
+    TRACKBAR_Refresh (wndPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
+	return 0;
+}   
+
 
 static LRESULT
 TRACKBAR_SetSel (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
 
-    if (!wndPtr->dwStyle & TBS_ENABLESELRANGE)
-	return 0;
-
     infoPtr->nSelMin = (INT32)LOWORD(lParam);
     infoPtr->nSelMax = (INT32)HIWORD(lParam);
+	infoPtr->flags |=TB_SELECTIONCHANGED;
+
+    if (!wndPtr->dwStyle & TBS_ENABLESELRANGE)
+		return 0;
 
     if (infoPtr->nSelMin < infoPtr->nRangeMin)
-	infoPtr->nSelMin = infoPtr->nRangeMin;
+		infoPtr->nSelMin = infoPtr->nRangeMin;
     if (infoPtr->nSelMax > infoPtr->nRangeMax)
-	infoPtr->nSelMax = infoPtr->nRangeMax;
+		infoPtr->nSelMax = infoPtr->nRangeMax;
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -512,13 +828,15 @@
 	return 0;
 
     infoPtr->nSelMax = (INT32)lParam;
+	infoPtr->flags  |=TB_SELECTIONCHANGED;
+	
     if (infoPtr->nSelMax > infoPtr->nRangeMax)
-	infoPtr->nSelMax = infoPtr->nRangeMax;
+		infoPtr->nSelMax = infoPtr->nRangeMax;
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -534,13 +852,14 @@
 	return 0;
 
     infoPtr->nSelMin = (INT32)lParam;
+	infoPtr->flags  |=TB_SELECTIONCHANGED;
     if (infoPtr->nSelMin < infoPtr->nRangeMin)
-	infoPtr->nSelMin = infoPtr->nRangeMin;
+		infoPtr->nSelMin = infoPtr->nRangeMin;
 
     if (wParam) {
-	HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
-	TRACKBAR_Refresh (wndPtr, hdc);
-	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		HDC32 hdc = GetDC32 (wndPtr->hwndSelf);
+		TRACKBAR_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
     }
 
     return 0;
@@ -551,10 +870,16 @@
 TRACKBAR_SetThumbLength (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+	HDC32 hdc;
 
     if (wndPtr->dwStyle & TBS_FIXEDLENGTH)
-	infoPtr->uThumbLen = (UINT32)wParam;
+		infoPtr->uThumbLen = (UINT32)wParam;
 
+	hdc = GetDC32 (wndPtr->hwndSelf);
+	infoPtr->flags |=TB_THUMBCHANGED;
+	TRACKBAR_Refresh (wndPtr, hdc);
+	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+	
     return 0;
 }
 
@@ -564,19 +889,24 @@
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
     INT32 nPos = (INT32)lParam;
+	HDC32 hdc;
 
-    if (nPos < infoPtr->nRangeMin)
-	return FALSE;
-    if (nPos > infoPtr->nRangeMax)
-	return FALSE;
+    if ((nPos < infoPtr->nRangeMin) || (nPos> infoPtr->nRangeMax))
+		return FALSE;
 
-    FIXME (trackbar, "%d - empty stub!\n", nPos);
+	infoPtr->uNumTics++;
+    infoPtr->tics=HeapReAlloc( SystemHeap, 0, infoPtr->tics,
+                           (infoPtr->uNumTics)*sizeof (DWORD));
+    infoPtr->tics[infoPtr->uNumTics-1]=nPos;
+
+ 	hdc = GetDC32 (wndPtr->hwndSelf);
+    TRACKBAR_Refresh (wndPtr, hdc);
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
 
     return TRUE;
 }
 
 
-//	case TBM_SETTICFREQ:
 
 
 static LRESULT
@@ -586,7 +916,7 @@
     INT32 fTemp = infoPtr->fLocation;
 
     infoPtr->fLocation = (INT32)wParam;
-
+	
     return fTemp;
 }
 
@@ -605,6 +935,19 @@
 //	case TBM_SETUNICODEFORMAT:
 
 
+static LRESULT
+TRACKBAR_InitializeThumb (WND *wndPtr)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+
+    infoPtr->uThumbLen = 23;   /* initial thumb length */
+
+	TRACKBAR_Calc (wndPtr,infoPtr);
+	TRACKBAR_CalcThumb (wndPtr, infoPtr);
+	infoPtr->flags &= ~TB_SELECTIONCHANGED;
+
+	return 0;
+}
 
 
 static LRESULT
@@ -617,18 +960,21 @@
     wndPtr->wExtra[0] = (DWORD)infoPtr;
 
 
-    /* default values */
-    infoPtr->nRangeMin = 0;
+    infoPtr->nRangeMin = 0;			 /* default values */
     infoPtr->nRangeMax = 100;
     infoPtr->nLineSize = 1;
     infoPtr->nPageSize = 20;
     infoPtr->nSelMin   = 0;
     infoPtr->nSelMax   = 0;
     infoPtr->nPos      = 0;
-    infoPtr->uThumbLen = 23;   /* initial thumb length */
-    infoPtr->uNumTics  = 2;    /* default start and end tic */
 
+    infoPtr->uNumTics  = 0;    /* start and end tic are not included in count*/
+	infoPtr->uTicFreq  = 1;
+	infoPtr->tics	   = NULL;
+	infoPtr->clrBk	   = GetSysColor32 (COLOR_BACKGROUND);
 
+	TRACKBAR_InitializeThumb (wndPtr);
+	
     return 0;
 }
 
@@ -667,12 +1013,64 @@
 TRACKBAR_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
-
+	int prevPlace,range,width,clickPlace,prevPos;
+	
     SetFocus32 (wndPtr->hwndSelf);
 
+	clickPlace=(INT32)LOWORD(lParam);
+    range=infoPtr->nRangeMax - infoPtr->nRangeMin;
+    width=infoPtr->rcChannel.right - infoPtr->rcChannel.left;
+    prevPlace = infoPtr->rcChannel.left +
+                    width*(65536*infoPtr->nPos/range)/65536;
+	printf ("%d->%d\n",prevPlace,clickPlace);
+
+	prevPos	= infoPtr->nPos;
+	if (clickPlace > prevPlace) {					/* similar to VK_NEXT */
+		infoPtr->nPos += infoPtr->nPageSize;
+        if (infoPtr->nPos > infoPtr->nRangeMax)
+			infoPtr->nPos = infoPtr->nRangeMax;
+		TRACKBAR_SendNotify (wndPtr, TB_PAGEUP);  
+	} else {
+        infoPtr->nPos -= infoPtr->nPageSize;	/* similar to VK_PRIOR */
+        if (infoPtr->nPos < infoPtr->nRangeMin)
+            infoPtr->nPos = infoPtr->nRangeMin;
+        TRACKBAR_SendNotify (wndPtr, TB_PAGEDOWN);
+	}
+
+	printf ("%d->%d\n",prevPos,infoPtr->nPos);
+	if (prevPos!=infoPtr->nPos) {
+    	HDC32 hdc;
+
+    	hdc=GetDC32 (wndPtr->hwndSelf);
+		infoPtr->flags |=TB_THUMBCHANGED;
+    	TRACKBAR_Refresh (wndPtr, hdc);
+    	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+ 	}
+
+
     return 0;
 }
 
+static LRESULT
+TRACKBAR_LButtonUp (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+
+    FIXME (trackbar,"stub\n");
+
+	TRACKBAR_SendNotify (wndPtr, TB_ENDTRACK);
+
+    return 0;
+}
+
+static LRESULT
+TRACKBAR_CaptureChanged (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    FIXME (trackbar,"stub\n");
+
+	TRACKBAR_SendNotify (wndPtr, TB_ENDTRACK);
+	return 0;
+}
 
 static LRESULT
 TRACKBAR_Paint (WND *wndPtr, WPARAM32 wParam)
@@ -708,11 +1106,8 @@
 TRACKBAR_Size (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
     TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
-    RECT32 rcClient;
 
-    GetClientRect32 (wndPtr->hwndSelf, &rcClient);
-
-    TRACKBAR_Calc (wndPtr, infoPtr, &rcClient);
+    TRACKBAR_Calc (wndPtr, infoPtr);
     TRACKBAR_AlignBuddies (wndPtr, infoPtr);
 
     return 0;
@@ -720,9 +1115,111 @@
 
 
 // << TRACKBAR_Timer >>
-// << TRACKBAR_WinIniChange >>
 
 
+static BOOL32
+TRACKBAR_SendNotify (WND *wndPtr, UINT32 code)
+
+{
+    TRACE (trackbar, "%x\n",code);
+	if (wndPtr->dwStyle & TBS_VERT) 
+    	return (BOOL32) SendMessage32A (GetParent32 (wndPtr->hwndSelf), 
+						WM_VSCROLL, (WPARAM32)code, (LPARAM) wndPtr->hwndSelf);
+
+   	return (BOOL32) SendMessage32A (GetParent32 (wndPtr->hwndSelf), 
+						WM_HSCROLL, (WPARAM32)code, (LPARAM) wndPtr->hwndSelf);
+}
+
+static LRESULT
+TRACKBAR_MouseMove (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+			
+	
+ 	return TRUE;
+}
+
+
+static LRESULT
+TRACKBAR_KeyDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TRACKBAR_INFO *infoPtr = TRACKBAR_GetInfoPtr(wndPtr);
+	INT32 pos;
+
+    TRACE (trackbar, "%x\n",wParam);
+
+	pos=infoPtr->nPos;
+	switch (wParam) {
+		case VK_LEFT:
+		case VK_UP: 
+			if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
+			infoPtr->nPos -= infoPtr->nLineSize;
+			if (infoPtr->nPos < infoPtr->nRangeMin) 
+				infoPtr->nPos = infoPtr->nRangeMin;
+			TRACKBAR_SendNotify (wndPtr, TB_LINEUP);
+			break;
+		case VK_RIGHT:
+		case VK_DOWN: 
+			if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
+			infoPtr->nPos += infoPtr->nLineSize;
+			if (infoPtr->nPos > infoPtr->nRangeMax) 
+				infoPtr->nPos = infoPtr->nRangeMax;
+			TRACKBAR_SendNotify (wndPtr, TB_LINEDOWN);
+            break;
+		case VK_NEXT:
+			if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
+			infoPtr->nPos += infoPtr->nPageSize;
+			if (infoPtr->nPos > infoPtr->nRangeMax) 
+				infoPtr->nPos = infoPtr->nRangeMax;
+			 TRACKBAR_SendNotify (wndPtr, TB_PAGEUP);
+            break;
+		case VK_PRIOR:
+			if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
+			infoPtr->nPos -= infoPtr->nPageSize;
+			if (infoPtr->nPos < infoPtr->nRangeMin) 
+				infoPtr->nPos = infoPtr->nRangeMin;
+			TRACKBAR_SendNotify (wndPtr, TB_PAGEDOWN);
+            break;
+		case VK_HOME: 
+			if (infoPtr->nPos == infoPtr->nRangeMin) return FALSE;
+			infoPtr->nPos = infoPtr->nRangeMin;
+			TRACKBAR_SendNotify (wndPtr, TB_TOP);
+            break;
+		case VK_END: 
+			if (infoPtr->nPos == infoPtr->nRangeMax) return FALSE;
+			infoPtr->nPos = infoPtr->nRangeMax;
+	 		TRACKBAR_SendNotify (wndPtr, TB_BOTTOM);
+            break;
+	}
+
+ if (pos!=infoPtr->nPos) { 
+	HDC32 hdc;
+
+	hdc=GetDC32 (wndPtr->hwndSelf);
+	infoPtr->flags |=TB_THUMBCHANGED;
+	TRACKBAR_Refresh (wndPtr, hdc);
+	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+ }
+
+ return TRUE;
+}
+
+static LRESULT
+TRACKBAR_KeyUp (WND *wndPtr, WPARAM32 wParam)
+{
+	switch (wParam) {
+		case VK_LEFT:
+		case VK_UP: 
+		case VK_RIGHT:
+		case VK_DOWN: 
+		case VK_NEXT:
+		case VK_PRIOR:
+		case VK_HOME: 
+		case VK_END: 	TRACKBAR_SendNotify (wndPtr, TB_ENDTRACK);
+	}
+ return TRUE;
+}
+
 LRESULT WINAPI
 TRACKBAR_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
 {
@@ -754,7 +1251,8 @@
 	case TBM_GETPOS:
 	    return TRACKBAR_GetPos (wndPtr, wParam, lParam);
 
-//	case TBM_GETPTICS:
+	case TBM_GETPTICS:
+		 return TRACKBAR_GetPTics (wndPtr);
 
 	case TBM_GETRANGEMAX:
 	    return TRACKBAR_GetRangeMax (wndPtr, wParam, lParam);
@@ -771,10 +1269,15 @@
 	case TBM_GETTHUMBLENGTH:
 	    return TRACKBAR_GetThumbLength (wndPtr, wParam, lParam);
 
-//	case TBM_GETTHUMBRECT:
-//	case TBM_GETTIC:
-//	case TBM_GETTICPOS:
+	case TBM_GETTHUMBRECT:
+        return TRACKBAR_GetThumbRect (wndPtr, wParam, lParam);
 
+    case TBM_GETTIC:
+        return TRACKBAR_GetTic (wndPtr, wParam, lParam);
+ 
+    case TBM_GETTICPOS:
+        return TRACKBAR_GetTicPos (wndPtr, wParam, lParam);
+ 
 	case TBM_GETTOOLTIPS:
 	    return TRACKBAR_GetToolTips (wndPtr, wParam, lParam);
 
@@ -816,7 +1319,9 @@
 	case TBM_SETTIC:
 	    return TRACKBAR_SetTic (wndPtr, wParam, lParam);
 
-//	case TBM_SETTICFREQ:
+    case TBM_SETTICFREQ:
+       return TRACKBAR_SetTicFreq (wndPtr, wParam);
+
 
 	case TBM_SETTIPSIDE:
 	    return TRACKBAR_SetTipSide (wndPtr, wParam, lParam);
@@ -827,7 +1332,8 @@
 //	case TBM_SETUNICODEFORMAT:
 
 
-//	case WM_CAPTURECHANGED:
+	case WM_CAPTURECHANGED:
+	    return TRACKBAR_CaptureChanged (wndPtr, wParam, lParam);
 
 	case WM_CREATE:
 	    return TRACKBAR_Create (wndPtr, wParam, lParam);
@@ -843,9 +1349,11 @@
 	case WM_GETDLGCODE:
 	    return DLGC_WANTARROWS;
 
-//	case WM_KEYDOWN:
-
-//	case WM_KEYUP:
+ 	case WM_KEYDOWN:
+       return TRACKBAR_KeyDown (wndPtr, wParam, lParam);
+        
+  	case WM_KEYUP:
+       return TRACKBAR_KeyUp (wndPtr, wParam);
 
 	case WM_KILLFOCUS:
 	    return TRACKBAR_KillFocus (wndPtr, wParam, lParam);
@@ -853,10 +1361,11 @@
 	case WM_LBUTTONDOWN:
 	    return TRACKBAR_LButtonDown (wndPtr, wParam, lParam);
 
-//	case WM_LBUTTONUP:
+	case WM_LBUTTONUP:
+	    return TRACKBAR_LButtonUp (wndPtr, wParam, lParam);
 
-//	case WM_MOUSEMOVE:
-//	    return TRACKBAR_MouseMove (wndPtr, wParam, lParam);
+	case WM_MOUSEMOVE:
+	    return TRACKBAR_MouseMove (wndPtr, wParam, lParam);
 
 	case WM_PAINT:
 	    return TRACKBAR_Paint (wndPtr, wParam);
@@ -869,7 +1378,8 @@
 
 //	case WM_TIMER:
 
-//	case WM_WININICHANGE:
+	case WM_WININICHANGE:
+		return TRACKBAR_InitializeThumb (wndPtr);
 
 	default:
 	    if (uMsg >= WM_USER)
diff --git a/dlls/comctl32/treeview.c b/dlls/comctl32/treeview.c
index a4eac47..9b5fcf5 100644
--- a/dlls/comctl32/treeview.c
+++ b/dlls/comctl32/treeview.c
@@ -1,16 +1,28 @@
-/*
- * Treeview control
+/* Treeview control
  *
- * Copyright 1998 Eric Kohl
+ * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
+ * Copyright 1998 Alex Priem <alexp@sci.kun.nl>
  *
- * NOTES
- *   This is just a dummy control. An author is needed! Any volunteers?
- *   I will only improve this control once in a while.
- *     Eric <ekohl@abo.rhein-zeitung.de>
  *
  * TODO:
- *   - All messages.
- *   - All notifications.
+ *   - Nearly all notifications.
+ * 
+ *   list-handling stuff: sort, sorted insertitem.
+ *
+ *   refreshtreeview: 	
+		-small array containing info about positions.
+ 		-better implementation of DrawItem (connecting lines).
+		-implement partial drawing?
+ *   Expand:		-ctlmacro expands twice ->toggle.
+ *  -drag&drop.
+ *  -scrollbars.
+ *  -Unicode messages
+ *  -TVITEMEX 
+ *
+ * FIXMEs:  
+   -GetNextItem: add flag for traversing visible items 
+   -DblClick:	ctlmacro.exe's NM_DBLCLK seems to go wrong (returns FALSE).
+	     
  */
 
 #include "windows.h"
@@ -19,26 +31,225 @@
 #include "heap.h"
 #include "win.h"
 #include "debug.h"
+#include <asm/bitops.h>      /* FIXME: linux specific */
+
+static int TREEVIEW_Timer;
+
 
 
 #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
 
 
 
+#include <asm/bitops.h>      /* FIXME: linux specific */
+
+static int TREEVIEW_Timer;
+
+  
+  #define TREEVIEW_GetInfoPtr(wndPtr) ((TREEVIEW_INFO *)wndPtr->wExtra[0])
+  
+  
+  
+
+static BOOL32
+TREEVIEW_SendSimpleNotify (WND *wndPtr, UINT32 code);
+static BOOL32
+TREEVIEW_SendTreeviewNotify (WND *wndPtr, UINT32 code, UINT32 action, 
+			INT32 oldItem, INT32 newItem, POINT32 pt);
+static LRESULT
+TREEVIEW_SelectItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam);
+static void
+TREEVIEW_Refresh (WND *wndPtr, HDC32 hdc);
+
+
+
+
+
+/* helper functions. Work with the assumption that validity of operands 
+   is checked beforehand */
+
+
+static TREEVIEW_ITEM *
+TREEVIEW_ValidItem (TREEVIEW_INFO *infoPtr,int  handle)
+{
+ 
+ if ((!handle) || (handle>infoPtr->uMaxHandle)) return NULL;
+ if (test_bit (handle, infoPtr->freeList)) return NULL;
+
+ return & infoPtr->items[handle];
+}
+
+
+
+static TREEVIEW_ITEM *TREEVIEW_GetPrevListItem (TREEVIEW_INFO *infoPtr, 
+					TREEVIEW_ITEM *tvItem)
+
+{
+ TREEVIEW_ITEM *wineItem;
+
+ if (tvItem->upsibling) 
+		return (& infoPtr->items[tvItem->upsibling]);
+
+ wineItem=tvItem;
+ while (wineItem->parent) {
+	wineItem=& infoPtr->items[wineItem->parent];
+	if (wineItem->upsibling) 
+                return (& infoPtr->items[wineItem->upsibling]);
+ } 
+
+ return NULL;
+}
+
+static TREEVIEW_ITEM *TREEVIEW_GetNextListItem (TREEVIEW_INFO *infoPtr, 
+					TREEVIEW_ITEM *tvItem)
+
+{
+ TREEVIEW_ITEM *wineItem;
+
+ if (tvItem->sibling) 
+		return (& infoPtr->items[tvItem->sibling]);
+
+ wineItem=tvItem;
+ while (wineItem->parent) {
+	wineItem=& infoPtr->items [wineItem->parent];
+	if (wineItem->sibling) 
+                return (& infoPtr->items [wineItem->sibling]);
+ } 
+
+ return NULL;
+}
+
+static TREEVIEW_ITEM *TREEVIEW_GetLastListItem (TREEVIEW_INFO *infoPtr)
+
+{
+  TREEVIEW_ITEM *wineItem;
+  
+ wineItem=NULL;
+ if (infoPtr->TopRootItem) 
+	wineItem=& infoPtr->items [infoPtr->TopRootItem];
+ while (wineItem->sibling) 
+	wineItem=& infoPtr->items [wineItem->sibling];
+
+ return wineItem;
+}
+	
+ 
+
+
+static void
+TREEVIEW_RemoveItem (TREEVIEW_INFO *infoPtr, TREEVIEW_ITEM *wineItem)
+
+{
+ TREEVIEW_ITEM *parentItem, *upsiblingItem, *siblingItem;
+ INT32 iItem;
+
+ iItem=wineItem->hItem;
+ set_bit ( iItem & 31, &infoPtr->freeList[iItem >>5]);
+ infoPtr->uNumItems--;
+ parentItem=NULL;
+ if (wineItem->pszText!=LPSTR_TEXTCALLBACK32A) 
+	HeapFree (GetProcessHeap (), 0, wineItem->pszText);
+
+ if (wineItem->parent) {
+	parentItem=& infoPtr->items[ wineItem->parent];
+	if (parentItem->cChildren==1) {
+		parentItem->cChildren=0;
+		parentItem->firstChild=0;    
+		return;
+	} else {
+		parentItem->cChildren--;
+		if (parentItem->firstChild==iItem) 
+			parentItem->firstChild=wineItem->sibling;
+		}
+ }
+
+ if (iItem==infoPtr->TopRootItem) 
+	infoPtr->TopRootItem=wineItem->sibling;
+ if (wineItem->upsibling) {
+	upsiblingItem=& infoPtr->items [wineItem->upsibling];
+	upsiblingItem->sibling=wineItem->sibling;
+ }
+ if (wineItem->sibling) {
+	siblingItem=& infoPtr->items [wineItem->sibling];
+	siblingItem->upsibling=wineItem->upsibling;
+ }
+}
+
+
+
+static void TREEVIEW_RemoveAllChildren (TREEVIEW_INFO *infoPtr, 
+					   TREEVIEW_ITEM *parentItem)
+
+{
+ TREEVIEW_ITEM *killItem;
+ INT32	kill;
+ 
+ kill=parentItem->firstChild;
+ while (kill) {
+ 	set_bit ( kill & 31, &infoPtr->freeList[kill >>5]);
+ 	killItem=& infoPtr->items[kill];
+	if (killItem->pszText!=LPSTR_TEXTCALLBACK32A) 
+		HeapFree (GetProcessHeap (), 0, killItem->pszText);
+	kill=killItem->sibling;
+ }
+ infoPtr->uNumItems -= parentItem->cChildren;
+ parentItem->firstChild = 0;
+ parentItem->cChildren = 0;
+}
+
+
+
+static void TREEVIEW_RemoveTree (TREEVIEW_INFO *infoPtr)
+					   
+
+{
+ TREEVIEW_ITEM *killItem;
+ int i;
+
+	/* bummer: if we didn't delete anything, test_bit is overhead */
+ 
+    for (i=1; i<=infoPtr->uMaxHandle; i++) 
+	if (!test_bit (i, infoPtr->freeList)) {
+		killItem=& infoPtr->items [i];	
+		if (killItem->pszText!=LPSTR_TEXTCALLBACK32A)
+			HeapFree (GetProcessHeap (), 0, killItem->pszText);
+	} 
+
+    if (infoPtr->uNumPtrsAlloced) {
+        HeapFree (GetProcessHeap (), 0, infoPtr->items);
+        HeapFree (GetProcessHeap (), 0, infoPtr->freeList);
+        infoPtr->uNumItems=0;
+        infoPtr->uNumPtrsAlloced=0;
+        infoPtr->uMaxHandle=0;
+    }   
+
+	/* this function doesn't remove infoPtr itself */
+}
+
+
+
+
+
+
+
+
+
+
 static LRESULT
 TREEVIEW_GetImageList (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-    TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
 
-    switch ((INT32)wParam) {
-	case TVSIL_NORMAL:
-	    return (LRESULT)infoPtr->himlNormal;
+  TRACE (treeview,"\n");
 
-	case TVSIL_STATE:
-	    return (LRESULT)infoPtr->himlState;
-    }
+  if (infoPtr==NULL) return 0;
 
-    return (LRESULT)NULL;
+  if ((INT32)wParam == TVSIL_NORMAL) 
+	return (LRESULT) infoPtr->himlNormal;
+  if ((INT32)wParam == TVSIL_STATE) 
+	return (LRESULT) infoPtr->himlState;
+
+  return 0;
 }
 
 
@@ -68,51 +279,862 @@
 
 
 static LRESULT
-TREEVIEW_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+TREEVIEW_SetItemHeight (WND *wndPtr, WPARAM32 wParam)
 {
-    TREEVIEW_INFO *infoPtr;
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  INT32 prevHeight=infoPtr->uItemHeight;
+  HDC32 hdc;
+  TEXTMETRIC32A tm;
 
-    /* allocate memory for info structure */
-    infoPtr = (TREEVIEW_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-                                   sizeof(TREEVIEW_INFO));
-    wndPtr->wExtra[0] = (DWORD)infoPtr;
 
-    if (infoPtr == NULL) {
-	ERR (treeview, "could not allocate info memory!\n");
-	return 0;
+  if (wParam==-1) {
+	hdc=GetDC32 (wndPtr->hwndSelf);
+	infoPtr->uItemHeight=-1;
+	GetTextMetrics32A (hdc, &tm);
+    infoPtr->uRealItemHeight= tm.tmHeight + tm.tmExternalLeading;
+	ReleaseDC32 (wndPtr->hwndSelf, hdc);
+	return prevHeight;
+  }
+
+	/* FIXME: check wParam > imagelist height */
+
+  if (!(wndPtr->dwStyle & TVS_NONEVENHEIGHT))
+	infoPtr->uItemHeight = (INT32) wParam & 0xfffffffe;
+  return prevHeight;
+}
+
+static LRESULT
+TREEVIEW_GetItemHeight (WND *wndPtr)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  
+  return infoPtr->uItemHeight;
+}
+  
+static LRESULT
+TREEVIEW_SetTextColor (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  COLORREF prevColor=infoPtr->clrText;
+
+  infoPtr->clrText=(COLORREF) lParam;
+  return (LRESULT) prevColor;
+}
+
+static LRESULT
+TREEVIEW_GetTextColor (WND *wndPtr)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+	
+  return (LRESULT) infoPtr->clrText;
+}
+
+
+static INT32
+TREEVIEW_DrawItem (WND *wndPtr, HDC32 hdc, TREEVIEW_ITEM *wineItem, 
+		   TREEVIEW_ITEM *upperItem, int indent)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  INT32  oldBkMode,center,xpos;
+  COLORREF oldBkColor;
+  UINT32 uTextJustify = DT_LEFT;
+  HPEN32 hOldPen, hnewPen,hRootPen;
+  RECT32 r,upper;
+  
+  hnewPen = CreatePen32(PS_DOT, 0, GetSysColor32(COLOR_WINDOWTEXT) );
+  hOldPen = SelectObject32( hdc, hnewPen );
+ 
+  r=wineItem->rect;
+  if (upperItem) 
+	upper=upperItem->rect;
+  else {
+	upper.top=0;
+	upper.left=8;
+  }
+  center=(r.top+r.bottom)/2;
+  xpos=r.left+8;
+
+  if (wndPtr->dwStyle & TVS_HASLINES) {
+	POINT32 points[3];
+	if ((wndPtr->dwStyle & TVS_LINESATROOT) && (indent==0)) {
+		points[0].y=points[1].y=center;
+		points[2].y=upper.top;
+		points[1].x=points[2].x=upper.left;
+		points[0].x=upper.left+12;
+		points[2].y+=5;
+
+ 		Polyline32 (hdc,points,3);
+	}
+	else {
+		points[0].y=points[1].y=center;
+                points[2].y=upper.top;
+                points[1].x=points[2].x=upper.left+13;
+                points[0].x=upper.left+25;
+                points[2].y+=5;
+ 		Polyline32 (hdc,points,3);
+	}
+ }
+
+  DeleteObject32(hnewPen);
+  SelectObject32(hdc, hOldPen);
+
+  if ((wndPtr->dwStyle & TVS_HASBUTTONS) && (wineItem->cChildren)) {
+/*
+  	hRootPen = CreatePen32(PS_SOLID, 0, GetSysColor32(COLOR_WINDOW) );
+  	SelectObject32( hdc, hRootPen );
+*/
+
+	Rectangle32 (hdc, xpos-4, center-4, xpos+5, center+5);
+	MoveToEx32 (hdc, xpos-2, center, NULL);
+	LineTo32   (hdc, xpos+3, center);
+	if (!(wineItem->state & TVIS_EXPANDED)) {
+		MoveToEx32 (hdc, xpos,   center-2, NULL);
+		LineTo32   (hdc, xpos,   center+3);
+	}
+ /* 	DeleteObject32(hRootPen); */
+        }
+
+
+  xpos+=13;
+
+  if (wineItem->mask & TVIF_IMAGE) {
+	if (wineItem->iImage!=I_IMAGECALLBACK) {
+  		if (infoPtr->himlNormal) {
+  			ImageList_Draw (infoPtr->himlNormal,wineItem->iImage, hdc,
+                      			xpos-2, r.top+1, ILD_NORMAL);
+  			xpos+=15;
+		}
+	}
+  }
+
+  r.left=xpos;
+  if ((wineItem->mask & TVIF_TEXT) && (wineItem->pszText)) {
+	    if (wineItem->state & TVIS_SELECTED) {
+            	oldBkMode = SetBkMode32(hdc, OPAQUE);
+		oldBkColor= SetBkColor32 (hdc, GetSysColor32( COLOR_HIGHLIGHT));
+		SetTextColor32 (hdc, GetSysColor32(COLOR_HIGHLIGHTTEXT));
+	    }
+	    else {
+            	oldBkMode = SetBkMode32(hdc, TRANSPARENT);
+	    }
+            r.left += 3;
+            r.right -= 3;
+			if (infoPtr->clrText==-1)
+            	SetTextColor32 (hdc, COLOR_BTNTEXT);
+			else 
+				SetTextColor32 (hdc, infoPtr->clrText);  /* FIXME: retval */
+            DrawText32A(hdc, wineItem->pszText, lstrlen32A(wineItem->pszText),
+                  &r, uTextJustify|DT_VCENTER|DT_SINGLELINE);
+            if (oldBkMode != TRANSPARENT)
+                SetBkMode32(hdc, oldBkMode);
+	    if (wineItem->state & TVIS_SELECTED)
+		SetBkColor32 (hdc, oldBkColor);
+        }
+
+ return wineItem->rect.right;
+}
+
+
+
+
+
+
+
+static LRESULT
+TREEVIEW_GetItemRect (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TREEVIEW_ITEM *wineItem;
+  INT32 iItem;
+  LPRECT32 lpRect;
+
+  TRACE (treeview,"\n");
+  if (infoPtr==NULL) return FALSE;
+  
+  iItem = (INT32)lParam;
+  wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
+  if (!wineItem) return FALSE;
+
+  wineItem=& infoPtr->items[ iItem ];
+  if (!wineItem->visible) return FALSE;
+
+  lpRect = (LPRECT32)lParam;
+  if (lpRect == NULL) return FALSE;
+	
+  if ((INT32) wParam) {
+  	lpRect->left	= wineItem->text.left;
+	lpRect->right	= wineItem->text.right;
+	lpRect->bottom	= wineItem->text.bottom;
+	lpRect->top	= wineItem->text.top;
+  } else {
+	lpRect->left 	= wineItem->rect.left;
+	lpRect->right	= wineItem->rect.right;
+	lpRect->bottom  = wineItem->rect.bottom;
+	lpRect->top	= wineItem->rect.top;
+  }
+
+  return TRUE;
+}
+
+
+
+static LRESULT
+TREEVIEW_GetVisibleCount (WND *wndPtr,  WPARAM32 wParam, LPARAM lParam)
+
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+
+  TRACE (treeview,"\n");
+
+  return (LRESULT) infoPtr->uVisibleHeight / infoPtr->uRealItemHeight;
+}
+
+
+
+static LRESULT
+TREEVIEW_SetItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TREEVIEW_ITEM *wineItem;
+  TV_ITEM *tvItem;
+  INT32 iItem,len;
+
+  TRACE (treeview,"\n");
+  tvItem=(LPTVITEM) lParam;
+  iItem=tvItem->hItem;
+
+  wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
+  if (!wineItem) return FALSE;
+
+  if (tvItem->mask & TVIF_CHILDREN) {
+        wineItem->cChildren=tvItem->cChildren;
+  }
+
+  if (tvItem->mask & TVIF_IMAGE) {
+       wineItem->iImage=tvItem->iImage;
+  }
+
+  if (tvItem->mask & TVIF_INTEGRAL) {
+/*        wineItem->iIntegral=tvItem->iIntegral; */
+  }
+
+  if (tvItem->mask & TVIF_PARAM) {
+        wineItem->lParam=tvItem->lParam;
+  }
+
+  if (tvItem->mask & TVIF_SELECTEDIMAGE) {
+        wineItem->iSelectedImage=tvItem->iSelectedImage;
+  }
+
+  if (tvItem->mask & TVIF_STATE) {
+        wineItem->state=tvItem->state & tvItem->stateMask;
+  }
+
+  if (tvItem->mask & TVIF_TEXT) {
+        len=tvItem->cchTextMax;
+        if (len>wineItem->cchTextMax) {
+		HeapFree (GetProcessHeap (), 0, wineItem->pszText);
+                wineItem->pszText= HeapAlloc (GetProcessHeap (), 
+				HEAP_ZERO_MEMORY, len+1);
+	}
+        lstrcpyn32A (wineItem->pszText, tvItem->pszText,len);
+   }
+
+  return TRUE;
+}
+
+
+
+
+
+static void
+TREEVIEW_Refresh (WND *wndPtr, HDC32 hdc)
+
+{
+    TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+    HFONT32 hFont, hOldFont;
+    RECT32 rect;
+    HBRUSH32 hbrBk;
+    INT32 iItem, indent, x, y, height;
+    INT32 viewtop,viewbottom,viewleft,viewright;
+    TREEVIEW_ITEM *wineItem, *prevItem;
+
+    TRACE (treeview,"\n");
+
+    if (TREEVIEW_Timer & TV_REFRESH_TIMER_SET) {
+		KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
+		TREEVIEW_Timer &= ~TV_REFRESH_TIMER_SET;
     }
 
-    if ((TREEVIEW_INFO*)wndPtr->wExtra[0] != infoPtr) {
-	ERR (treeview, "pointer assignment error!\n");
-	return 0;
-    }
+    
+    GetClientRect32 (wndPtr->hwndSelf, &rect);
+    if ((rect.left-rect.right ==0) || (rect.top-rect.bottom==0)) return;
+    viewtop=infoPtr->cy;
+    viewbottom=infoPtr->cy + rect.bottom-rect.top;
+    viewleft=infoPtr->cx;
+    viewright=infoPtr->cx + rect.right-rect.left;
 
-    /* set default settings */
-    infoPtr->clrBk = GetSysColor32 (COLOR_WINDOW);
-    infoPtr->clrText = GetSysColor32 (COLOR_BTNTEXT);
-    infoPtr->himlNormal = NULL;
-    infoPtr->himlState = NULL;
+	infoPtr->uVisibleHeight=viewbottom - viewtop;
+
+    hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject32 (DEFAULT_GUI_FONT);
+    hOldFont = SelectObject32 (hdc, hFont);
+
+    /* draw background */
+    hbrBk = GetSysColorBrush32(COLOR_WINDOW);
+    FillRect32(hdc, &rect, hbrBk);
 
 
-    return 0;
+    iItem=infoPtr->TopRootItem;
+    infoPtr->firstVisible=0;
+    wineItem=NULL;
+    indent=0;
+    x=y=0;
+    TRACE (treeview, "[%d %d %d %d]\n",viewtop,viewbottom,viewleft,viewright);
+
+    while (iItem) {
+		prevItem=wineItem;
+        wineItem= & infoPtr->items[iItem];
+
+		TRACE (treeview, "%d %d [%d %d %d %d] (%s)\n",y,x,
+			wineItem->rect.top, wineItem->rect.bottom,
+			wineItem->rect.left, wineItem->rect.right,
+			wineItem->pszText);
+
+		height=infoPtr->uRealItemHeight * wineItem->iIntegral;
+		if ((y >= viewtop) && (y <= viewbottom) &&
+	    	(x >= viewleft  ) && (x <= viewright)) {
+        		wineItem->rect.top = y - infoPtr->cy + rect.top;
+        		wineItem->rect.bottom = wineItem->rect.top + height ;
+         		wineItem->rect.left = x - infoPtr->cx + rect.left;
+        		wineItem->rect.right = rect.right;
+			if (!infoPtr->firstVisible)
+				infoPtr->firstVisible=wineItem->hItem;
+        		TREEVIEW_DrawItem (wndPtr, hdc, wineItem, prevItem, indent);
+		}
+		else {
+			wineItem->rect.top  = wineItem->rect.bottom = -1;
+			wineItem->rect.left = wineItem->rect.right = -1;
+ 		}
+
+		/* look up next item */
+	
+		if ((wineItem->firstChild) && (wineItem->state & TVIS_EXPANDED)) {
+			iItem=wineItem->firstChild;
+			indent++;
+			x+=infoPtr->uIndent;
+		}
+		else {
+			iItem=wineItem->sibling;
+			while ((!iItem) && (indent>0)) {
+				indent--;
+				x-=infoPtr->uIndent;
+				prevItem=wineItem;
+				wineItem=&infoPtr->items[wineItem->parent];
+				iItem=wineItem->sibling;
+			}
+		}
+        y +=height;
+    }				/* while */
+
+    infoPtr->uTotalHeight=y;
+    if (y >= (viewbottom-viewtop)) {
+ 		if (!(infoPtr->uInternalStatus & TV_VSCROLL))
+			ShowScrollBar32 (wndPtr->hwndSelf, SB_VERT, TRUE);
+		infoPtr->uInternalStatus |=TV_VSCROLL;
+ 		SetScrollRange32 (wndPtr->hwndSelf, SB_VERT, 0, 
+					y - infoPtr->uVisibleHeight, FALSE);
+		SetScrollPos32 (wndPtr->hwndSelf, SB_VERT, infoPtr->cy, TRUE);
+	}
+    else {
+		if (infoPtr->uInternalStatus & TV_VSCROLL) 
+			ShowScrollBar32 (wndPtr->hwndSelf, SB_VERT, FALSE);
+		infoPtr->uInternalStatus &= ~TV_VSCROLL;
+	}
+
+
+    SelectObject32 (hdc, hOldFont);
+}
+
+
+static LRESULT 
+TREEVIEW_HandleTimer ( WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  HDC32 hdc;
+
+  if (!infoPtr) return FALSE;
+ 
+  TRACE (treeview, "timer\n");
+
+  switch (wParam) {
+	case TV_REFRESH_TIMER:
+		KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
+		TREEVIEW_Timer &= ~TV_REFRESH_TIMER_SET;
+		hdc=GetDC32 (wndPtr->hwndSelf);
+		TREEVIEW_Refresh (wndPtr, hdc);
+		ReleaseDC32 (wndPtr->hwndSelf, hdc);
+		return 0;
+	case TV_EDIT_TIMER:
+		KillTimer32 (wndPtr->hwndSelf, TV_EDIT_TIMER);
+		TREEVIEW_Timer &= ~TV_EDIT_TIMER_SET;
+		return 0;
+ }
+		
+ return 1;
+}
+
+
+static void
+TREEVIEW_QueueRefresh (WND *wndPtr)
+
+{
+ 
+ TRACE (treeview,"queued\n");
+ if (TREEVIEW_Timer & TV_REFRESH_TIMER_SET) {
+	KillTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER);
+ }
+
+ SetTimer32 (wndPtr->hwndSelf, TV_REFRESH_TIMER, TV_REFRESH_DELAY, 0);
+ TREEVIEW_Timer|=TV_REFRESH_TIMER_SET;
+}
+
+
+
+static LRESULT
+TREEVIEW_GetItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  LPTVITEM      tvItem;
+  TREEVIEW_ITEM *wineItem;
+  INT32         iItem,len;
+
+  TRACE (treeview,"\n");
+  tvItem=(LPTVITEM) lParam;
+  iItem=tvItem->hItem;
+
+  wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
+  if (!wineItem) return FALSE;
+
+
+   if (tvItem->mask & TVIF_CHILDREN) {
+        tvItem->cChildren=wineItem->cChildren;
+   }
+
+   if (tvItem->mask & TVIF_HANDLE) {
+        tvItem->hItem=wineItem->hItem;
+   }
+
+   if (tvItem->mask & TVIF_IMAGE) {
+        tvItem->iImage=wineItem->iImage;
+   }
+
+   if (tvItem->mask & TVIF_INTEGRAL) {
+/*        tvItem->iIntegral=wineItem->iIntegral; */
+   }
+
+   if (tvItem->mask & TVIF_PARAM) {
+        tvItem->lParam=wineItem->lParam;
+   }
+
+   if (tvItem->mask & TVIF_SELECTEDIMAGE) {
+        tvItem->iSelectedImage=wineItem->iSelectedImage;
+   }
+
+   if (tvItem->mask & TVIF_STATE) {
+        tvItem->state=wineItem->state & tvItem->stateMask;
+   }
+
+   if (tvItem->mask & TVIF_TEXT) {
+	len=wineItem->cchTextMax;
+	if (wineItem->cchTextMax>tvItem->cchTextMax) 
+		len=tvItem->cchTextMax-1;
+        lstrcpyn32A (tvItem->pszText, tvItem->pszText,len);
+   }
+
+  return TRUE;
+}
+
+
+
+static LRESULT
+TREEVIEW_GetNextItem32 (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TREEVIEW_ITEM *wineItem;
+  INT32 iItem, flag;
+
+
+  TRACE (treeview,"item:%lu, flags:%x\n", lParam, wParam);
+  if (!infoPtr) return FALSE;
+
+  flag= (INT32) wParam;
+  switch (flag) {
+	case TVGN_ROOT: 	return (LRESULT) infoPtr->TopRootItem;
+	case TVGN_CARET: 	return (LRESULT) infoPtr->selectedItem;
+	case TVGN_FIRSTVISIBLE: return (LRESULT) infoPtr->firstVisible;
+	case TVGN_DROPHILITE:	return (LRESULT) infoPtr->dropItem;
+	}
+	
+  iItem= (INT32) lParam;
+  wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
+  if (!wineItem) return FALSE;
+
+  switch (flag)	{
+	case TVGN_NEXT: 	return (LRESULT) wineItem->sibling;
+	case TVGN_PREVIOUS: 	return (LRESULT) wineItem->upsibling;
+	case TVGN_PARENT: 	return (LRESULT) wineItem->parent;
+	case TVGN_CHILD: 	return (LRESULT) wineItem->firstChild;
+	case TVGN_LASTVISIBLE:  FIXME (treeview,"TVGN_LASTVISIBLE not implemented\n");
+				return 0;
+	case TVGN_NEXTVISIBLE:  wineItem=TREEVIEW_GetNextListItem 
+						(infoPtr,wineItem);
+				if (wineItem) 
+					return (LRESULT) wineItem->hItem;
+				else
+					return (LRESULT) 0;
+	case TVGN_PREVIOUSVISIBLE: wineItem=TREEVIEW_GetPrevListItem
+						(infoPtr, wineItem);
+				if (wineItem) 
+					return (LRESULT) wineItem->hItem;
+				else
+					return (LRESULT) 0;
+	default:	FIXME (treeview,"Unknown msg %x,item %x\n", flag,iItem);
+	}
+
+ return 0;
 }
 
 
 static LRESULT
-TREEVIEW_Destroy (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+TREEVIEW_GetCount (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
-    TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+
+ return (LRESULT) infoPtr->uNumItems;
+}
 
 
 
 
-    /* free tree view info data */
-    HeapFree (GetProcessHeap (), 0, infoPtr);
+/* the method used below isn't the most memory-friendly, but it avoids 
+   a lot of memory reallocations */ 
+
+/* BTW: we waste handle 0; 0 is not an allowed handle. Fix this by
+        decreasing infoptr->items with 1, and increasing it by 1 if 
+        it is referenced in mm-handling stuff? */
+
+static LRESULT
+TREEVIEW_InsertItem32A (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TVINSERTSTRUCT  *ptdi;
+  TV_ITEM 	*tvItem;
+  TREEVIEW_ITEM *wineItem, *parentItem, *prevsib, *sibItem;
+  INT32		iItem,listItems,i,len;
+  
+  TRACE (treeview,"\n");
+  ptdi = (TVINSERTSTRUCT *) lParam;
+
+	/* check if memory is available */
+
+  if (infoPtr->uNumPtrsAlloced==0) {
+        infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
+                                    TVITEM_ALLOC*sizeof (TREEVIEW_ITEM));
+        infoPtr->freeList= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
+                                    (1+(TVITEM_ALLOC>>5)) *sizeof (INT32));
+        infoPtr->uNumPtrsAlloced=TVITEM_ALLOC;
+	infoPtr->TopRootItem=1;
+   }
+
+  if (infoPtr->uNumItems == (infoPtr->uNumPtrsAlloced-1) ) {
+   	TREEVIEW_ITEM *oldItems = infoPtr->items;
+	INT32 *oldfreeList = infoPtr->freeList;
+
+	infoPtr->uNumPtrsAlloced*=2;
+        infoPtr->items = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
+                              infoPtr->uNumPtrsAlloced*sizeof (TREEVIEW_ITEM));
+        infoPtr->freeList= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
+                              (1+(infoPtr->uNumPtrsAlloced>>5))*sizeof (INT32));
+
+        memcpy (&infoPtr->items[0], &oldItems[0],
+                    infoPtr->uNumPtrsAlloced/2 * sizeof(TREEVIEW_ITEM));
+        memcpy (&infoPtr->freeList[0], &oldfreeList[0],
+                    infoPtr->uNumPtrsAlloced>>6 * sizeof(INT32));
+
+         HeapFree (GetProcessHeap (), 0, oldItems);  
+         HeapFree (GetProcessHeap (), 0, oldfreeList);  
+    }
+
+  iItem=0;
+  infoPtr->uNumItems++;
+
+  if (infoPtr->uMaxHandle==(infoPtr->uNumItems-1))  { 
+  	iItem=infoPtr->uNumItems;
+  	infoPtr->uMaxHandle++;
+  } 
+  else {					 /* check freelist */
+	for (i=0; i<infoPtr->uNumPtrsAlloced>>5; i++) {
+		if (infoPtr->freeList[i]) {
+			iItem=ffs (infoPtr->freeList[i]);
+			clear_bit (iItem & 31, & infoPtr->freeList[i]);
+			break;
+		}
+  	 } 
+  }
+  if (!iItem) ERR (treeview, "Argh -- can't find free item.\n");
+  
+  tvItem= & ptdi->item;
+  wineItem=& infoPtr->items[iItem];
+
+
+
+  if ((ptdi->hParent==TVI_ROOT) || (ptdi->hParent==0)) {
+	parentItem=NULL;
+	wineItem->parent=0; 
+	sibItem=&infoPtr->items [infoPtr->TopRootItem];
+	listItems=infoPtr->uNumItems;
+  }
+  else  {
+	parentItem= &infoPtr->items[ptdi->hParent];
+	if (!parentItem->firstChild) 
+		parentItem->firstChild=iItem;
+	wineItem->parent=ptdi->hParent;
+	sibItem=&infoPtr->items [parentItem->firstChild];
+	parentItem->cChildren++;
+	listItems=parentItem->cChildren;
+  }
+
+  wineItem->upsibling=0;  /* needed in case we're the first item in a list */ 
+  wineItem->sibling=0;     
+  wineItem->firstChild=0;
+
+  if (listItems>1) {
+     prevsib=NULL;
+     switch (ptdi->hInsertAfter) {
+		case TVI_FIRST: wineItem->sibling=infoPtr->TopRootItem;
+			infoPtr->TopRootItem=iItem;
+			break;
+		case TVI_LAST:  
+			while (sibItem->sibling) {
+				prevsib=sibItem;
+				sibItem=&infoPtr->items [sibItem->sibling];
+			}
+			sibItem->sibling=iItem;
+			if (prevsib!=NULL) 
+				wineItem->upsibling=prevsib->hItem;
+			else
+  				wineItem->sibling=0; 	/* terminate list */
+			break;
+		case TVI_SORT:  
+			FIXME (treeview, "Sorted insert not implemented yet\n");
+			break;
+		default:	
+			while ((sibItem->sibling) && (sibItem->sibling!=iItem)) {
+				prevsib=sibItem;
+                sibItem=&infoPtr->items [sibItem->sibling];
+            }
+			if (sibItem->sibling) 
+				WARN (treeview, "Buggy program tried to insert item after nonexisting handle.");
+			sibItem->upsibling=iItem;
+			wineItem->sibling=sibItem->hItem;
+			if (prevsib!=NULL) 
+				wineItem->upsibling=prevsib->hItem;
+			break;
+   	}
+   }	
+
+
+/* Fill in info structure */
+
+   wineItem->mask=tvItem->mask;
+   wineItem->hItem=iItem;
+   wineItem->iIntegral=1; 
+
+   if (tvItem->mask & TVIF_CHILDREN)
+	 wineItem->cChildren=tvItem->cChildren;
+
+   if (tvItem->mask & TVIF_IMAGE) 
+	wineItem->iImage=tvItem->iImage;
+
+/*   if (tvItem->mask & TVIF_INTEGRAL) 
+   	wineItem->iIntegral=tvItem->iIntegral;  */
+   
+
+   if (tvItem->mask & TVIF_PARAM) 
+	wineItem->lParam=tvItem->lParam;
+
+   if (tvItem->mask & TVIF_SELECTEDIMAGE) 
+	wineItem->iSelectedImage=tvItem->iSelectedImage;
+
+   if (tvItem->mask & TVIF_STATE) {
+	wineItem->state=tvItem->state;
+	wineItem->stateMask=tvItem->stateMask;
+   }
+
+   if (tvItem->mask & TVIF_TEXT) {
+   	TRACE (treeview,"(%s)\n", tvItem->pszText); 
+	if (tvItem->pszText!=LPSTR_TEXTCALLBACK32A) {
+		len = lstrlen32A (tvItem->pszText)+1;
+		wineItem->pszText=
+			HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, len+1);
+		lstrcpy32A (wineItem->pszText, tvItem->pszText);
+		wineItem->cchTextMax=len;
+	}
+   }
+
+   TREEVIEW_QueueRefresh (wndPtr);
+
+   return (LRESULT) iItem;
+}
+
+
+
+static LRESULT
+TREEVIEW_DeleteItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  INT32 iItem;
+  POINT32 pt;
+  TREEVIEW_ITEM *wineItem;
+
+  TRACE (treeview,"\n");
+  if (!infoPtr) return FALSE;
+
+  if ((INT32) lParam == TVI_ROOT) {
+	TREEVIEW_RemoveTree (infoPtr);
+  } else {
+  	iItem= (INT32) lParam;
+  	wineItem = TREEVIEW_ValidItem (infoPtr, iItem);
+  	if (!wineItem) return FALSE;
+	TREEVIEW_SendTreeviewNotify (wndPtr, TVN_DELETEITEM, 0, iItem, 0, pt);
+	TREEVIEW_RemoveItem (infoPtr, wineItem);
+  }
+
+  TREEVIEW_QueueRefresh (wndPtr);
+
+  return TRUE;
+}
+
+
+static LRESULT
+TREEVIEW_GetIndent (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+
+ return infoPtr->uIndent;
+}
+
+static LRESULT
+TREEVIEW_SetIndent (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  INT32 newIndent;
+   
+  newIndent=(INT32) wParam;
+  if (newIndent < MINIMUM_INDENT) newIndent=MINIMUM_INDENT;
+  infoPtr->uIndent=newIndent;
+  
+  return 0;
+}
+
+
+
+
+
+static LRESULT
+TREEVIEW_Create (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+    TREEVIEW_INFO *infoPtr;
+	HDC32 hdc;
+    TEXTMETRIC32A tm;
+  
+    TRACE (treeview,"\n");
+      /* allocate memory for info structure */
+      infoPtr = (TREEVIEW_INFO *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
+                                     sizeof(TREEVIEW_INFO));
+
+    wndPtr->wExtra[0] = (DWORD)infoPtr;
+
+    if (infoPtr == NULL) {
+		ERR (treeview, "could not allocate info memory!\n");
+		return 0;
+    }
+
+    if ((TREEVIEW_INFO*)wndPtr->wExtra[0] != infoPtr) {
+		ERR (treeview, "pointer assignment error!\n");
+		return 0;
+    }
+
+	hdc=GetDC32 (wndPtr->hwndSelf);
+
+    /* set default settings */
+    infoPtr->uInternalStatus=0;
+    infoPtr->uNumItems=0;
+    infoPtr->clrBk = GetSysColor32 (COLOR_WINDOW);
+    infoPtr->clrText = GetSysColor32 (COLOR_BTNTEXT);
+    infoPtr->cy = 0;
+    infoPtr->cx = 0;
+    infoPtr->uIndent = 15;
+    infoPtr->himlNormal = NULL;
+    infoPtr->himlState = NULL;
+	infoPtr->uItemHeight = -1;
+    GetTextMetrics32A (hdc, &tm);
+    infoPtr->uRealItemHeight= tm.tmHeight + tm.tmExternalLeading;
+
+    infoPtr->items = NULL;
+    infoPtr->selectedItem=0;
+    infoPtr->clrText=-1;	/* use system color */
+    infoPtr->dropItem=0;
+
+/*
+    infoPtr->hwndNotify = GetParent32 (wndPtr->hwndSelf);
+    infoPtr->bTransparent = (wndPtr->dwStyle & TBSTYLE_FLAT);
+*/
+
+    if (wndPtr->dwStyle & TBSTYLE_TOOLTIPS) {
+        /* Create tooltip control */
+//      infoPtr->hwndToolTip = CreateWindowEx32A (....);
+
+        /* Send TV_TOOLTIPSCREATED notification */
+
+    }
+    ReleaseDC32 (wndPtr->hwndSelf, hdc);
 
     return 0;
 }
 
 
+
+static LRESULT 
+TREEVIEW_Destroy (WND *wndPtr) 
+{
+   TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+     
+   TREEVIEW_RemoveTree (infoPtr);
+
+   HeapFree (GetProcessHeap (), 0, infoPtr);
+
+   return 0;
+}
+
+
+static LRESULT
+TREEVIEW_Paint (WND *wndPtr, WPARAM32 wParam)
+{
+    HDC32 hdc;
+    PAINTSTRUCT32 ps;
+
+    hdc = wParam==0 ? BeginPaint32 (wndPtr->hwndSelf, &ps) : (HDC32)wParam;
+    TREEVIEW_QueueRefresh (wndPtr);
+    if(!wParam)
+        EndPaint32 (wndPtr->hwndSelf, &ps);
+    return 0;
+}
+
+
+
 static LRESULT
 TREEVIEW_EraseBackground (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
 {
@@ -120,6 +1142,7 @@
     HBRUSH32 hBrush = CreateSolidBrush32 (infoPtr->clrBk);
     RECT32 rect;
 
+    TRACE (treeview,"\n");
     GetClientRect32 (wndPtr->hwndSelf, &rect);
     FillRect32 ((HDC32)wParam, &rect, hBrush);
     DeleteObject32 (hBrush);
@@ -128,161 +1151,653 @@
 
 
 
-LRESULT WINAPI
-TREEVIEW_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
+
+
+  
+
+
+
+static BOOL32
+TREEVIEW_SendSimpleNotify (WND *wndPtr, UINT32 code)
 {
-    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    NMHDR nmhdr;
 
-    switch (uMsg)
-    {
+    TRACE (treeview, "%x\n",code);
+    nmhdr.hwndFrom = wndPtr->hwndSelf;
+    nmhdr.idFrom   = wndPtr->wIDmenu;
+    nmhdr.code     = code;
 
-    case TVM_INSERTITEM32A:
-      FIXME (treeview, "Unimplemented msg TVM_INSERTITEM32A\n");
-      return 0;
+    return (BOOL32) SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+                                   (WPARAM32)nmhdr.idFrom, (LPARAM)&nmhdr);
+}
 
-    case TVM_INSERTITEM32W:
-      FIXME (treeview, "Unimplemented msg TVM_INSERTITEM32W\n");
-      return 0;
 
-    case TVM_DELETEITEM:
-      FIXME (treeview, "Unimplemented msg TVM_DELETEITEM\n");
-      return 0;
 
-    case TVM_EXPAND:
-      FIXME (treeview, "Unimplemented msg TVM_EXPAND\n");
-      return 0;
 
-    case TVM_GETITEMRECT:
-      FIXME (treeview, "Unimplemented msg TVM_GETITEMRECT\n");
-      return 0;
+static BOOL32
+TREEVIEW_SendTreeviewNotify (WND *wndPtr, UINT32 code, UINT32 action, 
+			INT32 oldItem, INT32 newItem, POINT32 pt)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  NMTREEVIEW nmhdr;
+  TREEVIEW_ITEM  *wineItem;
 
-    case TVM_GETCOUNT:
-      FIXME (treeview, "Unimplemented msg TVM_GETCOUNT\n");
-      return 0;
+  TRACE (treeview,"code:%x action:%x olditem:%x newitem:%x\n",
+		  code,action,oldItem,newItem);
+  nmhdr.hdr.hwndFrom = wndPtr->hwndSelf;
+  nmhdr.hdr.idFrom = wndPtr->wIDmenu;
+  nmhdr.hdr.code = code;
+  nmhdr.action = action;
+  if (oldItem) {
+  	wineItem=& infoPtr->items[oldItem];
+  	nmhdr.itemOld.mask 		= wineItem->mask;
+  	nmhdr.itemOld.hItem		= wineItem->hItem;
+  	nmhdr.itemOld.state		= wineItem->state;
+  	nmhdr.itemOld.stateMask	= wineItem->stateMask;
+  	nmhdr.itemOld.iImage 		= wineItem->iImage;
+  	nmhdr.itemOld.pszText 	= wineItem->pszText;
+  	nmhdr.itemOld.cchTextMax 	= wineItem->cchTextMax;
+  	nmhdr.itemOld.iImage 		= wineItem->iImage;
+  	nmhdr.itemOld.iSelectedImage 	= wineItem->iSelectedImage;
+  	nmhdr.itemOld.cChildren 	= wineItem->cChildren;
+  	nmhdr.itemOld.lParam		= wineItem->lParam;
+  }
 
-    case TVM_GETINDENT:
-      FIXME (treeview, "Unimplemented msg TVM_GETINDENT\n");
-      return 0;
+  if (newItem) {
+  	wineItem=& infoPtr->items[newItem];
+  	nmhdr.itemNew.mask 		= wineItem->mask;
+  	nmhdr.itemNew.hItem		= wineItem->hItem;
+  	nmhdr.itemNew.state		= wineItem->state;
+  	nmhdr.itemNew.stateMask	= wineItem->stateMask;
+  	nmhdr.itemNew.iImage 		= wineItem->iImage;
+  	nmhdr.itemNew.pszText 	= wineItem->pszText;
+  	nmhdr.itemNew.cchTextMax 	= wineItem->cchTextMax;
+  	nmhdr.itemNew.iImage 		= wineItem->iImage;
+  	nmhdr.itemNew.iSelectedImage 	= wineItem->iSelectedImage;
+  	nmhdr.itemNew.cChildren 	= wineItem->cChildren;
+  	nmhdr.itemNew.lParam		= wineItem->lParam;
+  }
 
-    case TVM_SETINDENT:
-      FIXME (treeview, "Unimplemented msg TVM_SETINDENT\n");
-      return 0;
+  nmhdr.ptDrag.x = pt.x;
+  nmhdr.ptDrag.y = pt.y;
 
-	case TVM_GETIMAGELIST:
-	    return TREEVIEW_GetImageList (wndPtr, wParam, lParam);
+  return (BOOL32)SendMessage32A (GetParent32 (wndPtr->hwndSelf), WM_NOTIFY,
+                                   (WPARAM32)wndPtr->wIDmenu, (LPARAM)&nmhdr);
 
-	case TVM_SETIMAGELIST:
-	    return TREEVIEW_SetImageList (wndPtr, wParam, lParam);
+}
 
-    case TVM_GETNEXTITEM:
-      FIXME (treeview, "Unimplemented msg TVM_GETNEXTITEM\n");
-      return 0;
 
-    case TVM_SELECTITEM:
-      FIXME (treeview, "Unimplemented msg TVM_SELECTITEM \n");
-      return 0;
 
-    case TVM_GETITEM32A:
-      FIXME (treeview, "Unimplemented msg TVM_GETITEM32A\n");
-      return 0;
 
-    case TVM_GETITEM32W:
-      FIXME (treeview, "Unimplemented msg TVM_GETITEM32W\n");
-      return 0;
+static LRESULT
+TREEVIEW_Expand (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+ TREEVIEW_ITEM *wineItem;
+ UINT32 flag;
+ INT32 expandItem;
+ POINT32 pt;
+ 
+ flag= (UINT32) wParam;
+ expandItem= (INT32) lParam;
+ TRACE (treeview,"flags:%x item:%x\n", expandItem, wParam);
+ wineItem = TREEVIEW_ValidItem (infoPtr, expandItem);
+ if (!wineItem) return 0;
+ if (!wineItem->cChildren) return 0;
 
-    case TVM_SETITEM32A:
-      FIXME (treeview, "Unimplemented msg TVM_SETITEM32A\n");
-      return 0;
+ if (flag & TVE_TOGGLE) {		/* FIXME: check exact behaviour here */
+	flag &= ~TVE_TOGGLE;		/* ie: bitwise ops or 'case' ops */
+	if (wineItem->state & TVIS_EXPANDED) 
+		flag |= TVE_COLLAPSE;
+	else
+		flag |= TVE_EXPAND;
+ }
 
-    case TVM_SETITEM32W:
-      FIXME (treeview, "Unimplemented msg TVM_SETITEM32W\n");
-      return 0;
+ switch (flag) {
+    case TVE_COLLAPSERESET: 
+   		if (!wineItem->state & TVIS_EXPANDED) return 0;
+		wineItem->state &= ~(TVIS_EXPANDEDONCE | TVIS_EXPANDED);
+		TREEVIEW_RemoveAllChildren (infoPtr, wineItem);
+		break;
 
-    case TVM_EDITLABEL32A:
-      FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32A\n");
-      return 0;
+    case TVE_COLLAPSE: 
+		if (!wineItem->state & TVIS_EXPANDED) return 0;
+		wineItem->state &= ~TVIS_EXPANDED;
+		break;
 
-    case TVM_EDITLABEL32W:
-      FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32W\n");
-      return 0;
+    case TVE_EXPAND: 
+		if (wineItem->state & TVIS_EXPANDED) return 0;
+		if (!(wineItem->state & TVIS_EXPANDEDONCE)) {
+    		if (TREEVIEW_SendTreeviewNotify (wndPtr, TVN_ITEMEXPANDING, 
+											0, 0, expandItem, pt))
+					return FALSE; 	/* FIXME: OK? */
+		wineItem->state |= TVIS_EXPANDED | TVIS_EXPANDEDONCE;
+    	TREEVIEW_SendTreeviewNotify (wndPtr, TVN_ITEMEXPANDED, 
+											0, 0, expandItem, pt);
+ 	}
+	wineItem->state |= TVIS_EXPANDED;
+	break;
+   case TVE_EXPANDPARTIAL:
+		FIXME (treeview, "TVE_EXPANDPARTIAL not implemented\n");
+		wineItem->state ^=TVIS_EXPANDED;
+		wineItem->state |=TVIS_EXPANDEDONCE;
+		break;
+  }
+ 
+ TREEVIEW_QueueRefresh (wndPtr);
 
-    case TVM_GETEDITCONTROL:
-      FIXME (treeview, "Unimplemented msg TVM_GETEDITCONTROL\n");
-      return 0;
+ return TRUE;
+}
 
-    case TVM_GETVISIBLECOUNT:
-      FIXME (treeview, "Unimplemented msg TVM_GETVISIBLECOUNT\n");
-      return 0;
 
-    case TVM_HITTEST:
-      FIXME (treeview, "Unimplemented msg TVM_HITTEST\n");
-      return 0;
 
-    case TVM_CREATEDRAGIMAGE:
-      FIXME (treeview, "Unimplemented msg TVM_CREATEDRAGIMAGE\n");
-      return 0;
+static HTREEITEM
+TREEVIEW_HitTest (WND *wndPtr, LPTVHITTESTINFO lpht)
+{
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+ TREEVIEW_ITEM *wineItem;
+ RECT32 rect;
+ UINT32 status,x,y;
+ 
 
-    case TVM_SORTCHILDREN:
-      FIXME (treeview, "Unimplemented msg TVM_SORTCHILDREN\n");
-      return 0;
 
-    case TVM_ENSUREVISIBLE:
-      FIXME (treeview, "Unimplemented msg TVM_ENSUREVISIBLE\n");
-      return 0;
+ GetClientRect32 (wndPtr->hwndSelf, &rect);
+ TRACE (treeview,"(%d,%d)\n",lpht->pt.x, lpht->pt.y);
 
-    case TVM_SORTCHILDRENCB:
-      FIXME (treeview, "Unimplemented msg TVM_SORTCHILDRENCB\n");
-      return 0;
+ status=0;
+ x=lpht->pt.x;
+ y=lpht->pt.y;
+ if (x < rect.left)  status|=TVHT_TOLEFT;
+ if (x > rect.right) status|=TVHT_TORIGHT;
+ if (y < rect.top )  status|=TVHT_ABOVE;
+ if (y > rect.bottom) status|=TVHT_BELOW;
+ if (status) {
+	lpht->flags=status;
+	return 0;
+ }
 
-    case TVM_ENDEDITLABELNOW:
-      FIXME (treeview, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
-      return 0;
+ if (!infoPtr->firstVisible) WARN (treeview,"Can't fetch first visible item");
+ wineItem=&infoPtr->items [infoPtr->firstVisible];
 
-    case TVM_GETISEARCHSTRING32A:
-      FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
-      return 0;
+ while ((wineItem!=NULL) && (y > wineItem->rect.bottom))
+       wineItem=TREEVIEW_GetNextListItem (infoPtr,wineItem);
+	
+ if (wineItem==NULL) {
+	lpht->flags=TVHT_NOWHERE;
+	return 0;
+ }
 
-    case TVM_GETISEARCHSTRING32W:
-      FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
-      return 0;
+ if (x>wineItem->rect.right) {
+	lpht->flags|=TVHT_ONITEMRIGHT;
+	return wineItem->hItem;
+ }
+ 
+	
+ if (x<wineItem->rect.left+10) lpht->flags|=TVHT_ONITEMBUTTON;
 
-    case TVM_SETTOOLTIPS:
-      FIXME (treeview, "Unimplemented msg TVM_SETTOOLTIPS\n");
-      return 0;
+ lpht->flags=TVHT_ONITEMLABEL;    /* FIXME: implement other flags */
+	
 
-    case TVM_GETTOOLTIPS:
-      FIXME (treeview, "Unimplemented msg TVM_GETTOOLTIPS\n");
-      return 0;
+ lpht->hItem=wineItem->hItem;
+ return wineItem->hItem;
+}
 
-	case WM_CREATE:
-	    return TREEVIEW_Create (wndPtr, wParam, lParam);
 
-	case WM_DESTROY:
-	    return TREEVIEW_Destroy (wndPtr, wParam, lParam);
+static LRESULT
+TREEVIEW_HitTest32 (WND *wndPtr, LPARAM lParam)
+{
+ 
+  return (LRESULT) TREEVIEW_HitTest (wndPtr, (LPTVHITTESTINFO) lParam);
+}
 
-//	case EM_ENABLE:
 
-	case WM_ERASEBKGND:
-	    return TREEVIEW_EraseBackground (wndPtr, wParam, lParam);
 
-	case WM_GETDLGCODE:
-	    return DLGC_WANTARROWS | DLGC_WANTCHARS;
 
-//	case WM_PAINT:
-//	    return TREEVIEW_Paint (wndPtr, wParam);
+LRESULT
+TREEVIEW_LButtonDoubleClick (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  TREEVIEW_ITEM *wineItem;
+  INT32 iItem;
+  TVHITTESTINFO ht;
 
-//	case WM_SETFONT:
+  TRACE (treeview,"\n");
+  ht.pt.x = (INT32)LOWORD(lParam);
+  ht.pt.y = (INT32)HIWORD(lParam);
+  SetFocus32 (wndPtr->hwndSelf);
 
-//	case WM_TIMER:
+  iItem=TREEVIEW_HitTest (wndPtr, &ht);
+  TRACE (treeview,"item %d \n",iItem);
+  wineItem=TREEVIEW_ValidItem (infoPtr, iItem);
+  if (!wineItem) return 0;
+ 
+  if (TREEVIEW_SendSimpleNotify (wndPtr, NM_DBLCLK)!=TRUE) {     /* FIXME!*/
+	wineItem->state &= ~TVIS_EXPANDEDONCE;
+	TREEVIEW_Expand (wndPtr, (WPARAM32) TVE_TOGGLE, (LPARAM) iItem);
+ }
+ return TRUE;
+}
 
-//	case WM_VSCROLL:
 
-	default:
-	    if (uMsg >= WM_USER)
+
+static LRESULT
+TREEVIEW_LButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+  INT32 iItem;
+  TVHITTESTINFO ht;
+
+  TRACE (treeview,"\n");
+  ht.pt.x = (INT32)LOWORD(lParam);
+  ht.pt.y = (INT32)HIWORD(lParam);
+
+  SetFocus32 (wndPtr->hwndSelf);
+  iItem=TREEVIEW_HitTest (wndPtr, &ht);
+  TRACE (treeview,"item %d \n",iItem);
+  if (ht.flags & TVHT_ONITEMBUTTON) {
+	TREEVIEW_Expand (wndPtr, (WPARAM32) TVE_TOGGLE, (LPARAM) iItem);
+  }
+	
+  if (TREEVIEW_SelectItem (wndPtr, (WPARAM32) TVGN_CARET, (LPARAM) iItem))
+	 return 0;
+
+  
+ return 0;
+}
+
+
+static LRESULT
+TREEVIEW_RButtonDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+
+ return 0;
+}
+
+
+
+
+/* FIXME: If the specified item is the child of a collapsed parent item,
+expand parent's list of child items to reveal the specified item.
+*/
+
+static LRESULT
+TREEVIEW_SelectItem (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+ TREEVIEW_ITEM *prevItem,*wineItem;
+ INT32 action,prevSelect, newSelect;
+ POINT32 dummy;
+
+  TRACE (treeview,"item %lx, flag %x\n", lParam, wParam);
+  newSelect= (INT32) lParam;
+  wineItem = TREEVIEW_ValidItem (infoPtr, newSelect);
+  if (!wineItem) return FALSE;
+  prevSelect=infoPtr->selectedItem;
+  prevItem= TREEVIEW_ValidItem (infoPtr, prevSelect);
+  dummy.x=0;
+  dummy.y=0;
+
+  action= (INT32) wParam;
+
+  switch (action) {
+	case TVGN_CARET: 
+	    if (TREEVIEW_SendTreeviewNotify (wndPtr, TVN_SELCHANGING, TVC_BYMOUSE, 
+										prevSelect, newSelect,dummy)) 
+			return FALSE;       /* FIXME: OK? */
+		
+	    if (prevItem) prevItem->state &= ~TVIS_SELECTED;
+  		infoPtr->selectedItem=newSelect;
+		wineItem->state |=TVIS_SELECTED;
+		TREEVIEW_SendTreeviewNotify (wndPtr, TVN_SELCHANGED, 
+				TVC_BYMOUSE, prevSelect, newSelect, dummy);
+		break;
+	case TVGN_DROPHILITE: 
+		FIXME (treeview, "DROPHILITE not implemented");
+		break;
+	case TVGN_FIRSTVISIBLE:
+		FIXME (treeview, "FIRSTVISIBLE not implemented");
+		break;
+ }
+ 
+ TREEVIEW_QueueRefresh (wndPtr);
+  
+ return TRUE;
+}
+
+
+
+/* FIXME: does KEYDOWN also send notifications?? If so, use 
+   TREEVIEW_SelectItem.
+*/
+   
+
+static LRESULT
+TREEVIEW_KeyDown (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+{
+ TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+ TREEVIEW_ITEM *prevItem,*newItem;
+ int prevSelect;
+
+
+ TRACE (treeview,"%x %lx",wParam, lParam);
+ prevSelect=infoPtr->selectedItem;
+ if (!prevSelect) return FALSE;
+
+ prevItem= TREEVIEW_ValidItem (infoPtr, prevSelect);
+ 
+ newItem=NULL;
+ switch (wParam) {
+	case VK_UP: 
+		newItem=TREEVIEW_GetPrevListItem (infoPtr, prevItem);
+		if (!newItem) 
+			newItem=& infoPtr->items[infoPtr->TopRootItem];
+		break;
+	case VK_DOWN: 
+		newItem=TREEVIEW_GetNextListItem (infoPtr, prevItem);
+		if (!newItem) newItem=prevItem;
+		break;
+	case VK_HOME:
+		newItem=& infoPtr->items[infoPtr->TopRootItem];
+		break;
+	case VK_END:
+		newItem=TREEVIEW_GetLastListItem (infoPtr);
+		break;
+	case VK_PRIOR:
+	case VK_NEXT:
+	case VK_BACK:
+	case VK_RETURN:
+		FIXME (treeview, "%x not implemented\n", wParam);
+		break;
+ }
+
+ if (!newItem) return FALSE;
+
+ if (prevItem!=newItem) {
+ 	prevItem->state &= ~TVIS_SELECTED;
+ 	newItem->state |= TVIS_SELECTED;
+ 	infoPtr->selectedItem=newItem->hItem;
+ 	TREEVIEW_QueueRefresh (wndPtr);
+ 	return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+static LRESULT
+TREEVIEW_VScroll (WND *wndPtr, WPARAM32 wParam, LPARAM lParam)
+
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+  int maxHeight;
+
+  TRACE (treeview,"wp %x, lp %lx\n", wParam, lParam);
+  if (!infoPtr->uInternalStatus & TV_VSCROLL) return FALSE;
+
+  switch (LOWORD (wParam)) {
+	case SB_LINEUP: 
+			if (!infoPtr->cy) return FALSE;
+			infoPtr->cy -= infoPtr->uRealItemHeight;
+			if (infoPtr->cy < 0) infoPtr->cy=0;
+			break;
+	case SB_LINEDOWN: 
+			maxHeight=infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
+			if (infoPtr->cy == maxHeight) return FALSE;
+			infoPtr->cy += infoPtr->uRealItemHeight;
+			if (infoPtr->cy > maxHeight) 
+				infoPtr->cy = maxHeight;
+			break;
+	case SB_PAGEUP:	
+			if (!infoPtr->cy) return FALSE;
+			infoPtr->cy -= infoPtr->uVisibleHeight;
+			if (infoPtr->cy < 0) infoPtr->cy=0;
+			break;
+	case SB_PAGEDOWN:
+			maxHeight=infoPtr->uTotalHeight-infoPtr->uVisibleHeight;
+			if (infoPtr->cy == maxHeight) return FALSE;
+			infoPtr->cy += infoPtr->uVisibleHeight;
+            if (infoPtr->cy > maxHeight)
+                infoPtr->cy = maxHeight;
+			break;
+	case SB_THUMBTRACK: 
+			infoPtr->cy = HIWORD (wParam);
+			break;
+			
+  }
+  
+  TREEVIEW_QueueRefresh (wndPtr);
+  return TRUE;
+}
+
+static LRESULT
+TREEVIEW_HScroll (WND *wndPtr, WPARAM32 wParam, LPARAM lParam) 
+{
+  TREEVIEW_INFO *infoPtr = TREEVIEW_GetInfoPtr(wndPtr);
+
+  TRACE (treeview,"wp %lx, lp %x\n", lParam, wParam);
+	
+  if (!infoPtr->uInternalStatus & TV_HSCROLL) return FALSE;
+  return TRUE;
+}
+
+
+
+
+  LRESULT WINAPI
+  TREEVIEW_WindowProc (HWND32 hwnd, UINT32 uMsg, WPARAM32 wParam, LPARAM lParam)
+  {
+      WND *wndPtr = WIN_FindWndPtr(hwnd);
+  
+  
+    switch (uMsg) {
+    	case TVM_INSERTITEM32A:
+          return TREEVIEW_InsertItem32A (wndPtr, wParam, lParam);
+
+    	case TVM_INSERTITEM32W:
+      		FIXME (treeview, "Unimplemented msg TVM_INSERTITEM32W\n");
+      		return 0;
+
+    	case TVM_DELETEITEM:
+      		return TREEVIEW_DeleteItem (wndPtr, wParam, lParam);
+
+    	case TVM_EXPAND:
+      		return TREEVIEW_Expand (wndPtr, wParam, lParam);
+
+    	case TVM_GETITEMRECT:
+      		return TREEVIEW_GetItemRect (wndPtr, wParam, lParam);
+
+    	case TVM_GETCOUNT:
+      		return TREEVIEW_GetCount (wndPtr, wParam, lParam);
+
+    	case TVM_GETINDENT:
+      		return TREEVIEW_GetIndent (wndPtr, wParam, lParam);
+
+    	case TVM_SETINDENT:
+      		return TREEVIEW_SetIndent (wndPtr, wParam, lParam);
+
+    	case TVM_GETIMAGELIST:
+      		return TREEVIEW_GetImageList (wndPtr, wParam, lParam);
+
+		case TVM_SETIMAGELIST:
+	    	return TREEVIEW_SetImageList (wndPtr, wParam, lParam);
+
+    	case TVM_GETNEXTITEM:
+      		return TREEVIEW_GetNextItem32 (wndPtr, wParam, lParam);
+
+    	case TVM_SELECTITEM:
+      		return TREEVIEW_SelectItem (wndPtr, wParam, lParam);
+
+    	case TVM_GETITEM32A:
+      		return TREEVIEW_GetItem (wndPtr, wParam, lParam);
+
+    	case TVM_GETITEM32W:
+      		FIXME (treeview, "Unimplemented msg TVM_GETITEM32W\n");
+      		return 0;
+
+    	case TVM_SETITEM32A:
+      		return TREEVIEW_SetItem (wndPtr, wParam, lParam);
+
+    	case TVM_SETITEM32W:
+      		FIXME (treeview, "Unimplemented msg TVM_SETITEMW\n");
+      		return 0;
+
+    	case TVM_EDITLABEL32A:
+      		FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32A \n");
+      		return 0;
+
+    	case TVM_EDITLABEL32W:
+      		FIXME (treeview, "Unimplemented msg TVM_EDITLABEL32W \n");
+      		return 0;
+
+    	case TVM_GETEDITCONTROL:
+      		FIXME (treeview, "Unimplemented msg TVM_GETEDITCONTROL\n");
+      		return 0;
+
+    	case TVM_GETVISIBLECOUNT:
+      		return TREEVIEW_GetVisibleCount (wndPtr, wParam, lParam);
+
+    	case TVM_HITTEST:
+      		return TREEVIEW_HitTest32 (wndPtr, lParam);
+
+    	case TVM_CREATEDRAGIMAGE:
+      		FIXME (treeview, "Unimplemented msg TVM_CREATEDRAGIMAGE\n");
+      		return 0;
+  
+    	case TVM_SORTCHILDREN:
+      		FIXME (treeview, "Unimplemented msg TVM_SORTCHILDREN\n");
+      		return 0;
+  
+    	case TVM_ENSUREVISIBLE:
+      		FIXME (treeview, "Unimplemented msg TVM_ENSUREVISIBLE\n");
+      		return 0;
+  
+    	case TVM_SORTCHILDRENCB:
+      		FIXME (treeview, "Unimplemented msg TVM_SORTCHILDRENCB\n");
+      		return 0;
+  
+    	case TVM_ENDEDITLABELNOW:
+      		FIXME (treeview, "Unimplemented msg TVM_ENDEDITLABELNOW\n");
+      		return 0;
+  
+    	case TVM_GETISEARCHSTRING32A:
+      		FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32A\n");
+      		return 0;
+  
+    	case TVM_GETISEARCHSTRING32W:
+      		FIXME (treeview, "Unimplemented msg TVM_GETISEARCHSTRING32W\n");
+      		return 0;
+  
+    	case TVM_SETTOOLTIPS:
+      		FIXME (treeview, "Unimplemented msg TVM_SETTOOLTIPS\n");
+      		return 0;
+  
+    	case TVM_GETTOOLTIPS:
+      		FIXME (treeview, "Unimplemented msg TVM_GETTOOLTIPS\n");
+      		return 0;
+  
+    	case TVM_SETINSERTMARK:
+      		FIXME (treeview, "Unimplemented msg TVM_SETINSERTMARK\n");
+      		return 0;
+  
+    	case TVM_SETITEMHEIGHT:
+      		return TREEVIEW_SetItemHeight (wndPtr, wParam);
+  
+    	case TVM_GETITEMHEIGHT:
+      		return TREEVIEW_GetItemHeight (wndPtr);
+  
+    	case TVM_SETBKCOLOR:
+      		FIXME (treeview, "Unimplemented msg TVM_SETBKCOLOR\n");
+      		return 0;
+	
+    	case TVM_SETTEXTCOLOR:
+      		return TREEVIEW_SetTextColor (wndPtr, wParam, lParam);
+  
+    	case TVM_GETBKCOLOR:
+      		FIXME (treeview, "Unimplemented msg TVM_GETBKCOLOR\n");
+      		return 0;
+  
+    	case TVM_GETTEXTCOLOR:
+      		return TREEVIEW_GetTextColor (wndPtr);
+  
+    	case TVM_SETSCROLLTIME:
+      		FIXME (treeview, "Unimplemented msg TVM_SETSCROLLTIME\n");
+      		return 0;
+  
+    	case TVM_GETSCROLLTIME:
+      		FIXME (treeview, "Unimplemented msg TVM_GETSCROLLTIME\n");
+      		return 0;
+  
+    	case TVM_SETINSERTMARKCOLOR:
+      		FIXME (treeview, "Unimplemented msg TVM_SETINSERTMARKCOLOR\n");
+      		return 0;
+  
+    	case TVM_SETUNICODEFORMAT:
+      		FIXME (treeview, "Unimplemented msg TVM_SETUNICODEFORMAT\n");
+      		return 0;
+  
+    	case TVM_GETUNICODEFORMAT:
+      		FIXME (treeview, "Unimplemented msg TVM_GETUNICODEFORMAT\n");
+      		return 0;
+  
+//		case WM_COMMAND:
+  
+		case WM_CREATE:
+			return TREEVIEW_Create (wndPtr, wParam, lParam);
+  
+		case WM_DESTROY:
+			return TREEVIEW_Destroy (wndPtr);
+  
+//		case WM_ENABLE:
+  
+		case WM_ERASEBKGND:
+	    	return TREEVIEW_EraseBackground (wndPtr, wParam, lParam);
+  
+		case WM_GETDLGCODE:
+	    	return DLGC_WANTARROWS | DLGC_WANTCHARS;
+  
+		case WM_PAINT:
+	    	return TREEVIEW_Paint (wndPtr, wParam);
+  
+//		case WM_GETFONT:
+//		case WM_SETFONT:
+  
+		case WM_KEYDOWN:
+			return TREEVIEW_KeyDown (wndPtr, wParam, lParam);
+  
+  
+//		case WM_KILLFOCUS:
+//		case WM_SETFOCUS:
+  
+  
+		case WM_LBUTTONDOWN:
+			return TREEVIEW_LButtonDown (wndPtr, wParam, lParam);
+  
+		case WM_LBUTTONDBLCLK:
+			return TREEVIEW_LButtonDoubleClick (wndPtr, wParam, lParam);
+  
+		case WM_RBUTTONDOWN:
+			return TREEVIEW_RButtonDown (wndPtr, wParam, lParam);
+  
+  
+//		case WM_SYSCOLORCHANGE:
+//		case WM_STYLECHANGED:
+//		case WM_SETREDRAW:
+  
+		case WM_TIMER:
+			return TREEVIEW_HandleTimer (wndPtr, wParam, lParam);
+  
+//		case WM_SIZE:
+		case WM_HSCROLL: 
+			return TREEVIEW_HScroll (wndPtr, wParam, lParam);
+		case WM_VSCROLL: 
+			return TREEVIEW_VScroll (wndPtr, wParam, lParam);
+  
+		default:
+	    	if (uMsg >= WM_USER)
 		FIXME (treeview, "Unknown msg %04x wp=%08x lp=%08lx\n",
-		       uMsg, wParam, lParam);
-	    return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
-    }
+  		     uMsg, wParam, lParam);
+  	    return DefWindowProc32A (hwnd, uMsg, wParam, lParam);
+      }
     return 0;
 }
 
diff --git a/dlls/comctl32/updown.c b/dlls/comctl32/updown.c
index e93b5ef..8ccc64a 100644
--- a/dlls/comctl32/updown.c
+++ b/dlls/comctl32/updown.c
@@ -27,14 +27,12 @@
  */
 
 #include <stdlib.h>
-#include <assert.h>
-#include <string.h>
 #include "windows.h"
+#include "commctrl.h"
 #include "winnls.h"
 #include "sysmetrics.h"
 #include "updown.h"
 #include "graphics.h"
-#include "heap.h"
 #include "win.h"
 #include "debug.h"
 
@@ -249,7 +247,7 @@
     if (!(wndPtr->dwStyle & UDS_NOTHOUSANDS)) {
       char txt2[20], *src = txt1, *dst = txt2;
       if(len%3 > 0){
-	strncpy(dst, src, len%3);
+	lstrcpyn32A (dst, src, len%3);
 	dst += len%3;
 	src += len%3;
       }
@@ -597,9 +595,7 @@
       return TRUE;
 
     case WM_CREATE:
-      infoPtr =
-	(UPDOWN_INFO*)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY,
-				 sizeof(UPDOWN_INFO));
+      infoPtr = (UPDOWN_INFO*)COMCTL32_Alloc (sizeof(UPDOWN_INFO));
       wndPtr->wExtra[0] = (DWORD)infoPtr;
 
       /* initialize the info struct */
@@ -618,9 +614,9 @@
     
     case WM_DESTROY:
       if(infoPtr->AccelVect)
-	free(infoPtr->AccelVect);
+	COMCTL32_Free (infoPtr->AccelVect);
 
-      HeapFree (GetProcessHeap (), 0, infoPtr);
+      COMCTL32_Free (infoPtr);
       wndPtr->wExtra[0] = 0;
 
       TRACE(updown, "UpDown Ctrl destruction, hwnd=%04x\n", hwnd);
@@ -715,13 +711,13 @@
     case UDM_SETACCEL:
       TRACE(updown, "UpDown Ctrl new accel info, hwnd=%04x\n", hwnd);
       if(infoPtr->AccelVect){
-	free(infoPtr->AccelVect);
+	COMCTL32_Free (infoPtr->AccelVect);
 	infoPtr->AccelCount = 0;
 	infoPtr->AccelVect  = 0;
       }
       if(wParam==0)
 	return TRUE;
-      infoPtr->AccelVect = malloc(wParam*sizeof(UDACCEL));
+      infoPtr->AccelVect = COMCTL32_Alloc (wParam*sizeof(UDACCEL));
       if(infoPtr->AccelVect==0)
 	return FALSE;
       memcpy(infoPtr->AccelVect, (void*)lParam, wParam*sizeof(UDACCEL));
@@ -816,9 +812,9 @@
 
     default: 
       if (message >= WM_USER) 
-	WARN(updown, "unknown msg %04x wp=%04x lp=%08lx\n", 
-		     message, wParam, lParam );
-      return DefWindowProc32A( hwnd, message, wParam, lParam ); 
+	ERR (updown, "unknown msg %04x wp=%04x lp=%08lx\n", 
+	     message, wParam, lParam);
+      return DefWindowProc32A (hwnd, message, wParam, lParam); 
     } 
 
     return 0;
diff --git a/dlls/psapi/Makefile.in b/dlls/psapi/Makefile.in
new file mode 100644
index 0000000..17c618b
--- /dev/null
+++ b/dlls/psapi/Makefile.in
@@ -0,0 +1,16 @@
+DEFS      = @DLLFLAGS@ -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = psapi
+
+C_SRCS = \
+	psapi_main.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
+
diff --git a/dlls/psapi/psapi_main.c b/dlls/psapi/psapi_main.c
new file mode 100644
index 0000000..94bc7f6
--- /dev/null
+++ b/dlls/psapi/psapi_main.c
@@ -0,0 +1,301 @@
+/*
+ *      PSAPI library
+ *
+ *      Copyright 1998  Patrik Stridvall
+ */
+
+#include "windows.h"
+#include "winbase.h"
+#include "wintypes.h"
+#include "winerror.h"
+#include "debug.h"
+#include "psapi.h"
+
+#include <string.h>
+
+/***********************************************************************
+ *           EmptyWorkingSet (PSAPI.1)
+ */
+BOOL32 WINAPI EmptyWorkingSet32(HANDLE32 hProcess)
+{
+  return SetProcessWorkingSetSize(hProcess, 0xFFFFFFFF, 0xFFFFFFFF);
+}
+
+/***********************************************************************
+ *           EnumDeviceDrivers (PSAPI.2)
+ */
+BOOL32 WINAPI EnumDeviceDrivers(
+  LPVOID *lpImageBase, DWORD cb, LPDWORD lpcbNeeded)
+{
+  FIXME(psapi, "(%p, %ld, %p): stub\n", lpImageBase, cb, lpcbNeeded);
+
+  if(lpcbNeeded)
+    *lpcbNeeded = 0;
+
+  return TRUE;
+}    
+
+
+/***********************************************************************
+ *           EnumProcesses (PSAPI.3)
+ */
+BOOL32 WINAPI EnumProcesses(DWORD *lpidProcess, DWORD cb, DWORD *lpcbNeeded)
+{
+  FIXME(psapi, "(%p, %ld, %p): stub\n", lpidProcess,cb, lpcbNeeded);
+
+  if(lpcbNeeded)
+    *lpcbNeeded = 0;
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *           EnumProcessModules (PSAPI.4)
+ */
+BOOL32 WINAPI EnumProcessModules(
+  HANDLE32 hProcess, HMODULE32 *lphModule, DWORD cb, LPDWORD lpcbNeeded)
+{
+  FIXME(psapi, "(hProcess=0x%08x, %p, %ld, %p): stub\n",
+    hProcess, lphModule, cb, lpcbNeeded
+  );
+
+  if(lpcbNeeded)
+    *lpcbNeeded = 0;
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *          GetDeviceDriverBaseName32A (PSAPI.5)
+ */
+DWORD WINAPI GetDeviceDriverBaseName32A(
+  LPVOID ImageBase, LPSTR lpBaseName, DWORD nSize)
+{
+  FIXME(psapi, "(%p, %s, %ld): stub\n",
+    ImageBase, debugstr_a(lpBaseName), nSize
+  );
+
+  if(lpBaseName && nSize)
+    lpBaseName[0] = '\0';
+
+  return 0;
+}
+
+/***********************************************************************
+ *           GetDeviceDriverBaseName32W (PSAPI.6)
+ */
+DWORD WINAPI GetDeviceDriverBaseName32W(
+  LPVOID ImageBase, LPWSTR lpBaseName, DWORD nSize)
+{
+  FIXME(psapi, "(%p, %s, %ld): stub\n",
+    ImageBase, debugstr_w(lpBaseName), nSize
+  );
+
+  if(lpBaseName && nSize)
+    lpBaseName[0] = '\0';
+
+  return 0;
+}
+
+/***********************************************************************
+ *           GetDeviceDriverFileName32A (PSAPI.7)
+ */
+DWORD WINAPI GetDeviceDriverFileName32A(
+  LPVOID ImageBase, LPSTR lpFilename, DWORD nSize)
+{
+  FIXME(psapi, "(%p, %s, %ld): stub\n",
+    ImageBase, debugstr_a(lpFilename), nSize
+  );
+
+  if(lpFilename && nSize)
+    lpFilename[0] = '\0';
+
+  return 0;
+}
+
+/***********************************************************************
+ *           GetDeviceDriverFileName32W (PSAPI.8)
+ */
+DWORD WINAPI GetDeviceDriverFileName32W(
+  LPVOID ImageBase, LPWSTR lpFilename, DWORD nSize)
+{
+  FIXME(psapi, "(%p, %s, %ld): stub\n",
+    ImageBase, debugstr_w(lpFilename), nSize
+  );
+
+  if(lpFilename && nSize)
+    lpFilename[0] = '\0';
+
+  return 0;
+}
+
+/***********************************************************************
+ *           GetMappedFileName32A (PSAPI.9)
+ */
+DWORD WINAPI GetMappedFileName32A(
+  HANDLE32 hProcess, LPVOID lpv, LPSTR lpFilename, DWORD nSize)
+{
+  FIXME(psapi, "(hProcess=0x%08x, %p, %s, %ld): stub\n",
+    hProcess, lpv, debugstr_a(lpFilename), nSize
+  );
+
+  if(lpFilename && nSize)
+    lpFilename[0] = '\0';
+
+  return 0;
+}
+
+/***********************************************************************
+ *           GetMappedFileName32W (PSAPI.10)
+ */
+DWORD WINAPI GetMappedFileName32W(
+  HANDLE32 hProcess, LPVOID lpv, LPWSTR lpFilename, DWORD nSize)
+{
+  FIXME(psapi, "(hProcess=0x%08x, %p, %s, %ld): stub\n",
+    hProcess, lpv, debugstr_w(lpFilename), nSize
+  );
+
+  if(lpFilename && nSize)
+    lpFilename[0] = '\0';
+
+  return 0;
+}
+
+/***********************************************************************
+ *           GetModuleBaseName32A (PSAPI.11)
+ */
+DWORD WINAPI GetModuleBaseName32A(
+  HANDLE32 hProcess, HMODULE32 hModule, LPSTR lpBaseName, DWORD nSize)
+{
+  FIXME(psapi, "(hProcess=0x%08x, hModule=0x%08x, %s, %ld): stub\n",
+    hProcess, hModule, debugstr_a(lpBaseName), nSize
+  );
+
+  if(lpBaseName && nSize)
+    lpBaseName[0] = '\0';
+
+  return 0;
+}
+
+/***********************************************************************
+ *           GetModuleBaseName32W (PSAPI.12)
+ */
+DWORD WINAPI GetModuleBaseName32W(
+  HANDLE32 hProcess, HMODULE32 hModule, LPWSTR lpBaseName, DWORD nSize)
+{
+  FIXME(psapi, "(hProcess=0x%08x, hModule=0x%08x, %s, %ld): stub\n",
+    hProcess, hModule, debugstr_w(lpBaseName), nSize);
+
+  if(lpBaseName && nSize)
+    lpBaseName[0] = '\0';
+
+  return 0;
+}
+
+/***********************************************************************
+ *           GetModuleFileNameEx32A (PSAPI.13)
+ */
+DWORD WINAPI GetModuleFileNameEx32A(
+  HANDLE32 hProcess, HMODULE32 hModule, LPSTR lpFilename, DWORD nSize)
+{
+  FIXME(psapi, "(hProcess=0x%08x,hModule=0x%08x, %s, %ld): stub\n",
+    hProcess, hModule, debugstr_a(lpFilename), nSize
+  );
+
+  if(lpFilename&&nSize)
+    lpFilename[0]='\0';
+
+  return 0;
+}
+
+/***********************************************************************
+ *           GetModuleFileNameEx32W (PSAPI.14)
+ */
+DWORD WINAPI GetModuleFileNameEx32W(
+  HANDLE32 hProcess, HMODULE32 hModule, LPWSTR lpFilename, DWORD nSize)
+{
+  FIXME(psapi, "(hProcess=0x%08x,hModule=0x%08x, %s, %ld): stub\n",
+    hProcess, hModule, debugstr_w(lpFilename), nSize
+  );
+
+  if(lpFilename && nSize)
+    lpFilename[0] = '\0';
+
+  return 0;
+}
+
+/***********************************************************************
+ *           GetModuleInformation32 (PSAPI.15)
+ */
+BOOL32 WINAPI GetModuleInformation32(
+  HANDLE32 hProcess, HMODULE32 hModule, LPMODULEINFO32 lpmodinfo, DWORD cb)
+{
+  FIXME(psapi, "(hProcess=0x%08x, hModule=0x%08x, %p, %ld): stub\n",
+    hProcess, hModule, lpmodinfo, cb
+  );
+
+  memset(lpmodinfo, 0, cb);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *           GetProcessMemoryInfo32 (PSAPI.16)
+ */
+BOOL32 WINAPI GetProcessMemoryInfo32(
+  HANDLE32 Process, PPROCESS_MEMORY_COUNTERS32 ppsmemCounters, DWORD cb)
+{
+  FIXME(psapi, "(hProcess=0x%08x, %p, %ld): stub\n",
+    Process, ppsmemCounters, cb
+  );
+
+  memset(ppsmemCounters, 0, cb);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *           GetWsChanges32 (PSAPI.17)
+ */
+BOOL32 WINAPI GetWsChanges32(
+  HANDLE32 hProcess, PPSAPI_WS_WATCH_INFORMATION32 lpWatchInfo, DWORD cb)
+{
+  FIXME(psapi, "(hProcess=0x%08x, %p, %ld): stub\n",
+    hProcess, lpWatchInfo, cb
+  );
+
+  memset(lpWatchInfo, 0, cb);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *           InitializeProcessForWsWatch32 (PSAPI.18)
+ */
+BOOL32 WINAPI InitializeProcessForWsWatch32(HANDLE32 hProcess)
+{
+  FIXME(psapi, "(hProcess=0x%08x): stub\n", hProcess);
+
+  return TRUE;
+}
+
+/***********************************************************************
+ *           QueryWorkingSet32 (PSAPI.?)
+ * FIXME
+ *     I haven't been able to find the ordinal for this function,
+ *     This means it can't be called from outside the DLL.
+ */
+BOOL32 WINAPI QueryWorkingSet32(HANDLE32 hProcess, LPVOID pv, DWORD cb)
+{
+  FIXME(psapi, "(hProcess=0x%08x, %p, %ld)", hProcess, pv, cb);
+
+  if(pv && cb)
+    ((DWORD *) pv)[0] = 0; /* Empty WorkingSet */
+
+  return TRUE;
+}
+
+
+
+
+
diff --git a/dlls/shell32/Makefile.in b/dlls/shell32/Makefile.in
index 2a7f204..6a58119 100644
--- a/dlls/shell32/Makefile.in
+++ b/dlls/shell32/Makefile.in
@@ -8,6 +8,7 @@
 
 C_SRCS = \
 	contmenu.c \
+	dataobject.c \
 	enumidlist.c \
 	folders.c \
 	pidl.c \
diff --git a/dlls/shell32/contmenu.c b/dlls/shell32/contmenu.c
index 9aa758c..9bca626 100644
--- a/dlls/shell32/contmenu.c
+++ b/dlls/shell32/contmenu.c
@@ -10,11 +10,6 @@
 #include "shlobj.h"
 #include "shell32_main.h"
 
-#define IDM_EXPLORE  0
-#define IDM_OPEN     1
-#define IDM_RENAME   2
-#define IDM_LAST     IDM_RENAME
-
 #define __T(x)      x
 #define _T(x)       __T(x)
 #define TEXT        _T
@@ -132,8 +127,26 @@
 	TRACE(shell,"(%p)->()\n",cm);
 	return cm;
 }
+/**************************************************************************
+*  ICM_InsertItem()
+*/ 
+static void ICM_InsertItem (HMENU32 hmenu, UINT32 indexMenu, UINT32 wID, UINT32 fType, LPSTR dwTypeData, UINT32 fState)
+{	MENUITEMINFO32A	mii;
 
-
+	ZeroMemory(&mii, sizeof(mii));
+	mii.cbSize = sizeof(mii);
+	if (fType == MFT_SEPARATOR)
+	{ mii.fMask = MIIM_ID | MIIM_TYPE;
+	}
+	else
+	{ mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
+	  mii.dwTypeData = dwTypeData;
+	  mii.fState = MFS_ENABLED | MFS_DEFAULT;
+	}
+	mii.wID = wID;
+	mii.fType = fType;
+	InsertMenuItem32A( hmenu, indexMenu, TRUE, &mii);
+}
 /**************************************************************************
 * IContextMenu_QueryContextMenu()
 */
@@ -141,71 +154,28 @@
 static HRESULT WINAPI  IContextMenu_QueryContextMenu( LPCONTEXTMENU this, HMENU32 hmenu,
 							UINT32 indexMenu,UINT32 idCmdFirst,UINT32 idCmdLast,UINT32 uFlags)
 {	BOOL32			fExplore ;
-	MENUITEMINFO32A	mii;
 
 	TRACE(shell,"(%p)->(hmenu=%x indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",this, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
+
 	if(!(CMF_DEFAULTONLY & uFlags))
 	{ if(!this->bAllValues)
-      { fExplore = uFlags & CMF_EXPLORE;
-        if(fExplore)
-        { ZeroMemory(&mii, sizeof(mii));
-          mii.cbSize = sizeof(mii);
-          mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
-          mii.wID = idCmdFirst + IDM_EXPLORE;
-          mii.fType = MFT_STRING;
-          mii.dwTypeData = TEXT("&Explore");
-          mii.fState = MFS_ENABLED | MFS_DEFAULT;
-          InsertMenuItem32A( hmenu, indexMenu++, TRUE, &mii);
+	  { fExplore = uFlags & CMF_EXPLORE;
+	    if(fExplore)
+	    { ICM_InsertItem(hmenu, indexMenu++, idCmdFirst+IDM_EXPLORE, MFT_STRING, TEXT("&Explore"), MFS_ENABLED|MFS_DEFAULT);
+	      ICM_InsertItem(hmenu, indexMenu++, idCmdFirst+IDM_OPEN, MFT_STRING, TEXT("&Open"), MFS_ENABLED);
+	    }
+	    else
+            { ICM_InsertItem(hmenu, indexMenu++, idCmdFirst+IDM_OPEN, MFT_STRING, TEXT("&Open"), MFS_ENABLED|MFS_DEFAULT);
+	      ICM_InsertItem(hmenu, indexMenu++, idCmdFirst+IDM_EXPLORE, MFT_STRING, TEXT("&Explore"), MFS_ENABLED);
+            }
 
-          ZeroMemory(&mii, sizeof(mii));
-          mii.cbSize = sizeof(mii);
-          mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
-          mii.wID = idCmdFirst + IDM_OPEN;
-          mii.fType = MFT_STRING;
-          mii.dwTypeData = TEXT("&Open");
-          mii.fState = MFS_ENABLED;
-          InsertMenuItem32A( hmenu, indexMenu++, TRUE, &mii);
-        }
-        else
-        { ZeroMemory(&mii, sizeof(mii));
-          mii.cbSize = sizeof(mii);
-          mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
-          mii.wID = idCmdFirst + IDM_OPEN;
-          mii.fType = MFT_STRING;
-          mii.dwTypeData = TEXT("&Open");
-          mii.fState = MFS_ENABLED | MFS_DEFAULT;
-          InsertMenuItem32A( hmenu, indexMenu++, TRUE, &mii);
-
-          ZeroMemory(&mii, sizeof(mii));
-          mii.cbSize = sizeof(mii);
-          mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
-          mii.wID = idCmdFirst + IDM_EXPLORE;
-          mii.fType = MFT_STRING;
-          mii.dwTypeData = TEXT("&Explore");
-          mii.fState = MFS_ENABLED;
-          InsertMenuItem32A( hmenu, indexMenu++, TRUE, &mii);
-        }
-
-        if(uFlags & CMF_CANRENAME)
-        { ZeroMemory(&mii, sizeof(mii));
-          mii.cbSize = sizeof(mii);
-          mii.fMask = MIIM_ID | MIIM_TYPE;
-          mii.wID = 0;
-          mii.fType = MFT_SEPARATOR;
-          InsertMenuItem32A( hmenu, indexMenu++, TRUE, &mii);
- 
-          ZeroMemory(&mii, sizeof(mii));
-          mii.cbSize = sizeof(mii);
-          mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
-          mii.wID = idCmdFirst + IDM_RENAME;
-          mii.fType = MFT_STRING;
-          mii.dwTypeData = TEXT("&Rename");
-          mii.fState = (IContextMenu_CanRenameItems(this) ? MFS_ENABLED : MFS_DISABLED);
-          InsertMenuItem32A( hmenu, indexMenu++, TRUE, &mii);
-        }
-      }
-      return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (IDM_LAST + 1));
-    }
+            if(uFlags & CMF_CANRENAME)
+            { ICM_InsertItem(hmenu, indexMenu++, 0, MFT_SEPARATOR, NULL, 0);
+	      ICM_InsertItem(hmenu, indexMenu++, idCmdFirst+IDM_RENAME, MFT_STRING, TEXT("&Rename"), (IContextMenu_CanRenameItems(this) ? MFS_ENABLED : MFS_DISABLED));
+	    }
+	  }
+	  return MAKE_HRESULT(SEVERITY_SUCCESS, 0, (IDM_LAST + 1));
+	}
 	return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 0);
 }
 
@@ -230,41 +200,41 @@
 	switch(LOWORD(lpcmi->lpVerb))
 	{ case IDM_EXPLORE:
 	  case IDM_OPEN:
-        /* Find the first item in the list that is not a value. These commands 
-      	should never be invoked if there isn't at least one key item in the list.*/
+            /* Find the first item in the list that is not a value. These commands 
+      	    should never be invoked if there isn't at least one folder item in the list.*/
 
-        for(i = 0; this->aPidls[i]; i++)
+	    for(i = 0; this->aPidls[i]; i++)
 	    { if(!_ILIsValue(this->aPidls[i]))
-            break;
-        }
+                break;
+	    }
       
-		pidlTemp = ILCombine(this->pSFParent->mpidl, this->aPidls[i]);
-		pidlFQ = ILCombine(this->pSFParent->mpidlNSRoot, pidlTemp);
-		SHFree(pidlTemp);
+	    pidlTemp = ILCombine(this->pSFParent->mpidl, this->aPidls[i]);
+	    pidlFQ = ILCombine(this->pSFParent->mpidlNSRoot, pidlTemp);
+	    SHFree(pidlTemp);
       
-		ZeroMemory(&sei, sizeof(sei));
-		sei.cbSize = sizeof(sei);
-		sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
-		sei.lpIDList = pidlFQ;
-		sei.lpClass = TEXT("folder");
-		sei.hwnd = lpcmi->hwnd;
-		sei.nShow = SW_SHOWNORMAL;
+	    ZeroMemory(&sei, sizeof(sei));
+	    sei.cbSize = sizeof(sei);
+	    sei.fMask = SEE_MASK_IDLIST | SEE_MASK_CLASSNAME;
+	    sei.lpIDList = pidlFQ;
+	    sei.lpClass = TEXT("folder");
+	    sei.hwnd = lpcmi->hwnd;
+	    sei.nShow = SW_SHOWNORMAL;
       
-		if(LOWORD(lpcmi->lpVerb) == IDM_EXPLORE)
+	    if(LOWORD(lpcmi->lpVerb) == IDM_EXPLORE)
 	    { sei.lpVerb = TEXT("explore");
-        }
-		else
-        { sei.lpVerb = TEXT("open");
-        }
-        ShellExecuteEx32A(&sei);
-		SHFree(pidlFQ);
-        break;
-
+	    }
+	    else
+	    { sei.lpVerb = TEXT("open");
+	    }
+	    ShellExecuteEx32A(&sei);
+	    SHFree(pidlFQ);
+	    break;
+		
 	  case IDM_RENAME:
-        MessageBeep32(MB_OK);
-        /*handle rename for the view here*/
-        break;
-   	}
+	    MessageBeep32(MB_OK);
+	    /*handle rename for the view here*/
+	    break;
+	}
 	return NOERROR;
 }
 
@@ -361,9 +331,9 @@
 	TRACE(shell,"(%p)->(apidl=%p count=%u)\n",this, aPidls, uItemCount);
 	if(this->aPidls)
 	{ for(i = 0; i < uItemCount; i++)
-      { this->aPidls[i] = ILClone(aPidls[i]);
-      }
-      return TRUE;
+	  { this->aPidls[i] = ILClone(aPidls[i]);
+	  }
+	  return TRUE;
  	}
 	return FALSE;
 }
diff --git a/dlls/shell32/dataobject.c b/dlls/shell32/dataobject.c
new file mode 100644
index 0000000..f9f790f
--- /dev/null
+++ b/dlls/shell32/dataobject.c
@@ -0,0 +1,259 @@
+/*
+ *	IEnumFORMATETC, IDataObject
+ *
+ * selecting and droping objects within the shell and/or common dialogs
+ *
+ *	Copyright 1998	<juergen.schmied@metronet.de>
+ */
+#include "debug.h"
+#include "shlobj.h"
+#include "winerror.h"
+#include "shell32_main.h"
+/***********************************************************************
+*   IEnumFORMATETC implementation
+*/
+static HRESULT WINAPI IEnumFORMATETC_QueryInterface (LPENUMFORMATETC this, REFIID riid, LPVOID * ppvObj);
+static ULONG WINAPI IEnumFORMATETC_AddRef (LPENUMFORMATETC this);
+static ULONG WINAPI IEnumFORMATETC_Release (LPENUMFORMATETC this);
+static HRESULT WINAPI IEnumFORMATETC_Next(LPENUMFORMATETC this, ULONG celt, FORMATETC32 *rgelt, ULONG *pceltFethed);
+static HRESULT WINAPI IEnumFORMATETC_Skip(LPENUMFORMATETC this, ULONG celt);
+static HRESULT WINAPI IEnumFORMATETC_Reset(LPENUMFORMATETC this);
+static HRESULT WINAPI IEnumFORMATETC_Clone(LPENUMFORMATETC this, LPENUMFORMATETC* ppenum);
+
+static struct IEnumFORMATETC_VTable efvt = 
+{	IEnumFORMATETC_QueryInterface,
+	IEnumFORMATETC_AddRef,
+	IEnumFORMATETC_Release,
+	IEnumFORMATETC_Next,
+	IEnumFORMATETC_Skip,
+	IEnumFORMATETC_Reset,
+	IEnumFORMATETC_Clone
+};
+
+extern LPENUMFORMATETC IEnumFORMATETC_Constructor(UINT32 cfmt, const FORMATETC32 afmt[])
+{	LPENUMFORMATETC ef;
+	DWORD size=cfmt * sizeof(FORMATETC32);
+	
+	ef=(LPENUMFORMATETC)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumFORMATETC));
+	ef->ref=1;
+	ef->lpvtbl=&efvt;
+
+	ef->posFmt = 0;
+	ef->countFmt = cfmt;
+	ef->pFmt = SHAlloc (size);
+
+	if (ef->pFmt)
+	{ memcpy(ef->pFmt, afmt, size);
+	}
+
+	TRACE(shell,"(%p)->()\n",ef);
+	return ef;
+}
+static HRESULT WINAPI IEnumFORMATETC_QueryInterface (LPENUMFORMATETC this, REFIID riid, LPVOID * ppvObj)
+{	char    xriid[50];
+	WINE_StringFromCLSID((LPCLSID)riid,xriid);
+	TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
+
+			*ppvObj = NULL;
+
+	if(IsEqualIID(riid, &IID_IUnknown))
+	{ *ppvObj = this; 
+	}
+	else if(IsEqualIID(riid, &IID_IEnumFORMATETC))
+	{ *ppvObj = (IDataObject*)this;
+	}   
+
+	if(*ppvObj)
+	{ (*(LPENUMFORMATETC*)ppvObj)->lpvtbl->fnAddRef(this);      
+	  TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
+	  return S_OK;
+	}
+	TRACE(shell,"-- Interface: E_NOINTERFACE\n");
+	return E_NOINTERFACE;
+
+}
+static ULONG WINAPI IEnumFORMATETC_AddRef (LPENUMFORMATETC this)
+{	TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
+	return ++(this->ref);
+}
+static ULONG WINAPI IEnumFORMATETC_Release (LPENUMFORMATETC this)
+{	TRACE(shell,"(%p)->()\n",this);
+	if (!--(this->ref)) 
+	{ TRACE(shell," destroying IEnumFORMATETC(%p)\n",this);
+	  if (this->pFmt)
+	  { SHFree (this->pFmt);
+	  }
+	  HeapFree(GetProcessHeap(),0,this);
+	  return 0;
+	}
+	return this->ref;
+}
+static HRESULT WINAPI IEnumFORMATETC_Next(LPENUMFORMATETC this, ULONG celt, FORMATETC32 *rgelt, ULONG *pceltFethed)
+{	UINT32 cfetch;
+	HRESULT hres = S_FALSE;
+
+	TRACE (shell, "(%p)->()\n", this);
+
+        if (this->posFmt < this->countFmt)
+        { cfetch = this->countFmt - this->posFmt;
+	  if (cfetch >= celt)
+	  { cfetch = celt;
+	    hres = S_OK;
+	  }
+	  memcpy(rgelt, &this->pFmt[this->posFmt], cfetch * sizeof(FORMATETC32));
+	  this->posFmt += cfetch;
+	}
+	else
+	{ cfetch = 0;
+        }
+
+        if (pceltFethed)
+        { *pceltFethed = cfetch;
+        }
+
+        return hres;
+}
+static HRESULT WINAPI IEnumFORMATETC_Skip(LPENUMFORMATETC this, ULONG celt)
+{	FIXME (shell, "(%p)->(num=%lu)\n", this, celt);
+
+	this->posFmt += celt;
+	if (this->posFmt > this->countFmt)
+        { this->posFmt = this->countFmt;
+	  return S_FALSE;
+	}
+	return S_OK;
+}
+static HRESULT WINAPI IEnumFORMATETC_Reset(LPENUMFORMATETC this)
+{	FIXME (shell, "(%p)->()\n", this);
+
+        this->posFmt = 0;
+        return S_OK;
+}
+static HRESULT WINAPI IEnumFORMATETC_Clone(LPENUMFORMATETC this, LPENUMFORMATETC* ppenum)
+{	FIXME (shell, "(%p)->(ppenum=%p)\n", this, ppenum);
+	return E_NOTIMPL;
+}
+
+/***********************************************************************
+*   IDataObject implementation
+*/
+
+static HRESULT WINAPI IDataObject_QueryInterface (LPDATAOBJECT, REFIID riid, LPVOID * ppvObj);
+static ULONG WINAPI IDataObject_AddRef (LPDATAOBJECT);
+static ULONG WINAPI IDataObject_Release (LPDATAOBJECT);
+static HRESULT WINAPI IDataObject_GetData (LPDATAOBJECT, LPFORMATETC32 pformatetcIn, STGMEDIUM32 *pmedium);
+static HRESULT WINAPI IDataObject_GetDataHere(LPDATAOBJECT, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium);
+static HRESULT WINAPI IDataObject_QueryGetData(LPDATAOBJECT, LPFORMATETC32 pformatetc);
+static HRESULT WINAPI IDataObject_GetCanonicalFormatEtc(LPDATAOBJECT, LPFORMATETC32 pformatectIn, LPFORMATETC32 pformatetcOut);
+static HRESULT WINAPI IDataObject_SetData(LPDATAOBJECT, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium, BOOL32 fRelease);
+static HRESULT WINAPI IDataObject_EnumFormatEtc(LPDATAOBJECT, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc);
+static HRESULT WINAPI IDataObject_DAdvise (LPDATAOBJECT, LPFORMATETC32 *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection);
+static HRESULT WINAPI IDataObject_DUnadvise(LPDATAOBJECT, DWORD dwConnection);
+static HRESULT WINAPI IDataObject_EnumDAdvise(LPDATAOBJECT, IEnumSTATDATA **ppenumAdvise);
+
+static struct IDataObject_VTable dtovt = 
+{	IDataObject_QueryInterface,
+	IDataObject_AddRef,
+	IDataObject_Release,
+	IDataObject_GetData,
+	IDataObject_GetDataHere,
+	IDataObject_QueryGetData,
+	IDataObject_GetCanonicalFormatEtc,
+	IDataObject_SetData,
+	IDataObject_EnumFormatEtc,
+	IDataObject_DAdvise,
+	IDataObject_DUnadvise,
+	IDataObject_EnumDAdvise
+};
+
+/**************************************************************************
+*  IDataObject_Constructor
+*/
+LPDATAOBJECT IDataObject_Constructor(HWND32 hwndOwner, LPSHELLFOLDER pcf, LPITEMIDLIST * apit, UINT32 cpit)
+{	LPDATAOBJECT dto;
+	dto=(LPDATAOBJECT)HeapAlloc(GetProcessHeap(),0,sizeof(IDataObject));
+	dto->ref=1;
+	dto->lpvtbl=&dtovt;
+	TRACE(shell,"(%p)->()\n",dto);
+	return dto;
+}
+/***************************************************************************
+*  IDataObject_QueryInterface
+*/
+static HRESULT WINAPI IDataObject_QueryInterface (LPDATAOBJECT this, REFIID riid, LPVOID * ppvObj)
+{	char    xriid[50];
+	WINE_StringFromCLSID((LPCLSID)riid,xriid);
+	TRACE(shell,"(%p)->(\n\tIID:\t%s,%p)\n",this,xriid,ppvObj);
+
+	*ppvObj = NULL;
+
+	if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
+	{ *ppvObj = this; 
+	}
+	else if(IsEqualIID(riid, &IID_IDataObject))  /*IDataObject*/
+	{ *ppvObj = (IDataObject*)this;
+	}   
+
+	if(*ppvObj)
+	{ (*(LPDATAOBJECT*)ppvObj)->lpvtbl->fnAddRef(this);      
+	  TRACE(shell,"-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
+	  return S_OK;
+	}
+	TRACE(shell,"-- Interface: E_NOINTERFACE\n");
+	return E_NOINTERFACE;
+}   
+/**************************************************************************
+*  IDataObject_AddRef
+*/
+static ULONG WINAPI IDataObject_AddRef(LPDATAOBJECT this)
+{	TRACE(shell,"(%p)->(count=%lu)\n",this,(this->ref)+1);
+	return ++(this->ref);
+}
+/**************************************************************************
+*  IDataObject_Release
+*/
+static ULONG WINAPI IDataObject_Release(LPDATAOBJECT this)
+{	TRACE(shell,"(%p)->()\n",this);
+	if (!--(this->ref)) 
+	{ TRACE(shell," destroying IDataObject(%p)\n",this);
+	  HeapFree(GetProcessHeap(),0,this);
+	  return 0;
+	}
+	return this->ref;
+}
+static HRESULT WINAPI IDataObject_GetData (LPDATAOBJECT this, LPFORMATETC32 pformatetcIn, STGMEDIUM32 *pmedium)
+{	FIXME (shell, "(%p)->()\n", this);
+	return E_NOTIMPL;
+}
+static HRESULT WINAPI IDataObject_GetDataHere(LPDATAOBJECT this, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium)
+{	FIXME (shell, "(%p)->()\n", this);
+	return E_NOTIMPL;
+}
+static HRESULT WINAPI IDataObject_QueryGetData(LPDATAOBJECT this, LPFORMATETC32 pformatetc)
+{	FIXME (shell, "(%p)->()\n", this);
+	return E_NOTIMPL;
+}
+static HRESULT WINAPI IDataObject_GetCanonicalFormatEtc(LPDATAOBJECT this, LPFORMATETC32 pformatectIn, LPFORMATETC32 pformatetcOut)
+{	FIXME (shell, "(%p)->()\n", this);
+	return E_NOTIMPL;
+}
+static HRESULT WINAPI IDataObject_SetData(LPDATAOBJECT this, LPFORMATETC32 pformatetc, STGMEDIUM32 *pmedium, BOOL32 fRelease)
+{	FIXME (shell, "(%p)->()\n", this);
+	return E_NOTIMPL;
+}
+static HRESULT WINAPI IDataObject_EnumFormatEtc(LPDATAOBJECT this, DWORD dwDirection, IEnumFORMATETC **ppenumFormatEtc)
+{	FIXME (shell, "(%p)->()\n", this);
+	return E_NOTIMPL;
+}
+static HRESULT WINAPI IDataObject_DAdvise (LPDATAOBJECT this, LPFORMATETC32 *pformatetc, DWORD advf, IAdviseSink *pAdvSink, DWORD *pdwConnection)
+{	FIXME (shell, "(%p)->()\n", this);
+	return E_NOTIMPL;
+}
+static HRESULT WINAPI IDataObject_DUnadvise(LPDATAOBJECT this, DWORD dwConnection)
+{	FIXME (shell, "(%p)->()\n", this);
+	return E_NOTIMPL;
+}
+static HRESULT WINAPI IDataObject_EnumDAdvise(LPDATAOBJECT this, IEnumSTATDATA **ppenumAdvise)
+{	FIXME (shell, "(%p)->()\n", this);
+	return E_NOTIMPL;
+}
diff --git a/dlls/shell32/enumidlist.c b/dlls/shell32/enumidlist.c
index 960d6ac..365be32 100644
--- a/dlls/shell32/enumidlist.c
+++ b/dlls/shell32/enumidlist.c
@@ -53,24 +53,26 @@
  *  IEnumIDList_Constructor
  */
 
-LPENUMIDLIST IEnumIDList_Constructor( LPCSTR lpszPath, DWORD dwFlags, HRESULT* pResult)
+LPENUMIDLIST IEnumIDList_Constructor( LPCSTR lpszPath, DWORD dwFlags)
 {	LPENUMIDLIST	lpeidl;
 
 	lpeidl = (LPENUMIDLIST)HeapAlloc(GetProcessHeap(),0,sizeof(IEnumIDList));
+	if (! lpeidl)
+	  return NULL;
+
 	lpeidl->ref = 1;
 	lpeidl->lpvtbl = &eidlvt;
 	lpeidl->mpFirst=NULL;
 	lpeidl->mpLast=NULL;
 	lpeidl->mpCurrent=NULL;
 
-	TRACE(shell,"(%p)->(%s 0x%08lx %p)\n",lpeidl,debugstr_a(lpszPath),dwFlags,pResult);
+	TRACE(shell,"(%p)->(%s flags=0x%08lx)\n",lpeidl,debugstr_a(lpszPath),dwFlags);
 
 	if(!IEnumIDList_CreateEnumList(lpeidl, lpszPath, dwFlags))
-	{ if(pResult)
-	  { *pResult = E_OUTOFMEMORY;
-	    HeapFree(GetProcessHeap(),0,lpeidl);
-	    return NULL;
+	{ if (lpeidl)
+	  { HeapFree(GetProcessHeap(),0,lpeidl);
 	  }
+	  return NULL;	  
 	}
 
 	TRACE(shell,"-- (%p)->()\n",lpeidl);
@@ -214,7 +216,7 @@
 	CHAR  szDriveName[4];
 	CHAR  szPath[MAX_PATH];
     
-	TRACE(shell,"(%p)->(%s 0x%08lx) \n",this,debugstr_a(lpszPath),dwFlags);
+	TRACE(shell,"(%p)->(path=%s flags=0x%08lx) \n",this,debugstr_a(lpszPath),dwFlags);
 
 	if (lpszPath && lpszPath[0]!='\0')
 	{ strcpy(szPath, lpszPath);
diff --git a/dlls/shell32/folders.c b/dlls/shell32/folders.c
index 75374f9..4373a3a 100644
--- a/dlls/shell32/folders.c
+++ b/dlls/shell32/folders.c
@@ -22,6 +22,7 @@
 #include "winnls.h"
 #include "winproc.h"
 #include "commctrl.h"
+#include "pidl.h"
 
 #include "shell32_main.h"
 
@@ -42,6 +43,24 @@
 static HRESULT WINAPI IShellLink_QueryInterface(LPSHELLLINK,REFIID,LPVOID*);
 static ULONG WINAPI IShellLink_AddRef(LPSHELLLINK);
 static ULONG WINAPI IShellLink_Release(LPSHELLLINK);
+static HRESULT WINAPI IShellLink_GetPath(LPSHELLLINK, LPSTR,INT32, WIN32_FIND_DATA32A *, DWORD);
+static HRESULT WINAPI IShellLink_GetIDList(LPSHELLLINK, LPITEMIDLIST *);
+static HRESULT WINAPI IShellLink_SetIDList(LPSHELLLINK, LPCITEMIDLIST);
+static HRESULT WINAPI IShellLink_GetDescription(LPSHELLLINK, LPSTR,INT32);
+static HRESULT WINAPI IShellLink_SetDescription(LPSHELLLINK, LPCSTR);
+static HRESULT WINAPI IShellLink_GetWorkingDirectory(LPSHELLLINK, LPSTR,INT32);
+static HRESULT WINAPI IShellLink_SetWorkingDirectory(LPSHELLLINK, LPCSTR);
+static HRESULT WINAPI IShellLink_GetArguments(LPSHELLLINK, LPSTR,INT32);
+static HRESULT WINAPI IShellLink_SetArguments(LPSHELLLINK, LPCSTR);
+static HRESULT WINAPI IShellLink_GetHotkey(LPSHELLLINK, WORD *);
+static HRESULT WINAPI IShellLink_SetHotkey(LPSHELLLINK, WORD);
+static HRESULT WINAPI IShellLink_GetShowCmd(LPSHELLLINK, INT32 *);
+static HRESULT WINAPI IShellLink_SetShowCmd(LPSHELLLINK, INT32);
+static HRESULT WINAPI IShellLink_GetIconLocation(LPSHELLLINK, LPSTR,INT32,INT32 *);
+static HRESULT WINAPI IShellLink_SetIconLocation(LPSHELLLINK, LPCSTR,INT32);
+static HRESULT WINAPI IShellLink_SetRelativePath(LPSHELLLINK, LPCSTR, DWORD);
+static HRESULT WINAPI IShellLink_Resolve(LPSHELLLINK, HWND32, DWORD);
+static HRESULT WINAPI IShellLink_SetPath(LPSHELLLINK, LPCSTR);
 
 
 /***********************************************************************
@@ -144,28 +163,28 @@
 * IShellLink Implementation
 */
 
-static struct IShellLink_VTable slvt = {
-  IShellLink_QueryInterface,
-  IShellLink_AddRef,
-  IShellLink_Release,
-    (void *)0xcafe0004,
-    (void *)0xcafe0005,
-    (void *)0xcafe0006,
-    (void *)0xcafe0007,
-    (void *)0xcafe0008,
-    (void *)0xcafe0009,
-    (void *)0xcafe0010,
-    (void *)0xcafe0011,
-    (void *)0xcafe0012,
-    (void *)0xcafe0013,
-    (void *)0xcafe0014,
-    (void *)0xcafe0015,
-    (void *)0xcafe0016,
-    (void *)0xcafe0017,
-    (void *)0xcafe0018,
-    (void *)0xcafe0019,
-    (void *)0xcafe0020,
-    (void *)0xcafe0021
+static struct IShellLink_VTable slvt = 
+{	IShellLink_QueryInterface,
+	IShellLink_AddRef,
+	IShellLink_Release,
+	IShellLink_GetPath,
+	IShellLink_GetIDList,
+	IShellLink_SetIDList,
+	IShellLink_GetDescription,
+	IShellLink_SetDescription,
+	IShellLink_GetWorkingDirectory,
+	IShellLink_SetWorkingDirectory,
+	IShellLink_GetArguments,
+	IShellLink_SetArguments,
+	IShellLink_GetHotkey,
+	IShellLink_SetHotkey,
+	IShellLink_GetShowCmd,
+	IShellLink_SetShowCmd,
+	IShellLink_GetIconLocation,
+	IShellLink_SetIconLocation,
+	IShellLink_SetRelativePath,
+	IShellLink_Resolve,
+	IShellLink_SetPath
 };
 
 /**************************************************************************
@@ -227,4 +246,85 @@
   return this->ref;
 }
 
+static HRESULT WINAPI IShellLink_GetPath(LPSHELLLINK this, LPSTR pszFile,INT32 cchMaxPath, WIN32_FIND_DATA32A *pfd, DWORD fFlags)
+{	FIXME(shell,"(%p)->(pfile=%p len=%u find_data=%p flags=%lu)\n",this, pszFile, cchMaxPath, pfd, fFlags);
+	strncpy(pszFile,"c:\\foo.bar", cchMaxPath);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_GetIDList(LPSHELLLINK this, LPITEMIDLIST * ppidl)
+{	FIXME(shell,"(%p)->(ppidl=%p)\n",this, ppidl);
+	*ppidl = _ILCreateDesktop();
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_SetIDList(LPSHELLLINK this, LPCITEMIDLIST pidl)
+{	FIXME(shell,"(%p)->(pidl=%p)\n",this, pidl);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_GetDescription(LPSHELLLINK this, LPSTR pszName,INT32 cchMaxName)
+{	FIXME(shell,"(%p)->(%p len=%u)\n",this, pszName, cchMaxName);
+	strncpy(pszName,"Description, FIXME",cchMaxName);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_SetDescription(LPSHELLLINK this, LPCSTR pszName)
+{	FIXME(shell,"(%p)->(desc=%s)\n",this, pszName);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_GetWorkingDirectory(LPSHELLLINK this, LPSTR pszDir,INT32 cchMaxPath)
+{	FIXME(shell,"(%p)->()\n",this);
+	strncpy(pszDir,"c:\\", cchMaxPath);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_SetWorkingDirectory(LPSHELLLINK this, LPCSTR pszDir)
+{	FIXME(shell,"(%p)->(dir=%s)\n",this, pszDir);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_GetArguments(LPSHELLLINK this, LPSTR pszArgs,INT32 cchMaxPath)
+{	FIXME(shell,"(%p)->(%p len=%u)\n",this, pszArgs, cchMaxPath);
+	strncpy(pszArgs, "", cchMaxPath);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_SetArguments(LPSHELLLINK this, LPCSTR pszArgs)
+{	FIXME(shell,"(%p)->(args=%s)\n",this, pszArgs);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_GetHotkey(LPSHELLLINK this, WORD *pwHotkey)
+{	FIXME(shell,"(%p)->(%p)\n",this, pwHotkey);
+	*pwHotkey=0x0;
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_SetHotkey(LPSHELLLINK this, WORD wHotkey)
+{	FIXME(shell,"(%p)->(hotkey=%x)\n",this, wHotkey);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_GetShowCmd(LPSHELLLINK this, INT32 *piShowCmd)
+{	FIXME(shell,"(%p)->(%p)\n",this, piShowCmd);
+	*piShowCmd=0;
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_SetShowCmd(LPSHELLLINK this, INT32 iShowCmd)
+{	FIXME(shell,"(%p)->(showcmd=%x)\n",this, iShowCmd);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_GetIconLocation(LPSHELLLINK this, LPSTR pszIconPath,INT32 cchIconPath,INT32 *piIcon)
+{	FIXME(shell,"(%p)->(%p len=%u iicon=%p)\n",this, pszIconPath, cchIconPath, piIcon);
+	strncpy(pszIconPath,"shell32.dll",cchIconPath);
+	*piIcon=1;
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_SetIconLocation(LPSHELLLINK this, LPCSTR pszIconPath,INT32 iIcon)
+{	FIXME(shell,"(%p)->(path=%s iicon=%u)\n",this, pszIconPath, iIcon);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_SetRelativePath(LPSHELLLINK this, LPCSTR pszPathRel, DWORD dwReserved)
+{	FIXME(shell,"(%p)->(path=%s %lx)\n",this, pszPathRel, dwReserved);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_Resolve(LPSHELLLINK this, HWND32 hwnd, DWORD fFlags)
+{	FIXME(shell,"(%p)->(hwnd=%x flags=%lx)\n",this, hwnd, fFlags);
+	return NOERROR;
+}
+static HRESULT WINAPI IShellLink_SetPath(LPSHELLLINK this, LPCSTR pszFile)
+{	FIXME(shell,"(%p)->(path=%s)\n",this, pszFile);
+	return NOERROR;
+}
 
diff --git a/dlls/shell32/pidl.c b/dlls/shell32/pidl.c
index caed624..67ccd94 100644
--- a/dlls/shell32/pidl.c
+++ b/dlls/shell32/pidl.c
@@ -3,8 +3,9 @@
  *
  *	Copyright 1998	Juergen Schmied
  *
- *  !!! currently work in progress on all classes !!!
- *  <contact juergen.schmied@metronet.de, 980801>
+ * NOTES
+ *  a pidl == NULL means desktop and is legal
+ *
  */
 
 #include <ctype.h>
@@ -29,15 +30,24 @@
 {	DWORD type;
 	CHAR * szData;
 	LPITEMIDLIST pidltemp = pidl;
-	TRACE(pidl,"---------- pidl=%p \n", pidl);
-	do
-	{ type   = _ILGetDataPointer(pidltemp)->type;
-	  szData = _ILGetTextPointer(type, _ILGetDataPointer(pidltemp));
+	if (! pidltemp)
+	{ TRACE(pidl,"-------- pidl = NULL (Root)\n");
+	  return;
+	}
+	TRACE(pidl,"-------- pidl=%p \n", pidl);
+	if (pidltemp->mkid.cb)
+	{ do
+	  { type   = _ILGetDataPointer(pidltemp)->type;
+	    szData = _ILGetTextPointer(type, _ILGetDataPointer(pidltemp));
 
-	  TRACE(pidl,"---- pidl=%p size=%u type=%lx %s\n",pidltemp, pidltemp->mkid.cb,type,debugstr_a(szData));
+	    TRACE(pidl,"---- pidl=%p size=%u type=%lx %s\n",pidltemp, pidltemp->mkid.cb,type,debugstr_a(szData));
 
-	  pidltemp = ILGetNext(pidltemp);
-	} while (pidltemp->mkid.cb);
+	    pidltemp = ILGetNext(pidltemp);
+	  } while (pidltemp->mkid.cb);
+	  return;
+	}
+	else
+	  TRACE(pidl,"empty pidl (Desktop)\n");	
 }
 /*************************************************************************
  * ILGetDisplayName			[SHELL32.15]
@@ -88,6 +98,8 @@
 
   TRACE(pidl,"%p\n",pidl);
 
+  pdump(pidl);
+
   if (!pidl)
     return NULL;
     
@@ -104,8 +116,40 @@
  *  duplicates the first idlist of a complex pidl
  */
 LPITEMIDLIST WINAPI ILCloneFirst(LPCITEMIDLIST pidl)
-{ FIXME(pidl,"pidl=%p\n",pidl);
-  return NULL;
+{	DWORD len;
+	LPITEMIDLIST newpidl=NULL;
+	TRACE(pidl,"pidl=%p\n",pidl);
+	
+	if (pidl)
+	{ len = pidl->mkid.cb;	
+	  newpidl = (LPITEMIDLIST) SHAlloc (len+2);
+	  if (newpidl)
+	  { memcpy(newpidl,pidl,len);
+   	    ILGetNext(newpidl)->mkid.cb = 0x00;
+	  }
+	 }
+
+  	return newpidl;
+}
+/*************************************************************************
+ * ILIsEqual [SHELL32.21]
+ *
+ */
+BOOL32 WINAPI ILIsEqual(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
+{	FIXME(pidl,"pidl1=%p pidl2=%p stub\n",pidl1, pidl2);
+	pdump (pidl1);
+	pdump (pidl2);
+	return FALSE;
+}
+/*************************************************************************
+ * ILFindChild [SHELL32.24]
+ *
+ */
+DWORD WINAPI ILFindChild(LPCITEMIDLIST pidl1,LPCITEMIDLIST pidl2)
+{	FIXME(pidl,"%p %p stub\n",pidl1,pidl2);
+	pdump (pidl1);
+	pdump (pidl2);
+	return 0;
 }
 
 /*************************************************************************
@@ -125,6 +169,9 @@
   if(!pidl1 && !pidl2)
   {  return NULL;
   }
+
+  pdump (pidl1);
+  pdump (pidl2);
  
   if(!pidl1)
   { pidlNew = ILClone(pidl2);
@@ -149,6 +196,18 @@
   return pidlNew;
 }
 /*************************************************************************
+ *  SHLogILFromFSIL [SHELL32.95]
+ *
+ * NOTES
+ *  might be the prepending of MyComputer to a filesystem pidl (?)
+ */
+LPITEMIDLIST WINAPI SHLogILFromFSIL(LPITEMIDLIST pidl)
+{	FIXME(pidl,"(pidl=%p)\n",pidl);
+	pdump(pidl);
+	return ILClone(pidl);
+}
+
+/*************************************************************************
  * ILGetSize [SHELL32.152]
  *  gets the byte size of an idlist including zero terminator (pidl)
  *
@@ -162,19 +221,19 @@
  *  exported by ordinal
  */
 DWORD WINAPI ILGetSize(LPITEMIDLIST pidl)
-{ LPSHITEMID si = &(pidl->mkid);
-  DWORD  len=0;
+{	LPSHITEMID si = &(pidl->mkid);
+	DWORD  len=0;
 
-  TRACE(pidl,"pidl=%p\n",pidl);
+	/*TRACE(pidl,"pidl=%p\n",pidl);*/
 
-  if (pidl)
-  { while (si->cb) 
-    { len += si->cb;
-      si  = (LPSHITEMID)(((LPBYTE)si)+si->cb);
-    }
-    len += 2;
+	if (pidl)
+	{ while (si->cb) 
+	  { len += si->cb;
+	    si  = (LPSHITEMID)(((LPBYTE)si)+si->cb);
+	  }
+	  len += 2;
 	}
-/*  TRACE(pidl,"-- size=%lu\n",len);*/
+	/*TRACE(pidl,"-- size=%lu\n",len);*/
 	return len;
 }
 /*************************************************************************
@@ -191,7 +250,7 @@
 LPITEMIDLIST WINAPI ILGetNext(LPITEMIDLIST pidl)
 {	LPITEMIDLIST nextpidl;
 
-	TRACE(pidl,"(pidl=%p)\n",pidl);
+/*	TRACE(pidl,"(pidl=%p)\n",pidl);*/
 	if(pidl)
 	{ nextpidl = (LPITEMIDLIST)(LPBYTE)(((LPBYTE)pidl) + pidl->mkid.cb);
 	  return nextpidl;
@@ -210,8 +269,8 @@
  *  Destroys the passed in idlist!
  */
 LPITEMIDLIST WINAPI ILAppend(LPITEMIDLIST pidl,LPCITEMIDLIST item,BOOL32 bEnd)
-{ TRACE(pidl,"(pidl=%p,pidl=%p,%08u)\n",pidl,item,bEnd);
-  return NULL;
+{	FIXME(pidl,"(pidl=%p,pidl=%p,%08u)stub\n",pidl,item,bEnd);
+	return NULL;
 }
 /*************************************************************************
  * ILFree [SHELL32.155]
@@ -222,10 +281,31 @@
  *     exported by ordinal
  */
 DWORD WINAPI ILFree(LPVOID pidl) 
-{ TRACE(pidl,"(pidl=0x%08lx)\n",(DWORD)pidl);
-  if (!pidl)
-		return 0;
-  return SHFree(pidl);
+{	TRACE(pidl,"(pidl=0x%08lx)\n",(DWORD)pidl);
+	if (!pidl)
+	  return 0;
+	return SHFree(pidl);
+}
+/*************************************************************************
+ * ILCreateFromPath [SHELL32.157]
+ *
+ */
+LPITEMIDLIST WINAPI ILCreateFromPath(LPSTR path) 
+{	LPSHELLFOLDER shellfolder;
+	LPITEMIDLIST pidlnew;
+	CHAR pszTemp[MAX_PATH*2];
+	LPWSTR lpszDisplayName = (LPWSTR)&pszTemp[0];
+	DWORD pchEaten;
+	
+	TRACE(pidl,"(path=%s)\n",path);
+	
+	LocalToWideChar32(lpszDisplayName, path, MAX_PATH);
+  
+	if (SHGetDesktopFolder(&shellfolder)==S_OK)
+	{ shellfolder->lpvtbl->fnParseDisplayName(shellfolder,0, NULL,lpszDisplayName,&pchEaten,&pidlnew,NULL);
+	  shellfolder->lpvtbl->fnRelease(shellfolder);
+	}
+	return pidlnew;
 }
 
 /**************************************************************************
@@ -303,12 +383,12 @@
  *  _ILIsDrive()
  *  _ILIsFolder()
  *  _ILIsValue()
-*/
+ */
 BOOL32 WINAPI _ILIsDesktop(LPCITEMIDLIST pidl)
 { TRACE(pidl,"(%p)\n",pidl);
 
   if (! pidl)
-    return FALSE;
+    return TRUE;
 
   return (  pidl->mkid.cb == 0x00 );
 }
@@ -695,7 +775,7 @@
 {	if(!pidl)
 	{ return NULL;
 	}
-	TRACE(pidl,"(%p)\n",  pidl);
+/*	TRACE(pidl,"(%p)\n",  pidl);*/
 	return (LPPIDLDATA)(&pidl->mkid.abID);
 }
 /**************************************************************************
@@ -703,7 +783,7 @@
  * gets a pointer to the string stored in the pidl
  */
 LPSTR WINAPI _ILGetTextPointer(PIDLTYPE type, LPPIDLDATA pidldata)
-{	TRACE(pidl,"(type=%x data=%p)\n", type, pidldata);
+{/*	TRACE(pidl,"(type=%x data=%p)\n", type, pidldata);*/
 
 	if(!pidldata)
 	{ return NULL;
diff --git a/dlls/shell32/shell32_main.c b/dlls/shell32/shell32_main.c
index ea39237..49753c5 100644
--- a/dlls/shell32/shell32_main.c
+++ b/dlls/shell32/shell32_main.c
@@ -89,9 +89,10 @@
  * http://premium.microsoft.com/msdn/library/techart/msdn193.htm
  */
 
-void WINAPI Control_RunDLL (HWND32 hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4)
-{ FIXME(shell, "(%08x, %p, \"%s\", %08lx)\n",
-	hwnd, code ? code : "(null)", cmd ? cmd : "(null)", arg4);
+void WINAPI Control_RunDLL( HWND32 hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4 )
+{
+    FIXME(shell, "(0x%08x, %p, %s, 0x%08lx): stub\n", hwnd, code,
+          debugstr_a(cmd), arg4);
 }
 
 /*************************************************************************
@@ -108,10 +109,10 @@
 BOOL32 WINAPI Shell_GetImageList(HIMAGELIST * imglist1,HIMAGELIST * imglist2)
 {	WARN(shell,"(%p,%p):semi-stub.\n",imglist1,imglist2);
 	if (imglist1)
-	{ *imglist1=ShellBigIconList;
+	{ *imglist1=ShellSmallIconList;
 	}
 	if (imglist2)
-	{ *imglist2=ShellSmallIconList;
+	{ *imglist2=ShellBigIconList;
 	}
 
 	return TRUE;
@@ -351,7 +352,7 @@
  *
  */
 LPITEMIDLIST WINAPI SHBrowseForFolder32A (LPBROWSEINFO32A lpbi)
-{ FIXME (shell, "(%lx,%s) empty stub!\n", (DWORD)lpbi, lpbi->lpszTitle);
+{ FIXME (shell, "(0x%lx,%s): stub\n", (DWORD)lpbi, debugstr_a(lpbi->lpszTitle));
   return NULL;
 }
 
diff --git a/dlls/shell32/shellole.c b/dlls/shell32/shellole.c
index bf78ba6..73db66a 100644
--- a/dlls/shell32/shellole.c
+++ b/dlls/shell32/shellole.c
@@ -239,7 +239,7 @@
 	return lpclf;
 }
 /**************************************************************************
- *  IClassFactory::QueryInterface
+ *  IClassFactory_QueryInterface
  */
 static HRESULT WINAPI IClassFactory_QueryInterface(
   LPCLASSFACTORY this, REFIID riid, LPVOID *ppvObj)
@@ -316,6 +316,9 @@
 	else if (IsEqualIID(riid, &IID_IContextMenu))
 	{ pObj = (IUnknown *)IContextMenu_Constructor(NULL, NULL, 0);
  	} 
+	else if (IsEqualIID(riid, &IID_IDataObject))
+	{ pObj = (IUnknown *)IDataObject_Constructor();
+ 	} 
 	else
 	{ ERR(shell,"unknown IID requested\n\tIID:\t%s\n",xriid);
 	  return(E_NOINTERFACE);
diff --git a/dlls/shell32/shellord.c b/dlls/shell32/shellord.c
index b8aa3f8..245bd7c 100644
--- a/dlls/shell32/shellord.c
+++ b/dlls/shell32/shellord.c
@@ -231,28 +231,26 @@
  * PathCombine [SHELL32.37]
  * 
  * NOTES
- *     concat_paths(char*target,const char*add);
- *     concats "target\\add" and writes them to target
+ *  if lpszFile='.' skip it
  */
-LPSTR WINAPI PathCombine(LPSTR target,LPSTR x1,LPSTR x2) {
-	char	buf[260];
-  TRACE(shell,"%s %s\n",x1,x2);
-	if (!x2 || !x2[0]) {
-		lstrcpy32A(target,x1);
-		return target;
+LPSTR WINAPI PathCombine(LPSTR szDest, LPCSTR lpszDir, LPCSTR lpszFile) 
+{	TRACE(shell,"%s %s\n",lpszDir,lpszFile);
+
+	if (!lpszFile || !lpszFile[0] || (lpszFile[0]=='.' && !lpszFile[1]) ) 
+	{ strcpy(szDest,lpszDir);
+	  return szDest;
 	}
-	lstrcpy32A(buf,x1);
-	PathAddBackslash(buf); /* append \ if not there */
-	lstrcat32A(buf,x2);
-	lstrcpy32A(target,buf);
-	return target;
+	strcpy(szDest,lpszDir);
+	PathAddBackslash(szDest);
+	strcat(szDest,lpszFile);
+	return szDest;
 }
 
 /*************************************************************************
  * PathIsUNC [SHELL32.39]
  * 
  * NOTES
- *     isUNC(const char*path);
+ *     PathIsUNC(char*path);
  */
 BOOL32 WINAPI PathIsUNC(LPCSTR path) {
   TRACE(shell,"%s\n",path);
@@ -260,6 +258,14 @@
 		return TRUE;
 	return FALSE;
 }
+/*************************************************************************
+ *  PathIsExe [SHELL32.43]
+ * 
+ */
+BOOL32 WINAPI PathIsExe (LPCSTR path)
+{  TRACE(shell,"path=%s\n",path);
+    return FALSE;
+}
 
 /*************************************************************************
  * PathFileExists [SHELL32.45]
@@ -274,6 +280,17 @@
     else
     	return TRUE;
 }
+/*************************************************************************
+ * PathMatchSpec [SHELL32.46]
+ * 
+ * NOTES
+ *     used from COMDLG32
+ */
+
+BOOL32 WINAPI PathMatchSpec(LPSTR x, LPSTR y) 
+{	FIXME(shell,"%s %s stub\n",x,y);
+	return TRUE;
+}
 
 /*************************************************************************
  * PathResolve [SHELL32.51]
@@ -417,7 +434,7 @@
  */
 DWORD WINAPI
 SHMapPIDLToSystemImageListIndex(LPSHELLFOLDER sh,DWORD y,DWORD z)
-{ FIXME(shell,"(folder=%p,%08lx,%08lx):stub.\n",sh,y,z);
+{ FIXME(shell,"(SF=%p,pidl=%08lx,%08lx):stub.\n",sh,y,z);
   return 0;
 }
 
@@ -872,7 +889,8 @@
  */
 BOOL32 WINAPI ShellExecuteEx32A (LPSHELLEXECUTEINFO32A sei)
 { 	CHAR szTemp[MAX_PATH];
-  	FIXME(shell,"%p stub\n",sei);
+
+  	FIXME(shell,"(%p): stub\n",sei);
 
 	if (sei->fMask & SEE_MASK_IDLIST)
 	{ SHGetPathFromIDList32A (sei->lpIDList,szTemp);
diff --git a/dlls/shell32/shlfolder.c b/dlls/shell32/shlfolder.c
index 5b03dcb..f78d3cc 100644
--- a/dlls/shell32/shlfolder.c
+++ b/dlls/shell32/shlfolder.c
@@ -4,7 +4,7 @@
  *	Copyright 1997	Marcus Meissner
  *	Copyright 1998	Juergen Schmied
  *
- *  !!! currently work in progress on all classes 980818 !!!
+ *  !!! currently work in progress on all classes 980930 !!!
  *  <contact juergen.schmied@metronet.de>
  */
 
@@ -105,8 +105,8 @@
 	sf=(LPSHELLFOLDER)HeapAlloc(GetProcessHeap(),0,sizeof(IShellFolder));
 	sf->ref=1;
 	sf->lpvtbl=&sfvt;
-	sf->mlpszFolder=NULL;
-	sf->mpSFParent=pParent;
+	sf->mlpszFolder=NULL;	/* path of the folder */
+	sf->mpSFParent=pParent;	/* parrent shellfolder */
 
 	TRACE(shell,"(%p)->(parent=%p, pidl=%p)\n",sf,pParent, pidl);
 	
@@ -114,24 +114,24 @@
 	sf->mpidl = ILClone(pidl);
 	sf->mpidlNSRoot = NULL;
 	
-	if(sf->mpidl)        /* do we have a pidl?*/
+	if(sf->mpidl)        /* do we have a pidl? */
 	{ dwSize = 0;
-	  if(sf->mpSFParent->mlpszFolder)
+	  if(sf->mpSFParent->mlpszFolder)		/* get the size of the parents path */
 	  { dwSize += strlen(sf->mpSFParent->mlpszFolder) + 1;
+	    TRACE(shell,"-- (%p)->(parent's path=%s)\n",sf, debugstr_a(sf->mpSFParent->mlpszFolder));
 	  }   
-	  dwSize += _ILGetFolderText(sf->mpidl,NULL,0);
+	  dwSize += _ILGetFolderText(sf->mpidl,NULL,0); /* add the size of the foldername*/
 	  sf->mlpszFolder = SHAlloc(dwSize);
 	  if(sf->mlpszFolder)
 	  { *(sf->mlpszFolder)=0x00;
-	    if(sf->mpSFParent->mlpszFolder)
+	    if(sf->mpSFParent->mlpszFolder)		/* if the parent has a path, get it*/
 	    {  strcpy(sf->mlpszFolder, sf->mpSFParent->mlpszFolder);
 	       PathAddBackslash (sf->mlpszFolder);
 	    }
 	    _ILGetFolderText(sf->mpidl, sf->mlpszFolder+strlen(sf->mlpszFolder), dwSize-strlen(sf->mlpszFolder));
+	    TRACE(shell,"-- (%p)->(my path=%s)\n",sf, debugstr_a(sf->mlpszFolder));
 	  }
 	}
-	
-	TRACE(shell,"-- (%p)->(%p,%p,parent=%s)\n",sf,pParent, pidl, debugstr_a(sf->mlpszFolder));
 	return sf;
 }
 /**************************************************************************
@@ -288,16 +288,15 @@
 	HWND32 hwndOwner,
 	DWORD dwFlags,
 	LPENUMIDLIST* ppEnumIDList)
-{ HRESULT  hr;
-	TRACE(shell,"(%p)->(HWND=0x%08x,0x%08lx,%p)\n",this,hwndOwner,dwFlags,ppEnumIDList);
+{	TRACE(shell,"(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",this,hwndOwner,dwFlags,ppEnumIDList);
 
-  *ppEnumIDList = NULL;
-	*ppEnumIDList = IEnumIDList_Constructor (this->mlpszFolder, dwFlags, &hr);
-  TRACE(shell,"-- (%p)->(new ID List: %p)\n",this,*ppEnumIDList);
-  if(!*ppEnumIDList)
-  { return hr;
-  }
-  return S_OK;		
+	*ppEnumIDList = NULL;
+	*ppEnumIDList = IEnumIDList_Constructor (this->mlpszFolder, dwFlags);
+	TRACE(shell,"-- (%p)->(new ID List: %p)\n",this,*ppEnumIDList);
+	if(!*ppEnumIDList)
+	{ return E_OUTOFMEMORY;
+	}
+	return S_OK;		
 }
 /**************************************************************************
  *  IShellFolder_Initialize()
@@ -496,19 +495,21 @@
   do
   { if (*pidltemp)
     { if (_ILIsDesktop( *pidltemp))
-      { *rgfInOut |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSANCESTOR);
+      { *rgfInOut |= ( SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANLINK );
       }
       else if (_ILIsMyComputer( *pidltemp))
-      { *rgfInOut |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER);
+      { *rgfInOut |= ( SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR
+      			| SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANRENAME | SFGAO_CANLINK );
       }
       else if (_ILIsDrive( *pidltemp))
-      { *rgfInOut |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER  | SFGAO_FILESYSTEM);
+      { *rgfInOut |= ( SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM  | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR  | 
+      			SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANLINK );
       }
       else if (_ILIsFolder( *pidltemp))
-      { *rgfInOut |= (SFGAO_FOLDER | SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM );
+      { *rgfInOut |= ( SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_CAPABILITYMASK );
       }
       else if (_ILIsValue( *pidltemp))
-      { *rgfInOut |= (SFGAO_FILESYSTEM);
+      { *rgfInOut |= (SFGAO_FILESYSTEM | SFGAO_CAPABILITYMASK );
       }
     }
     pidltemp++;
@@ -624,17 +625,14 @@
 		
 	TRACE(shell,"(%p)->(pidl=%p,0x%08lx,%p)\n",this,pidl,dwFlags,lpName);
 
-	if (!pidl)
-	{  return E_OUTOFMEMORY;
-	} 
-
 	szSpecial[0]=0x00; 
 	szDrive[0]=0x00;
 
 	/* test if simple(relative) or complex(absolute) pidl */
 	pidlTemp = ILGetNext(pidl);
-	if (pidlTemp->mkid.cb==0x00)
+	if (pidlTemp && pidlTemp->mkid.cb==0x00)
 	{ bSimplePidl = TRUE;
+	  TRACE(shell,"-- simple pidl\n");
 	}
 	if (_ILIsDesktop( pidl))
 	{ strcpy (szText,"Desktop");
@@ -667,12 +665,15 @@
 	  { case SHGDN_NORMAL:
 	      _ILGetPidlPath( pidl, szText, MAX_PATH);
 	      break;
+
+	    case SHGDN_INFOLDER | SHGDN_FORPARSING: /*fall thru*/
 	    case SHGDN_INFOLDER:
 	      pidlTemp = ILFindLastID(pidl);
 	      if (pidlTemp)
 	      { _ILGetItemText( pidlTemp, szText, MAX_PATH);
 	      }
 	      break;				
+
 	    case SHGDN_FORPARSING:
 	      if (bSimplePidl)
 	      { /* if the IShellFolder has parents, get the path from the
@@ -696,6 +697,7 @@
 	      }
 	      break;
 	    default:
+	      TRACE(shell,"--- wrong flags=%lx\n", dwFlags);
 	      return E_INVALIDARG;
 	  }
 	  if ((szText[0]==0x00 && szDrive[0]!=0x00)|| (bSimplePidl && szDrive[0]!=0x00))
@@ -706,7 +708,7 @@
 	  }
 	}
   
-	TRACE(shell,"-- (%p)->(%s,%s,%s)\n",this,szSpecial,szDrive,szText);
+	TRACE(shell,"-- (%p)->(%s)\n",this,szText);
 
 	if(!(lpName))
 	{  return E_OUTOFMEMORY;
diff --git a/dlls/shell32/shlview.c b/dlls/shell32/shlview.c
index 3939b38..13322f5 100644
--- a/dlls/shell32/shlview.c
+++ b/dlls/shell32/shlview.c
@@ -1,10 +1,7 @@
 /*
  *	ShellView
  *
- *	Copyright 1998	Juergen Schmied
- *
- *  !!! currently work in progress on all classes 980801 !!!
- *  <contact juergen.schmied@metronet.de>
+ *	Copyright 1998	<juergen.schmied@metronet.de>
  */
 
 #include <ctype.h>
@@ -48,6 +45,8 @@
 static HRESULT WINAPI IShellView_SelectItem(LPSHELLVIEW, LPCITEMIDLIST pidlItem, UINT32 uFlags);
 static HRESULT WINAPI IShellView_GetItemObject(LPSHELLVIEW, UINT32 uItem, REFIID riid,LPVOID *ppv);
 
+static BOOL32 ShellView_CanDoIDockingWindow(LPSHELLVIEW);
+
 static struct IShellView_VTable svvt = 
 { IShellView_QueryInterface,
   IShellView_AddRef,
@@ -71,8 +70,17 @@
 #define IDM_VIEW_FILES  (FCIDM_SHVIEWFIRST + 0x500)
 #define IDM_VIEW_IDW    (FCIDM_SHVIEWFIRST + 0x501)
 #define IDM_MYFILEITEM  (FCIDM_SHVIEWFIRST + 0x502)
+#define ID_LISTVIEW     2000
+#define MENU_OFFSET  1
+#define MENU_MAX     100
+#define TOOLBAR_ID   (L"SHELLDLL_DefView")
+//windowsx.h
+#define GET_WM_COMMAND_ID(wp, lp)               LOWORD(wp)
+#define GET_WM_COMMAND_HWND(wp, lp)             (HWND32)(lp)
+#define GET_WM_COMMAND_CMD(wp, lp)              HIWORD(wp)
+// winuser.h
+#define WM_SETTINGCHANGE                WM_WININICHANGE
 
-#define TOOLBAR_ID   (L"ShellView")
 typedef struct
 {  int   idCommand;
    int   iImage;
@@ -87,6 +95,11 @@
 { {IDM_VIEW_FILES, 0, IDS_TB_VIEW_FILES, IDS_MI_VIEW_FILES, 0, TBSTATE_ENABLED, TBSTYLE_BUTTON},
   {-1, 0, 0, 0, 0, 0, 0}   
 };
+BOOL32 g_bViewKeys;
+BOOL32 g_bShowIDW;
+
+typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
+
 /**************************************************************************
 *  IShellView_Constructor
 */
@@ -107,30 +120,70 @@
   return sv;
 }
 /**************************************************************************
+*  helperfunctions for communication with ICommDlgBrowser
+*
+*/
+static BOOL32 IsInCommDlg(LPSHELLVIEW this)
+{	return(this->pCommDlgBrowser != NULL);
+}
+static HRESULT IncludeObject(LPSHELLVIEW this, LPCITEMIDLIST pidl)
+{	if ( IsInCommDlg(this) )
+	{ TRACE(shell,"ICommDlgBrowser::IncludeObject pidl=%p\n", pidl);
+	  return (this->pCommDlgBrowser->lpvtbl->fnIncludeObject(this->pCommDlgBrowser, this, pidl));
+	}
+	return S_OK;
+}
+static HRESULT OnDefaultCommand(LPSHELLVIEW this)
+{	if (IsInCommDlg(this))
+	{ TRACE(shell,"ICommDlgBrowser::OnDefaultCommand\n");
+	  return (this->pCommDlgBrowser->lpvtbl->fnOnDefaultCommand(this->pCommDlgBrowser, this));
+	}
+	return S_FALSE;
+}
+static HRESULT OnStateChange(LPSHELLVIEW this, UINT32 uFlags)
+{	if (IsInCommDlg(this))
+	{ TRACE(shell,"ICommDlgBrowser::OnStateChange flags=%x\n", uFlags);
+	  return (this->pCommDlgBrowser->lpvtbl->fnOnStateChange(this->pCommDlgBrowser, this, uFlags));
+	}
+	return S_FALSE;
+}
+
+/**************************************************************************
 * ShellView_CreateList()
 *
-* NOTES
-*  internal
 */
-#define ID_LISTVIEW     2000
 
 BOOL32 ShellView_CreateList (LPSHELLVIEW this)
-{ DWORD dwStyle;
+{	DWORD dwStyle;
 
-  TRACE(shell,"%p\n",this);
+	TRACE(shell,"%p\n",this);
 
-  dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER |
-  		 LVS_ICON | LVS_SHAREIMAGELISTS | LVS_EDITLABELS ;
+	dwStyle = WS_TABSTOP | WS_VISIBLE | WS_CHILD | WS_BORDER | LVS_SHAREIMAGELISTS | LVS_EDITLABELS;
+	switch (this->FolderSettings.ViewMode)
+	{ case FVM_ICON:	dwStyle |= LVS_ICON;		break;
+	  case FVM_SMALLICON: 	dwStyle |= LVS_SMALLICON;	break;
+	  case FVM_LIST: 	dwStyle |= LVS_LIST;		break;
+	  case FVM_DETAILS: 	dwStyle |= LVS_REPORT;		break;
+	}
+	if (this->FolderSettings.fFlags && FWF_AUTOARRANGE)	dwStyle |= LVS_AUTOARRANGE;
+	/*if (this->FolderSettings.fFlags && FWF_DESKTOP); used from explorer*/
+	if (this->FolderSettings.fFlags && FWF_SINGLESEL)	dwStyle |= LVS_SINGLESEL;
 
-  this->hWndList=CreateWindowEx32A( WS_EX_CLIENTEDGE,WC_LISTVIEW32A,NULL,dwStyle,
-  								0,0,0,0,
-  								this->hWnd,(HMENU32)ID_LISTVIEW,shell32_hInstance,NULL);
+	this->hWndList=CreateWindowEx32A( WS_EX_CLIENTEDGE,
+					  WC_LISTVIEW32A,
+					  NULL,
+					  dwStyle,
+					  0,0,0,0,
+  					  this->hWnd,
+					  (HMENU32)ID_LISTVIEW,
+					  shell32_hInstance,
+					  NULL);
 
-  if(!this->hWndList)
-     return FALSE;
+	if(!this->hWndList)
+	  return FALSE;
 
-//  UpdateShellSettings();
-  return TRUE;
+	//  UpdateShellSettings();
+	return TRUE;
 }
 /**************************************************************************
 * ShellView_InitList()
@@ -177,7 +230,6 @@
 
   ListView_SetImageList(this->hWndList, ShellSmallIconList, LVSIL_SMALL);
   ListView_SetImageList(this->hWndList, ShellBigIconList, LVSIL_NORMAL);
-  ListView_SetBkColor(this->hWndList, 0x00800000 );
   
   return TRUE;
 }
@@ -188,13 +240,13 @@
 *  internal
 */   
 int CALLBACK ShellView_CompareItems(LPARAM lParam1, LPARAM lParam2, LPARAM lpData)
-{ LPSHELLFOLDER  pFolder = (LPSHELLFOLDER)lpData;
+{	LPSHELLFOLDER  pFolder = (LPSHELLFOLDER)lpData;
 
-  TRACE(shell,"\n");
-  if(!pFolder)
-    return 0;
+	TRACE(shell,"\n");
+	if(!pFolder)
+	  return 0;
 
- return (int)pFolder->lpvtbl->fnCompareIDs(pFolder, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2);
+	return (int)pFolder->lpvtbl->fnCompareIDs(pFolder, 0, (LPITEMIDLIST)lParam1, (LPITEMIDLIST)lParam2);
 }
 
 /**************************************************************************
@@ -223,12 +275,19 @@
       lvItem.lParam = (LPARAM)ILClone(pidl);		/*set the item's data*/
       lvItem.pszText = LPSTR_TEXTCALLBACK32A;		/*get text on a callback basis*/
       lvItem.iImage = I_IMAGECALLBACK;				/*get the image on a callback basis*/
-      ListView_InsertItem32A(this->hWndList, &lvItem);	/*add the item*/    
+      if ( S_OK == IncludeObject(this, ILClone(pidl) ))	/* fixme free the pidl*/
+      { ListView_InsertItem32A(this->hWndList, &lvItem);	/*add the item*/    
+      }
+      else
+      { SHFree(pidl); /* not viewed */
+      }
+
    }
 
    /*sort the items*/
-   ListView_SortItems(this->hWndList, ShellView_CompareItems, (LPARAM)this->pSFParent);
-     
+   /* ListView_SortItems(this->hWndList, ShellView_CompareItems, (LPARAM)this->pSFParent);*/
+
+   
    /*turn the listview's redrawing back on and force it to draw*/
    SendMessage32A(this->hWndList, WM_SETREDRAW, TRUE, 0);
    InvalidateRect32(this->hWndList, NULL, TRUE);
@@ -246,43 +305,47 @@
 */   
 LRESULT ShellView_OnCreate(LPSHELLVIEW this)
 { TRACE(shell,"%p\n",this);
+
   if(ShellView_CreateList(this))
   {  if(ShellView_InitList(this))
      { ShellView_FillList(this);
      }
   }
+
   return S_OK;
 }
 /**************************************************************************
 *  ShellView_OnSize()
 */   
 LRESULT ShellView_OnSize(LPSHELLVIEW this, WORD wWidth, WORD wHeight)
-{ TRACE(shell,"%p width=%u height=%u\n",this, wWidth,wHeight);
-  //resize the ListView to fit our window
-  if(this->hWndList)
-  { MoveWindow32(this->hWndList, 0, 0, wWidth, wHeight, TRUE);
-  }
-  return S_OK;
+{	TRACE(shell,"%p width=%u height=%u\n",this, wWidth,wHeight);
+
+	/*resize the ListView to fit our window*/
+	if(this->hWndList)
+	{ MoveWindow32(this->hWndList, 0, 0, wWidth, wHeight, TRUE);
+	}
+
+	return S_OK;
 }
 /**************************************************************************
 * ShellView_BuildFileMenu()
 */   
 HMENU32 ShellView_BuildFileMenu(LPSHELLVIEW this)
-{   CHAR			szText[MAX_PATH];
+{	CHAR			szText[MAX_PATH];
 	MENUITEMINFO32A	mii;
 	int				nTools,i;
 	HMENU32 		hSubMenu;
 
-	TRACE(shell,"(%p) stub\n",this);
+	TRACE(shell,"(%p) semi-stub\n",this);
 
-    hSubMenu = CreatePopupMenu32();
+	hSubMenu = CreatePopupMenu32();
 	if(hSubMenu)
 	{ /*get the number of items in our global array*/
 	  for(nTools = 0; g_Tools[nTools].idCommand != -1; nTools++){}
 
-	  //add the menu items
+	  /*add the menu items*/
 	  for(i = 0; i < nTools; i++)
-      { strcpy(szText, "dummy 44");
+	  { strcpy(szText, "dummy BuildFileMenu");
       
 	    ZeroMemory(&mii, sizeof(mii));
 	    mii.cbSize = sizeof(mii);
@@ -290,16 +353,16 @@
 
 	    if(TBSTYLE_SEP != g_Tools[i].bStyle)
 	    { mii.fType = MFT_STRING;
-          mii.fState = MFS_ENABLED;
-          mii.dwTypeData = szText;
-          mii.wID = g_Tools[i].idCommand;
-        }
+	      mii.fState = MFS_ENABLED;
+	      mii.dwTypeData = szText;
+	      mii.wID = g_Tools[i].idCommand;
+	    }
 	    else
-        { mii.fType = MFT_SEPARATOR;
-        }
-        /* tack this item onto the end of the menu */
-        InsertMenuItem32A(hSubMenu, (UINT32)-1, TRUE, &mii);
-      }
+	    { mii.fType = MFT_SEPARATOR;
+	    }
+	    /* tack this item onto the end of the menu */
+	    InsertMenuItem32A(hSubMenu, (UINT32)-1, TRUE, &mii);
+	  }
 	}
 	return hSubMenu;
 }
@@ -367,6 +430,24 @@
 	}
 }
 /**************************************************************************
+* ShellView_UpdateMenu()
+*/
+LRESULT ShellView_UpdateMenu(LPSHELLVIEW this, HMENU32 hMenu)
+{	TRACE(shell,"(%p)->(menu=0x%08x\n",this,hMenu);
+	CheckMenuItem32(hMenu, IDM_VIEW_FILES, MF_BYCOMMAND | (g_bViewKeys ? MF_CHECKED: MF_UNCHECKED));
+
+	if(ShellView_CanDoIDockingWindow(this))
+	{ EnableMenuItem32(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_ENABLED);
+	  CheckMenuItem32(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | (g_bShowIDW ? MF_CHECKED: MF_UNCHECKED));
+	}
+	else
+	{ EnableMenuItem32(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+	  CheckMenuItem32(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_UNCHECKED);
+	}
+	return 0;
+}
+
+/**************************************************************************
 * ShellView_OnDeactivate()
 *
 * NOTES
@@ -391,64 +472,63 @@
 */   
 LRESULT ShellView_OnActivate(LPSHELLVIEW this, UINT32 uState)
 {	OLEMENUGROUPWIDTHS32   omw = { {0, 0, 0, 0, 0, 0} };
-    MENUITEMINFO32A         mii;
-    CHAR                szText[MAX_PATH];
+	MENUITEMINFO32A         mii;
+	CHAR                szText[MAX_PATH];
 
 	TRACE(shell,"%p uState=%x\n",this,uState);    
 
 	//don't do anything if the state isn't really changing
 	if(this->uState == uState)
 	{ return S_OK;
-    }
+	}
 
 	ShellView_OnDeactivate(this);
 
 	//only do this if we are active
 	if(uState != SVUIA_DEACTIVATE)
 	{ //merge the menus
-      this->hMenu = CreateMenu32();
+	  this->hMenu = CreateMenu32();
    
 	  if(this->hMenu)
 	  { this->pShellBrowser->lpvtbl->fnInsertMenusSB(this->pShellBrowser, this->hMenu, &omw);
 
-        //build the top level menu
-        //get the menu item's text
-        strcpy(szText,"dummy 31");
+	    /*build the top level menu get the menu item's text*/
+	    strcpy(szText,"dummy 31");
       
-        ZeroMemory(&mii, sizeof(mii));
-        mii.cbSize = sizeof(mii);
-        mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
-        mii.fType = MFT_STRING;
-        mii.fState = MFS_ENABLED;
-        mii.dwTypeData = szText;
-        mii.hSubMenu = ShellView_BuildFileMenu(this);
+	    ZeroMemory(&mii, sizeof(mii));
+	    mii.cbSize = sizeof(mii);
+	    mii.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_STATE;
+	    mii.fType = MFT_STRING;
+	    mii.fState = MFS_ENABLED;
+	    mii.dwTypeData = szText;
+	    mii.hSubMenu = ShellView_BuildFileMenu(this);
 
-        //insert our menu into the menu bar
-        if(mii.hSubMenu)
-        { InsertMenuItem32A(this->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
-        }
+	    /*insert our menu into the menu bar*/
+	    if(mii.hSubMenu)
+	    { InsertMenuItem32A(this->hMenu, FCIDM_MENU_HELP, FALSE, &mii);
+	    }
 
-        //get the view menu so we can merge with it
-        ZeroMemory(&mii, sizeof(mii));
-        mii.cbSize = sizeof(mii);
-        mii.fMask = MIIM_SUBMENU;
+	    /*get the view menu so we can merge with it*/
+	    ZeroMemory(&mii, sizeof(mii));
+	    mii.cbSize = sizeof(mii);
+	    mii.fMask = MIIM_SUBMENU;
       
 	    if(GetMenuItemInfo32A(this->hMenu, FCIDM_MENU_VIEW, FALSE, &mii))
 	    { ShellView_MergeViewMenu(this, mii.hSubMenu);
-        }
+	    }
 
-        //add the items that should only be added if we have the focus
-        if(SVUIA_ACTIVATE_FOCUS == uState)
+	    /*add the items that should only be added if we have the focus*/
+	    if(SVUIA_ACTIVATE_FOCUS == uState)
 	    { //get the file menu so we can merge with it
 	      ZeroMemory(&mii, sizeof(mii));
-          mii.cbSize = sizeof(mii);
+	      mii.cbSize = sizeof(mii);
 	      mii.fMask = MIIM_SUBMENU;
       
 	      if(GetMenuItemInfo32A(this->hMenu, FCIDM_MENU_FILE, FALSE, &mii))
 	      { ShellView_MergeFileMenu(this, mii.hSubMenu);
-          }
-        }
-        this->pShellBrowser->lpvtbl->fnSetMenuSB(this->pShellBrowser, this->hMenu, 0, this->hWnd);
+	      }
+	    }
+	  this->pShellBrowser->lpvtbl->fnSetMenuSB(this->pShellBrowser, this->hMenu, 0, this->hWnd);
 	  }
 	}
 	this->uState = uState;
@@ -462,18 +542,16 @@
 *  internal
 */
 LRESULT ShellView_OnSetFocus(LPSHELLVIEW this)
-{ TRACE(shell,"%p\n",this);
-  /* Tell the browser one of our windows has received the focus. This should always 
-  be done before merging menus (OnActivate merges the menus) if one of our 
-  windows has the focus.*/
-  this->pShellBrowser->lpvtbl->fnOnViewWindowActive(this->pShellBrowser,this);
-  ShellView_OnActivate(this, SVUIA_ACTIVATE_FOCUS);
+{	TRACE(shell,"%p\n",this);
+	/* Tell the browser one of our windows has received the focus. This should always 
+	be done before merging menus (OnActivate merges the menus) if one of our 
+	windows has the focus.*/
+	this->pShellBrowser->lpvtbl->fnOnViewWindowActive(this->pShellBrowser,this);
+	ShellView_OnActivate(this, SVUIA_ACTIVATE_FOCUS);
 
-  return 0;
+	return 0;
 }
 
-BOOL32 g_bViewKeys;
-BOOL32 g_bShowIDW;
 /**************************************************************************
 * ShellView_OnKillFocus()
 */   
@@ -487,112 +565,85 @@
 * ShellView_AddRemoveDockingWindow()
 */   
 BOOL32 ShellView_AddRemoveDockingWindow(LPSHELLVIEW this, BOOL32 bAdd)
-{	TRACE(shell,"(%p)->(badd=0x%08x) stub\n",this,bAdd);
-	return FALSE;
-/*
-	BOOL32              bReturn = FALSE;
-	HRESULT32           hr;
-	IServiceProvider  *pSP;
-*/
+{	BOOL32	bReturn = FALSE;
+	HRESULT	hr;
+	LPSERVICEPROVIDER	pSP;
+	LPDOCKINGWINDOWFRAME	pFrame;
+	
+	FIXME(shell,"(%p)->(badd=0x%08x) stub\n",this,bAdd);
+
 	/* get the browser's IServiceProvider */
-/*	hr = this->pShellBrowser->QueryInterface((REFIID)IID_IServiceProvider, (LPVOID*)&pSP);
+	hr = this->pShellBrowser->lpvtbl->fnQueryInterface(this->pShellBrowser, (REFIID)&IID_IServiceProvider, (LPVOID*)&pSP);
 	if(SUCCEEDED(hr))
-	{
-	IDockingWindowFrame *pFrame;
-*/
-	/*get the IDockingWindowFrame pointer*/
-/*
-	hr = pSP->QueryService(SID_SShellBrowser, IID_IDockingWindowFrame, (LPVOID*)&pFrame);
-	if(SUCCEEDED(hr))
-	{ if(bAdd)
-	  { hr = S_OK;
-		if(!this->pDockingWindow)
-		{ //create the toolbar object
-	      this->pDockingWindow = new CDockingWindow(this, this->hWnd);
-	    }
-
-	    if(this->pDockingWindow)
-        { //add the toolbar object
-	      hr = pFrame->AddToolbar((IDockingWindow*)this->pDockingWindow, TOOLBAR_ID, 0);
-
-	      if(SUCCEEDED(hr))
-          { bReturn = TRUE;
+	{ /*get the IDockingWindowFrame pointer*/
+	  hr = pSP->lpvtbl->fnQueryService(pSP, &SID_SShellBrowser, &IID_IDockingWindowFrame, (LPVOID*)&pFrame);
+	  if(SUCCEEDED(hr))
+	  { if(bAdd)
+	    { hr = S_OK;
+	      /*if(!this->pDockingWindow)
+	      { //create the toolbar object
+	        this->pDockingWindow = DockingWindow_Constructor(this, this->hWnd);
 	      }
-	    }
-	  }
-      else
-      { if(this->pDockingWindow)
-        { hr = pFrame->RemoveToolbar((IDockingWindow*)this->pDockingWindow, DWFRF_NORMAL);
 
-	      if(SUCCEEDED(hr))
-          {*/
-            /* RemoveToolbar should release the toolbar object which will cause 
-            it to destroy itself. Our toolbar object is no longer valid at 
-            this point.*/
+	      if(this->pDockingWindow)
+	      { //add the toolbar object
+	        hr = pFrame->lpvtbl->fnAddToolbar(pFrame, (IDockingWindow*)this->pDockingWindow, TOOLBAR_ID, 0);
+
+	        if(SUCCEEDED(hr))
+	        { bReturn = TRUE;
+	        }
+	      }*/
+	    }
+	    else
+	    { /*if(this->pDockingWindow)
+	      { hr = pFrame->->lpvtbl->fnRemoveToolbar(pFrame, (IDockingWindow*)this->pDockingWindow, DWFRF_NORMAL);
+
+	        if(SUCCEEDED(hr))
+	        { // RemoveToolbar should release the toolbar object which will cause 
+	          //it to destroy itself. Our toolbar object is no longer valid at 
+	          //this point.
             
-/*          this->pDockingWindow = NULL;
-	        bReturn = TRUE;
-                             }
-	      }
+	          this->pDockingWindow = NULL;
+	          bReturn = TRUE;
+	        }
+	      }*/
 	    }
-	    pFrame->Release();
-      }
-	  pSP->Release();
+	    pFrame->lpvtbl->fnRelease(pFrame);
+	  }
+	  pSP->lpvtbl->fnRelease(pSP);
 	}
-	return bReturn;*/
+	return bReturn;
 }
 
 /**************************************************************************
 * ShellView_CanDoIDockingWindow()
 */   
 BOOL32 ShellView_CanDoIDockingWindow(LPSHELLVIEW this)
-{	TRACE(shell,"(%p) stub\n",this);
-	return FALSE;
-/*
-	BOOL32              bReturn = FALSE;
-	HRESULT32           hr;
-	IServiceProvider	*pSP;
-	IDockingWindowFrame *pFrame;
-
-	//get the browser's IServiceProvider
-	hr = this->pShellBrowser->lpvtbl->fnQueryInterface(this->pShellBrowser, (REFIID)IID_IServiceProvider, (LPVOID*)&pSP);
+{	BOOL32 bReturn = FALSE;
+	HRESULT hr;
+	LPSERVICEPROVIDER pSP;
+	LPDOCKINGWINDOWFRAME pFrame;
+	
+	FIXME(shell,"(%p) stub\n",this);
+	
+	/*get the browser's IServiceProvider*/
+	hr = this->pShellBrowser->lpvtbl->fnQueryInterface(this->pShellBrowser, (REFIID)&IID_IServiceProvider, (LPVOID*)&pSP);
 	if(hr==S_OK)
-	{ hr = pSP->lpvtbl->fnQueryService(pSP, SID_SShellBrowser, IID_IDockingWindowFrame, (LPVOID*)&pFrame);
+	{ hr = pSP->lpvtbl->fnQueryService(pSP, &SID_SShellBrowser, &IID_IDockingWindowFrame, (LPVOID*)&pFrame);
    	  if(SUCCEEDED(hr))
-      { bReturn = TRUE;
-        pFrame->lpvtbl->fnRelease(pFrame);
-      }
-	pSP->lpvtbl->fnRelease(pSP);
+	  { bReturn = TRUE;
+	    pFrame->lpvtbl->fnRelease(pFrame);
+	  }
+	  pSP->lpvtbl->fnRelease(pSP);
 	}
-	return bReturn;*/
-}
-/**************************************************************************
-* ShellView_UpdateMenu()
-*/
-LRESULT ShellView_UpdateMenu(LPSHELLVIEW this, HMENU32 hMenu)
-{	TRACE(shell,"(%p)->(menu=0x%08x\n",this,hMenu);
-	CheckMenuItem32(hMenu, IDM_VIEW_FILES, MF_BYCOMMAND | (g_bViewKeys ? MF_CHECKED: MF_UNCHECKED));
-
-	if(ShellView_CanDoIDockingWindow(this))
-	{ EnableMenuItem32(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_ENABLED);
-	  CheckMenuItem32(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | (g_bShowIDW ? MF_CHECKED: MF_UNCHECKED));
-	}
-	else
-	{ EnableMenuItem32(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
-	  CheckMenuItem32(hMenu, IDM_VIEW_IDW, MF_BYCOMMAND | MF_UNCHECKED);
-	}
-	return 0;
+	return bReturn;
 }
 
 /**************************************************************************
 *  ShellView_UpdateShellSettings()
-   
-**************************************************************************/
-typedef void (CALLBACK *PFNSHGETSETTINGSPROC)(LPSHELLFLAGSTATE lpsfs, DWORD dwMask);
-
-
+*/
 void ShellView_UpdateShellSettings(LPSHELLVIEW this)
-{	TRACE(shell,"(%p) stub\n",this);
+{	FIXME(shell,"(%p) stub\n",this);
 	return ;
 /*
 	SHELLFLAGSTATE       sfs;
@@ -641,14 +692,12 @@
 	return 0;
 }
 
-#define MENU_OFFSET  1
-#define MENU_MAX     100
-
 /**************************************************************************
 *   ShellView_DoContextMenu()
 */   
 void ShellView_DoContextMenu(LPSHELLVIEW this, WORD x, WORD y, BOOL32 fDefault)
-{	UINT32		uCommand, i, uSelected = ListView_GetSelectedCount(this->hWndList);
+{	UINT32	uCommand, i, uSelected = ListView_GetSelectedCount(this->hWndList);
+	DWORD	wFlags;
 	HMENU32 hMenu;
 	BOOL32  fExplore = FALSE;
 	HWND32  hwndTree = 0;
@@ -663,7 +712,7 @@
 	aSelectedItems = (LPITEMIDLIST*)SHAlloc(uSelected * sizeof(LPITEMIDLIST));
 
 	if(aSelectedItems)
-	{ TRACE(shell,"-- aSelectedItems\n");
+	{ TRACE(shell,"-- Items selected =%u\n", uSelected);
 	  ZeroMemory(&lvItem, sizeof(lvItem));
 	  lvItem.mask = LVIF_STATE | LVIF_PARAM;
 	  lvItem.stateMask = LVIS_SELECTED;
@@ -675,19 +724,25 @@
 	  { if(lvItem.state & LVIS_SELECTED)
 	    { aSelectedItems[i] = (LPITEMIDLIST)lvItem.lParam;
 	      i++;
+	      TRACE(shell,"-- selected Item found\n");
 	    }
 	    lvItem.iItem++;
 	  }
 
-	  this->pSFParent->lpvtbl->fnGetUIObjectOf(this->pSFParent, this->hWndParent, uSelected,
-      				(LPCITEMIDLIST*)aSelectedItems, &IID_IContextMenu, NULL,(LPVOID*)&pContextMenu);
+	  this->pSFParent->lpvtbl->fnGetUIObjectOf(	this->pSFParent,
+							this->hWndParent,
+							uSelected,
+							(LPCITEMIDLIST*)aSelectedItems,
+							&IID_IContextMenu,
+							NULL,
+							(LPVOID*)&pContextMenu);
    
 	  if(pContextMenu)
 	  { TRACE(shell,"-- pContextMenu\n");
 	    hMenu = CreatePopupMenu32();
 
-        /* See if we are in Explore or Open mode. If the browser's tree is present, 
-        then we are in Explore mode.*/
+            /* See if we are in Explore or Open mode. If the browser's tree is present, 
+            then we are in Explore mode.*/
         
 	    fExplore = FALSE;
 	    hwndTree = 0;
@@ -696,10 +751,12 @@
 	      fExplore = TRUE;
 	    }
 
-	    if(hMenu && SUCCEEDED(pContextMenu->lpvtbl->fnQueryContextMenu(pContextMenu,
-        					hMenu,0,MENU_OFFSET,MENU_MAX,CMF_NORMAL | 
-							(uSelected != 1 ? 0 : CMF_CANRENAME) |
-                            (fExplore ? CMF_EXPLORE : 0))))
+	    if(hMenu && SUCCEEDED(pContextMenu->lpvtbl->fnQueryContextMenu( pContextMenu,
+									    hMenu,
+									    0,
+									    MENU_OFFSET,
+									    MENU_MAX,
+									    CMF_NORMAL | (uSelected != 1 ? 0 : CMF_CANRENAME) | (fExplore ? CMF_EXPLORE : 0))))
 	    { if(fDefault)
 	      { TRACE(shell,"-- fDefault\n");
 	        uCommand = 0;
@@ -725,16 +782,31 @@
 	      }
          
 	      if(uCommand > 0)
-	      { TRACE(shell,"-- ! uCommand\n");
-	        ZeroMemory(&cmi, sizeof(cmi));
-	        cmi.cbSize = sizeof(cmi);
-	        cmi.hwnd = this->hWndParent;
-	        cmi.lpVerb = (LPCSTR)MAKEINTRESOURCE32A(uCommand - MENU_OFFSET);
+	      { TRACE(shell,"-- uCommand=%u\n", uCommand);
+	        if (((uCommand-MENU_OFFSET) == IDM_EXPLORE) || ((uCommand-MENU_OFFSET)  == IDM_OPEN))
+		{ if (IsInCommDlg(this))			/* are we part of a commctrl? */
+		  { TRACE(shell,"-- fnOnDefaultCommand\n");
+		    OnDefaultCommand(this);
+		  }
+		  else					/* we are acting with a full featured IShellBrowser */
+		  { TRACE(shell,"-- fnBrowseObject pidl =%p\n", aSelectedItems[0]);
+		    wFlags = SBSP_DEFBROWSER | SBSP_DEFMODE | SBSP_RELATIVE;
+		    this->pShellBrowser->lpvtbl->fnBrowseObject(	this->pShellBrowser, 
+								aSelectedItems[0], 
+								wFlags);
+		  }
+		}
+		else
+		{ ZeroMemory(&cmi, sizeof(cmi));
+	          cmi.cbSize = sizeof(cmi);
+	          cmi.hwnd = this->hWndParent;
+	          cmi.lpVerb = (LPCSTR)MAKEINTRESOURCE32A(uCommand - MENU_OFFSET);
 			pContextMenu->lpvtbl->fnInvokeCommand(pContextMenu, &cmi);
+		}
 	      }
 	      DestroyMenu32(hMenu);
 	    }
-	  pContextMenu->lpvtbl->fnRelease(pContextMenu);
+	    pContextMenu->lpvtbl->fnRelease(pContextMenu);
 	  }
 	  SHFree(aSelectedItems);
 	}
@@ -761,7 +833,7 @@
 	    break;
 
 	  default:
-	    FIXME(shell,"-- unknown command\n");
+	    FIXME(shell,"-- COMMAND unhandled\n");
 	}
 	return 0;
 }
@@ -782,44 +854,45 @@
 	TRACE(shell,"%p CtlID=%u lpnmh->code=%x\n",this,CtlID,lpnmh->code);
   
 	switch(lpnmh->code)
-	{   case NM_SETFOCUS:
-	    TRACE(shell,"NM_SETFOCUS %p\n",this);
+	{ case NM_SETFOCUS:
+	    TRACE(shell,"-- NM_SETFOCUS %p\n",this);
 	    ShellView_OnSetFocus(this);
 	    break;
 
 	  case NM_KILLFOCUS:
-	    TRACE(shell,"NM_KILLFOCUS %p\n",this);
+	    TRACE(shell,"-- NM_KILLFOCUS %p\n",this);
 	    ShellView_OnDeactivate(this);
 	    break;
 
 	  case HDN_ENDTRACK32A:
-	    TRACE(shell,"HDN_ENDTRACK32A %p\n",this);
+	    TRACE(shell,"-- HDN_ENDTRACK32A %p\n",this);
 	    /*nColumn1 = ListView_GetColumnWidth(this->hWndList, 0);
 	    nColumn2 = ListView_GetColumnWidth(this->hWndList, 1);*/
-	    return 0;
+	    break;
    
 	  case LVN_DELETEITEM:
-	    TRACE(shell,"LVN_DELETEITEM %p\n",this);
+	    TRACE(shell,"-- LVN_DELETEITEM %p\n",this);
 	    SHFree((LPITEMIDLIST)lpnmlv->lParam);     /*delete the pidl because we made a copy of it*/
 	    break;
    
-#ifdef LVN_ITEMACTIVATE
-	  case LVN_ITEMACTIVATE:
-#else
 	  case NM_DBLCLK:
 	  case NM_RETURN:
-#endif
-	    TRACE(shell,"LVN_ITEMACTIVATE | NM_RETURN %p\n",this);
+	    TRACE(shell,"-- NM_RETURN|NM_DBLCLK ignored, waiting for LVN_ITEMACTIVATE\n");
+	    break;
+
+	  case LVN_ITEMACTIVATE:
+	    TRACE(shell,"-- LVN_ITEMACTIVATE %p\n",this);
 	    ShellView_DoContextMenu(this, 0, 0, TRUE);
-	    return 0;
+	    break;
    
 	  case NM_RCLICK:
-	    TRACE(shell,"NM_RCLICK %p\n",this);
+	    TRACE(shell,"-- NM_RCLICK %p\n",this);
 	    dwCursor = GetMessagePos();
 	    ShellView_DoContextMenu(this, LOWORD(dwCursor), HIWORD(dwCursor), FALSE);
+	    break;
 
 	  case LVN_GETDISPINFO32A:
-	    TRACE(shell,"LVN_GETDISPINFO32A %p\n",this);
+	    TRACE(shell,"-- LVN_GETDISPINFO32A %p\n",this);
 	    pidl = (LPITEMIDLIST)lpdi->item.lParam;
 
 
@@ -858,27 +931,40 @@
 	      }
 	    }
 	    TRACE(shell,"-- text=%s image=%x\n",lpdi->item.pszText, lpdi->item.iImage);
-	    return 0;
+	    break;
 
 	  case NM_CLICK:
-	    TRACE(shell,"NM_CLICK %p\n",this);
+	    WARN(shell,"-- NM_CLICK %p\n",this);
 	    break;
 
 	  case LVN_ITEMCHANGING:
-	    TRACE(shell,"LVN_ITEMCHANGING %p\n",this);
+	    WARN(shell,"-- LVN_ITEMCHANGING %p\n",this);
 	    break;
 
 	  case LVN_ITEMCHANGED:
-	    TRACE(shell,"LVN_ITEMCHANGED %p\n",this);
+	    WARN(shell,"-- LVN_ITEMCHANGED %p\n",this);
+	    OnStateChange(this, CDBOSC_SELCHANGE);  
+	    break;
+
+	  case LVN_DELETEALLITEMS:
+	    WARN(shell,"-- LVN_DELETEALLITEMS %p\n",this);
+	    break;
+
+	  case LVN_INSERTITEM:
+	    WARN(shell,"-- LVN_INSERTITEM %p\n",this);
+	    break;
+
+	  case LVN_BEGINDRAG:
+	    WARN(shell,"-- LVN_BEGINDRAG %p\n",this);
 	    break;
 
 	  case NM_CUSTOMDRAW:
-	    TRACE(shell,"NM_CUSTOMDRAW %p\n",this);
+	    WARN(shell,"NM_CUSTOMDRAW %p\n",this);
 	    break;
 
 	  default:
-	    WARN (shell,"-- WM_NOTIFY unhandled\n");
-	    return 0;
+	    FIXME (shell,"-- WM_NOTIFY unhandled\n");
+	    break;;
 	}
 	return 0;
 }
@@ -886,23 +972,17 @@
 /**************************************************************************
 *  ShellView_WndProc
 */
-//windowsx.h
-#define GET_WM_COMMAND_ID(wp, lp)               LOWORD(wp)
-#define GET_WM_COMMAND_HWND(wp, lp)             (HWND32)(lp)
-#define GET_WM_COMMAND_CMD(wp, lp)              HIWORD(wp)
-// winuser.h
-#define WM_SETTINGCHANGE                WM_WININICHANGE
 
 LRESULT CALLBACK ShellView_WndProc(HWND32 hWnd, UINT32 uMessage, WPARAM32 wParam, LPARAM lParam)
 { LPSHELLVIEW pThis = (LPSHELLVIEW)GetWindowLong32A(hWnd, GWL_USERDATA);
   LPCREATESTRUCT32A lpcs;
   DWORD dwCursor;
   
-  FIXME(shell,"(hwnd=%x msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
+  TRACE(shell,"(hwnd=%x msg=%x wparm=%x lparm=%lx)\n",hWnd, uMessage, wParam, lParam);
     
   switch (uMessage)
   { case WM_NCCREATE:
-      { TRACE(shell,"WM_NCCREATE\n");
+      { TRACE(shell,"-- WM_NCCREATE\n");
         lpcs = (LPCREATESTRUCT32A)lParam;
         pThis = (LPSHELLVIEW)(lpcs->lpCreateParams);
         SetWindowLong32A(hWnd, GWL_USERDATA, (LONG)pThis);
@@ -911,87 +991,50 @@
       break;
    
    case WM_SIZE:
-      TRACE(shell,"WM_SIZE\n");
+      TRACE(shell,"-- WM_SIZE\n");
       return ShellView_OnSize(pThis,LOWORD(lParam), HIWORD(lParam));
    
    case WM_SETFOCUS:
-      TRACE(shell,"WM_SETFOCUS\n");   
+      TRACE(shell,"-- WM_SETFOCUS\n");   
       return ShellView_OnSetFocus(pThis);
  
    case WM_KILLFOCUS:
-      TRACE(shell,"WM_KILLFOCUS\n");
+      TRACE(shell,"-- WM_KILLFOCUS\n");
   	  return ShellView_OnKillFocus(pThis);
 
    case WM_CREATE:
-      TRACE(shell,"WM_CREATE\n");
+      TRACE(shell,"-- WM_CREATE\n");
       return ShellView_OnCreate(pThis);
 
    case WM_SHOWWINDOW:
-      TRACE(shell,"WM_SHOWWINDOW\n");
+      TRACE(shell,"-- WM_SHOWWINDOW\n");
       UpdateWindow32(pThis->hWndList);
       break;
 
    case WM_ACTIVATE:
-      TRACE(shell,"WM_ACTIVATE\n");
+      TRACE(shell,"-- WM_ACTIVATE\n");
       return ShellView_OnActivate(pThis, SVUIA_ACTIVATE_FOCUS);
    
    case WM_COMMAND:
-      TRACE(shell,"WM_COMMAND\n");
+      TRACE(shell,"-- WM_COMMAND\n");
       return ShellView_OnCommand(pThis, GET_WM_COMMAND_ID(wParam, lParam), 
                                   GET_WM_COMMAND_CMD(wParam, lParam), 
                                   GET_WM_COMMAND_HWND(wParam, lParam));
    
    case WM_INITMENUPOPUP:
-      TRACE(shell,"WM_INITMENUPOPUP\n");
+      TRACE(shell,"-- WM_INITMENUPOPUP\n");
       return ShellView_UpdateMenu(pThis, (HMENU32)wParam);
    
    case WM_NOTIFY:
-      TRACE(shell,"WM_NOTIFY\n");
+      TRACE(shell,"-- WM_NOTIFY\n");
       return ShellView_OnNotify(pThis,(UINT32)wParam, (LPNMHDR)lParam);
 
    case WM_SETTINGCHANGE:
-      TRACE(shell,"WM_SETTINGCHANGE\n");
+      TRACE(shell,"-- WM_SETTINGCHANGE\n");
       return ShellView_OnSettingChange(pThis,(LPCSTR)lParam);
 
-/* -------------*/
-   case WM_MOVE:
-      TRACE(shell,"WM_MOVE\n");   
-      break;
-   
-   case WM_ACTIVATEAPP:
-      TRACE(shell,"WM_ACTIVATEAPP\n");
-      break;
-
-   case WM_NOTIFYFORMAT:
-      TRACE(shell,"WM_NOTIFYFORMAT\n");
-      break;
-
-   case WM_NCPAINT:
-      TRACE(shell,"WM_NCPAINT\n");
-      break;
-
-   case WM_ERASEBKGND:
-      TRACE(shell,"WM_ERASEBKGND\n");
-      break;
-
-   case WM_PAINT:
-      TRACE(shell,"WM_PAINT\n");
-      break;
-
-   case WM_NCCALCSIZE:
-      TRACE(shell,"WM_NCCALCSIZE\n");
-      break;
-
-   case WM_WINDOWPOSCHANGING:
-      TRACE(shell,"WM_WINDOWPOSCHANGING\n");
-      break;
-
-   case WM_WINDOWPOSCHANGED:
-      TRACE(shell,"WM_WINDOWPOSCHANGED\n");
-      break;
-
    case WM_PARENTNOTIFY:
-      TRACE(shell,"WM_PARENTNOTIFY\n");
+      TRACE(shell,"-- WM_PARENTNOTIFY\n");
       if ( LOWORD(wParam) == WM_RBUTTONDOWN ) /* fixme: should not be handled here*/
       { dwCursor = GetMessagePos();
 	ShellView_DoContextMenu(pThis, LOWORD(dwCursor), HIWORD(dwCursor), FALSE);
@@ -999,19 +1042,92 @@
       }
       break;
 
+/* -------------*/
+   case WM_MOVE:
+      WARN(shell,"-- WM_MOVE\n");   
+      break;
+   
+   case WM_ACTIVATEAPP:
+      WARN(shell,"-- WM_ACTIVATEAPP\n");
+      break;
+
+   case WM_NOTIFYFORMAT:
+      WARN(shell,"-- WM_NOTIFYFORMAT\n");
+      break;
+
+   case WM_NCPAINT:
+      WARN(shell,"-- WM_NCPAINT\n");
+      break;
+
+   case WM_ERASEBKGND:
+      WARN(shell,"-- WM_ERASEBKGND\n");
+      break;
+
+   case WM_PAINT:
+      WARN(shell,"-- WM_PAINT\n");
+      break;
+
+   case WM_NCCALCSIZE:
+      WARN(shell,"-- WM_NCCALCSIZE\n");
+      break;
+
+   case WM_WINDOWPOSCHANGING:
+      WARN(shell,"-- WM_WINDOWPOSCHANGING\n");
+      break;
+
+   case WM_WINDOWPOSCHANGED:
+      WARN(shell,"-- WM_WINDOWPOSCHANGED\n");
+      break;
+
    case WM_MOUSEACTIVATE:
-      TRACE(shell,"WM_MOUSEACTIVATE\n");
+      WARN(shell,"-- WM_MOUSEACTIVATE\n");
       break;
 
    case WM_SETCURSOR:
-      TRACE(shell,"WM_SETCURSOR\n");
+      WARN(shell,"-- WM_SETCURSOR\n");
+      break;
+
+   case WM_DESTROY:
+      WARN(shell,"-- WM_DESTROY\n");
+      break;
+
+   case WM_NCDESTROY:
+      WARN(shell,"-- WM_NCDESTROY\n");
+      break;
+
+   case WM_CONTEXTMENU:
+      WARN(shell,"-- WM_CONTEXTMENU\n");
+      break;
+
+   case WM_MENUSELECT:
+      WARN(shell,"-- WM_MENUSELECT\n");
+      break;
+
+   case WM_CAPTURECHANGED:
+      WARN(shell,"-- WM_CAPTURECHANGED\n");
+      break;
+
+   case WM_CHILDACTIVATE:
+      WARN(shell,"-- WM_CHILDACTIVATE\n");
+      break;
+
+   case WM_ENTERIDLE:
+      WARN(shell,"-- WM_ENTERIDLE\n");
+      break;
+
+   default:
+      FIXME(shell,"-- MESSAGE unhandled\n");
       break;
   }
   return DefWindowProc32A (hWnd, uMessage, wParam, lParam);
 }
-
-
 /**************************************************************************
+*
+*
+*  The INTERFACE of the IShellView object
+*
+*
+***************************************************************************
 *  IShellView::QueryInterface
 */
 static HRESULT WINAPI IShellView_QueryInterface(LPSHELLVIEW this,REFIID riid, LPVOID *ppvObj)
@@ -1049,7 +1165,7 @@
 static ULONG WINAPI IShellView_Release(LPSHELLVIEW this)
 { TRACE(shell,"(%p)->()\n",this);
   if (!--(this->ref)) 
-  { TRACE(shell," destroying IEnumIDList(%p)\n",this);
+  { TRACE(shell," destroying IShellView(%p)\n",this);
 
     if(this->pSFParent)
        this->pSFParent->lpvtbl->fnRelease(this->pSFParent);
@@ -1063,10 +1179,10 @@
 *  ShellView_GetWindow
 */
 static HRESULT WINAPI IShellView_GetWindow(LPSHELLVIEW this,HWND32 * phWnd)
-{ TRACE(shell,"(%p) stub\n",this);
- *phWnd = this->hWnd;
+{	TRACE(shell,"(%p) stub\n",this);
+	*phWnd = this->hWnd;
 
- return S_OK;
+	return S_OK;
 }
 static HRESULT WINAPI IShellView_ContextSensitiveHelp(LPSHELLVIEW this,BOOL32 fEnterMode)
 { FIXME(shell,"(%p) stub\n",this);
@@ -1095,94 +1211,114 @@
 	LRESULT	lResult;
 	int		nPartArray[1] = {-1};
 
-	FIXME(shell,"(%p) stub\n",this);
-	//don't do anything if the state isn't really changing
+	FIXME(shell,"(%p)->(state=%x) stub\n",this, uState);
+	/*don't do anything if the state isn't really changing*/
 	if(this->uState == uState)
 	{ return S_OK;
-    }
+	}
 
-	//OnActivate handles the menu merging and internal state
+	/*OnActivate handles the menu merging and internal state*/
 	ShellView_OnActivate(this, uState);
 
-	//remove the docking window
+	/*remove the docking window*/
 	if(g_bShowIDW)
 	{ ShellView_AddRemoveDockingWindow(this, FALSE);
-    }
+	}
 
-	//only do this if we are active
+	/*only do this if we are active*/
 	if(uState != SVUIA_DEACTIVATE)
 	{ //update the status bar
 	   strcpy(szName, "dummy32");
    
-	  this->pSFParent->lpvtbl->fnGetFolderPath(this->pSFParent, szName + strlen(szName), sizeof(szName) - strlen(szName));
+	  this->pSFParent->lpvtbl->fnGetFolderPath( this->pSFParent,
+	  					    szName + strlen(szName),
+						    sizeof(szName) - strlen(szName));
 
 	  /* set the number of parts */
-	  this->pShellBrowser->lpvtbl->fnSendControlMsg(this->pShellBrowser,FCW_STATUS,
-      				 SB_SETPARTS, 1, (LPARAM)nPartArray, &lResult);
+	  this->pShellBrowser->lpvtbl->fnSendControlMsg(this->pShellBrowser,
+	  						FCW_STATUS,
+							SB_SETPARTS,
+							1,
+							(LPARAM)nPartArray,
+							&lResult);
 
 	  /* set the text for the parts */
-	  this->pShellBrowser->lpvtbl->fnSendControlMsg(this->pShellBrowser,FCW_STATUS,
-      				 SB_SETTEXT32A, 0, (LPARAM)szName, &lResult);
+	  this->pShellBrowser->lpvtbl->fnSendControlMsg(this->pShellBrowser,
+							FCW_STATUS,
+							SB_SETTEXT32A,
+							0,
+							(LPARAM)szName,
+							&lResult);
 
 	  //add the docking window if necessary
 	  if(g_bShowIDW)
 	  { ShellView_AddRemoveDockingWindow(this, TRUE);
-      }
+	  }
 	}
 	return S_OK;
 }
 static HRESULT WINAPI IShellView_Refresh(LPSHELLVIEW this)
-{	TRACE(shell,"(%p) stub\n",this);
+{	TRACE(shell,"(%p)\n",this);
+
 	ListView_DeleteAllItems(this->hWndList);
 	ShellView_FillList(this);
+
 	return S_OK;
 }
 static HRESULT WINAPI IShellView_CreateViewWindow(LPSHELLVIEW this, IShellView *lpPrevView,
                      LPCFOLDERSETTINGS lpfs, IShellBrowser * psb,RECT32 * prcView, HWND32  *phWnd)
-{  WNDCLASS32A wc;
-   *phWnd = 0;
+{	WNDCLASS32A wc;
+	*phWnd = 0;
 
-   TRACE(shell,"(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",this, lpPrevView,lpfs, psb, prcView, phWnd);
-   TRACE(shell,"-- left=%i top=%i right=%i bottom=%i\n",prcView->left,prcView->top, prcView->right, prcView->bottom);
+	TRACE(shell,"(%p)->(shlview=%p set=%p shlbrs=%p rec=%p hwnd=%p) incomplete\n",this, lpPrevView,lpfs, psb, prcView, phWnd);
+	TRACE(shell,"-- vmode=%x flags=%x left=%i top=%i right=%i bottom=%i\n",lpfs->ViewMode, lpfs->fFlags ,prcView->left,prcView->top, prcView->right, prcView->bottom);
+
+	/*set up the member variables*/
+	this->pShellBrowser = psb;
+	this->FolderSettings = *lpfs;
+
+	/*get our parent window*/
+	this->pShellBrowser->lpvtbl->fnAddRef(this->pShellBrowser);
+	this->pShellBrowser->lpvtbl->fnGetWindow(this->pShellBrowser, &(this->hWndParent));
+
+	/* try to get the ICommDlgBrowserInterface */
+	this->pCommDlgBrowser=NULL;
+	if ( SUCCEEDED (this->pShellBrowser->lpvtbl->fnQueryInterface( this->pShellBrowser,
+								        &IID_ICommDlgBrowser,
+									(LPVOID*) &this->pCommDlgBrowser)))
+	{ TRACE(shell,"-- CommDlgBrowser\n");
+	}
+	   
+	/*if our window class has not been registered, then do so*/
+	if(!GetClassInfo32A(shell32_hInstance, SV_CLASS_NAME, &wc))
+	{ ZeroMemory(&wc, sizeof(wc));
+	  wc.style          = CS_HREDRAW | CS_VREDRAW;
+	  wc.lpfnWndProc    = (WNDPROC32) ShellView_WndProc;
+	  wc.cbClsExtra     = 0;
+	  wc.cbWndExtra     = 0;
+	  wc.hInstance      = shell32_hInstance;
+	  wc.hIcon          = 0;
+	  wc.hCursor        = LoadCursor32A (0, IDC_ARROW32A);
+	  wc.hbrBackground  = (HBRUSH32) (COLOR_WINDOW + 1);
+	  wc.lpszMenuName   = NULL;
+	  wc.lpszClassName  = SV_CLASS_NAME;
    
-//if our window class has not been registered, then do so
-  if(!GetClassInfo32A(shell32_hInstance, SV_CLASS_NAME, &wc))
-  { ZeroMemory(&wc, sizeof(wc));
-    wc.style          = CS_HREDRAW | CS_VREDRAW;
-    wc.lpfnWndProc    = (WNDPROC32) ShellView_WndProc;
-    wc.cbClsExtra     = 0;
-    wc.cbWndExtra     = 0;
-    wc.hInstance      = shell32_hInstance;
-    wc.hIcon          = 0;
-    wc.hCursor        = LoadCursor32A (0, IDC_ARROW32A);
-    wc.hbrBackground  = (HBRUSH32) (COLOR_WINDOW + 1);
-    wc.lpszMenuName   = NULL;
-    wc.lpszClassName  = SV_CLASS_NAME;
-   
-    if(!RegisterClass32A(&wc))
-      return E_FAIL;
-   }
-   //set up the member variables
-   this->pShellBrowser = psb;
-   this->FolderSettings = *lpfs;
+	  if(!RegisterClass32A(&wc))
+	    return E_FAIL;
+	}
 
-   //get our parent window
-   this->pShellBrowser->lpvtbl->fnGetWindow(this->pShellBrowser, &(this->hWndParent));
-
-   *phWnd = CreateWindowEx32A(0, SV_CLASS_NAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
+	*phWnd = CreateWindowEx32A(0, SV_CLASS_NAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
                            prcView->left, prcView->top, prcView->right - prcView->left, prcView->bottom - prcView->top,
                            this->hWndParent, 0, shell32_hInstance, (LPVOID)this);
                            
-   if(!*phWnd)
-     return E_FAIL;
+	if(!*phWnd)
+	  return E_FAIL;
 
-   this->pShellBrowser->lpvtbl->fnAddRef(this->pShellBrowser);
-
-   return S_OK;
+	return S_OK;
 }
 
 static HRESULT WINAPI IShellView_DestroyViewWindow(LPSHELLVIEW this)
-{	TRACE(shell,"(%p) stub\n",this);
+{	TRACE(shell,"(%p)\n",this);
 
 	/*Make absolutely sure all our UI is cleaned up.*/
 	IShellView_UIActivate(this, SVUIA_DEACTIVATE);
@@ -1194,10 +1330,15 @@
 	return S_OK;
 }
 static HRESULT WINAPI IShellView_GetCurrentInfo(LPSHELLVIEW this, LPFOLDERSETTINGS lpfs)
-{ FIXME(shell,"(%p)->(%p)stub\n",this, lpfs);
-
-  *lpfs = this->FolderSettings;
-  return S_OK;
+{	TRACE(shell,"(%p)->(%p) vmode=%x flags=%x\n",this, lpfs, 
+		this->FolderSettings.ViewMode, this->FolderSettings.fFlags);
+  
+	if (lpfs)
+	{ *lpfs = this->FolderSettings;
+	  return NOERROR;
+	}
+	else
+	  return E_INVALIDARG;
 }
 static HRESULT WINAPI IShellView_AddPropertySheetPages(LPSHELLVIEW this, DWORD dwReserved,LPFNADDPROPSHEETPAGE lpfn, LPARAM lparam)
 { FIXME(shell,"(%p) stub\n",this);
@@ -1211,11 +1352,11 @@
 { FIXME(shell,"(%p)->(pidl=%p, 0x%08x) stub\n",this, pidlItem, uFlags);
   return E_NOTIMPL;
 }
-static HRESULT WINAPI IShellView_GetItemObject(LPSHELLVIEW this, UINT32 uItem, REFIID riid,LPVOID *ppvOut)
+static HRESULT WINAPI IShellView_GetItemObject(LPSHELLVIEW this, UINT32 uItem, REFIID riid, LPVOID *ppvOut)
 { char    xriid[50];
   WINE_StringFromCLSID((LPCLSID)riid,xriid);
 
-  FIXME(shell,"(%p)->(0x%08x,\n\t%s, %p)stub\n",this, uItem, xriid, ppvOut);
+  FIXME(shell,"(%p)->(uItem=0x%08x,\n\tIID=%s, ppv=%p)stub\n",this, uItem, xriid, ppvOut);
 
   *ppvOut = NULL;
   return E_NOTIMPL;
diff --git a/dlls/winaspi/Makefile.in b/dlls/winaspi/Makefile.in
new file mode 100644
index 0000000..eb83e44
--- /dev/null
+++ b/dlls/winaspi/Makefile.in
@@ -0,0 +1,15 @@
+DEFS      = @DLLFLAGS@ -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = winaspi
+
+C_SRCS = \
+	winaspi16.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
diff --git a/dlls/winaspi/winaspi16.c b/dlls/winaspi/winaspi16.c
new file mode 100644
index 0000000..4a6c3fd
--- /dev/null
+++ b/dlls/winaspi/winaspi16.c
@@ -0,0 +1,492 @@
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ldt.h>
+#include <memory.h>
+#include <unistd.h>
+#include <callback.h>
+#include "windows.h"
+#include "aspi.h"
+#include "winaspi.h"
+#include "options.h"
+#include "heap.h"
+#include "debug.h"
+#include "selectors.h"
+#include "module.h"
+#include "miscemu.h"
+
+
+/* FIXME!
+ * 1) Residual byte length reporting not handled
+ * 2) Make this code re-entrant for multithreading
+ * 3) Only linux supported so far
+ */
+
+#ifdef linux
+static int
+ASPI_OpenDevice16(SRB_ExecSCSICmd16 *prb)
+{
+    int	fd;
+    char	idstr[20];
+    char	device_str[50];
+    ASPI_DEVICE_INFO *curr;
+
+    /* search list of devices to see if we've opened it already.
+     * There is not an explicit open/close in ASPI land, so hopefully
+     * keeping a device open won't be a problem.
+     */
+
+    for (curr = ASPI_open_devices; curr; curr = curr->next) {
+	if (curr->hostId == prb->SRB_HaId &&
+	    curr->target == prb->SRB_Target &&
+	    curr->lun == prb->SRB_Lun) {
+	    return curr->fd;
+	}
+    }
+
+    /* device wasn't cached, go ahead and open it */
+    sprintf(idstr, "scsi c%1dt%1dd%1d", prb->SRB_HaId, prb->SRB_Target, prb->SRB_Lun);
+
+    if (!PROFILE_GetWineIniString(idstr, "Device", "", device_str, sizeof(device_str))) {
+	TRACE(aspi, "Trying to open unlisted scsi device %s\n", idstr);
+	return -1;
+    }
+
+    TRACE(aspi, "Opening device %s=%s\n", idstr, device_str);
+
+    fd = open(device_str, O_RDWR);
+    if (fd == -1) {
+	int save_error = errno;
+	ERR(aspi, "Error opening device %s, errno=%d\n", device_str, save_error);
+	return -1;
+    }
+
+    /* device is now open */
+    curr = HeapAlloc( SystemHeap, 0, sizeof(ASPI_DEVICE_INFO) );
+    curr->fd = fd;
+    curr->hostId = prb->SRB_HaId;
+    curr->target = prb->SRB_Target;
+    curr->lun = prb->SRB_Lun;
+
+    /* insert new record at beginning of open device list */
+    curr->next = ASPI_open_devices;
+    ASPI_open_devices = curr;
+    return fd;
+}
+
+
+static void
+ASPI_DebugPrintCmd(SRB_ExecSCSICmd16 *prb, UINT16 mode)
+{
+  BYTE	cmd;
+  int	i;
+  BYTE *cdb;
+  BYTE *lpBuf = 0;
+  dbg_decl_str(aspi, 512);
+
+  switch (mode)
+  {
+      case ASPI_DOS:
+	/* translate real mode address */
+	if (prb->SRB_BufPointer)
+	    lpBuf = (BYTE *)DOSMEM_MapRealToLinear((UINT32)prb->SRB_BufPointer);
+	break;
+      case ASPI_WIN16:
+	lpBuf = PTR_SEG_TO_LIN(prb->SRB_BufPointer);
+	break;
+  }
+
+  switch (prb->CDBByte[0]) {
+  case CMD_INQUIRY:
+    TRACE(aspi, "{\n");
+    TRACE(aspi, "\tEVPD: %d\n", prb->CDBByte[1] & 1);
+    TRACE(aspi, "\tLUN: %d\n", (prb->CDBByte[1] & 0xc) >> 1);
+    TRACE(aspi, "\tPAGE CODE: %d\n", prb->CDBByte[2]);
+    TRACE(aspi, "\tALLOCATION LENGTH: %d\n", prb->CDBByte[4]);
+    TRACE(aspi, "\tCONTROL: %d\n", prb->CDBByte[5]);
+    TRACE(aspi, "}\n");
+    break;
+  case CMD_SCAN_SCAN:
+    TRACE(aspi, "Transfer Length: %d\n", prb->CDBByte[4]);
+    break;
+  }
+
+  TRACE(aspi, "Host Adapter: %d\n", prb->SRB_HaId);
+  TRACE(aspi, "Flags: %d\n", prb->SRB_Flags);
+  if (TARGET_TO_HOST(prb)) {
+    TRACE(aspi, "\tData transfer: Target to host. Length checked.\n");
+  }
+  else if (HOST_TO_TARGET(prb)) {
+    TRACE(aspi, "\tData transfer: Host to target. Length checked.\n");
+  }
+  else if (NO_DATA_TRANSFERED(prb)) {
+    TRACE(aspi, "\tData transfer: none\n");
+  }
+  else {
+    WARN(aspi, "\tTransfer by scsi cmd. Length not checked\n");
+  }
+
+  TRACE(aspi, "\tResidual byte length reporting %s\n", prb->SRB_Flags & 0x4 ? "enabled" : "disabled");
+  TRACE(aspi, "\tLinking %s\n", prb->SRB_Flags & 0x2 ? "enabled" : "disabled");
+  TRACE(aspi, "\tPosting %s\n", prb->SRB_Flags & 0x1 ? "enabled" : "disabled");
+  TRACE(aspi, "Target: %d\n", prb->SRB_Target);
+  TRACE(aspi, "Lun: %d\n", prb->SRB_Lun);
+  TRACE(aspi, "BufLen: %ld\n", prb->SRB_BufLen);
+  TRACE(aspi, "SenseLen: %d\n", prb->SRB_SenseLen);
+  TRACE(aspi, "BufPtr: %lx (%p)\n", prb->SRB_BufPointer, lpBuf);
+  TRACE(aspi, "LinkPointer %lx\n", prb->SRB_Rsvd1);
+  TRACE(aspi, "CDB Length: %d\n", prb->SRB_CDBLen);
+  TRACE(aspi, "POST Proc: %lx\n", (DWORD) prb->SRB_PostProc);
+  cdb = &prb->CDBByte[0];
+  cmd = prb->CDBByte[0];
+  for (i = 0; i < prb->SRB_CDBLen; i++) {
+    if (i != 0) dsprintf(aspi, ",");
+    dsprintf(aspi, "%02x", *cdb++);
+  }
+  TRACE(aspi, "CDB buffer[%s]\n", dbg_str(aspi));
+}
+
+static void
+ASPI_PrintSenseArea16(SRB_ExecSCSICmd16 *prb)
+{
+  int	i;
+  BYTE *cdb;
+  dbg_decl_str(aspi, 512);
+
+  cdb = &prb->CDBByte[0];
+  for (i = 0; i < prb->SRB_SenseLen; i++) {
+    if (i) dsprintf(aspi, ",");
+    dsprintf(aspi, "%02x", *cdb++);
+  }
+  TRACE(aspi, "SenseArea[%s]\n", dbg_str(aspi));
+}
+
+static void
+ASPI_DebugPrintResult(SRB_ExecSCSICmd16 *prb, UINT16 mode)
+{
+  BYTE *lpBuf = 0;
+
+  switch (mode)
+  {
+      case ASPI_DOS:
+	/* translate real mode address */
+	if (prb->SRB_BufPointer)
+	    lpBuf = (BYTE *)DOSMEM_MapRealToLinear((UINT32)prb->SRB_BufPointer);
+	break;
+      case ASPI_WIN16:
+	lpBuf = PTR_SEG_TO_LIN(prb->SRB_BufPointer);
+	break;
+  }
+
+  switch (prb->CDBByte[0]) {
+  case CMD_INQUIRY:
+    TRACE(aspi, "Vendor: '%s'\n", lpBuf + INQUIRY_VENDOR);
+    break;
+  case CMD_TEST_UNIT_READY:
+    ASPI_PrintSenseArea16(prb);
+    break;
+  }
+}
+
+static WORD
+ASPI_ExecScsiCmd(DWORD ptrPRB, UINT16 mode)
+{
+  SRB_ExecSCSICmd16 *lpPRB = 0;
+  struct sg_header *sg_hd, *sg_reply_hdr;
+  int	status;
+  BYTE *lpBuf = 0;
+  int	in_len, out_len;
+  int	error_code = 0;
+  int	fd;
+
+  switch (mode)
+  {
+      case ASPI_DOS:
+	if (ptrPRB)
+	    lpPRB = (SRB_ExecSCSICmd16 *)DOSMEM_MapRealToLinear(ptrPRB);
+	break;
+      case ASPI_WIN16:
+	lpPRB = PTR_SEG_TO_LIN(ptrPRB);
+	break;
+  }
+
+  ASPI_DebugPrintCmd(lpPRB, mode);
+
+  fd = ASPI_OpenDevice16(lpPRB);
+  if (fd == -1) {
+      ERR(aspi, "Failed: could not open device. Device permissions !?\n");
+      lpPRB->SRB_Status = SS_ERR;
+      return SS_ERR;
+  }
+
+  sg_hd = NULL;
+  sg_reply_hdr = NULL;
+
+  lpPRB->SRB_Status = SS_PENDING;
+
+  switch (mode)
+  {
+      case ASPI_DOS:
+	/* translate real mode address */
+	if (ptrPRB)
+	    lpBuf = (BYTE *)DOSMEM_MapRealToLinear((UINT32)lpPRB->SRB_BufPointer);
+	break;
+      case ASPI_WIN16:
+	lpBuf = PTR_SEG_TO_LIN(lpPRB->SRB_BufPointer);
+	break;
+  }
+
+  if (!lpPRB->SRB_CDBLen) {
+      WARN(aspi, "Failed: lpPRB->SRB_CDBLen = 0.\n");
+      lpPRB->SRB_Status = SS_ERR;
+      return SS_ERR;
+  }
+
+  /* build up sg_header + scsi cmd */
+  if (HOST_TO_TARGET(lpPRB)) {
+    /* send header, command, and then data */
+    in_len = SCSI_OFF + lpPRB->SRB_CDBLen + lpPRB->SRB_BufLen;
+    sg_hd = (struct sg_header *) malloc(in_len);
+    memset(sg_hd, 0, SCSI_OFF);
+    memcpy(sg_hd + 1, &lpPRB->CDBByte[0], lpPRB->SRB_CDBLen);
+    if (lpPRB->SRB_BufLen) {
+      memcpy(((BYTE *) sg_hd) + SCSI_OFF + lpPRB->SRB_CDBLen, lpBuf, lpPRB->SRB_BufLen);
+    }
+  }
+  else {
+    /* send header and command - no data */
+    in_len = SCSI_OFF + lpPRB->SRB_CDBLen;
+    sg_hd = (struct sg_header *) malloc(in_len);
+    memset(sg_hd, 0, SCSI_OFF);
+    memcpy(sg_hd + 1, &lpPRB->CDBByte[0], lpPRB->SRB_CDBLen);
+  }
+
+  if (TARGET_TO_HOST(lpPRB)) {
+    out_len = SCSI_OFF + lpPRB->SRB_BufLen;
+    sg_reply_hdr = (struct sg_header *) malloc(out_len);
+    memset(sg_reply_hdr, 0, SCSI_OFF);
+    sg_hd->reply_len = out_len;
+  }
+  else {
+    out_len = SCSI_OFF;
+    sg_reply_hdr = (struct sg_header *) malloc(out_len);
+    memset(sg_reply_hdr, 0, SCSI_OFF);
+    sg_hd->reply_len = out_len;
+  }
+
+  status = write(fd, sg_hd, in_len);
+  if (status < 0 || status != in_len) {
+      int myerror = errno;
+
+    WARN(aspi, "Not enough bytes written to scsi device bytes=%d .. %d\n", in_len, status);
+    if (status < 0) {
+	if (myerror == ENOMEM) {
+	    MSG("ASPI: Linux generic scsi driver\n  You probably need to re-compile your kernel with a larger SG_BIG_BUFF value (sg.h)\n  Suggest 130560\n");
+	}
+	WARN(aspi, "errno: = %d\n", myerror);
+    }
+    goto error_exit;
+  }
+
+  status = read(fd, sg_reply_hdr, out_len);
+  if (status < 0 || status != out_len) {
+    WARN(aspi, "not enough bytes read from scsi device%d\n", status);
+    goto error_exit;
+  }
+
+  if (sg_reply_hdr->result != 0) {
+    error_code = sg_reply_hdr->result;
+    WARN(aspi, "reply header error (%d)\n", sg_reply_hdr->result);
+    goto error_exit;
+  }
+
+  if (TARGET_TO_HOST(lpPRB) && lpPRB->SRB_BufLen) {
+    memcpy(lpBuf, sg_reply_hdr + 1, lpPRB->SRB_BufLen);
+  }
+
+  /* copy in sense buffer to amount that is available in client */
+  if (lpPRB->SRB_SenseLen) {
+    int sense_len = lpPRB->SRB_SenseLen;
+    if (lpPRB->SRB_SenseLen > 16)
+      sense_len = 16;
+    memcpy(SENSE_BUFFER(lpPRB), &sg_reply_hdr->sense_buffer[0], sense_len);
+  }
+
+
+  lpPRB->SRB_Status = SS_COMP;
+  lpPRB->SRB_HaStat = HASTAT_OK;
+  lpPRB->SRB_TargStat = STATUS_GOOD;
+
+  /* now do posting */
+
+  if (ASPI_POSTING(lpPRB) && lpPRB->SRB_PostProc) {
+    TRACE(aspi, "Post Routine (%lx) called\n", (DWORD) lpPRB->SRB_PostProc);
+    switch (mode)
+    {
+      case ASPI_DOS:
+      {
+	SEGPTR spPRB = MapLS(lpPRB);
+
+	Callbacks->CallASPIPostProc(lpPRB->SRB_PostProc, spPRB);	
+	UnMapLS(spPRB);
+	break;
+      }
+      case ASPI_WIN16:
+        Callbacks->CallASPIPostProc(lpPRB->SRB_PostProc, ptrPRB);
+	break;
+    }
+  }
+
+  free(sg_reply_hdr);
+  free(sg_hd);
+  ASPI_DebugPrintResult(lpPRB, mode);
+  return SS_COMP;
+  
+error_exit:
+  if (error_code == EBUSY) {
+      lpPRB->SRB_Status = SS_ASPI_IS_BUSY;
+      TRACE(aspi, "Device busy\n");
+  }
+  else {
+      WARN(aspi, "Failed\n");
+      lpPRB->SRB_Status = SS_ERR;
+  }
+
+  /* I'm not sure exactly error codes work here
+   * We probably should set lpPRB->SRB_TargStat, SRB_HaStat ?
+   */
+  WARN(aspi, "error_exit\n");
+  free(sg_reply_hdr);
+  free(sg_hd);
+  return lpPRB->SRB_Status;
+}
+#endif
+
+
+/***********************************************************************
+ *             GetASPISupportInfo16   (WINASPI.1)
+ */
+
+WORD WINAPI GetASPISupportInfo16()
+{
+#ifdef linux
+    TRACE(aspi, "GETASPISupportInfo16\n");
+    /* high byte SS_COMP - low byte number of host adapters.
+     * FIXME!!! The number of host adapters is incorrect.
+     * I'm not sure how to determine this under linux etc.
+     */
+    return ((SS_COMP << 8) | 1);
+#else
+    return ((SS_COMP << 8) | 0);
+#endif
+}
+
+
+DWORD ASPI_SendASPICommand(DWORD ptrSRB, UINT16 mode)
+{
+#ifdef linux
+  LPSRB16 lpSRB = 0;
+
+  switch (mode)
+  {
+      case ASPI_DOS:
+	if (ptrSRB)
+	    lpSRB = (LPSRB16)DOSMEM_MapRealToLinear(ptrSRB);
+	break;
+      case ASPI_WIN16:
+	lpSRB = PTR_SEG_TO_LIN(ptrSRB);
+	break;
+  }
+
+  switch (lpSRB->common.SRB_Cmd) {
+  case SC_HA_INQUIRY:
+    lpSRB->inquiry.SRB_Status = SS_COMP;       /* completed successfully */
+    if (lpSRB->inquiry.SRB_55AASignature == 0x55aa) {
+	TRACE(aspi, "Extended request detected (Adaptec's ASPIxDOS).\nWe don't support it at the moment.\n");
+    }
+    lpSRB->inquiry.SRB_ExtBufferSize = 0x2000; /* bogus value */
+    lpSRB->inquiry.HA_Count = 1;               /* not always */
+    lpSRB->inquiry.HA_SCSI_ID = 7;             /* not always ID 7 */
+    strcat(lpSRB->inquiry.HA_ManagerId, "Wine ASPI16"); /* max 15 chars */
+    strcat(lpSRB->inquiry.HA_Identifier, "Wine host"); /* FIXME: return host
+adapter name */
+    memset(lpSRB->inquiry.HA_Unique, 0, 16); /* default HA_Unique content */
+    lpSRB->inquiry.HA_Unique[6] = 0x02; /* Maximum Transfer Length (128K, Byte> 4-7) */
+    FIXME(aspi, "ASPI: Partially implemented SC_HA_INQUIRY for adapter %d.\n", lpSRB->inquiry.SRB_HaId);
+    return SS_COMP;
+  case SC_GET_DEV_TYPE:
+    FIXME(aspi, "Not implemented SC_GET_DEV_TYPE\n");
+    break;
+  case SC_EXEC_SCSI_CMD:
+    return ASPI_ExecScsiCmd((DWORD)ptrSRB, mode);
+    break;
+  case SC_RESET_DEV:
+    FIXME(aspi, "Not implemented SC_RESET_DEV\n");
+    break;
+  default:
+    WARN(aspi, "Unknown command %d\n", lpSRB->common.SRB_Cmd);
+  }
+  return SS_INVALID_SRB;
+#else
+  return SS_INVALID_SRB;
+#endif
+}
+
+
+/***********************************************************************
+ *             SendASPICommand16   (WINASPI.2)
+ */
+WORD WINAPI SendASPICommand16(SEGPTR segptr_srb)
+{
+#ifdef linux
+    return ASPI_SendASPICommand(segptr_srb, ASPI_WIN16);
+#else
+    return 0; 
+#endif
+}
+
+
+/***********************************************************************
+ *             GetASPIDLLVersion16   (WINASPI.4)
+ */
+
+DWORD WINAPI GetASPIDLLVersion16()
+{
+#ifdef linux
+	return (DWORD)2;
+#else
+	return (DWORD)0;
+#endif
+}
+
+
+void WINAPI ASPI_DOS_func(DWORD srb)
+{
+       ASPI_SendASPICommand(srb, ASPI_DOS);
+}
+
+
+/* returns a real mode call address to ASPI_DOS_func() */
+void ASPI_DOS_HandleInt(CONTEXT *context)
+{
+#ifdef linux
+       FARPROC16 DOS_func;
+       DWORD dos;
+       LPBYTE dosptr;
+
+       DOS_func = MODULE_GetWndProcEntry16("ASPI_DOS_func");
+       dos = GlobalDOSAlloc(5);
+       dosptr = (BYTE *)PTR_SEG_OFF_TO_LIN(LOWORD(dos), 0);
+       *dosptr++ = 0xea; /* ljmp */
+       *(FARPROC16 *)dosptr = DOS_func;
+
+       *(DWORD *)PTR_SEG_OFF_TO_LIN(DS_reg(context), DX_reg(context))
+               = MAKELONG(0, HIWORD(dos)); /* real mode address */
+       RESET_CFLAG(context);
+       AX_reg(context) = CX_reg(context);
+#else
+       SET_CFLAG(context);
+#endif
+}
diff --git a/dlls/wnaspi32/Makefile.in b/dlls/wnaspi32/Makefile.in
new file mode 100644
index 0000000..1bf2b9b
--- /dev/null
+++ b/dlls/wnaspi32/Makefile.in
@@ -0,0 +1,15 @@
+DEFS      = @DLLFLAGS@ -D__WINE__
+TOPSRCDIR = @top_srcdir@
+TOPOBJDIR = ../..
+SRCDIR    = @srcdir@
+VPATH     = @srcdir@
+MODULE    = wnaspi32
+
+C_SRCS = \
+	winaspi32.c
+
+all: $(MODULE).o
+
+@MAKE_RULES@
+
+### Dependencies:
diff --git a/dlls/wnaspi32/winaspi32.c b/dlls/wnaspi32/winaspi32.c
new file mode 100644
index 0000000..5447f8d
--- /dev/null
+++ b/dlls/wnaspi32/winaspi32.c
@@ -0,0 +1,373 @@
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ldt.h>
+#include <memory.h>
+#include <unistd.h>
+#include <callback.h>
+#include "windows.h"
+#include "aspi.h"
+#include "wnaspi32.h"
+#include "options.h"
+#include "heap.h"
+#include "debug.h"
+#include "selectors.h"
+#include "module.h"
+#include "miscemu.h"
+
+
+/* FIXME!
+ * 1) Residual byte length reporting not handled
+ * 2) Make this code re-entrant for multithreading
+ * 3) Only linux supported so far
+ */
+
+#ifdef linux
+static int
+ASPI_OpenDevice32(SRB_ExecSCSICmd32 *prb)
+{
+    int	fd;
+    char	idstr[20];
+    char	device_str[50];
+    ASPI_DEVICE_INFO *curr;
+
+    /* search list of devices to see if we've opened it already.
+     * There is not an explicit open/close in ASPI land, so hopefully
+     * keeping a device open won't be a problem.
+     */
+
+    for (curr = ASPI_open_devices; curr; curr = curr->next) {
+	if (curr->hostId == prb->SRB_HaId &&
+	    curr->target == prb->SRB_Target &&
+	    curr->lun == prb->SRB_Lun) {
+	    return curr->fd;
+	}
+    }
+
+    /* device wasn't cached, go ahead and open it */
+    sprintf(idstr, "scsi c%1dt%1dd%1d", prb->SRB_HaId, prb->SRB_Target, prb->SRB_Lun);
+
+    if (!PROFILE_GetWineIniString(idstr, "Device", "", device_str, sizeof(device_str))) {
+	TRACE(aspi, "Trying to open unlisted scsi device %s\n", idstr);
+	return -1;
+    }
+
+    TRACE(aspi, "Opening device %s=%s\n", idstr, device_str);
+
+    fd = open(device_str, O_RDWR);
+    if (fd == -1) {
+	int save_error = errno;
+	ERR(aspi, "Error opening device %s, errno=%d\n", device_str, save_error);
+	return -1;
+    }
+
+    /* device is now open */
+    curr = HeapAlloc( SystemHeap, 0, sizeof(ASPI_DEVICE_INFO) );
+    curr->fd = fd;
+    curr->hostId = prb->SRB_HaId;
+    curr->target = prb->SRB_Target;
+    curr->lun = prb->SRB_Lun;
+
+    /* insert new record at beginning of open device list */
+    curr->next = ASPI_open_devices;
+    ASPI_open_devices = curr;
+    return fd;
+}
+
+
+static void
+ASPI_DebugPrintCmd32(SRB_ExecSCSICmd32 *prb)
+{
+  BYTE	cmd;
+  int	i;
+  BYTE *cdb;
+  dbg_decl_str(aspi, 512);
+
+  switch (prb->CDBByte[0]) {
+  case CMD_INQUIRY:
+    TRACE(aspi, "{\n");
+    TRACE(aspi, "\tEVPD: %d\n", prb->CDBByte[1] & 1);
+    TRACE(aspi, "\tLUN: %d\n", (prb->CDBByte[1] & 0xc) >> 1);
+    TRACE(aspi, "\tPAGE CODE: %d\n", prb->CDBByte[2]);
+    TRACE(aspi, "\tALLOCATION LENGTH: %d\n", prb->CDBByte[4]);
+    TRACE(aspi, "\tCONTROL: %d\n", prb->CDBByte[5]);
+    TRACE(aspi, "}\n");
+    break;
+  case CMD_SCAN_SCAN:
+    TRACE(aspi, "Transfer Length: %d\n", prb->CDBByte[4]);
+    break;
+  }
+
+  TRACE(aspi, "Host Adapter: %d\n", prb->SRB_HaId);
+  TRACE(aspi, "Flags: %d\n", prb->SRB_Flags);
+  if (TARGET_TO_HOST(prb)) {
+    TRACE(aspi, "\tData transfer: Target to host. Length checked.\n");
+  }
+  else if (HOST_TO_TARGET(prb)) {
+    TRACE(aspi, "\tData transfer: Host to target. Length checked.\n");
+  }
+  else if (NO_DATA_TRANSFERED(prb)) {
+    TRACE(aspi, "\tData transfer: none\n");
+  }
+  else {
+    WARN(aspi, "\tTransfer by scsi cmd. Length not checked.\n");
+  }
+
+  TRACE(aspi, "\tResidual byte length reporting %s\n", prb->SRB_Flags & 0x4 ? "enabled" : "disabled");
+  TRACE(aspi, "\tLinking %s\n", prb->SRB_Flags & 0x2 ? "enabled" : "disabled");
+  TRACE(aspi, "\tPosting %s\n", prb->SRB_Flags & 0x1 ? "enabled" : "disabled");
+  TRACE(aspi, "Target: %d\n", prb->SRB_Target);
+  TRACE(aspi, "Lun: %d\n", prb->SRB_Lun);
+  TRACE(aspi, "BufLen: %ld\n", prb->SRB_BufLen);
+  TRACE(aspi, "SenseLen: %d\n", prb->SRB_SenseLen);
+  TRACE(aspi, "BufPtr: %p\n", prb->SRB_BufPointer);
+  TRACE(aspi, "CDB Length: %d\n", prb->SRB_CDBLen);
+  TRACE(aspi, "POST Proc: %lx\n", (DWORD) prb->SRB_PostProc);
+  cdb = &prb->CDBByte[0];
+  cmd = prb->CDBByte[0];
+  for (i = 0; i < prb->SRB_CDBLen; i++) {
+    if (i != 0) dsprintf(aspi, ",");
+    dsprintf(aspi, "%02x", *cdb++);
+  }
+  TRACE(aspi, "CDB buffer[%s]\n", dbg_str(aspi));
+}
+
+static void
+ASPI_PrintSenseArea32(SRB_ExecSCSICmd32 *prb)
+{
+  int	i;
+  BYTE *cdb;
+  dbg_decl_str(aspi, 512);
+
+  cdb = &prb->CDBByte[0];
+  for (i = 0; i < prb->SRB_SenseLen; i++) {
+    if (i) dsprintf(aspi, ",");
+    dsprintf(aspi, "%02x", *cdb++);
+  }
+  TRACE(aspi, "SenseArea[%s]\n", dbg_str(aspi));
+}
+
+static void
+ASPI_DebugPrintResult32(SRB_ExecSCSICmd32 *prb)
+{
+
+  switch (prb->CDBByte[0]) {
+  case CMD_INQUIRY:
+    TRACE(aspi, "Vendor: '%s'\n", prb->SRB_BufPointer + INQUIRY_VENDOR);
+    break;
+  case CMD_TEST_UNIT_READY:
+    ASPI_PrintSenseArea32(prb);
+    break;
+  }
+}
+
+static WORD
+ASPI_ExecScsiCmd32(SRB_ExecSCSICmd32 *lpPRB)
+{
+  struct sg_header *sg_hd, *sg_reply_hdr;
+  int	status;
+  int	in_len, out_len;
+  int	error_code = 0;
+  int	fd;
+
+  ASPI_DebugPrintCmd32(lpPRB);
+
+  fd = ASPI_OpenDevice32(lpPRB);
+  if (fd == -1) {
+      ERR(aspi, "Failed: could not open device. Device permissions !?\n");
+      lpPRB->SRB_Status = SS_ERR;
+      return SS_ERR;
+  }
+
+  sg_hd = NULL;
+  sg_reply_hdr = NULL;
+
+  lpPRB->SRB_Status = SS_PENDING;
+
+  if (!lpPRB->SRB_CDBLen) {
+      WARN(aspi, "Failed: lpPRB->SRB_CDBLen = 0.\n");
+      lpPRB->SRB_Status = SS_ERR;
+      return SS_ERR;
+  }
+
+  /* build up sg_header + scsi cmd */
+  if (HOST_TO_TARGET(lpPRB)) {
+    /* send header, command, and then data */
+    in_len = SCSI_OFF + lpPRB->SRB_CDBLen + lpPRB->SRB_BufLen;
+    sg_hd = (struct sg_header *) malloc(in_len);
+    memset(sg_hd, 0, SCSI_OFF);
+    memcpy(sg_hd + 1, &lpPRB->CDBByte[0], lpPRB->SRB_CDBLen);
+    if (lpPRB->SRB_BufLen) {
+      memcpy(((BYTE *) sg_hd) + SCSI_OFF + lpPRB->SRB_CDBLen, lpPRB->SRB_BufPointer, lpPRB->SRB_BufLen);
+    }
+  }
+  else {
+    /* send header and command - no data */
+    in_len = SCSI_OFF + lpPRB->SRB_CDBLen;
+    sg_hd = (struct sg_header *) malloc(in_len);
+    memset(sg_hd, 0, SCSI_OFF);
+    memcpy(sg_hd + 1, &lpPRB->CDBByte[0], lpPRB->SRB_CDBLen);
+  }
+
+  if (TARGET_TO_HOST(lpPRB)) {
+    out_len = SCSI_OFF + lpPRB->SRB_BufLen;
+    sg_reply_hdr = (struct sg_header *) malloc(out_len);
+    memset(sg_reply_hdr, 0, SCSI_OFF);
+    sg_hd->reply_len = out_len;
+  }
+  else {
+    out_len = SCSI_OFF;
+    sg_reply_hdr = (struct sg_header *) malloc(out_len);
+    memset(sg_reply_hdr, 0, SCSI_OFF);
+    sg_hd->reply_len = out_len;
+  }
+
+  status = write(fd, sg_hd, in_len);
+  if (status < 0 || status != in_len) {
+      int myerror = errno;
+
+    WARN(aspi, "Not enough bytes written to scsi device bytes=%d .. %d\n", in_len, status);
+    if (status < 0) {
+	if (myerror == ENOMEM) {
+	    MSG("ASPI: Linux generic scsi driver\n  You probably need to re-compile your kernel with a larger SG_BIG_BUFF value (sg.h)\n  Suggest 130560\n");
+	}
+	WARN(aspi, "errno: = %d\n", myerror);
+    }
+    goto error_exit;
+  }
+
+  status = read(fd, sg_reply_hdr, out_len);
+  if (status < 0 || status != out_len) {
+    WARN(aspi, "not enough bytes read from scsi device%d\n", status);
+    goto error_exit;
+  }
+
+  if (sg_reply_hdr->result != 0) {
+    error_code = sg_reply_hdr->result;
+    WARN(aspi, "reply header error (%d)\n", sg_reply_hdr->result);
+    goto error_exit;
+  }
+
+  if (TARGET_TO_HOST(lpPRB) && lpPRB->SRB_BufLen) {
+    memcpy(lpPRB->SRB_BufPointer, sg_reply_hdr + 1, lpPRB->SRB_BufLen);
+  }
+
+  /* copy in sense buffer to amount that is available in client */
+  if (lpPRB->SRB_SenseLen) {
+    int sense_len = lpPRB->SRB_SenseLen;
+    if (lpPRB->SRB_SenseLen > 16)
+      sense_len = 16;
+    memcpy(SENSE_BUFFER(lpPRB), &sg_reply_hdr->sense_buffer[0], sense_len);
+  }
+
+
+  lpPRB->SRB_Status = SS_COMP;
+  lpPRB->SRB_HaStat = HASTAT_OK;
+  lpPRB->SRB_TargStat = STATUS_GOOD;
+
+  /* now do posting */
+
+  if (lpPRB->SRB_PostProc) {
+    if (ASPI_POSTING(lpPRB)) {
+      TRACE(aspi, "Post Routine (%lx) called\n", (DWORD) lpPRB->SRB_PostProc);
+      (*lpPRB->SRB_PostProc)(lpPRB);
+    }
+    else
+    if (lpPRB->SRB_Flags & SRB_EVENT_NOTIFY) {
+      TRACE(aspi, "Setting event %04x\n", (HANDLE32)lpPRB->SRB_PostProc);
+      SetEvent((HANDLE32)lpPRB->SRB_PostProc); /* FIXME: correct ? */
+    }
+  }
+  free(sg_reply_hdr);
+  free(sg_hd);
+  ASPI_DebugPrintResult32(lpPRB);
+  return SS_COMP;
+  
+error_exit:
+  if (error_code == EBUSY) {
+      lpPRB->SRB_Status = SS_ASPI_IS_BUSY;
+      TRACE(aspi, "Device busy\n");
+  }
+  else {
+      WARN(aspi, "Failed\n");
+      lpPRB->SRB_Status = SS_ERR;
+  }
+
+  /* I'm not sure exactly error codes work here
+   * We probably should set lpPRB->SRB_TargStat, SRB_HaStat ?
+   */
+  WARN(aspi, "error_exit\n");
+  free(sg_reply_hdr);
+  free(sg_hd);
+  return lpPRB->SRB_Status;
+}
+#endif
+
+
+/*******************************************************************
+ *     GetASPI32SupportInfo32		[WNASPI32.0]
+ *
+ * Checks if the ASPI subsystem is initialized correctly.
+ *
+ * RETURNS
+ *    HIWORD: 0.
+ *    HIBYTE of LOWORD: status (SS_COMP or SS_FAILED_INIT)
+ *    LOBYTE of LOWORD: # of host adapters.  
+ */
+DWORD WINAPI GetASPI32SupportInfo32()
+{
+    return ((SS_COMP << 8) | 1); /* FIXME: get # of host adapters installed */
+}
+
+
+/***********************************************************************
+ *             SendASPI32Command32 (WNASPI32.1)
+ */
+DWORD WINAPI SendASPI32Command32(LPSRB32 lpSRB)
+{
+#ifdef linux
+  switch (lpSRB->common.SRB_Cmd) {
+  case SC_HA_INQUIRY:
+    lpSRB->inquiry.SRB_Status = SS_COMP;       /* completed successfully */
+    lpSRB->inquiry.HA_Count = 1;               /* not always */
+    lpSRB->inquiry.HA_SCSI_ID = 7;             /* not always ID 7 */
+    strcat(lpSRB->inquiry.HA_ManagerId, "ASPI for WIN32"); /* max 15 chars, don't change */
+    strcat(lpSRB->inquiry.HA_Identifier, "Wine host"); /* FIXME: return host adapter name */
+    memset(lpSRB->inquiry.HA_Unique, 0, 16); /* default HA_Unique content */
+    lpSRB->inquiry.HA_Unique[6] = 0x02; /* Maximum Transfer Length (128K, Byte> 4-7) */
+    FIXME(aspi, "ASPI: Partially implemented SC_HA_INQUIRY for adapter %d.\n", lpSRB->inquiry.SRB_HaId);
+    return SS_COMP;
+  case SC_GET_DEV_TYPE:
+    FIXME(aspi, "Not implemented SC_GET_DEV_TYPE\n");
+    break;
+  case SC_EXEC_SCSI_CMD:
+    return ASPI_ExecScsiCmd32(&lpSRB->cmd);
+    break;
+  case SC_RESET_DEV:
+    FIXME(aspi, "Not implemented SC_RESET_DEV\n");
+    break;
+  default:
+    WARN(aspi, "Unknown command %d\n", lpSRB->common.SRB_Cmd);
+  }
+  return SS_INVALID_SRB;
+#else
+  return SS_INVALID_SRB;
+#endif
+}
+
+
+/***********************************************************************
+ *             GetASPI32DLLVersion32   (WNASPI32.3)
+ */
+
+DWORD WINAPI GetASPI32DLLVersion32()
+{
+#ifdef linux
+        return (DWORD)1;
+#else
+        return (DWORD)0;
+#endif
+}
+