Partially fixed up tree after merge from HEAD. More to do.
authorArt Yerkes <art.yerkes@gmail.com>
Sun, 8 Oct 2006 10:01:27 +0000 (10:01 +0000)
committerArt Yerkes <art.yerkes@gmail.com>
Sun, 8 Oct 2006 10:01:27 +0000 (10:01 +0000)
Fixing ICE in gcc is no fun.

svn path=/branches/powerpc/; revision=24443

56 files changed:
1  2  3 
reactos/boot/bootdata/hivesft.inf
reactos/boot/bootdata/hivesys.inf
reactos/boot/bootdata/packages/reactos.dff
reactos/boot/bootdata/txtsetup.sif
reactos/boot/bootdata/unattend.inf.sample
reactos/boot/freeldr/freeldr/arch/powerpc/compat.h
reactos/boot/freeldr/freeldr/arch/powerpc/mach.c
reactos/boot/freeldr/freeldr/arch/powerpc/mboot.c
reactos/boot/freeldr/freeldr/cache/cache.c
reactos/boot/freeldr/freeldr/freeldr_base.rbuild
reactos/boot/freeldr/freeldr/include/freeldr.h
reactos/boot/freeldr/freeldr/mm/mm.c
reactos/boot/freeldr/freeldr/reactos/reactos.c
reactos/boot/freeldr/freeldr/windows/conversion.c
reactos/boot/freeldr/freeldr/windows/wlmemory.c
reactos/boot/freeldr/freeldr/windows/wlregistry.c
reactos/include/ddk/winddk.h
reactos/include/ndk/asm.h
reactos/include/ndk/mmtypes.h
reactos/include/ndk/pstypes.h
reactos/include/psdk/intrin.h
reactos/include/psdk/winnt.h
reactos/include/psdk/winsock2.h
reactos/lib/cmlib/cmdata.h
reactos/lib/cmlib/cminit.c
reactos/lib/cmlib/cmlib.h
reactos/lib/cmlib/cmlib.mak
reactos/lib/cmlib/hivebin.c
reactos/lib/cmlib/hivecell.c
reactos/lib/cmlib/hiveinit.c
reactos/lib/cmlib/hivewrt.c
reactos/lib/rtl/exception.c
reactos/lib/rtl/i386/rtlmem.s
reactos/lib/rtl/registry.c
reactos/ntoskrnl/ex/sysinfo.c
reactos/ntoskrnl/include/internal/ex.h
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/include/internal/ke_x.h
reactos/ntoskrnl/include/internal/ldr.h
reactos/ntoskrnl/include/internal/ntoskrnl.h
reactos/ntoskrnl/include/internal/powerpc/ke.h
reactos/ntoskrnl/kd/kdmain.c
reactos/ntoskrnl/kd/wrappers/gdbstub.c
reactos/ntoskrnl/ke/apc.c
reactos/ntoskrnl/ke/dpc.c
reactos/ntoskrnl/ke/freeldr.c
reactos/ntoskrnl/ke/gmutex.c
reactos/ntoskrnl/ke/krnlinit.c
reactos/ntoskrnl/ke/process.c
reactos/ntoskrnl/ke/thrdobj.c
reactos/ntoskrnl/ldr/loader.c
reactos/ntoskrnl/mm/pagefile.c
reactos/ntoskrnl/ntoskrnl.def
reactos/ntoskrnl/ntoskrnl.rbuild
reactos/tools/ofw_interface/calls.ofw
reactos/tools/ppc.lost+found/link-freeldr

Simple merge
@@@@ -629,32 -632,12 -632,12 +621,6 @@@@ HKLM,"SYSTEM\CurrentControlSet\Services
   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"
@@@@ -31,8 -32,11 -32,11 +32,9 @@@@ Signature = "$ReactOS$
   ; 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
@@@@ -207,7 -215,9 -215,9 +211,9 @@@@ dll\win32\shfolder\shfolder.dl
   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
Simple merge
@@@@ -1,6 -1,31 -1,31 +1,32 @@@@
-  ; 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
+++
index 031710e,0000000,0000000..66797a6
mode 100644,000000,000000..100644
--- /dev/null
--- /dev/null
@@@@ -1,209 -1,0 -1,0 +1,108 @@@@
-  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;
@@@@ -310,58 -254,16 -254,16 +311,58 @@@@ VOID PpcVideoPrepareForReactOS() 
    */
   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:
@@@@ -466,58 -358,18 -358,18 +467,61 @@@@ VOID PpcHwDetect() 
       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;
@@@@ -642,3 -484,3 -484,3 +646,7 @@@@ void BootNewLinuxKernel() 
   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>
@@@@ -284,7 -284,7 -284,7 +284,7 @@@@ BOOLEAN CacheForceDiskSectorsIntoCache(
                //
                // 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>
@@@@ -56,7 -63,7 -63,7 +66,7 @@@@ PVOID MmAllocateMemory(ULONG MemorySize
   {
        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;
        }
index 0000000,a42184b,a42184b..7848dc4
mode 000000,100644,100644..100644
--- /dev/null
@@@@ -1,0 -1,123 -1,123 +1,135 @@@@
+  /*
+   * 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);
+       }
+  }
index 0000000,243c3a1,243c3a1..9f6cbc5
mode 000000,100644,100644..100644
--- /dev/null
@@@@ -1,0 -1,948 -1,948 +1,960 @@@@
 --\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
index 0000000,3498c31,3498c31..73ec593
mode 000000,100644,100644..100644
--- /dev/null
@@@@ -1,0 -1,390 -1,390 +1,403 @@@@
+  /*
+   * 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;
+  }
@@@@ -10755,50 -10593,6 -10593,6 +10822,53 @@@@ extern BOOLEAN KdDebuggerEnabled
   
   #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
Simple merge
Simple merge
Simple merge
index 0000000,4a9d940,4a9d940..ab36de3
mode 000000,100644,100644..100644
--- /dev/null
@@@@ -1,0 -1,1113 -1,1113 +1,2058 @@@@
+  /*\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
Simple merge
@@@@ -27,10 -27,10 -27,10 +27,12 @@@@ extern "C" 
   /*   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