DPRINT("Block request succeeded\n");
return TRUE;
}
+
+BOOLEAN VFATWriteSectors(IN PDEVICE_OBJECT pDeviceObject,
+ IN ULONG DiskSector,
+ IN ULONG SectorCount,
+ IN UCHAR* Buffer)
+{
+ LARGE_INTEGER sectorNumber;
+ PIRP irp;
+ IO_STATUS_BLOCK ioStatus;
+ KEVENT event;
+ NTSTATUS status;
+ ULONG sectorSize;
+ PULONG mbr;
+ int j;
+
+ DPRINT("VFATWriteSector(pDeviceObject %x, DiskSector %d, Buffer %x)\n",
+ pDeviceObject,DiskSector,Buffer);
+
+ sectorNumber.HighPart = 0;
+ sectorNumber.LowPart = DiskSector * BLOCKSIZE;
+
+ KeInitializeEvent(&event, NotificationEvent, FALSE);
+
+ sectorSize = BLOCKSIZE*SectorCount;
+
+ mbr = ExAllocatePool(NonPagedPool, sectorSize);
+
+ if (!mbr) {
+ return FALSE;
+ }
+
+
+ DPRINT("Building synchronous FSD Request...\n");
+ irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
+ pDeviceObject,
+ mbr,
+ sectorSize,
+ §orNumber,
+ &event,
+ &ioStatus );
+
+ if (!irp) {
+ DbgPrint("WRITE failed!!!\n");
+ ExFreePool(mbr);
+ return FALSE;
+ }
+
+ DPRINT("Calling IO Driver...\n");
+ status = IoCallDriver(pDeviceObject,
+ irp);
+
+ DPRINT("Waiting for IO Operation...\n");
+ if (status == STATUS_PENDING) {
+ KeWaitForSingleObject(&event,
+ Suspended,
+ KernelMode,
+ FALSE,
+ NULL);
+ DPRINT("Getting IO Status...\n");
+ status = ioStatus.Status;
+ }
+
+ if (!NT_SUCCESS(status)) {
+ DbgPrint("IO failed!!! Error code: %d\n", status);
+ ExFreePool(mbr);
+ return FALSE;
+ }
+
+ DPRINT("Copying memory...\n");
+ RtlCopyMemory(Buffer,mbr,sectorSize);
+
+ ExFreePool(mbr);
+ DPRINT("Block request succeeded\n");
+ return TRUE;
+}
+
+
28-10-1998 Reads entire FAT into memory
VFatReadSector modified to read in more than one sector at a time
7-11-1998 Fixed bug that assumed that directory data could be fragmented
+ 8-12-1998 Added FAT32 support
+ Added initial writability functions
+ WARNING: DO NOT ATTEMPT TO TEST WRITABILITY FUNCTIONS!!!
+ 12-12-1998 Added basic support for FILE_STANDARD_INFORMATION request
*/
#include <ddk/ntddk.h>
#include <internal/string.h>
#include <wstring.h>
+#include <ddk/cctypes.h>
#define NDEBUG
#include <internal/debug.h>
#define FAT16 (1)
#define FAT12 (2)
+#define FAT32 (3)
typedef struct
{
/* FUNCTIONS ****************************************************************/
+ULONG Fat32GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
+{
+ ULONG FATsector;
+ ULONG FATeis;
+ PULONG Block;
+ Block = ExAllocatePool(NonPagedPool,1024);
+ FATsector=CurrentCluster/(512/sizeof(ULONG));
+ FATeis=CurrentCluster-(FATsector*(512/sizeof(ULONG)));
+ VFATReadSectors(DeviceExt->StorageDevice,DeviceExt->FATStart+FATsector, 1,
+ Block);
+ CurrentCluster = Block[FATeis];
+ if (CurrentCluster >= 0xffffff8 && CurrentCluster <= 0xfffffff)
+ CurrentCluster = 0;
+ ExFreePool(Block);
+ return(CurrentCluster);
+}
+
ULONG Fat16GetNextCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
{
ULONG FATsector;
Block = (PUSHORT)(DeviceExt->FAT + (FATsector * BLOCKSIZE));
CurrentCluster = Block[FATeis];
-
if (CurrentCluster >= 0xfff8 && CurrentCluster <= 0xffff)
- {
CurrentCluster = 0;
- }
DPRINT("Returning %x\n",CurrentCluster);
-
return(CurrentCluster);
}
CBlock = (unsigned char *)(DeviceExt->FAT + (FATsector * BLOCKSIZE));
FATOffset = (CurrentCluster * 12) % (512 * 8);
-
DPRINT("FATSector %d FATOffset %d\n",FATsector,FATOffset);
-
if ((CurrentCluster % 2) == 0)
{
Entry = CBlock[((FATOffset / 24)*3)];
Entry = (CBlock[((FATOffset / 24)*3) + 1] >> 4);
Entry |= (CBlock[((FATOffset / 24)*3) + 2] << 4);
}
-
DPRINT("Entry %x\n",Entry);
-
if (Entry >= 0xff8 && Entry <= 0xfff)
- {
Entry = 0;
- }
-
CurrentCluster = Entry;
DPRINT("Returning %x\n",CurrentCluster);
-
return(CurrentCluster);
}
{
return(Fat16GetNextCluster(DeviceExt, CurrentCluster));
}
+ else if (DeviceExt->FatType == FAT32)
+ {
+ return(Fat32GetNextCluster(DeviceExt, CurrentCluster));
+ }
else
- {
+ {
return(Fat12GetNextCluster(DeviceExt, CurrentCluster));
}
}
+ULONG FAT16FindAvailableCluster(PDEVICE_EXTENSION DeviceExt)
+{
+ ULONG sector;
+ PUSHORT Block;
+ int i;
+
+ sector = 0;
+ Block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
+
+ while(sector<DeviceExt->Boot->FATSectors) {
+ memcpy(Block, DeviceExt->FAT+sector*BLOCKSIZE, BLOCKSIZE);
+
+ for(i=0; i<512; i++) {
+ if(Block[i]==0) {
+ ExFreePool(Block);
+ return i;
+ }
+ }
+
+ sector++;
+ }
+
+ /* Give an error message (out of disk space) if we reach here) */
+
+ ExFreePool(Block);
+ return 0;
+}
+
+void FAT16WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
+ ULONG NewValue)
+{
+ ULONG FATsector;
+ ULONG FATeis;
+ PUSHORT Block;
+
+ Block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
+
+ FATsector=ClusterToWrite/(512/sizeof(USHORT));
+ FATeis=ClusterToWrite-(FATsector*256);
+
+ /* Update the in-memory FAT */
+ memcpy(Block, DeviceExt->FAT+FATsector*BLOCKSIZE, BLOCKSIZE);
+ Block[FATeis] = NewValue;
+ memcpy(DeviceExt->FAT+FATsector*BLOCKSIZE, Block, BLOCKSIZE);
+
+ /* Write the changed FAT sector to disk */
+ VFATWriteSectors(DeviceExt->StorageDevice,
+ DeviceExt->FATStart+FATsector,
+ DeviceExt->Boot->SectorsPerCluster,
+ (UCHAR *)Block);
+
+ ExFreePool(Block);
+}
+
+void FAT12WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
+ ULONG NewValue)
+{
+ unsigned char* CBlock;
+ ULONG FATsector;
+ ULONG FATOffset;
+ ULONG Entry;
+
+ CBlock = ExAllocatePool(NonPagedPool,1024);
+ FATsector = (ClusterToWrite * 12) / (512 * 8);
+
+ memcpy(CBlock,DeviceExt->FAT+FATsector*BLOCKSIZE, BLOCKSIZE);
+ FATOffset = (ClusterToWrite * 12) % (512 * 8);
+
+ DPRINT("FATSector %d FATOffset %d\n",FATsector,FATOffset);
+
+ /*
+
+ Write 12-bit entry
+
+ if ((CurrentCluster % 2) == 0)
+ {
+ Entry = CBlock[((FATOffset / 24)*3)];
+ Entry |= (CBlock[((FATOffset / 24)*3) + 1] & 0xf);
+ }
+ else
+ {
+ Entry = (CBlock[((FATOffset / 24)*3) + 1] >> 4);
+ Entry |= (CBlock[((FATOffset / 24)*3) + 2] << 4);
+ } */
+
+ ExFreePool(CBlock);
+}
+
+void WriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG ClusterToWrite,
+ ULONG NewValue)
+{
+ if (DeviceExt->FatType == FAT16) {
+ FAT16WriteCluster(DeviceExt, ClusterToWrite, NewValue);
+ } else {
+ FAT12WriteCluster(DeviceExt, ClusterToWrite, NewValue);
+ }
+}
+
+ULONG GetNextWriteCluster(PDEVICE_EXTENSION DeviceExt, ULONG CurrentCluster)
+{
+ ULONG LastCluster, NewCluster;
+ BOOLEAN EOF = FALSE;
+
+ DPRINT("GetNextWriteCluster(DeviceExt %x, CurrentCluster %x)\n",
+ DeviceExt,CurrentCluster);
+
+ /* Find out what was happening in the last cluster's AU */
+
+ if (DeviceExt->FatType == FAT16)
+ {
+ LastCluster = Fat16GetNextCluster(DeviceExt, CurrentCluster);
+ if(LastCluster == 0xFFFF) {
+ EOF = TRUE;
+ }
+ }
+ else
+ {
+ LastCluster = Fat12GetNextCluster(DeviceExt, CurrentCluster);
+ if(LastCluster == 0xFFF) {
+ EOF = TRUE;
+ }
+ }
+
+ /* Check to see if we must append or overwrite */
+
+ if (EOF == TRUE) {
+
+ /* Append */
+
+ /* Firstly, find the next available open allocation unit */
+ NewCluster = FAT16FindAvailableCluster(DeviceExt);
+
+ /* Mark the new AU as the EOF */
+ if(DeviceExt->FatType == FAT16) {
+ FAT16WriteCluster(DeviceExt, NewCluster, 0xFFFF);
+ } else {
+ FAT12WriteCluster(DeviceExt, NewCluster, 0xFFF);
+ }
+
+ /* Now, write the AU of the LastCluster with the value of the newly
+ found AU */
+ WriteCluster(DeviceExt, LastCluster, NewCluster);
+
+ /* Return NewCluster as CurrentCluster */
+ return NewCluster;
+
+ } else {
+
+ /* Overwrite: Return LastCluster as CurrentCluster */
+ return LastCluster;
+
+ }
+}
+
unsigned long ClusterToSector(PDEVICE_EXTENSION DeviceExt,
unsigned long Cluster)
{
WCHAR name[256];
ULONG StartingSector;
ULONG NextCluster;
-
DPRINT("FileFile(Parent %x, FileToFind %w)\n",Parent,FileToFind);
if (Parent == NULL)
{
- Size = DeviceExt->rootDirectorySectors;
+ Size = DeviceExt->rootDirectorySectors;//FIXME : in fat32, no limit
StartingSector = DeviceExt->rootStart;
}
else
DPRINT("Parent->entry.FileSize %x\n",Parent->entry.FileSize);
Size = ULONG_MAX;
- StartingSector = ClusterToSector(DeviceExt, Parent->entry.FirstCluster);
- NextCluster = Parent->entry.FirstCluster;
+ if (DeviceExt->FatType == FAT32)
+ NextCluster = Parent->entry.FirstCluster+Parent->entry.FirstClusterHigh*65536;
+ else
+ NextCluster = Parent->entry.FirstCluster;
+ StartingSector = ClusterToSector(DeviceExt, NextCluster);
}
-
block = ExAllocatePool(NonPagedPool,BLOCKSIZE);
for (j=0; j<Size; j++)
DPRINT("Comparing %w %w\n",name,FileToFind);
if (wstrcmpi(name,FileToFind))
{
-
/* In the case of a long filename, the firstcluster is stored in
the next record -- where it's short name is */
+ if(DeviceExt->FatType==FAT32)
+ if(((FATDirEntry *)block)[i].FirstCluster==0
+ &&((FATDirEntry *)block)[i].FirstClusterHigh==0
+ ) i++;
+ else
if(((FATDirEntry *)block)[i].FirstCluster==0) i++;
-
DPRINT("Found it at cluster %u\n", ((FATDirEntry *)block)[i].FirstCluster);
+ if( i==ENTRIES_PER_SECTOR)
+ {
+ VFATReadSectors(DeviceExt->StorageDevice,StartingSector+1,1,block);
+ i=0;
+ }
memcpy(&Fcb->entry,&((FATDirEntry *)block)[i],
sizeof(FATDirEntry));
*/
{
BootSector* Boot;
-
+
Boot = ExAllocatePool(NonPagedPool,512);
VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)Boot);
if (strncmp(Boot->SysType,"FAT12",5)==0 ||
- strncmp(Boot->SysType,"FAT16",5)==0)
+ strncmp(Boot->SysType,"FAT16",5)==0 ||
+ strncmp(((struct _BootSector32 *)(Boot))->SysType,"FAT32",5)==0)
{
ExFreePool(Boot);
return(TRUE);
return(FALSE);
}
-NTSTATUS FsdMountDevice(PDEVICE_EXTENSION DeviceExt,
+NTSTATUS FsdMountDevice(PDEVICE_EXTENSION DeviceExt,
PDEVICE_OBJECT DeviceToMount)
/*
* FUNCTION: Mounts the device
DPRINT("Mounting VFAT device...");
DPRINT("DeviceExt %x\n",DeviceExt);
-
+
DeviceExt->Boot = ExAllocatePool(NonPagedPool,512);
VFATReadSectors(DeviceToMount, 0, 1, (UCHAR *)DeviceExt->Boot);
{
DeviceExt->FatType = FAT12;
}
+ else if (strncmp(((struct _BootSector32 *)(DeviceExt->Boot))->SysType,"FAT32",5)==0)
+ {
+ DeviceExt->FatType = FAT32;
+ DeviceExt->rootDirectorySectors=DeviceExt->Boot->SectorsPerCluster;
+ DeviceExt->rootStart=
+ DeviceExt->FATStart+DeviceExt->Boot->FATCount
+ * ((struct _BootSector32 *)( DeviceExt->Boot))->FATSectors32;
+ DeviceExt->dataStart=DeviceExt->rootStart;
+ }
else
{
DeviceExt->FatType = FAT16;
}
- DeviceExt->FAT = ExAllocatePool(NonPagedPool, BLOCKSIZE*DeviceExt->Boot->FATSectors);
- VFATReadSectors(DeviceToMount, DeviceExt->FATStart, DeviceExt->Boot->FATSectors, (UCHAR *)DeviceExt->FAT);
+ // with FAT32 it's not a good idea to load always fat in memory
+ // because on a 8GB partition with 2 KO clusters, the fat = 8 MO
+ if(DeviceExt->FatType!=FAT32)
+ {
+ DeviceExt->FAT = ExAllocatePool(NonPagedPool, BLOCKSIZE*DeviceExt->Boot->FATSectors);
+ VFATReadSectors(DeviceToMount, DeviceExt->FATStart, DeviceExt->Boot->FATSectors, (UCHAR *)DeviceExt->FAT);
+ }
}
void VFATLoadCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster)
{
ULONG Sector;
- ULONG i;
+
+ DPRINT("VFATLoadCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
+ DeviceExt,Buffer,Cluster);
+
+ Sector = ClusterToSector(DeviceExt, Cluster);
+
+ VFATReadSectors(DeviceExt->StorageDevice,
+ Sector,
+ DeviceExt->Boot->SectorsPerCluster,
+ Buffer);
+}
+
+void VFATWriteCluster(PDEVICE_EXTENSION DeviceExt, PVOID Buffer, ULONG Cluster)
+{
+ ULONG Sector;
-// DPRINT("VFATLoadCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
-// DeviceExt,Buffer,Cluster);
+ DPRINT("VFATWriteCluster(DeviceExt %x, Buffer %x, Cluster %d)\n",
+ DeviceExt,Buffer,Cluster);
- Sector = ClusterToSector(DeviceExt, Cluster);
+ Sector = ClusterToSector(DeviceExt, Cluster);
- VFATReadSectors(DeviceExt->StorageDevice,
- Sector,
- DeviceExt->Boot->SectorsPerCluster,
- Buffer);
+ VFATWriteSectors(DeviceExt->StorageDevice,
+ Sector,
+ DeviceExt->Boot->SectorsPerCluster,
+ Buffer);
}
NTSTATUS FsdReadFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
ULONG CurrentCluster;
ULONG FileOffset;
ULONG FirstCluster;
- PFCB Fcb;
+ PFCB Fcb;
PVOID Temp;
ULONG TempLength;
FirstCluster = ReadOffset / DeviceExt->BytesPerCluster;
Fcb = FileObject->FsContext;
- CurrentCluster = Fcb->entry.FirstCluster;
+ if (DeviceExt->FatType == FAT32)
+ CurrentCluster = Fcb->entry.FirstCluster+Fcb->entry.FirstClusterHigh*65536;
+ else
+ CurrentCluster = Fcb->entry.FirstCluster;
if (ReadOffset >= Fcb->entry.FileSize)
{
if (CurrentCluster == 0)
{
- ExFreePool(Temp);
+ ExFreePool(Temp);
return(STATUS_SUCCESS);
}
return(STATUS_SUCCESS);
}
+NTSTATUS FsdWriteFile(PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject,
+ PVOID Buffer, ULONG Length, ULONG WriteOffset)
+/*
+ * FUNCTION: Writes data to file
+ */
+{
+ ULONG CurrentCluster;
+ ULONG FileOffset;
+ ULONG FirstCluster;
+ PFCB Fcb;
+ PVOID Temp;
+ ULONG TempLength;
+
+ /* Locate the first cluster of the file */
+
+ FirstCluster = WriteOffset / DeviceExt->BytesPerCluster;
+ Fcb = FileObject->FsContext;
+ if (DeviceExt->FatType == FAT32)
+ CurrentCluster = Fcb->entry.FirstCluster+Fcb->entry.FirstClusterHigh*65536;
+ else
+ CurrentCluster = Fcb->entry.FirstCluster;
+
+ /* Allocate a buffer to hold 1 cluster of data */
+
+ Temp = ExAllocatePool(NonPagedPool,DeviceExt->BytesPerCluster);
+
+ /* Find the cluster according to the offset in the file */
+
+ for (FileOffset=0; FileOffset < FirstCluster; FileOffset++)
+ {
+ CurrentCluster = GetNextCluster(DeviceExt,CurrentCluster);
+ }
+ CHECKPOINT;
+
+ /*
+ If the offset in the cluster doesn't fall on the cluster boundary then
+ we have to write only from the specified offset
+ */
+
+ if ((WriteOffset % DeviceExt->BytesPerCluster)!=0)
+ {
+ TempLength = min(Length,DeviceExt->BytesPerCluster -
+ (WriteOffset % DeviceExt->BytesPerCluster));
+
+ /* Read in the existing cluster data */
+ VFATLoadCluster(DeviceExt,Temp,CurrentCluster);
+
+ /* Overwrite the last parts of the data as necessary */
+ memcpy(Temp + WriteOffset % DeviceExt->BytesPerCluster, Buffer,
+ TempLength);
+
+ /* Write the cluster back */
+ VFATWriteCluster(DeviceExt,Temp,CurrentCluster);
+
+ /* Next write cluster */
+ CurrentCluster = GetNextWriteCluster(DeviceExt, CurrentCluster);
+
+ Length = Length - TempLength;
+ Buffer = Buffer + TempLength;
+ }
+ CHECKPOINT;
+
+ /* Write the buffer in chunks of 1 cluster */
+
+ while (Length > DeviceExt->BytesPerCluster)
+ {
+ VFATWriteCluster(DeviceExt, Buffer, CurrentCluster);
+ CurrentCluster = GetNextWriteCluster(DeviceExt, CurrentCluster);
+
+ if (CurrentCluster == 0)
+ {
+ ExFreePool(Temp);
+ return(STATUS_SUCCESS);
+ }
+
+ Buffer = Buffer + DeviceExt->BytesPerCluster;
+ Length = Length - DeviceExt->BytesPerCluster;
+ }
+ CHECKPOINT;
+
+ /* Write the remainder */
+
+ if (Length > 0)
+ {
+ memcpy(Temp, Buffer, Length);
+ VFATWriteCluster(DeviceExt, Temp, CurrentCluster);
+ }
+
+ ExFreePool(Temp);
+ return(STATUS_SUCCESS);
+}
NTSTATUS FsdClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PFILE_OBJECT FileObject = Stack->FileObject;
PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
NTSTATUS Status;
-
+
Status = FsdCloseFile(DeviceExtension,FileObject);
Irp->IoStatus.Status = Status;
NTSTATUS FsdWrite(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
- DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
+ ULONG Length;
+ PVOID Buffer;
+ ULONG Offset;
+ PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+ PFILE_OBJECT FileObject = Stack->FileObject;
+ PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
+ NTSTATUS Status;
- Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
- Irp->IoStatus.Information = 0;
- return(STATUS_UNSUCCESSFUL);
+ DPRINT("FsdWrite(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
+
+ Length = Stack->Parameters.Write.Length;
+ Buffer = MmGetSystemAddressForMdl(Irp->MdlAddress);
+ Offset = Stack->Parameters.Write.ByteOffset.LowPart;
+
+ Status = FsdWriteFile(DeviceExt,FileObject,Buffer,Length,Offset);
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = Length;
+ IoCompleteRequest(Irp,IO_NO_INCREMENT);
+
+ return(Status);
}
NTSTATUS FsdRead(PDEVICE_OBJECT DeviceObject, PIRP Irp)
NTSTATUS FsdFileSystemControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
- PVPB vpb = Stack->Parameters.Mount.Vpb;
+// PVPB vpb = Stack->Parameters.Mount.Vpb;
PDEVICE_OBJECT DeviceToMount = Stack->Parameters.Mount.DeviceObject;
NTSTATUS Status;
-
+
DPRINT("VFAT FSC\n");
if (FsdHasFileSystem(DeviceToMount))
Status = STATUS_UNRECOGNIZED_VOLUME;
}
DPRINT("VFAT File system successfully mounted\n");
-
+
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
return(Status);
}
+NTSTATUS FsdGetStandardInformation(PFCB FCB, PDEVICE_OBJECT DeviceObject,
+ PFILE_STANDARD_INFORMATION StandardInfo)
+{
+ PDEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+ unsigned long AllocSize;
+
+ RtlZeroMemory(StandardInfo, sizeof(FILE_STANDARD_INFORMATION));
+
+ /* Make allocsize a rounded up multiple of BytesPerCluster */
+ AllocSize = 0;
+ while(AllocSize<FCB->entry.FileSize) {
+ AllocSize+=DeviceExtension->BytesPerCluster;
+ }
+
+ StandardInfo->AllocationSize = RtlConvertUlongToLargeInteger(AllocSize);
+ StandardInfo->EndOfFile = RtlConvertUlongToLargeInteger(FCB->entry.FileSize);
+ StandardInfo->NumberOfLinks = 0;
+ StandardInfo->DeletePending = FALSE;
+ if((FCB->entry.Attrib & 0x10)>0) {
+ StandardInfo->Directory = TRUE;
+ } else {
+ StandardInfo->Directory = FALSE;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS FsdQueryInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp)
+{
+ PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
+ FILE_INFORMATION_CLASS FileInformationClass =
+ Stack->Parameters.QueryFile.FileInformationClass;
+ PFILE_OBJECT FileObject = NULL;
+ PFCB FCB = NULL;
+ PCCB CCB = NULL;
+
+ NTSTATUS RC = STATUS_SUCCESS;
+ void *SystemBuffer;
+
+ FileObject = Stack->FileObject;
+ CCB = (PCCB)(FileObject->FsContext2);
+ FCB = CCB->Buffer; // Should be CCB->FCB???
+
+ SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
+
+ switch(FileInformationClass) {
+ case FileStandardInformation:
+ RC = FsdGetStandardInformation(FCB, DeviceObject, SystemBuffer);
+ break;
+ }
+
+ return RC;
+}
+
NTSTATUS DriverEntry(PDRIVER_OBJECT _DriverObject,
PUNICODE_STRING RegistryPath)
/*
UNICODE_STRING ustr;
ANSI_STRING astr;
- DbgPrint("VFAT 0.0.3\n");
+ DbgPrint("VFAT 0.0.4\n");
DriverObject = _DriverObject;
DriverObject->MajorFunction[IRP_MJ_WRITE] = FsdWrite;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
FsdFileSystemControl;
+ DriverObject->MajorFunction[IRP_MJ_QUERY_INFORMATION] =
+ FsdQueryInformation;
DriverObject->DriverUnload = NULL;
IoRegisterFileSystem(DeviceObject);
IN ULONG SectorCount,
IN UCHAR* Buffer);
+BOOLEAN VFATWriteSectors(IN PDEVICE_OBJECT pDeviceObject,
+ IN ULONG DiskSector,
+ IN ULONG SectorCount,
+ IN UCHAR* Buffer);
+
struct _BootSector {
unsigned char magic0, res0, magic1;
unsigned char OEMName[8];
unsigned char Res2[450];
} __attribute__((packed));
+struct _BootSector32 {
+ unsigned char magic0, res0, magic1;
+ unsigned char OEMName[8];
+ unsigned short BytesPerSector;
+ unsigned char SectorsPerCluster;
+ unsigned short ReservedSectors;
+ unsigned char FATCount;
+ unsigned short RootEntries, Sectors;
+ unsigned char Media;
+ unsigned short FATSectors, SectorsPerTrack, Heads;
+ unsigned long HiddenSectors, SectorsHuge;
+ unsigned long FATSectors32;
+ unsigned char x[31];
+ unsigned char VolumeLabel[11], SysType[8];
+ unsigned char Res2[422];
+} __attribute__((packed));
+
typedef struct _BootSector BootSector;
struct _FATDirEntry {
- unsigned char Filename[8], Ext[3], Attrib, Res[14];
+ unsigned char Filename[8], Ext[3], Attrib, Res[8];
+ unsigned short FirstClusterHigh;// higher
+ unsigned char Res2[4];
unsigned short FirstCluster;
unsigned long FileSize;
} __attribute__((packed));
typedef struct _slot slot;
#define BLOCKSIZE 512
+
+// Put the rest in struct.h
+/*
+typedef unsigned int uint32;
+
+typedef struct _SFsdIdentifier {
+ uint32 NodeType;
+ uint32 NodeSize;
+} SFsdIdentifier, *PtrSFsdIdentifier;
+
+typedef struct _SFsdNTRequiredFCB {
+ FSRTL_COMMON_FCB_HEADER CommonFCBHeader;
+ SECTION_OBJECT_POINTERS SectionObject;
+ ERESOURCE MainResource;
+ ERESOURCE PagingIoResource;
+} SFsdNTRequiredFCB, *PtrSFsdNTRequiredFCB;
+
+typedef struct _SFsdFileControlBlock {
+ SFsdIdentifier NodeIdentifier;
+ SFsdNTRequiredFCB NTRequiredFCB;
+ SFsdDiskDependentFCB DiskDependentFCB;
+ struct _SFsdVolumeControlBlock *PtrVCB;
+ LIST_ENTRY NextFCB;
+ uint32 FCBFlags;
+ LIST_ENTRY NextCCB;
+ SHARE_ACCESS FCBShareAccess;
+ uint32 LazyWriterThreadID;
+ uint32 ReferenceCount;
+ uint32 OpenHandleCount;
+ PtrSFsdObjectName FCBName;
+ LARGE_INTEGER CreationTime;
+ LARGE_INTEGER LastAccessTime;
+ LARGE_INTEGER LastWriteTime;
+ SFsdFileLockAnchorFCB ByteRangeLock;
+ OPLOCK FCBOplock;
+} SFsdFCB, *PtrSFsdFCB;
+
+*/
+#ifndef __DDK_LI_H
+#define __DDK_LI_H
+
+#define QUAD_PART(LI) (*(LONGLONG *)(&LI))
+
#ifdef COMPILER_LARGE_INTEGERS
#define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( ( LargeInteger >> 32) )
( LargeInteger |= ( ((LARGE_INTEGER)Signed_Long) << 32 ) )
#define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) \
( LargeInteger |= Unsigned_Long )
+#define LARGE_INTEGER_QUAD_PART(LargeInteger) (LargeInteger)
#else
-#define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( (LargeInteger.HighPart) )
-#define GET_LARGE_INTEGER_LOW_PART(LargeInteger) ( (LargeInteger.LowPart) )
+
+#define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( (LargeInteger).HighPart )
+#define GET_LARGE_INTEGER_LOW_PART(LargeInteger) ( (LargeInteger).LowPart )
#define SET_LARGE_INTEGER_HIGH_PART(LargeInteger,Signed_Long) \
- ( LargeInteger.HighPart= Signed_Long )
+ ((LargeInteger).HighPart = (Signed_Long))
#define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) \
- ( LargeInteger.LowPart = Unsigned_Long )
+ ((LargeInteger).LowPart = (Unsigned_Long))
+#define LARGE_INTEGER_QUAD_PART(LI) (*(LONGLONG *)(&(LI)))
+
+#endif
#endif
#include <windows.h>
-#define QUAD_PART(LI) (*(LONGLONG *)(&LI))
+#include <ddk/li.h>
#include <ddk/status.h>
#include <ddk/ntdef.h>
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
+#define INIT_UNICODE_STRING(us, str) \
+ ((us).Length = strlen((str)), \
+ (us).MaximumLength = (us).Length, \
+ (us).Buffer = (str), (us))
+
typedef enum _SECTION_INHERIT {
ViewShare = 1,
ViewUnmap = 2
#define __MODULE_H
#include <coff.h>
+#include <pe.h>
-typedef struct
-/*
- *
- */
+/* FIXME: replace this struct with struct below in all code */
+typedef struct _module
{
unsigned int nsyms;
unsigned int text_base;
unsigned int raw_data_off;
} module;
+typedef SCNHDR COFF_SECTION_HEADER, *PCOFF_SECTION_HEADER;
+
+typedef struct _MODULE
+{
+ PVOID Base;
+ unsigned int Size;
+ unsigned int Flags;
+ union
+ {
+ struct
+ {
+ unsigned int NumberOfSyms;
+ PVOID TextBase;
+ PVOID DataBase;
+ PVOID BSSBase;
+ SCNHDR *SectionList;
+ char *StringTable;
+ SYMENT *SymbolList;
+ } COFF;
+ struct
+ {
+ PIMAGE_FILE_HEADER FileHeader;
+ PIMAGE_OPTIONAL_HEADER OptionalHeader;
+ PCOFF_SECTION_HEADER SectionList;
+ } PE;
+ } Image;
+} MODULE, *PMODULE;
+
+#define MODULE_FLAG_BIN 0x0001
+#define MODULE_FLAG_MZ 0x0002
+#define MODULE_FLAG_NE 0x0004
+#define MODULE_FLAG_PE 0x0008
+#define MODULE_FLAG_COFF 0x0010
+
+typedef struct _INSTANCE
+{
+ HANDLE ModuleHandle;
+} INSTANCE, *PINSTANCE;
+
BOOLEAN process_boot_module(unsigned int start);
#endif
#endif
#define IMAGE_DOS_MAGIC 0x54ad
-#define IMAGE_NT_MAGIC 0x00004550
+#define IMAGE_PE_MAGIC 0x00004550
typedef struct _IMAGE_DOS_HEADER { // DOS .EXE header
WORD e_magic; // Magic number
#define IMAGE_SEPARATE_DEBUG_MISMATCH 0x8000 // when DBG was updated, the
// old checksum didn't match.
-
//
// End Image Format
//
-
#define SIZE_OF_NT_SIGNATURE sizeof (DWORD)
#define MAXRESOURCENAME 13
sizeof (IMAGE_FILE_HEADER) + \
sizeof (IMAGE_OPTIONAL_HEADER)))
-
-typedef struct tagImportDirectory
- {
- DWORD dwRVAFunctionNameList;
- DWORD dwUseless1;
- DWORD dwUseless2;
- DWORD dwRVAModuleName;
- DWORD dwRVAFunctionAddressList;
- }IMAGE_IMPORT_MODULE_DIRECTORY, * PIMAGE_IMPORT_MODULE_DIRECTORY;
+typedef struct _IMAGE_IMPORT_MODULE_DIRECTORY
+{
+ DWORD dwRVAFunctionNameList;
+ DWORD dwUseless1;
+ DWORD dwUseless2;
+ DWORD dwRVAModuleName;
+ DWORD dwRVAFunctionAddressList;
+} IMAGE_IMPORT_MODULE_DIRECTORY, *PIMAGE_IMPORT_MODULE_DIRECTORY;
+
+typedef struct _RELOCATION_DIRECTORY
+{
+ DWORD VirtualAddress; /* adresse virtuelle du bloc ou se font les relocations */
+ DWORD SizeOfBlock; // taille de cette structure + des structures
+ // relocation_entry qui suivent (ces dernieres sont
+ // donc au nombre de (SizeOfBlock-8)/2
+} RELOCATION_DIRECTORY, *PRELOCATION_DIRECTORY;
+
+typedef struct _RELOCATION_ENTRY
+{
+ WORD TypeOffset;
+ // (TypeOffset >> 12) est le type
+ // (TypeOffset&0xfff) est l'offset dans le bloc
+} RELOCATION_ENTRY, *PRELOCATION_ENTRY;
+
+#define TYPE_RELOC_ABSOLUTE 0
+#define TYPE_RELOC_HIGH 1
+#define TYPE_RELOC_LOW 2
+#define TYPE_RELOC_HIGHLOW 3
+#define TYPE_RELOC_HIGHADJ 4
+#define TYPE_RELOC_MIPS_JMPADDR 5
#ifndef _GNU_H_WINDOWS32_STRUCTURES
#define _GNU_H_WINDOWS32_STRUCTURES
+#ifdef COMPILER_LARGE_INTEGERS
+
+typedef long long int LARGE_INTEGER, *PLARGE_INTEGER;
+typedef unsigned long long int ULARGE_INTEGER, *PULARGE_INTEGER;
+
+#else
+
typedef struct _LARGE_INTEGER {
DWORD LowPart;
LONG HighPart;
} LARGE_INTEGER, *PLARGE_INTEGER;
+typedef struct _ULARGE_INTEGER {
+ DWORD LowPart;
+ DWORD HighPart;
+} ULARGE_INTEGER, *PULARGE_INTEGER;
+
+#endif
+
typedef struct _LIST_ENTRY {
struct _LIST_ENTRY *Flink;
struct _LIST_ENTRY *Blink;
DWORD Reserved;
} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION;
-typedef struct _ULARGE_INTEGER {
- DWORD LowPart;
- DWORD HighPart;
-} ULARGE_INTEGER, *PULARGE_INTEGER;
-
typedef struct _GENERIC_MAPPING {
ACCESS_MASK GenericRead;
ACCESS_MASK GenericWrite;
;
;
loading_msg db 'Loading: ',0
+death_msg: db 'death', 0
filelength_lo dw 0
filelength_hi dw 0
# Select the device drivers and filesystems you want
#
KERNEL_SERVICES = parallel keyboard null mouse serial sound ide test sdisk \
- minix vfat ext2fs
+ minix vfat # ext2fs
APPS = hello shell
Ccb->Buffer=ExAllocatePool(NonPagedPool,Dccb->SectorSize);
}
- Offset.HighPart = 0;
- Offset.LowPart = Ccb->BlockNr * Dccb->SectorSize;
+ SET_LARGE_INTEGER_HIGH_PART(Offset, 0);
+ SET_LARGE_INTEGER_LOW_PART(Offset, Ccb->BlockNr * Dccb->SectorSize);
KeInitializeEvent(&Event,NotificationEvent,FALSE);
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_READ,
Dccb->DeviceObject,
NTSTATUS Status;
KEVENT Event;
- Offset.HighPart = 0;
- Offset.LowPart = Ccb->BlockNr * Dccb->SectorSize;
+ SET_LARGE_INTEGER_HIGH_PART(Offset, 0);
+ SET_LARGE_INTEGER_LOW_PART(Offset, Ccb->BlockNr * Dccb->SectorSize);
KeInitializeEvent(&Event,NotificationEvent,FALSE);
Irp = IoBuildSynchronousFsdRequest(IRP_MJ_WRITE,
Dccb->DeviceObject,
PCCB CbFindModifiedCcb(PDCCB Dccb, PCCB Start)
{
-
+ UNIMPLEMENTED;
}
static VOID CbDeleteAllCcbs(PDCCB Dccb)
BOOLEAN ExTryToAcquireResourceExclusiveLite(PERESOURCE Resource)
{
LARGE_INTEGER timeout;
- timeout.HighPart = 0;
- timeout.LowPart = 0;
- KeWaitForSingleObject(&Resource->ExclusiveWaiters,Executive,KernelMode,
- FALSE,&timeout);
+
+ SET_LARGE_INTEGER_HIGH_PART(timeout, 0);
+ SET_LARGE_INTEGER_LOW_PART(timeout, 0);
+ return KeWaitForSingleObject(&Resource->ExclusiveWaiters,
+ Executive,
+ KernelMode,
+ FALSE,
+ &timeout) == STATUS_SUCCESS;
}
* FUNCTION: Returns the physical address corresponding to a virtual address
*/
{
- PHYSICAL_ADDRESS p;
- DPRINT("get_page_physical_address(vaddr %x)\n",vaddr);
- p.HighPart = 0;
- p.LowPart = PAGE_MASK(*get_page_entry((unsigned int)vaddr));
- return(p);
+ PHYSICAL_ADDRESS p;
+
+ DPRINT("get_page_physical_address(vaddr %x)\n", vaddr);
+ SET_LARGE_INTEGER_HIGH_PART(p, 0);
+ SET_LARGE_INTEGER_LOW_PART(p, PAGE_MASK(
+ *get_page_entry((unsigned int) vaddr)));
+
+ return p;
}
BOOL is_page_present(unsigned int vaddr)
#define SERIAL_PORT 0x03f8
#define SERIAL_BAUD_RATE 19200
#define SERIAL_LINE_CONTROL (SR_LCR_CS8 | SR_LCR_ST1 | SR_LCR_PNO)
-//#define NDEBUG
+
+#define NDEBUG
#include <internal/debug.h>
/* GLOBALS ******************************************************************/
}
if (StartingOffset!=NULL)
{
- StackPtr->Parameters.Write.ByteOffset.LowPart =
- StartingOffset->LowPart;
- StackPtr->Parameters.Write.ByteOffset.HighPart =
- StartingOffset->HighPart;
+ StackPtr->Parameters.Write.ByteOffset = *StartingOffset;
}
else
{
- StackPtr->Parameters.Write.ByteOffset.LowPart = 0;
- StackPtr->Parameters.Write.ByteOffset.HighPart = 0;
+ SET_LARGE_INTEGER_LOW_PART(StackPtr->Parameters.Write.ByteOffset, 0);
+ SET_LARGE_INTEGER_HIGH_PART(StackPtr->Parameters.Write.ByteOffset, 0);
}
}
StackPtr->Parameters.Write.Length = Length;
if (MajorFunction == IRP_MJ_READ)
{
- if (StartingOffset!=NULL)
+ if (StartingOffset != NULL)
{
- StackPtr->Parameters.Read.ByteOffset.LowPart =
- StartingOffset->LowPart;
- StackPtr->Parameters.Read.ByteOffset.HighPart =
- StartingOffset->HighPart;
+ StackPtr->Parameters.Read.ByteOffset = *StartingOffset;
}
else
{
- StackPtr->Parameters.Read.ByteOffset.LowPart = 0;
- StackPtr->Parameters.Read.ByteOffset.HighPart = 0;
+ SET_LARGE_INTEGER_LOW_PART(StackPtr->Parameters.Read.ByteOffset, 0);
+ SET_LARGE_INTEGER_HIGH_PART(StackPtr->Parameters.Read.ByteOffset, 0);
}
}
else
{
if (StartingOffset!=NULL)
{
- StackPtr->Parameters.Write.ByteOffset.LowPart =
- StartingOffset->LowPart;
- StackPtr->Parameters.Write.ByteOffset.HighPart =
- StartingOffset->HighPart;
+ StackPtr->Parameters.Write.ByteOffset = *StartingOffset;
}
else
{
- StackPtr->Parameters.Write.ByteOffset.LowPart = 0;
- StackPtr->Parameters.Write.ByteOffset.HighPart = 0;
+ SET_LARGE_INTEGER_LOW_PART(StackPtr->Parameters.Write.ByteOffset, 0);
+ SET_LARGE_INTEGER_HIGH_PART(StackPtr->Parameters.Write.ByteOffset, 0);
}
}
return(Irp);
}
+
}
if (FileObject != NULL)
{
- FileObject->CurrentByteOffset.LowPart =
- FileObject->CurrentByteOffset.LowPart + Irp->IoStatus.Information;
+ SET_LARGE_INTEGER_LOW_PART(FileObject->CurrentByteOffset,
+ GET_LARGE_INTEGER_LOW_PART(FileObject->CurrentByteOffset) +
+ Irp->IoStatus.Information);
}
}
StackPtr->Parameters.Read.Length = Length;
if (ByteOffset!=NULL)
{
- StackPtr->Parameters.Read.ByteOffset.LowPart = ByteOffset->LowPart;
- StackPtr->Parameters.Read.ByteOffset.HighPart = ByteOffset->HighPart;
+ StackPtr->Parameters.Read.ByteOffset = *ByteOffset;
}
else
{
- StackPtr->Parameters.Read.ByteOffset.LowPart = 0;
- StackPtr->Parameters.Read.ByteOffset.HighPart = 0;
+ SET_LARGE_INTEGER_LOW_PART(StackPtr->Parameters.Read.ByteOffset, 0);
+ SET_LARGE_INTEGER_HIGH_PART(StackPtr->Parameters.Read.ByteOffset, 0);
}
if (Key!=NULL)
{
/*
* Initalize the console (before printing anything)
*/
- HalInitConsole(&bp);
+ HalInitConsole(&_bp);
DbgPrint("Starting ReactOS "KERNEL_VERSION"\n");
-
+
start = KERNEL_BASE + PAGE_ROUND_UP(bp.module_length[0]);
if (start < ((int)&end))
{
/* FUNCTIONS **************************************************************/
-void KeCalibrateTimerLoop()
+VOID KeCalibrateTimerLoop(VOID)
{
unsigned int start_tick;
- unsigned int end_tick;
- unsigned int nr_ticks;
+// unsigned int end_tick;
+// unsigned int nr_ticks;
unsigned int i;
unsigned int microseconds;
}
-NTSTATUS KeAddThreadTimeout(PKTHREAD Thread, PLARGE_INTEGER Interval)
+NTSTATUS
+KeAddThreadTimeout(PKTHREAD Thread, PLARGE_INTEGER Interval)
{
- KeInitializeTimer(&(Thread->TimerBlock));
- KeSetTimer(&(Thread->TimerBlock),*Interval,NULL);
+ assert(Thread != NULL);
+ assert(Interval != NULL);
+
+ KeInitializeTimer(&(Thread->TimerBlock));
+ KeSetTimer(&(Thread->TimerBlock),*Interval,NULL);
+
+ return STATUS_SUCCESS;
}
}
}
+#if 0
static inline void ULLToLargeInteger(unsigned long long src,
PLARGE_INTEGER dest)
{
return(r);
}
+#endif
+
LARGE_INTEGER KeQueryPerformanceCounter(PLARGE_INTEGER PerformanceFreq)
/*
* NOTE: Returns the system tick count or the time-stamp on the pentium
*/
{
- PerformanceFreq->HighPart=0;
- PerformanceFreq->LowPart=0;
+ if (PerformanceFreq != NULL)
+ {
+ LARGE_INTEGER_QUAD_PART(*PerformanceFreq) = 0;
+ }
- return *PerformanceFreq;
+ return *PerformanceFreq;
}
ULONG KeQueryTimeIncrement(VOID)
* 1st of January, 1601.
*/
{
- ULLToLargeInteger(system_time,CurrentTime);
+ LARGE_INTEGER_QUAD_PART(*CurrentTime) = system_time;
}
NTSTATUS STDCALL NtGetTickCount(PULONG UpTime)
* TickCount (OUT) = Points to storage for the number of ticks
*/
{
- ULLToLargeInteger(ticks,TickCount);
+ LARGE_INTEGER_QUAD_PART(*TickCount) = ticks;
}
static void HandleExpiredTimer(PKTIMER current)
extern unsigned int EiFreeNonPagedPool;
extern unsigned int EiUsedNonPagedPool;
-VOID KiTimerInterrupt(VOID)
+BOOLEAN KiTimerInterrupt(VOID)
/*
* FUNCTION: Handles a timer interrupt
*/
*vidmem=0x7;
vidmem++;
}
-
- return(TRUE);
+
+ return TRUE;
}
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/ldr/loader.c
* PURPOSE: Loaders for PE executables
- * PROGRAMMER: Rex Jolliff (rex@lvcablemodem.com)
+ * PROGRAMMERS: Jean Michault
+ * Rex Jolliff (rex@lvcablemodem.com)
* UPDATE HISTORY:
* DW 22/05/98 Created
- * RJJ 10/12/98 Completed loader function and added hooks for MZ/PE
+ * RJJ 10/12/98 Completed image loader function and added hooks for MZ/PE
+ * RJJ 10/12/98 Built driver loader function and added hooks for PE/COFF
* RJJ 10/12/98 Rolled in David's code to load COFF drivers
+ * JM 14/12/98 Built initail PE user module loader
*/
/* INCLUDES *****************************************************************/
#include <internal/kernel.h>
#include <internal/linkage.h>
#include <internal/module.h>
+#include <internal/ob.h>
#include <internal/string.h>
#include <internal/symbol.h>
#include <ddk/ntddk.h>
-#include <ddk/li.h>
//#define NDEBUG
#include <internal/debug.h>
-#include "pe.h"
+/* MACROS ********************************************************************/
+
+#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S))
+
+/* GLOBALS *******************************************************************/
+
+POBJECT_TYPE ObModuleType = NULL;
/* FORWARD DECLARATIONS ******************************************************/
NTSTATUS LdrCOFFProcessDriver(PVOID ModuleLoadBase);
NTSTATUS LdrPEProcessDriver(PVOID ModuleLoadBase);
-/* COFF Driver load support **************************************************/
-
+/* COFF Driver load support */
static BOOLEAN LdrCOFFDoRelocations(module *Module, unsigned int SectionIndex);
static BOOLEAN LdrCOFFDoAddr32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
static BOOLEAN LdrCOFFDoReloc32Reloc(module *Module, SCNHDR *Section, RELOC *Relocation);
static unsigned int LdrCOFFGetKernelSymbolAddr(char *Name);
static unsigned int LdrCOFFGetSymbolValueByName(module *Module, char *SymbolName, unsigned int Idx);
+/* Image loader forward delcarations */
+static NTSTATUS LdrProcessMZImage(HANDLE ProcessHandle, HANDLE ModuleHandle, HANDLE FileHandle);
+static NTSTATUS LdrProcessPEImage(HANDLE ProcessHandle, HANDLE ModuleHandle, HANDLE FileHandle);
+static NTSTATUS LdrProcessBinImage(HANDLE ProcessHandle, HANDLE ModuleHandle, HANDLE FileHandle);
+
/* FUNCTIONS *****************************************************************/
+VOID LdrInitModuleManagment(VOID)
+{
+ ANSI_STRING AnsiString;
+
+ /* Register the process object type */
+ ObModuleType = ExAllocatePool(NonPagedPool, sizeof(OBJECT_TYPE));
+ ObModuleType->TotalObjects = 0;
+ ObModuleType->TotalHandles = 0;
+ ObModuleType->MaxObjects = ULONG_MAX;
+ ObModuleType->MaxHandles = ULONG_MAX;
+ ObModuleType->PagedPoolCharge = 0;
+ ObModuleType->NonpagedPoolCharge = sizeof(MODULE);
+ ObModuleType->Dump = NULL;
+ ObModuleType->Open = NULL;
+ ObModuleType->Close = NULL;
+ ObModuleType->Delete = NULL;
+ ObModuleType->Parse = NULL;
+ ObModuleType->Security = NULL;
+ ObModuleType->QueryName = NULL;
+ ObModuleType->OkayToClose = NULL;
+ RtlInitAnsiString(&AnsiString, "Module");
+ RtlAnsiStringToUnicodeString(&ObModuleType->TypeName, &AnsiString, TRUE);
+}
+
/*
* FUNCTION: Loads a kernel driver
* ARGUMENTS:
PIMAGE_DOS_HEADER PEDosHeader;
FILE_STANDARD_INFORMATION FileStdInfo;
+ DbgPrint("Loading Driver %W...\n", Filename);
+
/* Open the Driver */
InitializeObjectAttributes(&FileObjectAttributes,
Filename,
NTSTATUS
LdrPEProcessDriver(PVOID ModuleLoadBase)
{
- PULONG NTMagic;
+ unsigned int DriverSize;
+ PVOID DriverBase, CodeBase, InitializedDataBase, UninitializedDataBase;
+ PULONG PEMagic;
PIMAGE_DOS_HEADER PEDosHeader;
PIMAGE_FILE_HEADER PEFileHeader;
PIMAGE_OPTIONAL_HEADER PEOptionalHeader;
+ DbgPrint("Processing PE Driver at module base:%08lx\n", ModuleLoadBase);
+
/* Get header pointers */
PEDosHeader = (PIMAGE_DOS_HEADER) ModuleLoadBase;
PEMagic = (PULONG) ((unsigned int) ModuleLoadBase +
PEDosHeader->e_lfanew + sizeof(ULONG));
PEOptionalHeader = (PIMAGE_OPTIONAL_HEADER) ((unsigned int) ModuleLoadBase +
PEDosHeader->e_lfanew + sizeof(ULONG) + sizeof(IMAGE_FILE_HEADER));
+ CHECKPOINT;
/* Check file magic numbers */
if (PEDosHeader->e_magic != IMAGE_DOS_MAGIC ||
PEDosHeader->e_lfanew == 0 ||
- *PEMagic != IMAGE_NT_MAGIC ||
+ *PEMagic != IMAGE_PE_MAGIC ||
PEFileHeader->Machine != IMAGE_FILE_MACHINE_I386)
{
return STATUS_UNSUCCESSFUL;
}
+ CHECKPOINT;
+
+#if 0
+ /* FIXME: if image is fixed-address load, then fail */
+
+ /* FIXME: check/verify OS version number */
+
+ DbgPrint("OptionalHdrMagic:%04x LinkVersion:%d.%d\n",
+ PEOptionalHeader->Magic,
+ PEOptionalHeader->MajorLinkerVersion,
+ PEOptionalHeader->MinorLinkerVersion);
+ DbgPrint("Size: CODE:%08lx(%d) DATA:%08lx(%d) BSS:%08lx(%d)\n",
+ PEOptionalHeader->SizeOfCode,
+ PEOptionalHeader->SizeOfCode,
+ PEOptionalHeader->SizeOfInitializedData,
+ PEOptionalHeader->SizeOfInitializedData,
+ PEOptionalHeader->SizeOfUninitializedData,
+ PEOptionalHeader->SizeOfUninitializedData);
+ DbgPrint("Entry Point:%08lx\n", PEOptionalHeader->AddressOfEntryPoint);
+ CHECKPOINT;
+ /* Determine the size of the module */
+ DriverSize = ROUND_UP(PEOptionalHeader->SizeOfCode,
+ PEOptionalHeader->SectionAlignment) +
+ ROUND_UP(PEOptionalHeader->SizeOfInitializedData,
+ PEOptionalHeader->SectionAlignment) +
+ ROUND_UP(PEOptionalHeader->SizeOfUninitializedData,
+ PEOptionalHeader->SectionAlignment);
+ CHECKPOINT;
+ /* Allocate a virtual section for the module */
+ DriverBase = MmAllocateSection(DriverSize);
+ if (DriverBase == 0)
+ {
+ DbgPrint("Failed to allocate a virtual section for driver\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ CHECKPOINT;
+ /* Compute addresses for driver sections */
+ CodeBase = DriverBase;
+ InitializedDataBase = (PUCHAR) DriverBase +
+ (PUCHAR) ROUND_UP(PEOptionalHeader->SizeOfCode,
+ PEOptionalHeader->SectionAlignment);
+ UninitializedDataBase = (PUCHAR) InitializedDataBase +
+ (PUCHAR) ROUND_UP(PEOptionalHeader->SizeOfInitializedData,
+ PEOptionalHeader->SectionAlignment);
+
+ /* FIXME: Copy code section into virtual section */
+ memcpy(CodeBase,
+ (PVOID)(ModuleLoadBase + ???),
+ ROUND_UP(PEOptionalHeader->SizeOfCode,
+ PEOptionalHeader->FileAlignment));
+#endif
+
+ /* FIXME: Copy initialized data section into virtual section */
+ /* FIXME: Perform relocations fixups */
+ /* FIXME: compute address of entry point */
+
+ /* return InitializeLoadedDriver(EntryPoint); */
return STATUS_NOT_IMPLEMENTED;
}
return 0L;
}
-
-
-
-static NTSTATUS
-LdrProcessMZImage(HANDLE ProcessHandle,
- HANDLE FileHandle,
- PIMAGE_DOS_HEADER DosHeader)
+NTSTATUS LdrLoadLibrary(HANDLE ProcessHandle,
+ PHANDLE ModuleHandle,
+ PCHAR Name)
{
+#if 0
+ NTSTATUS Status;
+ ANSI_STRING afilename;
+ UNICODE_STRING ufilename,umodName;
+ PMODULE *Library, *Module;
+ OBJECT_ATTRIBUTES attr;
+ PWSTR Ignored;
+ char name2[512];
+
+ /* FIXME: this is broke */
+ /* FIXME: check for module already loaded */
+ /* FIXME: otherwise load module */
+ /* FIXME: we need to fix how modules are loaded so that they can
+ be shared... :( */
+
+ /* If module is already loaded, get a reference and return it */
+ strcpy(name2, "\\modules\\");
+ strcat(name2, Name);
+ RtlInitAnsiString(&afilename, name2);
+ RtlAnsiStringToUnicodeString(&umodName, &afilename, TRUE);
+ InitializeObjectAttributes(&attr, &umodName, 0, NULL, NULL);
+ Status = ObOpenObjectByName(&attr, (PVOID *) &Library, &Ignored);
+ DPRINT("LoadLibrary : Status=%x,pLibrary=%x\n",Status, Library);
+ if (!NT_SUCCESS(Status) || Library == NULL)
+ {
+ strcpy(name2, "\\??\\C:\\reactos\\system\\");
+ strcat(name2, name);
+ RtlInitAnsiString(&afilename, name2);
+ RtlAnsiStringToUnicodeString(&ufilename, &afilename, TRUE);
+ DPRINT("LoadLibrary,load %s\n", name2);
+ Library = LdrLoadImage(&ufilename);
+ /* FIXME: execute start code ? */
+ Module = ObGenericCreateObject(NULL, PROCESS_ALL_ACCESS, &attr, ObModuleType);
+ if (Module)
+ {
+ memcpy(Module, Library, PMODULE);
+ }
+ else
+ {
+ DbgPrint("library object not created\n");
+ }
+ RtlFreeUnicodeString(&ufilename);
+ Status = ObOpenObjectByName(&attr, (PVOID *)&Library, &Ignored);
+ }
+ else
+ {
+ DbgPrint("Library already loaded\n");
+ *Module = Library
+ }
+ RtlFreeUnicodeString(&umodName);
- /* FIXME: map VDM into low memory */
- /* FIXME: Build/Load image sections */
-
- return STATUS_NOT_IMPLEMENTED;
+ return STATUS_SUCCESS;
+#endif
+ UNIMPLEMENTED;
}
-static NTSTATUS
-LdrProcessPEImage(HANDLE ProcessHandle,
- HANDLE FileHandle,
- PIMAGE_DOS_HEADER DosHeader)
-{
-// PIMAGE_NT_HEADERS PEHeader;
-// PIMAGE_SECTION_HEADER Sections;
-
- // FIXME: Check architechture
- // FIXME: Build/Load image sections
- // FIXME: do relocations code sections
- // FIXME: resolve imports
- // FIXME: do fixups
-
- return STATUS_NOT_IMPLEMENTED;
-}
-/*
- * FUNCTION: Loads a PE executable into the specified process
+
+/* LdrLoadImage
+ * FUNCTION:
+ * Loads a module into the specified process
* ARGUMENTS:
- * Filename = File to load
- * ProcessHandle = handle
- * RETURNS: Status
+ * HANDLE ProcessHandle handle of the process to load the module into
+ * PHANDLE ModuleHandle handle of the loaded module
+ * PUNICODE_STRING Filename name of the module to load
+ * RETURNS:
+ * NTSTATUS
*/
NTSTATUS
-LdrLoadImage(PUNICODE_STRING Filename, HANDLE ProcessHandle)
+LdrLoadImage(HANDLE ProcessHandle,
+ PHANDLE ModuleHandle,
+ PUNICODE_STRING Filename)
{
- char BlockBuffer[512];
+#if 0
+ char BlockBuffer[1024];
NTSTATUS Status;
- ULONG SectionSize;
- HANDLE FileHandle;
- HANDLE ThreadHandle;
OBJECT_ATTRIBUTES FileObjectAttributes;
+ HANDLE FileHandle;
+ PMODULE Module;
PIMAGE_DOS_HEADER PEDosHeader;
- CONTEXT Context;
- HANDLE SectionHandle;
- PVOID BaseAddress;
/* FIXME: should DLLs be named sections? */
return Status;
}
+ /* Build a module structure for the image */
+ Module = ObGenericCreateObject(ModuleHandle,
+ PROCESS_ALL_ACCESS,
+ NULL,
+ ObModuleType);
+ if (Module == NULL)
+ {
+ ZwClose(FileHandle);
+ return Status;
+ }
+
/* Read first block of image to determine type */
- Status = ZwReadFile(FileHandle, 0, 0, 0, 0, BlockBuffer, 512, 0, 0);
+ Status = ZwReadFile(FileHandle, 0, 0, 0, 0, BlockBuffer, 1024, 0, 0);
if (!NT_SUCCESS(Status))
{
+ ObDereferenceObject(*ModuleHandle);
+ *ModuleHandle = NULL;
ZwClose(FileHandle);
+
return Status;
}
/* If MZ header exists */
PEDosHeader = (PIMAGE_DOS_HEADER) BlockBuffer;
- if (PEDosHeader->e_magic == 0x54AD && PEDosHeader->e_lfanew != 0L)
+ if (PEDosHeader->e_magic == IMAGE_DOS_MAGIC &&
+ PEDosHeader->e_lfanew != 0L &&
+ *(PULONG)((PUCHAR)BlockBuffer + PEDosHeader->e_lfanew) == IMAGE_PE_MAGIC)
{
Status = LdrProcessPEImage(ProcessHandle,
- FileHandle,
- PEDosHeader);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ ModuleHandle,
+ FileHandle);
}
else if (PEDosHeader->e_magic == 0x54AD)
{
Status = LdrProcessMZImage(ProcessHandle,
- FileHandle,
- PEDosHeader);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ ModuleHandle,
+ FileHandle);
}
else /* Assume bin format and load */
{
- FILE_STANDARD_INFORMATION FileStdInfo;
+ Status = LdrProcessBinImage(ProcessHandle,
+ ModuleHandle,
+ FileHandle);
+ }
+ /* FIXME: {else} could check for a.out, ELF, COFF, etc. images here... */
- /* Get the size of the file for the section */
- Status = ZwQueryInformationFile(FileHandle,
- NULL,
- &FileStdInfo,
- sizeof(FileStdInfo),
- FileStandardInformation);
- if (!NT_SUCCESS(Status))
+ /* FIXME: should we unconditionally dereference the module handle here? */
+ if (!NT_SUCCESS(Status))
+ {
+ ObDereferenceObject(*ModuleHandle);
+ *ModuleHandle = NULL;
+ }
+ ZwClose(FileHandle);
+
+ return Status;
+#endif
+ UNIMPLEMENTED;
+}
+
+#if 0
+static NTSTATUS
+LdrProcessMZImage(HANDLE ProcessHandle,
+ HANDLE ModuleHandle,
+ HANDLE FileHandle)
+{
+
+ /* FIXME: map VDM into low memory */
+ /* FIXME: Build/Load image sections */
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS
+LdrProcessPEImage(HANDLE ProcessHandle,
+ HANDLE ModuleHandle,
+ HANDLE FileHandle)
+{
+ int i;
+ NTSTATUS Status;
+ PVOID BaseSection;
+ PIMAGE_DOS_HEADER DosHeader;
+ PIMAGE_NT_HEADERS NTHeaders;
+ PMODULE Module;
+ LARGE_INTEGER SectionOffset;
+
+ /* Allocate memory for headers */
+ Module = HEADER_TO_BODY(ModuleHandle);
+ if (Module == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ DosHeader = (PIMAGE_DOS_HEADER)ExAllocatePool(NonPagedPool,
+ sizeof(IMAGE_DOS_HEADER) +
+ sizeof(IMAGE_NT_HEADERS));
+ if (DosHeader == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ NTHeaders = (PIMAGE_NT_HEADERS)((PUCHAR) DosHeader + sizeof(IMAGE_DOS_HEADER));
+
+ /* Read the headers into memory */
+ memset(Module, '\0', sizeof(PMODULE));
+ Status = ZwReadFile(FileHandle,
+ NULL, NULL, NULL, NULL,
+ DosHeader,
+ sizeof(IMAGE_DOS_HEADER),
+ 0, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(DosHeader);
+ return Status;
+ }
+ SET_LARGE_INTEGER_HIGH_PART(SectionOffset, 0);
+ SET_LARGE_INTEGER_LOW_PART(SectionOffset, DosHeader->e_lfanew);
+ Status = ZwReadFile(FileHandle,
+ NULL, NULL, NULL, NULL,
+ NTHeaders,
+ sizeof(IMAGE_NT_HEADERS),
+ &SectionOffset,
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(DosHeader);
+ return Status;
+ }
+
+ /* Allocate memory in process for image */
+ Module->Flags = MODULE_FLAG_PE;
+ Module->Base = (PVOID) NTHeaders->OptionalHeader.ImageBase;
+ Module->Size = NTHeaders->OptionalHeader.SizeOfImage;
+ Status = ZwAllocateVirtualMemory(ProcessHandle,
+ &Module->Base,
+ 0,
+ NULL,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(DosHeader);
+ return Status;
+ }
+
+ /* Load headers into virtual memory */
+ Status = ZwReadFile(FileHandle,
+ NULL, NULL, NULL, NULL,
+ Module->Base,
+ NTHeaders->OptionalHeader.SizeOfHeaders,
+ 0, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ ZwFreeVirtualMemory(ProcessHandle,
+ Module->Base,
+ 0,
+ MEM_RELEASE);
+ ExFreePool(DosHeader);
+ return Status;
+ }
+
+ /* Adjust module pointers into virtual memory */
+ DosHeader = (PIMAGE_DOS_HEADER) Module->Base;
+ NTHeaders = (PIMAGE_NT_HEADERS) ((PUCHAR)Module->Base +
+ DosHeader->e_lfanew);
+ Module->Image.PE.FileHeader = (PIMAGE_FILE_HEADER) ((PUCHAR)NTHeaders +
+ sizeof(DWORD));
+ Module->Image.PE.OptionalHeader = (PIMAGE_OPTIONAL_HEADER)
+ ((PUCHAR)Module->Image.PE.FileHeader + sizeof(IMAGE_FILE_HEADER));
+ Module->Image.PE.SectionList = (PCOFF_SECTION_HEADER) ((PUCHAR)NTHeaders +
+ sizeof(IMAGE_NT_HEADERS));
+
+ /* Build Image Sections */
+ /* FIXME: should probably use image directory to load sections. */
+ for (i = 0; i < Module->Image.PE.FileHeader->NumberOfSections; i++)
+ {
+ DPRINT("section %d\n", i);
+ BaseSection = (PVOID)((PCHAR) Module->Base +
+ Module->Image.PE.SectionList[i].s_vaddr);
+
+ /* Load code and initialized data sections from disk */
+ if ((Module->Image.PE.SectionList[i].s_flags & STYP_TEXT) ||
+ (Module->Image.PE.SectionList[i].s_flags & STYP_DATA))
{
- ZwClose(FileHandle);
- return Status;
+ SET_LARGE_INTEGER_HIGH_PART(SectionOffset, 0);
+ SET_LARGE_INTEGER_LOW_PART(SectionOffset,
+ Module->Image.PE.SectionList[i].s_scnptr);
+
+ /* FIXME: should probably map sections into sections */
+ Status = ZwReadFile(FileHandle,
+ NULL, NULL, NULL, NULL,
+ Module->Base + Module->Image.PE.SectionList[i].s_vaddr,
+ min(Module->Image.PE.SectionList[i].s_size,
+ Module->Image.PE.SectionList[i].s_paddr),
+ &SectionOffset, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ ZwFreeVirtualMemory(ProcessHandle,
+ Module->Base,
+ 0,
+ MEM_RELEASE);
+ ExFreePool(DosHeader);
+ return Status;
+ }
}
-
- /* Create the section for the code */
- Status = ZwCreateSection(&SectionHandle,
- SECTION_ALL_ACCESS,
- NULL,
- NULL,
- PAGE_READWRITE,
- MEM_COMMIT,
- FileHandle);
- ZwClose(FileHandle);
- if (!NT_SUCCESS(Status))
+ else if (Module->Image.PE.SectionList[i].s_flags & STYP_BSS)
{
- return Status;
+ memset((PVOID)(Module->Base +
+ Module->Image.PE.SectionList[i].s_vaddr),
+ 0,
+ Module->Image.PE.SectionList[i].s_size);
}
+ }
- /* Map a view of the section into the desired process */
- BaseAddress = (PVOID)0x10000;
- SectionSize = GET_LARGE_INTEGER_LOW_PART(FileStdInfo.AllocationSize);
- Status = ZwMapViewOfSection(SectionHandle,
- ProcessHandle,
- &BaseAddress,
- 0,
- SectionSize,
- NULL,
- &SectionSize,
- 0,
- MEM_COMMIT,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
+ /* Resolve Import Library references */
+ if (Module->Image.PE.OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
+ {
+ PIMAGE_IMPORT_MODULE_DIRECTORY ImportModuleDirectory;
+
+ /* Process each import module */
+ ImportModuleDirectory = (PIMAGE_IMPORT_MODULE_DIRECTORY)
+ ((PUCHAR)Module->Base + Module->Image.PE.OptionalHeader->
+ DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
+ while (ImportModuleDirectory->dwRVAModuleName)
{
- /* FIXME: destroy the section here */
+ PMODULE Library;
+ PVOID *LibraryExports;
+ PVOID *ImportAddressList; // was pImpAddr
+ PULONG FunctionNameList;
+ DWORD pName;
+ PWORD pHint;
+
+ /* Load the library module into the process */
+ /* FIXME: this should take a UNICODE string */
+ Status = LdrLoadLibrary(ProcessHandle,
+ &Library,
+ (PCHAR)(Module->Base +
+ ImportModuleDirectory->dwRVAModuleName));
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: Dereference all loaded modules */
+ ZwFreeVirtualMemory(ProcessHandle,
+ Module->Base,
+ 0,
+ MEM_RELEASE);
+ ExFreePool(DosHeader);
+
+ return Status;
+ }
+
+ /* Get the address of the export list for the library */
+ LibraryExports = (PVOID *)(Library->Base +
+ Library->Image.PE.OptionalHeader->
+ DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress +
+ sizeof(IMAGE_EXPORT_DIRECTORY));
+
+ /* Get the import address list */
+ ImportAddressList = (PVOID *)
+ ((PCHAR)Module->Image.PE.OptionalHeader->ImageBase +
+ ImportModuleDirectory->dwRVAFunctionAddressList);
+
+ /* Get the list of functions to import */
+ if (ImportModuleDirectory->dwRVAFunctionNameList != 0)
+ {
+ FunctionNameList = (PULONG) ((PCHAR)Module->Base +
+ ImportModuleDirectory->dwRVAFunctionNameList);
+ }
+ else
+ {
+ FunctionNameList = (PULONG) ((PCHAR)Module->Base +
+ ImportModuleDirectory->dwRVAFunctionAddressList);
+ }
- return Status;
+ /* Walk through function list and fixup addresses */
+ while(*FunctionNameList != 0L)
+ {
+ if ((*FunctionNameList) & 0x80000000) // hint
+ {
+ *ImportAddressList = LibraryExports[(*FunctionNameList) & 0x7fffffff];
+ }
+ else // hint-name
+ {
+ pName = (DWORD)((PCHAR)Module->Base + *FunctionNameList + 2);
+ pHint = (PWORD)((PCHAR)Module->Base + *FunctionNameList);
+
+ /* FIXME: verify name */
+
+ *ImportAddressList = LibraryExports[*pHint];
+ }
+
+ /* FIXME: verify value of hint */
+
+ ImportAddressList++;
+ FunctionNameList++;
+ }
+ ImportModuleDirectory++;
}
-
- /* Setup the context for the initial thread */
- memset(&Context,0,sizeof(CONTEXT));
- Context.SegSs = USER_DS;
- Context.Esp = 0x2000;
- Context.EFlags = 0x202;
- Context.SegCs = USER_CS;
- Context.Eip = 0x10000;
- Context.SegDs = USER_DS;
- Context.SegEs = USER_DS;
- Context.SegFs = USER_DS;
- Context.SegGs = USER_DS;
-
- /* Create the stack for the process */
- BaseAddress = (PVOID) 0x1000;
- SectionSize = 0x1000;
- Status = ZwAllocateVirtualMemory(ProcessHandle,
- &BaseAddress,
- 0,
- &SectionSize,
- MEM_COMMIT,
- PAGE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- /* FIXME: unmap the section here */
- /* FIXME: destroy the section here */
+ }
- return Status;
+ /* Do fixups */
+ if (Module->Base != (PVOID)Module->Image.PE.OptionalHeader->ImageBase)
+ {
+ USHORT NumberOfEntries;
+ PUSHORT pValue16;
+ ULONG RelocationRVA;
+ ULONG Delta32, Offset;
+ PULONG pValue32;
+ PRELOCATION_DIRECTORY RelocationDir;
+ PRELOCATION_ENTRY RelocationBlock;
+
+ RelocationRVA = NTHeaders->OptionalHeader.DataDirectory[
+ IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
+ if (RelocationRVA)
+ {
+ RelocationDir = (PRELOCATION_DIRECTORY)
+ ((PCHAR)Module->Base + RelocationRVA);
+ while (RelocationDir->SizeOfBlock)
+ {
+ Delta32 = (unsigned long)(Module->Base - NTHeaders->OptionalHeader.ImageBase);
+ RelocationBlock = (PRELOCATION_ENTRY)
+ (RelocationRVA + Module->Base + sizeof(RELOCATION_DIRECTORY));
+ NumberOfEntries =
+ (RelocationDir->SizeOfBlock - sizeof(RELOCATION_DIRECTORY)) /
+ sizeof(RELOCATION_ENTRY);
+ for (i = 0; i < NumberOfEntries; i++)
+ {
+ Offset = (RelocationBlock[i].TypeOffset & 0xfff) + RelocationDir->VirtualAddress;
+ switch (RelocationBlock[i].TypeOffset >> 12)
+ {
+ case TYPE_RELOC_ABSOLUTE:
+ break;
+
+ case TYPE_RELOC_HIGH:
+ pValue16 = (PUSHORT) (Module->Base + Offset);
+ *pValue16 += Delta32 >> 16;
+ break;
+
+ case TYPE_RELOC_LOW:
+ pValue16 = (PUSHORT)(Module->Base + Offset);
+ *pValue16 += Delta32 & 0xffff;
+ break;
+
+ case TYPE_RELOC_HIGHLOW:
+ pValue32 = (PULONG) (Module->Base + Offset);
+ *pValue32 += Delta32;
+ break;
+
+ case TYPE_RELOC_HIGHADJ:
+ /* FIXME: do the highadjust fixup */
+ DbgPrint("TYPE_RELOC_HIGHADJ fixup not implemented, sorry\n");
+// break;
+
+ default:
+ DbgPrint("unexpected fixup type\n");
+
+ /* FIXME: Dereference all loaded modules */
+
+ ZwFreeVirtualMemory(ProcessHandle,
+ Module->Base,
+ 0,
+ MEM_RELEASE);
+ ExFreePool(DosHeader);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ RelocationRVA += RelocationDir->SizeOfBlock;
+ RelocationDir = (PRELOCATION_DIRECTORY)((PCHAR)Module->Base +
+ RelocationRVA);
+ }
}
-
- /* Create the initial thread */
- Status = ZwCreateThread(&ThreadHandle,
- THREAD_ALL_ACCESS,
- NULL,
+ }
+
+ /* FIXME: Create the stack for the process */
+ /* FIXME: Setup the context for the initial thread */
+ /* FIXME: Create the initial thread */
+
+// fail: ZwFreeVirtualMemory(ProcessHandle, Module->ImageBase, 0, MEM_RELEASE);
+ ExFreePool(DosHeader);
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+NTSTATUS
+LdrProcessBinImage(HANDLE ProcessHandle,
+ HANDLE ModuleHandle,
+ HANDLE FileHandle)
+{
+ NTSTATUS Status;
+ FILE_STANDARD_INFORMATION FileStdInfo;
+ ULONG SectionSize;
+ HANDLE ThreadHandle;
+ CONTEXT Context;
+ HANDLE SectionHandle;
+ PVOID BaseAddress;
+
+ /* FIXME: should set module pointers */
+
+ /* Get the size of the file for the section */
+ Status = ZwQueryInformationFile(FileHandle,
+ NULL,
+ &FileStdInfo,
+ sizeof(FileStdInfo),
+ FileStandardInformation);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Create the section for the code */
+ Status = ZwCreateSection(&SectionHandle,
+ SECTION_ALL_ACCESS,
+ NULL,
+ NULL,
+ PAGE_READWRITE,
+ MEM_COMMIT,
+ FileHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ /* Map a view of the section into the desired process */
+ BaseAddress = (PVOID)0x10000;
+ SectionSize = GET_LARGE_INTEGER_LOW_PART(FileStdInfo.AllocationSize);
+ Status = ZwMapViewOfSection(SectionHandle,
ProcessHandle,
+ &BaseAddress,
+ 0,
+ SectionSize,
NULL,
- &Context,
- NULL,
- FALSE);
- if (!NT_SUCCESS(Status))
- {
- /* FIXME: destroy the stack memory block here */
- /* FIXME: unmap the section here */
- /* FIXME: destroy the section here */
+ &SectionSize,
+ 0,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: destroy the section here */
+ return Status;
+ }
+
+ /* Setup the context for the initial thread */
+ memset(&Context,0,sizeof(CONTEXT));
+ Context.SegSs = USER_DS;
+ Context.Esp = 0x2000;
+ Context.EFlags = 0x202;
+ Context.SegCs = USER_CS;
+ Context.Eip = 0x10000;
+ Context.SegDs = USER_DS;
+ Context.SegEs = USER_DS;
+ Context.SegFs = USER_DS;
+ Context.SegGs = USER_DS;
+
+ /* Create the stack for the process */
+ BaseAddress = (PVOID) 0x1000;
+ SectionSize = 0x1000;
+ Status = ZwAllocateVirtualMemory(ProcessHandle,
+ &BaseAddress,
+ 0,
+ &SectionSize,
+ MEM_COMMIT,
+ PAGE_READWRITE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: unmap the section here */
+ /* FIXME: destroy the section here */
- return Status;
- }
+ return Status;
+ }
+
+ /* Create the initial thread */
+ Status = ZwCreateThread(&ThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ ProcessHandle,
+ NULL,
+ &Context,
+ NULL,
+ FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ /* FIXME: destroy the stack memory block here */
+ /* FIXME: unmap the section here */
+ /* FIXME: destroy the section here */
+ return Status;
}
- /* FIXME: {else} could check for a.out, ELF, COFF, etc. images here... */
- return Status;
+ return STATUS_SUCCESS;
}
+#endif
objects/dbg.o: $(DBG_OBJECTS)
$(LD) -r $(DBG_OBJECTS) -o objects/dbg.o
+objects/ldr.o: $(LDR_OBJECTS)
+ $(LD) -r $(LDR_OBJECTS) -o objects/ldr.o
+
objects/nt.o: $(NT_OBJECTS)
$(LD) -r $(NT_OBJECTS) -o objects/nt.o
OBJECTS = objects/hal.o objects/ke.o objects/rtl.o objects/mm.o \
objects/io.o objects/ob.o objects/ps.o objects/ex.o \
objects/se.o objects/cm.o objects/tst.o objects/dbg.o\
- objects/nt.o objects/cc.o
-
+ objects/nt.o objects/cc.o objects/ldr.o
utils/export/export$(EXE_POSTFIX): utils/export/export.c
$(NATIVE_CC) -g utils/export/export.c -o utils/export/export$(EXE_POSTFIX)
{
for (i=0;i<=(MemoryArea->Length/PAGESIZE);i++)
{
- free_page(MmGetPhysicalAddress(MemoryArea->BaseAddress+
- (i*PAGESIZE)).LowPart,1);
+ free_page(GET_LARGE_INTEGER_LOW_PART(
+ MmGetPhysicalAddress(MemoryArea->BaseAddress + (i*PAGESIZE))),
+ 1);
}
}
{
DPRINT("Writing %x with physical address %x\n",
base+(i*PAGESIZE),mdl_pages[i]);
- set_page(base+(i*PAGESIZE),PA_READ + PA_SYSTEM,mdl_pages[i]);
+ set_page((DWORD)base+(i*PAGESIZE),PA_READ + PA_SYSTEM,mdl_pages[i]);
}
DPRINT("base %x\n",base);
Mdl->MdlFlags = Mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
for (i=0;i<(PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGESIZE);i++)
{
Address = Mdl->StartVa + (i*PAGESIZE);
- mdl_pages[i]=MmGetPhysicalAddress(Address).LowPart;
+ mdl_pages[i] = GET_LARGE_INTEGER_LOW_PART(MmGetPhysicalAddress(Address));
DPRINT("mdl_pages[i] %x\n",mdl_pages[i]);
}
}
Mdl->MdlFlags = Mdl->MdlFlags | MDL_SOURCE_IS_NONPAGED_POOL;
for (va=0; va<Mdl->Size; va++)
{
- ((PULONG)(Mdl + 1))[va] = MmGetPhysicalAddress(
- Mdl->StartVa+ (va * PAGESIZE)).LowPart;
+ ((PULONG)(Mdl + 1))[va] = GET_LARGE_INTEGER_LOW_PART(
+ MmGetPhysicalAddress(Mdl->StartVa + (va * PAGESIZE)));
}
Mdl->MappedSystemVa = Mdl->StartVa;
}
#include <ddk/ntddk.h>
#include <internal/pool.h>
-//#define NDEBUG
+#define NDEBUG
#include <internal/debug.h>
/* GLOBALS *****************************************************************/
}
else
{
- Section->MaximumSize.HighPart = 0;
- Section->MaximumSize.LowPart = 0xffffffff;
+ LARGE_INTEGER_QUAD_PART(Section->MaximumSize) = 0xffffffff;
}
Section->SectionPageProtection = SectionPageProtection;
Status = ObReferenceObjectByHandle(FileHandle,
return(Status);
}
- if ((*ViewSize) > Section->MaximumSize.LowPart)
+ if ((*ViewSize) > GET_LARGE_INTEGER_LOW_PART(Section->MaximumSize))
{
- (*ViewSize) = Section->MaximumSize.LowPart;
+ (*ViewSize) = GET_LARGE_INTEGER_LOW_PART(Section->MaximumSize);
}
MmCreateMemoryArea(UserMode,
Protect,
&Result);
Result->Data.SectionData.Section = Section;
- Result->Data.SectionData.ViewOffset = SectionOffset->LowPart;
+ Result->Data.SectionData.ViewOffset = GET_LARGE_INTEGER_LOW_PART(*SectionOffset);
DPRINT("*BaseAddress %x\n",*BaseAddress);
DPRINT("Result->Data.SectionData.Section->FileObject %x\n",
}
for (i=0;i<=(NumberOfBytes/PAGESIZE);i++)
{
- set_page(Result+(i*PAGESIZE),Attributes,PhysicalAddress.LowPart);
+ set_page(Result + (i * PAGESIZE),
+ Attributes,
+ GET_LARGE_INTEGER_LOW_PART(PhysicalAddress));
}
return((PVOID)Result);
}
DPRINT("MmSectionHandleFault(MemoryArea %x, Address %x)\n",
MemoryArea,Address);
- set_page(Address,0x7,get_free_page());
+ set_page((DWORD)Address,0x7,get_free_page());
- Offset.LowPart = (Address - MemoryArea->BaseAddress) +
+ LARGE_INTEGER_QUAD_PART(Offset) = (Address - MemoryArea->BaseAddress) +
MemoryArea->Data.SectionData.ViewOffset;
DPRINT("MemoryArea->Data.SectionData.Section->FileObject %x\n",
break;
case MEMORY_AREA_SECTION_VIEW_COMMIT:
- if (MmSectionHandleFault(MemoryArea,cr2)==STATUS_SUCCESS)
+ if (MmSectionHandleFault(MemoryArea, (PVOID)cr2)==STATUS_SUCCESS)
{
stat=1;
}
for (i=0; i<(NumberOfBytesToRead/PAGESIZE); i++)
{
- CurrentEntry = MmGetPageEntry(Process, BaseAddress + (i*PAGESIZE));
+ CurrentEntry = MmGetPageEntry(Process, (DWORD)BaseAddress + (i*PAGESIZE));
RtlCopyMemory(Buffer + (i*PAGESIZE),
(PVOID)physical_to_linear(PAGE_MASK(*CurrentEntry)),
PAGESIZE);
for (i=0; i<(NumberOfBytesToWrite/PAGESIZE); i++)
{
- CurrentEntry = MmGetPageEntry(Process, BaseAddress + (i*PAGESIZE));
+ CurrentEntry = MmGetPageEntry(Process, (DWORD)BaseAddress + (i*PAGESIZE));
RtlCopyMemory((PVOID)physical_to_linear(PAGE_MASK(*CurrentEntry)),
Buffer + (i*PAGESIZE),
PAGESIZE);
}
ObLookupObject(ObjectAttributes->RootDirectory,path,
- &hdr->Parent,&Ignored);
+ &hdr->Parent,&Ignored, 0L);
/*
* Initialize the object header
#include <internal/mm.h>
#include <internal/string.h>
-//#define NDEBUG
+#define NDEBUG
#include <internal/debug.h>
/* GLOBALS ******************************************************************/
{
DPRINT("Scheduling current thread\n");
KeQueryTickCount(&TickCount);
- CurrentThread->Tcb.LastTick = TickCount.LowPart;
+ CurrentThread->Tcb.LastTick = GET_LARGE_INTEGER_LOW_PART(TickCount);
CurrentThread->Tcb.ThreadState = THREAD_STATE_RUNNING;
KeReleaseSpinLock(&ThreadListLock,irql);
KeLowerIrql(PASSIVE_LEVEL);
Candidate->Tcb.ThreadState = THREAD_STATE_RUNNING;
KeQueryTickCount(&TickCount);
- CurrentThread->Tcb.LastTick = TickCount.LowPart;
+ CurrentThread->Tcb.LastTick = GET_LARGE_INTEGER_LOW_PART(TickCount);
CurrentThread = Candidate;
#include <internal/ctype.h>
#include <internal/string.h>
+#include <ddk/ntddk.h>
+
unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base)
{
unsigned long result = 0,value;
*str++ = ' ';
if (sign)
*str++ = sign;
- if (type & SPECIAL)
- if (base==8)
+ if (type & SPECIAL) {
+ if (base==8) {
*str++ = '0';
- else if (base==16) {
+ } else if (base==16) {
*str++ = '0';
*str++ = digits[33];
}
+ }
if (!(type & LEFT))
while (size-- > 0)
*str++ = c;
int i, base;
char * str;
const char *s;
- const short int* sw;
+ const short int *sw;
+ PUNICODE_STRING pus;
int flags; /* flags to number() */
// CHECKPOINT;
continue;
+ case 'W':
+ pus = va_arg(args, PUNICODE_STRING);
+ if (pus == NULL || pus->Length > pus->MaximumLength)
+ {
+ s = "<NULL>";
+ while ((*s) != 0)
+ {
+ *str++ = *s++;
+ }
+ }
+ else
+ {
+ for (i = 0; i < pus->Length; i++)
+ {
+ *str++ = (char)(pus->Buffer[i]);
+ }
+ }
+ continue;
+
case 's':
s = va_arg(args, char *);
if (!s)
--fmt;
continue;
}
- if (qualifier == 'l')
+ if (qualifier == 'l') {
num = va_arg(args, unsigned long);
- else if (qualifier == 'h')
- if (flags & SIGN)
+ } else if (qualifier == 'h') {
+ if (flags & SIGN) {
num = va_arg(args, short);
- else
+ } else {
num = va_arg(args, unsigned short);
- else if (flags & SIGN)
+ }
+ } else if (flags & SIGN) {
num = va_arg(args, int);
- else
+ } else {
num = va_arg(args, unsigned int);
+ }
str = number(str, num, base, field_width, precision, flags);
}
*str = '\0';
#include <internal/string.h>
#include <internal/ctype.h>
-//#define NDEBUG
+#define NDEBUG
#include <internal/debug.h>
int ShellChangeDir(char* args);
#include <internal/i386/segment.h>
#include <internal/ps.h>
-//#define NDEBUG
+#define NDEBUG
#include <internal/debug.h>
#include <in.h>
}
+#if 0
+void TstDriverLoad(void)
+{
+ NTSTATUS Status;
+ UNICODE_STRING DriverName;
+
+ INIT_UNICODE_STRING(DriverName, "C:\\reactos\\system\\keyboard.o");
+ Status = LdrLoadDriver(DriverName);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("driver load failed, status;%d(%x)\n", Status, Status);
+ }
+}
+#endif
+
void TstBegin()
{
+// TstDriverLoad();
ExExecuteShell();
// TstFileRead();
// TstGeneralWrite();
DEBUGGING_CFLAGS =
endif
-DEFINES = -DDBG -DCHECKED
+DEFINES = -DDBG -DCHECKED # -DCOMPILER_LARGE_INTEGERS
ifeq ($(WIN32_LEAN_AND_MEAN),yes)
LEAN_AND_MEAN_DEFINE = -DWIN32_LEAN_AND_MEAN