* Sync up to trunk head (r65394).
authorAmine Khaldi <amine.khaldi@reactos.org>
Thu, 13 Nov 2014 19:27:12 +0000 (19:27 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Thu, 13 Nov 2014 19:27:12 +0000 (19:27 +0000)
svn path=/branches/shell-experiments/; revision=65395

106 files changed:
1  2 
boot/freeldr/bootsect/fat.S
boot/freeldr/bootsect/fat32.S
boot/freeldr/bootsect/fatx.S
boot/freeldr/bootsect/isoboot.S
boot/freeldr/freeldr/cache/blocklist.c
boot/freeldr/freeldr/cache/cache.c
boot/freeldr/freeldr/linuxboot.c
boot/freeldr/freeldr/reactos/registry.c
cmake/gcc.cmake
cmake/msvc.cmake
dll/win32/CMakeLists.txt
dll/win32/msafd/CMakeLists.txt
dll/win32/msafd/misc/dllmain.c
dll/win32/msafd/misc/event.c
dll/win32/msafd/misc/helpers.c
dll/win32/msafd/misc/sndrcv.c
dll/win32/msafd/misc/stubs.c
dll/win32/msafd/msafd.h
dll/win32/npptools/CMakeLists.txt
dll/win32/npptools/main.c
dll/win32/npptools/npptools.spec
drivers/filesystems/fastfat/cleanup.c
drivers/filesystems/fastfat/close.c
drivers/filesystems/fastfat/fsctl.c
drivers/filesystems/fastfat/misc.c
drivers/filesystems/fastfat/vfat.h
media/doc/README.WINE
ntoskrnl/cache/section/data.c
ntoskrnl/cache/section/fault.c
ntoskrnl/include/internal/arch/intrin_i.h
ntoskrnl/include/internal/arch/ke.h
ntoskrnl/include/internal/ntoskrnl.h
ntoskrnl/kd64/kddata.c
ntoskrnl/kdbg/kdb_symbols.cmake.c
ntoskrnl/mm/ARM3/arm/init.c
ntoskrnl/mm/ARM3/contmem.c
ntoskrnl/mm/ARM3/drvmgmt.c
ntoskrnl/mm/ARM3/dynamic.c
ntoskrnl/mm/ARM3/expool.c
ntoskrnl/mm/ARM3/hypermap.c
ntoskrnl/mm/ARM3/i386/init.c
ntoskrnl/mm/ARM3/iosup.c
ntoskrnl/mm/ARM3/largepag.c
ntoskrnl/mm/ARM3/mdlsup.c
ntoskrnl/mm/ARM3/mmdbg.c
ntoskrnl/mm/ARM3/mmsup.c
ntoskrnl/mm/ARM3/ncache.c
ntoskrnl/mm/ARM3/pagfault.c
ntoskrnl/mm/ARM3/pfnlist.c
ntoskrnl/mm/ARM3/pool.c
ntoskrnl/mm/ARM3/procsup.c
ntoskrnl/mm/ARM3/section.c
ntoskrnl/mm/ARM3/session.c
ntoskrnl/mm/ARM3/special.c
ntoskrnl/mm/ARM3/sysldr.c
ntoskrnl/mm/ARM3/syspte.c
ntoskrnl/mm/ARM3/vadnode.c
ntoskrnl/mm/ARM3/virtual.c
ntoskrnl/mm/ARM3/zeropage.c
ntoskrnl/mm/amd64/init.c
ntoskrnl/mm/amd64/page.c
ntoskrnl/mm/arm/page.c
ntoskrnl/mm/i386/page.c
ntoskrnl/mm/marea.c
ntoskrnl/mm/mmfault.c
ntoskrnl/mm/rmap.c
ntoskrnl/mm/section.c
ntoskrnl/ntkrnlmp/CMakeLists.txt
ntoskrnl/po/poshtdwn.c
subsystems/ntvdm/CMakeLists.txt
subsystems/ntvdm/bios/bios32/bios32.c
subsystems/ntvdm/bios/bios32/bios32.h
subsystems/ntvdm/bios/bios32/bios32p.h
subsystems/ntvdm/bios/bios32/kbdbios32.c
subsystems/ntvdm/bios/bios32/kbdbios32.h
subsystems/ntvdm/bios/bios32/moubios32.c
subsystems/ntvdm/bios/bios32/moubios32.h
subsystems/ntvdm/bios/bios32/vidbios32.c
subsystems/ntvdm/bios/bios32/vidbios32.h
subsystems/ntvdm/bios/vidbios.c
subsystems/ntvdm/clock.c
subsystems/ntvdm/dos/dem.c
subsystems/ntvdm/dos/dos32krnl/dos.c
subsystems/ntvdm/dos/mouse32.c
subsystems/ntvdm/dos/mouse32.h
subsystems/ntvdm/hardware/mouse.c
subsystems/ntvdm/hardware/vga.c
win32ss/drivers/displays/framebuf/ddenable.c
win32ss/drivers/displays/framebuf/pointer.c
win32ss/drivers/displays/framebufacc/ddenable.c
win32ss/drivers/displays/vga/main/enable.c
win32ss/drivers/displays/vga/vgavideo/vgavideo.c
win32ss/gdi/dib/floodfill.c
win32ss/gdi/gdi32/misc/gdientry.c
win32ss/gdi/ntgdi/region.c
win32ss/gdi/ntgdi/xformobj.c
win32ss/user/ntuser/cursoricon_new.c
win32ss/user/ntuser/hotkey.c
win32ss/user/ntuser/message.c
win32ss/user/ntuser/msgqueue.c
win32ss/user/user32/controls/appswitch.c
win32ss/user/user32/misc/desktop.c
win32ss/user/user32/misc/winsta.c
win32ss/user/winsrv/consrv/frontends/gui/conwnd.c
win32ss/user/winsrv/consrv_new/frontends/gui/guiterm.c
win32ss/user/winsrv/usersrv/register.c

Simple merge
Simple merge
Simple merge
Simple merge
index fa0fdff,0000000..1b4c37a
mode 100644,000000..100644
--- /dev/null
@@@ -1,237 -1,0 +1,237 @@@
-     while (&CacheBlockToFree->ListEntry != &CacheDrive->CacheBlockHead && CacheBlockToFree->LockedInCache == TRUE)
 +/*
 + *  FreeLoader
 + *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
 + *
 + *  This program is free software; you can redistribute it and/or modify
 + *  it under the terms of the GNU General Public License as published by
 + *  the Free Software Foundation; either version 2 of the License, or
 + *  (at your option) any later version.
 + *
 + *  This program is distributed in the hope that it will be useful,
 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *  GNU General Public License for more details.
 + *
 + *  You should have received a copy of the GNU General Public License along
 + *  with this program; if not, write to the Free Software Foundation, Inc.,
 + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#include <freeldr.h>
 +#include <debug.h>
 +
 +DBG_DEFAULT_CHANNEL(CACHE);
 +
 +// Returns a pointer to a CACHE_BLOCK structure
 +// Adds the block to the cache manager block list
 +// in cache memory if it isn't already there
 +PCACHE_BLOCK CacheInternalGetBlockPointer(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
 +{
 +    PCACHE_BLOCK    CacheBlock = NULL;
 +
 +    TRACE("CacheInternalGetBlockPointer() BlockNumber = %d\n", BlockNumber);
 +
 +    CacheBlock = CacheInternalFindBlock(CacheDrive, BlockNumber);
 +
 +    if (CacheBlock != NULL)
 +    {
 +        TRACE("Cache hit! BlockNumber: %d CacheBlock->BlockNumber: %d\n", BlockNumber, CacheBlock->BlockNumber);
 +
 +        return CacheBlock;
 +    }
 +
 +    TRACE("Cache miss! BlockNumber: %d\n", BlockNumber);
 +
 +    CacheBlock = CacheInternalAddBlockToCache(CacheDrive, BlockNumber);
 +
 +    // Optimize the block list so it has a LRU structure
 +    CacheInternalOptimizeBlockList(CacheDrive, CacheBlock);
 +
 +    return CacheBlock;
 +}
 +
 +PCACHE_BLOCK CacheInternalFindBlock(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
 +{
 +    PCACHE_BLOCK    CacheBlock = NULL;
 +
 +    TRACE("CacheInternalFindBlock() BlockNumber = %d\n", BlockNumber);
 +
 +    //
 +    // Make sure the block list has entries before I start searching it.
 +    //
 +    if (!IsListEmpty(&CacheDrive->CacheBlockHead))
 +    {
 +        //
 +        // Search the list and find the BIOS drive number
 +        //
 +        CacheBlock = CONTAINING_RECORD(CacheDrive->CacheBlockHead.Flink, CACHE_BLOCK, ListEntry);
 +
 +        while (&CacheBlock->ListEntry != &CacheDrive->CacheBlockHead)
 +        {
 +            //
 +            // We found the block, so return it
 +            //
 +            if (CacheBlock->BlockNumber == BlockNumber)
 +            {
 +                //
 +                // Increment the blocks access count
 +                //
 +                CacheBlock->AccessCount++;
 +
 +                return CacheBlock;
 +            }
 +
 +            CacheBlock = CONTAINING_RECORD(CacheBlock->ListEntry.Flink, CACHE_BLOCK, ListEntry);
 +        }
 +    }
 +
 +    return NULL;
 +}
 +
 +PCACHE_BLOCK CacheInternalAddBlockToCache(PCACHE_DRIVE CacheDrive, ULONG BlockNumber)
 +{
 +    PCACHE_BLOCK    CacheBlock = NULL;
 +
 +    TRACE("CacheInternalAddBlockToCache() BlockNumber = %d\n", BlockNumber);
 +
 +    // Check the size of the cache so we don't exceed our limits
 +    CacheInternalCheckCacheSizeLimits(CacheDrive);
 +
 +    // We will need to add the block to the
 +    // drive's list of cached blocks. So allocate
 +    // the block memory.
 +    CacheBlock = FrLdrTempAlloc(sizeof(CACHE_BLOCK), TAG_CACHE_BLOCK);
 +    if (CacheBlock == NULL)
 +    {
 +        return NULL;
 +    }
 +
 +    // Now initialize the structure and
 +    // allocate room for the block data
 +    RtlZeroMemory(CacheBlock, sizeof(CACHE_BLOCK));
 +    CacheBlock->BlockNumber = BlockNumber;
 +    CacheBlock->BlockData = FrLdrTempAlloc(CacheDrive->BlockSize * CacheDrive->BytesPerSector,
 +                                           TAG_CACHE_DATA);
 +    if (CacheBlock->BlockData ==NULL)
 +    {
 +        FrLdrTempFree(CacheBlock, TAG_CACHE_BLOCK);
 +        return NULL;
 +    }
 +
 +    // Now try to read in the block
 +    if (!MachDiskReadLogicalSectors(CacheDrive->DriveNumber, (BlockNumber * CacheDrive->BlockSize), CacheDrive->BlockSize, (PVOID)DISKREADBUFFER))
 +    {
 +        FrLdrTempFree(CacheBlock->BlockData, TAG_CACHE_DATA);
 +        FrLdrTempFree(CacheBlock, TAG_CACHE_BLOCK);
 +        return NULL;
 +    }
 +    RtlCopyMemory(CacheBlock->BlockData, (PVOID)DISKREADBUFFER, CacheDrive->BlockSize * CacheDrive->BytesPerSector);
 +
 +    // Add it to our list of blocks managed by the cache
 +    InsertTailList(&CacheDrive->CacheBlockHead, &CacheBlock->ListEntry);
 +
 +    // Update the cache data
 +    CacheBlockCount++;
 +    CacheSizeCurrent = CacheBlockCount * (CacheDrive->BlockSize * CacheDrive->BytesPerSector);
 +
 +    CacheInternalDumpBlockList(CacheDrive);
 +
 +    return CacheBlock;
 +}
 +
 +BOOLEAN CacheInternalFreeBlock(PCACHE_DRIVE CacheDrive)
 +{
 +    PCACHE_BLOCK    CacheBlockToFree;
 +
 +    TRACE("CacheInternalFreeBlock()\n");
 +
 +    // Get a pointer to the last item in the block list
 +    // that isn't forced to be in the cache and remove
 +    // it from the list
 +    CacheBlockToFree = CONTAINING_RECORD(CacheDrive->CacheBlockHead.Blink, CACHE_BLOCK, ListEntry);
++    while (&CacheBlockToFree->ListEntry != &CacheDrive->CacheBlockHead && CacheBlockToFree->LockedInCache)
 +    {
 +        CacheBlockToFree = CONTAINING_RECORD(CacheBlockToFree->ListEntry.Blink, CACHE_BLOCK, ListEntry);
 +    }
 +
 +    // No blocks left in cache that can be freed
 +    // so just return
 +    if (IsListEmpty(&CacheDrive->CacheBlockHead))
 +    {
 +        return FALSE;
 +    }
 +
 +    RemoveEntryList(&CacheBlockToFree->ListEntry);
 +
 +    // Free the block memory and the block structure
 +    FrLdrTempFree(CacheBlockToFree->BlockData, TAG_CACHE_DATA);
 +    FrLdrTempFree(CacheBlockToFree, TAG_CACHE_BLOCK);
 +
 +    // Update the cache data
 +    CacheBlockCount--;
 +    CacheSizeCurrent = CacheBlockCount * (CacheDrive->BlockSize * CacheDrive->BytesPerSector);
 +
 +    return TRUE;
 +}
 +
 +VOID CacheInternalCheckCacheSizeLimits(PCACHE_DRIVE CacheDrive)
 +{
 +    SIZE_T        NewCacheSize;
 +
 +    TRACE("CacheInternalCheckCacheSizeLimits()\n");
 +
 +    // Calculate the size of the cache if we added a block
 +    NewCacheSize = (CacheBlockCount + 1) * (CacheDrive->BlockSize * CacheDrive->BytesPerSector);
 +
 +    // Check the new size against the cache size limit
 +    if (NewCacheSize > CacheSizeLimit)
 +    {
 +        CacheInternalFreeBlock(CacheDrive);
 +        CacheInternalDumpBlockList(CacheDrive);
 +    }
 +}
 +
 +VOID CacheInternalDumpBlockList(PCACHE_DRIVE CacheDrive)
 +{
 +    PCACHE_BLOCK    CacheBlock;
 +
 +    TRACE("Dumping block list for BIOS drive 0x%x.\n", CacheDrive->DriveNumber);
 +    TRACE("BytesPerSector: %d.\n", CacheDrive->BytesPerSector);
 +    TRACE("BlockSize: %d.\n", CacheDrive->BlockSize);
 +    TRACE("CacheSizeLimit: %d.\n", CacheSizeLimit);
 +    TRACE("CacheSizeCurrent: %d.\n", CacheSizeCurrent);
 +    TRACE("CacheBlockCount: %d.\n", CacheBlockCount);
 +
 +    CacheBlock = CONTAINING_RECORD(CacheDrive->CacheBlockHead.Flink, CACHE_BLOCK, ListEntry);
 +    while (&CacheBlock->ListEntry != &CacheDrive->CacheBlockHead)
 +    {
 +        TRACE("Cache Block: CacheBlock: 0x%x\n", CacheBlock);
 +        TRACE("Cache Block: Block Number: %d\n", CacheBlock->BlockNumber);
 +        TRACE("Cache Block: Access Count: %d\n", CacheBlock->AccessCount);
 +        TRACE("Cache Block: Block Data: 0x%x\n", CacheBlock->BlockData);
 +        TRACE("Cache Block: Locked In Cache: %d\n", CacheBlock->LockedInCache);
 +
 +        if (CacheBlock->BlockData == NULL)
 +        {
 +            BugCheck("CacheBlock->BlockData == NULL\n");
 +        }
 +
 +        CacheBlock = CONTAINING_RECORD(CacheBlock->ListEntry.Flink, CACHE_BLOCK, ListEntry);
 +    }
 +}
 +
 +VOID CacheInternalOptimizeBlockList(PCACHE_DRIVE CacheDrive, PCACHE_BLOCK CacheBlock)
 +{
 +
 +    TRACE("CacheInternalOptimizeBlockList()\n");
 +
 +    // Don't do this if this block is already at the head of the list
 +    if (&CacheBlock->ListEntry != CacheDrive->CacheBlockHead.Flink)
 +    {
 +        // Remove this item from the block list
 +        RemoveEntryList(&CacheBlock->ListEntry);
 +
 +        // Re-insert it at the head of the list
 +        InsertHeadList(&CacheDrive->CacheBlockHead, &CacheBlock->ListEntry);
 +    }
 +}
index 105a3c4,0000000..92f5237
mode 100644,000000..100644
--- /dev/null
@@@ -1,324 -1,0 +1,324 @@@
-     if ((CacheManagerInitialized == TRUE) &&
 +/*
 + *  FreeLoader
 + *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
 + *
 + *  This program is free software; you can redistribute it and/or modify
 + *  it under the terms of the GNU General Public License as published by
 + *  the Free Software Foundation; either version 2 of the License, or
 + *  (at your option) any later version.
 + *
 + *  This program is distributed in the hope that it will be useful,
 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *  GNU General Public License for more details.
 + *
 + *  You should have received a copy of the GNU General Public License along
 + *  with this program; if not, write to the Free Software Foundation, Inc.,
 + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#include <freeldr.h>
 +#include <debug.h>
 +
 +DBG_DEFAULT_CHANNEL(CACHE);
 +
 +///////////////////////////////////////////////////////////////////////////////////////
 +//
 +// Internal data
 +//
 +///////////////////////////////////////////////////////////////////////////////////////
 +CACHE_DRIVE        CacheManagerDrive;
 +BOOLEAN            CacheManagerInitialized = FALSE;
 +BOOLEAN            CacheManagerDataInvalid = FALSE;
 +ULONG            CacheBlockCount = 0;
 +SIZE_T            CacheSizeLimit = 0;
 +SIZE_T            CacheSizeCurrent = 0;
 +
 +BOOLEAN CacheInitializeDrive(UCHAR DriveNumber)
 +{
 +    PCACHE_BLOCK    NextCacheBlock;
 +    GEOMETRY    DriveGeometry;
 +
 +    // If we already have a cache for this drive then
 +    // by all means lets keep it, unless it is a removable
 +    // drive, in which case we'll invalidate the cache
-         (CacheManagerDataInvalid != TRUE))
++    if ((CacheManagerInitialized) &&
 +        (DriveNumber == CacheManagerDrive.DriveNumber) &&
 +        (DriveNumber >= 0x80) &&
++        (!CacheManagerDataInvalid))
 +    {
 +        return TRUE;
 +    }
 +
 +    CacheManagerDataInvalid = FALSE;
 +
 +    //
 +    // If we have already been initialized then free
 +    // the old data
 +    //
 +    if (CacheManagerInitialized)
 +    {
 +        CacheManagerInitialized = FALSE;
 +
 +        TRACE("CacheBlockCount: %d\n", CacheBlockCount);
 +        TRACE("CacheSizeLimit: %d\n", CacheSizeLimit);
 +        TRACE("CacheSizeCurrent: %d\n", CacheSizeCurrent);
 +        //
 +        // Loop through and free the cache blocks
 +        //
 +        while (!IsListEmpty(&CacheManagerDrive.CacheBlockHead))
 +        {
 +            NextCacheBlock = CONTAINING_RECORD(RemoveHeadList(&CacheManagerDrive.CacheBlockHead),
 +                                               CACHE_BLOCK,
 +                                               ListEntry);
 +
 +            FrLdrTempFree(NextCacheBlock->BlockData, TAG_CACHE_DATA);
 +            FrLdrTempFree(NextCacheBlock, TAG_CACHE_BLOCK);
 +        }
 +    }
 +
 +    // Initialize the structure
 +    RtlZeroMemory(&CacheManagerDrive, sizeof(CACHE_DRIVE));
 +    InitializeListHead(&CacheManagerDrive.CacheBlockHead);
 +    CacheManagerDrive.DriveNumber = DriveNumber;
 +    if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry))
 +    {
 +        return FALSE;
 +    }
 +    CacheManagerDrive.BytesPerSector = DriveGeometry.BytesPerSector;
 +
 +    // Get the number of sectors in each cache block
 +    CacheManagerDrive.BlockSize = MachDiskGetCacheableBlockCount(DriveNumber);
 +
 +    CacheBlockCount = 0;
 +    CacheSizeLimit = TotalPagesInLookupTable / 8 * MM_PAGE_SIZE;
 +    CacheSizeCurrent = 0;
 +    if (CacheSizeLimit > TEMP_HEAP_SIZE - (128 * 1024))
 +    {
 +        CacheSizeLimit = TEMP_HEAP_SIZE - (128 * 1024);
 +    }
 +
 +    CacheManagerInitialized = TRUE;
 +
 +    TRACE("Initializing BIOS drive 0x%x.\n", DriveNumber);
 +    TRACE("BytesPerSector: %d.\n", CacheManagerDrive.BytesPerSector);
 +    TRACE("BlockSize: %d.\n", CacheManagerDrive.BlockSize);
 +    TRACE("CacheSizeLimit: %d.\n", CacheSizeLimit);
 +
 +    return TRUE;
 +}
 +
 +VOID CacheInvalidateCacheData(VOID)
 +{
 +    CacheManagerDataInvalid = TRUE;
 +}
 +
 +BOOLEAN CacheReadDiskSectors(UCHAR DiskNumber, ULONGLONG StartSector, ULONG SectorCount, PVOID Buffer)
 +{
 +    PCACHE_BLOCK    CacheBlock;
 +    ULONG                StartBlock;
 +    ULONG                SectorOffsetInStartBlock;
 +    ULONG                CopyLengthInStartBlock;
 +    ULONG                EndBlock;
 +    ULONG                SectorOffsetInEndBlock;
 +    ULONG                BlockCount;
 +    ULONG                Idx;
 +
 +    TRACE("CacheReadDiskSectors() DiskNumber: 0x%x StartSector: %I64d SectorCount: %d Buffer: 0x%x\n", DiskNumber, StartSector, SectorCount, Buffer);
 +
 +    // If we aren't initialized yet then they can't do this
 +    if (CacheManagerInitialized == FALSE)
 +    {
 +        return FALSE;
 +    }
 +
 +    //
 +    // Caculate which blocks we must cache
 +    //
 +    StartBlock = (ULONG)(StartSector / CacheManagerDrive.BlockSize);
 +    SectorOffsetInStartBlock = (ULONG)(StartSector % CacheManagerDrive.BlockSize);
 +    CopyLengthInStartBlock = (ULONG)((SectorCount > (CacheManagerDrive.BlockSize - SectorOffsetInStartBlock)) ? (CacheManagerDrive.BlockSize - SectorOffsetInStartBlock) : SectorCount);
 +    EndBlock = (ULONG)((StartSector + (SectorCount - 1)) / CacheManagerDrive.BlockSize);
 +    SectorOffsetInEndBlock = (ULONG)(1 + (StartSector + (SectorCount - 1)) % CacheManagerDrive.BlockSize);
 +    BlockCount = (EndBlock - StartBlock) + 1;
 +    TRACE("StartBlock: %d SectorOffsetInStartBlock: %d CopyLengthInStartBlock: %d EndBlock: %d SectorOffsetInEndBlock: %d BlockCount: %d\n", StartBlock, SectorOffsetInStartBlock, CopyLengthInStartBlock, EndBlock, SectorOffsetInEndBlock, BlockCount);
 +
 +    //
 +    // Read the first block into the buffer
 +    //
 +    if (BlockCount > 0)
 +    {
 +        //
 +        // Get cache block pointer (this forces the disk sectors into the cache memory)
 +        //
 +        CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, StartBlock);
 +        if (CacheBlock == NULL)
 +        {
 +            return FALSE;
 +        }
 +
 +        //
 +        // Copy the portion requested into the buffer
 +        //
 +        RtlCopyMemory(Buffer,
 +            (PVOID)((ULONG_PTR)CacheBlock->BlockData + (SectorOffsetInStartBlock * CacheManagerDrive.BytesPerSector)),
 +            (CopyLengthInStartBlock * CacheManagerDrive.BytesPerSector));
 +        TRACE("1 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, ((ULONG_PTR)CacheBlock->BlockData + (SectorOffsetInStartBlock * CacheManagerDrive.BytesPerSector)), (CopyLengthInStartBlock * CacheManagerDrive.BytesPerSector));
 +
 +        //
 +        // Update the buffer address
 +        //
 +        Buffer = (PVOID)((ULONG_PTR)Buffer + (CopyLengthInStartBlock * CacheManagerDrive.BytesPerSector));
 +
 +        //
 +        // Update the block count
 +        //
 +        BlockCount--;
 +    }
 +
 +    //
 +    // Loop through the middle blocks and read them into the buffer
 +    //
 +    for (Idx=StartBlock+1; BlockCount>1; Idx++)
 +    {
 +        //
 +        // Get cache block pointer (this forces the disk sectors into the cache memory)
 +        //
 +        CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, Idx);
 +        if (CacheBlock == NULL)
 +        {
 +            return FALSE;
 +        }
 +
 +        //
 +        // Copy the portion requested into the buffer
 +        //
 +        RtlCopyMemory(Buffer,
 +            CacheBlock->BlockData,
 +            CacheManagerDrive.BlockSize * CacheManagerDrive.BytesPerSector);
 +        TRACE("2 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, CacheBlock->BlockData, CacheManagerDrive.BlockSize * CacheManagerDrive.BytesPerSector);
 +
 +        //
 +        // Update the buffer address
 +        //
 +        Buffer = (PVOID)((ULONG_PTR)Buffer + (CacheManagerDrive.BlockSize * CacheManagerDrive.BytesPerSector));
 +
 +        //
 +        // Update the block count
 +        //
 +        BlockCount--;
 +    }
 +
 +    //
 +    // Read the last block into the buffer
 +    //
 +    if (BlockCount > 0)
 +    {
 +        //
 +        // Get cache block pointer (this forces the disk sectors into the cache memory)
 +        //
 +        CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, EndBlock);
 +        if (CacheBlock == NULL)
 +        {
 +            return FALSE;
 +        }
 +
 +        //
 +        // Copy the portion requested into the buffer
 +        //
 +        RtlCopyMemory(Buffer,
 +            CacheBlock->BlockData,
 +            SectorOffsetInEndBlock * CacheManagerDrive.BytesPerSector);
 +        TRACE("3 - RtlCopyMemory(0x%x, 0x%x, %d)\n", Buffer, CacheBlock->BlockData, SectorOffsetInEndBlock * CacheManagerDrive.BytesPerSector);
 +
 +        //
 +        // Update the buffer address
 +        //
 +        Buffer = (PVOID)((ULONG_PTR)Buffer + (SectorOffsetInEndBlock * CacheManagerDrive.BytesPerSector));
 +
 +        //
 +        // Update the block count
 +        //
 +        BlockCount--;
 +    }
 +
 +    return TRUE;
 +}
 +
 +#if 0
 +BOOLEAN CacheForceDiskSectorsIntoCache(UCHAR DiskNumber, ULONGLONG StartSector, ULONG SectorCount)
 +{
 +    PCACHE_BLOCK    CacheBlock;
 +    ULONG                StartBlock;
 +    ULONG                EndBlock;
 +    ULONG                BlockCount;
 +    ULONG                Idx;
 +
 +    TRACE("CacheForceDiskSectorsIntoCache() DiskNumber: 0x%x StartSector: %d SectorCount: %d\n", DiskNumber, StartSector, SectorCount);
 +
 +    // If we aren't initialized yet then they can't do this
 +    if (CacheManagerInitialized == FALSE)
 +    {
 +        return FALSE;
 +    }
 +
 +    //
 +    // Caculate which blocks we must cache
 +    //
 +    StartBlock = StartSector / CacheManagerDrive.BlockSize;
 +    EndBlock = (StartSector + SectorCount) / CacheManagerDrive.BlockSize;
 +    BlockCount = (EndBlock - StartBlock) + 1;
 +
 +    //
 +    // Loop through and cache them
 +    //
 +    for (Idx=StartBlock; Idx<(StartBlock+BlockCount); Idx++)
 +    {
 +        //
 +        // Get cache block pointer (this forces the disk sectors into the cache memory)
 +        //
 +        CacheBlock = CacheInternalGetBlockPointer(&CacheManagerDrive, Idx);
 +        if (CacheBlock == NULL)
 +        {
 +            return FALSE;
 +        }
 +
 +        //
 +        // Lock the sectors into the cache
 +        //
 +        CacheBlock->LockedInCache = TRUE;
 +    }
 +
 +    return TRUE;
 +}
 +#endif
 +
 +BOOLEAN CacheReleaseMemory(ULONG MinimumAmountToRelease)
 +{
 +    ULONG                AmountReleased;
 +
 +    TRACE("CacheReleaseMemory() MinimumAmountToRelease = %d\n", MinimumAmountToRelease);
 +
 +    // If we aren't initialized yet then they can't do this
 +    if (CacheManagerInitialized == FALSE)
 +    {
 +        return FALSE;
 +    }
 +
 +    // Loop through and try to free the requested amount of memory
 +    for (AmountReleased=0; AmountReleased<MinimumAmountToRelease; )
 +    {
 +        // Try to free a block
 +        // If this fails then break out of the loop
 +        if (!CacheInternalFreeBlock(&CacheManagerDrive))
 +        {
 +            break;
 +        }
 +
 +        // It succeeded so increment the amount of memory we have freed
 +        AmountReleased += CacheManagerDrive.BlockSize * CacheManagerDrive.BytesPerSector;
 +    }
 +
 +    // Return status
 +    return (AmountReleased >= MinimumAmountToRelease);
 +}
index f7cb5bf,0000000..7d431d5
mode 100644,000000..100644
--- /dev/null
@@@ -1,517 -1,0 +1,517 @@@
-     if ((NewStyleLinuxKernel == FALSE) && (LinuxHasInitrd == TRUE))
 +/*
 + *  FreeLoader
 + *  Copyright (C) 1998-2003  Brian Palmer  <brianp@sginet.com>
 + *
 + *  This program is free software; you can redistribute it and/or modify
 + *  it under the terms of the GNU General Public License as published by
 + *  the Free Software Foundation; either version 2 of the License, or
 + *  (at your option) any later version.
 + *
 + *  This program is distributed in the hope that it will be useful,
 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *  GNU General Public License for more details.
 + *
 + *  You should have received a copy of the GNU General Public License along
 + *  with this program; if not, write to the Free Software Foundation, Inc.,
 + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#ifndef _M_ARM
 +
 +#include <freeldr.h>
 +#include <debug.h>
 +#ifdef __i386__
 +#define    LINUX_READ_CHUNK_SIZE    0x20000            // Read 128k at a time
 +
 +DBG_DEFAULT_CHANNEL(LINUX);
 +
 +PLINUX_BOOTSECTOR    LinuxBootSector = NULL;
 +PLINUX_SETUPSECTOR    LinuxSetupSector = NULL;
 +ULONG            SetupSectorSize = 0;
 +BOOLEAN            NewStyleLinuxKernel = FALSE;
 +ULONG            LinuxKernelSize = 0;
 +ULONG            LinuxInitrdSize = 0;
 +CHAR            LinuxKernelName[260];
 +CHAR            LinuxInitrdName[260];
 +BOOLEAN            LinuxHasInitrd = FALSE;
 +CHAR            LinuxCommandLine[260] = "";
 +ULONG            LinuxCommandLineSize = 0;
 +PVOID            LinuxKernelLoadAddress = NULL;
 +PVOID            LinuxInitrdLoadAddress = NULL;
 +CHAR            LinuxBootDescription[80];
 +CHAR            LinuxBootPath[260] = "";
 +
 +BOOLEAN RemoveQuotes(PCHAR QuotedString)
 +{
 +    CHAR    TempString[200];
 +    PCHAR p;
 +    PSTR Start;
 +
 +    //
 +    // Skip spaces up to "
 +    //
 +    p = QuotedString;
 +    while (*p == ' ' || *p == '"')
 +        p++;
 +    Start = p;
 +
 +    //
 +    // Go up to next "
 +    //
 +    while (*p != '"' && *p != ANSI_NULL)
 +        p++;
 +    *p = ANSI_NULL;
 +
 +    //
 +    // Copy result
 +    //
 +    strcpy(TempString, Start);
 +    strcpy(QuotedString, TempString);
 +
 +    return TRUE;
 +}
 +
 +VOID
 +LoadAndBootLinux(IN OperatingSystemItem* OperatingSystem,
 +                 IN USHORT OperatingSystemVersion)
 +{
 +    PCSTR    SectionName = OperatingSystem->SystemPartition;
 +    PCSTR    Description = OperatingSystem->LoadIdentifier;
 +    PFILE    LinuxKernel = 0;
 +    PFILE    LinuxInitrdFile = 0;
 +    CHAR    TempString[260];
 +
 +    UiDrawBackdrop();
 +
 +    if (Description)
 +    {
 +        sprintf(LinuxBootDescription, "Loading %s...", Description);
 +    }
 +    else
 +    {
 +        strcpy(LinuxBootDescription, "Loading Linux...");
 +    }
 +
 +    UiDrawStatusText(LinuxBootDescription);
 +    UiDrawProgressBarCenter(0, 100, LinuxBootDescription);
 +
 +    // Parse the .ini file section
 +    if (!LinuxParseIniSection(SectionName))
 +    {
 +        goto LinuxBootFailed;
 +    }
 +
 +    // Open the kernel
 +    LinuxKernel = FsOpenFile(LinuxKernelName);
 +    if (!LinuxKernel)
 +    {
 +        sprintf(TempString, "Linux kernel \'%s\' not found.", LinuxKernelName);
 +        UiMessageBox(TempString);
 +        goto LinuxBootFailed;
 +    }
 +
 +    // Open the initrd file image (if necessary)
 +    if (LinuxHasInitrd)
 +    {
 +        LinuxInitrdFile = FsOpenFile(LinuxInitrdName);
 +        if (!LinuxInitrdFile)
 +        {
 +            sprintf(TempString, "Linux initrd image \'%s\' not found.", LinuxInitrdName);
 +            UiMessageBox(TempString);
 +            goto LinuxBootFailed;
 +        }
 +    }
 +
 +    // Read the boot sector
 +    if (!LinuxReadBootSector(LinuxKernel))
 +    {
 +        goto LinuxBootFailed;
 +    }
 +
 +    // Read the setup sector
 +    if (!LinuxReadSetupSector(LinuxKernel))
 +    {
 +        goto LinuxBootFailed;
 +    }
 +
 +    // Calc kernel size
 +    LinuxKernelSize = FsGetFileSize(LinuxKernel) - (512 + SetupSectorSize);
 +
 +    // Get the file size
 +    LinuxInitrdSize = FsGetFileSize(LinuxInitrdFile);
 +
 +    // Read the kernel
 +    if (!LinuxReadKernel(LinuxKernel))
 +    {
 +        goto LinuxBootFailed;
 +    }
 +
 +    // Read the initrd (if necessary)
 +    if (LinuxHasInitrd)
 +    {
 +        if (!LinuxReadInitrd(LinuxInitrdFile))
 +        {
 +            goto LinuxBootFailed;
 +        }
 +    }
 +
 +    // If the default root device is set to FLOPPY (0000h), change to /dev/fd0 (0200h)
 +    if (LinuxBootSector->RootDevice == 0x0000)
 +    {
 +        LinuxBootSector->RootDevice = 0x0200;
 +    }
 +
 +    if (LinuxSetupSector->Version >= 0x0202)
 +    {
 +        LinuxSetupSector->CommandLinePointer = 0x99000;
 +    }
 +    else
 +    {
 +        LinuxBootSector->CommandLineMagic = LINUX_COMMAND_LINE_MAGIC;
 +        LinuxBootSector->CommandLineOffset = 0x9000;
 +    }
 +
 +    if (NewStyleLinuxKernel)
 +    {
 +        LinuxSetupSector->TypeOfLoader = LINUX_LOADER_TYPE_FREELOADER;
 +    }
 +    else
 +    {
 +        LinuxSetupSector->LoadFlags = 0;
 +    }
 +
 +    RtlCopyMemory((PVOID)0x90000, LinuxBootSector, 512);
 +    RtlCopyMemory((PVOID)0x90200, LinuxSetupSector, SetupSectorSize);
 +    RtlCopyMemory((PVOID)0x99000, LinuxCommandLine, LinuxCommandLineSize);
 +
 +    UiUnInitialize("Booting Linux...");
 +
 +    DiskStopFloppyMotor();
 +
 +    if (LinuxSetupSector->LoadFlags & LINUX_FLAG_LOAD_HIGH)
 +    {
 +        BootNewLinuxKernel();
 +    }
 +    else
 +    {
 +        BootOldLinuxKernel(LinuxKernelSize);
 +    }
 +
 +
 +LinuxBootFailed:
 +
 +    if (LinuxKernel)
 +    {
 +        FsCloseFile(LinuxKernel);
 +    }
 +    if (LinuxInitrdFile)
 +    {
 +        FsCloseFile(LinuxInitrdFile);
 +    }
 +
 +    if (LinuxBootSector != NULL)
 +    {
 +        MmFreeMemory(LinuxBootSector);
 +    }
 +    if (LinuxSetupSector != NULL)
 +    {
 +        MmFreeMemory(LinuxSetupSector);
 +    }
 +    if (LinuxKernelLoadAddress != NULL)
 +    {
 +        MmFreeMemory(LinuxKernelLoadAddress);
 +    }
 +    if (LinuxInitrdLoadAddress != NULL)
 +    {
 +        MmFreeMemory(LinuxInitrdLoadAddress);
 +    }
 +
 +    LinuxBootSector = NULL;
 +    LinuxSetupSector = NULL;
 +    LinuxKernelLoadAddress = NULL;
 +    LinuxInitrdLoadAddress = NULL;
 +    SetupSectorSize = 0;
 +    NewStyleLinuxKernel = FALSE;
 +    LinuxKernelSize = 0;
 +    LinuxHasInitrd = FALSE;
 +    strcpy(LinuxCommandLine, "");
 +    LinuxCommandLineSize = 0;
 +}
 +
 +BOOLEAN LinuxParseIniSection(PCSTR SectionName)
 +{
 +    ULONG_PTR    SectionId;
 +    CHAR        SettingName[260];
 +
 +    // Find all the message box settings and run them
 +    UiShowMessageBoxesInSection(SectionName);
 +
 +    // Try to open the operating system section in the .ini file
 +    if (!IniOpenSection(SectionName, &SectionId))
 +    {
 +        sprintf(SettingName, "Section [%s] not found in freeldr.ini.\n", SectionName);
 +        UiMessageBox(SettingName);
 +        return FALSE;
 +    }
 +
 +    if (!IniReadSettingByName(SectionId, "BootPath", LinuxBootPath, sizeof(LinuxBootPath)))
 +    {
 +        UiMessageBox("Boot path not specified for selected OS!");
 +        return FALSE;
 +    }
 +
 +    // Get the kernel name
 +    if (!IniReadSettingByName(SectionId, "Kernel", LinuxKernelName, sizeof(LinuxKernelName)))
 +    {
 +        UiMessageBox("Linux kernel filename not specified for selected OS!");
 +        return FALSE;
 +    }
 +
 +    // Get the initrd name
 +    if (IniReadSettingByName(SectionId, "Initrd", LinuxInitrdName, sizeof(LinuxInitrdName)))
 +    {
 +        LinuxHasInitrd = TRUE;
 +    }
 +
 +    // Get the command line
 +    if (IniReadSettingByName(SectionId, "CommandLine", LinuxCommandLine, sizeof(LinuxCommandLine)))
 +    {
 +        RemoveQuotes(LinuxCommandLine);
 +        LinuxCommandLineSize = strlen(LinuxCommandLine) + 1;
 +    }
 +
 +    return TRUE;
 +}
 +
 +BOOLEAN LinuxReadBootSector(PFILE LinuxKernelFile)
 +{
 +    // Allocate memory for boot sector
 +    LinuxBootSector = MmAllocateMemoryWithType(512, LoaderSystemCode);
 +    if (LinuxBootSector == NULL)
 +    {
 +        return FALSE;
 +    }
 +
 +    // Read linux boot sector
 +    FsSetFilePointer(LinuxKernelFile, 0);
 +    if (!FsReadFile(LinuxKernelFile, 512, NULL, LinuxBootSector))
 +    {
 +        return FALSE;
 +    }
 +
 +    // Check for validity
 +    if (LinuxBootSector->BootFlag != LINUX_BOOT_SECTOR_MAGIC)
 +    {
 +        UiMessageBox("Invalid boot sector magic (0xaa55)");
 +        return FALSE;
 +    }
 +
 +    DbgDumpBuffer(DPRINT_LINUX, LinuxBootSector, 512);
 +
 +    TRACE("SetupSectors: %d\n", LinuxBootSector->SetupSectors);
 +    TRACE("RootFlags: 0x%x\n", LinuxBootSector->RootFlags);
 +    TRACE("SystemSize: 0x%x\n", LinuxBootSector->SystemSize);
 +    TRACE("SwapDevice: 0x%x\n", LinuxBootSector->SwapDevice);
 +    TRACE("RamSize: 0x%x\n", LinuxBootSector->RamSize);
 +    TRACE("VideoMode: 0x%x\n", LinuxBootSector->VideoMode);
 +    TRACE("RootDevice: 0x%x\n", LinuxBootSector->RootDevice);
 +    TRACE("BootFlag: 0x%x\n", LinuxBootSector->BootFlag);
 +
 +    return TRUE;
 +}
 +
 +BOOLEAN LinuxReadSetupSector(PFILE LinuxKernelFile)
 +{
 +    UCHAR    TempLinuxSetupSector[512];
 +
 +    LinuxSetupSector = (PLINUX_SETUPSECTOR)TempLinuxSetupSector;
 +
 +    // Read first linux setup sector
 +    FsSetFilePointer(LinuxKernelFile, 512);
 +    if (!FsReadFile(LinuxKernelFile, 512, NULL, TempLinuxSetupSector))
 +    {
 +        return FALSE;
 +    }
 +
 +    // Check the kernel version
 +    if (!LinuxCheckKernelVersion())
 +    {
 +        return FALSE;
 +    }
 +
 +    if (NewStyleLinuxKernel)
 +    {
 +        SetupSectorSize = 512 * LinuxBootSector->SetupSectors;
 +    }
 +    else
 +    {
 +        SetupSectorSize = 4 * 512; // Always 4 setup sectors
 +    }
 +
 +    // Allocate memory for setup sectors
 +    LinuxSetupSector = MmAllocateMemoryWithType(SetupSectorSize, LoaderSystemCode);
 +    if (LinuxSetupSector == NULL)
 +    {
 +        return FALSE;
 +    }
 +
 +    // Copy over first setup sector
 +    RtlCopyMemory(LinuxSetupSector, TempLinuxSetupSector, 512);
 +
 +    // Read in the rest of the linux setup sectors
 +    FsSetFilePointer(LinuxKernelFile, 1024);
 +    if (!FsReadFile(LinuxKernelFile, SetupSectorSize - 512, NULL, (PVOID)((ULONG_PTR)LinuxSetupSector + 512)))
 +    {
 +        return FALSE;
 +    }
 +
 +    DbgDumpBuffer(DPRINT_LINUX, LinuxSetupSector, SetupSectorSize);
 +
 +    TRACE("SetupHeaderSignature: 0x%x (HdrS)\n", LinuxSetupSector->SetupHeaderSignature);
 +    TRACE("Version: 0x%x\n", LinuxSetupSector->Version);
 +    TRACE("RealModeSwitch: 0x%x\n", LinuxSetupSector->RealModeSwitch);
 +    TRACE("SetupSeg: 0x%x\n", LinuxSetupSector->SetupSeg);
 +    TRACE("StartSystemSeg: 0x%x\n", LinuxSetupSector->StartSystemSeg);
 +    TRACE("KernelVersion: 0x%x\n", LinuxSetupSector->KernelVersion);
 +    TRACE("TypeOfLoader: 0x%x\n", LinuxSetupSector->TypeOfLoader);
 +    TRACE("LoadFlags: 0x%x\n", LinuxSetupSector->LoadFlags);
 +    TRACE("SetupMoveSize: 0x%x\n", LinuxSetupSector->SetupMoveSize);
 +    TRACE("Code32Start: 0x%x\n", LinuxSetupSector->Code32Start);
 +    TRACE("RamdiskAddress: 0x%x\n", LinuxSetupSector->RamdiskAddress);
 +    TRACE("RamdiskSize: 0x%x\n", LinuxSetupSector->RamdiskSize);
 +    TRACE("BootSectKludgeOffset: 0x%x\n", LinuxSetupSector->BootSectKludgeOffset);
 +    TRACE("BootSectKludgeSegment: 0x%x\n", LinuxSetupSector->BootSectKludgeSegment);
 +    TRACE("HeapEnd: 0x%x\n", LinuxSetupSector->HeapEnd);
 +
 +    return TRUE;
 +}
 +
 +BOOLEAN LinuxReadKernel(PFILE LinuxKernelFile)
 +{
 +    ULONG        BytesLoaded;
 +    CHAR    StatusText[260];
 +    PVOID    LoadAddress;
 +
 +    sprintf(StatusText, "Loading %s", LinuxKernelName);
 +    UiDrawStatusText(StatusText);
 +
 +    // Allocate memory for Linux kernel
 +    LinuxKernelLoadAddress = MmAllocateMemoryAtAddress(LinuxKernelSize, (PVOID)LINUX_KERNEL_LOAD_ADDRESS, LoaderSystemCode);
 +    if (LinuxKernelLoadAddress != (PVOID)LINUX_KERNEL_LOAD_ADDRESS)
 +    {
 +        return FALSE;
 +    }
 +
 +    LoadAddress = LinuxKernelLoadAddress;
 +
 +    // Read linux kernel to 0x100000 (1mb)
 +    FsSetFilePointer(LinuxKernelFile, 512 + SetupSectorSize);
 +    for (BytesLoaded=0; BytesLoaded<LinuxKernelSize; )
 +    {
 +        if (!FsReadFile(LinuxKernelFile, LINUX_READ_CHUNK_SIZE, NULL, LoadAddress))
 +        {
 +            return FALSE;
 +        }
 +
 +        BytesLoaded += LINUX_READ_CHUNK_SIZE;
 +        LoadAddress = (PVOID)((ULONG_PTR)LoadAddress + LINUX_READ_CHUNK_SIZE);
 +
 +        UiDrawProgressBarCenter(BytesLoaded, LinuxKernelSize + LinuxInitrdSize, LinuxBootDescription);
 +    }
 +
 +    return TRUE;
 +}
 +
 +BOOLEAN LinuxCheckKernelVersion(VOID)
 +{
 +    // Just assume old kernel until we find otherwise
 +    NewStyleLinuxKernel = FALSE;
 +
 +    // Check for new style setup header
 +    if (LinuxSetupSector->SetupHeaderSignature != LINUX_SETUP_HEADER_ID)
 +    {
 +        NewStyleLinuxKernel = FALSE;
 +    }
 +    // Check for version below 2.0
 +    else if (LinuxSetupSector->Version < 0x0200)
 +    {
 +        NewStyleLinuxKernel = FALSE;
 +    }
 +    // Check for version 2.0
 +    else if (LinuxSetupSector->Version == 0x0200)
 +    {
 +        NewStyleLinuxKernel = TRUE;
 +    }
 +    // Check for version 2.01+
 +    else if (LinuxSetupSector->Version >= 0x0201)
 +    {
 +        NewStyleLinuxKernel = TRUE;
 +        LinuxSetupSector->HeapEnd = 0x9000;
 +        LinuxSetupSector->LoadFlags |= LINUX_FLAG_CAN_USE_HEAP;
 +    }
 +
++    if ((NewStyleLinuxKernel == FALSE) && (LinuxHasInitrd))
 +    {
 +        UiMessageBox("Error: Cannot load a ramdisk (initrd) with an old kernel image.");
 +        return FALSE;
 +    }
 +
 +    return TRUE;
 +}
 +
 +BOOLEAN LinuxReadInitrd(PFILE LinuxInitrdFile)
 +{
 +    ULONG        BytesLoaded;
 +    CHAR    StatusText[260];
 +
 +    sprintf(StatusText, "Loading %s", LinuxInitrdName);
 +    UiDrawStatusText(StatusText);
 +
 +    // Allocate memory for the ramdisk
 +    //LinuxInitrdLoadAddress = MmAllocateMemory(LinuxInitrdSize);
 +    // Try to align it at the next MB boundary after the kernel
 +    //LinuxInitrdLoadAddress = MmAllocateMemoryAtAddress(LinuxInitrdSize, (PVOID)ROUND_UP((LINUX_KERNEL_LOAD_ADDRESS + LinuxKernelSize), 0x100000));
 +    if (LinuxSetupSector->Version <= 0x0202)
 +    {
 +        LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LINUX_MAX_INITRD_ADDRESS, LoaderSystemCode);
 +    }
 +    else
 +    {
 +        LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LinuxSetupSector->InitrdAddressMax, LoaderSystemCode);
 +    }
 +    if (LinuxInitrdLoadAddress == NULL)
 +    {
 +        return FALSE;
 +    }
 +
 +    // Set the information in the setup struct
 +    LinuxSetupSector->RamdiskAddress = (ULONG)LinuxInitrdLoadAddress;
 +    LinuxSetupSector->RamdiskSize = LinuxInitrdSize;
 +
 +    TRACE("RamdiskAddress: 0x%x\n", LinuxSetupSector->RamdiskAddress);
 +    TRACE("RamdiskSize: 0x%x\n", LinuxSetupSector->RamdiskSize);
 +
 +    if (LinuxSetupSector->Version >= 0x0203)
 +    {
 +        TRACE("InitrdAddressMax: 0x%x\n", LinuxSetupSector->InitrdAddressMax);
 +    }
 +
 +    // Read in the ramdisk
 +    for (BytesLoaded=0; BytesLoaded<LinuxInitrdSize; )
 +    {
 +        if (!FsReadFile(LinuxInitrdFile, LINUX_READ_CHUNK_SIZE, NULL, (PVOID)LinuxInitrdLoadAddress))
 +        {
 +            return FALSE;
 +        }
 +
 +        BytesLoaded += LINUX_READ_CHUNK_SIZE;
 +        LinuxInitrdLoadAddress = (PVOID)((ULONG_PTR)LinuxInitrdLoadAddress + LINUX_READ_CHUNK_SIZE);
 +
 +        UiDrawProgressBarCenter(BytesLoaded + LinuxKernelSize, LinuxInitrdSize + LinuxKernelSize, LinuxBootDescription);
 +    }
 +
 +    return TRUE;
 +}
 +#endif /* __i386__ */
 +#endif
index d88688a,0000000..5733d18
mode 100644,000000..100644
--- /dev/null
@@@ -1,593 -1,0 +1,593 @@@
-     CurrentSet = (LastKnownGood == TRUE) ? LastKnownGoodSet : DefaultSet;
 +/*
 + *  FreeLoader
 + *
 + *  Copyright (C) 2014  Timo Kreuzer <timo.kreuzer@reactos.org>
 + *
 + *  This program is free software; you can redistribute it and/or modify
 + *  it under the terms of the GNU General Public License as published by
 + *  the Free Software Foundation; either version 2 of the License, or
 + *  (at your option) any later version.
 + *
 + *  This program is distributed in the hope that it will be useful,
 + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + *  GNU General Public License for more details.
 + *
 + *  You should have received a copy of the GNU General Public License along
 + *  with this program; if not, write to the Free Software Foundation, Inc.,
 + *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#include <freeldr.h>
 +#include <cmlib.h>
 +#include <debug.h>
 +
 +DBG_DEFAULT_CHANNEL(REGISTRY);
 +
 +static PCMHIVE CmHive;
 +static PCM_KEY_NODE RootKeyNode;
 +static FRLDRHKEY CurrentControlSetKey;
 +
 +BOOLEAN
 +RegImportBinaryHive(
 +    _In_ PCHAR ChunkBase,
 +    _In_ ULONG ChunkSize)
 +{
 +    NTSTATUS Status;
 +    TRACE("RegImportBinaryHive(%p, 0x%lx)\n", ChunkBase, ChunkSize);
 +
 +    /* Allocate and initialize the hive */
 +    CmHive = FrLdrTempAlloc(sizeof(CMHIVE), 'eviH');
 +    Status = HvInitialize(&CmHive->Hive,
 +                          HINIT_FLAT,
 +                          0,
 +                          0,
 +                          ChunkBase,
 +                          NULL,
 +                          NULL,
 +                          NULL,
 +                          NULL,
 +                          NULL,
 +                          NULL,
 +                          1,
 +                          NULL);
 +    if (!NT_SUCCESS(Status))
 +    {
 +        FrLdrTempFree(CmHive, 'eviH');
 +        ERR("Invalid hive Signature!\n");
 +        return FALSE;
 +    }
 +
 +    /* Save the root key node */
 +    RootKeyNode = HvGetCell(&CmHive->Hive, CmHive->Hive.BaseBlock->RootCell);
 +
 +    TRACE("RegImportBinaryHive done\n");
 +    return TRUE;
 +}
 +
 +VOID
 +RegInitializeRegistry(VOID)
 +{
 +    /* Nothing to do */
 +}
 +
 +
 +LONG
 +RegInitCurrentControlSet(
 +    _In_ BOOLEAN LastKnownGood)
 +{
 +    WCHAR ControlSetKeyName[80];
 +    FRLDRHKEY SelectKey;
 +    FRLDRHKEY SystemKey;
 +    ULONG CurrentSet = 0;
 +    ULONG DefaultSet = 0;
 +    ULONG LastKnownGoodSet = 0;
 +    ULONG DataSize;
 +    LONG Error;
 +    TRACE("RegInitCurrentControlSet\n");
 +
 +    Error = RegOpenKey(NULL,
 +                       L"\\Registry\\Machine\\SYSTEM\\Select",
 +                       &SelectKey);
 +    if (Error != ERROR_SUCCESS)
 +    {
 +        ERR("RegOpenKey() failed (Error %u)\n", (int)Error);
 +        return Error;
 +    }
 +
 +    DataSize = sizeof(ULONG);
 +    Error = RegQueryValue(SelectKey,
 +                          L"Default",
 +                          NULL,
 +                          (PUCHAR)&DefaultSet,
 +                          &DataSize);
 +    if (Error != ERROR_SUCCESS)
 +    {
 +        ERR("RegQueryValue('Default') failed (Error %u)\n", (int)Error);
 +        return Error;
 +    }
 +
 +    DataSize = sizeof(ULONG);
 +    Error = RegQueryValue(SelectKey,
 +                          L"LastKnownGood",
 +                          NULL,
 +                          (PUCHAR)&LastKnownGoodSet,
 +                          &DataSize);
 +    if (Error != ERROR_SUCCESS)
 +    {
 +        ERR("RegQueryValue('Default') failed (Error %u)\n", (int)Error);
 +        return Error;
 +    }
 +
++    CurrentSet = (LastKnownGood) ? LastKnownGoodSet : DefaultSet;
 +    wcscpy(ControlSetKeyName, L"ControlSet");
 +    switch(CurrentSet)
 +    {
 +        case 1:
 +            wcscat(ControlSetKeyName, L"001");
 +            break;
 +        case 2:
 +            wcscat(ControlSetKeyName, L"002");
 +            break;
 +        case 3:
 +            wcscat(ControlSetKeyName, L"003");
 +            break;
 +        case 4:
 +            wcscat(ControlSetKeyName, L"004");
 +            break;
 +        case 5:
 +            wcscat(ControlSetKeyName, L"005");
 +            break;
 +    }
 +
 +    Error = RegOpenKey(NULL,
 +                       L"\\Registry\\Machine\\SYSTEM",
 +                       &SystemKey);
 +    if (Error != ERROR_SUCCESS)
 +    {
 +        ERR("RegOpenKey(SystemKey) failed (Error %lu)\n", Error);
 +        return Error;
 +    }
 +
 +    Error = RegOpenKey(SystemKey,
 +                       ControlSetKeyName,
 +                       &CurrentControlSetKey);
 +    if (Error != ERROR_SUCCESS)
 +    {
 +        ERR("RegOpenKey(CurrentControlSetKey) failed (Error %lu)\n", Error);
 +        return Error;
 +    }
 +
 +    TRACE("RegInitCurrentControlSet done\n");
 +    return ERROR_SUCCESS;
 +}
 +
 +static
 +BOOLEAN
 +GetNextPathElement(
 +    _Out_ PUNICODE_STRING NextElement,
 +    _Inout_ PUNICODE_STRING RemainingPath)
 +{
 +    /* Check if there are any characters left */
 +    if (RemainingPath->Length < sizeof(WCHAR))
 +    {
 +        /* Nothing left, bail out early */
 +        return FALSE;
 +    }
 +
 +    /* The next path elements starts with the remaining path */
 +    NextElement->Buffer = RemainingPath->Buffer;
 +
 +    /* Loop until the path element ends */
 +    while ((RemainingPath->Length >= sizeof(WCHAR)) &&
 +           (RemainingPath->Buffer[0] != '\\'))
 +    {
 +        /* Skip this character */
 +        RemainingPath->Buffer++;
 +        RemainingPath->Length -= sizeof(WCHAR);
 +    }
 +
 +    NextElement->Length = (RemainingPath->Buffer - NextElement->Buffer) * sizeof(WCHAR);
 +    NextElement->MaximumLength = NextElement->Length;
 +
 +    /* Check if the path element ended with a path separator */
 +    if (RemainingPath->Length >= sizeof(WCHAR))
 +    {
 +        /* Skip the path separator */
 +        ASSERT(RemainingPath->Buffer[0] == '\\');
 +        RemainingPath->Buffer++;
 +        RemainingPath->Length -= sizeof(WCHAR);
 +    }
 +
 +    /* Return whether we got any characters */
 +    return TRUE;
 +}
 +
 +static
 +PCM_KEY_NODE
 +RegpFindSubkeyInIndex(
 +    _In_ PHHIVE Hive,
 +    _In_ PCM_KEY_INDEX IndexCell,
 +    _In_ PUNICODE_STRING SubKeyName)
 +{
 +    PCM_KEY_NODE SubKeyNode;
 +    ULONG i;
 +    TRACE("RegpFindSubkeyInIndex('%wZ')\n", SubKeyName);
 +
 +    /* Check the cell type */
 +    if ((IndexCell->Signature == CM_KEY_INDEX_ROOT) ||
 +        (IndexCell->Signature == CM_KEY_INDEX_LEAF))
 +    {
 +        ASSERT(FALSE);
 +
 +        /* Enumerate subindex cells */
 +        for (i = 0; i < IndexCell->Count; i++)
 +        {
 +            /* Get the subindex cell and call the function recursively */
 +            PCM_KEY_INDEX SubIndexCell = HvGetCell(Hive, IndexCell->List[i]);
 +
 +            SubKeyNode = RegpFindSubkeyInIndex(Hive, SubIndexCell, SubKeyName);
 +            if (SubKeyNode != NULL)
 +            {
 +                return SubKeyNode;
 +            }
 +        }
 +    }
 +    else if ((IndexCell->Signature == CM_KEY_FAST_LEAF) ||
 +             (IndexCell->Signature == CM_KEY_HASH_LEAF))
 +    {
 +        /* Directly enumerate subkey nodes */
 +        PCM_KEY_FAST_INDEX HashCell = (PCM_KEY_FAST_INDEX)IndexCell;
 +        for (i = 0; i < HashCell->Count; i++)
 +        {
 +            SubKeyNode = HvGetCell(Hive, HashCell->List[i].Cell);
 +            ASSERT(SubKeyNode->Signature == CM_KEY_NODE_SIGNATURE);
 +
 +            TRACE(" RegpFindSubkeyInIndex: checking '%.*s'\n",
 +                  SubKeyNode->NameLength, SubKeyNode->Name);
 +            if (CmCompareKeyName(SubKeyNode, SubKeyName, TRUE))
 +            {
 +                return SubKeyNode;
 +            }
 +        }
 +    }
 +    else
 +    {
 +        ASSERT(FALSE);
 +    }
 +
 +    return NULL;
 +}
 +
 +LONG
 +RegEnumKey(
 +    _In_ FRLDRHKEY Key,
 +    _In_ ULONG Index,
 +    _Out_ PWCHAR Name,
 +    _Inout_ ULONG* NameSize,
 +    _Out_opt_ FRLDRHKEY *SubKey)
 +{
 +    PHHIVE Hive = &CmHive->Hive;
 +    PCM_KEY_NODE KeyNode, SubKeyNode;
 +    PCM_KEY_INDEX IndexCell;
 +    PCM_KEY_FAST_INDEX HashCell;
 +    TRACE("RegEnumKey(%p, %lu, %p, %p->%u)\n",
 +          Key, Index, Name, NameSize, NameSize ? *NameSize : 0);
 +
 +    /* Get the key node */
 +    KeyNode = (PCM_KEY_NODE)Key;
 +    ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
 +
 +    /* Check if the index is valid */
 +    if ((KeyNode->SubKeyCounts[Stable] == 0) ||
 +        (Index >= KeyNode->SubKeyCounts[Stable]))
 +    {
 +        TRACE("RegEnumKey index out of bounds\n");
 +        return ERROR_NO_MORE_ITEMS;
 +    }
 +
 +    /* Get the index cell */
 +    IndexCell = HvGetCell(Hive, KeyNode->SubKeyLists[Stable]);
 +    TRACE("IndexCell: %x, SubKeyCounts: %x\n", IndexCell, KeyNode->SubKeyCounts[Stable]);
 +
 +    /* Check the cell type */
 +    if ((IndexCell->Signature == CM_KEY_FAST_LEAF) ||
 +        (IndexCell->Signature == CM_KEY_HASH_LEAF))
 +    {
 +        /* Get the value cell */
 +        HashCell = (PCM_KEY_FAST_INDEX)IndexCell;
 +        SubKeyNode = HvGetCell(Hive, HashCell->List[Index].Cell);
 +    }
 +    else
 +    {
 +        ASSERT(FALSE);
 +    }
 +
 +    *NameSize = CmCopyKeyName(SubKeyNode, Name, *NameSize);
 +
 +    if (SubKey != NULL)
 +    {
 +        *SubKey = (FRLDRHKEY)SubKeyNode;
 +    }
 +
 +    TRACE("RegEnumKey done -> %u, '%.*s'\n", *NameSize, *NameSize, Name);
 +    return STATUS_SUCCESS;
 +}
 +
 +LONG
 +RegOpenKey(
 +    _In_ FRLDRHKEY ParentKey,
 +    _In_z_ PCWSTR KeyName,
 +    _Out_ PFRLDRHKEY Key)
 +{
 +    UNICODE_STRING RemainingPath, SubKeyName;
 +    UNICODE_STRING CurrentControlSet = RTL_CONSTANT_STRING(L"CurrentControlSet");
 +    PHHIVE Hive = &CmHive->Hive;
 +    PCM_KEY_NODE KeyNode;
 +    PCM_KEY_INDEX IndexCell;
 +    TRACE("RegOpenKey(%p, '%S', %p)\n", ParentKey, KeyName, Key);
 +
 +    /* Initialize the remaining path name */
 +    RtlInitUnicodeString(&RemainingPath, KeyName);
 +
 +    /* Get the parent key node */
 +    KeyNode = (PCM_KEY_NODE)ParentKey;
 +
 +    /* Check if we have a parent key */
 +    if (KeyNode == NULL)
 +    {
 +        UNICODE_STRING SubKeyName1, SubKeyName2, SubKeyName3;
 +        UNICODE_STRING RegistryPath = RTL_CONSTANT_STRING(L"Registry");
 +        UNICODE_STRING MachinePath = RTL_CONSTANT_STRING(L"MACHINE");
 +        UNICODE_STRING SystemPath = RTL_CONSTANT_STRING(L"SYSTEM");
 +        TRACE("RegOpenKey: absolute path\n");
 +
 +        if ((RemainingPath.Length < sizeof(WCHAR)) ||
 +            RemainingPath.Buffer[0] != '\\')
 +        {
 +            /* The key path is not absolute */
 +            ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath);
 +            return ERROR_PATH_NOT_FOUND;
 +        }
 +
 +        /* Skip initial path separator */
 +        RemainingPath.Buffer++;
 +        RemainingPath.Length -= sizeof(WCHAR);
 +
 +        /* Get the first 3 path elements */
 +        GetNextPathElement(&SubKeyName1, &RemainingPath);
 +        GetNextPathElement(&SubKeyName2, &RemainingPath);
 +        GetNextPathElement(&SubKeyName3, &RemainingPath);
 +        TRACE("RegOpenKey: %wZ / %wZ / %wZ\n", &SubKeyName1, &SubKeyName2, &SubKeyName3);
 +
 +        /* Check if we have the correct path */
 +        if (!RtlEqualUnicodeString(&SubKeyName1, &RegistryPath, TRUE) ||
 +            !RtlEqualUnicodeString(&SubKeyName2, &MachinePath, TRUE) ||
 +            !RtlEqualUnicodeString(&SubKeyName3, &SystemPath, TRUE))
 +        {
 +            /* The key path is not inside HKLM\Machine\System */
 +            ERR("RegOpenKey: invalid path '%S' (%wZ)\n", KeyName, &RemainingPath);
 +            return ERROR_PATH_NOT_FOUND;
 +        }
 +
 +        /* Use the root key */
 +        KeyNode = RootKeyNode;
 +    }
 +
 +    ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
 +
 +    /* Check if this is the root key */
 +    if (KeyNode == RootKeyNode)
 +    {
 +        UNICODE_STRING TempPath = RemainingPath;
 +
 +        /* Get the first path element */
 +        GetNextPathElement(&SubKeyName, &TempPath);
 +
 +        /* Check if this is CurrentControlSet */
 +        if (RtlEqualUnicodeString(&SubKeyName, &CurrentControlSet, TRUE))
 +        {
 +            /* Use the CurrentControlSetKey and update the remaining path */
 +            KeyNode = (PCM_KEY_NODE)CurrentControlSetKey;
 +            RemainingPath = TempPath;
 +        }
 +    }
 +
 +    TRACE("RegOpenKey: RemainingPath '%wZ'\n", &RemainingPath);
 +
 +    /* Loop while there are path elements */
 +    while (GetNextPathElement(&SubKeyName, &RemainingPath))
 +    {
 +        TRACE("RegOpenKey: next element '%wZ'\n", &SubKeyName);
 +
 +        /* Check if there is any subkey */
 +        if (KeyNode->SubKeyCounts[Stable] == 0)
 +        {
 +            return ERROR_PATH_NOT_FOUND;
 +        }
 +
 +        /* Get the top level index cell */
 +        IndexCell = HvGetCell(Hive, KeyNode->SubKeyLists[Stable]);
 +
 +        /* Get the next sub key */
 +        KeyNode = RegpFindSubkeyInIndex(Hive, IndexCell, &SubKeyName);
 +        if (KeyNode == NULL)
 +        {
 +
 +            ERR("Did not find sub key '%wZ' (full %S)\n", &RemainingPath, KeyName);
 +            return ERROR_PATH_NOT_FOUND;
 +        }
 +    }
 +
 +    TRACE("RegOpenKey done\n");
 +    *Key = (FRLDRHKEY)KeyNode;
 +    return ERROR_SUCCESS;
 +}
 +
 +static
 +VOID
 +RepGetValueData(
 +    _In_ PHHIVE Hive,
 +    _In_ PCM_KEY_VALUE ValueCell,
 +    _Out_opt_ ULONG* Type,
 +    _Out_opt_ PUCHAR Data,
 +    _Inout_opt_ ULONG* DataSize)
 +{
 +    ULONG DataLength;
 +
 +    /* Does the caller want the type? */
 +    if (Type != NULL)
 +    {
 +        *Type = ValueCell->Type;
 +    }
 +
 +    /* Does the caller provide DataSize? */
 +    if (DataSize != NULL)
 +    {
 +        /* Get the data length */
 +        DataLength = ValueCell->DataLength & REG_DATA_SIZE_MASK;
 +
 +        /* Does the caller want the data? */
 +        if ((Data != NULL) && (*DataSize != 0))
 +        {
 +            /* Check where the data is stored */
 +            if ((DataLength <= sizeof(HCELL_INDEX)) &&
 +                 (ValueCell->DataLength & REG_DATA_IN_OFFSET))
 +            {
 +                /* The data member contains the data */
 +                RtlCopyMemory(Data,
 +                              &ValueCell->Data,
 +                              min(*DataSize, DataLength));
 +            }
 +            else
 +            {
 +                /* The data member contains the data cell index */
 +                PVOID DataCell = HvGetCell(Hive, ValueCell->Data);
 +                RtlCopyMemory(Data,
 +                              DataCell,
 +                              min(*DataSize, ValueCell->DataLength));
 +            }
 +
 +        }
 +
 +        /* Return the actual data length */
 +        *DataSize = DataLength;
 +    }
 +}
 +
 +LONG
 +RegQueryValue(
 +    _In_ FRLDRHKEY Key,
 +    _In_z_ PCWSTR ValueName,
 +    _Out_opt_ ULONG* Type,
 +    _Out_opt_ PUCHAR Data,
 +    _Inout_opt_ ULONG* DataSize)
 +{
 +    PHHIVE Hive = &CmHive->Hive;
 +    PCM_KEY_NODE KeyNode;
 +    PCM_KEY_VALUE ValueCell;
 +    PVALUE_LIST_CELL ValueListCell;
 +    UNICODE_STRING ValueNameString;
 +    ULONG i;
 +    TRACE("RegQueryValue(%p, '%S', %p, %p, %p)\n",
 +          Key, ValueName, Type, Data, DataSize);
 +
 +    /* Get the key node */
 +    KeyNode = (PCM_KEY_NODE)Key;
 +    ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
 +
 +    /* Check if there are any values */
 +    if (KeyNode->ValueList.Count == 0)
 +    {
 +        TRACE("RegQueryValue no values in key (%.*s)\n",
 +              KeyNode->NameLength, KeyNode->Name);
 +        return ERROR_INVALID_PARAMETER;
 +    }
 +
 +    /* Initialize value name string */
 +    RtlInitUnicodeString(&ValueNameString, ValueName);
 +
 +    ValueListCell = (PVALUE_LIST_CELL)HvGetCell(Hive, KeyNode->ValueList.List);
 +    TRACE("ValueListCell: %x\n", ValueListCell);
 +
 +    /* Loop all values */
 +    for (i = 0; i < KeyNode->ValueList.Count; i++)
 +    {
 +        /* Get the subkey node and check the name */
 +        ValueCell = HvGetCell(Hive, ValueListCell->ValueOffset[i]);
 +
 +        /* Compare the value name */
 +        TRACE("checking %.*s\n", ValueCell->NameLength, ValueCell->Name);
 +        if (CmCompareKeyValueName(ValueCell, &ValueNameString, TRUE))
 +        {
 +            RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
 +            TRACE("RegQueryValue success\n");
 +            return STATUS_SUCCESS;
 +        }
 +    }
 +
 +    TRACE("RegQueryValue value not found\n");
 +    return ERROR_INVALID_PARAMETER;
 +}
 +
 +
 +LONG
 +RegEnumValue(
 +    _In_ FRLDRHKEY Key,
 +    _In_ ULONG Index,
 +    _Out_ PWCHAR ValueName,
 +    _Inout_ ULONG* NameSize,
 +    _Out_ ULONG* Type,
 +    _Out_ PUCHAR Data,
 +    _Inout_ ULONG* DataSize)
 +{
 +    PHHIVE Hive = &CmHive->Hive;
 +    PCM_KEY_NODE KeyNode;
 +    PCM_KEY_VALUE ValueCell;
 +    PVALUE_LIST_CELL ValueListCell;
 +    TRACE("RegEnumValue(%p, %lu, %S, %p, %p, %p, %p (%lu))\n",
 +          Key, Index, ValueName, NameSize, Type, Data, DataSize, *DataSize);
 +
 +    /* Get the key node */
 +    KeyNode = (PCM_KEY_NODE)Key;
 +    ASSERT(KeyNode->Signature == CM_KEY_NODE_SIGNATURE);
 +
 +    /* Check if the index is valid */
 +    if ((KeyNode->ValueList.Count == 0) ||
 +        (Index >= KeyNode->ValueList.Count))
 +    {
 +        ERR("RegEnumValue: index invalid\n");
 +        return ERROR_NO_MORE_ITEMS;
 +    }
 +
 +    ValueListCell = (PVALUE_LIST_CELL)HvGetCell(Hive, KeyNode->ValueList.List);
 +    TRACE("ValueListCell: %x\n", ValueListCell);
 +
 +    /* Get the value cell */
 +    ValueCell = HvGetCell(Hive, ValueListCell->ValueOffset[Index]);
 +    ASSERT(ValueCell != NULL);
 +
 +    if (NameSize != NULL)
 +    {
 +        *NameSize = CmCopyKeyValueName(ValueCell, ValueName, *NameSize);
 +    }
 +
 +    RepGetValueData(Hive, ValueCell, Type, Data, DataSize);
 +
 +    if (DataSize != NULL)
 +    {
 +        if ((Data != NULL) && (*DataSize != 0))
 +        {
 +            RtlCopyMemory(Data,
 +                          &ValueCell->Data,
 +                          min(*DataSize, ValueCell->DataLength));
 +        }
 +
 +        *DataSize = ValueCell->DataLength;
 +    }
 +
 +    TRACE("RegEnumValue done\n");
 +    return STATUS_SUCCESS;
 +}
 +
 +/* EOF */
diff --cc cmake/gcc.cmake
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 0000000,f16d6c7..f16d6c7
mode 000000,100644..100644
--- /dev/null
index 0000000,a4a3ee3..a4a3ee3
mode 000000,100644..100644
--- /dev/null
index 0000000,9f69e21..9f69e21
mode 000000,100644..100644
--- /dev/null
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index 964dd24,0000000..e2585fc
mode 100644,000000..100644
--- /dev/null
@@@ -1,259 -1,0 +1,259 @@@
-        if (ppdev->bDDInitialized == TRUE)
 +/*
 + * ReactOS Generic Framebuffer display driver directdraw interface
 + *
 + * Copyright (C) 2006 Magnus Olsen
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#include "framebuf.h"
 +
 +VOID APIENTRY
 +DrvDisableDirectDraw( IN DHPDEV  dhpdev)
 +{
 +   PPDEV ppdev = (PPDEV)dhpdev;
 +   ppdev->bDDInitialized = FALSE;
 +   /* Add Clean up code here if we need it
 +      when we shout down directx interface */
 +}
 +
 +BOOL APIENTRY
 +DrvEnableDirectDraw(
 +  IN DHPDEV  dhpdev,
 +  OUT DD_CALLBACKS  *pCallBacks,
 +  OUT DD_SURFACECALLBACKS  *pSurfaceCallBacks,
 +  OUT DD_PALETTECALLBACKS  *pPaletteCallBacks)
 +{
 +       PPDEV ppdev = (PPDEV)dhpdev;
 +
-               if ( bDDrawHeap == TRUE)
++       if (ppdev->bDDInitialized)
 +       {
 +               return TRUE;
 +       }
 +
 +       /* Setup pixel format */
 +       ppdev->ddpfDisplay.dwSize = sizeof( DDPIXELFORMAT );
 +     ppdev->ddpfDisplay.dwFourCC = 0;
 +
 +     ppdev->ddpfDisplay.dwRBitMask = ppdev->RedMask;
 +     ppdev->ddpfDisplay.dwGBitMask = ppdev->GreenMask;
 +     ppdev->ddpfDisplay.dwBBitMask = ppdev->BlueMask;
 +
 +     ppdev->ddpfDisplay.dwRGBBitCount=ppdev->BitsPerPixel;
 +       ppdev->ddpfDisplay.dwRGBAlphaBitMask = 0;
 +       ppdev->ddpfDisplay.dwFlags = DDPF_RGB;
 +
 +       ppdev->pvmList = NULL;
 +
 +       switch(ppdev->iDitherFormat)
 +       {
 +              case BMF_8BPP:
 +             ppdev->ddpfDisplay.dwFlags  |= DDPF_PALETTEINDEXED8;
 +             break;
 +
 +        case BMF_16BPP:
 +             switch(ppdev->RedMask)
 +             {
 +                case 0x7C00:
 +                     ppdev->ddpfDisplay.dwRGBAlphaBitMask = 0x8000;
 +                     break;
 +
 +                default:
 +                     break;
 +                       }
 +             break;
 +
 +        case BMF_24BPP:
 +             break;
 +
 +        case BMF_32BPP:
 +             ppdev->ddpfDisplay.dwRGBAlphaBitMask = 0xff000000;
 +             break;
 +
 +        default:
 +           /* FIXME unknown pixel bits */
 +                      ppdev->ddpfDisplay.dwRGBBitCount=0;
 +            break;
 +       }
 +
 +       if (pCallBacks !=NULL)
 +       {
 +               memset(pCallBacks,0,sizeof(DD_CALLBACKS));
 +
 +               /* FILL pCallBacks with hal stuff */
 +         pCallBacks->dwSize = sizeof(DDHAL_DDCALLBACKS);
 +         pCallBacks->CanCreateSurface = (PDD_CANCREATESURFACE)DdCanCreateSurface;
 +         pCallBacks->CreateSurface =  (PDD_CREATESURFACE)DdCreateSurface;
 +
 +         /* Fill in the HAL Callback flags */
 +         pCallBacks->dwFlags = DDHAL_CB32_CANCREATESURFACE | DDHAL_CB32_CREATESURFACE;
 +       }
 +
 +       if (pSurfaceCallBacks !=NULL)
 +       {
 +               memset(pSurfaceCallBacks,0,sizeof(DD_SURFACECALLBACKS));
 +
 +               /* FILL pSurfaceCallBacks with hal stuff */
 +         // pSurfaceCallBacks.dwSize = sizeof(DDHAL_DDSURFACECALLBACKS);
 +         // pSurfaceCallBacks.DestroySurface = DdDestroySurface;
 +         // pSurfaceCallBacks.Lock = DdLock;
 +         // pSurfaceCallBacks.Blt = DdBlt;
 +
 +        // pSurfaceCallBacks->dwFlags = DDHAL_SURFCB32_DESTROYSURFACE | DDHAL_SURFCB32_LOCK | DDHAL_SURFCB32_BLT ;
 +       }
 +
 +       if (pPaletteCallBacks !=NULL)
 +       {
 +               memset(pPaletteCallBacks,0,sizeof(DD_PALETTECALLBACKS));
 +               /* FILL pPaletteCallBacks with hal stuff */
 +               /* We will not support this callback in the framebuf.dll */
 +       }
 +
 +
 +       /* Fixme fill the ppdev->dxHalInfo with the info we need */
 +       ppdev->bDDInitialized = TRUE;
 +       return ppdev->bDDInitialized;
 +}
 +
 +BOOL APIENTRY
 +DrvGetDirectDrawInfo(
 +  IN DHPDEV  dhpdev,
 +  OUT DD_HALINFO  *pHalInfo,
 +  OUT DWORD  *pdwNumHeaps,
 +  OUT VIDEOMEMORY  *pvmList,
 +  OUT DWORD  *pdwNumFourCCCodes,
 +  OUT DWORD  *pdwFourCC)
 +{
 +      PPDEV ppdev = (PPDEV)dhpdev;
 +      LONG i;
 +      DWORD heap = 1; /* we always alloc one heap */
 +      BOOL bDDrawHeap = FALSE;
 +
 +      if  (ppdev == NULL)
 +        return FALSE;
 +
 +      /*   check so pHalInfo,  pdwNumHeaps, pdwNumFourCCCodes is not NULL
 +           pdwFourCC and pvmList can be null
 +       */
 +
 +      if (pHalInfo == NULL)
 +              return FALSE;
 +
 +      if (pdwNumHeaps == NULL)
 +              return FALSE;
 +
 +      if (pdwNumFourCCCodes == NULL)
 +              return FALSE;
 +
 +      /*  Setup heap */
 +      if ( (ppdev->ScreenWidth < ppdev->MemWidth) || (ppdev->ScreenHeight < ppdev->MemHeight))
 +    {
 +       bDDrawHeap = TRUE;
 +       heap++;
 +    }
 +
 +    ppdev->dwHeap = heap;
 +    *pdwNumHeaps  = heap;
 +
 +      /* We do not support other fourcc */
 +    *pdwNumFourCCCodes = 0;
 +
 +
 +      /*
 +         check see if pvmList and pdwFourCC are frist call
 +         or frist. Secon call  we fill in pHalInfo info
 +    */
 +
 +      if(!(pvmList && pdwFourCC))
 +      {
 +
 +         RtlZeroMemory(pHalInfo, sizeof(DD_HALINFO));
 +         pHalInfo->dwSize = sizeof(DD_HALINFO);
 +
 +               pHalInfo->ddCaps.dwCaps =  DDCAPS_BLT        | DDCAPS_BLTQUEUE | DDCAPS_BLTCOLORFILL | DDCAPS_READSCANLINE |
 +                                              DDCAPS_BLTSTRETCH | DDCAPS_COLORKEY | DDCAPS_CANBLTSYSMEM;
 +
 +               pHalInfo->ddCaps.dwFXCaps = DDFXCAPS_BLTSTRETCHY     | DDFXCAPS_BLTSTRETCHX        |
 +                                               DDFXCAPS_BLTSTRETCHYN    | DDFXCAPS_BLTSTRETCHXN       |
 +                                                                       DDFXCAPS_BLTSHRINKY      | DDFXCAPS_BLTSHRINKX         |
 +                                     DDFXCAPS_BLTSHRINKYN     | DDFXCAPS_BLTSHRINKXN        |
 +                                                                       DDFXCAPS_BLTMIRRORUPDOWN | DDFXCAPS_BLTMIRRORLEFTRIGHT;
 +
 +              pHalInfo->ddCaps.dwCaps2 = DDCAPS2_NONLOCALVIDMEM | DDCAPS2_NONLOCALVIDMEMCAPS;
 +
 +              pHalInfo->ddCaps.ddsCaps.dwCaps =  DDSCAPS_OFFSCREENPLAIN | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP;
 +
 +              pHalInfo->ddCaps.dwCKeyCaps = DDCKEYCAPS_SRCBLT | DDCKEYCAPS_SRCBLTCLRSPACE;
 +
 +          pHalInfo->ddCaps.dwSVBCaps = DDCAPS_BLT;
 +          pHalInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM;
 +
 +              /* Calc how much memmory is left on the video cards memmory */
 +              pHalInfo->ddCaps.dwVidMemTotal = (ppdev->MemHeight - ppdev->ScreenHeight) * ppdev->ScreenDelta;
 +
 +        /* fill in some basic info that we need */
 +        pHalInfo->vmiData.pvPrimary                 = ppdev->ScreenPtr;
 +        pHalInfo->vmiData.dwDisplayWidth            = ppdev->ScreenWidth;
 +        pHalInfo->vmiData.dwDisplayHeight           = ppdev->ScreenHeight;
 +        pHalInfo->vmiData.lDisplayPitch             = ppdev->ScreenDelta;
 +        pHalInfo->vmiData.ddpfDisplay.dwSize        = sizeof(DDPIXELFORMAT);
 +        pHalInfo->vmiData.ddpfDisplay.dwFlags       = DDPF_RGB;
 +        pHalInfo->vmiData.ddpfDisplay.dwRGBBitCount = ppdev->BitsPerPixel;
 +              pHalInfo->vmiData.ddpfDisplay.dwRBitMask    = ppdev->RedMask;
 +        pHalInfo->vmiData.ddpfDisplay.dwGBitMask    = ppdev->GreenMask;
 +        pHalInfo->vmiData.ddpfDisplay.dwBBitMask    = ppdev->BlueMask;
 +        pHalInfo->vmiData.dwOffscreenAlign = 4;
 +
 +              if ( ppdev->BitsPerPixel == 8 )
 +              {
 +            pHalInfo->vmiData.ddpfDisplay.dwFlags |= DDPF_PALETTEINDEXED8;
 +        }
 +
 +          /*  FIXME
 +                  Config the rops we do not doing that yet
 +                   for we need write the rops table
 +        */
 +        for(i=0;i<DD_ROP_SPACE;i++ )
 +        {
 +           // pHALInfo->ddCaps.dwSVBRops[i] = rops[i];
 +                //  pHALInfo->ddCaps.dwRops[i] = rops[i];
 +        }
 +      }
 +
 +      /* Now build pvmList info */
 +      if(pvmList)
 +      {
 +              ppdev->pvmList = pvmList;
 +
++              if (bDDrawHeap)
 +              {
 +                      pvmList->dwFlags        = VIDMEM_ISLINEAR ;
 +            pvmList->fpStart        = ppdev->ScreenHeight * ppdev->ScreenDelta;
 +            pvmList->fpEnd          = ppdev->MemHeight * ppdev->ScreenDelta - 1;
 +                      pvmList->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
 +                      pvmList++;
 +              }
 +
 +              pvmList->fpStart = 0;
 +              pvmList->fpEnd = (ppdev->MemHeight * ppdev->ScreenDelta)  - 1;
 +              pvmList->dwFlags = VIDMEM_ISNONLOCAL | VIDMEM_ISLINEAR | VIDMEM_ISWC;
 +              pvmList->ddsCaps.dwCaps =  DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER ;
 +              pvmList->ddsCapsAlt.dwCaps = DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER;
 +
 +              pvmList = ppdev->pvmList;
 +      }
 +
 +      return TRUE;
 +}
index b1bfce5,0000000..e3a6ed6
mode 100644,000000..100644
--- /dev/null
@@@ -1,370 -1,0 +1,370 @@@
-    if (ppdev->PointerAttributes.Enable == TRUE)
 +/*
 + * ReactOS Generic Framebuffer display driver
 + *
 + * Copyright (C) 2004 Filip Navara
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#include "framebuf.h"
 +
 +#ifndef EXPERIMENTAL_MOUSE_CURSOR_SUPPORT
 +
 +/*
 + * DrvSetPointerShape
 + *
 + * Sets the new pointer shape.
 + *
 + * Status
 + *    @unimplemented
 + */
 +
 +ULONG APIENTRY
 +DrvSetPointerShape(
 +   IN SURFOBJ *pso,
 +   IN SURFOBJ *psoMask,
 +   IN SURFOBJ *psoColor,
 +   IN XLATEOBJ *pxlo,
 +   IN LONG xHot,
 +   IN LONG yHot,
 +   IN LONG x,
 +   IN LONG y,
 +   IN RECTL *prcl,
 +   IN FLONG fl)
 +{
 +/*   return SPS_DECLINE;*/
 +   return EngSetPointerShape(pso, psoMask, psoColor, pxlo, xHot, yHot, x, y, prcl, fl);
 +}
 +
 +/*
 + * DrvMovePointer
 + *
 + * Moves the pointer to a new position and ensures that GDI does not interfere
 + * with the display of the pointer.
 + *
 + * Status
 + *    @unimplemented
 + */
 +
 +VOID APIENTRY
 +DrvMovePointer(
 +   IN SURFOBJ *pso,
 +   IN LONG x,
 +   IN LONG y,
 +   IN RECTL *prcl)
 +{
 +   EngMovePointer(pso, x, y, prcl);
 +}
 +
 +#else
 +
 +VOID FASTCALL
 +IntHideMousePointer(PPDEV ppdev, SURFOBJ *DestSurface)
 +{
 +   if (ppdev->PointerAttributes.Enable == FALSE)
 +   {
 +      return;
 +   }
 +
 +   ppdev->PointerAttributes.Enable = FALSE;
 +   if (ppdev->PointerSaveSurface != NULL)
 +   {
 +      RECTL DestRect;
 +      POINTL SrcPoint;
 +      SURFOBJ *SaveSurface;
 +      SURFOBJ *MaskSurface;
 +
 +      DestRect.left = max(ppdev->PointerAttributes.Column, 0);
 +      DestRect.top = max(ppdev->PointerAttributes.Row, 0);
 +      DestRect.right = min(
 +         ppdev->PointerAttributes.Column + ppdev->PointerAttributes.Width,
 +         ppdev->ScreenWidth - 1);
 +      DestRect.bottom = min(
 +         ppdev->PointerAttributes.Row + ppdev->PointerAttributes.Height,
 +         ppdev->ScreenHeight - 1);
 +
 +      SrcPoint.x = max(-ppdev->PointerAttributes.Column, 0);
 +      SrcPoint.y = max(-ppdev->PointerAttributes.Row, 0);
 +
 +      SaveSurface = EngLockSurface(ppdev->PointerSaveSurface);
 +      MaskSurface = EngLockSurface(ppdev->PointerMaskSurface);
 +      EngBitBlt(DestSurface, SaveSurface, MaskSurface, NULL, NULL,
 +                &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, SRCCOPY);
 +      EngUnlockSurface(MaskSurface);
 +      EngUnlockSurface(SaveSurface);
 +   }
 +}
 +
 +VOID FASTCALL
 +IntShowMousePointer(PPDEV ppdev, SURFOBJ *DestSurface)
 +{
++   if (ppdev->PointerAttributes.Enable)
 +   {
 +      return;
 +   }
 +
 +   ppdev->PointerAttributes.Enable = TRUE;
 +
 +   /*
 +    * Copy the pixels under the cursor to temporary surface.
 +    */
 +
 +   if (ppdev->PointerSaveSurface != NULL)
 +   {
 +      RECTL DestRect;
 +      POINTL SrcPoint;
 +      SURFOBJ *SaveSurface;
 +
 +      SrcPoint.x = max(ppdev->PointerAttributes.Column, 0);
 +      SrcPoint.y = max(ppdev->PointerAttributes.Row, 0);
 +
 +      DestRect.left = SrcPoint.x - ppdev->PointerAttributes.Column;
 +      DestRect.top = SrcPoint.y - ppdev->PointerAttributes.Row;
 +      DestRect.right = min(
 +         ppdev->PointerAttributes.Width,
 +         ppdev->ScreenWidth - ppdev->PointerAttributes.Column - 1);
 +      DestRect.bottom = min(
 +         ppdev->PointerAttributes.Height,
 +         ppdev->ScreenHeight - ppdev->PointerAttributes.Row - 1);
 +
 +      SaveSurface = EngLockSurface(ppdev->PointerSaveSurface);
 +      EngBitBlt(SaveSurface, DestSurface, NULL, NULL, NULL,
 +                &DestRect, &SrcPoint, NULL, NULL, NULL, SRCCOPY);
 +      EngUnlockSurface(SaveSurface);
 +   }
 +
 +   /*
 +    * Blit the cursor on the screen.
 +    */
 +
 +   {
 +      RECTL DestRect;
 +      POINTL SrcPoint;
 +      SURFOBJ *ColorSurf;
 +      SURFOBJ *MaskSurf;
 +
 +      DestRect.left = max(ppdev->PointerAttributes.Column, 0);
 +      DestRect.top = max(ppdev->PointerAttributes.Row, 0);
 +      DestRect.right = min(
 +         ppdev->PointerAttributes.Column + ppdev->PointerAttributes.Width,
 +         ppdev->ScreenWidth - 1);
 +      DestRect.bottom = min(
 +         ppdev->PointerAttributes.Row + ppdev->PointerAttributes.Height,
 +         ppdev->ScreenHeight - 1);
 +
 +      SrcPoint.x = max(-ppdev->PointerAttributes.Column, 0);
 +      SrcPoint.y = max(-ppdev->PointerAttributes.Row, 0);
 +
 +      MaskSurf = EngLockSurface(ppdev->PointerMaskSurface);
 +      if (ppdev->PointerColorSurface != NULL)
 +      {
 +         ColorSurf = EngLockSurface(ppdev->PointerColorSurface);
 +         EngBitBlt(DestSurface, ColorSurf, MaskSurf, NULL, ppdev->PointerXlateObject,
 +                   &DestRect, &SrcPoint, &SrcPoint, NULL, NULL, 0xAACC);
 +         EngUnlockSurface(ColorSurf);
 +      }
 +      else
 +      {
 +         /* FIXME */
 +         EngBitBlt(DestSurface, MaskSurf, NULL, NULL, ppdev->PointerXlateObject,
 +                   &DestRect, &SrcPoint, NULL, NULL, NULL, SRCAND);
 +         SrcPoint.y += ppdev->PointerAttributes.Height;
 +         EngBitBlt(DestSurface, MaskSurf, NULL, NULL, ppdev->PointerXlateObject,
 +                   &DestRect, &SrcPoint, NULL, NULL, NULL, SRCINVERT);
 +      }
 +      EngUnlockSurface(MaskSurf);
 +   }
 +}
 +
 +/*
 + * DrvSetPointerShape
 + *
 + * Sets the new pointer shape.
 + *
 + * Status
 + *    @implemented
 + */
 +
 +ULONG APIENTRY
 +DrvSetPointerShape(
 +   IN SURFOBJ *pso,
 +   IN SURFOBJ *psoMask,
 +   IN SURFOBJ *psoColor,
 +   IN XLATEOBJ *pxlo,
 +   IN LONG xHot,
 +   IN LONG yHot,
 +   IN LONG x,
 +   IN LONG y,
 +   IN RECTL *prcl,
 +   IN FLONG fl)
 +{
 +   PPDEV ppdev = (PPDEV)pso->dhpdev;
 +   SURFOBJ *TempSurfObj;
 +
 +   IntHideMousePointer(ppdev, pso);
 +
 +   if (ppdev->PointerColorSurface != NULL)
 +   {
 +      /* FIXME: Is this really needed? */
 +      TempSurfObj = EngLockSurface(ppdev->PointerColorSurface);
 +      EngFreeMem(TempSurfObj->pvBits);
 +      TempSurfObj->pvBits = 0;
 +      EngUnlockSurface(TempSurfObj);
 +
 +      EngDeleteSurface(ppdev->PointerColorSurface);
 +      ppdev->PointerMaskSurface = NULL;
 +   }
 +
 +   if (ppdev->PointerMaskSurface != NULL)
 +   {
 +      /* FIXME: Is this really needed? */
 +      TempSurfObj = EngLockSurface(ppdev->PointerMaskSurface);
 +      EngFreeMem(TempSurfObj->pvBits);
 +      TempSurfObj->pvBits = 0;
 +      EngUnlockSurface(TempSurfObj);
 +
 +      EngDeleteSurface(ppdev->PointerMaskSurface);
 +      ppdev->PointerMaskSurface = NULL;
 +   }
 +
 +   if (ppdev->PointerSaveSurface != NULL)
 +   {
 +      EngDeleteSurface(ppdev->PointerSaveSurface);
 +      ppdev->PointerSaveSurface = NULL;
 +   }
 +
 +   /*
 +    * See if we are being asked to hide the pointer.
 +    */
 +
 +   if (psoMask == NULL)
 +   {
 +      return SPS_ACCEPT_EXCLUDE;
 +   }
 +
 +   ppdev->PointerHotSpot.x = xHot;
 +   ppdev->PointerHotSpot.y = yHot;
 +
 +   ppdev->PointerXlateObject = pxlo;
 +   ppdev->PointerAttributes.Column = x - xHot;
 +   ppdev->PointerAttributes.Row = y - yHot;
 +   ppdev->PointerAttributes.Width = psoMask->lDelta << 3;
 +   ppdev->PointerAttributes.Height = (psoMask->cjBits / psoMask->lDelta) >> 1;
 +
 +   if (psoColor != NULL)
 +   {
 +      SIZEL Size;
 +      PBYTE Bits;
 +
 +      Size.cx = ppdev->PointerAttributes.Width;
 +      Size.cy = ppdev->PointerAttributes.Height;
 +      Bits = EngAllocMem(0, psoColor->cjBits, ALLOC_TAG);
 +      memcpy(Bits, psoColor->pvBits, psoColor->cjBits);
 +
 +      ppdev->PointerColorSurface = (HSURF)EngCreateBitmap(Size,
 +         psoColor->lDelta, psoColor->iBitmapFormat, 0, Bits);
 +   }
 +   else
 +   {
 +      ppdev->PointerColorSurface = NULL;
 +   }
 +
 +   if (psoMask != NULL)
 +   {
 +      SIZEL Size;
 +      PBYTE Bits;
 +
 +      Size.cx = ppdev->PointerAttributes.Width;
 +      Size.cy = ppdev->PointerAttributes.Height << 1;
 +      Bits = EngAllocMem(0, psoMask->cjBits, ALLOC_TAG);
 +      memcpy(Bits, psoMask->pvBits, psoMask->cjBits);
 +
 +      ppdev->PointerMaskSurface = (HSURF)EngCreateBitmap(Size,
 +         psoMask->lDelta, psoMask->iBitmapFormat, 0, Bits);
 +   }
 +   else
 +   {
 +      ppdev->PointerMaskSurface = NULL;
 +   }
 +
 +   /*
 +    * Create surface for saving the pixels under the cursor.
 +    */
 +
 +   {
 +      SIZEL Size;
 +      LONG lDelta;
 +
 +      Size.cx = ppdev->PointerAttributes.Width;
 +      Size.cy = ppdev->PointerAttributes.Height;
 +
 +      switch (pso->iBitmapFormat)
 +      {
 +         case BMF_8BPP: lDelta = Size.cx; break;
 +         case BMF_16BPP: lDelta = Size.cx << 1; break;
 +         case BMF_24BPP: lDelta = Size.cx * 3; break;
 +         case BMF_32BPP: lDelta = Size.cx << 2; break;
 +      }
 +
 +      ppdev->PointerSaveSurface = (HSURF)EngCreateBitmap(
 +         Size, lDelta, pso->iBitmapFormat, BMF_NOZEROINIT, NULL);
 +   }
 +
 +   IntShowMousePointer(ppdev, pso);
 +
 +   return SPS_ACCEPT_EXCLUDE;
 +}
 +
 +/*
 + * DrvMovePointer
 + *
 + * Moves the pointer to a new position and ensures that GDI does not interfere
 + * with the display of the pointer.
 + *
 + * Status
 + *    @implemented
 + */
 +
 +VOID APIENTRY
 +DrvMovePointer(
 +   IN SURFOBJ *pso,
 +   IN LONG x,
 +   IN LONG y,
 +   IN RECTL *prcl)
 +{
 +   PPDEV ppdev = (PPDEV)pso->dhpdev;
 +   BOOL WasVisible;
 +
 +   WasVisible = ppdev->PointerAttributes.Enable;
 +   if (WasVisible)
 +   {
 +      IntHideMousePointer(ppdev, pso);
 +   }
 +
 +   if (x == -1)
 +   {
 +      return;
 +   }
 +
 +   ppdev->PointerAttributes.Column = x - ppdev->PointerHotSpot.x;
 +   ppdev->PointerAttributes.Row = y - ppdev->PointerHotSpot.y;
 +
 +   if (WasVisible)
 +   {
 +      IntShowMousePointer(ppdev, pso);
 +   }
 +}
 +
 +#endif
index 5b93b91,0000000..9b352a2
mode 100644,000000..100644
--- /dev/null
@@@ -1,260 -1,0 +1,260 @@@
-        if (ppdev->bDDInitialized == TRUE)
 +/*
 + * ReactOS Generic Framebuffer display driver directdraw interface
 + *
 + * Copyright (C) 2006 Magnus Olsen
 + *
 + * This program is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU General Public License
 + * as published by the Free Software Foundation; either version 2
 + * of the License, or (at your option) any later version.
 + *
 + * This program is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU General Public License for more details.
 + *
 + * You should have received a copy of the GNU General Public License along
 + * with this program; if not, write to the Free Software Foundation, Inc.,
 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 + */
 +
 +#include "framebuf.h"
 +
 +VOID APIENTRY
 +DrvDisableDirectDraw( IN DHPDEV  dhpdev)
 +{
 +   PPDEV ppdev = (PPDEV)dhpdev;
 +   ppdev->bDDInitialized = FALSE;
 +   /* Add Clean up code here if we need it
 +      when we shout down directx interface */
 +}
 +
 +BOOL APIENTRY
 +DrvEnableDirectDraw(
 +  IN DHPDEV  dhpdev,
 +  OUT DD_CALLBACKS  *pCallBacks,
 +  OUT DD_SURFACECALLBACKS  *pSurfaceCallBacks,
 +  OUT DD_PALETTECALLBACKS  *pPaletteCallBacks)
 +{
 +       PPDEV ppdev = (PPDEV)dhpdev;
 +
-               if ( bDDrawHeap == TRUE)
++       if (ppdev->bDDInitialized)
 +       {
 +               return TRUE;
 +       }
 +
 +       /* Setup pixel format */
 +       ppdev->ddpfDisplay.dwSize = sizeof( DDPIXELFORMAT );
 +     ppdev->ddpfDisplay.dwFourCC = 0;
 +
 +     ppdev->ddpfDisplay.dwRBitMask = ppdev->RedMask;
 +     ppdev->ddpfDisplay.dwGBitMask = ppdev->GreenMask;
 +     ppdev->ddpfDisplay.dwBBitMask = ppdev->BlueMask;
 +
 +     ppdev->ddpfDisplay.dwRGBBitCount=ppdev->BitsPerPixel;
 +       ppdev->ddpfDisplay.dwRGBAlphaBitMask = 0;
 +       ppdev->ddpfDisplay.dwFlags = DDPF_RGB;
 +
 +       ppdev->pvmList = NULL;
 +
 +       switch(ppdev->iDitherFormat)
 +       {
 +              case BMF_8BPP:
 +             ppdev->ddpfDisplay.dwFlags  |= DDPF_PALETTEINDEXED8;
 +             break;
 +
 +        case BMF_16BPP:
 +             switch(ppdev->RedMask)
 +             {
 +                case 0x7C00:
 +                     ppdev->ddpfDisplay.dwRGBAlphaBitMask = 0x8000;
 +                     break;
 +
 +                default:
 +                     break;
 +                       }
 +             break;
 +
 +        case BMF_24BPP:
 +             break;
 +
 +        case BMF_32BPP:
 +             ppdev->ddpfDisplay.dwRGBAlphaBitMask = 0xff000000;
 +             break;
 +
 +        default:
 +           /* FIXME unknown pixel bits */
 +                      ppdev->ddpfDisplay.dwRGBBitCount=0;
 +            break;
 +       }
 +
 +       if (pCallBacks !=NULL)
 +       {
 +               memset(pCallBacks,0,sizeof(DD_CALLBACKS));
 +
 +               /* FILL pCallBacks with hal stuff */
 +         pCallBacks->dwSize = sizeof(DDHAL_DDCALLBACKS);
 +         pCallBacks->CanCreateSurface = (PDD_CANCREATESURFACE)DdCanCreateSurface;
 +         pCallBacks->CreateSurface =  (PDD_CREATESURFACE)DdCreateSurface;
 +
 +         /* Fill in the HAL Callback flags */
 +         pCallBacks->dwFlags = DDHAL_CB32_CANCREATESURFACE | DDHAL_CB32_CREATESURFACE;
 +       }
 +
 +       if (pSurfaceCallBacks !=NULL)
 +       {
 +               memset(pSurfaceCallBacks,0,sizeof(DD_SURFACECALLBACKS));
 +
 +               /* FILL pSurfaceCallBacks with hal stuff */
 +         // pSurfaceCallBacks.dwSize = sizeof(DDHAL_DDSURFACECALLBACKS);
 +         // pSurfaceCallBacks.DestroySurface = DdDestroySurface;
 +         // pSurfaceCallBacks.Lock = DdLock;
 +         // pSurfaceCallBacks.Blt = DdBlt;
 +
 +        // pSurfaceCallBacks->dwFlags = DDHAL_SURFCB32_DESTROYSURFACE | DDHAL_SURFCB32_LOCK | DDHAL_SURFCB32_BLT ;
 +       }
 +
 +       if (pPaletteCallBacks !=NULL)
 +       {
 +               memset(pPaletteCallBacks,0,sizeof(DD_PALETTECALLBACKS));
 +               /* FILL pPaletteCallBacks with hal stuff */
 +               /* We will not support this callback in the framebuf.dll */
 +       }
 +
 +
 +       /* Fixme fill the ppdev->dxHalInfo with the info we need */
 +       ppdev->bDDInitialized = TRUE;
 +       return ppdev->bDDInitialized;
 +}
 +
 +BOOL APIENTRY
 +DrvGetDirectDrawInfo(
 +  IN DHPDEV  dhpdev,
 +  OUT DD_HALINFO  *pHalInfo,
 +  OUT DWORD  *pdwNumHeaps,
 +  OUT VIDEOMEMORY  *pvmList,
 +  OUT DWORD  *pdwNumFourCCCodes,
 +  OUT DWORD  *pdwFourCC)
 +{
 +      PPDEV ppdev = (PPDEV)dhpdev;
 +      LONG i;
 +      DWORD heap = 1; /* we always alloc one heap */
 +      BOOL bDDrawHeap = FALSE;
 +
 +      if  (ppdev == NULL)
 +        return FALSE;
 +
 +      /*   check so pHalInfo,  pdwNumHeaps, pdwNumFourCCCodes is not NULL
 +           pdwFourCC and pvmList can be null
 +       */
 +
 +      if (pHalInfo == NULL)
 +              return FALSE;
 +
 +      if (pdwNumHeaps == NULL)
 +              return FALSE;
 +
 +      if (pdwNumFourCCCodes == NULL)
 +              return FALSE;
 +
 +      /*  Setup heap */
 +      if ( (ppdev->ScreenWidth < ppdev->MemWidth) || (ppdev->ScreenHeight < ppdev->MemHeight))
 +    {
 +       bDDrawHeap = TRUE;
 +       heap++;
 +    }
 +
 +    ppdev->dwHeap = heap;
 +    *pdwNumHeaps  = heap;
 +
 +      /* We do not support other fourcc */
 +    *pdwNumFourCCCodes = 0;
 +
 +
 +      /*
 +         check see if pvmList and pdwFourCC are frist call
 +         or frist. Secon call  we fill in pHalInfo info
 +    */
 +
 +      if(!(pvmList && pdwFourCC))
 +      {
 +
 +         RtlZeroMemory(pHalInfo, sizeof(DD_HALINFO));
 +         pHalInfo->dwSize = sizeof(DD_HALINFO);
 +
 +               pHalInfo->ddCaps.dwCaps =  DDCAPS_BLT        | DDCAPS_BLTQUEUE | DDCAPS_BLTCOLORFILL | DDCAPS_READSCANLINE |
 +                                              DDCAPS_BLTSTRETCH | DDCAPS_COLORKEY | DDCAPS_CANBLTSYSMEM;
 +
 +               pHalInfo->ddCaps.dwFXCaps = DDFXCAPS_BLTSTRETCHY     | DDFXCAPS_BLTSTRETCHX        |
 +                                               DDFXCAPS_BLTSTRETCHYN    | DDFXCAPS_BLTSTRETCHXN       |
 +                                                                       DDFXCAPS_BLTSHRINKY      | DDFXCAPS_BLTSHRINKX         |
 +                                     DDFXCAPS_BLTSHRINKYN     | DDFXCAPS_BLTSHRINKXN        |
 +                                                                       DDFXCAPS_BLTMIRRORUPDOWN | DDFXCAPS_BLTMIRRORLEFTRIGHT;
 +
 +              pHalInfo->ddCaps.dwCaps2 = DDCAPS2_NONLOCALVIDMEM | DDCAPS2_NONLOCALVIDMEMCAPS;
 +
 +              pHalInfo->ddCaps.ddsCaps.dwCaps =  DDSCAPS_OFFSCREENPLAIN | DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP;
 +
 +              pHalInfo->ddCaps.dwCKeyCaps = DDCKEYCAPS_SRCBLT | DDCKEYCAPS_SRCBLTCLRSPACE;
 +
 +          pHalInfo->ddCaps.dwSVBCaps = DDCAPS_BLT;
 +          pHalInfo->ddCaps.ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM;
 +
 +              /* Calc how much memmory is left on the video cards memmory */
 +              pHalInfo->ddCaps.dwVidMemTotal = (ppdev->MemHeight - ppdev->ScreenHeight) * ppdev->ScreenDelta;
 +
 +        /* fill in some basic info that we need */
 +        pHalInfo->vmiData.pvPrimary                 = ppdev->ScreenPtr;
 +        pHalInfo->vmiData.dwDisplayWidth            = ppdev->ScreenWidth;
 +        pHalInfo->vmiData.dwDisplayHeight           = ppdev->ScreenHeight;
 +        pHalInfo->vmiData.lDisplayPitch             = ppdev->ScreenDelta;
 +        pHalInfo->vmiData.ddpfDisplay.dwSize        = sizeof(DDPIXELFORMAT);
 +        pHalInfo->vmiData.ddpfDisplay.dwFlags       = DDPF_RGB;
 +        pHalInfo->vmiData.ddpfDisplay.dwRGBBitCount = ppdev->BitsPerPixel;
 +              pHalInfo->vmiData.ddpfDisplay.dwRBitMask    = ppdev->RedMask;
 +        pHalInfo->vmiData.ddpfDisplay.dwGBitMask    = ppdev->GreenMask;
 +        pHalInfo->vmiData.ddpfDisplay.dwBBitMask    = ppdev->BlueMask;
 +        pHalInfo->vmiData.dwOffscreenAlign = 4;
 +
 +              if ( ppdev->BitsPerPixel == 8 )
 +              {
 +            pHalInfo->vmiData.ddpfDisplay.dwFlags |= DDPF_PALETTEINDEXED8;
 +        }
 +
 +          /*  FIXME
 +                  Config the rops we do not doing that yet
 +                   for we need write the rops table
 +        */
 +        for(i=0;i<DD_ROP_SPACE;i++ )
 +        {
 +           // pHALInfo->ddCaps.dwSVBRops[i] = rops[i];
 +                //  pHALInfo->ddCaps.dwRops[i] = rops[i];
 +        }
 +      }
 +
 +      /* Now build pvmList info */
 +      if(pvmList)
 +      {
 +              ppdev->pvmList = pvmList;
 +
++              if (bDDrawHeap)
 +              {
 +                      pvmList->dwFlags        = VIDMEM_ISLINEAR ;
 +            pvmList->fpStart        = ppdev->ScreenHeight * ppdev->ScreenDelta;
 +            pvmList->fpEnd          = ppdev->MemHeight * ppdev->ScreenDelta - 1;
 +                      pvmList->ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
 +                      pvmList++;
 +              }
 +
 +              pvmList->fpStart = 0;
 +              pvmList->fpEnd = (ppdev->MemHeight * ppdev->ScreenDelta)  - 1;
 +              pvmList->dwFlags = VIDMEM_ISNONLOCAL | VIDMEM_ISLINEAR | VIDMEM_ISWC;
 +              pvmList->ddsCaps.dwCaps =  DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER ;
 +              pvmList->ddsCapsAlt.dwCaps = DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER;
 +
 +              pvmList = ppdev->pvmList;
 +      }
 +
 +      return TRUE;
 +}
 +
index 80d032c,0000000..eb17d5d
mode 100644,000000..100644
--- /dev/null
@@@ -1,598 -1,0 +1,598 @@@
-     if(Enable==TRUE)
 +/*
 + * PROJECT:         ReactOS VGA display driver
 + * LICENSE:         GPL - See COPYING in the top level directory
 + * FILE:            drivers/video/displays/vga/main/enable.c
 + * PURPOSE:         
 + * PROGRAMMERS:     
 + */
 +
 +#include <vgaddi.h>
 +
 +static BOOL VGAInitialized = FALSE;
 +
 +static DRVFN FuncList[] =
 +{
 +    /* Required Display driver fuctions */
 +    {INDEX_DrvAssertMode, (PFN) DrvAssertMode},
 +    {INDEX_DrvCompletePDEV, (PFN) DrvCompletePDEV},
 +    {INDEX_DrvCopyBits, (PFN) DrvCopyBits},
 +    {INDEX_DrvDisablePDEV, (PFN) DrvDisablePDEV},
 +    {INDEX_DrvDisableSurface, (PFN) DrvDisableSurface},
 +    {INDEX_DrvEnablePDEV, (PFN) DrvEnablePDEV},
 +    {INDEX_DrvEnableSurface, (PFN) DrvEnableSurface},
 +    {INDEX_DrvGetModes, (PFN) DrvGetModes},
 +    {INDEX_DrvLineTo, (PFN) DrvLineTo},
 +    {INDEX_DrvPaint, (PFN) DrvPaint},
 +    {INDEX_DrvBitBlt, (PFN) DrvBitBlt},
 +    {INDEX_DrvTransparentBlt, (PFN) DrvTransparentBlt},
 +    {INDEX_DrvMovePointer, (PFN) DrvMovePointer},
 +    {INDEX_DrvSetPointerShape, (PFN) DrvSetPointerShape},
 +
 +#if 0
 +    /* Optional Display driver functions */
 +    {INDEX_, },
 +    {INDEX_DescribePixelFormat, (PFN) VGADDIDescribePixelFormat},
 +    {INDEX_DrvDitherColor, (PFN) VGADDIDitherColor},
 +    {INDEX_DrvFillPath, (PFN) VGADDIFillPath},
 +    {INDEX_DrvGetTrueTypeFile, (PFN) VGADDIGetTrueTypeFile},
 +    {INDEX_DrvLoadFontFile, (PFN) VGADDILoadFontFile},
 +    {INDEX_DrvQueryFont, (PFN) VGADDIQueryFont},
 +    {INDEX_DrvQueryFontCaps, (PFN) VGADDIQueryFontCaps},
 +    {INDEX_DrvQueryFontData, (PFN) VGADDIQueryFontData},
 +    {INDEX_DrvQueryFontFile, (PFN) VGADDIQueryFontFile},
 +    {INDEX_DrvQueryFontTree, (PFN) VGADDIQueryFontTree},
 +    {INDEX_DrvQueryTrueTypeOutline, (PFN) VGADDIQueryTrueTypeOutline},
 +    {INDEX_DrvQueryTrueTypeTable, (PFN) VGADDIQueryTrueTypeTable},
 +    {INDEX_DrvRealizeBrush, (PFN) VGADDIRealizeBrush},
 +    {INDEX_DrvResetPDEV, (PFN) VGADDIResetPDEV},
 +    {INDEX_DrvSetPalette, (PFN) VGADDISetPalette},
 +    {INDEX_DrvSetPixelFormat, (PFN) VGADDISetPixelFormat},
 +    {INDEX_DrvStretchBlt, (PFN) VGADDIStretchBlt},
 +    {INDEX_DrvStrokePath, (PFN) VGADDIStrokePath},
 +    {INDEX_DrvSwapBuffers, (PFN) VGADDISwapBuffers},
 +    {INDEX_DrvTextOut, (PFN) VGADDITextOut},
 +    {INDEX_DrvUnloadFontFile, (PFN) VGADDIUnloadFontFile},
 +#endif
 +};
 +
 +static GDIINFO gaulCap = {
 +    GDI_DRIVER_VERSION,    // ulVersion
 +    DT_RASDISPLAY,         // ulTechnology
 +    0,                     // ulHorzSize
 +    0,                     // ulVertSize
 +    0,                     // ulHorzRes (filled in at initialization)
 +    0,                     // ulVertRes (filled in at initialization)
 +    4,                     // cBitsPixel
 +    1,                     // cPlanes
 +    16,                    // ulNumColors
 +    0,                     // flRaster (DDI reserved field)
 +
 +    96,                    // ulLogPixelsX (must be set to 96 according to MSDN)
 +    96,                    // ulLogPixelsY (must be set to 96 according to MSDN)
 +
 +    TC_RA_ABLE | TC_SCROLLBLT,  // flTextCaps
 +
 +    6,                     // ulDACRed
 +    6,                     // ulDACGreen
 +    6,                     // ulDACBlue
 +
 +    0x0024,                // ulAspectX  (one-to-one aspect ratio)
 +    0x0024,                // ulAspectY
 +    0x0033,                // ulAspectXY
 +
 +    1,                     // xStyleStep
 +    1,                     // yStyleSte;
 +    3,                     // denStyleStep
 +
 +    { 0, 0 },              // ptlPhysOffset
 +    { 0, 0 },              // szlPhysSize
 +
 +    0,                     // ulNumPalReg (win3.1 16 color drivers say 0 too)
 +
 +// These fields are for halftone initialization.
 +
 +    {                                         // ciDevice, ColorInfo
 +        { 6700, 3300, 0 },                      // Red
 +        { 2100, 7100, 0 },                      // Green
 +        { 1400,  800, 0 },                      // Blue
 +        { 1750, 3950, 0 },                      // Cyan
 +        { 4050, 2050, 0 },                      // Magenta
 +        { 4400, 5200, 0 },                      // Yellow
 +        { 3127, 3290, 0 },                      // AlignmentWhite
 +        20000,                                  // RedGamma
 +        20000,                                  // GreenGamma
 +        20000,                                  // BlueGamma
 +        0, 0, 0, 0, 0, 0
 +    },
 +
 +    0,                                         // ulDevicePelsDPI
 +    PRIMARY_ORDER_CBA,                         // ulPrimaryOrder
 +    HT_PATSIZE_4x4_M,                          // ulHTPatternSize
 +    HT_FORMAT_4BPP_IRGB,                       // ulHTOutputFormat
 +    HT_FLAG_ADDITIVE_PRIMS,                    // flHTFlags
 +
 +    0,                                         // ulVRefresh
 +    8,                                         // ulBltAlignment
 +    0,                                         // ulPanningHorzRes
 +    0,                                         // ulPanningVertRes
 +
 +    0,                                         // xPanningAlignment
 +    0,                                         // yPanningAlignment
 +    0,                                         // cxHTPat
 +    0,                                         // cyHTPat
 +    NULL,                                      // pHTPatA
 +    NULL,                                      // pHTPatB
 +    NULL,                                      // pHTPatC
 +    0,                                         // flShadeBlend
 +    0,                                         // ulPhysicalPixelCharacteristics
 +    0                                          // ulPhysicalPixelGamma
 +};
 +
 +// Palette for VGA
 +
 +typedef struct _VGALOGPALETTE
 +{
 +    USHORT ident;
 +    USHORT NumEntries;
 +    PALETTEENTRY PaletteEntry[16];
 +} VGALOGPALETTE;
 +
 +const VGALOGPALETTE VGApalette =
 +{
 +
 +    0x400,  // driver version
 +    16,     // num entries
 +    {
 +        { 0x00, 0x00, 0x00, 0x00 }, // 0
 +        { 0x80, 0x00, 0x00, 0x00 }, // 1
 +        { 0x00, 0x80, 0x00, 0x00 }, // 2
 +        { 0x80, 0x80, 0x00, 0x00 }, // 3
 +        { 0x00, 0x00, 0x80, 0x00 }, // 4
 +        { 0x80, 0x00, 0x80, 0x00 }, // 5
 +        { 0x00, 0x80, 0x80, 0x00 }, // 6
 +        { 0x80, 0x80, 0x80, 0x00 }, // 7
 +        { 0xc0, 0xc0, 0xc0, 0x00 }, // 8
 +        { 0xff, 0x00, 0x00, 0x00 }, // 9
 +        { 0x00, 0xff, 0x00, 0x00 }, // 10
 +        { 0xff, 0xff, 0x00, 0x00 }, // 11
 +        { 0x00, 0x00, 0xff, 0x00 }, // 12
 +        { 0xff, 0x00, 0xff, 0x00 }, // 13
 +        { 0x00, 0xff, 0xff, 0x00 }, // 14
 +        { 0xff, 0xff, 0xff, 0x00 } // 15
 +    }
 +};
 +
 +// Devinfo structure passed back to the engine in DrvEnablePDEV
 +
 +#define SYSTM_LOGFONT {16,7,0,0,700,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,VARIABLE_PITCH | FF_DONTCARE, L"System"}
 +#define HELVE_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,VARIABLE_PITCH | FF_DONTCARE, L"MS Sans Serif"}
 +#define COURI_LOGFONT {12,9,0,0,400,0,0,0,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_STROKE_PRECIS,PROOF_QUALITY,FIXED_PITCH | FF_DONTCARE, L"Courier"}
 +
 +DEVINFO devinfoVGA =
 +{
 +    (GCAPS_OPAQUERECT | GCAPS_HORIZSTRIKE | GCAPS_ALTERNATEFILL | GCAPS_MONO_DITHER | GCAPS_COLOR_DITHER |
 +     GCAPS_WINDINGFILL | GCAPS_DITHERONREALIZE
 +    ),       // Graphics capabilities
 +
 +    SYSTM_LOGFONT,  // Default font description
 +    HELVE_LOGFONT,  // ANSI variable font description
 +    COURI_LOGFONT,  // ANSI fixed font description
 +    0,              // Count of device fonts
 +    BMF_4BPP,       // preferred DIB format
 +    8,              // Width of color dither
 +    8,              // Height of color dither
 +    NULL,           // Default palette to use for this device
 +    0               // flGraphicsCaps2
 +};
 +
 +BOOL APIENTRY
 +DrvEnableDriver(IN ULONG EngineVersion,
 +                IN ULONG SizeOfDED,
 +                OUT PDRVENABLEDATA DriveEnableData)
 +{
 +    DPRINT("DrvEnableDriver called...\n");
 +
 +    vgaPreCalc();
 +
 +    VGADDI_InitializeOffScreenMem((SCREEN_X * SCREEN_Y) >> 3, 65536 - ((SCREEN_X * SCREEN_Y) >> 3));
 +
 +    DriveEnableData->pdrvfn = FuncList;
 +    DriveEnableData->c = sizeof(FuncList) / sizeof(DRVFN);
 +    DriveEnableData->iDriverVersion = DDI_DRIVER_VERSION_NT4;
 +
 +    return  TRUE;
 +}
 +
 +//    DrvDisableDriver
 +//  DESCRIPTION:
 +//    This function is called by the KMGDI at exit.  It should cleanup.
 +//  ARGUMENTS:
 +//    NONE
 +//  RETURNS:
 +//    NONE
 +
 +VOID APIENTRY
 +DrvDisableDriver(VOID)
 +{
 +    return;
 +}
 +
 +//  -----------------------------------------------  Driver Implementation
 +
 +
 +//    DrvEnablePDEV
 +//  DESCRIPTION:
 +//    This function is called after DrvEnableDriver to get information
 +//    about the mode that is to be used.  This function just returns
 +//    information, and should not yet initialize the mode.
 +//  ARGUMENTS:
 +//    IN DEVMODEW *  DM            Describes the mode requested
 +//    IN LPWSTR      LogAddress
 +//    IN ULONG       PatternCount  number of patterns expected
 +//    OUT HSURF *    SurfPatterns  array to contain pattern handles
 +//    IN ULONG       GDIInfoSize   the size of the GDIInfo object passed in
 +//    OUT ULONG *    GDIInfo       GDI Info object
 +//    IN ULONG       DevInfoSize   the size of the DevInfo object passed in
 +//    OUT ULONG *    DevInfo       Device Info object
 +//    IN LPWSTR      DevDataFile   ignore
 +//    IN LPWSTR      DeviceName    Device name
 +//    IN HANDLE      Driver        handle to KM driver
 +//  RETURNS:
 +//    DHPDEV  a handle to a DPev object
 +
 +DHPDEV APIENTRY
 +DrvEnablePDEV(IN DEVMODEW *DM,
 +              IN LPWSTR LogAddress,
 +              IN ULONG PatternCount,
 +              OUT HSURF *SurfPatterns,
 +              IN ULONG GDIInfoSize,
 +              OUT ULONG *GDIInfo,
 +              IN ULONG DevInfoSize,
 +              OUT DEVINFO *DevInfo,
 +              IN HDEV Dev,
 +              IN LPWSTR DeviceName,
 +              IN HANDLE Driver)
 +{
 +    PPDEV  PDev;
 +
 +    PDev = EngAllocMem(FL_ZERO_MEMORY, sizeof(PDEV), ALLOC_TAG);
 +    if (PDev == NULL)
 +    {
 +        DPRINT1("EngAllocMem failed for PDEV\n");
 +        return NULL;
 +    }
 +    PDev->KMDriver = Driver;
 +    DPRINT( "PDev: %x, Driver: %x\n", PDev, PDev->KMDriver );
 +
 +    gaulCap.ulHorzRes = SCREEN_X;
 +    gaulCap.ulVertRes = SCREEN_Y;
 +    if (sizeof(GDIINFO) < GDIInfoSize)
 +        GDIInfoSize = sizeof(GDIINFO);
 +    memcpy(GDIInfo, &gaulCap, GDIInfoSize);
 +    DM->dmBitsPerPel = gaulCap.cBitsPixel * gaulCap.cPlanes;
 +    DM->dmPelsWidth = gaulCap.ulHorzRes;
 +    DM->dmPelsHeight = gaulCap.ulVertRes;
 +
 +    devinfoVGA.hpalDefault = EngCreatePalette(PAL_INDEXED, 16, (ULONG *) VGApalette.PaletteEntry, 0, 0, 0);
 +    if (sizeof(DEVINFO) < DevInfoSize)
 +        DevInfoSize = sizeof(DEVINFO);
 +    memcpy(DevInfo, &devinfoVGA, DevInfoSize);
 +
 +    return (DHPDEV) PDev;
 +}
 +
 +
 +//    DrvCompletePDEV
 +//  DESCRIPTION
 +//    Called after initialization of PDEV is complete.  Supplies
 +//    a reference to the GDI handle for the PDEV.
 +
 +VOID APIENTRY
 +DrvCompletePDEV(IN DHPDEV PDev,
 +                IN HDEV Dev)
 +{
 +    ((PPDEV) PDev)->GDIDevHandle = Dev; // Handle to the DC
 +}
 +
 +
 +BOOL APIENTRY
 +DrvAssertMode(IN DHPDEV DPev,
 +              IN BOOL Enable)
 +{
 +    PPDEV ppdev = (PPDEV)DPev;
 +    ULONG returnedDataLength;
 +
++    if (Enable)
 +    {
 +        /* Reenable our graphics mode */
 +        if (!InitPointer(ppdev))
 +        {
 +            /* Failed to set pointer */
 +            return FALSE;
 +        }
 +
 +        if (!VGAInitialized)
 +        {
 +            if (!InitVGA(ppdev, FALSE))
 +            {
 +                /* Failed to initialize the VGA */
 +                return FALSE;
 +            }
 +            VGAInitialized = TRUE;
 +      }
 +    }
 +    else
 +    {
 +        /* Go back to last known mode */
 +        DPRINT( "ppdev: %x, KMDriver: %x", ppdev, ppdev->KMDriver );
 +        if (EngDeviceIoControl(ppdev->KMDriver, IOCTL_VIDEO_RESET_DEVICE, NULL, 0, NULL, 0, &returnedDataLength))
 +        {
 +            /* Failed to go back to mode */
 +            return FALSE;
 +        }
 +        VGAInitialized = FALSE;
 +    }
 +    return TRUE;
 +}
 +
 +
 +VOID APIENTRY
 +DrvDisablePDEV(IN DHPDEV PDev)
 +{
 +    PPDEV ppdev = (PPDEV)PDev;
 +
 +    /*  EngDeletePalette(devinfoVGA.hpalDefault); */
 +    if (ppdev->pjPreallocSSBBuffer)
 +        EngFreeMem(ppdev->pjPreallocSSBBuffer);
 +
 +    if (ppdev->pucDIB4ToVGAConvBuffer)
 +        EngFreeMem(ppdev->pucDIB4ToVGAConvBuffer);
 +
 +    DPRINT("Freeing PDEV\n");
 +    EngFreeMem(PDev);
 +}
 +
 +
 +VOID APIENTRY
 +DrvDisableSurface(IN DHPDEV PDev)
 +{
 +    PPDEV ppdev = (PPDEV)PDev;
 +    PDEVSURF pdsurf = ppdev->AssociatedSurf;
 +
 +    DPRINT("KMDriver: %x\n", ppdev->KMDriver);
 +    DeinitVGA(ppdev);
 +    /* EngFreeMem(pdsurf->BankSelectInfo); */
 +
 +    if (pdsurf->BankInfo != NULL)
 +        EngFreeMem(pdsurf->BankInfo);
 +    if (pdsurf->BankInfo2RW != NULL)
 +        EngFreeMem(pdsurf->BankInfo2RW);
 +    if (pdsurf->BankBufferPlane0 != NULL)
 +        EngFreeMem(pdsurf->BankBufferPlane0);
 +    if (ppdev->pPointerAttributes != NULL)
 +        EngFreeMem(ppdev->pPointerAttributes);
 +
 +    /* free any pending saved screen bit blocks */
 +#if 0
 +    pSSB = pdsurf->ssbList;
 +    while (pSSB != (PSAVED_SCREEN_BITS) NULL)
 +    {
 +        /* Point to the next saved screen bits block */
 +        pSSBNext = (PSAVED_SCREEN_BITS) pSSB->pvNextSSB;
 +
 +        /* Free the current block */
 +        EngFreeMem(pSSB);
 +        pSSB = pSSBNext;
 +    }
 +#endif
 +    EngDeleteSurface((HSURF) ppdev->SurfHandle);
 +    /* EngFreeMem(pdsurf); */ /* free the surface */
 +}
 +
 +
 +static VOID
 +InitSavedBits(IN PPDEV ppdev)
 +{
 +    if (!(ppdev->fl & DRIVER_OFFSCREEN_REFRESHED))
 +        return;
 +
 +    /* set up rect to right of visible screen */
 +    ppdev->SavedBitsRight.left   = ppdev->sizeSurf.cx;
 +    ppdev->SavedBitsRight.top    = 0;
 +    ppdev->SavedBitsRight.right  = ppdev->sizeMem.cx - PLANAR_PELS_PER_CPU_ADDRESS;
 +    ppdev->SavedBitsRight.bottom = ppdev->sizeSurf.cy;
 +
 +    if ((ppdev->SavedBitsRight.right <= ppdev->SavedBitsRight.left) ||
 +        (ppdev->SavedBitsRight.bottom <= ppdev->SavedBitsRight.top))
 +    {
 +        ppdev->SavedBitsRight.left   = 0;
 +        ppdev->SavedBitsRight.top    = 0;
 +        ppdev->SavedBitsRight.right  = 0;
 +        ppdev->SavedBitsRight.bottom = 0;
 +    }
 +
 +    /* set up rect below visible screen */
 +    ppdev->SavedBitsBottom.left   = 0;
 +    ppdev->SavedBitsBottom.top    = ppdev->sizeSurf.cy;
 +    ppdev->SavedBitsBottom.right  = ppdev->sizeMem.cx - PLANAR_PELS_PER_CPU_ADDRESS;
 +    ppdev->SavedBitsBottom.bottom = ppdev->sizeMem.cy - ppdev->NumScansUsedByPointer;
 +
 +    if ((ppdev->SavedBitsBottom.right <= ppdev->SavedBitsBottom.left) ||
 +        (ppdev->SavedBitsBottom.bottom <= ppdev->SavedBitsBottom.top))
 +    {
 +        ppdev->SavedBitsBottom.left   = 0;
 +        ppdev->SavedBitsBottom.top    = 0;
 +        ppdev->SavedBitsBottom.right  = 0;
 +        ppdev->SavedBitsBottom.bottom = 0;
 +    }
 +
 +    ppdev->BitsSaved = FALSE;
 +}
 +
 +
 +HSURF APIENTRY
 +DrvEnableSurface(IN DHPDEV PDev)
 +{
 +    PPDEV ppdev = (PPDEV)PDev;
 +    PDEVSURF pdsurf;
 +    DHSURF dhsurf;
 +    HSURF hsurf;
 +
 +    DPRINT("DrvEnableSurface() called\n");
 +
 +    /* Initialize the VGA */
 +    if (!VGAInitialized)
 +    {
 +        if (!InitVGA(ppdev, TRUE))
 +            goto error_done;
 +        VGAInitialized = TRUE;
 +    }
 +
 +    /* dhsurf is of type DEVSURF, which is the drivers specialized surface type */
 +    dhsurf = (DHSURF)EngAllocMem(0, sizeof(DEVSURF), ALLOC_TAG);
 +    if (dhsurf == (DHSURF) 0)
 +        goto error_done;
 +
 +    pdsurf = (PDEVSURF) dhsurf;
 +    pdsurf->ident         = DEVSURF_IDENT;
 +    pdsurf->flSurf        = 0;
 +    pdsurf->Format        = BMF_PHYSDEVICE;
 +    pdsurf->jReserved1    = 0;
 +    pdsurf->jReserved2    = 0;
 +    pdsurf->ppdev         = ppdev;
 +    pdsurf->sizeSurf.cx   = ppdev->sizeSurf.cx;
 +    pdsurf->sizeSurf.cy   = ppdev->sizeSurf.cy;
 +    pdsurf->NextPlane     = 0;
 +    pdsurf->Scan0         = ppdev->fbScreen;
 +    pdsurf->BitmapStart   = ppdev->fbScreen;
 +    pdsurf->StartBmp      = ppdev->fbScreen;
 +    pdsurf->BankInfo      = NULL;
 +    pdsurf->BankInfo2RW   = NULL;
 +    pdsurf->BankBufferPlane0 = NULL;
 +
 +/*    pdsurf->Conv          = &ConvertBuffer[0]; */
 +
 +    if (!InitPointer(ppdev))
 +    {
 +        DPRINT1("DrvEnablePDEV failed bInitPointer\n");
 +        goto error_clean;
 +     }
 +
 +/*    if (!SetUpBanking(pdsurf, ppdev))
 +    {
 +        DPRINT1("DrvEnablePDEV failed SetUpBanking\n");
 +        goto error_clean;
 +    } BANKING CODE UNIMPLEMENTED */
 +
 +    if ((hsurf = EngCreateDeviceSurface(dhsurf, ppdev->sizeSurf, BMF_4BPP)) ==
 +        (HSURF)0)
 +    {
 +        /* Call to EngCreateDeviceSurface failed */
 +        DPRINT("EngCreateDeviceSurface call failed\n");
 +        goto error_clean;
 +    }
 +
 +    InitSavedBits(ppdev);
 +
 +    if (EngAssociateSurface(hsurf, ppdev->GDIDevHandle, HOOK_BITBLT | HOOK_PAINT | HOOK_LINETO | HOOK_COPYBITS |
 +        HOOK_TRANSPARENTBLT))
 +    {
 +        DPRINT("Successfully associated surface\n");
 +        ppdev->SurfHandle = hsurf;
 +        ppdev->AssociatedSurf = pdsurf;
 +
 +       /* Set up an empty saved screen block list */
 +       pdsurf->ssbList = NULL;
 +
 +      return hsurf;
 +    }
 +    DPRINT("EngAssociateSurface() failed\n");
 +    EngDeleteSurface(hsurf);
 +
 +error_clean:
 +    EngFreeMem(dhsurf);
 +
 +error_done:
 +    return (HSURF)0;
 +}
 +
 +
 +ULONG APIENTRY
 +DrvGetModes(IN HANDLE Driver,
 +            IN ULONG DataSize,
 +            OUT PDEVMODEW DM)
 +{
 +    DWORD NumModes;
 +    DWORD ModeSize;
 +    DWORD OutputSize;
 +    DWORD OutputModes = DataSize / (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
 +    PVIDEO_MODE_INFORMATION VideoModeInformation, VideoTemp;
 +
 +    NumModes = getAvailableModes(Driver,
 +                                 (PVIDEO_MODE_INFORMATION *) &VideoModeInformation,
 +                                 &ModeSize);
 +
 +    if (NumModes == 0)
 +        return 0;
 +
 +    if (DM == NULL)
 +    {
 +        OutputSize = NumModes * (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
 +    }
 +    else
 +    {
 +        OutputSize=0;
 +        VideoTemp = VideoModeInformation;
 +
 +        do
 +        {
 +            if (VideoTemp->Length != 0)
 +            {
 +                if (OutputModes == 0)
 +                    break;
 +
 +                memset(DM, 0, sizeof(DEVMODEW));
 +                memcpy(DM->dmDeviceName, DLL_NAME, sizeof(DLL_NAME));
 +
 +                DM->dmSpecVersion      = DM_SPECVERSION;
 +                DM->dmDriverVersion    = DM_SPECVERSION;
 +                DM->dmSize             = sizeof(DEVMODEW);
 +                DM->dmDriverExtra      = DRIVER_EXTRA_SIZE;
 +                DM->dmBitsPerPel       = VideoTemp->NumberOfPlanes *
 +                                         VideoTemp->BitsPerPlane;
 +                DM->dmPelsWidth        = VideoTemp->VisScreenWidth;
 +                DM->dmPelsHeight       = VideoTemp->VisScreenHeight;
 +                DM->dmDisplayFrequency = VideoTemp->Frequency;
 +                DM->dmDisplayFlags     = 0;
 +
 +                DM->dmFields           = DM_BITSPERPEL       |
 +                                         DM_PELSWIDTH        |
 +                                         DM_PELSHEIGHT       |
 +                                         DM_DISPLAYFREQUENCY |
 +                                         DM_DISPLAYFLAGS     ;
 +
 +                /* next DEVMODE entry */
 +                OutputModes--;
 +
 +                DM = (PDEVMODEW) ( ((ULONG_PTR)DM) + sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
 +
 +                OutputSize += (sizeof(DEVMODEW) + DRIVER_EXTRA_SIZE);
 +            }
 +
 +            VideoTemp = (PVIDEO_MODE_INFORMATION)(((PUCHAR)VideoTemp) + ModeSize);
 +
 +        } while (--NumModes);
 +    }
 +    return OutputSize;
 +}
 +
 +ULONG DbgPrint(PCCH Format,...)
 +{
 +    va_list ap;
 +    va_start(ap, Format);
 +    EngDebugPrint("VGADDI", (PCHAR)Format, ap);
 +    va_end(ap);
 +    return 0;
 +}
 +
 +/* EOF */
index 492761c,0000000..29ce0a7
mode 100644,000000..100644
--- /dev/null
@@@ -1,944 -1,0 +1,944 @@@
-         if (edgePixel == TRUE)
 +/*
 + * PROJECT:         ReactOS VGA display driver
 + * LICENSE:         GPL - See COPYING in the top level directory
 + * FILE:            drivers/video/displays/vga/vgavideo/vgavideo.c
 + * PURPOSE:         
 + * PROGRAMMERS:     
 + */
 +
 +#include <vgaddi.h>
 +
 +UCHAR PreCalcReverseByte[256];
 +int maskbit[640];
 +int y80[480];
 +int xconv[640];
 +int bit8[640];
 +int startmasks[8];
 +int endmasks[8];
 +PBYTE vidmem;
 +static ULONG UnpackPixel[256];
 +
 +static unsigned char leftMask;
 +static int byteCounter;
 +static unsigned char rightMask;
 +
 +UCHAR bytesPerPixel(ULONG Format)
 +{
 +    /* This function is taken from /subsys/win32k/eng/surface.c
 +     * FIXME: GDI bitmaps are supposed to be pixel-packed. Right now if the
 +     * pixel size if < 1 byte we expand it to 1 byte for simplicities sake */
 +
 +    switch (Format)
 +    {
 +        case BMF_1BPP:
 +            return 1;
 +
 +        case BMF_4BPP:
 +        case BMF_4RLE:
 +            return 1;
 +
 +        case BMF_8BPP:
 +        case BMF_8RLE:
 +            return 1;
 +
 +        case BMF_16BPP:
 +            return 2;
 +
 +        case BMF_24BPP:
 +            return 3;
 +
 +        case BMF_32BPP:
 +            return 4;
 +
 +        default:
 +            return 0;
 +    }
 +}
 +
 +VOID vgaPreCalc()
 +{
 +    ULONG j;
 +
 +    startmasks[0] = 255;
 +    startmasks[1] = 1;
 +    startmasks[2] = 3;
 +    startmasks[3] = 7;
 +    startmasks[4] = 15;
 +    startmasks[5] = 31;
 +    startmasks[6] = 63;
 +    startmasks[7] = 127;
 +
 +    endmasks[0] = 0;
 +    endmasks[1] = 128;
 +    endmasks[2] = 192;
 +    endmasks[3] = 224;
 +    endmasks[4] = 240;
 +    endmasks[5] = 248;
 +    endmasks[6] = 252;
 +    endmasks[7] = 254;
 +
 +    for (j = 0; j < 80; j++)
 +    {
 +        maskbit[j*8]   = 128;
 +        maskbit[j*8+1] = 64;
 +        maskbit[j*8+2] = 32;
 +        maskbit[j*8+3] = 16;
 +        maskbit[j*8+4] = 8;
 +        maskbit[j*8+5] = 4;
 +        maskbit[j*8+6] = 2;
 +        maskbit[j*8+7] = 1;
 +
 +        bit8[j*8]   = 7;
 +        bit8[j*8+1] = 6;
 +        bit8[j*8+2] = 5;
 +        bit8[j*8+3] = 4;
 +        bit8[j*8+4] = 3;
 +        bit8[j*8+5] = 2;
 +        bit8[j*8+6] = 1;
 +        bit8[j*8+7] = 0;
 +    }
 +    for (j = 0; j < SCREEN_Y; j++)
 +        y80[j]  = j*80;
 +    for (j = 0; j < SCREEN_X; j++)
 +        xconv[j] = j >> 3;
 +
 +    for (j = 0; j < 256; j++)
 +    {
 +        PreCalcReverseByte[j] =
 +            (((j >> 0) & 0x1) << 7) |
 +            (((j >> 1) & 0x1) << 6) |
 +            (((j >> 2) & 0x1) << 5) |
 +            (((j >> 3) & 0x1) << 4) |
 +            (((j >> 4) & 0x1) << 3) |
 +            (((j >> 5) & 0x1) << 2) |
 +            (((j >> 6) & 0x1) << 1) |
 +            (((j >> 7) & 0x1) << 0);
 +    }
 +
 +    for (j = 0; j < 256; j++)
 +    {
 +        UnpackPixel[j] =
 +            (((j >> 0) & 0x1) << 4) |
 +            (((j >> 1) & 0x1) << 0) |
 +            (((j >> 2) & 0x1) << 12) |
 +            (((j >> 3) & 0x1) << 8) |
 +            (((j >> 4) & 0x1) << 20) |
 +            (((j >> 5) & 0x1) << 16) |
 +            (((j >> 6) & 0x1) << 28) |
 +            (((j >> 7) & 0x1) << 24);
 +    }
 +}
 +
 +void
 +get_masks(int x, int w)
 +{
 +    register int tmp;
 +
 +    leftMask = rightMask = 0;
 +    byteCounter = w;
 +    /* right margin */
 +    tmp = (x+w) & 7;
 +    if (tmp)
 +    {
 +        byteCounter -= tmp;
 +        rightMask = (unsigned char)(0xff00 >> tmp);
 +    }
 +    /* left margin */
 +    tmp = x & 7;
 +    if (tmp)
 +    {
 +        byteCounter -= (8 - tmp);
 +        leftMask = (0xff >> tmp);
 +    }
 +    /* too small ? */
 +    if (byteCounter < 0)
 +    {
 +        leftMask &= rightMask;
 +        rightMask = 0;
 +        byteCounter = 0;
 +    }
 +    byteCounter /= 8;
 +}
 +
 +VOID vgaPutPixel(INT x, INT y, UCHAR c)
 +{
 +    ULONG offset;
 +
 +    offset = xconv[x]+y80[y];
 +
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D,maskbit[x]);
 +
 +    READ_REGISTER_UCHAR(vidmem + offset);
 +    WRITE_REGISTER_UCHAR(vidmem + offset, c);
 +}
 +
 +VOID vgaPutByte(INT x, INT y, UCHAR c)
 +{
 +    ULONG offset;
 +
 +    offset = xconv[x]+y80[y];
 +
 +    /* Set the write mode */
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D,0xff);
 +
 +    WRITE_REGISTER_UCHAR(vidmem + offset, c);
 +}
 +
 +VOID vgaGetByte(
 +    IN ULONG offset,
 +    OUT UCHAR *b,
 +    OUT UCHAR *g,
 +    OUT UCHAR *r,
 +    OUT UCHAR *i)
 +{
 +    WRITE_PORT_USHORT((PUSHORT)GRA_I, 0x0304);
 +    *i = READ_REGISTER_UCHAR(vidmem + offset);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
 +    *r = READ_REGISTER_UCHAR(vidmem + offset);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x01);
 +    *g = READ_REGISTER_UCHAR(vidmem + offset);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
 +    *b = READ_REGISTER_UCHAR(vidmem + offset);
 +}
 +
 +INT vgaGetPixel(
 +    IN INT x,
 +    IN INT y)
 +{
 +    UCHAR mask, b, g, r, i;
 +    ULONG offset;
 +
 +    offset = xconv[x] + y80[y];
 +    vgaGetByte(offset, &b, &g, &r, &i);
 +
 +    mask = maskbit[x];
 +    b = b & mask;
 +    g = g & mask;
 +    r = r & mask;
 +    i = i & mask;
 +
 +    mask = bit8[x];
 +    g = g >> mask;
 +    b = b >> mask;
 +    r = r >> mask;
 +    i = i >> mask;
 +
 +    return (b + 2 * g + 4 * r + 8 * i);
 +}
 +
 +BOOL vgaHLine(INT x, INT y, INT len, UCHAR c)
 +{
 +    ULONG orgx, pre1, midpre1;
 +    //ULONG orgpre1;
 +    LONG ileftpix, imidpix, irightpix;
 +
 +    orgx = x;
 +
 +    /*if ( len < 8 )
 +    {
 +        for (i = x; i < x+len; i++ )
 +            vgaPutPixel ( i, y, c );
 +
 +        return TRUE;
 +    }*/
 +
 +    /* Calculate the left mask pixels, middle bytes and right mask pixel */
 +    ileftpix = 7 - mod8(x-1);
 +    irightpix = mod8(x+len);
 +    imidpix = (len-ileftpix-irightpix) / 8;
 +
 +    pre1 = xconv[(x-1)&~7] + y80[y];
 +    //orgpre1=pre1;
 +
 +    /* check for overlap ( very short line ) */
 +    if ( (ileftpix+irightpix) > len )
 +    {
 +        int mask = startmasks[ileftpix] & endmasks[irightpix];
 +        /* Write left pixels */
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);     // set the mask
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D,mask);
 +
 +        READ_REGISTER_UCHAR(vidmem + pre1);
 +        WRITE_REGISTER_UCHAR(vidmem + pre1, c);
 +
 +        return TRUE;
 +    }
 +
 +    /* Left */
 +    if ( ileftpix > 0 )
 +    {
 +        /* Write left pixels */
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);     // set the mask
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D,startmasks[ileftpix]);
 +
 +        READ_REGISTER_UCHAR(vidmem + pre1);
 +        WRITE_REGISTER_UCHAR(vidmem + pre1, c);
 +
 +        /* Prepare new x for the middle */
 +        x = orgx + 8;
 +    }
 +
 +    if ( imidpix > 0 )
 +    {
 +        midpre1 = xconv[x] + y80[y];
 +
 +        /* Set mask to all pixels in byte */
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08);
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0xff);
 +        memset(vidmem+midpre1, c, imidpix); // write middle pixels, no need to read in latch because of the width
 +    }
 +
 +    if ( irightpix > 0 )
 +    {
 +        x = orgx + len - irightpix;
 +        pre1 = xconv[x] + y80[y];
 +
 +        /* Write right pixels */
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);     // set the mask bits
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D, endmasks[irightpix]);
 +        READ_REGISTER_UCHAR(vidmem + pre1);
 +        WRITE_REGISTER_UCHAR(vidmem + pre1, c);
 +    }
 +
 +    return TRUE;
 +}
 +
 +BOOL vgaVLine(INT x, INT y, INT len, UCHAR c)
 +{
 +    INT offset, i;
 +
 +    offset = xconv[x]+y80[y];
 +
 +#ifdef VGA_PERF
 +    vgaSetBitMaskRegister ( maskbit[x] );
 +#else
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I,0x08);       // set the mask
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D,maskbit[x]);
 +#endif
 +
 +    for(i=y; i<y+len; i++)
 +    {
 +        READ_REGISTER_UCHAR(vidmem + offset);
 +        WRITE_REGISTER_UCHAR(vidmem + offset, c);
 +        offset += 80;
 +    }
 +
 +    return TRUE;
 +}
 +
 +static const RECTL rclEmpty = { 0, 0, 0, 0 };
 +
 +BOOL VGADDIIntersectRect(PRECTL prcDst, PRECTL prcSrc1, PRECTL prcSrc2)
 +{
 +    prcDst->left  = max(prcSrc1->left, prcSrc2->left);
 +    prcDst->right = min(prcSrc1->right, prcSrc2->right);
 +
 +    if (prcDst->left < prcDst->right)
 +    {
 +        prcDst->top = max(prcSrc1->top, prcSrc2->top);
 +        prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
 +
 +       if (prcDst->top < prcDst->bottom)
 +           return TRUE;
 +    }
 +
 +    *prcDst = rclEmpty;
 +
 +    return FALSE;
 +}
 +
 +void DIB_BltFromVGA(int x, int y, int w, int h, void *b, int Dest_lDelta)
 +{
 +    ULONG plane;
 +    ULONG left = x >> 3;
 +    ULONG shift = x - (x & ~0x7);
 +    UCHAR pixel, nextpixel;
 +    LONG rightcount;
 +    INT i, j;
 +    LONG stride = w >> 3;
 +
 +    /* Calculate the number of rightmost bytes not in a dword block. */
 +    if (w >= 8)
 +    {
 +        rightcount = w % 8;
 +    }
 +    else
 +    {
 +        stride = 0;
 +        rightcount = w;
 +    }
 +
 +    /* Reset the destination. */
 +    for (j = 0; j < h; j++)
 +        memset((PVOID)((ULONG_PTR)b + (j * Dest_lDelta)), 0, abs(Dest_lDelta));
 +
 +    for (plane = 0; plane < 4; plane++)
 +    {
 +        PUCHAR dest = b;
 +
 +        /* Select the plane we are reading in this iteration. */
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04);
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane);
 +
 +        for (j = 0; j < h; j++)
 +        {
 +            PULONG destline = (PULONG)dest;
 +            PUCHAR src = vidmem + (y + j) * SCREEN_STRIDE + left;
 +            /* Read the data for one plane for an eight aligned pixel block. */
 +            nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src)];
 +            for (i = 0; i < stride; i++, src++, destline++)
 +            {
 +                /* Form the data for one plane for an aligned block in the destination. */
 +                pixel = nextpixel;
 +                pixel >>= shift;
 +
 +                nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src + 1)];
 +                pixel |= (nextpixel << (8 - shift));
 +
 +                /* Expand the plane data to 'chunky' format and store. */
 +                *destline |= (UnpackPixel[pixel] << plane);
 +            }
 +            /* Handle any pixels not falling into a full block. */
 +            if (rightcount != 0)
 +            {
 +                ULONG row;
 +
 +                /* Form the data for a complete block. */
 +                pixel = nextpixel;
 +                pixel >>= shift;
 +
 +                nextpixel = PreCalcReverseByte[READ_REGISTER_UCHAR(src + 1)];
 +                pixel |= (nextpixel << (8 - shift));
 +
 +                row = UnpackPixel[pixel] << plane;
 +
 +                /* Store the data for each pixel in the destination. */
 +                for (i = 0; i < rightcount; i++)
 +                {
 +                    ((PUCHAR)destline)[i] |= (row & 0xFF);
 +                    row >>= 8;
 +                }
 +            }
 +            dest += Dest_lDelta;
 +        }
 +    }
 +
 +#ifdef VGA_VERIFY
 +    for (j = 0; j < h; j++)
 +    {
 +        for (i = 0; i < w; i += 2)
 +        {
 +            UCHAR c1, c2;
 +            ULONG mask = (i < (w - 1)) ? 0xFF : 0xF0;
 +
 +            c1 = (vgaGetPixel(x + i, y + j) << 4) | (vgaGetPixel(x + i + 1, y + j));
 +            c2 = ((PUCHAR)b)[(j * Dest_lDelta) + (i >> 1)];
 +            if ((c1 & mask) != (c2 & mask))
 +                EngDebugBreak();
 +        }
 +    }
 +#endif /* VGA_VERIFY */
 +}
 +
 +/* DIB blt to the VGA. */
 +void DIB_BltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, int StartMod)
 +{
 +    PUCHAR pb, opb = b;
 +    LONG i, j;
 +    LONG x2 = x + w;
 +    LONG y2 = y + h;
 +    ULONG offset;
 +
 +    for (i = x; i < x2; i++)
 +    {
 +        pb = opb;
 +        offset = xconv[i] + y80[y];
 +
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08);       // set the mask
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D, maskbit[i]);
 +
 +        if (StartMod == ((i - x) % 2))
 +        {
 +            for (j = y; j < y2; j++)
 +            {
 +                READ_REGISTER_UCHAR(vidmem + offset);
 +                WRITE_REGISTER_UCHAR(vidmem + offset, (*pb & 0xf0) >> 4);
 +                offset += 80;
 +                pb += Source_lDelta;
 +            }
 +        }
 +        else
 +        {
 +            for (j = y; j < y2; j++)
 +            {
 +                READ_REGISTER_UCHAR(vidmem + offset);
 +                WRITE_REGISTER_UCHAR(vidmem + offset, *pb & 0x0f);
 +                offset += 80;
 +                pb += Source_lDelta;
 +            }
 +        }
 +
 +        if (StartMod != ((i - x) % 2))
 +            opb++;
 +    }
 +}
 +
 +
 +/* DIB blt to the VGA. */
 +void DIB_BltToVGAWithXlate(int x, int y, int w, int h, void *b, int Source_lDelta, XLATEOBJ* Xlate)
 +{
 +    PUCHAR pb, opb = b;
 +    ULONG i, j;
 +    ULONG x2 = x + w;
 +    ULONG y2 = y + h;
 +    ULONG offset;
 +
 +    for (i = x; i < x2; i++)
 +    {
 +        pb = opb;
 +        offset = xconv[i] + y80[y];
 +
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08);       // set the mask
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D, maskbit[i]);
 +
 +        if (0 == ((i - x) % 2))
 +        {
 +            for (j = y; j < y2; j++)
 +            {
 +                READ_REGISTER_UCHAR(vidmem + offset);
 +                WRITE_REGISTER_UCHAR(vidmem + offset, XLATEOBJ_iXlate(Xlate, (*pb & 0xf0) >> 4));
 +                offset += 80;
 +                pb += Source_lDelta;
 +            }
 +        }
 +        else
 +        {
 +            for (j = y; j < y2; j++)
 +            {
 +                READ_REGISTER_UCHAR(vidmem + offset);
 +                WRITE_REGISTER_UCHAR(vidmem + offset, XLATEOBJ_iXlate(Xlate, *pb & 0x0f));
 +                offset += 80;
 +                pb += Source_lDelta;
 +            }
 +        }
 +
 +        if (0 != ((i - x) % 2))
 +            opb++;
 +    }
 +}
 +
 +/* DIB blt to the VGA.
 + * For now we just do slow writes -- pixel by pixel,
 + * packing each one into the correct 4BPP format. */
 +void DIB_TransparentBltToVGA(int x, int y, int w, int h, void *b, int Source_lDelta, ULONG trans)
 +
 +{
 +    PUCHAR pb = b, opb = b;
 +    BOOLEAN edgePixel = FALSE;
 +    ULONG i, j;
 +    ULONG x2 = x + w;
 +    ULONG y2 = y + h;
 +    UCHAR b1, b2;
 +
 +    /* Check if the width is odd */
 +    if(mod2(w) > 0)
 +    {
 +        edgePixel = TRUE;
 +        x2 -= 1;
 +    }
 +
 +    for (j=y; j<y2; j++)
 +    {
 +        for (i=x; i<x2; i+=2)
 +        {
 +            b1 = (*pb & 0xf0) >> 4;
 +            b2 = *pb & 0x0f;
 +            if(b1 != trans) vgaPutPixel(i,   j, b1);
 +            if(b2 != trans) vgaPutPixel(i+1, j, b2);
 +            pb++;
 +        }
 +
++        if (edgePixel)
 +        {
 +            b1 = *pb;
 +            if(b1 != trans) vgaPutPixel(x2, j, b1);
 +            pb++;
 +        }
 +
 +        opb += Source_lDelta;
 +        pb = opb; // new test code
 +    }
 +}
 +
 +// This algorithm goes from left to right, storing each 4BPP pixel
 +// in an entire byte.
 +void FASTCALL
 +vgaReadScan( int x, int y, int w, void *b )
 +{
 +    unsigned char *vp, *vpP;
 +    unsigned char data, mask, maskP;
 +    unsigned char *bp;
 +    unsigned char plane_mask;
 +    int plane, i;
 +
 +    ASSIGNVP4(x, y, vpP)
 +    ASSIGNMK4(x, y, maskP)
 +    get_masks(x, w);
 +    WRITE_PORT_USHORT((PUSHORT)GRA_I, 0x0005);  // read mode 0
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04);  // read map select
 +
 +    memset ( b, 0, w );
 +
 +    for ( plane=0, plane_mask=1; plane < 4; plane++, plane_mask<<=1 )
 +    {
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane);  // read map select
 +
 +        vp = vpP;
 +        bp = b;
 +        if ( leftMask )
 +        {
 +            mask = maskP;
 +            data = *vp++;
 +            do
 +            {
 +                if (data & mask)
 +                    *bp |= plane_mask;
 +                bp++;
 +                mask >>= 1;
 +            } while (mask & leftMask);
 +        }
 +        if (byteCounter)
 +        {
 +            for (i=byteCounter; i>0; i--)
 +            {
 +                data = *vp++;
 +                if (data & 0x80) *bp |= plane_mask;
 +                bp++;
 +                
 +                if (data & 0x40) *bp |= plane_mask;
 +                bp++;
 +                if (data & 0x20) *bp |= plane_mask;
 +                bp++;
 +                if (data & 0x10) *bp |= plane_mask;
 +                bp++;
 +                if (data & 0x08) *bp |= plane_mask;
 +                bp++;
 +                if (data & 0x04) *bp |= plane_mask;
 +                bp++;
 +                if (data & 0x02) *bp |= plane_mask;
 +                bp++;
 +                if (data & 0x01) *bp |= plane_mask;
 +                bp++;
 +            }
 +        }
 +        if (rightMask)
 +        {
 +            mask = 0x80;
 +            data = *vp;
 +            do
 +            {
 +                if (data & mask)
 +                *bp |= plane_mask;
 +                bp++;
 +                mask >>= 1;
 +            } while (mask & rightMask);
 +        }
 +    }
 +}
 +
 +/* This algorithm goes from left to right
 + * It stores each 4BPP pixel in an entire byte. */
 +void FASTCALL
 +vgaWriteScan ( int x, int y, int w, void *b )
 +{
 +    unsigned char *bp;
 +    unsigned char *vp;
 +    //unsigned char init_mask;
 +    volatile unsigned char dummy;
 +    //int byte_per_line;
 +    int i, j, off, init_off = x&7;
 +
 +    bp = b;
 +    ASSIGNVP4(x, y, vp)
 +    //ASSIGNMK4(x, y, init_mask)
 +    //byte_per_line = SCREEN_X >> 3;
 +
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05);      // write mode 2
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03);      // replace
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08);      // bit mask
 +
 +    for ( j = 0; j < 8; j++)
 +    {
 +        unsigned int mask = 0x80 >> j;
 +        WRITE_PORT_UCHAR ( (PUCHAR)GRA_D, (unsigned char)mask );
 +        i = j - init_off;
 +        off = 0;
 +        if (j < init_off)
 +            i += 8, off++;
 +        while (i < w)
 +        {
 +            dummy = vp[off];
 +            dummy = bp[i];
 +            vp[off] = dummy;
 +            i += 8;
 +            off++;
 +        }
 +    }
 +}
 +
 +/* This algorithm goes from left to right, and inside that loop, top to bottom.
 + * It also stores each 4BPP pixel in an entire byte. */
 +void DFB_BltFromVGA(int x, int y, int w, int h, void *b, int bw)
 +{
 +    unsigned char *vp, *vpY, *vpP;
 +    unsigned char data, mask, maskP;
 +    unsigned char *bp, *bpY;
 +    unsigned char plane_mask;
 +    int byte_per_line = SCREEN_X >> 3;
 +    int plane, i, j;
 +
 +    ASSIGNVP4(x, y, vpP)
 +    ASSIGNMK4(x, y, maskP)
 +    get_masks(x, w);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05);  // read mode 0
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x04);  // read map select
 +
 +    /* clear buffer */
 +    bp = b;
 +    for (j = h; j > 0; j--)
 +    {
 +        memset(bp, 0, w);
 +        bp += bw;
 +    }
 +
 +    for (plane = 0, plane_mask = 1; plane < 4; plane++, plane_mask <<= 1)
 +    {
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D, plane);  // read map select
 +        vpY = vpP;
 +        bpY = b;
 +        for (j = h; j > 0; j--)
 +        {
 +            vp = vpY;
 +            bp = bpY;
 +            if (leftMask)
 +            {
 +                mask = maskP;
 +                data = *vp++;
 +                do
 +                {
 +                    if (data & mask)
 +                        *bp |= plane_mask;
 +                    bp++;
 +                    mask >>= 1;
 +                } while (mask & leftMask);
 +            }
 +            if (byteCounter)
 +            {
 +                for (i=byteCounter; i>0; i--)
 +                {
 +                    data = *vp++;
 +                    if (data & 0x80) *bp |= plane_mask;
 +                    bp++;
 +                    if (data & 0x40) *bp |= plane_mask;
 +                    bp++;
 +                    if (data & 0x20) *bp |= plane_mask;
 +                    bp++;
 +                    if (data & 0x10) *bp |= plane_mask;
 +                    bp++;
 +                    if (data & 0x08) *bp |= plane_mask;
 +                    bp++;
 +                    if (data & 0x04) *bp |= plane_mask;
 +                    bp++;
 +                    if (data & 0x02) *bp |= plane_mask;
 +                    bp++;
 +                    if (data & 0x01) *bp |= plane_mask;
 +                    bp++;
 +                }
 +            }
 +            if (rightMask)
 +            {
 +                mask = 0x80;
 +                data = *vp;
 +                do
 +                {
 +                    if (data & mask) *bp |= plane_mask;
 +                    bp++;
 +                    mask >>= 1;
 +                } while (mask & rightMask);
 +            }
 +            bpY += bw;
 +            vpY += byte_per_line;
 +        }
 +    }
 +
 +    // We don't need this if the next call is a DFB blt to VGA (as in the case of moving the mouse pointer)
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05);      // write mode 2
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03);      // replace
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
 +}
 +
 +/* This algorithm goes from left to right, and inside that loop, top to bottom.
 + * It also stores each 4BPP pixel in an entire byte. */
 +void DFB_BltToVGA(int x, int y, int w, int h, void *b, int bw)
 +{
 +    unsigned char *bp, *bpX;
 +    unsigned char *vp, *vpX;
 +    unsigned char mask;
 +    //volatile unsigned char dummy;
 +    int byte_per_line;
 +    int i, j;
 +
 +    bpX = b;
 +    ASSIGNVP4(x, y, vpX)
 +    ASSIGNMK4(x, y, mask)
 +    byte_per_line = SCREEN_X >> 3;
 +
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05);      // write mode 2
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03);      // replace
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08);      // bit mask
 +
 +    for (i=w; i>0; i--)
 +    {
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask);
 +        bp = bpX;
 +        vp = vpX;
 +        for (j = h; j > 0; j--)
 +        {
 +            //dummy = *vp;
 +            *vp = *bp;
 +            bp += bw;
 +            vp += byte_per_line;
 +        }
 +        bpX++;
 +        if ((mask >>= 1) == 0)
 +        {
 +            vpX++;
 +            mask = 0x80;
 +        }
 +    }
 +}
 +
 +/* This algorithm goes from goes from left to right, and inside that loop, top to bottom.
 + * It also stores each 4BPP pixel in an entire byte. */
 +void DFB_BltToVGA_Transparent(int x, int y, int w, int h, void *b, int bw, char Trans)
 +{
 +    unsigned char *bp, *bpX;
 +    unsigned char *vp, *vpX;
 +    unsigned char mask;
 +    //volatile unsigned char dummy;
 +    int byte_per_line;
 +    int i, j;
 +
 +    bpX = b;
 +    ASSIGNVP4(x, y, vpX)
 +    ASSIGNMK4(x, y, mask)
 +    byte_per_line = SCREEN_X >> 3;
 +
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x05);      // write mode 2
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x02);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x03);      // replace
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_D, 0x00);
 +    WRITE_PORT_UCHAR((PUCHAR)GRA_I, 0x08);      // bit mask
 +
 +    for (i=w; i>0; i--)
 +    {
 +        WRITE_PORT_UCHAR((PUCHAR)GRA_D, mask);
 +        bp = bpX;
 +        vp = vpX;
 +        for (j=h; j>0; j--)
 +        {
 +            if (*bp != Trans)
 +            {
 +                //dummy = *vp;
 +                *vp = *bp;
 +            }
 +            bp += bw;
 +            vp += byte_per_line;
 +        }
 +        bpX++;
 +        if ((mask >>= 1) == 0)
 +        {
 +            vpX++;
 +            mask = 0x80;
 +        }
 +    }
 +}
 +
 +/* This algorithm converts a DFB into a DIB
 + * WARNING: This algorithm is buggy */
 +void DFB_BltToDIB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw)
 +{
 +    unsigned char *bp, *bpX, *dib, *dibTmp;
 +    int i, j, dib_shift;
 +
 +    bpX = b;
 +    dib = (unsigned char *)bdib + y * dibw + (x / 2);
 +
 +    for (i=w; i>0; i--)
 +    {
 +        /* determine the bit shift for the DIB pixel */
 +        dib_shift = mod2(w-i);
 +        if(dib_shift > 0)
 +            dib_shift = 4;
 +        dibTmp = dib;
 +
 +        bp = bpX;
 +        for (j = h; j > 0; j--)
 +        {
 +            *dibTmp = *bp << dib_shift | *(bp + 1);
 +            dibTmp += dibw;
 +            bp += bw;
 +        }
 +        bpX++;
 +        if(dib_shift == 0)
 +            dib++;
 +    }
 +}
 +
 +/* This algorithm converts a DIB into a DFB */
 +void DIB_BltToDFB(int x, int y, int w, int h, void *b, int bw, void *bdib, int dibw)
 +{
 +    unsigned char *bp, *bpX, *dib, *dibTmp;
 +    int i, j, dib_shift, dib_and;
 +
 +    bpX = b;
 +    dib = (unsigned char *)bdib + y * dibw + (x / 2);
 +
 +    for (i=w; i>0; i--)
 +    {
 +        /* determine the bit shift for the DIB pixel */
 +        dib_shift = mod2(w-i);
 +        if(dib_shift > 0)
 +        {
 +            dib_shift = 0;
 +            dib_and = 0x0f;
 +        }
 +        else
 +        {
 +            dib_shift = 4;
 +            dib_and = 0xf0;
 +        }
 +
 +        dibTmp = dib;
 +        bp = bpX;
 +
 +        for (j=h; j>0; j--)
 +        {
 +            *bp = (*dibTmp & dib_and) >> dib_shift;
 +            dibTmp += dibw;
 +            bp += bw;
 +        }
 +
 +        bpX++;
 +        if (dib_shift == 0)
 +            dib++;
 +    }
 +}
index a24ade7,0000000..13a0fed
mode 100644,000000..100644
--- /dev/null
@@@ -1,173 -1,0 +1,173 @@@
-     if (isSurf == TRUE && 
 +/* 
 +* COPYRIGHT:         See COPYING in the top level directory
 +* PROJECT:           ReactOS win32 subsystem
 +* PURPOSE:           Flood filling support
 +* FILE:              subsystems/win32/win32k/dib/floodfill.c
 +* PROGRAMMER:        Gregor Schneider, <grschneider AT gmail DOT com>
 +*/
 +
 +#include <win32k.h>
 +
 +#define NDEBUG
 +#include <debug.h>
 +
 +/*
 +*  This floodfill algorithm is an iterative four neighbors version. It works with an internal stack like data structure.
 +*  The stack is kept in an array, sized for the worst case scenario of having to add all pixels of the surface.
 +*  This avoids having to allocate and free memory blocks  all the time. The stack grows from the end of the array towards the start.
 +*  All pixels are checked before being added, against belonging to the fill rule (FLOODFILLBORDER or FLOODFILLSURFACE) 
 +*  and the position in respect to the clip region. This guarantees all pixels lying on the stack belong to the filled surface.
 +*  Further optimisations of the algorithm are possible.
 +*/
 +
 +/* Floodfil helper structures and functions */
 +typedef struct _floodItem
 +{
 +  ULONG x;
 +  ULONG y;
 +} FLOODITEM;
 +
 +typedef struct _floodInfo
 +{
 +  ULONG floodLen;
 +  FLOODITEM *floodStart;
 +  FLOODITEM *floodData;
 +} FLOODINFO;
 +
 +static __inline BOOL initFlood(FLOODINFO *info, RECTL *DstRect)
 +{
 +  ULONG width = DstRect->right - DstRect->left;
 +  ULONG height = DstRect->bottom - DstRect->top;
 +  info->floodData = ExAllocatePoolWithTag(NonPagedPool, width * height * sizeof(FLOODITEM), TAG_DIB); 
 +  if (info->floodData == NULL)
 +  {
 +    return FALSE;
 +  }
 +  info->floodStart = info->floodData + (width * height);
 +  DPRINT("Allocated flood stack from %p to %p\n", info->floodData, info->floodStart);
 +  return TRUE;
 +}
 +static __inline VOID finalizeFlood(FLOODINFO *info)
 +{
 +  ExFreePoolWithTag(info->floodData, TAG_DIB);
 +}
 +static __inline VOID addItemFlood(FLOODINFO *info,
 +                                  ULONG x, 
 +                                  ULONG y, 
 +                                  SURFOBJ *DstSurf, 
 +                                  RECTL *DstRect, 
 +                                  ULONG Color, 
 +                                  BOOL isSurf)
 +{
 +  if (RECTL_bPointInRect(DstRect,x,y))
 +  {
++    if (isSurf &&
 +      DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) != Color)
 +    {
 +      return;
 +    }
 +    else if (isSurf == FALSE &&
 +      DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) == Color)
 +    {
 +      return;
 +    }
 +    info->floodStart--;
 +    info->floodStart->x = x;
 +    info->floodStart->y = y;
 +    info->floodLen++;
 +  }
 +}
 +static __inline VOID removeItemFlood(FLOODINFO *info)
 +{
 +  info->floodStart++;
 +  info->floodLen--;
 +}
 +
 +BOOLEAN DIB_XXBPP_FloodFillSolid(SURFOBJ *DstSurf, 
 +                                 BRUSHOBJ *Brush, 
 +                                 RECTL *DstRect, 
 +                                 POINTL *Origin,
 +                                 ULONG ConvColor, 
 +                                 UINT FillType)
 +{
 +  ULONG x, y;
 +  ULONG BrushColor;
 +  FLOODINFO flood = {0, NULL, NULL};
 +
 +  BrushColor = Brush->iSolidColor;
 +  x = Origin->x;
 +  y = Origin->y;
 +
 +  if (FillType == FLOODFILLBORDER)
 +  {
 +    /* Check if the start pixel has the border color */
 +    if (DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) == ConvColor)
 +    {
 +      return FALSE;
 +    }
 +
 +    if (initFlood(&flood, DstRect) == FALSE)
 +    {
 +      return FALSE;
 +    }
 +    addItemFlood(&flood, x, y, DstSurf, DstRect, ConvColor, FALSE);
 +    while (flood.floodLen != 0) 
 +    {
 +      x = flood.floodStart->x;
 +      y = flood.floodStart->y;
 +      removeItemFlood(&flood);
 +
 +      DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_PutPixel(DstSurf, x, y, BrushColor);
 +      if (flood.floodStart - 4 < flood.floodData)
 +      {   
 +        DPRINT1("Can't finish flooding!\n");
 +        finalizeFlood(&flood);
 +        return FALSE;
 +      }
 +      addItemFlood(&flood, x, y + 1, DstSurf, DstRect, ConvColor, FALSE);
 +      addItemFlood(&flood, x, y - 1, DstSurf, DstRect, ConvColor, FALSE);
 +      addItemFlood(&flood, x + 1, y, DstSurf, DstRect, ConvColor, FALSE);
 +      addItemFlood(&flood, x - 1, y, DstSurf, DstRect, ConvColor, FALSE);
 +    }
 +    finalizeFlood(&flood);
 +  }
 +  else if (FillType == FLOODFILLSURFACE)
 +  {
 +    /* Check if the start pixel has the surface color */
 +    if (DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_GetPixel(DstSurf, x, y) != ConvColor)
 +    {
 +      return FALSE;
 +    }
 +
 +    if (initFlood(&flood, DstRect) == FALSE)
 +    {
 +      return FALSE;
 +    }
 +    addItemFlood(&flood, x, y, DstSurf, DstRect, ConvColor, TRUE);
 +    while (flood.floodLen != 0) 
 +    {
 +      x = flood.floodStart->x;
 +      y = flood.floodStart->y;
 +      removeItemFlood(&flood);
 +
 +      DibFunctionsForBitmapFormat[DstSurf->iBitmapFormat].DIB_PutPixel(DstSurf, x, y, BrushColor);
 +      if (flood.floodStart - 4 < flood.floodData)
 +      {
 +        DPRINT1("Can't finish flooding!\n");
 +        finalizeFlood(&flood);
 +        return FALSE;
 +      }
 +      addItemFlood(&flood, x, y + 1, DstSurf, DstRect, ConvColor, TRUE);
 +      addItemFlood(&flood, x, y - 1, DstSurf, DstRect, ConvColor, TRUE);
 +      addItemFlood(&flood, x + 1, y, DstSurf, DstRect, ConvColor, TRUE);
 +      addItemFlood(&flood, x - 1, y, DstSurf, DstRect, ConvColor, TRUE);
 +    }
 +    finalizeFlood(&flood);
 +  }
 +  else
 +  {
 +    DPRINT1("Unsupported FloodFill type!\n");
 +    return FALSE;
 +  }
 +  return TRUE;
 +}
index 8f37312,0000000..eb933df
mode 100644,000000..100644
--- /dev/null
@@@ -1,2085 -1,0 +1,2085 @@@
-         if (Return == TRUE)
 +/*
 + * COPYRIGHT:        See COPYING in the top level directory
 + * PROJECT:          ReactOS GDI32
 + * PURPOSE:          GDI DirectX inteface
 + * FILE:             lib/gdi32/misc/gdientry.c
 + * PROGRAMERS:       Alex Ionescu (alex@relsoft.net)
 + *                   Magnus Olsen (magnus@greatlord.com)
 + */
 +
 +/* INCLUDES ******************************************************************/
 +
 +#include <precomp.h>
 +
 +#include <stdio.h>
 +#include <d3dhal.h>
 +
 +/* DATA **********************************************************************/
 +
 +HANDLE ghDirectDraw;
 +ULONG gcDirectDraw;
 +
 +#define GetDdHandle(Handle) ((HANDLE)Handle ? (HANDLE)Handle : ghDirectDraw)
 +
 +
 +
 +/* CALLBACKS *****************************************************************/
 +
 +/*
 + * @implemented
 + *
 + * DdAddAttachedSurface
 + */
 +DWORD
 +WINAPI
 +DdAddAttachedSurface(LPDDHAL_ADDATTACHEDSURFACEDATA Attach)
 +{
 +    /* Call win32k */
 +    return NtGdiDdAddAttachedSurface((HANDLE)Attach->lpDDSurface->hDDSurface,
 +                                     (HANDLE)Attach->lpSurfAttached->hDDSurface,
 +                                     (PDD_ADDATTACHEDSURFACEDATA)Attach);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdBlt
 + */
 +DWORD
 +WINAPI
 +DdBlt(LPDDHAL_BLTDATA Blt)
 +{
 +    HANDLE Surface = 0;
 +
 +    /* Use the right surface */
 +    if (Blt->lpDDSrcSurface)
 +    {
 +        Surface = (HANDLE)Blt->lpDDSrcSurface->hDDSurface;
 +    }
 +
 +    /* Call win32k */
 +    return NtGdiDdBlt((HANDLE)Blt->lpDDDestSurface->hDDSurface, Surface, (PDD_BLTDATA)Blt);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdDestroySurface
 + */
 +DWORD
 +WINAPI
 +DdDestroySurface(LPDDHAL_DESTROYSURFACEDATA pDestroySurface)
 +{
 +    DWORD Return = DDHAL_DRIVER_NOTHANDLED;
 +    BOOL RealDestroy;
 +
 +    if (pDestroySurface->lpDDSurface->hDDSurface)
 +    {
 +        /* Check if we shoudl really destroy it */
 +        RealDestroy = !(pDestroySurface->lpDDSurface->dwFlags & DDRAWISURF_DRIVERMANAGED) ||
 +                      !(pDestroySurface->lpDDSurface->dwFlags & DDRAWISURF_INVALID);
 +
 +        /* Call win32k */
 +        Return = NtGdiDdDestroySurface((HANDLE)pDestroySurface->lpDDSurface->hDDSurface, RealDestroy);
 +    }
 +
 +    return Return;
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdFlip
 + */
 +DWORD
 +WINAPI
 +DdFlip(LPDDHAL_FLIPDATA Flip)
 +{
 +    /* Note :
 +    * See http://msdn2.microsoft.com/en-us/library/ms794213.aspx and
 +    * http://msdn2.microsoft.com/en-us/library/ms792675.aspx
 +    */
 +
 +    HANDLE hSurfaceCurrentLeft = NULL;
 +    HANDLE hSurfaceTargetLeft = NULL;
 +
 +    /* Auto flip off or on */
 +    if (Flip->dwFlags & DDFLIP_STEREO )
 +    {
 +        if ( (Flip->lpSurfTargLeft) &&
 +                (Flip->lpSurfCurrLeft))
 +        {
 +            /* Auto flip on */
 +            hSurfaceTargetLeft = (HANDLE) Flip->lpSurfTargLeft->hDDSurface;
 +            hSurfaceCurrentLeft = (HANDLE) Flip->lpSurfCurrLeft->hDDSurface;
 +        }
 +    }
 +
 +    /* Call win32k */
 +    return NtGdiDdFlip( (HANDLE) Flip->lpSurfCurr->hDDSurface,
 +                        (HANDLE) Flip->lpSurfTarg->hDDSurface,
 +                        hSurfaceCurrentLeft,
 +                        hSurfaceTargetLeft,
 +                        (PDD_FLIPDATA) Flip);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdLock
 + */
 +DWORD
 +WINAPI
 +DdLock(LPDDHAL_LOCKDATA Lock)
 +{
 +
 +    /* Call win32k */
 +    return NtGdiDdLock((HANDLE)Lock->lpDDSurface->hDDSurface,
 +                       (PDD_LOCKDATA)Lock,
 +                       (HANDLE)Lock->lpDDSurface->hDC);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdUnlock
 + */
 +DWORD
 +WINAPI
 +DdUnlock(LPDDHAL_UNLOCKDATA Unlock)
 +{
 +    /* Call win32k */
 +    return NtGdiDdUnlock((HANDLE)Unlock->lpDDSurface->hDDSurface,
 +                         (PDD_UNLOCKDATA)Unlock);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdGetBltStatus
 + */
 +DWORD
 +WINAPI
 +DdGetBltStatus(LPDDHAL_GETBLTSTATUSDATA GetBltStatus)
 +{
 +    /* Call win32k */
 +    return NtGdiDdGetBltStatus((HANDLE)GetBltStatus->lpDDSurface->hDDSurface,
 +                               (PDD_GETBLTSTATUSDATA)GetBltStatus);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdGetBltStatus
 + */
 +DWORD
 +WINAPI
 +DdGetFlipStatus(LPDDHAL_GETFLIPSTATUSDATA GetFlipStatus)
 +{
 +    /* Call win32k */
 +    return NtGdiDdGetFlipStatus((HANDLE)GetFlipStatus->lpDDSurface->hDDSurface,
 +                                (PDD_GETFLIPSTATUSDATA)GetFlipStatus);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdUpdateOverlay
 + */
 +DWORD
 +WINAPI
 +DdUpdateOverlay(LPDDHAL_UPDATEOVERLAYDATA UpdateOverlay)
 +{
 +
 +    /* We have to handle this manually here */
 +    if (UpdateOverlay->dwFlags & DDOVER_KEYDEST)
 +    {
 +        /* Use the override */
 +        UpdateOverlay->dwFlags &= ~DDOVER_KEYDEST;
 +        UpdateOverlay->dwFlags |=  DDOVER_KEYDESTOVERRIDE;
 +
 +        /* Set the overlay */
 +        UpdateOverlay->overlayFX.dckDestColorkey =
 +            UpdateOverlay->lpDDDestSurface->ddckCKDestOverlay;
 +    }
 +    if (UpdateOverlay->dwFlags & DDOVER_KEYSRC)
 +    {
 +        /* Use the override */
 +        UpdateOverlay->dwFlags &= ~DDOVER_KEYSRC;
 +        UpdateOverlay->dwFlags |=  DDOVER_KEYSRCOVERRIDE;
 +
 +        /* Set the overlay */
 +        UpdateOverlay->overlayFX.dckSrcColorkey =
 +            UpdateOverlay->lpDDSrcSurface->ddckCKSrcOverlay;
 +    }
 +
 +    /* Call win32k */
 +    return NtGdiDdUpdateOverlay((HANDLE)UpdateOverlay->lpDDDestSurface->hDDSurface,
 +                                (HANDLE)UpdateOverlay->lpDDSrcSurface->hDDSurface,
 +                                (PDD_UPDATEOVERLAYDATA)UpdateOverlay);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdSetOverlayPosition
 + */
 +DWORD
 +WINAPI
 +DdSetOverlayPosition(LPDDHAL_SETOVERLAYPOSITIONDATA SetOverlayPosition)
 +{
 +    /* Call win32k */
 +    return NtGdiDdSetOverlayPosition( (HANDLE)SetOverlayPosition->lpDDSrcSurface->hDDSurface,
 +                                      (HANDLE)SetOverlayPosition->lpDDDestSurface->hDDSurface,
 +                                      (PDD_SETOVERLAYPOSITIONDATA) SetOverlayPosition);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdWaitForVerticalBlank
 + */
 +DWORD
 +WINAPI
 +DdWaitForVerticalBlank(LPDDHAL_WAITFORVERTICALBLANKDATA WaitForVerticalBlank)
 +{
 +    /* Call win32k */
 +    return NtGdiDdWaitForVerticalBlank(GetDdHandle(
 +                                           WaitForVerticalBlank->lpDD->hDD),
 +                                       (PDD_WAITFORVERTICALBLANKDATA)
 +                                       WaitForVerticalBlank);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdCanCreateSurface
 + */
 +DWORD
 +WINAPI
 +DdCanCreateSurface(LPDDHAL_CANCREATESURFACEDATA CanCreateSurface)
 +{
 +    /*
 +     * Note : This functions are basic same, in win32k
 +     * NtGdiDdCanCreateD3DBuffer and  NtGdiDdCanCreateSurface are mergs
 +     * toghter in win32k at end and retrurn same data, it is still sepreated
 +     * at user mode but in kmode it is not.
 +     */
 +
 +    /* Call win32k */
 +    return NtGdiDdCanCreateSurface(GetDdHandle(CanCreateSurface->lpDD->hDD),
 +                                   (PDD_CANCREATESURFACEDATA)CanCreateSurface);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdCreateSurface
 + */
 +DWORD
 +WINAPI
 +DdCreateSurface(LPDDHAL_CREATESURFACEDATA pCreateSurface)
 +{
 +    DWORD Return = DDHAL_DRIVER_NOTHANDLED;
 +    ULONG SurfaceCount = pCreateSurface->dwSCnt;
 +    DD_SURFACE_LOCAL DdSurfaceLocal;
 +    DD_SURFACE_MORE DdSurfaceMore;
 +    DD_SURFACE_GLOBAL DdSurfaceGlobal;
 +
 +    HANDLE hPrevSurface, hSurface;
 +
 +    PDD_SURFACE_LOCAL pDdSurfaceLocal = NULL;
 +    PDD_SURFACE_MORE pDdSurfaceMore = NULL;
 +    PDD_SURFACE_GLOBAL pDdSurfaceGlobal = NULL;
 +
 +    PDD_SURFACE_LOCAL ptmpDdSurfaceLocal = NULL;
 +    PDD_SURFACE_MORE ptmpDdSurfaceMore = NULL;
 +    PDD_SURFACE_GLOBAL ptmpDdSurfaceGlobal = NULL;
 +    PHANDLE phSurface = NULL, puhSurface = NULL;
 +    ULONG i;
 +    LPDDSURFACEDESC pSurfaceDesc = NULL;
 +
 +    /* TODO: Optimize speed. Most games/dx apps/programs do not want one surface, they want at least two.
 +     * So we need increase the stack to contain two surfaces instead of one. This will increase
 +     * the speed of the apps when allocating buffers. How to increase the surface stack space:
 +     * we need to create a struct for DD_SURFACE_LOCAL DdSurfaceLocal, DD_SURFACE_MORE DdSurfaceMore
 +     * DD_SURFACE_GLOBAL DdSurfaceGlobal, HANDLE hPrevSurface, hSurface like
 +     * struct { DD_SURFACE_LOCAL DdSurfaceLocal1, DD_SURFACE_LOCAL DdSurfaceLocal2 }
 +     * in a way that it may contain two surfaces, maybe even four. We need to watch what is most common before
 +     * we create the size. Activate this IF when you start doing the optimze and please also
 +     * take reports from users which value they got here.
 +     */
 +#if 1
 +    {
 +        char buffer[1024];
 +        \
 +        sprintf ( buffer, "Function %s : Optimze max to %d Surface ? (%s:%d)\n", __FUNCTION__, (int)SurfaceCount,__FILE__,__LINE__ );
 +        OutputDebugStringA(buffer);
 +    }
 +#endif
 +
 +    /* Check how many surfaces there are */
 +    if (SurfaceCount != 1)
 +    {
 +        /* We got more than one surface, so we need to allocate memory for them */
 +        pDdSurfaceLocal = (PDD_SURFACE_LOCAL) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (sizeof(DD_SURFACE_LOCAL) * SurfaceCount ));
 +        pDdSurfaceMore = (PDD_SURFACE_MORE) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (sizeof(DD_SURFACE_MORE) * SurfaceCount ));
 +        pDdSurfaceGlobal = (PDD_SURFACE_GLOBAL)  HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (sizeof(DD_SURFACE_GLOBAL) * SurfaceCount ));
 +        phSurface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (sizeof(HANDLE) * SurfaceCount ));
 +        puhSurface = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (sizeof(HANDLE) * SurfaceCount ));
 +
 +        /* Check if we successfully allocated all memory we need */
 +        if ((pDdSurfaceLocal == NULL) || (pDdSurfaceMore == NULL) || (pDdSurfaceGlobal == NULL) || (phSurface == NULL) || (puhSurface == NULL))
 +        {
 +            pCreateSurface->ddRVal = DDERR_OUTOFMEMORY;
 +
 +            if ( pDdSurfaceLocal != NULL )
 +            {
 +                HeapFree(GetProcessHeap(), 0, pDdSurfaceLocal);
 +            }
 +
 +            if ( pDdSurfaceMore != NULL )
 +            {
 +                HeapFree(GetProcessHeap(), 0, pDdSurfaceMore);
 +            }
 +
 +            if ( pDdSurfaceGlobal != NULL )
 +            {
 +                HeapFree(GetProcessHeap(), 0, pDdSurfaceGlobal);
 +            }
 +
 +            if ( phSurface != NULL )
 +            {
 +                HeapFree(GetProcessHeap(), 0, phSurface);
 +            }
 +
 +            if ( puhSurface != NULL )
 +            {
 +                HeapFree(GetProcessHeap(), 0, puhSurface);
 +            }
 +
 +            return DDHAL_DRIVER_HANDLED;
 +        }
 +    }
 +    else
 +    {
 +        /* We'll use what we have on the stack */
 +        pDdSurfaceLocal = &DdSurfaceLocal;
 +        pDdSurfaceMore = &DdSurfaceMore;
 +        pDdSurfaceGlobal = &DdSurfaceGlobal;
 +        phSurface = &hPrevSurface;
 +        puhSurface = &hSurface;
 +
 +        /* Clear the structures */
 +        RtlZeroMemory(&DdSurfaceLocal, sizeof(DdSurfaceLocal));
 +        RtlZeroMemory(&DdSurfaceGlobal, sizeof(DdSurfaceGlobal));
 +        RtlZeroMemory(&DdSurfaceMore, sizeof(DdSurfaceMore));
 +    }
 +
 +    /* check if we got a surface or not */
 +    if (SurfaceCount!=0)
 +    {
 +        /* Loop for each surface */
 +        ptmpDdSurfaceGlobal = pDdSurfaceGlobal;
 +        ptmpDdSurfaceLocal = pDdSurfaceLocal;
 +        ptmpDdSurfaceMore = pDdSurfaceMore;
 +        pSurfaceDesc = pCreateSurface->lpDDSurfaceDesc;
 +
 +        for (i = 0; i < SurfaceCount; i++)
 +        {
 +            LPDDRAWI_DDRAWSURFACE_LCL lcl = pCreateSurface->lplpSList[i];
 +            LPDDRAWI_DDRAWSURFACE_GBL gpl = pCreateSurface->lplpSList[i]->lpGbl;
 +
 +            phSurface[i] = (HANDLE)lcl->hDDSurface;
 +            ptmpDdSurfaceLocal->ddsCaps.dwCaps = lcl->ddsCaps.dwCaps;
 +
 +            ptmpDdSurfaceLocal->dwFlags = (ptmpDdSurfaceLocal->dwFlags &
 +                                           (0xB0000000 | DDRAWISURF_INMASTERSPRITELIST |
 +                                            DDRAWISURF_HELCB | DDRAWISURF_FRONTBUFFER |
 +                                            DDRAWISURF_BACKBUFFER | DDRAWISURF_INVALID |
 +                                            DDRAWISURF_DCIBUSY | DDRAWISURF_DCILOCK)) |
 +                                          (lcl->dwFlags & DDRAWISURF_DRIVERMANAGED);
 +
 +            ptmpDdSurfaceGlobal->wWidth = gpl->wWidth;
 +            ptmpDdSurfaceGlobal->wHeight = gpl->wHeight;
 +            ptmpDdSurfaceGlobal->lPitch = gpl->lPitch;
 +            ptmpDdSurfaceGlobal->fpVidMem = gpl->fpVidMem;
 +            ptmpDdSurfaceGlobal->dwBlockSizeX = gpl->dwBlockSizeX;
 +            ptmpDdSurfaceGlobal->dwBlockSizeY = gpl->dwBlockSizeY;
 +
 +            if (lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT)
 +            {
 +                RtlCopyMemory( &ptmpDdSurfaceGlobal->ddpfSurface ,
 +                               &gpl->ddpfSurface,
 +                               sizeof(DDPIXELFORMAT));
 +
 +                ptmpDdSurfaceGlobal->ddpfSurface.dwSize = sizeof(DDPIXELFORMAT);
 +            }
 +            else
 +            {
 +                RtlCopyMemory( &ptmpDdSurfaceGlobal->ddpfSurface ,
 +                               &gpl->lpDD->vmiData.ddpfDisplay,
 +                               sizeof(DDPIXELFORMAT));
 +            }
 +
 +            /* Note if lcl->lpSurfMore is NULL zero out
 +             * ptmpDdSurfaceMore->ddsCapsEx.dwCaps2,
 +             * dwCaps3, dwCaps4, ptmpDdSurfaceMore->dwSurfaceHandle
 +             */
 +            if (lcl->lpSurfMore)
 +            {
 +                ptmpDdSurfaceMore->ddsCapsEx.dwCaps2 = lcl->lpSurfMore->ddsCapsEx.dwCaps2;
 +                ptmpDdSurfaceMore->ddsCapsEx.dwCaps3 = lcl->lpSurfMore->ddsCapsEx.dwCaps3;
 +                ptmpDdSurfaceMore->ddsCapsEx.dwCaps4 = lcl->lpSurfMore->ddsCapsEx.dwCaps4;
 +                ptmpDdSurfaceMore->dwSurfaceHandle = lcl->lpSurfMore->dwSurfaceHandle;
 +            }
 +
 +
 +            /* count to next SurfaceCount */
 +            ptmpDdSurfaceGlobal = (PDD_SURFACE_GLOBAL) (((PBYTE) ((ULONG_PTR) ptmpDdSurfaceGlobal)) + sizeof(DD_SURFACE_GLOBAL));
 +            ptmpDdSurfaceLocal = (PDD_SURFACE_LOCAL) (((PBYTE) ((ULONG_PTR) ptmpDdSurfaceLocal)) + sizeof(DD_SURFACE_LOCAL));
 +            ptmpDdSurfaceMore = (PDD_SURFACE_MORE) (((PBYTE) ((ULONG_PTR) ptmpDdSurfaceMore)) + sizeof(DD_SURFACE_MORE));
 +        }
 +    }
 +
 +    /* Call win32k now */
 +    pCreateSurface->ddRVal = DDERR_GENERIC;
 +
 +    Return = NtGdiDdCreateSurface(GetDdHandle(pCreateSurface->lpDD->hDD),
 +                                  (HANDLE *)phSurface,
 +                                  pSurfaceDesc,
 +                                  pDdSurfaceGlobal,
 +                                  pDdSurfaceLocal,
 +                                  pDdSurfaceMore,
 +                                  (PDD_CREATESURFACEDATA)pCreateSurface,
 +                                  puhSurface);
 +
 +    if (SurfaceCount == 0)
 +    {
 +        pCreateSurface->ddRVal = DDERR_GENERIC;
 +    }
 +    else
 +    {
 +        ptmpDdSurfaceMore = pDdSurfaceMore;
 +        ptmpDdSurfaceGlobal = pDdSurfaceGlobal;
 +        ptmpDdSurfaceLocal = pDdSurfaceLocal;
 +
 +        for (i=0; i<SurfaceCount; i++)
 +        {
 +            LPDDRAWI_DDRAWSURFACE_LCL lcl = pCreateSurface->lplpSList[i];
 +            LPDDRAWI_DDRAWSURFACE_GBL gpl = pCreateSurface->lplpSList[i]->lpGbl;
 +
 +            gpl->lPitch = ptmpDdSurfaceGlobal->lPitch;
 +            gpl->fpVidMem = ptmpDdSurfaceGlobal->fpVidMem;
 +            gpl->dwBlockSizeX = ptmpDdSurfaceGlobal->dwBlockSizeX;
 +            gpl->dwBlockSizeY = ptmpDdSurfaceGlobal->dwBlockSizeY;
 +
 +            if (lcl->dwFlags & DDRAWISURF_HASPIXELFORMAT)
 +            {
 +                RtlCopyMemory( &gpl->ddpfSurface, &ptmpDdSurfaceGlobal->ddpfSurface , sizeof(DDPIXELFORMAT));
 +            }
 +
 +            if (pCreateSurface->ddRVal != DD_OK)
 +            {
 +                gpl->fpVidMem = 0;
 +                if (lcl->hDDSurface)
 +                {
 +                    NtGdiDdDeleteSurfaceObject( (HANDLE)lcl->hDDSurface);
 +                }
 +                lcl->hDDSurface = 0;
 +            }
 +            else
 +            {
 +
 +                lcl->hDDSurface = (ULONG_PTR) puhSurface[i];
 +            }
 +
 +            lcl->ddsCaps.dwCaps = ptmpDdSurfaceLocal->ddsCaps.dwCaps;
 +            if (lcl->lpSurfMore)
 +            {
 +                lcl->lpSurfMore->ddsCapsEx.dwCaps2 = ptmpDdSurfaceMore->ddsCapsEx.dwCaps2;
 +                lcl->lpSurfMore->ddsCapsEx.dwCaps3 = ptmpDdSurfaceMore->ddsCapsEx.dwCaps3;
 +                lcl->lpSurfMore->ddsCapsEx.dwCaps4 = ptmpDdSurfaceMore->ddsCapsEx.dwCaps4;
 +            }
 +
 +            /* count to next SurfaceCount */
 +            ptmpDdSurfaceGlobal = (PDD_SURFACE_GLOBAL) (((PBYTE) ((ULONG_PTR) ptmpDdSurfaceGlobal)) + sizeof(DD_SURFACE_GLOBAL));
 +            ptmpDdSurfaceLocal = (PDD_SURFACE_LOCAL) (((PBYTE) ((ULONG_PTR) ptmpDdSurfaceLocal)) + sizeof(DD_SURFACE_LOCAL));
 +            ptmpDdSurfaceMore = (PDD_SURFACE_MORE) (((PBYTE) ((ULONG_PTR) ptmpDdSurfaceMore)) + sizeof(DD_SURFACE_MORE));
 +        }
 +    }
 +
 +    /* Check if we have to free all our local allocations */
 +    if (SurfaceCount > 1)
 +    {
 +        if ( pDdSurfaceLocal != NULL )
 +        {
 +            HeapFree(GetProcessHeap(), 0, pDdSurfaceLocal);
 +        }
 +
 +        if ( pDdSurfaceMore != NULL )
 +        {
 +            HeapFree(GetProcessHeap(), 0, pDdSurfaceMore);
 +        }
 +
 +        if ( pDdSurfaceGlobal != NULL )
 +        {
 +            HeapFree(GetProcessHeap(), 0, pDdSurfaceGlobal);
 +        }
 +
 +        if ( phSurface != NULL )
 +        {
 +            HeapFree(GetProcessHeap(), 0, phSurface);
 +        }
 +
 +        if ( puhSurface != NULL )
 +        {
 +            HeapFree(GetProcessHeap(), 0, puhSurface);
 +        }
 +    }
 +
 +    /* Return */
 +    return Return;
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdSetColorKey
 + */
 +DWORD
 +WINAPI
 +DdSetColorKey(LPDDHAL_SETCOLORKEYDATA pSetColorKey)
 +{
 +    /* Call win32k */
 +    return NtGdiDdSetColorKey((HANDLE)pSetColorKey->lpDDSurface->hDDSurface,
 +                              (PDD_SETCOLORKEYDATA)pSetColorKey);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdGetScanLine
 + */
 +DWORD
 +WINAPI
 +DdGetScanLine(LPDDHAL_GETSCANLINEDATA pGetScanLine)
 +{
 +    /* Call win32k */
 +    return NtGdiDdGetScanLine(GetDdHandle(pGetScanLine->lpDD->hDD),
 +                              (PDD_GETSCANLINEDATA)pGetScanLine);
 +}
 +
 +
 +/*
 + * @implemented
 + *
 + * DvpCreateVideoPort
 + */
 +BOOL
 +WINAPI
 +DvpCreateVideoPort(LPDDHAL_CREATEVPORTDATA pDvdCreatePort)
 +{
 +    pDvdCreatePort->lpVideoPort->hDDVideoPort =
 +        NtGdiDvpCreateVideoPort(GetDdHandle(pDvdCreatePort->lpDD->lpGbl->hDD),
 +                                (PDD_CREATEVPORTDATA) pDvdCreatePort);
 +
 +    return TRUE;
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpCreateVideoPort
 + */
 +DWORD
 +WINAPI
 +DvpDestroyVideoPort(LPDDHAL_DESTROYVPORTDATA pDvdDestoryPort)
 +{
 +    return NtGdiDvpDestroyVideoPort(pDvdDestoryPort->lpVideoPort->hDDVideoPort, (PDD_DESTROYVPORTDATA)pDvdDestoryPort);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpCreateVideoPort
 + */
 +DWORD
 +WINAPI
 +DvpFlipVideoPort(LPDDHAL_FLIPVPORTDATA pDvdPortFlip)
 +{
 +    return NtGdiDvpFlipVideoPort(pDvdPortFlip->lpVideoPort->hDDVideoPort,
 +                                 (HANDLE)pDvdPortFlip->lpSurfCurr->hDDSurface,
 +                                 (HANDLE)pDvdPortFlip->lpSurfTarg->hDDSurface,
 +                                 (PDD_FLIPVPORTDATA) pDvdPortFlip);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpGetVideoPortBandwidth
 + */
 +DWORD
 +WINAPI
 +DvpGetVideoPortBandwidth(LPDDHAL_GETVPORTBANDWIDTHDATA pDvdPortBandWidth)
 +{
 +    return NtGdiDvpGetVideoPortBandwidth(pDvdPortBandWidth->lpVideoPort->hDDVideoPort, (PDD_GETVPORTBANDWIDTHDATA)pDvdPortBandWidth);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpColorControl
 + */
 +DWORD
 +WINAPI
 +DvpColorControl(LPDDHAL_VPORTCOLORDATA pDvdPortColorControl)
 +{
 +    return NtGdiDvpColorControl(pDvdPortColorControl->lpVideoPort->hDDVideoPort, (PDD_VPORTCOLORDATA) pDvdPortColorControl);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpGetVideoSignalStatus
 + */
 +DWORD
 +WINAPI
 +DvpGetVideoSignalStatus(LPDDHAL_GETVPORTSIGNALDATA pDvdPortVideoSignalStatus)
 +{
 +    return NtGdiDvpGetVideoSignalStatus(pDvdPortVideoSignalStatus->lpVideoPort->hDDVideoPort, (PDD_GETVPORTSIGNALDATA) pDvdPortVideoSignalStatus);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpGetVideoPortFlipStatus
 + */
 +DWORD
 +WINAPI
 +DvpGetVideoPortFlipStatus(LPDDHAL_GETVPORTFLIPSTATUSDATA pDvdPortVideoPortFlipStatus)
 +{
 +    return NtGdiDvpGetVideoPortFlipStatus(GetDdHandle(pDvdPortVideoPortFlipStatus->lpDD->lpGbl->hDD), (PDD_GETVPORTFLIPSTATUSDATA) pDvdPortVideoPortFlipStatus);
 +
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpCanCreateVideoPort
 + */
 +DWORD
 +WINAPI
 +DvpCanCreateVideoPort(LPDDHAL_CANCREATEVPORTDATA pDvdCanCreateVideoPort)
 +{
 +    return NtGdiDvpCanCreateVideoPort(GetDdHandle(pDvdCanCreateVideoPort->lpDD->lpGbl->hDD), (PDD_CANCREATEVPORTDATA) pDvdCanCreateVideoPort);
 +}
 +/*
 + * @implemented
 + *
 + * DvpWaitForVideoPortSync
 + */
 +DWORD
 +WINAPI
 +DvpWaitForVideoPortSync(LPDDHAL_WAITFORVPORTSYNCDATA pDvdWaitForVideoPortSync)
 +{
 +    return NtGdiDvpWaitForVideoPortSync(pDvdWaitForVideoPortSync->lpVideoPort->hDDVideoPort,  (PDD_WAITFORVPORTSYNCDATA) pDvdWaitForVideoPortSync);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpUpdateVideoPort
 + */
 +DWORD
 +WINAPI
 +DvpUpdateVideoPort(LPDDHAL_UPDATEVPORTDATA pDvdUpdateVideoPort)
 +{
 +    /*
 +     * Windows XP limit to max 10 handles of videoport surface and Vbi
 +     * ReactOS doing same to keep compatible, if it is more that 10
 +     * videoport surface or vbi the stack will be curpted in windows xp
 +     * ReactOS safe guard againts that
 +     *
 +     */
 +
 +    HANDLE phSurfaceVideo[10];
 +    HANDLE phSurfaceVbi[10];
 +
 +    if (pDvdUpdateVideoPort->dwFlags != DDRAWI_VPORTSTOP)
 +    {
 +        DWORD dwNumAutoflip;
 +        DWORD dwNumVBIAutoflip;
 +
 +        /* Take copy of lplpDDSurface for the handle value will be modify in dxg */
 +        dwNumAutoflip = pDvdUpdateVideoPort->dwNumAutoflip;
 +        if ((dwNumAutoflip == 0) &&
 +                (pDvdUpdateVideoPort->lplpDDSurface == 0))
 +        {
 +            dwNumAutoflip++;
 +        }
 +
 +        if (dwNumAutoflip != 0)
 +        {
 +            if (dwNumAutoflip>10)
 +            {
 +                dwNumAutoflip = 10;
 +            }
 +            memcpy(phSurfaceVideo,pDvdUpdateVideoPort->lplpDDSurface,dwNumAutoflip*sizeof(HANDLE));
 +        }
 +
 +        /* Take copy of lplpDDVBISurface for the handle value will be modify in dxg */
 +        dwNumVBIAutoflip = pDvdUpdateVideoPort->dwNumVBIAutoflip;
 +        if ( (dwNumVBIAutoflip == 0) &&
 +                (pDvdUpdateVideoPort->lplpDDVBISurface == 0) )
 +        {
 +            dwNumVBIAutoflip++;
 +        }
 +
 +        if (dwNumVBIAutoflip != 0)
 +        {
 +            if (dwNumVBIAutoflip>10)
 +            {
 +                dwNumVBIAutoflip = 10;
 +            }
 +            memcpy(phSurfaceVbi,pDvdUpdateVideoPort->lplpDDVBISurface,dwNumVBIAutoflip*sizeof(HANDLE));
 +        }
 +    }
 +
 +    /* Call Win32k */
 +    return NtGdiDvpUpdateVideoPort(pDvdUpdateVideoPort->lpVideoPort->hDDVideoPort,phSurfaceVideo,phSurfaceVbi, (PDD_UPDATEVPORTDATA)pDvdUpdateVideoPort);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpWaitForVideoPortSync
 + */
 +DWORD
 +WINAPI
 +DvpGetVideoPortField(LPDDHAL_FLIPVPORTDATA pDvdGetVideoPortField)
 +{
 +    return NtGdiDvpGetVideoPortField(pDvdGetVideoPortField->lpVideoPort->hDDVideoPort, (PDD_GETVPORTFIELDDATA)pDvdGetVideoPortField);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpWaitForVideoPortSync
 + */
 +DWORD
 +WINAPI
 +DvpGetVideoPortInputFormats(LPDDHAL_GETVPORTINPUTFORMATDATA pDvdGetVideoPortInputFormat)
 +{
 +    return NtGdiDvpGetVideoPortInputFormats(pDvdGetVideoPortInputFormat->lpVideoPort->hDDVideoPort, (PDD_GETVPORTINPUTFORMATDATA) pDvdGetVideoPortInputFormat);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpGetVideoPortLine
 + */
 +DWORD
 +WINAPI
 +DvpGetVideoPortLine(LPDDHAL_GETVPORTLINEDATA pDvdGetVideoPortLine)
 +{
 +    return NtGdiDvpGetVideoPortLine(pDvdGetVideoPortLine->lpVideoPort->hDDVideoPort, (PDD_GETVPORTLINEDATA)pDvdGetVideoPortLine);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpGetVideoPortOutputFormats
 + */
 +DWORD
 +WINAPI
 +DvpGetVideoPortOutputFormats(LPDDHAL_GETVPORTLINEDATA pDvdGetVideoPortOutputFormat)
 +{
 +    return NtGdiDvpGetVideoPortLine(pDvdGetVideoPortOutputFormat->lpVideoPort->hDDVideoPort, (PDD_GETVPORTLINEDATA)pDvdGetVideoPortOutputFormat);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DvpGetVideoPortConnectInfo
 + */
 +DWORD
 +WINAPI
 +DvpGetVideoPortConnectInfo(LPDDHAL_GETVPORTCONNECTDATA pDvdGetVideoPortInfo)
 +{
 +    return NtGdiDvpGetVideoPortConnectInfo( GetDdHandle( pDvdGetVideoPortInfo->lpDD->lpGbl->hDD) , (PDD_GETVPORTCONNECTDATA) pDvdGetVideoPortInfo);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdGetAvailDriverMemory
 + */
 +DWORD
 +WINAPI
 +DdGetAvailDriverMemory(LPDDHAL_GETAVAILDRIVERMEMORYDATA pDdGetAvailDriverMemory)
 +{
 +    return NtGdiDdGetAvailDriverMemory(GetDdHandle( pDdGetAvailDriverMemory->lpDD->hDD), (PDD_GETAVAILDRIVERMEMORYDATA) pDdGetAvailDriverMemory);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdAlphaBlt
 + */
 +DWORD
 +WINAPI
 +DdAlphaBlt(LPDDHAL_BLTDATA pDdAlphaBlt)
 +{
 +    HANDLE hDDSrcSurface = 0;
 +
 +    if (pDdAlphaBlt->lpDDSrcSurface != 0)
 +    {
 +        hDDSrcSurface = (HANDLE) pDdAlphaBlt->lpDDSrcSurface->hDDSurface;
 +    }
 +
 +    return NtGdiDdAlphaBlt((HANDLE)pDdAlphaBlt->lpDDDestSurface->hDDSurface, hDDSrcSurface, (PDD_BLTDATA)&pDdAlphaBlt);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdCreateSurfaceEx
 + */
 +DWORD
 +WINAPI
 +DdCreateSurfaceEx(LPDDHAL_CREATESURFACEEXDATA pDdCreateSurfaceEx)
 +{
 +    pDdCreateSurfaceEx->ddRVal = NtGdiDdCreateSurfaceEx( GetDdHandle(pDdCreateSurfaceEx->lpDDLcl->lpGbl->hDD),
 +                                 (HANDLE)pDdCreateSurfaceEx->lpDDSLcl->hDDSurface,
 +                                 pDdCreateSurfaceEx->lpDDSLcl->lpSurfMore->dwSurfaceHandle);
 +    return TRUE;
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdColorControl
 + */
 +DWORD
 +WINAPI
 +DdColorControl(LPDDHAL_COLORCONTROLDATA pDdColorControl)
 +{
 +    return NtGdiDdColorControl( (HANDLE) pDdColorControl->lpDDSurface->hDDSurface, (PDD_COLORCONTROLDATA) &pDdColorControl);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdSetExclusiveMode
 + */
 +DWORD
 +WINAPI
 +DdSetExclusiveMode(LPDDHAL_SETEXCLUSIVEMODEDATA pDdSetExclusiveMode)
 +{
 +    return NtGdiDdSetExclusiveMode( GetDdHandle(pDdSetExclusiveMode->lpDD->hDD), (PDD_SETEXCLUSIVEMODEDATA) &pDdSetExclusiveMode);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdFlipToGDISurface
 + */
 +DWORD
 +WINAPI
 +DdFlipToGDISurface(LPDDHAL_FLIPTOGDISURFACEDATA pDdFlipToGDISurface)
 +{
 +    return NtGdiDdFlipToGDISurface( GetDdHandle(pDdFlipToGDISurface->lpDD->hDD), (PDD_FLIPTOGDISURFACEDATA) &pDdFlipToGDISurface);
 +}
 +
 +/* TODO */
 +DWORD
 +WINAPI
 +DdGetDriverInfo(LPDDHAL_GETDRIVERINFODATA pData)
 +{
 +    DDHAL_GETDRIVERINFODATA pDrvInfoData;
 +    DWORD retValue = DDHAL_DRIVER_NOTHANDLED;
 +    HANDLE hDD;
 +
 +    /* FIXME add SEH around this functions */
 +
 +    RtlZeroMemory(&pDrvInfoData, sizeof (DDHAL_GETDRIVERINFODATA));
 +    RtlCopyMemory(&pDrvInfoData.guidInfo, &pData->guidInfo, sizeof(GUID));
 +
 +    hDD = GetDdHandle(pData->dwContext);
 +
 +    pDrvInfoData.dwSize = sizeof (DDHAL_GETDRIVERINFODATA);
 +    pDrvInfoData.ddRVal = DDERR_GENERIC;
 +    pDrvInfoData.dwContext = (ULONG_PTR)hDD;
 +
 +
 +    /* Videoport Callbacks check and setup for DirectX/ ReactX */
 +    if (IsEqualGUID(&pData->guidInfo, &GUID_VideoPortCallbacks))
 +    {
 +        DDHAL_DDVIDEOPORTCALLBACKS  pDvdPort;
 +        DDHAL_DDVIDEOPORTCALLBACKS* pUserDvdPort = (DDHAL_DDVIDEOPORTCALLBACKS *)pData->lpvData;
 +
 +        /* Clear internal out buffer and set it up*/
 +        RtlZeroMemory(&pDvdPort, DDVIDEOPORTCALLBACKSSIZE);
 +        pDvdPort.dwSize = DDVIDEOPORTCALLBACKSSIZE;
 +
 +        /* set up internal buffer */
 +        pDrvInfoData.lpvData = (PVOID)&pDvdPort;
 +        pDrvInfoData.dwExpectedSize = DDVIDEOPORTCALLBACKSSIZE ;
 +
 +        /* Call win32k */
 +        retValue = NtGdiDdGetDriverInfo(hDD, (PDD_GETDRIVERINFODATA)&pDrvInfoData);
 +
 +        /* Setup user out buffer and convert kmode callbacks to user mode */
 +        pUserDvdPort->dwSize = DDVIDEOPORTCALLBACKSSIZE;
 +        pUserDvdPort->dwFlags = pDrvInfoData.dwFlags =  0;
 +
 +        pUserDvdPort->dwFlags = (pDrvInfoData.dwFlags & ~(DDHAL_VPORT32_CREATEVIDEOPORT | DDHAL_VPORT32_FLIP |
 +                                 DDHAL_VPORT32_DESTROY | DDHAL_VPORT32_UPDATE | DDHAL_VPORT32_WAITFORSYNC)) |
 +                                (DDHAL_VPORT32_CREATEVIDEOPORT | DDHAL_VPORT32_FLIP |
 +                                 DDHAL_VPORT32_DESTROY | DDHAL_VPORT32_UPDATE);
 +
 +        pData->dwActualSize = DDVIDEOPORTCALLBACKSSIZE;
 +        pUserDvdPort->CreateVideoPort = (LPDDHALVPORTCB_CREATEVIDEOPORT) DvpCreateVideoPort;
 +        pUserDvdPort->FlipVideoPort = (LPDDHALVPORTCB_FLIP) DvpFlipVideoPort;
 +        pUserDvdPort->DestroyVideoPort = (LPDDHALVPORTCB_DESTROYVPORT) DvpDestroyVideoPort;
 +        pUserDvdPort->UpdateVideoPort = (LPDDHALVPORTCB_UPDATE) DvpUpdateVideoPort;
 +
 +        if (pDvdPort.CanCreateVideoPort)
 +        {
 +            pUserDvdPort->CanCreateVideoPort = (LPDDHALVPORTCB_CANCREATEVIDEOPORT) DvpCanCreateVideoPort;
 +        }
 +
 +        if (pDvdPort.GetVideoPortBandwidth)
 +        {
 +            pUserDvdPort->GetVideoPortBandwidth = (LPDDHALVPORTCB_GETBANDWIDTH) DvpGetVideoPortBandwidth;
 +        }
 +
 +        if (pDvdPort.GetVideoPortInputFormats)
 +        {
 +            pUserDvdPort->GetVideoPortInputFormats = (LPDDHALVPORTCB_GETINPUTFORMATS) DvpGetVideoPortInputFormats;
 +        }
 +
 +        if (pDvdPort.GetVideoPortOutputFormats)
 +        {
 +            pUserDvdPort->GetVideoPortOutputFormats = (LPDDHALVPORTCB_GETOUTPUTFORMATS) DvpGetVideoPortOutputFormats;
 +        }
 +
 +        if (pDvdPort.GetVideoPortField)
 +        {
 +            pUserDvdPort->GetVideoPortField = (LPDDHALVPORTCB_GETFIELD) DvpGetVideoPortField;
 +        }
 +
 +        if (pDvdPort.GetVideoPortLine)
 +        {
 +            pUserDvdPort->GetVideoPortLine = (LPDDHALVPORTCB_GETLINE) DvpGetVideoPortLine;
 +        }
 +
 +        if (pDvdPort.GetVideoPortConnectInfo)
 +        {
 +            pUserDvdPort->GetVideoPortConnectInfo = (LPDDHALVPORTCB_GETVPORTCONNECT) DvpGetVideoPortConnectInfo;
 +        }
 +
 +        if (pDvdPort.GetVideoPortFlipStatus)
 +        {
 +            pUserDvdPort->GetVideoPortFlipStatus = (LPDDHALVPORTCB_GETFLIPSTATUS) DvpGetVideoPortFlipStatus;
 +        }
 +
 +        if (pDvdPort.WaitForVideoPortSync)
 +        {
 +            pUserDvdPort->WaitForVideoPortSync = (LPDDHALVPORTCB_WAITFORSYNC) DvpWaitForVideoPortSync;
 +        }
 +
 +        if (pDvdPort.GetVideoSignalStatus)
 +        {
 +            pUserDvdPort->GetVideoSignalStatus = (LPDDHALVPORTCB_GETSIGNALSTATUS) DvpGetVideoSignalStatus;
 +        }
 +
 +        if (pDvdPort.ColorControl)
 +        {
 +            pUserDvdPort->ColorControl = (LPDDHALVPORTCB_COLORCONTROL) DvpColorControl;
 +        }
 +
 +        /* Windows XP never repot back the true return value,
 +         *  it only report back if we have a driver or not
 +         *  ReactOS keep this behoir to be compatible with
 +         *  Windows XP
 +         */
 +        pData->ddRVal = retValue;
 +    }
 +
 +    /* Color Control Callbacks check and setup for DirectX/ ReactX */
 +    if (IsEqualGUID(&pData->guidInfo, &GUID_ColorControlCallbacks))
 +    {
 +        DDHAL_DDCOLORCONTROLCALLBACKS  pColorControl;
 +        DDHAL_DDCOLORCONTROLCALLBACKS* pUserColorControl = (DDHAL_DDCOLORCONTROLCALLBACKS *)pData->lpvData;
 +
 +        /* Clear internal out buffer and set it up*/
 +        RtlZeroMemory(&pColorControl, DDCOLORCONTROLCALLBACKSSIZE);
 +        pColorControl.dwSize = DDCOLORCONTROLCALLBACKSSIZE;
 +
 +        /* set up internal buffer */
 +        pDrvInfoData.lpvData = (PVOID)&pColorControl;
 +        pDrvInfoData.dwExpectedSize = DDCOLORCONTROLCALLBACKSSIZE ;
 +
 +        /* Call win32k */
 +        retValue = NtGdiDdGetDriverInfo(hDD, (PDD_GETDRIVERINFODATA)&pDrvInfoData);
 +
 +        pData->dwActualSize = DDCOLORCONTROLCALLBACKSSIZE;
 +        pData->dwFlags = pDrvInfoData.dwFlags;
 +
 +        pUserColorControl->dwSize = DDCOLORCONTROLCALLBACKSSIZE;
 +        pUserColorControl->dwFlags = pColorControl.dwFlags;
 +
 +        if (pColorControl.ColorControl != NULL)
 +        {
 +            pUserColorControl->ColorControl = (LPDDHALCOLORCB_COLORCONTROL) DdColorControl;
 +        }
 +
 +        /* Windows XP never repot back the true return value,
 +         *  it only report back if we have a driver or not
 +         *  ReactOS keep this behoir to be compatible with
 +         *  Windows XP
 +         */
 +        pData->ddRVal = retValue;
 +    }
 +
 +    /* Misc Callbacks check and setup for DirectX/ ReactX */
 +    else if (IsEqualGUID(&pData->guidInfo, &GUID_MiscellaneousCallbacks))
 +    {
 +        DDHAL_DDMISCELLANEOUSCALLBACKS  pMisc;
 +        DDHAL_DDMISCELLANEOUSCALLBACKS* pUserMisc = (DDHAL_DDMISCELLANEOUSCALLBACKS *)pData->lpvData;
 +
 +        /* Clear internal out buffer and set it up*/
 +        RtlZeroMemory(&pMisc, DDMISCELLANEOUSCALLBACKSSIZE);
 +        pMisc.dwSize = DDMISCELLANEOUSCALLBACKSSIZE;
 +
 +        /* set up internal buffer */
 +        pDrvInfoData.lpvData = (PVOID)&pMisc;
 +        pDrvInfoData.dwExpectedSize = DDMISCELLANEOUSCALLBACKSSIZE ;
 +
 +        /* Call win32k */
 +        retValue = NtGdiDdGetDriverInfo(hDD, (PDD_GETDRIVERINFODATA)&pDrvInfoData);
 +
 +        pData->dwActualSize = DDMISCELLANEOUSCALLBACKSSIZE;
 +
 +        /* Only one callbacks are supported */
 +        pUserMisc->dwFlags = pMisc.dwFlags & DDHAL_MISCCB32_GETAVAILDRIVERMEMORY;
 +        pUserMisc->GetAvailDriverMemory = (LPDDHAL_GETAVAILDRIVERMEMORY) DdGetAvailDriverMemory;
 +
 +        /* This callbacks are only for win9x and theirfor it is not longer use in NT or ReactOS
 +         * pUserMisc->UpdateNonLocalHeap;
 +         * pUserMisc->GetHeapAlignment;
 +         * pUserMisc->GetSysmemBltStatus; */
 +
 +        /* Windows XP never repot back the true return value,
 +         *  it only report back if we have a driver or not
 +         *  ReactOS keep this behoir to be compatible with
 +         *  Windows XP
 +         */
 +        pData->ddRVal = retValue;
 +    }
 +
 +    /* Misc 2 Callbacks check and setup for DirectX/ ReactX */
 +    else if (IsEqualGUID(&pData->guidInfo, &GUID_Miscellaneous2Callbacks))
 +    {
 +        DDHAL_DDMISCELLANEOUS2CALLBACKS  pMisc;
 +        DDHAL_DDMISCELLANEOUS2CALLBACKS* pUserMisc = (DDHAL_DDMISCELLANEOUS2CALLBACKS *)pData->lpvData;
 +
 +        /* Clear internal out buffer and set it up*/
 +        RtlZeroMemory(&pMisc, DDMISCELLANEOUS2CALLBACKSSIZE);
 +        pMisc.dwSize = DDMISCELLANEOUS2CALLBACKSSIZE;
 +
 +        /* set up internal buffer */
 +        pDrvInfoData.lpvData = (PVOID)&pMisc;
 +        pDrvInfoData.dwExpectedSize = DDMISCELLANEOUS2CALLBACKSSIZE ;
 +
 +        /* Call win32k */
 +        retValue = NtGdiDdGetDriverInfo(hDD, (PDD_GETDRIVERINFODATA)&pDrvInfoData);
 +
 +        pData->dwActualSize = DDMISCELLANEOUS2CALLBACKSSIZE;
 +
 +        pUserMisc->dwFlags = pMisc.dwFlags;
 +
 +        /* This functions are not documneted in MSDN for this struct, here is directx/reactx alpha blend */
 +        if ( pMisc.Reserved )
 +        {
 +            pUserMisc->Reserved = (LPVOID) DdAlphaBlt;
 +        }
 +
 +        if ( pMisc.CreateSurfaceEx )
 +        {
 +            pUserMisc->CreateSurfaceEx = (LPDDHAL_CREATESURFACEEX) DdCreateSurfaceEx;
 +        }
 +
 +        if ( pMisc.GetDriverState )
 +        {
 +            pUserMisc->GetDriverState = (LPDDHAL_GETDRIVERSTATE) NtGdiDdGetDriverState;
 +        }
 +
 +        /* NOTE : pUserMisc->DestroyDDLocal is outdated and are not beign tuch */
 +
 +        /* Windows XP never repot back the true return value,
 +         *  it only report back if we have a driver or not
 +         *  ReactOS keep this behoir to be compatible with
 +         *  Windows XP
 +         */
 +        pData->ddRVal = retValue;
 +    }
 +
 +    /* NT Callbacks check and setup for DirectX/ ReactX */
 +    else if (IsEqualGUID(&pData->guidInfo, &GUID_NTCallbacks))
 +    {
 +        /* MS does not have DHAL_* version of this callbacks
 +         * so we are force using PDD_* callbacks here
 +         */
 +        DD_NTCALLBACKS  pNtKernel;
 +        PDD_NTCALLBACKS pUserNtKernel = (PDD_NTCALLBACKS)pData->lpvData;
 +
 +        /* Clear internal out buffer and set it up*/
 +        RtlZeroMemory(&pNtKernel, sizeof(DD_NTCALLBACKS));
 +        pNtKernel.dwSize = sizeof(DD_NTCALLBACKS);
 +
 +        /* set up internal buffer */
 +        pDrvInfoData.lpvData = (PVOID)&pNtKernel;
 +        pDrvInfoData.dwExpectedSize = sizeof(DD_NTCALLBACKS) ;
 +
 +        /* Call win32k */
 +        retValue = NtGdiDdGetDriverInfo(hDD, (PDD_GETDRIVERINFODATA)&pDrvInfoData);
 +
 +        pData->dwActualSize = sizeof(DD_NTCALLBACKS);
 +
 +        pUserNtKernel->dwSize = sizeof(DD_NTCALLBACKS);
 +        pUserNtKernel->dwFlags = pNtKernel.dwFlags;
 +        pUserNtKernel->FreeDriverMemory = 0;
 +
 +        if (pNtKernel.SetExclusiveMode)
 +        {
 +            pUserNtKernel->SetExclusiveMode = (PDD_SETEXCLUSIVEMODE) DdSetExclusiveMode;
 +        }
 +
 +        if (pNtKernel.FlipToGDISurface)
 +        {
 +            pUserNtKernel->FlipToGDISurface = (PDD_FLIPTOGDISURFACE) DdFlipToGDISurface;
 +        }
 +
 +        /* Windows XP never repot back the true return value,
 +         *  it only report back if we have a driver or not
 +         *  ReactOS keep this behoir to be compatible with
 +         *  Windows XP
 +         */
 +        pData->ddRVal = retValue;
 +    }
 +
 +    /* D3D Callbacks version 2 check and setup for DirectX/ ReactX */
 +    else if (IsEqualGUID(&pData->guidInfo, &GUID_D3DCallbacks2))
 +    {
 +        // FIXME GUID_D3DCallbacks2
 +    }
 +
 +    /* D3D Callbacks version 3 check and setup for DirectX/ ReactX */
 +    else if (IsEqualGUID(&pData->guidInfo, &GUID_D3DCallbacks3))
 +    {
 +        // FIXME GUID_D3DCallbacks3
 +    }
 +
 +    /* D3DParseUnknownCommand Callbacks check and setup for DirectX/ ReactX */
 +    else if (IsEqualGUID(&pData->guidInfo, &GUID_D3DParseUnknownCommandCallback))
 +    {
 +        // FIXME GUID_D3DParseUnknownCommandCallback
 +    }
 +
 +    /* MotionComp Callbacks check and setup for DirectX/ ReactX */
 +    else if (IsEqualGUID(&pData->guidInfo, &GUID_MotionCompCallbacks))
 +    {
 +        // FIXME GUID_MotionCompCallbacks
 +    }
 +
 +    /* FIXME VPE2 Callbacks check and setup for DirectX/ ReactX */
 +    //else if (IsEqualGUID(&pData->guidInfo, &GUID_VPE2Callbacks))
 +    //{
 +    // FIXME GUID_VPE2Callbacks
 +    //}
 +    else
 +    {
 +        /* set up internal buffer */
 +        pDrvInfoData.dwExpectedSize = pData->dwExpectedSize;
 +        pDrvInfoData.lpvData = pData->lpvData;
 +
 +        /* We do not cover all callbacks for user mode, they are only cover by kmode */
 +        retValue = NtGdiDdGetDriverInfo(hDD, (PDD_GETDRIVERINFODATA)&pDrvInfoData);
 +
 +        /* Setup return data */
 +        pData->dwActualSize = pDrvInfoData.dwActualSize;
 +        pData->lpvData = pDrvInfoData.lpvData;
 +        /* Windows XP never repot back the true return value,
 +         *  it only report back if we have a driver or not
 +         *  ReactOS keep this behoir to be compatible with
 +         *  Windows XP
 +         */
 +        pData->ddRVal = retValue;
 +    }
 +
 +    return retValue;
 +}
 +
 +
 +/*
 + * @implemented
 + *
 + * D3dContextCreate
 + */
 +BOOL
 +WINAPI
 +D3dContextCreate(LPD3DHAL_CONTEXTCREATEDATA pdcci)
 +{
 +    HANDLE hSurfZ = NULL;
 +
 +    if (pdcci->lpDDSZLcl)
 +    {
 +        hSurfZ = (HANDLE)pdcci->lpDDSZLcl->hDDSurface;
 +    }
 +
 +    return  NtGdiD3dContextCreate(GetDdHandle(pdcci->lpDDLcl->hDD),
 +                                  (HANDLE)pdcci->lpDDSLcl->hDDSurface,
 +                                  hSurfZ,
 +                                  (D3DNTHAL_CONTEXTCREATEI *)pdcci);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdCanCreateD3DBuffer
 + */
 +DWORD
 +WINAPI
 +DdCanCreateD3DBuffer(LPDDHAL_CANCREATESURFACEDATA CanCreateD3DBuffer)
 +{
 +    /*
 +     * Note : This functions are basic same, in win32k
 +     * NtGdiDdCanCreateD3DBuffer and  NtGdiDdCanCreateSurface are mergs
 +     * toghter in win32k at end and retrurn same data, it is still sepreated
 +     * at user mode but in kmode it is not.
 +     */
 +
 +    /* Call win32k */
 +    return NtGdiDdCanCreateD3DBuffer(GetDdHandle(CanCreateD3DBuffer->lpDD->hDD),
 +                                     (PDD_CANCREATESURFACEDATA)CanCreateD3DBuffer);
 +}
 +
 +
 +/*
 + * @implemented
 + *
 + * DdCreateD3DBuffer
 + */
 +DWORD
 +WINAPI
 +DdCreateD3DBuffer(LPDDHAL_CREATESURFACEDATA pCreateSurface)
 +{
 +    HANDLE puhSurface = 0;
 +    DDRAWI_DDRAWSURFACE_GBL *pSurfGBL;
 +    DDRAWI_DDRAWSURFACE_LCL *pSurfLcl;
 +    DD_SURFACE_GLOBAL puSurfaceGlobalData;
 +    DD_SURFACE_MORE puSurfaceMoreData;
 +    DD_SURFACE_LOCAL puSurfaceLocalData;
 +    DWORD retValue;
 +
 +    /* Zero all local memory pointer */
 +    RtlZeroMemory(&puSurfaceGlobalData, sizeof(DD_SURFACE_GLOBAL) );
 +    RtlZeroMemory(&puSurfaceMoreData, sizeof(DD_SURFACE_MORE) ) ;
 +    RtlZeroMemory(&puSurfaceLocalData, sizeof(DD_SURFACE_LOCAL) );
 +
 +    pCreateSurface->dwSCnt = 1;
 +    pSurfLcl = pCreateSurface->lplpSList[0];
 +    pSurfGBL = pSurfLcl->lpGbl;
 +
 +    /* Convert DDRAWI_DDRAWSURFACE_GBL to DD_SURFACE_GLOBAL */
 +    puSurfaceGlobalData.wWidth = pSurfGBL->wWidth;
 +    puSurfaceGlobalData.wHeight = pSurfGBL->wHeight;
 +    puSurfaceGlobalData.dwLinearSize = pSurfGBL->dwLinearSize;
 +    puSurfaceGlobalData.fpVidMem = pSurfGBL->fpVidMem;
 +    puSurfaceGlobalData.dwBlockSizeX = pSurfGBL->dwBlockSizeX;
 +    puSurfaceGlobalData.dwBlockSizeY = pSurfGBL->dwBlockSizeY;
 +
 +    /* Convert DDRAWI_DDRAWSURFACE_MORE to DD_SURFACE_MORE */
 +    puSurfaceMoreData.dwSurfaceHandle = pSurfLcl->lpSurfMore->dwSurfaceHandle;
 +    puSurfaceMoreData.ddsCapsEx.dwCaps2 = pSurfLcl->lpSurfMore->ddsCapsEx.dwCaps2;
 +    puSurfaceMoreData.ddsCapsEx.dwCaps3 = pSurfLcl->lpSurfMore->ddsCapsEx.dwCaps3;
 +    puSurfaceMoreData.ddsCapsEx.dwCaps4 = pSurfLcl->lpSurfMore->ddsCapsEx.dwCaps4;
 +
 +    /* Convert DDRAWI_DDRAWSURFACE_LCL to DD_SURFACE_LOCAL */
 +    puSurfaceLocalData.dwFlags = pSurfLcl->dwFlags;
 +    puSurfaceLocalData.ddsCaps.dwCaps = pSurfLcl->ddsCaps.dwCaps;
 +
 +    /* Call win32k */
 +    retValue = NtGdiDdCreateD3DBuffer( GetDdHandle(pCreateSurface->lpDD->hDD),
 +                                       (HANDLE*)&pSurfLcl->hDDSurface,
 +                                       pCreateSurface->lpDDSurfaceDesc,
 +                                       &puSurfaceGlobalData,
 +                                       &puSurfaceLocalData,
 +                                       &puSurfaceMoreData,
 +                                       (DD_CREATESURFACEDATA *) pCreateSurface,
 +                                       &puhSurface);
 +
 +    /* Setup surface handle if we got one back  */
 +    if ( puhSurface != NULL )
 +    {
 +        pCreateSurface->lplpSList[0]->hDDSurface = (ULONG_PTR)puhSurface;
 +    }
 +
 +    /* Convert DD_SURFACE_GLOBAL to DDRAWI_DDRAWSURFACE_GBL */
 +    pSurfGBL->dwLinearSize = puSurfaceGlobalData.dwLinearSize;
 +    pSurfGBL->fpVidMem = puSurfaceGlobalData.fpVidMem;
 +    pSurfGBL->dwBlockSizeX = puSurfaceGlobalData.dwBlockSizeX;
 +    pSurfGBL->dwBlockSizeY = puSurfaceGlobalData.dwBlockSizeY;
 +
 +    return retValue;
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdDestroyD3DBuffer
 + */
 +DWORD
 +WINAPI
 +DdDestroyD3DBuffer(LPDDHAL_DESTROYSURFACEDATA pDestroySurface)
 +{
 +    DWORD retValue = 0;
 +    if ( pDestroySurface->lpDDSurface->hDDSurface)
 +    {
 +        /* Call win32k */
 +        retValue = NtGdiDdDestroyD3DBuffer((HANDLE)pDestroySurface->lpDDSurface->hDDSurface);
 +    }
 +
 +    return retValue;
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdLockD3D
 + */
 +DWORD
 +WINAPI
 +DdLockD3D(LPDDHAL_LOCKDATA Lock)
 +{
 +
 +    /* Call win32k */
 +    return NtGdiDdLockD3D((HANDLE)Lock->lpDDSurface->hDDSurface, (PDD_LOCKDATA)Lock);
 +}
 +
 +/*
 + * @implemented
 + *
 + * DdUnlockD3D
 + */
 +DWORD
 +WINAPI
 +DdUnlockD3D(LPDDHAL_UNLOCKDATA Unlock)
 +{
 +    /* Call win32k */
 +    return NtGdiDdUnlock((HANDLE)Unlock->lpDDSurface->hDDSurface,
 +                         (PDD_UNLOCKDATA)Unlock);
 +}
 +
 +
 +/* PRIVATE FUNCTIONS *********************************************************/
 +
 +BOOL
 +WINAPI
 +bDDCreateSurface(LPDDRAWI_DDRAWSURFACE_LCL pSurface,
 +                 BOOL bComplete)
 +{
 +    DD_SURFACE_LOCAL SurfaceLocal;
 +    DD_SURFACE_GLOBAL SurfaceGlobal;
 +    DD_SURFACE_MORE SurfaceMore;
 +
 +    /* Zero struct */
 +    RtlZeroMemory(&SurfaceLocal, sizeof(DD_SURFACE_LOCAL));
 +    RtlZeroMemory(&SurfaceGlobal, sizeof(DD_SURFACE_GLOBAL));
 +    RtlZeroMemory(&SurfaceMore, sizeof(DD_SURFACE_MORE));
 +
 +    /* Set up SurfaceLocal struct */
 +    SurfaceLocal.ddsCaps.dwCaps = pSurface->ddsCaps.dwCaps;
 +    SurfaceLocal.dwFlags = pSurface->dwFlags;
 +
 +    /* Set up SurfaceMore struct */
 +    RtlMoveMemory(&SurfaceMore.ddsCapsEx,
 +                  &pSurface->ddckCKDestBlt,
 +                  sizeof(DDSCAPSEX));
 +    SurfaceMore.dwSurfaceHandle = (DWORD)pSurface->dbnOverlayNode.object_int->lpVtbl;
 +
 +    /* Set up SurfaceGlobal struct */
 +    SurfaceGlobal.fpVidMem = pSurface->lpGbl->fpVidMem;
 +    SurfaceGlobal.dwLinearSize = pSurface->lpGbl->dwLinearSize;
 +    SurfaceGlobal.wHeight = pSurface->lpGbl->wHeight;
 +    SurfaceGlobal.wWidth = pSurface->lpGbl->wWidth;
 +
 +    /* Check if we have a pixel format */
 +    if (pSurface->dwFlags & DDSD_PIXELFORMAT)
 +    {
 +        /* Use global one */
 +        SurfaceGlobal.ddpfSurface = pSurface->lpGbl->lpDD->vmiData.ddpfDisplay;
 +        SurfaceGlobal.ddpfSurface.dwSize = sizeof(DDPIXELFORMAT);
 +    }
 +    else
 +    {
 +        /* Use local one */
 +        SurfaceGlobal.ddpfSurface = pSurface->lpGbl->lpDD->vmiData.ddpfDisplay;
 +    }
 +
 +    /* Create the object */
 +    pSurface->hDDSurface = (DWORD)NtGdiDdCreateSurfaceObject(GetDdHandle(pSurface->lpGbl->lpDD->hDD),
 +                           (HANDLE)pSurface->hDDSurface,
 +                           &SurfaceLocal,
 +                           &SurfaceMore,
 +                           &SurfaceGlobal,
 +                           bComplete);
 +
 +    /* Return status */
 +    if (pSurface->hDDSurface) return TRUE;
 +    return FALSE;
 +}
 +
 +/* PUBLIC FUNCTIONS **********************************************************/
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 1
 + */
 +BOOL
 +WINAPI
 +DdCreateDirectDrawObject(LPDDRAWI_DIRECTDRAW_GBL pDirectDrawGlobal,
 +                         HDC hdc)
 +{
 +    BOOL Return = FALSE;
 +
 +    /* Check if the global hDC (hdc == 0) is being used */
 +    if (!hdc)
 +    {
 +        /* We'll only allow this if the global object doesn't exist yet */
 +        if (!ghDirectDraw)
 +        {
 +            /* Create the DC */
 +            if ((hdc = CreateDCW(L"Display", NULL, NULL, NULL)))
 +            {
 +                /* Create the DDraw Object */
 +                ghDirectDraw = NtGdiDdCreateDirectDrawObject(hdc);
 +
 +                /* Delete our DC */
 +                DeleteDC(hdc);
 +            }
 +        }
 +
 +        /* If we created the object, or had one ...*/
 +        if (ghDirectDraw)
 +        {
 +            /* Increase count and set success */
 +            gcDirectDraw++;
 +            Return = TRUE;
 +        }
 +
 +        /* Zero the handle */
 +        pDirectDrawGlobal->hDD = 0;
 +    }
 +    else
 +    {
 +        /* Using the per-process object, so create it */
 +        pDirectDrawGlobal->hDD = (ULONG_PTR)NtGdiDdCreateDirectDrawObject(hdc);
 +
 +        /* Set the return value */
 +        Return = pDirectDrawGlobal->hDD ? TRUE : FALSE;
 +    }
 +
 +    /* Return to caller */
 +    return Return;
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 2
 + */
 +BOOL
 +WINAPI
 +DdQueryDirectDrawObject(LPDDRAWI_DIRECTDRAW_GBL pDirectDrawGlobal,
 +                        LPDDHALINFO pHalInfo,
 +                        LPDDHAL_DDCALLBACKS pDDCallbacks,
 +                        LPDDHAL_DDSURFACECALLBACKS pDDSurfaceCallbacks,
 +                        LPDDHAL_DDPALETTECALLBACKS pDDPaletteCallbacks,
 +                        LPD3DHAL_CALLBACKS pD3dCallbacks,
 +                        LPD3DHAL_GLOBALDRIVERDATA pD3dDriverData,
 +                        LPDDHAL_DDEXEBUFCALLBACKS pD3dBufferCallbacks,
 +                        LPDDSURFACEDESC pD3dTextureFormats,
 +                        LPDWORD pdwFourCC,
 +                        LPVIDMEM pvmList)
 +{
 +    PVIDEOMEMORY VidMemList = NULL;
 +    DD_HALINFO HalInfo;
 +    D3DNTHAL_CALLBACKS D3dCallbacks;
 +    D3DNTHAL_GLOBALDRIVERDATA D3dDriverData;
 +    DD_D3DBUFCALLBACKS D3dBufferCallbacks;
 +    DWORD CallbackFlags[3];
 +    DWORD dwNumHeaps=0, FourCCs=0;
 +    DWORD Flags;
 +    BOOL retVal = TRUE;
 +
 +    /* Clear the structures */
 +    RtlZeroMemory(&HalInfo, sizeof(DD_HALINFO));
 +    RtlZeroMemory(&D3dCallbacks, sizeof(D3DNTHAL_CALLBACKS));
 +    RtlZeroMemory(&D3dDriverData, sizeof(D3DNTHAL_GLOBALDRIVERDATA));
 +    RtlZeroMemory(&D3dBufferCallbacks, sizeof(DD_D3DBUFCALLBACKS));
 +    RtlZeroMemory(CallbackFlags, sizeof(DWORD)*3);
 +
 +    /* Note : XP always alloc 24*sizeof(VIDEOMEMORY) of pvmlist so we change it to it */
 +    if ( (pvmList != NULL) &&
 +            (pHalInfo->vmiData.dwNumHeaps != 0) )
 +    {
 +        VidMemList = (PVIDEOMEMORY) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (sizeof(VIDEOMEMORY) * 24 ) * pHalInfo->vmiData.dwNumHeaps);
 +    }
 +
 +
 +    /* Do the query */
 +    if (!NtGdiDdQueryDirectDrawObject(GetDdHandle(pDirectDrawGlobal->hDD),
 +                                      &HalInfo,
 +                                      CallbackFlags,
 +                                      &D3dCallbacks,
 +                                      &D3dDriverData,
 +                                      &D3dBufferCallbacks,
 +                                      pD3dTextureFormats,
 +                                      &dwNumHeaps,
 +                                      VidMemList,
 +                                      &FourCCs,
 +                                      pdwFourCC))
 +    {
 +        /* We failed, free the memory and return */
 +        retVal = FALSE;
 +        goto cleanup;
 +    }
 +
 +    /* Clear the incoming pointer */
 +    RtlZeroMemory(pHalInfo, sizeof(DDHALINFO));
 +
 +    /* Convert all the data */
 +    pHalInfo->dwSize = sizeof(DDHALINFO);
 +    pHalInfo->lpDDCallbacks = pDDCallbacks;
 +    pHalInfo->lpDDSurfaceCallbacks = pDDSurfaceCallbacks;
 +    pHalInfo->lpDDPaletteCallbacks = pDDPaletteCallbacks;
 +
 +    /* Check for NT5+ D3D Data */
 +    if ( (D3dCallbacks.dwSize != 0) &&
 +            (D3dDriverData.dwSize != 0) )
 +    {
 +        /* Write these down */
 +        pHalInfo->lpD3DGlobalDriverData = (ULONG_PTR)pD3dDriverData;
 +        pHalInfo->lpD3DHALCallbacks = (ULONG_PTR)pD3dCallbacks;
 +
 +        /* Check for Buffer Callbacks */
 +        if (D3dBufferCallbacks.dwSize)
 +        {
 +            /* Write this one too */
 +            pHalInfo->lpDDExeBufCallbacks = pD3dBufferCallbacks;
 +        }
 +    }
 +
 +    /* Continue converting the rest */
 +    pHalInfo->vmiData.dwFlags = HalInfo.vmiData.dwFlags;
 +    pHalInfo->vmiData.dwDisplayWidth = HalInfo.vmiData.dwDisplayWidth;
 +    pHalInfo->vmiData.dwDisplayHeight = HalInfo.vmiData.dwDisplayHeight;
 +    pHalInfo->vmiData.lDisplayPitch = HalInfo.vmiData.lDisplayPitch;
 +    pHalInfo->vmiData.fpPrimary = 0;
 +
 +    RtlCopyMemory( &pHalInfo->vmiData.ddpfDisplay,
 +                   &HalInfo.vmiData.ddpfDisplay,
 +                   sizeof(DDPIXELFORMAT));
 +
 +    pHalInfo->vmiData.dwOffscreenAlign = HalInfo.vmiData.dwOffscreenAlign;
 +    pHalInfo->vmiData.dwOverlayAlign = HalInfo.vmiData.dwOverlayAlign;
 +    pHalInfo->vmiData.dwTextureAlign = HalInfo.vmiData.dwTextureAlign;
 +    pHalInfo->vmiData.dwZBufferAlign = HalInfo.vmiData.dwZBufferAlign;
 +    pHalInfo->vmiData.dwAlphaAlign = HalInfo.vmiData.dwAlphaAlign;
 +
 +    pHalInfo->vmiData.dwNumHeaps = dwNumHeaps;
 +    pHalInfo->vmiData.pvmList = pvmList;
 +
 +    RtlCopyMemory( &pHalInfo->ddCaps,
 +                   &HalInfo.ddCaps,
 +                   sizeof(DDCORECAPS ));
 +
 +    pHalInfo->ddCaps.dwNumFourCCCodes = FourCCs;
 +    pHalInfo->lpdwFourCC = pdwFourCC;
 +
 +    /* always force rope 0x1000 for hal it mean only source copy is supported */
 +    pHalInfo->ddCaps.dwRops[6] = 0x1000;
 +
 +    /* Set the HAL flags what ReactX got from the driver
 +     * Windows XP force setting DDHALINFO_GETDRIVERINFOSET if the driver does not set it
 +     * and ReactX doing same to keep compatible with drivers, but the driver are
 +     * force support DdGetDriverInfo acoriding MSDN but it seam some driver do not set
 +     * this flag even it is being supported. that is mean. It is small hack to keep
 +     * bad driver working, that trust this is always being setting by it self at end
 +     */
 +    pHalInfo->dwFlags = (HalInfo.dwFlags & ~DDHALINFO_GETDRIVERINFOSET) | DDHALINFO_GETDRIVERINFOSET;
 +    pHalInfo->GetDriverInfo = (LPDDHAL_GETDRIVERINFO) DdGetDriverInfo;
 +
 +    /* Now check if we got any DD callbacks */
 +    if (pDDCallbacks)
 +    {
 +        /* Zero the structure */
 +        RtlZeroMemory(pDDCallbacks, sizeof(DDHAL_DDCALLBACKS));
 +        pDDCallbacks->dwSize = sizeof(DDHAL_DDCALLBACKS);
 +
 +        /* Set the flags for this structure
 +         * Windows XP force setting DDHAL_CB32_CREATESURFACE if the driver does not set it
 +         * and ReactX doing same to keep compatible with drivers, but the driver are
 +         * force support pDDCallbacks acoriding MSDN but it seam some driver do not set
 +         * this flag even it is being supported. that is mean. It is small hack to keep
 +         * bad driver working, that trust this is always being setting by it self at end
 +        */
 +        Flags = (CallbackFlags[0] & ~DDHAL_CB32_CREATESURFACE) | DDHAL_CB32_CREATESURFACE;
 +        pDDCallbacks->dwFlags = Flags;
 +
 +        /* Write the always-on functions */
 +        pDDCallbacks->CreateSurface = DdCreateSurface;
 +
 +        /* Now write the pointers, if applicable */
 +        if (Flags & DDHAL_CB32_WAITFORVERTICALBLANK)
 +        {
 +            pDDCallbacks->WaitForVerticalBlank = DdWaitForVerticalBlank;
 +        }
 +        if (Flags & DDHAL_CB32_CANCREATESURFACE)
 +        {
 +            pDDCallbacks->CanCreateSurface = DdCanCreateSurface;
 +        }
 +        if (Flags & DDHAL_CB32_GETSCANLINE)
 +        {
 +            pDDCallbacks->GetScanLine = DdGetScanLine;
 +        }
 +    }
 +
 +    /* Check for DD Surface Callbacks */
 +    if (pDDSurfaceCallbacks)
 +    {
 +        /* Zero the structures */
 +        RtlZeroMemory(pDDSurfaceCallbacks, sizeof(DDHAL_DDSURFACECALLBACKS));
 +        pDDSurfaceCallbacks->dwSize  = sizeof(DDHAL_DDSURFACECALLBACKS);
 +
 +        /* Set the flags for this structure
 +         * Windows XP force setting DDHAL_SURFCB32_LOCK, DDHAL_SURFCB32_UNLOCK,
 +         * DDHAL_SURFCB32_SETCOLORKEY, DDHAL_SURFCB32_DESTROYSURFACE if the driver
 +         * does not set it and ReactX doing same to keep compatible with drivers,
 +         * but the driver are force support pDDSurfaceCallbacks acoriding MSDN but it seam
 +         * some driver do not set this flag even it is being supported. that is mean.
 +         * It is small hack to keep bad driver working, that trust this is always being
 +         * setting by it self at end
 +         */
 +
 +        Flags = (CallbackFlags[1] & ~(DDHAL_SURFCB32_LOCK | DDHAL_SURFCB32_UNLOCK |
 +                                      DDHAL_SURFCB32_SETCOLORKEY | DDHAL_SURFCB32_DESTROYSURFACE)) |
 +                (DDHAL_SURFCB32_LOCK | DDHAL_SURFCB32_UNLOCK |
 +                 DDHAL_SURFCB32_SETCOLORKEY | DDHAL_SURFCB32_DESTROYSURFACE);
 +
 +        pDDSurfaceCallbacks->dwFlags = Flags;
 +
 +        /* Write the always-on functions */
 +        pDDSurfaceCallbacks->Lock = DdLock;
 +        pDDSurfaceCallbacks->Unlock = DdUnlock;
 +        pDDSurfaceCallbacks->SetColorKey = DdSetColorKey;
 +        pDDSurfaceCallbacks->DestroySurface = DdDestroySurface;
 +
 +        /* Write the optional ones */
 +        if (Flags & DDHAL_SURFCB32_FLIP)
 +        {
 +            pDDSurfaceCallbacks->Flip = DdFlip;
 +        }
 +        if (Flags & DDHAL_SURFCB32_BLT)
 +        {
 +            pDDSurfaceCallbacks->Blt = DdBlt;
 +        }
 +        if (Flags & DDHAL_SURFCB32_GETBLTSTATUS)
 +        {
 +            pDDSurfaceCallbacks->GetBltStatus = DdGetBltStatus;
 +        }
 +        if (Flags & DDHAL_SURFCB32_GETFLIPSTATUS)
 +        {
 +            pDDSurfaceCallbacks->GetFlipStatus = DdGetFlipStatus;
 +        }
 +        if (Flags & DDHAL_SURFCB32_UPDATEOVERLAY)
 +        {
 +            pDDSurfaceCallbacks->UpdateOverlay = DdUpdateOverlay;
 +        }
 +        if (Flags & DDHAL_SURFCB32_SETOVERLAYPOSITION)
 +        {
 +            pDDSurfaceCallbacks->SetOverlayPosition = DdSetOverlayPosition;
 +        }
 +        if (Flags & DDHAL_SURFCB32_ADDATTACHEDSURFACE)
 +        {
 +            pDDSurfaceCallbacks->AddAttachedSurface = DdAddAttachedSurface;
 +        }
 +    }
 +
 +    /* Check for DD Palette Callbacks, This interface are dead for user mode,
 +     * only what it can support are being report back.
 +     */
 +    if (pDDPaletteCallbacks)
 +    {
 +        /* Zero the struct */
 +        RtlZeroMemory(pDDPaletteCallbacks, sizeof(DDHAL_DDPALETTECALLBACKS));
 +
 +        /* Write the header */
 +        pDDPaletteCallbacks->dwSize  = sizeof(DDHAL_DDPALETTECALLBACKS);
 +        pDDPaletteCallbacks->dwFlags = CallbackFlags[2];
 +    }
 +
 +    if (pD3dCallbacks)
 +    {
 +        /* Zero the struct */
 +        RtlZeroMemory(pD3dCallbacks, sizeof(DDHAL_DDEXEBUFCALLBACKS));
 +
 +        /* Check if we have one */
 +        if (D3dCallbacks.dwSize)
 +        {
 +            /* Write the header */
 +            pD3dCallbacks->dwSize = sizeof(DDHAL_DDEXEBUFCALLBACKS);
 +
 +            /* Now check for each callback */
 +            if (D3dCallbacks.ContextCreate)
 +            {
 +                pD3dCallbacks->ContextCreate = (LPD3DHAL_CONTEXTCREATECB) D3dContextCreate;
 +            }
 +            if (D3dCallbacks.ContextDestroy)
 +            {
 +                pD3dCallbacks->ContextDestroy = (LPD3DHAL_CONTEXTDESTROYCB) NtGdiD3dContextDestroy;
 +            }
 +            if (D3dCallbacks.ContextDestroyAll)
 +            {
 +                pD3dCallbacks->ContextDestroyAll = (LPD3DHAL_CONTEXTDESTROYALLCB) NtGdiD3dContextDestroyAll;
 +            }
 +        }
 +    }
 +
 +    /* Check for D3D Driver Data */
 +    if (pD3dDriverData)
 +    {
 +        /* Copy the struct */
 +        RtlMoveMemory(pD3dDriverData, &D3dDriverData, sizeof(D3DHAL_GLOBALDRIVERDATA));
 +
 +        /* Write the pointer to the texture formats */
 +        pD3dDriverData->lpTextureFormats = pD3dTextureFormats;
 +    }
 +
 +    /* Check for D3D Buffer Callbacks */
 +    if (pD3dBufferCallbacks)
 +    {
 +        /* Zero the struct */
 +        RtlZeroMemory(pD3dBufferCallbacks, sizeof(DDHAL_DDEXEBUFCALLBACKS));
 +
 +        if ( D3dBufferCallbacks.dwSize)
 +        {
 +            pD3dBufferCallbacks->dwSize = D3dBufferCallbacks.dwSize;
 +
 +            pD3dBufferCallbacks->dwFlags = D3dBufferCallbacks.dwFlags;
 +            if ( D3dBufferCallbacks.CanCreateD3DBuffer)
 +            {
 +                pD3dBufferCallbacks->CanCreateExecuteBuffer = (LPDDHALEXEBUFCB_CANCREATEEXEBUF)DdCanCreateD3DBuffer;
 +            }
 +
 +            if (D3dBufferCallbacks.CreateD3DBuffer)
 +            {
 +                pD3dBufferCallbacks->CreateExecuteBuffer = (LPDDHALEXEBUFCB_CREATEEXEBUF) DdCreateD3DBuffer;
 +            }
 +
 +            if ( D3dBufferCallbacks.DestroyD3DBuffer )
 +            {
 +                pD3dBufferCallbacks->DestroyExecuteBuffer = (LPDDHALEXEBUFCB_DESTROYEXEBUF) DdDestroyD3DBuffer;
 +            }
 +
 +            if ( D3dBufferCallbacks.LockD3DBuffer )
 +            {
 +                pD3dBufferCallbacks->LockExecuteBuffer = (LPDDHALEXEBUFCB_LOCKEXEBUF) DdLockD3D;
 +            }
 +
 +            if ( D3dBufferCallbacks.UnlockD3DBuffer )
 +            {
 +                pD3dBufferCallbacks->UnlockExecuteBuffer = (LPDDHALEXEBUFCB_UNLOCKEXEBUF) DdUnlockD3D;
 +            }
 +
 +        }
 +    }
 +
 +    /* FIXME VidMemList */
 +
 +cleanup:
 +    if (VidMemList)
 +    {
 +        HeapFree(GetProcessHeap(), 0, VidMemList);
 +    }
 +
 +    return retVal;
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 3
 + */
 +BOOL
 +WINAPI
 +DdDeleteDirectDrawObject(LPDDRAWI_DIRECTDRAW_GBL pDirectDrawGlobal)
 +{
 +    BOOL Return = FALSE;
 +
 +    /* If this is the global object */
 +    if(pDirectDrawGlobal->hDD)
 +    {
 +        /* Free it */
 +        Return = NtGdiDdDeleteDirectDrawObject((HANDLE)pDirectDrawGlobal->hDD);
-             if (Return == TRUE)
++        if (Return)
 +        {
 +            pDirectDrawGlobal->hDD = 0;
 +        }
 +    }
 +    else if (ghDirectDraw)
 +    {
 +        /* Always success here */
 +        Return = TRUE;
 +
 +        /* Make sure this is the last instance */
 +        if (!(--gcDirectDraw))
 +        {
 +            /* Delete the object */
 +            Return = NtGdiDdDeleteDirectDrawObject(ghDirectDraw);
++            if (Return)
 +            {
 +                ghDirectDraw = 0;
 +            }
 +        }
 +    }
 +
 +    /* Return */
 +    return Return;
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 4
 + */
 +BOOL
 +WINAPI
 +DdCreateSurfaceObject( LPDDRAWI_DDRAWSURFACE_LCL pSurfaceLocal,
 +                       BOOL bPrimarySurface)
 +{
 +    return bDDCreateSurface(pSurfaceLocal, TRUE);
 +}
 +
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 5
 + */
 +BOOL
 +WINAPI
 +DdDeleteSurfaceObject(LPDDRAWI_DDRAWSURFACE_LCL pSurfaceLocal)
 +{
 +    BOOL Return = FALSE;
 +
 +    /* Make sure there is one */
 +    if (pSurfaceLocal->hDDSurface)
 +    {
 +        /* Delete it */
 +        Return = NtGdiDdDeleteSurfaceObject((HANDLE)pSurfaceLocal->hDDSurface);
 +        pSurfaceLocal->hDDSurface = 0;
 +    }
 +
 +    return Return;
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 6
 + */
 +BOOL
 +WINAPI
 +DdResetVisrgn(LPDDRAWI_DDRAWSURFACE_LCL pSurfaceLocal,
 +              HWND hWnd)
 +{
 +    /* Call win32k directly */
 +    return NtGdiDdResetVisrgn((HANDLE) pSurfaceLocal->hDDSurface, hWnd);
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 7
 + */
 +HDC
 +WINAPI
 +DdGetDC(LPDDRAWI_DDRAWSURFACE_LCL pSurfaceLocal,
 +        LPPALETTEENTRY pColorTable)
 +{
 +    /* Call win32k directly */
 +    return NtGdiDdGetDC(pColorTable, (HANDLE) pSurfaceLocal->hDDSurface);
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 8
 + */
 +BOOL
 +WINAPI
 +DdReleaseDC(LPDDRAWI_DDRAWSURFACE_LCL pSurfaceLocal)
 +{
 +    /* Call win32k directly */
 +    return NtGdiDdReleaseDC((HANDLE) pSurfaceLocal->hDDSurface);
 +}
 +
 +/*
 + * @unimplemented
 + * GDIEntry 9
 + */
 +HBITMAP
 +WINAPI
 +DdCreateDIBSection(HDC hdc,
 +                   CONST BITMAPINFO *pbmi,
 +                   UINT iUsage,
 +                   VOID **ppvBits,
 +                   HANDLE hSectionApp,
 +                   DWORD dwOffset)
 +{
 +    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
 +    return 0;
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 10
 + */
 +BOOL
 +WINAPI
 +DdReenableDirectDrawObject(LPDDRAWI_DIRECTDRAW_GBL pDirectDrawGlobal,
 +                           BOOL *pbNewMode)
 +{
 +    /* Call win32k directly */
 +    return NtGdiDdReenableDirectDrawObject(GetDdHandle(pDirectDrawGlobal->hDD),
 +                                           pbNewMode);
 +}
 +
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 11
 + */
 +BOOL
 +WINAPI
 +DdAttachSurface( LPDDRAWI_DDRAWSURFACE_LCL pSurfaceFrom,
 +                 LPDDRAWI_DDRAWSURFACE_LCL pSurfaceTo)
 +{
 +    /* Create Surface if it does not exits one */
 +    if (!pSurfaceFrom->hDDSurface)
 +    {
 +        if (!bDDCreateSurface(pSurfaceFrom, FALSE))
 +        {
 +            return FALSE;
 +        }
 +    }
 +
 +    /* Create Surface if it does not exits one */
 +    if (!pSurfaceTo->hDDSurface)
 +    {
 +        if (!bDDCreateSurface(pSurfaceTo, FALSE))
 +        {
 +            return FALSE;
 +        }
 +    }
 +
 +    /* Call win32k */
 +    return NtGdiDdAttachSurface((HANDLE)pSurfaceFrom->hDDSurface,
 +                                (HANDLE)pSurfaceTo->hDDSurface);
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 12
 + */
 +VOID
 +WINAPI
 +DdUnattachSurface(LPDDRAWI_DDRAWSURFACE_LCL pSurface,
 +                  LPDDRAWI_DDRAWSURFACE_LCL pSurfaceAttached)
 +{
 +    /* Call win32k */
 +    NtGdiDdUnattachSurface((HANDLE)pSurface->hDDSurface,
 +                           (HANDLE)pSurfaceAttached->hDDSurface);
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 13
 + */
 +ULONG
 +WINAPI
 +DdQueryDisplaySettingsUniqueness()
 +{
 +    return GdiSharedHandleTable->flDeviceUniq;
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 14
 + */
 +HANDLE
 +WINAPI
 +DdGetDxHandle(LPDDRAWI_DIRECTDRAW_LCL pDDraw,
 +              LPDDRAWI_DDRAWSURFACE_LCL pSurface,
 +              BOOL bRelease)
 +{
 +    HANDLE hDD = NULL;
 +    HANDLE hSurface = NULL;
 +
 +    /* Check if we already have a surface */
 +    if (!pSurface)
 +    {
 +        /* We don't have one, use the DirectDraw Object handle instead */
 +        hDD = GetDdHandle(pDDraw->lpGbl->hDD);
 +    }
 +    else
 +    {
 +        hSurface = (HANDLE)pSurface->hDDSurface;
 +    }
 +
 +    /* Call the API */
 +    return (HANDLE)NtGdiDdGetDxHandle(hDD, hSurface, bRelease);
 +}
 +
 +/*
 + * @implemented
 + *
 + * GDIEntry 15
 + */
 +BOOL
 +WINAPI
 +DdSetGammaRamp(LPDDRAWI_DIRECTDRAW_LCL pDDraw,
 +               HDC hdc,
 +               LPVOID lpGammaRamp)
 +{
 +    /* Call win32k directly */
 +    return NtGdiDdSetGammaRamp(GetDdHandle(pDDraw->lpGbl->hDD),
 +                               hdc,
 +                               lpGammaRamp);
 +}
 +
 +
 +
 +
 +
Simple merge
index 6d7ca2d,0000000..dbd8e22
mode 100644,000000..100644
--- /dev/null
@@@ -1,554 -1,0 +1,554 @@@
- #define FIX2LONG(x) ((x) >> 4)
 +/*
 + * PROJECT:         ReactOS win32 kernel mode subsystem
 + * LICENSE:         GPL - See COPYING in the top level directory
 + * FILE:            win32ss/gdi/ntgdi/xformobj.c
 + * PURPOSE:         XFORMOBJ API
 + * PROGRAMMER:      Timo Kreuzer
 + */
 +
 +/** Includes ******************************************************************/
 +
 +#include <win32k.h>
 +#define NDEBUG
 +#include <debug.h>
 +
 +C_ASSERT(sizeof(FIX) == sizeof(LONG));
++#define FIX2LONG(x) (((x) + 8) >> 4)
 +#define LONG2FIX(x) ((x) << 4)
 +
 +#define FLOATOBJ_Equal _FLOATOBJ_Equal
 +#define FLOATOBJ_GetLong _FLOATOBJ_GetLong
 +#define FLOATOBJ_GetFix _FLOATOBJ_GetFix
 +#define FLOATOBJ_IsLong _FLOATOBJ_IsLong
 +#define FLOATOBJ_Equal0 _FLOATOBJ_Equal0
 +#define FLOATOBJ_Equal1 _FLOATOBJ_Equal1
 +
 +/** Inline helper functions ***************************************************/
 +
 +/*
 + * Inline helper to calculate pfo1 * pfo2 + pfo3 * pfo4
 + */
 +FORCEINLINE
 +VOID
 +MulAdd(
 +    PFLOATOBJ pfoDest,
 +    PFLOATOBJ pfo1,
 +    PFLOATOBJ pfo2,
 +    PFLOATOBJ pfo3,
 +    PFLOATOBJ pfo4)
 +{
 +    FLOATOBJ foTmp;
 +
 +    *pfoDest = *pfo1;
 +    FLOATOBJ_Mul(pfoDest, pfo2);
 +    foTmp = *pfo3;
 +    FLOATOBJ_Mul(&foTmp, pfo4);
 +    FLOATOBJ_Add(pfoDest, &foTmp);
 +}
 +
 +/*
 + * Inline helper to calculate pfo1 * l2 + pfo3 * l4
 + */
 +FORCEINLINE
 +VOID
 +MulAddLong(
 +    PFLOATOBJ pfoDest,
 +    PFLOATOBJ pfo1,
 +    LONG l2,
 +    PFLOATOBJ pfo3,
 +    LONG l4)
 +{
 +    FLOATOBJ foTmp;
 +
 +    *pfoDest = *pfo1;
 +    FLOATOBJ_MulLong(pfoDest, l2);
 +    foTmp = *pfo3;
 +    FLOATOBJ_MulLong(&foTmp, l4);
 +    FLOATOBJ_Add(pfoDest, &foTmp);
 +}
 +
 +/*
 + * Inline helper to calculate pfo1 * pfo2 - pfo3 * pfo4
 + */
 +FORCEINLINE
 +VOID
 +MulSub(
 +    PFLOATOBJ pfoDest,
 +    PFLOATOBJ pfo1,
 +    PFLOATOBJ pfo2,
 +    PFLOATOBJ pfo3,
 +    PFLOATOBJ pfo4)
 +{
 +    FLOATOBJ foTmp;
 +
 +    *pfoDest = *pfo1;
 +    FLOATOBJ_Mul(pfoDest, pfo2);
 +    foTmp = *pfo3;
 +    FLOATOBJ_Mul(&foTmp, pfo4);
 +    FLOATOBJ_Sub(pfoDest, &foTmp);
 +}
 +
 +/*
 + * Inline helper to get the complexity hint from flAccel
 + */
 +FORCEINLINE
 +ULONG
 +HintFromAccel(ULONG flAccel)
 +{
 +    switch (flAccel & (XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION))
 +    {
 +        case (XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION):
 +            return GX_IDENTITY;
 +        case (XFORM_SCALE|XFORM_UNITY):
 +            return GX_OFFSET;
 +        case XFORM_SCALE:
 +            return GX_SCALE;
 +        default:
 +            return GX_GENERAL;
 +    }
 +}
 +
 +/** Internal functions ********************************************************/
 +
 +ULONG
 +NTAPI
 +XFORMOBJ_UpdateAccel(
 +    IN XFORMOBJ *pxo)
 +{
 +    PMATRIX pmx = XFORMOBJ_pmx(pxo);
 +
 +    /* Copy Dx and Dy to FIX format */
 +    pmx->fxDx = FLOATOBJ_GetFix(&pmx->efDx);
 +    pmx->fxDy = FLOATOBJ_GetFix(&pmx->efDy);
 +
 +    pmx->flAccel = 0;
 +
 +    if (FLOATOBJ_Equal0(&pmx->efDx) &&
 +        FLOATOBJ_Equal0(&pmx->efDy))
 +    {
 +        pmx->flAccel |= XFORM_NO_TRANSLATION;
 +    }
 +
 +    if (FLOATOBJ_Equal0(&pmx->efM12) &&
 +        FLOATOBJ_Equal0(&pmx->efM21))
 +    {
 +        pmx->flAccel |= XFORM_SCALE;
 +    }
 +
 +    if (FLOATOBJ_Equal1(&pmx->efM11) &&
 +        FLOATOBJ_Equal1(&pmx->efM22))
 +    {
 +        pmx->flAccel |= XFORM_UNITY;
 +    }
 +
 +    if (FLOATOBJ_IsLong(&pmx->efM11) && FLOATOBJ_IsLong(&pmx->efM12) &&
 +        FLOATOBJ_IsLong(&pmx->efM21) && FLOATOBJ_IsLong(&pmx->efM22))
 +    {
 +        pmx->flAccel |= XFORM_INTEGER;
 +    }
 +
 +    return HintFromAccel(pmx->flAccel);
 +}
 +
 +
 +ULONG
 +NTAPI
 +XFORMOBJ_iSetXform(
 +    OUT XFORMOBJ *pxo,
 +    IN const XFORML *pxform)
 +{
 +    PMATRIX pmx = XFORMOBJ_pmx(pxo);
 +
 +    /* Check parameters */
 +    if (!pxo || !pxform) return DDI_ERROR;
 +
 +    /* Check if the xform is valid */
 +    if ((pxform->eM11 == 0) || (pxform->eM22 == 0)) return DDI_ERROR;
 +
 +    /* Copy members */
 +    FLOATOBJ_SetFloat(&pmx->efM11, pxform->eM11);
 +    FLOATOBJ_SetFloat(&pmx->efM12, pxform->eM12);
 +    FLOATOBJ_SetFloat(&pmx->efM21, pxform->eM21);
 +    FLOATOBJ_SetFloat(&pmx->efM22, pxform->eM22);
 +    FLOATOBJ_SetFloat(&pmx->efDx, pxform->eDx);
 +    FLOATOBJ_SetFloat(&pmx->efDy, pxform->eDy);
 +
 +    /* Update accelerators and return complexity */
 +    return XFORMOBJ_UpdateAccel(pxo);
 +}
 +
 +
 +/*
 + * Multiplies pxo1 with pxo2 and stores the result in pxo.
 + * returns complexity hint
 + * | efM11 efM12 0 |
 + * | efM21 efM22 0 |
 + * | efDx  efDy  1 |
 + */
 +ULONG
 +NTAPI
 +XFORMOBJ_iCombine(
 +    IN XFORMOBJ *pxo,
 +    IN XFORMOBJ *pxo1,
 +    IN XFORMOBJ *pxo2)
 +{
 +    MATRIX mx;
 +    PMATRIX pmx, pmx1, pmx2;
 +
 +    /* Get the source matrices */
 +    pmx1 = XFORMOBJ_pmx(pxo1);
 +    pmx2 = XFORMOBJ_pmx(pxo2);
 +
 +    /* Do a 3 x 3 matrix multiplication with mx as destinantion */
 +    MulAdd(&mx.efM11, &pmx1->efM11, &pmx2->efM11, &pmx1->efM12, &pmx2->efM21);
 +    MulAdd(&mx.efM12, &pmx1->efM11, &pmx2->efM12, &pmx1->efM12, &pmx2->efM22);
 +    MulAdd(&mx.efM21, &pmx1->efM21, &pmx2->efM11, &pmx1->efM22, &pmx2->efM21);
 +    MulAdd(&mx.efM22, &pmx1->efM21, &pmx2->efM12, &pmx1->efM22, &pmx2->efM22);
 +    MulAdd(&mx.efDx, &pmx1->efDx, &pmx2->efM11, &pmx1->efDy, &pmx2->efM21);
 +    FLOATOBJ_Add(&mx.efDx, &pmx2->efDx);
 +    MulAdd(&mx.efDy, &pmx1->efDx, &pmx2->efM12, &pmx1->efDy, &pmx2->efM22);
 +    FLOATOBJ_Add(&mx.efDy, &pmx2->efDy);
 +
 +    /* Copy back */
 +    pmx = XFORMOBJ_pmx(pxo);
 +    *pmx = mx;
 +
 +    /* Update accelerators and return complexity */
 +    return XFORMOBJ_UpdateAccel(pxo);
 +}
 +
 +
 +ULONG
 +NTAPI
 +XFORMOBJ_iCombineXform(
 +    IN XFORMOBJ *pxo,
 +    IN XFORMOBJ *pxo1,
 +    IN XFORML *pxform,
 +    IN BOOL bLeftMultiply)
 +{
 +    MATRIX mx;
 +    XFORMOBJ xo2;
 +
 +    XFORMOBJ_vInit(&xo2, &mx);
 +    XFORMOBJ_iSetXform(&xo2, pxform);
 +
 +    if (bLeftMultiply)
 +    {
 +        return XFORMOBJ_iCombine(pxo, &xo2, pxo1);
 +    }
 +    else
 +    {
 +        return XFORMOBJ_iCombine(pxo, pxo1, &xo2);
 +    }
 +}
 +
 +/*
 + * A^-1 = adj(A) / det(AT)
 + * A^-1 = 1/(a*d - b*c) * (a22,-a12,a21,-a11)
 + */
 +ULONG
 +NTAPI
 +XFORMOBJ_iInverse(
 +    OUT XFORMOBJ *pxoDst,
 +    IN XFORMOBJ *pxoSrc)
 +{
 +    PMATRIX pmxDst, pmxSrc;
 +    FLOATOBJ foDet;
 +    XFORM xformSrc;
 +
 +    pmxDst = XFORMOBJ_pmx(pxoDst);
 +    pmxSrc = XFORMOBJ_pmx(pxoSrc);
 +
 +    XFORMOBJ_iGetXform(pxoSrc, (XFORML*)&xformSrc);
 +
 +    /* det = M11 * M22 - M12 * M21 */
 +    MulSub(&foDet, &pmxSrc->efM11, &pmxSrc->efM22, &pmxSrc->efM12, &pmxSrc->efM21);
 +
 +    if (FLOATOBJ_Equal0(&foDet))
 +    {
 +        /* Determinant is 0! */
 +        return DDI_ERROR;
 +    }
 +
 +    /* Calculate adj(A) / det(A) */
 +    pmxDst->efM11 = pmxSrc->efM22;
 +    FLOATOBJ_Div(&pmxDst->efM11, &foDet);
 +    pmxDst->efM22 = pmxSrc->efM11;
 +    FLOATOBJ_Div(&pmxDst->efM22, &foDet);
 +
 +    /* The other 2 are negative, negate foDet for that */
 +    FLOATOBJ_Neg(&foDet);
 +    pmxDst->efM12 = pmxSrc->efM12;
 +    FLOATOBJ_Div(&pmxDst->efM12, &foDet);
 +    pmxDst->efM21 = pmxSrc->efM21;
 +    FLOATOBJ_Div(&pmxDst->efM21, &foDet);
 +
 +    /* Calculate the inverted x shift: Dx' = -Dx * M11' - Dy * M21' */
 +    pmxDst->efDx = pmxSrc->efDx;
 +    FLOATOBJ_Neg(&pmxDst->efDx);
 +    MulSub(&pmxDst->efDx, &pmxDst->efDx, &pmxDst->efM11, &pmxSrc->efDy, &pmxDst->efM21);
 +
 +    /* Calculate the inverted y shift: Dy' = -Dy * M22' - Dx * M12' */
 +    pmxDst->efDy = pmxSrc->efDy;
 +    FLOATOBJ_Neg(&pmxDst->efDy);
 +    MulSub(&pmxDst->efDy, &pmxDst->efDy, &pmxDst->efM22, &pmxSrc->efDx, &pmxDst->efM12);
 +
 +    /* Update accelerators and return complexity */
 +    return XFORMOBJ_UpdateAccel(pxoDst);
 +}
 +
 +
 +BOOL
 +NTAPI
 +XFORMOBJ_bXformFixPoints(
 +    IN XFORMOBJ  *pxo,
 +    IN ULONG  cPoints,
 +    IN PPOINTL  pptIn,
 +    OUT PPOINTL  pptOut)
 +{
 +    PMATRIX pmx;
 +    INT i;
 +    FLOATOBJ fo1, fo2;
 +    FLONG flAccel;
 +
 +    pmx = XFORMOBJ_pmx(pxo);
 +    flAccel = pmx->flAccel;
 +
 +    if ((flAccel & (XFORM_SCALE|XFORM_UNITY)) == (XFORM_SCALE|XFORM_UNITY))
 +    {
 +        /* Identity transformation, nothing todo */
 +    }
 +    else if (flAccel & XFORM_INTEGER)
 +    {
 +        if (flAccel & XFORM_UNITY)
 +        {
 +            /* 1-scale integer transform */
 +            LONG lM12 = FLOATOBJ_GetLong(&pmx->efM12);
 +            LONG lM21 = FLOATOBJ_GetLong(&pmx->efM21);
 +
 +            i = cPoints - 1;
 +            do
 +            {
 +                LONG x = pptIn[i].x + pptIn[i].y * lM21;
 +                LONG y = pptIn[i].y + pptIn[i].x * lM12;
 +                pptOut[i].y = y;
 +                pptOut[i].x = x;
 +            }
 +            while (--i >= 0);
 +        }
 +        else if (flAccel & XFORM_SCALE)
 +        {
 +            /* Diagonal integer transform */
 +            LONG lM11 = FLOATOBJ_GetLong(&pmx->efM11);
 +            LONG lM22 = FLOATOBJ_GetLong(&pmx->efM22);
 +
 +            i = cPoints - 1;
 +            do
 +            {
 +                pptOut[i].x = pptIn[i].x * lM11;
 +                pptOut[i].y = pptIn[i].y * lM22;
 +            }
 +            while (--i >= 0);
 +        }
 +        else
 +        {
 +            /* Full integer transform */
 +            LONG lM11 = FLOATOBJ_GetLong(&pmx->efM11);
 +            LONG lM12 = FLOATOBJ_GetLong(&pmx->efM12);
 +            LONG lM21 = FLOATOBJ_GetLong(&pmx->efM21);
 +            LONG lM22 = FLOATOBJ_GetLong(&pmx->efM22);
 +
 +            i = cPoints - 1;
 +            do
 +            {
 +                LONG x;
 +                x  = pptIn[i].x * lM11;
 +                x += pptIn[i].y * lM21;
 +                pptOut[i].y  = pptIn[i].y * lM22;
 +                pptOut[i].y += pptIn[i].x * lM12;
 +                pptOut[i].x = x;
 +            }
 +            while (--i >= 0);
 +        }
 +    }
 +    else if (flAccel & XFORM_UNITY)
 +    {
 +        /* 1-scale transform */
 +        i = cPoints - 1;
 +        do
 +        {
 +            fo1 = pmx->efM21;
 +            FLOATOBJ_MulLong(&fo1, pptIn[i].y);
 +            fo2 = pmx->efM12;
 +            FLOATOBJ_MulLong(&fo2, pptIn[i].x);
 +            pptOut[i].x = pptIn[i].x + FLOATOBJ_GetLong(&fo1);
 +            pptOut[i].y = pptIn[i].y + FLOATOBJ_GetLong(&fo2);
 +        }
 +        while (--i >= 0);
 +    }
 +    else if (flAccel & XFORM_SCALE)
 +    {
 +        /* Diagonal float transform */
 +        i = cPoints - 1;
 +        do
 +        {
 +            fo1 = pmx->efM11;
 +            FLOATOBJ_MulLong(&fo1, pptIn[i].x);
 +            pptOut[i].x = FLOATOBJ_GetLong(&fo1);
 +            fo2 = pmx->efM22;
 +            FLOATOBJ_MulLong(&fo2, pptIn[i].y);
 +            pptOut[i].y = FLOATOBJ_GetLong(&fo2);
 +        }
 +        while (--i >= 0);
 +    }
 +    else
 +    {
 +        /* Full float transform */
 +        i = cPoints - 1;
 +        do
 +        {
 +            MulAddLong(&fo1, &pmx->efM11, pptIn[i].x, &pmx->efM21, pptIn[i].y);
 +            MulAddLong(&fo2, &pmx->efM12, pptIn[i].x, &pmx->efM22, pptIn[i].y);
 +            pptOut[i].x = FLOATOBJ_GetLong(&fo1);
 +            pptOut[i].y = FLOATOBJ_GetLong(&fo2);
 +        }
 +        while (--i >= 0);
 +    }
 +
 +    if (!(pmx->flAccel & XFORM_NO_TRANSLATION))
 +    {
 +        /* Translate points */
 +        i = cPoints - 1;
 +        do
 +        {
 +            pptOut[i].x += pmx->fxDx;
 +            pptOut[i].y += pmx->fxDy;
 +        }
 +        while (--i >= 0);
 +    }
 +
 +    return TRUE;
 +}
 +
 +/** Public functions **********************************************************/
 +
 +// www.osr.com/ddk/graphics/gdifncs_0s2v.htm
 +ULONG
 +APIENTRY
 +XFORMOBJ_iGetXform(
 +    IN XFORMOBJ *pxo,
 +    OUT XFORML *pxform)
 +{
 +    PMATRIX pmx = XFORMOBJ_pmx(pxo);
 +
 +    /* Check parameters */
 +    if (!pxo || !pxform)
 +    {
 +        return DDI_ERROR;
 +    }
 +
 +    /* Copy members */
 +    pxform->eM11 = FLOATOBJ_GetFloat(&pmx->efM11);
 +    pxform->eM12 = FLOATOBJ_GetFloat(&pmx->efM12);
 +    pxform->eM21 = FLOATOBJ_GetFloat(&pmx->efM21);
 +    pxform->eM22 = FLOATOBJ_GetFloat(&pmx->efM22);
 +    pxform->eDx = FLOATOBJ_GetFloat(&pmx->efDx);
 +    pxform->eDy = FLOATOBJ_GetFloat(&pmx->efDy);
 +
 +    /* Return complexity hint */
 +    return HintFromAccel(pmx->flAccel);
 +}
 +
 +
 +// www.osr.com/ddk/graphics/gdifncs_5ig7.htm
 +ULONG
 +APIENTRY
 +XFORMOBJ_iGetFloatObjXform(
 +    IN XFORMOBJ *pxo,
 +    OUT FLOATOBJ_XFORM *pxfo)
 +{
 +    PMATRIX pmx = XFORMOBJ_pmx(pxo);
 +
 +    /* Check parameters */
 +    if (!pxo || !pxfo)
 +    {
 +        return DDI_ERROR;
 +    }
 +
 +    /* Copy members */
 +    pxfo->eM11 = pmx->efM11;
 +    pxfo->eM12 = pmx->efM12;
 +    pxfo->eM21 = pmx->efM21;
 +    pxfo->eM22 = pmx->efM22;
 +    pxfo->eDx = pmx->efDx;
 +    pxfo->eDy = pmx->efDy;
 +
 +    /* Return complexity hint */
 +    return HintFromAccel(pmx->flAccel);
 +}
 +
 +
 +// www.osr.com/ddk/graphics/gdifncs_027b.htm
 +BOOL
 +APIENTRY
 +XFORMOBJ_bApplyXform(
 +    IN XFORMOBJ *pxo,
 +    IN ULONG iMode,
 +    IN ULONG cPoints,
 +    IN PVOID pvIn,
 +    OUT PVOID pvOut)
 +{
 +    MATRIX mx;
 +    XFORMOBJ xoInv;
 +    POINTL *pptl;
 +    INT i;
 +
 +    /* Check parameters */
 +    if (!pxo || !pvIn || !pvOut || cPoints < 1)
 +    {
 +        return FALSE;
 +    }
 +
 +    /* Use inverse xform? */
 +    if (iMode == XF_INV_FXTOL || iMode == XF_INV_LTOL)
 +    {
 +        XFORMOBJ_vInit(&xoInv, &mx);
 +        if (XFORMOBJ_iInverse(&xoInv, pxo) == DDI_ERROR)
 +        {
 +            return FALSE;
 +        }
 +        pxo = &xoInv;
 +    }
 +
 +    /* Convert POINTL to POINTFIX? */
 +    if (iMode == XF_LTOFX || iMode == XF_LTOL || iMode == XF_INV_LTOL)
 +    {
 +        pptl = pvIn;
 +        for (i = cPoints - 1; i >= 0; i--)
 +        {
 +            pptl[i].x = LONG2FIX(pptl[i].x);
 +            pptl[i].y = LONG2FIX(pptl[i].y);
 +        }
 +    }
 +
 +    /* Do the actual fixpoint transformation */
 +    if (!XFORMOBJ_bXformFixPoints(pxo, cPoints, pvIn, pvOut))
 +    {
 +        return FALSE;
 +    }
 +
 +    /* Convert POINTFIX to POINTL? */
 +    if (iMode == XF_INV_FXTOL || iMode == XF_INV_LTOL || iMode == XF_LTOL)
 +    {
 +        pptl = pvOut;
 +        for (i = cPoints - 1; i >= 0; i--)
 +        {
 +            pptl[i].x = FIX2LONG(pptl[i].x);
 +            pptl[i].y = FIX2LONG(pptl[i].y);
 +        }
 +    }
 +
 +    return TRUE;
 +}
 +
 +/* EOF */
Simple merge
index 4be4c21,0000000..ddb0ce7
mode 100644,000000..100644
--- /dev/null
@@@ -1,607 -1,0 +1,607 @@@
-             if (pHotKey->id == IDHK_WINKEY && bWinHotkeyActive == TRUE)
 +/*
 + * COPYRIGHT:        See COPYING in the top level directory
 + * PROJECT:          ReactOS Win32k subsystem
 + * PURPOSE:          HotKey support
 + * FILE:             win32ss/user/ntuser/hotkey.c
 + * PROGRAMER:        Eric Kohl
 + */
 +
 +/*
 + * FIXME: Hotkey notifications are triggered by keyboard input (physical or programatically)
 + * and since only desktops on WinSta0 can receive input in seems very wrong to allow
 + * windows/threads on destops not belonging to WinSta0 to set hotkeys (receive notifications).
 + *     -- Gunnar
 + */
 +
 +#include <win32k.h>
 +DBG_DEFAULT_CHANNEL(UserHotkey);
 +
 +/* GLOBALS *******************************************************************/
 +
 +/*
 + * Hardcoded hotkeys. See http://ivanlef0u.fr/repo/windoz/VI20051005.html
 + * or http://repo.meh.or.id/Windows/VI20051005.html .
 + *
 + * NOTE: The (Shift-)F12 keys are used only for the "UserDebuggerHotKey" setting
 + * which enables setting a key shortcut which, when pressed, establishes a
 + * breakpoint in the code being debugged:
 + * see http://technet.microsoft.com/en-us/library/cc786263(v=ws.10).aspx
 + * and http://flylib.com/books/en/4.441.1.33/1/ for more details.
 + * By default the key is VK-F12 on a 101-key keyboard, and is VK_SUBTRACT
 + * (hyphen / substract sign) on a 82-key keyboard.
 + */
 +/*                       pti   pwnd  modifiers  vk      id  next */
 +// HOT_KEY hkF12 =      {NULL, 1,    0,         VK_F12, IDHK_F12,      NULL};
 +// HOT_KEY hkShiftF12 = {NULL, 1,    MOD_SHIFT, VK_F12, IDHK_SHIFTF12, &hkF12};
 +// HOT_KEY hkWinKey =   {NULL, 1,    MOD_WIN,   0,      IDHK_WINKEY,   &hkShiftF12};
 +
 +PHOT_KEY gphkFirst = NULL;
 +BOOL bWinHotkeyActive = FALSE;
 +
 +/* FUNCTIONS *****************************************************************/
 +
 +VOID FASTCALL
 +StartDebugHotKeys(VOID)
 +{
 +    UINT vk = VK_F12;
 +    UserUnregisterHotKey(PWND_BOTTOM, IDHK_F12);
 +    UserUnregisterHotKey(PWND_BOTTOM, IDHK_SHIFTF12);
 +    if (!ENHANCED_KEYBOARD(gKeyboardInfo.KeyboardIdentifier))
 +    {
 +        vk = VK_SUBTRACT;
 +    }
 +    UserRegisterHotKey(PWND_BOTTOM, IDHK_SHIFTF12, MOD_SHIFT, vk);
 +    UserRegisterHotKey(PWND_BOTTOM, IDHK_F12, 0, vk);
 +    TRACE("Start up the debugger hotkeys!! If you see this you eneabled debugprints. Congrats!\n");
 +}
 +
 +/*
 + * IntGetModifiers
 + *
 + * Returns a value that indicates if the key is a modifier key, and
 + * which one.
 + */
 +static
 +UINT FASTCALL
 +IntGetModifiers(PBYTE pKeyState)
 +{
 +    UINT fModifiers = 0;
 +
 +    if (IS_KEY_DOWN(pKeyState, VK_SHIFT))
 +        fModifiers |= MOD_SHIFT;
 +
 +    if (IS_KEY_DOWN(pKeyState, VK_CONTROL))
 +        fModifiers |= MOD_CONTROL;
 +
 +    if (IS_KEY_DOWN(pKeyState, VK_MENU))
 +        fModifiers |= MOD_ALT;
 +
 +    if (IS_KEY_DOWN(pKeyState, VK_LWIN) || IS_KEY_DOWN(pKeyState, VK_RWIN))
 +        fModifiers |= MOD_WIN;
 +
 +    return fModifiers;
 +}
 +
 +/*
 + * UnregisterWindowHotKeys
 + *
 + * Removes hotkeys registered by specified window on its cleanup
 + */
 +VOID FASTCALL
 +UnregisterWindowHotKeys(PWND pWnd)
 +{
 +    PHOT_KEY pHotKey = gphkFirst, phkNext, *pLink = &gphkFirst;
 +
 +    while (pHotKey)
 +    {
 +        /* Save next ptr for later use */
 +        phkNext = pHotKey->pNext;
 +
 +        /* Should we delete this hotkey? */
 +        if (pHotKey->pWnd == pWnd)
 +        {
 +            /* Update next ptr for previous hotkey and free memory */
 +            *pLink = phkNext;
 +            ExFreePoolWithTag(pHotKey, USERTAG_HOTKEY);
 +        }
 +        else /* This hotkey will stay, use its next ptr */
 +            pLink = &pHotKey->pNext;
 +
 +        /* Move to the next entry */
 +        pHotKey = phkNext;
 +    }
 +}
 +
 +/*
 + * UnregisterThreadHotKeys
 + *
 + * Removes hotkeys registered by specified thread on its cleanup
 + */
 +VOID FASTCALL
 +UnregisterThreadHotKeys(PTHREADINFO pti)
 +{
 +    PHOT_KEY pHotKey = gphkFirst, phkNext, *pLink = &gphkFirst;
 +
 +    while (pHotKey)
 +    {
 +        /* Save next ptr for later use */
 +        phkNext = pHotKey->pNext;
 +
 +        /* Should we delete this hotkey? */
 +        if (pHotKey->pti == pti)
 +        {
 +            /* Update next ptr for previous hotkey and free memory */
 +            *pLink = phkNext;
 +            ExFreePoolWithTag(pHotKey, USERTAG_HOTKEY);
 +        }
 +        else /* This hotkey will stay, use its next ptr */
 +            pLink = &pHotKey->pNext;
 +
 +        /* Move to the next entry */
 +        pHotKey = phkNext;
 +    }
 +}
 +
 +/*
 + * IsHotKey
 + *
 + * Checks if given key and modificators have corresponding hotkey
 + */
 +static PHOT_KEY FASTCALL
 +IsHotKey(UINT fsModifiers, WORD wVk)
 +{
 +    PHOT_KEY pHotKey = gphkFirst;
 +
 +    while (pHotKey)
 +    {
 +        if (pHotKey->fsModifiers == fsModifiers &&
 +            pHotKey->vk == wVk)
 +        {
 +            /* We have found it */
 +            return pHotKey;
 +        }
 +
 +        /* Move to the next entry */
 +        pHotKey = pHotKey->pNext;
 +    }
 +
 +    return NULL;
 +}
 +
 +/*
 + * co_UserProcessHotKeys
 + *
 + * Sends WM_HOTKEY message if given keys are hotkey
 + */
 +BOOL NTAPI
 +co_UserProcessHotKeys(WORD wVk, BOOL bIsDown)
 +{
 +    UINT fModifiers;
 +    PHOT_KEY pHotKey;
 +    PWND pWnd;
 +    BOOL DoNotPostMsg = FALSE;
 +
 +    if (wVk == VK_SHIFT || wVk == VK_CONTROL || wVk == VK_MENU ||
 +        wVk == VK_LWIN || wVk == VK_RWIN)
 +    {
 +        /* Those keys are specified by modifiers */
 +        wVk = 0;
 +    }
 +
 +    fModifiers = IntGetModifiers(gafAsyncKeyState);
 +
 +    /* Check if it is a hotkey */
 +    pHotKey = IsHotKey(fModifiers, wVk);
 +
 +    if (pHotKey)
 +    {
 +        TRACE("Hot key pressed (pWnd %p, id %d)\n", pHotKey->pWnd, pHotKey->id);
 +
 +        /* FIXME: See comment about "UserDebuggerHotKey" on top of this file. */
 +        if (pHotKey->id == IDHK_SHIFTF12 || pHotKey->id == IDHK_F12)
 +        {
 +            if (bIsDown)
 +            {
 +                ERR("Hot key pressed for Debug Activation! ShiftF12 = %d or F12 = %d\n",pHotKey->id == IDHK_SHIFTF12 , pHotKey->id == IDHK_F12);
 +                //DoNotPostMsg = co_ActivateDebugger(); // FIXME
 +            }
 +            return DoNotPostMsg;
 +        }
 +
 +        /* Process hotkey if it is key up event */
 +        if (!bIsDown)
 +        {
 +            /* WIN and F12 keys are not hardcoded here. See comments on top of this file. */
++            if (pHotKey->id == IDHK_WINKEY && bWinHotkeyActive)
 +            {
 +                pWnd = ValidateHwndNoErr(InputWindowStation->ShellWindow);
 +                if (pWnd)
 +                {
 +                   TRACE("System Hot key Id %d Key %d\n",pHotKey->id, wVk );
 +                   UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_TASKLIST, 0);
 +                   co_IntShellHookNotify(HSHELL_TASKMAN, 0, 0);
 +                   bWinHotkeyActive = FALSE;
 +                   return FALSE;
 +                }
 +            }
 +        }
 +        else
 +        {    /* The user pressed the win key */
 +            if (pHotKey->id == IDHK_WINKEY)
 +            {
 +               bWinHotkeyActive = TRUE;
 +               return FALSE;
 +            }
 +        }
 +
 +        if (bIsDown)
 +        {
 +            if (!pHotKey->pWnd)
 +            {
 +                TRACE("UPTM Hot key Id %d Key %d\n",pHotKey->id, wVk );
 +                UserPostThreadMessage(pHotKey->pti, WM_HOTKEY, pHotKey->id, MAKELONG(fModifiers, wVk));
 +                //ptiLastInput = pHotKey->pti;
 +                return TRUE; /* Don't send any message */
 +            }
 +            else
 +            {
 +               if (pHotKey->pWnd == PWND_BOTTOM)
 +               {
 +                   if (gpqForeground != NULL)
 +                   {
 +                      pWnd = gpqForeground->spwndFocus;
 +                   }
 +                   else
 +                      return FALSE;
 +                }
 +                else
 +                {
 +                   pWnd = pHotKey->pWnd;
 +                }
 +                if (pWnd)
 +                {          //  pWnd->head.rpdesk->pDeskInfo->spwndShell needs testing.
 +                   if (pWnd == ValidateHwndNoErr(InputWindowStation->ShellWindow) && pHotKey->id == SC_TASKLIST)
 +                   {
 +                      ERR("Sending to shell window w/o IDHK_WINKEY..\n");
 +                      UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_TASKLIST, 0);
 +                   }
 +                   else
 +                   {
 +                      TRACE("UPM Hot key Id %d Key %d\n",pHotKey->id, wVk );
 +                      UserPostMessage(UserHMGetHandle(pWnd), WM_HOTKEY, pHotKey->id, MAKELONG(fModifiers, wVk));
 +                   }
 +                   //ptiLastInput = pWnd->head.pti;
 +                   return TRUE; /* Don't send any message */
 +                }
 +            }
 +        }
 +    }
 +    return FALSE;
 +}
 +
 +
 +/*
 + * DefWndGetHotKey
 + *
 + * GetHotKey message support
 + */
 +UINT FASTCALL
 +DefWndGetHotKey(PWND pWnd)
 +{
 +    PHOT_KEY pHotKey = gphkFirst;
 +
 +    WARN("DefWndGetHotKey\n");
 +
 +    while (pHotKey)
 +    {
 +        if (pHotKey->pWnd == pWnd && pHotKey->id == IDHK_REACTOS)
 +        {
 +            /* We have found it */
 +            return MAKELONG(pHotKey->vk, pHotKey->fsModifiers);
 +        }
 +
 +        /* Move to the next entry */
 +        pHotKey = pHotKey->pNext;
 +    }
 +
 +    return 0;
 +}
 +
 +/*
 + * DefWndSetHotKey
 + *
 + * SetHotKey message support
 + */
 +INT FASTCALL
 +DefWndSetHotKey(PWND pWnd, WPARAM wParam)
 +{
 +    UINT fsModifiers, vk;
 +    PHOT_KEY pHotKey, *pLink;
 +    INT iRet = 1;
 +
 +    WARN("DefWndSetHotKey wParam 0x%x\n", wParam);
 +
 +    // A hot key cannot be associated with a child window.
 +    if (pWnd->style & WS_CHILD)
 +        return 0;
 +
 +    // VK_ESCAPE, VK_SPACE, and VK_TAB are invalid hot keys.
 +    if (LOWORD(wParam) == VK_ESCAPE ||
 +        LOWORD(wParam) == VK_SPACE ||
 +        LOWORD(wParam) == VK_TAB)
 +    {
 +        return -1;
 +    }
 +
 +    vk = LOWORD(wParam);
 +    fsModifiers = HIWORD(wParam);
 +
 +    if (wParam)
 +    {
 +        pHotKey = gphkFirst;
 +        while (pHotKey)
 +        {
 +            if (pHotKey->fsModifiers == fsModifiers &&
 +                pHotKey->vk == vk &&
 +                pHotKey->id == IDHK_REACTOS)
 +            {
 +                if (pHotKey->pWnd != pWnd)
 +                    iRet = 2; // Another window already has the same hot key.
 +                break;
 +            }
 +
 +            /* Move to the next entry */
 +            pHotKey = pHotKey->pNext;
 +        }
 +    }
 +
 +    pHotKey = gphkFirst;
 +    pLink = &gphkFirst;
 +    while (pHotKey)
 +    {
 +        if (pHotKey->pWnd == pWnd &&
 +            pHotKey->id == IDHK_REACTOS)
 +        {
 +            /* This window has already hotkey registered */
 +            break;
 +        }
 +
 +        /* Move to the next entry */
 +        pLink = &pHotKey->pNext;
 +        pHotKey = pHotKey->pNext;
 +    }
 +
 +    if (wParam)
 +    {
 +        if (!pHotKey)
 +        {
 +            /* Create new hotkey */
 +            pHotKey = ExAllocatePoolWithTag(PagedPool, sizeof(HOT_KEY), USERTAG_HOTKEY);
 +            if (pHotKey == NULL)
 +                return 0;
 +
 +            pHotKey->pWnd = pWnd;
 +            pHotKey->id = IDHK_REACTOS; // Don't care, these hot keys are unrelated to the hot keys set by RegisterHotKey
 +            pHotKey->pNext = gphkFirst;
 +            gphkFirst = pHotKey;
 +        }
 +
 +        /* A window can only have one hot key. If the window already has a
 +           hot key associated with it, the new hot key replaces the old one. */
 +        pHotKey->pti = NULL;
 +        pHotKey->fsModifiers = fsModifiers;
 +        pHotKey->vk = vk;
 +    }
 +    else if (pHotKey)
 +    {
 +        /* Remove hotkey */
 +        *pLink = pHotKey->pNext;
 +        ExFreePoolWithTag(pHotKey, USERTAG_HOTKEY);
 +    }
 +
 +    return iRet;
 +}
 +
 +
 +BOOL FASTCALL
 +UserRegisterHotKey(PWND pWnd,
 +                   int id,
 +                   UINT fsModifiers,
 +                   UINT vk)
 +{
 +    PHOT_KEY pHotKey;
 +    PTHREADINFO pHotKeyThread;
 +
 +    /* Find hotkey thread */
 +    if (pWnd == NULL || pWnd == PWND_BOTTOM)
 +    {
 +        pHotKeyThread = PsGetCurrentThreadWin32Thread();
 +    }
 +    else
 +    {
 +        pHotKeyThread = pWnd->head.pti;
 +    }
 +
 +    /* Check for existing hotkey */
 +    if (IsHotKey(fsModifiers, vk))
 +    {
 +        EngSetLastError(ERROR_HOTKEY_ALREADY_REGISTERED);
 +        WARN("Hotkey already exists\n");
 +        return FALSE;
 +    }
 +
 +    /* Create new hotkey */
 +    pHotKey = ExAllocatePoolWithTag(PagedPool, sizeof(HOT_KEY), USERTAG_HOTKEY);
 +    if (pHotKey == NULL)
 +    {
 +        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
 +        return FALSE;
 +    }
 +
 +    pHotKey->pti = pHotKeyThread;
 +    pHotKey->pWnd = pWnd;
 +    pHotKey->fsModifiers = fsModifiers;
 +    pHotKey->vk = vk;
 +    pHotKey->id = id;
 +
 +    /* Insert hotkey to the global list */
 +    pHotKey->pNext = gphkFirst;
 +    gphkFirst = pHotKey;
 +
 +    return TRUE;
 +}
 +
 +BOOL FASTCALL
 +UserUnregisterHotKey(PWND pWnd, int id)
 +{
 +    PHOT_KEY pHotKey = gphkFirst, phkNext, *pLink = &gphkFirst;
 +    BOOL bRet = FALSE;
 +
 +    while (pHotKey)
 +    {
 +        /* Save next ptr for later use */
 +        phkNext = pHotKey->pNext;
 +
 +        /* Should we delete this hotkey? */
 +        if (pHotKey->pWnd == pWnd && pHotKey->id == id)
 +        {
 +            /* Update next ptr for previous hotkey and free memory */
 +            *pLink = phkNext;
 +            ExFreePoolWithTag(pHotKey, USERTAG_HOTKEY);
 +
 +            bRet = TRUE;
 +        }
 +        else /* This hotkey will stay, use its next ptr */
 +            pLink = &pHotKey->pNext;
 +
 +        /* Move to the next entry */
 +        pHotKey = phkNext;
 +    }
 +    return bRet;
 +}
 +
 +
 +/* SYSCALLS *****************************************************************/
 +
 +
 +BOOL APIENTRY
 +NtUserRegisterHotKey(HWND hWnd,
 +                     int id,
 +                     UINT fsModifiers,
 +                     UINT vk)
 +{
 +    PHOT_KEY pHotKey;
 +    PWND pWnd = NULL;
 +    PTHREADINFO pHotKeyThread;
 +    BOOL bRet = FALSE;
 +
 +    TRACE("Enter NtUserRegisterHotKey\n");
 +
 +    if (fsModifiers & ~(MOD_ALT|MOD_CONTROL|MOD_SHIFT|MOD_WIN)) // FIXME: Does Win2k3 support MOD_NOREPEAT?
 +    {
 +        WARN("Invalid modifiers: %x\n", fsModifiers);
 +        EngSetLastError(ERROR_INVALID_FLAGS);
 +        return 0;
 +    }
 +
 +    UserEnterExclusive();
 +
 +    /* Find hotkey thread */
 +    if (hWnd == NULL)
 +    {
 +        pHotKeyThread = gptiCurrent;
 +    }
 +    else
 +    {
 +        pWnd = UserGetWindowObject(hWnd);
 +        if (!pWnd)
 +            goto cleanup;
 +
 +        pHotKeyThread = pWnd->head.pti;
 +
 +        /* Fix wine msg "Window on another thread" test_hotkey */
 +        if (pWnd->head.pti != gptiCurrent)
 +        {
 +           EngSetLastError(ERROR_WINDOW_OF_OTHER_THREAD);
 +           WARN("Must be from the same Thread.\n");
 +           goto cleanup;
 +        }
 +    }
 +
 +    /* Check for existing hotkey */
 +    if (IsHotKey(fsModifiers, vk))
 +    {
 +        EngSetLastError(ERROR_HOTKEY_ALREADY_REGISTERED);
 +        WARN("Hotkey already exists\n");
 +        goto cleanup;
 +    }
 +
 +    /* Create new hotkey */
 +    pHotKey = ExAllocatePoolWithTag(PagedPool, sizeof(HOT_KEY), USERTAG_HOTKEY);
 +    if (pHotKey == NULL)
 +    {
 +        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
 +        goto cleanup;
 +    }
 +
 +    pHotKey->pti = pHotKeyThread;
 +    pHotKey->pWnd = pWnd;
 +    pHotKey->fsModifiers = fsModifiers;
 +    pHotKey->vk = vk;
 +    pHotKey->id = id;
 +
 +    /* Insert hotkey to the global list */
 +    pHotKey->pNext = gphkFirst;
 +    gphkFirst = pHotKey;
 +
 +    bRet = TRUE;
 +
 +cleanup:
 +    TRACE("Leave NtUserRegisterHotKey, ret=%i\n", bRet);
 +    UserLeave();
 +    return bRet;
 +}
 +
 +
 +BOOL APIENTRY
 +NtUserUnregisterHotKey(HWND hWnd, int id)
 +{
 +    PHOT_KEY pHotKey = gphkFirst, phkNext, *pLink = &gphkFirst;
 +    BOOL bRet = FALSE;
 +    PWND pWnd = NULL;
 +
 +    TRACE("Enter NtUserUnregisterHotKey\n");
 +    UserEnterExclusive();
 +
 +    /* Fail if given window is invalid */
 +    if (hWnd && !(pWnd = UserGetWindowObject(hWnd)))
 +        goto cleanup;
 +
 +    while (pHotKey)
 +    {
 +        /* Save next ptr for later use */
 +        phkNext = pHotKey->pNext;
 +
 +        /* Should we delete this hotkey? */
 +        if (pHotKey->pWnd == pWnd && pHotKey->id == id)
 +        {
 +            /* Update next ptr for previous hotkey and free memory */
 +            *pLink = phkNext;
 +            ExFreePoolWithTag(pHotKey, USERTAG_HOTKEY);
 +
 +            bRet = TRUE;
 +        }
 +        else /* This hotkey will stay, use its next ptr */
 +            pLink = &pHotKey->pNext;
 +
 +        /* Move to the next entry */
 +        pHotKey = phkNext;
 +    }
 +
 +cleanup:
 +    TRACE("Leave NtUserUnregisterHotKey, ret=%i\n", bRet);
 +    UserLeave();
 +    return bRet;
 +}
 +
 +/* EOF */
index eb1e127,0000000..1df412b
mode 100644,000000..100644
--- /dev/null
@@@ -1,2951 -1,0 +1,2951 @@@
-     if (Ret == TRUE)
 +/*
 + * COPYRIGHT:        See COPYING in the top level directory
 + * PROJECT:          ReactOS Win32k subsystem
 + * PURPOSE:          Messages
 + * FILE:             subsystems/win32/win32k/ntuser/message.c
 + * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
 + */
 +
 +#include <win32k.h>
 +
 +#include <dde.h>
 +
 +DBG_DEFAULT_CHANNEL(UserMsg);
 +
 +#define PM_BADMSGFLAGS ~((QS_RAWINPUT << 16)|PM_QS_SENDMESSAGE|PM_QS_PAINT|PM_QS_POSTMESSAGE|PM_QS_INPUT|PM_NOYIELD|PM_REMOVE)
 +
 +/* FUNCTIONS *****************************************************************/
 +
 +NTSTATUS FASTCALL
 +IntInitMessageImpl(VOID)
 +{
 +    return STATUS_SUCCESS;
 +}
 +
 +NTSTATUS FASTCALL
 +IntCleanupMessageImpl(VOID)
 +{
 +    return STATUS_SUCCESS;
 +}
 +
 +/* From wine: */
 +/* flag for messages that contain pointers */
 +/* 32 messages per entry, messages 0..31 map to bits 0..31 */
 +
 +#define SET(msg) (1 << ((msg) & 31))
 +
 +static const unsigned int message_pointer_flags[] =
 +{
 +    /* 0x00 - 0x1f */
 +    SET(WM_CREATE) | SET(WM_SETTEXT) | SET(WM_GETTEXT) |
 +    SET(WM_WININICHANGE) | SET(WM_DEVMODECHANGE),
 +    /* 0x20 - 0x3f */
 +    SET(WM_GETMINMAXINFO) | SET(WM_DRAWITEM) | SET(WM_MEASUREITEM) | SET(WM_DELETEITEM) |
 +    SET(WM_COMPAREITEM),
 +    /* 0x40 - 0x5f */
 +    SET(WM_WINDOWPOSCHANGING) | SET(WM_WINDOWPOSCHANGED) | SET(WM_COPYDATA) |
 +    SET(WM_COPYGLOBALDATA) | SET(WM_NOTIFY) | SET(WM_HELP),
 +    /* 0x60 - 0x7f */
 +    SET(WM_STYLECHANGING) | SET(WM_STYLECHANGED),
 +    /* 0x80 - 0x9f */
 +    SET(WM_NCCREATE) | SET(WM_NCCALCSIZE) | SET(WM_GETDLGCODE),
 +    /* 0xa0 - 0xbf */
 +    SET(EM_GETSEL) | SET(EM_GETRECT) | SET(EM_SETRECT) | SET(EM_SETRECTNP),
 +    /* 0xc0 - 0xdf */
 +    SET(EM_REPLACESEL) | SET(EM_GETLINE) | SET(EM_SETTABSTOPS),
 +    /* 0xe0 - 0xff */
 +    SET(SBM_GETRANGE) | SET(SBM_SETSCROLLINFO) | SET(SBM_GETSCROLLINFO) | SET(SBM_GETSCROLLBARINFO),
 +    /* 0x100 - 0x11f */
 +    0,
 +    /* 0x120 - 0x13f */
 +    0,
 +    /* 0x140 - 0x15f */
 +    SET(CB_GETEDITSEL) | SET(CB_ADDSTRING) | SET(CB_DIR) | SET(CB_GETLBTEXT) |
 +    SET(CB_INSERTSTRING) | SET(CB_FINDSTRING) | SET(CB_SELECTSTRING) |
 +    SET(CB_GETDROPPEDCONTROLRECT) | SET(CB_FINDSTRINGEXACT),
 +    /* 0x160 - 0x17f */
 +    0,
 +    /* 0x180 - 0x19f */
 +    SET(LB_ADDSTRING) | SET(LB_INSERTSTRING) | SET(LB_GETTEXT) | SET(LB_SELECTSTRING) |
 +    SET(LB_DIR) | SET(LB_FINDSTRING) |
 +    SET(LB_GETSELITEMS) | SET(LB_SETTABSTOPS) | SET(LB_ADDFILE) | SET(LB_GETITEMRECT),
 +    /* 0x1a0 - 0x1bf */
 +    SET(LB_FINDSTRINGEXACT),
 +    /* 0x1c0 - 0x1df */
 +    0,
 +    /* 0x1e0 - 0x1ff */
 +    0,
 +    /* 0x200 - 0x21f */
 +    SET(WM_NEXTMENU) | SET(WM_SIZING) | SET(WM_MOVING) | SET(WM_DEVICECHANGE),
 +    /* 0x220 - 0x23f */
 +    SET(WM_MDICREATE) | SET(WM_MDIGETACTIVE) | SET(WM_DROPOBJECT) |
 +    SET(WM_QUERYDROPOBJECT) | SET(WM_DRAGLOOP) | SET(WM_DRAGSELECT) | SET(WM_DRAGMOVE),
 +    /* 0x240 - 0x25f */
 +    0,
 +    /* 0x260 - 0x27f */
 +    0,
 +    /* 0x280 - 0x29f */
 +    0,
 +    /* 0x2a0 - 0x2bf */
 +    0,
 +    /* 0x2c0 - 0x2df */
 +    0,
 +    /* 0x2e0 - 0x2ff */
 +    0,
 +    /* 0x300 - 0x31f */
 +    SET(WM_ASKCBFORMATNAME)
 +};
 +
 +/* check whether a given message type includes pointers */
 +static inline int is_pointer_message( UINT message )
 +{
 +    if (message >= 8*sizeof(message_pointer_flags)) return FALSE;
 +        return (message_pointer_flags[message / 32] & SET(message)) != 0;
 +}
 +#undef SET
 +
 +#define MMS_SIZE_WPARAM      -1
 +#define MMS_SIZE_WPARAMWCHAR -2
 +#define MMS_SIZE_LPARAMSZ    -3
 +#define MMS_SIZE_SPECIAL     -4
 +#define MMS_FLAG_READ        0x01
 +#define MMS_FLAG_WRITE       0x02
 +#define MMS_FLAG_READWRITE   (MMS_FLAG_READ | MMS_FLAG_WRITE)
 +typedef struct tagMSGMEMORY
 +{
 +    UINT Message;
 +    UINT Size;
 +    INT Flags;
 +}
 +MSGMEMORY, *PMSGMEMORY;
 +
 +static MSGMEMORY g_MsgMemory[] =
 +{
 +    { WM_CREATE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
 +    { WM_DDE_ACK, sizeof(KMDDELPARAM), MMS_FLAG_READ },
 +    { WM_DDE_EXECUTE, MMS_SIZE_WPARAM, MMS_FLAG_READ },
 +    { WM_GETMINMAXINFO, sizeof(MINMAXINFO), MMS_FLAG_READWRITE },
 +    { WM_GETTEXT, MMS_SIZE_WPARAMWCHAR, MMS_FLAG_WRITE },
 +    { WM_NCCALCSIZE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
 +    { WM_NCCREATE, MMS_SIZE_SPECIAL, MMS_FLAG_READWRITE },
 +    { WM_SETTEXT, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ },
 +    { WM_STYLECHANGED, sizeof(STYLESTRUCT), MMS_FLAG_READ },
 +    { WM_STYLECHANGING, sizeof(STYLESTRUCT), MMS_FLAG_READWRITE },
 +    { WM_SETTINGCHANGE, MMS_SIZE_LPARAMSZ, MMS_FLAG_READ },
 +    { WM_COPYDATA, MMS_SIZE_SPECIAL, MMS_FLAG_READ },
 +    { WM_COPYGLOBALDATA, MMS_SIZE_WPARAM, MMS_FLAG_READ },
 +    { WM_WINDOWPOSCHANGED, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
 +    { WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
 +    { WM_SIZING, sizeof(RECT), MMS_FLAG_READWRITE },
 +    { WM_MOVING, sizeof(RECT), MMS_FLAG_READWRITE },
 +};
 +
 +static PMSGMEMORY FASTCALL
 +FindMsgMemory(UINT Msg)
 +{
 +    PMSGMEMORY MsgMemoryEntry;
 +
 +    /* See if this message type is present in the table */
 +    for (MsgMemoryEntry = g_MsgMemory;
 +    MsgMemoryEntry < g_MsgMemory + sizeof(g_MsgMemory) / sizeof(MSGMEMORY);
 +    MsgMemoryEntry++)
 +    {
 +        if (Msg == MsgMemoryEntry->Message)
 +        {
 +            return MsgMemoryEntry;
 +        }
 +    }
 +
 +    return NULL;
 +}
 +
 +static UINT FASTCALL
 +MsgMemorySize(PMSGMEMORY MsgMemoryEntry, WPARAM wParam, LPARAM lParam)
 +{
 +    CREATESTRUCTW *Cs;
 +    PUNICODE_STRING WindowName;
 +    PUNICODE_STRING ClassName;
 +    UINT Size = 0;
 +
 +    _SEH2_TRY
 +    {
 +        if (MMS_SIZE_WPARAM == MsgMemoryEntry->Size)
 +        {
 +            Size = (UINT)wParam;
 +        }
 +        else if (MMS_SIZE_WPARAMWCHAR == MsgMemoryEntry->Size)
 +        {
 +            Size = (UINT) (wParam * sizeof(WCHAR));
 +        }
 +        else if (MMS_SIZE_LPARAMSZ == MsgMemoryEntry->Size)
 +        {
 +            // WM_SETTEXT and WM_SETTINGCHANGE can be null!
 +            if (!lParam)
 +            {
 +               TRACE("lParam is NULL!\n");
 +               Size = 0;
 +            }
 +            else
 +               Size = (UINT) ((wcslen((PWSTR) lParam) + 1) * sizeof(WCHAR));
 +        }
 +        else if (MMS_SIZE_SPECIAL == MsgMemoryEntry->Size)
 +        {
 +            switch(MsgMemoryEntry->Message)
 +            {
 +            case WM_CREATE:
 +            case WM_NCCREATE:
 +                Cs = (CREATESTRUCTW *) lParam;
 +                WindowName = (PUNICODE_STRING) Cs->lpszName;
 +                ClassName = (PUNICODE_STRING) Cs->lpszClass;
 +                Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
 +                if (IS_ATOM(ClassName->Buffer))
 +                {
 +                    Size += sizeof(WCHAR) + sizeof(ATOM);
 +                }
 +                else
 +                {
 +                    Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
 +                }
 +                break;
 +
 +            case WM_NCCALCSIZE:
 +                Size = wParam ? sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS) : sizeof(RECT);
 +                break;
 +
 +            case WM_COPYDATA:
 +                Size = sizeof(COPYDATASTRUCT) + ((PCOPYDATASTRUCT)lParam)->cbData;
 +                break;
 +
 +            default:
 +                ASSERT(FALSE);
 +                Size = 0;
 +                break;
 +            }
 +        }
 +        else
 +        {
 +            Size = MsgMemoryEntry->Size;
 +        }
 +    }
 +    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
 +    {
 +        ERR("Exception caught in MsgMemorySize()! Status: 0x%x\n", _SEH2_GetExceptionCode());
 +        Size = 0;
 +    }
 +    _SEH2_END;
 +    return Size;
 +}
 +
 +UINT lParamMemorySize(UINT Msg, WPARAM wParam, LPARAM lParam)
 +{
 +    PMSGMEMORY MsgMemoryEntry = FindMsgMemory(Msg);
 +    if(MsgMemoryEntry == NULL) return 0;
 +    return MsgMemorySize(MsgMemoryEntry, wParam, lParam);
 +}
 +
 +static NTSTATUS
 +PackParam(LPARAM *lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolNeeded)
 +{
 +    NCCALCSIZE_PARAMS *UnpackedNcCalcsize;
 +    NCCALCSIZE_PARAMS *PackedNcCalcsize;
 +    CREATESTRUCTW *UnpackedCs;
 +    CREATESTRUCTW *PackedCs;
 +    PLARGE_STRING WindowName;
 +    PUNICODE_STRING ClassName;
 +    POOL_TYPE PoolType;
 +    UINT Size;
 +    PCHAR CsData;
 +
 +    *lParamPacked = lParam;
 +
 +    if (NonPagedPoolNeeded)
 +        PoolType = NonPagedPool;
 +    else
 +        PoolType = PagedPool;
 +
 +    if (WM_NCCALCSIZE == Msg && wParam)
 +    {
 +
 +        UnpackedNcCalcsize = (NCCALCSIZE_PARAMS *) lParam;
 +        PackedNcCalcsize = ExAllocatePoolWithTag(PoolType,
 +        sizeof(NCCALCSIZE_PARAMS) + sizeof(WINDOWPOS),
 +        TAG_MSG);
 +
 +        if (NULL == PackedNcCalcsize)
 +        {
 +            ERR("Not enough memory to pack lParam\n");
 +            return STATUS_NO_MEMORY;
 +        }
 +        RtlCopyMemory(PackedNcCalcsize, UnpackedNcCalcsize, sizeof(NCCALCSIZE_PARAMS));
 +        PackedNcCalcsize->lppos = (PWINDOWPOS) (PackedNcCalcsize + 1);
 +        RtlCopyMemory(PackedNcCalcsize->lppos, UnpackedNcCalcsize->lppos, sizeof(WINDOWPOS));
 +        *lParamPacked = (LPARAM) PackedNcCalcsize;
 +    }
 +    else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
 +    {
 +        UnpackedCs = (CREATESTRUCTW *) lParam;
 +        WindowName = (PLARGE_STRING) UnpackedCs->lpszName;
 +        ClassName = (PUNICODE_STRING) UnpackedCs->lpszClass;
 +        Size = sizeof(CREATESTRUCTW) + WindowName->Length + sizeof(WCHAR);
 +        if (IS_ATOM(ClassName->Buffer))
 +        {
 +            Size += sizeof(WCHAR) + sizeof(ATOM);
 +        }
 +        else
 +        {
 +            Size += sizeof(WCHAR) + ClassName->Length + sizeof(WCHAR);
 +        }
 +        PackedCs = ExAllocatePoolWithTag(PoolType, Size, TAG_MSG);
 +        if (NULL == PackedCs)
 +        {
 +            ERR("Not enough memory to pack lParam\n");
 +            return STATUS_NO_MEMORY;
 +        }
 +        RtlCopyMemory(PackedCs, UnpackedCs, sizeof(CREATESTRUCTW));
 +        CsData = (PCHAR) (PackedCs + 1);
 +        PackedCs->lpszName = (LPCWSTR) (CsData - (PCHAR) PackedCs);
 +        RtlCopyMemory(CsData, WindowName->Buffer, WindowName->Length);
 +        CsData += WindowName->Length;
 +        *((WCHAR *) CsData) = L'\0';
 +        CsData += sizeof(WCHAR);
 +        PackedCs->lpszClass = (LPCWSTR) (CsData - (PCHAR) PackedCs);
 +        if (IS_ATOM(ClassName->Buffer))
 +        {
 +            *((WCHAR *) CsData) = L'A';
 +            CsData += sizeof(WCHAR);
 +            *((ATOM *) CsData) = (ATOM)(DWORD_PTR) ClassName->Buffer;
 +            CsData += sizeof(ATOM);
 +        }
 +        else
 +        {
 +            *((WCHAR *) CsData) = L'S';
 +            CsData += sizeof(WCHAR);
 +            RtlCopyMemory(CsData, ClassName->Buffer, ClassName->Length);
 +            CsData += ClassName->Length;
 +            *((WCHAR *) CsData) = L'\0';
 +            CsData += sizeof(WCHAR);
 +        }
 +        ASSERT(CsData == (PCHAR) PackedCs + Size);
 +        *lParamPacked = (LPARAM) PackedCs;
 +    }
 +    else if (PoolType == NonPagedPool)
 +    {
 +        PMSGMEMORY MsgMemoryEntry;
 +        PVOID PackedData;
 +        SIZE_T size;
 +
 +        MsgMemoryEntry = FindMsgMemory(Msg);
 +
 +        if (!MsgMemoryEntry)
 +        {
 +            /* Keep previous behavior */
 +            return STATUS_SUCCESS;
 +        }
 +        size = MsgMemorySize(MsgMemoryEntry, wParam, lParam);
 +        if (!size)
 +        {
 +           ERR("No size for lParamPacked\n");
 +           return STATUS_SUCCESS;
 +        }
 +        PackedData = ExAllocatePoolWithTag(NonPagedPool, size, TAG_MSG);
 +        if (PackedData == NULL)
 +        {
 +            ERR("Not enough memory to pack lParam\n");
 +            return STATUS_NO_MEMORY;
 +        }
 +        RtlCopyMemory(PackedData, (PVOID)lParam, MsgMemorySize(MsgMemoryEntry, wParam, lParam));
 +        *lParamPacked = (LPARAM)PackedData;
 +    }
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +static NTSTATUS
 +UnpackParam(LPARAM lParamPacked, UINT Msg, WPARAM wParam, LPARAM lParam, BOOL NonPagedPoolUsed)
 +{
 +    NCCALCSIZE_PARAMS *UnpackedParams;
 +    NCCALCSIZE_PARAMS *PackedParams;
 +    PWINDOWPOS UnpackedWindowPos;
 +
 +    if (lParamPacked == lParam)
 +    {
 +        return STATUS_SUCCESS;
 +    }
 +
 +    if (WM_NCCALCSIZE == Msg && wParam)
 +    {
 +        PackedParams = (NCCALCSIZE_PARAMS *) lParamPacked;
 +        UnpackedParams = (NCCALCSIZE_PARAMS *) lParam;
 +        UnpackedWindowPos = UnpackedParams->lppos;
 +        RtlCopyMemory(UnpackedParams, PackedParams, sizeof(NCCALCSIZE_PARAMS));
 +        UnpackedParams->lppos = UnpackedWindowPos;
 +        RtlCopyMemory(UnpackedWindowPos, PackedParams + 1, sizeof(WINDOWPOS));
 +        ExFreePool((PVOID) lParamPacked);
 +
 +        return STATUS_SUCCESS;
 +    }
 +    else if (WM_CREATE == Msg || WM_NCCREATE == Msg)
 +    {
 +        ExFreePool((PVOID) lParamPacked);
 +
 +        return STATUS_SUCCESS;
 +    }
 +    else if (NonPagedPoolUsed)
 +    {
 +        PMSGMEMORY MsgMemoryEntry;
 +        MsgMemoryEntry = FindMsgMemory(Msg);
 +        ASSERT(MsgMemoryEntry);
 +
 +        if (MsgMemoryEntry->Flags == MMS_FLAG_READWRITE)
 +        {
 +            //RtlCopyMemory((PVOID)lParam, (PVOID)lParamPacked, MsgMemoryEntry->Size);
 +        }
 +        ExFreePool((PVOID) lParamPacked);
 +        return STATUS_SUCCESS;
 +    }
 +
 +    ASSERT(FALSE);
 +
 +    return STATUS_INVALID_PARAMETER;
 +}
 +
 +static NTSTATUS FASTCALL
 +CopyMsgToKernelMem(MSG *KernelModeMsg, MSG *UserModeMsg, PMSGMEMORY MsgMemoryEntry)
 +{
 +    NTSTATUS Status;
 +
 +    PVOID KernelMem;
 +    UINT Size;
 +
 +    *KernelModeMsg = *UserModeMsg;
 +
 +    /* See if this message type is present in the table */
 +    if (NULL == MsgMemoryEntry)
 +    {
 +        /* Not present, no copying needed */
 +        return STATUS_SUCCESS;
 +    }
 +
 +    /* Determine required size */
 +    Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
 +
 +    if (0 != Size)
 +    {
 +        /* Allocate kernel mem */
 +        KernelMem = ExAllocatePoolWithTag(PagedPool, Size, TAG_MSG);
 +        if (NULL == KernelMem)
 +        {
 +            ERR("Not enough memory to copy message to kernel mem\n");
 +            return STATUS_NO_MEMORY;
 +        }
 +        KernelModeMsg->lParam = (LPARAM) KernelMem;
 +
 +        /* Copy data if required */
 +        if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_READ))
 +        {
 +            TRACE("Copy Message %d from usermode buffer\n", KernelModeMsg->message);
 +            Status = MmCopyFromCaller(KernelMem, (PVOID) UserModeMsg->lParam, Size);
 +            if (! NT_SUCCESS(Status))
 +            {
 +                ERR("Failed to copy message to kernel: invalid usermode lParam buffer\n");
 +                ExFreePoolWithTag(KernelMem, TAG_MSG);
 +                return Status;
 +            }
 +        }
 +        else
 +        {
 +            /* Make sure we don't pass any secrets to usermode */
 +            RtlZeroMemory(KernelMem, Size);
 +        }
 +    }
 +    else
 +    {
 +        KernelModeMsg->lParam = 0;
 +    }
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +static NTSTATUS FASTCALL
 +CopyMsgToUserMem(MSG *UserModeMsg, MSG *KernelModeMsg)
 +{
 +    NTSTATUS Status;
 +    PMSGMEMORY MsgMemoryEntry;
 +    UINT Size;
 +
 +    /* See if this message type is present in the table */
 +    MsgMemoryEntry = FindMsgMemory(UserModeMsg->message);
 +    if (NULL == MsgMemoryEntry)
 +    {
 +        /* Not present, no copying needed */
 +        return STATUS_SUCCESS;
 +    }
 +
 +    /* Determine required size */
 +    Size = MsgMemorySize(MsgMemoryEntry, UserModeMsg->wParam, UserModeMsg->lParam);
 +
 +    if (0 != Size)
 +    {
 +        /* Copy data if required */
 +        if (0 != (MsgMemoryEntry->Flags & MMS_FLAG_WRITE))
 +        {
 +            Status = MmCopyToCaller((PVOID) UserModeMsg->lParam, (PVOID) KernelModeMsg->lParam, Size);
 +            if (! NT_SUCCESS(Status))
 +            {
 +                ERR("Failed to copy message from kernel: invalid usermode lParam buffer\n");
 +                ExFreePool((PVOID) KernelModeMsg->lParam);
 +                return Status;
 +            }
 +        }
 +
 +        ExFreePool((PVOID) KernelModeMsg->lParam);
 +    }
 +
 +    return STATUS_SUCCESS;
 +}
 +
 +//
 +// Wakeup any thread/process waiting on idle input.
 +//
 +VOID FASTCALL
 +IdlePing(VOID)
 +{
 +   PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
 +   PTHREADINFO pti;
 +
 +   pti = PsGetCurrentThreadWin32Thread();
 +
 +   if ( pti )
 +   {
 +      pti->pClientInfo->cSpins = 0; // Reset spins.
 +
 +      if ( pti->pDeskInfo && pti == gptiForeground )
 +      {
 +         if ( pti->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) ||
 +              pti->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_FOREGROUNDIDLE) )
 +         {
 +            co_HOOK_CallHooks(WH_FOREGROUNDIDLE,HC_ACTION,0,0);
 +         }
 +      }
 +   }
 +
 +   TRACE("IdlePing ppi %p\n", ppi);
 +   if ( ppi && ppi->InputIdleEvent )
 +   {
 +      TRACE("InputIdleEvent\n");
 +      KeSetEvent( ppi->InputIdleEvent, IO_NO_INCREMENT, FALSE);
 +   }
 +}
 +
 +VOID FASTCALL
 +IdlePong(VOID)
 +{
 +   PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
 +
 +   TRACE("IdlePong ppi %p\n", ppi);
 +   if ( ppi && ppi->InputIdleEvent )
 +   {
 +      KeClearEvent(ppi->InputIdleEvent);
 +   }
 +}
 +
 +UINT FASTCALL
 +GetWakeMask(UINT first, UINT last )
 +{
 +    UINT mask = QS_POSTMESSAGE | QS_SENDMESSAGE;  /* Always selected */
 +
 +    if (first || last)
 +    {
 +        if ((first <= WM_KEYLAST) && (last >= WM_KEYFIRST)) mask |= QS_KEY;
 +        if ( ((first <= WM_MOUSELAST) && (last >= WM_MOUSEFIRST)) ||
 +             ((first <= WM_NCMOUSELAST) && (last >= WM_NCMOUSEFIRST)) ) mask |= QS_MOUSE;
 +        if ((first <= WM_TIMER) && (last >= WM_TIMER)) mask |= QS_TIMER;
 +        if ((first <= WM_SYSTIMER) && (last >= WM_SYSTIMER)) mask |= QS_TIMER;
 +        if ((first <= WM_PAINT) && (last >= WM_PAINT)) mask |= QS_PAINT;
 +    }
 +    else mask = QS_ALLINPUT;
 +
 +    return mask;
 +}
 +
 +static VOID FASTCALL
 +IntCallWndProc( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
 +{
 +    BOOL SameThread = FALSE;
 +    CWPSTRUCT CWP;
 +
 +    if (Window->head.pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread()))
 +        SameThread = TRUE;
 +
 +    CWP.hwnd    = hWnd;
 +    CWP.message = Msg;
 +    CWP.wParam  = wParam;
 +    CWP.lParam  = lParam;
 +    co_HOOK_CallHooks( WH_CALLWNDPROC, HC_ACTION, SameThread, (LPARAM)&CWP );
 +}
 +
 +static VOID FASTCALL
 +IntCallWndProcRet ( PWND Window, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *uResult)
 +{
 +    BOOL SameThread = FALSE;
 +    CWPRETSTRUCT CWPR;
 +
 +    if (Window->head.pti == ((PTHREADINFO)PsGetCurrentThreadWin32Thread()))
 +        SameThread = TRUE;
 +
 +    CWPR.hwnd    = hWnd;
 +    CWPR.message = Msg;
 +    CWPR.wParam  = wParam;
 +    CWPR.lParam  = lParam;
 +    CWPR.lResult = uResult ? (*uResult) : 0;
 +    co_HOOK_CallHooks( WH_CALLWNDPROCRET, HC_ACTION, SameThread, (LPARAM)&CWPR );
 +}
 +
 +static LRESULT handle_internal_message( PWND pWnd, UINT msg, WPARAM wparam, LPARAM lparam )
 +{
 +    LRESULT lRes;
 +    USER_REFERENCE_ENTRY Ref;
 +//    PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
 +
 +    if (!pWnd ||
 +         pWnd == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
 +         pWnd == UserGetMessageWindow() )  // pWnd->fnid == FNID_MESSAGEWND
 +       return 0;
 +
 +    TRACE("Internal Event Msg %p hWnd 0x%x\n",msg,pWnd->head.h);
 +
 +    switch(msg)
 +    {
 +       case WM_ASYNC_SHOWWINDOW:
 +          return co_WinPosShowWindow( pWnd, wparam );
 +       case WM_ASYNC_SETWINDOWPOS:
 +       {
 +          PWINDOWPOS winpos = (PWINDOWPOS)lparam;
 +          if (!winpos) return 0;
 +          lRes = co_WinPosSetWindowPos( pWnd,
 +                                        winpos->hwndInsertAfter,
 +                                        winpos->x,
 +                                        winpos->y,
 +                                        winpos->cx,
 +                                        winpos->cy,
 +                                        winpos->flags);
 +          ExFreePoolWithTag(winpos, USERTAG_SWP);
 +          return lRes;
 +       }
 +       case WM_ASYNC_SETACTIVEWINDOW:
 +       {
 +          PWND Window = (PWND)wparam;
 +          if (wparam) UserRefObjectCo(Window, &Ref);
 +          lRes = (LRESULT)co_IntSetActiveWindow(Window,(BOOL)lparam,TRUE,TRUE);
 +          if (wparam) UserDerefObjectCo(Window);
 +          return lRes;
 +       }
 +    }
 +    return 0;
 +}
 +
 +LRESULT FASTCALL
 +IntDispatchMessage(PMSG pMsg)
 +{
 +    LARGE_INTEGER TickCount;
 +    LONG Time;
 +    LRESULT retval = 0;
 +    PTHREADINFO pti;
 +    PWND Window = NULL;
 +    BOOL DoCallBack = TRUE;
 +
 +    if (pMsg->hwnd)
 +    {
 +        Window = UserGetWindowObject(pMsg->hwnd);
 +        if (!Window) return 0;
 +    }
 +
 +    pti = PsGetCurrentThreadWin32Thread();
 +
 +    if ( Window && Window->head.pti != pti)
 +    {
 +       EngSetLastError( ERROR_MESSAGE_SYNC_ONLY );
 +       return 0;
 +    }
 +
 +    if (((pMsg->message == WM_SYSTIMER) ||
 +         (pMsg->message == WM_TIMER)) &&
 +         (pMsg->lParam) )
 +    {
 +        if (pMsg->message == WM_TIMER)
 +        {
 +            if (ValidateTimerCallback(pti,pMsg->lParam))
 +            {
 +                KeQueryTickCount(&TickCount);
 +                Time = MsqCalculateMessageTime(&TickCount);
 +                retval = co_IntCallWindowProc((WNDPROC)pMsg->lParam,
 +                                              TRUE,
 +                                              pMsg->hwnd,
 +                                              WM_TIMER,
 +                                              pMsg->wParam,
 +                                              (LPARAM)Time,
 +            &n