--- /dev/null
- 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);
+ }
+}
--- /dev/null
- 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);
+}
--- /dev/null
- 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
--- /dev/null
- 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 */
--- /dev/null
- 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;
+}
--- /dev/null
- 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
--- /dev/null
- 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;
+}
+
--- /dev/null
- 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 */
--- /dev/null
- 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++;
+ }
+}
--- /dev/null
- 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;
+}
--- /dev/null
- 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);
+}
+
+
+
+
+
--- /dev/null
- #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 */
--- /dev/null
- 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 */
--- /dev/null
- 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