Fixing ICE in gcc is no fun.
svn path=/branches/powerpc/; revision=24443
HKLM,"SYSTEM\CurrentControlSet\Services\Ndis","Start",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\Ndis","Type",0x00010001,0x00000001
- ; PCI driver
- HKLM,"SYSTEM\CurrentControlSet\Enum\Root\*PNP0A03\0000","HardwareID",0x00010000,"*PNP0A03"
- HKLM,"SYSTEM\CurrentControlSet\Enum\Root\*PNP0A03\0000","DeviceDesc",0x00000000,"PCI bus"
- HKLM,"SYSTEM\CurrentControlSet\Enum\Root\*PNP0A03\0000\LogConf","BasicConfigVector",0x000A0001, \
- 40,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, \
- 01,00,00,00,01,00,01,00,01,00,00,00, \
- 00,06,00,00,00,00,00,00,01,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
-
- ; We need the PCI bus to be installed at 3rd boot to enumerate display cards and to
- ; not have the "CsrServerInitialization: failed to initialize video (Status=c0000001)"
- ; error when a custom driver (as the VMware one) is installed. At the moment,
- ; StartServiceW is not implemented, so PlugPlay service can't start during
- ; second stage setup. => We have to code PCI bus parameters it in registry...
- HKLM,"SYSTEM\CurrentControlSet\Enum\Root\*PNP0A03\0000","Service",0x00000000,"pci"
- HKLM,"SYSTEM\CurrentControlSet\Services\PCI","ErrorControl",0x00010001,0x00000003
- HKLM,"SYSTEM\CurrentControlSet\Services\PCI","Group",0x00000000,"Boot Bus Extender"
- HKLM,"SYSTEM\CurrentControlSet\Services\PCI","ImagePath",0x00020000,"system32\drivers\pci.sys"
- HKLM,"SYSTEM\CurrentControlSet\Services\PCI","Start",0x00010001,0x00000000
- HKLM,"SYSTEM\CurrentControlSet\Services\PCI","Type",0x00010001,0x00000001
- HKLM,"SYSTEM\CurrentControlSet\Services\PCI","Tag",0x00010001,0x00000002
-
- ; ACPI bus
- HKLM,"SYSTEM\CurrentControlSet\Enum\Root\*PNP0C08\0000","HardwareID",0x00010000,"*PNP0C08"
- HKLM,"SYSTEM\CurrentControlSet\Enum\Root\*PNP0C08\0000","DeviceDesc",0x00000000,"ACPI bus"
- HKLM,"SYSTEM\CurrentControlSet\Enum\Root\*PNP0C08\0000","Service",0x00000000,"acpi"
--; NetLogon
--HKLM,"SYSTEM\CurrentControlSet\Services\NetLogon","ErrorControl",0x00010001,0x00000001
--HKLM,"SYSTEM\CurrentControlSet\Services\Netlogon","ImagePath",0x00020000,"%SystemRoot%\system32\lsass.exe"
--HKLM,"SYSTEM\CurrentControlSet\Services\NetLogon","Start",0x00010001,0x00000003
--HKLM,"SYSTEM\CurrentControlSet\Services\Netlogon","Type",0x00010001,0x00000020
---
; Named Pipe filesystem driver
HKLM,"SYSTEM\CurrentControlSet\Services\Npfs","ErrorControl",0x00010001,0x00000000
HKLM,"SYSTEM\CurrentControlSet\Services\Npfs","Group",0x00000000,"File System"
; Base files
base\applications\cacls\cacls.exe 1
base\applications\calc\calc.exe 1
--base\applications\cmdutils\find\find.exe 1
--base\applications\cmdutils\more\more.exe 1
base\applications\control\control.exe 1
base\applications\devmgr\devmgrapp.exe 1
+ base\applications\devmgmt\devmgmt.exe 1
base\applications\games\solitaire\sol.exe 1
base\applications\games\winemine\winemine.exe 1
base\applications\getfirefox\getfirefox.exe 1
dll\win32\shlwapi\shlwapi.dll 1
dll\win32\smdll\smdll.dll 1
dll\win32\syssetup\syssetup.dll 1
--dll\win32\twain_32\twain_32.dll 1
++dll\win32\twain\twain_32.dll 1
+ dll\win32\ufat\ufat.dll 1
+ dll\win32\ufatx\ufatx.dll 1 optional
dll\win32\urlmon\urlmon.dll 1
dll\win32\user32\user32.dll 1
dll\win32\userenv\userenv.dll 1
- ; Install to \Device\Harddisk0\Partition1\ReactOS
+ ; In order to get unattended setup working:
+ ; 1. Copy unattend.inf.sample to unattend.inf, adjust as needed
+ ; 2. Uncomment the line in bootdata.rbuild to include it into bootcd
+
[Unattend]
Signature = "$ReactOS$"
+
+ ; yes - unattend setup enabled
+ ; no - unattend setup disabled
+ UnattendSetupEnabled = yes
+
+ ; Install to \Device\Harddisk0\Partition1\ReactOS
DestinationDiskNumber = 0
DestinationPartitionNumber = 1
- InstallationDirectory=ReactOS
+ InstallationDirectory=ReactOS
+
+ ; MBRInstallType=0 skips MBR installation
+ ; MBRInstallType=1 install MBR on floppy
+ ; MBRInstallType=2 install MBR on hdd
+ MBRInstallType=2
+
+ FullName="MyName"
+ ;OrgName="MyOrg"
+ ComputerName="MYCOMPUTERNAME";
+ AdminPassword="MyPassword"
+
+ ; TimeZone is set GMT as default
+ TimeZoneIndex=85
+
+ ; enable this setting to disable daylight saving changes
--; DisableAutoDaylightTimeSet = 1
+++; DisableAutoDaylightTimeSet = 1
+++
--- /dev/null
--- /dev/null
- font_char BootDigits[16] = {
- " XXXXX "
- "X X "
- "X x X "
- "X X X "
- "X X "
- " XXXXX "
- " ",
- " XX "
- " XXX "
- " XX "
- " XX "
- " XX "
- " XX "
- " ",
- " XXXX "
- " X X "
- " XX "
- " XX "
- " XX "
- " XXXXXX "
- " ",
- " XXXX "
- " X X "
- " XX "
- " X "
- " X X "
- " XXXX "
- " ",
- " X X "
- " X X "
- " XXXXXX "
- " X "
- " X "
- " X "
- " ",
- " XXXXXX "
- " X "
- " XXXXX "
- " X "
- " X "
- " XXXXX "
- " ",
- " XXXXX "
- " X "
- " XXXXX "
- " X X "
- " X X "
- " XXXX "
- " ",
- " XXXXXX "
- " XX "
- " XX "
- " XXXXX "
- " XX "
- " XX "
- " ",
- " XXXX "
- " X X "
- " XXXX "
- " X X "
- " X X "
- " XXXX "
- " ",
- " XXXX "
- " X X "
- " XXXXXX "
- " X X "
- " X X "
- " X X "
- " ",
- " XXXXX "
- " X X "
- " XXXXX "
- " X X "
- " X X "
- " XXXXX "
- " ",
- " XXXX "
- " X X "
- " X "
- " X "
- " X X "
- " XXXX "
- " ",
- " XXXXXX "
- " X "
- " XXXX "
- " X "
- " X "
- " XXXXXX "
- " ",
- " XXXXXX "
- " X "
- " XXXX "
- " X "
- " X "
- " X "
- " "
- };
-
++#ifndef _FREELDR_ARCH_COMPAT_H
++#define _FREELDR_ARCH_COMPAT_H
++
++#define __init
++#define __initdata
++
++#define SPRN_MSSCR0 0x3f6 /* Memory Subsystem Control Register 0 */
++#define SPRN_MSSSR0 0x3f7 /* Memory Subsystem Status Register 1 */
++#define SPRN_LDSTCR 0x3f8 /* Load/Store control register */
++#define SPRN_LDSTDB 0x3f4 /* */
++#define SPRN_LR 0x008 /* Link Register */
++#ifndef SPRN_PIR
++#define SPRN_PIR 0x3FF /* Processor Identification Register */
++#endif
++#define SPRN_PTEHI 0x3D5 /* 981 7450 PTE HI word (S/W TLB load) */
++#define SPRN_PTELO 0x3D6 /* 982 7450 PTE LO word (S/W TLB load) */
++#define SPRN_PURR 0x135 /* Processor Utilization of Resources Reg */
++#define SPRN_PVR 0x11F /* Processor Version Register */
++#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
++#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
++#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
++#define SPRN_ASR 0x118 /* Address Space Register */
++#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
++#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
++#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
++#define SPRN_SPRG2 0x112 /* Special Purpose Register General 2 */
++#define SPRN_SPRG3 0x113 /* Special Purpose Register General 3 */
++#define SPRN_SPRG4 0x114 /* Special Purpose Register General 4 */
++#define SPRN_SPRG5 0x115 /* Special Purpose Register General 5 */
++#define SPRN_SPRG6 0x116 /* Special Purpose Register General 6 */
++#define SPRN_SPRG7 0x117 /* Special Purpose Register General 7 */
++#define SPRN_SRR0 0x01A /* Save/Restore Register 0 */
++#define SPRN_SRR1 0x01B /* Save/Restore Register 1 */
++#ifndef SPRN_SVR
++#define SPRN_SVR 0x11E /* System Version Register */
++#endif
++#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */
++/* these bits were defined in inverted endian sense originally, ugh, confusing */
++
++/* Values for PP (assumes Ks=0, Kp=1) */
++#define PP_RWXX 0 /* Supervisor read/write, User none */
++#define PP_RWRX 1 /* Supervisor read/write, User read */
++#define PP_RWRW 2 /* Supervisor read/write, User read/write */
++#define PP_RXRX 3 /* Supervisor read, User read */
++
++/* Block size masks */
++#define BL_128K 0x000
++#define BL_256K 0x001
++#define BL_512K 0x003
++#define BL_1M 0x007
++#define BL_2M 0x00F
++#define BL_4M 0x01F
++#define BL_8M 0x03F
++#define BL_16M 0x07F
++#define BL_32M 0x0FF
++#define BL_64M 0x1FF
++#define BL_128M 0x3FF
++#define BL_256M 0x7FF
++
++/* BAT Access Protection */
++#define BPP_XX 0x00 /* No access */
++#define BPP_RX 0x01 /* Read only */
++#define BPP_RW 0x02 /* Read/write */
++
++/* Definitions for 40x embedded chips. */
++#define _PAGE_GUARDED 0x001 /* G: page is guarded from prefetch */
++#define _PAGE_FILE 0x001 /* when !present: nonlinear file mapping */
++#define _PAGE_PRESENT 0x002 /* software: PTE contains a translation */
++#define _PAGE_NO_CACHE 0x004 /* I: caching is inhibited */
++#define _PAGE_WRITETHRU 0x008 /* W: caching is write-through */
++#define _PAGE_USER 0x010 /* matches one of the zone permission bits */
++#define _PAGE_RW 0x040 /* software: Writes permitted */
++#define _PAGE_DIRTY 0x080 /* software: dirty page */
++#define _PAGE_HWWRITE 0x100 /* hardware: Dirty & RW, set in exception */
++#define _PAGE_HWEXEC 0x200 /* hardware: EX permission */
++#define _PAGE_ACCESSED 0x400 /* software: R: page referenced */
++
++#define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */
++#define _PMD_BAD 0x802
++#define _PMD_SIZE 0x0e0 /* size field, != 0 for large-page PMD entry */
++#define _PMD_SIZE_4M 0x0c0
++#define _PMD_SIZE_16M 0x0e0
++#define PMD_PAGE_SIZE(pmdval) (1024 << (((pmdval) & _PMD_SIZE) >> 4))
++
++#define PVR_VER(pvr)(((pvr) >> 16) & 0xFFFF) /* Version field */
++
++#define KERNELBASE 0x80000000
++
++typedef unsigned char __u8;
++typedef unsigned short __u16;
++typedef unsigned int __u32;
++
++typedef struct _pci_reg_property {
++ struct {
++ int a_hi, a_mid, a_lo;
++ } addr;
++ int size_hi, size_lo;
++} pci_reg_property;
++
++void btext_drawstring(const char *c);
++void btext_drawhex(unsigned long v);
++
++void *ioremap(__u32 phys, __u32 size);
++void iounmap(void *logical);
++
++__u32 GetPVR();
++
++#endif/*_FREELDR_ARCH_COMPAT_H*/
#include "freeldr.h"
#include "machine.h"
#include "of.h"
- #include "compat.h"
++#include "mmu.h"
++#include "ppcboot.h"
+++#include "compat.h"
--extern void BootMain( char * );
--extern char *GetFreeLoaderVersionString();
++extern void BootMain( LPSTR CmdLine );
++extern PCHAR GetFreeLoaderVersionString();
++extern ULONG CacheSizeLimit;
of_proxy ofproxy;
void *PageDirectoryStart, *PageDirectoryEnd;
--static int chosen_package, stdin_handle, part_handle = -1;
++static int chosen_package, stdin_handle, part_handle = -1, kernel_mem = 0;
+++int mmu_handle = 0;
BOOLEAN AcpiPresent = FALSE;
char BootPath[0x100] = { 0 }, BootPart[0x100] = { 0 }, CmdLine[0x100] = { 0 };
jmp_buf jmp;
*/
ULONG PpcGetMemoryMap( PBIOS_MEMORY_MAP BiosMemoryMap,
ULONG MaxMemoryMapSize ) {
-- printf("GetMemoryMap(chosen=%x)\n", chosen_package);
++ int i, memhandle, returned, total = 0, slots = 0;
++ int memdata[0x40];
-- BiosMemoryMap[0].Type = BiosMemoryUsable;
-- BiosMemoryMap[0].BaseAddress = 0;
-- BiosMemoryMap[0].Length = 32 * 1024 * 1024; /* Assume 32 meg for now */
++ printf("PpcGetMemoryMap(%d)\n", MaxMemoryMapSize);
-- printf( "Returning memory map (%dk total)\n",
-- (int)BiosMemoryMap[0].Length / 1024 );
++ memhandle = ofw_finddevice("/memory");
-- return 1;
++ returned = ofw_getprop(memhandle, "available",
++ (char *)memdata, sizeof(memdata));
++
++ printf("Returned data: %d\n", returned);
++ if( returned == -1 ) {
++ printf("getprop /memory[@reg] failed\n");
++ return 0;
++ }
++
++ for( i = 0; i < returned; i++ ) {
++ printf("%x ", memdata[i]);
++ }
++ printf("\n");
++
++ for( i = 0; i < returned / 2; i++ ) {
- BiosMemoryMap[slots].Type = MEMTYPE_USABLE;
+++ BiosMemoryMap[slots].Type = 1/*MEMTYPE_USABLE*/;
++ BiosMemoryMap[slots].BaseAddress = REV(memdata[i*2]);
++ BiosMemoryMap[slots].Length = REV(memdata[i*2+1]);
++ printf("MemoryMap[%d] = (%x:%x)\n",
++ i,
++ (int)BiosMemoryMap[slots].BaseAddress,
++ (int)BiosMemoryMap[slots].Length);
++
++ /* Hack for pearpc */
++ if( kernel_mem ) {
++ BiosMemoryMap[slots].Length = kernel_mem * 1024;
++ ofw_claim((int)BiosMemoryMap[slots].BaseAddress,
++ (int)BiosMemoryMap[slots].Length,
++ 0x1000);
++ total += BiosMemoryMap[slots].Length;
++ slots++;
++ break;
++ /* Normal way */
++ } else if( BiosMemoryMap[slots].Length &&
++ ofw_claim((int)BiosMemoryMap[slots].BaseAddress,
++ (int)BiosMemoryMap[slots].Length,
++ 0x1000) ) {
++ total += BiosMemoryMap[slots].Length;
++ slots++;
++ }
++ }
++
++ printf( "Returning memory map (%dk total)\n", total / 1024 );
++
++ return slots;
}
/* Strategy:
printf("PpcHwDetect\n");
}
--typedef unsigned int uint32_t;
++BOOLEAN PpcDiskNormalizeSystemPath(char *SystemPath, unsigned Size) {
++ CHAR BootPath[256];
++ ULONG PartitionNumber;
++ ULONG DriveNumber;
++ PARTITION_TABLE_ENTRY PartEntry;
++ char *p;
++
++ if (!DissectArcPath(SystemPath, BootPath, &DriveNumber, &PartitionNumber))
++ {
++ return FALSE;
++ }
++
++ if (0 != PartitionNumber)
++ {
++ return TRUE;
++ }
++
++ if (! DiskGetActivePartitionEntry(DriveNumber,
++ &PartEntry,
++ &PartitionNumber) ||
++ PartitionNumber < 1 || 9 < PartitionNumber)
++ {
++ return FALSE;
++ }
++
++ p = SystemPath;
++ while ('\0' != *p && 0 != _strnicmp(p, "partition(", 10)) {
++ p++;
++ }
++ p = strchr(p, ')');
++ if (NULL == p || '0' != *(p - 1)) {
++ return FALSE;
++ }
++ *(p - 1) = '0' + PartitionNumber;
++ return TRUE;
++}
++
++extern int _bss;
++typedef unsigned int uint32_t;
void PpcInit( of_proxy the_ofproxy ) {
- int len, stdin_handle_chosen;
-- int len;
+++ int len, stdin_handle_chosen, mmu_handle_chosen;
ofproxy = the_ofproxy;
++ //SetPhys(0x900, (19 << 26) | (50 << 1));
++
chosen_package = ofw_finddevice( "/chosen" );
ofw_getprop( chosen_package, "stdin",
-- &stdin_handle, sizeof(stdin_handle) );
++ (char *)&stdin_handle_chosen, sizeof(stdin_handle_chosen) );
+++ ofw_getprop( chosen_package, "mmu",
+++ (char *)&mmu_handle_chosen, sizeof(mmu_handle_chosen) );
-- stdin_handle = REV(stdin_handle);
++ stdin_handle = REV(stdin_handle_chosen);
+++ mmu_handle = REV(mmu_handle_chosen);
MachVtbl.ConsPutChar = PpcPutChar;
MachVtbl.ConsKbHit = PpcConsKbHit;
void ChainLoadBiosBootSectorCode() {
ofw_exit();
}
+++
+++void DbgBreakPoint() {
+++ ofw_exit();
+++}
*/
#include <freeldr.h>
--#include <internal/powerpc/ke.h>
++#include <of_call.h>
++#include "ppcboot.h"
++#include "mmu.h"
++#include "compat.h"
+++#include "font.h"
#define NDEBUG
#include <debug.h>
//
// Lock the sectors into the cache
//
--- CacheBlock->LockedInCache = TRUE;
+++ CacheBlock->LockedInCache = FALSE; //TRUE;
}
return TRUE;
*/
#include <freeldr.h>
+++#ifdef _M_PPC
+++#include "of.h"
+++#endif
#define NDEBUG
#include <debug.h>
{
ULONG PagesNeeded;
ULONG FirstFreePageFromEnd;
--- PVOID MemPointer;
+++ PVOID MemPointer = NULL;
if (MemorySize == 0)
{
// then return NULL
if (FreePagesInLookupTable < PagesNeeded)
{
- DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
-- DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
--- UiMessageBoxCritical("Memory allocation failed: out of memory.");
- while(1);
--- return NULL;
+++#ifdef _M_PPC
+++ printf("Allocating %d bytes directly ...\n", MemorySize);
+++ MemPointer = (PVOID)ofw_claim(0,MemorySize,MM_PAGE_SIZE);
+++#endif
+++ if( !MemPointer )
+++ {
+++ DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
+++ UiMessageBoxCritical("Memory allocation failed: out of memory.");
+++ while(1);
+++ return NULL;
+++ }
+++ else
+++ return MemPointer;
}
- FirstFreePageFromEnd = MmFindAvailablePagesFromEnd(PageLookupTableAddress, TotalPagesInLookupTable, PagesNeeded);
+ FirstFreePageFromEnd = MmFindAvailablePages(PageLookupTableAddress, TotalPagesInLookupTable, PagesNeeded, AllocateFromEnd);
- if (FirstFreePageFromEnd == 0)
+ if (FirstFreePageFromEnd == (ULONG)-1)
{
- DbgPrint((DPRINT_MEMORY, "Memory allocation failed. Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
UiMessageBoxCritical("Memory allocation failed: out of memory.");
return NULL;
}
--- /dev/null
+ /*
+ * PROJECT: EFI Windows Loader
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: freeldr/winldr/conversion.c
+ * PURPOSE: Physical <-> Virtual addressing mode conversions
+ * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
+ */
+
+ /* INCLUDES ***************************************************************/
+
+ #include <freeldr.h>
+
+++#ifdef _M_PPC
+++#include <of.h>
+++#include <mmu.h>
+++#endif
+ //#include <ndk/ldrtypes.h>
+
+ #define NDEBUG
+ #include <debug.h>
+
+ /* FUNCTIONS **************************************************************/
+
+ /* Arch-specific addresses translation implementation */
+ PVOID
+ VaToPa(PVOID Va)
+ {
+++#ifdef _M_IX86
+ return (PVOID)((ULONG_PTR)Va & ~KSEG0_BASE);
+++#elif defined(_M_PPC)
+++ return (PVOID)PpcVirt2phys((ULONG_PTR)Va,0);
+++#endif
+ }
+
+ PVOID
+ PaToVa(PVOID Pa)
+ {
+++#ifdef _M_IX86
+ return (PVOID)((ULONG_PTR)Pa | KSEG0_BASE);
+++#elif defined(_M_PPC)
+++ return (PVOID)ofw_phys2virt(mmu_handle,0,(ULONG_PTR)Pa,0);
+++#endif
+ }
+
+ VOID
+ List_PaToVa(LIST_ENTRY *ListEntry)
+ {
+ LIST_ENTRY *ListHead = ListEntry;
+ LIST_ENTRY *Next = ListEntry->Flink;
+ LIST_ENTRY *NextPA;
+
+ //Print(L"\n\nList_Entry: %X, First Next: %X\n", ListEntry, Next);
+ //
+ // Walk through the whole list
+ //
+ if (Next != NULL)
+ {
+ while (Next != PaToVa(ListHead))
+ {
+ NextPA = VaToPa(Next);
+ //Print(L"Current: %X, Flink: %X, Blink: %X\n", Next, NextPA->Flink, NextPA->Blink);
+
+ NextPA->Flink = PaToVa((PVOID)NextPA->Flink);
+ NextPA->Blink = PaToVa((PVOID)NextPA->Blink);
+
+ //Print(L"After converting Flink: %X, Blink: %X\n", NextPA->Flink, NextPA->Blink);
+
+ Next = NextPA->Flink;
+ }
+
+ //
+ // Finally convert first Flink/Blink
+ //
+ ListEntry->Flink = PaToVa((PVOID)ListEntry->Flink);
+ if (ListEntry->Blink)
+ ListEntry->Blink = PaToVa((PVOID)ListEntry->Blink);
+ }
+ }
+
+ // This function converts only Child->Child, and calls itself for each Sibling
+ VOID
+ ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start)
+ {
+ PCONFIGURATION_COMPONENT_DATA Child;
+ PCONFIGURATION_COMPONENT_DATA Sibling;
+
+ DbgPrint((DPRINT_WINDOWS, "ConvertConfigToVA(Start 0x%X)", Start));
+ Child = Start;
+
+ while (Child != NULL)
+ {
+ if (Child->ConfigurationData)
+ Child->ConfigurationData = PaToVa(Child->ConfigurationData);
+
+ if (Child->Child)
+ Child->Child = PaToVa(Child->Child);
+
+ if (Child->Parent)
+ Child->Parent = PaToVa(Child->Parent);
+
+ if (Child->Sibling)
+ Child->Sibling = PaToVa(Child->Sibling);
+
+ DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d", Child, Child->ComponentEntry.Class));
+
+ // If the child has a sibling list, then search the sibling list
+ // for an entry that matches the specified class, type, and key.
+ Sibling = Child->Sibling;
+ while (Sibling != NULL)
+ {
+ if (Sibling->ConfigurationData)
+ Sibling->ConfigurationData = PaToVa(Sibling->ConfigurationData);
+
+ if (Sibling->Child)
+ Sibling->Child = PaToVa(Sibling->Child);
+
+ if (Sibling->Parent)
+ Sibling->Parent = PaToVa(Sibling->Parent);
+
+ if (Sibling->Sibling)
+ Sibling->Sibling = PaToVa(Sibling->Sibling);
+
+ DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d", Sibling, Sibling->ComponentEntry.Class));
+
+ // If the sibling has a child tree, then search the child tree
+ // for an entry that matches the specified class, type, and key.
+ if (VaToPa(Sibling->Child) != NULL)
+ ConvertConfigToVA(VaToPa(Sibling->Child));
+
+ Sibling = VaToPa(Sibling->Sibling);
+ }
+
+ Child = VaToPa(Child->Child);
+ }
+ }
--- /dev/null
--\r
+ /*\r
+ * PROJECT: EFI Windows Loader\r
+ * LICENSE: GPL - See COPYING in the top level directory\r
+ * FILE: freeldr/winldr/wlmemory.c\r
+ * PURPOSE: Memory related routines\r
+ * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)\r
+ */\r
+ \r
+ /* INCLUDES ***************************************************************/\r
+ \r
+ #include <freeldr.h>\r
+ \r
+ #include <ndk/asm.h>\r
+ \r
+ #define NDEBUG\r
+ #include <debug.h>\r
+ \r
+ // This is needed because headers define wrong one for ReactOS\r
+ #undef KIP0PCRADDRESS\r
+ #define KIP0PCRADDRESS 0xffdff000\r
+ \r
+ //\r
+ // This is the zone which is used by the OS loader\r
+ //\r
+ #define LOADER_HIGH_ZONE ((16*1024*1024) >> MM_PAGE_SHIFT) //16Mb page\r
+ \r
+ #define HYPER_SPACE_ENTRY 0x300\r
+ \r
+ //TODO: Check if this is correct\r
+ PCHAR MemTypeDesc[] = {\r
+ "ExceptionBlock ",\r
+ "SystemBlock ",\r
+ "Free ",\r
+ "Bad ",\r
+ "LoadedProgram ",\r
+ "FirmwareTemporary ",\r
+ "FirmwarePermanent ",\r
+ "OsloaderHeap ",\r
+ "OsloaderStack ",\r
+ "SystemCode ",\r
+ "HalCode ",\r
+ "BootDriver ",\r
+ "ConsoleInDriver ",\r
+ "ConsoleOutDriver ",\r
+ "StartupDpcStack ",\r
+ "StartupKernelStack",\r
+ "StartupPanicStack ",\r
+ "StartupPcrPage ",\r
+ "StartupPdrPage ",\r
+ "RegistryData ",\r
+ "MemoryData ",\r
+ "NlsData ",\r
+ "SpecialMemory ",\r
+ "BBTMemory ",\r
+ "Maximum "\r
+ };\r
+ \r
+ VOID\r
+ WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);\r
+ \r
+ \r
+ VOID\r
+ MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ UINT64 BasePage,\r
+ UINT64 PageCount,\r
+ ULONG Type);\r
+ VOID\r
+ WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor);\r
+ \r
+ VOID\r
+ WinLdrRemoveDescriptor(IN PMEMORY_ALLOCATION_DESCRIPTOR Descriptor);\r
+ \r
+ VOID\r
+ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss);\r
+ \r
+ // This is needed only for SetProcessorContext routine\r
+ #pragma pack(2)\r
+ typedef struct\r
+ {\r
+ USHORT Limit;\r
+ ULONG Base;\r
+ } GDTIDT;\r
+ #pragma pack(4)\r
+ \r
+ // this is needed for new IDT filling\r
+ #if 0\r
+ extern ULONG_PTR i386DivideByZero;\r
+ extern ULONG_PTR i386DebugException;\r
+ extern ULONG_PTR i386NMIException;\r
+ extern ULONG_PTR i386Breakpoint;\r
+ extern ULONG_PTR i386Overflow;\r
+ extern ULONG_PTR i386BoundException;\r
+ extern ULONG_PTR i386InvalidOpcode;\r
+ extern ULONG_PTR i386FPUNotAvailable;\r
+ extern ULONG_PTR i386DoubleFault;\r
+ extern ULONG_PTR i386CoprocessorSegment;\r
+ extern ULONG_PTR i386InvalidTSS;\r
+ extern ULONG_PTR i386SegmentNotPresent;\r
+ extern ULONG_PTR i386StackException;\r
+ extern ULONG_PTR i386GeneralProtectionFault;\r
+ extern ULONG_PTR i386PageFault; // exc 14\r
+ extern ULONG_PTR i386CoprocessorError; // exc 16\r
+ extern ULONG_PTR i386AlignmentCheck; // exc 17\r
+++#else\r
+++typedef unsigned long long HARDWARE_PTE, *PHARDWARE_PTE;\r
+ #endif\r
+ \r
+ /* GLOBALS ***************************************************************/\r
+ \r
+ PHARDWARE_PTE PDE;\r
+ PHARDWARE_PTE HalPT;\r
+ \r
+ PUCHAR PhysicalPageTablesBuffer;\r
+ PUCHAR KernelPageTablesBuffer;\r
+ ULONG PhysicalPageTables;\r
+ ULONG KernelPageTables;\r
+ \r
+ MEMORY_ALLOCATION_DESCRIPTOR Mad[1024];\r
+ ULONG MadCount = 0;\r
+ \r
+ \r
+ /* FUNCTIONS **************************************************************/\r
+ \r
+ BOOLEAN\r
+ MempAllocatePageTables()\r
+ {\r
+++#ifdef _M_IX86\r
+ ULONG NumPageTables, TotalSize;\r
+ PUCHAR Buffer;\r
+ // It's better to allocate PDE + PTEs contigiuos\r
+ \r
+ // Max number of entries = MaxPageNum >> 10\r
+ // FIXME: This is a number to describe ALL physical memory\r
+ // and windows doesn't expect ALL memory mapped...\r
+ NumPageTables = (GetSystemMemorySize() >> MM_PAGE_SHIFT) >> 10;\r
+ \r
+ DbgPrint((DPRINT_WINDOWS, "NumPageTables = %d\n", NumPageTables));\r
+ \r
+ // Allocate memory block for all these things:\r
+ // PDE, HAL mapping page table, physical mapping, kernel mapping\r
+ TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE;\r
+ Buffer = MmAllocateMemory(TotalSize);\r
+ \r
+ if (Buffer == NULL)\r
+ {\r
+ UiMessageBox("Impossible to allocate memory block for page tables!");\r
+ return FALSE;\r
+ }\r
+ \r
+ // Zero all this memory block\r
+ RtlZeroMemory(Buffer, TotalSize);\r
+ \r
+ // Set up pointers correctly now\r
+ PDE = (PHARDWARE_PTE)Buffer;\r
+ \r
+ // Map the page directory at 0xC0000000 (maps itself)\r
+ PDE[HYPER_SPACE_ENTRY].PageFrameNumber = (ULONG)PDE >> MM_PAGE_SHIFT;\r
+ PDE[HYPER_SPACE_ENTRY].Valid = 1;\r
+ PDE[HYPER_SPACE_ENTRY].Write = 1;\r
+ \r
+ // The last PDE slot is allocated for HAL's memory mapping (Virtual Addresses 0xFFC00000 - 0xFFFFFFFF)\r
+ HalPT = (PHARDWARE_PTE)&Buffer[MM_PAGE_SIZE*1];\r
+ \r
+ // Map it\r
+ PDE[1023].PageFrameNumber = (ULONG)HalPT >> MM_PAGE_SHIFT;\r
+ PDE[1023].Valid = 1;\r
+ PDE[1023].Write = 1;\r
+ \r
+ // Store pointers to the tables for easier access\r
+ PhysicalPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2];\r
+ KernelPageTablesBuffer = PhysicalPageTablesBuffer + NumPageTables*MM_PAGE_SIZE;\r
+ \r
+ // Zero counters of page tables used\r
+ PhysicalPageTables = 0;\r
+ KernelPageTables = 0;\r
--\r
+++#endif\r
+ return TRUE;\r
+ }\r
+ \r
+ VOID\r
+ MempAllocatePTE(ULONG Entry, PHARDWARE_PTE *PhysicalPT, PHARDWARE_PTE *KernelPT)\r
+ {\r
+ //Print(L"Creating PDE Entry %X\n", Entry);\r
+ \r
+ // Identity mapping\r
+++#ifdef _M_IX86\r
+ *PhysicalPT = (PHARDWARE_PTE)&PhysicalPageTablesBuffer[PhysicalPageTables*MM_PAGE_SIZE];\r
+ PhysicalPageTables++;\r
+ \r
+ PDE[Entry].PageFrameNumber = (ULONG)*PhysicalPT >> MM_PAGE_SHIFT;\r
+ PDE[Entry].Valid = 1;\r
+ PDE[Entry].Write = 1;\r
+ \r
+ if (Entry+(KSEG0_BASE >> 22) > 1023)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "WARNING! Entry: %X > 1023\n", Entry+(KSEG0_BASE >> 22)));\r
+ }\r
+ \r
+ // Kernel-mode mapping\r
+ *KernelPT = (PHARDWARE_PTE)&KernelPageTablesBuffer[KernelPageTables*MM_PAGE_SIZE];\r
+ KernelPageTables++;\r
+ \r
+ PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber = ((ULONG)*KernelPT >> MM_PAGE_SHIFT);\r
+ PDE[Entry+(KSEG0_BASE >> 22)].Valid = 1;\r
+ PDE[Entry+(KSEG0_BASE >> 22)].Write = 1;\r
+++#endif\r
+ }\r
+ \r
+ BOOLEAN\r
+ MempSetupPaging(IN ULONG StartPage,\r
+ IN ULONG NumberOfPages)\r
+ {\r
+++#ifdef _M_IX86\r
+ PHARDWARE_PTE PhysicalPT;\r
+ PHARDWARE_PTE KernelPT;\r
+ ULONG Entry, Page;\r
+ \r
+ //Print(L"MempSetupPaging: SP 0x%X, Number: 0x%X\n", StartPage, NumberOfPages);\r
+ \r
+ // HACK\r
+ if (StartPage+NumberOfPages >= 0x80000)\r
+ {\r
+ //\r
+ // We can't map this as it requires more than 1 PDE\r
+ // and in fact it's not possible at all ;)\r
+ //\r
+ //Print(L"skipping...\n");\r
+ return TRUE;\r
+ }\r
+ \r
+ //\r
+ // Now actually set up the page tables for identity mapping\r
+ //\r
+ for (Page=StartPage; Page < StartPage+NumberOfPages; Page++)\r
+ {\r
+ Entry = Page >> 10;\r
+ \r
+ if (((PULONG)PDE)[Entry] == 0)\r
+ {\r
+ MempAllocatePTE(Entry, &PhysicalPT, &KernelPT);\r
+ }\r
+ else\r
+ {\r
+ PhysicalPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT);\r
+ KernelPT = (PHARDWARE_PTE)(PDE[Entry+(KSEG0_BASE >> 22)].PageFrameNumber << MM_PAGE_SHIFT);\r
+ }\r
+ \r
+ if (Page == 0)\r
+ {\r
+ PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;\r
+ PhysicalPT[Page & 0x3ff].Valid = 0;\r
+ PhysicalPT[Page & 0x3ff].Write = 0;\r
+ \r
+ KernelPT[Page & 0x3ff].PageFrameNumber = Page;\r
+ KernelPT[Page & 0x3ff].Valid = 0;\r
+ KernelPT[Page & 0x3ff].Write = 0;\r
+ }\r
+ else\r
+ {\r
+ PhysicalPT[Page & 0x3ff].PageFrameNumber = Page;\r
+ PhysicalPT[Page & 0x3ff].Valid = 1;\r
+ PhysicalPT[Page & 0x3ff].Write = 1;\r
+ \r
+ KernelPT[Page & 0x3ff].PageFrameNumber = Page;\r
+ KernelPT[Page & 0x3ff].Valid = 1;\r
+ KernelPT[Page & 0x3ff].Write = 1;\r
+ }\r
+ }\r
--\r
+++#endif\r
+ return TRUE;\r
+ }\r
+ \r
+ VOID\r
+ MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ UINT64 BasePage,\r
+ UINT64 PageCount,\r
+ ULONG Type)\r
+ {\r
+++#ifdef _M_IX86\r
+ BOOLEAN Status;\r
--\r
+ //\r
+ // Check for some weird stuff at the top\r
+ //\r
+ if (BasePage + PageCount > 0xF0000)\r
+ {\r
+ //\r
+ // Just skip this, without even adding to MAD list\r
+ //\r
+ return;\r
+ }\r
+ \r
+ //\r
+ // Base page and page count are always set\r
+ //\r
+ Mad[MadCount].BasePage = BasePage;\r
+ Mad[MadCount].PageCount = PageCount;\r
+ \r
+ //\r
+ // Check if it's more than the allowed for OS loader\r
+ // if yes - don't map the pages, just add as FirmwareTemporary\r
+ //\r
+ if (BasePage + PageCount > LOADER_HIGH_ZONE)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderFirmwareTemporary;\r
+ \r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+ \r
+ Status = MempSetupPaging(BasePage, PageCount);\r
+ if (!Status)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "Error during WinLdrpSetupPaging\n"));\r
+ return;\r
+ }\r
+ return;\r
+ }\r
+ \r
+ if (BasePage == 0xFFF && PageCount == 1)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderSpecialMemory;\r
+ \r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+ \r
+ //\r
+ // Map it\r
+ //\r
+ Status = MempSetupPaging(BasePage, PageCount);\r
+ if (!Status)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n"));\r
+ return;\r
+ }\r
+ }\r
+ else if (BasePage == 0 && PageCount == 1)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderFirmwarePermanent;\r
+ \r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+ \r
+ //\r
+ // Map it\r
+ //\r
+ Status = MempSetupPaging(BasePage, PageCount);\r
+ if (!Status)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n"));\r
+ return;\r
+ }\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // Now choose memory type as usual. FIXME!!!\r
+ //\r
+ if (Type == 0)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderFree;\r
+ }\r
+ else if (Type != 0 && Type != 1)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderFirmwarePermanent;\r
+ }\r
+ else if (Type == 1)\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderSystemCode;\r
+ }\r
+ else\r
+ {\r
+ Mad[MadCount].MemoryType = LoaderFirmwarePermanent;\r
+ }\r
+ \r
+ //\r
+ // Add descriptor\r
+ //\r
+ WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]);\r
+ MadCount++;\r
+ \r
+ //\r
+ // Map it\r
+ //\r
+ Status = MempSetupPaging(BasePage, PageCount);\r
+ if (!Status)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n"));\r
+ return;\r
+ }\r
+ }\r
+++#endif\r
+ }\r
+ \r
+ BOOLEAN\r
+ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ ULONG PcrBasePage,\r
+ ULONG TssBasePage,\r
+ PVOID GdtIdt)\r
+ {\r
+++#ifdef _M_IX86\r
+ ULONG i, PagesCount;\r
+ ULONG LastPageIndex, LastPageType;\r
+ PPAGE_LOOKUP_TABLE_ITEM MemoryMap;\r
+ ULONG NoEntries;\r
+ PKTSS Tss;\r
+ \r
+ //\r
+ // Creating a suitable memory map for the Windows can be tricky, so let's\r
+ // give a few advices:\r
+ // 1) One must not map the whole available memory pages to PDE!\r
+ // Map only what's needed - 16Mb, 24Mb, 32Mb max I think,\r
+ // thus occupying 4, 6 or 8 PDE entries for identical mapping,\r
+ // the same quantity for KSEG0_BASE mapping, one more entry for\r
+ // hyperspace and one more entry for HAL physical pages mapping.\r
+ // 2) Memory descriptors must map *the whole* physical memory\r
+ // showing any memory above 16/24/32 as FirmwareTemporary\r
+ //\r
+ // 3) Overall memory blocks count must not exceed 30\r
+ //\r
+ \r
+ //\r
+ // During MmInitMachineDependent, the kernel zeroes PDE at the following address\r
+ // 0xC0300000 - 0xC03007FC\r
+ //\r
+ // Then it finds the best place for non-paged pool:\r
+ // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD\r
+ //\r
+ \r
+ // Before we start mapping pages, create a block of memory, which will contain\r
+ // PDE and PTEs\r
+ if (MempAllocatePageTables() == FALSE)\r
+ return FALSE;\r
+ \r
+ // Setup an entry for each descriptor\r
+ MemoryMap = MmGetMemoryMap(&NoEntries);\r
+ if (MemoryMap == NULL)\r
+ {\r
+ UiMessageBox("Can not retrieve the current memory map");\r
+ return FALSE;\r
+ }\r
+ \r
+ DbgPrint((DPRINT_WINDOWS, "Got memory map with %d entries\n"));\r
+ \r
+ // Construct a good memory map from what we've got\r
+ PagesCount = 1;\r
+ LastPageIndex = 0;\r
+ LastPageType = MemoryMap[0].PageAllocated;\r
+ for(i=1;i<NoEntries;i++)\r
+ {\r
+ if (MemoryMap[i].PageAllocated == LastPageType)\r
+ {\r
+ PagesCount++;\r
+ }\r
+ else\r
+ {\r
+ // Add the region\r
+ MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType);\r
+ \r
+ // Reset our counter vars\r
+ LastPageIndex = i;\r
+ LastPageType = MemoryMap[i].PageAllocated;\r
+ PagesCount = 1;\r
+ }\r
+ }\r
+ \r
+ DbgPrint((DPRINT_WINDOWS, "MadCount: %d\n", MadCount));\r
+ \r
+ WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete!\r
+ \r
+ // Map our loader image, so we can continue running\r
+ /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT);\r
+ if (!Status)\r
+ {\r
+ UiMessageBox("Error during MempSetupPaging");\r
+ return;\r
+ }*/\r
+ \r
+ //VideoDisplayString(L"Hello from VGA, going into the kernel\n");\r
+ DbgPrint((DPRINT_WINDOWS, "HalPT: 0x%X\n", HalPT));\r
+ \r
+ // Page Tables have been setup, make special handling for PCR and TSS\r
+ // (which is done in BlSetupFotNt in usual ntldr)\r
+ HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage+1;\r
+ HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;\r
+ HalPT[(KI_USER_SHARED_DATA - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;\r
+ \r
+ HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].PageFrameNumber = PcrBasePage;\r
+ HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Valid = 1;\r
+ HalPT[(KIP0PCRADDRESS - 0xFFC00000) >> MM_PAGE_SHIFT].Write = 1;\r
+ \r
+ // Map VGA memory\r
+ //VideoMemoryBase = MmMapIoSpace(0xb8000, 4000, MmNonCached);\r
+ //DbgPrint((DPRINT_WINDOWS, "VideoMemoryBase: 0x%X\n", VideoMemoryBase));\r
+ \r
+ Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));\r
+ \r
+ // Fill the memory descriptor list and \r
+ //PrepareMemoryDescriptorList();\r
+ DbgPrint((DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n"));\r
+ List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);\r
+ \r
+ #if DEBUG\r
+ {\r
+ ULONG *PDE_Addr=(ULONG *)PDE;//0xC0300000;\r
+ int j;\r
+ \r
+ DbgPrint((DPRINT_WINDOWS, "\nPDE\n"));\r
+ \r
+ for (i=0; i<128; i++)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "0x%04X | ", i*8));\r
+ \r
+ for (j=0; j<8; j++)\r
+ {\r
+ DbgPrint((DPRINT_WINDOWS, "0x%08X ", PDE_Addr[i*8+j]));\r
+ }\r
+ \r
+ DbgPrint((DPRINT_WINDOWS, "\n"));\r
+ }\r
+ }\r
+ #endif\r
+ \r
+ \r
+ // Enable paging\r
+ //BS->ExitBootServices(ImageHandle,MapKey);\r
+ \r
+ // Disable Interrupts\r
+ Ke386DisableInterrupts();\r
+ \r
+ // Re-initalize EFLAGS\r
+ Ke386EraseFlags();\r
+ \r
+ // Set the PDBR\r
+ Ke386SetPageTableDirectory((ULONG_PTR)PDE);\r
+ \r
+ // Enable paging by modifying CR0\r
+ Ke386SetCr0(Ke386GetCr0() | CR0_PG);\r
+ \r
+ // Set processor context\r
+ WinLdrSetProcessorContext(GdtIdt, KIP0PCRADDRESS, KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT));\r
+ \r
+ // Zero KI_USER_SHARED_DATA page\r
+ memset((PVOID)KI_USER_SHARED_DATA, 0, MM_PAGE_SIZE);\r
--#endif\r
+++#endif\r
+ return TRUE;\r
+ }\r
+ \r
+ // Two special things this func does: it sorts descriptors,\r
+ // and it merges free ones\r
+ VOID\r
+ WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+ IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor)\r
+ {\r
+ PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead;\r
+ PLIST_ENTRY PreviousEntry, NextEntry;\r
+ PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL;\r
+ \r
+ DbgPrint((DPRINT_WINDOWS, "BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage,\r
+ NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]));\r
+ \r
+ /* Find a place where to insert the new descriptor to */\r
+ PreviousEntry = ListHead;\r
+ NextEntry = ListHead->Flink;\r
+ while (NextEntry != ListHead)\r
+ {\r
+ NextDescriptor = CONTAINING_RECORD(NextEntry,\r
+ MEMORY_ALLOCATION_DESCRIPTOR,\r
+ ListEntry);\r
+ if (NewDescriptor->BasePage < NextDescriptor->BasePage)\r
+ break;\r
+ \r
+ PreviousEntry = NextEntry;\r
+ PreviousDescriptor = NextDescriptor;\r
+ NextEntry = NextEntry->Flink;\r
+ }\r
+ \r
+ /* Don't forget about merging free areas */\r
+ if (NewDescriptor->MemoryType != LoaderFree)\r
+ {\r
+ /* Just insert, nothing to merge */\r
+ InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);\r
+ }\r
+ else\r
+ {\r
+ /* Previous block also free? */\r
+ if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) &&\r
+ ((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) ==\r
+ NewDescriptor->BasePage))\r
+ {\r
+ /* Just enlarge previous descriptor's PageCount */\r
+ PreviousDescriptor->PageCount += NewDescriptor->PageCount;\r
+ NewDescriptor = PreviousDescriptor;\r
+ }\r
+ else\r
+ {\r
+ /* Nope, just insert */\r
+ InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry);\r
+ }\r
+ \r
+ /* Next block is free ?*/\r
+ if ((NextEntry != ListHead) &&\r
+ (NextDescriptor->MemoryType == LoaderFree) &&\r
+ ((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage))\r
+ {\r
+ /* Enlarge next descriptor's PageCount */\r
+ NewDescriptor->PageCount += NextDescriptor->PageCount;\r
+ RemoveEntryList(&NextDescriptor->ListEntry);\r
+ }\r
+ }\r
+ \r
+ return;\r
+ }\r
+ \r
+ VOID\r
+ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss)\r
+ {\r
+++#ifdef _M_IX86\r
+ GDTIDT GdtDesc, IdtDesc, OldIdt;\r
+ PKGDTENTRY pGdt;\r
+ PKIDTENTRY pIdt;\r
+ ULONG Ldt = 0;\r
+++#endif\r
+ //ULONG i;\r
+ \r
+ DbgPrint((DPRINT_WINDOWS, "GDtIdt %p, Pcr %p, Tss 0x%08X\n",\r
+ GdtIdt, Pcr, Tss));\r
+ \r
+ // Kernel expects the PCR to be zero-filled on startup\r
+ // FIXME: Why zero it here when we can zero it right after allocation?\r
+ RtlZeroMemory((PVOID)Pcr, MM_PAGE_SIZE); //FIXME: Why zero only 1 page when we allocate 2?\r
+ \r
+++#ifdef _M_IX86\r
+ // Get old values of GDT and IDT\r
+ Ke386GetGlobalDescriptorTable(GdtDesc);\r
+ Ke386GetInterruptDescriptorTable(IdtDesc);\r
+ \r
+ // Save old IDT\r
+ OldIdt.Base = IdtDesc.Base;\r
+ OldIdt.Limit = IdtDesc.Limit;\r
+ \r
+ // Prepare new IDT+GDT\r
+ GdtDesc.Base = KSEG0_BASE | (ULONG_PTR)GdtIdt;\r
+ GdtDesc.Limit = NUM_GDT * sizeof(KGDTENTRY) - 1;\r
+ IdtDesc.Base = (ULONG)((PUCHAR)GdtDesc.Base + GdtDesc.Limit + 1);\r
+ IdtDesc.Limit = NUM_IDT * sizeof(KIDTENTRY) - 1;\r
+ \r
+ // ========================\r
+ // Fill all descriptors now\r
+ // ========================\r
+ \r
+ pGdt = (PKGDTENTRY)GdtDesc.Base;\r
+ pIdt = (PKIDTENTRY)IdtDesc.Base;\r
+ \r
+ //\r
+ // Code selector (0x8)\r
+ // Flat 4Gb\r
+ //\r
+ pGdt[1].LimitLow = 0xFFFF;\r
+ pGdt[1].BaseLow = 0;\r
+ pGdt[1].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[1].HighWord.Bytes.Flags1 = 0x9A;\r
+ pGdt[1].HighWord.Bytes.Flags2 = 0xCF;\r
+ pGdt[1].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // Data selector (0x10)\r
+ // Flat 4Gb\r
+ //\r
+ pGdt[2].LimitLow = 0xFFFF;\r
+ pGdt[2].BaseLow = 0;\r
+ pGdt[2].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[2].HighWord.Bytes.Flags1 = 0x92;\r
+ pGdt[2].HighWord.Bytes.Flags2 = 0xCF;\r
+ pGdt[2].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // Selector (0x18)\r
+ // Flat 2Gb\r
+ //\r
+ pGdt[3].LimitLow = 0xFFFF;\r
+ pGdt[3].BaseLow = 0;\r
+ pGdt[3].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[3].HighWord.Bytes.Flags1 = 0xFA;\r
+ pGdt[3].HighWord.Bytes.Flags2 = 0xCF;\r
+ pGdt[3].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // Selector (0x20)\r
+ // Flat 2Gb\r
+ //\r
+ pGdt[4].LimitLow = 0xFFFF;\r
+ pGdt[4].BaseLow = 0;\r
+ pGdt[4].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[4].HighWord.Bytes.Flags1 = 0xF2;\r
+ pGdt[4].HighWord.Bytes.Flags2 = 0xCF;\r
+ pGdt[4].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // TSS Selector (0x28)\r
+ //\r
+ pGdt[5].LimitLow = 0x78-1; // 60 dwords\r
+ pGdt[5].BaseLow = (USHORT)(Tss & 0xffff);\r
+ pGdt[5].HighWord.Bytes.BaseMid = (UCHAR)((Tss >> 16) & 0xff);\r
+ pGdt[5].HighWord.Bytes.Flags1 = 0x89;\r
+ pGdt[5].HighWord.Bytes.Flags2 = 0x00;\r
+ pGdt[5].HighWord.Bytes.BaseHi = (UCHAR)((Tss >> 24) & 0xff);\r
+ \r
+ //\r
+ // PCR Selector (0x30)\r
+ //\r
+ pGdt[6].LimitLow = 0x01;\r
+ pGdt[6].BaseLow = (USHORT)(Pcr & 0xffff);\r
+ pGdt[6].HighWord.Bytes.BaseMid = (UCHAR)((Pcr >> 16) & 0xff);\r
+ pGdt[6].HighWord.Bytes.Flags1 = 0x92;\r
+ pGdt[6].HighWord.Bytes.Flags2 = 0xC0;\r
+ pGdt[6].HighWord.Bytes.BaseHi = (UCHAR)((Pcr >> 24) & 0xff);\r
+ \r
+ //\r
+ // Selector (0x38)\r
+ //\r
+ pGdt[7].LimitLow = 0xFFFF;\r
+ pGdt[7].BaseLow = 0;\r
+ pGdt[7].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[7].HighWord.Bytes.Flags1 = 0xF3;\r
+ pGdt[7].HighWord.Bytes.Flags2 = 0x40;\r
+ pGdt[7].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // Some BIOS fuck (0x40)\r
+ //\r
+ pGdt[8].LimitLow = 0xFFFF;\r
+ pGdt[8].BaseLow = 0x400;\r
+ pGdt[8].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[8].HighWord.Bytes.Flags1 = 0xF2;\r
+ pGdt[8].HighWord.Bytes.Flags2 = 0x0;\r
+ pGdt[8].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // Selector (0x48)\r
+ //\r
+ pGdt[9].LimitLow = 0;\r
+ pGdt[9].BaseLow = 0;\r
+ pGdt[9].HighWord.Bytes.BaseMid = 0;\r
+ pGdt[9].HighWord.Bytes.Flags1 = 0;\r
+ pGdt[9].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[9].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // Selector (0x50)\r
+ //\r
+ pGdt[10].LimitLow = 0xFFFF; //FIXME: Not correct!\r
+ pGdt[10].BaseLow = 0;\r
+ pGdt[10].HighWord.Bytes.BaseMid = 0x2;\r
+ pGdt[10].HighWord.Bytes.Flags1 = 0x89;\r
+ pGdt[10].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[10].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // Selector (0x58)\r
+ //\r
+ pGdt[11].LimitLow = 0xFFFF;\r
+ pGdt[11].BaseLow = 0;\r
+ pGdt[11].HighWord.Bytes.BaseMid = 0x2;\r
+ pGdt[11].HighWord.Bytes.Flags1 = 0x9A;\r
+ pGdt[11].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[11].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // Selector (0x60)\r
+ //\r
+ pGdt[12].LimitLow = 0xFFFF;\r
+ pGdt[12].BaseLow = 0; //FIXME: Maybe not correct, but noone cares\r
+ pGdt[12].HighWord.Bytes.BaseMid = 0x2;\r
+ pGdt[12].HighWord.Bytes.Flags1 = 0x92;\r
+ pGdt[12].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[12].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // Video buffer Selector (0x68)\r
+ //\r
+ pGdt[13].LimitLow = 0x3FFF;\r
+ pGdt[13].BaseLow = 0x8000; //FIXME: I guess not correct for UGA\r
+ pGdt[13].HighWord.Bytes.BaseMid = 0x0B;\r
+ pGdt[13].HighWord.Bytes.Flags1 = 0x92;\r
+ pGdt[13].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[13].HighWord.Bytes.BaseHi = 0;\r
+ \r
+ //\r
+ // Points to GDT (0x70)\r
+ //\r
+ pGdt[14].LimitLow = NUM_GDT*sizeof(KGDTENTRY) - 1;\r
+ pGdt[14].BaseLow = 0x7000;\r
+ pGdt[14].HighWord.Bytes.BaseMid = 0xFF;\r
+ pGdt[14].HighWord.Bytes.Flags1 = 0x92;\r
+ pGdt[14].HighWord.Bytes.Flags2 = 0;\r
+ pGdt[14].HighWord.Bytes.BaseHi = 0xFF;\r
+ \r
+ //\r
+ // Some unused descriptors should go here\r
+ // ...\r
+ \r
+ //\r
+ // Fill IDT with Traps\r
+ //\r
+++#endif\r
+ #if 0\r
+ pIdt[0].Offset = (i386DivideByZero | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[0].ExtendedOffset = 0x8; // Selector\r
+ pIdt[0].Access = 0x8F00;\r
+ pIdt[0].Selector = (i386DivideByZero | KSEG0_BASE) >> 16; // Extended Offset\r
+ \r
+ pIdt[1].Offset = (i386DebugException | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[1].ExtendedOffset = 0x8; // Selector\r
+ pIdt[1].Access = 0x8F00;\r
+ pIdt[1].Selector = (i386DebugException | KSEG0_BASE) >> 16; // Extended Offset\r
+ \r
+ pIdt[2].Offset = (i386NMIException | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[2].ExtendedOffset = 0x8; // Selector\r
+ pIdt[2].Access = 0x8F00;\r
+ pIdt[2].Selector = (i386NMIException | KSEG0_BASE) >> 16; // Extended Offset\r
+ \r
+ pIdt[3].Offset = (i386Breakpoint | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[3].ExtendedOffset = 0x8; // Selector\r
+ pIdt[3].Access = 0x8F00;\r
+ pIdt[3].Selector = (i386Breakpoint | KSEG0_BASE) >> 16; // Extended Offset\r
+ \r
+ pIdt[4].Offset = (i386Overflow | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[4].ExtendedOffset = 0x8; // Selector\r
+ pIdt[4].Access = 0x8F00;\r
+ pIdt[4].Selector = (i386Overflow | KSEG0_BASE) >> 16; // Extended Offset\r
+ \r
+ pIdt[5].Selector = (i386BoundException | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[5].Offset = (i386BoundException | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[5].ExtendedOffset = 0x8; // Selector\r
+ pIdt[5].Access = 0x8F00;\r
+ \r
+ pIdt[6].Selector = (i386InvalidOpcode | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[6].Offset = (i386InvalidOpcode | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[6].ExtendedOffset = 0x8; // Selector\r
+ pIdt[6].Access = 0x8F00;\r
+ \r
+ pIdt[7].Selector = (i386FPUNotAvailable | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[7].Offset = (i386FPUNotAvailable | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[7].ExtendedOffset = 0x8; // Selector\r
+ pIdt[7].Access = 0x8F00;\r
+ \r
+ pIdt[8].Selector = (i386DoubleFault | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[8].Offset = (i386DoubleFault | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[8].ExtendedOffset = 0x8; // Selector\r
+ pIdt[8].Access = 0x8F00;\r
+ \r
+ pIdt[9].Selector = (i386CoprocessorSegment | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[9].Offset = (i386CoprocessorSegment | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[9].ExtendedOffset = 0x8; // Selector\r
+ pIdt[9].Access = 0x8F00;\r
+ \r
+ pIdt[10].Selector = (i386InvalidTSS | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[10].Offset = (i386InvalidTSS | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[10].ExtendedOffset = 0x8; // Selector\r
+ pIdt[10].Access = 0x8F00;\r
+ \r
+ pIdt[11].Selector = (i386SegmentNotPresent | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[11].Offset = (i386SegmentNotPresent | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[11].ExtendedOffset = 0x8; // Selector\r
+ pIdt[11].Access = 0x8F00;\r
+ \r
+ pIdt[12].Selector = (i386StackException | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[12].Offset = (i386StackException | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[12].ExtendedOffset = 0x8; // Selector\r
+ pIdt[12].Access = 0x8F00;\r
+ \r
+ pIdt[13].Selector = (i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[13].Offset = (i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[13].ExtendedOffset = 0x8; // Selector\r
+ pIdt[13].Access = 0x8F00;\r
+ \r
+ pIdt[14].Selector = (i386PageFault | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[14].Offset = (i386PageFault | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[14].ExtendedOffset = 0x8; // Selector\r
+ pIdt[14].Access = 0x8F00;\r
+ \r
+ pIdt[15].Selector = 0; // Extended Offset\r
+ pIdt[15].Offset = 0;\r
+ pIdt[15].ExtendedOffset = 0; // Selector\r
+ pIdt[15].Access = 0;\r
+ \r
+ pIdt[16].Selector = (i386CoprocessorError | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[16].Offset = (i386CoprocessorError | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[16].ExtendedOffset = 0x8; // Selector\r
+ pIdt[16].Access = 0x8F00;\r
+ \r
+ pIdt[17].Selector = (i386AlignmentCheck | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[17].Offset = (i386AlignmentCheck | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[17].ExtendedOffset = 0x8; // Selector\r
+ pIdt[17].Access = 0x8F00;\r
+ \r
+ /*for (i=0; i<16; i++)\r
+ {\r
+ //pIdt[i].Offset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;\r
+ //pIdt[i].ExtendedOffset = 0x8; // Selector\r
+ //pIdt[i].Access = 0x8F00;\r
+ //pIdt[i].Selector = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset\r
+ \r
+ pIdt[i].Offset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF;\r
+ pIdt[i].ExtendedOffset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset\r
+ pIdt[i].Access = 0x8F00;\r
+ pIdt[i].Selector = 0x8;\r
+ }*/\r
+ \r
+ // Copy the old IDT\r
+ RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit);\r
+ \r
+ \r
+ // Mask interrupts\r
+ //asm("cli\n"); // they are already masked before enabling paged mode\r
+ \r
+ // Load GDT+IDT\r
+ Ke386SetGlobalDescriptorTable(GdtDesc);\r
+ Ke386SetInterruptDescriptorTable(IdtDesc);\r
+ \r
+ // Jump to proper CS and clear prefetch queue\r
+ asm("ljmp $0x08, $mb1\n"\r
+ "mb1:\n");\r
+ \r
+ // Set SS selector\r
+ asm(".intel_syntax noprefix\n");\r
+ asm("mov ax, 0x10\n"); // DataSelector=0x10\r
+ asm("mov ss, ax\n");\r
+ asm(".att_syntax\n");\r
+ \r
+ // Set DS and ES selectors\r
+ Ke386SetDs(0x10);\r
+ Ke386SetEs(0x10); // this is vital for rep stosd\r
+ \r
+ // LDT = not used ever, thus set to 0\r
+ Ke386SetLocalDescriptorTable(Ldt);\r
+ \r
+ // Load TSR\r
+ Ke386SetTr(0x28);\r
+ \r
+ // Clear GS\r
+ asm(".intel_syntax noprefix\n");\r
+ asm("push 0\n");\r
+ asm("pop gs\n");\r
+ asm(".att_syntax\n");\r
+ \r
+ // Set FS to PCR\r
+ Ke386SetFs(0x30);\r
+ \r
+ // Real end of the function, just for information\r
+ /* do not uncomment!\r
+ pop edi;\r
+ pop esi;\r
+ pop ebx;\r
+ mov esp, ebp;\r
+ pop ebp;\r
+ ret\r
+ */\r
+++#endif\r
+ }\r
--- /dev/null
+ /*
+ * PROJECT: EFI Windows Loader
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: freeldr/winldr/wlregistry.c
+ * PURPOSE: Registry support functions
+ * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
+ */
+
+ /* INCLUDES ***************************************************************/
+
+ #include <freeldr.h>
+
+++#ifdef _M_PPC
+++#include <of.h>
+++#include <mmu.h>
+++#endif
+++
+ #define NDEBUG
+ #include <debug.h>
+
+ BOOLEAN
+ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN LPCSTR DirectoryPath,
+ IN LPCSTR AnsiFileName,
+ IN LPCSTR OemFileName,
+ IN LPCSTR LanguageFileName);
+
+
+ /* FUNCTIONS **************************************************************/
+
+ BOOLEAN
+ WinLdrLoadSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN LPCSTR DirectoryPath,
+ IN LPCSTR HiveName)
+ {
+ PFILE FileHandle;
+ CHAR FullHiveName[256];
+ BOOLEAN Status;
+ ULONG HiveFileSize;
+ ULONG_PTR HiveDataPhysical;
+ PVOID HiveDataVirtual;
+
+ /* Concatenate path and filename to get the full name */
+ strcpy(FullHiveName, DirectoryPath);
+ strcat(FullHiveName, HiveName);
+ //Print(L"Loading %s...\n", FullHiveName);
+ FileHandle = FsOpenFile(FullHiveName);
+
+ if (FileHandle == NULL)
+ {
+ UiMessageBox("Opening hive file failed!");
+ return FALSE;
+ }
+
+ /* Get the file length */
+ HiveFileSize = FsGetFileSize(FileHandle);
+
+ if (HiveFileSize == 0)
+ {
+ FsCloseFile(FileHandle);
+ UiMessageBox("Hive file has 0 size!");
+ return FALSE;
+ }
+
+ /* Round up the size to page boundary and alloc memory */
+ HiveDataPhysical = (ULONG_PTR)MmAllocateMemory(
+ MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT);
+
+ if (HiveDataPhysical == 0)
+ {
+ FsCloseFile(FileHandle);
+ UiMessageBox("Unable to alloc memory for a hive!");
+ return FALSE;
+ }
+
+ /* Convert address to virtual */
+++#ifdef _M_IX86
+ HiveDataVirtual = (PVOID)(KSEG0_BASE | HiveDataPhysical);
+++#elif defined(_M_PPC)
+++ HiveDataVirtual = (PVOID)HiveDataPhysical;
+++#endif
+
+ /* Fill LoaderBlock's entries */
+ LoaderBlock->RegistryLength = HiveFileSize;
+ LoaderBlock->RegistryBase = HiveDataVirtual;
+
+ /* Finally read from file to the memory */
+ Status = FsReadFile(FileHandle, HiveFileSize, NULL, (PVOID)HiveDataPhysical);
+ FsCloseFile(FileHandle);
+ if (!Status)
+ {
+ UiMessageBox("Unable to read from hive file!");
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ // Queries registry for those three file names
+ BOOLEAN WinLdrGetNLSNames(LPSTR AnsiName,
+ LPSTR OemName,
+ LPSTR LangName)
+ {
+ LONG rc = ERROR_SUCCESS;
+ FRLDRHKEY hKey;
+ WCHAR szIdBuffer[80];
+ WCHAR NameBuffer[80];
+ ULONG BufferSize;
+
+ /* open the codepage key */
+ rc = RegOpenKey(NULL,
+ L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
+ &hKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ //strcpy(szErrorOut, "Couldn't open CodePage registry key");
+ return FALSE;
+ }
+
+ /* get ANSI codepage */
+ BufferSize = sizeof(szIdBuffer);
+ rc = RegQueryValue(hKey, L"ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
+ if (rc != ERROR_SUCCESS)
+ {
+ //strcpy(szErrorOut, "Couldn't get ACP NLS setting");
+ return FALSE;
+ }
+
+ BufferSize = sizeof(NameBuffer);
+ rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
+ if (rc != ERROR_SUCCESS)
+ {
+ //strcpy(szErrorOut, "ACP NLS Setting exists, but isn't readable");
+ return FALSE;
+ }
+ sprintf(AnsiName, "%S", NameBuffer);
+
+ /* get OEM codepage */
+ BufferSize = sizeof(szIdBuffer);
+ rc = RegQueryValue(hKey, L"OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
+ if (rc != ERROR_SUCCESS)
+ {
+ //strcpy(szErrorOut, "Couldn't get OEMCP NLS setting");
+ return FALSE;
+ }
+
+ BufferSize = sizeof(NameBuffer);
+ rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
+ if (rc != ERROR_SUCCESS)
+ {
+ //strcpy(szErrorOut, "OEMCP NLS setting exists, but isn't readable");
+ return FALSE;
+ }
+ sprintf(OemName, "%S", NameBuffer);
+
+ /* open the language key */
+ rc = RegOpenKey(NULL,
+ L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
+ &hKey);
+ if (rc != ERROR_SUCCESS)
+ {
+ //strcpy(szErrorOut, "Couldn't open Language registry key");
+ return FALSE;
+ }
+
+ /* get the Unicode case table */
+ BufferSize = sizeof(szIdBuffer);
+ rc = RegQueryValue(hKey, L"Default", NULL, (PUCHAR)szIdBuffer, &BufferSize);
+ if (rc != ERROR_SUCCESS)
+ {
+ //strcpy(szErrorOut, "Couldn't get Language Default setting");
+ return FALSE;
+ }
+
+ BufferSize = sizeof(NameBuffer);
+ rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)NameBuffer, &BufferSize);
+ if (rc != ERROR_SUCCESS)
+ {
+ //strcpy(szErrorOut, "Language Default setting exists, but isn't readable");
+ return FALSE;
+ }
+ sprintf(LangName, "%S", NameBuffer);
+
+ return TRUE;
+ }
+
+ BOOLEAN WinLdrLoadAndScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN LPCSTR DirectoryPath)
+ {
+ CHAR SearchPath[1024];
+ CHAR AnsiName[256], OemName[256], LangName[256];
+ BOOLEAN Status;
+
+ // There is a simple logic here: try to load usual hive (system), if it
+ // fails, then give system.alt a try, and finally try a system.sav
+
+ // FIXME: For now we only try system
+ strcpy(SearchPath, DirectoryPath);
+ strcat(SearchPath, "SYSTEM32\\CONFIG\\");
+ Status = WinLdrLoadSystemHive(LoaderBlock, SearchPath, "SYSTEM");
+
+ // Fail if failed...
+ if (!Status)
+ return FALSE;
+
+ // Initialize in-memory registry
+ RegInitializeRegistry();
+
+ // Import what was loaded
+ Status = RegImportBinaryHive((PCHAR)VaToPa(LoaderBlock->RegistryBase), LoaderBlock->RegistryLength);
+ if (!Status)
+ {
+ UiMessageBox("Importing binary hive failed!");
+ return FALSE;
+ }
+
+ // Initialize the 'CurrentControlSet' link
+ if (RegInitCurrentControlSet(FALSE) != ERROR_SUCCESS)
+ {
+ UiMessageBox("Initializing CurrentControlSet link failed!");
+ return FALSE;
+ }
+
+ Status = WinLdrGetNLSNames(AnsiName, OemName, LangName);
+ if (!Status)
+ {
+ UiMessageBox("Getting NLS names from registry failed!");
+ return FALSE;
+ }
+
+ DbgPrint((DPRINT_WINDOWS, "NLS data %s %s %s\n", AnsiName, OemName, LangName));
+
+ /* Load NLS data, should be moved to WinLdrLoadAndScanSystemHive() */
+ strcpy(SearchPath, DirectoryPath);
+ strcat(SearchPath, "SYSTEM32\\");
+ Status = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
+ DbgPrint((DPRINT_WINDOWS, "NLS data loaded with status %d\n", Status));
+
+ return TRUE;
+ }
+
+
+ /* PRIVATE FUNCTIONS ******************************************************/
+
+ BOOLEAN
+ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
+ IN LPCSTR DirectoryPath,
+ IN LPCSTR AnsiFileName,
+ IN LPCSTR OemFileName,
+ IN LPCSTR LanguageFileName)
+ {
+ CHAR FileName[255];
+ PFILE AnsiFileHandle;
+ PFILE OemFileHandle;
+ PFILE LanguageFileHandle;
+ ULONG AnsiFileSize, OemFileSize, LanguageFileSize;
+ ULONG TotalSize;
+ ULONG_PTR NlsDataBase;
+ PVOID NlsVirtual;
+ BOOLEAN Status, AnsiEqualsOem = FALSE;
+
+ /* There may be a case, when OEM and ANSI page coincide */
+ if (!strcmp(AnsiFileName, OemFileName))
+ AnsiEqualsOem = TRUE;
+
+ /* Open file with ANSI and store its size */
+ //Print(L"Loading %s...\n", Filename);
+ strcpy(FileName, DirectoryPath);
+ strcat(FileName, AnsiFileName);
+ AnsiFileHandle = FsOpenFile(FileName);
+
+ if (AnsiFileHandle == NULL)
+ goto Failure;
+
+ AnsiFileSize = FsGetFileSize(AnsiFileHandle);
+ DbgPrint((DPRINT_WINDOWS, "AnsiFileSize: %d\n", AnsiFileSize));
+ FsCloseFile(AnsiFileHandle);
+
+ /* Open OEM file and store its length */
+ if (AnsiEqualsOem)
+ {
+ OemFileSize = 0;
+ }
+ else
+ {
+ //Print(L"Loading %s...\n", Filename);
+ strcpy(FileName, DirectoryPath);
+ strcat(FileName, OemFileName);
+ OemFileHandle = FsOpenFile(FileName);
+
+ if (OemFileHandle == NULL)
+ goto Failure;
+
+ OemFileSize = FsGetFileSize(OemFileHandle);
+ FsCloseFile(OemFileHandle);
+ }
+ DbgPrint((DPRINT_WINDOWS, "OemFileSize: %d\n", OemFileSize));
+
+ /* And finally open the language codepage file and store its length */
+ //Print(L"Loading %s...\n", Filename);
+ strcpy(FileName, DirectoryPath);
+ strcat(FileName, LanguageFileName);
+ LanguageFileHandle = FsOpenFile(FileName);
+
+ if (LanguageFileHandle == NULL)
+ goto Failure;
+
+ LanguageFileSize = FsGetFileSize(LanguageFileHandle);
+ FsCloseFile(LanguageFileHandle);
+ DbgPrint((DPRINT_WINDOWS, "LanguageFileSize: %d\n", LanguageFileSize));
+
+ /* Sum up all three length, having in mind that every one of them
+ must start at a page boundary => thus round up each file to a page */
+ TotalSize = MM_SIZE_TO_PAGES(AnsiFileSize) +
+ MM_SIZE_TO_PAGES(OemFileSize) +
+ MM_SIZE_TO_PAGES(LanguageFileSize);
+
+ NlsDataBase = (ULONG_PTR)MmAllocateMemory(TotalSize*MM_PAGE_SIZE);
+
+ if (NlsDataBase == 0)
+ goto Failure;
+
+++#ifdef _M_IX86
+ NlsVirtual = (PVOID)(KSEG0_BASE | NlsDataBase);
+++#elif defined(_M_PPC)
+++ NlsVirtual = (PVOID)NlsDataBase;
+++#endif
+ LoaderBlock->NlsData->AnsiCodePageData = NlsVirtual;
+ LoaderBlock->NlsData->OemCodePageData = (PVOID)((PUCHAR)NlsVirtual +
+ (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT));
+ LoaderBlock->NlsData->UnicodeCodePageData = (PVOID)((PUCHAR)NlsVirtual +
+ (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT) +
+ (MM_SIZE_TO_PAGES(OemFileSize) << MM_PAGE_SHIFT));
+
+ /* Ansi and OEM data are the same - just set pointers to the same area */
+ if (AnsiEqualsOem)
+ LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData;
+
+
+ /* Now actually read the data into memory, starting with Ansi file */
+ strcpy(FileName, DirectoryPath);
+ strcat(FileName, AnsiFileName);
+ AnsiFileHandle = FsOpenFile(FileName);
+
+ if (AnsiFileHandle == NULL)
+ goto Failure;
+
+ Status = FsReadFile(AnsiFileHandle, AnsiFileSize, NULL, VaToPa(LoaderBlock->NlsData->AnsiCodePageData));
+
+ if (!Status)
+ goto Failure;
+
+ FsCloseFile(AnsiFileHandle);
+
+ /* OEM now, if it doesn't equal Ansi of course */
+ if (!AnsiEqualsOem)
+ {
+ strcpy(FileName, DirectoryPath);
+ strcat(FileName, OemFileName);
+ OemFileHandle = FsOpenFile(FileName);
+
+ if (OemFileHandle == NULL)
+ goto Failure;
+
+ Status = FsReadFile(OemFileHandle, OemFileSize, NULL, VaToPa(LoaderBlock->NlsData->OemCodePageData));
+
+ if (!Status)
+ goto Failure;
+
+ FsCloseFile(AnsiFileHandle);
+ }
+
+ /* finally the language file */
+ strcpy(FileName, DirectoryPath);
+ strcat(FileName, LanguageFileName);
+ LanguageFileHandle = FsOpenFile(FileName);
+
+ if (LanguageFileHandle == NULL)
+ goto Failure;
+
+ Status = FsReadFile(LanguageFileHandle, LanguageFileSize, NULL, VaToPa(LoaderBlock->NlsData->UnicodeCodePageData));
+
+ if (!Status)
+ goto Failure;
+
+ FsCloseFile(LanguageFileHandle);
+
+ //
+ // THIS IS HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK
+ // Should go to WinLdrLoadOemHalFont(), when it will be implemented
+ //
+ LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData);
+
+ /* Convert NlsTables address to VA */
+ LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData);
+
+ return TRUE;
+
+ Failure:
+ //UiMessageBox("Error reading NLS file %s\n", Filename);
+ UiMessageBox("Error reading NLS file!");
+ return FALSE;
+ }
#endif
++#ifdef __GNUC__
++
++/* Available as intrinsics on MSVC */
++#ifdef _X86_
++static __inline void _disable(void) {__asm__ __volatile__("cli\n");}
++static __inline void _enable(void) {__asm__ __volatile__("sti\n");}
++
++static __inline ULONG64 __readcr3(void)
++{
++ ULONG_PTR Ret;
++ __asm__ __volatile__("movl %%cr3, %0;\n"
++ :"=r"(Ret));
++ return (ULONG64)Ret;
++}
++
++static __inline ULONG64 __readcr4(void)
++{
++ ULONG_PTR Ret;
++ __asm__ __volatile__("movl %%cr4, %0; \n"
++ :"=r"(Ret));
++ return (ULONG64)Ret;
++}
++#elif defined(_PPC_)
+++#ifndef _ENABLE_DISABLE_DEFINED
+++#define _ENABLE_DISABLE_DEFINED
++static __inline void _disable(void) {
++ /* Turn off EE bit */
++ __asm__ __volatile__
++ ("mfmsr 3\n\t"
++ "xor 4,5,5\n\t"
++ "addi 4,4,-1\n\t"
++ "and 0,3,4\n\t"
++ "mtmsr 0\n\t"
++ );
++}
++static __inline void _enable(void) {
++ /* Turn on EE bit */
++ __asm__ __volatile__
++ ("mfmsr 3\n\t"
++ "ori 0,3,0x8000\n\t"
++ "mtmsr 0\n\t"
++ );
++}
+++#endif
++#endif /*_X86_*/
++#endif
++
#ifdef __cplusplus
}
#endif
--- /dev/null
+ /*\r
+ Compatibility <intrin.h> header for GCC -- GCC equivalents of intrinsic\r
+ Microsoft Visual C++ functions. Originally developed for the ReactOS\r
+ (<http://www.reactos.org/>) and TinyKrnl (<http://www.tinykrnl.org/>)\r
+ projects.\r
+ \r
+ Copyright (c) 2006 KJK::Hyperion <hackbunny@reactos.com>\r
+ \r
+ Permission is hereby granted, free of charge, to any person obtaining a\r
+ copy of this software and associated documentation files (the "Software"),\r
+ to deal in the Software without restriction, including without limitation\r
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+ and/or sell copies of the Software, and to permit persons to whom the\r
+ Software is furnished to do so, subject to the following conditions:\r
+ \r
+ The above copyright notice and this permission notice shall be included in\r
+ all copies or substantial portions of the Software.\r
+ \r
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+ DEALINGS IN THE SOFTWARE.\r
+ */\r
+ \r
+ #ifndef KJK_INTRIN_H_\r
+ #define KJK_INTRIN_H_\r
+ \r
+ #ifndef __GNUC__\r
+ #error Unsupported compiler\r
+ #endif\r
+ \r
+ /*\r
+ FIXME: review all "memory" clobbers, add/remove to match Visual C++\r
+ behavior: some "obvious" memory barriers are not present in the Visual C++\r
+ implementation - e.g. __stosX; on the other hand, some memory barriers that\r
+ *are* present could have been missed\r
+ */\r
+ /*\r
+ FIXME: atomic intrinsics haven't been tested yet\r
+ */\r
+ \r
+ /*\r
+ NOTE: this is a *compatibility* header. Some functions may look wrong at\r
+ first, but they're only "as wrong" as they would be on Visual C++. Our\r
+ priority is compatibility\r
+ \r
+ NOTE: unlike most people who write inline asm for GCC, I didn't pull the\r
+ constraints and the uses of __volatile__ out of my... hat. Do not touch\r
+ them. I hate cargo cult programming\r
+ \r
+ NOTE: be very careful with declaring "memory" clobbers. Some "obvious"\r
+ barriers aren't there in Visual C++ (e.g. __stosX)\r
+ \r
+ NOTE: review all intrinsics with a return value, add/remove __volatile__\r
+ where necessary. If an intrinsic whose value is ignored generates a no-op\r
+ under Visual C++, __volatile__ must be omitted; if it always generates code\r
+ (for example, if it has side effects), __volatile__ must be specified. GCC\r
+ will only optimize out non-volatile asm blocks with outputs, so input-only\r
+ blocks are safe. Oddities such as the non-volatile 'rdmsr' are intentional\r
+ and follow Visual C++ behavior\r
+ \r
+ NOTE: on GCC 4.1.0, please use the __sync_* built-ins for barriers and\r
+ atomic operations. Test the version like this:\r
+ \r
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100\r
+ ...\r
+ \r
+ Pay attention to the type of barrier. Make it match with what Visual C++\r
+ would use in the same case\r
+ */\r
+ \r
+ /*\r
+ BUGBUG: 'long long' arguments and returns mess up GCC royally. There has to\r
+ be something we can do about them\r
+ */\r
+ #ifdef __i386__\r
+ \r
+ /*** Stack frame juggling ***/\r
+ #define _ReturnAddress() (__builtin_return_address(0))\r
+ #define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1]))\r
+ /* TODO: __getcallerseflags but how??? */\r
+ \r
+ \r
+ /*** Atomic operations ***/\r
+ /* TODO: _ReadBarrier */\r
+ /* TODO: _WriteBarrier */\r
+ \r
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100\r
+ #define _ReadWriteBarrier() __sync_synchronize()\r
+ #else\r
+ /* TODO: _ReadWriteBarrier() */\r
+ #endif\r
+ \r
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100\r
+ \r
+ static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)\r
+ {\r
+ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)\r
+ {\r
+ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)\r
+ {\r
+ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)\r
+ {\r
+ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)\r
+ {\r
+ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value)\r
+ {\r
+ /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */\r
+ __sync_synchronize();\r
+ return __sync_lock_test_and_set(Target, Value);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)\r
+ {\r
+ /* NOTE: ditto */\r
+ __sync_synchronize();\r
+ return __sync_lock_test_and_set(Target, Value);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)\r
+ {\r
+ return __sync_fetch_and_add(Addend, Value);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)\r
+ {\r
+ return __sync_fetch_and_and(value, mask);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)\r
+ {\r
+ return __sync_fetch_and_and(value, mask);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask)\r
+ {\r
+ return __sync_fetch_and_and(value, mask);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)\r
+ {\r
+ return __sync_fetch_and_or(value, mask);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)\r
+ {\r
+ return __sync_fetch_and_or(value, mask);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask)\r
+ {\r
+ return __sync_fetch_and_or(value, mask);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)\r
+ {\r
+ return __sync_fetch_and_xor(value, mask);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)\r
+ {\r
+ return __sync_fetch_and_xor(value, mask);\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask)\r
+ {\r
+ return __sync_fetch_and_xor(value, mask);\r
+ }\r
+ \r
+ #else\r
+ \r
+ static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)\r
+ {\r
+ char retval = Comperand;\r
+ __asm__("lock; cmpxchgb %b[Exchange], %[Destination]" : "a" (retval) : [Destination] "rm" (Destination), [Exchange] "r" (Exchange) : "memory");\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)\r
+ {\r
+ short retval = Comperand;\r
+ __asm__("lock; cmpxchgw %w[Exchange], %[Destination]" : "a" (retval) : [Destination] "rm" (Destination), [Exchange] "r" (Exchange): "memory");\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)\r
+ {\r
+ long retval = Comperand;\r
+ __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : "a" (retval) : [Destination] "rm" (Destination), [Exchange] "r" (Exchange): "memory");\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)\r
+ {\r
+ unsigned long lo32Retval = (unsigned long)((Comperand >> 0) & 0xFFFFFFFF);\r
+ long hi32Retval = (unsigned long)((Comperand >> 32) & 0xFFFFFFFF);\r
+ \r
+ unsigned long lo32Exchange = (unsigned long)((Exchange >> 0) & 0xFFFFFFFF);\r
+ long hi32Exchange = (unsigned long)((Exchange >> 32) & 0xFFFFFFFF);\r
+ \r
+ __asm__\r
+ (\r
+ "cmpxchg8b %[Destination]" :\r
+ "a" (lo32Retval), "d" (hi32Retval) :\r
+ [Destination] "rm" (Destination), "b" (lo32Exchange), "c" (hi32Exchange) :\r
+ "memory"\r
+ );\r
+ \r
+ {\r
+ union u_\r
+ {\r
+ long long ll;\r
+ struct s_\r
+ {\r
+ unsigned long lo32;\r
+ long hi32;\r
+ }\r
+ s;\r
+ }\r
+ u = { s : { lo32 : lo32Retval, hi32 : hi32Retval } };\r
+ \r
+ return u.ll;\r
+ }\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)\r
+ {\r
+ void * retval;\r
+ __asm__("lock; cmpxchgl %k[Exchange], %[Destination]" : "a" (retval) : [Destination] "rm" (Destination), [Exchange] "r" (Exchange), "a" (Comperand) : "memory");\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value)\r
+ {\r
+ long retval = Value;\r
+ __asm__("lock; xchgl %[retval], %[Target]" : [retval] "r" (retval) : [Target] "rm" (Target) : "memory");\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)\r
+ {\r
+ void * retval = Value;\r
+ __asm__("lock; xchgl %[retval], %[Target]" : [retval] "r" (retval) : [Target] "rm" (Target) : "memory");\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)\r
+ {\r
+ long retval = Value;\r
+ __asm__("lock; xaddl %[retval], %[Addend]" : "r" (retval) : "rm" (Addend));\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)\r
+ {\r
+ char x;\r
+ char y;\r
+ \r
+ y = *value;\r
+ \r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange8(value, x & mask, x);\r
+ }\r
+ while(y != x);\r
+ \r
+ return y;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)\r
+ {\r
+ short x;\r
+ short y;\r
+ \r
+ y = *value;\r
+ \r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange16(value, x & mask, x);\r
+ }\r
+ while(y != x);\r
+ \r
+ return y;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask)\r
+ {\r
+ long x;\r
+ long y;\r
+ \r
+ y = *value;\r
+ \r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange(value, x & mask, x);\r
+ }\r
+ while(y != x);\r
+ \r
+ return y;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)\r
+ {\r
+ char x;\r
+ char y;\r
+ \r
+ y = *value;\r
+ \r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange8(value, x | mask, x);\r
+ }\r
+ while(y != x);\r
+ \r
+ return y;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)\r
+ {\r
+ short x;\r
+ short y;\r
+ \r
+ y = *value;\r
+ \r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange16(value, x | mask, x);\r
+ }\r
+ while(y != x);\r
+ \r
+ return y;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask)\r
+ {\r
+ long x;\r
+ long y;\r
+ \r
+ y = *value;\r
+ \r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange(value, x | mask, x);\r
+ }\r
+ while(y != x);\r
+ \r
+ return y;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)\r
+ {\r
+ char x;\r
+ char y;\r
+ \r
+ y = *value;\r
+ \r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange8(value, x ^ mask, x);\r
+ }\r
+ while(y != x);\r
+ \r
+ return y;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)\r
+ {\r
+ short x;\r
+ short y;\r
+ \r
+ y = *value;\r
+ \r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange16(value, x ^ mask, x);\r
+ }\r
+ while(y != x);\r
+ \r
+ return y;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask)\r
+ {\r
+ long x;\r
+ long y;\r
+ \r
+ y = *value;\r
+ \r
+ do\r
+ {\r
+ x = y;\r
+ y = _InterlockedCompareExchange(value, x ^ mask, x);\r
+ }\r
+ while(y != x);\r
+ \r
+ return y;\r
+ }\r
+ \r
+ #endif\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedAddLargeStatistic(volatile long long * const Addend, const long Value)\r
+ {\r
+ __asm__\r
+ (\r
+ "lock; add %[Value], %[Lo32];"\r
+ "jae LABEL%=;"\r
+ "lock; adc $0, %[Hi32];"\r
+ "LABEL%=:;" :\r
+ [Lo32] "=m" (*((volatile long *)(Addend) + 0)), [Hi32] "=m" (*((volatile long *)(Addend) + 1)) :\r
+ [Value] "ir" (Value)\r
+ );\r
+ \r
+ return Value;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedDecrement(volatile long * const lpAddend)\r
+ {\r
+ return _InterlockedExchangeAdd(lpAddend, -1) - 1;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long _InterlockedIncrement(volatile long * const lpAddend)\r
+ {\r
+ return _InterlockedExchangeAdd(lpAddend, 1) + 1;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandreset(volatile long * const a, const long b)\r
+ {\r
+ unsigned char retval;\r
+ __asm__("lock; btr %[b], %[a]; setc %b[retval]" : [retval] "=q" (retval) : [a] "rm" (a), [b] "Nr" (b));\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandset(volatile long * const a, const long b)\r
+ {\r
+ unsigned char retval;\r
+ __asm__("lock; bts %[b], %[a]; setc %b[retval]" : [retval] "=q" (retval) : [a] "rm" (a), [b] "Nr" (b));\r
+ return retval;\r
+ }\r
+ \r
+ \r
+ /*** String operations ***/\r
+ /* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */\r
+ static __inline__ __attribute__((always_inline)) void __stosb(unsigned char * Dest, const unsigned char Data, size_t Count)\r
+ {\r
+ __asm__ __volatile__\r
+ (\r
+ "rep; stosb" :\r
+ [Dest] "=D" (Dest), [Count] "=c" (Count) :\r
+ "[Dest]" (Dest), "a" (Data), "[Count]" (Count)\r
+ );\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __stosw(unsigned short * Dest, const unsigned short Data, size_t Count)\r
+ {\r
+ __asm__ __volatile__\r
+ (\r
+ "rep; stosw" :\r
+ [Dest] "=D" (Dest), [Count] "=c" (Count) :\r
+ "[Dest]" (Dest), "a" (Data), "[Count]" (Count)\r
+ );\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __stosd(unsigned long * Dest, const unsigned long Data, size_t Count)\r
+ {\r
+ __asm__ __volatile__\r
+ (\r
+ "rep; stosl" :\r
+ [Dest] "=D" (Dest), [Count] "=c" (Count) :\r
+ "[Dest]" (Dest), "a" (Data), "[Count]" (Count)\r
+ );\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __movsb(unsigned char * Destination, const unsigned char * Source, size_t Count)\r
+ {\r
+ __asm__ __volatile__\r
+ (\r
+ "rep; movsb" :\r
+ [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :\r
+ "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)\r
+ );\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __movsw(unsigned short * Destination, const unsigned short * Source, size_t Count)\r
+ {\r
+ __asm__ __volatile__\r
+ (\r
+ "rep; movsw" :\r
+ [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :\r
+ "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)\r
+ );\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __movsd(unsigned long * Destination, const unsigned long * Source, size_t Count)\r
+ {\r
+ __asm__ __volatile__\r
+ (\r
+ "rep; movsd" :\r
+ [Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :\r
+ "[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)\r
+ );\r
+ }\r
+ \r
+ \r
+ /*** FS segment addressing ***/\r
+ static __inline__ __attribute__((always_inline)) void __writefsbyte(const unsigned long Offset, const unsigned char Data)\r
+ {\r
+ __asm__("movb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __writefsword(const unsigned long Offset, const unsigned short Data)\r
+ {\r
+ __asm__("movw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __writefsdword(const unsigned long Offset, const unsigned long Data)\r
+ {\r
+ __asm__("movl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned char __readfsbyte(const unsigned long Offset)\r
+ {\r
+ unsigned char value;\r
+ __asm__("movb %%fs:%a[Offset], %b[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));\r
+ return value;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned short __readfsword(const unsigned long Offset)\r
+ {\r
+ unsigned short value;\r
+ __asm__("movw %%fs:%a[Offset], %w[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));\r
+ return value;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned long __readfsdword(const unsigned long Offset)\r
+ {\r
+ unsigned long value;\r
+ __asm__("movl %%fs:%a[Offset], %k[value]" : [value] "=q" (value) : [Offset] "irm" (Offset));\r
+ return value;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __incfsbyte(const unsigned long Offset)\r
+ {\r
+ __asm__("incb %%fs:%a[Offset]" : : [Offset] "ir" (Offset));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __incfsword(const unsigned long Offset)\r
+ {\r
+ __asm__("incw %%fs:%a[Offset]" : : [Offset] "ir" (Offset));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __incfsdword(const unsigned long Offset)\r
+ {\r
+ __asm__("incl %%fs:%a[Offset]" : : [Offset] "ir" (Offset));\r
+ }\r
+ \r
+ /* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */\r
+ static __inline__ __attribute__((always_inline)) void __addfsbyte(const unsigned long Offset, const unsigned char Data)\r
+ {\r
+ if(!__builtin_constant_p(Offset))\r
+ __asm__("addb %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset));\r
+ else\r
+ __asm__("addb %b[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __addfsword(const unsigned long Offset, const unsigned short Data)\r
+ {\r
+ if(!__builtin_constant_p(Offset))\r
+ __asm__("addw %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset));\r
+ else\r
+ __asm__("addw %w[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __addfsdword(const unsigned long Offset, const unsigned int Data)\r
+ {\r
+ if(!__builtin_constant_p(Offset))\r
+ __asm__("addl %k[Offset], %%fs:%a[Offset]" : : [Offset] "r" (Offset));\r
+ else\r
+ __asm__("addl %k[Data], %%fs:%a[Offset]" : : [Offset] "ir" (Offset), [Data] "iq" (Data));\r
+ }\r
+ \r
+ \r
+ /*** Bit manipulation ***/\r
+ static __inline__ __attribute__((always_inline)) unsigned char _BitScanForward(unsigned long * const Index, const unsigned long Mask)\r
+ {\r
+ __asm__("bsfl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));\r
+ return Mask ? 1 : 0;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned char _BitScanReverse(unsigned long * const Index, const unsigned long Mask)\r
+ {\r
+ __asm__("bsrl %[Mask], %[Index]" : [Index] "=r" (*Index) : [Mask] "mr" (Mask));\r
+ return Mask ? 1 : 0;\r
+ }\r
+ \r
+ /* NOTE: again, the bizarre implementation follows Visual C++ */\r
+ static __inline__ __attribute__((always_inline)) unsigned char _bittest(const long * const a, const long b)\r
+ {\r
+ unsigned char retval;\r
+ \r
+ if(__builtin_constant_p(b))\r
+ __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));\r
+ else\r
+ __asm__("bt %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));\r
+ \r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned char _bittestandcomplement(long * const a, const long b)\r
+ {\r
+ unsigned char retval;\r
+ \r
+ if(__builtin_constant_p(b))\r
+ __asm__("btc %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));\r
+ else\r
+ __asm__("btc %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));\r
+ \r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned char _bittestandreset(long * const a, const long b)\r
+ {\r
+ unsigned char retval;\r
+ \r
+ if(__builtin_constant_p(b))\r
+ __asm__("btr %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));\r
+ else\r
+ __asm__("btr %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));\r
+ \r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned char _bittestandset(long * const a, const long b)\r
+ {\r
+ unsigned char retval;\r
+ \r
+ if(__builtin_constant_p(b))\r
+ __asm__("bts %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*(a + (b / 32))), [b] "Ir" (b % 32));\r
+ else\r
+ __asm__("bts %[b], %[a]; setb %b[retval]" : [retval] "=q" (retval) : [a] "mr" (*a), [b] "r" (b));\r
+ \r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned char _rotl8(const unsigned char value, const unsigned char shift)\r
+ {\r
+ unsigned char retval;\r
+ __asm__("rolb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned short _rotl16(const unsigned short value, const unsigned char shift)\r
+ {\r
+ unsigned short retval;\r
+ __asm__("rolw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned char _rotr8(const unsigned char value, const unsigned char shift)\r
+ {\r
+ unsigned char retval;\r
+ __asm__("rorb %b[shift], %b[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned short _rotr16(const unsigned short value, const unsigned char shift)\r
+ {\r
+ unsigned short retval;\r
+ __asm__("rorw %b[shift], %w[retval]" : [retval] "=rm" (retval) : "[retval]" (value), [shift] "Nc" (shift));\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned long long __ll_lshift(const unsigned long long Mask, int Bit)\r
+ {\r
+ unsigned long lo32 = (unsigned long)((Mask >> 0) & 0xFFFFFFFF);\r
+ unsigned long hi32 = (unsigned long)((Mask >> 32) & 0xFFFFFFFF);\r
+ \r
+ __asm__\r
+ (\r
+ "shldl %b[Bit], %k[Lo32], %k[Hi32]; sall %b[Bit], %k[Lo32]" :\r
+ [Lo32] "=q" (lo32), [Hi32] "=qm" (hi32):\r
+ "[Lo32]" (lo32), "[Hi32]" (hi32), [Bit] "Ic" (Bit)\r
+ );\r
+ \r
+ {\r
+ union u_\r
+ {\r
+ unsigned long long ull;\r
+ struct s_\r
+ {\r
+ unsigned long lo32;\r
+ unsigned long hi32;\r
+ }\r
+ s;\r
+ }\r
+ u = { s : { lo32 : lo32, hi32 : hi32 } };\r
+ \r
+ return u.ull;\r
+ }\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) long long __ll_rshift(const long long Mask, const int Bit)\r
+ {\r
+ unsigned long lo32 = (unsigned long)((Mask >> 0) & 0xFFFFFFFF);\r
+ long hi32 = (unsigned long)((Mask >> 32) & 0xFFFFFFFF);\r
+ \r
+ __asm__\r
+ (\r
+ "shrdl %b[Bit], %k[Lo32], %k[Hi32]; sarl %b[Bit], %k[Lo32]" :\r
+ [Lo32] "=q" (lo32), [Hi32] "=qm" (hi32):\r
+ "[Lo32]" (lo32), "[Hi32]" (hi32), [Bit] "Ic" (Bit)\r
+ );\r
+ \r
+ {\r
+ union u_\r
+ {\r
+ long long ll;\r
+ struct s_\r
+ {\r
+ unsigned long lo32;\r
+ long hi32;\r
+ }\r
+ s;\r
+ }\r
+ u = { s : { lo32 : lo32, hi32 : hi32 } };\r
+ \r
+ return u.ll;\r
+ }\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned long long __ull_rshift(const unsigned long long Mask, int Bit)\r
+ {\r
+ unsigned long lo32 = (unsigned long)((Mask >> 0) & 0xFFFFFFFF);\r
+ unsigned long hi32 = (unsigned long)((Mask >> 32) & 0xFFFFFFFF);\r
+ \r
+ __asm__\r
+ (\r
+ "shrdl %b[Bit], %k[Hi32], %k[Lo32]; shrl %b[Bit], %k[Hi32]" :\r
+ [Lo32] "=qm" (lo32), [Hi32] "=q" (hi32):\r
+ "[Lo32]" (lo32), "[Hi32]" (hi32), [Bit] "Ic" (Bit)\r
+ );\r
+ \r
+ {\r
+ union u_\r
+ {\r
+ unsigned long long ull;\r
+ struct s_\r
+ {\r
+ unsigned long lo32;\r
+ unsigned long hi32;\r
+ }\r
+ s;\r
+ }\r
+ u = { s : { lo32 : lo32, hi32 : hi32 } };\r
+ \r
+ return u.ull;\r
+ }\r
+ }\r
+ \r
+ \r
+ /*** 64-bit math ***/\r
+ static __inline__ __attribute__((always_inline)) long long __emul(const int a, const int b)\r
+ {\r
+ unsigned long lo32;\r
+ long hi32;\r
+ \r
+ __asm__("imul %[b]" : "=a" (lo32), "=d" (hi32) : [a] "a" (a), [b] "rm" (b));\r
+ \r
+ {\r
+ union u_\r
+ {\r
+ long long ll;\r
+ struct s_\r
+ {\r
+ unsigned long lo32;\r
+ long hi32;\r
+ }\r
+ s;\r
+ }\r
+ u = { s : { lo32 : lo32, hi32 : hi32 } };\r
+ \r
+ return u.ll;\r
+ }\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned long long __emulu(const unsigned int a, const unsigned int b)\r
+ {\r
+ unsigned long lo32;\r
+ unsigned long hi32;\r
+ \r
+ __asm__("mul %[b]" : "=a" (lo32), "=d" (hi32) : [a] "a" (a), [b] "rm" (b));\r
+ \r
+ {\r
+ union u_\r
+ {\r
+ unsigned long long ull;\r
+ struct s_\r
+ {\r
+ unsigned long lo32;\r
+ unsigned long hi32;\r
+ }\r
+ s;\r
+ }\r
+ u = { s : { lo32 : lo32, hi32 : hi32 } };\r
+ \r
+ return u.ull;\r
+ }\r
+ }\r
+ \r
+ \r
+ /*** Port I/O ***/\r
+ static __inline__ __attribute__((always_inline)) unsigned char __inbyte(const unsigned short Port)\r
+ {\r
+ unsigned char byte;\r
+ __asm__ __volatile__("inb %w[Port], %b[byte]" : [byte] "=a" (byte) : [Port] "Nd" (Port));\r
+ return byte;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned short __inword(const unsigned short Port)\r
+ {\r
+ unsigned short word;\r
+ __asm__ __volatile__("inw %w[Port], %w[word]" : [word] "=a" (word) : [Port] "Nd" (Port));\r
+ return word;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned long __indword(const unsigned short Port)\r
+ {\r
+ unsigned long dword;\r
+ __asm__ __volatile__("inl %w[Port], %k[dword]" : [dword] "=a" (dword) : [Port] "Nd" (Port));\r
+ return dword;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __inbytestring(unsigned short Port, unsigned char * Buffer, unsigned long Count)\r
+ {\r
+ __asm__ __volatile__\r
+ (\r
+ "rep; insb" :\r
+ [Buffer] "=D" (Buffer), [Count] "=c" (Count) :\r
+ "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :\r
+ "memory"\r
+ );\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __inwordstring(unsigned short Port, unsigned short * Buffer, unsigned long Count)\r
+ {\r
+ __asm__ __volatile__\r
+ (\r
+ "rep; insw" :\r
+ [Buffer] "=D" (Buffer), [Count] "=c" (Count) :\r
+ "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :\r
+ "memory"\r
+ );\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __indwordstring(unsigned short Port, unsigned long * Buffer, unsigned long Count)\r
+ {\r
+ __asm__ __volatile__\r
+ (\r
+ "rep; insl" :\r
+ [Buffer] "=D" (Buffer), [Count] "=c" (Count) :\r
+ "d" (Port), "[Buffer]" (Buffer), "[Count]" (Count) :\r
+ "memory"\r
+ );\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __outbyte(unsigned short const Port, const unsigned char Data)\r
+ {\r
+ __asm__ __volatile__("outb %b[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __outword(unsigned short const Port, const unsigned short Data)\r
+ {\r
+ __asm__ __volatile__("outw %w[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __outdword(unsigned short const Port, const unsigned long Data)\r
+ {\r
+ __asm__ __volatile__("outl %k[Data], %w[Port]" : : [Port] "Nd" (Port), [Data] "a" (Data));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __outbytestring(unsigned short const Port, const unsigned char * const Buffer, const unsigned long Count)\r
+ {\r
+ __asm__ __volatile__("rep; outsb" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __outwordstring(unsigned short const Port, const unsigned short * const Buffer, const unsigned long Count)\r
+ {\r
+ __asm__ __volatile__("rep; outsw" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __outdwordstring(unsigned short const Port, const unsigned long * const Buffer, const unsigned long Count)\r
+ {\r
+ __asm__ __volatile__("rep; outsl" : : [Port] "d" (Port), [Buffer] "S" (Buffer), "c" (Count));\r
+ }\r
+ \r
+ \r
+ /*** System information ***/\r
+ static __inline__ __attribute__((always_inline)) void __cpuid(int CPUInfo[], const int InfoType)\r
+ {\r
+ __asm__("cpuid" : "=a" (CPUInfo[0]), "=b" (CPUInfo[1]), "=c" (CPUInfo[2]), "=d" (CPUInfo[3]) : "a" (InfoType));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned long long __rdtsc(void)\r
+ {\r
+ unsigned long lo32;\r
+ unsigned long hi32;\r
+ \r
+ __asm__("rdtsc" : "=a" (lo32), "=d" (hi32));\r
+ \r
+ {\r
+ union u_\r
+ {\r
+ unsigned long long ull;\r
+ struct s_\r
+ {\r
+ unsigned long lo32;\r
+ unsigned long hi32;\r
+ }\r
+ s;\r
+ }\r
+ u = { s : { lo32 : lo32, hi32 : hi32 } };\r
+ \r
+ return u.ull;\r
+ }\r
+ }\r
+ \r
+ \r
+ /*** Interrupts ***/\r
+ static __inline__ __attribute__((always_inline)) void __debugbreak(void)\r
+ {\r
+ __asm__("int $3");\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __int2c(void)\r
+ {\r
+ __asm__("int $0x2c");\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void _disable(void)\r
+ {\r
+ __asm__("cli");\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void _enable(void)\r
+ {\r
+ __asm__("sti");\r
+ }\r
+ \r
+ \r
+ /*** Protected memory management ***/\r
+ static __inline__ __attribute__((always_inline)) unsigned long __readcr0(void)\r
+ {\r
+ unsigned long value;\r
+ __asm__("mov %%cr0, %[value]" : [value] "=q" (value));\r
+ return value;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned long __readcr2(void)\r
+ {\r
+ unsigned long value;\r
+ __asm__("mov %%cr2, %[value]" : [value] "=q" (value));\r
+ return value;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned long __readcr3(void)\r
+ {\r
+ unsigned long value;\r
+ __asm__("mov %%cr3, %[value]" : [value] "=q" (value));\r
+ return value;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned long __readcr4(void)\r
+ {\r
+ unsigned long value;\r
+ __asm__("mov %%cr4, %[value]" : [value] "=q" (value));\r
+ return value;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __writecr0(const unsigned long long Data)\r
+ {\r
+ __asm__("mov %[Data], %%cr0" : : [Data] "q" ((const unsigned long)(Data & 0xFFFFFFFF)));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __writecr3(const unsigned long long Data)\r
+ {\r
+ __asm__("mov %[Data], %%cr3" : : [Data] "q" ((const unsigned long)(Data & 0xFFFFFFFF)));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __writecr4(const unsigned long long Data)\r
+ {\r
+ __asm__("mov %[Data], %%cr4" : : [Data] "q" ((const unsigned long)(Data & 0xFFFFFFFF)));\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __invlpg(void * const Address)\r
+ {\r
+ __asm__("invlpg %[Address]" : : [Address] "m" (*((unsigned char *)(Address))));\r
+ }\r
+ \r
+ \r
+ /*** System operations ***/\r
+ static __inline__ __attribute__((always_inline)) unsigned long long __readmsr(const int reg)\r
+ {\r
+ unsigned long lo32;\r
+ unsigned long hi32;\r
+ \r
+ __asm__("rdmsr" : "=a" (lo32), "=d" (hi32) : "c" (reg));\r
+ \r
+ {\r
+ union u_\r
+ {\r
+ unsigned long long ull;\r
+ struct s_\r
+ {\r
+ unsigned long lo32;\r
+ unsigned long hi32;\r
+ }\r
+ s;\r
+ }\r
+ u = { s : { lo32 : lo32, hi32 : hi32 } };\r
+ \r
+ return u.ull;\r
+ }\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __writemsr(const unsigned long Register, const unsigned long long Value)\r
+ {\r
+ __asm__\r
+ (\r
+ "wrmsr" :\r
+ :\r
+ "a" ((unsigned long)((Value >> 0) & 0xFFFFFFFF)),\r
+ "d" ((unsigned long)((Value >> 32) & 0xFFFFFFFF)),\r
+ "c" (Register)\r
+ );\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) unsigned long long __readpmc(const int counter)\r
+ {\r
+ unsigned long lo32;\r
+ unsigned long hi32;\r
+ \r
+ __asm__("rdpmc" : "=a" (lo32), "=d" (hi32) : "c" (counter));\r
+ \r
+ {\r
+ union u_\r
+ {\r
+ unsigned long long ull;\r
+ struct s_\r
+ {\r
+ unsigned long lo32;\r
+ unsigned long hi32;\r
+ }\r
+ s;\r
+ }\r
+ u = { s : { lo32 : lo32, hi32 : hi32 } };\r
+ \r
+ return u.ull;\r
+ }\r
+ }\r
+ \r
+ /* NOTE: an immediate value for 'a' will raise an ICE in Visual C++ */\r
+ static __inline__ __attribute__((always_inline)) unsigned long __segmentlimit(const unsigned long a)\r
+ {\r
+ unsigned long retval;\r
+ __asm__ __volatile__("lsl %[a], %[retval]" : [retval] "=r" (retval) : [a] "rm" (a));\r
+ return retval;\r
+ }\r
+ \r
+ static __inline__ __attribute__((always_inline)) void __wbinvd(void)\r
+ {\r
+ __asm__("wbinvd");\r
+ }\r
+ \r
+++#elif defined(_M_PPC)\r
+++\r
+++/*** Stack frame juggling ***/\r
+++#define _ReturnAddress() (__builtin_return_address(0))\r
+++#define _AddressOfReturnAddress() (&(((void **)(__builtin_frame_address(0)))[1]))\r
+++/* TODO: __getcallerseflags but how??? */\r
+++\r
+++\r
+++/*** Atomic operations ***/\r
+++/* TODO: _ReadBarrier */\r
+++/* TODO: _WriteBarrier */\r
+++\r
+++#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100\r
+++#define _ReadWriteBarrier() __sync_synchronize()\r
+++#else\r
+++/* TODO: _ReadWriteBarrier() */\r
+++#endif\r
+++\r
+++#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100\r
+++\r
+++static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)\r
+++{\r
+++ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)\r
+++{\r
+++ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)\r
+++{\r
+++ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)\r
+++{\r
+++ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)\r
+++{\r
+++ return __sync_val_compare_and_swap(Destination, Comperand, Exchange);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value)\r
+++{\r
+++ /* NOTE: __sync_lock_test_and_set would be an acquire barrier, so we force a full barrier */\r
+++ __sync_synchronize();\r
+++ return __sync_lock_test_and_set(Target, Value);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)\r
+++{\r
+++ /* NOTE: ditto */\r
+++ __sync_synchronize();\r
+++ return __sync_lock_test_and_set(Target, Value);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)\r
+++{\r
+++ return __sync_fetch_and_add(Addend, Value);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)\r
+++{\r
+++ return __sync_fetch_and_and(value, mask);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)\r
+++{\r
+++ return __sync_fetch_and_and(value, mask);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask)\r
+++{\r
+++ return __sync_fetch_and_and(value, mask);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)\r
+++{\r
+++ return __sync_fetch_and_or(value, mask);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)\r
+++{\r
+++ return __sync_fetch_and_or(value, mask);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask)\r
+++{\r
+++ return __sync_fetch_and_or(value, mask);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)\r
+++{\r
+++ return __sync_fetch_and_xor(value, mask);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)\r
+++{\r
+++ return __sync_fetch_and_xor(value, mask);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask)\r
+++{\r
+++ return __sync_fetch_and_xor(value, mask);\r
+++}\r
+++\r
+++#else\r
+++\r
+++static __inline__ __attribute__((always_inline)) char _InterlockedCompareExchange8(volatile char * const Destination, const char Exchange, const char Comperand)\r
+++{\r
+++ char retval = Comperand;\r
+++ __asm__ __volatile__ (\r
+++ "sync\n"\r
+++ "1: lbarx %0,0,%1\n"\r
+++ " subf. %0,%2,%0\n"\r
+++ " bne 2f\n"\r
+++ " stbcx. %3,0,%1\n"\r
+++ " bne- 1b\n"\r
+++ "2: isync"\r
+++ : "=b" (retval)\r
+++ : "b" (Destination), "r" (Comperand), "r" (Exchange)\r
+++ : "cr0", "memory");\r
+++ return retval;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) short _InterlockedCompareExchange16(volatile short * const Destination, const short Exchange, const short Comperand)\r
+++{\r
+++ short retval = Comperand;\r
+++ __asm__ __volatile__ (\r
+++ "sync\n"\r
+++ "1: lharx %0,0,%1\n"\r
+++ " subf. %0,%2,%0\n"\r
+++ " bne 2f\n"\r
+++ " sthcx. %3,0,%1\n"\r
+++ " bne- 1b\n"\r
+++ "2: isync"\r
+++ : "=b" (retval)\r
+++ : "b" (Destination), "r" (Comperand), "r" (Exchange)\r
+++ : "cr0", "memory");\r
+++ return retval;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedCompareExchange(volatile long * const Destination, const long Exchange, const long Comperand)\r
+++{\r
+++ long retval = Comperand;\r
+++ __asm__ __volatile__ (\r
+++ "sync\n"\r
+++ "1: lwarx %0,0,%1\n"\r
+++ " subf. %0,%2,%0\n"\r
+++ " bne 2f\n"\r
+++ " stwcx. %3,0,%1\n"\r
+++ " bne- 1b\n"\r
+++ "2: isync"\r
+++ : "=b" (retval)\r
+++ : "b" (Destination), "r" (Comperand), "r" (Exchange)\r
+++ : "cr0", "memory");\r
+++ return retval;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long long _InterlockedCompareExchange64(volatile long long * const Destination, const long long Exchange, const long long Comperand)\r
+++{\r
+++ unsigned long lo32Retval = (unsigned long)((Comperand >> 0) & 0xFFFFFFFF);\r
+++ long hi32Retval = (unsigned long)((Comperand >> 32) & 0xFFFFFFFF);\r
+++\r
+++ unsigned long lo32Exchange = (unsigned long)((Exchange >> 0) & 0xFFFFFFFF);\r
+++ long hi32Exchange = (unsigned long)((Exchange >> 32) & 0xFFFFFFFF);\r
+++\r
+++#if 0\r
+++ __asm__\r
+++ (\r
+++ "cmpxchg8b %[Destination]" :\r
+++ "a" (lo32Retval), "d" (hi32Retval) :\r
+++ [Destination] "rm" (Destination), "b" (lo32Exchange), "c" (hi32Exchange) :\r
+++ "memory"\r
+++ );\r
+++#endif\r
+++ {\r
+++ union u_\r
+++ {\r
+++ long long ll;\r
+++ struct s_\r
+++ {\r
+++ unsigned long lo32;\r
+++ long hi32;\r
+++ }\r
+++ s;\r
+++ }\r
+++ u = { s : { lo32 : lo32Retval, hi32 : hi32Retval } };\r
+++\r
+++ return u.ll;\r
+++ }\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void * _InterlockedCompareExchangePointer(void * volatile * const Destination, void * const Exchange, void * const Comperand)\r
+++{\r
+++ return (void *)_InterlockedCompareExchange\r
+++ ((long *)Destination, (long) Exchange, (long) Comperand);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedExchange(volatile long * const Target, const long Value)\r
+++{\r
+++ long retval;\r
+++ __asm__ __volatile__ (\r
+++ "sync\n"\r
+++ "1: lwarx %0,0,%1\n"\r
+++ " stwcx. %2,0,%1\n"\r
+++ " bne- 1b\n"\r
+++ : "=b" (retval)\r
+++ : "b" (Target), "b" (Value)\r
+++ : "cr0", "memory");\r
+++ return retval;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void * _InterlockedExchangePointer(void * volatile * const Target, void * const Value)\r
+++{\r
+++ void * retval;\r
+++ __asm__ __volatile__ (\r
+++ "sync\n"\r
+++ "1: lwarx %0,0,%1\n"\r
+++ " stwcx. %2,0,%1\n"\r
+++ " bne- 1b\n"\r
+++ : "=b" (retval)\r
+++ : "b" (Target), "b" (Value)\r
+++ : "cr0", "memory");\r
+++ return retval;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedExchangeAdd(volatile long * const Addend, const long Value)\r
+++{\r
+++ long x;\r
+++ long y = *Addend;\r
+++ long addend = y;\r
+++ \r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange(Addend, addend + Value, x);\r
+++ } \r
+++ while(y != x);\r
+++\r
+++ return y;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) char _InterlockedAnd8(volatile char * const value, const char mask)\r
+++{\r
+++ char x;\r
+++ char y;\r
+++\r
+++ y = *value;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange8(value, x & mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return y;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) short _InterlockedAnd16(volatile short * const value, const short mask)\r
+++{\r
+++ short x;\r
+++ short y;\r
+++\r
+++ y = *value;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange16(value, x & mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return y;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedAnd(volatile long * const value, const long mask)\r
+++{\r
+++ long x;\r
+++ long y;\r
+++\r
+++ y = *value;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange(value, x & mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return y;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) char _InterlockedOr8(volatile char * const value, const char mask)\r
+++{\r
+++ char x;\r
+++ char y;\r
+++\r
+++ y = *value;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange8(value, x | mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return y;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) short _InterlockedOr16(volatile short * const value, const short mask)\r
+++{\r
+++ short x;\r
+++ short y;\r
+++\r
+++ y = *value;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange16(value, x | mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return y;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedOr(volatile long * const value, const long mask)\r
+++{\r
+++ long x;\r
+++ long y;\r
+++\r
+++ y = *value;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange(value, x | mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return y;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) char _InterlockedXor8(volatile char * const value, const char mask)\r
+++{\r
+++ char x;\r
+++ char y;\r
+++\r
+++ y = *value;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange8(value, x ^ mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return y;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) short _InterlockedXor16(volatile short * const value, const short mask)\r
+++{\r
+++ short x;\r
+++ short y;\r
+++\r
+++ y = *value;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange16(value, x ^ mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return y;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedXor(volatile long * const value, const long mask)\r
+++{\r
+++ long x;\r
+++ long y;\r
+++\r
+++ y = *value;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange(value, x ^ mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return y;\r
+++}\r
+++\r
+++#endif\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedAddLargeStatistic(volatile long long * const Addend, const long Value)\r
+++{\r
+++#if 0\r
+++ __asm__\r
+++ (\r
+++ "lock; add %[Value], %[Lo32];"\r
+++ "jae LABEL%=;"\r
+++ "lock; adc $0, %[Hi32];"\r
+++ "LABEL%=:;" :\r
+++ [Lo32] "=m" (*((volatile long *)(Addend) + 0)), [Hi32] "=m" (*((volatile long *)(Addend) + 1)) :\r
+++ [Value] "ir" (Value)\r
+++ );\r
+++#endif\r
+++ return Value;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedDecrement(volatile long * const lpAddend)\r
+++{\r
+++ return _InterlockedExchangeAdd(lpAddend, -1) - 1;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long _InterlockedIncrement(volatile long * const lpAddend)\r
+++{\r
+++ return _InterlockedExchangeAdd(lpAddend, 1) + 1;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandreset(volatile long * const a, const long b)\r
+++{\r
+++ long x;\r
+++ long y;\r
+++ long mask = ~(1<<b);\r
+++\r
+++ y = *a;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange(a, x & mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return (y & ~mask) != 0;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned char _interlockedbittestandset(volatile long * const a, const long b)\r
+++{\r
+++ long x;\r
+++ long y;\r
+++ long mask = 1<<b;\r
+++\r
+++ y = *a;\r
+++\r
+++ do\r
+++ {\r
+++ x = y;\r
+++ y = _InterlockedCompareExchange(a, x | mask, x);\r
+++ }\r
+++ while(y != x);\r
+++\r
+++ return (y & ~mask) != 0;\r
+++}\r
+++\r
+++\r
+++/*** String operations ***/\r
+++/* NOTE: we don't set a memory clobber in the __stosX functions because Visual C++ doesn't */\r
+++/* Note that the PPC store multiple operations may raise an exception in LE \r
+++ * mode */\r
+++static __inline__ __attribute__((always_inline)) void __stosb(unsigned char * Dest, const unsigned char Data, size_t Count)\r
+++{\r
+++ memset(Dest, Data, Count);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __stosw(unsigned short * Dest, const unsigned short Data, size_t Count)\r
+++{\r
+++ while(Count--) \r
+++ *Dest++ = Data;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __stosd(unsigned long * Dest, const unsigned long Data, size_t Count)\r
+++{\r
+++ while(Count--)\r
+++ *Dest++ = Data;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __movsb(unsigned char * Destination, const unsigned char * Source, size_t Count)\r
+++{\r
+++ memcpy(Destination, Source, Count);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __movsw(unsigned short * Destination, const unsigned short * Source, size_t Count)\r
+++{\r
+++ memcpy(Destination, Source, Count * sizeof(*Source));\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __movsd(unsigned long * Destination, const unsigned long * Source, size_t Count)\r
+++{\r
+++ memcpy(Destination, Source, Count * sizeof(*Source));\r
+++}\r
+++\r
+++\r
+++/*** FS segment addressing ***/\r
+++/* On PowerPC, r13 points to TLS data, including the TEB at 0(r13) from what I\r
+++ * can tell */\r
+++static __inline__ __attribute__((always_inline)) void __writefsbyte(const unsigned long Offset, const unsigned char Data)\r
+++{\r
+++ char *addr;\r
+++ __asm__("\tadd %2,13,%0\n"\r
+++ "\tstb %1,0(%2)\n" \r
+++ : \r
+++ : "b" (Offset), "b" (Data), "b" (addr));\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __writefsword(const unsigned long Offset, const unsigned short Data)\r
+++{\r
+++ char *addr;\r
+++ __asm__("\tadd %2,13,%0\n"\r
+++ "\tsth %1,0(%2)\n"\r
+++ : \r
+++ : "b" (Offset), "b" (Data), "b" (addr));\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __writefsdword(const unsigned long Offset, const unsigned long Data)\r
+++{\r
+++ char *addr;\r
+++ __asm__("\tadd %2,13,%0\n"\r
+++ "\tstw %1,0(%2)\n" \r
+++ : \r
+++ : "b" (Offset), "b" (Data), "b" (addr));\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned char __readfsbyte(const unsigned long Offset)\r
+++{\r
+++ char result;\r
+++ char *addr;\r
+++ __asm__("\tadd %2,13,%1\n"\r
+++ "\tlbz %0,0(%2)\n"\r
+++ : "=b" (result)\r
+++ : "b" (Offset), "b" (addr));\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned short __readfsword(const unsigned long Offset)\r
+++{\r
+++ unsigned short result;\r
+++ char *addr;\r
+++ __asm__("\tadd %2,13,%1\n"\r
+++ "\tlhz %0,0(%2)\n"\r
+++ : "=b" (result)\r
+++ : "b" (Offset), "b" (addr));\r
+++ return result;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned long __readfsdword(const unsigned long Offset)\r
+++{\r
+++ unsigned long result;\r
+++ char *addr;\r
+++ __asm__("\tadd %2,13,%1\n"\r
+++ "\tlwz %0,0(%2)\n"\r
+++ : "=b" (result)\r
+++ : "b" (Offset), "b" (addr));\r
+++ return result;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __incfsbyte(const unsigned long Offset)\r
+++{\r
+++ __writefsbyte(Offset, __readfsbyte(Offset)+1);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __incfsword(const unsigned long Offset)\r
+++{\r
+++ __writefsword(Offset, __readfsword(Offset)+1);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __incfsdword(const unsigned long Offset)\r
+++{\r
+++ __writefsdword(Offset, __readfsdword(Offset)+1);\r
+++}\r
+++\r
+++/* NOTE: the bizarre implementation of __addfsxxx mimics the broken Visual C++ behavior */\r
+++/* PPC Note: Not sure about the bizarre behavior. We'll try to emulate it later */\r
+++static __inline__ __attribute__((always_inline)) void __addfsbyte(const unsigned long Offset, const unsigned char Data)\r
+++{\r
+++ __writefsbyte(Offset, __readfsbyte(Offset) + Data);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __addfsword(const unsigned long Offset, const unsigned short Data)\r
+++{\r
+++ __writefsword(Offset, __readfsword(Offset) + Data);\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __addfsdword(const unsigned long Offset, const unsigned int Data)\r
+++{\r
+++ __writefsdword(Offset, __readfsdword(Offset) + Data);\r
+++}\r
+++\r
+++\r
+++/*** Bit manipulation ***/\r
+++static __inline__ __attribute__((always_inline)) unsigned char _BitScanForward(unsigned long * const Index, const unsigned long Mask)\r
+++{\r
+++ if(Mask == 0) return 0;\r
+++ else {\r
+++ unsigned long mask = Mask;\r
+++ mask &= -mask;\r
+++ *Index = \r
+++ ((mask & 0xffff0000) ? 16 : 0) +\r
+++ ((mask & 0xff00ff00) ? 8 : 0) +\r
+++ ((mask & 0xf0f0f0f0) ? 4 : 0) +\r
+++ ((mask & 0xcccccccc) ? 2 : 0) +\r
+++ ((mask & 0xaaaaaaaa) ? 1 : 0);\r
+++ return 1;\r
+++ }\r
+++}\r
+++\r
+++/* Thanks http://www.jjj.de/bitwizardry/files/bithigh.h */\r
+++static __inline__ __attribute__((always_inline)) unsigned char _BitScanReverse(unsigned long * const Index, const unsigned long Mask)\r
+++{\r
+++ unsigned long check = 16, checkmask;\r
+++ if(Mask == 0) return 0;\r
+++ else {\r
+++ unsigned long mask = Mask;\r
+++ *Index = 0;\r
+++ while(check) {\r
+++ checkmask = ((1<<check)-1) << check;\r
+++ if( mask & checkmask ) {\r
+++ mask >>= check;\r
+++ *Index += check;\r
+++ }\r
+++ check >>= 1;\r
+++ }\r
+++ return 1;\r
+++ }\r
+++}\r
+++\r
+++/* NOTE: again, the bizarre implementation follows Visual C++ */\r
+++static __inline__ __attribute__((always_inline)) unsigned char _bittest(const long * const a, const long b)\r
+++{\r
+++ return ((*a) & (1<<b)) != 0;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned char _bittestandcomplement(long * const a, const long b)\r
+++{\r
+++ unsigned char ret = ((*a) & (1<<b)) != 0;\r
+++ (*a) ^= (1<<b);\r
+++ return ret;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned char _bittestandreset(long * const a, const long b)\r
+++{\r
+++ unsigned char ret = ((*a) & (1<<b)) != 0;\r
+++ (*a) &= ~(1<<b);\r
+++ return ret;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned char _bittestandset(long * const a, const long b)\r
+++{\r
+++ unsigned char ret = ((*a) & (1<<b)) != 0;\r
+++ (*a) |= (1<<b);\r
+++ return ret;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned char _rotl8(const unsigned char value, const unsigned char shift)\r
+++{\r
+++ return (value << shift) | (value >> (8-shift));\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned short _rotl16(const unsigned short value, const unsigned char shift)\r
+++{\r
+++ return (value << shift) | (value >> (16-shift)); \r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned char _rotr8(const unsigned char value, const unsigned char shift)\r
+++{\r
+++ return (value >> shift) | (value << (8-shift)); \r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned short _rotr16(const unsigned short value, const unsigned char shift)\r
+++{\r
+++ return (value >> shift) | (value << (16-shift)); \r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned long long __ll_lshift(const unsigned long long Mask, int Bit)\r
+++{\r
+++ return Mask << Bit;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) long long __ll_rshift(const long long Mask, const int Bit)\r
+++{\r
+++ return Mask >> Bit;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned long long __ull_rshift(const unsigned long long Mask, int Bit)\r
+++{\r
+++ return Mask >> Bit;\r
+++}\r
+++\r
+++\r
+++/*** 64-bit math ***/\r
+++static __inline__ __attribute__((always_inline)) long long __emul(const int a, const int b)\r
+++{\r
+++ return a * b;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned long long __emulu(const unsigned int a, const unsigned int b)\r
+++{\r
+++ return a * b;\r
+++}\r
+++\r
+++\r
+++/*** Port I/O ***/\r
+++static __inline__ __attribute__((always_inline)) unsigned char __inbyte(const unsigned short Port)\r
+++{\r
+++ int ret;\r
+++ __asm__(\r
+++ "mfmsr 5\n\t"\r
+++ "xori %1,%1,7\n\t" /* Undo effects of LE without swapping */\r
+++ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+++ "mtmsr 6\n\t"\r
+++ "isync\n\t"\r
+++ "sync\n\t"\r
+++ "lbz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */\r
+++ "mtmsr 5\n\t" : "=r" (ret) : "b" (Port)\r
+++ );\r
+++ return ret;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned short __inword(const unsigned short Port)\r
+++{\r
+++ int ret;\r
+++ __asm__(\r
+++ "mfmsr 5\n\t"\r
+++ "xori %1,%1,6\n\t" /* Undo effects of LE without swapping */\r
+++ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+++ "mtmsr 6\n\t"\r
+++ "isync\n\t"\r
+++ "sync\n\t"\r
+++ "lhz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */\r
+++ "mtmsr 5\n\t" : "=r" (ret) : "b" (Port)\r
+++ );\r
+++ return ret;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned long __indword(const unsigned short Port)\r
+++{\r
+++ int ret;\r
+++ __asm__(\r
+++ "mfmsr 5\n\t"\r
+++ "xori %1,%1,4\n\t" /* Undo effects of LE without swapping */\r
+++ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+++ "mtmsr 6\n\t"\r
+++ "isync\n\t"\r
+++ "sync\n\t"\r
+++ "lwz %0,0(%1)\n\t" /* Get actual value at phys addr r3 */\r
+++ "mtmsr 5\n\t" : "=r" (ret) : "b" (Port)\r
+++ );\r
+++ return ret;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __inbytestring(unsigned short Port, unsigned char * Buffer, unsigned long Count)\r
+++{\r
+++ while(Count--) {\r
+++ *Buffer++ = __inbyte(Port);\r
+++ }\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __inwordstring(unsigned short Port, unsigned short * Buffer, unsigned long Count)\r
+++{\r
+++ while(Count--) {\r
+++ *Buffer++ = __inword(Port);\r
+++ }\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __indwordstring(unsigned short Port, unsigned long * Buffer, unsigned long Count)\r
+++{\r
+++ while(Count--) {\r
+++ *Buffer++ = __indword(Port);\r
+++ }\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __outbyte(unsigned short const Port, const unsigned char Data)\r
+++{\r
+++ __asm__(\r
+++ "mfmsr 5\n\t"\r
+++ "xori %0,%0,7\n\t" /* Undo effects of LE without swapping */\r
+++ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+++ "mtmsr 6\n\t"\r
+++ "sync\n\t"\r
+++ "eieio\n\t"\r
+++ "stb %1,0(%0)\n\t" /* Set actual value at phys addr r3 */\r
+++ "dcbst 0,%1\n\t"\r
+++ "mtmsr 5\n\t"\r
+++ "sync\n\t"\r
+++ "eieio\n\t" : : "b" (Port), "r" (Data)\r
+++ );\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __outword(unsigned short const Port, const unsigned short Data)\r
+++{\r
+++ __asm__(\r
+++ "mfmsr 5\n\t"\r
+++ "xori %0,%0,7\n\t" /* Undo effects of LE without swapping */\r
+++ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+++ "mtmsr 6\n\t"\r
+++ "sync\n\t"\r
+++ "eieio\n\t"\r
+++ "sth %1,0(%0)\n\t" /* Set actual value at phys addr r3 */\r
+++ "dcbst 0,%1\n\t"\r
+++ "mtmsr 5\n\t"\r
+++ "sync\n\t"\r
+++ "eieio\n\t" : : "b" (Port), "b" (Data)\r
+++ );\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __outdword(unsigned short const Port, const unsigned long Data)\r
+++{\r
+++ __asm__(\r
+++ "mfmsr 5\n\t"\r
+++ "xori %0,%0,7\n\t" /* Undo effects of LE without swapping */\r
+++ "andi. 6,5,0xffef\n\t"/* turn off MSR[DR] */\r
+++ "mtmsr 6\n\t"\r
+++ "sync\n\t"\r
+++ "eieio\n\t"\r
+++ "stw %1,0(%0)\n\t" /* Set actual value at phys addr r3 */\r
+++ "dcbst 0,%1\n\t"\r
+++ "mtmsr 5\n\t"\r
+++ "sync\n\t"\r
+++ "eieio\n\t" : : "b" (Port), "b" (Data)\r
+++ );\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __outbytestring(unsigned short const Port, const unsigned char * const Buffer, const unsigned long Count)\r
+++{\r
+++ unsigned long count = Count;\r
+++ unsigned char *buffer = Buffer;\r
+++ while(count--) {\r
+++ __outbyte(Port, *buffer++);\r
+++ }\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __outwordstring(unsigned short const Port, const unsigned short * const Buffer, const unsigned long Count)\r
+++{\r
+++ unsigned long count = Count;\r
+++ unsigned short *buffer = Buffer;\r
+++ while(count--) {\r
+++ __outword(Port, *buffer++);\r
+++ }\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __outdwordstring(unsigned short const Port, const unsigned long * const Buffer, const unsigned long Count)\r
+++{\r
+++ unsigned long count = Count;\r
+++ unsigned long *buffer = Buffer;\r
+++ while(count--) {\r
+++ __outdword(Port, *buffer++);\r
+++ }\r
+++}\r
+++\r
+++\r
+++/*** System information ***/\r
+++static __inline__ __attribute__((always_inline)) void __cpuid(int CPUInfo[], const int InfoType)\r
+++{\r
+++ unsigned long lo32;\r
+++ __asm__("mfpvr" : "=b" (lo32));\r
+++ return lo32;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) unsigned long long __rdtsc(void)\r
+++{\r
+++ unsigned long lo32;\r
+++ __asm__("mfdec" : "=b" (lo32));\r
+++ return lo32;\r
+++}\r
+++\r
+++\r
+++/*** Interrupts ***/\r
+++/* Finally decided to do this by enabling single step trap */\r
+++static __inline__ __attribute__((always_inline)) void __debugbreak(void)\r
+++{\r
+++ \r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __int2c(void)\r
+++{\r
+++ /* Not sure yet */\r
+++}\r
+++\r
+++#ifndef _ENABLE_DISABLE_DEFINED\r
+++#define _ENABLE_DISABLE_DEFINED\r
+++static __inline__ __attribute__((always_inline)) void _disable(void)\r
+++{\r
+++ __asm__ __volatile__("mfmsr 0\n\t" \\r
+++ "li 8,0x7fff\n\t" \\r
+++ "and 0,8,0\n\t" \\r
+++ "mtmsr 0\n\t");\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void _enable(void)\r
+++{\r
+++ __asm__ __volatile__("mfmsr 0\n\t" \\r
+++ "lis 8,0x8000@ha\n\t" \\r
+++ "or 0,8,0\n\t" \\r
+++ "mtmsr 0\n\t");\r
+++}\r
+++#endif\r
+++\r
+++/*** Protected memory management ***/\r
+++static __inline__ __attribute__((always_inline)) unsigned long __readsdr1(void)\r
+++{\r
+++ unsigned long value;\r
+++ __asm__("mfsdr1 %0" : "=b" (value));\r
+++ return value;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __writesdr1(const unsigned long long Data)\r
+++{\r
+++ __asm__("mtsdr1 %0" : : "b" (Data));\r
+++}\r
+++\r
+++/*** System operations ***/\r
+++/* This likely has a different meaning from the X86 equivalent. We'll keep\r
+++ * the name cause it fits */\r
+++static __inline__ __attribute__((always_inline)) unsigned long long __readmsr()\r
+++{\r
+++ unsigned long temp;\r
+++ __asm__("mfmsr %0" : "=b" (temp));\r
+++ return temp;\r
+++}\r
+++\r
+++static __inline__ __attribute__((always_inline)) void __writemsr(const unsigned long Value)\r
+++{\r
+++ __asm__("mtmsr %0" : : "b" (Value));\r
+++}\r
+++\r
+++/* We'll make sure of the following:\r
+++ * IO operations have completed\r
+++ * Write operations through cache have completed\r
+++ * We've reloaded anything in the data or instruction cache that might have\r
+++ * changed in real ram.\r
+++ */\r
+++static __inline__ __attribute__((always_inline)) void __wbinvd(void)\r
+++{\r
+++ __asm__("eieio\n\t"\r
+++ "dcs\n\t"\r
+++ "sync\n\t"\r
+++ "isync\n\t");\r
+++}\r
+ #else\r
+ /* TODO: the x64 architecture shares most of the intrinsics. It should be easy to support */\r
+ #error Unsupported architecture\r
+ #endif\r
+ \r
+ \r
+ /*** Miscellaneous ***/\r
+ /* BUGBUG: only good for use in macros. Cannot be taken the address of */\r
+ #define __noop(...) ((void)0)\r
+ \r
+ /* TODO: __assume. GCC only supports the weaker __builtin_expect */\r
+ \r
+ #endif\r
+ \r
+ /* EOF */\r
/* Names common to Winsock1.1 and Winsock2 */
#if !defined ( _BSDTYPES_DEFINED )
/* also defined in gmon.h and in cygwin's sys/types */
+++#if 0
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
+++#endif
#define _BSDTYPES_DEFINED
#endif /* ! def _BSDTYPES_DEFINED */
typedef u_int SOCKET;
---/*\r
--- * PROJECT: registry manipulation library\r
--- * LICENSE: GPL - See COPYING in the top level directory\r
--- * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>\r
--- * Copyright 2001 - 2005 Eric Kohl\r
--- */\r
---\r
---#ifndef CMLIB_CMDATA_H\r
---#define CMLIB_CMDATA_H\r
---\r
---#define REG_INIT_BLOCK_LIST_SIZE 32\r
---#define REG_INIT_HASH_TABLE_SIZE 3\r
---#define REG_EXTEND_HASH_TABLE_SIZE 4\r
---#define REG_VALUE_LIST_CELL_MULTIPLE 4\r
---\r
---#define REG_KEY_CELL_ID 0x6b6e\r
---#define REG_HASH_TABLE_CELL_ID 0x666c\r
---#define REG_VALUE_CELL_ID 0x6b76\r
---#define REG_SECURITY_CELL_ID 0x6b73\r
--\r
--#ifndef _CM_\r
---\r
---#include <pshpack1.h>\r
---\r
---typedef struct _CM_VIEW_OF_FILE\r
---{\r
--- LIST_ENTRY LRUViewList;\r
--- LIST_ENTRY PinViewList;\r
--- ULONG FileOffset;\r
--- ULONG Size;\r
--- PULONG ViewAddress;\r
--- PVOID Bcb;\r
--- ULONG UseCount;\r
---} CM_VIEW_OF_FILE, *PCM_VIEW_OF_FILE;\r
---\r
---typedef struct _CHILD_LIST\r
---{\r
--- ULONG Count;\r
--- HCELL_INDEX List;\r
---} CHILD_LIST, *PCHILD_LIST;\r
---\r
---typedef struct _CM_KEY_NODE\r
---{\r
--- /* Key cell identifier "kn" (0x6b6e) */\r
--- USHORT Id;\r
---\r
--- /* Flags */\r
--- USHORT Flags;\r
---\r
--- /* Time of last flush */\r
--- LARGE_INTEGER LastWriteTime;\r
---\r
--- ULONG Spare;\r
---\r
--- /* BlockAddress offset of parent key cell */\r
--- HCELL_INDEX Parent;\r
---\r
--- /* Count of sub keys for the key in this key cell (stable & volatile) */\r
--- ULONG SubKeyCounts[HvMaxStorageType];\r
---\r
--- /* BlockAddress offset of has table for FIXME: subkeys/values? (stable & volatile) */\r
--- HCELL_INDEX SubKeyLists[HvMaxStorageType];\r
---\r
--- CHILD_LIST ValueList;\r
---\r
--- /* BlockAddress offset of security cell */\r
--- HCELL_INDEX SecurityKeyOffset;\r
---\r
--- /* BlockAddress offset of registry key class */\r
--- HCELL_INDEX ClassNameOffset;\r
---\r
--- ULONG MaxNameLen;\r
--- ULONG MaxClassLen;\r
--- ULONG MaxValueNameLen;\r
--- ULONG MaxValueDataLen;\r
--- ULONG WorkVar;\r
---\r
--- /* Size in bytes of key name */\r
--- USHORT NameSize;\r
---\r
--- /* Size of class name in bytes */\r
--- USHORT ClassSize;\r
---\r
--- /* Name of key (not zero terminated) */\r
--- UCHAR Name[0];\r
---} CM_KEY_NODE, *PCM_KEY_NODE;\r
---\r
---/* CM_KEY_NODE.Flags constants */\r
---#define REG_KEY_VOLATILE_CELL 0x01\r
---#define REG_KEY_ROOT_CELL 0x0C\r
---#define REG_KEY_LINK_CELL 0x10\r
---#define REG_KEY_NAME_PACKED 0x20\r
---\r
---/*\r
--- * Hash record\r
--- *\r
--- * HashValue:\r
--- * packed name: four letters of value's name\r
--- * otherwise: Zero!\r
--- */\r
---typedef struct _HASH_RECORD\r
---{\r
--- HCELL_INDEX KeyOffset;\r
--- ULONG HashValue;\r
---} HASH_RECORD, *PHASH_RECORD;\r
---\r
---typedef struct _HASH_TABLE_CELL\r
---{\r
--- USHORT Id;\r
--- USHORT HashTableSize;\r
--- HASH_RECORD Table[0];\r
---} HASH_TABLE_CELL, *PHASH_TABLE_CELL;\r
---\r
---typedef struct _VALUE_LIST_CELL\r
---{\r
--- HCELL_INDEX ValueOffset[0];\r
---} VALUE_LIST_CELL, *PVALUE_LIST_CELL;\r
---\r
---typedef struct _CM_KEY_VALUE\r
---{\r
--- USHORT Id; // "kv"\r
--- USHORT NameSize; // length of Name\r
--- ULONG DataSize; // length of datas in the cell pointed by DataOffset\r
--- HCELL_INDEX DataOffset;// datas are here if high bit of DataSize is set\r
--- ULONG DataType;\r
--- USHORT Flags;\r
--- USHORT Unused1;\r
--- UCHAR Name[0]; /* warning : not zero terminated */\r
---} CM_KEY_VALUE, *PCM_KEY_VALUE;\r
---\r
---/* CM_KEY_VALUE.Flags constants */\r
---#define REG_VALUE_NAME_PACKED 0x0001\r
---\r
---/* CM_KEY_VALUE.DataSize mask constants */\r
---#define REG_DATA_SIZE_MASK 0x7FFFFFFF\r
---#define REG_DATA_IN_OFFSET 0x80000000\r
---\r
---typedef struct _CM_KEY_SECURITY\r
---{\r
--- USHORT Signature; // "sk"\r
--- USHORT Reserved;\r
--- HCELL_INDEX Flink;\r
--- HCELL_INDEX Blink;\r
--- ULONG ReferenceCount;\r
--- ULONG DescriptorLength;\r
--- //SECURITY_DESCRIPTOR_RELATIVE Descriptor;\r
--- UCHAR Data[0];\r
---} CM_KEY_SECURITY, *PCM_KEY_SECURITY;\r
---\r
---#include <poppack.h>\r
--\r
--#endif\r
---\r
---#endif /* CMLIB_CMDATA_H */\r
+++/*
+++ * PROJECT: registry manipulation library
+++ * LICENSE: GPL - See COPYING in the top level directory
+++ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>
+++ * Copyright 2001 - 2005 Eric Kohl
+++ */
+++
+++#ifndef CMLIB_CMDATA_H
+++#define CMLIB_CMDATA_H
+++
+++#define REG_INIT_BLOCK_LIST_SIZE 32
+++#define REG_INIT_HASH_TABLE_SIZE 3
+++#define REG_EXTEND_HASH_TABLE_SIZE 4
+++#define REG_VALUE_LIST_CELL_MULTIPLE 4
+++
+++#define REG_KEY_CELL_ID 0x6b6e
+++#define REG_HASH_TABLE_CELL_ID 0x666c
+++#define REG_VALUE_CELL_ID 0x6b76
+++#define REG_SECURITY_CELL_ID 0x6b73
+++
+++#ifndef _CM_
+++
+++#include <pshpack1.h>
+++
+++typedef struct _CM_VIEW_OF_FILE
+++{
+++ LIST_ENTRY LRUViewList;
+++ LIST_ENTRY PinViewList;
+++ ULONG FileOffset;
+++ ULONG Size;
+++ PULONG ViewAddress;
+++ PVOID Bcb;
+++ ULONG UseCount;
+++} CM_VIEW_OF_FILE, *PCM_VIEW_OF_FILE;
+++
+++typedef struct _CHILD_LIST
+++{
+++ ULONG Count;
+++ HCELL_INDEX List;
+++} CHILD_LIST, *PCHILD_LIST;
+++
+++typedef struct _CM_KEY_NODE
+++{
+++ /* Key cell identifier "kn" (0x6b6e) */
+++ USHORT Id;
+++
+++ /* Flags */
+++ USHORT Flags;
+++
+++ /* Time of last flush */
+++ LARGE_INTEGER LastWriteTime;
+++
+++ ULONG Spare;
+++
+++ /* BlockAddress offset of parent key cell */
+++ HCELL_INDEX Parent;
+++
+++ /* Count of sub keys for the key in this key cell (stable & volatile) */
+++ ULONG SubKeyCounts[HvMaxStorageType];
+++
+++ /* BlockAddress offset of has table for FIXME: subkeys/values? (stable & volatile) */
+++ HCELL_INDEX SubKeyLists[HvMaxStorageType];
+++
+++ CHILD_LIST ValueList;
+++
+++ /* BlockAddress offset of security cell */
+++ HCELL_INDEX SecurityKeyOffset;
+++
+++ /* BlockAddress offset of registry key class */
+++ HCELL_INDEX ClassNameOffset;
+++
+++ ULONG MaxNameLen;
+++ ULONG MaxClassLen;
+++ ULONG MaxValueNameLen;
+++ ULONG MaxValueDataLen;
+++ ULONG WorkVar;
+++
+++ /* Size in bytes of key name */
+++ USHORT NameSize;
+++
+++ /* Size of class name in bytes */
+++ USHORT ClassSize;
+++
+++ /* Name of key (not zero terminated) */
+++ UCHAR Name[0];
+++} CM_KEY_NODE, *PCM_KEY_NODE;
+++
+++/* CM_KEY_NODE.Flags constants */
+++#define REG_KEY_VOLATILE_CELL 0x01
+++#define REG_KEY_ROOT_CELL 0x0C
+++#define REG_KEY_LINK_CELL 0x10
+++#define REG_KEY_NAME_PACKED 0x20
+++
+++/*
+++ * Hash record
+++ *
+++ * HashValue:
+++ * packed name: four letters of value's name
+++ * otherwise: Zero!
+++ */
+++typedef struct _HASH_RECORD
+++{
+++ HCELL_INDEX KeyOffset;
+++ ULONG HashValue;
+++} HASH_RECORD, *PHASH_RECORD;
+++
+++typedef struct _HASH_TABLE_CELL
+++{
+++ USHORT Id;
+++ USHORT HashTableSize;
+++ HASH_RECORD Table[0];
+++} HASH_TABLE_CELL, *PHASH_TABLE_CELL;
+++
+++typedef struct _VALUE_LIST_CELL
+++{
+++ HCELL_INDEX ValueOffset[0];
+++} VALUE_LIST_CELL, *PVALUE_LIST_CELL;
+++
+++typedef struct _CM_KEY_VALUE
+++{
+++ USHORT Id; // "kv"
+++ USHORT NameSize; // length of Name
+++ ULONG DataSize; // length of datas in the cell pointed by DataOffset
+++ HCELL_INDEX DataOffset;// datas are here if high bit of DataSize is set
+++ ULONG DataType;
+++ USHORT Flags;
+++ USHORT Unused1;
+++ UCHAR Name[0]; /* warning : not zero terminated */
+++} CM_KEY_VALUE, *PCM_KEY_VALUE;
+++
+++/* CM_KEY_VALUE.Flags constants */
+++#define REG_VALUE_NAME_PACKED 0x0001
+++
+++/* CM_KEY_VALUE.DataSize mask constants */
+++#define REG_DATA_SIZE_MASK 0x7FFFFFFF
+++#define REG_DATA_IN_OFFSET 0x80000000
+++
+++typedef struct _CM_KEY_SECURITY
+++{
+++ USHORT Signature; // "sk"
+++ USHORT Reserved;
+++ HCELL_INDEX Flink;
+++ HCELL_INDEX Blink;
+++ ULONG ReferenceCount;
+++ ULONG DescriptorLength;
+++ //SECURITY_DESCRIPTOR_RELATIVE Descriptor;
+++ UCHAR Data[0];
+++} CM_KEY_SECURITY, *PCM_KEY_SECURITY;
+++
+++#include <poppack.h>
+++
+++#endif
+++
+++#endif /* CMLIB_CMDATA_H */
---/*\r
--- * PROJECT: registry manipulation library\r
--- * LICENSE: GPL - See COPYING in the top level directory\r
--- * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>\r
--- * Copyright 2001 - 2005 Eric Kohl\r
--- */\r
---\r
---#include "cmlib.h"\r
---\r
---BOOLEAN CMAPI\r
---CmCreateRootNode(\r
--- PHHIVE Hive,\r
--- PCWSTR Name)\r
---{\r
--- PCM_KEY_NODE KeyCell;\r
--- HCELL_INDEX RootCellIndex;\r
- ULONG NameSize;\r
-- SIZE_T NameSize;\r
---\r
--- NameSize = wcslen(Name) * sizeof(WCHAR);\r
--- RootCellIndex = HvAllocateCell(Hive, sizeof(CM_KEY_NODE) + NameSize, HvStable);\r
--- if (RootCellIndex == HCELL_NULL)\r
--- return FALSE;\r
---\r
--- Hive->HiveHeader->RootCell = RootCellIndex;\r
--- Hive->HiveHeader->Checksum = HvpHiveHeaderChecksum(Hive->HiveHeader);\r
---\r
--- KeyCell = (PCM_KEY_NODE)HvGetCell(Hive, RootCellIndex);\r
--- KeyCell->Id = REG_KEY_CELL_ID;\r
--- KeyCell->Flags = REG_KEY_ROOT_CELL;\r
--- KeyCell->LastWriteTime.QuadPart = 0;\r
--- KeyCell->Parent = HCELL_NULL;\r
--- KeyCell->SubKeyCounts[0] = 0;\r
--- KeyCell->SubKeyCounts[1] = 0;\r
--- KeyCell->SubKeyLists[0] = HCELL_NULL;\r
--- KeyCell->SubKeyLists[1] = HCELL_NULL;\r
--- KeyCell->ValueList.Count = 0;\r
--- KeyCell->ValueList.List = HCELL_NULL;\r
--- KeyCell->SecurityKeyOffset = HCELL_NULL;\r
--- KeyCell->ClassNameOffset = HCELL_NULL; \r
- KeyCell->NameSize = NameSize;\r
-- KeyCell->NameSize = (USHORT)NameSize;\r
--- KeyCell->ClassSize = 0;\r
--- memcpy(KeyCell->Name, Name, NameSize);\r
---\r
--- return TRUE;\r
---}\r
---\r
---static VOID CMAPI\r
---CmpPrepareKey(\r
--- PHHIVE RegistryHive,\r
--- PCM_KEY_NODE KeyCell)\r
---{\r
--- PCM_KEY_NODE SubKeyCell;\r
--- PHASH_TABLE_CELL HashCell;\r
--- ULONG i;\r
---\r
--- ASSERT(KeyCell->Id == REG_KEY_CELL_ID);\r
---\r
--- KeyCell->SubKeyLists[HvVolatile] = HCELL_NULL;\r
--- KeyCell->SubKeyCounts[HvVolatile] = 0;\r
---\r
--- /* Enumerate and add subkeys */\r
--- if (KeyCell->SubKeyCounts[HvStable] > 0)\r
--- {\r
--- HashCell = HvGetCell(RegistryHive, KeyCell->SubKeyLists[HvStable]);\r
---\r
--- for (i = 0; i < KeyCell->SubKeyCounts[HvStable]; i++)\r
--- {\r
--- SubKeyCell = HvGetCell(RegistryHive, HashCell->Table[i].KeyOffset);\r
--- CmpPrepareKey(RegistryHive, SubKeyCell);\r
--- }\r
--- }\r
---}\r
---\r
---VOID CMAPI\r
---CmPrepareHive(\r
--- PHHIVE RegistryHive)\r
---{ \r
--- PCM_KEY_NODE RootCell;\r
---\r
--- RootCell = HvGetCell(RegistryHive, RegistryHive->HiveHeader->RootCell);\r
--- CmpPrepareKey(RegistryHive, RootCell);\r
---}\r
+++/*
+++ * PROJECT: registry manipulation library
+++ * LICENSE: GPL - See COPYING in the top level directory
+++ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>
+++ * Copyright 2001 - 2005 Eric Kohl
+++ */
+++
+++#include "cmlib.h"
+++
+++BOOLEAN CMAPI
+++CmCreateRootNode(
+++ PHHIVE Hive,
+++ PCWSTR Name)
+++{
+++ PCM_KEY_NODE KeyCell;
+++ HCELL_INDEX RootCellIndex;
+++ SIZE_T NameSize;
+++
+++ NameSize = wcslen(Name) * sizeof(WCHAR);
+++ RootCellIndex = HvAllocateCell(Hive, sizeof(CM_KEY_NODE) + NameSize, HvStable);
+++ if (RootCellIndex == HCELL_NULL)
+++ return FALSE;
+++
+++ Hive->HiveHeader->RootCell = RootCellIndex;
+++ Hive->HiveHeader->Checksum = HvpHiveHeaderChecksum(Hive->HiveHeader);
+++
+++ KeyCell = (PCM_KEY_NODE)HvGetCell(Hive, RootCellIndex);
+++ KeyCell->Id = REG_KEY_CELL_ID;
+++ KeyCell->Flags = REG_KEY_ROOT_CELL;
+++ KeyCell->LastWriteTime.QuadPart = 0;
+++ KeyCell->Parent = HCELL_NULL;
+++ KeyCell->SubKeyCounts[0] = 0;
+++ KeyCell->SubKeyCounts[1] = 0;
+++ KeyCell->SubKeyLists[0] = HCELL_NULL;
+++ KeyCell->SubKeyLists[1] = HCELL_NULL;
+++ KeyCell->ValueList.Count = 0;
+++ KeyCell->ValueList.List = HCELL_NULL;
+++ KeyCell->SecurityKeyOffset = HCELL_NULL;
+++ KeyCell->ClassNameOffset = HCELL_NULL;
+++ KeyCell->NameSize = (USHORT)NameSize;
+++ KeyCell->ClassSize = 0;
+++ memcpy(KeyCell->Name, Name, NameSize);
+++
+++ return TRUE;
+++}
+++
+++static VOID CMAPI
+++CmpPrepareKey(
+++ PHHIVE RegistryHive,
+++ PCM_KEY_NODE KeyCell)
+++{
+++ PCM_KEY_NODE SubKeyCell;
+++ PHASH_TABLE_CELL HashCell;
+++ ULONG i;
+++
+++ ASSERT(KeyCell->Id == REG_KEY_CELL_ID);
+++
+++ KeyCell->SubKeyLists[HvVolatile] = HCELL_NULL;
+++ KeyCell->SubKeyCounts[HvVolatile] = 0;
+++
+++ /* Enumerate and add subkeys */
+++ if (KeyCell->SubKeyCounts[HvStable] > 0)
+++ {
+++ HashCell = HvGetCell(RegistryHive, KeyCell->SubKeyLists[HvStable]);
+++
+++ for (i = 0; i < KeyCell->SubKeyCounts[HvStable]; i++)
+++ {
+++ SubKeyCell = HvGetCell(RegistryHive, HashCell->Table[i].KeyOffset);
+++ CmpPrepareKey(RegistryHive, SubKeyCell);
+++ }
+++ }
+++}
+++
+++VOID CMAPI
+++CmPrepareHive(
+++ PHHIVE RegistryHive)
+++{
+++ PCM_KEY_NODE RootCell;
+++
+++ RootCell = HvGetCell(RegistryHive, RegistryHive->HiveHeader->RootCell);
+++ CmpPrepareKey(RegistryHive, RootCell);
+++}
---/*\r
--- * PROJECT: registry manipulation library\r
--- * LICENSE: GPL - See COPYING in the top level directory\r
--- * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>\r
--- * Copyright 2001 - 2005 Eric Kohl\r
--- */\r
---\r
---#ifndef CMLIB_H\r
---#define CMLIB_H\r
---\r
--#define WIN32_NO_STATUS\r
---#include <ntddk.h>\r
---#include "hivedata.h"\r
---#include "cmdata.h"\r
---\r
---#ifndef ROUND_UP\r
---#define ROUND_UP(a,b) ((((a)+(b)-1)/(b))*(b))\r
---#define ROUND_DOWN(a,b) (((a)/(b))*(b))\r
---#endif\r
---\r
- #define CMAPI\r
--#define CMAPI NTAPI\r
---\r
---struct _HHIVE;\r
---\r
---typedef PVOID (CMAPI *PGET_CELL_ROUTINE)(\r
--- struct _HHIVE *Hive,\r
--- HCELL_INDEX Cell);\r
---\r
---typedef VOID (CMAPI *PRELEASE_CELL_ROUTINE)(\r
--- struct _HHIVE *Hive,\r
--- HCELL_INDEX Cell);\r
---\r
---typedef PVOID (CMAPI *PALLOCATE_ROUTINE)(\r
- ULONG Size,\r
-- SIZE_T Size,\r
--- BOOLEAN Paged);\r
---\r
---typedef VOID (CMAPI *PFREE_ROUTINE)(\r
--- PVOID Ptr);\r
---\r
---typedef BOOLEAN (CMAPI *PFILE_READ_ROUTINE)(\r
--- struct _HHIVE *RegistryHive,\r
--- ULONG FileType,\r
- ULONG FileOffset,\r
-- ULONGLONG FileOffset,\r
--- PVOID Buffer,\r
- ULONG BufferLength);\r
-- SIZE_T BufferLength);\r
---\r
---typedef BOOLEAN (CMAPI *PFILE_WRITE_ROUTINE)(\r
--- struct _HHIVE *RegistryHive,\r
--- ULONG FileType,\r
- ULONG FileOffset,\r
-- ULONGLONG FileOffset,\r
--- PVOID Buffer,\r
- ULONG BufferLength);\r
-- SIZE_T BufferLength);\r
---\r
---typedef BOOLEAN (CMAPI *PFILE_SET_SIZE_ROUTINE)(\r
--- struct _HHIVE *RegistryHive,\r
--- ULONG FileType,\r
- ULONG FileSize);\r
-- ULONGLONG FileSize);\r
---\r
---typedef BOOLEAN (CMAPI *PFILE_FLUSH_ROUTINE)(\r
--- struct _HHIVE *RegistryHive,\r
--- ULONG FileType);\r
---\r
---typedef struct _HMAP_ENTRY\r
---{\r
--- ULONG_PTR Bin;\r
--- ULONG_PTR Block;\r
- PCM_VIEW_OF_FILE CmHive;\r
-- struct _CM_VIEW_OF_FILE *CmHive;\r
--- ULONG MemAlloc;\r
---} HMAP_ENTRY, *PHMAP_ENTRY;\r
---\r
---typedef struct _HMAP_TABLE\r
---{\r
--- HMAP_ENTRY Table[512];\r
---} HMAP_TABLE, *PHMAP_TABLE;\r
---\r
---typedef struct _HMAP_DIRECTORY\r
---{\r
--- PHMAP_TABLE Directory[2048];\r
---} HMAP_DIRECTORY, *PHMAP_DIRECTORY;\r
---\r
---typedef struct _DUAL\r
---{\r
--- ULONG Length;\r
--- PHMAP_DIRECTORY Map;\r
--- PHMAP_ENTRY BlockList; // PHMAP_TABLE SmallDir;\r
--- ULONG Guard;\r
--- HCELL_INDEX FreeDisplay[24]; //FREE_DISPLAY FreeDisplay[24];\r
--- ULONG FreeSummary;\r
--- LIST_ENTRY FreeBins;\r
---} DUAL, *PDUAL;\r
---\r
---typedef struct _HHIVE\r
---{\r
--- ULONG Signature;\r
--- PGET_CELL_ROUTINE GetCellRoutine;\r
--- PRELEASE_CELL_ROUTINE ReleaseCellRoutine;\r
--- PALLOCATE_ROUTINE Allocate;\r
--- PFREE_ROUTINE Free;\r
--- PFILE_READ_ROUTINE FileRead;\r
--- PFILE_WRITE_ROUTINE FileWrite;\r
--- PFILE_SET_SIZE_ROUTINE FileSetSize;\r
--- PFILE_FLUSH_ROUTINE FileFlush;\r
--- PHBASE_BLOCK HiveHeader;\r
--- RTL_BITMAP DirtyVector;\r
--- ULONG DirtyCount;\r
--- ULONG DirtyAlloc;\r
--- ULONG BaseBlockAlloc;\r
--- ULONG Cluster;\r
--- BOOLEAN Flat;\r
--- BOOLEAN ReadOnly;\r
--- BOOLEAN Log;\r
--- BOOLEAN DirtyFlag;\r
-- ULONG HvBinHeadersUse;\r
-- ULONG HvFreeCellsUse;\r
-- ULONG HvUsedcellsUse;\r
-- ULONG CmUsedCellsUse;\r
--- ULONG HiveFlags;\r
--- ULONG LogSize;\r
--- ULONG RefreshCount;\r
--- ULONG StorageTypeCount;\r
--- ULONG Version;\r
--- DUAL Storage[HvMaxStorageType];\r
---} HHIVE, *PHHIVE;\r
---\r
--#ifndef _CM_\r
---typedef struct _EREGISTRY_HIVE\r
---{\r
--- HHIVE Hive;\r
--- LIST_ENTRY HiveList;\r
--- UNICODE_STRING HiveFileName;\r
--- UNICODE_STRING LogFileName;\r
--- PCM_KEY_SECURITY RootSecurityCell;\r
--- ULONG Flags;\r
--- HANDLE HiveHandle;\r
--- HANDLE LogHandle;\r
---} EREGISTRY_HIVE, *PEREGISTRY_HIVE;\r
--#endif\r
---\r
---/*\r
--- * Public functions.\r
--- */\r
---\r
---#define HV_OPERATION_CREATE_HIVE 0\r
---#define HV_OPERATION_MEMORY 1\r
---#define HV_OPERATION_MEMORY_INPLACE 3\r
---\r
---NTSTATUS CMAPI\r
---HvInitialize(\r
--- PHHIVE RegistryHive,\r
--- ULONG Operation,\r
--- ULONG_PTR HiveData OPTIONAL,\r
--- ULONG Cluster OPTIONAL,\r
-- ULONG Flags,\r
-- ULONG FileType,\r
--- PALLOCATE_ROUTINE Allocate,\r
--- PFREE_ROUTINE Free,\r
--- PFILE_READ_ROUTINE FileRead,\r
--- PFILE_WRITE_ROUTINE FileWrite,\r
--- PFILE_SET_SIZE_ROUTINE FileSetSize,\r
--- PFILE_FLUSH_ROUTINE FileFlush,\r
--- IN PUNICODE_STRING FileName);\r
---\r
---VOID CMAPI \r
---HvFree(\r
--- PHHIVE RegistryHive);\r
---\r
---PVOID CMAPI\r
---HvGetCell(\r
--- PHHIVE RegistryHive,\r
--- HCELL_INDEX CellOffset);\r
--\r
--#define HvReleaseCell(h, c) \\r
-- if (h->ReleaseCellRoutine) h->ReleaseCellRoutine(h, c)\r
---\r
---LONG CMAPI\r
---HvGetCellSize(\r
--- PHHIVE RegistryHive,\r
--- PVOID Cell);\r
---\r
---HCELL_INDEX CMAPI\r
---HvAllocateCell(\r
--- PHHIVE RegistryHive,\r
- ULONG Size,\r
-- SIZE_T Size,\r
--- HV_STORAGE_TYPE Storage);\r
---\r
---HCELL_INDEX CMAPI\r
---HvReallocateCell(\r
--- PHHIVE RegistryHive,\r
--- HCELL_INDEX CellOffset,\r
--- ULONG Size);\r
---\r
---VOID CMAPI\r
---HvFreeCell(\r
--- PHHIVE RegistryHive,\r
--- HCELL_INDEX CellOffset);\r
---\r
---VOID CMAPI\r
---HvMarkCellDirty(\r
--- PHHIVE RegistryHive,\r
--- HCELL_INDEX CellOffset);\r
---\r
---BOOLEAN CMAPI\r
---HvSyncHive(\r
--- PHHIVE RegistryHive);\r
---\r
---BOOLEAN CMAPI\r
---HvWriteHive(\r
--- PHHIVE RegistryHive);\r
---\r
---BOOLEAN CMAPI\r
---CmCreateRootNode(\r
--- PHHIVE Hive,\r
--- PCWSTR Name);\r
---\r
---VOID CMAPI\r
---CmPrepareHive(\r
--- PHHIVE RegistryHive);\r
---\r
---/*\r
--- * Private functions.\r
--- */\r
---\r
---PHBIN CMAPI\r
---HvpAddBin(\r
--- PHHIVE RegistryHive,\r
--- ULONG Size,\r
--- HV_STORAGE_TYPE Storage);\r
---\r
---NTSTATUS CMAPI\r
---HvpCreateHiveFreeCellList(\r
--- PHHIVE Hive);\r
---\r
---ULONG CMAPI\r
---HvpHiveHeaderChecksum(\r
--- PHBASE_BLOCK HiveHeader);\r
---\r
---#endif /* CMLIB_H */\r
+++/*
+++ * PROJECT: registry manipulation library
+++ * LICENSE: GPL - See COPYING in the top level directory
+++ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>
+++ * Copyright 2001 - 2005 Eric Kohl
+++ */
+++
+++#ifndef CMLIB_H
+++#define CMLIB_H
+++
+++#define WIN32_NO_STATUS
+++#include <ntddk.h>
+++#include "hivedata.h"
+++#include "cmdata.h"
+++
+++#ifndef ROUND_UP
+++#define ROUND_UP(a,b) ((((a)+(b)-1)/(b))*(b))
+++#define ROUND_DOWN(a,b) (((a)/(b))*(b))
+++#endif
+++
+++#define CMAPI NTAPI
+++
+++struct _HHIVE;
+++
+++typedef PVOID (CMAPI *PGET_CELL_ROUTINE)(
+++ struct _HHIVE *Hive,
+++ HCELL_INDEX Cell);
+++
+++typedef VOID (CMAPI *PRELEASE_CELL_ROUTINE)(
+++ struct _HHIVE *Hive,
+++ HCELL_INDEX Cell);
+++
+++typedef PVOID (CMAPI *PALLOCATE_ROUTINE)(
+++ SIZE_T Size,
+++ BOOLEAN Paged);
+++
+++typedef VOID (CMAPI *PFREE_ROUTINE)(
+++ PVOID Ptr);
+++
+++typedef BOOLEAN (CMAPI *PFILE_READ_ROUTINE)(
+++ struct _HHIVE *RegistryHive,
+++ ULONG FileType,
+++ ULONGLONG FileOffset,
+++ PVOID Buffer,
+++ SIZE_T BufferLength);
+++
+++typedef BOOLEAN (CMAPI *PFILE_WRITE_ROUTINE)(
+++ struct _HHIVE *RegistryHive,
+++ ULONG FileType,
+++ ULONGLONG FileOffset,
+++ PVOID Buffer,
+++ SIZE_T BufferLength);
+++
+++typedef BOOLEAN (CMAPI *PFILE_SET_SIZE_ROUTINE)(
+++ struct _HHIVE *RegistryHive,
+++ ULONG FileType,
+++ ULONGLONG FileSize);
+++
+++typedef BOOLEAN (CMAPI *PFILE_FLUSH_ROUTINE)(
+++ struct _HHIVE *RegistryHive,
+++ ULONG FileType);
+++
+++typedef struct _HMAP_ENTRY
+++{
+++ ULONG_PTR Bin;
+++ ULONG_PTR Block;
+++ struct _CM_VIEW_OF_FILE *CmHive;
+++ ULONG MemAlloc;
+++} HMAP_ENTRY, *PHMAP_ENTRY;
+++
+++typedef struct _HMAP_TABLE
+++{
+++ HMAP_ENTRY Table[512];
+++} HMAP_TABLE, *PHMAP_TABLE;
+++
+++typedef struct _HMAP_DIRECTORY
+++{
+++ PHMAP_TABLE Directory[2048];
+++} HMAP_DIRECTORY, *PHMAP_DIRECTORY;
+++
+++typedef struct _DUAL
+++{
+++ ULONG Length;
+++ PHMAP_DIRECTORY Map;
+++ PHMAP_ENTRY BlockList; // PHMAP_TABLE SmallDir;
+++ ULONG Guard;
+++ HCELL_INDEX FreeDisplay[24]; //FREE_DISPLAY FreeDisplay[24];
+++ ULONG FreeSummary;
+++ LIST_ENTRY FreeBins;
+++} DUAL, *PDUAL;
+++
+++typedef struct _HHIVE
+++{
+++ ULONG Signature;
+++ PGET_CELL_ROUTINE GetCellRoutine;
+++ PRELEASE_CELL_ROUTINE ReleaseCellRoutine;
+++ PALLOCATE_ROUTINE Allocate;
+++ PFREE_ROUTINE Free;
+++ PFILE_READ_ROUTINE FileRead;
+++ PFILE_WRITE_ROUTINE FileWrite;
+++ PFILE_SET_SIZE_ROUTINE FileSetSize;
+++ PFILE_FLUSH_ROUTINE FileFlush;
+++ PHBASE_BLOCK HiveHeader;
+++ RTL_BITMAP DirtyVector;
+++ ULONG DirtyCount;
+++ ULONG DirtyAlloc;
+++ ULONG BaseBlockAlloc;
+++ ULONG Cluster;
+++ BOOLEAN Flat;
+++ BOOLEAN ReadOnly;
+++ BOOLEAN Log;
+++ BOOLEAN DirtyFlag;
+++ ULONG HvBinHeadersUse;
+++ ULONG HvFreeCellsUse;
+++ ULONG HvUsedcellsUse;
+++ ULONG CmUsedCellsUse;
+++ ULONG HiveFlags;
+++ ULONG LogSize;
+++ ULONG RefreshCount;
+++ ULONG StorageTypeCount;
+++ ULONG Version;
+++ DUAL Storage[HvMaxStorageType];
+++} HHIVE, *PHHIVE;
+++
+++#ifndef _CM_
+++typedef struct _EREGISTRY_HIVE
+++{
+++ HHIVE Hive;
+++ LIST_ENTRY HiveList;
+++ UNICODE_STRING HiveFileName;
+++ UNICODE_STRING LogFileName;
+++ PCM_KEY_SECURITY RootSecurityCell;
+++ ULONG Flags;
+++ HANDLE HiveHandle;
+++ HANDLE LogHandle;
+++} EREGISTRY_HIVE, *PEREGISTRY_HIVE;
+++#endif
+++
+++/*
+++ * Public functions.
+++ */
+++
+++#define HV_OPERATION_CREATE_HIVE 0
+++#define HV_OPERATION_MEMORY 1
+++#define HV_OPERATION_MEMORY_INPLACE 3
+++
+++NTSTATUS CMAPI
+++HvInitialize(
+++ PHHIVE RegistryHive,
+++ ULONG Operation,
+++ ULONG_PTR HiveData OPTIONAL,
+++ ULONG Cluster OPTIONAL,
+++ ULONG Flags,
+++ ULONG FileType,
+++ PALLOCATE_ROUTINE Allocate,
+++ PFREE_ROUTINE Free,
+++ PFILE_READ_ROUTINE FileRead,
+++ PFILE_WRITE_ROUTINE FileWrite,
+++ PFILE_SET_SIZE_ROUTINE FileSetSize,
+++ PFILE_FLUSH_ROUTINE FileFlush,
+++ IN PUNICODE_STRING FileName);
+++
+++VOID CMAPI
+++HvFree(
+++ PHHIVE RegistryHive);
+++
+++PVOID CMAPI
+++HvGetCell(
+++ PHHIVE RegistryHive,
+++ HCELL_INDEX CellOffset);
+++
+++#define HvReleaseCell(h, c) \
+++ if (h->ReleaseCellRoutine) h->ReleaseCellRoutine(h, c)
+++
+++LONG CMAPI
+++HvGetCellSize(
+++ PHHIVE RegistryHive,
+++ PVOID Cell);
+++
+++HCELL_INDEX CMAPI
+++HvAllocateCell(
+++ PHHIVE RegistryHive,
+++ SIZE_T Size,
+++ HV_STORAGE_TYPE Storage);
+++
+++HCELL_INDEX CMAPI
+++HvReallocateCell(
+++ PHHIVE RegistryHive,
+++ HCELL_INDEX CellOffset,
+++ ULONG Size);
+++
+++VOID CMAPI
+++HvFreeCell(
+++ PHHIVE RegistryHive,
+++ HCELL_INDEX CellOffset);
+++
+++VOID CMAPI
+++HvMarkCellDirty(
+++ PHHIVE RegistryHive,
+++ HCELL_INDEX CellOffset);
+++
+++BOOLEAN CMAPI
+++HvSyncHive(
+++ PHHIVE RegistryHive);
+++
+++BOOLEAN CMAPI
+++HvWriteHive(
+++ PHHIVE RegistryHive);
+++
+++BOOLEAN CMAPI
+++CmCreateRootNode(
+++ PHHIVE Hive,
+++ PCWSTR Name);
+++
+++VOID CMAPI
+++CmPrepareHive(
+++ PHHIVE RegistryHive);
+++
+++/*
+++ * Private functions.
+++ */
+++
+++PHBIN CMAPI
+++HvpAddBin(
+++ PHHIVE RegistryHive,
+++ ULONG Size,
+++ HV_STORAGE_TYPE Storage);
+++
+++NTSTATUS CMAPI
+++HvpCreateHiveFreeCellList(
+++ PHHIVE Hive);
+++
+++ULONG CMAPI
+++HvpHiveHeaderChecksum(
+++ PHBASE_BLOCK HiveHeader);
+++
+++#endif /* CMLIB_H */
---CMLIB_BASE = $(LIB_BASE_)cmlib\r
---CMLIB_BASE_ = $(CMLIB_BASE)$(SEP)\r
---CMLIB_INT = $(INTERMEDIATE_)$(CMLIB_BASE)_host\r
---CMLIB_INT_ = $(INTERMEDIATE_)$(CMLIB_BASE)_host$(SEP)\r
---CMLIB_OUT = $(OUTPUT_)$(CMLIB_BASE)_host\r
---CMLIB_OUT_ = $(OUTPUT_)$(CMLIB_BASE)_host$(SEP)\r
---\r
---$(CMLIB_INT): | $(LIB_INT)\r
--- $(ECHO_MKDIR)\r
--- ${mkdir} $@\r
---\r
---ifneq ($(INTERMEDIATE),$(OUTPUT))\r
---$(CMLIB_OUT): | $(OUTPUT_)$(LIB_BASE)\r
--- $(ECHO_MKDIR)\r
--- ${mkdir} $@\r
---endif\r
---\r
---CMLIB_HOST_TARGET = \\r
--- $(CMLIB_OUT)$(SEP)cmlib.a\r
---\r
---CMLIB_HOST_SOURCES = $(addprefix $(CMLIB_BASE_), \\r
-- cminit.c \\r
--- hivebin.c \\r
--- hivecell.c \\r
--- hiveinit.c \\r
-- hivesum.c \\r
-- hivewrt.c \\r
--- )\r
---\r
---CMLIB_HOST_OBJECTS = \\r
--- $(subst $(CMLIB_BASE), $(CMLIB_INT), $(CMLIB_HOST_SOURCES:.c=.o))\r
---\r
- CMLIB_HOST_CFLAGS = -O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \\r
- -D_X86_ -D__i386__ -D_REACTOS_ \\r
- -DCMLIB_HOST -D_M_IX86 -I$(CMLIB_BASE) -Iinclude/reactos -Iinclude/psdk -Iinclude/ddk \\r
--CMLIB_HOST_CFLAGS = -O3 -Wall -Wwrite-strings -Wpointer-arith \\r
-- -D_X86_ -D__i386__ -D_REACTOS_ -D_NTOSKRNL_\\r
-- -DCMLIB_HOST -D_M_IX86 -I$(CMLIB_BASE) -Iinclude/reactos -Iinclude/psdk -Iinclude/ddk -Iinclude/crt \\r
--- -D__NO_CTYPE_INLINES\r
---\r
---$(CMLIB_HOST_TARGET): $(CMLIB_HOST_OBJECTS) | $(CMLIB_OUT)\r
--- $(ECHO_AR)\r
--- $(host_ar) -r $@ $(CMLIB_HOST_OBJECTS)\r
--\r
--$(CMLIB_INT_)cminit.o: $(CMLIB_BASE_)cminit.c | $(CMLIB_INT)\r
-- $(ECHO_CC)\r
-- ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@\r
---\r
---$(CMLIB_INT_)hivebin.o: $(CMLIB_BASE_)hivebin.c | $(CMLIB_INT)\r
--- $(ECHO_CC)\r
--- ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@\r
---\r
---$(CMLIB_INT_)hivecell.o: $(CMLIB_BASE_)hivecell.c | $(CMLIB_INT)\r
--- $(ECHO_CC)\r
--- ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@\r
---\r
---$(CMLIB_INT_)hiveinit.o: $(CMLIB_BASE_)hiveinit.c | $(CMLIB_INT)\r
-- $(ECHO_CC)\r
-- ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@\r
--\r
--$(CMLIB_INT_)hivesum.o: $(CMLIB_BASE_)hivesum.c | $(CMLIB_INT)\r
-- $(ECHO_CC)\r
-- ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@\r
--\r
--$(CMLIB_INT_)hivewrt.o: $(CMLIB_BASE_)hivewrt.c | $(CMLIB_INT)\r
--- $(ECHO_CC)\r
--- ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@\r
---\r
---.PHONY: cmlib_host\r
---cmlib_host: $(CMLIB_HOST_TARGET)\r
---\r
---.PHONY: cmlib_host_clean\r
---cmlib_host_clean:\r
--- -@$(rm) $(CMLIB_HOST_TARGET) $(CMLIB_HOST_OBJECTS) 2>$(NUL)\r
---clean: cmlib_host_clean\r
+++CMLIB_BASE = $(LIB_BASE_)cmlib
+++CMLIB_BASE_ = $(CMLIB_BASE)$(SEP)
+++CMLIB_INT = $(INTERMEDIATE_)$(CMLIB_BASE)_host
+++CMLIB_INT_ = $(INTERMEDIATE_)$(CMLIB_BASE)_host$(SEP)
+++CMLIB_OUT = $(OUTPUT_)$(CMLIB_BASE)_host
+++CMLIB_OUT_ = $(OUTPUT_)$(CMLIB_BASE)_host$(SEP)
+++
+++$(CMLIB_INT): | $(LIB_INT)
+++ $(ECHO_MKDIR)
+++ ${mkdir} $@
+++
+++ifneq ($(INTERMEDIATE),$(OUTPUT))
+++$(CMLIB_OUT): | $(OUTPUT_)$(LIB_BASE)
+++ $(ECHO_MKDIR)
+++ ${mkdir} $@
+++endif
+++
+++CMLIB_HOST_TARGET = \
+++ $(CMLIB_OUT)$(SEP)cmlib.a
+++
+++CMLIB_HOST_SOURCES = $(addprefix $(CMLIB_BASE_), \
+++ cminit.c \
+++ hivebin.c \
+++ hivecell.c \
+++ hiveinit.c \
+++ hivesum.c \
+++ hivewrt.c \
+++ )
+++
+++CMLIB_HOST_OBJECTS = \
+++ $(subst $(CMLIB_BASE), $(CMLIB_INT), $(CMLIB_HOST_SOURCES:.c=.o))
+++
+++CMLIB_HOST_CFLAGS = -O3 -Wall -Wwrite-strings -Wpointer-arith \
+++ -D_X86_ -D__i386__ -D_REACTOS_ -D_NTOSKRNL_\
+++ -DCMLIB_HOST -D_M_IX86 -I$(CMLIB_BASE) -Iinclude/reactos -Iinclude/psdk -Iinclude/ddk -Iinclude/crt \
+++ -D__NO_CTYPE_INLINES
+++
+++$(CMLIB_HOST_TARGET): $(CMLIB_HOST_OBJECTS) | $(CMLIB_OUT)
+++ $(ECHO_AR)
+++ $(host_ar) -r $@ $(CMLIB_HOST_OBJECTS)
+++
+++$(CMLIB_INT_)cminit.o: $(CMLIB_BASE_)cminit.c | $(CMLIB_INT)
+++ $(ECHO_CC)
+++ ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@
+++
+++$(CMLIB_INT_)hivebin.o: $(CMLIB_BASE_)hivebin.c | $(CMLIB_INT)
+++ $(ECHO_CC)
+++ ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@
+++
+++$(CMLIB_INT_)hivecell.o: $(CMLIB_BASE_)hivecell.c | $(CMLIB_INT)
+++ $(ECHO_CC)
+++ ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@
+++
+++$(CMLIB_INT_)hiveinit.o: $(CMLIB_BASE_)hiveinit.c | $(CMLIB_INT)
+++ $(ECHO_CC)
+++ ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@
+++
+++$(CMLIB_INT_)hivesum.o: $(CMLIB_BASE_)hivesum.c | $(CMLIB_INT)
+++ $(ECHO_CC)
+++ ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@
+++
+++$(CMLIB_INT_)hivewrt.o: $(CMLIB_BASE_)hivewrt.c | $(CMLIB_INT)
+++ $(ECHO_CC)
+++ ${host_gcc} $(CMLIB_HOST_CFLAGS) -c $< -o $@
+++
+++.PHONY: cmlib_host
+++cmlib_host: $(CMLIB_HOST_TARGET)
+++
+++.PHONY: cmlib_host_clean
+++cmlib_host_clean:
+++ -@$(rm) $(CMLIB_HOST_TARGET) $(CMLIB_HOST_OBJECTS) 2>$(NUL)
+++clean: cmlib_host_clean
---/*\r
--- * PROJECT: registry manipulation library\r
--- * LICENSE: GPL - See COPYING in the top level directory\r
--- * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>\r
--- * Copyright 2005 Hartmut Birr\r
--- * Copyright 2001 - 2005 Eric Kohl\r
--- */\r
---\r
---#include "cmlib.h"\r
---\r
---PHBIN CMAPI\r
---HvpAddBin(\r
--- PHHIVE RegistryHive,\r
--- ULONG Size,\r
--- HV_STORAGE_TYPE Storage)\r
---{\r
--- PHMAP_ENTRY BlockList;\r
--- PHBIN Bin;\r
- ULONG BinSize;\r
-- SIZE_T BinSize;\r
--- ULONG i;\r
--- ULONG BitmapSize;\r
--- ULONG BlockCount;\r
--- ULONG OldBlockListSize;\r
--- PHCELL Block;\r
---\r
--- BinSize = ROUND_UP(Size + sizeof(HBIN), HV_BLOCK_SIZE);\r
- BlockCount = BinSize / HV_BLOCK_SIZE;\r
-- BlockCount = (ULONG)(BinSize / HV_BLOCK_SIZE);\r
---\r
--- Bin = RegistryHive->Allocate(BinSize, TRUE);\r
--- if (Bin == NULL)\r
--- return NULL;\r
- RtlZeroMemory(Bin, sizeof(HBIN));\r
-- RtlZeroMemory(Bin, BinSize);\r
---\r
--- Bin->Signature = HV_BIN_SIGNATURE;\r
--- Bin->FileOffset = RegistryHive->Storage[Storage].Length *\r
--- HV_BLOCK_SIZE;\r
- Bin->Size = BinSize;\r
-- Bin->Size = (ULONG)BinSize;\r
---\r
--- /* Allocate new block list */\r
--- OldBlockListSize = RegistryHive->Storage[Storage].Length;\r
--- BlockList = RegistryHive->Allocate(sizeof(HMAP_ENTRY) *\r
--- (OldBlockListSize + BlockCount), TRUE);\r
--- if (BlockList == NULL)\r
--- {\r
--- RegistryHive->Free(Bin);\r
--- return NULL;\r
--- }\r
---\r
--- if (OldBlockListSize > 0)\r
--- {\r
--- RtlCopyMemory(BlockList, RegistryHive->Storage[Storage].BlockList,\r
--- OldBlockListSize * sizeof(HMAP_ENTRY));\r
--- RegistryHive->Free(RegistryHive->Storage[Storage].BlockList);\r
--- }\r
---\r
--- RegistryHive->Storage[Storage].BlockList = BlockList;\r
--- RegistryHive->Storage[Storage].Length += BlockCount;\r
--- \r
--- for (i = 0; i < BlockCount; i++)\r
--- {\r
--- RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].Block =\r
--- ((ULONG_PTR)Bin + (i * HV_BLOCK_SIZE));\r
--- RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].Bin = (ULONG_PTR)Bin;\r
--- }\r
---\r
--- /* Initialize a free block in this heap. */\r
--- Block = (PHCELL)(Bin + 1);\r
- Block->Size = BinSize - sizeof(HBIN);\r
-- Block->Size = (LONG)(BinSize - sizeof(HBIN));\r
---\r
--- if (Storage == HvStable)\r
--- {\r
--- /* Calculate bitmap size in bytes (always a multiple of 32 bits). */\r
--- BitmapSize = ROUND_UP(RegistryHive->Storage[HvStable].Length,\r
--- sizeof(ULONG) * 8) / 8;\r
---\r
--- /* Grow bitmap if necessary. */\r
--- if (BitmapSize > RegistryHive->DirtyVector.SizeOfBitMap / 8)\r
--- {\r
--- PULONG BitmapBuffer;\r
---\r
--- BitmapBuffer = RegistryHive->Allocate(BitmapSize, TRUE);\r
--- RtlZeroMemory(BitmapBuffer, BitmapSize);\r
--- RtlCopyMemory(BitmapBuffer,\r
--- RegistryHive->DirtyVector.Buffer,\r
--- RegistryHive->DirtyVector.SizeOfBitMap / 8);\r
--- RegistryHive->Free(RegistryHive->DirtyVector.Buffer);\r
--- RtlInitializeBitMap(&RegistryHive->DirtyVector, BitmapBuffer,\r
--- BitmapSize * 8);\r
--- }\r
---\r
--- /* Mark new bin dirty. */\r
--- RtlSetBits(&RegistryHive->DirtyVector,\r
--- Bin->FileOffset / HV_BLOCK_SIZE,\r
--- BlockCount);\r
--- }\r
---\r
--- return Bin;\r
---}\r
+++/*
+++ * PROJECT: registry manipulation library
+++ * LICENSE: GPL - See COPYING in the top level directory
+++ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>
+++ * Copyright 2005 Hartmut Birr
+++ * Copyright 2001 - 2005 Eric Kohl
+++ */
+++
+++#include "cmlib.h"
+++
+++PHBIN CMAPI
+++HvpAddBin(
+++ PHHIVE RegistryHive,
+++ ULONG Size,
+++ HV_STORAGE_TYPE Storage)
+++{
+++ PHMAP_ENTRY BlockList;
+++ PHBIN Bin;
+++ SIZE_T BinSize;
+++ ULONG i;
+++ ULONG BitmapSize;
+++ ULONG BlockCount;
+++ ULONG OldBlockListSize;
+++ PHCELL Block;
+++
+++ BinSize = ROUND_UP(Size + sizeof(HBIN), HV_BLOCK_SIZE);
+++ BlockCount = (ULONG)(BinSize / HV_BLOCK_SIZE);
+++
+++ Bin = RegistryHive->Allocate(BinSize, TRUE);
+++ if (Bin == NULL)
+++ return NULL;
+++ RtlZeroMemory(Bin, BinSize);
+++
+++ Bin->Signature = HV_BIN_SIGNATURE;
+++ Bin->FileOffset = RegistryHive->Storage[Storage].Length *
+++ HV_BLOCK_SIZE;
+++ Bin->Size = (ULONG)BinSize;
+++
+++ /* Allocate new block list */
+++ OldBlockListSize = RegistryHive->Storage[Storage].Length;
+++ BlockList = RegistryHive->Allocate(sizeof(HMAP_ENTRY) *
+++ (OldBlockListSize + BlockCount), TRUE);
+++ if (BlockList == NULL)
+++ {
+++ RegistryHive->Free(Bin);
+++ return NULL;
+++ }
+++
+++ if (OldBlockListSize > 0)
+++ {
+++ RtlCopyMemory(BlockList, RegistryHive->Storage[Storage].BlockList,
+++ OldBlockListSize * sizeof(HMAP_ENTRY));
+++ RegistryHive->Free(RegistryHive->Storage[Storage].BlockList);
+++ }
+++
+++ RegistryHive->Storage[Storage].BlockList = BlockList;
+++ RegistryHive->Storage[Storage].Length += BlockCount;
+++
+++ for (i = 0; i < BlockCount; i++)
+++ {
+++ RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].Block =
+++ ((ULONG_PTR)Bin + (i * HV_BLOCK_SIZE));
+++ RegistryHive->Storage[Storage].BlockList[OldBlockListSize + i].Bin = (ULONG_PTR)Bin;
+++ }
+++
+++ /* Initialize a free block in this heap. */
+++ Block = (PHCELL)(Bin + 1);
+++ Block->Size = (LONG)(BinSize - sizeof(HBIN));
+++
+++ if (Storage == HvStable)
+++ {
+++ /* Calculate bitmap size in bytes (always a multiple of 32 bits). */
+++ BitmapSize = ROUND_UP(RegistryHive->Storage[HvStable].Length,
+++ sizeof(ULONG) * 8) / 8;
+++
+++ /* Grow bitmap if necessary. */
+++ if (BitmapSize > RegistryHive->DirtyVector.SizeOfBitMap / 8)
+++ {
+++ PULONG BitmapBuffer;
+++
+++ BitmapBuffer = RegistryHive->Allocate(BitmapSize, TRUE);
+++ RtlZeroMemory(BitmapBuffer, BitmapSize);
+++ RtlCopyMemory(BitmapBuffer,
+++ RegistryHive->DirtyVector.Buffer,
+++ RegistryHive->DirtyVector.SizeOfBitMap / 8);
+++ RegistryHive->Free(RegistryHive->DirtyVector.Buffer);
+++ RtlInitializeBitMap(&RegistryHive->DirtyVector, BitmapBuffer,
+++ BitmapSize * 8);
+++ }
+++
+++ /* Mark new bin dirty. */
+++ RtlSetBits(&RegistryHive->DirtyVector,
+++ Bin->FileOffset / HV_BLOCK_SIZE,
+++ BlockCount);
+++ }
+++
+++ return Bin;
+++}
---/*\r
--- * PROJECT: registry manipulation library\r
--- * LICENSE: GPL - See COPYING in the top level directory\r
--- * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>\r
--- * Copyright 2001 - 2005 Eric Kohl\r
--- */\r
---\r
---#include "cmlib.h"\r
---#define NDEBUG\r
---#include <debug.h>\r
---\r
---static PHCELL __inline CMAPI\r
---HvpGetCellHeader(\r
--- PHHIVE RegistryHive,\r
--- HCELL_INDEX CellIndex)\r
---{\r
--- PVOID Block;\r
---\r
--- ASSERT(CellIndex != HCELL_NULL);\r
--- if (!RegistryHive->Flat)\r
--- {\r
--- ULONG CellType;\r
--- ULONG CellBlock;\r
--- ULONG CellOffset;\r
---\r
--- CellType = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;\r
--- CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;\r
--- CellOffset = (CellIndex & HCELL_OFFSET_MASK) >> HCELL_OFFSET_SHIFT;\r
--- ASSERT(CellBlock < RegistryHive->Storage[CellType].Length);\r
--- Block = (PVOID)RegistryHive->Storage[CellType].BlockList[CellBlock].Block;\r
--- ASSERT(Block != NULL);\r
--- return (PVOID)((ULONG_PTR)Block + CellOffset);\r
--- }\r
--- else\r
--- {\r
--- ASSERT((CellIndex & HCELL_TYPE_MASK) == HvStable);\r
--- return (PVOID)((ULONG_PTR)RegistryHive->HiveHeader + HV_BLOCK_SIZE +\r
--- CellIndex);\r
--- }\r
---}\r
---\r
---PVOID CMAPI\r
---HvGetCell(\r
--- PHHIVE RegistryHive,\r
--- HCELL_INDEX CellIndex)\r
---{\r
--- return (PVOID)(HvpGetCellHeader(RegistryHive, CellIndex) + 1);\r
---}\r
---\r
---static LONG __inline CMAPI\r
---HvpGetCellFullSize(\r
--- PHHIVE RegistryHive,\r
--- PVOID Cell)\r
---{\r
--- return ((PHCELL)Cell - 1)->Size;\r
---}\r
---\r
---LONG CMAPI\r
---HvGetCellSize(\r
--- PHHIVE RegistryHive,\r
--- PVOID Cell)\r
---{\r
--- PHCELL CellHeader;\r
---\r
--- CellHeader = (PHCELL)Cell - 1;\r
--- if (CellHeader->Size < 0)\r
--- return CellHeader->Size + sizeof(HCELL);\r
--- else\r
--- return CellHeader->Size - sizeof(HCELL);\r
---}\r
---\r
---VOID CMAPI\r
---HvMarkCellDirty(\r
--- PHHIVE RegistryHive,\r
--- HCELL_INDEX CellIndex)\r
---{\r
--- LONG CellSize;\r
--- ULONG CellBlock;\r
--- ULONG CellLastBlock;\r
---\r
--- ASSERT(RegistryHive->ReadOnly == FALSE);\r
---\r
--- if ((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT != HvStable)\r
--- return;\r
---\r
--- CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;\r
--- CellLastBlock = ((CellIndex + HV_BLOCK_SIZE - 1) & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;\r
---\r
--- CellSize = HvpGetCellFullSize(RegistryHive, HvGetCell(RegistryHive, CellIndex));\r
--- if (CellSize < 0)\r
--- CellSize = -CellSize;\r
---\r
--- RtlSetBits(&RegistryHive->DirtyVector,\r
--- CellBlock, CellLastBlock - CellBlock);\r
---}\r
---\r
---static ULONG __inline CMAPI\r
---HvpComputeFreeListIndex(\r
--- ULONG Size)\r
---{\r
--- ULONG Index;\r
--- static CCHAR FindFirstSet[256] = {\r
--- 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,\r
--- 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\r
--- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\r
--- 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\r
--- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\r
--- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\r
--- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\r
--- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\r
--- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\r
--- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\r
--- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\r
--- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\r
--- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\r
--- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\r
--- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,\r
--- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};\r
---\r
--- Index = (Size >> 3) - 1;\r
--- if (Index >= 16)\r
--- {\r
--- if (Index > 255)\r
--- Index = 23;\r
--- else\r
--- Index = FindFirstSet[Index] + 7;\r
--- }\r
---\r
--- return Index;\r
---}\r
---\r
---static NTSTATUS CMAPI\r
---HvpAddFree(\r
--- PHHIVE RegistryHive,\r
--- PHCELL FreeBlock,\r
--- HCELL_INDEX FreeIndex)\r
---{\r
--- PHCELL_INDEX FreeBlockData;\r
--- HV_STORAGE_TYPE Storage;\r
--- ULONG Index;\r
---\r
--- ASSERT(RegistryHive != NULL);\r
--- ASSERT(FreeBlock != NULL);\r
---\r
--- Storage = (FreeIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;\r
--- Index = HvpComputeFreeListIndex((ULONG)FreeBlock->Size);\r
---\r
--- FreeBlockData = (PHCELL_INDEX)(FreeBlock + 1);\r
--- *FreeBlockData = RegistryHive->Storage[Storage].FreeDisplay[Index];\r
--- RegistryHive->Storage[Storage].FreeDisplay[Index] = FreeIndex;\r
---\r
--- /* FIXME: Eventually get rid of free bins. */\r
---\r
--- return STATUS_SUCCESS;\r
---}\r
---\r
---static VOID CMAPI\r
---HvpRemoveFree(\r
--- PHHIVE RegistryHive,\r
--- PHCELL CellBlock,\r
--- HCELL_INDEX CellIndex)\r
---{\r
--- PHCELL_INDEX FreeCellData;\r
--- PHCELL_INDEX pFreeCellOffset;\r
--- HV_STORAGE_TYPE Storage;\r
--- ULONG Index;\r
---\r
--- ASSERT(RegistryHive->ReadOnly == FALSE);\r
---\r
--- Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;\r
--- Index = HvpComputeFreeListIndex((ULONG)CellBlock->Size);\r
---\r
--- pFreeCellOffset = &RegistryHive->Storage[Storage].FreeDisplay[Index];\r
--- while (*pFreeCellOffset != HCELL_NULL)\r
--- {\r
--- FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset);\r
--- if (*pFreeCellOffset == CellIndex)\r
--- {\r
--- *pFreeCellOffset = *FreeCellData;\r
--- return;\r
--- }\r
--- pFreeCellOffset = FreeCellData;\r
--- }\r
---\r
--- ASSERT(FALSE);\r
---}\r
---\r
---static HCELL_INDEX CMAPI\r
---HvpFindFree(\r
--- PHHIVE RegistryHive,\r
--- ULONG Size,\r
--- HV_STORAGE_TYPE Storage)\r
---{\r
--- PHCELL_INDEX FreeCellData;\r
--- HCELL_INDEX FreeCellOffset;\r
--- PHCELL_INDEX pFreeCellOffset;\r
--- ULONG Index;\r
---\r
--- for (Index = HvpComputeFreeListIndex(Size); Index < 24; Index++)\r
--- {\r
--- pFreeCellOffset = &RegistryHive->Storage[Storage].FreeDisplay[Index];\r
--- while (*pFreeCellOffset != HCELL_NULL)\r
--- {\r
--- FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset);\r
- if (HvpGetCellFullSize(RegistryHive, FreeCellData) >= Size)\r
-- if ((ULONG)HvpGetCellFullSize(RegistryHive, FreeCellData) >= Size)\r
--- {\r
--- FreeCellOffset = *pFreeCellOffset;\r
--- *pFreeCellOffset = *FreeCellData;\r
--- return FreeCellOffset;\r
--- }\r
--- pFreeCellOffset = FreeCellData;\r
--- }\r
--- }\r
---\r
--- return HCELL_NULL;\r
---}\r
---\r
---NTSTATUS CMAPI\r
---HvpCreateHiveFreeCellList(\r
--- PHHIVE Hive)\r
---{\r
--- HCELL_INDEX BlockOffset;\r
--- PHCELL FreeBlock;\r
--- ULONG BlockIndex;\r
--- ULONG FreeOffset;\r
--- PHBIN Bin;\r
--- NTSTATUS Status;\r
--- ULONG Index;\r
---\r
--- /* Initialize the free cell list */\r
--- for (Index = 0; Index < 24; Index++)\r
--- {\r
--- Hive->Storage[HvStable].FreeDisplay[Index] = HCELL_NULL;\r
--- Hive->Storage[HvVolatile].FreeDisplay[Index] = HCELL_NULL;\r
--- }\r
---\r
--- BlockOffset = 0;\r
--- BlockIndex = 0;\r
--- while (BlockIndex < Hive->Storage[HvStable].Length)\r
--- {\r
--- Bin = (PHBIN)Hive->Storage[HvStable].BlockList[BlockIndex].Bin;\r
---\r
--- /* Search free blocks and add to list */\r
--- FreeOffset = sizeof(HBIN);\r
--- while (FreeOffset < Bin->Size)\r
--- {\r
--- FreeBlock = (PHCELL)((ULONG_PTR)Bin + FreeOffset);\r
--- if (FreeBlock->Size > 0)\r
--- {\r
--- Status = HvpAddFree(Hive, FreeBlock, Bin->FileOffset + FreeOffset);\r
--- if (!NT_SUCCESS(Status))\r
--- return Status;\r
---\r
--- FreeOffset += FreeBlock->Size;\r
--- }\r
--- else\r
--- {\r
--- FreeOffset -= FreeBlock->Size;\r
--- }\r
--- }\r
---\r
--- BlockIndex += Bin->Size / HV_BLOCK_SIZE;\r
--- BlockOffset += Bin->Size;\r
--- }\r
---\r
--- return STATUS_SUCCESS;\r
---}\r
---\r
---HCELL_INDEX CMAPI\r
---HvAllocateCell(\r
--- PHHIVE RegistryHive,\r
--- ULONG Size,\r
--- HV_STORAGE_TYPE Storage)\r
---{\r
--- PHCELL FreeCell;\r
--- HCELL_INDEX FreeCellOffset;\r
--- PHCELL NewCell;\r
--- PHBIN Bin;\r
---\r
--- ASSERT(RegistryHive->ReadOnly == FALSE);\r
---\r
--- /* Round to 16 bytes multiple. */\r
--- Size = ROUND_UP(Size + sizeof(HCELL), 16);\r
---\r
--- /* First search in free blocks. */\r
--- FreeCellOffset = HvpFindFree(RegistryHive, Size, Storage);\r
---\r
--- /* If no free cell was found we need to extend the hive file. */\r
--- if (FreeCellOffset == HCELL_NULL)\r
--- {\r
--- Bin = HvpAddBin(RegistryHive, Size, Storage);\r
--- if (Bin == NULL)\r
--- return HCELL_NULL;\r
--- FreeCellOffset = Bin->FileOffset + sizeof(HBIN);\r
--- FreeCellOffset |= Storage << HCELL_TYPE_SHIFT;\r
--- }\r
---\r
--- FreeCell = HvpGetCellHeader(RegistryHive, FreeCellOffset);\r
---\r
--- /* Split the block in two parts */\r
--- /* FIXME: There is some minimal cell size that we must respect. */\r
- if (FreeCell->Size > Size + sizeof(HCELL_INDEX))\r
-- if ((ULONG)FreeCell->Size > Size + sizeof(HCELL_INDEX))\r
--- {\r
--- NewCell = (PHCELL)((ULONG_PTR)FreeCell + Size);\r
--- NewCell->Size = FreeCell->Size - Size;\r
--- FreeCell->Size = Size;\r
--- HvpAddFree(RegistryHive, NewCell, FreeCellOffset + Size);\r
--- if (Storage == HvStable)\r
--- HvMarkCellDirty(RegistryHive, FreeCellOffset + Size);\r
--- }\r
---\r
--- if (Storage == HvStable)\r
--- HvMarkCellDirty(RegistryHive, FreeCellOffset);\r
--- FreeCell->Size = -FreeCell->Size;\r
--- RtlZeroMemory(FreeCell + 1, Size - sizeof(HCELL));\r
---\r
--- return FreeCellOffset;\r
---}\r
---\r
---HCELL_INDEX CMAPI\r
---HvReallocateCell(\r
--- PHHIVE RegistryHive,\r
--- HCELL_INDEX CellIndex,\r
--- ULONG Size)\r
---{\r
--- PVOID OldCell;\r
--- PVOID NewCell;\r
--- LONG OldCellSize;\r
--- HCELL_INDEX NewCellIndex;\r
--- HV_STORAGE_TYPE Storage;\r
---\r
--- ASSERT(CellIndex != HCELL_NULL);\r
---\r
--- Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;\r
---\r
--- OldCell = HvGetCell(RegistryHive, CellIndex);\r
--- OldCellSize = HvGetCellSize(RegistryHive, OldCell);\r
--- ASSERT(OldCellSize < 0);\r
--- \r
--- /*\r
--- * If new data size is larger than the current, destroy current\r
--- * data block and allocate a new one.\r
--- *\r
--- * FIXME: Merge with adjacent free cell if possible.\r
--- * FIXME: Implement shrinking.\r
--- */\r
- if (Size > -OldCellSize)\r
-- if (Size > (ULONG)-OldCellSize)\r
--- {\r
--- NewCellIndex = HvAllocateCell(RegistryHive, Size, Storage);\r
--- if (NewCellIndex == HCELL_NULL)\r
--- return HCELL_NULL;\r
---\r
--- NewCell = HvGetCell(RegistryHive, NewCellIndex);\r
- RtlCopyMemory(NewCell, OldCell, -OldCellSize);\r
-- RtlCopyMemory(NewCell, OldCell, (SIZE_T)-OldCellSize);\r
--- \r
--- HvFreeCell(RegistryHive, CellIndex);\r
---\r
--- return NewCellIndex;\r
--- }\r
---\r
--- return CellIndex;\r
---}\r
---\r
---VOID CMAPI\r
---HvFreeCell(\r
--- PHHIVE RegistryHive,\r
--- HCELL_INDEX CellIndex)\r
---{\r
--- PHCELL Free;\r
--- PHCELL Neighbor;\r
--- PHBIN Bin;\r
--- ULONG CellType;\r
--- ULONG CellBlock;\r
---\r
--- ASSERT(RegistryHive->ReadOnly == FALSE);\r
--- \r
--- Free = HvpGetCellHeader(RegistryHive, CellIndex);\r
---\r
--- ASSERT(Free->Size < 0); \r
--- \r
--- Free->Size = -Free->Size;\r
---\r
--- CellType = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;\r
--- CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;\r
---\r
--- /* FIXME: Merge free blocks */\r
--- Bin = (PHBIN)RegistryHive->Storage[CellType].BlockList[CellBlock].Bin;\r
---\r
--- if ((CellIndex & ~HCELL_TYPE_MASK) + Free->Size <\r
--- Bin->FileOffset + Bin->Size)\r
--- {\r
--- Neighbor = (PHCELL)((ULONG_PTR)Free + Free->Size);\r
--- if (Neighbor->Size > 0)\r
--- {\r
--- HvpRemoveFree(RegistryHive, Neighbor,\r
- ((HCELL_INDEX)Neighbor - (HCELL_INDEX)Bin +\r
- Bin->FileOffset) | (CellIndex & HCELL_TYPE_MASK));\r
-- ((HCELL_INDEX)((ULONG_PTR)Neighbor - (ULONG_PTR)Bin +\r
-- Bin->FileOffset)) | (CellIndex & HCELL_TYPE_MASK));\r
--- Free->Size += Neighbor->Size;\r
--- }\r
--- }\r
---\r
--- Neighbor = (PHCELL)(Bin + 1);\r
--- while (Neighbor < Free)\r
--- {\r
--- if (Neighbor->Size > 0)\r
--- {\r
--- if ((ULONG_PTR)Neighbor + Neighbor->Size == (ULONG_PTR)Free)\r
--- {\r
--- Neighbor->Size += Free->Size;\r
--- if (CellType == HvStable)\r
--- HvMarkCellDirty(RegistryHive,\r
- (HCELL_INDEX)Neighbor - (HCELL_INDEX)Bin +\r
- Bin->FileOffset);\r
-- (HCELL_INDEX)((ULONG_PTR)Neighbor - (ULONG_PTR)Bin +\r
-- Bin->FileOffset));\r
--- return;\r
--- }\r
--- Neighbor = (PHCELL)((ULONG_PTR)Neighbor + Neighbor->Size);\r
--- }\r
--- else\r
--- {\r
--- Neighbor = (PHCELL)((ULONG_PTR)Neighbor - Neighbor->Size);\r
--- }\r
--- }\r
---\r
--- /* Add block to the list of free blocks */\r
--- HvpAddFree(RegistryHive, Free, CellIndex);\r
---\r
--- if (CellType == HvStable)\r
--- HvMarkCellDirty(RegistryHive, CellIndex);\r
---}\r
+++/*
+++ * PROJECT: registry manipulation library
+++ * LICENSE: GPL - See COPYING in the top level directory
+++ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>
+++ * Copyright 2001 - 2005 Eric Kohl
+++ */
+++
+++#include "cmlib.h"
+++#define NDEBUG
+++#include <debug.h>
+++
+++static PHCELL __inline CMAPI
+++HvpGetCellHeader(
+++ PHHIVE RegistryHive,
+++ HCELL_INDEX CellIndex)
+++{
+++ PVOID Block;
+++
+++ ASSERT(CellIndex != HCELL_NULL);
+++ if (!RegistryHive->Flat)
+++ {
+++ ULONG CellType;
+++ ULONG CellBlock;
+++ ULONG CellOffset;
+++
+++ CellType = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
+++ CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
+++ CellOffset = (CellIndex & HCELL_OFFSET_MASK) >> HCELL_OFFSET_SHIFT;
+++ ASSERT(CellBlock < RegistryHive->Storage[CellType].Length);
+++ Block = (PVOID)RegistryHive->Storage[CellType].BlockList[CellBlock].Block;
+++ ASSERT(Block != NULL);
+++ return (PVOID)((ULONG_PTR)Block + CellOffset);
+++ }
+++ else
+++ {
+++ ASSERT((CellIndex & HCELL_TYPE_MASK) == HvStable);
+++ return (PVOID)((ULONG_PTR)RegistryHive->HiveHeader + HV_BLOCK_SIZE +
+++ CellIndex);
+++ }
+++}
+++
+++PVOID CMAPI
+++HvGetCell(
+++ PHHIVE RegistryHive,
+++ HCELL_INDEX CellIndex)
+++{
+++ return (PVOID)(HvpGetCellHeader(RegistryHive, CellIndex) + 1);
+++}
+++
+++static LONG __inline CMAPI
+++HvpGetCellFullSize(
+++ PHHIVE RegistryHive,
+++ PVOID Cell)
+++{
+++ return ((PHCELL)Cell - 1)->Size;
+++}
+++
+++LONG CMAPI
+++HvGetCellSize(
+++ PHHIVE RegistryHive,
+++ PVOID Cell)
+++{
+++ PHCELL CellHeader;
+++
+++ CellHeader = (PHCELL)Cell - 1;
+++ if (CellHeader->Size < 0)
+++ return CellHeader->Size + sizeof(HCELL);
+++ else
+++ return CellHeader->Size - sizeof(HCELL);
+++}
+++
+++VOID CMAPI
+++HvMarkCellDirty(
+++ PHHIVE RegistryHive,
+++ HCELL_INDEX CellIndex)
+++{
+++ LONG CellSize;
+++ ULONG CellBlock;
+++ ULONG CellLastBlock;
+++
+++ ASSERT(RegistryHive->ReadOnly == FALSE);
+++
+++ if ((CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT != HvStable)
+++ return;
+++
+++ CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
+++ CellLastBlock = ((CellIndex + HV_BLOCK_SIZE - 1) & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
+++
+++ CellSize = HvpGetCellFullSize(RegistryHive, HvGetCell(RegistryHive, CellIndex));
+++ if (CellSize < 0)
+++ CellSize = -CellSize;
+++
+++ RtlSetBits(&RegistryHive->DirtyVector,
+++ CellBlock, CellLastBlock - CellBlock);
+++}
+++
+++static ULONG __inline CMAPI
+++HvpComputeFreeListIndex(
+++ ULONG Size)
+++{
+++ ULONG Index;
+++ static CCHAR FindFirstSet[256] = {
+++ 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+++ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+++ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+++ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+++ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+++ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+++ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+++ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
+++
+++ Index = (Size >> 3) - 1;
+++ if (Index >= 16)
+++ {
+++ if (Index > 255)
+++ Index = 23;
+++ else
+++ Index = FindFirstSet[Index] + 7;
+++ }
+++
+++ return Index;
+++}
+++
+++static NTSTATUS CMAPI
+++HvpAddFree(
+++ PHHIVE RegistryHive,
+++ PHCELL FreeBlock,
+++ HCELL_INDEX FreeIndex)
+++{
+++ PHCELL_INDEX FreeBlockData;
+++ HV_STORAGE_TYPE Storage;
+++ ULONG Index;
+++
+++ ASSERT(RegistryHive != NULL);
+++ ASSERT(FreeBlock != NULL);
+++
+++ Storage = (FreeIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
+++ Index = HvpComputeFreeListIndex((ULONG)FreeBlock->Size);
+++
+++ FreeBlockData = (PHCELL_INDEX)(FreeBlock + 1);
+++ *FreeBlockData = RegistryHive->Storage[Storage].FreeDisplay[Index];
+++ RegistryHive->Storage[Storage].FreeDisplay[Index] = FreeIndex;
+++
+++ /* FIXME: Eventually get rid of free bins. */
+++
+++ return STATUS_SUCCESS;
+++}
+++
+++static VOID CMAPI
+++HvpRemoveFree(
+++ PHHIVE RegistryHive,
+++ PHCELL CellBlock,
+++ HCELL_INDEX CellIndex)
+++{
+++ PHCELL_INDEX FreeCellData;
+++ PHCELL_INDEX pFreeCellOffset;
+++ HV_STORAGE_TYPE Storage;
+++ ULONG Index;
+++
+++ ASSERT(RegistryHive->ReadOnly == FALSE);
+++
+++ Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
+++ Index = HvpComputeFreeListIndex((ULONG)CellBlock->Size);
+++
+++ pFreeCellOffset = &RegistryHive->Storage[Storage].FreeDisplay[Index];
+++ while (*pFreeCellOffset != HCELL_NULL)
+++ {
+++ FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset);
+++ if (*pFreeCellOffset == CellIndex)
+++ {
+++ *pFreeCellOffset = *FreeCellData;
+++ return;
+++ }
+++ pFreeCellOffset = FreeCellData;
+++ }
+++
+++ ASSERT(FALSE);
+++}
+++
+++static HCELL_INDEX CMAPI
+++HvpFindFree(
+++ PHHIVE RegistryHive,
+++ ULONG Size,
+++ HV_STORAGE_TYPE Storage)
+++{
+++ PHCELL_INDEX FreeCellData;
+++ HCELL_INDEX FreeCellOffset;
+++ PHCELL_INDEX pFreeCellOffset;
+++ ULONG Index;
+++
+++ for (Index = HvpComputeFreeListIndex(Size); Index < 24; Index++)
+++ {
+++ pFreeCellOffset = &RegistryHive->Storage[Storage].FreeDisplay[Index];
+++ while (*pFreeCellOffset != HCELL_NULL)
+++ {
+++ FreeCellData = (PHCELL_INDEX)HvGetCell(RegistryHive, *pFreeCellOffset);
+++ if ((ULONG)HvpGetCellFullSize(RegistryHive, FreeCellData) >= Size)
+++ {
+++ FreeCellOffset = *pFreeCellOffset;
+++ *pFreeCellOffset = *FreeCellData;
+++ return FreeCellOffset;
+++ }
+++ pFreeCellOffset = FreeCellData;
+++ }
+++ }
+++
+++ return HCELL_NULL;
+++}
+++
+++NTSTATUS CMAPI
+++HvpCreateHiveFreeCellList(
+++ PHHIVE Hive)
+++{
+++ HCELL_INDEX BlockOffset;
+++ PHCELL FreeBlock;
+++ ULONG BlockIndex;
+++ ULONG FreeOffset;
+++ PHBIN Bin;
+++ NTSTATUS Status;
+++ ULONG Index;
+++
+++ /* Initialize the free cell list */
+++ for (Index = 0; Index < 24; Index++)
+++ {
+++ Hive->Storage[HvStable].FreeDisplay[Index] = HCELL_NULL;
+++ Hive->Storage[HvVolatile].FreeDisplay[Index] = HCELL_NULL;
+++ }
+++
+++ BlockOffset = 0;
+++ BlockIndex = 0;
+++ while (BlockIndex < Hive->Storage[HvStable].Length)
+++ {
+++ Bin = (PHBIN)Hive->Storage[HvStable].BlockList[BlockIndex].Bin;
+++
+++ /* Search free blocks and add to list */
+++ FreeOffset = sizeof(HBIN);
+++ while (FreeOffset < Bin->Size)
+++ {
+++ FreeBlock = (PHCELL)((ULONG_PTR)Bin + FreeOffset);
+++ if (FreeBlock->Size > 0)
+++ {
+++ Status = HvpAddFree(Hive, FreeBlock, Bin->FileOffset + FreeOffset);
+++ if (!NT_SUCCESS(Status))
+++ return Status;
+++
+++ FreeOffset += FreeBlock->Size;
+++ }
+++ else
+++ {
+++ FreeOffset -= FreeBlock->Size;
+++ }
+++ }
+++
+++ BlockIndex += Bin->Size / HV_BLOCK_SIZE;
+++ BlockOffset += Bin->Size;
+++ }
+++
+++ return STATUS_SUCCESS;
+++}
+++
+++HCELL_INDEX CMAPI
+++HvAllocateCell(
+++ PHHIVE RegistryHive,
+++ ULONG Size,
+++ HV_STORAGE_TYPE Storage)
+++{
+++ PHCELL FreeCell;
+++ HCELL_INDEX FreeCellOffset;
+++ PHCELL NewCell;
+++ PHBIN Bin;
+++
+++ ASSERT(RegistryHive->ReadOnly == FALSE);
+++
+++ /* Round to 16 bytes multiple. */
+++ Size = ROUND_UP(Size + sizeof(HCELL), 16);
+++
+++ /* First search in free blocks. */
+++ FreeCellOffset = HvpFindFree(RegistryHive, Size, Storage);
+++
+++ /* If no free cell was found we need to extend the hive file. */
+++ if (FreeCellOffset == HCELL_NULL)
+++ {
+++ Bin = HvpAddBin(RegistryHive, Size, Storage);
+++ if (Bin == NULL)
+++ return HCELL_NULL;
+++ FreeCellOffset = Bin->FileOffset + sizeof(HBIN);
+++ FreeCellOffset |= Storage << HCELL_TYPE_SHIFT;
+++ }
+++
+++ FreeCell = HvpGetCellHeader(RegistryHive, FreeCellOffset);
+++
+++ /* Split the block in two parts */
+++ /* FIXME: There is some minimal cell size that we must respect. */
+++ if ((ULONG)FreeCell->Size > Size + sizeof(HCELL_INDEX))
+++ {
+++ NewCell = (PHCELL)((ULONG_PTR)FreeCell + Size);
+++ NewCell->Size = FreeCell->Size - Size;
+++ FreeCell->Size = Size;
+++ HvpAddFree(RegistryHive, NewCell, FreeCellOffset + Size);
+++ if (Storage == HvStable)
+++ HvMarkCellDirty(RegistryHive, FreeCellOffset + Size);
+++ }
+++
+++ if (Storage == HvStable)
+++ HvMarkCellDirty(RegistryHive, FreeCellOffset);
+++ FreeCell->Size = -FreeCell->Size;
+++ RtlZeroMemory(FreeCell + 1, Size - sizeof(HCELL));
+++
+++ return FreeCellOffset;
+++}
+++
+++HCELL_INDEX CMAPI
+++HvReallocateCell(
+++ PHHIVE RegistryHive,
+++ HCELL_INDEX CellIndex,
+++ ULONG Size)
+++{
+++ PVOID OldCell;
+++ PVOID NewCell;
+++ LONG OldCellSize;
+++ HCELL_INDEX NewCellIndex;
+++ HV_STORAGE_TYPE Storage;
+++
+++ ASSERT(CellIndex != HCELL_NULL);
+++
+++ Storage = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
+++
+++ OldCell = HvGetCell(RegistryHive, CellIndex);
+++ OldCellSize = HvGetCellSize(RegistryHive, OldCell);
+++ ASSERT(OldCellSize < 0);
+++
+++ /*
+++ * If new data size is larger than the current, destroy current
+++ * data block and allocate a new one.
+++ *
+++ * FIXME: Merge with adjacent free cell if possible.
+++ * FIXME: Implement shrinking.
+++ */
+++ if (Size > (ULONG)-OldCellSize)
+++ {
+++ NewCellIndex = HvAllocateCell(RegistryHive, Size, Storage);
+++ if (NewCellIndex == HCELL_NULL)
+++ return HCELL_NULL;
+++
+++ NewCell = HvGetCell(RegistryHive, NewCellIndex);
+++ RtlCopyMemory(NewCell, OldCell, (SIZE_T)-OldCellSize);
+++
+++ HvFreeCell(RegistryHive, CellIndex);
+++
+++ return NewCellIndex;
+++ }
+++
+++ return CellIndex;
+++}
+++
+++VOID CMAPI
+++HvFreeCell(
+++ PHHIVE RegistryHive,
+++ HCELL_INDEX CellIndex)
+++{
+++ PHCELL Free;
+++ PHCELL Neighbor;
+++ PHBIN Bin;
+++ ULONG CellType;
+++ ULONG CellBlock;
+++
+++ ASSERT(RegistryHive->ReadOnly == FALSE);
+++
+++ Free = HvpGetCellHeader(RegistryHive, CellIndex);
+++
+++ ASSERT(Free->Size < 0);
+++
+++ Free->Size = -Free->Size;
+++
+++ CellType = (CellIndex & HCELL_TYPE_MASK) >> HCELL_TYPE_SHIFT;
+++ CellBlock = (CellIndex & HCELL_BLOCK_MASK) >> HCELL_BLOCK_SHIFT;
+++
+++ /* FIXME: Merge free blocks */
+++ Bin = (PHBIN)RegistryHive->Storage[CellType].BlockList[CellBlock].Bin;
+++
+++ if ((CellIndex & ~HCELL_TYPE_MASK) + Free->Size <
+++ Bin->FileOffset + Bin->Size)
+++ {
+++ Neighbor = (PHCELL)((ULONG_PTR)Free + Free->Size);
+++ if (Neighbor->Size > 0)
+++ {
+++ HvpRemoveFree(RegistryHive, Neighbor,
+++ ((HCELL_INDEX)((ULONG_PTR)Neighbor - (ULONG_PTR)Bin +
+++ Bin->FileOffset)) | (CellIndex & HCELL_TYPE_MASK));
+++ Free->Size += Neighbor->Size;
+++ }
+++ }
+++
+++ Neighbor = (PHCELL)(Bin + 1);
+++ while (Neighbor < Free)
+++ {
+++ if (Neighbor->Size > 0)
+++ {
+++ if ((ULONG_PTR)Neighbor + Neighbor->Size == (ULONG_PTR)Free)
+++ {
+++ Neighbor->Size += Free->Size;
+++ if (CellType == HvStable)
+++ HvMarkCellDirty(RegistryHive,
+++ (HCELL_INDEX)((ULONG_PTR)Neighbor - (ULONG_PTR)Bin +
+++ Bin->FileOffset));
+++ return;
+++ }
+++ Neighbor = (PHCELL)((ULONG_PTR)Neighbor + Neighbor->Size);
+++ }
+++ else
+++ {
+++ Neighbor = (PHCELL)((ULONG_PTR)Neighbor - Neighbor->Size);
+++ }
+++ }
+++
+++ /* Add block to the list of free blocks */
+++ HvpAddFree(RegistryHive, Free, CellIndex);
+++
+++ if (CellType == HvStable)
+++ HvMarkCellDirty(RegistryHive, CellIndex);
+++}
---/*\r
--- * PROJECT: registry manipulation library\r
--- * LICENSE: GPL - See COPYING in the top level directory\r
--- * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>\r
--- * Copyright 2001 - 2005 Eric Kohl\r
--- */\r
---\r
---#include "cmlib.h"\r
---#define NDEBUG\r
---#include <debug.h>\r
---\r
---/**\r
--- * @name HvpVerifyHiveHeader\r
--- *\r
--- * Internal function to verify that a hive header has valid format.\r
--- */\r
---\r
---BOOLEAN CMAPI\r
---HvpVerifyHiveHeader(\r
--- PHBASE_BLOCK HiveHeader)\r
---{\r
--- if (HiveHeader->Signature != HV_SIGNATURE ||\r
--- HiveHeader->Major != HV_MAJOR_VER ||\r
- HiveHeader->Minor > HV_MINOR_VER ||\r
-- HiveHeader->Minor < HV_MINOR_VER ||\r
--- HiveHeader->Type != HV_TYPE_PRIMARY ||\r
--- HiveHeader->Format != HV_FORMAT_MEMORY ||\r
--- HiveHeader->Cluster != 1 ||\r
--- HiveHeader->Sequence1 != HiveHeader->Sequence2 ||\r
--- HvpHiveHeaderChecksum(HiveHeader) != HiveHeader->Checksum)\r
--- {\r
--- DPRINT1("Verify Hive Header failed: \n");\r
--- DPRINT1(" Signature: 0x%x and not 0x%x, Major: 0x%x and not 0x%x\n",\r
--- HiveHeader->Signature, HV_SIGNATURE, HiveHeader->Major, HV_MAJOR_VER);\r
- DPRINT1(" Minor: 0x%x is not > 0x%x, Type: 0x%x and not 0x%x\n",\r
-- DPRINT1(" Minor: 0x%x is not >= 0x%x, Type: 0x%x and not 0x%x\n",\r
--- HiveHeader->Minor, HV_MINOR_VER, HiveHeader->Type, HV_TYPE_PRIMARY);\r
--- DPRINT1(" Format: 0x%x and not 0x%x, Cluster: 0x%x and not 1\n",\r
--- HiveHeader->Format, HV_FORMAT_MEMORY, HiveHeader->Cluster);\r
--- DPRINT1(" Sequence: 0x%x and not 0x%x, Checksum: 0x%x and not 0x%x\n",\r
--- HiveHeader->Sequence1, HiveHeader->Sequence2,\r
--- HvpHiveHeaderChecksum(HiveHeader), HiveHeader->Checksum);\r
--- return FALSE;\r
--- }\r
---\r
--- return TRUE;\r
---}\r
---\r
---/**\r
--- * @name HvpFreeHiveBins\r
--- *\r
--- * Internal function to free all bin storage associated with hive\r
--- * descriptor.\r
--- */\r
---\r
---VOID CMAPI\r
---HvpFreeHiveBins(\r
--- PHHIVE Hive)\r
---{ \r
--- ULONG i;\r
--- PHBIN Bin;\r
--- ULONG Storage;\r
---\r
--- for (Storage = HvStable; Storage < HvMaxStorageType; Storage++)\r
--- {\r
--- Bin = NULL;\r
--- for (i = 0; i < Hive->Storage[Storage].Length; i++)\r
--- {\r
--- if (Hive->Storage[Storage].BlockList[i].Bin == (ULONG_PTR)NULL)\r
--- continue;\r
--- if (Hive->Storage[Storage].BlockList[i].Bin != (ULONG_PTR)Bin)\r
--- {\r
--- Bin = (PHBIN)Hive->Storage[Storage].BlockList[i].Bin;\r
--- Hive->Free((PHBIN)Hive->Storage[Storage].BlockList[i].Bin);\r
--- }\r
--- Hive->Storage[Storage].BlockList[i].Bin = (ULONG_PTR)NULL;\r
--- Hive->Storage[Storage].BlockList[i].Block = (ULONG_PTR)NULL;\r
--- }\r
---\r
--- if (Hive->Storage[Storage].Length)\r
--- Hive->Free(Hive->Storage[Storage].BlockList);\r
--- }\r
---}\r
---\r
---/**\r
--- * @name HvpCreateHive\r
--- *\r
--- * Internal helper function to initalize hive descriptor structure for\r
--- * newly created hive.\r
--- *\r
--- * @see HvInitialize\r
--- */\r
---\r
---NTSTATUS CMAPI\r
---HvpCreateHive(\r
--- PHHIVE RegistryHive)\r
---{\r
--- PHBASE_BLOCK HiveHeader;\r
--- ULONG Index;\r
---\r
--- HiveHeader = RegistryHive->Allocate(sizeof(HBASE_BLOCK), FALSE);\r
--- if (HiveHeader == NULL)\r
--- return STATUS_NO_MEMORY;\r
--- RtlZeroMemory(HiveHeader, sizeof(HBASE_BLOCK));\r
--- HiveHeader->Signature = HV_SIGNATURE;\r
--- HiveHeader->Major = HV_MAJOR_VER;\r
--- HiveHeader->Minor = HV_MINOR_VER;\r
--- HiveHeader->Type = HV_TYPE_PRIMARY;\r
--- HiveHeader->Format = HV_FORMAT_MEMORY;\r
--- HiveHeader->Cluster = 1;\r
--- HiveHeader->RootCell = HCELL_NULL;\r
--- HiveHeader->Length = HV_BLOCK_SIZE;\r
--- HiveHeader->Sequence1 = 1;\r
--- HiveHeader->Sequence2 = 1;\r
--- /* FIXME: Fill in the file name */\r
--- HiveHeader->Checksum = HvpHiveHeaderChecksum(HiveHeader);\r
---\r
--- RegistryHive->HiveHeader = HiveHeader;\r
--- for (Index = 0; Index < 24; Index++)\r
--- {\r
--- RegistryHive->Storage[HvStable].FreeDisplay[Index] = HCELL_NULL;\r
--- RegistryHive->Storage[HvVolatile].FreeDisplay[Index] = HCELL_NULL;\r
--- }\r
--- RtlInitializeBitMap(&RegistryHive->DirtyVector, NULL, 0);\r
---\r
--- return STATUS_SUCCESS;\r
---}\r
---\r
---/**\r
--- * @name HvpInitializeMemoryHive\r
--- *\r
--- * Internal helper function to initalize hive descriptor structure for\r
--- * a hive stored in memory. The data of the hive are copied and it is\r
--- * prepared for read/write access.\r
--- *\r
--- * @see HvInitialize\r
--- */\r
---\r
---NTSTATUS CMAPI\r
---HvpInitializeMemoryHive(\r
--- PHHIVE Hive,\r
--- ULONG_PTR ChunkBase)\r
---{\r
--- SIZE_T BlockIndex;\r
--- PHBIN Bin, NewBin;\r
--- ULONG i;\r
--- ULONG BitmapSize;\r
--- PULONG BitmapBuffer;\r
--- SIZE_T ChunkSize;\r
---\r
--- //\r
--- // This hack is similar in magnitude to the US's National Debt\r
--- //\r
--- ChunkSize = ((PHBASE_BLOCK)ChunkBase)->Length;\r
--- ((PHBASE_BLOCK)ChunkBase)->Length = HV_BLOCK_SIZE;\r
- DPRINT1("ChunkSize: %lx\n", ChunkSize);\r
-- DPRINT("ChunkSize: %lx\n", ChunkSize);\r
---\r
--- if (ChunkSize < sizeof(HBASE_BLOCK) ||\r
--- !HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))\r
--- {\r
--- DPRINT1("Registry is corrupt: ChunkSize %d < sizeof(HBASE_BLOCK) %d, "\r
--- "or HvpVerifyHiveHeader() failed\n", ChunkSize, sizeof(HBASE_BLOCK));\r
--- return STATUS_REGISTRY_CORRUPT;\r
--- }\r
---\r
--- Hive->HiveHeader = Hive->Allocate(sizeof(HBASE_BLOCK), FALSE);\r
--- if (Hive->HiveHeader == NULL)\r
--- {\r
--- return STATUS_NO_MEMORY;\r
--- }\r
--- RtlCopyMemory(Hive->HiveHeader, (PVOID)ChunkBase, sizeof(HBASE_BLOCK));\r
---\r
--- /*\r
--- * Build a block list from the in-memory chunk and copy the data as\r
--- * we go.\r
--- */\r
--- \r
- Hive->Storage[HvStable].Length = (ChunkSize / HV_BLOCK_SIZE) - 1;\r
-- Hive->Storage[HvStable].Length = (ULONG)(ChunkSize / HV_BLOCK_SIZE) - 1;\r
--- Hive->Storage[HvStable].BlockList =\r
--- Hive->Allocate(Hive->Storage[HvStable].Length *\r
--- sizeof(HMAP_ENTRY), FALSE);\r
--- if (Hive->Storage[HvStable].BlockList == NULL)\r
--- {\r
--- DPRINT1("Allocating block list failed\n");\r
--- Hive->Free(Hive->HiveHeader);\r
--- return STATUS_NO_MEMORY;\r
--- }\r
---\r
--- for (BlockIndex = 0; BlockIndex < Hive->Storage[HvStable].Length; )\r
--- {\r
--- Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HV_BLOCK_SIZE);\r
--- if (Bin->Signature != HV_BIN_SIGNATURE ||\r
--- (Bin->Size % HV_BLOCK_SIZE) != 0)\r
--- {\r
--- Hive->Free(Hive->HiveHeader);\r
--- Hive->Free(Hive->Storage[HvStable].BlockList);\r
--- return STATUS_REGISTRY_CORRUPT;\r
--- }\r
---\r
--- NewBin = Hive->Allocate(Bin->Size, TRUE);\r
--- if (NewBin == NULL)\r
--- {\r
--- Hive->Free(Hive->HiveHeader);\r
--- Hive->Free(Hive->Storage[HvStable].BlockList);\r
--- return STATUS_NO_MEMORY;\r
--- }\r
---\r
--- Hive->Storage[HvStable].BlockList[BlockIndex].Bin = (ULONG_PTR)NewBin;\r
--- Hive->Storage[HvStable].BlockList[BlockIndex].Block = (ULONG_PTR)NewBin;\r
---\r
--- RtlCopyMemory(NewBin, Bin, Bin->Size);\r
---\r
--- if (Bin->Size > HV_BLOCK_SIZE)\r
--- {\r
--- for (i = 1; i < Bin->Size / HV_BLOCK_SIZE; i++)\r
--- {\r
--- Hive->Storage[HvStable].BlockList[BlockIndex + i].Bin = (ULONG_PTR)NewBin;\r
--- Hive->Storage[HvStable].BlockList[BlockIndex + i].Block =\r
--- ((ULONG_PTR)NewBin + (i * HV_BLOCK_SIZE));\r
--- }\r
--- }\r
---\r
--- BlockIndex += Bin->Size / HV_BLOCK_SIZE;\r
--- }\r
---\r
--- if (HvpCreateHiveFreeCellList(Hive))\r
--- {\r
--- HvpFreeHiveBins(Hive);\r
--- Hive->Free(Hive->HiveHeader);\r
--- return STATUS_NO_MEMORY;\r
--- }\r
---\r
--- BitmapSize = ROUND_UP(Hive->Storage[HvStable].Length,\r
--- sizeof(ULONG) * 8) / 8;\r
--- BitmapBuffer = (PULONG)Hive->Allocate(BitmapSize, TRUE);\r
--- if (BitmapBuffer == NULL)\r
--- {\r
--- HvpFreeHiveBins(Hive);\r
--- Hive->Free(Hive->HiveHeader);\r
--- return STATUS_NO_MEMORY;\r
--- }\r
---\r
--- RtlInitializeBitMap(&Hive->DirtyVector, BitmapBuffer, BitmapSize * 8);\r
--- RtlClearAllBits(&Hive->DirtyVector);\r
---\r
--- return STATUS_SUCCESS;\r
---}\r
---\r
---/**\r
--- * @name HvpInitializeMemoryInplaceHive\r
--- *\r
--- * Internal helper function to initalize hive descriptor structure for\r
--- * a hive stored in memory. The in-memory data of the hive are directly\r
--- * used and it is read-only accessible.\r
--- *\r
--- * @see HvInitialize\r
--- */\r
---\r
---NTSTATUS CMAPI\r
---HvpInitializeMemoryInplaceHive(\r
--- PHHIVE Hive,\r
--- ULONG_PTR ChunkBase)\r
---{\r
--- if (!HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))\r
--- {\r
--- return STATUS_REGISTRY_CORRUPT;\r
--- }\r
---\r
--- Hive->HiveHeader = (PHBASE_BLOCK)ChunkBase;\r
--- Hive->ReadOnly = TRUE;\r
--- Hive->Flat = TRUE;\r
---\r
--- return STATUS_SUCCESS;\r
---}\r
---\r
---/**\r
--- * @name HvInitialize\r
--- *\r
--- * Allocate a new hive descriptor structure and intialize it.\r
--- *\r
--- * @param RegistryHive\r
--- * Output variable to store pointer to the hive descriptor.\r
--- * @param Operation\r
--- * - HV_OPERATION_CREATE_HIVE\r
--- * Create a new hive for read/write access.\r
--- * - HV_OPERATION_MEMORY\r
--- * Load and copy in-memory hive for read/write access. The\r
--- * pointer to data passed to this routine can be freed after\r
--- * the function is executed.\r
--- * - HV_OPERATION_MEMORY_INPLACE\r
--- * Load an in-memory hive for read-only access. The pointer\r
--- * to data passed to this routine MUSTN'T be freed until\r
--- * HvFree is called.\r
--- * @param ChunkBase\r
--- * Pointer to hive data.\r
--- * @param ChunkSize\r
--- * Size of passed hive data.\r
--- *\r
--- * @return\r
--- * STATUS_NO_MEMORY - A memory allocation failed.\r
--- * STATUS_REGISTRY_CORRUPT - Registry corruption was detected.\r
--- * STATUS_SUCCESS\r
--- * \r
--- * @see HvFree\r
--- */\r
---\r
---NTSTATUS CMAPI\r
---HvInitialize(\r
--- PHHIVE RegistryHive,\r
--- ULONG Operation,\r
-- ULONG HiveType,\r
-- ULONG HiveFlags,\r
--- ULONG_PTR HiveData OPTIONAL,\r
--- ULONG Cluster OPTIONAL,\r
--- PALLOCATE_ROUTINE Allocate,\r
--- PFREE_ROUTINE Free,\r
--- PFILE_READ_ROUTINE FileRead,\r
--- PFILE_WRITE_ROUTINE FileWrite,\r
--- PFILE_SET_SIZE_ROUTINE FileSetSize,\r
--- PFILE_FLUSH_ROUTINE FileFlush,\r
--- IN PUNICODE_STRING FileName)\r
---{\r
--- NTSTATUS Status;\r
--- PHHIVE Hive = RegistryHive;\r
---\r
--- /*\r
--- * Create a new hive structure that will hold all the maintenance data.\r
--- */\r
---\r
--- RtlZeroMemory(Hive, sizeof(HHIVE));\r
---\r
--- Hive->Allocate = Allocate;\r
--- Hive->Free = Free;\r
--- Hive->FileRead = FileRead;\r
--- Hive->FileWrite = FileWrite;\r
--- Hive->FileSetSize = FileSetSize;\r
--- Hive->FileFlush = FileFlush;\r
---\r
--- switch (Operation)\r
--- {\r
--- case HV_OPERATION_CREATE_HIVE:\r
--- Status = HvpCreateHive(Hive);\r
--- break;\r
---\r
--- case HV_OPERATION_MEMORY:\r
--- Status = HvpInitializeMemoryHive(Hive, HiveData);\r
--- break;\r
---\r
--- case HV_OPERATION_MEMORY_INPLACE:\r
--- Status = HvpInitializeMemoryInplaceHive(Hive, HiveData);\r
--- break;\r
---\r
--- default:\r
--- /* FIXME: A better return status value is needed */\r
--- Status = STATUS_NOT_IMPLEMENTED;\r
--- ASSERT(FALSE);\r
--- }\r
---\r
--- if (!NT_SUCCESS(Status))\r
--- {\r
--- Hive->Free(Hive);\r
--- return Status;\r
--- }\r
---\r
--- return Status;\r
---}\r
---\r
---/**\r
--- * @name HvFree\r
--- *\r
--- * Free all stroage and handles associated with hive descriptor.\r
--- */\r
---\r
---VOID CMAPI \r
---HvFree(\r
--- PHHIVE RegistryHive)\r
---{\r
--- if (!RegistryHive->ReadOnly)\r
--- {\r
--- /* Release hive bitmap */\r
--- if (RegistryHive->DirtyVector.Buffer)\r
--- {\r
--- RegistryHive->Free(RegistryHive->DirtyVector.Buffer);\r
--- }\r
---\r
--- HvpFreeHiveBins(RegistryHive);\r
--- }\r
---\r
--- RegistryHive->Free(RegistryHive);\r
---}\r
---\r
---/* EOF */\r
+++/*
+++ * PROJECT: registry manipulation library
+++ * LICENSE: GPL - See COPYING in the top level directory
+++ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>
+++ * Copyright 2001 - 2005 Eric Kohl
+++ */
+++
+++#include "cmlib.h"
+++#define NDEBUG
+++#include <debug.h>
+++
+++/**
+++ * @name HvpVerifyHiveHeader
+++ *
+++ * Internal function to verify that a hive header has valid format.
+++ */
+++
+++BOOLEAN CMAPI
+++HvpVerifyHiveHeader(
+++ PHBASE_BLOCK HiveHeader)
+++{
+++ if (HiveHeader->Signature != HV_SIGNATURE ||
+++ HiveHeader->Major != HV_MAJOR_VER ||
+++ HiveHeader->Minor < HV_MINOR_VER ||
+++ HiveHeader->Type != HV_TYPE_PRIMARY ||
+++ HiveHeader->Format != HV_FORMAT_MEMORY ||
+++ HiveHeader->Cluster != 1 ||
+++ HiveHeader->Sequence1 != HiveHeader->Sequence2 ||
+++ HvpHiveHeaderChecksum(HiveHeader) != HiveHeader->Checksum)
+++ {
+++ DPRINT1("Verify Hive Header failed: \n");
+++ DPRINT1(" Signature: 0x%x and not 0x%x, Major: 0x%x and not 0x%x\n",
+++ HiveHeader->Signature, HV_SIGNATURE, HiveHeader->Major, HV_MAJOR_VER);
+++ DPRINT1(" Minor: 0x%x is not >= 0x%x, Type: 0x%x and not 0x%x\n",
+++ HiveHeader->Minor, HV_MINOR_VER, HiveHeader->Type, HV_TYPE_PRIMARY);
+++ DPRINT1(" Format: 0x%x and not 0x%x, Cluster: 0x%x and not 1\n",
+++ HiveHeader->Format, HV_FORMAT_MEMORY, HiveHeader->Cluster);
+++ DPRINT1(" Sequence: 0x%x and not 0x%x, Checksum: 0x%x and not 0x%x\n",
+++ HiveHeader->Sequence1, HiveHeader->Sequence2,
+++ HvpHiveHeaderChecksum(HiveHeader), HiveHeader->Checksum);
+++ return FALSE;
+++ }
+++
+++ return TRUE;
+++}
+++
+++/**
+++ * @name HvpFreeHiveBins
+++ *
+++ * Internal function to free all bin storage associated with hive
+++ * descriptor.
+++ */
+++
+++VOID CMAPI
+++HvpFreeHiveBins(
+++ PHHIVE Hive)
+++{
+++ ULONG i;
+++ PHBIN Bin;
+++ ULONG Storage;
+++
+++ for (Storage = HvStable; Storage < HvMaxStorageType; Storage++)
+++ {
+++ Bin = NULL;
+++ for (i = 0; i < Hive->Storage[Storage].Length; i++)
+++ {
+++ if (Hive->Storage[Storage].BlockList[i].Bin == (ULONG_PTR)NULL)
+++ continue;
+++ if (Hive->Storage[Storage].BlockList[i].Bin != (ULONG_PTR)Bin)
+++ {
+++ Bin = (PHBIN)Hive->Storage[Storage].BlockList[i].Bin;
+++ Hive->Free((PHBIN)Hive->Storage[Storage].BlockList[i].Bin);
+++ }
+++ Hive->Storage[Storage].BlockList[i].Bin = (ULONG_PTR)NULL;
+++ Hive->Storage[Storage].BlockList[i].Block = (ULONG_PTR)NULL;
+++ }
+++
+++ if (Hive->Storage[Storage].Length)
+++ Hive->Free(Hive->Storage[Storage].BlockList);
+++ }
+++}
+++
+++/**
+++ * @name HvpCreateHive
+++ *
+++ * Internal helper function to initalize hive descriptor structure for
+++ * newly created hive.
+++ *
+++ * @see HvInitialize
+++ */
+++
+++NTSTATUS CMAPI
+++HvpCreateHive(
+++ PHHIVE RegistryHive)
+++{
+++ PHBASE_BLOCK HiveHeader;
+++ ULONG Index;
+++
+++ HiveHeader = RegistryHive->Allocate(sizeof(HBASE_BLOCK), FALSE);
+++ if (HiveHeader == NULL)
+++ return STATUS_NO_MEMORY;
+++ RtlZeroMemory(HiveHeader, sizeof(HBASE_BLOCK));
+++ HiveHeader->Signature = HV_SIGNATURE;
+++ HiveHeader->Major = HV_MAJOR_VER;
+++ HiveHeader->Minor = HV_MINOR_VER;
+++ HiveHeader->Type = HV_TYPE_PRIMARY;
+++ HiveHeader->Format = HV_FORMAT_MEMORY;
+++ HiveHeader->Cluster = 1;
+++ HiveHeader->RootCell = HCELL_NULL;
+++ HiveHeader->Length = HV_BLOCK_SIZE;
+++ HiveHeader->Sequence1 = 1;
+++ HiveHeader->Sequence2 = 1;
+++ /* FIXME: Fill in the file name */
+++ HiveHeader->Checksum = HvpHiveHeaderChecksum(HiveHeader);
+++
+++ RegistryHive->HiveHeader = HiveHeader;
+++ for (Index = 0; Index < 24; Index++)
+++ {
+++ RegistryHive->Storage[HvStable].FreeDisplay[Index] = HCELL_NULL;
+++ RegistryHive->Storage[HvVolatile].FreeDisplay[Index] = HCELL_NULL;
+++ }
+++ RtlInitializeBitMap(&RegistryHive->DirtyVector, NULL, 0);
+++
+++ return STATUS_SUCCESS;
+++}
+++
+++/**
+++ * @name HvpInitializeMemoryHive
+++ *
+++ * Internal helper function to initalize hive descriptor structure for
+++ * a hive stored in memory. The data of the hive are copied and it is
+++ * prepared for read/write access.
+++ *
+++ * @see HvInitialize
+++ */
+++
+++NTSTATUS CMAPI
+++HvpInitializeMemoryHive(
+++ PHHIVE Hive,
+++ ULONG_PTR ChunkBase)
+++{
+++ SIZE_T BlockIndex;
+++ PHBIN Bin, NewBin;
+++ ULONG i;
+++ ULONG BitmapSize;
+++ PULONG BitmapBuffer;
+++ SIZE_T ChunkSize;
+++
+++ //
+++ // This hack is similar in magnitude to the US's National Debt
+++ //
+++ ChunkSize = ((PHBASE_BLOCK)ChunkBase)->Length;
+++ ((PHBASE_BLOCK)ChunkBase)->Length = HV_BLOCK_SIZE;
+++ DPRINT("ChunkSize: %lx\n", ChunkSize);
+++
+++ if (ChunkSize < sizeof(HBASE_BLOCK) ||
+++ !HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
+++ {
+++ DPRINT1("Registry is corrupt: ChunkSize %d < sizeof(HBASE_BLOCK) %d, "
+++ "or HvpVerifyHiveHeader() failed\n", ChunkSize, sizeof(HBASE_BLOCK));
+++ return STATUS_REGISTRY_CORRUPT;
+++ }
+++
+++ Hive->HiveHeader = Hive->Allocate(sizeof(HBASE_BLOCK), FALSE);
+++ if (Hive->HiveHeader == NULL)
+++ {
+++ return STATUS_NO_MEMORY;
+++ }
+++ RtlCopyMemory(Hive->HiveHeader, (PVOID)ChunkBase, sizeof(HBASE_BLOCK));
+++
+++ /*
+++ * Build a block list from the in-memory chunk and copy the data as
+++ * we go.
+++ */
+++
+++ Hive->Storage[HvStable].Length = (ULONG)(ChunkSize / HV_BLOCK_SIZE) - 1;
+++ Hive->Storage[HvStable].BlockList =
+++ Hive->Allocate(Hive->Storage[HvStable].Length *
+++ sizeof(HMAP_ENTRY), FALSE);
+++ if (Hive->Storage[HvStable].BlockList == NULL)
+++ {
+++ DPRINT1("Allocating block list failed\n");
+++ Hive->Free(Hive->HiveHeader);
+++ return STATUS_NO_MEMORY;
+++ }
+++
+++ for (BlockIndex = 0; BlockIndex < Hive->Storage[HvStable].Length; )
+++ {
+++ Bin = (PHBIN)((ULONG_PTR)ChunkBase + (BlockIndex + 1) * HV_BLOCK_SIZE);
+++ if (Bin->Signature != HV_BIN_SIGNATURE ||
+++ (Bin->Size % HV_BLOCK_SIZE) != 0)
+++ {
+++ Hive->Free(Hive->HiveHeader);
+++ Hive->Free(Hive->Storage[HvStable].BlockList);
+++ return STATUS_REGISTRY_CORRUPT;
+++ }
+++
+++ NewBin = Hive->Allocate(Bin->Size, TRUE);
+++ if (NewBin == NULL)
+++ {
+++ Hive->Free(Hive->HiveHeader);
+++ Hive->Free(Hive->Storage[HvStable].BlockList);
+++ return STATUS_NO_MEMORY;
+++ }
+++
+++ Hive->Storage[HvStable].BlockList[BlockIndex].Bin = (ULONG_PTR)NewBin;
+++ Hive->Storage[HvStable].BlockList[BlockIndex].Block = (ULONG_PTR)NewBin;
+++
+++ RtlCopyMemory(NewBin, Bin, Bin->Size);
+++
+++ if (Bin->Size > HV_BLOCK_SIZE)
+++ {
+++ for (i = 1; i < Bin->Size / HV_BLOCK_SIZE; i++)
+++ {
+++ Hive->Storage[HvStable].BlockList[BlockIndex + i].Bin = (ULONG_PTR)NewBin;
+++ Hive->Storage[HvStable].BlockList[BlockIndex + i].Block =
+++ ((ULONG_PTR)NewBin + (i * HV_BLOCK_SIZE));
+++ }
+++ }
+++
+++ BlockIndex += Bin->Size / HV_BLOCK_SIZE;
+++ }
+++
+++ if (HvpCreateHiveFreeCellList(Hive))
+++ {
+++ HvpFreeHiveBins(Hive);
+++ Hive->Free(Hive->HiveHeader);
+++ return STATUS_NO_MEMORY;
+++ }
+++
+++ BitmapSize = ROUND_UP(Hive->Storage[HvStable].Length,
+++ sizeof(ULONG) * 8) / 8;
+++ BitmapBuffer = (PULONG)Hive->Allocate(BitmapSize, TRUE);
+++ if (BitmapBuffer == NULL)
+++ {
+++ HvpFreeHiveBins(Hive);
+++ Hive->Free(Hive->HiveHeader);
+++ return STATUS_NO_MEMORY;
+++ }
+++
+++ RtlInitializeBitMap(&Hive->DirtyVector, BitmapBuffer, BitmapSize * 8);
+++ RtlClearAllBits(&Hive->DirtyVector);
+++
+++ return STATUS_SUCCESS;
+++}
+++
+++/**
+++ * @name HvpInitializeMemoryInplaceHive
+++ *
+++ * Internal helper function to initalize hive descriptor structure for
+++ * a hive stored in memory. The in-memory data of the hive are directly
+++ * used and it is read-only accessible.
+++ *
+++ * @see HvInitialize
+++ */
+++
+++NTSTATUS CMAPI
+++HvpInitializeMemoryInplaceHive(
+++ PHHIVE Hive,
+++ ULONG_PTR ChunkBase)
+++{
+++ if (!HvpVerifyHiveHeader((PHBASE_BLOCK)ChunkBase))
+++ {
+++ return STATUS_REGISTRY_CORRUPT;
+++ }
+++
+++ Hive->HiveHeader = (PHBASE_BLOCK)ChunkBase;
+++ Hive->ReadOnly = TRUE;
+++ Hive->Flat = TRUE;
+++
+++ return STATUS_SUCCESS;
+++}
+++
+++/**
+++ * @name HvInitialize
+++ *
+++ * Allocate a new hive descriptor structure and intialize it.
+++ *
+++ * @param RegistryHive
+++ * Output variable to store pointer to the hive descriptor.
+++ * @param Operation
+++ * - HV_OPERATION_CREATE_HIVE
+++ * Create a new hive for read/write access.
+++ * - HV_OPERATION_MEMORY
+++ * Load and copy in-memory hive for read/write access. The
+++ * pointer to data passed to this routine can be freed after
+++ * the function is executed.
+++ * - HV_OPERATION_MEMORY_INPLACE
+++ * Load an in-memory hive for read-only access. The pointer
+++ * to data passed to this routine MUSTN'T be freed until
+++ * HvFree is called.
+++ * @param ChunkBase
+++ * Pointer to hive data.
+++ * @param ChunkSize
+++ * Size of passed hive data.
+++ *
+++ * @return
+++ * STATUS_NO_MEMORY - A memory allocation failed.
+++ * STATUS_REGISTRY_CORRUPT - Registry corruption was detected.
+++ * STATUS_SUCCESS
+++ *
+++ * @see HvFree
+++ */
+++
+++NTSTATUS CMAPI
+++HvInitialize(
+++ PHHIVE RegistryHive,
+++ ULONG Operation,
+++ ULONG HiveType,
+++ ULONG HiveFlags,
+++ ULONG_PTR HiveData OPTIONAL,
+++ ULONG Cluster OPTIONAL,
+++ PALLOCATE_ROUTINE Allocate,
+++ PFREE_ROUTINE Free,
+++ PFILE_READ_ROUTINE FileRead,
+++ PFILE_WRITE_ROUTINE FileWrite,
+++ PFILE_SET_SIZE_ROUTINE FileSetSize,
+++ PFILE_FLUSH_ROUTINE FileFlush,
+++ IN PUNICODE_STRING FileName)
+++{
+++ NTSTATUS Status;
+++ PHHIVE Hive = RegistryHive;
+++
+++ /*
+++ * Create a new hive structure that will hold all the maintenance data.
+++ */
+++
+++ RtlZeroMemory(Hive, sizeof(HHIVE));
+++
+++ Hive->Allocate = Allocate;
+++ Hive->Free = Free;
+++ Hive->FileRead = FileRead;
+++ Hive->FileWrite = FileWrite;
+++ Hive->FileSetSize = FileSetSize;
+++ Hive->FileFlush = FileFlush;
+++
+++ switch (Operation)
+++ {
+++ case HV_OPERATION_CREATE_HIVE:
+++ Status = HvpCreateHive(Hive);
+++ break;
+++
+++ case HV_OPERATION_MEMORY:
+++ Status = HvpInitializeMemoryHive(Hive, HiveData);
+++ break;
+++
+++ case HV_OPERATION_MEMORY_INPLACE:
+++ Status = HvpInitializeMemoryInplaceHive(Hive, HiveData);
+++ break;
+++
+++ default:
+++ /* FIXME: A better return status value is needed */
+++ Status = STATUS_NOT_IMPLEMENTED;
+++ ASSERT(FALSE);
+++ }
+++
+++ if (!NT_SUCCESS(Status))
+++ {
+++ Hive->Free(Hive);
+++ return Status;
+++ }
+++
+++ return Status;
+++}
+++
+++/**
+++ * @name HvFree
+++ *
+++ * Free all stroage and handles associated with hive descriptor.
+++ */
+++
+++VOID CMAPI
+++HvFree(
+++ PHHIVE RegistryHive)
+++{
+++ if (!RegistryHive->ReadOnly)
+++ {
+++ /* Release hive bitmap */
+++ if (RegistryHive->DirtyVector.Buffer)
+++ {
+++ RegistryHive->Free(RegistryHive->DirtyVector.Buffer);
+++ }
+++
+++ HvpFreeHiveBins(RegistryHive);
+++ }
+++
+++ RegistryHive->Free(RegistryHive);
+++}
+++
+++/* EOF */
---/*\r
--- * PROJECT: registry manipulation library\r
--- * LICENSE: GPL - See COPYING in the top level directory\r
--- * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>\r
--- * Copyright 2001 - 2005 Eric Kohl\r
--- */\r
---\r
---#include "cmlib.h"\r
---#define NDEBUG\r
---#include <debug.h>\r
---\r
---static BOOLEAN CMAPI\r
---HvpWriteLog(\r
--- PHHIVE RegistryHive)\r
---{\r
- ULONG FileOffset;\r
- ULONG BufferSize;\r
- ULONG BitmapSize;\r
-- ULONGLONG FileOffset;\r
-- SIZE_T BufferSize;\r
-- SIZE_T BitmapSize;\r
--- PUCHAR Buffer;\r
--- PUCHAR Ptr;\r
--- ULONG BlockIndex;\r
--- ULONG LastIndex;\r
--- PVOID BlockPtr;\r
--- BOOLEAN Success;\r
--- \r
--- ASSERT(RegistryHive->ReadOnly == FALSE);\r
--- \r
--- DPRINT("HvpWriteLog called\n");\r
---\r
--- if (RegistryHive->HiveHeader->Sequence1 !=\r
--- RegistryHive->HiveHeader->Sequence2)\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- BitmapSize = RegistryHive->DirtyVector.SizeOfBitMap;\r
--- BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize;\r
--- BufferSize = ROUND_UP(BufferSize, HV_BLOCK_SIZE);\r
---\r
--- DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);\r
---\r
--- Buffer = RegistryHive->Allocate(BufferSize, TRUE);\r
--- if (Buffer == NULL)\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- /* Update first update counter and checksum */\r
--- RegistryHive->HiveHeader->Type = HV_TYPE_LOG;\r
--- RegistryHive->HiveHeader->Sequence1++;\r
--- RegistryHive->HiveHeader->Checksum =\r
--- HvpHiveHeaderChecksum(RegistryHive->HiveHeader);\r
---\r
--- /* Copy hive header */\r
--- RtlCopyMemory(Buffer, RegistryHive->HiveHeader, HV_LOG_HEADER_SIZE);\r
--- Ptr = Buffer + HV_LOG_HEADER_SIZE;\r
--- RtlCopyMemory(Ptr, "DIRT", 4);\r
--- Ptr += 4;\r
--- RtlCopyMemory(Ptr, RegistryHive->DirtyVector.Buffer, BitmapSize);\r
---\r
--- /* Write hive block and block bitmap */\r
--- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,\r
--- 0, Buffer, BufferSize);\r
--- if (!Success)\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- RegistryHive->Free(Buffer);\r
---\r
--- /* Write dirty blocks */\r
--- FileOffset = BufferSize;\r
--- BlockIndex = 0;\r
--- while (BlockIndex < RegistryHive->Storage[HvStable].Length)\r
--- {\r
--- LastIndex = BlockIndex;\r
--- BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);\r
--- if (BlockIndex == ~0 || BlockIndex < LastIndex)\r
--- {\r
--- break;\r
--- }\r
---\r
--- BlockPtr = (PVOID)RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;\r
---\r
--- /* Write hive block */\r
--- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,\r
--- FileOffset, BlockPtr,\r
--- HV_BLOCK_SIZE);\r
--- if (!Success)\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- BlockIndex++;\r
--- FileOffset += HV_BLOCK_SIZE;\r
--- }\r
---\r
--- Success = RegistryHive->FileSetSize(RegistryHive, HV_TYPE_LOG, FileOffset);\r
--- if (!Success)\r
--- {\r
--- DPRINT("FileSetSize failed\n");\r
--- return FALSE;\r
--- }\r
---\r
--- /* Flush the log file */\r
--- Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);\r
--- if (!Success)\r
--- {\r
--- DPRINT("FileFlush failed\n");\r
--- }\r
---\r
--- /* Update first and second update counter and checksum. */\r
--- RegistryHive->HiveHeader->Sequence2++;\r
--- RegistryHive->HiveHeader->Checksum =\r
--- HvpHiveHeaderChecksum(RegistryHive->HiveHeader);\r
---\r
--- /* Write hive header again with updated sequence counter. */\r
--- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,\r
--- 0, RegistryHive->HiveHeader,\r
--- HV_LOG_HEADER_SIZE);\r
--- if (!Success)\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- /* Flush the log file */\r
--- Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);\r
--- if (!Success)\r
--- {\r
--- DPRINT("FileFlush failed\n");\r
--- }\r
---\r
--- return TRUE;\r
---}\r
---\r
---static BOOLEAN CMAPI\r
---HvpWriteHive(\r
--- PHHIVE RegistryHive,\r
--- BOOLEAN OnlyDirty)\r
---{\r
- ULONG FileOffset;\r
-- ULONGLONG FileOffset;\r
--- ULONG BlockIndex;\r
--- ULONG LastIndex;\r
--- PVOID BlockPtr;\r
--- BOOLEAN Success;\r
---\r
--- ASSERT(RegistryHive->ReadOnly == FALSE);\r
--- \r
--- DPRINT("HvpWriteHive called\n");\r
---\r
--- if (RegistryHive->HiveHeader->Sequence1 !=\r
--- RegistryHive->HiveHeader->Sequence2)\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- /* Update first update counter and checksum */\r
--- RegistryHive->HiveHeader->Type = HV_TYPE_PRIMARY;\r
--- RegistryHive->HiveHeader->Sequence1++;\r
--- RegistryHive->HiveHeader->Checksum =\r
--- HvpHiveHeaderChecksum(RegistryHive->HiveHeader);\r
---\r
--- /* Write hive block */\r
--- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,\r
--- 0, RegistryHive->HiveHeader,\r
--- sizeof(HBASE_BLOCK));\r
--- if (!Success)\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- BlockIndex = 0;\r
--- while (BlockIndex < RegistryHive->Storage[HvStable].Length)\r
--- {\r
--- if (OnlyDirty)\r
--- {\r
--- LastIndex = BlockIndex;\r
--- BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);\r
--- if (BlockIndex == ~0 || BlockIndex < LastIndex)\r
--- {\r
--- break;\r
--- }\r
--- }\r
---\r
--- BlockPtr = (PVOID)RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;\r
--- FileOffset = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)HV_BLOCK_SIZE;\r
---\r
--- /* Write hive block */\r
--- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,\r
--- FileOffset, BlockPtr,\r
--- HV_BLOCK_SIZE);\r
--- if (!Success)\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- BlockIndex++;\r
--- }\r
---\r
--- Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);\r
--- if (!Success)\r
--- {\r
--- DPRINT("FileFlush failed\n");\r
--- }\r
---\r
--- /* Update second update counter and checksum */\r
--- RegistryHive->HiveHeader->Sequence2++;\r
--- RegistryHive->HiveHeader->Checksum =\r
--- HvpHiveHeaderChecksum(RegistryHive->HiveHeader);\r
---\r
--- /* Write hive block */\r
--- Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,\r
--- 0, RegistryHive->HiveHeader,\r
--- sizeof(HBASE_BLOCK));\r
--- if (!Success)\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);\r
--- if (!Success)\r
--- {\r
--- DPRINT("FileFlush failed\n");\r
--- }\r
---\r
--- return TRUE;\r
---}\r
---\r
---BOOLEAN CMAPI\r
---HvSyncHive(\r
--- PHHIVE RegistryHive)\r
---{\r
--- ASSERT(RegistryHive->ReadOnly == FALSE);\r
---\r
--- if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0)\r
--- {\r
--- return TRUE;\r
--- }\r
---\r
--- /* Update hive header modification time */\r
--- KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);\r
---\r
--- /* Update log file */\r
--- if (!HvpWriteLog(RegistryHive))\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- /* Update hive file */\r
--- if (!HvpWriteHive(RegistryHive, TRUE))\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- /* Clear dirty bitmap. */\r
--- RtlClearAllBits(&RegistryHive->DirtyVector);\r
---\r
--- return TRUE;\r
---}\r
---\r
---BOOLEAN CMAPI\r
---HvWriteHive(\r
--- PHHIVE RegistryHive)\r
---{\r
--- ASSERT(RegistryHive->ReadOnly == FALSE);\r
---\r
--- /* Update hive header modification time */\r
--- KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);\r
---\r
--- /* Update hive file */\r
--- if (!HvpWriteHive(RegistryHive, FALSE))\r
--- {\r
--- return FALSE;\r
--- }\r
---\r
--- return TRUE;\r
---}\r
+++/*
+++ * PROJECT: registry manipulation library
+++ * LICENSE: GPL - See COPYING in the top level directory
+++ * COPYRIGHT: Copyright 2005 Filip Navara <navaraf@reactos.org>
+++ * Copyright 2001 - 2005 Eric Kohl
+++ */
+++
+++#include "cmlib.h"
+++#define NDEBUG
+++#include <debug.h>
+++
+++static BOOLEAN CMAPI
+++HvpWriteLog(
+++ PHHIVE RegistryHive)
+++{
+++ ULONGLONG FileOffset;
+++ SIZE_T BufferSize;
+++ SIZE_T BitmapSize;
+++ PUCHAR Buffer;
+++ PUCHAR Ptr;
+++ ULONG BlockIndex;
+++ ULONG LastIndex;
+++ PVOID BlockPtr;
+++ BOOLEAN Success;
+++
+++ ASSERT(RegistryHive->ReadOnly == FALSE);
+++
+++ DPRINT("HvpWriteLog called\n");
+++
+++ if (RegistryHive->HiveHeader->Sequence1 !=
+++ RegistryHive->HiveHeader->Sequence2)
+++ {
+++ return FALSE;
+++ }
+++
+++ BitmapSize = RegistryHive->DirtyVector.SizeOfBitMap;
+++ BufferSize = HV_LOG_HEADER_SIZE + sizeof(ULONG) + BitmapSize;
+++ BufferSize = ROUND_UP(BufferSize, HV_BLOCK_SIZE);
+++
+++ DPRINT("Bitmap size %lu buffer size: %lu\n", BitmapSize, BufferSize);
+++
+++ Buffer = RegistryHive->Allocate(BufferSize, TRUE);
+++ if (Buffer == NULL)
+++ {
+++ return FALSE;
+++ }
+++
+++ /* Update first update counter and checksum */
+++ RegistryHive->HiveHeader->Type = HV_TYPE_LOG;
+++ RegistryHive->HiveHeader->Sequence1++;
+++ RegistryHive->HiveHeader->Checksum =
+++ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+++
+++ /* Copy hive header */
+++ RtlCopyMemory(Buffer, RegistryHive->HiveHeader, HV_LOG_HEADER_SIZE);
+++ Ptr = Buffer + HV_LOG_HEADER_SIZE;
+++ RtlCopyMemory(Ptr, "DIRT", 4);
+++ Ptr += 4;
+++ RtlCopyMemory(Ptr, RegistryHive->DirtyVector.Buffer, BitmapSize);
+++
+++ /* Write hive block and block bitmap */
+++ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+++ 0, Buffer, BufferSize);
+++ if (!Success)
+++ {
+++ return FALSE;
+++ }
+++
+++ RegistryHive->Free(Buffer);
+++
+++ /* Write dirty blocks */
+++ FileOffset = BufferSize;
+++ BlockIndex = 0;
+++ while (BlockIndex < RegistryHive->Storage[HvStable].Length)
+++ {
+++ LastIndex = BlockIndex;
+++ BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
+++ if (BlockIndex == ~0 || BlockIndex < LastIndex)
+++ {
+++ break;
+++ }
+++
+++ BlockPtr = (PVOID)RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;
+++
+++ /* Write hive block */
+++ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+++ FileOffset, BlockPtr,
+++ HV_BLOCK_SIZE);
+++ if (!Success)
+++ {
+++ return FALSE;
+++ }
+++
+++ BlockIndex++;
+++ FileOffset += HV_BLOCK_SIZE;
+++ }
+++
+++ Success = RegistryHive->FileSetSize(RegistryHive, HV_TYPE_LOG, FileOffset);
+++ if (!Success)
+++ {
+++ DPRINT("FileSetSize failed\n");
+++ return FALSE;
+++ }
+++
+++ /* Flush the log file */
+++ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);
+++ if (!Success)
+++ {
+++ DPRINT("FileFlush failed\n");
+++ }
+++
+++ /* Update first and second update counter and checksum. */
+++ RegistryHive->HiveHeader->Sequence2++;
+++ RegistryHive->HiveHeader->Checksum =
+++ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+++
+++ /* Write hive header again with updated sequence counter. */
+++ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+++ 0, RegistryHive->HiveHeader,
+++ HV_LOG_HEADER_SIZE);
+++ if (!Success)
+++ {
+++ return FALSE;
+++ }
+++
+++ /* Flush the log file */
+++ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);
+++ if (!Success)
+++ {
+++ DPRINT("FileFlush failed\n");
+++ }
+++
+++ return TRUE;
+++}
+++
+++static BOOLEAN CMAPI
+++HvpWriteHive(
+++ PHHIVE RegistryHive,
+++ BOOLEAN OnlyDirty)
+++{
+++ ULONGLONG FileOffset;
+++ ULONG BlockIndex;
+++ ULONG LastIndex;
+++ PVOID BlockPtr;
+++ BOOLEAN Success;
+++
+++ ASSERT(RegistryHive->ReadOnly == FALSE);
+++
+++ DPRINT("HvpWriteHive called\n");
+++
+++ if (RegistryHive->HiveHeader->Sequence1 !=
+++ RegistryHive->HiveHeader->Sequence2)
+++ {
+++ return FALSE;
+++ }
+++
+++ /* Update first update counter and checksum */
+++ RegistryHive->HiveHeader->Type = HV_TYPE_PRIMARY;
+++ RegistryHive->HiveHeader->Sequence1++;
+++ RegistryHive->HiveHeader->Checksum =
+++ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+++
+++ /* Write hive block */
+++ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+++ 0, RegistryHive->HiveHeader,
+++ sizeof(HBASE_BLOCK));
+++ if (!Success)
+++ {
+++ return FALSE;
+++ }
+++
+++ BlockIndex = 0;
+++ while (BlockIndex < RegistryHive->Storage[HvStable].Length)
+++ {
+++ if (OnlyDirty)
+++ {
+++ LastIndex = BlockIndex;
+++ BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
+++ if (BlockIndex == ~0 || BlockIndex < LastIndex)
+++ {
+++ break;
+++ }
+++ }
+++
+++ BlockPtr = (PVOID)RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;
+++ FileOffset = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)HV_BLOCK_SIZE;
+++
+++ /* Write hive block */
+++ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+++ FileOffset, BlockPtr,
+++ HV_BLOCK_SIZE);
+++ if (!Success)
+++ {
+++ return FALSE;
+++ }
+++
+++ BlockIndex++;
+++ }
+++
+++ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);
+++ if (!Success)
+++ {
+++ DPRINT("FileFlush failed\n");
+++ }
+++
+++ /* Update second update counter and checksum */
+++ RegistryHive->HiveHeader->Sequence2++;
+++ RegistryHive->HiveHeader->Checksum =
+++ HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+++
+++ /* Write hive block */
+++ Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+++ 0, RegistryHive->HiveHeader,
+++ sizeof(HBASE_BLOCK));
+++ if (!Success)
+++ {
+++ return FALSE;
+++ }
+++
+++ Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);
+++ if (!Success)
+++ {
+++ DPRINT("FileFlush failed\n");
+++ }
+++
+++ return TRUE;
+++}
+++
+++BOOLEAN CMAPI
+++HvSyncHive(
+++ PHHIVE RegistryHive)
+++{
+++ ASSERT(RegistryHive->ReadOnly == FALSE);
+++
+++ if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0)
+++ {
+++ return TRUE;
+++ }
+++
+++ /* Update hive header modification time */
+++ KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);
+++
+++ /* Update log file */
+++ if (!HvpWriteLog(RegistryHive))
+++ {
+++ return FALSE;
+++ }
+++
+++ /* Update hive file */
+++ if (!HvpWriteHive(RegistryHive, TRUE))
+++ {
+++ return FALSE;
+++ }
+++
+++ /* Clear dirty bitmap. */
+++ RtlClearAllBits(&RegistryHive->DirtyVector);
+++
+++ return TRUE;
+++}
+++
+++BOOLEAN CMAPI
+++HvWriteHive(
+++ PHHIVE RegistryHive)
+++{
+++ ASSERT(RegistryHive->ReadOnly == FALSE);
+++
+++ /* Update hive header modification time */
+++ KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);
+++
+++ /* Update hive file */
+++ if (!HvpWriteHive(RegistryHive, FALSE))
+++ {
+++ return FALSE;
+++ }
+++
+++ return TRUE;
+++}
__asm__("mov %%ebp, %0" : "=r" (Stack) : );
#elif defined(_MSC_VER)
__asm mov Stack, ebp
- #elif defined(_M_PPC)
- __asm__("mr %0, %%r1" : "=r" (Stack) : );
++#endif
#endif
/* Set it as the stack begin limit as well */
---/*\r
--- * COPYRIGHT: See COPYING in the top level directory\r
--- * PROJECT: ReactOS Run-Time Library\r
--- * PURPOSE: Memory functions\r
--- * FILE: lib/rtl/i386/rtlswap.S\r
--- * PROGRAMER: Alex Ionescu (alex.ionescu@reactos.org)\r
--- */\r
---\r
---.intel_syntax noprefix\r
---\r
---/* GLOBALS *******************************************************************/\r
---\r
---.globl _RtlCompareMemory@12\r
---.globl _RtlCompareMemoryUlong@12\r
---.globl _RtlFillMemory@12\r
---.globl _RtlFillMemoryUlong@12\r
---.globl _RtlMoveMemory@12\r
---.globl _RtlZeroMemory@8\r
---.globl @RtlPrefetchMemoryNonTemporal@8\r
---\r
---/* FUNCTIONS *****************************************************************/\r
---\r
---.func RtlCompareMemory@12\r
---_RtlCompareMemory@12:\r
---\r
--- /* Save volatiles */\r
--- push esi\r
--- push edi\r
---\r
--- /* Clear direction flag and load pointers and size in ULONGs */\r
--- cld\r
--- mov esi, [esp+12]\r
--- mov edi, [esp+16]\r
--- mov ecx, [esp+20]\r
--- shr ecx, 2\r
--- jz NoUlongs\r
---\r
--- /* Compare the ULONGs */\r
--- repe cmpsd\r
--- jnz NotEqual\r
---\r
---NoUlongs:\r
---\r
--- /* Compare what's left */\r
--- mov ecx, [esp+20]\r
--- and ecx, 3\r
--- jz NoneLeft\r
--- repe cmpsb\r
--- jnz NotEqual2\r
---\r
---NoneLeft:\r
---\r
--- /* We're done, return full count */\r
--- mov eax, [esp+20]\r
--- pop edi\r
--- pop esi\r
--- ret 12\r
---\r
---NotEqual:\r
--- /* Compare the last ULONG */\r
--- sub esi, 4\r
--- sub edi, 4\r
--- mov ecx, 5\r
--- repe cmpsb\r
---\r
---NotEqual2:\r
---\r
--- /* Remember how many mathced */\r
--- dec esi\r
--- sub esi, [esp+12]\r
---\r
--- /* Return count */\r
--- mov eax, esi\r
--- pop edi\r
--- pop esi\r
--- ret 12\r
---.endfunc\r
---\r
---.func RtlCompareMemoryUlong@12\r
---_RtlCompareMemoryUlong@12:\r
---\r
--- /* Get pointers and size in ULONGs */\r
--- push edi\r
--- mov edi, [esp+8]\r
--- mov ecx, [esp+12]\r
--- mov eax, [esp+16]\r
--- shr ecx, 2\r
---\r
--- /* Do the compare and check result */\r
--- repe scasd\r
--- jz Done\r
--- sub edi, 4\r
---\r
--- /* Return count */\r
---Done:\r
--- sub edi, [esp+8]\r
--- mov eax, edi\r
--- pop edi\r
--- ret 12\r
---.endfunc\r
---\r
---.func RtlFillMemory@12\r
---_RtlFillMemory@12:\r
---\r
--- /* Get pointers and size */\r
--- push edi\r
--- mov edi, [esp+8]\r
--- mov ecx, [esp+12]\r
---\r
--- /* Get pattern */\r
--- mov al, [esp+16]\r
--- mov ah, al\r
--- shl eax, 16\r
--- mov al, [esp+16]\r
--- mov ah, al\r
---\r
--- /* Clear direction flag and set ULONG size and UCHAR remainder */\r
--- cld\r
--- mov edx, ecx\r
--- and edx, 3\r
--- shr ecx, 2\r
---\r
--- /* Do the fill */\r
--- rep stosd\r
--- or ecx, edx\r
--- jnz ByteFill\r
---\r
--- /* Return */\r
--- pop edi\r
--- ret 12\r
---\r
---ByteFill:\r
--- /* Fill what's left */\r
--- rep stosb\r
--- pop edi\r
--- ret 12\r
---.endfunc\r
---\r
---.func RtlFillMemoryUlong@12\r
---_RtlFillMemoryUlong@12:\r
---\r
--- /* Get pointer, size and pattern */\r
--- push edi\r
--- mov edi, [esp+8]\r
--- mov ecx, [esp+12]\r
--- mov eax, [esp+16]\r
--- shr ecx, 2\r
---\r
--- /* Do the fill and return */\r
--- rep stosd\r
--- pop edi\r
--- ret 12\r
---.endfunc\r
---\r
---.func RtlFillMemoryUlonglong@16\r
---_RtlFillMemoryUlonglong@16:\r
---\r
--- /* Save volatiles */\r
--- push edi\r
--- push esi\r
---\r
--- /* Get pointer, size and pattern */\r
--- mov ecx, [esp+16]\r
--- mov esi, [esp+12]\r
--- mov eax, [esp+20]\r
--- shr ecx, 2\r
--- sub ecx, 2\r
---\r
--- /* Save the first part */\r
--- mov [esi], eax\r
---\r
--- /* Read second part */\r
--- mov eax, [esp+24]\r
--- lea edi, [esi+8]\r
--- mov [esi+4], eax\r
---\r
--- /* Do the fill and return */\r
--- rep movsd\r
--- pop esi\r
--- pop edi\r
--- ret 16\r
---.endfunc\r
---\r
---.func RtlZeroMemory@8\r
---_RtlZeroMemory@8:\r
---\r
--- /* Get pointers and size */\r
--- push edi\r
--- mov edi, [esp+8]\r
--- mov ecx, [esp+12]\r
---\r
--- /* Get pattern */\r
--- xor eax, eax\r
---\r
--- /* Clear direction flag and set ULONG size and UCHAR remainder */\r
--- cld\r
--- mov edx, ecx\r
--- and edx, 3\r
--- shr ecx, 2\r
---\r
--- /* Do the fill */\r
--- rep stosd\r
--- or ecx, edx\r
--- jnz ByteZero\r
---\r
--- /* Return */\r
--- pop edi\r
--- ret 8\r
---\r
---ByteZero:\r
--- /* Fill what's left */\r
--- rep stosb\r
--- pop edi\r
--- ret 8\r
---.endfunc\r
---\r
---.func RtlMoveMemory@12\r
---_RtlMoveMemory@12:\r
---\r
--- /* Save volatiles */\r
--- push esi\r
--- push edi\r
---\r
--- /* Get pointers and size */\r
--- mov esi, [esp+16]\r
--- mov edi, [esp+12]\r
--- mov ecx, [esp+20]\r
--- cld\r
---\r
--- /* Check if the destination is higher (or equal) */\r
--- cmp esi, edi\r
--- jbe Overlap\r
---\r
--- /* Set ULONG size and UCHAR remainder */\r
---DoMove:\r
--- mov edx, ecx\r
--- and edx, 3\r
--- shr ecx, 2\r
---\r
--- /* Do the move */\r
--- rep movsd\r
--- or ecx, edx\r
--- jnz ByteMove\r
---\r
--- /* Return */\r
--- pop edi\r
--- pop esi\r
--- ret 12\r
---\r
---ByteMove:\r
--- /* Move what's left */\r
- rep stosb\r
-- rep movsb\r
---\r
---DoneMove:\r
--- /* Restore volatiles */\r
--- pop edi\r
--- pop esi\r
--- ret 12\r
---\r
---Overlap:\r
--- /* Don't copy if they're equal */\r
--- jz DoneMove\r
---\r
--- /* Compare pointer distance with given length and check for overlap */\r
--- mov eax, edi\r
--- sub eax, esi\r
--- cmp ecx, eax\r
--- jbe DoMove\r
---\r
--- /* Set direction flag for backward move */\r
--- std\r
---\r
--- /* Copy byte-by-byte the non-overlapping distance */\r
--- add esi, ecx\r
--- add edi, ecx\r
--- dec esi\r
--- dec edi\r
---\r
--- /* Do the move, reset flag and return */\r
--- rep movsb\r
--- cld\r
--- jmp DoneMove\r
---.endfunc\r
---\r
---.func @RtlPrefetchMemoryNonTemporal@8, @RtlPrefetchMemoryNonTemporal@8\r
---@RtlPrefetchMemoryNonTemporal@8:\r
---\r
--- /*\r
--- * Overwritten by ntoskrnl/ke/i386/kernel.c if SSE is supported\r
--- * (see Ki386SetProcessorFeatures())\r
--- */\r
--- ret\r
---\r
--- /* Get granularity */\r
--- mov eax, [_Ke386CacheAlignment]\r
---\r
---FetchLine:\r
---\r
--- /* Prefetch this line */\r
--- prefetchnta byte ptr [ecx]\r
---\r
--- /* Update address and count */\r
--- add ecx, eax\r
--- sub edx, eax\r
---\r
--- /* Keep looping for the next line, or return if done */\r
--- ja FetchLine\r
--- ret\r
---.endfunc\r
---\r
---/* FIXME: HACK */\r
---_Ke386CacheAlignment:\r
--- .long 0x40\r
+++/*
+++ * COPYRIGHT: See COPYING in the top level directory
+++ * PROJECT: ReactOS Run-Time Library
+++ * PURPOSE: Memory functions
+++ * FILE: lib/rtl/i386/rtlswap.S
+++ * PROGRAMER: Alex Ionescu (alex.ionescu@reactos.org)
+++ */
+++
+++.intel_syntax noprefix
+++
+++/* GLOBALS *******************************************************************/
+++
+++.globl _RtlCompareMemory@12
+++.globl _RtlCompareMemoryUlong@12
+++.globl _RtlFillMemory@12
+++.globl _RtlFillMemoryUlong@12
+++.globl _RtlMoveMemory@12
+++.globl _RtlZeroMemory@8
+++.globl @RtlPrefetchMemoryNonTemporal@8
+++
+++/* FUNCTIONS *****************************************************************/
+++
+++.func RtlCompareMemory@12
+++_RtlCompareMemory@12:
+++
+++ /* Save volatiles */
+++ push esi
+++ push edi
+++
+++ /* Clear direction flag and load pointers and size in ULONGs */
+++ cld
+++ mov esi, [esp+12]
+++ mov edi, [esp+16]
+++ mov ecx, [esp+20]
+++ shr ecx, 2
+++ jz NoUlongs
+++
+++ /* Compare the ULONGs */
+++ repe cmpsd
+++ jnz NotEqual
+++
+++NoUlongs:
+++
+++ /* Compare what's left */
+++ mov ecx, [esp+20]
+++ and ecx, 3
+++ jz NoneLeft
+++ repe cmpsb
+++ jnz NotEqual2
+++
+++NoneLeft:
+++
+++ /* We're done, return full count */
+++ mov eax, [esp+20]
+++ pop edi
+++ pop esi
+++ ret 12
+++
+++NotEqual:
+++ /* Compare the last ULONG */
+++ sub esi, 4
+++ sub edi, 4
+++ mov ecx, 5
+++ repe cmpsb
+++
+++NotEqual2:
+++
+++ /* Remember how many mathced */
+++ dec esi
+++ sub esi, [esp+12]
+++
+++ /* Return count */
+++ mov eax, esi
+++ pop edi
+++ pop esi
+++ ret 12
+++.endfunc
+++
+++.func RtlCompareMemoryUlong@12
+++_RtlCompareMemoryUlong@12:
+++
+++ /* Get pointers and size in ULONGs */
+++ push edi
+++ mov edi, [esp+8]
+++ mov ecx, [esp+12]
+++ mov eax, [esp+16]
+++ shr ecx, 2
+++
+++ /* Do the compare and check result */
+++ repe scasd
+++ jz Done
+++ sub edi, 4
+++
+++ /* Return count */
+++Done:
+++ sub edi, [esp+8]
+++ mov eax, edi
+++ pop edi
+++ ret 12
+++.endfunc
+++
+++.func RtlFillMemory@12
+++_RtlFillMemory@12:
+++
+++ /* Get pointers and size */
+++ push edi
+++ mov edi, [esp+8]
+++ mov ecx, [esp+12]
+++
+++ /* Get pattern */
+++ mov al, [esp+16]
+++ mov ah, al
+++ shl eax, 16
+++ mov al, [esp+16]
+++ mov ah, al
+++
+++ /* Clear direction flag and set ULONG size and UCHAR remainder */
+++ cld
+++ mov edx, ecx
+++ and edx, 3
+++ shr ecx, 2
+++
+++ /* Do the fill */
+++ rep stosd
+++ or ecx, edx
+++ jnz ByteFill
+++
+++ /* Return */
+++ pop edi
+++ ret 12
+++
+++ByteFill:
+++ /* Fill what's left */
+++ rep stosb
+++ pop edi
+++ ret 12
+++.endfunc
+++
+++.func RtlFillMemoryUlong@12
+++_RtlFillMemoryUlong@12:
+++
+++ /* Get pointer, size and pattern */
+++ push edi
+++ mov edi, [esp+8]
+++ mov ecx, [esp+12]
+++ mov eax, [esp+16]
+++ shr ecx, 2
+++
+++ /* Do the fill and return */
+++ rep stosd
+++ pop edi
+++ ret 12
+++.endfunc
+++
+++.func RtlFillMemoryUlonglong@16
+++_RtlFillMemoryUlonglong@16:
+++
+++ /* Save volatiles */
+++ push edi
+++ push esi
+++
+++ /* Get pointer, size and pattern */
+++ mov ecx, [esp+16]
+++ mov esi, [esp+12]
+++ mov eax, [esp+20]
+++ shr ecx, 2
+++ sub ecx, 2
+++
+++ /* Save the first part */
+++ mov [esi], eax
+++
+++ /* Read second part */
+++ mov eax, [esp+24]
+++ lea edi, [esi+8]
+++ mov [esi+4], eax
+++
+++ /* Do the fill and return */
+++ rep movsd
+++ pop esi
+++ pop edi
+++ ret 16
+++.endfunc
+++
+++.func RtlZeroMemory@8
+++_RtlZeroMemory@8:
+++
+++ /* Get pointers and size */
+++ push edi
+++ mov edi, [esp+8]
+++ mov ecx, [esp+12]
+++
+++ /* Get pattern */
+++ xor eax, eax
+++
+++ /* Clear direction flag and set ULONG size and UCHAR remainder */
+++ cld
+++ mov edx, ecx
+++ and edx, 3
+++ shr ecx, 2
+++
+++ /* Do the fill */
+++ rep stosd
+++ or ecx, edx
+++ jnz ByteZero
+++
+++ /* Return */
+++ pop edi
+++ ret 8
+++
+++ByteZero:
+++ /* Fill what's left */
+++ rep stosb
+++ pop edi
+++ ret 8
+++.endfunc
+++
+++.func RtlMoveMemory@12
+++_RtlMoveMemory@12:
+++
+++ /* Save volatiles */
+++ push esi
+++ push edi
+++
+++ /* Get pointers and size */
+++ mov esi, [esp+16]
+++ mov edi, [esp+12]
+++ mov ecx, [esp+20]
+++ cld
+++
+++ /* Check if the destination is higher (or equal) */
+++ cmp esi, edi
+++ jbe Overlap
+++
+++ /* Set ULONG size and UCHAR remainder */
+++DoMove:
+++ mov edx, ecx
+++ and edx, 3
+++ shr ecx, 2
+++
+++ /* Do the move */
+++ rep movsd
+++ or ecx, edx
+++ jnz ByteMove
+++
+++ /* Return */
+++ pop edi
+++ pop esi
+++ ret 12
+++
+++ByteMove:
+++ /* Move what's left */
+++ rep movsb
+++
+++DoneMove:
+++ /* Restore volatiles */
+++ pop edi
+++ pop esi
+++ ret 12
+++
+++Overlap:
+++ /* Don't copy if they're equal */
+++ jz DoneMove
+++
+++ /* Compare pointer distance with given length and check for overlap */
+++ mov eax, edi
+++ sub eax, esi
+++ cmp ecx, eax
+++ jbe DoMove
+++
+++ /* Set direction flag for backward move */
+++ std
+++
+++ /* Copy byte-by-byte the non-overlapping distance */
+++ add esi, ecx
+++ add edi, ecx
+++ dec esi
+++ dec edi
+++
+++ /* Do the move, reset flag and return */
+++ rep movsb
+++ cld
+++ jmp DoneMove
+++.endfunc
+++
+++.func @RtlPrefetchMemoryNonTemporal@8, @RtlPrefetchMemoryNonTemporal@8
+++@RtlPrefetchMemoryNonTemporal@8:
+++
+++ /*
+++ * Overwritten by ntoskrnl/ke/i386/kernel.c if SSE is supported
+++ * (see Ki386SetProcessorFeatures())
+++ */
+++ ret
+++
+++ /* Get granularity */
+++ mov eax, [_Ke386CacheAlignment]
+++
+++FetchLine:
+++
+++ /* Prefetch this line */
+++ prefetchnta byte ptr [ecx]
+++
+++ /* Update address and count */
+++ add ecx, eax
+++ sub edx, eax
+++
+++ /* Keep looping for the next line, or return if done */
+++ ja FetchLine
+++ ret
+++.endfunc
+++
+++/* FIXME: HACK */
+++_Ke386CacheAlignment:
+++ .long 0x40
PWSTR ValueName;
UNICODE_STRING EnvValue;
UNICODE_STRING EnvExpandedValue;
+++#ifdef DEBUG
+ ULONG DataSize = 0;
+++#endif
PAGED_CODE_RTL();
#else
#define ExAcquireResourceLock(l, i) KeAcquireSpinLock(l, i);
#define ExReleaseResourceLock(l, i) KeReleaseSpinLock(l, i);
++#endif /* CONFIG_SMP */
++#elif defined(_M_PPC) /* _M_IX86 */
++/* XXX arty fixme */
++#define ExAcquireResourceLock(l,i) KeAcquireSpinLock(l,i);
++#define ExReleaseResourceLock(l,i) KeReleaseSpinLock(l,i);
#endif
+ #define ExAcquireRundownProtection _ExAcquireRundownProtection
+ #define ExReleaseRundownProtection _ExReleaseRundownProtection
+ #define ExInitializeRundownProtection _ExInitializeRundownProtection
+ #define ExWaitForRundownProtectionRelease _ExWaitForRundownProtectionRelease
+ #define ExRundownCompleted _ExRundownCompleted
+
/* INITIALIZATION FUNCTIONS *************************************************/
VOID
extern ULONG KeI386NpxPresent;
extern ULONG KeI386XMMIPresent;
extern ULONG KeI386FxsrPresent;
+ extern ULONG KiMXCsrMask;
extern ULONG KeI386CpuType;
extern ULONG KeI386CpuStep;
++#endif
extern ULONG KeProcessorArchitecture;
extern ULONG KeProcessorLevel;
extern ULONG KeProcessorRevision;
VOID
);
++#ifdef _M_IX86
++#define KeHaltProcessor Ke386HaltProcessor
++#define KeEnableInterrupts Ke386EnableInterrupts
++#define KeDisableInterrupts Ke386DisableInterrupts
++#elif defined(_M_PPC)
++#define KeHaltProcessor KePPCHaltProcessor
++#define KeEnableInterrupts KePPCEnableInterrupts
++#define KeDisableInterrupts KePPCDisableInterrupts
++#endif
++
+ VOID
+ FASTCALL
+ KiInsertQueueApc(
+ IN PKAPC Apc,
+ IN KPRIORITY PriorityBoost
+ );
+
+ NTSTATUS
+ NTAPI
+ KiCallUserMode(
+ IN PVOID *OutputBuffer,
+ IN PULONG OutputLength
+ );
+
+ PULONG
+ NTAPI
+ KiGetUserModeStackAddress(
+ VOID
+ );
+
+ ULONG_PTR
+ NTAPI
+ Ki386EnableGlobalPage(IN volatile ULONG_PTR Context);
+
+ VOID
+ NTAPI
+ KiInitializePAT(VOID);
+
+ VOID
+ NTAPI
+ KiInitializeMTRR(IN BOOLEAN FinalCpu);
+
+ VOID
+ NTAPI
+ KiAmdK6InitializeMTRR(VOID);
+
+ VOID
+ NTAPI
+ KiRestoreFastSyscallReturnState(VOID);
+
+ ULONG_PTR
+ NTAPI
+ Ki386EnableDE(IN ULONG_PTR Context);
+
+ ULONG_PTR
+ NTAPI
+ Ki386EnableFxsr(IN ULONG_PTR Context);
+
+ ULONG_PTR
+ NTAPI
+ Ki386EnableXMMIExceptions(IN ULONG_PTR Context);
+
+ VOID
+ NTAPI
+ KiInitMachineDependent(VOID);
+
+ VOID
+ NTAPI
+ KiI386PentiumLockErrataFixup(VOID);
+
+ VOID
+ WRMSR(
+ IN ULONG Register,
+ IN LONGLONG Value
+ );
+
#include "ke_x.h"
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_KE_H */
} \\r
}\r
\r
+++#undef FORCEINLINE\r
+++#define FORCEINLINE\r
+++\r
//\r
// Recalculates the due time\r
//\r
}\r
\r
//\r
- // Rules for checking alertability:\r
- // - For Alertable waits ONLY:\r
- // * We don't wait and return STATUS_ALERTED if the thread is alerted\r
- // in EITHER the specified wait mode OR in Kernel Mode.\r
- // - For BOTH Alertable AND Non-Alertable waits:\r
- // * We don't want and return STATUS_USER_APC if the User Mode APC list\r
- // is not empty AND the wait mode is User Mode.\r
+ // Checks if a wait in progress should be interrupted by APCs or an alertable\r
+ // state.\r
//\r
- #define KiCheckAlertability() \\r
- { \\r
- if (Alertable) \\r
- { \\r
- if (CurrentThread->Alerted[(int)WaitMode]) \\r
- { \\r
- CurrentThread->Alerted[(int)WaitMode] = FALSE; \\r
- WaitStatus = STATUS_ALERTED; \\r
- break; \\r
- } \\r
- else if ((WaitMode != KernelMode) && \\r
- (!IsListEmpty(&CurrentThread-> \\r
- ApcState.ApcListHead[UserMode]))) \\r
- { \\r
- CurrentThread->ApcState.UserApcPending = TRUE; \\r
- WaitStatus = STATUS_USER_APC; \\r
- break; \\r
- } \\r
- else if (CurrentThread->Alerted[KernelMode]) \\r
- { \\r
- CurrentThread->Alerted[KernelMode] = FALSE; \\r
- WaitStatus = STATUS_ALERTED; \\r
- break; \\r
- } \\r
- } \\r
- else if ((WaitMode != KernelMode) && \\r
- (CurrentThread->ApcState.UserApcPending)) \\r
- { \\r
- WaitStatus = STATUS_USER_APC; \\r
- break; \\r
- } \\r
+ FORCEINLINE\r
+ NTSTATUS\r
+ KiCheckAlertability(IN PKTHREAD Thread,\r
+ IN BOOLEAN Alertable,\r
+ IN KPROCESSOR_MODE WaitMode)\r
+ {\r
+ /* Check if the wait is alertable */\r
+ if (Alertable)\r
+ {\r
+ /* It is, first check if the thread is alerted in this mode */\r
+ if (Thread->Alerted[WaitMode])\r
+ {\r
+ /* It is, so bail out of the wait */\r
+ Thread->Alerted[WaitMode] = FALSE;\r
+ return STATUS_ALERTED;\r
+ }\r
+ else if ((WaitMode != KernelMode) &&\r
+ (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))\r
+ {\r
+ /* It's isn't, but this is a user wait with queued user APCs */\r
+ Thread->ApcState.UserApcPending = TRUE;\r
+ return STATUS_USER_APC;\r
+ }\r
+ else if (Thread->Alerted[KernelMode])\r
+ {\r
+ /* It isn't that either, but we're alered in kernel mode */\r
+ Thread->Alerted[KernelMode] = FALSE;\r
+ return STATUS_ALERTED;\r
+ }\r
+ }\r
+ else if ((WaitMode != KernelMode) && (Thread->ApcState.UserApcPending))\r
+ {\r
+ /* Not alertable, but this is a user wait with pending user APCs */\r
+ return STATUS_USER_APC;\r
+ }\r
+ \r
+ /* Otherwise, we're fine */\r
+ return STATUS_WAIT_0;\r
+ }\r
+ \r
+ FORCEINLINE\r
+ BOOLEAN\r
+ KxDelayThreadWait(IN PKTHREAD Thread,\r
+ IN BOOLEAN Alertable,\r
+ IN KPROCESSOR_MODE WaitMode)\r
+ {\r
+ BOOLEAN Swappable;\r
+ PKWAIT_BLOCK TimerBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];\r
+ \r
+ /* Setup the Wait Block */\r
+ Thread->WaitBlockList = TimerBlock;\r
+ TimerBlock->NextWaitBlock = TimerBlock;\r
+ \r
+ /* Link the timer to this Wait Block */\r
+ Thread->Timer.Header.WaitListHead.Flink = &TimerBlock->WaitListEntry;\r
+ Thread->Timer.Header.WaitListHead.Blink = &TimerBlock->WaitListEntry;\r
+ \r
+ /* Clear wait status */\r
+ Thread->WaitStatus = STATUS_WAIT_0;\r
+ \r
+ /* Setup wait fields */\r
+ Thread->Alertable = Alertable;\r
+ Thread->WaitReason = DelayExecution;\r
+ Thread->WaitMode = WaitMode;\r
+ \r
+ /* Check if we can swap the thread's stack */\r
+ Thread->WaitListEntry.Flink = NULL;\r
+ Swappable = KiCheckThreadStackSwap(Thread, WaitMode);\r
+ \r
+ /* Set the wait time */\r
+ Thread->WaitTime = ((PLARGE_INTEGER)&KeTickCount)->LowPart;\r
+ return Swappable;\r
}\r
+ \r
+ FORCEINLINE\r
+ BOOLEAN\r
+ KxMultiThreadWait(IN PKTHREAD Thread,\r
+ IN PKWAIT_BLOCK WaitBlock,\r
+ IN BOOLEAN Alertable,\r
+ IN KWAIT_REASON WaitReason,\r
+ IN KPROCESSOR_MODE WaitMode)\r
+ {\r
+ BOOLEAN Swappable;\r
+ PKTIMER ThreadTimer = &Thread->Timer;\r
+ \r
+ /* Set default wait status */\r
+ Thread->WaitStatus = STATUS_WAIT_0;\r
+ \r
+ /* Link wait block array to the thread */\r
+ Thread->WaitBlockList = WaitBlock;\r
+ \r
+ /* Initialize the timer list */\r
+ InitializeListHead(&ThreadTimer->Header.WaitListHead);\r
+ \r
+ /* Set wait settings */\r
+ Thread->Alertable = Alertable;\r
+ Thread->WaitMode = WaitMode;\r
+ Thread->WaitReason = WaitReason;\r
+ \r
+ /* Check if we can swap the thread's stack */\r
+ Thread->WaitListEntry.Flink = NULL;\r
+ Swappable = KiCheckThreadStackSwap(Thread, WaitMode);\r
+ \r
+ /* Set the wait time */\r
+ Thread->WaitTime = ((PLARGE_INTEGER)&KeTickCount)->LowPart;\r
+ return Swappable;\r
+ }\r
+ \r
+ FORCEINLINE\r
+ BOOLEAN\r
+ KxSingleThreadWait(IN PKTHREAD Thread,\r
+ IN PKWAIT_BLOCK WaitBlock,\r
+ IN PVOID Object,\r
+ IN PLARGE_INTEGER Timeout,\r
+ IN BOOLEAN Alertable,\r
+ IN KWAIT_REASON WaitReason,\r
+ IN KPROCESSOR_MODE WaitMode)\r
+ {\r
+ BOOLEAN Swappable;\r
+ PKWAIT_BLOCK TimerBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];\r
+ \r
+ /* Setup the Wait Block */\r
+ Thread->WaitBlockList = WaitBlock;\r
+ WaitBlock->WaitKey = STATUS_WAIT_0;\r
+ WaitBlock->Object = Object;\r
+ WaitBlock->WaitType = WaitAny;\r
+ \r
+ /* Clear wait status */\r
+ Thread->WaitStatus = STATUS_WAIT_0;\r
+ \r
+ /* Check if we have a timer */\r
+ if (Timeout)\r
+ {\r
+ /* Pointer to timer block */\r
+ WaitBlock->NextWaitBlock = TimerBlock;\r
+ TimerBlock->NextWaitBlock = WaitBlock;\r
+ \r
+ /* Link the timer to this Wait Block */\r
+ Thread->Timer.Header.WaitListHead.Flink = &TimerBlock->WaitListEntry;\r
+ Thread->Timer.Header.WaitListHead.Blink = &TimerBlock->WaitListEntry;\r
+ }\r
+ else\r
+ {\r
+ /* No timer block, just ourselves */\r
+ WaitBlock->NextWaitBlock = WaitBlock;\r
+ }\r
+ \r
+ /* Setup wait fields */\r
+ Thread->Alertable = Alertable;\r
+ Thread->WaitReason = WaitReason;\r
+ Thread->WaitMode = WaitMode;\r
+ \r
+ /* Check if we can swap the thread's stack */\r
+ Thread->WaitListEntry.Flink = NULL;\r
+ Swappable = KiCheckThreadStackSwap(Thread, WaitMode);\r
+ \r
+ /* Set the wait time */\r
+ Thread->WaitTime = ((PLARGE_INTEGER)&KeTickCount)->LowPart;\r
+ return Swappable;\r
+ }\r
+ \r
+ //\r
+ // Unwaits a Thread\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KxUnwaitThread(IN DISPATCHER_HEADER *Object,\r
+ IN KPRIORITY Increment)\r
+ {\r
+ PLIST_ENTRY WaitEntry, WaitList;\r
+ PKWAIT_BLOCK CurrentWaitBlock;\r
+ PKTHREAD WaitThread;\r
+ ULONG WaitKey;\r
+ \r
+ /* Loop the Wait Entries */\r
+ WaitList = &Object->WaitListHead;\r
+ WaitEntry = WaitList->Flink;\r
+ do\r
+ {\r
+ /* Get the current wait block */\r
+ CurrentWaitBlock = CONTAINING_RECORD(WaitEntry,\r
+ KWAIT_BLOCK,\r
+ WaitListEntry);\r
+ \r
+ /* Get the waiting thread */\r
+ WaitThread = CurrentWaitBlock->Thread;\r
+ \r
+ /* Check the current Wait Mode */\r
+ if (CurrentWaitBlock->WaitType == WaitAny)\r
+ {\r
+ /* Use the actual wait key */\r
+ WaitKey = CurrentWaitBlock->WaitKey;\r
+ }\r
+ else\r
+ {\r
+ /* Otherwise, use STATUS_KERNEL_APC */\r
+ WaitKey = STATUS_KERNEL_APC;\r
+ }\r
+ \r
+ /* Unwait the thread */\r
+ KiUnwaitThread(WaitThread, WaitKey, Increment);\r
+ \r
+ /* Next entry */\r
+ WaitEntry = WaitList->Flink;\r
+ } while (WaitEntry != WaitList);\r
+ }\r
+ \r
+ //\r
+ // Unwaits a Thread waiting on an event\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KxUnwaitThreadForEvent(IN PKEVENT Event,\r
+ IN KPRIORITY Increment)\r
+ {\r
+ PLIST_ENTRY WaitEntry, WaitList;\r
+ PKWAIT_BLOCK CurrentWaitBlock;\r
+ PKTHREAD WaitThread;\r
+ \r
+ /* Loop the Wait Entries */\r
+ WaitList = &Event->Header.WaitListHead;\r
+ WaitEntry = WaitList->Flink;\r
+ do\r
+ {\r
+ /* Get the current wait block */\r
+ CurrentWaitBlock = CONTAINING_RECORD(WaitEntry,\r
+ KWAIT_BLOCK,\r
+ WaitListEntry);\r
+ \r
+ /* Get the waiting thread */\r
+ WaitThread = CurrentWaitBlock->Thread;\r
+ \r
+ /* Check the current Wait Mode */\r
+ if (CurrentWaitBlock->WaitType == WaitAny)\r
+ {\r
+ /* Un-signal it */\r
+ Event->Header.SignalState = 0;\r
+ \r
+ /* Un-signal the event and unwait the thread */\r
+ KiUnwaitThread(WaitThread, CurrentWaitBlock->WaitKey, Increment);\r
+ break;\r
+ }\r
+ else\r
+ {\r
+ /* Unwait the thread with STATUS_KERNEL_APC */\r
+ KiUnwaitThread(WaitThread, STATUS_KERNEL_APC, Increment);\r
+ }\r
+ \r
+ /* Next entry */\r
+ WaitEntry = WaitList->Flink;\r
+ } while (WaitEntry != WaitList);\r
+ }\r
+ \r
+ #ifndef _CONFIG_SMP\r
+ //\r
+ // Spinlock Acquire at IRQL >= DISPATCH_LEVEL\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)\r
+ {\r
+ /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */\r
+ UNREFERENCED_PARAMETER(SpinLock);\r
+ }\r
+ \r
+ //\r
+ // Spinlock Release at IRQL >= DISPATCH_LEVEL\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)\r
+ {\r
+ /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */\r
+ UNREFERENCED_PARAMETER(SpinLock);\r
+ }\r
+ \r
+ //\r
+ // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+ //\r
+ VOID\r
+ FORCEINLINE\r
+ KiAcquireDispatcherObject(IN DISPATCHER_HEADER* Object)\r
+ {\r
+ UNREFERENCED_PARAMETER(Object);\r
+ }\r
+ \r
+ //\r
+ // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+ //\r
+ VOID\r
+ FORCEINLINE\r
+ KiReleaseDispatcherObject(IN DISPATCHER_HEADER* Object)\r
+ {\r
+ UNREFERENCED_PARAMETER(Object);\r
+ }\r
+ \r
+ KIRQL\r
+ FORCEINLINE\r
+ KiAcquireDispatcherLock(VOID)\r
+ {\r
+ /* Raise to DPC level */\r
+ return KeRaiseIrqlToDpcLevel();\r
+ }\r
+ \r
+ VOID\r
+ FORCEINLINE\r
+ KiReleaseDispatcherLock(IN KIRQL OldIrql)\r
+ {\r
+ /* Just exit the dispatcher */\r
+ KiExitDispatcher(OldIrql);\r
+ }\r
+ \r
+ VOID\r
+ FORCEINLINE\r
+ KiAcquireDispatcherLockAtDpcLevel(VOID)\r
+ {\r
+ /* This is a no-op at DPC Level for UP systems */\r
+ return;\r
+ }\r
+ \r
+ VOID\r
+ FORCEINLINE\r
+ KiReleaseDispatcherLockFromDpcLevel(VOID)\r
+ {\r
+ /* This is a no-op at DPC Level for UP systems */\r
+ return;\r
+ }\r
+ \r
+ //\r
+ // This routine makes the thread deferred ready on the boot CPU.\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiInsertDeferredReadyList(IN PKTHREAD Thread)\r
+ {\r
+ /* Set the thread to deferred state and boot CPU */\r
+ Thread->State = DeferredReady;\r
+ Thread->DeferredProcessor = 0;\r
+ \r
+ /* Make the thread ready immediately */\r
+ KiDeferredReadyThread(Thread);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiRescheduleThread(IN BOOLEAN NewThread,\r
+ IN ULONG Cpu)\r
+ {\r
+ /* This is meaningless on UP systems */\r
+ UNREFERENCED_PARAMETER(NewThread);\r
+ UNREFERENCED_PARAMETER(Cpu);\r
+ }\r
+ \r
+ //\r
+ // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiSetThreadSwapBusy(IN PKTHREAD Thread)\r
+ {\r
+ UNREFERENCED_PARAMETER(Thread);\r
+ }\r
+ \r
+ //\r
+ // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiAcquirePrcbLock(IN PKPRCB Prcb)\r
+ {\r
+ UNREFERENCED_PARAMETER(Prcb);\r
+ }\r
+ \r
+ //\r
+ // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiReleasePrcbLock(IN PKPRCB Prcb)\r
+ {\r
+ UNREFERENCED_PARAMETER(Prcb);\r
+ }\r
+ \r
+ //\r
+ // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiAcquireThreadLock(IN PKTHREAD Thread)\r
+ {\r
+ UNREFERENCED_PARAMETER(Thread);\r
+ }\r
+ \r
+ //\r
+ // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiReleaseThreadLock(IN PKTHREAD Thread)\r
+ {\r
+ UNREFERENCED_PARAMETER(Thread);\r
+ }\r
+ \r
+ //\r
+ // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+ //\r
+ FORCEINLINE\r
+ BOOLEAN\r
+ KiTryThreadLock(IN PKTHREAD Thread)\r
+ {\r
+ UNREFERENCED_PARAMETER(Thread);\r
+ return FALSE;\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiCheckDeferredReadyList(IN PKPRCB Prcb)\r
+ {\r
+ /* There are no deferred ready lists on UP systems */\r
+ UNREFERENCED_PARAMETER(Prcb);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiRundownThread(IN PKTHREAD Thread)\r
+ {\r
+ /* Check if this is the NPX Thread */\r
+ if (KeGetCurrentPrcb()->NpxThread == Thread)\r
+ {\r
+ /* Clear it */\r
+ KeGetCurrentPrcb()->NpxThread = NULL;\r
+++#ifdef _M_IX86\r
+ #ifdef __GNUC__\r
+ __asm__("fninit\n\t");\r
+ #else\r
+ __asm fninit;\r
+++#endif\r
+ #endif\r
+ }\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiRequestApcInterrupt(IN BOOLEAN NeedApc,\r
+ IN UCHAR Processor)\r
+ {\r
+ /* We deliver instantly on UP */\r
+ UNREFERENCED_PARAMETER(NeedApc);\r
+ UNREFERENCED_PARAMETER(Processor);\r
+ }\r
+ \r
+ #else\r
+ \r
+ //\r
+ // Spinlock Acquisition at IRQL >= DISPATCH_LEVEL\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)\r
+ {\r
+ for (;;)\r
+ {\r
+ /* Try to acquire it */\r
+ if (InterlockedBitTestAndSet((PLONG)SpinLock, 0))\r
+ {\r
+ /* Value changed... wait until it's locked */\r
+ while (*(volatile KSPIN_LOCK *)SpinLock == 1)\r
+ {\r
+ #ifdef DBG\r
+ /* On debug builds, we use a much slower but useful routine */\r
+ Kii386SpinOnSpinLock(SpinLock, 5);\r
+ #else\r
+ /* Otherwise, just yield and keep looping */\r
+ YieldProcessor();\r
+ #endif\r
+ }\r
+ }\r
+ else\r
+ {\r
+ #ifdef DBG\r
+ /* On debug builds, we OR in the KTHREAD */\r
+ *SpinLock = KeGetCurrentThread() | 1;\r
+ #endif\r
+ /* All is well, break out */\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Spinlock Release at IRQL >= DISPATCH_LEVEL\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)\r
+ {\r
+ #ifdef DBG\r
+ /* Make sure that the threads match */\r
+ if ((KeGetCurrentThread() | 1) != *SpinLock)\r
+ {\r
+ /* They don't, bugcheck */\r
+ KeBugCheckEx(SPIN_LOCK_NOT_OWNED, SpinLock, 0, 0, 0);\r
+ }\r
+ #endif\r
+ /* Clear the lock */\r
+ InterlockedAnd(SpinLock, 0);\r
+ }\r
+ \r
+ KIRQL\r
+ FORCEINLINE\r
+ KiAcquireDispatcherObject(IN DISPATCHER_HEADER* Object)\r
+ {\r
+ LONG OldValue, NewValue;\r
+ \r
+ /* Make sure we're at a safe level to touch the lock */\r
+ ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);\r
+ \r
+ /* Start acquire loop */\r
+ do\r
+ {\r
+ /* Loop until the other CPU releases it */\r
+ while ((UCHAR)Object->Lock & KOBJECT_LOCK_BIT)\r
+ {\r
+ /* Let the CPU know that this is a loop */\r
+ YieldProcessor();\r
+ };\r
+ \r
+ /* Try acquiring the lock now */\r
+ NewValue = InterlockedCompareExchange(&Object->Lock,\r
+ OldValue | KOBJECT_LOCK_BIT,\r
+ OldValue);\r
+ } while (NewValue != OldValue);\r
+ }\r
+ \r
+ KIRQL\r
+ FORCEINLINE\r
+ KiReleaseDispatcherObject(IN DISPATCHER_HEADER* Object)\r
+ {\r
+ /* Make sure we're at a safe level to touch the lock */\r
+ ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);\r
+ \r
+ /* Release it */\r
+ InterlockedAnd(&Object->Lock, ~KOBJECT_LOCK_BIT);\r
+ }\r
+ \r
+ KIRQL\r
+ FORCEINLINE\r
+ KiAcquireDispatcherLock(VOID)\r
+ {\r
+ /* Raise to synchronization level and acquire the dispatcher lock */\r
+ return KeAcquireQueuedSpinLockRaiseToSynch(LockQueueDispatcherLock);\r
+ }\r
+ \r
+ VOID\r
+ FORCEINLINE\r
+ KiReleaseDispatcherLock(IN KIRQL OldIrql)\r
+ {\r
+ /* First release the lock */\r
+ KeReleaseQueuedSpinLockFromDpcLevel(&KeGetCurrentPrcb()->\r
+ LockQueue[LockQueueDispatcherLock]);\r
+ \r
+ /* Then exit the dispatcher */\r
+ KiExitDispatcher(OldIrql);\r
+ }\r
+ \r
+ //\r
+ // This routine inserts a thread into the deferred ready list of the given CPU\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiInsertDeferredReadyList(IN PKTHREAD Thread)\r
+ {\r
+ PKPRCB Prcb = KeGetCurrentPrcb();\r
+ \r
+ /* Set the thread to deferred state and CPU */\r
+ Thread->State = DeferredReady;\r
+ Thread->DeferredProcessor = Prcb->Number;\r
+ \r
+ /* Add it on the list */\r
+ PushEntryList(&Prcb->DeferredReadyListHead, &Thread->SwapListEntry);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiRescheduleThread(IN BOOLEAN NewThread,\r
+ IN ULONG Cpu)\r
+ {\r
+ /* Check if a new thread needs to be scheduled on a different CPU */\r
+ if ((NewThread) && !(KeGetPcr()->Number == Cpu))\r
+ {\r
+ /* Send an IPI to request delivery */\r
+ KiIpiSendRequest(AFFINITY_MASK(Cpu), IPI_DPC);\r
+ }\r
+ }\r
+ \r
+ //\r
+ // This routine sets the current thread in a swap busy state, which ensure that\r
+ // nobody else tries to swap it concurrently.\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiSetThreadSwapBusy(IN PKTHREAD Thread)\r
+ {\r
+ /* Make sure nobody already set it */\r
+ ASSERT(Thread->SwapBusy == FALSE);\r
+ \r
+ /* Set it ourselves */\r
+ Thread->SwapBusy = TRUE;\r
+ }\r
+ \r
+ //\r
+ // This routine acquires the PRCB lock so that only one caller can touch\r
+ // volatile PRCB data.\r
+ //\r
+ // Since this is a simple optimized spin-lock, it must be be only acquired\r
+ // at dispatcher level or higher!\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiAcquirePrcbLock(IN PKPRCB Prcb)\r
+ {\r
+ /* Make sure we're at a safe level to touch the PRCB lock */\r
+ ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);\r
+ \r
+ /* Start acquire loop */\r
+ for (;;)\r
+ {\r
+ /* Acquire the lock and break out if we acquired it first */\r
+ if (!InterlockedExchange(&Prcb->PrcbLock, 1)) break;\r
+ \r
+ /* Loop until the other CPU releases it */\r
+ do\r
+ {\r
+ /* Let the CPU know that this is a loop */\r
+ YieldProcessor();\r
+ } while (Prcb->PrcbLock);\r
+ }\r
+ }\r
+ \r
+ //\r
+ // This routine releases the PRCB lock so that other callers can touch\r
+ // volatile PRCB data.\r
+ //\r
+ // Since this is a simple optimized spin-lock, it must be be only acquired\r
+ // at dispatcher level or higher!\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiReleasePrcbLock(IN PKPRCB Prcb)\r
+ {\r
+ /* Make sure it's acquired! */\r
+ ASSERT(Prcb->PrcbLock != 0);\r
+ \r
+ /* Release it */\r
+ InterlockedAnd(&Prcb->PrcbLock, 0);\r
+ }\r
+ \r
+ //\r
+ // This routine acquires the thread lock so that only one caller can touch\r
+ // volatile thread data.\r
+ //\r
+ // Since this is a simple optimized spin-lock, it must be be only acquired\r
+ // at dispatcher level or higher!\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiAcquireThreadLock(IN PKTHREAD Thread)\r
+ {\r
+ /* Make sure we're at a safe level to touch the thread lock */\r
+ ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);\r
+ \r
+ /* Start acquire loop */\r
+ for (;;)\r
+ {\r
+ /* Acquire the lock and break out if we acquired it first */\r
+ if (!InterlockedExchange(&Thread->ThreadLock, 1)) break;\r
+ \r
+ /* Loop until the other CPU releases it */\r
+ do\r
+ {\r
+ /* Let the CPU know that this is a loop */\r
+ YieldProcessor();\r
+ } while (Thread->ThreadLock);\r
+ }\r
+ }\r
+ \r
+ //\r
+ // This routine releases the thread lock so that other callers can touch\r
+ // volatile thread data.\r
+ //\r
+ // Since this is a simple optimized spin-lock, it must be be only acquired\r
+ // at dispatcher level or higher!\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KiReleaseThreadLock(IN PKTHREAD Thread)\r
+ {\r
+ /* Release it */\r
+ InterlockedAnd(&Thread->ThreadLock, 0);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ BOOLEAN\r
+ KiTryThreadLock(IN PKTHREAD Thread)\r
+ {\r
+ LONG Value;\r
+ \r
+ /* If the lock isn't acquired, return false */\r
+ if (!Thread->ThreadLock) return FALSE;\r
+ \r
+ /* Otherwise, try to acquire it and check the result */\r
+ Value = 1;\r
+ Value = InterlockedExchange(&Thread->ThreadLock, &Value);\r
+ \r
+ /* Return the lock state */\r
+ return (Value == TRUE);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiCheckDeferredReadyList(IN PKPRCB Prcb)\r
+ {\r
+ /* Scan the deferred ready lists if required */\r
+ if (Prcb->DeferredReadyListHead.Next) KiProcessDeferredReadyList(Prcb);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiRequestApcInterrupt(IN BOOLEAN NeedApc,\r
+ IN UCHAR Processor)\r
+ {\r
+ /* Check if we need to request APC delivery */\r
+ if (NeedApc)\r
+ {\r
+ /* Check if it's on another CPU */\r
+ if (KeGetPcr()->Number != Cpu)\r
+ {\r
+ /* Send an IPI to request delivery */\r
+ KiIpiSendRequest(AFFINITY_MASK(Cpu), IPI_DPC);\r
+ }\r
+ else\r
+ {\r
+ /* Request a software interrupt */\r
+ HalRequestSoftwareInterrupt(APC_LEVEL);\r
+ }\r
+ }\r
+ }\r
+ \r
+ #endif\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiAcquireApcLock(IN PKTHREAD Thread,\r
+ IN PKLOCK_QUEUE_HANDLE Handle)\r
+ {\r
+ /* Acquire the lock and raise to synchronization level */\r
+ KeAcquireInStackQueuedSpinLockRaiseToSynch(&Thread->ApcQueueLock, Handle);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiAcquireApcLockAtDpcLevel(IN PKTHREAD Thread,\r
+ IN PKLOCK_QUEUE_HANDLE Handle)\r
+ {\r
+ /* Acquire the lock */\r
+ KeAcquireInStackQueuedSpinLockAtDpcLevel(&Thread->ApcQueueLock, Handle);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiAcquireApcLockAtApcLevel(IN PKTHREAD Thread,\r
+ IN PKLOCK_QUEUE_HANDLE Handle)\r
+ {\r
+ /* Acquire the lock */\r
+ KeAcquireInStackQueuedSpinLock(&Thread->ApcQueueLock, Handle);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiReleaseApcLock(IN PKLOCK_QUEUE_HANDLE Handle)\r
+ {\r
+ /* Release the lock */\r
+ KeReleaseInStackQueuedSpinLock(Handle);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiReleaseApcLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE Handle)\r
+ {\r
+ /* Release the lock */\r
+ KeReleaseInStackQueuedSpinLockFromDpcLevel(Handle);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiAcquireProcessLock(IN PKPROCESS Process,\r
+ IN PKLOCK_QUEUE_HANDLE Handle)\r
+ {\r
+ /* Acquire the lock and raise to synchronization level */\r
+ KeAcquireInStackQueuedSpinLockRaiseToSynch(&Process->ProcessLock, Handle);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiReleaseProcessLock(IN PKLOCK_QUEUE_HANDLE Handle)\r
+ {\r
+ /* Release the lock */\r
+ KeReleaseInStackQueuedSpinLock(Handle);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiReleaseProcessLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE Handle)\r
+ {\r
+ /* Release the lock */\r
+ KeReleaseInStackQueuedSpinLockFromDpcLevel(Handle);\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiAcquireDeviceQueueLock(IN PKDEVICE_QUEUE DeviceQueue,\r
+ IN PKLOCK_QUEUE_HANDLE DeviceLock)\r
+ {\r
+ /* Check if we were called from a threaded DPC */\r
+ if (KeGetCurrentPrcb()->DpcThreadActive)\r
+ {\r
+ /* Lock the Queue, we're not at DPC level */\r
+ KeAcquireInStackQueuedSpinLock(&DeviceQueue->Lock, DeviceLock);\r
+ }\r
+ else\r
+ {\r
+ /* We must be at DPC level, acquire the lock safely */\r
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);\r
+ KeAcquireInStackQueuedSpinLockAtDpcLevel(&DeviceQueue->Lock,\r
+ DeviceLock);\r
+ }\r
+ }\r
+ \r
+ FORCEINLINE\r
+ VOID\r
+ KiReleaseDeviceQueueLock(IN PKLOCK_QUEUE_HANDLE DeviceLock)\r
+ {\r
+ /* Check if we were called from a threaded DPC */\r
+ if (KeGetCurrentPrcb()->DpcThreadActive)\r
+ {\r
+ /* Unlock the Queue, we're not at DPC level */\r
+ KeReleaseInStackQueuedSpinLock(DeviceLock);\r
+ }\r
+ else\r
+ {\r
+ /* We must be at DPC level, release the lock safely */\r
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);\r
+ KeReleaseInStackQueuedSpinLockFromDpcLevel(DeviceLock);\r
+ }\r
+ }\r
+ \r
+ //\r
+ // This routine queues a thread that is ready on the PRCB's ready lists.\r
+ // If this thread cannot currently run on this CPU, then the thread is\r
+ // added to the deferred ready list instead.\r
+ //\r
+ // This routine must be entered with the PRCB lock held and it will exit\r
+ // with the PRCB lock released!\r
+ //\r
+ FORCEINLINE\r
+ VOID\r
+ KxQueueReadyThread(IN PKTHREAD Thread,\r
+ IN PKPRCB Prcb)\r
+ {\r
+ BOOLEAN Preempted;\r
+ KPRIORITY Priority;\r
+ \r
+ /* Sanity checks */\r
+ ASSERT(Prcb == KeGetCurrentPrcb());\r
+ ASSERT(Thread->State == Running);\r
+ ASSERT(Thread->NextProcessor == Prcb->Number);\r
+ \r
+ /* Check if this thread is allowed to run in this CPU */\r
+ #ifdef _CONFIG_SMP\r
+ if ((Thread->Affinity) & (Prcb->SetMember))\r
+ #else\r
+ if (TRUE)\r
+ #endif\r
+ {\r
+ /* Set thread ready for execution */\r
+ Thread->State = Ready;\r
+ \r
+ /* Save current priority and if someone had pre-empted it */\r
+ Priority = Thread->Priority;\r
+ Preempted = Thread->Preempted;\r
+ \r
+ /* We're not pre-empting now, and set the wait time */\r
+ Thread->Preempted = FALSE;\r
+ Thread->WaitTime = KeTickCount.LowPart;\r
+ \r
+ /* Sanity check */\r
+ ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));\r
+ \r
+ /* Insert this thread in the appropriate order */\r
+ Preempted ? InsertHeadList(&Prcb->DispatcherReadyListHead[Priority],\r
+ &Thread->WaitListEntry) :\r
+ InsertTailList(&Prcb->DispatcherReadyListHead[Priority],\r
+ &Thread->WaitListEntry);\r
+ \r
+ /* Update the ready summary */\r
+ Prcb->ReadySummary |= PRIORITY_MASK(Priority);\r
+ \r
+ /* Sanity check */\r
+ ASSERT(Priority == Thread->Priority);\r
+ \r
+ /* Release the PRCB lock */\r
+ KiReleasePrcbLock(Prcb);\r
+ }\r
+ else\r
+ {\r
+ /* Otherwise, prepare this thread to be deferred */\r
+ Thread->State = DeferredReady;\r
+ Thread->DeferredProcessor = Prcb->Number;\r
+ \r
+ /* Release the lock and defer scheduling */\r
+ KiReleasePrcbLock(Prcb);\r
+ KiDeferredReadyThread(Thread);\r
+ }\r
+ }\r
+ \r
+ //\r
+ // This routine scans for an appropriate ready thread to select at the\r
+ // given priority and for the given CPU.\r
+ //\r
+ FORCEINLINE\r
+ PKTHREAD\r
+ KiSelectReadyThread(IN KPRIORITY Priority,\r
+ IN PKPRCB Prcb)\r
+ {\r
+ LONG PriorityMask, PrioritySet, HighPriority;\r
+ PLIST_ENTRY ListEntry;\r
+ PKTHREAD Thread;\r
+ \r
+ /* Save the current mask and get the priority set for the CPU */\r
+ PriorityMask = Priority;\r
+ PrioritySet = Prcb->ReadySummary >> (UCHAR)Priority;\r
+ if (!PrioritySet) return NULL;\r
+ \r
+ /* Get the highest priority possible */\r
+ BitScanReverse((PULONG)&HighPriority, PrioritySet);\r
+ ASSERT((PrioritySet & PRIORITY_MASK(HighPriority)) != 0);\r
+ HighPriority += PriorityMask;\r
+ \r
+ /* Make sure the list isn't at highest priority */\r
+ ASSERT(IsListEmpty(&Prcb->DispatcherReadyListHead[HighPriority]) == FALSE);\r
+ \r
+ /* Get the first thread on the list */\r
+ ListEntry = &Prcb->DispatcherReadyListHead[HighPriority];\r
+ Thread = CONTAINING_RECORD(ListEntry, KTHREAD, WaitListEntry);\r
+ \r
+ /* Make sure this thread is here for a reason */\r
+ ASSERT(HighPriority == Thread->Priority);\r
+ ASSERT(Thread->Affinity & AFFINITY_MASK(Prcb->Number));\r
+ ASSERT(Thread->NextProcessor == Prcb->Number);\r
+ \r
+ /* Remove it from the list */\r
+ RemoveEntryList(&Thread->WaitListEntry);\r
+ if (IsListEmpty(&Thread->WaitListEntry))\r
+ {\r
+ /* The list is empty now, reset the ready summary */\r
+ Prcb->ReadySummary ^= PRIORITY_MASK(HighPriority);\r
+ }\r
+ \r
+ /* Sanity check and return the thread */\r
+ ASSERT((Thread == NULL) ||\r
+ (Thread->BasePriority == 0) ||\r
+ (Thread->Priority != 0));\r
+ return Thread;\r
+ }\r
+ \r
+ //\r
+ // This routine computes the new priority for a thread. It is only valid for\r
+ // threads with priorities in the dynamic priority range.\r
+ //\r
+ SCHAR\r
+ FORCEINLINE\r
+ KiComputeNewPriority(IN PKTHREAD Thread)\r
+ {\r
+ SCHAR Priority;\r
+ \r
+ /* Priority sanity checks */\r
+ ASSERT((Thread->PriorityDecrement >= 0) &&\r
+ (Thread->PriorityDecrement <= Thread->Priority));\r
+ ASSERT((Thread->Priority < LOW_REALTIME_PRIORITY) ?\r
+ TRUE : (Thread->PriorityDecrement == 0));\r
+ \r
+ /* Get the current priority */\r
+ Priority = Thread->Priority;\r
+ if (Priority < LOW_REALTIME_PRIORITY)\r
+ {\r
+ /* Decrease priority by the priority decrement */\r
+ Priority -= (Thread->PriorityDecrement + 1);\r
+ \r
+ /* Don't go out of bounds */\r
+ if (Priority < Thread->BasePriority) Priority = Thread->BasePriority;\r
+ \r
+ /* Reset the priority decrement */\r
+ Thread->PriorityDecrement = 0;\r
+ }\r
+ \r
+ /* Sanity check */\r
+ ASSERT((Thread->BasePriority == 0) || (Priority != 0));\r
+ \r
+ /* Return the new priority */\r
+ return Priority;\r
+ }\r
+ \r
VOID
NTAPI
---LdrInitModuleManagement(VOID);
+++LdrInitModuleManagement(
+++ IN PVOID KernelBase
+++);
NTSTATUS
NTAPI
#endif
+ C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCall) == 0x300);
+ C_ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
+ C_ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
+ C_ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
+ C_ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
+ C_ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
+ C_ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
+ C_ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
+ C_ASSERT(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
+ C_ASSERT(FIELD_OFFSET(KTHREAD, ApcState.Process) == KTHREAD_APCSTATE_PROCESS);
+ C_ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
+++#ifdef _M_IX86
+ C_ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
+ C_ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
+ C_ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
+ C_ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
+ C_ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
+++#endif
+ //C_ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
+ //C_ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
+ C_ASSERT(FIELD_OFFSET(KPCR, IRR) == KPCR_IRR);
+ C_ASSERT(FIELD_OFFSET(KPCR, IDR) == KPCR_IDR);
+ C_ASSERT(FIELD_OFFSET(KPCR, Irql) == KPCR_IRQL);
+++#ifdef _M_IX86
+ C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
+ C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
+ C_ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
+ C_ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
+ C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, DpcStack) == KPCR_PRCB_DPC_STACK);
+ C_ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
+++#endif
+
#endif /* INCLUDE_INTERNAL_NTOSKRNL_H */
#ifndef __NTOSKRNL_INCLUDE_INTERNAL_POWERPC_KE_H
#define __NTOSKRNL_INCLUDE_INTERNAL_POWERPC_KE_H
+++#include <ndk/powerpc/ketypes.h>
+++
#if __GNUC__ >=3
#pragma GCC system_header
#endif
#define KeArchEraseFlags()
#define KeArchDisableInterrupts() KePPCDisableInterrupts()
- ULONG Value = 0;
- return (struct _KPRCB *) Value;
++static __inline struct _KPRCB * KeGetCurrentPrcb(
++ VOID)
++{
- static __inline KIRQL KeGetCurrentIrql(
+++ return (struct _KPRCB *)__readfsdword(0x20);
+++}
+++
+++__inline struct _KPCR * NTHALAPI KeGetCurrentKPCR(
+++ VOID)
+++{
+++ return (struct _KPCR *)__readfsdword(0x1c);
++}
++
- return PASSIVE_LEVEL;
+++__inline KIRQL NTHALAPI KeGetCurrentIrql(
++ VOID)
++{
+++ return ((KIPCR *)KeGetCurrentKPCR())->CurrentIrql;
++}
++
++VOID
++STDCALL
++KePPCInitThreadWithContext(
++ PKTHREAD Thread,
++ PKSYSTEM_ROUTINE SystemRoutine,
++ PKSTART_ROUTINE StartRoutine,
++ PVOID StartContext,
++ PCONTEXT Context);
++
++VOID
++STDCALL
++KeApplicationProcessorInitDispatcher(
++ VOID);
++
++VOID
++STDCALL
++KeCreateApplicationProcessorIdleThread(
++ ULONG Id);
++
++VOID KePPCHaltProcessor();
++
++#ifdef _NTOSKRNL_ /* FIXME: Move flags above to NDK instead of here */
++VOID
++STDCALL
++KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
++ PKSTART_ROUTINE StartRoutine,
++ PVOID StartContext,
++ BOOLEAN UserThread,
++ KTRAP_FRAME TrapFrame);
++#endif
++
++#endif /* __ASM__ */
++
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_POWERPC_KE_H */
/* EOF */
*
*--*/
VOID
- STDCALL
- KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
- IN PKTRAP_FRAME TrapFrame,
- IN PKNORMAL_ROUTINE NormalRoutine,
- IN PVOID NormalContext,
- IN PVOID SystemArgument1,
- IN PVOID SystemArgument2)
+ NTAPI
+ _KeLeaveCriticalRegion(VOID)
{
- CONTEXT Context;
- ULONG_PTR Stack;
- ULONG Size;
-
- DPRINT("KiInitializeUserApc(TrapFrame %x/%x)\n", TrapFrame,
- KeGetCurrentThread()->TrapFrame);
+ /* Use inlined version */
+ KeLeaveCriticalRegion();
+ }
- #ifdef _M_IX86
- /* Don't deliver APCs in V86 mode */
- if (TrapFrame->EFlags & X86_EFLAGS_VM) return;
- #endif
+ /*++
+ * KeInitializeApc
+ * @implemented NT4
+ *
+ * The The KeInitializeApc routine initializes an APC object, and registers
+ * the Kernel, Rundown and Normal routines for that object.
+ *
+ * @param Apc
+ * Pointer to a KAPC structure that represents the APC object to
+ * initialize. The caller must allocate storage for the structure
+ * from resident memory.
+ *
+ * @param Thread
+ * Thread to which to deliver the APC.
+ *
+ * @param TargetEnvironment
+ * APC Environment to be used.
+ *
+ * @param KernelRoutine
+ * Points to the KernelRoutine to associate with the APC.
+ * This routine is executed for all APCs.
+ *
+ * @param RundownRoutine
+ * Points to the RundownRoutine to associate with the APC.
+ * This routine is executed when the Thread exists during APC execution.
+ *
+ * @param NormalRoutine
+ * Points to the NormalRoutine to associate with the APC.
+ * This routine is executed at PASSIVE_LEVEL. If this is not specifed,
+ * the APC becomes a Special APC and the Mode and Context parameters are
+ * ignored.
+ *
+ * @param Mode
+ * Specifies the processor mode at which to run the Normal Routine.
+ *
+ * @param Context
+ * Specifices the value to pass as Context parameter to the registered
+ * routines.
+ *
+ * @return None.
+ *
+ * @remarks The caller can queue an initialized APC with KeInsertQueueApc.
+ *
+ *--*/
+ VOID
+ NTAPI
+ KeInitializeApc(IN PKAPC Apc,
+ IN PKTHREAD Thread,
+ IN KAPC_ENVIRONMENT TargetEnvironment,
+ IN PKKERNEL_ROUTINE KernelRoutine,
+ IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
+ IN PKNORMAL_ROUTINE NormalRoutine,
+ IN KPROCESSOR_MODE Mode,
+ IN PVOID Context)
+ {
+ /* Sanity check */
+ ASSERT(TargetEnvironment <= InsertApcEnvironment);
- /* Save the full context */
- Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
- KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
+ /* Set up the basic APC Structure Data */
+ Apc->Type = ApcObject;
+ Apc->Size = sizeof(KAPC);
- /* Protect with SEH */
- _SEH_TRY
+ /* Set the Environment */
+ if (TargetEnvironment == CurrentApcEnvironment)
+ {
+ /* Use the current one for the thread */
+ Apc->ApcStateIndex = Thread->ApcStateIndex;
+ }
+ else
{
- /* Get the aligned size */
- Size = ((sizeof(CONTEXT) + 3) & ~3) + 4 * sizeof(ULONG_PTR);
- Stack = (Context.Esp & ~3) - Size;
+ /* Sanity check */
+ ASSERT((TargetEnvironment <= Thread->ApcStateIndex) ||
+ (TargetEnvironment == InsertApcEnvironment));
- /* Probe and copy */
- ProbeForWrite((PVOID)Stack, Size, 4);
- RtlMoveMemory((PVOID)(Stack + 4 * sizeof(ULONG_PTR)),
- &Context,
- sizeof(CONTEXT));
+ /* Use the one that was given */
+ Apc->ApcStateIndex = TargetEnvironment;
+ }
- /* Run at APC dispatcher */
- TrapFrame->Eip = (ULONG)KeUserApcDispatcher;
- TrapFrame->HardwareEsp = Stack;
++#ifdef _M_IX86
+ /* Set the Thread and Routines */
+ Apc->Thread = Thread;
+ Apc->KernelRoutine = KernelRoutine;
+ Apc->RundownRoutine = RundownRoutine;
+ Apc->NormalRoutine = NormalRoutine;
++#endif
- /* Setup the stack */
- *(PULONG_PTR)(Stack + 0 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalRoutine;
- *(PULONG_PTR)(Stack + 1 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalContext;
- *(PULONG_PTR)(Stack + 2 * sizeof(ULONG_PTR)) = (ULONG_PTR)SystemArgument1;
- *(PULONG_PTR)(Stack + 3 * sizeof(ULONG_PTR)) = (ULONG_PTR)SystemArgument2;
+ /* Check if this is a special APC */
+ if (NormalRoutine)
+ {
+ /* It's a normal one. Set the context and mode */
+ Apc->ApcMode = Mode;
+ Apc->NormalContext = Context;
}
- _SEH_HANDLE
+ else
{
- /* FIXME: Get the record and raise an exception */
+ /* It's a special APC, which can only be kernel mode */
+ Apc->ApcMode = KernelMode;
+ Apc->NormalContext = NULL;
}
- _SEH_END;
+
+ /* The APC is not inserted*/
+ Apc->Inserted = FALSE;
}
/*++
if (InterlockedExchange(&Prcb->DpcSetEventRequest, 0))
{
/* Signal it */
-- KeSetEvent(&Prcb->DpcEvent, 0, 0);
++ KeSetEvent((PVOID)&Prcb->DpcEvent, 0, 0);
}
- /* Lock dispatcher */
- OldIrql = KeRaiseIrqlToSynchLevel();
- ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
-
- /* Get the Thread's Process */
- Process = CurrentThread->ApcState.Process;
+ /* Raise to synchronization level and lock the PRCB and thread */
+ KeRaiseIrqlToSynchLevel();
+ KiAcquireThreadLock(Thread);
+ KiAcquirePrcbLock(Prcb);
/* Check if Quantum expired */
- if (CurrentThread->Quantum <= 0)
+ if (Thread->Quantum <= 0)
{
- /* Reset the new Quantum */
- CurrentThread->Quantum = CurrentThread->QuantumReset;
-
- /* Calculate new priority */
- OldPriority = CurrentThread->Priority;
- if (OldPriority < LOW_REALTIME_PRIORITY)
+ /* Make sure that we're not real-time or without a quantum */
+ if ((Thread->Priority < LOW_REALTIME_PRIORITY) &&
+ !(Thread->ApcState.Process->DisableQuantum))
{
- /* Set the New Priority and add the Priority Decrement */
- NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
-
- /* Don't go out of bounds */
- if (NewPriority < CurrentThread->BasePriority)
- {
- NewPriority = CurrentThread->BasePriority;
- }
+ /* Reset the new Quantum */
+ Thread->Quantum = Thread->QuantumReset;
- /* Reset the priority decrement */
- CurrentThread->PriorityDecrement = 0;
+ /* Calculate new priority */
+ Priority = Thread->Priority = KiComputeNewPriority(Thread);
- /* Set a new priority if needed */
- if (OldPriority != NewPriority)
+ /* Check if a new thread is scheduled */
+ if (!Prcb->NextThread)
{
- /* Set new Priority */
- BOOLEAN Dummy; /* <- This is a hack anyways... */
- KiSetPriorityThread(CurrentThread, NewPriority, &Dummy);
+ /* FIXME: TODO. Add code from new scheduler */
}
else
{
*/
if (((Dpc->Importance == HighImportance) ||
(DpcData->DpcQueueDepth >=
-- Prcb->MaximumDpcQueueDepth)) &&
++ Prcb->MaximumDpcQueueDepth))
++#ifndef _M_PPC
++ &&
- (!(AFFINITY_MASK(Cpu) & IdleProcessorMask) ||
+ (!(AFFINITY_MASK(Cpu) & KiIdleSummary) ||
-- (Prcb->Sleeping)))
++ (Prcb->Sleeping))
++#endif
++ )
{
/* Set interrupt requested */
Prcb->DpcInterruptRequested = TRUE;
/* FreeLDR Memory Data */
ADDRESS_RANGE KeMemoryMap[64];
ULONG KeMemoryMapRangeCount;
---ULONG_PTR FirstKrnlPhysAddr;
---ULONG_PTR LastKrnlPhysAddr;
---ULONG_PTR LastKernelAddress;
--ULONG MmFreeLdrMemHigher, MmFreeLdrMemLower;
--ULONG MmFreeLdrPageDirectoryStart, MmFreeLdrPageDirectoryEnd;
+++ULONG_PTR MmFreeLdrFirstKrnlPhysAddr, MmFreeLdrLastKrnlPhysAddr;
+++ULONG_PTR MmFreeLdrLastKernelAddress;
+++ULONG MmFreeLdrMemHigher;
+++ULONG MmFreeLdrPageDirectoryEnd;
/* FreeLDR Loader Data */
- ROS_LOADER_PARAMETER_BLOCK KeLoaderBlock;
+ ROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
static CHAR KeLoaderCommandLine[256];
+ BOOLEAN AcpiTableDetected;
/* FreeLDR PE Hack Data */
---extern unsigned int _image_base__;
---ULONG_PTR KERNEL_BASE = (ULONG_PTR)&_image_base__;
extern LDR_DATA_TABLE_ENTRY HalModuleObject;
+ /* NT Loader Data */
+ LOADER_PARAMETER_BLOCK BldrLoaderBlock;
+ LOADER_PARAMETER_EXTENSION BldrExtensionBlock;
+ CHAR BldrCommandLine[256];
+ CHAR BldrArcBootPath[64];
+ CHAR BldrArcHalPath[64];
+ CHAR BldrNtHalPath[64];
+ CHAR BldrNtBootPath[64];
+ LDR_DATA_TABLE_ENTRY BldrModules[64];
+ MEMORY_ALLOCATION_DESCRIPTOR BldrMemoryDescriptors[64];
+ WCHAR BldrModuleStrings[64][260];
+ NLS_DATA_BLOCK BldrNlsDataBlock;
+ SETUP_LOADER_BLOCK BldrSetupBlock;
+
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
- KiRosPrepareForSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
+ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
+ IN PLOADER_PARAMETER_BLOCK *NtLoaderBlock)
+ {
+ PLOADER_PARAMETER_BLOCK LoaderBlock;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ PMEMORY_ALLOCATION_DESCRIPTOR MdEntry;
+ PLOADER_MODULE RosEntry;
+ ULONG i, j, ModSize;
+ PVOID ModStart;
+ PCHAR DriverName;
+ PCHAR BootPath, HalPath;
+ CHAR CommandLine[256];
+
+ /* First get some kernel-loader globals */
+ AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
+ MmFreeLdrMemHigher = RosLoaderBlock->MemHigher;
-- MmFreeLdrMemLower = RosLoaderBlock->MemLower;
-- MmFreeLdrPageDirectoryStart = RosLoaderBlock->PageDirectoryStart;
+ MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
+ KeLoaderModuleCount = RosLoaderBlock->ModsCount;
+
+ /* Set the NT Loader block and initialize it */
+ *NtLoaderBlock = LoaderBlock = &BldrLoaderBlock;
+ RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
+
+ /* Set the NLS Data block */
+ LoaderBlock->NlsData = &BldrNlsDataBlock;
+
+ /* Assume this is from FreeLDR's SetupLdr */
+ LoaderBlock->SetupLdrBlock = &BldrSetupBlock;
+
+ /* Setup the list heads */
+ InitializeListHead(&LoaderBlock->LoadOrderListHead);
+ InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
+ InitializeListHead(&LoaderBlock->BootDriverListHead);
+
+ /* Loop boot driver list */
+ for (i = 0; i < KeLoaderModuleCount; i++)
+ {
+ /* Get the ROS loader entry */
+ RosEntry = &KeLoaderModules[i];
+ DriverName = (PCHAR)RosEntry->String;
+ ModStart = (PVOID)RosEntry->ModStart;
+ ModSize = RosEntry->ModEnd - (ULONG_PTR)ModStart;
+
+ /* Check if this is any of the NLS files */
+ if (!_stricmp(DriverName, "ansi.nls"))
+ {
+ /* ANSI Code page */
+ LoaderBlock->NlsData->AnsiCodePageData = ModStart;
+
+ /* Create an MD for it */
+ MdEntry = &BldrMemoryDescriptors[i];
+ MdEntry->MemoryType = LoaderNlsData;
+ MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+ MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+ InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+ &MdEntry->ListEntry);
+ continue;
+ }
+ else if (!_stricmp(DriverName, "oem.nls"))
+ {
+ /* OEM Code page */
+ LoaderBlock->NlsData->OemCodePageData = ModStart;
+
+ /* Create an MD for it */
+ MdEntry = &BldrMemoryDescriptors[i];
+ MdEntry->MemoryType = LoaderNlsData;
+ MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+ MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+ InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+ &MdEntry->ListEntry);
+ continue;
+ }
+ else if (!_stricmp(DriverName, "casemap.nls"))
+ {
+ /* Unicode Code page */
+ LoaderBlock->NlsData->UnicodeCodePageData = ModStart;
+
+ /* Create an MD for it */
+ MdEntry = &BldrMemoryDescriptors[i];
+ MdEntry->MemoryType = LoaderNlsData;
+ MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+ MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+ InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+ &MdEntry->ListEntry);
+ continue;
+ }
+
+ /* Check if this is the SYSTEM hive */
+ if (!(_stricmp(DriverName, "system")) ||
+ !(_stricmp(DriverName, "system.hiv")))
+ {
+ /* Save registry data */
+ LoaderBlock->RegistryBase = ModStart;
+ LoaderBlock->RegistryLength = ModSize;
+
+ /* Disable setup mode */
+ LoaderBlock->SetupLdrBlock = NULL;
+
+ /* Create an MD for it */
+ MdEntry = &BldrMemoryDescriptors[i];
+ MdEntry->MemoryType = LoaderRegistryData;
+ MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+ MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+ InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+ &MdEntry->ListEntry);
+ continue;
+ }
+
+ /* Check if this is the HARDWARE hive */
+ if (!(_stricmp(DriverName, "hardware")) ||
+ !(_stricmp(DriverName, "hardware.hiv")))
+ {
+ /* Create an MD for it */
+ MdEntry = &BldrMemoryDescriptors[i];
+ MdEntry->MemoryType = LoaderRegistryData;
+ MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+ MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+ InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+ &MdEntry->ListEntry);
+ continue;
+ }
+
+ /* Setup the loader entry */
+ LdrEntry = &BldrModules[i];
+ RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY));
+
+ /* Convert driver name from ANSI to Unicode */
+ for (j = 0; j < strlen(DriverName); j++)
+ {
+ BldrModuleStrings[i][j] = DriverName[j];
+ }
+
+ /* Setup driver name */
+ RtlInitUnicodeString(&LdrEntry->BaseDllName, BldrModuleStrings[i]);
+ RtlInitUnicodeString(&LdrEntry->FullDllName, BldrModuleStrings[i]);
+
+ /* Copy data from Freeldr Module Entry */
+ LdrEntry->DllBase = ModStart;
+ LdrEntry->SizeOfImage = ModSize;
+
+ /* Initialize other data */
+ LdrEntry->LoadCount = 1;
+ LdrEntry->Flags = LDRP_IMAGE_DLL |
+ LDRP_ENTRY_PROCESSED;
+ if (RosEntry->Reserved) LdrEntry->Flags |= LDRP_ENTRY_INSERTED;
+
+ /* Insert it into the loader block */
+ InsertTailList(&LoaderBlock->LoadOrderListHead,
+ &LdrEntry->InLoadOrderLinks);
+
+ /* Check if this is the kernel */
+ if (!(_stricmp(DriverName, "ntoskrnl.exe")))
+ {
+ /* Create an MD for it */
+ MdEntry = &BldrMemoryDescriptors[i];
+ MdEntry->MemoryType = LoaderSystemCode;
+ MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+ MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+ InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+ &MdEntry->ListEntry);
+ }
+ else if (!(_stricmp(DriverName, "hal.dll")))
+ {
+++ /* The HAL actually gets loaded somewhere else */
+++ ModStart = HalModuleObject.DllBase;
+++
+ /* Create an MD for the HAL */
+ MdEntry = &BldrMemoryDescriptors[i];
+ MdEntry->MemoryType = LoaderHalCode;
+ MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+ MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+ InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+ &MdEntry->ListEntry);
+ }
+ else
+ {
+ /* Create an MD for any driver */
+ MdEntry = &BldrMemoryDescriptors[i];
+ MdEntry->MemoryType = LoaderBootDriver;
+ MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+ MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+ InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+ &MdEntry->ListEntry);
+ }
+ }
+
+ /* Setup command line */
+ LoaderBlock->LoadOptions = BldrCommandLine;
+ strcpy(BldrCommandLine, KeLoaderCommandLine);
+
+ /* Setup the extension block */
+ LoaderBlock->Extension = &BldrExtensionBlock;
+ LoaderBlock->Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
+ LoaderBlock->Extension->MajorVersion = 5;
+ LoaderBlock->Extension->MinorVersion = 2;
+
+ /* Now setup the setup block if we have one */
+ if (LoaderBlock->SetupLdrBlock)
+ {
+ /* All we'll setup right now is the flag for text-mode setup */
+ LoaderBlock->SetupLdrBlock->Flags = 1;
+ }
+
+ /* Make a copy of the command line */
+ strcpy(CommandLine, LoaderBlock->LoadOptions);
+
+ /* Find the first \, separating the ARC path from NT path */
+ BootPath = strchr(CommandLine, '\\');
+ *BootPath = ANSI_NULL;
+ strncpy(BldrArcBootPath, CommandLine, 63);
+ LoaderBlock->ArcBootDeviceName = BldrArcBootPath;
+
+ /* The rest of the string is the NT path */
+ HalPath = strchr(BootPath + 1, ' ');
+ *HalPath = ANSI_NULL;
+ BldrNtBootPath[0] = '\\';
+ strncat(BldrNtBootPath, BootPath + 1, 63);
+ strcat(BldrNtBootPath,"\\");
+ LoaderBlock->NtBootPathName = BldrNtBootPath;
+
+ /* Set the HAL paths */
+ strncpy(BldrArcHalPath, BldrArcBootPath, 63);
+ LoaderBlock->ArcHalDeviceName = BldrArcHalPath;
+ strcpy(BldrNtHalPath, "\\");
+ LoaderBlock->NtHalPathName = BldrNtHalPath;
+
+ /* Use this new command line */
+ strncpy(LoaderBlock->LoadOptions, HalPath + 2, 255);
+
+ /* Parse it and change every slash to a space */
+ BootPath = LoaderBlock->LoadOptions;
+ do {if (*BootPath == '/') *BootPath = ' ';} while (*BootPath++);
+ }
+
+ VOID
+ FASTCALL
+ KiRosPrepareForSystemStartup(IN ULONG Dummy,
+ IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
{
- #ifdef _M_IX86
ULONG i;
ULONG size;
ULONG HalBase;
ULONG DriverBase;
ULONG DriverSize;
--- PIMAGE_NT_HEADERS NtHeader;
--- PIMAGE_OPTIONAL_HEADER OptHead;
+ PLOADER_PARAMETER_BLOCK NtLoaderBlock;
CHAR* s;
+++#ifdef _M_IX86
+ PKTSS Tss;
+ PKGDTENTRY TssEntry;
+++#endif
+++#ifdef _M_IX86
/* Load the GDT and IDT */
Ke386SetGlobalDescriptorTable(KiGdtDescriptor);
Ke386SetInterruptDescriptorTable(KiIdtDescriptor);
+ /* Initialize the boot TSS */
+ Tss = &KiBootTss;
+ TssEntry = &KiBootGdt[KGDT_TSS / sizeof(KGDTENTRY)];
+ TssEntry->HighWord.Bits.Type = I386_TSS;
+ TssEntry->HighWord.Bits.Pres = 1;
+ TssEntry->HighWord.Bits.Dpl = 0;
+ TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
+ TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
+ TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
+++#endif
+
/* Copy the Loader Block Data locally since Low-Memory will be wiped */
- memcpy(&KeLoaderBlock, LoaderBlock, sizeof(ROS_LOADER_PARAMETER_BLOCK));
- memcpy(&KeLoaderModules[1],
- (PVOID)KeLoaderBlock.ModsAddr,
- sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
- KeLoaderBlock.ModsCount++;
- KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
+ memcpy(&KeRosLoaderBlock, LoaderBlock, sizeof(ROS_LOADER_PARAMETER_BLOCK));
-- memcpy(&KeLoaderModules[1],
+++ memcpy(&KeLoaderModules[0],
+ (PVOID)KeRosLoaderBlock.ModsAddr,
+ sizeof(LOADER_MODULE) * KeRosLoaderBlock.ModsCount);
-- KeRosLoaderBlock.ModsCount++;
+ KeRosLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
/* Check for BIOS memory map */
KeMemoryMapRangeCount = 0;
/* Set the Command Line */
strcpy(KeLoaderCommandLine, (PCHAR)LoaderBlock->CommandLine);
- KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
-
- /* Write the first Module (the Kernel) */
- strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
- KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
- KeLoaderModules[0].ModStart = KERNEL_BASE;
-
- /* Read PE Data */
- NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
- OptHead = &NtHeader->OptionalHeader;
-
- /* Set Kernel Ending */
- KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart +
- PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
+ KeRosLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
-- /* Write the first Module (the Kernel) */
-- strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
-- KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
-- KeLoaderModules[0].ModStart = KERNEL_BASE;
--
-- /* Read PE Data */
-- NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
-- OptHead = &NtHeader->OptionalHeader;
--
-- /* Set Kernel Ending */
-- KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart +
-- PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
--
/* Create a block for each module */
- for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+ for (i = 1; i < KeRosLoaderBlock.ModsCount; i++)
{
/* Check if we have to copy the path or not */
if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0)
strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
}
+++#ifdef _M_IX86
/* Substract the base Address in Physical Memory */
KeLoaderModules[i].ModStart -= 0x200000;
/* Add the Kernel Base Address in Virtual Memory */
--- KeLoaderModules[i].ModStart += KERNEL_BASE;
+++ KeLoaderModules[i].ModStart += KSEG0_BASE;
/* Substract the base Address in Physical Memory */
KeLoaderModules[i].ModEnd -= 0x200000;
/* Add the Kernel Base Address in Virtual Memory */
--- KeLoaderModules[i].ModEnd += KERNEL_BASE;
+++ KeLoaderModules[i].ModEnd += KSEG0_BASE;
+++#endif
/* Select the proper String */
KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
}
/* Choose last module address as the final kernel address */
- LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.
-- LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeRosLoaderBlock.
--- ModsCount - 1].ModEnd);
+++ MmFreeLdrLastKernelAddress =
+++ PAGE_ROUND_UP(KeLoaderModules[KeRosLoaderBlock.ModsCount - 1].ModEnd);
/* Select the HAL Base */
HalBase = KeLoaderModules[1].ModStart;
/* Choose Driver Base */
--- DriverBase = LastKernelAddress;
+++ DriverBase = MmFreeLdrLastKernelAddress;
LdrHalBase = (ULONG_PTR)DriverBase;
/* Initialize Module Management */
--- LdrInitModuleManagement();
+++ LdrInitModuleManagement((PVOID)KeLoaderModules[0].ModStart);
/* Load HAL.DLL with the PE Loader */
LdrSafePEProcessModule((PVOID)HalBase,
(PVOID)DriverBase,
--- (PVOID)KERNEL_BASE,
+++ (PVOID)KeLoaderModules[0].ModStart,
&DriverSize);
//
OptionalHeader.SizeOfImage;
/* Increase the last kernel address with the size of HAL */
--- LastKernelAddress += PAGE_ROUND_UP(DriverSize);
+++ MmFreeLdrLastKernelAddress += PAGE_ROUND_UP(DriverSize);
+++#ifdef _M_IX86
/* Now select the final beginning and ending Kernel Addresses */
--- FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000;
--- LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
+++ MmFreeLdrFirstKrnlPhysAddr = KeLoaderModules[0].ModStart -
+++ KSEG0_BASE + 0x200000;
+++ MmFreeLdrLastKrnlPhysAddr = MmFreeLdrLastKernelAddress -
+++ KSEG0_BASE + 0x200000;
+++#endif
/* Setup the IDT */
KeInitExceptions(); // ONCE HACK BELOW IS GONE, MOVE TO KISYSTEMSTARTUP!
KeInitInterrupts(); // ROS HACK DEPRECATED SOON BY NEW HAL
- #elif defined(_M_PPC)
- ULONG DriverBase = 0;
- ULONG DriverSize = 0;
-
- memset( KeLoaderModules, 0, sizeof(KeLoaderModules) );
- memset( KeLoaderCommandLine, 0, sizeof(KeLoaderCommandLine) );
- memset( KeLoaderModuleStrings, 0, sizeof(KeLoaderModuleStrings) );
-
- /* Stop here for now -- we'll write this part later */
- char *foo = 0;
- *foo = 1;
- #endif
/* Load the Kernel with the PE Loader */
--- LdrSafePEProcessModule((PVOID)KERNEL_BASE,
--- (PVOID)KERNEL_BASE,
+++ LdrSafePEProcessModule((PVOID)KeLoaderModules[0].ModStart,
+++ (PVOID)KeLoaderModules[0].ModStart,
(PVOID)DriverBase,
&DriverSize);
---/*\r
--- * PROJECT: ReactOS Kernel\r
--- * LICENSE: GPL - See COPYING in the top level directory\r
--- * FILE: ntoskrnl/ke/krnlinit.c\r
--- * PURPOSE: Portable part of kernel initialization\r
--- * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)\r
--- */\r
---\r
- /* INCLUDES *****************************************************************/\r
--/* INCLUDES ******************************************************************/\r
---\r
---#include <ntoskrnl.h>\r
---#define NDEBUG\r
---#include <debug.h>\r
---#include <internal/napi.h>\r
---\r
---/* GLOBALS *******************************************************************/\r
--\r
--/* System call count */\r
--ULONG KiServiceLimit = NUMBER_OF_SYSCALLS;\r
--\r
--/* ARC Loader Block */\r
--PLOADER_PARAMETER_BLOCK KeLoaderBlock;\r
---\r
---/* PRCB Array */\r
---PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];\r
---\r
---/* NUMA Node Support */\r
---KNODE KiNode0;\r
---PKNODE KeNodeBlock[1];\r
---UCHAR KeNumberNodes = 1;\r
---UCHAR KeProcessNodeSeed;\r
---\r
---/* Initial Process and Thread */\r
---ETHREAD KiInitialThread;\r
---EPROCESS KiInitialProcess;\r
---\r
---/* System-defined Spinlocks */\r
---KSPIN_LOCK KiDispatcherLock;\r
---KSPIN_LOCK MmPfnLock;\r
---KSPIN_LOCK MmSystemSpaceLock;\r
---KSPIN_LOCK CcBcbSpinLock;\r
---KSPIN_LOCK CcMasterSpinLock;\r
---KSPIN_LOCK CcVacbSpinLock;\r
---KSPIN_LOCK CcWorkQueueSpinLock;\r
---KSPIN_LOCK NonPagedPoolLock;\r
---KSPIN_LOCK MmNonPagedPoolLock;\r
---KSPIN_LOCK IopCancelSpinLock;\r
---KSPIN_LOCK IopVpbSpinLock;\r
---KSPIN_LOCK IopDatabaseLock;\r
---KSPIN_LOCK IopCompletionLock;\r
---KSPIN_LOCK NtfsStructLock;\r
---KSPIN_LOCK AfdWorkQueueSpinLock;\r
---KSPIN_LOCK KiTimerTableLock[16];\r
---KSPIN_LOCK KiReverseStallIpiLock;\r
---\r
---/* FUNCTIONS *****************************************************************/\r
---\r
---VOID\r
---NTAPI\r
---KiInitSystem(VOID)\r
---{\r
--- ULONG i;\r
---\r
--- /* Initialize Bugcheck Callback data */\r
--- InitializeListHead(&BugcheckCallbackListHead);\r
--- InitializeListHead(&BugcheckReasonCallbackListHead);\r
--- KeInitializeSpinLock(&BugCheckCallbackLock);\r
---\r
--- /* Initialize the Timer Expiration DPC */\r
--- KeInitializeDpc(&KiExpireTimerDpc, KiExpireTimers, NULL);\r
--- KeSetTargetProcessorDpc(&KiExpireTimerDpc, 0);\r
---\r
--- /* Initialize Profiling data */\r
--- KeInitializeSpinLock(&KiProfileLock);\r
--- InitializeListHead(&KiProfileListHead);\r
--- InitializeListHead(&KiProfileSourceListHead);\r
---\r
--- /* Loop the timer table */\r
--- for (i = 0; i < TIMER_TABLE_SIZE; i++)\r
--- {\r
--- /* Initialize the list and entries */\r
--- InitializeListHead(&KiTimerTableListHead[i].Entry);\r
--- KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;\r
--- KiTimerTableListHead[i].Time.LowPart = 0;\r
--- }\r
---\r
--- /* Initialize old-style list */\r
--- InitializeListHead(&KiTimerListHead);\r
---\r
--- /* Initialize the Swap event and all swap lists */\r
--- KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);\r
--- InitializeListHead(&KiProcessInSwapListHead);\r
--- InitializeListHead(&KiProcessOutSwapListHead);\r
--- InitializeListHead(&KiStackInSwapListHead);\r
---\r
--- /* Initialize the mutex for generic DPC calls */\r
--- KeInitializeMutex(&KiGenericCallDpcMutex, 0);\r
---\r
--- /* Initialize the syscall table */\r
--- KeServiceDescriptorTable[0].Base = MainSSDT;\r
--- KeServiceDescriptorTable[0].Count = NULL;\r
- KeServiceDescriptorTable[0].Limit = NUMBER_OF_SYSCALLS;\r
-- KeServiceDescriptorTable[0].Limit = KiServiceLimit;\r
--- KeServiceDescriptorTable[1].Limit = 0;\r
--- KeServiceDescriptorTable[0].Number = MainSSPT;\r
---\r
--- /* Copy the the current table into the shadow table for win32k */\r
--- RtlCopyMemory(KeServiceDescriptorTableShadow,\r
--- KeServiceDescriptorTable,\r
--- sizeof(KeServiceDescriptorTable));\r
---}\r
---\r
---LARGE_INTEGER\r
---NTAPI\r
---KiComputeReciprocal(IN LONG Divisor,\r
--- OUT PUCHAR Shift)\r
---{\r
--- LARGE_INTEGER Reciprocal = {{0}};\r
--- LONG BitCount = 0, Remainder = 1;\r
---\r
--- /* Start by calculating the remainder */\r
--- while (Reciprocal.HighPart >= 0)\r
--- {\r
--- /* Increase the loop (bit) count */\r
--- BitCount++;\r
---\r
--- /* Calculate the current fraction */\r
--- Reciprocal.HighPart = (Reciprocal.HighPart << 1) |\r
--- (Reciprocal.LowPart >> 31);\r
--- Reciprocal.LowPart <<= 1;\r
---\r
--- /* Double the remainder and see if we went past the divisor */\r
--- Remainder <<= 1;\r
--- if (Remainder >= Divisor)\r
--- {\r
--- /* Set the low-bit and calculate the new remainder */\r
--- Remainder -= Divisor;\r
--- Reciprocal.LowPart |= 1;\r
--- }\r
--- }\r
---\r
--- /* Check if we have a remainder */\r
--- if (Remainder)\r
--- {\r
--- /* Check if the current fraction value is too large */\r
--- if ((Reciprocal.LowPart == 0xFFFFFFFF) &&\r
--- (Reciprocal.HighPart == 0xFFFFFFFF))\r
--- {\r
--- /* Set the high bit and reduce the bit count */\r
--- Reciprocal.LowPart = 0;\r
--- Reciprocal.HighPart = 0x80000000;\r
--- BitCount--;\r
--- }\r
--- else\r
--- {\r
--- /* Check if only the lowest bits got too large */\r
--- if (Reciprocal.LowPart == 0xFFFFFFFF)\r
--- {\r
--- /* Reset them and increase the high bits instead */\r
--- Reciprocal.LowPart = 0;\r
--- Reciprocal.HighPart++;\r
--- }\r
--- else\r
--- {\r
--- /* All is well, increase the low bits */\r
--- Reciprocal.LowPart++;\r
--- }\r
--- }\r
--- }\r
---\r
--- /* Now calculate the actual shift and return the reciprocal */\r
--- *Shift = (UCHAR)BitCount - 64;\r
--- return Reciprocal;\r
---}\r
---\r
---VOID\r
---NTAPI\r
---KiInitSpinLocks(IN PKPRCB Prcb,\r
--- IN CCHAR Number)\r
---{\r
--- ULONG i;\r
---\r
--- /* Initialize Dispatcher Fields */\r
--- Prcb->QueueIndex = 1;\r
--- Prcb->ReadySummary = 0;\r
--- Prcb->DeferredReadyListHead.Next = NULL;\r
--- for (i = 0; i < 32; i++)\r
--- {\r
--- /* Initialize the ready list */\r
--- InitializeListHead(&Prcb->DispatcherReadyListHead[i]);\r
--- }\r
---\r
--- /* Initialize DPC Fields */\r
--- InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);\r
--- KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);\r
--- Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;\r
--- Prcb->DpcData[DPC_NORMAL].DpcCount = 0;\r
--- Prcb->DpcRoutineActive = FALSE;\r
--- Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;\r
--- Prcb->MinimumDpcRate = KiMinimumDpcRate;\r
--- Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;\r
--- KeInitializeDpc(&Prcb->CallDpc, NULL, NULL);\r
--- KeSetTargetProcessorDpc(&Prcb->CallDpc, Number);\r
--- KeSetImportanceDpc(&Prcb->CallDpc, HighImportance);\r
---\r
--- /* Initialize the Wait List Head */\r
--- InitializeListHead(&Prcb->WaitListHead);\r
---\r
--- /* Initialize Queued Spinlocks */\r
--- Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock;\r
--- Prcb->LockQueue[LockQueueExpansionLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL;\r
--- Prcb->LockQueue[LockQueuePfnLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock;\r
--- Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock;\r
--- Prcb->LockQueue[LockQueueBcbLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock;\r
--- Prcb->LockQueue[LockQueueMasterLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock;\r
--- Prcb->LockQueue[LockQueueVacbLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock;\r
--- Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock;\r
--- Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock;\r
--- Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock;\r
--- Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock;\r
--- Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock;\r
--- Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock;\r
--- Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock;\r
--- Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock;\r
--- Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL;\r
--- Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;\r
--- Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;\r
--- Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;\r
---\r
--- /* Loop timer locks */\r
--- for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)\r
--- {\r
--- /* Initialize the lock and setup the Queued Spinlock */\r
--- KeInitializeSpinLock(&KiTimerTableLock[i]);\r
--- Prcb->LockQueue[i].Next = NULL;\r
--- Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];\r
--- }\r
---\r
--- /* Check if this is the boot CPU */\r
--- if (!Number)\r
--- {\r
--- /* Initialize the lock themselves */\r
--- KeInitializeSpinLock(&KiDispatcherLock);\r
--- KeInitializeSpinLock(&KiReverseStallIpiLock);\r
--- KeInitializeSpinLock(&MmPfnLock);\r
--- KeInitializeSpinLock(&MmSystemSpaceLock);\r
--- KeInitializeSpinLock(&CcBcbSpinLock);\r
--- KeInitializeSpinLock(&CcMasterSpinLock);\r
--- KeInitializeSpinLock(&CcVacbSpinLock);\r
--- KeInitializeSpinLock(&CcWorkQueueSpinLock);\r
--- KeInitializeSpinLock(&IopCancelSpinLock);\r
--- KeInitializeSpinLock(&IopCompletionLock);\r
--- KeInitializeSpinLock(&IopDatabaseLock);\r
--- KeInitializeSpinLock(&IopVpbSpinLock);\r
--- KeInitializeSpinLock(&NonPagedPoolLock);\r
--- KeInitializeSpinLock(&MmNonPagedPoolLock);\r
--- KeInitializeSpinLock(&NtfsStructLock);\r
--- KeInitializeSpinLock(&AfdWorkQueueSpinLock);\r
- KeInitializeDispatcher(); // ROS OLD DISPATCHER\r
--- }\r
---}\r
---\r
- /* FIXME: Rename and make portable */\r
- VOID\r
--BOOLEAN\r
---NTAPI\r
- KeInit2(VOID)\r
--KeInitSystem(VOID)\r
---{\r
- ULONG Protect;\r
- \r
- #ifdef _M_IX86\r
- /* Check if Fxsr was found */\r
- if (KeI386FxsrPresent)\r
- {\r
- /* Enable it. FIXME: Send an IPI */\r
- Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSFXSR);\r
- \r
- /* Check if XMM was found too */\r
- if (KeI386XMMIPresent)\r
- {\r
- /* Enable it: FIXME: Send an IPI. */\r
- Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSXMMEXCPT);\r
- \r
- /* FIXME: Implement and enable XMM Page Zeroing for Mm */\r
- }\r
- }\r
- \r
- if (KeFeatureBits & KF_GLOBAL_PAGE)\r
- {\r
- ULONG Flags;\r
- /* Enable global pages */\r
- Ke386GlobalPagesEnabled = TRUE;\r
- Ke386SaveFlags(Flags);\r
- Ke386DisableInterrupts();\r
- Ke386SetCr4(Ke386GetCr4() | X86_CR4_PGE);\r
- Ke386RestoreFlags(Flags);\r
- }\r
- \r
- if (KeFeatureBits & KF_FAST_SYSCALL)\r
- {\r
- extern void KiFastCallEntry(void);\r
- \r
- /* CS Selector of the target segment. */\r
- Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);\r
- /* Target ESP. */\r
- Ke386Wrmsr(0x175, 0, 0);\r
- /* Target EIP. */\r
- Ke386Wrmsr(0x176, (ULONG_PTR)KiFastCallEntry, 0);\r
- }\r
- #endif\r
- \r
- /* Does the CPU Support 'prefetchnta' (SSE) */\r
- if(KeFeatureBits & KF_XMMI)\r
-- /* Check if Threaded DPCs are enabled */\r
-- if (KeThreadDpcEnable)\r
--- {\r
- Protect = MmGetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal);\r
- MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect | PAGE_IS_WRITABLE);\r
- /* Replace the ret by a nop */\r
- *(PCHAR)RtlPrefetchMemoryNonTemporal = 0x90;\r
- MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect);\r
-- /* FIXME: TODO */\r
-- DPRINT1("Threaded DPCs not yet supported\n");\r
--- }\r
---\r
- /* Set IDT to writable */\r
- #ifdef _M_IX86\r
- Protect = MmGetPageProtect(NULL, (PVOID)KiIdt);\r
- MmSetPageProtect(NULL, (PVOID)KiIdt, Protect | PAGE_IS_WRITABLE);\r
- #endif\r
-- /* Initialize non-portable parts of the kernel */\r
-- KiInitMachineDependent();\r
-- return TRUE;\r
---}\r
--\r
+++/*
+++ * PROJECT: ReactOS Kernel
+++ * LICENSE: GPL - See COPYING in the top level directory
+++ * FILE: ntoskrnl/ke/krnlinit.c
+++ * PURPOSE: Portable part of kernel initialization
+++ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+++ */
+++
+++/* INCLUDES ******************************************************************/
+++
+++#include <ntoskrnl.h>
+++#define NDEBUG
+++#include <debug.h>
+++#include <internal/napi.h>
+++
+++/* GLOBALS *******************************************************************/
+++
+++/* System call count */
+++ULONG KiServiceLimit = NUMBER_OF_SYSCALLS;
+++
+++/* ARC Loader Block */
+++PLOADER_PARAMETER_BLOCK KeLoaderBlock;
+++
+++/* PRCB Array */
+++PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
+++
+++/* NUMA Node Support */
+++KNODE KiNode0;
+++PKNODE KeNodeBlock[1];
+++UCHAR KeNumberNodes = 1;
+++UCHAR KeProcessNodeSeed;
+++
+++/* Initial Process and Thread */
+++ETHREAD KiInitialThread;
+++EPROCESS KiInitialProcess;
+++
+++/* System-defined Spinlocks */
+++KSPIN_LOCK KiDispatcherLock;
+++KSPIN_LOCK MmPfnLock;
+++KSPIN_LOCK MmSystemSpaceLock;
+++KSPIN_LOCK CcBcbSpinLock;
+++KSPIN_LOCK CcMasterSpinLock;
+++KSPIN_LOCK CcVacbSpinLock;
+++KSPIN_LOCK CcWorkQueueSpinLock;
+++KSPIN_LOCK NonPagedPoolLock;
+++KSPIN_LOCK MmNonPagedPoolLock;
+++KSPIN_LOCK IopCancelSpinLock;
+++KSPIN_LOCK IopVpbSpinLock;
+++KSPIN_LOCK IopDatabaseLock;
+++KSPIN_LOCK IopCompletionLock;
+++KSPIN_LOCK NtfsStructLock;
+++KSPIN_LOCK AfdWorkQueueSpinLock;
+++KSPIN_LOCK KiTimerTableLock[16];
+++KSPIN_LOCK KiReverseStallIpiLock;
+++
+++/* FUNCTIONS *****************************************************************/
+++
+++VOID
+++NTAPI
+++KiInitSystem(VOID)
+++{
+++ ULONG i;
+++
+++ /* Initialize Bugcheck Callback data */
+++ InitializeListHead(&BugcheckCallbackListHead);
+++ InitializeListHead(&BugcheckReasonCallbackListHead);
+++ KeInitializeSpinLock(&BugCheckCallbackLock);
+++
+++ /* Initialize the Timer Expiration DPC */
+++ KeInitializeDpc(&KiExpireTimerDpc, KiExpireTimers, NULL);
+++ KeSetTargetProcessorDpc(&KiExpireTimerDpc, 0);
+++
+++ /* Initialize Profiling data */
+++ KeInitializeSpinLock(&KiProfileLock);
+++ InitializeListHead(&KiProfileListHead);
+++ InitializeListHead(&KiProfileSourceListHead);
+++
+++ /* Loop the timer table */
+++ for (i = 0; i < TIMER_TABLE_SIZE; i++)
+++ {
+++ /* Initialize the list and entries */
+++ InitializeListHead(&KiTimerTableListHead[i].Entry);
+++ KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;
+++ KiTimerTableListHead[i].Time.LowPart = 0;
+++ }
+++
+++ /* Initialize old-style list */
+++ InitializeListHead(&KiTimerListHead);
+++
+++ /* Initialize the Swap event and all swap lists */
+++ KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);
+++ InitializeListHead(&KiProcessInSwapListHead);
+++ InitializeListHead(&KiProcessOutSwapListHead);
+++ InitializeListHead(&KiStackInSwapListHead);
+++
+++ /* Initialize the mutex for generic DPC calls */
+++ KeInitializeMutex(&KiGenericCallDpcMutex, 0);
+++
+++ /* Initialize the syscall table */
+++ KeServiceDescriptorTable[0].Base = MainSSDT;
+++ KeServiceDescriptorTable[0].Count = NULL;
+++ KeServiceDescriptorTable[0].Limit = KiServiceLimit;
+++ KeServiceDescriptorTable[1].Limit = 0;
+++ KeServiceDescriptorTable[0].Number = MainSSPT;
+++
+++ /* Copy the the current table into the shadow table for win32k */
+++ RtlCopyMemory(KeServiceDescriptorTableShadow,
+++ KeServiceDescriptorTable,
+++ sizeof(KeServiceDescriptorTable));
+++}
+++
+++LARGE_INTEGER
+++NTAPI
+++KiComputeReciprocal(IN LONG Divisor,
+++ OUT PUCHAR Shift)
+++{
+++ LARGE_INTEGER Reciprocal = {{0}};
+++ LONG BitCount = 0, Remainder = 1;
+++
+++ /* Start by calculating the remainder */
+++ while (Reciprocal.HighPart >= 0)
+++ {
+++ /* Increase the loop (bit) count */
+++ BitCount++;
+++
+++ /* Calculate the current fraction */
+++ Reciprocal.HighPart = (Reciprocal.HighPart << 1) |
+++ (Reciprocal.LowPart >> 31);
+++ Reciprocal.LowPart <<= 1;
+++
+++ /* Double the remainder and see if we went past the divisor */
+++ Remainder <<= 1;
+++ if (Remainder >= Divisor)
+++ {
+++ /* Set the low-bit and calculate the new remainder */
+++ Remainder -= Divisor;
+++ Reciprocal.LowPart |= 1;
+++ }
+++ }
+++
+++ /* Check if we have a remainder */
+++ if (Remainder)
+++ {
+++ /* Check if the current fraction value is too large */
+++ if ((Reciprocal.LowPart == 0xFFFFFFFF) &&
+++ (Reciprocal.HighPart == 0xFFFFFFFF))
+++ {
+++ /* Set the high bit and reduce the bit count */
+++ Reciprocal.LowPart = 0;
+++ Reciprocal.HighPart = 0x80000000;
+++ BitCount--;
+++ }
+++ else
+++ {
+++ /* Check if only the lowest bits got too large */
+++ if (Reciprocal.LowPart == 0xFFFFFFFF)
+++ {
+++ /* Reset them and increase the high bits instead */
+++ Reciprocal.LowPart = 0;
+++ Reciprocal.HighPart++;
+++ }
+++ else
+++ {
+++ /* All is well, increase the low bits */
+++ Reciprocal.LowPart++;
+++ }
+++ }
+++ }
+++
+++ /* Now calculate the actual shift and return the reciprocal */
+++ *Shift = (UCHAR)BitCount - 64;
+++ return Reciprocal;
+++}
+++
+++VOID
+++NTAPI
+++KiInitSpinLocks(IN PKPRCB Prcb,
+++ IN CCHAR Number)
+++{
+++ ULONG i;
+++
+++ /* Initialize Dispatcher Fields */
+++ Prcb->QueueIndex = 1;
+++ Prcb->ReadySummary = 0;
+++ Prcb->DeferredReadyListHead.Next = NULL;
+++ for (i = 0; i < 32; i++)
+++ {
+++ /* Initialize the ready list */
+++ InitializeListHead(&Prcb->DispatcherReadyListHead[i]);
+++ }
+++
+++ /* Initialize DPC Fields */
+++ InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);
+++ KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);
+++ Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;
+++ Prcb->DpcData[DPC_NORMAL].DpcCount = 0;
+++ Prcb->DpcRoutineActive = FALSE;
+++ Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
+++ Prcb->MinimumDpcRate = KiMinimumDpcRate;
+++ Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
+++ KeInitializeDpc(&Prcb->CallDpc, NULL, NULL);
+++ KeSetTargetProcessorDpc(&Prcb->CallDpc, Number);
+++ KeSetImportanceDpc(&Prcb->CallDpc, HighImportance);
+++
+++ /* Initialize the Wait List Head */
+++ InitializeListHead(&Prcb->WaitListHead);
+++
+++ /* Initialize Queued Spinlocks */
+++ Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock;
+++ Prcb->LockQueue[LockQueueExpansionLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL;
+++ Prcb->LockQueue[LockQueuePfnLock].Next = NULL;
+++ Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock;
+++ Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock;
+++ Prcb->LockQueue[LockQueueBcbLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock;
+++ Prcb->LockQueue[LockQueueMasterLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock;
+++ Prcb->LockQueue[LockQueueVacbLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock;
+++ Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock;
+++ Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock;
+++ Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock;
+++ Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock;
+++ Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock;
+++ Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock;
+++ Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock;
+++ Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock;
+++ Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL;
+++ Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
+++ Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;
+++ Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;
+++
+++ /* Loop timer locks */
+++ for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)
+++ {
+++ /* Initialize the lock and setup the Queued Spinlock */
+++ KeInitializeSpinLock(&KiTimerTableLock[i]);
+++ Prcb->LockQueue[i].Next = NULL;
+++ Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];
+++ }
+++
+++ /* Check if this is the boot CPU */
+++ if (!Number)
+++ {
+++ /* Initialize the lock themselves */
+++ KeInitializeSpinLock(&KiDispatcherLock);
+++ KeInitializeSpinLock(&KiReverseStallIpiLock);
+++ KeInitializeSpinLock(&MmPfnLock);
+++ KeInitializeSpinLock(&MmSystemSpaceLock);
+++ KeInitializeSpinLock(&CcBcbSpinLock);
+++ KeInitializeSpinLock(&CcMasterSpinLock);
+++ KeInitializeSpinLock(&CcVacbSpinLock);
+++ KeInitializeSpinLock(&CcWorkQueueSpinLock);
+++ KeInitializeSpinLock(&IopCancelSpinLock);
+++ KeInitializeSpinLock(&IopCompletionLock);
+++ KeInitializeSpinLock(&IopDatabaseLock);
+++ KeInitializeSpinLock(&IopVpbSpinLock);
+++ KeInitializeSpinLock(&NonPagedPoolLock);
+++ KeInitializeSpinLock(&MmNonPagedPoolLock);
+++ KeInitializeSpinLock(&NtfsStructLock);
+++ KeInitializeSpinLock(&AfdWorkQueueSpinLock);
+++ }
+++}
+++
+++BOOLEAN
+++NTAPI
+++KeInitSystem(VOID)
+++{
+++ /* Check if Threaded DPCs are enabled */
+++ if (KeThreadDpcEnable)
+++ {
+++ /* FIXME: TODO */
+++ DPRINT1("Threaded DPCs not yet supported\n");
+++ }
+++
+++ /* Initialize non-portable parts of the kernel */
+++ KiInitMachineDependent();
+++ return TRUE;
+++}
+++
Process->Affinity = Affinity;
Process->BasePriority = (CHAR)Priority;
Process->QuantumReset = 6;
- Process->DirectoryTableBase = DirectoryTableBase;
- Process->AutoAlignment = TRUE;
+ Process->DirectoryTableBase = *DirectoryTableBase;
+ Process->AutoAlignment = Enable;
++#ifdef _M_IX86
- Process->IopmOffset = 0xFFFF;
+ Process->IopmOffset = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
++#endif
/* Initialize the lists */
InitializeListHead(&Process->ThreadListHead);
--- /dev/null
+ /*\r
+ * PROJECT: ReactOS Kernel\r
+ * LICENSE: GPL - See COPYING in the top level directory\r
+ * FILE: ntoskrnl/ke/thrdobj.c\r
+ * PURPOSE: Implements routines to manage the Kernel Thread Object\r
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)\r
+ */\r
+ \r
+ /* INCLUDES ******************************************************************/\r
+ \r
+ #include <ntoskrnl.h>\r
+ #define NDEBUG\r
+ #include <internal/debug.h>\r
+ \r
+ extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];\r
+ extern LIST_ENTRY PspReaperListHead;\r
+ \r
+ ULONG KiMask32Array[MAXIMUM_PRIORITY] =\r
+ {\r
+ 0x1, 0x2, 0x4, 0x8, 0x10, 0x20,\r
+ 0x40, 0x80, 0x100, 0x200, 0x4000, 0x800,\r
+ 0x1000, 0x2000, 0x4000, 0x8000, 0x10000, 0x20000,\r
+ 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000,\r
+ 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000,\r
+ 0x40000000, 0x80000000\r
+ };\r
+ \r
+ /* FUNCTIONS *****************************************************************/\r
+ \r
+ UCHAR\r
+ NTAPI\r
+ KeFindNextRightSetAffinity(IN UCHAR Number,\r
+ IN ULONG Set)\r
+ {\r
+ ULONG Bit, Result;\r
+ ASSERT(Set != 0);\r
+ \r
+ /* Calculate the mask */\r
+ Bit = (AFFINITY_MASK(Number) - 1) & Set;\r
+ \r
+ /* If it's 0, use the one we got */\r
+ if (!Bit) Bit = Set;\r
+ \r
+ /* Now find the right set and return it */\r
+ BitScanReverse(&Result, Bit);\r
+ return (UCHAR)Result;\r
+ }\r
+ \r
+ KPRIORITY\r
+ NTAPI\r
+ KeQueryBasePriorityThread(IN PKTHREAD Thread)\r
+ {\r
+ LONG BaseIncrement;\r
+ KIRQL OldIrql;\r
+ PKPROCESS Process;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Raise IRQL to synch level */\r
+ OldIrql = KeRaiseIrqlToSynchLevel();\r
+ \r
+ /* Lock the thread */\r
+ KiAcquireThreadLock(Thread);\r
+ \r
+ /* Get the Process */\r
+ Process = Thread->ApcStatePointer[0]->Process;\r
+ \r
+ /* Calculate the base increment */\r
+ BaseIncrement = Thread->BasePriority - Process->BasePriority;\r
+ \r
+ /* If saturation occured, return the saturation increment instead */\r
+ if (Thread->Saturation) BaseIncrement = (HIGH_PRIORITY + 1) / 2 *\r
+ Thread->Saturation;\r
+ \r
+ /* Release thread lock */\r
+ KiReleaseThreadLock(Thread);\r
+ \r
+ /* Lower IRQl and return Increment */\r
+ KeLowerIrql(OldIrql);\r
+ return BaseIncrement;\r
+ }\r
+ \r
+ VOID\r
+ NTAPI\r
+ KeReadyThread(IN PKTHREAD Thread)\r
+ {\r
+ KIRQL OldIrql;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Lock the Dispatcher Database */\r
+ OldIrql = KiAcquireDispatcherLock();\r
+ \r
+ /* Make the thread ready */\r
+ KiReadyThread(Thread);\r
+ \r
+ /* Unlock dispatcher database */\r
+ KiReleaseDispatcherLock(OldIrql);\r
+ }\r
+ \r
+ ULONG\r
+ NTAPI\r
+ KeAlertResumeThread(IN PKTHREAD Thread)\r
+ {\r
+ ULONG PreviousCount;\r
+ KLOCK_QUEUE_HANDLE ApcLock;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Lock the Dispatcher Database and the APC Queue */\r
+ KiAcquireApcLock(Thread, &ApcLock);\r
+ KiAcquireDispatcherLockAtDpcLevel();\r
+ \r
+ /* Return if Thread is already alerted. */\r
+ if (!Thread->Alerted[KernelMode])\r
+ {\r
+ /* If it's Blocked, unblock if it we should */\r
+ if ((Thread->State == Waiting) && (Thread->Alertable))\r
+ {\r
+ /* Abort the wait */\r
+ KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);\r
+ }\r
+ else\r
+ {\r
+ /* If not, simply Alert it */\r
+ Thread->Alerted[KernelMode] = TRUE;\r
+ }\r
+ }\r
+ \r
+ /* Save the old Suspend Count */\r
+ PreviousCount = Thread->SuspendCount;\r
+ \r
+ /* If the thread is suspended, decrease one of the suspend counts */\r
+ if (PreviousCount)\r
+ {\r
+ /* Decrease count. If we are now zero, unwait it completely */\r
+ if (--Thread->SuspendCount)\r
+ {\r
+ /* Signal and satisfy */\r
+ Thread->SuspendSemaphore.Header.SignalState++;\r
+ KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);\r
+ }\r
+ }\r
+ \r
+ /* Release Locks and return the Old State */\r
+ KiReleaseDispatcherLockFromDpcLevel();\r
+ KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+ KiExitDispatcher(ApcLock.OldIrql);\r
+ return PreviousCount;\r
+ }\r
+ \r
+ BOOLEAN\r
+ NTAPI\r
+ KeAlertThread(IN PKTHREAD Thread,\r
+ IN KPROCESSOR_MODE AlertMode)\r
+ {\r
+ BOOLEAN PreviousState;\r
+ KLOCK_QUEUE_HANDLE ApcLock;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Lock the Dispatcher Database and the APC Queue */\r
+ KiAcquireApcLock(Thread, &ApcLock);\r
+ KiAcquireDispatcherLockAtDpcLevel();\r
+ \r
+ /* Save the Previous State */\r
+ PreviousState = Thread->Alerted[AlertMode];\r
+ \r
+ /* Check if it's already alerted */\r
+ if (!PreviousState)\r
+ {\r
+ /* Check if the thread is alertable, and blocked in the given mode */\r
+ if ((Thread->State == Waiting) &&\r
+ ((AlertMode == KernelMode) || (Thread->WaitMode == AlertMode)) &&\r
+ (Thread->Alertable))\r
+ {\r
+ /* Abort the wait to alert the thread */\r
+ KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);\r
+ }\r
+ else\r
+ {\r
+ /* Otherwise, merely set the alerted state */\r
+ Thread->Alerted[AlertMode] = TRUE;\r
+ }\r
+ }\r
+ \r
+ /* Release the Dispatcher Lock */\r
+ KiReleaseDispatcherLockFromDpcLevel();\r
+ KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+ KiExitDispatcher(ApcLock.OldIrql);\r
+ \r
+ /* Return the old state */\r
+ return PreviousState;\r
+ }\r
+ \r
+ ULONG\r
+ NTAPI\r
+ KeForceResumeThread(IN PKTHREAD Thread)\r
+ {\r
+ KLOCK_QUEUE_HANDLE ApcLock;\r
+ ULONG PreviousCount;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Lock the APC Queue */\r
+ KiAcquireApcLock(Thread, &ApcLock);\r
+ \r
+ /* Save the old Suspend Count */\r
+ PreviousCount = Thread->SuspendCount + Thread->FreezeCount;\r
+ \r
+ /* If the thread is suspended, wake it up!!! */\r
+ if (PreviousCount)\r
+ {\r
+ /* Unwait it completely */\r
+ Thread->SuspendCount = 0;\r
+ Thread->FreezeCount = 0;\r
+ \r
+ /* Lock the dispatcher */\r
+ KiAcquireDispatcherLockAtDpcLevel();\r
+ \r
+ /* Signal and satisfy */\r
+ Thread->SuspendSemaphore.Header.SignalState++;\r
+ KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);\r
+ \r
+ /* Release the dispatcher */\r
+ KiReleaseDispatcherLockFromDpcLevel();\r
+ }\r
+ \r
+ /* Release Lock and return the Old State */\r
+ KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+ KiExitDispatcher(ApcLock.OldIrql);\r
+ return PreviousCount;\r
+ }\r
+ \r
+ /*\r
+ * Used by the debugging code to freeze all the process's threads\r
+ * while the debugger is examining their state.\r
+ */\r
+ VOID\r
+ NTAPI\r
+ KeFreezeAllThreads(IN PKPROCESS Process)\r
+ {\r
+ KLOCK_QUEUE_HANDLE LockHandle, ApcLock;\r
+ PKTHREAD Current, CurrentThread = KeGetCurrentThread();\r
+ PLIST_ENTRY ListHead, NextEntry;\r
+ LONG OldCount;\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Lock the process */\r
+ KiAcquireProcessLock(Process, &LockHandle);\r
+ \r
+ /* If someone is already trying to free us, try again */\r
+ while (CurrentThread->FreezeCount)\r
+ {\r
+ /* Release and re-acquire the process lock so the APC will go through */\r
+ KiReleaseProcessLock(&LockHandle);\r
+ KiAcquireProcessLock(Process, &LockHandle);\r
+ }\r
+ \r
+ /* Enter a critical region */\r
+ KeEnterCriticalRegion();\r
+ \r
+ /* Loop the Process's Threads */\r
+ ListHead = &Process->ThreadListHead;\r
+ NextEntry = ListHead->Flink;\r
+ while (NextEntry != ListHead)\r
+ {\r
+ /* Get the current thread */\r
+ Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);\r
+ \r
+ /* Lock it */\r
+ KiAcquireApcLockAtDpcLevel(Current, &ApcLock);\r
+ \r
+ /* Make sure it's not ours, and check if APCs are enabled */\r
+ if ((Current != CurrentThread) && (Current->ApcQueueable))\r
+ {\r
+ /* Sanity check */\r
+ OldCount = Current->SuspendCount;\r
+ ASSERT(OldCount != MAXIMUM_SUSPEND_COUNT);\r
+ \r
+ /* Increase the freeze count */\r
+ Current->FreezeCount++;\r
+ \r
+ /* Make sure it wasn't already suspended */\r
+ if (!(OldCount) && !(Current->SuspendCount))\r
+ {\r
+ /* Did we already insert it? */\r
+ if (!Current->SuspendApc.Inserted)\r
+ {\r
+ /* Insert the APC */\r
+ Current->SuspendApc.Inserted = TRUE;\r
+ KiInsertQueueApc(&Current->SuspendApc, IO_NO_INCREMENT);\r
+ }\r
+ else\r
+ {\r
+ /* Lock the dispatcher */\r
+ KiAcquireDispatcherLockAtDpcLevel();\r
+ \r
+ /* Unsignal the semaphore, the APC was already inserted */\r
+ Current->SuspendSemaphore.Header.SignalState--;\r
+ \r
+ /* Release the dispatcher */\r
+ KiReleaseDispatcherLockFromDpcLevel();\r
+ }\r
+ }\r
+ }\r
+ \r
+ /* Release the APC lock */\r
+ KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+ }\r
+ \r
+ /* Release the process lock and exit the dispatcher */\r
+ KiReleaseProcessLock(&LockHandle);\r
+ KiExitDispatcher(LockHandle.OldIrql);\r
+ }\r
+ \r
+ ULONG\r
+ NTAPI\r
+ KeResumeThread(IN PKTHREAD Thread)\r
+ {\r
+ KLOCK_QUEUE_HANDLE ApcLock;\r
+ ULONG PreviousCount;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Lock the APC Queue */\r
+ KiAcquireApcLock(Thread, &ApcLock);\r
+ \r
+ /* Save the Old Count */\r
+ PreviousCount = Thread->SuspendCount;\r
+ \r
+ /* Check if it existed */\r
+ if (PreviousCount)\r
+ {\r
+ /* Decrease the suspend count */\r
+ Thread->SuspendCount--;\r
+ \r
+ /* Check if the thrad is still suspended or not */\r
+ if ((!Thread->SuspendCount) && (!Thread->FreezeCount))\r
+ {\r
+ /* Acquire the dispatcher lock */\r
+ KiAcquireDispatcherLockAtDpcLevel();\r
+ \r
+ /* Signal the Suspend Semaphore */\r
+ Thread->SuspendSemaphore.Header.SignalState++;\r
+ KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);\r
+ \r
+ /* Release the dispatcher lock */\r
+ KiReleaseDispatcherLockFromDpcLevel();\r
+ }\r
+ }\r
+ \r
+ /* Release APC Queue lock and return the Old State */\r
+ KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+ KiExitDispatcher(ApcLock.OldIrql);\r
+ return PreviousCount;\r
+ }\r
+ \r
+ VOID\r
+ NTAPI\r
+ KeRundownThread(VOID)\r
+ {\r
+ KIRQL OldIrql;\r
+ PKTHREAD Thread = KeGetCurrentThread();\r
+ PLIST_ENTRY NextEntry, ListHead;\r
+ PKMUTANT Mutant;\r
+ \r
+ /* Optimized path if nothing is on the list at the moment */\r
+ if (IsListEmpty(&Thread->MutantListHead)) return;\r
+ \r
+ /* Lock the Dispatcher Database */\r
+ OldIrql = KiAcquireDispatcherLock();\r
+ \r
+ /* Get the List Pointers */\r
+ ListHead = &Thread->MutantListHead;\r
+ NextEntry = ListHead->Flink;\r
+ while (NextEntry != ListHead)\r
+ {\r
+ /* Get the Mutant */\r
+ Mutant = CONTAINING_RECORD(NextEntry, KMUTANT, MutantListEntry);\r
+ \r
+ /* Make sure it's not terminating with APCs off */\r
+ if (Mutant->ApcDisable)\r
+ {\r
+ /* Bugcheck the system */\r
+ KEBUGCHECKEX(0, //THREAD_TERMINATE_HELD_MUTEX,\r
+ (ULONG_PTR)Thread,\r
+ (ULONG_PTR)Mutant,\r
+ 0,\r
+ 0);\r
+ }\r
+ \r
+ /* Now we can remove it */\r
+ RemoveEntryList(&Mutant->MutantListEntry);\r
+ \r
+ /* Unconditionally abandon it */\r
+ Mutant->Header.SignalState = 1;\r
+ Mutant->Abandoned = TRUE;\r
+ Mutant->OwnerThread = NULL;\r
+ \r
+ /* Check if the Wait List isn't empty */\r
+ if (!IsListEmpty(&Mutant->Header.WaitListHead))\r
+ {\r
+ /* Wake the Mutant */\r
+ KiWaitTest(&Mutant->Header, MUTANT_INCREMENT);\r
+ }\r
+ \r
+ /* Move on */\r
+ NextEntry = NextEntry->Flink;\r
+ }\r
+ \r
+ /* Release the Lock */\r
+ KiReleaseDispatcherLock(OldIrql);\r
+ }\r
+ \r
+ VOID\r
+ NTAPI\r
+ KeStartThread(IN OUT PKTHREAD Thread)\r
+ {\r
+ KLOCK_QUEUE_HANDLE LockHandle;\r
+ #ifdef CONFIG_SMP\r
+ PKNODE Node;\r
+ PKPRCB NodePrcb;\r
+ ULONG Set, Mask;\r
+ #endif\r
+ UCHAR IdealProcessor = 0;\r
+ PKPROCESS Process = Thread->ApcState.Process;\r
+ \r
+ /* Setup static fields from parent */\r
+++#ifdef _M_IX86\r
+ Thread->Iopl = Process->Iopl;\r
+++#endif\r
+ Thread->Quantum = Process->QuantumReset;\r
+ Thread->QuantumReset = Process->QuantumReset;\r
+ Thread->SystemAffinityActive = FALSE;\r
+ \r
+ /* Lock the process */\r
+ KiAcquireProcessLock(Process, &LockHandle);\r
+ \r
+ /* Setup volatile data */\r
+ Thread->Priority = Process->BasePriority;\r
+ Thread->BasePriority = Process->BasePriority;\r
+ Thread->Affinity = Process->Affinity;\r
+ Thread->UserAffinity = Process->Affinity;\r
+ \r
+ #ifdef CONFIG_SMP\r
+ /* Get the KNODE and its PRCB */\r
+ Node = KeNodeBlock[Process->IdealNode];\r
+ NodePrcb = (PKPRCB)(KPCR_BASE + (Process->ThreadSeed * PAGE_SIZE));\r
+ \r
+ /* Calculate affinity mask */\r
+ Set = ~NodePrcb->MultiThreadProcessorSet;\r
+ Mask = (ULONG)(Node->ProcessorMask & Process->Affinity);\r
+ Set &= Mask;\r
+ if (Set) Mask = Set;\r
+ \r
+ /* Get the new thread seed */\r
+ IdealProcessor = KeFindNextRightSetAffinity(Process->ThreadSeed, Mask);\r
+ Process->ThreadSeed = IdealProcessor;\r
+ \r
+ /* Sanity check */\r
+ ASSERT((Thread->UserAffinity & AFFINITY_MASK(IdealProcessor)));\r
+ #endif\r
+ \r
+ /* Set the Ideal Processor */\r
+ Thread->IdealProcessor = IdealProcessor;\r
+ Thread->UserIdealProcessor = IdealProcessor;\r
+ \r
+ /* Lock the Dispatcher Database */\r
+ KiAcquireDispatcherLockAtDpcLevel();\r
+ \r
+ /* Insert the thread into the process list */\r
+ InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);\r
+ \r
+ /* Increase the stack count */\r
+ ASSERT(Process->StackCount != MAXULONG_PTR);\r
+ Process->StackCount++;\r
+ \r
+ /* Release locks and return */\r
+ KiReleaseDispatcherLockFromDpcLevel();\r
+ KiReleaseProcessLock(&LockHandle);\r
+ }\r
+ \r
+ VOID\r
+ NTAPI\r
+ KiSuspendRundown(IN PKAPC Apc)\r
+ {\r
+ /* Does nothing */\r
+ UNREFERENCED_PARAMETER(Apc);\r
+ }\r
+ \r
+ VOID\r
+ NTAPI\r
+ KiSuspendNop(IN PKAPC Apc,\r
+ IN PKNORMAL_ROUTINE *NormalRoutine,\r
+ IN PVOID *NormalContext,\r
+ IN PVOID *SystemArgument1,\r
+ IN PVOID *SystemArgument2)\r
+ {\r
+ /* Does nothing */\r
+ UNREFERENCED_PARAMETER(Apc);\r
+ UNREFERENCED_PARAMETER(NormalRoutine);\r
+ UNREFERENCED_PARAMETER(NormalContext);\r
+ UNREFERENCED_PARAMETER(SystemArgument1);\r
+ UNREFERENCED_PARAMETER(SystemArgument2);\r
+ }\r
+ \r
+ VOID\r
+ NTAPI\r
+ KiSuspendThread(IN PVOID NormalContext,\r
+ IN PVOID SystemArgument1,\r
+ IN PVOID SystemArgument2)\r
+ {\r
+ /* Non-alertable kernel-mode suspended wait */\r
+ KeWaitForSingleObject(&KeGetCurrentThread()->SuspendSemaphore,\r
+ Suspended,\r
+ KernelMode,\r
+ FALSE,\r
+ NULL);\r
+ }\r
+ \r
+ NTSTATUS\r
+ NTAPI\r
+ KeSuspendThread(PKTHREAD Thread)\r
+ {\r
+ KLOCK_QUEUE_HANDLE ApcLock;\r
+ ULONG PreviousCount;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Lock the APC Queue */\r
+ KiAcquireApcLock(Thread, &ApcLock);\r
+ \r
+ /* Save the Old Count */\r
+ PreviousCount = Thread->SuspendCount;\r
+ \r
+ /* Handle the maximum */\r
+ if (PreviousCount == MAXIMUM_SUSPEND_COUNT)\r
+ {\r
+ /* Raise an exception */\r
+ KiReleaseApcLock(&ApcLock);\r
+ RtlRaiseStatus(STATUS_SUSPEND_COUNT_EXCEEDED);\r
+ }\r
+ \r
+ /* Should we bother to queue at all? */\r
+ if (Thread->ApcQueueable)\r
+ {\r
+ /* Increment the suspend count */\r
+ Thread->SuspendCount++;\r
+ \r
+ /* Check if we should suspend it */\r
+ if (!(PreviousCount) && !(Thread->FreezeCount))\r
+ {\r
+ /* Is the APC already inserted? */\r
+ if (!Thread->SuspendApc.Inserted)\r
+ {\r
+ /* Not inserted, insert it */\r
+ Thread->SuspendApc.Inserted = TRUE;\r
+ KiInsertQueueApc(&Thread->SuspendApc, IO_NO_INCREMENT);\r
+ }\r
+ else\r
+ {\r
+ /* Lock the dispatcher */\r
+ KiAcquireDispatcherLockAtDpcLevel();\r
+ \r
+ /* Unsignal the semaphore, the APC was already inserted */\r
+ Thread->SuspendSemaphore.Header.SignalState--;\r
+ \r
+ /* Release the dispatcher */\r
+ KiReleaseDispatcherLockFromDpcLevel();\r
+ }\r
+ }\r
+ }\r
+ \r
+ /* Release Lock and return the Old State */\r
+ KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+ KiExitDispatcher(ApcLock.OldIrql);\r
+ return PreviousCount;\r
+ }\r
+ \r
+ BOOLEAN\r
+ NTAPI\r
+ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)\r
+ {\r
+ PKTHREAD Thread = KeGetCurrentThread();\r
+ BOOLEAN OldState;\r
+ KLOCK_QUEUE_HANDLE ApcLock;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Lock the Dispatcher Database and the APC Queue */\r
+ KiAcquireApcLock(Thread, &ApcLock);\r
+ KiAcquireDispatcherLockAtDpcLevel();\r
+ \r
+ /* Save the old State */\r
+ OldState = Thread->Alerted[AlertMode];\r
+ \r
+ /* Check the Thread is alerted */\r
+ if (OldState)\r
+ {\r
+ /* Disable alert for this mode */\r
+ Thread->Alerted[AlertMode] = FALSE;\r
+ }\r
+ else if ((AlertMode != KernelMode) &&\r
+ (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))\r
+ {\r
+ /* If the mode is User and the Queue isn't empty, set Pending */\r
+ Thread->ApcState.UserApcPending = TRUE;\r
+ }\r
+ \r
+ /* Release Locks and return the Old State */\r
+ KiReleaseDispatcherLockFromDpcLevel();\r
+ KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+ KiExitDispatcher(ApcLock.OldIrql);\r
+ return OldState;\r
+ }\r
+ \r
+ NTSTATUS\r
+ NTAPI\r
+ KeInitThread(IN OUT PKTHREAD Thread,\r
+ IN PVOID KernelStack,\r
+ IN PKSYSTEM_ROUTINE SystemRoutine,\r
+ IN PKSTART_ROUTINE StartRoutine,\r
+ IN PVOID StartContext,\r
+ IN PCONTEXT Context,\r
+ IN PVOID Teb,\r
+ IN PKPROCESS Process)\r
+ {\r
+ BOOLEAN AllocatedStack = FALSE;\r
+ ULONG i;\r
+ PKWAIT_BLOCK TimerWaitBlock;\r
+ PKTIMER Timer;\r
+ NTSTATUS Status;\r
+ \r
+ /* Initalize the Dispatcher Header */\r
+ KeInitializeDispatcherHeader(&Thread->DispatcherHeader,\r
+ ThreadObject,\r
+ sizeof(KTHREAD) / sizeof(LONG),\r
+ FALSE);\r
+ \r
+ /* Initialize the Mutant List */\r
+ InitializeListHead(&Thread->MutantListHead);\r
+ \r
+ /* Initialize the wait blocks */\r
+ for (i = 0; i< (THREAD_WAIT_OBJECTS + 1); i++)\r
+ {\r
+ /* Put our pointer */\r
+ Thread->WaitBlock[i].Thread = Thread;\r
+ }\r
+ \r
+ /* Set swap settings */\r
+ Thread->EnableStackSwap = FALSE;//TRUE;\r
+ Thread->IdealProcessor = 1;\r
+ Thread->SwapBusy = FALSE;\r
+ Thread->AdjustReason = 0;\r
+ \r
+ /* Initialize the lock */\r
+ KeInitializeSpinLock(&Thread->ThreadLock);\r
+ \r
+ /* Setup the Service Descriptor Table for Native Calls */\r
+ Thread->ServiceTable = KeServiceDescriptorTable;\r
+ \r
+ /* Setup APC Fields */\r
+ InitializeListHead(&Thread->ApcState.ApcListHead[0]);\r
+ InitializeListHead(&Thread->ApcState.ApcListHead[1]);\r
+ Thread->ApcState.Process = Process;\r
+ Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;\r
+ Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;\r
+ Thread->ApcStateIndex = OriginalApcEnvironment;\r
+ Thread->ApcQueueable = TRUE;\r
+ KeInitializeSpinLock(&Thread->ApcQueueLock);\r
+ \r
+ /* Initialize the Suspend APC */\r
+ KeInitializeApc(&Thread->SuspendApc,\r
+ Thread,\r
+ OriginalApcEnvironment,\r
+ KiSuspendNop,\r
+ KiSuspendRundown,\r
+ KiSuspendThread,\r
+ KernelMode,\r
+ NULL);\r
+ \r
+ /* Initialize the Suspend Semaphore */\r
+ KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 2);\r
+ \r
+ /* Setup the timer */\r
+ Timer = &Thread->Timer;\r
+ KeInitializeTimer(Timer);\r
+ TimerWaitBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];\r
+ TimerWaitBlock->Object = Timer;\r
+ TimerWaitBlock->WaitKey = STATUS_TIMEOUT;\r
+ TimerWaitBlock->WaitType = WaitAny;\r
+ TimerWaitBlock->NextWaitBlock = NULL;\r
+ \r
+ /* Link the two wait lists together */\r
+ TimerWaitBlock->WaitListEntry.Flink = &Timer->Header.WaitListHead;\r
+ TimerWaitBlock->WaitListEntry.Blink = &Timer->Header.WaitListHead;\r
+ \r
+ /* Set the TEB */\r
+ Thread->Teb = Teb;\r
+ \r
+ /* Check if we have a kernel stack */\r
+ if (!KernelStack)\r
+ {\r
+ /* We don't, allocate one */\r
+ KernelStack = (PVOID)((ULONG_PTR)MmCreateKernelStack(FALSE) +\r
+ KERNEL_STACK_SIZE);\r
+ if (!KernelStack) return STATUS_INSUFFICIENT_RESOURCES;\r
+ \r
+ /* Remember for later */\r
+ AllocatedStack = TRUE;\r
+ }\r
+ \r
+ /* Set the Thread Stacks */\r
+ Thread->InitialStack = (PCHAR)KernelStack;\r
+ Thread->StackBase = (PCHAR)KernelStack;\r
+ Thread->StackLimit = (ULONG_PTR)KernelStack - KERNEL_STACK_SIZE;\r
+ Thread->KernelStackResident = TRUE;\r
+ \r
+ /* ROS Mm HACK */\r
+ MmUpdatePageDir((PEPROCESS)Process,\r
+ (PVOID)Thread->StackLimit,\r
+ KERNEL_STACK_SIZE);\r
+ MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));\r
+ \r
+ /* Enter SEH to avoid crashes due to user mode */\r
+ Status = STATUS_SUCCESS;\r
+ _SEH_TRY\r
+ {\r
+ /* Initalize the Thread Context */\r
+++#ifdef _M_IX86\r
+ Ke386InitThreadWithContext(Thread,\r
+ SystemRoutine,\r
+ StartRoutine,\r
+ StartContext,\r
+ Context);\r
+++#endif\r
+ }\r
+ _SEH_HANDLE\r
+ {\r
+ /* Set failure status */\r
+ Status = STATUS_UNSUCCESSFUL;\r
+ \r
+ /* Check if a stack was allocated */\r
+ if (AllocatedStack)\r
+ {\r
+ /* Delete the stack */\r
+ MmDeleteKernelStack(Thread->StackBase, FALSE);\r
+ Thread->InitialStack = NULL;\r
+ }\r
+ }\r
+ _SEH_END;\r
+ \r
+ /* Set the Thread to initalized */\r
+ Thread->State = Initialized;\r
+ return Status;\r
+ }\r
+ \r
+ VOID\r
+ NTAPI\r
+ KeInitializeThread(IN PKPROCESS Process,\r
+ IN OUT PKTHREAD Thread,\r
+ IN PKSYSTEM_ROUTINE SystemRoutine,\r
+ IN PKSTART_ROUTINE StartRoutine,\r
+ IN PVOID StartContext,\r
+ IN PCONTEXT Context,\r
+ IN PVOID Teb,\r
+ IN PVOID KernelStack)\r
+ {\r
+ /* Initailize and start the thread on success */\r
+ if (NT_SUCCESS(KeInitThread(Thread,\r
+ KernelStack,\r
+ SystemRoutine,\r
+ StartRoutine,\r
+ StartContext,\r
+ Context,\r
+ Teb,\r
+ Process)))\r
+ {\r
+ /* Start it */\r
+ KeStartThread(Thread);\r
+ }\r
+ }\r
+ \r
+ VOID\r
+ NTAPI\r
+ KeUninitThread(IN PKTHREAD Thread)\r
+ {\r
+ /* Delete the stack */\r
+ MmDeleteKernelStack(Thread->StackBase, FALSE);\r
+ Thread->InitialStack = NULL;\r
+ }\r
+ \r
+ /* PUBLIC FUNCTIONS **********************************************************/\r
+ \r
+ /*\r
+ * @unimplemented\r
+ */\r
+ VOID\r
+ NTAPI\r
+ KeCapturePersistentThreadState(IN PVOID CurrentThread,\r
+ IN ULONG Setting1,\r
+ IN ULONG Setting2,\r
+ IN ULONG Setting3,\r
+ IN ULONG Setting4,\r
+ IN ULONG Setting5,\r
+ IN PVOID ThreadState)\r
+ {\r
+ UNIMPLEMENTED;\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ #undef KeGetCurrentThread\r
+ PKTHREAD\r
+ NTAPI\r
+ KeGetCurrentThread(VOID)\r
+ {\r
+++#ifdef _M_IX86\r
+ /* Return the current thread on this PCR */\r
+ return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;\r
+++#elif defined(_M_PPC)\r
+++ return KeGetCurrentKPCR()->Prcb->CurrentThread;\r
+++#endif\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ KPROCESSOR_MODE\r
+ NTAPI\r
+ KeGetPreviousMode(VOID)\r
+ {\r
+ /* Return the previous mode of this thread */\r
+ return KeGetCurrentThread()->PreviousMode;\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ ULONG\r
+ NTAPI\r
+ KeQueryRuntimeThread(IN PKTHREAD Thread,\r
+ OUT PULONG UserTime)\r
+ {\r
+ ASSERT_THREAD(Thread);\r
+ \r
+ /* Return the User Time */\r
+ *UserTime = Thread->UserTime;\r
+ \r
+ /* Return the Kernel Time */\r
+ return Thread->KernelTime;\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ BOOLEAN\r
+ NTAPI\r
+ KeSetKernelStackSwapEnable(IN BOOLEAN Enable)\r
+ {\r
+ BOOLEAN PreviousState;\r
+ PKTHREAD Thread = KeGetCurrentThread();\r
+ \r
+ /* Save Old State */\r
+ PreviousState = Thread->EnableStackSwap;\r
+ \r
+ /* Set New State */\r
+ Thread->EnableStackSwap = Enable;\r
+ \r
+ /* Return Old State */\r
+ return PreviousState;\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ KPRIORITY\r
+ NTAPI\r
+ KeQueryPriorityThread(IN PKTHREAD Thread)\r
+ {\r
+ ASSERT_THREAD(Thread);\r
+ \r
+ /* Return the current priority */\r
+ return Thread->Priority;\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ VOID\r
+ NTAPI\r
+ KeRevertToUserAffinityThread(VOID)\r
+ {\r
+ KIRQL OldIrql;\r
+ PKPRCB Prcb;\r
+ PKTHREAD NextThread, CurrentThread = KeGetCurrentThread();\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ ASSERT(CurrentThread->SystemAffinityActive != FALSE);\r
+ \r
+ /* Lock the Dispatcher Database */\r
+ OldIrql = KiAcquireDispatcherLock();\r
+ \r
+ /* Set the user affinity and processor and disable system affinity */\r
+ CurrentThread->Affinity = CurrentThread->UserAffinity;\r
+ CurrentThread->IdealProcessor = CurrentThread->UserIdealProcessor;\r
+ CurrentThread->SystemAffinityActive = FALSE;\r
+ \r
+ /* Get the current PRCB and check if it doesn't match this affinity */\r
+ Prcb = KeGetCurrentPrcb();\r
+ if (!(Prcb->SetMember & CurrentThread->Affinity))\r
+ {\r
+ /* Lock the PRCB */\r
+ KiAcquirePrcbLock(Prcb);\r
+ \r
+ #ifdef NEW_SCHEDULER\r
+ /* Check if there's no next thread scheduled */\r
+ if (!Prcb->NextThread)\r
+ {\r
+ /* Select a new thread and set it on standby */\r
+ NextThread = KiSelectNextThread(Prcb);\r
+ NextThread->State = Standby;\r
+ Prcb->NextThread = NextThread;\r
+ }\r
+ #else\r
+ /* We need to dispatch a new thread */\r
+ NextThread = NULL;\r
+ CurrentThread->WaitIrql = OldIrql;\r
+ KiDispatchThreadNoLock(Ready);\r
+ KeLowerIrql(OldIrql);\r
+ return;\r
+ #endif\r
+ \r
+ /* Release the PRCB lock */\r
+ KiReleasePrcbLock(Prcb);\r
+ }\r
+ \r
+ /* Unlock dispatcher database */\r
+ KiReleaseDispatcherLock(OldIrql);\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ UCHAR\r
+ NTAPI\r
+ KeSetIdealProcessorThread(IN PKTHREAD Thread,\r
+ IN UCHAR Processor)\r
+ {\r
+ CCHAR OldIdealProcessor;\r
+ KIRQL OldIrql;\r
+ ASSERT(Processor <= MAXIMUM_PROCESSORS);\r
+ \r
+ /* Lock the Dispatcher Database */\r
+ OldIrql = KiAcquireDispatcherLock();\r
+ \r
+ /* Save Old Ideal Processor */\r
+ OldIdealProcessor = Thread->UserIdealProcessor;\r
+ \r
+ /* Make sure a valid CPU was given */\r
+ if (Processor < MAXIMUM_PROCESSORS)\r
+ {\r
+ /* Check if the user ideal CPU is in the affinity */\r
+ if (Thread->UserIdealProcessor & AFFINITY_MASK(Processor))\r
+ {\r
+ /* Set the ideal processor */\r
+ Thread->IdealProcessor = Processor;\r
+ \r
+ /* Check if system affinity is used */\r
+ if (!Thread->SystemAffinityActive)\r
+ {\r
+ /* It's not, so update the user CPU too */\r
+ Thread->UserIdealProcessor = Processor;\r
+ }\r
+ }\r
+ }\r
+ \r
+ /* Release dispatcher lock and return the old ideal CPU */\r
+ KiReleaseDispatcherLock(OldIrql);\r
+ return OldIdealProcessor;\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ VOID\r
+ NTAPI\r
+ KeSetSystemAffinityThread(IN KAFFINITY Affinity)\r
+ {\r
+ KIRQL OldIrql;\r
+ PKPRCB Prcb;\r
+ PKTHREAD NextThread, CurrentThread = KeGetCurrentThread();\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ ASSERT((Affinity & KeActiveProcessors) != 0);\r
+ \r
+ /* Lock the Dispatcher Database */\r
+ OldIrql = KiAcquireDispatcherLock();\r
+ \r
+ /* Restore the affinity and enable system affinity */\r
+ CurrentThread->Affinity = Affinity;\r
+ CurrentThread->SystemAffinityActive = TRUE;\r
+ \r
+ /* Check if the ideal processor is part of the affinity */\r
+ #ifdef CONFIG_SMP\r
+ if (!(Affinity & AFFINITY_MASK(CurrentThread->IdealProcessor)))\r
+ {\r
+ ULONG AffinitySet, NodeMask;\r
+ \r
+ /* It's not! Get the PRCB */\r
+ Prcb = KiProcessorBlock[CurrentThread->IdealProcessor];\r
+ \r
+ /* Calculate the affinity set */\r
+ AffinitySet = KeActiveProcessors & Affinity;\r
+ NodeMask = Prcb->ParentNode->ProcessorMask & AffinitySet;\r
+ if (NodeMask)\r
+ {\r
+ /* Use the Node set instead */\r
+ AffinitySet = NodeMask;\r
+ }\r
+ \r
+ /* Calculate the ideal CPU from the affinity set */\r
+ BitScanReverse(&NodeMask, AffinitySet);\r
+ CurrentThread->IdealProcessor = (UCHAR)NodeMask;\r
+ }\r
+ #endif\r
+ \r
+ /* Get the current PRCB and check if it doesn't match this affinity */\r
+ Prcb = KeGetCurrentPrcb();\r
+ if (!(Prcb->SetMember & CurrentThread->Affinity))\r
+ {\r
+ /* Lock the PRCB */\r
+ KiAcquirePrcbLock(Prcb);\r
+ \r
+ #ifdef NEW_SCHEDULER\r
+ /* Check if there's no next thread scheduled */\r
+ if (!Prcb->NextThread)\r
+ {\r
+ /* Select a new thread and set it on standby */\r
+ NextThread = KiSelectNextThread(Prcb);\r
+ NextThread->State = Standby;\r
+ Prcb->NextThread = NextThread;\r
+ }\r
+ #else\r
+ /* We need to dispatch a new thread */\r
+ NextThread = NULL;\r
+ CurrentThread->WaitIrql = OldIrql;\r
+ KiDispatchThreadNoLock(Ready);\r
+ KeLowerIrql(OldIrql);\r
+ return;\r
+ #endif\r
+ \r
+ /* Release the PRCB lock */\r
+ KiReleasePrcbLock(Prcb);\r
+ }\r
+ \r
+ /* Unlock dispatcher database */\r
+ KiReleaseDispatcherLock(OldIrql);\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ LONG\r
+ NTAPI\r
+ KeSetBasePriorityThread(IN PKTHREAD Thread,\r
+ IN LONG Increment)\r
+ {\r
+ KIRQL OldIrql;\r
+ KPRIORITY OldBasePriority, Priority, BasePriority;\r
+ LONG OldIncrement;\r
+ PKPROCESS Process;\r
+ BOOLEAN Released;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Get the process */\r
+ Process = Thread->ApcState.Process;\r
+ \r
+ /* Lock the Dispatcher Database */\r
+ OldIrql = KiAcquireDispatcherLock();\r
+ \r
+ /* Lock the thread */\r
+ KiAcquireThreadLock(Thread);\r
+ \r
+ /* Save the old base priority and increment */\r
+ OldBasePriority = Thread->BasePriority;\r
+ OldIncrement = OldBasePriority - Process->BasePriority;\r
+ \r
+ /* If priority saturation happened, use the saturated increment */\r
+ if (Thread->Saturation) OldIncrement = (HIGH_PRIORITY + 1) / 2 *\r
+ Thread->Saturation;\r
+ \r
+ /* Now check if saturation is being used for the new value */\r
+ if (abs(Increment) >= ((HIGH_PRIORITY + 1) / 2))\r
+ {\r
+ /* Check if we need positive or negative saturation */\r
+ Thread->Saturation = (Increment > 0) ? 1 : -1;\r
+ }\r
+ \r
+ /* Normalize the Base Priority */\r
+ BasePriority = Process->BasePriority + Increment;\r
+ if (Process->BasePriority >= LOW_REALTIME_PRIORITY)\r
+ {\r
+ /* Check if it's too low */\r
+ if (BasePriority < LOW_REALTIME_PRIORITY)\r
+ {\r
+ /* Set it to the lowest real time level */\r
+ BasePriority = LOW_REALTIME_PRIORITY;\r
+ }\r
+ \r
+ /* Check if it's too high */\r
+ if (BasePriority > HIGH_PRIORITY) BasePriority = HIGH_PRIORITY;\r
+ \r
+ /* We are at real time, so use the raw base priority */\r
+ Priority = BasePriority;\r
+ }\r
+ else\r
+ {\r
+ /* Check if it's entering the real time range */\r
+ if (BasePriority >= LOW_REALTIME_PRIORITY)\r
+ {\r
+ /* Set it to the highest dynamic level */\r
+ BasePriority = LOW_REALTIME_PRIORITY - 1;\r
+ }\r
+ \r
+ /* Check if it's too low and normalize it */\r
+ if (BasePriority <= LOW_PRIORITY) BasePriority = 1;\r
+ \r
+ /* Check if Saturation is used */\r
+ if (Thread->Saturation)\r
+ {\r
+ /* Use the raw base priority */\r
+ Priority = BasePriority;\r
+ }\r
+ else\r
+ {\r
+ /* Otherwise, calculate the new priority */\r
+ Priority = KiComputeNewPriority(Thread);\r
+ \r
+ /* Check if it entered the real-time range */\r
+ if (Priority >= LOW_REALTIME_PRIORITY)\r
+ {\r
+ /* Normalize it down to the highest dynamic priority */\r
+ Priority = LOW_REALTIME_PRIORITY - 1;\r
+ }\r
+ }\r
+ }\r
+ \r
+ /* Finally set the new base priority */\r
+ Thread->BasePriority = (SCHAR)BasePriority;\r
+ \r
+ /* Reset the decrements */\r
+ Thread->PriorityDecrement = 0;\r
+ \r
+ /* Check if we're changing priority after all */\r
+ if (Priority != Thread->Priority)\r
+ {\r
+ /* Reset the quantum and do the actual priority modification */\r
+ Thread->Quantum = Thread->QuantumReset;\r
+ KiSetPriorityThread(Thread, Priority, &Released);\r
+ }\r
+ \r
+ /* Release thread lock */\r
+ KiReleaseThreadLock(Thread);\r
+ \r
+ /* Check if lock was released */\r
+ if (!Released)\r
+ {\r
+ /* Release the dispatcher database */\r
+ KiReleaseDispatcherLock(OldIrql);\r
+ }\r
+ else\r
+ {\r
+ /* Lower IRQL only */\r
+ KeLowerIrql(OldIrql);\r
+ }\r
+ \r
+ /* Return old increment */\r
+ return OldIncrement;\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ KAFFINITY\r
+ NTAPI\r
+ KeSetAffinityThread(IN PKTHREAD Thread,\r
+ IN KAFFINITY Affinity)\r
+ {\r
+ KIRQL OldIrql;\r
+ KAFFINITY OldAffinity;\r
+ BOOLEAN Released;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Lock the dispatcher database */\r
+ OldIrql = KiAcquireDispatcherLock();\r
+ \r
+ /* Call the internal function */\r
+ OldAffinity = KiSetAffinityThread(Thread, Affinity, &Released);\r
+ \r
+ /* Check if lock was released */\r
+ if (!Released)\r
+ {\r
+ /* Release the dispatcher database */\r
+ KiReleaseDispatcherLock(OldIrql);\r
+ }\r
+ else\r
+ {\r
+ /* Lower IRQL only */\r
+ KeLowerIrql(OldIrql);\r
+ }\r
+ \r
+ /* Return old affinity */\r
+ return OldAffinity;\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ KPRIORITY\r
+ NTAPI\r
+ KeSetPriorityThread(IN PKTHREAD Thread,\r
+ IN KPRIORITY Priority)\r
+ {\r
+ KIRQL OldIrql;\r
+ KPRIORITY OldPriority;\r
+ BOOLEAN Released;\r
+ ASSERT_THREAD(Thread);\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ ASSERT((Priority <= HIGH_PRIORITY) && (Priority >= LOW_PRIORITY));\r
+ \r
+ /* Lock the Dispatcher Database */\r
+ OldIrql = KiAcquireDispatcherLock();\r
+ \r
+ /* Lock the thread */\r
+ KiAcquireThreadLock(Thread);\r
+ \r
+ /* Save the old Priority */\r
+ OldPriority = Thread->Priority;\r
+ \r
+ /* Make sure that an actual change is being done */\r
+ if (OldPriority != Priority)\r
+ {\r
+ /* Reset the Quantum and Decrements */\r
+ Thread->Quantum = Thread->QuantumReset;\r
+ Thread->PriorityDecrement = 0;\r
+ \r
+ /* Set the new Priority */\r
+ KiSetPriorityThread(Thread, Priority, &Released);\r
+ }\r
+ \r
+ /* Release thread lock */\r
+ KiReleaseThreadLock(Thread);\r
+ \r
+ /* Check if lock was released */\r
+ if (!Released)\r
+ {\r
+ /* Release the dispatcher database */\r
+ KiReleaseDispatcherLock(OldIrql);\r
+ }\r
+ else\r
+ {\r
+ /* Lower IRQL only */\r
+ KeLowerIrql(OldIrql);\r
+ }\r
+ \r
+ /* Return Old Priority */\r
+ return OldPriority;\r
+ }\r
+ \r
+ /*\r
+ * @implemented\r
+ */\r
+ VOID\r
+ NTAPI\r
+ KeTerminateThread(IN KPRIORITY Increment)\r
+ {\r
+ PLIST_ENTRY *ListHead;\r
+ PETHREAD Entry, SavedEntry;\r
+ PETHREAD *ThreadAddr;\r
+ KLOCK_QUEUE_HANDLE LockHandle;\r
+ PKTHREAD Thread = KeGetCurrentThread();\r
+ PKPROCESS Process = Thread->ApcState.Process;\r
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+ \r
+ /* Lock the process */\r
+ KiAcquireProcessLock(Process, &LockHandle);\r
+ \r
+ /* Make sure we won't get Swapped */\r
+ KiSetThreadSwapBusy(Thread);\r
+ \r
+ /* Save the Kernel and User Times */\r
+ Process->KernelTime += Thread->KernelTime;\r
+ Process->UserTime += Thread->UserTime;\r
+ \r
+ /* Get the current entry and our Port */\r
+ Entry = (PETHREAD)PspReaperListHead.Flink;\r
+ ThreadAddr = &((PETHREAD)Thread)->ReaperLink;\r
+ \r
+ /* Add it to the reaper's list */\r
+ do\r
+ {\r
+ /* Get the list head */\r
+ ListHead = &PspReaperListHead.Flink;\r
+ \r
+ /* Link ourselves */\r
+ *ThreadAddr = Entry;\r
+ SavedEntry = Entry;\r
+ \r
+ /* Now try to do the exchange */\r
+ Entry = InterlockedCompareExchangePointer(ListHead, ThreadAddr, Entry);\r
+ \r
+ /* Break out if the change was succesful */\r
+ } while (Entry != SavedEntry);\r
+ \r
+ /* Acquire the dispatcher lock */\r
+ KiAcquireDispatcherLockAtDpcLevel();\r
+ \r
+ /* Check if the reaper wasn't active */\r
+ if (!Entry)\r
+ {\r
+ /* Activate it as a work item, directly through its Queue */\r
+ KiInsertQueue(&ExWorkerQueue[HyperCriticalWorkQueue].WorkerQueue,\r
+ &PspReaperWorkItem.List,\r
+ FALSE);\r
+ }\r
+ \r
+ /* Check the thread has an associated queue */\r
+ if (Thread->Queue)\r
+ {\r
+ /* Remove it from the list, and handle the queue */\r
+ RemoveEntryList(&Thread->QueueListEntry);\r
+ KiActivateWaiterQueue(Thread->Queue);\r
+ }\r
+ \r
+ /* Signal the thread */\r
+ Thread->DispatcherHeader.SignalState = TRUE;\r
+ if (!IsListEmpty(&Thread->DispatcherHeader.WaitListHead))\r
+ {\r
+ /* Unwait the threads */\r
+ KxUnwaitThread(&Thread->DispatcherHeader, Increment);\r
+ }\r
+ \r
+ /* Remove the thread from the list */\r
+ RemoveEntryList(&Thread->ThreadListEntry);\r
+ \r
+ /* Release the process lock */\r
+ KiReleaseProcessLockFromDpcLevel(&LockHandle);\r
+ \r
+ /* Set us as terminated, decrease the Process's stack count */\r
+ Thread->State = Terminated;\r
+ \r
+ /* Decrease stack count */\r
+ ASSERT(Process->StackCount != 0);\r
+ ASSERT(Process->State == ProcessInMemory);\r
+ Process->StackCount--;\r
+ if (!Process->StackCount)\r
+ {\r
+ /* FIXME: Swap stacks */\r
+ }\r
+ \r
+ /* Rundown arch-specific parts */\r
+ KiRundownThread(Thread);\r
+ \r
+ /* Swap to a new thread */\r
+ KiReleaseDispatcherLockFromDpcLevel();\r
+ KiSwapThread(Thread, KeGetCurrentPrcb());\r
+ }\r
VOID
INIT_FUNCTION
NTAPI
---LdrInitModuleManagement ( VOID )
+++LdrInitModuleManagement ( PVOID KernelBase )
{
PIMAGE_NT_HEADERS NtHeader;
/* Initialize ModuleObject for NTOSKRNL */
RtlZeroMemory(&NtoskrnlModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
--- NtoskrnlModuleObject.DllBase = (PVOID) KERNEL_BASE;
+++ NtoskrnlModuleObject.DllBase = (PVOID) KernelBase;
RtlInitUnicodeString(&NtoskrnlModuleObject.FullDllName, KERNEL_MODULE_NAME);
LdrpBuildModuleBaseName(&NtoskrnlModuleObject.BaseDllName, &NtoskrnlModuleObject.FullDllName);
--- NtHeader = RtlImageNtHeader((PVOID)KERNEL_BASE);
+++ NtHeader = RtlImageNtHeader((PVOID)KernelBase);
NtoskrnlModuleObject.EntryPoint = (PVOID) ((ULONG_PTR) NtoskrnlModuleObject.DllBase + NtHeader->OptionalHeader.AddressOfEntryPoint);
DPRINT("ModuleObject:%08x entrypoint at %x\n", &NtoskrnlModuleObject, NtoskrnlModuleObject.EntryPoint);
NtoskrnlModuleObject.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
<module name="ntoskrnl" type="kernel" installbase="system32" installname="ntoskrnl.exe">
- <bootstrap base="reactos" />
- <importlibrary definition="ntoskrnl.def" />
- <define name="_SEH_NO_NATIVE_NLG" />
- <define name="_DISABLE_TIDENTS" />
- <define name="__NTOSKRNL__" />
- <define name="_NTOSKRNL_" />
- <define name="__NO_CTYPE_INLINES" />
- <define name="__USE_W32API" />
- <include base="kjs">include</include>
- <include base="cmlib">.</include>
- <include base="ntoskrnl">include</include>
- <include base="ReactOS">include/reactos/drivers</include>
- <library>csq</library>
- <library>hal</library>
- <library>kjs</library>
- <library>pseh</library>
- <library>cmlib</library>
- <library>rtl</library>
- <library>rossym</library>
- <library>string</library>
- <library>wdmguid</library>
- <directory name="include">
- <pch>ntoskrnl.h</pch>
- </directory>
- <directory name="ke">
- <if property="ARCH" value="i386">
- <directory name="i386">
- <file first="true">boot.S</file>
- <file>abios.c</file>
- <file>cpu.c</file>
- <file>ctxswitch.S</file>
+ <bootstrap base="reactos" />
+ <importlibrary definition="ntoskrnl.def" />
+ <define name="_SEH_NO_NATIVE_NLG" />
+ <define name="_DISABLE_TIDENTS" />
+ <define name="__NTOSKRNL__" />
+ <define name="_NTOSKRNL_" />
+ <define name="_NTSYSTEM_" />
+ <define name="__NO_CTYPE_INLINES" />
+ <define name="__USE_W32API" />
+ <define name="WIN9X_COMPAT_SPINLOCK" />
+ <include base="kjs">include</include>
+ <include base="cmlib">.</include>
+ <include base="ntoskrnl">include</include>
+ <include base="ReactOS">include/reactos/drivers</include>
+ <library>csq</library>
+ <library>hal</library>
+ <library>kjs</library>
+ <library>pseh</library>
+ <library>cmlib</library>
+ <library>rtl</library>
+ <library>rossym</library>
+ <library>string</library>
+ <library>wdmguid</library>
+ <directory name="include">
+ <pch>ntoskrnl.h</pch>
+ </directory>
+ <directory name="ke">
+ <if property="ARCH" value="i386">
+ <directory name="i386">
+ <file first="true">boot.S</file>
+ <file>abios.c</file>
+ <file>cpu.c</file>
+ <file>ctxswitch.S</file>
<file>clock.S</file>
- <file>exp.c</file>
- <!-- <file>irq.c</file> -->
- <file>kiinit.c</file>
- <file>ldt.c</file>
- <file>thread.c</file>
- <file>trap.s</file>
- <file>usercall_asm.S</file>
- <file>v86vdm.c</file>
- <file>v86m_sup.S</file>
- </directory>
- </if>
+ <file>exp.c</file>
-- <!-- <file>irq.c</file> -->
+ <file>kiinit.c</file>
+ <file>ldt.c</file>
+ <file>mtrr.c</file>
+ <file>patpge.c</file>
+ <file>thread.c</file>
+ <file>trap.s</file>
+ <file>usercall_asm.S</file>
+ <file>usercall.c</file>
+ <file>v86vdm.c</file>
+ <file>v86m_sup.S</file>
+ </directory>
+ </if>
++ <if property="ARCH" value="powerpc">
++ <directory name="powerpc">
++ <file first="true">main_asm.S</file>
++ <file>kiinit.c</file>
++ <file>ppc_irq.c</file>
++ </directory>
++ </if>
- <file>apc.c</file>
- <file>bug.c</file>
- <file>clock.c</file>
- <file>device.c</file>
- <file>dpc.c</file>
- <file>event.c</file>
- <file>exception.c</file>
- <file>freeldr.c</file>
- <file>gate.c</file>
- <file>gmutex.c</file>
- <file>ipi.c</file>
- <file>kqueue.c</file>
- <file>krnlinit.c</file>
- <file>kthread.c</file>
- <file>mutex.c</file>
- <file>process.c</file>
- <file>profile.c</file>
- <file>queue.c</file>
- <file>sem.c</file>
- <file>spinlock.c</file>
- <file>timer.c</file>
- <file>usercall.c</file>
- <file>wait.c</file>
- </directory>
+ <file>apc.c</file>
+ <file>bug.c</file>
+ <file>clock.c</file>
+ <file>config.c</file>
+ <file>devqueue.c</file>
+ <file>dpc.c</file>
+ <file>event.c</file>
+ <file>except.c</file>
+ <file>freeldr.c</file>
+ <file>gate.c</file>
+ <file>gmutex.c</file>
+ <file>ipi.c</file>
+ <file>krnlinit.c</file>
+ <file>mutex.c</file>
+ <file>process.c</file>
+ <file>profile.c</file>
+ <file>queue.c</file>
+ <file>sem.c</file>
+ <file>spinlock.c</file>
+ <file>thrdschd.c</file>
+ <file>thrdobj.c</file>
+ <file>timer.c</file>
+ <file>wait.c</file>
+ </directory>
-- <directory name="deprecated">
-- <file>irqhand.S</file>
-- <file>irq.c</file>
-- </directory>
++ <if property="ARCH" value="i386">
++ <directory name="deprecated">
++ <file>irqhand.S</file>
++ <file>irq.c</file>
++ </directory>
++ </if>
- <directory name="cc">
- <file>cacheman.c</file>
- <file>copy.c</file>
- <file>fs.c</file>
- <file>mdl.c</file>
- <file>pin.c</file>
- <file>view.c</file>
- </directory>
- <directory name="cm">
- <file>import.c</file>
- <file>ntfunc.c</file>
- <file>regfile.c</file>
- <file>registry.c</file>
- <file>regobj.c</file>
- </directory>
- <directory name="kdbg">
- <if property="ARCH" value="i386">
- <directory name="i386">
- <if property="KDBG" value="1">
- <group>
- <file>i386-dis.c</file>
- <file>kdb_help.S</file>
- <file>longjmp.S</file>
- <file>setjmp.S</file>
- </group>
- </if>
- </directory>
- </if>
- <if property="KDBG" value="1">
- <file>kdb.c</file>
- <file>kdb_cli.c</file>
- <file>kdb_expr.c</file>
- <file>kdb_keyboard.c</file>
- <file>kdb_serial.c</file>
- <file>kdb_string.c</file>
- </if>
- <if property="DBG_OR_KDBG" value="true">
- <file>kdb_symbols.c</file>
- </if>
- </directory>
- <directory name="dbgk">
- <file>dbgkutil.c</file>
- <file>debug.c</file>
- </directory>
- <directory name="ex">
- <if property="ARCH" value="i386">
- <directory name="i386">
- <file>interlck_asm.S</file>
- <file>fastinterlck_asm.S</file>
- </directory>
- </if>
- <file>atom.c</file>
- <file>callback.c</file>
- <file>dbgctrl.c</file>
- <file>error.c</file>
+ <directory name="cc">
+ <file>cacheman.c</file>
+ <file>copy.c</file>
+ <file>fs.c</file>
+ <file>mdl.c</file>
+ <file>pin.c</file>
+ <file>view.c</file>
+ </directory>
+ <directory name="cm">
+ <file>import.c</file>
+ <file>ntfunc.c</file>
+ <file>regfile.c</file>
+ <file>registry.c</file>
+ <file>regobj.c</file>
+ </directory>
+ <directory name="kdbg">
+ <if property="ARCH" value="i386">
+ <directory name="i386">
+ <if property="KDBG" value="1">
+ <group>
+ <file>i386-dis.c</file>
+ <file>kdb_help.S</file>
+ <file>longjmp.S</file>
+ <file>setjmp.S</file>
+ </group>
+ </if>
+ </directory>
+ </if>
+ <if property="KDBG" value="1">
+ <file>kdb.c</file>
+ <file>kdb_cli.c</file>
+ <file>kdb_expr.c</file>
+ <file>kdb_keyboard.c</file>
+ <file>kdb_serial.c</file>
+ <file>kdb_string.c</file>
+ </if>
+ <if property="DBG_OR_KDBG" value="true">
+ <file>kdb_symbols.c</file>
+ </if>
+ </directory>
+ <directory name="dbgk">
+ <file>dbgkutil.c</file>
+ <file>debug.c</file>
+ </directory>
+ <directory name="ex">
+ <if property="ARCH" value="i386">
+ <directory name="i386">
+ <file>interlck_asm.S</file>
+ <file>fastinterlck_asm.S</file>
+ </directory>
+ </if>
+ <file>atom.c</file>
+ <file>callback.c</file>
+ <file>dbgctrl.c</file>
+ <file>error.c</file>
<file>efi.c</file>
- <file>event.c</file>
- <file>evtpair.c</file>
- <file>fmutex.c</file>
- <file>handle.c</file>
- <file>init.c</file>
- <file>locale.c</file>
- <file>lookas.c</file>
- <file>mutant.c</file>
- <file>power.c</file>
- <file>pushlock.c</file>
- <file>profile.c</file>
- <file>resource.c</file>
- <file>rundown.c</file>
- <file>sem.c</file>
- <file>sysinfo.c</file>
- <file>time.c</file>
- <file>timer.c</file>
- <file>uuid.c</file>
- <file>win32k.c</file>
- <file>work.c</file>
- <file>zone.c</file>
- <file>zw.S</file>
- </directory>
- <directory name="fs">
- <file>context.c</file>
- <file>fastio.c</file>
- <file>filelock.c</file>
- <file>mcb.c</file>
- <file>name.c</file>
- <file>notify.c</file>
- <file>oplock.c</file>
- <file>pool.c</file>
- <file>tunnel.c</file>
- <file>unc.c</file>
- <file>util.c</file>
- </directory>
- <directory name="inbv">
- <file>inbv.c</file>
- </directory>
- <directory name="io">
+ <file>event.c</file>
+ <file>evtpair.c</file>
+ <file>fmutex.c</file>
+ <file>handle.c</file>
+ <file>init.c</file>
+ <file>locale.c</file>
+ <file>lookas.c</file>
+ <file>mutant.c</file>
+ <file>power.c</file>
+ <file>pushlock.c</file>
+ <file>profile.c</file>
+ <file>resource.c</file>
+ <file>rundown.c</file>
+ <file>sem.c</file>
+ <file>sysinfo.c</file>
+ <file>time.c</file>
+ <file>timer.c</file>
+ <file>uuid.c</file>
+ <file>win32k.c</file>
+ <file>work.c</file>
+ <file>zone.c</file>
+ <file>zw.S</file>
+ </directory>
+ <directory name="fs">
+ <file>context.c</file>
+ <file>fastio.c</file>
+ <file>filelock.c</file>
+ <file>mcb.c</file>
+ <file>name.c</file>
+ <file>notify.c</file>
+ <file>oplock.c</file>
+ <file>pool.c</file>
+ <file>tunnel.c</file>
+ <file>unc.c</file>
+ <file>util.c</file>
+ </directory>
+ <directory name="inbv">
+ <file>inbv.c</file>
+ </directory>
+ <directory name="io">
<directory name="iomgr">
- <file>adapter.c</file>
- <file>arcname.c</file>
- <file>bootlog.c</file>
- <file>controller.c</file>
- <file>device.c</file>
- <file>deviface.c</file>
- <file>disk.c</file>
- <file>driver.c</file>
- <file>drvrlist.c</file>
- <file>error.c</file>
- <file>event.c</file>
+ <file>adapter.c</file>
+ <file>arcname.c</file>
+ <file>bootlog.c</file>
+ <file>controller.c</file>
+ <file>device.c</file>
+ <file>deviface.c</file>
+ <file>disk.c</file>
+ <file>driver.c</file>
+ <file>drvrlist.c</file>
+ <file>error.c</file>
+ <file>event.c</file>
<file>file.c</file>
<file>iocomp.c</file>
<file>iofunc.c</file>
--- /dev/null
--- /dev/null
++# Function Args Returns Types
++# Real OFW functions to proxy
++finddevice 1 1 char* int
++open 1 1 char* int
++getprop 4 1 int char* char*:arg3 int int
++write 3 1 int char*:arg2 int int
++read 3 1 int char*:arg2 int int
++exit 0 0
++child 1 1 int int
++peer 1 1 int int
++parent 1 1 int int
++seek 3 1 int int int int
++# MMU methods
++# claim (virt size align -- base)
++claim 3 1 int int int int
+++# claim-mem (size align -- base)
+++claim-mem 2 1 int int int
++# release (virt size --)
++release 2 0 int int
++package-to-path 3 1 int char*:arg2 int int
++# Declare the call-method BE function
+++call-method 0 0
++# Convenience functions that interact closely with OFW (written in BE asm)
++-dumpregs 0 0
++-print_string 1 0 char*
++-print_number 1 0 int
++-print_eol 0 0
++-print_space 0 0
++# MMU Methods
++@phys2virt!translate 4 1 int int int int&0 int
++@virt2phys!translate 2 1 int int&1 int
--- /dev/null
--- /dev/null
- powerpc-unknown-linux-gnu-ld -EL -g -nostartfiles -nostdlib -N -Ttext=0xe17000 -o freeldr.elf obj-ppc/boot/freeldr/freeldr/arch/powerpc/boot.o obj-ppc/boot/freeldr/freeldr/cache/blocklist.o obj-ppc/boot/freeldr/freeldr/cache/cache.o obj-ppc/boot/freeldr/freeldr/comm/rs232.o obj-ppc/boot/freeldr/freeldr/disk/disk.o obj-ppc/boot/freeldr/freeldr/disk/partition.o obj-ppc/boot/freeldr/freeldr/fs/ext2.o obj-ppc/boot/freeldr/freeldr/fs/fat.o obj-ppc/boot/freeldr/freeldr/fs/fs.o obj-ppc/boot/freeldr/freeldr/fs/fsrec.o obj-ppc/boot/freeldr/freeldr/fs/iso.o obj-ppc/boot/freeldr/freeldr/fs/ntfs.o obj-ppc/boot/freeldr/freeldr/inifile/ini_init.o obj-ppc/boot/freeldr/freeldr/inifile/inifile.o obj-ppc/boot/freeldr/freeldr/inifile/parse.o obj-ppc/boot/freeldr/freeldr/math/libgcc2.o obj-ppc/boot/freeldr/freeldr/mm/meminit.o obj-ppc/boot/freeldr/freeldr/mm/mm.o obj-ppc/boot/freeldr/freeldr/reactos/registry.o obj-ppc/boot/freeldr/freeldr/reactos/binhive.o obj-ppc/boot/freeldr/freeldr/reactos/arcname.o obj-ppc/boot/freeldr/freeldr/reactos/reactos.o obj-ppc/boot/freeldr/freeldr/rtl/list.o obj-ppc/boot/freeldr/freeldr/ui/gui.o obj-ppc/boot/freeldr/freeldr/ui/tui.o obj-ppc/boot/freeldr/freeldr/ui/tuimenu.o obj-ppc/boot/freeldr/freeldr/ui/ui.o obj-ppc/boot/freeldr/freeldr/video/bank.o obj-ppc/boot/freeldr/freeldr/video/fade.o obj-ppc/boot/freeldr/freeldr/video/palette.o obj-ppc/boot/freeldr/freeldr/video/pixel.o obj-ppc/boot/freeldr/freeldr/video/video.o obj-ppc/boot/freeldr/freeldr/freeldr.o obj-ppc/boot/freeldr/freeldr/debug.o obj-ppc/boot/freeldr/freeldr/version.o obj-ppc/boot/freeldr/freeldr/cmdline.o obj-ppc/boot/freeldr/freeldr/machine.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mach.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/ofw.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mmu.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mboot.o obj-ppc/boot/freeldr/freeldr/bootmgr.o obj-ppc/boot/freeldr/freeldr/drivemap.o obj-ppc/boot/freeldr/freeldr/miscboot.o obj-ppc/boot/freeldr/freeldr/options.o obj-ppc/boot/freeldr/freeldr/linuxboot.o obj-ppc/boot/freeldr/freeldr/oslist.o obj-ppc/boot/freeldr/freeldr/custom.o obj-ppc/lib/rossym/rossym.a obj-ppc/lib/cmlib/cmlib.a obj-ppc/lib/string/string.a obj-ppc/lib/rtl/rtl.a /usr/local/pkg/reactos-powerpc/lib/libgcc.a
++#!/bin/sh -v
++
++export PATH=$PATH:/usr/local/pkg/reactos-powerpc/bin
+++powerpc-unknown-linux-gnu-ld -EL -g -nostartfiles -nostdlib -N -Ttext=0xe17000 -o freeldr.elf obj-ppc/boot/freeldr/freeldr/arch/powerpc/boot.o obj-ppc/boot/freeldr/freeldr/cache/blocklist.o obj-ppc/boot/freeldr/freeldr/cache/cache.o obj-ppc/boot/freeldr/freeldr/comm/rs232.o obj-ppc/boot/freeldr/freeldr/disk/disk.o obj-ppc/boot/freeldr/freeldr/disk/partition.o obj-ppc/boot/freeldr/freeldr/fs/ext2.o obj-ppc/boot/freeldr/freeldr/fs/fat.o obj-ppc/boot/freeldr/freeldr/fs/fs.o obj-ppc/boot/freeldr/freeldr/fs/fsrec.o obj-ppc/boot/freeldr/freeldr/fs/iso.o obj-ppc/boot/freeldr/freeldr/fs/ntfs.o obj-ppc/boot/freeldr/freeldr/inifile/ini_init.o obj-ppc/boot/freeldr/freeldr/inifile/inifile.o obj-ppc/boot/freeldr/freeldr/inifile/parse.o obj-ppc/boot/freeldr/freeldr/math/libgcc2.o obj-ppc/boot/freeldr/freeldr/mm/meminit.o obj-ppc/boot/freeldr/freeldr/mm/mm.o obj-ppc/boot/freeldr/freeldr/reactos/registry.o obj-ppc/boot/freeldr/freeldr/reactos/binhive.o obj-ppc/boot/freeldr/freeldr/reactos/arcname.o obj-ppc/boot/freeldr/freeldr/reactos/reactos.o obj-ppc/boot/freeldr/freeldr/rtl/list.o obj-ppc/boot/freeldr/freeldr/ui/gui.o obj-ppc/boot/freeldr/freeldr/ui/tui.o obj-ppc/boot/freeldr/freeldr/ui/tuimenu.o obj-ppc/boot/freeldr/freeldr/ui/ui.o obj-ppc/boot/freeldr/freeldr/video/bank.o obj-ppc/boot/freeldr/freeldr/video/fade.o obj-ppc/boot/freeldr/freeldr/video/palette.o obj-ppc/boot/freeldr/freeldr/video/pixel.o obj-ppc/boot/freeldr/freeldr/video/video.o obj-ppc/boot/freeldr/freeldr/freeldr.o obj-ppc/boot/freeldr/freeldr/debug.o obj-ppc/boot/freeldr/freeldr/version.o obj-ppc/boot/freeldr/freeldr/cmdline.o obj-ppc/boot/freeldr/freeldr/machine.o obj-ppc/boot/freeldr/freeldr/windows/conversion.o obj-ppc/boot/freeldr/freeldr/windows/peloader.o obj-ppc/boot/freeldr/freeldr/windows/winldr.o obj-ppc/boot/freeldr/freeldr/windows/wlmemory.o obj-ppc/boot/freeldr/freeldr/windows/wlregistry.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mach.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/ofw.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mmu.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mboot.o obj-ppc/boot/freeldr/freeldr/bootmgr.o obj-ppc/boot/freeldr/freeldr/drivemap.o obj-ppc/boot/freeldr/freeldr/miscboot.o obj-ppc/boot/freeldr/freeldr/options.o obj-ppc/boot/freeldr/freeldr/linuxboot.o obj-ppc/boot/freeldr/freeldr/oslist.o obj-ppc/boot/freeldr/freeldr/custom.o obj-ppc/lib/rossym/rossym.a obj-ppc/lib/cmlib/cmlib.a obj-ppc/lib/string/string.a obj-ppc/lib/rtl/rtl.a /usr/local/pkg/reactos-powerpc/lib/libgcc.a
++powerpc-unknown-linux-gnu-objcopy -O binary freeldr.elf freeldr.tmp.le
++output-ppc/tools/ppc-le2be freeldr.tmp.le freeldr.tmp
++powerpc-unknown-linux-gnu-objcopy -I binary -B powerpc:common -O elf32-powerpc freeldr.tmp ofwldr.payload
++reactos-powerpc-as -mbig -o ofwboot.o boot/freeldr/bootsect/ofwboot.s boot/freeldr/bootsect/ofw_util.s boot/freeldr/bootsect/ofw.s
++powerpc-unknown-linux-gnu-ld -EB -Ttext 0xe00000 -Tdata 0xe17000 -e _begin -o ofwldr.x ofwboot.o ofwldr.payload
++powerpc-unknown-linux-gnu-objcopy --only-section=.text --only-section=.data ofwldr.x ofwldr