Sync with trunk (r49303)
authorJérôme Gardou <jerome.gardou@reactos.org>
Wed, 27 Oct 2010 15:52:24 +0000 (15:52 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Wed, 27 Oct 2010 15:52:24 +0000 (15:52 +0000)
svn path=/branches/cmake-bringup/; revision=49307

156 files changed:
1  2 
base/applications/rapps/rapps/firefox36.txt
base/applications/rapps/rapps/libreoffice.txt
base/applications/rapps/rapps/mirandaim.txt
base/applications/rapps/rapps/mirc.txt
base/applications/rapps/rapps/opera.txt
base/applications/rapps/rapps/scummvm.txt
base/applications/rapps/rapps/seamonkey.txt
base/applications/rapps/rapps/thunderbird.txt
base/shell/explorer/desktop/desktop.cpp
base/system/services/rpcserver.c
boot/bootdata/hivesys_i386.inf
boot/bootdata/packages/reactos.dff
dll/win32/gdi32/include/gdi32p.h
dll/win32/gdi32/misc/wingl.c
dll/win32/gdi32/objects/bitmap.c
dll/win32/gdi32/objects/dc.c
dll/win32/user32/include/cursor.h
dll/win32/user32/include/user32.h
dll/win32/user32/include/user32p.h
dll/win32/user32/misc/display.c
dll/win32/user32/misc/misc.c
dll/win32/user32/windows/class.c
dll/win32/user32/windows/cursoricon.c
dll/win32/user32/windows/defwnd.c
dll/win32/user32/windows/draw.c
dll/win32/user32/windows/hook.c
dll/win32/user32/windows/input.c
dll/win32/user32/windows/menu.c
dll/win32/user32/windows/message.c
dll/win32/user32/windows/window.c
drivers/ksfilter/ks/property.c
drivers/wdm/audio/backpln/portcls/filter_wavecyclic.cpp
drivers/wdm/audio/backpln/portcls/filter_wavepci.cpp
drivers/wdm/audio/backpln/portcls/guids.cpp
drivers/wdm/audio/backpln/portcls/interfaces.hpp
drivers/wdm/audio/backpln/portcls/irpstream.cpp
drivers/wdm/audio/backpln/portcls/pin_dmus.cpp
drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp
drivers/wdm/audio/backpln/portcls/pin_wavert.cpp
drivers/wdm/audio/backpln/portcls/port_wavecyclic.cpp
drivers/wdm/audio/backpln/portcls/private.hpp
drivers/wdm/audio/backpln/portcls/undoc.cpp
hal/halx86/generic/usage.c
include/psdk/ks.h
include/psdk/ksmedia.h
include/reactos/win32k/ntuser.h
ntoskrnl/include/internal/io.h
ntoskrnl/io/iomgr/iorsrce.c
ntoskrnl/io/pnpmgr/pnpreport.c
ntoskrnl/io/pnpmgr/pnpres.c
ntoskrnl/mm/ARM3/virtual.c
subsystems/win32/csrss/win32csr/desktopbg.c
subsystems/win32/win32k/CMakeLists.txt
subsystems/win32/win32k/dib/alphablend.c
subsystems/win32/win32k/dib/dib.c
subsystems/win32/win32k/dib/dib.h
subsystems/win32/win32k/dib/dib16bpp.c
subsystems/win32/win32k/dib/dib1bpp.c
subsystems/win32/win32k/dib/dib24bpp.c
subsystems/win32/win32k/dib/dib32bpp.c
subsystems/win32/win32k/dib/dib4bpp.c
subsystems/win32/win32k/dib/dib8bpp.c
subsystems/win32/win32k/eng/alphablend.c
subsystems/win32/win32k/eng/bitblt.c
subsystems/win32/win32k/eng/copybits.c
subsystems/win32/win32k/eng/device.c
subsystems/win32/win32k/eng/engbrush.c
subsystems/win32/win32k/eng/engmisc.c
subsystems/win32/win32k/eng/gradient.c
subsystems/win32/win32k/eng/ldevobj.c
subsystems/win32/win32k/eng/lineto.c
subsystems/win32/win32k/eng/mapping.c
subsystems/win32/win32k/eng/mem.c
subsystems/win32/win32k/eng/mouse.c
subsystems/win32/win32k/eng/paint.c
subsystems/win32/win32k/eng/pdevobj.c
subsystems/win32/win32k/eng/rlecomp.c
subsystems/win32/win32k/eng/semaphor.c
subsystems/win32/win32k/eng/stretchblt.c
subsystems/win32/win32k/eng/surface.c
subsystems/win32/win32k/eng/transblt.c
subsystems/win32/win32k/eng/xlate.c
subsystems/win32/win32k/include/bitmaps.h
subsystems/win32/win32k/include/dc.h
subsystems/win32/win32k/include/device.h
subsystems/win32/win32k/include/dib.h
subsystems/win32/win32k/include/eng.h
subsystems/win32/win32k/include/gdiobj.h
subsystems/win32/win32k/include/hook.h
subsystems/win32/win32k/include/inteng.h
subsystems/win32/win32k/include/intgdi.h
subsystems/win32/win32k/include/ldevobj.h
subsystems/win32/win32k/include/misc.h
subsystems/win32/win32k/include/mouse.h
subsystems/win32/win32k/include/msgqueue.h
subsystems/win32/win32k/include/palette.h
subsystems/win32/win32k/include/pdevobj.h
subsystems/win32/win32k/include/region.h
subsystems/win32/win32k/include/surface.h
subsystems/win32/win32k/include/win32.h
subsystems/win32/win32k/include/win32kp.h
subsystems/win32/win32k/include/window.h
subsystems/win32/win32k/include/xlateobj.h
subsystems/win32/win32k/main/dllmain.c
subsystems/win32/win32k/misc/copy.c
subsystems/win32/win32k/misc/driver.c
subsystems/win32/win32k/misc/file.c
subsystems/win32/win32k/misc/registry.c
subsystems/win32/win32k/ntddraw/dxeng.c
subsystems/win32/win32k/ntuser/callback.c
subsystems/win32/win32k/ntuser/caret.c
subsystems/win32/win32k/ntuser/clipboard.c
subsystems/win32/win32k/ntuser/cursoricon.c
subsystems/win32/win32k/ntuser/desktop.c
subsystems/win32/win32k/ntuser/display.c
subsystems/win32/win32k/ntuser/event.c
subsystems/win32/win32k/ntuser/focus.c
subsystems/win32/win32k/ntuser/hook.c
subsystems/win32/win32k/ntuser/input.c
subsystems/win32/win32k/ntuser/kbdlayout.c
subsystems/win32/win32k/ntuser/message.c
subsystems/win32/win32k/ntuser/metric.c
subsystems/win32/win32k/ntuser/msgqueue.c
subsystems/win32/win32k/ntuser/ntstubs.c
subsystems/win32/win32k/ntuser/ntuser.c
subsystems/win32/win32k/ntuser/object.c
subsystems/win32/win32k/ntuser/simplecall.c
subsystems/win32/win32k/ntuser/windc.c
subsystems/win32/win32k/ntuser/window.c
subsystems/win32/win32k/ntuser/winpos.c
subsystems/win32/win32k/objects/arc.c
subsystems/win32/win32k/objects/bitblt.c
subsystems/win32/win32k/objects/bitmaps.c
subsystems/win32/win32k/objects/brush.c
subsystems/win32/win32k/objects/cliprgn.c
subsystems/win32/win32k/objects/dcattr.c
subsystems/win32/win32k/objects/dclife.c
subsystems/win32/win32k/objects/dcobjs.c
subsystems/win32/win32k/objects/dcstate.c
subsystems/win32/win32k/objects/dcutil.c
subsystems/win32/win32k/objects/device.c
subsystems/win32/win32k/objects/dibobj.c
subsystems/win32/win32k/objects/drawing.c
subsystems/win32/win32k/objects/fillshap.c
subsystems/win32/win32k/objects/freetype.c
subsystems/win32/win32k/objects/gdibatch.c
subsystems/win32/win32k/objects/gdiobj.c
subsystems/win32/win32k/objects/icm.c
subsystems/win32/win32k/objects/line.c
subsystems/win32/win32k/objects/palette.c
subsystems/win32/win32k/objects/path.c
subsystems/win32/win32k/objects/pen.c
subsystems/win32/win32k/objects/region.c
subsystems/win32/win32k/objects/stockobj.c
subsystems/win32/win32k/stubs/stubs.c

@@@ -2,47 -2,47 +2,47 @@@
  
  [Section]
  Name = Mozilla Firefox 3.6
- Version = 3.6.10
+ Version = 3.6.11
  Licence = MPL/GPL/LGPL
  Description = The most popular and one of the best free Web Browsers out there.
  Size = 8.1M
  Category = 5
  URLSite = http://www.mozilla.com/en-US/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.10/win32/en-US/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/en-US/Firefox%20Setup%203.6.11.exe
  CDPath = none
  
  [Section.0407]
  Description = Der populärste und einer der besten freien Webbrowser.
  Size = 8.0M
  URLSite = http://www.mozilla-europe.org/de/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.10/win32/de/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/de/Firefox%20Setup%203.6.11.exe
  
  [Section.040a]
  Description = El más popular y uno de los mejores navegadores web gratuitos que hay.
  Size = 8.0M
  URLSite = http://www.mozilla-europe.org/es/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.10/win32/es-ES/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/es-ES/Firefox%20Setup%203.6.11.exe
  
  [Section.0414]
  Description = Mest populære og best også gratis nettleserene der ute.
  Size = 8.0M
  URLSite = http://www.mozilla-europe.org/no/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.10/win32/nb-NO/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/nb-NO/Firefox%20Setup%203.6.11.exe
  
  [Section.0415]
  Description = Najpopularniejsza i jedna z najlepszych darmowych przeglądarek internetowych.
  Size = 8.8M
  URLSite = http://www.mozilla-europe.org/pl/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.10/win32/pl/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/pl/Firefox%20Setup%203.6.11.exe
  
  [Section.0419]
  Description = Один из самых популярных и лучших бесплатных браузеров.
  Size = 8.4M
  URLSite = http://www.mozilla-europe.org/ru/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.10/win32/ru/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/ru/Firefox%20Setup%203.6.11.exe
  
  [Section.0422]
  Description = Найпопулярніший та один з кращих безплатних веб-браузерів.
  Size = 8.4M
  URLSite = http://www.mozilla-europe.org/uk/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.10/win32/uk/Firefox%20Setup%203.6.10.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/firefox/releases/3.6.11/win32/uk/Firefox%20Setup%203.6.11.exe
@@@ -2,13 -2,13 +2,13 @@@
  
  [Section]
  Name = LibreOffice
- Version = 3.3.0 Beta 1
+ Version = 3.3.0 Beta 2
  Licence = LGPL
  Description = Former called OpenOffice. Open Source Office Suite.
- Size = 138.0MB
+ Size = 318.0MB
  Category = 6
  URLSite = http://www.documentfoundation.org/
- URLDownload = http://download.documentfoundation.org/libreoffice/testing/LO_3.3.0-beta1_Win_x86_install_en-US.exe
+ URLDownload = http://download.documentfoundation.org/libreoffice/testing/3.3.0-beta2/win/x86/LibO_3.3.0_beta2_Win_x86_install_multi.exe
  CDPath = none
  
  [Section.0407]
@@@ -2,13 -2,13 +2,13 @@@
  
  [Section]
  Name = Miranda IM
- Version = 0.9.5
+ Version = 0.9.8
  Licence = GPL
  Description = Open source multiprotocol instant messaging application - May not work completely.
- Size = 2.2MB
+ Size = 3.0MB
  Category = 5
  URLSite = http://www.miranda-im.org/
- URLDownload = http://miranda.googlecode.com/files/miranda-im-v0.9.5-unicode.exe
+ URLDownload = http://miranda.googlecode.com/files/miranda-im-v0.9.8-unicode.exe
  CDPath = none
  
  [Section.0407]
@@@ -2,13 -2,13 +2,13 @@@
  
  [Section]
  Name = mIRC
- Version = 7.1
+ Version = 7.14
  Licence = Shareware
  Description = The most popular client for the Internet Relay Chat (IRC).
- Size = 1.8M
+ Size = 2.0M
  Category = 5
  URLSite = http://www.mirc.com/
- URLDownload = http://download.mirc.com/mirc71.exe
+ URLDownload = http://download.mirc.com/mirc714.exe
  CDPath = none
  
  [Section.0407]
@@@ -2,13 -2,13 +2,13 @@@
  
  [Section]
  Name = Opera
- Version = 10.62
+ Version = 10.63
  Licence = Freeware
  Description = The popular Opera Browser with many advanced features and including a Mail and BitTorrent client.
  Size = 12.7M
  Category = 5
  URLSite = http://www.opera.com/
- URLDownload = http://get4.opera.com/pub/opera/win/1062/int/Opera_1062_int_Setup.exe
+ URLDownload = http://get4.opera.com/pub/opera/win/1063/int/Opera_1063_int_Setup.exe
  CDPath = none
  
  [Section.0407]
@@@ -2,13 -2,13 +2,13 @@@
  
  [Section]
  Name = ScummVM
- Version = 1.1.1
+ Version = 1.2.0
  Licence = GPL
  Description = Sam and Max, Day of the Tentacle, etc on ReactOS.
- Size = 3.3MB
+ Size = 3.5MB
  Category = 4
  URLSite = http://scummvm.org/
- URLDownload = http://dfn.dl.sourceforge.net/project/scummvm/scummvm/1.1.1/scummvm-1.1.1-win32.exe
+ URLDownload = http://dfn.dl.sourceforge.net/project/scummvm/scummvm/1.2.0/scummvm-1.2.0-win32.exe
  CDPath = none
  
  [Section.0407]
@@@ -2,31 -2,31 +2,31 @@@
  
  [Section]
  Name = Mozilla SeaMonkey
- Version = 2.0.8
+ Version = 2.0.9
  Licence = MPL/GPL/LGPL
  Description = Mozilla Suite is alive. This is the one and only Browser, Mail, Chat, and Composer bundle you will ever need.
  Size = 10.1MB
  Category = 5
  URLSite = http://www.seamonkey-project.org/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.8/win32/en-US/SeaMonkey%20Setup%202.0.8.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/en-US/SeaMonkey%20Setup%202.0.9.exe
  CDPath = none
  
  [Section.0407]
  Description = Mozilla Suite lebt. Dies ist das einzige Browser-, Mail-, Chat- and Composerwerkzeug-Bundle welches Sie benötigen.
  Size = 10.0MB
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.8/win32/de/SeaMonkey%20Setup%202.0.8.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/de/SeaMonkey%20Setup%202.0.9.exe
  
  [Section.040a]
  Description = La suite de Mozilla está viva. Es el primero y único navegador web, gestor de correo, lector de noticias, Chat y editor HTML que necesitarás.
  Size = 10.0MB
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.8/win32/es-ES/SeaMonkey%20Setup%202.0.8.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/es-ES/SeaMonkey%20Setup%202.0.9.exe
  
  [Section.0415]
  Description = Pakiet Mozilla żyje. W zestawie: przeglądarka, klient poczty, IRC oraz Edytor HTML - wszystko, czego potrzebujesz.
  Size = 10.8MB
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.8/win32/pl/SeaMonkey%20Setup%202.0.8.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/pl/SeaMonkey%20Setup%202.0.9.exe
  
  [Section.0419]
  Description = Продолжение Mozilla Suite. Включает браузер, почтовый клиент, IRC-клиент и HTML-редактор.
  Size = 10.4MB
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.8/win32/ru/SeaMonkey%20Setup%202.0.8.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/seamonkey/releases/2.0.9/win32/ru/SeaMonkey%20Setup%202.0.9.exe
@@@ -2,41 -2,41 +2,41 @@@
  
  [Section]
  Name = Mozilla Thunderbird
- Version = 3.1.4
+ Version = 3.1.5
  Licence = MPL/GPL/LGPL
  Description = The most popular and one of the best free Mail Clients out there.
  Size = 9.0M
  Category = 5
  URLSite = http://www.mozilla-europe.org/en/products/thunderbird/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.4/win32/en-US/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/en-US/Thunderbird%20Setup%203.1.5.exe
  CDPath = none
  
  [Section.0407]
  Description = Der populärste und einer der besten freien Mail-Clients.
  Size = 8.8M
  URLSite = http://www.mozilla-europe.org/de/products/thunderbird/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.4/win32/de/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/de/Thunderbird%20Setup%203.1.5.exe
  
  [Section.040a]
  Description = El más popular y uno de los mejores clientes mail que hay.
  Size = 8.8M
  URLSite = http://www.mozilla-europe.org/es/products/thunderbird/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.4/win32/es-ES/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/es-ES/Thunderbird%20Setup%203.1.5.exe
  
  [Section.0415]
  Description = Najpopularniejszy i jeden z najlepszych darmowych klientów poczty.
  Size = 9.7M
  URLSite = http://www.mozilla-europe.org/pl/products/thunderbird/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.4/win32/pl/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/pl/Thunderbird%20Setup%203.1.5.exe
  
  [Section.0419]
  Description = Один из самых популярных и лучших бесплатных почтовых клиентов.
  Size = 9.2M
  URLSite = http://www.mozilla-europe.org/ru/products/thunderbird/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.4/win32/ru/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/ru/Thunderbird%20Setup%203.1.5.exe
  
  [Section.0422]
  Description = Найпопулярніший та один з кращих поштових клієнтів.
  Size = 9.2M
  URLSite = http://www.mozillamessaging.com/uk/thunderbird/
- URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.4/win32/uk/Thunderbird%20Setup%203.1.4.exe
+ URLDownload = http://releases.mozilla.org/pub/mozilla.org/thunderbird/releases/3.1.5/win32/uk/Thunderbird%20Setup%203.1.5.exe
@@@ -435,6 -435,12 +435,12 @@@ LRESULT DesktopWindow::WndProc(UINT nms
                explorer_show_frame(SW_SHOWNORMAL);
                break;
  
+       case WM_DISPLAYCHANGE:
+         MoveWindow(_hwnd, 0, 0, LOWORD(lparam), HIWORD(lparam), TRUE);
+         MoveWindow(g_Globals._hwndShellView, 0, 0, LOWORD(lparam), HIWORD(lparam), TRUE);
+         MoveWindow(_desktopBar, 0, HIWORD(lparam) - DESKTOPBARBAR_HEIGHT, LOWORD(lparam), DESKTOPBARBAR_HEIGHT, TRUE);
+         break;
          case WM_GETISHELLBROWSER:
                return (LRESULT)static_cast<IShellBrowser*>(this);
  
index b30b11e,0000000..28bce05
mode 100644,000000..100644
--- /dev/null
@@@ -1,5382 -1,0 +1,5418 @@@
-     /* FIXME: Insert more data here */
 +/*
 + * PROJECT:     ReactOS Service Control Manager
 + * LICENSE:     GPL - See COPYING in the top level directory
 + * FILE:        base/system/services/rpcserver.c
 + * PURPOSE:     RPC server interface for the advapi32 calls
 + * COPYRIGHT:   Copyright 2005-2006 Eric Kohl
 + *              Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
 + *              Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
 + */
 +
 +/* INCLUDES ****************************************************************/
 +
 +#include "services.h"
 +#include "svcctl_s.h"
 +
 +#define NDEBUG
 +#include <debug.h>
 +
 +/* GLOBALS *****************************************************************/
 +
 +#define MANAGER_TAG 0x72674D68  /* 'hMgr' */
 +#define SERVICE_TAG 0x63765368  /* 'hSvc' */
 +
 +typedef struct _SCMGR_HANDLE
 +{
 +    DWORD Tag;
 +    DWORD DesiredAccess;
 +} SCMGR_HANDLE;
 +
 +
 +typedef struct _MANAGER_HANDLE
 +{
 +    SCMGR_HANDLE Handle;
 +    WCHAR DatabaseName[1];
 +} MANAGER_HANDLE, *PMANAGER_HANDLE;
 +
 +
 +typedef struct _SERVICE_HANDLE
 +{
 +    SCMGR_HANDLE Handle;
-     /* FIXME: Insert more data here */
 +    PSERVICE ServiceEntry;
-     if (_wcsicmp(lpDatabaseName,SERVICES_FAILED_DATABASEW)==0)
 +} SERVICE_HANDLE, *PSERVICE_HANDLE;
 +
 +
 +#define SC_MANAGER_READ \
 +  (STANDARD_RIGHTS_READ | \
 +   SC_MANAGER_QUERY_LOCK_STATUS | \
 +   SC_MANAGER_ENUMERATE_SERVICE)
 +
 +#define SC_MANAGER_WRITE \
 +  (STANDARD_RIGHTS_WRITE | \
 +   SC_MANAGER_MODIFY_BOOT_CONFIG | \
 +   SC_MANAGER_CREATE_SERVICE)
 +
 +#define SC_MANAGER_EXECUTE \
 +  (STANDARD_RIGHTS_EXECUTE | \
 +   SC_MANAGER_LOCK | \
 +   SC_MANAGER_ENUMERATE_SERVICE | \
 +   SC_MANAGER_CONNECT | \
 +   SC_MANAGER_CREATE_SERVICE)
 +
 +
 +#define SERVICE_READ \
 +  (STANDARD_RIGHTS_READ | \
 +   SERVICE_INTERROGATE | \
 +   SERVICE_ENUMERATE_DEPENDENTS | \
 +   SERVICE_QUERY_STATUS | \
 +   SERVICE_QUERY_CONFIG)
 +
 +#define SERVICE_WRITE \
 +  (STANDARD_RIGHTS_WRITE | \
 +   SERVICE_CHANGE_CONFIG)
 +
 +#define SERVICE_EXECUTE \
 +  (STANDARD_RIGHTS_EXECUTE | \
 +   SERVICE_USER_DEFINED_CONTROL | \
 +   SERVICE_PAUSE_CONTINUE | \
 +   SERVICE_STOP | \
 +   SERVICE_START)
 +
 +
 +/* VARIABLES ***************************************************************/
 +
 +static GENERIC_MAPPING
 +ScmManagerMapping = {SC_MANAGER_READ,
 +                     SC_MANAGER_WRITE,
 +                     SC_MANAGER_EXECUTE,
 +                     SC_MANAGER_ALL_ACCESS};
 +
 +static GENERIC_MAPPING
 +ScmServiceMapping = {SERVICE_READ,
 +                     SERVICE_WRITE,
 +                     SERVICE_EXECUTE,
 +                     SC_MANAGER_ALL_ACCESS};
 +
 +
 +/* FUNCTIONS ***************************************************************/
 +
 +VOID
 +ScmStartRpcServer(VOID)
 +{
 +    RPC_STATUS Status;
 +
 +    DPRINT("ScmStartRpcServer() called\n");
 +
 +    Status = RpcServerUseProtseqEpW(L"ncacn_np",
 +                                    10,
 +                                    L"\\pipe\\ntsvcs",
 +                                    NULL);
 +    if (Status != RPC_S_OK)
 +    {
 +        DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
 +        return;
 +    }
 +
 +    Status = RpcServerRegisterIf(svcctl_v2_0_s_ifspec,
 +                                 NULL,
 +                                 NULL);
 +    if (Status != RPC_S_OK)
 +    {
 +        DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
 +        return;
 +    }
 +
 +    Status = RpcServerListen(1, 20, TRUE);
 +    if (Status != RPC_S_OK)
 +    {
 +        DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
 +        return;
 +    }
 +
 +    DPRINT("ScmStartRpcServer() done\n");
 +}
 +
 +
 +static DWORD
 +ScmCreateManagerHandle(LPWSTR lpDatabaseName,
 +                       SC_HANDLE *Handle)
 +{
 +    PMANAGER_HANDLE Ptr;
 +
 +    if (lpDatabaseName == NULL)
 +        lpDatabaseName = SERVICES_ACTIVE_DATABASEW;
 +
-     /* FIXME: initialize more data here */
++    if (_wcsicmp(lpDatabaseName, SERVICES_FAILED_DATABASEW) == 0)
 +    {
 +        DPRINT("Database %S, does not exist\n",lpDatabaseName);
 +        return ERROR_DATABASE_DOES_NOT_EXIST;
 +    }
 +    else if (_wcsicmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
 +    {
 +        DPRINT("Invalid Database name %S.\n",lpDatabaseName);
 +        return ERROR_INVALID_NAME;
 +    }
 +
 +    Ptr = (MANAGER_HANDLE*) HeapAlloc(GetProcessHeap(),
 +                    HEAP_ZERO_MEMORY,
 +                    sizeof(MANAGER_HANDLE) + (wcslen(lpDatabaseName) + 1) * sizeof(WCHAR));
 +    if (Ptr == NULL)
 +        return ERROR_NOT_ENOUGH_MEMORY;
 +
 +    Ptr->Handle.Tag = MANAGER_TAG;
 +
-     /* FIXME: initialize more data here */
 +    wcscpy(Ptr->DatabaseName, lpDatabaseName);
 +
 +    *Handle = (SC_HANDLE)Ptr;
 +
 +    return ERROR_SUCCESS;
 +}
 +
 +
 +static DWORD
 +ScmCreateServiceHandle(PSERVICE lpServiceEntry,
 +                       SC_HANDLE *Handle)
 +{
 +    PSERVICE_HANDLE Ptr;
 +
 +    Ptr = (SERVICE_HANDLE*) HeapAlloc(GetProcessHeap(),
 +                    HEAP_ZERO_MEMORY,
 +                    sizeof(SERVICE_HANDLE));
 +    if (Ptr == NULL)
 +        return ERROR_NOT_ENOUGH_MEMORY;
 +
 +    Ptr->Handle.Tag = SERVICE_TAG;
 +
-     hManager = (PMANAGER_HANDLE)*hSCObject;
-     hService = (PSERVICE_HANDLE)*hSCObject;
-     if (hManager->Handle.Tag == MANAGER_TAG)
 +    Ptr->ServiceEntry = lpServiceEntry;
 +
 +    *Handle = (SC_HANDLE)Ptr;
 +
 +    return ERROR_SUCCESS;
 +}
 +
 +
 +static PMANAGER_HANDLE
 +ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle)
 +{
 +    PMANAGER_HANDLE pManager = NULL;
 +
 +    _SEH2_TRY
 +    {
 +        if (((PMANAGER_HANDLE)Handle)->Handle.Tag == MANAGER_TAG)
 +            pManager = (PMANAGER_HANDLE)Handle;
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        DPRINT1("Exception: Invalid Service Manager handle!\n");
 +    }
 +    _SEH2_END;
 +
 +    return pManager;
 +}
 +
 +
 +static PSERVICE_HANDLE
 +ScmGetServiceFromHandle(SC_RPC_HANDLE Handle)
 +{
 +    PSERVICE_HANDLE pService = NULL;
 +
 +    _SEH2_TRY
 +    {
 +        if (((PSERVICE_HANDLE)Handle)->Handle.Tag == SERVICE_TAG)
 +            pService = (PSERVICE_HANDLE)Handle;
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        DPRINT1("Exception: Invalid Service handle!\n");
 +    }
 +    _SEH2_END;
 +
 +    return pService;
 +}
 +
 +
 +static DWORD
 +ScmCheckAccess(SC_HANDLE Handle,
 +               DWORD dwDesiredAccess)
 +{
 +    PMANAGER_HANDLE hMgr;
 +
 +    hMgr = (PMANAGER_HANDLE)Handle;
 +    if (hMgr->Handle.Tag == MANAGER_TAG)
 +    {
 +        RtlMapGenericMask(&dwDesiredAccess,
 +                          &ScmManagerMapping);
 +
 +        hMgr->Handle.DesiredAccess = dwDesiredAccess;
 +
 +        return ERROR_SUCCESS;
 +    }
 +    else if (hMgr->Handle.Tag == SERVICE_TAG)
 +    {
 +        RtlMapGenericMask(&dwDesiredAccess,
 +                          &ScmServiceMapping);
 +
 +        hMgr->Handle.DesiredAccess = dwDesiredAccess;
 +
 +        return ERROR_SUCCESS;
 +    }
 +
 +    return ERROR_INVALID_HANDLE;
 +}
 +
 +
 +DWORD
 +ScmAssignNewTag(PSERVICE lpService)
 +{
 +    /* FIXME */
 +    DPRINT("Assigning new tag to service %S\n", lpService->lpServiceName);
 +    lpService->dwTag = 0;
 +    return ERROR_SUCCESS;
 +}
 +
 +
 +/* Internal recursive function */
 +/* Need to search for every dependency on every service */
 +static DWORD
 +Int_EnumDependentServicesW(HKEY hServicesKey,
 +                           PSERVICE lpService,
 +                           DWORD dwServiceState,
 +                           PSERVICE *lpServices,
 +                           LPDWORD pcbBytesNeeded,
 +                           LPDWORD lpServicesReturned)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    WCHAR szNameBuf[MAX_PATH];
 +    WCHAR szValueBuf[MAX_PATH];
 +    WCHAR *lpszNameBuf = szNameBuf;
 +    WCHAR *lpszValueBuf = szValueBuf;
 +    DWORD dwSize;
 +    DWORD dwNumSubKeys;
 +    DWORD dwIteration;
 +    PSERVICE lpCurrentService;
 +    HKEY hServiceEnumKey;
 +    DWORD dwCurrentServiceState = SERVICE_ACTIVE;
 +    DWORD dwDependServiceStrPtr = 0;
 +    DWORD dwRequiredSize = 0;
 +
 +    /* Get the number of service keys */
 +    dwError = RegQueryInfoKeyW(hServicesKey,
 +                               NULL,
 +                               NULL,
 +                               NULL,
 +                               &dwNumSubKeys,
 +                               NULL,
 +                               NULL,
 +                               NULL,
 +                               NULL,
 +                               NULL,
 +                               NULL,
 +                               NULL);
 +    if (dwError != ERROR_SUCCESS)
 +    {
 +        DPRINT("ERROR! Unable to get number of services keys.\n");
 +        return dwError;
 +    }
 +
 +    /* Iterate the service keys to see if another service depends on the this service */
 +    for (dwIteration = 0; dwIteration < dwNumSubKeys; dwIteration++)
 +    {
 +        dwSize = MAX_PATH;
 +        dwError = RegEnumKeyExW(hServicesKey,
 +                                dwIteration,
 +                                lpszNameBuf,
 +                                &dwSize,
 +                                NULL,
 +                                NULL,
 +                                NULL,
 +                                NULL);
 +        if (dwError != ERROR_SUCCESS)
 +            return dwError;
 +
 +        /* Open the Service key */
 +        dwError = RegOpenKeyExW(hServicesKey,
 +                                lpszNameBuf,
 +                                0,
 +                                KEY_READ,
 +                                &hServiceEnumKey);
 +        if (dwError != ERROR_SUCCESS)
 +            return dwError;
 +
 +        dwSize = MAX_PATH;
 +
 +        /* Check for the DependOnService Value */
 +        dwError = RegQueryValueExW(hServiceEnumKey,
 +                                   L"DependOnService",
 +                                   NULL,
 +                                   NULL,
 +                                   (LPBYTE)lpszValueBuf,
 +                                   &dwSize);
 +
 +        /* FIXME: Handle load order. */
 +
 +        /* If the service found has a DependOnService value */
 +        if (dwError == ERROR_SUCCESS)
 +        {
 +            dwDependServiceStrPtr = 0;
 +
 +            /* Can be more than one Dependencies in the DependOnService string */
 +            while (wcslen(lpszValueBuf + dwDependServiceStrPtr) > 0)
 +            {
 +                if (_wcsicmp(lpszValueBuf + dwDependServiceStrPtr, lpService->lpServiceName) == 0)
 +                {
 +                    /* Get the current enumed service pointer */
 +                    lpCurrentService = ScmGetServiceEntryByName(lpszNameBuf);
 +
 +                    /* Check for valid Service */
 +                    if (!lpCurrentService)
 +                    {
 +                        /* This should never happen! */
 +                        DPRINT("This should not happen at this point, report to Developer\n");
 +                        return ERROR_NOT_FOUND;
 +                    }
 +
 +                    /* Determine state the service is in */
 +                    if (lpCurrentService->Status.dwCurrentState == SERVICE_STOPPED)
 +                        dwCurrentServiceState = SERVICE_INACTIVE;
 +
 +                    /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
 +                    if ((dwCurrentServiceState == dwServiceState) ||
 +                        (dwServiceState == SERVICE_STATE_ALL))
 +                    {
 +                        /* Calculate the required size */
 +                        dwRequiredSize += sizeof(SERVICE_STATUS);
 +                        dwRequiredSize += ((wcslen(lpCurrentService->lpServiceName) + 1) * sizeof(WCHAR));
 +                        dwRequiredSize += ((wcslen(lpCurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
 +
 +                        /* Add the size for service name and display name pointers */
 +                        dwRequiredSize += (2 * sizeof(PVOID));
 +
 +                        /* increase the BytesNeeded size */
 +                        *pcbBytesNeeded = *pcbBytesNeeded + dwRequiredSize;
 +
 +                        /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
 +                           comes first */
 +
 +                        /* Recursive call to check for its dependencies */
 +                        Int_EnumDependentServicesW(hServicesKey,
 +                                                   lpCurrentService,
 +                                                   dwServiceState,
 +                                                   lpServices,
 +                                                   pcbBytesNeeded,
 +                                                   lpServicesReturned);
 +
 +                        /* If the lpServices is valid set the service pointer */
 +                        if (lpServices)
 +                            lpServices[*lpServicesReturned] = lpCurrentService;
 +
 +                        *lpServicesReturned = *lpServicesReturned + 1;
 +                    }
 +                }
 +
 +                dwDependServiceStrPtr += (wcslen(lpszValueBuf + dwDependServiceStrPtr) + 1);
 +            }
 +        }
 +        else if (*pcbBytesNeeded)
 +        {
 +            dwError = ERROR_SUCCESS;
 +        }
 +
 +        RegCloseKey(hServiceEnumKey);
 +    }
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 0 */
 +DWORD RCloseServiceHandle(
 +    LPSC_RPC_HANDLE hSCObject)
 +{
 +    PMANAGER_HANDLE hManager;
 +    PSERVICE_HANDLE hService;
 +    PSERVICE lpService;
 +    HKEY hServicesKey;
 +    DWORD dwError;
 +    DWORD pcbBytesNeeded = 0;
 +    DWORD dwServicesReturned = 0;
 +
 +    DPRINT("RCloseServiceHandle() called\n");
 +
 +    DPRINT("hSCObject = %p\n", *hSCObject);
 +
 +    if (*hSCObject == 0)
 +        return ERROR_INVALID_HANDLE;
 +
-     else if (hService->Handle.Tag == SERVICE_TAG)
++    hManager = ScmGetServiceManagerFromHandle(*hSCObject);
++    hService = ScmGetServiceFromHandle(*hSCObject);
++
++    if (hManager != NULL)
 +    {
 +        DPRINT("Found manager handle\n");
 +
 +        /* FIXME: add handle cleanup code */
 +
 +        HeapFree(GetProcessHeap(), 0, hManager);
 +        hManager = NULL;
 +
 +        DPRINT("RCloseServiceHandle() done\n");
 +        return ERROR_SUCCESS;
 +    }
++    else if (hService != NULL)
 +    {
 +        DPRINT("Found service handle\n");
 +
 +        /* Get the pointer to the service record */
 +        lpService = hService->ServiceEntry;
 +
 +        /* FIXME: add handle cleanup code */
 +
 +        /* Free the handle */
 +        HeapFree(GetProcessHeap(), 0, hService);
 +        hService = NULL;
 +
 +        ASSERT(lpService->dwRefCount > 0);
 +
 +        lpService->dwRefCount--;
 +        DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
 +               lpService->dwRefCount);
 +
 +        if (lpService->dwRefCount == 0)
 +        {
 +            /* If this service has been marked for deletion */
 +            if (lpService->bDeleted)
 +            {
 +                /* Open the Services Reg key */
 +                dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
 +                                        L"System\\CurrentControlSet\\Services",
 +                                        0,
 +                                        KEY_SET_VALUE | KEY_READ,
 +                                        &hServicesKey);
 +                if (dwError != ERROR_SUCCESS)
 +                {
 +                    DPRINT("Failed to open services key\n");
 +                    return dwError;
 +                }
 +
 +                /* Call the internal function with NULL, just to get bytes we need */
 +                Int_EnumDependentServicesW(hServicesKey,
 +                                           lpService,
 +                                           SERVICE_ACTIVE,
 +                                           NULL,
 +                                           &pcbBytesNeeded,
 +                                           &dwServicesReturned);
 +
 +                /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
 +                if (pcbBytesNeeded)
 +                {
 +                    DPRINT("Deletion failed due to running dependencies.\n");
 +                    RegCloseKey(hServicesKey);
 +                    return ERROR_SUCCESS;
 +                }
 +
 +                /* There are no references and no runnning dependencies,
 +                   it is now safe to delete the service */
 +
 +                /* Delete the Service Key */
 +                dwError = RegDeleteKeyW(hServicesKey,
 +                                        lpService->lpServiceName);
 +
 +                RegCloseKey(hServicesKey);
 +
 +                if (dwError != ERROR_SUCCESS)
 +                {
 +                    DPRINT("Failed to Delete the Service Registry key\n");
 +                    return dwError;
 +                }
 +
 +                /* Delete the Service */
 +                ScmDeleteServiceRecord(lpService);
 +            }
 +        }
 +
 +        DPRINT("RCloseServiceHandle() done\n");
 +        return ERROR_SUCCESS;
 +    }
 +
 +    DPRINT("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
 +
 +    return ERROR_INVALID_HANDLE;
 +}
 +
 +
 +/* Function 1 */
 +DWORD RControlService(
 +    SC_RPC_HANDLE hService,
 +    DWORD dwControl,
 +    LPSERVICE_STATUS lpServiceStatus)
 +{
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService;
 +    ACCESS_MASK DesiredAccess;
 +    DWORD dwError = ERROR_SUCCESS;
 +    DWORD pcbBytesNeeded = 0;
 +    DWORD dwServicesReturned = 0;
++    DWORD dwControlsAccepted;
++    DWORD dwCurrentState;
 +    HKEY hServicesKey = NULL;
 +
 +    DPRINT("RControlService() called\n");
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    /* Check the service handle */
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +
 +    /* Check the service entry point */
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT1("lpService == NULL!\n"); 
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* Check access rights */
 +    switch (dwControl)
 +    {
 +        case SERVICE_CONTROL_STOP:
 +            DesiredAccess = SERVICE_STOP;
 +            break;
 +
 +        case SERVICE_CONTROL_PAUSE:
 +        case SERVICE_CONTROL_CONTINUE:
 +            DesiredAccess = SERVICE_PAUSE_CONTINUE;
 +            break;
 +
 +        case SERVICE_INTERROGATE:
 +            DesiredAccess = SERVICE_INTERROGATE;
 +            break;
 +
 +        default:
 +            if (dwControl >= 128 && dwControl <= 255)
 +                DesiredAccess = SERVICE_USER_DEFINED_CONTROL;
 +            else
 +                DesiredAccess = SERVICE_QUERY_CONFIG |
 +                                SERVICE_CHANGE_CONFIG |
 +                                SERVICE_QUERY_STATUS |
 +                                SERVICE_START |
 +                                SERVICE_PAUSE_CONTINUE;
 +            break;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  DesiredAccess))
 +        return ERROR_ACCESS_DENIED;
 +
 +    if (dwControl == SERVICE_CONTROL_STOP)
 +    {
 +        /* Check if the service has dependencies running as windows
 +           doesn't stop a service that does */
 +
 +        /* Open the Services Reg key */
 +        dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
 +                                L"System\\CurrentControlSet\\Services",
 +                                0,
 +                                KEY_READ,
 +                                &hServicesKey);
 +        if (dwError != ERROR_SUCCESS)
 +        {
 +            DPRINT("Failed to open services key\n");
 +            return dwError;
 +        }
 +
 +        /* Call the internal function with NULL, just to get bytes we need */
 +        Int_EnumDependentServicesW(hServicesKey,
 +                                   lpService,
 +                                   SERVICE_ACTIVE,
 +                                   NULL,
 +                                   &pcbBytesNeeded,
 +                                   &dwServicesReturned);
 +
 +        RegCloseKey(hServicesKey);
 +
 +        /* If pcbBytesNeeded is not zero then there are services running that
 +           are dependent on this service */
 +        if (pcbBytesNeeded != 0)
 +        {
 +            DPRINT("Service has running dependencies. Failed to stop service.\n");
 +            return ERROR_DEPENDENT_SERVICES_RUNNING;
 +        }
 +    }
 +
 +    if (lpService->Status.dwServiceType & SERVICE_DRIVER)
 +    {
 +        /* Send control code to the driver */
 +        dwError = ScmControlDriver(lpService,
 +                                   dwControl,
 +                                   lpServiceStatus);
 +    }
 +    else
 +    {
++        dwControlsAccepted = lpService->Status.dwControlsAccepted;
++        dwCurrentState = lpService->Status.dwCurrentState;
++
++        /* Check the current state before sending a control request */
++        switch (dwCurrentState)
++        {
++            case SERVICE_STOP_PENDING:
++            case SERVICE_STOPPED:
++                return ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
++
++            case SERVICE_START_PENDING:
++                switch (dwControl)
++                {
++                    case SERVICE_CONTROL_STOP:
++                        break;
++
++                    case SERVICE_CONTROL_INTERROGATE:
++                        RtlCopyMemory(lpServiceStatus,
++                                      &lpService->Status,
++                                      sizeof(SERVICE_STATUS));
++                        return ERROR_SUCCESS;
++
++                    default:
++                        return ERROR_SERVICE_CANNOT_ACCEPT_CTRL;
++                }
++                break;
++        }
++
++        /* Check if the control code is acceptable to the service */
++        switch (dwControl)
++        {
++            case SERVICE_CONTROL_STOP:
++                if ((dwControlsAccepted & SERVICE_ACCEPT_STOP) == 0)
++                    return ERROR_INVALID_SERVICE_CONTROL;
++                break;
++
++            case SERVICE_CONTROL_PAUSE:
++            case SERVICE_CONTROL_CONTINUE:
++                if ((dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) == 0)
++                    return ERROR_INVALID_SERVICE_CONTROL;
++                break;
++        }
++
 +        /* Send control code to the service */
 +        dwError = ScmControlService(lpService,
 +                                    dwControl);
 +
 +        /* Return service status information */
 +        RtlCopyMemory(lpServiceStatus,
 +                      &lpService->Status,
 +                      sizeof(SERVICE_STATUS));
 +    }
 +
 +    if ((dwError == ERROR_SUCCESS) && (pcbBytesNeeded))
 +        dwError = ERROR_DEPENDENT_SERVICES_RUNNING;
 +
 +    if (dwError == ERROR_SUCCESS &&
 +        dwControl == SERVICE_CONTROL_STOP && 
 +        lpServiceStatus->dwCurrentState == SERVICE_STOPPED)
 +    {
 +        lpService->ProcessId = 0; /* FIXME */
 +        lpService->ThreadId = 0;
 +    }
 +
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 2 */
 +DWORD RDeleteService(
 +    SC_RPC_HANDLE hService)
 +{
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService;
 +    DWORD dwError;
 +
 +    DPRINT("RDeleteService() called\n");
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  DELETE))
 +        return ERROR_ACCESS_DENIED;
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* FIXME: Acquire service database lock exclusively */
 +
 +    if (lpService->bDeleted)
 +    {
 +        DPRINT("The service has already been marked for delete!\n");
 +        return ERROR_SERVICE_MARKED_FOR_DELETE;
 +    }
 +
 +    /* Mark service for delete */
 +    lpService->bDeleted = TRUE;
 +
 +    dwError = ScmMarkServiceForDelete(lpService);
 +
 +    /* FIXME: Release service database lock */
 +
 +    DPRINT("RDeleteService() done\n");
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 3 */
 +DWORD RLockServiceDatabase(
 +    SC_RPC_HANDLE hSCManager,
 +    LPSC_RPC_LOCK lpLock)
 +{
 +    PMANAGER_HANDLE hMgr;
 +
 +    DPRINT("RLockServiceDatabase() called\n");
 +
 +    *lpLock = 0;
 +
 +    hMgr = ScmGetServiceManagerFromHandle(hSCManager);
 +    if (hMgr == NULL)
 +    {
 +        DPRINT1("Invalid service manager handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
 +                                  SC_MANAGER_LOCK))
 +        return ERROR_ACCESS_DENIED;
 +
 +//    return ScmLockDatabase(0, hMgr->0xC, hLock);
 +
 +    /* FIXME: Lock the database */
 +    *lpLock = (SC_RPC_LOCK)0x12345678; /* Dummy! */
 +
 +    return ERROR_SUCCESS;
 +}
 +
 +
 +/* Function 4 */
 +DWORD RQueryServiceObjectSecurity(
 +    SC_RPC_HANDLE hService,
 +    SECURITY_INFORMATION dwSecurityInformation,
 +    LPBYTE lpSecurityDescriptor,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_256K pcbBytesNeeded)
 +{
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService;
 +    ULONG DesiredAccess = 0;
 +    NTSTATUS Status;
 +    DWORD dwBytesNeeded;
 +    DWORD dwError;
 +
 +
 +    SECURITY_DESCRIPTOR ObjectDescriptor;
 +
 +    DPRINT("RQueryServiceObjectSecurity() called\n");
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (dwSecurityInformation & (DACL_SECURITY_INFORMATION ||
 +                                 GROUP_SECURITY_INFORMATION ||
 +                                 OWNER_SECURITY_INFORMATION))
 +        DesiredAccess |= READ_CONTROL;
 +
 +    if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
 +        DesiredAccess |= ACCESS_SYSTEM_SECURITY;
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  DesiredAccess))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* FIXME: Lock the service list */
 +
 +    /* hack */
 +    Status = RtlCreateSecurityDescriptor(&ObjectDescriptor, SECURITY_DESCRIPTOR_REVISION);
 +
 +    Status = RtlQuerySecurityObject(&ObjectDescriptor  /* lpService->lpSecurityDescriptor */,
 +                                    dwSecurityInformation,
 +                                    (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
 +                                    cbBufSize,
 +                                    &dwBytesNeeded);
 +
 +    /* FIXME: Unlock the service list */
 +
 +    if (NT_SUCCESS(Status))
 +    {
 +        *pcbBytesNeeded = dwBytesNeeded;
 +        dwError = STATUS_SUCCESS;
 +    }
 +    else if (Status == STATUS_BUFFER_TOO_SMALL)
 +    {
 +        *pcbBytesNeeded = dwBytesNeeded;
 +        dwError = ERROR_INSUFFICIENT_BUFFER;
 +    }
 +    else if (Status == STATUS_BAD_DESCRIPTOR_FORMAT)
 +    {
 +        dwError = ERROR_GEN_FAILURE;
 +    }
 +    else
 +    {
 +        dwError = RtlNtStatusToDosError(Status);
 +    }
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 5 */
 +DWORD RSetServiceObjectSecurity(
 +    SC_RPC_HANDLE hService,
 +    DWORD dwSecurityInformation,
 +    LPBYTE lpSecurityDescriptor,
 +    DWORD dwSecuityDescriptorSize)
 +{
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService;
 +    ULONG DesiredAccess = 0;
 +    /* HANDLE hToken = NULL; */
 +    HKEY hServiceKey;
 +    /* NTSTATUS Status; */
 +    DWORD dwError;
 +
 +    DPRINT("RSetServiceObjectSecurity() called\n");
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (dwSecurityInformation == 0 ||
 +        dwSecurityInformation & ~(OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
 +        | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION))
 +        return ERROR_INVALID_PARAMETER;
 +
 +    if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor))
 +        return ERROR_INVALID_PARAMETER;
 +
 +    if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
 +        DesiredAccess |= ACCESS_SYSTEM_SECURITY;
 +
 +    if (dwSecurityInformation & DACL_SECURITY_INFORMATION)
 +        DesiredAccess |= WRITE_DAC;
 +
 +    if (dwSecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
 +        DesiredAccess |= WRITE_OWNER;
 +
 +    if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) &&
 +        (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
 +        return ERROR_INVALID_PARAMETER;
 +
 +    if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) &&
 +        (((PISECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
 +        return ERROR_INVALID_PARAMETER;
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  DesiredAccess))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (lpService->bDeleted)
 +        return ERROR_SERVICE_MARKED_FOR_DELETE;
 +
 +#if 0
 +    RpcImpersonateClient(NULL);
 +
 +    Status = NtOpenThreadToken(NtCurrentThread(),
 +                               8,
 +                               TRUE,
 +                               &hToken);
 +    if (!NT_SUCCESS(Status))
 +        return RtlNtStatusToDosError(Status); 
 +
 +    RpcRevertToSelf();
 +
 +    /* FIXME: Lock service database */
 +
 +    Status = RtlSetSecurityObject(dwSecurityInformation,
 +                                  (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
 +                                  &lpService->lpSecurityDescriptor,
 +                                  &ScmServiceMapping,
 +                                  hToken);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        dwError = RtlNtStatusToDosError(Status);
 +        goto Done;
 +    }
 +#endif
 +
 +    dwError = ScmOpenServiceKey(lpService->lpServiceName,
 +                                READ_CONTROL | KEY_CREATE_SUB_KEY | KEY_SET_VALUE,
 +                                &hServiceKey);
 +    if (dwError != ERROR_SUCCESS)
 +        goto Done;
 +
 +    UNIMPLEMENTED;
 +    dwError = ERROR_SUCCESS;
 +//    dwError = ScmWriteSecurityDescriptor(hServiceKey,
 +//                                         lpService->lpSecurityDescriptor);
 +
 +    RegFlushKey(hServiceKey);
 +    RegCloseKey(hServiceKey);
 +
 +Done:
 +
 +#if 0
 +    if (hToken != NULL)
 +        NtClose(hToken);
 +#endif
 +
 +    /* FIXME: Unlock service database */
 +
 +    DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 6 */
 +DWORD RQueryServiceStatus(
 +    SC_RPC_HANDLE hService,
 +    LPSERVICE_STATUS lpServiceStatus)
 +{
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService;
 +
 +    DPRINT("RQueryServiceStatus() called\n");
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_QUERY_STATUS))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    ScmLockDatabaseShared();
 +
 +    /* Return service status information */
 +    RtlCopyMemory(lpServiceStatus,
 +                  &lpService->Status,
 +                  sizeof(SERVICE_STATUS));
 +
 +    ScmUnlockDatabase();
 +
 +    return ERROR_SUCCESS;
 +}
 +
 +
 +static BOOL
 +ScmIsValidServiceState(DWORD dwCurrentState)
 +{
 +    switch (dwCurrentState)
 +    {
 +        case SERVICE_STOPPED:
 +        case SERVICE_START_PENDING:
 +        case SERVICE_STOP_PENDING:
 +        case SERVICE_RUNNING:
 +        case SERVICE_CONTINUE_PENDING:
 +        case SERVICE_PAUSE_PENDING:
 +        case SERVICE_PAUSED:
 +            return TRUE;
 +
 +        default:
 +            return FALSE;
 +    }
 +}
 +
 +
 +/* Function 7 */
 +DWORD RSetServiceStatus(
 +    RPC_SERVICE_STATUS_HANDLE hServiceStatus,
 +    LPSERVICE_STATUS lpServiceStatus)
 +{
 +    PSERVICE lpService;
 +
 +    DPRINT("RSetServiceStatus() called\n");
 +    DPRINT("hServiceStatus = %p\n", hServiceStatus);
 +    DPRINT("dwServiceType = %lu\n", lpServiceStatus->dwServiceType);
 +    DPRINT("dwCurrentState = %lu\n", lpServiceStatus->dwCurrentState);
 +    DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus->dwControlsAccepted);
 +    DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus->dwWin32ExitCode);
 +    DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus->dwServiceSpecificExitCode);
 +    DPRINT("dwCheckPoint = %lu\n", lpServiceStatus->dwCheckPoint);
 +    DPRINT("dwWaitHint = %lu\n", lpServiceStatus->dwWaitHint);
 +
 +    if (hServiceStatus == 0)
 +    {
 +        DPRINT("hServiceStatus == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    lpService = (PSERVICE)hServiceStatus;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* Check current state */
 +    if (!ScmIsValidServiceState(lpServiceStatus->dwCurrentState))
 +    {
 +        DPRINT("Invalid service state!\n");
 +        return ERROR_INVALID_DATA;
 +    }
 +
 +    /* Check service type */
 +    if (!(lpServiceStatus->dwServiceType & SERVICE_WIN32) &&
 +         (lpServiceStatus->dwServiceType & SERVICE_DRIVER))
 +    {
 +        DPRINT("Invalid service type!\n");
 +        return ERROR_INVALID_DATA;
 +    }
 +
 +    /* Check accepted controls */
 +    if (lpServiceStatus->dwControlsAccepted & ~0xFF)
 +    {
 +        DPRINT("Invalid controls accepted!\n");
 +        return ERROR_INVALID_DATA;
 +    }
 +
 +    ScmLockDatabaseExclusive();
 +
 +    RtlCopyMemory(&lpService->Status,
 +                  lpServiceStatus,
 +                  sizeof(SERVICE_STATUS));
 +
 +    ScmUnlockDatabase();
 +
 +    DPRINT("Set %S to %lu\n", lpService->lpDisplayName, lpService->Status.dwCurrentState);
 +    DPRINT("RSetServiceStatus() done\n");
 +
 +    return ERROR_SUCCESS;
 +}
 +
 +
 +/* Function 8 */
 +DWORD RUnlockServiceDatabase(
 +    LPSC_RPC_LOCK Lock)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_SUCCESS;
 +}
 +
 +
 +/* Function 9 */
 +DWORD RNotifyBootConfigStatus(
 +    SVCCTL_HANDLEW lpMachineName,
 +    DWORD BootAcceptable)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 10 */
 +DWORD RI_ScSetServiceBitsW(
 +    RPC_SERVICE_STATUS_HANDLE hServiceStatus,
 +    DWORD dwServiceBits,
 +    int bSetBitsOn,
 +    int bUpdateImmediately,
 +    wchar_t *lpString)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 11 */
 +DWORD RChangeServiceConfigW(
 +    SC_RPC_HANDLE hService,
 +    DWORD dwServiceType,
 +    DWORD dwStartType,
 +    DWORD dwErrorControl,
 +    LPWSTR lpBinaryPathName,
 +    LPWSTR lpLoadOrderGroup,
 +    LPDWORD lpdwTagId,
 +    LPBYTE lpDependencies,
 +    DWORD dwDependSize,
 +    LPWSTR lpServiceStartName,
 +    LPBYTE lpPassword,
 +    DWORD dwPwSize,
 +    LPWSTR lpDisplayName)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +    HKEY hServiceKey = NULL;
 +    LPWSTR lpDisplayNameW = NULL;
 +
 +    DPRINT("RChangeServiceConfigW() called\n");
 +    DPRINT("dwServiceType = %lu\n", dwServiceType);
 +    DPRINT("dwStartType = %lu\n", dwStartType);
 +    DPRINT("dwErrorControl = %lu\n", dwErrorControl);
 +    DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
 +    DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
 +    DPRINT("lpDisplayName = %S\n", lpDisplayName);
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_CHANGE_CONFIG))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* FIXME: Lock database exclusively */
 +
 +    if (lpService->bDeleted)
 +    {
 +        /* FIXME: Unlock database */
 +        DPRINT("The service has already been marked for delete!\n");
 +        return ERROR_SERVICE_MARKED_FOR_DELETE;
 +    }
 +
 +    /* Open the service key */
 +    dwError = ScmOpenServiceKey(lpService->szServiceName,
 +                                KEY_SET_VALUE,
 +                                &hServiceKey);
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    /* Write service data to the registry */
 +    /* Set the display name */
 +    if (lpDisplayName != NULL && *lpDisplayName != 0)
 +    {
 +        RegSetValueExW(hServiceKey,
 +                       L"DisplayName",
 +                       0,
 +                       REG_SZ,
 +                       (LPBYTE)lpDisplayName,
 +                       (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
 +
 +        /* Update the display name */
 +        lpDisplayNameW = (LPWSTR)HeapAlloc(GetProcessHeap(),
 +                                           0,
 +                                           (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
 +        if (lpDisplayNameW == NULL)
 +        {
 +            dwError = ERROR_NOT_ENOUGH_MEMORY;
 +            goto done;
 +        }
 +
 +        if (lpService->lpDisplayName != lpService->lpServiceName)
 +            HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
 +
 +        lpService->lpDisplayName = lpDisplayNameW;
 +    }
 +
 +    if (dwServiceType != SERVICE_NO_CHANGE)
 +    {
 +        /* Set the service type */
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"Type",
 +                                 0,
 +                                 REG_DWORD,
 +                                 (LPBYTE)&dwServiceType,
 +                                 sizeof(DWORD));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        lpService->Status.dwServiceType = dwServiceType;
 +    }
 +
 +    if (dwStartType != SERVICE_NO_CHANGE)
 +    {
 +        /* Set the start value */
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"Start",
 +                                 0,
 +                                 REG_DWORD,
 +                                 (LPBYTE)&dwStartType,
 +                                 sizeof(DWORD));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        lpService->dwStartType = dwStartType;
 +    }
 +
 +    if (dwErrorControl != SERVICE_NO_CHANGE)
 +    {
 +        /* Set the error control value */
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"ErrorControl",
 +                                 0,
 +                                 REG_DWORD,
 +                                 (LPBYTE)&dwErrorControl,
 +                                 sizeof(DWORD));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        lpService->dwErrorControl = dwErrorControl;
 +    }
 +
 +#if 0
 +    /* FIXME: set the new ImagePath value */
 +
 +    /* Set the image path */
 +    if (dwServiceType & SERVICE_WIN32)
 +    {
 +        if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
 +        {
 +            dwError = RegSetValueExW(hServiceKey,
 +                                     L"ImagePath",
 +                                     0,
 +                                     REG_EXPAND_SZ,
 +                                     (LPBYTE)lpBinaryPathName,
 +                                     (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
 +            if (dwError != ERROR_SUCCESS)
 +                goto done;
 +        }
 +    }
 +    else if (dwServiceType & SERVICE_DRIVER)
 +    {
 +        if (lpImagePath != NULL && *lpImagePath != 0)
 +        {
 +            dwError = RegSetValueExW(hServiceKey,
 +                                     L"ImagePath",
 +                                     0,
 +                                     REG_EXPAND_SZ,
 +                                     (LPBYTE)lpImagePath,
 +                                     (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
 +            if (dwError != ERROR_SUCCESS)
 +                goto done;
 +        }
 +    }
 +#endif
 +
 +    /* Set the group name */
 +    if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
 +    {
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"Group",
 +                                 0,
 +                                 REG_SZ,
 +                                 (LPBYTE)lpLoadOrderGroup,
 +                                 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        dwError = ScmSetServiceGroup(lpService,
 +                                     lpLoadOrderGroup);
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +
 +    if (lpdwTagId != NULL)
 +    {
 +        dwError = ScmAssignNewTag(lpService);
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"Tag",
 +                                 0,
 +                                 REG_DWORD,
 +                                 (LPBYTE)&lpService->dwTag,
 +                                 sizeof(DWORD));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        *lpdwTagId = lpService->dwTag;
 +    }
 +
 +    /* Write dependencies */
 +    if (lpDependencies != NULL && *lpDependencies != 0)
 +    {
 +        dwError = ScmWriteDependencies(hServiceKey,
 +                                       (LPWSTR)lpDependencies,
 +                                       dwDependSize);
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +
 +    if (lpPassword != NULL)
 +    {
 +        /* FIXME: Write password */
 +    }
 +
 +    /* FIXME: Unlock database */
 +
 +done:
 +    if (hServiceKey != NULL)
 +        RegCloseKey(hServiceKey);
 +
 +    DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Create a path suitable for the bootloader out of the full path */
 +DWORD
 +ScmConvertToBootPathName(wchar_t *CanonName, wchar_t **RelativeName)
 +{
 +    DWORD ServiceNameLen, BufferSize, ExpandedLen;
 +    WCHAR Dest;
 +    WCHAR *Expanded;
 +    UNICODE_STRING NtPathName, SystemRoot, LinkTarget;
 +    OBJECT_ATTRIBUTES ObjectAttributes;
 +    NTSTATUS Status;
 +    HANDLE SymbolicLinkHandle;
 +
 +    DPRINT("ScmConvertToBootPathName %S\n", CanonName);
 +
 +    ServiceNameLen = wcslen(CanonName);
 +
 +    /* First check, if it's already good */
 +    if (ServiceNameLen > 12 &&
 +        !_wcsnicmp(L"\\SystemRoot\\", CanonName, 12))
 +    {
 +        *RelativeName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
 +        if (*RelativeName == NULL)
 +        {
 +            DPRINT("Error allocating memory for boot driver name!\n");
 +            return ERROR_NOT_ENOUGH_MEMORY;
 +        }
 +
 +        /* Copy it */
 +        wcscpy(*RelativeName, CanonName);
 +
 +        DPRINT("Bootdriver name %S\n", *RelativeName);
 +        return ERROR_SUCCESS;
 +    }
 +
 +    /* If it has %SystemRoot% prefix, substitute it to \System*/
 +    if (ServiceNameLen > 13 &&
 +        !_wcsnicmp(L"%SystemRoot%\\", CanonName, 13))
 +    {
 +        /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
 +        *RelativeName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR));
 +
 +        if (*RelativeName == NULL)
 +        {
 +            DPRINT("Error allocating memory for boot driver name!\n");
 +            return ERROR_NOT_ENOUGH_MEMORY;
 +        }
 +
 +        /* Copy it */
 +        wcscpy(*RelativeName, L"\\SystemRoot\\");
 +        wcscat(*RelativeName, CanonName + 13);
 +
 +        DPRINT("Bootdriver name %S\n", *RelativeName);
 +        return ERROR_SUCCESS;
 +    }
 +
 +    /* Get buffer size needed for expanding env strings */
 +    BufferSize = ExpandEnvironmentStringsW(L"%SystemRoot%\\", &Dest, 1);
 +
 +    if (BufferSize <= 1)
 +    {
 +        DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
 +        return ERROR_INVALID_ENVIRONMENT;
 +    }
 +
 +    /* Allocate memory, since the size is known now */
 +    Expanded = LocalAlloc(LMEM_ZEROINIT, BufferSize * sizeof(WCHAR) + sizeof(WCHAR));
 +    if (!Expanded)
 +    {
 +        DPRINT("Error allocating memory for boot driver name!\n");
 +        return ERROR_NOT_ENOUGH_MEMORY;
 +    }
 +
 +    /* Expand it */
 +    if (ExpandEnvironmentStringsW(L"%SystemRoot%\\", Expanded, BufferSize) >
 +        BufferSize)
 +    {
 +        DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
 +        LocalFree(Expanded);
 +        return ERROR_NOT_ENOUGH_MEMORY;
 +    }
 +
 +    /* Convert to NY-style path */
 +    if (!RtlDosPathNameToNtPathName_U(Expanded, &NtPathName, NULL, NULL))
 +    {
 +        DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
 +        return ERROR_INVALID_ENVIRONMENT;
 +    }
 +
 +    DPRINT("Converted to NT-style %wZ\n", &NtPathName);
 +
 +    /* No need to keep the dos-path anymore */
 +    LocalFree(Expanded);
 +
 +    /* Copy it to the allocated place */
 +    Expanded = LocalAlloc(LMEM_ZEROINIT, NtPathName.Length + sizeof(WCHAR));
 +    if (!Expanded)
 +    {
 +            DPRINT("Error allocating memory for boot driver name!\n");
 +            return ERROR_NOT_ENOUGH_MEMORY;
 +    }
 +
 +    ExpandedLen = NtPathName.Length / sizeof(WCHAR);
 +    wcsncpy(Expanded, NtPathName.Buffer, ExpandedLen);
 +    Expanded[ExpandedLen] = 0;
 +
 +    if (ServiceNameLen > ExpandedLen &&
 +        !_wcsnicmp(Expanded, CanonName, ExpandedLen))
 +    {
 +        /* Only \SystemRoot\ is missing */
 +        *RelativeName = LocalAlloc(LMEM_ZEROINIT,
 +            (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR));
 +        if (*RelativeName == NULL)
 +        {
 +            DPRINT("Error allocating memory for boot driver name!\n");
 +            LocalFree(Expanded);
 +            return ERROR_NOT_ENOUGH_MEMORY;
 +        }
 +
 +        wcscpy(*RelativeName, L"\\SystemRoot\\");
 +        wcscat(*RelativeName, CanonName + ExpandedLen);
 +
 +        RtlFreeUnicodeString(&NtPathName);
 +        return ERROR_SUCCESS;
 +    }
 +
 +    /* The most complex case starts here */
 +    RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot");
 +    InitializeObjectAttributes(&ObjectAttributes,
 +                               &SystemRoot,
 +                               OBJ_CASE_INSENSITIVE,
 +                               NULL,
 +                               NULL);
 +
 +    /* Open this symlink */
 +    Status = NtOpenSymbolicLinkObject(&SymbolicLinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes);
 +
 +    if (NT_SUCCESS(Status))
 +    {
 +        LinkTarget.Length = 0;
 +        LinkTarget.MaximumLength = 0;
 +
 +        DPRINT("Opened symbolic link object\n");
 +
 +        Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize);
 +        if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_TOO_SMALL)
 +        {
 +            /* Check if required buffer size is sane */
 +            if (BufferSize > 0xFFFD)
 +            {
 +                DPRINT("Too large buffer required\n");
 +                *RelativeName = 0;
 +
 +                if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
 +                LocalFree(Expanded);
 +                return ERROR_NOT_ENOUGH_MEMORY;
 +            }
 +
 +            /* Alloc the string */
 +            LinkTarget.Buffer = LocalAlloc(LMEM_ZEROINIT, BufferSize + sizeof(WCHAR));
 +            if (!LinkTarget.Buffer)
 +            {
 +                DPRINT("Unable to alloc buffer\n");
 +                if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
 +                LocalFree(Expanded);
 +                return ERROR_NOT_ENOUGH_MEMORY;
 +            }
 +
 +            /* Do a real query now */
 +            LinkTarget.Length = BufferSize;
 +            LinkTarget.MaximumLength = LinkTarget.Length + sizeof(WCHAR);
 +
 +            Status = NtQuerySymbolicLinkObject(SymbolicLinkHandle, &LinkTarget, &BufferSize);
 +            if (NT_SUCCESS(Status))
 +            {
 +                DPRINT("LinkTarget: %wZ\n", &LinkTarget);
 +
 +                ExpandedLen = LinkTarget.Length / sizeof(WCHAR);
 +                if ((ServiceNameLen > ExpandedLen) &&
 +                    !_wcsnicmp(LinkTarget.Buffer, CanonName, ExpandedLen))
 +                {
 +                    *RelativeName = LocalAlloc(LMEM_ZEROINIT,
 +                       (ServiceNameLen - ExpandedLen) * sizeof(WCHAR) + 13*sizeof(WCHAR));
 +
 +                    if (*RelativeName == NULL)
 +                    {
 +                        DPRINT("Unable to alloc buffer\n");
 +                        if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
 +                        LocalFree(Expanded);
 +                        RtlFreeUnicodeString(&NtPathName);
 +                        return ERROR_NOT_ENOUGH_MEMORY;
 +                    }
 +
 +                    /* Copy it over, substituting the first part
 +                       with SystemRoot */
 +                    wcscpy(*RelativeName, L"\\SystemRoot\\");
 +                    wcscat(*RelativeName, CanonName+ExpandedLen+1);
 +
 +                    /* Cleanup */
 +                    if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
 +                    LocalFree(Expanded);
 +                    RtlFreeUnicodeString(&NtPathName);
 +
 +                    /* Return success */
 +                    return ERROR_SUCCESS;
 +                }
 +                else
 +                {
 +                    if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
 +                    LocalFree(Expanded);
 +                    RtlFreeUnicodeString(&NtPathName);
 +                    return ERROR_INVALID_PARAMETER;
 +                }
 +            }
 +            else
 +            {
 +                DPRINT("Error, Status = %08X\n", Status);
 +                if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
 +                LocalFree(Expanded);
 +                RtlFreeUnicodeString(&NtPathName);
 +                return ERROR_INVALID_PARAMETER;
 +            }
 +        }
 +        else
 +        {
 +            DPRINT("Error, Status = %08X\n", Status);
 +            if (SymbolicLinkHandle) NtClose(SymbolicLinkHandle);
 +            LocalFree(Expanded);
 +            RtlFreeUnicodeString(&NtPathName);
 +            return ERROR_INVALID_PARAMETER;
 +        }
 +    }
 +    else
 +    {
 +        DPRINT("Error, Status = %08X\n", Status);
 +        LocalFree(Expanded);
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    /* Failure */
 +    *RelativeName = NULL;
 +    return ERROR_INVALID_PARAMETER;
 +}
 +
 +DWORD
 +ScmCanonDriverImagePath(DWORD dwStartType,
 +                        const wchar_t *lpServiceName,
 +                        wchar_t **lpCanonName)
 +{
 +    DWORD ServiceNameLen, Result;
 +    UNICODE_STRING NtServiceName;
 +    WCHAR *RelativeName;
 +    const WCHAR *SourceName = lpServiceName;
 +
 +    /* Calculate the length of the service's name */
 +    ServiceNameLen = wcslen(lpServiceName);
 +
 +    /* 12 is wcslen(L"\\SystemRoot\\") */
 +    if (ServiceNameLen > 12 &&
 +        !_wcsnicmp(L"\\SystemRoot\\", lpServiceName, 12))
 +    {
 +        /* SystemRoot prefix is already included */
 +
 +        *lpCanonName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
 +
 +        if (*lpCanonName == NULL)
 +        {
 +            DPRINT("Error allocating memory for canonized service name!\n");
 +            return ERROR_NOT_ENOUGH_MEMORY;
 +        }
 +
 +        /* If it's a boot-time driver, it must be systemroot relative */
 +        if (dwStartType == SERVICE_BOOT_START)
 +            SourceName += 12;
 +
 +        /* Copy it */
 +        wcscpy(*lpCanonName, SourceName);
 +
 +        DPRINT("Canonicalized name %S\n", *lpCanonName);
 +        return NO_ERROR;
 +    }
 +
 +    /* Check if it has %SystemRoot% (len=13) */
 +    if (ServiceNameLen > 13 &&
 +        !_wcsnicmp(L"%%SystemRoot%%\\", lpServiceName, 13))
 +    {
 +        /* Substitute %SystemRoot% with \\SystemRoot\\ */
 +        *lpCanonName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
 +
 +        if (*lpCanonName == NULL)
 +        {
 +            DPRINT("Error allocating memory for canonized service name!\n");
 +            return ERROR_NOT_ENOUGH_MEMORY;
 +        }
 +
 +        /* If it's a boot-time driver, it must be systemroot relative */
 +        if (dwStartType == SERVICE_BOOT_START)
 +            wcscpy(*lpCanonName, L"\\SystemRoot\\");
 +
 +        wcscat(*lpCanonName, lpServiceName + 13);
 +
 +        DPRINT("Canonicalized name %S\n", *lpCanonName);
 +        return NO_ERROR;
 +    }
 +
 +    /* Check if it's a relative path name */
 +    if (lpServiceName[0] != L'\\' && lpServiceName[1] != L':')
 +    {
 +        *lpCanonName = LocalAlloc(LMEM_ZEROINIT, ServiceNameLen * sizeof(WCHAR) + sizeof(WCHAR));
 +
 +        if (*lpCanonName == NULL)
 +        {
 +            DPRINT("Error allocating memory for canonized service name!\n");
 +            return ERROR_NOT_ENOUGH_MEMORY;
 +        }
 +
 +        /* Just copy it over without changing */
 +        wcscpy(*lpCanonName, lpServiceName);
 +
 +        return NO_ERROR;
 +    }
 +
 +    /* It seems to be a DOS path, convert it */
 +    if (!RtlDosPathNameToNtPathName_U(lpServiceName, &NtServiceName, NULL, NULL))
 +    {
 +        DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    *lpCanonName = LocalAlloc(LMEM_ZEROINIT, NtServiceName.Length + sizeof(WCHAR));
 +
 +    if (*lpCanonName == NULL)
 +    {
 +        DPRINT("Error allocating memory for canonized service name!\n");
 +        RtlFreeUnicodeString(&NtServiceName);
 +        return ERROR_NOT_ENOUGH_MEMORY;
 +    }
 +
 +    /* Copy the string */
 +    wcsncpy(*lpCanonName, NtServiceName.Buffer, NtServiceName.Length / sizeof(WCHAR));
 +
 +    /* The unicode string is not needed anymore */
 +    RtlFreeUnicodeString(&NtServiceName);
 +
 +    if (dwStartType != SERVICE_BOOT_START)
 +    {
 +        DPRINT("Canonicalized name %S\n", *lpCanonName);
 +        return NO_ERROR;
 +    }
 +
 +    /* The service is boot-started, so must be relative */
 +    Result = ScmConvertToBootPathName(*lpCanonName, &RelativeName);
 +    if (Result)
 +    {
 +        /* There is a problem, free name and return */
 +        LocalFree(*lpCanonName);
 +        DPRINT("Error converting named!\n");
 +        return Result;
 +    }
 +
 +    ASSERT(RelativeName);
 +
 +    /* Copy that string */
 +    wcscpy(*lpCanonName, RelativeName + 12);
 +
 +    /* Free the allocated buffer */
 +    LocalFree(RelativeName);
 +
 +    DPRINT("Canonicalized name %S\n", *lpCanonName);
 +
 +    /* Success */
 +    return NO_ERROR;
 +}
 +
 +
 +/* Function 12 */
 +DWORD RCreateServiceW(
 +    SC_RPC_HANDLE hSCManager,
 +    LPCWSTR lpServiceName,
 +    LPCWSTR lpDisplayName,
 +    DWORD dwDesiredAccess,
 +    DWORD dwServiceType,
 +    DWORD dwStartType,
 +    DWORD dwErrorControl,
 +    LPCWSTR lpBinaryPathName,
 +    LPCWSTR lpLoadOrderGroup,
 +    LPDWORD lpdwTagId,
 +    LPBYTE lpDependencies,
 +    DWORD dwDependSize,
 +    LPCWSTR lpServiceStartName,
 +    LPBYTE lpPassword,
 +    DWORD dwPwSize,
 +    LPSC_RPC_HANDLE lpServiceHandle)
 +{
 +    PMANAGER_HANDLE hManager;
 +    DWORD dwError = ERROR_SUCCESS;
 +    PSERVICE lpService = NULL;
 +    SC_HANDLE hServiceHandle = NULL;
 +    LPWSTR lpImagePath = NULL;
 +    HKEY hServiceKey = NULL;
 +    LPWSTR lpObjectName;
 +
 +    DPRINT("RCreateServiceW() called\n");
 +    DPRINT("lpServiceName = %S\n", lpServiceName);
 +    DPRINT("lpDisplayName = %S\n", lpDisplayName);
 +    DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess);
 +    DPRINT("dwServiceType = %lu\n", dwServiceType);
 +    DPRINT("dwStartType = %lu\n", dwStartType);
 +    DPRINT("dwErrorControl = %lu\n", dwErrorControl);
 +    DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
 +    DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hManager = ScmGetServiceManagerFromHandle(hSCManager);
 +    if (hManager == NULL)
 +    {
 +        DPRINT1("Invalid service manager handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* Check access rights */
 +    if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
 +                                  SC_MANAGER_CREATE_SERVICE))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n",
 +               hManager->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    if (wcslen(lpServiceName) == 0)
 +    {
 +        return ERROR_INVALID_NAME;
 +    }
 +
 +    if (wcslen(lpBinaryPathName) == 0)
 +    {
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    if ((dwServiceType == (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) &&
 +        (lpServiceStartName))
 +    {
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    if ((dwServiceType > SERVICE_WIN32_SHARE_PROCESS) &&
 +        (dwServiceType != (SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS)) &&
 +        (dwServiceType != (SERVICE_WIN32_SHARE_PROCESS | SERVICE_INTERACTIVE_PROCESS)))
 +    {
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    if (dwStartType > SERVICE_DISABLED)
 +    {
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    lpService = ScmGetServiceEntryByName(lpServiceName);
 +    if (lpService)
 +    {
 +        /* check if it is marked for deletion */
 +        if (lpService->bDeleted)
 +            return ERROR_SERVICE_MARKED_FOR_DELETE;
 +        /* Return Error exist */
 +        return ERROR_SERVICE_EXISTS;
 +    }
 +
 +    if (lpDisplayName != NULL &&
 +        ScmGetServiceEntryByDisplayName(lpDisplayName) != NULL)
 +        return ERROR_DUPLICATE_SERVICE_NAME;
 +
 +    if (dwServiceType & SERVICE_DRIVER)
 +    {
 +        dwError = ScmCanonDriverImagePath(dwStartType,
 +                                          lpBinaryPathName,
 +                                          &lpImagePath);
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +    else
 +    {
 +        if (dwStartType == SERVICE_BOOT_START ||
 +            dwStartType == SERVICE_SYSTEM_START)
 +        {
 +            return ERROR_INVALID_PARAMETER;
 +        }
 +    }
 +
 +    /* Allocate a new service entry */
 +    dwError = ScmCreateNewServiceRecord(lpServiceName,
 +                                        &lpService);
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    /* Fill the new service entry */
 +    lpService->Status.dwServiceType = dwServiceType;
 +    lpService->dwStartType = dwStartType;
 +    lpService->dwErrorControl = dwErrorControl;
 +
 +    /* Fill the display name */
 +    if (lpDisplayName != NULL &&
 +        *lpDisplayName != 0 &&
 +        _wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
 +    {
 +        lpService->lpDisplayName = (WCHAR*) HeapAlloc(GetProcessHeap(), 0,
 +                                             (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
 +        if (lpService->lpDisplayName == NULL)
 +        {
 +            dwError = ERROR_NOT_ENOUGH_MEMORY;
 +            goto done;
 +        }
 +        wcscpy(lpService->lpDisplayName, lpDisplayName);
 +    }
 +
 +    /* Assign the service to a group */
 +    if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
 +    {
 +        dwError = ScmSetServiceGroup(lpService,
 +                                     lpLoadOrderGroup);
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +
 +    /* Assign a new tag */
 +    if (lpdwTagId != NULL)
 +    {
 +        dwError = ScmAssignNewTag(lpService);
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +
 +    /* Write service data to the registry */
 +    /* Create the service key */
 +    dwError = ScmCreateServiceKey(lpServiceName,
 +                                  KEY_WRITE,
 +                                  &hServiceKey);
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    /* Set the display name */
 +    if (lpDisplayName != NULL && *lpDisplayName != 0)
 +    {
 +        RegSetValueExW(hServiceKey,
 +                       L"DisplayName",
 +                       0,
 +                       REG_SZ,
 +                       (LPBYTE)lpDisplayName,
 +                       (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
 +    }
 +
 +    /* Set the service type */
 +    dwError = RegSetValueExW(hServiceKey,
 +                             L"Type",
 +                             0,
 +                             REG_DWORD,
 +                             (LPBYTE)&dwServiceType,
 +                             sizeof(DWORD));
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    /* Set the start value */
 +    dwError = RegSetValueExW(hServiceKey,
 +                             L"Start",
 +                             0,
 +                             REG_DWORD,
 +                             (LPBYTE)&dwStartType,
 +                             sizeof(DWORD));
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    /* Set the error control value */
 +    dwError = RegSetValueExW(hServiceKey,
 +                             L"ErrorControl",
 +                             0,
 +                             REG_DWORD,
 +                             (LPBYTE)&dwErrorControl,
 +                             sizeof(DWORD));
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    /* Set the image path */
 +    if (dwServiceType & SERVICE_WIN32)
 +    {
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"ImagePath",
 +                                 0,
 +                                 REG_EXPAND_SZ,
 +                                 (LPBYTE)lpBinaryPathName,
 +                                 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +    else if (dwServiceType & SERVICE_DRIVER)
 +    {
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"ImagePath",
 +                                 0,
 +                                 REG_EXPAND_SZ,
 +                                 (LPBYTE)lpImagePath,
 +                                 (wcslen(lpImagePath) + 1) * sizeof(WCHAR));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +
 +    /* Set the group name */
 +    if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
 +    {
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"Group",
 +                                 0,
 +                                 REG_SZ,
 +                                 (LPBYTE)lpLoadOrderGroup,
 +                                 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +
 +    if (lpdwTagId != NULL)
 +    {
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"Tag",
 +                                 0,
 +                                 REG_DWORD,
 +                                 (LPBYTE)&lpService->dwTag,
 +                                 sizeof(DWORD));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +
 +    /* Write dependencies */
 +    if (lpDependencies != NULL && *lpDependencies != 0)
 +    {
 +        dwError = ScmWriteDependencies(hServiceKey,
 +                                       (LPWSTR)lpDependencies,
 +                                       dwDependSize);
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +
 +    /* Write service start name */
 +    if (dwServiceType & SERVICE_WIN32)
 +    {
 +        lpObjectName = (lpServiceStartName != NULL) ? (LPWSTR)lpServiceStartName : L"LocalSystem";
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"ObjectName",
 +                                 0,
 +                                 REG_SZ,
 +                                 (LPBYTE)lpObjectName,
 +                                 (wcslen(lpObjectName) + 1) * sizeof(WCHAR));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +
 +    if (lpPassword != NULL)
 +    {
 +        /* FIXME: Write password */
 +    }
 +
 +    dwError = ScmCreateServiceHandle(lpService,
 +                                     &hServiceHandle);
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    dwError = ScmCheckAccess(hServiceHandle,
 +                             dwDesiredAccess);
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    lpService->dwRefCount = 1;
 +    DPRINT("CreateService - lpService->dwRefCount %u\n", lpService->dwRefCount);
 +
 +done:;
 +    if (hServiceKey != NULL)
 +        RegCloseKey(hServiceKey);
 +
 +    if (dwError == ERROR_SUCCESS)
 +    {
 +        DPRINT("hService %p\n", hServiceHandle);
 +        *lpServiceHandle = (SC_RPC_HANDLE)hServiceHandle;
 +
 +        if (lpdwTagId != NULL)
 +            *lpdwTagId = lpService->dwTag;
 +    }
 +    else
 +    {
 +        /* Release the display name buffer */
 +        if (lpService->lpServiceName != NULL)
 +            HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
 +
 +        if (hServiceHandle)
 +        {
 +            /* Remove the service handle */
 +            HeapFree(GetProcessHeap(), 0, hServiceHandle);
 +        }
 +
 +        if (lpService != NULL)
 +        {
 +            /* FIXME: remove the service entry */
 +        }
 +    }
 +
 +    if (lpImagePath != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpImagePath);
 +
 +    DPRINT("RCreateServiceW() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 13 */
 +DWORD REnumDependentServicesW(
 +    SC_RPC_HANDLE hService,
 +    DWORD dwServiceState,
 +    LPBYTE lpServices,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_256K pcbBytesNeeded,
 +    LPBOUNDED_DWORD_256K lpServicesReturned)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    DWORD dwServicesReturned = 0;
 +    DWORD dwServiceCount;
 +    HKEY hServicesKey = NULL;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +    PSERVICE *lpServicesArray = NULL;
 +    LPENUM_SERVICE_STATUSW lpServicesPtr = NULL;
 +    LPWSTR lpStr;
 +
 +    *pcbBytesNeeded = 0;
 +    *lpServicesReturned = 0;
 +
 +    DPRINT("REnumDependentServicesW() called\n");
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +
 +    /* Check access rights */
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SC_MANAGER_ENUMERATE_SERVICE))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n",
 +               hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    /* Open the Services Reg key */
 +    dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
 +                            L"System\\CurrentControlSet\\Services",
 +                            0,
 +                            KEY_READ,
 +                            &hServicesKey);
 +    if (dwError != ERROR_SUCCESS)
 +        return dwError;
 +
 +    /* First determine the bytes needed and get the number of dependent services */
 +    dwError = Int_EnumDependentServicesW(hServicesKey,
 +                                         lpService,
 +                                         dwServiceState,
 +                                         NULL,
 +                                         pcbBytesNeeded,
 +                                         &dwServicesReturned);
 +    if (dwError != ERROR_SUCCESS)
 +        goto Done;
 +
 +    /* If buffer size is less than the bytes needed or pointer is null */
 +    if ((!lpServices) || (cbBufSize < *pcbBytesNeeded))
 +    {
 +        dwError = ERROR_MORE_DATA;
 +        goto Done;
 +    }
 +
 +    /* Allocate memory for array of service pointers */
 +    lpServicesArray = HeapAlloc(GetProcessHeap(),
 +                                0,
 +                                (dwServicesReturned + 1) * sizeof(PSERVICE));
 +    if (!lpServicesArray)
 +    {
 +        DPRINT("Could not allocate a buffer!!\n");
 +        dwError = ERROR_NOT_ENOUGH_MEMORY;
 +        goto Done;
 +    }
 +
 +    dwServicesReturned = 0;
 +    *pcbBytesNeeded = 0;
 +
 +    dwError = Int_EnumDependentServicesW(hServicesKey,
 +                                         lpService,
 +                                         dwServiceState,
 +                                         lpServicesArray,
 +                                         pcbBytesNeeded,
 +                                         &dwServicesReturned);
 +    if (dwError != ERROR_SUCCESS)
 +    {
 +        goto Done;
 +    }
 +
 +    lpServicesPtr = (LPENUM_SERVICE_STATUSW) lpServices;
 +    lpStr = (LPWSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSW)));
 +
 +    /* Copy EnumDepenedentService to Buffer */
 +    for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++)
 +    {
 +        lpService = lpServicesArray[dwServiceCount];
 +
 +        /* Copy status info */
 +        memcpy(&lpServicesPtr->ServiceStatus,
 +               &lpService->Status,
 +               sizeof(SERVICE_STATUS));
 +
 +        /* Copy display name */
 +        wcscpy(lpStr, lpService->lpDisplayName);
 +        lpServicesPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
 +        lpStr += (wcslen(lpService->lpDisplayName) + 1);
 +
 +        /* Copy service name */
 +        wcscpy(lpStr, lpService->lpServiceName);
 +        lpServicesPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
 +        lpStr += (wcslen(lpService->lpServiceName) + 1);
 +
 +        lpServicesPtr ++;
 +    }
 +
 +    *lpServicesReturned = dwServicesReturned;
 +
 +Done:
 +    if (lpServicesArray != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpServicesArray);
 +
 +    RegCloseKey(hServicesKey);
 +
 +    DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 14 */
 +DWORD REnumServicesStatusW(
 +    SC_RPC_HANDLE hSCManager,
 +    DWORD dwServiceType,
 +    DWORD dwServiceState,
 +    LPBYTE lpBuffer,
 +    DWORD dwBufSize,
 +    LPBOUNDED_DWORD_256K pcbBytesNeeded,
 +    LPBOUNDED_DWORD_256K lpServicesReturned,
 +    LPBOUNDED_DWORD_256K lpResumeHandle)
 +{
 +    PMANAGER_HANDLE hManager;
 +    PSERVICE lpService;
 +    DWORD dwError = ERROR_SUCCESS;
 +    PLIST_ENTRY ServiceEntry;
 +    PSERVICE CurrentService;
 +    DWORD dwState;
 +    DWORD dwRequiredSize;
 +    DWORD dwServiceCount;
 +    DWORD dwSize;
 +    DWORD dwLastResumeCount = 0;
 +    LPENUM_SERVICE_STATUSW lpStatusPtr;
 +    LPWSTR lpStringPtr;
 +
 +    DPRINT("REnumServicesStatusW() called\n");
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hManager = ScmGetServiceManagerFromHandle(hSCManager);
 +    if (hManager == NULL)
 +    {
 +        DPRINT1("Invalid service manager handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +
 +    *pcbBytesNeeded = 0;
 +    *lpServicesReturned = 0;
 +
 +    if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
 +    {
 +        DPRINT("Not a valid Service Type!\n");
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
 +    {
 +        DPRINT("Not a valid Service State!\n");
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    /* Check access rights */
 +    if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
 +                                  SC_MANAGER_ENUMERATE_SERVICE))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n",
 +                hManager->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    if (lpResumeHandle)
 +        dwLastResumeCount = *lpResumeHandle;
 +
 +    /* FIXME: Lock the service list shared */
 +
 +    lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
 +    if (lpService == NULL)
 +    {
 +        dwError = ERROR_SUCCESS;
 +        goto Done;
 +    }
 +
 +    dwRequiredSize = 0;
 +    dwServiceCount = 0;
 +
 +    for (ServiceEntry = &lpService->ServiceListEntry;
 +         ServiceEntry != &ServiceListHead;
 +         ServiceEntry = ServiceEntry->Flink)
 +    {
 +        CurrentService = CONTAINING_RECORD(ServiceEntry,
 +                                           SERVICE,
 +                                           ServiceListEntry);
 +
 +        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
 +            continue;
 +
 +        dwState = SERVICE_ACTIVE;
 +        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
 +            dwState = SERVICE_INACTIVE;
 +
 +        if ((dwState & dwServiceState) == 0)
 +            continue;
 +
 +        dwSize = sizeof(ENUM_SERVICE_STATUSW) +
 +                 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
 +                 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
 +
 +        if (dwRequiredSize + dwSize > dwBufSize)
 +        {
 +            DPRINT("Service name: %S  no fit\n", CurrentService->lpServiceName);
 +            break;
 +        }
 +
 +        DPRINT("Service name: %S  fit\n", CurrentService->lpServiceName);
 +        dwRequiredSize += dwSize;
 +        dwServiceCount++;
 +        dwLastResumeCount = CurrentService->dwResumeCount;
 +    }
 +
 +    DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
 +    DPRINT("dwServiceCount: %lu\n", dwServiceCount);
 +
 +    for (;
 +         ServiceEntry != &ServiceListHead;
 +         ServiceEntry = ServiceEntry->Flink)
 +    {
 +        CurrentService = CONTAINING_RECORD(ServiceEntry,
 +                                           SERVICE,
 +                                           ServiceListEntry);
 +
 +        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
 +            continue;
 +
 +        dwState = SERVICE_ACTIVE;
 +        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
 +            dwState = SERVICE_INACTIVE;
 +
 +        if ((dwState & dwServiceState) == 0)
 +            continue;
 +
 +        dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
 +                           ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
 +                           ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
 +
 +        dwError = ERROR_MORE_DATA;
 +    }
 +
 +    DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
 +
 +    if (lpResumeHandle)
 +        *lpResumeHandle = dwLastResumeCount;
 +
 +    *lpServicesReturned = dwServiceCount;
 +    *pcbBytesNeeded = dwRequiredSize;
 +
 +    lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpBuffer;
 +    lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
 +                           dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
 +
 +    dwRequiredSize = 0;
 +    for (ServiceEntry = &lpService->ServiceListEntry;
 +         ServiceEntry != &ServiceListHead;
 +         ServiceEntry = ServiceEntry->Flink)
 +    {
 +        CurrentService = CONTAINING_RECORD(ServiceEntry,
 +                                           SERVICE,
 +                                           ServiceListEntry);
 +
 +        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
 +            continue;
 +
 +        dwState = SERVICE_ACTIVE;
 +        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
 +            dwState = SERVICE_INACTIVE;
 +
 +        if ((dwState & dwServiceState) == 0)
 +            continue;
 +
 +        dwSize = sizeof(ENUM_SERVICE_STATUSW) +
 +                 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
 +                 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
 +
 +        if (dwRequiredSize + dwSize > dwBufSize)
 +            break;
 +
 +        /* Copy the service name */
 +        wcscpy(lpStringPtr, CurrentService->lpServiceName);
 +        lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
 +        lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
 +
 +        /* Copy the display name */
 +        wcscpy(lpStringPtr, CurrentService->lpDisplayName);
 +        lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
 +        lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
 +
 +        /* Copy the status information */
 +        memcpy(&lpStatusPtr->ServiceStatus,
 +               &CurrentService->Status,
 +               sizeof(SERVICE_STATUS));
 +
 +        lpStatusPtr++;
 +        dwRequiredSize += dwSize;
 +    }
 +
 +    if (dwError == 0) 
 +    {
 +        *pcbBytesNeeded = 0;
 +        if (lpResumeHandle) *lpResumeHandle = 0;
 +    }
 +
 +Done:;
 +    /* FIXME: Unlock the service list */
 +
 +    DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 15 */
 +DWORD ROpenSCManagerW(
 +    LPWSTR lpMachineName,
 +    LPWSTR lpDatabaseName,
 +    DWORD dwDesiredAccess,
 +    LPSC_RPC_HANDLE lpScHandle)
 +{
 +    DWORD dwError;
 +    SC_HANDLE hHandle;
 +
 +    DPRINT("ROpenSCManagerW() called\n");
 +    DPRINT("lpMachineName = %p\n", lpMachineName);
 +    DPRINT("lpMachineName: %S\n", lpMachineName);
 +    DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
 +    DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
 +    DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    if (!lpScHandle)
 +        return ERROR_INVALID_PARAMETER;
 +
 +    dwError = ScmCreateManagerHandle(lpDatabaseName,
 +                                     &hHandle);
 +    if (dwError != ERROR_SUCCESS)
 +    {
 +        DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
 +        return dwError;
 +    }
 +
 +    /* Check the desired access */
 +    dwError = ScmCheckAccess(hHandle,
 +                             dwDesiredAccess | SC_MANAGER_CONNECT);
 +    if (dwError != ERROR_SUCCESS)
 +    {
 +        DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError);
 +        HeapFree(GetProcessHeap(), 0, hHandle);
 +        return dwError;
 +    }
 +
 +    *lpScHandle = (SC_RPC_HANDLE)hHandle;
 +    DPRINT("*hScm = %p\n", *lpScHandle);
 +
 +    DPRINT("ROpenSCManagerW() done\n");
 +
 +    return ERROR_SUCCESS;
 +}
 +
 +
 +/* Function 16 */
 +DWORD ROpenServiceW(
 +    SC_RPC_HANDLE hSCManager,
 +    LPWSTR lpServiceName,
 +    DWORD dwDesiredAccess,
 +    LPSC_RPC_HANDLE lpServiceHandle)
 +{
 +    PSERVICE lpService;
 +    PMANAGER_HANDLE hManager;
 +    SC_HANDLE hHandle;
 +    DWORD dwError;
 +
 +    DPRINT("ROpenServiceW() called\n");
 +    DPRINT("hSCManager = %p\n", hSCManager);
 +    DPRINT("lpServiceName = %p\n", lpServiceName);
 +    DPRINT("lpServiceName: %S\n", lpServiceName);
 +    DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hManager = ScmGetServiceManagerFromHandle(hSCManager);
 +    if (hManager == NULL)
 +    {
 +        DPRINT1("Invalid service manager handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!lpServiceHandle)
 +        return ERROR_INVALID_PARAMETER;
 +
 +    if (!lpServiceName)
 +        return ERROR_INVALID_ADDRESS;
 +
 +    /* FIXME: Lock the service list */
 +
 +    /* Get service database entry */
 +    lpService = ScmGetServiceEntryByName(lpServiceName);
 +    if (lpService == NULL)
 +    {
 +        DPRINT("Could not find a service!\n");
 +        return ERROR_SERVICE_DOES_NOT_EXIST;
 +    }
 +
 +    /* Create a service handle */
 +    dwError = ScmCreateServiceHandle(lpService,
 +                                     &hHandle);
 +    if (dwError != ERROR_SUCCESS)
 +    {
 +        DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
 +        return dwError;
 +    }
 +
 +    /* Check the desired access */
 +    dwError = ScmCheckAccess(hHandle,
 +                             dwDesiredAccess);
 +    if (dwError != ERROR_SUCCESS)
 +    {
 +        DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError);
 +        HeapFree(GetProcessHeap(), 0, hHandle);
 +        return dwError;
 +    }
 +
 +    lpService->dwRefCount++;
 +    DPRINT("OpenService - lpService->dwRefCount %u\n",lpService->dwRefCount);
 +
 +    *lpServiceHandle = (SC_RPC_HANDLE)hHandle;
 +    DPRINT("*hService = %p\n", *lpServiceHandle);
 +
 +    DPRINT("ROpenServiceW() done\n");
 +
 +    return ERROR_SUCCESS;
 +}
 +
 +
 +/* Function 17 */
 +DWORD RQueryServiceConfigW(
 +    SC_RPC_HANDLE hService,
 +    LPQUERY_SERVICE_CONFIGW lpServiceConfig,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_8K pcbBytesNeeded)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +    HKEY hServiceKey = NULL;
 +    LPWSTR lpImagePath = NULL;
 +    LPWSTR lpServiceStartName = NULL;
 +    LPWSTR lpDependencies = NULL;
 +    DWORD dwDependenciesLength = 0;
 +    DWORD dwRequiredSize;
 +    LPQUERY_SERVICE_CONFIGW lpConfig = NULL;
 +    WCHAR lpEmptyString[] = {0,0};
 +    LPWSTR lpStr;
 +
 +    DPRINT("RQueryServiceConfigW() called\n");
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_QUERY_CONFIG))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* FIXME: Lock the service database shared */
 +
 +    dwError = ScmOpenServiceKey(lpService->lpServiceName,
 +                                KEY_READ,
 +                                &hServiceKey);
 +    if (dwError != ERROR_SUCCESS)
 +        goto Done;
 +
 +    /* Read the image path */
 +    dwError = ScmReadString(hServiceKey,
 +                            L"ImagePath",
 +                            &lpImagePath);
 +    if (dwError != ERROR_SUCCESS)
 +        goto Done;
 +
 +    /* Read the service start name */
 +    ScmReadString(hServiceKey,
 +                  L"ObjectName",
 +                  &lpServiceStartName);
 +
 +    /* Read the dependencies */
 +    ScmReadDependencies(hServiceKey,
 +                        &lpDependencies,
 +                        &dwDependenciesLength);
 +
 +    dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
 +
 +    if (lpImagePath != NULL)
 +        dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
 +    else
 +        dwRequiredSize += 2 * sizeof(WCHAR);
 +
 +    if (lpService->lpGroup != NULL)
 +        dwRequiredSize += ((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR));
 +    else
 +        dwRequiredSize += 2 * sizeof(WCHAR);
 +
 +    if (lpDependencies != NULL)
 +        dwRequiredSize += dwDependenciesLength * sizeof(WCHAR);
 +    else
 +        dwRequiredSize += 2 * sizeof(WCHAR);
 +
 +    if (lpServiceStartName != NULL)
 +        dwRequiredSize += ((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
 +    else
 +        dwRequiredSize += 2 * sizeof(WCHAR);
 +
 +    if (lpService->lpDisplayName != NULL)
 +        dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
 +    else
 +        dwRequiredSize += 2 * sizeof(WCHAR);
 +
 +    if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
 +    {
 +        dwError = ERROR_INSUFFICIENT_BUFFER;
 +    }
 +    else
 +    {
 +        lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig;
 +        lpConfig->dwServiceType = lpService->Status.dwServiceType;
 +        lpConfig->dwStartType = lpService->dwStartType;
 +        lpConfig->dwErrorControl = lpService->dwErrorControl;
 +        lpConfig->dwTagId = lpService->dwTag;
 +
 +        lpStr = (LPWSTR)(lpConfig + 1);
 +
 +        /* Append the image path */
 +        if (lpImagePath != NULL)
 +        {
 +            wcscpy(lpStr, lpImagePath);
 +        }
 +        else
 +        {
 +            wcscpy(lpStr, lpEmptyString);
 +        }
 +
 +        lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
 +        lpStr += (wcslen(lpStr) + 1);
 +
 +        /* Append the group name */
 +        if (lpService->lpGroup != NULL)
 +        {
 +            wcscpy(lpStr, lpService->lpGroup->lpGroupName);
 +        }
 +        else
 +        {
 +            wcscpy(lpStr, lpEmptyString);
 +        }
 +
 +        lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
 +        lpStr += (wcslen(lpStr) + 1);
 +
 +        /* Append Dependencies */
 +        if (lpDependencies != NULL)
 +        {
 +            memcpy(lpStr,
 +                   lpDependencies,
 +                   dwDependenciesLength * sizeof(WCHAR));
 +        }
 +        else
 +        {
 +            wcscpy(lpStr, lpEmptyString);
 +        }
 +
 +        lpConfig->lpDependencies = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
 +        if (lpDependencies != NULL)
 +            lpStr += dwDependenciesLength * sizeof(WCHAR);
 +        else
 +            lpStr += (wcslen(lpStr) + 1);
 +
 +        /* Append the service start name */
 +        if (lpServiceStartName != NULL)
 +        {
 +            wcscpy(lpStr, lpServiceStartName);
 +        }
 +        else
 +        {
 +            wcscpy(lpStr, lpEmptyString);
 +        }
 +
 +        lpConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
 +        lpStr += (wcslen(lpStr) + 1);
 +
 +        /* Append the display name */
 +        if (lpService->lpDisplayName != NULL)
 +        {
 +            wcscpy(lpStr, lpService->lpDisplayName);
 +        }
 +        else
 +        {
 +            wcscpy(lpStr, lpEmptyString);
 +        }
 +
 +        lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
 +    }
 +
 +    if (pcbBytesNeeded != NULL)
 +        *pcbBytesNeeded = dwRequiredSize;
 +
 +Done:;
 +    if (lpImagePath != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpImagePath);
 +
 +    if (lpServiceStartName != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpServiceStartName);
 +
 +    if (lpDependencies != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpDependencies);
 +
 +    if (hServiceKey != NULL)
 +        RegCloseKey(hServiceKey);
 +
 +    /* FIXME: Unlock the service database */
 +
 +    DPRINT("RQueryServiceConfigW() done\n");
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 18 */
 +DWORD RQueryServiceLockStatusW(
 +    SC_RPC_HANDLE hSCManager,
 +    LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_4K pcbBytesNeeded)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 19 */
 +DWORD RStartServiceW(
 +    SC_RPC_HANDLE hService,
 +    DWORD argc,
 +    LPSTRING_PTRSW argv)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +
 +    DPRINT("RStartServiceW() called\n");
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_START))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (lpService->dwStartType == SERVICE_DISABLED)
 +        return ERROR_SERVICE_DISABLED;
 +
 +    if (lpService->bDeleted)
 +        return ERROR_SERVICE_MARKED_FOR_DELETE;
 +
 +    if (argv) {
 +        UNIMPLEMENTED;
 +        argv = NULL;
 +    }
 +
 +    /* Start the service */
 +    dwError = ScmStartService(lpService, argc, (LPWSTR *)argv);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 20 */
 +DWORD RGetServiceDisplayNameW(
 +    SC_RPC_HANDLE hSCManager,
 +    LPCWSTR lpServiceName,
 +    LPWSTR lpDisplayName,
 +    DWORD *lpcchBuffer)
 +{
 +//    PMANAGER_HANDLE hManager;
 +    PSERVICE lpService;
 +    DWORD dwLength;
 +    DWORD dwError;
 +
 +    DPRINT("RGetServiceDisplayNameW() called\n");
 +    DPRINT("hSCManager = %p\n", hSCManager);
 +    DPRINT("lpServiceName: %S\n", lpServiceName);
 +    DPRINT("lpDisplayName: %p\n", lpDisplayName);
 +    DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
 +
 +//    hManager = (PMANAGER_HANDLE)hSCManager;
 +//    if (hManager->Handle.Tag != MANAGER_TAG)
 +//    {
 +//        DPRINT("Invalid manager handle!\n");
 +//        return ERROR_INVALID_HANDLE;
 +//    }
 +
 +    /* Get service database entry */
 +    lpService = ScmGetServiceEntryByName(lpServiceName);
 +    if (lpService == NULL)
 +    {
 +        DPRINT("Could not find a service!\n");
 +
 +        /* If the service could not be found and lpcchBuffer is less than 2, windows
 +           puts null in lpDisplayName and puts 2 in lpcchBuffer */
 +        if (*lpcchBuffer < 2)
 +        {
 +            *lpcchBuffer = 2;
 +            if (lpDisplayName != NULL)
 +            {
 +                *lpDisplayName = '\0';
 +            }
 +        }
 +
 +        return ERROR_SERVICE_DOES_NOT_EXIST;
 +    }
 +
 +    if (!lpService->lpDisplayName)
 +    {
 +        dwLength = wcslen(lpService->lpServiceName);
 +
 +        if (lpDisplayName != NULL &&
 +            *lpcchBuffer > dwLength)
 +        {
 +            wcscpy(lpDisplayName, lpService->lpServiceName);
 +        }
 +    }
 +    else
 +    {
 +        dwLength = wcslen(lpService->lpDisplayName);
 +
 +        if (lpDisplayName != NULL &&
 +            *lpcchBuffer > dwLength)
 +        {
 +            wcscpy(lpDisplayName, lpService->lpDisplayName);
 +        }
 +    }
 +
 +    dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
 +
 +    *lpcchBuffer = dwLength;
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 21 */
 +DWORD RGetServiceKeyNameW(
 +    SC_RPC_HANDLE hSCManager,
 +    LPCWSTR lpDisplayName,
 +    LPWSTR lpServiceName,
 +    DWORD *lpcchBuffer)
 +{
 +//    PMANAGER_HANDLE hManager;
 +    PSERVICE lpService;
 +    DWORD dwLength;
 +    DWORD dwError;
 +
 +    DPRINT("RGetServiceKeyNameW() called\n");
 +    DPRINT("hSCManager = %p\n", hSCManager);
 +    DPRINT("lpDisplayName: %S\n", lpDisplayName);
 +    DPRINT("lpServiceName: %p\n", lpServiceName);
 +    DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
 +
 +//    hManager = (PMANAGER_HANDLE)hSCManager;
 +//    if (hManager->Handle.Tag != MANAGER_TAG)
 +//    {
 +//        DPRINT("Invalid manager handle!\n");
 +//        return ERROR_INVALID_HANDLE;
 +//    }
 +
 +    /* Get service database entry */
 +    lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
 +    if (lpService == NULL)
 +    {
 +        DPRINT("Could not find a service!\n");
 +
 +        /* If the service could not be found and lpcchBuffer is less than 2, windows
 +           puts null in lpDisplayName and puts 2 in lpcchBuffer */
 +        if (*lpcchBuffer < 2)
 +        {
 +            *lpcchBuffer = 2;
 +            if (lpServiceName != NULL)
 +            {
 +                *lpServiceName = '\0';
 +            }
 +        }
 +
 +        return ERROR_SERVICE_DOES_NOT_EXIST;
 +    }
 +
 +    dwLength = wcslen(lpService->lpServiceName);
 +
 +    if (lpServiceName != NULL &&
 +        *lpcchBuffer > dwLength)
 +    {
 +        wcscpy(lpServiceName, lpService->lpServiceName);
 +        *lpcchBuffer = dwLength;
 +        return ERROR_SUCCESS;
 +    }
 +
 +    dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
 +
 +    *lpcchBuffer = dwLength;
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 22 */
 +DWORD RI_ScSetServiceBitsA(
 +    RPC_SERVICE_STATUS_HANDLE hServiceStatus,
 +    DWORD dwServiceBits,
 +    int bSetBitsOn,
 +    int bUpdateImmediately,
 +    char *lpString)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 23 */
 +DWORD RChangeServiceConfigA(
 +    SC_RPC_HANDLE hService,
 +    DWORD dwServiceType,
 +    DWORD dwStartType,
 +    DWORD dwErrorControl,
 +    LPSTR lpBinaryPathName,
 +    LPSTR lpLoadOrderGroup,
 +    LPDWORD lpdwTagId,
 +    LPSTR lpDependencies,
 +    DWORD dwDependSize,
 +    LPSTR lpServiceStartName,
 +    LPBYTE lpPassword,
 +    DWORD dwPwSize,
 +    LPSTR lpDisplayName)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +    HKEY hServiceKey = NULL;
 +    LPWSTR lpDisplayNameW = NULL;
 +    // LPWSTR lpBinaryPathNameW = NULL;
 +    LPWSTR lpLoadOrderGroupW = NULL;
 +    LPWSTR lpDependenciesW = NULL;
 +    // LPWSTR lpPasswordW = NULL;
 +
 +    DPRINT("RChangeServiceConfigA() called\n");
 +    DPRINT("dwServiceType = %lu\n", dwServiceType);
 +    DPRINT("dwStartType = %lu\n", dwStartType);
 +    DPRINT("dwErrorControl = %lu\n", dwErrorControl);
 +    DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName);
 +    DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup);
 +    DPRINT("lpDisplayName = %s\n", lpDisplayName);
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_CHANGE_CONFIG))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* FIXME: Lock database exclusively */
 +
 +    if (lpService->bDeleted)
 +    {
 +        /* FIXME: Unlock database */
 +        DPRINT("The service has already been marked for delete!\n");
 +        return ERROR_SERVICE_MARKED_FOR_DELETE;
 +    }
 +
 +    /* Open the service key */
 +    dwError = ScmOpenServiceKey(lpService->szServiceName,
 +                                KEY_SET_VALUE,
 +                                &hServiceKey);
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    /* Write service data to the registry */
 +
 +    if (lpDisplayName != NULL && *lpDisplayName != 0)
 +    {
 +        /* Set the display name */
 +        lpDisplayNameW = HeapAlloc(GetProcessHeap(),
 +                                   0,
 +                                   (strlen(lpDisplayName) + 1) * sizeof(WCHAR));
 +        if (lpDisplayNameW == NULL)
 +        {
 +            dwError = ERROR_NOT_ENOUGH_MEMORY;
 +            goto done;
 +        }
 +
 +        MultiByteToWideChar(CP_ACP,
 +                            0,
 +                            lpDisplayName,
 +                            -1,
 +                            lpDisplayNameW,
 +                            strlen(lpDisplayName) + 1);
 +
 +        RegSetValueExW(hServiceKey,
 +                       L"DisplayName",
 +                       0,
 +                       REG_SZ,
 +                       (LPBYTE)lpDisplayNameW,
 +                       (wcslen(lpDisplayNameW) + 1) * sizeof(WCHAR));
 +
 +        /* Update lpService->lpDisplayName */
 +        if (lpService->lpDisplayName)
 +            HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
 +
 +        lpService->lpDisplayName = lpDisplayNameW;
 +    }
 +
 +    if (dwServiceType != SERVICE_NO_CHANGE)
 +    {
 +        /* Set the service type */
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"Type",
 +                                 0,
 +                                 REG_DWORD,
 +                                 (LPBYTE)&dwServiceType,
 +                                 sizeof(DWORD));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        lpService->Status.dwServiceType = dwServiceType;
 +    }
 +
 +    if (dwStartType != SERVICE_NO_CHANGE)
 +    {
 +        /* Set the start value */
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"Start",
 +                                 0,
 +                                 REG_DWORD,
 +                                 (LPBYTE)&dwStartType,
 +                                 sizeof(DWORD));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        lpService->dwStartType = dwStartType;
 +    }
 +
 +    if (dwErrorControl != SERVICE_NO_CHANGE)
 +    {
 +        /* Set the error control value */
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"ErrorControl",
 +                                 0,
 +                                 REG_DWORD,
 +                                 (LPBYTE)&dwErrorControl,
 +                                 sizeof(DWORD));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        lpService->dwErrorControl = dwErrorControl;
 +    }
 +
 +#if 0
 +    /* FIXME: set the new ImagePath value */
 +
 +    /* Set the image path */
 +    if (dwServiceType & SERVICE_WIN32)
 +    {
 +        if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
 +        {
 +            lpBinaryPathNameW=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName)+1) * sizeof(WCHAR));
 +            MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, strlen(lpBinaryPathName)+1);
 +            dwError = RegSetValueExW(hServiceKey,
 +                                     L"ImagePath",
 +                                     0,
 +                                     REG_EXPAND_SZ,
 +                                     (LPBYTE)lpBinaryPathNameW,
 +                                     (wcslen(lpBinaryPathNameW) + 1) * sizeof(WCHAR));
 +            if (dwError != ERROR_SUCCESS)
 +                goto done;
 +        }
 +    }
 +    else if (dwServiceType & SERVICE_DRIVER)
 +    {
 +        if (lpImagePath != NULL && *lpImagePath != 0)
 +        {
 +            dwError = RegSetValueExW(hServiceKey,
 +                                     L"ImagePath",
 +                                     0,
 +                                     REG_EXPAND_SZ,
 +                                     (LPBYTE)lpImagePath,
 +                                     (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
 +            if (dwError != ERROR_SUCCESS)
 +                goto done;
 +        }
 +    }
 +#endif
 +
 +    /* Set the group name */
 +    if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
 +    {
 +        lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(),
 +                                      0,
 +                                      (strlen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
 +        if (lpLoadOrderGroupW == NULL)
 +        {
 +            dwError = ERROR_NOT_ENOUGH_MEMORY;
 +            goto done;
 +        }
 +
 +        MultiByteToWideChar(CP_ACP,
 +                            0,
 +                            lpLoadOrderGroup,
 +                            -1,
 +                            lpLoadOrderGroupW,
 +                            strlen(lpLoadOrderGroup) + 1);
 +
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"Group",
 +                                 0,
 +                                 REG_SZ,
 +                                 (LPBYTE)lpLoadOrderGroupW,
 +                                 (wcslen(lpLoadOrderGroupW) + 1) * sizeof(WCHAR));
 +        if (dwError != ERROR_SUCCESS)
 +        {
 +            HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
 +            goto done;
 +        }
 +
 +        dwError = ScmSetServiceGroup(lpService,
 +                                     lpLoadOrderGroupW);
 +
 +        HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
 +
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +    }
 +
 +    if (lpdwTagId != NULL)
 +    {
 +        dwError = ScmAssignNewTag(lpService);
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        dwError = RegSetValueExW(hServiceKey,
 +                                 L"Tag",
 +                                 0,
 +                                 REG_DWORD,
 +                                 (LPBYTE)&lpService->dwTag,
 +                                 sizeof(DWORD));
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        *lpdwTagId = lpService->dwTag;
 +    }
 +
 +    /* Write dependencies */
 +    if (lpDependencies != NULL && *lpDependencies != 0)
 +    {
 +        lpDependenciesW = HeapAlloc(GetProcessHeap(),
 +                                    0,
 +                                    (strlen(lpDependencies) + 1) * sizeof(WCHAR));
 +        if (lpDependenciesW == NULL)
 +        {
 +            dwError = ERROR_NOT_ENOUGH_MEMORY;
 +            goto done;
 +        }
 +
 +        MultiByteToWideChar(CP_ACP,
 +                            0,
 +                            lpDependencies,
 +                            dwDependSize,
 +                            lpDependenciesW,
 +                            strlen(lpDependencies) + 1);
 +
 +        dwError = ScmWriteDependencies(hServiceKey,
 +                                       (LPWSTR)lpDependenciesW,
 +                                       dwDependSize);
 +
 +        HeapFree(GetProcessHeap(), 0, lpDependenciesW);
 +    }
 +
 +    if (lpPassword != NULL)
 +    {
 +        /* FIXME: Write password */
 +    }
 +
 +    /* FIXME: Unlock database */
 +
 +done:
 +    if (hServiceKey != NULL)
 +        RegCloseKey(hServiceKey);
 +
 +    DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 24 */
 +DWORD RCreateServiceA(
 +    SC_RPC_HANDLE hSCManager,
 +    LPSTR lpServiceName,
 +    LPSTR lpDisplayName,
 +    DWORD dwDesiredAccess,
 +    DWORD dwServiceType,
 +    DWORD dwStartType,
 +    DWORD dwErrorControl,
 +    LPSTR lpBinaryPathName,
 +    LPSTR lpLoadOrderGroup,
 +    LPDWORD lpdwTagId,
 +    LPBYTE lpDependencies,
 +    DWORD dwDependSize,
 +    LPSTR lpServiceStartName,
 +    LPBYTE lpPassword,
 +    DWORD dwPwSize,
 +    LPSC_RPC_HANDLE lpServiceHandle)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    LPWSTR lpServiceNameW = NULL;
 +    LPWSTR lpDisplayNameW = NULL;
 +    LPWSTR lpBinaryPathNameW = NULL;
 +    LPWSTR lpLoadOrderGroupW = NULL;
 +    LPWSTR lpDependenciesW = NULL;
 +    LPWSTR lpServiceStartNameW = NULL;
 +    DWORD dwDependenciesLength = 0;
 +    DWORD dwLength;
 +    int len;
 +    LPSTR lpStr;
 +
 +    if (lpServiceName)
 +    {
 +        len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0);
 +        lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +        if (!lpServiceNameW)
 +        {
 +            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
 +            goto cleanup;
 +        }
 +        MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len);
 +    }
 +
 +    if (lpDisplayName)
 +    {
 +        len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0);
 +        lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +        if (!lpDisplayNameW)
 +        {
 +            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
 +            goto cleanup;
 +        }
 +        MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
 +    }
 +
 +    if (lpBinaryPathName)
 +    {
 +        len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
 +        lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +        if (!lpBinaryPathNameW)
 +        {
 +            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
 +            goto cleanup;
 +        }
 +        MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len);
 +    }
 +
 +    if (lpLoadOrderGroup)
 +    {
 +        len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
 +        lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +        if (!lpLoadOrderGroupW)
 +        {
 +            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
 +            goto cleanup;
 +        }
 +        MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
 +    }
 +
 +    if (lpDependencies)
 +    {
 +        lpStr = (LPSTR)lpDependencies;
 +        while (*lpStr)
 +        {
 +            dwLength = strlen(lpStr) + 1;
 +            dwDependenciesLength += dwLength;
 +            lpStr = lpStr + dwLength;
 +        }
 +        dwDependenciesLength++;
 +
 +        lpDependenciesW = HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength * sizeof(WCHAR));
 +        if (!lpDependenciesW)
 +        {
 +            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
 +            goto cleanup;
 +        }
 +        MultiByteToWideChar(CP_ACP, 0, (LPSTR)lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
 +    }
 +
 +    if (lpServiceStartName)
 +    {
 +        len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
 +        lpServiceStartNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
 +        if (!lpServiceStartNameW)
 +        {
 +            SetLastError(ERROR_NOT_ENOUGH_MEMORY);
 +            goto cleanup;
 +        }
 +        MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
 +    }
 +
 +    dwError = RCreateServiceW(hSCManager,
 +                              lpServiceNameW,
 +                              lpDisplayNameW,
 +                              dwDesiredAccess,
 +                              dwServiceType,
 +                              dwStartType,
 +                              dwErrorControl,
 +                              lpBinaryPathNameW,
 +                              lpLoadOrderGroupW,
 +                              lpdwTagId,
 +                              (LPBYTE)lpDependenciesW,
 +                              dwDependenciesLength,
 +                              lpServiceStartNameW,
 +                              lpPassword,
 +                              dwPwSize,
 +                              lpServiceHandle);
 +
 +cleanup:
 +    if (lpServiceNameW !=NULL)
 +        HeapFree(GetProcessHeap(), 0, lpServiceNameW);
 +
 +    if (lpDisplayNameW != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
 +
 +    if (lpBinaryPathNameW != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
 +
 +    if (lpLoadOrderGroupW != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
 +
 +    if (lpDependenciesW != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpDependenciesW);
 +
 +    if (lpServiceStartNameW != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 25 */
 +DWORD REnumDependentServicesA(
 +    SC_RPC_HANDLE hService,
 +    DWORD dwServiceState,
 +    LPBYTE lpServices,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_256K pcbBytesNeeded,
 +    LPBOUNDED_DWORD_256K lpServicesReturned)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    DWORD dwServicesReturned = 0;
 +    DWORD dwServiceCount;
 +    HKEY hServicesKey = NULL;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +    PSERVICE *lpServicesArray = NULL;
 +    LPENUM_SERVICE_STATUSA lpServicesPtr = NULL;
 +    LPSTR lpStr;
 +
 +    *pcbBytesNeeded = 0;
 +    *lpServicesReturned = 0;
 +
 +    DPRINT("REnumDependentServicesA() called\n");
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +
 +    /* Check access rights */
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SC_MANAGER_ENUMERATE_SERVICE))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n",
 +               hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    /* Open the Services Reg key */
 +    dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
 +                            L"System\\CurrentControlSet\\Services",
 +                            0,
 +                            KEY_READ,
 +                            &hServicesKey);
 +
 +    if (dwError != ERROR_SUCCESS)
 +        return dwError;
 +
 +    /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
 +             both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
 +             are the same for both. Verified in WINXP. */
 +
 +    /* First determine the bytes needed and get the number of dependent services*/
 +    dwError = Int_EnumDependentServicesW(hServicesKey,
 +                                         lpService,
 +                                         dwServiceState,
 +                                         NULL,
 +                                         pcbBytesNeeded,
 +                                         &dwServicesReturned);
 +    if (dwError != ERROR_SUCCESS)
 +        goto Done;
 +
 +    /* If buffer size is less than the bytes needed or pointer is null*/
 +    if ((!lpServices) || (cbBufSize < *pcbBytesNeeded))
 +    {
 +        dwError = ERROR_MORE_DATA;
 +        goto Done;
 +    }
 +
 +    /* Allocate memory for array of service pointers */
 +    lpServicesArray = HeapAlloc(GetProcessHeap(),
 +                                0,
 +                                (dwServicesReturned + 1) * sizeof(PSERVICE));
 +    if (!lpServicesArray)
 +    {
 +        DPRINT("Could not allocate a buffer!!\n");
 +        dwError = ERROR_NOT_ENOUGH_MEMORY;
 +        goto Done;
 +    }
 +
 +    dwServicesReturned = 0;
 +    *pcbBytesNeeded = 0;
 +
 +    dwError = Int_EnumDependentServicesW(hServicesKey,
 +                                         lpService,
 +                                         dwServiceState,
 +                                         lpServicesArray,
 +                                         pcbBytesNeeded,
 +                                         &dwServicesReturned);
 +    if (dwError != ERROR_SUCCESS)
 +    {
 +        goto Done;
 +    }
 +
 +    lpServicesPtr = (LPENUM_SERVICE_STATUSA)lpServices;
 +    lpStr = (LPSTR)(lpServices + (dwServicesReturned * sizeof(ENUM_SERVICE_STATUSA)));
 +
 +    /* Copy EnumDepenedentService to Buffer */
 +    for (dwServiceCount = 0; dwServiceCount < dwServicesReturned; dwServiceCount++)
 +    {
 +        lpService = lpServicesArray[dwServiceCount];
 +
 +        /* Copy the status info */
 +        memcpy(&lpServicesPtr->ServiceStatus,
 +               &lpService->Status,
 +               sizeof(SERVICE_STATUS));
 +
 +        /* Copy display name */
 +        WideCharToMultiByte(CP_ACP,
 +                            0,
 +                            lpService->lpDisplayName,
 +                            -1,
 +                            lpStr,
 +                            wcslen(lpService->lpDisplayName),
 +                            0,
 +                            0);
 +        lpServicesPtr->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
 +        lpStr += strlen(lpStr) + 1;
 +
 +        /* Copy service name */
 +        WideCharToMultiByte(CP_ACP,
 +                            0,
 +                            lpService->lpServiceName,
 +                            -1,
 +                            lpStr,
 +                            wcslen(lpService->lpServiceName),
 +                            0,
 +                            0);
 +        lpServicesPtr->lpServiceName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServices);
 +        lpStr += strlen(lpStr) + 1;
 +
 +        lpServicesPtr ++;
 +    }
 +
 +    *lpServicesReturned = dwServicesReturned;
 +
 +Done:
 +    if (lpServicesArray)
 +        HeapFree(GetProcessHeap(), 0, lpServicesArray);
 +
 +    RegCloseKey(hServicesKey);
 +
 +    DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 26 */
 +DWORD REnumServicesStatusA(
 +    SC_RPC_HANDLE hSCManager,
 +    DWORD dwServiceType,
 +    DWORD dwServiceState,
 +    LPBYTE lpBuffer,
 +    DWORD dwBufSize,
 +    LPBOUNDED_DWORD_256K pcbBytesNeeded,
 +    LPBOUNDED_DWORD_256K lpServicesReturned,
 +    LPBOUNDED_DWORD_256K lpResumeHandle)
 +{
 +    LPENUM_SERVICE_STATUSW lpStatusPtrW = NULL;
 +    LPENUM_SERVICE_STATUSA lpStatusPtrA = NULL;
 +    LPWSTR lpStringPtrW;
 +    LPSTR lpStringPtrA;
 +    DWORD dwError;
 +    DWORD dwServiceCount;
 +
 +    DPRINT("REnumServicesStatusA() called\n");
 +
 +    if ((dwBufSize > 0) && (lpBuffer))
 +    {
 +        lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwBufSize);
 +        if (!lpStatusPtrW)
 +        {
 +            DPRINT("Failed to allocate buffer!\n");
 +            return ERROR_NOT_ENOUGH_MEMORY;
 +        }
 +    }
 +
 +    dwError = REnumServicesStatusW(hSCManager,
 +                                   dwServiceType,
 +                                   dwServiceState,
 +                                   (LPBYTE)lpStatusPtrW,
 +                                   dwBufSize,
 +                                   pcbBytesNeeded,
 +                                   lpServicesReturned,
 +                                   lpResumeHandle);
 +
 +    /* if no services were returned then we are Done */
 +    if (*lpServicesReturned == 0)
 +        goto Done;
 +
 +    lpStatusPtrA = (LPENUM_SERVICE_STATUSA)lpBuffer;
 +    lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
 +                  *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSA));
 +    lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + 
 +                  *lpServicesReturned * sizeof(ENUM_SERVICE_STATUSW));
 +
 +    for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++)
 +    {
 +        /* Copy the service name */
 +        WideCharToMultiByte(CP_ACP,
 +                            0,
 +                            lpStringPtrW,
 +                            -1,
 +                            lpStringPtrA,
 +                            wcslen(lpStringPtrW),
 +                            0,
 +                            0);
 +
 +        lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
 +        lpStringPtrA += wcslen(lpStringPtrW) + 1;
 +        lpStringPtrW += wcslen(lpStringPtrW) + 1;
 +
 +        /* Copy the display name */
 +        WideCharToMultiByte(CP_ACP,
 +                            0,
 +                            lpStringPtrW,
 +                            -1,
 +                            lpStringPtrA,
 +                            wcslen(lpStringPtrW),
 +                            0,
 +                            0);
 +
 +        lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
 +        lpStringPtrA += wcslen(lpStringPtrW) + 1;
 +        lpStringPtrW += wcslen(lpStringPtrW) + 1;
 +
 +        /* Copy the status information */
 +        memcpy(&lpStatusPtrA->ServiceStatus,
 +               &lpStatusPtrW->ServiceStatus,
 +               sizeof(SERVICE_STATUS));
 +
 +        lpStatusPtrA++;
 +    }
 +
 +Done:;
 +    if (lpStatusPtrW)
 +        HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
 +
 +    DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 27 */
 +DWORD ROpenSCManagerA(
 +    LPSTR lpMachineName,
 +    LPSTR lpDatabaseName,
 +    DWORD dwDesiredAccess,
 +    LPSC_RPC_HANDLE lpScHandle)
 +{
 +    UNICODE_STRING MachineName;
 +    UNICODE_STRING DatabaseName;
 +    DWORD dwError;
 +
 +    DPRINT("ROpenSCManagerA() called\n");
 +
 +    if (lpMachineName)
 +        RtlCreateUnicodeStringFromAsciiz(&MachineName,
 +                                         lpMachineName);
 +
 +    if (lpDatabaseName)
 +        RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
 +                                         lpDatabaseName);
 +
 +    dwError = ROpenSCManagerW(lpMachineName ? MachineName.Buffer : NULL,
 +                              lpDatabaseName ? DatabaseName.Buffer : NULL,
 +                              dwDesiredAccess,
 +                              lpScHandle);
 +
 +    if (lpMachineName)
 +        RtlFreeUnicodeString(&MachineName);
 +
 +    if (lpDatabaseName)
 +        RtlFreeUnicodeString(&DatabaseName);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 28 */
 +DWORD ROpenServiceA(
 +    SC_RPC_HANDLE hSCManager,
 +    LPSTR lpServiceName,
 +    DWORD dwDesiredAccess,
 +    LPSC_RPC_HANDLE lpServiceHandle)
 +{
 +    UNICODE_STRING ServiceName;
 +    DWORD dwError;
 +
 +    DPRINT("ROpenServiceA() called\n");
 +
 +    if (lpServiceName)
 +        RtlCreateUnicodeStringFromAsciiz(&ServiceName,
 +                                         lpServiceName);
 +
 +    dwError = ROpenServiceW(hSCManager,
 +                            lpServiceName ? ServiceName.Buffer : NULL,
 +                            dwDesiredAccess,
 +                            lpServiceHandle);
 +
 +    if (lpServiceName)
 +        RtlFreeUnicodeString(&ServiceName);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 29 */
 +DWORD RQueryServiceConfigA(
 +    SC_RPC_HANDLE hService,
 +    LPQUERY_SERVICE_CONFIGA lpServiceConfig,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_8K pcbBytesNeeded)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +    HKEY hServiceKey = NULL;
 +    LPWSTR lpImagePath = NULL;
 +    LPWSTR lpServiceStartName = NULL;
 +    LPWSTR lpDependencies = NULL;
 +    DWORD dwDependenciesLength = 0;
 +    DWORD dwRequiredSize;
 +    LPQUERY_SERVICE_CONFIGA lpConfig = NULL;
 +    CHAR lpEmptyString[]={0,0};
 +    LPSTR lpStr;
 +
 +    DPRINT("RQueryServiceConfigA() called\n");
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_QUERY_CONFIG))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* FIXME: Lock the service database shared */
 +
 +    dwError = ScmOpenServiceKey(lpService->lpServiceName,
 +                                KEY_READ,
 +                                &hServiceKey);
 +    if (dwError != ERROR_SUCCESS)
 +        goto Done;
 +
 +    /* Read the image path */
 +    dwError = ScmReadString(hServiceKey,
 +                            L"ImagePath",
 +                            &lpImagePath);
 +    if (dwError != ERROR_SUCCESS)
 +        goto Done;
 +
 +    /* Read the service start name */
 +    ScmReadString(hServiceKey,
 +                  L"ObjectName",
 +                  &lpServiceStartName);
 +
 +    /* Read the dependencies */
 +    ScmReadDependencies(hServiceKey,
 +                        &lpDependencies,
 +                        &dwDependenciesLength);
 +
 +    dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
 +
 +    if (lpImagePath != NULL)
 +        dwRequiredSize += wcslen(lpImagePath) + 1;
 +    else
 +        dwRequiredSize += 2;
 +
 +    if ((lpService->lpGroup != NULL) && (lpService->lpGroup->lpGroupName != NULL))
 +        dwRequiredSize += wcslen(lpService->lpGroup->lpGroupName) + 1;
 +    else
 +        dwRequiredSize += 2;
 +
 +    /* Add Dependencies length */
 +    if (lpDependencies != NULL)
 +        dwRequiredSize += dwDependenciesLength;
 +    else
 +        dwRequiredSize += 2;
 +
 +    if (lpServiceStartName != NULL)
 +        dwRequiredSize += wcslen(lpServiceStartName) + 1;
 +    else
 +        dwRequiredSize += 2;
 +
 +    if (lpService->lpDisplayName != NULL)
 +        dwRequiredSize += wcslen(lpService->lpDisplayName) + 1;
 +    else
 +        dwRequiredSize += 2;
 +
 +    if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
 +    {
 +        dwError = ERROR_INSUFFICIENT_BUFFER;
 +    }
 +    else
 +    {
 +        lpConfig = (LPQUERY_SERVICE_CONFIGA)lpServiceConfig;
 +        lpConfig->dwServiceType = lpService->Status.dwServiceType;
 +        lpConfig->dwStartType = lpService->dwStartType;
 +        lpConfig->dwErrorControl = lpService->dwErrorControl;
 +        lpConfig->dwTagId = lpService->dwTag;
 +
 +        lpStr = (LPSTR)(lpServiceConfig + 1);
 +
 +        /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
 +          Verified in WINXP*/
 +
 +        if (lpImagePath)
 +        {
 +            WideCharToMultiByte(CP_ACP,
 +                                0,
 +                                lpImagePath,
 +                                -1,
 +                                lpStr,
 +                                wcslen(lpImagePath) + 1,
 +                                0,
 +                                0);
 +        }
 +        else
 +        {
 +            strcpy(lpStr, lpEmptyString);
 +        }
 +
 +        lpConfig->lpBinaryPathName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
 +        lpStr += (strlen((LPSTR)lpStr) + 1);
 +
 +        if (lpService->lpGroup && lpService->lpGroup->lpGroupName)
 +        {
 +            WideCharToMultiByte(CP_ACP,
 +                                0,
 +                                lpService->lpGroup->lpGroupName,
 +                                -1,
 +                                lpStr,
 +                                wcslen(lpService->lpGroup->lpGroupName) + 1,
 +                                0,
 +                                0);
 +        }
 +        else
 +        {
 +            strcpy(lpStr, lpEmptyString);
 +        }
 +
 +        lpConfig->lpLoadOrderGroup = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
 +        lpStr += (strlen(lpStr) + 1);
 +
 +        /* Append Dependencies */
 +        if (lpDependencies)
 +        {
 +            WideCharToMultiByte(CP_ACP,
 +                                0,
 +                                lpDependencies,
 +                                dwDependenciesLength,
 +                                lpStr,
 +                                dwDependenciesLength,
 +                                0,
 +                                0);
 +        }
 +        else
 +        {
 +            strcpy(lpStr, lpEmptyString);
 +        }
 +
 +        lpConfig->lpDependencies = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
 +        if (lpDependencies)
 +            lpStr += dwDependenciesLength;
 +        else
 +            lpStr += (strlen(lpStr) + 1);
 +
 +        if (lpServiceStartName)
 +        {
 +            WideCharToMultiByte(CP_ACP,
 +                                0,
 +                                lpServiceStartName,
 +                                -1,
 +                                lpStr,
 +                                wcslen(lpServiceStartName) + 1,
 +                                0,
 +                                0);
 +        }
 +        else
 +        {
 +            strcpy(lpStr, lpEmptyString);
 +        }
 +
 +        lpConfig->lpServiceStartName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
 +        lpStr += (strlen(lpStr) + 1);
 +
 +        if (lpService->lpDisplayName)
 +        {
 +            WideCharToMultiByte(CP_ACP,
 +                                0,
 +                                lpService->lpDisplayName,
 +                                -1,
 +                                lpStr,
 +                                wcslen(lpService->lpDisplayName) + 1,
 +                                0,
 +                                0);
 +        }
 +        else
 +        {
 +            strcpy(lpStr, lpEmptyString);
 +        }
 +
 +        lpConfig->lpDisplayName = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
 +    }
 +
 +    if (pcbBytesNeeded != NULL)
 +        *pcbBytesNeeded = dwRequiredSize;
 +
 +Done:;
 +    if (lpImagePath != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpImagePath);
 +
 +    if (lpServiceStartName != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpServiceStartName);
 +
 +    if (lpDependencies != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpDependencies);
 +
 +    if (hServiceKey != NULL)
 +        RegCloseKey(hServiceKey);
 +
 +    /* FIXME: Unlock the service database */
 +
 +    DPRINT("RQueryServiceConfigA() done\n");
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 30 */
 +DWORD RQueryServiceLockStatusA(
 +    SC_RPC_HANDLE hSCManager,
 +    LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_4K pcbBytesNeeded)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 31 */
 +DWORD RStartServiceA(
 +    SC_RPC_HANDLE hService,
 +    DWORD argc,
 +    LPSTRING_PTRSA argv)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +
 +    DPRINT("RStartServiceA() called\n");
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_START))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (lpService->dwStartType == SERVICE_DISABLED)
 +        return ERROR_SERVICE_DISABLED;
 +
 +    if (lpService->bDeleted)
 +        return ERROR_SERVICE_MARKED_FOR_DELETE;
 +
 +    /* FIXME: Convert argument vector to Unicode */
 +
 +    /* Start the service */
 +    dwError = ScmStartService(lpService, 0, NULL);
 +
 +    /* FIXME: Free argument vector */
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 32 */
 +DWORD RGetServiceDisplayNameA(
 +    SC_RPC_HANDLE hSCManager,
 +    LPCSTR lpServiceName,
 +    LPSTR lpDisplayName,
 +    LPBOUNDED_DWORD_4K lpcchBuffer)
 +{
 +//    PMANAGER_HANDLE hManager;
 +    PSERVICE lpService = NULL;
 +    DWORD dwLength;
 +    DWORD dwError;
 +    LPWSTR lpServiceNameW;
 +
 +    DPRINT("RGetServiceDisplayNameA() called\n");
 +    DPRINT("hSCManager = %p\n", hSCManager);
 +    DPRINT("lpServiceName: %s\n", lpServiceName);
 +    DPRINT("lpDisplayName: %p\n", lpDisplayName);
 +    DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
 +
 +//    hManager = (PMANAGER_HANDLE)hSCManager;
 +//    if (hManager->Handle.Tag != MANAGER_TAG)
 +//    {
 +//        DPRINT("Invalid manager handle!\n");
 +//        return ERROR_INVALID_HANDLE;
 +//    }
 +
 +    if (lpServiceName != NULL)
 +    {
 +        dwLength = strlen(lpServiceName) + 1;
 +        lpServiceNameW = HeapAlloc(GetProcessHeap(),
 +                                   HEAP_ZERO_MEMORY,
 +                                   dwLength * sizeof(WCHAR));
 +        if (!lpServiceNameW)
 +            return ERROR_NOT_ENOUGH_MEMORY;
 +
 +        MultiByteToWideChar(CP_ACP,
 +                            0,
 +                            lpServiceName,
 +                            -1,
 +                            lpServiceNameW,
 +                            dwLength);
 +
 +        lpService = ScmGetServiceEntryByName(lpServiceNameW);
 +
 +        HeapFree(GetProcessHeap(), 0, lpServiceNameW);
 +    }
 +
 +    if (lpService == NULL)
 +    {
 +        DPRINT("Could not find a service!\n");
 +
 +        /* If the service could not be found and lpcchBuffer is 0, windows
 +           puts null in lpDisplayName and puts 1 in lpcchBuffer */
 +        if (*lpcchBuffer == 0)
 +        {
 +            *lpcchBuffer = 1;
 +            if (lpDisplayName != NULL)
 +            {
 +                *lpDisplayName = '\0';
 +            }
 +        }
 +        return ERROR_SERVICE_DOES_NOT_EXIST;
 +    }
 +
 +    if (!lpService->lpDisplayName)
 +    {
 +        dwLength = wcslen(lpService->lpServiceName);
 +        if (lpDisplayName != NULL &&
 +            *lpcchBuffer > dwLength)
 +        {
 +            WideCharToMultiByte(CP_ACP,
 +                                0,
 +                                lpService->lpServiceName,
 +                                wcslen(lpService->lpServiceName),
 +                                lpDisplayName,
 +                                dwLength + 1,
 +                                NULL,
 +                                NULL);
 +            return ERROR_SUCCESS;
 +        }
 +    }
 +    else
 +    {
 +        dwLength = wcslen(lpService->lpDisplayName);
 +        if (lpDisplayName != NULL &&
 +            *lpcchBuffer > dwLength)
 +        {
 +            WideCharToMultiByte(CP_ACP,
 +                                0,
 +                                lpService->lpDisplayName,
 +                                wcslen(lpService->lpDisplayName),
 +                                lpDisplayName,
 +                                dwLength + 1,
 +                                NULL,
 +                                NULL);
 +            return ERROR_SUCCESS;
 +        }
 +    }
 +
 +    dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
 +
 +    *lpcchBuffer = dwLength * 2;
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 33 */
 +DWORD RGetServiceKeyNameA(
 +    SC_RPC_HANDLE hSCManager,
 +    LPCSTR lpDisplayName,
 +    LPSTR lpServiceName,
 +    LPBOUNDED_DWORD_4K lpcchBuffer)
 +{
 +    PSERVICE lpService;
 +    DWORD dwLength;
 +    DWORD dwError;
 +    LPWSTR lpDisplayNameW;
 +
 +    DPRINT("RGetServiceKeyNameA() called\n");
 +    DPRINT("hSCManager = %p\n", hSCManager);
 +    DPRINT("lpDisplayName: %s\n", lpDisplayName);
 +    DPRINT("lpServiceName: %p\n", lpServiceName);
 +    DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
 +
 +    dwLength = strlen(lpDisplayName) + 1;
 +    lpDisplayNameW = HeapAlloc(GetProcessHeap(),
 +                               HEAP_ZERO_MEMORY,
 +                               dwLength * sizeof(WCHAR));
 +    if (!lpDisplayNameW)
 +        return ERROR_NOT_ENOUGH_MEMORY;
 +
 +    MultiByteToWideChar(CP_ACP,
 +                        0,
 +                        lpDisplayName,
 +                        -1,
 +                        lpDisplayNameW,
 +                        dwLength);
 +
 +    lpService = ScmGetServiceEntryByDisplayName(lpDisplayNameW);
 +
 +    HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
 +
 +    if (lpService == NULL)
 +    {
 +        DPRINT("Could not find the service!\n");
 +
 +        /* If the service could not be found and lpcchBuffer is 0,
 +           put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
 +        if (*lpcchBuffer == 0)
 +        {
 +            *lpcchBuffer = 1;
 +            if (lpServiceName != NULL)
 +            {
 +                *lpServiceName = '\0';
 +            }
 +        }
 +
 +        return ERROR_SERVICE_DOES_NOT_EXIST;
 +    }
 +
 +    dwLength = wcslen(lpService->lpServiceName);
 +    if (lpServiceName != NULL &&
 +        *lpcchBuffer > dwLength)
 +    {
 +        WideCharToMultiByte(CP_ACP,
 +                            0,
 +                            lpService->lpServiceName,
 +                            wcslen(lpService->lpServiceName),
 +                            lpServiceName,
 +                            dwLength + 1,
 +                            NULL,
 +                            NULL);
 +        return ERROR_SUCCESS;
 +    }
 +
 +    dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
 +
 +    *lpcchBuffer = dwLength * 2;
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 34 */
 +DWORD RI_ScGetCurrentGroupStateW(
 +    SC_RPC_HANDLE hSCManager,
 +    LPWSTR lpLoadOrderGroup,
 +    LPDWORD lpState)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 35 */
 +DWORD REnumServiceGroupW(
 +    SC_RPC_HANDLE hSCManager,
 +    DWORD dwServiceType,
 +    DWORD dwServiceState,
 +    LPBYTE lpBuffer,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_256K pcbBytesNeeded,
 +    LPBOUNDED_DWORD_256K lpServicesReturned,
 +    LPBOUNDED_DWORD_256K lpResumeIndex,
 +    LPCWSTR pszGroupName)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +//
 +// WARNING: This function is untested
 +//
 +/* Function 36 */
 +DWORD RChangeServiceConfig2A(
 +    SC_RPC_HANDLE hService,
 +    SC_RPC_CONFIG_INFOA Info)
 +{
 +    SC_RPC_CONFIG_INFOW InfoW;
 +    DWORD dwRet, dwLength;
 +    PVOID ptr = NULL;
 +
 +    DPRINT("RChangeServiceConfig2A() called\n");
 +    DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
 +
 +    InfoW.dwInfoLevel = Info.dwInfoLevel;
 +
 +    if (InfoW.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
 +    {
 +        LPSERVICE_DESCRIPTIONW lpServiceDescriptonW;
 +        LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
 +
 +        lpServiceDescriptonA = Info.psd;
 +
 +        ///if (lpServiceDescriptonA &&
 +        ///lpServiceDescriptonA->lpDescription)
 +        ///{
 +            dwLength = (strlen(Info.lpDescription) + 1) * sizeof(WCHAR);
 +
 +            lpServiceDescriptonW = HeapAlloc(GetProcessHeap(),
 +                                            0,
 +                                            dwLength + sizeof(SERVICE_DESCRIPTIONW));
 +            if (!lpServiceDescriptonW)
 +            {
 +                return ERROR_NOT_ENOUGH_MEMORY;
 +            }
 +
 +            lpServiceDescriptonW->lpDescription = (LPWSTR)(lpServiceDescriptonW + 1);
 +
 +            MultiByteToWideChar(CP_ACP,
 +                                0,
 +                                Info.lpDescription,
 +                                -1,
 +                                lpServiceDescriptonW->lpDescription,
 +                                dwLength);
 +
 +            ptr = lpServiceDescriptonW;
 +            InfoW.psd = lpServiceDescriptonW;
 +        ///}
 +    }
 +    else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
 +    {
 +        LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW;
 +        LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA;
 +        DWORD dwRebootLen = 0;
 +        DWORD dwCommandLen = 0;
 +
 +        lpServiceFailureActionsA = Info.psfa;
 +
 +        if (lpServiceFailureActionsA)
 +        {
 +            if (lpServiceFailureActionsA->lpRebootMsg)
 +            {
 +                dwRebootLen = (strlen(lpServiceFailureActionsA->lpRebootMsg) + 1) * sizeof(WCHAR);
 +            }
 +            if (lpServiceFailureActionsA->lpCommand)
 +            {
 +                dwCommandLen = (strlen(lpServiceFailureActionsA->lpCommand) + 1) * sizeof(WCHAR);
 +            }
 +            dwLength = dwRebootLen + dwCommandLen + sizeof(SERVICE_FAILURE_ACTIONSW);
 +
 +            lpServiceFailureActionsW = HeapAlloc(GetProcessHeap(),
 +                                                 0,
 +                                                 dwLength);
 +            if (!lpServiceFailureActionsW)
 +            {
 +                return ERROR_NOT_ENOUGH_MEMORY;
 +            }
 +
 +            lpServiceFailureActionsW->cActions = lpServiceFailureActionsA->cActions;
 +            lpServiceFailureActionsW->dwResetPeriod = lpServiceFailureActionsA->dwResetPeriod;
 +            CopyMemory(lpServiceFailureActionsW->lpsaActions, lpServiceFailureActionsA->lpsaActions, sizeof(SC_ACTION));
 +
 +            if (lpServiceFailureActionsA->lpRebootMsg)
 +            {
 +                MultiByteToWideChar(CP_ACP,
 +                                    0,
 +                                    lpServiceFailureActionsA->lpRebootMsg,
 +                                    -1,
 +                                    lpServiceFailureActionsW->lpRebootMsg,
 +                                    dwRebootLen);
 +            }
 +
 +            if (lpServiceFailureActionsA->lpCommand)
 +            {
 +                MultiByteToWideChar(CP_ACP,
 +                                    0,
 +                                    lpServiceFailureActionsA->lpCommand,
 +                                    -1,
 +                                    lpServiceFailureActionsW->lpCommand,
 +                                    dwCommandLen);
 +            }
 +
 +            ptr = lpServiceFailureActionsW;
 +        }
 +    }
 +
 +    dwRet = RChangeServiceConfig2W(hService, InfoW);
 +
 +    HeapFree(GetProcessHeap(), 0, ptr);
 +
 +    return dwRet;
 +}
 +
 +
 +/* Function 37 */
 +DWORD RChangeServiceConfig2W(
 +    SC_RPC_HANDLE hService,
 +    SC_RPC_CONFIG_INFOW Info)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +    HKEY hServiceKey = NULL;
 +
 +    DPRINT("RChangeServiceConfig2W() called\n");
 +    DPRINT("dwInfoLevel = %lu\n", Info.dwInfoLevel);
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_CHANGE_CONFIG))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* FIXME: Lock database exclusively */
 +
 +    if (lpService->bDeleted)
 +    {
 +        /* FIXME: Unlock database */
 +        DPRINT("The service has already been marked for delete!\n");
 +        return ERROR_SERVICE_MARKED_FOR_DELETE;
 +    }
 +
 +    /* Open the service key */
 +    dwError = ScmOpenServiceKey(lpService->szServiceName,
 +                                KEY_SET_VALUE,
 +                                &hServiceKey);
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    if (Info.dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
 +    {
 +        LPSERVICE_DESCRIPTIONW lpServiceDescription;
 +
 +        lpServiceDescription = (LPSERVICE_DESCRIPTIONW)Info.psd;
 +        lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpServiceDescription + sizeof(LPSERVICE_DESCRIPTIONW));
 +
 +        if (lpServiceDescription != NULL &&
 +            lpServiceDescription->lpDescription != NULL)
 +        {
 +            DPRINT("Setting value %S\n", lpServiceDescription->lpDescription);
 +            RegSetValueExW(hServiceKey,
 +                           L"Description",
 +                           0,
 +                           REG_SZ,
 +                           (LPBYTE)lpServiceDescription->lpDescription,
 +                           (wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR));
 +
 +            if (dwError != ERROR_SUCCESS)
 +                goto done;
 +        }
 +    }
 +    else if (Info.dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
 +    {
 +        UNIMPLEMENTED;
 +        dwError = ERROR_CALL_NOT_IMPLEMENTED;
 +        goto done;
 +    }
 +
 +done:
 +    /* FIXME: Unlock database */
 +    if (hServiceKey != NULL)
 +        RegCloseKey(hServiceKey);
 +
 +    DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 38 */
 +DWORD RQueryServiceConfig2A(
 +    SC_RPC_HANDLE hService,
 +    DWORD dwInfoLevel,
 +    LPBYTE lpBuffer,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_8K pcbBytesNeeded)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +    HKEY hServiceKey = NULL;
 +    LPWSTR lpDescriptionW = NULL;
 +    LPSTR lpDescription = NULL;
 +
 +    DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
 +           hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
 +
 +    if (!lpBuffer)
 +        return ERROR_INVALID_ADDRESS;
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_QUERY_CONFIG))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* FIXME: Lock the service database shared */
 +
 +    dwError = ScmOpenServiceKey(lpService->lpServiceName,
 +                                KEY_READ,
 +                                &hServiceKey);
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
 +    {
 +        LPSERVICE_DESCRIPTIONA lpServiceDescription = (LPSERVICE_DESCRIPTIONA)lpBuffer;
 +        LPSTR lpStr;
 +
 +        *pcbBytesNeeded = sizeof(SERVICE_DESCRIPTIONA);
 +
 +        dwError = ScmReadString(hServiceKey,
 +                                L"Description",
 +                                &lpDescriptionW);
 +        if (dwError == ERROR_SUCCESS)
 +        {
 +            *pcbBytesNeeded += ((wcslen(lpDescriptionW) + 1) * sizeof(WCHAR));
 +        }
 +
 +        if (cbBufSize >= *pcbBytesNeeded)
 +        {
 +
 +            if (dwError == ERROR_SUCCESS)
 +            {
 +                lpStr = (LPSTR)(lpServiceDescription + 1);
 +
 +                WideCharToMultiByte(CP_ACP,
 +                                    0,
 +                                    lpDescriptionW,
 +                                    -1,
 +                                    lpStr,
 +                                    wcslen(lpDescriptionW),
 +                                    NULL,
 +                                    NULL);
 +                lpServiceDescription->lpDescription = (LPSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
 +            }
 +            else
 +            {
 +                lpServiceDescription->lpDescription = NULL;
 +                goto done;
 +            }
 +        }
 +        else
 +        {
 +            dwError = ERROR_INSUFFICIENT_BUFFER;
 +            goto done;
 +        }
 +    }
 +    else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
 +    {
 +        UNIMPLEMENTED;
 +        dwError = ERROR_CALL_NOT_IMPLEMENTED;
 +        goto done;
 +    }
 +
 +done:
 +    if (lpDescription != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpDescription);
 +
 +    if (hServiceKey != NULL)
 +        RegCloseKey(hServiceKey);
 +
 +    /* FIXME: Unlock database */
 +
 +    DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 39 */
 +DWORD RQueryServiceConfig2W(
 +    SC_RPC_HANDLE hService,
 +    DWORD dwInfoLevel,
 +    LPBYTE lpBuffer,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_8K pcbBytesNeeded)
 +{
 +    DWORD dwError = ERROR_SUCCESS;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService = NULL;
 +    HKEY hServiceKey = NULL;
 +    DWORD dwRequiredSize;
 +    LPWSTR lpDescription = NULL;
 +    LPWSTR lpFailureCommand = NULL;
 +    LPWSTR lpRebootMessage = NULL;
 +
 +    DPRINT("RQueryServiceConfig2W() called\n");
 +
 +    if (!lpBuffer)
 +        return ERROR_INVALID_ADDRESS;
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_QUERY_CONFIG))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    /* FIXME: Lock the service database shared */
 +
 +    dwError = ScmOpenServiceKey(lpService->lpServiceName,
 +                                KEY_READ,
 +                                &hServiceKey);
 +    if (dwError != ERROR_SUCCESS)
 +        goto done;
 +
 +    if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
 +    {
 +        LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)lpBuffer;
 +        LPWSTR lpStr;
 +
 +        dwError = ScmReadString(hServiceKey,
 +                                L"Description",
 +                                &lpDescription);
 +        if (dwError != ERROR_SUCCESS)
 +            goto done;
 +
 +        dwRequiredSize = sizeof(SERVICE_DESCRIPTIONW) + ((wcslen(lpDescription) + 1) * sizeof(WCHAR));
 +
 +        if (cbBufSize < dwRequiredSize)
 +        {
 +            *pcbBytesNeeded = dwRequiredSize;
 +            dwError = ERROR_INSUFFICIENT_BUFFER;
 +            goto done;
 +        }
 +
 +        lpStr = (LPWSTR)(lpServiceDescription + 1);
 +        wcscpy(lpStr, lpDescription);
 +        lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
 +    }
 +    else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
 +    {
 +        LPWSTR lpStr;
 +        LPSERVICE_FAILURE_ACTIONSW lpFailureActions = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
 +
 +        UNIMPLEMENTED;
 +
 +        dwError = ScmReadString(hServiceKey,
 +                                L"FailureCommand",
 +                                &lpFailureCommand);
 +
 +        dwError = ScmReadString(hServiceKey,
 +                                L"RebootMessage",
 +                                &lpRebootMessage);
 +
 +        dwRequiredSize = sizeof(SERVICE_FAILURE_ACTIONSW);
 +
 +        if (lpFailureCommand)
 +            dwRequiredSize += (wcslen(lpFailureCommand) + 1) * sizeof(WCHAR);
 +
 +        if (lpRebootMessage)
 +            dwRequiredSize += (wcslen(lpRebootMessage) + 1) * sizeof(WCHAR);
 +
 +        if (cbBufSize < dwRequiredSize)
 +        {
 +            *pcbBytesNeeded = dwRequiredSize;
 +            dwError = ERROR_INSUFFICIENT_BUFFER;
 +            goto done;
 +        }
 +
 +        lpFailureActions->cActions = 0; 
 +        lpFailureActions->dwResetPeriod = 0;
 +        lpFailureActions->lpCommand = NULL;
 +        lpFailureActions->lpRebootMsg = NULL;
 +        lpFailureActions->lpsaActions = NULL;
 +
 +        lpStr = (LPWSTR)(lpFailureActions + 1);
 +        if (lpRebootMessage)
 +        {
 +            wcscpy(lpStr, lpRebootMessage);
 +            lpFailureActions->lpRebootMsg = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpRebootMessage);
 +            lpStr += wcslen(lpRebootMessage) + 1;
 +        }
 +
 +        if (lpFailureCommand)
 +        {
 +            wcscpy(lpStr, lpFailureCommand);
 +            lpFailureActions->lpCommand = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpFailureCommand);
 +            lpStr += wcslen(lpRebootMessage) + 1;
 +        }
 +        dwError = STATUS_SUCCESS;
 +        goto done;
 +    }
 +
 +done:
 +    if (lpDescription != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpDescription);
 +
 +    if (lpRebootMessage != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpRebootMessage);
 +
 +    if (lpFailureCommand != NULL)
 +        HeapFree(GetProcessHeap(), 0, lpFailureCommand);
 +
 +    if (hServiceKey != NULL)
 +        RegCloseKey(hServiceKey);
 +
 +    /* FIXME: Unlock database */
 +
 +    DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 40 */
 +DWORD RQueryServiceStatusEx(
 +    SC_RPC_HANDLE hService,
 +    SC_STATUS_TYPE InfoLevel,
 +    LPBYTE lpBuffer,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_8K pcbBytesNeeded)
 +{
 +    LPSERVICE_STATUS_PROCESS lpStatus;
 +    PSERVICE_HANDLE hSvc;
 +    PSERVICE lpService;
 +
 +    DPRINT("RQueryServiceStatusEx() called\n");
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    if (InfoLevel != SC_STATUS_PROCESS_INFO)
 +        return ERROR_INVALID_LEVEL;
 +
 +    *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
 +
 +    if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
 +        return ERROR_INSUFFICIENT_BUFFER;
 +
 +    hSvc = ScmGetServiceFromHandle(hService);
 +    if (hSvc == NULL)
 +    {
 +        DPRINT1("Invalid service handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
 +                                  SERVICE_QUERY_STATUS))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    lpService = hSvc->ServiceEntry;
 +    if (lpService == NULL)
 +    {
 +        DPRINT("lpService == NULL!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer;
 +
 +    /* Return service status information */
 +    RtlCopyMemory(lpStatus,
 +                  &lpService->Status,
 +                  sizeof(SERVICE_STATUS));
 +
 +    lpStatus->dwProcessId = lpService->ProcessId;     /* FIXME */
 +    lpStatus->dwServiceFlags = 0;                     /* FIXME */
 +
 +    return ERROR_SUCCESS;
 +}
 +
 +
 +/* Function 41 */
 +DWORD REnumServicesStatusExA(
 +    SC_RPC_HANDLE hSCManager,
 +    SC_ENUM_TYPE InfoLevel,
 +    DWORD dwServiceType,
 +    DWORD dwServiceState,
 +    LPBYTE lpBuffer,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_256K pcbBytesNeeded,
 +    LPBOUNDED_DWORD_256K lpServicesReturned,
 +    LPBOUNDED_DWORD_256K lpResumeIndex,
 +    LPCSTR pszGroupName)
 +{
 +    LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW = NULL;
 +    LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA = NULL;
 +    LPWSTR lpStringPtrW;
 +    LPSTR lpStringPtrA;
 +    LPWSTR pszGroupNameW = NULL;
 +    DWORD dwError;
 +    DWORD dwServiceCount;
 +
 +    DPRINT("REnumServicesStatusExA() called\n");
 +
 +    if (pszGroupName)
 +    {
 +        pszGroupNameW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (strlen(pszGroupName) + 1) * sizeof(WCHAR));
 +        if (!pszGroupNameW)
 +        {
 +             DPRINT("Failed to allocate buffer!\n");
 +             return ERROR_NOT_ENOUGH_MEMORY;
 +        }
 +
 +        MultiByteToWideChar(CP_ACP,
 +                            0,
 +                            pszGroupName,
 +                            -1,
 +                            pszGroupNameW,
 +                            strlen(pszGroupName) + 1);
 +    }
 +
 +    if ((cbBufSize > 0) && (lpBuffer))
 +    {
 +        lpStatusPtrW = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cbBufSize);
 +        if (!lpStatusPtrW)
 +        {
 +            DPRINT("Failed to allocate buffer!\n");
 +            return ERROR_NOT_ENOUGH_MEMORY;
 +        }
 +    }
 +
 +    dwError = REnumServicesStatusExW(hSCManager,
 +                                     InfoLevel,
 +                                     dwServiceType,
 +                                     dwServiceState,
 +                                     (LPBYTE)lpStatusPtrW,
 +                                     cbBufSize,
 +                                     pcbBytesNeeded,
 +                                     lpServicesReturned,
 +                                     lpResumeIndex,
 +                                     pszGroupNameW);
 +
 +    /* if no services were returned then we are Done */
 +    if (*lpServicesReturned == 0)
 +        goto Done;
 +
 +    lpStatusPtrA = (LPENUM_SERVICE_STATUS_PROCESSA)lpBuffer;
 +    lpStringPtrA = (LPSTR)((ULONG_PTR)lpBuffer +
 +                  *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSA));
 +    lpStringPtrW = (LPWSTR)((ULONG_PTR)lpStatusPtrW + 
 +                  *lpServicesReturned * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
 +
 +    for (dwServiceCount = 0; dwServiceCount < *lpServicesReturned; dwServiceCount++)
 +    {
 +        /* Copy the service name */
 +        WideCharToMultiByte(CP_ACP,
 +                            0,
 +                            lpStringPtrW,
 +                            -1,
 +                            lpStringPtrA,
 +                            wcslen(lpStringPtrW),
 +                            0,
 +                            0);
 +
 +        lpStatusPtrA->lpServiceName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
 +        lpStringPtrA += wcslen(lpStringPtrW) + 1;
 +        lpStringPtrW += wcslen(lpStringPtrW) + 1;
 +
 +        /* Copy the display name */
 +        WideCharToMultiByte(CP_ACP,
 +                            0,
 +                            lpStringPtrW,
 +                            -1,
 +                            lpStringPtrA,
 +                            wcslen(lpStringPtrW),
 +                            0,
 +                            0);
 +
 +        lpStatusPtrA->lpDisplayName = (LPSTR)((ULONG_PTR)lpStringPtrA - (ULONG_PTR)lpBuffer);
 +        lpStringPtrA += wcslen(lpStringPtrW) + 1;
 +        lpStringPtrW += wcslen(lpStringPtrW) + 1;
 +
 +        /* Copy the status information */
 +        memcpy(&lpStatusPtrA->ServiceStatusProcess,
 +               &lpStatusPtrW->ServiceStatusProcess,
 +               sizeof(SERVICE_STATUS));
 +
 +        lpStatusPtrA->ServiceStatusProcess.dwProcessId = lpStatusPtrW->ServiceStatusProcess.dwProcessId; /* FIXME */
 +        lpStatusPtrA->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
 +        lpStatusPtrA++;
 +    }
 +
 +Done:;
 +    if (pszGroupNameW)
 +        HeapFree(GetProcessHeap(), 0, pszGroupNameW);
 +
 +    if (lpStatusPtrW)
 +        HeapFree(GetProcessHeap(), 0, lpStatusPtrW);
 +
 +    DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 42 */
 +DWORD REnumServicesStatusExW(
 +    SC_RPC_HANDLE hSCManager,
 +    SC_ENUM_TYPE InfoLevel,
 +    DWORD dwServiceType,
 +    DWORD dwServiceState,
 +    LPBYTE lpBuffer,
 +    DWORD cbBufSize,
 +    LPBOUNDED_DWORD_256K pcbBytesNeeded,
 +    LPBOUNDED_DWORD_256K lpServicesReturned,
 +    LPBOUNDED_DWORD_256K lpResumeIndex,
 +    LPCWSTR pszGroupName)
 +{
 +    PMANAGER_HANDLE hManager;
 +    PSERVICE lpService;
 +    DWORD dwError = ERROR_SUCCESS;
 +    PLIST_ENTRY ServiceEntry;
 +    PSERVICE CurrentService;
 +    DWORD dwState;
 +    DWORD dwRequiredSize;
 +    DWORD dwServiceCount;
 +    DWORD dwSize;
 +    DWORD dwLastResumeCount = 0;
 +    LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
 +    LPWSTR lpStringPtr;
 +
 +    DPRINT("REnumServicesStatusExW() called\n");
 +
 +    if (ScmShutdown)
 +        return ERROR_SHUTDOWN_IN_PROGRESS;
 +
 +    if (InfoLevel != SC_ENUM_PROCESS_INFO)
 +        return ERROR_INVALID_LEVEL;
 +
 +    hManager = ScmGetServiceManagerFromHandle(hSCManager);
 +    if (hManager == NULL)
 +    {
 +        DPRINT1("Invalid service manager handle!\n");
 +        return ERROR_INVALID_HANDLE;
 +    }
 +
 +    *pcbBytesNeeded = 0;
 +    *lpServicesReturned = 0;
 +
 +    if ((dwServiceType!=SERVICE_DRIVER) && (dwServiceType!=SERVICE_WIN32))
 +    {
 +        DPRINT("Not a valid Service Type!\n");
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    if ((dwServiceState<SERVICE_ACTIVE) || (dwServiceState>SERVICE_STATE_ALL))
 +    {
 +        DPRINT("Not a valid Service State!\n");
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    /* Check access rights */
 +    if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
 +                                  SC_MANAGER_ENUMERATE_SERVICE))
 +    {
 +        DPRINT("Insufficient access rights! 0x%lx\n",
 +               hManager->Handle.DesiredAccess);
 +        return ERROR_ACCESS_DENIED;
 +    }
 +
 +    if (lpResumeIndex) dwLastResumeCount = *lpResumeIndex;
 +
 +    /* Lock the service list shared */
 +
 +    lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
 +    if (lpService == NULL)
 +    {
 +        dwError = ERROR_SUCCESS;
 +        goto Done;
 +    }
 +
 +    dwRequiredSize = 0;
 +    dwServiceCount = 0;
 +
 +    for (ServiceEntry = &lpService->ServiceListEntry;
 +         ServiceEntry != &ServiceListHead;
 +         ServiceEntry = ServiceEntry->Flink)
 +    {
 +        CurrentService = CONTAINING_RECORD(ServiceEntry,
 +                                           SERVICE,
 +                                           ServiceListEntry);
 +
 +        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
 +            continue;
 +
 +        dwState = SERVICE_ACTIVE;
 +        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
 +            dwState = SERVICE_INACTIVE;
 +
 +        if ((dwState & dwServiceState) == 0)
 +            continue;
 +
 +        if (pszGroupName)
 +        {
 +            if (*pszGroupName == 0)
 +            {
 +                if (CurrentService->lpGroup != NULL)
 +                    continue;
 +            }
 +            else
 +            {
 +                if ((CurrentService->lpGroup == NULL) ||
 +                    _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
 +                    continue;
 +            }
 +        }
 +
 +        dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
 +                 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
 +                 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
 +
 +        if (dwRequiredSize + dwSize <= cbBufSize)
 +        {
 +            DPRINT("Service name: %S  fit\n", CurrentService->lpServiceName);
 +            dwRequiredSize += dwSize;
 +            dwServiceCount++;
 +            dwLastResumeCount = CurrentService->dwResumeCount;
 +        }
 +        else
 +        {
 +            DPRINT("Service name: %S  no fit\n", CurrentService->lpServiceName);
 +            break;
 +        }
 +
 +    }
 +
 +    DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
 +    DPRINT("dwServiceCount: %lu\n", dwServiceCount);
 +
 +    for (;
 +         ServiceEntry != &ServiceListHead;
 +         ServiceEntry = ServiceEntry->Flink)
 +    {
 +        CurrentService = CONTAINING_RECORD(ServiceEntry,
 +                                           SERVICE,
 +                                           ServiceListEntry);
 +
 +        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
 +            continue;
 +
 +        dwState = SERVICE_ACTIVE;
 +        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
 +            dwState = SERVICE_INACTIVE;
 +
 +        if ((dwState & dwServiceState) == 0)
 +            continue;
 +
 +        if (pszGroupName)
 +        {
 +            if (*pszGroupName == 0)
 +            {
 +                if (CurrentService->lpGroup != NULL)
 +                    continue;
 +            }
 +            else
 +            {
 +                if ((CurrentService->lpGroup == NULL) ||
 +                    _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
 +                    continue;
 +            }
 +        }
 +
 +        dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
 +                           ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
 +                           ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
 +
 +        dwError = ERROR_MORE_DATA;
 +    }
 +
 +    DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
 +
 +    if (lpResumeIndex)
 +        *lpResumeIndex = dwLastResumeCount;
 +
 +    *lpServicesReturned = dwServiceCount;
 +    *pcbBytesNeeded = dwRequiredSize;
 +
 +    /* If there was no services that matched */
 +    if ((!dwServiceCount) && (dwError != ERROR_MORE_DATA))
 +    {
 +        dwError = ERROR_SERVICE_DOES_NOT_EXIST;
 +        goto Done;
 +    }
 +
 +    lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpBuffer;
 +    lpStringPtr = (LPWSTR)((ULONG_PTR)lpBuffer +
 +                           dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
 +
 +    dwRequiredSize = 0;
 +    for (ServiceEntry = &lpService->ServiceListEntry;
 +         ServiceEntry != &ServiceListHead;
 +         ServiceEntry = ServiceEntry->Flink)
 +    {
 +        CurrentService = CONTAINING_RECORD(ServiceEntry,
 +                                           SERVICE,
 +                                           ServiceListEntry);
 +
 +        if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
 +            continue;
 +
 +        dwState = SERVICE_ACTIVE;
 +        if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
 +            dwState = SERVICE_INACTIVE;
 +
 +        if ((dwState & dwServiceState) == 0)
 +            continue;
 +
 +        if (pszGroupName)
 +        {
 +            if (*pszGroupName == 0)
 +            {
 +                if (CurrentService->lpGroup != NULL)
 +                    continue;
 +            }
 +            else
 +            {
 +                if ((CurrentService->lpGroup == NULL) ||
 +                    _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
 +                    continue;
 +            }
 +        }
 +
 +        dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
 +                 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
 +                 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
 +
 +        if (dwRequiredSize + dwSize <= cbBufSize)
 +        {
 +            /* Copy the service name */
 +            wcscpy(lpStringPtr,
 +                   CurrentService->lpServiceName);
 +            lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
 +            lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
 +
 +            /* Copy the display name */
 +            wcscpy(lpStringPtr,
 +                   CurrentService->lpDisplayName);
 +            lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpBuffer);
 +            lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
 +
 +            /* Copy the status information */
 +            memcpy(&lpStatusPtr->ServiceStatusProcess,
 +                   &CurrentService->Status,
 +                   sizeof(SERVICE_STATUS));
 +            lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */
 +            lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
 +
 +            lpStatusPtr++;
 +            dwRequiredSize += dwSize;
 +        }
 +        else
 +        {
 +            break;
 +        }
 +    }
 +
 +    if (dwError == 0) 
 +    {
 +        *pcbBytesNeeded = 0;
 +        if (lpResumeIndex)
 +            *lpResumeIndex = 0;
 +    }
 +
 +Done:;
 +    /* Unlock the service list */
 +
 +    DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError);
 +
 +    return dwError;
 +}
 +
 +
 +/* Function 43 */
 +DWORD RSendTSMessage(
 +    handle_t BindingHandle)  /* FIXME */
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 44 */
 +DWORD RCreateServiceWOW64A(
 +    handle_t BindingHandle,
 +    LPSTR lpServiceName,
 +    LPSTR lpDisplayName,
 +    DWORD dwDesiredAccess,
 +    DWORD dwServiceType,
 +    DWORD dwStartType,
 +    DWORD dwErrorControl,
 +    LPSTR lpBinaryPathName,
 +    LPSTR lpLoadOrderGroup,
 +    LPDWORD lpdwTagId,
 +    LPBYTE lpDependencies,
 +    DWORD dwDependSize,
 +    LPSTR lpServiceStartName,
 +    LPBYTE lpPassword,
 +    DWORD dwPwSize,
 +    LPSC_RPC_HANDLE lpServiceHandle)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 45 */
 +DWORD RCreateServiceWOW64W(
 +    handle_t BindingHandle,
 +    LPWSTR lpServiceName,
 +    LPWSTR lpDisplayName,
 +    DWORD dwDesiredAccess,
 +    DWORD dwServiceType,
 +    DWORD dwStartType,
 +    DWORD dwErrorControl,
 +    LPWSTR lpBinaryPathName,
 +    LPWSTR lpLoadOrderGroup,
 +    LPDWORD lpdwTagId,
 +    LPBYTE lpDependencies,
 +    DWORD dwDependSize,
 +    LPWSTR lpServiceStartName,
 +    LPBYTE lpPassword,
 +    DWORD dwPwSize,
 +    LPSC_RPC_HANDLE lpServiceHandle)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 46 */
 +DWORD RQueryServiceTagInfo(
 +    handle_t BindingHandle)  /* FIXME */
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 47 */
 +DWORD RNotifyServiceStatusChange(
 +    SC_RPC_HANDLE hService,
 +    SC_RPC_NOTIFY_PARAMS NotifyParams,
 +    GUID *pClientProcessGuid,
 +    GUID *pSCMProcessGuid,
 +    PBOOL pfCreateRemoteQueue,
 +    LPSC_NOTIFY_RPC_HANDLE phNotify)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 48 */
 +DWORD RGetNotifyResults(
 +    SC_NOTIFY_RPC_HANDLE hNotify,
 +    PSC_RPC_NOTIFY_PARAMS_LIST *ppNotifyParams)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 49 */
 +DWORD RCloseNotifyHandle(
 +    LPSC_NOTIFY_RPC_HANDLE phNotify,
 +    PBOOL pfApcFired)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 50 */
 +DWORD RControlServiceExA(
 +    SC_RPC_HANDLE hService,
 +    DWORD dwControl,
 +    DWORD dwInfoLevel)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 51 */
 +DWORD RControlServiceExW(
 +    SC_RPC_HANDLE hService,
 +    DWORD dwControl,
 +    DWORD dwInfoLevel)
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 52 */
 +DWORD RSendPnPMessage(
 +    handle_t BindingHandle)  /* FIXME */
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 53 */
 +DWORD RValidatePnPService(
 +    handle_t BindingHandle)  /* FIXME */
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 54 */
 +DWORD ROpenServiceStatusHandle(
 +    handle_t BindingHandle)  /* FIXME */
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +/* Function 55 */
 +DWORD RFunction55(
 +    handle_t BindingHandle)  /* FIXME */
 +{
 +    UNIMPLEMENTED;
 +    return ERROR_CALL_NOT_IMPLEMENTED;
 +}
 +
 +
 +void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
 +{
 +    return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
 +}
 +
 +
 +void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
 +{
 +    HeapFree(GetProcessHeap(), 0, ptr);
 +}
 +
 +
 +void __RPC_USER SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject)
 +{
 +}
 +
 +
 +void __RPC_USER SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock)
 +{
 +}
 +
 +
 +void __RPC_USER SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify)
 +{
 +}
 +
 +/* EOF */
@@@ -1085,7 -1085,7 +1085,7 @@@ HKLM,"SYSTEM\CurrentControlSet\Services
  HKLM,"SYSTEM\CurrentControlSet\Services\Blue","ErrorControl",0x00010001,0x00000000
  HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Group",0x00000000,"Video Init"
  HKLM,"SYSTEM\CurrentControlSet\Services\Blue","ImagePath",0x00020000,"system32\drivers\blue.sys"
- HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Start",0x00010001,0x00000004
+ HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Start",0x00010001,0x00000001
  HKLM,"SYSTEM\CurrentControlSet\Services\Blue","Type",0x00010001,0x00000001
  
  ; Cdfs (ISO96660) filesystem driver
@@@ -586,6 -586,8 +586,8 @@@ media\fonts\symbol.tt
  media\fonts\tahoma.ttf                              3
  media\fonts\tahomabd.ttf                            3
  
+ media\vgafonts\vgafonts.cab                         4
  media\nls\c_037.nls                                 1
  media\nls\c_424.nls                                 1
  media\nls\c_500.nls                                 1
@@@ -146,7 -146,7 +146,7 @@@ typedef BOOL (WINAPI *STARTPAGEPRINTER
  typedef BOOL (WINAPI *SEEKPRINTER) (HANDLE,LARGE_INTEGER,PLARGE_INTEGER,DWORD,BOOL);
  typedef BOOL (WINAPI *SPLREADPRINTER) (HANDLE,LPBYTE *,DWORD);
  // Same as ddk/winsplp.h DriverUnloadComplete?
- typedef BOOL (WINAPI *SPLDRIVERUNLOADCOMPLETE) (LPWSTR); 
+ typedef BOOL (WINAPI *SPLDRIVERUNLOADCOMPLETE) (LPWSTR);
  // Driver support:
  // DrvDocumentEvent api/winddiui.h not W2k8 DocumentEventAW
  typedef INT (WINAPI *DOCUMENTEVENT) (HANDLE,HDC,INT,ULONG,PVOID,ULONG,PVOID);
@@@ -173,10 -173,10 +173,10 @@@ HEAP_strdupA2W
  VOID
  HEAP_free(LPVOID memory);
  
- VOID 
+ VOID
  FASTCALL
  FONT_TextMetricWToA(
-     const TEXTMETRICW *ptmW, 
+     const TEXTMETRICW *ptmW,
      LPTEXTMETRICA ptmA
  );
  
@@@ -279,7 -279,7 +279,7 @@@ WINAP
  GdiSetLastError( DWORD dwErrCode );
  
  DWORD WINAPI GdiGetCodePage(HDC);
- UINT FASTCALL DIB_BitmapBitsSize( PBITMAPINFO );
+ UINT FASTCALL DIB_BitmapBitsSize( CONST BITMAPINFO* );
  
  int
  WINAPI
@@@ -166,6 -166,10 +166,10 @@@ SetPixelFormat(HDC  hdc
                 INT  iPixelFormat,
                 CONST PIXELFORMATDESCRIPTOR * ppfd)
  {
+   /* Can only be set once */
+   INT current = GetPixelFormat(hdc);
+   if(current) return current == iPixelFormat ;
+   
    if (glSetPixelFormat == NULL)
      if (OpenGLEnable() == FALSE)
        return(0);
@@@ -34,7 -34,7 +34,7 @@@ DIB_BitmapMaxBitsSize( PBITMAPINFO Info
  
  UINT
  FASTCALL
- DIB_BitmapBitsSize( PBITMAPINFO Info )
+ DIB_BitmapBitsSize( CONST BITMAPINFO* Info )
  {
    UINT Ret;
  
    if ( Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
    {
       PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info;
-      Ret = Core->bcHeight * 
+      Ret = Core->bcHeight *
            ((Core->bcWidth * Core->bcPlanes * Core->bcBitCount  + 31) & ~31 ) / 8;
    }
    else /* assume BITMAPINFOHEADER */
    {
-      if ((Info->bmiHeader.biCompression) && 
+      if ((Info->bmiHeader.biCompression) &&
           (Info->bmiHeader.biCompression != BI_BITFIELDS))
           return Info->bmiHeader.biSizeImage;
          // Make Height positive always....
-      Ret = abs(Info->bmiHeader.biHeight) * 
+      Ret = abs(Info->bmiHeader.biHeight) *
            ((Info->bmiHeader.biWidth * Info->bmiHeader.biPlanes * Info->bmiHeader.biBitCount + 31) & ~31 ) / 8;
    }
    return Ret;
@@@ -132,12 -132,12 +132,12 @@@ WINAP
  GdiGetBitmapBitsSize(BITMAPINFO *lpbmi)
  {
      int retSize;
-     
      if (lpbmi->bmiHeader.biSize == FIELD_OFFSET(BITMAPINFOHEADER, biPlanes))
      {
          /* Calc the bits Size and align it*/
-         retSize = HIWORD(lpbmi->bmiHeader.biWidth) * ((LOWORD(lpbmi->bmiHeader.biWidth) * 
-                   LOWORD(lpbmi->bmiHeader.biHeight) * HIWORD(lpbmi->bmiHeader.biHeight) + 31) 
+         retSize = HIWORD(lpbmi->bmiHeader.biWidth) * ((LOWORD(lpbmi->bmiHeader.biWidth) *
+                   LOWORD(lpbmi->bmiHeader.biHeight) * HIWORD(lpbmi->bmiHeader.biHeight) + 31)
                    & -32) / 8;
      }
      else
              if (lpbmi->bmiHeader.biHeight >=0 )
              {
                  /* Calc the bits Size and align it*/
-                 retSize = lpbmi->bmiHeader.biHeight * ((lpbmi->bmiHeader.biWidth * 
+                 retSize = lpbmi->bmiHeader.biHeight * ((lpbmi->bmiHeader.biWidth *
                            lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
              }
              else
              {
                  /* Make height postiive if it negitve then calc the bits Size and align it*/
-                 retSize = (-lpbmi->bmiHeader.biHeight) * ((lpbmi->bmiHeader.biWidth * 
+                 retSize = (-lpbmi->bmiHeader.biHeight) * ((lpbmi->bmiHeader.biWidth *
                            lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
              }
          }
@@@ -189,7 -189,7 +189,7 @@@ CreateDIBSection
     {  // Verify header due to converted may == info.
        if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
        {
-          if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG || 
+          if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
                pConvertedInfo->bmiHeader.biCompression  == BI_PNG )
           {
              SetLastError(ERROR_INVALID_PARAMETER);
@@@ -319,7 -319,7 +319,7 @@@ CreateBitmapIndirect(const BITMAP *pbm
          (!(pbm->bmWidthBytes & 1)) )
  
     {
-         
        bitmap = CreateBitmap(pbm->bmWidth,
                              pbm->bmHeight,
                              pbm->bmPlanes,
@@@ -409,7 -409,7 +409,7 @@@ GetDIBits
       {
          if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
          {
-            if ( lpbmi->bmiHeader.biCompression == BI_JPEG || 
+            if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
                  lpbmi->bmiHeader.biCompression == BI_PNG )
             {
                SetLastError(ERROR_INVALID_PARAMETER);
@@@ -461,78 -461,61 +461,61 @@@ CreateDIBitmap( HDC hDC
    LONG width, height, compr, dibsize;
    WORD planes, bpp;
  //  PDC_ATTR pDc_Attr;
-   PBITMAPINFO pConvertedInfo;
-   UINT ConvertedInfoSize;
-   UINT cjBmpScanSize;
-   PVOID pvSafeBits = NULL;
+   UINT InfoSize = 0;
+   UINT cjBmpScanSize = 0;
    HBITMAP hBmp;
+   NTSTATUS Status = STATUS_SUCCESS;
  
    if (!Header) return 0;
  
-   pConvertedInfo = ConvertBitmapInfo(Data, ColorUse,
-                                           &ConvertedInfoSize, FALSE);
    if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
    {
       GdiSetLastError(ERROR_INVALID_PARAMETER);
       return NULL;
    }
  
-   if ( pConvertedInfo )
-   {
-      if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
-      {
-         if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG || 
-              pConvertedInfo->bmiHeader.biCompression == BI_PNG )
-         {
-            hBmp = NULL;
-            goto Exit;
-         }
-      }
-   }
-   
  // For Icm support.
  // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
  
-   cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
-   DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", pConvertedInfo,bpp,dibsize,ConvertedInfoSize,cjBmpScanSize);
+   if(Data)
+   {
+       _SEH2_TRY
+       {
+           cjBmpScanSize = DIB_BitmapBitsSize(Data);
+           CalculateColorTableSize(&Data->bmiHeader, &ColorUse, &InfoSize);
+           InfoSize += Data->bmiHeader.biSize;
+       }
+       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+       {
+             Status = _SEH2_GetExceptionCode();
+       }
+       _SEH2_END
+   }
+   if(!NT_SUCCESS(Status))
+   {
+      GdiSetLastError(ERROR_INVALID_PARAMETER);
+      return NULL;
+   }
+   DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", Data,bpp,dibsize,InfoSize,cjBmpScanSize);
  
    if ( !width || !height )
       hBmp = GetStockObject(DEFAULT_BITMAP);
    else
    {
-      if ( Bits && Init == CBM_INIT )
-      {
-         pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
-         if (pvSafeBits == NULL)
-         {
-             hBmp = NULL;
-             goto Exit;
-         }
-         else
-         {
-            RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
-         }
-      }
       hBmp = NtGdiCreateDIBitmapInternal(hDC,
                                          width,
                                          height,
                                          Init,
-                                         (LPBYTE)pvSafeBits,
-                                         (PBITMAPINFO)pConvertedInfo,
+                                         (LPBYTE)Bits,
+                                         (LPBITMAPINFO)Data,
                                          ColorUse,
-                                         ConvertedInfoSize,
+                                         InfoSize,
                                          cjBmpScanSize,
                                          0,
                                          0);
-      if ( Bits && Init == CBM_INIT )
-         RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
    }
- Exit:
-   if (Data != pConvertedInfo)
-      RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
    return hBmp;
  }
  
@@@ -588,7 -571,7 +571,7 @@@ SetDIBits(HDC hDC
  
   if ( hOldBitmap )
   {
-     if ( hDC )    
+     if ( hDC )
        hPal = SelectPalette(SavehDC, (HPALETTE)GetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE), FALSE);
  
      if ( lpbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
@@@ -782,7 -765,7 +765,7 @@@ SetDIBitsToDevice
  /*
    if ( !pDc_Attr ||
         ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
-        (pConvertedInfo->bmiHeader.biCompression == BI_JPEG || 
+        (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
          pConvertedInfo->bmiHeader.biCompression  == BI_PNG )) )*/
    {
      LinesCopied = NtGdiSetDIBitsToDeviceInternal( hdc,
       RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
    if (lpbmi != pConvertedInfo)
       RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
-          
    return LinesCopied;
  }
  
@@@ -886,17 -869,12 +869,12 @@@ StretchDIBits(HDC hdc
      }
    }
  #endif
-   if ( iUsage ) // Save time, we only look at non RGB.
-   {
-      pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
-                                       &ConvertedInfoSize, FALSE);
-      if (!pConvertedInfo)
-      {
+     pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
+                                   &ConvertedInfoSize, FALSE);
+     if (!pConvertedInfo)
+     {
          return 0;
-      }
-   }
-   else
-      pConvertedInfo = (PBITMAPINFO)lpBitsInfo;
+     }
  
    cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
  
  /*
    if ( !pDc_Attr ||
         ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
-        (pConvertedInfo->bmiHeader.biCompression == BI_JPEG || 
+        (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
          pConvertedInfo->bmiHeader.biCompression  == BI_PNG )) )*/
    {
       LinesCopied = NtGdiStretchDIBitsInternal( hdc,
@@@ -15,7 -15,7 +15,7 @@@ IntCreateDICW ( LPCWSTR   lpwszDriver
  {
   UNICODE_STRING Device, Output;
   HDC hDC = NULL;
-  BOOL Display = FALSE, Default = TRUE;
+  BOOL Display = FALSE, Default = FALSE;
   ULONG UMdhpdev = 0;
  
   HANDLE hspool = NULL;
@@@ -31,7 -31,7 +31,7 @@@
  
   if ((!lpwszDevice) && (!lpwszDriver))
   {
-      Default = FALSE;  // Ask Win32k to set Default device.
+      Default = TRUE;  // Ask Win32k to set Default device.
       Display = TRUE;   // Most likely to be DISPLAY.
   }
   else
@@@ -60,7 -60,7 +60,7 @@@
      DPRINT1("Not a DISPLAY device! %wZ\n", &Device);
   }
  
-  hDC = NtGdiOpenDCW( (Default ? &Device : NULL),
+  hDC = NtGdiOpenDCW( (Default ? NULL : &Device),
                       (PDEVMODEW) lpInitData,
                       (lpwszOutput ? &Output : NULL),
                        iType,             // DCW 0 and ICW 1.
@@@ -318,7 -318,7 +318,7 @@@ WINAP
  DeleteObject(HGDIOBJ hObject)
  {
    UINT Type = 0;
-     
    /* From Wine: DeleteObject does not SetLastError() on a null object */
    if(!hObject) return FALSE;
  
  
    Type = GDI_HANDLE_GET_TYPE(hObject);
  
-   if ((Type == GDI_OBJECT_TYPE_METAFILE) || 
+   if ((Type == GDI_OBJECT_TYPE_METAFILE) ||
        (Type == GDI_OBJECT_TYPE_ENHMETAFILE))
       return FALSE;
  
       case GDI_OBJECT_TYPE_METADC:
         return MFDRV_DeleteObject( hObject );
       case GDI_OBJECT_TYPE_EMF:
-      {          
+      {
         PLDC pLDC = GdiGetLDC(hObject);
         if ( !pLDC ) return FALSE;
         return EMFDRV_DeleteObject( hObject );
@@@ -533,7 -533,7 +533,7 @@@ GetDeviceCaps(HDC hDC
          return NtGdiGetDeviceCaps(hDC,i);
    }
    DPRINT("Device CAPS2\n");
-   
    switch (i)
    {
      case DRIVERVERSION:
@@@ -1603,7 -1603,7 +1603,7 @@@ SelectObject(HDC hDC
  
  #if 0
          case GDI_OBJECT_TYPE_METADC:
-             return MFDRV_SelectObject( hDC, hGdiObj); 
+             return MFDRV_SelectObject( hDC, hGdiObj);
          case GDI_OBJECT_TYPE_EMF:
              PLDC pLDC = GdiGetLDC(hDC);
              if ( !pLDC ) return NULL;
@@@ -1,2 -1,12 +1,12 @@@
  HCURSOR
- CursorIconToCursor(HICON hIcon, BOOL SemiTransparent);
+ CursorIconToCursor(HICON hIcon,
+                    BOOL SemiTransparent);
+ HICON CreateCursorIconFromData(PVOID ImageData,
+                                ICONIMAGE* IconImage,
+                                int cxDesired,
+                                int cyDesired,
+                                int xHotspot,
+                                int yHotspot,
+                                BOOL fIcon);
@@@ -43,7 -43,8 +43,8 @@@
  #include <pseh/pseh2.h>
  
  #define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
- #define ISITHOOKED(HookId) (GetWin32ClientInfo()->fsHooks & HOOKID_TO_FLAG(HookId))
+ #define ISITHOOKED(HookId) (GetWin32ClientInfo()->fsHooks & HOOKID_TO_FLAG(HookId) ||\
+                            (GetWin32ClientInfo()->pDeskInfo && GetWin32ClientInfo()->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId)))
  
  /* Temporarily in here for now. */
  typedef struct _USERAPIHOOKINFO
@@@ -168,7 -169,7 +169,7 @@@ SharedPtrToKernel(PVOID Ptr
  static __inline BOOL
  IsThreadHooked(PCLIENTINFO pci)
  {
-     return pci->fsHooks != 0;
+     return (pci->fsHooks|pci->pDeskInfo->fsHooks) != 0;
  }
  
  static __inline PDESKTOPINFO
@@@ -194,3 -195,4 +195,4 @@@ VOID FASTCALL GetConnected(VOID)
  BOOL FASTCALL DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi);
  BOOL FASTCALL TestWindowProcess(PWND);
  VOID UserGetWindowBorders(DWORD, DWORD, SIZE *, BOOL);
+ VOID FASTCALL IntNotifyWinEvent(DWORD, HWND, LONG, LONG, DWORD);
@@@ -83,9 -83,6 +83,6 @@@
  #define NtUserGetCursorPos(lpPoint) \
    (BOOL)NtUserCallOneParam((DWORD_PTR)lpPoint, ONEPARAM_ROUTINE_GETCURSORPOSITION)
  
- #define NtUserIsWindowInDestroy(hWnd) \
-   (BOOL)NtUserCallOneParam((DWORD_PTR)hWnd, ONEPARAM_ROUTINE_ISWINDOWINDESTROY)
  #define NtUserEnableProcessWindowGhosting(bEnable) \
    NtUserCallOneParam((DWORD_PTR)bEnable, ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING)
  
@@@ -457,7 -457,6 +457,6 @@@ ChangeDisplaySettingsExA
    LONG rc;
    UNICODE_STRING DeviceName;
    PUNICODE_STRING pDeviceName = &DeviceName;
-   LPDEVMODEW pDevModeW;
  
    if (lpszDeviceName != NULL)
      {
      pDeviceName = NULL;
  
    if (lpDevMode != NULL)
+   {
+     LPDEVMODEW pDevModeW;
      pDevModeW = GdiConvertToDevmodeW(lpDevMode);
+     if(pDevModeW)
+     {
+       rc = NtUserChangeDisplaySettings ( pDeviceName, pDevModeW, hwnd, dwflags, lParam );
+       RtlFreeHeap(GetProcessHeap(), 0, pDevModeW);
+     }
+     else
+       rc = DISP_CHANGE_SUCCESSFUL;
+   }
    else
-     pDevModeW = NULL;
-   rc = NtUserChangeDisplaySettings ( pDeviceName, pDevModeW, hwnd, dwflags, lParam );
-   if (pDevModeW != NULL)
-     RtlFreeHeap(GetProcessHeap(), 0, pDevModeW);
+     rc = NtUserChangeDisplaySettings ( pDeviceName, NULL, hwnd, dwflags, lParam );
  
    if (lpszDeviceName != NULL)
      RtlFreeUnicodeString ( &DeviceName );
@@@ -539,6 -543,6 +543,6 @@@ ChangeDisplaySettingsW
    DWORD dwflags)
  {
    if(lpDevMode)
-     lpDevMode->dmDriverExtra = 0; 
+     lpDevMode->dmDriverExtra = 0;
    return ChangeDisplaySettingsExW ( NULL, lpDevMode, NULL, dwflags, 0 );
  }
@@@ -304,13 -304,13 +304,13 @@@ GetUser32Handle(HANDLE handle
  static const BOOL g_ObjectHeapTypeShared[VALIDATE_TYPE_EVENT + 1] =
  {
      FALSE, /* VALIDATE_TYPE_FREE (not used) */
-     FALSE, /* VALIDATE_TYPE_WIN  FALSE */
+     FALSE, /* VALIDATE_TYPE_WIN */
      TRUE, /* VALIDATE_TYPE_MENU  FALSE */
      TRUE, /* VALIDATE_TYPE_CURSOR */
      TRUE, /* VALIDATE_TYPE_MWPOS */
-     TRUE, /* VALIDATE_TYPE_HOOK  FALSE */
+     FALSE, /* VALIDATE_TYPE_HOOK */
      FALSE, /* (not used) */
-     TRUE, /* VALIDATE_TYPE_CALLPROC  FALSE */
+     FALSE, /* VALIDATE_TYPE_CALLPROC */
      TRUE, /* VALIDATE_TYPE_ACCEL */
      FALSE, /* (not used) */
      FALSE, /* (not used) */
@@@ -298,7 -298,7 +298,7 @@@ IntGetWndProc(PWND pWnd, BOOL Ansi
       }
       return Ret;
    }
-   // Wine Class tests: 
+   // Wine Class tests:
    /*  Edit controls are special - they return a wndproc handle when
        GetWindowLongPtr is called with a different A/W.
        On the other hand there is no W->A->W conversion so this control
@@@ -831,7 -831,6 +831,6 @@@ CreateSmallIcon(HICON StdIcon
     int SmallIconWidth;
     int SmallIconHeight;
     BITMAP StdBitmapInfo;
-    HDC hInfoDc = NULL;
     HDC hSourceDc = NULL;
     HDC hDestDc = NULL;
     ICONINFO SmallInfo;
        return StdIcon;
     }
  
-    /* Get a handle to a info DC and handles to DCs which can be used to
-       select a bitmap into. This is done to avoid triggering a switch to
-       graphics mode (if we're currently in text/blue screen mode) */
-    hInfoDc = CreateICW(NULL, NULL, NULL, NULL);
-    if (NULL == hInfoDc)
-    {
-       ERR("Failed to create info DC\n");
-       goto cleanup;
-    }
     hSourceDc = CreateCompatibleDC(NULL);
     if (NULL == hSourceDc)
     {
        ERR("Failed to select source color bitmap\n");
        goto cleanup;
     }
-    SmallInfo.hbmColor = CreateCompatibleBitmap(hInfoDc, SmallIconWidth,
+    SmallInfo.hbmColor = CreateCompatibleBitmap(hSourceDc, SmallIconWidth,
                                                SmallIconHeight);
     if (NULL == SmallInfo.hbmColor)
     {
        ERR("Failed to select source mask bitmap\n");
        goto cleanup;
     }
-    SmallInfo.hbmMask = CreateBitmap(SmallIconWidth, SmallIconHeight, 1, 1,
-                                     NULL);
+    SmallInfo.hbmMask = CreateCompatibleBitmap(hSourceDc, SmallIconWidth, SmallIconHeight);
     if (NULL == SmallInfo.hbmMask)
     {
        ERR("Failed to create mask bitmap\n");
@@@ -976,10 -965,6 +965,6 @@@ cleanup
     {
        DeleteDC(hSourceDc);
     }
-    if (NULL != hInfoDc)
-    {
-       DeleteDC(hInfoDc);
-    }
  
     return SmallIcon;
  }
@@@ -1070,9 -1055,9 +1055,9 @@@ RegisterClassExWOWW(WNDCLASSEXW *lpwcx
     clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer;
     clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer;
     clsMenuName.pusMenuName = &MenuName;
-    
     Atom = NtUserRegisterClassExWOW( &WndClass,
-                                     &ClassName,  
+                                     &ClassName,
                                       NULL, //PUNICODE_STRING ClsNVersion,
                                      &clsMenuName,
                                       fnID,
@@@ -458,10 -458,16 +458,16 @@@ static BOOL create_icon_bitmaps( const 
      void *color_bits, *mask_bits;
      BOOL ret = FALSE;
      HDC hdc = 0;
+       static HDC hScreenDC = 0;
  
      if (!(info = HeapAlloc( GetProcessHeap(), 0, max( size, FIELD_OFFSET( BITMAPINFO, bmiColors[2] )))))
          return FALSE;
-     if (!(hdc = CreateCompatibleDC( 0 ))) goto done;
+       if(!hScreenDC)
+       {
+               hScreenDC = GetDC(0);
+               if(!hScreenDC) goto done;
+       }
+     if (!(hdc = CreateCompatibleDC(hScreenDC))) goto done;
  
      memcpy( info, bmi, size );
      info->bmiHeader.biHeight /= 2;
      else
      {
          if (!(*mask = CreateBitmap( width, height, 1, 1, NULL ))) goto done;
-         if (!(*color = CreateBitmap( width, height, bmi->bmiHeader.biPlanes,
-                                      bmi->bmiHeader.biBitCount, NULL )))
+         if (!(*color = CreateBitmap( width, height, GetDeviceCaps(hScreenDC, PLANES),
+                                      GetDeviceCaps(hScreenDC, BITSPIXEL), NULL )))
          {
              DeleteObject( *mask );
              goto done;
      ret = TRUE;
  
  done:
-     DeleteDC( hdc );
+     if(hdc) DeleteDC( hdc );
      HeapFree( GetProcessHeap(), 0, info );
      return ret;
  }
@@@ -103,6 -103,7 +103,7 @@@ BOO
  FASTCALL
  DefSetText(HWND hWnd, PCWSTR String, BOOL Ansi)
  {
+   BOOL Ret;
    LARGE_STRING lsString;
  
    if ( String )
       else
          RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&lsString, String, 0);
    }
-   return NtUserDefSetText(hWnd, (String ? &lsString : NULL));
+   Ret = NtUserDefSetText(hWnd, (String ? &lsString : NULL));
+   if (Ret)
+      IntNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
+   return Ret;
  }
  
  void
@@@ -1969,7 -1975,6 +1975,6 @@@ RealDefWindowProcA(HWND hWnd
              {
                  DefWndNCPaint(hWnd, (HRGN)1, -1);
              }
              Result = 1;
              break;
          }
@@@ -1373,9 -1373,9 +1373,9 @@@ IntDrawState(HDC hdc, HBRUSH hbr, DRAWS
      }
  
      if (flags & DSS_DISABLED)
-         hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DHILIGHT));
+         hbrtmp = GetSysColorBrush(COLOR_3DHILIGHT);
      else if (flags & DSS_DEFAULT)
-         hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
+         hbrtmp = GetSysColorBrush(COLOR_3DSHADOW);
  
      /* Draw light or dark shadow */
      if (flags & (DSS_DISABLED|DSS_DEFAULT))
          if(!BitBlt(hdc, x+1, y+1, cx, cy, memdc, 0, 0, 0x00B8074A))
              goto cleanup;
          SelectObject(hdc, hbsave);
-         DeleteObject(hbrtmp);
-         hbrtmp = 0;
      }
  
      if (flags & DSS_DISABLED)
      {
-         hbr = hbrtmp = CreateSolidBrush(GetSysColor(COLOR_3DSHADOW));
+         hbr = hbrtmp = GetSysColorBrush(COLOR_3DSHADOW);
          if(!hbrtmp)
              goto cleanup;
      }
@@@ -1418,8 -1416,6 +1416,6 @@@ cleanup
          SelectObject(hdc, hbsave);
      if(hbmsave)
          SelectObject(memdc, hbmsave);
-     if(hbrtmp)
-         DeleteObject(hbrtmp);
      if(hbm)
          DeleteObject(hbm);
      if(memdc)
  
  WINE_DEFAULT_DEBUG_CHANNEL(user32);
  
+ typedef struct _NOTIFYEVENT
+ {
+    DWORD event;
+    LONG  idObject;
+    LONG  idChild;
+    DWORD flags;
+ } NOTIFYEVENT, *PNOTIFYEVENT;
  /* PRIVATE FUNCTIONS *********************************************************/
  
  static
@@@ -99,6 -107,29 +107,29 @@@ IntSetWindowsHook
    return NtUserSetWindowsHookEx(hMod, &USModuleName, dwThreadId, idHook, lpfn, bAnsi);
  }
  
+ /*
+    Since ReactOS uses User32 as the main message source this was needed.
+    Base on the funny rules from the wine tests it left it with this option.
+    8^(
+  */
+ VOID
+ FASTCALL
+ IntNotifyWinEvent(
+                  DWORD event,
+                  HWND  hwnd,
+                  LONG  idObject,
+                  LONG  idChild,
+                  DWORD flags
+                  )
+ {
+   NOTIFYEVENT ne;
+   ne.event    = event;
+   ne.idObject = idObject;
+   ne.idChild  = idChild;
+   ne.flags    = flags;
+   if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(event))
+   NtUserCallHwndParam(hwnd, (DWORD)&ne, HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT);
+ }
  
  /* FUNCTIONS *****************************************************************/
  
@@@ -195,7 -226,7 +226,7 @@@ CallNextHookEx
  {
    PCLIENTINFO ClientInfo;
    DWORD Flags, Save;
-   PHOOK pHook;
+   PHOOK pHook, phkNext;
    LRESULT lResult = 0;
  
    GetConnected();
  
    if (!ClientInfo->phkCurrent) return 0;
    
-   pHook = SharedPtrToUser(ClientInfo->phkCurrent);
+   pHook = DesktopPtrToUser(ClientInfo->phkCurrent);
+   if (!pHook->phkNext) return 0; // Nothing to do....
+   phkNext = DesktopPtrToUser(pHook->phkNext);
  
-   if (pHook->HookId == WH_CALLWNDPROC || pHook->HookId == WH_CALLWNDPROCRET)
+   if ( phkNext->HookId == WH_CALLWNDPROC ||
+        phkNext->HookId == WH_CALLWNDPROCRET)
    {
       Save = ClientInfo->dwHookData;
       Flags = ClientInfo->CI_flags & CI_CURTHPRHOOK;
       if (wParam) ClientInfo->CI_flags |= CI_CURTHPRHOOK;
       else        ClientInfo->CI_flags &= ~CI_CURTHPRHOOK;
  
-      if (pHook->HookId == WH_CALLWNDPROC)
+      if (phkNext->HookId == WH_CALLWNDPROC)
       {
          PCWPSTRUCT pCWP = (PCWPSTRUCT)lParam;
  
                             pCWP->lParam, 
                            (ULONG_PTR)&lResult,
                             FNID_CALLWNDPROC,
-                            pHook->Ansi);
+                            phkNext->Ansi);
       }
       else
       {
                             pCWPR->lParam, 
                            (ULONG_PTR)&lResult,
                             FNID_CALLWNDPROCRET,
-                            pHook->Ansi);
+                            phkNext->Ansi);
       }
       ClientInfo->CI_flags ^= ((ClientInfo->CI_flags ^ Flags) & CI_CURTHPRHOOK);
       ClientInfo->dwHookData = Save;
  
  
  /*
-  * @unimplemented
+  * @implemented
   */
  HHOOK
  WINAPI
  SetWindowsHookW(int idHook, HOOKPROC lpfn)
  {
-   return IntSetWindowsHook(idHook, lpfn, NULL, 0, FALSE);
+   DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
+   return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, FALSE);
+ //  return NtUserSetWindowsHookAW(idHook, lpfn, FALSE);
  }
  
  /*
-  * @unimplemented
+  * @implemented
   */
  HHOOK
  WINAPI
  SetWindowsHookA(int idHook, HOOKPROC lpfn)
  {
-   return IntSetWindowsHook(idHook, lpfn, NULL, 0, TRUE);
+   DWORD ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
+   return IntSetWindowsHook(idHook, lpfn, NULL, ThreadId, TRUE);
+ //  return NtUserSetWindowsHookAW(idHook, lpfn, TRUE);
  }
  
  /*
@@@ -377,7 -417,7 +417,7 @@@ IsWinEventHookInstalled
  }
  
  /*
-  * @unimplemented
+  * @implemented
   */
  HHOOK
  WINAPI
@@@ -392,7 -432,7 +432,7 @@@ SetWindowsHookExA
  
  
  /*
-  * @unimplemented
+  * @implemented
   */
  HHOOK
  WINAPI
@@@ -409,22 -449,21 +449,21 @@@ NTSTATUS WINAP
  User32CallHookProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
  {
    PHOOKPROC_CALLBACK_ARGUMENTS Common;
-   LRESULT Result;
    CREATESTRUCTW Csw;
    CBT_CREATEWNDW CbtCreatewndw;
-   CREATESTRUCTA Csa;
-   CBT_CREATEWNDA CbtCreatewnda;
    PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
-   WPARAM wParam = 0;
-   LPARAM lParam = 0;
-   PKBDLLHOOKSTRUCT KeyboardLlData;
-   PMSLLHOOKSTRUCT MouseLlData;
-   PMSG Msg;
-   PMOUSEHOOKSTRUCT MHook;
-   PCWPSTRUCT CWP;
-   PCWPRETSTRUCT CWPR;
+   KBDLLHOOKSTRUCT KeyboardLlData, *pKeyboardLlData;
+   MSLLHOOKSTRUCT MouseLlData, *pMouseLlData;
+   MSG Msg, *pMsg;
+   PMOUSEHOOKSTRUCT pMHook;
+   CWPSTRUCT CWP, *pCWP;
+   CWPRETSTRUCT CWPR, *pCWPR;
    PRECTL prl;  
    LPCBTACTIVATESTRUCT pcbtas;
+   WPARAM wParam = 0;
+   LPARAM lParam = 0;
+   LRESULT Result = 0;
+   BOOL Hit = FALSE;
  
    Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Arguments;
  
            CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS)
                                ((PCHAR) Common + Common->lParam);
            Csw = CbtCreatewndExtra->Cs;
-           if (NULL != CbtCreatewndExtra->Cs.lpszName)
-           {
-               Csw.lpszName = (LPCWSTR)((PCHAR) CbtCreatewndExtra
-                                        + (ULONG_PTR) CbtCreatewndExtra->Cs.lpszName);
-           }
-           if (0 != HIWORD(CbtCreatewndExtra->Cs.lpszClass))
-           {
-               Csw.lpszClass = (LPCWSTR)((PCHAR) CbtCreatewndExtra
-                                          + LOWORD((ULONG_PTR) CbtCreatewndExtra->Cs.lpszClass));
-           }
+           Csw.lpszName = CbtCreatewndExtra->Cs.lpszName;
+           Csw.lpszClass = CbtCreatewndExtra->Cs.lpszClass;
            wParam = Common->wParam;
-           if (Common->Ansi)
-           {
-               memcpy(&Csa, &Csw, sizeof(CREATESTRUCTW));
-               CbtCreatewnda.lpcs = &Csa;
-               CbtCreatewnda.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
-               lParam = (LPARAM) &CbtCreatewnda;
-           }
-           else
-           {
-               CbtCreatewndw.lpcs = &Csw;
-               CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
-               lParam = (LPARAM) &CbtCreatewndw;
-           }
+           CbtCreatewndw.lpcs = &Csw;
+           CbtCreatewndw.hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
+           lParam = (LPARAM) &CbtCreatewndw;
            break;
          case HCBT_CLICKSKIPPED:
-             MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
-             lParam = (LPARAM) MHook;
+             pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+             lParam = (LPARAM) pMHook;
              break;
          case HCBT_MOVESIZE:
              prl = (PRECTL)((PCHAR) Common + Common->lParam);
              pcbtas = (LPCBTACTIVATESTRUCT)((PCHAR) Common + Common->lParam);
              lParam = (LPARAM) pcbtas;
              break;
-         case HCBT_KEYSKIPPED:
+         case HCBT_KEYSKIPPED: /* The rest SEH support */
          case HCBT_MINMAX:
          case HCBT_SETFOCUS:
          case HCBT_SYSCOMMAND:
        }
  
        if (Common->Proc)
-          Result = Common->Proc(Common->Code, wParam, lParam);
+       {
+          _SEH2_TRY
+          {
+             Result = Common->Proc(Common->Code, wParam, lParam);
+          }
+          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+          {
+             Hit = TRUE;
+          }
+          _SEH2_END;
+       }
        else
        {
           ERR("Common = 0x%x, Proc = 0x%x\n",Common,Common->Proc);
        {
          case HCBT_CREATEWND:
            CbtCreatewndExtra->WndInsertAfter = CbtCreatewndw.hwndInsertAfter; 
+           CbtCreatewndExtra->Cs.x = CbtCreatewndw.lpcs->x;
+           CbtCreatewndExtra->Cs.y = CbtCreatewndw.lpcs->y;
+           CbtCreatewndExtra->Cs.cx = CbtCreatewndw.lpcs->cx;
+           CbtCreatewndExtra->Cs.cy = CbtCreatewndw.lpcs->cy;
            break;
        }
        break;
      }
      case WH_KEYBOARD_LL:
-       KeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
-       Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) KeyboardLlData);
+       ERR("WH_KEYBOARD_LL: Code %d, wParam %d\n",Common->Code,Common->wParam);
+       pKeyboardLlData = (PKBDLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+       RtlCopyMemory(&KeyboardLlData, pKeyboardLlData, sizeof(KBDLLHOOKSTRUCT));
+       Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &KeyboardLlData);
        break;
      case WH_MOUSE_LL:
-       MouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
-       Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MouseLlData);
+       pMouseLlData = (PMSLLHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+       RtlCopyMemory(&MouseLlData, pMouseLlData, sizeof(MSLLHOOKSTRUCT));
+       Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &MouseLlData);
        break;
-     case WH_MOUSE:
-       MHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
-       Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) MHook);
+     case WH_MOUSE: /* SEH support */
+       pMHook = (PMOUSEHOOKSTRUCT)((PCHAR) Common + Common->lParam);
+       _SEH2_TRY
+       {
+          Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) pMHook);
+       }
+       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+       {
+          Hit = TRUE;
+       }
+       _SEH2_END;
        break;
      case WH_CALLWNDPROC:
-       CWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam);
-       Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWP);
+       ERR("WH_CALLWNDPROC: Code %d, wParam %d\n",Common->Code,Common->wParam);
+       pCWP = (PCWPSTRUCT)((PCHAR) Common + Common->lParam);
+       RtlCopyMemory(&CWP, pCWP, sizeof(CWPSTRUCT));
+       Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWP);
        break;
      case WH_CALLWNDPROCRET:
-       CWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam);
-       Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) CWPR);
+       pCWPR = (PCWPRETSTRUCT)((PCHAR) Common + Common->lParam);
+       RtlCopyMemory(&CWPR, pCWPR, sizeof(CWPRETSTRUCT));
+       Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &CWPR);
        break;
-     case WH_MSGFILTER:
+     case WH_MSGFILTER: /* All SEH support */
+       ERR("WH_MSGFILTER: Code %d, wParam %d\n",Common->Code,Common->wParam);
      case WH_SYSMSGFILTER:
      case WH_GETMESSAGE:
-       Msg = (PMSG)((PCHAR) Common + Common->lParam);
- //      FIXME("UHOOK Memory: %x: %x\n",Common, Msg);
-       Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) Msg);
+       pMsg = (PMSG)((PCHAR) Common + Common->lParam);
+       RtlCopyMemory(&Msg, pMsg, sizeof(MSG));
+       _SEH2_TRY
+       {
+          Result = Common->Proc(Common->Code, Common->wParam, (LPARAM) &Msg);
+       }
+       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+       {
+          Hit = TRUE;
+       }
+       _SEH2_END;
+       if (!Hit && Common->HookId == WH_GETMESSAGE)
+          RtlCopyMemory(pMsg, &Msg, sizeof(MSG));
        break;
-     case WH_FOREGROUNDIDLE:
+     case WH_FOREGROUNDIDLE: /* <-- SEH support */
      case WH_KEYBOARD:
      case WH_SHELL:
-       Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
+       _SEH2_TRY
+       {
+          Result = Common->Proc(Common->Code, Common->wParam, Common->lParam);
+       }
+       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+       {
+          Hit = TRUE;
+       }
+       _SEH2_END;
        break;
      default:
        return ZwCallbackReturn(NULL, 0, STATUS_NOT_SUPPORTED);
    }
+   if (Hit)
+   {
+      ERR("Hook Exception! Id: %d, Code %d, Proc 0x%x\n",Common->HookId,Common->Code,Common->Proc);
+   }
    return ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS);
  }
  
@@@ -138,6 -138,7 +138,7 @@@ EnableWindow(HWND hWnd
      
      if (Update)
      {
+         IntNotifyWinEvent(EVENT_OBJECT_STATECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
          SendMessageW(hWnd, WM_ENABLE, (LPARAM)bEnable, 0);
      }
      // Return nonzero if it was disabled, or zero if it wasn't:
@@@ -1636,6 -1636,8 +1636,8 @@@ static BOOL FASTCALL MenuShowPopup(HWN
          top_popup_hmenu = hmenu;
      }
  
+     IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPSTART, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
      /* Display the window */
  
      SetWindowPos( MenuInfo.Wnd, HWND_TOPMOST, 0, 0, 0, 0,
@@@ -3445,6 -3447,7 +3447,7 @@@ static INT FASTCALL MenuTrackMenu(HMEN
  
                  if (MenuInfo.Flags & MF_POPUP)
                  {
+                     IntNotifyWinEvent(EVENT_SYSTEM_MENUPOPUPEND, MenuInfo.Wnd, OBJID_CLIENT, CHILDID_SELF, 0);
                      DestroyWindow(MenuInfo.Wnd);
                      MenuInfo.Wnd = NULL;
  
@@@ -3518,7 -3521,11 +3521,11 @@@ static BOOL FASTCALL MenuInitTracking(H
          MenuInfo.Wnd = hWnd;
          MenuSetRosMenuInfo(&MenuInfo);
      }
-  
+     IntNotifyWinEvent( EVENT_SYSTEM_MENUSTART,
+                        hWnd,
+                        MenuInfo.Flags & MF_SYSMENU ? OBJID_SYSMENU : OBJID_MENU,
+                        CHILDID_SELF, 0);
      return TRUE;
  }
  /***********************************************************************
@@@ -3528,6 -3535,7 +3535,7 @@@ static BOOL FASTCALL MenuExitTracking(H
  {
      TRACE("hwnd=%p\n", hWnd);
  
+     IntNotifyWinEvent( EVENT_SYSTEM_MENUEND, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
      SendMessageW( hWnd, WM_EXITMENULOOP, bPopup, 0 );
      ShowCaret(0);
      top_popup = 0;
@@@ -3645,7 -3653,7 +3653,7 @@@ BOOL WINAPI TrackPopupMenuEx( HMENU Men
  {
      BOOL ret = FALSE;
  
-     if (!IsMenu(Menu))
+     if (!IsMenu(Menu))    
      {
        SetLastError( ERROR_INVALID_MENU_HANDLE );
        return FALSE;
@@@ -2064,13 -2064,18 +2064,18 @@@ SendMessageW(HWND Wnd
  
    if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
    {
-       if (Window != NULL && Window->head.pti == ti && !IsThreadHooked(GetWin32ClientInfo()))
+       if ( Window != NULL &&
+            Window->head.pti == ti &&
+           !IsThreadHooked(GetWin32ClientInfo()) &&
+           !(Window->state & WNDS_SERVERSIDEWINDOWPROC) )
        {
            /* NOTE: We can directly send messages to the window procedure
                     if *all* the following conditions are met:
  
                     * Window belongs to calling thread
                     * The calling thread is not being hooked
+                    * Not calling a server side proc:
+                      Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
             */
  
            return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, FALSE);
@@@ -2130,13 -2135,18 +2135,18 @@@ SendMessageA(HWND Wnd, UINT Msg, WPARA
  
    if (Wnd != HWND_BROADCAST && (Msg < WM_DDE_FIRST || Msg > WM_DDE_LAST))
    {
-       if (Window != NULL && Window->head.pti == ti && !IsThreadHooked(GetWin32ClientInfo()))
+       if ( Window != NULL &&
+            Window->head.pti == ti &&
+           !IsThreadHooked(GetWin32ClientInfo()) &&
+           !(Window->state & WNDS_SERVERSIDEWINDOWPROC) )
        {
            /* NOTE: We can directly send messages to the window procedure
                     if *all* the following conditions are met:
  
                     * Window belongs to calling thread
                     * The calling thread is not being hooked
+                    * Not calling a server side proc: 
+                      Desktop, Switch, ScrollBar, Menu, IconTitle, or hWndMessage
             */
  
            return IntCallMessageProc(Window, Wnd, Msg, wParam, lParam, TRUE);
@@@ -2060,7 -2060,11 +2060,11 @@@ AnyPopup(VOID
  BOOL WINAPI
  IsWindowInDestroy(HWND hWnd)
  {
-     return NtUserIsWindowInDestroy(hWnd);
+     PWND pwnd;
+     pwnd = ValidateHwnd(hWnd);
+     if (!pwnd)
+        return FALSE;
+     return ((pwnd->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY);
  }
  
  /*
@@@ -47,6 -47,25 +47,25 @@@ FindPropertyHandler
                          IoStatus->Information = PropertySet[Index].PropertyItem[ItemIndex].MinData;
                          return STATUS_MORE_ENTRIES;
                      }
+                     /* store property set */
+                     *Set = (PKSPROPERTY_SET)&PropertySet[Index];
+                     if (Property->Flags & KSPROPERTY_TYPE_SET)
+                     {
+                         /* store property handler */
+                         *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler;
+                         return STATUS_SUCCESS;
+                     }
+                     if (Property->Flags & KSPROPERTY_TYPE_GET)
+                     {
+                         /* store property handler */
+                         *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler;
+                         return STATUS_SUCCESS;
+                     }
                      if (Property->Flags & KSPROPERTY_TYPE_BASICSUPPORT)
                      {
                          PULONG Flags;
                          /* clear flags */
                          *Flags = 0;
  
+                         IoStatus->Information = sizeof(ULONG);
+                         if (PropertySet[Index].PropertyItem[ItemIndex].SupportHandler)
+                         {
+                             /* use support handler from driver */
+                             *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].SupportHandler;
+                             return STATUS_SUCCESS;
+                         }
                          if (PropertySet[Index].PropertyItem[ItemIndex].GetSupported)
                              *Flags |= KSPROPERTY_TYPE_GET;
  
                          if (PropertySet[Index].PropertyItem[ItemIndex].SetSupported)
                              *Flags |= KSPROPERTY_TYPE_SET;
  
-                         IoStatus->Information = sizeof(ULONG);
                          if (OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
                          {
                              /* get output buffer */
                          }
                          return STATUS_SUCCESS;
                      }
-                     if (Property->Flags & KSPROPERTY_TYPE_SET)
-                         *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].SetPropertyHandler;
-                     if (Property->Flags & KSPROPERTY_TYPE_GET)
-                         *PropertyHandler = PropertySet[Index].PropertyItem[ItemIndex].GetPropertyHandler;
-                     *Set = (PKSPROPERTY_SET)&PropertySet[Index];
-                     return STATUS_SUCCESS;
                  }
              }
          }
@@@ -171,7 -189,7 +189,7 @@@ KspPropertyHandler
              }
          }
      }
-     else if (IsEqualGUIDAligned(&Property->Set, &GUID_NULL) && Property->Id == 0 && Property->Flags == KSPROPERTY_TYPE_SETSUPPORT)
+     else if (IsEqualGUIDAligned(&Property->Set, &GUID_NULL) && Property->Id == 0 && (Property->Flags & KSPROPERTY_TYPE_SETSUPPORT) == KSPROPERTY_TYPE_SETSUPPORT)
      {
          // store output size
          Irp->IoStatus.Information = sizeof(GUID) * PropertySetsCount;
         {
             RtlMoveMemory(&Guid[Index], PropertySet[Index].Set, sizeof(GUID));
         }
-        return STATUS_SUCCESS;
+        Status = STATUS_SUCCESS;
      }
  
      /* done */
@@@ -327,7 -327,7 +327,7 @@@ CPortFilterWaveCyclic::Init
  NTSTATUS
  NTAPI
  CPortFilterWaveCyclic::FreePin(
-     IN struct IPortPinWaveCyclic* Pin)
+     IN PPORTPINWAVECYCLIC Pin)
  {
      ULONG Index;
  
@@@ -96,13 -96,14 +96,14 @@@ CPortFilterWavePci::NewIrpTarget
          return STATUS_UNSUCCESSFUL;
      }
  
-     if (m_Pins[ConnectDetails->PinId] && m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount)
+     if (m_Pins[ConnectDetails->PinId] && 
+         (m_Descriptor->Factory.Instances[ConnectDetails->PinId].CurrentPinInstanceCount == m_Descriptor->Factory.Instances[ConnectDetails->PinId].MaxFilterInstanceCount))
      {
-         // release existing instance
-         PC_ASSERT(0);
-         m_Pins[ConnectDetails->PinId]->Close(DeviceObject, NULL);
+         // no available instance
+         return STATUS_UNSUCCESSFUL;
      }
  
      // now create the pin
      Status = NewPortPinWavePci(&Pin);
      if (!NT_SUCCESS(Status))
@@@ -305,6 -306,26 +306,26 @@@ CPortFilterWavePci::Init
      return STATUS_SUCCESS;
  }
  
+ NTSTATUS
+ NTAPI
+ CPortFilterWavePci::FreePin(
+     IN struct IPortPinWavePci* Pin)
+ {
+     ULONG Index;
+     for(Index = 0; Index < m_Descriptor->Factory.PinDescriptorCount; Index++)
+     {
+         if (m_Pins[Index] == Pin)
+         {
+             m_Descriptor->Factory.Instances[Index].CurrentPinInstanceCount--;
+             m_Pins[Index] = NULL;
+             return STATUS_SUCCESS;
+         }
+     }
+     return STATUS_UNSUCCESSFUL;
+ }
  NTSTATUS 
  NewPortFilterWavePci(
      OUT IPortFilterWavePci ** OutFilter)
@@@ -79,6 -79,7 +79,7 @@@ const GUID KSPROPSETID_Topolog
  const GUID KSPROPSETID_Pin                     = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
  const GUID KSPROPSETID_Connection              = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
  const GUID KSPROPTYPESETID_General             = {0x97E99BA0L, 0xBDEA, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
+ const GUID KSPROPSETID_DrmAudioStream          = {0x2f2c8ddd,  0x4198, 0x4fac, {0xba, 0x29, 0x61, 0xbb, 0x05, 0xb7, 0xde, 0x06}};
  
  const GUID KSEVENTSETID_LoopedStreaming        = {0x4682B940L, 0xC6EF, 0x11D0, {0x96, 0xD8, 0x00, 0xAA, 0x00, 0x51, 0xE5, 0x1D}};
  const GUID KSEVENTSETID_Connection             = {0x7f4bcbe0L, 0x9ea5, 0x11cf, {0xa5, 0xd6, 0x28, 0xdb, 0x04, 0xc1, 0x00, 0x00}};
@@@ -321,8 -321,7 +321,7 @@@ DECLARE_INTERFACE_(IIrpQueue, IUnknown
      STDMETHOD_(NTSTATUS, Init)(THIS_
          IN KSPIN_CONNECT *ConnectDetails,
          IN ULONG FrameSize,
-         IN ULONG Alignment,
-         IN PVOID SilenceBuffer) PURE;
+         IN ULONG Alignment) PURE;
  
      STDMETHOD_(NTSTATUS, AddMapping)(THIS_
          IN PIRP Irp,
      STDMETHODIMP_(NTSTATUS) Init(THIS_                 \
          IN KSPIN_CONNECT *ConnectDetails,              \
          IN ULONG FrameSize,                            \
-         IN ULONG Alignment,                            \
-         IN PVOID SilenceBuffer);                       \
+         IN ULONG Alignment);                           \
                                                         \
      STDMETHODIMP_(NTSTATUS) AddMapping(THIS_           \
          IN PIRP Irp,                                   \
@@@ -599,6 -597,8 +597,8 @@@ DECLARE_INTERFACE_(IIrpStreamVirtual, I
  #undef INTERFACE
  #define INTERFACE IPortFilterWavePci
  
+ struct IPortPinWavePci;
  DECLARE_INTERFACE_(IPortFilterWavePci, IIrpTarget)
  {
      DEFINE_ABSTRACT_UNKNOWN()
  
      STDMETHOD_(NTSTATUS, Init)(THIS_
          IN PPORTWAVEPCI Port)PURE;
+     STDMETHOD_(NTSTATUS, FreePin)(THIS_
+         IN struct IPortPinWavePci* Pin)PURE;
  };
  
  typedef IPortFilterWavePci *PPORTFILTERWAVEPCI;
  #define IMP_IPortFilterPci           \
      IMP_IIrpTarget;                         \
      STDMETHODIMP_(NTSTATUS) Init(THIS_      \
-         IN PPORTWAVEPCI Port)
+         IN PPORTWAVEPCI Port);              \
+     STDMETHODIMP_(NTSTATUS) FreePin(THIS_   \
+         IN struct IPortPinWavePci* Pin)
  
  /*****************************************************************************
   * IPortPinWavePci
@@@ -43,7 -43,6 +43,6 @@@ protected
      LIST_ENTRY m_IrpList;
      LIST_ENTRY m_FreeIrpList;
      PIRP m_Irp;
-     PVOID m_SilenceBuffer;
  
      ULONG m_OutOfMapping;
      ULONG m_MaxFrameSize;
@@@ -84,12 -83,10 +83,10 @@@ NTAP
  CIrpQueue::Init(
      IN KSPIN_CONNECT *ConnectDetails,
      IN ULONG FrameSize,
-     IN ULONG Alignment,
-     IN PVOID SilenceBuffer)
+     IN ULONG Alignment)
  {
      m_ConnectDetails = ConnectDetails;
      m_MaxFrameSize = FrameSize;
-     m_SilenceBuffer = SilenceBuffer;
      m_Alignment = Alignment;
  
      InitializeListHead(&m_IrpList);
@@@ -259,22 -256,13 +256,13 @@@ CIrpQueue::GetMapping
          m_CurrentOffset = Offset = 0;
      }
  
-     if (!Irp && m_SilenceBuffer && m_MaxFrameSize)
-     {
-         DPRINT("NoIrp\n");
-         // no irp available, use silence buffer
-         *Buffer = (PUCHAR)m_SilenceBuffer;
-         *BufferSize = m_MaxFrameSize;
-         return STATUS_SUCCESS;
-     }
      if (!Irp)
      {
          // no irp buffer available
+         DPRINT("NoIrp\n");
          return STATUS_UNSUCCESSFUL;
      }
  
      // get stream header
      StreamHeader = (PKSSTREAM_HEADER)Irp->Tail.Overlay.DriverContext[2];
  
@@@ -604,7 -604,7 +604,7 @@@ CPortPinDMus::Init
          }
      }
  
-     Status = m_IrpQueue->Init(ConnectDetails, 0, 0, NULL);
+     Status = m_IrpQueue->Init(ConnectDetails, 0, 0);
      if (!NT_SUCCESS(Status))
      {
          DPRINT("IrpQueue_Init failed with %x\n", Status);
@@@ -73,7 -73,7 +73,7 @@@ protected
      ULONG m_StopCount;
      KSAUDIO_POSITION m_Position;
      KSALLOCATOR_FRAMING m_AllocatorFraming;
-     SUBDEVICE_DESCRIPTOR m_Descriptor;
+     PSUBDEVICE_DESCRIPTOR m_Descriptor;
  
      KSPIN_LOCK m_EventListLock;
      LIST_ENTRY m_EventList;
@@@ -105,10 -105,12 +105,12 @@@ NTSTATUS NTAPI PinWaveCyclicAudioPositi
  NTSTATUS NTAPI PinWaveCyclicAllocatorFraming(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
  NTSTATUS NTAPI PinWaveCyclicAddEndOfStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY  EventEntry);
  NTSTATUS NTAPI PinWaveCyclicAddLoopedStreamEvent(IN PIRP Irp, IN PKSEVENTDATA  EventData, IN PKSEVENT_ENTRY EventEntry);
+ NTSTATUS NTAPI PinWaveCyclicDRMHandler(IN PIRP Irp, IN PKSIDENTIFIER Request, IN OUT PVOID Data);
  
  
  DEFINE_KSPROPERTY_CONNECTIONSET(PinWaveCyclicConnectionSet, PinWaveCyclicState, PinWaveCyclicDataFormat, PinWaveCyclicAllocatorFraming);
  DEFINE_KSPROPERTY_AUDIOSET(PinWaveCyclicAudioSet, PinWaveCyclicAudioPosition);
+ DEFINE_KSPROPERTY_DRMSET(PinWaveCyclicDRMSet, PinWaveCyclicDRMHandler);
  
  KSEVENT_ITEM PinWaveCyclicConnectionEventSet =
  {
@@@ -146,6 -148,13 +148,13 @@@ KSPROPERTY_SET PinWaveCyclicPropertySet
          (const KSPROPERTY_ITEM*)&PinWaveCyclicAudioSet,
          0,
          NULL
+     },
+     {
+         &KSPROPSETID_DrmAudioStream,
+         sizeof(PinWaveCyclicDRMSet) / sizeof(KSPROPERTY_ITEM),
+         (const KSPROPERTY_ITEM*)&PinWaveCyclicDRMSet,
+         0,
+         NULL
      }
  };
  
@@@ -192,6 -201,19 +201,19 @@@ CPortPinWaveCyclic::QueryInterface
      return STATUS_UNSUCCESSFUL;
  }
  
+ NTSTATUS
+ NTAPI
+ PinWaveCyclicDRMHandler(
+     IN PIRP Irp,
+     IN PKSIDENTIFIER Request,
+     IN OUT PVOID Data)
+ {
+     DPRINT1("PinWaveCyclicDRMHandler\n");
+     ASSERT(0);
+     return STATUS_INVALID_PARAMETER;
+ }
  NTSTATUS
  NTAPI
  PinWaveCyclicAddEndOfStreamEvent(
@@@ -448,12 -470,14 +470,14 @@@ PinWaveCyclicState
              {
                  // FIXME
                  // complete with successful state
+                 Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize);
                  Pin->m_IrpQueue->CancelBuffers();
                  Pin->m_Position.PlayOffset = 0;
                  Pin->m_Position.WriteOffset = 0;
              }
              else if (Pin->m_State == KSSTATE_STOP)
              {
+                 Pin->m_Stream->Silence(Pin->m_CommonBuffer, Pin->m_CommonBufferSize);
                  Pin->m_IrpQueue->CancelBuffers();
                  Pin->m_Position.PlayOffset = 0;
                  Pin->m_Position.WriteOffset = 0;
@@@ -662,6 -686,7 +686,7 @@@ CPortPinWaveCyclic::UpdateCommonBuffer
      ULONG BufferLength;
      ULONG BytesToCopy;
      ULONG BufferSize;
+     ULONG Gap;
      PUCHAR Buffer;
      NTSTATUS Status;
  
      {
          Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
          if (!NT_SUCCESS(Status))
-             return;
+         {
+             Gap = Position - m_CommonBufferOffset;
+             if (Gap > m_FrameSize)
+             {
+                 // insert silence samples
+                 DPRINT1("Inserting Silence Buffer Offset %lu GapLength %lu\n", m_CommonBufferOffset, BufferLength);
+                 m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
+                 m_CommonBufferOffset += BufferLength;
+                 break;
+             }
+         }
  
          BytesToCopy = min(BufferLength, BufferSize);
  
          m_IrpQueue->UpdateMapping(BytesToCopy);
          m_CommonBufferOffset += BytesToCopy;
  
-         BufferLength = Position - m_CommonBufferOffset;
+         BufferLength -= BytesToCopy;
          m_Position.PlayOffset += BytesToCopy;
  
          if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
@@@ -720,7 -756,18 +756,18 @@@ CPortPinWaveCyclic::UpdateCommonBufferO
      {
          Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
          if (!NT_SUCCESS(Status))
-             return;
+         {
+             Gap = m_CommonBufferSize - m_CommonBufferOffset + Position;
+             if (Gap > m_FrameSize)
+             {
+                 // insert silence samples
+                 DPRINT1("Overlap Inserting Silence Buffer Size %lu Offset %lu Gap %lu Position %lu\n", m_CommonBufferSize, m_CommonBufferOffset, Gap, Position);
+                 m_Stream->Silence((PUCHAR)m_CommonBuffer + m_CommonBufferOffset, BufferLength);
+                 m_CommonBufferOffset += BufferLength;
+             }
+             break;
+         }
  
          BytesToCopy = min(BufferLength, BufferSize);
  
          m_CommonBufferOffset += BytesToCopy;
          m_Position.PlayOffset += BytesToCopy;
  
-         BufferLength = m_CommonBufferSize - m_CommonBufferOffset;
+         BufferLength -=BytesToCopy;
  
          if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
          {
                  m_Position.PlayOffset = m_Position.PlayOffset % m_Position.WriteOffset;
              }
          }
      }
  
      if (Gap == Length)
@@@ -773,22 -819,13 +819,13 @@@ CPortPinWaveCyclic::RequestService(
  {
      ULONG Position;
      NTSTATUS Status;
-     PUCHAR Buffer;
-     ULONG BufferSize;
      ULONGLONG OldOffset, NewOffset;
  
      PC_ASSERT_IRQL(DISPATCH_LEVEL);
  
      if (m_State == KSSTATE_RUN)
      {
-         Status = m_IrpQueue->GetMapping(&Buffer, &BufferSize);
-         if (!NT_SUCCESS(Status))
-         {
-             return;
-         }
          Status = m_Stream->GetPosition(&Position);
-         DPRINT("Position %u Buffer %p BufferSize %u ActiveIrpOffset %u Capture %u\n", Position, Buffer, m_CommonBufferSize, BufferSize, m_Capture);
  
          OldOffset = m_Position.PlayOffset;
  
@@@ -841,7 -878,7 +878,7 @@@ CPortPinWaveCyclic::DeviceIoControl
      if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY)
      {
          /* handle property with subdevice descriptor */
-         Status = PcHandlePropertyWithTable(Irp,  m_Descriptor.FilterPropertySetCount, m_Descriptor.FilterPropertySet, &m_Descriptor);
+         Status = PcHandlePropertyWithTable(Irp,  m_Descriptor->FilterPropertySetCount, m_Descriptor->FilterPropertySet, m_Descriptor);
  
          if (Status == STATUS_NOT_FOUND)
          {
      }
      else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_ENABLE_EVENT)
      {
-         Status = PcHandleEnableEventWithTable(Irp, &m_Descriptor);
+         Status = PcHandleEnableEventWithTable(Irp, m_Descriptor);
      }
      else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_DISABLE_EVENT)
      {
-         Status = PcHandleDisableEventWithTable(Irp, &m_Descriptor);
+         Status = PcHandleDisableEventWithTable(Irp, m_Descriptor);
      }
      else if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_RESET_STATE)
      {
@@@ -960,27 -997,29 +997,29 @@@ CPortPinWaveCyclic::Close
      {
          // free format
          FreeItem(m_Format, TAG_PORTCLASS);
+         // format is freed
          m_Format = NULL;
      }
  
      if (m_IrpQueue)
      {
-         // fixme cancel irps
-         m_IrpQueue->Release();
-     }
+         // cancel remaining irps
+         m_IrpQueue->CancelBuffers();
  
+         // release irp queue
+         m_IrpQueue->Release();
  
-     if (m_Port)
-     {
-         // release reference to port driver
-         m_Port->Release();
-         m_Port = NULL;
+         // queue is freed
+         m_IrpQueue = NULL;
      }
  
      if (m_ServiceGroup)
      {
          // remove member from service group
          m_ServiceGroup->RemoveMember(PSERVICESINK(this));
+         // do not release service group, it is released by the miniport object
          m_ServiceGroup = NULL;
      }
  
          // set state to stop
          m_State = KSSTATE_STOP;
  
          DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
          // release stream
          m_Stream->Release();
  
+         // stream is now freed
+         m_Stream = NULL;
      }
  
  
      if (m_Filter)
      {
-         // release reference to filter instance
+         // disconnect pin from filter
          m_Filter->FreePin((PPORTPINWAVECYCLIC)this);
+         // release filter reference
          m_Filter->Release();
+         // pin is done with filter
          m_Filter = NULL;
      }
  
+     if (m_Port)
+     {
+         // release reference to port driver
+         m_Port->Release();
+         // work is done for port
+         m_Port = NULL;
+     }
      Irp->IoStatus.Information = 0;
      Irp->IoStatus.Status = STATUS_SUCCESS;
      IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@@ -1103,7 -1157,6 +1157,6 @@@ CPortPinWaveCyclic::Init
      PKSDATAFORMAT DataFormat;
      PDEVICE_OBJECT DeviceObject;
      BOOLEAN Capture;
-     PVOID SilenceBuffer;
      PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
      //IDrmAudioStream * DrmAudio = NULL;
  
  #endif
  
      DPRINT1("CPortPinWaveCyclic::Init Status %x PinId %u Capture %u\n", Status, ConnectDetails->PinId, Capture);
-     DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize);
  
      if (!NT_SUCCESS(Status))
          return Status;
      InitializeListHead(&m_EventList);
      KeInitializeSpinLock(&m_EventListLock);
  
-     /* set up subdevice descriptor */
-     RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
-     m_Descriptor.FilterPropertySet = PinWaveCyclicPropertySet;
-     m_Descriptor.FilterPropertySetCount = sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET);
-     m_Descriptor.UnknownStream = (PUNKNOWN)m_Stream;
-     m_Descriptor.DeviceDescriptor = SubDeviceDescriptor->DeviceDescriptor;
-     m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
-     m_Descriptor.PortPin = (PVOID)this;
-     m_Descriptor.EventSetCount = sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET);
-     m_Descriptor.EventSet = PinWaveCyclicEventSet;
-     m_Descriptor.EventList = &m_EventList;
-     m_Descriptor.EventListLock = &m_EventListLock;
+     Status = PcCreateSubdeviceDescriptor(&m_Descriptor,
+                                          SubDeviceDescriptor->InterfaceCount,
+                                          SubDeviceDescriptor->Interfaces,
+                                          0, /* FIXME KSINTERFACE_STANDARD with KSINTERFACE_STANDARD_STREAMING / KSINTERFACE_STANDARD_LOOPED_STREAMING */
+                                          NULL,
+                                          sizeof(PinWaveCyclicPropertySet) / sizeof(KSPROPERTY_SET),
+                                          PinWaveCyclicPropertySet,
+                                          0,
+                                          0,
+                                          0,
+                                          NULL,
+                                          sizeof(PinWaveCyclicEventSet) / sizeof(KSEVENT_SET),
+                                          PinWaveCyclicEventSet,
+                                          SubDeviceDescriptor->DeviceDescriptor);
+     m_Descriptor->UnknownStream = (PUNKNOWN)m_Stream;
+     m_Descriptor->UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
+     m_Descriptor->PortPin = (PVOID)this;
+     m_Descriptor->EventList = &m_EventList;
+     m_Descriptor->EventListLock = &m_EventListLock;
  
      // initialize reset state
      m_ResetState = KSRESET_END;
      PC_ASSERT(NT_SUCCESS(Status));
      PC_ASSERT(m_FrameSize);
  
-     SilenceBuffer = AllocateItem(NonPagedPool, m_FrameSize, TAG_PORTCLASS);
-     if (!SilenceBuffer)
-         return STATUS_INSUFFICIENT_RESOURCES;
+     DPRINT1("Bits %u Samples %u Channels %u Tag %u FrameSize %u CommonBufferSize %lu\n", ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wBitsPerSample, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nSamplesPerSec, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.nChannels, ((PKSDATAFORMAT_WAVEFORMATEX)(DataFormat))->WaveFormatEx.wFormatTag, m_FrameSize, m_CommonBufferSize);
  
  
      /* set up allocator framing */
      m_AllocatorFraming.Reserved = 0;
      m_AllocatorFraming.FrameSize = m_FrameSize;
  
-     m_Stream->Silence(SilenceBuffer, m_FrameSize);
      m_Stream->Silence(m_CommonBuffer, m_CommonBufferSize);
  
-     Status = m_IrpQueue->Init(ConnectDetails, m_FrameSize, 0, SilenceBuffer);
+     Status = m_IrpQueue->Init(ConnectDetails, m_FrameSize, 0);
      if (!NT_SUCCESS(Status))
      {
         m_IrpQueue->Release();
      m_Port = Port;
      m_Filter = Filter;
  
-     //DPRINT("Setting state to acquire %x\n", m_Stream->SetState(KSSTATE_ACQUIRE));
-     //DPRINT("Setting state to pause %x\n", m_Stream->SetState(KSSTATE_PAUSE));
      return STATUS_SUCCESS;
  }
  
@@@ -62,8 -62,6 +62,6 @@@ protected
      KSAUDIO_POSITION m_Position;
      ULONG m_StopCount;
  
-     ULONG m_Delay;
      BOOL m_bUsePrefetch;
      ULONG m_PrefetchOffset;
      SUBDEVICE_DESCRIPTOR m_Descriptor;
@@@ -637,41 -635,85 +635,85 @@@ CPortPinWavePci::Close
      IN PDEVICE_OBJECT DeviceObject,
      IN PIRP Irp)
  {
-     ISubdevice *SubDevice;
      NTSTATUS Status;
-     PSUBDEVICE_DESCRIPTOR Descriptor;
+     if (m_Format)
+     {
+         // free format
+         FreeItem(m_Format, TAG_PORTCLASS);
+         // format is freed
+         m_Format = NULL;
+     }
+     if (m_IrpQueue)
+     {
+         // cancel remaining irps
+         m_IrpQueue->CancelBuffers();
+         // release irp queue
+         m_IrpQueue->Release();
+         // queue is freed
+         m_IrpQueue = NULL;
+     }
  
      if (m_ServiceGroup)
      {
+         // remove member from service group
          m_ServiceGroup->RemoveMember(PSERVICESINK(this));
+         // do not release service group, it is released by the miniport object
+         m_ServiceGroup = NULL;
      }
  
      if (m_Stream)
      {
          if (m_State != KSSTATE_STOP)
          {
-             m_Stream->SetState(KSSTATE_STOP);
+             // stop stream
+             Status = m_Stream->SetState(KSSTATE_STOP);
+             if (!NT_SUCCESS(Status))
+             {
+                 DPRINT("Warning: failed to stop stream with %x\n", Status);
+                 PC_ASSERT(0);
+             }
          }
+         // set state to stop
+         m_State = KSSTATE_STOP;
+         DPRINT("Closing stream at Irql %u\n", KeGetCurrentIrql());
+         // release stream
          m_Stream->Release();
+         // stream is now freed
+         m_Stream = NULL;
      }
  
-     Status = m_Port->QueryInterface(IID_ISubdevice, (PVOID*)&SubDevice);
-     if (NT_SUCCESS(Status))
+     if (m_Filter)
      {
-         Status = SubDevice->GetDescriptor(&Descriptor);
-         if (NT_SUCCESS(Status))
-         {
-             Descriptor->Factory.Instances[m_ConnectDetails->PinId].CurrentPinInstanceCount--;
-         }
-         SubDevice->Release();
+         // disconnect pin from filter
+         m_Filter->FreePin((PPORTPINWAVEPCI)this);
+         // release filter reference
+         m_Filter->Release();
+         // pin is done with filter
+         m_Filter = NULL;
      }
  
-     if (m_Format)
+     if (m_Port)
      {
-         FreeItem(m_Format, TAG_PORTCLASS);
-         m_Format = NULL;
+         // release reference to port driver
+         m_Port->Release();
+         // work is done for port
+         m_Port = NULL;
      }
  
+     // successfully complete irp
      Irp->IoStatus.Status = STATUS_SUCCESS;
      Irp->IoStatus.Information = 0;
      IoCompleteRequest(Irp, IO_NO_INCREMENT);
@@@ -756,42 -798,66 +798,66 @@@ CPortPinWavePci::Init
      NTSTATUS Status;
      PKSDATAFORMAT DataFormat;
      BOOLEAN Capture;
+     ISubdevice * Subdevice = NULL;
+     PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
  
+     // check if it is a source / sink pin
+     if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
+     {
+         // sink pin
+         Capture = FALSE;
+     }
+     else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
+     {
+         // source pin
+         Capture = TRUE;
+     }
+     else
+     {
+         DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
+         DbgBreakPoint();
+         while(TRUE);
+     }
+     // add port / filter reference
      Port->AddRef();
      Filter->AddRef();
  
+     // initialize pin
      m_Port = Port;
      m_Filter = Filter;
      m_KsPinDescriptor = KsPinDescriptor;
      m_ConnectDetails = ConnectDetails;
      m_Miniport = GetWavePciMiniport(Port);
      m_DeviceObject = DeviceObject;
-     DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
+     m_State = KSSTATE_STOP;
+     m_Capture = Capture;
  
      DPRINT("IPortPinWavePci_fnInit entered\n");
  
+     // get dataformat
+     DataFormat = (PKSDATAFORMAT)(ConnectDetails + 1);
+     // allocate data format
      m_Format = (PKSDATAFORMAT)AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS);
      if (!m_Format)
-         return STATUS_INSUFFICIENT_RESOURCES;
+     {
+         // release references
+         m_Port->Release();
+         m_Filter->Release();
  
-     RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
+         // no dangling pointers
+         Port = NULL;
+         Filter = NULL;
  
-     if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_IN)
-     {
-         Capture = FALSE;
-     }
-     else if (KsPinDescriptor->Communication == KSPIN_COMMUNICATION_SINK && KsPinDescriptor->DataFlow == KSPIN_DATAFLOW_OUT)
-     {
-         Capture = TRUE;
-     }
-     else
-     {
-         DPRINT("Unexpected Communication %u DataFlow %u\n", KsPinDescriptor->Communication, KsPinDescriptor->DataFlow);
-         DbgBreakPoint();
-         while(TRUE);
+         // failed to allocate data format
+         return STATUS_INSUFFICIENT_RESOURCES;
      }
  
+     // copy data format
+     RtlMoveMemory(m_Format, DataFormat, DataFormat->FormatSize);
+     // allocate new stream
      Status = m_Miniport->NewStream(&m_Stream,
                                     NULL,
                                     NonPagedPool,
      DPRINT("IPortPinWavePci_fnInit Status %x\n", Status);
  
      if (!NT_SUCCESS(Status))
+     {
+         // free references
+         Port->Release();
+         Filter->Release();
+         // free data format
+         FreeItem(m_Format, TAG_PORTCLASS);
+         // no dangling pointers
+         m_Port = NULL;
+         m_Filter = NULL;
+         m_Format = NULL;
+         // failed to allocate stream
          return Status;
+     }
  
-     if (m_ServiceGroup)
+     // get allocator requirements for pin
+     Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming);
+     if (NT_SUCCESS(Status))
      {
-         Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
-         if (!NT_SUCCESS(Status))
-         {
-             DPRINT("Failed to add pin to service group\n");
-             return Status;
-         }
+         DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n",
+                m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
      }
  
-     // delay of 10 milisec
-     m_Delay = Int32x32To64(10, -10000);
-     Status = m_Stream->GetAllocatorFraming(&m_AllocatorFraming);
+     // allocate new irp queue
+     Status = NewIrpQueue(&m_IrpQueue);
      if (!NT_SUCCESS(Status))
      {
-         DPRINT("GetAllocatorFraming failed with %x\n", Status);
+         // free references
+         Port->Release();
+         Filter->Release();
+         m_Stream->Release();
+         // free data format
+         FreeItem(m_Format, TAG_PORTCLASS);
+         // no dangling pointers
+         m_Port = NULL;
+         m_Filter = NULL;
+         m_Format = NULL;
+         m_Stream = NULL;
+         // failed to allocate irp queue
+         return Status;
      }
  
-     DPRINT("OptionFlags %x RequirementsFlag %x PoolType %x Frames %lu FrameSize %lu FileAlignment %lu\n",
-            m_AllocatorFraming.OptionsFlags, m_AllocatorFraming.RequirementsFlags, m_AllocatorFraming.PoolType, m_AllocatorFraming.Frames, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
+     // initialize irp queue
+     Status = m_IrpQueue->Init(ConnectDetails, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment);
+     if (!NT_SUCCESS(Status))
+     {
+         // this should never happen
+         ASSERT(0);
+     }
  
-     ISubdevice * Subdevice = NULL;
      // get subdevice interface
      Status = Port->QueryInterface(IID_ISubdevice, (PVOID*)&Subdevice);
  
      if (!NT_SUCCESS(Status))
-         return Status;
-     PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor = NULL;
+     {
+         // this function should never fail
+         ASSERT(0);
+     }
  
+     // get subdevice descriptor
      Status = Subdevice->GetDescriptor(&SubDeviceDescriptor);
      if (!NT_SUCCESS(Status))
      {
-         // failed to get descriptor
-         Subdevice->Release();
-         return Status;
+         // this function should never fail
+         ASSERT(0);
      }
  
+     // release subdevice
+     Subdevice->Release();
      /* set up subdevice descriptor */
      RtlZeroMemory(&m_Descriptor, sizeof(SUBDEVICE_DESCRIPTOR));
      m_Descriptor.FilterPropertySet = PinWavePciPropertySet;
      m_Descriptor.UnknownMiniport = SubDeviceDescriptor->UnknownMiniport;
      m_Descriptor.PortPin = (PVOID)this;
  
+     if (m_ServiceGroup)
+     {
+         Status = m_ServiceGroup->AddMember(PSERVICESINK(this));
+         if (!NT_SUCCESS(Status))
+         {
+             // free references
+             m_Stream->Release();
+             Port->Release();
+             Filter->Release();
  
+             // free data format
+             FreeItem(m_Format, TAG_PORTCLASS);
  
-     Status = NewIrpQueue(&m_IrpQueue);
-     if (!NT_SUCCESS(Status))
-         return Status;
+             // no dangling pointers
+             m_Stream = NULL;
+             m_Port = NULL;
+             m_Filter = NULL;
+             m_Format = NULL;
  
-     Status = m_IrpQueue->Init(ConnectDetails, m_AllocatorFraming.FrameSize, m_AllocatorFraming.FileAlignment, NULL);
-     if (!NT_SUCCESS(Status))
-     {
-         DPRINT("IrpQueue_Init failed with %x\n", Status);
-         return Status;
+             // failed to add to service group
+             return Status;
+         }
      }
  
-     m_State = KSSTATE_STOP;
-     m_Capture = Capture;
  
      return STATUS_SUCCESS;
  }
@@@ -587,7 -587,7 +587,7 @@@ CPortPinWaveRT::Init
          goto cleanup;
      }
  
-     Status = m_IrpQueue->Init(ConnectDetails, 0, 0, NULL);
+     Status = m_IrpQueue->Init(ConnectDetails, 0, 0);
      if (!NT_SUCCESS(Status))
      {
          goto cleanup;
@@@ -275,12 -275,12 +275,12 @@@ CPortWaveCyclic::Init
      }
  
      // create the subdevice descriptor
-     Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor, 
+     Status = PcCreateSubdeviceDescriptor(&m_SubDeviceDescriptor,
                                           4,
                                           InterfaceGuids,
-                                          0, 
+                                          0,
                                           NULL,
-                                          2, 
+                                          2,
                                           WaveCyclicPropertySet,
                                           0,
                                           0,
@@@ -356,6 -356,22 +356,22 @@@ DEFINE_KSPROPERTY_TABLE(PinSet) {
      DEFINE_KSPROPERTY_ITEM_AUDIO_POSITION(PropPositionHandler, PropPositionHandler)\
  }
  
+ #define DEFINE_KSPROPERTY_ITEM_DRMAUDIOSTREAM_CONTENTID(SetHandler)\
+     DEFINE_KSPROPERTY_ITEM(\
+         KSPROPERTY_DRMAUDIOSTREAM_CONTENTID,\
+         NULL,\
+         sizeof(KSPROPERTY),\
+         sizeof(ULONG),\
+         (SetHandler),\
+         NULL, 0, NULL, NULL, 0)
+ #define DEFINE_KSPROPERTY_DRMSET(PinSet,\
+     PropPositionHandler)\
+ DEFINE_KSPROPERTY_TABLE(PinSet) {\
+     DEFINE_KSPROPERTY_ITEM_DRMAUDIOSTREAM_CONTENTID(PropPositionHandler)\
+ }
  #define DEFINE_KSPROPERTY_PINPROPOSEDATAFORMAT(PinSet,\
      PropGeneral, PropInstances, PropIntersection)\
  DEFINE_KSPROPERTY_TABLE(PinSet) {\
@@@ -8,22 -8,6 +8,6 @@@
  
  #include "private.hpp"
  
- KSPIN_INTERFACE PinInterfaces[] = 
- {
-     {
-         {STATIC_KSINTERFACESETID_Standard},
-         KSINTERFACE_STANDARD_STREAMING,
-         0
-     },
-     {
-         {STATIC_KSINTERFACESETID_Standard},
-         KSINTERFACE_STANDARD_LOOPED_STREAMING,
-         0
-     }
- };
  NTSTATUS
  NTAPI
  KsoDispatchCreateWithGenericFactory(
@@@ -87,334 -71,432 +71,432 @@@ PcHandleDisableEventWithTable
  }
  
  NTSTATUS
- PcHandleGuidNullRequest(
-     IN OUT PIRP Irp,
+ NTAPI
+ PcHandlePropertyWithTable(
+     IN PIRP Irp,
+     IN ULONG PropertySetCount,
+     IN PKSPROPERTY_SET PropertySet,
      IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
  {
-     PPCNODE_DESCRIPTOR Node;
-     PPCPROPERTY_ITEM PropertyItem;
      PIO_STACK_LOCATION IoStack;
-     PKSP_NODE Property;
-     LPGUID Buffer;
-     ULONG Count = 0, SubIndex, Index;
  
      // get current irp stack location
      IoStack = IoGetCurrentIrpStackLocation(Irp);
  
-     // access property
-     Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
-     if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
+     if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY))
      {
-         // request is out of bounds
-         Irp->IoStatus.Information = 0;
+         // certainly an invalid request
          return STATUS_INVALID_PARAMETER;
      }
  
-     Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
+     // store device descriptor
+     KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
  
-     if (!Node->AutomationTable)
-     {
-         // request is out of bounds
-         Irp->IoStatus.Information = 0;
-         return STATUS_INVALID_PARAMETER;
-     }
+     // then try KsPropertyHandler 
+     return KsPropertyHandler(Irp, PropertySetCount, PropertySet);
+ }
  
-     PC_ASSERT(Node->AutomationTable);
-     PC_ASSERT(Node->AutomationTable->PropertyCount);
-     PC_ASSERT(Node->AutomationTable->PropertyItemSize);
-     Buffer = (LPGUID)AllocateItem(NonPagedPool,  sizeof (GUID) * Node->AutomationTable->PropertyCount, TAG_PORTCLASS);
-     if  (!Buffer)
-         return  STATUS_INSUFFICIENT_RESOURCES;
-      PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
-      for (Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
-      {
-          BOOL Found = FALSE;
-          for (SubIndex = 0; SubIndex < Count; SubIndex++)
-          {
-              if  (IsEqualGUIDAligned(Buffer[SubIndex], *PropertyItem->Set))
-              {
-                  Found = TRUE;
-                  break;
-              }
-          }
-          if (!Found)
-          {
-              RtlMoveMemory(&Buffer[Count], PropertyItem->Set, sizeof (GUID));
-              Count++;
-          }
-          PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
-      }
-      // store result length
-      Irp->IoStatus.Information =  sizeof (GUID) * Count;
-      if  (IoStack->Parameters.DeviceIoControl.OutputBufferLength <  sizeof (GUID) * Count)
-      {
-          // buffer too small
-          FreeItem(Buffer, TAG_PORTCLASS);
-          return  STATUS_MORE_ENTRIES;
-      }
-      RtlMoveMemory(Irp->UserBuffer, Buffer,  sizeof (GUID) * Count);
-      FreeItem(Buffer, TAG_PORTCLASS);
-      return STATUS_SUCCESS;
+ VOID
+ NTAPI
+ PcAcquireFormatResources(
+     LONG Unknown,
+     LONG Unknown2,
+     LONG Unknown3,
+     LONG Unknown4)
+ {
+     UNIMPLEMENTED;
  }
  
  NTSTATUS
- PcFindNodePropertyHandler(
-     PIRP Irp,
-     PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
-     OUT PPCPROPERTY_ITEM * OutPropertyItem)
+ PcAddToEventTable(
+     PVOID Ptr,
+     LONG Unknown2,
+     ULONG Length,
+     LONG Unknown3,
+     LONG Unknown4,
+     LONG Unknown5,
+     LONG Unknown6,
+     LONG Unknown7)
  {
-     PPCNODE_DESCRIPTOR Node;
+     UNIMPLEMENTED;
+     return STATUS_NOT_IMPLEMENTED;
+ }
+ NTSTATUS
+ NTAPI
+ PropertyItemDispatch(
+     IN PIRP Irp,
+     IN PKSIDENTIFIER  Request,
+     IN OUT PVOID  Data)
+ {
+     PPCPROPERTY_REQUEST PropertyRequest;
+     PSUBDEVICE_DESCRIPTOR Descriptor;
+     PKSPROPERTY Property;
+     PPCNODE_DESCRIPTOR NodeDescriptor;
+     PKSNODEPROPERTY NodeProperty;
+     PKSPROPERTY_SET PropertySet;
      PPCPROPERTY_ITEM PropertyItem;
+     PPCAUTOMATION_TABLE NodeAutomation;
      PIO_STACK_LOCATION IoStack;
-     PKSP_NODE Property;
-     ULONG Index;
+     ULONG InstanceSize, ValueSize, Index;
+     PVOID Instance;
+     NTSTATUS Status;
  
-     // get current irp stack location
+     // allocate a property request
+     PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
+     if (!PropertyRequest)
+         return STATUS_INSUFFICIENT_RESOURCES;
+     // grab device descriptor
+     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
+     // get current irp stack
      IoStack = IoGetCurrentIrpStackLocation(Irp);
  
-     // access property
-     Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+     // get input property request
+     Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
  
-     if (Property->NodeId >= SubDeviceDescriptor->DeviceDescriptor->NodeCount)
+     // get property set
+     PropertySet = (PKSPROPERTY_SET)KSPROPERTY_SET_IRP_STORAGE(Irp);
+     // sanity check
+     PC_ASSERT(Descriptor);
+     PC_ASSERT(Descriptor->UnknownMiniport);
+     // get instance / value size
+     InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength;
+     Instance = Data;
+     ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
+      // initialize property request
+      PropertyRequest->MajorTarget = Descriptor->UnknownMiniport;
+      PropertyRequest->MinorTarget = Descriptor->UnknownStream;
+      PropertyRequest->Irp = Irp;
+      PropertyRequest->Verb = Property->Flags;
+     // check if this is filter / pin property request
+     if (!(Property->Flags & KSPROPERTY_TYPE_TOPOLOGY))
      {
-         // request is out of bounds
-         DPRINT("InvalidIndex %u %u\n", Property->NodeId, SubDeviceDescriptor->DeviceDescriptor->NodeCount);
-         return STATUS_INVALID_PARAMETER;
+         // adjust input buffer size
+         InstanceSize -= sizeof(KSPROPERTY);
+         Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSPROPERTY));
+         // filter / pin property request dont use node field
+         PropertyRequest->Node = MAXULONG;
+     }
+     else if (InstanceSize >= sizeof(KSNODEPROPERTY))
+     {
+         // request is for a node
+         InstanceSize -= sizeof(KSNODEPROPERTY);
+         Instance = (PVOID)((ULONG_PTR)Instance + sizeof(KSNODEPROPERTY));
+         // cast node property request
+         NodeProperty = (PKSNODEPROPERTY)Request;
+         // store node id
+         PropertyRequest->Node = NodeProperty->NodeId;
+     }
+     else
+     {
+         // invalid buffer size
+         return STATUS_INVALID_BUFFER_SIZE;
      }
  
-     Node = (PPCNODE_DESCRIPTOR)((ULONG_PTR)SubDeviceDescriptor->DeviceDescriptor->Nodes + (Property->NodeId * SubDeviceDescriptor->DeviceDescriptor->NodeSize));
+     // store instance size
+     PropertyRequest->InstanceSize = InstanceSize;
+     PropertyRequest->Instance = (InstanceSize != 0 ? Instance : NULL);
  
-     if (!Node->AutomationTable)
+     // store value size
+     PropertyRequest->ValueSize = ValueSize;
+     PropertyRequest->Value = (ValueSize != 0 ? Irp->UserBuffer : NULL);
+     // now scan the property set for the attached property set item stored in Relations member
+     if (PropertySet)
      {
-         // request is out of bounds
-         Irp->IoStatus.Information = 0;
-         return STATUS_NOT_FOUND;
+         // sanity check
+         PC_ASSERT(IsEqualGUIDAligned(Property->Set, *PropertySet->Set));
+         for(Index = 0; Index < PropertySet->PropertiesCount; Index++)
+         {
+             // check if they got the same property id
+             if (PropertySet->PropertyItem[Index].PropertyId == Property->Id)
+             {
+                 // found item
+                 PropertyRequest->PropertyItem = (const PCPROPERTY_ITEM*)PropertySet->PropertyItem[Index].Relations;
+                 // done
+                 break;
+             }
+         }
      }
  
-     // sanity checks
-     PC_ASSERT(Node->AutomationTable);
-     PC_ASSERT(Node->AutomationTable->PropertyCount);
-     PC_ASSERT(Node->AutomationTable->PropertyItemSize);
+     // check if there has been a property set item attached
+     if (!PropertyRequest->PropertyItem)
+     {
+         // is topology node id valid
+         if (PropertyRequest->Node < Descriptor->DeviceDescriptor->NodeCount)
+         {
+             // get node descriptor
+             NodeDescriptor = (PPCNODE_DESCRIPTOR) ((ULONG_PTR)Descriptor->DeviceDescriptor->Nodes + PropertyRequest->Node * Descriptor->DeviceDescriptor->NodeSize);
  
-     PropertyItem = (PCPROPERTY_ITEM*)Node->AutomationTable->Properties;
+             // get node automation table
+             NodeAutomation = (PPCAUTOMATION_TABLE)NodeDescriptor->AutomationTable;
  
-     DPRINT("NodeId %u PropertyCount %u\n", Property->NodeId, Node->AutomationTable->PropertyCount);
-     for(Index = 0; Index < Node->AutomationTable->PropertyCount; Index++)
+             // has it got a automation table
+             if (NodeAutomation)
+             {
+                 // now scan the properties and check if it supports this request
+                 PropertyItem = (PPCPROPERTY_ITEM)NodeAutomation->Properties;
+                 for(Index = 0; Index < NodeAutomation->PropertyCount; Index++)
+                 {
+                     // are they same property
+                     if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Set))
+                     {
+                         if (PropertyItem->Id == Property->Id)
+                         {
+                             // found match
+                             PropertyRequest->PropertyItem = PropertyItem;
+                             // done
+                             break;
+                         }
+                     }
+                     // move to next property item
+                     PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeAutomation->PropertyItemSize);
+                 }
+             }
+         }
+     }
+     if (PropertyRequest->PropertyItem && PropertyRequest->PropertyItem->Handler)
      {
-         if (IsEqualGUIDAligned(*PropertyItem->Set, Property->Property.Set) && PropertyItem->Id == Property->Property.Id)
+         // now call the handler
+         UNICODE_STRING GuidBuffer;
+         RtlStringFromGUID(Property->Set, &GuidBuffer);
+         DPRINT1("Calling Node %lu MajorTarget %p MinorTarget %p PropertySet %S PropertyId %lu PropertyFlags %lx InstanceSize %lu ValueSize %lu Handler %p PropertyRequest %p\n",
+                 PropertyRequest->Node, PropertyRequest->MajorTarget, PropertyRequest->MinorTarget, GuidBuffer.Buffer, Property->Id, Property->Flags, PropertyRequest->InstanceSize, PropertyRequest->ValueSize,
+                 PropertyRequest->PropertyItem->Handler, PropertyRequest);
+ #if 0
+         Status = PropertyRequest->PropertyItem->Handler(PropertyRequest);
+ #else
+         Status = STATUS_NOT_FOUND;
+ #endif
+          Irp->IoStatus.Information = PropertyRequest->ValueSize;
+         if (Status != STATUS_PENDING)
          {
-             //found property handler
-             *OutPropertyItem = PropertyItem;
-             return STATUS_SUCCESS;
+             // free property request
+             FreeItem(PropertyRequest, TAG_PORTCLASS);
          }
-         PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + Node->AutomationTable->PropertyItemSize);
+     }
+     else
+     {
+         FreeItem(PropertyRequest, TAG_PORTCLASS);
+         Status = STATUS_NOT_FOUND;
      }
  
-     // no handler yet found
-     DPRINT("NotFound\n");
-     return STATUS_NOT_FOUND;
+     /* done */
+     return Status;
  }
  
  NTSTATUS
- PcNodeBasicSupportHandler(
-     PIRP Irp,
-     PPCPROPERTY_ITEM PropertyItem)
+ PcAddToPropertyTable(
+     IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor,
+     IN PPCPROPERTY_ITEM PropertyItem,
+     IN ULONG bNode)
  {
-     PULONG Flags;
-     PIO_STACK_LOCATION IoStack;
-     PKSPROPERTY_DESCRIPTION Description;
-     PKSP_NODE Property;
+     ULONG bFound = FALSE;
+     ULONG Index, PropertySetIndex, PropertySetItemIndex;
+     PKSPROPERTY_SET NewPropertySet;
+     PKSPROPERTY_ITEM FilterPropertyItem, NewFilterPropertyItem;
+     LPGUID Guid;
+     //UNICODE_STRING GuidBuffer;
  
-     // get current irp stack location
-     IoStack = IoGetCurrentIrpStackLocation(Irp);
-     // access property
-     Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+ ASSERT(PropertyItem->Set);
+       //      RtlStringFromGUID(*PropertyItem->Set, &GuidBuffer);
+    // DPRINT1("PcAddToPropertyTable Adding Item Set %S Id %lu Flags %lx\n", GuidBuffer.Buffer, PropertyItem->Id, PropertyItem->Flags);
  
-     PC_ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(ULONG));
-     Flags= (PULONG)Irp->UserBuffer;
  
-     // reset flags
-     *Flags = 0;
  
-     if (PropertyItem->Flags & KSPROPERTY_TYPE_SET)
-         *Flags |= KSPROPERTY_TYPE_SET;
+     //DPRINT1("FilterPropertySetCount %lu\n", SubDeviceDescriptor->FilterPropertySetCount);
+     // first step check if the property set is present already
+     for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySetCount; Index++)
+     {
  
-     if (PropertyItem->Flags & KSPROPERTY_TYPE_GET)
-         *Flags |= KSPROPERTY_TYPE_GET;
+               //RtlStringFromGUID(*SubDeviceDescriptor->FilterPropertySet[Index].Set, &GuidBuffer);
+         //DPRINT1("FilterProperty Set %S PropertyCount %lu\n", GuidBuffer.Buffer, SubDeviceDescriptor->FilterPropertySet[Index].PropertiesCount);
+         if (IsEqualGUIDAligned(*SubDeviceDescriptor->FilterPropertySet[Index].Set, *PropertyItem->Set))
+         {
+             // property set is already present
+             bFound = TRUE;
+             PropertySetIndex = Index;
  
-     // store result length
-     Irp->IoStatus.Information = sizeof(ULONG);
+             // break out
+             break;
+         }
+     }
  
-     if (IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(KSPROPERTY_DESCRIPTION))
+     // is the property set present
+     if (!bFound)
      {
-         // get output buffer
-         Description = (PKSPROPERTY_DESCRIPTION)Irp->UserBuffer;
-         // store result
-         Description->DescriptionSize = sizeof(KSPROPERTY_DESCRIPTION);
-         Description->PropTypeSet.Set = KSPROPTYPESETID_General;
-         Description->PropTypeSet.Id = 0;
-         Description->PropTypeSet.Flags = 0;
-         Description->MembersListCount = 0;
-         Description->Reserved = 0;
-         Irp->IoStatus.Information = sizeof(KSPROPERTY_DESCRIPTION);
-     }
-     return STATUS_SUCCESS;
- }
+         // need to allocate a property set
+         NewPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySetCount + 1) * sizeof(KSPROPERTY_SET), TAG_PORTCLASS);
+         if (!NewPropertySet)
+         {
+             // out of memory
+             return STATUS_INSUFFICIENT_RESOURCES;
+         }
  
+         // need to allocate property set guid
+         Guid = (LPGUID)AllocateItem(NonPagedPool, sizeof(GUID), TAG_PORTCLASS);
+         if (!Guid)
+         {
+             // out of memory
+             FreeItem(NewPropertySet, TAG_PORTCLASS);
+             return STATUS_INSUFFICIENT_RESOURCES;
+         }
  
- NTSTATUS
- PcHandleNodePropertyRequest(
-     PIRP Irp,
-     IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
- {
-     PIO_STACK_LOCATION IoStack;
-     PPCPROPERTY_ITEM  PropertyItem;
-     PPCPROPERTY_REQUEST PropertyRequest;
-     PKSP_NODE Property;
-     NTSTATUS Status;
+         // are any existing property sets
+         if (SubDeviceDescriptor->FilterPropertySetCount)
+         {
+             // copy property sets
+             RtlMoveMemory(NewPropertySet, SubDeviceDescriptor->FilterPropertySet, SubDeviceDescriptor->FilterPropertySetCount * sizeof(KSPROPERTY_SET));
  
-     // get current irp stack location
-     IoStack = IoGetCurrentIrpStackLocation(Irp);
+             // release memory
+             FreeItem(SubDeviceDescriptor->FilterPropertySet, TAG_PORTCLASS);
+         }
  
-     if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSP_NODE))
-     {
-         // certainly not a node property request
-         return STATUS_NOT_FOUND;
-     }
+         // store new property set descriptors
+         SubDeviceDescriptor->FilterPropertySet = NewPropertySet;
  
-     // access property
-     Property = (PKSP_NODE)IoStack->Parameters.DeviceIoControl.Type3InputBuffer;
+         // store index 
+         PropertySetIndex = SubDeviceDescriptor->FilterPropertySetCount;
  
-     if (IsEqualGUIDAligned(Property->Property.Set, GUID_NULL) && Property->Property.Id == 0 && Property->Property.Flags == (KSPROPERTY_TYPE_SETSUPPORT | KSPROPERTY_TYPE_TOPOLOGY))
-     {
-         return PcHandleGuidNullRequest(Irp, SubDeviceDescriptor);
+         // increment property set count
+         SubDeviceDescriptor->FilterPropertySetCount++;
+         // copy property guid
+         RtlMoveMemory(Guid, PropertyItem->Set, sizeof(GUID));
+         // initialize property set 
+         SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].Set = Guid;
+         SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount = 0;
      }
  
-     // find property handler
-     Status = PcFindNodePropertyHandler(Irp, SubDeviceDescriptor, &PropertyItem);
+     // as the property set has been indentified, now search for duplicate property set item entries
+     FilterPropertyItem = (PKSPROPERTY_ITEM)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem;
+     bFound = FALSE;
  
-     // check for success
-     if (!NT_SUCCESS(Status))
+     for(Index = 0; Index < SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount; Index++)
      {
-         // might not be a node property request
-         DPRINT("NotFound\n");
-         return STATUS_NOT_FOUND;
+         // now search for an equal property set item
+         if (FilterPropertyItem->PropertyId == PropertyItem->Id)
+         {
+             // found existing property set item
+             bFound = TRUE;
+             PropertySetItemIndex = Index;
+             break;
+         }
+         // move to next entry
+         FilterPropertyItem++;
      }
  
-     if (Property->Property.Flags & KSPROPERTY_TYPE_BASICSUPPORT)
+     if (!bFound)
      {
-         // caller issued a basic property request
-         if (!(PropertyItem->Flags & KSPROPERTY_TYPE_BASICSUPPORT))
+         // need to allocate memory for new property set item
+         NewFilterPropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount + 1) * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
+         if (!NewFilterPropertyItem)
          {
-             // driver does not have a basic support handler
-             return PcNodeBasicSupportHandler(Irp, PropertyItem);
+             // out of memory
+             return STATUS_INSUFFICIENT_RESOURCES;
          }
-     }
  
-     // sanity check
-     PC_ASSERT(SubDeviceDescriptor->UnknownMiniport);
+         // are any existing property set items
+         if (SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount)
+         {
+             // copy property item sets
+             RtlMoveMemory(NewFilterPropertyItem,
+                           (PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem,
+                           SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount * sizeof(KSPROPERTY_ITEM));
  
-     // allocate a property request
-     PropertyRequest = (PPCPROPERTY_REQUEST)AllocateItem(NonPagedPool, sizeof(PCPROPERTY_REQUEST), TAG_PORTCLASS);
-     if (!PropertyRequest)
-         return STATUS_INSUFFICIENT_RESOURCES;
+             // release old descriptors
+             FreeItem((PVOID)SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem, TAG_PORTCLASS);
+         }
  
-      // initialize property request
-      PropertyRequest->MajorTarget = SubDeviceDescriptor->UnknownMiniport;
-      PropertyRequest->MinorTarget = SubDeviceDescriptor->UnknownStream;
-      PropertyRequest->Irp = Irp;
-      PropertyRequest->Node = Property->NodeId;
-      PropertyRequest->PropertyItem = PropertyItem;
-      PropertyRequest->Verb = Property->Property.Flags;
-      PropertyRequest->InstanceSize = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSNODEPROPERTY);
-      PropertyRequest->Instance = (PVOID)((ULONG_PTR)IoStack->Parameters.DeviceIoControl.Type3InputBuffer + sizeof(KSNODEPROPERTY));
-      PropertyRequest->ValueSize = IoStack->Parameters.DeviceIoControl.OutputBufferLength;
-      PropertyRequest->Value = Irp->UserBuffer;
-      Status = PropertyItem->Handler(PropertyRequest);
-      if (Status != STATUS_PENDING)
-      {
-          //request completed
-          Irp->IoStatus.Information = PropertyRequest->ValueSize;
-          FreeItem(PropertyRequest, TAG_PORTCLASS);
-      }
+         // store new descriptor
+         SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem = NewFilterPropertyItem;
  
-      // done
-      DPRINT("Status %x\n", Status);
-      return Status;
- }
+         // store index
+         PropertySetItemIndex = SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount;
  
- NTSTATUS
- NTAPI
- PcHandlePropertyWithTable(
-     IN PIRP Irp,
-     IN ULONG PropertySetCount,
-     IN PKSPROPERTY_SET PropertySet,
-     IN PSUBDEVICE_DESCRIPTOR SubDeviceDescriptor)
- {
-     NTSTATUS Status;
+         // increment property item set count
+         SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertiesCount++;
  
-     // try handle it as node property request
-     Status = PcHandleNodePropertyRequest(Irp, SubDeviceDescriptor);
+         // now initialize property item
+         FilterPropertyItem = (PKSPROPERTY_ITEM)&SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex];
+         FilterPropertyItem->PropertyId = PropertyItem->Id;
+         FilterPropertyItem->MinProperty = sizeof(KSPROPERTY);
+         FilterPropertyItem->MinData = 0;
  
-     if (Status == STATUS_NOT_FOUND)
-     {
-         // store device descriptor
-         KSPROPERTY_ITEM_IRP_STORAGE(Irp) = (PKSPROPERTY_ITEM)SubDeviceDescriptor;
+         // are any set operations supported
+         if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_SET)
+         {
+             // setup handler 
+             FilterPropertyItem->SetPropertyHandler = PropertyItemDispatch;
+         }
  
-         /* then try KsPropertyHandler */
-         Status = KsPropertyHandler(Irp, PropertySetCount, PropertySet);
-     }
+         // are set operation supported
+         if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
+         {
+             // setup handler
+             FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
+         }
  
-     return Status;
- }
+         // are get operations supported
+         if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_GET)
+         {
+             // setup handler 
+             FilterPropertyItem->GetPropertyHandler = PropertyItemDispatch;
+         }
  
- VOID
- NTAPI
- PcAcquireFormatResources(
-     LONG Unknown,
-     LONG Unknown2,
-     LONG Unknown3,
-     LONG Unknown4)
- {
-     UNIMPLEMENTED;
- }
+         // are basic support operations supported
+         if (PropertyItem->Flags & PCPROPERTY_ITEM_FLAG_BASICSUPPORT)
+         {
+             // setup handler 
+             FilterPropertyItem->SupportHandler = PropertyItemDispatch;
+         }
  
- NTSTATUS
- PcAddToEventTable(
-     PVOID Ptr,
-     LONG Unknown2,
-     ULONG Length,
-     LONG Unknown3,
-     LONG Unknown4,
-     LONG Unknown5,
-     LONG Unknown6,
-     LONG Unknown7)
- {
-     UNIMPLEMENTED;
-     return STATUS_NOT_IMPLEMENTED;
- }
+         if (!bNode)
+         {
+             // store property item in relations
+             // only store property item of filter properties / pin properties
+             // because filter & pin properties do not require a specific context
+             // on the other hand node properties are specifically bound to a node
+              
+             FilterPropertyItem->Relations = (const KSPROPERTY*)PropertyItem;
+         }
+     }
+     else
+     {
+         // property set item handler already present
  
- NTSTATUS
- PcAddToPropertyTable(
-     PVOID Ptr,
-     LONG Unknown,
-     LONG Unknown2,
-     LONG Unknown3,
-     CHAR Unknown4)
- {
-     UNIMPLEMENTED;
-     return STATUS_NOT_IMPLEMENTED;
+         if (bNode)
+         {
+             // filter & pin properties should not be exposed on a node
+             ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations == NULL);
+         }
+         else
+         {
+             // node properties should not be exposed on a filter & pin
+             ASSERT(SubDeviceDescriptor->FilterPropertySet[PropertySetIndex].PropertyItem[PropertySetItemIndex].Relations != NULL);
+         }
+     }
+     // done
+     return STATUS_SUCCESS;
  }
  
  NTSTATUS
@@@ -491,6 -573,15 +573,15 @@@ DumpFilterDescriptor
                      EventItem = (PPCEVENT_ITEM)((ULONG_PTR)EventItem + NodeDescriptor->AutomationTable->EventItemSize);
                  }
  
+                 DPRINT1(" Index %u PropertyCount %u\n", Index, NodeDescriptor->AutomationTable->PropertyCount);
+                 PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
+                 for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
+                 {
+                     RtlStringFromGUID(*PropertyItem->Set, &GuidString);
+                     DPRINT1("  PropertyIndex %u GUID %S Id %u Flags %x\n", SubIndex, GuidString.Buffer, PropertyItem->Id, PropertyItem->Flags);
+                     PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
+                 }
              }
  
  
@@@ -539,10 -630,13 +630,13 @@@ PcCreateSubdeviceDescriptor
      IN PPCFILTER_DESCRIPTOR FilterDescription)
  {
      SUBDEVICE_DESCRIPTOR * Descriptor;
-     ULONG Index;
+     ULONG Index, SubIndex;
      NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
      PPCPIN_DESCRIPTOR SrcDescriptor;
+     PPCNODE_DESCRIPTOR NodeDescriptor;
+     PPCPROPERTY_ITEM PropertyItem;
  
+     // allocate subdevice descriptor
      Descriptor = (PSUBDEVICE_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(SUBDEVICE_DESCRIPTOR), TAG_PORTCLASS);
      if (!Descriptor)
          return STATUS_INSUFFICIENT_RESOURCES;
      InitializeListHead(&Descriptor->SymbolicLinkList);
      InitializeListHead(&Descriptor->PhysicalConnectionList);
  
+     //FIXME add driver category guids
      Descriptor->Interfaces = (GUID*)AllocateItem(NonPagedPool, sizeof(GUID) * InterfaceCount, TAG_PORTCLASS);
      if (!Descriptor->Interfaces)
          goto cleanup;
      RtlCopyMemory(Descriptor->Interfaces, InterfaceGuids, sizeof(GUID) * InterfaceCount);
      Descriptor->InterfaceCount = InterfaceCount;
  
+     //DumpFilterDescriptor(FilterDescription);
+     // are any property sets supported by the portcls
      if (FilterPropertiesCount)
      {
-        /// FIXME
-        /// handle driver properties
-        DumpFilterDescriptor(FilterDescription);
+        // first allocate filter properties set
         Descriptor->FilterPropertySet = (PKSPROPERTY_SET)AllocateItem(NonPagedPool, sizeof(KSPROPERTY_SET) * FilterPropertiesCount, TAG_PORTCLASS);
         if (! Descriptor->FilterPropertySet)
             goto cleanup;
  
+        // now copy all filter property sets
         Descriptor->FilterPropertySetCount = FilterPropertiesCount;
         for(Index = 0; Index < FilterPropertiesCount; Index++)
         {
+            // copy property set
             RtlMoveMemory(&Descriptor->FilterPropertySet[Index], &FilterProperties[Index], sizeof(KSPROPERTY_SET));
-        }
-     }
-     Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
-     if (!Descriptor->Topology)
-         goto cleanup;
  
-     if (FilterDescription->ConnectionCount)
-     {
-         Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
-         if (!Descriptor->Topology->TopologyConnections)
-             goto cleanup;
-         RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR));
-         Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount;
+            if (Descriptor->FilterPropertySet[Index].PropertiesCount)
+            {
+                // copy property items to make sure they are dynamically allocated
+                Descriptor->FilterPropertySet[Index].PropertyItem = (PKSPROPERTY_ITEM)AllocateItem(NonPagedPool, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM), TAG_PORTCLASS);
+                if (!Descriptor->FilterPropertySet[Index].PropertyItem)
+                {
+                    // no memory
+                    goto cleanup;
+                }
+                // copy filter property items
+                RtlMoveMemory((PVOID)Descriptor->FilterPropertySet[Index].PropertyItem, FilterProperties[Index].PropertyItem, FilterProperties[Index].PropertiesCount * sizeof(KSPROPERTY_ITEM));
+            }
+        }
      }
  
-     if (FilterDescription->NodeCount)
+     // now check if the filter descriptor supports filter properties
+     if (FilterDescription->AutomationTable)
      {
-         Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
-         if (!Descriptor->Topology->TopologyNodes)
-             goto cleanup;
+         // get first entry
+         PropertyItem = (PPCPROPERTY_ITEM)FilterDescription->AutomationTable->Properties;
  
-         Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
-         if (!Descriptor->Topology->TopologyNodesNames)
-             goto cleanup;
-         for(Index = 0; Index < FilterDescription->NodeCount; Index++)
+         // copy driver filter property sets
+         for(Index = 0; Index < FilterDescription->AutomationTable->PropertyCount; Index++)
          {
-             if (FilterDescription->Nodes[Index].Type)
-             {
-                 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], FilterDescription->Nodes[Index].Type, sizeof(GUID));
-             }
-             if (FilterDescription->Nodes[Index].Name)
+             // add the property item
+             Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
+             // check for success
+             if (Status != STATUS_SUCCESS)
              {
-                 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], FilterDescription->Nodes[Index].Name, sizeof(GUID));
+                 // goto cleanup
+                 goto cleanup;
              }
+             // move to next entry
+             PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + FilterDescription->AutomationTable->PropertyItemSize);
          }
-         Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
      }
  
+     // check if the filter has pins
      if (FilterDescription->PinCount)
      {
+         // allocate pin factory descriptors
          Descriptor->Factory.KsPinDescriptor = (PKSPIN_DESCRIPTOR)AllocateItem(NonPagedPool, sizeof(KSPIN_DESCRIPTOR) * FilterDescription->PinCount, TAG_PORTCLASS);
          if (!Descriptor->Factory.KsPinDescriptor)
              goto cleanup;
  
+         // allocate pin instance info
          Descriptor->Factory.Instances = (PPIN_INSTANCE_INFO)AllocateItem(NonPagedPool, FilterDescription->PinCount * sizeof(PIN_INSTANCE_INFO), TAG_PORTCLASS);
          if (!Descriptor->Factory.Instances)
              goto cleanup;
  
+         // initialize pin factory descriptor
          Descriptor->Factory.PinDescriptorCount = FilterDescription->PinCount;
          Descriptor->Factory.PinDescriptorSize = sizeof(KSPIN_DESCRIPTOR);
  
+         // grab first entry
          SrcDescriptor = (PPCPIN_DESCRIPTOR)FilterDescription->Pins;
-         DPRINT("Size %u Expected %u\n", FilterDescription->PinSize, sizeof(PCPIN_DESCRIPTOR));
  
          // copy pin factories
          for(Index = 0; Index < FilterDescription->PinCount; Index++)
          {
+             // copy pin descriptor
              RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
  
-             Descriptor->Factory.KsPinDescriptor[Index].Interfaces = PinInterfaces;
-             Descriptor->Factory.KsPinDescriptor[Index].InterfacesCount = sizeof(PinInterfaces) / sizeof(KSPIN_INTERFACE);
-             DPRINT("Index %u DataRangeCount %u\n", Index, SrcDescriptor->KsPinDescriptor.DataRangesCount);
+             // initialize pin factory instance data
              Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;
              Descriptor->Factory.Instances[Index].MaxFilterInstanceCount = SrcDescriptor->MaxFilterInstanceCount;
              Descriptor->Factory.Instances[Index].MaxGlobalInstanceCount = SrcDescriptor->MaxGlobalInstanceCount;
              Descriptor->Factory.Instances[Index].MinFilterInstanceCount = SrcDescriptor->MinFilterInstanceCount;
+             // check if the descriptor has an automation table
+             if (SrcDescriptor->AutomationTable)
+             {
+                 // it has, grab first entry
+                 PropertyItem = (PPCPROPERTY_ITEM)SrcDescriptor->AutomationTable->Properties;
+                 // now add all supported property items
+                 for(SubIndex = 0; SubIndex < SrcDescriptor->AutomationTable->PropertyCount; SubIndex++)
+                 {
+                     // add the property item to the table
+                     Status = PcAddToPropertyTable(Descriptor, PropertyItem, FALSE);
+                     // check for success
+                     if (Status != STATUS_SUCCESS)
+                     {
+                         // goto cleanup
+                         goto cleanup;
+                     }
+                     // move to next entry
+                     PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + SrcDescriptor->AutomationTable->PropertyItemSize);
+                 }
+             }
+             // move to next entry
              SrcDescriptor = (PPCPIN_DESCRIPTOR)((ULONG_PTR)SrcDescriptor + FilterDescription->PinSize);
          }
      }
  
+     // allocate topology descriptor
+     Descriptor->Topology = (PKSTOPOLOGY)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY), TAG_PORTCLASS);
+     if (!Descriptor->Topology)
+         goto cleanup;
+     // are there any connections
+     if (FilterDescription->ConnectionCount)
+     {
+         // allocate connection descriptor
+         Descriptor->Topology->TopologyConnections = (PKSTOPOLOGY_CONNECTION)AllocateItem(NonPagedPool, sizeof(KSTOPOLOGY_CONNECTION) * FilterDescription->ConnectionCount, TAG_PORTCLASS);
+         if (!Descriptor->Topology->TopologyConnections)
+             goto cleanup;
+         // copy connection descriptor
+         RtlMoveMemory((PVOID)Descriptor->Topology->TopologyConnections, FilterDescription->Connections, FilterDescription->ConnectionCount * sizeof(PCCONNECTION_DESCRIPTOR));
+         // store connection count
+         Descriptor->Topology->TopologyConnectionsCount = FilterDescription->ConnectionCount;
+     }
+     // does the filter have nodes
+     if (FilterDescription->NodeCount)
+     {
+         // allocate topology node types array
+         Descriptor->Topology->TopologyNodes = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
+         if (!Descriptor->Topology->TopologyNodes)
+             goto cleanup;
+         // allocate topology node names array
+         Descriptor->Topology->TopologyNodesNames = (const GUID *)AllocateItem(NonPagedPool, sizeof(GUID) * FilterDescription->NodeCount, TAG_PORTCLASS);
+         if (!Descriptor->Topology->TopologyNodesNames)
+             goto cleanup;
+         // grab first entry
+        NodeDescriptor = (PPCNODE_DESCRIPTOR)FilterDescription->Nodes;
+        // iterate all nodes and copy node types / names and node properties
+         for(Index = 0; Index < FilterDescription->NodeCount; Index++)
+         {
+             // does it have a type
+             if (NodeDescriptor->Type)
+             {
+                 // copy node type
+                 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodes[Index], NodeDescriptor->Type, sizeof(GUID));
+             }
+             // does it have a node name
+             if (NodeDescriptor->Name)
+             {
+                 // copy node name
+                 RtlMoveMemory((PVOID)&Descriptor->Topology->TopologyNodesNames[Index], NodeDescriptor->Name, sizeof(GUID));
+             }
+             // check if has an automation table
+             if (NodeDescriptor->AutomationTable)
+             {
+                 // grab first entry
+                 PropertyItem = (PPCPROPERTY_ITEM)NodeDescriptor->AutomationTable->Properties;
+                 // copy all node properties into the global property set
+                 for(SubIndex = 0; SubIndex < NodeDescriptor->AutomationTable->PropertyCount; SubIndex++)
+                 {
+                     // add to property set
+                     Status = PcAddToPropertyTable(Descriptor, PropertyItem, TRUE);
+                     // check for success
+                     if (Status != STATUS_SUCCESS)
+                     {
+                         // failed
+                         goto cleanup;
+                     }
+                     // move to next property item
+                     PropertyItem = (PPCPROPERTY_ITEM)((ULONG_PTR)PropertyItem + NodeDescriptor->AutomationTable->PropertyItemSize);
+                 }
+             }
+             // move to next descriptor
+             NodeDescriptor = (PPCNODE_DESCRIPTOR)((ULONG_PTR)NodeDescriptor + FilterDescription->NodeSize);
+         }
+         // now store the topology node count
+         Descriptor->Topology->TopologyNodesCount = FilterDescription->NodeCount;
+     }
+     // store descriptor
      Descriptor->DeviceDescriptor = FilterDescription;
+     // store result
      *OutSubdeviceDescriptor = Descriptor;
+     // done
      return STATUS_SUCCESS;
  
  cleanup:
@@@ -235,8 -235,9 +235,9 @@@ HalpReportResourceUsage(IN PUNICODE_STR
          if (!HalpGetInfoFromACPI)
          {
              /* No, so use our local table */
-             Port = HalpComPortIrqMapping[0][0];
-             for (i = 0; Port; i++)
+             for (i = 0, Port = HalpComPortIrqMapping[i][0];
+                  Port;
+                  i++, Port = HalpComPortIrqMapping[i][0])
              {
                  /* Is this the port we want? */
                  if (Port == (ULONG_PTR)KdComPortInUse)
                                         PRIMARY_VECTOR_BASE,
                                         HIGH_LEVEL);
                  }
-                 
-                 /* Next port */
-                 Port = HalpComPortIrqMapping[i][0];
              }
          }
      }
@@@ -509,6 -507,9 +507,9 @@@ HalpEnableInterruptHandler(IN UCHAR Fla
                             IN PVOID Handler,
                             IN KINTERRUPT_MODE Mode)
  {
+     /* Set the IDT_LATCHED flag for latched interrupts */
+     if (Mode == Latched) Flags |= IDT_LATCHED;
+     
      /* Register the vector */
      HalpRegisterVector(Flags, BusVector, SystemVector, Irql);
  
diff --combined include/psdk/ks.h
@@@ -1005,11 -1005,6 +1005,6 @@@ DEFINE_GUIDSTRUCT("97E99BA0-BDEA-11CF-A
      KSPROPERTY_DIRECTSOUND3DLISTENER_VELOCITY
  */
  
- #define KSPROPSETID_DrmAudioStream
- /*
-     KSPROPERTY_DRMAUDIOSTREAM_CONTENTID
- */
  #define KSPROPSETID_Hrtf3d
  /*
      KSPROPERTY_HRTF3D_FILTER_FORMAT
diff --combined include/psdk/ksmedia.h
@@@ -565,6 -565,15 +565,15 @@@ typedef struct 
  #endif // !_NTDDK_
  } LOOPEDSTREAMING_POSITION_EVENT_DATA, *PLOOPEDSTREAMING_POSITION_EVENT_DATA ;
  
+ #define STATIC_KSPROPSETID_DrmAudioStream\
+     0x2f2c8ddd, 0x4198, 0x4fac, 0xba, 0x29, 0x61, 0xbb, 0x5, 0xb7, 0xde, 0x6
+ DEFINE_GUIDSTRUCT("2F2C8DDD-4198-4fac-BA29-61BB05B7DE06", KSPROPSETID_DrmAudioStream);
+ #define KSPROPSETID_DrmAudioStream DEFINE_GUIDNAMED(KSPROPSETID_DrmAudioStream)
+ typedef enum {
+     KSPROPERTY_DRMAUDIOSTREAM_CONTENTID
+ } KSPROPERTY_DRMAUDIOSTREAM;
  
  /*
      SysAudio Properties
@@@ -51,13 -51,15 +51,15 @@@ VOID NTAPI RtlInitLargeAnsiString(IN OU
  VOID NTAPI RtlInitLargeUnicodeString(IN OUT PLARGE_UNICODE_STRING,IN PCWSTR,IN INT);
  BOOL NTAPI RtlLargeStringToUnicodeString( PUNICODE_STRING, PLARGE_STRING);
  
+ #define NB_HOOKS (WH_MAXHOOK-WH_MINHOOK+1)
  typedef struct _DESKTOPINFO
  {
      PVOID pvDesktopBase;
      PVOID pvDesktopLimit;
      struct _WND *spwnd;
      DWORD fsHooks;
-     struct tagHOOK * aphkStart[16];
+     LIST_ENTRY aphkStart[NB_HOOKS];
  
      HWND hTaskManWindow;
      HWND hProgmanWindow;
@@@ -127,15 -129,23 +129,23 @@@ typedef struct _PROCMARKHEA
  /* Window Client Information structure */
  struct  _ETHREAD;
  
+ #define WEF_SETBYWNDPTI      0x0001
  typedef struct tagHOOK
  {
    THRDESKHEAD    head;
+   struct tagHOOK *phkNext;   /* This is for user space. */
+   int            HookId;     /* Hook table index */
+   ULONG_PTR      offPfn;
+   ULONG          flags;      /* Some internal flags */
+   INT            ihmod;
+   PTHREADINFO    ptiHooked;
+   struct _DESKTOP *rpdesk;
+   /* ReactOS */
    LIST_ENTRY     Chain;      /* Hook chain entry */
    struct _ETHREAD* Thread;   /* Thread owning the hook */
-   int            HookId;     /* Hook table index */
    HOOKPROC       Proc;       /* Hook function */
    BOOLEAN        Ansi;       /* Is it an Ansi hook? */
-   ULONG          Flags;      /* Some internal flags */
    UNICODE_STRING ModuleName; /* Module name for global hooks */
  } HOOK, *PHOOK;
  
@@@ -3149,7 -3159,6 +3159,6 @@@ typedef struct tagKMDDELPARA
  #define NOPARAM_ROUTINE_ANYPOPUP              0xffff0006
  #define ONEPARAM_ROUTINE_CSRSS_GUICHECK       0xffff0008
  #define ONEPARAM_ROUTINE_SWITCHCARETSHOWING   0xfffe0008
- #define ONEPARAM_ROUTINE_ISWINDOWINDESTROY    0xfffe000c
  #define ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING 0xfffe000d
  #define ONEPARAM_ROUTINE_GETDESKTOPMAPPING    0xfffe000e
  #define ONEPARAM_ROUTINE_MSQSETWAKEMASK       0xfffe0027
  #define TWOPARAM_ROUTINE_SETCARETPOS        0xfffd0060
  #define TWOPARAM_ROUTINE_REGISTERLOGONPROC  0xfffd0062
  #define TWOPARAM_ROUTINE_ROS_UPDATEUISTATE  0x1004
+ #define HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT 0x1005
  
  DWORD
  NTAPI
@@@ -514,6 -514,21 +514,21 @@@ IopAssignDeviceResources
      IN PDEVICE_NODE DeviceNode
  );
  
+ NTSTATUS
+ NTAPI
+ IopCreateResourceListFromRequirements(
+     IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList,
+     OUT PCM_RESOURCE_LIST *ResourceList
+ );
+ NTSTATUS
+ NTAPI
+ IopDetectResourceConflict(
+      IN PCM_RESOURCE_LIST ResourceList,
+      IN BOOLEAN Silent,
+      OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor
+ );
  //
  // PNP Routines
  //
@@@ -841,7 -841,7 +841,7 @@@ IoGetConfigurationInformation(VOID
  }
  
  /*
-  * @unimplemented
+  * @halfplemented
   */
  NTSTATUS NTAPI
  IoReportResourceUsage(PUNICODE_STRING DriverClassName,
        *       a conflict is detected with another driver.
        */
  {
-    UNIMPLEMENTED;
-    *ConflictDetected = FALSE;
-    return STATUS_SUCCESS;
+     NTSTATUS Status;
+     PCM_RESOURCE_LIST ResourceList;
+     
+     DPRINT1("IoReportResourceUsage is halfplemented!\n");
+     
+     if (!DriverList && !DeviceList)
+         return STATUS_INVALID_PARAMETER;
+     
+     if (DeviceList)
+         ResourceList = DeviceList;
+     else
+         ResourceList = DriverList;
+     
+     Status = IopDetectResourceConflict(ResourceList, FALSE, NULL);
+     if (Status == STATUS_CONFLICTING_ADDRESSES)
+     {
+         *ConflictDetected = TRUE;
+         
+         if (!OverrideConflict)
+         {
+             DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
+             return STATUS_CONFLICTING_ADDRESSES;
+         }
+         else
+         {
+             DPRINT1("Proceeding with conflicting resources\n");
+         }
+     }
+     else if (!NT_SUCCESS(Status))
+     {
+         return Status;
+     }
+     /* TODO: Claim resources in registry */
+     
+     *ConflictDetected = FALSE;
+     
+     return STATUS_SUCCESS;
  }
  
  /*
-  * @unimplemented
+  * @halfplemented
   */
  NTSTATUS NTAPI
  IoAssignResources(PUNICODE_STRING RegistryPath,
                  PIO_RESOURCE_REQUIREMENTS_LIST RequestedResources,
                  PCM_RESOURCE_LIST* AllocatedResources)
  {
-    UNIMPLEMENTED;
-    return(STATUS_NOT_IMPLEMENTED);
+     NTSTATUS Status;
+     
+     DPRINT1("IoAssignResources is halfplemented!\n");
+     
+     Status = IopCreateResourceListFromRequirements(RequestedResources,
+                                                    AllocatedResources);
+     if (!NT_SUCCESS(Status))
+     {
+         if (Status == STATUS_CONFLICTING_ADDRESSES)
+             DPRINT1("Denying an attempt to claim resources currently in use by another device!\n");
+         
+         return Status;
+     }
+     
+     /* TODO: Claim resources in registry */
+     
+     return STATUS_SUCCESS;
  }
  
  /*
@@@ -38,9 -38,6 +38,6 @@@ NTSTATU
  IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
                                  PVOID Context);
  
- NTSTATUS
- IopDetectResourceConflict(IN PCM_RESOURCE_LIST ResourceList);
  NTSTATUS
  PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject,
                         IN OUT PKEVENT SyncEvent OPTIONAL,
@@@ -379,7 -376,7 +376,7 @@@ IoReportResourceForDetection(IN PDRIVER
          ResourceList = DriverList;
  
      /* Look for a resource conflict */
-     Status = IopDetectResourceConflict(ResourceList);
+     Status = IopDetectResourceConflict(ResourceList, FALSE, NULL);
      if (Status == STATUS_CONFLICTING_ADDRESSES)
      {
          /* Oh noes */
  #define NDEBUG
  #include <debug.h>
  
- NTSTATUS
- IopDetectResourceConflict(
-    IN PCM_RESOURCE_LIST ResourceList,
-    IN BOOLEAN Silent,
-    OUT OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor);
  static
  BOOLEAN
  IopCheckDescriptorForConflict(PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc, OPTIONAL PCM_PARTIAL_RESOURCE_DESCRIPTOR ConflictingDescriptor)
@@@ -187,8 -181,8 +181,8 @@@ IopFindInterruptResource
     return FALSE;
  }
  
- static
- NTSTATUS
+ NTSTATUS NTAPI
  IopCreateResourceListFromRequirements(
     IN PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList,
     OUT PCM_RESOURCE_LIST *ResourceList)
@@@ -336,9 -330,6 +330,6 @@@ IopCheckResourceDescriptor
     ULONG i, ii;
     BOOLEAN Result = FALSE;
  
-    if (ResDesc->ShareDisposition == CmResourceShareShared)
-        return FALSE;
     for (i = 0; i < ResourceList->Count; i++)
     {
        PCM_PARTIAL_RESOURCE_LIST ResList = &ResourceList->List[i].PartialResourceList;
@@@ -615,40 -606,61 +606,61 @@@ IopUpdateResourceMap(IN PDEVICE_NODE De
  
    if (DeviceNode->ResourceList)
    {
-       PWCHAR DeviceName = NULL;
        UNICODE_STRING NameU;
-       UNICODE_STRING Suffix;
+       UNICODE_STRING RawSuffix, TranslatedSuffix;
        ULONG OldLength = 0;
  
        ASSERT(DeviceNode->ResourceListTranslated);
+       
+       RtlInitUnicodeString(&TranslatedSuffix, L".Translated");
+       RtlInitUnicodeString(&RawSuffix, L".Raw");
  
        Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
                                     DevicePropertyPhysicalDeviceObjectName,
                                     0,
                                     NULL,
                                     &OldLength);
-      if ((OldLength != 0) && (Status == STATUS_BUFFER_TOO_SMALL))
-      {
-         DeviceName = ExAllocatePool(NonPagedPool, OldLength);
-         ASSERT(DeviceName);
-         IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
-                             DevicePropertyPhysicalDeviceObjectName,
-                             OldLength,
-                             DeviceName,
-                             &OldLength);
-                             
-         RtlInitUnicodeString(&NameU, DeviceName);
-      }
-      else
-      {
-         /* Some failure */
-         ASSERT(!NT_SUCCESS(Status));
-         return Status;
-      }
-       RtlInitUnicodeString(&Suffix, L".Raw");
-       RtlAppendUnicodeStringToString(&NameU, &Suffix);
+       if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
+       {
+           ASSERT(OldLength);
+           
+           NameU.Buffer = ExAllocatePool(PagedPool, OldLength + TranslatedSuffix.Length);
+           if (!NameU.Buffer)
+           {
+               ZwClose(PnpMgrLevel2);
+               return STATUS_INSUFFICIENT_RESOURCES;
+           }
+           
+           NameU.Length = 0;
+           NameU.MaximumLength = OldLength + TranslatedSuffix.Length;
+           
+           Status = IoGetDeviceProperty(DeviceNode->PhysicalDeviceObject,
+                                        DevicePropertyPhysicalDeviceObjectName,
+                                        NameU.MaximumLength,
+                                        NameU.Buffer,
+                                        &OldLength);
+           if (!NT_SUCCESS(Status))
+           {
+               ZwClose(PnpMgrLevel2);
+               ExFreePool(NameU.Buffer);
+               return Status;
+           }
+       }
+       else if (!NT_SUCCESS(Status))
+       {
+           /* Some failure */
+           ZwClose(PnpMgrLevel2);
+           return Status;
+       }
+       else
+       {
+           /* This should never happen */
+           ASSERT(FALSE);
+       }
+       
+       NameU.Length = OldLength;
+       RtlAppendUnicodeStringToString(&NameU, &RawSuffix);
  
        Status = ZwSetValueKey(PnpMgrLevel2,
                               &NameU,
        if (!NT_SUCCESS(Status))
        {
            ZwClose(PnpMgrLevel2);
+           ExFreePool(NameU.Buffer);
            return Status;
        }
  
        /* "Remove" the suffix by setting the length back to what it used to be */
-       NameU.Length = (USHORT)OldLength;
+       NameU.Length = OldLength;
  
-       RtlInitUnicodeString(&Suffix, L".Translated");
-       RtlAppendUnicodeStringToString(&NameU, &Suffix);
+       RtlAppendUnicodeStringToString(&NameU, &TranslatedSuffix);
  
        Status = ZwSetValueKey(PnpMgrLevel2,
                               &NameU,
                               DeviceNode->ResourceListTranslated,
                               PnpDetermineResourceListSize(DeviceNode->ResourceListTranslated));
        ZwClose(PnpMgrLevel2);
-       ASSERT(DeviceName);
-       ExFreePool(DeviceName);
+       ExFreePool(NameU.Buffer);
        if (!NT_SUCCESS(Status))
            return Status;
    }
@@@ -718,7 -730,7 +730,7 @@@ IopTranslateDeviceResources
     DeviceNode->ResourceListTranslated = ExAllocatePool(PagedPool, ListSize);
     if (!DeviceNode->ResourceListTranslated)
     {
-       Status =STATUS_NO_MEMORY;
+       Status = STATUS_NO_MEMORY;
        goto cleanup;
     }
     RtlCopyMemory(DeviceNode->ResourceListTranslated, DeviceNode->ResourceList, ListSize);
                    &DescriptorTranslated->u.Port.Start))
                 {
                    Status = STATUS_UNSUCCESSFUL;
+                   DPRINT1("Failed to translate port resource (Start: 0xI64x)\n", DescriptorRaw->u.Port.Start.QuadPart);
                    goto cleanup;
                 }
                 break;
                    DescriptorRaw->u.Interrupt.Vector,
                    (PKIRQL)&DescriptorTranslated->u.Interrupt.Level,
                    &DescriptorTranslated->u.Interrupt.Affinity);
+                 
+                if (!DescriptorTranslated->u.Interrupt.Vector)
+                {
+                    Status = STATUS_UNSUCCESSFUL;
+                    DPRINT1("Failed to translate interrupt resource (Vector: 0x%x | Level: 0x%x)\n", DescriptorRaw->u.Interrupt.Vector,
+                                                                                                    DescriptorRaw->u.Interrupt.Level);
+                    goto cleanup;
+                }
                 break;
              }
              case CmResourceTypeMemory:
                    &DescriptorTranslated->u.Memory.Start))
                 {
                    Status = STATUS_UNSUCCESSFUL;
+                   DPRINT1("Failed to translate memory resource (Start: 0xI64x)\n", DescriptorRaw->u.Memory.Start.QuadPart);
                    goto cleanup;
                 }
              }
@@@ -864,16 -886,21 +886,21 @@@ IopAssignDeviceResources
     Status = IopCreateResourceListFromRequirements(DeviceNode->ResourceRequirements,
                                                    &DeviceNode->ResourceList);
     if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create a resource list from supplied resources for %wZ\n", &DeviceNode->InstancePath);
         goto ByeBye;
+    }
  
-    Status = IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL);
-    if (!NT_SUCCESS(Status))
-        goto ByeBye;
+    /* IopCreateResourceListFromRequirements should NEVER succeed with a conflicting list */
+    ASSERT(IopDetectResourceConflict(DeviceNode->ResourceList, FALSE, NULL) != STATUS_CONFLICTING_ADDRESSES);
  
  Finish:
     Status = IopTranslateDeviceResources(DeviceNode);
     if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to translate resources for %wZ\n", &DeviceNode->InstancePath);
         goto ByeBye;
+    }
  
     Status = IopUpdateResourceMapForPnPDevice(DeviceNode);
     if (!NT_SUCCESS(Status))
@@@ -935,7 -962,7 +962,7 @@@ ByeBye
     return Result;
  }
  
- NTSTATUS
+ NTSTATUS NTAPI
  IopDetectResourceConflict(
     IN PCM_RESOURCE_LIST ResourceList,
     IN BOOLEAN Silent,
@@@ -1048,6 -1048,48 +1048,48 @@@ MmFlushVirtualMemory(IN PEPROCESS Proce
      return STATUS_SUCCESS;
  }
  
+ ULONG
+ NTAPI
+ MiGetPageProtection(IN PMMPTE PointerPte)
+ {
+     MMPTE TempPte;
+     PMMPFN Pfn;
+     PAGED_CODE();
+     /* Copy this PTE's contents */
+     TempPte = *PointerPte;
+     /* Assure it's not totally zero */
+     ASSERT(TempPte.u.Long);
+     /* Check for a special prototype format */
+     if (TempPte.u.Soft.Valid == 0 &&
+         TempPte.u.Soft.Prototype == 1)
+     {
+         /* Unsupported now */
+         UNIMPLEMENTED;
+         ASSERT(FALSE);
+     }
+     /* In the easy case of transition or demand zero PTE just return its protection */
+     if (!TempPte.u.Hard.Valid) return MmProtectToValue[TempPte.u.Soft.Protection];
+     /* If we get here, the PTE is valid, so look up the page in PFN database */
+     Pfn = MiGetPfnEntry(TempPte.u.Hard.PageFrameNumber);
+     if (!Pfn->u3.e1.PrototypePte)
+     {
+         /* Return protection of the original pte */
+         return MmProtectToValue[Pfn->OriginalPte.u.Soft.Protection];
+     }
+     /* This is hardware PTE */
+     UNIMPLEMENTED;
+     ASSERT(FALSE);
+     return PAGE_NOACCESS;
+ }
  ULONG
  NTAPI
  MiQueryAddressState(IN PVOID Va,
              {
                  /* This means it's committed */
                  State = MEM_COMMIT;
-                 
-                 /* For now, we lie about the protection */
-                 Protect = PAGE_EXECUTE_READWRITE;
+                 /* Get protection state of this page */
+                 Protect = MiGetPageProtection(PointerPte);
              }
              else
              {
@@@ -2306,7 -2348,7 +2348,7 @@@ NtQueryVirtualMemory(IN HANDLE ProcessH
      NTSTATUS Status;
      PMMVAD Vad = NULL;
      PVOID Address, NextAddress;
-     BOOLEAN Found;
+     BOOLEAN Found = FALSE;
      ULONG NewProtect, NewState, BaseVpn;
      MEMORY_BASIC_INFORMATION MemoryInfo;
      KAPC_STATE ApcState;
      if ((BaseAddress > MM_HIGHEST_VAD_ADDRESS) ||
          (PAGE_ALIGN(BaseAddress) == (PVOID)USER_SHARED_DATA))
      {
-         /* FIXME: We should return some bogus info structure */
-         UNIMPLEMENTED;
-         while (TRUE);
+         Address = PAGE_ALIGN(BaseAddress);
+         /* Make up an info structure describing this range */
+         MemoryInfo.BaseAddress = Address;
+         MemoryInfo.AllocationProtect = PAGE_READONLY;
+         MemoryInfo.Type = MEM_PRIVATE;
+         /* Special case for shared data */
+         if (Address == (PVOID)USER_SHARED_DATA)
+         {
+             MemoryInfo.AllocationBase = (PVOID)USER_SHARED_DATA;
+             MemoryInfo.State = MEM_COMMIT;
+             MemoryInfo.Protect = PAGE_READONLY;
+             MemoryInfo.RegionSize = PAGE_SIZE;
+         }
+         else
+         {
+             MemoryInfo.AllocationBase = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1;
+             MemoryInfo.State = MEM_RESERVE;
+             MemoryInfo.Protect = PAGE_NOACCESS;
+             MemoryInfo.RegionSize = (ULONG_PTR)MemoryInfo.AllocationBase - (ULONG_PTR)Address;
+         }
+         /* Return the data (FIXME: Use SEH) */
+         *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
+         if (ReturnLength) *ReturnLength = sizeof(MEMORY_BASIC_INFORMATION);
+         return STATUS_SUCCESS;
      }
  
      /* Check if this is for a local or remote process */
      /* Was a VAD found? */
      if (!Found)
      {
-         /* We don't handle this yet */
-         UNIMPLEMENTED;
-         while (TRUE);
+         Address = PAGE_ALIGN(BaseAddress);
+         /* Calculate region size */
+         if (Vad)
+         {
+             if (Vad->StartingVpn >= BaseVpn)
+             {
+                 /* Region size is the free space till the start of that VAD */
+                 MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
+             }
+             else
+             {
+                 /* Get the next VAD */
+                 Vad = (PMMVAD)MiGetNextNode((PMMADDRESS_NODE)Vad);
+                 if (Vad)
+                 {
+                     /* Region size is the free space till the start of that VAD */
+                     MemoryInfo.RegionSize = (ULONG_PTR)(Vad->StartingVpn << PAGE_SHIFT) - (ULONG_PTR)Address;
+                 }
+                 else
+                 {
+                     /* Maximum possible region size with that base address */
+                     MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
+                 }
+             }
+         }
+         else
+         {
+             /* Maximum possible region size with that base address */
+             MemoryInfo.RegionSize = (PCHAR)MM_HIGHEST_VAD_ADDRESS + 1 - (PCHAR)Address;
+         }
+         /* Check if we were attached */
+         if (ProcessHandle != NtCurrentProcess())
+         {
+             /* Detach and derefernece the process */
+             KeUnstackDetachProcess(&ApcState);
+             ObDereferenceObject(TargetProcess);
+         }
+         /* Build the rest of the initial information block */
+         MemoryInfo.BaseAddress = Address;
+         MemoryInfo.AllocationBase = NULL;
+         MemoryInfo.AllocationProtect = 0;
+         MemoryInfo.State = MEM_FREE;
+         MemoryInfo.Protect = PAGE_NOACCESS;
+         MemoryInfo.Type = 0;
+         /* Return the data (FIXME: Use SEH) */
+         *(PMEMORY_BASIC_INFORMATION)MemoryInformation = MemoryInfo;
+         if (ReturnLength) *ReturnLength = sizeof(MEMORY_BASIC_INFORMATION);
+         return STATUS_SUCCESS;
      }
-    
      /* This must be a VM VAD */
      ASSERT(Vad->u.VadFlags.PrivateMemory);
     
@@@ -68,6 -68,10 +68,10 @@@ DtbgWindowProc(HWND Wnd
      case WM_CLOSE:
          return 0;
  
+     case WM_DISPLAYCHANGE:
+         MoveWindow(Wnd, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE);
+         break;
      case WM_NOTIFY:
      {
          PPRIVATE_NOTIFY_DESKTOP nmh = (PPRIVATE_NOTIFY_DESKTOP)lParam;
index 0654d67,0000000..36f2ceb
mode 100644,000000..100644
--- /dev/null
@@@ -1,191 -1,0 +1,194 @@@
-     dib/dib1bpp.c
 +
 +
 +
 +include_directories(.)
 +include_directories(include)
 +include_directories(${REACTOS_SOURCE_DIR}/ntoskrnl/include)
 +include_directories(${REACTOS_SOURCE_DIR}/lib/3rdparty/freetype/include)
 +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/subsys)
 +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/drivers)
 +
 +add_definitions(-DLANGPACK)
 +add_definitions(-D_WIN32K_)
 +
 +list(APPEND SOURCE
-     ldr/loader.c
++    dib/alphablend.c
++      dib/dib1bpp.c
 +    dib/dib4bpp.c
 +    dib/dib8bpp.c
 +    dib/dib16bpp.c
 +    dib/dib24bpp.c
 +    dib/dib32bpp.c
 +    dib/dib.c
 +    dib/floodfill.c
 +    dib/stretchblt.c
 +    eng/alphablend.c
 +    eng/bitblt.c
 +    eng/engbrush.c
 +    eng/engevent.c
 +    eng/clip.c
 +    eng/copybits.c
 +    eng/debug.c
 +    eng/device.c
 +    eng/driverobj.c
 +    eng/error.c
 +    eng/float.c
 +    eng/gradient.c
 +    eng/lineto.c
++      eng/ldevobj.c
 +    eng/mapping.c
 +    eng/mem.c
 +    eng/engmisc.c
 +    eng/mouse.c
 +    eng/paint.c
++      eng/pdevobj.c
 +    eng/perfcnt.c
++      eng/rlecomp.c
 +    eng/semaphor.c
 +    eng/sort.c
 +    eng/string.c
 +    eng/stretchblt.c
 +    eng/surface.c
 +    eng/transblt.c
 +    eng/engwindow.c
 +    eng/xlate.c
 +    main/dllmain.c
 +    misc/driver.c
 +    misc/err.c
 +    misc/file.c
 +    misc/math.c
 +    misc/rtlstr.c
 +    misc/copy.c
 +    misc/registry.c
 +    misc/usrheap.c
 +    ntddraw/ddraw.c
 +    ntddraw/dd.c
 +    ntddraw/ddsurf.c
 +    ntddraw/d3d.c
 +    ntddraw/dvp.c
 +    ntddraw/mocomp.c
 +    ntddraw/eng.c
 +    ntddraw/dxeng.c
 +    ntuser/accelerator.c
 +    ntuser/callback.c
 +    ntuser/callproc.c
 +    ntuser/caret.c
 +    ntuser/class.c
 +    ntuser/clipboard.c
 +    ntuser/csr.c
 +    ntuser/cursoricon.c
 +    ntuser/defwnd.c
 +    ntuser/desktop.c
 +    ntuser/display.c
 +    ntuser/event.c
 +    ntuser/focus.c
 +    ntuser/guicheck.c
 +    ntuser/hook.c
 +    ntuser/hotkey.c
 +    ntuser/input.c
 +    ntuser/keyboard.c
 +    ntuser/kbdlayout.c
 +    ntuser/menu.c
 +    ntuser/message.c
 +    ntuser/metric.c
 +    ntuser/misc.c
 +    ntuser/monitor.c
 +    ntuser/msgqueue.c
 +    ntuser/ntstubs.c
 +    ntuser/ntuser.c
 +    ntuser/painting.c
 +    ntuser/prop.c
 +    ntuser/scrollbar.c
 +    ntuser/session.c
 +    ntuser/simplecall.c
 +    ntuser/sysparams.c
 +    ntuser/timer.c
 +    ntuser/useratom.c
 +    ntuser/vis.c
 +    ntuser/windc.c
 +    ntuser/window.c
 +    ntuser/winpos.c
 +    ntuser/winsta.c
 +    ntuser/object.c
 +    objects/arc.c
 +    objects/bezier.c
 +    objects/bitblt.c
 +    objects/bitmaps.c
 +    objects/brush.c
 +    objects/cliprgn.c
 +    objects/coord.c
 +    objects/dcattr.c
 +    objects/dclife.c
 +    objects/dcobjs.c
 +    objects/dcstate.c
 +    objects/dcutil.c
 +    objects/device.c
 +    objects/dibobj.c
 +    objects/drawing.c
 +    objects/fillshap.c
 +    objects/font.c
 +    objects/freetype.c
 +    objects/gdibatch.c
 +    objects/gdiobj.c
 +    objects/icm.c
 +    objects/line.c
 +    objects/metafile.c
 +    objects/palette.c
 +    objects/path.c
 +    objects/pen.c
 +    objects/polyfill.c
 +    objects/print.c
 +    objects/rect.c
 +    objects/region.c
 +    objects/stockobj.c
 +    objects/text.c
 +    objects/wingl.c
 +    objects/xformobj.c
 +    stubs/stubs.c
 +    stubs/umpdstubs.c
 +    win32k.rc)
 +
 +list(APPEND GENDIB_GENERATED
 +    ${CMAKE_CURRENT_BINARY_DIR}/dib/dib8gen.c
 +    ${CMAKE_CURRENT_BINARY_DIR}/dib/dib16gen.c
 +    ${CMAKE_CURRENT_BINARY_DIR}/dib/dib32gen.c)
 +
 +set_source_files_properties(${GENDIB_GENERATED} PROPERTIES GENERATED TRUE)
 +
 +list(APPEND SOURCE ${GENDIB_GENERATED})
 +
 +if(ARCH MATCHES i386)
 +list(APPEND SOURCE
 +    dib/i386/dib24bpp_hline.s
 +    dib/i386/dib32bpp_hline.s
 +    dib/i386/dib32bpp_colorfill.s
 +    eng/i386/floatobj.S
 +    misc/i386/cos_asm.s
 +    misc/i386/sin_asm.s
 +    misc/i386/atan2_asm.s
 +    misc/i386/floor_asm.s
 +    misc/i386/ceil_asm.s)
 +else()
 +list(APPEND SOURCE
 +    dib/dib24bppc.c
 +    dib/dib32bppc.c)
 +endif(ARCH MATCHES i386)
 +
 +add_library(win32k SHARED
 +    ${CMAKE_CURRENT_BINARY_DIR}/win32k_pch.h.gch
 +    ${SOURCE})
 +
 +set_target_properties(win32k PROPERTIES LINK_FLAGS "-Wl,-entry,_DriverEntry@8 -Wl,--image-base,0x00010000 -Wl,--subsystem,native" SUFFIX ".sys")
 +
 +target_link_libraries(win32k
 +    ${CMAKE_CURRENT_SOURCE_DIR}/win32k_i386.def
 +    pseh
 +    -lntoskrnl
 +    -lhal
 +    -lftfd
 +    dxguid
 +    libcntpr)
 +
 +add_pch(win32k ${CMAKE_CURRENT_SOURCE_DIR}/pch.h ${SOURCE})
 +add_dependencies(win32k psdk gendib_generated bugcodes subsystem_napi buildno_header)
 +add_livecd_target(win32k reactos/system32)
index 0000000,be269cf..be269cf
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,123 +1,123 @@@
+ /*
+  * PROJECT:         Win32 subsystem
+  * LICENSE:         See COPYING in the top level directory
+  * FILE:            subsystems/win32/win32k/dib/stretchblt.c
+  * PURPOSE:         AlphaBlend implementation suitable for all bit depths
+  * PROGRAMMERS:     Jérôme Gardou
+  */
+ #include <win32k.h>
+ #define NDEBUG
+ #include <debug.h>
+ typedef union
+ {
+   ULONG ul;
+   struct
+   {
+     UCHAR red;
+     UCHAR green;
+     UCHAR blue;
+     UCHAR alpha;
+   } col;
+ } NICEPIXEL32;
+ static __inline UCHAR
+ Clamp8(ULONG val)
+ {
+   return (val > 255) ? 255 : val;
+ }
+ BOOLEAN
+ DIB_XXBPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
+                      RECTL* SourceRect, CLIPOBJ* ClipRegion,
+                      XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
+ {
+   INT DstX, DstY, SrcX, SrcY;
+   BLENDFUNCTION BlendFunc;
+   register NICEPIXEL32 DstPixel32;
+   register NICEPIXEL32 SrcPixel32;
+   UCHAR Alpha, SrcBpp = BitsPerFormat(Source->iBitmapFormat);
+   EXLATEOBJ* pexlo;
+   EXLATEOBJ exloSrcRGB, exloDstRGB, exloRGBSrc;
+   PFN_DIB_PutPixel pfnDibPutPixel = DibFunctionsForBitmapFormat[Dest->iBitmapFormat].DIB_PutPixel;
+   DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
+     SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
+     DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
+   BlendFunc = BlendObj->BlendFunction;
+   if (BlendFunc.BlendOp != AC_SRC_OVER)
+   {
+     DPRINT1("BlendOp != AC_SRC_OVER\n");
+     return FALSE;
+   }
+   if (BlendFunc.BlendFlags != 0)
+   {
+     DPRINT1("BlendFlags != 0\n");
+     return FALSE;
+   }
+   if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
+   {
+     DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
+     return FALSE;
+   }
+   if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
+     SrcBpp != 32)
+   {
+     DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
+     return FALSE;
+   }
+   if (!ColorTranslation)
+   {
+     DPRINT1("ColorTranslation must not be NULL!\n");
+     return FALSE;
+   }
+   pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo);
+   EXLATEOBJ_vInitialize(&exloSrcRGB, pexlo->ppalSrc, &gpalRGB, 0, 0, 0);
+   EXLATEOBJ_vInitialize(&exloDstRGB, pexlo->ppalDst, &gpalRGB, 0, 0, 0);
+   EXLATEOBJ_vInitialize(&exloRGBSrc, &gpalRGB, pexlo->ppalSrc, 0, 0, 0);
+   SrcY = SourceRect->top;
+   DstY = DestRect->top;
+   while ( DstY < DestRect->bottom )
+   {
+     SrcX = SourceRect->left;
+     DstX = DestRect->left;
+     while(DstX < DestRect->right)
+     {
+       SrcPixel32.ul = DIB_GetSource(Source, SrcX, SrcY, &exloSrcRGB.xlo);
+       SrcPixel32.col.red = (SrcPixel32.col.red * BlendFunc.SourceConstantAlpha) / 255;
+       SrcPixel32.col.green = (SrcPixel32.col.green * BlendFunc.SourceConstantAlpha) / 255;
+       SrcPixel32.col.blue = (SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha) / 255;
+       Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
+            (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
+            BlendFunc.SourceConstantAlpha ;
+       DstPixel32.ul = DIB_GetSource(Dest, DstX, DstY, &exloDstRGB.xlo);
+       DstPixel32.col.red = Clamp8((DstPixel32.col.red * (255 - Alpha)) / 255 + SrcPixel32.col.red) ;
+       DstPixel32.col.green = Clamp8((DstPixel32.col.green * (255 - Alpha)) / 255 + SrcPixel32.col.green) ;
+       DstPixel32.col.blue = Clamp8((DstPixel32.col.blue * (255 - Alpha)) / 255 + SrcPixel32.col.blue) ;
+       DstPixel32.ul = XLATEOBJ_iXlate(&exloRGBSrc.xlo, DstPixel32.ul);
+       pfnDibPutPixel(Dest, DstX, DstY, XLATEOBJ_iXlate(ColorTranslation, DstPixel32.ul));
+       DstX++;
+       SrcX = SourceRect->left + ((DstX-DestRect->left)*(SourceRect->right - SourceRect->left))
+                                             /(DestRect->right-DestRect->left);
+     }
+     DstY++;
+     SrcY = SourceRect->top + ((DstY-DestRect->top)*(SourceRect->bottom - SourceRect->top))
+                                             /(DestRect->bottom-DestRect->top);
+   }
+   EXLATEOBJ_vCleanup(&exloDstRGB);
+   EXLATEOBJ_vCleanup(&exloRGBSrc);
+   EXLATEOBJ_vCleanup(&exloSrcRGB);
+   return TRUE;
+ }
@@@ -29,25 -29,25 +29,25 @@@ DIB_FUNCTIONS DibFunctionsForBitmapForm
    {
      DIB_1BPP_PutPixel, DIB_1BPP_GetPixel, DIB_1BPP_HLine, DIB_1BPP_VLine,
      DIB_1BPP_BitBlt, DIB_1BPP_BitBltSrcCopy, DIB_XXBPP_StretchBlt,
-     DIB_1BPP_TransparentBlt, DIB_1BPP_ColorFill, DIB_1BPP_AlphaBlend
+     DIB_1BPP_TransparentBlt, DIB_1BPP_ColorFill, DIB_XXBPP_AlphaBlend
    },
    /* BMF_4BPP */
    {
      DIB_4BPP_PutPixel, DIB_4BPP_GetPixel, DIB_4BPP_HLine, DIB_4BPP_VLine,
      DIB_4BPP_BitBlt, DIB_4BPP_BitBltSrcCopy, DIB_XXBPP_StretchBlt,
-     DIB_4BPP_TransparentBlt, DIB_4BPP_ColorFill, DIB_4BPP_AlphaBlend
+     DIB_4BPP_TransparentBlt, DIB_4BPP_ColorFill, DIB_XXBPP_AlphaBlend
    },
    /* BMF_8BPP */
    {
      DIB_8BPP_PutPixel, DIB_8BPP_GetPixel, DIB_8BPP_HLine, DIB_8BPP_VLine,
      DIB_8BPP_BitBlt, DIB_8BPP_BitBltSrcCopy, DIB_XXBPP_StretchBlt,
-     DIB_8BPP_TransparentBlt, DIB_8BPP_ColorFill, DIB_8BPP_AlphaBlend
+     DIB_8BPP_TransparentBlt, DIB_8BPP_ColorFill, DIB_XXBPP_AlphaBlend
    },
    /* BMF_16BPP */
    {
      DIB_16BPP_PutPixel, DIB_16BPP_GetPixel, DIB_16BPP_HLine, DIB_16BPP_VLine,
      DIB_16BPP_BitBlt, DIB_16BPP_BitBltSrcCopy, DIB_XXBPP_StretchBlt,
-     DIB_16BPP_TransparentBlt, DIB_16BPP_ColorFill, DIB_16BPP_AlphaBlend
+     DIB_16BPP_TransparentBlt, DIB_16BPP_ColorFill, DIB_XXBPP_AlphaBlend
    },
    /* BMF_24BPP */
    {
@@@ -78,7 -78,6 +78,6 @@@ BOOLEAN DIB_1BPP_BitBlt(PBLTINFO)
  BOOLEAN DIB_1BPP_BitBltSrcCopy(PBLTINFO);
  BOOLEAN DIB_1BPP_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,XLATEOBJ*,ULONG);
  BOOLEAN DIB_1BPP_ColorFill(SURFOBJ*, RECTL*, ULONG);
- BOOLEAN DIB_1BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
  
  VOID DIB_4BPP_PutPixel(SURFOBJ*,LONG,LONG,ULONG);
  ULONG DIB_4BPP_GetPixel(SURFOBJ*,LONG,LONG);
@@@ -88,7 -87,6 +87,6 @@@ BOOLEAN DIB_4BPP_BitBlt(PBLTINFO)
  BOOLEAN DIB_4BPP_BitBltSrcCopy(PBLTINFO);
  BOOLEAN DIB_4BPP_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,XLATEOBJ*,ULONG);
  BOOLEAN DIB_4BPP_ColorFill(SURFOBJ*, RECTL*, ULONG);
- BOOLEAN DIB_4BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
  
  VOID DIB_8BPP_PutPixel(SURFOBJ*,LONG,LONG,ULONG);
  ULONG DIB_8BPP_GetPixel(SURFOBJ*,LONG,LONG);
@@@ -98,7 -96,6 +96,6 @@@ BOOLEAN DIB_8BPP_BitBlt(PBLTINFO)
  BOOLEAN DIB_8BPP_BitBltSrcCopy(PBLTINFO);
  BOOLEAN DIB_8BPP_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,XLATEOBJ*,ULONG);
  BOOLEAN DIB_8BPP_ColorFill(SURFOBJ*, RECTL*, ULONG);
- BOOLEAN DIB_8BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
  
  VOID DIB_16BPP_PutPixel(SURFOBJ*,LONG,LONG,ULONG);
  ULONG DIB_16BPP_GetPixel(SURFOBJ*,LONG,LONG);
@@@ -108,7 -105,6 +105,6 @@@ BOOLEAN DIB_16BPP_BitBlt(PBLTINFO)
  BOOLEAN DIB_16BPP_BitBltSrcCopy(PBLTINFO);
  BOOLEAN DIB_16BPP_TransparentBlt(SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,XLATEOBJ*,ULONG);
  BOOLEAN DIB_16BPP_ColorFill(SURFOBJ*, RECTL*, ULONG);
- BOOLEAN DIB_16BPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
  
  VOID DIB_24BPP_PutPixel(SURFOBJ*,LONG,LONG,ULONG);
  ULONG DIB_24BPP_GetPixel(SURFOBJ*,LONG,LONG);
@@@ -132,6 -128,7 +128,7 @@@ BOOLEAN DIB_32BPP_AlphaBlend(SURFOBJ*, 
  
  BOOLEAN DIB_XXBPP_StretchBlt(SURFOBJ*,SURFOBJ*,SURFOBJ*,SURFOBJ*,RECTL*,RECTL*,POINTL*,BRUSHOBJ*,POINTL*,XLATEOBJ*,ROP4);
  BOOLEAN DIB_XXBPP_FloodFillSolid(SURFOBJ*, BRUSHOBJ*, RECTL*, POINTL*, ULONG, UINT);
+ BOOLEAN DIB_XXBPP_AlphaBlend(SURFOBJ*, SURFOBJ*, RECTL*, RECTL*, CLIPOBJ*, XLATEOBJ*, BLENDOBJ*);
  
  extern unsigned char notmask[2];
  extern unsigned char altnotmask[2];
@@@ -525,174 -525,4 +525,4 @@@ DIB_16BPP_TransparentBlt(SURFOBJ *DestS
    return TRUE;
  }
  
- typedef union
- {
-   ULONG ul;
-   struct
-   {
-     UCHAR red;
-     UCHAR green;
-     UCHAR blue;
-     UCHAR alpha;
-   } col;
- } NICEPIXEL32;
- typedef union
- {
-   USHORT us;
-   struct
-   {
-     USHORT  red:5,
-     green:6,
-     blue:5;
-   } col;
- } NICEPIXEL16;
- static __inline UCHAR
- Clamp5(ULONG val)
- {
-   return (val > 31) ? 31 : val;
- }
- static __inline UCHAR
- Clamp8(ULONG val)
- {
-   return (val > 255) ? 255 : val;
- }
- static __inline UCHAR
- Clamp6(ULONG val)
- {
-   return (val > 63) ? 63 : val;
- }
- BOOLEAN
- DIB_16BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
-                      RECTL* SourceRect, CLIPOBJ* ClipRegion,
-                      XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
- {
-   INT Rows, Cols, SrcX, SrcY;
-   register PUSHORT Dst;
-   ULONG DstDelta;
-   BLENDFUNCTION BlendFunc;
-   register NICEPIXEL16 SrcPixel16;
-   register NICEPIXEL16 DstPixel16;
-   register NICEPIXEL32 SrcPixel32;
-   register NICEPIXEL32 DstPixel32;
-   UCHAR Alpha, SrcBpp;
-   EXLATEOBJ *pexlo;
-   EXLATEOBJ exloDst2Src;
-   DPRINT("DIB_16BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
-     SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
-     DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
-   ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
-     DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
-   BlendFunc = BlendObj->BlendFunction;
-   if (BlendFunc.BlendOp != AC_SRC_OVER)
-   {
-     DPRINT1("BlendOp != AC_SRC_OVER\n");
-     return FALSE;
-   }
-   if (BlendFunc.BlendFlags != 0)
-   {
-     DPRINT1("BlendFlags != 0\n");
-     return FALSE;
-   }
-   if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
-   {
-     DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
-     return FALSE;
-   }
-   if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
-     BitsPerFormat(Source->iBitmapFormat) != 32)
-   {
-     DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
-     return FALSE;
-   }
-   if (!ColorTranslation)
-   {
-     DPRINT1("ColorTranslation must not be NULL!\n");
-     return FALSE;
-   }
-   pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo);
-   EXLATEOBJ_vInitialize(&exloDst2Src, pexlo->ppalDst, pexlo->ppalSrc, 0, 0, 0);
-   Dst = (PUSHORT)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
-     (DestRect->left << 1));
-   DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 1);
-   SrcBpp = BitsPerFormat(Source->iBitmapFormat);
-   Rows = DestRect->bottom - DestRect->top;
-   SrcY = SourceRect->top;
-   while (--Rows >= 0)
-   {
-     Cols = DestRect->right - DestRect->left;
-     SrcX = SourceRect->left;
-     while (--Cols >= 0)
-     {
-       if (SrcBpp <= 16)
-       {
-         SrcPixel16.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
-         SrcPixel32.col.red = (SrcPixel16.col.red << 3);
-         SrcPixel32.col.green = (SrcPixel16.col.green << 2);
-         SrcPixel32.col.blue = (SrcPixel16.col.blue << 3);
-         SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha / 255;
-         SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha / 255;
-         SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
-         SrcPixel32.col.alpha = (SrcBpp == 32) ?
-           (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) :
-         BlendFunc.SourceConstantAlpha;
-         Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
-           SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
-         DstPixel16.us = *Dst;
-         DstPixel16.col.red = Clamp5(DstPixel16.col.red * (255 - Alpha) / 255 +
-           (SrcPixel32.col.red >> 3));
-         DstPixel16.col.green = Clamp6(DstPixel16.col.green * (255 - Alpha) / 255 +
-           (SrcPixel32.col.green >> 2));
-         DstPixel16.col.blue = Clamp5(DstPixel16.col.blue * (255 - Alpha) / 255 +
-           (SrcPixel32.col.blue >> 3));
-         *Dst++ = DstPixel16.us;
-       }
-       else
-       {
-         SrcPixel32.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
-         SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha  / 255;
-         SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha  / 255;
-         SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
-         SrcPixel32.col.alpha = (SrcBpp == 32) ?
-           (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) :
-         BlendFunc.SourceConstantAlpha;
-         Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
-           SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
-         DstPixel32.ul = XLATEOBJ_iXlate(&exloDst2Src.xlo, *Dst);
-         SrcPixel32.col.red = Clamp8(DstPixel32.col.red * (255 - Alpha) / 255 + SrcPixel32.col.red);
-         SrcPixel32.col.green = Clamp8(DstPixel32.col.green * (255 - Alpha) / 255 + SrcPixel32.col.green);
-         SrcPixel32.col.blue = Clamp8(DstPixel32.col.blue * (255 - Alpha) / 255 +  SrcPixel32.col.blue);
-         *Dst++ = XLATEOBJ_iXlate(ColorTranslation, SrcPixel32.ul);
-       }
-     }
-     Dst = (PUSHORT)((ULONG_PTR)Dst + DstDelta);
-     SrcY++;
-   }
-   EXLATEOBJ_vCleanup(&exloDst2Src);
-   return TRUE;
- }
  /* EOF */
@@@ -33,7 -33,7 +33,7 @@@ DIB_1BPP_GetPixel(SURFOBJ *SurfObj, LON
  VOID
  DIB_1BPP_HLine(SURFOBJ *SurfObj, LONG x1, LONG x2, LONG y, ULONG c)
  {
-   while(x1 < x2) 
+   while(x1 < x2)
    {
      DIB_1BPP_PutPixel(SurfObj, x1, y, c);
      x1++;
@@@ -43,7 -43,7 +43,7 @@@
  VOID
  DIB_1BPP_VLine(SURFOBJ *SurfObj, LONG x, LONG y1, LONG y2, ULONG c)
  {
-   while(y1 < y2) 
+   while(y1 < y2)
    {
      DIB_1BPP_PutPixel(SurfObj, x, y1, c);
      y1++;
@@@ -474,13 -474,4 +474,4 @@@ DIB_1BPP_TransparentBlt(SURFOBJ *DestSu
    return FALSE;
  }
  
- BOOLEAN
- DIB_1BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
-                     RECTL* SourceRect, CLIPOBJ* ClipRegion,
-                     XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
- {
-   UNIMPLEMENTED;
-   return FALSE;
- }
  /* EOF */
@@@ -37,7 -37,7 +37,7 @@@ DIB_24BPP_VLine(SURFOBJ *SurfObj, LONG 
    LONG lDelta = SurfObj->lDelta;
  
    c &= 0xFFFFFF;
-   while(y1++ < y2) 
+   while(y1++ < y2)
    {
      *(PUSHORT)(addr) = c & 0xFFFF;
      *(addr + 2) = c >> 16;
@@@ -466,7 -466,6 +466,6 @@@ DIB_24BPP_AlphaBlend(SURFOBJ* Dest, SUR
  {
     INT Rows, Cols, SrcX, SrcY;
     register PUCHAR Dst;
-    ULONG DstDelta;
     BLENDFUNCTION BlendFunc;
     register NICEPIXEL32 DstPixel, SrcPixel;
     UCHAR Alpha, SrcBpp;
            SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
            DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
  
-    ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
-           DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
     BlendFunc = BlendObj->BlendFunction;
     if (BlendFunc.BlendOp != AC_SRC_OVER)
     {
  
     Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
                               (DestRect->left * 3));
-    DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) * 3);
     SrcBpp = BitsPerFormat(Source->iBitmapFormat);
  
-    Rows = DestRect->bottom - DestRect->top;
+    Rows = 0;
     SrcY = SourceRect->top;
-    while (--Rows >= 0)
-    {
-       Cols = DestRect->right - DestRect->left;
-       SrcX = SourceRect->left;
-       while (--Cols >= 0)
+    while (++Rows <= DestRect->bottom - DestRect->top)
+   {
+     Cols = 0;
+     SrcX = SourceRect->left;
+     while (++Cols <= DestRect->right - DestRect->left)
+     {
+       SrcPixel.ul = DIB_GetSource(Source, SrcX, SrcY, ColorTranslation);
+       SrcPixel.col.red = (SrcPixel.col.red * BlendFunc.SourceConstantAlpha) / 255;
+       SrcPixel.col.green = (SrcPixel.col.green * BlendFunc.SourceConstantAlpha) / 255;
+       SrcPixel.col.blue = (SrcPixel.col.blue * BlendFunc.SourceConstantAlpha) / 255;
+       if (!(BlendFunc.AlphaFormat & AC_SRC_ALPHA))
        {
-          SrcPixel.ul = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
-          SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
-          SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
-          SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
-          SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
-          Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
-                  SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
-          /* copy only 24bits of dst */
-          DstPixel.ul = *(PUSHORT)(Dst) + (*(Dst+2) << 16);
-          DstPixel.col.red = Clamp8(DstPixel.col.red * (255 - Alpha) / 255 + SrcPixel.col.red);
-          DstPixel.col.green = Clamp8(DstPixel.col.green * (255 - Alpha) / 255 + SrcPixel.col.green);
-          DstPixel.col.blue = Clamp8(DstPixel.col.blue * (255 - Alpha) / 255 + SrcPixel.col.blue);
-          /* copy back 24bits of result */
-          *(PUSHORT)(Dst) = (USHORT)(DstPixel.ul & 0xFFFF);
-          *(Dst + 2) = (UCHAR)((DstPixel.ul >> 16) & 0xFF);
-          Dst = (PUCHAR)((ULONG_PTR)Dst + 3);
+           Alpha = BlendFunc.SourceConstantAlpha ;
        }
-       Dst = (PUCHAR)((ULONG_PTR)Dst + DstDelta);
-       SrcY++;
-    }
+       else
+       {
+         Alpha = (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha) / 255;
+       }
+       DstPixel.col.red = Clamp8((*Dst * (255 - Alpha)) / 255 + SrcPixel.col.red) ;
+       DstPixel.col.green = Clamp8((*(Dst+1) * (255 - Alpha) / 255 + SrcPixel.col.green)) ;
+       DstPixel.col.blue = Clamp8((*(Dst+2) * (255 - Alpha)) / 255 + SrcPixel.col.blue) ;
+       *Dst++ = DstPixel.col.red;
+       *Dst++ = DstPixel.col.green;
+       *Dst++ = DstPixel.col.blue;
+       SrcX = SourceRect->left + (Cols*(SourceRect->right - SourceRect->left))/(DestRect->right - DestRect->left);
+     }
+     Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + ((DestRect->top + Rows) * Dest->lDelta) +
+                 (DestRect->left*3));
+     SrcY = SourceRect->top + (Rows*(SourceRect->bottom - SourceRect->top))/(DestRect->bottom - DestRect->top);
+   }
  
     return TRUE;
  }
@@@ -54,8 -54,8 +54,8 @@@ DIB_32BPP_BitBltSrcCopy(PBLTINFO BltInf
    PBYTE    SourceBits_4BPP, SourceLine_4BPP;
    PDWORD   Source32, Dest32;
  
-   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 
-     + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta) 
+   DestBits = (PBYTE)BltInfo->DestSurface->pvScan0
+     + (BltInfo->DestRect.top * BltInfo->DestSurface->lDelta)
      + 4 * BltInfo->DestRect.left;
  
    switch (BltInfo->SourceSurface->iBitmapFormat)
@@@ -83,8 -83,8 +83,8 @@@
      break;
  
    case BMF_4BPP:
-     SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0 
-       + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) 
+     SourceBits_4BPP = (PBYTE)BltInfo->SourceSurface->pvScan0
+       + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
        + (BltInfo->SourcePoint.x >> 1);
  
      for (j=BltInfo->DestRect.top; j<BltInfo->DestRect.bottom; j++)
      break;
  
    case BMF_24BPP:
-     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0 
-       + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta) 
+     SourceLine = (PBYTE)BltInfo->SourceSurface->pvScan0
+       + (BltInfo->SourcePoint.y * BltInfo->SourceSurface->lDelta)
        + 3 * BltInfo->SourcePoint.x;
      DestLine = DestBits;
  
      break;
  
    case BMF_32BPP:
-     if (NULL == BltInfo->XlateSourceToDest || 
+     if (NULL == BltInfo->XlateSourceToDest ||
        0 != (BltInfo->XlateSourceToDest->flXlate & XO_TRIVIAL))
      {
        if (BltInfo->DestRect.top < BltInfo->SourcePoint.y)
        }
        else
        {
-         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0 
-           + ((BltInfo->SourcePoint.y 
-           + BltInfo->DestRect.bottom 
-           - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta) 
+         SourceBits = (PBYTE)BltInfo->SourceSurface->pvScan0
+           + ((BltInfo->SourcePoint.y
+           + BltInfo->DestRect.bottom
+           - BltInfo->DestRect.top - 1) * BltInfo->SourceSurface->lDelta)
            + 4 * BltInfo->SourcePoint.x;
          DestBits = (PBYTE)BltInfo->DestSurface->pvScan0 + ((BltInfo->DestRect.bottom - 1) * BltInfo->DestSurface->lDelta) + 4 * BltInfo->DestRect.left;
          for (j = BltInfo->DestRect.bottom - 1; BltInfo->DestRect.top <= j; j--)
@@@ -348,7 -348,6 +348,6 @@@ DIB_32BPP_AlphaBlend(SURFOBJ* Dest, SUR
  {
    INT Rows, Cols, SrcX, SrcY;
    register PULONG Dst;
-   ULONG DstDelta;
    BLENDFUNCTION BlendFunc;
    register NICEPIXEL32 DstPixel, SrcPixel;
    UCHAR Alpha, SrcBpp;
      SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
      DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
  
-   ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
-     DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
    BlendFunc = BlendObj->BlendFunction;
    if (BlendFunc.BlendOp != AC_SRC_OVER)
    {
  
    Dst = (PULONG)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
      (DestRect->left << 2));
-   DstDelta = Dest->lDelta - ((DestRect->right - DestRect->left) << 2);
    SrcBpp = BitsPerFormat(Source->iBitmapFormat);
  
-   Rows = DestRect->bottom - DestRect->top;
-   SrcY = SourceRect->top;
-   while (--Rows >= 0)
+   Rows = 0;
+    SrcY = SourceRect->top;
+    while (++Rows <= DestRect->bottom - DestRect->top)
    {
-     Cols = DestRect->right - DestRect->left;
+     Cols = 0;
      SrcX = SourceRect->left;
-     while (--Cols >= 0)
+     while (++Cols <= DestRect->right - DestRect->left)
      {
-       SrcPixel.ul = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
-       SrcPixel.col.red = SrcPixel.col.red * BlendFunc.SourceConstantAlpha / 255;
-       SrcPixel.col.green = SrcPixel.col.green * BlendFunc.SourceConstantAlpha / 255;
-       SrcPixel.col.blue = SrcPixel.col.blue * BlendFunc.SourceConstantAlpha / 255;
-       SrcPixel.col.alpha = (SrcBpp == 32) ? (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
+       SrcPixel.ul = DIB_GetSource(Source, SrcX, SrcY, ColorTranslation);
+       SrcPixel.col.red = (SrcPixel.col.red * BlendFunc.SourceConstantAlpha) / 255;
+       SrcPixel.col.green = (SrcPixel.col.green * BlendFunc.SourceConstantAlpha)  / 255;
+       SrcPixel.col.blue = (SrcPixel.col.blue * BlendFunc.SourceConstantAlpha) / 255;
+       SrcPixel.col.alpha = (32 == SrcBpp) ?
+                         (SrcPixel.col.alpha * BlendFunc.SourceConstantAlpha) / 255 :
+                         BlendFunc.SourceConstantAlpha ;
  
        Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
-         SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha;
+            SrcPixel.col.alpha : BlendFunc.SourceConstantAlpha ;
  
        DstPixel.ul = *Dst;
-       DstPixel.col.red = Clamp8(DstPixel.col.red * (255 - Alpha) / 255 + SrcPixel.col.red);
-       DstPixel.col.green = Clamp8(DstPixel.col.green * (255 - Alpha) / 255 + SrcPixel.col.green);
-       DstPixel.col.blue = Clamp8(DstPixel.col.blue * (255 - Alpha) / 255 + SrcPixel.col.blue);
-       DstPixel.col.alpha = Clamp8(DstPixel.col.alpha * (255 - Alpha) / 255 + SrcPixel.col.alpha);
+       DstPixel.col.red = Clamp8((DstPixel.col.red * (255 - Alpha)) / 255 + SrcPixel.col.red) ;
+       DstPixel.col.green = Clamp8((DstPixel.col.green * (255 - Alpha)) / 255 + SrcPixel.col.green) ;
+       DstPixel.col.blue = Clamp8((DstPixel.col.blue * (255 - Alpha)) / 255 + SrcPixel.col.blue) ;
+       DstPixel.col.alpha = Clamp8((DstPixel.col.alpha * (255 - Alpha)) / 255 + SrcPixel.col.alpha) ;
        *Dst++ = DstPixel.ul;
+       SrcX = SourceRect->left + (Cols*(SourceRect->right - SourceRect->left))/(DestRect->right - DestRect->left);
      }
-     Dst = (PULONG)((ULONG_PTR)Dst + DstDelta);
-     SrcY++;
+     Dst = (PULONG)((ULONG_PTR)Dest->pvScan0 + ((DestRect->top + Rows) * Dest->lDelta) +
+                 (DestRect->left << 2));
+     SrcY = SourceRect->top + (Rows*(SourceRect->bottom - SourceRect->top))/(DestRect->bottom - DestRect->top);
    }
  
    return TRUE;
@@@ -32,7 -32,7 +32,7 @@@ DIB_4BPP_HLine(SURFOBJ *SurfObj, LONG x
    PBYTE  addr = (PBYTE)SurfObj->pvScan0 + (x1>>1) + y * SurfObj->lDelta;
    LONG  cx = x1;
  
-   while(cx < x2) 
+   while(cx < x2)
    {
      *addr = (*addr & notmask[x1&1]) | (c << ((1-(x1&1))<<2));
      if((++x1 & 1) == 0)
@@@ -48,7 -48,7 +48,7 @@@ DIB_4BPP_VLine(SURFOBJ *SurfObj, LONG x
    int  lDelta = SurfObj->lDelta;
  
    addr += (x>>1) + y1 * lDelta;
-   while(y1++ < y2) 
+   while(y1++ < y2)
    {
      *addr = (*addr & notmask[x&1]) | (c << ((1-(x&1))<<2));
      addr += lDelta;
@@@ -81,8 -81,8 +81,8 @@@ DIB_4BPP_BitBltSrcCopy(PBLTINFO BltInfo
            if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
            {
              DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
-           } 
-           else 
+           }
+           else
            {
              DIB_4BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
            }
@@@ -375,13 -375,4 +375,4 @@@ DIB_4BPP_TransparentBlt(SURFOBJ *DestSu
    return FALSE;
  }
  
- BOOLEAN
- DIB_4BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
-                     RECTL* SourceRect, CLIPOBJ* ClipRegion,
-                     XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
- {
-   UNIMPLEMENTED;
-   return FALSE;
- }
  /* EOF */
@@@ -43,7 -43,7 +43,7 @@@ DIB_8BPP_VLine(SURFOBJ *SurfObj, LONG x
    LONG lDelta = SurfObj->lDelta;
  
    byteaddr = addr;
-   while(y1++ < y2) 
+   while(y1++ < y2)
    {
      *addr = c;
  
@@@ -74,8 -74,8 +74,8 @@@ DIB_8BPP_BitBltSrcCopy(PBLTINFO BltInfo
            if(DIB_1BPP_GetPixel(BltInfo->SourceSurface, sx, sy) == 0)
            {
              DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 0));
-           } 
-           else 
+           }
+           else
            {
              DIB_8BPP_PutPixel(BltInfo->DestSurface, i, j, XLATEOBJ_iXlate(BltInfo->XlateSourceToDest, 1));
            }
@@@ -362,130 -362,4 +362,4 @@@ DIB_8BPP_TransparentBlt(SURFOBJ *DestSu
    return TRUE;
  }
  
- typedef union {
-   ULONG ul;
-   struct {
-     UCHAR red;
-     UCHAR green;
-     UCHAR blue;
-     UCHAR alpha;
-   } col;
- } NICEPIXEL32;
- typedef union {
-   USHORT us;
-   struct {
-     USHORT red:5,
-     green:6,
-     blue:5;
-   } col;
- } NICEPIXEL16;
- static __inline UCHAR
- Clamp8(ULONG val)
- {
-   return (val > 255) ? 255 : val;
- }
- BOOLEAN
- DIB_8BPP_AlphaBlend(SURFOBJ* Dest, SURFOBJ* Source, RECTL* DestRect,
-                     RECTL* SourceRect, CLIPOBJ* ClipRegion,
-                     XLATEOBJ* ColorTranslation, BLENDOBJ* BlendObj)
- {
-   INT Rows, Cols, SrcX, SrcY;
-   register PUCHAR Dst;
-   ULONG DstDelta;
-   BLENDFUNCTION BlendFunc;
-   register NICEPIXEL32 DstPixel32;
-   register NICEPIXEL32 SrcPixel32;
-   register NICEPIXEL16 SrcPixel16;
-   UCHAR Alpha, SrcBpp;
-   EXLATEOBJ exloDst2Src;
-   EXLATEOBJ* pexlo;
-   DPRINT("DIB_8BPP_AlphaBlend: srcRect: (%d,%d)-(%d,%d), dstRect: (%d,%d)-(%d,%d)\n",
-     SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom,
-     DestRect->left, DestRect->top, DestRect->right, DestRect->bottom);
-   ASSERT(DestRect->bottom - DestRect->top == SourceRect->bottom - SourceRect->top &&
-     DestRect->right - DestRect->left == SourceRect->right - SourceRect->left);
-   BlendFunc = BlendObj->BlendFunction;
-   if (BlendFunc.BlendOp != AC_SRC_OVER)
-   {
-     DPRINT1("BlendOp != AC_SRC_OVER\n");
-     return FALSE;
-   }
-   if (BlendFunc.BlendFlags != 0)
-   {
-     DPRINT1("BlendFlags != 0\n");
-     return FALSE;
-   }
-   if ((BlendFunc.AlphaFormat & ~AC_SRC_ALPHA) != 0)
-   {
-     DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendFunc.AlphaFormat);
-     return FALSE;
-   }
-   if ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0 &&
-     BitsPerFormat(Source->iBitmapFormat) != 32)
-   {
-     DPRINT1("Source bitmap must be 32bpp when AC_SRC_ALPHA is set\n");
-     return FALSE;
-   }
-   if (!ColorTranslation)
-   {
-     DPRINT1("ColorTranslation must not be NULL!\n");
-     return FALSE;
-   }
-   pexlo = CONTAINING_RECORD(ColorTranslation, EXLATEOBJ, xlo);
-   EXLATEOBJ_vInitialize(&exloDst2Src, pexlo->ppalDst, pexlo->ppalSrc, 0, 0, 0);
-   Dst = (PUCHAR)((ULONG_PTR)Dest->pvScan0 + (DestRect->top * Dest->lDelta) +
-     DestRect->left);
-   DstDelta = Dest->lDelta - (DestRect->right - DestRect->left);
-   SrcBpp = BitsPerFormat(Source->iBitmapFormat);
-   Rows = DestRect->bottom - DestRect->top;
-   SrcY = SourceRect->top;
-   while (--Rows >= 0)
-   {
-     Cols = DestRect->right - DestRect->left;
-     SrcX = SourceRect->left;
-     while (--Cols >= 0)
-     {
-       if (SrcBpp <= 16)
-       {
-         SrcPixel16.us = DIB_GetSource(Source, SrcX++, SrcY, ColorTranslation);
-         SrcPixel32.col.red = (SrcPixel16.col.red << 3) | (SrcPixel16.col.red >> 2);
-         SrcPixel32.col.green = (SrcPixel16.col.green << 2) | (SrcPixel16.col.green >> 4);
-         SrcPixel32.col.blue = (SrcPixel16.col.blue << 3) | (SrcPixel16.col.blue >> 2);
-       }
-       else
-       {
-         SrcPixel32.ul = DIB_GetSourceIndex(Source, SrcX++, SrcY);
-       }
-       SrcPixel32.col.red = SrcPixel32.col.red * BlendFunc.SourceConstantAlpha / 255;
-       SrcPixel32.col.green = SrcPixel32.col.green * BlendFunc.SourceConstantAlpha / 255;
-       SrcPixel32.col.blue = SrcPixel32.col.blue * BlendFunc.SourceConstantAlpha / 255;
-       SrcPixel32.col.alpha = (SrcBpp == 32) ? (SrcPixel32.col.alpha * BlendFunc.SourceConstantAlpha / 255) : BlendFunc.SourceConstantAlpha;
-       Alpha = ((BlendFunc.AlphaFormat & AC_SRC_ALPHA) != 0) ?
-         SrcPixel32.col.alpha : BlendFunc.SourceConstantAlpha;
-       DstPixel32.ul = XLATEOBJ_iXlate(&exloDst2Src.xlo, *Dst);
-       SrcPixel32.col.red = Clamp8(DstPixel32.col.red * (255 - Alpha) / 255 + SrcPixel32.col.red);
-       SrcPixel32.col.green = Clamp8(DstPixel32.col.green * (255 - Alpha) / 255 + SrcPixel32.col.green);
-       SrcPixel32.col.blue = Clamp8(DstPixel32.col.blue * (255 - Alpha) / 255 +  SrcPixel32.col.blue);
-       *Dst++ = XLATEOBJ_iXlate(ColorTranslation, SrcPixel32.ul);
-     }
-     Dst = (PUCHAR)((ULONG_PTR)Dst + DstDelta);
-     SrcY++;
-   }
-   EXLATEOBJ_vCleanup(&exloDst2Src);
-   return TRUE;
- }
  /* EOF */
@@@ -1,4 -1,4 +1,4 @@@
- /* 
+ /*
   * COPYRIGHT:        See COPYING in the top level directory
   * PROJECT:          ReactOS kernel
   * PURPOSE:          GDI alpha blending functions
@@@ -25,10 -25,6 +25,6 @@@ EngAlphaBlend(IN SURFOBJ *psoDest
                IN PRECTL SourceRect,
                IN BLENDOBJ *BlendObj)
  {
-     RECTL              SourceStretchedRect;
-     SIZEL              SourceStretchedSize;
-     HBITMAP            SourceStretchedBitmap = 0;
-     SURFOBJ*           SourceStretchedObj = NULL;
      RECTL              InputRect;
      RECTL              OutputRect;
      RECTL              ClipRect;
@@@ -39,7 -35,6 +35,6 @@@
      INTENG_ENTER_LEAVE EnterLeaveDest;
      SURFOBJ*           InputObj;
      SURFOBJ*           OutputObj;
-     LONG               Width;
      LONG               ClippingType;
      RECT_ENUM          RectEnum;
      BOOL               EnumMore;
@@@ -71,7 -66,7 +66,7 @@@
      InputRect = *SourceRect;
      if ( (InputRect.top < 0) || (InputRect.bottom < 0) ||
           (InputRect.left < 0) || (InputRect.right < 0) ||
-          InputRect.right > psoSource->sizlBitmap.cx || 
+          InputRect.right > psoSource->sizlBitmap.cx ||
           InputRect.bottom > psoSource->sizlBitmap.cy )
      {
          SetLastWin32Error(ERROR_INVALID_PARAMETER);
          return TRUE;
      }
  
-     /* Stretch source if needed */
-     if (OutputRect.right - OutputRect.left != InputRect.right - InputRect.left ||
-             OutputRect.bottom - OutputRect.top != InputRect.bottom - InputRect.top)
-     {
-         SourceStretchedSize.cx = OutputRect.right - OutputRect.left;
-         SourceStretchedSize.cy = OutputRect.bottom - OutputRect.top;
-         Width = DIB_GetDIBWidthBytes(SourceStretchedSize.cx, BitsPerFormat(psoSource->iBitmapFormat));
-         /* FIXME: Maybe it is a good idea to use EngCreateDeviceBitmap and IntEngStretchBlt
-                   if possible to get a HW accelerated stretch. */
-         SourceStretchedBitmap = EngCreateBitmap(SourceStretchedSize, Width, psoSource->iBitmapFormat,
-                                                 BMF_TOPDOWN | BMF_NOZEROINIT, NULL);
-         if (SourceStretchedBitmap == 0)
-         {
-             DPRINT1("EngCreateBitmap failed!\n");
-             return FALSE;
-         }
-         SourceStretchedObj = EngLockSurface((HSURF)SourceStretchedBitmap);
-         if (SourceStretchedObj == NULL)
-         {
-             DPRINT1("EngLockSurface failed!\n");
-             EngDeleteSurface((HSURF)SourceStretchedBitmap);
-             return FALSE;
-         }
-         SourceStretchedRect.left = 0;
-         SourceStretchedRect.right = SourceStretchedSize.cx;
-         SourceStretchedRect.top = 0;
-         SourceStretchedRect.bottom = SourceStretchedSize.cy;
-         /* FIXME: IntEngStretchBlt isn't used here atm because it results in a
-                   try to acquire an already acquired mutex (lock the already locked source surface) */
-         /*if (!IntEngStretchBlt(SourceStretchedObj, psoSource, NULL, NULL,
-                               NULL, &SourceStretchedRect, SourceRect, NULL,
-                               NULL, NULL, COLORONCOLOR))*/
-         if (!EngStretchBlt(SourceStretchedObj, psoSource, NULL, NULL, NULL,
-                            NULL, NULL, &SourceStretchedRect, &InputRect,
-                            NULL, COLORONCOLOR))
-         {
-             DPRINT1("EngStretchBlt failed!\n");
-             EngFreeMem(SourceStretchedObj->pvBits);
-             EngUnlockSurface(SourceStretchedObj);
-             EngDeleteSurface((HSURF)SourceStretchedBitmap);
-             return FALSE;
-         }
-         InputRect.top = SourceStretchedRect.top;
-         InputRect.bottom = SourceStretchedRect.bottom;
-         InputRect.left = SourceStretchedRect.left;
-         InputRect.right = SourceStretchedRect.right;
-         psoSource = SourceStretchedObj;
-     }
      /* Now call the DIB function */
      if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj))
      {
-         if (SourceStretchedObj != NULL)
-         {
-             EngFreeMem(SourceStretchedObj->pvBits);
-             EngUnlockSurface(SourceStretchedObj);
-         }
-         if (SourceStretchedBitmap != 0)
-         {
-             EngDeleteSurface((HSURF)SourceStretchedBitmap);
-         }
          return FALSE;
      }
      InputRect.left +=  Translate.x;
  
      if (!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj))
      {
-         IntEngLeave(&EnterLeaveSource);
-         if (SourceStretchedObj != NULL)
-         {
-             EngFreeMem(SourceStretchedObj->pvBits);
-             EngUnlockSurface(SourceStretchedObj);
-         }
-         if (SourceStretchedBitmap != 0)
-         {
-             EngDeleteSurface((HSURF)SourceStretchedBitmap);
-         }
          return FALSE;
      }
      OutputRect.left += Translate.x;
      IntEngLeave(&EnterLeaveDest);
      IntEngLeave(&EnterLeaveSource);
  
-     if (SourceStretchedObj != NULL)
-     {
-         EngFreeMem(SourceStretchedObj->pvBits);
-         EngUnlockSurface(SourceStretchedObj);
-     }
-     if (SourceStretchedBitmap != 0)
-     {
-         EngDeleteSurface((HSURF)SourceStretchedBitmap);
-     }
      return Ret;
  }
  
@@@ -305,17 -221,8 +221,8 @@@ IntEngAlphaBlend(IN SURFOBJ *psoDest
          return TRUE;
      }
  
-     SURFACE_LockBitmapBits(psurfDest);
-     MouseSafetyOnDrawStart(psoDest, DestRect->left, DestRect->top,
-                            DestRect->right, DestRect->bottom);
-     if (psoSource != psoDest)
-         SURFACE_LockBitmapBits(psurfSource);
-     MouseSafetyOnDrawStart(psoSource, SourceRect->left, SourceRect->top,
-                            SourceRect->right, SourceRect->bottom);
      /* Call the driver's DrvAlphaBlend if available */
-     if (psurfDest->flHooks & HOOK_ALPHABLEND)
+     if (psurfDest->flags & HOOK_ALPHABLEND)
      {
          ret = GDIDEVFUNCS(psoDest).AlphaBlend(
                    psoDest, psoSource, ClipRegion, ColorTranslation,
                              DestRect, SourceRect, BlendObj);
      }
  
-     MouseSafetyOnDrawEnd(psoSource);
-     if (psoSource != psoDest)
-         SURFACE_UnlockBitmapBits(psurfSource);
-     MouseSafetyOnDrawEnd(psoDest);
-     SURFACE_UnlockBitmapBits(psurfDest);
      return ret;
  }
  
@@@ -522,7 -522,7 +522,7 @@@ EngBitBlt(SURFOBJ *DestObj
  }
  
  BOOL APIENTRY
- IntEngBitBltEx(
+ IntEngBitBlt(
      SURFOBJ *psoTrg,
      SURFOBJ *psoSrc,
      SURFOBJ *psoMask,
      POINTL *pptlMask,
      BRUSHOBJ *pbo,
      POINTL *pptlBrush,
-     ROP4 rop4,
-     BOOL bRemoveMouse)
+     ROP4 rop4)
  {
      SURFACE *psurfTrg;
      SURFACE *psurfSrc = NULL;
          psurfSrc = NULL;
      }
  
-     if (bRemoveMouse)
-     {
-         SURFACE_LockBitmapBits(psurfTrg);
-         if (psoSrc)
-         {
-             if (psoSrc != psoTrg)
-             {
-                 SURFACE_LockBitmapBits(psurfSrc);
-             }
-             MouseSafetyOnDrawStart(psoSrc, rclSrc.left, rclSrc.top,
-                                    rclSrc.right, rclSrc.bottom);
-         }
-         MouseSafetyOnDrawStart(psoTrg, rclClipped.left, rclClipped.top,
-                                rclClipped.right, rclClipped.bottom);
-     }
      /* Is the target surface device managed? */
-     if (psurfTrg->flHooks & HOOK_BITBLT)
+     if (psurfTrg->flags & HOOK_BITBLT)
      {
          /* Is the source a different device managed surface? */
-         if (psoSrc && psoSrc->hdev != psoTrg->hdev && psurfSrc->flHooks & HOOK_BITBLT)
+         if (psoSrc && psoSrc->hdev != psoTrg->hdev && psurfSrc->flags & HOOK_BITBLT)
          {
              DPRINT1("Need to copy to standard bitmap format!\n");
              ASSERT(FALSE);
      }
  
      /* Is the source surface device managed? */
-     else if (psoSrc && psurfSrc->flHooks & HOOK_BITBLT)
+     else if (psoSrc && psurfSrc->flags & HOOK_BITBLT)
      {
          pfnBitBlt = GDIDEVFUNCS(psoSrc).BitBlt;
      }
  
      // FIXME: cleanup temp surface!
  
-     if (bRemoveMouse)
-     {
-         MouseSafetyOnDrawEnd(psoTrg);
-         if (psoSrc)
-         {
-             MouseSafetyOnDrawEnd(psoSrc);
-             if (psoSrc != psoTrg)
-             {
-                 SURFACE_UnlockBitmapBits(psurfSrc);
-             }
-         }
-         SURFACE_UnlockBitmapBits(psurfTrg);
-     }
      return bResult;
  }
  
@@@ -983,27 -950,20 +950,20 @@@ IntEngMaskBlt(SURFOBJ *psoDest
      ASSERT(psoDest);
      psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
  
-     SURFACE_LockBitmapBits(psurfDest);
-     MouseSafetyOnDrawStart(psoDest, OutputRect.left, OutputRect.top,
-                            OutputRect.right, OutputRect.bottom);
      /* Dummy BitBlt to let driver know that it should flush its changes.
         This should really be done using a call to DrvSynchronizeSurface,
         but the VMware driver doesn't hook that call. */
-     IntEngBitBltEx(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation,
+     IntEngBitBlt(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation,
                     DestRect, pptlMask, pptlMask, pbo, BrushOrigin,
-                    R4_NOOP, FALSE);
+                    R4_NOOP);
  
      ret = EngMaskBitBlt(psoDest, psoMask, ClipRegion, DestColorTranslation, SourceColorTranslation,
                          &OutputRect, &InputPoint, pbo, BrushOrigin);
  
      /* Dummy BitBlt to let driver know that something has changed. */
-     IntEngBitBltEx(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation,
+     IntEngBitBlt(psoDest, NULL, psoMask, ClipRegion, DestColorTranslation,
                     DestRect, pptlMask, pptlMask, pbo, BrushOrigin,
-                    R4_NOOP, FALSE);
-     MouseSafetyOnDrawEnd(psoDest);
-     SURFACE_UnlockBitmapBits(psurfDest);
+                    R4_NOOP);
  
      return ret;
  }
@@@ -53,13 -53,7 +53,7 @@@ EngCopyBits(SURFOBJ *psoDest
      ASSERT(psoDest != NULL && psoSource != NULL && DestRect != NULL && SourcePoint != NULL);
  
      psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
-     SURFACE_LockBitmapBits(psurfSource);
      psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
-     if (psoDest != psoSource)
-     {
-         SURFACE_LockBitmapBits(psurfDest);
-     }
  
      // FIXME: Don't punt to the driver's DrvCopyBits immediately. Instead,
      //        mark the copy block function to be DrvCopyBits instead of the
@@@ -73,7 -67,7 +67,7 @@@
          if (psoDest->iType!=STYPE_BITMAP)
          {
              /* FIXME: Eng* functions shouldn't call Drv* functions. ? */
-             if (psurfDest->flHooks & HOOK_COPYBITS)
+             if (psurfDest->flags & HOOK_COPYBITS)
              {
                  ret = GDIDEVFUNCS(psoDest).CopyBits(
                            psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);
@@@ -86,7 -80,7 +80,7 @@@
          if (psoSource->iType!=STYPE_BITMAP)
          {
              /* FIXME: Eng* functions shouldn't call Drv* functions. ? */
-             if (psurfSource->flHooks & HOOK_COPYBITS)
+             if (psurfSource->flags & HOOK_COPYBITS)
              {
                  ret = GDIDEVFUNCS(psoSource).CopyBits(
                            psoDest, psoSource, Clip, ColorTranslation, DestRect, SourcePoint);
      }
  
  cleanup:
-     if (psoDest != psoSource)
-     {
-         SURFACE_UnlockBitmapBits(psurfDest);
-     }
-     SURFACE_UnlockBitmapBits(psurfSource);
      return ret;
  }
  
@@@ -198,20 -186,7 +186,7 @@@ IntEngCopyBits
      RECTL *prclDest,
      POINTL *ptlSource)
  {
-     BOOL bResult;
-     MouseSafetyOnDrawStart(psoSource, ptlSource->x, ptlSource->y,
-                            (ptlSource->x + abs(prclDest->right - prclDest->left)),
-                            (ptlSource->y + abs(prclDest->bottom - prclDest->top)));
-     MouseSafetyOnDrawStart(psoDest, prclDest->left, prclDest->top, prclDest->right, prclDest->bottom);
-     bResult = EngCopyBits(psoDest, psoSource, pco, pxlo, prclDest, ptlSource);
-     MouseSafetyOnDrawEnd(psoDest);
-     MouseSafetyOnDrawEnd(psoSource);
-     return bResult;
+     return EngCopyBits(psoDest, psoSource, pco, pxlo, prclDest, ptlSource);
  }
  
  
  #define NDEBUG
  #include <debug.h>
  
+ PGRAPHICS_DEVICE gpPrimaryGraphicsDevice;
+ PGRAPHICS_DEVICE gpVgaGraphicsDevice;
+ static PGRAPHICS_DEVICE gpGraphicsDeviceFirst = NULL;
+ static PGRAPHICS_DEVICE gpGraphicsDeviceLast = NULL;
+ static HSEMAPHORE ghsemGraphicsDeviceList;
+ static ULONG giDevNum = 1;
+ BOOL
+ NTAPI
+ InitDeviceImpl()
+ {
+     ghsemGraphicsDeviceList = EngCreateSemaphore();
+     if (!ghsemGraphicsDeviceList)
+         return FALSE;
+     return TRUE;
+ }
+ PGRAPHICS_DEVICE
+ NTAPI
+ EngpRegisterGraphicsDevice(
+     PUNICODE_STRING pustrDeviceName,
+     PUNICODE_STRING pustrDiplayDrivers,
+     PUNICODE_STRING pustrDescription,
+     PDEVMODEW pdmDefault)
+ {
+     PGRAPHICS_DEVICE pGraphicsDevice;
+     PDEVICE_OBJECT pDeviceObject;
+     PFILE_OBJECT pFileObject;
+     NTSTATUS Status;
+     PWSTR pwsz;
+     ULONG i, cj, cModes = 0;
+     BOOL bEnable = TRUE;
+     PDEVMODEINFO pdminfo;
+     PDEVMODEW pdm, pdmEnd;
+     PLDEVOBJ pldev;
+     DPRINT1("EngpRegisterGraphicsDevice(%S)\n", pustrDeviceName->Buffer);
+     /* Allocate a GRAPHICS_DEVICE structure */
+     pGraphicsDevice = ExAllocatePoolWithTag(PagedPool,
+                                             sizeof(GRAPHICS_DEVICE),
+                                             GDITAG_GDEVICE);
+     if (!pGraphicsDevice)
+     {
+         DPRINT1("ExAllocatePoolWithTag failed\n");
+         return NULL;
+     }
+     /* Try to open the driver */
+     Status = IoGetDeviceObjectPointer(pustrDeviceName,
+                                       FILE_READ_DATA | FILE_WRITE_DATA,
+                                       &pFileObject,
+                                       &pDeviceObject);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Could not open driver, 0x%lx\n", Status);
+         ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE);
+         return NULL;
+     }
+     /* Enable the device */
+     EngFileWrite(pFileObject, &bEnable, sizeof(BOOL), &cj);
+     /* Copy the device and file object pointers */
+     pGraphicsDevice->DeviceObject = pDeviceObject;
+     pGraphicsDevice->FileObject = pFileObject;
+     /* Copy device name */
+     wcsncpy(pGraphicsDevice->szNtDeviceName,
+             pustrDeviceName->Buffer,
+             sizeof(pGraphicsDevice->szNtDeviceName) / sizeof(WCHAR));
+     /* Create a win device name (FIXME: virtual devices!) */
+     swprintf(pGraphicsDevice->szWinDeviceName, L"\\\\.\\VIDEO%d", (CHAR)giDevNum);
+     /* Allocate a buffer for the strings */
+     cj = pustrDiplayDrivers->Length + pustrDescription->Length + sizeof(WCHAR);
+     pwsz = ExAllocatePoolWithTag(PagedPool, cj, GDITAG_DRVSUP);
+     if (!pwsz)
+     {
+         DPRINT1("Could not allocate string buffer\n");
+         ASSERT(FALSE); // FIXME
+     }
+     /* Copy display driver names */
+     pGraphicsDevice->pDiplayDrivers = pwsz;
+     RtlCopyMemory(pGraphicsDevice->pDiplayDrivers,
+                   pustrDiplayDrivers->Buffer,
+                   pustrDiplayDrivers->Length);
+     /* Copy description */
+     pGraphicsDevice->pwszDescription = pwsz + pustrDiplayDrivers->Length / sizeof(WCHAR);
+     RtlCopyMemory(pGraphicsDevice->pwszDescription,
+                   pustrDescription->Buffer,
+                   pustrDescription->Length + sizeof(WCHAR));
+     /* Initialize the pdevmodeInfo list and default index  */
+     pGraphicsDevice->pdevmodeInfo = NULL;
+     pGraphicsDevice->iDefaultMode = 0;
+     pGraphicsDevice->iCurrentMode = 0;
+     // FIXME: initialize state flags
+     pGraphicsDevice->StateFlags = 0;
+     /* Loop through the driver names
+      * This is a REG_MULTI_SZ string */
+     for (; *pwsz; pwsz += wcslen(pwsz) + 1)
+     {
+         DPRINT1("trying driver: %ls\n", pwsz);
+         /* Try to load the display driver */
+         pldev = EngLoadImageEx(pwsz, LDEV_DEVICE_DISPLAY);
+         if (!pldev)
+         {
+             DPRINT1("Could not load driver: '%ls'\n", pwsz);
+             continue;
+         }
+         /* Get the mode list from the driver */
+         pdminfo = LDEVOBJ_pdmiGetModes(pldev, pDeviceObject);
+         if (!pdminfo)
+         {
+             DPRINT1("Could not get mode list for '%ls'\n", pwsz);
+             continue;
+         }
+         /* Attach the mode info to the device */
+         pdminfo->pdmiNext = pGraphicsDevice->pdevmodeInfo;
+         pGraphicsDevice->pdevmodeInfo = pdminfo;
+         /* Count DEVMODEs */
+         pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode);
+         for (pdm = pdminfo->adevmode;
+              pdm + 1 <= pdmEnd;
+              pdm = (DEVMODEW*)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra))
+         {
+             cModes++;
+         }
+         // FIXME: release the driver again until it's used?
+     }
+     if (!pGraphicsDevice->pdevmodeInfo || cModes == 0)
+     {
+         DPRINT1("No devmodes\n");
+         ExFreePool(pGraphicsDevice);
+         return NULL;
+     }
+     /* Allocate an index buffer */
+     pGraphicsDevice->cDevModes = cModes;
+     pGraphicsDevice->pDevModeList = ExAllocatePoolWithTag(PagedPool,
+                                                           cModes * sizeof(DEVMODEENTRY),
+                                                           GDITAG_GDEVICE);
+     if (!pGraphicsDevice->pDevModeList)
+     {
+         DPRINT1("No devmode list\n");
+         ExFreePool(pGraphicsDevice);
+         return NULL;
+     }
+     /* Loop through all DEVMODEINFOs */
+     for (pdminfo = pGraphicsDevice->pdevmodeInfo, i = 0;
+          pdminfo;
+          pdminfo = pdminfo->pdmiNext)
+     {
+         /* Calculate End of the DEVMODEs */
+         pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode);
+         /* Loop through the DEVMODEs */
+         for (pdm = pdminfo->adevmode;
+              pdm + 1 <= pdmEnd;
+              pdm = (PDEVMODEW)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra))
+         {
+             /* Compare with the default entry */
+             if (pdm->dmBitsPerPel == pdmDefault->dmBitsPerPel &&
+                 pdm->dmPelsWidth == pdmDefault->dmPelsWidth &&
+                 pdm->dmPelsHeight == pdmDefault->dmPelsHeight &&
+                 pdm->dmDisplayFrequency == pdmDefault->dmDisplayFrequency)
+             {
+                 pGraphicsDevice->iDefaultMode = i;
+                 pGraphicsDevice->iCurrentMode = i;
+                 DPRINT1("Found default entry: %ld '%ls'\n", i, pdm->dmDeviceName);
+             }
+             /* Initialize the entry */
+             pGraphicsDevice->pDevModeList[i].dwFlags = 0;
+             pGraphicsDevice->pDevModeList[i].pdm = pdm;
+             i++;
+         }
+      }
+     /* Lock loader */
+     EngAcquireSemaphore(ghsemGraphicsDeviceList);
+     /* Insert the device into the global list */
+     pGraphicsDevice->pNextGraphicsDevice = gpGraphicsDeviceLast;
+     gpGraphicsDeviceLast = pGraphicsDevice;
+     if (!gpGraphicsDeviceFirst)
+         gpGraphicsDeviceFirst = pGraphicsDevice;
+     /* Increment device number */
+     giDevNum++;
+     /* Unlock loader */
+     EngReleaseSemaphore(ghsemGraphicsDeviceList);
+     DPRINT1("Prepared %ld modes for %ls\n", cModes, pGraphicsDevice->pwszDescription);
+     return pGraphicsDevice;
+ }
+ PGRAPHICS_DEVICE
+ NTAPI
+ EngpFindGraphicsDevice(
+     PUNICODE_STRING pustrDevice,
+     ULONG iDevNum,
+     DWORD dwFlags)
+ {
+     UNICODE_STRING ustrCurrent;
+     PGRAPHICS_DEVICE pGraphicsDevice;
+     ULONG i;
+     /* Lock list */
+     EngAcquireSemaphore(ghsemGraphicsDeviceList);
+     if (pustrDevice)
+     {
+         /* Loop through the list of devices */
+         for (pGraphicsDevice = gpGraphicsDeviceFirst;
+              pGraphicsDevice;
+              pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice)
+         {
+             /* Compare the device name */
+             RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName);
+             if (RtlEqualUnicodeString(&ustrCurrent, pustrDevice, FALSE))
+             {
+                 break;
+             }
+         }
+     }
+     else
+     {
+         /* Loop through the list of devices */
+         for (pGraphicsDevice = gpGraphicsDeviceFirst, i = 0;
+              pGraphicsDevice && i < iDevNum;
+              pGraphicsDevice = pGraphicsDevice->pNextGraphicsDevice, i++);
+     }
+     /* Unlock list */
+     EngReleaseSemaphore(ghsemGraphicsDeviceList);
+     return pGraphicsDevice;
+ }
  static
  NTSTATUS
  EngpFileIoRequest(
      /* Initialize an event */
      KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
  
-     /* Build IPR */
+     /* Build IRP */
      liStartOffset.QuadPart = ullStartOffset;
      pIrp = IoBuildSynchronousFsdRequest(ulMajorFunction,
                                          pDeviceObject,
@@@ -113,7 -371,7 +371,7 @@@ EngFileIoControl
      /* Initialize an event */
      KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
  
-     /* Build IO control IPR */
+     /* Build IO control IRP */
      pIrp = IoBuildDeviceIoControlRequest(dwIoControlCode,
                                           pDeviceObject,
                                           lpInBuffer,
@@@ -18,8 -18,6 +18,6 @@@ VOI
  NTAPI
  EBRUSHOBJ_vInit(EBRUSHOBJ *pebo, PBRUSH pbrush, PDC pdc)
  {
-     HPALETTE hpal = NULL;
      ASSERT(pebo);
      ASSERT(pbrush);
      ASSERT(pdc);
      pebo->crCurrentText = pdc->pdcattr->crForegroundClr;
  
      pebo->psurfTrg = pdc->dclevel.pSurface;
- //    ASSERT(pebo->psurfTrg); // FIXME: some dcs don't have a surface
+     ASSERT(pebo->psurfTrg);
+     ASSERT(pebo->psurfTrg->ppal);
  
-     if (pebo->psurfTrg)
-         hpal = pebo->psurfTrg->hDIBPalette;
-     if (!hpal) hpal = pPrimarySurface->devinfo.hpalDefault;
-     pebo->ppalSurf = PALETTE_ShareLockPalette(hpal);
-     if (!pebo->ppalSurf)
-         pebo->ppalSurf = &gpalRGB;
+     pebo->ppalSurf = pebo->psurfTrg->ppal;
+     GDIOBJ_IncrementShareCount(&pebo->ppalSurf->BaseObject);
  
      if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
      {
@@@ -80,7 -75,12 +75,12 @@@ EBRUSHOBJ_vSetSolidBrushColor(EBRUSHOB
      pebo->ulRGBColor = crColor;
  
      /* Initialize an XLATEOBJ RGB -> surface */
-     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, pebo->ppalSurf, 0, 0, 0);
+     EXLATEOBJ_vInitialize(&exlo,
+                           &gpalRGB,
+                           pebo->ppalSurf,
+                           pebo->crCurrentBack,
+                           0,
+                           0);
  
      /* Translate the brush color to the target format */
      iSolidColor = XLATEOBJ_iXlate(&exlo.xlo, crColor);
@@@ -109,8 -109,7 +109,7 @@@ EBRUSHOBJ_vCleanup(EBRUSHOBJ *pebo
          pebo->BrushObject.pvRbrush = NULL;
      }
  
-     if (pebo->ppalSurf != &gpalRGB)
-         PALETTE_ShareUnlockPalette(pebo->ppalSurf);
+     PALETTE_ShareUnlockPalette(pebo->ppalSurf);
  }
  
  VOID
@@@ -145,7 -144,7 +144,7 @@@ EngRealizeBrush
      ULONG lWidth;
  
      /* Calculate width in bytes of the realized brush */
-     lWidth = DIB_GetDIBWidthBytes(psoPattern->sizlBitmap.cx,
+     lWidth = WIDTH_BYTES_ALIGN32(psoPattern->sizlBitmap.cx,
                                    BitsPerFormat(psoDst->iBitmapFormat));
  
      /* Allocate a bitmap */
@@@ -192,12 -191,8 +191,8 @@@ EBRUSHOBJ_bRealizeBrush(EBRUSHOBJ *pebo
      PPDEVOBJ ppdev = NULL;
      EXLATEOBJ exlo;
  
-     // FIXME: all EBRUSHOBJs need a surface, see EBRUSHOBJ_vInit
-     if (!pebo->psurfTrg)
-     {
-         DPRINT1("Pattern brush has no target surface!\n");
-         return FALSE;
-     }
+     /* All EBRUSHOBJs have a surface, see EBRUSHOBJ_vInit */
+     ASSERT(pebo->psurfTrg);
  
      ppdev = (PPDEVOBJ)pebo->psurfTrg->SurfObj.hdev;
  
  
      psurfPattern = SURFACE_ShareLockSurface(pebo->pbrush->hbmPattern);
      ASSERT(psurfPattern);
+     ASSERT(psurfPattern->ppal);
  
      /* FIXME: implement mask */
      psurfMask = NULL;
  
      /* Initialize XLATEOBJ for the brush */
-     EXLATEOBJ_vInitBrushXlate(&exlo,
-                               pebo->pbrush,
-                               pebo->psurfTrg,
-                               pebo->crCurrentText,
-                               pebo->crCurrentBack);
+     EXLATEOBJ_vInitialize(&exlo, 
+                           psurfPattern->ppal,
+                           pebo->psurfTrg->ppal,
+                           0,
+                           pebo->crCurrentBack,
+                           pebo->crCurrentText);
  
      /* Create the realization */
      bResult = pfnRealzizeBrush(&pebo->BrushObject,
@@@ -56,7 -56,7 +56,7 @@@ IntEngEnter(PINTENG_ENTER_LEAVE EnterLe
      {
      /* Driver needs to support DrvCopyBits, else we can't do anything */
      SURFACE *psurfDest = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
-     if (!(psurfDest->flHooks & HOOK_COPYBITS))
+     if (!(psurfDest->flags & HOOK_COPYBITS))
      {
        return FALSE;
      }
@@@ -64,7 -64,7 +64,7 @@@
      /* Allocate a temporary bitmap */
      BitmapSize.cx = DestRect->right - DestRect->left;
      BitmapSize.cy = DestRect->bottom - DestRect->top;
-     Width = DIB_GetDIBWidthBytes(BitmapSize.cx, BitsPerFormat(psoDest->iBitmapFormat));
+     Width = WIDTH_BYTES_ALIGN32(BitmapSize.cx, BitsPerFormat(psoDest->iBitmapFormat));
      EnterLeave->OutputBitmap = EngCreateBitmap(BitmapSize, Width,
                                                 psoDest->iBitmapFormat,
                                                 BMF_TOPDOWN | BMF_NOZEROINIT, NULL);
                                          &ClippedDestRect, &SrcPoint))
        {
            EngDeleteClip(EnterLeave->TrivialClipObj);
-           EngFreeMem((*ppsoOutput)->pvBits);
            EngUnlockSurface(*ppsoOutput);
            EngDeleteSurface((HSURF)EnterLeave->OutputBitmap);
            return FALSE;
    if (NULL != *ppsoOutput)
    {
      SURFACE* psurfOutput = CONTAINING_RECORD(*ppsoOutput, SURFACE, SurfObj);
-     if (0 != (psurfOutput->flHooks & HOOK_SYNCHRONIZE))
+     if (0 != (psurfOutput->flags & HOOK_SYNCHRONIZE))
      {
        if (NULL != GDIDEVFUNCS(*ppsoOutput).SynchronizeSurface)
          {
@@@ -219,7 -218,6 +218,6 @@@ IntEngLeave(PINTENG_ENTER_LEAVE EnterLe
            Result = TRUE;
          }
        }
-     EngFreeMem(EnterLeave->OutputObj->pvBits);
      EngUnlockSurface(EnterLeave->OutputObj);
      EngDeleteSurface((HSURF)EnterLeave->OutputBitmap);
      EngDeleteClip(EnterLeave->TrivialClipObj);
@@@ -548,14 -548,7 +548,7 @@@ IntEngGradientFill
    psurf = CONTAINING_RECORD(psoDest, SURFACE, SurfObj);
    ASSERT(psurf);
  
-   SURFACE_LockBitmapBits(psurf);
-   MouseSafetyOnDrawStart(
-         psoDest,
-         pco->rclBounds.left,
-         pco->rclBounds.top,
-       pco->rclBounds.right,
-         pco->rclBounds.bottom);
-   if(psurf->flHooks & HOOK_GRADIENTFILL)
+   if(psurf->flags & HOOK_GRADIENTFILL)
    {
      Ret = GDIDEVFUNCS(psoDest).GradientFill(
        psoDest, pco, pxlo, pVertex, nVertex, pMesh, nMesh,
      Ret = EngGradientFill(psoDest, pco, pxlo, pVertex, nVertex, pMesh, nMesh, prclExtents,
                            pptlDitherOrg, ulMode);
    }
-   MouseSafetyOnDrawEnd(psoDest);
-   SURFACE_UnlockBitmapBits(psurf);
  
    return Ret;
  }
index 0000000,6296a01..6296a01
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,504 +1,504 @@@
+ /*
+  * COPYRIGHT:        See COPYING in the top level directory
+  * PROJECT:          ReactOS kernel
+  * PURPOSE:          Support for logical devices
+  * FILE:             subsystems/win32/win32k/eng/ldevobj.c
+  * PROGRAMER:        Timo Kreuzer (timo.kreuzer@reactos.org)
+  */
+ #include <win32k.h>
+ #include <intrin.h>
+ #define NDEBUG
+ #include <debug.h>
+ #ifndef RVA_TO_ADDR
+ #define RVA_TO_ADDR(Base,Rva) ((PVOID)(((ULONG_PTR)(Base)) + (Rva)))
+ #endif
+ /** Globals *******************************************************************/
+ HSEMAPHORE ghsemLDEVList;
+ LDEVOBJ *gpldevHead = NULL;
+ LDEVOBJ *gpldevWin32k = NULL;
+ /** Private functions *********************************************************/
+ BOOL
+ NTAPI
+ InitLDEVImpl()
+ {
+     /* Initialize the loader lock */
+     ghsemLDEVList = EngCreateSemaphore();
+     if (!ghsemLDEVList)
+     {
+         return FALSE;
+     }
+     /* Allocate a LDEVOBJ for win32k */
+     gpldevWin32k = ExAllocatePoolWithTag(PagedPool,
+                                          sizeof(LDEVOBJ) +
+                                          sizeof(SYSTEM_GDI_DRIVER_INFORMATION),
+                                          GDITAG_LDEV);
+     if (!gpldevWin32k)
+     {
+         return FALSE;
+     }
+     /* Initialize the LDEVOBJ for win32k */
+     gpldevWin32k->pldevNext = NULL;
+     gpldevWin32k->pldevPrev = NULL;
+     gpldevWin32k->ldevtype = LDEV_DEVICE_DISPLAY;
+     gpldevWin32k->cRefs = 1;
+     gpldevWin32k->ulDriverVersion = GDI_ENGINE_VERSION;
+     gpldevWin32k->pGdiDriverInfo = (PVOID)(gpldevWin32k + 1);
+     RtlInitUnicodeString(&gpldevWin32k->pGdiDriverInfo->DriverName,
+                          L"\\SystemRoot\\System32\\win32k.sys");
+     gpldevWin32k->pGdiDriverInfo->ImageAddress = &__ImageBase;
+     gpldevWin32k->pGdiDriverInfo->SectionPointer = NULL;
+     gpldevWin32k->pGdiDriverInfo->EntryPoint = (PVOID)DriverEntry;
+     gpldevWin32k->pGdiDriverInfo->ExportSectionPointer = NULL;
+     gpldevWin32k->pGdiDriverInfo->ImageLength = 0; // FIXME;
+     return TRUE;
+ }
+ PLDEVOBJ
+ NTAPI
+ LDEVOBJ_AllocLDEV(LDEVTYPE ldevtype)
+ {
+     PLDEVOBJ pldev;
+     /* Allocate the structure from paged pool */
+     pldev = ExAllocatePoolWithTag(PagedPool, sizeof(LDEVOBJ), GDITAG_LDEV);
+     if (!pldev)
+     {
+         DPRINT1("Failed to allocate LDEVOBJ.\n");
+         return NULL;
+     }
+     /* Zero out the structure */
+     RtlZeroMemory(pldev, sizeof(LDEVOBJ));
+     /* Set the ldevtype */
+     pldev->ldevtype = ldevtype;
+     return pldev;
+ }
+ VOID
+ NTAPI
+ LDEVOBJ_vFreeLDEV(PLDEVOBJ pldev)
+ {
+     /* Make sure we don't have a driver loaded */
+     ASSERT(pldev && pldev->pGdiDriverInfo == NULL);
+     /* Free the memory */
+     ExFreePoolWithTag(pldev, TAG_LDEV);
+ }
+ PDEVMODEINFO
+ NTAPI
+ LDEVOBJ_pdmiGetModes(
+     PLDEVOBJ pldev,
+     HANDLE hDriver)
+ {
+     ULONG cbSize, cbFull;
+     PDEVMODEINFO pdminfo;
+     DPRINT("LDEVOBJ_pdmiGetModes(%p, %p)\n", pldev, hDriver);
+     /* Call the driver to get the required size */
+     cbSize = pldev->pfn.GetModes(hDriver, 0, NULL);
+     if (!cbSize)
+     {
+         DPRINT1("DrvGetModes returned 0\n");
+         return NULL;
+     }
+     /* Add space for the header */
+     cbFull = cbSize + FIELD_OFFSET(DEVMODEINFO, adevmode);
+     /* Allocate a buffer for the DEVMODE array */
+     pdminfo = ExAllocatePoolWithTag(PagedPool, cbFull, GDITAG_DEVMODE);
+     if (!pdminfo)
+     {
+         DPRINT1("Could not allocate devmodeinfo\n");
+         return NULL;
+     }
+     pdminfo->pldev = pldev;
+     pdminfo->cbdevmode = cbSize;
+     /* Call the driver again to fill the buffer */
+     cbSize = pldev->pfn.GetModes(hDriver, cbSize, pdminfo->adevmode);
+     if (!cbSize)
+     {
+         /* Could not get modes */
+         DPRINT1("returned size %ld(%ld)\n", cbSize, pdminfo->cbdevmode);
+         ExFreePool(pdminfo);
+         pdminfo = NULL;
+     }
+     return pdminfo;
+ }
+ BOOL
+ NTAPI
+ LDEVOBJ_bLoadImage(
+     IN PLDEVOBJ pldev,
+     PUNICODE_STRING pstrPathName)
+ {
+     PSYSTEM_GDI_DRIVER_INFORMATION pDriverInfo;
+     NTSTATUS Status;
+     ULONG cbSize;
+     /* Make sure no image is loaded yet */
+     ASSERT(pldev && pldev->pGdiDriverInfo == NULL);
+     /* Allocate a SYSTEM_GDI_DRIVER_INFORMATION structure */
+     cbSize = sizeof(SYSTEM_GDI_DRIVER_INFORMATION) + pstrPathName->Length;
+     pDriverInfo = ExAllocatePoolWithTag(PagedPool, cbSize, GDITAG_LDEV);
+     if (!pDriverInfo)
+     {
+         DPRINT1("Failed to allocate SYSTEM_GDI_DRIVER_INFORMATION\n");
+         return FALSE;
+     }
+     /* Initialize the UNICODE_STRING and copy the driver name */
+     RtlInitEmptyUnicodeString(&pDriverInfo->DriverName,
+                               (PWSTR)(pDriverInfo + 1),
+                               pstrPathName->Length);
+     RtlCopyUnicodeString(&pDriverInfo->DriverName, pstrPathName);
+     /* Try to load the driver */
+     Status = ZwSetSystemInformation(SystemLoadGdiDriverInformation,
+                                     pDriverInfo,
+                                     sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Failed to load a GDI driver: '%S', Status = 0x%lx\n", 
+                 pstrPathName->Buffer, Status);
+         /* Free the allocated memory */
+         ExFreePoolWithTag(pDriverInfo, TAG_LDEV);
+         return FALSE;
+     }
+     /* Set the driver info */
+     pldev->pGdiDriverInfo = pDriverInfo;
+     /* Return success. */
+     return TRUE;
+ }
+ VOID
+ NTAPI
+ LDEVOBJ_vUnloadImage(
+     IN PLDEVOBJ pldev)
+ {
+     NTSTATUS Status;
+     /* Make sure we have a driver info */
+     ASSERT(pldev && pldev->pGdiDriverInfo != NULL);
+     /* Check if we have loaded a driver */
+     if (pldev->pfn.DisableDriver)
+     {
+         /* Call the unload function */
+         pldev->pfn.DisableDriver();
+     }
+     /* Unload the driver */
+     Status = ZwSetSystemInformation(SystemUnloadGdiDriverInformation,
+                                     &pldev->pGdiDriverInfo->ImageAddress,
+                                     sizeof(HANDLE));
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Failed to unload the driver, this is bad.\n");
+     }
+     /* Free the driver info structure */
+     ExFreePoolWithTag(pldev->pGdiDriverInfo, GDITAG_LDEV);
+     pldev->pGdiDriverInfo = NULL;
+ }
+ BOOL
+ NTAPI
+ LDEVOBJ_bLoadDriver(
+     IN PLDEVOBJ pldev)
+ {
+     PFN_DrvEnableDriver pfnEnableDriver;
+     DRVENABLEDATA ded;
+     ULONG i;
+     /* Make sure we have a driver info */
+     ASSERT(pldev && pldev->pGdiDriverInfo != NULL);
+     /* Call the drivers DrvEnableDriver function */
+     RtlZeroMemory(&ded, sizeof(ded));
+     pfnEnableDriver = pldev->pGdiDriverInfo->EntryPoint;
+     if (!pfnEnableDriver(GDI_ENGINE_VERSION, sizeof(ded), &ded))
+     {
+         DPRINT1("DrvEnableDriver failed\n");
+         /* Unload the image. */
+         LDEVOBJ_vUnloadImage(pldev);
+         return FALSE;
+     }
+     /* Copy the returned driver version */
+     pldev->ulDriverVersion = ded.iDriverVersion;
+     /* Fill the driver function array */
+     for (i = 0; i < ded.c; i++)
+     {
+         pldev->apfn[ded.pdrvfn[i].iFunc] = ded.pdrvfn[i].pfn;
+     }
+     /* Return success. */
+     return TRUE;
+ }
+ PVOID
+ NTAPI
+ LDEVOBJ_pvFindImageProcAddress(
+     IN PLDEVOBJ pldev,
+     IN LPSTR    pszProcName)
+ {
+     PVOID pvImageBase;
+     PIMAGE_EXPORT_DIRECTORY pExportDir;
+     PVOID pvProcAdress = NULL;
+     PUSHORT pOrdinals;
+     PULONG pNames, pAddresses;
+     ULONG i, cbSize;
+     /* Make sure we have a driver info */
+     ASSERT(pldev && pldev->pGdiDriverInfo != NULL);
+     /* Get the pointer to the export directory */
+     pvImageBase = pldev->pGdiDriverInfo->ImageAddress;
+     pExportDir = RtlImageDirectoryEntryToData(pvImageBase,
+                                               TRUE,
+                                               IMAGE_DIRECTORY_ENTRY_EXPORT,
+                                               &cbSize);
+     if (!pExportDir)
+     {
+         return NULL;
+     }
+     /* Get pointers to some tables */
+     pNames = RVA_TO_ADDR(pvImageBase, pExportDir->AddressOfNames);
+     pOrdinals = RVA_TO_ADDR(pvImageBase, pExportDir->AddressOfNameOrdinals);
+     pAddresses = RVA_TO_ADDR(pvImageBase, pExportDir->AddressOfFunctions);
+     /* Loop the export table */
+     for (i = 0; i < pExportDir->NumberOfNames; i++)
+     {
+         /* Compare the name */
+         if (_stricmp(pszProcName, RVA_TO_ADDR(pvImageBase, pNames[i])) == 0)
+         {
+             /* Found! Calculate the procedure address */
+             pvProcAdress = RVA_TO_ADDR(pvImageBase, pAddresses[pOrdinals[i]]);
+             break;
+         }
+     }
+     /* Return the address */
+     return pvProcAdress;
+ }
+ PLDEVOBJ
+ NTAPI
+ EngLoadImageEx(
+     LPWSTR pwszDriverName,
+     ULONG ldevtype)
+ {
+     WCHAR acwBuffer[MAX_PATH];
+     PLDEVOBJ pldev;
+     UNICODE_STRING strDriverName;
+     ULONG cwcLength;
+     LPWSTR pwsz;
+     DPRINT("EngLoadImageEx(%ls, %ld)\n", pwszDriverName, ldevtype);
+     ASSERT(pwszDriverName);
+     /* Initialize buffer for the the driver name */
+     RtlInitEmptyUnicodeString(&strDriverName, acwBuffer, sizeof(acwBuffer));
+     /* Start path with systemroot */
+     RtlAppendUnicodeToString(&strDriverName, L"\\SystemRoot\\System32\\");
+     /* Get Length of given string */
+     cwcLength = wcslen(pwszDriverName);
+     /* Check if we have a system32 path given */
+     pwsz = pwszDriverName + cwcLength;
+     while (pwsz > pwszDriverName)
+     {
+         if (_wcsnicmp(pwsz, L"\\system32\\", 10) == 0)
+         {
+             /* Driver name starts after system32 */
+             pwsz += 10;
+             break;
+         }
+         pwsz--;
+     }
+     /* Append the driver name */
+     RtlAppendUnicodeToString(&strDriverName, pwsz);
+     /* MSDN says "The driver must include this suffix in the pwszDriver string."
+        But in fact it's optional. */
+     if (_wcsnicmp(pwszDriverName + cwcLength - 4, L".dll", 4) != 0)
+     {
+         /* Append the .dll suffix */
+         RtlAppendUnicodeToString(&strDriverName, L".dll");
+     }
+     /* Lock loader */
+     EngAcquireSemaphore(ghsemLDEVList);
+     /* Search the List of LDEVS for the driver name */
+     for (pldev = gpldevHead; pldev != NULL; pldev = pldev->pldevNext)
+     {
+         /* Check if the ldev is associated with a file */
+         if (pldev->pGdiDriverInfo)
+         {
+             /* Check for match (case insensative) */
+             if (RtlEqualUnicodeString(&pldev->pGdiDriverInfo->DriverName, &strDriverName, 1))
+             {
+                 /* Image found in LDEV list */
+                 break;
+             }
+         }
+     }
+     /* Did we find one? */
+     if (!pldev)
+     {
+         /* No, allocate a new LDEVOBJ */
+         pldev = LDEVOBJ_AllocLDEV(ldevtype);
+         if (!pldev)
+         {
+             DPRINT1("Could not allocate LDEV\n");
+             goto leave;
+         }
+         /* Load the image */
+         if (!LDEVOBJ_bLoadImage(pldev, &strDriverName))
+         {
+             LDEVOBJ_vFreeLDEV(pldev);
+             pldev = NULL;
+             DPRINT1("LDEVOBJ_bLoadImage failed\n");
+             goto leave;
+         }
+         /* Shall we load a driver? */
+         if (ldevtype != LDEV_IMAGE)
+         {
+             /* Load the driver */
+             if (!LDEVOBJ_bLoadDriver(pldev))
+             {
+                 DPRINT1("LDEVOBJ_bLoadDriver failed\n");
+                 LDEVOBJ_vFreeLDEV(pldev);
+                 pldev = NULL;
+                 goto leave;
+             }
+         }
+         /* Insert the LDEV into the global list */
+         pldev->pldevPrev = NULL;
+         pldev->pldevNext = gpldevHead;
+         gpldevHead = pldev;
+     }
+     /* Increase ref count */
+     pldev->cRefs++;
+ leave:
+     /* Unlock loader */
+     EngReleaseSemaphore(ghsemLDEVList);
+     DPRINT("EngLoadImageEx returning %p\n", pldev);
+     return pldev;
+ }
+ /** Exported functions ********************************************************/
+ HANDLE
+ APIENTRY
+ EngLoadImage(
+     LPWSTR pwszDriverName)
+ {
+     return (HANDLE)EngLoadImageEx(pwszDriverName, LDEV_IMAGE);
+ }
+ VOID
+ APIENTRY
+ EngUnloadImage(
+     IN HANDLE hModule)
+ {
+     PLDEVOBJ pldev = (PLDEVOBJ)hModule;
+     /* Make sure the LDEV is in the list */
+     ASSERT(pldev->pldevPrev || pldev->pldevNext);
+     /* Lock loader */
+     EngAcquireSemaphore(ghsemLDEVList);
+     /* Decrement reference count */
+     pldev->cRefs--;
+     /* No more references left? */
+     if (pldev->cRefs == 0)
+     {
+         /* Remove ldev from the list */
+         if (pldev->pldevPrev)
+             pldev->pldevPrev->pldevNext = pldev->pldevNext;
+         if (pldev->pldevNext)
+             pldev->pldevNext->pldevPrev = pldev->pldevPrev;
+         /* Unload the image */
+         LDEVOBJ_vUnloadImage(pldev);
+     }
+     /* Unlock loader */
+     EngReleaseSemaphore(ghsemLDEVList);
+ }
+ PVOID
+ APIENTRY
+ EngFindImageProcAddress(
+     IN HANDLE hModule,
+     IN LPSTR  lpProcName)
+ {
+     PLDEVOBJ pldev = (PLDEVOBJ)hModule;
+     ASSERT(gpldevWin32k != NULL);
+     /* Check if win32k is requested */
+     if (!pldev)
+     {
+         pldev = gpldevWin32k;
+     }
+     /* Check if the drivers entry point is requested */
+     if (_strnicmp(lpProcName, "DrvEnableDriver", 15) == 0)
+     {
+         return pldev->pGdiDriverInfo->EntryPoint;
+     }
+     /* Try to find the address */
+     return LDEVOBJ_pvFindImageProcAddress(pldev, lpProcName);
+ }
@@@ -565,10 -565,7 +565,7 @@@ IntEngLineTo(SURFOBJ *psoDest
      if (b.left == b.right) b.right++;
      if (b.top == b.bottom) b.bottom++;
  
-     SURFACE_LockBitmapBits(psurfDest);
-     MouseSafetyOnDrawStart(psoDest, x1, y1, x2, y2);
-     if (psurfDest->flHooks & HOOK_LINETO)
+     if (psurfDest->flags & HOOK_LINETO)
      {
          /* Call the driver's DrvLineTo */
          ret = GDIDEVFUNCS(psoDest).LineTo(
      }
  
  #if 0
-     if (! ret && (psurfDest->flHooks & HOOK_STROKEPATH))
+     if (! ret && (psurfDest->flags & HOOK_STROKEPATH))
      {
          /* FIXME: Emulate LineTo using drivers DrvStrokePath and set ret on success */
      }
          ret = EngLineTo(psoDest, ClipObj, pbo, x1, y1, x2, y2, RectBounds, Mix);
      }
  
-     MouseSafetyOnDrawEnd(psoDest);
-     SURFACE_UnlockBitmapBits(psurfDest);
      return ret;
  }
  
@@@ -3,7 -3,7 +3,7 @@@
   * PROJECT:           ReactOS kernel
   * PURPOSE:           Functions for mapping files and sections
   * FILE:              subsys/win32k/eng/device.c
-  * PROGRAMER:
+  * PROGRAMER:         Timo Kreuzer (timo.kreuzer@reactos.org)
   */
  
  #include <win32k.h>
  #define NDEBUG
  #include <debug.h>
  
+ // HACK!!!
+ #define MmMapViewInSessionSpace MmMapViewInSystemSpace
+ #define MmUnmapViewInSessionSpace MmUnmapViewInSystemSpace
+ typedef struct _ENGSECTION
+ {
+     PVOID pvSectionObject;
+     PVOID pvMappedBase;
+     SIZE_T cjViewSize;
+     ULONG ulTag;
+ } ENGSECTION, *PENGSECTION;
+ typedef struct _FILEVIEW
+ {
+     LARGE_INTEGER  LastWriteTime;  
+     PVOID          pvKView;
+     PVOID          pvViewFD;  
+     SIZE_T         cjView;  
+     PVOID          pSection;  
+ } FILEVIEW, *PFILEVIEW;   
+ typedef struct _FONTFILEVIEW 
+ {
+     FILEVIEW;
+     DWORD          reserved[2];
+     PWSTR          pwszPath;
+     SIZE_T         ulRegionSize;
+     ULONG          cKRefCount;
+     ULONG          cRefCountFD;
+     PVOID          pvSpoolerBase;
+     DWORD          dwSpoolerPid;
+ } FONTFILEVIEW, *PFONTFILEVIEW;
+ enum
+ {
+     FVF_SYSTEMROOT = 1,
+     FVF_READONLY = 2,
+     FVF_FONTFILE = 4,
+ };
+ HANDLE ghSystem32Directory;
+ HANDLE ghRootDirectory;
+ PVOID
+ NTAPI
+ EngCreateSection(
+     IN ULONG fl,
+     IN SIZE_T cjSize,
+     IN ULONG ulTag)
+ {
+     NTSTATUS Status;
+     PENGSECTION pSection;
+     PVOID pvSectionObject;
+     LARGE_INTEGER liSize;
+     /* Allocate a section object */
+     pSection = EngAllocMem(0, sizeof(ENGSECTION), 'stsU');
+     if (!pSection) return NULL;
+     liSize.QuadPart = cjSize;
+     Status = MmCreateSection(&pvSectionObject,
+                              SECTION_ALL_ACCESS,
+                              NULL,
+                              &liSize,
+                              PAGE_READWRITE,
+                              SEC_COMMIT,
+                              NULL,
+                              NULL);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Failed to create a section Status=0x%x\n", Status);
+         EngFreeMem(pSection);
+         return NULL;
+     }
+     /* Set the fields of the section */
+     pSection->ulTag = ulTag;
+     pSection->pvSectionObject = pvSectionObject;
+     pSection->pvMappedBase = NULL;
+     pSection->cjViewSize = cjSize;
+     return pSection;
+ }
+ BOOL
+ APIENTRY
+ EngMapSection(
+     IN PVOID pvSection,
+     IN BOOL bMap,
+     IN HANDLE hProcess,
+     OUT PVOID* pvBaseAddress)
+ {
+     NTSTATUS Status;
+     PENGSECTION pSection = pvSection;
+     PEPROCESS pepProcess;
+     /* Get a pointer to the process */
+     Status = ObReferenceObjectByHandle(hProcess,
+                                        PROCESS_VM_OPERATION,
+                                        NULL,
+                                        KernelMode,
+                                        (PVOID*)&pepProcess,
+                                        NULL);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Could not access process %p, Status=0x%lx\n", hProcess, Status);
+         return FALSE;
+     }
+     if (bMap)
+     {
+         /* Make sure the section isn't already mapped */
+         ASSERT(pSection->pvMappedBase == NULL);
+         /* Map the section into the process address space */
+         Status = MmMapViewOfSection(pSection->pvSectionObject,
+                                     pepProcess,
+                                     &pSection->pvMappedBase,
+                                     0,
+                                     pSection->cjViewSize,
+                                     NULL,
+                                     &pSection->cjViewSize,
+                                     0,
+                                     0,
+                                     PAGE_READWRITE);
+         if (!NT_SUCCESS(Status))
+         {
+             DPRINT1("Failed to map a section Status=0x%x\n", Status);
+         }
+     }
+     else
+     {
+         /* Make sure the section is mapped */
+         ASSERT(pSection->pvMappedBase);
+         /* Unmap the section from the process address space */
+         Status = MmUnmapViewOfSection(pepProcess, pSection->pvMappedBase);
+         if (NT_SUCCESS(Status))
+         {
+             pSection->pvMappedBase = NULL;
+         }
+         else
+         {
+             DPRINT1("Failed to unmap a section @ &p Status=0x%x\n", 
+                     pSection->pvMappedBase, Status);
+         }
+     }
+     /* Dereference the process */
+     ObDereferenceObject(pepProcess);
+     /* Set the new mapping base and return bool status */
+     *pvBaseAddress = pSection->pvMappedBase;
+     return NT_SUCCESS(Status);
+ }
+ BOOL
+ APIENTRY
+ EngFreeSectionMem(
+     IN PVOID pvSection OPTIONAL,
+     IN PVOID pvMappedBase OPTIONAL)
+ {
+     NTSTATUS Status;
+     PENGSECTION pSection = pvSection;
+     BOOL bResult = TRUE;
+     /* Did the caller give us a mapping base? */
+     if (pvMappedBase)
+     {
+         Status = MmUnmapViewInSessionSpace(pvMappedBase);
+         if (!NT_SUCCESS(Status))
+         {
+             DPRINT1("MmUnmapViewInSessionSpace failed: 0x%lx\n", Status);
+             bResult = FALSE;
+         }
+     }
+     /* Check if we should free the section as well */
+     if (pSection)
+     {
+         /* Dereference the kernel section */
+         ObDereferenceObject(pSection->pvSectionObject);
+         /* Finally free the section memory itself */
+         EngFreeMem(pSection);
+     }
+     return bResult;
+ }
+ PVOID
+ APIENTRY
+ EngAllocSectionMem(
+     OUT PVOID *ppvSection,
+     IN ULONG fl,
+     IN SIZE_T cjSize,
+     IN ULONG ulTag)
+ {
+     NTSTATUS Status;
+     PENGSECTION pSection;
+     /* Check parameter */
+     if (cjSize == 0) return NULL;
+     /* Allocate a section object */
+     pSection = EngCreateSection(fl, cjSize, ulTag);
+     if (!pSection)
+     {
+         *ppvSection = NULL;
+         return NULL;
+     }
+     /* Map the section in session space */
+     Status = MmMapViewInSessionSpace(pSection->pvSectionObject,
+                                      &pSection->pvMappedBase,
+                                      &pSection->cjViewSize);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Failed to map a section Status=0x%x\n", Status);
+         *ppvSection = NULL;
+         EngFreeSectionMem(pSection, NULL);
+         return NULL;
+     }
+     if (fl & FL_ZERO_MEMORY)
+     {
+         RtlZeroMemory(pSection->pvMappedBase, cjSize);
+     }
+     /* Set section pointer and return base address */
+     *ppvSection = pSection;
+     return pSection->pvMappedBase;
+ }
+ PFILEVIEW
+ NTAPI
+ EngLoadModuleEx(
+     LPWSTR pwsz,
+     ULONG cjSizeOfModule,
+     FLONG fl)
+ {
+     PFILEVIEW pFileView = NULL;
+     OBJECT_ATTRIBUTES ObjectAttributes;
+     HANDLE hRootDir;
+     UNICODE_STRING ustrFileName;
+     IO_STATUS_BLOCK IoStatusBlock;
+     FILE_BASIC_INFORMATION FileInformation;
+     HANDLE hFile;
+     NTSTATUS Status;
+     LARGE_INTEGER liSize;
+     if (fl & FVF_FONTFILE)
+     {
+         pFileView = EngAllocMem(0, sizeof(FONTFILEVIEW), 'vffG');
+     }
+     else
+     {
+         pFileView = EngAllocMem(0, sizeof(FILEVIEW), 'liFg');
+     }
+     /* Check for success */
+     if (!pFileView) return NULL;
+     /* Check if the file is relative to system32 */
+     if (fl & FVF_SYSTEMROOT)
+     {
+         hRootDir = ghSystem32Directory;
+     }
+     else
+     {
+         hRootDir = ghRootDirectory;
+     }
+     /* Initialize unicode string and object attributes */
+     RtlInitUnicodeString(&ustrFileName, pwsz);
+     InitializeObjectAttributes(&ObjectAttributes,
+                                &ustrFileName,
+                                OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
+                                hRootDir,
+                                NULL);
+     /* Now open the file */
+     Status = ZwCreateFile(&hFile,
+                           FILE_READ_DATA,
+                           &ObjectAttributes,
+                           &IoStatusBlock,
+                           NULL,
+                           FILE_ATTRIBUTE_NORMAL,
+                           0,
+                           FILE_OPEN,
+                           FILE_NON_DIRECTORY_FILE,
+                           NULL,
+                           0);
+     Status = ZwQueryInformationFile(hFile,
+                                     &IoStatusBlock,
+                                     &FileInformation,
+                                     sizeof(FILE_BASIC_INFORMATION),
+                                     FileBasicInformation);
+     if (NT_SUCCESS(Status))
+     {
+         pFileView->LastWriteTime = FileInformation.LastWriteTime;
+     }
+     /* Create a section from the file */
+     liSize.QuadPart = cjSizeOfModule;
+     Status = MmCreateSection(&pFileView->pSection,
+                              SECTION_ALL_ACCESS,
+                              NULL,
+                              cjSizeOfModule ? &liSize : NULL,
+                              fl & FVF_READONLY ? PAGE_EXECUTE_READ : PAGE_EXECUTE_READWRITE,
+                              SEC_COMMIT,
+                              hFile,
+                              NULL);
+     /* Close the file handle */
+     ZwClose(hFile);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Failed to create a section Status=0x%x\n", Status);
+         EngFreeMem(pFileView);
+         return NULL;
+     }
+     pFileView->pvKView = NULL;
+     pFileView->pvViewFD = NULL;
+     pFileView->cjView = 0;
+     return pFileView;
+ }
  HANDLE
  APIENTRY
  EngLoadModule(LPWSTR pwsz)
  {
-     UNIMPLEMENTED;
-     return NULL;
+     /* Forward to EngLoadModuleEx */
+     return (HANDLE)EngLoadModuleEx(pwsz, 0, FVF_READONLY | FVF_SYSTEMROOT);
  }
  
  HANDLE
@@@ -25,9 -361,8 +361,8 @@@ EngLoadModuleForWrite
        IN LPWSTR pwsz,
        IN ULONG  cjSizeOfModule)
  {
-     // www.osr.com/ddk/graphics/gdifncs_98rr.htm
-     UNIMPLEMENTED;
-     return NULL;
+     /* Forward to EngLoadModuleEx */
+     return (HANDLE)EngLoadModuleEx(pwsz, cjSizeOfModule, FVF_SYSTEMROOT);
  }
  
  PVOID
@@@ -36,17 -371,46 +371,46 @@@ EngMapModule
        IN  HANDLE h,
        OUT PULONG pulSize)
  {
-     // www.osr.com/ddk/graphics/gdifncs_9b1j.htm
-     UNIMPLEMENTED;
-     return NULL;
+     PFILEVIEW pFileView = (PFILEVIEW)h;
+     NTSTATUS Status;
+     pFileView->cjView = 0;
+     /* Map the section in session space */
+     Status = MmMapViewInSessionSpace(pFileView->pSection,
+                                      &pFileView->pvKView,
+                                      &pFileView->cjView);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Failed to map a section Status=0x%x\n", Status);
+         *pulSize = 0;
+         return NULL;
+     }
+     *pulSize = pFileView->cjView;
+     return pFileView->pvKView;
  }
  
  VOID
  APIENTRY
- EngFreeModule (IN HANDLE h)
+ EngFreeModule(IN HANDLE h)
  {
-     // www.osr.com/ddk/graphics/gdifncs_9fzb.htm
-     UNIMPLEMENTED;
+     PFILEVIEW pFileView = (PFILEVIEW)h;
+     NTSTATUS Status;
+     /* Unmap the section */
+     Status = MmUnmapViewInSessionSpace(pFileView->pvKView);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("MmUnmapViewInSessionSpace failed: 0x%lx\n", Status);
+         ASSERT(FALSE);
+     }
+     /* Dereference the section */
+     ObDereferenceObject(pFileView->pSection);
+     /* Free the file view memory */
+     EngFreeMem(pFileView);
  }
  
  PVOID
@@@ -56,8 -420,28 +420,28 @@@ EngMapFile
      IN ULONG cjSize,
      OUT ULONG_PTR *piFile)
  {
-     UNIMPLEMENTED;
-     return NULL;
+     HANDLE hModule;
+     PVOID pvBase;
+     /* Load the file */
+     hModule = EngLoadModuleEx(pwsz, 0, 0);
+     if (!hModule)
+     {
+         *piFile = 0;
+         return NULL;
+     }
+     /* Map the file */
+     pvBase = EngMapModule(hModule, &cjSize);
+     if (!pvBase)
+     {
+         EngFreeModule(hModule);
+         hModule = NULL;
+     }
+     /* Set iFile and return mapped base */
+     *piFile = (ULONG_PTR)hModule;
+     return pvBase;
  }
  
  BOOL
@@@ -65,8 -449,11 +449,11 @@@ APIENTR
  EngUnmapFile(
      IN ULONG_PTR iFile)
  {
-     UNIMPLEMENTED;
-     return FALSE;
+     HANDLE hModule = (HANDLE)iFile;
+     EngFreeModule(hModule);
+     return TRUE;
  }
  
  
@@@ -110,36 -497,3 +497,3 @@@ EngUnmapFontFile
      // www.osr.com/ddk/graphics/gdifncs_09wn.htm
      EngUnmapFontFileFD(iFile);
  }
- BOOLEAN
- APIENTRY
- EngMapSection(IN PVOID Section,
-               IN BOOLEAN Map,
-               IN HANDLE Process,
-               IN PVOID* BaseAddress)
- {
-     UNIMPLEMENTED;
-     return FALSE;
- }
- PVOID
- APIENTRY
- EngAllocSectionMem(IN PVOID SectionObject,
-                    IN ULONG Flags,
-                    IN SIZE_T MemSize,
-                    IN ULONG Tag)
- {
-     UNIMPLEMENTED;
-     return NULL;
- }
- BOOLEAN
- APIENTRY
- EngFreeSectionMem(IN PVOID SectionObject OPTIONAL,
-                   IN PVOID MappedBase)
- {
-     UNIMPLEMENTED;
-     return FALSE;
- }
@@@ -79,6 -79,7 +79,7 @@@ EngAllocUserMem(SIZE_T cj, ULONG Tag
      }
  
    /* TODO: Add allocation info to AVL tree (stored inside W32PROCESS structure) */
+   //hSecure = EngSecureMem(NewMem, cj);
  
    return NewMem;
  }
@@@ -166,6 -167,7 +167,7 @@@ HackUnsecureVirtualMemory
  HANDLE APIENTRY
  EngSecureMem(PVOID Address, ULONG Length)
  {
+     return (HANDLE)-1; // HACK!!!
    return MmSecureVirtualMemory(Address, Length, PAGE_READWRITE);
  }
  
  VOID APIENTRY
  EngUnsecureMem(HANDLE Mem)
  {
+     if (Mem == (HANDLE)-1) return;  // HACK!!!
    MmUnsecureVirtualMemory((PVOID) Mem);
  }
  
@@@ -37,23 -37,17 +37,17 @@@ EngSetPointerTag
   */
  INT INTERNAL_CALL
  MouseSafetyOnDrawStart(
-     SURFOBJ *pso,
+     PPDEVOBJ ppdev,
      LONG HazardX1,
      LONG HazardY1,
      LONG HazardX2,
      LONG HazardY2)
  {
      LONG tmp;
-     PDEVOBJ *ppdev;
      GDIPOINTER *pgp;
  
-     ASSERT(pso != NULL);
-     ppdev = GDIDEV(pso);
-     if (ppdev == NULL)
-     {
-         return FALSE;
-     }
+     ASSERT(ppdev != NULL);
+     ASSERT(ppdev->pSurface != NULL);
  
      pgp = &ppdev->Pointer;
  
      }
  
      if (pgp->Exclude.right >= HazardX1
-             && pgp->Exclude.left <= HazardX2
-             && pgp->Exclude.bottom >= HazardY1
-             && pgp->Exclude.top <= HazardY2)
+         && pgp->Exclude.left <= HazardX2
+         && pgp->Exclude.bottom >= HazardY1
+         && pgp->Exclude.top <= HazardY2)
      {
          ppdev->SafetyRemoveLevel = ppdev->SafetyRemoveCount;
-         ppdev->pfnMovePointer(pso, -1, -1, NULL);
+         ppdev->pfnMovePointer(&ppdev->pSurface->SurfObj, -1, -1, NULL);
      }
  
      return(TRUE);
   */
  INT INTERNAL_CALL
  MouseSafetyOnDrawEnd(
-     SURFOBJ *pso)
+     PPDEVOBJ ppdev)
  {
-     PDEVOBJ *ppdev;
      GDIPOINTER *pgp;
  
-     ASSERT(pso != NULL);
-     ppdev = (PDEVOBJ*)pso->hdev;
-     if (ppdev == NULL)
-     {
-         return(FALSE);
-     }
+     ASSERT(ppdev != NULL);
+     ASSERT(ppdev->pSurface != NULL);
  
      pgp = &ppdev->Pointer;
  
          return FALSE;
      }
  
-     ppdev->pfnMovePointer(pso, gpsi->ptCursor.x, gpsi->ptCursor.y, &pgp->Exclude);
+     ppdev->pfnMovePointer(&ppdev->pSurface->SurfObj,
+                           gpsi->ptCursor.x,
+                           gpsi->ptCursor.y,
+                           &pgp->Exclude);
  
      ppdev->SafetyRemoveLevel = 0;
  
@@@ -175,18 -165,17 +165,17 @@@ IntHideMousePointer
      ptlSave.x = rclDest.left - pt.x;
      ptlSave.y = rclDest.top - pt.y;
  
-     IntEngBitBltEx(psoDest,
-                    &pgp->psurfSave->SurfObj,
-                    NULL,
-                    NULL,
-                    NULL,
-                    &rclDest,
-                    &ptlSave,
-                    &ptlSave,
-                    NULL,
-                    NULL,
-                    ROP3_TO_ROP4(SRCCOPY),
-                    FALSE);
+     IntEngBitBlt(psoDest,
+                  &pgp->psurfSave->SurfObj,
+                  NULL,
+                  NULL,
+                  NULL,
+                  &rclDest,
+                  &ptlSave,
+                  &ptlSave,
+                  NULL,
+                  NULL,
+                  ROP3_TO_ROP4(SRCCOPY));
  }
  
  VOID
@@@ -229,77 -218,72 +218,72 @@@ IntShowMousePointer(PDEVOBJ *ppdev, SUR
      rclPointer.bottom = min(pgp->Size.cy, psoDest->sizlBitmap.cy - pt.y);
  
      /* Copy the pixels under the cursor to temporary surface. */
-     IntEngBitBltEx(&pgp->psurfSave->SurfObj,
-                    psoDest,
-                    NULL,
-                    NULL,
-                    NULL,
-                    &rclPointer,
-                    (POINTL*)&rclSurf,
-                    NULL,
-                    NULL,
-                    NULL,
-                    ROP3_TO_ROP4(SRCCOPY),
-                    FALSE);
+     IntEngBitBlt(&pgp->psurfSave->SurfObj,
+                  psoDest,
+                  NULL,
+                  NULL,
+                  NULL,
+                  &rclPointer,
+                  (POINTL*)&rclSurf,
+                  NULL,
+                  NULL,
+                  NULL,
+                  ROP3_TO_ROP4(SRCCOPY));
  
      /* Blt the pointer on the screen. */
      if (pgp->psurfColor)
      {
-         IntEngBitBltEx(psoDest,
-                        &pgp->psurfMask->SurfObj,
-                        NULL,
-                        NULL,
-                        NULL,
-                        &rclSurf,
-                        (POINTL*)&rclPointer,
-                        NULL,
-                        NULL,
-                        NULL,
-                        ROP3_TO_ROP4(SRCAND),
-                        FALSE);
-         IntEngBitBltEx(psoDest,
-                        &pgp->psurfColor->SurfObj,
-                        NULL,
-                        NULL,
-                        NULL,
-                        &rclSurf,
-                        (POINTL*)&rclPointer,
-                        NULL,
-                        NULL,
-                        NULL,
-                        ROP3_TO_ROP4(SRCINVERT),
-                        FALSE);
+         IntEngBitBlt(psoDest,
+                      &pgp->psurfMask->SurfObj,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &rclSurf,
+                      (POINTL*)&rclPointer,
+                      NULL,
+                      NULL,
+                      NULL,
+                      ROP3_TO_ROP4(SRCAND));
+         IntEngBitBlt(psoDest,
+                      &pgp->psurfColor->SurfObj,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &rclSurf,
+                      (POINTL*)&rclPointer,
+                      NULL,
+                      NULL,
+                      NULL,
+                      ROP3_TO_ROP4(SRCINVERT));
      }
      else
      {
-         IntEngBitBltEx(psoDest,
-                        &pgp->psurfMask->SurfObj,
-                        NULL,
-                        NULL,
-                        NULL,
-                        &rclSurf,
-                        (POINTL*)&rclPointer,
-                        NULL,
-                        NULL,
-                        NULL,
-                        ROP3_TO_ROP4(SRCAND),
-                        FALSE);
+         IntEngBitBlt(psoDest,
+                      &pgp->psurfMask->SurfObj,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &rclSurf,
+                      (POINTL*)&rclPointer,
+                      NULL,
+                      NULL,
+                      NULL,
+                      ROP3_TO_ROP4(SRCAND));
  
          rclPointer.top += pgp->Size.cy;
  
-         IntEngBitBltEx(psoDest,
-                        &pgp->psurfMask->SurfObj,
-                        NULL,
-                        NULL,
-                        NULL,
-                        &rclSurf,
-                        (POINTL*)&rclPointer,
-                        NULL,
-                        NULL,
-                        NULL,
-                        ROP3_TO_ROP4(SRCINVERT),
-                        FALSE);
+         IntEngBitBlt(psoDest,
+                      &pgp->psurfMask->SurfObj,
+                      NULL,
+                      NULL,
+                      NULL,
+                      &rclSurf,
+                      (POINTL*)&rclPointer,
+                      NULL,
+                      NULL,
+                      NULL,
+                      ROP3_TO_ROP4(SRCINVERT));
      }
  }
  
@@@ -353,7 -337,7 +337,7 @@@ EngSetPointerShape
          rectl.bottom = sizel.cy;
  
          /* Calculate lDelta for our surfaces. */
-         lDelta = DIB_GetDIBWidthBytes(sizel.cx, 
+         lDelta = WIDTH_BYTES_ALIGN32(sizel.cx, 
                                        BitsPerFormat(pso->iBitmapFormat));
  
          /* Create a bitmap for saving the pixels under the cursor. */
  
          /* Create a bitmap to copy the color bitmap to */
          hbmColor = EngCreateBitmap(psoColor->sizlBitmap,
-                                    lDelta,
-                                    pso->iBitmapFormat,
-                                    BMF_TOPDOWN | BMF_NOZEROINIT,
-                                    NULL);
+                            lDelta,
+                            pso->iBitmapFormat,
+                            BMF_TOPDOWN | BMF_NOZEROINIT,
+                            NULL);
          psurfColor = SURFACE_ShareLockSurface(hbmColor);
          if (!psurfColor) goto failure;
  
@@@ -540,28 -524,13 +524,13 @@@ EngMovePointer
              prcl->right = prcl->left + pgp->Size.cx;
              prcl->bottom = prcl->top + pgp->Size.cy;
          }
-     } 
+     }
      else if (prcl != NULL)
      {
          prcl->left = prcl->top = prcl->right = prcl->bottom = -1;
      }
  }
  
- VOID APIENTRY
- IntEngMovePointer(
-     IN SURFOBJ *pso,
-     IN LONG x,
-     IN LONG y,
-     IN RECTL *prcl)
- {
-     SURFACE *psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj);
-     PPDEVOBJ ppdev = (PPDEVOBJ)pso->hdev;
-     SURFACE_LockBitmapBits(psurf);
-     ppdev->pfnMovePointer(pso, x, y, prcl);
-     SURFACE_UnlockBitmapBits(psurf);
- }
  ULONG APIENTRY
  IntEngSetPointerShape(
     IN SURFOBJ *pso,
     IN FLONG fl)
  {
      ULONG ulResult = SPS_DECLINE;
-     SURFACE *psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj);
      PFN_DrvSetPointerShape pfnSetPointerShape;
      PPDEVOBJ ppdev = GDIDEV(pso);
  
      pfnSetPointerShape = GDIDEVFUNCS(pso).SetPointerShape;
  
-     SURFACE_LockBitmapBits(psurf);
      if (pfnSetPointerShape)
      {
          ulResult = pfnSetPointerShape(pso,
          ppdev->pfnMovePointer = EngMovePointer;
      }
  
-     SURFACE_UnlockBitmapBits(psurf);
      return ulResult;
  }
  
@@@ -649,10 -614,14 +614,14 @@@ GreSetPointerShape
          return 0;
      }
  
-     psurf = pdc->dclevel.pSurface;
+     ASSERT(pdc->dctype == DCTYPE_DIRECT);
+     EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
+     /* We're not sure DC surface is the good one */
+     psurf = pdc->ppdev->pSurface;
      if (!psurf)
      {
          DPRINT1("DC has no surface.\n");
+         EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
          DC_UnlockDc(pdc);
          return 0;
      }
      {
          /* We have one, lock it */
          psurfColor = SURFACE_ShareLockSurface(hbmColor);
-         
          if (psurfColor)
          {
              /* Create an XLATEOBJ, no mono support */
      if (psurfMask)
          SURFACE_ShareUnlockSurface(psurfMask);
  
+     EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
      /* Unlock the DC */
      DC_UnlockDc(pdc);
  
@@@ -724,12 -695,23 +695,23 @@@ GreMovePointer
          DPRINT1("Failed to lock the DC.\n");
          return;
      }
+     ASSERT(pdc->dctype == DCTYPE_DIRECT);
+     /* Acquire PDEV lock */
+     EngAcquireSemaphore(pdc->ppdev->hsemDevLock);
  
-     /* Store the cursor exclude position in the PDEV */
-     prcl = &pdc->ppdev->Pointer.Exclude;
+     /* Check if we need to move it */
+     if(pdc->ppdev->SafetyRemoveLevel == 0)
+     {
+         /* Store the cursor exclude position in the PDEV */
+         prcl = &pdc->ppdev->Pointer.Exclude;
+         /* Call Eng/Drv function */
+         pdc->ppdev->pfnMovePointer(&pdc->ppdev->pSurface->SurfObj, x, y, prcl);
+     }
  
-     /* Call Eng/Drv function */
-     IntEngMovePointer(&pdc->dclevel.pSurface->SurfObj, x, y, prcl);
+     /* Release PDEV lock */
+     EngReleaseSemaphore(pdc->ppdev->hsemDevLock);
  
      /* Unlock the DC */
      DC_UnlockDc(pdc);
  #define NDEBUG
  #include <debug.h>
  
static BOOL APIENTRY FillSolidUnlocked(SURFOBJ *pso, PRECTL pRect, ULONG iColor)
BOOL APIENTRY FillSolid(SURFOBJ *pso, PRECTL pRect, ULONG iColor)
  {
    LONG y;
    ULONG LineWidth;
  
    ASSERT(pso);
    ASSERT(pRect);
-   MouseSafetyOnDrawStart(pso, pRect->left, pRect->top, pRect->right, pRect->bottom);
    LineWidth  = pRect->right - pRect->left;
    DPRINT(" LineWidth: %d, top: %d, bottom: %d\n", LineWidth, pRect->top, pRect->bottom);
    for (y = pRect->top; y < pRect->bottom; y++)
      DibFunctionsForBitmapFormat[pso->iBitmapFormat].DIB_HLine(
        pso, pRect->left, pRect->right, y, iColor);
    }
-   MouseSafetyOnDrawEnd(pso);
    return TRUE;
  }
  
- BOOL APIENTRY FillSolid(SURFOBJ *pso, PRECTL pRect, ULONG iColor)
- {
-   SURFACE *psurf;
-   BOOL Result;
-   psurf = CONTAINING_RECORD(pso, SURFACE, SurfObj);
-   SURFACE_LockBitmapBits(psurf);
-   Result = FillSolidUnlocked(pso, pRect, iColor);
-   SURFACE_UnlockBitmapBits(psurf);
-   return Result;
- }
  BOOL APIENTRY
  EngPaintRgn(SURFOBJ *pso, CLIPOBJ *ClipRegion, ULONG iColor, MIX Mix,
              BRUSHOBJ *BrushObj, POINTL *BrushPoint)
@@@ -85,7 -71,7 +71,7 @@@
  
      if (ClipRegion->iDComplexity == DC_RECT)
      {
-       FillSolidUnlocked(pso, &(ClipRegion->rclBounds), iColor);
+       FillSolid(pso, &(ClipRegion->rclBounds), iColor);
      } else {
  
        /* Enumerate all the rectangles and draw them */
@@@ -94,7 -80,7 +80,7 @@@
        do {
          EnumMore = CLIPOBJ_bEnum(ClipRegion, sizeof(RectEnum), (PVOID) &RectEnum);
          for (i = 0; i < RectEnum.c; i++) {
-           FillSolidUnlocked(pso, RectEnum.arcl + i, iColor);
+           FillSolid(pso, RectEnum.arcl + i, iColor);
          }
        } while (EnumMore);
      }
@@@ -136,18 -122,11 +122,11 @@@ IntEngPaint(IN SURFOBJ *pso
  
    DPRINT("pso->iType == %d\n", pso->iType);
    /* Is the surface's Paint function hooked? */
-   if((pso->iType!=STYPE_BITMAP) && (psurf->flHooks & HOOK_PAINT))
+   if((pso->iType!=STYPE_BITMAP) && (psurf->flags & HOOK_PAINT))
    {
      // Call the driver's DrvPaint
-     SURFACE_LockBitmapBits(psurf);
-     MouseSafetyOnDrawStart(pso, ClipRegion->rclBounds.left,
-                                ClipRegion->rclBounds.top, ClipRegion->rclBounds.right,
-                                                        ClipRegion->rclBounds.bottom);
      ret = GDIDEVFUNCS(pso).Paint(
        pso, ClipRegion, Brush, BrushOrigin, Mix);
-     MouseSafetyOnDrawEnd(pso);
-     SURFACE_UnlockBitmapBits(psurf);
      return ret;
    }
    return EngPaint(pso, ClipRegion, Brush, BrushOrigin, Mix );
index 0000000,26c0f4b..26c0f4b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,844 +1,844 @@@
+ /*
+  * COPYRIGHT:        See COPYING in the top level directory
+  * PROJECT:          ReactOS kernel
+  * PURPOSE:          Support for physical devices
+  * FILE:             subsystems/win32/win32k/eng/pdevobj.c
+  * PROGRAMER:        Timo Kreuzer (timo.kreuzer@reactos.org)
+  */
+ #include <win32k.h>
+ #include <intrin.h>
+ #define NDEBUG
+ #include <debug.h>
+ PPDEVOBJ gppdevPrimary = NULL;
+ static PPDEVOBJ gppdevList = NULL;
+ static HSEMAPHORE ghsemPDEV;
+ BOOL
+ NTAPI
+ InitPDEVImpl()
+ {
+     ghsemPDEV = EngCreateSemaphore();
+     return TRUE;
+ }
+ PPDEVOBJ
+ PDEVOBJ_AllocPDEV()
+ {
+     PPDEVOBJ ppdev;
+     ppdev = ExAllocatePoolWithTag(PagedPool, sizeof(PDEVOBJ), GDITAG_PDEV);
+     if (!ppdev)
+         return NULL;
+     RtlZeroMemory(ppdev, sizeof(PDEVOBJ));
+     ppdev->cPdevRefs = 1;
+     return ppdev;
+ }
+ VOID
+ NTAPI
+ PDEVOBJ_vRelease(PPDEVOBJ ppdev)
+ {
+     /* Lock loader */
+     EngAcquireSemaphore(ghsemPDEV);
+     /* Decrease reference count */
+     --ppdev->cPdevRefs;
+     ASSERT(ppdev->cPdevRefs >= 0) ;
+     /* Check if references are left */
+     if (ppdev->cPdevRefs == 0)
+     {
+         /* Do we have a surface? */
+         if(ppdev->pSurface)
+         {
+             /* Release the surface and let the driver free it */
+             SURFACE_ShareUnlockSurface(ppdev->pSurface);
+             ppdev->pfn.DisableSurface(ppdev->dhpdev);
+         }
+         /* Do we have a palette? */
+         if(ppdev->ppalSurf)
+         {
+             PALETTE_ShareUnlockPalette(ppdev->ppalSurf);
+         }
+         /* Disable PDEV */
+         ppdev->pfn.DisablePDEV(ppdev->dhpdev);
+         /* Remove it from list */
+         if( ppdev == gppdevList )
+             gppdevList = ppdev->ppdevNext ;
+         else
+         {
+             PPDEVOBJ ppdevCurrent = gppdevList;
+             BOOL found = FALSE ;
+             while (!found && ppdevCurrent->ppdevNext)
+             {
+                 if (ppdevCurrent->ppdevNext == ppdev)
+                     found = TRUE;
+                 else
+                     ppdevCurrent = ppdevCurrent->ppdevNext ;
+             }
+             if(found)
+                 ppdevCurrent->ppdevNext = ppdev->ppdevNext;
+         }
+         /* Is this the primary one ? */
+         if (ppdev == gppdevPrimary)
+             gppdevPrimary = NULL;
+         /* Free it */
+         ExFreePoolWithTag(ppdev, GDITAG_PDEV );
+     }
+     /* Unlock loader */
+     EngReleaseSemaphore(ghsemPDEV);
+ }
+ BOOL
+ NTAPI
+ PDEVOBJ_bEnablePDEV(
+     PPDEVOBJ ppdev,
+     PDEVMODEW pdevmode,
+     PWSTR pwszLogAddress)
+ {
+     PFN_DrvEnablePDEV pfnEnablePDEV;
+     DPRINT1("PDEVOBJ_bEnablePDEV()\n");
+     /* Get the DrvEnablePDEV function */
+     pfnEnablePDEV = ppdev->pldev->pfn.EnablePDEV;
+     /* Call the drivers DrvEnablePDEV function */
+     ppdev->dhpdev = pfnEnablePDEV(pdevmode,
+                                   pwszLogAddress,
+                                   HS_DDI_MAX,
+                                   ppdev->ahsurf,
+                                   sizeof(GDIINFO),
+                                   &ppdev->gdiinfo,
+                                   sizeof(DEVINFO),
+                                   &ppdev->devinfo,
+                                   (HDEV)ppdev,
+                                   ppdev->pGraphicsDevice->pwszDescription,
+                                   ppdev->pGraphicsDevice->DeviceObject);
+     /* Fix up some values */
+     if (ppdev->gdiinfo.ulLogPixelsX == 0)
+         ppdev->gdiinfo.ulLogPixelsX = 96;
+     if (ppdev->gdiinfo.ulLogPixelsY == 0)
+         ppdev->gdiinfo.ulLogPixelsY = 96;
+     /* Setup Palette */
+     GDIOBJ_SetOwnership(ppdev->devinfo.hpalDefault, NULL);
+     ppdev->ppalSurf = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
+     DPRINT1("PDEVOBJ_bEnablePDEV - dhpdev = %p\n", ppdev->dhpdev);
+     return TRUE;
+ }
+ VOID
+ NTAPI
+ PDEVOBJ_vCompletePDEV(
+     PPDEVOBJ ppdev)
+ {
+     /* Call the drivers DrvCompletePDEV function */
+     ppdev->pldev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev);
+ }
+ PSURFACE
+ NTAPI
+ PDEVOBJ_pSurface(
+     PPDEVOBJ ppdev)
+ {
+     HSURF hsurf;
+     /* Check if we already have a surface */
+     if (ppdev->pSurface)
+     {
+         /* Increment reference count */
+         GDIOBJ_IncrementShareCount(&ppdev->pSurface->BaseObject);
+     }
+     else
+     {
+         /* Call the drivers DrvEnableSurface */
+         hsurf = ppdev->pldev->pfn.EnableSurface(ppdev->dhpdev);
+         /* Lock the surface */
+         ppdev->pSurface = SURFACE_ShareLockSurface(hsurf);
+     }
+     DPRINT("PDEVOBJ_pSurface() returning %p\n", ppdev->pSurface);
+     return ppdev->pSurface;
+ }
+ PDEVMODEW
+ NTAPI
+ PDEVOBJ_pdmMatchDevMode(
+     PPDEVOBJ ppdev,
+     PDEVMODEW pdm)
+ {
+     PGRAPHICS_DEVICE pGraphicsDevice;
+     PDEVMODEW pdmCurrent;
+     INT i;
+     DWORD dwFields;
+     pGraphicsDevice = ppdev->pGraphicsDevice;
+     for (i = 0; i < pGraphicsDevice->cDevModes; i++)
+     {
+         pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
+         /* Compare asked DEVMODE fields
+          * Only compare those that are valid in both DEVMODE structs */
+         dwFields = pdmCurrent->dmFields & pdm->dmFields ;
+         /* For now, we only need those */
+         if ((dwFields & DM_BITSPERPEL) &&
+                 (pdmCurrent->dmBitsPerPel != pdm->dmBitsPerPel))
+             continue;
+         if ((dwFields & DM_PELSWIDTH) &&
+                 (pdmCurrent->dmPelsWidth != pdm->dmPelsWidth))
+             continue;
+         if ((dwFields & DM_PELSHEIGHT) &&
+                 (pdmCurrent->dmPelsHeight != pdm->dmPelsHeight))
+             continue;
+         if ((dwFields & DM_DISPLAYFREQUENCY) &&
+                 (pdmCurrent->dmDisplayFrequency != pdm->dmDisplayFrequency))
+             continue;
+         /* Match! Return the DEVMODE */
+         return pdmCurrent;
+     }
+     /* Nothing found */
+     return NULL;
+ }
+ static
+ PPDEVOBJ
+ EngpCreatePDEV(
+     PUNICODE_STRING pustrDeviceName,
+     PDEVMODEW pdm)
+ {
+     PGRAPHICS_DEVICE pGraphicsDevice;
+     PPDEVOBJ ppdev;
+     /* Try to find the GRAPHICS_DEVICE */
+     if (pustrDeviceName)
+     {
+         pGraphicsDevice = EngpFindGraphicsDevice(pustrDeviceName, 0, 0);
+         if (!pGraphicsDevice)
+         {
+             DPRINT1("No GRAPHICS_DEVICE found for %ls!\n",
+                     pustrDeviceName ? pustrDeviceName->Buffer : 0);
+             return NULL;
+         }
+     }
+     else
+     {
+         pGraphicsDevice = gpPrimaryGraphicsDevice;
+     }
+     /* Allocate a new PDEVOBJ */
+     ppdev = PDEVOBJ_AllocPDEV();
+     if (!ppdev)
+     {
+         DPRINT1("failed to allocate a PDEV\n");
+         return NULL;
+     }
+     /* If no DEVMODEW is given, ... */
+     if (!pdm)
+     {
+         /* ... use the device's default one */
+         pdm = pGraphicsDevice->pDevModeList[pGraphicsDevice->iDefaultMode].pdm;
+         DPRINT1("Using iDefaultMode = %ld\n", pGraphicsDevice->iDefaultMode);
+     }
+     /* Try to get a diplay driver */
+     ppdev->pldev = EngLoadImageEx(pdm->dmDeviceName, LDEV_DEVICE_DISPLAY);
+     if (!ppdev->pldev)
+     {
+         DPRINT1("Could not load display driver '%ls'\n",
+                 pGraphicsDevice->pDiplayDrivers);
+         ExFreePoolWithTag(ppdev, GDITAG_PDEV);
+         return NULL;
+     }
+     /* Copy the function table */
+     ppdev->pfn = ppdev->pldev->pfn;
+     /* Set MovePointer function */
+     ppdev->pfnMovePointer = ppdev->pfn.MovePointer;
+     if (!ppdev->pfnMovePointer)
+         ppdev->pfnMovePointer = EngMovePointer;
+     ppdev->pGraphicsDevice = pGraphicsDevice;
+     ppdev->hsemDevLock = EngCreateSemaphore();
+     // Should we change the ative mode of pGraphicsDevice ?
+     ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, pdm) ;
+     /* FIXME! */
+     ppdev->flFlags = PDEV_DISPLAY;
+     /* HACK: Don't use the pointer */
+     ppdev->Pointer.Exclude.right = -1;
+     /* Call the driver to enable the PDEV */
+     if (!PDEVOBJ_bEnablePDEV(ppdev, pdm, NULL))
+     {
+         DPRINT1("Failed to enable PDEV!\n");
+         ASSERT(FALSE);
+     }
+     /* FIXME: this must be done in a better way */
+     pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
+     /* Tell the driver that the PDEV is ready */
+     PDEVOBJ_vCompletePDEV(ppdev);
+     /* Return the PDEV */
+     return ppdev;
+ }
+ VOID
+ NTAPI
+ PDEVOBJ_vSwitchPdev(
+     PPDEVOBJ ppdev,
+     PPDEVOBJ ppdev2)
+ {
+     PDEVOBJ pdevTmp;
+     DWORD tmpStateFlags;
+     /* Exchange data */
+     pdevTmp = *ppdev;
+     /* Exchange driver functions */
+     ppdev->pfn = ppdev2->pfn;
+     ppdev2->pfn = pdevTmp.pfn;
+     /* Exchange LDEVs */
+     ppdev->pldev = ppdev2->pldev;
+     ppdev2->pldev = pdevTmp.pldev;
+     /* Exchange DHPDEV */
+     ppdev->dhpdev = ppdev2->dhpdev;
+     ppdev2->dhpdev = pdevTmp.dhpdev;
+     /* Exchange surfaces and associate them with their new PDEV */
+     ppdev->pSurface = ppdev2->pSurface;
+     ppdev2->pSurface = pdevTmp.pSurface;
+     ppdev->pSurface->SurfObj.hdev = (HDEV)ppdev;
+     ppdev2->pSurface->SurfObj.hdev = (HDEV)ppdev2;
+     /* Exchange devinfo */
+     ppdev->devinfo = ppdev2->devinfo;
+     ppdev2->devinfo = pdevTmp.devinfo;
+     /* Exchange gdiinfo */
+     ppdev->gdiinfo = ppdev2->gdiinfo;
+     ppdev2->gdiinfo = pdevTmp.gdiinfo;
+     /* Exchange DEVMODE */
+     ppdev->pdmwDev = ppdev2->pdmwDev;
+     ppdev2->pdmwDev = pdevTmp.pdmwDev;
+     /* Exchange state flags */
+     tmpStateFlags = ppdev->pGraphicsDevice->StateFlags;
+     ppdev->pGraphicsDevice->StateFlags = ppdev2->pGraphicsDevice->StateFlags;
+     ppdev2->pGraphicsDevice->StateFlags = tmpStateFlags;
+     /* Notify each driver instance of its new HDEV association */
+     ppdev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev);
+     ppdev2->pfn.CompletePDEV(ppdev2->dhpdev, (HDEV)ppdev2);
+ }
+ BOOL
+ NTAPI
+ PDEVOBJ_bSwitchMode(
+     PPDEVOBJ ppdev,
+     PDEVMODEW pdm)
+ {
+     UNICODE_STRING ustrDevice;
+     PPDEVOBJ ppdevTmp;
+     PSURFACE pSurface;
+     BOOL retval = FALSE;
+     /* Lock the PDEV */
+     EngAcquireSemaphore(ppdev->hsemDevLock);
+     /* And everything else */
+     EngAcquireSemaphore(ghsemPDEV);
+     DPRINT1("PDEVOBJ_bSwitchMode, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface);
+     // Lookup the GraphicsDevice + select DEVMODE
+     // pdm = PDEVOBJ_pdmMatchDevMode(ppdev, pdm);
+     /* 1. Temporarily disable the current PDEV */
+     if (!ppdev->pfn.AssertMode(ppdev->dhpdev, FALSE))
+     {
+         DPRINT1("DrvAssertMode failed\n");
+         goto leave;
+     }
+     /* 2. Create new PDEV */
+     RtlInitUnicodeString(&ustrDevice, ppdev->pGraphicsDevice->szWinDeviceName);
+     ppdevTmp = EngpCreatePDEV(&ustrDevice, pdm);
+     if (!ppdevTmp)
+     {
+         DPRINT1("Failed to create a new PDEV\n");
+         goto leave;
+     }
+     /* 3. Create a new surface */
+     pSurface = PDEVOBJ_pSurface(ppdevTmp);
+     if (!pSurface)
+     {
+         DPRINT1("DrvEnableSurface failed\n");
+         goto leave;
+     }
+     /* 4. Get DirectDraw information */
+     /* 5. Enable DirectDraw Not traced */
+     /* 6. Copy old PDEV state to new PDEV instance */
+     /* 7. Switch the PDEVs */
+     PDEVOBJ_vSwitchPdev(ppdev, ppdevTmp);
+     /* 8. Disable DirectDraw */
+     PDEVOBJ_vRelease(ppdevTmp);
+     /* Update primary display capabilities */
+     if(ppdev == gppdevPrimary)
+     {
+         PDEVOBJ_vGetDeviceCaps(ppdev, &GdiHandleTable->DevCaps);
+     }
+     /* Success! */
+     retval = TRUE;
+ leave:
+     /* Unlock PDEV */
+     EngReleaseSemaphore(ppdev->hsemDevLock);
+     EngReleaseSemaphore(ghsemPDEV);
+     DPRINT1("leave, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface);
+     return retval;
+ }
+ PPDEVOBJ
+ NTAPI
+ EngpGetPDEV(
+     PUNICODE_STRING pustrDeviceName)
+ {
+     UNICODE_STRING ustrCurrent;
+     PPDEVOBJ ppdev;
+     PGRAPHICS_DEVICE pGraphicsDevice;
+     /* Acquire PDEV lock */
+     EngAcquireSemaphore(ghsemPDEV);
+     /* If no device name is given, ... */
+     if (!pustrDeviceName && gppdevPrimary)
+     {
+         /* ... use the primary PDEV */
+         ppdev = gppdevPrimary;
+         /* Reference the pdev */
+         InterlockedIncrement(&ppdev->cPdevRefs);
+         goto leave;
+     }
+     /* Loop all present PDEVs */
+     for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext)
+     {
+         /* Get a pointer to the GRAPHICS_DEVICE */
+         pGraphicsDevice = ppdev->pGraphicsDevice;
+         /* Compare the name */
+         RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName);
+         if (RtlEqualUnicodeString(pustrDeviceName, &ustrCurrent, FALSE))
+         {
+             /* Found! Reference the PDEV */
+             InterlockedIncrement(&ppdev->cPdevRefs);
+             break;
+         }
+     }
+     /* Did we find one? */
+     if (!ppdev)
+     {
+         /* No, create a new PDEV */
+         ppdev = EngpCreatePDEV(pustrDeviceName, NULL);
+         if (ppdev)
+         {
+             /* Insert the PDEV into the list */
+             ppdev->ppdevNext = gppdevList;
+             gppdevList = ppdev;
+             /* Set as primary PDEV, if we don't have one yet */
+             if (!gppdevPrimary)
+             {
+                 gppdevPrimary = ppdev;
+                 ppdev->pGraphicsDevice->StateFlags |= DISPLAY_DEVICE_PRIMARY_DEVICE;
+             }
+         }
+     }
+ leave:
+     /* Release PDEV lock */
+     EngReleaseSemaphore(ghsemPDEV);
+     return ppdev;
+ }
+ INT
+ NTAPI
+ PDEVOBJ_iGetColorManagementCaps(PPDEVOBJ ppdev)
+ {
+     INT ret = CM_NONE;
+     if (ppdev->flFlags & PDEV_DISPLAY)
+     {
+         if (ppdev->devinfo.iDitherFormat == BMF_8BPP ||
+             ppdev->devinfo.flGraphicsCaps2 & GCAPS2_CHANGEGAMMARAMP)
+             ret = CM_GAMMA_RAMP;
+     }
+     if (ppdev->devinfo.flGraphicsCaps & GCAPS_CMYKCOLOR)
+         ret |= CM_CMYK_COLOR;
+     if (ppdev->devinfo.flGraphicsCaps & GCAPS_ICM)
+         ret |= CM_DEVICE_ICM;
+     return ret;
+ }
+ VOID
+ NTAPI
+ PDEVOBJ_vGetDeviceCaps(
+     IN PPDEVOBJ ppdev,
+     OUT PDEVCAPS pDevCaps)
+ {
+     PGDIINFO pGdiInfo = &ppdev->gdiinfo;
+     pDevCaps->ulVersion = pGdiInfo->ulVersion;
+     pDevCaps->ulTechnology = pGdiInfo->ulTechnology;
+     pDevCaps->ulHorzSizeM = (pGdiInfo->ulHorzSize + 500) / 1000;
+     pDevCaps->ulVertSizeM = (pGdiInfo->ulVertSize + 500) / 1000;
+     pDevCaps->ulHorzSize = pGdiInfo->ulHorzSize;
+     pDevCaps->ulVertSize = pGdiInfo->ulVertSize;
+     pDevCaps->ulHorzRes = pGdiInfo->ulHorzRes;
+     pDevCaps->ulVertRes = pGdiInfo->ulVertRes;
+     pDevCaps->ulBitsPixel = pGdiInfo->cBitsPixel;
+     if (pDevCaps->ulBitsPixel == 15) pDevCaps->ulBitsPixel = 16;
+     pDevCaps->ulPlanes = pGdiInfo->cPlanes;
+     pDevCaps->ulNumPens = pGdiInfo->ulNumColors;
+     if (pDevCaps->ulNumPens != -1) pDevCaps->ulNumPens *= 5;
+     pDevCaps->ulNumFonts = 0; // PDEVOBJ_cFonts(ppdev);
+     pDevCaps->ulNumColors = pGdiInfo->ulNumColors;
+     pDevCaps->ulRasterCaps = pGdiInfo->flRaster;
+     pDevCaps->ulAspectX = pGdiInfo->ulAspectX;
+     pDevCaps->ulAspectY = pGdiInfo->ulAspectY;
+     pDevCaps->ulAspectXY = pGdiInfo->ulAspectXY;
+     pDevCaps->ulLogPixelsX = pGdiInfo->ulLogPixelsX;
+     pDevCaps->ulLogPixelsY = pGdiInfo->ulLogPixelsY;
+     pDevCaps->ulSizePalette = pGdiInfo->ulNumPalReg;
+     pDevCaps->ulColorRes = pGdiInfo->ulDACRed +
+                            pGdiInfo->ulDACGreen +
+                            pGdiInfo->ulDACBlue;
+     pDevCaps->ulPhysicalWidth = pGdiInfo->szlPhysSize.cx;
+     pDevCaps->ulPhysicalHeight = pGdiInfo->szlPhysSize.cy;
+     pDevCaps->ulPhysicalOffsetX = pGdiInfo->ptlPhysOffset.x;
+     pDevCaps->ulPhysicalOffsetY = pGdiInfo->ptlPhysOffset.y;
+     pDevCaps->ulTextCaps = pGdiInfo->flTextCaps;
+     pDevCaps->ulTextCaps |= (TC_SO_ABLE|TC_UA_ABLE|TC_CP_STROKE|TC_OP_STROKE|TC_OP_CHARACTER);
+     if (pGdiInfo->ulTechnology != DT_PLOTTER)
+         pDevCaps->ulTextCaps |= TC_VA_ABLE;
+     pDevCaps->ulVRefresh = pGdiInfo->ulVRefresh;
+     pDevCaps->ulDesktopHorzRes = pGdiInfo->ulHorzRes;
+     pDevCaps->ulDesktopVertRes = pGdiInfo->ulVertRes;
+     pDevCaps->ulBltAlignment = pGdiInfo->ulBltAlignment;
+     pDevCaps->ulPanningHorzRes = pGdiInfo->ulPanningHorzRes;
+     pDevCaps->ulPanningVertRes = pGdiInfo->ulPanningVertRes;
+     pDevCaps->xPanningAlignment = pGdiInfo->xPanningAlignment;
+     pDevCaps->yPanningAlignment = pGdiInfo->yPanningAlignment;
+     pDevCaps->ulShadeBlend = pGdiInfo->flShadeBlend;
+     pDevCaps->ulColorMgmtCaps = PDEVOBJ_iGetColorManagementCaps(ppdev);
+ }
+ /** Exported functions ********************************************************/
+ LPWSTR
+ APIENTRY
+ EngGetDriverName(IN HDEV hdev)
+ {
+     PPDEVOBJ ppdev = (PPDEVOBJ)hdev;
+     PLDEVOBJ pldev;
+     if (!hdev)
+         return NULL;
+     pldev = ppdev->pldev;
+     ASSERT(pldev);
+     if (!pldev->pGdiDriverInfo)
+         return NULL;
+     return pldev->pGdiDriverInfo->DriverName.Buffer;
+ }
+ INT
+ APIENTRY
+ NtGdiGetDeviceCaps(
+     HDC hdc,
+     INT Index)
+ {
+     PDC pdc;
+     DEVCAPS devcaps;
+     /* Lock the given DC */
+     pdc = DC_LockDc(hdc);
+     if (!pdc)
+     {
+         SetLastWin32Error(ERROR_INVALID_HANDLE);
+         return 0;
+     }
+     /* Get the data */
+     PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps);
+     /* Unlock the DC */
+     DC_UnlockDc(pdc);
+     /* Return capability */
+     switch (Index)
+     {
+         case DRIVERVERSION:
+             return devcaps.ulVersion;
+         case TECHNOLOGY:
+             return devcaps.ulTechnology;
+         case HORZSIZE:
+             return devcaps.ulHorzSize;
+         case VERTSIZE:
+             return devcaps.ulVertSize;
+         case HORZRES:
+             return devcaps.ulHorzRes;
+         case VERTRES:
+             return devcaps.ulVertRes;
+         case LOGPIXELSX:
+             return devcaps.ulLogPixelsX;
+         case LOGPIXELSY:
+             return devcaps.ulLogPixelsY;
+         case BITSPIXEL:
+             return devcaps.ulBitsPixel;
+         case PLANES:
+             return devcaps.ulPlanes;
+         case NUMBRUSHES:
+             return -1;
+         case NUMPENS:
+             return devcaps.ulNumPens;
+         case NUMFONTS:
+             return devcaps.ulNumFonts;
+         case NUMCOLORS:
+             return devcaps.ulNumColors;
+         case ASPECTX:
+             return devcaps.ulAspectX;
+         case ASPECTY:
+             return devcaps.ulAspectY;
+         case ASPECTXY:
+             return devcaps.ulAspectXY;
+         case CLIPCAPS:
+             return CP_RECTANGLE;
+         case SIZEPALETTE:
+             return devcaps.ulSizePalette;
+         case NUMRESERVED:
+             return 20;
+         case COLORRES:
+             return devcaps.ulColorRes;
+         case DESKTOPVERTRES:
+             return devcaps.ulVertRes;
+         case DESKTOPHORZRES:
+             return devcaps.ulHorzRes;
+         case BLTALIGNMENT:
+             return devcaps.ulBltAlignment;
+         case SHADEBLENDCAPS:
+             return devcaps.ulShadeBlend;
+         case COLORMGMTCAPS:
+             return devcaps.ulColorMgmtCaps;
+         case PHYSICALWIDTH:
+             return devcaps.ulPhysicalWidth;
+         case PHYSICALHEIGHT:
+             return devcaps.ulPhysicalHeight;
+         case PHYSICALOFFSETX:
+             return devcaps.ulPhysicalOffsetX;
+         case PHYSICALOFFSETY:
+             return devcaps.ulPhysicalOffsetY;
+         case VREFRESH:
+             return devcaps.ulVRefresh;
+         case RASTERCAPS:
+             return devcaps.ulRasterCaps;
+         case CURVECAPS:
+             return (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
+                     CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
+         case LINECAPS:
+             return (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
+                     LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
+         case POLYGONALCAPS:
+             return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
+                     PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
+         case TEXTCAPS:
+             return devcaps.ulTextCaps;
+         case CAPS1:
+         case PDEVICESIZE:
+         case SCALINGFACTORX:
+         case SCALINGFACTORY:
+         default:
+             return 0;
+     }
+     return 0;
+ }
+ BOOL
+ APIENTRY
+ NtGdiGetDeviceCapsAll(
+     IN HDC hDC,
+     OUT PDEVCAPS pDevCaps)
+ {
+     PDC pdc;
+     DEVCAPS devcaps;
+     BOOL bResult = TRUE;
+     /* Lock the given DC */
+     pdc = DC_LockDc(hDC);
+     if (!pdc)
+     {
+         SetLastWin32Error(ERROR_INVALID_HANDLE);
+         return FALSE;
+     }
+     /* Get the data */
+     PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps);
+     /* Unlock the DC */
+     DC_UnlockDc(pdc);
+     /* Copy data to caller */
+     _SEH2_TRY
+     {
+         ProbeForWrite(pDevCaps, sizeof(DEVCAPS), 1);
+         RtlCopyMemory(pDevCaps, &devcaps, sizeof(DEVCAPS));
+     }
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+         SetLastNtError(_SEH2_GetExceptionCode());
+         bResult = FALSE;
+     }
+     _SEH2_END;
+     return bResult;
+ }
+ DHPDEV
+ APIENTRY
+ NtGdiGetDhpdev(
+     IN HDEV hdev)
+ {
+     PPDEVOBJ ppdev;
+     DHPDEV dhpdev = NULL;
+     /* Check parameter */
+     if (!hdev || (PCHAR)hdev < (PCHAR)MmSystemRangeStart)
+         return NULL;
+     /* Lock PDEV list */
+     EngAcquireSemaphore(ghsemPDEV);
+     /* Walk through the list of PDEVs */
+     for (ppdev = gppdevList;  ppdev; ppdev = ppdev->ppdevNext)
+     {
+         /* Compare with the given HDEV */
+         if (ppdev == hdev)
+         {
+             /* Found the PDEV! Get it's dhpdev and break */
+             dhpdev = ppdev->dhpdev;
+             break;
+         }
+     }
+     /* Unlock PDEV list */
+     EngReleaseSemaphore(ghsemPDEV);
+     return dhpdev;
+ }
+ PSIZEL
+ FASTCALL
+ PDEVOBJ_sizl(PPDEVOBJ ppdev, PSIZEL psizl)
+ {
+     if (ppdev->flFlags & PDEV_META_DEVICE)
+     {
+         psizl->cx = ppdev->ulHorzRes;
+         psizl->cy = ppdev->ulVertRes;
+     }
+     else
+     {
+         psizl->cx = ppdev->gdiinfo.ulHorzRes;
+         psizl->cy = ppdev->gdiinfo.ulVertRes;
+     }
+     return psizl;
+ }
index 0000000,dc8a071..dc8a071
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,99 +1,99 @@@
+ /*
+  * COPYRIGHT:         See COPYING in the top level directory
+  * PROJECT:           ReactOS kernel
+  * PURPOSE:           RLE compression
+  * FILE:              subsystems/win32k/eng/rlecomp.c
+  * PROGRAMER:         Jason Filby
+  */
+ #include <win32k.h>
+ #define NDEBUG
+ #include <debug.h>
+ enum Rle_EscapeCodes
+ {
+     RLE_EOL   = 0, /* End of line */
+     RLE_END   = 1, /* End of bitmap */
+     RLE_DELTA = 2  /* Delta */
+ };
+ VOID DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta, ULONG Format)
+ {
+     INT x = 0;
+     INT y = Size.cy - 1;
+     INT c;
+     INT length;
+     INT width;
+     INT height = Size.cy - 1;
+     BYTE *begin = CompressedBits;
+     BYTE *bits = CompressedBits;
+     BYTE *temp;
+     INT shift = 0;
+     if (Format == BMF_4RLE)
+         shift = 1;
+     else if(Format != BMF_8RLE)
+         return;
+     width = ((Size.cx + shift) >> shift);
+     _SEH2_TRY
+     {
+         while (y >= 0)
+         {
+             length = (*bits++) >> shift;
+             if (length)
+             {
+                 c = *bits++;
+                 while (length--)
+                 {
+                     if (x >= width) break;
+                     temp = UncompressedBits + (((height - y) * Delta) + x);
+                     x++;
+                     *temp = c;
+                 }
+             }
+             else
+             {
+                 length = *bits++;
+                 switch (length)
+                 {
+                 case RLE_EOL:
+                     x = 0;
+                     y--;
+                     break;
+                 case RLE_END:
+                     _SEH2_YIELD(return);
+                 case RLE_DELTA:
+                     x += (*bits++) >> shift;
+                     y -= (*bits++) >> shift;
+                     break;
+                 default:
+                     length = length >> shift;
+                     while (length--)
+                     {
+                         c = *bits++;
+                         if (x < width)
+                         {
+                             temp = UncompressedBits + (((height - y) * Delta) + x);
+                             x++;
+                             *temp = c;
+                         }
+                     }
+                     if ((bits - begin) & 1)
+                     {
+                         bits++;
+                     }
+                 }
+             }
+         }
+     }
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+         DPRINT1("Decoding error\n");
+     }
+     _SEH2_END;
+     return;
+ }
@@@ -69,6 -69,19 +69,19 @@@ EngReleaseSemaphore ( IN HSEMAPHORE hse
    IntGdiReleaseSemaphore ( hsem );
  }
  
+ VOID
+ NTAPI
+ EngAcquireSemaphoreShared(
+     IN HSEMAPHORE hsem)
+ {
+     PTHREADINFO pti;
+     ASSERT(hsem);
+     ExEnterCriticalRegionAndAcquireResourceShared((PERESOURCE)hsem);
+     pti = PsGetThreadWin32Thread(PsGetCurrentThread());
+     if (pti) ++pti->dwEngAcquireCount;
+ }
  /*
   * @implemented
   */
@@@ -462,25 -462,16 +462,16 @@@ IntEngStretchBlt(SURFOBJ *psoDest
  
      /* No success yet */
      ret = FALSE;
-     SURFACE_LockBitmapBits(psurfDest);
-     MouseSafetyOnDrawStart(psoDest, OutputRect.left, OutputRect.top,
-                            OutputRect.right, OutputRect.bottom);
  
      if (UsesSource)
      {
          psurfSource = CONTAINING_RECORD(psoSource, SURFACE, SurfObj);
-         if (psoSource != psoDest)
-         {
-             SURFACE_LockBitmapBits(psurfSource);
-         }
-         MouseSafetyOnDrawStart(psoSource, InputRect.left, InputRect.top,
-                                InputRect.right, InputRect.bottom);
      }
  
      /* Prepare color adjustment */
  
      /* Call the driver's DrvStretchBlt if available */
-     if (psurfDest->flHooks & HOOK_STRETCHBLTROP)
+     if (psurfDest->flags & HOOK_STRETCHBLTROP)
      {
          /* Drv->StretchBltROP (look at http://www.osronline.com/ddkx/graphics/ddifncs_0z3b.htm ) */
          ret = GDIDEVFUNCS(psoDest).StretchBltROP(psoDest,
                                 ROP);
      }
  
-     if (UsesSource)
-     {
-         MouseSafetyOnDrawEnd(psoSource);
-         if (psoSource != psoDest)
-         {
-             SURFACE_UnlockBitmapBits(psurfSource);
-         }
-     }
-     MouseSafetyOnDrawEnd(psoDest);
-     SURFACE_UnlockBitmapBits(psurfDest);
      return ret;
  }
  
@@@ -3,7 -3,8 +3,8 @@@
   * PROJECT:           ReactOS kernel
   * PURPOSE:           GDI Driver Surace Functions
   * FILE:              subsys/win32k/eng/surface.c
-  * PROGRAMER:         Jason Filby
+  * PROGRAMERS:        Jason Filby
+  *                    Timo Kreuzer
   * REVISION HISTORY:
   *                 3/7/1999: Created
   *                 9/11/2000: Updated to handle real pixel packed bitmaps (UPDATE TO DATE COMPLETED)
  #define NDEBUG
  #include <debug.h>
  
- enum Rle_EscapeCodes
- {
-     RLE_EOL   = 0, /* End of line */
-     RLE_END   = 1, /* End of bitmap */
-     RLE_DELTA = 2  /* Delta */
- };
+ ULONG giUniqueSurface = 0;
  
- INT FASTCALL BitsPerFormat(ULONG Format)
+ UCHAR
+ gajBitsPerFormat[11] =
  {
-     switch (Format)
-     {
-         case BMF_1BPP:
-             return 1;
-         case BMF_4BPP:
-             /* Fall through */
-         case BMF_4RLE:
-             return 4;
-         case BMF_8BPP:
-             /* Fall through */
-         case BMF_8RLE:
-             return 8;
-         case BMF_16BPP:
-             return 16;
-         case BMF_24BPP:
-             return 24;
+     0, /*  0: unused */
+     1, /*  1: BMF_1BPP */
+     4, /*  2: BMF_4BPP */
+     8, /*  3: BMF_8BPP */
+    16, /*  4: BMF_16BPP */
+    24, /*  5: BMF_24BPP */
+    32, /*  6: BMF_32BPP */
+     4, /*  7: BMF_4RLE */
+     8, /*  8: BMF_8RLE */
+     0, /*  9: BMF_JPEG */
+     0, /* 10: BMF_PNG */
+ };
  
-         case BMF_32BPP:
-             return 32;
-         default:
-             return 0;
-     }
- }
  
  ULONG FASTCALL BitmapFormat(WORD Bits, DWORD Compression)
  {
      }
  }
  
- BOOL INTERNAL_CALL
+ BOOL
+ INTERNAL_CALL
  SURFACE_Cleanup(PVOID ObjectBody)
  {
      PSURFACE psurf = (PSURFACE)ObjectBody;
      PVOID pvBits = psurf->SurfObj.pvBits;
+     NTSTATUS Status;
  
-     /* If this is an API bitmap, free the bits */
-     if (pvBits != NULL &&
-         (psurf->flFlags & BITMAPOBJ_IS_APIBITMAP))
+     /* Check if the surface has bits */
+     if (pvBits)
      {
-         /* Check if we have a DIB section */
-         if (psurf->hSecure)
+         /* Only bitmaps can have bits */
+         ASSERT(psurf->SurfObj.iType == STYPE_BITMAP);
+         /* Check if it is a DIB section */
+         if (psurf->hDIBSection)
          {
-             // FIXME: IMPLEMENT ME!
-             // MmUnsecureVirtualMemory(psurf->hSecure);
-             if (psurf->hDIBSection)
+             /* Unsecure the memory */
+             EngUnsecureMem(psurf->hSecure);
+             /* Calculate the real start of the section */
+             pvBits = (PVOID)((ULONG_PTR)pvBits - psurf->dwOffset);
+             /* Unmap the section */
+             Status = MmUnmapViewOfSection(PsGetCurrentProcess(), pvBits);
+             if (!NT_SUCCESS(Status))
              {
-                 /* DIB was created from a section */
-                 NTSTATUS Status;
-                 pvBits = (PVOID)((ULONG_PTR)pvBits - psurf->dwOffset);
-                 Status = ZwUnmapViewOfSection(NtCurrentProcess(), pvBits);
-                 if (!NT_SUCCESS(Status))
-                 {
-                     DPRINT1("Could not unmap section view!\n");
-                     // Should we BugCheck here?
-                 }
+                 DPRINT1("Could not unmap section view!\n");
+                 // Should we BugCheck here?
+                 ASSERT(FALSE);
              }
-             else
+         }
+         else if (psurf->SurfObj.fjBitmap & BMF_USERMEM)
+         {
+             /* Bitmap was allocated from usermode memory */
+             EngFreeUserMem(pvBits);
+         }
+         else if (psurf->SurfObj.fjBitmap & BMF_KMSECTION)
+         {
+             /* Bitmap was allocated from a kernel section */
+             if (!EngFreeSectionMem(NULL, pvBits))
              {
-                 /* DIB was allocated */
-                 EngFreeUserMem(pvBits);
+                 DPRINT1("EngFreeSectionMem failed for %p!\n", pvBits);
+                 // Should we BugCheck here?
+                 ASSERT(FALSE);
              }
          }
-         else
+         else if (psurf->SurfObj.fjBitmap & BMF_RLE_HACK)
          {
-             // FIXME: use TAG
-             ExFreePool(psurf->SurfObj.pvBits);
+             /* HACK: Free RLE decompressed bits */
+             EngFreeMem(pvBits);
          }
-         if (psurf->hDIBPalette != NULL)
+         else
          {
-             GreDeleteObject(psurf->hDIBPalette);
+             /* There should be nothing to free */
+             ASSERT(psurf->SurfObj.fjBitmap & BMF_DONT_FREE);
          }
      }
  
-     if (NULL != psurf->BitsLock)
-     {
-         ExFreePoolWithTag(psurf->BitsLock, TAG_SURFACE);
-         psurf->BitsLock = NULL;
-     }
-     return TRUE;
- }
- BOOL INTERNAL_CALL
- SURFACE_InitBitsLock(PSURFACE psurf)
- {
-     psurf->BitsLock = ExAllocatePoolWithTag(NonPagedPool,
-                           sizeof(FAST_MUTEX),
-                           TAG_SURFACE);
-     if (NULL == psurf->BitsLock)
+     /* Free palette */
+     if(psurf->ppal)
      {
-         return FALSE;
+         PALETTE_ShareUnlockPalette(psurf->ppal);
      }
  
-     ExInitializeFastMutex(psurf->BitsLock);
      return TRUE;
  }
  
- void INTERNAL_CALL
- SURFACE_CleanupBitsLock(PSURFACE psurf)
- {
-     if (NULL != psurf->BitsLock)
-     {
-         ExFreePoolWithTag(psurf->BitsLock, TAG_SURFACE);
-         psurf->BitsLock = NULL;
-     }
- }
  
- /*
-  * @implemented
-  */
- HBITMAP APIENTRY
EngCreateDeviceBitmap(IN DHSURF dhsurf,
-                       IN SIZEL Size,
-                       IN ULONG Format)
+ PSURFACE
+ NTAPI
+ SURFACE_AllocSurface(
+     IN ULONG iType,
    IN ULONG cx,
+     IN ULONG cy,
+     IN ULONG iFormat)
  {
-     HBITMAP NewBitmap;
+     PSURFACE psurf;
      SURFOBJ *pso;
  
-     NewBitmap = EngCreateBitmap(Size, DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format)), Format, 0, NULL);
-     if (!NewBitmap)
-     {
-         DPRINT1("EngCreateBitmap failed\n");
-         return 0;
-     }
-     pso = EngLockSurface((HSURF)NewBitmap);
-     if (!pso)
+     /* Verify format */
+     if (iFormat < BMF_1BPP || iFormat > BMF_PNG)
      {
-         DPRINT1("EngLockSurface failed on newly created bitmap!\n");
-         GreDeleteObject(NewBitmap);
+         DPRINT1("Invalid bitmap format: %ld\n", iFormat);
          return NULL;
      }
  
-     pso->dhsurf = dhsurf;
-     EngUnlockSurface(pso);
-     return NewBitmap;
- }
+     /* Allocate a SURFACE object */
+     psurf = (PSURFACE)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP);
  
- BOOL DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta, ULONG Format)
- {
-     INT x = 0;
-     INT y = Size.cy - 1;
-     INT c;
-     INT length;
-     INT width;
-     INT height = Size.cy - 1;
-     BYTE *begin = CompressedBits;
-     BYTE *bits = CompressedBits;
-     BYTE *temp;
-     INT shift = 0;
-     if (Format == BMF_4RLE)
-         shift = 1;
-     else if(Format != BMF_8RLE)
-         return FALSE;
-     width = ((Size.cx + shift) >> shift);
-     _SEH2_TRY
-     {
-         while (y >= 0)
-         {
-             length = (*bits++) >> shift;
-             if (length)
-             {
-                 c = *bits++;
-                 while (length--)
-                 {
-                     if (x >= width) break;
-                     temp = UncompressedBits + (((height - y) * Delta) + x);
-                     x++;
-                     *temp = c;
-                 }
-             }
-             else
-             {
-                 length = *bits++;
-                 switch (length)
-                 {
-                 case RLE_EOL:
-                     x = 0;
-                     y--;
-                     break;
-                 case RLE_END:
-                     _SEH2_YIELD(return TRUE);
-                 case RLE_DELTA:
-                     x += (*bits++) >> shift;
-                     y -= (*bits++) >> shift;
-                     break;
-                 default:
-                     length = length >> shift;
-                     while (length--)
-                     {
-                         c = *bits++;
-                         if (x < width)
-                         {
-                             temp = UncompressedBits + (((height - y) * Delta) + x);
-                             x++;
-                             *temp = c;
-                         }
-                     }
-                     if ((bits - begin) & 1)
-                     {
-                         bits++;
-                     }
-                 }
-             }
-         }
-     }
-     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     if (psurf)
      {
-         DPRINT1("Decoding error\n");
-         _SEH2_YIELD(return FALSE);
+         /* Initialize the basic fields */
+         pso = &psurf->SurfObj;
+         pso->hsurf = psurf->BaseObject.hHmgr;
+         pso->sizlBitmap.cx = cx;
+         pso->sizlBitmap.cy = cy;
+         pso->iBitmapFormat = iFormat;
+         pso->iType = iType;
+         pso->iUniq = InterlockedIncrement((PLONG)&giUniqueSurface);
+         /* Assign a default palette and increment its reference count */
+         psurf->ppal = appalSurfaceDefault[iFormat];
+         GDIOBJ_IncrementShareCount(&psurf->ppal->BaseObject);
      }
-     _SEH2_END;
  
-     return TRUE;
+     return psurf;
  }
  
- HBITMAP FASTCALL
- IntCreateBitmap(IN SIZEL Size,
-                 IN LONG Width,
-                 IN ULONG Format,
-                 IN ULONG Flags,
-                 IN PVOID Bits)
+ BOOL
+ NTAPI
+ SURFACE_bSetBitmapBits(
+     IN PSURFACE psurf,
+     IN USHORT fjBitmap,
+     IN ULONG ulWidth,
+     IN PVOID pvBits OPTIONAL)
  {
-     HBITMAP hbmp;
-     SURFOBJ *pso;
-     PSURFACE psurf;
-     PVOID UncompressedBits;
-     ULONG UncompressedFormat;
+     SURFOBJ *pso = &psurf->SurfObj;
+     PVOID pvSection;
+     UCHAR cBitsPixel;
  
-     if (Format == 0)
-         return 0;
+     /* Only bitmaps can have bits */
+     ASSERT(psurf->SurfObj.iType == STYPE_BITMAP);
  
-     psurf = SURFACE_AllocSurfaceWithHandle();
-     if (psurf == NULL)
-     {
-         return 0;
-     }
-     hbmp = psurf->BaseObject.hHmgr;
+     /* Get bits per pixel from the format */
+     cBitsPixel = gajBitsPerFormat[pso->iBitmapFormat];
  
-     if (! SURFACE_InitBitsLock(psurf))
+     /* Is a width in bytes given? */
+     if (ulWidth)
      {
-         SURFACE_UnlockSurface(psurf);
-         SURFACE_FreeSurfaceByHandle(hbmp);
-         return 0;
+         /* Align the width (Windows compatibility, drivers expect that) */
+         ulWidth = WIDTH_BYTES_ALIGN32((ulWidth << 3) / cBitsPixel, cBitsPixel);
      }
-     pso = &psurf->SurfObj;
+       else
+       {
+         /* Calculate width from the bitmap width in pixels */
+         ulWidth = WIDTH_BYTES_ALIGN32(pso->sizlBitmap.cx, cBitsPixel);
+       }
  
-     if (Format == BMF_4RLE)
-     {
-         pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_4BPP));
-         pso->cjBits = pso->lDelta * Size.cy;
-         UncompressedFormat = BMF_4BPP;
-         UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
-         DecompressBitmap(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta, Format);
-     }
-     else if (Format == BMF_8RLE)
-     {
-         pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(BMF_8BPP));
-         pso->cjBits = pso->lDelta * Size.cy;
-         UncompressedFormat = BMF_8BPP;
-         UncompressedBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
-         DecompressBitmap(Size, (BYTE *)Bits, (BYTE *)UncompressedBits, pso->lDelta, Format);
-     }
-     else
-     {
-         pso->lDelta = abs(Width);
-         pso->cjBits = pso->lDelta * Size.cy;
-         UncompressedBits = Bits;
-         UncompressedFormat = Format;
-     }
+     /* Calculate the bitmap size in bytes */
+     pso->cjBits = ulWidth * pso->sizlBitmap.cy;
  
-     if (UncompressedBits != NULL)
+     /* Did the caller provide bits? */
+     if (pvBits)
      {
-         pso->pvBits = UncompressedBits;
+         /* Yes, so let him free it */
+         fjBitmap |= BMF_DONT_FREE;
      }
-     else
+     else if (pso->cjBits)
      {
-         if (pso->cjBits == 0)
+         /* We must allocate memory, check what kind */
+         if (fjBitmap & BMF_USERMEM)
          {
-             pso->pvBits = NULL;
+             /* User mode memory was requested */
+             pvBits = EngAllocUserMem(pso->cjBits, 0);
          }
          else
          {
-             if (0 != (Flags & BMF_USERMEM))
-             {
-                 pso->pvBits = EngAllocUserMem(pso->cjBits, 0);
-             }
-             else
-             {
-                 pso->pvBits = EngAllocMem(0 != (Flags & BMF_NOZEROINIT) ?
-                                                   0 : FL_ZERO_MEMORY,
-                                               pso->cjBits, TAG_DIB);
-             }
-             if (pso->pvBits == NULL)
-             {
-                 SURFACE_UnlockSurface(psurf);
-                 SURFACE_FreeSurfaceByHandle(hbmp);
-                 SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-                 return 0;
-             }
+             /* Use a kernel mode section */
+             fjBitmap |= BMF_KMSECTION;
+             pvBits = EngAllocSectionMem(&pvSection,
+                                         (fjBitmap & BMF_NOZEROINIT) ?
+                                                 0 : FL_ZERO_MEMORY,
+                                         pso->cjBits, TAG_DIB);
+             /* Free the section already, but keep the mapping */
+             if (pvBits) EngFreeSectionMem(pvSection, NULL);
          }
+         /* Check for failure */
+         if (!pvBits) return FALSE;
      }
  
-     if (0 == (Flags & BMF_TOPDOWN))
+     /* Set pvBits, pvScan0 and lDelta */
+     pso->pvBits = pvBits;
+     if (fjBitmap & BMF_TOPDOWN)
      {
-         pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - pso->lDelta);
-         pso->lDelta = - pso->lDelta;
+         /* Topdown is the normal way */
+         pso->pvScan0 = pso->pvBits;
+         pso->lDelta = ulWidth;
      }
      else
      {
-         pso->pvScan0 = pso->pvBits;
+         /* Inversed bitmap (bottom up) */
+         pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ulWidth);
+         pso->lDelta = -ulWidth;
      }
  
-     pso->dhsurf = 0; /* device managed surface */
-     pso->hsurf = (HSURF)hbmp;
-     pso->dhpdev = NULL;
-     pso->hdev = NULL;
-     pso->sizlBitmap = Size;
-     pso->iBitmapFormat = UncompressedFormat;
-     pso->iType = STYPE_BITMAP;
-     pso->fjBitmap = Flags & (BMF_TOPDOWN | BMF_NOZEROINIT);
-     pso->iUniq = 0;
-     psurf->flHooks = 0;
-     psurf->flFlags = 0;
-     psurf->dimension.cx = 0;
-     psurf->dimension.cy = 0;
-     
-     psurf->hSecure = NULL;
-     psurf->hDIBSection = NULL;
-     SURFACE_UnlockSurface(psurf);
+     pso->fjBitmap = fjBitmap;
  
-     return hbmp;
+     /* Success */
+     return TRUE;
  }
  
- /* Name gleaned from C++ symbol information for SURFMEM::bInitDIB */
- typedef struct _DEVBITMAPINFO
- {
-     ULONG Format;
-     ULONG Width;
-     ULONG Height;
-     ULONG Flags;
-     ULONG Size;
- } DEVBITMAPINFO, *PDEVBITMAPINFO;
- SURFOBJ*
- FASTCALL
- SURFMEM_bCreateDib(IN PDEVBITMAPINFO BitmapInfo,
-                    IN PVOID Bits)
+ HBITMAP
+ APIENTRY
+ EngCreateBitmap(
+     IN SIZEL sizl,
+     IN LONG lWidth,
+     IN ULONG iFormat,
+     IN ULONG fl,
+     IN PVOID pvBits)
  {
-     BOOLEAN Compressed = FALSE;
-     ULONG ScanLine = 0; // Compiler is dumb
-     ULONG Size;
-     SURFOBJ *pso;
      PSURFACE psurf;
-     SIZEL LocalSize;
-     BOOLEAN AllocatedLocally = FALSE;
-     PVOID DecompressedBits = NULL;
-     /*
-      * First, check the format so we can get the aligned scanline width.
-      * RLE and the newer fancy-smanshy JPG/PNG support do NOT have scanlines
-      * since they are compressed surfaces!
-      */
-     switch (BitmapInfo->Format)
-     {
-         case BMF_1BPP:
-             ScanLine = ((BitmapInfo->Width + 31) & ~31) >> 3;
-             break;
-         case BMF_4BPP:
-             ScanLine = ((BitmapInfo->Width + 7) & ~7) >> 1;
-             break;
-         case BMF_8BPP:
-             ScanLine = (BitmapInfo->Width + 3) & ~3;
-             break;
-         case BMF_16BPP:
-             ScanLine = ((BitmapInfo->Width + 1) & ~1) << 1;
-             break;
-         case BMF_24BPP:
-             ScanLine = ((BitmapInfo->Width * 3) + 3) & ~3;
-             break;
-         case BMF_32BPP:
-             ScanLine = BitmapInfo->Width << 2;
-             break;
-         case BMF_8RLE:
-             ScanLine = (BitmapInfo->Width + 3) & ~3;
-             Compressed = TRUE;
-             break;
-         case BMF_4RLE:
-             ScanLine = ((BitmapInfo->Width + 7) & ~7) >> 1;
-             Compressed = TRUE;
-             break;
-         case BMF_JPEG:
-         case BMF_PNG:
-             ASSERT(FALSE); // ENGDDI shouldn't be creating PNGs for drivers ;-)
-             DPRINT1("No support for JPEG and PNG formats\n");
-             return NULL;
-         default:
-             DPRINT1("Invalid bitmap format\n");
-             return NULL;
-     }
-     /* Save local bitmap size */
-     LocalSize.cy = BitmapInfo->Height;
-     LocalSize.cx = BitmapInfo->Width;
-     /* Does the device manage its own surface? */
-     if (!Bits)
-     {
-         /* We need to allocate bits for the caller, figure out the size */
-         if (Compressed)
-         {
-             /* Note: we should not be seeing this scenario from ENGDDI */
-             ASSERT(FALSE);
-             DPRINT1("RLE compressed bitmap requested with no valid bitmap bits\n");
-             return NULL;
-         }
-         else
-         {
-             /* The height times the bytes for each scanline */
-             Size = BitmapInfo->Height * ScanLine;
-         }
-         
-         if (Size)
-         {
-             /* Check for allocation flag */
-             if (BitmapInfo->Flags & BMF_USERMEM)
-             {
-                 /* Get the bits from user-mode memory */
-                 Bits = EngAllocUserMem(Size, 'mbuG');
-             }
-             else
-             {
-                 /* Get kernel bits (zeroed out if requested) */
-                 Bits = EngAllocMem((BitmapInfo->Flags & BMF_NOZEROINIT) ? 0 : FL_ZERO_MEMORY,
-                                    Size,
-                                    TAG_DIB);
-             }
-             AllocatedLocally = TRUE;
-             /* Bail out if that failed */
-             if (!Bits) return NULL;
-         }
-     }
-     else
-     {
-         /* Should not have asked for user memory */
-         ASSERT((BitmapInfo->Flags & BMF_USERMEM) == 0);
-         if (Compressed)
-         {
-             DecompressedBits = EngAllocMem(FL_ZERO_MEMORY, BitmapInfo->Height * ScanLine, TAG_DIB);
-             if(!DecompressedBits)
-                 return NULL;
-             if(!DecompressBitmap(LocalSize, (BYTE *)Bits, (BYTE *)DecompressedBits, ScanLine, BitmapInfo->Format))
-             {
-                 EngFreeMem(DecompressedBits);
-                 return NULL;
-             }
-             BitmapInfo->Format = (BitmapInfo->Format == BMF_4RLE) ? BMF_4BPP : BMF_8BPP;
-         }
-     }
+     HBITMAP hbmp;
  
-     /* Allocate the actual surface object structure */
-     psurf = SURFACE_AllocSurfaceWithHandle();
+     /* Allocate a surface */
+     psurf = SURFACE_AllocSurface(STYPE_BITMAP, sizl.cx, sizl.cy, iFormat);
      if (!psurf)
      {
-         if(Bits && AllocatedLocally)
-         {
-             if(BitmapInfo->Flags & BMF_USERMEM)
-                 EngFreeUserMem(Bits);
-             else
-                 EngFreeMem(Bits);
-         }
-         if (DecompressedBits)
-             EngFreeMem(DecompressedBits);
+         DPRINT1("SURFACE_AllocSurface failed.\n");
          return NULL;
      }
  
-     /* Lock down the surface */
-     if (!SURFACE_InitBitsLock(psurf))
+     /* Get the handle for the bitmap */
+     hbmp = (HBITMAP)psurf->SurfObj.hsurf;
+     /* Set the bitmap bits */
+     if (!SURFACE_bSetBitmapBits(psurf, fl, lWidth, pvBits))
      {
          /* Bail out if that failed */
-         SURFACE_UnlockSurface(psurf);
-         SURFACE_FreeSurfaceByHandle(psurf->BaseObject.hHmgr);
+         DPRINT1("SURFACE_bSetBitmapBits failed.\n");
+         SURFACE_FreeSurfaceByHandle(hbmp);
          return NULL;
      }
  
-     /* We should now have our surface object */
-     pso = &psurf->SurfObj;
+     /* Set public ownership */
+     GDIOBJ_SetOwnership(hbmp, NULL);
  
-     /* Save format and flags */
-     pso->iBitmapFormat = BitmapInfo->Format;
-     pso->fjBitmap = BitmapInfo->Flags & (BMF_TOPDOWN | BMF_UMPDMEM | BMF_USERMEM);
-     /* Save size and type */
-     pso->sizlBitmap = LocalSize;
-     pso->iType = STYPE_BITMAP;
-     /* Device-managed surface, no flags or dimension */
-     pso->dhsurf = 0;
-     pso->dhpdev = NULL;
-     pso->hdev = NULL;
-     psurf->flFlags = 0;
-     psurf->dimension.cx = 0;
-     psurf->dimension.cy = 0;
-     psurf->hSecure = NULL;
-     psurf->hDIBSection = NULL;
-     psurf->flHooks = 0;
-     /* Set bits */
-      if(Compressed)
-          pso->pvBits = DecompressedBits;
-      else
-          pso->pvBits = Bits;
-     /* Number of bits is based on the height times the scanline */
-     pso->cjBits = BitmapInfo->Height * ScanLine;
-     if (BitmapInfo->Flags & BMF_TOPDOWN)
-     {
-         /* For topdown, the base address starts with the bits */
-         pso->pvScan0 = pso->pvBits;
-         pso->lDelta = ScanLine;
-     }
-     else
-     {
-         /* Otherwise we start with the end and go up */
-         pso->pvScan0 = (PVOID)((ULONG_PTR)pso->pvBits + pso->cjBits - ScanLine);
-         pso->lDelta = -ScanLine;
-     }
-     /* Finally set the handle and uniq */
-     pso->hsurf = (HSURF)psurf->BaseObject.hHmgr;
-     pso->iUniq = 0;
-     
-     /* Unlock and return the surface */
+     /* Unlock the surface and return */
      SURFACE_UnlockSurface(psurf);
-     return pso;
+     return hbmp;
  }
  
  /*
   */
  HBITMAP
  APIENTRY
- EngCreateBitmap(IN SIZEL Size,
-                 IN LONG Width,
-                 IN ULONG Format,
-                 IN ULONG Flags,
-                 IN PVOID Bits)
+ EngCreateDeviceBitmap(
+     IN DHSURF dhsurf,
+     IN SIZEL sizl,
+     IN ULONG iFormat)
  {
-     SURFOBJ* Surface;
-     DEVBITMAPINFO BitmapInfo;
-     
-     /* Capture the parameters */
-     BitmapInfo.Format = Format;
-     BitmapInfo.Width = Size.cx;
-     BitmapInfo.Height = Size.cy;
-     BitmapInfo.Flags = Flags;
-     /*
-      * If the display driver supports framebuffer access, use the scanline width
-      * to determine the actual width of the bitmap, and convert it to pels instead
-      * of bytes.
-      */
-     if ((Bits) && (Width))
+     PSURFACE psurf;
+     HBITMAP hbmp;
+     /* Allocate a surface */
+     psurf = SURFACE_AllocSurface(STYPE_DEVBITMAP, sizl.cx, sizl.cy, iFormat);
+     if (!psurf)
      {
-         switch (BitmapInfo.Format)
-         {
-             /* Do the conversion for each bit depth we support */
-             case BMF_1BPP:
-                 BitmapInfo.Width = Width * 8;
-                 break;
-             case BMF_4BPP:
-                 BitmapInfo.Width = Width * 2;
-                 break;
-             case BMF_8BPP:
-                 BitmapInfo.Width = Width;
-                 break;
-             case BMF_16BPP:
-                 BitmapInfo.Width = Width / 2;
-                 break;
-             case BMF_24BPP:
-                 BitmapInfo.Width = Width / 3;
-                 break;
-             case BMF_32BPP:
-                 BitmapInfo.Width = Width / 4;
-                 break;
-         }
+         return 0;
      }
-     
-     /* Now create the surface */
-     Surface = SURFMEM_bCreateDib(&BitmapInfo, Bits);
-     if (!Surface) return 0;
-     /* Set public ownership and reutrn the handle */
-     GDIOBJ_SetOwnership(Surface->hsurf, NULL);
-     return Surface->hsurf;
+     /* Set the device handle */
+     psurf->SurfObj.dhsurf = dhsurf;
+     /* Get the handle for the bitmap */
+     hbmp = (HBITMAP)psurf->SurfObj.hsurf;
+     /* Set public ownership */
+     GDIOBJ_SetOwnership(hbmp, NULL);
+     /* Unlock the surface and return */
+     SURFACE_UnlockSurface(psurf);
+     return hbmp;
  }
  
- /*
-  * @unimplemented
-  */
- HSURF APIENTRY
- EngCreateDeviceSurface(IN DHSURF dhsurf,
-                        IN SIZEL Size,
-                        IN ULONG Format)
+ HSURF
+ APIENTRY
+ EngCreateDeviceSurface(
+     IN DHSURF dhsurf,
+     IN SIZEL sizl,
+     IN ULONG iFormat)
  {
-     HSURF hsurf;
-     SURFOBJ *pso;
      PSURFACE psurf;
+     HSURF hsurf;
  
-     psurf = SURFACE_AllocSurfaceWithHandle();
+     /* Allocate a surface */
+     psurf = SURFACE_AllocSurface(STYPE_DEVICE, sizl.cx, sizl.cy, iFormat);
      if (!psurf)
      {
          return 0;
      }
  
-     hsurf = psurf->BaseObject.hHmgr;
-     GDIOBJ_SetOwnership(hsurf, NULL);
+     /* Set the device handle */
+     psurf->SurfObj.dhsurf = dhsurf;
  
-     if (!SURFACE_InitBitsLock(psurf))
-     {
-         SURFACE_UnlockSurface(psurf);
-         SURFACE_FreeSurfaceByHandle(hsurf);
-         return 0;
-     }
-     pso = &psurf->SurfObj;
+     /* Get the handle for the surface */
+     hsurf = psurf->SurfObj.hsurf;
  
-     pso->dhsurf = dhsurf;
-     pso->hsurf = hsurf;
-     pso->sizlBitmap = Size;
-     pso->iBitmapFormat = Format;
-     pso->lDelta = DIB_GetDIBWidthBytes(Size.cx, BitsPerFormat(Format));
-     pso->iType = STYPE_DEVICE;
-     pso->iUniq = 0;
-     psurf->flHooks = 0;
+     /* Set public ownership */
+     GDIOBJ_SetOwnership(hsurf, NULL);
  
+     /* Unlock the surface and return */
      SURFACE_UnlockSurface(psurf);
      return hsurf;
  }
  
- /*
-  * @implemented
-  */
  BOOL
  APIENTRY
  EngAssociateSurface(
      pso->dhpdev = ppdev->dhpdev;
  
      /* Hook up specified functions */
-     psurf->flHooks = flHooks;
+     psurf->flags &= ~HOOK_FLAGS;
+     psurf->flags |= (flHooks & HOOK_FLAGS);
+     /* Get palette */
+     psurf->ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
  
      SURFACE_UnlockSurface(psurf);
  
      return TRUE;
  }
  
- /*
-  * @implemented
-  */
- BOOL APIENTRY
+ BOOL
+ APIENTRY
  EngModifySurface(
      IN HSURF hsurf,
      IN HDEV hdev,
      pso->dhpdev = ppdev->dhpdev;
  
      /* Hook up specified functions */
-     psurf->flHooks = flHooks;
+     psurf->flags &= ~HOOK_FLAGS;
+     psurf->flags |= (flHooks & HOOK_FLAGS);
+     /* Get palette */
+     psurf->ppal = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
  
      SURFACE_UnlockSurface(psurf);
  
      return TRUE;
  }
  
- /*
-  * @implemented
-  */
- BOOL APIENTRY
+ BOOL
+ APIENTRY
  EngDeleteSurface(IN HSURF hsurf)
  {
      GDIOBJ_SetOwnership(hsurf, PsGetCurrentProcess());
      return TRUE;
  }
  
- /*
-  * @implemented
-  */
- BOOL APIENTRY
- EngEraseSurface(SURFOBJ *pso,
-                 RECTL *Rect,
-                 ULONG iColor)
+ BOOL
+ APIENTRY
+ EngEraseSurface(
+     SURFOBJ *pso,
+     RECTL *prcl,
+     ULONG iColor)
  {
      ASSERT(pso);
-     ASSERT(Rect);
-     return FillSolid(pso, Rect, iColor);
+     ASSERT(prcl);
+     return FillSolid(pso, prcl, iColor);
  }
  
  /*
@@@ -836,10 -484,8 +484,8 @@@ NtGdiEngLockSurface(IN HSURF hsurf
  }
  
  
- /*
-  * @implemented
-  */
- SURFOBJ * APIENTRY
+ SURFOBJ *
+ APIENTRY
  EngLockSurface(IN HSURF hsurf)
  {
      SURFACE *psurf = GDIOBJ_ShareLockObj(hsurf, GDI_OBJECT_TYPE_BITMAP);
      return NULL;
  }
  
- /*
-  * @implemented
-  */
- VOID APIENTRY
+ VOID
+ APIENTRY
  NtGdiEngUnlockSurface(IN SURFOBJ *pso)
  {
      EngUnlockSurface(pso);
  }
  
- /*
-  * @implemented
-  */
- VOID APIENTRY
+ VOID
+ APIENTRY
  EngUnlockSurface(IN SURFOBJ *pso)
  {
      if (pso != NULL)
      }
  }
  
  /* EOF */
@@@ -76,7 -76,7 +76,7 @@@ EngTransparentBlt(SURFOBJ *psoDest
      OutputRect.top = DestRect->bottom;
      OutputRect.bottom = DestRect->top;
    }
-     
    if(Clip)
    {
      if(OutputRect.left < Clip->rclBounds.left)
@@@ -284,17 -284,7 +284,7 @@@ IntEngTransparentBlt(SURFOBJ *psoDest
      OutputRect = InputClippedRect;
    }
  
-   if(psoSource != psoDest)
-   {
-     SURFACE_LockBitmapBits(psurfSource);
-     MouseSafetyOnDrawStart(psoSource, InputRect.left, InputRect.top,
-                            InputRect.right, InputRect.bottom);
-   }
-   SURFACE_LockBitmapBits(psurfDest);
-   MouseSafetyOnDrawStart(psoDest, OutputRect.left, OutputRect.top,
-                          OutputRect.right, OutputRect.bottom);
-   if(psurfDest->flHooks & HOOK_TRANSPARENTBLT)
+   if(psurfDest->flags & HOOK_TRANSPARENTBLT)
    {
      Ret = GDIDEVFUNCS(psoDest).TransparentBlt(
        psoDest, psoSource, Clip, ColorTranslation, &OutputRect,
                              &OutputRect, &InputRect, iTransColor, Reserved);
    }
  
-   MouseSafetyOnDrawEnd(psoDest);
-   SURFACE_UnlockBitmapBits(psurfDest);
-   if(psoSource != psoDest)
-   {
-     MouseSafetyOnDrawEnd(psoSource);
-     SURFACE_UnlockBitmapBits(psurfSource);
-   }
    return Ret;
  }
  
@@@ -64,7 -64,7 +64,7 @@@ EXLATEOBJ_iXlateRGBtoBGR(PEXLATEOBJ pxl
  {
      ULONG iNewColor;
  
-     /* Copy green and alpha */
+     /* Copy green */
      iNewColor = iColor & 0xff00ff00;
  
      /* Mask red and blue */
@@@ -362,19 -362,19 +362,19 @@@ EXLATEOBJ_vInitialize
      EXLATEOBJ_vInitTrivial(pexlo);
  
      if (ppalDst == ppalSrc || !ppalSrc || !ppalDst ||
-         ((ppalDst->Mode == PAL_RGB || ppalDst->Mode == PAL_BGR) &&
-          ppalDst->Mode == ppalSrc->Mode))
+         ((ppalDst->flFlags == PAL_RGB || ppalDst->flFlags == PAL_BGR) &&
+          ppalDst->flFlags == ppalSrc->flFlags))
      {
          return;
      }
  
      pexlo->ppalSrc = ppalSrc;
      pexlo->ppalDst = ppalDst;
-     pexlo->xlo.iSrcType = ppalSrc->Mode;
-     pexlo->xlo.iDstType = ppalDst->Mode;
+     pexlo->xlo.iSrcType = ppalSrc->flFlags;
+     pexlo->xlo.iDstType = ppalDst->flFlags;
  
      /* Chack if both of the pallettes are indexed */
-     if (!(ppalSrc->Mode & PAL_INDEXED) || !(ppalDst->Mode & PAL_INDEXED))
+     if (!(ppalSrc->flFlags & PAL_INDEXED) || !(ppalDst->flFlags & PAL_INDEXED))
      {
          /* At least one palette is not indexed, calculate shifts/masks */
          ULONG aulMasksSrc[3], aulMasksDst[3];
          pexlo->ulBlueShift = CalculateShift(aulMasksSrc[2], aulMasksDst[2]);
      }
  
-     if (ppalSrc->Mode & PAL_MONOCHROME)
+     if (ppalSrc->flFlags & PAL_MONOCHROME)
      {
          /* This is a monochrome palette */
-         if (!(ppalDst->Mode & PAL_MONOCHROME))
+         if (!(ppalDst->flFlags & PAL_MONOCHROME))
          {
              /* Mono to color, use the dest DC's fore and back color */
              pexlo->pfnXlate = EXLATEOBJ_iXlateTable;
                  PALETTE_ulGetNearestIndex(ppalDst, crDstBackColor);
          }
      }
-     else if (ppalDst->Mode & PAL_MONOCHROME)
+     else if (ppalDst->flFlags & PAL_MONOCHROME)
      {
          pexlo->pfnXlate = EXLATEOBJ_iXlateToMono;
          pexlo->xlo.flXlate |= XO_TO_MONO;
          pexlo->xlo.cEntries = 1;
  
-         if (ppalSrc->Mode & PAL_INDEXED)
+         if (ppalSrc->flFlags & PAL_INDEXED)
          {
              pexlo->aulXlate[0] =
                  PALETTE_ulGetNearestPaletteIndex(ppalSrc, crSrcBackColor);
          }
-         else if (ppalSrc->Mode & PAL_BGR)
+         else if (ppalSrc->flFlags & PAL_BGR)
          {
              pexlo->aulXlate[0] = crSrcBackColor;
          }
-         else if (ppalSrc->Mode & PAL_RGB)
+         else if (ppalSrc->flFlags & PAL_RGB)
          {
              pexlo->aulXlate[0] = RGB(GetBValue(crSrcBackColor),
                                       GetGValue(crSrcBackColor),
                                       GetRValue(crSrcBackColor));
          }
-         else if (ppalSrc->Mode & PAL_BITFIELDS)
+         else if (ppalSrc->flFlags & PAL_BITFIELDS)
          {
              PALETTE_vGetBitMasks(ppalSrc, &pexlo->ulRedMask);
              pexlo->ulRedShift = CalculateShift(0xFF, pexlo->ulRedMask);
              pexlo->aulXlate[0] = EXLATEOBJ_iXlateShiftAndMask(pexlo, crSrcBackColor);
          }
      }
-     else if (ppalSrc->Mode & PAL_INDEXED)
+     else if (ppalSrc->flFlags & PAL_INDEXED)
      {
          cEntries = ppalSrc->NumColors;
  
          pexlo->xlo.cEntries = cEntries;
  
          pexlo->pfnXlate = EXLATEOBJ_iXlateTable;
-         if (ppalDst->Mode & PAL_INDEXED)
+         if (ppalDst->flFlags & PAL_INDEXED)
          {
              pexlo->xlo.flXlate |= XO_TABLE;
  
              }
          }
      }
-     else if (ppalSrc->Mode & PAL_RGB)
+     else if (ppalSrc->flFlags & PAL_RGB)
      {
-         if (ppalDst->Mode & PAL_INDEXED)
+         if (ppalDst->flFlags & PAL_INDEXED)
              pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoPal;
  
-         else if (ppalDst->Mode & PAL_BGR)
+         else if (ppalDst->flFlags & PAL_BGR)
              pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoBGR;
  
-         else if (ppalDst->Mode & PAL_RGB16_555)
+         else if (ppalDst->flFlags & PAL_RGB16_555)
              pexlo->pfnXlate = EXLATEOBJ_iXlateRGBto555;
  
-         else if (ppalDst->Mode & PAL_RGB16_565)
+         else if (ppalDst->flFlags & PAL_RGB16_565)
              pexlo->pfnXlate = EXLATEOBJ_iXlateRGBto565;
  
-         else if (ppalDst->Mode & PAL_BITFIELDS)
+         else if (ppalDst->flFlags & PAL_BITFIELDS)
              pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
      }
-     else if (ppalSrc->Mode & PAL_BGR)
+     else if (ppalSrc->flFlags & PAL_BGR)
      {
-         if (ppalDst->Mode & PAL_INDEXED)
+         if (ppalDst->flFlags & PAL_INDEXED)
              pexlo->pfnXlate = EXLATEOBJ_iXlateBitfieldsToPal;
  
-         else if (ppalDst->Mode & PAL_RGB)
+         else if (ppalDst->flFlags & PAL_RGB)
              /* The inverse function works the same */
              pexlo->pfnXlate = EXLATEOBJ_iXlateRGBtoBGR;
  
-         else if (ppalDst->Mode & PAL_RGB16_555)
+         else if (ppalDst->flFlags & PAL_RGB16_555)
              pexlo->pfnXlate = EXLATEOBJ_iXlateBGRto555;
  
-         else if (ppalDst->Mode & PAL_RGB16_565)
+         else if (ppalDst->flFlags & PAL_RGB16_565)
              pexlo->pfnXlate = EXLATEOBJ_iXlateBGRto565;
  
-         else if (ppalDst->Mode & PAL_BITFIELDS)
+         else if (ppalDst->flFlags & PAL_BITFIELDS)
              pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
      }
-     else if (ppalSrc->Mode & PAL_RGB16_555)
+     else if (ppalSrc->flFlags & PAL_RGB16_555)
      {
-         if (ppalDst->Mode & PAL_INDEXED)
+         if (ppalDst->flFlags & PAL_INDEXED)
              pexlo->pfnXlate = EXLATEOBJ_iXlate555toPal;
  
-         else if (ppalDst->Mode & PAL_RGB)
+         else if (ppalDst->flFlags & PAL_RGB)
              pexlo->pfnXlate = EXLATEOBJ_iXlate555toRGB;
  
-         else if (ppalDst->Mode & PAL_BGR)
+         else if (ppalDst->flFlags & PAL_BGR)
              pexlo->pfnXlate = EXLATEOBJ_iXlate555toBGR;
  
-         else if (ppalDst->Mode & PAL_RGB16_565)
+         else if (ppalDst->flFlags & PAL_RGB16_565)
              pexlo->pfnXlate = EXLATEOBJ_iXlate555to565;
  
-         else if (ppalDst->Mode & PAL_BITFIELDS)
+         else if (ppalDst->flFlags & PAL_BITFIELDS)
              pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
      }
-     else if (ppalSrc->Mode & PAL_RGB16_565)
+     else if (ppalSrc->flFlags & PAL_RGB16_565)
      {
-         if (ppalDst->Mode & PAL_INDEXED)
+         if (ppalDst->flFlags & PAL_INDEXED)
              pexlo->pfnXlate = EXLATEOBJ_iXlate565toPal;
  
-         else if (ppalDst->Mode & PAL_RGB)
+         else if (ppalDst->flFlags & PAL_RGB)
              pexlo->pfnXlate = EXLATEOBJ_iXlate565toRGB;
  
-         else if (ppalDst->Mode & PAL_BGR)
+         else if (ppalDst->flFlags & PAL_BGR)
              pexlo->pfnXlate = EXLATEOBJ_iXlate565toBGR;
  
-         else if (ppalDst->Mode & PAL_RGB16_555)
+         else if (ppalDst->flFlags & PAL_RGB16_555)
              pexlo->pfnXlate = EXLATEOBJ_iXlate565to555;
  
-         else if (ppalDst->Mode & PAL_BITFIELDS)
+         else if (ppalDst->flFlags & PAL_BITFIELDS)
              pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
      }
-     else if (ppalSrc->Mode & PAL_BITFIELDS)
+     else if (ppalSrc->flFlags & PAL_BITFIELDS)
      {
-         if (ppalDst->Mode & PAL_INDEXED)
+         if (ppalDst->flFlags & PAL_INDEXED)
              pexlo->pfnXlate = EXLATEOBJ_iXlateBitfieldsToPal;
          else
              pexlo->pfnXlate = EXLATEOBJ_iXlateShiftAndMask;
@@@ -603,157 -603,24 +603,24 @@@ EXLATEOBJ_vInitXlateFromDCs
      PDC pdcDst)
  {
      PSURFACE psurfDst, psurfSrc;
-     HPALETTE hpalSrc, hpalDst;
-     PPALETTE ppalSrc, ppalDst, ppalDstDc;
-     DPRINT("Enter EXLATEOBJ_vInitXlateFromDCs\n");
-     /* Do basic init */
-     EXLATEOBJ_vInitTrivial(pexlo);
  
      psurfDst = pdcDst->dclevel.pSurface;
      psurfSrc = pdcSrc->dclevel.pSurface;
  
+     /* Check for trivial color translation */
      if (psurfDst == psurfSrc)
      {
+         EXLATEOBJ_vInitTrivial(pexlo);
          return;
      }
  
-     hpalSrc = psurfSrc->hDIBPalette;
-     if (!hpalSrc) 
-         hpalSrc = pPrimarySurface->devinfo.hpalDefault;
-     ppalSrc = PALETTE_ShareLockPalette(hpalSrc);
-     if (!ppalSrc)
-         return;
-     hpalDst = psurfDst->hDIBPalette;
-     if (!hpalDst) hpalDst = pPrimarySurface->devinfo.hpalDefault;
-     ppalDst = PALETTE_ShareLockPalette(hpalDst);
-     if (!ppalDst)
-     {
-         PALETTE_ShareUnlockPalette(ppalSrc);
-         return;
-     }
-     ppalDstDc = pdcDst->dclevel.ppal;
-     ASSERT(ppalDstDc);
-     /* KB41464 details how to convert between mono and color */
-     if (psurfDst->SurfObj.iBitmapFormat == BMF_1BPP)
-     {
-         if (psurfSrc->SurfObj.iBitmapFormat != BMF_1BPP)
-         {
-             // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
-             EXLATEOBJ_vInitialize(pexlo,
-                                   ppalSrc,
-                                   &gpalMono,
-                                   pdcSrc->pdcattr->crBackgroundClr,
-                                   pdcDst->pdcattr->crBackgroundClr,
-                                   pdcDst->pdcattr->crForegroundClr);
-         }
-     }
-     else if (psurfSrc->SurfObj.iBitmapFormat == BMF_1BPP && !psurfSrc->hSecure)
-     {
-         // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
-         EXLATEOBJ_vInitialize(pexlo,
-                               &gpalMono,
-                               ppalDst,
-                               0,
-                               pdcDst->pdcattr->crBackgroundClr,
-                               pdcDst->pdcattr->crForegroundClr);
-     }
-     else
-     {
-         EXLATEOBJ_vInitialize(pexlo, ppalSrc, ppalDst, 0, 0, 0);
-     }
-     PALETTE_ShareUnlockPalette(ppalDst);
-     PALETTE_ShareUnlockPalette(ppalSrc);
- }
- VOID
- NTAPI
- EXLATEOBJ_vInitBrushXlate(
-     PEXLATEOBJ pexlo,
-     BRUSH *pbrush,
-     SURFACE *psurfDst,
-     COLORREF crForegroundClr,
-     COLORREF crBackgroundClr)
- {
-     HPALETTE hpalDst = NULL;
-     PPALETTE ppalDst, ppalPattern;
-     SURFACE *psurfPattern;
-     ASSERT(pexlo);
-     ASSERT(pbrush);
-     ASSERT(psurfDst);
-     ASSERT(!(pbrush->flAttrs & (GDIBRUSH_IS_SOLID | GDIBRUSH_IS_NULL)));
-     EXLATEOBJ_vInitTrivial(pexlo);
-     hpalDst = psurfDst->hDIBPalette;
-     if (!hpalDst) hpalDst = pPrimarySurface->devinfo.hpalDefault;
-     ppalDst = PALETTE_ShareLockPalette(hpalDst);
-     if (!ppalDst)
-     {
-         DPRINT1("No ppalDst!\n");
-         return;
-     }
-     psurfPattern = SURFACE_ShareLockSurface(pbrush->hbmPattern);
-     if (!psurfPattern)
-     {
-         PALETTE_ShareUnlockPalette(ppalDst);
-         return;
-     }
- #if 0
-     if (psurfDst->SurfObj.iBitmapFormat == BMF_1BPP)
-     {
-         if (psurfSrc->SurfObj.iBitmapFormat != BMF_1BPP)
-         {
-             // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
-             EXLATEOBJ_vInitialize(pexlo,
-                                   ppalSrc,
-                                   &gpalMono,
-                                   0,
-                                   crBackgroundClr,
-                                   crForegroundClr);
-         }
-     }
-     else
- #endif
-     if (psurfPattern->SurfObj.iBitmapFormat == BMF_1BPP &&
-         !(pbrush->flAttrs & GDIBRUSH_IS_DIB))
-     {
-         /* Special case: 1 bpp pattern, not a DIB brush. */
-         if (psurfDst->SurfObj.iBitmapFormat != BMF_1BPP)
-         {
-             // HACK!! FIXME: 1bpp DDBs should have gpalMono already!
-             EXLATEOBJ_vInitialize(pexlo,
-                                   &gpalMono,
-                                   ppalDst,
-                                   0,
-                                   crBackgroundClr,
-                                   crForegroundClr);
-         }
-     }
-     else
-     {
-         /* Default: use the patterns' palette */
-         ppalPattern = PALETTE_LockPalette(psurfPattern->hDIBPalette);
-         if (ppalPattern)
-         {
-             EXLATEOBJ_vInitialize(pexlo, &gpalRGB, ppalDst, 0, 0, 0);
-             PALETTE_UnlockPalette(ppalPattern);
-         }
-     }
-     PALETTE_ShareUnlockPalette(ppalDst);
-     SURFACE_ShareUnlockSurface(psurfPattern);
+     /* Normal initialisation. No surface means DEFAULT_BITMAP */
+     EXLATEOBJ_vInitialize(pexlo,
+                           psurfSrc ? psurfSrc->ppal : &gpalMono,
+                           psurfDst ? psurfDst->ppal : &gpalMono,
+                           pdcSrc->pdcattr->crBackgroundClr,
+                           pdcDst->pdcattr->crBackgroundClr,
+                           pdcDst->pdcattr->crForegroundClr);
  }
  
  VOID
@@@ -827,9 -694,9 +694,9 @@@ XLATEOBJ_cGetPalette(XLATEOBJ *pxlo, UL
      /* Verify palette type match */
      if (!ppal ||
          ((iPal == XO_SRCPALETTE || iPal == XO_DESTPALETTE)
-             && !(ppal->Mode & PAL_INDEXED)) ||
+             && !(ppal->flFlags & PAL_INDEXED)) ||
          ((iPal == XO_SRCBITFIELDS || iPal == XO_DESTBITFIELDS)
-             && !(ppal->Mode & PAL_BITFIELDS)))
+             && !(ppal->flFlags & PAL_BITFIELDS)))
      {
          return 0;
      }
      }
  
      /* Copy the values into the buffer */
-     if (ppal->Mode & PAL_INDEXED)
+     if (ppal->flFlags & PAL_INDEXED)
      {
          cPal = min(cPal, ppal->NumColors);
          for (i = 0; i < cPal; i++)
@@@ -2,11 -2,47 +2,47 @@@
  
  #include "surface.h"
  
- INT     FASTCALL DIB_GetDIBWidthBytes (INT  width, INT  depth);
- int     APIENTRY  DIB_GetDIBImageBytes (INT  width, INT  height, INT  depth);
- INT     FASTCALL DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse);
+ typedef struct tagBITMAPV5INFO
+ {
+     BITMAPV5HEADER bmiHeader;
+     RGBQUAD        bmiColors[256];
+ } BITMAPV5INFO, *PBITMAPV5INFO;
  INT     APIENTRY  BITMAP_GetObject(SURFACE * bmp, INT count, LPVOID buffer);
  HBITMAP FASTCALL IntCreateBitmap(IN SIZEL Size, IN LONG Width, IN ULONG Format, IN ULONG Flags, IN PVOID Bits);
  HBITMAP FASTCALL BITMAP_CopyBitmap (HBITMAP  hBitmap);
  UINT    FASTCALL BITMAP_GetRealBitsPixel(UINT nBitsPixel);
- INT     FASTCALL BITMAP_GetWidthBytes (INT bmWidth, INT bpp);
+ HBITMAP
+ APIENTRY
+ GreCreateBitmap(
+     IN INT nWidth,
+     IN INT nHeight,
+     IN UINT cPlanes,
+     IN UINT cBitsPixel,
+     IN OPTIONAL PVOID pvBits);
+ HBITMAP
+ APIENTRY
+ GreCreateBitmapEx(
+     IN INT nWidth,
+     IN INT nHeight,
+     IN ULONG cjWidthBytes,
+     IN ULONG iFormat,
+     IN USHORT fjBitmap,
+     IN ULONG cjBits,
+     IN OPTIONAL PVOID pvBits,
+       IN FLONG flags);
+ HBITMAP
+ FASTCALL
+ GreCreateDIBitmapInternal(
+     IN HDC hDc,
+     IN INT cx,
+     IN INT cy,
+     IN DWORD fInit,
+     IN OPTIONAL LPBYTE pjInit,
+     IN OPTIONAL PBITMAPINFO pbmi,
+     IN DWORD iUsage,
+     IN FLONG fl,
+     IN HANDLE hcmXform);
@@@ -1,4 -1,5 +1,5 @@@
- #pragma once
+ #ifndef __WIN32K_DC_H
+ #define __WIN32K_DC_H
  
  typedef struct _DC *PDC;
  
  /* fl */
  #define DC_FL_PAL_BACK 1
  
+ #define DC_DISPLAY  1
+ #define DC_DIRECT 2
+ #define DC_CANCELED 4
+ #define DC_PERMANANT 0x08
+ #define DC_DIRTY_RAO 0x10
+ #define DC_ACCUM_WMGR 0x20
+ #define DC_ACCUM_APP 0x40
+ #define DC_RESET 0x80
+ #define DC_SYNCHRONIZEACCESS 0x100
+ #define DC_EPSPRINTINGESCAPE 0x200
+ #define DC_TEMPINFODC 0x400
+ #define DC_FULLSCREEN 0x800
+ #define DC_IN_CLONEPDEV 0x1000
+ #define DC_REDIRECTION 0x2000
+ #define DC_SHAREACCESS 0x4000
+ typedef enum
+ {
+   DCTYPE_DIRECT = 0,
+   DCTYPE_MEMORY = 1,
+   DCTYPE_INFO = 2,
+ } DCTYPE;
  /* Type definitions ***********************************************************/
  
  typedef struct _ROS_DC_INFO
@@@ -29,7 -54,7 +54,7 @@@
    HRGN     hClipRgn;     /* Clip region (may be 0) */
    HRGN     hGCClipRgn;   /* GC clip region (ClipRgn AND VisRgn) */
  
-   CLIPOBJ     *CombinedClip; /* Use XCLIPOBJ in DC. */
+   CLIPOBJ     *CombinedClip;
  
    UNICODE_STRING    DriverName;
  
@@@ -136,13 -161,12 +161,12 @@@ extern PDC defaultDCstate
  
  NTSTATUS FASTCALL InitDcImpl(VOID);
  PPDEVOBJ FASTCALL IntEnumHDev(VOID);
HDC  FASTCALL DC_AllocDC(PUNICODE_STRING  Driver);
PDC NTAPI DC_AllocDcWithHandle();
  VOID FASTCALL DC_InitDC(HDC  DCToInit);
- HDC  FASTCALL DC_FindOpenDC(PUNICODE_STRING  Driver);
  VOID FASTCALL DC_AllocateDcAttr(HDC);
  VOID FASTCALL DC_FreeDcAttr(HDC);
  BOOL INTERNAL_CALL DC_Cleanup(PVOID ObjectBody);
- BOOL FASTCALL DC_SetOwnership(HDC DC, PEPROCESS Owner);
+ BOOL FASTCALL DC_SetOwnership(HDC hDC, PEPROCESS Owner);
  VOID FASTCALL DC_LockDisplay(HDC);
  VOID FASTCALL DC_UnlockDisplay(HDC);
  BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL);
@@@ -155,10 -179,16 +179,16 @@@ VOID FASTCALL DC_vUpdateFillBrush(PDC p
  VOID FASTCALL DC_vUpdateLineBrush(PDC pdc);
  VOID FASTCALL DC_vUpdateTextBrush(PDC pdc);
  VOID FASTCALL DC_vUpdateBackgroundBrush(PDC pdc);
+ VOID FASTCALL DC_vFinishBlit(PDC pdc1, PDC pdc2);
+ VOID FASTCALL DC_vPrepareDCsForBlit(PDC pdc1, RECT rc1, PDC pdc2, RECT rc2);
+ VOID NTAPI DC_vRestoreDC(IN PDC pdc, INT iSaveLevel);
  
  BOOL FASTCALL DCU_SyncDcAttrtoUser(PDC);
  BOOL FASTCALL DCU_SynchDcAttrtoUser(HDC);
  VOID FASTCALL DCU_SetDcUndeletable(HDC);
+ VOID NTAPI DC_vFreeDcAttr(PDC pdc);
+ VOID NTAPI DC_vInitDc(PDC pdc, DCTYPE dctype, PPDEVOBJ ppdev);
  
  COLORREF FASTCALL IntGdiSetBkColor (HDC hDC, COLORREF Color);
  INT FASTCALL IntGdiSetBkMode(HDC  hDC, INT  backgroundMode);
@@@ -174,12 -204,9 +204,9 @@@ VOID FASTCALL IntGdiUnreferencePdev(PPD
  HDC FASTCALL IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC);
  BOOL FASTCALL IntGdiCleanDC(HDC hDC);
  VOID FASTCALL IntvGetDeviceCaps(PPDEVOBJ, PDEVCAPS);
- INT FASTCALL IntGdiGetDeviceCaps(PDC,INT);
  BOOL FASTCALL MakeInfoDC(PDC,BOOL);
  BOOL FASTCALL IntSetDefaultRegion(PDC);
  
- extern PPDEVOBJ pPrimarySurface;
  VOID
  FORCEINLINE
  DC_vSelectSurface(PDC pdc, PSURFACE psurfNew)
@@@ -228,5 -255,6 +255,6 @@@ DC_vSelectPalette(PDC pdc, PPALETTE ppa
      pdc->dclevel.ppal = ppal;
  }
  
- BOOL FASTCALL IntPrepareDriverIfNeeded(VOID);
- extern PDEVOBJ PrimarySurface;
+ extern PBRUSH pbrDefaultBrush ;
+ #endif /* not __WIN32K_DC_H */
index 0000000,cdf60d7..cdf60d7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,57 +1,57 @@@
+ //#define _PDEVOBJ _PDEVOBJ2
+ //#define PDEVOBJ PDEVOBJ2
+ //#define PPDEVOBJ PPDEVOBJ2
+ //typedef struct _PDEVOBJ *PPDEVOBJ;
+ #define TAG_GDEV 'gdev'
+ VOID
+ APIENTRY
+ EngFileWrite(
+     IN PFILE_OBJECT pFileObject,
+     IN PVOID lpBuffer,
+     IN SIZE_T nLength,
+     IN PSIZE_T lpBytesWritten);
+ PGRAPHICS_DEVICE
+ NTAPI
+ EngpFindGraphicsDevice(
+     PUNICODE_STRING pustrDevice,
+     DWORD iDevNum,
+     DWORD dwFlags);
+ PGRAPHICS_DEVICE
+ NTAPI
+ EngpRegisterGraphicsDevice(
+     PUNICODE_STRING pustrDeviceName,
+     PUNICODE_STRING pustrDiplayDrivers,
+     PUNICODE_STRING pustrDescription,
+     PDEVMODEW pdmDefault);
+ BOOL
+ NTAPI
+ InitDeviceImpl();
+ BOOL
+ FASTCALL
+ DC_AllocDcAttr(PDC pdc);
+ //#define KeRosDumpStackFrames(Frames, Count) KdSystemDebugControl(TAG('R', 'o', 's', 'D'), (PVOID)Frames, Count, NULL, 0, NULL, KernelMode)
+ NTSYSAPI ULONG APIENTRY RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN ULONG Flags);
+ BOOL
+ NTAPI
+ PDEVOBJ_bSwitchMode(
+     PPDEVOBJ ppdev,
+     PDEVMODEW pdm);
+ PDEVMODEW
+ NTAPI
+ PDEVOBJ_pdmMatchDevMode(
+     PPDEVOBJ ppdev,
+     PDEVMODEW pdm);
+ extern PGRAPHICS_DEVICE gpPrimaryGraphicsDevice;
+ extern PGRAPHICS_DEVICE gpVgaGraphicsDevice;
@@@ -5,15 -5,17 +5,17 @@@
  INT FASTCALL
  DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse);
  HBITMAP APIENTRY
- DIB_CreateDIBSection (PDC dc, PBITMAPINFO bmi, UINT usage, LPVOID *bits, HANDLE section, DWORD offset, DWORD ovr_pitch);
- INT APIENTRY
- DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, PLONG width, PLONG height, PWORD planes, PWORD bpp, PLONG compr, PLONG size );
+ DIB_CreateDIBSection (PDC dc, CONST BITMAPINFO *bmi, UINT usage, LPVOID *bits, HANDLE section, DWORD offset, DWORD ovr_pitch);
+ int FASTCALL
+ DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
+                        LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size );
  INT APIENTRY
  DIB_GetDIBImageBytes (INT  width, INT height, INT depth);
- INT FASTCALL
- DIB_GetDIBWidthBytes (INT width, INT depth);
- RGBQUAD * FASTCALL
- DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi);
+ HPALETTE FASTCALL
+ DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi);
  
  HPALETTE FASTCALL
- BuildDIBPalette (CONST BITMAPINFO *bmi, PINT paletteType);
+ BuildDIBPalette (CONST BITMAPINFO *bmi);
+ BITMAPINFO* FASTCALL DIB_ConvertBitmapInfo(CONST BITMAPINFO* bmi, DWORD Usage);
+ VOID FASTCALL DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig);
@@@ -21,3 -21,19 +21,19 @@@ IntEngWindowChanged
  VOID FASTCALL IntGdiAcquireSemaphore ( HSEMAPHORE hsem );
  VOID FASTCALL IntGdiReleaseSemaphore ( HSEMAPHORE hsem );
  ULONGLONG APIENTRY EngGetTickCount(VOID);
+ BOOL
+ APIENTRY
+ EngFreeSectionMem(
+     IN PVOID pvSection OPTIONAL,
+     IN PVOID pvMappedBase OPTIONAL);
+ PVOID
+ APIENTRY
+ EngAllocSectionMem(
+     OUT PVOID *ppvSection,
+     IN ULONG fl,
+     IN SIZE_T cjSize,
+     IN ULONG ulTag);
+ VOID DecompressBitmap(SIZEL Size, BYTE *CompressedBits, BYTE *UncompressedBits, LONG Delta, ULONG iFormat);
@@@ -71,6 -71,7 +71,7 @@@ VOID    INTERNAL_CALL GDIOBJ_FreeObj (P
  BOOL    INTERNAL_CALL GDIOBJ_FreeObjByHandle (HGDIOBJ hObj, DWORD ObjectType);
  PGDIOBJ INTERNAL_CALL GDIOBJ_LockObj (HGDIOBJ hObj, DWORD ObjectType);
  PGDIOBJ INTERNAL_CALL GDIOBJ_ShareLockObj (HGDIOBJ hObj, DWORD ObjectType);
+ VOID INTERNAL_CALL GDIOBJ_LockMultipleObjs(ULONG ulCount, IN HGDIOBJ* ahObj, OUT PGDIOBJ* apObj);
  
  PVOID   INTERNAL_CALL GDI_MapHandleTable(PSECTION_OBJECT SectionObject, PEPROCESS Process);
  
@@@ -1,17 -1,10 +1,10 @@@
  #pragma once
  
  #define HOOK_THREAD_REFERENCED        (0x1)
- #define NB_HOOKS (WH_MAXHOOK-WH_MINHOOK+1)
  #define HOOKID_TO_INDEX(HookId) (HookId - WH_MINHOOK)
  #define HOOKID_TO_FLAG(HookId) (1 << ((HookId) + 1))
  #define ISITHOOKED(HookId) (((PTHREADINFO)PsGetCurrentThreadWin32Thread())->fsHooks & HOOKID_TO_FLAG(HookId))
  
- typedef struct tagHOOKTABLE
- {
-   LIST_ENTRY Hooks[NB_HOOKS];  /* array of hook chains */
-   UINT       Counts[NB_HOOKS]; /* use counts for each hook chain */
- } HOOKTABLE, *PHOOKTABLE;
  typedef struct tagEVENTHOOK
  {
    THROBJHEAD     head;
@@@ -32,11 -25,22 +25,22 @@@ typedef struct tagEVENTTABL
    UINT       Counts;
  } EVENTTABLE, *PEVENTTABLE;
  
+ typedef struct _NOTIFYEVENT
+ {
+    DWORD event;
+    LONG  idObject;
+    LONG  idChild;
+    DWORD flags; 
+ } NOTIFYEVENT, *PNOTIFYEVENT;
+ LRESULT FASTCALL co_CallHook(INT HookId, INT Code, WPARAM wParam, LPARAM lParam);
  LRESULT FASTCALL co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam);
  LRESULT FASTCALL co_EVENT_CallEvents(DWORD, HWND, UINT_PTR, LONG_PTR);
  VOID FASTCALL HOOK_DestroyThreadHooks(PETHREAD Thread);
+ VOID FASTCALL EVENT_DestroyThreadEvents(PETHREAD Thread);
  PHOOK FASTCALL IntGetHookObject(HHOOK);
  PHOOK FASTCALL IntGetNextHook(PHOOK Hook);
  LRESULT FASTCALL UserCallNextHookEx( PHOOK pHook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi);
+ BOOL FASTCALL IntUnhookWindowsHook(int,HOOKPROC);
  
  /* EOF */
@@@ -45,7 -45,7 +45,7 @@@ IntEngLineTo(SURFOBJ *Surface
               MIX mix);
  
  BOOL APIENTRY
- IntEngBitBltEx(SURFOBJ *DestObj,
+ IntEngBitBlt(SURFOBJ *DestObj,
                 SURFOBJ *SourceObj,
                 SURFOBJ *Mask,
                 CLIPOBJ *ClipRegion,
                 POINTL *MaskOrigin,
                 BRUSHOBJ *Brush,
                 POINTL *BrushOrigin,
-                ROP4 Rop4,
-                BOOL RemoveMouse);
- #define IntEngBitBlt(DestObj, SourceObj, Mask, ClipRegion, ColorTranslation, \
-                      DestRect, SourcePoint, MaskOrigin, Brush, BrushOrigin, \
-                      Rop4) \
-         IntEngBitBltEx((DestObj), (SourceObj), (Mask), (ClipRegion), \
-                        (ColorTranslation), (DestRect), (SourcePoint), \
-                        (MaskOrigin), (Brush), (BrushOrigin), (Rop4), TRUE)
+                ROP4 Rop4);
  
  BOOL APIENTRY
  IntEngStretchBlt(SURFOBJ *DestObj,
@@@ -167,9 -167,6 +167,6 @@@ IntGetSysColor(INT nIndex)
  
  /* Other Stuff */
  
- INT FASTCALL
- IntGdiGetDeviceCaps(PDC dc, INT Index);
  INT
  FASTCALL
  IntGdiEscape(PDC    dc,
@@@ -186,14 -183,6 +183,6 @@@ IntEnumDisplaySettings
    IN OUT LPDEVMODEW pDevMode,
    IN DWORD dwFlags);
  
- LONG
- FASTCALL
- IntChangeDisplaySettings(
-   IN PUNICODE_STRING pDeviceName  OPTIONAL,
-   IN LPDEVMODEW pDevMode,
-   IN DWORD dwflags,
-   IN PVOID lParam  OPTIONAL);
  HBITMAP
  FASTCALL
  IntCreateCompatibleBitmap(PDC Dc,
index 0000000,40070db..40070db
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,86 +1,86 @@@
+ #ifdef __GNUC__
+ /* Hack, for bug in ld.  Will be removed soon.  */
+ #define __ImageBase _image_base__
+ #endif
+ extern IMAGE_DOS_HEADER __ImageBase;
+ #define TAG_LDEV 'Gldv'
+ #define GDI_ENGINE_VERSION DDI_DRIVER_VERSION_NT5_01
+ typedef enum
+ {
+     LDEV_DEVICE_DISPLAY = 1,
+     LDEV_DEVICE_PRINTER = 2,
+     LDEV_DEVICE_META = 3,
+     LDEV_DEVICE_MIRROR = 4,
+     LDEV_IMAGE = 5,
+     LDEV_FONT = 6,
+ } LDEVTYPE;
+ typedef struct _LDEVOBJ
+ {
+     struct _LDEVOBJ *pldevNext;
+     struct _LDEVOBJ *pldevPrev;
+     SYSTEM_GDI_DRIVER_INFORMATION *pGdiDriverInfo;
+     LDEVTYPE ldevtype;
+     ULONG cRefs;
+     ULONG ulDriverVersion;
+     union
+     {
+         PVOID apfn[INDEX_LAST];
+         DRIVER_FUNCTIONS pfn;
+     };
+ } LDEVOBJ, *PLDEVOBJ;
+ extern PLDEVOBJ gpldevHead;
+ extern HSEMAPHORE ghsemDriverMgmt;
+ PLDEVOBJ
+ NTAPI
+ LDEVOBJ_pldevLoadImage(
+     PUNICODE_STRING pusPathName,
+     LDEVTYPE ldevtype);
+ BOOL
+ NTAPI
+ LDEVOBJ_bLoadDriver(
+     IN PLDEVOBJ pldev);
+ PVOID
+ NTAPI
+ LDEVOBJ_pvFindImageProcAddress(
+     IN PLDEVOBJ pldev,
+     IN LPSTR    lpProcName);
+ PDEVMODEINFO
+ NTAPI
+ LDEVOBJ_pdmiGetModes(
+     PLDEVOBJ pldev,
+     HANDLE hDriver);
+ BOOL
+ NTAPI
+ InitLDEVImpl();
+ PLDEVOBJ
+ APIENTRY
+ EngLoadImageEx(
+     LPWSTR pwszDriverName,
+     ULONG ldevtype);
+ PLDEVOBJ
+ NTAPI
+ EngGetLDEV(
+     PDEVMODEW pdm);
+ NTSTATUS
+ APIENTRY
+ DriverEntry (
+   IN  PDRIVER_OBJECT  DriverObject,
+   IN  PUNICODE_STRING RegistryPath);
@@@ -29,6 -29,33 +29,33 @@@ VOID FASTCALL IntUserManualGuiCheck(LON
  PVOID APIENTRY HackSecureVirtualMemory(IN PVOID,IN SIZE_T,IN ULONG,OUT PVOID *);
  VOID APIENTRY HackUnsecureVirtualMemory(IN PVOID);
  
+ NTSTATUS
+ NTAPI
+ RegOpenKey(
+     LPCWSTR pwszKeyName,
+     PHKEY phkey);
+ NTSTATUS
+ NTAPI
+ RegQueryValue(
+     IN HKEY hkey,
+     IN PCWSTR pwszValueName,
+     IN ULONG ulType,
+     OUT PVOID pvData,
+     IN OUT PULONG pcbValue);
+ VOID
+ NTAPI
+ RegWriteSZ(HKEY hkey, PWSTR pwszValue, PWSTR pwszData);
+ VOID
+ NTAPI
+ RegWriteDWORD(HKEY hkey, PWSTR pwszValue, DWORD dwData);
+ BOOL
+ NTAPI
+ RegReadDWORD(HKEY hkey, PWSTR pwszValue, PDWORD pdwData);
  BOOL
  NTAPI
  RegReadUserSetting(
@@@ -2,8 -2,8 +2,8 @@@
  
  #include <include/winsta.h>
  
- INT  INTERNAL_CALL MouseSafetyOnDrawStart(SURFOBJ *SurfObj, LONG HazardX1, LONG HazardY1, LONG HazardX2, LONG HazardY2);
- INT  INTERNAL_CALL MouseSafetyOnDrawEnd(SURFOBJ *SurfObj);
+ INT  INTERNAL_CALL MouseSafetyOnDrawStart(PPDEVOBJ ppdev, LONG HazardX1, LONG HazardY1, LONG HazardX2, LONG HazardY2);
+ INT  INTERNAL_CALL MouseSafetyOnDrawEnd(PPDEVOBJ ppdev);
  
  #ifndef XBUTTON1
  #define XBUTTON1      (0x01)
@@@ -87,9 -87,6 +87,6 @@@ typedef struct _USER_MESSAGE_QUEU
    /* Caret information for this queue */
    PTHRDCARETINFO CaretInfo;
  
-   /* Window hooks */
-   PHOOKTABLE Hooks;
    /* queue state tracking */
    WORD WakeMask;
    WORD QueueBits;
@@@ -212,9 -209,6 +209,6 @@@ BOOL APIENTRY IntInitMessagePumpHook()
  BOOL APIENTRY IntUninitMessagePumpHook();
  #define MAKE_LONG(x, y) ((((y) & 0xFFFF) << 16) | ((x) & 0xFFFF))
  
- PHOOKTABLE FASTCALL MsqGetHooks(PUSER_MESSAGE_QUEUE Queue);
- VOID FASTCALL MsqSetHooks(PUSER_MESSAGE_QUEUE Queue, PHOOKTABLE Hooks);
  LPARAM FASTCALL MsqSetMessageExtraInfo(LPARAM lParam);
  LPARAM FASTCALL MsqGetMessageExtraInfo(VOID);
  VOID APIENTRY MsqRemoveWindowMessagesFromQueue(PVOID pWindow); /* F*(&$ headers, will be gone in the rewrite! */
@@@ -40,7 -40,7 +40,7 @@@ typedef struct _PALETT
    PALOBJ PalObj;
    XLATEOBJ *logicalToSystem;
    HPALETTE Self;
-   ULONG Mode; // PAL_INDEXED, PAL_BITFIELDS, PAL_RGB, PAL_BGR
+   FLONG flFlags; // PAL_INDEXED, PAL_BITFIELDS, PAL_RGB, PAL_BGR
    ULONG NumColors;
    PALETTEENTRY *IndexedColors;
    ULONG RedMask;
@@@ -52,8 -52,8 +52,8 @@@
    HDEV  hPDev;
  } PALETTE, *PPALETTE;
  
- extern PALETTE gpalRGB, gpalBGR, gpalMono;
+ extern PALETTE gpalRGB, gpalBGR, gpalMono, gpalRGB555, gpalRGB565, *gppalDefault;
+ extern PPALETTE appalSurfaceDefault[];
  
  HPALETTE FASTCALL PALETTE_AllocPalette(ULONG Mode,
                                         ULONG NumColors,
@@@ -1,6 -1,5 +1,5 @@@
- #pragma once
- #include <drivers/directx/directxint.h>
+ #ifndef __WIN32K_PDEVOBJ_H
+ #define __WIN32K_PDEVOBJ_H
  
  /* PDEVOBJ flags */
  #define PDEV_DISPLAY             0x00000001 /* Display device */
@@@ -37,6 -36,21 +36,21 @@@ typedef struct _GDIPOINTER /* should st
    RECTL    Exclude; /* required publicly for SPS_ACCEPT_EXCLUDE */
  } GDIPOINTER, *PGDIPOINTER;
  
+ typedef struct _DEVMODEINFO
+ {
+     struct _DEVMODEINFO *pdmiNext;
+     struct _LDEVOBJ *pldev;
+     ULONG cbdevmode;
+     DEVMODEW adevmode[1];
+ } DEVMODEINFO, *PDEVMODEINFO;
+ typedef struct
+ {
+     DWORD dwFlags;
+     PDEVMODEW pdm;
+ } DEVMODEENTRY, *PDEVMODEENTRY;
  typedef struct _GRAPHICS_DEVICE
  {
      WCHAR            szNtDeviceName[CCHDEVICENAME/2];
      DWORD            hkClassDriverConfig;
      DWORD            StateFlags;                     /* See DISPLAY_DEVICE_* */
      ULONG            cbdevmodeInfo;
-     PVOID            devmodeInfo;
-     DWORD            cbdevmodeInfo1;
-     PVOID            devmodeInfo1;
-     LPWSTR           pwszDeviceNames;
+     PDEVMODEINFO     pdevmodeInfo;
+     ULONG            cDevModes;
+     PDEVMODEENTRY    pDevModeList;
+     LPWSTR           pDiplayDrivers;
      LPWSTR           pwszDescription;
      DWORD            dwUnknown;
      PVOID            pUnknown;
      PFILE_OBJECT     FileObject;
      DWORD            ProtocolType;
+     ULONG            iDefaultMode;
+     ULONG            iCurrentMode;
  } GRAPHICS_DEVICE, *PGRAPHICS_DEVICE;
  
  typedef struct _PDEVOBJ
@@@ -64,8 -80,8 +80,8 @@@
      BASEOBJECT                BaseObject;
  
      struct _PDEVOBJ *         ppdevNext;
-     INT                       cPdevRefs;
-     INT                       cPdevOpenRefs;
+     LONG                      cPdevRefs;
+     LONG                      cPdevOpenRefs;
      struct _PDEVOBJ *         ppdevParent;
      FLONG                     flFlags;  // flags
  //  FLONG                     flAccelerated;
  //  PFN_DrvSetPalette         pfnDrvSetPalette;
  //  PFN_DrvNotify             pfnDrvNotify;
  //  ULONG                     TagSig;
//  PLDEVOBJ                  pldev;
    struct _LDEVOBJ *         pldev;
      DHPDEV                    dhpdev;         /* DHPDEV for device. */
-     PVOID                     ppalSurf;       /* PEPALOBJ/PPALETTE for this device. */
+     struct _PALETTE*          ppalSurf;       /* PEPALOBJ/PPALETTE for this device. */
      DEVINFO                   devinfo;
      GDIINFO                   gdiinfo;
-     HSURF                     pSurface;       /* SURFACE for this device., FIXME: PSURFACE */
+     PSURFACE                  pSurface;       /* SURFACE for this device. */
  //  HANDLE                    hSpooler;       /* Handle to spooler, if spooler dev driver. */
  //  PVOID                     pDesktopId;
      PGRAPHICS_DEVICE          pGraphicsDevice;
      POINTL                    ptlOrigion;
-     PVOID                     pdmwDev;        /* Ptr->DEVMODEW.dmSize + dmDriverExtra == alloc size. */
+     PDEVMODEW                 pdmwDev;        /* Ptr->DEVMODEW.dmSize + dmDriverExtra == alloc size. */
  //  DWORD                     Unknown3;
      FLONG                     DxDd_Flags;     /* DxDD active status flags. */
  //  LONG                      devAttr;
      union
      {
        DRIVER_FUNCTIONS        DriverFunctions;
+       DRIVER_FUNCTIONS        pfn;
        PVOID                   apfn[INDEX_LAST];         // B8C 0x0598
      };
  
      /* ros specific */
      ULONG         DxDd_nCount;
-     ULONG         DisplayNumber;
-     DEVMODEW      DMW;
-     PFILE_OBJECT  VideoFileObject;
-     BOOLEAN       PreparedDriver;
      GDIPOINTER    Pointer;
      /* Stuff to keep track of software cursors; win32k gdi part */
      UINT SafetyRemoveLevel; /* at what level was the cursor removed?
      struct _EDD_DIRECTDRAW_GLOBAL * pEDDgpl;
  } PDEVOBJ, *PPDEVOBJ;
  
- /* PDEV and EDDX extra data container.*/
- typedef struct _PDEVEDD
- {
-     PDEVOBJ pdevobj;
-     EDD_DIRECTDRAW_GLOBAL EDDgpl;
- } PDEVEDD, *PPDEVEDD;
+ /* Globals ********************************************************************/
+ extern PPDEVOBJ gppdevPrimary;
+ #define pPrimarySurface gppdevPrimary
+ /* Function prototypes ********************************************************/
+ PPDEVOBJ
+ NTAPI
+ EngpGetPDEV(PUNICODE_STRING pustrDevice);
+ VOID
+ NTAPI
+ PDEVOBJ_vRelease(PPDEVOBJ ppdev);
+ PSURFACE
+ NTAPI
+ PDEVOBJ_pSurface(
+     PPDEVOBJ ppdev);
+ VOID
+ NTAPI
+ PDEVOBJ_vGetDeviceCaps(
+     PPDEVOBJ ppdev,
+     PDEVCAPS pDevCaps);
+ BOOL
+ NTAPI
+ InitPDEVImpl();
+ BOOL
+ NTAPI
+ InitLDEVImpl();
+ BOOL
+ NTAPI
+ InitDeviceImpl();
  
- PSIZEL FASTCALL PDEV_sizl(PPDEVOBJ, PSIZEL);
+ PSIZEL
+ FASTCALL
+ PDEVOBJ_sizl(PPDEVOBJ, PSIZEL);
  
- extern ULONG gdwDirectDrawContext;
+ #endif /* !__WIN32K_PDEVOBJ_H */
@@@ -14,7 -14,7 +14,7 @@@ typedef struct _ROSRGNDAT
  
    RGNDATAHEADER rdh;
    RECTL        *Buffer;
- } ROSRGNDATA, *PROSRGNDATA, *LPROSRGNDATA;
+ } ROSRGNDATA, *PROSRGNDATA, *LPROSRGNDATA, REGION, *PREGION;
  
  
  /* Functions ******************************************************************/
@@@ -8,48 -8,88 +8,88 @@@
  /* GDI surface object */
  typedef struct _SURFACE
  {
-   BASEOBJECT  BaseObject;
-   SURFOBJ     SurfObj;
-   FLONG             flHooks;
-   FLONG       flFlags;
-   struct _PALETTE  *ppal;
-   union
-   {
-     HANDLE    hSecureUMPD;  // if UMPD_SURFACE set
-     HANDLE    hMirrorParent;// if MIRROR_SURFACE set
-     HANDLE    hDDSurface;   // if DIRECTDRAW_SURFACE set
-   };
-   SIZEL       dimension;    /* For SetBitmapDimension(), do NOT use
+     BASEOBJECT  BaseObject;
+     SURFOBJ     SurfObj;
+     //XDCOBJ *   pdcoAA;
+     FLONG       flags;
+     struct _PALETTE  *ppal;
+     //UINT       unk_050;
+     union
+     {
+         HANDLE  hSecureUMPD;  // if UMPD_SURFACE set
+         HANDLE  hMirrorParent;// if MIRROR_SURFACE set
+         HANDLE  hDDSurface;   // if DIRECTDRAW_SURFACE set
+     };
+     SIZEL       sizlDim;      /* For SetBitmapDimension(), do NOT use
                                 to get width/height of bitmap, use
                                 bitmap.bmWidth/bitmap.bmHeight for
                                 that */
-   
-   HDC         hDC; // Doc in "Undocumented Windows", page 546, seems to be supported with XP.
-   ULONG       cRef;         // 0x064
-   HPALETTE    hpalHint;
  
-   /* For device-independent bitmaps: */
-   HANDLE      hDIBSection;
-   HANDLE      hSecure;
-   DWORD       dwOffset;
+     HDC         hdc;          // Doc in "Undocumented Windows", page 546, seems to be supported with XP.
+     ULONG       cRef;
+     HPALETTE    hpalHint;
+     /* For device-independent bitmaps: */
+     HANDLE      hDIBSection;
+     HANDLE      hSecure;
+     DWORD       dwOffset;
+     //UINT       unk_078;
  
    /* reactos specific */
-   PFAST_MUTEX BitsLock;     /* You need to hold this lock before you touch
-                                the actual bits in the bitmap */
-   HPALETTE hDIBPalette;
-   DWORD dsBitfields[3]; // hack, should probably use palette instead
-   DWORD biClrUsed;
-   DWORD biClrImportant;
+     DWORD biClrImportant;
  } SURFACE, *PSURFACE;
  
- #define BITMAPOBJ_IS_APIBITMAP                0x1
+ // flags field:
+ //#define HOOK_BITBLT               0x00000001
+ //#define HOOK_STRETCHBLT           0x00000002
+ //#define HOOK_PLGBLT               0x00000004
+ //#define HOOK_TEXTOUT              0x00000008
+ //#define HOOK_PAINT                0x00000010
+ //#define HOOK_STROKEPATH           0x00000020
+ //#define HOOK_FILLPATH             0x00000040
+ //#define HOOK_STROKEANDFILLPATH    0x00000080
+ //#define HOOK_LINETO               0x00000100
+ //#define SHAREACCESS_SURFACE       0x00000200
+ //#define HOOK_COPYBITS             0x00000400
+ //#define REDIRECTION_SURFACE       0x00000800 // ?
+ //#define HOOK_MOVEPANNING          0x00000800
+ //#define HOOK_SYNCHRONIZE          0x00001000
+ //#define HOOK_STRETCHBLTROP        0x00002000
+ //#define HOOK_SYNCHRONIZEACCESS    0x00004000
+ //#define USE_DEVLOCK_SURFACE       0x00004000
+ //#define HOOK_TRANSPARENTBLT       0x00008000
+ //#define HOOK_ALPHABLEND           0x00010000
+ //#define HOOK_GRADIENTFILL         0x00020000
+ //#if (NTDDI_VERSION < 0x06000000)
+ // #define HOOK_FLAGS               0x0003B5FF
+ //#else
+ // #define HOOK_FLAGS               0x0003B5EF
+ //#endif
+ #define UMPD_SURFACE              0x00040000
+ #define MIRROR_SURFACE            0x00080000
+ #define DIRECTDRAW_SURFACE        0x00100000
+ #define DRIVER_CREATED_SURFACE    0x00200000
+ #define ENG_CREATE_DEVICE_SURFACE 0x00400000
+ #define DDB_SURFACE               0x00800000
+ #define LAZY_DELETE_SURFACE       0x01000000
+ #define BANDING_SURFACE           0x02000000
+ #define API_BITMAP                0x04000000
+ #define PALETTE_SELECT_SET        0x08000000
+ #define UNREADABLE_SURFACE        0x10000000
+ #define DYNAMIC_MODE_PALETTE      0x20000000
+ #define ABORT_SURFACE             0x40000000
+ #define PDEV_SURFACE              0x80000000
+ #define BMF_DONT_FREE 0x100
+ #define BMF_RLE_HACK  0x200
  
  /*  Internal interface  */
  
- #define SURFACE_AllocSurface()    ((PSURFACE) GDIOBJ_AllocObj(GDIObjType_SURF_TYPE))
  #define SURFACE_AllocSurfaceWithHandle()    ((PSURFACE) GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_BITMAP))
  #define SURFACE_FreeSurface(pBMObj) GDIOBJ_FreeObj((POBJ) pBMObj, GDIObjType_SURF_TYPE)
  #define SURFACE_FreeSurfaceByHandle(hBMObj) GDIOBJ_FreeObjByHandle((HGDIOBJ) hBMObj, GDI_OBJECT_TYPE_BITMAP)
  #define  SURFACE_ShareUnlockSurface(pBMObj)  \
    GDIOBJ_ShareUnlockObjByPtr ((POBJ)pBMObj)
  
- #define SURFACE_LockBitmapBits(pBMObj) ExEnterCriticalRegionAndAcquireFastMutexUnsafe((pBMObj)->BitsLock)
- #define SURFACE_UnlockBitmapBits(pBMObj) ExReleaseFastMutexUnsafeAndLeaveCriticalRegion((pBMObj)->BitsLock)
  BOOL INTERNAL_CALL SURFACE_Cleanup(PVOID ObjectBody);
- BOOL INTERNAL_CALL SURFACE_InitBitsLock(SURFACE *pBMObj);
- void INTERNAL_CALL SURFACE_CleanupBitsLock(SURFACE *pBMObj);
+ PSURFACE
+ NTAPI
+ SURFACE_AllocSurface(
+     IN ULONG iType,
+     IN ULONG cx,
+     IN ULONG cy,
+     IN ULONG iFormat);
+ BOOL
+ NTAPI
+ SURFACE_bSetBitmapBits(
+     IN PSURFACE psurf,
+     IN USHORT fjBitmap,
+     IN ULONG ulWidth,
+     IN PVOID pvBits OPTIONAL);
  
  #define GDIDEV(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))
  #define GDIDEVFUNCS(SurfObj) ((PDEVOBJ *)((SurfObj)->hdev))->DriverFunctions
  
- INT   FASTCALL BitsPerFormat (ULONG Format);
  ULONG FASTCALL BitmapFormat (WORD Bits, DWORD Compression);
+ extern UCHAR gajBitsPerFormat[];
+ #define BitsPerFormat(Format) gajBitsPerFormat[Format]
+ #define WIDTH_BYTES_ALIGN32(cx, bpp) ((((cx) * (bpp) + 31) & ~31) >> 3)
+ #define WIDTH_BYTES_ALIGN16(cx, bpp) ((((cx) * (bpp) + 15) & ~15) >> 3)
@@@ -96,6 -96,7 +96,7 @@@ typedef struct _THREADINF
      LIST_ENTRY          PtiLink;
      POINT               ptLast;
  
+     LIST_ENTRY          aphkStart[NB_HOOKS];
      CLIENTTHREADINFO    cti;  // Used only when no Desktop or pcti NULL.
    /* ReactOS */
    LIST_ENTRY WindowListHead;
@@@ -150,6 -151,8 +151,8 @@@ typedef struct _W32PROCES
    LIST_ENTRY    GDIBrushAttrFreeList;
  } W32PROCESS, *PW32PROCESS;
  
+ #define CLIBS 32
  typedef struct _PROCESSINFO
  {
    W32PROCESS;
    struct _DESKTOP* rpdeskStartup;
    PCLS pclsPrivateList;
    PCLS pclsPublicList;
+   DWORD dwhmodLibLoadedMask;
+   HANDLE ahmodLibLoaded[CLIBS];
+   struct _WINSTATION_OBJECT *prpwinsta;
+   HWINSTA hwinsta;
+   ACCESS_MASK amwinsta;
+   DWORD dwHotkey;
    HMONITOR hMonitor;
+   LUID luidSession;
    USERSTARTUPINFO usi;
-   ULONG Flags;
    DWORD dwLayout;
    DWORD dwRegisteredClasses;
    /* ReactOS */
@@@ -78,4 -78,6 +78,6 @@@
  #include <include/gdifloat.h>
  #include <include/engobjects.h>
  #include <include/engevent.h>
+ #include <include/ldevobj.h>
+ #include <include/device.h>
  #include <dib/dib.h>
@@@ -104,7 -104,7 +104,7 @@@ IntShowOwnedPopups( PWND owner, BOOL fS
  LRESULT FASTCALL
  IntDefWindowProc( PWND Window, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL Ansi);
  
- VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG);
+ VOID FASTCALL IntNotifyWinEvent(DWORD, PWND, LONG, LONG, DWORD);
  
  PWND FASTCALL co_UserCreateWindowEx(CREATESTRUCTW*, PUNICODE_STRING, PLARGE_STRING);
  WNDPROC FASTCALL IntGetWindowProc(PWND,BOOL);
@@@ -45,7 -45,6 +45,6 @@@ DbgCmpXlate(XLATEOBJ *pxlo1, XLATEOBJ *
  
  VOID NTAPI EXLATEOBJ_vInitialize(PEXLATEOBJ pexlo, PALETTE *ppalSrc, PALETTE *ppalDst, ULONG, ULONG, ULONG);
  VOID NTAPI EXLATEOBJ_vInitXlateFromDCs(PEXLATEOBJ pexlo, PDC pdcSrc, PDC pdcDst);
- VOID NTAPI EXLATEOBJ_vInitBrushXlate(PEXLATEOBJ pexlo, BRUSH *pbrush, SURFACE *psurf, COLORREF crForegroundClr, COLORREF crBackgroundClr);
  VOID NTAPI EXLATEOBJ_vInitSrcMonoXlate(PEXLATEOBJ pexlo, PPALETTE ppalDst, ULONG Color0, ULONG Color1);
  VOID NTAPI EXLATEOBJ_vCleanup(PEXLATEOBJ pexlo);
  
@@@ -34,8 -34,6 +34,6 @@@ BOOL INTERNAL_CALL GDI_CleanupForProces
  PGDI_HANDLE_TABLE GdiHandleTable = NULL;
  PSECTION_OBJECT GdiTableSection = NULL;
  
- LIST_ENTRY GlobalDriverListHead;
  HANDLE GlobalUserHeap = NULL;
  PSECTION_OBJECT GlobalUserHeapSection = NULL;
  
@@@ -175,6 -173,7 +173,7 @@@ Win32kThreadCallback(struct _ETHREAD *T
  {
      struct _EPROCESS *Process;
      PTHREADINFO Win32Thread;
+     int i;
      DECLARE_RETURN(NTSTATUS);
  
      DPRINT("Enter Win32kThreadCallback\n");
        InitializeListHead(&Win32Thread->WindowListHead);
        InitializeListHead(&Win32Thread->W32CallbackListHead);
        InitializeListHead(&Win32Thread->PtiLink);
+       for (i = 0; i < NB_HOOKS; i++)
+       {
+          InitializeListHead(&Win32Thread->aphkStart[i]);
+       }
  
        /*
         * inherit the thread desktop and process window station (if not yet inherited) from the process startup
        Win32Thread->TIF_flags |= TIF_INCLEANUP;
        DceFreeThreadDCE(Win32Thread);
        HOOK_DestroyThreadHooks(Thread);
+       EVENT_DestroyThreadEvents(Thread);
        /* Cleanup timers */
        DestroyTimersForThread(Win32Thread);
        KeSetEvent(Win32Thread->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
@@@ -362,6 -366,7 +366,7 @@@ Win32kInitWin32Thread(PETHREAD Thread
    return(STATUS_SUCCESS);
  }
  
+ C_ASSERT(sizeof(SERVERINFO) <= PAGE_SIZE);
  
  /*
   * This definition doesn't work
@@@ -417,8 -422,19 +422,19 @@@ DriverEntry 
          return STATUS_UNSUCCESSFUL;
      }
  
-   /* Initialize a list of loaded drivers in Win32 subsystem */
-   InitializeListHead(&GlobalDriverListHead);
+    if (!gpsi)
+    {
+       gpsi = UserHeapAlloc(sizeof(SERVERINFO));
+       if (gpsi)
+       {
+          RtlZeroMemory(gpsi, sizeof(SERVERINFO));
+          DPRINT("Global Server Data -> %x\n", gpsi);
+       }
+       else
+       {
+           ASSERT(FALSE);
+       }
+    }
  
    if(!hsemDriverMgmt) hsemDriverMgmt = EngCreateSemaphore();
  
        return STATUS_UNSUCCESSFUL;
    }
  
+   /* Initialize default palettes */
+   PALETTE_Init();
+   /* Create stock objects, ie. precreated objects commonly
+      used by win32 applications */
+   CreateStockObjects();
+   CreateSysColorObjects();
+   InitXlateImpl();
+   InitPDEVImpl();
+   InitLDEVImpl();
+   InitDeviceImpl();
+   Status = InitDcImpl();
+   if (!NT_SUCCESS(Status))
+   {
+     DPRINT1("Failed to initialize Device context implementation!\n");
+     return STATUS_UNSUCCESSFUL;
+   }
    Status = InitUserImpl();
    if (!NT_SUCCESS(Status))
    {
        return(Status);
      }
  
-   Status = InitDcImpl();
-   if (!NT_SUCCESS(Status))
-   {
-     DPRINT1("Failed to initialize Device context implementation!\n");
-     return STATUS_UNSUCCESSFUL;
-   }
    /* Initialize FreeType library */
    if (! InitFontSupport())
      {
        return STATUS_UNSUCCESSFUL;
      }
  
-   InitXlateImpl();
-   /* Create stock objects, ie. precreated objects commonly
-      used by win32 applications */
-   CreateStockObjects();
-   CreateSysColorObjects();
    gusLanguageID = IntGdiGetLanguageID();
  
    return STATUS_SUCCESS;
@@@ -5,7 -5,7 +5,7 @@@ NTSTATUS _MmCopyFromCaller( PVOID Targe
  
      _SEH2_TRY
      {
-         /* ProbeForRead(Source,Bytes,1); */
+         ProbeForRead(Source,Bytes,1);
          RtlCopyMemory(Target,Source,Bytes);
      }
      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@@@ -1,621 -1,1 +1,1 @@@
- /*
-  *  ReactOS W32 Subsystem
-  *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
-  *
-  *  This program is free software; you can redistribute it and/or modify
-  *  it under the terms of the GNU General Public License as published by
-  *  the Free Software Foundation; either version 2 of the License, or
-  *  (at your option) any later version.
-  *
-  *  This program is distributed in the hope that it will be useful,
-  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  *  GNU General Public License for more details.
-  *
-  *  You should have received a copy of the GNU General Public License along
-  *  with this program; if not, write to the Free Software Foundation, Inc.,
-  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-  */
- /* $Id$
-  *
-  * GDI Driver support routines
-  * (mostly swiped from Wine)
-  *
-  */
  
- #include <win32k.h>
- #define NDEBUG
- #include <debug.h>
- /* #define TRACE_DRV_CALLS to get a log of all calls into the display driver. */
- #undef TRACE_DRV_CALLS
- typedef struct _GRAPHICS_DRIVER
- {
-   PWSTR  Name;
-   PFN_DrvEnableDriver  EnableDriver;
-   int  ReferenceCount;
-   struct _GRAPHICS_DRIVER  *Next;
- } GRAPHICS_DRIVER, *PGRAPHICS_DRIVER;
- static PGRAPHICS_DRIVER  DriverList;
- static PGRAPHICS_DRIVER  GenericDriver = NULL;
- BOOL DRIVER_RegisterDriver(LPCWSTR  Name, PFN_DrvEnableDriver  EnableDriver)
- {
-   PGRAPHICS_DRIVER  Driver;
-   
-   DPRINT( "DRIVER_RegisterDriver( Name: %S )\n", Name );
-   
-   if (GenericDriver != NULL)
-   {
-      return FALSE;
-   }
-   Driver = ExAllocatePoolWithTag(PagedPool, sizeof(*Driver), TAG_DRIVER);
-   if (!Driver)  return  FALSE;
-   Driver->ReferenceCount = 0;
-   Driver->EnableDriver = EnableDriver;
-   if (Name)
-   {
-     Driver->Name = ExAllocatePoolWithTag(PagedPool,
-                                          (wcslen(Name) + 1) * sizeof(WCHAR),
-                                          TAG_DRIVER);
-     if (Driver->Name == NULL)
-     {
-         DPRINT1("Out of memory\n");
-         ExFreePoolWithTag(Driver, TAG_DRIVER);
-         return  FALSE;
-     }
-     wcscpy(Driver->Name, Name);
-     Driver->Next  = DriverList;
-     DriverList = Driver;
-     return  TRUE;
-   }
-   GenericDriver = Driver;
-   return  TRUE;
- }
- PFN_DrvEnableDriver DRIVER_FindExistingDDIDriver(LPCWSTR Name)
- {
-   GRAPHICS_DRIVER *Driver = DriverList;
-   while (Driver && Name)
-   {
-     if (!_wcsicmp(Driver->Name, Name))
-     {
-       return Driver->EnableDriver;
-     }
-     Driver = Driver->Next;
-   }
-   return NULL;
- }
- PFN_DrvEnableDriver DRIVER_FindDDIDriver(LPCWSTR Name)
- {
-   static WCHAR DefaultPath[] = L"\\SystemRoot\\System32\\";
-   static WCHAR DefaultExtension[] = L".DLL";
-   PFN_DrvEnableDriver ExistingDriver;
-   SYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo;
-   NTSTATUS Status;
-   LPWSTR FullName;
-   LPCWSTR p;
-   BOOL PathSeparatorFound;
-   BOOL DotFound;
-   UINT Size;
-   DotFound = FALSE;
-   PathSeparatorFound = FALSE;
-   p = Name;
-   while (L'\0' != *p)
-   {
-     if (L'\\' == *p || L'/' == *p)
-     {
-       PathSeparatorFound = TRUE;
-       DotFound = FALSE;
-     }
-     else if (L'.' == *p)
-     {
-       DotFound = TRUE;
-     }
-     p++;
-   }
-   Size = (wcslen(Name) + 1) * sizeof(WCHAR);
-   if (! PathSeparatorFound)
-   {
-     Size += sizeof(DefaultPath) - sizeof(WCHAR);
-   }
-   if (! DotFound)
-   {
-     Size += sizeof(DefaultExtension) - sizeof(WCHAR);
-   }
-   FullName = ExAllocatePoolWithTag(PagedPool, Size, TAG_DRIVER);
-   if (NULL == FullName)
-   {
-     DPRINT1("Out of memory\n");
-     return NULL;
-   }
-   if (PathSeparatorFound)
-   {
-     FullName[0] = L'\0';
-   }
-   else
-   {
-     wcscpy(FullName, DefaultPath);
-   }
-   wcscat(FullName, Name);
-   if (! DotFound)
-   {
-     wcscat(FullName, DefaultExtension);
-   }
-   /* First see if the driver hasn't already been loaded */
-   ExistingDriver = DRIVER_FindExistingDDIDriver(FullName);
-   if (ExistingDriver)
-   {
-     ExFreePoolWithTag(FullName, TAG_DRIVER);
-     return ExistingDriver;
-   }
-   /* If not, then load it */
-   RtlInitUnicodeString (&GdiDriverInfo.DriverName, FullName);
-   Status = ZwSetSystemInformation (SystemLoadGdiDriverInformation, &GdiDriverInfo, sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
-   if (!NT_SUCCESS(Status))
-   {
-     ExFreePoolWithTag(FullName, TAG_DRIVER);
-     return NULL;
-   }
-   DRIVER_RegisterDriver( L"DISPLAY", GdiDriverInfo.EntryPoint);
-   DRIVER_RegisterDriver( FullName, GdiDriverInfo.EntryPoint);
-   ExFreePoolWithTag(FullName, TAG_DRIVER);
-   return (PFN_DrvEnableDriver)GdiDriverInfo.EntryPoint;
- }
- #define BEGIN_FUNCTION_MAP() \
-   ULONG i; \
-   for (i = 0; i < DED->c; i++) \
-   { \
-     switch(DED->pdrvfn[i].iFunc) \
-     {
- #define END_FUNCTION_MAP() \
-       default: \
-         DPRINT1("Unsupported DDI function 0x%x\n", DED->pdrvfn[i].iFunc); \
-         break; \
-     } \
-   }
- #ifdef TRACE_DRV_CALLS
- typedef struct _TRACEDRVINFO
-   {
-   unsigned Index;
-   char *Name;
-   PVOID DrvRoutine;
-   }
- TRACEDRVINFO, *PTRACEDRVINFO;
- __asm__(
- " .text\n"
- "TraceDrv:\n"
- " pushl %eax\n"
- " call  _FindTraceInfo\n"
- " add   $4,%esp\n"
- " pushl %eax\n"
- " pushl 4(%eax)\n"
- " call  _DbgPrint\n"
- " addl  $4,%esp\n"
- " popl  %eax\n"
- " mov   8(%eax),%eax\n"
- " jmp   *%eax\n"
- );
- #define TRACEDRV_ROUTINE(function) \
- unsigned TraceDrvIndex##function = INDEX_Drv##function; \
- __asm__ ( \
- " .text\n" \
- "_Trace" #function ":\n" \
- " movl _TraceDrvIndex" #function ",%eax\n" \
- " jmp TraceDrv\n" \
- ); \
- extern PVOID Trace##function;
- TRACEDRV_ROUTINE(EnablePDEV)
- TRACEDRV_ROUTINE(CompletePDEV)
- TRACEDRV_ROUTINE(DisablePDEV)
- TRACEDRV_ROUTINE(EnableSurface)
- TRACEDRV_ROUTINE(DisableSurface)
- TRACEDRV_ROUTINE(AssertMode)
- TRACEDRV_ROUTINE(Offset)
- TRACEDRV_ROUTINE(ResetPDEV)
- TRACEDRV_ROUTINE(DisableDriver)
- TRACEDRV_ROUTINE(CreateDeviceBitmap)
- TRACEDRV_ROUTINE(DeleteDeviceBitmap)
- TRACEDRV_ROUTINE(RealizeBrush)
- TRACEDRV_ROUTINE(DitherColor)
- TRACEDRV_ROUTINE(StrokePath)
- TRACEDRV_ROUTINE(FillPath)
- TRACEDRV_ROUTINE(StrokeAndFillPath)
- TRACEDRV_ROUTINE(Paint)
- TRACEDRV_ROUTINE(BitBlt)
- TRACEDRV_ROUTINE(TransparentBlt)
- TRACEDRV_ROUTINE(CopyBits)
- TRACEDRV_ROUTINE(StretchBlt)
- TRACEDRV_ROUTINE(StretchBltROP)
- TRACEDRV_ROUTINE(SetPalette)
- TRACEDRV_ROUTINE(TextOut)
- TRACEDRV_ROUTINE(Escape)
- TRACEDRV_ROUTINE(DrawEscape)
- TRACEDRV_ROUTINE(QueryFont)
- TRACEDRV_ROUTINE(QueryFontTree)
- TRACEDRV_ROUTINE(QueryFontData)
- TRACEDRV_ROUTINE(SetPointerShape)
- TRACEDRV_ROUTINE(MovePointer)
- TRACEDRV_ROUTINE(LineTo)
- TRACEDRV_ROUTINE(SendPage)
- TRACEDRV_ROUTINE(StartPage)
- TRACEDRV_ROUTINE(EndDoc)
- TRACEDRV_ROUTINE(StartDoc)
- TRACEDRV_ROUTINE(GetGlyphMode)
- TRACEDRV_ROUTINE(Synchronize)
- TRACEDRV_ROUTINE(SaveScreenBits)
- TRACEDRV_ROUTINE(GetModes)
- TRACEDRV_ROUTINE(Free)
- TRACEDRV_ROUTINE(DestroyFont)
- TRACEDRV_ROUTINE(QueryFontCaps)
- TRACEDRV_ROUTINE(LoadFontFile)
- TRACEDRV_ROUTINE(UnloadFontFile)
- TRACEDRV_ROUTINE(FontManagement)
- TRACEDRV_ROUTINE(QueryTrueTypeTable)
- TRACEDRV_ROUTINE(QueryTrueTypeOutline)
- TRACEDRV_ROUTINE(GetTrueTypeFile)
- TRACEDRV_ROUTINE(QueryFontFile)
- TRACEDRV_ROUTINE(QueryAdvanceWidths)
- TRACEDRV_ROUTINE(SetPixelFormat)
- TRACEDRV_ROUTINE(DescribePixelFormat)
- TRACEDRV_ROUTINE(SwapBuffers)
- TRACEDRV_ROUTINE(StartBanding)
- TRACEDRV_ROUTINE(NextBand)
- TRACEDRV_ROUTINE(GetDirectDrawInfo)
- TRACEDRV_ROUTINE(EnableDirectDraw)
- TRACEDRV_ROUTINE(DisableDirectDraw)
- TRACEDRV_ROUTINE(QuerySpoolType)
- TRACEDRV_ROUTINE(IcmSetDeviceGammaRamp)
- TRACEDRV_ROUTINE(GradientFill)
- TRACEDRV_ROUTINE(SynchronizeSurface)
- TRACEDRV_ROUTINE(AlphaBlend)
- #define TRACEDRVINFO_ENTRY(function) \
-     { INDEX_Drv##function, "Drv" #function "\n", NULL }
- static TRACEDRVINFO TraceDrvInfo[] =
-   {
-     TRACEDRVINFO_ENTRY(EnablePDEV),
-     TRACEDRVINFO_ENTRY(CompletePDEV),
-     TRACEDRVINFO_ENTRY(DisablePDEV),
-     TRACEDRVINFO_ENTRY(EnableSurface),
-     TRACEDRVINFO_ENTRY(DisableSurface),
-     TRACEDRVINFO_ENTRY(AssertMode),
-     TRACEDRVINFO_ENTRY(Offset),
-     TRACEDRVINFO_ENTRY(ResetPDEV),
-     TRACEDRVINFO_ENTRY(DisableDriver),
-     TRACEDRVINFO_ENTRY(CreateDeviceBitmap),
-     TRACEDRVINFO_ENTRY(DeleteDeviceBitmap),
-     TRACEDRVINFO_ENTRY(RealizeBrush),
-     TRACEDRVINFO_ENTRY(DitherColor),
-     TRACEDRVINFO_ENTRY(StrokePath),
-     TRACEDRVINFO_ENTRY(FillPath),
-     TRACEDRVINFO_ENTRY(StrokeAndFillPath),
-     TRACEDRVINFO_ENTRY(Paint),
-     TRACEDRVINFO_ENTRY(BitBlt),
-     TRACEDRVINFO_ENTRY(TransparentBlt),
-     TRACEDRVINFO_ENTRY(CopyBits),
-     TRACEDRVINFO_ENTRY(StretchBlt),
-     TRACEDRVINFO_ENTRY(StretchBltROP),
-     TRACEDRVINFO_ENTRY(SetPalette),
-     TRACEDRVINFO_ENTRY(TextOut),
-     TRACEDRVINFO_ENTRY(Escape),
-     TRACEDRVINFO_ENTRY(DrawEscape),
-     TRACEDRVINFO_ENTRY(QueryFont),
-     TRACEDRVINFO_ENTRY(QueryFontTree),
-     TRACEDRVINFO_ENTRY(QueryFontData),
-     TRACEDRVINFO_ENTRY(SetPointerShape),
-     TRACEDRVINFO_ENTRY(MovePointer),
-     TRACEDRVINFO_ENTRY(LineTo),
-     TRACEDRVINFO_ENTRY(SendPage),
-     TRACEDRVINFO_ENTRY(StartPage),
-     TRACEDRVINFO_ENTRY(EndDoc),
-     TRACEDRVINFO_ENTRY(StartDoc),
-     TRACEDRVINFO_ENTRY(GetGlyphMode),
-     TRACEDRVINFO_ENTRY(Synchronize),
-     TRACEDRVINFO_ENTRY(SaveScreenBits),
-     TRACEDRVINFO_ENTRY(GetModes),
-     TRACEDRVINFO_ENTRY(Free),
-     TRACEDRVINFO_ENTRY(DestroyFont),
-     TRACEDRVINFO_ENTRY(QueryFontCaps),
-     TRACEDRVINFO_ENTRY(LoadFontFile),
-     TRACEDRVINFO_ENTRY(UnloadFontFile),
-     TRACEDRVINFO_ENTRY(FontManagement),
-     TRACEDRVINFO_ENTRY(QueryTrueTypeTable),
-     TRACEDRVINFO_ENTRY(QueryTrueTypeOutline),
-     TRACEDRVINFO_ENTRY(GetTrueTypeFile),
-     TRACEDRVINFO_ENTRY(QueryFontFile),
-     TRACEDRVINFO_ENTRY(QueryAdvanceWidths),
-     TRACEDRVINFO_ENTRY(SetPixelFormat),
-     TRACEDRVINFO_ENTRY(DescribePixelFormat),
-     TRACEDRVINFO_ENTRY(SwapBuffers),
-     TRACEDRVINFO_ENTRY(StartBanding),
-     TRACEDRVINFO_ENTRY(NextBand),
-     TRACEDRVINFO_ENTRY(GetDirectDrawInfo),
-     TRACEDRVINFO_ENTRY(EnableDirectDraw),
-     TRACEDRVINFO_ENTRY(DisableDirectDraw),
-     TRACEDRVINFO_ENTRY(QuerySpoolType),
-     TRACEDRVINFO_ENTRY(IcmSetDeviceGammaRamp),
-     TRACEDRVINFO_ENTRY(GradientFill),
-     TRACEDRVINFO_ENTRY(SynchronizeSurface),
-     TRACEDRVINFO_ENTRY(AlphaBlend)
-   };
- PTRACEDRVINFO
- FindTraceInfo(unsigned Index)
- {
-   unsigned i;
-   for (i = 0; i < sizeof(TraceDrvInfo) / sizeof(TRACEDRVINFO); i++)
-     {
-       if (TraceDrvInfo[i].Index == Index)
-         {
-           return TraceDrvInfo + i;
-         }
-     }
-   return NULL;
- }
- #define DRIVER_FUNCTION(function) \
-       case INDEX_Drv##function: \
-         FindTraceInfo(INDEX_Drv##function)->DrvRoutine = DED->pdrvfn[i].pfn; \
-         *(PVOID*)&DF->function = &Trace##function; \
-         break
- #else
- #define DRIVER_FUNCTION(function) \
-       case INDEX_Drv##function: \
-         *(PVOID*)&DF->function = DED->pdrvfn[i].pfn; \
-         break
- #endif
- BOOL DRIVER_BuildDDIFunctions(PDRVENABLEDATA  DED,
-                                PDRIVER_FUNCTIONS  DF)
- {
-   BEGIN_FUNCTION_MAP();
-     DRIVER_FUNCTION(EnablePDEV);   
-     DRIVER_FUNCTION(CompletePDEV);
-     DRIVER_FUNCTION(DisablePDEV);
-     DRIVER_FUNCTION(EnableSurface);
-     DRIVER_FUNCTION(DisableSurface);
-     DRIVER_FUNCTION(AssertMode);
-     DRIVER_FUNCTION(Offset);
-     DRIVER_FUNCTION(ResetPDEV);
-     DRIVER_FUNCTION(DisableDriver);
-     DRIVER_FUNCTION(Unknown1);
-     DRIVER_FUNCTION(CreateDeviceBitmap);
-     DRIVER_FUNCTION(DeleteDeviceBitmap);
-     DRIVER_FUNCTION(RealizeBrush);
-     DRIVER_FUNCTION(DitherColor);
-     DRIVER_FUNCTION(StrokePath);
-     DRIVER_FUNCTION(FillPath);
-     DRIVER_FUNCTION(StrokeAndFillPath);
-     DRIVER_FUNCTION(Paint);
-     DRIVER_FUNCTION(BitBlt);
-     DRIVER_FUNCTION(CopyBits);
-     DRIVER_FUNCTION(StretchBlt);
-     DRIVER_FUNCTION(Unknown2);    
-     DRIVER_FUNCTION(SetPalette);
-     DRIVER_FUNCTION(TextOut);
-     DRIVER_FUNCTION(Escape);
-     DRIVER_FUNCTION(DrawEscape);
-     DRIVER_FUNCTION(QueryFont);
-     DRIVER_FUNCTION(QueryFontTree);
-     DRIVER_FUNCTION(QueryFontData);
-     DRIVER_FUNCTION(SetPointerShape);
-     DRIVER_FUNCTION(MovePointer);
-     DRIVER_FUNCTION(LineTo);
-     DRIVER_FUNCTION(SendPage);
-     DRIVER_FUNCTION(StartPage);
-     DRIVER_FUNCTION(EndDoc);
-     DRIVER_FUNCTION(StartDoc);
-     DRIVER_FUNCTION(Unknown3);
-     DRIVER_FUNCTION(GetGlyphMode);
-     DRIVER_FUNCTION(Synchronize);
-     DRIVER_FUNCTION(Unknown4);
-     DRIVER_FUNCTION(SaveScreenBits);
-     DRIVER_FUNCTION(GetModes);
-     DRIVER_FUNCTION(Free);
-     DRIVER_FUNCTION(DestroyFont);
-     DRIVER_FUNCTION(QueryFontCaps);
-     DRIVER_FUNCTION(LoadFontFile);
-     DRIVER_FUNCTION(UnloadFontFile);
-     DRIVER_FUNCTION(FontManagement);
-     DRIVER_FUNCTION(QueryTrueTypeTable);
-     DRIVER_FUNCTION(QueryTrueTypeOutline);
-     DRIVER_FUNCTION(GetTrueTypeFile);
-     DRIVER_FUNCTION(QueryFontFile);
-     DRIVER_FUNCTION(QueryAdvanceWidths);
-     DRIVER_FUNCTION(SetPixelFormat);
-     DRIVER_FUNCTION(DescribePixelFormat);
-     DRIVER_FUNCTION(SwapBuffers);
-     DRIVER_FUNCTION(StartBanding);
-     DRIVER_FUNCTION(NextBand);
-     DRIVER_FUNCTION(GetDirectDrawInfo);
-     DRIVER_FUNCTION(EnableDirectDraw);
-     DRIVER_FUNCTION(DisableDirectDraw);
-     DRIVER_FUNCTION(QuerySpoolType);
-     DRIVER_FUNCTION(Unknown5);   
-     DRIVER_FUNCTION(IcmCreateColorTransform);   
-     DRIVER_FUNCTION(IcmDeleteColorTransform);   
-     DRIVER_FUNCTION(IcmCheckBitmapBits);   
-     DRIVER_FUNCTION(IcmSetDeviceGammaRamp);   
-     DRIVER_FUNCTION(GradientFill);   
-     DRIVER_FUNCTION(StretchBltROP);   
-     DRIVER_FUNCTION(PlgBlt);   
-     DRIVER_FUNCTION(AlphaBlend);   
-     DRIVER_FUNCTION(SynthesizeFont);   
-     DRIVER_FUNCTION(GetSynthesizedFontFiles);   
-     DRIVER_FUNCTION(TransparentBlt);   
-     DRIVER_FUNCTION(QueryPerBandInfo);   
-     DRIVER_FUNCTION(QueryDeviceSupport);   
-     DRIVER_FUNCTION(Reserved1);   
-     DRIVER_FUNCTION(Reserved2);   
-     DRIVER_FUNCTION(Reserved3);   
-     DRIVER_FUNCTION(Reserved4);   
-     DRIVER_FUNCTION(Reserved5);   
-     DRIVER_FUNCTION(Reserved6); 
-     DRIVER_FUNCTION(Reserved7); 
-     DRIVER_FUNCTION(Reserved8); 
-     DRIVER_FUNCTION(DeriveSurface); 
-     DRIVER_FUNCTION(QueryGlyphAttrs); 
-     DRIVER_FUNCTION(Notify); 
-     DRIVER_FUNCTION(SynchronizeSurface); 
-     DRIVER_FUNCTION(ResetDevice); 
-     DRIVER_FUNCTION(Reserved9); 
-     DRIVER_FUNCTION(Reserved10); 
-     DRIVER_FUNCTION(Reserved11);     
-   END_FUNCTION_MAP();
-   return TRUE;
- }
- typedef LONG VP_STATUS;
- typedef VP_STATUS (APIENTRY *PMP_DRIVERENTRY)(PVOID, PVOID);
- PFILE_OBJECT DRIVER_FindMPDriver(ULONG DisplayNumber)
- {
-   OBJECT_ATTRIBUTES ObjectAttributes;
-   WCHAR DeviceNameBuffer[20];
-   UNICODE_STRING DeviceName;
-   IO_STATUS_BLOCK Iosb;
-   HANDLE DisplayHandle;
-   NTSTATUS Status;
-   PFILE_OBJECT VideoFileObject;
-   swprintf(DeviceNameBuffer, L"\\??\\DISPLAY%d", DisplayNumber + 1);
-   RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
-   InitializeObjectAttributes(&ObjectAttributes,
-                            &DeviceName,
-                            0,
-                            NULL,
-                            NULL);
-   Status = ZwOpenFile(&DisplayHandle,
-                     FILE_ALL_ACCESS,
-                     &ObjectAttributes,
-                     &Iosb,
-                     0,
-                     FILE_SYNCHRONOUS_IO_ALERT);
-   if (NT_SUCCESS(Status))
-     {
-       Status = ObReferenceObjectByHandle(DisplayHandle,
-                                          FILE_READ_DATA | FILE_WRITE_DATA,
-                                          IoFileObjectType,
-                                          KernelMode,
-                                          (PVOID *)&VideoFileObject,
-                                          NULL);
-       ZwClose(DisplayHandle);
-     }
-   if (!NT_SUCCESS(Status))
-     {
-       DPRINT1("Unable to connect to miniport (Status %lx)\n", Status);
-       DPRINT1("Perhaps the miniport wasn't loaded?\n");
-       return(NULL);
-     }
-   return VideoFileObject;
- }
- BOOL DRIVER_UnregisterDriver(LPCWSTR  Name)
- {
-   PGRAPHICS_DRIVER  Driver = NULL;
-   if (Name)
-   {
-     if (DriverList != NULL)
-     {
-       if (!_wcsicmp(DriverList->Name, Name))
-       {
-         Driver = DriverList;
-         DriverList = DriverList->Next;
-       }
-       else
-       {
-         Driver = DriverList;
-         while (Driver->Next && _wcsicmp(Driver->Name, Name))
-         {
-           Driver = Driver->Next;
-         }
-       }
-     }
-   }
-   else
-   {
-     if (GenericDriver != NULL)
-     {
-       Driver = GenericDriver;
-       GenericDriver = NULL;
-     }
-   }
-   if (Driver != NULL)
-   {
-     ExFreePoolWithTag(Driver->Name, TAG_DRIVER);
-     ExFreePoolWithTag(Driver, TAG_DRIVER);
-     return  TRUE;
-   }
-   else
-   {
-     return  FALSE;
-   }
- }
- INT DRIVER_ReferenceDriver (LPCWSTR  Name)
- {
-   GRAPHICS_DRIVER *Driver = DriverList;
-   while (Driver && Name)
-   {
-     DPRINT( "Comparing %S to %S\n", Driver->Name, Name );
-     if (!_wcsicmp( Driver->Name, Name))
-     {
-       return ++Driver->ReferenceCount;
-     }
-     Driver = Driver->Next;
-   }
-   DPRINT( "Driver %S not found to reference, generic count: %d\n", Name, GenericDriver->ReferenceCount );
-   ASSERT( GenericDriver != 0 );
-   return ++GenericDriver->ReferenceCount;
- }
- INT DRIVER_UnreferenceDriver (LPCWSTR  Name)
- {
-   GRAPHICS_DRIVER *Driver = DriverList;
-   while (Driver && Name)
-   {
-     DPRINT( "Comparing %S to %S\n", Driver->Name, Name );
-     if (!_wcsicmp( Driver->Name, Name))
-     {
-       return --Driver->ReferenceCount;
-     }
-     Driver = Driver->Next;
-   }
-   DPRINT( "Driver '%S' not found to dereference, generic count: %d\n", Name, GenericDriver->ReferenceCount );
-   ASSERT( GenericDriver != 0 );
-   return --GenericDriver->ReferenceCount;
- }
- /* EOF */
@@@ -149,213 -149,98 +149,98 @@@ W32kMapViewOfSection
      return pvBase;
  }
  
- typedef struct tagBITMAPV5INFO
- {
-     BITMAPV5HEADER bmiHeader;
-     RGBQUAD        bmiColors[256];
- } BITMAPV5INFO, *PBITMAPV5INFO;
- // FIXME: this should go to dibobj.c
- NTSTATUS
- ProbeAndConvertBitmapInfo(
-     OUT BITMAPV5HEADER *pbmhDst,
-     OUT RGBQUAD *pbmiColorsDst,
-     ULONG cColors,
-     IN  PBITMAPINFO pbmiUnsafe)
- {
-     DWORD dwSize;
-     RGBQUAD *pbmiColors;
-     ULONG ulWidthBytes;
-     /* Get the size and probe */
-     ProbeForRead(&pbmiUnsafe->bmiHeader.biSize, sizeof(DWORD), 1);
-     dwSize = pbmiUnsafe->bmiHeader.biSize;
-     ProbeForRead(pbmiUnsafe, dwSize, 1);
-     /* Check the size */
-     // FIXME: are intermediate sizes allowed? As what are they interpreted?
-     //        make sure we don't use a too big dwSize later
-     if (dwSize != sizeof(BITMAPCOREHEADER) &&
-         dwSize != sizeof(BITMAPINFOHEADER) &&
-         dwSize != sizeof(BITMAPV4HEADER) &&
-         dwSize != sizeof(BITMAPV5HEADER))
-     {
-         return STATUS_INVALID_PARAMETER;
-     }
-     pbmiColors = (RGBQUAD*)((PCHAR)pbmiUnsafe + dwSize);
-     pbmhDst->bV5Size = sizeof(BITMAPV5HEADER);
-     if (dwSize == sizeof(BITMAPCOREHEADER))
-     {
-         PBITMAPCOREHEADER pbch = (PBITMAPCOREHEADER)pbmiUnsafe;
-         /* Manually copy the fields that are present */
-         pbmhDst->bV5Width = pbch->bcWidth;
-         pbmhDst->bV5Height = pbch->bcHeight;
-         pbmhDst->bV5Planes = pbch->bcPlanes;
-         pbmhDst->bV5BitCount = pbch->bcBitCount;
-         /* Set some default values */
-         pbmhDst->bV5Compression = BI_RGB;
-         pbmhDst->bV5SizeImage = 0;
-         pbmhDst->bV5XPelsPerMeter = 72;
-         pbmhDst->bV5YPelsPerMeter = 72;
-         pbmhDst->bV5ClrUsed = 0;
-         pbmhDst->bV5ClrImportant = 0;
-     }
-     else
-     {
-         /* Copy valid fields */
-         memcpy(pbmhDst, pbmiUnsafe, dwSize);
-         /* Zero out the rest of the V5 header */
-         memset((char*)pbmhDst + dwSize, 0, sizeof(BITMAPV5HEADER) - dwSize);
-     }
-     if (dwSize < sizeof(BITMAPV4HEADER))
-     {
-         if (pbmhDst->bV5Compression == BI_BITFIELDS)
-         {
-             DWORD *pMasks = (DWORD*)pbmiColors;
-             pbmhDst->bV5RedMask = pMasks[0];
-             pbmhDst->bV5GreenMask = pMasks[1];
-             pbmhDst->bV5BlueMask = pMasks[2];
-             pbmhDst->bV5AlphaMask = 0;
-             pbmhDst->bV5ClrUsed = 0;
-         }
- //        pbmhDst->bV5CSType;
- //        pbmhDst->bV5Endpoints;
- //        pbmhDst->bV5GammaRed;
- //        pbmhDst->bV5GammaGreen;
- //        pbmhDst->bV5GammaBlue;
-     }
-     if (dwSize < sizeof(BITMAPV5HEADER))
-     {
- //        pbmhDst->bV5Intent;
- //        pbmhDst->bV5ProfileData;
- //        pbmhDst->bV5ProfileSize;
- //        pbmhDst->bV5Reserved;
-     }
-     ulWidthBytes = ((pbmhDst->bV5Width * pbmhDst->bV5Planes *
-                      pbmhDst->bV5BitCount + 31) & ~31) / 8;
-     if (pbmhDst->bV5SizeImage == 0)
-         pbmhDst->bV5SizeImage = abs(ulWidthBytes * pbmhDst->bV5Height);
-     if (pbmhDst->bV5ClrUsed == 0)
-         pbmhDst->bV5ClrUsed = pbmhDst->bV5BitCount == 1 ? 2 :
-                               (pbmhDst->bV5BitCount == 4 ? 16 :
-                               (pbmhDst->bV5BitCount == 8 ? 256 : 0));
-     if (pbmhDst->bV5Planes != 1)
-     {
-         return STATUS_INVALID_PARAMETER;
-     }
-     if (pbmhDst->bV5BitCount != 0 && pbmhDst->bV5BitCount != 1 &&
-         pbmhDst->bV5BitCount != 4 && pbmhDst->bV5BitCount != 8 &&
-         pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 24 &&
-         pbmhDst->bV5BitCount != 32)
-     {
-         DPRINT("Invalid bit count: %d\n", pbmhDst->bV5BitCount);
-         return STATUS_INVALID_PARAMETER;
-     }
-     if ((pbmhDst->bV5BitCount == 0 &&
-          pbmhDst->bV5Compression != BI_JPEG && pbmhDst->bV5Compression != BI_PNG))
-     {
-         DPRINT("Bit count 0 is invalid for compression %d.\n", pbmhDst->bV5Compression);
-         return STATUS_INVALID_PARAMETER;
-     }
-     if (pbmhDst->bV5Compression == BI_BITFIELDS &&
-         pbmhDst->bV5BitCount != 16 && pbmhDst->bV5BitCount != 32)
-     {
-         DPRINT("Bit count %d is invalid for compression BI_BITFIELDS.\n", pbmhDst->bV5BitCount);
-         return STATUS_INVALID_PARAMETER;
-     }
-     /* Copy Colors */
-     cColors = min(cColors, pbmhDst->bV5ClrUsed);
-     memcpy(pbmiColorsDst, pbmiColors, cColors * sizeof(RGBQUAD));
-     return STATUS_SUCCESS;
- }
  HBITMAP
  NTAPI
  UserLoadImage(PCWSTR pwszName)
  {
-     NTSTATUS Status;
+     NTSTATUS Status = STATUS_SUCCESS;
      HANDLE hFile, hSection;
      BITMAPFILEHEADER *pbmfh;
      LPBITMAPINFO pbmi;
-     ULONG cjInfoSize;
      PVOID pvBits;
      HBITMAP hbmp = 0;
-     BITMAPV5INFO bmiLocal;
+     DPRINT("Enter UserLoadImage(%ls)\n", pwszName);
  
      /* Open the file */
      hFile = W32kOpenFile(pwszName, FILE_READ_DATA);
-     if (hFile == INVALID_HANDLE_VALUE)
-           return NULL;
+     if (!hFile)
+     {
+         return NULL;
+     }
  
      /* Create a section */
      hSection = W32kCreateFileSection(hFile, SEC_COMMIT, PAGE_READONLY, 0);
      ZwClose(hFile);
      if (!hSection)
-           return NULL;
+     {
+         return NULL;
+     }
  
      /* Map the section */
      pbmfh = W32kMapViewOfSection(hSection, PAGE_READONLY, 0);
      ZwClose(hSection);
      if (!pbmfh)
-           return NULL;
-     /* Get a pointer to the BITMAPINFO */
-     pbmi = (LPBITMAPINFO)(pbmfh + 1);
-     /* Create a normalized local BITMAPINFO */
-     _SEH2_TRY
      {
-         Status = ProbeAndConvertBitmapInfo(&bmiLocal.bmiHeader,
-                                            bmiLocal.bmiColors,
-                                            256,
-                                            pbmi);
+         return NULL;
      }
-     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-     {
-         Status = _SEH2_GetExceptionCode();
-     }
-     _SEH2_END
  
-     if (NT_SUCCESS(Status))
-     {
-         cjInfoSize = bmiLocal.bmiHeader.bV5Size +
-                      bmiLocal.bmiHeader.bV5ClrUsed * sizeof(RGBQUAD);
-         pvBits = (PVOID)((PCHAR)pbmi + cjInfoSize);
-         // FIXME: use Gre... so that the BITMAPINFO doesn't get probed
-         hbmp = NtGdiCreateDIBitmapInternal(NULL,
-                                            bmiLocal.bmiHeader.bV5Width,
-                                            bmiLocal.bmiHeader.bV5Height,
-                                            CBM_INIT,
-                                            pvBits,
-                                            pbmi,
-                                            DIB_RGB_COLORS,
-                                            bmiLocal.bmiHeader.bV5Size,
-                                            bmiLocal.bmiHeader.bV5SizeImage,
-                                            0,
-                                            0);
-     }
+     /* Get a pointer to the BITMAPINFO */
+     pbmi = (LPBITMAPINFO)(pbmfh + 1);
  
+       _SEH2_TRY
+       {
+               ProbeForRead(&pbmfh->bfSize, sizeof(DWORD), 1);
+               ProbeForRead(pbmfh, pbmfh->bfSize, 1);
+       }
+       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+       {
+               Status = _SEH2_GetExceptionCode();
+       }
+       _SEH2_END
+       if(!NT_SUCCESS(Status))
+       {
+               DPRINT1("Bad File?\n");
+               goto leave;
+       }
+     if (pbmfh->bfType == 0x4D42 /* 'BM' */)
+     {
+               /* Could be BITMAPCOREINFO */
+               BITMAPINFO* pConvertedInfo;
+               HDC hdc;
+               pvBits = (PVOID)((PCHAR)pbmfh + pbmfh->bfOffBits);
+               pConvertedInfo = DIB_ConvertBitmapInfo(pbmi, DIB_RGB_COLORS);
+               if(!pConvertedInfo)
+               {
+                       DPRINT1("Unable to convert the bitmap Info\n");
+                       goto leave;
+               }
+               hdc = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
+         hbmp = GreCreateDIBitmapInternal(hdc,
+                                          pConvertedInfo->bmiHeader.biWidth,
+                                                        pConvertedInfo->bmiHeader.biHeight,
+                                          CBM_INIT,
+                                          pvBits,
+                                          pConvertedInfo,
+                                          DIB_RGB_COLORS,
+                                          0,
+                                          0);
+               NtGdiDeleteObjectApp(hdc);
+               DIB_FreeConvertedBitmapInfo(pConvertedInfo, pbmi);
+     }
+       else
+       {
+               DPRINT1("Unknown file type!\n");
+       }
+ leave:
      /* Unmap our section, we don't need it anymore */
      ZwUnmapViewOfSection(NtCurrentProcess(), pbmfh);
  
  #define NDEBUG
  #include <debug.h>
  
+ NTSTATUS
+ NTAPI
+ RegOpenKey(
+     LPCWSTR pwszKeyName,
+     PHKEY phkey)
+ {
+     NTSTATUS Status;
+     OBJECT_ATTRIBUTES ObjectAttributes;
+     UNICODE_STRING ustrKeyName;
+     HKEY hkey;
+     /* Initialize the key name */
+     RtlInitUnicodeString(&ustrKeyName, pwszKeyName);
+     /* Initialize object attributes */
+     InitializeObjectAttributes(&ObjectAttributes,
+                                &ustrKeyName,
+                                OBJ_CASE_INSENSITIVE,
+                                NULL,
+                                NULL);
+     /* Open the key */
+     Status = ZwOpenKey(&hkey, KEY_READ, &ObjectAttributes);
+     if (NT_SUCCESS(Status))
+     {
+         *phkey = hkey;
+     }
+     return Status;
+ }
+ NTSTATUS
+ NTAPI
+ RegQueryValue(
+     IN HKEY hkey,
+     IN PCWSTR pwszValueName,
+     IN ULONG ulType,
+     OUT PVOID pvData,
+     IN OUT PULONG pcbValue)
+ {
+     NTSTATUS Status;
+     UNICODE_STRING ustrValueName;
+     BYTE ajBuffer[100];
+     PKEY_VALUE_PARTIAL_INFORMATION pInfo;
+     ULONG cbInfoSize, cbDataSize;
+     /* Check if the local buffer is sufficient */
+     cbInfoSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + *pcbValue;
+     if (cbInfoSize <= sizeof(ajBuffer))
+     {
+         pInfo = (PVOID)ajBuffer;
+     }
+     else
+     {
+         /* It's not, allocate a sufficient buffer */
+         pInfo = ExAllocatePoolWithTag(PagedPool, cbInfoSize, TAG_TEMP);
+         if (!pInfo)
+         {
+             return STATUS_INSUFFICIENT_RESOURCES;
+         }
+     }
+     /* Query the value */
+     RtlInitUnicodeString(&ustrValueName, pwszValueName);
+     Status = ZwQueryValueKey(hkey,
+                              &ustrValueName,
+                              KeyValuePartialInformation,
+                              (PVOID)pInfo,
+                              cbInfoSize,
+                              &cbInfoSize);
+     cbDataSize = cbInfoSize - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
+     if (NT_SUCCESS(Status))
+     {
+         /* Did we get the right type */
+         if (pInfo->Type == ulType)
+         {
+             /* Copy the contents to the caller */
+             RtlCopyMemory(pvData, pInfo->Data, min(*pcbValue, cbDataSize));
+         }
+         else
+             Status = STATUS_OBJECT_TYPE_MISMATCH;
+     }
+     /* Return the data size to the caller */
+     *pcbValue = cbDataSize;
+     /* Cleanup */
+     if (pInfo != (PVOID)ajBuffer)
+         ExFreePoolWithTag(pInfo, TAG_TEMP);
+     return Status;
+ }
+ VOID
+ NTAPI
+ RegWriteSZ(HKEY hkey, PWSTR pwszValue, PWSTR pwszData)
+ {
+     UNICODE_STRING ustrValue;
+     UNICODE_STRING ustrData;
+     RtlInitUnicodeString(&ustrValue, pwszValue);
+     RtlInitUnicodeString(&ustrData, pwszData);
+     ZwSetValueKey(hkey, &ustrValue, 0, REG_SZ, &ustrData, ustrData.Length + sizeof(WCHAR));
+ }
+ VOID
+ NTAPI
+ RegWriteDWORD(HKEY hkey, PWSTR pwszValue, DWORD dwData)
+ {
+     UNICODE_STRING ustrValue;
+     RtlInitUnicodeString(&ustrValue, pwszValue);
+     ZwSetValueKey(hkey, &ustrValue, 0, REG_DWORD, &dwData, sizeof(DWORD));
+ }
+ BOOL
+ NTAPI
+ RegReadDWORD(HKEY hkey, PWSTR pwszValue, PDWORD pdwData)
+ {
+     NTSTATUS Status;
+     ULONG cbSize = sizeof(DWORD);
+     Status = RegQueryValue(hkey, pwszValue, REG_DWORD, pdwData, &cbSize);
+     return NT_SUCCESS(Status);
+ }
  BOOL
  NTAPI
  RegReadUserSetting(
@@@ -163,7 -291,8 +291,8 @@@ RegWriteUserSetting
      Status = RtlAppendUnicodeToString(&usKeyName, pwszKeyName);
      if (!NT_SUCCESS(Status))
      {
-         DPRINT1("RtlAppendUnicodeToString failed with Status=%lx, buf:%d,%d\n", Status, usKeyName.Length, usKeyName.MaximumLength);
+         DPRINT1("RtlAppendUnicodeToString failed with Status=%lx, buf:%d,%d\n", 
+                 Status, usKeyName.Length, usKeyName.MaximumLength);
          return FALSE;
      }
  
@@@ -1,4 -1,4 +1,4 @@@
  /*
+ /*
   * PROJECT:          ReactOS Win32 Subsystem
   * LICENSE:          GPL - See COPYING in the top level directory
   * FILE:             subsystems/win32/win32k/ntddraw/dxeng.c
@@@ -297,8 -297,7 +297,7 @@@ DxEngGetHdevData(HDEV hDev
          break;
        case DxEGShDevData_hSpooler:
          DPRINT1("requested DXEGSHDEVDATA DxEGShDevData_hSpooler\n");
-          // retVal = (DWORD_PTR) PDev->hSpooler; // If the device is a spooler driver.
-         retVal = (DWORD_PTR) PDev->VideoFileObject->DeviceObject;
+         retVal = 0;//(DWORD_PTR) PDev->hSpooler; // If the device is a spooler driver.
          break;
        case DxEGShDevData_DitherFmt:
          DPRINT1("requested DXEGSHDEVDATA DxEGShDevData_DitherFmt\n");
@@@ -324,20 -324,18 +324,18 @@@ co_IntCallHookProc(INT HookId
                     PUNICODE_STRING ModuleName)
  {
     ULONG ArgumentLength;
-    PVOID Argument;
+    PVOID Argument = NULL;
     LRESULT Result = 0;
     NTSTATUS Status;
     PVOID ResultPointer;
     ULONG ResultLength;
     PHOOKPROC_CALLBACK_ARGUMENTS Common;
-    CBT_CREATEWNDW *CbtCreateWnd =NULL;
+    CBT_CREATEWNDW *CbtCreateWnd = NULL;
     PCHAR Extra;
     PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS CbtCreatewndExtra = NULL;
-    UNICODE_STRING WindowName;
-    UNICODE_STRING ClassName;
-    PANSI_STRING asWindowName;
-    PANSI_STRING asClassName;
     PTHREADINFO pti;
+    PWND pWnd;
+    BOOL Hit = FALSE;
  
     ASSERT(Proc);
  
           switch(Code)
           {
              case HCBT_CREATEWND:
-                CbtCreateWnd = (CBT_CREATEWNDW *) lParam;
-                ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS);
-                asWindowName = (PANSI_STRING)&WindowName;
-                asClassName = (PANSI_STRING)&ClassName;
-                if (Ansi)
-                {
-                   RtlInitAnsiString(asWindowName, (PCSZ)CbtCreateWnd->lpcs->lpszName);
-                   ArgumentLength += WindowName.Length + sizeof(CHAR);
-                }
-                else
-                {
-                   RtlInitUnicodeString(&WindowName, CbtCreateWnd->lpcs->lpszName);
-                   ArgumentLength += WindowName.Length + sizeof(WCHAR);
-                }
-                if (! IS_ATOM(CbtCreateWnd->lpcs->lpszClass))
+                pWnd = UserGetWindowObject((HWND) wParam);
+                if (!pWnd)
                 {
-                   if (Ansi)
-                   {
-                      RtlInitAnsiString(asClassName, (PCSZ)CbtCreateWnd->lpcs->lpszClass);
-                      ArgumentLength += ClassName.Length + sizeof(CHAR);
-                   }
-                   else
-                   {
-                      RtlInitUnicodeString(&ClassName, CbtCreateWnd->lpcs->lpszClass);
-                      ArgumentLength += ClassName.Length + sizeof(WCHAR);
-                   }
+                   DPRINT1("WH_CBT HCBT_CREATEWND wParam bad hWnd!\n");
+                   goto Fault_Exit;
                 }
+               // Due to KsStudio.exe, just pass the callers original pointers
+               // except class which point to kernel space if not an atom.
+               // Found by, Olaf Siejka
+                CbtCreateWnd = (CBT_CREATEWNDW *) lParam;
+                ArgumentLength += sizeof(HOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS);
                 break;
  
              case HCBT_MOVESIZE:
                 break;
              default:
                 DPRINT1("Trying to call unsupported CBT hook %d\n", Code);
-                return 0;
+                goto Fault_Exit;
           }
           break;
        case WH_KEYBOARD_LL:
           break;
        default:
           DPRINT1("Trying to call unsupported window hook %d\n", HookId);
-          return 0;
+          goto Fault_Exit;
     }
  
     Argument = IntCbAllocateMemory(ArgumentLength);
     if (NULL == Argument)
     {
        DPRINT1("HookProc callback failed: out of memory\n");
-       return 0;
+       goto Fault_Exit;
     }
     Common = (PHOOKPROC_CALLBACK_ARGUMENTS) Argument;
     Common->HookId = HookId;
     Common->Proc = Proc;
     Common->Ansi = Ansi;
     Common->ModuleNameLength = ModuleName->Length;
-    memcpy(Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
+    if (ModuleName->Buffer)
+       RtlCopyMemory(Common->ModuleName, ModuleName->Buffer, ModuleName->Length);
     Extra = (PCHAR) Common->ModuleName + Common->ModuleNameLength;
  
     switch(HookId)
                 CbtCreatewndExtra = (PHOOKPROC_CBT_CREATEWND_EXTRA_ARGUMENTS) Extra;
                 RtlCopyMemory( &CbtCreatewndExtra->Cs, CbtCreateWnd->lpcs, sizeof(CREATESTRUCTW) );
                 CbtCreatewndExtra->WndInsertAfter = CbtCreateWnd->hwndInsertAfter;
+                CbtCreatewndExtra->Cs.lpszClass = CbtCreateWnd->lpcs->lpszClass; // if Atom
+                CbtCreatewndExtra->Cs.lpszName = CbtCreateWnd->lpcs->lpszName;
                 Extra = (PCHAR) (CbtCreatewndExtra + 1);
-                RtlCopyMemory(Extra, WindowName.Buffer, WindowName.Length);
-                CbtCreatewndExtra->Cs.lpszName = (LPCWSTR) (Extra - (PCHAR) CbtCreatewndExtra);
-                CbtCreatewndExtra->Cs.lpszClass = ClassName.Buffer;
-                Extra += WindowName.Length;
-                if (Ansi)
-                {
-                  *((CHAR *) Extra) = '\0';
-                  Extra += sizeof(CHAR);
-                }
-                else
-                {
-                  *((WCHAR *) Extra) = L'\0';
-                  Extra += sizeof(WCHAR);
-                }
-                if (! IS_ATOM(ClassName.Buffer))
-                {
-                   RtlCopyMemory(Extra, ClassName.Buffer, ClassName.Length);
-                   CbtCreatewndExtra->Cs.lpszClass =
-                      (LPCWSTR)(ULONG_PTR) MAKELONG(Extra - (PCHAR) CbtCreatewndExtra, 1);
-                   Extra += ClassName.Length;
-                   if (Ansi)
-                      *((CHAR *) Extra) = '\0';
-                   else
-                      *((WCHAR *) Extra) = L'\0';
-                }
                 break;
              case HCBT_CLICKSKIPPED:
                 RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MOUSEHOOKSTRUCT));
        case WH_GETMESSAGE:
           RtlCopyMemory(Extra, (PVOID) lParam, sizeof(MSG));
           Common->lParam = (LPARAM) (Extra - (PCHAR) Common);
- //         DPRINT1("KHOOK Memory: %x\n",Common);
           break;
        case WH_FOREGROUNDIDLE:
        case WH_KEYBOARD:
     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
     {
        Result = 0;
+       Hit = TRUE;
     }
     _SEH2_END;
  
     if (!NT_SUCCESS(Status))
     {
-       return 0;
+       goto Fault_Exit;
     }
-    if (HookId == WH_CBT && Code == HCBT_CREATEWND)
+    /* Support write backs... SEH is in UserCallNextHookEx. */
+    switch (HookId)
     {
-       if (CbtCreatewndExtra)
-       {
-          _SEH2_TRY
-          { /*
-               The parameters could have been changed, include the coordinates
-               and dimensions of the window. We copy it back.
-             */
-             CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
-             CbtCreateWnd->lpcs->x  = CbtCreatewndExtra->Cs.x;
-             CbtCreateWnd->lpcs->y  = CbtCreatewndExtra->Cs.y;
-             CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx;
-             CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy;
+       case WH_CBT:
+          if (Code == HCBT_CREATEWND)
+          {
+             if (CbtCreatewndExtra)
+             {/*
+                The parameters could have been changed, include the coordinates
+                and dimensions of the window. We copy it back.
+               */
+                CbtCreateWnd->hwndInsertAfter = CbtCreatewndExtra->WndInsertAfter;
+                CbtCreateWnd->lpcs->x  = CbtCreatewndExtra->Cs.x;
+                CbtCreateWnd->lpcs->y  = CbtCreatewndExtra->Cs.y;
+                CbtCreateWnd->lpcs->cx = CbtCreatewndExtra->Cs.cx;
+                CbtCreateWnd->lpcs->cy = CbtCreatewndExtra->Cs.cy;
+             }
           }
-          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+          break;
+       // "The GetMsgProc hook procedure can examine or modify the message."
+       case WH_GETMESSAGE:
+          if (lParam)
           {
-             Result = 0;
+             RtlCopyMemory((PVOID) lParam, Extra, sizeof(MSG));
           }
-          _SEH2_END;
-       }
+          break;
     }
  
+ Fault_Exit:
+    if (Hit)
+    {
+       DPRINT1("Exception CallHookProc HookId %d Code %d\n",HookId,Code);
+    }
     if (Argument) IntCbFreeMemory(Argument);
  
     return Result;
@@@ -30,10 -30,13 +30,13 @@@ stati
  BOOL FASTCALL
  co_IntHideCaret(PTHRDCARETINFO CaretInfo)
  {
+    PWND pWnd;
     if(CaretInfo->hWnd && CaretInfo->Visible && CaretInfo->Showing)
     {
+       pWnd = UserGetWindowObject(CaretInfo->hWnd);
        co_IntSendMessage(CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
        CaretInfo->Showing = 0;
+       IntNotifyWinEvent(EVENT_OBJECT_HIDE, pWnd, OBJID_CARET, CHILDID_SELF, 0);
        return TRUE;
     }
     return FALSE;
@@@ -43,17 -46,20 +46,20 @@@ BOOL FASTCAL
  co_IntDestroyCaret(PTHREADINFO Win32Thread)
  {
     PUSER_MESSAGE_QUEUE ThreadQueue;
+    PWND pWnd;
     ThreadQueue = (PUSER_MESSAGE_QUEUE)Win32Thread->MessageQueue;
  
     if(!ThreadQueue || !ThreadQueue->CaretInfo)
        return FALSE;
  
+    pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
     co_IntHideCaret(ThreadQueue->CaretInfo);
     ThreadQueue->CaretInfo->Bitmap = (HBITMAP)0;
     ThreadQueue->CaretInfo->hWnd = (HWND)0;
     ThreadQueue->CaretInfo->Size.cx = ThreadQueue->CaretInfo->Size.cy = 0;
     ThreadQueue->CaretInfo->Showing = 0;
     ThreadQueue->CaretInfo->Visible = 0;
+    IntNotifyWinEvent(EVENT_OBJECT_DESTROY, pWnd, OBJID_CARET, CHILDID_SELF, 0);
     return TRUE;
  }
  
@@@ -176,6 -182,7 +182,7 @@@ BOOL FASTCAL
  co_IntSetCaretPos(int X, int Y)
  {
     PTHREADINFO pti;
+    PWND pWnd;
     PUSER_MESSAGE_QUEUE ThreadQueue;
  
     pti = PsGetCurrentThreadWin32Thread();
  
     if(ThreadQueue->CaretInfo->hWnd)
     {
+       pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
        if(ThreadQueue->CaretInfo->Pos.x != X || ThreadQueue->CaretInfo->Pos.y != Y)
        {
           co_IntHideCaret(ThreadQueue->CaretInfo);
           ThreadQueue->CaretInfo->Pos.y = Y;
           co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
           IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TMRF_SYSTEM);
+          IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_CARET, CHILDID_SELF, 0);
        }
        return TRUE;
     }
@@@ -277,6 -286,7 +286,7 @@@ BOOL FASTCALL co_UserHideCaret(PWND Win
  BOOL FASTCALL co_UserShowCaret(PWND Window OPTIONAL)
  {
     PTHREADINFO pti;
+    PWND pWnd;
     PUSER_MESSAGE_QUEUE ThreadQueue;
  
     if (Window) ASSERT_REFS_CO(Window);
        ThreadQueue->CaretInfo->Visible = 1;
        if(!ThreadQueue->CaretInfo->Showing)
        {
+          pWnd = UserGetWindowObject(ThreadQueue->CaretInfo->hWnd);
           co_IntSendMessage(ThreadQueue->CaretInfo->hWnd, WM_SYSTIMER, IDCARETTIMER, 0);
+          IntNotifyWinEvent(EVENT_OBJECT_SHOW, pWnd, OBJID_CARET, OBJID_CARET, 0);
        }
        IntSetTimer(UserGetWindowObject(ThreadQueue->CaretInfo->hWnd), IDCARETTIMER, IntGetCaretBlinkTime(), NULL, TMRF_SYSTEM);
     }
     return TRUE;
  }
  
@@@ -370,7 -381,7 +381,7 @@@ NtUserCreateCaret
     }
     ThreadQueue->CaretInfo->Visible = 0;
     ThreadQueue->CaretInfo->Showing = 0;
+    IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_CARET, CHILDID_SELF, 0);
     RETURN(TRUE);
  
  CLEANUP:
@@@ -243,34 -243,62 +243,62 @@@ IntEmptyClipboardData(VOID
  /*==============================================================*/
  
  HANDLE FASTCALL
- renderBITMAPfromDIB(LPBYTE hDIB)
+ renderBITMAPfromDIB(LPBYTE pDIB)
  {
      HDC hdc;
      HBITMAP hbitmap;
-     unsigned int offset;
-     BITMAPINFOHEADER *ih;
+     PBITMAPINFO pBmi, pConvertedBmi = NULL;
+     NTSTATUS Status ;
+       UINT offset = 0; /* Stupid compiler */
+       pBmi = (BITMAPINFO*)pDIB;
  
      //hdc = UserGetDCEx(NULL, NULL, DCX_USESTYLE);
      hdc = UserGetDCEx(ClipboardWindow, NULL, DCX_USESTYLE);
  
-     ih = (BITMAPINFOHEADER *)hDIB;
-     offset = sizeof(BITMAPINFOHEADER) + ((ih->biBitCount <= 8) ? (sizeof(RGBQUAD) * (1 << ih->biBitCount)) : 0);
-     hbitmap = NtGdiCreateDIBitmapInternal(hdc,
-                                           ih->biWidth,
-                                           ih->biHeight,
-                                           CBM_INIT,
-                                           (LPBYTE)ih+offset,
-                                           (LPBITMAPINFO)ih,
-                                           DIB_RGB_COLORS,
-                                           ih->biBitCount,
-                                           ih->biSizeImage,
-                                           0,
-                                           0);
+     /* Probe it */
+     _SEH2_TRY
+     {
+         ProbeForRead(&pBmi->bmiHeader.biSize, sizeof(DWORD), 1);
+               ProbeForRead(pBmi, pBmi->bmiHeader.biSize, 1);
+               ProbeForRead(pBmi, DIB_BitmapInfoSize(pBmi, DIB_RGB_COLORS), 1);
+               pConvertedBmi = DIB_ConvertBitmapInfo(pBmi, DIB_RGB_COLORS);
+               if(!pConvertedBmi)
+               {
+                       Status = STATUS_INVALID_PARAMETER;
+               }
+               else
+               {
+                       offset = DIB_BitmapInfoSize((BITMAPINFO*)pBmi, DIB_RGB_COLORS);
+                       ProbeForRead(pDIB + offset, pConvertedBmi->bmiHeader.biSizeImage, 1);
+               }
+     }
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+         Status = _SEH2_GetExceptionCode();
+     }
+     _SEH2_END
+     if(!NT_SUCCESS(Status))
+     {
+         UserReleaseDC(ClipboardWindow, hdc, FALSE);
+         return NULL;
+     }
+     hbitmap = GreCreateDIBitmapInternal(hdc,
+                                         pConvertedBmi->bmiHeader.biWidth,
+                                         pConvertedBmi->bmiHeader.biHeight,
+                                         CBM_INIT,
+                                         pDIB+offset,
+                                         pConvertedBmi,
+                                         DIB_RGB_COLORS,
+                                         0,
+                                         0);
      //UserReleaseDC(NULL, hdc, FALSE);
      UserReleaseDC(ClipboardWindow, hdc, FALSE);
  
+       DIB_FreeConvertedBitmapInfo(pConvertedBmi, pBmi);
      return hbitmap;
  }
  
@@@ -109,7 -109,7 +109,7 @@@ UserSetCursor
      PCURICON_OBJECT OldCursor;
      HCURSOR hOldCursor = (HCURSOR)0;
      HDC hdcScreen;
-       
        CurInfo = IntGetSysCursorInfo();
  
      OldCursor = CurInfo->CurrentCursorObject;
@@@ -483,6 -483,7 +483,7 @@@ IntCleanupCurIcons(struct _EPROCESS *Pr
  
  }
  
  /*
   * @implemented
   */
@@@ -692,52 -693,73 +693,73 @@@ CLEANUP
      END_CLEANUP;
  }
  
- /*
-  * @implemented
-  */
  BOOL
  APIENTRY
NtUserClipCursor(
-     RECTL *UnsafeRect)
+ UserClipCursor(
+     RECTL *prcl)
  {
      /* FIXME - check if process has WINSTA_WRITEATTRIBUTES */
      PSYSTEM_CURSORINFO CurInfo;
-     RECTL Rect;
      PWND DesktopWindow = NULL;
-     DECLARE_RETURN(BOOL);
-     DPRINT("Enter NtUserClipCursor\n");
-     UserEnterExclusive();
-     if (NULL != UnsafeRect && ! NT_SUCCESS(MmCopyFromCaller(&Rect, UnsafeRect, sizeof(RECT))))
-     {
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         RETURN(FALSE);
-     }
  
      CurInfo = IntGetSysCursorInfo();
  
      DesktopWindow = UserGetDesktopWindow();
  
-     if ((Rect.right > Rect.left) && (Rect.bottom > Rect.top)
-             && DesktopWindow && UnsafeRect != NULL)
+     if (prcl != NULL &&
+        (prcl->right > prcl->left) &&
+        (prcl->bottom > prcl->top) &&
+         DesktopWindow != NULL)
      {
          CurInfo->bClipped = TRUE;
-         RECTL_bIntersectRect(&CurInfo->rcClip, &Rect, &DesktopWindow->rcWindow);
+         RECTL_bIntersectRect(&CurInfo->rcClip, prcl, &DesktopWindow->rcWindow);
          UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, FALSE);
+     }
+     else
+     {
+         CurInfo->bClipped = FALSE;
+     }
+     return TRUE;
+ }
+ /*
+  * @implemented
+  */
+ BOOL
+ APIENTRY
+ NtUserClipCursor(
+     RECTL *prcl)
+ {
+     RECTL rclLocal;
+     BOOL bResult;
+     if (prcl)
+     {
+         _SEH2_TRY
+         {
+             /* Probe and copy rect */
+             ProbeForRead(prcl, sizeof(RECTL), 1);
+             rclLocal = *prcl;
+         }
+         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+         {
+             SetLastWin32Error(ERROR_INVALID_PARAMETER);
+             _SEH2_YIELD(return FALSE;)
+         }
+         _SEH2_END
  
-         RETURN(TRUE);
+         prcl = &rclLocal;
      }
+       
+       UserEnterExclusive();
  
-     CurInfo->bClipped = FALSE;
-     RETURN(TRUE);
+     /* Call the internal function */
+     bResult = UserClipCursor(prcl);
  
- CLEANUP:
-     DPRINT("Leave NtUserClipCursor, ret=%i\n",_ret_);
      UserLeave();
-     END_CLEANUP;
+     return bResult;
  }
  
  
@@@ -937,12 -959,12 +959,12 @@@ NtUserSetCursorContents
  
      /* Delete old bitmaps */
      if ((CurIcon->IconInfo.hbmColor)
-               && (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor))
+                       && (CurIcon->IconInfo.hbmColor != IconInfo.hbmColor))
      {
          GreDeleteObject(CurIcon->IconInfo.hbmColor);
      }
      if ((CurIcon->IconInfo.hbmMask)
-               && (CurIcon->IconInfo.hbmMask != IconInfo.hbmMask))
+                       && CurIcon->IconInfo.hbmMask != IconInfo.hbmMask)
      {
          GreDeleteObject(CurIcon->IconInfo.hbmMask);
      }
          CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy / 2;
  
          SURFACE_UnlockSurface(psurfBmp);
-         GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
      }
+       GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
  
      Ret = TRUE;
  
@@@ -1287,23 -1309,12 +1309,12 @@@ UserDrawIconEx
        if(bAlpha && (diFlags & DI_IMAGE))
        {
                BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
-         DWORD Pixel;
-         BYTE Red, Green, Blue, Alpha;
-         DWORD Count = 0;
+         BYTE Alpha;
          INT i, j;
          PSURFACE psurf;
-         PBYTE pBits ;
+         PBYTE ptr ;
          HBITMAP hMemBmp = NULL;
  
-         pBits = ExAllocatePoolWithTag(PagedPool,
-                                       bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
-                                       TAG_BITMAP);
-         if (pBits == NULL)
-         {
-             Ret = FALSE;
-             goto CleanupAlpha;
-         }
          hMemBmp = BITMAP_CopyBitmap(hbmColor);
          if(!hMemBmp)
          {
              DPRINT1("SURFACE_LockSurface failed!\n");
              goto CleanupAlpha;
          }
-         /* get color bits */
-         IntGetBitmapBits(psurf,
-                          bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
-                          pBits);
  
          /* premultiply with the alpha channel value */
-         for (i = 0; i < abs(bmpColor.bmHeight); i++)
+         for (i = 0; i < psurf->SurfObj.sizlBitmap.cy; i++)
          {
-                       Count = i*bmpColor.bmWidthBytes;
-             for (j = 0; j < bmpColor.bmWidth; j++)
+                       ptr = (PBYTE)psurf->SurfObj.pvScan0 + i*psurf->SurfObj.lDelta;
+             for (j = 0; j < psurf->SurfObj.sizlBitmap.cx; j++)
              {
-                 Pixel = *(DWORD *)(pBits + Count);
-                 Alpha = ((BYTE)(Pixel >> 24) & 0xff);
+                 Alpha = ptr[3];
+                 ptr[0] = (ptr[0] * Alpha) / 0xff;
+                 ptr[1] = (ptr[1] * Alpha) / 0xff;
+                 ptr[2] = (ptr[2] * Alpha) / 0xff;
  
-                 Red   = (((BYTE)(Pixel >>  0)) * Alpha) / 0xff;
-                 Green = (((BYTE)(Pixel >>  8)) * Alpha) / 0xff;
-                 Blue  = (((BYTE)(Pixel >> 16)) * Alpha) / 0xff;
-                 *(DWORD *)(pBits + Count) = (DWORD)(Red | (Green << 8) | (Blue << 16) | (Alpha << 24));
-                 Count += sizeof(DWORD);
+                               ptr += 4;
              }
          }
  
-         /* set mem bits */
-         IntSetBitmapBits(psurf,
-                          bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
-                          pBits);
          SURFACE_UnlockSurface(psurf);
  
          hTmpBmp = NtGdiSelectBitmap(hMemDC, hMemBmp);
                                NULL);
          NtGdiSelectBitmap(hMemDC, hTmpBmp);
      CleanupAlpha:
-         if(pBits) ExFreePoolWithTag(pBits, TAG_BITMAP);
          if(hMemBmp) NtGdiDeleteObjectApp(hMemBmp);
                if(Ret) goto done;
      }
  
      if (diFlags & DI_MASK)
      {
          hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
@@@ -616,8 -616,6 +616,6 @@@ UserRedrawDesktop(
  {
      PWND Window = NULL;
  
-     UserEnterExclusive();
      Window = UserGetDesktopWindow();
  
      IntInvalidateWindows( Window,
                         RDW_ERASE |
                    RDW_INVALIDATE |
                   RDW_ALLCHILDREN);
-     UserLeave();
  }
  
  
@@@ -884,6 -881,7 +881,7 @@@ NtUserCreateDesktop
     LARGE_STRING WindowName;
     PWND pWnd = NULL;
     CREATESTRUCTW Cs;
+    INT i;
     DECLARE_RETURN(HDESK);
  
     DPRINT("Enter NtUserCreateDesktop: %wZ\n", lpszDesktopName);
     /* Initialize some local (to win32k) desktop state. */
     InitializeListHead(&DesktopObject->PtiList);
     DesktopObject->ActiveMessageQueue = NULL;
+    /* Setup Global Hooks. */
+    for (i = 0; i < NB_HOOKS; i++)
+    {
+       InitializeListHead(&DesktopObject->pDeskInfo->aphkStart[i]);
+    }
     ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
  
     if (! NT_SUCCESS(Status))
  /*
-  * PROJECT:         ReactOS Kernel
-  * LICENSE:         GPL - See COPYING in the top level directory
-  * FILE:            subsystems/win32/win32k/ntuser/display.c
-  * PURPOSE:         display settings
-  * COPYRIGHT:       Copyright 2007 ReactOS
-  *
+  * COPYRIGHT:        See COPYING in the top level directory
+  * PROJECT:          ReactOS kernel
+  * PURPOSE:          Video initialization and display settings
+  * FILE:             subsystems/win32/win32k/ntuser/display.c
+  * PROGRAMER:        Timo Kreuzer (timo.kreuzer@reactos.org)
   */
  
- /* INCLUDES ******************************************************************/
  #include <win32k.h>
  
+ #include <intrin.h>
  #define NDEBUG
  #include <debug.h>
  
- #define SIZEOF_DEVMODEW_300 188
- #define SIZEOF_DEVMODEW_400 212
- #define SIZEOF_DEVMODEW_500 220
+ BOOL InitSysParams();
+ BOOL gbBaseVideo = 0;
+ static const PWCHAR KEY_ROOT = L"";
+ static const PWCHAR KEY_VIDEO = L"\\Registry\\Machine\\HARDWARE\\DEVICEMAP\\VIDEO";
+ VOID
+ RegWriteDisplaySettings(HKEY hkey, PDEVMODEW pdm)
+ {
+     RegWriteDWORD(hkey, L"DefaultSettings.BitsPerPel", pdm->dmBitsPerPel);
+     RegWriteDWORD(hkey, L"DefaultSettings.XResolution", pdm->dmPelsWidth);
+     RegWriteDWORD(hkey, L"DefaultSettings.YResolution", pdm->dmPelsHeight);
+     RegWriteDWORD(hkey, L"DefaultSettings.Flags", pdm->dmDisplayFlags);
+     RegWriteDWORD(hkey, L"DefaultSettings.VRefresh", pdm->dmDisplayFrequency);
+     RegWriteDWORD(hkey, L"DefaultSettings.XPanning", pdm->dmPanningWidth);
+     RegWriteDWORD(hkey, L"DefaultSettings.YPanning", pdm->dmPanningHeight);
+     RegWriteDWORD(hkey, L"DefaultSettings.Orientation", pdm->dmDisplayOrientation);
+     RegWriteDWORD(hkey, L"DefaultSettings.FixedOutput", pdm->dmDisplayFixedOutput);
+     RegWriteDWORD(hkey, L"Attach.RelativeX", pdm->dmPosition.x);
+     RegWriteDWORD(hkey, L"Attach.RelativeY", pdm->dmPosition.y);
+ //    RegWriteDWORD(hkey, L"Attach.ToDesktop, pdm->dmBitsPerPel", pdm->);
+ }
+ VOID
+ RegReadDisplaySettings(HKEY hkey, PDEVMODEW pdm)
+ {
+     DWORD dwValue;
+     /* Zero out the structure */
+     RtlZeroMemory(pdm, sizeof(DEVMODEW));
+ /* Helper macro */
+ #define READ(field, str, flag) \
+     if (RegReadDWORD(hkey, L##str, &dwValue)) \
+     { \
+         pdm->field = dwValue; \
+         pdm->dmFields |= flag; \
+     }
+     /* Read all present settings */
+     READ(dmBitsPerPel, "DefaultSettings.BitsPerPel", DM_BITSPERPEL);
+     READ(dmPelsWidth, "DefaultSettings.XResolution", DM_PELSWIDTH);
+     READ(dmPelsHeight, "DefaultSettings.YResolution", DM_PELSHEIGHT);
+     READ(dmDisplayFlags, "DefaultSettings.Flags", DM_DISPLAYFLAGS);
+     READ(dmDisplayFrequency, "DefaultSettings.VRefresh", DM_DISPLAYFREQUENCY);
+     READ(dmPanningWidth, "DefaultSettings.XPanning", DM_PANNINGWIDTH);
+     READ(dmPanningHeight, "DefaultSettings.YPanning", DM_PANNINGHEIGHT);
+     READ(dmDisplayOrientation, "DefaultSettings.Orientation", DM_DISPLAYORIENTATION);
+     READ(dmDisplayFixedOutput, "DefaultSettings.FixedOutput", DM_DISPLAYFIXEDOUTPUT);
+     READ(dmPosition.x, "Attach.RelativeX", DM_POSITION);
+     READ(dmPosition.y, "Attach.RelativeY", DM_POSITION);
+ }
+ PGRAPHICS_DEVICE
+ NTAPI
+ InitDisplayDriver(
+     IN PWSTR pwszDeviceName,
+     IN PWSTR pwszRegKey)
+ {
+     PGRAPHICS_DEVICE pGraphicsDevice;
+     UNICODE_STRING ustrDeviceName, ustrDisplayDrivers, ustrDescription;
+     NTSTATUS Status;
+     WCHAR awcBuffer[128];
+     ULONG cbSize;
+     HKEY hkey;
+     DEVMODEW dmDefault;
+     DPRINT1("InitDisplayDriver(%S, %S);\n",
+             pwszDeviceName, pwszRegKey);
+     /* Open the driver's registry key */
+     Status = RegOpenKey(pwszRegKey, &hkey);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Failed to open registry key: %ls\n", pwszRegKey);
+         return NULL;
+     }
+     /* Query the diplay drivers */
+     cbSize = sizeof(awcBuffer) - 10;
+     Status = RegQueryValue(hkey,
+                            L"InstalledDisplayDrivers",
+                            REG_MULTI_SZ,
+                            awcBuffer,
+                            &cbSize);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Didn't find 'InstalledDisplayDrivers', status = 0x%lx\n", Status);
+         ZwClose(hkey);
+         return NULL;
+     }
+     /* Initialize the UNICODE_STRING */
+     ustrDisplayDrivers.Buffer = awcBuffer;
+     ustrDisplayDrivers.MaximumLength = cbSize;
+     ustrDisplayDrivers.Length = cbSize;
+     /* Set Buffer for description and size of remaining buffer */
+     ustrDescription.Buffer = awcBuffer + (cbSize / sizeof(WCHAR));
+     cbSize = sizeof(awcBuffer) - cbSize;
+     /* Query the device string */
+     Status = RegQueryValue(hkey,
+                            L"Device Description",
+                            REG_SZ,
+                            ustrDescription.Buffer,
+                            &cbSize);
+     if (NT_SUCCESS(Status))
+     {
+         ustrDescription.MaximumLength = cbSize;
+         ustrDescription.Length = cbSize;
+     }
+     else
+     {
+         RtlInitUnicodeString(&ustrDescription, L"<unknown>");
+     }
+     /* Query the default settings */
+     RegReadDisplaySettings(hkey, &dmDefault);
+     /* Close the registry key */
+     ZwClose(hkey);
+     /* Register the device with GDI */
+     RtlInitUnicodeString(&ustrDeviceName, pwszDeviceName);
+     pGraphicsDevice = EngpRegisterGraphicsDevice(&ustrDeviceName,
+                                                  &ustrDisplayDrivers,
+                                                  &ustrDescription,
+                                                  &dmDefault);
+     return pGraphicsDevice;
+ }
+ BOOL
+ InitVideo(
+     PUNICODE_STRING pustrRegPath,
+     FLONG flags)
+ {
+     ULONG iDevNum, iVGACompatible = -1, ulMaxObjectNumber = 0;
+     WCHAR awcDeviceName[20];
+     WCHAR awcBuffer[256];
+     NTSTATUS Status;
+     PGRAPHICS_DEVICE pGraphicsDevice;
+     ULONG cbValue;
+     HKEY hkey;
+     DPRINT1("----------------------------- InitVideo() -------------------------------\n");
+     Status = RegOpenKey(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control", &hkey);
+     if (NT_SUCCESS(Status))
+     {
+         cbValue = 256;
+         Status = RegQueryValue(hkey, L"SystemStartOptions", REG_SZ, awcBuffer, &cbValue);
+         if (NT_SUCCESS(Status))
+         {
+             /* Check if VGA mode is requested. */
+             if (wcsstr(awcBuffer, L"/BASEVIDEO") != 0)
+             {
+                 DPRINT1("VGA mode requested.\n");
+                 gbBaseVideo = TRUE;
+             }
+         }
+         ZwClose(hkey);
+     }
+     /* Open the key for the adapters */
+     Status = RegOpenKey(KEY_VIDEO, &hkey);
+     if (!NT_SUCCESS(Status))
+     {
+         DPRINT1("Could not open device registry key!\n");
+         ASSERT(FALSE);
+     }
+     /* Read the name of the VGA adapter */
+     cbValue = 20;
+     Status = RegQueryValue(hkey, L"VgaCompatible", REG_SZ, awcDeviceName, &cbValue);
+     if (NT_SUCCESS(Status))
+     {
+         iVGACompatible = _wtoi(&awcDeviceName[13]);
+         DPRINT1("VGA adapter = %ld\n", iVGACompatible);
+     }
+     /* Get the maximum mumber of adapters */
+     if (!RegReadDWORD(hkey, L"MaxObjectNumber", &ulMaxObjectNumber))
+     {
+         DPRINT1("Could not read MaxObjectNumber, defaulting to 0.\n");
+     }
+     DPRINT("Found %ld devices\n", ulMaxObjectNumber);
+     /* Loop through all adapters */
+     cbValue = 256;
+     for (iDevNum = 0; iDevNum <= ulMaxObjectNumber; iDevNum++)
+     {
+         /* Create the adapter's key name */
+         swprintf(awcDeviceName, L"\\Device\\Video%lu", iDevNum);
+         /* Read the reg key name */
+         Status = RegQueryValue(hkey, awcDeviceName, REG_SZ, awcBuffer, &cbValue);
+         pGraphicsDevice = InitDisplayDriver(awcDeviceName, awcBuffer);
+         /* Check if this is the VGA adapter */
+         if (iDevNum == iVGACompatible)
+         {
+             /* Set the VGA device as primary */
+             gpVgaGraphicsDevice = pGraphicsDevice;
+             DPRINT1("gpVgaGraphicsDevice = %p\n", gpVgaGraphicsDevice);
+         }
+         /* Set the first one as primary device */
+         if (!gpPrimaryGraphicsDevice)
+             gpPrimaryGraphicsDevice = pGraphicsDevice;
+     }
+     ZwClose(hkey);
+     if (gbBaseVideo)
+     {
+         if (gpVgaGraphicsDevice)
+         {
+             /* Set the VgaAdapter as primary */
+             gpPrimaryGraphicsDevice = gpVgaGraphicsDevice;
+             // FIXME: DEVMODE
+         }
+         else
+         {
+             DPRINT1("Could not find VGA compatible driver. Trying normal.\n");
+         }
+     }
+     InitSysParams();
  
- /* PUBLIC FUNCTIONS ***********************************************************/
+     return 1;
+ }
  
  NTSTATUS
- APIENTRY
NtUserEnumDisplaySettings(
-    PUNICODE_STRING pusDeviceName,
-    DWORD iModeNum,
-    LPDEVMODEW lpDevMode, /* FIXME is this correct? */
-    DWORD dwFlags )
+ NTAPI
UserEnumDisplayDevices(
+     PUNICODE_STRING pustrDevice,
+     DWORD iDevNum,
+     PDISPLAY_DEVICEW pdispdev,
+     DWORD dwFlags)
  {
+     PGRAPHICS_DEVICE pGraphicsDevice;
+     ULONG cbSize;
+     HKEY hkey;
      NTSTATUS Status;
-     LPDEVMODEW pSafeDevMode;
-     PUNICODE_STRING pusSafeDeviceName = NULL;
-     UNICODE_STRING usSafeDeviceName;
-     USHORT Size = 0, ExtraSize = 0;
  
-     /* Copy the devmode */
-     _SEH2_TRY
+     /* Ask gdi for the GRAPHICS_DEVICE */
+     pGraphicsDevice = EngpFindGraphicsDevice(pustrDevice, iDevNum, 0);
+     if (!pGraphicsDevice)
      {
-         ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
-         Size = lpDevMode->dmSize;
-         ExtraSize = lpDevMode->dmDriverExtra;
+         /* No device found */
+         DPRINT1("No GRAPHICS_DEVICE found\n");
+         return STATUS_UNSUCCESSFUL;
      }
-     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     /* Open thhe device map registry key */
+     Status = RegOpenKey(KEY_VIDEO, &hkey);
+     if (!NT_SUCCESS(Status))
      {
-         DPRINT("FIXME ? : Out of range of DEVMODEW size \n");
-         _SEH2_YIELD(return _SEH2_GetExceptionCode());
+         /* No device found */
+         DPRINT1("Could not open reg key\n");
+         return STATUS_UNSUCCESSFUL;
      }
-     _SEH2_END;
  
-     if (Size != sizeof(DEVMODEW))
+     /* Query the registry path */
+     cbSize = sizeof(pdispdev->DeviceKey);
+     RegQueryValue(hkey,
+                   pGraphicsDevice->szNtDeviceName,
+                   REG_SZ,
+                   pdispdev->DeviceKey,
+                   &cbSize);
+     /* Close registry key */
+     ZwClose(hkey);
+     /* Copy device name, device string and StateFlags */
+     wcsncpy(pdispdev->DeviceName, pGraphicsDevice->szWinDeviceName, 32);
+     wcsncpy(pdispdev->DeviceString, pGraphicsDevice->pwszDescription, 128);
+     pdispdev->StateFlags = pGraphicsDevice->StateFlags;
+     // FIXME: fill in DEVICE ID
+     return STATUS_SUCCESS;
+ }
+ //NTSTATUS
+ BOOL
+ NTAPI
+ NtUserEnumDisplayDevices(
+     PUNICODE_STRING pustrDevice,
+     DWORD iDevNum,
+     PDISPLAY_DEVICEW pDisplayDevice,
+     DWORD dwFlags)
+ {
+     UNICODE_STRING ustrDevice;
+     WCHAR awcDevice[CCHDEVICENAME];
+     DISPLAY_DEVICEW dispdev;
+     NTSTATUS Status;
+     DPRINT("Enter NtUserEnumDisplayDevices(%wZ, %ld)\n",
+            pustrDevice, iDevNum);
+     // FIXME: HACK, desk.cpl passes broken crap
+     if (pustrDevice && iDevNum != 0)
+         return FALSE;
+     dispdev.cb = sizeof(DISPLAY_DEVICEW);
+     if (pustrDevice)
      {
-         return STATUS_BUFFER_TOO_SMALL;
+         /* Initialize destination string */
+         RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
+         _SEH2_TRY
+         {
+             /* Probe the UNICODE_STRING and the buffer */
+             ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+             ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+             /* Copy the string */
+             RtlCopyUnicodeString(&ustrDevice, pustrDevice);
+         }
+         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+         {
+ //            _SEH2_YIELD(return _SEH2_GetExceptionCode());
+             _SEH2_YIELD(return NT_SUCCESS(_SEH2_GetExceptionCode()));
+         }
+         _SEH2_END
+         if (ustrDevice.Length > 0)
+             pustrDevice = &ustrDevice;
+         else
+             pustrDevice = NULL;
+    }
+     /* Acquire global USER lock */
+     UserEnterExclusive();
+     /* Call the internal function */
+     Status = UserEnumDisplayDevices(pustrDevice, iDevNum, &dispdev, dwFlags);
+     /* Release lock */
+     UserLeave();
+     /* On success copy data to caller */
+     if (NT_SUCCESS(Status))
+     {
+         /* Enter SEH */
+         _SEH2_TRY
+         {
+             /* First probe the cb field */
+             ProbeForWrite(&pDisplayDevice->cb, sizeof(DWORD), 1);
+             /* Check the buffer size */
+             if (pDisplayDevice->cb)
+             {
+                 /* Probe the output buffer */
+                 pDisplayDevice->cb = min(pDisplayDevice->cb, sizeof(dispdev));
+                 ProbeForWrite(pDisplayDevice, pDisplayDevice->cb, 1);
+                 /* Copy as much as the given buffer allows */
+                 RtlCopyMemory(pDisplayDevice, &dispdev, pDisplayDevice->cb);
+             }
+         }
+         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+         {
+             Status = _SEH2_GetExceptionCode();
+         }
+         _SEH2_END
      }
  
-     pSafeDevMode = ExAllocatePoolWithTag(PagedPool, Size + ExtraSize, GDITAG_DEVMODE);
-     if (pSafeDevMode == NULL)
+     DPRINT1("Leave NtUserEnumDisplayDevices, Status = 0x%lx\n", Status);
+     /* Return the result */
+ //    return Status;
+     return NT_SUCCESS(Status); // FIXME
+ }
+ NTSTATUS
+ NTAPI
+ UserEnumCurrentDisplaySettings(
+     PUNICODE_STRING pustrDevice,
+     PDEVMODEW *ppdm)
+ {
+     PPDEVOBJ ppdev;
+     /* Get the PDEV for the device */
+     ppdev = EngpGetPDEV(pustrDevice);
+     if (!ppdev)
      {
-         return STATUS_NO_MEMORY;
+         /* No device found */
+         DPRINT1("No PDEV found!\n");
+         return STATUS_UNSUCCESSFUL;
      }
-     pSafeDevMode->dmSize = Size;
-     pSafeDevMode->dmDriverExtra = ExtraSize;
  
-     /* Copy the device name */
-     if (pusDeviceName != NULL)
+     *ppdm = ppdev->pdmwDev;
+     PDEVOBJ_vRelease(ppdev);
+     return STATUS_SUCCESS;
+ }
+ NTSTATUS
+ NTAPI
+ UserEnumDisplaySettings(
+    PUNICODE_STRING pustrDevice,
+    DWORD iModeNum,
+    LPDEVMODEW *ppdm,
+    DWORD dwFlags)
+ {
+     PGRAPHICS_DEVICE pGraphicsDevice;
+     PDEVMODEENTRY pdmentry;
+     ULONG i, iFoundMode;
+     DPRINT("Enter UserEnumDisplaySettings('%ls', %ld)\n",
+             pustrDevice ? pustrDevice->Buffer : NULL, iModeNum);
+     /* Ask gdi for the GRAPHICS_DEVICE */
+     pGraphicsDevice = EngpFindGraphicsDevice(pustrDevice, 0, 0);
+     if (!pGraphicsDevice)
      {
-         Status = IntSafeCopyUnicodeString(&usSafeDeviceName, pusDeviceName);
-         if (!NT_SUCCESS(Status))
+         /* No device found */
+         DPRINT1("No device found!\n");
+         return STATUS_UNSUCCESSFUL;
+     }
+     if (iModeNum >= pGraphicsDevice->cDevModes)
+         return STATUS_NO_MORE_ENTRIES;
+     iFoundMode = 0;
+     for (i = 0; i < pGraphicsDevice->cDevModes; i++)
+     {
+         pdmentry = &pGraphicsDevice->pDevModeList[i];
+         /* FIXME: consider EDS_RAWMODE */
+ #if 0
+         if ((!(dwFlags & EDS_RAWMODE) && (pdmentry->dwFlags & 1)) ||!
+             (dwFlags & EDS_RAWMODE))
+ #endif
          {
-             ExFreePool(pSafeDevMode);
-             return Status;
+             /* Is this the one we want? */
+             if (iFoundMode == iModeNum)
+             {
+                 *ppdm = pdmentry->pdm;
+                 return STATUS_SUCCESS;
+             }
+             /* Increment number of found modes */
+             iFoundMode++;
          }
-         pusSafeDeviceName = &usSafeDeviceName;
      }
  
-     /* Call internal function */
-     Status = IntEnumDisplaySettings(pusSafeDeviceName, iModeNum, pSafeDevMode, dwFlags);
+     /* Nothing was found */
+     return STATUS_INVALID_PARAMETER;
+ }
  
-     if (pusSafeDeviceName != NULL)
-         RtlFreeUnicodeString(pusSafeDeviceName);
+ NTSTATUS
+ NTAPI
+ UserOpenDisplaySettingsKey(
+     OUT PHKEY phkey,
+     IN PUNICODE_STRING pustrDevice,
+     IN BOOL bGlobal)
+ {
+     HKEY hkey;
+     DISPLAY_DEVICEW dispdev;
+     NTSTATUS Status;
  
+     /* Get device info */
+     Status = UserEnumDisplayDevices(pustrDevice, 0, &dispdev, 0);
      if (!NT_SUCCESS(Status))
+         return Status;
+     if (bGlobal)
      {
-         ExFreePool(pSafeDevMode);
+         // FIXME: need to fix the registry key somehow
+     }
+     /* Open the registry key */
+     Status = RegOpenKey(dispdev.DeviceKey, &hkey);
+     if (!NT_SUCCESS(Status))
          return Status;
+     *phkey = hkey;
+     return Status;
+ }
+ NTSTATUS
+ NTAPI
+ UserEnumRegistryDisplaySettings(
+     IN PUNICODE_STRING pustrDevice,
+     OUT LPDEVMODEW pdm)
+ {
+     HKEY hkey;
+     NTSTATUS Status = UserOpenDisplaySettingsKey(&hkey, pustrDevice, 0);
+     if(NT_SUCCESS(Status))
+     {
+         RegReadDisplaySettings(hkey, pdm);
+         ZwClose(hkey);
+         return STATUS_SUCCESS;
      }
+     return Status ;
+ }
+ NTSTATUS
+ APIENTRY
+ NtUserEnumDisplaySettings(
+     IN PUNICODE_STRING pustrDevice,
+     IN DWORD iModeNum,
+     OUT LPDEVMODEW lpDevMode,
+     IN DWORD dwFlags)
+ {
+     UNICODE_STRING ustrDevice;
+     WCHAR awcDevice[CCHDEVICENAME];
+     NTSTATUS Status;
+     ULONG cbSize, cbExtra;
+     DEVMODEW dmReg, *pdm;
  
-     /* Copy some information back */
-     _SEH2_TRY
+     DPRINT1("Enter NtUserEnumDisplaySettings(%ls, %ld)\n",
+             pustrDevice ? pustrDevice->Buffer : 0, iModeNum);
+     if (pustrDevice)
      {
-         ProbeForWrite(lpDevMode,Size + ExtraSize, 1);
-         lpDevMode->dmPelsWidth = pSafeDevMode->dmPelsWidth;
-         lpDevMode->dmPelsHeight = pSafeDevMode->dmPelsHeight;
-         lpDevMode->dmBitsPerPel = pSafeDevMode->dmBitsPerPel;
-         lpDevMode->dmDisplayFrequency = pSafeDevMode->dmDisplayFrequency;
-         lpDevMode->dmDisplayFlags = pSafeDevMode->dmDisplayFlags;
+         /* Initialize destination string */
+         RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
  
-         /* output private/extra driver data */
-         if (ExtraSize > 0)
+         _SEH2_TRY
          {
-             memcpy((PCHAR)lpDevMode + Size, (PCHAR)pSafeDevMode + Size, ExtraSize);
+             /* Probe the UNICODE_STRING and the buffer */
+             ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+             ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+             /* Copy the string */
+             RtlCopyUnicodeString(&ustrDevice, pustrDevice);
          }
+         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+         {
+             _SEH2_YIELD(return _SEH2_GetExceptionCode());
+         }
+         _SEH2_END
+         pustrDevice = &ustrDevice;
+    }
+     /* Acquire global USER lock */
+     UserEnterExclusive();
+     if (iModeNum == ENUM_REGISTRY_SETTINGS)
+     {
+         /* Get the registry settings */
+         Status = UserEnumRegistryDisplaySettings(pustrDevice, &dmReg);
+         pdm = &dmReg;
      }
-     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     else if (iModeNum == ENUM_CURRENT_SETTINGS)
      {
-         Status = _SEH2_GetExceptionCode();
+         /* Get the current settings */
+         Status = UserEnumCurrentDisplaySettings(pustrDevice, &pdm);
+     }
+     else
+     {
+         /* Get specified settings */
+         Status = UserEnumDisplaySettings(pustrDevice, iModeNum, &pdm, dwFlags);
+     }
+     /* Release lock */
+     UserLeave();
+     /* Did we succeed? */
+     if (NT_SUCCESS(Status))
+     {
+         /* Copy some information back */
+         _SEH2_TRY
+         {
+             ProbeForRead(lpDevMode, sizeof(DEVMODEW), 1);
+             cbSize = lpDevMode->dmSize;
+             cbExtra = lpDevMode->dmDriverExtra;
+             ProbeForWrite(lpDevMode, cbSize + cbExtra, 1);
+             /* Output what we got */
+             RtlCopyMemory(lpDevMode, pdm, min(cbSize, pdm->dmSize));
+             /* output private/extra driver data */
+             if (cbExtra > 0 && pdm->dmDriverExtra > 0)
+             {
+                 RtlCopyMemory((PCHAR)lpDevMode + cbSize,
+                               (PCHAR)pdm + pdm->dmSize,
+                               min(cbExtra, pdm->dmDriverExtra));
+             }
+         }
+         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+         {
+             Status = _SEH2_GetExceptionCode();
+         }
+         _SEH2_END;
      }
-     _SEH2_END;
  
-     ExFreePool(pSafeDevMode);
      return Status;
  }
  
+ BOOL APIENTRY UserClipCursor(RECTL *prcl);
+ VOID APIENTRY UserRedrawDesktop();
+ HCURSOR FASTCALL UserSetCursor(PCURICON_OBJECT NewCursor, BOOL ForceChange);
  
  LONG
  APIENTRY
NtUserChangeDisplaySettings(
-    PUNICODE_STRING lpszDeviceName,
-    LPDEVMODEW lpDevMode,
+ UserChangeDisplaySettings(
+    PUNICODE_STRING pustrDevice,
+    LPDEVMODEW pdm,
     HWND hwnd,
-    DWORD dwflags,
+    DWORD flags,
     LPVOID lParam)
  {
-    NTSTATUS Status = STATUS_SUCCESS;
-    LPDEVMODEW lpSafeDevMode = NULL;
-    DEVMODEW DevMode;
-    PUNICODE_STRING pSafeDeviceName = NULL;
-    UNICODE_STRING SafeDeviceName;
-    LONG Ret;
-    /* Check arguments */
- #ifdef CDS_VIDEOPARAMETERS
-     if (dwflags != CDS_VIDEOPARAMETERS && lParam != NULL)
- #else
-     if (lParam != NULL)
- #endif
+     DEVMODEW dm;
+     LONG lResult = DISP_CHANGE_SUCCESSFUL;
+     HKEY hkey;
+     NTSTATUS Status;
+     PPDEVOBJ ppdev;
+     PDESKTOP pdesk;
+     /* If no DEVMODE is given, use registry settings */
+     if (!pdm)
      {
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
+         /* Get the registry settings */
+         Status = UserEnumRegistryDisplaySettings(pustrDevice, &dm);
+         if (!NT_SUCCESS(Status))
+         {
+             DPRINT1("Could not load registry settings\n");
+             return DISP_CHANGE_BADPARAM;
+         }
+     }
+     else if (pdm->dmSize < FIELD_OFFSET(DEVMODEW, dmFields))
+         return DISP_CHANGE_BADMODE; /* This is what winXP SP3 returns */
+     else
+         dm = *pdm;
+     /* Check params */
+     if ((dm.dmFields & (DM_PELSWIDTH | DM_PELSHEIGHT)) != (DM_PELSWIDTH | DM_PELSHEIGHT))
+     {
+         DPRINT1("devmode doesn't specify the resolution.\n");
+         return DISP_CHANGE_BADMODE;
+     }
+     /* Get the PDEV */
+     ppdev = EngpGetPDEV(pustrDevice);
+     if (!ppdev)
+     {
+         DPRINT1("failed to get PDEV\n");
          return DISP_CHANGE_BADPARAM;
      }
  
-     if (hwnd != NULL)
+     /* Fixup values */
+     if(dm.dmBitsPerPel == 0 || !(dm.dmFields & DM_BITSPERPEL))
+     {
+         dm.dmBitsPerPel = ppdev->pdmwDev->dmBitsPerPel;
+         dm.dmFields |= DM_BITSPERPEL;
+     }
+     if((dm.dmFields & DM_DISPLAYFREQUENCY) && (dm.dmDisplayFrequency == 0))
+         dm.dmDisplayFrequency = ppdev->pdmwDev->dmDisplayFrequency;
+     /* Look for the requested DEVMODE */
+     pdm = PDEVOBJ_pdmMatchDevMode(ppdev, &dm);
+     if (!pdm)
+     {
+         DPRINT1("Could not find a matching DEVMODE\n");
+         lResult = DISP_CHANGE_BADMODE;
+         goto leave;
+     }
+     else if (flags & CDS_TEST)
+     {
+         /* It's possible, go ahead! */
+         lResult = DISP_CHANGE_SUCCESSFUL;
+         goto leave;
+     }
+     /* Shall we update the registry? */
+     if (flags & CDS_UPDATEREGISTRY)
+     {
+         /* Open the local or global settings key */
+         Status = UserOpenDisplaySettingsKey(&hkey, pustrDevice, flags & CDS_GLOBAL);
+         if (NT_SUCCESS(Status))
+         {
+             /* Store the settings */
+             RegWriteDisplaySettings(hkey, pdm);
+             /* Close the registry key */
+             ZwClose(hkey);
+         }
+         else
+         {
+             DPRINT1("Could not open registry key\n");
+             lResult = DISP_CHANGE_NOTUPDATED;
+         }
+     }
+     /* Check if DEVMODE matches the current mode */
+     if (pdm == ppdev->pdmwDev && !(flags & CDS_RESET))
+     {
+         DPRINT1("DEVMODE matches, nothing to do\n");
+         goto leave;
+     }
+     /* Shall we apply the settings? */
+     if (!(flags & CDS_NORESET))
+     {
+         ULONG ulResult;
+         /* Remove mouse pointer */
+         UserSetCursor(NULL, TRUE);
+         /* Do the mode switch */
+         ulResult = PDEVOBJ_bSwitchMode(ppdev, pdm);
+         /* Restore mouse pointer, no hooks called */
+         UserSetCursorPos(gpsi->ptCursor.x, gpsi->ptCursor.y, FALSE);
+         /* Check for failure */
+         if (!ulResult)
+         {
+             DPRINT1("failed to set mode\n");
+             lResult = (lResult == DISP_CHANGE_NOTUPDATED) ?
+                 DISP_CHANGE_FAILED : DISP_CHANGE_RESTART;
+             goto leave;
+         }
+         /* Update the system metrics */
+         InitMetrics();
+         //IntvGetDeviceCaps(&PrimarySurface, &GdiHandleTable->DevCaps);
+         /* Remove all cursor clipping */
+         UserClipCursor(NULL);
+         pdesk = IntGetActiveDesktop();
+         //IntHideDesktop(pdesk);
+         /* Send WM_DISPLAYCHANGE to all toplevel windows */
+         co_IntSendMessageTimeout(HWND_BROADCAST,
+                                  WM_DISPLAYCHANGE,
+                                  (WPARAM)ppdev->gdiinfo.cBitsPixel,
+                                  (LPARAM)(ppdev->gdiinfo.ulHorzRes + (ppdev->gdiinfo.ulVertRes << 16)),
+                                  SMTO_NORMAL,
+                                  100,
+                                  &ulResult);
+         //co_IntShowDesktop(pdesk, ppdev->gdiinfo.ulHorzRes, ppdev->gdiinfo.ulVertRes);
+         UserRedrawDesktop();
+     }
+ leave:
+     /* Release the PDEV */
+     PDEVOBJ_vRelease(ppdev);
+     return lResult;
+ }
+ LONG
+ APIENTRY
+ NtUserChangeDisplaySettings(
+     PUNICODE_STRING pustrDevice,
+     LPDEVMODEW lpDevMode,
+     HWND hwnd,
+     DWORD dwflags,
+     LPVOID lParam)
+ {
+     WCHAR awcDevice[CCHDEVICENAME];
+     UNICODE_STRING ustrDevice;
+     DEVMODEW dmLocal;
+     LONG lRet;
+     /* Check arguments */
+     if ((dwflags != CDS_VIDEOPARAMETERS && lParam != NULL) ||
+         (hwnd != NULL))
      {
          SetLastWin32Error(ERROR_INVALID_PARAMETER);
          return DISP_CHANGE_BADPARAM;
      }
  
-     /* Copy devmode */
-     if (lpDevMode != NULL)
+     /* Check flags */
+     if ((dwflags & (CDS_GLOBAL|CDS_NORESET)) && !(dwflags & CDS_UPDATEREGISTRY))
+     {
+         return DISP_CHANGE_BADFLAGS;
+     }
+     /* Copy the device name */
+     if (pustrDevice)
      {
+         /* Initialize destination string */
+         RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
          _SEH2_TRY
          {
-             ProbeForRead(lpDevMode, sizeof(DevMode.dmSize), 1);
-             DevMode.dmSize = lpDevMode->dmSize;
-             DevMode.dmSize = min(sizeof(DevMode), DevMode.dmSize);
-             ProbeForRead(lpDevMode, DevMode.dmSize, 1);
-             RtlCopyMemory(&DevMode, lpDevMode, DevMode.dmSize);
+             /* Probe the UNICODE_STRING and the buffer */
+             ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+             ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+             /* Copy the string */
+             RtlCopyUnicodeString(&ustrDevice, pustrDevice);
          }
          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
          {
-             Status = _SEH2_GetExceptionCode();
+             /* Set and return error */
+             SetLastNtError(_SEH2_GetExceptionCode());
+             _SEH2_YIELD(return DISP_CHANGE_BADPARAM);
          }
          _SEH2_END
  
-         if (!NT_SUCCESS(Status))
+         pustrDevice = &ustrDevice;
+    }
+     /* Copy devmode */
+     if (lpDevMode)
+     {
+         _SEH2_TRY
          {
-             SetLastNtError(Status);
-             return DISP_CHANGE_BADPARAM;
-         }
+             /* Probe the size field of the structure */
+             ProbeForRead(lpDevMode, sizeof(dmLocal.dmSize), 1);
  
-         if (DevMode.dmDriverExtra > 0)
+             /* Calculate usable size */
+             dmLocal.dmSize = min(sizeof(dmLocal), lpDevMode->dmSize);
+             /* Probe and copy the full DEVMODE */
+             ProbeForRead(lpDevMode, dmLocal.dmSize, 1);
+             RtlCopyMemory(&dmLocal, lpDevMode, dmLocal.dmSize);
+         }
+         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
          {
-             DPRINT1("lpDevMode->dmDriverExtra is IGNORED!\n");
-             DevMode.dmDriverExtra = 0;
+             /* Set and return error */
+             SetLastNtError(_SEH2_GetExceptionCode());
+             _SEH2_YIELD(return DISP_CHANGE_BADPARAM);
          }
-         lpSafeDevMode = &DevMode;
-     }
+         _SEH2_END
  
-     /* Copy the device name */
-     if (lpszDeviceName != NULL)
-     {
-         Status = IntSafeCopyUnicodeString(&SafeDeviceName, lpszDeviceName);
-         if (!NT_SUCCESS(Status))
+         /* Check for extra parameters */
+         if (dmLocal.dmDriverExtra > 0)
          {
-             SetLastNtError(Status);
-             return DISP_CHANGE_BADPARAM;
+             /* FIXME: TODO */
+             DPRINT1("lpDevMode->dmDriverExtra is IGNORED!\n");
+             dmLocal.dmDriverExtra = 0;
          }
-         pSafeDeviceName = &SafeDeviceName;
+         /* Use the local structure */
+         lpDevMode = &dmLocal;
      }
  
+     // FIXME: Copy videoparameters
+     /* Acquire global USER lock */
+     UserEnterExclusive();
      /* Call internal function */
-     Ret = IntChangeDisplaySettings(pSafeDeviceName, lpSafeDevMode, dwflags, lParam);
+     lRet = UserChangeDisplaySettings(pustrDevice, lpDevMode, hwnd, dwflags, NULL);
  
-     if (pSafeDeviceName != NULL)
-         RtlFreeUnicodeString(pSafeDeviceName);
+     /* Release lock */
+     UserLeave();
  
-     return Ret;
+     return lRet;
  }
  
@@@ -2,7 -2,7 +2,7 @@@
   * COPYRIGHT:         See COPYING in the top level directory
   * PROJECT:           ReactOS kernel
   * PURPOSE:           Window event handlers
-  * FILE:              subsystem/win32/win32k/ntuser/event.c
+  * FILE:              subsystems/win32/win32k/ntuser/event.c
   * PROGRAMER:         James Tabor (james.tabor@rectos.org)
   */
  
@@@ -103,12 -103,15 +103,15 @@@ IntCallLowLevelEvent( PEVENTHOOK pEH
                          LONG idChild)
  {
     NTSTATUS Status;
-    ULONG_PTR uResult;
-    EVENTPACK EP;
+    PEVENTPACK pEP;
+    ULONG_PTR uResult = 0;
  
-    EP.pEH = pEH;
-    EP.idObject = idObject;
-    EP.idChild = idChild;
+    pEP = ExAllocatePoolWithTag(NonPagedPool, sizeof(EVENTPACK), TAG_HOOK);
+    if (!pEP) return 0;
+    pEP->pEH = pEH;
+    pEP->idObject = idObject;
+    pEP->idChild = idChild;
  
     /* FIXME should get timeout from
      * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
                                 hwnd,
                                 event,
                                 0,
-                               (LPARAM)&EP,
+                               (LPARAM)pEP,
                                 5000,
                                 TRUE,
                                 MSQ_ISEVENT,
                                &uResult);
+    if (!NT_SUCCESS(Status))
+    { 
+       ExFreePoolWithTag(pEP, TAG_HOOK);
+    }
     return NT_SUCCESS(Status) ? uResult : 0;
  }
  
  static
  BOOL
  FASTCALL
@@@ -145,14 -150,49 +150,49 @@@ IntRemoveEvent(PEVENTHOOK pEH
     return FALSE;
  }
  
+ VOID
+ FASTCALL
+ EVENT_DestroyThreadEvents(PETHREAD Thread)
+ {
+    PTHREADINFO pti;
+    PEVENTHOOK pEH;
+    PLIST_ENTRY pLE;
+    pti = Thread->Tcb.Win32Thread;
+    if (!pti) return;
+    if (!GlobalEvents || !GlobalEvents->Counts) return;
+    pLE = GlobalEvents->Events.Flink;
+    if (IsListEmpty(pLE)) return;
+    pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+    do
+    {
+       if (IsListEmpty(pLE)) break;
+       if (!pEH) break;
+       pLE = pEH->Chain.Flink;
+       if (pEH->head.pti == pti)
+       {
+          IntRemoveEvent(pEH);
+       }
+       pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
+    } while (pLE != &GlobalEvents->Events);
+    return;
+ }
  /* FUNCTIONS *****************************************************************/
  
+ //
+ // Dispatch MsgQueue Event Call processor!
+ //
  LRESULT
  FASTCALL
  co_EVENT_CallEvents( DWORD event,
-                        HWND hwnd, 
-                     UINT_PTR idObject,
-                     LONG_PTR idChild)
+                      HWND hwnd, 
+                      UINT_PTR idObject,
+                      LONG_PTR idChild)
  {
     PEVENTHOOK pEH;
     LRESULT Result;
                                   hwnd,
                                   pEP->idObject,
                                   pEP->idChild,
-                                 (DWORD_PTR)(NtCurrentTeb()->ClientId).UniqueThread,
+                                  PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
                                  (DWORD)EngGetTickCount(),
                                   pEH->Proc);
+    ExFreePoolWithTag(pEP, TAG_HOOK);
     return Result;
  }
  
@@@ -177,55 -219,66 +219,66 @@@ IntNotifyWinEvent
     DWORD Event,
     PWND  pWnd,
     LONG  idObject,
-    LONG  idChild)
+    LONG  idChild,
+    DWORD flags)
  {
     PEVENTHOOK pEH;
     PLIST_ENTRY pLE;
+    PTHREADINFO pti, ptiCurrent;
  
     DPRINT("IntNotifyWinEvent GlobalEvents = 0x%x pWnd 0x%x\n",GlobalEvents, pWnd);
  
-    if (!pWnd) return;
+    if (!GlobalEvents || !GlobalEvents->Counts) return;
  
     if (pWnd && pWnd->state & WNDS_DESTROYED) return;
  
-    if (!GlobalEvents || !GlobalEvents->Counts) return;
+    ptiCurrent = PsGetCurrentThreadWin32Thread();
+    if (pWnd && flags & WEF_SETBYWNDPTI)
+       pti = pWnd->head.pti;
+    else
+       pti = ptiCurrent;
  
     pLE = GlobalEvents->Events.Flink;
     pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
     do
-    { 
+    {
+      if (!pEH) break;
       UserReferenceObject(pEH);
       // Must be inside the event window.
       if ( (pEH->eventMin <= Event) && (pEH->eventMax >= Event))
       {
-         if (pEH->head.pti->pEThread != PsGetCurrentThread())
-         { // if all process || all thread || other thread same process
-            if (!(pEH->idProcess) || !(pEH->idThread) || 
-                (NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)(DWORD_PTR)pEH->idProcess))
+ // if all process || all thread || other thread same process
+ // if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
+         if ( (!pEH->idProcess || pEH->idProcess == PtrToUint(pti->pEThread->Cid.UniqueProcess)) &&
+              (!(pEH->Flags & WINEVENT_SKIPOWNPROCESS) || pEH->head.pti->ppi != pti->ppi) &&
+              (!pEH->idThread  || pEH->idThread == PtrToUint(pti->pEThread->Cid.UniqueThread)) &&
+              (!(pEH->Flags & WINEVENT_SKIPOWNTHREAD)  || pEH->head.pti != pti) &&
+                pEH->head.pti->rpdesk == ptiCurrent->rpdesk ) // Same as hooks.
+         {
+            // Send message to the thread if pEH is not current.
+            if (pEH->head.pti != ptiCurrent)
             {
+               DPRINT1("Global Event 0x%x, idObject %d\n", Event, idObject);
                IntCallLowLevelEvent( pEH,
                                      Event,
                                      UserHMGetHandle(pWnd),
                                      idObject,
                                      idChild);
             }
-         }// if ^skip own thread && ((Pid && CPid == Pid && ^skip own process) || all process)
-         else if ( !(pEH->Flags & WINEVENT_SKIPOWNTHREAD) &&
-                    ( ((pEH->idProcess &&
-                      NtCurrentTeb()->ClientId.UniqueProcess == (PVOID)(DWORD_PTR)pEH->idProcess) &&
-                      !(pEH->Flags & WINEVENT_SKIPOWNPROCESS)) ||
-                      !pEH->idProcess ) )
-         {
-             // What in the deuce is this right-aligned formatting?
-            co_IntCallEventProc(          UserHMGetHandle(pEH),
-                                                         Event,
-                                         UserHMGetHandle(pWnd),
-                                                      idObject,
-                                                       idChild,
-              PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
-                                      (DWORD)EngGetTickCount(),
-                                                     pEH->Proc);
-         }
+            else
+            {
+               DPRINT1("Local Event 0x%x, idObject %d\n", Event, idObject);
+               co_IntCallEventProc( UserHMGetHandle(pEH),
+                                    Event,
+                                    UserHMGetHandle(pWnd),
+                                    idObject,
+                                    idChild,
+                                    PtrToUint(NtCurrentTeb()->ClientId.UniqueThread),
+                                   (DWORD)EngGetTickCount(),
+                                    pEH->Proc);
+            }
+         }        
       }
       UserDereferenceObject(pEH);
       pLE = pEH->Chain.Flink;
@@@ -246,17 -299,21 +299,21 @@@ NtUserNotifyWinEvent
     UserEnterExclusive();
  
     /* Validate input */
-    if (hWnd && (hWnd != INVALID_HANDLE_VALUE) && !(Window = UserGetWindowObject(hWnd)))
+    if (hWnd && (hWnd != INVALID_HANDLE_VALUE))
     {
-       UserLeave();
-       return;
+      Window = UserGetWindowObject(hWnd);
+      if (!Window)
+      {
+        UserLeave();
+        return;
+      }
     }
  
     if (gpsi->dwInstalledEventHooks & GetMaskFromEvent(Event))
     {
-       UserRefObjectCo(Window, &Ref);
-       IntNotifyWinEvent( Event, Window, idObject, idChild);
-       UserDerefObjectCo(Window);
+       if (Window) UserRefObjectCo(Window, &Ref);
+       IntNotifyWinEvent( Event, Window, idObject, idChild, WEF_SETBYWNDPTI);
+       if (Window) UserDerefObjectCo(Window);
     }
     UserLeave();
  }
@@@ -322,7 -379,7 +379,7 @@@ NtUserSetWinEventHook
           goto SetEventExit;
        }
     }
+    // Creator, pti is set here.
     pEH = UserCreateObject(gHandleTable, NULL, &Handle, otEvent, sizeof(EVENTHOOK));
     if (pEH)
     {
        GlobalEvents->Counts++;
  
        UserHMGetHandle(pEH) = Handle;
-       if (Thread)
-          pEH->head.pti = Thread->Tcb.Win32Thread;
-       else
-          pEH->head.pti = GetW32ThreadInfo();
        pEH->eventMin  = eventMin;
        pEH->eventMax  = eventMax;
-       pEH->idProcess = idProcess;
-       pEH->idThread  = idThread;
+       pEH->idProcess = idProcess; // These are cmp'ed
+       pEH->idThread  = idThread;  //  "
        pEH->Flags     = dwflags;
+     /*
+        If WINEVENT_INCONTEXT, set offset from hmod and proc. Save ihmod from
+        the atom index table where the hmod data is saved to be recalled later
+        if fSync set by WINEVENT_INCONTEXT.
+        If WINEVENT_OUTOFCONTEXT just use proc..
+        Do this instead....
+      */
        if (NULL != hmodWinEventProc)
        {
           pEH->offPfn = (ULONG_PTR)((char *)lpfnWinEventProc - (char *)hmodWinEventProc);
@@@ -165,6 -165,7 +165,7 @@@ co_IntSendKillFocusMessages(HWND hWndPr
  {
     if (hWndPrev)
     {
+       IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
        co_IntPostOrSendMessage(hWndPrev, WM_KILLFOCUS, (WPARAM)hWnd, 0);
     }
  }
@@@ -174,6 -175,8 +175,8 @@@ co_IntSendSetFocusMessages(HWND hWndPre
  {
     if (hWnd)
     {
+       PWND pWnd = UserGetWindowObject(hWnd);
+       IntNotifyWinEvent(EVENT_OBJECT_FOCUS, pWnd, OBJID_CLIENT, CHILDID_SELF, 0);
        co_IntPostOrSendMessage(hWnd, WM_SETFOCUS, (WPARAM)hWndPrev, 0);
     }
  }
@@@ -356,8 -359,10 +359,10 @@@ co_IntSetActiveWindow(PWND Wnd OPTIONAL
     cbt.fMouse     = FALSE;
     cbt.hWndActive = hWndPrev;
     if (co_HOOK_CallHooks( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt))
+    {
+       DPRINT1("SetActiveWindow WH_CBT Call Hook return!\n");
        return 0;
+    }
     ThreadQueue->ActiveWindow = hWnd;
  
     co_IntSendDeactivateMessages(hWndPrev, hWnd);
@@@ -392,9 -397,11 +397,11 @@@ co_IntSetFocusWindow(PWND Window OPTION
           return hWndPrev;
        }
  
-      if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev))
-         return 0;
+       if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)Window->head.h, (LPARAM)hWndPrev))
+       {
+          DPRINT1("SetFocusWindow 1 WH_CBT Call Hook return!\n");
+          return 0;
+       }
        ThreadQueue->FocusWindow = Window->head.h;
  
        co_IntSendKillFocusMessages(hWndPrev, Window->head.h);
     else
     {
        ThreadQueue->FocusWindow = 0;
-      if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
-         return 0;
+       if (co_HOOK_CallHooks( WH_CBT, HCBT_SETFOCUS, (WPARAM)0, (LPARAM)hWndPrev))
+       {
+          DPRINT1("SetFocusWindow 2 WH_CBT Call Hook return!\n");
+          return 0;
+       }
  
        co_IntSendKillFocusMessages(hWndPrev, 0);
     }
@@@ -533,7 -542,7 +542,7 @@@ NtUserSetCapture(HWND hWnd
  {
     PTHREADINFO pti;
     PUSER_MESSAGE_QUEUE ThreadQueue;
-    PWND Window;
+    PWND Window, pWnd;
     HWND hWndPrev;
     DECLARE_RETURN(HWND);
  
  
     hWndPrev = MsqSetStateWindow(ThreadQueue, MSQ_STATE_CAPTURE, hWnd);
  
+    if (hWndPrev)
+    {
+       pWnd = UserGetWindowObject(hWndPrev);
+       if (pWnd)
+          IntNotifyWinEvent(EVENT_SYSTEM_CAPTUREEND, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
+    }
     /* also remove other windows if not capturing anymore */
-    if(hWnd == NULL)
+    if (hWnd == NULL)
     {
        MsqSetStateWindow(ThreadQueue, MSQ_STATE_MENUOWNER, NULL);
        MsqSetStateWindow(ThreadQueue, MSQ_STATE_MOVESIZE, NULL);
     }
  
+    if (Window)
+       IntNotifyWinEvent(EVENT_SYSTEM_CAPTURESTART, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
     co_IntPostOrSendMessage(hWndPrev, WM_CAPTURECHANGED, 0, (LPARAM)hWnd);
     ThreadQueue->CaptureWindow = hWnd;
  
@@@ -2,8 -2,10 +2,10 @@@
   * COPYRIGHT:        See COPYING in the top level directory
   * PROJECT:          ReactOS kernel
   * PURPOSE:          Window hooks
-  * FILE:             subsystem/win32/win32k/ntuser/hook.c
+  * FILE:             subsystems/win32/win32k/ntuser/hook.c
   * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
+  *                   James Tabor (james.tabor@rectos.org)
+  *
   * REVISION HISTORY:
   *       06-06-2001  CSH  Created
   * NOTE:             Most of this code was adapted from Wine,
  #define NDEBUG
  #include <debug.h>
  
- static PHOOKTABLE GlobalHooks;
- /* PRIVATE FUNCTIONS *********************************************************/
- /* create a new hook table */
- static
- PHOOKTABLE
- IntAllocHookTable(void)
- {
-     PHOOKTABLE Table;
-     UINT i;
-     Table = ExAllocatePoolWithTag(PagedPool, sizeof(HOOKTABLE), TAG_HOOK);
-     if (NULL != Table)
-     {
-         for (i = 0; i < NB_HOOKS; i++)
-         {
-             InitializeListHead(&Table->Hooks[i]);
-             Table->Counts[i] = 0;
-         }
-     }
-     return Table;
- }
- PHOOK
- FASTCALL
- IntGetHookObject(HHOOK hHook)
- {
-     PHOOK Hook;
-     if (!hHook)
-     {
-         SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
-         return NULL;
-     }
-     Hook = (PHOOK)UserGetObject(gHandleTable, hHook, otHook);
-     if (!Hook)
-     {
-         SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
-         return NULL;
-     }
-     ASSERT(Hook->head.cLockObj >= 0);
-     Hook->head.cLockObj++;
-     return Hook;
- }
- /* create a new hook and add it to the specified table */
- static
- PHOOK
- IntAddHook(PETHREAD Thread, int HookId, BOOLEAN Global, PWINSTATION_OBJECT WinStaObj)
- {
-     PTHREADINFO W32Thread;
-     PHOOK Hook;
-     PHOOKTABLE Table = Global ? GlobalHooks : MsqGetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue);
-     HANDLE Handle;
-     if (NULL == Table)
-     {
-         Table = IntAllocHookTable();
-         if (NULL == Table)
-         {
-             return NULL;
-         }
-         if (Global)
-         {
-             GlobalHooks = Table;
-         }
-         else
-         {
-             MsqSetHooks(((PTHREADINFO)Thread->Tcb.Win32Thread)->MessageQueue, Table);
-         }
-     }
-     Hook = UserCreateObject(gHandleTable, NULL, &Handle, otHook, sizeof(HOOK));
-     if (NULL == Hook)
-     {
-         return NULL;
-     }
-     Hook->Thread = Thread;
-     Hook->HookId = HookId;
-     if (Thread)
-     {
-         W32Thread = ((PTHREADINFO)Thread->Tcb.Win32Thread);
-         ASSERT(W32Thread != NULL);
-         W32Thread->fsHooks |= HOOKID_TO_FLAG(HookId);
-         if (W32Thread->pClientInfo)
-            W32Thread->pClientInfo->fsHooks = W32Thread->fsHooks;
-         if (W32Thread->pDeskInfo) // Do this for now.
-            W32Thread->pDeskInfo->fsHooks= W32Thread->fsHooks;
-         Hook->head.pti = W32Thread;
-         Hook->head.rpdesk = W32Thread->rpdesk;
-     }
-     RtlInitUnicodeString(&Hook->ModuleName, NULL);
-     InsertHeadList(&Table->Hooks[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
-     return Hook;
- }
- /* get the hook table that a given hook belongs to */
- static
- PHOOKTABLE
- FASTCALL
- IntGetTable(PHOOK Hook)
- {
-     if (NULL == Hook->Thread || WH_KEYBOARD_LL == Hook->HookId ||
-         WH_MOUSE_LL == Hook->HookId)
-     {
-         return GlobalHooks;
-     }
-     return MsqGetHooks(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue);
- }
- /* get the first hook in the chain */
- static
- PHOOK
- FASTCALL
- IntGetFirstHook(PHOOKTABLE Table, int HookId)
+ typedef struct _HOOKPACK
  {
-     PLIST_ENTRY Elem = Table->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
+   PHOOK pHk; 
+   LPARAM lParam;
+ } HOOKPACK, *PHOOKPACK;
  
-     return Elem == &Table->Hooks[HOOKID_TO_INDEX(HookId)]
-            ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain);
- }
- /* find the first non-deleted hook in the chain */
- static
- PHOOK
- FASTCALL
- IntGetFirstValidHook(PHOOKTABLE Table, int HookId)
- {
-     PHOOK Hook;
-     PLIST_ENTRY Elem;
-     Hook = IntGetFirstHook(Table, HookId);
-     while (NULL != Hook && NULL == Hook->Proc)
-     {
-         Elem = Hook->Chain.Flink;
-         Hook = (Elem == &Table->Hooks[HOOKID_TO_INDEX(HookId)]
-                 ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain));
-     }
-     return Hook;
- }
- /* find the next hook in the chain, skipping the deleted ones */
- PHOOK
- FASTCALL
- IntGetNextHook(PHOOK Hook)
- {
-     PHOOKTABLE Table = IntGetTable(Hook);
-     int HookId = Hook->HookId;
-     PLIST_ENTRY Elem;
-     Elem = Hook->Chain.Flink;
-     while (Elem != &Table->Hooks[HOOKID_TO_INDEX(HookId)])
-     {
-         Hook = CONTAINING_RECORD(Elem, HOOK, Chain);
-         if (NULL != Hook->Proc)
-         {
-             return Hook;
-         }
-     }
-     if (NULL != GlobalHooks && Table != GlobalHooks)  /* now search through the global table */
-     {
-         return IntGetFirstValidHook(GlobalHooks, HookId);
-     }
-     return NULL;
- }
+ /* PRIVATE FUNCTIONS *********************************************************/
  
- /* free a hook, removing it from its chain */
  static
- VOID
+ LRESULT
  FASTCALL
- IntFreeHook(PHOOKTABLE Table, PHOOK Hook, PWINSTATION_OBJECT WinStaObj)
- {
-     RemoveEntryList(&Hook->Chain);
-     RtlFreeUnicodeString(&Hook->ModuleName);
-     /* Dereference thread if required */
-     if (Hook->Flags & HOOK_THREAD_REFERENCED)
-     {
-         ObDereferenceObject(Hook->Thread);
-     }
-     /* Close handle */
-     UserDeleteObject(UserHMGetHandle(Hook), otHook);
- }
- /* remove a hook, freeing it if the chain is not in use */
- static
- VOID
- IntRemoveHook(PHOOK Hook, PWINSTATION_OBJECT WinStaObj, BOOL TableAlreadyLocked)
+ IntCallLowLevelHook( PHOOK Hook,
+                      INT Code,
+                      WPARAM wParam,
+                      LPARAM lParam)
  {
-     PTHREADINFO W32Thread;
-     PHOOKTABLE Table = IntGetTable(Hook);
-     ASSERT(NULL != Table); // At this point this should not be null!
-     W32Thread = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
-     ASSERT(W32Thread != NULL);
-     W32Thread->fsHooks &= ~HOOKID_TO_FLAG(Hook->HookId);
-     GetWin32ClientInfo()->fsHooks = W32Thread->fsHooks;
-     if (W32Thread->pDeskInfo) // Do this for now.
-        W32Thread->pDeskInfo->fsHooks= W32Thread->fsHooks;
+     NTSTATUS Status;
+     PTHREADINFO pti;
+     PHOOKPACK pHP;
+     ULONG_PTR uResult = 0;
  
-     if (0 != Table->Counts[HOOKID_TO_INDEX(Hook->HookId)])
-     {
-         Hook->Proc = NULL; /* chain is in use, just mark it and return */
-     }
+     if (Hook->Thread)
+        pti = Hook->Thread->Tcb.Win32Thread;
      else
-     {
-         IntFreeHook(Table, Hook, WinStaObj);
-     }
- }
+        pti = Hook->head.pti;
  
- /* release a hook chain, removing deleted hooks if the use count drops to 0 */
- static
- VOID
- FASTCALL
- IntReleaseHookChain(PHOOKTABLE Table, int HookId, PWINSTATION_OBJECT WinStaObj)
- {
-     PLIST_ENTRY Elem;
-     PHOOK HookObj;
+     pHP = ExAllocatePoolWithTag(NonPagedPool, sizeof(HOOKPACK), TAG_HOOK);
+     if (!pHP) return 0;
  
-     if (NULL == Table)
-     {
-         return;
-     }
-     /* use count shouldn't already be 0 */
-     ASSERT(0 != Table->Counts[HOOKID_TO_INDEX(HookId)]);
-     if (0 == Table->Counts[HOOKID_TO_INDEX(HookId)])
-     {
-         return;
-     }
-     if (0 == --Table->Counts[HOOKID_TO_INDEX(HookId)])
-     {
-         Elem = Table->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
-         while (Elem != &Table->Hooks[HOOKID_TO_INDEX(HookId)])
-         {
-             HookObj = CONTAINING_RECORD(Elem, HOOK, Chain);
-             Elem = Elem->Flink;
-             if (NULL == HookObj->Proc)
-             {
-                 IntFreeHook(Table, HookObj, WinStaObj);
-             }
-         }
-     }
- }
- static
- LRESULT
- FASTCALL
- IntCallLowLevelHook(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
- {
-     NTSTATUS Status;
-     ULONG_PTR uResult;
+     pHP->pHk = Hook;
+     pHP->lParam = lParam;
  
      /* FIXME should get timeout from
       * HKEY_CURRENT_USER\Control Panel\Desktop\LowLevelHooksTimeout */
-     Status = co_MsqSendMessage(((PTHREADINFO)Hook->Thread->Tcb.Win32Thread)->MessageQueue,
-                                 IntToPtr(Code),
-                                 Hook->HookId,
+     Status = co_MsqSendMessage( pti->MessageQueue,
+                                 IntToPtr(Code), // hWnd
+                                 Hook->HookId,   // Msg
                                  wParam,
-                                 lParam,
+                                 (LPARAM)pHP,
                                  5000,
                                  TRUE,
                                  MSQ_ISHOOK,
-                                 &uResult);
-     return NT_SUCCESS(Status) ? uResult : 0;
- }
- /*
-   Called from inside kernel space.
-  */
- LRESULT
- FASTCALL
- co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
- {
-     PHOOK Hook, SaveHook;
-     PTHREADINFO pti;
-     PCLIENTINFO ClientInfo;
-     PHOOKTABLE Table;
-     LRESULT Result;
-     PWINSTATION_OBJECT WinStaObj;
-     NTSTATUS Status;
-     ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
- #if 0
-     /* FIXME! Check pDeskInfo->fsHooks for global hooks! */
-     if (!ISITHOOKED(HookId))
-     {
-         return 0;
-     }
- #endif
-     pti = PsGetCurrentThreadWin32Thread();
-     if (!pti)
-     {
-         Table = NULL;
-     }
-     else
-     {
-         Table = MsqGetHooks(pti->MessageQueue);
-     }
-     if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
-     {
-         /* try global table */
-         Table = GlobalHooks;
-         if (NULL == Table || ! (Hook = IntGetFirstValidHook(Table, HookId)))
-         {
-             return 0;  /* no hook set */
-         }
-     }
-     if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
-     {
-         DPRINT1("\nHook found by Id and posted to Thread! %d\n",HookId );
-         /* Post it in message queue. */
-         return IntCallLowLevelHook(Hook, Code, wParam, lParam);
-     }
-     Table->Counts[HOOKID_TO_INDEX(HookId)]++;
-     if (Table != GlobalHooks && GlobalHooks != NULL)
-     {
-         GlobalHooks->Counts[HOOKID_TO_INDEX(HookId)]++;
-     }
-     ClientInfo = GetWin32ClientInfo();
-     SaveHook = ClientInfo->phkCurrent;
-     ClientInfo->phkCurrent = Hook;     /* Load the call. */
-     Result = co_IntCallHookProc(HookId,
-                                 Code,
-                                 wParam,
-                                 lParam,
-                                 Hook->Proc,
-                                 Hook->Ansi,
-                                 &Hook->ModuleName);
-     ClientInfo->phkCurrent = SaveHook;
-     Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                                             KernelMode,
-                                             0,
-                                             &WinStaObj);
+                                &uResult);
      if (!NT_SUCCESS(Status))
      {
-         DPRINT1("Invalid window station????\n");
-     }
-     else
-     {
-         IntReleaseHookChain(MsqGetHooks(pti->MessageQueue), HookId, WinStaObj);
-         IntReleaseHookChain(GlobalHooks, HookId, WinStaObj);
-         ObDereferenceObject(WinStaObj);
-     }
-     return Result;
- }
- VOID
- FASTCALL
- HOOK_DestroyThreadHooks(PETHREAD Thread)
- {
-     int HookId;
-     PLIST_ENTRY Elem;
-     PHOOK HookObj;
-     PWINSTATION_OBJECT WinStaObj;
-     NTSTATUS Status;
-     if (NULL != GlobalHooks)
-     {
-         Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                                                 KernelMode,
-                                                 0,
-                                                 &WinStaObj);
-         if (!NT_SUCCESS(Status))
-         {
-             DPRINT1("Invalid window station????\n");
-             return;
-         }
-         for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
-         {
-             /* only low-level keyboard/mouse global hooks can be owned by a thread */
-             switch(HookId)
-             {
-                 case WH_KEYBOARD_LL:
-                 case WH_MOUSE_LL:
-                     Elem = GlobalHooks->Hooks[HOOKID_TO_INDEX(HookId)].Flink;
-                     while (Elem != &GlobalHooks->Hooks[HOOKID_TO_INDEX(HookId)])
-                     {
-                         HookObj = CONTAINING_RECORD(Elem, HOOK, Chain);
-                         Elem = Elem->Flink;
-                         if (HookObj->Thread == Thread)
-                         {
-                             IntRemoveHook(HookObj, WinStaObj, TRUE);
-                         }
-                     }
-                     break;
-             }
-         }
+        DPRINT1("Error Hook Call SendMsg. %d Status: 0x%x\n", Hook->HookId, Status);
+        ExFreePoolWithTag(pHP, TAG_HOOK);
      }
+     return NT_SUCCESS(Status) ? uResult : 0;
  }
  
  static
  LRESULT
  FASTCALL
- co_HOOK_CallHookNext(PHOOK Hook, INT Code, WPARAM wParam, LPARAM lParam)
+ co_HOOK_CallHookNext( PHOOK Hook,
+                       INT Code,
+                       WPARAM wParam,
+                       LPARAM lParam)
  {
-     if ((Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL))
+     if ( (Hook->Thread != PsGetCurrentThread()) && (Hook->Thread != NULL) )
      {
-         DPRINT1("CALLING HOOK from another Thread. %d\n", Hook->HookId);
+         DPRINT1("Calling Next HOOK from another Thread. %d\n", Hook->HookId);
          return IntCallLowLevelHook(Hook, Code, wParam, lParam);
      }
  
-     DPRINT("CALLING HOOK %d\n", Hook->HookId);
+     DPRINT("Calling Next HOOK %d\n", Hook->HookId);
  
-     return co_IntCallHookProc(Hook->HookId,
-                               Code,
-                               wParam,
-                               lParam,
-                               Hook->Proc,
-                               Hook->Ansi,
+     return co_IntCallHookProc( Hook->HookId,
+                                Code,
+                                wParam,
+                                lParam,
+                                Hook->Proc,
+                                Hook->Ansi,
                                &Hook->ModuleName);
  }
  
+ //
+ // Dispatch MsgQueue Hook Call processor!
+ //
+ LRESULT
+ FASTCALL
+ co_CallHook( INT HookId,
+              INT Code,
+              WPARAM wParam,
+              LPARAM lParam)
+ {
+     LRESULT Result;
+     PHOOK phk;
+     PHOOKPACK pHP = (PHOOKPACK)lParam;
+     phk = pHP->pHk;
+     /* The odds are high for this to be a Global call. */
+     Result = co_IntCallHookProc( HookId,
+                                  Code,
+                                  wParam,
+                                  pHP->lParam,
+                                  phk->Proc,
+                                  phk->Ansi,
+                                 &phk->ModuleName);
+     ExFreePoolWithTag(pHP, TAG_HOOK);
+     return Result;
+ }
  
  LRESULT
  FASTCALL
- IntCallDebugHook(PHOOK Hook,
-                  int Code,
-                  WPARAM wParam,
-                  LPARAM lParam)
+ IntCallDebugHook( PHOOK Hook,
+                   int Code,
+                   WPARAM wParam,
+                   LPARAM lParam,
+                   BOOL Ansi)
  {
      LRESULT lResult = 0;
      ULONG Size;
      return lResult;
  }
  
- /*
-    Called from user space via CallNextHook.
-  */
  LRESULT
  FASTCALL
- UserCallNextHookEx(PHOOK Hook,
-                    int Code,
-                    WPARAM wParam,
-                    LPARAM lParam,
-                    BOOL Ansi)
+ UserCallNextHookEx( PHOOK Hook,
+                     int Code,
+                     WPARAM wParam,
+                     LPARAM lParam,
+                     BOOL Ansi)
  {
      LRESULT lResult = 0;
      BOOL BadChk = FALSE;
                      break;
              }
              break;
+ /*
+  Note WH_JOURNALPLAYBACK,
+     "To have the system wait before processing the message, the return value
+      must be the amount of time, in clock ticks, that the system should wait."
+  */
          case WH_JOURNALPLAYBACK:
          case WH_JOURNALRECORD:
          {
          }
  
          case WH_DEBUG:
-             lResult = IntCallDebugHook(Hook, Code, wParam, lParam);
+             lResult = IntCallDebugHook(Hook, Code, wParam, lParam, Ansi);
              break;
  
          /*
              DPRINT1("Unsupported HOOK Id -> %d\n",Hook->HookId);
              break;
      }
      return lResult; 
  }
  
+ PHOOK
+ FASTCALL
+ IntGetHookObject(HHOOK hHook)
+ {
+     PHOOK Hook;
+     
+     if (!hHook)
+     {
+        SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
+        return NULL;
+     }
+     Hook = (PHOOK)UserGetObject(gHandleTable, hHook, otHook);
+     if (!Hook)
+     {
+        SetLastWin32Error(ERROR_INVALID_HOOK_HANDLE);
+        return NULL;
+     }
+     UserReferenceObject(Hook);
+     return Hook;
+ }
+ /* get the first hook in the chain */
+ static
+ PHOOK
+ FASTCALL
+ IntGetFirstHook(PLIST_ENTRY Table)
+ {
+     PLIST_ENTRY Elem = Table->Flink;
+     if (IsListEmpty(Table)) return NULL;
+     return Elem == Table ? NULL : CONTAINING_RECORD(Elem, HOOK, Chain);
+ }
+ /* find the next hook in the chain  */
+ PHOOK
+ FASTCALL
+ IntGetNextHook(PHOOK Hook)
+ {
+     int HookId = Hook->HookId;
+     PLIST_ENTRY Elem;
+     PTHREADINFO pti;
+     if (Hook->Thread)
+     {
+        pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
+        Elem = Hook->Chain.Flink;
+        if (Elem != &pti->aphkStart[HOOKID_TO_INDEX(HookId)])
+           return CONTAINING_RECORD(Elem, HOOK, Chain);
+     }
+     else
+     {
+        pti = PsGetCurrentThreadWin32Thread();
+        Elem = Hook->Chain.Flink;
+        if (Elem != &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)])
+           return CONTAINING_RECORD(Elem, HOOK, Chain);
+     }
+     return NULL;
+ }
+ /* free a hook, removing it from its chain */
+ static
+ VOID
+ FASTCALL
+ IntFreeHook(PHOOK Hook)
+ {
+     RemoveEntryList(&Hook->Chain);
+     if (Hook->ModuleName.Buffer)
+     {
+        ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
+        Hook->ModuleName.Buffer = NULL;
+     }
+     /* Close handle */
+     UserDeleteObject(UserHMGetHandle(Hook), otHook);
+ }
+ /* remove a hook, freeing it from the chain */
+ static
+ BOOL
+ FASTCALL
+ IntRemoveHook(PHOOK Hook)
+ {
+     INT HookId;
+     PTHREADINFO pti;
+     HookId = Hook->HookId;
+     if (Hook->Thread) // Local
+     {
+        pti = ((PTHREADINFO)Hook->Thread->Tcb.Win32Thread);
+        IntFreeHook( Hook);
+        if ( IsListEmpty(&pti->aphkStart[HOOKID_TO_INDEX(HookId)]) )
+        {
+           pti->fsHooks &= ~HOOKID_TO_FLAG(HookId);
+           _SEH2_TRY
+           {
+              GetWin32ClientInfo()->fsHooks = pti->fsHooks;
+           }
+           _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+           {
+           }
+           _SEH2_END;
+           return TRUE;
+        }
+     }
+     else // Global
+     {
+        IntFreeHook( Hook);
+        pti = PsGetCurrentThreadWin32Thread();
+        if ( pti->rpdesk &&
+             pti->rpdesk->pDeskInfo &&
+             IsListEmpty(&pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)]) )
+        {
+           pti->rpdesk->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId);
+           return TRUE;
+        }
+     }
+     return FALSE;
+ }
+ VOID
+ FASTCALL
+ HOOK_DestroyThreadHooks(PETHREAD Thread)
+ {
+    PTHREADINFO pti;
+    int HookId;
+    PHOOK HookObj;
+    PLIST_ENTRY pElem;
+    pti = Thread->Tcb.Win32Thread;
+    if (!pti || !pti->pDeskInfo) return;
+ // Local Thread cleanup.
+    if (pti->fsHooks)
+    {
+       for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
+       {
+          PLIST_ENTRY pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
+          if (IsListEmpty(pLLE)) continue;
+          pElem = pLLE->Flink;
+          HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+          do
+          {
+             if (!HookObj) break;
+             if (IntRemoveHook(HookObj)) break;
+             pElem = HookObj->Chain.Flink;
+             HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+          }
+          while (pElem != pLLE);
+       }
+       pti->fsHooks = 0;
+    }
+ // Global search based on Thread and cleanup.
+    if (pti->rpdesk->pDeskInfo->fsHooks)
+    {
+       for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
+       {
+          PLIST_ENTRY pGLE = &pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)];
+          if (IsListEmpty(pGLE)) continue;
+          pElem = pGLE->Flink;
+          HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+          do
+          {
+             if (!HookObj) break;
+             if (HookObj->head.pti == pti)
+             {
+                if (IntRemoveHook(HookObj)) break;
+             }
+             pElem = HookObj->Chain.Flink;
+             HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
+          }
+          while (pElem != pGLE);
+       }
+    }
+    return;
+ }
+ /*
+   Win32k Kernel Space Hook Caller.
+  */
  LRESULT
- APIENTRY
NtUserCallNextHookEx(int Code,
-                      WPARAM wParam,
-                      LPARAM lParam,
-                      BOOL Ansi)
+ FASTCALL
co_HOOK_CallHooks( INT HookId,
+                    INT Code,
+                    WPARAM wParam,
+                    LPARAM lParam)
  {
-     PHOOK HookObj, NextObj;
+     PHOOK Hook, SaveHook;
+     PTHREADINFO pti;
      PCLIENTINFO ClientInfo;
-     PWINSTATION_OBJECT WinStaObj;
-     NTSTATUS Status;
-     DECLARE_RETURN(LRESULT);
+     PLIST_ENTRY pLLE, pGLE;
+     BOOL Local = FALSE, Global = FALSE;
+     LRESULT Result = 0;
  
-     DPRINT("Enter NtUserCallNextHookEx\n");
-     UserEnterExclusive();
+     ASSERT(WH_MINHOOK <= HookId && HookId <= WH_MAXHOOK);
  
-     Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                                             KernelMode,
-                                             0,
-                                             &WinStaObj);
-     if (!NT_SUCCESS(Status))
+     pti = PsGetCurrentThreadWin32Thread();
+     if (!pti || !pti->rpdesk || !pti->rpdesk->pDeskInfo)
+        goto Exit; // Must have a desktop running for hooks.
+     if ( pti->TIF_flags & TIF_INCLEANUP)
+        goto Exit;
+     if ( ISITHOOKED(HookId) )
      {
-         SetLastNtError(Status);
-         RETURN( 0);
+        DPRINT("Local Hooker %d\n", HookId);
+        Local = TRUE;
      }
  
-     ObDereferenceObject(WinStaObj);
+     if ( pti->rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(HookId) )
+     {
+        DPRINT("Global Hooker %d\n", HookId);
+        Global = TRUE;
+     }
  
-     ClientInfo = GetWin32ClientInfo();
+     if ( !Local && !Global ) goto Exit; // No work!
  
-     if (!ClientInfo) RETURN( 0);
+     pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
+     pGLE = &pti->rpdesk->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)];
+     Hook = NULL;
  
-     HookObj = ClientInfo->phkCurrent;
+     /* SetWindowHookEx sorts out the Thread issue by placing the Hook to
+        the correct Thread if not NULL.
+      */
+     if ( Local )
+     {
+        Hook = IntGetFirstHook(pLLE);
+        if (!Hook)
+        {
+           DPRINT1("No Local Hook Found!\n");
+           goto Exit;
+        }
+        ObReferenceObject(Hook->Thread);
+        ClientInfo = pti->pClientInfo;
+        SaveHook = pti->sphkCurrent;
+        /* Load it for the next call. */
+        pti->sphkCurrent = Hook;
+        Hook->phkNext = IntGetNextHook(Hook);
+        if (ClientInfo)
+        {
+           _SEH2_TRY
+           {
+              ClientInfo->phkCurrent = Hook;
+           }
+           _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+           {
+              ClientInfo = NULL; // Don't bother next run.
+           }
+           _SEH2_END;
+        }
+        Result = co_IntCallHookProc( HookId,
+                                     Code,
+                                     wParam,
+                                     lParam,
+                                     Hook->Proc,
+                                     Hook->Ansi,
+                                    &Hook->ModuleName);
+        if (ClientInfo)
+        {
+           _SEH2_TRY
+           {
+              ClientInfo->phkCurrent = SaveHook;
+           }
+           _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+           {
+           }
+           _SEH2_END;
+        }
+        pti->sphkCurrent = SaveHook;
+        Hook->phkNext = NULL;
+        ObDereferenceObject(Hook->Thread);
+     }
  
-     if (!HookObj) RETURN( 0);
+     if ( Global )
+     {
+        PTHREADINFO ptiHook;
+        Hook = IntGetFirstHook(pGLE);
+        if (!Hook)
+        {
+           DPRINT1("No Global Hook Found!\n");
+           goto Exit;
+        }
+       /* Performance goes down the drain. If more hooks are associated to this
+        * hook ID, this will have to post to each of the thread message queues
+        * or make a direct call.
+        */
+        do
+        {
+          /* Hook->Thread is null, we hax around this with Hook->head.pti. */
+           ptiHook = Hook->head.pti;
+          /* "Global hook monitors messages for all threads in the same desktop
+           *  as the calling thread."
+           */
+           if ( ptiHook->TIF_flags & TIF_INCLEANUP ||
+                ptiHook->rpdesk != pti->rpdesk)
+           {
+              Hook = IntGetNextHook(Hook);
+              if (!Hook) break;
+              continue;
+           }
+           // Lockup the thread while this links through user world.
+           ObReferenceObject(ptiHook->pEThread);
+           if (ptiHook != pti )
+           {
+              DPRINT("\nGlobal Hook posting to another Thread! %d\n",HookId );
+              Result = IntCallLowLevelHook(Hook, Code, wParam, lParam);
+           }
+           else
+           { /* Make the direct call. */
+              DPRINT("\nLocal Hook calling to Thread! %d\n",HookId );
+              Result = co_IntCallHookProc( HookId,
+                                           Code,
+                                           wParam,
+                                           lParam,
+                                           Hook->Proc,
+                                           Hook->Ansi,
+                                          &Hook->ModuleName);
+           }
+           ObDereferenceObject(ptiHook->pEThread);
+           Hook = IntGetNextHook(Hook);
+        }
+        while ( Hook );
+        DPRINT("Ret: Global HookId %d Result 0x%x\n", HookId,Result);
+     }
+ Exit:
+     return Result;
+ }
  
-     /* Check that the first hook in the chain is not this hook */
-     NextObj = IntGetFirstHook(IntGetTable(HookObj), HookObj->HookId);
+ BOOL
+ FASTCALL
+ IntUnhookWindowsHook(int HookId, HOOKPROC pfnFilterProc)
+ {
+     PHOOK Hook;
+     PLIST_ENTRY pLLE, pLE;
+     PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
  
-     /* Its the same so it has already been called */
-     if (HookObj == NextObj) RETURN(0);
+     if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
+     {
+        SetLastWin32Error(ERROR_INVALID_HOOK_FILTER);
+        return FALSE;
+     }
  
-     UserReferenceObject(HookObj);
+     if (pti->fsHooks)
+     {
+        pLLE = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
+        if (IsListEmpty(pLLE)) return FALSE;
+        pLE = pLLE->Flink;
+        Hook = CONTAINING_RECORD(pLE, HOOK, Chain);
+        do
+        {
+           if (!Hook) break;
+           if (Hook->Proc == pfnFilterProc)
+           {
+              if (Hook->head.pti == pti)
+              {
+                 IntRemoveHook(Hook);
+                 UserDereferenceObject(Hook);
+                 return TRUE;
+              }
+              else
+              {
+                 SetLastWin32Error(ERROR_ACCESS_DENIED);
+                 return FALSE;
+              }
+           }
+           pLE = Hook->Chain.Flink;
+           Hook = CONTAINING_RECORD(pLE, HOOK, Chain);
+        }
+        while (pLE != pLLE);
+     }
+     return FALSE;
+ }
  
-     Ansi = HookObj->Ansi;
+ /*
+  *  Support for compatibility only? Global hooks are processed in kernel space.
+  *  This is very thread specific! Never seeing applications with more than one
+  *  hook per thread installed. Most of the applications are Global hookers and
+  *  associated with just one hook Id. Maybe it's for diagnostic testing or a
+  *  throw back to 3.11?
+  */
+ LRESULT
+ APIENTRY
+ NtUserCallNextHookEx( int Code,
+                       WPARAM wParam,
+                       LPARAM lParam,
+                       BOOL Ansi)
+ {
+     PTHREADINFO pti;
+     PHOOK HookObj, NextObj;
+     PCLIENTINFO ClientInfo;
+     LRESULT lResult = 0;
+     DECLARE_RETURN(LRESULT);
+     DPRINT("Enter NtUserCallNextHookEx\n");
+     UserEnterExclusive();
  
-     if (NULL != HookObj->Thread && (HookObj->Thread != PsGetCurrentThread()))
+     pti = GetW32ThreadInfo();
+     HookObj = pti->sphkCurrent;
+     if (!HookObj) RETURN( 0);
+     NextObj = HookObj->phkNext;
+     pti->sphkCurrent = NextObj;
+     ClientInfo = pti->pClientInfo;
+     _SEH2_TRY
      {
-         DPRINT1("Thread mismatch\n");
-         UserDereferenceObject(HookObj);
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         RETURN( 0);
+        ClientInfo->phkCurrent = NextObj;
      }
-    
-     NextObj = IntGetNextHook(HookObj);
-     ClientInfo->phkCurrent = NextObj; /* Preset next hook from list. */
-     UserCallNextHookEx( HookObj, Code, wParam, lParam, Ansi);
-     UserDereferenceObject(HookObj);
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+        ClientInfo = NULL;
+     }
+     _SEH2_END;
  
-     RETURN( (LRESULT)NextObj);
+     /* Now in List run down. */
+     if (ClientInfo && NextObj)
+     {
+        NextObj->phkNext = IntGetNextHook(NextObj);
+        lResult = UserCallNextHookEx( NextObj, Code, wParam, lParam, NextObj->Ansi);
+     }
+     RETURN( lResult);
  
  CLEANUP:
      DPRINT("Leave NtUserCallNextHookEx, ret=%i\n",_ret_);
  
  HHOOK
  APIENTRY
- NtUserSetWindowsHookAW(int idHook, 
-                        HOOKPROC lpfn,
-                        BOOL Ansi)
+ NtUserSetWindowsHookAW( int idHook, 
+                         HOOKPROC lpfn,
+                         BOOL Ansi)
  {
+     DWORD ThreadId;
      UNICODE_STRING USModuleName;
  
      RtlInitUnicodeString(&USModuleName, NULL);
-     return NtUserSetWindowsHookEx(NULL, &USModuleName, 0, idHook, lpfn, Ansi);
+     ThreadId = PtrToUint(NtCurrentTeb()->ClientId.UniqueThread);
+     return NtUserSetWindowsHookEx( NULL,
+                                   &USModuleName,
+                                    ThreadId,
+                                    idHook,
+                                    lpfn,
+                                    Ansi);
  }
  
  HHOOK
  APIENTRY
- NtUserSetWindowsHookEx(HINSTANCE Mod,
-                        PUNICODE_STRING UnsafeModuleName,
-                        DWORD ThreadId,
-                        int HookId,
-                        HOOKPROC HookProc,
-                        BOOL Ansi)
+ NtUserSetWindowsHookEx( HINSTANCE Mod,
+                         PUNICODE_STRING UnsafeModuleName,
+                         DWORD ThreadId,
+                         int HookId,
+                         HOOKPROC HookProc,
+                         BOOL Ansi)
  {
      PWINSTATION_OBJECT WinStaObj;
-     PCLIENTINFO ClientInfo;
-     BOOLEAN Global;
-     PETHREAD Thread;
      PHOOK Hook;
      UNICODE_STRING ModuleName;
      NTSTATUS Status;
      HHOOK Handle;
-     BOOLEAN ThreadReferenced = FALSE;
+     PETHREAD Thread = NULL;
+     PTHREADINFO ptiCurrent, pti = NULL;
+     BOOL Hit = FALSE;
      DECLARE_RETURN(HHOOK);
  
      DPRINT("Enter NtUserSetWindowsHookEx\n");
      UserEnterExclusive();
  
+     ptiCurrent = GetW32ThreadInfo();
      if (HookId < WH_MINHOOK || WH_MAXHOOK < HookId )
      {
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
+         SetLastWin32Error(ERROR_INVALID_HOOK_FILTER);
          RETURN( NULL);
      }
  
          RETURN( NULL);
      }
  
-     ClientInfo = GetWin32ClientInfo();
      if (ThreadId)  /* thread-local hook */
      {
-         if (HookId == WH_JOURNALRECORD ||
+        if ( HookId == WH_JOURNALRECORD ||
              HookId == WH_JOURNALPLAYBACK ||
              HookId == WH_KEYBOARD_LL ||
              HookId == WH_MOUSE_LL ||
              HookId == WH_SYSMSGFILTER)
-         {
-             /* these can only be global */
-             SetLastWin32Error(ERROR_INVALID_PARAMETER);
-             RETURN( NULL);
-         }
-         Mod = NULL;
-         Global = FALSE;
-         if (!NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)(DWORD_PTR) ThreadId, &Thread)))
-         {
-             DPRINT1("Invalid thread id 0x%x\n", ThreadId);
-             SetLastWin32Error(ERROR_INVALID_PARAMETER);
-             RETURN( NULL);
-         }
-         /* Thread was referenced */
-         ThreadReferenced = TRUE;
-         if (Thread->ThreadsProcess != PsGetCurrentProcess())
-         {
-             ObDereferenceObject(Thread);
-             DPRINT1("Can't specify thread belonging to another process\n");
-             SetLastWin32Error(ERROR_INVALID_PARAMETER);
-             RETURN( NULL);
-         }
+        {
+            DPRINT1("Local hook installing Global HookId: %d\n",HookId);
+            /* these can only be global */
+            SetLastWin32Error(ERROR_GLOBAL_ONLY_HOOK);
+            RETURN( NULL);
+        }
+        if (!NT_SUCCESS(PsLookupThreadByThreadId((HANDLE)(DWORD_PTR) ThreadId, &Thread)))
+        {
+           DPRINT1("Invalid thread id 0x%x\n", ThreadId);
+           SetLastWin32Error(ERROR_INVALID_PARAMETER);
+           RETURN( NULL);
+        }
+        pti = Thread->Tcb.Win32Thread;
+        ObDereferenceObject(Thread);
+        if ( pti->rpdesk != ptiCurrent->rpdesk) // gptiCurrent->rpdesk)
+        {
+           DPRINT1("Local hook wrong desktop HookId: %d\n",HookId);
+           SetLastWin32Error(ERROR_ACCESS_DENIED);
+           RETURN( NULL);
+        }
+        if (Thread->ThreadsProcess != PsGetCurrentProcess())
+        {
+           if ( !Mod &&
+               (HookId == WH_GETMESSAGE ||
+                HookId == WH_CALLWNDPROC ||
+                HookId == WH_CBT ||
+                HookId == WH_HARDWARE ||
+                HookId == WH_DEBUG ||
+                HookId == WH_SHELL ||
+                HookId == WH_FOREGROUNDIDLE ||
+                HookId == WH_CALLWNDPROCRET) )
+           {
+              DPRINT1("Local hook needs hMod HookId: %d\n",HookId);
+              SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
+              RETURN( NULL);
+           }
+           if ( (pti->TIF_flags & (TIF_CSRSSTHREAD|TIF_SYSTEMTHREAD)) && 
+                (HookId == WH_GETMESSAGE ||
+                 HookId == WH_CALLWNDPROC ||
+                 HookId == WH_CBT ||
+                 HookId == WH_HARDWARE ||
+                 HookId == WH_DEBUG ||
+                 HookId == WH_SHELL ||
+                 HookId == WH_FOREGROUNDIDLE ||
+                 HookId == WH_CALLWNDPROCRET) )
+           {
+              SetLastWin32Error(ERROR_HOOK_TYPE_NOT_ALLOWED);
+              RETURN( NULL);
+           }
+        }
      }
      else  /* system-global hook */
      {
-         if (HookId == WH_KEYBOARD_LL || HookId == WH_MOUSE_LL)
-         {
-             Mod = NULL;
-             Thread = PsGetCurrentThread();
-             Status = ObReferenceObjectByPointer(Thread,
-                                                 THREAD_ALL_ACCESS,
-                                                 PsThreadType,
-                                                 KernelMode);
-             if (!NT_SUCCESS(Status))
-             {
-                 SetLastNtError(Status);
-                 RETURN( (HANDLE) NULL);
-             }
-             /* Thread was referenced */
-             ThreadReferenced = TRUE;
-         }
-         else if (NULL ==  Mod)
-         {
-             SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
-             RETURN( NULL);
-         }
-         else
-         {
-             Thread = NULL;
-         }
-         Global = TRUE;
+        pti = ptiCurrent; // gptiCurrent;
+        if ( !Mod &&
+             (HookId == WH_GETMESSAGE ||
+              HookId == WH_CALLWNDPROC ||
+              HookId == WH_CBT ||
+              HookId == WH_SYSMSGFILTER ||
+              HookId == WH_HARDWARE ||
+              HookId == WH_DEBUG ||
+              HookId == WH_SHELL ||
+              HookId == WH_FOREGROUNDIDLE ||
+              HookId == WH_CALLWNDPROCRET) )
+        {
+           DPRINT1("Global hook needs hMod HookId: %d\n",HookId);
+           SetLastWin32Error(ERROR_HOOK_NEEDS_HMOD);
+           RETURN( NULL);
+        }
      }
  
-     if ((Global && (HookId != WH_KEYBOARD_LL && HookId != WH_MOUSE_LL)) ||
-         WH_DEBUG == HookId ||
-         WH_JOURNALPLAYBACK == HookId ||
-         WH_JOURNALRECORD == HookId)
-     {
- #if 0 /* Removed to get winEmbed working again */
-         UNIMPLEMENTED
- #else
-         DPRINT1("Not implemented: HookId %d Global %s\n", HookId, Global ? "TRUE" : "FALSE");
- #endif
-         /* Dereference thread if needed */
-         if (ThreadReferenced) ObDereferenceObject(Thread);
-         SetLastWin32Error(ERROR_NOT_SUPPORTED);
-         RETURN( NULL);
-     }
-     Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                                             KernelMode,
-                                             0,
+     Status = IntValidateWindowStationHandle( PsGetCurrentProcess()->Win32WindowStation,
+                                              KernelMode,
+                                              0,
                                              &WinStaObj);
  
      if (!NT_SUCCESS(Status))
      {
-         /* Dereference thread if needed */
-         if (ThreadReferenced) ObDereferenceObject(Thread);
-         SetLastNtError(Status);
-         RETURN( (HANDLE) NULL);
+        SetLastNtError(Status);
+        RETURN( NULL);
      }
+     ObDereferenceObject(WinStaObj);
  
-     Hook = IntAddHook(Thread, HookId, Global, WinStaObj);
-     if (NULL == Hook)
+     Hook = UserCreateObject(gHandleTable, NULL, &Handle, otHook, sizeof(HOOK));
+     if (!Hook)
      {
-         /* Dereference thread if needed */
-         if (ThreadReferenced) ObDereferenceObject(Thread);
-         ObDereferenceObject(WinStaObj);
-         RETURN( NULL);
+        RETURN( NULL);
      }
  
-     /* Let IntFreeHook now that this thread needs a dereference */
-     if (ThreadReferenced)
+     Hook->ihmod   = (INT)Mod; // Module Index from atom table, Do this for now.
+     Hook->Thread  = Thread; /* Set Thread, Null is Global. */
+     Hook->HookId  = HookId;
+     Hook->rpdesk  = pti->rpdesk;
+     Hook->phkNext = NULL; /* Dont use as a chain! Use link lists for chaining. */
+     Hook->Proc    = HookProc;
+     Hook->Ansi    = Ansi;
+     if (ThreadId)  /* thread-local hook */
      {
-         Hook->Flags |= HOOK_THREAD_REFERENCED;
+        InsertHeadList(&pti->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
+        pti->sphkCurrent = NULL;
+        Hook->ptiHooked = pti;
+        pti->fsHooks |= HOOKID_TO_FLAG(HookId);
+        if (pti->pClientInfo)
+        {
+           if ( pti->ppi == ptiCurrent->ppi) /* gptiCurrent->ppi) */
+           {
+              _SEH2_TRY
+              {
+                 pti->pClientInfo->fsHooks = pti->fsHooks;
+                 pti->pClientInfo->phkCurrent = 0;
+              }
+              _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+              {
+                 Hit = TRUE;
+              }
+              _SEH2_END;
+              if (Hit)
+              {
+                 DPRINT1("Problem writing to Local ClientInfo!\n");
+              }
+           }
+           else
+           {
+              KeAttachProcess(&pti->ppi->peProcess->Pcb);
+              _SEH2_TRY
+              {
+                 pti->pClientInfo->fsHooks = pti->fsHooks;
+                 pti->pClientInfo->phkCurrent = 0;
+              }
+              _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+              {
+                 Hit = TRUE;
+              }
+              _SEH2_END;
+              KeDetachProcess();
+              if (Hit)
+              {
+                 DPRINT1("Problem writing to Remote ClientInfo!\n");
+              }
+           }
+        }
      }
-     if (NULL != Mod)
+     else
      {
-         Status = MmCopyFromCaller(&ModuleName, UnsafeModuleName, sizeof(UNICODE_STRING));
-         if (!NT_SUCCESS(Status))
-         {
-             UserDereferenceObject(Hook);
-             IntRemoveHook(Hook, WinStaObj, FALSE);
-             ObDereferenceObject(WinStaObj);
-             SetLastNtError(Status);
-             RETURN( NULL);
-         }
+        InsertHeadList(&pti->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)], &Hook->Chain);
+        Hook->ptiHooked = NULL;
+        //gptiCurrent->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId);
+        pti->pDeskInfo->fsHooks |= HOOKID_TO_FLAG(HookId);
+     }
  
-         Hook->ModuleName.Buffer = ExAllocatePoolWithTag(PagedPool,
+     RtlInitUnicodeString(&Hook->ModuleName, NULL);
+     if (Mod)
+     {
+        Status = MmCopyFromCaller(&ModuleName,
+                                   UnsafeModuleName,
+                                   sizeof(UNICODE_STRING));
+        if (!NT_SUCCESS(Status))
+        {
+           IntRemoveHook(Hook);
+           SetLastNtError(Status);
+           RETURN( NULL);
+        }
+        Hook->ModuleName.Buffer = ExAllocatePoolWithTag( PagedPool,
                                                          ModuleName.MaximumLength,
                                                          TAG_HOOK);
-         if (NULL == Hook->ModuleName.Buffer)
-         {
-             UserDereferenceObject(Hook);
-             IntRemoveHook(Hook, WinStaObj, FALSE);
-             ObDereferenceObject(WinStaObj);
-             SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
-             RETURN( NULL);
-         }
-         Hook->ModuleName.MaximumLength = ModuleName.MaximumLength;
-         Status = MmCopyFromCaller(Hook->ModuleName.Buffer,
+        if (NULL == Hook->ModuleName.Buffer)
+        {
+           IntRemoveHook(Hook);
+           SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+           RETURN( NULL);
+        }
+        Hook->ModuleName.MaximumLength = ModuleName.MaximumLength;
+        Status = MmCopyFromCaller( Hook->ModuleName.Buffer,
                                    ModuleName.Buffer,
                                    ModuleName.MaximumLength);
-         if (!NT_SUCCESS(Status))
-         {
-             ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
-             UserDereferenceObject(Hook);
-             IntRemoveHook(Hook, WinStaObj, FALSE);
-             ObDereferenceObject(WinStaObj);
-             SetLastNtError(Status);
-             RETURN( NULL);
-         }
-         Hook->ModuleName.Length = ModuleName.Length;
-         /* make proc relative to the module base */
-         Hook->Proc = (void *)((char *)HookProc - (char *)Mod);
+        if (!NT_SUCCESS(Status))
+        {
+           ExFreePoolWithTag(Hook->ModuleName.Buffer, TAG_HOOK);
+           Hook->ModuleName.Buffer = NULL;
+           IntRemoveHook(Hook);
+           SetLastNtError(Status);
+           RETURN( NULL);
+        }
+        Hook->ModuleName.Length = ModuleName.Length;
+        /* make proc relative to the module base */
+        Hook->offPfn = (ULONG_PTR)((char *)HookProc - (char *)Mod);
      }
      else
-         Hook->Proc = HookProc;
-     Hook->Ansi = Ansi;
-     Handle = UserHMGetHandle(Hook);
-     /* Clear the client threads next hook. */
-     ClientInfo->phkCurrent = 0;
-     UserDereferenceObject(Hook);
-     ObDereferenceObject(WinStaObj);
+        Hook->offPfn = 0;
  
+     DPRINT1("Installing: HookId %d Global %s\n", HookId, !ThreadId ? "TRUE" : "FALSE");
      RETURN( Handle);
  
  CLEANUP:
      END_CLEANUP;
  }
  
  BOOL
  APIENTRY
  NtUserUnhookWindowsHookEx(HHOOK Hook)
  {
-     PWINSTATION_OBJECT WinStaObj;
      PHOOK HookObj;
-     NTSTATUS Status;
      DECLARE_RETURN(BOOL);
  
      DPRINT("Enter NtUserUnhookWindowsHookEx\n");
      UserEnterExclusive();
  
-     Status = IntValidateWindowStationHandle(PsGetCurrentProcess()->Win32WindowStation,
-                                             KernelMode,
-                                             0,
-                                             &WinStaObj);
-     if (!NT_SUCCESS(Status))
-     {
-         SetLastNtError(Status);
-         RETURN( FALSE);
-     }
-     /*  Status = UserReferenceObjectByHandle(gHandleTable, Hook,
-                                              otHookProc, (PVOID *) &HookObj); */
      if (!(HookObj = IntGetHookObject(Hook)))
      {
          DPRINT1("Invalid handle passed to NtUserUnhookWindowsHookEx\n");
-         ObDereferenceObject(WinStaObj);
          /* SetLastNtError(Status); */
          RETURN( FALSE);
      }
  
      ASSERT(Hook == UserHMGetHandle(HookObj));
  
-     IntRemoveHook(HookObj, WinStaObj, FALSE);
+     IntRemoveHook(HookObj);
  
      UserDereferenceObject(HookObj);
-     ObDereferenceObject(WinStaObj);
  
      RETURN( TRUE);
  
@@@ -1347,7 -1347,7 +1347,7 @@@ IntKeyboardInput(KEYBDINPUT *ki
     KbdHookData.dwExtraInfo = ki->dwExtraInfo;
     if (co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData))
     {
-       DPRINT("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
+       DPRINT1("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
               Msg.message, vk_hook, Msg.lParam);
        if (Entered) UserLeave();
        return FALSE;
@@@ -163,10 -163,7 +163,7 @@@ static BOOL UserLoadKbdDll(WCHAR *wsKLI
        DPRINT("Loaded %wZ\n", &FullLayoutPath);
  
        RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" );
-       LdrGetProcedureAddress((*(PDRIVERS*)phModule)->BaseAddress,
-                              &kbdProcedureName,
-                              0,
-                              (PVOID*)&layerDescGetFn);
+       layerDescGetFn = EngFindImageProcAddress(*phModule, "KbdLayerDescriptor");
  
        if(layerDescGetFn)
        {
@@@ -368,9 -368,10 +368,10 @@@ IntDispatchMessage(PMSG pMsg
  {
    LARGE_INTEGER TickCount;
    LONG Time;
-   LRESULT retval;
+   LRESULT retval = 0;
    PMSGMEMORY MsgMemoryEntry;
    INT lParamBufferSize;
+   PTHREADINFO pti;
    LPARAM lParamPacked;
    PWND Window = NULL;
  
       if (!Window) return 0;
    }
  
+   pti = PsGetCurrentThreadWin32Thread();
    if (((pMsg->message == WM_SYSTIMER) ||
         (pMsg->message == WM_TIMER)) &&
        (pMsg->lParam) )
    {
       if (pMsg->message == WM_TIMER)
       {
-         if (ValidateTimerCallback(PsGetCurrentThreadWin32Thread(),pMsg->lParam))
+         ObReferenceObject(pti->pEThread);
+         if (ValidateTimerCallback(pti,pMsg->lParam))
          {
             KeQueryTickCount(&TickCount);
             Time = MsqCalculateMessageTime(&TickCount);
-            return co_IntCallWindowProc((WNDPROC)pMsg->lParam,
+            retval = co_IntCallWindowProc((WNDPROC)pMsg->lParam,
                                          TRUE,
                                          pMsg->hwnd,
                                          WM_TIMER,
                                          (LPARAM)Time,
                                          sizeof(LPARAM));
          }
-         return 0;        
+         ObDereferenceObject(pti->pEThread);
+         return retval;        
       }
       else
       {
       DPRINT1("Failed to pack message parameters\n");
       return 0;
    }
+   ObReferenceObject(pti->pEThread);
    retval = co_IntCallWindowProc( Window->lpfnWndProc,
                                  !Window->Unicode,
                                   pMsg->hwnd,
       co_UserGetUpdateRgn( Window, hrgn, TRUE );
       REGION_FreeRgnByHandle( hrgn );
    }
+   ObDereferenceObject(pti->pEThread);
    return retval;
  }
  
@@@ -625,7 -631,7 +631,7 @@@ co_IntTranslateMouseMessage
        }
     }
  
-    if ( gspv.bMouseClickLock && 
+    if ( gspv.bMouseClickLock &&
          ( (Msg->message == WM_LBUTTONUP) ||
            (Msg->message == WM_LBUTTONDOWN) ) )
     {
@@@ -784,6 -790,7 +790,7 @@@ BOOL ProcessMouseMessage(MSG* Msg, BOOL
                             HCBT_CLICKSKIPPED,
                             Msg->message,
                             (LPARAM)&MHook);
+         DPRINT1("MouseMessage WH_CBT Call Hook return!\n");
          return FALSE;
      }
  
@@@ -812,6 -819,7 +819,7 @@@ BOOL ProcessKeyboardMessage(MSG* Msg, B
                             HCBT_KEYSKIPPED,
                             LOWORD(Msg->wParam),
                             Msg->lParam );
+         DPRINT1("KeyboardMessage WH_CBT Call Hook return!\n");
          return FALSE;
      }
        return TRUE;
@@@ -859,98 -867,98 +867,98 @@@ co_IntPeekMessage( PUSER_MESSAGE Msg
  
     do
     {
-        KeQueryTickCount(&LargeTickCount);
-        ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
-        /* Dispatch sent messages here. */
-        while (co_MsqDispatchOneSentMessage(ThreadQueue))
-           ;
-        /* Now look for a quit message. */
-        if (ThreadQueue->QuitPosted)
-        {
-           /* According to the PSDK, WM_QUIT messages are always returned, regardless
-              of the filter specified */
-           Msg->Msg.hwnd = NULL;
-           Msg->Msg.message = WM_QUIT;
-           Msg->Msg.wParam = ThreadQueue->QuitExitCode;
-           Msg->Msg.lParam = 0;
-           if (RemoveMessages)
-           {
-              ThreadQueue->QuitPosted = FALSE;
-           }
+    KeQueryTickCount(&LargeTickCount);
+    ThreadQueue->LastMsgRead = LargeTickCount.u.LowPart;
+    /* Dispatch sent messages here. */
+    while (co_MsqDispatchOneSentMessage(ThreadQueue))
+       ;
+    /* Now look for a quit message. */
+    if (ThreadQueue->QuitPosted)
+    {
+       /* According to the PSDK, WM_QUIT messages are always returned, regardless
+          of the filter specified */
+       Msg->Msg.hwnd = NULL;
+       Msg->Msg.message = WM_QUIT;
+       Msg->Msg.wParam = ThreadQueue->QuitExitCode;
+       Msg->Msg.lParam = 0;
+       if (RemoveMessages)
+       {
+          ThreadQueue->QuitPosted = FALSE;
+       }
  
            return TRUE;
-        }
+    }
  
-        /* Now check for normal messages. */
+    /* Now check for normal messages. */
         if (co_MsqFindMessage( ThreadQueue,
-                               FALSE,
-                               RemoveMessages,
-                               Window,
-                               MsgFilterMin,
-                               MsgFilterMax,
+                                 FALSE,
+                                 RemoveMessages,
+                                 Window,
+                                 MsgFilterMin,
+                                 MsgFilterMax,
                                &Message ))
-        {
-           RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
-           if (RemoveMessages)
-           {
-              MsqDestroyMessage(Message);
-           }
+    {
+       RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
+       if (RemoveMessages)
+       {
+          MsqDestroyMessage(Message);
+       }
            break;
-        }
+    }
  
-        /* Check for hardware events. */
+    /* Check for hardware events. */
         if(co_MsqFindMessage( ThreadQueue,
-                              TRUE,
-                              RemoveMessages,
-                              Window,
-                              MsgFilterMin,
-                              MsgFilterMax,
+                                 TRUE,
+                                 RemoveMessages,
+                                 Window,
+                                 MsgFilterMin,
+                                 MsgFilterMax,
                               &Message ))
-        {
-           RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
-           if (RemoveMessages)
-           {
-              MsqDestroyMessage(Message);
-           }
+    {
+       RtlCopyMemory(Msg, Message, sizeof(USER_MESSAGE));
+       if (RemoveMessages)
+       {
+          MsqDestroyMessage(Message);
+       }
  
            if(!ProcessHardwareMessage(&Msg->Msg, RemoveMessages))
                continue;
  
            break;
-        }
+    }
  
-        /* Check for sent messages again. */
-        while (co_MsqDispatchOneSentMessage(ThreadQueue))
-           ;
+    /* Check for sent messages again. */
+    while (co_MsqDispatchOneSentMessage(ThreadQueue))
+       ;
  
-        /* Check for paint messages. */
+    /* Check for paint messages. */
         if( IntGetPaintMessage( Window,
-                                MsgFilterMin,
-                                MsgFilterMax,
-                                pti,
-                                &Msg->Msg,
-                                RemoveMessages))
-        {
+                             MsgFilterMin,
+                             MsgFilterMax,
+                             pti,
+                             &Msg->Msg,
+                             RemoveMessages))
+    {
            break;
-        }
+    }
  
-        if (PostTimerMessages(Window))
-        {
+    if (PostTimerMessages(Window))
+    {
            continue;
-        }
+             }
  
-        return FALSE;
-    }
+              return FALSE;
+           }
     while (TRUE);
  
-    // The WH_GETMESSAGE hook enables an application to monitor messages about to
-    // be returned by the GetMessage or PeekMessage function.
+       // The WH_GETMESSAGE hook enables an application to monitor messages about to
+       // be returned by the GetMessage or PeekMessage function.
  
-    co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)&Msg->Msg);
-    return TRUE;
+       co_HOOK_CallHooks( WH_GETMESSAGE, HC_ACTION, RemoveMsg & PM_REMOVE, (LPARAM)&Msg->Msg);
+       return TRUE;
  }
  
  static NTSTATUS FASTCALL
@@@ -1232,7 -1240,7 +1240,7 @@@ UserPostMessage( HWND Wnd
        return FALSE;
     }
  
-    if (!Wnd) 
+    if (!Wnd)
        return UserPostThreadMessage( PtrToInt(PsGetCurrentThreadId()),
                                      Msg,
                                      wParam,
  
        if (List != NULL)
        {
+          UserPostMessage(DesktopWindow->head.h, Msg, wParam, lParam);
           for (i = 0; List[i]; i++)
              UserPostMessage(List[i], Msg, wParam, lParam);
           ExFreePool(List);
@@@ -1322,13 -1331,13 +1331,13 @@@ co_IntSendMessageTimeoutSingle( HWND hW
                                  UINT uTimeout,
                                  ULONG_PTR *uResult )
  {
-    ULONG_PTR Result;
     NTSTATUS Status;
     PWND Window = NULL;
     PMSGMEMORY MsgMemoryEntry;
     INT lParamBufferSize;
     LPARAM lParamPacked;
     PTHREADINFO Win32Thread;
+    ULONG_PTR Result = 0;
     DECLARE_RETURN(LRESULT);
     USER_REFERENCE_ENTRY Ref;
  
            RETURN( FALSE);
        }
  
+       ObReferenceObject(Win32Thread->pEThread);
        Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
                                                 !Window->Unicode,
                                                  hWnd,
           *uResult = Result;
        }
  
+       ObDereferenceObject(Win32Thread->pEThread);
        IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
  
        if (! NT_SUCCESS(UnpackParam(lParamPacked, Msg, wParam, lParam, FALSE)))
@@@ -1474,6 -1486,9 +1486,9 @@@ co_IntSendMessageTimeout( HWND hWnd
        return 0;
     }
  
+    /* Send message to the desktop window too! */
+    co_IntSendMessageTimeoutSingle(DesktopWindow->head.h, Msg, wParam, lParam, uFlags, uTimeout, uResult);
     Children = IntWinListChildren(DesktopWindow);
     if (NULL == Children)
     {
@@@ -1575,7 -1590,7 +1590,7 @@@ co_IntSendMessageWithCallBack( HWND hWn
     /* If this is not a callback and it can be sent now, then send it. */
     if ((Window->head.pti->MessageQueue == Win32Thread->MessageQueue) && (CompletionCallback == NULL))
     {
+       ObReferenceObject(Win32Thread->pEThread);
        Result = (ULONG_PTR)co_IntCallWindowProc( Window->lpfnWndProc,
                                                 !Window->Unicode,
                                                  hWnd,
        {
           *uResult = Result;
        }
+       ObDereferenceObject(Win32Thread->pEThread);
     }
  
     IntCallWndProcRet( Window, hWnd, Msg, wParam, lParam, (LRESULT *)uResult);
@@@ -1818,6 -1834,7 +1834,7 @@@ UserSendNotifyMessage( HWND hWnd
  
        if (List != NULL)
        {
+          UserSendNotifyMessage(DesktopWindow->head.h, Msg, wParam, lParam);
           for (i = 0; List[i]; i++)
           {
              UserSendNotifyMessage(List[i], Msg, wParam, lParam);
@@@ -2410,7 -2427,7 +2427,7 @@@ NtUserDispatchMessage(PMSG UnsafeMsgInf
    BOOL Hit = FALSE;
    MSG SafeMsg;
  
-   UserEnterExclusive();  
+   UserEnterExclusive();
    _SEH2_TRY
    {
      ProbeForRead(UnsafeMsgInfo, sizeof(MSG), 1);
      Hit = TRUE;
    }
    _SEH2_END;
-   
    if (!Hit) Res = IntDispatchMessage(&SafeMsg);
  
    UserLeave();
@@@ -2553,12 -2570,13 +2570,13 @@@ NtUserMessageCall
                                              2000,
                                              &RetVal);
                 }
+                Ret = RetVal;
              }
              else if (parm.flags & BSF_POSTMESSAGE)
              {
                 Ret = UserPostMessage(HWND_BROADCAST, Msg, wParam, lParam);
              }
-             else if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
+             else //Everything else,,,, if ( parm.flags & BSF_SENDNOTIFYMESSAGE)
              {
                 Ret = UserSendNotifyMessage(HWND_BROADCAST, Msg, wParam, lParam);
              }
        case FNID_CALLWNDPROC:
        case FNID_CALLWNDPROCRET:
        {
-          PCLIENTINFO ClientInfo = GetWin32ClientInfo();
-          PHOOK NextObj, Hook = ClientInfo->phkCurrent;
+          PTHREADINFO pti;
+          PCLIENTINFO ClientInfo;
+          PHOOK NextObj, Hook;
  
-          if (!ClientInfo || !Hook) break;
+          pti = GetW32ThreadInfo();
  
-          UserReferenceObject(Hook);
+          Hook = pti->sphkCurrent;
  
-          if (Hook->Thread && (Hook->Thread != PsGetCurrentThread()))
+          if (!Hook) break;
+          NextObj = Hook->phkNext;
+          ClientInfo = pti->pClientInfo;
+          _SEH2_TRY
           {
-             UserDereferenceObject(Hook);
-             break;
+             ClientInfo->phkCurrent = NextObj;
           }
+          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+          {
+             ClientInfo = NULL;
+          }
+          _SEH2_END;
+          if (!ClientInfo || !NextObj) break;
  
-          NextObj = IntGetNextHook(Hook);
-          ClientInfo->phkCurrent = NextObj;
+          NextObj->phkNext = IntGetNextHook(NextObj);
  
           if ( Hook->HookId == WH_CALLWNDPROC)
           {
                                            Hook->Ansi,
                                            &Hook->ModuleName);
           }
-          UserDereferenceObject(Hook);
-          lResult = (LRESULT) NextObj;
        }
        break;
     }
              {
                  BadChk = TRUE;
              }
-             _SEH2_END;      
+             _SEH2_END;
           }
           break;
        default:
-          break;   
+          break;
     }
  
     UserLeave();
@@@ -24,9 -24,19 +24,19 @@@ FASTCAL
  InitMetrics(VOID)
  {
      INT *piSysMet;
-     ULONG Width = pPrimarySurface->gdiinfo.ulHorzRes;
-     ULONG Height = pPrimarySurface->gdiinfo.ulVertRes;
+     ULONG Width, Height;
+     /* FIXME: HACK, due to missing PDEV on first init */
+     if (!pPrimarySurface)
+     {
+         Width = 640;
+         Height = 480;
+     }
+     else
+     {
+         Width = pPrimarySurface->gdiinfo.ulHorzRes;
+         Height = pPrimarySurface->gdiinfo.ulVertRes;
+     }
  
      piSysMet = gpsi->aiSysMet;
  
@@@ -798,7 -798,7 +798,7 @@@ co_MsqPostKeyboardMessage(UINT uMsg, WP
     KbdHookData.dwExtraInfo = 0;
     if (co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, Msg.message, (LPARAM) &KbdHookData))
     {
-       DPRINT("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
+       DPRINT1("Kbd msg %d wParam %d lParam 0x%08x dropped by WH_KEYBOARD_LL hook\n",
               Msg.message, Msg.wParam, Msg.lParam);
        if (Entered) UserLeave();
        return;
@@@ -948,26 -948,25 +948,25 @@@ co_MsqDispatchOneSentMessage(PUSER_MESS
                    &Message->ListEntry);
  
     if (Message->HookMessage == MSQ_ISHOOK)
-    {
-       Result = co_HOOK_CallHooks(Message->Msg.message,
-                                  (INT)(INT_PTR)Message->Msg.hwnd,
-                                  Message->Msg.wParam,
-                                  Message->Msg.lParam);
+    {  // Direct Hook Call processor
+       Result = co_CallHook( Message->Msg.message,     // HookId
+                            (INT)(INT_PTR)Message->Msg.hwnd, // Code
+                             Message->Msg.wParam,
+                             Message->Msg.lParam);
     }
     else if (Message->HookMessage == MSQ_ISEVENT)
-    {
+    {  // Direct Event Call processor
        Result = co_EVENT_CallEvents( Message->Msg.message,
                                      Message->Msg.hwnd,
                                      Message->Msg.wParam,
                                      Message->Msg.lParam);
     }
     else
-    {
-       /* Call the window procedure. */
-       Result = co_IntSendMessage(Message->Msg.hwnd,
-                                  Message->Msg.message,
-                                  Message->Msg.wParam,
-                                  Message->Msg.lParam);
+    {  /* Call the window procedure. */
+       Result = co_IntSendMessage( Message->Msg.hwnd,
+                                   Message->Msg.message,
+                                   Message->Msg.wParam,
+                                   Message->Msg.lParam);
     }
  
     /* remove the message from the local dispatching list, because it doesn't need
@@@ -1133,10 -1132,10 +1132,10 @@@ co_MsqSendMessage(PUSER_MESSAGE_QUEUE M
     PUSER_SENT_MESSAGE Message;
     KEVENT CompletionEvent;
     NTSTATUS WaitStatus;
-    LRESULT Result;
     PUSER_MESSAGE_QUEUE ThreadQueue;
     LARGE_INTEGER Timeout;
     PLIST_ENTRY Entry;
+    LRESULT Result = 0;   //// Result could be trashed. ////
  
     if(!(Message = ExAllocatePoolWithTag(PagedPool, sizeof(USER_SENT_MESSAGE), TAG_USRMSG)))
     {
  
     /* FIXME - increase reference counter of sender's message queue here */
  
-    Result = 0;
     Message->Msg.hwnd = Wnd;
     Message->Msg.message = Msg;
     Message->Msg.wParam = wParam;
     Message->SenderQueue = ThreadQueue;
     IntReferenceMessageQueue(ThreadQueue);
     Message->CompletionCallback = NULL;
+    Message->CompletionCallbackContext = 0;
     Message->HookMessage = HookMessage;
     Message->HasPackedLParam = FALSE;
  
@@@ -1632,18 -1631,6 +1631,6 @@@ MsqDestroyMessageQueue(PUSER_MESSAGE_QU
     IntDereferenceMessageQueue(MessageQueue);
  }
  
- PHOOKTABLE FASTCALL
- MsqGetHooks(PUSER_MESSAGE_QUEUE Queue)
- {
-    return Queue->Hooks;
- }
- VOID FASTCALL
- MsqSetHooks(PUSER_MESSAGE_QUEUE Queue, PHOOKTABLE Hooks)
- {
-    Queue->Hooks = Hooks;
- }
  LPARAM FASTCALL
  MsqSetMessageExtraInfo(LPARAM lParam)
  {
@@@ -199,39 -199,6 +199,6 @@@ NtUserDrawAnimatedRects
     return 0;
  }
  
- BOOL
- APIENTRY
- NtUserEnumDisplayDevices (
-    PUNICODE_STRING lpDevice, /* device name */
-    DWORD iDevNum, /* display device */
-    PDISPLAY_DEVICEW lpDisplayDevice, /* device information */
-    DWORD dwFlags ) /* reserved */
- {
-    DPRINT1("NtUserEnumDisplayDevices() is UNIMPLEMENTED!\n");
-    if (lpDevice->Length == 0 && iDevNum > 0)
-    {
-       /* Only one display device present */
-       return FALSE;
-    }
-    else if (lpDevice->Length != 0)
-    {
-        /* Can't enumerate monitors :( */
-        return FALSE;
-    }
-    if (lpDisplayDevice->cb < sizeof(DISPLAY_DEVICE))
-       return FALSE;
-    wcscpy(lpDisplayDevice->DeviceName, L"\\\\.\\DISPLAY1");
-    wcscpy(lpDisplayDevice->DeviceString, L"<Unknown>");
-    lpDisplayDevice->StateFlags = DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
-                                  | DISPLAY_DEVICE_MODESPRUNED
-                                  | DISPLAY_DEVICE_PRIMARY_DEVICE
-                                  | DISPLAY_DEVICE_VGA_COMPATIBLE;
-    lpDisplayDevice->DeviceID[0] = L'0';
-    lpDisplayDevice->DeviceKey[0] = L'0';
-    return TRUE;
- }
  DWORD
  APIENTRY
  NtUserEvent(
@@@ -73,16 -73,6 +73,6 @@@ NTSTATUS FASTCALL InitUserImpl(VOID
        return Status;
     }
  
-    if (!gpsi)
-    {
-       gpsi = UserHeapAlloc(sizeof(SERVERINFO));
-       if (gpsi)
-       {
-          RtlZeroMemory(gpsi, sizeof(SERVERINFO));
-          DPRINT("Global Server Data -> %x\n", gpsi);
-       }
-    }
     InitUserAtoms();
  
     InitSysParams();
@@@ -90,6 -80,8 +80,8 @@@
     return STATUS_SUCCESS;
  }
  
+ BOOL
+ InitVideo(ULONG);
  
  NTSTATUS
  NTAPI
@@@ -100,6 -92,7 +92,7 @@@ UserInitialize
  // Set W32PF_Flags |= (W32PF_READSCREENACCESSGRANTED | W32PF_IOWINSTA)
  // Create Object Directory,,, Looks like create workstation. "\\Windows\\WindowStations"
  // Create Event for Diconnect Desktop.
+     InitVideo(0);
  // Initialize Video.
  // {
  //     DrvInitConsole.
@@@ -139,8 -132,8 +132,8 @@@ NtUserInitialize
  {
      NTSTATUS Status;
  
-     DPRINT("Enter NtUserInitialize(%lx, %p, %p)\n",
-            dwWinVersion, hPowerRequestEvent, hMediaRequestEvent);
+     DPRINT1("Enter NtUserInitialize(%lx, %p, %p)\n",
+             dwWinVersion, hPowerRequestEvent, hMediaRequestEvent);
  
      /* Check the Windows version */
      if (dwWinVersion != 0)
@@@ -330,8 -330,8 +330,8 @@@ UserCreateObject( PUSER_HANDLE_TABLE ht
     {
        case otWindow:
  //      case otMenu:
//      case otHook:
//      case otCallProc:
+       case otHook:
+       case otCallProc:
        case otInputContext:
           Object = DesktopHeapAlloc(rpdesk, size);
           dt = TRUE;
@@@ -420,8 -420,8 +420,8 @@@ UserDereferenceObject(PVOID object
       {
          case otWindow:
  //        case otMenu:
//        case otHook:
//        case otCallProc:
+         case otHook:
+         case otCallProc:
          case otInputContext:
             return DesktopHeapFree(((PTHRDESKHEAD)object)->rpdesk, object);
  
@@@ -228,21 -228,6 +228,6 @@@ NtUserCallOneParam
              RETURN (ret);
           }
  
-       case ONEPARAM_ROUTINE_ISWINDOWINDESTROY:
-          {
-             PWND Window;
-             DWORD_PTR Result;
-             if(!(Window = UserGetWindowObject((HWND)Param)))
-             {
-                RETURN( FALSE);
-             }
-             Result = (DWORD_PTR)IntIsWindowInDestroy(Window);
-             RETURN( Result);
-          }
        case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING:
           {
              BOOL Enable;
@@@ -473,6 -458,8 +458,8 @@@ NtUserCallTwoParam
        case TWOPARAM_ROUTINE_SETCURSORPOS:
           RETURN( (DWORD_PTR)UserSetCursorPos((int)Param1, (int)Param2, FALSE));
  
+       case TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK:
+          RETURN( IntUnhookWindowsHook((int)Param1, (HOOKPROC)Param2));
     }
     DPRINT1("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n",
             Routine, Param1, Param2);
@@@ -713,6 -700,21 +700,21 @@@ NtUserCallHwndParam
           UserLeave();
           return 0;
        }
+       case HWNDPARAM_ROUTINE_ROS_NOTIFYWINEVENT:
+       {
+          PWND pWnd;
+          PNOTIFYEVENT pne;
+          UserEnterExclusive();
+          pne = (PNOTIFYEVENT)Param;
+          if (hWnd)
+             pWnd = UserGetWindowObject(hWnd);
+          else
+             pWnd = NULL;
+          IntNotifyWinEvent(pne->event, pWnd, pne->idObject, pne->idChild, pne->flags);
+          UserLeave();
+          return 0;
+       }
     }
  
     UNIMPLEMENTED;
@@@ -41,6 -41,9 +41,9 @@@ DceCreateDisplayDC(VOID
    UNICODE_STRING DriverName;
    RtlInitUnicodeString(&DriverName, L"DISPLAY");
    hDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
+   co_IntGraphicsCheck(TRUE);
  //
  // If NULL, first time through! Build the default window dc!
  //
@@@ -163,7 -163,6 +163,6 @@@ IntIsWindow(HWND hWnd
  }
  
  
  PWND FASTCALL
  IntGetParent(PWND Wnd)
  {
     return NULL;
  }
  
  /*
   * IntWinListChildren
   *
@@@ -348,7 -346,7 +346,7 @@@ static LRESULT co_UserFreeWindow(PWND W
     Window->state2 |= WNDS2_INDESTROY;
     Window->style &= ~WS_VISIBLE;
  
-    IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, 0);
+    IntNotifyWinEvent(EVENT_OBJECT_DESTROY, Window, OBJID_WINDOW, CHILDID_SELF, 0);
  
     /* remove the window already at this point from the thread window list so we
        don't get into trouble when destroying the thread windows while we're still
        if(BelongsToThreadData)
           co_IntSendMessage(Window->head.h, WM_NCDESTROY, 0, 0);
     }
     DestroyTimersForWindow(ThreadData, Window);
     HOOK_DestroyThreadHooks(ThreadData->pEThread); // This is needed here too!
  
     /* flush the message queue */
@@@ -1168,6 -1168,7 +1168,7 @@@ co_IntSetParent(PWND Wnd, PWND WndNewPa
  
     }
  
+    IntNotifyWinEvent(EVENT_OBJECT_PARENTCHANGE, Wnd ,OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
     /*
      * SetParent additionally needs to make hwnd the top window
      * in the z-order and send the expected WM_WINDOWPOSCHANGING and
@@@ -1227,13 -1228,6 +1228,6 @@@ IntUnlinkWindow(PWND Wnd
     Wnd->spwndPrev = Wnd->spwndNext = NULL;
  }
  
- BOOL FASTCALL
- IntIsWindowInDestroy(PWND Window)
- {
-    return ((Window->state2 & WNDS2_INDESTROY) == WNDS2_INDESTROY);
- }
  BOOL
  FASTCALL
  IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl)
@@@ -1635,6 -1629,33 +1629,33 @@@ PWND FASTCALL IntCreateWindow(CREATESTR
  
     pti = PsGetCurrentThreadWin32Thread();
  
+    if (!(Cs->dwExStyle & WS_EX_LAYOUTRTL))
+    {
+       if (ParentWindow)
+       {
+          if ( (Cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD &&
+               ParentWindow->ExStyle & WS_EX_LAYOUTRTL &&
+              !(ParentWindow->ExStyle & WS_EX_NOINHERITLAYOUT) )
+             Cs->dwExStyle |= WS_EX_LAYOUTRTL;
+       }
+       else
+       {/* 
+         Note from MSDN http://msdn.microsoft.com/en-us/library/aa913269.aspx :
+         Dialog boxes and message boxes do not inherit layout, so you must
+         set the layout explicitly.
+        */
+          if ( Class && Class->fnid != FNID_DIALOG)
+          {
+             PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
+             if (ppi->dwLayout & LAYOUT_RTL)
+             {
+                Cs->dwExStyle |= WS_EX_LAYOUTRTL;
+             }
+          }
+       }      
+    }
     /* Automatically add WS_EX_WINDOWEDGE */
     if ((Cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
           ((!(Cs->dwExStyle & WS_EX_STATICEDGE)) &&
@@@ -1877,17 -1898,19 +1898,19 @@@ co_UserCreateWindowEx(CREATESTRUCTW* Cs
                       PLARGE_STRING WindowName)
  {
     PWND Window = NULL, ParentWindow = NULL, OwnerWindow;
-    HWND hWnd, hWndParent, hWndOwner;
+    HWND hWnd, hWndParent, hWndOwner, hwndInsertAfter;
     DWORD dwStyle;
     PWINSTATION_OBJECT WinSta;
     PCLS Class = NULL;
     SIZE Size;
     POINT MaxPos;
-    CBT_CREATEWNDW CbtCreate;
+    CBT_CREATEWNDW * pCbtCreate;
     LRESULT Result;
     USER_REFERENCE_ENTRY ParentRef, Ref;
     PTHREADINFO pti;
+    ANSI_STRING asClassName;
     DWORD dwShowMode = SW_SHOW;
+    CREATESTRUCTW *pCsw;
     DECLARE_RETURN(PWND);
  
     /* Get the current window station and reference it */
     WinSta = pti->rpdesk->rpwinstaParent;
     ObReferenceObjectByPointer(WinSta, KernelMode, ExWindowStationObjectType, 0);
  
+    pCsw = NULL;
+    pCbtCreate = NULL;
+    RtlInitAnsiString(&asClassName, NULL);
     /* Get the class and reference it*/
     Class = IntGetAndReferenceClass(ClassName, Cs->hInstance);
     if(!Class)
         RETURN(0);
     }
  
-    hWnd = Window->head.h;
+    hWnd = UserHMGetHandle(Window);
  
     UserRefObjectCo(Window, &Ref);
     ObDereferenceObject(WinSta);
  
-    /* Call the WH_CBT hook */
-    dwStyle = Cs->style;
-    Cs->style = Window->style; /* HCBT_CREATEWND needs the real window style */
-    CbtCreate.lpcs = Cs;
-    CbtCreate.hwndInsertAfter = HWND_TOP;
+    //// Call the WH_CBT hook ////
+    // Allocate the calling structures Justin Case this goes Global.
+    pCsw = ExAllocatePoolWithTag(NonPagedPool, sizeof(CREATESTRUCTW), TAG_HOOK);
+    pCbtCreate = ExAllocatePoolWithTag(NonPagedPool, sizeof(CBT_CREATEWNDW), TAG_HOOK);
+    /* Fill the new CREATESTRUCTW */
+    pCsw->lpCreateParams = Cs->lpCreateParams;
+    pCsw->hInstance = Cs->hInstance;
+    pCsw->hMenu = Cs->hMenu;
+    pCsw->hwndParent = Cs->hwndParent;
+    pCsw->cx = Cs->cx;
+    pCsw->cy = Cs->cy;
+    pCsw->x = Cs->x;
+    pCsw->y = Cs->y;
+    pCsw->dwExStyle = Cs->dwExStyle;
+    dwStyle = Cs->style;       // Save it anyway.
+    pCsw->style = Window->style; /* HCBT_CREATEWND needs the real window style */
+    pCsw->lpszName  = (LPCWSTR) WindowName->Buffer;
+    pCsw->lpszClass = (LPCWSTR) ClassName->Buffer;
+    if (Window->state & WNDS_ANSICREATOR)
+    {
+       if (!IS_ATOM(ClassName->Buffer))
+       {
+          RtlUnicodeStringToAnsiString(&asClassName, ClassName, TRUE);
+          pCsw->lpszClass = (LPCWSTR) asClassName.Buffer;
+       }
+    }
+    pCbtCreate->lpcs = pCsw;
+    pCbtCreate->hwndInsertAfter = HWND_TOP;
  
-    if (co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) &CbtCreate))
+    Result = co_HOOK_CallHooks(WH_CBT, HCBT_CREATEWND, (WPARAM) hWnd, (LPARAM) pCbtCreate);
+    if (Result != 0)
     {
-       DPRINT1("HCBT_CREATEWND hook failed!\n");
+       DPRINT1("WH_CBT HCBT_CREATEWND hook failed! 0x%x\n", Result);
        RETURN( (PWND) NULL);
     }
+    // Write back changes.
+    Cs->cx = pCsw->cx;
+    Cs->cy = pCsw->cy;
+    Cs->x = pCsw->x;
+    Cs->y = pCsw->y;
+    hwndInsertAfter = pCbtCreate->hwndInsertAfter;
  
     Cs->style = dwStyle; /* NCCREATE and WM_NCCALCSIZE need the original values*/
  
     }
     
     /* Send the NCCREATE message */
-    Result = co_IntSendMessage(Window->head.h, WM_NCCREATE, 0, (LPARAM) Cs);
+    Result = co_IntSendMessage(UserHMGetHandle(Window), WM_NCCREATE, 0, (LPARAM) Cs);
     if (!Result)
     {
        DPRINT1("co_UserCreateWindowEx(): NCCREATE message failed\n");
  
  
     /* Send the WM_CREATE message. */
-    Result = co_IntSendMessage(Window->head.h, WM_CREATE, 0, (LPARAM) Cs);
+    Result = co_IntSendMessage(UserHMGetHandle(Window), WM_CREATE, 0, (LPARAM) Cs);
     if (Result == (LRESULT)-1)
     {
        DPRINT1("co_UserCreateWindowEx(): WM_CREATE message failed\n");
     }
  
     /* Send the EVENT_OBJECT_CREATE event*/
-    IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, 0);
+    IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_WINDOW, CHILDID_SELF, 0);
  
     /* By setting the flag below it can be examined to determine if the window
        was created successfully and a valid pwnd was passed back to caller since
  
        if (Window->ExStyle & WS_EX_MDICHILD)
        {
-         co_IntSendMessage(ParentWindow->head.h, WM_MDIREFRESHMENU, 0, 0);
+         co_IntSendMessage(UserHMGetHandle(ParentWindow), WM_MDIREFRESHMENU, 0, 0);
          /* ShowWindow won't activate child windows */
          co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
        }
@@@ -2121,6 -2183,10 +2183,10 @@@ CLEANUP
             IntDereferenceClass(Class, pti->pDeskInfo, pti->ppi);
     }
  
+    if (pCsw) ExFreePoolWithTag(pCsw, TAG_HOOK);
+    if (pCbtCreate) ExFreePoolWithTag(pCbtCreate, TAG_HOOK);
+    RtlFreeAnsiString(&asClassName);
     if (Window)
     {
        UserDerefObjectCo(Window);
@@@ -2280,7 -2346,7 +2346,7 @@@ NtUserCreateWindowEx
      /* Call the internal function */
      pwnd = co_UserCreateWindowEx(&Cs, &ustrClassName, plstrWindowName);
  
-       if(!pwnd)
+     if(!pwnd)
      {
          DPRINT1("co_UserCreateWindowEx failed!\n");
      }
@@@ -2343,7 -2409,11 +2409,11 @@@ BOOLEAN FASTCALL co_UserDestroyWindow(P
     /* If window was created successfully and it is hooked */
     if ((Window->state2 & WNDS2_WMCREATEMSGPROCESSED))
     {
-       if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hWnd, 0)) return FALSE;
+       if (co_HOOK_CallHooks(WH_CBT, HCBT_DESTROYWND, (WPARAM) hWnd, 0))
+       {
+          DPRINT1("Destroy Window WH_CBT Call Hook return!\n");
+          return FALSE;
+       }
     }
  
     /* Inform the parent */
@@@ -299,8 -299,10 +299,10 @@@ co_WinPosMinMaximize(PWND Wnd, UINT Sho
     WinPosInitInternalPos(Wnd, &Size, &Wnd->rcWindow);
  
     if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag))
+    {
+       DPRINT1("WinPosMinMaximize WH_CBT Call Hook return!\n");
        return SWP_NOSIZE | SWP_NOMOVE;
+    }
        if (Wnd->style & WS_MINIMIZE)
        {
           if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0))
                 }
              }
        }
     return(SwpFlags);
  }
  
@@@ -1358,6 -1359,14 +1359,14 @@@ co_WinPosSetWindowPos
        co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
     }
  
+    if ( WinPos.flags & SWP_FRAMECHANGED  || WinPos.flags & SWP_STATECHANGED ||
+       !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) )
+    {
+       PWND pWnd = UserGetWindowObject(WinPos.hwnd);
+       if (pWnd)
+          IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
+    }
     return TRUE;
  }
  
@@@ -31,7 -31,7 +31,7 @@@ BOOL FASTCALL IntDrawArc( PDC dc, INT X
  static
  BOOL
  FASTCALL
- IntArc( DC *dc, 
+ IntArc( DC *dc,
          int  Left,
          int  Top,
          int  Right,
@@@ -91,7 -91,7 +91,7 @@@
      }
  
      if (!PenWidth) PenWidth = 1;
-     pbrushPen->ptPenWidth.x = PenWidth;  
+     pbrushPen->ptPenWidth.x = PenWidth;
  
      RectBounds.left   = Left;
      RectBounds.right  = Right;
  
      IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
      IntLPtoDP(dc, (LPPOINT)&RectSEpts, 2);
-     
      RectBounds.left   += dc->ptlDCOrig.x;
      RectBounds.right  += dc->ptlDCOrig.x;
      RectBounds.top    += dc->ptlDCOrig.y;
      }
      if (arctype == GdiTypeChord)
          PUTLINE(EfCx + CenterX, EfCy + CenterY, SfCx + CenterX, SfCy + CenterY, dc->eboLine);
-            
      pbrushPen->ptPenWidth.x = PenOrigWidth;
      PEN_UnlockPen(pbrushPen);
      DPRINT("IntArc Exit.\n");
@@@ -219,12 -219,6 +219,6 @@@ IntGdiArcInternal
  
    pdcattr = dc->pdcattr;
  
-   if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
-     DC_vUpdateFillBrush(dc);
-   if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
-     DC_vUpdateLineBrush(dc);
    if (arctype == GdiTypeArcTo)
    {
      if (dc->dclevel.flPath & DCPATH_CLOCKWISE)
@@@ -329,7 -323,14 +323,14 @@@ NtGdiAngleArc
    }
    worker.l  = dwStartAngle;
    worker1.l = dwSweepAngle;
+   DC_vPrepareDCsForBlit(pDC, pDC->rosdc.CombinedClip->rclBounds,
+                            NULL, pDC->rosdc.CombinedClip->rclBounds);
+   if (pDC->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+     DC_vUpdateFillBrush(pDC);
+   if (pDC->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+     DC_vUpdateLineBrush(pDC);
    Ret = IntGdiAngleArc( pDC, x, y, dwRadius, worker.f, worker1.f);
+   DC_vFinishBlit(pDC, NULL);
    DC_UnlockDc( pDC );
    return Ret;
  }
@@@ -364,6 -365,15 +365,15 @@@ NtGdiArcInternal
      return TRUE;
    }
  
+   DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+                             NULL, dc->rosdc.CombinedClip->rclBounds);
+   if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+     DC_vUpdateFillBrush(dc);
+   if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+     DC_vUpdateLineBrush(dc);
    Ret = IntGdiArcInternal(
                    arctype,
                    dc,
                    XEndArc,
                    YEndArc);
  
+   DC_vFinishBlit(dc, NULL);
    DC_UnlockDc( dc );
    return Ret;
  }
@@@ -42,6 -42,8 +42,8 @@@ NtGdiAlphaBlend
  {
      PDC DCDest;
      PDC DCSrc;
+     HDC ahDC[2];
+     PGDIOBJ apObj[2];
      SURFACE *BitmapDest, *BitmapSrc;
      RECTL DestRect, SourceRect;
      BOOL bResult;
          return FALSE;
      }
  
-     DCDest = DC_LockDc(hDCDest);
-     if (NULL == DCDest)
+     DPRINT("Locking DCs\n");
+     ahDC[0] = hDCDest;
+     ahDC[1] = hDCSrc ;
+     GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
+     DCDest = apObj[0];
+     DCSrc = apObj[1];
+     if ((NULL == DCDest) || (NULL == DCSrc))
      {
-         DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCDest);
+         DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hDCDest, hDCSrc);
          SetLastWin32Error(ERROR_INVALID_HANDLE);
+         if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+         if(DCDest) GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
          return FALSE;
      }
  
-     if (DCDest->dctype == DC_TYPE_INFO)
+     if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
      {
-         DC_UnlockDc(DCDest);
+         GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+         GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
          /* Yes, Windows really returns TRUE in this case */
          return TRUE;
      }
  
-     if (hDCSrc != hDCDest)
-     {
-         DCSrc = DC_LockDc(hDCSrc);
-         if (NULL == DCSrc)
-         {
-             DC_UnlockDc(DCDest);
-             DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiAlphaBlend\n", hDCSrc);
-             SetLastWin32Error(ERROR_INVALID_HANDLE);
-             return FALSE;
-         }
-         if (DCSrc->dctype == DC_TYPE_INFO)
-         {
-             DC_UnlockDc(DCSrc);
-             DC_UnlockDc(DCDest);
-             /* Yes, Windows really returns TRUE in this case */
-             return TRUE;
-         }
-     }
-     else
-     {
-         DCSrc = DCDest;
-     }
      DestRect.left   = XOriginDest;
      DestRect.top    = YOriginDest;
      DestRect.right  = XOriginDest + WidthDest;
          !SourceRect.right ||
          !SourceRect.bottom)
      {
-         if (hDCSrc != hDCDest)
-             DC_UnlockDc(DCSrc);
-         DC_UnlockDc(DCDest);
+         GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+         GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
          return TRUE;
      }
  
+     /* Prepare DCs for blit */
+     DPRINT("Preparing DCs for blit\n");
+     DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
      /* Determine surfaces to be used in the bitblt */
      BitmapDest = DCDest->dclevel.pSurface;
      if (!BitmapDest)
      {
-         if (hDCSrc != hDCDest)
-             DC_UnlockDc(DCSrc);
-         DC_UnlockDc(DCDest);
-         return FALSE;
+         bResult = FALSE ;
+         goto leave ;
      }
  
      BitmapSrc = DCSrc->dclevel.pSurface;
      if (!BitmapSrc)
      {
-         if (hDCSrc != hDCDest)
-             DC_UnlockDc(DCSrc);
-         DC_UnlockDc(DCDest);
-         return FALSE;
+         bResult = FALSE;
+         goto leave;
      }
  
      /* Create the XLATEOBJ. */
      EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
  
      /* Perform the alpha blend operation */
+     DPRINT("Performing the alpha Blend\n");
      bResult = IntEngAlphaBlend(&BitmapDest->SurfObj,
                                 &BitmapSrc->SurfObj,
                                 DCDest->rosdc.CombinedClip,
                                 &BlendObj);
  
      EXLATEOBJ_vCleanup(&exlo);
-     DC_UnlockDc(DCDest);
-     if (hDCSrc != hDCDest)
-         DC_UnlockDc(DCSrc);
+ leave :
+     DPRINT("Finishing blit\n");
+     DC_vFinishBlit(DCDest, DCSrc);
+     GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+     GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
  
      return bResult;
  }
@@@ -182,59 -171,64 +171,64 @@@ NtGdiBitBlt
  {
      PDC DCDest;
      PDC DCSrc = NULL;
+     HDC ahDC[2];
+     PGDIOBJ apObj[2];
      PDC_ATTR pdcattr = NULL;
      SURFACE *BitmapDest, *BitmapSrc = NULL;
-     RECTL DestRect;
+     RECTL DestRect, SourceRect;
      POINTL SourcePoint;
      BOOL Status = FALSE;
      EXLATEOBJ exlo;
      XLATEOBJ *XlateObj = NULL;
      BOOL UsesSource = ROP3_USES_SOURCE(ROP);
  
-     DCDest = DC_LockDc(hDCDest);
+     DPRINT("Locking DCs\n");
+     ahDC[0] = hDCDest;
+     ahDC[1] = hDCSrc ;
+     GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
+     DCDest = apObj[0];
+     DCSrc = apObj[1];
      if (NULL == DCDest)
      {
+         if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
          DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
          return FALSE;
      }
  
      if (DCDest->dctype == DC_TYPE_INFO)
      {
-         DC_UnlockDc(DCDest);
+         if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+         GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
          /* Yes, Windows really returns TRUE in this case */
          return TRUE;
      }
  
      if (UsesSource)
      {
-         if (hDCSrc != hDCDest)
+         if (NULL == DCSrc)
          {
-             DCSrc = DC_LockDc(hDCSrc);
-             if (NULL == DCSrc)
-             {
-                 DC_UnlockDc(DCDest);
-                 DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
-                 return FALSE;
-             }
-             if (DCSrc->dctype == DC_TYPE_INFO)
-             {
-                 DC_UnlockDc(DCSrc);
-                 DC_UnlockDc(DCDest);
-                 /* Yes, Windows really returns TRUE in this case */
-                 return TRUE;
-             }
+             GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
+             DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
+             return FALSE;
          }
-         else
+         if (DCSrc->dctype == DC_TYPE_INFO)
          {
-             DCSrc = DCDest;
+             GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
+             GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+             /* Yes, Windows really returns TRUE in this case */
+             return TRUE;
          }
      }
+     else if(DCSrc)
+     {
+         DPRINT1("Getting a valid Source handle without using source!!!\n");
+         GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+         DCSrc = NULL ;
+     }
  
      pdcattr = DCDest->pdcattr;
  
-     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
-         DC_vUpdateFillBrush(DCDest);
      DestRect.left   = XDest;
      DestRect.top    = YDest;
      DestRect.right  = XDest+Width;
  
          SourcePoint.x += DCSrc->ptlDCOrig.x;
          SourcePoint.y += DCSrc->ptlDCOrig.y;
+         /* Calculate Source Rect */
+         SourceRect.left = SourcePoint.x;
+         SourceRect.top = SourcePoint.y;
+         SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left;
+         SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ;
      }
  
+     /* Prepare blit */
+     DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
+     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+         DC_vUpdateFillBrush(DCDest);
      /* Determine surfaces to be used in the bitblt */
      BitmapDest = DCDest->dclevel.pSurface;
      if (!BitmapDest)
                            &DCDest->dclevel.pbrFill->ptOrigin,
                            ROP3_TO_ROP4(ROP));
  
-       if (UsesSource)
+     if (UsesSource)
          EXLATEOBJ_vCleanup(&exlo);
  cleanup:
-     if (UsesSource && hDCSrc != hDCDest)
+     DC_vFinishBlit(DCDest, DCSrc);
+     if (UsesSource)
      {
-         DC_UnlockDc(DCSrc);
+         GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
      }
-     DC_UnlockDc(DCDest);
+     GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
  
      return Status;
  }
@@@ -318,97 -324,38 +324,38 @@@ NtGdiTransparentBlt
      COLORREF TransColor)
  {
      PDC DCDest, DCSrc;
+     HDC ahDC[2];
+     PGDIOBJ apObj[2];
      RECTL rcDest, rcSrc;
      SURFACE *BitmapDest, *BitmapSrc = NULL;
-     HPALETTE SourcePalette = 0, DestPalette = 0;
-     PPALETTE PalDestGDI, PalSourceGDI;
      ULONG TransparentColor = 0;
      BOOL Ret = FALSE;
      EXLATEOBJ exlo;
  
-     if(!(DCDest = DC_LockDc(hdcDst)))
-     {
-         DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst);
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return FALSE;
-     }
-     if (DCDest->dctype == DC_TYPE_INFO)
-     {
-         DC_UnlockDc(DCDest);
-         /* Yes, Windows really returns TRUE in this case */
-         return TRUE;
-     }
+     DPRINT("Locking DCs\n");
+     ahDC[0] = hdcDst;
+     ahDC[1] = hdcSrc ;
+     GDIOBJ_LockMultipleObjs(2, ahDC, apObj);
+     DCDest = apObj[0];
+     DCSrc = apObj[1];
  
-     if((hdcDst != hdcSrc) && !(DCSrc = DC_LockDc(hdcSrc)))
+     if ((NULL == DCDest) || (NULL == DCSrc))
      {
-         DC_UnlockDc(DCDest);
-         DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc);
+         DPRINT1("Invalid dc handle (dest=0x%08x, src=0x%08x) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc);
          SetLastWin32Error(ERROR_INVALID_HANDLE);
+         if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+         if(DCDest) GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
          return FALSE;
      }
  
-     if(hdcDst == hdcSrc)
-     {
-         DCSrc = DCDest;
-     }
-     if (DCSrc->dctype == DC_TYPE_INFO)
+     if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO)
      {
-         DC_UnlockDc(DCSrc);
-         if(hdcDst != hdcSrc)
-         {
-             DC_UnlockDc(DCDest);
-         }
+         GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+         GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
          /* Yes, Windows really returns TRUE in this case */
          return TRUE;
      }
  
-     BitmapDest = DCDest->dclevel.pSurface;
-     if (!BitmapDest)
-     {
-         goto done;
-     }
-     BitmapSrc = DCSrc->dclevel.pSurface;
-     if (!BitmapSrc)
-     {
-         goto done;
-     }
-     DestPalette = BitmapDest->hDIBPalette;
-     if (!DestPalette) DestPalette = pPrimarySurface->devinfo.hpalDefault;
-     SourcePalette = BitmapSrc->hDIBPalette;
-     if (!SourcePalette) SourcePalette = pPrimarySurface->devinfo.hpalDefault;
-     if(!(PalSourceGDI = PALETTE_LockPalette(SourcePalette)))
-     {
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         goto done;
-     }
-     PALETTE_UnlockPalette(PalSourceGDI);
-     if(DestPalette != SourcePalette)
-     {
-         if (!(PalDestGDI = PALETTE_LockPalette(DestPalette)))
-         {
-             SetLastWin32Error(ERROR_INVALID_HANDLE);
-             goto done;
-         }
-         PALETTE_UnlockPalette(PalDestGDI);
-     }
-     else
-     {
-         PalDestGDI = PalSourceGDI;
-     }
-     /* Translate Transparent (RGB) Color to the source palette */
-     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, PalSourceGDI, 0, 0, 0);
-     TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor);
-     EXLATEOBJ_vCleanup(&exlo);
-     EXLATEOBJ_vInitialize(&exlo, PalSourceGDI, PalDestGDI, 0, 0, 0);
      rcDest.left   = xDst;
      rcDest.top    = yDst;
      rcDest.right  = rcDest.left + cxDst;
      rcSrc.right  += DCSrc->ptlDCOrig.x;
      rcSrc.bottom += DCSrc->ptlDCOrig.y;
  
+     /* Prepare for blit */
+     DC_vPrepareDCsForBlit(DCDest, rcDest, DCSrc, rcSrc);
+     BitmapDest = DCDest->dclevel.pSurface;
+     if (!BitmapDest)
+     {
+         goto done;
+     }
+     BitmapSrc = DCSrc->dclevel.pSurface;
+     if (!BitmapSrc)
+     {
+         goto done;
+     }
+     /* Translate Transparent (RGB) Color to the source palette */
+     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, BitmapSrc->ppal, 0, 0, 0);
+     TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor);
+     EXLATEOBJ_vCleanup(&exlo);
+     EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest);
      Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj,
          DCDest->rosdc.CombinedClip, &exlo.xlo, &rcDest, &rcSrc,
          TransparentColor, 0);
  
- done:
-     DC_UnlockDc(DCSrc);
-     if(hdcDst != hdcSrc)
-     {
-         DC_UnlockDc(DCDest);
-     }
      EXLATEOBJ_vCleanup(&exlo);
+ done:
+     DC_vFinishBlit(DCDest, DCSrc);
+     GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
+     GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
      return Ret;
  }
  
@@@ -674,6 -643,8 +643,8 @@@ GreStretchBltMask
      PDC DCDest;
      PDC DCSrc  = NULL;
      PDC DCMask = NULL;
+     HDC ahDC[3];
+     PGDIOBJ apObj[3];
      PDC_ATTR pdcattr;
      SURFACE *BitmapDest, *BitmapSrc = NULL;
      SURFACE *BitmapMask = NULL;
          return FALSE;
      }
  
-     DCDest = DC_LockDc(hDCDest);
+     DPRINT("Locking DCs\n");
+     ahDC[0] = hDCDest;
+     ahDC[1] = hDCSrc ;
+     ahDC[2] = hDCMask ;
+     GDIOBJ_LockMultipleObjs(3, ahDC, apObj);
+     DCDest = apObj[0];
+     DCSrc = apObj[1];
+     DCMask = apObj[2];
      if (NULL == DCDest)
      {
-         DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest);
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
+         if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+         if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
+         DPRINT("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
          return FALSE;
      }
  
      if (DCDest->dctype == DC_TYPE_INFO)
      {
-         DC_UnlockDc(DCDest);
+         if(DCSrc) GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+         if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
+         GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
          /* Yes, Windows really returns TRUE in this case */
          return TRUE;
      }
  
      if (UsesSource)
      {
-         if (hDCSrc != hDCDest)
+         if (NULL == DCSrc)
          {
-             DCSrc = DC_LockDc(hDCSrc);
-             if (NULL == DCSrc)
-             {
-                 DC_UnlockDc(DCDest);
-                 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc);
-                 SetLastWin32Error(ERROR_INVALID_HANDLE);
-                 return FALSE;
-             }
-             if (DCSrc->dctype == DC_TYPE_INFO)
-             {
-                 DC_UnlockDc(DCSrc);
-                 DC_UnlockDc(DCDest);
-                 /* Yes, Windows really returns TRUE in this case */
-                 return TRUE;
-             }
+             GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
+             if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
+             DPRINT("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
+             return FALSE;
          }
-         else
+         if (DCSrc->dctype == DC_TYPE_INFO)
          {
-             DCSrc = DCDest;
+             GDIOBJ_UnlockObjByPtr(&DCDest->BaseObject);
+             GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+             if(DCMask) GDIOBJ_UnlockObjByPtr(&DCMask->BaseObject);
+             /* Yes, Windows really returns TRUE in this case */
+             return TRUE;
          }
      }
+     else if(DCSrc)
+     {
+         DPRINT1("Getting a valid Source handle without using source!!!\n");
+         GDIOBJ_UnlockObjByPtr(&DCSrc->BaseObject);
+         DCSrc = NULL ;
+     }
  
      pdcattr = DCDest->pdcattr;
  
-     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
-         DC_vUpdateFillBrush(DCDest);
      DestRect.left   = XOriginDest;
      DestRect.top    = YOriginDest;
      DestRect.right  = XOriginDest+WidthDest;
      BrushOrigin.x = 0;
      BrushOrigin.y = 0;
  
+     /* Only prepare Source and Dest, hdcMask represents a DIB */
+     DC_vPrepareDCsForBlit(DCDest, DestRect, DCSrc, SourceRect);
+     if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+         DC_vUpdateFillBrush(DCDest);
      /* Determine surfaces to be used in the bitblt */
      BitmapDest = DCDest->dclevel.pSurface;
      if (BitmapDest == NULL)
      BrushOrigin.y += DCDest->ptlDCOrig.y;
  
      /* Make mask surface for source surface */
-     if (BitmapSrc && hDCMask)
+     if (BitmapSrc && DCMask)
      {
-         DCMask = DC_LockDc(hDCMask);
-         if (DCMask)
+         BitmapMask = DCMask->dclevel.pSurface;
+         if (BitmapMask &&
+             (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
+              BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
          {
-             BitmapMask = DCMask->dclevel.pSurface;
-             if (BitmapMask &&
-                 (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc ||
-                  BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc))
-             {
-                 DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n", 
-                         BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy, 
-                         WidthSrc, HeightSrc);
-                 goto failed;
-             }
-             /* Create mask offset point */
-             MaskPoint.x = XOriginMask;
-             MaskPoint.y = YOriginMask;
-             IntLPtoDP(DCMask, &MaskPoint, 1);
-             MaskPoint.x += DCMask->ptlDCOrig.x;
-             MaskPoint.y += DCMask->ptlDCOrig.x;
+             DPRINT1("%dx%d mask is smaller than %dx%d bitmap\n",
+                     BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy,
+                     WidthSrc, HeightSrc);
+             EXLATEOBJ_vCleanup(&exlo);
+             goto failed;
          }
+         /* Create mask offset point */
+         MaskPoint.x = XOriginMask;
+         MaskPoint.y = YOriginMask;
+         IntLPtoDP(DCMask, &MaskPoint, 1);
+         MaskPoint.x += DCMask->ptlDCOrig.x;
+         MaskPoint.y += DCMask->ptlDCOrig.x;
      }
  
      /* Perform the bitblt operation */
                                &DCDest->eboFill.BrushObject,
                                &BrushOrigin,
                                ROP3_TO_ROP4(ROP));
- failed:
      if (UsesSource)
      {
          EXLATEOBJ_vCleanup(&exlo);
      }
-     if (UsesSource && hDCSrc != hDCDest)
+ failed:
+     DC_vFinishBlit(DCDest, DCSrc);
+     if (UsesSource)
      {
          DC_UnlockDc(DCSrc);
      }
@@@ -889,19 -871,12 +871,12 @@@ IntPatBlt
  {
      RECTL DestRect;
      SURFACE *psurf;
-     EBRUSHOBJ eboFill;
+     EBRUSHOBJ eboFill ;
      POINTL BrushOrigin;
      BOOL ret;
  
      ASSERT(pbrush);
  
-     psurf = pdc->dclevel.pSurface;
-     if (psurf == NULL)
-     {
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return FALSE;
-     }
      if (pbrush->flAttrs & GDIBRUSH_IS_NULL)
      {
          return TRUE;
      BrushOrigin.x = pbrush->ptOrigin.x + pdc->ptlDCOrig.x;
      BrushOrigin.y = pbrush->ptOrigin.y + pdc->ptlDCOrig.y;
  
+     DC_vPrepareDCsForBlit(pdc, DestRect, NULL, DestRect);
+     psurf = pdc->dclevel.pSurface;
+     if (pdc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+         DC_vUpdateFillBrush(pdc);
      EBRUSHOBJ_vInit(&eboFill, pbrush, pdc);
  
      ret = IntEngBitBlt(
          &DestRect,
          NULL,
          NULL,
-         &eboFill.BrushObject, // use pDC->eboFill
+         &eboFill.BrushObject,
          &BrushOrigin,
          ROP3_TO_ROP4(dwRop));
  
+     DC_vFinishBlit(pdc, NULL);
      EBRUSHOBJ_vCleanup(&eboFill);
  
      return ret;
  #define NDEBUG
  #include <debug.h>
  
- HBITMAP APIENTRY
- IntGdiCreateBitmap(
-     INT Width,
-     INT Height,
-     UINT Planes,
-     UINT BitsPixel,
-     IN OPTIONAL LPBYTE pBits)
+ LONG APIENTRY
+ IntSetBitmapBits(
+     PSURFACE psurf,
+     DWORD Bytes,
+     IN PBYTE Bits)
  {
-     HBITMAP hBitmap;
-     SIZEL Size;
-     LONG WidthBytes;
-     PSURFACE psurfBmp;
+     /* Don't copy more bytes than the buffer has */
+     Bytes = min(Bytes, psurf->SurfObj.cjBits);
  
-     /* NOTE: Windows also doesn't store nr. of planes separately! */
-     BitsPixel = BITMAP_GetRealBitsPixel(BitsPixel * Planes);
+     RtlCopyMemory(psurf->SurfObj.pvBits, Bits, Bytes);
  
-     /* Check parameters */
-     if (BitsPixel == 0 || Width <= 0 || Width >= 0x8000000 || Height == 0)
-     {
-         DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
-                 Width, Height, BitsPixel);
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return 0;
-     }
+     return Bytes;
+ }
  
-     WidthBytes = BITMAP_GetWidthBytes(Width, BitsPixel);
+ void
+ NTAPI
+ UnsafeSetBitmapBits(
+     PSURFACE psurf,
+     IN ULONG cjBits,
+     IN PVOID pvBits)
+ {
+     PUCHAR pjDst, pjSrc;
+     LONG lDeltaDst, lDeltaSrc;
+     ULONG nWidth, nHeight, cBitsPixel;
  
-     Size.cx = Width;
-     Size.cy = abs(Height);
+     nWidth = psurf->SurfObj.sizlBitmap.cx;
+     nHeight = psurf->SurfObj.sizlBitmap.cy;
+     cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
  
-     /* Make sure that cjBits will not overflow */
-     if ((ULONGLONG)WidthBytes * Size.cy >= 0x100000000ULL)
-     {
-         DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
-                 Width, Height, BitsPixel);
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return 0;
-     }
+     /* Get pointers */
+     pjDst = psurf->SurfObj.pvScan0;
+     pjSrc = pvBits;
+     lDeltaDst = psurf->SurfObj.lDelta;
+     lDeltaSrc = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
  
-     /* Create the bitmap object. */
-     hBitmap = IntCreateBitmap(Size, WidthBytes,
-                               BitmapFormat(BitsPixel, BI_RGB),
-                               (Height < 0 ? BMF_TOPDOWN : 0) |
-                               (NULL == pBits ? 0 : BMF_NOZEROINIT), NULL);
-     if (!hBitmap)
+     while (nHeight--)
      {
-         DPRINT("IntGdiCreateBitmap: returned 0\n");
-         return 0;
+         /* Copy one line */
+         memcpy(pjDst, pjSrc, lDeltaSrc);
+         pjSrc += lDeltaSrc;
+         pjDst += lDeltaDst;
      }
  
-     psurfBmp = SURFACE_LockSurface(hBitmap);
-     if (psurfBmp == NULL)
+ }
+ HBITMAP
+ APIENTRY
+ GreCreateBitmapEx(
+     IN INT nWidth,
+     IN INT nHeight,
+     IN ULONG cjWidthBytes,
+     IN ULONG iFormat,
+     IN USHORT fjBitmap,
+     IN ULONG cjSizeImage,
+     IN OPTIONAL PVOID pvBits,
+       IN FLONG flags)
+ {
+     PSURFACE psurf;
+     SURFOBJ *pso;
+     HBITMAP hbmp;
+     PVOID pvCompressedBits;
+     SIZEL sizl;
+     /* Verify format */
+     if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL;
+     /* Allocate a surface */
+     psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat);
+     if (!psurf)
      {
-         GreDeleteObject(hBitmap);
+         DPRINT1("SURFACE_AllocSurface failed.\n");
          return NULL;
      }
  
-     psurfBmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
-     psurfBmp->hDC = NULL; // Fixme
+     /* Get the handle for the bitmap and the surfobj */
+     hbmp = (HBITMAP)psurf->SurfObj.hsurf;
+     pso = &psurf->SurfObj;
  
-     if (NULL != pBits)
+     /* The infamous RLE hack */
+     if (iFormat == BMF_4RLE || iFormat == BMF_8RLE)
      {
-         IntSetBitmapBits(psurfBmp, psurfBmp->SurfObj.cjBits, pBits);
+         sizl.cx = nWidth;
+         sizl.cy = nHeight;
+         pvCompressedBits = pvBits;
+         pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB);
+         DecompressBitmap(sizl, pvCompressedBits, pvBits, pso->lDelta, iFormat);
+         fjBitmap |= BMF_RLE_HACK;
      }
  
-     SURFACE_UnlockSurface(psurfBmp);
+       /* Mark as API bitmap */
+       psurf->flags |= (flags | API_BITMAP);
  
-     DPRINT("IntGdiCreateBitmap : %dx%d, %d BPP colors, topdown %d, returning %08x\n",
-            Size.cx, Size.cy, BitsPixel, (Height < 0 ? 1 : 0), hBitmap);
+     /* Set the bitmap bits */
+     if (!SURFACE_bSetBitmapBits(psurf, fjBitmap, cjWidthBytes, pvBits))
+     {
+         /* Bail out if that failed */
+         DPRINT1("SURFACE_bSetBitmapBits failed.\n");
+         SURFACE_FreeSurfaceByHandle(hbmp);
+         return NULL;
+     }
  
-     return hBitmap;
+     /* Unlock the surface and return */
+     SURFACE_UnlockSurface(psurf);
+     return hbmp;
  }
  
+ /* Creates a DDB surface,
+  * as in CreateCompatibleBitmap or CreateBitmap.
+  */
+ HBITMAP
+ APIENTRY
+ GreCreateBitmap(
+     IN INT nWidth,
+     IN INT nHeight,
+     IN UINT cPlanes,
+     IN UINT cBitsPixel,
+     IN OPTIONAL PVOID pvBits)
+ {
+     /* Call the extended function */
+     return GreCreateBitmapEx(nWidth,
+                              nHeight,
+                              0, /* auto width */
+                              BitmapFormat(cBitsPixel * cPlanes, BI_RGB),
+                              0, /* no bitmap flags */
+                              0, /* auto size */
+                              pvBits,
+                                                        DDB_SURFACE /* DDB */);
+ }
  
- HBITMAP APIENTRY
+ HBITMAP
+ APIENTRY
  NtGdiCreateBitmap(
-     INWidth,
-     INHeight,
-     UINT Planes,
-     UINT BitsPixel,
+     IN INT nWidth,
+     IN INT nHeight,
+     IN UINT cPlanes,
+     IN UINT cBitsPixel,
      IN OPTIONAL LPBYTE pUnsafeBits)
  {
-     if (pUnsafeBits)
+     HBITMAP hbmp;
+     ULONG cjWidthBytes, iFormat;
+     /* NOTE: Windows also doesn't store nr. of planes separately! */
+     cBitsPixel = BITMAP_GetRealBitsPixel(cBitsPixel * cPlanes);
+     /* Calculate bitmap format */
+     iFormat = BitmapFormat(cBitsPixel, BI_RGB);
+     /* Check parameters */
+     if (iFormat == 0 || nWidth <= 0 || nWidth >= 0x8000000 || nHeight <= 0)
      {
-         BOOL Hit = FALSE;
-         UINT cjBits = BITMAP_GetWidthBytes(Width, BitsPixel) * abs(Height);
+         DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
+                 nWidth, nHeight, cBitsPixel);
+         EngSetLastError(ERROR_INVALID_PARAMETER);
+         return NULL;
+     }
  
-         // FIXME: Use MmSecureVirtualMemory
+     /* Make sure that cjBits will not overflow */
+     cjWidthBytes = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
+     if ((ULONGLONG)cjWidthBytes * nHeight >= 0x100000000ULL)
+     {
+         DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
+                 nWidth, nHeight, cBitsPixel);
+         EngSetLastError(ERROR_INVALID_PARAMETER);
+         return NULL;
+     }
+       /* cBitsPixel = cBitsPixel * cPlanes now! */
+       hbmp = GreCreateBitmap(nWidth, nHeight, 1, cBitsPixel, NULL);
+     if (pUnsafeBits)
+     {
+               PSURFACE psurf = SURFACE_LockSurface(hbmp);
          _SEH2_TRY
          {
-             ProbeForRead(pUnsafeBits, cjBits, 1);
+             ProbeForRead(pUnsafeBits, cjWidthBytes * nHeight, 1);
+             UnsafeSetBitmapBits(psurf, 0, pUnsafeBits);
          }
          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
          {
-             Hit = TRUE;
+                       SURFACE_UnlockSurface(psurf);
+             SURFACE_FreeSurfaceByHandle(hbmp);
+             _SEH2_YIELD(return NULL;)
          }
          _SEH2_END
  
-         if (Hit) return 0;
+               SURFACE_UnlockSurface(psurf);
      }
  
-     return IntGdiCreateBitmap(Width, Height, Planes, BitsPixel, pUnsafeBits);
+     return hbmp;
  }
  
  HBITMAP FASTCALL
  IntCreateCompatibleBitmap(
      PDC Dc,
      {
          if (Dc->dctype != DC_TYPE_MEMORY)
          {
-             Bmp = IntGdiCreateBitmap(abs(Width),
-                                      abs(Height),
-                                      IntGdiGetDeviceCaps(Dc,PLANES),
-                                      IntGdiGetDeviceCaps(Dc,BITSPIXEL),
-                                      NULL);
+             PSURFACE psurf;
+             Bmp = GreCreateBitmap(abs(Width),
+                                   abs(Height),
+                                   1,
+                                   Dc->ppdev->gdiinfo.cBitsPixel,
+                                   NULL);
+             psurf = SURFACE_LockSurface(Bmp);
+             ASSERT(psurf);
+             /* Set palette */
+             psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
+             /* Set flags */
+             psurf->flags = API_BITMAP;
+             psurf->hdc = NULL; // Fixme
+             SURFACE_UnlockSurface(psurf);
          }
          else
          {
              {
                  if (Count == sizeof(BITMAP))
                  {
-                     /* We have a bitmap bug!!! W/O the HACK, we have white icons.
-                        MSDN Note: When a memory device context is created, it initially
-                        has a 1-by-1 monochrome bitmap selected into it. If this memory
-                        device context is used in CreateCompatibleBitmap, the bitmap that
-                        is created is a monochrome bitmap. To create a color bitmap, use
-                        the hDC that was used to create the memory device context, as
-                        shown in the following code:
-                            HDC memDC = CreateCompatibleDC(hDC);
-                            HBITMAP memBM = CreateCompatibleBitmap(hDC, nWidth, nHeight);
-                            SelectObject(memDC, memBM);
-                      */
-                     Bmp = IntGdiCreateBitmap(abs(Width),
-                                              abs(Height),
-                                              dibs.dsBm.bmPlanes,
-                                              IntGdiGetDeviceCaps(Dc,BITSPIXEL),//<-- HACK! dibs.dsBm.bmBitsPixel, // <-- Correct!
-                                              NULL);
+                     PSURFACE psurfBmp;
+                     Bmp = GreCreateBitmap(abs(Width),
+                                   abs(Height),
+                                   1,
+                                   dibs.dsBm.bmBitsPixel,
+                                   NULL);
+                     psurfBmp = SURFACE_LockSurface(Bmp);
+                     ASSERT(psurfBmp);
+                     /* Assign palette */
+                     psurfBmp->ppal = psurf->ppal;
+                     GDIOBJ_IncrementShareCount((POBJ)psurf->ppal);
+                     /* Set flags */
+                     psurfBmp->flags = API_BITMAP;
+                     psurfBmp->hdc = NULL; // Fixme
+                     SURFACE_UnlockSurface(psurfBmp);
                  }
                  else
                  {
                      /* A DIB section is selected in the DC */
-                     BITMAPINFO *bi;
+                                       BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0};
                      PVOID Bits;
-                     /* Allocate memory for a BITMAPINFOHEADER structure and a
-                        color table. The maximum number of colors in a color table
-                        is 256 which corresponds to a bitmap with depth 8.
-                        Bitmaps with higher depths don't have color tables. */
-                     bi = ExAllocatePoolWithTag(PagedPool,
-                                                sizeof(BITMAPINFOHEADER) +
-                                                    256 * sizeof(RGBQUAD),
-                                                TAG_TEMP);
-                     if (bi)
+                                       BITMAPINFO* bi = (BITMAPINFO*)buf;
+                     bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
+                     bi->bmiHeader.biWidth         = Width;
+                     bi->bmiHeader.biHeight        = Height;
+                     bi->bmiHeader.biPlanes        = dibs.dsBmih.biPlanes;
+                     bi->bmiHeader.biBitCount      = dibs.dsBmih.biBitCount;
+                     bi->bmiHeader.biCompression   = dibs.dsBmih.biCompression;
+                     bi->bmiHeader.biSizeImage     = 0;
+                     bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
+                     bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
+                     bi->bmiHeader.biClrUsed       = dibs.dsBmih.biClrUsed;
+                     bi->bmiHeader.biClrImportant  = dibs.dsBmih.biClrImportant;
+                     if (bi->bmiHeader.biCompression == BI_BITFIELDS)
+                     {
+                         /* Copy the color masks */
+                         RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD));
+                     }
+                     else if (bi->bmiHeader.biBitCount <= 8)
                      {
-                         bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
-                         bi->bmiHeader.biWidth         = Width;
-                         bi->bmiHeader.biHeight        = Height;
-                         bi->bmiHeader.biPlanes        = dibs.dsBmih.biPlanes;
-                         bi->bmiHeader.biBitCount      = dibs.dsBmih.biBitCount;
-                         bi->bmiHeader.biCompression   = dibs.dsBmih.biCompression;
-                         bi->bmiHeader.biSizeImage     = 0;
-                         bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
-                         bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
-                         bi->bmiHeader.biClrUsed       = dibs.dsBmih.biClrUsed;
-                         bi->bmiHeader.biClrImportant  = dibs.dsBmih.biClrImportant;
-                         if (bi->bmiHeader.biCompression == BI_BITFIELDS)
+                         /* Copy the color table */
+                         UINT Index;
+                         PPALETTE PalGDI;
+                         if (!psurf->ppal)
                          {
-                             /* Copy the color masks */
-                             RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3 * sizeof(DWORD));
+                             SetLastWin32Error(ERROR_INVALID_HANDLE);
+                             return 0;
                          }
-                         else if (bi->bmiHeader.biBitCount <= 8)
+                         PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
+                         for (Index = 0;
+                                 Index < 256 && Index < PalGDI->NumColors;
+                                 Index++)
                          {
-                             /* Copy the color table */
-                             UINT Index;
-                             PPALETTE PalGDI = PALETTE_LockPalette(psurf->hDIBPalette);
-                             if (!PalGDI)
-                             {
-                                 ExFreePoolWithTag(bi, TAG_TEMP);
-                                 SetLastWin32Error(ERROR_INVALID_HANDLE);
-                                 return 0;
-                             }
-                             for (Index = 0;
-                                     Index < 256 && Index < PalGDI->NumColors;
-                                     Index++)
-                             {
-                                 bi->bmiColors[Index].rgbRed   = PalGDI->IndexedColors[Index].peRed;
-                                 bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
-                                 bi->bmiColors[Index].rgbBlue  = PalGDI->IndexedColors[Index].peBlue;
-                                 bi->bmiColors[Index].rgbReserved = 0;
-                             }
-                             PALETTE_UnlockPalette(PalGDI);
+                             bi->bmiColors[Index].rgbRed   = PalGDI->IndexedColors[Index].peRed;
+                             bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
+                             bi->bmiColors[Index].rgbBlue  = PalGDI->IndexedColors[Index].peBlue;
+                             bi->bmiColors[Index].rgbReserved = 0;
                          }
+                         PALETTE_UnlockPalette(PalGDI);
  
                          Bmp = DIB_CreateDIBSection(Dc,
                                                     bi,
                                                     NULL,
                                                     0,
                                                     0);
-                         ExFreePoolWithTag(bi, TAG_TEMP);
                          return Bmp;
                      }
                  }
@@@ -272,7 -356,7 +356,7 @@@ NtGdiCreateCompatibleBitmap
      }
  
      if (!hDC)
-         return IntGdiCreateBitmap(Width, Height, 1, 1, 0);
+         return GreCreateBitmap(Width, Height, 1, 1, 0);
  
      Dc = DC_LockDc(hDC);
  
@@@ -313,7 -397,7 +397,7 @@@ NtGdiGetBitmapDimension
      _SEH2_TRY
      {
          ProbeForWrite(Dimension, sizeof(SIZE), 1);
-         *Dimension = psurfBmp->dimension;
+         *Dimension = psurfBmp->sizlDim;
      }
      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
      {
@@@ -334,8 -418,6 +418,6 @@@ NtGdiGetPixel(HDC hDC, INT XPos, INT YP
      BOOL bInRect = FALSE;
      SURFACE *psurf;
      SURFOBJ *pso;
-     HPALETTE hpal = 0;
-     PPALETTE ppal;
      EXLATEOBJ exlo;
      HBITMAP hBmpTmp;
  
          psurf = dc->dclevel.pSurface;
          if (psurf)
          {
-             pso = &psurf->SurfObj;
-             hpal = psurf->hDIBPalette;
-             if (!hpal) hpal = pPrimarySurface->devinfo.hpalDefault;
-             ppal = PALETTE_ShareLockPalette(hpal);
-             if (psurf->SurfObj.iBitmapFormat == BMF_1BPP && !psurf->hSecure)
-             {
-                 /* FIXME: palette should be gpalMono already ! */
-                 EXLATEOBJ_vInitialize(&exlo, &gpalMono, &gpalRGB, 0, 0xffffff, 0);
-             }
-             else
-             {
-                 EXLATEOBJ_vInitialize(&exlo, ppal, &gpalRGB, 0, 0xffffff, 0);
-             }
+                       pso = &psurf->SurfObj;
+             EXLATEOBJ_vInitialize(&exlo, psurf->ppal, &gpalRGB, 0, 0xffffff, 0);
              // check if this DC has a DIB behind it...
              if (pso->pvScan0) // STYPE_BITMAP == pso->iType
              {
              }
  
              EXLATEOBJ_vCleanup(&exlo);
-             PALETTE_ShareUnlockPalette(ppal);
          }
      }
      DC_UnlockDc(dc);
                                                    0,
                                                    0);
  
-             //HBITMAP hBmpTmp = IntGdiCreateBitmap(1, 1, 1, 32, NULL);
+             //HBITMAP hBmpTmp = GreCreateBitmap(1, 1, 1, 32, NULL);
              if (hBmpTmp)
              {
                  HBITMAP hBmpOld = (HBITMAP)NtGdiSelectBitmap(hDCTmp, hBmpTmp);
@@@ -482,6 -550,36 +550,36 @@@ IntGetBitmapBits
      return ret;
  }
  
+ VOID
+ FASTCALL
+ UnsafeGetBitmapBits(
+     PSURFACE psurf,
+       DWORD Bytes,
+       OUT PBYTE pvBits)
+ {
+       PUCHAR pjDst, pjSrc;
+     LONG lDeltaDst, lDeltaSrc;
+     ULONG nWidth, nHeight, cBitsPixel;
+     nWidth = psurf->SurfObj.sizlBitmap.cx;
+     nHeight = psurf->SurfObj.sizlBitmap.cy;
+     cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+     /* Get pointers */
+     pjSrc = psurf->SurfObj.pvScan0;
+     pjDst = pvBits;
+     lDeltaSrc = psurf->SurfObj.lDelta;
+     lDeltaDst = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
+     while (nHeight--)
+     {
+         /* Copy one line */
+         RtlCopyMemory(pjDst, pjSrc, lDeltaDst);
+         pjSrc += lDeltaSrc;
+         pjDst += lDeltaDst;
+     }
+ }
  LONG APIENTRY
  NtGdiGetBitmapBits(
      HBITMAP hBitmap,
          return 0;
      }
  
-     bmSize = BITMAP_GetWidthBytes(psurf->SurfObj.sizlBitmap.cx,
+     bmSize = WIDTH_BYTES_ALIGN16(psurf->SurfObj.sizlBitmap.cx,
               BitsPerFormat(psurf->SurfObj.iBitmapFormat)) *
               abs(psurf->SurfObj.sizlBitmap.cy);
  
      _SEH2_TRY
      {
          ProbeForWrite(pUnsafeBits, Bytes, 1);
-         ret = IntGetBitmapBits(psurf, Bytes, pUnsafeBits);
+         UnsafeGetBitmapBits(psurf, Bytes, pUnsafeBits);
+               ret = Bytes;
      }
      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
      {
  }
  
  
- LONG APIENTRY
- IntSetBitmapBits(
-     PSURFACE psurf,
-     DWORD Bytes,
-     IN PBYTE Bits)
- {
-     LONG ret;
-     /* Don't copy more bytes than the buffer has */
-     Bytes = min(Bytes, psurf->SurfObj.cjBits);
- #if 0
-     /* FIXME: call DDI specific function here if available  */
-     if (psurf->DDBitmap)
-     {
-         DPRINT("Calling device specific BitmapBits\n");
-         if (psurf->DDBitmap->funcs->pBitmapBits)
-         {
-             ret = psurf->DDBitmap->funcs->pBitmapBits(hBitmap,
-                                                       (void *)Bits,
-                                                       Bytes,
-                                                       DDB_SET);
-         }
-         else
-         {
-             DPRINT("BitmapBits == NULL??\n");
-             ret = 0;
-         }
-     }
-     else
- #endif
-     {
-         RtlCopyMemory(psurf->SurfObj.pvBits, Bits, Bytes);
-         ret = Bytes;
-     }
-     return ret;
- }
  LONG APIENTRY
  NtGdiSetBitmapBits(
      HBITMAP hBitmap,
      _SEH2_TRY
      {
          ProbeForRead(pUnsafeBits, Bytes, 1);
-         ret = IntSetBitmapBits(psurf, Bytes, pUnsafeBits);
+         UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits);
+         ret = 1;
      }
      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
      {
@@@ -637,7 -697,7 +697,7 @@@ NtGdiSetBitmapDimension
          _SEH2_TRY
          {
              ProbeForWrite(Size, sizeof(SIZE), 1);
-             *Size = psurf->dimension;
+             *Size = psurf->sizlDim;
          }
          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
          {
      }
  
      /* The dimension is changed even if writing the old value failed */
-     psurf->dimension.cx = Width;
-     psurf->dimension.cy = Height;
+     psurf->sizlDim.cx = Width;
+     psurf->sizlDim.cy = Height;
  
      SURFACE_UnlockSurface(psurf);
  
@@@ -665,7 -725,7 +725,7 @@@ VOID IntHandleSpecialColorType(HDC hDC
      switch (*Color >> 24)
      {
          case 0x10: /* DIBINDEX */
-             if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1) 
+             if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1)
              {
                  *Color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue);
              }
          default:
              DPRINT("Unsupported color type %d passed\n", *Color >> 24);
              break;
-     }   
+     }
  }
  
  BOOL APIENTRY
@@@ -786,40 -846,6 +846,6 @@@ BITMAP_GetRealBitsPixel(UINT nBitsPixel
      return 0;
  }
  
- INT FASTCALL
- BITMAP_GetWidthBytes(INT bmWidth, INT bpp)
- {
- #if 0
-     switch (bpp)
-     {
-     case 1:
-         return 2 * ((bmWidth+15) >> 4);
-     case 24:
-         bmWidth *= 3; /* fall through */
-     case 8:
-         return bmWidth + (bmWidth & 1);
-     case 32:
-         return bmWidth * 4;
-     case 16:
-     case 15:
-         return bmWidth * 2;
-     case 4:
-         return 2 * ((bmWidth+3) >> 2);
-     default:
-         DPRINT ("stub");
-     }
-     return -1;
- #endif
-     return ((bmWidth * bpp + 15) & ~15) >> 3;
- }
  HBITMAP FASTCALL
  BITMAP_CopyBitmap(HBITMAP hBitmap)
  {
          return 0;
      }
  
-     Bitmap = GDIOBJ_LockObj(hBitmap, GDI_OBJECT_TYPE_BITMAP);
+     Bitmap = SURFACE_LockSurface(hBitmap);
      if (Bitmap == NULL)
      {
          return 0;
  
      Size.cx = abs(bm.bmWidth);
      Size.cy = abs(bm.bmHeight);
-     res = IntCreateBitmap(Size,
-                           bm.bmWidthBytes,
-                           BitmapFormat(bm.bmBitsPixel * bm.bmPlanes, BI_RGB),
-                           (bm.bmHeight < 0 ? BMF_TOPDOWN : 0) | BMF_NOZEROINIT,
-                           NULL);
+     res = GreCreateBitmapEx(Size.cx,
+                                                       Size.cy,
+                                                       bm.bmWidthBytes,
+                                                       Bitmap->SurfObj.iBitmapFormat,
+                                                       Bitmap->SurfObj.fjBitmap,
+                                                       Bitmap->SurfObj.cjBits,
+                                                       NULL,
+                                                       Bitmap->flags);
  
      if (res)
      {
-         PBYTE buf;
-         resBitmap = GDIOBJ_LockObj(res, GDI_OBJECT_TYPE_BITMAP);
+         resBitmap = SURFACE_LockSurface(res);
          if (resBitmap)
          {
-             buf = ExAllocatePoolWithTag(PagedPool,
-                                         bm.bmWidthBytes * abs(bm.bmHeight),
-                                         TAG_BITMAP);
-             if (buf == NULL)
-             {
-                 GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
-                 GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
-                 GreDeleteObject(res);
-                 return 0;
-             }
-             IntGetBitmapBits(Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
-             IntSetBitmapBits(resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
-             ExFreePoolWithTag(buf,TAG_BITMAP);
-             resBitmap->flFlags = Bitmap->flFlags;
-             GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
+             IntSetBitmapBits(resBitmap, Bitmap->SurfObj.cjBits, Bitmap->SurfObj.pvBits);
+                       SURFACE_UnlockSurface(resBitmap);
          }
          else
          {
          }
      }
  
-     GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
+     SURFACE_UnlockSurface(Bitmap);
  
      return  res;
  }
@@@ -900,15 -915,17 +915,17 @@@ BITMAP_GetObject(SURFACE *psurf, INT Co
      pBitmap->bmType = 0;
      pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx;
      pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy;
-     pBitmap->bmWidthBytes = abs(psurf->SurfObj.lDelta);
      pBitmap->bmPlanes = 1;
      pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+       pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN16(pBitmap->bmWidth, pBitmap->bmBitsPixel);
  
      /* Check for DIB section */
      if (psurf->hSecure)
      {
          /* Set bmBits in this case */
          pBitmap->bmBits = psurf->SurfObj.pvBits;
+               /* DIBs data are 32 bits aligned */
+               pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN32(pBitmap->bmWidth, pBitmap->bmBitsPixel);
  
          if (Count >= sizeof(DIBSECTION))
          {
              pds->dsBmih.biHeight = pds->dsBm.bmHeight;
              pds->dsBmih.biPlanes = pds->dsBm.bmPlanes;
              pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel;
-             switch (psurf->SurfObj.iBitmapFormat)
-             {
-                 /* FIXME: What about BI_BITFIELDS? */
-                 case BMF_1BPP:
-                 case BMF_4BPP:
-                 case BMF_8BPP:
-                 case BMF_16BPP:
-                 case BMF_24BPP:
-                 case BMF_32BPP:
-                    pds->dsBmih.biCompression = BI_RGB;
-                    break;
-                 case BMF_4RLE:
-                    pds->dsBmih.biCompression = BI_RLE4;
-                    break;
-                 case BMF_8RLE:
-                    pds->dsBmih.biCompression = BI_RLE8;
-                    break;
-                 case BMF_JPEG:
-                    pds->dsBmih.biCompression = BI_JPEG;
-                    break;
-                 case BMF_PNG:
-                    pds->dsBmih.biCompression = BI_PNG;
-                    break;
-             }
+                       if(psurf->ppal->flFlags & PAL_BITFIELDS)
+                       {
+                               pds->dsBmih.biCompression = BI_BITFIELDS;
+                       }
+                       else
+                       {
+                               switch (psurf->SurfObj.iBitmapFormat)
+                               {
+                                       case BMF_1BPP:
+                                       case BMF_4BPP:
+                                       case BMF_8BPP:
+                                       case BMF_16BPP:
+                                       case BMF_24BPP:
+                                       case BMF_32BPP:
+                                          pds->dsBmih.biCompression = BI_RGB;
+                                          break;
+                                       case BMF_4RLE:
+                                          pds->dsBmih.biCompression = BI_RLE4;
+                                          break;
+                                       case BMF_8RLE:
+                                          pds->dsBmih.biCompression = BI_RLE8;
+                                          break;
+                                       case BMF_JPEG:
+                                          pds->dsBmih.biCompression = BI_JPEG;
+                                          break;
+                                       case BMF_PNG:
+                                          pds->dsBmih.biCompression = BI_PNG;
+                                          break;
+                               }
+                       }
              pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
              pds->dsBmih.biXPelsPerMeter = 0;
              pds->dsBmih.biYPelsPerMeter = 0;
-             pds->dsBmih.biClrUsed = psurf->biClrUsed;
+             pds->dsBmih.biClrUsed = psurf->ppal->NumColors;
              pds->dsBmih.biClrImportant = psurf->biClrImportant;
-             pds->dsBitfields[0] = psurf->dsBitfields[0];
-             pds->dsBitfields[1] = psurf->dsBitfields[1];
-             pds->dsBitfields[2] = psurf->dsBitfields[2];
+             pds->dsBitfields[0] = psurf->ppal->RedMask;
+             pds->dsBitfields[1] = psurf->ppal->GreenMask;
+             pds->dsBitfields[2] = psurf->ppal->BlueMask;
              pds->dshSection = psurf->hDIBSection;
              pds->dsOffset = psurf->dwOffset;
  
@@@ -975,14 -998,15 +998,15 @@@ APIENTR
  NtGdiGetDCforBitmap(
      IN HBITMAP hsurf)
  {
-     HDC hDC = NULL;
+     HDC hdc = NULL;
      PSURFACE psurf = SURFACE_LockSurface(hsurf);
      if (psurf)
      {
-         hDC = psurf->hDC;
+         hdc = psurf->hdc;
          SURFACE_UnlockSurface(psurf);
      }
-     return hDC;
+     return hdc;
  }
  
  /* EOF */
@@@ -1,9 -1,9 +1,9 @@@
- /* 
+ /*
   * COPYRIGHT:         See COPYING in the top level directory
   * PROJECT:           ReactOS win32 subsystem
   * PURPOSE:           Functions for brushes
   * FILE:              subsystem/win32/win32k/objects/brush.c
-  * PROGRAMER:         
+  * PROGRAMER:
   */
  
  #include <win32k.h>
@@@ -19,13 -19,13 +19,13 @@@ typedef struct _GDI_OBJ_ATTR_FREELIS
    DWORD nEntries;
    PVOID AttrList[GDIOBJATTRFREE];
  } GDI_OBJ_ATTR_FREELIST, *PGDI_OBJ_ATTR_FREELIST;
-       
  typedef struct _GDI_OBJ_ATTR_ENTRY
  {
    RGN_ATTR Attr[GDIOBJATTRFREE];
  } GDI_OBJ_ATTR_ENTRY, *PGDI_OBJ_ATTR_ENTRY;
  
- static const USHORT HatchBrushes[NB_HATCH_STYLES][8] =
+ static const ULONG HatchBrushes[NB_HATCH_STYLES][8] =
  {
      {0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF}, /* HS_HORIZONTAL */
      {0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7, 0xF7}, /* HS_VERTICAL   */
@@@ -46,7 -46,7 +46,7 @@@ AllocateObjectAttr(VOID
    PGDI_OBJ_ATTR_FREELIST pGdiObjAttrFreeList;
    PGDI_OBJ_ATTR_ENTRY pGdiObjAttrEntry;
    int i;
-   
    pti = PsGetCurrentThreadWin32Thread();
    if (pti->pgdiBrushAttr)
    {
@@@ -127,9 -127,9 +127,9 @@@ FreeObjectAttr(PVOID pAttr
    PGDI_OBJ_ATTR_FREELIST pGdiObjAttrFreeList;
  
    pti = PsGetCurrentThreadWin32Thread();
-   
    if (!pti) return;
-   
    if (!pti->pgdiBrushAttr)
    {  // If it is null, just cache it for the next time.
       pti->pgdiBrushAttr = pAttr;
@@@ -244,129 -244,6 +244,6 @@@ BRUSH_GetObject(PBRUSH pbrush, INT Coun
      return sizeof(LOGBRUSH);
  }
  
- /**
-  * @name CalculateColorTableSize
-  *
-  * Internal routine to calculate the number of color table entries.
-  *
-  * @param BitmapInfoHeader
-  *        Input bitmap information header, can be any version of
-  *        BITMAPINFOHEADER or BITMAPCOREHEADER.
-  *
-  * @param ColorSpec
-  *        Pointer to variable which specifiing the color mode (DIB_RGB_COLORS
-  *        or DIB_RGB_COLORS). On successful return this value is normalized
-  *        according to the bitmap info.
-  *
-  * @param ColorTableSize
-  *        On successful return this variable is filled with number of
-  *        entries in color table for the image with specified parameters.
-  *
-  * @return
-  *    TRUE if the input values together form a valid image, FALSE otherwise.
-  */
- BOOL
- APIENTRY
- CalculateColorTableSize(
-     CONST BITMAPINFOHEADER *BitmapInfoHeader,
-     UINT *ColorSpec,
-     UINT *ColorTableSize)
- {
-     WORD BitCount;
-     DWORD ClrUsed;
-     DWORD Compression;
-     /*
-      * At first get some basic parameters from the passed BitmapInfoHeader
-      * structure. It can have one of the following formats:
-      * - BITMAPCOREHEADER (the oldest one with totally different layout
-      *                     from the others)
-      * - BITMAPINFOHEADER (the standard and most common header)
-      * - BITMAPV4HEADER (extension of BITMAPINFOHEADER)
-      * - BITMAPV5HEADER (extension of BITMAPV4HEADER)
-      */
-     if (BitmapInfoHeader->biSize == sizeof(BITMAPCOREHEADER))
-     {
-         BitCount = ((LPBITMAPCOREHEADER)BitmapInfoHeader)->bcBitCount;
-         ClrUsed = 0;
-         Compression = BI_RGB;
-     }
-     else
-     {
-         BitCount = BitmapInfoHeader->biBitCount;
-         ClrUsed = BitmapInfoHeader->biClrUsed;
-         Compression = BitmapInfoHeader->biCompression;
-     }
-     switch (Compression)
-     {
-         case BI_BITFIELDS:
-             if (*ColorSpec == DIB_PAL_COLORS)
-                 *ColorSpec = DIB_RGB_COLORS;
-             if (BitCount != 16 && BitCount != 32)
-                 return FALSE;
-             /* For BITMAPV4HEADER/BITMAPV5HEADER the masks are included in
-              * the structure itself (bV4RedMask, bV4GreenMask, and bV4BlueMask).
-              * For BITMAPINFOHEADER the color masks are stored in the palette. */
-             if (BitmapInfoHeader->biSize > sizeof(BITMAPINFOHEADER))
-                 *ColorTableSize = 0;
-             else
-                 *ColorTableSize = 3;
-             return TRUE;
-         case BI_RGB:
-             switch (BitCount)
-             {
-                 case 1:
-                     *ColorTableSize = ClrUsed ? min(ClrUsed, 2) : 2;
-                     return TRUE;
-                 case 4:
-                     *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
-                     return TRUE;
-                 case 8:
-                     *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
-                     return TRUE;
-                 default:
-                     if (*ColorSpec == DIB_PAL_COLORS)
-                         *ColorSpec = DIB_RGB_COLORS;
-                     if (BitCount != 16 && BitCount != 24 && BitCount != 32)
-                         return FALSE;
-                     *ColorTableSize = ClrUsed;
-                     return TRUE;
-             }
-         case BI_RLE4:
-             if (BitCount == 4)
-             {
-                 *ColorTableSize = ClrUsed ? min(ClrUsed, 16) : 16;
-                 return TRUE;
-             }
-             return FALSE;
-         case BI_RLE8:
-             if (BitCount == 8)
-             {
-                 *ColorTableSize = ClrUsed ? min(ClrUsed, 256) : 256;
-                 return TRUE;
-             }
-             return FALSE;
-         case BI_JPEG:
-         case BI_PNG:
-             *ColorTableSize = ClrUsed;
-             return TRUE;
-         default:
-             return FALSE;
-     }
- }
  HBRUSH
  APIENTRY
  IntGdiCreateDIBBrush(
      PBRUSH pbrush;
      HBITMAP hPattern;
      ULONG_PTR DataPtr;
-     UINT PaletteEntryCount;
-     PSURFACE psurfPattern;
-     INT PaletteType;
+     PVOID pvDIBits;
  
      if (BitmapInfo->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
      {
          return NULL;
      }
  
-     if (!CalculateColorTableSize(&BitmapInfo->bmiHeader,
-                                  &ColorSpec,
-                                  &PaletteEntryCount))
-     {
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return NULL;
-     }
-     // FIXME: What about BI_BITFIELDS
-     DataPtr = (ULONG_PTR)BitmapInfo + BitmapInfo->bmiHeader.biSize;
-     if (ColorSpec == DIB_RGB_COLORS)
-         DataPtr += PaletteEntryCount * sizeof(RGBQUAD);
-     else
-         DataPtr += PaletteEntryCount * sizeof(USHORT);
+     DataPtr = (ULONG_PTR)BitmapInfo + DIB_BitmapInfoSize(BitmapInfo, ColorSpec);
  
-     hPattern = IntGdiCreateBitmap(BitmapInfo->bmiHeader.biWidth,
-                                   BitmapInfo->bmiHeader.biHeight,
-                                   BitmapInfo->bmiHeader.biPlanes,
-                                   BitmapInfo->bmiHeader.biBitCount,
-                                   (PVOID)DataPtr);
+     hPattern = DIB_CreateDIBSection(NULL, BitmapInfo, ColorSpec, &pvDIBits, NULL, 0, 0);
      if (hPattern == NULL)
      {
          SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
          return NULL;
      }
-     psurfPattern = SURFACE_LockSurface(hPattern);
-     ASSERT(psurfPattern != NULL);
-     psurfPattern->hDIBPalette = BuildDIBPalette(BitmapInfo, &PaletteType);
-     SURFACE_UnlockSurface(psurfPattern);
+       RtlCopyMemory(pvDIBits,
+                         (PVOID)DataPtr,
+                                 DIB_GetDIBImageBytes(BitmapInfo->bmiHeader.biWidth,
+                                        BitmapInfo->bmiHeader.biHeight,
+                                        BitmapInfo->bmiHeader.biBitCount * BitmapInfo->bmiHeader.biPlanes));
  
      pbrush = BRUSH_AllocBrushWithHandle();
      if (pbrush == NULL)
@@@ -455,7 -313,7 +313,7 @@@ IntGdiCreateHatchBrush
          return 0;
      }
  
-     hPattern = IntGdiCreateBitmap(8, 8, 1, 1, (LPBYTE)HatchBrushes[Style]);
+     hPattern = GreCreateBitmap(8, 8, 1, 1, (LPBYTE)HatchBrushes[Style]);
      if (hPattern == NULL)
      {
          SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
@@@ -28,27 -28,16 +28,16 @@@ CLIPPING_UpdateGCRegion(DC* Dc
     PROSRGNDATA CombinedRegion;
     HRGN hRgnVis = Dc->prgnVis->BaseObject.hHmgr;
  
-    /* Experiment with API region based on wine.. */
-    if (Dc->rosdc.hClipRgn && Dc->dclevel.prgnMeta)
+     // would prefer this, but the rest of the code sucks
+ //    ASSERT(Dc->rosdc.hGCClipRgn);
+ //    ASSERT(Dc->rosdc.hClipRgn);
+    if (!Dc->prgnVis)
     {
-       PROSRGNDATA pClipRgn;
-       if ((pClipRgn = RGNOBJAPI_Lock(Dc->rosdc.hClipRgn, NULL)))
-       {
-          if (!Dc->prgnAPI) Dc->prgnAPI = IntSysCreateRectpRgn( 0, 0, 0, 0 );
-          IntGdiCombineRgn( Dc->prgnAPI,
-                            pClipRgn,
-                            Dc->dclevel.prgnMeta,
-                            RGN_AND );
-          RGNOBJAPI_Unlock(pClipRgn);
-       }
+       DPRINT1("Warning, prgnVis is NULL!\n");
     }
     else
     {
-       if (Dc->prgnAPI)
-          GreDeleteObject(((PROSRGNDATA)Dc->prgnAPI)->BaseObject.hHmgr);
-       Dc->prgnAPI = NULL;
+        hRgnVis = Dc->prgnVis->BaseObject.hHmgr ;
     }
  
  
  
     NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, Dc->ptlDCOrig.x, Dc->ptlDCOrig.y);
  
-     if((CombinedRegion = RGNOBJAPI_Lock(Dc->rosdc.hGCClipRgn, NULL)))
-     {
-         CLIPOBJ *CombinedClip;
-       
-         CombinedClip = IntEngCreateClipRegion(CombinedRegion->rdh.nCount,
-                                               CombinedRegion->Buffer,
-                                               &CombinedRegion->rdh.rcBound);
+    if((CombinedRegion = RGNOBJAPI_Lock(Dc->rosdc.hGCClipRgn, NULL)))
+    {
+      CLIPOBJ *CombinedClip;
  
-         RGNOBJAPI_Unlock(CombinedRegion);
+      CombinedClip = IntEngCreateClipRegion(CombinedRegion->rdh.nCount,
+         CombinedRegion->Buffer,
+         &CombinedRegion->rdh.rcBound);
  
-         if (!CombinedClip)
-         {
-             DPRINT1("IntEngCreateClipRegion() failed\n");
-             return ERROR;
-         }
+      RGNOBJAPI_Unlock(CombinedRegion);
  
-         if (Dc->rosdc.CombinedClip != NULL)
-             IntEngDeleteClipRegion(Dc->rosdc.CombinedClip);
+      if ( !CombinedClip )
+      {
+        DPRINT1("IntEngCreateClipRegion() failed\n");
+        return ERROR;
+      }
  
-         Dc->rosdc.CombinedClip = CombinedClip;
-     }
+      if(Dc->rosdc.CombinedClip != NULL)
+        IntEngDeleteClipRegion(Dc->rosdc.CombinedClip);
  
+       Dc->rosdc.CombinedClip = CombinedClip ;
+    }
  
     return NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, -Dc->ptlDCOrig.x, -Dc->ptlDCOrig.y);
  }
@@@ -115,7 -103,6 +103,6 @@@ GdiSelectVisRgn(HDC hdc, HRGN hrgn
      NtGdiOffsetRgn(dc->prgnVis->BaseObject.hHmgr, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y);
      CLIPPING_UpdateGCRegion(dc);
    }
    DC_UnlockDc(dc);
  
    return retval;
@@@ -166,6 -153,7 +153,7 @@@ int FASTCALL GdiExtSelectClipRgn(PDC dc
      else
        NtGdiCombineRgn(dc->rosdc.hClipRgn, dc->rosdc.hClipRgn, hrgn, fnMode);
    }
    return CLIPPING_UpdateGCRegion(dc);
  }
  
@@@ -233,6 -221,7 +221,7 @@@ GdiGetClipBox(HDC hDC, PRECTL rc
        retval = REGION_GetRgnBox(pRgnNew, rc);
  
          REGION_FreeRgnByHandle(pRgnNew->BaseObject.hHmgr);
        DC_UnlockDc(dc);
          if(Unlock) REGION_UnlockRgn(pRgn);
        return retval;
@@@ -529,6 -518,7 +518,7 @@@ IntGdiSetMetaRgn(PDC pDC
    return Ret;
  }
  
  int APIENTRY NtGdiSetMetaRgn(HDC  hDC)
  {
    INT Ret;
@@@ -570,7 -560,7 +560,7 @@@ NEW_CLIPPING_UpdateGCRegion(PDC pDC
       IntGdiCombineRgn( pDC->prgnAPI,
                         pDC->dclevel.prgnClip,
                         pDC->dclevel.prgnMeta,
-                        RGN_AND );
+                        RGN_AND);
    }
    else
    {
          IntGdiCombineRgn( pDC->prgnAPI,
                            pDC->dclevel.prgnClip,
                            NULL,
-                           RGN_COPY );
+                           RGN_COPY);
       }
       else if (pDC->dclevel.prgnMeta)
       {
          IntGdiCombineRgn( pDC->prgnAPI,
                            pDC->dclevel.prgnMeta,
                            NULL,
-                           RGN_COPY );
+                           RGN_COPY);
       }
    }
  
    IntGdiCombineRgn( pDC->prgnRao,
                      pDC->prgnVis,
                      pDC->prgnAPI,
-                     RGN_AND );
+                     RGN_AND);
  
-   RtlCopyMemory( &pDC->erclClip,
-                  &((PROSRGNDATA)pDC->prgnRao)->rdh.rcBound,
-                  sizeof(RECTL));
+   RtlCopyMemory(&pDC->erclClip,
+                 &((PROSRGNDATA)pDC->prgnRao)->rdh.rcBound,
+                 sizeof(RECTL));
  
    pDC->fs &= ~DC_FLAG_DIRTY_RAO;
  
    IntGdiOffsetRgn(pDC->prgnRao, pDC->ptlDCOrig.x, pDC->ptlDCOrig.y);
  
    // pDC->co should be used. Example, CLIPOBJ_cEnumStart uses XCLIPOBJ to build
-   // the rects from region objects rects in pClipRgn->Buffer. 
+   // the rects from region objects rects in pClipRgn->Buffer.
    // With pDC->co.pClipRgn->Buffer,
    // pDC->co.pClipRgn = pDC->prgnRao ? pDC->prgnRao : pDC->prgnVis;
  
    co = IntEngCreateClipRegion( ((PROSRGNDATA)pDC->prgnRao)->rdh.nCount,
                                 ((PROSRGNDATA)pDC->prgnRao)->Buffer,
-                                &pDC->erclClip);
+                                  &pDC->erclClip);
    if (co)
    {
      if (pDC->rosdc.CombinedClip != NULL)
-      IntEngDeleteClipRegion(pDC->rosdc.CombinedClip);
+       IntEngDeleteClipRegion(pDC->rosdc.CombinedClip);
  
      pDC->rosdc.CombinedClip = co;
    }
@@@ -152,35 -152,49 +152,49 @@@ FreeDcAttr(PDC_ATTR pDc_Attr
    return;
  }
  
+ BOOL
+ FASTCALL
+ DC_AllocDcAttr(PDC pdc)
+ {
+     DC_AllocateDcAttr(pdc->BaseObject.hHmgr);
+     *pdc->pdcattr = pdc->dcattr;
+     return TRUE;
+ }
+ // CHECK against current head
  VOID
  FASTCALL
  DC_AllocateDcAttr(HDC hDC)
  {
    PVOID NewMem = NULL;
    PDC pDC;
+   HANDLE Pid = NtCurrentProcess();
+   ULONG MemSize = sizeof(DC_ATTR); //PAGE_SIZE it will allocate that size
+   NTSTATUS Status = ZwAllocateVirtualMemory(Pid,
+                                         &NewMem,
+                                               0,
+                                        &MemSize,
+                          MEM_COMMIT|MEM_RESERVE,
+                                  PAGE_READWRITE);
    {
      INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)hDC);
      PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
-     NewMem = AllocateDcAttr();
      // FIXME: dc could have been deleted!!! use GDIOBJ_InsertUserData
-     if (NewMem)
+     if (NT_SUCCESS(Status))
      {
-        RtlZeroMemory(NewMem, sizeof(DC_ATTR));
-        Entry->UserData = NewMem;
-        DPRINT("DC_ATTR allocated! 0x%x\n",NewMem);
+       RtlZeroMemory(NewMem, MemSize);
+       Entry->UserData  = NewMem;
+       DPRINT("DC_ATTR allocated! 0x%x\n",NewMem);
      }
      else
      {
-        DPRINT1("DC_ATTR not allocated!\n");
+        DPRINT("DC_ATTR not allocated!\n");
      }
    }
    pDC = DC_LockDc(hDC);
    ASSERT(pDC->pdcattr == &pDC->dcattr);
-   if (NewMem)
+   if(NewMem)
    {
       pDC->pdcattr = NewMem; // Store pointer
    }
  }
  
  VOID
- FASTCALL
- DC_FreeDcAttr(HDC  DCToFree )
+ NTAPI
+ DC_vFreeDcAttr(PDC pdc)
  {
-   PDC pDC = DC_LockDc(DCToFree);
-   if (pDC->pdcattr == &pDC->dcattr) return; // Internal DC object!
-   pDC->pdcattr = &pDC->dcattr;
-   DC_UnlockDc(pDC);
+     HANDLE Pid = NtCurrentProcess();
+     INT Index;
+     PGDI_TABLE_ENTRY pent;
  
-   {
-     INT Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)DCToFree);
-     PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
-     if (Entry->UserData)
+     if (pdc->pdcattr == &pdc->dcattr)
      {
-        FreeDcAttr(Entry->UserData);
-        Entry->UserData = NULL;
+         // Internal DC object!
+         return;
+     }
+     pdc->pdcattr = &pdc->dcattr;
+     Index = GDI_HANDLE_GET_INDEX(pdc->BaseObject.hHmgr);
+     pent = &GdiHandleTable->Entries[Index];
+     if(pent->UserData)
+     {
+         ULONG MemSize = sizeof(DC_ATTR);
+         NTSTATUS Status = ZwFreeVirtualMemory(Pid,
+                                               &pent->UserData,
+                                               &MemSize,
+                                               MEM_RELEASE);
+         if (!NT_SUCCESS(Status))
+         {
+             DPRINT1("DC_FreeDC failed to free DC_ATTR 0x%p\n", pent->UserData);
+             ASSERT(FALSE);
+         }
+         pent->UserData = NULL;
      }
-   }
  }
  
  
@@@ -218,12 -246,8 +246,8 @@@ CopytoUserDcAttr(PDC dc, PDC_ATTR pdcat
  
    _SEH2_TRY
    {
-       ProbeForWrite( pdcattr,
-              sizeof(DC_ATTR),
-                            1);
-       RtlCopyMemory( pdcattr,
-                 &dc->dcattr,
-              sizeof(DC_ATTR));
+       ProbeForWrite(pdcattr, sizeof(DC_ATTR), 1);
+       RtlCopyMemory(pdcattr, &dc->dcattr, sizeof(DC_ATTR));
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
  #define NDEBUG
  #include <debug.h>
  
- /** Internal functions ********************************************************/
+ //FIXME: windows uses 0x0012009f
+ #define DIRTY_DEFAULT DIRTY_CHARSET|DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL
  
- HDC FASTCALL
- DC_AllocDC(PUNICODE_STRING Driver)
- {
-     PDC  NewDC;
-     PDC_ATTR pdcattr;
-     HDC  hDC;
-     PWSTR Buf = NULL;
-     XFORM xformTemplate;
-     PBRUSH pbrush;
-     HSURF hsurf;
-     if (Driver != NULL)
-     {
-         Buf = ExAllocatePoolWithTag(PagedPool, Driver->MaximumLength, TAG_DC);
-         if (!Buf)
-         {
-             DPRINT1("ExAllocatePoolWithTag failed\n");
-             return NULL;
-         }
-         RtlCopyMemory(Buf, Driver->Buffer, Driver->MaximumLength);
-     }
+ PSURFACE psurfDefaultBitmap = NULL;
+ PBRUSH pbrDefaultBrush = NULL;
  
-     NewDC = (PDC)GDIOBJ_AllocObjWithHandle(GDI_OBJECT_TYPE_DC);
-     if (!NewDC)
-     {
-         if (Buf)
-         {
-             ExFreePoolWithTag(Buf, TAG_DC);
-         }
-         DPRINT1("GDIOBJ_AllocObjWithHandle failed\n");
-         return NULL;
-     }
+ // FIXME: these should go to floatobj.h or something
+ #define FLOATOBJ_0 {0x00000000, 0x00000000}
+ #define FLOATOBJ_1 {0x40000000, 0x00000002}
+ #define FLOATOBJ_16 {0x40000000, 0x00000006}
+ #define FLOATOBJ_1_16 {0x40000000, 0xfffffffe}
  
-     hDC = NewDC->BaseObject.hHmgr;
+ static const FLOATOBJ gef0 = FLOATOBJ_0;
+ static const FLOATOBJ gef1 = FLOATOBJ_1;
+ static const FLOATOBJ gef16 = FLOATOBJ_16;
  
-     NewDC->pdcattr = &NewDC->dcattr;
-     DC_AllocateDcAttr(hDC);
+ static const MATRIX   gmxWorldToDeviceDefault =
+ {
+     FLOATOBJ_16, FLOATOBJ_0,
+     FLOATOBJ_0, FLOATOBJ_16,
+     FLOATOBJ_0, FLOATOBJ_0,
+     0, 0, 0x4b
+ };
  
-     if (Driver != NULL)
-     {
-         RtlCopyMemory(&NewDC->rosdc.DriverName, Driver, sizeof(UNICODE_STRING));
-         NewDC->rosdc.DriverName.Buffer = Buf;
-     }
-     pdcattr = NewDC->pdcattr;
+ static const MATRIX   gmxDeviceToWorldDefault =
+ {
+     FLOATOBJ_1_16, FLOATOBJ_0,
+     FLOATOBJ_0, FLOATOBJ_1_16,
+     FLOATOBJ_0, FLOATOBJ_0,
+     0, 0, 0x53
+ };
  
-     // FIXME: no floating point in the kernel!
-     xformTemplate.eM11 = 1.0f;
-     xformTemplate.eM12 = 0.0f;
-     xformTemplate.eM21 = 0.0f;
-     xformTemplate.eM22 = 1.0f;
-     xformTemplate.eDx = 0.0f;
-     xformTemplate.eDy = 0.0f;
-     XForm2MatrixS(&NewDC->dclevel.mxWorldToDevice, &xformTemplate);
-     XForm2MatrixS(&NewDC->dclevel.mxDeviceToWorld, &xformTemplate);
-     XForm2MatrixS(&NewDC->dclevel.mxWorldToPage, &xformTemplate);
+ static const MATRIX   gmxWorldToPageDefault =
+ {
+     FLOATOBJ_1, FLOATOBJ_0,
+     FLOATOBJ_0, FLOATOBJ_1,
+     FLOATOBJ_0, FLOATOBJ_0,
+     0, 0, 0x63
+ };
  
-     // Setup syncing bits for the dcattr data packets.
-     pdcattr->flXform = DEVICE_TO_PAGE_INVALID;
+ // HACK!! Fix XFORMOBJ then use 1:16 / 16:1
+ #define gmxWorldToDeviceDefault gmxWorldToPageDefault
+ #define gmxDeviceToWorldDefault gmxWorldToPageDefault
  
-     pdcattr->ulDirty_ = 0;  // Server side
+ /** Internal functions ********************************************************/
  
-     pdcattr->iMapMode = MM_TEXT;
-     pdcattr->iGraphicsMode = GM_COMPATIBLE;
-     pdcattr->jFillMode = ALTERNATE;
+ NTSTATUS
+ InitDcImpl()
+ {
+     psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
+     if (!psurfDefaultBitmap)
+         return STATUS_UNSUCCESSFUL;
  
-     pdcattr->szlWindowExt.cx = 1; // Float to Int,,, WRONG!
-     pdcattr->szlWindowExt.cy = 1;
-     pdcattr->szlViewportExt.cx = 1;
-     pdcattr->szlViewportExt.cy = 1;
+     pbrDefaultBrush = BRUSH_ShareLockBrush(StockObjects[BLACK_BRUSH]);
+     if (!pbrDefaultBrush)
+         return STATUS_UNSUCCESSFUL;
  
-     pdcattr->crForegroundClr = 0;
-     pdcattr->ulForegroundClr = 0;
+     return STATUS_SUCCESS;
+ }
  
-     pdcattr->ulBackgroundClr = 0xffffff;
-     pdcattr->crBackgroundClr = 0xffffff;
  
-     pdcattr->ulPenClr = RGB(0, 0, 0);
-     pdcattr->crPenClr = RGB(0, 0, 0);
+ PDC
+ NTAPI
+ DC_AllocDcWithHandle()
+ {
+     PDC pdc;
+     pdc = (PDC)GDIOBJ_AllocObjWithHandle(GDILoObjType_LO_DC_TYPE);
  
-     pdcattr->ulBrushClr = RGB(255, 255, 255);   // Do this way too.
-     pdcattr->crBrushClr = RGB(255, 255, 255);
+     pdc->pdcattr = &pdc->dcattr;
  
- //// This fixes the default brush and pen settings. See DC_InitDC.
+     return pdc;
+ }
  
-     /* Create the default fill brush */
-     pdcattr->hbrush = NtGdiGetStockObject(WHITE_BRUSH);
-     NewDC->dclevel.pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush);
-     EBRUSHOBJ_vInit(&NewDC->eboFill, NewDC->dclevel.pbrFill, NewDC);
  
-     /* Create the default pen / line brush */
-     pdcattr->hpen = NtGdiGetStockObject(BLACK_PEN);
-     NewDC->dclevel.pbrLine = PEN_ShareLockPen(pdcattr->hpen);
-     EBRUSHOBJ_vInit(&NewDC->eboLine, NewDC->dclevel.pbrLine, NewDC);
+ void
+ DC_InitHack(PDC pdc)
+ {
+     TextIntRealizeFont(pdc->pdcattr->hlfntNew,NULL);
+     pdc->pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
  
-     /* Create the default text brush */
-     pbrush = BRUSH_ShareLockBrush(NtGdiGetStockObject(BLACK_BRUSH));
-     EBRUSHOBJ_vInit(&NewDC->eboText, pbrush, NewDC);
-     pdcattr->ulDirty_ |= DIRTY_TEXT;
+     /* This should never fail */
+     ASSERT(pdc->dclevel.ppal);
  
-     /* Create the default background brush */
-     pbrush = BRUSH_ShareLockBrush(NtGdiGetStockObject(WHITE_BRUSH));
-     EBRUSHOBJ_vInit(&NewDC->eboBackground, pbrush, NewDC);
+     /* Select regions */
+     pdc->rosdc.hClipRgn = NULL;
+     pdc->rosdc.hGCClipRgn = NULL;
+ }
  
-     pdcattr->hlfntNew = NtGdiGetStockObject(SYSTEM_FONT);
-     TextIntRealizeFont(pdcattr->hlfntNew,NULL);
-     NewDC->hlfntCur = pdcattr->hlfntNew;
-     NewDC->dclevel.plfnt = GDIOBJ_GetKernelObj(pdcattr->hlfntNew);
+ VOID
+ NTAPI
+ DC_vInitDc(
+     PDC pdc,
+     DCTYPE dctype,
+     PPDEVOBJ ppdev)
+ {
+     /* Setup some basic fields */
+     pdc->dctype = dctype;
+     pdc->ppdev = ppdev;
+     pdc->dhpdev = ppdev->dhpdev;
+     pdc->hsem = ppdev->hsemDevLock;
+     pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
+     pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
+     pdc->fs = DC_DIRTY_RAO;
+     /* Setup dc attribute */
+     pdc->pdcattr = &pdc->dcattr;
+     pdc->dcattr.pvLDC = NULL;
+     pdc->dcattr.ulDirty_ = DIRTY_DEFAULT;
+     if (ppdev == gppdevPrimary)
+         pdc->dcattr.ulDirty_ |= DC_PRIMARY_DISPLAY;
+     /* Setup the DC size */
+     if (dctype == DCTYPE_MEMORY)
+     {
+         /* Memory DCs have a 1 x 1 bitmap by default */
+         pdc->dclevel.sizl.cx = 1;
+         pdc->dclevel.sizl.cy = 1;
+     }
+     else
+     {
+         /* Other DC's are as big as the related PDEV */
+           pdc->dclevel.sizl.cx = ppdev->gdiinfo.ulHorzRes;
+           pdc->dclevel.sizl.cy = ppdev->gdiinfo.ulVertRes;
+     }
  
-     NewDC->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE);
-     NewDC->dclevel.ppal = PALETTE_ShareLockPalette(NewDC->dclevel.hpal);
-     /* This should never fail */
-     ASSERT(NewDC->dclevel.ppal);
+     /* Setup Window rect based on DC size */
+     pdc->erclWindow.left = 0;
+     pdc->erclWindow.top = 0;
+     pdc->erclWindow.right = pdc->dclevel.sizl.cx;
+     pdc->erclWindow.bottom = pdc->dclevel.sizl.cy;
  
-     NewDC->dclevel.laPath.eMiterLimit = 10.0; // FIXME: use FLOATL or FLOATOBJ!
+     if (dctype == DCTYPE_DIRECT)
+     {
+         /* Direct DCs get the surface from the PDEV */
+         pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
+         pdc->erclBounds.left = 0x7fffffff;
+         pdc->erclBounds.top = 0x7fffffff;
+         pdc->erclBounds.right = 0x80000000;
+         pdc->erclBounds.bottom = 0x80000000;
+         pdc->erclBoundsApp.left = 0xffffffff;
+         pdc->erclBoundsApp.top = 0xfffffffc;
+         pdc->erclBoundsApp.right = 0x00007ffc; // FIXME
+         pdc->erclBoundsApp.bottom = 0x00000333; // FIXME
+         pdc->erclClip = pdc->erclBounds;
+ //        pdc->co
+         pdc->fs |= DC_SYNCHRONIZEACCESS | DC_ACCUM_APP | DC_PERMANANT | DC_DISPLAY;
+     }
+     else
+     {
+         /* Non-direct DCs don't have a surface by default */
+         pdc->dclevel.pSurface = NULL;
  
-     NewDC->dclevel.lSaveDepth = 1;
+         // FIXME: HACK, because our code expects a surface
+         pdc->dclevel.pSurface = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
  
-     hsurf = (HBITMAP)PrimarySurface.pSurface; // <- what kind of haxx0ry is that?
-     NewDC->dclevel.pSurface = SURFACE_ShareLockSurface(hsurf);
+         pdc->erclBounds.left = 0;
+         pdc->erclBounds.top = 0;
+         pdc->erclBounds.right = 0;
+         pdc->erclBounds.bottom = 0;
+         pdc->erclBoundsApp = pdc->erclBounds;
+         pdc->erclClip = pdc->erclWindow;
+ //        pdc->co = NULL
+     }
  
+ //        pdc->dcattr.VisRectRegion:
+     /* Setup coordinate transformation data */
+       pdc->dclevel.mxWorldToDevice = gmxWorldToDeviceDefault;
+       pdc->dclevel.mxDeviceToWorld = gmxDeviceToWorldDefault;
+       pdc->dclevel.mxWorldToPage = gmxWorldToPageDefault;
+       pdc->dclevel.efM11PtoD = gef16;
+       pdc->dclevel.efM22PtoD = gef16;
+       pdc->dclevel.efDxPtoD = gef0;
+       pdc->dclevel.efDyPtoD = gef0;
+       pdc->dclevel.efM11_TWIPS = gef0;
+       pdc->dclevel.efM22_TWIPS = gef0;
+       pdc->dclevel.efPr11 = gef0;
+       pdc->dclevel.efPr22 = gef0;
+       pdc->dcattr.mxWorldToDevice = pdc->dclevel.mxWorldToDevice;
+       pdc->dcattr.mxDeviceToWorld = pdc->dclevel.mxDeviceToWorld;
+       pdc->dcattr.mxWorldToPage = pdc->dclevel.mxWorldToPage;
+       pdc->dcattr.efM11PtoD = pdc->dclevel.efM11PtoD;
+       pdc->dcattr.efM22PtoD = pdc->dclevel.efM22PtoD;
+       pdc->dcattr.efDxPtoD = pdc->dclevel.efDxPtoD;
+       pdc->dcattr.efDyPtoD = pdc->dclevel.efDyPtoD;
+       pdc->dcattr.iMapMode = MM_TEXT;
+       pdc->dcattr.dwLayout = 0;
+       pdc->dcattr.flXform = PAGE_TO_DEVICE_SCALE_IDENTITY |
+                             PAGE_TO_DEVICE_IDENTITY |
+                             WORLD_TO_PAGE_IDENTITY;
+     /* Setup more coordinates */
+     pdc->ptlDCOrig.x = 0;
+     pdc->ptlDCOrig.y = 0;
+       pdc->dcattr.lWindowOrgx = 0;
+       pdc->dcattr.ptlWindowOrg.x = 0;
+       pdc->dcattr.ptlWindowOrg.y = 0;
+       pdc->dcattr.szlWindowExt.cx = 1;
+       pdc->dcattr.szlWindowExt.cy = 1;
+       pdc->dcattr.ptlViewportOrg.x = 0;
+       pdc->dcattr.ptlViewportOrg.y = 0;
+       pdc->dcattr.szlViewportExt.cx = 1;
+       pdc->dcattr.szlViewportExt.cy = 1;
+     pdc->dcattr.szlVirtualDevicePixel.cx = ppdev->gdiinfo.ulHorzRes;
+     pdc->dcattr.szlVirtualDevicePixel.cy = ppdev->gdiinfo.ulVertRes;
+     pdc->dcattr.szlVirtualDeviceMm.cx = ppdev->gdiinfo.ulHorzSize;
+     pdc->dcattr.szlVirtualDeviceMm.cy = ppdev->gdiinfo.ulVertSize;
+     pdc->dcattr.szlVirtualDeviceSize.cx = 0;
+     pdc->dcattr.szlVirtualDeviceSize.cy = 0;
+     /* Setup regions */
+     pdc->prgnAPI = NULL;
+       pdc->prgnRao = NULL;
      /* Allocate a Vis region */
-     NewDC->prgnVis = IntSysCreateRectpRgn(0, 0, 1, 1);
-     if (!NewDC->prgnVis)
-     {
-         DPRINT1("IntSysCreateRectpRgn failed\n");
-         if (!GDIOBJ_FreeObjByHandle(hDC, GDI_OBJECT_TYPE_DC))
-         {
-             ASSERT(FALSE);
-         }
-         return NULL;
-     }
+     pdc->prgnVis = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
+       ASSERT(pdc->prgnVis);
+       GDIOBJ_CopyOwnership(pdc->BaseObject.hHmgr, pdc->prgnVis->BaseObject.hHmgr);
+     /* Setup palette */
+     pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE];
+     pdc->dclevel.ppal = PALETTE_ShareLockPalette(pdc->dclevel.hpal);
+     /* Setup path */
+       pdc->dclevel.hPath = NULL;
+     pdc->dclevel.flPath = 0;
+ //    pdc->dclevel.lapath:
+     /* Setup colors */
+       pdc->dcattr.crBackgroundClr = RGB(0xff, 0xff, 0xff);
+       pdc->dcattr.ulBackgroundClr = RGB(0xff, 0xff, 0xff);
+       pdc->dcattr.crForegroundClr = RGB(0, 0, 0);
+       pdc->dcattr.ulForegroundClr = RGB(0, 0, 0);
+       pdc->dcattr.crBrushClr = RGB(0xff, 0xff, 0xff);
+       pdc->dcattr.ulBrushClr = RGB(0xff, 0xff, 0xff);
+       pdc->dcattr.crPenClr = RGB(0, 0, 0);
+       pdc->dcattr.ulPenClr = RGB(0, 0, 0);
+     /* Select the default fill and line brush */
+       pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH];
+       pdc->dcattr.hpen = StockObjects[BLACK_PEN];
+     pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush);
+     pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen);
+       pdc->dclevel.ptlBrushOrigin.x = 0;
+       pdc->dclevel.ptlBrushOrigin.y = 0;
+       pdc->dcattr.ptlBrushOrigin = pdc->dclevel.ptlBrushOrigin;
+     /* Initialize EBRUSHOBJs */
+     EBRUSHOBJ_vInit(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
+     EBRUSHOBJ_vInit(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
+     EBRUSHOBJ_vInit(&pdc->eboText, pbrDefaultBrush, pdc);
+     EBRUSHOBJ_vInit(&pdc->eboBackground, pbrDefaultBrush, pdc);
+     /* Setup fill data */
+       pdc->dcattr.jROP2 = R2_COPYPEN;
+       pdc->dcattr.jBkMode = 2;
+       pdc->dcattr.lBkMode = 2;
+       pdc->dcattr.jFillMode = ALTERNATE;
+       pdc->dcattr.lFillMode = 1;
+       pdc->dcattr.jStretchBltMode = 1;
+       pdc->dcattr.lStretchBltMode = 1;
+     pdc->ptlFillOrigin.x = 0;
+     pdc->ptlFillOrigin.y = 0;
+     /* Setup drawing position */
+       pdc->dcattr.ptlCurrent.x = 0;
+       pdc->dcattr.ptlCurrent.y = 0;
+       pdc->dcattr.ptfxCurrent.x = 0;
+       pdc->dcattr.ptfxCurrent.y = 0;
+       /* Setup ICM data */
+       pdc->dclevel.lIcmMode = 0;
+       pdc->dcattr.lIcmMode = 0;
+       pdc->dcattr.hcmXform = NULL;
+       pdc->dcattr.flIcmFlags = 0;
+       pdc->dcattr.IcmBrushColor = CLR_INVALID;
+       pdc->dcattr.IcmPenColor = CLR_INVALID;
+       pdc->dcattr.pvLIcm = NULL;
+     pdc->dcattr.hColorSpace = NULL; // FIXME: 0189001f
+       pdc->dclevel.pColorSpace = NULL; // FIXME
+     pdc->pClrxFormLnk = NULL;
+ //    pdc->dclevel.ca =
+       /* Setup font data */
+     pdc->hlfntCur = NULL; // FIXME: 2f0a0cf8
+     pdc->pPFFList = NULL;
+     pdc->flSimulationFlags = 0;
+     pdc->lEscapement = 0;
+     pdc->prfnt = NULL;
+       pdc->dcattr.flFontMapper = 0;
+       pdc->dcattr.flTextAlign = 0;
+       pdc->dcattr.lTextAlign = 0;
+       pdc->dcattr.lTextExtra = 0;
+       pdc->dcattr.lRelAbs = 1;
+       pdc->dcattr.lBreakExtra = 0;
+       pdc->dcattr.cBreak = 0;
+     pdc->dcattr.hlfntNew = StockObjects[SYSTEM_FONT];
+ //    pdc->dclevel.pFont = LFONT_ShareLockFont(pdc->dcattr.hlfntNew);
+     /* Other stuff */
+     pdc->hdcNext = NULL;
+     pdc->hdcPrev = NULL;
+     pdc->ipfdDevMax = 0x0000ffff;
+     pdc->ulCopyCount = -1;
+     pdc->ptlDoBanding.x = 0;
+     pdc->ptlDoBanding.y = 0;
+       pdc->dclevel.lSaveDepth = 1;
+       pdc->dclevel.hdcSave = NULL;
+       pdc->dcattr.iGraphicsMode = GM_COMPATIBLE;
+       pdc->dcattr.iCS_CP = 0;
+     pdc->pSurfInfo = NULL;
  
-     return NewDC;
  }
  
- BOOL INTERNAL_CALL
+ BOOL
+ INTERNAL_CALL
  DC_Cleanup(PVOID ObjectBody)
  {
-     PDC pDC = (PDC)ObjectBody;
+     PDC pdc = (PDC)ObjectBody;
  
-     /* Free driver name (HACK) */
-     if (pDC->rosdc.DriverName.Buffer)
-         ExFreePoolWithTag(pDC->rosdc.DriverName.Buffer, TAG_DC);
+     /* Free DC_ATTR */
+     DC_vFreeDcAttr(pdc);
  
-     /* Deselect dc objects */
-     DC_vSelectSurface(pDC, NULL);
-     DC_vSelectFillBrush(pDC, NULL);
-     DC_vSelectLineBrush(pDC, NULL);
-     DC_vSelectPalette(pDC, NULL);
+     /* Delete saved DCs */
+     DC_vRestoreDC(pdc, 1);
  
-     /* Dereference default brushes */
-     if (pDC->eboText.pbrush)
-         BRUSH_ShareUnlockBrush(pDC->eboText.pbrush);
-     if (pDC->eboBackground.pbrush)
-         BRUSH_ShareUnlockBrush(pDC->eboBackground.pbrush);
+     /* Deselect dc objects */
+     DC_vSelectSurface(pdc, NULL);
+     DC_vSelectFillBrush(pdc, NULL);
+     DC_vSelectLineBrush(pdc, NULL);
+     DC_vSelectPalette(pdc, NULL);
  
      /* Cleanup the dc brushes */
-     EBRUSHOBJ_vCleanup(&pDC->eboFill);
-     EBRUSHOBJ_vCleanup(&pDC->eboLine);
-     EBRUSHOBJ_vCleanup(&pDC->eboText);
-     EBRUSHOBJ_vCleanup(&pDC->eboBackground);
+     EBRUSHOBJ_vCleanup(&pdc->eboFill);
+     EBRUSHOBJ_vCleanup(&pdc->eboLine);
+     EBRUSHOBJ_vCleanup(&pdc->eboText);
+     EBRUSHOBJ_vCleanup(&pdc->eboBackground);
+     /*  Free regions */
+     if (pdc->rosdc.hClipRgn)
+         GreDeleteObject(pdc->rosdc.hClipRgn);
+     if (pdc->prgnVis)
+         REGION_FreeRgnByHandle(pdc->prgnVis->BaseObject.hHmgr);
+     if (pdc->rosdc.hGCClipRgn)
+         GreDeleteObject(pdc->rosdc.hGCClipRgn);
+     if (NULL != pdc->rosdc.CombinedClip)
+         IntEngDeleteClipRegion(pdc->rosdc.CombinedClip);
+     PATH_Delete(pdc->dclevel.hPath);
+     if(pdc->dclevel.pSurface)
+         SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
+     PDEVOBJ_vRelease(pdc->ppdev) ;
  
      return TRUE;
  }
@@@ -186,205 -378,239 +378,239 @@@ DC_SetOwnership(HDC hDC, PEPROCESS Owne
      INT Index;
      PGDI_TABLE_ENTRY Entry;
      PDC pDC;
+     BOOL ret = FALSE;
+     if (!GDIOBJ_SetOwnership(hDC, Owner))
+     {
+         DPRINT1("GDIOBJ_SetOwnership failed\n");
+         return FALSE;
+     }
  
-     if (!GDIOBJ_SetOwnership(hDC, Owner)) return FALSE;
      pDC = DC_LockDc(hDC);
-     if (pDC)
+     if (!pDC)
      {
+         DPRINT1("Could not lock DC\n");
+         return FALSE;
+     }
      /*
         System Regions:
            These regions do not use attribute sections and when allocated, use
            gdiobj level functions.
      */
-         if (pDC->rosdc.hClipRgn)
-         {   // FIXME! HAX!!!
-             Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hClipRgn);
-             Entry = &GdiHandleTable->Entries[Index];
-             if (Entry->UserData) FreeObjectAttr(Entry->UserData);
-             Entry->UserData = NULL;
-             //
-             if (!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) return FALSE;
-         }
-         if (pDC->prgnVis)
-         {   // FIXME! HAX!!!
-             Index = GDI_HANDLE_GET_INDEX(pDC->prgnVis->BaseObject.hHmgr);
-             Entry = &GdiHandleTable->Entries[Index];
-             if (Entry->UserData) FreeObjectAttr(Entry->UserData);
-             Entry->UserData = NULL;
-             //
-             if (!GDIOBJ_SetOwnership(pDC->prgnVis->BaseObject.hHmgr, Owner)) return FALSE;
-         }
-         if (pDC->rosdc.hGCClipRgn)
-         {   // FIXME! HAX!!!
-             Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hGCClipRgn);
-             Entry = &GdiHandleTable->Entries[Index];
-             if (Entry->UserData) FreeObjectAttr(Entry->UserData);
-             Entry->UserData = NULL;
-             //
-             if (!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) return FALSE;
-         }
-         if (pDC->dclevel.hPath)
-         {
-             if (!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) return FALSE;
-         }
-         DC_UnlockDc(pDC);
+     if (pDC->rosdc.hClipRgn)
+     {   // FIXME! HAX!!!
+         Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hClipRgn);
+         Entry = &GdiHandleTable->Entries[Index];
+         if (Entry->UserData) FreeObjectAttr(Entry->UserData);
+         Entry->UserData = NULL;
+         //
+         if (!GDIOBJ_SetOwnership(pDC->rosdc.hClipRgn, Owner)) goto leave;
+     }
+     if (pDC->prgnVis)
+     {   // FIXME! HAX!!!
+         Index = GDI_HANDLE_GET_INDEX(pDC->prgnVis->BaseObject.hHmgr);
+         Entry = &GdiHandleTable->Entries[Index];
+         if (Entry->UserData) FreeObjectAttr(Entry->UserData);
+         Entry->UserData = NULL;
+         //
+         if (!GDIOBJ_SetOwnership(pDC->prgnVis->BaseObject.hHmgr, Owner)) goto leave;
+     }
+     if (pDC->rosdc.hGCClipRgn)
+     {   // FIXME! HAX!!!
+         Index = GDI_HANDLE_GET_INDEX(pDC->rosdc.hGCClipRgn);
+         Entry = &GdiHandleTable->Entries[Index];
+         if (Entry->UserData) FreeObjectAttr(Entry->UserData);
+         Entry->UserData = NULL;
+         //
+         if (!GDIOBJ_SetOwnership(pDC->rosdc.hGCClipRgn, Owner)) goto leave;
+     }
+     if (pDC->dclevel.hPath)
+     {
+         if (!GDIOBJ_SetOwnership(pDC->dclevel.hPath, Owner)) goto leave;
      }
+     ret = TRUE;
  
-     return TRUE;
+ leave:
+     DC_UnlockDc(pDC);
+     return ret;
  }
  
  
- HDC FASTCALL
- IntGdiCreateDC(
-     PUNICODE_STRING Driver,
-     PUNICODE_STRING Device,
-     PVOID pUMdhpdev,
-     CONST PDEVMODEW InitData,
-     BOOL CreateAsIC)
+ int FASTCALL
+ CLIPPING_UpdateGCRegion(DC* Dc);
+ static
+ void
+ DC_vUpdateDC(PDC pdc)
  {
-     HDC      hdc;
-     PDC      pdc;
-     PDC_ATTR pdcattr;
-     HRGN     hVisRgn;
-     UNICODE_STRING StdDriver;
-     BOOL calledFromUser;
+     HRGN hVisRgn ;
+     PPDEVOBJ ppdev = pdc->ppdev ;
+     pdc->dhpdev = ppdev->dhpdev;
  
-     RtlInitUnicodeString(&StdDriver, L"DISPLAY");
+     SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
+     pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
  
-     DPRINT("DriverName: %wZ, DeviceName: %wZ\n", Driver, Device);
+     PDEVOBJ_sizl(pdc->ppdev, &pdc->dclevel.sizl);
+     hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
+     ASSERT(hVisRgn);
+     GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
+     GreDeleteObject(hVisRgn);
  
-     if (NULL == Driver || 0 == RtlCompareUnicodeString(Driver, &StdDriver, TRUE))
+     pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
+     pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
+     /* Mark EBRUSHOBJs as dirty */
+     pdc->pdcattr->ulDirty_ |= DIRTY_DEFAULT ;
+ }
+ /* Prepare a blit for up to 2 DCs */
+ /* rc1 and rc2 are the rectangles where we want to draw or
+  * from where we take pixels. */
+ VOID
+ FASTCALL
+ DC_vPrepareDCsForBlit(PDC pdc1,
+                       RECT rc1,
+                       PDC pdc2,
+                       RECT rc2)
+ {
+     PDC pdcFirst, pdcSecond;
+     PRECT prcFirst, prcSecond;
+     /* Lock them in good order */
+     if(pdc2)
      {
-         if (CreateAsIC)
+         if((ULONG_PTR)pdc1->ppdev->hsemDevLock >= (ULONG_PTR)pdc2->ppdev->hsemDevLock)
          {
-             if (! IntPrepareDriverIfNeeded())
-             {
-                 /* Here, we have two possibilities:
-                  * a) return NULL, and hope that the caller
-                  *    won't call us in a loop
-                  * b) bugcheck, but caller is unable to
-                  *    react on the problem
-                  */
-                 /*DPRINT1("Unable to prepare graphics driver, returning NULL ic\n");
-                 return NULL;*/
-                 KeBugCheck(VIDEO_DRIVER_INIT_FAILURE);
-             }
+             pdcFirst = pdc1;
+             prcFirst = &rc1;
+             pdcSecond = pdc2;
+             prcSecond = &rc2;
          }
          else
          {
-             calledFromUser = UserIsEntered();
-             if (!calledFromUser)
-             {
-                 UserEnterExclusive();
-             }
-             if (! co_IntGraphicsCheck(TRUE))
-             {
-                 if (!calledFromUser)
-                 {
-                     UserLeave();
-                 }
-                 DPRINT1("Unable to initialize graphics, returning NULL dc\n");
-                 return NULL;
-             }
-             if (!calledFromUser)
-             {
-                 UserLeave();
-             }
+             pdcFirst = pdc2;
+             prcFirst = &rc2;
+             pdcSecond = pdc1;
+             prcSecond = &rc1;
          }
      }
-     /*  Check for existing DC object  */
-     if ((hdc = DC_FindOpenDC(Driver)) != NULL)
+     else
      {
-         hdc = NtGdiCreateCompatibleDC(hdc);
-         if (!hdc)
-             DPRINT1("NtGdiCreateCompatibleDC() failed\n");
-         return hdc;
+         pdcFirst = pdc1 ;
+         prcFirst = &rc1;
+         pdcSecond = NULL ;
      }
  
-     /*  Allocate a DC object  */
-     pdc = DC_AllocDC(Driver);
-     if (pdc == NULL)
+     if(pdcFirst && pdcFirst->dctype == DCTYPE_DIRECT)
      {
-         DPRINT1("DC_AllocDC() failed\n");
-         return NULL;
+         EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock);
+         MouseSafetyOnDrawStart(pdcFirst->ppdev,
+                                     prcFirst->left,
+                                     prcFirst->top,
+                                     prcFirst->right,
+                                     prcFirst->bottom) ;
+         /* Update surface if needed */
+         if(pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface)
+         {
+             DC_vUpdateDC(pdcFirst);
+         }
      }
-     hdc = pdc->BaseObject.hHmgr;
-     pdcattr = pdc->pdcattr;
-     pdc->dctype = DC_TYPE_DIRECT;
-     pdc->dhpdev = PrimarySurface.dhpdev;
-     if (pUMdhpdev) pUMdhpdev = pdc->dhpdev; // set DHPDEV for device.
-     pdc->ppdev = (PVOID)&PrimarySurface;
-     // ATM we only have one display.
-     pdcattr->ulDirty_ |= DC_PRIMARY_DISPLAY;
-     pdc->flGraphicsCaps  = PrimarySurface.devinfo.flGraphicsCaps;
-     pdc->flGraphicsCaps2 = PrimarySurface.devinfo.flGraphicsCaps2;
-     pdc->dclevel.hpal = NtGdiGetStockObject(DEFAULT_PALETTE);
-     pdcattr->jROP2 = R2_COPYPEN;
+     if(pdcSecond && pdcSecond->dctype == DCTYPE_DIRECT)
+     {
+         EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock);
+         MouseSafetyOnDrawStart(pdcSecond->ppdev,
+                                     prcSecond->left,
+                                     prcSecond->top,
+                                     prcSecond->right,
+                                     prcSecond->bottom) ;
+         /* Update surface if needed */
+         if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface)
+         {
+             DC_vUpdateDC(pdcSecond);
+         }
+     }
+ }
  
-     pdc->erclWindow.top = pdc->erclWindow.left = 0;
-     pdc->erclWindow.right  = pdc->ppdev->gdiinfo.ulHorzRes;
-     pdc->erclWindow.bottom = pdc->ppdev->gdiinfo.ulVertRes;
-     pdc->dclevel.flPath &= ~DCPATH_CLOCKWISE; // Default is CCW.
+ /* Finishes a blit for one or two DCs */
+ VOID
+ FASTCALL
+ DC_vFinishBlit(PDC pdc1, PDC pdc2)
+ {
+     if(pdc1->dctype == DCTYPE_DIRECT)
+     {
+         MouseSafetyOnDrawEnd(pdc1->ppdev);
+         EngReleaseSemaphore(pdc1->ppdev->hsemDevLock);
+     }
  
-     pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
+     if(pdc2)
+     {
+         if(pdc2->dctype == DCTYPE_DIRECT)
+         {
+             MouseSafetyOnDrawEnd(pdc2->ppdev);
+             EngReleaseSemaphore(pdc2->ppdev->hsemDevLock);
+         }
+     }
+ }
  
-     hVisRgn = IntSysCreateRectRgn(0, 0, pdc->ppdev->gdiinfo.ulHorzRes,
-                                  pdc->ppdev->gdiinfo.ulVertRes);
+ HDC
+ NTAPI
+ GreOpenDCW(
+     PUNICODE_STRING pustrDevice,
+     DEVMODEW *pdmInit,
+     PUNICODE_STRING pustrLogAddr,
+     ULONG iType,
+     BOOL bDisplay,
+     HANDLE hspool,
+     VOID *pDriverInfo2,
+     VOID *pUMdhpdev)
+ {
+     PPDEVOBJ ppdev;
+     PDC pdc;
+     HDC hdc;
  
-     if (!CreateAsIC)
-     {
-         pdc->pSurfInfo = NULL;
- //    pdc->dclevel.pSurface =
-         DC_UnlockDc(pdc);
+     DPRINT("GreOpenDCW(%S, iType=%ld)\n",
+            pustrDevice ? pustrDevice->Buffer : NULL, iType);
  
-         /*  Initialize the DC state  */
-         IntGdiSetTextColor(hdc, RGB(0, 0, 0));
-         IntGdiSetBkColor(hdc, RGB(255, 255, 255));
-     }
-     else
+     /* Get a PDEVOBJ for the device */
+     ppdev = EngpGetPDEV(pustrDevice);
+     if (!ppdev)
      {
-         /* From MSDN2:
-            The CreateIC function creates an information context for the specified device.
-            The information context provides a fast way to get information about the
-            device without creating a device context (DC). However, GDI drawing functions
-            cannot accept a handle to an information context.
-          */
-         pdc->dctype = DC_TYPE_INFO;
- //    pdc->pSurfInfo =
- //        DC_vSelectSurface(pdc, NULL);
-         pdcattr->crBackgroundClr = pdcattr->ulBackgroundClr = RGB(255, 255, 255);
-         pdcattr->crForegroundClr = RGB(0, 0, 0);
-         DC_UnlockDc(pdc);
+         DPRINT1("Didn't find a suitable PDEV\n");
+         return NULL;
      }
-     DC_InitDC(hdc);
  
-     if (hVisRgn)
+     DPRINT("GreOpenDCW - ppdev = %p\n", ppdev);
+     pdc = DC_AllocDcWithHandle();
+     if (!pdc)
      {
-         GdiSelectVisRgn(hdc, hVisRgn);
-         REGION_FreeRgnByHandle(hVisRgn);
+         DPRINT1("Could not Allocate a DC\n");
+         PDEVOBJ_vRelease(ppdev);
+         return NULL;
      }
+     hdc = pdc->BaseObject.hHmgr;
+     /* Lock ppdev and initialize the new DC */
+     DC_vInitDc(pdc, iType, ppdev);
+     /* FIXME: HACK! */
+     DC_InitHack(pdc);
+     DC_AllocDcAttr(pdc);
+     DC_UnlockDc(pdc);
  
-     IntGdiSetTextAlign(hdc, TA_TOP);
-     IntGdiSetBkMode(hdc, OPAQUE);
+     DPRINT("returning hdc = %p\n", hdc);
  
      return hdc;
  }
  
HDC APIENTRY
+ HDC
+ APIENTRY
  NtGdiOpenDCW(
-     PUNICODE_STRING Device,
-     DEVMODEW *InitData,
+     PUNICODE_STRING pustrDevice,
+     DEVMODEW *pdmInit,
      PUNICODE_STRING pustrLogAddr,
      ULONG iType,
      BOOL bDisplay,
      VOID *pDriverInfo2,
      VOID *pUMdhpdev)
  {
-     UNICODE_STRING SafeDevice;
-     DEVMODEW SafeInitData;
-     PVOID Dhpdev;
-     HDC Ret;
-     NTSTATUS Status = STATUS_SUCCESS;
-     if (!Device) return UserGetDesktopDC(iType,FALSE,TRUE);
-     if (InitData)
+     UNICODE_STRING ustrDevice;
+     WCHAR awcDevice[CCHDEVICENAME];
+     DEVMODEW dmInit;
+     PVOID dhpdev;
+     HDC hdc;
+     /* Only if a devicename is given, we need any data */
+     if (pustrDevice)
      {
+         /* Initialize destination string */
+         RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
          _SEH2_TRY
          {
+             /* Probe the UNICODE_STRING and the buffer */
+             ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
+             ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
+             /* Copy the string */
+             RtlCopyUnicodeString(&ustrDevice, pustrDevice);
+             if (pdmInit)
+             {
+                 /* FIXME: could be larger */
+                 ProbeForRead(pdmInit, sizeof(DEVMODEW), 1);
+                 RtlCopyMemory(&dmInit, pdmInit, sizeof(DEVMODEW));
+             }
              if (pUMdhpdev)
              {
-                 ProbeForWrite(pUMdhpdev, sizeof(PVOID), 1);
+                 ProbeForWrite(pUMdhpdev, sizeof(HANDLE), 1);
              }
-             ProbeForRead(InitData, sizeof(DEVMODEW), 1);
-             RtlCopyMemory(&SafeInitData, InitData, sizeof(DEVMODEW));
          }
          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
          {
-             Status = _SEH2_GetExceptionCode();
+             SetLastNtError(_SEH2_GetExceptionCode());
+             _SEH2_YIELD(return NULL);
          }
-         _SEH2_END;
+         _SEH2_END
+     }
+     else
+     {
+         pdmInit = NULL;
+         pUMdhpdev = NULL;
+     }
  
-         if (!NT_SUCCESS(Status))
+     /* FIXME: HACK! */
+     if (pustrDevice)
+     {
+         UNICODE_STRING ustrDISPLAY = RTL_CONSTANT_STRING(L"DISPLAY");
+         if (RtlEqualUnicodeString(&ustrDevice, &ustrDISPLAY, TRUE))
          {
-             SetLastNtError(Status);
-             return NULL;
+             pustrDevice = NULL;
          }
-         /* FIXME - InitData can have some more bytes! */
      }
  
-     if (Device)
+     /* Call the internal function */
+     hdc = GreOpenDCW(pustrDevice ? &ustrDevice : NULL,
+                      pdmInit ? &dmInit : NULL,
+                      NULL, // fixme pwszLogAddress
+                      iType,
+                      bDisplay,
+                      hspool,
+                      NULL, //FIXME: pDriverInfo2
+                      pUMdhpdev ? &dhpdev : NULL);
+     /* If we got a HDC and a UM dhpdev is requested,... */
+     if (hdc && pUMdhpdev)
      {
-         Status = IntSafeCopyUnicodeString(&SafeDevice, Device);
-         if (!NT_SUCCESS(Status))
+         /* Copy dhpdev to caller (FIXME: use dhpdev?? */
+         _SEH2_TRY
          {
-             SetLastNtError(Status);
-             return NULL;
+             /* Pointer was already probed */
+             *(HANDLE*)pUMdhpdev = dhpdev;
          }
+         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+         {
+             /* Ignore error */
+         }
+         _SEH2_END
      }
  
-     Ret = IntGdiCreateDC(Device ? &SafeDevice : NULL,
-                          NULL,
-                          pUMdhpdev ? &Dhpdev : NULL,
-                          InitData ? &SafeInitData : NULL,
-                          (BOOL) iType); // FALSE 0 DCW, TRUE 1 ICW
-     // FIXME!!!!
-     if (pUMdhpdev) pUMdhpdev = Dhpdev;
-     return Ret;
+     return hdc;
  }
  
- HDC FASTCALL
- IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC)
+ HDC
+ APIENTRY
+ NtGdiCreateCompatibleDC(HDC hdc)
  {
-     HDC hDC;
-     UNICODE_STRING DriverName;
-     RtlInitUnicodeString(&DriverName, L"DISPLAY");
+     HDC hdcNew;
+     PPDEVOBJ ppdev;
+     PDC pdc, pdcNew;
  
-     if (DcType != DC_TYPE_MEMORY)
-         hDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, (DcType == DC_TYPE_INFO));
-     else
-         hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth!
- //
- // There is room to grow here~
- //
- //
- // If NULL, first time through! Build the default (was window) dc!
- // Setup clean DC state for the system.
- //
-     if (hDC && !defaultDCstate) // Ultra HAX! Dedicated to GvG!
-     { // This is a cheesy way to do this.
-         PDC dc = DC_LockDc(hDC);
-         HSURF hsurf;
-         defaultDCstate = ExAllocatePoolWithTag(PagedPool, sizeof(DC), TAG_DC);
-         if (!defaultDCstate)
+     DPRINT("NtGdiCreateCompatibleDC(0x%p)\n", hdc);
+     /* Did the caller provide a DC? */
+     if (hdc)
+     {
+         /* Yes, try to lock it */
+         pdc = DC_LockDc(hdc);
+         if (!pdc)
          {
-             DC_UnlockDc(dc);
+             DPRINT1("Could not lock source DC %p\n", hdc);
              return NULL;
          }
-         RtlZeroMemory(defaultDCstate, sizeof(DC));
-         defaultDCstate->pdcattr = &defaultDCstate->dcattr;
-         hsurf = (HSURF)PrimarySurface.pSurface; // HAX²
-         defaultDCstate->dclevel.pSurface = SURFACE_ShareLockSurface(hsurf);
-         DC_vCopyState(dc, defaultDCstate, TRUE);
-         DC_UnlockDc(dc);
+         /* Get the pdev from the DC */
+         ppdev = pdc->ppdev;
+         InterlockedIncrement(&ppdev->cPdevRefs);
+         /* Unlock the source DC */
+         DC_UnlockDc(pdc);
      }
-     return hDC;
+     else
+     {
+         /* No DC given, get default device */
+         ppdev = EngpGetPDEV(NULL);
+     }
+     if (!ppdev)
+     {
+         DPRINT1("Didn't find a suitable PDEV\n");
+         return NULL;
+     }
+     /* Allocate a new DC */
+     pdcNew = DC_AllocDcWithHandle();
+     if (!pdcNew)
+     {
+         DPRINT1("Could not allocate a new DC\n");
+         PDEVOBJ_vRelease(ppdev);
+         return NULL;
+     }
+     hdcNew = pdcNew->BaseObject.hHmgr;
+     /* Lock ppdev and initialize the new DC */
+     DC_vInitDc(pdcNew, DCTYPE_MEMORY, ppdev);
+     /* FIXME: HACK! */
+     DC_InitHack(pdcNew);
+     /* Allocate a dc attribute */
+     DC_AllocDcAttr(pdcNew);
+     // HACK!
+     DC_vSelectSurface(pdcNew, psurfDefaultBitmap);
+     DC_UnlockDc(pdcNew);
+     DPRINT("Leave NtGdiCreateCompatibleDC hdcNew = %p\n", hdcNew);
+     return hdcNew;
  }
  
  BOOL
@@@ -500,102 -786,69 +786,69 @@@ IntGdiDeleteDC(HDC hDC, BOOL Force
  
      if (!Force)
      {
+         /* Windows permits NtGdiDeleteObjectApp to delete a permanent DC
+          * For some reason, it's still a valid handle, pointing to some kernel data.
+          * Not sure if this is a bug, a feature, some cache stuff... Who knows?
+          * See NtGdiDeleteObjectApp test for details */
          if (DCToDelete->fs & DC_FLAG_PERMANENT)
          {
-             DPRINT1("No! You Naughty Application!\n");
              DC_UnlockDc(DCToDelete);
-             return UserReleaseDC(NULL, hDC, FALSE);
+             if(UserReleaseDC(NULL, hDC, FALSE))
+             {
+                 /* ReactOs feature : call UserReleaseDC
+                  * I don't think windows does it.
+                  * Still, complain, no one should ever call DeleteDC
+                  * on a window DC */
+                  DPRINT1("No, you naughty application!\n");
+                  return TRUE;
+             }
+             else
+             {
+                 /* This is not a window owned DC.
+                  * Force its deletion */
+                 return IntGdiDeleteDC(hDC, TRUE);
+             }
          }
      }
  
-     /*  First delete all saved DCs  */
-     while (DCToDelete->dclevel.lSaveDepth > 1)
-     {
-         PDC  savedDC;
-         HDC  savedHDC;
+     DC_UnlockDc(DCToDelete);
  
-         savedHDC = DCToDelete->hdcNext;
-         savedDC = DC_LockDc(savedHDC);
-         if (savedDC == NULL)
+     if (!IsObjectDead(hDC))
+     {
+         if (!GDIOBJ_FreeObjByHandle(hDC, GDI_OBJECT_TYPE_DC))
          {
-             break;
+             DPRINT1("DC_FreeDC failed\n");
          }
-         DCToDelete->hdcNext = savedDC->hdcNext;
-         DCToDelete->dclevel.lSaveDepth--;
-         DC_UnlockDc(savedDC);
-         IntGdiDeleteDC(savedHDC, Force);
-     }
-     /*  Free GDI resources allocated to this DC  */
-     if (!(DCToDelete->dclevel.flPath & DCPATH_SAVESTATE))
-     {
-         /*
-         NtGdiSelectPen (DCHandle, STOCK_BLACK_PEN);
-         NtGdiSelectBrush (DCHandle, STOCK_WHITE_BRUSH);
-         NtGdiSelectFont (DCHandle, STOCK_SYSTEM_FONT);
-         DC_LockDC (DCHandle); NtGdiSelectXxx does not recognize stock objects yet  */
-     }
-     if (DCToDelete->rosdc.hClipRgn)
-     {
-         GreDeleteObject(DCToDelete->rosdc.hClipRgn);
-     }
-     if (DCToDelete->prgnVis)
-     {
-         GreDeleteObject(DCToDelete->prgnVis->BaseObject.hHmgr);
-     }
-     if (NULL != DCToDelete->rosdc.CombinedClip)
-     {
-         IntEngDeleteClipRegion(DCToDelete->rosdc.CombinedClip);
-     }
-     if (DCToDelete->rosdc.hGCClipRgn)
-     {
-         GreDeleteObject(DCToDelete->rosdc.hGCClipRgn);
-     }
-     if (DCToDelete->dclevel.prgnMeta)
-     {
-        GreDeleteObject(((PROSRGNDATA)DCToDelete->dclevel.prgnMeta)->BaseObject.hHmgr);
      }
-     if (DCToDelete->prgnAPI)
+     else
      {
-        GreDeleteObject(((PROSRGNDATA)DCToDelete->prgnAPI)->BaseObject.hHmgr);
+         DPRINT1("Attempted to Delete 0x%x currently being destroyed!!!\n", hDC);
      }
-     PATH_Delete(DCToDelete->dclevel.hPath);
-     DC_UnlockDc(DCToDelete);
-     GreDeleteObject(hDC);
+     
      return TRUE;
  }
  
- HDC FASTCALL
- DC_FindOpenDC(PUNICODE_STRING  Driver)
+ BOOL
+ APIENTRY
+ NtGdiDeleteObjectApp(HANDLE DCHandle)
  {
-     return NULL;
- }
+     /* Complete all pending operations */
+     NtGdiFlushUserBatch();
  
- /*!
-  * Initialize some common fields in the Device Context structure.
- */
- VOID FASTCALL
- DC_InitDC(HDC  DCHandle)
- {
- //  NtGdiRealizeDefaultPalette(DCHandle);
+     if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
  
- ////  Removed for now.. See above brush and pen.
- //  NtGdiSelectBrush(DCHandle, NtGdiGetStockObject( WHITE_BRUSH ));
- //  NtGdiSelectPen(DCHandle, NtGdiGetStockObject( BLACK_PEN ));
- ////
-     //NtGdiSelectFont(DCHandle, hFont);
+     if (GDI_HANDLE_GET_TYPE(DCHandle) != GDI_OBJECT_TYPE_DC)
+         return GreDeleteObject((HGDIOBJ) DCHandle);
  
-     /*
-       {
-         int res;
-         res = CLIPPING_UpdateGCRegion(DCToInit);
-         ASSERT ( res != ERROR );
-       }
-     */
+     if (IsObjectDead((HGDIOBJ)DCHandle)) return TRUE;
+     if (!GDIOBJ_OwnedByCurrentProcess(DCHandle))
+     {
+         SetLastWin32Error(ERROR_INVALID_HANDLE);
+         return FALSE;
+     }
  
-     /* Set virtual resolution */
-     NtGdiSetVirtualResolution(DCHandle, 0, 0, 0, 0);
+     return IntGdiDeleteDC(DCHandle, FALSE);
  }
  
  BOOL
@@@ -618,7 -871,7 +871,7 @@@ MakeInfoDC(PDC pdc, BOOL bSet
          pdc->dctype = DC_TYPE_INFO;
          pdc->dclevel.pSurface = NULL;
  
-         PDEV_sizl(pdc->ppdev, &sizl);
+         PDEVOBJ_sizl(pdc->ppdev, &sizl);
  
          if ( sizl.cx == pdc->dclevel.sizl.cx &&
               sizl.cy == pdc->dclevel.sizl.cy )
@@@ -669,132 -922,42 +922,42 @@@ NtGdiMakeInfoDC
      return FALSE;
  }
  
- HDC APIENTRY
- NtGdiCreateCompatibleDC(HDC hDC)
- {
-     PDC pdcNew, pdcOld;
-     PDC_ATTR pdcattrNew, pdcattrOld;
-     HDC hdcNew, DisplayDC = NULL;
-     UNICODE_STRING DriverName;
-     DWORD Layout = 0;
-     HSURF hsurf;
-     if (hDC == NULL)
-     {
-         RtlInitUnicodeString(&DriverName, L"DISPLAY");
-         DisplayDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, TRUE);
-         if (NULL == DisplayDC)
-         {
-             DPRINT1("Failed to create DisplayDC\n");
-             return NULL;
-         }
-         hDC = DisplayDC;
-     }
-     /*  Allocate a new DC based on the original DC's device  */
-     pdcOld = DC_LockDc(hDC);
-     if (NULL == pdcOld)
-     {
-         if (NULL != DisplayDC)
-         {
-             NtGdiDeleteObjectApp(DisplayDC);
-         }
-         DPRINT1("Failed to lock hDC\n");
-         return NULL;
-     }
-     pdcNew = DC_AllocDC(&pdcOld->rosdc.DriverName);
-     if (!pdcNew)
-     {
-         DPRINT1("Failed to create pdcNew\n");
-         DC_UnlockDc(pdcOld);
-         if (DisplayDC)
-         {
-             NtGdiDeleteObjectApp(DisplayDC);
-         }
-         return  NULL;
-     }
-     hdcNew = pdcNew->BaseObject.hHmgr;
-     pdcattrOld = pdcOld->pdcattr;
-     pdcattrNew = pdcNew->pdcattr;
-     /* Copy information from original DC to new DC  */
-     pdcNew->dclevel.hdcSave = hdcNew;
-     pdcNew->dhpdev = pdcOld->dhpdev;
-     /* DriverName is copied in the AllocDC routine  */
-     pdcattrNew->ptlWindowOrg   = pdcattrOld->ptlWindowOrg;
-     pdcattrNew->szlWindowExt   = pdcattrOld->szlWindowExt;
-     pdcattrNew->ptlViewportOrg = pdcattrOld->ptlViewportOrg;
-     pdcattrNew->szlViewportExt = pdcattrOld->szlViewportExt;
-     pdcNew->dctype        = DC_TYPE_MEMORY; // Always!
-     hsurf      = NtGdiGetStockObject(DEFAULT_BITMAP);
-     pdcNew->dclevel.pSurface = SURFACE_ShareLockSurface(hsurf);
-     pdcNew->ppdev          = pdcOld->ppdev;
-     pdcNew->dclevel.hpal    = pdcOld->dclevel.hpal;
-     pdcattrNew->lTextAlign      = pdcattrOld->lTextAlign;
-     pdcattrNew->lBkMode         = pdcattrOld->lBkMode;
-     pdcattrNew->jBkMode         = pdcattrOld->jBkMode;
-     pdcattrNew->jROP2           = pdcattrOld->jROP2;
-     pdcattrNew->dwLayout        = pdcattrOld->dwLayout;
-     if (pdcattrOld->dwLayout & LAYOUT_ORIENTATIONMASK) Layout = pdcattrOld->dwLayout;
-     pdcNew->dclevel.flPath     = pdcOld->dclevel.flPath;
-     pdcattrNew->ulDirty_        = pdcattrOld->ulDirty_;
-     pdcattrNew->iCS_CP          = pdcattrOld->iCS_CP;
-     pdcNew->erclWindow.left = pdcNew->erclWindow.top = 0;
-     pdcNew->erclWindow.right = pdcNew->erclWindow.bottom = 1;
  
-     DC_UnlockDc(pdcNew);
-     DC_UnlockDc(pdcOld);
-     if (NULL != DisplayDC)
-     {
-         NtGdiDeleteObjectApp(DisplayDC);
-     }
-     if (Layout) NtGdiSetLayout(hdcNew, -1, Layout);
+ HDC FASTCALL
+ IntGdiCreateDC(
+     PUNICODE_STRING Driver,
+     PUNICODE_STRING pustrDevice,
+     PVOID pUMdhpdev,
+     CONST PDEVMODEW pdmInit,
+     BOOL CreateAsIC)
+ {
+     HDC hdc;
+     hdc = GreOpenDCW(pustrDevice,
+                      pdmInit,
+                      NULL,
+                      CreateAsIC ? DCTYPE_INFO :
+                           (Driver ? DC_TYPE_DIRECT : DC_TYPE_DIRECT),
+                      TRUE,
+                      NULL,
+                      NULL,
+                      pUMdhpdev);
  
-     DC_InitDC(hdcNew);
-     return hdcNew;
+     return hdc;
  }
  
- BOOL
- APIENTRY
- NtGdiDeleteObjectApp(HANDLE DCHandle)
+ HDC FASTCALL
+ IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC)
  {
-   GDIOBJTYPE ObjType;
-   /* Complete all pending operations */
-   NtGdiFlushUserBatch();
-   if (GDI_HANDLE_IS_STOCKOBJ(DCHandle)) return TRUE;
-   if (IsObjectDead((HGDIOBJ)DCHandle)) return TRUE;
-   ObjType = GDI_OBJECT_GET_TYPE_INDEX((ULONG_PTR)DCHandle);
-   if (GreGetObjectOwner( DCHandle, ObjType))
-   {
-      switch(ObjType)
-      {
-         case GDIObjType_DC_TYPE:
-           return IntGdiDeleteDC(DCHandle, FALSE);
+     HDC hDC;
+     UNIMPLEMENTED;
+     ASSERT(FALSE);
  
-         case GDIObjType_RGN_TYPE:
-         case GDIObjType_SURF_TYPE:
-         case GDIObjType_PAL_TYPE:
-         case GDIObjType_LFONT_TYPE:
-         case GDIObjType_BRUSH_TYPE:
-           return GreDeleteObject((HGDIOBJ) DCHandle);
+     if (DcType == DC_TYPE_MEMORY)
+         hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth!
+     else
+         hDC = IntGdiCreateDC(NULL, NULL, NULL, NULL, (DcType == DC_TYPE_INFO));
  
-         default:
-           return FALSE;
-      }
-   }
-   return (DCHandle != NULL);
+     return hDC;
  }
  
@@@ -110,8 -110,10 +110,10 @@@ DC_vUpdateTextBrush(PDC pdc
  {
      PDC_ATTR pdcattr = pdc->pdcattr;
  
+     /* Timo : The text brush should never be changed.
+      * Jérôme : Yeah, but its palette must be updated anyway! */
      if(pdcattr->ulDirty_ & DIRTY_TEXT)
-         EBRUSHOBJ_vUpdate(&pdc->eboText, pdc->eboText.pbrush, pdc);
+         EBRUSHOBJ_vUpdate(&pdc->eboText, pbrDefaultBrush, pdc);
  
      /* Update the eboText's solid color */
      EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboText, pdcattr->crForegroundClr);
@@@ -127,7 -129,7 +129,7 @@@ DC_vUpdateBackgroundBrush(PDC pdc
      PDC_ATTR pdcattr = pdc->pdcattr;
  
      if(pdcattr->ulDirty_ & DIRTY_BACKGROUND)
-         EBRUSHOBJ_vUpdate(&pdc->eboBackground, pdc->eboBackground.pbrush, pdc);
+         EBRUSHOBJ_vUpdate(&pdc->eboBackground, pbrDefaultBrush, pdc);
  
      /* Update the eboBackground's solid color */
      EBRUSHOBJ_vSetSolidBrushColor(&pdc->eboBackground, pdcattr->crBackgroundClr);
@@@ -164,7 -166,7 +166,7 @@@ GdiSelectPalette
  
      /* Is this a valid palette for this depth? */
        if ((BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) <= 8
-                                       && ppal->Mode == PAL_INDEXED) ||
+                                       && (ppal->flFlags & PAL_INDEXED)) ||
                        (BitsPerFormat(pdc->dclevel.pSurface->SurfObj.iBitmapFormat) > 8))
      {
          /* Get old palette, set new one */
@@@ -282,14 -284,24 +284,24 @@@ NtGdiSelectBitmap
      }
  
      /* Get the handle for the old bitmap */
-     psurfOld = pDC->dclevel.pSurface;
-     hOrgBmp = psurfOld ? psurfOld->BaseObject.hHmgr : NULL;
+     ASSERT(pDC->dclevel.pSurface);
+     hOrgBmp = pDC->dclevel.pSurface->BaseObject.hHmgr;
+       /* Lock it, to be sure while we mess with it*/
+       psurfOld = SURFACE_LockSurface(hOrgBmp);
+       /* Reset hdc, this surface isn't selected anymore */
+       psurfOld->hdc = NULL;
  
      /* Release the old bitmap, reference the new */
      DC_vSelectSurface(pDC, psurfBmp);
  
+       /* And unlock it, now we're done */
+       SURFACE_UnlockSurface(psurfOld);
      // If Info DC this is zero and pSurface is moved to DC->pSurfInfo.
-     psurfBmp->hDC = hDC;
+     psurfBmp->hdc = hDC;
  
      /* FIXME; improve by using a region without a handle and selecting it */
      hVisRgn = IntSysCreateRectRgn( 0,
@@@ -356,6 -368,7 +368,7 @@@ NtGdiSelectClipPath
      if (pPath->state != PATH_Closed)
      {
          SetLastWin32Error(ERROR_CAN_NOT_COMPLETE);
+         DC_UnlockDc(pdc);
          return FALSE;
      }
  
@@@ -15,9 -15,14 +15,14 @@@ VOI
  FASTCALL
  DC_vCopyState(PDC pdcSrc, PDC pdcDst, BOOL To)
  {
+     DPRINT("DC_vCopyState(%p, %p)\n", pdcSrc->BaseObject.hHmgr, pdcDst->BaseObject.hHmgr);
      /* Copy full DC attribute */
      *pdcDst->pdcattr = *pdcSrc->pdcattr;
-     
+     /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
+     /* The VisRectRegion field needs to be set to a valid state */
      /* Mark some fields as dirty */
      pdcDst->pdcattr->ulDirty_ |= 0x0012001f; // Note: Use if, To is FALSE....
  
@@@ -36,7 -41,6 +41,6 @@@
      pdcDst->dclevel.hpal            = pdcSrc->dclevel.hpal;
  
      /* Handle references here correctly */
-     DC_vSelectSurface(pdcDst, pdcSrc->dclevel.pSurface);
      DC_vSelectFillBrush(pdcDst, pdcSrc->dclevel.pbrFill);
      DC_vSelectLineBrush(pdcDst, pdcSrc->dclevel.pbrLine);
      DC_vSelectPalette(pdcDst, pdcSrc->dclevel.ppal);
@@@ -91,53 -95,35 +95,35 @@@ NtGdiResetDC
  }
  
  
- BOOL
- APIENTRY
NtGdiRestoreDC(
-     HDC hdc,
+ VOID
+ NTAPI
DC_vRestoreDC(
+     IN PDC pdc,
      INT iSaveLevel)
  {
-     PDC pdc, pdcSave;
+     PEPROCESS pepCurrentProcess;
      HDC hdcSave;
+     PDC pdcSave;
  
-     DPRINT("NtGdiRestoreDC(%lx, %d)\n", hdc, iSaveLevel);
+     ASSERT(iSaveLevel > 0);
+     DPRINT("DC_vRestoreDC(%p, %ld)\n", pdc->BaseObject.hHmgr, iSaveLevel);
  
-     /* Lock the original DC */
-     pdc = DC_LockDc(hdc);
-     if (!pdc)
-     {
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return FALSE;
-     }
-     ASSERT(pdc->dclevel.lSaveDepth > 0);
-     /* Negative values are relative to the stack top */
-     if (iSaveLevel < 0)
-         iSaveLevel = pdc->dclevel.lSaveDepth + iSaveLevel;
-     /* Check if we have a valid instance */
-     if (iSaveLevel <= 0 || iSaveLevel >= pdc->dclevel.lSaveDepth)
-     {
-         DPRINT("Illegal save level, requested: %ld, current: %ld\n",
-                iSaveLevel, pdc->dclevel.lSaveDepth);
-         DC_UnlockDc(pdc);
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
-         return FALSE;
-     }
+     /* Get current process */
+     pepCurrentProcess = PsGetCurrentProcess();
  
      /* Loop the save levels */
      while (pdc->dclevel.lSaveDepth > iSaveLevel)
      {
          hdcSave = pdc->dclevel.hdcSave;
+         DPRINT("RestoreDC = %p\n", hdcSave);
  
          /* Set us as the owner */
-         if (!IntGdiSetDCOwnerEx(hdcSave, GDI_OBJ_HMGR_POWNED, FALSE ))
+         if (!GDIOBJ_SetOwnership(hdcSave, pepCurrentProcess))
          {
              /* Could not get ownership. That's bad! */
-             DPRINT1("Could not get ownership of saved DC (%p) for dc %p!\n",
-                     hdcSave, hdc);
-             return FALSE;
+             DPRINT1("Could not get ownership of saved DC (%p) for hdc %p!\n",
+                     hdcSave, pdc->BaseObject.hHmgr);
+             return;// FALSE;
          }
  
          /* Lock the saved dc */
          {
              /* WTF? Internal error! */
              DPRINT1("Could not lock the saved DC (%p) for dc %p!\n",
-                     hdcSave, hdc);
-             DC_UnlockDc(pdc);
-             return FALSE;
+                     hdcSave, pdc->BaseObject.hHmgr);
+             return;// FALSE;
          }
  
          /* Remove the saved dc from the queue */
              /* Copy the state back */
              DC_vCopyState(pdcSave, pdc, FALSE);
  
+             /* Only memory DC's change their surface */
+             if (pdc->dctype == DCTYPE_MEMORY)
+                 DC_vSelectSurface(pdc, pdcSave->dclevel.pSurface);
              // Restore Path by removing it, if the Save flag is set.
              // BeginPath will takecare of the rest.
              if (pdc->dclevel.hPath && pdc->dclevel.flPath & DCPATH_SAVE)
                  pdc->dclevel.hPath = 0;
                  pdc->dclevel.flPath &= ~DCPATH_SAVE;
              }
-             // Attempt to plug the leak!
-             if (pdcSave->rosdc.hClipRgn)
-             {
-                DPRINT("Have hClipRgn!\n");
-                REGION_FreeRgnByHandle(pdcSave->rosdc.hClipRgn);
-             }
-             // FIXME! Handle prgnMeta!
          }
  
+         /* Prevent save dc from being restored */
+         pdcSave->dclevel.lSaveDepth = 1;
+         /* Unlock it */
+         DC_UnlockDc(pdcSave);
          /* Delete the saved dc */
          GreDeleteObject(hdcSave);
      }
  
+     DPRINT("Leave DC_vRestoreDC()\n");
+ }
+ BOOL
+ APIENTRY
+ NtGdiRestoreDC(
+     HDC hdc,
+     INT iSaveLevel)
+ {
+     PDC pdc;
+     DPRINT("NtGdiRestoreDC(%p, %d)\n", hdc, iSaveLevel);
+     /* Lock the original DC */
+     pdc = DC_LockDc(hdc);
+     if (!pdc)
+     {
+         SetLastWin32Error(ERROR_INVALID_HANDLE);
+         return FALSE;
+     }
+     ASSERT(pdc->dclevel.lSaveDepth > 0);
+     /* Negative values are relative to the stack top */
+     if (iSaveLevel < 0)
+         iSaveLevel = pdc->dclevel.lSaveDepth + iSaveLevel;
+     /* Check if we have a valid instance */
+     if (iSaveLevel <= 0 || iSaveLevel >= pdc->dclevel.lSaveDepth)
+     {
+         DPRINT("Illegal save level, requested: %ld, current: %ld\n",
+                iSaveLevel, pdc->dclevel.lSaveDepth);
+         DC_UnlockDc(pdc);
+         SetLastWin32Error(ERROR_INVALID_PARAMETER);
+         return FALSE;
+     }
+     /* Call the internal function */
+     DC_vRestoreDC(pdc, iSaveLevel);
      DC_UnlockDc(pdc);
  
-     DPRINT("Leaving NtGdiRestoreDC\n");
+     DPRINT("Leave NtGdiRestoreDC\n");
      return TRUE;
  }
  
@@@ -200,7 -229,7 +229,7 @@@ NtGdiSaveDC
      PDC pdc, pdcSave;
      INT lSaveDepth;
  
-     DPRINT("NtGdiSaveDC(%lx)\n", hDC);
+     DPRINT("NtGdiSaveDC(%p)\n", hDC);
  
      /* Lock the original dc */
      pdc = DC_LockDc(hDC);
      }
  
      /* Allocate a new dc */
-     pdcSave = DC_AllocDC(NULL);
+     pdcSave = DC_AllocDcWithHandle();
      if (pdcSave == NULL)
      {
          DPRINT("Could not allocate a new DC\n");
      }
      hdcSave = pdcSave->BaseObject.hHmgr;
  
-     /* Copy the current state */
-     DC_vCopyState(pdc, pdcSave, TRUE);
+     InterlockedIncrement(&pdc->ppdev->cPdevRefs);
+     DC_vInitDc(pdcSave, DCTYPE_MEMORY, pdc->ppdev);
+     /* Handle references here correctly */
+ //    pdcSrc->dclevel.pSurface = NULL;
+ //    pdcSrc->dclevel.pbrFill = NULL;
+ //    pdcSrc->dclevel.pbrLine = NULL;
+ //    pdcSrc->dclevel.ppal = NULL;
  
      /* Make it a kernel handle
         (FIXME: windows handles this different, see wiki)*/
-     IntGdiSetDCOwnerEx(hdcSave, GDI_OBJ_HMGR_NONE, FALSE);
+     GDIOBJ_SetOwnership(hdcSave, NULL);
+     /* Copy the current state */
+     DC_vCopyState(pdc, pdcSave, TRUE);
+     /* Only memory DC's change their surface */
+     if (pdc->dctype == DCTYPE_MEMORY)
+         DC_vSelectSurface(pdcSave, pdc->dclevel.pSurface);
  
      /* Copy path. FIXME: why this way? */
      pdcSave->dclevel.hPath = pdc->dclevel.hPath;
      DC_UnlockDc(pdcSave);
      DC_UnlockDc(pdc);
  
-     DPRINT("Leave NtGdiSaveDC: %ld\n", lSaveDepth);
+     DPRINT("Leave NtGdiSaveDC: %ld, hdcSave = %p\n", lSaveDepth, hdcSave);
      return lSaveDepth;
  }
  
@@@ -145,7 -145,7 +145,7 @@@ IntSetDefaultRegion(PDC pdc
      if (pdc->ppdev->flFlags & PDEV_META_DEVICE)
      {
          pSurface = pdc->dclevel.pSurface;
-         if (pSurface && pSurface->flFlags & PDEV_SURFACE)
+         if (pSurface && pSurface->flags & PDEV_SURFACE)
          {
              rclClip.left   += pdc->ppdev->ptlOrigion.x;
              rclClip.top    += pdc->ppdev->ptlOrigion.y;
  #define NDEBUG
  #include <debug.h>
  
- // TODO: proper implementation of LDEVOBJ and PDEVOBJ interface
- /*static*/ PDEVOBJ PrimarySurface;
- PPDEVOBJ pPrimarySurface = &PrimarySurface;
- static KEVENT VideoDriverNeedsPreparation;
- static KEVENT VideoDriverPrepared;
  PDC defaultDCstate = NULL;
  
- PSIZEL
- FASTCALL
- PDEV_sizl(PPDEVOBJ ppdev, PSIZEL psizl)
- {
-     if (ppdev->flFlags & PDEV_META_DEVICE)
-     {
-         psizl->cx = ppdev->ulHorzRes;
-         psizl->cy = ppdev->ulVertRes;
-     }
-     else
-     {
-         psizl->cx = ppdev->gdiinfo.ulHorzRes;
-         psizl->cy = ppdev->gdiinfo.ulVertRes;
-     }
-     return psizl;
- }
- NTSTATUS FASTCALL
- InitDcImpl(VOID)
- {
-     KeInitializeEvent(&VideoDriverNeedsPreparation, SynchronizationEvent, TRUE);
-     KeInitializeEvent(&VideoDriverPrepared, NotificationEvent, FALSE);
-     return STATUS_SUCCESS;
- }
- static BOOLEAN FASTCALL
- GetRegistryPath(PUNICODE_STRING RegistryPath, ULONG DisplayNumber)
- {
-     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
-     WCHAR DeviceNameBuffer[20];
-     NTSTATUS Status;
-     swprintf(DeviceNameBuffer, L"\\Device\\Video%lu", DisplayNumber);
-     RtlInitUnicodeString(RegistryPath, NULL);
-     RtlZeroMemory(QueryTable, sizeof(QueryTable));
-     QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
-     QueryTable[0].Name = DeviceNameBuffer;
-     QueryTable[0].EntryContext = RegistryPath;
-     Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
-                                     L"VIDEO",
-                                     QueryTable,
-                                     NULL,
-                                     NULL);
-     if (! NT_SUCCESS(Status))
-     {
-         DPRINT1("No \\Device\\Video%lu value in DEVICEMAP\\VIDEO found\n", DisplayNumber);
-         return FALSE;
-     }
-     DPRINT("RegistryPath %wZ\n", RegistryPath);
-     return TRUE;
- }
- NTSTATUS
- NTAPI
- EnumDisplayQueryRoutine(IN PWSTR ValueName,
-                         IN ULONG ValueType,
-                         IN PVOID ValueData,
-                         IN ULONG ValueLength,
-                         IN PVOID Context,
-                         IN PVOID EntryContext)
- {
-     if ((Context == NULL) && ((ValueType == REG_SZ) || (ValueType == REG_MULTI_SZ)))
-     {
-         *(PULONG)EntryContext = ValueLength;
-     }
-     else
-     {
-         DPRINT1("Value data: %S %d\n", ValueData, ValueLength);
-         RtlCopyMemory(Context, ValueData, ValueLength);
-     }
-     return STATUS_SUCCESS;
- }
- static BOOL FASTCALL
- FindDriverFileNames(PUNICODE_STRING DriverFileNames, ULONG DisplayNumber)
- {
-     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
-     UNICODE_STRING RegistryPath;
-     NTSTATUS Status;
-     PWCHAR DriverNames = NULL;
-     ULONG Length = 0;
-     if (! GetRegistryPath(&RegistryPath, DisplayNumber))
-     {
-         DPRINT("GetRegistryPath failed\n");
-         return FALSE;
-     }
-     RtlZeroMemory(QueryTable, sizeof(QueryTable));
-     QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
-     QueryTable[0].Name = L"InstalledDisplayDrivers";
-     QueryTable[0].EntryContext = &Length;
-     QueryTable[0].QueryRoutine = EnumDisplayQueryRoutine;
-     Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
-                                     RegistryPath.Buffer,
-                                     QueryTable,
-                                     NULL,
-                                     NULL);
-  //   DPRINT1("Status: %lx\n", Status);
-     if (Length)
-     {
-         DriverNames = ExAllocatePoolWithTag(PagedPool, Length, TAG_DRIVER);
-        // DPRINT1("Length allocated: %d\n", Length);
-         Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
-                                         RegistryPath.Buffer,
-                                         QueryTable,
-                                         DriverNames,
-                                         NULL);
-         if (!NT_SUCCESS(Status)) DriverNames = NULL;
-     }
-     ExFreePoolWithTag(RegistryPath.Buffer, TAG_RTLREGISTRY);
-     if (! NT_SUCCESS(Status))
-     {
-         DPRINT1("No InstalledDisplayDrivers value in service entry found\n");
-         return FALSE;
-     }
-     
-     RtlInitUnicodeString(DriverFileNames, DriverNames);
-     DriverFileNames->Length = Length;
-     DriverFileNames->MaximumLength = Length;
-     //DPRINT1("DriverFileNames %wZ\n", DriverFileNames);
-     return TRUE;
- }
- static NTSTATUS APIENTRY
- DevModeCallback(IN PWSTR ValueName,
-                 IN ULONG ValueType,
-                 IN PVOID ValueData,
-                 IN ULONG ValueLength,
-                 IN PVOID Context,
-                 IN PVOID EntryContext)
- {
-     PDEVMODEW DevMode = (PDEVMODEW) Context;
-     DPRINT("Found registry value for name %S: type %d, length %d\n",
-            ValueName, ValueType, ValueLength);
-     if (REG_DWORD == ValueType && sizeof(DWORD) == ValueLength)
-     {
-         if (0 == _wcsicmp(ValueName, L"DefaultSettings.BitsPerPel"))
-         {
-             DevMode->dmBitsPerPel = *((DWORD *) ValueData);
-         }
-         else if (0 == _wcsicmp(ValueName, L"DefaultSettings.Flags"))
-         {
-             DevMode->dmDisplayFlags = *((DWORD *) ValueData);
-         }
-         else if (0 == _wcsicmp(ValueName, L"DefaultSettings.VRefresh"))
-         {
-             DevMode->dmDisplayFrequency = *((DWORD *) ValueData);
-         }
-         else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XPanning"))
-         {
-             DevMode->dmPanningWidth = *((DWORD *) ValueData);
-         }
-         else if (0 == _wcsicmp(ValueName, L"DefaultSettings.XResolution"))
-         {
-             DevMode->dmPelsWidth = *((DWORD *) ValueData);
-         }
-         else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YPanning"))
-         {
-             DevMode->dmPanningHeight = *((DWORD *) ValueData);
-         }
-         else if (0 == _wcsicmp(ValueName, L"DefaultSettings.YResolution"))
-         {
-             DevMode->dmPelsHeight = *((DWORD *) ValueData);
-         }
-     }
-     return STATUS_SUCCESS;
- }
- static BOOL FASTCALL
- SetupDevMode(PDEVMODEW DevMode, ULONG DisplayNumber)
- {
-     UNICODE_STRING RegistryPath;
-     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
-     NTSTATUS Status;
-     BOOLEAN Valid = TRUE;
-     if (!GetRegistryPath(&RegistryPath, DisplayNumber))
-     {
-         DPRINT("GetRegistryPath failed\n");
-         return FALSE;
-     }
-     RtlZeroMemory(QueryTable, sizeof(QueryTable));
-     QueryTable[0].QueryRoutine = DevModeCallback;
-     QueryTable[0].Flags = 0;
-     QueryTable[0].Name = NULL;
-     QueryTable[0].EntryContext = NULL;
-     QueryTable[0].DefaultType = REG_NONE;
-     QueryTable[0].DefaultData = NULL;
-     QueryTable[0].DefaultLength = 0;
-     Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
-                                     RegistryPath.Buffer,
-                                     QueryTable,
-                                     DevMode,
-                                     NULL);
-     if (! NT_SUCCESS(Status))
-     {
-         DPRINT("RtlQueryRegistryValues for %wZ failed with status 0x%08x\n",
-                &RegistryPath, Status);
-         Valid = FALSE;
-     }
-     else
-     {
-         DPRINT("dmBitsPerPel %d dmDisplayFrequency %d dmPelsWidth %d dmPelsHeight %d\n",
-                DevMode->dmBitsPerPel, DevMode->dmDisplayFrequency,
-                DevMode->dmPelsWidth, DevMode->dmPelsHeight);
-         if (0 == DevMode->dmBitsPerPel || 0 == DevMode->dmDisplayFrequency
-                 || 0 == DevMode->dmPelsWidth || 0 == DevMode->dmPelsHeight)
-         {
-             DPRINT("Not all required devmode members are set\n");
-             Valid = FALSE;
-         }
-     }
-     ExFreePoolWithTag(RegistryPath.Buffer, TAG_RTLREGISTRY);
-     if (! Valid)
-     {
-         RtlZeroMemory(DevMode, sizeof(DEVMODEW));
-     }
-     return Valid;
- }
- static BOOL FASTCALL
- IntPrepareDriver(VOID)
- {
-     PFN_DrvEnableDriver GDEnableDriver;
-     DRVENABLEDATA DED;
-     UNICODE_STRING DriverFileNames;
-     PWSTR CurrentName;
-     BOOL GotDriver;
-     BOOL DoDefault;
-     ULONG DisplayNumber;
-     LARGE_INTEGER Zero;
-     BOOLEAN ret = FALSE;
-     Zero.QuadPart = 0;
-     if (STATUS_SUCCESS != KeWaitForSingleObject(&VideoDriverNeedsPreparation, Executive, KernelMode, TRUE, &Zero))
-     {
-         /* Concurrent access. Wait for VideoDriverPrepared event */
-         if (STATUS_SUCCESS == KeWaitForSingleObject(&VideoDriverPrepared, Executive, KernelMode, TRUE, NULL))
-             ret = PrimarySurface.PreparedDriver;
-         goto cleanup;
-     }
-     // HAX! Fixme so I can support more than one! So how many?
-     for (DisplayNumber = 0; ; DisplayNumber++)
-     {
-         DPRINT("Trying to load display driver no. %d\n", DisplayNumber);
-         RtlZeroMemory(&PrimarySurface, sizeof(PrimarySurface));
- //      if (!pPrimarySurface) pPrimarySurface = ExAllocatePoolWithTag(PagedPool, gdwDirectDrawContext + sizeof(PDEVOBJ), TAG_GDIPDEV);
-         PrimarySurface.VideoFileObject = DRIVER_FindMPDriver(DisplayNumber);
-         /* Open the miniport driver  */
-         if (PrimarySurface.VideoFileObject == NULL)
-         {
-             DPRINT1("FindMPDriver failed\n");
-             goto cleanup;
-         }
-         /* Retrieve DDI driver names from registry */
-         RtlInitUnicodeString(&DriverFileNames, NULL);
-         if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
-         {
-             DPRINT1("FindDriverFileNames failed\n");
-             continue;
-         }
-         /*
-          * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
-          * scan all of them until a good one found.
-          */
-         CurrentName = DriverFileNames.Buffer;
-         GotDriver = FALSE;
-         while (!GotDriver &&
-                 CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
-         {
-             /* Get the DDI driver's entry point */
-             GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
-             if (NULL == GDEnableDriver)
-             {
-                 DPRINT("FindDDIDriver failed for %S\n", CurrentName);
-             }
-             else
-             {
-                 /*  Call DDI driver's EnableDriver function  */
-                 RtlZeroMemory(&DED, sizeof(DED));
-                 if (! GDEnableDriver(DDI_DRIVER_VERSION_NT5_01, sizeof(DED), &DED))
-                 {
-                     DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
-                 }
-                 else
-                 {
-                     GotDriver = TRUE;
-                 }
-             }
-             if (! GotDriver)
-             {
-                 /* Skip to the next name but never get past the Unicode string */
-                 while (L'\0' != *CurrentName &&
-                         CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
-                 {
-                     CurrentName++;
-                 }
-                 if (CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR)))
-                 {
-                     CurrentName++;
-                 }
-             }
-         }
-         if (!GotDriver)
-         {
-             ObDereferenceObject(PrimarySurface.VideoFileObject);
-             ExFreePoolWithTag(DriverFileNames.Buffer, TAG_RTLREGISTRY);
-             DPRINT1("No suitable DDI driver found\n");
-             continue;
-         }
-         DPRINT1("Display driver %S loaded\n", CurrentName);
-         ExFreePoolWithTag(DriverFileNames.Buffer, TAG_RTLREGISTRY);
-         DPRINT("Building DDI Functions\n");
-         /* Construct DDI driver function dispatch table */
-         if (!DRIVER_BuildDDIFunctions(&DED, &PrimarySurface.DriverFunctions))
-         {
-             ObDereferenceObject(PrimarySurface.VideoFileObject);
-             DPRINT1("BuildDDIFunctions failed\n");
-             goto cleanup;
-         }
-         /* Allocate a phyical device handle from the driver */
-         // Support DMW.dmSize + DMW.dmDriverExtra & Alloc DMW then set prt pdmwDev.
-         PrimarySurface.DMW.dmSize = sizeof (PrimarySurface.DMW);
-         if (SetupDevMode(&PrimarySurface.DMW, DisplayNumber))
-         {
-             PrimarySurface.dhpdev = PrimarySurface.DriverFunctions.EnablePDEV(
-                                        &PrimarySurface.DMW,
-                                        L"",
-                                        HS_DDI_MAX,
-                                        PrimarySurface.ahsurf,
-                                        sizeof(PrimarySurface.gdiinfo),
-                                        &PrimarySurface.gdiinfo,
-                                        sizeof(PrimarySurface.devinfo),
-                                        &PrimarySurface.devinfo,
-                                        NULL,
-                                        L"",
-                                        (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
-             DoDefault = (NULL == PrimarySurface.dhpdev);
-             if (DoDefault)
-             {
-                 DPRINT1("DrvEnablePDev with registry parameters failed\n");
-             }
-         }
-         else
-         {
-             DoDefault = TRUE;
-         }
-         if (DoDefault)
-         {
-             RtlZeroMemory(&(PrimarySurface.DMW), sizeof(DEVMODEW));
-             PrimarySurface.DMW.dmSize = sizeof (PrimarySurface.DMW);
-             PrimarySurface.dhpdev = PrimarySurface.DriverFunctions.EnablePDEV(
-                                        &PrimarySurface.DMW,
-                                        L"",
-                                        HS_DDI_MAX,
-                                        PrimarySurface.ahsurf,
-                                        sizeof(PrimarySurface.gdiinfo),
-                                        &PrimarySurface.gdiinfo,
-                                        sizeof(PrimarySurface.devinfo),
-                                        &PrimarySurface.devinfo,
-                                        NULL,
-                                        L"",
-                                        (HANDLE) (PrimarySurface.VideoFileObject->DeviceObject));
-             if (NULL == PrimarySurface.dhpdev)
-             {
-                 ObDereferenceObject(PrimarySurface.VideoFileObject);
-                 DPRINT1("DrvEnablePDEV with default parameters failed\n");
-                 DPRINT1("Perhaps DDI driver doesn't match miniport driver?\n");
-                 continue;
-             }
-             // Update the primary surface with what we really got
-             PrimarySurface.DMW.dmPelsWidth = PrimarySurface.gdiinfo.ulHorzRes;
-             PrimarySurface.DMW.dmPelsHeight = PrimarySurface.gdiinfo.ulVertRes;
-             PrimarySurface.DMW.dmBitsPerPel = PrimarySurface.gdiinfo.cBitsPixel;
-             PrimarySurface.DMW.dmDisplayFrequency = PrimarySurface.gdiinfo.ulVRefresh;
-         }
-         if (!PrimarySurface.DMW.dmDriverExtra)
-         {
-             PrimarySurface.pdmwDev = &PrimarySurface.DMW; // HAX!
-         }
-         else
-         {
-             DPRINT1("WARNING!!! Need to Alloc DMW !!!!!!\n");
-         }
-         // Dont remove until we finish testing other drivers.
-         if (PrimarySurface.DMW.dmDriverExtra != 0)
-         {
-             DPRINT1("**** DMW extra = %u bytes. Please report to ros-dev@reactos.org ****\n", PrimarySurface.DMW.dmDriverExtra);
-         }
-         if (0 == PrimarySurface.gdiinfo.ulLogPixelsX)
-         {
-             DPRINT("Adjusting gdiinfo.ulLogPixelsX\n");
-             PrimarySurface.gdiinfo.ulLogPixelsX = 96;
-         }
-         if (0 == PrimarySurface.gdiinfo.ulLogPixelsY)
-         {
-             DPRINT("Adjusting gdiinfo.ulLogPixelsY\n");
-             PrimarySurface.gdiinfo.ulLogPixelsY = 96;
-         }
-         PrimarySurface.Pointer.Exclude.right = -1;
-         DPRINT("calling completePDev\n");
-         /* Complete initialization of the physical device */
-         PrimarySurface.DriverFunctions.CompletePDEV(
-             PrimarySurface.dhpdev,
-             (HDEV)&PrimarySurface);
-         DPRINT("calling DRIVER_ReferenceDriver\n");
-         DRIVER_ReferenceDriver(L"DISPLAY");
-         PrimarySurface.PreparedDriver = TRUE;
-         PrimarySurface.DisplayNumber = DisplayNumber;
-         PrimarySurface.flFlags = PDEV_DISPLAY; // Hard set,, add more flags.
-         PrimarySurface.hsemDevLock = (PERESOURCE)EngCreateSemaphore();
-         // Should be null,, but make sure for now.
-         PrimarySurface.pvGammaRamp = NULL;
-         PrimarySurface.ppdevNext = NULL;    // Fixme! We need to support more than display drvs.
-         PrimarySurface.ppdevParent = NULL;  // Always NULL if primary.
-         PrimarySurface.pGraphicsDevice = NULL; // Fixme!
-         PrimarySurface.pEDDgpl = ExAllocatePoolWithTag(PagedPool, sizeof(EDD_DIRECTDRAW_GLOBAL), TAG_EDDGBL);
-         if (PrimarySurface.pEDDgpl)
-         {
-             RtlZeroMemory( PrimarySurface.pEDDgpl ,sizeof(EDD_DIRECTDRAW_GLOBAL));
-             ret = TRUE;
-         }
-         goto cleanup;
-     }
- cleanup:
-     KeSetEvent(&VideoDriverPrepared, 1, FALSE);
-     return ret;
- }
- BOOL FASTCALL
- IntPrepareDriverIfNeeded(VOID)
+ VOID FASTCALL
+ IntGdiReferencePdev(PPDEVOBJ ppdev)
  {
-     return (PrimarySurface.PreparedDriver ? TRUE : IntPrepareDriver());
+     UNIMPLEMENTED;
  }
  
static BOOL FASTCALL
PrepareVideoPrt(VOID)
VOID FASTCALL
IntGdiUnreferencePdev(PPDEVOBJ ppdev, DWORD CleanUpType)
  {
-     PIRP Irp;
-     NTSTATUS Status;
-     IO_STATUS_BLOCK Iosb;
-     BOOL Prepare = TRUE;
-     ULONG Length = sizeof(BOOL);
-     PIO_STACK_LOCATION StackPtr;
-     LARGE_INTEGER StartOffset;
-     PFILE_OBJECT FileObject = PrimarySurface.VideoFileObject;
-     PDEVICE_OBJECT DeviceObject = FileObject->DeviceObject;
-     DPRINT("PrepareVideoPrt() called\n");
-     KeClearEvent(&PrimarySurface.VideoFileObject->Event);
-     ObReferenceObjectByPointer(FileObject, 0, IoFileObjectType, KernelMode);
-     StartOffset.QuadPart = 0;
-     Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
-                                        DeviceObject,
-                                        (PVOID) &Prepare,
-                                        Length,
-                                        &StartOffset,
-                                        NULL,
-                                        &Iosb);
-     if (NULL == Irp)
-     {
-         return FALSE;
-     }
-     /* Set up IRP Data */
-     Irp->Tail.Overlay.OriginalFileObject = FileObject;
-     Irp->RequestorMode = KernelMode;
-     Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
-     Irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
-     Irp->Flags |= IRP_WRITE_OPERATION;
-     /* Setup Stack Data */
-     StackPtr = IoGetNextIrpStackLocation(Irp);
-     StackPtr->FileObject = PrimarySurface.VideoFileObject;
-     StackPtr->Parameters.Write.Key = 0;
-     Status = IoCallDriver(DeviceObject, Irp);
-     if (STATUS_PENDING == Status)
-     {
-         KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, TRUE, 0);
-         Status = Iosb.Status;
-     }
-     return NT_SUCCESS(Status);
+     UNIMPLEMENTED;
  }
  
  BOOL FASTCALL
- IntCreatePrimarySurface(VOID)
+ IntCreatePrimarySurface()
  {
      SIZEL SurfSize;
-     RECTL SurfaceRect;
-     SURFOBJ *SurfObj;
+     SURFOBJ *pso;
      BOOL calledFromUser;
  
-     if (! IntPrepareDriverIfNeeded())
-     {
-         return FALSE;
-     }
-     if (! PrepareVideoPrt())
-     {
-         return FALSE;
-     }
-     DPRINT("calling EnableSurface\n");
-     /* Enable the drawing surface */
-     PrimarySurface.pSurface =
-         PrimarySurface.DriverFunctions.EnableSurface(PrimarySurface.dhpdev);
-     if (NULL == PrimarySurface.pSurface)
-     {
-         /*      PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.dhpdev, FALSE);*/
-         PrimarySurface.DriverFunctions.DisablePDEV(PrimarySurface.dhpdev);
-         ObDereferenceObject(PrimarySurface.VideoFileObject);
-         DPRINT1("DrvEnableSurface failed\n");
-         return FALSE;
-     }
-     PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.dhpdev, TRUE);
      calledFromUser = UserIsEntered(); //fixme: possibly upgrade a shared lock
      if (!calledFromUser)
      {
      }
  
      /* attach monitor */
-     IntAttachMonitor(&PrimarySurface, PrimarySurface.DisplayNumber);
+     IntAttachMonitor(gppdevPrimary, 0);
  
-     SurfObj = EngLockSurface(PrimarySurface.pSurface);
-     SurfObj->dhpdev = PrimarySurface.dhpdev;
-     SurfSize = SurfObj->sizlBitmap;
-     SurfaceRect.left = SurfaceRect.top = 0;
-     SurfaceRect.right = SurfObj->sizlBitmap.cx;
-     SurfaceRect.bottom = SurfObj->sizlBitmap.cy;
-     /* FIXME - why does EngEraseSurface() sometimes crash?
-        EngEraseSurface(SurfObj, &SurfaceRect, 0); */
+     DPRINT1("IntCreatePrimarySurface, pPrimarySurface=%p, pPrimarySurface->pSurface = %p\n",
+         pPrimarySurface, pPrimarySurface->pSurface);
  
-     /* Put the pointer in the center of the screen */
-     gpsi->ptCursor.x = (SurfaceRect.right - SurfaceRect.left) / 2;
-     gpsi->ptCursor.y = (SurfaceRect.bottom - SurfaceRect.top) / 2;
+     /* Create surface */
+     pso = &PDEVOBJ_pSurface(pPrimarySurface)->SurfObj;
+     SurfSize = pso->sizlBitmap;
  
-     /* Give the PDEV a MovePointer function */
-     PrimarySurface.pfnMovePointer = PrimarySurface.DriverFunctions.MovePointer;
-     if (!PrimarySurface.pfnMovePointer)
-         PrimarySurface.pfnMovePointer = EngMovePointer;
+     /* Put the pointer in the center of the screen */
+     gpsi->ptCursor.x = pso->sizlBitmap.cx / 2;
+     gpsi->ptCursor.y = pso->sizlBitmap.cy / 2;
  
-     EngUnlockSurface(SurfObj);
      co_IntShowDesktop(IntGetActiveDesktop(), SurfSize.cx, SurfSize.cy);
  
      // Init Primary Displays Device Capabilities.
-     IntvGetDeviceCaps(&PrimarySurface, &GdiHandleTable->DevCaps);
+     PDEVOBJ_vGetDeviceCaps(pPrimarySurface, &GdiHandleTable->DevCaps);
  
      if (!calledFromUser)
      {
  }
  
  VOID FASTCALL
- IntDestroyPrimarySurface(VOID)
+ IntDestroyPrimarySurface()
  {
-     BOOL calledFromUser;
-     DRIVER_UnreferenceDriver(L"DISPLAY");
-     calledFromUser = UserIsEntered();
-     if (!calledFromUser)
-     {
-         UserEnterExclusive();
-     }
-     /* detach monitor */
-     IntDetachMonitor(&PrimarySurface);
-     if (!calledFromUser)
-     {
-         UserLeave();
-     }
-     /*
-      * FIXME: Hide a mouse pointer there. Also because we have to prevent
-      * memory leaks with the Eng* mouse routines.
-      */
-     DPRINT("Reseting display\n" );
-     PrimarySurface.DriverFunctions.AssertMode(PrimarySurface.dhpdev, FALSE);
-     PrimarySurface.DriverFunctions.DisableSurface(PrimarySurface.dhpdev);
-     PrimarySurface.DriverFunctions.DisablePDEV(PrimarySurface.dhpdev);
-     PrimarySurface.PreparedDriver = FALSE;
-     KeSetEvent(&VideoDriverNeedsPreparation, 1, FALSE);
-     KeResetEvent(&VideoDriverPrepared);
-     DceEmptyCache();
-     ObDereferenceObject(PrimarySurface.VideoFileObject);
- }
- INT
- FASTCALL
- IntcFonts(PPDEVOBJ pDevObj)
- {
-     ULONG_PTR Junk;
- // Msdn DrvQueryFont:
- // If the number of fonts in DEVINFO is -1 and iFace is zero, the driver
- // should return the number of fonts it supports.
-     if ( pDevObj->devinfo.cFonts == -1)
-     {
-         if (pDevObj->DriverFunctions.QueryFont)
-             pDevObj->devinfo.cFonts =
-                 (ULONG)pDevObj->DriverFunctions.QueryFont(pDevObj->dhpdev, 0, 0, &Junk);
-         else
-             pDevObj->devinfo.cFonts = 0;
-     }
-     return pDevObj->devinfo.cFonts;
- }
- //
- // Support multi display/device locks.
- //
- VOID
- FASTCALL
- DC_LockDisplay(HDC hDC)
- {
-     PERESOURCE Resource;
-     PDC dc = DC_LockDc(hDC);
-     if (!dc) return;
-     Resource = dc->ppdev->hsemDevLock;
-     DC_UnlockDc(dc);
-     if (!Resource) return;
-     KeEnterCriticalRegion();
-     ExAcquireResourceExclusiveLite( Resource , TRUE);
- }
- VOID
- FASTCALL
- DC_UnlockDisplay(HDC hDC)
- {
-     PERESOURCE Resource;
-     PDC dc = DC_LockDc(hDC);
-     if (!dc) return;
-     Resource = dc->ppdev->hsemDevLock;
-     DC_UnlockDc(dc);
-     if (!Resource) return;
-     ExReleaseResourceLite( Resource );
-     KeLeaveCriticalRegion();
+     UNIMPLEMENTED;
  }
  
- //
- // Enumerate HDev
- //
  PPDEVOBJ FASTCALL
  IntEnumHDev(VOID)
  {
  // I guess we will soon have more than one primary surface.
  // This will do for now.
-     return &PrimarySurface;
+     return pPrimarySurface;
  }
  
  
- VOID FASTCALL
- IntGdiReferencePdev(PPDEVOBJ ppdev)
- {
-     if (!hsemDriverMgmt) hsemDriverMgmt = EngCreateSemaphore(); // Hax, should be in dllmain.c
-     IntGdiAcquireSemaphore(hsemDriverMgmt);
-     ppdev->cPdevRefs++;
-     IntGdiReleaseSemaphore(hsemDriverMgmt);
- }
- VOID FASTCALL
- IntGdiUnreferencePdev(PPDEVOBJ ppdev, DWORD CleanUpType)
- {
-     IntGdiAcquireSemaphore(hsemDriverMgmt);
-     ppdev->cPdevRefs--;
-     if (!ppdev->cPdevRefs)
-     {
-         // Handle the destruction of ppdev or PDEVOBJ or PDEVOBJ or PDEV etc.
-     }
-     IntGdiReleaseSemaphore(hsemDriverMgmt);
- }
- INT
- FASTCALL
- IntGetColorManagementCaps(PPDEVOBJ pDevObj)
- {
-     INT ret = CM_NONE;
-     if ( pDevObj->flFlags & PDEV_DISPLAY)
-     {
-         if (pDevObj->devinfo.iDitherFormat == BMF_8BPP ||
-             pDevObj->devinfo.flGraphicsCaps2 & GCAPS2_CHANGEGAMMARAMP)
-             ret = CM_GAMMA_RAMP;
-     }
-     if (pDevObj->devinfo.flGraphicsCaps & GCAPS_CMYKCOLOR)
-         ret |= CM_CMYK_COLOR;
-     if (pDevObj->devinfo.flGraphicsCaps & GCAPS_ICM)
-         ret |= CM_DEVICE_ICM;
-     return ret;
- }
- INT FASTCALL
- IntGdiGetDeviceCaps(PDC dc, INT Index)
- {
-     INT ret = 0;
-     PPDEVOBJ ppdev = dc->ppdev;
-     /* Retrieve capability */
-     switch (Index)
-     {
-         case DRIVERVERSION:
-             ret = ppdev->gdiinfo.ulVersion;
-             break;
-         case TECHNOLOGY:
-             ret = ppdev->gdiinfo.ulTechnology;
-             break;
-         case HORZSIZE:
-             ret = ppdev->gdiinfo.ulHorzSize;
-             break;
-         case VERTSIZE:
-             ret = ppdev->gdiinfo.ulVertSize;
-             break;
-         case HORZRES:
-             ret = ppdev->gdiinfo.ulHorzRes;
-             break;
-         case VERTRES:
-             ret = ppdev->gdiinfo.ulVertRes;
-             break;
-         case LOGPIXELSX:
-             ret = ppdev->gdiinfo.ulLogPixelsX;
-             break;
-         case LOGPIXELSY:
-             ret = ppdev->gdiinfo.ulLogPixelsY;
-             break;
-         case CAPS1:
-             if ( ppdev->pGraphicsDevice &&
-                     (((PGRAPHICS_DEVICE)ppdev->pGraphicsDevice)->StateFlags &
-                      DISPLAY_DEVICE_MIRRORING_DRIVER))
-                 ret = C1_MIRRORING;
-             break;
-         case BITSPIXEL:
-             ret = ppdev->gdiinfo.cBitsPixel;
-             break;
-         case PLANES:
-             ret = ppdev->gdiinfo.cPlanes;
-             break;
-         case NUMBRUSHES:
-             ret = -1;
-             break;
-         case NUMPENS:
-             ret = ppdev->gdiinfo.ulNumColors;
-             if ( ret != -1 ) ret *= 5;
-             break;
-         case NUMFONTS:
-             ret = IntcFonts(ppdev);
-             break;
-         case NUMCOLORS:
-             ret = ppdev->gdiinfo.ulNumColors;
-             break;
-         case ASPECTX:
-             ret = ppdev->gdiinfo.ulAspectX;
-             break;
-         case ASPECTY:
-             ret = ppdev->gdiinfo.ulAspectY;
-             break;
-         case ASPECTXY:
-             ret = ppdev->gdiinfo.ulAspectXY;
-             break;
-         case CLIPCAPS:
-             ret = CP_RECTANGLE;
-             break;
-         case SIZEPALETTE:
-             ret = ppdev->gdiinfo.ulNumPalReg;
-             break;
-         case NUMRESERVED:
-             ret = 20;
-             break;
-         case COLORRES:
-             ret = ppdev->gdiinfo.ulDACRed +
-                   ppdev->gdiinfo.ulDACGreen +
-                   ppdev->gdiinfo.ulDACBlue;
-             break;
-         case DESKTOPVERTRES:
-             ret = ppdev->gdiinfo.ulVertRes;
-             break;
-         case DESKTOPHORZRES:
-             ret = ppdev->gdiinfo.ulHorzRes;
-             break;
-         case BLTALIGNMENT:
-             ret = ppdev->gdiinfo.ulBltAlignment;
-             break;
-         case SHADEBLENDCAPS:
-             ret = ppdev->gdiinfo.flShadeBlend;
-             break;
-         case COLORMGMTCAPS:
-             ret = IntGetColorManagementCaps(ppdev);
-             break;
-         case PHYSICALWIDTH:
-             ret = ppdev->gdiinfo.szlPhysSize.cx;
-             break;
-         case PHYSICALHEIGHT:
-             ret = ppdev->gdiinfo.szlPhysSize.cy;
-             break;
-         case PHYSICALOFFSETX:
-             ret = ppdev->gdiinfo.ptlPhysOffset.x;
-             break;
-         case PHYSICALOFFSETY:
-             ret = ppdev->gdiinfo.ptlPhysOffset.y;
-             break;
-         case VREFRESH:
-             ret = ppdev->gdiinfo.ulVRefresh;
-             break;
-         case RASTERCAPS:
-             ret = ppdev->gdiinfo.flRaster;
-             break;
-         case CURVECAPS:
-             ret = (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
-                    CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
-             break;
-         case LINECAPS:
-             ret = (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
-                    LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
-             break;
-         case POLYGONALCAPS:
-             ret = (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
-                    PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
-             break;
-         case TEXTCAPS:
-             ret = ppdev->gdiinfo.flTextCaps;
-             if (ppdev->gdiinfo.ulTechnology) ret |= TC_VA_ABLE;
-             ret |= (TC_SO_ABLE|TC_UA_ABLE);
-             break;
-         case PDEVICESIZE:
-         case SCALINGFACTORX:
-         case SCALINGFACTORY:
-         default:
-             ret = 0;
-             break;
-     }
-     return ret;
- }
- INT APIENTRY
- NtGdiGetDeviceCaps(HDC  hDC,
-                    INT  Index)
- {
-     PDC  dc;
-     INT  ret;
-     dc = DC_LockDc(hDC);
-     if (dc == NULL)
-     {
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return 0;
-     }
-     ret = IntGdiGetDeviceCaps(dc, Index);
-     DPRINT("(%04x,%d): returning %d\n", hDC, Index, ret);
-     DC_UnlockDc( dc );
-     return ret;
- }
- VOID
- FASTCALL
- IntvGetDeviceCaps(
-     PPDEVOBJ pDevObj,
-     PDEVCAPS pDevCaps)
- {
-     ULONG Tmp = 0;
-     PGDIINFO pGdiInfo = &pDevObj->gdiinfo;
-     pDevCaps->ulVersion         = pGdiInfo->ulVersion;
-     pDevCaps->ulTechnology      = pGdiInfo->ulTechnology;
-     pDevCaps->ulHorzSizeM       = (pGdiInfo->ulHorzSize + 500) / 1000;
-     pDevCaps->ulVertSizeM       = (pGdiInfo->ulVertSize + 500) / 1000;
-     pDevCaps->ulHorzSize        = pGdiInfo->ulHorzSize;
-     pDevCaps->ulVertSize        = pGdiInfo->ulVertSize;
-     pDevCaps->ulHorzRes         = pGdiInfo->ulHorzRes;
-     pDevCaps->ulVertRes         = pGdiInfo->ulVertRes;
-     pDevCaps->ulVRefresh        = pGdiInfo->ulVRefresh;
-     pDevCaps->ulDesktopHorzRes  = pGdiInfo->ulHorzRes;
-     pDevCaps->ulDesktopVertRes  = pGdiInfo->ulVertRes;
-     pDevCaps->ulBltAlignment    = pGdiInfo->ulBltAlignment;
-     pDevCaps->ulPlanes          = pGdiInfo->cPlanes;
-     pDevCaps->ulBitsPixel       = pGdiInfo->cBitsPixel;
-     if (pGdiInfo->cBitsPixel == 15) pDevCaps->ulBitsPixel = 16;
-     Tmp = pGdiInfo->ulNumColors;
-     if ( Tmp != -1 ) Tmp *= 5;
-     pDevCaps->ulNumPens = Tmp;
-     pDevCaps->ulNumColors       = pGdiInfo->ulNumColors;
-     pDevCaps->ulNumFonts        = IntcFonts(pDevObj);
-     pDevCaps->ulRasterCaps      = pGdiInfo->flRaster;
-     pDevCaps->ulShadeBlend      = pGdiInfo->flShadeBlend;
-     pDevCaps->ulAspectX         = pGdiInfo->ulAspectX;
-     pDevCaps->ulAspectY         = pGdiInfo->ulAspectY;
-     pDevCaps->ulAspectXY        = pGdiInfo->ulAspectXY;
-     pDevCaps->ulLogPixelsX      = pGdiInfo->ulLogPixelsX;
-     pDevCaps->ulLogPixelsY      = pGdiInfo->ulLogPixelsY;
-     pDevCaps->ulSizePalette     = pGdiInfo->ulNumPalReg;
-     pDevCaps->ulColorRes        = pGdiInfo->ulDACRed + pGdiInfo->ulDACGreen + pGdiInfo->ulDACBlue;
-     pDevCaps->ulPhysicalWidth   = pGdiInfo->szlPhysSize.cx;
-     pDevCaps->ulPhysicalHeight  = pGdiInfo->szlPhysSize.cy;
-     pDevCaps->ulPhysicalOffsetX = pGdiInfo->ptlPhysOffset.x;
-     pDevCaps->ulPhysicalOffsetY = pGdiInfo->ptlPhysOffset.y;
-     pDevCaps->ulPanningHorzRes  = pGdiInfo->ulPanningHorzRes;
-     pDevCaps->ulPanningVertRes  = pGdiInfo->ulPanningVertRes;
-     pDevCaps->xPanningAlignment = pGdiInfo->xPanningAlignment;
-     pDevCaps->yPanningAlignment = pGdiInfo->yPanningAlignment;
-     Tmp = 0;
-     Tmp = pGdiInfo->flTextCaps | (TC_SO_ABLE|TC_UA_ABLE|TC_CP_STROKE|TC_OP_STROKE|TC_OP_CHARACTER);
-     pDevCaps->ulTextCaps = pGdiInfo->flTextCaps | (TC_SO_ABLE|TC_UA_ABLE|TC_CP_STROKE|TC_OP_STROKE|TC_OP_CHARACTER);
-     if (pGdiInfo->ulTechnology)
-         pDevCaps->ulTextCaps = Tmp | TC_VA_ABLE;
-     pDevCaps->ulColorMgmtCaps = IntGetColorManagementCaps(pDevObj);
-     return;
- }
- /*
- * @implemented
- */
- BOOL
- APIENTRY
- NtGdiGetDeviceCapsAll (
-     IN HDC hDC,
-     OUT PDEVCAPS pDevCaps)
- {
-     PDC  dc;
-     PDEVCAPS pSafeDevCaps;
-     NTSTATUS Status = STATUS_SUCCESS;
-     dc = DC_LockDc(hDC);
-     if (!dc)
-     {
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return FALSE;
-     }
-     pSafeDevCaps = ExAllocatePoolWithTag(PagedPool, sizeof(DEVCAPS), TAG_TEMP);
-     if (!pSafeDevCaps)
-     {
-         DC_UnlockDc(dc);
-         return FALSE;
-     }
-     IntvGetDeviceCaps(dc->ppdev, pSafeDevCaps);
-     _SEH2_TRY
-     {
-         ProbeForWrite(pDevCaps,
-         sizeof(DEVCAPS),
-         1);
-         RtlCopyMemory(pDevCaps, pSafeDevCaps, sizeof(DEVCAPS));
-     }
-     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
-     {
-         Status = _SEH2_GetExceptionCode();
-     }
-     _SEH2_END;
-     ExFreePoolWithTag(pSafeDevCaps, TAG_TEMP);
-     DC_UnlockDc(dc);
-     if (!NT_SUCCESS(Status))
-     {
-         SetLastNtError(Status);
-         return FALSE;
-     }
-     return TRUE;
- }
- /*
-  * @implemented
-  */
- DHPDEV
- APIENTRY
- NtGdiGetDhpdev(
-     IN HDEV hdev)
- {
-     PPDEVOBJ ppdev, pGdiDevice = (PPDEVOBJ) hdev;
-     if (!pGdiDevice) return NULL;
-     if ( pGdiDevice < (PPDEVOBJ)MmSystemRangeStart) return NULL;
-     ppdev = pPrimarySurface;
-     IntGdiAcquireSemaphore(hsemDriverMgmt);
-     do
-     {
-         if (pGdiDevice == ppdev) break;
-         else
-             ppdev = ppdev->ppdevNext;
-     }
-     while (ppdev != NULL);
-     IntGdiReleaseSemaphore(hsemDriverMgmt);
-     if (!ppdev) return NULL;
-     return pGdiDevice->dhpdev;
- }
- static NTSTATUS FASTCALL
- GetVideoRegistryKey(
-     OUT PUNICODE_STRING RegistryPath,
-     IN PCUNICODE_STRING DeviceName) /* ex: "\Device\Video0" */
- {
-     RTL_QUERY_REGISTRY_TABLE QueryTable[2];
-     NTSTATUS Status;
-     RtlInitUnicodeString(RegistryPath, NULL);
-     RtlZeroMemory(QueryTable, sizeof(QueryTable));
-     QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_DIRECT;
-     QueryTable[0].Name = DeviceName->Buffer;
-     QueryTable[0].EntryContext = RegistryPath;
-     Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
-                                     L"VIDEO",
-                                     QueryTable,
-                                     NULL,
-                                     NULL);
-     if (!NT_SUCCESS(Status))
-     {
-         DPRINT1("No %wZ value in DEVICEMAP\\VIDEO found (Status 0x%08lx)\n", DeviceName, Status);
-         return STATUS_NO_SUCH_DEVICE;
-     }
-     DPRINT("RegistryPath %wZ\n", RegistryPath);
-     return STATUS_SUCCESS;
- }
- static NTSTATUS FASTCALL
- GetVideoDeviceName(
-     OUT PUNICODE_STRING VideoDeviceName,
-     IN PCUNICODE_STRING DisplayDevice) /* ex: "\.\DISPLAY1" or "\??\DISPLAY1" */
- {
-     UNICODE_STRING Prefix = RTL_CONSTANT_STRING(L"\\??\\");
-     UNICODE_STRING ObjectName;
-     UNICODE_STRING KernelModeName = { 0, };
-     OBJECT_ATTRIBUTES ObjectAttributes;
-     USHORT LastSlash;
-     ULONG Length;
-     HANDLE LinkHandle = NULL;
-     NTSTATUS Status;
-     RtlInitUnicodeString(VideoDeviceName, NULL);
-     /* Get device name (DisplayDevice is "\.\xxx") */
-     for (LastSlash = DisplayDevice->Length / sizeof(WCHAR); LastSlash > 0; LastSlash--)
-     {
-         if (DisplayDevice->Buffer[LastSlash - 1] == L'\\')
-             break;
-     }
-     if (LastSlash == 0)
-     {
-         DPRINT1("Invalid device name '%wZ'\n", DisplayDevice);
-         Status = STATUS_OBJECT_NAME_INVALID;
-         goto cleanup;
-     }
-     ObjectName = *DisplayDevice;
-     ObjectName.Length -= LastSlash * sizeof(WCHAR);
-     ObjectName.MaximumLength -= LastSlash * sizeof(WCHAR);
-     ObjectName.Buffer += LastSlash;
-     /* Create "\??\xxx" (ex: "\??\DISPLAY1") */
-     KernelModeName.MaximumLength = Prefix.Length + ObjectName.Length + sizeof(UNICODE_NULL);
-     KernelModeName.Buffer = ExAllocatePoolWithTag(PagedPool,
-                             KernelModeName.MaximumLength,
-                             TAG_DC);
-     if (!KernelModeName.Buffer)
-     {
-         Status = STATUS_NO_MEMORY;
-         goto cleanup;
-     }
-     RtlCopyUnicodeString(&KernelModeName, &Prefix);
-     Status = RtlAppendUnicodeStringToString(&KernelModeName, &ObjectName);
-     if (!NT_SUCCESS(Status))
-         goto cleanup;
-     /* Open \??\xxx (ex: "\??\DISPLAY1") */
-     InitializeObjectAttributes(&ObjectAttributes,
-                                &KernelModeName,
-                                OBJ_KERNEL_HANDLE,
-                                NULL,
-                                NULL);
-     Status = ZwOpenSymbolicLinkObject(&LinkHandle,
-                                       GENERIC_READ,
-                                       &ObjectAttributes);
-     if (!NT_SUCCESS(Status))
-     {
-         DPRINT1("Unable to open symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status);
-         Status = STATUS_NO_SUCH_DEVICE;
-         goto cleanup;
-     }
-     Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, &Length);
-     if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_TOO_SMALL)
-     {
-         DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status);
-         Status = STATUS_NO_SUCH_DEVICE;
-         goto cleanup;
-     }
-     VideoDeviceName->MaximumLength = Length;
-     VideoDeviceName->Buffer = ExAllocatePoolWithTag(PagedPool,
-                               VideoDeviceName->MaximumLength + sizeof(UNICODE_NULL),
-                               TAG_DC);
-     if (!VideoDeviceName->Buffer)
-     {
-         Status = STATUS_NO_MEMORY;
-         goto cleanup;
-     }
-     Status = ZwQuerySymbolicLinkObject(LinkHandle, VideoDeviceName, NULL);
-     VideoDeviceName->Buffer[VideoDeviceName->MaximumLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
-     if (!NT_SUCCESS(Status))
-     {
-         DPRINT1("Unable to query symbolic link %wZ (Status 0x%08lx)\n", &KernelModeName, Status);
-         Status = STATUS_NO_SUCH_DEVICE;
-         goto cleanup;
-     }
-     Status = STATUS_SUCCESS;
- cleanup:
-     if (!NT_SUCCESS(Status) && VideoDeviceName->Buffer)
-         ExFreePoolWithTag(VideoDeviceName->Buffer, TAG_DC);
-     if (KernelModeName.Buffer)
-         ExFreePoolWithTag(KernelModeName.Buffer, TAG_DC);
-     if (LinkHandle)
-         ZwClose(LinkHandle);
-     return Status;
- }
- LONG
- FASTCALL
- IntChangeDisplaySettings(
-     IN PUNICODE_STRING pDeviceName  OPTIONAL,
-     IN LPDEVMODEW DevMode,
-     IN DWORD dwflags,
-     IN PVOID lParam  OPTIONAL)
- {
-     BOOLEAN NoReset = FALSE;
-     BOOLEAN Reset = FALSE;
-     LONG Ret = DISP_CHANGE_SUCCESSFUL;
-     NTSTATUS Status ;
-     DPRINT1("display flags : %x\n",dwflags);
-     if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
-     {
-         /* Check global, reset and noreset flags */
-         if ((dwflags & CDS_GLOBAL) == CDS_GLOBAL)
-             DPRINT1("CDS_GLOBAL unhandled");
-         if ((dwflags & CDS_NORESET) == CDS_NORESET)
-             NoReset = TRUE;
-         dwflags &= ~(CDS_GLOBAL | CDS_NORESET);
-     }
-     if ((dwflags & CDS_RESET) == CDS_RESET)
-         Reset = TRUE;
-     if ((dwflags & CDS_SET_PRIMARY) == CDS_SET_PRIMARY)
-         DPRINT1("CDS_SET_PRIMARY unhandled");
-     dwflags &= ~(CDS_RESET | CDS_SET_PRIMARY);
-     if (Reset && NoReset)
-         return DISP_CHANGE_BADFLAGS;
-     if (dwflags == 0)
-     {
-         /* Dynamically change graphics mode */
-         DPRINT1("flag 0 UNIMPLEMENTED\n");
-         SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
-         return DISP_CHANGE_FAILED;
-     }
-     if ((dwflags & CDS_TEST) == CDS_TEST)
-     {
-         /* Test resolution */
-         dwflags &= ~CDS_TEST;
-         Status = IntEnumDisplaySettings(pDeviceName, ENUM_REGISTRY_SETTINGS, DevMode, 0);
-         if (!NT_SUCCESS(Status))
-             Ret = DISP_CHANGE_BADMODE;
-         return Ret;
-     }
-     if ((dwflags & CDS_FULLSCREEN) == CDS_FULLSCREEN)
-     {
-         DEVMODEW lpDevMode;
-         /* Full Screen */
-         dwflags &= ~CDS_FULLSCREEN;
-         DPRINT1("flag CDS_FULLSCREEN partially implemented\n");
-         Ret = DISP_CHANGE_FAILED;
-         RtlZeroMemory(&lpDevMode, sizeof(DEVMODEW));
-         lpDevMode.dmSize = sizeof(DEVMODEW);
-         Status = IntEnumDisplaySettings(pDeviceName, ENUM_CURRENT_SETTINGS, &lpDevMode, 0);
-         if (!NT_SUCCESS(Status))
-             return DISP_CHANGE_FAILED;
-         DPRINT1("Req Mode     : %d x %d x %d\n", DevMode->dmPelsWidth,DevMode->dmPelsHeight,DevMode->dmBitsPerPel);
-         DPRINT1("Current Mode : %d x %d x %d\n", lpDevMode.dmPelsWidth,lpDevMode.dmPelsHeight, lpDevMode.dmBitsPerPel);
-         if ((lpDevMode.dmBitsPerPel == DevMode->dmBitsPerPel) &&
-                 (lpDevMode.dmPelsWidth  == DevMode->dmPelsWidth) &&
-                 (lpDevMode.dmPelsHeight == DevMode->dmPelsHeight))
-             Ret = DISP_CHANGE_SUCCESSFUL;
-     }
-     if ((dwflags & CDS_VIDEOPARAMETERS) == CDS_VIDEOPARAMETERS)
-     {
-         dwflags &= ~CDS_VIDEOPARAMETERS;
-         if (lParam == NULL)
-             Ret=DISP_CHANGE_BADPARAM;
-         else
-         {
-             DPRINT1("flag CDS_VIDEOPARAMETERS UNIMPLEMENTED\n");
-             Ret = DISP_CHANGE_FAILED;
-             SetLastWin32Error(ERROR_CALL_NOT_IMPLEMENTED);
-         }
-     }
-     if ((dwflags & CDS_UPDATEREGISTRY) == CDS_UPDATEREGISTRY)
-     {
-         UNICODE_STRING DeviceName;
-         UNICODE_STRING RegistryKey;
-         UNICODE_STRING InDeviceName;
-         OBJECT_ATTRIBUTES ObjectAttributes;
-         HANDLE DevInstRegKey;
-         ULONG NewValue;
-         DPRINT1("set CDS_UPDATEREGISTRY\n");
-         dwflags &= ~CDS_UPDATEREGISTRY;
-         /* Check if pDeviceName is NULL, we need to retrieve it */
-         if (pDeviceName == NULL)
-         {
-             WCHAR szBuffer[MAX_DRIVER_NAME];
-             PDC DC;
-             PWND Wnd=NULL;
-             HWND hWnd;
-             HDC hDC;
-             hWnd = IntGetDesktopWindow();
-             if (!(Wnd = UserGetWindowObject(hWnd)))
-             {
-                 return FALSE;
-             }
-             hDC = UserGetWindowDC(Wnd);
-             DC = DC_LockDc(hDC);
-             if (NULL == DC)
-             {
-                 return FALSE;
-             }
-             swprintf (szBuffer, L"\\\\.\\DISPLAY%lu", DC->ppdev->DisplayNumber);
-             DC_UnlockDc(DC);
-             RtlInitUnicodeString(&InDeviceName, szBuffer);
-             pDeviceName = &InDeviceName;
-         }
-         Status = GetVideoDeviceName(&DeviceName, pDeviceName);
-         if (!NT_SUCCESS(Status))
-         {
-             DPRINT1("Unable to get destination of '%wZ' (Status 0x%08lx)\n", pDeviceName, Status);
-             return DISP_CHANGE_FAILED;
-         }
-         Status = GetVideoRegistryKey(&RegistryKey, &DeviceName);
-         if (!NT_SUCCESS(Status))
-         {
-             DPRINT1("Unable to get registry key for '%wZ' (Status 0x%08lx)\n", &DeviceName, Status);
-             ExFreePoolWithTag(DeviceName.Buffer, TAG_DC);
-             return DISP_CHANGE_FAILED;
-         }
-         ExFreePoolWithTag(DeviceName.Buffer, TAG_DC);
-         InitializeObjectAttributes(&ObjectAttributes, &RegistryKey,
-                                    OBJ_CASE_INSENSITIVE, NULL, NULL);
-         Status = ZwOpenKey(&DevInstRegKey, KEY_SET_VALUE, &ObjectAttributes);
-         if (!NT_SUCCESS(Status))
-         {
-             DPRINT1("Unable to open registry key %wZ (Status 0x%08lx)\n", &RegistryKey, Status);
-             ExFreePoolWithTag(RegistryKey.Buffer, TAG_RTLREGISTRY);
-             return DISP_CHANGE_FAILED;
-         }
-         ExFreePoolWithTag(RegistryKey.Buffer, TAG_RTLREGISTRY);
-         /* Update needed fields */
-         if (NT_SUCCESS(Status) && DevMode->dmFields & DM_BITSPERPEL)
-         {
-             RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.BitsPerPel");
-             NewValue = DevMode->dmBitsPerPel;
-             Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
-         }
-         if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSWIDTH)
-         {
-             RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.XResolution");
-             NewValue = DevMode->dmPelsWidth;
-             Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
-         }
-         if (NT_SUCCESS(Status) && DevMode->dmFields & DM_PELSHEIGHT)
-         {
-             RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.YResolution");
-             NewValue = DevMode->dmPelsHeight;
-             Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
-         }
-         if (NT_SUCCESS(Status) && DevMode->dmFields & DM_DISPLAYFREQUENCY)
-         {
-             RtlInitUnicodeString(&RegistryKey, L"DefaultSettings.VRefresh");
-             NewValue = DevMode->dmDisplayFrequency;
-             Status = ZwSetValueKey(DevInstRegKey, &RegistryKey, 0, REG_DWORD, &NewValue, sizeof(NewValue));
-         }
-         ZwClose(DevInstRegKey);
-         if (NT_SUCCESS(Status))
-             Ret = DISP_CHANGE_RESTART;
-         else
-             /* return DISP_CHANGE_NOTUPDATED when we can save to reg only valid for NT */
-             Ret = DISP_CHANGE_NOTUPDATED;
-     }
-     if (dwflags != 0)
-         Ret = DISP_CHANGE_BADFLAGS;
-     DPRINT("IntChangeDisplaySettings returning %x\n", Ret);
-     return Ret;
- }
- #define SIZEOF_DEVMODEW_300 188
- #define SIZEOF_DEVMODEW_400 212
- #define SIZEOF_DEVMODEW_500 220
- static NTSTATUS FASTCALL
- GetDisplayNumberFromDeviceName(
-     IN PUNICODE_STRING pDeviceName  OPTIONAL,
-     OUT ULONG *DisplayNumber)
- {
-     UNICODE_STRING DisplayString = RTL_CONSTANT_STRING(L"\\\\.\\DISPLAY");
-     NTSTATUS Status = STATUS_SUCCESS;
-     ULONG Length;
-     ULONG Number;
-     ULONG i;
-     if (DisplayNumber == NULL)
-         return STATUS_INVALID_PARAMETER_2;
-     /* Check if DeviceName is valid */
-     if (pDeviceName &&
-             pDeviceName->Length > 0 && pDeviceName->Length <= DisplayString.Length)
-         return STATUS_OBJECT_NAME_INVALID;
-     if (pDeviceName == NULL || pDeviceName->Length == 0)
-     {
-         PWND DesktopObject;
-         HDC DesktopHDC;
-         PDC pDC;
-         DesktopObject = UserGetDesktopWindow();
-         DesktopHDC = UserGetWindowDC(DesktopObject);
-         pDC = DC_LockDc(DesktopHDC);
-         *DisplayNumber = pDC->ppdev->DisplayNumber;
-         DC_UnlockDc(pDC);
-         UserReleaseDC(DesktopObject, DesktopHDC, FALSE);
-         return STATUS_SUCCESS;
-     }
-     /* Hack to check if the first parts are equal, by faking the device name length */
-     Length = pDeviceName->Length;
-     pDeviceName->Length = DisplayString.Length;
-     if (RtlEqualUnicodeString(&DisplayString, pDeviceName, FALSE) == FALSE)
-         Status = STATUS_OBJECT_NAME_INVALID;
-     pDeviceName->Length = Length;
-     if (NT_SUCCESS(Status))
-     {
-         /* Convert the last part of pDeviceName to a number */
-         Number = 0;
-         Length = pDeviceName->Length / sizeof(WCHAR);
-         for (i = DisplayString.Length / sizeof(WCHAR); i < Length; i++)
-         {
-             WCHAR Char = pDeviceName->Buffer[i];
-             if (Char >= L'0' && Char <= L'9')
-                 Number = Number * 10 + Char - L'0';
-             else if (Char != L'\0')
-                 return STATUS_OBJECT_NAME_INVALID;
-         }
-         *DisplayNumber = Number - 1;
-     }
-     return Status;
- }
- /*! \brief Enumerate possible display settings for the given display...
-  *
-  * \todo Make thread safe!?
-  * \todo Don't ignore pDeviceName
-  * \todo Implement non-raw mode (only return settings valid for driver and monitor)
-  */
- NTSTATUS
- FASTCALL
- IntEnumDisplaySettings(
-     IN PUNICODE_STRING pDeviceName  OPTIONAL,
-     IN DWORD iModeNum,
-     IN OUT LPDEVMODEW pDevMode,
-     IN DWORD dwFlags)
- {
-     static DEVMODEW *CachedDevModes = NULL, *CachedDevModesEnd = NULL;
-     static DWORD SizeOfCachedDevModes = 0;
-     static UNICODE_STRING CachedDeviceName;
-     PDEVMODEW CachedMode = NULL;
-     DEVMODEW DevMode;
-     ULONG DisplayNumber;
-     NTSTATUS Status;
-     Status = GetDisplayNumberFromDeviceName(pDeviceName, &DisplayNumber);
-     if (!NT_SUCCESS(Status))
-     {
-         return Status;
-     }
-     if (pDevMode != NULL)
-     {
-         DPRINT("DevMode->dmSize = %d\n", pDevMode->dmSize);
-         DPRINT("DevMode->dmExtraSize = %d\n", pDevMode->dmDriverExtra);
-         if (pDevMode->dmSize != SIZEOF_DEVMODEW_300 &&
-                 pDevMode->dmSize != SIZEOF_DEVMODEW_400 &&
-                 pDevMode->dmSize != SIZEOF_DEVMODEW_500)
-         {
-             return STATUS_BUFFER_TOO_SMALL;
-         }
-     }
-     if (iModeNum == ENUM_CURRENT_SETTINGS)
-     {
-         CachedMode = &PrimarySurface.DMW;
-         ASSERT(CachedMode->dmSize > 0);
-     }
-     else if (iModeNum == ENUM_REGISTRY_SETTINGS)
-     {
-         RtlZeroMemory(&DevMode, sizeof (DevMode));
-         DevMode.dmSize = sizeof (DevMode);
-         DevMode.dmDriverExtra = 0;
-         if (SetupDevMode(&DevMode, DisplayNumber))
-             CachedMode = &DevMode;
-         else
-         {
-             return STATUS_UNSUCCESSFUL; // FIXME: what status?
-         }
-         /* FIXME: Maybe look for the matching devmode supplied by the
-          *        driver so we can provide driver private/extra data?
-          */
-     }
-     else
-     {
-         BOOL IsCachedDevice = (CachedDevModes != NULL);
-         if (CachedDevModes &&
-                 ((pDeviceName == NULL && CachedDeviceName.Length > 0) ||
-                  (pDeviceName != NULL && pDeviceName->Buffer != NULL && CachedDeviceName.Length == 0) ||
-                  (pDeviceName != NULL && pDeviceName->Buffer != NULL && CachedDeviceName.Length > 0 && RtlEqualUnicodeString(pDeviceName, &CachedDeviceName, TRUE) == FALSE)))
-         {
-             IsCachedDevice = FALSE;
-         }
-         if (iModeNum == 0 || IsCachedDevice == FALSE) /* query modes from drivers */
-         {
-             UNICODE_STRING DriverFileNames;
-             LPWSTR CurrentName;
-             DRVENABLEDATA DrvEnableData;
-             /* Free resources from last driver cache */
-             if (IsCachedDevice == FALSE && CachedDeviceName.Buffer != NULL)
-             {
-                 RtlFreeUnicodeString(&CachedDeviceName);
-             }
-             /* Retrieve DDI driver names from registry */
-             RtlInitUnicodeString(&DriverFileNames, NULL);
-             if (!FindDriverFileNames(&DriverFileNames, DisplayNumber))
-             {
-                 DPRINT1("FindDriverFileNames failed\n");
-                 return STATUS_UNSUCCESSFUL;
-             }
-             if (!IntPrepareDriverIfNeeded())
-             {
-                 DPRINT1("IntPrepareDriverIfNeeded failed\n");
-                 return STATUS_UNSUCCESSFUL;
-             }
-             /*
-              * DriverFileNames may be a list of drivers in REG_SZ_MULTI format,
-              * scan all of them until a good one found.
-              */
-             CurrentName = DriverFileNames.Buffer;
-             for (;CurrentName < DriverFileNames.Buffer + (DriverFileNames.Length / sizeof (WCHAR));
-                     CurrentName += wcslen(CurrentName) + 1)
-             {
-                 INT i;
-                 PFN_DrvEnableDriver GDEnableDriver;
-                 PFN_DrvGetModes GetModes = NULL;
-                 INT SizeNeeded, SizeUsed;
-                 /* Get the DDI driver's entry point */
-                 //GDEnableDriver = DRIVER_FindDDIDriver(CurrentName);
-                 GDEnableDriver = DRIVER_FindExistingDDIDriver(L"DISPLAY");
-                 if (NULL == GDEnableDriver)
-                 {
-                     DPRINT("FindDDIDriver failed for %S\n", CurrentName);
-                     continue;
-                 }
-                 /*  Call DDI driver's EnableDriver function  */
-                 RtlZeroMemory(&DrvEnableData, sizeof(DrvEnableData));
-                 if (!GDEnableDriver(DDI_DRIVER_VERSION_NT5_01, sizeof (DrvEnableData), &DrvEnableData))
-                 {
-                     DPRINT("DrvEnableDriver failed for %S\n", CurrentName);
-                     continue;
-                 }
-                 CachedDevModesEnd = CachedDevModes;
-                 /* find DrvGetModes function */
-                 for (i = 0; i < DrvEnableData.c; i++)
-                 {
-                     PDRVFN DrvFn = DrvEnableData.pdrvfn + i;
-                     if (DrvFn->iFunc == INDEX_DrvGetModes)
-                     {
-                         GetModes = (PFN_DrvGetModes)DrvFn->pfn;
-                         break;
-                     }
-                 }
-                 if (GetModes == NULL)
-                 {
-                     DPRINT("DrvGetModes doesn't exist for %S\n", CurrentName);
-                     continue;
-                 }
-                 /* make sure we have enough memory to hold the modes */
-                 SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject), 0, NULL);
-                 if (SizeNeeded <= 0)
-                 {
-                     DPRINT("DrvGetModes failed for %S\n", CurrentName);
-                     break;
-                 }
-                 SizeUsed = (PCHAR)CachedDevModesEnd - (PCHAR)CachedDevModes;
-                 if (SizeOfCachedDevModes < SizeUsed + SizeNeeded)
-                 {
-                     PVOID NewBuffer;
-                     SizeOfCachedDevModes += SizeNeeded;
-                     NewBuffer = ExAllocatePoolWithTag(PagedPool, SizeOfCachedDevModes, GDITAG_DEVMODE);
-                     if (NewBuffer == NULL)
-                     {
-                         /* clean up */
-                         ExFreePool(CachedDevModes);
-                         CachedDevModes = NULL;
-                         CachedDevModesEnd = NULL;
-                         SizeOfCachedDevModes = 0;
-                         if (CachedDeviceName.Buffer != NULL)
-                             RtlFreeUnicodeString(&CachedDeviceName);
-                         return STATUS_NO_MEMORY;
-                     }
-                     if (CachedDevModes != NULL)
-                     {
-                         RtlCopyMemory(NewBuffer, CachedDevModes, SizeUsed);
-                         ExFreePool(CachedDevModes);
-                     }
-                     CachedDevModes = NewBuffer;
-                     CachedDevModesEnd = (DEVMODEW *)((PCHAR)NewBuffer + SizeUsed);
-                 }
-                 if (!IsCachedDevice)
-                 {
-                     if (CachedDeviceName.Buffer != NULL)
-                         RtlFreeUnicodeString(&CachedDeviceName);
-                     if (pDeviceName)
-                         IntSafeCopyUnicodeString(&CachedDeviceName, pDeviceName);
-                     IsCachedDevice = TRUE;
-                 }
-                 /* query modes */
-                 SizeNeeded = GetModes((HANDLE)(PrimarySurface.VideoFileObject->DeviceObject),
-                                       SizeNeeded,
-                                       CachedDevModesEnd);
-                 if (SizeNeeded <= 0)
-                 {
-                     DPRINT("DrvGetModes failed for %S\n", CurrentName);
-                 }
-                 else
-                 {
-                     CachedDevModesEnd = (DEVMODEW *)((PCHAR)CachedDevModesEnd + SizeNeeded);
-                 }
-             }
-             ExFreePoolWithTag(DriverFileNames.Buffer, TAG_RTLREGISTRY);
-         }
-         /* return cached info */
-         CachedMode = CachedDevModes;
-         if (CachedMode >= CachedDevModesEnd)
-         {
-             return STATUS_NO_MORE_ENTRIES;
-         }
-         while (iModeNum-- > 0 && CachedMode < CachedDevModesEnd)
-         {
-             ASSERT(CachedMode->dmSize > 0);
-             CachedMode = (DEVMODEW *)((PCHAR)CachedMode + CachedMode->dmSize + CachedMode->dmDriverExtra);
-         }
-         if (CachedMode >= CachedDevModesEnd)
-         {
-             return STATUS_NO_MORE_ENTRIES;
-         }
-     }
-     ASSERT(CachedMode != NULL);
-     if (pDevMode != NULL)
-     {
-         RtlCopyMemory(pDevMode, CachedMode, min(pDevMode->dmSize, CachedMode->dmSize));
-         RtlZeroMemory(pDevMode + pDevMode->dmSize, pDevMode->dmDriverExtra);
-         RtlCopyMemory(pDevMode + min(pDevMode->dmSize, CachedMode->dmSize), CachedMode + CachedMode->dmSize, min(pDevMode->dmDriverExtra, CachedMode->dmDriverExtra));
-     }
-     return STATUS_SUCCESS;
- }
  INT
  APIENTRY
  NtGdiDrawEscape(
      return 0;
  }
  
@@@ -42,6 -42,26 +42,26 @@@ static const RGBQUAD EGAColorsQuads[16
      { 0xff, 0xff, 0xff, 0x00 }
  };
  
+ static const RGBTRIPLE EGAColorsTriples[16] = {
+ /* rgbBlue, rgbGreen, rgbRed */
+     { 0x00, 0x00, 0x00 },
+     { 0x00, 0x00, 0x80 },
+     { 0x00, 0x80, 0x00 },
+     { 0x00, 0x80, 0x80 },
+     { 0x80, 0x00, 0x00 },
+     { 0x80, 0x00, 0x80 },
+     { 0x80, 0x80, 0x00 },
+     { 0x80, 0x80, 0x80 },
+     { 0xc0, 0xc0, 0xc0 },
+     { 0x00, 0x00, 0xff },
+     { 0x00, 0xff, 0x00 },
+     { 0x00, 0xff, 0xff },
+     { 0xff, 0x00, 0x00 },
+     { 0xff, 0x00, 0xff },
+     { 0xff, 0xff, 0x00 },
+     { 0xff, 0xff, 0xff }
+ };
  static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
  /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
      { 0x00, 0x00, 0x00, 0x00 },
      { 0xff, 0xff, 0xff, 0x00 }
  };
  
+ static const RGBQUAD DefLogPaletteTriples[20] = { /* Copy of Default Logical Palette */
+ /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
+     { 0x00, 0x00, 0x00 },
+     { 0x00, 0x00, 0x80 },
+     { 0x00, 0x80, 0x00 },
+     { 0x00, 0x80, 0x80 },
+     { 0x80, 0x00, 0x00 },
+     { 0x80, 0x00, 0x80 },
+     { 0x80, 0x80, 0x00 },
+     { 0xc0, 0xc0, 0xc0 },
+     { 0xc0, 0xdc, 0xc0 },
+     { 0xf0, 0xca, 0xa6 },
+     { 0xf0, 0xfb, 0xff },
+     { 0xa4, 0xa0, 0xa0 },
+     { 0x80, 0x80, 0x80 },
+     { 0x00, 0x00, 0xf0 },
+     { 0x00, 0xff, 0x00 },
+     { 0x00, 0xff, 0xff },
+     { 0xff, 0x00, 0x00 },
+     { 0xff, 0x00, 0xff },
+     { 0xff, 0xff, 0x00 },
+     { 0xff, 0xff, 0xff }
+ };
  
  UINT
  APIENTRY
@@@ -109,14 -153,15 +153,15 @@@ IntSetDIBColorTable
          if (StartIndex + Entries > (1 << biBitCount))
              Entries = (1 << biBitCount) - StartIndex;
  
-         PalGDI = PALETTE_LockPalette(psurf->hDIBPalette);
-         if (PalGDI == NULL)
+         if (psurf->ppal == NULL)
          {
              DC_UnlockDc(dc);
              SetLastWin32Error(ERROR_INVALID_HANDLE);
              return 0;
          }
  
+         PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
          for (Index = StartIndex;
               Index < StartIndex + Entries && Index < PalGDI->NumColors;
               Index++)
@@@ -181,14 -226,15 +226,15 @@@ IntGetDIBColorTable
          if (StartIndex + Entries > (1 << biBitCount))
              Entries = (1 << biBitCount) - StartIndex;
  
-         PalGDI = PALETTE_LockPalette(psurf->hDIBPalette);
-         if (PalGDI == NULL)
+         if (psurf->ppal == NULL)
          {
              DC_UnlockDc(dc);
              SetLastWin32Error(ERROR_INVALID_HANDLE);
              return 0;
          }
  
+         PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr);
          for (Index = StartIndex;
               Index < StartIndex + Entries && Index < PalGDI->NumColors;
               Index++)
@@@ -219,132 -265,67 +265,67 @@@ IntSetDIBits
      CONST BITMAPINFO  *bmi,
      UINT  ColorUse)
  {
-     SURFACE  *bitmap;
      HBITMAP     SourceBitmap;
+       PSURFACE    psurfDst, psurfSrc;
      INT         result = 0;
-     BOOL        copyBitsResult;
-     SURFOBJ    *DestSurf, *SourceSurf;
-     SIZEL       SourceSize;
-     POINTL      ZeroPoint;
-     RECTL       DestRect;
-     EXLATEOBJ   exlo;
-     PPALETTE    ppalDDB, ppalDIB;
-     //RGBQUAD    *lpRGB;
-     HPALETTE    DDB_Palette, DIB_Palette;
-     ULONG       DIB_Palette_Type;
-     INT         DIBWidth;
-     // Check parameters
-     if (!(bitmap = SURFACE_LockSurface(hBitmap)))
-     {
-         return 0;
-     }
-     // Get RGB values
-     //if (ColorUse == DIB_PAL_COLORS)
-     //  lpRGB = DIB_MapPaletteColors(hDC, bmi);
-     //else
-     //  lpRGB = &bmi->bmiColors;
-     DestSurf = &bitmap->SurfObj;
+       RECT            rcDst;
+       POINTL          ptSrc;
+       PVOID           pvBits;
+       EXLATEOBJ       exlo;
  
-     // Create source surface
-     SourceSize.cx = bmi->bmiHeader.biWidth;
-     SourceSize.cy = ScanLines;
-     // Determine width of DIB
-     DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
-     SourceBitmap = EngCreateBitmap(SourceSize,
-                                    DIBWidth,
-                                    BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
-                                    bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
-                                    (PVOID) Bits);
-     if (0 == SourceBitmap)
+     SourceBitmap = DIB_CreateDIBSection(DC, bmi, ColorUse, &pvBits, NULL, 0, 0);
+       if (0 == SourceBitmap)
      {
-         SURFACE_UnlockSurface(bitmap);
+               DPRINT1("Error : Could not create a DIBSection.\n");
          SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
          return 0;
      }
  
-     SourceSurf = EngLockSurface((HSURF)SourceBitmap);
-     if (NULL == SourceSurf)
-     {
-         EngDeleteSurface((HSURF)SourceBitmap);
-         SURFACE_UnlockSurface(bitmap);
-         SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-         return 0;
-     }
+       RtlCopyMemory(pvBits, Bits, DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
+                                                                                                        bmi->bmiHeader.biHeight,
+                                                                                                        bmi->bmiHeader.biBitCount));
  
-     // Use hDIBPalette if it exists
-     if (bitmap->hDIBPalette)
-     {
-         DDB_Palette = bitmap->hDIBPalette;
-     }
-     else
-     {
-         // Destination palette obtained from the hDC
-         DDB_Palette = DC->ppdev->devinfo.hpalDefault;
-     }
-     ppalDDB = PALETTE_LockPalette(DDB_Palette);
-     if (NULL == ppalDDB)
-     {
-         EngUnlockSurface(SourceSurf);
-         EngDeleteSurface((HSURF)SourceBitmap);
-         SURFACE_UnlockSurface(bitmap);
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         return 0;
-     }
-     // Source palette obtained from the BITMAPINFO
-     DIB_Palette = BuildDIBPalette((PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type);
-     if (NULL == DIB_Palette)
-     {
-         EngUnlockSurface(SourceSurf);
-         EngDeleteSurface((HSURF)SourceBitmap);
-         SURFACE_UnlockSurface(bitmap);
-         SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-         return 0;
-     }
-     ppalDIB = PALETTE_LockPalette(DIB_Palette);
-     /* Initialize XLATEOBJ for color translation */
-     EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0);
+       psurfDst = SURFACE_LockSurface(hBitmap);
+       psurfSrc = SURFACE_LockSurface(SourceBitmap);
  
-     // Zero point
-     ZeroPoint.x = 0;
-     ZeroPoint.y = 0;
+       if(!(psurfSrc && psurfDst))
+       {
+               DPRINT1("Error, could not lock surfaces\n");
+               goto cleanup;
+       }
  
-     // Determine destination rectangle
-     DestRect.left     = 0;
-     DestRect.top      = abs(bmi->bmiHeader.biHeight) - StartScan - ScanLines;
-     DestRect.right    = SourceSize.cx;
-     DestRect.bottom   = DestRect.top + ScanLines;
+       rcDst.top = bmi->bmiHeader.biHeight < 0 ?
+               abs(bmi->bmiHeader.biHeight) - (ScanLines + StartScan) : StartScan;
+       rcDst.left = 0;
+       rcDst.bottom = rcDst.top + ScanLines;
+       rcDst.right = psurfDst->SurfObj.sizlBitmap.cx;
  
-     copyBitsResult = IntEngCopyBits(DestSurf, SourceSurf, NULL, &exlo.xlo, &DestRect, &ZeroPoint);
+       ptSrc.x = 0;
+       ptSrc.y = 0;
  
-     // If it succeeded, return number of scanlines copies
-     if (copyBitsResult == TRUE)
-     {
-         result = SourceSize.cy;
- // or
- //        result = abs(bmi->bmiHeader.biHeight) - StartScan;
-     }
+       EXLATEOBJ_vInitialize(&exlo, psurfSrc->ppal, psurfDst->ppal, 0, 0, 0);
  
-     // Clean up
-     EXLATEOBJ_vCleanup(&exlo);
-     PALETTE_UnlockPalette(ppalDIB);
-     PALETTE_UnlockPalette(ppalDDB);
-     PALETTE_FreePaletteByHandle(DIB_Palette);
-     EngUnlockSurface(SourceSurf);
-     EngDeleteSurface((HSURF)SourceBitmap);
+       result = IntEngCopyBits(&psurfDst->SurfObj,
+                                   &psurfSrc->SurfObj,
+                                                       NULL,
+                                                       &exlo.xlo,
+                                                       &rcDst,
+                                                       &ptSrc);
+       if(result)
+               result = ScanLines;
  
- //    if (ColorUse == DIB_PAL_COLORS)
- //        WinFree((LPSTR)lpRGB);
+       EXLATEOBJ_vCleanup(&exlo);
  
-     SURFACE_UnlockSurface(bitmap);
+ cleanup:
+       if(psurfSrc)
+       {
+               SURFACE_UnlockSurface(psurfSrc);
+       }
+       if(psurfDst)
+       {
+               SURFACE_UnlockSurface(psurfDst);
+       }
+       GreDeleteObject(SourceBitmap);
  
      return result;
  }
@@@ -366,17 -347,19 +347,19 @@@ NtGdiSetDIBits
      PDC Dc;
      INT Ret;
      NTSTATUS Status = STATUS_SUCCESS;
-     UINT cjBits;
  
      if (!Bits) return 0;
  
      _SEH2_TRY
-     {  // FYI: We converted from CORE in gdi.
-         ProbeForRead(bmi, sizeof(BITMAPINFO), 1);
-         cjBits = bmi->bmiHeader.biBitCount * bmi->bmiHeader.biPlanes * bmi->bmiHeader.biWidth;
-         cjBits = ((cjBits + 31) & ~31) / 8;
-         cjBits *= ScanLines;
-         ProbeForRead(Bits, cjBits, 1);
+     {
+         ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
+               ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
+               ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, ColorUse), 1);
+         ProbeForRead(Bits,
+                      DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
+                                           ScanLines,
+                                           bmi->bmiHeader.biBitCount),
+                                1);
      }
      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
      {
@@@ -440,15 -423,14 +423,14 @@@ NtGdiSetDIBitsToDeviceInternal
      INT DIBWidth;
      SIZEL SourceSize;
      EXLATEOBJ exlo;
-     PPALETTE ppalDDB = NULL, ppalDIB = NULL;
-     HPALETTE hpalDDB, hpalDIB = NULL;
-     ULONG DIBPaletteType;
+     PPALETTE ppalDIB = NULL;
+     HPALETTE hpalDIB = NULL;
  
      if (!Bits) return 0;
  
      _SEH2_TRY
      {
-         ProbeForRead(bmi, cjMaxInfo , 1);
+         ProbeForRead(bmi, cjMaxInfo, 1);
          ProbeForRead(Bits, cjMaxBits, 1);
      }
      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
          return 0;
      }
  
-     /* Use destination palette obtained from the DC by default */
-     hpalDDB = pDC->ppdev->devinfo.hpalDefault;
-     /* Try to use hDIBPalette if it exists */
      pSurf = pDC->dclevel.pSurface;
-     if (pSurf && pSurf->hDIBPalette)
-     {
-         hpalDDB = pSurf->hDIBPalette;
-     }
  
      pDestSurf = pSurf ? &pSurf->SurfObj : NULL;
  
      SourceSize.cx = bmi->bmiHeader.biWidth;
      SourceSize.cy = ScanLines;
  
-     DIBWidth = DIB_GetDIBWidthBytes(SourceSize.cx, bmi->bmiHeader.biBitCount);
+     DIBWidth = WIDTH_BYTES_ALIGN32(SourceSize.cx, bmi->bmiHeader.biBitCount);
  
      hSourceBitmap = EngCreateBitmap(SourceSize,
                                      DIBWidth,
-                                     BitmapFormat(bmi->bmiHeader.biBitCount, bmi->bmiHeader.biCompression),
+                                     BitmapFormat(bmi->bmiHeader.biBitCount,
+                                                  bmi->bmiHeader.biCompression),
                                      bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
                                      (PVOID) Bits);
      if (!hSourceBitmap)
          goto Exit;
      }
  
-     /* Obtain destination palette */
-     ppalDDB = PALETTE_LockPalette(hpalDDB);
-     if (!ppalDDB)
-     {
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         Status = STATUS_UNSUCCESSFUL;
-         goto Exit;
-     }
+     ASSERT(pSurf->ppal);
  
      /* Create a palette for the DIB */
-     hpalDIB = BuildDIBPalette(bmi, (PINT)&DIBPaletteType);
+     hpalDIB = BuildDIBPalette(bmi);
      if (!hpalDIB)
      {
          SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
  
      /* Lock the DIB palette */
      ppalDIB = PALETTE_LockPalette(hpalDIB);
-     if (!ppalDDB)
+     if (!ppalDIB)
      {
          SetLastWin32Error(ERROR_INVALID_HANDLE);
          Status = STATUS_UNSUCCESSFUL;
      }
  
      /* Initialize EXLATEOBJ */
-     EXLATEOBJ_vInitialize(&exlo, ppalDIB, ppalDDB, 0, 0, 0);
+     EXLATEOBJ_vInitialize(&exlo, ppalDIB, pSurf->ppal, 0, 0, 0);
  
      /* Copy the bits */
      DPRINT("BitsToDev with dstsurf=(%d|%d) (%d|%d), src=(%d|%d) w=%d h=%d\n",
@@@ -583,7 -551,6 +551,6 @@@ Exit
      }
  
      if (ppalDIB) PALETTE_UnlockPalette(ppalDIB);
-     if (ppalDDB) PALETTE_UnlockPalette(ppalDDB);
  
      if (pSourceSurf) EngUnlockSurface(pSourceSurf);
      if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
@@@ -608,37 -575,29 +575,29 @@@ NtGdiGetDIBitsInternal
      UINT MaxBits,
      UINT MaxInfo)
  {
-     PDC Dc;
-     SURFACE *psurf = NULL;
-     HBITMAP hDestBitmap = NULL;
-     HPALETTE hSourcePalette = NULL;
-     HPALETTE hDestPalette = NULL;
-     PPALETTE ppalSrc = NULL;
-     PPALETTE ppalDst = NULL;
-     NTSTATUS Status = STATUS_SUCCESS;
-     ULONG Result = 0;
-     BOOL bPaletteMatch = FALSE;
-     PBYTE ChkBits = Bits;
-     PVOID ColorPtr;
-     RGBQUAD *rgbQuads;
-     ULONG DestPaletteType;
-     ULONG Index;
+       BITMAPCOREINFO* pbmci = NULL;
+       PSURFACE psurf = NULL;
+       PDC pDC;
+       LONG width, height;
+       WORD planes, bpp;
+       DWORD compr, size ;
+       int i, bitmap_type;
+       RGBTRIPLE* rgbTriples;
+       RGBQUAD* rgbQuads;
+       VOID* colorPtr;
+       NTSTATUS Status = STATUS_SUCCESS;
  
      DPRINT("Entered NtGdiGetDIBitsInternal()\n");
  
      if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
          return 0;
  
-     // if ScanLines == 0, no need to copy Bits.
-     if (!ScanLines)
-         ChkBits = NULL;
      _SEH2_TRY
      {
-         ProbeForRead(&Info->bmiHeader.biSize, sizeof(DWORD), 1);
-         ProbeForWrite(Info, Info->bmiHeader.biSize, 1); // Comp for Core.
-         if (ChkBits) ProbeForWrite(ChkBits, MaxBits, 1);
+               /* Probe for read and write */
+         ProbeForRead(Info, MaxInfo, 1);
+               ProbeForWrite(Info, MaxInfo, 1);
+         if (Bits) ProbeForWrite(Bits, MaxBits, 1);
      }
      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
      {
          return 0;
      }
  
-     Dc = DC_LockDc(hDC);
-     if (Dc == NULL) return 0;
-     if (Dc->dctype == DC_TYPE_INFO)
+       colorPtr = (LPBYTE)Info + Info->bmiHeader.biSize;
+       rgbTriples = colorPtr;
+       rgbQuads = colorPtr;
+       bitmap_type = DIB_GetBitmapInfo(&Info->bmiHeader,
+                                           &width,
+                                                                       &height,
+                                                                       &planes,
+                                                                       &bpp,
+                                                                       &compr,
+                                                                       &size);
+       if(bitmap_type == -1)
+       {
+               DPRINT("Wrong bitmap format\n");
+               SetLastWin32Error(ERROR_INVALID_PARAMETER);
+               return 0;
+       }
+       else if(bitmap_type == 0)
+       {
+               /* We need a BITMAPINFO to create a DIB, but we have to fill
+                * the BITMAPCOREINFO we're provided */
+               pbmci = (BITMAPCOREINFO*)Info;
+               Info = DIB_ConvertBitmapInfo((BITMAPINFO*)pbmci, Usage);
+               if(Info == NULL)
+               {
+                       DPRINT1("Error, could not convert the BITMAPCOREINFO!\n");
+                       return 0;
+               }
+               rgbQuads = Info->bmiColors;
+       }
+     pDC = DC_LockDc(hDC);
+     if (pDC == NULL || pDC->dctype == DC_TYPE_INFO)
      {
-         DC_UnlockDc(Dc);
-         return 0;
+               ScanLines = 0;
+         goto done;
      }
-     DC_UnlockDc(Dc);
  
      /* Get a pointer to the source bitmap object */
      psurf = SURFACE_LockSurface(hBitmap);
      if (psurf == NULL)
-         return 0;
-     hSourcePalette = psurf->hDIBPalette;
-     if (!hSourcePalette)
-     {
-         hSourcePalette = pPrimarySurface->devinfo.hpalDefault;
-     }
-     ColorPtr = ((PBYTE)Info + Info->bmiHeader.biSize);
-     rgbQuads = (RGBQUAD *)ColorPtr;
-     /* Copy palette information
-      * Always create a palette for 15 & 16 bit. */
-     if ((Info->bmiHeader.biBitCount == BitsPerFormat(psurf->SurfObj.iBitmapFormat) &&
-          Info->bmiHeader.biBitCount != 15 && Info->bmiHeader.biBitCount != 16) ||
-          !ChkBits)
      {
-         hDestPalette = hSourcePalette;
-         bPaletteMatch = TRUE;
-     }
-     else
-         hDestPalette = BuildDIBPalette(Info, (PINT)&DestPaletteType); //hDestPalette = Dc->DevInfo->hpalDefault;
-     ppalSrc = PALETTE_LockPalette(hSourcePalette);
-     /* FIXME - ppalSrc can be NULL!!! Don't assert here! */
-     ASSERT(ppalSrc);
-     if (!bPaletteMatch)
-     {
-         ppalDst = PALETTE_LockPalette(hDestPalette);
-         /* FIXME - ppalDst can be NULL!!!! Don't assert here!!! */
-         DPRINT("ppalDst : %p\n", ppalDst);
-         ASSERT(ppalDst);
-     }
-     else
-     {
-         ppalDst = ppalSrc;
-     }
-     /* Copy palette. */
-     /* FIXME: This is largely incomplete. ATM no Core!*/
-     switch (Info->bmiHeader.biBitCount)
-     {
-         case 1:
-         case 4:
-         case 8:
-             Info->bmiHeader.biClrUsed = 0;
-             if (psurf->hSecure &&
-                 BitsPerFormat(psurf->SurfObj.iBitmapFormat) == Info->bmiHeader.biBitCount)
-             {
-                 if (Usage == DIB_RGB_COLORS)
-                 {
-                     if (ppalDst->NumColors != 1 << Info->bmiHeader.biBitCount)
-                         Info->bmiHeader.biClrUsed = ppalDst->NumColors;
-                     for (Index = 0;
-                          Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
-                          Index++)
-                     {
-                         rgbQuads[Index].rgbRed   = ppalDst->IndexedColors[Index].peRed;
-                         rgbQuads[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
-                         rgbQuads[Index].rgbBlue  = ppalDst->IndexedColors[Index].peBlue;
-                         rgbQuads[Index].rgbReserved = 0;
-                     }
-                 }
-                 else
-                 {
-                     PWORD Ptr = ColorPtr;
-                     for (Index = 0;
-                          Index < (1 << Info->bmiHeader.biBitCount);
-                          Index++)
+         ScanLines = 0;
+         goto done;
+     }
+       /* Fill in the structure */
+       switch(bpp)
+       {
+       case 0: /* Only info */
+               if(pbmci)
+               {
+                       pbmci->bmciHeader.bcWidth = psurf->SurfObj.sizlBitmap.cx;
+                       pbmci->bmciHeader.bcHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
+                               -psurf->SurfObj.sizlBitmap.cy :
+                           psurf->SurfObj.sizlBitmap.cy;
+                       pbmci->bmciHeader.bcPlanes = 1;
+                       pbmci->bmciHeader.bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+               }
+               Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
+               Info->bmiHeader.biHeight = (psurf->SurfObj.fjBitmap & BMF_TOPDOWN) ?
+                       -psurf->SurfObj.sizlBitmap.cy :
+                   psurf->SurfObj.sizlBitmap.cy;;
+               Info->bmiHeader.biPlanes = 1;
+               Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
+               Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes( Info->bmiHeader.biWidth,
+                                                                                                                       Info->bmiHeader.biHeight,
+                                                                                                                       Info->bmiHeader.biBitCount);
+               if(psurf->hSecure)
+               {
+                       switch(Info->bmiHeader.biBitCount)
+                       {
+                       case 16:
+                       case 32:
+                               Info->bmiHeader.biCompression = BI_BITFIELDS;
+                               break;
+                       default:
+                               Info->bmiHeader.biCompression = BI_RGB;
+                               break;
+                       }
+               }
+               else if(Info->bmiHeader.biBitCount > 8)
+               {
+                       Info->bmiHeader.biCompression = BI_BITFIELDS;
+               }
+               else
+               {
+                       Info->bmiHeader.biCompression = BI_RGB;
+               }
+               Info->bmiHeader.biXPelsPerMeter = 0;
+         Info->bmiHeader.biYPelsPerMeter = 0;
+         Info->bmiHeader.biClrUsed = 0;
+         Info->bmiHeader.biClrImportant = 0;
+               ScanLines = abs(Info->bmiHeader.biHeight);
+               goto done;
+       case 1:
+       case 4:
+       case 8:
+               Info->bmiHeader.biClrUsed = 0;
+               /* If the bitmap if a DIB section and has the same format than what
+                * we're asked, go ahead! */
+               if((psurf->hSecure) &&
+                       (BitsPerFormat(psurf->SurfObj.iBitmapFormat) == bpp))
+               {
+                       if(Usage == DIB_RGB_COLORS)
+                       {
+                               unsigned int colors = min(psurf->ppal->NumColors, 1 << bpp);
+                               if(pbmci)
+                               {
+                                       for(i=0; i < colors; i++)
+                                       {
+                                               rgbTriples[i].rgbtRed = psurf->ppal->IndexedColors[i].peRed;
+                                               rgbTriples[i].rgbtGreen = psurf->ppal->IndexedColors[i].peGreen;
+                                               rgbTriples[i].rgbtBlue = psurf->ppal->IndexedColors[i].peBlue;
+                                       }
+                               }
+                               if(colors != 1 << bpp) Info->bmiHeader.biClrUsed = colors;
+                               for(i=0; i < colors; i++)
+                               {
+                                       rgbQuads[i].rgbRed = psurf->ppal->IndexedColors[i].peRed;
+                                       rgbQuads[i].rgbGreen = psurf->ppal->IndexedColors[i].peGreen;
+                                       rgbQuads[i].rgbBlue = psurf->ppal->IndexedColors[i].peBlue;
+                               }
+                       }
+                       else
+                       {
+                               for(i=0; i < 1 << bpp; i++)
+                               {
+                                       if(pbmci) ((WORD*)rgbTriples)[i] = i;
+                                       ((WORD*)rgbQuads)[i] = i;
+                               }
+                       }
+               }
+               else
+               {
+                       if(Usage == DIB_PAL_COLORS)
+                       {
+                               for(i=0; i < 1 << bpp; i++)
+                               {
+                                       if(pbmci) ((WORD*)rgbTriples)[i] = i;
+                                       ((WORD*)rgbQuads)[i] = i;
+                               }
+                       }
+                       else if(bpp > 1 && bpp == BitsPerFormat(psurf->SurfObj.iBitmapFormat)) {
+                 /* For color DDBs in native depth (mono DDBs always have
+                    a black/white palette):
+                    Generate the color map from the selected palette */
+                 PPALETTE pDcPal = PALETTE_LockPalette(pDC->dclevel.hpal);
+                               if(!pDcPal)
+                               {
+                                       ScanLines = 0 ;
+                                       goto done ;
+                               }
+                 for (i = 0; i < pDcPal->NumColors; i++) {
+                     if (pbmci)
                      {
-                         Ptr[Index] = (WORD)Index;
+                         rgbTriples[i].rgbtRed   = pDcPal->IndexedColors[i].peRed;
+                         rgbTriples[i].rgbtGreen = pDcPal->IndexedColors[i].peGreen;
+                         rgbTriples[i].rgbtBlue  = pDcPal->IndexedColors[i].peBlue;
                      }
-                 }
-             }
-             else
-             {
-                 if (Usage == DIB_PAL_COLORS)
-                 {
-                     PWORD Ptr = ColorPtr;
-                     for (Index = 0;
-                          Index < (1 << Info->bmiHeader.biBitCount);
-                          Index++)
-                     {
-                         Ptr[Index] = (WORD)Index;
-                     }
-                 }
-                 else if (Info->bmiHeader.biBitCount > 1  && bPaletteMatch)
-                 {
-                     for (Index = 0;
-                          Index < (1 << Info->bmiHeader.biBitCount) && Index < ppalDst->NumColors;
-                          Index++)
+                     rgbQuads[i].rgbRed      = pDcPal->IndexedColors[i].peRed;
+                     rgbQuads[i].rgbGreen    = pDcPal->IndexedColors[i].peGreen;
+                     rgbQuads[i].rgbBlue     = pDcPal->IndexedColors[i].peBlue;
+                     rgbQuads[i].rgbReserved = 0;
+                               }
+                               PALETTE_UnlockPalette(pDcPal);
+             } else {
+                 switch (bpp) {
+                 case 1:
+                     if (pbmci)
                      {
-                         Info->bmiColors[Index].rgbRed   = ppalDst->IndexedColors[Index].peRed;
-                         Info->bmiColors[Index].rgbGreen = ppalDst->IndexedColors[Index].peGreen;
-                         Info->bmiColors[Index].rgbBlue  = ppalDst->IndexedColors[Index].peBlue;
-                         Info->bmiColors[Index].rgbReserved = 0;
+                         rgbTriples[0].rgbtRed = rgbTriples[0].rgbtGreen =
+                             rgbTriples[0].rgbtBlue = 0;
+                         rgbTriples[1].rgbtRed = rgbTriples[1].rgbtGreen =
+                             rgbTriples[1].rgbtBlue = 0xff;
                      }
-                 }
-                 else
-                 {
-                     switch (Info->bmiHeader.biBitCount)
+                     rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen =
+                         rgbQuads[0].rgbBlue = 0;
+                     rgbQuads[0].rgbReserved = 0;
+                     rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen =
+                         rgbQuads[1].rgbBlue = 0xff;
+                     rgbQuads[1].rgbReserved = 0;
+                     break;
+                 case 4:
+                     if (pbmci)
+                         RtlCopyMemory(rgbTriples, EGAColorsTriples, sizeof(EGAColorsTriples));
+                     RtlCopyMemory(rgbQuads, EGAColorsQuads, sizeof(EGAColorsQuads));
+                     break;
+                 case 8:
                      {
-                         case 1:
-                             rgbQuads[0].rgbRed = rgbQuads[0].rgbGreen = rgbQuads[0].rgbBlue = 0;
-                             rgbQuads[0].rgbReserved = 0;
-                             rgbQuads[1].rgbRed = rgbQuads[1].rgbGreen = rgbQuads[1].rgbBlue = 0xff;
-                             rgbQuads[1].rgbReserved = 0;
-                             break;
-                         case 4:
-                             RtlCopyMemory(ColorPtr, EGAColorsQuads, sizeof(EGAColorsQuads));
-                             break;
-                         case 8:
+                                               INT r, g, b;
+                         RGBQUAD *color;
+                         if (pbmci)
                          {
-                             INT r, g, b;
-                             RGBQUAD *color;
-                             RtlCopyMemory(rgbQuads, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
-                             RtlCopyMemory(rgbQuads + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
-                             color = rgbQuads + 10;
-                             for (r = 0; r <= 5; r++) /* FIXME */
-                                 for (g = 0; g <= 5; g++)
-                                     for (b = 0; b <= 5; b++)
-                                     {
-                                         color->rgbRed = (r * 0xff) / 5;
-                                         color->rgbGreen = (g * 0xff) / 5;
-                                         color->rgbBlue = (b * 0xff) / 5;
-                                         color->rgbReserved = 0;
+                             RGBTRIPLE *colorTriple;
+                             RtlCopyMemory(rgbTriples, DefLogPaletteTriples,
+                                        10 * sizeof(RGBTRIPLE));
+                             RtlCopyMemory(rgbTriples + 246, DefLogPaletteTriples + 10,
+                                        10 * sizeof(RGBTRIPLE));
+                             colorTriple = rgbTriples + 10;
+                             for(r = 0; r <= 5; r++) /* FIXME */
+                                                       {
+                                 for(g = 0; g <= 5; g++)
+                                                               {
+                                     for(b = 0; b <= 5; b++)
+                                                                       {
+                                         colorTriple->rgbtRed =   (r * 0xff) / 5;
+                                         colorTriple->rgbtGreen = (g * 0xff) / 5;
+                                         colorTriple->rgbtBlue =  (b * 0xff) / 5;
                                          color++;
                                      }
+                                                               }
+                                                       }
                          }
-                         break;
+                                               memcpy(rgbQuads, DefLogPaletteQuads,
+                                    10 * sizeof(RGBQUAD));
+                         memcpy(rgbQuads + 246, DefLogPaletteQuads + 10,
+                                10 * sizeof(RGBQUAD));
+                         color = rgbQuads + 10;
+                         for(r = 0; r <= 5; r++) /* FIXME */
+                                               {
+                             for(g = 0; g <= 5; g++)
+                                                       {
+                                 for(b = 0; b <= 5; b++)
+                                                               {
+                                     color->rgbRed =   (r * 0xff) / 5;
+                                     color->rgbGreen = (g * 0xff) / 5;
+                                     color->rgbBlue =  (b * 0xff) / 5;
+                                     color->rgbReserved = 0;
+                                     color++;
+                                 }
+                                                       }
+                                               }
                      }
                  }
              }
+         }
+         break;
  
-         case 15:
-             if (Info->bmiHeader.biCompression == BI_BITFIELDS)
-             {
-                 ((PDWORD)Info->bmiColors)[0] = 0x7c00;
-                 ((PDWORD)Info->bmiColors)[1] = 0x03e0;
-                 ((PDWORD)Info->bmiColors)[2] = 0x001f;
-             }
-             break;
+     case 15:
+         if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+         {
+             ((PDWORD)Info->bmiColors)[0] = 0x7c00;
+             ((PDWORD)Info->bmiColors)[1] = 0x03e0;
+             ((PDWORD)Info->bmiColors)[2] = 0x001f;
+         }
+         break;
  
-         case 16:
-             if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+     case 16:
+         if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+         {
+             if (psurf->hSecure)
+                       {
+                               ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
+                 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
+                 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
+                       }
+             else
              {
                  ((PDWORD)Info->bmiColors)[0] = 0xf800;
                  ((PDWORD)Info->bmiColors)[1] = 0x07e0;
                  ((PDWORD)Info->bmiColors)[2] = 0x001f;
              }
-             break;
+         }
+         break;
  
-         case 24:
-         case 32:
-             if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+     case 24:
+     case 32:
+         if (Info->bmiHeader.biCompression == BI_BITFIELDS)
+         {
+             if (psurf->hSecure)
+                       {
+                               ((PDWORD)Info->bmiColors)[0] = psurf->ppal->RedMask;
+                 ((PDWORD)Info->bmiColors)[1] = psurf->ppal->GreenMask;
+                 ((PDWORD)Info->bmiColors)[2] = psurf->ppal->BlueMask;
+                       }
+             else
              {
                  ((PDWORD)Info->bmiColors)[0] = 0xff0000;
                  ((PDWORD)Info->bmiColors)[1] = 0x00ff00;
                  ((PDWORD)Info->bmiColors)[2] = 0x0000ff;
              }
-             break;
-     }
-     if (!bPaletteMatch)
-         PALETTE_UnlockPalette(ppalDst);
-     /* fill out the BITMAPINFO struct */
-     if (!ChkBits)
-     {  // Core or not to Core? We have converted from Core in Gdi~ so?
-         if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
-         {
-             BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
-             coreheader->bcWidth = psurf->SurfObj.sizlBitmap.cx;
-             coreheader->bcPlanes = 1;
-             coreheader->bcBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
-             coreheader->bcHeight = psurf->SurfObj.sizlBitmap.cy;
-             if (psurf->SurfObj.lDelta > 0)
-                 coreheader->bcHeight = -coreheader->bcHeight;
-         }
-         if (Info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
-         {
-             Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
-             Info->bmiHeader.biHeight = psurf->SurfObj.sizlBitmap.cy;
-             Info->bmiHeader.biPlanes = 1;
-             Info->bmiHeader.biBitCount = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
-             switch (psurf->SurfObj.iBitmapFormat)
-             {
-                     /* FIXME: What about BI_BITFIELDS? */
-                 case BMF_1BPP:
-                 case BMF_4BPP:
-                 case BMF_8BPP:
-                 case BMF_16BPP:
-                 case BMF_24BPP:
-                 case BMF_32BPP:
-                     Info->bmiHeader.biCompression = BI_RGB;
-                     break;
-                 case BMF_4RLE:
-                     Info->bmiHeader.biCompression = BI_RLE4;
-                     break;
-                 case BMF_8RLE:
-                     Info->bmiHeader.biCompression = BI_RLE8;
-                     break;
-                 case BMF_JPEG:
-                     Info->bmiHeader.biCompression = BI_JPEG;
-                     break;
-                 case BMF_PNG:
-                     Info->bmiHeader.biCompression = BI_PNG;
-                     break;
-             }
-             /* Image size has to be calculated */
-             Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(Info->bmiHeader.biWidth,
-                                           Info->bmiHeader.biBitCount) * Info->bmiHeader.biHeight;
-             Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
-             Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
-             Info->bmiHeader.biClrUsed = 0;
-             Info->bmiHeader.biClrImportant = 1 << Info->bmiHeader.biBitCount; /* FIXME */
-             /* Report negtive height for top-down bitmaps. */
-             if (psurf->SurfObj.lDelta > 0)
-                 Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
          }
-         Result = psurf->SurfObj.sizlBitmap.cy;
-     }
-     else
-     {
-         SIZEL DestSize;
-         POINTL SourcePoint;
- //
- // If we have a good dib pointer, why not just copy bits from there w/o XLATE'ing them.
- //
-         /* Create the destination bitmap too for the copy operation */
-         if (StartScan > psurf->SurfObj.sizlBitmap.cy)
+         break;
+     }
+       Info->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(width, height, bpp);
+       if(Bits && ScanLines)
+       {
+               /* Create a DIBSECTION, blt it, profit */
+               PVOID pDIBits ;
+               HBITMAP hBmpDest;
+               PSURFACE psurfDest;
+               EXLATEOBJ exlo;
+               RECT rcDest;
+               POINTL srcPoint;
+               BOOL ret ;
+               if (StartScan > psurf->SurfObj.sizlBitmap.cy)
          {
-             goto cleanup;
+                       ScanLines = 0;
+             goto done;
          }
          else
          {
              ScanLines = min(ScanLines, psurf->SurfObj.sizlBitmap.cy - StartScan);
-             DestSize.cx = psurf->SurfObj.sizlBitmap.cx;
-             DestSize.cy = ScanLines;
-             hDestBitmap = NULL;
-             if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
-             {
-                 BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
-                 hDestBitmap = EngCreateBitmap(DestSize,
-                                               DIB_GetDIBWidthBytes(DestSize.cx, coreheader->bcBitCount),
-                                               BitmapFormat(coreheader->bcBitCount, BI_RGB),
-                                               0 < coreheader->bcHeight ? 0 : BMF_TOPDOWN,
-                                               Bits);
-             }
-             if (Info->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
-             {
-                 Info->bmiHeader.biSizeImage = DIB_GetDIBWidthBytes(DestSize.cx,
-                                               Info->bmiHeader.biBitCount) * DestSize.cy;
-                 hDestBitmap = EngCreateBitmap(DestSize,
-                                               DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount),
-                                               BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
-                                               0 < Info->bmiHeader.biHeight ? 0 : BMF_TOPDOWN,
-                                               Bits);
-             }
-             if (hDestBitmap == NULL)
-                 goto cleanup;
-         }
-         if (NT_SUCCESS(Status))
-         {
-             EXLATEOBJ exlo;
-             SURFOBJ *DestSurfObj;
-             RECTL DestRect;
-             EXLATEOBJ_vInitialize(&exlo, ppalSrc, ppalDst, 0, 0, 0);
-             SourcePoint.x = 0;
-             SourcePoint.y = psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines);
-             /* Determine destination rectangle */
-             DestRect.top = 0;
-             DestRect.left = 0;
-             DestRect.right = DestSize.cx;
-             DestRect.bottom = DestSize.cy;
-             DestSurfObj = EngLockSurface((HSURF)hDestBitmap);
-             if (IntEngCopyBits(DestSurfObj,
-                                &psurf->SurfObj,
-                                NULL,
-                                &exlo.xlo,
-                                &DestRect,
-                                &SourcePoint))
-             {
-                 DPRINT("GetDIBits %d \n",abs(Info->bmiHeader.biHeight) - StartScan);
-                 Result = ScanLines;
-             }
-             EXLATEOBJ_vCleanup(&exlo);
-             EngUnlockSurface(DestSurfObj);
-         }
-     }
- cleanup:
-     PALETTE_UnlockPalette(ppalSrc);
-     if (hDestBitmap != NULL)
-         EngDeleteSurface((HSURF)hDestBitmap);
-     if (hDestPalette != NULL && bPaletteMatch == FALSE)
-         PALETTE_FreePaletteByHandle(hDestPalette);
-     SURFACE_UnlockSurface(psurf);
-     DPRINT("leaving NtGdiGetDIBitsInternal\n");
-     return Result;
+               }
+               /* Fixup values */
+               Info->bmiHeader.biWidth = psurf->SurfObj.sizlBitmap.cx;
+               Info->bmiHeader.biHeight = height < 0 ?
+                       -ScanLines : ScanLines;
+               /* Create the DIB */
+               hBmpDest = DIB_CreateDIBSection(pDC, Info, Usage, &pDIBits, NULL, 0, 0);
+               /* Restore them */
+               Info->bmiHeader.biWidth = width;
+               Info->bmiHeader.biHeight = height;
+               if(!hBmpDest)
+               {
+                       DPRINT1("Unable to create a DIB Section!\n");
+                       SetLastWin32Error(ERROR_INVALID_PARAMETER);
+                       ScanLines = 0;
+                       goto done ;
+               }
+               psurfDest = SURFACE_LockSurface(hBmpDest);
+               rcDest.left = 0;
+               rcDest.top = 0;
+               rcDest.bottom = ScanLines;
+               rcDest.right = psurf->SurfObj.sizlBitmap.cx;
+               srcPoint.x = 0;
+               srcPoint.y = height < 0 ?
+                       psurf->SurfObj.sizlBitmap.cy - (StartScan + ScanLines) : StartScan;
+               EXLATEOBJ_vInitialize(&exlo, psurf->ppal, psurfDest->ppal, 0, 0, 0);
+               ret = IntEngCopyBits(&psurfDest->SurfObj,
+                                                        &psurf->SurfObj,
+                                                        NULL,
+                                                        &exlo.xlo,
+                                                        &rcDest,
+                                                        &srcPoint);
+               if(!ret)
+                       ScanLines = 0;
+               else
+               {
+                       Status = STATUS_SUCCESS;
+                       _SEH2_TRY
+                       {
+                               RtlCopyMemory(Bits, pDIBits, DIB_GetDIBImageBytes (width, height, bpp));
+                       }
+                       _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+                       {
+                               Status = _SEH2_GetExceptionCode();
+                       }
+                       _SEH2_END
+                       if(!NT_SUCCESS(Status))
+                       {
+                               DPRINT1("Unable to copy bits to the user provided pointer\n");
+                               ScanLines = 0;
+                       }
+               }
+               GreDeleteObject(hBmpDest);
+               EXLATEOBJ_vCleanup(&exlo);
+       }
+       else ScanLines = abs(height);
+ done:
+       if(pDC) DC_UnlockDc(pDC);
+       if(psurf) SURFACE_UnlockSurface(psurf);
+       if(pbmci) DIB_FreeConvertedBitmapInfo(Info, (BITMAPINFO*)pbmci);
+       return ScanLines;
  }
  
  INT
  APIENTRY
  NtGdiStretchDIBitsInternal(
      UINT cjMaxBits,
      HANDLE hcmXform)
  {
-     HBITMAP hBitmap, hOldBitmap = NULL;
-     HDC hdcMem;
-     HPALETTE hPal = NULL;
-     PDC pDC;
-     BOOL Hit = FALSE;
+     PDC pdc;
+     INT ret = 0;
+     LONG height;
+     LONG width;
+     WORD planes, bpp;
+     DWORD compr, size;
+     HBITMAP hBitmap;
+     BOOL fastpath = FALSE;
+     NTSTATUS Status = STATUS_SUCCESS;
+       PBYTE safeBits ;
  
      if (!Bits || !BitsInfo)
-     {
-         SetLastWin32Error(ERROR_INVALID_PARAMETER);
          return 0;
-     }
+       safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
+       if(!safeBits)
+       {
+               SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+               return 0;
+       }
+     if (!(pdc = DC_LockDc(hDC)))
+       {
+               ExFreePoolWithTag(safeBits, TAG_DIB);
+               SetLastWin32Error(ERROR_INVALID_HANDLE);
+               return 0;
+       }
  
      _SEH2_TRY
      {
          ProbeForRead(BitsInfo, cjMaxInfo, 1);
          ProbeForRead(Bits, cjMaxBits, 1);
+         if (DIB_GetBitmapInfo( &BitsInfo->bmiHeader, &width, &height, &planes, &bpp, &compr, &size ) == -1)
+         {
+             DPRINT1("Invalid bitmap\n");
+             Status = STATUS_INVALID_PARAMETER;
+         }
+               RtlCopyMemory(safeBits, Bits, cjMaxBits);
      }
      _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
      {
-         Hit = TRUE;
+         Status = _SEH2_GetExceptionCode();
      }
      _SEH2_END
  
-     if (Hit)
-     {
-         DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits);
-         return 0;
-     }
-     hdcMem = NtGdiCreateCompatibleDC(hDC);
-     if (hdcMem == NULL)
+     if(!NT_SUCCESS(Status))
      {
-         DPRINT1("NtGdiCreateCompatibleDC fail create hdc\n");
-         return 0;
+         DPRINT1("Error, failed to read the DIB bits\n");
+         goto cleanup;
      }
  
-     hBitmap = NtGdiCreateCompatibleBitmap(hDC,
-                                           abs(BitsInfo->bmiHeader.biWidth),
-                                           abs(BitsInfo->bmiHeader.biHeight));
-     if (hBitmap == NULL)
+     if (width < 0)
      {
-         DPRINT1("NtGdiCreateCompatibleBitmap fail create bitmap\n");
-         DPRINT1("hDC : 0x%08x \n", hDC);
-         DPRINT1("BitsInfo->bmiHeader.biWidth : 0x%08x \n", BitsInfo->bmiHeader.biWidth);
-         DPRINT1("BitsInfo->bmiHeader.biHeight : 0x%08x \n", BitsInfo->bmiHeader.biHeight);
+         DPRINT1("Bitmap has a negative width\n");
          return 0;
      }
  
-     /* Select the bitmap into hdcMem, and save a handle to the old bitmap */
-     hOldBitmap = NtGdiSelectBitmap(hdcMem, hBitmap);
+     hBitmap = NtGdiGetDCObject(hDC, OBJ_BITMAP);
  
-     if (Usage == DIB_PAL_COLORS)
+     if (XDest == 0 && YDest == 0 && XSrc == 0 && XSrc == 0 &&
+         DestWidth == SrcWidth && DestHeight == SrcHeight &&
+         compr == BI_RGB &&
+         ROP == SRCCOPY)
      {
-         hPal = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE);
-         hPal = GdiSelectPalette(hdcMem, hPal, FALSE);
+         BITMAP bmp;
+         if (IntGdiGetObject(hBitmap, sizeof(bmp), &bmp) == sizeof(bmp))
+         {
+             if (bmp.bmBitsPixel == bpp &&
+                 bmp.bmWidth == SrcWidth &&
+                 bmp.bmHeight == SrcHeight &&
+                 bmp.bmPlanes == planes)
+                 fastpath = TRUE;
+         }
      }
  
-     if (BitsInfo->bmiHeader.biCompression == BI_RLE4 ||
-             BitsInfo->bmiHeader.biCompression == BI_RLE8)
+     if (fastpath)
      {
-         /* copy existing bitmap from destination dc */
-         if (SrcWidth == DestWidth && SrcHeight == DestHeight)
-             NtGdiBitBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
-                         SrcWidth, SrcHeight, hDC, XDest, YDest, ROP, 0, 0);
-         else
-             NtGdiStretchBlt(hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
-                             SrcWidth, SrcHeight, hDC, XDest, YDest, DestWidth, DestHeight,
-                             ROP, 0);
+         /* fast path */
+         DPRINT1("using fast path\n");
+         ret = IntSetDIBits( pdc, hBitmap, 0, height, safeBits, BitsInfo, Usage);
      }
-     pDC = DC_LockDc(hdcMem);
-     if (pDC != NULL)
+     else
      {
-         /* Note BitsInfo->bmiHeader.biHeight is the number of scanline,
-          * if it negitve we getting to many scanline for scanline is UINT not
-          * a INT, so we need make the negtive value to positve and that make the
-          * count correct for negtive bitmap, TODO : we need testcase for this api */
-         IntSetDIBits(pDC, hBitmap, 0, abs(BitsInfo->bmiHeader.biHeight), Bits,
-                      BitsInfo, Usage);
-         DC_UnlockDc(pDC);
+         /* slow path - need to use StretchBlt */
+         HBITMAP hOldBitmap;
+         HDC hdcMem;
+         PVOID pvBits;
+         hdcMem = NtGdiCreateCompatibleDC( hDC );
+         hBitmap = DIB_CreateDIBSection(pdc, BitsInfo, Usage, &pvBits, NULL, 0, 0);
+               if(!hBitmap)
+               {
+                       DPRINT1("Error, failed to create a DIB section\n");
+                       NtGdiDeleteObjectApp(hdcMem);
+                       goto cleanup;
+               }
+         RtlCopyMemory(pvBits, safeBits, cjMaxBits);
+         hOldBitmap = NtGdiSelectBitmap( hdcMem, hBitmap );
+         /* Origin for DIBitmap may be bottom left (positive biHeight) or top
+            left (negative biHeight) */
+         ret = NtGdiStretchBlt( hDC, XDest, YDest, DestWidth, DestHeight,
+                              hdcMem, XSrc, abs(height) - SrcHeight - YSrc,
+                              SrcWidth, SrcHeight, ROP, 0 );
+         
+               if(ret)
+             ret = SrcHeight;
+         NtGdiSelectBitmap( hdcMem, hOldBitmap );
+         NtGdiDeleteObjectApp( hdcMem );
+         GreDeleteObject( hBitmap );
      }
-     /* Origin for DIBitmap may be bottom left (positive biHeight) or top
-        left (negative biHeight) */
-     if (SrcWidth == DestWidth && SrcHeight == DestHeight)
-         NtGdiBitBlt(hDC, XDest, YDest, DestWidth, DestHeight,
-                     hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
-                     ROP, 0, 0);
-     else
-         NtGdiStretchBlt(hDC, XDest, YDest, DestWidth, DestHeight,
-                         hdcMem, XSrc, abs(BitsInfo->bmiHeader.biHeight) - SrcHeight - YSrc,
-                         SrcWidth, SrcHeight, ROP, 0);
-     /* cleanup */
-     if (hPal)
-         GdiSelectPalette(hdcMem, hPal, FALSE);
-     if (hOldBitmap)
-         NtGdiSelectBitmap(hdcMem, hOldBitmap);
-     NtGdiDeleteObjectApp(hdcMem);
-     GreDeleteObject(hBitmap);
-     return SrcHeight;
+ cleanup:
+       ExFreePoolWithTag(safeBits, TAG_DIB);
+     DC_UnlockDc(pdc);
+     return ret;
  }
  
  
@@@ -1137,40 -1161,19 +1161,19 @@@ IntCreateDIBitmap
      else if ((coloruse != DIB_RGB_COLORS) || (init != CBM_INIT) || !data) fColor = FALSE;
      else
      {
-         if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
-         {
-             const RGBQUAD *rgb = data->bmiColors;
-             DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
-             // Check if the first color of the colormap is black
-             if ((col == RGB(0, 0, 0)))
-             {
-                 rgb++;
-                 col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
+         const RGBQUAD *rgb = (RGBQUAD*)((PBYTE)data + data->bmiHeader.biSize);
+         DWORD col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
  
-                 // If the second color is white, create a monochrome bitmap
-                 fColor = (col != RGB(0xff,0xff,0xff));
-             }
-             else fColor = TRUE;
-         }
-         else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+         // Check if the first color of the colormap is black
+         if ((col == RGB(0, 0, 0)))
          {
-             RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
-             DWORD col = RGB(rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
+             rgb++;
+             col = RGB(rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue);
  
-             if ((col == RGB(0,0,0)))
-             {
-                 rgb++;
-                 col = RGB(rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
-                 fColor = (col != RGB(0xff,0xff,0xff));
-             }
-             else fColor = TRUE;
-         }
-         else
-         {
-             DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize);
-             return 0;
+             // If the second color is white, create a monochrome bitmap
+             fColor = (col != RGB(0xff,0xff,0xff));
          }
+         else fColor = TRUE;
      }
  
      // Now create the bitmap
      }
      else
      {
-         handle = IntGdiCreateBitmap(width,
-                                     height,
-                                     1,
-                                     1,
-                                     NULL);
+         handle = GreCreateBitmap(width,
+                                  height,
+                                  1,
+                                  1,
+                                  NULL);
      }
  
      if (height < 0)
@@@ -1214,72 -1217,106 +1217,106 @@@ NtGdiCreateDIBitmapInternal
      IN UINT cjMaxBits,
      IN FLONG fl,
      IN HANDLE hcmXform)
+ {
+     NTSTATUS Status = STATUS_SUCCESS;
+       PBYTE safeBits = NULL;
+       HBITMAP hbmResult = NULL;
+       if(pjInit && (fInit == CBM_INIT))
+       {
+               safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
+               if(!safeBits)
+               {
+                       SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
+                       return NULL;
+               }
+       }
+     _SEH2_TRY
+     {
+         if(pbmi) ProbeForRead(pbmi, cjMaxInitInfo, 1);
+         if(pjInit && (fInit == CBM_INIT))
+               {
+                       ProbeForRead(pjInit, cjMaxBits, 1);
+                       RtlCopyMemory(safeBits, pjInit, cjMaxBits);
+               }
+     }
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+         Status = _SEH2_GetExceptionCode();
+     }
+     _SEH2_END
+     if(!NT_SUCCESS(Status))
+     {
+         SetLastNtError(Status);
+               goto cleanup;
+     }
+     hbmResult =  GreCreateDIBitmapInternal(hDc,
+                                                              cx,
+                                                                  cy,
+                                                                              fInit,
+                                            safeBits,
+                                            pbmi,
+                                            iUsage,
+                                            fl,
+                                            hcmXform);
+ cleanup:
+       if (safeBits) ExFreePoolWithTag(safeBits, TAG_DIB);
+       return hbmResult;
+ }
+ HBITMAP
+ FASTCALL
+ GreCreateDIBitmapInternal(
+     IN HDC hDc,
+     IN INT cx,
+     IN INT cy,
+     IN DWORD fInit,
+     IN OPTIONAL LPBYTE pjInit,
+     IN OPTIONAL PBITMAPINFO pbmi,
+     IN DWORD iUsage,
+     IN FLONG fl,
+     IN HANDLE hcmXform)
  {
      PDC Dc;
      HBITMAP Bmp;
-     UINT bpp;
+     WORD bpp;
+     HDC hdcDest;
  
-     if (!hDc) // CreateBitmap
+     if (!hDc) /* 1bpp monochrome bitmap */
      {  // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
-         hDc = IntGdiCreateDC(NULL, NULL, NULL, NULL,FALSE);
-         if (!hDc)
+         hdcDest = NtGdiCreateCompatibleDC(0);
+         if(!hdcDest)
          {
-             SetLastWin32Error(ERROR_INVALID_HANDLE);
-             return NULL;
-         }
-         Dc = DC_LockDc(hDc);
-         if (!Dc)
-         {
-             NtGdiDeleteObjectApp(hDc);
-             SetLastWin32Error(ERROR_INVALID_HANDLE);
              return NULL;
          }
-         bpp = 1;
-         Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
+     }
+     else
+     {
+         hdcDest = hDc;
+     }
  
-         DC_UnlockDc(Dc);
-         NtGdiDeleteObjectApp(hDc);
+     Dc = DC_LockDc(hdcDest);
+     if (!Dc)
+     {
+         SetLastWin32Error(ERROR_INVALID_HANDLE);
+         return NULL;
      }
-     else // CreateCompatibleBitmap
+     /* It's OK to set bpp=0 here, as IntCreateDIBitmap will create a compatible Bitmap
+      * if bpp != 1 and ignore the real value that was passed */
+     if (pbmi)
+         bpp = pbmi->bmiHeader.biBitCount;
+     else
+         bpp = 0;
+     Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
+     DC_UnlockDc(Dc);
+     if(!hDc)
      {
-         Dc = DC_LockDc(hDc);
-         if (!Dc)
-         {
-             SetLastWin32Error(ERROR_INVALID_HANDLE);
-             return NULL;
-         }
-         /* pbmi == null
-            First create an un-initialised bitmap.  The depth of the bitmap
-            should match that of the hdc and not that supplied in bmih.
-          */
-         if (pbmi)
-             bpp = pbmi->bmiHeader.biBitCount;
-         else
-         {
-             if (Dc->dctype != DC_TYPE_MEMORY)
-                 bpp = IntGdiGetDeviceCaps(Dc, BITSPIXEL);
-             else
-             {
-                 DIBSECTION dibs;
-                 INT Count;
-                 SURFACE *psurf = Dc->dclevel.pSurface;
-                 Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
-                 if (!Count)
-                     bpp = 1;
-                 else
-                 {
-                     if (Count == sizeof(BITMAP))
-                         /* A device-dependent bitmap is selected in the DC */
-                         bpp = dibs.dsBm.bmBitsPixel;
-                     else
-                         /* A DIB section is selected in the DC */
-                         bpp = dibs.dsBmih.biBitCount;
-                 }
-             }
-         }
-         Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
-         DC_UnlockDc(Dc);
+         NtGdiDeleteObjectApp(hdcDest);
      }
      return Bmp;
  }
@@@ -1291,7 -1328,7 +1328,7 @@@ NtGdiCreateDIBSection
      IN HDC hDC,
      IN OPTIONAL HANDLE hSection,
      IN DWORD dwOffset,
-     IN LPBITMAPINFO bmi,
+     IN BITMAPINFO* bmi,
      IN DWORD Usage,
      IN UINT cjHeader,
      IN FLONG fl,
      HBITMAP hbitmap = 0;
      DC *dc;
      BOOL bDesktopDC = FALSE;
+       NTSTATUS Status = STATUS_SUCCESS;
  
      if (!bmi) return hbitmap; // Make sure.
  
+       _SEH2_TRY
+     {
+         ProbeForRead(&bmi->bmiHeader.biSize, sizeof(DWORD), 1);
+               ProbeForRead(bmi, bmi->bmiHeader.biSize, 1);
+               ProbeForRead(bmi, DIB_BitmapInfoSize(bmi, Usage), 1);
+     }
+     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+     {
+         Status = _SEH2_GetExceptionCode();
+     }
+     _SEH2_END
+     if(!NT_SUCCESS(Status))
+     {
+         SetLastNtError(Status);
+         return NULL;
+     }
      // If the reference hdc is null, take the desktop dc
      if (hDC == 0)
      {
      if ((dc = DC_LockDc(hDC)))
      {
          hbitmap = DIB_CreateDIBSection(dc,
-                                        (BITMAPINFO*)bmi,
+                                        bmi,
                                         Usage,
                                         Bits,
                                         hSection,
@@@ -1337,7 -1393,7 +1393,7 @@@ HBITMA
  APIENTRY
  DIB_CreateDIBSection(
      PDC dc,
-     BITMAPINFO *bmi,
+     CONST BITMAPINFO *bmi,
      UINT usage,
      LPVOID *bits,
      HANDLE section,
      HBITMAP res = 0;
      SURFACE *bmp = NULL;
      void *mapBits = NULL;
+     HPALETTE hpal ;
  
      // Fill BITMAP32 structure with DIB data
-     BITMAPINFOHEADER *bi = &bmi->bmiHeader;
+     CONST BITMAPINFOHEADER *bi = &bmi->bmiHeader;
      INT effHeight;
      ULONG totalSize;
      BITMAP bm;
      SIZEL Size;
-     RGBQUAD *lpRGB;
      HANDLE hSecure;
-     DWORD dsBitfields[3] = {0};
-     ULONG ColorCount;
  
      DPRINT("format (%ld,%ld), planes %d, bpp %d, size %ld, colors %ld (%s)\n",
             bi->biWidth, bi->biHeight, bi->biPlanes, bi->biBitCount,
      bm.bmType = 0;
      bm.bmWidth = bi->biWidth;
      bm.bmHeight = effHeight;
-     bm.bmWidthBytes = ovr_pitch ? ovr_pitch : (ULONG) DIB_GetDIBWidthBytes(bm.bmWidth, bi->biBitCount);
+     bm.bmWidthBytes = ovr_pitch ? ovr_pitch : WIDTH_BYTES_ALIGN32(bm.bmWidth, bi->biBitCount);
  
      bm.bmPlanes = bi->biPlanes;
      bm.bmBitsPixel = bi->biBitCount;
      {
          offset = 0;
          bm.bmBits = EngAllocUserMem(totalSize, 0);
+               if(!bm.bmBits) goto cleanup;
      }
  
  //  hSecure = MmSecureVirtualMemory(bm.bmBits, totalSize, PAGE_READWRITE);
  
      if (usage == DIB_PAL_COLORS)
      {
-         lpRGB = DIB_MapPaletteColors(dc, bmi);
-         ColorCount = bi->biClrUsed;
-         if (ColorCount == 0)
-         {
-             ColorCount = 1 << bi->biBitCount;
-         }
+               if(dc)
+               {
+                       PPALETTE pdcPal ;
+                       pdcPal = PALETTE_LockPalette(dc->dclevel.hpal);
+                       hpal = DIB_MapPaletteColors(pdcPal, bmi);
+                       PALETTE_UnlockPalette(pdcPal);
+               }
+               else
+               {
+                       /* For DIB Brushes */
+                       DPRINT1("FIXME : Unsupported DIB_PAL_COLORS without a DC to map colors.\n");
+                       /* HACK */
+                       hpal = (HPALETTE) 0xFFFFFFFF;
+               }
      }
      else
-     {
-         lpRGB = bmi->bmiColors;
-         ColorCount = 1 << bi->biBitCount;
-     }
-     /* Set dsBitfields values */
-     if (usage == DIB_PAL_COLORS || bi->biBitCount <= 8)
-     {
-         dsBitfields[0] = dsBitfields[1] = dsBitfields[2] = 0;
-     }
-     else if (bi->biCompression == BI_RGB)
-     {
-         switch (bi->biBitCount)
-         {
-             case 15:
-             case 16:
-                 dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB       : 0x7c00;
-                 dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x03e0;
-                 dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x001f;
-                 break;
+       {
+         hpal = BuildDIBPalette(bmi);
+       }
  
-             case 24:
-             case 32:
-                 dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB       : 0xff0000;
-                 dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x00ff00;
-                 dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x0000ff;
-                 break;
-         }
-     }
-     else
-     {
-         dsBitfields[0] = ((DWORD*)bmi->bmiColors)[0];
-         dsBitfields[1] = ((DWORD*)bmi->bmiColors)[1];
-         dsBitfields[2] = ((DWORD*)bmi->bmiColors)[2];
-     }
+       if(!hpal)
+       {
+               DPRINT1("Error : Could not create a palette for the DIB.\n");
+               goto cleanup;
+       }
  
      // Create Device Dependent Bitmap and add DIB pointer
      Size.cx = bm.bmWidth;
      Size.cy = abs(bm.bmHeight);
-     res = IntCreateBitmap(Size,
-                           bm.bmWidthBytes,
-                           BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
-                           BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
-                           (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
-                           bm.bmBits);
+     res = GreCreateBitmapEx(bm.bmWidth,
+                             abs(bm.bmHeight),
+                             bm.bmWidthBytes,
+                             BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
+                             BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
+                               (bi->biHeight < 0 ? BMF_TOPDOWN : 0),
+                             bi->biSizeImage,
+                             bm.bmBits,
+                                                       0);
      if (!res)
      {
-         if (lpRGB != bmi->bmiColors)
-         {
-             ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
-         }
          SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
-         return NULL;
+         goto cleanup;
      }
      bmp = SURFACE_LockSurface(res);
      if (NULL == bmp)
      {
-         if (lpRGB != bmi->bmiColors)
-         {
-             ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
-         }
-         SetLastWin32Error(ERROR_INVALID_HANDLE);
-         GreDeleteObject(bmp);
-         return NULL;
+               SetLastWin32Error(ERROR_INVALID_HANDLE);
+         goto cleanup;
      }
  
      /* WINE NOTE: WINE makes use of a colormap, which is a color translation
                    table between the DIB and the X physical device. Obviously,
                    this is left out of the ReactOS implementation. Instead,
                    we call NtGdiSetDIBColorTable. */
-     if (bi->biBitCount <= 8)
-     {
-         bi->biClrUsed = 1 << bi->biBitCount;
-     }
-     else
-     {
-         bi->biClrUsed = 0;
-     }
      bmp->hDIBSection = section;
      bmp->hSecure = hSecure;
      bmp->dwOffset = offset;
-     bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
-     bmp->dsBitfields[0] = dsBitfields[0];
-     bmp->dsBitfields[1] = dsBitfields[1];
-     bmp->dsBitfields[2] = dsBitfields[2];
-     bmp->biClrUsed = bi->biClrUsed;
+     bmp->flags = API_BITMAP;
      bmp->biClrImportant = bi->biClrImportant;
  
-     if (bi->biClrUsed != 0)
-     {
-         bmp->hDIBPalette = PALETTE_AllocPaletteIndexedRGB(ColorCount, lpRGB);
-     }
-     else
-     {
-         bmp->hDIBPalette = PALETTE_AllocPalette(PAL_BITFIELDS, 0, NULL,
-                                                 dsBitfields[0],
-                                                 dsBitfields[1],
-                                                 dsBitfields[2]);
-     }
+       /* HACK */
+       if(hpal != (HPALETTE)0xFFFFFFFF)
+       {
+               bmp->ppal = PALETTE_ShareLockPalette(hpal);
+               /* Lazy delete hpal, it will be freed at surface release */
+               GreDeleteObject(hpal);
+       }
  
      // Clean up in case of errors
+ cleanup:
      if (!res || !bmp || !bm.bmBits)
      {
          DPRINT("got an error res=%08x, bmp=%p, bm.bmBits=%p\n", res, bmp, bm.bmBits);
          }
      }
  
-     if (lpRGB != bmi->bmiColors)
-     {
-         ExFreePoolWithTag(lpRGB, TAG_COLORMAP);
-     }
      if (bmp)
      {
          SURFACE_UnlockSurface(bmp);
  }
  
  /***********************************************************************
-  *           DIB_GetDIBWidthBytes
+  *           DIB_GetBitmapInfo
   *
-  * Return the width of a DIB bitmap in bytes. DIB bitmap data is 32-bit aligned.
-  * http://www.microsoft.com/msdn/sdk/platforms/doc/sdk/win32/struc/src/str01.htm
-  * 11/16/1999 (RJJ) lifted from wine
+  * Get the info from a bitmap header.
+  * Return 0 for COREHEADER, 1 for INFOHEADER, -1 for error.
   */
- INT FASTCALL DIB_GetDIBWidthBytes(INT width, INT depth)
+ int
+ FASTCALL
+ DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
+                        LONG *height, WORD *planes, WORD *bpp, DWORD *compr, DWORD *size )
  {
-     return ((width * depth + 31) & ~31) >> 3;
+     if (header->biSize == sizeof(BITMAPCOREHEADER))
+     {
+         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)header;
+         *width  = core->bcWidth;
+         *height = core->bcHeight;
+         *planes = core->bcPlanes;
+         *bpp    = core->bcBitCount;
+         *compr  = BI_RGB;
+         *size   = 0;
+         return 0;
+     }
+     if (header->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
+     {
+         *width  = header->biWidth;
+         *height = header->biHeight;
+         *planes = header->biPlanes;
+         *bpp    = header->biBitCount;
+         *compr  = header->biCompression;
+         *size   = header->biSizeImage;
+         return 1;
+     }
+     DPRINT1("(%d): unknown/wrong size for header\n", header->biSize );
+     return -1;
  }
  
  /***********************************************************************
  
  INT APIENTRY DIB_GetDIBImageBytes(INT  width, INT height, INT depth)
  {
-     return DIB_GetDIBWidthBytes(width, depth) * (height < 0 ? -height : height);
+     return WIDTH_BYTES_ALIGN32(width, depth) * (height < 0 ? -height : height);
  }
  
  /***********************************************************************
  
  INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
  {
-     int colors;
+     unsigned int colors, size, masks = 0;
  
      if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
      {
-         BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)info;
+         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
          colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
-         return sizeof(BITMAPCOREHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
+         return sizeof(BITMAPCOREHEADER) + colors *
+              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
      }
      else  /* assume BITMAPINFOHEADER */
      {
          colors = info->bmiHeader.biClrUsed;
-         if (!colors && (info->bmiHeader.biBitCount <= 8)) colors = 1 << info->bmiHeader.biBitCount;
-         return sizeof(BITMAPINFOHEADER) + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
+         if (colors > 256) colors = 256;
+         if (!colors && (info->bmiHeader.biBitCount <= 8))
+             colors = 1 << info->bmiHeader.biBitCount;
+         if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
+         size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
+         return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
      }
  }
  
- RGBQUAD *
+ HPALETTE
  FASTCALL
- DIB_MapPaletteColors(PDC dc, CONST BITMAPINFO* lpbmi)
+ DIB_MapPaletteColors(PPALETTE ppal, CONST BITMAPINFO* lpbmi)
  {
-     RGBQUAD *lpRGB;
+     PALETTEENTRY* ppalEntries;
      ULONG nNumColors,i;
      USHORT *lpIndex;
-     PPALETTE palGDI;
-     palGDI = PALETTE_LockPalette(dc->dclevel.hpal);
-     if (NULL == palGDI)
-     {
-         return NULL;
-     }
+       HPALETTE hpal;
  
-     if (palGDI->Mode != PAL_INDEXED)
+     if (!(ppal->flFlags & PAL_INDEXED))
      {
-         PALETTE_UnlockPalette(palGDI);
          return NULL;
      }
  
          nNumColors = min(nNumColors, lpbmi->bmiHeader.biClrUsed);
      }
  
-     lpRGB = (RGBQUAD *)ExAllocatePoolWithTag(PagedPool, sizeof(RGBQUAD) * nNumColors, TAG_COLORMAP);
-     if (lpRGB == NULL)
+       /* Don't have more colors than we need */
+       nNumColors = min(ppal->NumColors, nNumColors);
+     ppalEntries = ExAllocatePoolWithTag(PagedPool, sizeof(PALETTEENTRY) * nNumColors, TAG_COLORMAP);
+     if (ppalEntries == NULL)
      {
-         PALETTE_UnlockPalette(palGDI);
+         DPRINT1("Could not allocate palette entries\n");
          return NULL;
      }
  
-     lpIndex = (USHORT *)&lpbmi->bmiColors[0];
+     lpIndex = (USHORT *)((PBYTE)lpbmi + lpbmi->bmiHeader.biSize);
  
      for (i = 0; i < nNumColors; i++)
      {
-         if (*lpIndex < palGDI->NumColors)
+         if (*lpIndex < ppal->NumColors)
          {
-             lpRGB[i].rgbRed = palGDI->IndexedColors[*lpIndex].peRed;
-             lpRGB[i].rgbGreen = palGDI->IndexedColors[*lpIndex].peGreen;
-             lpRGB[i].rgbBlue = palGDI->IndexedColors[*lpIndex].peBlue;
+             ppalEntries[i] = ppal->IndexedColors[*lpIndex];
          }
          else
          {
-             lpRGB[i].rgbRed = 0;
-             lpRGB[i].rgbGreen = 0;
-             lpRGB[i].rgbBlue = 0;
+             ppalEntries[i].peRed = 0;
+                       ppalEntries[i].peGreen = 0;
+                       ppalEntries[i].peBlue = 0;
+                       ppalEntries[i].peFlags = 0;
          }
-         lpRGB[i].rgbReserved = 0;
          lpIndex++;
      }
-     PALETTE_UnlockPalette(palGDI);
  
-     return lpRGB;
+       hpal = PALETTE_AllocPalette(PAL_INDEXED, nNumColors, (ULONG*)ppalEntries, 0, 0, 0);
+       ExFreePoolWithTag(ppalEntries, TAG_COLORMAP);
+       return hpal;
  }
  
  HPALETTE
  FASTCALL
- BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType)
+ BuildDIBPalette(CONST BITMAPINFO *bmi)
  {
      BYTE bits;
      ULONG ColorCount;
-     PALETTEENTRY *palEntries = NULL;
      HPALETTE hPal;
-     ULONG RedMask, GreenMask, BlueMask;
+     ULONG RedMask = 0, GreenMask = 0, BlueMask = 0;
+     PDWORD pdwColors = (PDWORD)((PBYTE)bmi + bmi->bmiHeader.biSize);
+       INT paletteType;
  
      // Determine Bits Per Pixel
      bits = bmi->bmiHeader.biBitCount;
      // Determine paletteType from Bits Per Pixel
      if (bits <= 8)
      {
-         *paletteType = PAL_INDEXED;
+         paletteType = PAL_INDEXED;
          RedMask = GreenMask = BlueMask = 0;
      }
      else if (bmi->bmiHeader.biCompression == BI_BITFIELDS)
      {
-         *paletteType = PAL_BITFIELDS;
-         RedMask = ((ULONG *)bmi->bmiColors)[0];
-         GreenMask = ((ULONG *)bmi->bmiColors)[1];
-         BlueMask = ((ULONG *)bmi->bmiColors)[2];
-     }
-     else if (bits < 24)
-     {
-         *paletteType = PAL_BITFIELDS;
-         RedMask = 0x7c00;
-         GreenMask = 0x03e0;
-         BlueMask = 0x001f;
+         paletteType = PAL_BITFIELDS;
+         RedMask = pdwColors[0];
+         GreenMask = pdwColors[1];
+         BlueMask = pdwColors[2];
      }
      else
      {
-         *paletteType = PAL_BGR;
-         RedMask = 0xff0000;
-         GreenMask = 0x00ff00;
-         BlueMask = 0x0000ff;
+         paletteType = PAL_BITFIELDS;
+         switch (bits)
+         {
+             case 15:
+                 paletteType |= PAL_RGB16_555;
+                 RedMask = 0x7C00;
+                 GreenMask = 0x03E0;
+                 BlueMask = 0x001F;
+                 break;
+             case 16:
+                 paletteType |= PAL_RGB16_565;
+                 RedMask = 0xF800;
+                 GreenMask = 0x07E0;
+                 BlueMask = 0x001F;
+                 break;
+             case 24:
+             case 32:
+                 paletteType |= PAL_BGR;
+                 RedMask = 0xFF0000;
+                 GreenMask = 0x00FF00;
+                 BlueMask = 0x0000FF;
+                 break;
+         }
      }
  
      if (bmi->bmiHeader.biClrUsed == 0)
          ColorCount = bmi->bmiHeader.biClrUsed;
      }
  
-     if (PAL_INDEXED == *paletteType)
+     if (PAL_INDEXED == paletteType)
      {
-         hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
+         hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)pdwColors);
      }
      else
      {
-         hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
-                                     (ULONG*) palEntries,
+         hPal = PALETTE_AllocPalette(paletteType, 0,
+                                     NULL,
                                      RedMask, GreenMask, BlueMask);
      }
  
      return hPal;
  }
  
+ /* Converts a BITMAPCOREINFO to a BITMAPINFO structure,
+  * or does nothing if it's already a BITMAPINFO (or V4 or V5) */
+ BITMAPINFO*
+ FASTCALL
+ DIB_ConvertBitmapInfo (CONST BITMAPINFO* pbmi, DWORD Usage)
+ {
+       CONST BITMAPCOREINFO* pbmci = (BITMAPCOREINFO*)pbmi;
+       BITMAPINFO* pNewBmi ;
+       UINT numColors = 0, ColorsSize = 0;
+       if(pbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) return (BITMAPINFO*)pbmi;
+       if(pbmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) return NULL;
+       if(pbmci->bmciHeader.bcBitCount <= 8)
+       {
+               numColors = 1 << pbmci->bmciHeader.bcBitCount;
+               if(Usage == DIB_PAL_COLORS)
+               {
+                       ColorsSize = numColors * sizeof(WORD);
+               }
+               else
+               {
+                       ColorsSize = numColors * sizeof(RGBQUAD);
+               }
+       }
+       else if (Usage == DIB_PAL_COLORS)
+       {
+               /* Invalid at high Res */
+               return NULL;
+       }
+       pNewBmi = ExAllocatePoolWithTag(PagedPool, sizeof(BITMAPINFOHEADER) + ColorsSize, TAG_DIB);
+       if(!pNewBmi) return NULL;
+       RtlZeroMemory(pNewBmi, sizeof(BITMAPINFOHEADER) + ColorsSize);
+       pNewBmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+       pNewBmi->bmiHeader.biBitCount = pbmci->bmciHeader.bcBitCount;
+       pNewBmi->bmiHeader.biWidth = pbmci->bmciHeader.bcWidth;
+       pNewBmi->bmiHeader.biHeight = pbmci->bmciHeader.bcHeight;
+       pNewBmi->bmiHeader.biPlanes = pbmci->bmciHeader.bcPlanes;
+       pNewBmi->bmiHeader.biCompression = BI_RGB ;
+       pNewBmi->bmiHeader.biSizeImage = DIB_GetDIBImageBytes(pNewBmi->bmiHeader.biWidth,
+                                                                                               pNewBmi->bmiHeader.biHeight,
+                                                                                               pNewBmi->bmiHeader.biBitCount);
+       if(Usage == DIB_PAL_COLORS)
+       {
+               RtlCopyMemory(pNewBmi->bmiColors, pbmci->bmciColors, ColorsSize);
+       }
+       else
+       {
+               UINT i;
+               for(i=0; i<numColors; i++)
+               {
+                       pNewBmi->bmiColors[i].rgbRed = pbmci->bmciColors[i].rgbtRed;
+                       pNewBmi->bmiColors[i].rgbGreen = pbmci->bmciColors[i].rgbtGreen;
+                       pNewBmi->bmiColors[i].rgbBlue = pbmci->bmciColors[i].rgbtBlue;
+               }
+       }
+       return pNewBmi ;
+ }
+ /* Frees a BITMAPINFO created with DIB_ConvertBitmapInfo */
+ VOID
+ FASTCALL
+ DIB_FreeConvertedBitmapInfo(BITMAPINFO* converted, BITMAPINFO* orig)
+ {
+       if(converted != orig)
+               ExFreePoolWithTag(converted, TAG_DIB);
+ }
  /* EOF */
@@@ -64,14 -64,14 +64,14 @@@ typedef struct _Rec
  } Rect, *PRect;
  
  int FASTCALL IntFillRect(DC *dc, INT XLeft, INT YLeft, INT Width, INT Height, PBRUSH pbrush, BOOL Pen);
- int FASTCALL app_fill_rect(DC *dc, Rect r, PBRUSH pbrush, BOOL Pen);
//int FASTCALL app_fill_rect(DC *dc, Rect r, PBRUSH pbrush, BOOL Pen);
  
  static
  POINT
  INTERNAL_CALL
  app_new_point(int x, int y)
  {
-       POINT p;        
+       POINT p;
        p.x = x;
        p.y = y;
        return p;
@@@ -332,7 -332,7 +332,7 @@@ app_draw_ellipse(DC *g, Rect r, PBRUSH 
   *
   *  The draw_arc algorithm is based on draw_ellipse, but unlike
   *  that algorithm is not symmetric in the general case, since
-  *  an angular portion is clipped from the shape. 
+  *  an angular portion is clipped from the shape.
   *  This clipping is performed by keeping track of two hypothetical
   *  lines joining the centre point to the enclosing rectangle,
   *  at the angles start_angle and end_angle, using a line-intersection
@@@ -376,7 -376,7 +376,7 @@@ app_fill_arc_rect(DC *g
        rise2 = p2.y - p0.y;
        run2  = p2.x - p0.x;
  
-       if (r.y <= p0.y) // 
+       if (r.y <= p0.y) //
          {
                /* in top half of arc ellipse */
  
   *  between an outer and inner ellipse, and also the draw_arc and
   *  fill_arc operations which additionally clip drawing between
   *  a start_angle and an end_angle.
-  *  
+  *
   */
  static
  int
@@@ -912,7 -912,7 +912,7 @@@ app_fill_arc(DC *g, Rect r, int start_a
                r1.height = r1.y+r1.height-r2.y;
                r1.y = r2.y;
                while (r1.height > 0) {
-                       result &= app_fill_arc_rect(g, 
+                       result &= app_fill_arc_rect(g,
                                rect(r1.x, r1.y, r1.width, 1),
                                p0, p1, p2, start_angle, end_angle, pbrush, FALSE);
                        r1.y += 1;
@@@ -1273,7 -1273,7 +1273,7 @@@ IntFillArc( PDC dc
    pdcattr = dc->pdcattr;
  
    pbrush = BRUSH_LockBrush(pdcattr->hbrush);
-   if (!pbrush)   
+   if (!pbrush)
    {
        DPRINT1("FillArc Fail\n");
        SetLastWin32Error(ERROR_INTERNAL_ERROR);
                      (dc->dclevel.flPath & DCPATH_CLOCKWISE) ? -Start : -End,
                       pbrush, Chord);
  
-   BRUSH_UnlockBrush(pbrush);    
+   BRUSH_UnlockBrush(pbrush);
    return ret;
  }
  
@@@ -1329,7 -1329,7 +1329,7 @@@ IntFillEllipse( PDC dc
                  INT XLeft,
                  INT YLeft,
                  INT Width,
-                 INT Height, 
+                 INT Height,
                  PBRUSH pbrush)
  {
    return (BOOL)app_fill_ellipse(dc, rect( XLeft, YLeft, Width, Height), pbrush);
@@@ -1343,7 -1343,7 +1343,7 @@@ IntFillRoundRect( PDC dc
                    INT Right,
                    INT Bottom,
                    INT Wellipse,
-                   INT Hellipse, 
+                   INT Hellipse,
                    PBRUSH pbrush)
  {
    Rect r;
                        270, 360, pbrush,FALSE);
  
       app_fill_arc(dc, rect(r.x+r.width-rx-rx, r.y, rx+rx, ry+ry),
-                       0, 90, pbrush,FALSE);   
+                       0, 90, pbrush,FALSE);
    }
    if (Wellipse < r.width)
    {
@@@ -1419,7 -1419,7 +1419,7 @@@ IntDrawRoundRect( PDC dc
    r = rect( Left, Top, abs(Right-Left), abs(Bottom-Top));
    rx = Wellipse/2;
    ry = Hellipse/2;
-   
    if (Wellipse > r.width)
    {
       if (Hellipse > r.height) // > W > H
          app_draw_arc(dc, rect(r.x, r.y, Wellipse - 1, r.height - 1),
                           90, 270, pbrushPen, FALSE);
          app_draw_arc(dc, rect(Right - Wellipse, r.y, Wellipse - 1, r.height - 1),
-                          270, 90, pbrushPen, FALSE);        
+                          270, 90, pbrushPen, FALSE);
    }
    else // < W < H
    {
@@@ -110,7 -110,7 +110,7 @@@ IntGdiPolygon(PDC    dc
                                    psurf,
                                    &dc->eboFill.BrushObject,
                                    Points,
-                                   Count, 
+                                   Count,
                                    DestRect,
                                    &BrushOrigin);
          }
@@@ -271,15 -271,15 +271,15 @@@ NtGdiEllipse
      }
  
      if (!PenWidth) PenWidth = 1;
-     pbrush->ptPenWidth.x = PenWidth;  
+     pbrush->ptPenWidth.x = PenWidth;
  
      RectBounds.left   = Left;
      RectBounds.right  = Right;
      RectBounds.top    = Top;
      RectBounds.bottom = Bottom;
-                 
      IntLPtoDP(dc, (LPPOINT)&RectBounds, 2);
-  
      RectBounds.left += dc->ptlDCOrig.x;
      RectBounds.right += dc->ptlDCOrig.x;
      RectBounds.top += dc->ptlDCOrig.y;
                 CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2);
  
      pFillBrushObj = BRUSH_LockBrush(pdcattr->hbrush);
-     if (NULL == pFillBrushObj)   
+     if (NULL == pFillBrushObj)
      {
          DPRINT1("FillEllipse Fail\n");
          SetLastWin32Error(ERROR_INTERNAL_ERROR);
@@@ -478,6 -478,15 +478,15 @@@ NtGdiPolyPolyDraw( IN HDC hDC
          return TRUE;
      }
  
+     DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+                             NULL, dc->rosdc.CombinedClip->rclBounds);
+     if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
+         DC_vUpdateFillBrush(dc);
+     if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+         DC_vUpdateLineBrush(dc);
      /* Perform the actual work */
      switch (iFunc)
      {
      }
  
      /* Cleanup and return */
+     DC_vFinishBlit(dc, NULL);
      DC_UnlockDc(dc);
      ExFreePool(pTemp);
  
@@@ -529,19 -539,6 +539,6 @@@ IntRectangle(PDC dc
  
      pdcattr = dc->pdcattr;
  
-     /* Do we rotate or shear? */
-     if (!(dc->dclevel.mxWorldToDevice.flAccel & MX_SCALE))
-     {
-         POINTL DestCoords[4];
-         ULONG  PolyCounts = 4;
-         DestCoords[0].x = DestCoords[3].x = LeftRect;
-         DestCoords[0].y = DestCoords[1].y = TopRect;
-         DestCoords[1].x = DestCoords[2].x = RightRect;
-         DestCoords[2].y = DestCoords[3].y = BottomRect;
-         // Use IntGdiPolyPolygon so to support PATH.
-         return IntGdiPolyPolygon(dc, DestCoords, &PolyCounts, 1);
-     }
      // Rectangle Path only.
      if ( PATH_IsPathOpen(dc->dclevel) )
      {
          DestRect.bottom--;
      }
  
+     DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
      if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
          DC_vUpdateFillBrush(dc);
  
          ret = FALSE;
          goto cleanup;
      }
      psurf = dc->dclevel.pSurface;
      if (!psurf)
      {
      }
  
  cleanup:
+     DC_vFinishBlit(dc, NULL);
      /* Move current position in DC?
         MSDN: The current position is neither used nor updated by Rectangle. */
  
@@@ -675,8 -677,25 +677,25 @@@ NtGdiRectangle(HDC  hDC
          return TRUE;
      }
  
-     ret = IntRectangle ( dc, LeftRect, TopRect, RightRect, BottomRect );
-     DC_UnlockDc ( dc );
+     /* Do we rotate or shear? */
+     if (!(dc->dclevel.mxWorldToDevice.flAccel & MX_SCALE))
+     {
+         POINTL DestCoords[4];
+         ULONG PolyCounts = 4;
+         DestCoords[0].x = DestCoords[3].x = LeftRect;
+         DestCoords[0].y = DestCoords[1].y = TopRect;
+         DestCoords[1].x = DestCoords[2].x = RightRect;
+         DestCoords[2].y = DestCoords[3].y = BottomRect;
+         // Use IntGdiPolyPolygon so to support PATH.
+         ret = IntGdiPolyPolygon(dc, DestCoords, &PolyCounts, 1);
+     }
+     else
+     {
+         ret = IntRectangle(dc, LeftRect, TopRect, RightRect, BottomRect );
+     }
+     DC_UnlockDc(dc);
  
      return ret;
  }
@@@ -750,7 -769,7 +769,7 @@@ IntRoundRect
      }
  
      if (!PenWidth) PenWidth = 1;
-     pbrushLine->ptPenWidth.x = PenWidth;  
+     pbrushLine->ptPenWidth.x = PenWidth;
  
      RectBounds.left = Left;
      RectBounds.top = Top;
      RectBounds.bottom += dc->ptlDCOrig.y;
  
      pbrushFill = BRUSH_LockBrush(pdcattr->hbrush);
-     if (NULL == pbrushFill)   
+     if (NULL == pbrushFill)
      {
          DPRINT1("FillRound Fail\n");
          SetLastWin32Error(ERROR_INTERNAL_ERROR);
          ret = FALSE;
-     } 
+     }
      else
      {
          RtlCopyMemory(&brushTemp, pbrushFill, sizeof(brushTemp));
@@@ -849,16 -868,14 +868,14 @@@ GreGradientFill
  {
      PDC pdc;
      SURFACE *psurf;
-     PPALETTE ppal;
      EXLATEOBJ exlo;
      RECTL rclExtent;
      POINTL ptlDitherOrg;
      ULONG i;
      BOOL bRet;
-     HPALETTE hDestPalette;
  
-     /* Check parameters */
-     if (ulMode == GRADIENT_FILL_TRIANGLE)
+     /* check parameters */
+     if (ulMode & GRADIENT_FILL_TRIANGLE)
      {
          PGRADIENT_TRIANGLE pTriangle = (PGRADIENT_TRIANGLE)pMesh;
  
  
      /* Lock the output DC */
      pdc = DC_LockDc(hdc);
-     if (!pdc)
+     if(!pdc)
      {
          SetLastWin32Error(ERROR_INVALID_HANDLE);
          return FALSE;
      }
  
-     if (pdc->dctype == DC_TYPE_INFO)
+     if(pdc->dctype == DC_TYPE_INFO)
      {
          DC_UnlockDc(pdc);
          /* Yes, Windows really returns TRUE in this case */
      }
  
      psurf = pdc->dclevel.pSurface;
-     if (!psurf)
+     if(!psurf)
      {
          /* Memory DC with no surface selected */
          DC_UnlockDc(pdc);
-         return TRUE; // CHECKME
+         return TRUE; //CHECKME
      }
  
      /* calculate extent */
          rclExtent.top = min(rclExtent.top, (pVertex + i)->y);
          rclExtent.bottom = max(rclExtent.bottom, (pVertex + i)->y);
      }
      IntLPtoDP(pdc, (LPPOINT)&rclExtent, 2);
      rclExtent.left   += pdc->ptlDCOrig.x;
      rclExtent.right  += pdc->ptlDCOrig.x;
      rclExtent.top    += pdc->ptlDCOrig.y;
  
      ptlDitherOrg.x = ptlDitherOrg.y = 0;
      IntLPtoDP(pdc, (LPPOINT)&ptlDitherOrg, 1);
      ptlDitherOrg.x += pdc->ptlDCOrig.x;
      ptlDitherOrg.y += pdc->ptlDCOrig.y;
  
-     hDestPalette = psurf->hDIBPalette;
-     if (!hDestPalette) hDestPalette = pPrimarySurface->devinfo.hpalDefault;
-     ppal = PALETTE_LockPalette(hDestPalette);
-     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppal, 0, 0, 0);
+     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0, 0);
  
      ASSERT(pdc->rosdc.CombinedClip);
  
+     DC_vPrepareDCsForBlit(pdc, rclExtent, NULL, rclExtent);
      bRet = IntEngGradientFill(&psurf->SurfObj,
-                               pdc->rosdc.CombinedClip,
-                               &exlo.xlo,
-                               pVertex,
-                               nVertex,
-                               pMesh,
-                               nMesh,
-                               &rclExtent,
-                               &ptlDitherOrg,
-                               ulMode);
+                              pdc->rosdc.CombinedClip,
+                              &exlo.xlo,
+                              pVertex,
+                              nVertex,
+                              pMesh,
+                              nMesh,
+                              &rclExtent,
+                              &ptlDitherOrg,
+                              ulMode);
  
      EXLATEOBJ_vCleanup(&exlo);
-     if (ppal)
-         PALETTE_UnlockPalette(ppal);
+     DC_vFinishBlit(pdc, NULL);
      DC_UnlockDc(pdc);
  
      return bRet;
@@@ -996,16 -1009,16 +1009,16 @@@ NtGdiGradientFill
              return FALSE;
      }
  
-     cbVertex = nVertex * sizeof(TRIVERTEX);
-     if (cbVertex + cbMesh <= cbVertex)
+     cbVertex = nVertex * sizeof(TRIVERTEX) ;
+     if(cbVertex + cbMesh <= cbVertex)
      {
          /* Overflow */
-         return FALSE;
+         return FALSE ;
      }
  
      /* Allocate a kernel mode buffer */
      SafeVertex = ExAllocatePoolWithTag(PagedPool, cbVertex + cbMesh, TAG_SHAPE);
-     if (!SafeVertex)
+     if(!SafeVertex)
      {
          SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
          return FALSE;
@@@ -1048,8 -1061,6 +1061,6 @@@ NtGdiExtFloodFill
      PDC dc;
      PDC_ATTR   pdcattr;
      SURFACE    *psurf = NULL;
-     HPALETTE   hpal;
-     PPALETTE   ppal;
      EXLATEOBJ  exlo;
      BOOL       Ret = FALSE;
      RECTL      DestRect;
          goto cleanup;
      }
  
-     hpal = dc->dclevel.pSurface->hDIBPalette;
-     if (!hpal) hpal = pPrimarySurface->devinfo.hpalDefault;
-     ppal = PALETTE_ShareLockPalette(hpal);
-     
-     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, ppal, 0, 0xffffff, 0);
+     EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0xffffff, 0);
  
      /* Only solid fills supported for now
       * How to support pattern brushes and non standard surfaces (not offering dib functions):
      Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType);
  
      EXLATEOBJ_vCleanup(&exlo);
-     PALETTE_ShareUnlockPalette(ppal);
  
  cleanup:
      DC_UnlockDc(dc);
@@@ -2249,7 -2249,7 +2249,7 @@@ TextIntGetTextExtentPoint(PDC dc
  
      Size->cx = (TotalWidth + 32) >> 6;
      Size->cy = (TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight < 0 ? - TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight : TextObj->logfont.elfEnumLogfontEx.elfLogFont.lfHeight);
-     Size->cy = EngMulDiv(Size->cy, IntGdiGetDeviceCaps(dc, LOGPIXELSY), 72);
+     Size->cy = EngMulDiv(Size->cy, dc->ppdev->gdiinfo.ulLogPixelsY, 72);
  
      return TRUE;
  }
@@@ -3160,7 -3160,7 +3160,7 @@@ GreExtTextOutW
      LONGLONG TextLeft, RealXStart;
      ULONG TextTop, previous, BackgroundLeft;
      FT_Bool use_kerning;
-     RECTL DestRect, MaskRect;
+     RECTL DestRect, MaskRect, DummyRect = {0, 0, 0, 0};
      POINTL SourcePoint, BrushOrigin;
      HBITMAP HSourceGlyph;
      SURFOBJ *SourceGlyphSurf;
      BOOLEAN Render;
      POINT Start;
      BOOL DoBreak = FALSE;
-     HPALETTE hDestPalette;
-     PPALETTE ppalDst;
      USHORT DxShift;
  
      // TODO: Write test-cases to exactly match real Windows in different
  
      pdcattr = dc->pdcattr;
  
-     if (pdcattr->ulDirty_ & DIRTY_TEXT)
-         DC_vUpdateTextBrush(dc);
      if ((fuOptions & ETO_OPAQUE) || pdcattr->jBkMode == OPAQUE)
      {
          if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
          IntLPtoDP(dc, (POINT *)lprc, 2);
      }
  
-     psurf = dc->dclevel.pSurface;
-     if (!psurf)
-     {
-         goto fail;
-     }
-     SurfObj = &psurf->SurfObj;
      Start.x = XStart;
      Start.y = YStart;
      IntLPtoDP(dc, &Start, 1);
          DestRect.right  += dc->ptlDCOrig.x;
          DestRect.bottom += dc->ptlDCOrig.y;
  
+         DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect);
+         if (pdcattr->ulDirty_ & DIRTY_BACKGROUND)
+             DC_vUpdateBackgroundBrush(dc);
          IntEngBitBlt(
-             &psurf->SurfObj,
+             &dc->dclevel.pSurface->SurfObj,
              NULL,
              NULL,
              dc->rosdc.CombinedClip,
              &BrushOrigin,
              ROP3_TO_ROP4(PATCOPY));
          fuOptions &= ~ETO_OPAQUE;
+         DC_vFinishBlit(dc, NULL);
      }
      else
      {
      TextTop = YStart;
      BackgroundLeft = (RealXStart + 32) >> 6;
  
-     /* Create the xlateobj */
-     hDestPalette = psurf->hDIBPalette;
-     if (!hDestPalette) hDestPalette = pPrimarySurface->devinfo.hpalDefault;
-     ppalDst = PALETTE_LockPalette(hDestPalette);
-     EXLATEOBJ_vInitialize(&exloRGB2Dst, &gpalRGB, ppalDst, 0, 0, 0);
-     EXLATEOBJ_vInitialize(&exloDst2RGB, ppalDst, &gpalRGB, 0, 0, 0);
-     PALETTE_UnlockPalette(ppalDst);
+     /* Lock blit with a dummy rect */
+     DC_vPrepareDCsForBlit(dc, DummyRect, NULL, DummyRect);
  
+     psurf = dc->dclevel.pSurface ;
+     SurfObj = &psurf->SurfObj ;
+     EXLATEOBJ_vInitialize(&exloRGB2Dst, &gpalRGB, psurf->ppal, 0, 0, 0);
+     EXLATEOBJ_vInitialize(&exloDst2RGB, psurf->ppal, &gpalRGB, 0, 0, 0);
+       if ((fuOptions & ETO_OPAQUE) && (dc->pdcattr->ulDirty_ & DIRTY_BACKGROUND))
+         DC_vUpdateBackgroundBrush(dc) ;
+     if(dc->pdcattr->ulDirty_ & DIRTY_TEXT)
+         DC_vUpdateTextBrush(dc) ;
  
      /*
       * The main rendering loop.
       */
      for (i = 0; i < Count; i++)
      {
          if (fuOptions & ETO_GLYPH_INDEX)
              DestRect.right = (TextLeft + (realglyph->root.advance.x >> 10) + 32) >> 6;
              DestRect.top = TextTop + yoff - ((face->size->metrics.ascender + 32) >> 6);
              DestRect.bottom = TextTop + yoff + ((32 - face->size->metrics.descender) >> 6);
+             MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
              IntEngBitBlt(
                  &psurf->SurfObj,
                  NULL,
                  &dc->eboBackground.BrushObject,
                  &BrushOrigin,
                  ROP3_TO_ROP4(PATCOPY));
+             MouseSafetyOnDrawEnd(dc->ppdev);
              BackgroundLeft = DestRect.right;
          }
  
          DestRect.left = ((TextLeft + 32) >> 6) + realglyph->left;
              DestRect.right = lprc->right + dc->ptlDCOrig.x;
              DoBreak = TRUE;
          }
+         MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom);
          IntEngMaskBlt(
              SurfObj,
              SourceGlyphSurf,
              (PPOINTL)&MaskRect,
              &dc->eboText.BrushObject,
              &BrushOrigin);
+         MouseSafetyOnDrawEnd(dc->ppdev) ;
  
          EngUnlockSurface(SourceGlyphSurf);
          EngDeleteSurface((HSURF)HSourceGlyph);
  
          String++;
      }
      IntUnLockFreeType;
  
+     DC_vFinishBlit(dc, NULL) ;
      EXLATEOBJ_vCleanup(&exloRGB2Dst);
      EXLATEOBJ_vCleanup(&exloDst2RGB);
      if (TextObj != NULL)
@@@ -3628,6 -3631,7 +3631,7 @@@ fail2
  fail:
      if (TextObj != NULL)
          TEXTOBJ_UnlockText(TextObj);
      DC_UnlockDc(dc);
  
      return FALSE;
@@@ -51,8 -51,9 +51,9 @@@ SynchonizeDriver(FLONG Flags
        Flags = DSS_TIMER_EVENT;
  
    Device = IntEnumHDev();
-   SurfObj = EngLockSurface( Device->pSurface );
+ //  UNIMPLEMENTED;
+ //ASSERT(FALSE);
+   SurfObj = 0;// EngLockSurface( Device->pSurface );
    if(!SurfObj) return;
    DoDeviceSync( SurfObj, NULL, Flags);
    EngUnlockSurface(SurfObj);
@@@ -8,7 -8,7 +8,7 @@@
  
  /** INCLUDES ******************************************************************/
  
//#define GDI_DEBUG
+ #define GDI_DEBUG
  
  #include <win32k.h>
  #define NDEBUG
@@@ -635,10 -635,7 +635,7 @@@ LockHandle
                  PEPROCESS OldProcess;
                  Object->BaseFlags |= BASEFLAG_READY_TO_DIE;
                  DPRINT("Object %p, ulShareCount = %d\n", Object->hHmgr, Object->ulShareCount);
-                 //GDIDBG_TRACECALLER();
-                 //GDIDBG_TRACESHARELOCKER(GDI_HANDLE_GET_INDEX(hObj));
-                 /* Set NULL owner. This will permit an other process to kill the object
-                  * Do the work here to avoid race conditions */
+                 /* Set NULL owner. Do the work here to avoid race conditions */
                  Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess);
                  if (NT_SUCCESS(Status))
                  {
                      }
                      ObDereferenceObject(OldProcess);
                  }
-                 (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
+                 (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, NULL);
                  /* Don't wait on shared locks */
                  return FALSE;
              }
                   */
                  DPRINT1("Object->cExclusiveLock = %d\n", Object->cExclusiveLock);
                  GDIDBG_TRACECALLER();
-                 GDIDBG_TRACELOCKER(GDI_HANDLE_GET_INDEX(hObj));
+                 GDIDBG_TRACELOCKER(hObj);
                  (void)InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
                  /* do not assert here for it will call again from dxg.sys it being call twice */
  
              }
              DPRINT1("Type = 0x%lx, KernelData = 0x%p, ProcessId = 0x%p\n", Entry->Type, Entry->KernelData, Entry->ProcessId);
              GDIDBG_TRACECALLER();
-             GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
+             GDIDBG_TRACEALLOCATOR(hObj);
          }
      }
  
@@@ -833,7 -830,7 +830,7 @@@ GreDeleteObject(HGDIOBJ hObject
               break;
  
            case GDI_OBJECT_TYPE_DC:
-              DC_FreeDcAttr(hObject);
//             DC_FreeDcAttr(hObject);
               break;
         }
  
@@@ -970,12 -967,14 +967,14 @@@ GDIOBJ_LockObj(HGDIOBJ hObj, DWORD Expe
      if(hObj == NULL)
          return NULL ;
  
+     GDIDBG_INITLOOPTRACE();
      HandleIndex = GDI_HANDLE_GET_INDEX(hObj);
      HandleType = GDI_HANDLE_GET_TYPE(hObj);
      HandleUpper = GDI_HANDLE_GET_UPPER(hObj);
  
      /* Check that the handle index is valid. */
-     if (HandleIndex >= GDI_HANDLE_COUNT)
+     if (HandleIndex >= GDI_HANDLE_COUNT )
          return NULL;
  
      Entry = &GdiHandleTable->Entries[HandleIndex];
      {
          DPRINT1("Tried to lock object (0x%p) of wrong owner! ProcessId = %p, HandleProcessId = %p\n", hObj, ProcessId, HandleProcessId);
          GDIDBG_TRACECALLER();
-         GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
+         GDIDBG_TRACEALLOCATOR(hObj);
          return NULL;
      }
  
              /*
               * The handle is currently locked, wait some time and try again.
               */
+             GDIDBG_TRACELOOP(hObj, PrevProcId, NULL);
  
              DelayExecution();
              continue;
@@@ -1649,6 -1649,38 +1649,38 @@@ GDI_MapHandleTable(PSECTION_OBJECT Sect
      return MappedView;
  }
  
+ /* Locks 2 or 3 objects at a time */
+ VOID
+ INTERNAL_CALL
+ GDIOBJ_LockMultipleObjs(ULONG ulCount,
+                         IN HGDIOBJ* ahObj,
+                         OUT PGDIOBJ* apObj)
+ {
+     UINT auiIndices[3] = {0,1,2};
+     UINT i, tmp ;
+     BOOL bUnsorted = TRUE;
+     /* First is greatest */
+     while(bUnsorted)
+     {
+         bUnsorted = FALSE;
+         for(i=1; i<ulCount; i++)
+         {
+             if((ULONG_PTR)ahObj[auiIndices[i-1]] < (ULONG_PTR)ahObj[auiIndices[i]])
+             {
+                 tmp = auiIndices[i-1];
+                 auiIndices[i-1] = auiIndices[i];
+                 auiIndices[i] = tmp;
+                 bUnsorted = TRUE;
+             }
+         }
+     }
+     for(i=0;i<ulCount;i++)
+         apObj[auiIndices[i]] = GDIOBJ_LockObj(ahObj[auiIndices[i]], GDI_OBJECT_TYPE_DONTCARE);
+ }
  /** PUBLIC FUNCTIONS **********************************************************/
  
  BOOL
@@@ -1741,10 -1773,9 +1773,9 @@@ IntGdiSetDCOwnerEx( HDC hDC, DWORD Owne
    {
       pDC = DC_LockDc ( hDC );
       MmCopyFromCaller(&pDC->dcattr, pDC->pdcattr, sizeof(DC_ATTR));
+      DC_vFreeDcAttr(pDC);
       DC_UnlockDc( pDC );
  
-      DC_FreeDcAttr( hDC );         // Free the dcattr!
       if (!DC_SetOwnership( hDC, NULL )) // This hDC is inaccessible!
          return Ret;
    }
@@@ -256,9 -256,9 +256,9 @@@ UpdateDeviceGammaRamp( HDEV hPDev 
       palPtr = (PALOBJ*) palGDI;
  
       if (pGDev->flFlags & PDEV_GAMMARAMP_TABLE)
-         palGDI->Mode |= PAL_GAMMACORRECTION;
+         palGDI->flFlags |= PAL_GAMMACORRECTION;
       else
-         palGDI->Mode &= ~PAL_GAMMACORRECTION;
+         palGDI->flFlags &= ~PAL_GAMMACORRECTION;
  
       if (!(pGDev->flFlags & PDEV_DRIVER_PUNTED_CALL)) // No punting, we hook
       {
@@@ -113,9 -113,6 +113,6 @@@ IntGdiLineTo(DC  *dc
      }
      else
      {
-        if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
-           DC_vUpdateLineBrush(dc);
          psurf = dc->dclevel.pSurface;
          if (NULL == psurf)
          {
@@@ -250,6 -247,9 +247,9 @@@ IntGdiPolyline(DC      *dc
      if (PATH_IsPathOpen(dc->dclevel))
          return PATH_Polyline(dc, pt, Count);
  
+     DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+                             NULL, dc->rosdc.CombinedClip->rclBounds);
      if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
          DC_vUpdateFillBrush(dc);
  
          }
      }
  
+     DC_vFinishBlit(dc, NULL);
      return Ret;
  }
  
@@@ -376,6 -378,7 +378,7 @@@ NtGdiLineTo(HDC  hDC
  {
      DC *dc;
      BOOL Ret;
+     RECT rcLockRect ;
  
      dc = DC_LockDc(hDC);
      if (!dc)
          return TRUE;
      }
  
+     rcLockRect.left = dc->pdcattr->ptlCurrent.x;
+     rcLockRect.top = dc->pdcattr->ptlCurrent.y;
+     rcLockRect.right = XEnd;
+     rcLockRect.bottom = YEnd;
+     IntLPtoDP(dc, &rcLockRect, 2);
+     /* The DCOrg is in device coordinates */
+     rcLockRect.left += dc->ptlDCOrig.x;
+     rcLockRect.top += dc->ptlDCOrig.y;
+     rcLockRect.right += dc->ptlDCOrig.x;
+     rcLockRect.bottom += dc->ptlDCOrig.y;
+     DC_vPrepareDCsForBlit(dc, rcLockRect, NULL, rcLockRect);
+     if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
+         DC_vUpdateLineBrush(dc);
      Ret = IntGdiLineTo(dc, XEnd, YEnd);
  
+     DC_vFinishBlit(dc, NULL);
      DC_UnlockDc(dc);
      return Ret;
  }
@@@ -14,7 -14,8 +14,8 @@@
  
  static UINT SystemPaletteUse = SYSPAL_NOSTATIC;  /* the program need save the pallete and restore it */
  
- PALETTE gpalRGB, gpalBGR, gpalMono;
+ PALETTE gpalRGB, gpalBGR, gpalMono, gpalRGB555, gpalRGB565, *gppalDefault;
+ PPALETTE appalSurfaceDefault[11];
  
  const PALETTEENTRY g_sysPalTemplate[NB_RESERVED_COLORS] =
  {
@@@ -84,18 -85,51 +85,51 @@@ HPALETTE FASTCALL PALETTE_Init(VOID
  
      /*  palette_size = visual->map_entries; */
  
-     gpalRGB.Mode = PAL_RGB;
+     gpalRGB.flFlags = PAL_RGB;
      gpalRGB.RedMask = RGB(0xFF, 0x00, 0x00);
      gpalRGB.GreenMask = RGB(0x00, 0xFF, 0x00);
      gpalRGB.BlueMask = RGB(0x00, 0x00, 0xFF);
+     gpalRGB.BaseObject.ulShareCount = 0;
+     gpalRGB.BaseObject.BaseFlags = 0 ;
  
-     gpalBGR.Mode = PAL_BGR;
+     gpalBGR.flFlags = PAL_BGR;
      gpalBGR.RedMask = RGB(0x00, 0x00, 0xFF);
      gpalBGR.GreenMask = RGB(0x00, 0xFF, 0x00);
      gpalBGR.BlueMask = RGB(0xFF, 0x00, 0x00);
+     gpalBGR.BaseObject.ulShareCount = 0;
+     gpalBGR.BaseObject.BaseFlags = 0 ;
+     gpalRGB555.flFlags = PAL_RGB16_555 | PAL_BITFIELDS;
+     gpalRGB555.RedMask = 0x7C00;
+     gpalRGB555.GreenMask = 0x3E0;
+     gpalRGB555.BlueMask = 0x1F;
+     gpalRGB555.BaseObject.ulShareCount = 0;
+     gpalRGB555.BaseObject.BaseFlags = 0 ;
+     gpalRGB565.flFlags = PAL_RGB16_565 | PAL_BITFIELDS;
+     gpalRGB565.RedMask = 0xF800;
+     gpalRGB565.GreenMask = 0x7E0;
+     gpalRGB565.BlueMask = 0x1F;
+     gpalRGB565.BaseObject.ulShareCount = 0;
+     gpalRGB565.BaseObject.BaseFlags = 0 ;
  
      memset(&gpalMono, 0, sizeof(PALETTE));
-     gpalMono.Mode = PAL_MONOCHROME;
+     gpalMono.flFlags = PAL_MONOCHROME;
+     gpalMono.BaseObject.ulShareCount = 0;
+     gpalMono.BaseObject.BaseFlags = 0 ;
+     /* Initialize default surface palettes */
+     gppalDefault = PALETTE_ShareLockPalette(hpalette);
+     appalSurfaceDefault[BMF_1BPP] = &gpalMono;
+     appalSurfaceDefault[BMF_4BPP] = gppalDefault;
+     appalSurfaceDefault[BMF_8BPP] = gppalDefault;
+     appalSurfaceDefault[BMF_16BPP] = &gpalRGB565;
+     appalSurfaceDefault[BMF_24BPP] = &gpalBGR;
+     appalSurfaceDefault[BMF_32BPP] = &gpalBGR;
+     appalSurfaceDefault[BMF_4RLE] = gppalDefault;
+     appalSurfaceDefault[BMF_8RLE] = gppalDefault;
+     appalSurfaceDefault[BMF_JPEG] = &gpalRGB;
+     appalSurfaceDefault[BMF_PNG] = &gpalRGB;
  
      return hpalette;
  }
@@@ -128,7 -162,7 +162,7 @@@ PALETTE_AllocPalette(ULONG Mode
      NewPalette = PalGDI->BaseObject.hHmgr;
  
      PalGDI->Self = NewPalette;
-     PalGDI->Mode = Mode;
+     PalGDI->flFlags = Mode;
  
      if (NULL != Colors)
      {
          RtlCopyMemory(PalGDI->IndexedColors, Colors, sizeof(PALETTEENTRY) * NumColors);
      }
  
-     if (PAL_INDEXED == Mode)
+     if (Mode & PAL_INDEXED)
      {
          PalGDI->NumColors = NumColors;
      }
-     else if (PAL_BITFIELDS == Mode)
+     else if (Mode & PAL_BITFIELDS)
      {
          PalGDI->RedMask = Red;
          PalGDI->GreenMask = Green;
          PalGDI->BlueMask = Blue;
-         
          if (Red == 0x7c00 && Green == 0x3E0 && Blue == 0x1F)
-             PalGDI->Mode |= PAL_RGB16_555;
+             PalGDI->flFlags |= PAL_RGB16_555;
          else if (Red == 0xF800 && Green == 0x7E0 && Blue == 0x1F)
-             PalGDI->Mode |= PAL_RGB16_565;
+             PalGDI->flFlags |= PAL_RGB16_565;
+         else if (Red == 0xFF0000 && Green == 0xFF00 && Blue == 0xFF)
+             PalGDI->flFlags |= PAL_BGR;
      }
  
      PALETTE_UnlockPalette(PalGDI);
@@@ -183,7 -219,7 +219,7 @@@ PALETTE_AllocPaletteIndexedRGB(ULONG Nu
      NewPalette = PalGDI->BaseObject.hHmgr;
  
      PalGDI->Self = NewPalette;
-     PalGDI->Mode = PAL_INDEXED;
+     PalGDI->flFlags = PAL_INDEXED;
  
      PalGDI->IndexedColors = ExAllocatePoolWithTag(PagedPool,
                                                    sizeof(PALETTEENTRY) * NumColors,
@@@ -287,7 -323,7 +323,7 @@@ ULON
  NTAPI
  PALETTE_ulGetNearestIndex(PALETTE* ppal, ULONG ulColor)
  {
-     if (ppal->Mode & PAL_INDEXED) // use fl & PALINDEXED
+     if (ppal->flFlags & PAL_INDEXED) // use fl & PALINDEXED
          return PALETTE_ulGetNearestPaletteIndex(ppal, ulColor);
      else
          return PALETTE_ulGetNearestBitFieldsIndex(ppal, ulColor);
@@@ -299,19 -335,19 +335,19 @@@ PALETTE_vGetBitMasks(PPALETTE ppal, PUL
  {
      ASSERT(pulColors);
  
-     if (ppal->Mode & PAL_INDEXED || ppal->Mode & PAL_RGB)
+     if (ppal->flFlags & PAL_INDEXED || ppal->flFlags & PAL_RGB)
      {
          pulColors[0] = RGB(0xFF, 0x00, 0x00);
          pulColors[1] = RGB(0x00, 0xFF, 0x00);
          pulColors[2] = RGB(0x00, 0x00, 0xFF);
      }
-     else if (ppal->Mode & PAL_BGR)
+     else if (ppal->flFlags & PAL_BGR)
      {
          pulColors[0] = RGB(0x00, 0x00, 0xFF);
          pulColors[1] = RGB(0x00, 0xFF, 0x00);
          pulColors[2] = RGB(0xFF, 0x00, 0x00);
      }
-     else if (ppal->Mode & PAL_BITFIELDS)
+     else if (ppal->flFlags & PAL_BITFIELDS)
      {
          pulColors[0] = ppal->RedMask;
          pulColors[1] = ppal->GreenMask;
@@@ -358,7 -394,7 +394,7 @@@ EngCreatePalette
  {
      HPALETTE Palette;
  
-     Palette = PALETTE_AllocPalette(Mode, NumColors, Colors, Red, Green, Blue);
+       Palette = PALETTE_AllocPalette(Mode, NumColors, Colors, Red, Green, Blue);
      if (Palette != NULL)
      {
          GDIOBJ_SetOwnership(Palette, NULL);
@@@ -399,7 -435,7 +435,7 @@@ PALOBJ_cGetColors(PALOBJ *PalObj, ULON
      /* NOTE: PaletteEntry ULONGs are in the same order as PALETTEENTRY. */
      RtlCopyMemory(PaletteEntry, PalGDI->IndexedColors + Start, sizeof(ULONG) * Colors);
  
-     if (PalGDI->Mode & PAL_GAMMACORRECTION)
+     if (PalGDI->flFlags & PAL_GAMMACORRECTION)
          ColorCorrection(PalGDI, (PPALETTEENTRY)PaletteEntry, Colors);
  
      return Colors;
@@@ -630,17 -666,17 +666,17 @@@ COLORREF APIENTRY NtGdiGetNearestColor(
           return nearest;
        }
  
-       if (palGDI->Mode & PAL_INDEXED)
+       if (palGDI->flFlags & PAL_INDEXED)
        {
           ULONG index;
           index = PALETTE_ulGetNearestPaletteIndex(palGDI, Color);
           nearest = PALETTE_ulGetRGBColorFromIndex(palGDI, index);
        }
-       else if (palGDI->Mode & PAL_RGB || palGDI->Mode & PAL_BGR)
+       else if (palGDI->flFlags & PAL_RGB || palGDI->flFlags & PAL_BGR)
        {
           nearest = Color;
        }
-       else if (palGDI->Mode & PAL_BITFIELDS)
+       else if (palGDI->flFlags & PAL_BITFIELDS)
        {
           RBits = 8 - GetNumberOfBits(palGDI->RedMask);
           GBits = 8 - GetNumberOfBits(palGDI->GreenMask);
@@@ -668,7 -704,7 +704,7 @@@ NtGdiGetNearestPaletteIndex
  
      if (ppal)
      {
-         if (ppal->Mode & PAL_INDEXED)
+         if (ppal->flFlags & PAL_INDEXED)
          {
              /* Return closest match for the given RGB color */
              index = PALETTE_ulGetNearestPaletteIndex(ppal, crColor);
@@@ -408,7 -408,7 +408,7 @@@ BOOL FASTCALL PATH_RoundRect(DC *dc, IN
     FLOAT_POINT ellCorners[2];
  
     pPath = PATH_LockPath( dc->dclevel.hPath );
-    if (!pPath) return FALSE;   
+    if (!pPath) return FALSE;
  
     /* Check that path is open */
     if(pPath->state!=PATH_Open)
@@@ -544,7 -544,7 +544,7 @@@ PATH_Arc ( PDC dc, INT x1, INT y1, INT 
    if ( pPath->state != PATH_Open )
    {
      Ret = FALSE;
-     goto ArcExit;    
+     goto ArcExit;
    }
  
    /* Check for zero height / width */
@@@ -697,7 -697,7 +697,7 @@@ PATH_PolyBezierTo ( PDC dc, const POIN
  
     pPath = PATH_LockPath( dc->dclevel.hPath );
     if (!pPath) return FALSE;
-    
    /* Check that path is open */
    if ( pPath->state != PATH_Open )
    {
@@@ -805,7 -805,7 +805,7 @@@ PATH_PolylineTo ( PDC dc, const POINT *
  
    pPath = PATH_LockPath( dc->dclevel.hPath );
    if (!pPath) return FALSE;
-    
    /* Check that path is open */
    if ( pPath->state != PATH_Open )
    {
@@@ -1597,7 -1597,7 +1597,7 @@@ PATH_WidenPath(DC *dc
                  numStrokes++;
                  j = 0;
                  if (numStrokes == 1)
-                    pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(PPATH), TAG_PATH);                
+                    pStrokes = ExAllocatePoolWithTag(PagedPool, numStrokes * sizeof(PPATH), TAG_PATH);
                  else
                  {
                     pOldStrokes = pStrokes; // Save old pointer.
          }
      }
  
-     pNewPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);  
+     pNewPath = ExAllocatePoolWithTag(PagedPool, sizeof(PATH), TAG_PATH);
      PATH_InitGdiPath(pNewPath);
      pNewPath->state = PATH_Open;
  
@@@ -2012,7 -2012,7 +2012,7 @@@ PATH_add_outline(PDC dc, INT x, INT y, 
    }
  
    IntGdiCloseFigure( pPath );
-   PATH_UnlockPath( pPath );     
+   PATH_UnlockPath( pPath );
    return TRUE;
  }
  
   *      PATH_ExtTextOut
   */
  BOOL
- FASTCALL 
+ FASTCALL
  PATH_ExtTextOut(PDC dc, INT x, INT y, UINT flags, const RECTL *lprc,
                       LPCWSTR str, UINT count, const INT *dx)
  {
@@@ -2210,7 -2210,7 +2210,7 @@@ NtGdiCloseFigure(HDC hDC
    {
       SetLastWin32Error(ERROR_INVALID_PARAMETER);
       return FALSE;
-   }   
+   }
    pPath = PATH_LockPath( pDc->dclevel.hPath );
    if (!pPath)
    {
@@@ -2281,7 -2281,7 +2281,7 @@@ NtGdiFillPath(HDC  hDC
    PPATH pPath;
    PDC_ATTR pdcattr;
    PDC dc = DC_LockDc ( hDC );
-  
    if ( !dc )
    {
       SetLastWin32Error(ERROR_INVALID_PARAMETER);
       return FALSE;
    }
  
+   DC_vPrepareDCsForBlit(dc, dc->rosdc.CombinedClip->rclBounds,
+                             NULL, dc->rosdc.CombinedClip->rclBounds);
    pdcattr = dc->pdcattr;
  
    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
    }
  
    PATH_UnlockPath( pPath );
+   DC_vFinishBlit(dc, NULL);
    DC_UnlockDc ( dc );
    return ret;
  }
@@@ -2328,7 -2332,7 +2332,7 @@@ NtGdiFlattenPath(HDC  hDC
     pDc = DC_LockDc(hDC);
     if (!pDc)
     {
-       SetLastWin32Error(ERROR_INVALID_HANDLE);  
+       SetLastWin32Error(ERROR_INVALID_HANDLE);
        return FALSE;
     }
  
@@@ -2572,6 -2576,9 +2576,9 @@@ NtGdiStrokeAndFillPath(HDC hDC
       return FALSE;
    }
  
+   DC_vPrepareDCsForBlit(pDc, pDc->rosdc.CombinedClip->rclBounds,
+                             NULL, pDc->rosdc.CombinedClip->rclBounds);
    pdcattr = pDc->pdcattr;
  
    if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
    if (bRet) PATH_EmptyPath(pPath);
  
    PATH_UnlockPath( pPath );
+   DC_vFinishBlit(pDc, NULL);
    DC_UnlockDc(pDc);
    return bRet;
  }
@@@ -2612,12 -2620,17 +2620,17 @@@ NtGdiStrokePath(HDC hDC
       return FALSE;
    }
  
+   DC_vPrepareDCsForBlit(pDc, pDc->rosdc.CombinedClip->rclBounds,
+                             NULL, pDc->rosdc.CombinedClip->rclBounds);
    pdcattr = pDc->pdcattr;
  
    if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
       DC_vUpdateLineBrush(pDc);
  
    bRet = PATH_StrokePath(pDc, pPath);
+   DC_vFinishBlit(pDc, NULL);
    PATH_EmptyPath(pPath);
  
    PATH_UnlockPath( pPath );
@@@ -2630,7 -2643,7 +2643,7 @@@ APIENTR
  NtGdiWidenPath(HDC  hDC)
  {
    BOOL Ret;
-   PDC pdc = DC_LockDc ( hDC );    
+   PDC pdc = DC_LockDc ( hDC );
    if ( !pdc )
    {
       SetLastWin32Error(ERROR_INVALID_PARAMETER);
@@@ -63,11 -63,11 +63,11 @@@ IntGdiExtCreatePen
  {
     HPEN hPen;
     PBRUSH pbrushPen;
-    static const BYTE PatternAlternate[] = {0x55, 0x55, 0x55};
-    static const BYTE PatternDash[] = {0xFF, 0xFF, 0xC0};
-    static const BYTE PatternDot[] = {0xE3, 0x8E, 0x38};
-    static const BYTE PatternDashDot[] = {0xFF, 0x81, 0xC0};
-    static const BYTE PatternDashDotDot[] = {0xFF, 0x8E, 0x38};
+    static const BYTE PatternAlternate[] = {0x55, 0x55, 0x55, 0};
+    static const BYTE PatternDash[] = {0xFF, 0xFF, 0xC0, 0};
+    static const BYTE PatternDot[] = {0xE3, 0x8E, 0x38, 0};
+    static const BYTE PatternDashDot[] = {0xFF, 0x81, 0xC0, 0};
+    static const BYTE PatternDashDotDot[] = {0xFF, 0x8E, 0x38, 0};
  
     dwWidth = abs(dwWidth);
  
  
        case PS_ALTERNATE:
           pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
-          pbrushPen->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternAlternate);
+          pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternAlternate);
           break;
  
        case PS_DOT:
           pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
-          pbrushPen->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDot);
+          pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDot);
           break;
  
        case PS_DASH:
           pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
-          pbrushPen->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDash);
+          pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDash);
           break;
  
        case PS_DASHDOT:
           pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
-          pbrushPen->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDot);
+          pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDot);
           break;
  
        case PS_DASHDOTDOT:
           pbrushPen->flAttrs |= GDIBRUSH_IS_BITMAP;
-          pbrushPen->hbmPattern = IntGdiCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDotDot);
+          pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDotDot);
           break;
  
        case PS_INSIDEFRAME:
@@@ -3687,7 -3687,7 +3687,7 @@@ NtGdiGetRandomRgn
          else if (pDC->dclevel.prgnMeta) hSrc = ((PROSRGNDATA)pDC->dclevel.prgnMeta)->BaseObject.hHmgr;
          break;
      case SYSRGN:
-         if (pDC->prgnVis) hSrc = ((PROSRGNDATA)pDC->prgnVis)->BaseObject.hHmgr;
+         if (pDC->prgnVis) hSrc = pDC->prgnVis->BaseObject.hHmgr;
          break;
      default:
          hSrc = 0;
@@@ -180,7 -180,7 +180,7 @@@ CreateStockObjects(void
      StockObjects[NULL_PEN]  = IntCreateStockPen(NullPen.lopnStyle, NullPen.lopnWidth.x, BS_SOLID, NullPen.lopnColor);
  
      StockObjects[20] = NULL; /* TODO: Unknown internal stock object */
-     StockObjects[DEFAULT_BITMAP] = IntGdiCreateBitmap(1, 1, 1, 1, NULL);
+     StockObjects[DEFAULT_BITMAP] = GreCreateBitmap(1, 1, 1, 1, NULL);
  
      (void) TextIntCreateFontIndirect(&OEMFixedFont, (HFONT*)&StockObjects[OEM_FIXED_FONT]);
      (void) TextIntCreateFontIndirect(&AnsiFixedFont, (HFONT*)&StockObjects[ANSI_FIXED_FONT]);
      (void) TextIntCreateFontIndirect(&SystemFixedFont, (HFONT*)&StockObjects[SYSTEM_FIXED_FONT]);
      (void) TextIntCreateFontIndirect(&DefaultGuiFont, (HFONT*)&StockObjects[DEFAULT_GUI_FONT]);
  
-     StockObjects[DEFAULT_PALETTE] = (HGDIOBJ)PALETTE_Init();
+     StockObjects[DEFAULT_PALETTE] = (HGDIOBJ)gppalDefault->BaseObject.hHmgr;
  
      for (Object = 0; Object < NB_STOCK_OBJECTS; Object++)
      {
@@@ -150,18 -150,6 +150,6 @@@ EngFindResource
    return NULL;
  }
  
- /*
-  * @unimplemented
-  */
- LPWSTR
- APIENTRY
- EngGetDriverName ( IN HDEV hdev )
- {
-   // www.osr.com/ddk/graphics/gdifncs_2gx3.htm
-   UNIMPLEMENTED;
-   return NULL;
- }
  /*
   * @unimplemented
   */