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 =
+++      HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+++
+++   /* Copy hive header */
+++   RtlCopyMemory(Buffer, RegistryHive->HiveHeader, HV_LOG_HEADER_SIZE);
+++   Ptr = Buffer + HV_LOG_HEADER_SIZE;
+++   RtlCopyMemory(Ptr, "DIRT", 4);
+++   Ptr += 4;
+++   RtlCopyMemory(Ptr, RegistryHive->DirtyVector.Buffer, BitmapSize);
+++
+++   /* Write hive block and block bitmap */
+++   Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+++                                     0, Buffer, BufferSize);
+++   if (!Success)
+++   {
+++      return FALSE;
+++   }
+++
+++   RegistryHive->Free(Buffer);
+++
+++   /* Write dirty blocks */
+++   FileOffset = BufferSize;
+++   BlockIndex = 0;
+++   while (BlockIndex < RegistryHive->Storage[HvStable].Length)
+++   {
+++      LastIndex = BlockIndex;
+++      BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
+++      if (BlockIndex == ~0 || BlockIndex < LastIndex)
+++      {
+++         break;
+++      }
+++
+++      BlockPtr = (PVOID)RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;
+++
+++      /* Write hive block */
+++      Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+++                                        FileOffset, BlockPtr,
+++                                        HV_BLOCK_SIZE);
+++      if (!Success)
+++      {
+++         return FALSE;
+++      }
+++
+++      BlockIndex++;
+++      FileOffset += HV_BLOCK_SIZE;
+++    }
+++
+++   Success = RegistryHive->FileSetSize(RegistryHive, HV_TYPE_LOG, FileOffset);
+++   if (!Success)
+++   {
+++      DPRINT("FileSetSize failed\n");
+++      return FALSE;
+++    }
+++
+++   /* Flush the log file */
+++   Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);
+++   if (!Success)
+++   {
+++      DPRINT("FileFlush failed\n");
+++   }
+++
+++   /* Update first and second update counter and checksum. */
+++   RegistryHive->HiveHeader->Sequence2++;
+++   RegistryHive->HiveHeader->Checksum =
+++      HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+++
+++   /* Write hive header again with updated sequence counter. */
+++   Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_LOG,
+++                                     0, RegistryHive->HiveHeader,
+++                                     HV_LOG_HEADER_SIZE);
+++   if (!Success)
+++   {
+++      return FALSE;
+++   }
+++
+++   /* Flush the log file */
+++   Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_LOG);
+++   if (!Success)
+++   {
+++      DPRINT("FileFlush failed\n");
+++   }
+++
+++   return TRUE;
+++}
+++
+++static BOOLEAN CMAPI
+++HvpWriteHive(
+++   PHHIVE RegistryHive,
+++   BOOLEAN OnlyDirty)
+++{
+++   ULONGLONG FileOffset;
+++   ULONG BlockIndex;
+++   ULONG LastIndex;
+++   PVOID BlockPtr;
+++   BOOLEAN Success;
+++
+++   ASSERT(RegistryHive->ReadOnly == FALSE);
+++   
+++   DPRINT("HvpWriteHive called\n");
+++
+++   if (RegistryHive->HiveHeader->Sequence1 !=
+++       RegistryHive->HiveHeader->Sequence2)
+++   {
+++      return FALSE;
+++   }
+++
+++   /* Update first update counter and checksum */
+++   RegistryHive->HiveHeader->Type = HV_TYPE_PRIMARY;
+++   RegistryHive->HiveHeader->Sequence1++;
+++   RegistryHive->HiveHeader->Checksum =
+++      HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+++
+++   /* Write hive block */
+++   Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+++                                     0, RegistryHive->HiveHeader,
+++                                     sizeof(HBASE_BLOCK));
+++   if (!Success)
+++   {
+++      return FALSE;
+++   }
+++
+++   BlockIndex = 0;
+++   while (BlockIndex < RegistryHive->Storage[HvStable].Length)
+++   {
+++      if (OnlyDirty)
+++      {
+++         LastIndex = BlockIndex;
+++         BlockIndex = RtlFindSetBits(&RegistryHive->DirtyVector, 1, BlockIndex);
+++         if (BlockIndex == ~0 || BlockIndex < LastIndex)
+++         {
+++            break;
+++         }
+++      }
+++
+++      BlockPtr = (PVOID)RegistryHive->Storage[HvStable].BlockList[BlockIndex].Block;
+++      FileOffset = (ULONGLONG)(BlockIndex + 1) * (ULONGLONG)HV_BLOCK_SIZE;
+++
+++      /* Write hive block */
+++      Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+++                                        FileOffset, BlockPtr,
+++                                        HV_BLOCK_SIZE);
+++      if (!Success)
+++      {
+++         return FALSE;
+++      }
+++
+++      BlockIndex++;
+++   }
+++
+++   Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);
+++   if (!Success)
+++   {
+++      DPRINT("FileFlush failed\n");
+++   }
+++
+++   /* Update second update counter and checksum */
+++   RegistryHive->HiveHeader->Sequence2++;
+++   RegistryHive->HiveHeader->Checksum =
+++      HvpHiveHeaderChecksum(RegistryHive->HiveHeader);
+++
+++   /* Write hive block */
+++   Success = RegistryHive->FileWrite(RegistryHive, HV_TYPE_PRIMARY,
+++                                     0, RegistryHive->HiveHeader,
+++                                     sizeof(HBASE_BLOCK));
+++   if (!Success)
+++   {
+++      return FALSE;
+++   }
+++
+++   Success = RegistryHive->FileFlush(RegistryHive, HV_TYPE_PRIMARY);
+++   if (!Success)
+++   {
+++      DPRINT("FileFlush failed\n");
+++   }
+++
+++   return TRUE;
+++}
+++
+++BOOLEAN CMAPI
+++HvSyncHive(
+++   PHHIVE RegistryHive)
+++{
+++   ASSERT(RegistryHive->ReadOnly == FALSE);
+++
+++   if (RtlFindSetBits(&RegistryHive->DirtyVector, 1, 0) == ~0)
+++   {
+++      return TRUE;
+++   }
+++
+++   /* Update hive header modification time */
+++   KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);
+++
+++   /* Update log file */
+++   if (!HvpWriteLog(RegistryHive))
+++   {
+++      return FALSE;
+++   }
+++
+++   /* Update hive file */
+++   if (!HvpWriteHive(RegistryHive, TRUE))
+++   {
+++      return FALSE;
+++   }
+++
+++   /* Clear dirty bitmap. */
+++   RtlClearAllBits(&RegistryHive->DirtyVector);
+++
+++   return TRUE;
+++}
+++
+++BOOLEAN CMAPI
+++HvWriteHive(
+++   PHHIVE RegistryHive)
+++{
+++   ASSERT(RegistryHive->ReadOnly == FALSE);
+++
+++   /* Update hive header modification time */
+++   KeQuerySystemTime(&RegistryHive->HiveHeader->TimeStamp);
+++
+++   /* Update hive file */
+++   if (!HvpWriteHive(RegistryHive, FALSE))
+++   {
+++      return FALSE;
+++   }
+++
+++   return TRUE;
+++}
@@@@ -130,9 -126,6 -126,6 +127,7 @@@@ RtlWalkFrameChain(OUT PVOID *Callers
       __asm__("mov %%ebp, %0" : "=r" (Stack) : );
   #elif defined(_MSC_VER)
       __asm mov Stack, ebp
-  #elif defined(_M_PPC)
-      __asm__("mr %0, %%r1" : "=r" (Stack) : );
 ++#endif
   #endif
   
       /* Set it as the stack begin limit as well */
---/*\r
--- * COPYRIGHT:         See COPYING in the top level directory\r
--- * PROJECT:           ReactOS Run-Time Library\r
--- * PURPOSE:           Memory functions\r
--- * FILE:              lib/rtl/i386/rtlswap.S\r
--- * PROGRAMER:         Alex Ionescu (alex.ionescu@reactos.org)\r
--- */\r
---\r
---.intel_syntax noprefix\r
---\r
---/* GLOBALS *******************************************************************/\r
---\r
---.globl _RtlCompareMemory@12\r
---.globl _RtlCompareMemoryUlong@12\r
---.globl _RtlFillMemory@12\r
---.globl _RtlFillMemoryUlong@12\r
---.globl _RtlMoveMemory@12\r
---.globl _RtlZeroMemory@8\r
---.globl @RtlPrefetchMemoryNonTemporal@8\r
---\r
---/* FUNCTIONS *****************************************************************/\r
---\r
---.func RtlCompareMemory@12\r
---_RtlCompareMemory@12:\r
---\r
---    /* Save volatiles */\r
---    push esi\r
---    push edi\r
---\r
---    /* Clear direction flag and load pointers and size in ULONGs */\r
---    cld\r
---    mov esi, [esp+12]\r
---    mov edi, [esp+16]\r
---    mov ecx, [esp+20]\r
---    shr ecx, 2\r
---    jz NoUlongs\r
---\r
---    /* Compare the ULONGs */\r
---    repe cmpsd\r
---    jnz NotEqual\r
---\r
---NoUlongs:\r
---\r
---    /* Compare what's left */\r
---    mov ecx, [esp+20]\r
---    and ecx, 3\r
---    jz NoneLeft\r
---    repe cmpsb\r
---    jnz NotEqual2\r
---\r
---NoneLeft:\r
---\r
---    /* We're done, return full count */\r
---    mov eax, [esp+20]\r
---    pop edi\r
---    pop esi\r
---    ret 12\r
---\r
---NotEqual:\r
---    /* Compare the last ULONG */\r
---    sub esi, 4\r
---    sub edi, 4\r
---    mov ecx, 5\r
---    repe cmpsb\r
---\r
---NotEqual2:\r
---\r
---    /* Remember how many mathced */\r
---    dec esi\r
---    sub esi, [esp+12]\r
---\r
---    /* Return count */\r
---    mov eax, esi\r
---    pop edi\r
---    pop esi\r
---    ret 12\r
---.endfunc\r
---\r
---.func RtlCompareMemoryUlong@12\r
---_RtlCompareMemoryUlong@12:\r
---\r
---    /* Get pointers and size in ULONGs */\r
---    push edi\r
---    mov edi, [esp+8]\r
---    mov ecx, [esp+12]\r
---    mov eax, [esp+16]\r
---    shr ecx, 2\r
---\r
---    /* Do the compare and check result */\r
---    repe scasd\r
---    jz Done\r
---    sub edi, 4\r
---\r
---    /* Return count */\r
---Done:\r
---    sub edi, [esp+8]\r
---    mov eax, edi\r
---    pop edi\r
---    ret 12\r
---.endfunc\r
---\r
---.func RtlFillMemory@12\r
---_RtlFillMemory@12:\r
---\r
---    /* Get pointers and size  */\r
---    push edi\r
---    mov edi, [esp+8]\r
---    mov ecx, [esp+12]\r
---\r
---    /* Get pattern */\r
---    mov al, [esp+16]\r
---    mov ah, al\r
---    shl eax, 16\r
---    mov al, [esp+16]\r
---    mov ah, al\r
---\r
---    /* Clear direction flag and set ULONG size and UCHAR remainder */\r
---    cld\r
---    mov edx, ecx\r
---    and edx, 3\r
---    shr ecx, 2\r
---\r
---    /* Do the fill */\r
---    rep stosd\r
---    or ecx, edx\r
---    jnz ByteFill\r
---\r
---    /* Return */\r
---    pop edi\r
---    ret 12\r
---\r
---ByteFill:\r
---    /* Fill what's left */\r
---    rep stosb\r
---    pop edi\r
---    ret 12\r
---.endfunc\r
---\r
---.func RtlFillMemoryUlong@12\r
---_RtlFillMemoryUlong@12:\r
---\r
---    /* Get pointer, size and pattern */\r
---    push edi\r
---    mov edi, [esp+8]\r
---    mov ecx, [esp+12]\r
---    mov eax, [esp+16]\r
---    shr ecx, 2\r
---\r
---    /* Do the fill and return */\r
---    rep stosd\r
---    pop edi\r
---    ret 12\r
---.endfunc\r
---\r
---.func RtlFillMemoryUlonglong@16\r
---_RtlFillMemoryUlonglong@16:\r
---\r
---    /* Save volatiles */\r
---    push edi\r
---    push esi\r
---\r
---    /* Get pointer, size and pattern */\r
---    mov ecx, [esp+16]\r
---    mov esi, [esp+12]\r
---    mov eax, [esp+20]\r
---    shr ecx, 2\r
---    sub ecx, 2\r
---\r
---    /* Save the first part */\r
---    mov [esi], eax\r
---\r
---    /* Read second part */\r
---    mov eax, [esp+24]\r
---    lea edi, [esi+8]\r
---    mov [esi+4], eax\r
---\r
---    /* Do the fill and return */\r
---    rep movsd\r
---    pop esi\r
---    pop edi\r
---    ret 16\r
---.endfunc\r
---\r
---.func RtlZeroMemory@8\r
---_RtlZeroMemory@8:\r
---\r
---    /* Get pointers and size  */\r
---    push edi\r
---    mov edi, [esp+8]\r
---    mov ecx, [esp+12]\r
---\r
---    /* Get pattern */\r
---    xor eax, eax\r
---\r
---    /* Clear direction flag and set ULONG size and UCHAR remainder */\r
---    cld\r
---    mov edx, ecx\r
---    and edx, 3\r
---    shr ecx, 2\r
---\r
---    /* Do the fill */\r
---    rep stosd\r
---    or ecx, edx\r
---    jnz ByteZero\r
---\r
---    /* Return */\r
---    pop edi\r
---    ret 8\r
---\r
---ByteZero:\r
---    /* Fill what's left */\r
---    rep stosb\r
---    pop edi\r
---    ret 8\r
---.endfunc\r
---\r
---.func RtlMoveMemory@12\r
---_RtlMoveMemory@12:\r
---\r
---    /* Save volatiles */\r
---    push esi\r
---    push edi\r
---\r
---    /* Get pointers and size  */\r
---    mov esi, [esp+16]\r
---    mov edi, [esp+12]\r
---    mov ecx, [esp+20]\r
---    cld\r
---\r
---    /* Check if the destination is higher (or equal) */\r
---    cmp esi, edi\r
---    jbe Overlap\r
---\r
---    /* Set ULONG size and UCHAR remainder */\r
---DoMove:\r
---    mov edx, ecx\r
---    and edx, 3\r
---    shr ecx, 2\r
---\r
---    /* Do the move */\r
---    rep movsd\r
---    or ecx, edx\r
---    jnz ByteMove\r
---\r
---    /* Return */\r
---    pop edi\r
---    pop esi\r
---    ret 12\r
---\r
---ByteMove:\r
---    /* Move what's left */\r
-      rep stosb\r
 --    rep movsb\r
---\r
---DoneMove:\r
---    /* Restore volatiles */\r
---    pop edi\r
---    pop esi\r
---    ret 12\r
---\r
---Overlap:\r
---    /* Don't copy if they're equal */\r
---    jz DoneMove\r
---\r
---    /* Compare pointer distance with given length and check for overlap */\r
---    mov eax, edi\r
---    sub eax, esi\r
---    cmp ecx, eax\r
---    jbe DoMove\r
---\r
---    /* Set direction flag for backward move */\r
---    std\r
---\r
---    /* Copy byte-by-byte the non-overlapping distance */\r
---    add esi, ecx\r
---    add edi, ecx\r
---    dec esi\r
---    dec edi\r
---\r
---    /* Do the move, reset flag and return */\r
---    rep movsb\r
---    cld\r
---    jmp DoneMove\r
---.endfunc\r
---\r
---.func @RtlPrefetchMemoryNonTemporal@8, @RtlPrefetchMemoryNonTemporal@8\r
---@RtlPrefetchMemoryNonTemporal@8:\r
---\r
---    /*\r
---     * Overwritten by ntoskrnl/ke/i386/kernel.c if SSE is supported\r
---     * (see Ki386SetProcessorFeatures())\r
---     */\r
---    ret\r
---\r
---    /* Get granularity */\r
---    mov eax, [_Ke386CacheAlignment]\r
---\r
---FetchLine:\r
---\r
---    /* Prefetch this line */\r
---    prefetchnta byte ptr [ecx]\r
---\r
---    /* Update address and count */\r
---    add ecx, eax\r
---    sub edx, eax\r
---\r
---    /* Keep looping for the next line, or return if done */\r
---    ja FetchLine\r
---    ret\r
---.endfunc\r
---\r
---/* FIXME: HACK */\r
---_Ke386CacheAlignment:\r
---    .long   0x40\r
+++/*
+++ * COPYRIGHT:         See COPYING in the top level directory
+++ * PROJECT:           ReactOS Run-Time Library
+++ * PURPOSE:           Memory functions
+++ * FILE:              lib/rtl/i386/rtlswap.S
+++ * PROGRAMER:         Alex Ionescu (alex.ionescu@reactos.org)
+++ */
+++
+++.intel_syntax noprefix
+++
+++/* GLOBALS *******************************************************************/
+++
+++.globl _RtlCompareMemory@12
+++.globl _RtlCompareMemoryUlong@12
+++.globl _RtlFillMemory@12
+++.globl _RtlFillMemoryUlong@12
+++.globl _RtlMoveMemory@12
+++.globl _RtlZeroMemory@8
+++.globl @RtlPrefetchMemoryNonTemporal@8
+++
+++/* FUNCTIONS *****************************************************************/
+++
+++.func RtlCompareMemory@12
+++_RtlCompareMemory@12:
+++
+++    /* Save volatiles */
+++    push esi
+++    push edi
+++
+++    /* Clear direction flag and load pointers and size in ULONGs */
+++    cld
+++    mov esi, [esp+12]
+++    mov edi, [esp+16]
+++    mov ecx, [esp+20]
+++    shr ecx, 2
+++    jz NoUlongs
+++
+++    /* Compare the ULONGs */
+++    repe cmpsd
+++    jnz NotEqual
+++
+++NoUlongs:
+++
+++    /* Compare what's left */
+++    mov ecx, [esp+20]
+++    and ecx, 3
+++    jz NoneLeft
+++    repe cmpsb
+++    jnz NotEqual2
+++
+++NoneLeft:
+++
+++    /* We're done, return full count */
+++    mov eax, [esp+20]
+++    pop edi
+++    pop esi
+++    ret 12
+++
+++NotEqual:
+++    /* Compare the last ULONG */
+++    sub esi, 4
+++    sub edi, 4
+++    mov ecx, 5
+++    repe cmpsb
+++
+++NotEqual2:
+++
+++    /* Remember how many mathced */
+++    dec esi
+++    sub esi, [esp+12]
+++
+++    /* Return count */
+++    mov eax, esi
+++    pop edi
+++    pop esi
+++    ret 12
+++.endfunc
+++
+++.func RtlCompareMemoryUlong@12
+++_RtlCompareMemoryUlong@12:
+++
+++    /* Get pointers and size in ULONGs */
+++    push edi
+++    mov edi, [esp+8]
+++    mov ecx, [esp+12]
+++    mov eax, [esp+16]
+++    shr ecx, 2
+++
+++    /* Do the compare and check result */
+++    repe scasd
+++    jz Done
+++    sub edi, 4
+++
+++    /* Return count */
+++Done:
+++    sub edi, [esp+8]
+++    mov eax, edi
+++    pop edi
+++    ret 12
+++.endfunc
+++
+++.func RtlFillMemory@12
+++_RtlFillMemory@12:
+++
+++    /* Get pointers and size  */
+++    push edi
+++    mov edi, [esp+8]
+++    mov ecx, [esp+12]
+++
+++    /* Get pattern */
+++    mov al, [esp+16]
+++    mov ah, al
+++    shl eax, 16
+++    mov al, [esp+16]
+++    mov ah, al
+++
+++    /* Clear direction flag and set ULONG size and UCHAR remainder */
+++    cld
+++    mov edx, ecx
+++    and edx, 3
+++    shr ecx, 2
+++
+++    /* Do the fill */
+++    rep stosd
+++    or ecx, edx
+++    jnz ByteFill
+++
+++    /* Return */
+++    pop edi
+++    ret 12
+++
+++ByteFill:
+++    /* Fill what's left */
+++    rep stosb
+++    pop edi
+++    ret 12
+++.endfunc
+++
+++.func RtlFillMemoryUlong@12
+++_RtlFillMemoryUlong@12:
+++
+++    /* Get pointer, size and pattern */
+++    push edi
+++    mov edi, [esp+8]
+++    mov ecx, [esp+12]
+++    mov eax, [esp+16]
+++    shr ecx, 2
+++
+++    /* Do the fill and return */
+++    rep stosd
+++    pop edi
+++    ret 12
+++.endfunc
+++
+++.func RtlFillMemoryUlonglong@16
+++_RtlFillMemoryUlonglong@16:
+++
+++    /* Save volatiles */
+++    push edi
+++    push esi
+++
+++    /* Get pointer, size and pattern */
+++    mov ecx, [esp+16]
+++    mov esi, [esp+12]
+++    mov eax, [esp+20]
+++    shr ecx, 2
+++    sub ecx, 2
+++
+++    /* Save the first part */
+++    mov [esi], eax
+++
+++    /* Read second part */
+++    mov eax, [esp+24]
+++    lea edi, [esi+8]
+++    mov [esi+4], eax
+++
+++    /* Do the fill and return */
+++    rep movsd
+++    pop esi
+++    pop edi
+++    ret 16
+++.endfunc
+++
+++.func RtlZeroMemory@8
+++_RtlZeroMemory@8:
+++
+++    /* Get pointers and size  */
+++    push edi
+++    mov edi, [esp+8]
+++    mov ecx, [esp+12]
+++
+++    /* Get pattern */
+++    xor eax, eax
+++
+++    /* Clear direction flag and set ULONG size and UCHAR remainder */
+++    cld
+++    mov edx, ecx
+++    and edx, 3
+++    shr ecx, 2
+++
+++    /* Do the fill */
+++    rep stosd
+++    or ecx, edx
+++    jnz ByteZero
+++
+++    /* Return */
+++    pop edi
+++    ret 8
+++
+++ByteZero:
+++    /* Fill what's left */
+++    rep stosb
+++    pop edi
+++    ret 8
+++.endfunc
+++
+++.func RtlMoveMemory@12
+++_RtlMoveMemory@12:
+++
+++    /* Save volatiles */
+++    push esi
+++    push edi
+++
+++    /* Get pointers and size  */
+++    mov esi, [esp+16]
+++    mov edi, [esp+12]
+++    mov ecx, [esp+20]
+++    cld
+++
+++    /* Check if the destination is higher (or equal) */
+++    cmp esi, edi
+++    jbe Overlap
+++
+++    /* Set ULONG size and UCHAR remainder */
+++DoMove:
+++    mov edx, ecx
+++    and edx, 3
+++    shr ecx, 2
+++
+++    /* Do the move */
+++    rep movsd
+++    or ecx, edx
+++    jnz ByteMove
+++
+++    /* Return */
+++    pop edi
+++    pop esi
+++    ret 12
+++
+++ByteMove:
+++    /* Move what's left */
+++    rep movsb
+++
+++DoneMove:
+++    /* Restore volatiles */
+++    pop edi
+++    pop esi
+++    ret 12
+++
+++Overlap:
+++    /* Don't copy if they're equal */
+++    jz DoneMove
+++
+++    /* Compare pointer distance with given length and check for overlap */
+++    mov eax, edi
+++    sub eax, esi
+++    cmp ecx, eax
+++    jbe DoMove
+++
+++    /* Set direction flag for backward move */
+++    std
+++
+++    /* Copy byte-by-byte the non-overlapping distance */
+++    add esi, ecx
+++    add edi, ecx
+++    dec esi
+++    dec edi
+++
+++    /* Do the move, reset flag and return */
+++    rep movsb
+++    cld
+++    jmp DoneMove
+++.endfunc
+++
+++.func @RtlPrefetchMemoryNonTemporal@8, @RtlPrefetchMemoryNonTemporal@8
+++@RtlPrefetchMemoryNonTemporal@8:
+++
+++    /*
+++     * Overwritten by ntoskrnl/ke/i386/kernel.c if SSE is supported
+++     * (see Ki386SetProcessorFeatures())
+++     */
+++    ret
+++
+++    /* Get granularity */
+++    mov eax, [_Ke386CacheAlignment]
+++
+++FetchLine:
+++
+++    /* Prefetch this line */
+++    prefetchnta byte ptr [ecx]
+++
+++    /* Update address and count */
+++    add ecx, eax
+++    sub edx, eax
+++
+++    /* Keep looping for the next line, or return if done */
+++    ja FetchLine
+++    ret
+++.endfunc
+++
+++/* FIXME: HACK */
+++_Ke386CacheAlignment:
+++    .long   0x40
@@@@ -584,6 -584,7 -584,7 +584,9 @@@@ RtlQueryRegistryValues(IN ULONG Relativ
     PWSTR ValueName;
     UNICODE_STRING EnvValue;
     UNICODE_STRING EnvExpandedValue;
+++#ifdef DEBUG
+    ULONG DataSize = 0;
+++#endif
   
     PAGED_CODE_RTL();
   
Simple merge
@@@@ -28,13 -38,14 -38,14 +39,19 @@@@ PVOID ExpNlsSectionPointer
   #else
   #define ExAcquireResourceLock(l, i) KeAcquireSpinLock(l, i);
   #define ExReleaseResourceLock(l, i) KeReleaseSpinLock(l, i);
 ++#endif /* CONFIG_SMP */
 ++#elif defined(_M_PPC) /* _M_IX86 */
 ++/* XXX arty fixme */
 ++#define ExAcquireResourceLock(l,i) KeAcquireSpinLock(l,i);
 ++#define ExReleaseResourceLock(l,i) KeReleaseSpinLock(l,i);
   #endif
   
+  #define ExAcquireRundownProtection                      _ExAcquireRundownProtection
+  #define ExReleaseRundownProtection                      _ExReleaseRundownProtection
+  #define ExInitializeRundownProtection                   _ExInitializeRundownProtection
+  #define ExWaitForRundownProtectionRelease               _ExWaitForRundownProtectionRelease
+  #define ExRundownCompleted                              _ExRundownCompleted
+  
   /* INITIALIZATION FUNCTIONS *************************************************/
   
   VOID
@@@@ -77,9 -70,9 -70,9 +71,10 @@@@ extern ULONG_PTR KERNEL_BASE
   extern ULONG KeI386NpxPresent;
   extern ULONG KeI386XMMIPresent;
   extern ULONG KeI386FxsrPresent;
+  extern ULONG KiMXCsrMask;
   extern ULONG KeI386CpuType;
   extern ULONG KeI386CpuStep;
 ++#endif
   extern ULONG KeProcessorArchitecture;
   extern ULONG KeProcessorLevel;
   extern ULONG KeProcessorRevision;
@@@@ -829,16 -796,72 -796,72 +800,82 @@@@ KiInitSystem
       VOID
   );
   
 ++#ifdef _M_IX86
 ++#define KeHaltProcessor Ke386HaltProcessor
 ++#define KeEnableInterrupts Ke386EnableInterrupts
 ++#define KeDisableInterrupts Ke386DisableInterrupts
 ++#elif defined(_M_PPC)
 ++#define KeHaltProcessor KePPCHaltProcessor
 ++#define KeEnableInterrupts KePPCEnableInterrupts
 ++#define KeDisableInterrupts KePPCDisableInterrupts
 ++#endif
 ++
+  VOID
+  FASTCALL
+  KiInsertQueueApc(
+      IN PKAPC Apc,
+      IN KPRIORITY PriorityBoost
+  );
+  
+  NTSTATUS
+  NTAPI
+  KiCallUserMode(
+      IN PVOID *OutputBuffer,
+      IN PULONG OutputLength
+  );
+  
+  PULONG
+  NTAPI
+  KiGetUserModeStackAddress(
+      VOID
+  );
+  
+  ULONG_PTR
+  NTAPI
+  Ki386EnableGlobalPage(IN volatile ULONG_PTR Context);
+  
+  VOID
+  NTAPI
+  KiInitializePAT(VOID);
+  
+  VOID
+  NTAPI
+  KiInitializeMTRR(IN BOOLEAN FinalCpu);
+  
+  VOID
+  NTAPI
+  KiAmdK6InitializeMTRR(VOID);
+  
+  VOID
+  NTAPI
+  KiRestoreFastSyscallReturnState(VOID);
+  
+  ULONG_PTR
+  NTAPI
+  Ki386EnableDE(IN ULONG_PTR Context);
+  
+  ULONG_PTR
+  NTAPI
+  Ki386EnableFxsr(IN ULONG_PTR Context);
+  
+  ULONG_PTR
+  NTAPI
+  Ki386EnableXMMIExceptions(IN ULONG_PTR Context);
+  
+  VOID
+  NTAPI
+  KiInitMachineDependent(VOID);
+  
+  VOID
+  NTAPI
+  KiI386PentiumLockErrataFixup(VOID);
+  
+  VOID
+  WRMSR(
+      IN ULONG Register,
+      IN LONGLONG Value
+  );
+  
   #include "ke_x.h"
   
   #endif /* __NTOSKRNL_INCLUDE_INTERNAL_KE_H */
       }                                                                       \\r
   }\r
   \r
+++#undef FORCEINLINE\r
+++#define FORCEINLINE\r
+++\r
   //\r
   // Recalculates the due time\r
   //\r
@@@@ -208,43 -250,1016 -250,1016 +253,1018 @@@@ KiCheckThreadStackSwap(IN PKTHREAD Thre
   }\r
   \r
   //\r
-  // Rules for checking alertability:\r
-  //  - For Alertable waits ONLY:\r
-  //      * We don't wait and return STATUS_ALERTED if the thread is alerted\r
-  //        in EITHER the specified wait mode OR in Kernel Mode.\r
-  //  - For BOTH Alertable AND Non-Alertable waits:\r
-  //      * We don't want and return STATUS_USER_APC if the User Mode APC list\r
-  //        is not empty AND the wait mode is User Mode.\r
+  // Checks if a wait in progress should be interrupted by APCs or an alertable\r
+  // state.\r
   //\r
-  #define KiCheckAlertability()                                               \\r
-  {                                                                           \\r
-      if (Alertable)                                                          \\r
-      {                                                                       \\r
-          if (CurrentThread->Alerted[(int)WaitMode])                          \\r
-          {                                                                   \\r
-              CurrentThread->Alerted[(int)WaitMode] = FALSE;                  \\r
-              WaitStatus = STATUS_ALERTED;                                    \\r
-              break;                                                          \\r
-          }                                                                   \\r
-          else if ((WaitMode != KernelMode) &&                                \\r
-                  (!IsListEmpty(&CurrentThread->                              \\r
-                                ApcState.ApcListHead[UserMode])))             \\r
-          {                                                                   \\r
-              CurrentThread->ApcState.UserApcPending = TRUE;                  \\r
-              WaitStatus = STATUS_USER_APC;                                   \\r
-              break;                                                          \\r
-          }                                                                   \\r
-          else if (CurrentThread->Alerted[KernelMode])                        \\r
-          {                                                                   \\r
-              CurrentThread->Alerted[KernelMode] = FALSE;                     \\r
-              WaitStatus = STATUS_ALERTED;                                    \\r
-              break;                                                          \\r
-          }                                                                   \\r
-      }                                                                       \\r
-      else if ((WaitMode != KernelMode) &&                                    \\r
-               (CurrentThread->ApcState.UserApcPending))                      \\r
-      {                                                                       \\r
-          WaitStatus = STATUS_USER_APC;                                       \\r
-          break;                                                              \\r
-      }                                                                       \\r
+  FORCEINLINE\r
+  NTSTATUS\r
+  KiCheckAlertability(IN PKTHREAD Thread,\r
+                      IN BOOLEAN Alertable,\r
+                      IN KPROCESSOR_MODE WaitMode)\r
+  {\r
+      /* Check if the wait is alertable */\r
+      if (Alertable)\r
+      {\r
+          /* It is, first check if the thread is alerted in this mode */\r
+          if (Thread->Alerted[WaitMode])\r
+          {\r
+              /* It is, so bail out of the wait */\r
+              Thread->Alerted[WaitMode] = FALSE;\r
+              return STATUS_ALERTED;\r
+          }\r
+          else if ((WaitMode != KernelMode) &&\r
+                  (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))\r
+          {\r
+              /* It's isn't, but this is a user wait with queued user APCs */\r
+              Thread->ApcState.UserApcPending = TRUE;\r
+              return STATUS_USER_APC;\r
+          }\r
+          else if (Thread->Alerted[KernelMode])\r
+          {\r
+              /* It isn't that either, but we're alered in kernel mode */\r
+              Thread->Alerted[KernelMode] = FALSE;\r
+              return STATUS_ALERTED;\r
+          }\r
+      }\r
+      else if ((WaitMode != KernelMode) && (Thread->ApcState.UserApcPending))\r
+      {\r
+          /* Not alertable, but this is a user wait with pending user APCs */\r
+          return STATUS_USER_APC;\r
+      }\r
+  \r
+      /* Otherwise, we're fine */\r
+      return STATUS_WAIT_0;\r
+  }\r
+  \r
+  FORCEINLINE\r
+  BOOLEAN\r
+  KxDelayThreadWait(IN PKTHREAD Thread,\r
+                     IN BOOLEAN Alertable,\r
+                     IN KPROCESSOR_MODE WaitMode)\r
+  {\r
+      BOOLEAN Swappable;\r
+      PKWAIT_BLOCK TimerBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];\r
+  \r
+      /* Setup the Wait Block */\r
+      Thread->WaitBlockList = TimerBlock;\r
+      TimerBlock->NextWaitBlock = TimerBlock;\r
+  \r
+      /* Link the timer to this Wait Block */\r
+      Thread->Timer.Header.WaitListHead.Flink = &TimerBlock->WaitListEntry;\r
+      Thread->Timer.Header.WaitListHead.Blink = &TimerBlock->WaitListEntry;\r
+  \r
+      /* Clear wait status */\r
+      Thread->WaitStatus = STATUS_WAIT_0;\r
+  \r
+      /* Setup wait fields */\r
+      Thread->Alertable = Alertable;\r
+      Thread->WaitReason = DelayExecution;\r
+      Thread->WaitMode = WaitMode;\r
+  \r
+      /* Check if we can swap the thread's stack */\r
+      Thread->WaitListEntry.Flink = NULL;\r
+      Swappable = KiCheckThreadStackSwap(Thread, WaitMode);\r
+  \r
+      /* Set the wait time */\r
+      Thread->WaitTime = ((PLARGE_INTEGER)&KeTickCount)->LowPart;\r
+      return Swappable;\r
   }\r
+  \r
+  FORCEINLINE\r
+  BOOLEAN\r
+  KxMultiThreadWait(IN PKTHREAD Thread,\r
+                    IN PKWAIT_BLOCK WaitBlock,\r
+                    IN BOOLEAN Alertable,\r
+                    IN KWAIT_REASON WaitReason,\r
+                    IN KPROCESSOR_MODE WaitMode)\r
+  {\r
+      BOOLEAN Swappable;\r
+      PKTIMER ThreadTimer = &Thread->Timer;\r
+  \r
+      /* Set default wait status */\r
+      Thread->WaitStatus = STATUS_WAIT_0;\r
+  \r
+      /* Link wait block array to the thread */\r
+      Thread->WaitBlockList = WaitBlock;\r
+  \r
+      /* Initialize the timer list */\r
+      InitializeListHead(&ThreadTimer->Header.WaitListHead);\r
+  \r
+      /* Set wait settings */\r
+      Thread->Alertable = Alertable;\r
+      Thread->WaitMode = WaitMode;\r
+      Thread->WaitReason = WaitReason;\r
+  \r
+      /* Check if we can swap the thread's stack */\r
+      Thread->WaitListEntry.Flink = NULL;\r
+      Swappable = KiCheckThreadStackSwap(Thread, WaitMode);\r
+  \r
+      /* Set the wait time */\r
+      Thread->WaitTime = ((PLARGE_INTEGER)&KeTickCount)->LowPart;\r
+      return Swappable;\r
+  }\r
+  \r
+  FORCEINLINE\r
+  BOOLEAN\r
+  KxSingleThreadWait(IN PKTHREAD Thread,\r
+                     IN PKWAIT_BLOCK WaitBlock,\r
+                     IN PVOID Object,\r
+                     IN PLARGE_INTEGER Timeout,\r
+                     IN BOOLEAN Alertable,\r
+                     IN KWAIT_REASON WaitReason,\r
+                     IN KPROCESSOR_MODE WaitMode)\r
+  {\r
+      BOOLEAN Swappable;\r
+      PKWAIT_BLOCK TimerBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];\r
+  \r
+      /* Setup the Wait Block */\r
+      Thread->WaitBlockList = WaitBlock;\r
+      WaitBlock->WaitKey = STATUS_WAIT_0;\r
+      WaitBlock->Object = Object;\r
+      WaitBlock->WaitType = WaitAny;\r
+  \r
+      /* Clear wait status */\r
+      Thread->WaitStatus = STATUS_WAIT_0;\r
+  \r
+      /* Check if we have a timer */\r
+      if (Timeout)\r
+      {\r
+          /* Pointer to timer block */\r
+          WaitBlock->NextWaitBlock = TimerBlock;\r
+          TimerBlock->NextWaitBlock = WaitBlock;\r
+  \r
+          /* Link the timer to this Wait Block */\r
+          Thread->Timer.Header.WaitListHead.Flink = &TimerBlock->WaitListEntry;\r
+          Thread->Timer.Header.WaitListHead.Blink = &TimerBlock->WaitListEntry;\r
+      }\r
+      else\r
+      {\r
+          /* No timer block, just ourselves */\r
+          WaitBlock->NextWaitBlock = WaitBlock;\r
+      }\r
+  \r
+      /* Setup wait fields */\r
+      Thread->Alertable = Alertable;\r
+      Thread->WaitReason = WaitReason;\r
+      Thread->WaitMode = WaitMode;\r
+  \r
+      /* Check if we can swap the thread's stack */\r
+      Thread->WaitListEntry.Flink = NULL;\r
+      Swappable = KiCheckThreadStackSwap(Thread, WaitMode);\r
+  \r
+      /* Set the wait time */\r
+      Thread->WaitTime = ((PLARGE_INTEGER)&KeTickCount)->LowPart;\r
+      return Swappable;\r
+  }\r
+  \r
+  //\r
+  // Unwaits a Thread\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KxUnwaitThread(IN DISPATCHER_HEADER *Object,\r
+                 IN KPRIORITY Increment)\r
+  {\r
+      PLIST_ENTRY WaitEntry, WaitList;\r
+      PKWAIT_BLOCK CurrentWaitBlock;\r
+      PKTHREAD WaitThread;\r
+      ULONG WaitKey;\r
+  \r
+      /* Loop the Wait Entries */\r
+      WaitList = &Object->WaitListHead;\r
+      WaitEntry = WaitList->Flink;\r
+      do\r
+      {\r
+          /* Get the current wait block */\r
+          CurrentWaitBlock = CONTAINING_RECORD(WaitEntry,\r
+                                               KWAIT_BLOCK,\r
+                                               WaitListEntry);\r
+  \r
+          /* Get the waiting thread */\r
+          WaitThread = CurrentWaitBlock->Thread;\r
+  \r
+          /* Check the current Wait Mode */\r
+          if (CurrentWaitBlock->WaitType == WaitAny)\r
+          {\r
+              /* Use the actual wait key */\r
+              WaitKey = CurrentWaitBlock->WaitKey;\r
+          }\r
+          else\r
+          {\r
+              /* Otherwise, use STATUS_KERNEL_APC */\r
+              WaitKey = STATUS_KERNEL_APC;\r
+          }\r
+  \r
+          /* Unwait the thread */\r
+          KiUnwaitThread(WaitThread, WaitKey, Increment);\r
+  \r
+          /* Next entry */\r
+          WaitEntry = WaitList->Flink;\r
+      } while (WaitEntry != WaitList);\r
+  }\r
+  \r
+  //\r
+  // Unwaits a Thread waiting on an event\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KxUnwaitThreadForEvent(IN PKEVENT Event,\r
+                         IN KPRIORITY Increment)\r
+  {\r
+      PLIST_ENTRY WaitEntry, WaitList;\r
+      PKWAIT_BLOCK CurrentWaitBlock;\r
+      PKTHREAD WaitThread;\r
+  \r
+      /* Loop the Wait Entries */\r
+      WaitList = &Event->Header.WaitListHead;\r
+      WaitEntry = WaitList->Flink;\r
+      do\r
+      {\r
+          /* Get the current wait block */\r
+          CurrentWaitBlock = CONTAINING_RECORD(WaitEntry,\r
+                                               KWAIT_BLOCK,\r
+                                               WaitListEntry);\r
+  \r
+          /* Get the waiting thread */\r
+          WaitThread = CurrentWaitBlock->Thread;\r
+  \r
+          /* Check the current Wait Mode */\r
+          if (CurrentWaitBlock->WaitType == WaitAny)\r
+          {\r
+              /* Un-signal it */\r
+              Event->Header.SignalState = 0;\r
+  \r
+              /* Un-signal the event and unwait the thread */\r
+              KiUnwaitThread(WaitThread, CurrentWaitBlock->WaitKey, Increment);\r
+              break;\r
+          }\r
+          else\r
+          {\r
+              /* Unwait the thread with STATUS_KERNEL_APC */\r
+              KiUnwaitThread(WaitThread, STATUS_KERNEL_APC, Increment);\r
+          }\r
+  \r
+          /* Next entry */\r
+          WaitEntry = WaitList->Flink;\r
+      } while (WaitEntry != WaitList);\r
+  }\r
+  \r
+  #ifndef _CONFIG_SMP\r
+  //\r
+  // Spinlock Acquire at IRQL >= DISPATCH_LEVEL\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)\r
+  {\r
+      /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */\r
+      UNREFERENCED_PARAMETER(SpinLock);\r
+  }\r
+  \r
+  //\r
+  // Spinlock Release at IRQL >= DISPATCH_LEVEL\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)\r
+  {\r
+      /* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */\r
+      UNREFERENCED_PARAMETER(SpinLock);\r
+  }\r
+  \r
+  //\r
+  // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+  //\r
+  VOID\r
+  FORCEINLINE\r
+  KiAcquireDispatcherObject(IN DISPATCHER_HEADER* Object)\r
+  {\r
+      UNREFERENCED_PARAMETER(Object);\r
+  }\r
+  \r
+  //\r
+  // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+  //\r
+  VOID\r
+  FORCEINLINE\r
+  KiReleaseDispatcherObject(IN DISPATCHER_HEADER* Object)\r
+  {\r
+      UNREFERENCED_PARAMETER(Object);\r
+  }\r
+  \r
+  KIRQL\r
+  FORCEINLINE\r
+  KiAcquireDispatcherLock(VOID)\r
+  {\r
+      /* Raise to DPC level */\r
+      return KeRaiseIrqlToDpcLevel();\r
+  }\r
+  \r
+  VOID\r
+  FORCEINLINE\r
+  KiReleaseDispatcherLock(IN KIRQL OldIrql)\r
+  {\r
+      /* Just exit the dispatcher */\r
+      KiExitDispatcher(OldIrql);\r
+  }\r
+  \r
+  VOID\r
+  FORCEINLINE\r
+  KiAcquireDispatcherLockAtDpcLevel(VOID)\r
+  {\r
+      /* This is a no-op at DPC Level for UP systems */\r
+      return;\r
+  }\r
+  \r
+  VOID\r
+  FORCEINLINE\r
+  KiReleaseDispatcherLockFromDpcLevel(VOID)\r
+  {\r
+      /* This is a no-op at DPC Level for UP systems */\r
+      return;\r
+  }\r
+  \r
+  //\r
+  // This routine makes the thread deferred ready on the boot CPU.\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiInsertDeferredReadyList(IN PKTHREAD Thread)\r
+  {\r
+      /* Set the thread to deferred state and boot CPU */\r
+      Thread->State = DeferredReady;\r
+      Thread->DeferredProcessor = 0;\r
+  \r
+      /* Make the thread ready immediately */\r
+      KiDeferredReadyThread(Thread);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiRescheduleThread(IN BOOLEAN NewThread,\r
+                     IN ULONG Cpu)\r
+  {\r
+      /* This is meaningless on UP systems */\r
+      UNREFERENCED_PARAMETER(NewThread);\r
+      UNREFERENCED_PARAMETER(Cpu);\r
+  }\r
+  \r
+  //\r
+  // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiSetThreadSwapBusy(IN PKTHREAD Thread)\r
+  {\r
+      UNREFERENCED_PARAMETER(Thread);\r
+  }\r
+  \r
+  //\r
+  // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiAcquirePrcbLock(IN PKPRCB Prcb)\r
+  {\r
+      UNREFERENCED_PARAMETER(Prcb);\r
+  }\r
+  \r
+  //\r
+  // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiReleasePrcbLock(IN PKPRCB Prcb)\r
+  {\r
+      UNREFERENCED_PARAMETER(Prcb);\r
+  }\r
+  \r
+  //\r
+  // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiAcquireThreadLock(IN PKTHREAD Thread)\r
+  {\r
+      UNREFERENCED_PARAMETER(Thread);\r
+  }\r
+  \r
+  //\r
+  // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiReleaseThreadLock(IN PKTHREAD Thread)\r
+  {\r
+      UNREFERENCED_PARAMETER(Thread);\r
+  }\r
+  \r
+  //\r
+  // This routine protects against multiple CPU acquires, it's meaningless on UP.\r
+  //\r
+  FORCEINLINE\r
+  BOOLEAN\r
+  KiTryThreadLock(IN PKTHREAD Thread)\r
+  {\r
+      UNREFERENCED_PARAMETER(Thread);\r
+      return FALSE;\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiCheckDeferredReadyList(IN PKPRCB Prcb)\r
+  {\r
+      /* There are no deferred ready lists on UP systems */\r
+      UNREFERENCED_PARAMETER(Prcb);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiRundownThread(IN PKTHREAD Thread)\r
+  {\r
+      /* Check if this is the NPX Thread */\r
+      if (KeGetCurrentPrcb()->NpxThread == Thread)\r
+      {\r
+          /* Clear it */\r
+          KeGetCurrentPrcb()->NpxThread = NULL;\r
+++#ifdef _M_IX86\r
+  #ifdef __GNUC__\r
+          __asm__("fninit\n\t");\r
+  #else\r
+          __asm fninit;\r
+++#endif\r
+  #endif\r
+      }\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiRequestApcInterrupt(IN BOOLEAN NeedApc,\r
+                        IN UCHAR Processor)\r
+  {\r
+      /* We deliver instantly on UP */\r
+      UNREFERENCED_PARAMETER(NeedApc);\r
+      UNREFERENCED_PARAMETER(Processor);\r
+  }\r
+  \r
+  #else\r
+  \r
+  //\r
+  // Spinlock Acquisition at IRQL >= DISPATCH_LEVEL\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)\r
+  {\r
+      for (;;)\r
+      {\r
+          /* Try to acquire it */\r
+          if (InterlockedBitTestAndSet((PLONG)SpinLock, 0))\r
+          {\r
+              /* Value changed... wait until it's locked */\r
+              while (*(volatile KSPIN_LOCK *)SpinLock == 1)\r
+              {\r
+  #ifdef DBG\r
+                  /* On debug builds, we use a much slower but useful routine */\r
+                  Kii386SpinOnSpinLock(SpinLock, 5);\r
+  #else\r
+                  /* Otherwise, just yield and keep looping */\r
+                  YieldProcessor();\r
+  #endif\r
+              }\r
+          }\r
+          else\r
+          {\r
+  #ifdef DBG\r
+              /* On debug builds, we OR in the KTHREAD */\r
+              *SpinLock = KeGetCurrentThread() | 1;\r
+  #endif\r
+              /* All is well, break out */\r
+              break;\r
+          }\r
+      }\r
+  }\r
+  \r
+  //\r
+  // Spinlock Release at IRQL >= DISPATCH_LEVEL\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)\r
+  {\r
+  #ifdef DBG\r
+      /* Make sure that the threads match */\r
+      if ((KeGetCurrentThread() | 1) != *SpinLock)\r
+      {\r
+          /* They don't, bugcheck */\r
+          KeBugCheckEx(SPIN_LOCK_NOT_OWNED, SpinLock, 0, 0, 0);\r
+      }\r
+  #endif\r
+      /* Clear the lock */\r
+      InterlockedAnd(SpinLock, 0);\r
+  }\r
+  \r
+  KIRQL\r
+  FORCEINLINE\r
+  KiAcquireDispatcherObject(IN DISPATCHER_HEADER* Object)\r
+  {\r
+      LONG OldValue, NewValue;\r
+  \r
+      /* Make sure we're at a safe level to touch the lock */\r
+      ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);\r
+  \r
+      /* Start acquire loop */\r
+      do\r
+      {\r
+          /* Loop until the other CPU releases it */\r
+          while ((UCHAR)Object->Lock & KOBJECT_LOCK_BIT)\r
+          {\r
+              /* Let the CPU know that this is a loop */\r
+              YieldProcessor();\r
+          };\r
+  \r
+          /* Try acquiring the lock now */\r
+          NewValue = InterlockedCompareExchange(&Object->Lock,\r
+                                                OldValue | KOBJECT_LOCK_BIT,\r
+                                                OldValue);\r
+      } while (NewValue != OldValue);\r
+  }\r
+  \r
+  KIRQL\r
+  FORCEINLINE\r
+  KiReleaseDispatcherObject(IN DISPATCHER_HEADER* Object)\r
+  {\r
+      /* Make sure we're at a safe level to touch the lock */\r
+      ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);\r
+  \r
+      /* Release it */\r
+      InterlockedAnd(&Object->Lock, ~KOBJECT_LOCK_BIT);\r
+  }\r
+  \r
+  KIRQL\r
+  FORCEINLINE\r
+  KiAcquireDispatcherLock(VOID)\r
+  {\r
+      /* Raise to synchronization level and acquire the dispatcher lock */\r
+      return KeAcquireQueuedSpinLockRaiseToSynch(LockQueueDispatcherLock);\r
+  }\r
+  \r
+  VOID\r
+  FORCEINLINE\r
+  KiReleaseDispatcherLock(IN KIRQL OldIrql)\r
+  {\r
+      /* First release the lock */\r
+      KeReleaseQueuedSpinLockFromDpcLevel(&KeGetCurrentPrcb()->\r
+                                          LockQueue[LockQueueDispatcherLock]);\r
+  \r
+      /* Then exit the dispatcher */\r
+      KiExitDispatcher(OldIrql);\r
+  }\r
+  \r
+  //\r
+  // This routine inserts a thread into the deferred ready list of the given CPU\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiInsertDeferredReadyList(IN PKTHREAD Thread)\r
+  {\r
+      PKPRCB Prcb = KeGetCurrentPrcb();\r
+  \r
+      /* Set the thread to deferred state and CPU */\r
+      Thread->State = DeferredReady;\r
+      Thread->DeferredProcessor = Prcb->Number;\r
+  \r
+      /* Add it on the list */\r
+      PushEntryList(&Prcb->DeferredReadyListHead, &Thread->SwapListEntry);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiRescheduleThread(IN BOOLEAN NewThread,\r
+                     IN ULONG Cpu)\r
+  {\r
+      /* Check if a new thread needs to be scheduled on a different CPU */\r
+      if ((NewThread) && !(KeGetPcr()->Number == Cpu))\r
+      {\r
+          /* Send an IPI to request delivery */\r
+          KiIpiSendRequest(AFFINITY_MASK(Cpu), IPI_DPC);\r
+      }\r
+  }\r
+  \r
+  //\r
+  // This routine sets the current thread in a swap busy state, which ensure that\r
+  // nobody else tries to swap it concurrently.\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiSetThreadSwapBusy(IN PKTHREAD Thread)\r
+  {\r
+      /* Make sure nobody already set it */\r
+      ASSERT(Thread->SwapBusy == FALSE);\r
+  \r
+      /* Set it ourselves */\r
+      Thread->SwapBusy = TRUE;\r
+  }\r
+  \r
+  //\r
+  // This routine acquires the PRCB lock so that only one caller can touch\r
+  // volatile PRCB data.\r
+  //\r
+  // Since this is a simple optimized spin-lock, it must be be only acquired\r
+  // at dispatcher level or higher!\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiAcquirePrcbLock(IN PKPRCB Prcb)\r
+  {\r
+      /* Make sure we're at a safe level to touch the PRCB lock */\r
+      ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);\r
+  \r
+      /* Start acquire loop */\r
+      for (;;)\r
+      {\r
+          /* Acquire the lock and break out if we acquired it first */\r
+          if (!InterlockedExchange(&Prcb->PrcbLock, 1)) break;\r
+  \r
+          /* Loop until the other CPU releases it */\r
+          do\r
+          {\r
+              /* Let the CPU know that this is a loop */\r
+              YieldProcessor();\r
+          } while (Prcb->PrcbLock);\r
+      }\r
+  }\r
+  \r
+  //\r
+  // This routine releases the PRCB lock so that other callers can touch\r
+  // volatile PRCB data.\r
+  //\r
+  // Since this is a simple optimized spin-lock, it must be be only acquired\r
+  // at dispatcher level or higher!\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiReleasePrcbLock(IN PKPRCB Prcb)\r
+  {\r
+      /* Make sure it's acquired! */\r
+      ASSERT(Prcb->PrcbLock != 0);\r
+  \r
+      /* Release it */\r
+      InterlockedAnd(&Prcb->PrcbLock, 0);\r
+  }\r
+  \r
+  //\r
+  // This routine acquires the thread lock so that only one caller can touch\r
+  // volatile thread data.\r
+  //\r
+  // Since this is a simple optimized spin-lock, it must be be only acquired\r
+  // at dispatcher level or higher!\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiAcquireThreadLock(IN PKTHREAD Thread)\r
+  {\r
+      /* Make sure we're at a safe level to touch the thread lock */\r
+      ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);\r
+  \r
+      /* Start acquire loop */\r
+      for (;;)\r
+      {\r
+          /* Acquire the lock and break out if we acquired it first */\r
+          if (!InterlockedExchange(&Thread->ThreadLock, 1)) break;\r
+  \r
+          /* Loop until the other CPU releases it */\r
+          do\r
+          {\r
+              /* Let the CPU know that this is a loop */\r
+              YieldProcessor();\r
+          } while (Thread->ThreadLock);\r
+      }\r
+  }\r
+  \r
+  //\r
+  // This routine releases the thread lock so that other callers can touch\r
+  // volatile thread data.\r
+  //\r
+  // Since this is a simple optimized spin-lock, it must be be only acquired\r
+  // at dispatcher level or higher!\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KiReleaseThreadLock(IN PKTHREAD Thread)\r
+  {\r
+      /* Release it */\r
+      InterlockedAnd(&Thread->ThreadLock, 0);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  BOOLEAN\r
+  KiTryThreadLock(IN PKTHREAD Thread)\r
+  {\r
+      LONG Value;\r
+  \r
+      /* If the lock isn't acquired, return false */\r
+      if (!Thread->ThreadLock) return FALSE;\r
+  \r
+      /* Otherwise, try to acquire it and check the result */\r
+      Value = 1;\r
+      Value = InterlockedExchange(&Thread->ThreadLock, &Value);\r
+  \r
+      /* Return the lock state */\r
+      return (Value == TRUE);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiCheckDeferredReadyList(IN PKPRCB Prcb)\r
+  {\r
+      /* Scan the deferred ready lists if required */\r
+      if (Prcb->DeferredReadyListHead.Next) KiProcessDeferredReadyList(Prcb);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiRequestApcInterrupt(IN BOOLEAN NeedApc,\r
+                        IN UCHAR Processor)\r
+  {\r
+      /* Check if we need to request APC delivery */\r
+      if (NeedApc)\r
+      {\r
+          /* Check if it's on another CPU */\r
+          if (KeGetPcr()->Number != Cpu)\r
+          {\r
+              /* Send an IPI to request delivery */\r
+              KiIpiSendRequest(AFFINITY_MASK(Cpu), IPI_DPC);\r
+          }\r
+          else\r
+          {\r
+              /* Request a software interrupt */\r
+              HalRequestSoftwareInterrupt(APC_LEVEL);\r
+          }\r
+      }\r
+  }\r
+  \r
+  #endif\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiAcquireApcLock(IN PKTHREAD Thread,\r
+                   IN PKLOCK_QUEUE_HANDLE Handle)\r
+  {\r
+      /* Acquire the lock and raise to synchronization level */\r
+      KeAcquireInStackQueuedSpinLockRaiseToSynch(&Thread->ApcQueueLock, Handle);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiAcquireApcLockAtDpcLevel(IN PKTHREAD Thread,\r
+                             IN PKLOCK_QUEUE_HANDLE Handle)\r
+  {\r
+      /* Acquire the lock */\r
+      KeAcquireInStackQueuedSpinLockAtDpcLevel(&Thread->ApcQueueLock, Handle);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiAcquireApcLockAtApcLevel(IN PKTHREAD Thread,\r
+                             IN PKLOCK_QUEUE_HANDLE Handle)\r
+  {\r
+      /* Acquire the lock */\r
+      KeAcquireInStackQueuedSpinLock(&Thread->ApcQueueLock, Handle);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiReleaseApcLock(IN PKLOCK_QUEUE_HANDLE Handle)\r
+  {\r
+      /* Release the lock */\r
+      KeReleaseInStackQueuedSpinLock(Handle);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiReleaseApcLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE Handle)\r
+  {\r
+      /* Release the lock */\r
+      KeReleaseInStackQueuedSpinLockFromDpcLevel(Handle);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiAcquireProcessLock(IN PKPROCESS Process,\r
+                       IN PKLOCK_QUEUE_HANDLE Handle)\r
+  {\r
+      /* Acquire the lock and raise to synchronization level */\r
+      KeAcquireInStackQueuedSpinLockRaiseToSynch(&Process->ProcessLock, Handle);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiReleaseProcessLock(IN PKLOCK_QUEUE_HANDLE Handle)\r
+  {\r
+      /* Release the lock */\r
+      KeReleaseInStackQueuedSpinLock(Handle);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiReleaseProcessLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE Handle)\r
+  {\r
+      /* Release the lock */\r
+      KeReleaseInStackQueuedSpinLockFromDpcLevel(Handle);\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiAcquireDeviceQueueLock(IN PKDEVICE_QUEUE DeviceQueue,\r
+                           IN PKLOCK_QUEUE_HANDLE DeviceLock)\r
+  {\r
+      /* Check if we were called from a threaded DPC */\r
+      if (KeGetCurrentPrcb()->DpcThreadActive)\r
+      {\r
+          /* Lock the Queue, we're not at DPC level */\r
+          KeAcquireInStackQueuedSpinLock(&DeviceQueue->Lock, DeviceLock);\r
+      }\r
+      else\r
+      {\r
+          /* We must be at DPC level, acquire the lock safely */\r
+          ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);\r
+          KeAcquireInStackQueuedSpinLockAtDpcLevel(&DeviceQueue->Lock,\r
+                                                   DeviceLock);\r
+      }\r
+  }\r
+  \r
+  FORCEINLINE\r
+  VOID\r
+  KiReleaseDeviceQueueLock(IN PKLOCK_QUEUE_HANDLE DeviceLock)\r
+  {\r
+      /* Check if we were called from a threaded DPC */\r
+      if (KeGetCurrentPrcb()->DpcThreadActive)\r
+      {\r
+          /* Unlock the Queue, we're not at DPC level */\r
+          KeReleaseInStackQueuedSpinLock(DeviceLock);\r
+      }\r
+      else\r
+      {\r
+          /* We must be at DPC level, release the lock safely */\r
+          ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);\r
+          KeReleaseInStackQueuedSpinLockFromDpcLevel(DeviceLock);\r
+      }\r
+  }\r
+  \r
+  //\r
+  // This routine queues a thread that is ready on the PRCB's ready lists.\r
+  // If this thread cannot currently run on this CPU, then the thread is\r
+  // added to the deferred ready list instead.\r
+  //\r
+  // This routine must be entered with the PRCB lock held and it will exit\r
+  // with the PRCB lock released!\r
+  //\r
+  FORCEINLINE\r
+  VOID\r
+  KxQueueReadyThread(IN PKTHREAD Thread,\r
+                     IN PKPRCB Prcb)\r
+  {\r
+      BOOLEAN Preempted;\r
+      KPRIORITY Priority;\r
+  \r
+      /* Sanity checks */\r
+      ASSERT(Prcb == KeGetCurrentPrcb());\r
+      ASSERT(Thread->State == Running);\r
+      ASSERT(Thread->NextProcessor == Prcb->Number);\r
+  \r
+      /* Check if this thread is allowed to run in this CPU */\r
+  #ifdef _CONFIG_SMP\r
+      if ((Thread->Affinity) & (Prcb->SetMember))\r
+  #else\r
+      if (TRUE)\r
+  #endif\r
+      {\r
+          /* Set thread ready for execution */\r
+          Thread->State = Ready;\r
+  \r
+          /* Save current priority and if someone had pre-empted it */\r
+          Priority = Thread->Priority;\r
+          Preempted = Thread->Preempted;\r
+  \r
+          /* We're not pre-empting now, and set the wait time */\r
+          Thread->Preempted = FALSE;\r
+          Thread->WaitTime = KeTickCount.LowPart;\r
+  \r
+          /* Sanity check */\r
+          ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));\r
+  \r
+          /* Insert this thread in the appropriate order */\r
+          Preempted ? InsertHeadList(&Prcb->DispatcherReadyListHead[Priority],\r
+                                     &Thread->WaitListEntry) :\r
+                      InsertTailList(&Prcb->DispatcherReadyListHead[Priority],\r
+                                     &Thread->WaitListEntry);\r
+  \r
+          /* Update the ready summary */\r
+          Prcb->ReadySummary |= PRIORITY_MASK(Priority);\r
+  \r
+          /* Sanity check */\r
+          ASSERT(Priority == Thread->Priority);\r
+  \r
+          /* Release the PRCB lock */\r
+          KiReleasePrcbLock(Prcb);\r
+      }\r
+      else\r
+      {\r
+          /* Otherwise, prepare this thread to be deferred */\r
+          Thread->State = DeferredReady;\r
+          Thread->DeferredProcessor = Prcb->Number;\r
+  \r
+          /* Release the lock and defer scheduling */\r
+          KiReleasePrcbLock(Prcb);\r
+          KiDeferredReadyThread(Thread);\r
+      }\r
+  }\r
+  \r
+  //\r
+  // This routine scans for an appropriate ready thread to select at the\r
+  // given priority and for the given CPU.\r
+  //\r
+  FORCEINLINE\r
+  PKTHREAD\r
+  KiSelectReadyThread(IN KPRIORITY Priority,\r
+                      IN PKPRCB Prcb)\r
+  {\r
+      LONG PriorityMask, PrioritySet, HighPriority;\r
+      PLIST_ENTRY ListEntry;\r
+      PKTHREAD Thread;\r
+  \r
+      /* Save the current mask and get the priority set for the CPU */\r
+      PriorityMask = Priority;\r
+      PrioritySet = Prcb->ReadySummary >> (UCHAR)Priority;\r
+      if (!PrioritySet) return NULL;\r
+  \r
+      /*  Get the highest priority possible */\r
+      BitScanReverse((PULONG)&HighPriority, PrioritySet);\r
+      ASSERT((PrioritySet & PRIORITY_MASK(HighPriority)) != 0);\r
+      HighPriority += PriorityMask;\r
+  \r
+      /* Make sure the list isn't at highest priority */\r
+      ASSERT(IsListEmpty(&Prcb->DispatcherReadyListHead[HighPriority]) == FALSE);\r
+  \r
+      /* Get the first thread on the list */\r
+      ListEntry = &Prcb->DispatcherReadyListHead[HighPriority];\r
+      Thread = CONTAINING_RECORD(ListEntry, KTHREAD, WaitListEntry);\r
+  \r
+      /* Make sure this thread is here for a reason */\r
+      ASSERT(HighPriority == Thread->Priority);\r
+      ASSERT(Thread->Affinity & AFFINITY_MASK(Prcb->Number));\r
+      ASSERT(Thread->NextProcessor == Prcb->Number);\r
+  \r
+      /* Remove it from the list */\r
+      RemoveEntryList(&Thread->WaitListEntry);\r
+      if (IsListEmpty(&Thread->WaitListEntry))\r
+      {\r
+          /* The list is empty now, reset the ready summary */\r
+          Prcb->ReadySummary ^= PRIORITY_MASK(HighPriority);\r
+      }\r
+  \r
+      /* Sanity check and return the thread */\r
+      ASSERT((Thread == NULL) ||\r
+             (Thread->BasePriority == 0) ||\r
+             (Thread->Priority != 0));\r
+      return Thread;\r
+  }\r
+  \r
+  //\r
+  // This routine computes the new priority for a thread. It is only valid for\r
+  // threads with priorities in the dynamic priority range.\r
+  //\r
+  SCHAR\r
+  FORCEINLINE\r
+  KiComputeNewPriority(IN PKTHREAD Thread)\r
+  {\r
+      SCHAR Priority;\r
+  \r
+      /* Priority sanity checks */\r
+      ASSERT((Thread->PriorityDecrement >= 0) &&\r
+             (Thread->PriorityDecrement <= Thread->Priority));\r
+      ASSERT((Thread->Priority < LOW_REALTIME_PRIORITY) ?\r
+              TRUE : (Thread->PriorityDecrement == 0));\r
+  \r
+      /* Get the current priority */\r
+      Priority = Thread->Priority;\r
+      if (Priority < LOW_REALTIME_PRIORITY)\r
+      {\r
+          /* Decrease priority by the priority decrement */\r
+          Priority -= (Thread->PriorityDecrement + 1);\r
+  \r
+          /* Don't go out of bounds */\r
+          if (Priority < Thread->BasePriority) Priority = Thread->BasePriority;\r
+  \r
+          /* Reset the priority decrement */\r
+          Thread->PriorityDecrement = 0;\r
+      }\r
+  \r
+      /* Sanity check */\r
+      ASSERT((Thread->BasePriority == 0) || (Priority != 0));\r
+  \r
+      /* Return the new priority */\r
+      return Priority;\r
+  }\r
+  \r
@@@@ -21,7 -21,7 -21,7 +21,9 @@@@ LdrLoadAutoConfigDrivers(VOID)
   
   VOID
   NTAPI
---LdrInitModuleManagement(VOID);
+++LdrInitModuleManagement(
+++    IN PVOID KernelBase
+++);
   
   NTSTATUS
   NTAPI
@@@@ -291,4 -293,32 -293,32 +300,36 @@@@ DefaultQueryInfoBufferCheck(ULONG Class
   
   #endif
   
+  C_ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCall) == 0x300);
+  C_ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
+  C_ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
+  C_ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
+  C_ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
+  C_ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
+  C_ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
+  C_ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
+  C_ASSERT(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
+  C_ASSERT(FIELD_OFFSET(KTHREAD, ApcState.Process) == KTHREAD_APCSTATE_PROCESS);
+  C_ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
+++#ifdef _M_IX86
+  C_ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
+  C_ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
+  C_ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
+  C_ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
+  C_ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
+++#endif
+  //C_ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
+  //C_ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
+  C_ASSERT(FIELD_OFFSET(KPCR, IRR) == KPCR_IRR);
+  C_ASSERT(FIELD_OFFSET(KPCR, IDR) == KPCR_IDR);
+  C_ASSERT(FIELD_OFFSET(KPCR, Irql) == KPCR_IRQL);
+++#ifdef _M_IX86
+  C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
+  C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
+  C_ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
+  C_ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
+  C_ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, DpcStack) == KPCR_PRCB_DPC_STACK);
+  C_ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
+++#endif
+  
   #endif /* INCLUDE_INTERNAL_NTOSKRNL_H */
   #ifndef __NTOSKRNL_INCLUDE_INTERNAL_POWERPC_KE_H
   #define __NTOSKRNL_INCLUDE_INTERNAL_POWERPC_KE_H
   
+++#include <ndk/powerpc/ketypes.h>
+++
   #if __GNUC__ >=3
   #pragma GCC system_header
   #endif
@@@@ -129,52 -129,8 -129,8 +131,57 @@@@ __asm__ __volatile__("mfmsr 0\n\t" 
   #define KeArchEraseFlags()
   #define KeArchDisableInterrupts() KePPCDisableInterrupts()
   
-    ULONG Value = 0;
-    return (struct _KPRCB *) Value;
 ++static __inline struct _KPRCB * KeGetCurrentPrcb(
 ++  VOID)
 ++{
-  static __inline KIRQL KeGetCurrentIrql(
+++    return (struct _KPRCB *)__readfsdword(0x20);
+++}
+++
+++__inline struct _KPCR * NTHALAPI KeGetCurrentKPCR(
+++    VOID)
+++{
+++    return (struct _KPCR *)__readfsdword(0x1c);
 ++}
 ++
-      return PASSIVE_LEVEL;
+++__inline KIRQL NTHALAPI KeGetCurrentIrql(
 ++    VOID)
 ++{
+++    return ((KIPCR *)KeGetCurrentKPCR())->CurrentIrql;
 ++}
 ++
 ++VOID
 ++STDCALL
 ++KePPCInitThreadWithContext(
 ++     PKTHREAD Thread,
 ++     PKSYSTEM_ROUTINE SystemRoutine,
 ++     PKSTART_ROUTINE StartRoutine,
 ++     PVOID StartContext,
 ++     PCONTEXT Context);
 ++
 ++VOID
 ++STDCALL
 ++KeApplicationProcessorInitDispatcher(
 ++  VOID);
 ++
 ++VOID
 ++STDCALL
 ++KeCreateApplicationProcessorIdleThread(
 ++  ULONG Id);
 ++
 ++VOID KePPCHaltProcessor();
 ++
 ++#ifdef _NTOSKRNL_ /* FIXME: Move flags above to NDK instead of here */
 ++VOID
 ++STDCALL
 ++KiThreadStartup(PKSYSTEM_ROUTINE SystemRoutine,
 ++                PKSTART_ROUTINE StartRoutine,
 ++                PVOID StartContext,
 ++                BOOLEAN UserThread,
 ++                KTRAP_FRAME TrapFrame);
 ++#endif
 ++
 ++#endif /* __ASM__ */
 ++
   #endif /* __NTOSKRNL_INCLUDE_INTERNAL_POWERPC_KE_H */
   
   /* EOF */
Simple merge
@@@@ -893,60 -581,113 -581,113 +581,115 @@@@ _KeEnterCriticalRegion(VOID
    *
    *--*/
   VOID
-  STDCALL
-  KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
-                      IN PKTRAP_FRAME TrapFrame,
-                      IN PKNORMAL_ROUTINE NormalRoutine,
-                      IN PVOID NormalContext,
-                      IN PVOID SystemArgument1,
-                      IN PVOID SystemArgument2)
+  NTAPI
+  _KeLeaveCriticalRegion(VOID)
   {
-      CONTEXT Context;
-      ULONG_PTR Stack;
-      ULONG Size;
-  
-      DPRINT("KiInitializeUserApc(TrapFrame %x/%x)\n", TrapFrame,
-              KeGetCurrentThread()->TrapFrame);
+      /* Use inlined version */
+      KeLeaveCriticalRegion();
+  }
   
-  #ifdef _M_IX86
-      /* Don't deliver APCs in V86 mode */
-      if (TrapFrame->EFlags & X86_EFLAGS_VM) return;
-  #endif
+  /*++
+   * KeInitializeApc
+   * @implemented NT4
+   *
+   *     The The KeInitializeApc routine initializes an APC object, and registers
+   *     the Kernel, Rundown and Normal routines for that object.
+   *
+   * @param Apc
+   *        Pointer to a KAPC structure that represents the APC object to
+   *        initialize. The caller must allocate storage for the structure
+   *        from resident memory.
+   *
+   * @param Thread
+   *        Thread to which to deliver the APC.
+   *
+   * @param TargetEnvironment
+   *        APC Environment to be used.
+   *
+   * @param KernelRoutine
+   *        Points to the KernelRoutine to associate with the APC.
+   *        This routine is executed for all APCs.
+   *
+   * @param RundownRoutine
+   *        Points to the RundownRoutine to associate with the APC.
+   *        This routine is executed when the Thread exists during APC execution.
+   *
+   * @param NormalRoutine
+   *        Points to the NormalRoutine to associate with the APC.
+   *        This routine is executed at PASSIVE_LEVEL. If this is not specifed,
+   *        the APC becomes a Special APC and the Mode and Context parameters are
+   *        ignored.
+   *
+   * @param Mode
+   *        Specifies the processor mode at which to run the Normal Routine.
+   *
+   * @param Context
+   *        Specifices the value to pass as Context parameter to the registered
+   *        routines.
+   *
+   * @return None.
+   *
+   * @remarks The caller can queue an initialized APC with KeInsertQueueApc.
+   *
+   *--*/
+  VOID
+  NTAPI
+  KeInitializeApc(IN PKAPC Apc,
+                  IN PKTHREAD Thread,
+                  IN KAPC_ENVIRONMENT TargetEnvironment,
+                  IN PKKERNEL_ROUTINE KernelRoutine,
+                  IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
+                  IN PKNORMAL_ROUTINE NormalRoutine,
+                  IN KPROCESSOR_MODE Mode,
+                  IN PVOID Context)
+  {
+      /* Sanity check */
+      ASSERT(TargetEnvironment <= InsertApcEnvironment);
   
-      /* Save the full context */
-      Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
-      KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
+      /* Set up the basic APC Structure Data */
+      Apc->Type = ApcObject;
+      Apc->Size = sizeof(KAPC);
   
-      /* Protect with SEH */
-      _SEH_TRY
+      /* Set the Environment */
+      if (TargetEnvironment == CurrentApcEnvironment)
+      {
+          /* Use the current one for the thread */
+          Apc->ApcStateIndex = Thread->ApcStateIndex;
+      }
+      else
       {
-          /* Get the aligned size */
-          Size = ((sizeof(CONTEXT) + 3) & ~3) + 4 * sizeof(ULONG_PTR);
-          Stack = (Context.Esp & ~3) - Size;
+          /* Sanity check */
+          ASSERT((TargetEnvironment <= Thread->ApcStateIndex) ||
+                 (TargetEnvironment == InsertApcEnvironment));
   
-          /* Probe and copy */
-          ProbeForWrite((PVOID)Stack, Size, 4);
-          RtlMoveMemory((PVOID)(Stack + 4 * sizeof(ULONG_PTR)),
-                        &Context,
-                        sizeof(CONTEXT));
+          /* Use the one that was given */
+          Apc->ApcStateIndex = TargetEnvironment;
+      }
   
-          /* Run at APC dispatcher */
-          TrapFrame->Eip = (ULONG)KeUserApcDispatcher;
-          TrapFrame->HardwareEsp = Stack;
 ++#ifdef _M_IX86
+      /* Set the Thread and Routines */
+      Apc->Thread = Thread;
+      Apc->KernelRoutine = KernelRoutine;
+      Apc->RundownRoutine = RundownRoutine;
+      Apc->NormalRoutine = NormalRoutine;
 ++#endif
   
-          /* Setup the stack */
-          *(PULONG_PTR)(Stack + 0 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalRoutine;
-          *(PULONG_PTR)(Stack + 1 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalContext;
-          *(PULONG_PTR)(Stack + 2 * sizeof(ULONG_PTR)) = (ULONG_PTR)SystemArgument1;
-          *(PULONG_PTR)(Stack + 3 * sizeof(ULONG_PTR)) = (ULONG_PTR)SystemArgument2;
+      /* Check if this is a special APC */
+      if (NormalRoutine)
+      {
+          /* It's a normal one. Set the context and mode */
+          Apc->ApcMode = Mode;
+          Apc->NormalContext = Context;
       }
-      _SEH_HANDLE
+      else
       {
-          /* FIXME: Get the record and raise an exception */
+          /* It's a special APC, which can only be kernel mode */
+          Apc->ApcMode = KernelMode;
+          Apc->NormalContext = NULL;
       }
-      _SEH_END;
+  
+      /* The APC is not inserted*/
+      Apc->Inserted = FALSE;
   }
   
   /*++
@@@@ -41,44 -47,31 -47,31 +47,31 @@@@ KiQuantumEnd(VOID
       if (InterlockedExchange(&Prcb->DpcSetEventRequest, 0))
       {
           /* Signal it */
 --        KeSetEvent(&Prcb->DpcEvent, 0, 0);
 ++        KeSetEvent((PVOID)&Prcb->DpcEvent, 0, 0);
       }
   
-      /* Lock dispatcher */
-      OldIrql = KeRaiseIrqlToSynchLevel();
-      ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
-  
-      /* Get the Thread's Process */
-      Process = CurrentThread->ApcState.Process;
+      /* Raise to synchronization level and lock the PRCB and thread */
+      KeRaiseIrqlToSynchLevel();
+      KiAcquireThreadLock(Thread);
+      KiAcquirePrcbLock(Prcb);
   
       /* Check if Quantum expired */
-      if (CurrentThread->Quantum <= 0)
+      if (Thread->Quantum <= 0)
       {
-          /* Reset the new Quantum */
-          CurrentThread->Quantum = CurrentThread->QuantumReset;
-  
-          /* Calculate new priority */
-          OldPriority = CurrentThread->Priority;
-          if (OldPriority < LOW_REALTIME_PRIORITY)
+          /* Make sure that we're not real-time or without a quantum */
+          if ((Thread->Priority < LOW_REALTIME_PRIORITY) &&
+              !(Thread->ApcState.Process->DisableQuantum))
           {
-              /* Set the New Priority and add the Priority Decrement */
-              NewPriority = OldPriority - CurrentThread->PriorityDecrement - 1;
-  
-              /* Don't go out of bounds */
-              if (NewPriority < CurrentThread->BasePriority)
-              {
-                  NewPriority = CurrentThread->BasePriority;
-              }
+              /* Reset the new Quantum */
+              Thread->Quantum = Thread->QuantumReset;
   
-              /* Reset the priority decrement */
-              CurrentThread->PriorityDecrement = 0;
+              /* Calculate new priority */
+              Priority = Thread->Priority = KiComputeNewPriority(Thread);
   
-              /* Set a new priority if needed */
-              if (OldPriority != NewPriority)
+              /* Check if a new thread is scheduled */
+              if (!Prcb->NextThread)
               {
-                  /* Set new Priority */
-                  BOOLEAN Dummy; /* <- This is a hack anyways... */
-                  KiSetPriorityThread(CurrentThread, NewPriority, &Dummy);
+                  /* FIXME: TODO. Add code from new scheduler */
               }
               else
               {
@@@@ -336,13 -358,9 -358,9 +358,13 @@@@ KeInsertQueueDpc(IN PKDPC Dpc
                        */
                       if (((Dpc->Importance == HighImportance) ||
                           (DpcData->DpcQueueDepth >=
 --                         Prcb->MaximumDpcQueueDepth)) &&
 ++                         Prcb->MaximumDpcQueueDepth))
 ++#ifndef _M_PPC
 ++                                 &&
-                          (!(AFFINITY_MASK(Cpu) & IdleProcessorMask) ||
+                          (!(AFFINITY_MASK(Cpu) & KiIdleSummary) ||
 --                         (Prcb->Sleeping)))
 ++                         (Prcb->Sleeping))
 ++#endif
 ++                    )
                       {
                           /* Set interrupt requested */
                           Prcb->DpcInterruptRequested = TRUE;
@@@@ -22,46 -22,311 -22,311 +22,310 @@@@ static CHAR KeLoaderModuleStrings[64][2
   /* FreeLDR Memory Data */
   ADDRESS_RANGE KeMemoryMap[64];
   ULONG KeMemoryMapRangeCount;
---ULONG_PTR FirstKrnlPhysAddr;
---ULONG_PTR LastKrnlPhysAddr;
---ULONG_PTR LastKernelAddress;
 --ULONG MmFreeLdrMemHigher, MmFreeLdrMemLower;
 --ULONG MmFreeLdrPageDirectoryStart, MmFreeLdrPageDirectoryEnd;
+++ULONG_PTR MmFreeLdrFirstKrnlPhysAddr, MmFreeLdrLastKrnlPhysAddr;
+++ULONG_PTR MmFreeLdrLastKernelAddress;
+++ULONG MmFreeLdrMemHigher;
+++ULONG MmFreeLdrPageDirectoryEnd;
   
   /* FreeLDR Loader Data */
-  ROS_LOADER_PARAMETER_BLOCK KeLoaderBlock;
+  ROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
   static CHAR KeLoaderCommandLine[256];
+  BOOLEAN AcpiTableDetected;
   
   /* FreeLDR PE Hack Data */
---extern unsigned int _image_base__;
---ULONG_PTR KERNEL_BASE = (ULONG_PTR)&_image_base__;
   extern LDR_DATA_TABLE_ENTRY HalModuleObject;
   
+  /* NT Loader Data */
+  LOADER_PARAMETER_BLOCK BldrLoaderBlock;
+  LOADER_PARAMETER_EXTENSION BldrExtensionBlock;
+  CHAR BldrCommandLine[256];
+  CHAR BldrArcBootPath[64];
+  CHAR BldrArcHalPath[64];
+  CHAR BldrNtHalPath[64];
+  CHAR BldrNtBootPath[64];
+  LDR_DATA_TABLE_ENTRY BldrModules[64];
+  MEMORY_ALLOCATION_DESCRIPTOR BldrMemoryDescriptors[64];
+  WCHAR BldrModuleStrings[64][260];
+  NLS_DATA_BLOCK BldrNlsDataBlock;
+  SETUP_LOADER_BLOCK BldrSetupBlock;
+  
   /* FUNCTIONS *****************************************************************/
   
   VOID
   NTAPI
-  KiRosPrepareForSystemStartup(IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
+  KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
+                       IN PLOADER_PARAMETER_BLOCK *NtLoaderBlock)
+  {
+      PLOADER_PARAMETER_BLOCK LoaderBlock;
+      PLDR_DATA_TABLE_ENTRY LdrEntry;
+      PMEMORY_ALLOCATION_DESCRIPTOR MdEntry;
+      PLOADER_MODULE RosEntry;
+      ULONG i, j, ModSize;
+      PVOID ModStart;
+      PCHAR DriverName;
+      PCHAR BootPath, HalPath;
+      CHAR CommandLine[256];
+  
+      /* First get some kernel-loader globals */
+      AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
+      MmFreeLdrMemHigher = RosLoaderBlock->MemHigher;
 --    MmFreeLdrMemLower = RosLoaderBlock->MemLower;
 --    MmFreeLdrPageDirectoryStart = RosLoaderBlock->PageDirectoryStart;
+      MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
+      KeLoaderModuleCount = RosLoaderBlock->ModsCount;
+  
+      /* Set the NT Loader block and initialize it */
+      *NtLoaderBlock = LoaderBlock = &BldrLoaderBlock;
+      RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
+  
+      /* Set the NLS Data block */
+      LoaderBlock->NlsData = &BldrNlsDataBlock;
+  
+      /* Assume this is from FreeLDR's SetupLdr */
+      LoaderBlock->SetupLdrBlock = &BldrSetupBlock;
+  
+      /* Setup the list heads */
+      InitializeListHead(&LoaderBlock->LoadOrderListHead);
+      InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
+      InitializeListHead(&LoaderBlock->BootDriverListHead);
+  
+      /* Loop boot driver list */
+      for (i = 0; i < KeLoaderModuleCount; i++)
+      {
+          /* Get the ROS loader entry */
+          RosEntry = &KeLoaderModules[i];
+          DriverName = (PCHAR)RosEntry->String;
+          ModStart = (PVOID)RosEntry->ModStart;
+          ModSize = RosEntry->ModEnd - (ULONG_PTR)ModStart;
+  
+          /* Check if this is any of the NLS files */
+          if (!_stricmp(DriverName, "ansi.nls"))
+          {
+              /* ANSI Code page */
+              LoaderBlock->NlsData->AnsiCodePageData = ModStart;
+  
+              /* Create an MD for it */
+              MdEntry = &BldrMemoryDescriptors[i];
+              MdEntry->MemoryType = LoaderNlsData;
+              MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+              MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+              InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+                             &MdEntry->ListEntry);
+              continue;
+          }
+          else if (!_stricmp(DriverName, "oem.nls"))
+          {
+              /* OEM Code page */
+              LoaderBlock->NlsData->OemCodePageData = ModStart;
+  
+              /* Create an MD for it */
+              MdEntry = &BldrMemoryDescriptors[i];
+              MdEntry->MemoryType = LoaderNlsData;
+              MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+              MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+              InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+                             &MdEntry->ListEntry);
+              continue;
+          }
+          else if (!_stricmp(DriverName, "casemap.nls"))
+          {
+              /* Unicode Code page */
+              LoaderBlock->NlsData->UnicodeCodePageData = ModStart;
+  
+              /* Create an MD for it */
+              MdEntry = &BldrMemoryDescriptors[i];
+              MdEntry->MemoryType = LoaderNlsData;
+              MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+              MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+              InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+                             &MdEntry->ListEntry);
+              continue;
+          }
+  
+          /* Check if this is the SYSTEM hive */
+          if (!(_stricmp(DriverName, "system")) ||
+              !(_stricmp(DriverName, "system.hiv")))
+          {
+              /* Save registry data */
+              LoaderBlock->RegistryBase = ModStart;
+              LoaderBlock->RegistryLength = ModSize;
+  
+              /* Disable setup mode */
+              LoaderBlock->SetupLdrBlock = NULL;
+  
+              /* Create an MD for it */
+              MdEntry = &BldrMemoryDescriptors[i];
+              MdEntry->MemoryType = LoaderRegistryData;
+              MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+              MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+              InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+                             &MdEntry->ListEntry);
+              continue;
+          }
+  
+          /* Check if this is the HARDWARE hive */
+          if (!(_stricmp(DriverName, "hardware")) ||
+              !(_stricmp(DriverName, "hardware.hiv")))
+          {
+              /* Create an MD for it */
+              MdEntry = &BldrMemoryDescriptors[i];
+              MdEntry->MemoryType = LoaderRegistryData;
+              MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+              MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+              InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+                             &MdEntry->ListEntry);
+              continue;
+          }
+  
+          /* Setup the loader entry */
+          LdrEntry = &BldrModules[i];
+          RtlZeroMemory(LdrEntry, sizeof(LDR_DATA_TABLE_ENTRY));
+  
+          /* Convert driver name from ANSI to Unicode */
+          for (j = 0; j < strlen(DriverName); j++)
+          {
+              BldrModuleStrings[i][j] = DriverName[j];
+          }
+  
+          /* Setup driver name */
+          RtlInitUnicodeString(&LdrEntry->BaseDllName, BldrModuleStrings[i]);
+          RtlInitUnicodeString(&LdrEntry->FullDllName, BldrModuleStrings[i]);
+  
+          /* Copy data from Freeldr Module Entry */
+          LdrEntry->DllBase = ModStart;
+          LdrEntry->SizeOfImage = ModSize;
+  
+          /* Initialize other data */
+          LdrEntry->LoadCount = 1;
+          LdrEntry->Flags = LDRP_IMAGE_DLL |
+                            LDRP_ENTRY_PROCESSED;
+          if (RosEntry->Reserved) LdrEntry->Flags |= LDRP_ENTRY_INSERTED;
+  
+          /* Insert it into the loader block */
+          InsertTailList(&LoaderBlock->LoadOrderListHead,
+                         &LdrEntry->InLoadOrderLinks);
+  
+          /* Check if this is the kernel */
+          if (!(_stricmp(DriverName, "ntoskrnl.exe")))
+          {
+              /* Create an MD for it */
+              MdEntry = &BldrMemoryDescriptors[i];
+              MdEntry->MemoryType = LoaderSystemCode;
+              MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+              MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+              InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+                             &MdEntry->ListEntry);
+          }
+          else if (!(_stricmp(DriverName, "hal.dll")))
+          {
+++            /* The HAL actually gets loaded somewhere else */
+++            ModStart = HalModuleObject.DllBase;
+++
+              /* Create an MD for the HAL */
+              MdEntry = &BldrMemoryDescriptors[i];
+              MdEntry->MemoryType = LoaderHalCode;
+              MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+              MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+              InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+                             &MdEntry->ListEntry);
+          }
+          else
+          {
+              /* Create an MD for any driver */
+              MdEntry = &BldrMemoryDescriptors[i];
+              MdEntry->MemoryType = LoaderBootDriver;
+              MdEntry->BasePage = (ULONG_PTR)ModStart >> PAGE_SHIFT;
+              MdEntry->PageCount = ModSize >> PAGE_SHIFT;
+              InsertTailList(&LoaderBlock->MemoryDescriptorListHead,
+                             &MdEntry->ListEntry);
+          }
+      }
+  
+      /* Setup command line */
+      LoaderBlock->LoadOptions = BldrCommandLine;
+      strcpy(BldrCommandLine, KeLoaderCommandLine);
+  
+      /* Setup the extension block */
+      LoaderBlock->Extension = &BldrExtensionBlock;
+      LoaderBlock->Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
+      LoaderBlock->Extension->MajorVersion = 5;
+      LoaderBlock->Extension->MinorVersion = 2;
+  
+      /* Now setup the setup block if we have one */
+      if (LoaderBlock->SetupLdrBlock)
+      {
+          /* All we'll setup right now is the flag for text-mode setup */
+          LoaderBlock->SetupLdrBlock->Flags = 1;
+      }
+  
+      /* Make a copy of the command line */
+      strcpy(CommandLine, LoaderBlock->LoadOptions);
+  
+      /* Find the first \, separating the ARC path from NT path */
+      BootPath = strchr(CommandLine, '\\');
+      *BootPath = ANSI_NULL;
+      strncpy(BldrArcBootPath, CommandLine, 63);
+      LoaderBlock->ArcBootDeviceName = BldrArcBootPath;
+  
+      /* The rest of the string is the NT path */
+      HalPath = strchr(BootPath + 1, ' ');
+      *HalPath = ANSI_NULL;
+      BldrNtBootPath[0] = '\\';
+      strncat(BldrNtBootPath, BootPath + 1, 63);
+      strcat(BldrNtBootPath,"\\");
+      LoaderBlock->NtBootPathName = BldrNtBootPath;
+  
+      /* Set the HAL paths */
+      strncpy(BldrArcHalPath, BldrArcBootPath, 63);
+      LoaderBlock->ArcHalDeviceName = BldrArcHalPath;
+      strcpy(BldrNtHalPath, "\\");
+      LoaderBlock->NtHalPathName = BldrNtHalPath;
+  
+      /* Use this new command line */
+      strncpy(LoaderBlock->LoadOptions, HalPath + 2, 255);
+  
+      /* Parse it and change every slash to a space */
+      BootPath = LoaderBlock->LoadOptions;
+      do {if (*BootPath == '/') *BootPath = ' ';} while (*BootPath++);
+  }
+  
+  VOID
+  FASTCALL
+  KiRosPrepareForSystemStartup(IN ULONG Dummy,
+                               IN PROS_LOADER_PARAMETER_BLOCK LoaderBlock)
   {
-  #ifdef _M_IX86
       ULONG i;
       ULONG size;
       ULONG HalBase;
       ULONG DriverBase;
       ULONG DriverSize;
---    PIMAGE_NT_HEADERS NtHeader;
---    PIMAGE_OPTIONAL_HEADER OptHead;
+      PLOADER_PARAMETER_BLOCK NtLoaderBlock;
       CHAR* s;
+++#ifdef _M_IX86
+      PKTSS Tss;
+      PKGDTENTRY TssEntry;
+++#endif
   
+++#ifdef _M_IX86
       /* Load the GDT and IDT */
       Ke386SetGlobalDescriptorTable(KiGdtDescriptor);
       Ke386SetInterruptDescriptorTable(KiIdtDescriptor);
   
+      /* Initialize the boot TSS */
+      Tss = &KiBootTss;
+      TssEntry = &KiBootGdt[KGDT_TSS / sizeof(KGDTENTRY)];
+      TssEntry->HighWord.Bits.Type = I386_TSS;
+      TssEntry->HighWord.Bits.Pres = 1;
+      TssEntry->HighWord.Bits.Dpl = 0;
+      TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
+      TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
+      TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
+++#endif
+  
       /* Copy the Loader Block Data locally since Low-Memory will be wiped */
-      memcpy(&KeLoaderBlock, LoaderBlock, sizeof(ROS_LOADER_PARAMETER_BLOCK));
-      memcpy(&KeLoaderModules[1],
-             (PVOID)KeLoaderBlock.ModsAddr,
-             sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
-      KeLoaderBlock.ModsCount++;
-      KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
+      memcpy(&KeRosLoaderBlock, LoaderBlock, sizeof(ROS_LOADER_PARAMETER_BLOCK));
 --    memcpy(&KeLoaderModules[1],
+++    memcpy(&KeLoaderModules[0],
+             (PVOID)KeRosLoaderBlock.ModsAddr,
+             sizeof(LOADER_MODULE) * KeRosLoaderBlock.ModsCount);
 --    KeRosLoaderBlock.ModsCount++;
+      KeRosLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
   
       /* Check for BIOS memory map */
       KeMemoryMapRangeCount = 0;
   
       /* Set the Command Line */
       strcpy(KeLoaderCommandLine, (PCHAR)LoaderBlock->CommandLine);
-      KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
-  
-      /* Write the first Module (the Kernel) */
-      strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
-      KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
-      KeLoaderModules[0].ModStart = KERNEL_BASE;
-  
-      /* Read PE Data */
-      NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
-      OptHead = &NtHeader->OptionalHeader;
-  
-      /* Set Kernel Ending */
-      KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart +
-                                  PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
+      KeRosLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
   
 --    /* Write the first Module (the Kernel) */
 --    strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
 --    KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
 --    KeLoaderModules[0].ModStart = KERNEL_BASE;
 --
 --    /* Read PE Data */
 --    NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
 --    OptHead = &NtHeader->OptionalHeader;
 --
 --    /* Set Kernel Ending */
 --    KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart +
 --                                PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
 --
       /* Create a block for each module */
-      for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+      for (i = 1; i < KeRosLoaderBlock.ModsCount; i++)
       {
           /* Check if we have to copy the path or not */
           if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0)
               strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
           }
   
+++#ifdef _M_IX86
           /* Substract the base Address in Physical Memory */
           KeLoaderModules[i].ModStart -= 0x200000;
   
           /* Add the Kernel Base Address in Virtual Memory */
---        KeLoaderModules[i].ModStart += KERNEL_BASE;
+++        KeLoaderModules[i].ModStart += KSEG0_BASE;
   
           /* Substract the base Address in Physical Memory */
           KeLoaderModules[i].ModEnd -= 0x200000;
   
           /* Add the Kernel Base Address in Virtual Memory */
---        KeLoaderModules[i].ModEnd += KERNEL_BASE;
+++        KeLoaderModules[i].ModEnd += KSEG0_BASE;
+++#endif
   
           /* Select the proper String */
           KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
       }
   
       /* Choose last module address as the final kernel address */
-      LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.
 --    LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeRosLoaderBlock.
---                                                      ModsCount - 1].ModEnd);
+++    MmFreeLdrLastKernelAddress =
+++        PAGE_ROUND_UP(KeLoaderModules[KeRosLoaderBlock.ModsCount - 1].ModEnd);
   
       /* Select the HAL Base */
       HalBase = KeLoaderModules[1].ModStart;
   
       /* Choose Driver Base */
---    DriverBase = LastKernelAddress;
+++    DriverBase = MmFreeLdrLastKernelAddress;
       LdrHalBase = (ULONG_PTR)DriverBase;
   
       /* Initialize Module Management */
---    LdrInitModuleManagement();
+++    LdrInitModuleManagement((PVOID)KeLoaderModules[0].ModStart);
   
       /* Load HAL.DLL with the PE Loader */
       LdrSafePEProcessModule((PVOID)HalBase,
                               (PVOID)DriverBase,
---                            (PVOID)KERNEL_BASE,
+++                            (PVOID)KeLoaderModules[0].ModStart,
                               &DriverSize);
   
       //
                                                       OptionalHeader.SizeOfImage;
   
       /* Increase the last kernel address with the size of HAL */
---    LastKernelAddress += PAGE_ROUND_UP(DriverSize);
+++    MmFreeLdrLastKernelAddress += PAGE_ROUND_UP(DriverSize);
   
+++#ifdef _M_IX86
       /* Now select the final beginning and ending Kernel Addresses */
---    FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000;
---    LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
+++    MmFreeLdrFirstKrnlPhysAddr = KeLoaderModules[0].ModStart -
+++                                 KSEG0_BASE + 0x200000;
+++    MmFreeLdrLastKrnlPhysAddr = MmFreeLdrLastKernelAddress -
+++                                KSEG0_BASE + 0x200000;
+++#endif
   
       /* Setup the IDT */
       KeInitExceptions(); // ONCE HACK BELOW IS GONE, MOVE TO KISYSTEMSTARTUP!
       KeInitInterrupts(); // ROS HACK DEPRECATED SOON BY NEW HAL
-  #elif defined(_M_PPC)
-      ULONG DriverBase = 0;
-      ULONG DriverSize = 0;
-      
-      memset( KeLoaderModules, 0, sizeof(KeLoaderModules) );
-      memset( KeLoaderCommandLine, 0, sizeof(KeLoaderCommandLine) );
-      memset( KeLoaderModuleStrings, 0, sizeof(KeLoaderModuleStrings) );
-  
-      /* Stop here for now -- we'll write this part later */
-      char *foo = 0;
-      *foo = 1;
-  #endif
   
       /* Load the Kernel with the PE Loader */
---    LdrSafePEProcessModule((PVOID)KERNEL_BASE,
---                           (PVOID)KERNEL_BASE,
+++    LdrSafePEProcessModule((PVOID)KeLoaderModules[0].ModStart,
+++                           (PVOID)KeLoaderModules[0].ModStart,
                              (PVOID)DriverBase,
                              &DriverSize);
   
Simple merge
---/*\r
--- * PROJECT:         ReactOS Kernel\r
--- * LICENSE:         GPL - See COPYING in the top level directory\r
--- * FILE:            ntoskrnl/ke/krnlinit.c\r
--- * PURPOSE:         Portable part of kernel initialization\r
--- * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)\r
--- */\r
---\r
-  /* INCLUDES *****************************************************************/\r
 --/* INCLUDES ******************************************************************/\r
---\r
---#include <ntoskrnl.h>\r
---#define NDEBUG\r
---#include <debug.h>\r
---#include <internal/napi.h>\r
---\r
---/* GLOBALS *******************************************************************/\r
 --\r
 --/* System call count */\r
 --ULONG KiServiceLimit = NUMBER_OF_SYSCALLS;\r
 --\r
 --/* ARC Loader Block */\r
 --PLOADER_PARAMETER_BLOCK KeLoaderBlock;\r
---\r
---/* PRCB Array */\r
---PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];\r
---\r
---/* NUMA Node Support */\r
---KNODE KiNode0;\r
---PKNODE KeNodeBlock[1];\r
---UCHAR KeNumberNodes = 1;\r
---UCHAR KeProcessNodeSeed;\r
---\r
---/* Initial Process and Thread */\r
---ETHREAD KiInitialThread;\r
---EPROCESS KiInitialProcess;\r
---\r
---/* System-defined Spinlocks */\r
---KSPIN_LOCK KiDispatcherLock;\r
---KSPIN_LOCK MmPfnLock;\r
---KSPIN_LOCK MmSystemSpaceLock;\r
---KSPIN_LOCK CcBcbSpinLock;\r
---KSPIN_LOCK CcMasterSpinLock;\r
---KSPIN_LOCK CcVacbSpinLock;\r
---KSPIN_LOCK CcWorkQueueSpinLock;\r
---KSPIN_LOCK NonPagedPoolLock;\r
---KSPIN_LOCK MmNonPagedPoolLock;\r
---KSPIN_LOCK IopCancelSpinLock;\r
---KSPIN_LOCK IopVpbSpinLock;\r
---KSPIN_LOCK IopDatabaseLock;\r
---KSPIN_LOCK IopCompletionLock;\r
---KSPIN_LOCK NtfsStructLock;\r
---KSPIN_LOCK AfdWorkQueueSpinLock;\r
---KSPIN_LOCK KiTimerTableLock[16];\r
---KSPIN_LOCK KiReverseStallIpiLock;\r
---\r
---/* FUNCTIONS *****************************************************************/\r
---\r
---VOID\r
---NTAPI\r
---KiInitSystem(VOID)\r
---{\r
---    ULONG i;\r
---\r
---    /* Initialize Bugcheck Callback data */\r
---    InitializeListHead(&BugcheckCallbackListHead);\r
---    InitializeListHead(&BugcheckReasonCallbackListHead);\r
---    KeInitializeSpinLock(&BugCheckCallbackLock);\r
---\r
---    /* Initialize the Timer Expiration DPC */\r
---    KeInitializeDpc(&KiExpireTimerDpc, KiExpireTimers, NULL);\r
---    KeSetTargetProcessorDpc(&KiExpireTimerDpc, 0);\r
---\r
---    /* Initialize Profiling data */\r
---    KeInitializeSpinLock(&KiProfileLock);\r
---    InitializeListHead(&KiProfileListHead);\r
---    InitializeListHead(&KiProfileSourceListHead);\r
---\r
---    /* Loop the timer table */\r
---    for (i = 0; i < TIMER_TABLE_SIZE; i++)\r
---    {\r
---        /* Initialize the list and entries */\r
---        InitializeListHead(&KiTimerTableListHead[i].Entry);\r
---        KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;\r
---        KiTimerTableListHead[i].Time.LowPart = 0;\r
---    }\r
---\r
---    /* Initialize old-style list */\r
---    InitializeListHead(&KiTimerListHead);\r
---\r
---    /* Initialize the Swap event and all swap lists */\r
---    KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);\r
---    InitializeListHead(&KiProcessInSwapListHead);\r
---    InitializeListHead(&KiProcessOutSwapListHead);\r
---    InitializeListHead(&KiStackInSwapListHead);\r
---\r
---    /* Initialize the mutex for generic DPC calls */\r
---    KeInitializeMutex(&KiGenericCallDpcMutex, 0);\r
---\r
---    /* Initialize the syscall table */\r
---    KeServiceDescriptorTable[0].Base = MainSSDT;\r
---    KeServiceDescriptorTable[0].Count = NULL;\r
-      KeServiceDescriptorTable[0].Limit = NUMBER_OF_SYSCALLS;\r
 --    KeServiceDescriptorTable[0].Limit = KiServiceLimit;\r
---    KeServiceDescriptorTable[1].Limit = 0;\r
---    KeServiceDescriptorTable[0].Number = MainSSPT;\r
---\r
---    /* Copy the the current table into the shadow table for win32k */\r
---    RtlCopyMemory(KeServiceDescriptorTableShadow,\r
---                  KeServiceDescriptorTable,\r
---                  sizeof(KeServiceDescriptorTable));\r
---}\r
---\r
---LARGE_INTEGER\r
---NTAPI\r
---KiComputeReciprocal(IN LONG Divisor,\r
---                    OUT PUCHAR Shift)\r
---{\r
---    LARGE_INTEGER Reciprocal = {{0}};\r
---    LONG BitCount = 0, Remainder = 1;\r
---\r
---    /* Start by calculating the remainder */\r
---    while (Reciprocal.HighPart >= 0)\r
---    {\r
---        /* Increase the loop (bit) count */\r
---        BitCount++;\r
---\r
---        /* Calculate the current fraction */\r
---        Reciprocal.HighPart = (Reciprocal.HighPart << 1) |\r
---                              (Reciprocal.LowPart >> 31);\r
---        Reciprocal.LowPart <<= 1;\r
---\r
---        /* Double the remainder and see if we went past the divisor */\r
---        Remainder <<= 1;\r
---        if (Remainder >= Divisor)\r
---        {\r
---            /* Set the low-bit and calculate the new remainder */\r
---            Remainder -= Divisor;\r
---            Reciprocal.LowPart |= 1;\r
---        }\r
---    }\r
---\r
---    /* Check if we have a remainder */\r
---    if (Remainder)\r
---    {\r
---        /* Check if the current fraction value is too large */\r
---        if ((Reciprocal.LowPart == 0xFFFFFFFF) &&\r
---            (Reciprocal.HighPart == 0xFFFFFFFF))\r
---        {\r
---            /* Set the high bit and reduce the bit count */\r
---            Reciprocal.LowPart = 0;\r
---            Reciprocal.HighPart = 0x80000000;\r
---            BitCount--;\r
---        }\r
---        else\r
---        {\r
---            /* Check if only the lowest bits got too large */\r
---            if (Reciprocal.LowPart == 0xFFFFFFFF)\r
---            {\r
---                /* Reset them and increase the high bits instead */\r
---                Reciprocal.LowPart = 0;\r
---                Reciprocal.HighPart++;\r
---            }\r
---            else\r
---            {\r
---                /* All is well, increase the low bits */\r
---                Reciprocal.LowPart++;\r
---            }\r
---        }\r
---    }\r
---\r
---    /* Now calculate the actual shift and return the reciprocal */\r
---    *Shift = (UCHAR)BitCount - 64;\r
---    return Reciprocal;\r
---}\r
---\r
---VOID\r
---NTAPI\r
---KiInitSpinLocks(IN PKPRCB Prcb,\r
---                IN CCHAR Number)\r
---{\r
---    ULONG i;\r
---\r
---    /* Initialize Dispatcher Fields */\r
---    Prcb->QueueIndex = 1;\r
---    Prcb->ReadySummary = 0;\r
---    Prcb->DeferredReadyListHead.Next = NULL;\r
---    for (i = 0; i < 32; i++)\r
---    {\r
---        /* Initialize the ready list */\r
---        InitializeListHead(&Prcb->DispatcherReadyListHead[i]);\r
---    }\r
---\r
---    /* Initialize DPC Fields */\r
---    InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);\r
---    KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);\r
---    Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;\r
---    Prcb->DpcData[DPC_NORMAL].DpcCount = 0;\r
---    Prcb->DpcRoutineActive = FALSE;\r
---    Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;\r
---    Prcb->MinimumDpcRate = KiMinimumDpcRate;\r
---    Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;\r
---    KeInitializeDpc(&Prcb->CallDpc, NULL, NULL);\r
---    KeSetTargetProcessorDpc(&Prcb->CallDpc, Number);\r
---    KeSetImportanceDpc(&Prcb->CallDpc, HighImportance);\r
---\r
---    /* Initialize the Wait List Head */\r
---    InitializeListHead(&Prcb->WaitListHead);\r
---\r
---    /* Initialize Queued Spinlocks */\r
---    Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock;\r
---    Prcb->LockQueue[LockQueueExpansionLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL;\r
---    Prcb->LockQueue[LockQueuePfnLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock;\r
---    Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock;\r
---    Prcb->LockQueue[LockQueueBcbLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock;\r
---    Prcb->LockQueue[LockQueueMasterLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock;\r
---    Prcb->LockQueue[LockQueueVacbLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock;\r
---    Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock;\r
---    Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock;\r
---    Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock;\r
---    Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock;\r
---    Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock;\r
---    Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock;\r
---    Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock;\r
---    Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock;\r
---    Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL;\r
---    Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;\r
---    Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;\r
---    Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;\r
---\r
---    /* Loop timer locks */\r
---    for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)\r
---    {\r
---        /* Initialize the lock and setup the Queued Spinlock */\r
---        KeInitializeSpinLock(&KiTimerTableLock[i]);\r
---        Prcb->LockQueue[i].Next = NULL;\r
---        Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];\r
---    }\r
---\r
---    /* Check if this is the boot CPU */\r
---    if (!Number)\r
---    {\r
---        /* Initialize the lock themselves */\r
---        KeInitializeSpinLock(&KiDispatcherLock);\r
---        KeInitializeSpinLock(&KiReverseStallIpiLock);\r
---        KeInitializeSpinLock(&MmPfnLock);\r
---        KeInitializeSpinLock(&MmSystemSpaceLock);\r
---        KeInitializeSpinLock(&CcBcbSpinLock);\r
---        KeInitializeSpinLock(&CcMasterSpinLock);\r
---        KeInitializeSpinLock(&CcVacbSpinLock);\r
---        KeInitializeSpinLock(&CcWorkQueueSpinLock);\r
---        KeInitializeSpinLock(&IopCancelSpinLock);\r
---        KeInitializeSpinLock(&IopCompletionLock);\r
---        KeInitializeSpinLock(&IopDatabaseLock);\r
---        KeInitializeSpinLock(&IopVpbSpinLock);\r
---        KeInitializeSpinLock(&NonPagedPoolLock);\r
---        KeInitializeSpinLock(&MmNonPagedPoolLock);\r
---        KeInitializeSpinLock(&NtfsStructLock);\r
---        KeInitializeSpinLock(&AfdWorkQueueSpinLock);\r
-          KeInitializeDispatcher(); // ROS OLD DISPATCHER\r
---    }\r
---}\r
---\r
-  /* FIXME: Rename and make portable */\r
-  VOID\r
 --BOOLEAN\r
---NTAPI\r
-  KeInit2(VOID)\r
 --KeInitSystem(VOID)\r
---{\r
-      ULONG Protect;\r
-  \r
-  #ifdef _M_IX86\r
-      /* Check if Fxsr was found */\r
-      if (KeI386FxsrPresent)\r
-      {\r
-          /* Enable it. FIXME: Send an IPI */\r
-          Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSFXSR);\r
-  \r
-          /* Check if XMM was found too */\r
-          if (KeI386XMMIPresent)\r
-          {\r
-              /* Enable it: FIXME: Send an IPI. */\r
-              Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSXMMEXCPT);\r
-  \r
-              /* FIXME: Implement and enable XMM Page Zeroing for Mm */\r
-          }\r
-      }\r
-  \r
-      if (KeFeatureBits & KF_GLOBAL_PAGE)\r
-      {\r
-          ULONG Flags;\r
-          /* Enable global pages */\r
-          Ke386GlobalPagesEnabled = TRUE;\r
-          Ke386SaveFlags(Flags);\r
-          Ke386DisableInterrupts();\r
-          Ke386SetCr4(Ke386GetCr4() | X86_CR4_PGE);\r
-          Ke386RestoreFlags(Flags);\r
-      }\r
-  \r
-      if (KeFeatureBits & KF_FAST_SYSCALL)\r
-      {\r
-          extern void KiFastCallEntry(void);\r
-  \r
-          /* CS Selector of the target segment. */\r
-          Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);\r
-          /* Target ESP. */\r
-          Ke386Wrmsr(0x175, 0, 0);\r
-          /* Target EIP. */\r
-          Ke386Wrmsr(0x176, (ULONG_PTR)KiFastCallEntry, 0);\r
-      }\r
-  #endif\r
-  \r
-      /* Does the CPU Support 'prefetchnta' (SSE)  */\r
-      if(KeFeatureBits & KF_XMMI)\r
 --    /* Check if Threaded DPCs are enabled */\r
 --    if (KeThreadDpcEnable)\r
---    {\r
-          Protect = MmGetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal);\r
-          MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect | PAGE_IS_WRITABLE);\r
-          /* Replace the ret by a nop */\r
-          *(PCHAR)RtlPrefetchMemoryNonTemporal = 0x90;\r
-          MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect);\r
 --        /* FIXME: TODO */\r
 --        DPRINT1("Threaded DPCs not yet supported\n");\r
---    }\r
---\r
-      /* Set IDT to writable */\r
-  #ifdef _M_IX86\r
-      Protect = MmGetPageProtect(NULL, (PVOID)KiIdt);\r
-      MmSetPageProtect(NULL, (PVOID)KiIdt, Protect | PAGE_IS_WRITABLE);\r
-  #endif\r
 --    /* Initialize non-portable parts of the kernel */\r
 --    KiInitMachineDependent();\r
 --    return TRUE;\r
---}\r
 --\r
+++/*
+++ * PROJECT:         ReactOS Kernel
+++ * LICENSE:         GPL - See COPYING in the top level directory
+++ * FILE:            ntoskrnl/ke/krnlinit.c
+++ * PURPOSE:         Portable part of kernel initialization
+++ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+++ */
+++
+++/* INCLUDES ******************************************************************/
+++
+++#include <ntoskrnl.h>
+++#define NDEBUG
+++#include <debug.h>
+++#include <internal/napi.h>
+++
+++/* GLOBALS *******************************************************************/
+++
+++/* System call count */
+++ULONG KiServiceLimit = NUMBER_OF_SYSCALLS;
+++
+++/* ARC Loader Block */
+++PLOADER_PARAMETER_BLOCK KeLoaderBlock;
+++
+++/* PRCB Array */
+++PKPRCB KiProcessorBlock[MAXIMUM_PROCESSORS];
+++
+++/* NUMA Node Support */
+++KNODE KiNode0;
+++PKNODE KeNodeBlock[1];
+++UCHAR KeNumberNodes = 1;
+++UCHAR KeProcessNodeSeed;
+++
+++/* Initial Process and Thread */
+++ETHREAD KiInitialThread;
+++EPROCESS KiInitialProcess;
+++
+++/* System-defined Spinlocks */
+++KSPIN_LOCK KiDispatcherLock;
+++KSPIN_LOCK MmPfnLock;
+++KSPIN_LOCK MmSystemSpaceLock;
+++KSPIN_LOCK CcBcbSpinLock;
+++KSPIN_LOCK CcMasterSpinLock;
+++KSPIN_LOCK CcVacbSpinLock;
+++KSPIN_LOCK CcWorkQueueSpinLock;
+++KSPIN_LOCK NonPagedPoolLock;
+++KSPIN_LOCK MmNonPagedPoolLock;
+++KSPIN_LOCK IopCancelSpinLock;
+++KSPIN_LOCK IopVpbSpinLock;
+++KSPIN_LOCK IopDatabaseLock;
+++KSPIN_LOCK IopCompletionLock;
+++KSPIN_LOCK NtfsStructLock;
+++KSPIN_LOCK AfdWorkQueueSpinLock;
+++KSPIN_LOCK KiTimerTableLock[16];
+++KSPIN_LOCK KiReverseStallIpiLock;
+++
+++/* FUNCTIONS *****************************************************************/
+++
+++VOID
+++NTAPI
+++KiInitSystem(VOID)
+++{
+++    ULONG i;
+++
+++    /* Initialize Bugcheck Callback data */
+++    InitializeListHead(&BugcheckCallbackListHead);
+++    InitializeListHead(&BugcheckReasonCallbackListHead);
+++    KeInitializeSpinLock(&BugCheckCallbackLock);
+++
+++    /* Initialize the Timer Expiration DPC */
+++    KeInitializeDpc(&KiExpireTimerDpc, KiExpireTimers, NULL);
+++    KeSetTargetProcessorDpc(&KiExpireTimerDpc, 0);
+++
+++    /* Initialize Profiling data */
+++    KeInitializeSpinLock(&KiProfileLock);
+++    InitializeListHead(&KiProfileListHead);
+++    InitializeListHead(&KiProfileSourceListHead);
+++
+++    /* Loop the timer table */
+++    for (i = 0; i < TIMER_TABLE_SIZE; i++)
+++    {
+++        /* Initialize the list and entries */
+++        InitializeListHead(&KiTimerTableListHead[i].Entry);
+++        KiTimerTableListHead[i].Time.HighPart = 0xFFFFFFFF;
+++        KiTimerTableListHead[i].Time.LowPart = 0;
+++    }
+++
+++    /* Initialize old-style list */
+++    InitializeListHead(&KiTimerListHead);
+++
+++    /* Initialize the Swap event and all swap lists */
+++    KeInitializeEvent(&KiSwapEvent, SynchronizationEvent, FALSE);
+++    InitializeListHead(&KiProcessInSwapListHead);
+++    InitializeListHead(&KiProcessOutSwapListHead);
+++    InitializeListHead(&KiStackInSwapListHead);
+++
+++    /* Initialize the mutex for generic DPC calls */
+++    KeInitializeMutex(&KiGenericCallDpcMutex, 0);
+++
+++    /* Initialize the syscall table */
+++    KeServiceDescriptorTable[0].Base = MainSSDT;
+++    KeServiceDescriptorTable[0].Count = NULL;
+++    KeServiceDescriptorTable[0].Limit = KiServiceLimit;
+++    KeServiceDescriptorTable[1].Limit = 0;
+++    KeServiceDescriptorTable[0].Number = MainSSPT;
+++
+++    /* Copy the the current table into the shadow table for win32k */
+++    RtlCopyMemory(KeServiceDescriptorTableShadow,
+++                  KeServiceDescriptorTable,
+++                  sizeof(KeServiceDescriptorTable));
+++}
+++
+++LARGE_INTEGER
+++NTAPI
+++KiComputeReciprocal(IN LONG Divisor,
+++                    OUT PUCHAR Shift)
+++{
+++    LARGE_INTEGER Reciprocal = {{0}};
+++    LONG BitCount = 0, Remainder = 1;
+++
+++    /* Start by calculating the remainder */
+++    while (Reciprocal.HighPart >= 0)
+++    {
+++        /* Increase the loop (bit) count */
+++        BitCount++;
+++
+++        /* Calculate the current fraction */
+++        Reciprocal.HighPart = (Reciprocal.HighPart << 1) |
+++                              (Reciprocal.LowPart >> 31);
+++        Reciprocal.LowPart <<= 1;
+++
+++        /* Double the remainder and see if we went past the divisor */
+++        Remainder <<= 1;
+++        if (Remainder >= Divisor)
+++        {
+++            /* Set the low-bit and calculate the new remainder */
+++            Remainder -= Divisor;
+++            Reciprocal.LowPart |= 1;
+++        }
+++    }
+++
+++    /* Check if we have a remainder */
+++    if (Remainder)
+++    {
+++        /* Check if the current fraction value is too large */
+++        if ((Reciprocal.LowPart == 0xFFFFFFFF) &&
+++            (Reciprocal.HighPart == 0xFFFFFFFF))
+++        {
+++            /* Set the high bit and reduce the bit count */
+++            Reciprocal.LowPart = 0;
+++            Reciprocal.HighPart = 0x80000000;
+++            BitCount--;
+++        }
+++        else
+++        {
+++            /* Check if only the lowest bits got too large */
+++            if (Reciprocal.LowPart == 0xFFFFFFFF)
+++            {
+++                /* Reset them and increase the high bits instead */
+++                Reciprocal.LowPart = 0;
+++                Reciprocal.HighPart++;
+++            }
+++            else
+++            {
+++                /* All is well, increase the low bits */
+++                Reciprocal.LowPart++;
+++            }
+++        }
+++    }
+++
+++    /* Now calculate the actual shift and return the reciprocal */
+++    *Shift = (UCHAR)BitCount - 64;
+++    return Reciprocal;
+++}
+++
+++VOID
+++NTAPI
+++KiInitSpinLocks(IN PKPRCB Prcb,
+++                IN CCHAR Number)
+++{
+++    ULONG i;
+++
+++    /* Initialize Dispatcher Fields */
+++    Prcb->QueueIndex = 1;
+++    Prcb->ReadySummary = 0;
+++    Prcb->DeferredReadyListHead.Next = NULL;
+++    for (i = 0; i < 32; i++)
+++    {
+++        /* Initialize the ready list */
+++        InitializeListHead(&Prcb->DispatcherReadyListHead[i]);
+++    }
+++
+++    /* Initialize DPC Fields */
+++    InitializeListHead(&Prcb->DpcData[DPC_NORMAL].DpcListHead);
+++    KeInitializeSpinLock(&Prcb->DpcData[DPC_NORMAL].DpcLock);
+++    Prcb->DpcData[DPC_NORMAL].DpcQueueDepth = 0;
+++    Prcb->DpcData[DPC_NORMAL].DpcCount = 0;
+++    Prcb->DpcRoutineActive = FALSE;
+++    Prcb->MaximumDpcQueueDepth = KiMaximumDpcQueueDepth;
+++    Prcb->MinimumDpcRate = KiMinimumDpcRate;
+++    Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold;
+++    KeInitializeDpc(&Prcb->CallDpc, NULL, NULL);
+++    KeSetTargetProcessorDpc(&Prcb->CallDpc, Number);
+++    KeSetImportanceDpc(&Prcb->CallDpc, HighImportance);
+++
+++    /* Initialize the Wait List Head */
+++    InitializeListHead(&Prcb->WaitListHead);
+++
+++    /* Initialize Queued Spinlocks */
+++    Prcb->LockQueue[LockQueueDispatcherLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueDispatcherLock].Lock = &KiDispatcherLock;
+++    Prcb->LockQueue[LockQueueExpansionLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueExpansionLock].Lock = NULL;
+++    Prcb->LockQueue[LockQueuePfnLock].Next = NULL;
+++    Prcb->LockQueue[LockQueuePfnLock].Lock = &MmPfnLock;
+++    Prcb->LockQueue[LockQueueSystemSpaceLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueSystemSpaceLock].Lock = &MmSystemSpaceLock;
+++    Prcb->LockQueue[LockQueueBcbLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueBcbLock].Lock = &CcBcbSpinLock;
+++    Prcb->LockQueue[LockQueueMasterLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueMasterLock].Lock = &CcMasterSpinLock;
+++    Prcb->LockQueue[LockQueueVacbLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueVacbLock].Lock = &CcVacbSpinLock;
+++    Prcb->LockQueue[LockQueueWorkQueueLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueWorkQueueLock].Lock = &CcWorkQueueSpinLock;
+++    Prcb->LockQueue[LockQueueNonPagedPoolLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueNonPagedPoolLock].Lock = &NonPagedPoolLock;
+++    Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueMmNonPagedPoolLock].Lock = &MmNonPagedPoolLock;
+++    Prcb->LockQueue[LockQueueIoCancelLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueIoCancelLock].Lock = &IopCancelSpinLock;
+++    Prcb->LockQueue[LockQueueIoVpbLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueIoVpbLock].Lock = &IopVpbSpinLock;
+++    Prcb->LockQueue[LockQueueIoDatabaseLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueIoDatabaseLock].Lock = &IopDatabaseLock;
+++    Prcb->LockQueue[LockQueueIoCompletionLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueIoCompletionLock].Lock = &IopCompletionLock;
+++    Prcb->LockQueue[LockQueueNtfsStructLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueNtfsStructLock].Lock = &NtfsStructLock;
+++    Prcb->LockQueue[LockQueueAfdWorkQueueLock].Next = NULL;
+++    Prcb->LockQueue[LockQueueAfdWorkQueueLock].Lock = &AfdWorkQueueSpinLock;
+++    Prcb->LockQueue[LockQueueUnusedSpare16].Next = NULL;
+++    Prcb->LockQueue[LockQueueUnusedSpare16].Lock = NULL;
+++
+++    /* Loop timer locks */
+++    for (i = 0; i < LOCK_QUEUE_TIMER_TABLE_LOCKS; i++)
+++    {
+++        /* Initialize the lock and setup the Queued Spinlock */
+++        KeInitializeSpinLock(&KiTimerTableLock[i]);
+++        Prcb->LockQueue[i].Next = NULL;
+++        Prcb->LockQueue[i].Lock = &KiTimerTableLock[i];
+++    }
+++
+++    /* Check if this is the boot CPU */
+++    if (!Number)
+++    {
+++        /* Initialize the lock themselves */
+++        KeInitializeSpinLock(&KiDispatcherLock);
+++        KeInitializeSpinLock(&KiReverseStallIpiLock);
+++        KeInitializeSpinLock(&MmPfnLock);
+++        KeInitializeSpinLock(&MmSystemSpaceLock);
+++        KeInitializeSpinLock(&CcBcbSpinLock);
+++        KeInitializeSpinLock(&CcMasterSpinLock);
+++        KeInitializeSpinLock(&CcVacbSpinLock);
+++        KeInitializeSpinLock(&CcWorkQueueSpinLock);
+++        KeInitializeSpinLock(&IopCancelSpinLock);
+++        KeInitializeSpinLock(&IopCompletionLock);
+++        KeInitializeSpinLock(&IopDatabaseLock);
+++        KeInitializeSpinLock(&IopVpbSpinLock);
+++        KeInitializeSpinLock(&NonPagedPoolLock);
+++        KeInitializeSpinLock(&MmNonPagedPoolLock);
+++        KeInitializeSpinLock(&NtfsStructLock);
+++        KeInitializeSpinLock(&AfdWorkQueueSpinLock);
+++    }
+++}
+++
+++BOOLEAN
+++NTAPI
+++KeInitSystem(VOID)
+++{
+++    /* Check if Threaded DPCs are enabled */
+++    if (KeThreadDpcEnable)
+++    {
+++        /* FIXME: TODO */
+++        DPRINT1("Threaded DPCs not yet supported\n");
+++    }
+++
+++    /* Initialize non-portable parts of the kernel */
+++    KiInitMachineDependent();
+++    return TRUE;
+++}
+++
@@@@ -129,11 -155,9 -155,9 +155,11 @@@@ KeInitializeProcess(IN OUT PKPROCESS Pr
       Process->Affinity = Affinity;
       Process->BasePriority = (CHAR)Priority;
       Process->QuantumReset = 6;
-      Process->DirectoryTableBase = DirectoryTableBase;
-      Process->AutoAlignment = TRUE;
+      Process->DirectoryTableBase = *DirectoryTableBase;
+      Process->AutoAlignment = Enable;
 ++#ifdef _M_IX86
-      Process->IopmOffset = 0xFFFF;
+      Process->IopmOffset = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
 ++#endif
   
       /* Initialize the lists */
       InitializeListHead(&Process->ThreadListHead);
index 0000000,e4c683b,e4c683b..60b6200
mode 000000,100644,100644..100644
--- /dev/null
@@@@ -1,0 -1,1362 -1,1362 +1,1370 @@@@
+  /*\r
+   * PROJECT:         ReactOS Kernel\r
+   * LICENSE:         GPL - See COPYING in the top level directory\r
+   * FILE:            ntoskrnl/ke/thrdobj.c\r
+   * PURPOSE:         Implements routines to manage the Kernel Thread Object\r
+   * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)\r
+   */\r
+  \r
+  /* INCLUDES ******************************************************************/\r
+  \r
+  #include <ntoskrnl.h>\r
+  #define NDEBUG\r
+  #include <internal/debug.h>\r
+  \r
+  extern EX_WORK_QUEUE ExWorkerQueue[MaximumWorkQueue];\r
+  extern LIST_ENTRY PspReaperListHead;\r
+  \r
+  ULONG KiMask32Array[MAXIMUM_PRIORITY] =\r
+  {\r
+      0x1,        0x2,       0x4,       0x8,       0x10,       0x20,\r
+      0x40,       0x80,      0x100,     0x200,     0x4000,     0x800,\r
+      0x1000,     0x2000,    0x4000,    0x8000,    0x10000,    0x20000,\r
+      0x40000,    0x80000,   0x100000,  0x200000,  0x400000,   0x800000,\r
+      0x1000000,  0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000,\r
+      0x40000000, 0x80000000\r
+  };\r
+  \r
+  /* FUNCTIONS *****************************************************************/\r
+  \r
+  UCHAR\r
+  NTAPI\r
+  KeFindNextRightSetAffinity(IN UCHAR Number,\r
+                             IN ULONG Set)\r
+  {\r
+      ULONG Bit, Result;\r
+      ASSERT(Set != 0);\r
+  \r
+      /* Calculate the mask */\r
+      Bit = (AFFINITY_MASK(Number) - 1) & Set;\r
+  \r
+      /* If it's 0, use the one we got */\r
+      if (!Bit) Bit = Set;\r
+  \r
+      /* Now find the right set and return it */\r
+      BitScanReverse(&Result, Bit);\r
+      return (UCHAR)Result;\r
+  }\r
+  \r
+  KPRIORITY\r
+  NTAPI\r
+  KeQueryBasePriorityThread(IN PKTHREAD Thread)\r
+  {\r
+      LONG BaseIncrement;\r
+      KIRQL OldIrql;\r
+      PKPROCESS Process;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Raise IRQL to synch level */\r
+      OldIrql = KeRaiseIrqlToSynchLevel();\r
+  \r
+      /* Lock the thread */\r
+      KiAcquireThreadLock(Thread);\r
+  \r
+      /* Get the Process */\r
+      Process = Thread->ApcStatePointer[0]->Process;\r
+  \r
+      /* Calculate the base increment */\r
+      BaseIncrement = Thread->BasePriority - Process->BasePriority;\r
+  \r
+      /* If saturation occured, return the saturation increment instead */\r
+      if (Thread->Saturation) BaseIncrement = (HIGH_PRIORITY + 1) / 2 *\r
+                                              Thread->Saturation;\r
+  \r
+      /* Release thread lock */\r
+      KiReleaseThreadLock(Thread);\r
+  \r
+      /* Lower IRQl and return Increment */\r
+      KeLowerIrql(OldIrql);\r
+      return BaseIncrement;\r
+  }\r
+  \r
+  VOID\r
+  NTAPI\r
+  KeReadyThread(IN PKTHREAD Thread)\r
+  {\r
+      KIRQL OldIrql;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Lock the Dispatcher Database */\r
+      OldIrql = KiAcquireDispatcherLock();\r
+  \r
+      /* Make the thread ready */\r
+      KiReadyThread(Thread);\r
+  \r
+      /* Unlock dispatcher database */\r
+      KiReleaseDispatcherLock(OldIrql);\r
+  }\r
+  \r
+  ULONG\r
+  NTAPI\r
+  KeAlertResumeThread(IN PKTHREAD Thread)\r
+  {\r
+      ULONG PreviousCount;\r
+      KLOCK_QUEUE_HANDLE ApcLock;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Lock the Dispatcher Database and the APC Queue */\r
+      KiAcquireApcLock(Thread, &ApcLock);\r
+      KiAcquireDispatcherLockAtDpcLevel();\r
+  \r
+      /* Return if Thread is already alerted. */\r
+      if (!Thread->Alerted[KernelMode])\r
+      {\r
+          /* If it's Blocked, unblock if it we should */\r
+          if ((Thread->State == Waiting) && (Thread->Alertable))\r
+          {\r
+              /* Abort the wait */\r
+              KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);\r
+          }\r
+          else\r
+          {\r
+              /* If not, simply Alert it */\r
+              Thread->Alerted[KernelMode] = TRUE;\r
+          }\r
+      }\r
+  \r
+      /* Save the old Suspend Count */\r
+      PreviousCount = Thread->SuspendCount;\r
+  \r
+      /* If the thread is suspended, decrease one of the suspend counts */\r
+      if (PreviousCount)\r
+      {\r
+          /* Decrease count. If we are now zero, unwait it completely */\r
+          if (--Thread->SuspendCount)\r
+          {\r
+              /* Signal and satisfy */\r
+              Thread->SuspendSemaphore.Header.SignalState++;\r
+              KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);\r
+          }\r
+      }\r
+  \r
+      /* Release Locks and return the Old State */\r
+      KiReleaseDispatcherLockFromDpcLevel();\r
+      KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+      KiExitDispatcher(ApcLock.OldIrql);\r
+      return PreviousCount;\r
+  }\r
+  \r
+  BOOLEAN\r
+  NTAPI\r
+  KeAlertThread(IN PKTHREAD Thread,\r
+                IN KPROCESSOR_MODE AlertMode)\r
+  {\r
+      BOOLEAN PreviousState;\r
+      KLOCK_QUEUE_HANDLE ApcLock;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Lock the Dispatcher Database and the APC Queue */\r
+      KiAcquireApcLock(Thread, &ApcLock);\r
+      KiAcquireDispatcherLockAtDpcLevel();\r
+  \r
+      /* Save the Previous State */\r
+      PreviousState = Thread->Alerted[AlertMode];\r
+  \r
+      /* Check if it's already alerted */\r
+      if (!PreviousState)\r
+      {\r
+          /* Check if the thread is alertable, and blocked in the given mode */\r
+          if ((Thread->State == Waiting) &&\r
+              ((AlertMode == KernelMode) || (Thread->WaitMode == AlertMode)) &&\r
+              (Thread->Alertable))\r
+          {\r
+              /* Abort the wait to alert the thread */\r
+              KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);\r
+          }\r
+          else\r
+          {\r
+              /* Otherwise, merely set the alerted state */\r
+              Thread->Alerted[AlertMode] = TRUE;\r
+          }\r
+      }\r
+  \r
+      /* Release the Dispatcher Lock */\r
+      KiReleaseDispatcherLockFromDpcLevel();\r
+      KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+      KiExitDispatcher(ApcLock.OldIrql);\r
+  \r
+      /* Return the old state */\r
+      return PreviousState;\r
+  }\r
+  \r
+  ULONG\r
+  NTAPI\r
+  KeForceResumeThread(IN PKTHREAD Thread)\r
+  {\r
+      KLOCK_QUEUE_HANDLE ApcLock;\r
+      ULONG PreviousCount;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Lock the APC Queue */\r
+      KiAcquireApcLock(Thread, &ApcLock);\r
+  \r
+      /* Save the old Suspend Count */\r
+      PreviousCount = Thread->SuspendCount + Thread->FreezeCount;\r
+  \r
+      /* If the thread is suspended, wake it up!!! */\r
+      if (PreviousCount)\r
+      {\r
+          /* Unwait it completely */\r
+          Thread->SuspendCount = 0;\r
+          Thread->FreezeCount = 0;\r
+  \r
+          /* Lock the dispatcher */\r
+          KiAcquireDispatcherLockAtDpcLevel();\r
+  \r
+          /* Signal and satisfy */\r
+          Thread->SuspendSemaphore.Header.SignalState++;\r
+          KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);\r
+  \r
+          /* Release the dispatcher */\r
+          KiReleaseDispatcherLockFromDpcLevel();\r
+      }\r
+  \r
+      /* Release Lock and return the Old State */\r
+      KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+      KiExitDispatcher(ApcLock.OldIrql);\r
+      return PreviousCount;\r
+  }\r
+  \r
+  /*\r
+   * Used by the debugging code to freeze all the process's threads\r
+   * while the debugger is examining their state.\r
+   */\r
+  VOID\r
+  NTAPI\r
+  KeFreezeAllThreads(IN PKPROCESS Process)\r
+  {\r
+      KLOCK_QUEUE_HANDLE LockHandle, ApcLock;\r
+      PKTHREAD Current, CurrentThread = KeGetCurrentThread();\r
+      PLIST_ENTRY ListHead, NextEntry;\r
+      LONG OldCount;\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Lock the process */\r
+      KiAcquireProcessLock(Process, &LockHandle);\r
+  \r
+      /* If someone is already trying to free us, try again */\r
+      while (CurrentThread->FreezeCount)\r
+      {\r
+          /* Release and re-acquire the process lock so the APC will go through */\r
+          KiReleaseProcessLock(&LockHandle);\r
+          KiAcquireProcessLock(Process, &LockHandle);\r
+      }\r
+  \r
+      /* Enter a critical region */\r
+      KeEnterCriticalRegion();\r
+  \r
+      /* Loop the Process's Threads */\r
+      ListHead = &Process->ThreadListHead;\r
+      NextEntry = ListHead->Flink;\r
+      while (NextEntry != ListHead)\r
+      {\r
+          /* Get the current thread */\r
+          Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);\r
+  \r
+          /* Lock it */\r
+          KiAcquireApcLockAtDpcLevel(Current, &ApcLock);\r
+  \r
+          /* Make sure it's not ours, and check if APCs are enabled */\r
+          if ((Current != CurrentThread) && (Current->ApcQueueable))\r
+          {\r
+              /* Sanity check */\r
+              OldCount = Current->SuspendCount;\r
+              ASSERT(OldCount != MAXIMUM_SUSPEND_COUNT);\r
+  \r
+              /* Increase the freeze count */\r
+              Current->FreezeCount++;\r
+  \r
+              /* Make sure it wasn't already suspended */\r
+              if (!(OldCount) && !(Current->SuspendCount))\r
+              {\r
+                  /* Did we already insert it? */\r
+                  if (!Current->SuspendApc.Inserted)\r
+                  {\r
+                      /* Insert the APC */\r
+                      Current->SuspendApc.Inserted = TRUE;\r
+                      KiInsertQueueApc(&Current->SuspendApc, IO_NO_INCREMENT);\r
+                  }\r
+                  else\r
+                  {\r
+                      /* Lock the dispatcher */\r
+                      KiAcquireDispatcherLockAtDpcLevel();\r
+  \r
+                      /* Unsignal the semaphore, the APC was already inserted */\r
+                      Current->SuspendSemaphore.Header.SignalState--;\r
+  \r
+                      /* Release the dispatcher */\r
+                      KiReleaseDispatcherLockFromDpcLevel();\r
+                  }\r
+              }\r
+          }\r
+  \r
+          /* Release the APC lock */\r
+          KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+      }\r
+  \r
+      /* Release the process lock and exit the dispatcher */\r
+      KiReleaseProcessLock(&LockHandle);\r
+      KiExitDispatcher(LockHandle.OldIrql);\r
+  }\r
+  \r
+  ULONG\r
+  NTAPI\r
+  KeResumeThread(IN PKTHREAD Thread)\r
+  {\r
+      KLOCK_QUEUE_HANDLE ApcLock;\r
+      ULONG PreviousCount;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Lock the APC Queue */\r
+      KiAcquireApcLock(Thread, &ApcLock);\r
+  \r
+      /* Save the Old Count */\r
+      PreviousCount = Thread->SuspendCount;\r
+  \r
+      /* Check if it existed */\r
+      if (PreviousCount)\r
+      {\r
+          /* Decrease the suspend count */\r
+          Thread->SuspendCount--;\r
+  \r
+          /* Check if the thrad is still suspended or not */\r
+          if ((!Thread->SuspendCount) && (!Thread->FreezeCount))\r
+          {\r
+              /* Acquire the dispatcher lock */\r
+              KiAcquireDispatcherLockAtDpcLevel();\r
+  \r
+              /* Signal the Suspend Semaphore */\r
+              Thread->SuspendSemaphore.Header.SignalState++;\r
+              KiWaitTest(&Thread->SuspendSemaphore.Header, IO_NO_INCREMENT);\r
+  \r
+              /* Release the dispatcher lock */\r
+              KiReleaseDispatcherLockFromDpcLevel();\r
+          }\r
+      }\r
+  \r
+      /* Release APC Queue lock and return the Old State */\r
+      KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+      KiExitDispatcher(ApcLock.OldIrql);\r
+      return PreviousCount;\r
+  }\r
+  \r
+  VOID\r
+  NTAPI\r
+  KeRundownThread(VOID)\r
+  {\r
+      KIRQL OldIrql;\r
+      PKTHREAD Thread = KeGetCurrentThread();\r
+      PLIST_ENTRY NextEntry, ListHead;\r
+      PKMUTANT Mutant;\r
+  \r
+      /* Optimized path if nothing is on the list at the moment */\r
+      if (IsListEmpty(&Thread->MutantListHead)) return;\r
+  \r
+      /* Lock the Dispatcher Database */\r
+      OldIrql = KiAcquireDispatcherLock();\r
+  \r
+      /* Get the List Pointers */\r
+      ListHead = &Thread->MutantListHead;\r
+      NextEntry = ListHead->Flink;\r
+      while (NextEntry != ListHead)\r
+      {\r
+          /* Get the Mutant */\r
+          Mutant = CONTAINING_RECORD(NextEntry, KMUTANT, MutantListEntry);\r
+  \r
+          /* Make sure it's not terminating with APCs off */\r
+          if (Mutant->ApcDisable)\r
+          {\r
+              /* Bugcheck the system */\r
+              KEBUGCHECKEX(0, //THREAD_TERMINATE_HELD_MUTEX,\r
+                           (ULONG_PTR)Thread,\r
+                           (ULONG_PTR)Mutant,\r
+                           0,\r
+                           0);\r
+          }\r
+  \r
+          /* Now we can remove it */\r
+          RemoveEntryList(&Mutant->MutantListEntry);\r
+  \r
+          /* Unconditionally abandon it */\r
+          Mutant->Header.SignalState = 1;\r
+          Mutant->Abandoned = TRUE;\r
+          Mutant->OwnerThread = NULL;\r
+  \r
+          /* Check if the Wait List isn't empty */\r
+          if (!IsListEmpty(&Mutant->Header.WaitListHead))\r
+          {\r
+              /* Wake the Mutant */\r
+              KiWaitTest(&Mutant->Header, MUTANT_INCREMENT);\r
+          }\r
+  \r
+          /* Move on */\r
+          NextEntry = NextEntry->Flink;\r
+      }\r
+  \r
+      /* Release the Lock */\r
+      KiReleaseDispatcherLock(OldIrql);\r
+  }\r
+  \r
+  VOID\r
+  NTAPI\r
+  KeStartThread(IN OUT PKTHREAD Thread)\r
+  {\r
+      KLOCK_QUEUE_HANDLE LockHandle;\r
+  #ifdef CONFIG_SMP\r
+      PKNODE Node;\r
+      PKPRCB NodePrcb;\r
+      ULONG Set, Mask;\r
+  #endif\r
+      UCHAR IdealProcessor = 0;\r
+      PKPROCESS Process = Thread->ApcState.Process;\r
+  \r
+      /* Setup static fields from parent */\r
+++#ifdef _M_IX86\r
+      Thread->Iopl = Process->Iopl;\r
+++#endif\r
+      Thread->Quantum = Process->QuantumReset;\r
+      Thread->QuantumReset = Process->QuantumReset;\r
+      Thread->SystemAffinityActive = FALSE;\r
+  \r
+      /* Lock the process */\r
+      KiAcquireProcessLock(Process, &LockHandle);\r
+  \r
+      /* Setup volatile data */\r
+      Thread->Priority = Process->BasePriority;\r
+      Thread->BasePriority = Process->BasePriority;\r
+      Thread->Affinity = Process->Affinity;\r
+      Thread->UserAffinity = Process->Affinity;\r
+  \r
+  #ifdef CONFIG_SMP\r
+      /* Get the KNODE and its PRCB */\r
+      Node = KeNodeBlock[Process->IdealNode];\r
+      NodePrcb = (PKPRCB)(KPCR_BASE + (Process->ThreadSeed * PAGE_SIZE));\r
+  \r
+      /* Calculate affinity mask */\r
+      Set = ~NodePrcb->MultiThreadProcessorSet;\r
+      Mask = (ULONG)(Node->ProcessorMask & Process->Affinity);\r
+      Set &= Mask;\r
+      if (Set) Mask = Set;\r
+  \r
+      /* Get the new thread seed */\r
+      IdealProcessor = KeFindNextRightSetAffinity(Process->ThreadSeed, Mask);\r
+      Process->ThreadSeed = IdealProcessor;\r
+  \r
+      /* Sanity check */\r
+      ASSERT((Thread->UserAffinity & AFFINITY_MASK(IdealProcessor)));\r
+  #endif\r
+  \r
+      /* Set the Ideal Processor */\r
+      Thread->IdealProcessor = IdealProcessor;\r
+      Thread->UserIdealProcessor = IdealProcessor;\r
+  \r
+      /* Lock the Dispatcher Database */\r
+      KiAcquireDispatcherLockAtDpcLevel();\r
+  \r
+      /* Insert the thread into the process list */\r
+      InsertTailList(&Process->ThreadListHead, &Thread->ThreadListEntry);\r
+  \r
+      /* Increase the stack count */\r
+      ASSERT(Process->StackCount != MAXULONG_PTR);\r
+      Process->StackCount++;\r
+  \r
+      /* Release locks and return */\r
+      KiReleaseDispatcherLockFromDpcLevel();\r
+      KiReleaseProcessLock(&LockHandle);\r
+  }\r
+  \r
+  VOID\r
+  NTAPI\r
+  KiSuspendRundown(IN PKAPC Apc)\r
+  {\r
+      /* Does nothing */\r
+      UNREFERENCED_PARAMETER(Apc);\r
+  }\r
+  \r
+  VOID\r
+  NTAPI\r
+  KiSuspendNop(IN PKAPC Apc,\r
+               IN PKNORMAL_ROUTINE *NormalRoutine,\r
+               IN PVOID *NormalContext,\r
+               IN PVOID *SystemArgument1,\r
+               IN PVOID *SystemArgument2)\r
+  {\r
+      /* Does nothing */\r
+      UNREFERENCED_PARAMETER(Apc);\r
+      UNREFERENCED_PARAMETER(NormalRoutine);\r
+      UNREFERENCED_PARAMETER(NormalContext);\r
+      UNREFERENCED_PARAMETER(SystemArgument1);\r
+      UNREFERENCED_PARAMETER(SystemArgument2);\r
+  }\r
+  \r
+  VOID\r
+  NTAPI\r
+  KiSuspendThread(IN PVOID NormalContext,\r
+                  IN PVOID SystemArgument1,\r
+                  IN PVOID SystemArgument2)\r
+  {\r
+      /* Non-alertable kernel-mode suspended wait */\r
+      KeWaitForSingleObject(&KeGetCurrentThread()->SuspendSemaphore,\r
+                            Suspended,\r
+                            KernelMode,\r
+                            FALSE,\r
+                            NULL);\r
+  }\r
+  \r
+  NTSTATUS\r
+  NTAPI\r
+  KeSuspendThread(PKTHREAD Thread)\r
+  {\r
+      KLOCK_QUEUE_HANDLE ApcLock;\r
+      ULONG PreviousCount;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Lock the APC Queue */\r
+      KiAcquireApcLock(Thread, &ApcLock);\r
+  \r
+      /* Save the Old Count */\r
+      PreviousCount = Thread->SuspendCount;\r
+  \r
+      /* Handle the maximum */\r
+      if (PreviousCount == MAXIMUM_SUSPEND_COUNT)\r
+      {\r
+          /* Raise an exception */\r
+          KiReleaseApcLock(&ApcLock);\r
+          RtlRaiseStatus(STATUS_SUSPEND_COUNT_EXCEEDED);\r
+      }\r
+  \r
+      /* Should we bother to queue at all? */\r
+      if (Thread->ApcQueueable)\r
+      {\r
+          /* Increment the suspend count */\r
+          Thread->SuspendCount++;\r
+  \r
+          /* Check if we should suspend it */\r
+          if (!(PreviousCount) && !(Thread->FreezeCount))\r
+          {\r
+              /* Is the APC already inserted? */\r
+              if (!Thread->SuspendApc.Inserted)\r
+              {\r
+                  /* Not inserted, insert it */\r
+                  Thread->SuspendApc.Inserted = TRUE;\r
+                  KiInsertQueueApc(&Thread->SuspendApc, IO_NO_INCREMENT);\r
+              }\r
+              else\r
+              {\r
+                  /* Lock the dispatcher */\r
+                  KiAcquireDispatcherLockAtDpcLevel();\r
+  \r
+                  /* Unsignal the semaphore, the APC was already inserted */\r
+                  Thread->SuspendSemaphore.Header.SignalState--;\r
+  \r
+                  /* Release the dispatcher */\r
+                  KiReleaseDispatcherLockFromDpcLevel();\r
+              }\r
+          }\r
+      }\r
+  \r
+      /* Release Lock and return the Old State */\r
+      KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+      KiExitDispatcher(ApcLock.OldIrql);\r
+      return PreviousCount;\r
+  }\r
+  \r
+  BOOLEAN\r
+  NTAPI\r
+  KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)\r
+  {\r
+      PKTHREAD Thread = KeGetCurrentThread();\r
+      BOOLEAN OldState;\r
+      KLOCK_QUEUE_HANDLE ApcLock;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Lock the Dispatcher Database and the APC Queue */\r
+      KiAcquireApcLock(Thread, &ApcLock);\r
+      KiAcquireDispatcherLockAtDpcLevel();\r
+  \r
+      /* Save the old State */\r
+      OldState = Thread->Alerted[AlertMode];\r
+  \r
+      /* Check the Thread is alerted */\r
+      if (OldState)\r
+      {\r
+          /* Disable alert for this mode */\r
+          Thread->Alerted[AlertMode] = FALSE;\r
+      }\r
+      else if ((AlertMode != KernelMode) &&\r
+               (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))\r
+      {\r
+          /* If the mode is User and the Queue isn't empty, set Pending */\r
+          Thread->ApcState.UserApcPending = TRUE;\r
+      }\r
+  \r
+      /* Release Locks and return the Old State */\r
+      KiReleaseDispatcherLockFromDpcLevel();\r
+      KiReleaseApcLockFromDpcLevel(&ApcLock);\r
+      KiExitDispatcher(ApcLock.OldIrql);\r
+      return OldState;\r
+  }\r
+  \r
+  NTSTATUS\r
+  NTAPI\r
+  KeInitThread(IN OUT PKTHREAD Thread,\r
+               IN PVOID KernelStack,\r
+               IN PKSYSTEM_ROUTINE SystemRoutine,\r
+               IN PKSTART_ROUTINE StartRoutine,\r
+               IN PVOID StartContext,\r
+               IN PCONTEXT Context,\r
+               IN PVOID Teb,\r
+               IN PKPROCESS Process)\r
+  {\r
+      BOOLEAN AllocatedStack = FALSE;\r
+      ULONG i;\r
+      PKWAIT_BLOCK TimerWaitBlock;\r
+      PKTIMER Timer;\r
+      NTSTATUS Status;\r
+  \r
+      /* Initalize the Dispatcher Header */\r
+      KeInitializeDispatcherHeader(&Thread->DispatcherHeader,\r
+                                   ThreadObject,\r
+                                   sizeof(KTHREAD) / sizeof(LONG),\r
+                                   FALSE);\r
+  \r
+      /* Initialize the Mutant List */\r
+      InitializeListHead(&Thread->MutantListHead);\r
+  \r
+      /* Initialize the wait blocks */\r
+      for (i = 0; i< (THREAD_WAIT_OBJECTS + 1); i++)\r
+      {\r
+          /* Put our pointer */\r
+          Thread->WaitBlock[i].Thread = Thread;\r
+      }\r
+  \r
+      /* Set swap settings */\r
+      Thread->EnableStackSwap = FALSE;//TRUE;\r
+      Thread->IdealProcessor = 1;\r
+      Thread->SwapBusy = FALSE;\r
+      Thread->AdjustReason = 0;\r
+  \r
+      /* Initialize the lock */\r
+      KeInitializeSpinLock(&Thread->ThreadLock);\r
+  \r
+      /* Setup the Service Descriptor Table for Native Calls */\r
+      Thread->ServiceTable = KeServiceDescriptorTable;\r
+  \r
+      /* Setup APC Fields */\r
+      InitializeListHead(&Thread->ApcState.ApcListHead[0]);\r
+      InitializeListHead(&Thread->ApcState.ApcListHead[1]);\r
+      Thread->ApcState.Process = Process;\r
+      Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;\r
+      Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;\r
+      Thread->ApcStateIndex = OriginalApcEnvironment;\r
+      Thread->ApcQueueable = TRUE;\r
+      KeInitializeSpinLock(&Thread->ApcQueueLock);\r
+  \r
+      /* Initialize the Suspend APC */\r
+      KeInitializeApc(&Thread->SuspendApc,\r
+                      Thread,\r
+                      OriginalApcEnvironment,\r
+                      KiSuspendNop,\r
+                      KiSuspendRundown,\r
+                      KiSuspendThread,\r
+                      KernelMode,\r
+                      NULL);\r
+  \r
+      /* Initialize the Suspend Semaphore */\r
+      KeInitializeSemaphore(&Thread->SuspendSemaphore, 0, 2);\r
+  \r
+      /* Setup the timer */\r
+      Timer = &Thread->Timer;\r
+      KeInitializeTimer(Timer);\r
+      TimerWaitBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];\r
+      TimerWaitBlock->Object = Timer;\r
+      TimerWaitBlock->WaitKey = STATUS_TIMEOUT;\r
+      TimerWaitBlock->WaitType = WaitAny;\r
+      TimerWaitBlock->NextWaitBlock = NULL;\r
+  \r
+      /* Link the two wait lists together */\r
+      TimerWaitBlock->WaitListEntry.Flink = &Timer->Header.WaitListHead;\r
+      TimerWaitBlock->WaitListEntry.Blink = &Timer->Header.WaitListHead;\r
+  \r
+      /* Set the TEB */\r
+      Thread->Teb = Teb;\r
+  \r
+      /* Check if we have a kernel stack */\r
+      if (!KernelStack)\r
+      {\r
+          /* We don't, allocate one */\r
+          KernelStack = (PVOID)((ULONG_PTR)MmCreateKernelStack(FALSE) +\r
+                                KERNEL_STACK_SIZE);\r
+          if (!KernelStack) return STATUS_INSUFFICIENT_RESOURCES;\r
+  \r
+          /* Remember for later */\r
+          AllocatedStack = TRUE;\r
+      }\r
+  \r
+      /* Set the Thread Stacks */\r
+      Thread->InitialStack = (PCHAR)KernelStack;\r
+      Thread->StackBase = (PCHAR)KernelStack;\r
+      Thread->StackLimit = (ULONG_PTR)KernelStack - KERNEL_STACK_SIZE;\r
+      Thread->KernelStackResident = TRUE;\r
+  \r
+      /* ROS Mm HACK */\r
+      MmUpdatePageDir((PEPROCESS)Process,\r
+                      (PVOID)Thread->StackLimit,\r
+                      KERNEL_STACK_SIZE);\r
+      MmUpdatePageDir((PEPROCESS)Process, (PVOID)Thread, sizeof(ETHREAD));\r
+  \r
+      /* Enter SEH to avoid crashes due to user mode */\r
+      Status = STATUS_SUCCESS;\r
+      _SEH_TRY\r
+      {\r
+          /* Initalize the Thread Context */\r
+++#ifdef _M_IX86\r
+          Ke386InitThreadWithContext(Thread,\r
+                                     SystemRoutine,\r
+                                     StartRoutine,\r
+                                     StartContext,\r
+                                     Context);\r
+++#endif\r
+      }\r
+      _SEH_HANDLE\r
+      {\r
+          /* Set failure status */\r
+          Status = STATUS_UNSUCCESSFUL;\r
+  \r
+          /* Check if a stack was allocated */\r
+          if (AllocatedStack)\r
+          {\r
+              /* Delete the stack */\r
+              MmDeleteKernelStack(Thread->StackBase, FALSE);\r
+              Thread->InitialStack = NULL;\r
+          }\r
+      }\r
+      _SEH_END;\r
+  \r
+      /* Set the Thread to initalized */\r
+      Thread->State = Initialized;\r
+      return Status;\r
+  }\r
+  \r
+  VOID\r
+  NTAPI\r
+  KeInitializeThread(IN PKPROCESS Process,\r
+                     IN OUT PKTHREAD Thread,\r
+                     IN PKSYSTEM_ROUTINE SystemRoutine,\r
+                     IN PKSTART_ROUTINE StartRoutine,\r
+                     IN PVOID StartContext,\r
+                     IN PCONTEXT Context,\r
+                     IN PVOID Teb,\r
+                     IN PVOID KernelStack)\r
+  {\r
+      /* Initailize and start the thread on success */\r
+      if (NT_SUCCESS(KeInitThread(Thread,\r
+                                  KernelStack,\r
+                                  SystemRoutine,\r
+                                  StartRoutine,\r
+                                  StartContext,\r
+                                  Context,\r
+                                  Teb,\r
+                                  Process)))\r
+      {\r
+          /* Start it */\r
+          KeStartThread(Thread);\r
+      }\r
+  }\r
+  \r
+  VOID\r
+  NTAPI\r
+  KeUninitThread(IN PKTHREAD Thread)\r
+  {\r
+      /* Delete the stack */\r
+      MmDeleteKernelStack(Thread->StackBase, FALSE);\r
+      Thread->InitialStack = NULL;\r
+  }\r
+  \r
+  /* PUBLIC FUNCTIONS **********************************************************/\r
+  \r
+  /*\r
+   * @unimplemented\r
+   */\r
+  VOID\r
+  NTAPI\r
+  KeCapturePersistentThreadState(IN PVOID CurrentThread,\r
+                                 IN ULONG Setting1,\r
+                                 IN ULONG Setting2,\r
+                                 IN ULONG Setting3,\r
+                                 IN ULONG Setting4,\r
+                                 IN ULONG Setting5,\r
+                                 IN PVOID ThreadState)\r
+  {\r
+      UNIMPLEMENTED;\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  #undef KeGetCurrentThread\r
+  PKTHREAD\r
+  NTAPI\r
+  KeGetCurrentThread(VOID)\r
+  {\r
+++#ifdef _M_IX86\r
+      /* Return the current thread on this PCR */\r
+      return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;\r
+++#elif defined(_M_PPC)\r
+++    return KeGetCurrentKPCR()->Prcb->CurrentThread;\r
+++#endif\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  KPROCESSOR_MODE\r
+  NTAPI\r
+  KeGetPreviousMode(VOID)\r
+  {\r
+      /* Return the previous mode of this thread */\r
+      return KeGetCurrentThread()->PreviousMode;\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  ULONG\r
+  NTAPI\r
+  KeQueryRuntimeThread(IN PKTHREAD Thread,\r
+                       OUT PULONG UserTime)\r
+  {\r
+      ASSERT_THREAD(Thread);\r
+  \r
+      /* Return the User Time */\r
+      *UserTime = Thread->UserTime;\r
+  \r
+      /* Return the Kernel Time */\r
+      return Thread->KernelTime;\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  BOOLEAN\r
+  NTAPI\r
+  KeSetKernelStackSwapEnable(IN BOOLEAN Enable)\r
+  {\r
+      BOOLEAN PreviousState;\r
+      PKTHREAD Thread = KeGetCurrentThread();\r
+  \r
+      /* Save Old State */\r
+      PreviousState = Thread->EnableStackSwap;\r
+  \r
+      /* Set New State */\r
+      Thread->EnableStackSwap = Enable;\r
+  \r
+      /* Return Old State */\r
+      return PreviousState;\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  KPRIORITY\r
+  NTAPI\r
+  KeQueryPriorityThread(IN PKTHREAD Thread)\r
+  {\r
+      ASSERT_THREAD(Thread);\r
+  \r
+      /* Return the current priority */\r
+      return Thread->Priority;\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  VOID\r
+  NTAPI\r
+  KeRevertToUserAffinityThread(VOID)\r
+  {\r
+      KIRQL OldIrql;\r
+      PKPRCB Prcb;\r
+      PKTHREAD NextThread, CurrentThread = KeGetCurrentThread();\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+      ASSERT(CurrentThread->SystemAffinityActive != FALSE);\r
+  \r
+      /* Lock the Dispatcher Database */\r
+      OldIrql = KiAcquireDispatcherLock();\r
+  \r
+      /* Set the user affinity and processor and disable system affinity */\r
+      CurrentThread->Affinity = CurrentThread->UserAffinity;\r
+      CurrentThread->IdealProcessor = CurrentThread->UserIdealProcessor;\r
+      CurrentThread->SystemAffinityActive = FALSE;\r
+  \r
+      /* Get the current PRCB and check if it doesn't match this affinity */\r
+      Prcb = KeGetCurrentPrcb();\r
+      if (!(Prcb->SetMember & CurrentThread->Affinity))\r
+      {\r
+          /* Lock the PRCB */\r
+          KiAcquirePrcbLock(Prcb);\r
+  \r
+  #ifdef NEW_SCHEDULER\r
+          /* Check if there's no next thread scheduled */\r
+          if (!Prcb->NextThread)\r
+          {\r
+              /* Select a new thread and set it on standby */\r
+              NextThread = KiSelectNextThread(Prcb);\r
+              NextThread->State = Standby;\r
+              Prcb->NextThread = NextThread;\r
+          }\r
+  #else\r
+          /* We need to dispatch a new thread */\r
+          NextThread = NULL;\r
+          CurrentThread->WaitIrql = OldIrql;\r
+          KiDispatchThreadNoLock(Ready);\r
+          KeLowerIrql(OldIrql);\r
+          return;\r
+  #endif\r
+  \r
+          /* Release the PRCB lock */\r
+          KiReleasePrcbLock(Prcb);\r
+      }\r
+  \r
+      /* Unlock dispatcher database */\r
+      KiReleaseDispatcherLock(OldIrql);\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  UCHAR\r
+  NTAPI\r
+  KeSetIdealProcessorThread(IN PKTHREAD Thread,\r
+                            IN UCHAR Processor)\r
+  {\r
+      CCHAR OldIdealProcessor;\r
+      KIRQL OldIrql;\r
+      ASSERT(Processor <= MAXIMUM_PROCESSORS);\r
+  \r
+      /* Lock the Dispatcher Database */\r
+      OldIrql = KiAcquireDispatcherLock();\r
+  \r
+      /* Save Old Ideal Processor */\r
+      OldIdealProcessor = Thread->UserIdealProcessor;\r
+  \r
+      /* Make sure a valid CPU was given */\r
+      if (Processor < MAXIMUM_PROCESSORS)\r
+      {\r
+          /* Check if the user ideal CPU is in the affinity */\r
+          if (Thread->UserIdealProcessor & AFFINITY_MASK(Processor))\r
+          {\r
+              /* Set the ideal processor */\r
+              Thread->IdealProcessor = Processor;\r
+  \r
+              /* Check if system affinity is used */\r
+              if (!Thread->SystemAffinityActive)\r
+              {\r
+                  /* It's not, so update the user CPU too */\r
+                  Thread->UserIdealProcessor = Processor;\r
+              }\r
+          }\r
+      }\r
+  \r
+      /* Release dispatcher lock and return the old ideal CPU */\r
+      KiReleaseDispatcherLock(OldIrql);\r
+      return OldIdealProcessor;\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  VOID\r
+  NTAPI\r
+  KeSetSystemAffinityThread(IN KAFFINITY Affinity)\r
+  {\r
+      KIRQL OldIrql;\r
+      PKPRCB Prcb;\r
+      PKTHREAD NextThread, CurrentThread = KeGetCurrentThread();\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+      ASSERT((Affinity & KeActiveProcessors) != 0);\r
+  \r
+      /* Lock the Dispatcher Database */\r
+      OldIrql = KiAcquireDispatcherLock();\r
+  \r
+      /* Restore the affinity and enable system affinity */\r
+      CurrentThread->Affinity = Affinity;\r
+      CurrentThread->SystemAffinityActive = TRUE;\r
+  \r
+      /* Check if the ideal processor is part of the affinity */\r
+  #ifdef CONFIG_SMP\r
+      if (!(Affinity & AFFINITY_MASK(CurrentThread->IdealProcessor)))\r
+      {\r
+          ULONG AffinitySet, NodeMask;\r
+  \r
+          /* It's not! Get the PRCB */\r
+          Prcb = KiProcessorBlock[CurrentThread->IdealProcessor];\r
+  \r
+          /* Calculate the affinity set */\r
+          AffinitySet = KeActiveProcessors & Affinity;\r
+          NodeMask = Prcb->ParentNode->ProcessorMask & AffinitySet;\r
+          if (NodeMask)\r
+          {\r
+              /* Use the Node set instead */\r
+              AffinitySet = NodeMask;\r
+          }\r
+  \r
+          /* Calculate the ideal CPU from the affinity set */\r
+          BitScanReverse(&NodeMask, AffinitySet);\r
+          CurrentThread->IdealProcessor = (UCHAR)NodeMask;\r
+      }\r
+  #endif\r
+  \r
+      /* Get the current PRCB and check if it doesn't match this affinity */\r
+      Prcb = KeGetCurrentPrcb();\r
+      if (!(Prcb->SetMember & CurrentThread->Affinity))\r
+      {\r
+          /* Lock the PRCB */\r
+          KiAcquirePrcbLock(Prcb);\r
+  \r
+  #ifdef NEW_SCHEDULER\r
+          /* Check if there's no next thread scheduled */\r
+          if (!Prcb->NextThread)\r
+          {\r
+              /* Select a new thread and set it on standby */\r
+              NextThread = KiSelectNextThread(Prcb);\r
+              NextThread->State = Standby;\r
+              Prcb->NextThread = NextThread;\r
+          }\r
+  #else\r
+          /* We need to dispatch a new thread */\r
+          NextThread = NULL;\r
+          CurrentThread->WaitIrql = OldIrql;\r
+          KiDispatchThreadNoLock(Ready);\r
+          KeLowerIrql(OldIrql);\r
+          return;\r
+  #endif\r
+  \r
+          /* Release the PRCB lock */\r
+          KiReleasePrcbLock(Prcb);\r
+      }\r
+  \r
+      /* Unlock dispatcher database */\r
+      KiReleaseDispatcherLock(OldIrql);\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  LONG\r
+  NTAPI\r
+  KeSetBasePriorityThread(IN PKTHREAD Thread,\r
+                          IN LONG Increment)\r
+  {\r
+      KIRQL OldIrql;\r
+      KPRIORITY OldBasePriority, Priority, BasePriority;\r
+      LONG OldIncrement;\r
+      PKPROCESS Process;\r
+      BOOLEAN Released;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Get the process */\r
+      Process = Thread->ApcState.Process;\r
+  \r
+      /* Lock the Dispatcher Database */\r
+      OldIrql = KiAcquireDispatcherLock();\r
+  \r
+      /* Lock the thread */\r
+      KiAcquireThreadLock(Thread);\r
+  \r
+      /* Save the old base priority and increment */\r
+      OldBasePriority = Thread->BasePriority;\r
+      OldIncrement = OldBasePriority - Process->BasePriority;\r
+  \r
+      /* If priority saturation happened, use the saturated increment */\r
+      if (Thread->Saturation) OldIncrement = (HIGH_PRIORITY + 1) / 2 *\r
+                                              Thread->Saturation;\r
+  \r
+      /* Now check if saturation is being used for the new value */\r
+      if (abs(Increment) >= ((HIGH_PRIORITY + 1) / 2))\r
+      {\r
+          /* Check if we need positive or negative saturation */\r
+          Thread->Saturation = (Increment > 0) ? 1 : -1;\r
+      }\r
+  \r
+      /* Normalize the Base Priority */\r
+      BasePriority = Process->BasePriority + Increment;\r
+      if (Process->BasePriority >= LOW_REALTIME_PRIORITY)\r
+      {\r
+          /* Check if it's too low */\r
+          if (BasePriority < LOW_REALTIME_PRIORITY)\r
+          {\r
+              /* Set it to the lowest real time level */\r
+              BasePriority = LOW_REALTIME_PRIORITY;\r
+          }\r
+  \r
+          /* Check if it's too high */\r
+          if (BasePriority > HIGH_PRIORITY) BasePriority = HIGH_PRIORITY;\r
+  \r
+          /* We are at real time, so use the raw base priority */\r
+          Priority = BasePriority;\r
+      }\r
+      else\r
+      {\r
+          /* Check if it's entering the real time range */\r
+          if (BasePriority >= LOW_REALTIME_PRIORITY)\r
+          {\r
+              /* Set it to the highest dynamic level */\r
+              BasePriority = LOW_REALTIME_PRIORITY - 1;\r
+          }\r
+  \r
+          /* Check if it's too low and normalize it */\r
+          if (BasePriority <= LOW_PRIORITY) BasePriority = 1;\r
+  \r
+          /* Check if Saturation is used */\r
+          if (Thread->Saturation)\r
+          {\r
+              /* Use the raw base priority */\r
+              Priority = BasePriority;\r
+          }\r
+          else\r
+          {\r
+              /* Otherwise, calculate the new priority */\r
+              Priority = KiComputeNewPriority(Thread);\r
+  \r
+              /* Check if it entered the real-time range */\r
+              if (Priority >= LOW_REALTIME_PRIORITY)\r
+              {\r
+                  /* Normalize it down to the highest dynamic priority */\r
+                  Priority = LOW_REALTIME_PRIORITY - 1;\r
+              }\r
+          }\r
+      }\r
+  \r
+      /* Finally set the new base priority */\r
+      Thread->BasePriority = (SCHAR)BasePriority;\r
+  \r
+      /* Reset the decrements */\r
+      Thread->PriorityDecrement = 0;\r
+  \r
+      /* Check if we're changing priority after all */\r
+      if (Priority != Thread->Priority)\r
+      {\r
+          /* Reset the quantum and do the actual priority modification */\r
+          Thread->Quantum = Thread->QuantumReset;\r
+          KiSetPriorityThread(Thread, Priority, &Released);\r
+      }\r
+  \r
+      /* Release thread lock */\r
+      KiReleaseThreadLock(Thread);\r
+  \r
+      /* Check if lock was released */\r
+      if (!Released)\r
+      {\r
+          /* Release the dispatcher database */\r
+          KiReleaseDispatcherLock(OldIrql);\r
+      }\r
+      else\r
+      {\r
+          /* Lower IRQL only */\r
+          KeLowerIrql(OldIrql);\r
+      }\r
+  \r
+      /* Return old increment */\r
+      return OldIncrement;\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  KAFFINITY\r
+  NTAPI\r
+  KeSetAffinityThread(IN PKTHREAD Thread,\r
+                      IN KAFFINITY Affinity)\r
+  {\r
+      KIRQL OldIrql;\r
+      KAFFINITY OldAffinity;\r
+      BOOLEAN Released;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Lock the dispatcher database */\r
+      OldIrql = KiAcquireDispatcherLock();\r
+  \r
+      /* Call the internal function */\r
+      OldAffinity = KiSetAffinityThread(Thread, Affinity, &Released);\r
+  \r
+      /* Check if lock was released */\r
+      if (!Released)\r
+      {\r
+          /* Release the dispatcher database */\r
+          KiReleaseDispatcherLock(OldIrql);\r
+      }\r
+      else\r
+      {\r
+          /* Lower IRQL only */\r
+          KeLowerIrql(OldIrql);\r
+      }\r
+  \r
+      /* Return old affinity */\r
+      return OldAffinity;\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  KPRIORITY\r
+  NTAPI\r
+  KeSetPriorityThread(IN PKTHREAD Thread,\r
+                      IN KPRIORITY Priority)\r
+  {\r
+      KIRQL OldIrql;\r
+      KPRIORITY OldPriority;\r
+      BOOLEAN Released;\r
+      ASSERT_THREAD(Thread);\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+      ASSERT((Priority <= HIGH_PRIORITY) && (Priority >= LOW_PRIORITY));\r
+  \r
+      /* Lock the Dispatcher Database */\r
+      OldIrql = KiAcquireDispatcherLock();\r
+  \r
+      /* Lock the thread */\r
+      KiAcquireThreadLock(Thread);\r
+  \r
+      /* Save the old Priority */\r
+      OldPriority = Thread->Priority;\r
+  \r
+      /* Make sure that an actual change is being done */\r
+      if (OldPriority != Priority)\r
+      {\r
+          /* Reset the Quantum and Decrements */\r
+          Thread->Quantum = Thread->QuantumReset;\r
+          Thread->PriorityDecrement = 0;\r
+  \r
+          /* Set the new Priority */\r
+          KiSetPriorityThread(Thread, Priority, &Released);\r
+      }\r
+  \r
+      /* Release thread lock */\r
+      KiReleaseThreadLock(Thread);\r
+  \r
+      /* Check if lock was released */\r
+      if (!Released)\r
+      {\r
+          /* Release the dispatcher database */\r
+          KiReleaseDispatcherLock(OldIrql);\r
+      }\r
+      else\r
+      {\r
+          /* Lower IRQL only */\r
+          KeLowerIrql(OldIrql);\r
+      }\r
+  \r
+      /* Return Old Priority */\r
+      return OldPriority;\r
+  }\r
+  \r
+  /*\r
+   * @implemented\r
+   */\r
+  VOID\r
+  NTAPI\r
+  KeTerminateThread(IN KPRIORITY Increment)\r
+  {\r
+      PLIST_ENTRY *ListHead;\r
+      PETHREAD Entry, SavedEntry;\r
+      PETHREAD *ThreadAddr;\r
+      KLOCK_QUEUE_HANDLE LockHandle;\r
+      PKTHREAD Thread = KeGetCurrentThread();\r
+      PKPROCESS Process = Thread->ApcState.Process;\r
+      ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);\r
+  \r
+      /* Lock the process */\r
+      KiAcquireProcessLock(Process, &LockHandle);\r
+  \r
+      /* Make sure we won't get Swapped */\r
+      KiSetThreadSwapBusy(Thread);\r
+  \r
+      /* Save the Kernel and User Times */\r
+      Process->KernelTime += Thread->KernelTime;\r
+      Process->UserTime += Thread->UserTime;\r
+  \r
+      /* Get the current entry and our Port */\r
+      Entry = (PETHREAD)PspReaperListHead.Flink;\r
+      ThreadAddr = &((PETHREAD)Thread)->ReaperLink;\r
+  \r
+      /* Add it to the reaper's list */\r
+      do\r
+      {\r
+          /* Get the list head */\r
+          ListHead = &PspReaperListHead.Flink;\r
+  \r
+          /* Link ourselves */\r
+          *ThreadAddr = Entry;\r
+          SavedEntry = Entry;\r
+  \r
+          /* Now try to do the exchange */\r
+          Entry = InterlockedCompareExchangePointer(ListHead, ThreadAddr, Entry);\r
+  \r
+          /* Break out if the change was succesful */\r
+      } while (Entry != SavedEntry);\r
+  \r
+      /* Acquire the dispatcher lock */\r
+      KiAcquireDispatcherLockAtDpcLevel();\r
+  \r
+      /* Check if the reaper wasn't active */\r
+      if (!Entry)\r
+      {\r
+          /* Activate it as a work item, directly through its Queue */\r
+          KiInsertQueue(&ExWorkerQueue[HyperCriticalWorkQueue].WorkerQueue,\r
+                        &PspReaperWorkItem.List,\r
+                        FALSE);\r
+      }\r
+  \r
+      /* Check the thread has an associated queue */\r
+      if (Thread->Queue)\r
+      {\r
+          /* Remove it from the list, and handle the queue */\r
+          RemoveEntryList(&Thread->QueueListEntry);\r
+          KiActivateWaiterQueue(Thread->Queue);\r
+      }\r
+  \r
+      /* Signal the thread */\r
+      Thread->DispatcherHeader.SignalState = TRUE;\r
+      if (!IsListEmpty(&Thread->DispatcherHeader.WaitListHead))\r
+      {\r
+          /* Unwait the threads */\r
+          KxUnwaitThread(&Thread->DispatcherHeader, Increment);\r
+      }\r
+  \r
+      /* Remove the thread from the list */\r
+      RemoveEntryList(&Thread->ThreadListEntry);\r
+  \r
+      /* Release the process lock */\r
+      KiReleaseProcessLockFromDpcLevel(&LockHandle);\r
+  \r
+      /* Set us as terminated, decrease the Process's stack count */\r
+      Thread->State = Terminated;\r
+  \r
+      /* Decrease stack count */\r
+      ASSERT(Process->StackCount != 0);\r
+      ASSERT(Process->State == ProcessInMemory);\r
+      Process->StackCount--;\r
+      if (!Process->StackCount)\r
+      {\r
+          /* FIXME: Swap stacks */\r
+      }\r
+  \r
+      /* Rundown arch-specific parts */\r
+      KiRundownThread(Thread);\r
+  \r
+      /* Swap to a new thread */\r
+      KiReleaseDispatcherLockFromDpcLevel();\r
+      KiSwapThread(Thread, KeGetCurrentPrcb());\r
+  }\r
@@@@ -112,7 -107,7 -107,7 +107,7 @@@@ LdrInit1 ( VOID 
   VOID
   INIT_FUNCTION
   NTAPI
---LdrInitModuleManagement ( VOID )
+++LdrInitModuleManagement ( PVOID KernelBase )
   {
       PIMAGE_NT_HEADERS NtHeader;
   
   
       /* Initialize ModuleObject for NTOSKRNL */
       RtlZeroMemory(&NtoskrnlModuleObject, sizeof(LDR_DATA_TABLE_ENTRY));
---    NtoskrnlModuleObject.DllBase = (PVOID) KERNEL_BASE;
+++    NtoskrnlModuleObject.DllBase = (PVOID) KernelBase;
       RtlInitUnicodeString(&NtoskrnlModuleObject.FullDllName, KERNEL_MODULE_NAME);
       LdrpBuildModuleBaseName(&NtoskrnlModuleObject.BaseDllName, &NtoskrnlModuleObject.FullDllName);
   
---    NtHeader = RtlImageNtHeader((PVOID)KERNEL_BASE);
+++    NtHeader = RtlImageNtHeader((PVOID)KernelBase);
       NtoskrnlModuleObject.EntryPoint = (PVOID) ((ULONG_PTR) NtoskrnlModuleObject.DllBase + NtHeader->OptionalHeader.AddressOfEntryPoint);
       DPRINT("ModuleObject:%08x  entrypoint at %x\n", &NtoskrnlModuleObject, NtoskrnlModuleObject.EntryPoint);
       NtoskrnlModuleObject.SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
Simple merge
Simple merge
   <module name="ntoskrnl" type="kernel" installbase="system32" installname="ntoskrnl.exe">
-       <bootstrap base="reactos" />
-       <importlibrary definition="ntoskrnl.def" />
-       <define name="_SEH_NO_NATIVE_NLG" />
-       <define name="_DISABLE_TIDENTS" />
-       <define name="__NTOSKRNL__" />
-       <define name="_NTOSKRNL_" />
-       <define name="__NO_CTYPE_INLINES" />
-       <define name="__USE_W32API" />
-       <include base="kjs">include</include>
-       <include base="cmlib">.</include>
-       <include base="ntoskrnl">include</include>
-       <include base="ReactOS">include/reactos/drivers</include>
-       <library>csq</library>
-       <library>hal</library>
-       <library>kjs</library>
-       <library>pseh</library>
-       <library>cmlib</library>
-       <library>rtl</library>
-       <library>rossym</library>
-       <library>string</library>
-       <library>wdmguid</library>
-       <directory name="include">
-               <pch>ntoskrnl.h</pch>
-       </directory>
-       <directory name="ke">
-               <if property="ARCH" value="i386">
-                       <directory name="i386">
-                               <file first="true">boot.S</file>
-                               <file>abios.c</file>
-                               <file>cpu.c</file>
-                               <file>ctxswitch.S</file>
+      <bootstrap base="reactos" />
+      <importlibrary definition="ntoskrnl.def" />
+      <define name="_SEH_NO_NATIVE_NLG" />
+      <define name="_DISABLE_TIDENTS" />
+      <define name="__NTOSKRNL__" />
+      <define name="_NTOSKRNL_" />
+      <define name="_NTSYSTEM_" />
+      <define name="__NO_CTYPE_INLINES" />
+      <define name="__USE_W32API" />
+      <define name="WIN9X_COMPAT_SPINLOCK" />
+      <include base="kjs">include</include>
+      <include base="cmlib">.</include>
+      <include base="ntoskrnl">include</include>
+      <include base="ReactOS">include/reactos/drivers</include>
+      <library>csq</library>
+      <library>hal</library>
+      <library>kjs</library>
+      <library>pseh</library>
+      <library>cmlib</library>
+      <library>rtl</library>
+      <library>rossym</library>
+      <library>string</library>
+      <library>wdmguid</library>
+      <directory name="include">
+          <pch>ntoskrnl.h</pch>
+      </directory>
+      <directory name="ke">
+          <if property="ARCH" value="i386">
+              <directory name="i386">
+                  <file first="true">boot.S</file>
+                  <file>abios.c</file>
+                  <file>cpu.c</file>
+                  <file>ctxswitch.S</file>
                   <file>clock.S</file>
-                               <file>exp.c</file>
-                  <!-- <file>irq.c</file> -->
-                               <file>kiinit.c</file>
-                               <file>ldt.c</file>
-                               <file>thread.c</file>
-                               <file>trap.s</file>
-                               <file>usercall_asm.S</file>
-                               <file>v86vdm.c</file>
-                               <file>v86m_sup.S</file>
-                       </directory>
-               </if>
+                  <file>exp.c</file>
 --                <!-- <file>irq.c</file> -->
+                  <file>kiinit.c</file>
+                  <file>ldt.c</file>
+                  <file>mtrr.c</file>
+                  <file>patpge.c</file>
+                  <file>thread.c</file>
+                  <file>trap.s</file>
+                  <file>usercall_asm.S</file>
+                  <file>usercall.c</file>
+                  <file>v86vdm.c</file>
+                  <file>v86m_sup.S</file>
+              </directory>
+          </if>
 ++             <if property="ARCH" value="powerpc">
 ++                     <directory name="powerpc">
 ++                             <file first="true">main_asm.S</file>
 ++                             <file>kiinit.c</file>
 ++                             <file>ppc_irq.c</file>
 ++                     </directory>
 ++             </if>
-                       <file>apc.c</file>
-                       <file>bug.c</file>
-                       <file>clock.c</file>
-                       <file>device.c</file>
-                       <file>dpc.c</file>
-                       <file>event.c</file>
-                       <file>exception.c</file>
-                       <file>freeldr.c</file>
-                       <file>gate.c</file>
-                       <file>gmutex.c</file>
-                       <file>ipi.c</file>
-                       <file>kqueue.c</file>
-                       <file>krnlinit.c</file>
-                       <file>kthread.c</file>
-                       <file>mutex.c</file>
-                       <file>process.c</file>
-                       <file>profile.c</file>
-                       <file>queue.c</file>
-                       <file>sem.c</file>
-                       <file>spinlock.c</file>
-                       <file>timer.c</file>
-                       <file>usercall.c</file>
-                       <file>wait.c</file>
-       </directory>
+              <file>apc.c</file>
+              <file>bug.c</file>
+              <file>clock.c</file>
+              <file>config.c</file>
+              <file>devqueue.c</file>
+              <file>dpc.c</file>
+              <file>event.c</file>
+              <file>except.c</file>
+              <file>freeldr.c</file>
+              <file>gate.c</file>
+              <file>gmutex.c</file>
+              <file>ipi.c</file>
+              <file>krnlinit.c</file>
+              <file>mutex.c</file>
+              <file>process.c</file>
+              <file>profile.c</file>
+              <file>queue.c</file>
+              <file>sem.c</file>
+              <file>spinlock.c</file>
+              <file>thrdschd.c</file>
+              <file>thrdobj.c</file>
+              <file>timer.c</file>
+              <file>wait.c</file>
+      </directory>
 --    <directory name="deprecated">
 --        <file>irqhand.S</file>
 --        <file>irq.c</file>
 --    </directory>
 ++        <if property="ARCH" value="i386">
 ++            <directory name="deprecated">
 ++                <file>irqhand.S</file>
 ++                <file>irq.c</file>
 ++            </directory>
 ++        </if>
-       <directory name="cc">
-                       <file>cacheman.c</file>
-                       <file>copy.c</file>
-                       <file>fs.c</file>
-                       <file>mdl.c</file>
-                       <file>pin.c</file>
-                       <file>view.c</file>
-       </directory>
-       <directory name="cm">
-                       <file>import.c</file>
-                       <file>ntfunc.c</file>
-                       <file>regfile.c</file>
-                       <file>registry.c</file>
-                       <file>regobj.c</file>
-       </directory>
-       <directory name="kdbg">
-               <if property="ARCH" value="i386">
-                       <directory name="i386">
-                               <if property="KDBG" value="1">
-                                       <group>
-                                               <file>i386-dis.c</file>
-                                               <file>kdb_help.S</file>
-                                               <file>longjmp.S</file>
-                                               <file>setjmp.S</file>
-                                       </group>
-                               </if>
-                       </directory>
-               </if>
-               <if property="KDBG" value="1">
-                       <file>kdb.c</file>
-                       <file>kdb_cli.c</file>
-                       <file>kdb_expr.c</file>
-                       <file>kdb_keyboard.c</file>
-                       <file>kdb_serial.c</file>
-                       <file>kdb_string.c</file>
-               </if>
-               <if property="DBG_OR_KDBG" value="true">
-                       <file>kdb_symbols.c</file>
-               </if>
-       </directory>
-       <directory name="dbgk">
-               <file>dbgkutil.c</file>
-               <file>debug.c</file>
-       </directory>
-       <directory name="ex">
-               <if property="ARCH" value="i386">
-                       <directory name="i386">
-                               <file>interlck_asm.S</file>
-                               <file>fastinterlck_asm.S</file>
-                       </directory>
-               </if>
-                       <file>atom.c</file>
-                       <file>callback.c</file>
-                       <file>dbgctrl.c</file>
-                       <file>error.c</file>
+      <directory name="cc">
+              <file>cacheman.c</file>
+              <file>copy.c</file>
+              <file>fs.c</file>
+              <file>mdl.c</file>
+              <file>pin.c</file>
+              <file>view.c</file>
+      </directory>
+      <directory name="cm">
+              <file>import.c</file>
+              <file>ntfunc.c</file>
+              <file>regfile.c</file>
+              <file>registry.c</file>
+              <file>regobj.c</file>
+      </directory>
+      <directory name="kdbg">
+          <if property="ARCH" value="i386">
+              <directory name="i386">
+                  <if property="KDBG" value="1">
+                      <group>
+                          <file>i386-dis.c</file>
+                          <file>kdb_help.S</file>
+                          <file>longjmp.S</file>
+                          <file>setjmp.S</file>
+                      </group>
+                  </if>
+              </directory>
+          </if>
+          <if property="KDBG" value="1">
+              <file>kdb.c</file>
+              <file>kdb_cli.c</file>
+              <file>kdb_expr.c</file>
+              <file>kdb_keyboard.c</file>
+              <file>kdb_serial.c</file>
+              <file>kdb_string.c</file>
+          </if>
+          <if property="DBG_OR_KDBG" value="true">
+              <file>kdb_symbols.c</file>
+          </if>
+      </directory>
+      <directory name="dbgk">
+          <file>dbgkutil.c</file>
+          <file>debug.c</file>
+      </directory>
+      <directory name="ex">
+          <if property="ARCH" value="i386">
+              <directory name="i386">
+                  <file>interlck_asm.S</file>
+                  <file>fastinterlck_asm.S</file>
+              </directory>
+          </if>
+              <file>atom.c</file>
+              <file>callback.c</file>
+              <file>dbgctrl.c</file>
+              <file>error.c</file>
               <file>efi.c</file>
-                       <file>event.c</file>
-                       <file>evtpair.c</file>
-                       <file>fmutex.c</file>
-                       <file>handle.c</file>
-                       <file>init.c</file>
-                       <file>locale.c</file>
-                       <file>lookas.c</file>
-                       <file>mutant.c</file>
-                       <file>power.c</file>
-                       <file>pushlock.c</file>
-                       <file>profile.c</file>
-                       <file>resource.c</file>
-                       <file>rundown.c</file>
-                       <file>sem.c</file>
-                       <file>sysinfo.c</file>
-                       <file>time.c</file>
-                       <file>timer.c</file>
-                       <file>uuid.c</file>
-                       <file>win32k.c</file>
-                       <file>work.c</file>
-                       <file>zone.c</file>
-               <file>zw.S</file>
-       </directory>
-       <directory name="fs">
-                       <file>context.c</file>
-                       <file>fastio.c</file>
-                       <file>filelock.c</file>
-                       <file>mcb.c</file>
-                       <file>name.c</file>
-                       <file>notify.c</file>
-                       <file>oplock.c</file>
-                       <file>pool.c</file>
-                       <file>tunnel.c</file>
-                       <file>unc.c</file>
-                       <file>util.c</file>
-       </directory>
-       <directory name="inbv">
-               <file>inbv.c</file>
-       </directory>
-       <directory name="io">
+              <file>event.c</file>
+              <file>evtpair.c</file>
+              <file>fmutex.c</file>
+              <file>handle.c</file>
+              <file>init.c</file>
+              <file>locale.c</file>
+              <file>lookas.c</file>
+              <file>mutant.c</file>
+              <file>power.c</file>
+              <file>pushlock.c</file>
+              <file>profile.c</file>
+              <file>resource.c</file>
+              <file>rundown.c</file>
+              <file>sem.c</file>
+              <file>sysinfo.c</file>
+              <file>time.c</file>
+              <file>timer.c</file>
+              <file>uuid.c</file>
+              <file>win32k.c</file>
+              <file>work.c</file>
+              <file>zone.c</file>
+          <file>zw.S</file>
+      </directory>
+      <directory name="fs">
+              <file>context.c</file>
+              <file>fastio.c</file>
+              <file>filelock.c</file>
+              <file>mcb.c</file>
+              <file>name.c</file>
+              <file>notify.c</file>
+              <file>oplock.c</file>
+              <file>pool.c</file>
+              <file>tunnel.c</file>
+              <file>unc.c</file>
+              <file>util.c</file>
+      </directory>
+      <directory name="inbv">
+          <file>inbv.c</file>
+      </directory>
+      <directory name="io">
           <directory name="iomgr">
-                       <file>adapter.c</file>
-                       <file>arcname.c</file>
-                       <file>bootlog.c</file>
-                       <file>controller.c</file>
-                       <file>device.c</file>
-                       <file>deviface.c</file>
-                       <file>disk.c</file>
-                       <file>driver.c</file>
-                       <file>drvrlist.c</file>
-                       <file>error.c</file>
-                       <file>event.c</file>
+              <file>adapter.c</file>
+              <file>arcname.c</file>
+              <file>bootlog.c</file>
+              <file>controller.c</file>
+              <file>device.c</file>
+              <file>deviface.c</file>
+              <file>disk.c</file>
+              <file>driver.c</file>
+              <file>drvrlist.c</file>
+              <file>error.c</file>
+              <file>event.c</file>
               <file>file.c</file>
               <file>iocomp.c</file>
               <file>iofunc.c</file>
index 7d8f0be,0000000,0000000..4b8677e
mode 100644,000000,000000..100644
--- /dev/null
--- /dev/null
@@@@ -1,29 -1,0 -1,0 +1,31 @@@@
 ++# Function           Args    Returns Types
 ++# Real OFW functions to proxy
 ++finddevice           1       1       char* int
 ++open                 1       1       char* int
 ++getprop                      4       1       int char* char*:arg3 int int
 ++write                        3       1       int char*:arg2 int int
 ++read                 3       1       int char*:arg2 int int
 ++exit                 0       0       
 ++child                        1       1       int int
 ++peer                 1       1       int int
 ++parent                       1       1       int int
 ++seek                 3       1       int int int int
 ++# MMU methods 
 ++# claim (virt size align -- base)
 ++claim                        3       1       int int int int
+++# claim-mem (size align -- base)
+++claim-mem            2       1       int int int
 ++# release (virt size --)
 ++release                      2       0       int int
 ++package-to-path         3       1       int char*:arg2 int int
 ++# Declare the call-method BE function
 +++call-method         0       0       
 ++# Convenience functions that interact closely with OFW (written in BE asm)
 ++-dumpregs            0       0
 ++-print_string                1       0       char*
 ++-print_number                1       0       int
 ++-print_eol           0       0       
 ++-print_space         0       0       
 ++# MMU Methods
 ++@phys2virt!translate 4       1       int int int int&0 int
 ++@virt2phys!translate 2       1       int int&1 int
index ae44a7e,0000000,0000000..2951365
mode 100755,000000,000000..100755
--- /dev/null
--- /dev/null
@@@@ -1,10 -1,0 -1,0 +1,10 @@@@
-  powerpc-unknown-linux-gnu-ld -EL -g -nostartfiles -nostdlib -N -Ttext=0xe17000 -o freeldr.elf obj-ppc/boot/freeldr/freeldr/arch/powerpc/boot.o obj-ppc/boot/freeldr/freeldr/cache/blocklist.o obj-ppc/boot/freeldr/freeldr/cache/cache.o obj-ppc/boot/freeldr/freeldr/comm/rs232.o obj-ppc/boot/freeldr/freeldr/disk/disk.o obj-ppc/boot/freeldr/freeldr/disk/partition.o obj-ppc/boot/freeldr/freeldr/fs/ext2.o obj-ppc/boot/freeldr/freeldr/fs/fat.o obj-ppc/boot/freeldr/freeldr/fs/fs.o obj-ppc/boot/freeldr/freeldr/fs/fsrec.o obj-ppc/boot/freeldr/freeldr/fs/iso.o obj-ppc/boot/freeldr/freeldr/fs/ntfs.o obj-ppc/boot/freeldr/freeldr/inifile/ini_init.o obj-ppc/boot/freeldr/freeldr/inifile/inifile.o obj-ppc/boot/freeldr/freeldr/inifile/parse.o obj-ppc/boot/freeldr/freeldr/math/libgcc2.o obj-ppc/boot/freeldr/freeldr/mm/meminit.o obj-ppc/boot/freeldr/freeldr/mm/mm.o obj-ppc/boot/freeldr/freeldr/reactos/registry.o obj-ppc/boot/freeldr/freeldr/reactos/binhive.o obj-ppc/boot/freeldr/freeldr/reactos/arcname.o obj-ppc/boot/freeldr/freeldr/reactos/reactos.o obj-ppc/boot/freeldr/freeldr/rtl/list.o obj-ppc/boot/freeldr/freeldr/ui/gui.o obj-ppc/boot/freeldr/freeldr/ui/tui.o obj-ppc/boot/freeldr/freeldr/ui/tuimenu.o obj-ppc/boot/freeldr/freeldr/ui/ui.o obj-ppc/boot/freeldr/freeldr/video/bank.o obj-ppc/boot/freeldr/freeldr/video/fade.o obj-ppc/boot/freeldr/freeldr/video/palette.o obj-ppc/boot/freeldr/freeldr/video/pixel.o obj-ppc/boot/freeldr/freeldr/video/video.o obj-ppc/boot/freeldr/freeldr/freeldr.o obj-ppc/boot/freeldr/freeldr/debug.o obj-ppc/boot/freeldr/freeldr/version.o obj-ppc/boot/freeldr/freeldr/cmdline.o obj-ppc/boot/freeldr/freeldr/machine.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mach.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/ofw.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mmu.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mboot.o obj-ppc/boot/freeldr/freeldr/bootmgr.o obj-ppc/boot/freeldr/freeldr/drivemap.o obj-ppc/boot/freeldr/freeldr/miscboot.o obj-ppc/boot/freeldr/freeldr/options.o obj-ppc/boot/freeldr/freeldr/linuxboot.o obj-ppc/boot/freeldr/freeldr/oslist.o obj-ppc/boot/freeldr/freeldr/custom.o obj-ppc/lib/rossym/rossym.a obj-ppc/lib/cmlib/cmlib.a obj-ppc/lib/string/string.a obj-ppc/lib/rtl/rtl.a /usr/local/pkg/reactos-powerpc/lib/libgcc.a
 ++#!/bin/sh -v
 ++
 ++export PATH=$PATH:/usr/local/pkg/reactos-powerpc/bin
+++powerpc-unknown-linux-gnu-ld -EL -g -nostartfiles -nostdlib -N -Ttext=0xe17000 -o freeldr.elf obj-ppc/boot/freeldr/freeldr/arch/powerpc/boot.o obj-ppc/boot/freeldr/freeldr/cache/blocklist.o obj-ppc/boot/freeldr/freeldr/cache/cache.o obj-ppc/boot/freeldr/freeldr/comm/rs232.o obj-ppc/boot/freeldr/freeldr/disk/disk.o obj-ppc/boot/freeldr/freeldr/disk/partition.o obj-ppc/boot/freeldr/freeldr/fs/ext2.o obj-ppc/boot/freeldr/freeldr/fs/fat.o obj-ppc/boot/freeldr/freeldr/fs/fs.o obj-ppc/boot/freeldr/freeldr/fs/fsrec.o obj-ppc/boot/freeldr/freeldr/fs/iso.o obj-ppc/boot/freeldr/freeldr/fs/ntfs.o obj-ppc/boot/freeldr/freeldr/inifile/ini_init.o obj-ppc/boot/freeldr/freeldr/inifile/inifile.o obj-ppc/boot/freeldr/freeldr/inifile/parse.o obj-ppc/boot/freeldr/freeldr/math/libgcc2.o obj-ppc/boot/freeldr/freeldr/mm/meminit.o obj-ppc/boot/freeldr/freeldr/mm/mm.o obj-ppc/boot/freeldr/freeldr/reactos/registry.o obj-ppc/boot/freeldr/freeldr/reactos/binhive.o obj-ppc/boot/freeldr/freeldr/reactos/arcname.o obj-ppc/boot/freeldr/freeldr/reactos/reactos.o obj-ppc/boot/freeldr/freeldr/rtl/list.o obj-ppc/boot/freeldr/freeldr/ui/gui.o obj-ppc/boot/freeldr/freeldr/ui/tui.o obj-ppc/boot/freeldr/freeldr/ui/tuimenu.o obj-ppc/boot/freeldr/freeldr/ui/ui.o obj-ppc/boot/freeldr/freeldr/video/bank.o obj-ppc/boot/freeldr/freeldr/video/fade.o obj-ppc/boot/freeldr/freeldr/video/palette.o obj-ppc/boot/freeldr/freeldr/video/pixel.o obj-ppc/boot/freeldr/freeldr/video/video.o obj-ppc/boot/freeldr/freeldr/freeldr.o obj-ppc/boot/freeldr/freeldr/debug.o obj-ppc/boot/freeldr/freeldr/version.o obj-ppc/boot/freeldr/freeldr/cmdline.o obj-ppc/boot/freeldr/freeldr/machine.o obj-ppc/boot/freeldr/freeldr/windows/conversion.o obj-ppc/boot/freeldr/freeldr/windows/peloader.o obj-ppc/boot/freeldr/freeldr/windows/winldr.o obj-ppc/boot/freeldr/freeldr/windows/wlmemory.o obj-ppc/boot/freeldr/freeldr/windows/wlregistry.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mach.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/ofw.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mmu.o obj-ppc/boot/freeldr/freeldr/arch/powerpc/mboot.o obj-ppc/boot/freeldr/freeldr/bootmgr.o obj-ppc/boot/freeldr/freeldr/drivemap.o obj-ppc/boot/freeldr/freeldr/miscboot.o obj-ppc/boot/freeldr/freeldr/options.o obj-ppc/boot/freeldr/freeldr/linuxboot.o obj-ppc/boot/freeldr/freeldr/oslist.o obj-ppc/boot/freeldr/freeldr/custom.o obj-ppc/lib/rossym/rossym.a obj-ppc/lib/cmlib/cmlib.a obj-ppc/lib/string/string.a obj-ppc/lib/rtl/rtl.a /usr/local/pkg/reactos-powerpc/lib/libgcc.a
 ++powerpc-unknown-linux-gnu-objcopy -O binary freeldr.elf freeldr.tmp.le
 ++output-ppc/tools/ppc-le2be freeldr.tmp.le freeldr.tmp
 ++powerpc-unknown-linux-gnu-objcopy -I binary -B powerpc:common -O elf32-powerpc freeldr.tmp ofwldr.payload
 ++reactos-powerpc-as -mbig -o ofwboot.o boot/freeldr/bootsect/ofwboot.s boot/freeldr/bootsect/ofw_util.s boot/freeldr/bootsect/ofw.s
 ++powerpc-unknown-linux-gnu-ld -EB -Ttext 0xe00000 -Tdata 0xe17000 -e _begin -o ofwldr.x ofwboot.o ofwldr.payload
 ++powerpc-unknown-linux-gnu-objcopy --only-section=.text --only-section=.data ofwldr.x ofwldr