From 91aeffd9314b990c0d3a5def1acfe76aa3b3fa09 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Mon, 6 Oct 2003 18:24:54 +0000 Subject: [PATCH] I commited more files than I wanted by mistake. :( This patch reverses most of the changes and addes commit message for the others. reactos/config - Reversed reactos/lib/gdi32/objects/bitblt.c - Reversed reactos/lib/kernel32/process/create.c - Added output of user mode exception address. reactos/lib/user32/controls/button.c - Fixed debug print reactos/lib/user32/windows/bitmap.c - Reversed reactos/ntoskrnl/cm/rtlfunc.c - Reversed reactos/ntoskrnl/io/driver.c - Reversed reactos/subsys/system/explorer/buildno.h - Updated reactos/subsys/system/explorer/explorer_intres.rc - Changed VK_S and VK_X to numeric values, because MinGW doesn't have these constants. reactos/subsys/system/explorer/makefile - Reversed reactos/subsys/win32k/ntuser/windc.c - Reversed svn path=/trunk/; revision=6255 --- reactos/config | 76 +- reactos/lib/gdi32/objects/bitblt.c | 772 +++++----- reactos/lib/user32/windows/bitmap.c | 1245 +++++++-------- reactos/ntoskrnl/cm/rtlfunc.c | 1524 +++++++++---------- reactos/ntoskrnl/io/driver.c | 1508 +++++++++--------- reactos/subsys/system/explorer/makefile_rex | 170 +-- reactos/subsys/win32k/ntuser/windc.c | 1119 +++++++------- 7 files changed, 3143 insertions(+), 3271 deletions(-) diff --git a/reactos/config b/reactos/config index c00c17bc693..f806bdf43a1 100644 --- a/reactos/config +++ b/reactos/config @@ -1,38 +1,38 @@ -# -# 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 := 1 - -# -# Whether to use Structured Exception Handling -# -SEH := 0 - - -# -# Which version of NDIS do we support up to? -# -#NDISVERSION=NDIS50 - +# +# 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 + diff --git a/reactos/lib/gdi32/objects/bitblt.c b/reactos/lib/gdi32/objects/bitblt.c index 6f2942fd3cc..dd0616de300 100644 --- a/reactos/lib/gdi32/objects/bitblt.c +++ b/reactos/lib/gdi32/objects/bitblt.c @@ -1,386 +1,386 @@ -#ifdef UNICODE -#undef UNICODE -#endif - -#undef WIN32_LEAN_AND_MEAN -#include -#include -#include -#include - -/* - * @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 TRUE; -} - - -/* - * @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) - -*/ +#ifdef UNICODE +#undef UNICODE +#endif + +#undef WIN32_LEAN_AND_MEAN +#include +#include +#include +#include + +/* + * @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) + +*/ diff --git a/reactos/lib/user32/windows/bitmap.c b/reactos/lib/user32/windows/bitmap.c index c47bd5396a8..b4833935850 100644 --- a/reactos/lib/user32/windows/bitmap.c +++ b/reactos/lib/user32/windows/bitmap.c @@ -1,622 +1,623 @@ -/* - * 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.15 2003/10/06 17:53:55 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 -#include -#include -#include -#include - -/*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: - 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)); -} +/* + * 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.16 2003/10/06 18:24:54 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 +#include +#include +#include +#include + +/*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)); +} diff --git a/reactos/ntoskrnl/cm/rtlfunc.c b/reactos/ntoskrnl/cm/rtlfunc.c index 0df054daa34..4b97ba2d012 100644 --- a/reactos/ntoskrnl/cm/rtlfunc.c +++ b/reactos/ntoskrnl/cm/rtlfunc.c @@ -1,768 +1,756 @@ -/* - * 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 -#include -#include -#include -#include -#include - -#define NDEBUG -#include - -#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 */ - - -#define HACK - -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) - { -#ifdef HACK - ULONG PreviousMode; - extern VOID KeSetPreviousMode(ULONG Mode); - - PreviousMode = KeGetPreviousMode(); - KeSetPreviousMode(KernelMode); -#endif - Status = NtDuplicateObject(NtCurrentProcess(), - (HANDLE)Path, - NtCurrentProcess(), - KeyHandle, - 0, - FALSE, - DUPLICATE_SAME_ACCESS); -#ifdef HACK - KeSetPreviousMode(PreviousMode); -#endif - 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 */ +/* + * 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 +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +#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 */ diff --git a/reactos/ntoskrnl/io/driver.c b/reactos/ntoskrnl/io/driver.c index 690cc5bec23..cfb355570a1 100644 --- a/reactos/ntoskrnl/io/driver.c +++ b/reactos/ntoskrnl/io/driver.c @@ -1,812 +1,696 @@ -/* $Id: driver.c,v 1.19 2003/10/06 17:53:55 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 -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define NDEBUG -#include - -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') - -/* PRIVATE 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"); -} - -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); -} - -/* - * IopGetDriverNameFromKeyNode - * - * Returns a module path from service registry key node. - * - * Parameters - * ImagePath - * The result path. - * KeyHandle - * Registry handle for service registry key node - * (\Registry\Machine\System\CurrentControlSet\Services\...) - * - * Return Value - * Status - */ - -NTSTATUS STDCALL -IopGetDriverNameFromKeyNode(PUNICODE_STRING ImagePath, HANDLE KeyHandle) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - UNICODE_STRING RegistryImagePath; - NTSTATUS Status; - - RtlZeroMemory(&QueryTable, sizeof(QueryTable)); - RtlInitUnicodeString(&RegistryImagePath, NULL); - - QueryTable[0].Name = L"ImagePath"; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT; - QueryTable[0].EntryContext = &RegistryImagePath; - - Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, - (PWSTR)KeyHandle, QueryTable, NULL, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status); - RtlFreeUnicodeString(&RegistryImagePath); - return STATUS_UNSUCCESSFUL; - } - - if (RegistryImagePath.Length == 0) - { - return STATUS_UNSUCCESSFUL; - } else - if (RegistryImagePath.Buffer[0] != L'\\') - { - ImagePath->Length = sizeof(UNICODE_NULL) + - ((12 + wcslen(RegistryImagePath.Buffer)) * sizeof(WCHAR)); - ImagePath->Buffer = ExAllocatePool(NonPagedPool, ImagePath->Length); - if (ImagePath->Buffer == NULL) - { - RtlFreeUnicodeString(&RegistryImagePath); - return STATUS_UNSUCCESSFUL; - } - wcscpy(ImagePath->Buffer, L"\\SystemRoot\\"); - wcscat(ImagePath->Buffer, RegistryImagePath.Buffer); - RtlFreeUnicodeString(&RegistryImagePath); - } else - { - ImagePath->Length = RegistryImagePath.Length; - ImagePath->Buffer = RegistryImagePath.Buffer; - } - - return STATUS_SUCCESS; -} - -/* - * IopUnloadDriver - * - * Unloads a device driver. - * - * Parameters - * DriverServiceName - * Name of the service to unload (registry key). - * UnloadPnpDrivers - * Whether to unload Plug & Plug or only legacy drivers. If this - * parameter is set to FALSE, the routine will unload only legacy - * drivers. - * - * Return Value - * Status - * - * To do - * Guard the whole function by SEH. - */ - -NTSTATUS STDCALL -IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers) -{ - UNICODE_STRING ImagePath; - UNICODE_STRING ObjectName; - PDRIVER_OBJECT DriverObject; - PMODULE_OBJECT ModuleObject; - HANDLE KeyHandle; - NTSTATUS Status; - LPWSTR Start; - - DPRINT("IopUnloadDriver('%wZ', %d)\n", DriverServiceName, UnloadPnpDrivers); - - /* - * Get the service name from the module name - */ - Start = wcsrchr(DriverServiceName->Buffer, L'\\'); - if (Start == NULL) - Start = DriverServiceName->Buffer; - else - Start++; - - /* - * Construct the driver object name - */ - 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; - } - - /* - * Free the buffer for driver object name - */ - ExFreePool(ObjectName.Buffer); - - /* - * Get path of service... - */ - Status = RtlpGetRegistryHandle(RTL_REGISTRY_ABSOLUTE, - DriverServiceName->Buffer, FALSE, &KeyHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status); - return Status; - } - Status = IopGetDriverNameFromKeyNode(&ImagePath, KeyHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT("IopGetDriverNameFromKeyNode() failed (Status %x)\n", Status); - NtClose(KeyHandle); - return Status; - } - NtClose(KeyHandle); - - /* - * ... and check if it's loaded - */ - ModuleObject = LdrGetModuleObject(&ImagePath); - if (ModuleObject == NULL) - { - return STATUS_UNSUCCESSFUL; - } - - /* - * Free the service path - */ - RtlFreeUnicodeString(&ImagePath); - - /* - * 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; -} - -/* FUNCTIONS ******************************************************************/ - -/* - * NtLoadDriver - * - * Loads a device driver. - * - * Parameters - * DriverServiceName - * Name of the service to load (registry key). - * - * Return Value - * Status - */ - -NTSTATUS STDCALL -NtLoadDriver(IN PUNICODE_STRING DriverServiceName) -{ - RTL_QUERY_REGISTRY_TABLE QueryTable[2]; - UNICODE_STRING ImagePath; - HANDLE KeyHandle; - NTSTATUS Status; - ULONG Type; - PDEVICE_NODE DeviceNode; - PMODULE_OBJECT ModuleObject; - LPWSTR Start; - - DPRINT("NtLoadDriver(%wZ)\n", DriverServiceName); - - /* - * Check security privileges - */ -#if 0 - if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, KeGetPreviousMode())) - return STATUS_PRIVILEGE_NOT_HELD; -#endif - - RtlInitUnicodeString(&ImagePath, NULL); - - /* - * Open service registry key - */ - Status = RtlpGetRegistryHandle(RTL_REGISTRY_ABSOLUTE, - DriverServiceName->Buffer, FALSE, &KeyHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlpGetRegistryHandle() failed (Status %x)\n", Status); - return Status; - } - - /* - * Get service type - */ - RtlZeroMemory(&QueryTable, sizeof(QueryTable)); - QueryTable[0].Name = L"Type"; - QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED; - QueryTable[0].EntryContext = &Type; - Status = RtlQueryRegistryValues(RTL_REGISTRY_HANDLE, (PWSTR)KeyHandle, - QueryTable, NULL, NULL); - if (!NT_SUCCESS(Status)) - { - DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status); - RtlFreeUnicodeString(&ImagePath); - NtClose(KeyHandle); - return Status; - } - - /* - * Get module path - */ - Status = IopGetDriverNameFromKeyNode(&ImagePath, KeyHandle); - if (!NT_SUCCESS(Status)) - { - DPRINT("IopGetDriverNameFromKeyNode() failed (Status %x)\n", Status); - NtClose(KeyHandle); - return Status; - } - - /* - * Close service registry key - */ - NtClose(KeyHandle); - - DPRINT("FullImagePath: '%S'\n", ImagePath.Buffer); - DPRINT("Type: %lx\n", Type); - - /* - * See, if the driver module isn't already loaded - */ - ModuleObject = LdrGetModuleObject(&ImagePath); - if (ModuleObject != NULL) - { - return STATUS_IMAGE_ALREADY_LOADED; - } - - /* - * Create device node - */ - /* Use IopRootDeviceNode for now */ - Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &DeviceNode); - if (!NT_SUCCESS(Status)) - { - DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status); - return Status; - } - - /* - * Load the driver module - */ - Status = LdrLoadModule(&ImagePath, &ModuleObject); - if (!NT_SUCCESS(Status)) - { - DPRINT("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); - - /* - * Initialize the driver module - */ - Status = IopInitializeDriver( - ModuleObject->EntryPoint, - DeviceNode, - (Type == 2 /*SERVICE_FILE_SYSTEM_DRIVER*/ || - Type == 8 /*SERVICE_RECOGNIZER_DRIVER*/), - ModuleObject->Base, - ModuleObject->Length, - FALSE); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IopInitializeDriver() failed (Status %lx)\n", Status); - LdrUnloadModule(ModuleObject); - IopFreeDeviceNode(DeviceNode); - } - - return Status; -} - - -/* - * NtUnloadDriver - * - * Unloads a legacy device driver. - * - * Parameters - * DriverServiceName - * Name of the service to unload (registry key). - * - * Return Value - * Status - */ - -NTSTATUS STDCALL -NtUnloadDriver(IN PUNICODE_STRING DriverServiceName) -{ - return IopUnloadDriver(DriverServiceName, FALSE); -} - -/* EOF */ +/* $Id: driver.c,v 1.20 2003/10/06 18:24:54 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NDEBUG +#include + + +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 */ diff --git a/reactos/subsys/system/explorer/makefile_rex b/reactos/subsys/system/explorer/makefile_rex index 054e0942b8c..90970824c1c 100644 --- a/reactos/subsys/system/explorer/makefile_rex +++ b/reactos/subsys/system/explorer/makefile_rex @@ -1,85 +1,85 @@ -# -# ReactOS explorer -# -# Makefile -# - -PATH_TO_TOP = ../../.. - -TARGET_TYPE = program - -TARGET_APPTYPE = windows - -TARGET_NAME = explorer - -TARGET_CFLAGS = -g3 -fexceptions -Os -DNDEBUG -DWIN32 -D_ROS_ -Wall -D_WIN32_IE=0x0501 -D_WIN32_WINNT=0x0501 - -TARGET_CPPFLAGS = -g3 -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 +# +# 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 diff --git a/reactos/subsys/win32k/ntuser/windc.c b/reactos/subsys/win32k/ntuser/windc.c index e8cfa9d5c22..aa008192280 100644 --- a/reactos/subsys/win32k/ntuser/windc.c +++ b/reactos/subsys/win32k/ntuser/windc.c @@ -1,560 +1,559 @@ -/* - * 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.28 2003/10/06 17:53:55 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NDEBUG -#include - -/* 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; - DbgPrint("FIXME\n"); - /* 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 */ +/* + * 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.29 2003/10/06 18:24:54 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NDEBUG +#include + +/* 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 */