Fixed line endings.
authorFilip Navara <filip.navara@gmail.com>
Mon, 6 Oct 2003 18:49:50 +0000 (18:49 +0000)
committerFilip Navara <filip.navara@gmail.com>
Mon, 6 Oct 2003 18:49:50 +0000 (18:49 +0000)
svn path=/trunk/; revision=6257

reactos/config
reactos/lib/gdi32/objects/bitblt.c
reactos/lib/user32/windows/bitmap.c
reactos/ntoskrnl/cm/rtlfunc.c
reactos/ntoskrnl/io/driver.c
reactos/subsys/system/explorer/buildno.h
reactos/subsys/system/explorer/makefile_rex
reactos/subsys/win32k/ntuser/windc.c

index f806bdf..2db3d94 100644 (file)
@@ -1,38 +1,38 @@
-#\r
-# Architecture to build for\r
-#\r
-# Specify one of: i386\r
-# Possible values in the future: alpha,i386,m68k,mips,powerpc\r
-ARCH := i386\r
-\r
-#\r
-# Whether to compile in the kernel debugger\r
-#\r
-KDBG := 0\r
-\r
-#\r
-# Whether to compile for debugging\r
-#\r
-DBG := 0\r
-\r
-#\r
-# Whether to compile a multiprocessor or single processor version\r
-#\r
-MP := 0\r
-\r
-#\r
-# Whether to compile for ACPI compliant systems\r
-#\r
-ACPI := 0\r
-\r
-#\r
-# Whether to use Structured Exception Handling\r
-#\r
-SEH := 0\r
-\r
-\r
-#\r
-# Which version of NDIS do we support up to?\r
-#\r
-#NDISVERSION=NDIS50\r
-\r
+#
+# Architecture to build for
+#
+# Specify one of: i386
+# Possible values in the future: alpha,i386,m68k,mips,powerpc
+ARCH := i386
+
+#
+# Whether to compile in the kernel debugger
+#
+KDBG := 0
+
+#
+# Whether to compile for debugging
+#
+DBG := 0
+
+#
+# Whether to compile a multiprocessor or single processor version
+#
+MP := 0
+
+#
+# Whether to compile for ACPI compliant systems
+#
+ACPI := 0
+
+#
+# Whether to use Structured Exception Handling
+#
+SEH := 0
+
+
+#
+# Which version of NDIS do we support up to?
+#
+#NDISVERSION=NDIS50
+
index dd0616d..d940273 100644 (file)
-#ifdef UNICODE\r
-#undef UNICODE\r
-#endif\r
-\r
-#undef WIN32_LEAN_AND_MEAN\r
-#include <windows.h>\r
-#include <ddk/ntddk.h>\r
-#include <win32k/kapi.h>\r
-#include <debug.h>\r
-\r
-/*\r
- * @implemented\r
- */\r
-BOOL\r
-STDCALL\r
-BitBlt(HDC  hDCDest,\r
-       INT  XDest,\r
-       INT  YDest,\r
-       INT  Width,\r
-       INT  Height,\r
-       HDC  hDCSrc,\r
-       INT  XSrc,\r
-       INT  YSrc,\r
-       DWORD  ROP)\r
-{\r
-       return NtGdiBitBlt(hDCDest, XDest, YDest, Width, Height, hDCSrc, XSrc, YSrc, ROP);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-HBITMAP\r
-STDCALL\r
-CreateBitmap(INT  Width,\r
-       INT  Height,\r
-       UINT  Planes,\r
-       UINT  BitsPerPel,\r
-       CONST VOID *Bits)\r
-{\r
-       return NtGdiCreateBitmap(Width, Height, Planes, BitsPerPel, Bits);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-HBITMAP\r
-STDCALL\r
-CreateBitmapIndirect(CONST BITMAP  *BM)\r
-{\r
-       return NtGdiCreateBitmapIndirect(BM);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-HBITMAP\r
-STDCALL\r
-CreateCompatibleBitmap(HDC hDC,\r
-       INT  Width,\r
-       INT  Height)\r
-{\r
-       return NtGdiCreateCompatibleBitmap(hDC, Width, Height);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-HBITMAP\r
-STDCALL\r
-CreateDiscardableBitmap(HDC  hDC,\r
-       INT  Width,\r
-       INT  Height)\r
-{\r
-       return NtGdiCreateDiscardableBitmap(hDC, Width, Height);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-HBITMAP\r
-STDCALL\r
-CreateDIBitmap(HDC  hDC,\r
-       CONST BITMAPINFOHEADER  *bmih,\r
-       DWORD  Init,\r
-       CONST VOID  *bInit,\r
-       CONST BITMAPINFO  *bmi,\r
-       UINT  Usage)\r
-{\r
-       return NtGdiCreateDIBitmap(hDC, bmih, Init, bInit, bmi, Usage);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-LONG\r
-STDCALL\r
-GetBitmapBits(HBITMAP  hBitmap,\r
-       LONG  Count,\r
-       LPVOID  Bits)\r
-{\r
-       return NtGdiGetBitmapBits(hBitmap, Count, Bits);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-BOOL\r
-STDCALL\r
-GetBitmapDimensionEx(HBITMAP  hBitmap,\r
-       LPSIZE  Dimension)\r
-{\r
-       return NtGdiGetBitmapDimensionEx(hBitmap, Dimension);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-int\r
-STDCALL\r
-GetDIBits(HDC  hDC,\r
-       HBITMAP hBitmap,\r
-       UINT  StartScan,\r
-       UINT  ScanLines,\r
-       LPVOID  Bits,\r
-       LPBITMAPINFO   bi,\r
-       UINT  Usage)\r
-{\r
-       return NtGdiGetDIBits(hDC, hBitmap, StartScan, ScanLines, Bits, bi, Usage);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-BOOL\r
-STDCALL\r
-MaskBlt(HDC  hDCDest,\r
-       INT  XDest,\r
-       INT  YDest,\r
-       INT  Width,\r
-       INT  Height,\r
-       HDC  hDCSrc,\r
-       INT  XSrc,\r
-       INT  YSrc,\r
-       HBITMAP  hMaskBitmap,\r
-       INT  xMask,\r
-       INT  yMask,\r
-       DWORD  ROP)\r
-{\r
-       return NtGdiMaskBlt(hDCDest, XDest, YDest, Width, Height, hDCSrc, XSrc, YSrc, hMaskBitmap, xMask, yMask, ROP);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-BOOL\r
-STDCALL\r
-PlgBlt(HDC  hDCDest,\r
-       CONST POINT  *Point,\r
-       HDC  hDCSrc, \r
-       INT  XSrc,  \r
-       INT  YSrc,  \r
-       INT  Width, \r
-       INT  Height,\r
-       HBITMAP  hMaskBitmap,\r
-       INT  xMask,      \r
-       INT  yMask)\r
-{\r
-       return NtGdiPlgBlt(hDCDest, Point, hDCSrc, XSrc, YSrc, Width, Height, hMaskBitmap, xMask, yMask);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-LONG\r
-STDCALL\r
-SetBitmapBits(HBITMAP  hBitmap,\r
-       DWORD  Bytes,\r
-       CONST VOID *Bits)\r
-{\r
-       return NtGdiSetBitmapBits(hBitmap, Bytes, Bits);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-int\r
-STDCALL\r
-SetDIBits(HDC  hDC,\r
-       HBITMAP  hBitmap,\r
-       UINT  StartScan,\r
-       UINT  ScanLines,\r
-       CONST VOID  *Bits,\r
-       CONST BITMAPINFO  *bmi,\r
-       UINT  ColorUse)\r
-{\r
-       return NtGdiSetDIBits(hDC, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-int\r
-STDCALL\r
-SetDIBitsToDevice(HDC  hDC,\r
-       INT  XDest,\r
-       INT  YDest,\r
-       DWORD  Width,\r
-       DWORD  Height,\r
-       INT  XSrc,\r
-       INT  YSrc,\r
-       UINT  StartScan,\r
-       UINT  ScanLines,\r
-       CONST VOID  *Bits,\r
-       CONST BITMAPINFO  *bmi,\r
-       UINT  ColorUse)\r
-{\r
-       return NtGdiSetDIBitsToDevice(hDC, XDest, YDest, Width, Height, XSrc, YSrc, StartScan, ScanLines,\r
-               Bits, bmi, ColorUse);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-BOOL\r
-STDCALL\r
-StretchBlt(\r
-           HDC hdcDest,      // handle to destination DC\r
-           int nXOriginDest, // x-coord of destination upper-left corner\r
-           int nYOriginDest, // y-coord of destination upper-left corner\r
-           int nWidthDest,   // width of destination rectangle\r
-           int nHeightDest,  // height of destination rectangle\r
-           HDC hdcSrc,       // handle to source DC\r
-           int nXOriginSrc,  // x-coord of source upper-left corner\r
-           int nYOriginSrc,  // y-coord of source upper-left corner\r
-           int nWidthSrc,    // width of source rectangle\r
-           int nHeightSrc,   // height of source rectangle\r
-           DWORD dwRop       // raster operation code\r
-       )\r
-{\r
-       //SetLastError(ERROR_CALL_NOT_IMPLEMENTED);\r
-       if ( (nWidthDest==nWidthSrc) && (nHeightDest==nHeightSrc) )\r
-       {\r
-               return  BitBlt(hdcDest,\r
-                               nXOriginDest,  // x-coord of destination upper-left corner\r
-                               nYOriginDest,  // y-coord of destination upper-left corner\r
-                               nWidthDest,  // width of destination rectangle\r
-                               nHeightDest, // height of destination rectangle\r
-                               hdcSrc,  // handle to source DC\r
-                               nXOriginSrc,   // x-coordinate of source upper-left corner\r
-                               nYOriginSrc,   // y-coordinate of source upper-left corner\r
-                               dwRop  // raster operation code\r
-                               );\r
-       }\r
-       \r
-       DPRINT1("FIXME: StretchBlt can only Blt, not Stretch!\n");\r
-       return FALSE;\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-int\r
-STDCALL\r
-StretchDIBits(HDC  hDC,\r
-       INT  XDest,\r
-       INT  YDest,\r
-       INT  DestWidth,\r
-       INT  DestHeight,\r
-       INT  XSrc,\r
-       INT  YSrc,\r
-       INT  SrcWidth,\r
-       INT  SrcHeight,\r
-       CONST VOID  *Bits,\r
-       CONST BITMAPINFO  *BitsInfo,\r
-       UINT  Usage,\r
-       DWORD  ROP)\r
-{\r
-       return NtGdiStretchDIBits(hDC, XDest, YDest, DestWidth, DestHeight, XSrc, YSrc,\r
-               SrcWidth, SrcHeight, Bits, BitsInfo, Usage, ROP);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-HBITMAP \r
-STDCALL \r
-CreateDIBSection(HDC hDC,\r
-       CONST BITMAPINFO  *bmi,\r
-       UINT  Usage,\r
-       VOID  *Bits,\r
-       HANDLE  hSection,\r
-       DWORD  dwOffset)\r
-{\r
-       return NtGdiCreateDIBSection(hDC, bmi, Usage, Bits, hSection, dwOffset);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-COLORREF \r
-STDCALL \r
-SetPixel(HDC  hDC,\r
-       INT  X,\r
-       INT  Y,\r
-       COLORREF  Color)\r
-{\r
-       return NtGdiSetPixel(hDC, X, Y, Color);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-BOOL STDCALL\r
-PatBlt(HDC hDC, INT Top, INT Left, INT Width, INT Height, ULONG Rop)\r
-{\r
-  return(NtGdiPatBlt(hDC, Top, Left, Width, Height, Rop));\r
-}\r
-\r
-/*\r
- * @implemented\r
- */\r
-WINBOOL \r
-STDCALL \r
-PolyPatBlt(HDC hDC,DWORD dwRop,PPATRECT pRects,int cRects,ULONG Reserved)\r
-{\r
-       return NtGdiPolyPatBlt(hDC,dwRop,pRects,cRects,Reserved);\r
-}\r
-\r
-\r
-/*\r
-\r
-BOOL STDCALL NtGdiExtFloodFill(HDC  hDC, INT  XStart, INT  YStart, COLORREF  Color, UINT  FillType)\r
-BOOL STDCALL NtGdiFloodFill(HDC  hDC, INT  XStart, INT  YStart, COLORREF  Fill)\r
-UINT STDCALL NtGdiGetDIBColorTable(HDC  hDC, UINT  StartIndex, UINT  Entries, RGBQUAD  *Colors)\r
-COLORREF STDCALL NtGdiGetPixel(HDC  hDC,\r
-                       INT  XPos,\r
-                       INT  YPos)\r
-BOOL STDCALL NtGdiSetBitmapDimensionEx(HBITMAP  hBitmap,\r
-                               INT  Width,\r
-                               INT  Height,\r
-                               LPSIZE  Size)\r
-UINT STDCALL NtGdiSetDIBColorTable(HDC  hDC,\r
-                           UINT  StartIndex,\r
-                           UINT  Entries,\r
-                           CONST RGBQUAD  *Colors)\r
-BOOL STDCALL NtGdiSetPixelV(HDC  hDC,\r
-                    INT  X,\r
-                    INT  Y,\r
-                    COLORREF  Color)\r
-BOOL STDCALL NtGdiStretchBlt(HDC  hDCDest,\r
-                     INT  XOriginDest,\r
-                     INT  YOriginDest,\r
-                     INT  WidthDest,\r
-                     INT  HeightDest,\r
-                     HDC  hDCSrc,\r
-                     INT  XOriginSrc,\r
-                     INT  YOriginSrc,\r
-                     INT  WidthSrc,    \r
-                     INT  HeightSrc, \r
-                     DWORD  ROP)\r
-\r
-INT BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp)\r
-HBITMAP  BITMAPOBJ_CopyBitmap(HBITMAP  hBitmap)\r
-int DIB_GetDIBWidthBytes(int  width, int  depth)\r
-int DIB_GetDIBImageBytes (int  width, int  height, int  depth)\r
-int DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)\r
-\r
-*/\r
+#ifdef UNICODE
+#undef UNICODE
+#endif
+
+#undef WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <ddk/ntddk.h>
+#include <win32k/kapi.h>
+#include <debug.h>
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+BitBlt(HDC  hDCDest,
+       INT  XDest,
+       INT  YDest,
+       INT  Width,
+       INT  Height,
+       HDC  hDCSrc,
+       INT  XSrc,
+       INT  YSrc,
+       DWORD  ROP)
+{
+       return NtGdiBitBlt(hDCDest, XDest, YDest, Width, Height, hDCSrc, XSrc, YSrc, ROP);
+}
+
+
+/*
+ * @implemented
+ */
+HBITMAP
+STDCALL
+CreateBitmap(INT  Width,
+       INT  Height,
+       UINT  Planes,
+       UINT  BitsPerPel,
+       CONST VOID *Bits)
+{
+       return NtGdiCreateBitmap(Width, Height, Planes, BitsPerPel, Bits);
+}
+
+
+/*
+ * @implemented
+ */
+HBITMAP
+STDCALL
+CreateBitmapIndirect(CONST BITMAP  *BM)
+{
+       return NtGdiCreateBitmapIndirect(BM);
+}
+
+
+/*
+ * @implemented
+ */
+HBITMAP
+STDCALL
+CreateCompatibleBitmap(HDC hDC,
+       INT  Width,
+       INT  Height)
+{
+       return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
+}
+
+
+/*
+ * @implemented
+ */
+HBITMAP
+STDCALL
+CreateDiscardableBitmap(HDC  hDC,
+       INT  Width,
+       INT  Height)
+{
+       return NtGdiCreateDiscardableBitmap(hDC, Width, Height);
+}
+
+
+/*
+ * @implemented
+ */
+HBITMAP
+STDCALL
+CreateDIBitmap(HDC  hDC,
+       CONST BITMAPINFOHEADER  *bmih,
+       DWORD  Init,
+       CONST VOID  *bInit,
+       CONST BITMAPINFO  *bmi,
+       UINT  Usage)
+{
+       return NtGdiCreateDIBitmap(hDC, bmih, Init, bInit, bmi, Usage);
+}
+
+
+/*
+ * @implemented
+ */
+LONG
+STDCALL
+GetBitmapBits(HBITMAP  hBitmap,
+       LONG  Count,
+       LPVOID  Bits)
+{
+       return NtGdiGetBitmapBits(hBitmap, Count, Bits);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+GetBitmapDimensionEx(HBITMAP  hBitmap,
+       LPSIZE  Dimension)
+{
+       return NtGdiGetBitmapDimensionEx(hBitmap, Dimension);
+}
+
+
+/*
+ * @implemented
+ */
+int
+STDCALL
+GetDIBits(HDC  hDC,
+       HBITMAP hBitmap,
+       UINT  StartScan,
+       UINT  ScanLines,
+       LPVOID  Bits,
+       LPBITMAPINFO   bi,
+       UINT  Usage)
+{
+       return NtGdiGetDIBits(hDC, hBitmap, StartScan, ScanLines, Bits, bi, Usage);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+MaskBlt(HDC  hDCDest,
+       INT  XDest,
+       INT  YDest,
+       INT  Width,
+       INT  Height,
+       HDC  hDCSrc,
+       INT  XSrc,
+       INT  YSrc,
+       HBITMAP  hMaskBitmap,
+       INT  xMask,
+       INT  yMask,
+       DWORD  ROP)
+{
+       return NtGdiMaskBlt(hDCDest, XDest, YDest, Width, Height, hDCSrc, XSrc, YSrc, hMaskBitmap, xMask, yMask, ROP);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+PlgBlt(HDC  hDCDest,
+       CONST POINT  *Point,
+       HDC  hDCSrc, 
+       INT  XSrc,  
+       INT  YSrc,  
+       INT  Width, 
+       INT  Height,
+       HBITMAP  hMaskBitmap,
+       INT  xMask,      
+       INT  yMask)
+{
+       return NtGdiPlgBlt(hDCDest, Point, hDCSrc, XSrc, YSrc, Width, Height, hMaskBitmap, xMask, yMask);
+}
+
+
+/*
+ * @implemented
+ */
+LONG
+STDCALL
+SetBitmapBits(HBITMAP  hBitmap,
+       DWORD  Bytes,
+       CONST VOID *Bits)
+{
+       return NtGdiSetBitmapBits(hBitmap, Bytes, Bits);
+}
+
+
+/*
+ * @implemented
+ */
+int
+STDCALL
+SetDIBits(HDC  hDC,
+       HBITMAP  hBitmap,
+       UINT  StartScan,
+       UINT  ScanLines,
+       CONST VOID  *Bits,
+       CONST BITMAPINFO  *bmi,
+       UINT  ColorUse)
+{
+       return NtGdiSetDIBits(hDC, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
+}
+
+
+/*
+ * @implemented
+ */
+int
+STDCALL
+SetDIBitsToDevice(HDC  hDC,
+       INT  XDest,
+       INT  YDest,
+       DWORD  Width,
+       DWORD  Height,
+       INT  XSrc,
+       INT  YSrc,
+       UINT  StartScan,
+       UINT  ScanLines,
+       CONST VOID  *Bits,
+       CONST BITMAPINFO  *bmi,
+       UINT  ColorUse)
+{
+       return NtGdiSetDIBitsToDevice(hDC, XDest, YDest, Width, Height, XSrc, YSrc, StartScan, ScanLines,
+               Bits, bmi, ColorUse);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+STDCALL
+StretchBlt(
+           HDC hdcDest,      // handle to destination DC
+           int nXOriginDest, // x-coord of destination upper-left corner
+           int nYOriginDest, // y-coord of destination upper-left corner
+           int nWidthDest,   // width of destination rectangle
+           int nHeightDest,  // height of destination rectangle
+           HDC hdcSrc,       // handle to source DC
+           int nXOriginSrc,  // x-coord of source upper-left corner
+           int nYOriginSrc,  // y-coord of source upper-left corner
+           int nWidthSrc,    // width of source rectangle
+           int nHeightSrc,   // height of source rectangle
+           DWORD dwRop       // raster operation code
+       )
+{
+       //SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+       if ( (nWidthDest==nWidthSrc) && (nHeightDest==nHeightSrc) )
+       {
+               return  BitBlt(hdcDest,
+                               nXOriginDest,  // x-coord of destination upper-left corner
+                               nYOriginDest,  // y-coord of destination upper-left corner
+                               nWidthDest,  // width of destination rectangle
+                               nHeightDest, // height of destination rectangle
+                               hdcSrc,  // handle to source DC
+                               nXOriginSrc,   // x-coordinate of source upper-left corner
+                               nYOriginSrc,   // y-coordinate of source upper-left corner
+                               dwRop  // raster operation code
+                               );
+       }
+       
+       DPRINT1("FIXME: StretchBlt can only Blt, not Stretch!\n");
+       return FALSE;
+}
+
+
+/*
+ * @implemented
+ */
+int
+STDCALL
+StretchDIBits(HDC  hDC,
+       INT  XDest,
+       INT  YDest,
+       INT  DestWidth,
+       INT  DestHeight,
+       INT  XSrc,
+       INT  YSrc,
+       INT  SrcWidth,
+       INT  SrcHeight,
+       CONST VOID  *Bits,
+       CONST BITMAPINFO  *BitsInfo,
+       UINT  Usage,
+       DWORD  ROP)
+{
+       return NtGdiStretchDIBits(hDC, XDest, YDest, DestWidth, DestHeight, XSrc, YSrc,
+               SrcWidth, SrcHeight, Bits, BitsInfo, Usage, ROP);
+}
+
+
+/*
+ * @implemented
+ */
+HBITMAP 
+STDCALL 
+CreateDIBSection(HDC hDC,
+       CONST BITMAPINFO  *bmi,
+       UINT  Usage,
+       VOID  *Bits,
+       HANDLE  hSection,
+       DWORD  dwOffset)
+{
+       return NtGdiCreateDIBSection(hDC, bmi, Usage, Bits, hSection, dwOffset);
+}
+
+
+/*
+ * @implemented
+ */
+COLORREF 
+STDCALL 
+SetPixel(HDC  hDC,
+       INT  X,
+       INT  Y,
+       COLORREF  Color)
+{
+       return NtGdiSetPixel(hDC, X, Y, Color);
+}
+
+
+/*
+ * @implemented
+ */
+BOOL STDCALL
+PatBlt(HDC hDC, INT Top, INT Left, INT Width, INT Height, ULONG Rop)
+{
+  return(NtGdiPatBlt(hDC, Top, Left, Width, Height, Rop));
+}
+
+/*
+ * @implemented
+ */
+WINBOOL 
+STDCALL 
+PolyPatBlt(HDC hDC,DWORD dwRop,PPATRECT pRects,int cRects,ULONG Reserved)
+{
+       return NtGdiPolyPatBlt(hDC,dwRop,pRects,cRects,Reserved);
+}
+
+
+/*
+
+BOOL STDCALL NtGdiExtFloodFill(HDC  hDC, INT  XStart, INT  YStart, COLORREF  Color, UINT  FillType)
+BOOL STDCALL NtGdiFloodFill(HDC  hDC, INT  XStart, INT  YStart, COLORREF  Fill)
+UINT STDCALL NtGdiGetDIBColorTable(HDC  hDC, UINT  StartIndex, UINT  Entries, RGBQUAD  *Colors)
+COLORREF STDCALL NtGdiGetPixel(HDC  hDC,
+                       INT  XPos,
+                       INT  YPos)
+BOOL STDCALL NtGdiSetBitmapDimensionEx(HBITMAP  hBitmap,
+                               INT  Width,
+                               INT  Height,
+                               LPSIZE  Size)
+UINT STDCALL NtGdiSetDIBColorTable(HDC  hDC,
+                           UINT  StartIndex,
+                           UINT  Entries,
+                           CONST RGBQUAD  *Colors)
+BOOL STDCALL NtGdiSetPixelV(HDC  hDC,
+                    INT  X,
+                    INT  Y,
+                    COLORREF  Color)
+BOOL STDCALL NtGdiStretchBlt(HDC  hDCDest,
+                     INT  XOriginDest,
+                     INT  YOriginDest,
+                     INT  WidthDest,
+                     INT  HeightDest,
+                     HDC  hDCSrc,
+                     INT  XOriginSrc,
+                     INT  YOriginSrc,
+                     INT  WidthSrc,    
+                     INT  HeightSrc, 
+                     DWORD  ROP)
+
+INT BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp)
+HBITMAP  BITMAPOBJ_CopyBitmap(HBITMAP  hBitmap)
+int DIB_GetDIBWidthBytes(int  width, int  depth)
+int DIB_GetDIBImageBytes (int  width, int  height, int  depth)
+int DIB_BitmapInfoSize (const BITMAPINFO * info, WORD coloruse)
+
+*/
index b483393..4359fdb 100644 (file)
-/*\r
- *  ReactOS kernel\r
- *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team\r
- *\r
- *  This program is free software; you can redistribute it and/or modify\r
- *  it under the terms of the GNU General Public License as published by\r
- *  the Free Software Foundation; either version 2 of the License, or\r
- *  (at your option) any later version.\r
- *\r
- *  This program is distributed in the hope that it will be useful,\r
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- *  GNU General Public License for more details.\r
- *\r
- *  You should have received a copy of the GNU General Public License\r
- *  along with this program; if not, write to the Free Software\r
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- */\r
-/* $Id: bitmap.c,v 1.16 2003/10/06 18:24:54 navaraf Exp $\r
- *\r
- * PROJECT:         ReactOS user32.dll\r
- * FILE:            lib/user32/windows/input.c\r
- * PURPOSE:         Input\r
- * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)\r
- * UPDATE HISTORY:\r
- *      09-05-2001  CSH  Created\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#include <string.h>\r
-#include <windows.h>\r
-#include <user32.h>\r
-#include <debug.h>\r
-#include <stdlib.h>\r
-\r
-/*forward declerations... actualy in user32\windows\icon.c but usful here****/\r
-HICON ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);\r
-CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors);\r
-CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors);\r
-\r
-\r
-/* FUNCTIONS *****************************************************************/\r
-\r
-/*\r
- * @implemented\r
- */\r
-HANDLE STDCALL\r
-LoadImageA(HINSTANCE hinst,\r
-          LPCSTR lpszName,\r
-          UINT uType,\r
-          int cxDesired,\r
-          int cyDesired,\r
-          UINT fuLoad)\r
-{\r
-  LPWSTR lpszWName;\r
-  HANDLE Handle;\r
-  UNICODE_STRING NameString;\r
-\r
-  if (HIWORD(lpszName))\r
-    {      \r
-      RtlCreateUnicodeStringFromAsciiz(&NameString, (LPSTR)lpszName);\r
-      lpszWName = NameString.Buffer;\r
-      Handle = LoadImageW(hinst, lpszWName, uType, cxDesired,\r
-                         cyDesired, fuLoad);\r
-      RtlFreeUnicodeString(&NameString);\r
-    }\r
-  else\r
-    {\r
-      Handle = LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired,\r
-                         cyDesired, fuLoad);\r
-    }\r
-  return(Handle);\r
-}\r
-\r
-\r
-HANDLE STATIC\r
-LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad)\r
-{\r
-  HANDLE hResource;\r
-  HANDLE h2Resource;\r
-  HANDLE hFile;\r
-  HANDLE hSection;\r
-  CURSORICONDIR* IconDIR;\r
-  HDC hScreenDc;\r
-  HANDLE hIcon;\r
-  ULONG HeaderSize;\r
-  ULONG ColourCount;\r
-  PVOID Data;\r
-  CURSORICONDIRENTRY* dirEntry;\r
-  ICONIMAGE* SafeIconImage;\r
-  GRPCURSORICONDIR* IconResDir;\r
-  INT id;\r
-  ICONIMAGE *ResIcon;\r
-\r
-  if (fuLoad & LR_SHARED)\r
-    DbgPrint("FIXME: need LR_SHARED support Loading cursor images\n");\r
-\r
-  if (!(fuLoad & LR_LOADFROMFILE))\r
-  {\r
-      if (hinst == NULL)\r
-         {\r
-           hinst = GetModuleHandleW(L"USER32");\r
-         }\r
-      hResource = FindResourceW(hinst, lpszName, RT_GROUP_CURSOR);\r
-      if (hResource == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-\r
-      hResource = LoadResource(hinst, hResource);\r
-      if (hResource == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-      IconResDir = LockResource(hResource);\r
-      if (IconResDir == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-\r
-      //find the best fitting in the IconResDir for this resolution\r
-      id = LookupIconIdFromDirectoryEx((PBYTE) IconResDir, TRUE,\r
-                32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));\r
-\r
-         h2Resource = FindResourceW(hinst,\r
-                     MAKEINTRESOURCEW(id),\r
-                     MAKEINTRESOURCEW(RT_CURSOR));\r
-\r
-      hResource = LoadResource(hinst, h2Resource);\r
-      if (hResource == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-\r
-      ResIcon = LockResource(hResource);\r
-      if (ResIcon == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-      return CreateIconFromResourceEx((PBYTE) ResIcon,\r
-                  SizeofResource(hinst, h2Resource), FALSE, 0x00030000,\r
-                  32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));\r
-  }\r
-  else\r
-  {\r
-      hFile = CreateFileW(lpszName,\r
-                        GENERIC_READ,\r
-                        FILE_SHARE_READ,\r
-                        NULL,\r
-                        OPEN_EXISTING,\r
-                        0,\r
-                        NULL);\r
-      if (hFile == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-\r
-      hSection = CreateFileMappingW(hFile,\r
-                                  NULL,\r
-                                  PAGE_READONLY,\r
-                                  0,\r
-                                  0,\r
-                                  NULL);\r
-\r
-      CloseHandle(hFile);\r
-      if (hSection == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-      IconDIR = MapViewOfFile(hSection,\r
-                                FILE_MAP_READ,\r
-                                0,\r
-                                0,\r
-                                0);\r
-\r
-      CloseHandle(hSection);\r
-      if (IconDIR == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-\r
-      //pick the best size.\r
-      dirEntry = (CURSORICONDIRENTRY *)  CURSORICON_FindBestIcon( IconDIR, 32, 32, 1);\r
-\r
-\r
-      if (!dirEntry)\r
-         {\r
-         if (fuLoad & LR_LOADFROMFILE)\r
-                {\r
-              UnmapViewOfFile(IconDIR);\r
-                }\r
-         return(NULL);\r
-         }\r
-\r
-      SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, dirEntry->dwBytesInRes); \r
-\r
-      memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);\r
-  }\r
-\r
-  //at this point we have a copy of the icon image to play with\r
-\r
-  SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;\r
-\r
-  if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))\r
-    {\r
-      BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;\r
-      ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;\r
-      HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);\r
-    }\r
-  else\r
-    {\r
-      ColourCount = SafeIconImage->icHeader.biClrUsed;\r
-      if (ColourCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)\r
-       {\r
-         ColourCount = 1 << SafeIconImage->icHeader.biBitCount;\r
-       }\r
-      HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);\r
-    }\r
-  \r
-  //make data point to the start of the XOR image data\r
-  Data = (PBYTE)SafeIconImage + HeaderSize;\r
-\r
-\r
-  //get a handle to the screen dc, the icon we create is going to be compatable with this\r
-  hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);\r
-  if (hScreenDc == NULL)\r
-  {\r
-      if (fuLoad & LR_LOADFROMFILE)\r
-         {\r
-               RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);\r
-        UnmapViewOfFile(IconDIR);\r
-         }\r
-      return(NULL);\r
-  }\r
-\r
-  hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot);\r
-  RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);\r
-  return hIcon;\r
-}\r
-\r
-\r
-HANDLE STATIC\r
-LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuLoad)\r
-{\r
-  HANDLE hResource;\r
-  HANDLE h2Resource;\r
-  HANDLE hFile;\r
-  HANDLE hSection;\r
-  CURSORICONDIR* IconDIR;\r
-  HDC hScreenDc;\r
-  HANDLE hIcon;\r
-  ULONG HeaderSize;\r
-  ULONG ColourCount;\r
-  PVOID Data;\r
-  CURSORICONDIRENTRY* dirEntry;\r
-  ICONIMAGE* SafeIconImage;\r
-  GRPCURSORICONDIR* IconResDir;\r
-  INT id;\r
-  ICONIMAGE *ResIcon;\r
-\r
-  if (fuLoad & LR_SHARED)\r
-    DbgPrint("FIXME: need LR_SHARED support Loading icon images\n");\r
-\r
-  if (!(fuLoad & LR_LOADFROMFILE))\r
-  {\r
-      if (hinst == NULL)\r
-         {\r
-           hinst = GetModuleHandleW(L"USER32");\r
-         }\r
-      hResource = FindResourceW(hinst, lpszName, RT_GROUP_ICON);\r
-      if (hResource == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-\r
-      hResource = LoadResource(hinst, hResource);\r
-      if (hResource == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-      IconResDir = LockResource(hResource);\r
-      if (IconResDir == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-\r
-      //find the best fitting in the IconResDir for this resolution\r
-      id = LookupIconIdFromDirectoryEx((PBYTE) IconResDir, TRUE,\r
-                width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));\r
-\r
-         h2Resource = FindResourceW(hinst,\r
-                     MAKEINTRESOURCEW(id),\r
-                     MAKEINTRESOURCEW(RT_ICON));\r
-\r
-      hResource = LoadResource(hinst, h2Resource);\r
-      if (hResource == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-\r
-      ResIcon = LockResource(hResource);\r
-      if (ResIcon == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-      return CreateIconFromResourceEx((PBYTE) ResIcon,\r
-                  SizeofResource(hinst, h2Resource), TRUE, 0x00030000,\r
-                  width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));\r
-  }\r
-  else\r
-  {\r
-      hFile = CreateFileW(lpszName,\r
-                        GENERIC_READ,\r
-                        FILE_SHARE_READ,\r
-                        NULL,\r
-                        OPEN_EXISTING,\r
-                        0,\r
-                        NULL);\r
-      if (hFile == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-\r
-      hSection = CreateFileMappingW(hFile,\r
-                                  NULL,\r
-                                  PAGE_READONLY,\r
-                                  0,\r
-                                  0,\r
-                                  NULL);\r
-\r
-      CloseHandle(hFile);\r
-      if (hSection == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-      IconDIR = MapViewOfFile(hSection,\r
-                                FILE_MAP_READ,\r
-                                0,\r
-                                0,\r
-                                0);\r
-\r
-      CloseHandle(hSection);\r
-      if (IconDIR == NULL)\r
-         {\r
-           return(NULL);\r
-         }\r
-\r
-      //pick the best size.\r
-      dirEntry = (CURSORICONDIRENTRY *)  CURSORICON_FindBestIcon( IconDIR, width, height, 1);\r
-\r
-\r
-      if (!dirEntry)\r
-         {\r
-         if (fuLoad & LR_LOADFROMFILE)\r
-                {\r
-              UnmapViewOfFile(IconDIR);\r
-                }\r
-         return(NULL);\r
-         }\r
-\r
-      SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, dirEntry->dwBytesInRes); \r
-\r
-      memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);\r
-  }\r
-\r
-  //at this point we have a copy of the icon image to play with\r
-\r
-  SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;\r
-\r
-  if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))\r
-    {\r
-      BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;\r
-      ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;\r
-      HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);\r
-    }\r
-  else\r
-    {\r
-      ColourCount = SafeIconImage->icHeader.biClrUsed;\r
-      if (ColourCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)\r
-       {\r
-         ColourCount = 1 << SafeIconImage->icHeader.biBitCount;\r
-       }\r
-      HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);\r
-    }\r
-  \r
-  //make data point to the start of the XOR image data\r
-  Data = (PBYTE)SafeIconImage + HeaderSize;\r
-\r
-\r
-  //get a handle to the screen dc, the icon we create is going to be compatable with this\r
-  hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);\r
-  if (hScreenDc == NULL)\r
-  {\r
-      if (fuLoad & LR_LOADFROMFILE)\r
-         {\r
-               RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);\r
-        UnmapViewOfFile(IconDIR);\r
-         }\r
-      return(NULL);\r
-  }\r
-\r
-  hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2);\r
-  RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);\r
-  return hIcon;\r
-}\r
-\r
-\r
-HANDLE STATIC\r
-LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)\r
-{\r
-  HANDLE hResource;\r
-  HANDLE hFile;\r
-  HANDLE hSection;\r
-  BITMAPINFO* BitmapInfo;\r
-  BITMAPINFO* PrivateInfo;\r
-  HDC hScreenDc;\r
-  HANDLE hBitmap;\r
-  ULONG HeaderSize;\r
-  ULONG ColourCount;\r
-  PVOID Data;\r
-\r
-  if (!(fuLoad & LR_LOADFROMFILE))\r
-    {\r
-      if (hInstance == NULL)\r
-       {\r
-         hInstance = GetModuleHandleW(L"USER32");\r
-       }\r
-      hResource = FindResourceW(hInstance, lpszName, RT_BITMAP);\r
-      if (hResource == NULL)\r
-       {\r
-         return(NULL);\r
-       }\r
-      hResource = LoadResource(hInstance, hResource);\r
-      if (hResource == NULL)\r
-       {\r
-         return(NULL);\r
-       }\r
-      BitmapInfo = LockResource(hResource);\r
-      if (BitmapInfo == NULL)\r
-       {\r
-         return(NULL);\r
-       }\r
-    }\r
-  else\r
-    {\r
-      hFile = CreateFileW(lpszName,\r
-                        GENERIC_READ,\r
-                        FILE_SHARE_READ,\r
-                        NULL,\r
-                        OPEN_EXISTING,\r
-                        0,\r
-                        NULL);\r
-      if (hFile == NULL)\r
-       {\r
-         return(NULL);\r
-       }\r
-      hSection = CreateFileMappingW(hFile,\r
-                                  NULL,\r
-                                  PAGE_READONLY,\r
-                                  0,\r
-                                  0,\r
-                                  NULL);\r
-      CloseHandle(hFile);\r
-      if (hSection == NULL)\r
-       {               \r
-         return(NULL);\r
-       }\r
-      BitmapInfo = MapViewOfFile(hSection,\r
-                                FILE_MAP_READ,\r
-                                0,\r
-                                0,\r
-                                0);\r
-      CloseHandle(hSection);\r
-      if (BitmapInfo == NULL)\r
-       {\r
-         return(NULL);\r
-       }\r
-       /* offset BitmapInfo by 14 bytes to acount for the size of BITMAPFILEHEADER\r
-          unfortunatly sizeof(BITMAPFILEHEADER) = 16, but the acutal size should be 14!\r
-       */\r
-       BitmapInfo = (BITMAPINFO*)(((PBYTE)BitmapInfo) + 14);\r
-    }\r
-\r
-  if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))\r
-    {\r
-      BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)BitmapInfo;\r
-      ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;\r
-      HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);\r
-    }\r
-  else\r
-    {\r
-      ColourCount = BitmapInfo->bmiHeader.biClrUsed;\r
-      if (ColourCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8)\r
-       {\r
-         ColourCount = 1 << BitmapInfo->bmiHeader.biBitCount;\r
-       }\r
-      HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);\r
-    }\r
-  Data = (PVOID)BitmapInfo + HeaderSize;\r
-\r
-  PrivateInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, HeaderSize);\r
-  if (PrivateInfo == NULL)\r
-    {\r
-      if (fuLoad & LR_LOADFROMFILE)\r
-       {\r
-         UnmapViewOfFile(BitmapInfo);\r
-       }\r
-      return(NULL);\r
-    }\r
-  memcpy(PrivateInfo, BitmapInfo, HeaderSize);\r
-\r
-  /* FIXME: Handle colour conversion and transparency. */\r
-\r
-  hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);\r
-  if (hScreenDc == NULL)\r
-    {\r
-      if (fuLoad & LR_LOADFROMFILE)\r
-       {\r
-         UnmapViewOfFile(BitmapInfo);\r
-       }\r
-      return(NULL);\r
-    }\r
-\r
-  if (fuLoad & LR_CREATEDIBSECTION)\r
-    {\r
-      DIBSECTION Dib;\r
-\r
-      hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL, \r
-                                0, 0);\r
-      GetObjectA(hBitmap, sizeof(DIBSECTION), &Dib);\r
-      SetDIBits(hScreenDc, hBitmap, 0, Dib.dsBm.bmHeight, Data, BitmapInfo,\r
-               DIB_RGB_COLORS);\r
-    }\r
-  else\r
-    {\r
-      hBitmap = CreateDIBitmap(hScreenDc, &PrivateInfo->bmiHeader, CBM_INIT,\r
-                              Data, PrivateInfo, DIB_RGB_COLORS);\r
-    }\r
-\r
-  RtlFreeHeap(RtlGetProcessHeap(), 0, PrivateInfo);\r
-  /*DeleteDC(hScreenDc);*/\r
-  if (fuLoad & LR_LOADFROMFILE)\r
-    {\r
-      UnmapViewOfFile(BitmapInfo);\r
-    }\r
-  return(hBitmap);\r
-}\r
-\r
-HANDLE STDCALL\r
-LoadImageW(HINSTANCE hinst,\r
-          LPCWSTR lpszName,\r
-          UINT uType,\r
-          int cxDesired,\r
-          int cyDesired,\r
-          UINT fuLoad)\r
-{  \r
-  if (fuLoad & LR_DEFAULTSIZE)\r
-    {\r
-      if (uType == IMAGE_ICON)\r
-       {\r
-         if (cxDesired == 0)\r
-           {\r
-             cxDesired = GetSystemMetrics(SM_CXICON);\r
-           }\r
-         if (cyDesired == 0)\r
-           {\r
-             cyDesired = GetSystemMetrics(SM_CYICON);\r
-           }\r
-       }\r
-      else if (uType == IMAGE_CURSOR)\r
-       {\r
-         if (cxDesired == 0)\r
-           {\r
-             cxDesired = GetSystemMetrics(SM_CXCURSOR);\r
-           }\r
-         if (cyDesired == 0)\r
-           {\r
-             cyDesired = GetSystemMetrics(SM_CYCURSOR);\r
-           }\r
-       }\r
-    }\r
-\r
-  switch (uType)\r
-    {\r
-    case IMAGE_BITMAP:\r
-      {\r
-       return(LoadBitmapImage(hinst, lpszName, fuLoad));\r
-      }\r
-    case IMAGE_CURSOR:\r
-      {\r
-       return(LoadCursorImage(hinst, lpszName, fuLoad));\r
-      }\r
-    case IMAGE_ICON:\r
-      {\r
-       return(LoadIconImage(hinst, lpszName, cxDesired, cyDesired, fuLoad));\r
-      }\r
-    default:\r
-      DbgBreakPoint();\r
-      break;\r
-    }\r
-  return(NULL);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-HBITMAP STDCALL\r
-LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName)\r
-{\r
-  return(LoadImageA(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0));\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-HBITMAP STDCALL\r
-LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName)\r
-{\r
-  return(LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0));\r
-}\r
+/*
+ *  ReactOS kernel
+ *  Copyright (C) 1998, 1999, 2000, 2001 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: bitmap.c,v 1.17 2003/10/06 18:49:49 navaraf Exp $
+ *
+ * PROJECT:         ReactOS user32.dll
+ * FILE:            lib/user32/windows/input.c
+ * PURPOSE:         Input
+ * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * UPDATE HISTORY:
+ *      09-05-2001  CSH  Created
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <string.h>
+#include <windows.h>
+#include <user32.h>
+#include <debug.h>
+#include <stdlib.h>
+
+/*forward declerations... actualy in user32\windows\icon.c but usful here****/
+HICON ICON_CreateIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot);
+CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors);
+CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors);
+
+
+/* FUNCTIONS *****************************************************************/
+
+/*
+ * @implemented
+ */
+HANDLE STDCALL
+LoadImageA(HINSTANCE hinst,
+          LPCSTR lpszName,
+          UINT uType,
+          int cxDesired,
+          int cyDesired,
+          UINT fuLoad)
+{
+  LPWSTR lpszWName;
+  HANDLE Handle;
+  UNICODE_STRING NameString;
+
+  if (HIWORD(lpszName))
+    {      
+      RtlCreateUnicodeStringFromAsciiz(&NameString, (LPSTR)lpszName);
+      lpszWName = NameString.Buffer;
+      Handle = LoadImageW(hinst, lpszWName, uType, cxDesired,
+                         cyDesired, fuLoad);
+      RtlFreeUnicodeString(&NameString);
+    }
+  else
+    {
+      Handle = LoadImageW(hinst, (LPCWSTR)lpszName, uType, cxDesired,
+                         cyDesired, fuLoad);
+    }
+  return(Handle);
+}
+
+
+HANDLE STATIC
+LoadCursorImage(HINSTANCE hinst, LPCWSTR lpszName, UINT fuLoad)
+{
+  HANDLE hResource;
+  HANDLE h2Resource;
+  HANDLE hFile;
+  HANDLE hSection;
+  CURSORICONDIR* IconDIR;
+  HDC hScreenDc;
+  HANDLE hIcon;
+  ULONG HeaderSize;
+  ULONG ColourCount;
+  PVOID Data;
+  CURSORICONDIRENTRY* dirEntry;
+  ICONIMAGE* SafeIconImage;
+  GRPCURSORICONDIR* IconResDir;
+  INT id;
+  ICONIMAGE *ResIcon;
+
+  if (fuLoad & LR_SHARED)
+    DbgPrint("FIXME: need LR_SHARED support Loading cursor images\n");
+
+  if (!(fuLoad & LR_LOADFROMFILE))
+  {
+      if (hinst == NULL)
+         {
+           hinst = GetModuleHandleW(L"USER32");
+         }
+      hResource = FindResourceW(hinst, lpszName, RT_GROUP_CURSOR);
+      if (hResource == NULL)
+         {
+           return(NULL);
+         }
+
+      hResource = LoadResource(hinst, hResource);
+      if (hResource == NULL)
+         {
+           return(NULL);
+         }
+      IconResDir = LockResource(hResource);
+      if (IconResDir == NULL)
+         {
+           return(NULL);
+         }
+
+      //find the best fitting in the IconResDir for this resolution
+      id = LookupIconIdFromDirectoryEx((PBYTE) IconResDir, TRUE,
+                32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+
+         h2Resource = FindResourceW(hinst,
+                     MAKEINTRESOURCEW(id),
+                     MAKEINTRESOURCEW(RT_CURSOR));
+
+      hResource = LoadResource(hinst, h2Resource);
+      if (hResource == NULL)
+         {
+           return(NULL);
+         }
+
+      ResIcon = LockResource(hResource);
+      if (ResIcon == NULL)
+         {
+           return(NULL);
+         }
+      return CreateIconFromResourceEx((PBYTE) ResIcon,
+                  SizeofResource(hinst, h2Resource), FALSE, 0x00030000,
+                  32, 32, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+  }
+  else
+  {
+      hFile = CreateFileW(lpszName,
+                        GENERIC_READ,
+                        FILE_SHARE_READ,
+                        NULL,
+                        OPEN_EXISTING,
+                        0,
+                        NULL);
+      if (hFile == NULL)
+         {
+           return(NULL);
+         }
+
+      hSection = CreateFileMappingW(hFile,
+                                  NULL,
+                                  PAGE_READONLY,
+                                  0,
+                                  0,
+                                  NULL);
+
+      CloseHandle(hFile);
+      if (hSection == NULL)
+         {
+           return(NULL);
+         }
+      IconDIR = MapViewOfFile(hSection,
+                                FILE_MAP_READ,
+                                0,
+                                0,
+                                0);
+
+      CloseHandle(hSection);
+      if (IconDIR == NULL)
+         {
+           return(NULL);
+         }
+
+      //pick the best size.
+      dirEntry = (CURSORICONDIRENTRY *)  CURSORICON_FindBestIcon( IconDIR, 32, 32, 1);
+
+
+      if (!dirEntry)
+         {
+         if (fuLoad & LR_LOADFROMFILE)
+                {
+              UnmapViewOfFile(IconDIR);
+                }
+         return(NULL);
+         }
+
+      SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, dirEntry->dwBytesInRes); 
+
+      memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
+  }
+
+  //at this point we have a copy of the icon image to play with
+
+  SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
+
+  if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
+    {
+      BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
+      ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
+      HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
+    }
+  else
+    {
+      ColourCount = SafeIconImage->icHeader.biClrUsed;
+      if (ColourCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
+       {
+         ColourCount = 1 << SafeIconImage->icHeader.biBitCount;
+       }
+      HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
+    }
+  
+  //make data point to the start of the XOR image data
+  Data = (PBYTE)SafeIconImage + HeaderSize;
+
+
+  //get a handle to the screen dc, the icon we create is going to be compatable with this
+  hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
+  if (hScreenDc == NULL)
+  {
+      if (fuLoad & LR_LOADFROMFILE)
+         {
+               RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+        UnmapViewOfFile(IconDIR);
+         }
+      return(NULL);
+  }
+
+  hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, 32, 32, dirEntry->Info.cursor.wXHotspot, dirEntry->Info.cursor.wYHotspot);
+  RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+  return hIcon;
+}
+
+
+HANDLE STATIC
+LoadIconImage(HINSTANCE hinst, LPCWSTR lpszName, INT width, INT height, UINT fuLoad)
+{
+  HANDLE hResource;
+  HANDLE h2Resource;
+  HANDLE hFile;
+  HANDLE hSection;
+  CURSORICONDIR* IconDIR;
+  HDC hScreenDc;
+  HANDLE hIcon;
+  ULONG HeaderSize;
+  ULONG ColourCount;
+  PVOID Data;
+  CURSORICONDIRENTRY* dirEntry;
+  ICONIMAGE* SafeIconImage;
+  GRPCURSORICONDIR* IconResDir;
+  INT id;
+  ICONIMAGE *ResIcon;
+
+  if (fuLoad & LR_SHARED)
+    DbgPrint("FIXME: need LR_SHARED support Loading icon images\n");
+
+  if (!(fuLoad & LR_LOADFROMFILE))
+  {
+      if (hinst == NULL)
+         {
+           hinst = GetModuleHandleW(L"USER32");
+         }
+      hResource = FindResourceW(hinst, lpszName, RT_GROUP_ICON);
+      if (hResource == NULL)
+         {
+           return(NULL);
+         }
+
+      hResource = LoadResource(hinst, hResource);
+      if (hResource == NULL)
+         {
+           return(NULL);
+         }
+      IconResDir = LockResource(hResource);
+      if (IconResDir == NULL)
+         {
+           return(NULL);
+         }
+
+      //find the best fitting in the IconResDir for this resolution
+      id = LookupIconIdFromDirectoryEx((PBYTE) IconResDir, TRUE,
+                width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+
+         h2Resource = FindResourceW(hinst,
+                     MAKEINTRESOURCEW(id),
+                     MAKEINTRESOURCEW(RT_ICON));
+
+      hResource = LoadResource(hinst, h2Resource);
+      if (hResource == NULL)
+         {
+           return(NULL);
+         }
+
+      ResIcon = LockResource(hResource);
+      if (ResIcon == NULL)
+         {
+           return(NULL);
+         }
+      return CreateIconFromResourceEx((PBYTE) ResIcon,
+                  SizeofResource(hinst, h2Resource), TRUE, 0x00030000,
+                  width, height, fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
+  }
+  else
+  {
+      hFile = CreateFileW(lpszName,
+                        GENERIC_READ,
+                        FILE_SHARE_READ,
+                        NULL,
+                        OPEN_EXISTING,
+                        0,
+                        NULL);
+      if (hFile == NULL)
+         {
+           return(NULL);
+         }
+
+      hSection = CreateFileMappingW(hFile,
+                                  NULL,
+                                  PAGE_READONLY,
+                                  0,
+                                  0,
+                                  NULL);
+
+      CloseHandle(hFile);
+      if (hSection == NULL)
+         {
+           return(NULL);
+         }
+      IconDIR = MapViewOfFile(hSection,
+                                FILE_MAP_READ,
+                                0,
+                                0,
+                                0);
+
+      CloseHandle(hSection);
+      if (IconDIR == NULL)
+         {
+           return(NULL);
+         }
+
+      //pick the best size.
+      dirEntry = (CURSORICONDIRENTRY *)  CURSORICON_FindBestIcon( IconDIR, width, height, 1);
+
+
+      if (!dirEntry)
+         {
+         if (fuLoad & LR_LOADFROMFILE)
+                {
+              UnmapViewOfFile(IconDIR);
+                }
+         return(NULL);
+         }
+
+      SafeIconImage = RtlAllocateHeap(RtlGetProcessHeap(), 0, dirEntry->dwBytesInRes); 
+
+      memcpy(SafeIconImage, ((PBYTE)IconDIR) + dirEntry->dwImageOffset, dirEntry->dwBytesInRes);
+  }
+
+  //at this point we have a copy of the icon image to play with
+
+  SafeIconImage->icHeader.biHeight = SafeIconImage->icHeader.biHeight /2;
+
+  if (SafeIconImage->icHeader.biSize == sizeof(BITMAPCOREHEADER))
+    {
+      BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)SafeIconImage;
+      ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
+      HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
+    }
+  else
+    {
+      ColourCount = SafeIconImage->icHeader.biClrUsed;
+      if (ColourCount == 0 && SafeIconImage->icHeader.biBitCount <= 8)
+       {
+         ColourCount = 1 << SafeIconImage->icHeader.biBitCount;
+       }
+      HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
+    }
+  
+  //make data point to the start of the XOR image data
+  Data = (PBYTE)SafeIconImage + HeaderSize;
+
+
+  //get a handle to the screen dc, the icon we create is going to be compatable with this
+  hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
+  if (hScreenDc == NULL)
+  {
+      if (fuLoad & LR_LOADFROMFILE)
+         {
+               RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+        UnmapViewOfFile(IconDIR);
+         }
+      return(NULL);
+  }
+
+  hIcon = ICON_CreateIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2);
+  RtlFreeHeap(RtlGetProcessHeap(), 0, SafeIconImage);
+  return hIcon;
+}
+
+
+HANDLE STATIC
+LoadBitmapImage(HINSTANCE hInstance, LPCWSTR lpszName, UINT fuLoad)
+{
+  HANDLE hResource;
+  HANDLE hFile;
+  HANDLE hSection;
+  BITMAPINFO* BitmapInfo;
+  BITMAPINFO* PrivateInfo;
+  HDC hScreenDc;
+  HANDLE hBitmap;
+  ULONG HeaderSize;
+  ULONG ColourCount;
+  PVOID Data;
+
+  if (!(fuLoad & LR_LOADFROMFILE))
+    {
+      if (hInstance == NULL)
+       {
+         hInstance = GetModuleHandleW(L"USER32");
+       }
+      hResource = FindResourceW(hInstance, lpszName, RT_BITMAP);
+      if (hResource == NULL)
+       {
+         return(NULL);
+       }
+      hResource = LoadResource(hInstance, hResource);
+      if (hResource == NULL)
+       {
+         return(NULL);
+       }
+      BitmapInfo = LockResource(hResource);
+      if (BitmapInfo == NULL)
+       {
+         return(NULL);
+       }
+    }
+  else
+    {
+      hFile = CreateFileW(lpszName,
+                        GENERIC_READ,
+                        FILE_SHARE_READ,
+                        NULL,
+                        OPEN_EXISTING,
+                        0,
+                        NULL);
+      if (hFile == NULL)
+       {
+         return(NULL);
+       }
+      hSection = CreateFileMappingW(hFile,
+                                  NULL,
+                                  PAGE_READONLY,
+                                  0,
+                                  0,
+                                  NULL);
+      CloseHandle(hFile);
+      if (hSection == NULL)
+       {               
+         return(NULL);
+       }
+      BitmapInfo = MapViewOfFile(hSection,
+                                FILE_MAP_READ,
+                                0,
+                                0,
+                                0);
+      CloseHandle(hSection);
+      if (BitmapInfo == NULL)
+       {
+         return(NULL);
+       }
+       /* offset BitmapInfo by 14 bytes to acount for the size of BITMAPFILEHEADER
+          unfortunatly sizeof(BITMAPFILEHEADER) = 16, but the acutal size should be 14!
+       */
+       BitmapInfo = (BITMAPINFO*)(((PBYTE)BitmapInfo) + 14);
+    }
+
+  if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+    {
+      BITMAPCOREHEADER* Core = (BITMAPCOREHEADER*)BitmapInfo;
+      ColourCount = (Core->bcBitCount <= 8) ? (1 << Core->bcBitCount) : 0;
+      HeaderSize = sizeof(BITMAPCOREHEADER) + ColourCount * sizeof(RGBTRIPLE);
+    }
+  else
+    {
+      ColourCount = BitmapInfo->bmiHeader.biClrUsed;
+      if (ColourCount == 0 && BitmapInfo->bmiHeader.biBitCount <= 8)
+       {
+         ColourCount = 1 << BitmapInfo->bmiHeader.biBitCount;
+       }
+      HeaderSize = sizeof(BITMAPINFOHEADER) + ColourCount * sizeof(RGBQUAD);
+    }
+  Data = (PVOID)BitmapInfo + HeaderSize;
+
+  PrivateInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, HeaderSize);
+  if (PrivateInfo == NULL)
+    {
+      if (fuLoad & LR_LOADFROMFILE)
+       {
+         UnmapViewOfFile(BitmapInfo);
+       }
+      return(NULL);
+    }
+  memcpy(PrivateInfo, BitmapInfo, HeaderSize);
+
+  /* FIXME: Handle colour conversion and transparency. */
+
+  hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL);
+  if (hScreenDc == NULL)
+    {
+      if (fuLoad & LR_LOADFROMFILE)
+       {
+         UnmapViewOfFile(BitmapInfo);
+       }
+      return(NULL);
+    }
+
+  if (fuLoad & LR_CREATEDIBSECTION)
+    {
+      DIBSECTION Dib;
+
+      hBitmap = CreateDIBSection(hScreenDc, PrivateInfo, DIB_RGB_COLORS, NULL, 
+                                0, 0);
+      GetObjectA(hBitmap, sizeof(DIBSECTION), &Dib);
+      SetDIBits(hScreenDc, hBitmap, 0, Dib.dsBm.bmHeight, Data, BitmapInfo,
+               DIB_RGB_COLORS);
+    }
+  else
+    {
+      hBitmap = CreateDIBitmap(hScreenDc, &PrivateInfo->bmiHeader, CBM_INIT,
+                              Data, PrivateInfo, DIB_RGB_COLORS);
+    }
+
+  RtlFreeHeap(RtlGetProcessHeap(), 0, PrivateInfo);
+  /*DeleteDC(hScreenDc);*/
+  if (fuLoad & LR_LOADFROMFILE)
+    {
+      UnmapViewOfFile(BitmapInfo);
+    }
+  return(hBitmap);
+}
+
+HANDLE STDCALL
+LoadImageW(HINSTANCE hinst,
+          LPCWSTR lpszName,
+          UINT uType,
+          int cxDesired,
+          int cyDesired,
+          UINT fuLoad)
+{  
+  if (fuLoad & LR_DEFAULTSIZE)
+    {
+      if (uType == IMAGE_ICON)
+       {
+         if (cxDesired == 0)
+           {
+             cxDesired = GetSystemMetrics(SM_CXICON);
+           }
+         if (cyDesired == 0)
+           {
+             cyDesired = GetSystemMetrics(SM_CYICON);
+           }
+       }
+      else if (uType == IMAGE_CURSOR)
+       {
+         if (cxDesired == 0)
+           {
+             cxDesired = GetSystemMetrics(SM_CXCURSOR);
+           }
+         if (cyDesired == 0)
+           {
+             cyDesired = GetSystemMetrics(SM_CYCURSOR);
+           }
+       }
+    }
+
+  switch (uType)
+    {
+    case IMAGE_BITMAP:
+      {
+       return(LoadBitmapImage(hinst, lpszName, fuLoad));
+      }
+    case IMAGE_CURSOR:
+      {
+       return(LoadCursorImage(hinst, lpszName, fuLoad));
+      }
+    case IMAGE_ICON:
+      {
+       return(LoadIconImage(hinst, lpszName, cxDesired, cyDesired, fuLoad));
+      }
+    default:
+      DbgBreakPoint();
+      break;
+    }
+  return(NULL);
+}
+
+
+/*
+ * @implemented
+ */
+HBITMAP STDCALL
+LoadBitmapA(HINSTANCE hInstance, LPCSTR lpBitmapName)
+{
+  return(LoadImageA(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0));
+}
+
+
+/*
+ * @implemented
+ */
+HBITMAP STDCALL
+LoadBitmapW(HINSTANCE hInstance, LPCWSTR lpBitmapName)
+{
+  return(LoadImageW(hInstance, lpBitmapName, IMAGE_BITMAP, 0, 0, 0));
+}
index 4b97ba2..1ba1220 100644 (file)
-/*\r
- * COPYRIGHT:        See COPYING in the top level directory\r
- * PROJECT:          ReactOS kernel\r
- * FILE:             ntoskrnl/cm/rtlfunc.c\r
- * PURPOSE:          Rtlxxx function for registry access\r
- * UPDATE HISTORY:\r
-*/\r
-\r
-/* INCLUDES *****************************************************************/\r
-\r
-#include <ddk/ntddk.h>\r
-#include <roscfg.h>\r
-#include <internal/ob.h>\r
-#include <limits.h>\r
-#include <string.h>\r
-#include <internal/registry.h>\r
-\r
-#define NDEBUG\r
-#include <internal/debug.h>\r
-\r
-#include "cm.h"\r
-\r
-\r
-/* FUNCTIONS ****************************************************************/\r
-\r
-/*\r
- * @implemented\r
- */\r
-NTSTATUS STDCALL\r
-RtlCheckRegistryKey(IN ULONG RelativeTo,\r
-                   IN PWSTR Path)\r
-{\r
-  HANDLE KeyHandle;\r
-  NTSTATUS Status;\r
-\r
-  Status = RtlpGetRegistryHandle(RelativeTo,\r
-                                Path,\r
-                                FALSE,\r
-                                &KeyHandle);\r
-  if (!NT_SUCCESS(Status))\r
-    return(Status);\r
-\r
-  NtClose(KeyHandle);\r
-\r
-  return(STATUS_SUCCESS);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-NTSTATUS STDCALL\r
-RtlCreateRegistryKey(IN ULONG RelativeTo,\r
-                    IN PWSTR Path)\r
-{\r
-  HANDLE KeyHandle;\r
-  NTSTATUS Status;\r
-\r
-  Status = RtlpGetRegistryHandle(RelativeTo,\r
-                                Path,\r
-                                TRUE,\r
-                                &KeyHandle);\r
-  if (!NT_SUCCESS(Status))\r
-    return(Status);\r
-\r
-  NtClose(KeyHandle);\r
-\r
-  return(STATUS_SUCCESS);\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-NTSTATUS STDCALL\r
-RtlDeleteRegistryValue(IN ULONG RelativeTo,\r
-                      IN PCWSTR Path,\r
-                      IN PCWSTR ValueName)\r
-{\r
-  HANDLE KeyHandle;\r
-  NTSTATUS Status;\r
-  UNICODE_STRING Name;\r
-\r
-  Status = RtlpGetRegistryHandle(RelativeTo,\r
-                                (PWSTR) Path,\r
-                                TRUE,\r
-                                &KeyHandle);\r
-  if (!NT_SUCCESS(Status))\r
-    return(Status);\r
-\r
-  RtlInitUnicodeString(&Name,\r
-                      ValueName);\r
-\r
-  NtDeleteValueKey(KeyHandle,\r
-                  &Name);\r
-\r
-  NtClose(KeyHandle);\r
-\r
-  return(STATUS_SUCCESS);\r
-}\r
-\r
-\r
-NTSTATUS STDCALL\r
-RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess,\r
-                  OUT PHANDLE KeyHandle)\r
-{\r
-  OBJECT_ATTRIBUTES ObjectAttributes;\r
-  UNICODE_STRING KeyPath = UNICODE_STRING_INITIALIZER(L"\\Registry\\User\\.Default");\r
-  NTSTATUS Status;\r
-\r
-  Status = RtlFormatCurrentUserKeyPath(&KeyPath);\r
-  if (NT_SUCCESS(Status))\r
-    {\r
-      InitializeObjectAttributes(&ObjectAttributes,\r
-                                &KeyPath,\r
-                                OBJ_CASE_INSENSITIVE,\r
-                                NULL,\r
-                                NULL);\r
-      Status = NtOpenKey(KeyHandle,\r
-                        DesiredAccess,\r
-                        &ObjectAttributes);\r
-      RtlFreeUnicodeString(&KeyPath);\r
-      if (NT_SUCCESS(Status))\r
-       return(STATUS_SUCCESS);\r
-    }\r
-\r
-  InitializeObjectAttributes(&ObjectAttributes,\r
-                            &KeyPath,\r
-                            OBJ_CASE_INSENSITIVE,\r
-                            NULL,\r
-                            NULL);\r
-  Status = NtOpenKey(KeyHandle,\r
-                    DesiredAccess,\r
-                    &ObjectAttributes);\r
-  return(Status);\r
-}\r
-\r
-\r
-/*\r
- * @unimplemented\r
- */\r
-NTSTATUS STDCALL\r
-RtlQueryRegistryValues(IN ULONG RelativeTo,\r
-                      IN PCWSTR Path,\r
-                      IN PRTL_QUERY_REGISTRY_TABLE QueryTable,\r
-                      IN PVOID Context,\r
-                      IN PVOID Environment)\r
-{\r
-  NTSTATUS Status;\r
-  HANDLE BaseKeyHandle;\r
-  HANDLE CurrentKeyHandle;\r
-  PRTL_QUERY_REGISTRY_TABLE QueryEntry;\r
-  OBJECT_ATTRIBUTES ObjectAttributes;\r
-  UNICODE_STRING KeyName;\r
-  PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;\r
-  PKEY_VALUE_FULL_INFORMATION FullValueInfo;\r
-  ULONG BufferSize;\r
-  ULONG ResultSize;\r
-  ULONG ValueNameSize;\r
-  ULONG Index;\r
-  ULONG StringLen;\r
-  PWSTR StringPtr;\r
-  PWSTR ValueName;\r
-\r
-  DPRINT("RtlQueryRegistryValues() called\n");\r
-\r
-  Status = RtlpGetRegistryHandle(RelativeTo,\r
-                                (PWSTR) Path,\r
-                                FALSE,\r
-                                &BaseKeyHandle);\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      DPRINT("RtlpGetRegistryHandle() failed with status %x\n", Status);\r
-      return(Status);\r
-    }\r
-\r
-  CurrentKeyHandle = BaseKeyHandle;\r
-  QueryEntry = QueryTable;\r
-  while ((QueryEntry->QueryRoutine != NULL) ||\r
-        (QueryEntry->Name != NULL))\r
-    {\r
-      if (((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) != 0) &&\r
-         (BaseKeyHandle != CurrentKeyHandle))\r
-       {\r
-         NtClose(CurrentKeyHandle);\r
-         CurrentKeyHandle = BaseKeyHandle;\r
-       }\r
-\r
-      if (QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY)\r
-       {\r
-         DPRINT("Open new subkey: %S\n", QueryEntry->Name);\r
-\r
-         RtlInitUnicodeString(&KeyName,\r
-                              QueryEntry->Name);\r
-         InitializeObjectAttributes(&ObjectAttributes,\r
-                                    &KeyName,\r
-                                    OBJ_CASE_INSENSITIVE,\r
-                                    BaseKeyHandle,\r
-                                    NULL);\r
-         Status = NtOpenKey(&CurrentKeyHandle,\r
-                            KEY_ALL_ACCESS,\r
-                            &ObjectAttributes);\r
-         if (!NT_SUCCESS(Status))\r
-           break;\r
-       }\r
-      else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DIRECT)\r
-       {\r
-         DPRINT("Query value directly: %S\n", QueryEntry->Name);\r
-\r
-         RtlInitUnicodeString(&KeyName,\r
-                              QueryEntry->Name);\r
-\r
-         BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;\r
-         ValueInfo = ExAllocatePool(PagedPool, BufferSize);\r
-         if (ValueInfo == NULL)\r
-           {\r
-             Status = STATUS_NO_MEMORY;\r
-             break;\r
-           }\r
-\r
-         Status = ZwQueryValueKey(CurrentKeyHandle,\r
-                                  &KeyName,\r
-                                  KeyValuePartialInformation,\r
-                                  ValueInfo,\r
-                                  BufferSize,\r
-                                  &ResultSize);\r
-         if (!NT_SUCCESS(Status))\r
-           {\r
-             if (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED)\r
-               {\r
-                 ExFreePool(ValueInfo);\r
-                 Status = STATUS_OBJECT_NAME_NOT_FOUND;\r
-                 goto ByeBye;\r
-               }\r
-       \r
-             if (QueryEntry->DefaultType == REG_SZ)\r
-               {\r
-                 PUNICODE_STRING ValueString;\r
-                 PUNICODE_STRING SourceString;\r
-\r
-                 SourceString = (PUNICODE_STRING)QueryEntry->DefaultData;\r
-                 ValueString = (PUNICODE_STRING)QueryEntry->EntryContext;\r
-                 if (ValueString->Buffer == 0)\r
-                   {\r
-                     ValueString->Length = SourceString->Length;\r
-                     ValueString->MaximumLength = SourceString->MaximumLength;\r
-                     ValueString->Buffer = ExAllocatePool(PagedPool,\r
-                                                          ValueString->MaximumLength);\r
-                     if (!ValueString->Buffer)\r
-                       break;\r
-                     ValueString->Buffer[0] = 0;\r
-                     memcpy(ValueString->Buffer,\r
-                            SourceString->Buffer,\r
-                            SourceString->MaximumLength);\r
-                   }\r
-                 else\r
-                   {\r
-                     ValueString->Length = RtlMin(SourceString->Length,\r
-                                                  ValueString->MaximumLength - sizeof(WCHAR));\r
-                     memcpy(ValueString->Buffer,\r
-                            SourceString->Buffer,\r
-                            ValueString->Length);\r
-                     ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0;\r
-                   }\r
-               }\r
-             else\r
-               {\r
-                 memcpy(QueryEntry->EntryContext,\r
-                        QueryEntry->DefaultData,\r
-                        QueryEntry->DefaultLength);\r
-               }\r
-             Status = STATUS_SUCCESS;\r
-           }\r
-         else\r
-           {\r
-             if (ValueInfo->Type == REG_SZ ||\r
-                 ValueInfo->Type == REG_MULTI_SZ ||\r
-                 ValueInfo->Type == REG_EXPAND_SZ)\r
-               {\r
-                 PUNICODE_STRING ValueString;\r
-\r
-                 ValueString = (PUNICODE_STRING)QueryEntry->EntryContext;\r
-                 if (ValueString->Buffer == 0)\r
-                   {\r
-                     RtlInitUnicodeString(ValueString,\r
-                                          NULL);\r
-                     ValueString->MaximumLength = ValueInfo->DataLength;\r
-                     ValueString->Buffer = ExAllocatePool(PagedPool,\r
-                                                          ValueString->MaximumLength);\r
-                     if (!ValueString->Buffer)\r
-                       break;\r
-                     ValueString->Buffer[0] = 0;\r
-                   }\r
-                 ValueString->Length = RtlMin(ValueInfo->DataLength,\r
-                                              ValueString->MaximumLength) - sizeof(WCHAR);\r
-                 memcpy(ValueString->Buffer,\r
-                        ValueInfo->Data,\r
-                        ValueString->Length);\r
-                 ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0;\r
-               }\r
-             else\r
-               {\r
-                 memcpy(QueryEntry->EntryContext,\r
-                        ValueInfo->Data,\r
-                        ValueInfo->DataLength);\r
-               }\r
-           }\r
-\r
-         if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE)\r
-           {\r
-             DPRINT("FIXME: Delete value: %S\n", QueryEntry->Name);\r
-\r
-           }\r
-\r
-         ExFreePool(ValueInfo);\r
-       }\r
-      else\r
-       {\r
-         DPRINT("Query value via query routine: %S\n", QueryEntry->Name);\r
-\r
-         if (QueryEntry->Name != NULL)\r
-           {\r
-             DPRINT("Callback\n");\r
-\r
-             RtlInitUnicodeString(&KeyName,\r
-                                  QueryEntry->Name);\r
-\r
-             BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;\r
-             ValueInfo = ExAllocatePool(PagedPool,\r
-                                        BufferSize);\r
-             if (ValueInfo == NULL)\r
-               {\r
-                 Status = STATUS_NO_MEMORY;\r
-                 break;\r
-               }\r
-\r
-             Status = NtQueryValueKey(CurrentKeyHandle,\r
-                                      &KeyName,\r
-                                      KeyValuePartialInformation,\r
-                                      ValueInfo,\r
-                                      BufferSize,\r
-                                      &ResultSize);\r
-             if (!NT_SUCCESS(Status))\r
-               {\r
-                 Status = QueryEntry->QueryRoutine(QueryEntry->Name,\r
-                                                   QueryEntry->DefaultType,\r
-                                                   QueryEntry->DefaultData,\r
-                                                   QueryEntry->DefaultLength,\r
-                                                   Context,\r
-                                                   QueryEntry->EntryContext);\r
-               }\r
-             else if ((ValueInfo->Type == REG_MULTI_SZ) &&\r
-                      !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND))\r
-               {\r
-                 DPRINT("Expand REG_MULTI_SZ type\n");\r
-                 StringPtr = (PWSTR)ValueInfo->Data;\r
-                 while (*StringPtr != 0)\r
-                   {\r
-                     StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR);\r
-                     Status = QueryEntry->QueryRoutine(QueryEntry->Name,\r
-                                                       REG_SZ,\r
-                                                       (PVOID)StringPtr,\r
-                                                       StringLen,\r
-                                                       Context,\r
-                                                       QueryEntry->EntryContext);\r
-                     if(!NT_SUCCESS(Status))\r
-                       break;\r
-                     StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen);\r
-                   }\r
-               }\r
-             else\r
-               {\r
-                 Status = QueryEntry->QueryRoutine(QueryEntry->Name,\r
-                                                   ValueInfo->Type,\r
-                                                   ValueInfo->Data,\r
-                                                   ValueInfo->DataLength,\r
-                                                   Context,\r
-                                                   QueryEntry->EntryContext);\r
-               }\r
-\r
-             if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE)\r
-               {\r
-                 DPRINT("FIXME: Delete value: %S\n", QueryEntry->Name);\r
-\r
-               }\r
-\r
-             ExFreePool(ValueInfo);\r
-\r
-             if (!NT_SUCCESS(Status))\r
-               break;\r
-           }\r
-         else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_NOVALUE)\r
-           {\r
-             DPRINT("Simple callback\n");\r
-             Status = QueryEntry->QueryRoutine(NULL,\r
-                                               REG_NONE,\r
-                                               NULL,\r
-                                               0,\r
-                                               Context,\r
-                                               QueryEntry->EntryContext);\r
-             if (!NT_SUCCESS(Status))\r
-               break;\r
-           }\r
-         else\r
-           {\r
-             DPRINT("Enumerate values\n");\r
-\r
-             BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + 4096;\r
-             FullValueInfo = ExAllocatePool(PagedPool,\r
-                                            BufferSize);\r
-             if (FullValueInfo == NULL)\r
-               {\r
-                 Status = STATUS_NO_MEMORY;\r
-                 break;\r
-               }\r
-              ValueNameSize = 256 * sizeof(WCHAR);\r
-             ValueName = ExAllocatePool(PagedPool,\r
-                                        ValueNameSize);\r
-             if (ValueName == NULL)\r
-               {\r
-                 Status = STATUS_NO_MEMORY;\r
-                 break;\r
-               }\r
-             Index = 0;\r
-             while (TRUE)\r
-               {\r
-                 Status = NtEnumerateValueKey(CurrentKeyHandle,\r
-                                              Index,\r
-                                              KeyValueFullInformation,\r
-                                              FullValueInfo,\r
-                                              BufferSize,\r
-                                              &ResultSize);\r
-                 if (!NT_SUCCESS(Status))\r
-                   {\r
-                     if ((Status == STATUS_NO_MORE_ENTRIES) &&\r
-                         (Index == 0) &&\r
-                         (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED))\r
-                       {\r
-                         Status = STATUS_OBJECT_NAME_NOT_FOUND;\r
-                       }\r
-                     else if (Status == STATUS_NO_MORE_ENTRIES)\r
-                       {\r
-                         Status = STATUS_SUCCESS;\r
-                       }\r
-                     break;\r
-                   }\r
-\r
-                  if (FullValueInfo->NameLength > ValueNameSize - sizeof(WCHAR))\r
-                   {\r
-                     /* Should not happen, because the name length is limited to 255 characters */\r
-                     ExFreePool(ValueName);\r
-                     ValueNameSize = FullValueInfo->NameLength + sizeof(WCHAR);\r
-                     ValueName = ExAllocatePool(PagedPool, ValueNameSize);\r
-                     if (ValueName == NULL)\r
-                       {\r
-                         Status = STATUS_NO_MEMORY;\r
-                         break;\r
-                       }\r
-                   }\r
-\r
-                 RtlCopyMemory(ValueName, \r
-                               FullValueInfo->Name,\r
-                               FullValueInfo->NameLength);\r
-                 ValueName[FullValueInfo->NameLength / sizeof(WCHAR)] = 0;\r
-\r
-                 if ((FullValueInfo->Type == REG_MULTI_SZ) &&\r
-                     !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND))\r
-                   {\r
-                     DPRINT("Expand REG_MULTI_SZ type\n");\r
-\r
-                     StringPtr = (PWSTR)((PVOID)FullValueInfo + FullValueInfo->DataOffset);\r
-                     while (*StringPtr != 0)\r
-                       {\r
-                         StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR);\r
-                         Status = QueryEntry->QueryRoutine(ValueName,\r
-                                                           REG_SZ,\r
-                                                           (PVOID)StringPtr,\r
-                                                           StringLen,\r
-                                                           Context,\r
-                                                           QueryEntry->EntryContext);\r
-                         if(!NT_SUCCESS(Status))\r
-                           break;\r
-                         StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen);\r
-                       }\r
-                   }\r
-                 else\r
-                   {\r
-                     Status = QueryEntry->QueryRoutine(ValueName,\r
-                                                       FullValueInfo->Type,\r
-                                                       (PVOID)FullValueInfo + FullValueInfo->DataOffset,\r
-                                                       FullValueInfo->DataLength,\r
-                                                       Context,\r
-                                                       QueryEntry->EntryContext);\r
-                   }\r
-\r
-                 if (!NT_SUCCESS(Status))\r
-                   break;\r
-\r
-                 /* FIXME: How will these be deleted? */\r
-\r
-                 Index++;\r
-               }\r
-\r
-             ExFreePool(FullValueInfo);\r
-             ExFreePool(ValueName);\r
-\r
-             if (!NT_SUCCESS(Status))\r
-               break;\r
-           }\r
-       }\r
-\r
-      QueryEntry++;\r
-    }\r
-\r
-ByeBye:\r
-\r
-  if (CurrentKeyHandle != BaseKeyHandle)\r
-    NtClose(CurrentKeyHandle);\r
-\r
-  NtClose(BaseKeyHandle);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/*\r
- * @implemented\r
- */\r
-NTSTATUS STDCALL\r
-RtlWriteRegistryValue(IN ULONG RelativeTo,\r
-                     IN PCWSTR Path,\r
-                     IN PCWSTR ValueName,\r
-                     IN ULONG ValueType,\r
-                     IN PVOID ValueData,\r
-                     IN ULONG ValueLength)\r
-{\r
-  HANDLE KeyHandle;\r
-  NTSTATUS Status;\r
-  UNICODE_STRING Name;\r
-\r
-  Status = RtlpGetRegistryHandle(RelativeTo,\r
-                                (PWSTR) Path,\r
-                                TRUE,\r
-                                &KeyHandle);\r
-  if (!NT_SUCCESS(Status))\r
-    return(Status);\r
-\r
-  RtlInitUnicodeString(&Name,\r
-                      ValueName);\r
-\r
-  NtSetValueKey(KeyHandle,\r
-               &Name,\r
-               0,\r
-               ValueType,\r
-               ValueData,\r
-               ValueLength);\r
-\r
-  NtClose(KeyHandle);\r
-\r
-  return(STATUS_SUCCESS);\r
-}\r
-\r
-\r
-/*\r
- * @unimplemented\r
- */\r
-NTSTATUS STDCALL\r
-RtlFormatCurrentUserKeyPath(IN OUT PUNICODE_STRING KeyPath)\r
-{\r
-  /* FIXME: !!! */\r
-  RtlCreateUnicodeString(KeyPath,\r
-                        L"\\Registry\\User\\.Default");\r
-\r
-  return(STATUS_SUCCESS);\r
-}\r
-\r
-/*  ------------------------------------------  Private Implementation  */\r
-\r
-\r
-NTSTATUS\r
-RtlpGetRegistryHandle(ULONG RelativeTo,\r
-                     PWSTR Path,\r
-                     BOOLEAN Create,\r
-                     PHANDLE KeyHandle)\r
-{\r
-  UNICODE_STRING KeyName;\r
-  WCHAR KeyBuffer[MAX_PATH];\r
-  OBJECT_ATTRIBUTES ObjectAttributes;\r
-  NTSTATUS Status;\r
-\r
-  if (RelativeTo & RTL_REGISTRY_HANDLE)\r
-    {\r
-      Status = NtDuplicateObject(NtCurrentProcess(),\r
-                                (HANDLE)Path,\r
-                                NtCurrentProcess(),\r
-                                KeyHandle,\r
-                                0,\r
-                                FALSE,\r
-                                DUPLICATE_SAME_ACCESS);\r
-      return(Status);\r
-    }\r
-\r
-  if (RelativeTo & RTL_REGISTRY_OPTIONAL)\r
-    RelativeTo &= ~RTL_REGISTRY_OPTIONAL;\r
-\r
-  if (RelativeTo >= RTL_REGISTRY_MAXIMUM)\r
-    return STATUS_INVALID_PARAMETER;\r
-\r
-  KeyName.Length = 0;\r
-  KeyName.MaximumLength = MAX_PATH;\r
-  KeyName.Buffer = KeyBuffer;\r
-  KeyBuffer[0] = 0;\r
-\r
-  switch (RelativeTo)\r
-    {\r
-      case RTL_REGISTRY_SERVICES:\r
-       RtlAppendUnicodeToString(&KeyName,\r
-                                L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");\r
-       break;\r
-\r
-      case RTL_REGISTRY_CONTROL:\r
-       RtlAppendUnicodeToString(&KeyName,\r
-                                L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\");\r
-       break;\r
-\r
-      case RTL_REGISTRY_WINDOWS_NT:\r
-       RtlAppendUnicodeToString(&KeyName,\r
-                                L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\");\r
-       break;\r
-\r
-      case RTL_REGISTRY_DEVICEMAP:\r
-       RtlAppendUnicodeToString(&KeyName,\r
-                                L"\\Registry\\Machine\\Hardware\\DeviceMap\\");\r
-       break;\r
-\r
-      case RTL_REGISTRY_USER:\r
-       Status = RtlFormatCurrentUserKeyPath(&KeyName);\r
-       if (!NT_SUCCESS(Status))\r
-         return(Status);\r
-       break;\r
-\r
-      /* ReactOS specific */\r
-      case RTL_REGISTRY_ENUM:\r
-       RtlAppendUnicodeToString(&KeyName,\r
-                                L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");\r
-       break;\r
-    }\r
-\r
-  if (Path[0] == L'\\' && RelativeTo != RTL_REGISTRY_ABSOLUTE)\r
-    {\r
-      Path++;\r
-    }\r
-  RtlAppendUnicodeToString(&KeyName,\r
-                          Path);\r
-\r
-  DPRINT("KeyName '%wZ'\n", &KeyName);\r
-\r
-  InitializeObjectAttributes(&ObjectAttributes,\r
-                            &KeyName,\r
-                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF,\r
-                            NULL,\r
-                            NULL);\r
-\r
-  if (Create == TRUE)\r
-    {\r
-      Status = NtCreateKey(KeyHandle,\r
-                          KEY_ALL_ACCESS,\r
-                          &ObjectAttributes,\r
-                          0,\r
-                          NULL,\r
-                          0,\r
-                          NULL);\r
-    }\r
-  else\r
-    {\r
-      Status = NtOpenKey(KeyHandle,\r
-                        KEY_ALL_ACCESS,\r
-                        &ObjectAttributes);\r
-    }\r
-\r
-  return(Status);\r
-}\r
-\r
-\r
-NTSTATUS\r
-RtlpCreateRegistryKeyPath(PWSTR Path)\r
-{\r
-  OBJECT_ATTRIBUTES ObjectAttributes;\r
-  WCHAR KeyBuffer[MAX_PATH];\r
-  UNICODE_STRING KeyName;\r
-  HANDLE KeyHandle;\r
-  NTSTATUS Status;\r
-  PWCHAR Current;\r
-  PWCHAR Next;\r
-\r
-  if (_wcsnicmp(Path, L"\\Registry\\", 10) != 0)\r
-    {\r
-      return STATUS_INVALID_PARAMETER;\r
-    }\r
-\r
-  wcsncpy (KeyBuffer, Path, MAX_PATH-1);\r
-  RtlInitUnicodeString (&KeyName, KeyBuffer);\r
-\r
-  /* Skip \\Registry\\ */\r
-  Current = KeyName.Buffer;\r
-  Current = wcschr (Current, '\\') + 1;\r
-  Current = wcschr (Current, '\\') + 1;\r
-\r
-  do\r
-   {\r
-      Next = wcschr (Current, '\\');\r
-      if (Next == NULL)\r
-       {\r
-         /* The end */\r
-       }\r
-      else\r
-       {\r
-         *Next = 0;\r
-       }\r
-\r
-      InitializeObjectAttributes (&ObjectAttributes,\r
-                                 &KeyName,\r
-                                 OBJ_CASE_INSENSITIVE,\r
-                                 NULL,\r
-                                 NULL);\r
-\r
-      DPRINT("Create '%S'\n", KeyName.Buffer);\r
-\r
-      Status = NtCreateKey (&KeyHandle,\r
-                           KEY_ALL_ACCESS,\r
-                           &ObjectAttributes,\r
-                           0,\r
-                           NULL,\r
-                           0,\r
-                           NULL);\r
-      if (!NT_SUCCESS (Status))\r
-       {\r
-         DPRINT ("NtCreateKey() failed with status %x\n", Status);\r
-         return Status;\r
-       }\r
-\r
-      NtClose (KeyHandle);\r
-\r
-      if (Next != NULL)\r
-       {\r
-         *Next = L'\\';\r
-       }\r
-\r
-      Current = Next + 1;\r
-    }\r
-   while (Next != NULL);\r
-\r
-  return STATUS_SUCCESS;\r
-}\r
-\r
-/* EOF */\r
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * FILE:             ntoskrnl/cm/rtlfunc.c
+ * PURPOSE:          Rtlxxx function for registry access
+ * UPDATE HISTORY:
+*/
+
+/* INCLUDES *****************************************************************/
+
+#include <ddk/ntddk.h>
+#include <roscfg.h>
+#include <internal/ob.h>
+#include <limits.h>
+#include <string.h>
+#include <internal/registry.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+#include "cm.h"
+
+
+/* FUNCTIONS ****************************************************************/
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+RtlCheckRegistryKey(IN ULONG RelativeTo,
+                   IN PWSTR Path)
+{
+  HANDLE KeyHandle;
+  NTSTATUS Status;
+
+  Status = RtlpGetRegistryHandle(RelativeTo,
+                                Path,
+                                FALSE,
+                                &KeyHandle);
+  if (!NT_SUCCESS(Status))
+    return(Status);
+
+  NtClose(KeyHandle);
+
+  return(STATUS_SUCCESS);
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+RtlCreateRegistryKey(IN ULONG RelativeTo,
+                    IN PWSTR Path)
+{
+  HANDLE KeyHandle;
+  NTSTATUS Status;
+
+  Status = RtlpGetRegistryHandle(RelativeTo,
+                                Path,
+                                TRUE,
+                                &KeyHandle);
+  if (!NT_SUCCESS(Status))
+    return(Status);
+
+  NtClose(KeyHandle);
+
+  return(STATUS_SUCCESS);
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+RtlDeleteRegistryValue(IN ULONG RelativeTo,
+                      IN PCWSTR Path,
+                      IN PCWSTR ValueName)
+{
+  HANDLE KeyHandle;
+  NTSTATUS Status;
+  UNICODE_STRING Name;
+
+  Status = RtlpGetRegistryHandle(RelativeTo,
+                                (PWSTR) Path,
+                                TRUE,
+                                &KeyHandle);
+  if (!NT_SUCCESS(Status))
+    return(Status);
+
+  RtlInitUnicodeString(&Name,
+                      ValueName);
+
+  NtDeleteValueKey(KeyHandle,
+                  &Name);
+
+  NtClose(KeyHandle);
+
+  return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS STDCALL
+RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess,
+                  OUT PHANDLE KeyHandle)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyPath = UNICODE_STRING_INITIALIZER(L"\\Registry\\User\\.Default");
+  NTSTATUS Status;
+
+  Status = RtlFormatCurrentUserKeyPath(&KeyPath);
+  if (NT_SUCCESS(Status))
+    {
+      InitializeObjectAttributes(&ObjectAttributes,
+                                &KeyPath,
+                                OBJ_CASE_INSENSITIVE,
+                                NULL,
+                                NULL);
+      Status = NtOpenKey(KeyHandle,
+                        DesiredAccess,
+                        &ObjectAttributes);
+      RtlFreeUnicodeString(&KeyPath);
+      if (NT_SUCCESS(Status))
+       return(STATUS_SUCCESS);
+    }
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyPath,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+  Status = NtOpenKey(KeyHandle,
+                    DesiredAccess,
+                    &ObjectAttributes);
+  return(Status);
+}
+
+
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlQueryRegistryValues(IN ULONG RelativeTo,
+                      IN PCWSTR Path,
+                      IN PRTL_QUERY_REGISTRY_TABLE QueryTable,
+                      IN PVOID Context,
+                      IN PVOID Environment)
+{
+  NTSTATUS Status;
+  HANDLE BaseKeyHandle;
+  HANDLE CurrentKeyHandle;
+  PRTL_QUERY_REGISTRY_TABLE QueryEntry;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING KeyName;
+  PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
+  PKEY_VALUE_FULL_INFORMATION FullValueInfo;
+  ULONG BufferSize;
+  ULONG ResultSize;
+  ULONG ValueNameSize;
+  ULONG Index;
+  ULONG StringLen;
+  PWSTR StringPtr;
+  PWSTR ValueName;
+
+  DPRINT("RtlQueryRegistryValues() called\n");
+
+  Status = RtlpGetRegistryHandle(RelativeTo,
+                                (PWSTR) Path,
+                                FALSE,
+                                &BaseKeyHandle);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("RtlpGetRegistryHandle() failed with status %x\n", Status);
+      return(Status);
+    }
+
+  CurrentKeyHandle = BaseKeyHandle;
+  QueryEntry = QueryTable;
+  while ((QueryEntry->QueryRoutine != NULL) ||
+        (QueryEntry->Name != NULL))
+    {
+      if (((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY)) != 0) &&
+         (BaseKeyHandle != CurrentKeyHandle))
+       {
+         NtClose(CurrentKeyHandle);
+         CurrentKeyHandle = BaseKeyHandle;
+       }
+
+      if (QueryEntry->Flags & RTL_QUERY_REGISTRY_SUBKEY)
+       {
+         DPRINT("Open new subkey: %S\n", QueryEntry->Name);
+
+         RtlInitUnicodeString(&KeyName,
+                              QueryEntry->Name);
+         InitializeObjectAttributes(&ObjectAttributes,
+                                    &KeyName,
+                                    OBJ_CASE_INSENSITIVE,
+                                    BaseKeyHandle,
+                                    NULL);
+         Status = NtOpenKey(&CurrentKeyHandle,
+                            KEY_ALL_ACCESS,
+                            &ObjectAttributes);
+         if (!NT_SUCCESS(Status))
+           break;
+       }
+      else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DIRECT)
+       {
+         DPRINT("Query value directly: %S\n", QueryEntry->Name);
+
+         RtlInitUnicodeString(&KeyName,
+                              QueryEntry->Name);
+
+         BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
+         ValueInfo = ExAllocatePool(PagedPool, BufferSize);
+         if (ValueInfo == NULL)
+           {
+             Status = STATUS_NO_MEMORY;
+             break;
+           }
+
+         Status = ZwQueryValueKey(CurrentKeyHandle,
+                                  &KeyName,
+                                  KeyValuePartialInformation,
+                                  ValueInfo,
+                                  BufferSize,
+                                  &ResultSize);
+         if (!NT_SUCCESS(Status))
+           {
+             if (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED)
+               {
+                 ExFreePool(ValueInfo);
+                 Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                 goto ByeBye;
+               }
+       
+             if (QueryEntry->DefaultType == REG_SZ)
+               {
+                 PUNICODE_STRING ValueString;
+                 PUNICODE_STRING SourceString;
+
+                 SourceString = (PUNICODE_STRING)QueryEntry->DefaultData;
+                 ValueString = (PUNICODE_STRING)QueryEntry->EntryContext;
+                 if (ValueString->Buffer == 0)
+                   {
+                     ValueString->Length = SourceString->Length;
+                     ValueString->MaximumLength = SourceString->MaximumLength;
+                     ValueString->Buffer = ExAllocatePool(PagedPool,
+                                                          ValueString->MaximumLength);
+                     if (!ValueString->Buffer)
+                       break;
+                     ValueString->Buffer[0] = 0;
+                     memcpy(ValueString->Buffer,
+                            SourceString->Buffer,
+                            SourceString->MaximumLength);
+                   }
+                 else
+                   {
+                     ValueString->Length = RtlMin(SourceString->Length,
+                                                  ValueString->MaximumLength - sizeof(WCHAR));
+                     memcpy(ValueString->Buffer,
+                            SourceString->Buffer,
+                            ValueString->Length);
+                     ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0;
+                   }
+               }
+             else
+               {
+                 memcpy(QueryEntry->EntryContext,
+                        QueryEntry->DefaultData,
+                        QueryEntry->DefaultLength);
+               }
+             Status = STATUS_SUCCESS;
+           }
+         else
+           {
+             if (ValueInfo->Type == REG_SZ ||
+                 ValueInfo->Type == REG_MULTI_SZ ||
+                 ValueInfo->Type == REG_EXPAND_SZ)
+               {
+                 PUNICODE_STRING ValueString;
+
+                 ValueString = (PUNICODE_STRING)QueryEntry->EntryContext;
+                 if (ValueString->Buffer == 0)
+                   {
+                     RtlInitUnicodeString(ValueString,
+                                          NULL);
+                     ValueString->MaximumLength = ValueInfo->DataLength;
+                     ValueString->Buffer = ExAllocatePool(PagedPool,
+                                                          ValueString->MaximumLength);
+                     if (!ValueString->Buffer)
+                       break;
+                     ValueString->Buffer[0] = 0;
+                   }
+                 ValueString->Length = RtlMin(ValueInfo->DataLength,
+                                              ValueString->MaximumLength) - sizeof(WCHAR);
+                 memcpy(ValueString->Buffer,
+                        ValueInfo->Data,
+                        ValueString->Length);
+                 ((PWSTR)ValueString->Buffer)[ValueString->Length / sizeof(WCHAR)] = 0;
+               }
+             else
+               {
+                 memcpy(QueryEntry->EntryContext,
+                        ValueInfo->Data,
+                        ValueInfo->DataLength);
+               }
+           }
+
+         if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE)
+           {
+             DPRINT("FIXME: Delete value: %S\n", QueryEntry->Name);
+
+           }
+
+         ExFreePool(ValueInfo);
+       }
+      else
+       {
+         DPRINT("Query value via query routine: %S\n", QueryEntry->Name);
+
+         if (QueryEntry->Name != NULL)
+           {
+             DPRINT("Callback\n");
+
+             RtlInitUnicodeString(&KeyName,
+                                  QueryEntry->Name);
+
+             BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 4096;
+             ValueInfo = ExAllocatePool(PagedPool,
+                                        BufferSize);
+             if (ValueInfo == NULL)
+               {
+                 Status = STATUS_NO_MEMORY;
+                 break;
+               }
+
+             Status = NtQueryValueKey(CurrentKeyHandle,
+                                      &KeyName,
+                                      KeyValuePartialInformation,
+                                      ValueInfo,
+                                      BufferSize,
+                                      &ResultSize);
+             if (!NT_SUCCESS(Status))
+               {
+                 Status = QueryEntry->QueryRoutine(QueryEntry->Name,
+                                                   QueryEntry->DefaultType,
+                                                   QueryEntry->DefaultData,
+                                                   QueryEntry->DefaultLength,
+                                                   Context,
+                                                   QueryEntry->EntryContext);
+               }
+             else if ((ValueInfo->Type == REG_MULTI_SZ) &&
+                      !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND))
+               {
+                 DPRINT("Expand REG_MULTI_SZ type\n");
+                 StringPtr = (PWSTR)ValueInfo->Data;
+                 while (*StringPtr != 0)
+                   {
+                     StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR);
+                     Status = QueryEntry->QueryRoutine(QueryEntry->Name,
+                                                       REG_SZ,
+                                                       (PVOID)StringPtr,
+                                                       StringLen,
+                                                       Context,
+                                                       QueryEntry->EntryContext);
+                     if(!NT_SUCCESS(Status))
+                       break;
+                     StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen);
+                   }
+               }
+             else
+               {
+                 Status = QueryEntry->QueryRoutine(QueryEntry->Name,
+                                                   ValueInfo->Type,
+                                                   ValueInfo->Data,
+                                                   ValueInfo->DataLength,
+                                                   Context,
+                                                   QueryEntry->EntryContext);
+               }
+
+             if (QueryEntry->Flags & RTL_QUERY_REGISTRY_DELETE)
+               {
+                 DPRINT("FIXME: Delete value: %S\n", QueryEntry->Name);
+
+               }
+
+             ExFreePool(ValueInfo);
+
+             if (!NT_SUCCESS(Status))
+               break;
+           }
+         else if (QueryEntry->Flags & RTL_QUERY_REGISTRY_NOVALUE)
+           {
+             DPRINT("Simple callback\n");
+             Status = QueryEntry->QueryRoutine(NULL,
+                                               REG_NONE,
+                                               NULL,
+                                               0,
+                                               Context,
+                                               QueryEntry->EntryContext);
+             if (!NT_SUCCESS(Status))
+               break;
+           }
+         else
+           {
+             DPRINT("Enumerate values\n");
+
+             BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + 4096;
+             FullValueInfo = ExAllocatePool(PagedPool,
+                                            BufferSize);
+             if (FullValueInfo == NULL)
+               {
+                 Status = STATUS_NO_MEMORY;
+                 break;
+               }
+              ValueNameSize = 256 * sizeof(WCHAR);
+             ValueName = ExAllocatePool(PagedPool,
+                                        ValueNameSize);
+             if (ValueName == NULL)
+               {
+                 Status = STATUS_NO_MEMORY;
+                 break;
+               }
+             Index = 0;
+             while (TRUE)
+               {
+                 Status = NtEnumerateValueKey(CurrentKeyHandle,
+                                              Index,
+                                              KeyValueFullInformation,
+                                              FullValueInfo,
+                                              BufferSize,
+                                              &ResultSize);
+                 if (!NT_SUCCESS(Status))
+                   {
+                     if ((Status == STATUS_NO_MORE_ENTRIES) &&
+                         (Index == 0) &&
+                         (QueryEntry->Flags & RTL_QUERY_REGISTRY_REQUIRED))
+                       {
+                         Status = STATUS_OBJECT_NAME_NOT_FOUND;
+                       }
+                     else if (Status == STATUS_NO_MORE_ENTRIES)
+                       {
+                         Status = STATUS_SUCCESS;
+                       }
+                     break;
+                   }
+
+                  if (FullValueInfo->NameLength > ValueNameSize - sizeof(WCHAR))
+                   {
+                     /* Should not happen, because the name length is limited to 255 characters */
+                     ExFreePool(ValueName);
+                     ValueNameSize = FullValueInfo->NameLength + sizeof(WCHAR);
+                     ValueName = ExAllocatePool(PagedPool, ValueNameSize);
+                     if (ValueName == NULL)
+                       {
+                         Status = STATUS_NO_MEMORY;
+                         break;
+                       }
+                   }
+
+                 RtlCopyMemory(ValueName, 
+                               FullValueInfo->Name,
+                               FullValueInfo->NameLength);
+                 ValueName[FullValueInfo->NameLength / sizeof(WCHAR)] = 0;
+
+                 if ((FullValueInfo->Type == REG_MULTI_SZ) &&
+                     !(QueryEntry->Flags & RTL_QUERY_REGISTRY_NOEXPAND))
+                   {
+                     DPRINT("Expand REG_MULTI_SZ type\n");
+
+                     StringPtr = (PWSTR)((PVOID)FullValueInfo + FullValueInfo->DataOffset);
+                     while (*StringPtr != 0)
+                       {
+                         StringLen = (wcslen(StringPtr) + 1) * sizeof(WCHAR);
+                         Status = QueryEntry->QueryRoutine(ValueName,
+                                                           REG_SZ,
+                                                           (PVOID)StringPtr,
+                                                           StringLen,
+                                                           Context,
+                                                           QueryEntry->EntryContext);
+                         if(!NT_SUCCESS(Status))
+                           break;
+                         StringPtr = (PWSTR)((PUCHAR)StringPtr + StringLen);
+                       }
+                   }
+                 else
+                   {
+                     Status = QueryEntry->QueryRoutine(ValueName,
+                                                       FullValueInfo->Type,
+                                                       (PVOID)FullValueInfo + FullValueInfo->DataOffset,
+                                                       FullValueInfo->DataLength,
+                                                       Context,
+                                                       QueryEntry->EntryContext);
+                   }
+
+                 if (!NT_SUCCESS(Status))
+                   break;
+
+                 /* FIXME: How will these be deleted? */
+
+                 Index++;
+               }
+
+             ExFreePool(FullValueInfo);
+             ExFreePool(ValueName);
+
+             if (!NT_SUCCESS(Status))
+               break;
+           }
+       }
+
+      QueryEntry++;
+    }
+
+ByeBye:
+
+  if (CurrentKeyHandle != BaseKeyHandle)
+    NtClose(CurrentKeyHandle);
+
+  NtClose(BaseKeyHandle);
+
+  return Status;
+}
+
+
+/*
+ * @implemented
+ */
+NTSTATUS STDCALL
+RtlWriteRegistryValue(IN ULONG RelativeTo,
+                     IN PCWSTR Path,
+                     IN PCWSTR ValueName,
+                     IN ULONG ValueType,
+                     IN PVOID ValueData,
+                     IN ULONG ValueLength)
+{
+  HANDLE KeyHandle;
+  NTSTATUS Status;
+  UNICODE_STRING Name;
+
+  Status = RtlpGetRegistryHandle(RelativeTo,
+                                (PWSTR) Path,
+                                TRUE,
+                                &KeyHandle);
+  if (!NT_SUCCESS(Status))
+    return(Status);
+
+  RtlInitUnicodeString(&Name,
+                      ValueName);
+
+  NtSetValueKey(KeyHandle,
+               &Name,
+               0,
+               ValueType,
+               ValueData,
+               ValueLength);
+
+  NtClose(KeyHandle);
+
+  return(STATUS_SUCCESS);
+}
+
+
+/*
+ * @unimplemented
+ */
+NTSTATUS STDCALL
+RtlFormatCurrentUserKeyPath(IN OUT PUNICODE_STRING KeyPath)
+{
+  /* FIXME: !!! */
+  RtlCreateUnicodeString(KeyPath,
+                        L"\\Registry\\User\\.Default");
+
+  return(STATUS_SUCCESS);
+}
+
+/*  ------------------------------------------  Private Implementation  */
+
+
+NTSTATUS
+RtlpGetRegistryHandle(ULONG RelativeTo,
+                     PWSTR Path,
+                     BOOLEAN Create,
+                     PHANDLE KeyHandle)
+{
+  UNICODE_STRING KeyName;
+  WCHAR KeyBuffer[MAX_PATH];
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  NTSTATUS Status;
+
+  if (RelativeTo & RTL_REGISTRY_HANDLE)
+    {
+      Status = NtDuplicateObject(NtCurrentProcess(),
+                                (HANDLE)Path,
+                                NtCurrentProcess(),
+                                KeyHandle,
+                                0,
+                                FALSE,
+                                DUPLICATE_SAME_ACCESS);
+      return(Status);
+    }
+
+  if (RelativeTo & RTL_REGISTRY_OPTIONAL)
+    RelativeTo &= ~RTL_REGISTRY_OPTIONAL;
+
+  if (RelativeTo >= RTL_REGISTRY_MAXIMUM)
+    return STATUS_INVALID_PARAMETER;
+
+  KeyName.Length = 0;
+  KeyName.MaximumLength = MAX_PATH;
+  KeyName.Buffer = KeyBuffer;
+  KeyBuffer[0] = 0;
+
+  switch (RelativeTo)
+    {
+      case RTL_REGISTRY_SERVICES:
+       RtlAppendUnicodeToString(&KeyName,
+                                L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+       break;
+
+      case RTL_REGISTRY_CONTROL:
+       RtlAppendUnicodeToString(&KeyName,
+                                L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\");
+       break;
+
+      case RTL_REGISTRY_WINDOWS_NT:
+       RtlAppendUnicodeToString(&KeyName,
+                                L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\");
+       break;
+
+      case RTL_REGISTRY_DEVICEMAP:
+       RtlAppendUnicodeToString(&KeyName,
+                                L"\\Registry\\Machine\\Hardware\\DeviceMap\\");
+       break;
+
+      case RTL_REGISTRY_USER:
+       Status = RtlFormatCurrentUserKeyPath(&KeyName);
+       if (!NT_SUCCESS(Status))
+         return(Status);
+       break;
+
+      /* ReactOS specific */
+      case RTL_REGISTRY_ENUM:
+       RtlAppendUnicodeToString(&KeyName,
+                                L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
+       break;
+    }
+
+  if (Path[0] == L'\\' && RelativeTo != RTL_REGISTRY_ABSOLUTE)
+    {
+      Path++;
+    }
+  RtlAppendUnicodeToString(&KeyName,
+                          Path);
+
+  DPRINT("KeyName '%wZ'\n", &KeyName);
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &KeyName,
+                            OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
+                            NULL,
+                            NULL);
+
+  if (Create == TRUE)
+    {
+      Status = NtCreateKey(KeyHandle,
+                          KEY_ALL_ACCESS,
+                          &ObjectAttributes,
+                          0,
+                          NULL,
+                          0,
+                          NULL);
+    }
+  else
+    {
+      Status = NtOpenKey(KeyHandle,
+                        KEY_ALL_ACCESS,
+                        &ObjectAttributes);
+    }
+
+  return(Status);
+}
+
+
+NTSTATUS
+RtlpCreateRegistryKeyPath(PWSTR Path)
+{
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  WCHAR KeyBuffer[MAX_PATH];
+  UNICODE_STRING KeyName;
+  HANDLE KeyHandle;
+  NTSTATUS Status;
+  PWCHAR Current;
+  PWCHAR Next;
+
+  if (_wcsnicmp(Path, L"\\Registry\\", 10) != 0)
+    {
+      return STATUS_INVALID_PARAMETER;
+    }
+
+  wcsncpy (KeyBuffer, Path, MAX_PATH-1);
+  RtlInitUnicodeString (&KeyName, KeyBuffer);
+
+  /* Skip \\Registry\\ */
+  Current = KeyName.Buffer;
+  Current = wcschr (Current, '\\') + 1;
+  Current = wcschr (Current, '\\') + 1;
+
+  do
+   {
+      Next = wcschr (Current, '\\');
+      if (Next == NULL)
+       {
+         /* The end */
+       }
+      else
+       {
+         *Next = 0;
+       }
+
+      InitializeObjectAttributes (&ObjectAttributes,
+                                 &KeyName,
+                                 OBJ_CASE_INSENSITIVE,
+                                 NULL,
+                                 NULL);
+
+      DPRINT("Create '%S'\n", KeyName.Buffer);
+
+      Status = NtCreateKey (&KeyHandle,
+                           KEY_ALL_ACCESS,
+                           &ObjectAttributes,
+                           0,
+                           NULL,
+                           0,
+                           NULL);
+      if (!NT_SUCCESS (Status))
+       {
+         DPRINT ("NtCreateKey() failed with status %x\n", Status);
+         return Status;
+       }
+
+      NtClose (KeyHandle);
+
+      if (Next != NULL)
+       {
+         *Next = L'\\';
+       }
+
+      Current = Next + 1;
+    }
+   while (Next != NULL);
+
+  return STATUS_SUCCESS;
+}
+
+/* EOF */
index cfb3555..e2d2c8d 100644 (file)
-/* $Id: driver.c,v 1.20 2003/10/06 18:24:54 navaraf Exp $\r
- *\r
- * COPYRIGHT:      See COPYING in the top level directory\r
- * PROJECT:        ReactOS kernel\r
- * FILE:           ntoskrnl/io/driver.c\r
- * PURPOSE:        Manage devices\r
- * PROGRAMMER:     David Welch (welch@cwcom.net)\r
- * UPDATE HISTORY:\r
- *                 15/05/98: Created\r
- */\r
-\r
-/* INCLUDES ****************************************************************/\r
-\r
-#include <limits.h>\r
-#include <ddk/ntddk.h>\r
-#include <internal/io.h>\r
-#include <internal/po.h>\r
-#include <internal/ldr.h>\r
-#include <internal/id.h>\r
-#include <internal/pool.h>\r
-#include <internal/registry.h>\r
-\r
-#include <roscfg.h>\r
-\r
-#define NDEBUG\r
-#include <internal/debug.h>\r
-\r
-\r
-typedef struct _SERVICE_GROUP\r
-{\r
-  LIST_ENTRY GroupListEntry;\r
-  UNICODE_STRING GroupName;\r
-\r
-  BOOLEAN ServicesRunning;\r
-\r
-} SERVICE_GROUP, *PSERVICE_GROUP;\r
-\r
-\r
-typedef struct _SERVICE\r
-{\r
-  LIST_ENTRY ServiceListEntry;\r
-  UNICODE_STRING ServiceName;\r
-  UNICODE_STRING RegistryPath;\r
-  UNICODE_STRING ServiceGroup;\r
-  UNICODE_STRING ImagePath;\r
-\r
-  ULONG Start;\r
-  ULONG Type;\r
-  ULONG ErrorControl;\r
-  ULONG Tag;\r
-\r
-  BOOLEAN ServiceRunning;      // needed ??\r
-\r
-} SERVICE, *PSERVICE;\r
-\r
-\r
-/* GLOBALS *******************************************************************/\r
-\r
-static LIST_ENTRY GroupListHead = {NULL, NULL};\r
-static LIST_ENTRY ServiceListHead  = {NULL, NULL};\r
-\r
-POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;\r
-\r
-#define TAG_DRIVER             TAG('D', 'R', 'V', 'R')\r
-#define TAG_DRIVER_EXTENSION   TAG('D', 'R', 'V', 'E')\r
-\r
-\r
-/* FUNCTIONS ***************************************************************/\r
-\r
-NTSTATUS STDCALL\r
-IopCreateDriver(PVOID ObjectBody,\r
-               PVOID Parent,\r
-               PWSTR RemainingPath,\r
-               POBJECT_ATTRIBUTES ObjectAttributes)\r
-{\r
-  DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",\r
-        ObjectBody,\r
-        Parent,\r
-        RemainingPath);\r
-  if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)\r
-    {\r
-      return(STATUS_UNSUCCESSFUL);\r
-    }\r
-\r
-  return(STATUS_SUCCESS);\r
-}\r
-\r
-\r
-VOID\r
-IopInitDriverImplementation(VOID)\r
-{\r
-  /*  Register the process object type  */\r
-  IoDriverObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));\r
-  IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'R');\r
-  IoDriverObjectType->TotalObjects = 0;\r
-  IoDriverObjectType->TotalHandles = 0;\r
-  IoDriverObjectType->MaxObjects = ULONG_MAX;\r
-  IoDriverObjectType->MaxHandles = ULONG_MAX;\r
-  IoDriverObjectType->PagedPoolCharge = 0;\r
-  IoDriverObjectType->NonpagedPoolCharge = sizeof(DRIVER_OBJECT);\r
-  IoDriverObjectType->Dump = NULL;\r
-  IoDriverObjectType->Open = NULL;\r
-  IoDriverObjectType->Close = NULL;\r
-  IoDriverObjectType->Delete = NULL;\r
-  IoDriverObjectType->Parse = NULL;\r
-  IoDriverObjectType->Security = NULL;\r
-  IoDriverObjectType->QueryName = NULL;\r
-  IoDriverObjectType->OkayToClose = NULL;\r
-  IoDriverObjectType->Create = IopCreateDriver;\r
-  IoDriverObjectType->DuplicationNotify = NULL;\r
-  RtlInitUnicodeStringFromLiteral(&IoDriverObjectType->TypeName, L"Driver");\r
-}\r
-\r
-/**********************************************************************\r
- * NAME                                                        EXPORTED\r
- *     NtLoadDriver\r
- *\r
- * DESCRIPTION\r
- *     Loads a device driver.\r
- *     \r
- * ARGUMENTS\r
- *     DriverServiceName\r
- *             Name of the service to load (registry key).\r
- *             \r
- * RETURN VALUE\r
- *     Status.\r
- *\r
- * REVISIONS\r
- */\r
-NTSTATUS STDCALL\r
-NtLoadDriver(IN PUNICODE_STRING DriverServiceName)\r
-{\r
-  RTL_QUERY_REGISTRY_TABLE QueryTable[3];\r
-  WCHAR FullImagePathBuffer[MAX_PATH];\r
-  UNICODE_STRING ImagePath;\r
-  UNICODE_STRING FullImagePath;\r
-  NTSTATUS Status;\r
-  ULONG Type;\r
-  PDEVICE_NODE DeviceNode;\r
-  PMODULE_OBJECT ModuleObject;\r
-  LPWSTR Start;\r
-\r
-  DPRINT("NtLoadDriver(%wZ) called\n", DriverServiceName);\r
-\r
-  RtlInitUnicodeString(&ImagePath, NULL);\r
-\r
-  /* Get service data */\r
-  RtlZeroMemory(&QueryTable,\r
-               sizeof(QueryTable));\r
-\r
-  QueryTable[0].Name = L"Type";\r
-  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
-  QueryTable[0].EntryContext = &Type;\r
-\r
-  QueryTable[1].Name = L"ImagePath";\r
-  QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-  QueryTable[1].EntryContext = &ImagePath;\r
-\r
-  Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,\r
-                                 DriverServiceName->Buffer,\r
-                                 QueryTable,\r
-                                 NULL,\r
-                                 NULL);\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);\r
-      RtlFreeUnicodeString(&ImagePath);\r
-      return(Status);\r
-    }\r
-\r
-  if (ImagePath.Length == 0)\r
-    {\r
-      wcscpy(FullImagePathBuffer, L"\\SystemRoot\\system32\\drivers");\r
-      wcscat(FullImagePathBuffer, wcsrchr(DriverServiceName->Buffer, L'\\'));\r
-      wcscat(FullImagePathBuffer, L".sys");\r
-    }\r
-  else if (ImagePath.Buffer[0] != L'\\')\r
-    {\r
-      wcscpy(FullImagePathBuffer, L"\\SystemRoot\\");\r
-      wcscat(FullImagePathBuffer, ImagePath.Buffer);\r
-    }\r
-  else\r
-    {\r
-      wcscpy(FullImagePathBuffer, ImagePath.Buffer);\r
-    }\r
-\r
-  RtlFreeUnicodeString(&ImagePath);\r
-  RtlInitUnicodeString(&FullImagePath, FullImagePathBuffer);\r
-\r
-  DPRINT("FullImagePath: '%S'\n", FullImagePathBuffer);\r
-  DPRINT("Type %lx\n", Type);\r
-\r
-  /* Use IopRootDeviceNode for now */\r
-  Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);\r
-      return(Status);\r
-    }\r
-\r
-  ModuleObject = LdrGetModuleObject(DriverServiceName);\r
-  if (ModuleObject != NULL)\r
-    {\r
-      return(STATUS_IMAGE_ALREADY_LOADED);\r
-    }\r
-\r
-  Status = LdrLoadModule(&FullImagePath, &ModuleObject);\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      DPRINT1("LdrLoadModule() failed (Status %lx)\n", Status);\r
-      IopFreeDeviceNode(DeviceNode);\r
-      return(Status);\r
-    }\r
-\r
-  /* Set a service name for the device node */\r
-  Start = wcsrchr(DriverServiceName->Buffer, L'\\');\r
-  if (Start == NULL)\r
-    Start = DriverServiceName->Buffer;\r
-  else\r
-    Start++;\r
-  RtlCreateUnicodeString(&DeviceNode->ServiceName, Start);\r
-\r
-  Status = IopInitializeDriver(ModuleObject->EntryPoint,\r
-                              DeviceNode,\r
-                              (Type == 2 || Type == 8),\r
-                              ModuleObject->Base,\r
-                              ModuleObject->Length,\r
-                              FALSE);\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status);\r
-      LdrUnloadModule(ModuleObject);\r
-      IopFreeDeviceNode(DeviceNode);\r
-    }\r
-\r
-  return(Status);\r
-}\r
-\r
-\r
-NTSTATUS STDCALL\r
-NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)\r
-{\r
-  RTL_QUERY_REGISTRY_TABLE QueryTable[2];\r
-  WCHAR FullImagePathBuffer[MAX_PATH];\r
-  UNICODE_STRING ImagePath;\r
-  UNICODE_STRING FullImagePath;\r
-  UNICODE_STRING ObjectName;\r
-  PDRIVER_OBJECT DriverObject;\r
-  NTSTATUS Status;\r
-  PMODULE_OBJECT ModuleObject;\r
-  LPWSTR Start;\r
-\r
-  DPRINT("DriverServiceName: '%wZ'\n", DriverServiceName);\r
-\r
-  /* Get the service name from the module name */\r
-  Start = wcsrchr(DriverServiceName->Buffer, L'\\');\r
-  if (Start == NULL)\r
-    Start = DriverServiceName->Buffer;\r
-  else\r
-    Start++;\r
-\r
-  ObjectName.Length = wcslen(Start) + 8;\r
-  ObjectName.Buffer = ExAllocatePool(NonPagedPool,\r
-    ObjectName.Length * sizeof(WCHAR));\r
-  wcscpy(ObjectName.Buffer, L"\\Driver\\");\r
-  memcpy(ObjectName.Buffer + 8, Start, (ObjectName.Length - 8) * sizeof(WCHAR));\r
-\r
-  /* Find the driver object */\r
-  Status = ObReferenceObjectByName(&ObjectName, 0, 0, 0, IoDriverObjectType,\r
-    KernelMode, 0, (PVOID*)&DriverObject);\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      DPRINT("Can't locate driver object for %wZ\n", ObjectName);\r
-      return Status;\r
-    }\r
-  ObDereferenceObject(DriverObject);\r
-\r
-  RtlInitUnicodeString(&ImagePath, NULL);\r
-\r
-  /* Get service data */\r
-  RtlZeroMemory(&QueryTable,\r
-               sizeof(QueryTable));\r
-\r
-  QueryTable[0].Name = L"ImagePath";\r
-  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-  QueryTable[0].EntryContext = &ImagePath;\r
-\r
-  Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,\r
-                                 DriverServiceName->Buffer,\r
-                                 QueryTable,\r
-                                 NULL,\r
-                                 NULL);\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);\r
-      RtlFreeUnicodeString(&ImagePath);\r
-      return(Status);\r
-    }\r
-\r
-  if (ImagePath.Length == 0)\r
-    {\r
-      wcscpy(FullImagePathBuffer, L"\\SystemRoot\\system32\\drivers");\r
-      wcscat(FullImagePathBuffer, wcsrchr(DriverServiceName->Buffer, L'\\'));\r
-      wcscat(FullImagePathBuffer, L".sys");\r
-    }\r
-  else if (ImagePath.Buffer[0] != L'\\')\r
-    {\r
-      wcscpy(FullImagePathBuffer, L"\\SystemRoot\\");\r
-      wcscat(FullImagePathBuffer, ImagePath.Buffer);\r
-    }\r
-  else\r
-    {\r
-      wcscpy(FullImagePathBuffer, ImagePath.Buffer);\r
-    }\r
-\r
-  RtlFreeUnicodeString(&ImagePath);\r
-  RtlInitUnicodeString(&FullImagePath, FullImagePathBuffer);\r
-\r
-  ModuleObject = LdrGetModuleObject(DriverServiceName);\r
-  if (ModuleObject == NULL)\r
-    {\r
-      return STATUS_UNSUCCESSFUL;\r
-    }\r
-\r
-  /* Unload the module and release the references to the device object */\r
-\r
-  if (DriverObject->DriverUnload)\r
-    (*DriverObject->DriverUnload)(DriverObject);\r
-  ObDereferenceObject(DriverObject);\r
-  ObDereferenceObject(DriverObject);\r
-  LdrUnloadModule(ModuleObject);\r
-\r
-  return STATUS_SUCCESS;\r
-}\r
-\r
-\r
-static NTSTATUS STDCALL\r
-IopCreateGroupListEntry(PWSTR ValueName,\r
-                       ULONG ValueType,\r
-                       PVOID ValueData,\r
-                       ULONG ValueLength,\r
-                       PVOID Context,\r
-                       PVOID EntryContext)\r
-{\r
-  PSERVICE_GROUP Group;\r
-\r
-  if (ValueType == REG_SZ)\r
-    {\r
-      DPRINT("GroupName: '%S'\n", (PWCHAR)ValueData);\r
-\r
-      Group = ExAllocatePool(NonPagedPool,\r
-                            sizeof(SERVICE_GROUP));\r
-      if (Group == NULL)\r
-       {\r
-         return(STATUS_INSUFFICIENT_RESOURCES);\r
-       }\r
-\r
-      RtlZeroMemory(Group, sizeof(SERVICE_GROUP));\r
-\r
-      if (!RtlCreateUnicodeString(&Group->GroupName,\r
-                                 (PWSTR)ValueData))\r
-       {\r
-         return(STATUS_INSUFFICIENT_RESOURCES);\r
-       }\r
-\r
-\r
-      InsertTailList(&GroupListHead,\r
-                    &Group->GroupListEntry);\r
-    }\r
-\r
-  return(STATUS_SUCCESS);\r
-}\r
-\r
-\r
-static NTSTATUS STDCALL\r
-IopCreateServiceListEntry(PUNICODE_STRING ServiceName)\r
-{\r
-  RTL_QUERY_REGISTRY_TABLE QueryTable[6];\r
-  PSERVICE Service;\r
-  NTSTATUS Status;\r
-\r
-  DPRINT("ServiceName: '%wZ'\n", ServiceName);\r
-\r
-  /* Allocate service entry */\r
-  Service = (PSERVICE)ExAllocatePool(NonPagedPool, sizeof(SERVICE));\r
-  if (Service == NULL)\r
-    {\r
-      DPRINT1("ExAllocatePool() failed\n");\r
-      return(STATUS_INSUFFICIENT_RESOURCES);\r
-    }\r
-  RtlZeroMemory(Service, sizeof(SERVICE));\r
-\r
-  /* Get service data */\r
-  RtlZeroMemory(&QueryTable,\r
-               sizeof(QueryTable));\r
-\r
-  QueryTable[0].Name = L"Start";\r
-  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
-  QueryTable[0].EntryContext = &Service->Start;\r
-\r
-  QueryTable[1].Name = L"Type";\r
-  QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
-  QueryTable[1].EntryContext = &Service->Type;\r
-\r
-  QueryTable[2].Name = L"ErrorControl";\r
-  QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;\r
-  QueryTable[2].EntryContext = &Service->ErrorControl;\r
-\r
-  QueryTable[3].Name = L"Group";\r
-  QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-  QueryTable[3].EntryContext = &Service->ServiceGroup;\r
-\r
-  QueryTable[4].Name = L"ImagePath";\r
-  QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;\r
-  QueryTable[4].EntryContext = &Service->ImagePath;\r
-\r
-  Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,\r
-                                 ServiceName->Buffer,\r
-                                 QueryTable,\r
-                                 NULL,\r
-                                 NULL);\r
-  if (!NT_SUCCESS(Status) || Service->Start > 1)\r
-    {\r
-      RtlFreeUnicodeString(&Service->ServiceGroup);\r
-      RtlFreeUnicodeString(&Service->ImagePath);\r
-      ExFreePool(Service);\r
-      return(Status);\r
-    }\r
-\r
-  /* Copy service name */\r
-  Service->ServiceName.Length = ServiceName->Length;\r
-  Service->ServiceName.MaximumLength = ServiceName->Length + sizeof(WCHAR);\r
-  Service->ServiceName.Buffer = ExAllocatePool(NonPagedPool,\r
-                                              Service->ServiceName.MaximumLength);\r
-  RtlCopyMemory(Service->ServiceName.Buffer,\r
-               ServiceName->Buffer,\r
-               ServiceName->Length);\r
-  Service->ServiceName.Buffer[ServiceName->Length / sizeof(WCHAR)] = 0;\r
-\r
-  /* Build registry path */\r
-  Service->RegistryPath.MaximumLength = MAX_PATH * sizeof(WCHAR);\r
-  Service->RegistryPath.Buffer = ExAllocatePool(NonPagedPool,\r
-                                               MAX_PATH * sizeof(WCHAR));\r
-  wcscpy(Service->RegistryPath.Buffer,\r
-        L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");\r
-  wcscat(Service->RegistryPath.Buffer,\r
-        Service->ServiceName.Buffer);\r
-  Service->RegistryPath.Length = wcslen(Service->RegistryPath.Buffer) * sizeof(WCHAR);\r
-\r
-  DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName);\r
-  DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath);\r
-  DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup);\r
-  DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath);\r
-  DPRINT("Start %lx  Type %lx  ErrorControl %lx\n",\r
-        Service->Start, Service->Type, Service->ErrorControl);\r
-\r
-  /* Append service entry */\r
-  InsertTailList(&ServiceListHead,\r
-                &Service->ServiceListEntry);\r
-\r
-  return(STATUS_SUCCESS);\r
-}\r
-\r
-\r
-NTSTATUS\r
-IoCreateDriverList(VOID)\r
-{\r
-  RTL_QUERY_REGISTRY_TABLE QueryTable[2];\r
-  PKEY_BASIC_INFORMATION KeyInfo = NULL;\r
-  OBJECT_ATTRIBUTES ObjectAttributes;\r
-  UNICODE_STRING ServicesKeyName;\r
-  UNICODE_STRING SubKeyName;\r
-  HANDLE KeyHandle;\r
-  NTSTATUS Status;\r
-  ULONG Index;\r
-\r
-  ULONG KeyInfoLength = 0;\r
-  ULONG ReturnedLength;\r
-\r
-  DPRINT("IoCreateDriverList() called\n");\r
-\r
-  /* Initialize basic variables */\r
-  InitializeListHead(&GroupListHead);\r
-  InitializeListHead(&ServiceListHead);\r
-\r
-  /* Build group order list */\r
-  RtlZeroMemory(&QueryTable,\r
-               sizeof(QueryTable));\r
-\r
-  QueryTable[0].Name = L"List";\r
-  QueryTable[0].QueryRoutine = IopCreateGroupListEntry;\r
-\r
-  Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,\r
-                                 L"ServiceGroupOrder",\r
-                                 QueryTable,\r
-                                 NULL,\r
-                                 NULL);\r
-  if (!NT_SUCCESS(Status))\r
-    return(Status);\r
-\r
-  /* Enumerate services and create the service list */\r
-  RtlInitUnicodeStringFromLiteral(&ServicesKeyName,\r
-                      L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");\r
-\r
-  InitializeObjectAttributes(&ObjectAttributes,\r
-                            &ServicesKeyName,\r
-                            OBJ_CASE_INSENSITIVE,\r
-                            NULL,\r
-                            NULL);\r
-\r
-  Status = NtOpenKey(&KeyHandle,\r
-                    0x10001,\r
-                    &ObjectAttributes);\r
-  if (!NT_SUCCESS(Status))\r
-    {\r
-      return(Status);\r
-    }\r
-\r
-  KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR);\r
-  KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength);\r
-  if (KeyInfo == NULL)\r
-    {\r
-      NtClose(KeyHandle);\r
-      return(STATUS_INSUFFICIENT_RESOURCES);\r
-    }\r
-\r
-  Index = 0;\r
-  while (TRUE)\r
-    {\r
-      Status = NtEnumerateKey(KeyHandle,\r
-                             Index,\r
-                             KeyBasicInformation,\r
-                             KeyInfo,\r
-                             KeyInfoLength,\r
-                             &ReturnedLength);\r
-      if (NT_SUCCESS(Status))\r
-       {\r
-         if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR))\r
-           {\r
-\r
-             SubKeyName.Length = KeyInfo->NameLength;\r
-             SubKeyName.MaximumLength = KeyInfo->NameLength + sizeof(WCHAR);\r
-             SubKeyName.Buffer = KeyInfo->Name;\r
-             SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0;\r
-\r
-             DPRINT("KeyName: '%wZ'\n", &SubKeyName);\r
-             IopCreateServiceListEntry(&SubKeyName);\r
-           }\r
-       }\r
-\r
-      if (!NT_SUCCESS(Status))\r
-       break;\r
-\r
-      Index++;\r
-    }\r
-\r
-  ExFreePool(KeyInfo);\r
-  NtClose(KeyHandle);\r
-\r
-  DPRINT("IoCreateDriverList() done\n");\r
-\r
-  return(STATUS_SUCCESS);\r
-}\r
-\r
-\r
-VOID\r
-LdrLoadAutoConfigDrivers(VOID)\r
-{\r
-  PLIST_ENTRY GroupEntry;\r
-  PLIST_ENTRY ServiceEntry;\r
-  PSERVICE_GROUP CurrentGroup;\r
-  PSERVICE CurrentService;\r
-  NTSTATUS Status;\r
-\r
-  CHAR TextBuffer [256];\r
-  ULONG x, y, cx, cy;\r
-\r
-  DPRINT("LdrLoadAutoConfigDrivers() called\n");\r
-\r
-  GroupEntry = GroupListHead.Flink;\r
-  while (GroupEntry != &GroupListHead)\r
-    {\r
-      CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);\r
-\r
-      DPRINT("Group: %wZ\n", &CurrentGroup->GroupName);\r
-\r
-      ServiceEntry = ServiceListHead.Flink;\r
-      while (ServiceEntry != &ServiceListHead)\r
-       {\r
-         CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);\r
-\r
-         if ((RtlCompareUnicodeString(&CurrentGroup->GroupName, &CurrentService->ServiceGroup, TRUE) == 0) &&\r
-             (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/))\r
-           {\r
-\r
-             HalQueryDisplayParameters(&x, &y, &cx, &cy);\r
-             RtlFillMemory(TextBuffer, x, ' ');\r
-             TextBuffer[x] = '\0';\r
-             HalSetDisplayParameters(0, y-1);\r
-             HalDisplayString(TextBuffer);\r
-\r
-             sprintf(TextBuffer, "Loading %S...\n", CurrentService->ServiceName.Buffer);\r
-             HalSetDisplayParameters(0, y-1);\r
-             HalDisplayString(TextBuffer);\r
-             HalSetDisplayParameters(cx, cy);\r
-\r
-             DPRINT("  Path: %wZ\n", &CurrentService->RegistryPath);\r
-             Status = NtLoadDriver(&CurrentService->RegistryPath);\r
-             if (!NT_SUCCESS(Status))\r
-               {\r
-                 DPRINT("NtLoadDriver() failed (Status %lx)\n", Status);\r
-#if 0\r
-                 if (CurrentService->ErrorControl == 1)\r
-                   {\r
-                     /* Log error */\r
-\r
-                   }\r
-                 else if (CurrentService->ErrorControl == 2)\r
-                   {\r
-                     if (IsLastKnownGood == FALSE)\r
-                       {\r
-                         /* Boot last known good configuration */\r
-\r
-                       }\r
-                   }\r
-                 else if (CurrentService->ErrorControl == 3)\r
-                   {\r
-                     if (IsLastKnownGood == FALSE)\r
-                       {\r
-                         /* Boot last known good configuration */\r
-\r
-                       }\r
-                     else\r
-                       {\r
-                         /* BSOD! */\r
-\r
-                       }\r
-                   }\r
-#endif\r
-               }\r
-           }\r
-         ServiceEntry = ServiceEntry->Flink;\r
-       }\r
-\r
-      GroupEntry = GroupEntry->Flink;\r
-    }\r
-\r
-  DPRINT("LdrLoadAutoConfigDrivers() done\n");\r
-}\r
-\r
-\r
-NTSTATUS\r
-IoDestroyDriverList(VOID)\r
-{\r
-  PLIST_ENTRY GroupEntry;\r
-  PLIST_ENTRY ServiceEntry;\r
-  PSERVICE_GROUP CurrentGroup;\r
-  PSERVICE CurrentService;\r
-\r
-  DPRINT("IoDestroyDriverList() called\n");\r
-\r
-  /* Destroy group list */\r
-  GroupEntry = GroupListHead.Flink;\r
-  while (GroupEntry != &GroupListHead)\r
-    {\r
-      CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);\r
-\r
-      RtlFreeUnicodeString(&CurrentGroup->GroupName);\r
-      RemoveEntryList(GroupEntry);\r
-      ExFreePool(CurrentGroup);\r
-\r
-      GroupEntry = GroupListHead.Flink;\r
-    }\r
-\r
-  /* Destroy service list */\r
-  ServiceEntry = ServiceListHead.Flink;\r
-  while (ServiceEntry != &ServiceListHead)\r
-    {\r
-      CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);\r
-\r
-      RtlFreeUnicodeString(&CurrentService->ServiceName);\r
-      RtlFreeUnicodeString(&CurrentService->RegistryPath);\r
-      RtlFreeUnicodeString(&CurrentService->ServiceGroup);\r
-      RtlFreeUnicodeString(&CurrentService->ImagePath);\r
-      RemoveEntryList(ServiceEntry);\r
-      ExFreePool(CurrentService);\r
-\r
-      ServiceEntry = ServiceListHead.Flink;\r
-    }\r
-\r
-  DPRINT("IoDestroyDriverList() done\n");\r
-\r
-  return(STATUS_SUCCESS);\r
-}\r
-\r
-/* EOF */\r
+/* $Id: driver.c,v 1.21 2003/10/06 18:49:50 navaraf Exp $
+ *
+ * COPYRIGHT:      See COPYING in the top level directory
+ * PROJECT:        ReactOS kernel
+ * FILE:           ntoskrnl/io/driver.c
+ * PURPOSE:        Manage devices
+ * PROGRAMMER:     David Welch (welch@cwcom.net)
+ * UPDATE HISTORY:
+ *                 15/05/98: Created
+ */
+
+/* INCLUDES ****************************************************************/
+
+#include <limits.h>
+#include <ddk/ntddk.h>
+#include <internal/io.h>
+#include <internal/po.h>
+#include <internal/ldr.h>
+#include <internal/id.h>
+#include <internal/pool.h>
+#include <internal/registry.h>
+
+#include <roscfg.h>
+
+#define NDEBUG
+#include <internal/debug.h>
+
+
+typedef struct _SERVICE_GROUP
+{
+  LIST_ENTRY GroupListEntry;
+  UNICODE_STRING GroupName;
+
+  BOOLEAN ServicesRunning;
+
+} SERVICE_GROUP, *PSERVICE_GROUP;
+
+
+typedef struct _SERVICE
+{
+  LIST_ENTRY ServiceListEntry;
+  UNICODE_STRING ServiceName;
+  UNICODE_STRING RegistryPath;
+  UNICODE_STRING ServiceGroup;
+  UNICODE_STRING ImagePath;
+
+  ULONG Start;
+  ULONG Type;
+  ULONG ErrorControl;
+  ULONG Tag;
+
+  BOOLEAN ServiceRunning;      // needed ??
+
+} SERVICE, *PSERVICE;
+
+
+/* GLOBALS *******************************************************************/
+
+static LIST_ENTRY GroupListHead = {NULL, NULL};
+static LIST_ENTRY ServiceListHead  = {NULL, NULL};
+
+POBJECT_TYPE EXPORTED IoDriverObjectType = NULL;
+
+#define TAG_DRIVER             TAG('D', 'R', 'V', 'R')
+#define TAG_DRIVER_EXTENSION   TAG('D', 'R', 'V', 'E')
+
+
+/* FUNCTIONS ***************************************************************/
+
+NTSTATUS STDCALL
+IopCreateDriver(PVOID ObjectBody,
+               PVOID Parent,
+               PWSTR RemainingPath,
+               POBJECT_ATTRIBUTES ObjectAttributes)
+{
+  DPRINT("LdrCreateModule(ObjectBody %x, Parent %x, RemainingPath %S)\n",
+        ObjectBody,
+        Parent,
+        RemainingPath);
+  if (RemainingPath != NULL && wcschr(RemainingPath + 1, '\\') != NULL)
+    {
+      return(STATUS_UNSUCCESSFUL);
+    }
+
+  return(STATUS_SUCCESS);
+}
+
+
+VOID
+IopInitDriverImplementation(VOID)
+{
+  /*  Register the process object type  */
+  IoDriverObjectType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
+  IoDriverObjectType->Tag = TAG('D', 'R', 'V', 'R');
+  IoDriverObjectType->TotalObjects = 0;
+  IoDriverObjectType->TotalHandles = 0;
+  IoDriverObjectType->MaxObjects = ULONG_MAX;
+  IoDriverObjectType->MaxHandles = ULONG_MAX;
+  IoDriverObjectType->PagedPoolCharge = 0;
+  IoDriverObjectType->NonpagedPoolCharge = sizeof(DRIVER_OBJECT);
+  IoDriverObjectType->Dump = NULL;
+  IoDriverObjectType->Open = NULL;
+  IoDriverObjectType->Close = NULL;
+  IoDriverObjectType->Delete = NULL;
+  IoDriverObjectType->Parse = NULL;
+  IoDriverObjectType->Security = NULL;
+  IoDriverObjectType->QueryName = NULL;
+  IoDriverObjectType->OkayToClose = NULL;
+  IoDriverObjectType->Create = IopCreateDriver;
+  IoDriverObjectType->DuplicationNotify = NULL;
+  RtlInitUnicodeStringFromLiteral(&IoDriverObjectType->TypeName, L"Driver");
+}
+
+/**********************************************************************
+ * NAME                                                        EXPORTED
+ *     NtLoadDriver
+ *
+ * DESCRIPTION
+ *     Loads a device driver.
+ *     
+ * ARGUMENTS
+ *     DriverServiceName
+ *             Name of the service to load (registry key).
+ *             
+ * RETURN VALUE
+ *     Status.
+ *
+ * REVISIONS
+ */
+NTSTATUS STDCALL
+NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
+{
+  RTL_QUERY_REGISTRY_TABLE QueryTable[3];
+  WCHAR FullImagePathBuffer[MAX_PATH];
+  UNICODE_STRING ImagePath;
+  UNICODE_STRING FullImagePath;
+  NTSTATUS Status;
+  ULONG Type;
+  PDEVICE_NODE DeviceNode;
+  PMODULE_OBJECT ModuleObject;
+  LPWSTR Start;
+
+  DPRINT("NtLoadDriver(%wZ) called\n", DriverServiceName);
+
+  RtlInitUnicodeString(&ImagePath, NULL);
+
+  /* Get service data */
+  RtlZeroMemory(&QueryTable,
+               sizeof(QueryTable));
+
+  QueryTable[0].Name = L"Type";
+  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+  QueryTable[0].EntryContext = &Type;
+
+  QueryTable[1].Name = L"ImagePath";
+  QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[1].EntryContext = &ImagePath;
+
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+                                 DriverServiceName->Buffer,
+                                 QueryTable,
+                                 NULL,
+                                 NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
+      RtlFreeUnicodeString(&ImagePath);
+      return(Status);
+    }
+
+  if (ImagePath.Length == 0)
+    {
+      wcscpy(FullImagePathBuffer, L"\\SystemRoot\\system32\\drivers");
+      wcscat(FullImagePathBuffer, wcsrchr(DriverServiceName->Buffer, L'\\'));
+      wcscat(FullImagePathBuffer, L".sys");
+    }
+  else if (ImagePath.Buffer[0] != L'\\')
+    {
+      wcscpy(FullImagePathBuffer, L"\\SystemRoot\\");
+      wcscat(FullImagePathBuffer, ImagePath.Buffer);
+    }
+  else
+    {
+      wcscpy(FullImagePathBuffer, ImagePath.Buffer);
+    }
+
+  RtlFreeUnicodeString(&ImagePath);
+  RtlInitUnicodeString(&FullImagePath, FullImagePathBuffer);
+
+  DPRINT("FullImagePath: '%S'\n", FullImagePathBuffer);
+  DPRINT("Type %lx\n", Type);
+
+  /* Use IopRootDeviceNode for now */
+  Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status);
+      return(Status);
+    }
+
+  ModuleObject = LdrGetModuleObject(DriverServiceName);
+  if (ModuleObject != NULL)
+    {
+      return(STATUS_IMAGE_ALREADY_LOADED);
+    }
+
+  Status = LdrLoadModule(&FullImagePath, &ModuleObject);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("LdrLoadModule() failed (Status %lx)\n", Status);
+      IopFreeDeviceNode(DeviceNode);
+      return(Status);
+    }
+
+  /* Set a service name for the device node */
+  Start = wcsrchr(DriverServiceName->Buffer, L'\\');
+  if (Start == NULL)
+    Start = DriverServiceName->Buffer;
+  else
+    Start++;
+  RtlCreateUnicodeString(&DeviceNode->ServiceName, Start);
+
+  Status = IopInitializeDriver(ModuleObject->EntryPoint,
+                              DeviceNode,
+                              (Type == 2 || Type == 8),
+                              ModuleObject->Base,
+                              ModuleObject->Length,
+                              FALSE);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status);
+      LdrUnloadModule(ModuleObject);
+      IopFreeDeviceNode(DeviceNode);
+    }
+
+  return(Status);
+}
+
+
+NTSTATUS STDCALL
+NtUnloadDriver(IN PUNICODE_STRING DriverServiceName)
+{
+  RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+  WCHAR FullImagePathBuffer[MAX_PATH];
+  UNICODE_STRING ImagePath;
+  UNICODE_STRING FullImagePath;
+  UNICODE_STRING ObjectName;
+  PDRIVER_OBJECT DriverObject;
+  NTSTATUS Status;
+  PMODULE_OBJECT ModuleObject;
+  LPWSTR Start;
+
+  DPRINT("DriverServiceName: '%wZ'\n", DriverServiceName);
+
+  /* Get the service name from the module name */
+  Start = wcsrchr(DriverServiceName->Buffer, L'\\');
+  if (Start == NULL)
+    Start = DriverServiceName->Buffer;
+  else
+    Start++;
+
+  ObjectName.Length = wcslen(Start) + 8;
+  ObjectName.Buffer = ExAllocatePool(NonPagedPool,
+    ObjectName.Length * sizeof(WCHAR));
+  wcscpy(ObjectName.Buffer, L"\\Driver\\");
+  memcpy(ObjectName.Buffer + 8, Start, (ObjectName.Length - 8) * sizeof(WCHAR));
+
+  /* Find the driver object */
+  Status = ObReferenceObjectByName(&ObjectName, 0, 0, 0, IoDriverObjectType,
+    KernelMode, 0, (PVOID*)&DriverObject);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT("Can't locate driver object for %wZ\n", ObjectName);
+      return Status;
+    }
+  ObDereferenceObject(DriverObject);
+
+  RtlInitUnicodeString(&ImagePath, NULL);
+
+  /* Get service data */
+  RtlZeroMemory(&QueryTable,
+               sizeof(QueryTable));
+
+  QueryTable[0].Name = L"ImagePath";
+  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[0].EntryContext = &ImagePath;
+
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
+                                 DriverServiceName->Buffer,
+                                 QueryTable,
+                                 NULL,
+                                 NULL);
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
+      RtlFreeUnicodeString(&ImagePath);
+      return(Status);
+    }
+
+  if (ImagePath.Length == 0)
+    {
+      wcscpy(FullImagePathBuffer, L"\\SystemRoot\\system32\\drivers");
+      wcscat(FullImagePathBuffer, wcsrchr(DriverServiceName->Buffer, L'\\'));
+      wcscat(FullImagePathBuffer, L".sys");
+    }
+  else if (ImagePath.Buffer[0] != L'\\')
+    {
+      wcscpy(FullImagePathBuffer, L"\\SystemRoot\\");
+      wcscat(FullImagePathBuffer, ImagePath.Buffer);
+    }
+  else
+    {
+      wcscpy(FullImagePathBuffer, ImagePath.Buffer);
+    }
+
+  RtlFreeUnicodeString(&ImagePath);
+  RtlInitUnicodeString(&FullImagePath, FullImagePathBuffer);
+
+  ModuleObject = LdrGetModuleObject(DriverServiceName);
+  if (ModuleObject == NULL)
+    {
+      return STATUS_UNSUCCESSFUL;
+    }
+
+  /* Unload the module and release the references to the device object */
+
+  if (DriverObject->DriverUnload)
+    (*DriverObject->DriverUnload)(DriverObject);
+  ObDereferenceObject(DriverObject);
+  ObDereferenceObject(DriverObject);
+  LdrUnloadModule(ModuleObject);
+
+  return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS STDCALL
+IopCreateGroupListEntry(PWSTR ValueName,
+                       ULONG ValueType,
+                       PVOID ValueData,
+                       ULONG ValueLength,
+                       PVOID Context,
+                       PVOID EntryContext)
+{
+  PSERVICE_GROUP Group;
+
+  if (ValueType == REG_SZ)
+    {
+      DPRINT("GroupName: '%S'\n", (PWCHAR)ValueData);
+
+      Group = ExAllocatePool(NonPagedPool,
+                            sizeof(SERVICE_GROUP));
+      if (Group == NULL)
+       {
+         return(STATUS_INSUFFICIENT_RESOURCES);
+       }
+
+      RtlZeroMemory(Group, sizeof(SERVICE_GROUP));
+
+      if (!RtlCreateUnicodeString(&Group->GroupName,
+                                 (PWSTR)ValueData))
+       {
+         return(STATUS_INSUFFICIENT_RESOURCES);
+       }
+
+
+      InsertTailList(&GroupListHead,
+                    &Group->GroupListEntry);
+    }
+
+  return(STATUS_SUCCESS);
+}
+
+
+static NTSTATUS STDCALL
+IopCreateServiceListEntry(PUNICODE_STRING ServiceName)
+{
+  RTL_QUERY_REGISTRY_TABLE QueryTable[6];
+  PSERVICE Service;
+  NTSTATUS Status;
+
+  DPRINT("ServiceName: '%wZ'\n", ServiceName);
+
+  /* Allocate service entry */
+  Service = (PSERVICE)ExAllocatePool(NonPagedPool, sizeof(SERVICE));
+  if (Service == NULL)
+    {
+      DPRINT1("ExAllocatePool() failed\n");
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+  RtlZeroMemory(Service, sizeof(SERVICE));
+
+  /* Get service data */
+  RtlZeroMemory(&QueryTable,
+               sizeof(QueryTable));
+
+  QueryTable[0].Name = L"Start";
+  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+  QueryTable[0].EntryContext = &Service->Start;
+
+  QueryTable[1].Name = L"Type";
+  QueryTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+  QueryTable[1].EntryContext = &Service->Type;
+
+  QueryTable[2].Name = L"ErrorControl";
+  QueryTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+  QueryTable[2].EntryContext = &Service->ErrorControl;
+
+  QueryTable[3].Name = L"Group";
+  QueryTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[3].EntryContext = &Service->ServiceGroup;
+
+  QueryTable[4].Name = L"ImagePath";
+  QueryTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
+  QueryTable[4].EntryContext = &Service->ImagePath;
+
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+                                 ServiceName->Buffer,
+                                 QueryTable,
+                                 NULL,
+                                 NULL);
+  if (!NT_SUCCESS(Status) || Service->Start > 1)
+    {
+      RtlFreeUnicodeString(&Service->ServiceGroup);
+      RtlFreeUnicodeString(&Service->ImagePath);
+      ExFreePool(Service);
+      return(Status);
+    }
+
+  /* Copy service name */
+  Service->ServiceName.Length = ServiceName->Length;
+  Service->ServiceName.MaximumLength = ServiceName->Length + sizeof(WCHAR);
+  Service->ServiceName.Buffer = ExAllocatePool(NonPagedPool,
+                                              Service->ServiceName.MaximumLength);
+  RtlCopyMemory(Service->ServiceName.Buffer,
+               ServiceName->Buffer,
+               ServiceName->Length);
+  Service->ServiceName.Buffer[ServiceName->Length / sizeof(WCHAR)] = 0;
+
+  /* Build registry path */
+  Service->RegistryPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
+  Service->RegistryPath.Buffer = ExAllocatePool(NonPagedPool,
+                                               MAX_PATH * sizeof(WCHAR));
+  wcscpy(Service->RegistryPath.Buffer,
+        L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+  wcscat(Service->RegistryPath.Buffer,
+        Service->ServiceName.Buffer);
+  Service->RegistryPath.Length = wcslen(Service->RegistryPath.Buffer) * sizeof(WCHAR);
+
+  DPRINT("ServiceName: '%wZ'\n", &Service->ServiceName);
+  DPRINT("RegistryPath: '%wZ'\n", &Service->RegistryPath);
+  DPRINT("ServiceGroup: '%wZ'\n", &Service->ServiceGroup);
+  DPRINT("ImagePath: '%wZ'\n", &Service->ImagePath);
+  DPRINT("Start %lx  Type %lx  ErrorControl %lx\n",
+        Service->Start, Service->Type, Service->ErrorControl);
+
+  /* Append service entry */
+  InsertTailList(&ServiceListHead,
+                &Service->ServiceListEntry);
+
+  return(STATUS_SUCCESS);
+}
+
+
+NTSTATUS
+IoCreateDriverList(VOID)
+{
+  RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+  PKEY_BASIC_INFORMATION KeyInfo = NULL;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+  UNICODE_STRING ServicesKeyName;
+  UNICODE_STRING SubKeyName;
+  HANDLE KeyHandle;
+  NTSTATUS Status;
+  ULONG Index;
+
+  ULONG KeyInfoLength = 0;
+  ULONG ReturnedLength;
+
+  DPRINT("IoCreateDriverList() called\n");
+
+  /* Initialize basic variables */
+  InitializeListHead(&GroupListHead);
+  InitializeListHead(&ServiceListHead);
+
+  /* Build group order list */
+  RtlZeroMemory(&QueryTable,
+               sizeof(QueryTable));
+
+  QueryTable[0].Name = L"List";
+  QueryTable[0].QueryRoutine = IopCreateGroupListEntry;
+
+  Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
+                                 L"ServiceGroupOrder",
+                                 QueryTable,
+                                 NULL,
+                                 NULL);
+  if (!NT_SUCCESS(Status))
+    return(Status);
+
+  /* Enumerate services and create the service list */
+  RtlInitUnicodeStringFromLiteral(&ServicesKeyName,
+                      L"\\Registry\\Machine\\System\\CurrentControlSet\\Services");
+
+  InitializeObjectAttributes(&ObjectAttributes,
+                            &ServicesKeyName,
+                            OBJ_CASE_INSENSITIVE,
+                            NULL,
+                            NULL);
+
+  Status = NtOpenKey(&KeyHandle,
+                    0x10001,
+                    &ObjectAttributes);
+  if (!NT_SUCCESS(Status))
+    {
+      return(Status);
+    }
+
+  KeyInfoLength = sizeof(KEY_BASIC_INFORMATION) + MAX_PATH * sizeof(WCHAR);
+  KeyInfo = ExAllocatePool(NonPagedPool, KeyInfoLength);
+  if (KeyInfo == NULL)
+    {
+      NtClose(KeyHandle);
+      return(STATUS_INSUFFICIENT_RESOURCES);
+    }
+
+  Index = 0;
+  while (TRUE)
+    {
+      Status = NtEnumerateKey(KeyHandle,
+                             Index,
+                             KeyBasicInformation,
+                             KeyInfo,
+                             KeyInfoLength,
+                             &ReturnedLength);
+      if (NT_SUCCESS(Status))
+       {
+         if (KeyInfo->NameLength < MAX_PATH * sizeof(WCHAR))
+           {
+
+             SubKeyName.Length = KeyInfo->NameLength;
+             SubKeyName.MaximumLength = KeyInfo->NameLength + sizeof(WCHAR);
+             SubKeyName.Buffer = KeyInfo->Name;
+             SubKeyName.Buffer[SubKeyName.Length / sizeof(WCHAR)] = 0;
+
+             DPRINT("KeyName: '%wZ'\n", &SubKeyName);
+             IopCreateServiceListEntry(&SubKeyName);
+           }
+       }
+
+      if (!NT_SUCCESS(Status))
+       break;
+
+      Index++;
+    }
+
+  ExFreePool(KeyInfo);
+  NtClose(KeyHandle);
+
+  DPRINT("IoCreateDriverList() done\n");
+
+  return(STATUS_SUCCESS);
+}
+
+
+VOID
+LdrLoadAutoConfigDrivers(VOID)
+{
+  PLIST_ENTRY GroupEntry;
+  PLIST_ENTRY ServiceEntry;
+  PSERVICE_GROUP CurrentGroup;
+  PSERVICE CurrentService;
+  NTSTATUS Status;
+
+  CHAR TextBuffer [256];
+  ULONG x, y, cx, cy;
+
+  DPRINT("LdrLoadAutoConfigDrivers() called\n");
+
+  GroupEntry = GroupListHead.Flink;
+  while (GroupEntry != &GroupListHead)
+    {
+      CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
+
+      DPRINT("Group: %wZ\n", &CurrentGroup->GroupName);
+
+      ServiceEntry = ServiceListHead.Flink;
+      while (ServiceEntry != &ServiceListHead)
+       {
+         CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
+
+         if ((RtlCompareUnicodeString(&CurrentGroup->GroupName, &CurrentService->ServiceGroup, TRUE) == 0) &&
+             (CurrentService->Start == 1 /*SERVICE_SYSTEM_START*/))
+           {
+
+             HalQueryDisplayParameters(&x, &y, &cx, &cy);
+             RtlFillMemory(TextBuffer, x, ' ');
+             TextBuffer[x] = '\0';
+             HalSetDisplayParameters(0, y-1);
+             HalDisplayString(TextBuffer);
+
+             sprintf(TextBuffer, "Loading %S...\n", CurrentService->ServiceName.Buffer);
+             HalSetDisplayParameters(0, y-1);
+             HalDisplayString(TextBuffer);
+             HalSetDisplayParameters(cx, cy);
+
+             DPRINT("  Path: %wZ\n", &CurrentService->RegistryPath);
+             Status = NtLoadDriver(&CurrentService->RegistryPath);
+             if (!NT_SUCCESS(Status))
+               {
+                 DPRINT("NtLoadDriver() failed (Status %lx)\n", Status);
+#if 0
+                 if (CurrentService->ErrorControl == 1)
+                   {
+                     /* Log error */
+
+                   }
+                 else if (CurrentService->ErrorControl == 2)
+                   {
+                     if (IsLastKnownGood == FALSE)
+                       {
+                         /* Boot last known good configuration */
+
+                       }
+                   }
+                 else if (CurrentService->ErrorControl == 3)
+                   {
+                     if (IsLastKnownGood == FALSE)
+                       {
+                         /* Boot last known good configuration */
+
+                       }
+                     else
+                       {
+                         /* BSOD! */
+
+                       }
+                   }
+#endif
+               }
+           }
+         ServiceEntry = ServiceEntry->Flink;
+       }
+
+      GroupEntry = GroupEntry->Flink;
+    }
+
+  DPRINT("LdrLoadAutoConfigDrivers() done\n");
+}
+
+
+NTSTATUS
+IoDestroyDriverList(VOID)
+{
+  PLIST_ENTRY GroupEntry;
+  PLIST_ENTRY ServiceEntry;
+  PSERVICE_GROUP CurrentGroup;
+  PSERVICE CurrentService;
+
+  DPRINT("IoDestroyDriverList() called\n");
+
+  /* Destroy group list */
+  GroupEntry = GroupListHead.Flink;
+  while (GroupEntry != &GroupListHead)
+    {
+      CurrentGroup = CONTAINING_RECORD(GroupEntry, SERVICE_GROUP, GroupListEntry);
+
+      RtlFreeUnicodeString(&CurrentGroup->GroupName);
+      RemoveEntryList(GroupEntry);
+      ExFreePool(CurrentGroup);
+
+      GroupEntry = GroupListHead.Flink;
+    }
+
+  /* Destroy service list */
+  ServiceEntry = ServiceListHead.Flink;
+  while (ServiceEntry != &ServiceListHead)
+    {
+      CurrentService = CONTAINING_RECORD(ServiceEntry, SERVICE, ServiceListEntry);
+
+      RtlFreeUnicodeString(&CurrentService->ServiceName);
+      RtlFreeUnicodeString(&CurrentService->RegistryPath);
+      RtlFreeUnicodeString(&CurrentService->ServiceGroup);
+      RtlFreeUnicodeString(&CurrentService->ImagePath);
+      RemoveEntryList(ServiceEntry);
+      ExFreePool(CurrentService);
+
+      ServiceEntry = ServiceListHead.Flink;
+    }
+
+  DPRINT("IoDestroyDriverList() done\n");
+
+  return(STATUS_SUCCESS);
+}
+
+/* EOF */
index 8c69d61..dbbb00c 100644 (file)
@@ -1,11 +1,11 @@
-/* Do not edit - Machine generated */\r
-#ifndef _INC_REACTOS_BUILDNO\r
-#define _INC_REACTOS_BUILDNO\r
-#define KERNEL_VERSION_BUILD   36\r
-#define KERNEL_VERSION_BUILD_STR       "36"\r
-#define KERNEL_RELEASE_RC      "0.1.3.36\0"\r
-#define KERNEL_RELEASE_STR     "0.1.3.36"\r
-#define KERNEL_VERSION_RC      "0.1.3\0"\r
-#define KERNEL_VERSION_STR     "0.1.3"\r
-#endif\r
-/* EOF */\r
+/* Do not edit - Machine generated */
+#ifndef _INC_REACTOS_BUILDNO
+#define _INC_REACTOS_BUILDNO
+#define KERNEL_VERSION_BUILD   36
+#define KERNEL_VERSION_BUILD_STR       "36"
+#define KERNEL_RELEASE_RC      "0.1.3.36\0"
+#define KERNEL_RELEASE_STR     "0.1.3.36"
+#define KERNEL_VERSION_RC      "0.1.3\0"
+#define KERNEL_VERSION_STR     "0.1.3"
+#endif
+/* EOF */
index 9097082..2fbed4c 100644 (file)
@@ -1,85 +1,85 @@
-#\r
-#  ReactOS explorer\r
-#\r
-#  Makefile\r
-#\r
-\r
-PATH_TO_TOP = ../../..\r
-\r
-TARGET_TYPE = program\r
-\r
-TARGET_APPTYPE = windows\r
-\r
-TARGET_NAME = explorer\r
-\r
-TARGET_CFLAGS = -fexceptions -Os -DNDEBUG -DWIN32 -D_ROS_ -Wall -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501\r
-       \r
-TARGET_CPPFLAGS = -fexceptions -Os -DNDEBUG -DWIN32 -D_ROS_ -Wall -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501\r
-\r
-TARGET_RCFLAGS = -DNDEBUG -DWIN32 -D_ROS_\r
-\r
-ifdef UNICODE\r
-TARGET_CFLAGS += -DUNICODE\r
-TARGET_CPPFLAGS += -DUNICODE\r
-# MK_DEFENTRY = _wWinMain@16\r
-endif\r
-\r
-VPATH += shell\r
-VPATH += utility\r
-VPATH += taskbar\r
-VPATH += desktop\r
-VPATH += dialogs\r
-\r
-WINE_MODE = yes\r
-\r
-WINE_RC = $(TARGET_NAME)\r
-\r
-WINE_INCLUDE = ./\r
-\r
-TARGET_GCCLIBS = comctl32 ole32 uuid stdc++\r
-\r
-all: buildno.h explorer.exe\r
-       @strip explorer.exe\r
-\r
-buildno.h: ../../../include/reactos/buildno.h\r
-       updatebuildno\r
-\r
-TARGET_SDKLIBS = \\r
-       kernel32.a \\r
-       user32.a \\r
-       gdi32.a \\r
-       advapi32.a \\r
-       version.a\r
-\r
-TARGET_OBJECTS = \\r
-       startup.o \\r
-       shellclasses.o \\r
-       utility.o \\r
-       window.o \\r
-       dragdropimpl.o \\r
-       shellbrowserimpl.o \\r
-       explorer.o \\r
-       entries.o \\r
-       winfs.o \\r
-       unixfs.o \\r
-       shellfs.o \\r
-       mainframe.o \\r
-       filechild.o \\r
-       pane.o \\r
-       shellbrowser.o \\r
-       desktop.o \\r
-       desktopbar.o \\r
-       taskbar.o \\r
-       startmenu.o \\r
-       traynotify.o \\r
-       quicklaunch.o \\r
-       searchprogram.o\r
-\r
-include $(PATH_TO_TOP)/rules.mak\r
-\r
-include $(TOOLS_PATH)/helper.mk\r
-\r
-# overide LD_CC to use g++ for linking of the executable\r
-LD_CC = $(CXX)\r
-\r
-# EOF\r
+#
+#  ReactOS explorer
+#
+#  Makefile
+#
+
+PATH_TO_TOP = ../../..
+
+TARGET_TYPE = program
+
+TARGET_APPTYPE = windows
+
+TARGET_NAME = explorer
+
+TARGET_CFLAGS = -fexceptions -Os -DNDEBUG -DWIN32 -D_ROS_ -Wall -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501
+       
+TARGET_CPPFLAGS = -fexceptions -Os -DNDEBUG -DWIN32 -D_ROS_ -Wall -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501
+
+TARGET_RCFLAGS = -DNDEBUG -DWIN32 -D_ROS_
+
+ifdef UNICODE
+TARGET_CFLAGS += -DUNICODE
+TARGET_CPPFLAGS += -DUNICODE
+# MK_DEFENTRY = _wWinMain@16
+endif
+
+VPATH += shell
+VPATH += utility
+VPATH += taskbar
+VPATH += desktop
+VPATH += dialogs
+
+WINE_MODE = yes
+
+WINE_RC = $(TARGET_NAME)
+
+WINE_INCLUDE = ./
+
+TARGET_GCCLIBS = comctl32 ole32 uuid stdc++
+
+all: buildno.h explorer.exe
+       @strip explorer.exe
+
+buildno.h: ../../../include/reactos/buildno.h
+       updatebuildno
+
+TARGET_SDKLIBS = \
+       kernel32.a \
+       user32.a \
+       gdi32.a \
+       advapi32.a \
+       version.a
+
+TARGET_OBJECTS = \
+       startup.o \
+       shellclasses.o \
+       utility.o \
+       window.o \
+       dragdropimpl.o \
+       shellbrowserimpl.o \
+       explorer.o \
+       entries.o \
+       winfs.o \
+       unixfs.o \
+       shellfs.o \
+       mainframe.o \
+       filechild.o \
+       pane.o \
+       shellbrowser.o \
+       desktop.o \
+       desktopbar.o \
+       taskbar.o \
+       startmenu.o \
+       traynotify.o \
+       quicklaunch.o \
+       searchprogram.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
+
+# overide LD_CC to use g++ for linking of the executable
+LD_CC = $(CXX)
+
+# EOF
index aa00819..d45921c 100644 (file)
-/*\r
- *  ReactOS W32 Subsystem\r
- *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team\r
- *\r
- *  This program is free software; you can redistribute it and/or modify\r
- *  it under the terms of the GNU General Public License as published by\r
- *  the Free Software Foundation; either version 2 of the License, or\r
- *  (at your option) any later version.\r
- *\r
- *  This program is distributed in the hope that it will be useful,\r
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- *  GNU General Public License for more details.\r
- *\r
- *  You should have received a copy of the GNU General Public License\r
- *  along with this program; if not, write to the Free Software\r
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- */\r
-/* $Id: windc.c,v 1.29 2003/10/06 18:24:54 navaraf Exp $\r
- *\r
- * COPYRIGHT:        See COPYING in the top level directory\r
- * PROJECT:          ReactOS kernel\r
- * PURPOSE:          Window classes\r
- * FILE:             subsys/win32k/ntuser/class.c\r
- * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)\r
- * REVISION HISTORY:\r
- *       06-06-2001  CSH  Created\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#include <ddk/ntddk.h>\r
-#include <win32k/win32k.h>\r
-#include <win32k/region.h>\r
-#include <include/class.h>\r
-#include <include/error.h>\r
-#include <include/winsta.h>\r
-#include <include/msgqueue.h>\r
-#include <include/window.h>\r
-#include <include/rect.h>\r
-#include <include/dce.h>\r
-#include <include/vis.h>\r
-#include <include/object.h>\r
-\r
-#define NDEBUG\r
-#include <debug.h>\r
-\r
-/* GLOBALS *******************************************************************/\r
-\r
-static PDCE FirstDce = NULL;\r
-static HDC defaultDCstate;\r
-\r
-#define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \\r
-                              DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)\r
-\r
-/* FUNCTIONS *****************************************************************/\r
-\r
-HRGN STDCALL\r
-DceGetVisRgn(HWND hWnd, ULONG Flags, HWND hWndChild, ULONG CFlags)\r
-{\r
-  PWINDOW_OBJECT Window;\r
-  PWINDOW_OBJECT Child;\r
-  HRGN VisRgn;\r
-  HRGN VisChild;\r
-  HRGN ChildRect;\r
-  HRGN ParentRect;\r
-\r
-  Window = IntGetWindowObject(hWnd);\r
-\r
-  if (NULL == Window)\r
-    {\r
-      return NULL;\r
-    }\r
-\r
-  VisRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window,\r
-                                    0 == (Flags & DCX_WINDOW),\r
-                                    0 != (Flags & DCX_CLIPCHILDREN),\r
-                                    0 != (Flags & DCX_CLIPSIBLINGS));\r
-  if (NULL != hWndChild && 0 != (CFlags & DCX_CLIPCHILDREN))\r
-    {\r
-      /* We need to filter out the child windows of hWndChild */\r
-      Child = IntGetWindowObject(hWnd);\r
-      if (NULL != Child)\r
-       {\r
-    if (Child->FirstChild)\r
-           {\r
-             /* Compute the visible region of the child */\r
-             VisChild = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,\r
-                                                 Child, FALSE, TRUE, FALSE);\r
-             /* If the child doesn't obscure the whole window, we need to\r
-                 extend it. First compute the difference between window and child */\r
-             ChildRect = UnsafeIntCreateRectRgnIndirect(&(Child->ClientRect));\r
-             if (0 == (Flags & DCX_WINDOW))\r
-               {\r
-                 ParentRect = UnsafeIntCreateRectRgnIndirect(&(Window->ClientRect));\r
-               }\r
-             else\r
-               {\r
-                 ParentRect = UnsafeIntCreateRectRgnIndirect(&(Window->WindowRect));\r
-               }\r
-             NtGdiCombineRgn(ChildRect, ParentRect, ChildRect, RGN_DIFF);\r
-\r
-             /* Now actually extend the child by adding the difference */\r
-             NtGdiCombineRgn(VisChild, VisChild, ChildRect, RGN_OR);\r
-\r
-             /* Clip the childs children */\r
-             NtGdiCombineRgn(VisRgn, VisRgn, VisChild, RGN_AND);\r
-           }\r
-         IntReleaseWindowObject(Child);\r
-       }\r
-    }\r
-\r
-  IntReleaseWindowObject(Window);\r
-\r
-  return VisRgn;\r
-}\r
-\r
-HDC STDCALL\r
-NtUserGetDC(HWND hWnd)\r
-{\r
-    return NtUserGetDCEx(hWnd, NULL, NULL == hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE);\r
-}\r
-\r
-PDCE FASTCALL\r
-DceAllocDCE(HWND hWnd, DCE_TYPE Type)\r
-{\r
-  HDCE DceHandle;\r
-  DCE* Dce;\r
-\r
-  DceHandle = DCEOBJ_AllocDCE();\r
-  if(!DceHandle)\r
-    return NULL;\r
-  \r
-  Dce = DCEOBJ_LockDCE(DceHandle);\r
-  Dce->hDC = NtGdiCreateDC(L"DISPLAY", NULL, NULL, NULL);\r
-  if (NULL == defaultDCstate)\r
-    {\r
-      defaultDCstate = NtGdiGetDCState(Dce->hDC);\r
-      GDIOBJ_MarkObjectGlobal(defaultDCstate);\r
-    }\r
-  Dce->hwndCurrent = hWnd;\r
-  Dce->hClipRgn = NULL;\r
-  Dce->next = FirstDce;\r
-  FirstDce = Dce;\r
-\r
-  if (Type != DCE_CACHE_DC)\r
-    {\r
-      Dce->DCXFlags = DCX_DCEBUSY;\r
-      if (hWnd != NULL)\r
-       {\r
-         PWINDOW_OBJECT WindowObject;\r
-\r
-         WindowObject = IntGetWindowObject(hWnd);\r
-         if (WindowObject->Style & WS_CLIPCHILDREN)\r
-           {\r
-             Dce->DCXFlags |= DCX_CLIPCHILDREN;\r
-           }\r
-         if (WindowObject->Style & WS_CLIPSIBLINGS)\r
-           {\r
-             Dce->DCXFlags |= DCX_CLIPSIBLINGS;\r
-           }\r
-         IntReleaseWindowObject(WindowObject);\r
-       }\r
-    }\r
-  else\r
-    {\r
-      Dce->DCXFlags = DCX_CACHE | DCX_DCEEMPTY;\r
-    }\r
-\r
-  return(Dce);\r
-}\r
-\r
-VOID STATIC STDCALL\r
-DceSetDrawable(PWINDOW_OBJECT WindowObject, HDC hDC, ULONG Flags,\r
-              BOOL SetClipOrigin)\r
-{\r
-  DC *dc = DC_LockDc(hDC);\r
-  if(!dc)\r
-    return;\r
-  \r
-  if (WindowObject == NULL)\r
-    {\r
-      dc->w.DCOrgX = 0;\r
-      dc->w.DCOrgY = 0;\r
-    }\r
-  else\r
-    {\r
-      if (Flags & DCX_WINDOW)\r
-       {\r
-         dc->w.DCOrgX = WindowObject->WindowRect.left;\r
-         dc->w.DCOrgY = WindowObject->WindowRect.top;\r
-       }\r
-      else\r
-       {\r
-         dc->w.DCOrgX = WindowObject->ClientRect.left;\r
-         dc->w.DCOrgY = WindowObject->ClientRect.top;\r
-       }\r
-    }\r
-  DC_UnlockDc(hDC);\r
-}\r
-\r
-\r
-STATIC VOID FASTCALL\r
-DceDeleteClipRgn(DCE* Dce)\r
-{\r
-  Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN | DCX_WINDOWPAINT);\r
-\r
-  if (Dce->DCXFlags & DCX_KEEPCLIPRGN )\r
-    {\r
-      Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;\r
-    }\r
-  else if (Dce->hClipRgn > (HRGN) 1)\r
-    {\r
-      NtGdiDeleteObject(Dce->hClipRgn);\r
-    }\r
-\r
-  Dce->hClipRgn = NULL;\r
-\r
-  /* make it dirty so that the vis rgn gets recomputed next time */\r
-  Dce->DCXFlags |= DCX_DCEDIRTY;\r
-}\r
-\r
-STATIC INT FASTCALL\r
-DceReleaseDC(DCE* dce)\r
-{\r
-  if (DCX_DCEBUSY != (dce->DCXFlags & (DCX_DCEEMPTY | DCX_DCEBUSY)))\r
-    {\r
-      return 0;\r
-    }\r
-\r
-  /* restore previous visible region */\r
-\r
-  if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) &&\r
-      (dce->DCXFlags & (DCX_CACHE | DCX_WINDOWPAINT)) )\r
-    {\r
-      DceDeleteClipRgn( dce );\r
-    }\r
-\r
-  if (dce->DCXFlags & DCX_CACHE)\r
-    {\r
-      /* make the DC clean so that SetDCState doesn't try to update the vis rgn */\r
-      NtGdiSetHookFlags(dce->hDC, DCHF_VALIDATEVISRGN);\r
-      NtGdiSetDCState(dce->hDC, defaultDCstate);\r
-      dce->DCXFlags &= ~DCX_DCEBUSY;\r
-      if (dce->DCXFlags & DCX_DCEDIRTY)\r
-       {\r
-         /* don't keep around invalidated entries\r
-          * because SetDCState() disables hVisRgn updates\r
-          * by removing dirty bit. */\r
-         dce->hwndCurrent = 0;\r
-         dce->DCXFlags &= DCX_CACHE;\r
-         dce->DCXFlags |= DCX_DCEEMPTY;\r
-       }\r
-    }\r
-\r
-  return 1;\r
-}\r
-\r
-HDC STDCALL\r
-NtUserGetDCEx(HWND hWnd, HANDLE ClipRegion, ULONG Flags)\r
-{\r
-  PWINDOW_OBJECT Window;\r
-  ULONG DcxFlags;\r
-  DCE* Dce;\r
-  BOOL UpdateVisRgn = TRUE;\r
-  BOOL UpdateClipOrigin = FALSE;\r
-  HANDLE hRgnVisible = NULL;\r
-\r
-  if (NULL == hWnd)\r
-    {\r
-      Flags &= ~DCX_USESTYLE;\r
-      Window = NULL;\r
-    }\r
-  else if (NULL == (Window = IntGetWindowObject(hWnd)))\r
-    {\r
-      return(0);\r
-    }\r
-\r
-  if (NULL == Window || NULL == Window->Dce)\r
-    {\r
-      Flags |= DCX_CACHE;\r
-    }\r
-\r
-\r
-  if (Flags & DCX_USESTYLE)\r
-    {\r
-      Flags &= ~(DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP);\r
-\r
-      if (Window->Style & WS_CLIPSIBLINGS)\r
-       {\r
-         Flags |= DCX_CLIPSIBLINGS;\r
-       }\r
-\r
-      if (!(Flags & DCX_WINDOW))\r
-       {\r
-         if (Window->Class->style & CS_PARENTDC)\r
-           {\r
-             Flags |= DCX_PARENTCLIP;\r
-           }\r
-\r
-         if (Window->Style & WS_CLIPCHILDREN &&\r
-             !(Window->Style & WS_MINIMIZE))\r
-           {\r
-             Flags |= DCX_CLIPCHILDREN;\r
-           }\r
-       }\r
-      else\r
-       {\r
-         Flags |= DCX_CACHE;\r
-       }\r
-    }\r
-\r
-  if (Flags & DCX_NOCLIPCHILDREN)\r
-    {\r
-      Flags |= DCX_CACHE;\r
-      Flags |= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN);\r
-    }\r
-\r
-  if (Flags & DCX_WINDOW)\r
-    {\r
-      Flags = (Flags & ~DCX_CLIPCHILDREN) | DCX_CACHE;\r
-    }\r
-\r
-  if (NULL == Window || !(Window->Style & WS_CHILD) || NULL == Window->Parent)\r
-    {\r
-      Flags &= ~DCX_PARENTCLIP;\r
-    }\r
-  else if (Flags & DCX_PARENTCLIP)\r
-    {\r
-      Flags |= DCX_CACHE;\r
-      if (!(Flags & (DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS)))\r
-       {\r
-         if ((Window->Style & WS_VISIBLE) && \r
-             (Window->Parent->Style & WS_VISIBLE))\r
-           {\r
-             Flags &= ~DCX_CLIPCHILDREN;\r
-             if (Window->Parent->Style & WS_CLIPSIBLINGS)\r
-               {\r
-                 Flags |= DCX_CLIPSIBLINGS;\r
-               }\r
-           }\r
-       }\r
-    }\r
-\r
-  DcxFlags = Flags & DCX_CACHECOMPAREMASK;\r
-\r
-  if (Flags & DCX_CACHE)\r
-    {\r
-      DCE* DceEmpty = NULL;\r
-      DCE* DceUnused = NULL;\r
-\r
-      for (Dce = FirstDce; Dce != NULL; Dce = Dce->next)\r
-       {\r
-         if ((Dce->DCXFlags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE)\r
-           {\r
-             DceUnused = Dce;\r
-             if (Dce->DCXFlags & DCX_DCEEMPTY)\r
-               {\r
-                 DceEmpty = Dce;\r
-               }\r
-             else if (Dce->hwndCurrent == hWnd &&\r
-                      ((Dce->DCXFlags & DCX_CACHECOMPAREMASK) == DcxFlags))\r
-               {\r
-#if 0 /* FIXME */\r
-                 UpdateVisRgn = FALSE;\r
-#endif\r
-                 UpdateClipOrigin = TRUE;\r
-                 break;\r
-               }\r
-           }\r
-       }\r
-\r
-      if (Dce == NULL)\r
-       {\r
-         Dce = (DceEmpty == NULL) ? DceEmpty : DceUnused;\r
-       }\r
-\r
-      if (Dce == NULL)\r
-       {\r
-         Dce = DceAllocDCE(NULL, DCE_CACHE_DC);\r
-       }\r
-    }\r
-  else\r
-    {\r
-      Dce = Window->Dce;\r
-      /* FIXME: Implement this. */\r
-      DbgBreakPoint();\r
-    }\r
-\r
-  if (NULL == Dce)\r
-    {\r
-      if(NULL != Window)\r
-        IntReleaseWindowObject(Window);\r
-      return(NULL);\r
-    }\r
-\r
-  Dce->hwndCurrent = hWnd;\r
-  Dce->hClipRgn = NULL;\r
-  Dce->DCXFlags = DcxFlags | (Flags & DCX_WINDOWPAINT) | DCX_DCEBUSY;\r
-\r
-  if (0 == (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) && NULL != ClipRegion)\r
-    {\r
-      NtGdiDeleteObject(ClipRegion);\r
-      ClipRegion = NULL;\r
-    }\r
-\r
-  if (NULL != Dce->hClipRgn)\r
-    {\r
-      DceDeleteClipRgn(Dce);\r
-    }\r
-\r
-  if (NULL != ClipRegion)\r
-    {\r
-      Dce->hClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);\r
-      if(Dce->hClipRgn)\r
-        NtGdiCombineRgn(Dce->hClipRgn, ClipRegion, NULL, RGN_COPY);\r
-      NtGdiDeleteObject(ClipRegion);\r
-    }\r
-\r
-  DceSetDrawable(Window, Dce->hDC, Flags, UpdateClipOrigin);\r
-\r
-  if (UpdateVisRgn)\r
-    {\r
-      if (Flags & DCX_PARENTCLIP)\r
-       {\r
-         PWINDOW_OBJECT Parent;\r
-\r
-         Parent = Window->Parent;\r
-\r
-         if (Window->Style & WS_VISIBLE &&\r
-             !(Parent->Style & WS_MINIMIZE))\r
-           {\r
-             if (Parent->Style & WS_CLIPSIBLINGS)\r
-               {\r
-                 DcxFlags = DCX_CLIPSIBLINGS | \r
-                   (Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));\r
-               }\r
-             else\r
-               {\r
-                 DcxFlags = Flags & \r
-                   ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);\r
-               }\r
-             hRgnVisible = DceGetVisRgn(Parent->Self, DcxFlags, \r
-                                        Window->Self, Flags);\r
-           }\r
-         else\r
-           {\r
-             hRgnVisible = NtGdiCreateRectRgn(0, 0, 0, 0);\r
-           }\r
-       }\r
-      else\r
-       {\r
-         if (hWnd == IntGetDesktopWindow())\r
-           {\r
-             hRgnVisible = \r
-               NtGdiCreateRectRgn(0, 0, \r
-                                 NtUserGetSystemMetrics(SM_CXSCREEN),\r
-                                 NtUserGetSystemMetrics(SM_CYSCREEN));\r
-           }\r
-         else\r
-           {\r
-             hRgnVisible = DceGetVisRgn(hWnd, Flags, 0, 0);\r
-           }\r
-       }\r
-\r
-      if (0 != (Flags & DCX_INTERSECTRGN))\r
-       {\r
-         NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_AND);\r
-       }\r
-\r
-      if (0 != (Flags & DCX_EXCLUDERGN))\r
-       {\r
-         NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_DIFF);\r
-       }\r
-\r
-      Dce->DCXFlags &= ~DCX_DCEDIRTY;\r
-      NtGdiSelectVisRgn(Dce->hDC, hRgnVisible);\r
-    }\r
-\r
-  if (hRgnVisible != NULL)\r
-    {\r
-      NtGdiDeleteObject(hRgnVisible);\r
-    }\r
-  if (NULL != Window)\r
-    {\r
-      IntReleaseWindowObject(Window);\r
-    }\r
-\r
-  return(Dce->hDC);\r
-}\r
-\r
-BOOL FASTCALL\r
-DCE_InternalDelete(PDCE Dce)\r
-{\r
-  PDCE PrevInList;\r
-\r
-  if (Dce == FirstDce)\r
-    {\r
-      FirstDce = Dce->next;\r
-      PrevInList = Dce;\r
-    }\r
-  else\r
-    {\r
-      for (PrevInList = FirstDce; NULL != PrevInList; PrevInList = PrevInList->next)\r
-       {\r
-         if (Dce == PrevInList->next)\r
-           {\r
-             PrevInList->next = Dce->next;\r
-             break;\r
-           }\r
-       }\r
-      assert(NULL != PrevInList);\r
-    }\r
-\r
-  return NULL != PrevInList;\r
-}\r
-\r
-HWND FASTCALL\r
-IntWindowFromDC(HDC hDc)\r
-{\r
-  DCE *Dce;\r
-  for (Dce = FirstDce; Dce != NULL; Dce = Dce->next)\r
-  {\r
-    if(Dce->hDC == hDc)\r
-    {\r
-      return Dce->hwndCurrent;\r
-    }\r
-  }\r
-  return 0;\r
-}\r
-\r
-INT STDCALL\r
-NtUserReleaseDC(HWND hWnd, HDC hDc)\r
-{\r
-  DCE *dce;\r
-  INT nRet = 0;\r
-\r
-  /* FIXME USER_Lock(); */\r
-  dce = FirstDce;\r
-\r
-  DPRINT("%p %p\n", hWnd, hDc);\r
-\r
-  while (dce && (dce->hDC != hDc))\r
-    {\r
-      dce = dce->next;\r
-    }\r
-\r
-  if (dce && (dce->DCXFlags & DCX_DCEBUSY))\r
-    {\r
-      nRet = DceReleaseDC(dce);\r
-    }\r
-\r
-  /* FIXME USER_Unlock(); */\r
-\r
-  return nRet;\r
-}\r
-  \r
-\r
-/* EOF */\r
+/*
+ *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/* $Id: windc.c,v 1.30 2003/10/06 18:49:50 navaraf Exp $
+ *
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * PURPOSE:          Window classes
+ * FILE:             subsys/win32k/ntuser/class.c
+ * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * REVISION HISTORY:
+ *       06-06-2001  CSH  Created
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ddk/ntddk.h>
+#include <win32k/win32k.h>
+#include <win32k/region.h>
+#include <include/class.h>
+#include <include/error.h>
+#include <include/winsta.h>
+#include <include/msgqueue.h>
+#include <include/window.h>
+#include <include/rect.h>
+#include <include/dce.h>
+#include <include/vis.h>
+#include <include/object.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
+
+static PDCE FirstDce = NULL;
+static HDC defaultDCstate;
+
+#define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
+                              DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)
+
+/* FUNCTIONS *****************************************************************/
+
+HRGN STDCALL
+DceGetVisRgn(HWND hWnd, ULONG Flags, HWND hWndChild, ULONG CFlags)
+{
+  PWINDOW_OBJECT Window;
+  PWINDOW_OBJECT Child;
+  HRGN VisRgn;
+  HRGN VisChild;
+  HRGN ChildRect;
+  HRGN ParentRect;
+
+  Window = IntGetWindowObject(hWnd);
+
+  if (NULL == Window)
+    {
+      return NULL;
+    }
+
+  VisRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window,
+                                    0 == (Flags & DCX_WINDOW),
+                                    0 != (Flags & DCX_CLIPCHILDREN),
+                                    0 != (Flags & DCX_CLIPSIBLINGS));
+  if (NULL != hWndChild && 0 != (CFlags & DCX_CLIPCHILDREN))
+    {
+      /* We need to filter out the child windows of hWndChild */
+      Child = IntGetWindowObject(hWnd);
+      if (NULL != Child)
+       {
+    if (Child->FirstChild)
+           {
+             /* Compute the visible region of the child */
+             VisChild = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
+                                                 Child, FALSE, TRUE, FALSE);
+             /* If the child doesn't obscure the whole window, we need to
+                 extend it. First compute the difference between window and child */
+             ChildRect = UnsafeIntCreateRectRgnIndirect(&(Child->ClientRect));
+             if (0 == (Flags & DCX_WINDOW))
+               {
+                 ParentRect = UnsafeIntCreateRectRgnIndirect(&(Window->ClientRect));
+               }
+             else
+               {
+                 ParentRect = UnsafeIntCreateRectRgnIndirect(&(Window->WindowRect));
+               }
+             NtGdiCombineRgn(ChildRect, ParentRect, ChildRect, RGN_DIFF);
+
+             /* Now actually extend the child by adding the difference */
+             NtGdiCombineRgn(VisChild, VisChild, ChildRect, RGN_OR);
+
+             /* Clip the childs children */
+             NtGdiCombineRgn(VisRgn, VisRgn, VisChild, RGN_AND);
+           }
+         IntReleaseWindowObject(Child);
+       }
+    }
+
+  IntReleaseWindowObject(Window);
+
+  return VisRgn;
+}
+
+HDC STDCALL
+NtUserGetDC(HWND hWnd)
+{
+    return NtUserGetDCEx(hWnd, NULL, NULL == hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE);
+}
+
+PDCE FASTCALL
+DceAllocDCE(HWND hWnd, DCE_TYPE Type)
+{
+  HDCE DceHandle;
+  DCE* Dce;
+
+  DceHandle = DCEOBJ_AllocDCE();
+  if(!DceHandle)
+    return NULL;
+  
+  Dce = DCEOBJ_LockDCE(DceHandle);
+  Dce->hDC = NtGdiCreateDC(L"DISPLAY", NULL, NULL, NULL);
+  if (NULL == defaultDCstate)
+    {
+      defaultDCstate = NtGdiGetDCState(Dce->hDC);
+      GDIOBJ_MarkObjectGlobal(defaultDCstate);
+    }
+  Dce->hwndCurrent = hWnd;
+  Dce->hClipRgn = NULL;
+  Dce->next = FirstDce;
+  FirstDce = Dce;
+
+  if (Type != DCE_CACHE_DC)
+    {
+      Dce->DCXFlags = DCX_DCEBUSY;
+      if (hWnd != NULL)
+       {
+         PWINDOW_OBJECT WindowObject;
+
+         WindowObject = IntGetWindowObject(hWnd);
+         if (WindowObject->Style & WS_CLIPCHILDREN)
+           {
+             Dce->DCXFlags |= DCX_CLIPCHILDREN;
+           }
+         if (WindowObject->Style & WS_CLIPSIBLINGS)
+           {
+             Dce->DCXFlags |= DCX_CLIPSIBLINGS;
+           }
+         IntReleaseWindowObject(WindowObject);
+       }
+    }
+  else
+    {
+      Dce->DCXFlags = DCX_CACHE | DCX_DCEEMPTY;
+    }
+
+  return(Dce);
+}
+
+VOID STATIC STDCALL
+DceSetDrawable(PWINDOW_OBJECT WindowObject, HDC hDC, ULONG Flags,
+              BOOL SetClipOrigin)
+{
+  DC *dc = DC_LockDc(hDC);
+  if(!dc)
+    return;
+  
+  if (WindowObject == NULL)
+    {
+      dc->w.DCOrgX = 0;
+      dc->w.DCOrgY = 0;
+    }
+  else
+    {
+      if (Flags & DCX_WINDOW)
+       {
+         dc->w.DCOrgX = WindowObject->WindowRect.left;
+         dc->w.DCOrgY = WindowObject->WindowRect.top;
+       }
+      else
+       {
+         dc->w.DCOrgX = WindowObject->ClientRect.left;
+         dc->w.DCOrgY = WindowObject->ClientRect.top;
+       }
+    }
+  DC_UnlockDc(hDC);
+}
+
+
+STATIC VOID FASTCALL
+DceDeleteClipRgn(DCE* Dce)
+{
+  Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN | DCX_WINDOWPAINT);
+
+  if (Dce->DCXFlags & DCX_KEEPCLIPRGN )
+    {
+      Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
+    }
+  else if (Dce->hClipRgn > (HRGN) 1)
+    {
+      NtGdiDeleteObject(Dce->hClipRgn);
+    }
+
+  Dce->hClipRgn = NULL;
+
+  /* make it dirty so that the vis rgn gets recomputed next time */
+  Dce->DCXFlags |= DCX_DCEDIRTY;
+}
+
+STATIC INT FASTCALL
+DceReleaseDC(DCE* dce)
+{
+  if (DCX_DCEBUSY != (dce->DCXFlags & (DCX_DCEEMPTY | DCX_DCEBUSY)))
+    {
+      return 0;
+    }
+
+  /* restore previous visible region */
+
+  if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) &&
+      (dce->DCXFlags & (DCX_CACHE | DCX_WINDOWPAINT)) )
+    {
+      DceDeleteClipRgn( dce );
+    }
+
+  if (dce->DCXFlags & DCX_CACHE)
+    {
+      /* make the DC clean so that SetDCState doesn't try to update the vis rgn */
+      NtGdiSetHookFlags(dce->hDC, DCHF_VALIDATEVISRGN);
+      NtGdiSetDCState(dce->hDC, defaultDCstate);
+      dce->DCXFlags &= ~DCX_DCEBUSY;
+      if (dce->DCXFlags & DCX_DCEDIRTY)
+       {
+         /* don't keep around invalidated entries
+          * because SetDCState() disables hVisRgn updates
+          * by removing dirty bit. */
+         dce->hwndCurrent = 0;
+         dce->DCXFlags &= DCX_CACHE;
+         dce->DCXFlags |= DCX_DCEEMPTY;
+       }
+    }
+
+  return 1;
+}
+
+HDC STDCALL
+NtUserGetDCEx(HWND hWnd, HANDLE ClipRegion, ULONG Flags)
+{
+  PWINDOW_OBJECT Window;
+  ULONG DcxFlags;
+  DCE* Dce;
+  BOOL UpdateVisRgn = TRUE;
+  BOOL UpdateClipOrigin = FALSE;
+  HANDLE hRgnVisible = NULL;
+
+  if (NULL == hWnd)
+    {
+      Flags &= ~DCX_USESTYLE;
+      Window = NULL;
+    }
+  else if (NULL == (Window = IntGetWindowObject(hWnd)))
+    {
+      return(0);
+    }
+
+  if (NULL == Window || NULL == Window->Dce)
+    {
+      Flags |= DCX_CACHE;
+    }
+
+
+  if (Flags & DCX_USESTYLE)
+    {
+      Flags &= ~(DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP);
+
+      if (Window->Style & WS_CLIPSIBLINGS)
+       {
+         Flags |= DCX_CLIPSIBLINGS;
+       }
+
+      if (!(Flags & DCX_WINDOW))
+       {
+         if (Window->Class->style & CS_PARENTDC)
+           {
+             Flags |= DCX_PARENTCLIP;
+           }
+
+         if (Window->Style & WS_CLIPCHILDREN &&
+             !(Window->Style & WS_MINIMIZE))
+           {
+             Flags |= DCX_CLIPCHILDREN;
+           }
+       }
+      else
+       {
+         Flags |= DCX_CACHE;
+       }
+    }
+
+  if (Flags & DCX_NOCLIPCHILDREN)
+    {
+      Flags |= DCX_CACHE;
+      Flags |= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN);
+    }
+
+  if (Flags & DCX_WINDOW)
+    {
+      Flags = (Flags & ~DCX_CLIPCHILDREN) | DCX_CACHE;
+    }
+
+  if (NULL == Window || !(Window->Style & WS_CHILD) || NULL == Window->Parent)
+    {
+      Flags &= ~DCX_PARENTCLIP;
+    }
+  else if (Flags & DCX_PARENTCLIP)
+    {
+      Flags |= DCX_CACHE;
+      if (!(Flags & (DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS)))
+       {
+         if ((Window->Style & WS_VISIBLE) && 
+             (Window->Parent->Style & WS_VISIBLE))
+           {
+             Flags &= ~DCX_CLIPCHILDREN;
+             if (Window->Parent->Style & WS_CLIPSIBLINGS)
+               {
+                 Flags |= DCX_CLIPSIBLINGS;
+               }
+           }
+       }
+    }
+
+  DcxFlags = Flags & DCX_CACHECOMPAREMASK;
+
+  if (Flags & DCX_CACHE)
+    {
+      DCE* DceEmpty = NULL;
+      DCE* DceUnused = NULL;
+
+      for (Dce = FirstDce; Dce != NULL; Dce = Dce->next)
+       {
+         if ((Dce->DCXFlags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE)
+           {
+             DceUnused = Dce;
+             if (Dce->DCXFlags & DCX_DCEEMPTY)
+               {
+                 DceEmpty = Dce;
+               }
+             else if (Dce->hwndCurrent == hWnd &&
+                      ((Dce->DCXFlags & DCX_CACHECOMPAREMASK) == DcxFlags))
+               {
+#if 0 /* FIXME */
+                 UpdateVisRgn = FALSE;
+#endif
+                 UpdateClipOrigin = TRUE;
+                 break;
+               }
+           }
+       }
+
+      if (Dce == NULL)
+       {
+         Dce = (DceEmpty == NULL) ? DceEmpty : DceUnused;
+       }
+
+      if (Dce == NULL)
+       {
+         Dce = DceAllocDCE(NULL, DCE_CACHE_DC);
+       }
+    }
+  else
+    {
+      Dce = Window->Dce;
+      /* FIXME: Implement this. */
+      DbgBreakPoint();
+    }
+
+  if (NULL == Dce)
+    {
+      if(NULL != Window)
+        IntReleaseWindowObject(Window);
+      return(NULL);
+    }
+
+  Dce->hwndCurrent = hWnd;
+  Dce->hClipRgn = NULL;
+  Dce->DCXFlags = DcxFlags | (Flags & DCX_WINDOWPAINT) | DCX_DCEBUSY;
+
+  if (0 == (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) && NULL != ClipRegion)
+    {
+      NtGdiDeleteObject(ClipRegion);
+      ClipRegion = NULL;
+    }
+
+  if (NULL != Dce->hClipRgn)
+    {
+      DceDeleteClipRgn(Dce);
+    }
+
+  if (NULL != ClipRegion)
+    {
+      Dce->hClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
+      if(Dce->hClipRgn)
+        NtGdiCombineRgn(Dce->hClipRgn, ClipRegion, NULL, RGN_COPY);
+      NtGdiDeleteObject(ClipRegion);
+    }
+
+  DceSetDrawable(Window, Dce->hDC, Flags, UpdateClipOrigin);
+
+  if (UpdateVisRgn)
+    {
+      if (Flags & DCX_PARENTCLIP)
+       {
+         PWINDOW_OBJECT Parent;
+
+         Parent = Window->Parent;
+
+         if (Window->Style & WS_VISIBLE &&
+             !(Parent->Style & WS_MINIMIZE))
+           {
+             if (Parent->Style & WS_CLIPSIBLINGS)
+               {
+                 DcxFlags = DCX_CLIPSIBLINGS | 
+                   (Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
+               }
+             else
+               {
+                 DcxFlags = Flags & 
+                   ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
+               }
+             hRgnVisible = DceGetVisRgn(Parent->Self, DcxFlags, 
+                                        Window->Self, Flags);
+           }
+         else
+           {
+             hRgnVisible = NtGdiCreateRectRgn(0, 0, 0, 0);
+           }
+       }
+      else
+       {
+         if (hWnd == IntGetDesktopWindow())
+           {
+             hRgnVisible = 
+               NtGdiCreateRectRgn(0, 0, 
+                                 NtUserGetSystemMetrics(SM_CXSCREEN),
+                                 NtUserGetSystemMetrics(SM_CYSCREEN));
+           }
+         else
+           {
+             hRgnVisible = DceGetVisRgn(hWnd, Flags, 0, 0);
+           }
+       }
+
+      if (0 != (Flags & DCX_INTERSECTRGN))
+       {
+         NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_AND);
+       }
+
+      if (0 != (Flags & DCX_EXCLUDERGN))
+       {
+         NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_DIFF);
+       }
+
+      Dce->DCXFlags &= ~DCX_DCEDIRTY;
+      NtGdiSelectVisRgn(Dce->hDC, hRgnVisible);
+    }
+
+  if (hRgnVisible != NULL)
+    {
+      NtGdiDeleteObject(hRgnVisible);
+    }
+  if (NULL != Window)
+    {
+      IntReleaseWindowObject(Window);
+    }
+
+  return(Dce->hDC);
+}
+
+BOOL FASTCALL
+DCE_InternalDelete(PDCE Dce)
+{
+  PDCE PrevInList;
+
+  if (Dce == FirstDce)
+    {
+      FirstDce = Dce->next;
+      PrevInList = Dce;
+    }
+  else
+    {
+      for (PrevInList = FirstDce; NULL != PrevInList; PrevInList = PrevInList->next)
+       {
+         if (Dce == PrevInList->next)
+           {
+             PrevInList->next = Dce->next;
+             break;
+           }
+       }
+      assert(NULL != PrevInList);
+    }
+
+  return NULL != PrevInList;
+}
+
+HWND FASTCALL
+IntWindowFromDC(HDC hDc)
+{
+  DCE *Dce;
+  for (Dce = FirstDce; Dce != NULL; Dce = Dce->next)
+  {
+    if(Dce->hDC == hDc)
+    {
+      return Dce->hwndCurrent;
+    }
+  }
+  return 0;
+}
+
+INT STDCALL
+NtUserReleaseDC(HWND hWnd, HDC hDc)
+{
+  DCE *dce;
+  INT nRet = 0;
+
+  /* FIXME USER_Lock(); */
+  dce = FirstDce;
+
+  DPRINT("%p %p\n", hWnd, hDc);
+
+  while (dce && (dce->hDC != hDc))
+    {
+      dce = dce->next;
+    }
+
+  if (dce && (dce->DCXFlags & DCX_DCEBUSY))
+    {
+      nRet = DceReleaseDC(dce);
+    }
+
+  /* FIXME USER_Unlock(); */
+
+  return nRet;
+}
+  
+
+/* EOF */