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 =
+++ HvpHiveHeaderCh