Compare commits

..

1 Commits

Author SHA1 Message Date
The ReactOS Team
6caaf63c2c This commit was manufactured by cvs2svn to create tag 'krnl0015'.
svn path=/tags/krnl0015/; revision=940
2000-01-19 07:05:04 +00:00
1627 changed files with 280052 additions and 6183 deletions

View File

@@ -1,2 +0,0 @@
To build this branch apply the patch to trunk. And replace ntoskrnl/mm, ntoskrnl/cc with the folders from here.
This branch currently applies against: 0.3.1 branch - r25940

View File

@@ -1,120 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/cc/cacheman.c
* PURPOSE: Cache manager
*
* PROGRAMMERS: David Welch (welch@cwcom.net)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
PFSN_PREFETCHER_GLOBALS CcPfGlobals;
/* FUNCTIONS *****************************************************************/
VOID
NTAPI
CcPfInitializePrefetcher(VOID)
{
/* Notify debugger */
DbgPrintEx(DPFLTR_PREFETCHER_ID,
DPFLTR_TRACE_LEVEL,
"CCPF: InitializePrefetecher()\n");
/* Setup the Prefetcher Data */
InitializeListHead(&CcPfGlobals.ActiveTraces);
InitializeListHead(&CcPfGlobals.CompletedTraces);
ExInitializeFastMutex(&CcPfGlobals.CompletedTracesLock);
/* FIXME: Setup the rest of the prefetecher */
}
BOOLEAN NTAPI
CcInitializeCacheManager (VOID)
{
CcInitView ();
return TRUE;
}
/*
* @unimplemented
*/
LARGE_INTEGER NTAPI
CcGetFlushedValidData (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
IN BOOLEAN BcbListHeld)
{
LARGE_INTEGER i;
UNIMPLEMENTED;
i.QuadPart = 0;
return i;
}
/*
* @unimplemented
*/
PVOID NTAPI
CcRemapBcb (IN PVOID Bcb)
{
UNIMPLEMENTED;
return 0;
}
/*
* @unimplemented
*/
VOID NTAPI
CcScheduleReadAhead (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID NTAPI
CcSetAdditionalCacheAttributes (IN PFILE_OBJECT FileObject,
IN BOOLEAN DisableReadAhead,
IN BOOLEAN DisableWriteBehind)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID NTAPI
CcSetBcbOwnerPointer (IN PVOID Bcb,
IN PVOID Owner)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID NTAPI
CcSetDirtyPageThreshold (IN PFILE_OBJECT FileObject,
IN ULONG DirtyPageThreshold)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID NTAPI
CcSetReadAheadGranularity (IN PFILE_OBJECT FileObject,
IN ULONG Granularity)
{
DPRINT("CcSetReadAheadGranularity(0x%p 0x%x)\n", FileObject, Granularity);
}

616
cc/copy.c
View File

@@ -1,616 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/cc/copy.c
* PURPOSE: Implements cache managers copy interface
*
* PROGRAMMERS:
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
static PFN_TYPE CcZeroPage = 0;
#define MAX_ZERO_LENGTH (256 * 1024)
#define MAX_RW_LENGTH (256 * 1024)
#if defined(__GNUC__)
/* void * alloca(size_t size); */
#elif defined(_MSC_VER)
void *_alloca (size_t size);
#else
#error Unknown compiler for alloca intrinsic stack allocation "function"
#endif
ULONG CcFastMdlReadWait;
ULONG CcFastMdlReadNotPossible;
ULONG CcFastReadNotPossible;
ULONG CcFastReadWait;
ULONG CcFastReadNoWait;
ULONG CcFastReadResourceMiss;
extern FAST_MUTEX CcCacheViewLock;
extern LIST_ENTRY CcFreeCacheViewListHead;
extern LIST_ENTRY CcInUseCacheViewListHead;
/* FUNCTIONS *****************************************************************/
NTSTATUS NTAPI MmMapViewInSystemCache (PCACHE_VIEW);
VOID NTAPI
CcInitCacheZeroPage (VOID)
{
NTSTATUS Status;
Status = MmRequestPageMemoryConsumer (MC_NPPOOL, TRUE, &CcZeroPage);
if (!NT_SUCCESS (Status))
{
DbgPrint ("Can't allocate CcZeroPage.\n");
KeBugCheck(CACHE_MANAGER);
}
Status = MiZeroPage (CcZeroPage);
if (!NT_SUCCESS (Status))
{
DbgPrint ("Can't zero out CcZeroPage.\n");
KeBugCheck(CACHE_MANAGER);
}
}
/*
* @unimplemented
*/
BOOLEAN NTAPI
CcCanIWrite (IN PFILE_OBJECT FileObject,
IN ULONG BytesToWrite,
IN BOOLEAN Wait,
IN BOOLEAN Retrying)
{
/* Our cache is always ready for writes */
return TRUE;
}
BOOLEAN NTAPI
CcCopyRead (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus)
{
ULONG Index;
PBCB Bcb;
LARGE_INTEGER Offset;
PLIST_ENTRY entry;
PCACHE_VIEW current = NULL;
ULONG CurrentLength;
NTSTATUS Status;
DPRINT ("CcCopyRead(FileObject 0x%p, FileOffset %I64x, "
"Length %d, Wait %d, Buffer 0x%p, IoStatus 0x%p)\n",
FileObject, FileOffset->QuadPart, Length, Wait, Buffer, IoStatus);
if (!Wait)
{
IoStatus->Information = 0;
IoStatus->Status = STATUS_UNSUCCESSFUL;
return FALSE;
}
IoStatus->Information = Length;
IoStatus->Status = STATUS_SUCCESS;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
if (FileOffset->QuadPart + Length > Bcb->FileSizes.FileSize.QuadPart)
{
KeBugCheck(CACHE_MANAGER);
}
if (Bcb->FileSizes.AllocationSize.QuadPart > sizeof (Bcb->CacheView) / sizeof (Bcb->CacheView[0]) * CACHE_VIEW_SIZE)
{
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
Offset = *FileOffset;
ExAcquireFastMutex (&CcCacheViewLock);
while (Length)
{
Index = Offset.QuadPart / CACHE_VIEW_SIZE;
if (Bcb->CacheView[Index] && Bcb->CacheView[Index]->Bcb == Bcb)
{
if (Bcb->CacheView[Index]->RefCount == 0)
{
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcInUseCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
}
Bcb->CacheView[Index]->RefCount++;
}
else
{
if (IsListEmpty (&CcFreeCacheViewListHead))
{
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
entry = CcFreeCacheViewListHead.Flink;
while (entry != &CcFreeCacheViewListHead)
{
current = CONTAINING_RECORD (entry, CACHE_VIEW, ListEntry);
entry = entry->Flink;
if (current->Bcb == NULL)
{
break;
}
}
if (entry == &CcFreeCacheViewListHead)
{
KeBugCheck(CACHE_MANAGER);
}
if (current->Bcb)
{
current->Bcb->CacheView[current->SectionData.ViewOffset / CACHE_VIEW_SIZE] = NULL;
}
Bcb->CacheView[Index] = current;
if (Bcb->CacheView[Index]->Bcb != NULL)
{
DPRINT1 ("%x\n", Bcb->CacheView[Index]->Bcb);
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
Bcb->CacheView[Index]->RefCount = 1;
Bcb->CacheView[Index]->Bcb = Bcb;
Bcb->CacheView[Index]->SectionData.ViewOffset = Index * CACHE_VIEW_SIZE;
Bcb->CacheView[Index]->SectionData.Section = Bcb->Section;
Bcb->CacheView[Index]->SectionData.Segment = Bcb->Section->Segment;
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcInUseCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
Status = MmMapViewInSystemCache (Bcb->CacheView[Index]);
if (!NT_SUCCESS (Status))
{
KeBugCheck(CACHE_MANAGER);
}
}
ExReleaseFastMutex (&CcCacheViewLock);
if (Offset.QuadPart % CACHE_VIEW_SIZE)
{
if (Length > CACHE_VIEW_SIZE - Offset.u.LowPart % CACHE_VIEW_SIZE)
{
CurrentLength = CACHE_VIEW_SIZE - Offset.u.LowPart % CACHE_VIEW_SIZE;
}
else
{
CurrentLength = Length;
}
memcpy (Buffer,
(PVOID) ((ULONG_PTR) Bcb->CacheView[Index]->BaseAddress + Offset.u.LowPart % CACHE_VIEW_SIZE), CurrentLength);
Buffer = (PVOID) ((ULONG_PTR) Buffer + CurrentLength);
Length -= CurrentLength;
Offset.QuadPart += CurrentLength;
}
else
{
CurrentLength = Length > CACHE_VIEW_SIZE ? CACHE_VIEW_SIZE : Length;
memcpy (Buffer, Bcb->CacheView[Index]->BaseAddress, CurrentLength);
Buffer = (PVOID) ((ULONG_PTR) Buffer + CurrentLength);
Length -= CurrentLength;
Offset.QuadPart += CurrentLength;
}
ExAcquireFastMutex (&CcCacheViewLock);
Bcb->CacheView[Index]->RefCount--;
if (Bcb->CacheView[Index]->RefCount == 0)
{
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcFreeCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
}
}
ExReleaseFastMutex (&CcCacheViewLock);
return TRUE;
}
/*
* @implemented
*/
BOOLEAN NTAPI
CcCopyWrite (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Wait,
IN PVOID Buffer)
{
ULONG Index;
PBCB Bcb;
LARGE_INTEGER Offset;
PLIST_ENTRY entry;
PCACHE_VIEW current = NULL;
ULONG CurrentLength;
NTSTATUS Status;
DPRINT ("CcCopyWrite(FileObject 0x%p, FileOffset %I64x, "
"Length %d, Wait %d, Buffer 0x%p)\n", FileObject, FileOffset->QuadPart, Length, Wait, Buffer);
if (!Wait)
{
return FALSE;
}
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
if (FileOffset->QuadPart + Length > Bcb->FileSizes.FileSize.QuadPart)
{
KeBugCheck(CACHE_MANAGER);
}
if (Bcb->FileSizes.AllocationSize.QuadPart > sizeof (Bcb->CacheView) / sizeof (Bcb->CacheView[0]) * CACHE_VIEW_SIZE)
{
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
Offset = *FileOffset;
ExAcquireFastMutex (&CcCacheViewLock);
while (Length)
{
Index = Offset.QuadPart / CACHE_VIEW_SIZE;
if (Bcb->CacheView[Index] && Bcb->CacheView[Index]->Bcb == Bcb)
{
if (Bcb->CacheView[Index]->RefCount == 0)
{
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcInUseCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
}
Bcb->CacheView[Index]->RefCount++;
}
else
{
if (IsListEmpty (&CcFreeCacheViewListHead))
{
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
entry = CcFreeCacheViewListHead.Flink;
while (entry != &CcFreeCacheViewListHead)
{
current = CONTAINING_RECORD (entry, CACHE_VIEW, ListEntry);
entry = entry->Flink;
if (current->Bcb == NULL)
{
break;
}
}
if (entry == &CcFreeCacheViewListHead)
{
KeBugCheck(CACHE_MANAGER);
}
if (current->Bcb)
{
current->Bcb->CacheView[current->SectionData.ViewOffset / CACHE_VIEW_SIZE] = NULL;
}
Bcb->CacheView[Index] = current;
if (Bcb->CacheView[Index]->Bcb != NULL)
{
DPRINT1 ("%x\n", Bcb->CacheView[Index]->Bcb);
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
Bcb->CacheView[Index]->RefCount = 1;
Bcb->CacheView[Index]->Bcb = Bcb;
Bcb->CacheView[Index]->SectionData.ViewOffset = Index * CACHE_VIEW_SIZE;
Bcb->CacheView[Index]->SectionData.Section = Bcb->Section;
Bcb->CacheView[Index]->SectionData.Segment = Bcb->Section->Segment;
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcInUseCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
Status = MmMapViewInSystemCache (Bcb->CacheView[Index]);
if (!NT_SUCCESS (Status))
{
KeBugCheck(CACHE_MANAGER);
}
}
ExReleaseFastMutex (&CcCacheViewLock);
if (Offset.QuadPart % CACHE_VIEW_SIZE)
{
if (Length > CACHE_VIEW_SIZE - Offset.u.LowPart % CACHE_VIEW_SIZE)
{
CurrentLength = CACHE_VIEW_SIZE - Offset.u.LowPart % CACHE_VIEW_SIZE;
}
else
{
CurrentLength = Length;
}
memcpy ((PVOID) ((ULONG_PTR) Bcb->CacheView[Index]->BaseAddress + Offset.u.LowPart % CACHE_VIEW_SIZE),
Buffer, CurrentLength);
Buffer = (PVOID) ((ULONG_PTR) Buffer + CurrentLength);
Length -= CurrentLength;
Offset.QuadPart += CurrentLength;
}
else
{
CurrentLength = Length > CACHE_VIEW_SIZE ? CACHE_VIEW_SIZE : Length;
memcpy (Bcb->CacheView[Index]->BaseAddress, Buffer, CurrentLength);
Buffer = (PVOID) ((ULONG_PTR) Buffer + CurrentLength);
Length -= CurrentLength;
Offset.QuadPart += CurrentLength;
}
ExAcquireFastMutex (&CcCacheViewLock);
Bcb->CacheView[Index]->RefCount--;
if (Bcb->CacheView[Index]->RefCount == 0)
{
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcFreeCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
}
}
ExReleaseFastMutex (&CcCacheViewLock);
return TRUE;
}
/*
* @unimplemented
*/
VOID NTAPI
CcDeferWrite (IN PFILE_OBJECT FileObject,
IN PCC_POST_DEFERRED_WRITE PostRoutine,
IN PVOID Context1,
IN PVOID Context2,
IN ULONG BytesToWrite,
IN BOOLEAN Retrying)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID NTAPI
CcFastCopyRead (IN PFILE_OBJECT FileObject,
IN ULONG FileOffset,
IN ULONG Length,
IN ULONG PageCount,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID NTAPI
CcFastCopyWrite (IN PFILE_OBJECT FileObject,
IN ULONG FileOffset,
IN ULONG Length,
IN PVOID Buffer)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
NTSTATUS NTAPI
CcWaitForCurrentLazyWriterActivity (VOID)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
/*
* @implemented
*/
BOOLEAN NTAPI
CcZeroData (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER StartOffset,
IN PLARGE_INTEGER EndOffset,
IN BOOLEAN Wait)
{
NTSTATUS Status;
LARGE_INTEGER WriteOffset;
ULONG Length;
ULONG CurrentLength;
PMDL Mdl;
ULONG i;
IO_STATUS_BLOCK Iosb;
KEVENT Event;
LARGE_INTEGER Offset;
ULONG Index;
DPRINT ("CcZeroData(FileObject 0x%p, StartOffset %I64x, EndOffset %I64x, "
"Wait %d)\n", FileObject, StartOffset->QuadPart, EndOffset->QuadPart, Wait);
Length = EndOffset->u.LowPart - StartOffset->u.LowPart;
WriteOffset.QuadPart = StartOffset->QuadPart;
if (FileObject->SectionObjectPointer->SharedCacheMap == NULL)
{
/* File is not cached */
Mdl = alloca (MmSizeOfMdl (NULL, MAX_ZERO_LENGTH));
while (Length > 0)
{
if (Length + WriteOffset.u.LowPart % PAGE_SIZE > MAX_ZERO_LENGTH)
{
CurrentLength = MAX_ZERO_LENGTH - WriteOffset.u.LowPart % PAGE_SIZE;
}
else
{
CurrentLength = Length;
}
MmInitializeMdl (Mdl, (PVOID) WriteOffset.u.LowPart, CurrentLength);
Mdl->MdlFlags |= (MDL_PAGES_LOCKED | MDL_IO_PAGE_READ);
for (i = 0; i < ((Mdl->Size - sizeof (MDL)) / sizeof (ULONG)); i++)
{
((PPFN_TYPE) (Mdl + 1))[i] = CcZeroPage;
}
KeInitializeEvent (&Event, NotificationEvent, FALSE);
Status = IoSynchronousPageWrite (FileObject, Mdl, &WriteOffset, &Event, &Iosb);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject (&Event, Executive, KernelMode, FALSE, NULL);
Status = Iosb.Status;
}
MmUnmapLockedPages (Mdl->MappedSystemVa, Mdl);
if (!NT_SUCCESS (Status))
{
return (FALSE);
}
WriteOffset.QuadPart += CurrentLength;
Length -= CurrentLength;
}
}
else
{
/* File is cached */
PBCB Bcb;
PCACHE_VIEW current = NULL;
PLIST_ENTRY entry;
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
if (!Wait)
{
return FALSE;
}
if (EndOffset->QuadPart > Bcb->FileSizes.FileSize.QuadPart)
{
KeBugCheck(CACHE_MANAGER);
}
if (Bcb->FileSizes.AllocationSize.QuadPart > sizeof (Bcb->CacheView) / sizeof (Bcb->CacheView[0]) * CACHE_VIEW_SIZE)
{
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
Offset = *StartOffset;
Length = EndOffset->QuadPart - StartOffset->QuadPart;
ExAcquireFastMutex (&CcCacheViewLock);
while (Length)
{
Index = Offset.QuadPart / CACHE_VIEW_SIZE;
if (Bcb->CacheView[Index] && Bcb->CacheView[Index]->Bcb == Bcb)
{
if (Bcb->CacheView[Index]->RefCount == 0)
{
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcInUseCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
}
Bcb->CacheView[Index]->RefCount++;
}
else
{
if (IsListEmpty (&CcFreeCacheViewListHead))
{
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
entry = CcFreeCacheViewListHead.Flink;
while (entry != &CcFreeCacheViewListHead)
{
current = CONTAINING_RECORD (entry, CACHE_VIEW, ListEntry);
entry = entry->Flink;
if (current->Bcb == NULL)
{
break;
}
}
if (entry == &CcFreeCacheViewListHead)
{
KeBugCheck(CACHE_MANAGER);
}
Bcb->CacheView[Index] = current;
if (Bcb->CacheView[Index]->Bcb != NULL)
{
DPRINT1 ("%x\n", Bcb->CacheView[Index]->Bcb);
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
Bcb->CacheView[Index]->RefCount = 1;
Bcb->CacheView[Index]->Bcb = Bcb;
Bcb->CacheView[Index]->SectionData.ViewOffset = Index * CACHE_VIEW_SIZE;
Bcb->CacheView[Index]->SectionData.Section = Bcb->Section;
Bcb->CacheView[Index]->SectionData.Segment = Bcb->Section->Segment;
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcInUseCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
Status = MmMapViewInSystemCache (Bcb->CacheView[Index]);
if (!NT_SUCCESS (Status))
{
KeBugCheck(CACHE_MANAGER);
}
}
ExReleaseFastMutex (&CcCacheViewLock);
if (Offset.QuadPart % CACHE_VIEW_SIZE)
{
if (Length > CACHE_VIEW_SIZE - Offset.u.LowPart % CACHE_VIEW_SIZE)
{
CurrentLength = CACHE_VIEW_SIZE - Offset.u.LowPart % CACHE_VIEW_SIZE;
}
else
{
CurrentLength = Length;
}
memset ((PVOID) ((ULONG_PTR) Bcb->CacheView[Index]->BaseAddress + Offset.u.LowPart % CACHE_VIEW_SIZE), 0,
CurrentLength);
Length -= CurrentLength;
Offset.QuadPart += CurrentLength;
}
else
{
CurrentLength = Length > CACHE_VIEW_SIZE ? CACHE_VIEW_SIZE : Length;
memset (Bcb->CacheView[Index]->BaseAddress, 0, CurrentLength);
Length -= CurrentLength;
Offset.QuadPart += CurrentLength;
}
ExAcquireFastMutex (&CcCacheViewLock);
Bcb->CacheView[Index]->RefCount--;
if (Bcb->CacheView[Index]->RefCount == 0)
{
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcFreeCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
}
}
ExReleaseFastMutex (&CcCacheViewLock);
}
return (TRUE);
}

189
cc/fs.c
View File

@@ -1,189 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/cc/fs.c
* PURPOSE: Implements cache managers functions useful for File Systems
*
* PROGRAMMERS: Alex Ionescu
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
#ifndef ROUND_DOWN
#define ROUND_DOWN(X,Y) ((X) & ~((Y) - 1))
#endif
/* GLOBALS *****************************************************************/
extern PCACHE_VIEW CcCacheViewArray;
extern ULONG CcCacheViewArrayCount;
extern FAST_MUTEX CcCacheViewLock;
NTSTATUS NTAPI MmUnmapViewInSystemCache (PCACHE_VIEW);
NTSTATUS NTAPI MmChangeSectionSize (PSECTION_OBJECT Section, PLARGE_INTEGER NewMaxSize);
/* FUNCTIONS *****************************************************************/
/*
* @unimplemented
*/
LARGE_INTEGER NTAPI
CcGetDirtyPages (IN PVOID LogHandle,
IN PDIRTY_PAGE_ROUTINE DirtyPageRoutine,
IN PVOID Context1,
IN PVOID Context2)
{
LARGE_INTEGER i;
UNIMPLEMENTED;
i.QuadPart = 0;
return i;
}
/*
* @implemented
*/
PFILE_OBJECT NTAPI
CcGetFileObjectFromBcb (IN PVOID Bcb)
{
PINTERNAL_BCB iBcb = (PINTERNAL_BCB) Bcb;
return iBcb->Bcb->FileObject;
}
/*
* @unimplemented
*/
LARGE_INTEGER NTAPI
CcGetLsnForFileObject (IN PFILE_OBJECT FileObject,
OUT PLARGE_INTEGER OldestLsn OPTIONAL)
{
LARGE_INTEGER i;
UNIMPLEMENTED;
i.QuadPart = 0;
return i;
}
/*
* @unimplemented
*/
BOOLEAN NTAPI
CcIsThereDirtyData (IN PVPB Vpb)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/
BOOLEAN NTAPI
CcPurgeCacheSection (IN PSECTION_OBJECT_POINTERS SectionObjectPointer,
IN PLARGE_INTEGER FileOffset OPTIONAL,
IN ULONG Length,
IN BOOLEAN UninitializeCacheMaps)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @implemented
*/
VOID NTAPI
CcSetFileSizes (IN PFILE_OBJECT FileObject,
IN PCC_FILE_SIZES FileSizes)
{
PBCB Bcb;
NTSTATUS Status;
ULONG i;
DPRINT ("CcSetFileSizes(FileObject 0x%p, FileSizes 0x%p)\n", FileObject, FileSizes);
DPRINT ("AllocationSize %d, FileSize %d, ValidDataLength %d\n",
(ULONG) FileSizes->AllocationSize.QuadPart,
(ULONG) FileSizes->FileSize.QuadPart, (ULONG) FileSizes->ValidDataLength.QuadPart);
DPRINT ("%wZ\n", &FileObject->FileName);
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
if (Bcb == NULL)
{
return;
}
DPRINT ("AllocationSize %d, FileSize %d, ValidDataLength %d\n",
(ULONG) Bcb->FileSizes.AllocationSize.QuadPart,
(ULONG) Bcb->FileSizes.FileSize.QuadPart, (ULONG) Bcb->FileSizes.ValidDataLength.QuadPart);
ExAcquireFastMutex (&CcCacheViewLock);
DPRINT ("%d\n", Bcb->FileSizes.FileSize.u.LowPart);
for (i = ROUND_DOWN (FileSizes->AllocationSize.QuadPart, CACHE_VIEW_SIZE) / CACHE_VIEW_SIZE;
i < ROUND_UP (Bcb->FileSizes.AllocationSize.QuadPart, CACHE_VIEW_SIZE) / CACHE_VIEW_SIZE; i++)
{
if (Bcb->CacheView[i] != NULL)
{
if (Bcb->CacheView[i]->Bcb != Bcb)
{
KeBugCheck(CACHE_MANAGER);
}
if (Bcb->CacheView[i]->RefCount > 0)
{
KeBugCheck(CACHE_MANAGER);
}
Status = MmUnmapViewInSystemCache (Bcb->CacheView[i]);
if (!NT_SUCCESS (Status))
{
KeBugCheck(CACHE_MANAGER);
}
Bcb->CacheView[i]->RefCount = 0;
Bcb->CacheView[i]->Bcb = NULL;
Bcb->CacheView[i] = NULL;
}
}
#if 0
for (i = 0; i < CcCacheViewArrayCount; i++)
{
if (CcCacheViewArray[i].Bcb == Bcb)
{
if (PAGE_ROUND_UP (FileSizes->AllocationSize.QuadPart) <= CcCacheViewArray[i].SectionData.ViewOffset ||
(PAGE_ROUND_UP (FileSizes->AllocationSize.QuadPart) > CcCacheViewArray[i].SectionData.ViewOffset &&
PAGE_ROUND_UP (FileSizes->AllocationSize.QuadPart) <=
CcCacheViewArray[i].SectionData.ViewOffset + CACHE_VIEW_SIZE))
{
if (CcCacheViewArray[i].RefCount > 0)
{
KeBugCheck(CACHE_MANAGER);
}
Status = MmUnmapViewInSystemCache (&CcCacheViewArray[i]);
if (!NT_SUCCESS (Status))
{
KeBugCheck(CACHE_MANAGER);
}
CcCacheViewArray[i].RefCount = 0;
CcCacheViewArray[i].Bcb = NULL;
}
}
}
#endif
Status = MmChangeSectionSize ((PSECTION_OBJECT)Bcb->Section, &FileSizes->FileSize);
Bcb->FileSizes = *FileSizes;
ExReleaseFastMutex (&CcCacheViewLock);
}
/*
* @unimplemented
*/
VOID NTAPI
CcSetLogHandleForFile (IN PFILE_OBJECT FileObject,
IN PVOID LogHandle,
IN PFLUSH_TO_LSN FlushToLsnRoutine)
{
UNIMPLEMENTED;
}

169
cc/mdl.c
View File

@@ -1,169 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/cc/fs.c
* PURPOSE: Implements MDL Cache Manager Functions
*
* PROGRAMMERS: Alex Ionescu
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
VOID NTAPI
CcMdlRead (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
OUT PMDL * MdlChain,
OUT PIO_STATUS_BLOCK IoStatus)
{
UNIMPLEMENTED;
}
/*
* NAME INTERNAL
* CcMdlReadCompleteDev@8
*
* DESCRIPTION
*
* ARGUMENTS
* MdlChain
* DeviceObject
*
* RETURN VALUE
* None.
*
* NOTE
* Used by CcMdlReadComplete@8 and FsRtl
*
*/
VOID NTAPI
CcMdlReadCompleteDev (IN PMDL MdlChain,
IN PFILE_OBJECT FileObject)
{
PMDL Mdl;
/* Free MDLs */
while ((Mdl = MdlChain))
{
MdlChain = Mdl->Next;
MmUnlockPages (Mdl);
IoFreeMdl (Mdl);
}
}
/*
* NAME EXPORTED
* CcMdlReadComplete@8
*
* DESCRIPTION
*
* ARGUMENTS
*
* RETURN VALUE
* None.
*
* NOTE
* From Bo Branten's ntifs.h v13.
*
* @implemented
*/
VOID NTAPI
CcMdlReadComplete (IN PFILE_OBJECT FileObject,
IN PMDL MdlChain)
{
PDEVICE_OBJECT DeviceObject = NULL;
PFAST_IO_DISPATCH FastDispatch;
/* Get Fast Dispatch Data */
DeviceObject = IoGetRelatedDeviceObject (FileObject);
FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
/* Check if we support Fast Calls, and check this one */
if (FastDispatch && FastDispatch->MdlReadComplete)
{
/* Use the fast path */
FastDispatch->MdlReadComplete (FileObject, MdlChain, DeviceObject);
}
/* Use slow path */
CcMdlReadComplete2 (MdlChain, FileObject);
}
/*
* @implemented
*/
VOID NTAPI
CcMdlWriteComplete (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain)
{
PDEVICE_OBJECT DeviceObject = NULL;
PFAST_IO_DISPATCH FastDispatch;
/* Get Fast Dispatch Data */
DeviceObject = IoGetRelatedDeviceObject (FileObject);
FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
/* Check if we support Fast Calls, and check this one */
if (FastDispatch && FastDispatch->MdlWriteComplete)
{
/* Use the fast path */
FastDispatch->MdlWriteComplete (FileObject, FileOffset, MdlChain, DeviceObject);
}
/* Use slow path */
CcMdlWriteComplete2 (FileObject, FileOffset, MdlChain);
}
/*
* @unimplemented
*/
VOID NTAPI
CcMdlReadComplete2 (IN PMDL MemoryDescriptorList,
IN PFILE_OBJECT FileObject)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID NTAPI
CcMdlWriteComplete2 (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID NTAPI
CcMdlWriteAbort (IN PFILE_OBJECT FileObject,
IN PMDL MdlChain)
{
UNIMPLEMENTED;
}
/*
* @unimplemented
*/
VOID NTAPI
CcPrepareMdlWrite (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
OUT PMDL * MdlChain,
OUT PIO_STATUS_BLOCK IoStatus)
{
UNIMPLEMENTED;
}

313
cc/pin.c
View File

@@ -1,313 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/cc/pin.c
* PURPOSE: Implements cache managers pinning interface
*
* PROGRAMMERS:
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
extern NPAGED_LOOKASIDE_LIST iBcbLookasideList;
extern FAST_MUTEX CcCacheViewLock;
extern LIST_ENTRY CcFreeCacheViewListHead;
extern LIST_ENTRY CcInUseCacheViewListHead;
/* FUNCTIONS *****************************************************************/
NTSTATUS NTAPI MmMapViewInSystemCache (PCACHE_VIEW);
/*
* @implemented
*/
BOOLEAN NTAPI
CcMapData (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG Flags,
OUT PVOID * piBcb,
OUT PVOID * pBuffer)
{
PINTERNAL_BCB iBcb;
PBCB Bcb;
ULONG Index;
NTSTATUS Status;
PLIST_ENTRY entry;
PCACHE_VIEW current = NULL;
DPRINT ("CcMapData(FileObject 0x%p, FileOffset %I64x, Length %d,"
" pBcb 0x%p, pBuffer 0x%p)\n", FileObject, FileOffset->QuadPart, Length, piBcb, pBuffer);
ASSERT (FileObject);
ASSERT (FileObject->SectionObjectPointer);
ASSERT (FileObject->SectionObjectPointer->SharedCacheMap);
ASSERT (FileOffset);
ASSERT (piBcb);
ASSERT (pBuffer);
//ASSERT (Flags & MAP_WAIT);
if (!(Flags & MAP_WAIT))
{
DPRINT1("Reading without MAP_WAIT flag!\n");
//*piBcb = NULL;
//*pBuffer = NULL;
//return FALSE;
}
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
if (FileOffset->QuadPart + Length > Bcb->FileSizes.AllocationSize.QuadPart)
{
DPRINT ("%d %I64d %I64d\n", Length, FileOffset->QuadPart + Length, Bcb->FileSizes.AllocationSize.QuadPart);
// KEBUGCHECK(0);
}
if (FileOffset->QuadPart + Length - ROUND_DOWN (FileOffset->QuadPart, CACHE_VIEW_SIZE) > CACHE_VIEW_SIZE)
{
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
if (Bcb->FileSizes.AllocationSize.QuadPart > sizeof (Bcb->CacheView) / sizeof (Bcb->CacheView[0]) * CACHE_VIEW_SIZE)
{
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
ExAcquireFastMutex (&CcCacheViewLock);
Index = FileOffset->QuadPart / CACHE_VIEW_SIZE;
if (Bcb->CacheView[Index] && Bcb->CacheView[Index]->Bcb == Bcb)
{
if (Bcb->CacheView[Index]->RefCount == 0)
{
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcInUseCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
}
Bcb->CacheView[Index]->RefCount++;
}
else
{
if (IsListEmpty (&CcFreeCacheViewListHead))
{
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
entry = CcFreeCacheViewListHead.Flink;
while (entry != &CcFreeCacheViewListHead)
{
current = CONTAINING_RECORD (entry, CACHE_VIEW, ListEntry);
entry = entry->Flink;
if (current->Bcb == NULL)
{
break;
}
}
if (entry == &CcFreeCacheViewListHead)
{
KeBugCheck(CACHE_MANAGER);
}
Bcb->CacheView[Index] = current;
if (Bcb->CacheView[Index]->Bcb != NULL)
{
DPRINT1 ("%x\n", Bcb->CacheView[Index]->Bcb);
/* not implemented */
KeBugCheck(CACHE_MANAGER);
}
Bcb->CacheView[Index]->RefCount = 1;
Bcb->CacheView[Index]->Bcb = Bcb;
Bcb->CacheView[Index]->SectionData.ViewOffset = Index * CACHE_VIEW_SIZE;
Bcb->CacheView[Index]->SectionData.Section = Bcb->Section;
Bcb->CacheView[Index]->SectionData.Segment = Bcb->Section->Segment;
RemoveEntryList (&Bcb->CacheView[Index]->ListEntry);
InsertHeadList (&CcInUseCacheViewListHead, &Bcb->CacheView[Index]->ListEntry);
Status = MmMapViewInSystemCache (Bcb->CacheView[Index]);
if (!NT_SUCCESS (Status))
{
KeBugCheck(CACHE_MANAGER);
}
}
ExReleaseFastMutex (&CcCacheViewLock);
iBcb = ExAllocateFromNPagedLookasideList (&iBcbLookasideList);
if (iBcb == NULL)
{
KeBugCheck(CACHE_MANAGER);
}
memset (iBcb, 0, sizeof (INTERNAL_BCB));
iBcb->Bcb = Bcb;
iBcb->Index = Index;
*piBcb = iBcb;
*pBuffer = (PVOID) ((ULONG_PTR) Bcb->CacheView[Index]->BaseAddress +
(ULONG_PTR) (FileOffset->QuadPart - Bcb->CacheView[Index]->SectionData.ViewOffset));
DPRINT ("CcMapData() done\n");
return TRUE;
}
/*
* @unimplemented
*/
BOOLEAN NTAPI
CcPinMappedData (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG Flags,
OUT PVOID * Bcb)
{
/* no-op for current implementation. */
return TRUE;
}
/*
* @unimplemented
*/
BOOLEAN NTAPI
CcPinRead (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN ULONG Flags,
OUT PVOID * Bcb,
OUT PVOID * Buffer)
{
if (CcMapData (FileObject, FileOffset, Length, Flags, Bcb, Buffer))
{
if (CcPinMappedData (FileObject, FileOffset, Length, Flags, Bcb))
return TRUE;
else
CcUnpinData (Bcb);
}
return FALSE;
}
/*
* @unimplemented
*/
BOOLEAN NTAPI
CcPreparePinWrite (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
IN BOOLEAN Zero,
IN ULONG Flags,
OUT PVOID * Bcb,
OUT PVOID * Buffer)
{
/*
* FIXME: This is function is similar to CcPinRead, but doesn't
* read the data if they're not present. Instead it should just
* prepare the cache segments and zero them out if Zero == TRUE.
*
* For now calling CcPinRead is better than returning error or
* just having UNIMPLEMENTED here.
*/
return CcPinRead (FileObject, FileOffset, Length, Flags, Bcb, Buffer);
}
/*
* @implemented
*/
VOID NTAPI
CcSetDirtyPinnedData (IN PVOID Bcb,
IN PLARGE_INTEGER Lsn)
{
// PINTERNAL_BCB iBcb = Bcb;
// iBcb->Dirty = TRUE;
// UNIMPLEMENTED;
}
/*
* @implemented
*/
VOID NTAPI
CcUnpinData (IN PVOID _iBcb)
{
PINTERNAL_BCB iBcb = _iBcb;
DPRINT ("CcUnpinData(%x)\n", _iBcb);
ExAcquireFastMutex (&CcCacheViewLock);
iBcb->Bcb->CacheView[iBcb->Index]->RefCount--;
if (iBcb->Bcb->CacheView[iBcb->Index]->RefCount == 0)
{
RemoveEntryList (&iBcb->Bcb->CacheView[iBcb->Index]->ListEntry);
InsertHeadList (&CcFreeCacheViewListHead, &iBcb->Bcb->CacheView[iBcb->Index]->ListEntry);
}
ExReleaseFastMutex (&CcCacheViewLock);
ExFreeToNPagedLookasideList (&iBcbLookasideList, iBcb);
DPRINT ("CcUnpinData done\n");
}
/*
* @unimplemented
*/
VOID NTAPI
CcUnpinDataForThread (IN PVOID Bcb,
IN ERESOURCE_THREAD ResourceThreadId)
{
UNIMPLEMENTED;
}
/*
* @implemented
*/
VOID NTAPI
CcRepinBcb (IN PVOID Bcb)
{
#if 0
PINTERNAL_BCB iBcb = Bcb;
// iBcb->RefCount++;
ExAcquireFastMutex (&CcCacheViewLock);
iBcb->Bcb->CacheView[iBcb->Index]->RefCount++;
ExReleaseFastMutex (&CcCacheViewLock);
#endif
}
/*
* @implemented
*/
VOID NTAPI
CcUnpinRepinnedBcb (IN PVOID Bcb,
IN BOOLEAN WriteThrough,
OUT PIO_STATUS_BLOCK IoStatus)
{
#if 0
PINTERNAL_BCB iBcb = Bcb;
DPRINT ("CcUnpinRepinnedBcb(%x)\n", Bcb);
ExAcquireFastMutex (&CcCacheViewLock);
iBcb->Bcb->CacheView[iBcb->Index]->RefCount--;
if (iBcb->Bcb->CacheView[iBcb->Index]->RefCount == 0)
{
RemoveEntryList (&iBcb->Bcb->CacheView[iBcb->Index]->ListEntry);
InsertHeadList (&CcFreeCacheViewListHead, &iBcb->Bcb->CacheView[iBcb->Index]->ListEntry);
}
ExReleaseFastMutex (&CcCacheViewLock);
ExFreeToNPagedLookasideList (&iBcbLookasideList, iBcb);
#endif
IoStatus->Status = STATUS_SUCCESS;
DPRINT ("CcUnpinRepinnedBcb done\n");
}

287
cc/view.c
View File

@@ -1,287 +0,0 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/cc/view.c
* PURPOSE: Cache manager
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
#ifdef ROUND_UP
#undef ROUND_UP
#endif
#ifdef ROUND_DOWN
#undef ROUND_DOWN
#endif
#define ROUND_UP(N, S) (((N) + (S) - 1) & ~((S) - 1))
#define ROUND_DOWN(N, S) ((N) & ~((S) - 1))
NPAGED_LOOKASIDE_LIST iBcbLookasideList;
static NPAGED_LOOKASIDE_LIST BcbLookasideList;
PVOID CcCacheViewBase;
ULONG CcCacheViewArrayCount;
PCACHE_VIEW CcCacheViewArray;
FAST_MUTEX CcCacheViewLock;
LIST_ENTRY CcFreeCacheViewListHead;
LIST_ENTRY CcInUseCacheViewListHead;
PMEMORY_AREA CcCacheViewMemoryArea;
NTSTATUS NTAPI MmCreateDataFileSection (PSECTION_OBJECT * SectionObject,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PLARGE_INTEGER UMaximumSize,
ULONG SectionPageProtection,
ULONG AllocationAttributes,
PFILE_OBJECT FileObject,
BOOLEAN CacheManager);
NTSTATUS NTAPI MmUnmapViewInSystemCache (PCACHE_VIEW);
NTSTATUS MmFlushDataFileSection (PSECTION_OBJECT Section, PLARGE_INTEGER StartOffset, ULONG Length);
/* FUNCTIONS *****************************************************************/
/*
* @implemented
*/
VOID NTAPI
CcFlushCache (IN PSECTION_OBJECT_POINTERS SectionObjectPointers,
IN PLARGE_INTEGER FileOffset OPTIONAL,
IN ULONG Length,
OUT PIO_STATUS_BLOCK IoStatus)
{
PBCB Bcb;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT ("CcFlushCache(SectionObjectPointers 0x%p, FileOffset 0x%p, Length %d, IoStatus 0x%p)\n",
SectionObjectPointers, FileOffset, Length, IoStatus);
if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
{
Bcb = (PBCB) SectionObjectPointers->SharedCacheMap;
ASSERT (Bcb);
Status = MmFlushDataFileSection ((PSECTION_OBJECT)Bcb->Section, FileOffset, Length);
}
if (IoStatus)
{
IoStatus->Status = Status;
IoStatus->Status = STATUS_SUCCESS;
}
}
/*
* @implemented
*/
PFILE_OBJECT NTAPI
CcGetFileObjectFromSectionPtrs (IN PSECTION_OBJECT_POINTERS SectionObjectPointers)
{
PBCB Bcb;
if (SectionObjectPointers && SectionObjectPointers->SharedCacheMap)
{
Bcb = (PBCB) SectionObjectPointers->SharedCacheMap;
ASSERT (Bcb);
return Bcb->FileObject;
}
return NULL;
}
NTSTATUS
CcTrimMemory (ULONG Target, ULONG Priority, PULONG NrFreedPages)
{
DPRINT1("Trim function for cache memory is not implemented yet.\n");
(*NrFreedPages) = 0;
return STATUS_SUCCESS;
}
VOID INIT_FUNCTION NTAPI
CcInitView (VOID)
{
NTSTATUS Status;
PHYSICAL_ADDRESS BoundaryAddressMultiple;
ULONG i;
ULONG Size;
PVOID Base;
DPRINT ("CcInitView()\n");
ExInitializeFastMutex (&CcCacheViewLock);
ExInitializeNPagedLookasideList (&iBcbLookasideList, NULL, NULL, 0, sizeof (INTERNAL_BCB), TAG_IBCB, 20);
ExInitializeNPagedLookasideList (&BcbLookasideList, NULL, NULL, 0, sizeof (BCB), TAG_BCB, 20);
InitializeListHead (&CcFreeCacheViewListHead);
InitializeListHead (&CcInUseCacheViewListHead);
BoundaryAddressMultiple.QuadPart = 0LL;
Size = MmSystemRangeStart >= (PVOID) 0xC0000000 ? 0x18000000 : 0x20000000;
CcCacheViewBase = (PVOID) (0xF0000000 - Size);
MmLockAddressSpace (MmGetKernelAddressSpace ());
Status = MmCreateMemoryArea (MmGetKernelAddressSpace (),
MEMORY_AREA_CACHE_SEGMENT,
&CcCacheViewBase, Size, 0, &CcCacheViewMemoryArea, FALSE, FALSE, BoundaryAddressMultiple);
MmUnlockAddressSpace (MmGetKernelAddressSpace ());
DPRINT ("CcCacheViewBase: %x\n", CcCacheViewBase);
if (!NT_SUCCESS (Status))
{
KeBugCheck(CACHE_MANAGER);
}
CcCacheViewArray = ExAllocatePool (NonPagedPool, sizeof (CACHE_VIEW) * (Size / CACHE_VIEW_SIZE));
if (CcCacheViewArray == NULL)
{
KeBugCheck(CACHE_MANAGER);
}
Base = CcCacheViewBase;
CcCacheViewArrayCount = Size / CACHE_VIEW_SIZE;
for (i = 0; i < CcCacheViewArrayCount; i++)
{
CcCacheViewArray[i].BaseAddress = Base;
CcCacheViewArray[i].RefCount = 0;
CcCacheViewArray[i].Bcb = NULL;
CcCacheViewArray[i].SectionData.ViewOffset = 0;
InsertTailList (&CcFreeCacheViewListHead, &CcCacheViewArray[i].ListEntry);
Base = (PVOID) ((ULONG_PTR) Base + CACHE_VIEW_SIZE);
}
MmInitializeMemoryConsumer(MC_CACHE, CcTrimMemory);
CcInitCacheZeroPage ();
}
VOID NTAPI
CcInitializeCacheMap (IN PFILE_OBJECT FileObject,
IN PCC_FILE_SIZES FileSizes,
IN BOOLEAN PinAccess,
IN PCACHE_MANAGER_CALLBACKS CallBacks,
IN PVOID LazyWriterContext)
{
PBCB Bcb;
NTSTATUS Status;
DPRINT ("CcInitializeCacheMap(), %wZ\n", &FileObject->FileName);
DPRINT ("%I64x (%I64d)\n", FileSizes->FileSize.QuadPart, FileSizes->FileSize.QuadPart);
ASSERT (FileObject);
ASSERT (FileSizes);
ExAcquireFastMutex (&CcCacheViewLock);
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
if (Bcb == NULL)
{
Bcb = ExAllocateFromNPagedLookasideList (&BcbLookasideList);
if (Bcb == NULL)
{
KeBugCheck(CACHE_MANAGER);
}
memset (Bcb, 0, sizeof (BCB));
Bcb->FileObject = FileObject;
Bcb->FileSizes = *FileSizes;
Bcb->PinAccess = PinAccess;
Bcb->CallBacks = CallBacks;
Bcb->LazyWriterContext = LazyWriterContext;
Bcb->RefCount = 0;
DPRINT ("%x %x\n", FileObject, FileSizes->FileSize.QuadPart);
Status = MmCreateDataFileSection ((PSECTION_OBJECT*)&Bcb->Section,
STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_WRITE,
NULL, &Bcb->FileSizes.FileSize, PAGE_READWRITE, SEC_COMMIT, Bcb->FileObject, TRUE);
if (!NT_SUCCESS (Status))
{
DPRINT1 ("%x\n", Status);
KeBugCheck(CACHE_MANAGER);
}
FileObject->SectionObjectPointer->SharedCacheMap = Bcb;
}
if (FileObject->PrivateCacheMap == NULL)
{
FileObject->PrivateCacheMap = Bcb;
Bcb->RefCount++;
}
ExReleaseFastMutex (&CcCacheViewLock);
DPRINT ("CcInitializeCacheMap() done\n");
}
BOOLEAN NTAPI
CcUninitializeCacheMap (IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER TruncateSize OPTIONAL,
IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent OPTIONAL)
{
PBCB Bcb;
ULONG i;
NTSTATUS Status;
DPRINT ("CcUninitializeCacheMap(), %wZ\n", &FileObject->FileName);
ExAcquireFastMutex (&CcCacheViewLock);
Bcb = FileObject->SectionObjectPointer->SharedCacheMap;
if (Bcb)
{
if (FileObject->PrivateCacheMap == Bcb)
{
Bcb->RefCount--;
FileObject->PrivateCacheMap = NULL;
}
if (Bcb->RefCount == 0)
{
Bcb->RefCount++;
ExReleaseFastMutex (&CcCacheViewLock);
MmFlushDataFileSection ((PSECTION_OBJECT)Bcb->Section, NULL, 0);
ExAcquireFastMutex (&CcCacheViewLock);
Bcb->RefCount--;
if (Bcb->RefCount == 0)
{
for (i = 0; i < ROUND_UP (Bcb->FileSizes.AllocationSize.QuadPart, CACHE_VIEW_SIZE) / CACHE_VIEW_SIZE; i++)
{
if (Bcb->CacheView[i] && Bcb->CacheView[i]->Bcb == Bcb)
{
if (Bcb->CacheView[i]->RefCount > 0)
{
KeBugCheck(CACHE_MANAGER);
}
Status = MmUnmapViewInSystemCache (Bcb->CacheView[i]);
if (!NT_SUCCESS (Status))
{
KeBugCheck(CACHE_MANAGER);
}
Bcb->CacheView[i]->RefCount = 0;
Bcb->CacheView[i]->Bcb = NULL;
Bcb->CacheView[i] = NULL;
}
}
DPRINT ("%x\n", Bcb->Section);
ObDereferenceObject (Bcb->Section);
FileObject->SectionObjectPointer->SharedCacheMap = NULL;
ExFreeToNPagedLookasideList (&BcbLookasideList, Bcb);
}
}
}
DPRINT ("CcUninitializeCacheMap() done, %wZ\n", &FileObject->FileName);
ExReleaseFastMutex (&CcCacheViewLock);
return TRUE;
}
/* EOF */

View File

@@ -1,141 +0,0 @@
Index: include/reactos/exeformat.h
===================================================================
--- include/reactos/exeformat.h (revision 34037)
+++ include/reactos/exeformat.h (working copy)
@@ -35,6 +35,7 @@
typedef NTSTATUS (NTAPI * PEXEFMT_CB_READ_FILE)
(
IN PVOID File,
+ ULONG SectorSize,
IN PLARGE_INTEGER Offset,
IN ULONG Length,
OUT PVOID * Data,
Index: ntoskrnl/include/internal/mm.h
===================================================================
--- ntoskrnl/include/internal/mm.h (revision 34040)
+++ ntoskrnl/include/internal/mm.h (working copy)
@@ -187,6 +187,9 @@
ULONG Flags;
ULONG Characteristics;
BOOLEAN WriteCopy;
+ LIST_ENTRY ListEntry;
+ ULONG BytesPerSector;
+ PFILE_OBJECT FileObject;
} MM_SECTION_SEGMENT, *PMM_SECTION_SEGMENT;
typedef struct _MM_IMAGE_SECTION_OBJECT
@@ -203,6 +206,10 @@
BOOLEAN Executable;
ULONG NrSegments;
ULONG ImageSize;
+ ULONG RefCount;
+ LIST_ENTRY ListEntry;
+ PFILE_OBJECT FileObject;
+ ULONG BytesPerSector;
PMM_SECTION_SEGMENT Segments;
} MM_IMAGE_SECTION_OBJECT, *PMM_IMAGE_SECTION_OBJECT;
@@ -221,6 +228,16 @@
};
} ROS_SECTION_OBJECT, *PROS_SECTION_OBJECT;
+typedef struct
+{
+ ROS_SECTION_OBJECT* Section;
+ ULONG ViewOffset;
+ LIST_ENTRY ViewListEntry;
+ PMM_SECTION_SEGMENT Segment;
+// BOOLEAN WriteCopyView;
+ LIST_ENTRY RegionListHead;
+} SECTION_DATA, *PSECTION_DATA;
+
typedef struct _MEMORY_AREA
{
PVOID StartingAddress;
@@ -235,17 +252,10 @@
ULONG PageOpCount;
union
{
+ SECTION_DATA SectionData;
struct
{
- ROS_SECTION_OBJECT* Section;
- ULONG ViewOffset;
- PMM_SECTION_SEGMENT Segment;
- BOOLEAN WriteCopyView;
LIST_ENTRY RegionListHead;
- } SectionData;
- struct
- {
- LIST_ENTRY RegionListHead;
} VirtualMemoryData;
} Data;
} MEMORY_AREA, *PMEMORY_AREA;
Index: ntoskrnl/include/internal/cc.h
===================================================================
--- ntoskrnl/include/internal/cc.h (revision 34040)
+++ ntoskrnl/include/internal/cc.h (working copy)
@@ -102,19 +102,29 @@
LONG ActivePrefetches;
} PFSN_PREFETCHER_GLOBALS, *PPFSN_PREFETCHER_GLOBALS;
+#define CACHE_VIEW_SIZE (128 * 1024) // 128kB
+
+struct _BCB;
+
+typedef struct
+{
+ SECTION_DATA SectionData;
+ PVOID BaseAddress;
+ ULONG RefCount;
+ struct _BCB* Bcb;
+ LIST_ENTRY ListEntry;
+} CACHE_VIEW, *PCACHE_VIEW;
+
typedef struct _BCB
{
- LIST_ENTRY BcbSegmentListHead;
- LIST_ENTRY BcbRemoveListEntry;
- BOOLEAN RemoveOnClose;
- ULONG TimeStamp;
PFILE_OBJECT FileObject;
- ULONG CacheSegmentSize;
- LARGE_INTEGER AllocationSize;
- LARGE_INTEGER FileSize;
- PCACHE_MANAGER_CALLBACKS Callbacks;
- PVOID LazyWriteContext;
- KSPIN_LOCK BcbLock;
+ CC_FILE_SIZES FileSizes;
+ BOOLEAN PinAccess;
+ PCACHE_MANAGER_CALLBACKS CallBacks;
+ PVOID LazyWriterContext;
+ PCACHE_VIEW CacheView[2048];
+ PVOID LargeCacheView;
+ PROS_SECTION_OBJECT Section;
ULONG RefCount;
#if defined(DBG) || defined(KDBG)
BOOLEAN Trace; /* enable extra trace output for this BCB and it's cache segments */
@@ -159,8 +169,8 @@
typedef struct _INTERNAL_BCB
{
PUBLIC_BCB PFCB;
- PCACHE_SEGMENT CacheSegment;
- BOOLEAN Dirty;
+ PBCB Bcb;
+ ULONG Index;
CSHORT RefCount; /* (At offset 0x34 on WinNT4) */
} INTERNAL_BCB, *PINTERNAL_BCB;
Index: drivers/filesystems/fastfat/vfat.h
===================================================================
--- drivers/filesystems/fastfat/vfat.h (revision 34037)
+++ drivers/filesystems/fastfat/vfat.h (working copy)
@@ -6,7 +6,7 @@
#ifdef __GNUC__
#include <ccros.h>
-#define USE_ROS_CC_AND_FS
+//#define USE_ROS_CC_AND_FS
#else
#define KEBUGCHECK KeBugCheck
#define KEBUGCHECKEX KeBugCheckEx

4346
mm.patch

File diff suppressed because it is too large Load Diff

2
reactos/.cvsignore Normal file
View File

@@ -0,0 +1,2 @@
dist
errors

340
reactos/COPYING Normal file
View File

@@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

14
reactos/CREDITS Normal file
View File

@@ -0,0 +1,14 @@
In no particular order
Rex Jolliff (rex@lvcablemodem.com)
Boudewijn Dekker (ariadne@xs4all.nl)
Eric Kohl (ekohl@abo.rhein-zeitung.de)
Emanuele Aliberti (ea@iol.it)
David Welch (welch@cwcom.net)
Iwan Fatahi (i_fatahi@hotmail.com)
Robert Bergkvist (fragdance@hotmail.com)
Victor Kirhenshtein (sauros@iname.com)
Jason Filby (jasonfilby@yahoo.com)
Brian Palmer (brianp@sginet.com)
Phillip Susi (phreak@iag.net)
Paolo Pantaleo (paolopan@freemail.it)

12
reactos/ChangeLog Normal file
View File

@@ -0,0 +1,12 @@
9/6/99: Implemented ZwOpenProcess
Partially implemented killing other threads (possible memory
leaks)
Made a start on a proper implemention of APCs (based on
article in NT insider)
8/12/98: Corrected bug in shell (Read two keypresses and assumed they
where the key going up and down respectively)
Corrected race in dpc handling
Took out cleanup sections in ZwReadFile (now handled by the APC)
Disabled broken code in kernel32

31
reactos/INSTALL Normal file
View File

@@ -0,0 +1,31 @@
1. Build environment
To build the system you need either mingw32 installed on Windows or a
mingw32 cross compiler running on unix.
2. Building
To build from Windows run make. To build from unix, edit rules.mak and change
the PREFIX variable to the correct value for your cross-compiler, then run
'make'.
3. Installation
Installation isn't yet automated, sorry. The system can only be installed on
the first partition which must be formatted for DOS. Set up a directory
structure like the following
make directories C:\reactos,C:\reactos\system,C:\reactos\system\drivers
Copy apps/shell/shell.exe to C:\reactos\system32
Copy subsys/smss/smss.exe to C:\reactos\system32
Copy services/dd/keyboard/keyboard.sys to C:\reactos\system32\drivers
Copy services/dd/blue/blue.sys to C:\reactos\system32\drivers
Copy lib/ntdll/ntdll.dll to C:\reactos\system32
Copy lib/kernel32/kernel32.dll to C:\reactos\system32
Copy lib/crtdll/crtdll.dll to C:\reactos\system32
The system can only be started from DOS. Copy the following files,
services/dd/ide/ide.sys, services/fs/vfat/vfatfsd.sys and
loaders/dos/loadros.com, to a suitable directory. The system can then be
booted with the command 'loadros.com ide.sys vfatfsd.sys'.

280
reactos/Makefile Normal file
View File

@@ -0,0 +1,280 @@
#
# Global makefile
#
#
# Select your host
#
#HOST = mingw32-linux
#HOST = djgpp-msdos
#HOST = mingw32-windows
include rules.mak
#
# Required to run the system
#
COMPONENTS = iface_native ntoskrnl
DLLS = ntdll kernel32 crtdll advapi32 fmifs gdi32
#DLLS = mingw32 user32
SUBSYS = smss win32k
#SUBSYS = csrss
#
# Select the server(s) you want to build
#
SERVERS = win32
# SERVERS = posix linux os2
#
# Select the loader(s) you want to build
#
LOADERS = dos
# LOADERS = boot
#
# Select the device drivers and filesystems you want
#
DEVICE_DRIVERS = blue ide keyboard null parallel serial
# DEVICE_DRIVERS = beep event floppy ide_test mouse sound test test1
FS_DRIVERS = vfat
# FS_DRIVERS = minix ext2 template
KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS)
APPS = args hello shell test cat bench apc shm lpc thread event
all: buildno $(COMPONENTS) $(DLLS) $(SUBSYS) $(LOADERS) $(KERNEL_SERVICES) $(APPS)
.PHONY: all
clean: buildno_clean $(COMPONENTS:%=%_clean) $(DLLS:%=%_clean) $(LOADERS:%=%_clean) \
$(KERNEL_SERVICES:%=%_clean) $(SUBSYS:%=%_clean) $(APPS:%=%_clean)
.PHONY: clean
floppy: make_floppy_dirs autoexec_floppy $(COMPONENTS:%=%_floppy) \
$(DLLS:%=%_floppy) $(LOADERS:%=%_floppy) \
$(KERNEL_SERVICES:%=%_floppy) $(SUBSYS:%=%_floppy) \
$(APPS:%=%_floppy)
dist: clean_dist_dir make_dist_dirs $(COMPONENTS:%=%_dist) $(DLLS:%=%_dist) \
$(LOADERS:%=%_dist) $(KERNEL_SERVICES:%=%_dist) $(SUBSYS:%=%_dist) \
$(APPS:%=%_dist)
#
# Build number generator
#
buildno: include/reactos/version.h
make -C apps/buildno
buildno_clean:
make -C apps/buildno clean
buildno_floppy:
buildno_dist:
.PHONY: buildno buildno_clean buildno_floppy buildno_dist
#
# Applications
#
$(APPS): %:
make -C apps/$*
$(APPS:%=%_clean): %_clean:
make -C apps/$* clean
$(APPS:%=%_floppy): %_floppy:
make -C apps/$* floppy
$(APPS:%=%_dist): %_dist:
make -C apps/$* dist
.PHONY: $(APPS) $(APPS:%=%_clean) $(APPS:%=%_floppy) $(APPS:%=%_dist)
#
# Interfaces
#
iface_native:
make -C iface/native
iface_native_clean:
make -C iface/native clean
iface_native_floppy:
iface_native_dist:
.PHONY: iface_native iface_native_clean iface_native_floppy \
iface_native_dist
#
# Device driver rules
#
$(DEVICE_DRIVERS): %:
make -C services/dd/$*
$(DEVICE_DRIVERS:%=%_clean): %_clean:
make -C services/dd/$* clean
$(DEVICE_DRIVERS:%=%_floppy): %_floppy:
make -C services/dd/$* floppy
$(DEVICE_DRIVERS:%=%_dist): %_dist:
make -C services/dd/$* dist
.PHONY: $(DEVICE_DRIVERS) $(DEVICE_DRIVERS:%=%_clean) \
$(DEVICE_DRIVERS:%=%_floppy) $(DEVICE_DRIVERS:%=%_dist)
$(FS_DRIVERS): %:
make -C services/fs/$*
$(FS_DRIVERS:%=%_clean): %_clean:
make -C services/fs/$* clean
$(FS_DRIVERS:%=%_floppy): %_floppy:
make -C services/fs/$* floppy
$(FS_DRIVERS:%=%_dist): %_dist:
make -C services/fs/$* dist
.PHONY: $(FS_DRIVERS) $(FS_DRIVERS:%=%_clean) $(FS_DRIVERS:%=%_floppy) \
$(FS_DRIVERS:%=%_dist)
#
# Kernel loaders
#
$(LOADERS): %:
make -C loaders/$*
$(LOADERS:%=%_clean): %_clean:
make -C loaders/$* clean
$(LOADERS:%=%_floppy): %_floppy:
make -C loaders/$* floppy
$(LOADERS:%=%_dist): %_dist:
make -C loaders/$* dist
.PHONY: $(LOADERS) $(LOADERS:%=%_clean) $(LOADERS:%=%_floppy) \
$(LOADERS:%=%_dist)
#
# Required system components
#
ntoskrnl:
make -C ntoskrnl
ntoskrnl_clean:
make -C ntoskrnl clean
ntoskrnl_floppy:
make -C ntoskrnl floppy
ntoskrnl_dist:
make -C ntoskrnl dist
.PHONY: ntoskrnl ntoskrnl_clean ntoskrnl_floppy ntoskrnl_dist
#
# Required DLLs
#
$(DLLS): %:
make -C lib/$*
$(DLLS:%=%_clean): %_clean:
make -C lib/$* clean
$(DLLS:%=%_floppy): %_floppy:
make -C lib/$* floppy
$(DLLS:%=%_dist): %_dist:
make -C lib/$* dist
.PHONY: $(DLLS) $(DLLS:%=%_clean) $(DLLS:%=%_floppy) $(DLLS:%=%_dist)
#
# Kernel Subsystems
#
$(SUBSYS): %:
make -C subsys/$*
$(SUBSYS:%=%_clean): %_clean:
make -C subsys/$* clean
$(SUBSYS:%=%_floppy): %_floppy:
make -C subsys/$* floppy
$(SUBSYS:%=%_dist): %_dist:
make -C subsys/$* dist
.PHONY: $(SUBSYS) $(SUBSYS:%=%_clean) $(SUBSYS:%=%_floppy) \
$(SUBSYS:%=%_dist)
#
# Make an install floppy
#
install: all
./install.sh /mnt/hda1
make_floppy_dirs:
ifeq ($(DOSCLI),yes)
mkdir $(FLOPPY_DIR)\dlls
mkdir $(FLOPPY_DIR)\apps
mkdir $(FLOPPY_DIR)\drivers
mkdir $(FLOPPY_DIR)\subsys
else
mkdir $(FLOPPY_DIR)/dlls $(FLOPPY_DIR)/apps $(FLOPPY_DIR)/drivers
mkdir $(FLOPPY_DIR)/subsys
endif
.PHONY: make_floppy_dirs
autoexec_floppy: $(FLOPPY_DIR)/autoexec.bat
$(FLOPPY_DIR)/autoexec.bat: bootflop.bat
ifeq ($(DOSCLI),yes)
$(CP) bootflop.bat $(FLOPPY_DIR)\autoexec.bat
else
$(CP) bootflop.bat $(FLOPPY_DIR)/autoexec.bat
endif
#
# Make a distribution saveset
#
clean_dist_dir:
ifeq ($(DOSCLI),yes)
- $(RM) $(DIST_DIR)\dlls\*.dll
- $(RM) $(DIST_DIR)\apps\*.exe
- $(RM) $(DIST_DIR)\drivers\*.sys
- $(RM) $(DIST_DIR)\subsys\*.exe
- $(RMDIR) $(DIST_DIR)\dlls
- $(RMDIR) $(DIST_DIR)\apps
- $(RMDIR) $(DIST_DIR)\drivers
- $(RMDIR) $(DIST_DIR)\subsys
- $(RMDIR) $(DIST_DIR)
else
$(RM) -r $(DIST_DIR)
endif
make_dist_dirs:
ifeq ($(DOSCLI),yes)
mkdir $(DIST_DIR)
mkdir $(DIST_DIR)\dlls
mkdir $(DIST_DIR)\apps
mkdir $(DIST_DIR)\drivers
mkdir $(DIST_DIR)\dlls
mkdir $(DIST_DIR)\subsys
else
mkdir $(DIST_DIR) $(DIST_DIR)/dlls $(DIST_DIR)/apps $(DIST_DIR)/drivers
mkdir $(DIST_DIR)/subsys
endif
.PHONY: clean_dist_dir make_dist_dirs

15
reactos/NEWS Normal file
View File

@@ -0,0 +1,15 @@
0.0.14: Converted to PE format
All system libraries are now dlls
0.0.13: Mostly bugfixes (I think)
0.0.12: Added support for multiple processes (not really tested)
System calls
kernel32 now compiles (only as a static library)
Fixed invalid tss bug (hopefully)
Added section support
Added some of the ZwxxxVirtual calls
Added prototype caching functions (only the Minix fsd actually
uses them)
Added handle access and type checking
Prototype APC implementation (no support for user APCs)

24
reactos/README Normal file
View File

@@ -0,0 +1,24 @@
About Reactos
1. What is Reactos
A project aiming to make an approximate clone of Windows NT, compatible
with most Windows applications.
The project has a website at http://www.reactos.com/
2. Building Reactos
See the INSTALL file for more details.
3. More information
See the doc subdirectory for some sparse notes
4. Who is responsible
See the CREDITS file
5. Recent developments
See the NEWS file

View File

@@ -0,0 +1,33 @@
#include <windows.h>
extern int main(int args, char* argv[], char* environ[]);
static unsigned int _argc = 0;
static char** _argv = NULL;
static char** _environ = NULL;
int mainCRTStartup(PWSTR args)
{
int nRet;
// SetUnhandledExceptionFilter(NULL);
// _fpreset();
// __GetMainArgs(&_argc, &_argv, &_environ, 0);
nRet = main(_argc, _argv, _environ);
// _cexit();
ExitProcess(nRet);
}
int WinMainCRTStartup()
{
return mainCRTStartup(NULL);
}
void __main(void)
{
}

View File

@@ -0,0 +1,97 @@
#include <ddk/ntddk.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
HANDLE OutputHandle;
HANDLE InputHandle;
void debug_printf(char* fmt, ...)
{
va_list args;
char buffer[255];
va_start(args,fmt);
vsprintf(buffer,fmt,args);
WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
va_end(args);
}
VOID STDCALL ApcRoutine(PVOID Context,
PIO_STATUS_BLOCK IoStatus,
ULONG Reserved)
{
printf("(apc.exe) ApcRoutine(Context %x)\n", Context);
}
void main(int argc, char* argv[])
{
int i;
NTSTATUS Status;
HANDLE FileHandle;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING FileName;
IO_STATUS_BLOCK IoStatus;
CHAR Buffer[256];
HANDLE EventHandle;
AllocConsole();
InputHandle = GetStdHandle(STD_INPUT_HANDLE);
OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
printf("APC test program\n");
EventHandle = CreateEventW(NULL,
FALSE,
FALSE,
NULL);
if (EventHandle == INVALID_HANDLE_VALUE)
{
printf("Failed to create event\n");
return;
}
printf("Opening file\n");
RtlInitUnicodeString(&FileName,
L"\\C:\\a.txt");
InitializeObjectAttributes(&ObjectAttributes,
&FileName,
0,
NULL,
NULL);
printf("Creating file\n");
FileHandle = CreateFileW(L"C:\\a.txt",
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
if (FileHandle == INVALID_HANDLE_VALUE)
{
printf("Open failed\n");
return;
}
printf("Reading file\n");
Status = ZwReadFile(FileHandle,
NULL,
ApcRoutine,
0xdeadbeef,
&IoStatus,
Buffer,
256,
NULL,
NULL);
if (!NT_SUCCESS(Status))
{
printf("Read failed\n");
}
printf("Waiting\n");
WaitForSingleObjectEx(EventHandle, INFINITE, TRUE);
printf("Returned from wait\n");
ZwClose(FileHandle);
printf("Program finished\n");
for(;;);
}

View File

@@ -0,0 +1,44 @@
#
#
#
OBJECTS= ../common/crt0.o apc.o
PROGS= apc.exe
BASE_CFLAGS = -I../../include
LIBS = ../../lib/crtdll/crtdll.a ../../lib/kernel32/kernel32.a \
../../lib/ntdll/ntdll.a
all: $(PROGS)
.phony: all
clean:
- $(RM) apc.o
- $(RM) apc.exe
- $(RM) apc.sym
.phony: clean
floppy: $(PROGS:%=$(FLOPPY_DIR)/apps/%)
$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* $(FLOPPY_DIR)\apps\$*
else
$(CP) $* $(FLOPPY_DIR)/apps/$*
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%)
$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* ..\..\$(DIST_DIR)\apps\$*
else
$(CP) $* ../../$(DIST_DIR)/apps/$*
endif
apc.exe: $(OBJECTS) $(LIBS)
$(LD) $(OBJECTS) $(LIBS) -o apc.exe
$(NM) --numeric-sort apc.exe > apc.sym
include ../../rules.mak

View File

@@ -0,0 +1,39 @@
#include <ddk/ntddk.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
HANDLE OutputHandle;
HANDLE InputHandle;
void debug_printf(char* fmt, ...)
{
va_list args;
char buffer[255];
va_start(args,fmt);
vsprintf(buffer,fmt,args);
WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
va_end(args);
}
int main(int argc, char* argv[])
{
int i;
AllocConsole();
InputHandle = GetStdHandle(STD_INPUT_HANDLE);
OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
printf("GetCommandLineA() %s\n",GetCommandLineA());
debug_printf("GetCommandLineA() %s\n",GetCommandLineA());
debug_printf("argc %d\n", argc);
for (i=0; i<argc; i++)
{
debug_printf("Argv[%d]: %x\n",i,argv[i]);
debug_printf("Argv[%d]: '%s'\n",i,argv[i]);
}
return 0;
}

View File

@@ -0,0 +1,42 @@
#
#
#
OBJECTS= args.o
PROGS= args.exe
BASE_CFLAGS = -I../../include
all: $(PROGS)
.phony: all
clean:
- $(RM) args.o
- $(RM) args.exe
- $(RM) args.sym
.phony: clean
floppy: $(PROGS:%=$(FLOPPY_DIR)/apps/%)
$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* $(FLOPPY_DIR)\apps\$*
else
$(CP) $* $(FLOPPY_DIR)/apps/$*
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%)
$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* ..\..\$(DIST_DIR)\apps\$*
else
$(CP) $* ../../$(DIST_DIR)/apps/$*
endif
args.exe: $(OBJECTS)
$(CC) $(OBJECTS) -o args.exe
$(NM) --numeric-sort args.exe > args.sym
include ../../rules.mak

View File

@@ -0,0 +1,8 @@
/*
*
*/
int main(int argc, char* argv[])
{
}

View File

@@ -0,0 +1,82 @@
#include <stdio.h>
#include <windows.h>
#define NR_THREADS (0x1)
DWORD WINAPI
thread_main1(LPVOID param)
{
printf("Thread 1 running (Counter %lu)\n", (DWORD)param);
return 0;
}
DWORD WINAPI
thread_main2(LPVOID param)
{
printf("Thread 2 running (Counter %lu)\n", (DWORD)param);
return 0;
}
int main (void)
{
HANDLE hThread;
DWORD i=0;
DWORD id;
#if 1
printf("Creating %d threads...\n",NR_THREADS*2);
for (i=0;i<NR_THREADS;i++)
{
CreateThread(NULL,
0,
thread_main1,
(LPVOID)i,
0,
&id);
/* CreateThread(NULL,
0,
thread_main2,
(LPVOID)i,
0,
&id);*/
}
printf("All threads created...\n");
/*
* Waiting for threads is not implemented yet.
* If you want to see all threads running, uncomment the
* call to SuspendThread(). The test application will
* freeze after all threads are created.
*/
/* SuspendThread (GetCurrentThread()); */
#else
printf("Creating thread...\n");
hThread = CreateThread(NULL,
0,
thread_main1,
(LPVOID)i,
0,
&id);
printf("Thread created. Waiting for termination...\n");
WaitForSingleObject (hThread,
-1);
CloseHandle (hThread);
printf("Thread terminated...\n");
#endif
return 0;
}

View File

@@ -0,0 +1,41 @@
#
#
#
PROGS = bench-thread
all: $(PROGS:%=%.exe)
.phony: all
clean: $(PROGS:%=%_clean)
$(PROGS:%=%_clean): %_clean:
- $(RM) $*.o
- $(RM) $*.exe
- $(RM) $*.sym
.phony: clean
floppy: # $(PROGS:%=$(FLOPPY_DIR)/apps/%.exe)
$(PROGS:%=$(FLOPPY_DIR)/apps/%.exe): $(FLOPPY_DIR)/apps/%.exe: %.exe
ifeq ($(DOSCLI),yes)
$(CP) $*.exe $(FLOPPY_DIR)\apps\$*.exe
else
$(CP) $*.exe $(FLOPPY_DIR)/apps/$*.exe
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%.exe)
$(PROGS:%=../../$(DIST_DIR)/apps/%.exe): ../../$(DIST_DIR)/apps/%.exe: %.exe
ifeq ($(DOSCLI),yes)
$(CP) $*.exe ..\..\$(DIST_DIR)\apps\$*.exe
else
$(CP) $*.exe ../../$(DIST_DIR)/apps/$*.exe
endif
bench-thread.exe: bench-thread.c
$(CC) $(CFLAGS) bench-thread.c -lkernel32 -o bench-thread.exe
$(NM) --numeric-sort bench-thread.exe > bench-thread.sym
include ../../rules.mak

View File

@@ -0,0 +1,33 @@
#include <windows.h>
#include <stdio.h>
HANDLE events[2];
DWORD WINAPI thread( LPVOID crap )
{
SetEvent( events[0] );
if( crap )
SetEvent( events[1] );
return 1;
}
int main()
{
DWORD id, Status;
printf( "Creating events\n" );
events[0] = CreateEvent( 0, TRUE, FALSE, 0 );
events[1] = CreateEvent( 0, TRUE, FALSE, 0 );
printf( "Created events\n" );
CreateThread( 0, 0, thread, 0, 0, &id );
printf( "WaitForSingleObject %s\n", ( WaitForSingleObject( events[0], INFINITE ) == WAIT_OBJECT_0 ? "worked" : "failed" ) );
ResetEvent( events[0] );
CreateThread( 0, 0, thread, 0, 0, &id );
printf( "WaitForMultipleObjects with waitall = FALSE %s\n", ( WaitForMultipleObjects( 2, events, FALSE, INFINITE ) == WAIT_OBJECT_0 ? "worked" : "failed" ) );
ResetEvent( events[0] );
CreateThread( 0, 0, thread, (void *)1, 0, &id );
Status = WaitForMultipleObjects( 2, events, TRUE, INFINITE );
printf( "WaitForMultipleObjects with waitall = TRUE %s\n", ( Status == WAIT_OBJECT_0 || Status == WAIT_OBJECT_0 + 1 ? "worked" : "failed" ) );
ResetEvent( events[0] );
printf( "WaitForSingleObject with timeout %s\n", ( WaitForSingleObject( events[0], 100 ) == WAIT_TIMEOUT ? "worked" : "failed" ) );
return 0;
}

View File

@@ -0,0 +1,41 @@
#
#
#
PROGS = event
all: $(PROGS:%=%.exe)
.phony: all
clean: $(PROGS:%=%_clean)
$(PROGS:%=%_clean): %_clean:
- $(RM) $*.o
- $(RM) $*.exe
- $(RM) $*.sym
.phony: clean
floppy: # $(PROGS:%=$(FLOPPY_DIR)/apps/%.exe)
$(PROGS:%=$(FLOPPY_DIR)/apps/%.exe): $(FLOPPY_DIR)/apps/%.exe: %.exe
ifeq ($(DOSCLI),yes)
$(CP) $*.exe $(FLOPPY_DIR)\apps\$*.exe
else
$(CP) $*.exe $(FLOPPY_DIR)/apps/$*.exe
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%.exe)
$(PROGS:%=../../$(DIST_DIR)/apps/%.exe): ../../$(DIST_DIR)/apps/%.exe: %.exe
ifeq ($(DOSCLI),yes)
$(CP) $*.exe ..\..\$(DIST_DIR)\apps\$*.exe
else
$(CP) $*.exe ../../$(DIST_DIR)/apps/$*.exe
endif
event.exe: event.c
$(CC) $(CFLAGS) event.c -lkernel32 -o event.exe
$(NM) --numeric-sort event.exe > event.sym
include ../../rules.mak

View File

@@ -0,0 +1,8 @@
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("Hello world\n");
return(0);
}

View File

@@ -0,0 +1,39 @@
#
#
#
OBJECTS = hello.o
PROGS = hello.exe
LIBS =
CLEAN_FILES = hello.o hello.exe
all: hello.exe
clean: $(CLEAN_FILES:%=%_clean)
$(CLEAN_FILES:%=%_clean): %_clean:
- $(RM) $*
.phony: clean $(CLEAN_FILES:%=%_clean)
floppy: $(PROGS:%=$(FLOPPY_DIR)/apps/%)
$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* $(FLOPPY_DIR)\apps\$*
else
$(CP) $* $(FLOPPY_DIR)/apps/$*
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%)
$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* ..\..\$(DIST_DIR)\apps\$*
else
$(CP) $* ../../$(DIST_DIR)/apps/$*
endif
hello.exe: $(OBJECTS)
$(CC) $(OBJECTS) -o hello.exe
include ../../rules.mak

View File

@@ -0,0 +1,205 @@
/* $Id: conport.c,v 1.5 1999/07/17 23:10:12 ea Exp $
*
* reactos/apps/lpc/conport.c
*
* To be run in a real WNT 4.0 system with
* "\SmApiPort" as argument. Do not try to
* connect to "\Windows\ApiPort" since that
* reboots immeditely.
*
* Use Russinovich' HandleEx to verify
* conport.exe owns two unnamed LPC ports:
* the one created by kernel32.dll connecting
* to csrss.exe, and one connected to here.
*
* 19990627 (Emanuele Aliberti)
* Initial implementation.
* 19990704 (EA)
* Dump object's attributes moved in dumpinfo.c.
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define PROTO_LPC
#include <ddk/ntddk.h>
#include "dumpinfo.h"
#define LPC_CONNECT_FLAG1 0x00000001
#define LPC_CONNECT_FLAG2 0x00000010
#define LPC_CONNECT_FLAG3 0x00000100
#define LPC_CONNECT_FLAG4 0x00001000
#define LPC_CONNECT_FLAG5 0x00010000
NTSTATUS
(STDCALL * ConnectPort)(
OUT PHANDLE PortHandle,
IN PUNICODE_STRING PortName,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN DWORD Unknown3,
IN DWORD Unknown4,
IN DWORD Unknown5,
IN DWORD Unknown6,
IN ULONG Flags
);
NTSTATUS
(STDCALL * QueryObject)(
IN HANDLE ObjectHandle,
IN CINT ObjectInformationClass,
OUT PVOID ObjectInformation,
IN ULONG Length,
OUT PULONG ResultLength
);
NTSTATUS
(STDCALL * YieldExecution)(VOID);
#define BUF_SIZE 1024
#define MAXARG 1000000
VOID
TryConnectPort(char *port_name)
{
DWORD Status = 0;
HANDLE Port = 0;
int i;
UNICODE_STRING PortName;
OBJECT_ATTRIBUTES ObjectAttributes;
WORD Name [BUF_SIZE] = {0};
int dwx = 0;
char * port_name_save = port_name;
/*
* Convert the port's name to Unicode.
*/
for (
PortName.Length = 0;
( *port_name
&& (PortName.Length < BUF_SIZE)
);
)
{
Name[PortName.Length++] = (WORD) *port_name++;
}
Name[PortName.Length] = 0;
PortName.Length = PortName.Length * sizeof (WORD);
PortName.MaximumLength = PortName.Length + sizeof (WORD);
PortName.Buffer = (PWSTR) Name;
/*
* Prepare the port object attributes.
*/
ObjectAttributes.Length =
sizeof (OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory =
NULL;
ObjectAttributes.ObjectName =
NULL /*& PortName */;
ObjectAttributes.Attributes =
OBJ_CASE_INSENSITIVE;
ObjectAttributes.SecurityDescriptor =
NULL;
ObjectAttributes.SecurityQualityOfService =
NULL;
/*
* Try to issue a connection request.
*/
Port = 0;
Status = ConnectPort(
& Port,
& PortName,
& ObjectAttributes,
0,
0,
0,
0,
LPC_CONNECT_FLAG5
);
if (Status == STATUS_SUCCESS)
{
DumpInfo(
Name,
Status,
"connected",
Port
);
/* Hot waiting */
for (dwx=0; dwx<MAXARG; ++dwx)
{
YieldExecution();
}
if (FALSE == CloseHandle(Port))
{
printf(
"Could not close the port handle %08X.\n",
Port
);
}
return;
}
printf(
"Connection to port \"%s\" failed (Status = %08X).\n",
port_name_save,
Status
);
}
main( int argc, char * argv[] )
{
HINSTANCE ntdll;
if (argc != 2)
{
printf("WNT LPC Port Connector\n");
printf("Usage: %s [port_name]\n",argv[0]);
exit(EXIT_FAILURE);
}
printf("LoadLibrary(NTDLL)\n");
ntdll = LoadLibrary("NTDLL");
if (ntdll == NULL)
{
printf("Could not load NTDLL\n");
return EXIT_FAILURE;
}
printf("GetProcAddress(NTDLL.NtConnectPort)\n");
ConnectPort = (VOID*) GetProcAddress(
ntdll,
"NtConnectPort"
);
if (ConnectPort == NULL)
{
FreeLibrary(ntdll);
printf("Could not find NTDLL.NtConnectPort\n");
return EXIT_FAILURE;
}
printf("GetProcAddress(NTDLL.NtQueryObject)\n");
QueryObject = (VOID*) GetProcAddress(
ntdll,
"NtQueryObject"
);
if (QueryObject == NULL)
{
FreeLibrary(ntdll);
printf("Could not find NTDLL.NtQueryObject\n");
return EXIT_FAILURE;
}
printf("GetProcAddress(NTDLL.NtYieldExecution)\n");
YieldExecution = (VOID*) GetProcAddress(
ntdll,
"NtYieldExecution"
);
if (YieldExecution == NULL)
{
FreeLibrary(ntdll);
printf("Could not find NTDLL.NtYieldExecution\n");
return EXIT_FAILURE;
}
printf("TryConnectPort(%s)\n",argv[1]);
TryConnectPort(argv[1]);
printf("Done\n");
return EXIT_SUCCESS;
}
/* EOF */

View File

@@ -0,0 +1,192 @@
/* $Id: creport.c,v 1.2 1999/07/17 23:10:12 ea Exp $
*
* reactos/apps/lpc/creport.c
*
* To be run in a real WNT 4.0 system to
* create an LPC named port.
*
* Use Russinovich' HandleEx to verify
* creport.exe owns the named LPC port
* you asked to create.
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#define PROTO_LPC
#include <ddk/ntddk.h>
#include "dumpinfo.h"
#define LPC_CONNECT_FLAG1 0x00000001
#define LPC_CONNECT_FLAG2 0x00000010
#define LPC_CONNECT_FLAG3 0x00000100
#define LPC_CONNECT_FLAG4 0x00001000
#define LPC_CONNECT_FLAG5 0x00010000
NTSTATUS
(STDCALL * CreatePort)(
/*OUT PHANDLE PortHandle,*/
PVOID Buffer,
IN POBJECT_ATTRIBUTES PortAttributes OPTIONAL,
IN ACCESS_MASK DesiredAccess,
IN DWORD Unknown3,
IN ULONG Flags
);
NTSTATUS
(STDCALL * QueryObject)(
IN HANDLE ObjectHandle,
IN CINT ObjectInformationClass,
OUT PVOID ObjectInformation,
IN ULONG Length,
OUT PULONG ResultLength
);
NTSTATUS
(STDCALL * YieldExecution)(VOID);
#define BUF_SIZE 1024
#define MAXARG 5000000
VOID
TryCreatePort(char *port_name)
{
DWORD Status = 0;
HANDLE Port = 0;
int i;
UNICODE_STRING PortName;
OBJECT_ATTRIBUTES ObjectAttributes;
WORD Name [BUF_SIZE] = {0};
int dwx = 0;
char * port_name_save = port_name;
/*
* Convert the port's name to Unicode.
*/
for (
PortName.Length = 0;
( *port_name
&& (PortName.Length < BUF_SIZE)
);
)
{
Name[PortName.Length++] = (WORD) *port_name++;
}
Name[PortName.Length] = 0;
PortName.Length = PortName.Length * sizeof (WORD);
PortName.MaximumLength = PortName.Length + sizeof (WORD);
PortName.Buffer = (PWSTR) Name;
/*
* Prepare the port object attributes.
*/
ObjectAttributes.Length =
sizeof (OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory =
NULL;
ObjectAttributes.ObjectName =
& PortName;
ObjectAttributes.Attributes =
0; //OBJ_CASE_INSENSITIVE --> STATUS_INVALID_PARAMETER ==> case sensitive!;
ObjectAttributes.SecurityDescriptor =
NULL;
ObjectAttributes.SecurityQualityOfService =
NULL;
/*
* Try to issue a connection request.
*/
Port = 0;
Status = CreatePort(
& Port,
& ObjectAttributes,
0, /* ACCESS_MASK? */
0, /* Unknown3 */
LPC_CONNECT_FLAG5
);
if (Status == STATUS_SUCCESS)
{
DumpInfo(
Name,
Status,
"created",
Port
);
/* Hot waiting */
for (dwx=0; dwx<MAXARG; ++dwx)
{
YieldExecution();
}
if (FALSE == CloseHandle(Port))
{
printf(
"Could not close the port handle %08X.\n",
Port
);
}
return;
}
printf(
"Creating port \"%s\" failed (Status = %08X).\n",
port_name_save,
Status
);
}
main( int argc, char * argv[] )
{
HINSTANCE ntdll;
if (argc != 2)
{
printf("WNT LPC Port Creator\n");
printf("Usage: %s [port_name]\n",argv[0]);
exit(EXIT_FAILURE);
}
printf("LoadLibrary(NTDLL)\n");
ntdll = LoadLibrary("NTDLL");
if (ntdll == NULL)
{
printf("Could not load NTDLL\n");
return EXIT_FAILURE;
}
printf("GetProcAddress(NTDLL.NtCreatePort)\n");
CreatePort = (VOID*) GetProcAddress(
ntdll,
"NtCreatePort"
);
if (CreatePort == NULL)
{
FreeLibrary(ntdll);
printf("Could not find NTDLL.NtCreatePort\n");
return EXIT_FAILURE;
}
printf("GetProcAddress(NTDLL.NtQueryObject)\n");
QueryObject = (VOID*) GetProcAddress(
ntdll,
"NtQueryObject"
);
if (QueryObject == NULL)
{
FreeLibrary(ntdll);
printf("Could not find NTDLL.NtQueryObject\n");
return EXIT_FAILURE;
}
printf("GetProcAddress(NTDLL.NtYieldExecution)\n");
YieldExecution = (VOID*) GetProcAddress(
ntdll,
"NtYieldExecution"
);
if (YieldExecution == NULL)
{
FreeLibrary(ntdll);
printf("Could not find NTDLL.NtYieldExecution\n");
return EXIT_FAILURE;
}
printf("TryCreatePort(%s)\n",argv[1]);
TryCreatePort(argv[1]);
printf("Done\n");
return EXIT_SUCCESS;
}
/* EOF */

View File

@@ -0,0 +1,239 @@
/* $Id: dumpinfo.c,v 1.2 1999/07/17 23:10:12 ea Exp $
*
* reactos/apps/lpc/dumpinfo.c
*
* ReactOS Operating System
*
* Dump a kernel object's attributes by its handle.
*
* 19990627 (Emanuele Aliberti)
* Initial implementation.
* 19990704 (EA)
* Added code to find the basic information buffer size
* for the LPC port object.
* 19990710 (EA)
*
*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <ddk/ntddk.h>
#define BUF_SIZE 1024
#define MAX_BASIC_INFO_SIZE 512
extern
NTSTATUS
(STDCALL * QueryObject)(
IN HANDLE ObjectHandle,
IN CINT ObjectInformationClass,
OUT PVOID ObjectInformation,
IN ULONG Length,
OUT PULONG ResultLength
);
extern
NTSTATUS
(STDCALL * QueryInformationPort)(
IN HANDLE PortHandle,
IN CINT PortInformationClass, /* guess */
OUT PVOID PortInformation, /* guess */
IN ULONG PortInformationLength, /* guess */
OUT PULONG ReturnLength /* guess */
);
/*
static
VOID
DumpBuffer(
char *Name,
BYTE *buffer,
ULONG size
)
{
register ULONG i = 0;
printf("%s [%d] = ",Name,size);
for ( i = 0;
i != size;
++i
)
{
printf("%02X",buffer[i]);
}
printf("\n");
}
*/
VOID
DumpInfo (
LPCWSTR Name,
NTSTATUS Status,
LPCWSTR Comment,
HANDLE Port
)
{
BYTE ObjectInformation [BUF_SIZE] = {0};
ULONG ResultLength;
wprintf(
L"Port \"%s\" %s:\n",
Name,
Comment
);
printf("\tStatus = %08X\n",Status);
printf("\tPort = %08X\n\n",Port);
/*
* Query object information.
*/
printf("Basic Information:\n");
Status = QueryObject(
Port,
ObjectBasicInformation,
ObjectInformation,
sizeof (LPC_PORT_BASIC_INFORMATION),
& ResultLength
);
if (Status == STATUS_SUCCESS)
{
PLPC_PORT_BASIC_INFORMATION i;
i = (PLPC_PORT_BASIC_INFORMATION) ObjectInformation;
printf( "\tUnknown01 = 0x%08X\n", i->Unknown0 );
printf( "\tUnknown02 = 0x%08X\n", i->Unknown1 );
printf( "\tUnknown03 = 0x%08X\n", i->Unknown2 );
printf( "\tUnknown04 = 0x%08X\n", i->Unknown3 );
printf( "\tUnknown05 = 0x%08X\n", i->Unknown4 );
printf( "\tUnknown06 = 0x%08X\n", i->Unknown5 );
printf( "\tUnknown07 = 0x%08X\n", i->Unknown6 );
printf( "\tUnknown08 = 0x%08X\n", i->Unknown7 );
printf( "\tUnknown09 = 0x%08X\n", i->Unknown8 );
printf( "\tUnknown10 = 0x%08X\n", i->Unknown9 );
printf( "\tUnknown11 = 0x%08X\n", i->Unknown10 );
printf( "\tUnknown12 = 0x%08X\n", i->Unknown11 );
printf( "\tUnknown13 = 0x%08X\n", i->Unknown12 );
printf( "\tUnknown14 = 0x%08X\n", i->Unknown13 );
}
else
{
printf("\tStatus = %08X\n",Status);
}
printf("Type Information:\n");
Status = QueryObject(
Port,
ObjectTypeInformation,
ObjectInformation,
sizeof ObjectInformation,
& ResultLength
);
if (Status == STATUS_SUCCESS)
{
OBJECT_TYPE_INFORMATION * i;
i = (OBJECT_TYPE_INFORMATION *) ObjectInformation;
wprintf(
L"\tName: \"%s\"\n",
(i->Name.Length ? i->Name.Buffer : L"")
);
/*
FIXME: why this always raise an access violation exception?
wprintf(
L"\tType: \"%s\"\n",
(i->Type.Length ? i->Type.Buffer : L"")
);
/**/
printf(
"\tTotal Handles: %d\n",
i->TotalHandles
);
printf(
"\tReference Count: %d\n",
i->ReferenceCount
);
}
else
{
printf("\tStatus = %08X\n",Status);
}
printf("Name Information:\n");
Status = QueryObject(
Port,
ObjectNameInformation,
ObjectInformation,
sizeof ObjectInformation,
& ResultLength
);
if (Status == STATUS_SUCCESS)
{
OBJECT_NAME_INFORMATION * i;
i = (OBJECT_NAME_INFORMATION *) ObjectInformation;
wprintf(
L"\tName: \"%s\"\n",
(i->Name.Length ? i->Name.Buffer : L"")
);
}
else
{
printf("\tStatus = %08X\n",Status);
}
printf("Data Information:\n");
Status = QueryObject(
Port,
ObjectDataInformation,
ObjectInformation,
sizeof ObjectInformation,
& ResultLength
);
if (Status == STATUS_SUCCESS)
{
OBJECT_DATA_INFORMATION * i;
i = (OBJECT_DATA_INFORMATION *) ObjectInformation;
printf(
"\tInherit Handle: %s\n",
(i->bInheritHandle ? "TRUE" : "FALSE")
);
printf(
"\tProtect from Close: %s\n",
(i->bProtectFromClose ? "TRUE" : "FALSE")
);
}
else
{
printf("\tStatus = %08X\n",Status);
}
//---
printf("Port Information:\n");
/* Status = QueryInformationPort(
Port,
1, /* info class * /
ObjectInformation,
sizeof ObjectInformation,
& ResultLength
);
if (Status == STATUS_SUCCESS)
{
DWORD * i = ObjectInformation;
int j = 0;
while (j < ResultLength / sizeof (DWORD))
{
printf("\t%08X\n",i[j]);
++j;
}
}
else
{
printf("\tStatus = %08X\n",Status);
}
*/
}
/* EOF */

View File

@@ -0,0 +1,8 @@
VOID
DumpInfo (
LPCWSTR Name,
NTSTATUS Status,
LPCWSTR Comment,
HANDLE Port
);

View File

@@ -0,0 +1,62 @@
#include <ddk/ntddk.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
HANDLE OutputHandle;
HANDLE InputHandle;
void debug_printf(char* fmt, ...)
{
va_list args;
char buffer[255];
va_start(args,fmt);
vsprintf(buffer,fmt,args);
WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
va_end(args);
}
void main(int argc, char* argv[])
{
UNICODE_STRING PortName;
NTSTATUS Status;
HANDLE PortHandle;
LPCMESSAGE Request;
ULONG ConnectInfoLength;
printf("(lpcclt.exe) Lpc client\n");
RtlInitUnicodeString(&PortName, L"\\TestPort");
printf("(lpcclt.exe) Connecting to port\n");
ConnectInfoLength = 0;
Status = NtConnectPort(&PortHandle,
&PortName,
NULL,
0,
0,
0,
NULL,
&ConnectInfoLength);
if (!NT_SUCCESS(Status))
{
printf("(lpcclt.exe) Failed to connect\n");
return;
}
strcpy(Request.MessageData, GetCommandLineA());
Request.ActualMessageLength = strlen(Request.MessageData);
Request.TotalMessageLength = sizeof(LPCMESSAGE);
printf("(lpcclt.exe) Sending message\n");
Status = NtRequestPort(PortHandle, &Request);
if (!NT_SUCCESS(Status))
{
printf("(lpcclt.exe) Failed to send request\n");
return;
}
printf("(lpcclt.exe) Succeeded\n");
}

View File

@@ -0,0 +1,98 @@
#include <ddk/ntddk.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
HANDLE OutputHandle;
HANDLE InputHandle;
void debug_printf(char* fmt, ...)
{
va_list args;
char buffer[255];
va_start(args,fmt);
vsprintf(buffer,fmt,args);
WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
va_end(args);
}
void main(int argc, char* argv[])
{
UNICODE_STRING PortName;
OBJECT_ATTRIBUTES ObjectAttributes;
NTSTATUS Status;
HANDLE NamedPortHandle;
HANDLE PortHandle;
LPCMESSAGE ConnectMsg;
printf("(lpcsrv.exe) Lpc test server\n");
RtlInitUnicodeString(&PortName, L"\\TestPort");
InitializeObjectAttributes(&ObjectAttributes,
&PortName,
0,
NULL,
NULL);
printf("(lpcsrv.exe) Creating port\n");
Status = NtCreatePort(&NamedPortHandle,
&ObjectAttributes,
0,
0,
0);
if (!NT_SUCCESS(Status))
{
printf("(lpcsrv.exe) Failed to create port\n");
return;
}
printf("(lpcsrv.exe) Listening for connections\n");
Status = NtListenPort(NamedPortHandle,
&ConnectMsg);
if (!NT_SUCCESS(Status))
{
printf("(lpcsrv.exe) Failed to listen for connections\n");
return;
}
printf("(lpcsrv.exe) Accepting connections\n");
Status = NtAcceptConnectPort(&PortHandle,
NamedPortHandle,
NULL,
1,
0,
NULL);
if (!NT_SUCCESS(Status))
{
printf("(lpcsrv.exe) Failed to accept connection\n");
return;
}
printf("(lpcsrv.exe) Completing connection\n");
Status = NtCompleteConnectPort(PortHandle);
if (!NT_SUCCESS(Status))
{
printf("(lpcsrv.exe) Failed to complete connection\n");
return;
}
for(;;)
{
LPCMESSAGE Request;
Status = NtReplyWaitReceivePort(PortHandle,
0,
NULL,
&Request);
if (!NT_SUCCESS(Status))
{
printf("(lpcsrv.exe) Failed to receive request\n");
return;
}
printf("(lpcsrv.exe) Message contents are <%s>\n", Request.MessageData);
}
}

View File

@@ -0,0 +1,51 @@
#
#
#
SRV_OBJECTS= ../common/crt0.o lpcsrv.o
CLT_OBJECTS= ../common/crt0.o lpcclt.o
PROGS= lpcsrv.exe lpcclt.exe
BASE_CFLAGS = -I../../include
LIBS = ../../lib/crtdll/crtdll.a ../../lib/kernel32/kernel32.a \
../../lib/ntdll/ntdll.a
all: $(PROGS)
.phony: all
clean:
- $(RM) lpcsrv.o
- $(RM) lpcsrv.exe
- $(RM) lpcsrv.sym
.phony: clean
floppy: $(PROGS:%=$(FLOPPY_DIR)/apps/%)
$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* $(FLOPPY_DIR)\apps\$*
else
$(CP) $* $(FLOPPY_DIR)/apps/$*
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%)
$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* ..\..\$(DIST_DIR)\apps\$*
else
$(CP) $* ../../$(DIST_DIR)/apps/$*
endif
lpcsrv.exe: $(SRV_OBJECTS) $(LIBS)
$(LD) $(SRV_OBJECTS) $(LIBS) -o lpcsrv.exe
$(NM) --numeric-sort lpcsrv.exe > lpcsrv.sym
lpcclt.exe: $(CLT_OBJECTS) $(LIBS)
$(LD) $(CLT_OBJECTS) $(LIBS) -o lpcclt.exe
$(NM) --numeric-sort lpcclt.exe > lpcclt.sym
include ../../rules.mak

View File

@@ -0,0 +1,51 @@
#
#
#
SRV_OBJECTS= ../common/crt0.o shmsrv.o
CLT_OBJECTS= ../common/crt0.o shmclt.o
PROGS= shmsrv.exe shmclt.exe
BASE_CFLAGS = -I../../include
LIBS = ../../lib/crtdll/crtdll.a ../../lib/kernel32/kernel32.a \
../../lib/ntdll/ntdll.a
all: $(PROGS)
.phony: all
clean:
- $(RM) *.o
- $(RM) *.exe
- $(RM) *.sym
.phony: clean
floppy: $(PROGS:%=$(FLOPPY_DIR)/apps/%)
$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* $(FLOPPY_DIR)\apps\$*
else
$(CP) $* $(FLOPPY_DIR)/apps/$*
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%)
$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* ..\..\$(DIST_DIR)\apps\$*
else
$(CP) $* ../../$(DIST_DIR)/apps/$*
endif
shmsrv.exe: $(SRV_OBJECTS) $(LIBS)
$(LD) $(SRV_OBJECTS) $(LIBS) -o shmsrv.exe
$(NM) --numeric-sort shmsrv.exe > shmsrv.sym
shmclt.exe: $(CLT_OBJECTS) $(LIBS)
$(LD) $(CLT_OBJECTS) $(LIBS) -o shmclt.exe
$(NM) --numeric-sort shmsrv.exe > shmclt.sym
include ../../rules.mak

View File

@@ -0,0 +1,60 @@
#include <ddk/ntddk.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
HANDLE OutputHandle;
HANDLE InputHandle;
void debug_printf(char* fmt, ...)
{
va_list args;
char buffer[255];
va_start(args,fmt);
vsprintf(buffer,fmt,args);
WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
va_end(args);
}
int
main(int argc, char* argv[])
{
HANDLE Section;
PVOID BaseAddress;
char buffer[256];
printf("Shm test server\n");
Section = OpenFileMappingW (
// PAGE_EXECUTE_READWRITE, invalid parameter
FILE_MAP_WRITE,
FALSE,
L"TestSection"
);
if (Section == NULL)
{
printf("Failed to open section (err=%d)", GetLastError());
return 1;
}
BaseAddress = MapViewOfFile(Section,
FILE_MAP_ALL_ACCESS,
0,
0,
8192);
if (BaseAddress == NULL)
{
printf("Failed to map section (err=%d)\n", GetLastError());
return 1;
}
printf("BaseAddress %x\n", (UINT) BaseAddress);
printf("Copying from section\n");
strcpy(buffer, BaseAddress);
printf("Copyed <%s>\n", buffer);
// for(;;);
return 0;
}

View File

@@ -0,0 +1,52 @@
/* $Id: shmsrv.c,v 1.3 1999/12/30 01:51:36 dwelch Exp $
*
* FILE : reactos/apps/shm/shmsrv.c
* AUTHOR: David Welch
*/
#include <ddk/ntddk.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
HANDLE Section;
PVOID BaseAddress;
printf("Shm test server\n");
Section = CreateFileMappingW (
(HANDLE) 0xFFFFFFFF,
NULL,
PAGE_READWRITE,
0,
8192,
L"TestSection"
);
if (Section == NULL)
{
printf("Failed to create section (err=%d)", GetLastError());
return 1;
}
printf("Mapping view of section\n");
BaseAddress = MapViewOfFile(Section,
FILE_MAP_ALL_ACCESS,
0,
0,
8192);
printf("BaseAddress %x\n", (UINT) BaseAddress);
if (BaseAddress == NULL)
{
printf("Failed to map section\n");
}
printf("Copying to section\n");
printf("Copying %s\n", GetCommandLineA());
strcpy(BaseAddress, GetCommandLineA());
for(;;);
return 0;
}

View File

@@ -0,0 +1,11 @@
#include <stdio.h>
int
main (void)
{
int i;
puts ("This should print \"wow = I\" for I from 0 to 39 inclusive.");
for (i = 0; i < 40; i++)
printf ("%s = %d\n", "wow", i);
return 0;
}

View File

@@ -0,0 +1,53 @@
#include <stdio.h>
#include <string.h>
int
main (void)
{
FILE *f;
int i;
const char filename[] = "/tmp/bug3.test";
f = fopen(filename, "w+");
for (i=0; i<9000; i++)
putc ('x', f);
fseek (f, 8180L, 0);
fwrite ("Where does this text go?", 1, 24, f);
fflush (f);
rewind (f);
for (i=0; i<9000; i++)
{
int j;
if ((j = getc(f)) != 'x')
{
if (i != 8180)
{
printf ("Test FAILED!");
return 1;
}
else
{
char buf[25];
buf[0] = j;
fread (buf + 1, 1, 23, f);
buf[24] = '\0';
if (strcmp (buf, "Where does this text go?") != 0)
{
printf ("%s\nTest FAILED!\n", buf);
return 1;
}
i += 23;
}
}
}
fclose(f);
remove(filename);
puts ("Test succeeded.");
return 0;
}

View File

@@ -0,0 +1,74 @@
#
#
#
PROGS= test-stdio tst-printf tstdiomisc bug2 bug3 \
temptest test-fseek test_rdwr
all: $(PROGS:%=%.exe)
.phony: all
$(PROGS:%=%_clean): %_clean:
- $(RM) $*.o
- $(RM) $*.exe
- $(RM) $*.sym
clean: $(PROGS:%=%_clean)
.phony: clean
floppy: # $(PROGS:%=$(FLOPPY_DIR)/apps/%.exe)
$(PROGS:%=$(FLOPPY_DIR)/apps/%.exe): $(FLOPPY_DIR)/apps/%.exe: %.exe
ifeq ($(DOSCLI),yes)
$(CP) $*.exe $(FLOPPY_DIR)\apps\$*.exe
else
$(CP) $*.exe $(FLOPPY_DIR)/apps/$*.exe
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%.exe)
$(PROGS:%=../../$(DIST_DIR)/apps/%.exe): ../../$(DIST_DIR)/apps/%.exe: %.exe
ifeq ($(DOSCLI),yes)
$(CP) $*.exe ..\..\$(DIST_DIR)\apps\$*.exe
else
$(CP) $*.exe ../../$(DIST_DIR)/apps/$*.exe
endif
bug2.exe: bug2.c
$(CC) bug2.c -lkernel32 -o bug2.exe
$(NM) --numeric-sort bug2.exe > bug2.sym
bug3.exe: bug3.c
$(CC) bug3.c -lkernel32 -o bug3.exe
$(NM) --numeric-sort bug3.exe > bug3.sym
temptest.exe: temptest.c
$(CC) temptest.c -lkernel32 -o temptest.exe
$(NM) --numeric-sort temptest.exe > temptest.sym
test-fseek.exe: test-fseek.c
$(CC) test-fseek.c -lkernel32 -o test-fseek.exe
$(NM) --numeric-sort test-fseek.exe > test-fseek.sym
test-fwrite.exe: test-fwrite.c
$(CC) test-fwrite.c -lkernel32 -o test-fwrite.exe
$(NM) --numeric-sort test-fwrite.exe > test-fwrite.sym
test_rdwr.exe: test_rdwr.c
$(CC) test_rdwr.c -lkernel32 -o test_rdwr.exe
$(NM) --numeric-sort test_rdwr.exe > test_rdwr.sym
test-stdio.exe: test-stdio.c
$(CC) test-stdio.c -lkernel32 -o test-stdio.exe
$(NM) --numeric-sort test-stdio.exe > test-stdio.sym
tst-printf.exe: tst-printf.c
$(CC) tst-printf.c -lkernel32 -o tst-printf.exe
$(NM) --numeric-sort tst-printf.exe > tst-printf.sym
tstdiomisc.exe: tstdiomisc.c
$(CC) tstdiomisc.c -lkernel32 -o tstdiomisc.exe
$(NM) --numeric-sort tstdiomisc.exe > tstdiomisc.sym
include ../../rules.mak

View File

@@ -0,0 +1,27 @@
#include <stdio.h>
#include <string.h>
char *files[500];
int
main (int argc, char *argv[])
{
FILE *fp;
int i;
for (i = 0; i < 500; i++) {
files[i] = tempnam (NULL, "file");
if (files[i] == NULL) {
printf ("tempnam failed\n");
exit (1);
}
printf ("file: %s\n", files[i]);
fp = fopen (files[i], "w");
fclose (fp);
}
for (i = 0; i < 500; i++)
remove (files[i]);
exit (0);
}

View File

@@ -0,0 +1,85 @@
/* Copyright (C) 1991, 1992, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <stdio.h>
#define TESTFILE "/tmp/test.dat"
int
main (void)
{
FILE *fp;
int i, j;
puts ("\nFile seek test");
fp = fopen (TESTFILE, "w");
if (fp == NULL)
{
perror (TESTFILE);
return 1;
}
for (i = 0; i < 256; i++)
putc (i, fp);
if (freopen (TESTFILE, "r", fp) != fp)
{
perror ("Cannot open file for reading");
return 1;
}
for (i = 1; i <= 255; i++)
{
printf ("%3d\n", i);
fseek (fp, (long) -i, SEEK_END);
if ((j = getc (fp)) != 256 - i)
{
printf ("SEEK_END failed %d\n", j);
break;
}
if (fseek (fp, (long) i, SEEK_SET))
{
puts ("Cannot SEEK_SET");
break;
}
if ((j = getc (fp)) != i)
{
printf ("SEEK_SET failed %d\n", j);
break;
}
if (fseek (fp, (long) i, SEEK_SET))
{
puts ("Cannot SEEK_SET");
break;
}
if (fseek (fp, (long) (i >= 128 ? -128 : 128), SEEK_CUR))
{
puts ("Cannot SEEK_CUR");
break;
}
if ((j = getc (fp)) != (i >= 128 ? i - 128 : i + 128))
{
printf ("SEEK_CUR failed %d\n", j);
break;
}
}
fclose (fp);
remove (TESTFILE);
puts ((i > 255) ? "Test succeeded." : "Test FAILED!");
return (i > 255) ? 0 : 1;
}

View File

@@ -0,0 +1,68 @@
#include <stdio.h>
#include <string.h>
int
main (int argc, char *argv[])
{
FILE *f = tmpfile ();
char obuf[99999], ibuf[sizeof obuf];
char *line;
size_t linesz;
if (! f)
{
perror ("tmpfile");
return 1;
}
if (fputs ("line\n", f) == EOF)
{
perror ("fputs");
return 1;
}
memset (obuf, 'z', sizeof obuf);
memset (ibuf, 'y', sizeof ibuf);
if (fwrite (obuf, sizeof obuf, 1, f) != 1)
{
perror ("fwrite");
return 1;
}
rewind (f);
line = NULL;
linesz = 0;
if (getline (&line, &linesz, f) != 5)
{
perror ("getline");
return 1;
}
if (strcmp (line, "line\n"))
{
puts ("Lines differ. Test FAILED!");
return 1;
}
if (fread (ibuf, sizeof ibuf, 1, f) != 1)
{
perror ("fread");
return 1;
}
if (memcmp (ibuf, obuf, sizeof ibuf))
{
puts ("Buffers differ. Test FAILED!");
return 1;
}
asprintf (&line, "\
GDB is free software and you are welcome to distribute copies of it\n\
under certain conditions; type \"show copying\" to see the conditions.\n\
There is absolutely no warranty for GDB; type \"show warranty\" for details.\n\
");
puts ("Test succeeded.");
return 0;
}

View File

@@ -0,0 +1,55 @@
#include <stdio.h>
#include <string.h>
int main()
{
char msg1[] = "testing _write\n";
char msg2[] = "testing putchar.";
char msg3[] = "testing printf.";
char tmpbuf[255];
FILE* f1;
write(1, msg1, strlen(msg1));
write(1, msg2, strlen(msg2));
putchar('o'); putchar('k'); putchar('\n');
write(1, msg3, strlen(msg3));
printf("ok\n");
printf("Testing fopen\n");
f1 = fopen("tmp.txt","w+b");
if (f1 == NULL)
{
printf("fopen failed\n");
return(1);
}
printf("Testing fwrite\n");
if (fwrite(msg1, 1, strlen(msg1)+1, f1) != (strlen(msg1)+1))
{
printf("fwrite failed\n");
return(1);
}
printf("Testing fread\n");
fseek(f1, 0, SEEK_SET);
if (fread(tmpbuf, 1, strlen(msg1)+1, f1) != (strlen(msg1)+1))
{
printf("fread failed\n");
return(1);
}
if (strcmp(tmpbuf,msg1) != 0)
{
printf("fread failed, data corrupt\n");
return(1);
}
printf("Testing fclose\n");
if (fclose(f1) != 0)
{
printf("fclose failed\n");
return(1);
}
return(0);
}

View File

@@ -0,0 +1,129 @@
/* Copyright (C) 1991, 1992, 1996, 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main (int argc, char **argv)
{
static const char hello[] = "Hello, world.\n";
static const char replace[] = "Hewwo, world.\n";
static const size_t replace_from = 2, replace_to = 4;
char filename[FILENAME_MAX];
char *name = strrchr (*argv, '/');
char buf[BUFSIZ];
FILE *f;
int lose = 0;
if (name != NULL)
++name;
else
name = *argv;
(void) sprintf (filename, "/tmp/%s.test", name);
f = fopen (filename, "w+");
if (f == NULL)
{
perror (filename);
exit (1);
}
(void) fputs (hello, f);
rewind (f);
(void) fgets (buf, sizeof (buf), f);
rewind (f);
(void) fputs (buf, f);
rewind (f);
{
size_t i;
for (i = 0; i < replace_from; ++i)
{
int c = getc (f);
if (c == EOF)
{
printf ("EOF at %Zu.\n", i);
lose = 1;
break;
}
else if (c != hello[i])
{
printf ("Got '%c' instead of '%c' at %Zu.\n",
(unsigned char) c, hello[i], i);
lose = 1;
break;
}
}
}
{
long int where = ftell (f);
if (where == (long int) replace_from)
{
register size_t i;
for (i = replace_from; i < replace_to; ++i)
if (putc(replace[i], f) == EOF)
{
printf ("putc('%c') got %s at %Zu.\n",
replace[i], strerror (errno), i);
lose = 1;
break;
}
}
else if (where == -1L)
{
printf ("ftell got %s (should be at %Zu).\n",
strerror (errno), replace_from);
lose = 1;
}
else
{
printf ("ftell returns %lu; should be %Zu.\n", where, replace_from);
lose = 1;
}
}
if (!lose)
{
rewind (f);
if (fgets (buf, sizeof (buf), f) == NULL)
{
printf ("fgets got %s.\n", strerror(errno));
lose = 1;
}
else if (strcmp (buf, replace))
{
printf ("Read \"%s\" instead of \"%s\".\n", buf, replace);
lose = 1;
}
}
if (lose)
printf ("Test FAILED! Losing file is \"%s\".\n", filename);
else
{
(void) remove (filename);
puts ("Test succeeded.");
}
exit (lose ? EXIT_FAILURE : EXIT_SUCCESS);
}

View File

@@ -0,0 +1,311 @@
/* Copyright (C) 1991, 92, 93, 95, 96, 97, 98 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#ifdef BSD
#include </usr/include/stdio.h>
#define EXIT_SUCCESS 0
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include <float.h>
void rfg1 (void);
void rfg2 (void);
void
fmtchk (const char *fmt)
{
(void) fputs(fmt, stdout);
(void) printf(":\t`");
(void) printf(fmt, 0x12);
(void) printf("'\n");
}
void
fmtst1chk (const char *fmt)
{
(void) fputs(fmt, stdout);
(void) printf(":\t`");
(void) printf(fmt, 4, 0x12);
(void) printf("'\n");
}
void
fmtst2chk (const char *fmt)
{
(void) fputs(fmt, stdout);
(void) printf(":\t`");
(void) printf(fmt, 4, 4, 0x12);
(void) printf("'\n");
}
/* This page is covered by the following copyright: */
/* (C) Copyright C E Chew
*
* Feel free to copy, use and distribute this software provided:
*
* 1. you do not pretend that you wrote it
* 2. you leave this copyright notice intact.
*/
/*
* Extracted from exercise.c for glibc-1.05 bug report by Bruce Evans.
*/
#define DEC -123
#define INT 255
#define UNS (~0)
/* Formatted Output Test
*
* This exercises the output formatting code.
*/
void
fp_test (void)
{
int i, j, k, l;
char buf[7];
char *prefix = buf;
char tp[20];
puts("\nFormatted output test");
printf("prefix 6d 6o 6x 6X 6u\n");
strcpy(prefix, "%");
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
for (k = 0; k < 2; k++) {
for (l = 0; l < 2; l++) {
strcpy(prefix, "%");
if (i == 0) strcat(prefix, "-");
if (j == 0) strcat(prefix, "+");
if (k == 0) strcat(prefix, "#");
if (l == 0) strcat(prefix, "0");
printf("%5s |", prefix);
strcpy(tp, prefix);
strcat(tp, "6d |");
printf(tp, DEC);
strcpy(tp, prefix);
strcat(tp, "6o |");
printf(tp, INT);
strcpy(tp, prefix);
strcat(tp, "6x |");
printf(tp, INT);
strcpy(tp, prefix);
strcat(tp, "6X |");
printf(tp, INT);
strcpy(tp, prefix);
strcat(tp, "6u |");
printf(tp, UNS);
printf("\n");
}
}
}
}
printf("%10s\n", (char *) NULL);
printf("%-10s\n", (char *) NULL);
}
int
main (int argc, char *argv[])
{
static char shortstr[] = "Hi, Z.";
static char longstr[] = "Good morning, Doctor Chandra. This is Hal. \
I am ready for my first lesson today.";
fmtchk("%.4x");
fmtchk("%04x");
fmtchk("%4.4x");
fmtchk("%04.4x");
fmtchk("%4.3x");
fmtchk("%04.3x");
fmtst1chk("%.*x");
fmtst1chk("%0*x");
fmtst2chk("%*.*x");
fmtst2chk("%0*.*x");
#ifndef BSD
printf("bad format:\t\"%b\"\n");
printf("nil pointer (padded):\t\"%10p\"\n", (void *) NULL);
#endif
printf("decimal negative:\t\"%d\"\n", -2345);
printf("octal negative:\t\"%o\"\n", -2345);
printf("hex negative:\t\"%x\"\n", -2345);
printf("long decimal number:\t\"%ld\"\n", -123456L);
printf("long octal negative:\t\"%lo\"\n", -2345L);
printf("long unsigned decimal number:\t\"%lu\"\n", -123456L);
printf("zero-padded LDN:\t\"%010ld\"\n", -123456L);
printf("left-adjusted ZLDN:\t\"%-010ld\"\n", -123456);
printf("space-padded LDN:\t\"%10ld\"\n", -123456L);
printf("left-adjusted SLDN:\t\"%-10ld\"\n", -123456L);
printf("zero-padded string:\t\"%010s\"\n", shortstr);
printf("left-adjusted Z string:\t\"%-010s\"\n", shortstr);
printf("space-padded string:\t\"%10s\"\n", shortstr);
printf("left-adjusted S string:\t\"%-10s\"\n", shortstr);
printf("null string:\t\"%s\"\n", (char *)NULL);
printf("limited string:\t\"%.22s\"\n", longstr);
printf("e-style >= 1:\t\"%e\"\n", 12.34);
printf("e-style >= .1:\t\"%e\"\n", 0.1234);
printf("e-style < .1:\t\"%e\"\n", 0.001234);
printf("e-style big:\t\"%.60e\"\n", 1e20);
printf ("e-style == .1:\t\"%e\"\n", 0.1);
printf("f-style >= 1:\t\"%f\"\n", 12.34);
printf("f-style >= .1:\t\"%f\"\n", 0.1234);
printf("f-style < .1:\t\"%f\"\n", 0.001234);
printf("g-style >= 1:\t\"%g\"\n", 12.34);
printf("g-style >= .1:\t\"%g\"\n", 0.1234);
printf("g-style < .1:\t\"%g\"\n", 0.001234);
printf("g-style big:\t\"%.60g\"\n", 1e20);
printf (" %6.5f\n", .099999999860301614);
printf (" %6.5f\n", .1);
printf ("x%5.4fx\n", .5);
printf ("%#03x\n", 1);
{
double d = FLT_MIN;
int niter = 17;
while (niter-- != 0)
printf ("%.17e\n", d / 2);
fflush (stdout);
}
printf ("%15.5e\n", 4.9406564584124654e-324);
#define FORMAT "|%12.4f|%12.4e|%12.4g|\n"
printf (FORMAT, 0.0, 0.0, 0.0);
printf (FORMAT, 1.0, 1.0, 1.0);
printf (FORMAT, -1.0, -1.0, -1.0);
printf (FORMAT, 100.0, 100.0, 100.0);
printf (FORMAT, 1000.0, 1000.0, 1000.0);
printf (FORMAT, 10000.0, 10000.0, 10000.0);
printf (FORMAT, 12345.0, 12345.0, 12345.0);
printf (FORMAT, 100000.0, 100000.0, 100000.0);
printf (FORMAT, 123456.0, 123456.0, 123456.0);
#undef FORMAT
{
char buf[20];
printf ("sprintf (\"%%30s\", \"foo\") == %d, \"%.*s\"\n",
sprintf (buf, "%30s", "foo"), sizeof (buf), buf);
}
fp_test ();
printf ("%e should be 1.234568e+06\n", 1234567.8);
printf ("%f should be 1234567.800000\n", 1234567.8);
printf ("%g should be 1.23457e+06\n", 1234567.8);
printf ("%g should be 123.456\n", 123.456);
printf ("%g should be 1e+06\n", 1000000.0);
printf ("%g should be 10\n", 10.0);
printf ("%g should be 0.02\n", 0.02);
{
double x=1.0;
printf("%.17f\n",(1.0/x/10.0+1.0)*x-x);
}
puts ("--- Should be no further output. ---");
rfg1 ();
rfg2 ();
{
char buf[200];
int result;
sprintf(buf,"%*s%*s%*s",-1,"one",-20,"two",-30,"three");
result = strcmp (buf,
"onetwo three ");
puts (result != 0 ? "Test failed!" : "Test ok.");
return result != 0;
}
}
void
rfg1 (void)
{
char buf[100];
sprintf (buf, "%5.s", "xyz");
if (strcmp (buf, " ") != 0)
printf ("got: '%s', expected: '%s'\n", buf, " ");
sprintf (buf, "%5.f", 33.3);
if (strcmp (buf, " 33") != 0)
printf ("got: '%s', expected: '%s'\n", buf, " 33");
sprintf (buf, "%8.e", 33.3e7);
if (strcmp (buf, " 3e+08") != 0)
printf ("got: '%s', expected: '%s'\n", buf, " 3e+08");
sprintf (buf, "%8.E", 33.3e7);
if (strcmp (buf, " 3E+08") != 0)
printf ("got: '%s', expected: '%s'\n", buf, " 3E+08");
sprintf (buf, "%.g", 33.3);
if (strcmp (buf, "3e+01") != 0)
printf ("got: '%s', expected: '%s'\n", buf, "3e+01");
sprintf (buf, "%.G", 33.3);
if (strcmp (buf, "3E+01") != 0)
printf ("got: '%s', expected: '%s'\n", buf, "3E+01");
}
void
rfg2 (void)
{
int prec;
char buf[100];
prec = 0;
sprintf (buf, "%.*g", prec, 3.3);
if (strcmp (buf, "3") != 0)
printf ("got: '%s', expected: '%s'\n", buf, "3");
prec = 0;
sprintf (buf, "%.*G", prec, 3.3);
if (strcmp (buf, "3") != 0)
printf ("got: '%s', expected: '%s'\n", buf, "3");
prec = 0;
sprintf (buf, "%7.*G", prec, 3.33);
if (strcmp (buf, " 3") != 0)
printf ("got: '%s', expected: '%s'\n", buf, " 3");
prec = 3;
sprintf (buf, "%04.*o", prec, 33);
if (strcmp (buf, " 041") != 0)
printf ("got: '%s', expected: '%s'\n", buf, " 041");
prec = 7;
sprintf (buf, "%09.*u", prec, 33);
if (strcmp (buf, " 0000033") != 0)
printf ("got: '%s', expected: '%s'\n", buf, " 0000033");
prec = 3;
sprintf (buf, "%04.*x", prec, 33);
if (strcmp (buf, " 021") != 0)
printf ("got: '%s', expected: '%s'\n", buf, " 021");
prec = 3;
sprintf (buf, "%04.*X", prec, 33);
if (strcmp (buf, " 021") != 0)
printf ("got: '%s', expected: '%s'\n", buf, " 021");
}

View File

@@ -0,0 +1,56 @@
#include <stdio.h>
int
t1 (void)
{
int n = -1;
sscanf ("abc ", "abc %n", &n);
printf ("t1: count=%d\n", n);
return n != 5;
}
int
t2 (void)
{
int result = 0;
int n;
long N;
int retval;
#define SCAN(INPUT, FORMAT, VAR, EXP_RES, EXP_VAL) \
VAR = -1; \
retval = sscanf (INPUT, FORMAT, &VAR); \
printf ("sscanf (\"%s\", \"%s\", &x) => %d, x = %ld\n", \
INPUT, FORMAT, retval, (long int) VAR); \
result |= retval != EXP_RES || VAR != EXP_VAL
SCAN ("12345", "%ld", N, 1, 12345);
SCAN ("12345", "%llllld", N, 0, -1);
SCAN ("12345", "%LLLLLd", N, 0, -1);
SCAN ("test ", "%*s%n", n, 0, 4);
SCAN ("test ", "%2*s%n", n, 0, -1);
SCAN ("12 ", "%l2d", n, 0, -1);
SCAN ("12 ", "%2ld", N, 1, 12);
n = -1;
N = -1;
retval = sscanf ("1 1", "%d %Z", &n, &N);
printf ("sscanf (\"1 1\", \"%%d %%Z\", &n, &N) => %d, n = %d, N = %ld\n", \
retval, n, N); \
result |= retval != 1 || n != 1 || N != -1;
return result;
}
int
main (int argc, char *argv[])
{
int result = 0;
result |= t1 ();
result |= t2 ();
result |= fflush (stdout) == EOF;
return result;
}

View File

@@ -0,0 +1,41 @@
#
#
#
PROGS = thread
all: $(PROGS:%=%.exe)
.phony: all
clean: $(PROGS:%=%_clean)
$(PROGS:%=%_clean): %_clean:
- $(RM) $*.o
- $(RM) $*.exe
- $(RM) $*.sym
.phony: clean
floppy: # $(PROGS:%=$(FLOPPY_DIR)/apps/%.exe)
$(PROGS:%=$(FLOPPY_DIR)/apps/%.exe): $(FLOPPY_DIR)/apps/%.exe: %.exe
ifeq ($(DOSCLI),yes)
$(CP) $*.exe $(FLOPPY_DIR)\apps\$*.exe
else
$(CP) $*.exe $(FLOPPY_DIR)/apps/$*.exe
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%.exe)
$(PROGS:%=../../$(DIST_DIR)/apps/%.exe): ../../$(DIST_DIR)/apps/%.exe: %.exe
ifeq ($(DOSCLI),yes)
$(CP) $*.exe ..\..\$(DIST_DIR)\apps\$*.exe
else
$(CP) $*.exe ../../$(DIST_DIR)/apps/$*.exe
endif
thread.exe: thread.c
$(CC) $(CFLAGS) thread.c -lkernel32 -o thread.exe
$(NM) --numeric-sort thread.exe > thread.sym
include ../../rules.mak

View File

@@ -0,0 +1,46 @@
#include <stdio.h>
#include <windows.h>
#define NR_THREADS (10)
ULONG nr;
DWORD WINAPI thread_main1(LPVOID param)
{
ULONG s;
printf("Thread %d running\n", (DWORD)param);
s = nr = ((nr * 1103515245) + 12345) & 0x7fffffff;
s = s % 10;
printf("s %d\n", s);
Sleep(s);
printf("Thread %d finished\n", (DWORD)param);
return 0;
}
int main (int argc, char* argv[])
{
HANDLE hThread;
DWORD i=0;
DWORD id;
ULONG nr;
nr = atoi(argv[1]);
printf("Seed %d\n", nr);
printf("Creating %d threads...\n",NR_THREADS*2);
for (i=0;i<NR_THREADS;i++)
{
CreateThread(NULL,
0,
thread_main1,
(LPVOID)i,
0,
&id);
}
printf("All threads created...\n");
for(;;);
return 0;
}

View File

@@ -0,0 +1,2 @@
buildno
buildno.exe

View File

@@ -0,0 +1,26 @@
# $Id: Makefile,v 1.3 1999/11/12 12:01:09 dwelch Exp $
#
BASE_CFLAGS = -I../../include
TARGETNAME=buildno
CLEAN_FILES= $(TARGETNAME).o $(TARGETNAME)$(EXE_POSTFIX) $(TARGETNAME).sym
all: $(TARGETNAME)$(EXE_POSTFIX)
$(EXE_PREFIX)$(TARGETNAME)$(EXE_POSTFIX) -q
$(TARGETNAME)$(EXE_POSTFIX): $(TARGETNAME).c ../../include/reactos/version.h
$(NATIVE_CC) -I../../include -o $(TARGETNAME)$(EXE_POSTFIX) $(TARGETNAME).c
clean:
$(RM) $(TARGETNAME).o
$(RM) $(TARGETNAME).sym
$(RM) $(TARGETNAME)$(EXE_POSTFIX)
.phony: clean
include ../../rules.mak
# EOF

View File

@@ -0,0 +1,262 @@
/* $Id: buildno.c,v 1.2 1999/12/26 20:21:02 ea Exp $
*
* buildno - Generate the build number for ReactOS
*
* Copyright (c) 1999 Emanuele Aliberti
*
*
* It assumes the last release date is defined in
* <reactos/version.h> as a macro named
*
* KERNEL_RELEASE_DATE
*
* as a 32-bit unsigned long YYYYMMDD (UTC).
*
* The build number is the number of full days
* elapsed since the last release date (UTC).
*
* The build number is stored in the file
* <reactos/buildno.h> as a set of macros:
*
* KERNEL_VERSION_BUILD
* KERNEL_VERSION_BUILD_STR
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <reactos/version.h>
#define FALSE 0
#define TRUE 1
/* File to (over)write */
#define BUILDNO_INCLUDE_FILE "../../include/reactos/buildno.h"
static char * argv0 = "";
int
elapsed_days (
time_t t_today,
time_t t_release_day
)
{
double seconds = difftime (t_today, t_release_day);
double days = seconds / (double) 86400.0;
char buf [32];
char * dot = buf;
sprintf (buf, "%f", days );
while ( *dot && *dot != '.') ++dot;
*dot = '\0';
return atol (buf);
}
void
write_h (int build)
{
FILE *h = NULL;
h = fopen ( BUILDNO_INCLUDE_FILE, "w");
if (!h)
{
fprintf (
stderr,
"%s: can not create file \"%s\"!\n",
argv0,
BUILDNO_INCLUDE_FILE
);
return;
}
fprintf (
h,
"/* Do not edit - Machine generated */\n"
);
fprintf (h, "#ifndef _INC_REACTOS_BUILDNO\n" );
fprintf (h, "#define _INC_REACTOS_BUILDNO\n" );
fprintf (
h,
"#define KERNEL_VERSION_BUILD\t%d\n",
build
);
fprintf (
h,
"#define KERNEL_VERSION_BUILD_STR\t\"%d\"\n",
build
);
fprintf (
h,
"#define KERNEL_RELEASE_RC\t\"%d.%d.%d.%d\\0\"\n",
KERNEL_VERSION_MAJOR,
KERNEL_VERSION_MINOR,
KERNEL_VERSION_PATCH_LEVEL,
build
);
fprintf (
h,
"#define KERNEL_RELEASE_STR\t\"%d.%d.%d.%d\"\n",
KERNEL_VERSION_MAJOR,
KERNEL_VERSION_MINOR,
KERNEL_VERSION_PATCH_LEVEL,
build
);
fprintf (
h,
"#define KERNEL_VERSION_RC\t\"%d.%d.%d\\0\"\n",
KERNEL_VERSION_MAJOR,
KERNEL_VERSION_MINOR,
KERNEL_VERSION_PATCH_LEVEL
);
fprintf (
h,
"#define KERNEL_VERSION_STR\t\"%d.%d.%d\"\n",
KERNEL_VERSION_MAJOR,
KERNEL_VERSION_MINOR,
KERNEL_VERSION_PATCH_LEVEL
);
fprintf (
h,
"#endif\n/* EOF */\n"
);
fclose (h);
}
void
usage (void)
{
fprintf (
stderr,
"Usage: %s [-q]\n",
argv0
);
exit (EXIT_SUCCESS);
}
int
main (int argc, char * argv [])
{
int quiet = FALSE;
int year = 0;
int month = 0;
int day = 0;
int build = 0;
time_t t0 = 0;
struct tm t0_tm = {0};
time_t t1 = 0;
struct tm * t1_tm = NULL;
argv0 = argv[0];
switch (argc)
{
case 1:
break;
case 2:
if (argv[1][0] == '-')
{
if (argv[1][1] == 'q')
{
quiet = TRUE;
}
else
{
usage ();
}
}
else
{
usage ();
}
break;
default:
usage ();
}
/*
* We are building TODAY!
*/
time (& t0);
/*
* "Parse" the release date.
*/
day = KERNEL_RELEASE_DATE % 100;
month = ( ( KERNEL_RELEASE_DATE
% 10000
)
- day
)
/ 100;
year =
( KERNEL_RELEASE_DATE
- (month * 100)
- day
)
/ 10000;
if (FALSE == quiet)
{
printf ( "\n\
ReactOS Build Number Generator\n\n\
Last release: %4d-%02d-%02d\n",
year,
month,
day
);
}
t0_tm.tm_year = year - ((year > 1999) ? 2000 : 1900);
t0_tm.tm_mon = month;
t0_tm.tm_mday = day;
t0 = mktime (& t0_tm);
time (& t1); /* current build time */
t1_tm = gmtime (& t1);
t1_tm->tm_year +=
(t1_tm->tm_year < 70)
? 2000
: 1900;
if (FALSE == quiet)
{
printf (
"Current date: %4d-%02d-%02d\n\n",
t1_tm->tm_year,
t1_tm->tm_mon,
t1_tm->tm_mday
);
}
/*
* Compute delta days.
*/
build = elapsed_days (t1, t0);
if (FALSE == quiet)
{
printf (
"Build number: %d (elapsed days since last release)\n",
build
);
printf (
"ROS Version : %d.%d.%d.%d\n",
KERNEL_VERSION_MAJOR,
KERNEL_VERSION_MINOR,
KERNEL_VERSION_PATCH_LEVEL,
build
);
}
/*
* (Over)write the include file.
*/
write_h (build);
return EXIT_SUCCESS;
}
/* EOF */

View File

@@ -0,0 +1,26 @@
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
int i;
FILE* in;
char ch;
for (i=1; i<argc; i++)
{
in = fopen(argv[i],"r");
if (in == NULL)
{
printf("Failed to open file %s\n", argv[i]);
return(0);
}
while ((ch = fgetc(in)) != EOF)
{
putchar(ch);
}
fclose(in);
}
return 0;
}

View File

@@ -0,0 +1,42 @@
#
#
#
OBJECTS= cat.o
PROGS= cat.exe
all: cat.exe
.phony: all
clean:
- $(RM) cat.o
- $(RM) cat.exe
- $(RM) cat.sym
.phony: clean
floppy: $(PROGS:%=$(FLOPPY_DIR)/apps/%)
$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* $(FLOPPY_DIR)\apps\$*
else
$(CP) $* $(FLOPPY_DIR)/apps/$*
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%)
$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* ..\..\$(DIST_DIR)\apps\$*
else
$(CP) $* ../../$(DIST_DIR)/apps/$*
endif
.PHONY: floppy dist
cat.exe: $(OBJECTS) $(LIBS)
$(CC) $(OBJECTS) -o cat.exe
$(NM) --numeric-sort cat.exe > cat.sym
include ../../rules.mak

View File

@@ -0,0 +1,42 @@
#
#
#
OBJECTS= ../common/crt0.o shell.o
PROGS= shell.exe
LIBS= ../../lib/kernel32/kernel32.a ../../lib/ntdll/ntdll.a
CLEAN_FILES= shell.o shell.exe shell.sym
BASE_CFLAGS = -I../../include
all: shell.exe
clean: $(CLEAN_FILES:%=%_clean)
$(CLEAN_FILES:%=%_clean): %_clean:
- $(RM) $*
.phony: clean $(CLEAN_FILES:%=%_clean)
floppy: $(PROGS:%=$(FLOPPY_DIR)/apps/%)
$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* $(FLOPPY_DIR)\apps\$*
else
$(CP) $* $(FLOPPY_DIR)/apps/$*
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%)
$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* ..\..\$(DIST_DIR)\apps\$*
else
$(CP) $* ../../$(DIST_DIR)/apps/$*
endif
shell.exe: $(OBJECTS) $(LIBS)
$(CC) -specs=../../specs $(OBJECTS) $(LIBS) -lgcc -o shell.exe
$(NM) --numeric-sort shell.exe > shell.sym
include ../../rules.mak

View File

@@ -0,0 +1,389 @@
#include <ddk/ntddk.h>
#include <windows.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
HANDLE InputHandle, OutputHandle;
void debug_printf(char* fmt, ...)
{
va_list args;
char buffer[255];
va_start(args,fmt);
vsprintf(buffer,fmt,args);
WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
va_end(args);
}
void ExecuteVer(void)
{
debug_printf(
"Reactos Simple Shell\n(compiled on %s, at %s)\n",
__DATE__,
__TIME__
);
}
void ExecuteCd(char* cmdline)
{
if (!SetCurrentDirectoryA(cmdline))
{
debug_printf("Invalid directory\n");
}
}
void ExecuteDir(char* cmdline)
{
HANDLE shandle;
WIN32_FIND_DATA FindData;
int nFile=0, nRep=0;
FILETIME fTime;
SYSTEMTIME sTime;
shandle = FindFirstFile("*",&FindData);
if (shandle==INVALID_HANDLE_VALUE)
{
debug_printf("Invalid directory\n");
return;
}
do
{
debug_printf("%-15.15s",FindData.cAlternateFileName);
if(FindData.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
debug_printf("<DIR> "),nRep++;
else
debug_printf(" %10d ",FindData.nFileSizeLow),nFile++;
FileTimeToLocalFileTime(&FindData.ftLastWriteTime ,&fTime);
FileTimeToSystemTime(&fTime, &sTime);
debug_printf("%02d/%02d/%04d %02d:%02d:%02d "
,sTime.wMonth,sTime.wDay,sTime.wYear
,sTime.wHour,sTime.wMinute,sTime.wSecond);
debug_printf("%s\n",FindData.cFileName);
} while(FindNextFile(shandle,&FindData));
debug_printf("\n %d files\n %d directories\n\n",nFile,nRep);
FindClose(shandle);
}
void ExecuteReboot(char* cmdline)
{
NtShutdownSystem (ShutdownReboot);
}
void ExecuteType(char* cmdline)
{
HANDLE FileHandle;
char c;
DWORD Result;
FileHandle = CreateFile(cmdline,
FILE_GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (FileHandle == NULL)
{
debug_printf("Unknown file\n");
return;
}
while (ReadFile(FileHandle,
&c,
1,
&Result,
NULL))
{
debug_printf("%c",c);
c = 0;
}
CloseHandle(FileHandle);
}
int ExecuteProcess(char* name, char* cmdline, BOOL detached)
{
PROCESS_INFORMATION ProcessInformation;
STARTUPINFO StartupInfo;
// char arguments;
BOOL ret;
memset(&StartupInfo, 0, sizeof(StartupInfo));
StartupInfo.cb = sizeof (STARTUPINFO);
StartupInfo.lpTitle = name;
ret = CreateProcessA(name,
cmdline,
NULL,
NULL,
FALSE,
((TRUE == detached)
? DETACHED_PROCESS
: CREATE_NEW_CONSOLE
),
NULL,
NULL,
& StartupInfo,
& ProcessInformation
);
if (TRUE == detached)
{
if (ret)
{
debug_printf("%s detached:\n"
"\thProcess = %08X\n"
"\thThread = %08X\n"
"\tPID = %d\n"
"\tTID = %d\n\n",
name,
ProcessInformation.hProcess,
ProcessInformation.hThread,
ProcessInformation.dwProcessId,
ProcessInformation.dwThreadId);
CloseHandle(ProcessInformation.hProcess);
CloseHandle(ProcessInformation.hThread);
}
else
{
debug_printf("Could not detach %s\n", name);
}
}
else
{
if (ret)
{
debug_printf("ProcessInformation.hThread %x\n",
ProcessInformation.hThread);
// CloseHandle(ProcessInformation.hThread);
WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
CloseHandle(ProcessInformation.hProcess);
debug_printf("Thandle %x\n", ProcessInformation.hThread);
CloseHandle(ProcessInformation.hThread);
}
}
return(ret);
}
void ExecuteStart(char* CommandLine)
{
char *ImageName = CommandLine;
for ( ;
( (*CommandLine)
&& (*CommandLine != ' ')
&& (*CommandLine != '\t')
);
CommandLine++
);
*CommandLine++ = '\0';
while ( (*CommandLine)
&& ( (*CommandLine == ' ')
|| (*CommandLine == '\t')
)
);
ExecuteProcess(
ImageName,
CommandLine,
TRUE
);
return;
}
void
ExecuteKill(char * lpPid)
{
HANDLE hProcess;
DWORD dwProcessId;
dwProcessId = (DWORD) atol(lpPid);
debug_printf("dwProcessId %d\n",dwProcessId);
hProcess = OpenProcess(
PROCESS_TERMINATE,
FALSE,
dwProcessId
);
if (NULL == hProcess)
{
debug_printf(
"Could not open the process with PID = %d\n",
dwProcessId
);
return;
}
if (FALSE == TerminateProcess(
hProcess,
0
)
) {
debug_printf(
"Could not terminate the process with PID = %d\n",
dwProcessId
);
}
CloseHandle(hProcess);
return;
}
void ExecuteCommand(char* line)
{
char* cmd;
char* tail;
if (isalpha(line[0]) && line[1] == ':' && line[2] == 0)
{
line[2] = '\\';
line[3] = 0;
SetCurrentDirectoryA(line);
return;
}
tail = line;
while ((*tail)!=' ' && (*tail)!=0)
{
tail++;
}
if ((*tail)==' ')
{
*tail = 0;
tail++;
}
cmd = line;
if (cmd==NULL || *cmd == '\0' )
{
return;
}
if (strcmp(cmd,"cd")==0)
{
ExecuteCd(tail);
return;
}
if (strcmp(cmd,"dir")==0)
{
ExecuteDir(tail);
return;
}
if (strcmp(cmd,"kill")==0)
{
ExecuteKill(tail);
return;
}
if (strcmp(cmd,"reboot")==0)
{
ExecuteReboot(tail);
return;
}
if (strcmp(cmd,"type")==0)
{
ExecuteType(tail);
return;
}
if (strcmp(cmd,"ver")==0)
{
ExecuteVer();
return;
}
if (strcmp(cmd,"validate")==0)
{
debug_printf("Validating heap...");
if (HeapValidate(GetProcessHeap(),0,NULL))
{
debug_printf("succeeded\n");
}
else
{
debug_printf("failed\n");
}
return;
}
if (strcmp(cmd,"start") == 0)
{
ExecuteStart(tail);
return;
}
if (strcmp(cmd,"exit")==0)
{
ExitProcess(0);
return;
}
if (ExecuteProcess(cmd,tail,FALSE))
{
return;
}
debug_printf("Unknown command\n");
}
void ReadLine(char* line)
{
// KEY_EVENT_RECORD KeyEvent;
DWORD Result;
UCHAR CurrentDir[255];
char ch;
int length = 0;
GetCurrentDirectoryA(255,CurrentDir);
debug_printf("%s>", CurrentDir);
do
{
if (!ReadConsoleA(InputHandle,
&ch,
1,
&Result,
NULL))
{
debug_printf("Failed to read from console\n");
for(;;);
}
switch (ch)
{
case '\b':
if (length > 0)
{
debug_printf("\b \b");
line--;
length--;
}
break;
default:
debug_printf("%c", ch);
*line = ch;
line++;
length++;
}
} while (ch != '\n');
line--;
*line = 0;
}
int main(void)
{
static char line[255];
AllocConsole();
InputHandle = GetStdHandle(STD_INPUT_HANDLE);
OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
debug_printf("Shell Starting...\n");
SetCurrentDirectoryA("C:\\");
for(;;)
{
ReadLine(line);
ExecuteCommand(line);
}
return 0;
}

1
reactos/boot.bat Normal file
View File

@@ -0,0 +1 @@
loadros ntoskrnl.exe ide.sys vfatfs.sys

32
reactos/bootflop.bat Normal file
View File

@@ -0,0 +1,32 @@
@ECHO OFF
:
: copy files to HD...
:
COPY /Y A:\DRIVERS\*.SYS C:\reactos\system32\drivers > NUL:
COPY /Y A:\DLLS\*.DLL C:\reactos\system32 > NUL:
COPY /Y A:\APPS\*.EXE C:\reactos\system32 > NUL:
COPY /Y A:\SUBSYS\*.EXE C:\reactos\system32 > NUL:
COPY /Y A:\SUBSYS\*.DLL C:\reactos\system32 > NUL:
:
: present a menu to the booter...
:
: ECHO 1) IDE,VFatFSD
: ECHO 2) No Drivers
: CHOICE /C:123 /T:1,3 "Select kernel boot config"
: IF ERRORLEVEL 2 GOTO :L2
:L1
CLS
LOADROS NTOSKRNL.EXE DRIVERS\IDE.SYS DRIVERS\VFATFSD.SYS
GOTO :END
:L2
CLS
LOADROS NTOSKRNL.EXE
GOTO :END
:END
EXIT

22
reactos/doc/DIRS Normal file
View File

@@ -0,0 +1,22 @@
DIRECTORIES
system : compiled versions of the various system components and
libraries
ntoskrnl : kernel source
ntoskrnl/hal : hardware abstraction layer source
ntoskrnl/mm : memory managment subsystem source
ntoskrnl/io : IO manager subsystem source
ntoskrnl/ke : kernel source
include : win32 headers
include/internal : kernel private header files
include/ntdll : system library private header files
include/kernel32 : system library private header files
include/ddk : header files for modules
lib/ntdll : NT dll source
lib/kernel32 : kernel32 source
doc : documentation
loaders/dos : DOS based loader
loaders/boot : boot loader
services : various services (device drivers, filesystems etc)
services/dd : device drivers
services/fs : file systems

130
reactos/doc/HACKING Normal file
View File

@@ -0,0 +1,130 @@
* Introduction
Having successfully built ReactOS and been amazed by what it does, you're
now desperate to fill in some of the omissions, this document shows you how.
* Prerequisites
A working knowledge of NT driver development is useful for understanding the
kernel and some of its abstractions. The NT4 ddk is available for free
download from http://www.microsoft.com/hwdev/. The Windows 98 and Windows
2000 DDKs are also available but the NT4 one is the most useful. See
Legal Stuff below however.
There are a number of books on NT driver development, I would recommend
'Windows NT Device Driver Development' (http://www.osr.com/book/) since OSR
seem to know their stuff. There is only one book on NT filesystem
development 'Windows NT File System Internals'. Please don't buy any of
these books unless you need to, and can afford it.
These mailing lists and newsgroups are useful for NT internals related
questions,
ntfsd@atria.com, ntdev@atria.com
(subscribe by email to majordomo@atria.com)
comp.os.????
microsoft.public.????
* Style
There is no coding style used for ReactOS, however the following guidelines
make things easier
Include information at the top of a module about its purpose, contact
information for its programmer and any useful notes.
Include a comment by each non-trival function describing its arguments,
purpose and any other notes.
Update the documentation in this directory
These guidelines are an ideal, no one manages to implement them all the
time, straightforward working code is probably just as good.
* Debugging
Debugging kernel-mode code is tricky, these are some snippets
DbgPrint writes a message to the console using a printf style format
string. The DPRINT macro (defined in internal/debug.h) expands to
DbgPrint unless NDEBUG is defined, this is useful for having copious
output from a module only when a problem is being debugging. DPRINT
also prefixes the message with the file and line number to make it
easier to see where output is coming from. DbgPrint can be used at any
point including in interrupt handlers.
There are options in ntoskrnl/kd/kdebug.c for copying DbgPrint output
to a serial device or bochs logging port (parallel support should also
be added). This can be useful if a lot of output is being generated.
It should be possible to include support for debugging the kernel with
gdb over a serial line. Bochs (a shareware CPU emulator) is also useful
for debugging the kernel, I wrote some patches to allow capture of console
output from within bochs to file and for debugging a kernel running
under bochs with gdb. Contact me (welch@cwcom.net) if you're are
interested.
If CPU reports an exception not handled by the kernel (any page fault
not part of virtual memory support or any other exception) the kernel
will display output like this and halt
General Protection Fault Exception: 13(0)
CS:EIP xxxxxxxx:xxxxxxx
DS xxxx ES xxxx FS xxxx GS xxxxx
EAX: xxxx EBX: xxxx
....
EDI: xxxx EFLAGS: xxxx ESP: xxxx
cr2: xxxx
Stack: xxxx xxxx xxxx ...
....
Frames: xxxx xxxx xxxx ...
....
The fault type will usually be either 'General Protection' or
'Page Fault', see your Intel manual for the more exotic types. The
'EIP' number is the address of the faulting instruction. If the 'CS'
number is 0x20 then the exception occured in kernel mode, if it is 0x11
then the exception occurred in user mode. 'cr2' is the address that the
faulting instruction was trying to access, if the exception was a page
fault. The number printed after 'Frames' are any addresses on the stack
that look like function addresses.
If the kernel detects a serious problem that it will bug check, displaying
output like this
Bug detected (code x, param x x x x)
Frames: xxx xxxx xxxx
....
Again the numbers printed after 'Frames' are any addresses on the stack
that look like function addresss. Usually the kernel will also print a
message describing the problem in more detail, the bug check code isn't
very useful at the moment.
* Contacts
There is a mailing list for kernel development,
ros-kernel@reactos.com
The main developers use a cvs account to coordinate changes, ask
rex (rex@lvcablemodem.com) for an account if you are going to be adding
a lot of code. Smaller patches can go to the mailing list or to the
relevant developer (usually the comment at the top of a module will have
an email address). Regular snapshots are made available for download,
see the mailing list for announcements.
* Legal stuff
The ReactOS project is GPL'ed, please make sure any code submitted is
compatible with this.
The NT4 ddk license agreement allows its usage for developing nt drivers
only. Legally therefore it can not be used to develop ReactOS, neither the
documentation or the sample code. I'm not a lawyer, but I doubt the
effiacy of 'shrinkwrap licenses' particularly on freely downloadable
software. The only precendent I know of, in a Scottish court, didn't
upload this type of license.
Also the 'fair use' section of copyright law allows the 'quoting' of small
sections from copyrighted documents, e.g. Windows API or DDK documentation

6
reactos/doc/INDEX Normal file
View File

@@ -0,0 +1,6 @@
HACKING: Some notes for adding code to ReactOS
DIRS: Explanation of directory layout
INTERNALS: Some notes on kernel internals
TODO: Bugs and omissions, big and little things that need to be done
NOTES: Unsorted material, some of it is redundant
BUGLIST: Known bugs, please update when you find one

43
reactos/doc/INTERNALS Normal file
View File

@@ -0,0 +1,43 @@
A collection of articles on kernel internals, please add to this
------------------------------------------------------------------------------
IRQ level
------------------------------------------------------------------------------
IRQ level (IRQL) is a per-processor state in ReactOS used to coordinate
execution between ISRs and between threads. There are several levels
PASSIVE_LEVEL, APC_LEVEL: The normal level for user mode and most
kernel mode code. At the moment APC_LEVEL is unused.
DISPATCH_LEVEL: At this level all irqs are still allowed but thread
rescheduling on the current processor is disabled. This is used by
the spinlock synchronization primitive to implement its uniprocessor
semantics (multiprocessor is more complex). It is also used for some
other forms of synchronization, DPCs for example. Many APIs are
unavailable at this IRQL, usually those that might have to wait. It
is recommended that you don't spend too much time at this IRQL
otherwise system responsiveness will be reduced.
> DISPATCH_LEVEL: Each irq is assigned a priority (which will be
greater than DISPATCH_LEVEL). At an irq's priority level that irq,
lower priority irqs and thread rescheduling are disabled. Higher
priority irqs can still run. Very few APIs are available at IRQLs
greater than DISPATCH_LEVEL.
HIGH_LEVEL: All irqs are disabled.
-------------------------------------------------------------------------------
DPCs
-------------------------------------------------------------------------------
It is a design goal not to spend too much time in ISRs, for this reason
ISRs should postpone most processing till it can run at a lower IRQL. The
mechanism for this is a Delayed Procedure Call (DPC). When a DPC object is
created, it is associated with a function. The DPC object can then be inserted
in the DPC queue from an ISR. If the IRQL on return from the ISR is less than
DISPATCH_LEVEL the DPC queue will be drained, otherwise this will happen when
the IRQL level drops below DISPATCH_LEVEL or the processor becomes idle. When
the DPC queue is drained each DPC object is removed and the associated
function is called at DISPATCH_LEVEL. A DPC object can only be inserted once,
further insertions before it is removed will have no effect.

36
reactos/doc/apc Normal file
View File

@@ -0,0 +1,36 @@
APC
Asynchronous procedure call
An APC is a Kernel-defined control object representing a procedure
that is called asynchronously. APCs are thread-context dependent; that
is, they are queued to a particular thread for execution.
There are three different kinds of APCs in NT:
User APCs are used by certain asynchronous NT system services to allow
user-mode applications or protected subsystems to synchronize the
execution of a thread with the completion of an operation or the
occurrence of an event such as a timers expiration. User APCs are, by
default, disabled. That is, they are queued to the user-mode thread,
but they are not executed except at well-defined points in the
program. Specifically, they can only be executed when an application
or protected subsystem has called a wait service and has enabled
alerts to occur, or if it has called the test-alert service.
Kernel APCs are normal kernel-mode APCs. They are much like a normal
user APC except that they are executable by default. That is, they are
enabled except when the thread is already executing a Kernel APC.
(Note that a special Kernel APC always preempts these.)
Special Kernel APCs cannot be blocked except by running at a raised
IRQL. They are executed at APC_LEVEL IRQL (see IDT), in kernel mode.
These types of APCs are used by the system to force a thread to
execute a procedure in the threads context. An example of this is I/O
completion: the I/O Manager needs to get back into the context of the
original requestor of the I/O operation so that it can copy buffers,
and so forth. In order to do this, the I/O Manager must be able to
access the virtual address space of the thread/process, and the most
efficient way to complete the operation is to be in the calling
threads context.

696
reactos/doc/notes Normal file
View File

@@ -0,0 +1,696 @@
*** This file contains messages I've culled off the net as well
as previous discussions all of which have useful info on fixes
that need to be added to ReactOS. messages are between five
dashes on a line by themselves. If you implement the fix
reffered to in a message, feel free to delete it from the file.
Rex ***
-----
Subject: [ros-kernel] Inside the Boot Process
Date: Mon, 22 Mar 1999 22:05:47 +0100
From: Emanuele Aliberti <ea@iol.it>
For those working on the boot loader: in WinNt Magazine november 1998
issue (http://www.winntmag.com/) there is a detailed description, by
Mark Russinovich, of the r<>le the MBR, NTLDR, boot.ini, ntdetect.com...
play in the boot process ("Inside the Boot Process, Part 1").
-----
Yes with DPCs, KeDrainDpcQueue should go to HIGH_LEVEL because
it needs to synchronize with KeInsertDpcQueue. Also the idle thread
should run at DISPATCH_LEVEL and regularly drain the dpc queue, that
way if an irq happens and the dpc can't be executed immediately it
will be executed as soon as the processor is idle rather than
waiting for the next timer tick
-----
About the console driver, I think it might be quite useful to have a simple
way for apps to print to the screen for debugging. But when the kernel is more
stable, console handling should be moved to user level because console printing
needs to know about windows and so on which can only be done at user level.
-----
Subject: Re: IMSAMP-how to avoid rebooting?
Date: 9 Nov 1998 00:40:32 -0000
From: Charles Bryant <n51190709.ch@chch.demon.co.uk>
Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
References: 1, 2 , 3 , 4
In article <un264wzle.fsf@xxx.yyy.zzz>, David C. <qqqq@xxx.yyy.zzz> wrote:
>The reason it won't unload when something is bound to it is the same
>reason you can't unload any other driver that has an open client. If
>you install any driver, and have a user program (or another driver) open
>a handle to it, and then give the "net stop" command to unload it,
>you'll find that the unload will be delayed until the user program
>closes its handle.
When developing a driver I found this to be a considerable nuisance.
Frequently a bug would leave an IRP stuck in the driver and I
couldn't unload and reload a fixed version. While reading NTDDK.H I
found a suspicious constant and discovered that the Flags field in
the device (the one which you OR in DO_BUFFERED_IO or DO_DIRECT_IO)
has a bit called DO_UNLOAD_PENDING. By experiment I confirmed that
this bit is set when you do 'net stop', so a driver can check it
periodically (e.g. from a timer DPC every ten seconds) and cancel all
queued IRPs if it is found to be set.
Since this is not documented anywhere that I can find, it might be
unwise to rely on it for production code, but it is very useful for
debugging. Maybe someone with internals knowledge can comment on the
reliability of it.
-----
Subject: Re: Kernel bugs
Date: Fri, 23 Oct 1998 12:08:36 -0700
From: rex <rex@lvcablemodem.com>
To: Jason Filby <jasonfilby@yahoo.com>
References: 1
Jason Filby wrote:
> Hi,
>
> Ok -- here's most of what I get when I press a key:
>
> Page fault detected at address 1fd4 with eip c042f794
> Recursive page fault detected
> Exception 14(2)
> CS:EIP 20:c042f794
>
> Rex -- do you know of anyway to find out which function in what file
> is causing the exception? I know that for problems in the kernel, you
> just look in the ntoskrnl\kernel.sym file and find the EIP value which
> matches the one given in the exception debug text. But what about
> modules? How can we track exceptions that occur in functions in modules?
>
I know this is a little belated, but I thought I'd take astab at answering
this anyway. add an option to the
makefile for the module to generate a listing file with
symbol information. Then, on a boot test, note the
address that the module is loaded at, and subtract
this from the EIP value. add any offset used in the
module link specification (I dont think there currently
is one), and look for the last symbol with a lower
address offset.
Brian, I have an idea on how to make this exception
dump information a little more useful. We should
have the load information for the load modules
in memory somewhere. Perhaps the exception
dump could check offending addresses to see if
they lie in the kernel or in a module, and if they
lie in a module the proper offset could be subtracted
and this number could be displayed seperately. If
I get a chance today, I'll make this change and send
it to ya.
Rex.
-----
Subject: [ros-kernel] Pet peeve of the week
Resent-Date: Sun, 25 Oct 1998 11:57:40 -0600
Resent-From: ros-kernel@sid-dis.com
Date: Sun, 25 Oct 1998 09:53:48 -0800
From: rex <rex@lvcablemodem.com>
Reply-To: <ros-kernel@sid-dis.com>
To: ReactOS Kernel Forum <ros-kernel@sid-dis.com>
Hi all,
I guess it's about time to start another mailstorm
on the list. :)
I have a suggestion for a change to the kernel.
It not a very big change, and I hope everyone
will agree that it makes sense.
There is a structure used in many places in the
kernel called LARGE_INTEGER. the is also
a version called ULARGE_INTEGER, but it
is not used at all as far as I can tell. this structure
is equivalent to a long long int. You can literally
cast a pointer to a LARGE_INTEGER to a
long long int and all manipulation will work
seemlessly. My suggestion is that we replace the
use of this structure with long long ints. Even
microsoft, in their infinite wisdom, has made this
suggestion in the DDK documentation. If you're
wondering where, look at the RTL functions
that manipulate LARGE_INTEGER structs.
Replacing LI's with long long ints will work
because they are binary compatable. All software
compiled to use LI's will manipulate long long ints
correctly and vice versa. There is one problem
with this suggestion: the LARGE_INTEGER type
is a structure containing 2 members. Any code
that accesses the structure by members will break.
I think the kernel side impact is minimal, and is
worth the change. However, the structure is used
in several of the Win32 API functions, and needs
to remain there. I think we build a conditionally
compiled version of the LARGE_INTEGER type.
In kernel mode code (the kernel proper and drivers)
the LARGE INTEGER will be the following:
typedef long long int LARGE_INTEGER,
*PLARGE_INTEGER;
typedef unsigned long long int ULARGE_INTEGER,
*PULARGE_INTEGER;
and in user mode code it will expand out to the
current definition (which by the way, is not
strictly correct, but can't be because it uses a
MS compiler extension).
Brian, I would be willing to make the conversion
to those kernel modules that needed it, and of
course to the IDE driver if we want to go forward
with the change.
Lastly, I'll mention what made me consider this.
I was fixing the timer routines, and two of the
three problems turned out to be related to LI
conversion problems.
Rex.
-----
Subject: Re: [ros-kernel] Pet peeve of the week
Date: Thu, 29 Oct 1998 19:10:37 +0100
From: Boudewijn <ariadne@xs4all.nl>
To: rex@lvcablemodem.com
References: 1
Hai Rex
I think it is a good idea to wrap a makro around the member access
to large integers.
I haven't tested this, but do you think this is a good sugestion ?
#ifdef COMPILER_LARGE_INTEGERS
#define GET_LARGE_INTEGER_HIGH_PART(LargeInteger) ( ( LargeInteger >>
32) )
#define GET_LARGE_INTEGER_LOW_PART(LargeInteger) ( (LargeInteger &
0xFFFFFFFF) )
#define SET_LARGE_INTEGER_HIGH_PART(LargeInteger,Signed_Long) (
LargeInteger |= ( ((LARGE_INTEGER)Signed_Long) << 32 ) )
#define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) (
LargeInteger |= Unsigned_Long )
#else
#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 )
#define SET_LARGE_INTEGER_LOW_PART(LargeInteger,Unsigned_Long) (
LargeInteger.LowPart = Unsigned_Long )
#endif
Boudewijn
-----
Subject: Re: Question on "Sending buffers on the stack to asynchronous DeviceIoControl with buffered I/O"
Date: Mon, 16 Nov 1998 11:24:57 -0800
From: "-Paul" <paulsan@microsoftSPAM.com>
Organization: Microsoft Corp.
Newsgroups: microsoft.public.win32.programmer.kernel, comp.os.ms-windows.programmer.nt.kernel-mode
References: 1
Radu, I post the following information occassionally for questions such as
yours. I hope it helps.
-Paul
Here is an explanation of buffers and DeviceIoControl.
First, here are the parameters,
BOOL DeviceIoControl(
HANDLE hDevice, // handle to device of interest
DWORD dwIoControlCode, // control code of operation to perform
LPVOID lpInBuffer, // pointer to buffer to supply input data
DWORD nInBufferSize, // size of input buffer
LPVOID lpOutBuffer, // pointer to buffer to receive output data
DWORD nOutBufferSize, // size of output buffer
LPDWORD lpBytesReturned, // pointer to variable to receive output byte
count
LPOVERLAPPED lpOverlapped // pointer to overlapped structure for
asynchronous operation
);
METHOD_BUFFERED
user-mode perspective
lpInBuffer - optional, contains data that is written to the driver
lpOutBuffer - optional, contains data that is read from the driver after
the call has completed
lpInBuffer and lpOutBuffer can be two buffers or a single shared buffer.
If a shared buffer, lpInBuffer is overwritten by lpOutBuffer.
I/O Manager perspective
examines nInBufferSize and nOutBufferSize. Allocates memory from non-paged
pool and puts the address of this pool in Irp->AssociatedIrp.SystemBuffer.
The size of this buffer is equal to the size of the larger of the two
bufferes. This buffer is accessible at any IRQL.
copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
copies nOutBufferSize to
irpSp->Parameters.DeviceIoControl.OutputBufferLength
copies contents of lpInBuffer to SystemBuffer allocated above
calls your driver
Device Driver perspective
you have one buffer, Irp->AssociatedIrp.SystemBuffer. You read input data
from this buffer and you write output data to the same buffer, overwriting
the input data.
Before calling IoCompleteRequest, you must
- set IoStatus.Status to an approriate NtStatus
- if IoStatus.Status == STATUS_SUCCESS
set IoStatus.Information to the
number of bytes you want copied
from the SystemBuffer back into
lpOutBuffer.
I/O Manager Completion Routine perspective
looks at IoStatus block, if IoStatus.Status = STATUS_SUCCESS, copies the
number of bytes specified by IoStatus.Information from
Irp->AssociatedIrp.SystemBuffer into lpOutBuffer
completes the request
METHOD_IN_DIRECT
user-mode perspective
lpInBuffer - optional, contains data that is written to the driver. This
buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid
confusion, mentally rename this buffer to lpControlBuffer. This is
typically a small, optional buffer that might contain a control structure
with useful information for the device driver. This buffer is smal and is
double buffered.
lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is read by
the driver. To avoid confusion, mentally rename this buffer to
lpDataTransferBuffer. This is physically the same buffer that the device
driver will read from. There is no double buffering. Technically, this
buffer is still optional, but since you are using this buffering method,
what would be the point???
I/O Manager perspective
If lpInBuffer exists, allocates memory from non-paged pool and puts the
address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is
accessible at any IRQL.
copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
copies nOutBufferSize to
irpSp->Parameters.DeviceIoControl.OutputBufferLength
copies contents of lpInBuffer to SystemBuffer allocated above
So far this is completely identical to METHOD_BUFFERED. Most likely
lpInBuffer (mentally renamed to lpControlBuffer) is very small in size.
For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is
allocated. lpOutBuffer is probed and locked into memory. Then, the user
buffer virtual addresses are checked to be sure they are readable in the
caller's access mode.
The MDL is address is stored in Irp->MdlAddress.
Your driver is called.
Device Driver perspective
The device driver can read the copy of lpOutBuffer via
Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to
this buffer is lost. The I/O Manager does not copy any data back to the
user-mode buffers as it did in the completion routine for METHOD_BUFFERED.
Art Baker's book is wrong in this respect (page 168, "data going from the
driver back to the caller is passed through an intermediate system-space
buffer" and page 177, "When the IOCTL IRP is completed, the contents of the
system buffer will be copied back into the callers original output buffer".
The device driver accesses the Win32 buffer directly via Irp->MdlAddress.
The driver uses whatever Mdl API's to read the buffer. Usually, this
buffer is to be written to some mass storage media or some similar
operation. Since this is a large data transfer, assume a completion
routine is required.
mark the Irp pending
queue it
return status pending
Device Driver Completion Routine perspective
standard completion routine operations
set IoStatus.Status to an approriate NtStatus
IoStatus.Information is not needed
completete the request
I/O Manager Completion Routine perspective
standard I/O Manager completion routine operations
unmap the pages
deallocate the Mdl
complete the request
METHOD_OUT_DIRECT
user-mode perspective
lpInBuffer - optional, contains data that is written to the driver. This
buffer is used in the exact same fashion as METHOD_BUFFERED. To avoid
confusion, mentally rename this buffer to lpControlBuffer. This is
typically a small, optional buffer that might contain a control structure
with useful information for the device driver. This buffer is smal and is
double buffered.
lpOutBuffer - NOT OPTIONAL, This LARGE buffer contains data that is written
by the driver and read by the wer-mode application when the request is
completed. To avoid confusion, mentally rename this buffer to
lpDataTransferBuffer. This is physically the same buffer that the device
driver will write to. There is no double buffering. Technically, this
buffer is still optional, but since you are using this buffering method,
what would be the point???
I/O Manager perspective
If lpInBuffer exists, allocates memory from non-paged pool and puts the
address of this pool in Irp->AssociatedIrp.SystemBuffer. This buffer is
accessible at any IRQL.
copies nInBufferSize to irpSp->Parameters.DeviceIoControl.InputBufferLength
copies nOutBufferSize to
irpSp->Parameters.DeviceIoControl.OutputBufferLength
copies contents of lpInBuffer to SystemBuffer allocated above
So far this is completely identical to METHOD_BUFFERED. Most likely
lpInBuffer (mentally renamed to lpControlBuffer) is very small in size.
For lpOutBuffer (mentally renamed to lpDataTransferBuffer), an MDL is
allocated. lpOutBuffer is probed and locked into memory. Then the user
buffer's addresses are checked to make sure the caller could write to them
in the caller's access mode.
The MDL is address is stored in Irp->MdlAddress.
Your driver is called.
Device Driver perspective
The device driver can read the copy of lpOutBuffer via
Irp->AssociatedIrp.SystemBuffer. Anything written by the device driver to
this buffer is lost.
The device driver accesses the Win32 buffer directly via Irp->MdlAddress.
The driver uses whatever Mdl API's to write data to the buffer. Usually,
this buffer is to be read from some mass storage media or some similar
operation. Since this is a large data transfer, assume a completion
routine is required.
mark the Irp pending
queue it
return status pending
Device Driver Completion Routine perspective
standard completion routine operations
set IoStatus.Status to an approriate NtStatus
IoStatus.Information is not needed
completete the request
I/O Manager Completion Routine perspective
standard I/O Manager completion routine operations
unmap the pages
deallocate the Mdl
complete the request
METHOD_NEITHER
I/O Manager perspective
Irp->UserBuffer = lpOutputBuffer;
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = lpInputBuffer;
No comments here. Don't use METHOD_DIRECT unless you know what you are
doing. Simple rule.
If your IOCtl involves no data transfer buffers, then METHOD_NEITHER is the
fastest path through the I/O Manager that involves an Irp.
Final Comment
Don't touch Irp->UserBuffer. This is a bookmark for the I/O Manager. Two
major problems can occur. 1 - page fault at high IRQL, or 2 - you write
something to Irp->UserBuffer and the I/O Manager overwrites you in its
completion routine. File systems access Irp->UserBuffer, but FSD writers
know all of the above and know when it is safe to touch Irp->UserBuffer.
Radu Woinaroski wrote in message <364F8F6E.2434B010@scitec.com.au>...
>Hello,
>
>I have a kernel-mode device driver that accepts a number of IoControl
>commands that use buffered data transfer (METHOD_BUFFERED).
>
>A user mode API provides a higher level access then the DeviceIoControl
>function.
>
>The function is implemented like that
>
>BOOL
Something(
> HANDLE hDevice ,
> int param1,
> int param2,
> DWORD * pReturn,
> LPOVERLAPPED pOverlapped)
>{
> // here a data buffer on the stack sent to asynchronous DeviceIoControl
>call
> int aDataIn[2];
> aDataIn[0] = param1;
> aDataIn[1] = param2;
>
> return DeviceIoControl(
> hDevice,
> DO_SOMETHING_IO,
> aDataIn,
> sizeof(int)*2,
> pReturn,
> sizeof(DWORD),
> pOverlapped);
>}
>
>The aDataIn buffer will not exist after DeviceIoControl returns (and
>when the I/O operation terminates). I know that for buffered IO the
>input data buffer is copyed by de IOManager to a nonpaged-pool area
>before passing the request to driver dispatch routine (DeviceControl).
>At the point of calling the dispatch routine (DeviceControl) the driver
>runs in the context of the calling thread so DeviceIoControl hasn't
>returned yet (?? or so I think) so aDataI
n will still be valid at the
>time IOManager copyes it to its buffer. So, this apears to work ok (at
>least in my opinion).
>
>Does I/O Manager use the Input buffer from the call to the Win32
>DeviceIoControl any where else after the first copy ?
>
>Is there any reason why this approach (passing a buffer on the stack to
>a asynchronous DeviceIoControl that uses buffered I/O) wouldn't work ?
>
>Allocating buffers from heap and deleting them on IO completion while
>managing asynchronous IO seems too much work ;-) .
>
>Thanks in advance for your opinions
>Radu W.
>
>--
>Radu Woinaroski
>Scitec
>Sydney, Australia
>Radu.Woinaroski@scitec.com.au
-----
Subject: Re: PCI ISR problem
Date: Fri, 20 Nov 1998 18:04:48 GMT
From: jeh@cmkrnl.com (Jamie Hanrahan)
Organization: Kernel Mode Systems, San Diego, CA
Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
References: 1
On Thu, 19 Nov 1998 15:46:13 -0600, Eric Gardiner
<eric.gardiner@natinst.com> wrote:
>I'm having problems with NT4 not hooking the interrupt line indicated by
>a PCI device. Here's what I'm doing:
>
>1) Enumerating the PCI buses on the system (using HalGetBusData) until
>I find my device.
>2) Once my device is found, I read the "Interrupt Line Register" in the
>device's PCI config space to determine what interrupt level to pass to
>HalGetInterruptVector.
Whups! No. Call HalAssignSlotResources and look at the returned
CM_RESOURCE_LIST to find the vector, level, port addresses, etc., for
your device. (Then pass the returned CM_RESOURCE_LIST to ExFreePool.)
See Knowledge Base article Q152044.
--- Jamie Hanrahan, Kernel Mode Systems, San Diego CA (jeh@cmkrnl.com)
Drivers, internals, networks, applications, and training for VMS and Windows NT
NT kernel driver FAQ, links, and other information: http://www.cmkrnl.com/
Please post replies, followups, questions, etc., in news, not via e-mail.
-----
Subject: Re: IRP canceling
Date: Mon, 23 Nov 1998 09:05:47 -0500
From: Walter Oney <waltoney@oneysoft.com>
Organization: Walter Oney Software
Newsgroups: comp.os.ms-windows.programmer.nt.kernel-mode
References: 1
Seol,Keun Seok wrote:
> But, if the IRP was the CurrentIrp of the Device Object,
> the Driver's Start I/O routine will try to process the IRP.
> In the DDK help, the Start I/O routine MUST check the current IRP's
> Cancel bit.
> If set, Start I/O routine must just return.
>
> But I think that the IRP already completed should not be accessed.
You're absolutely right. I recommend the following code in a standard
StartIo routine to avoid the problem you point out:
VOID StartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
KIRQL oldirql;
IoAcquireCancelSpinLock(&oldirql);
if (Irp != DeviceObject->CurrentIrp || Irp->Cancel)
{
IoReleaseCancelSpinLock(oldirql);
return;
}
else
{
IoSetCancelRoutine(Irp, NULL);
IoReleaseCancelSpinLock(oldirql);
}
. . .
}
This dovetails with a standard cancel routine:
VOID CancelRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
if (DeviceObject->CurrentIrp == Irp)
{
IoReleaseCancelSpinLock(Irp->CancelIrql);
IoStartNextPacket(DeviceObject, TRUE);
}
else
{
KeRemoveEntryDeviceQueue(&DeviceObject->DeviceQueue,
&Irp->Tail.Overlay.DeviceQueueEntry);
IoReleaseCancelSpinLock(Irp->CancelIrql);
}
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
You need to remember that the C language specification requires that
evaluation of boolean operators short circuit when the result is known.
So, if StartIo discovers that the Irp it got as an argument is not the
same as CurrentIrp, it will not attempt to evaulate Irp->Cancel.
Now, as to why this works: StartIo gets called either by IoStartPacket
or IoStartNextPacket. Each of them will grab the cancel spin lock and
set CurrentIrp, then release the spin lock and call StartIo. If someone
should sneak in on another CPU and cancel this very same IRP, your
cancel routine will immediately release the spin lock and call
IoStartNextPacket. One of two things will then happen. IoStartNextPacket
may succeed in getting the cancel spin lock, whereupon it will nullify
the CurrentIrp pointer. If another IRP is on the queue, it will remove
it from the queue, set CurrentIrp to point to this *new* IRP, release
the spin lock, and call StartIo. [You now have two instances of StartIo
running on two different CPUs for two different IRPs, but it's not a
problem because they won't be able to interfere with each other.]
Meanwhile, your original instance of StartIo gets the cancel spin lock
and sees that CurrentIrp is not equal to the IRP pointer it got as an
argument, so it gives up.
The second way this could play out is that StartIo gets the cancel lock
before IoStartNextPacket does. In this case, CurrentIrp is still
pointing to the IRP that's in the process of being cancelled and that
StartIo got as an argument. But this IRP hasn't been completed yet (the
CPU that's running your cancel routine is spinning inside
IoStartNextPacket and therefore hasn't gotten to calling
IoCompleteRequest yet), so no-one will have been able to call IoFreeIrp
to make your pointer invalid.
People may tell you that you should be using your own queues for IRPs so
you can avoid bottlenecking the system on the global cancel spin lock.
That's true enough, but doing it correctly with Plug and Play and Power
management things in the way is gigantically complicated. There's a
sample in the NT 5 beta-2 DDK called CANCEL that shows how to manage
your own queue if you don't worry about PNP and POWER. I hear tell of an
upcoming MSJ article by a Microsoft developer that may solve the
complete problem.
-----
Subject: ANNOUNCE: ALINK v1.5
Date: 16 Nov 1998 16:36:05 GMT
From: anthony_w@my-dejanews.com
Organization: Deja News - The Leader in Internet Discussion
Newsgroups: comp.os.ms-windows.programmer.win32, comp.lang.asm.x86, comp.os.msdos.programmer
ALINK is a freeware linker, creating MSDOS COM and EXE files and Win32 PE EXE
and DLL files from OMF format OBJ and LIB files, win32-COFF format OBJ files,
and win32 RES files.
NEW for version 1.5:
Win32 COFF object file support.
Download it now from my home page.
Anthony
--
anthony_w@geocities.com
http://www.geocities.com/SiliconValley/Network/4311/index.html
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
-----

59
reactos/doc/todo Normal file
View File

@@ -0,0 +1,59 @@
* Critical path tasks
Test and debug Registry routines
Finish multiple system service table support (HalRegisterServiceTable)
Modify GENNTDLL to generate all needed system service tables
* These tasks would be nice
Separate HAL into KM DLL
* Function groups totally or partially unimplemented
Dma functions (see hal/x86/dma.c)
PCI interface functions (see hal/x86/bios32.c, hal/x86/pci.c)
HalExamineMbr
Locale support (see ex/locale.c)
Shutdown support (see ex/power.c)
Zw(Set/Get)SystemInformation (see ex/sysinfo.c)
Adapter functions (see io/adapter.c)
Io cancelation support (see io/cancel, et al)
Directory change notification (see io/dir.c)
Error logging (see io/errlog.c)
Buffer flushing (see io/flush.c)
Io completion ports (see io/iocomp.c)
File locking (see io/lock.c)
Mailslots (see io/mailslot.c)
Named pipes (see io/npipe.c)
Hardware resource management (see io/resource.c)
File access checking (see io/share.c)
APCs to user-mode (see ke/apc.c, ke/apchelp.asm)
Exception support (see ke/catch.c)
Mutex support (see ke/mutex.c)
Semaphore support (see ke/sem.c)
Timer support (see ke/timer.c)
Properly calibrate delay loop (see ke/timer.c)
Waiting for multiple objects (see ke/wait.c)
Single linked lists (see rtl/slist.c)
Sequenced lists (see rtl/seqlist.c)
* Verify implementation
Fast mutexes (see ex/fmutex.c)
* Major areas
Security support (see se/*.c)
Registry support (see cm/*.c)
Paging support
File system cache support
SCSI miniport driver
Network support
Video drivers
USER and GDI modules
* Drivers
NTFS, EXT2 filesystems
Many others (use oem's where possible)
* For the future
DOS, Win16, POSIX subsystems

View File

@@ -0,0 +1,4 @@
base.tmp
junk.tmp
temp.exp

View File

@@ -0,0 +1,290 @@
/* $Id: beep.c,v 1.4 1999/10/16 12:41:42 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/dd/beep/beep.c
* PURPOSE: BEEP device driver
* PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
* UPDATE HISTORY:
* 30/01/99 Created
* 16/10/99 Minor fixes
*/
/* INCLUDES ****************************************************************/
#include <ddk/ntddk.h>
#include <ddk/ntddbeep.h>
#define NDEBUG
#include <internal/debug.h>
/* TYEPEDEFS ***************************************************************/
typedef struct tagBEEP_DEVICE_EXTENSION
{
KDPC Dpc;
KTIMER Timer;
KEVENT Event;
BOOL BeepOn;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
/* FUNCTIONS ***************************************************************/
VOID BeepDPC (PKDPC Dpc, PVOID DeferredContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
PDEVICE_EXTENSION DeviceExtension = DeferredContext;
DPRINT ("BeepDPC() called!\n");
HalMakeBeep (0);
DeviceExtension->BeepOn = FALSE;
KeSetEvent (&(DeviceExtension->Event), 0, TRUE);
DPRINT ("BeepDPC() finished!\n");
}
NTSTATUS BeepCreate (PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
* FUNCTION: Handles user mode requests
* ARGUMENTS:
* DeviceObject = Device for request
* Irp = I/O request packet describing request
* RETURNS: Success or failure
*/
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status;
if (Stack->MajorFunction == IRP_MJ_CREATE)
{
DPRINT ("BeepCreate() called!\n");
Irp->IoStatus.Information = 0;
status = STATUS_SUCCESS;
}
else
status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp,IO_NO_INCREMENT);
return (status);
}
NTSTATUS BeepClose(PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
* FUNCTION: Handles user mode requests
* ARGUMENTS:
* DeviceObject = Device for request
* Irp = I/O request packet describing request
* RETURNS: Success or failure
*/
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation (Irp);
NTSTATUS status;
switch (Stack->MajorFunction)
{
case IRP_MJ_CLOSE:
DPRINT ("BeepClose() called!\n");
Irp->IoStatus.Information = 0;
status = STATUS_SUCCESS;
break;
default:
status = STATUS_NOT_IMPLEMENTED;
}
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return (status);
}
NTSTATUS BeepCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
* FUNCTION: Handles user mode requests
* ARGUMENTS:
* DeviceObject = Device for request
* Irp = I/O request packet describing request
* RETURNS: Success or failure
*/
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation (Irp);
NTSTATUS status;
if (Stack->MajorFunction == IRP_MJ_CLEANUP)
{
DPRINT ("BeepCleanup() called!\n");
Irp->IoStatus.Information = 0;
status = STATUS_SUCCESS;
}
else
status = STATUS_NOT_IMPLEMENTED;
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return (status);
}
NTSTATUS BeepDeviceControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
/*
* FUNCTION: Handles user mode requests
* ARGUMENTS:
* DeviceObject = Device for request
* Irp = I/O request packet describing request
* RETURNS: Success or failure
*/
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_EXTENSION DeviceExtension;
PBEEP_SET_PARAMETERS pbsp;
NTSTATUS status;
DeviceExtension = DeviceObject->DeviceExtension;
DPRINT ("BeepDeviceControl() called!\n");
if (Stack->Parameters.DeviceIoControl.IoControlCode == IOCTL_BEEP_SET)
{
Irp->IoStatus.Information = 0;
if (Stack->Parameters.DeviceIoControl.InputBufferLength == sizeof(BEEP_SET_PARAMETERS))
{
pbsp = (PBEEP_SET_PARAMETERS)Irp->AssociatedIrp.SystemBuffer;
if (pbsp->Frequency >= BEEP_FREQUENCY_MINIMUM &&
pbsp->Frequency <= BEEP_FREQUENCY_MAXIMUM)
{
LARGE_INTEGER DueTime;
DueTime.QuadPart = 0;
/* do the beep!! */
DPRINT ("Beep:\n Freq: %lu Hz\n Dur: %lu ms\n",
pbsp->Frequency, pbsp->Duration);
if (pbsp->Duration >= 0)
{
DueTime.QuadPart = (LONGLONG)pbsp->Duration * -10000;
KeSetTimer (&DeviceExtension->Timer,
DueTime,
&DeviceExtension->Dpc);
HalMakeBeep (pbsp->Frequency);
DeviceExtension->BeepOn = TRUE;
KeWaitForSingleObject (&(DeviceExtension->Event),
Executive,
KernelMode,
FALSE,
NULL);
}
else if (pbsp->Duration == (DWORD)-1)
{
if (DeviceExtension->BeepOn)
{
HalMakeBeep (0);
DeviceExtension->BeepOn = FALSE;
}
else
{
HalMakeBeep (pbsp->Frequency);
DeviceExtension->BeepOn = TRUE;
}
}
DPRINT ("Did the beep!\n");
status = STATUS_SUCCESS;
}
else
{
status = STATUS_INVALID_PARAMETER;
}
}
else
{
status = STATUS_INVALID_PARAMETER;
}
}
else
{
status = STATUS_NOT_IMPLEMENTED;
}
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return (status);
}
NTSTATUS BeepUnload(PDRIVER_OBJECT DriverObject)
{
DPRINT ("BeepUnload() called!\n");
return (STATUS_SUCCESS);
}
STDCALL NTSTATUS
DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
/*
* FUNCTION: Called by the system to initalize the driver
* ARGUMENTS:
* DriverObject = object describing this driver
* RegistryPath = path to our configuration entries
* RETURNS: Success or failure
*/
{
PDEVICE_OBJECT DeviceObject;
PDEVICE_EXTENSION DeviceExtension;
NTSTATUS ret;
ANSI_STRING ansi_device_name;
UNICODE_STRING device_name;
ANSI_STRING asymlink_name;
UNICODE_STRING symlink_name;
DbgPrint ("Beep Device Driver 0.0.2\n");
RtlInitAnsiString (&ansi_device_name, "\\Device\\Beep");
RtlAnsiStringToUnicodeString (&device_name, &ansi_device_name, TRUE);
ret = IoCreateDevice (DriverObject,
sizeof(DEVICE_EXTENSION),
&device_name,
FILE_DEVICE_BEEP,
0,
FALSE,
&DeviceObject);
if (ret!=STATUS_SUCCESS)
{
return (ret);
}
/* prelininary */
RtlInitAnsiString (&asymlink_name, "\\??\\Beep");
RtlAnsiStringToUnicodeString (&symlink_name, &asymlink_name, TRUE);
IoCreateSymbolicLink (&symlink_name, &device_name);
DriverObject->MajorFunction[IRP_MJ_CREATE] = BeepCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = BeepClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = BeepCleanup;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = BeepDeviceControl;
DriverObject->DriverUnload = BeepUnload;
/* set up device extension */
DeviceExtension = DeviceObject->DeviceExtension;
DeviceExtension->BeepOn = FALSE;
KeInitializeDpc (&(DeviceExtension->Dpc),
BeepDPC,
DeviceExtension);
KeInitializeTimer (&(DeviceExtension->Timer));
KeInitializeEvent (&(DeviceExtension->Event),
SynchronizationEvent,
FALSE);
return (STATUS_SUCCESS);
}
/* EOF */

View File

@@ -0,0 +1,39 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "PC Speaker Device Driver\0"
VALUE "FileVersion", "0.0.2\0"
VALUE "InternalName", "beep\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "beep.sys\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@@ -0,0 +1,71 @@
# $Id: makefile,v 1.6 1999/12/04 20:58:35 ea Exp $
#
#
TARGET = beep
OBJECTS = beep.o beep.coff ../../../ntoskrnl/ntoskrnl.a
BASE_CFLAGS = -I../../../include
all: beep.sys
.PHONY: all
clean:
- $(RM) beep.o
- $(RM) beep.coff
- $(RM) junk.tmp
- $(RM) base.tmp
- $(RM) temp.exp
- $(RM) beep.sys
.phony: clean
floppy: $(FLOPPY_DIR)/drivers/$(TARGET).sys
$(FLOPPY_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
ifeq ($(DOSCLI),yes)
$(CP) $(TARGET).sys $(FLOPPY_DIR)\drivers\$(TARGET).sys
else
$(CP) $(TARGET).sys $(FLOPPY_DIR)/drivers/$(TARGET).sys
endif
dist: ../../../$(DIST_DIR)/drivers/$(TARGET).sys
../../../$(DIST_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
ifeq ($(DOSCLI),yes)
$(CP) $(TARGET).sys ..\..\..\$(DIST_DIR)\drivers\$(TARGET).sys
else
$(CP) $(TARGET).sys ../../../$(DIST_DIR)/drivers/$(TARGET).sys
endif
beep.sys: $(OBJECTS)
$(CC) \
-specs=../../svc_specs \
-mdll \
-o junk.tmp \
-Wl,--defsym,_end=end \
-Wl,--defsym,_edata=__data_end__ \
-Wl,--defsym,_etext=etext \
-Wl,--base-file,base.tmp \
$(OBJECTS)
- $(RM) junk.tmp
$(DLLTOOL) \
--dllname beep.sys \
--base-file base.tmp \
--output-exp temp.exp \
--kill-at
- $(RM) base.tmp
$(CC) \
--verbose \
-Wl,--image-base,0x10000 \
-Wl,-e,_DriverEntry@8 \
-Wl,temp.exp \
-specs=../../svc_specs \
-mdll \
-o $(TARGET).sys \
$(OBJECTS)
- $(RM) temp.exp
include ../../../rules.mak

View File

@@ -0,0 +1,4 @@
base.tmp
junk.tmp
temp.exp

View File

@@ -0,0 +1,634 @@
/* $Id: blue.c,v 1.19 2000/01/11 17:33:44 ekohl Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/dd/blue/blue.c
* PURPOSE: Console (blue screen) device driver
* PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de)
* UPDATE HISTORY:
* ??? Created
*/
/* INCLUDES ******************************************************************/
#include <ddk/ntddk.h>
#include <ddk/ntddblue.h>
#include <string.h>
#include <defines.h>
#define NDEBUG
#include <internal/debug.h>
/* DEFINITIONS ***************************************************************/
#define IDMAP_BASE 0xd0000000
#define VIDMEM_BASE 0xb8000
#define CRTC_COMMAND ((PUCHAR)0x3d4)
#define CRTC_DATA ((PUCHAR)0x3d5)
#define CRTC_COLUMNS 0x01
#define CRTC_OVERFLOW 0x07
#define CRTC_ROWS 0x12
#define CRTC_SCANLINES 0x09
#define CRTC_CURSORSTART 0x0a
#define CRTC_CURSOREND 0x0b
#define CRTC_CURSORPOSHI 0x0e
#define CRTC_CURSORPOSLO 0x0f
#define ATTRC_WRITEREG ((PUCHAR)0x3c0)
#define ATTRC_READREG ((PUCHAR)0x3c1)
#define ATTRC_INPST1 ((PUCHAR)0x3da)
#define TAB_WIDTH 8
/* NOTES ******************************************************************/
/*
* [[character][attribute]][[character][attribute]]....
*/
/* TYPEDEFS ***************************************************************/
typedef struct _DEVICE_EXTENSION
{
PBYTE VideoMemory; /* Pointer to video memory */
DWORD CursorSize;
BOOL CursorVisible;
WORD CharAttribute;
DWORD Mode;
BYTE ScanLines; /* Height of a text line */
WORD Rows; /* Number of rows */
WORD Columns; /* Number of columns */
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
/* FUNCTIONS **************************************************************/
NTSTATUS
ScrCreate (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
unsigned int offset;
BYTE data, value;
DeviceExtension = DeviceObject->DeviceExtension;
/* initialize device extension */
/* get pointer to video memory */
/* FIXME : use MmMapIoSpace() */
DeviceExtension->VideoMemory = (PBYTE)(IDMAP_BASE + VIDMEM_BASE);
/* disable interrupts */
__asm__("cli\n\t");
/* get current output position */
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
offset = READ_PORT_UCHAR (CRTC_DATA);
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
/* switch blinking characters off */
READ_PORT_UCHAR (ATTRC_INPST1);
value = READ_PORT_UCHAR (ATTRC_WRITEREG);
WRITE_PORT_UCHAR (ATTRC_WRITEREG, 0x10);
data = READ_PORT_UCHAR (ATTRC_READREG);
data = data & ~0x08;
WRITE_PORT_UCHAR (ATTRC_WRITEREG, data);
WRITE_PORT_UCHAR (ATTRC_WRITEREG, value);
READ_PORT_UCHAR (ATTRC_INPST1);
/* read screen information from crt controller */
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_COLUMNS);
DeviceExtension->Columns = READ_PORT_UCHAR (CRTC_DATA) + 1;
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_ROWS);
DeviceExtension->Rows = READ_PORT_UCHAR (CRTC_DATA);
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_OVERFLOW);
data = READ_PORT_UCHAR (CRTC_DATA);
DeviceExtension->Rows |= (((data & 0x02) << 7) | ((data & 0x40) << 3));
DeviceExtension->Rows++;
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_SCANLINES);
DeviceExtension->ScanLines = (READ_PORT_UCHAR (CRTC_DATA) & 0x1F) + 1;
/* enable interrupts */
__asm__("sti\n\t");
/* calculate number of text rows */
DeviceExtension->Rows =
DeviceExtension->Rows / DeviceExtension->ScanLines;
DPRINT ("%d Columns %d Rows %d Scanlines\n",
DeviceExtension->Columns,
DeviceExtension->Rows,
DeviceExtension->ScanLines);
DeviceExtension->CursorSize = 5; /* FIXME: value correct?? */
DeviceExtension->CursorVisible = TRUE;
/* more initialization */
DeviceExtension->CharAttribute = 0x17; /* light grey on blue */
DeviceExtension->Mode = ENABLE_PROCESSED_OUTPUT |
ENABLE_WRAP_AT_EOL_OUTPUT;
/* show blinking cursor */
__asm__("cli\n\t");
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
WRITE_PORT_UCHAR (CRTC_DATA, (DeviceExtension->ScanLines - 1) & 0x1F);
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
data = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
WRITE_PORT_UCHAR (CRTC_DATA,
data | ((DeviceExtension->ScanLines - 1) & 0x1F));
__asm__("sti\n\t");
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return (Status);
}
NTSTATUS
ScrWrite (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
PDEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
char *pch = Irp->UserBuffer;
char *vidmem;
int i, j, offset;
int cursorx, cursory;
int rows, columns;
DeviceExtension = DeviceObject->DeviceExtension;
vidmem = DeviceExtension->VideoMemory;
rows = DeviceExtension->Rows;
columns = DeviceExtension->Columns;
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
offset = READ_PORT_UCHAR (CRTC_DATA)<<8;
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
offset += READ_PORT_UCHAR (CRTC_DATA);
cursory = offset / columns;
cursorx = offset % columns;
for (i = 0; i < stk->Parameters.Write.Length; i++, pch++)
{
switch (*pch)
{
case '\b':
if (cursorx > 0)
{
cursorx--;
}
else if (cursory > 0)
{
cursorx = columns - 1;
cursory--;
}
break;
case '\n':
cursory++;
cursorx = 0;
break;
case '\r':
break;
case '\t':
offset = TAB_WIDTH - (cursorx % TAB_WIDTH);
for (j = 0; j < offset; j++)
{
vidmem[(cursorx * 2) + (cursory * columns * 2)] = ' ';
cursorx++;
if (cursorx >= columns)
{
cursory++;
cursorx = 0;
}
}
break;
default:
vidmem[(cursorx * 2) + (cursory * columns * 2)] = *pch;
vidmem[(cursorx * 2) + (cursory * columns * 2) + 1] = (char) DeviceExtension->CharAttribute;
cursorx++;
if (cursorx >= columns)
{
cursory++;
cursorx = 0;
}
break;
}
if (cursory >= rows)
{
unsigned short *LinePtr;
memcpy (vidmem,
&vidmem[columns * 2],
columns * (rows - 1) * 2);
LinePtr = (unsigned short *) &vidmem[columns * (rows - 1) * 2];
for (j = 0; j < columns; j++)
{
LinePtr[j] = DeviceExtension->CharAttribute << 8;
}
cursory = rows - 1;
for (j = 0; j < columns; j++)
{
vidmem[(j * 2) + (cursory * columns * 2)] = ' ';
vidmem[(j * 2) + (cursory * columns * 2) + 1] = (char)DeviceExtension->CharAttribute;
}
}
}
/* Set the cursor position */
offset = (cursory * columns) + cursorx;
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
WRITE_PORT_UCHAR (CRTC_DATA, offset);
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
offset >>= 8;
WRITE_PORT_UCHAR (CRTC_DATA, offset);
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return (Status);
}
NTSTATUS
ScrIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation (Irp);
PDEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
DeviceExtension = DeviceObject->DeviceExtension;
switch (stk->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_CONSOLE_GET_SCREEN_BUFFER_INFO:
{
PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
int rows = DeviceExtension->Rows;
int columns = DeviceExtension->Columns;
unsigned int offset;
/* read cursor position from crtc */
__asm__("cli\n\t");
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
offset = READ_PORT_UCHAR (CRTC_DATA);
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
offset += (READ_PORT_UCHAR (CRTC_DATA) << 8);
__asm__("sti\n\t");
pcsbi->dwSize.X = rows;
pcsbi->dwSize.Y = columns;
pcsbi->dwCursorPosition.X = (SHORT)(offset % columns);
pcsbi->dwCursorPosition.Y = (SHORT)(offset / columns);
pcsbi->wAttributes = DeviceExtension->CharAttribute;
pcsbi->srWindow.Left = 0;
pcsbi->srWindow.Right = columns - 1;
pcsbi->srWindow.Top = 0;
pcsbi->srWindow.Bottom = rows - 1;
pcsbi->dwMaximumWindowSize.X = columns;
pcsbi->dwMaximumWindowSize.Y = rows;
Irp->IoStatus.Information = sizeof (CONSOLE_SCREEN_BUFFER_INFO);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_SET_SCREEN_BUFFER_INFO:
{
PCONSOLE_SCREEN_BUFFER_INFO pcsbi = (PCONSOLE_SCREEN_BUFFER_INFO)Irp->AssociatedIrp.SystemBuffer;
unsigned int offset;
DeviceExtension->CharAttribute = pcsbi->wAttributes;
offset = (pcsbi->dwCursorPosition.Y * DeviceExtension->Columns) +
pcsbi->dwCursorPosition.X;
__asm__("cli\n\t");
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSLO);
WRITE_PORT_UCHAR (CRTC_DATA, offset);
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORPOSHI);
WRITE_PORT_UCHAR (CRTC_DATA, offset>>8);
__asm__("sti\n\t");
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_GET_CURSOR_INFO:
{
PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
pcci->dwSize = DeviceExtension->CursorSize;
pcci->bVisible = DeviceExtension->CursorVisible;
Irp->IoStatus.Information = sizeof (CONSOLE_CURSOR_INFO);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_SET_CURSOR_INFO:
{
PCONSOLE_CURSOR_INFO pcci = (PCONSOLE_CURSOR_INFO)Irp->AssociatedIrp.SystemBuffer;
BYTE data, value;
DWORD size, height;
DeviceExtension->CursorSize = pcci->dwSize;
DeviceExtension->CursorVisible = pcci->bVisible;
height = DeviceExtension->ScanLines;
data = (pcci->bVisible) ? 0x40 : 0x20;
size = (pcci->dwSize * height) / 100;
if (size < 1)
size = 1;
data |= (BYTE)(height - size);
__asm__("cli\n\t");
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSORSTART);
WRITE_PORT_UCHAR (CRTC_DATA, data);
WRITE_PORT_UCHAR (CRTC_COMMAND, CRTC_CURSOREND);
value = READ_PORT_UCHAR (CRTC_DATA) & 0xE0;
WRITE_PORT_UCHAR (CRTC_DATA, value | (height - 1));
__asm__("sti\n\t");
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_GET_MODE:
{
PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
pcm->dwMode = DeviceExtension->Mode;
Irp->IoStatus.Information = sizeof(CONSOLE_MODE);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_SET_MODE:
{
PCONSOLE_MODE pcm = (PCONSOLE_MODE)Irp->AssociatedIrp.SystemBuffer;
DeviceExtension->Mode = pcm->dwMode;
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_FILL_OUTPUT_ATTRIBUTE:
{
POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
char *vidmem;
int offset;
DWORD dwCount;
vidmem = DeviceExtension->VideoMemory;
offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
(Buf->dwCoord.X * 2) + 1;
for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
{
vidmem[offset + (dwCount * 2)] = (char) Buf->wAttribute;
}
Buf->dwTransfered = Buf->nLength;
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_READ_OUTPUT_ATTRIBUTE:
{
POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
LPWORD pAttr = (LPWORD)MmGetSystemAddressForMdl(Irp->MdlAddress);
char *vidmem;
int offset;
DWORD dwCount;
vidmem = DeviceExtension->VideoMemory;
offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
(Buf->dwCoord.X * 2) + 1;
for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pAttr++)
{
(char) *pAttr = vidmem[offset + (dwCount * 2)];
}
Buf->dwTransfered = dwCount;
Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_WRITE_OUTPUT_ATTRIBUTE:
{
POUTPUT_ATTRIBUTE Buf = (POUTPUT_ATTRIBUTE)Irp->AssociatedIrp.SystemBuffer;
LPWORD pAttr = (LPWORD)MmGetSystemAddressForMdl(Irp->MdlAddress);
char *vidmem;
int offset;
DWORD dwCount;
vidmem = DeviceExtension->VideoMemory;
offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
(Buf->dwCoord.X * 2) + 1;
for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pAttr++)
{
vidmem[offset + (dwCount * 2)] = (char) *pAttr;
}
Buf->dwTransfered = dwCount;
Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_SET_TEXT_ATTRIBUTE:
DeviceExtension->CharAttribute = (WORD)*(LPWORD)Irp->AssociatedIrp.SystemBuffer;
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
break;
case IOCTL_CONSOLE_FILL_OUTPUT_CHARACTER:
{
POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
char *vidmem;
int offset;
DWORD dwCount;
vidmem = DeviceExtension->VideoMemory;
offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
(Buf->dwCoord.X * 2);
CHECKPOINT
for (dwCount = 0; dwCount < Buf->nLength; dwCount++)
{
vidmem[offset + (dwCount * 2)] = (char) Buf->cCharacter;
}
Buf->dwTransfered = Buf->nLength;
Irp->IoStatus.Information = 0;
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_READ_OUTPUT_CHARACTER:
{
POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress);
char *vidmem;
int offset;
DWORD dwCount;
vidmem = DeviceExtension->VideoMemory;
offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
(Buf->dwCoord.X * 2);
for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pChar++)
{
*pChar = vidmem[offset + (dwCount * 2)];
}
Buf->dwTransfered = dwCount;
Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
Status = STATUS_SUCCESS;
}
break;
case IOCTL_CONSOLE_WRITE_OUTPUT_CHARACTER:
{
POUTPUT_CHARACTER Buf = (POUTPUT_CHARACTER)Irp->AssociatedIrp.SystemBuffer;
LPSTR pChar = (LPSTR)MmGetSystemAddressForMdl(Irp->MdlAddress);
char *vidmem;
int offset;
DWORD dwCount;
vidmem = DeviceExtension->VideoMemory;
offset = (Buf->dwCoord.Y * DeviceExtension->Columns * 2) +
(Buf->dwCoord.X * 2) + 1;
for (dwCount = 0; dwCount < stk->Parameters.Write.Length; dwCount++, pChar++)
{
vidmem[offset + (dwCount * 2)] = (char) *pChar;
}
Buf->dwTransfered = dwCount;
Irp->IoStatus.Information = sizeof(OUTPUT_ATTRIBUTE);
Status = STATUS_SUCCESS;
}
break;
default:
Status = STATUS_NOT_IMPLEMENTED;
}
Irp->IoStatus.Status = Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return (Status);
}
NTSTATUS
ScrDispatch (PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS Status;
switch (stk->MajorFunction)
{
case IRP_MJ_CLOSE:
Status = STATUS_SUCCESS;
break;
default:
Status = STATUS_NOT_IMPLEMENTED;
break;
}
Irp->IoStatus.Status = Status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return (Status);
}
/*
* Module entry point
*/
NTSTATUS STDCALL
DriverEntry (PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT DeviceObject;
ANSI_STRING adevice_name;
UNICODE_STRING device_name;
ANSI_STRING asymlink_name;
UNICODE_STRING symlink_name;
DbgPrint ("Screen Driver 0.0.6\n");
DriverObject->MajorFunction[IRP_MJ_CREATE] = ScrCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScrDispatch;
DriverObject->MajorFunction[IRP_MJ_READ] = ScrDispatch;
DriverObject->MajorFunction[IRP_MJ_WRITE] = ScrWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = ScrIoControl;
RtlInitAnsiString (&adevice_name, "\\Device\\BlueScreen");
RtlAnsiStringToUnicodeString (&device_name, &adevice_name, TRUE);
IoCreateDevice (DriverObject,
sizeof(DEVICE_EXTENSION),
&device_name,
FILE_DEVICE_SCREEN,
0,
TRUE,
&DeviceObject);
RtlInitAnsiString (&asymlink_name, "\\??\\BlueScreen");
RtlAnsiStringToUnicodeString (&symlink_name, &asymlink_name, TRUE);
IoCreateSymbolicLink (&symlink_name, &device_name);
RtlFreeUnicodeString (&device_name);
RtlFreeUnicodeString (&symlink_name);
return (STATUS_SUCCESS);
}
/* EOF */

View File

@@ -0,0 +1,39 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "HAL Console Device Driver\0"
VALUE "FileVersion", "0.0.6\0"
VALUE "InternalName", "blue\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "blue.sys\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@@ -0,0 +1,70 @@
# $Id: makefile,v 1.10 1999/12/18 10:17:41 ea Exp $
#
#
TARGET = blue
BASE_CFLAGS = -I../../../include
OBJECTS = $(TARGET).o $(TARGET).coff ../../../ntoskrnl/ntoskrnl.a
all: $(TARGET).sys
.phony: all
clean:
- $(RM) $(TARGET).o
- $(RM) $(TARGET).coff
- $(RM) junk.tmp
- $(RM) base.tmp
- $(RM) temp.exp
- $(RM) blue.sys
.phony: clean
floppy: $(FLOPPY_DIR)/drivers/$(TARGET).sys
$(FLOPPY_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
ifeq ($(DOSCLI),yes)
$(CP) $(TARGET).sys $(FLOPPY_DIR)\drivers\$(TARGET).sys
else
$(CP) $(TARGET).sys $(FLOPPY_DIR)/drivers/$(TARGET).sys
endif
dist: ../../../$(DIST_DIR)/drivers/$(TARGET).sys
../../../$(DIST_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
ifeq ($(DOSCLI),yes)
$(CP) $(TARGET).sys ..\..\..\$(DIST_DIR)\drivers\$(TARGET).sys
else
$(CP) $(TARGET).sys ../../../$(DIST_DIR)/drivers/$(TARGET).sys
endif
$(TARGET).sys: $(OBJECTS)
$(CC) \
-specs=../../svc_specs \
-mdll \
-o junk.tmp \
-Wl,--defsym,_end=end \
-Wl,--defsym,_edata=__data_end__ \
-Wl,--defsym,_etext=etext \
-Wl,--base-file,base.tmp $(OBJECTS)
- $(RM) junk.tmp
$(DLLTOOL) \
--dllname $(TARGET).sys \
--base-file base.tmp \
--output-exp temp.exp \
--kill-at
- $(RM) base.tmp
$(CC) \
--verbose \
-Wl,--image-base,0x10000 \
-Wl,-e,_DriverEntry@8 \
-Wl,temp.exp \
-specs=../../svc_specs \
-mdll \
-o $(TARGET).sys \
$(OBJECTS)
- $(RM) temp.exp
include ../../../rules.mak

View File

@@ -0,0 +1,2 @@
DIRS=exe \
sys

View File

@@ -0,0 +1,168 @@
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
EventTest.c
Abstract:
Simple console test app demonstrating how a Win32 app can share
an event object with a kernel-mode driver. For more information
on using Event Objects at the application level see the Win32 SDK.
Author:
Jeff Midkiff (jeffmi) 23-Jul-96
Enviroment:
User Mode
Revision History:
--*/
//
// INCLUDES
//
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <winioctl.h>
#include <conio.h>
#include "event.h"
//
// MAIN
//
void __cdecl
main(
int argc,
char ** argv
)
{
BOOL bStatus;
HANDLE hDevice;
ULONG ulReturnedLength;
SET_EVENT setEvent;
FLOAT fDelay;
if ( (argc < 2) || (argv[1] == NULL) ) {
printf("event <delay>\n");
printf("\twhere <delay> = time to delay the event signal in seconds.\n");
exit(0);
}
sscanf( argv[1], "%f", &fDelay );
//
// open the device
//
hDevice = CreateFile(
"\\\\.\\EVENT", // lpFileName
GENERIC_READ | GENERIC_WRITE, // dwDesiredAccess
FILE_SHARE_READ | FILE_SHARE_WRITE, // dwShareMode
NULL, // lpSecurityAttributes
OPEN_EXISTING, // dwCreationDistribution
0, // dwFlagsAndAttributes
NULL // hTemplateFile
);
if (hDevice == INVALID_HANDLE_VALUE) {
printf("CreateFile error = %d\n", GetLastError() );
exit(0);
}
//
// set the event signal delay
//
setEvent.DueTime.QuadPart = -((LONGLONG)(fDelay * 10.0E6));// use relative time for this sample
//
// test the driver for bad event handles
//
setEvent.hEvent = NULL;
bStatus = DeviceIoControl(
hDevice, // Handle to device
IOCTL_SET_EVENT, // IO Control code
&setEvent, // Input Buffer to driver.
SIZEOF_SETEVENT, // Length of input buffer in bytes.
NULL, // Output Buffer from driver.
0, // Length of output buffer in bytes.
&ulReturnedLength, // Bytes placed in buffer.
NULL // synchronous call
);
if ( !bStatus ) {
printf("Bad handle TEST returned code %d.\n\n", GetLastError() );
} else {
printf("we should never get here\n");
exit(0);
}
//
//
//
setEvent.hEvent = CreateEvent(
NULL, // lpEventAttributes
TRUE, // bManualReset
FALSE, // bInitialState
NULL // lpName
);
if ( !setEvent.hEvent ) {
printf("CreateEvent error = %d\n", GetLastError() );
} else {
printf("Event HANDLE = 0x%x\n", setEvent.hEvent );
printf("Press any key to exit.\n");
while( !_kbhit() ) {
bStatus = DeviceIoControl(
hDevice, // Handle to device
IOCTL_SET_EVENT, // IO Control code
&setEvent, // Input Buffer to driver.
SIZEOF_SETEVENT, // Length of input buffer in bytes.
NULL, // Output Buffer from driver.
0, // Length of output buffer in bytes.
&ulReturnedLength, // Bytes placed in buffer.
NULL // synchronous call
);
if ( !bStatus ) {
printf("Ioctl failed with code %d\n", GetLastError() );
break;
} else {
printf("Waiting for Event...\n");
WaitForSingleObject(setEvent.hEvent,
INFINITE );
printf("Event signalled.\n\n");
ResetEvent( setEvent.hEvent);
//printf("Event reset.\n");
}
}
}
//
// close the driver
//
if ( !CloseHandle(hDevice) ) {
printf("Failed to close device.\n");
}
exit(0);
}
// EOF

View File

@@ -0,0 +1,7 @@
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#
!INCLUDE $(NTMAKEENV)\makefile.def

View File

@@ -0,0 +1,10 @@
TARGETNAME=event
TARGETPATH=$(BASEDIR)\lib
TARGETTYPE=PROGRAM
INCLUDES=..\sys
SOURCES=eventtest.c
UMTYPE=console
UMBASE=0x100000

View File

@@ -0,0 +1,50 @@
This sample demonstrates one way that a Windows NT kernel-mode device driver
can share and explicitly signal an Event Object with a Win32 application.
It is composed of two parts, a Windows NT kernel-mode device driver and a Win32
console test application. Both are built using the Windows NT DDK.
Instructions:
-------------
1) Build the driver and test application in either the FREE or CHECKED build environment:
BLD
Both the driver and application are put in %NTDDK%\LIB\*\FREE | CHECKED on your build machine.
2) Copy the newly built driver to your Target machine's %SystemRoot%\system32\drivers
directory. Copy the newly built application to your target machine.
Also copy the EVENT.INI file to your Target machine.
3) Update the Target machine's Registry by running REGINI.EXE on the EVENT.INI file, i.e.:
REGINI EVENT.INI
This adds a driver key under the
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services tree in the Registry.
You can verify this by running REGEDIT32.EXE and looking at the \Event key.
4) Reboot the Target machine for the Registry changes to take effect.
Your driver will not load until you reboot.
5) Load the driver from the command line:
NET START EVENT
6) Run the test app from the command line:
EVENT <DELAY>
where DELAY = time to delay the Event signal in seconds.
7) Unload the driver from the command line:
NET STOP EVENT

View File

@@ -0,0 +1,447 @@
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
Event.c
Abstract:
This sample demonstrates one way that a Windows NT kernel-mode driver
can share and explicitly signal an Event Object with a Win32 application.
This sample uses the following method:
The application creates an event object using CreateEvent().
The app passes the event handle to the driver in a private IOCTL.
The driver is running in the app's thread context during the IOCTL so
there is a valid user-mode handle at that time.
The driver dereferences the user-mode handle into system space & saves
the new system handle for later use.
The driver signals the event via KeSetEvent() at IRQL <= DISPATCH_LEVEL.
The driver MUST delete any driver references to the event object at
Unload time.
An alternative method would be to create a named event in the driver via
IoCreateNotificationEvent and then open the event in user mode. This API
however is new to Windows NT 4.0 so you can not use this method in your
NT 3.5x drivers.
Note that this sample's event can be signalled (almost) at will from within
the driver. A different event signal can be set when the driver is setup to
do asynchronous I/O, and it is opened with FILE_FLAG_OVERLAPPED, and an
event handle is passed down in an OVERLAPPED struct from the app's Read,
Write, or DeviceIoControl. This different event signal is set by the I/O
Manager when the driver calls IoCompleteRequest on a pending Irp. This type
of Irp completion signal is not the purpose of this sample, hence the lack of
Irp queing.
Author:
Jeff Midkiff (jeffmi) 23-Jul-96
Enviroment:
Kernel Mode Only
Revision History:
--*/
//
// INCLUDES
//
#include "ntddk.h"
#include "event.h"
//
// DEFINES
//
#define USER_NAME L"\\DosDevices\\EVENT"
#define SYSTEM_NAME L"\\Device\\EVENT"
//
// DATA
//
typedef struct _DEVICE_EXTENSION {
KDPC Dpc;
KTIMER Timer;
HANDLE hEvent;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
//
// PROTOS
//
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
NTSTATUS
Unload(
IN PDRIVER_OBJECT DriverObject
);
NTSTATUS
Dispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
CustomTimerDPC(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
This routine gets called by the system to initialize the driver.
Arguments:
DriverObject - the system supplied driver object.
RegistryPath - the system supplied registry path for this driver.
Return Value:
NTSTATUS
--*/
{
PDEVICE_OBJECT pDeviceObject;
PDEVICE_EXTENSION pDeviceExtension;
UNICODE_STRING usSystemName;
UNICODE_STRING usUserName;
NTSTATUS status;
KdPrint(("Event!DriverEntry - IN\n"));
//
// create the device object
//
RtlInitUnicodeString( &usSystemName, SYSTEM_NAME );
status = IoCreateDevice(
DriverObject, // DriverObject
sizeof( DEVICE_EXTENSION ), // DeviceExtensionSize
&usSystemName, // DeviceName
FILE_DEVICE_UNKNOWN, // DeviceType
0, // DeviceCharacteristics
TRUE, // Exclusive
&pDeviceObject // DeviceObject
);
if ( !NT_SUCCESS(status) ) {
KdPrint(("\tIoCreateDevice returned 0x%x\n", status));
return( status );
}
//
// Set up dispatch entry points for the driver.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = Dispatch;
DriverObject->DriverUnload = Unload;
//
// Create a symbolic link into user mode for the driver.
//
RtlInitUnicodeString( &usUserName, USER_NAME );
status = IoCreateSymbolicLink( &usUserName, &usSystemName );
if ( !NT_SUCCESS(status) ) {
IoDeleteDevice( pDeviceObject );
KdPrint(("\tIoCreateSymbolicLink returned 0x%x\n", status));
return( status );
}
//
// establish user-buffer access method
//
pDeviceObject->Flags |= DO_BUFFERED_IO;
//
// setup the device extension
//
pDeviceExtension = pDeviceObject->DeviceExtension;
KeInitializeDpc(
&pDeviceExtension->Dpc, // Dpc
CustomTimerDPC, // DeferredRoutine
pDeviceObject // DeferredContext
);
KeInitializeTimer(
&pDeviceExtension->Timer // Timer
);
pDeviceExtension->hEvent = NULL;
KdPrint(("Event!DriverEntry - OUT\n"));
return( status );
}
NTSTATUS
Unload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
This routine gets called to remove the driver from the system.
Arguments:
DriverObject - the system supplied driver object.
Return Value:
NTSTATUS
--*/
{
PDEVICE_OBJECT pDeviceObject = DriverObject->DeviceObject;
PDEVICE_EXTENSION pDeviceExtension = pDeviceObject->DeviceExtension;
UNICODE_STRING usUserName;
KdPrint(("Event!Unload\n"));
//
// dereference the event object or it will NEVER go away until reboot
//
if ( pDeviceExtension->hEvent )
ObDereferenceObject( pDeviceExtension->hEvent );
// Delete the user-mode symbolic link.
RtlInitUnicodeString( &usUserName, USER_NAME );
IoDeleteSymbolicLink( &usUserName );
// Delete the DeviceObject
IoDeleteDevice( pDeviceObject );
return( STATUS_SUCCESS );
}
NTSTATUS
Dispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This device control dispatcher handles IOCTLs.
Arguments:
DeviceObject - Context for the activity.
Irp - The device control argument block.
Return Value:
NTSTATUS
--*/
{
PDEVICE_EXTENSION pDeviceExtension;
PIO_STACK_LOCATION pIrpStack;
PSET_EVENT pSetEvent;
ULONG ulInformation = 0L;
NTSTATUS status = STATUS_NOT_IMPLEMENTED;
KdPrint(("Event!Dispatch - IN\n"));
pDeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
pIrpStack = IoGetCurrentIrpStackLocation( Irp );
switch( pIrpStack->MajorFunction )
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
KdPrint(("\t%s\n", (IRP_MJ_CREATE == pIrpStack->MajorFunction) ? "IRP_MJ_CREATE" : "IRP_MJ_CLOSE"));
status = STATUS_SUCCESS;
break;
case IRP_MJ_DEVICE_CONTROL:
switch( pIrpStack->Parameters.DeviceIoControl.IoControlCode )
{
case IOCTL_SET_EVENT:
KdPrint(("\tIOCTL_SET_EVENT\n"));
if ( pIrpStack->Parameters.DeviceIoControl.InputBufferLength < SIZEOF_SETEVENT ) {
// Parameters are invalid
KdPrint(("\tSTATUS_INVALID_PARAMETER\n"));
status = STATUS_INVALID_PARAMETER;
} else {
pSetEvent = (PSET_EVENT)Irp->AssociatedIrp.SystemBuffer;
KdPrint(("\tuser-mode HANDLE = 0x%x\n", pSetEvent->hEvent ));
status = ObReferenceObjectByHandle( pSetEvent->hEvent,
SYNCHRONIZE,
NULL,
KernelMode,
&pDeviceExtension->hEvent,
NULL
);
if ( !NT_SUCCESS(status) ) {
KdPrint(("\tUnable to reference User-Mode Event object, Error = 0x%x\n", status));
} else {
KdPrint(("\tkernel-mode HANDLE = 0x%x\n", pDeviceExtension->hEvent ));
//
// Start the timer to run the CustomTimerDPC in DueTime seconds to
// simulate an interrupt (which would queue a DPC).
// The user's event object is signaled in the DPC.
//
// ensure relative time for this sample
if ( pSetEvent->DueTime.QuadPart > 0 )
pSetEvent->DueTime.QuadPart = -(pSetEvent->DueTime.QuadPart);
KdPrint(("\tDueTime = %d\n", pSetEvent->DueTime.QuadPart ));
KeSetTimer(
&pDeviceExtension->Timer, // Timer
pSetEvent->DueTime, // DueTime
&pDeviceExtension->Dpc // Dpc
);
status = STATUS_SUCCESS;
}
}
break;
default:
// should never hit this
ASSERT(0);
status = STATUS_NOT_IMPLEMENTED;
break;
} // switch IoControlCode
break;
default:
// should never hit this
ASSERT(0);
status = STATUS_NOT_IMPLEMENTED;
break;
} // switch MajorFunction
//
// complete the Irp
//
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = ulInformation;
IoCompleteRequest( Irp, IO_NO_INCREMENT );
KdPrint(("Event!Dispatch - OUT\n"));
return status;
}
VOID
CustomTimerDPC(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
/*++
Routine Description:
This is the DPC associated with this drivers Timer object setup in DriverEntry.
Arguments:
Dpc - our DPC object associated with our Timer
DeferredContext - Context for the DPC that we setup in DriverEntry
SystemArgument1 -
SystemArgument2 -
Return Value:
Nothing.
--*/
{
PDEVICE_OBJECT pDeviceObject = DeferredContext;
PDEVICE_EXTENSION pDeviceExtension = pDeviceObject->DeviceExtension;
KdPrint(("Event!CustomTimerDPC - IN\n"));
//
// Signal the Event created user-mode
//
// Note:
// Do not call KeSetEvent from your ISR;
// you must call it at IRQL <= DISPATCH_LEVEL.
// Your ISR should queue a DPC and the DPC can
// then call KeSetEvent on the ISR's behalf.
//
KeSetEvent((PKEVENT)pDeviceExtension->hEvent,// Event
0, // Increment
FALSE // Wait
);
// there is no Irp to complete here
KdPrint(("Event!CustomTimerDPC - OUT\n"));
return;
}
// EOF

View File

@@ -0,0 +1,43 @@
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
Event.h
Abstract:
Author:
Jeff Midkiff (jeffmi) 23-Jul-96
Enviroment:
Revision History:
--*/
#ifndef __EVENT__
#define __EVENT__
#include "devioctl.h"
typedef struct _SET_EVENT
{
HANDLE hEvent;
LARGE_INTEGER DueTime; // requested DueTime in 100-nanosecond units
} SET_EVENT, *PSET_EVENT;
#define SIZEOF_SETEVENT sizeof(SET_EVENT)
#define IOCTL_SET_EVENT \
CTL_CODE( FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS )
#endif // __EVENT__

View File

@@ -0,0 +1,7 @@
; note - the service name matches the driver's file (.sys) name
\Registry\Machine\System\CurrentControlSet\Services\Event
Type = REG_DWORD 0x00000001
Start = REG_DWORD 0x00000003
Group = Extended Base
ErrorControl = REG_DWORD 0x00000001

View File

@@ -0,0 +1,11 @@
#include <windows.h>
#include <ntverp.h>
#define VER_FILETYPE VFT_DRV
#define VER_FILESUBTYPE VFT2_DRV_SYSTEM
#define VER_FILEDESCRIPTION_STR "Sample Event Driver"
#define VER_INTERNALNAME_STR "event.sys"
#include "common.ver"

View File

@@ -0,0 +1,7 @@
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#
!INCLUDE $(NTMAKEENV)\makefile.def

View File

@@ -0,0 +1,6 @@
TARGETNAME=event
TARGETPATH=$(BASEDIR)\lib
TARGETTYPE=DRIVER
SOURCES=event.c \
event.rc

View File

@@ -0,0 +1,444 @@
//
// FLOPPY.C - NEC-765/8272A floppy device driver
// written by Rex Jolliff
// with help from various other sources, including but not limited to:
// Art Baker's NT Device Driver Book, Linux Source, and the internet.
//
// Modification History:
// 08/19/98 RJJ Created.
//
// To do:
// FIXME: get it working
// FIXME: add support for DMA hardware
// FIXME: should add support for floppy tape/zip devices
#include <ddk/ntddk.h>
#include "floppy.h"
#define VERSION "V0.0.1"
// --------------------------------------------------- File Statics
typedef struct _FLOPPY_CONTROLLER_PARAMETERS
{
int PortBase;
int Vector;
int IrqL;
int SynchronizeIrqL;
KINTERRUPT_MODE InterruptMode;
KAFFINITY Affinity;
} FLOPPY_CONTROLLER_PARAMETERS, *PFLOPPY_CONTROLLER_PARAMETERS;
#define FLOPPY_MAX_CONTROLLERS 2
FLOPPY_CONTROLLER_PARAMETERS ControllerParameters[FLOPPY_MAX_CONTROLLERS] =
{
{0x03f0, 6, 6, 6, LevelSensitive, 0xffff},
{0x0370, 6, 6, 6, LevelSensitive, 0xffff},
};
FLOPPY_DEVICE_PARAMETERS DeviceTypes[] =
{
/* Unknown */
{0, 500, 16, 16, 8000, 1000, 3000, 0, 20, 5, 80, 3000, 20, {3,1,2,0,2}, 0, 0, { 7, 4, 8, 2, 1, 5, 3,10}, 1500, 0, "unknown"},
/* 5 1/4 360 KB PC*/
{1, 300, 16, 16, 8000, 1000, 3000, 0, 20, 5, 40, 3000, 17, {3,1,2,0,2}, 0, 0, { 1, 0, 0, 0, 0, 0, 0, 0}, 1500, 1, "360K PC"},
/* 5 1/4 HD AT*/
{2, 500, 16, 16, 6000, 400, 3000, 14, 20, 6, 83, 3000, 17, {3,1,2,0,2}, 0, 0, { 2, 5, 6,23,10,20,11, 0}, 1500, 2, "1.2M"},
/* 3 1/2 DD*/
{3, 250, 16, 16, 3000, 1000, 3000, 0, 20, 5, 83, 3000, 20, {3,1,2,0,2}, 0, 0, { 4,22,21,30, 3, 0, 0, 0}, 1500, 4, "720k"},
/* 3 1/2 HD*/
{4, 500, 16, 16, 4000, 400, 3000, 10, 20, 5, 83, 3000, 20, {3,1,2,0,2}, 0, 0, { 7, 4,25,22,31,21,29,11}, 1500, 7, "1.44M"},
/* 3 1/2 ED*/
{5, 1000, 15, 8, 3000, 400, 3000, 10, 20, 5, 83, 3000, 40, {3,1,2,0,2}, 0, 0, { 7, 8, 4,25,28,22,31,21}, 1500, 8, "2.88M AMI BIOS"},
/* 3 1/2 ED*/
{6, 1000, 15, 8, 3000, 400, 3000, 10, 20, 5, 83, 3000, 40, {3,1,2,0,2}, 0, 0, { 7, 8, 4,25,28,22,31,21}, 1500, 8, "2.88M"}
};
static BOOLEAN FloppyInitialized = FALSE;
// ------------------------------------------------------ Functions
// ModuleEntry
//
// DESCRIPTION:
// This function initializes the driver, locates and claims
// hardware resources, and creates various NT objects needed
// to process I/O requests.
//
// RUN LEVEL:
// PASSIVE_LEVEL
//
// ARGUMENTS:
// IN PDRIVER_OBJECT DriverObject System allocated Driver Object
// for this driver
// IN PUNICODE_STRING RegistryPath Name of registry driver service
// key
//
// RETURNS:
// NTSTATUS
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
NTSTATUS RC;
PFLOPPY_DEVICE_EXTENSION DeviceExtension;
// Export other driver entry points...
DriverObject->DriverStartIo = FloppyStartIo;
DriverObject->MajorFunction[IRP_MJ_CREATE] = FloppyDispatchOpenClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FloppyDispatchOpenClose;
DriverObject->MajorFunction[IRP_MJ_READ] = FloppyDispatchReadWrite;
DriverObject->MajorFunction[IRP_MJ_WRITE] = FloppyDispatchReadWrite;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FloppyDispatchDeviceControl;
// Try to detect controller and abort if it fails
if (!FloppyCreateController(DriverObject,
&ControllerParameters[0],
0))
{
DPRINT("Could not find floppy controller");
return STATUS_NO_SUCH_DEVICE;
}
return STATUS_SUCCESS;
}
static BOOLEAN
FloppyCreateController(PDRIVER_OBJECT DriverObject,
PFLOPPY_CONTROLLER_PARAMETERS ControllerParameters,
int Index)
{
PFLOPPY_CONTROLLER_TYPE ControllerType;
PCONTROLLER_OBJECT ControllerObject;
PFLOPPY_CONTROLLER_EXTENSION ControllerExtension;
/* Detect controller and determine type */
if (!FloppyGetControllerVersion(ControllerParameters, &ControllerType))
{
return FALSE;
}
// FIXME: Register port ranges and interrupts with HAL
/* Create controller object for FDC */
ControllerObject = IoCreateController(sizeof(FLOPPY_CONTROLLER_EXTENSION));
if (ControllerObject == NULL)
{
DPRINT("Could not create controller object for controller %d\n",
Index);
return FALSE;
}
// FIXME: fill out controller data
ControllerExtension = (PFLOPPY_CONTROLLER_EXTENSION)
ControllerObject->ControllerExtension;
ControllerExtension->Number = Index;
ControllerExtension->PortBase = ControllerParameters->PortBase;
ControllerExtension->Vector = ControllerParameters->Vector;
ControllerExtension->FDCType = ControllerType;
/* Initialize the spin lock in the controller extension */
KeInitializeSpinLock(&ControllerExtension->SpinLock);
/* Register an interrupt handler for this controller */
RC = IoConnectInterrupt(&ControllerExtension->Interrupt,
FloppyIsr,
ControllerExtension,
&ControllerExtension->SpinLock,
ControllerExtension->Vector,
ControllerParameters->IrqL,
ControllerParameters->SynchronizeIrqL,
ControllerParameters->InterruptMode,
FALSE,
ControllerParameters->Affinity,
FALSE);
if (!NT_SUCCESS(RC))
{
DPRINT("Could not Connect Interrupt %d\n", ControllerExtension->Vector);
IoDeleteController(ControllerObject);
return FALSE;
}
// FIXME: setup DMA stuff for controller
// Check for each possible drive and create devices for them
for (DriveIdx = 0; DriveIdx < FLOPPY_MAX_DRIVES; DriveIdx++)
{
// FIXME: try to identify the drive
// FIXME: create a device if it's there
}
return STATUS_SUCCESS;
}
// FloppyGetControllerVersion
//
// DESCRIPTION
// Get the type/version of the floppy controller
//
// RUN LEVEL:
// PASSIVE_LEVEL
//
// ARGUMENTS:
// IN OUT PFLOPPY_DEVICE_EXTENSION DeviceExtension
//
// RETURNS:
// BOOL success or failure
//
// COMMENTS:
// This routine (get_fdc_version) was originally written by David C. Niemi
//
static BOOLEAN
FloppyGetControllerVersion(IN PFLOPPY_CONTROLLER_PARAMETERS ControllerParameters,
OUT PFLOPPY_CONTROLLER_TYPE ControllerType)
{
BYTE ResultReturned
BYTE Result[FLOPPY_MAX_REPLIES];
int ResultLength;
/* 82072 and better know DUMPREGS */
if (!FloppyWriteCommandByte(ControllerParameters->PortBase,
FLOPPY_CMD_DUMP_FDC))
{
return FALSE;
}
ResultLength = FloppyReadResultCode(PortBase, &Result));
if (ResultLength < 0)
{
return FALSE;
}
/* 8272a/765 don't know DUMPREGS */
if ((ResultLength == 1) && (Result[0] == 0x80))
{
DPRINT("FDC %d is an 8272A\n", PortBase);
*ControllerType = FDC_8272A;
return TRUE;
}
if (r != 10)
{
DPRINT("FDC %d init: DUMP_FDC: unexpected return of %d bytes.\n",
PortBase,
ResultLength);
return FALSE;
}
if (!FloppyConfigure(PortBase, FALSE, 0x0a))
{
DPRINT("FDC %d is an 82072\n", PortBase);
*ControllerType = FDC_82072;
return TRUE;
}
FloppyWriteCommandByte(PortBase, FLOPPY_CMD_PPND_RW);
if (FloppyNeedsMoreOutput(PortBase, Result) == FLOPPY_NEEDS_OUTPUT)
{
FloppyWriteCommandByte(PortBase, 0);
}
else
{
DPRINT("FDC %d is an 82072A\n", PortBase);
*ControllerType = FDC_82072A;
return TRUE;
}
/* Pre-1991 82077, doesn't know LOCK/UNLOCK */
FloppyWriteCommandByte(PortBase, FLOPPY_CMD_UNLK_FIFO);
ResultLength = FloppyReadResultCode(PortBase, &Result));
if ((ResultLength == 1) && (Result[0] == 0x80))
{
DPRINT("FDC %d is a pre-1991 82077\n", PortBase);
*ControllerType = FDC_82077_ORIG;
return TRUE;
}
if ((ResultLength != 1) || (Result[0] != 0x00))
{
DPRINT("FDC %d init: UNLOCK: unexpected return of %d bytes.\n",
PortBase,
ResultLength);
return FALSE;
}
/* Revised 82077AA passes all the tests */
FloppyWriteCommandByte(PortBase, FLOPPY_CMD_PARTID);
ResultLength = FloppyReadResultCode(PortBase, &Result));
if (ResultLength != 1)
{
DPRINT("FDC %d init: PARTID: unexpected return of %d bytes.\n",
PortBase,
ResultLength);
return FALSE;
}
if (Result[0] == 0x80)
{
DPRINT("FDC %d is a post-1991 82077\n", PortBase);
*ControllerType = FDC_82077;
return TRUE;
}
switch (Result[0] >> 5)
{
case 0x0:
/* Either a 82078-1 or a 82078SL running at 5Volt */
DPRINT("FDC %d is an 82078.\n", PortBase);
*ControllerType = FDC_82078;
return TRUE;
case 0x1:
DPRINT("FDC %d is a 44pin 82078\n", PortBase);
*ControllerType = FDC_82078;
return TRUE;
case 0x2:
DPRINT("FDC %d is a S82078B\n", PortBase);
*ControllerType = FDC_S82078B;
return TRUE;
case 0x3:
DPRINT("FDC %d is a National Semiconductor PC87306\n", PortBase);
*ControllerType = FDC_87306;
return TRUE;
default:
DPRINT("FDC %d init: 82078 variant with unknown PARTID=%d.\n",
PortBase,
Result[0] >> 5);
*ControllerType = FDC_82078_UNKN;
return TRUE;
}
}
/* sends a command byte to the fdc */
static BOOLEAN
FloppyWriteCommandByte(WORD PortBase, BYTE Byte)
{
int Status;
if ((Status = FloppyWaitUntilReady()) < 0)
{
return FALSE;
}
if ((Status & (STATUS_READY|STATUS_DIR|STATUS_DMA)) == STATUS_READY)
{
FloppyWriteData(PortBase, Byte);
return 0;
}
if (FloppyInitialized)
{
DPRINT("Unable to send byte %x to FDC. Fdc=%x Status=%x\n",
Byte,
PortBase,
Status);
}
return FALSE;
}
/* gets the response from the fdc */
static int
FloppyReadResultCode(WORD PortBase, PBYTE Result)
{
int Replies;
int Status;
for (Replies = 0; Replies < FLOPPY_MAX_REPLIES; Replies++)
{
if ((Status = FloppyWaitUntilReady(PortBase)) < 0)
{
break;
}
Status &= STATUS_DIR | STATUS_READY | STATUS_BUSY | STATUS_DMA;
if ((Status & ~STATUS_BUSY) == STATUS_READY)
{
return Replies;
}
if (Status == (STATUS_DIR | STATUS_READY | STATUS_BUSY))
{
Result[Replies] = fd_inb(FD_DATA);
}
else
{
break;
}
}
if (FloppyInitialized)
{
DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
PortBase,
Status,
Replies);
}
return -1;
}
/* waits until the fdc becomes ready */
static int
FloppyWaitUntilReady(WORD PortBase)
{
int Retries;
int Status;
for (Retries = 0; Retries < FLOPPY_MAX_STAT_RETRIES; Retries++)
{
status = FloppyReadSTAT(PortBase);
if (Status & STATUS_READY)
{
return Status;
}
}
if (FloppyInitialized)
{
DPRINT("Getstatus times out (%x) on fdc %d\n",
Status,
PortBase);
}
return -1;
}
#define MORE_OUTPUT -2
/* does the fdc need more output? */
static int
FloppyNeedsMoreOutput(WORD PortBase, PBYTE Result)
{
int Status;
if ((Status = FloppyWaitUntilReady(PortBase)) < 0)
return -1;
if ((Status & (STATUS_READY | STATUS_DIR | STATUS_DMA)) == STATUS_READY)
{
return FLOPPY_NEEDS_OUTPUT;
}
return FloppyReadResultCode(PortBase, Result);
}
static BOOLEAN
FloppyConfigure(WORD PortBase, BOOLEAN DisableFIFO, BYTE FIFODepth)
{
BYTE Result[FLOPPY_MAX_REPLIES];
/* Turn on FIFO */
FloppyWriteCommandByte(FLOPPY_CMD_CFG_FIFO);
if (FloppyNeedsOutput(PortBase, Result) != FLOPPY_NEEDS_OUTPUT)
{
return FALSE;
}
FloppyWriteCommandByte(PortBase, 0);
FloppyWriteCommandByte(PortBase,
0x10 |
(DisableFIFO ? 0x20 : 0x00) |
(FIFODepth & 0x0f));
/* pre-compensation from track 0 upwards */
FloppyWriteCommandByte(PortBase, 0);
return TRUE;
}

View File

@@ -0,0 +1,158 @@
#define FLOPPY_MAX_STAT_RETRIES 10000
#define FLOPPY_NEEDS_OUTPUT -2
//
// Floppy register definitions
//
#define FLOPPY_REG_DOR 0x0002
#define FLOPPY_REG_MSTAT 0x0004
#define FLOPPY_MS_DRV0BUSY 0x01
#define FLOPPY_MS_DRV1BUSY 0x02
#define FLOPPY_MS_DRV2BUSY 0x04
#define FLOPPY_MS_DRV3BUSY 0x08
#define FLOPPY_MS_FDCBUSY 0x10
#define FLOPPY_MS_DMAMODE 0x20
#define FLOPPY_MS_DATADIR 0x40
#define FLOPPY_MS_DATARDY 0x80
#define FLOPPY_REG_DATA 0x0005
#define FLOPPY_REG_DIR 0x0007 /* READ ONLY */
#define FLOPPY_DI_DSKCHNG 0x80
#define FLOPPY_REG_CCNTL 0x0007 /* WRITE ONLY */
#define FLOPPY_CMD_RD_TRK 0x02
#define FLOPPY_CMD_SPEC_CHARS 0x03
#define FLOPPY_CSC_SRT_SHIFT 4
#define FLOPPY_CSC_HUT_MASK 0x0f
#define FLOPPY_CSC_HLT_SHIFT 1
#define FLOPPY_CSC_NON_DMA 0x01
#define FLOPPY_CMD_SNS_DRV 0x04
#define FLOPPY_CMD_WRT_DATA 0x05
#define FLOPPY_CMD_RD_DATA 0x06
#define FLOPPY_CMD_RECAL 0x07
#define FLOPPY_CMD_SNS_INTR 0x08
#define FLOPPY_CSI_IC_MASK 0xe0
#define FLOPPY_CSI_IC_RDYCH 0x60
#define FLOPPY_CSI_IC_SEEKGD 0x80
#define FLOPPY_CSI_IC_SEEKBD 0xc0
#define FLOPPY_CMD_WRT_DEL 0x09
#define FLOPPY_CMD_RD_ID 0x0a
#define FLOPPY_CMD_RD_DEL 0x0c
#define FLOPPY_CMD_FMT_TRK 0x0d
#define FLOPPY_CMD_DUMP_FDC 0x0e
#define FLOPPY_CMD_SEEK 0x0f
#define FLOPPY_CMD_VERSION 0x10
#define FLOPPY_CMD_SCN_EQ 0x11
#define FLOPPY_CMD_PPND_RW 0x12
#define FLOPPY_CMD_CFG_FIFO 0x13
#define FLOPPY_CMD_LCK_FIFO 0x14
#define FLOPPY_CMD_PARTID 0x18
#define FLOPPY_CMD_SCN_LE 0x19
#define FLOPPY_CMD_SCN_GE 0x1d
#define FLOPPY_CMD_CFG_PWR 0x27
#define FLOPPY_CMD_SAVE_FDC 0x2e
#define FLOPPY_CMD_FMT_ISO 0x33
#define FLOPPY_CMD_DMA_READ 0x46
#define FLOPPY_CMD_DMA_WRT 0x4a
#define FLOPPY_CMD_REST_FDC 0x4e
#define FLOPPY_CMD_DRV_SPEC 0x8e
#define FLOPPY_CMD_RSEEK_OUT 0x8f
#define FLOPPY_CMD_ULK_FIFO 0x94
#define FLOPPY_CMD_RSEEK_IN 0xcf
#define FLOPPY_CMD_FMT_WRT 0xef
// Command Code modifiers
#define FLOPPY_C0M_SK 0x20
#define FLOPPY_C0M_MFM 0x40
#define FLOPPY_C0M_MT 0x80
#define FLOPPY_C1M_DRVMASK 0x03
#define FLOPPY_C1M_HEAD1 0x04
// Status code values and masks
#define FLOPPY_ST0_INVALID 0x80
// useful command defines
#define FLOPPY_CMD_READ (FLOPPY_CMD_RD_DATA | FLOPPY_C0M_SK | FLOPPY_C0M_MFM | FLOPPY_C0M_MT)
#define FLOPPY_CMD_WRITE (FLOPPY_CMD_WRT_DATA | FLOPPY_C0M_MFM | FLOPPY_C0M_MT)
#define FLOPPY_CMD_FORMAT (FLOPPY_CMD_FMT_TRK | FLOPPY_C0M_MFM)
//
// HAL floppy register access commands
//
#define FloppyWriteDOR(A, V) (WRITE_BYTE((A) + FLOPPY_REG_DOR, (V)))
#define FloppyReadMSTAT(A) (READ_BYTE((A) + FLOPPY_REG_MSTAT))
#define FloppyReadDATA(A) (READ_BYTE((A) + FLOPPY_REG_DATA))
#define FloppyWriteDATA(A, V) (WRITE_BYTE((A) + FLOPPY_REG_DATA, (V)))
#define FloppyReadDIR(A) (READ_BYTE((A) + FLOPPY_REG_DIR))
#define FloppyWriteCCNTL(A, V) (WRITE_BYTE((A) + FLOPPY_REG_CCNTL, (V)))
//
// Known Floppy controller types
//
typedef enum _FLOPPY_CONTROLLER_TYPE
{
FDC_NONE,
FDC_UNKNOWN,
FDC_8272A, /* Intel 8272a, NEC 765 */
FDC_765ED, /* Non-Intel 1MB-compatible FDC, can't detect */
FDC_82072, /* Intel 82072; 8272a + FIFO + DUMPREGS */
FDC_82072A, /* 82072A (on Sparcs) */
FDC_82077_ORIG, /* Original version of 82077AA, sans LOCK */
FDC_82077, /* 82077AA-1 */
FDC_82078_UNKN, /* Unknown 82078 variant */
FDC_82078, /* 44pin 82078 or 64pin 82078SL */
FDC_82078_1, /* 82078-1 (2Mbps fdc) */
FDC_S82078B, /* S82078B (first seen on Adaptec AVA-2825 VLB SCSI/EIDE/Floppy controller) */
FDC_87306 /* National Semiconductor PC 87306 */
} FLOPPY_CONTROLLER_TYPE, *PFLOPPY_CONTROLLER_TYPE;
typedef struct _FLOPPY_ERROR_THRESHOLDS
{
/* number of errors to be reached before aborting */
unsigned int Abort;
/* maximal number of errors permitted to read an entire track at once */
unsigned int ReadTrack;
/* maximal number of errors before a reset is tried */
unsigned int Reset;
/* maximal number of errors before a recalibrate is tried */
unsigned int Recal;
/*
* Threshold for reporting FDC errors to the console.
* Setting this to zero may flood your screen when using
* ultra cheap floppies ;-)
*/
unsigned int Reporting;
} FLOPPY_ERROR_THRESHOLDS;
#define FDP_DEBUG 0x02
#define FDP_SILENT_DCL_CLEAR 0x04
#define FDP_MSG 0x10
#define FDP_BROKEN_DCL 0x20
#define FDP_INVERTED_DCL 0x80
typedef struct _FLOPPY_DEVICE_PARAMETERS
{
char CMOSType;
unsigned long MaxDTR; /* Step rate, usec */
unsigned long HLT; /* Head load/settle time, msec */
unsigned long HUT; /* Head unload time (remnant of 8" drives) */
unsigned long SRT; /* Step rate, usec */
unsigned long Spinup; /* time needed for spinup */
unsigned long Spindown; /* timeout needed for spindown */
unsigned char SpindownOffset; /* decides in which position the disk will stop */
unsigned char SelectDelay; /* delay to wait after select */
unsigned char RPS; /* rotations per second */
unsigned char Tracks; /* maximum number of tracks */
unsigned long Timeout; /* timeout for interrupt requests */
unsigned char InterleaveSect; /* if there are more sectors, use interleave */
FLOPPY_ERROR_THRESHOLDS MaxErrors;
char Flags; /* various flags, including ftd_msg */
BOOLEAN ReadTrack; /* use readtrack during probing? */
short Autodetect[8]; /* autodetected formats */
int CheckFreq; /* how often should the drive be checked for disk changes */
int NativeFormat; /* native format of this drive */
char *DriveName; /* name of the drive for reporting */
} FLOPPY_DEVICE_PARAMETERS, *PFLOPPY_DEVICE_PARAMETERS;

View File

@@ -0,0 +1,3 @@
base.tmp
junk.tmp
temp.exp

2058
reactos/drivers/dd/ide/ide.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
//
// IDE.H - defines and typedefs for the IDE Driver module.
//
#ifndef __IDE_H
#define __IDE_H
#ifdef __cplusplus
extern "C" {
#endif
#define IDE_MAXIMUM_DEVICES 8
#define IDE_MAX_NAME_LENGTH 50
#define IDE_NT_ROOTDIR_NAME "\\Device"
#define IDE_NT_DEVICE_NAME "\\Harddisk"
#define IDE_NT_PARTITION_NAME "\\Partition"
#define IDE_WIN32_DEVICE_NAME "\\DosDevices\\IDE"
#define IDE_DRIVER_NAME "IDEDRIVER"
#define IDE_SECTOR_BUF_SZ 512
#define IDE_MAX_SECTORS_PER_XFER 256
#define IDE_MAX_RESET_RETRIES 10000
#define IDE_MAX_POLL_RETRIES 100000
#define IDE_MAX_WRITE_RETRIES 1000
#define IDE_MAX_BUSY_RETRIES 100
//#define IDE_MAX_BUSY_RETRIES 100000
#define IDE_MAX_DRQ_RETRIES 10000
//#define IDE_MAX_CMD_RETRIES 1
#define IDE_MAX_CMD_RETRIES 0
#define IDE_CMD_TIMEOUT 5
#define IDE_RESET_PULSE_LENGTH 500 /* maybe a little too long */
#define IDE_RESET_BUSY_TIMEOUT 31
#define IDE_RESET_DRDY_TIMEOUT 120
// Control Block offsets and masks
#define IDE_REG_ALT_STATUS 0x0000
#define IDE_REG_DEV_CNTRL 0x0000 /* device control register */
#define IDE_DC_SRST 0x04 /* drive reset (both drives) */
#define IDE_DC_nIEN 0x02 /* IRQ enable (active low) */
#define IDE_REG_DRV_ADDR 0x0001
// Command Block offsets and masks
#define IDE_REG_DATA_PORT 0x0000
#define IDE_REG_ERROR 0x0001 /* error register */
#define IDE_ER_AMNF 0x01 /* addr mark not found */
#define IDE_ER_TK0NF 0x02 /* track 0 not found */
#define IDE_ER_ABRT 0x04 /* command aborted */
#define IDE_ER_MCR 0x08 /* media change requested */
#define IDE_ER_IDNF 0x10 /* ID not found */
#define IDE_ER_MC 0x20 /* Media changed */
#define IDE_ER_UNC 0x40 /* Uncorrectable data error */
#define IDE_REG_PRECOMP 0x0001
#define IDE_REG_SECTOR_CNT 0x0002
#define IDE_REG_SECTOR_NUM 0x0003
#define IDE_REG_CYL_LOW 0x0004
#define IDE_REG_CYL_HIGH 0x0005
#define IDE_REG_DRV_HEAD 0x0006
#define IDE_DH_FIXED 0xA0
#define IDE_DH_LBA 0x40
#define IDE_DH_HDMASK 0x0F
#define IDE_DH_DRV0 0x00
#define IDE_DH_DRV1 0x10
#define IDE_REG_STATUS 0x0007
#define IDE_SR_BUSY 0x80
#define IDE_SR_DRDY 0x40
#define IDE_SR_DRQ 0x08
#define IDE_SR_ERR 0x01
#define IDE_REG_COMMAND 0x0007
#define IDE_CMD_READ 0x20
#define IDE_CMD_READ_RETRY 0x21
#define IDE_CMD_WRITE 0x30
#define IDE_CMD_WRITE_RETRY 0x31
#define IDE_CMD_IDENT_DRV 0xEC
//
// Access macros for command registers
// Each macro takes an address of the command port block, and data
//
#define IDEReadError(Address) (inb_p((Address) + IDE_REG_ERROR))
#define IDEWritePrecomp(Address, Data) (outb_p((Address) + IDE_REG_PRECOMP, (Data)))
#define IDEReadSectorCount(Address) (inb_p((Address) + IDE_REG_SECTOR_CNT))
#define IDEWriteSectorCount(Address, Data) (outb_p((Address) + IDE_REG_SECTOR_CNT, (Data)))
#define IDEReadSectorNum(Address) (inb_p((Address) + IDE_REG_SECTOR_NUM))
#define IDEWriteSectorNum(Address, Data) (outb_p((Address) + IDE_REG_SECTOR_NUM, (Data)))
#define IDEReadCylinderLow(Address) (inb_p((Address) + IDE_REG_CYL_LOW))
#define IDEWriteCylinderLow(Address, Data) (outb_p((Address) + IDE_REG_CYL_LOW, (Data)))
#define IDEReadCylinderHigh(Address) (inb_p((Address) + IDE_REG_CYL_HIGH))
#define IDEWriteCylinderHigh(Address, Data) (outb_p((Address) + IDE_REG_CYL_HIGH, (Data)))
#define IDEReadDriveHead(Address) (inb_p((Address) + IDE_REG_DRV_HEAD))
#define IDEWriteDriveHead(Address, Data) (outb_p((Address) + IDE_REG_DRV_HEAD, (Data)))
#define IDEReadStatus(Address) (inb_p((Address) + IDE_REG_STATUS))
#define IDEWriteCommand(Address, Data) (outb_p((Address) + IDE_REG_COMMAND, (Data)))
//
// Data block read and write commands
//
#define IDEReadBlock(Address, Buffer, Count) \
(insw((Address) + IDE_REG_DATA_PORT, (Buffer), (Count) / 2))
#define IDEWriteBlock(Address, Buffer, Count) \
(outsw((Address) + IDE_REG_DATA_PORT, (Buffer), (Count) / 2))
//
// Access macros for control registers
// Each macro takes an address of the control port blank and data
//
#define IDEWriteDriveControl(Address, Data) (outb_p((Address) + IDE_REG_DEV_CNTRL, (Data)))
// IDE_DEVICE_EXTENSION
//
// DESCRIPTION:
// Extension to be placed in each device object
//
// ACCESS:
// Allocated from NON-PAGED POOL
// Available at any IRQL
//
typedef struct _IDE_DEVICE_EXTENSION {
PDEVICE_OBJECT DeviceObject;
PCONTROLLER_OBJECT ControllerObject;
struct _IDE_DEVICE_EXTESION *DiskExtension;
int UnitNumber;
BOOLEAN LBASupported;
BOOLEAN DMASupported;
int BytesPerSector;
int LogicalHeads;
int SectorsPerLogCyl;
int SectorsPerLogTrk;
int Offset;
int Size;
int Operation;
ULONG BytesRequested;
ULONG BytesToTransfer;
ULONG BytesRemaining;
ULONG StartingSector;
int SectorsTransferred;
BYTE *TargetAddress;
} IDE_DEVICE_EXTENSION, *PIDE_DEVICE_EXTENSION;
// IDE_TIMER_STATES
//
// DESCRIPTION:
// An enumeration containing the states in the timer DFA
//
typedef enum _IDE_TIMER_STATES {
IDETimerIdle,
IDETimerCmdWait,
IDETimerResetWaitForBusyNegate,
IDETimerResetWaitForDrdyAssert
} IDE_TIMER_STATES;
// IDE_CONTROLLER_EXTENSION
//
// DESCRIPTION:
// Driver-defined structure used to hold miscellaneous controller information.
//
// ACCESS:
// Allocated from NON-PAGED POOL
// Available at any IRQL
//
typedef struct _IDE_CONTROLLER_EXTENSION {
KSPIN_LOCK SpinLock;
int Number;
int Vector;
int CommandPortBase;
int ControlPortBase;
BOOLEAN DMASupported;
BOOLEAN ControllerInterruptBug;
PKINTERRUPT Interrupt;
BOOLEAN OperationInProgress;
BYTE DeviceStatus;
PIDE_DEVICE_EXTENSION DeviceForOperation;
PIRP CurrentIrp;
int Retries;
IDE_TIMER_STATES TimerState;
LONG TimerCount;
PDEVICE_OBJECT TimerDevice;
} IDE_CONTROLLER_EXTENSION, *PIDE_CONTROLLER_EXTENSION;
// IDE_DRIVE_IDENTIFY
typedef struct _IDE_DRIVE_IDENTIFY {
WORD ConfigBits; /*00*/
WORD LogicalCyls; /*01*/
WORD Reserved02; /*02*/
WORD LogicalHeads; /*03*/
WORD BytesPerTrack; /*04*/
WORD BytesPerSector; /*05*/
WORD SectorsPerTrack; /*06*/
BYTE InterSectorGap; /*07*/
BYTE InterSectorGapSize;
BYTE Reserved08H; /*08*/
BYTE BytesInPLO;
WORD VendorUniqueCnt; /*09*/
char SerialNumber[20]; /*10*/
WORD ControllerType; /*20*/
WORD BufferSize; /*21*/
WORD ECCByteCnt; /*22*/
char FirmwareRev[8]; /*23*/
char ModelNumber[40]; /*27*/
WORD RWMultImplemented; /*47*/
WORD Reserved48; /*48*/
WORD Capabilities; /*49*/
#define IDE_DRID_STBY_SUPPORTED 0x2000
#define IDE_DRID_IORDY_SUPPORTED 0x0800
#define IDE_DRID_IORDY_DISABLE 0x0400
#define IDE_DRID_LBA_SUPPORTED 0x0200
#define IDE_DRID_DMA_SUPPORTED 0x0100
WORD Reserved50; /*50*/
WORD MinPIOTransTime; /*51*/
WORD MinDMATransTime; /*52*/
WORD TMFieldsValid; /*53*/
WORD TMCylinders; /*54*/
WORD TMHeads; /*55*/
WORD TMSectorsPerTrk; /*56*/
WORD TMCapacity; /*57*/
WORD Reserved53[198]; /*58*/
} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;
#ifdef __cplusplus
}
#endif
#endif /* __IDE_H */

View File

@@ -0,0 +1,39 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "IDE Disk Device Driver\0"
VALUE "FileVersion", "0.1.4\0"
VALUE "InternalName", "ide\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "ide.sys\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@@ -0,0 +1,20 @@
#define IOCTL_DISK_GET_DRIVE_GEOMETRY CTL_CODE(FILE_DEVICE_DISK, 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_GET_PARTITION_INFO CTL_CODE(FILE_DEVICE_DISK, 1, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DISK_SET_PARTITION_INFO CTL_CODE(FILE_DEVICE_DISK, 2, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_DISK_GET_DRIVE_LAYOUT CTL_CODE(FILE_DEVICE_DISK, 3, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_DISK_SET_DRIVE_LAYOUT CTL_CODE(FILE_DEVICE_DISK, 4, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_DISK_VERIFY CTL_CODE(FILE_DEVICE_DISK, 5, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_FORMAT_TRACKS CTL_CODE(FILE_DEVICE_DISK, 6, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_DISK_REASSIGN_BLOCKS CTL_CODE(FILE_DEVICE_DISK, 7, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_DISK_PERFORMANCE CTL_CODE(FILE_DEVICE_DISK, 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_IS_WRITABLE CTL_CODE(FILE_DEVICE_DISK, 9, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_LOGGING CTL_CODE(FILE_DEVICE_DISK, 10, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_FORMAT_TRACKS_EX CTL_CODE(FILE_DEVICE_DISK, 11, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_DISK_HISTOGRAM_STRUCTURE CTL_CODE(FILE_DEVICE_DISK, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_HISTOGRAM_DATA CTL_CODE(FILE_DEVICE_DISK, 13, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_HISTOGRAM_RESET CTL_CODE(FILE_DEVICE_DISK, 14, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_REQUEST_STRUCTURE CTL_CODE(FILE_DEVICE_DISK, 15, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_DISK_REQUEST_DATA CTL_CODE(FILE_DEVICE_DISK, 16, METHOD_BUFFERED, FILE_ANY_ACCESS)

View File

@@ -0,0 +1,69 @@
# $Id: makefile,v 1.10 1999/12/18 10:17:41 ea Exp $
#
#
TARGET=ide
OBJECTS = $(TARGET).o $(TARGET).coff ../../../ntoskrnl/ntoskrnl.a
BASE_CFLAGS = -I../../../include
all: $(TARGET).sys
.phony: all
clean:
- $(RM) $(TARGET).o
- $(RM) $(TARGET).coff
- $(RM) junk.tmp
- $(RM) base.tmp
- $(RM) temp.exp
- $(RM) $(TARGET).sys
.phony: clean
floppy: $(FLOPPY_DIR)/drivers/$(TARGET).sys
$(FLOPPY_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
ifeq ($(DOSCLI),yes)
$(CP) $(TARGET).sys $(FLOPPY_DIR)\drivers\$(TARGET).sys
else
$(CP) $(TARGET).sys $(FLOPPY_DIR)/drivers/$(TARGET).sys
endif
dist: ../../../$(DIST_DIR)/drivers/$(TARGET).sys
../../../$(DIST_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
ifeq ($(DOSCLI),yes)
$(CP) $(TARGET).sys ..\..\..\$(DIST_DIR)\drivers\$(TARGET).sys
else
$(CP) $(TARGET).sys ../../../$(DIST_DIR)/drivers/$(TARGET).sys
endif
$(TARGET).sys: $(OBJECTS)
$(CC) \
-specs=../../svc_specs \
-mdll \
-o junk.tmp \
-Wl,--defsym,_end=end \
-Wl,--defsym,_edata=__data_end__ \
-Wl,--defsym,_etext=etext \
-Wl,--base-file,base.tmp $(OBJECTS)
- $(RM) junk.tmp
$(DLLTOOL) \
--dllname $(TARGET).sys \
--base-file base.tmp \
--output-exp temp.exp \
--kill-at
- $(RM) base.tmp
$(CC) \
--verbose \
-Wl,--image-base,0x10000 \
-Wl,-e,_DriverEntry@8 \
-Wl,temp.exp \
-specs=../../svc_specs \
-mdll \
-o $(TARGET).sys \
$(OBJECTS)
- $(RM) temp.exp
include ../../../rules.mak

View File

@@ -0,0 +1,93 @@
/**
*** Partition.h - defines and structs for harddrive partition info
***
*** 05/30/98 RJJ Created
**/
#ifndef __PARTITION_H
#define __PARTITION_H
#define PARTITION_MAGIC 0xaa55
#define PART_MAGIC_OFFSET 0x01fe
#define PARTITION_OFFSET 0x01be
#define PARTITION_TBL_SIZE 4
#define PTCHSToLBA(c, h, s, scnt, hcnt) ((s) & 0x3f) + \
(scnt) * ( (h) + (hcnt) * ((c) | (((s) & 0xc0) << 2)))
#define PTLBAToCHS(lba, c, h, s, scnt, hcnt) ( \
(s) = (lba) % (scnt) + 1, \
(lba) /= (scnt), \
(h) = (lba) % (hcnt), \
(lba) /= (heads), \
(c) = (lba) & 0xff, \
(s) |= ((lba) >> 2) & 0xc0)
/* taken from linux fdisk src */
typedef enum PartitionTypes {
PTEmpty = 0,
PTDOS3xPrimary, /* 1 */
PTXENIXRoot, /* 2 */
PTXENIXUsr, /* 3 */
PTOLDDOS16Bit, /* 4 */
PTDosExtended, /* 5 */
PTDos5xPrimary, /* 6 */
PTOS2HPFS, /* 7 */
PTAIX, /* 8 */
PTAIXBootable, /* 9 */
PTOS2BootMgr, /* 10 */
PTWin95FAT32,
PTWin95FAT32LBA,
PTWin95FAT16LBA,
PTWin95ExtendedLBA,
PTVenix286 = 0x40,
PTNovell = 0x51,
PTMicroport = 0x52,
PTGnuHurd = 0x63,
PTNetware286 = 0x64,
PTNetware386 = 0x65,
PTPCIX = 0x75,
PTOldMinix = 0x80,
PTMinix = 0x81,
PTLinuxSwap = 0x82,
PTLinuxExt2 = 0x83,
PTAmoeba = 0x93,
PTAmoebaBBT = 0x94,
PTBSD = 0xa5,
PTBSDIFS = 0xb7,
PTBSDISwap = 0xb8,
PTSyrinx = 0xc7,
PTCPM = 0xdb,
PTDOSAccess = 0xe1,
PTDOSRO = 0xe3,
PTDOSSecondary = 0xf2,
PTBBT = 0xff
} PARTITIONTYPES;
#define PartitionIsSupported(P) \
((P)->PartitionType == PTDOS3xPrimary || \
(P)->PartitionType == PTOLDDOS16Bit || \
(P)->PartitionType == PTDos5xPrimary || \
(P)->PartitionType == PTWin95FAT32 || \
(P)->PartitionType == PTWin95FAT32LBA || \
(P)->PartitionType == PTWin95FAT16LBA || \
(P)->PartitionType == PTLinuxExt2)
#define PartitionIsExtended(P) \
((P)->PartitionType == PTDosExtended)
typedef struct Partition {
unsigned char BootFlags;
unsigned char StartingHead;
unsigned char StartingSector;
unsigned char StartingCylinder;
unsigned char PartitionType;
unsigned char EndingHead;
unsigned char EndingSector;
unsigned char EndingCylinder;
unsigned int StartingBlock;
unsigned int SectorCount;
} PARTITION;
#endif // PARTITION_H

View File

@@ -0,0 +1,4 @@
base.tmp
junk.tmp
temp.exp

View File

@@ -0,0 +1,732 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: services/dd/keyboard/keyboard.c
* PURPOSE: Keyboard driver
* PROGRAMMER: Victor Kirhenshtein (sauros@iname.com)
* Jason Filby (jasonfilby@yahoo.com)
*/
/* INCLUDES ****************************************************************/
#include <ddk/ntddk.h>
#include <internal/mmhal.h>
#include <internal/halio.h>
#include <string.h>
#include <internal/string.h>
#include <defines.h>
#define NDEBUG
#include <internal/debug.h>
#include "keyboard.h"
/* GLOBALS *******************************************************************/
/*
* Driver data
*/
static KEY_EVENT_RECORD kbdBuffer[KBD_BUFFER_SIZE];
static int bufHead,bufTail;
static int keysInBuffer;
static int extKey;
static BYTE ledStatus;
static BYTE capsDown,numDown,scrollDown;
static DWORD ctrlKeyState;
static PKINTERRUPT KbdInterrupt;
static KDPC KbdDpc;
static BOOLEAN AlreadyOpened = FALSE;
/*
* PURPOSE: Current irp being processed
*/
static PIRP CurrentIrp;
/*
* PURPOSE: Number of keys that have been read into the current irp's buffer
*/
static ULONG KeysRead;
static ULONG KeysRequired;
/*
* Virtual key codes table
*
* Comments:
* * PrtSc = VK_PRINT
* * Alt+PrtSc (SysRq) = VK_EXECUTE
* * Alt = VK_MENU
*/
static const WORD vkTable[128]=
{
/* 00 - 07 */ 0, VK_ESCAPE, VK_1, VK_2, VK_3, VK_4, VK_5, VK_6,
/* 08 - 0F */ VK_7, VK_8, VK_9, VK_0, 189, 187, VK_BACK, VK_TAB,
/* 10 - 17 */ VK_Q, VK_W, VK_E, VK_R, VK_T, VK_Y, VK_U, VK_I,
/* 18 - 1F */ VK_O, VK_P, 219, 221, VK_RETURN, VK_CONTROL, VK_A, VK_S,
/* 20 - 27 */ VK_D, VK_F, VK_G, VK_H, VK_J, VK_K, VK_L, 186,
/* 28 - 2F */ 222, 192, VK_SHIFT, 220, VK_Z, VK_X, VK_C, VK_V,
/* 30 - 37 */ VK_B, VK_N, VK_M, 188, 190, 191, VK_SHIFT, VK_MULTIPLY,
/* 38 - 3F */ VK_MENU, VK_SPACE, VK_CAPITAL, VK_F1, VK_F2, VK_F3, VK_F4, VK_F5,
/* 40 - 47 */ VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, VK_NUMLOCK, VK_SCROLL, VK_HOME,
/* 48 - 4F */ VK_UP, VK_PRIOR, VK_SUBTRACT, VK_LEFT, VK_CLEAR, VK_RIGHT, VK_ADD, VK_END,
/* 50 - 57 */ VK_DOWN, VK_NEXT, VK_INSERT, VK_DELETE, VK_EXECUTE, 0, 0, VK_F11,
/* 58 - 5F */ VK_F12, 0, 0, 91, 92, 93, 0, 0,
/* 60 - 67 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 68 - 6F */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 70 - 77 */ 0, 0, 0, 0, 0, 0, 0, 0,
/* 78 - 7F */ 0, 0, 0, 0, 0, 0, 0, VK_PAUSE
};
static const WORD vkKeypadTable[13]= /* 47 - 53 */
{
VK_NUMPAD7, VK_NUMPAD8, VK_NUMPAD9, VK_SUBTRACT,
VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_ADD,
VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, VK_NUMPAD0, VK_DECIMAL
};
/*
* ASCII translation tables
*/
static const BYTE asciiTable1[10]=
{
')','!','@','#','$','%','^','&','*','('
};
static const BYTE asciiTable2[16]=
{
'0','1','2','3','4','5','6','7','8','9','*','+',0,'-','.','/'
};
static const BYTE asciiTable3[37]=
{
';','=',',','-','.','/','`', 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'[', '\\', ']', '\''
};
static const BYTE asciiTable4[37]=
{
':','+','<','_','>','?','~', 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
'{', '|', '}', '"'
};
/* FUNCTIONS *****************************************************************/
static void KbdWrite(int addr,BYTE data)
/*
* FUNCTION: Write data to keyboard
*/
{
BYTE status;
do
{
status=inb_p(KBD_CTRL_PORT); // Wait until input buffer empty
} while(status & KBD_IBF);
outb_p(addr,data);
}
static int KbdReadData(void)
/*
* FUNCTION: Read data from port 0x60
*/
{
int i;
BYTE status,data;
i=500000;
do
{
status=inb_p(KBD_CTRL_PORT);
if (!(status & KBD_OBF)) // Check if data available
continue;
data=inb_p(KBD_DATA_PORT);
if (status & (KBD_GTO | KBD_PERR)) // Check for timeout error
continue;
return data;
} while(--i);
return -1; // Timed out
}
/*
* Set keyboard LED's
*/
static void SetKeyboardLEDs(BYTE status)
{
KbdWrite(KBD_DATA_PORT,0xED);
if (KbdReadData()!=KBD_ACK) // Error
return;
KbdWrite(KBD_DATA_PORT,status);
KbdReadData();
}
/*
* Process scan code
*/
static void ProcessScanCode(BYTE scanCode,BOOL isDown)
{
switch(scanCode)
{
case 0x1D: // Ctrl
if (extKey)
{
if (isDown)
ctrlKeyState|=RIGHT_CTRL_PRESSED;
else
ctrlKeyState&=~RIGHT_CTRL_PRESSED;
}
else
{
if (isDown)
ctrlKeyState|=LEFT_CTRL_PRESSED;
else
ctrlKeyState&=~LEFT_CTRL_PRESSED;
}
break;
case 0x2A: // Left shift
case 0x36: // Right shift
if (isDown)
ctrlKeyState|=SHIFT_PRESSED;
else
ctrlKeyState&=~SHIFT_PRESSED;
break;
case 0x38: // Alt
if (extKey)
{
if (isDown)
ctrlKeyState|=RIGHT_ALT_PRESSED;
else
ctrlKeyState&=~RIGHT_ALT_PRESSED;
}
else
{
if (isDown)
ctrlKeyState|=LEFT_ALT_PRESSED;
else
ctrlKeyState&=~LEFT_ALT_PRESSED;
}
break;
case 0x3A: // CapsLock
if (ctrlKeyState & CTRL_PRESSED)
break;
if (isDown)
{
if (!capsDown)
{
capsDown=1;
if (ctrlKeyState & CAPSLOCK_ON)
{
ledStatus&=~KBD_LED_CAPS;
ctrlKeyState&=~CAPSLOCK_ON;
}
else
{
ledStatus|=KBD_LED_CAPS;
ctrlKeyState|=CAPSLOCK_ON;
}
SetKeyboardLEDs(ledStatus);
}
}
else
{
capsDown=0;
}
break;
case 0x45: // NumLock
if (ctrlKeyState & CTRL_PRESSED)
break;
if (isDown)
{
if (!numDown)
{
numDown=1;
if (ctrlKeyState & NUMLOCK_ON)
{
ledStatus&=~KBD_LED_NUM;
ctrlKeyState&=~NUMLOCK_ON;
}
else
{
ledStatus|=KBD_LED_NUM;
ctrlKeyState|=NUMLOCK_ON;
}
SetKeyboardLEDs(ledStatus);
}
}
else
{
numDown=0;
}
break;
case 0x46: // ScrollLock
if (ctrlKeyState & CTRL_PRESSED)
break;
if (isDown)
{
if (!scrollDown)
{
scrollDown=1;
if (ctrlKeyState & SCROLLLOCK_ON)
{
ledStatus&=~KBD_LED_SCROLL;
ctrlKeyState&=~SCROLLLOCK_ON;
}
else
{
ledStatus|=KBD_LED_SCROLL;
ctrlKeyState|=SCROLLLOCK_ON;
}
SetKeyboardLEDs(ledStatus);
}
}
else
{
scrollDown=0;
}
break;
default:
break;
}
}
/*
* Translate virtual key code to ASCII
*/
static BYTE VirtualToAscii(WORD keyCode,BOOL isDown)
{
if ((ctrlKeyState & ALT_PRESSED)&&(ctrlKeyState & CTRL_PRESSED))
return 0; // Ctrl+Alt+char always 0
if ((!isDown)&&(ctrlKeyState & ALT_PRESSED))
return 0; // Alt+char is 0 when key is released
if (ctrlKeyState & CTRL_PRESSED)
{
if ((keyCode>=VK_A)&&(keyCode<=VK_Z))
return keyCode-VK_A+1;
switch(keyCode)
{
case VK_SPACE:
return ' ';
case VK_BACK:
return 127;
case VK_RETURN:
return 10;
case 219: /* [ */
if (ctrlKeyState & SHIFT_PRESSED)
return 0;
return 27;
case 220: /* \ */
if (ctrlKeyState & SHIFT_PRESSED)
return 0;
return 28;
case 221: /* ] */
if (ctrlKeyState & SHIFT_PRESSED)
return 0;
return 29;
default:
return 0;
}
}
if ((keyCode>=VK_A)&&(keyCode<=VK_Z))
{
if (ctrlKeyState & CAPSLOCK_ON)
if (ctrlKeyState & SHIFT_PRESSED)
return keyCode-VK_A+'a';
else
return keyCode-VK_A+'A';
else
if (ctrlKeyState & SHIFT_PRESSED)
return keyCode-VK_A+'A';
else
return keyCode-VK_A+'a';
}
if ((keyCode>=VK_0)&&(keyCode<=VK_9))
{
if (ctrlKeyState & SHIFT_PRESSED)
return asciiTable1[keyCode-VK_0];
else
return keyCode-VK_0+'0';
}
if ((keyCode>=VK_NUMPAD0)&&(keyCode<=VK_DIVIDE))
return asciiTable2[keyCode-VK_NUMPAD0];
if ((keyCode>=186)&&(keyCode<=222))
{
if (ctrlKeyState & SHIFT_PRESSED)
return asciiTable4[keyCode-186];
else
return asciiTable3[keyCode-186];
}
switch(keyCode)
{
case VK_SPACE:
return ' ';
case VK_RETURN:
return '\n';
case VK_BACK:
return 8;
case VK_TAB:
return 9;
}
return 0;
}
/*
* Translate scan code to virtual key code
*/
static WORD ScanToVirtual(BYTE scanCode)
{
if ((scanCode>=0x47)&&(scanCode<=0x53)&&(ctrlKeyState & NUMLOCK_ON)&&
(!extKey)&&(!(ctrlKeyState & SHIFT_PRESSED)))
return vkKeypadTable[scanCode-0x47];
if ((scanCode==0x35)&&(extKey)) // Gray divide
return VK_DIVIDE;
if ((scanCode==0x37)&&(extKey)) // Print screen
return VK_PRINT;
return vkTable[scanCode];
}
/*
* Keyboard IRQ handler
*/
static VOID KbdDpcRoutine(PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2)
{
PIRP Irp = (PIRP)SystemArgument2;
PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)SystemArgument1;
CHECKPOINT;
DPRINT("KbdDpcRoutine(DeviceObject %x, Irp %x)\n",
DeviceObject,Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
IoStartNextPacket(DeviceObject,FALSE);
}
static BOOLEAN KeyboardHandler(PKINTERRUPT Interrupt, PVOID Context)
{
BYTE thisKey;
BOOL isDown;
static BYTE lastKey;
CHECKPOINT;
// Read scan code
thisKey=inb_p(KBD_DATA_PORT);
if ((thisKey==0xE0)||(thisKey==0xE1)) // Extended key
{
extKey=1; // Wait for next byte
lastKey=thisKey;
return FALSE;
}
isDown=!(thisKey & 0x80);
thisKey&=0x7F;
// The keyboard maintains its own internal caps lock and num lock
// statuses. In caps lock mode E0 AA precedes make code and
// E0 2A follow break code. In num lock mode, E0 2A precedes
// make code and E0 AA follow break code. We maintain our own caps lock
// and num lock statuses, so we will just ignore these.
// Some keyboards have L-Shift/R-Shift modes instead of caps lock
// mode. If right shift pressed, E0 B6 / E0 36 pairs generated.
if (extKey & ((thisKey==0x2A)||(thisKey==0x36)))
{
extKey=0;
return FALSE;
}
// Check for PAUSE sequence
if (extKey && (lastKey==0xE1))
{
if (thisKey==0x1D)
lastKey=0xFF; // Sequence is OK
else
extKey=0;
return FALSE;
}
if (extKey && (lastKey==0xFF))
{
if (thisKey!=0x45)
{
extKey=0; // Bad sequence
return FALSE;
}
thisKey=0x7F; // Pseudo-code for PAUSE
}
ProcessScanCode(thisKey,isDown);
// DbgPrint("Key: %c\n",VirtualToAscii(ScanToVirtual(thisKey),isDown));
// DbgPrint("Key: %x\n",ScanToVirtual(thisKey));
if (ScanToVirtual(thisKey)==0x2a)
{
KeBugCheck(0);
}
if (CurrentIrp!=NULL)
{
KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)
CurrentIrp->AssociatedIrp.SystemBuffer;
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(CurrentIrp);
CHECKPOINT;
rec[KeysRead].bKeyDown=isDown;
rec[KeysRead].wRepeatCount=1;
rec[KeysRead].wVirtualKeyCode=ScanToVirtual(thisKey);
rec[KeysRead].wVirtualScanCode=thisKey;
rec[KeysRead].uChar.AsciiChar=VirtualToAscii(rec->wVirtualKeyCode,isDown);
rec[KeysRead].dwControlKeyState=ctrlKeyState;
if (extKey)
{
rec[KeysRead].dwControlKeyState|=ENHANCED_KEY;
}
KeysRead++;
DPRINT("KeysRequired %d KeysRead %x\n",KeysRequired,KeysRead);
if (KeysRead==KeysRequired)
{
KeInsertQueueDpc(&KbdDpc,stk->DeviceObject,CurrentIrp);
CurrentIrp=NULL;
}
CHECKPOINT;
return TRUE;
}
// Buffer is full ?
if (keysInBuffer==KBD_BUFFER_SIZE) // Buffer is full
{
extKey=0;
return(TRUE);
}
kbdBuffer[bufHead].bKeyDown=isDown;
kbdBuffer[bufHead].wRepeatCount=1;
kbdBuffer[bufHead].wVirtualKeyCode=ScanToVirtual(thisKey);
kbdBuffer[bufHead].wVirtualScanCode=thisKey;
kbdBuffer[bufHead].uChar.UnicodeChar=0;
// kbdBuffer[bufHead].uChar.AsciiChar=TranslateScanCode(thisKey);
kbdBuffer[bufHead].uChar.AsciiChar=VirtualToAscii(kbdBuffer[bufHead].wVirtualKeyCode,isDown);
kbdBuffer[bufHead].dwControlKeyState=ctrlKeyState;
if (extKey)
kbdBuffer[bufHead].dwControlKeyState|=ENHANCED_KEY;
bufHead++;
bufHead&=KBD_WRAP_MASK; // Modulo KBD_BUFFER_SIZE
keysInBuffer++;
extKey=0;
return TRUE;
}
//
// Initialize keyboard
//
static void KeyboardConnectInterrupt(void)
{
ULONG MappedIrq;
KIRQL Dirql;
KAFFINITY Affinity;
NTSTATUS Status;
MappedIrq = HalGetInterruptVector(Internal,
0,
0,
KEYBOARD_IRQ,
&Dirql,
&Affinity);
Status = IoConnectInterrupt(&KbdInterrupt,
KeyboardHandler,
NULL,
NULL,
MappedIrq,
Dirql,
Dirql,
0,
FALSE,
Affinity,
FALSE);
}
static int InitializeKeyboard(void)
{
// Initialize variables
bufHead=0;
bufTail=0;
keysInBuffer=0;
ledStatus=0;
capsDown=0;
numDown=0;
scrollDown=0;
ctrlKeyState=0;
extKey=0;
KeyboardConnectInterrupt();
KeInitializeDpc(&KbdDpc,KbdDpcRoutine,NULL);
return 0;
}
/*
* Read data from keyboard buffer
*/
BOOLEAN KbdSynchronizeRoutine(PVOID Context)
{
PIRP Irp = (PIRP)Context;
KEY_EVENT_RECORD* rec = (KEY_EVENT_RECORD *)Irp->AssociatedIrp.SystemBuffer;
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
ULONG NrToRead = stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
int i;
DPRINT("NrToRead %d keysInBuffer %d\n",NrToRead,keysInBuffer);
NrToRead = min(NrToRead,keysInBuffer);
DPRINT("NrToRead %d stk->Parameters.Read.Length %d\n",
NrToRead,stk->Parameters.Read.Length);
DPRINT("sizeof(KEY_EVENT_RECORD) %d\n",sizeof(KEY_EVENT_RECORD));
for (i=0;i<NrToRead;i++)
{
memcpy(&rec[i],&kbdBuffer[bufTail],sizeof(KEY_EVENT_RECORD));
bufTail++;
bufTail&=KBD_WRAP_MASK;
keysInBuffer--;
}
if ((stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD))==NrToRead)
{
return(TRUE);
}
KeysRequired=stk->Parameters.Read.Length/sizeof(KEY_EVENT_RECORD);
KeysRead=NrToRead;
CurrentIrp=Irp;
return(FALSE);
}
VOID KbdStartIo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
#ifndef NDEBUG
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
#endif
DPRINT("KeyboardStartIo(DeviceObject %x Irp %x)\n",DeviceObject,Irp);
if (KeSynchronizeExecution(KbdInterrupt, KbdSynchronizeRoutine, Irp))
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoStartNextPacket(DeviceObject, FALSE);
}
DPRINT("stk->Parameters.Read.Length %d\n",stk->Parameters.Read.Length);
DPRINT("KeysRequired %d\n",KeysRequired);
}
NTSTATUS KbdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION stk = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS Status;
DPRINT("DeviceObject %x\n",DeviceObject);
DPRINT("Irp %x\n",Irp);
DPRINT("IRP_MJ_CREATE %d stk->MajorFunction %d\n",
IRP_MJ_CREATE, stk->MajorFunction);
DPRINT("AlreadyOpened %d\n",AlreadyOpened);
switch (stk->MajorFunction)
{
case IRP_MJ_CREATE:
if (AlreadyOpened == TRUE)
{
CHECKPOINT;
// Status = STATUS_UNSUCCESSFUL;
Status = STATUS_SUCCESS;
}
else
{
CHECKPOINT;
Status = STATUS_SUCCESS;
AlreadyOpened = TRUE;
}
break;
case IRP_MJ_CLOSE:
Status = STATUS_SUCCESS;
break;
case IRP_MJ_READ:
DPRINT("Handling Read request\n");
DPRINT("Queueing packet\n");
IoStartPacket(DeviceObject,Irp,NULL,NULL);
Status = STATUS_PENDING;
break;
default:
Status = STATUS_NOT_IMPLEMENTED;
break;
}
if (Status==STATUS_PENDING)
{
DPRINT("Marking irp pending\n");
IoMarkIrpPending(Irp);
}
else
{
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
}
DPRINT("Status %d\n",Status);
return(Status);
}
NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath)
/*
* FUNCTION: Module entry point
*/
{
PDEVICE_OBJECT DeviceObject;
UNICODE_STRING DeviceName;
UNICODE_STRING SymlinkName;
DbgPrint("Keyboard Driver 0.0.4\n");
InitializeKeyboard();
DriverObject->MajorFunction[IRP_MJ_CREATE] = KbdDispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = KbdDispatch;
DriverObject->MajorFunction[IRP_MJ_READ] = KbdDispatch;
DriverObject->DriverStartIo = KbdStartIo;
RtlInitUnicodeString(&DeviceName, L"\\Device\\Keyboard");
IoCreateDevice(DriverObject,
0,
&DeviceName,
FILE_DEVICE_KEYBOARD,
0,
TRUE,
&DeviceObject);
DeviceObject->Flags = DeviceObject->Flags | DO_BUFFERED_IO;
RtlInitUnicodeString(&SymlinkName, L"\\??\\Keyboard");
IoCreateSymbolicLink(&SymlinkName, &DeviceName);
return(STATUS_SUCCESS);
}

View File

@@ -0,0 +1,67 @@
/*
* Some defines
*/
#define KEYBOARD_IRQ 1
#define KBD_BUFFER_SIZE 32
#define KBD_WRAP_MASK 0x1F
#define disable() __asm__("cli\n\t")
#define enable() __asm__("sti\n\t")
#define ALT_PRESSED (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)
#define CTRL_PRESSED (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)
/*
* Keyboard controller ports
*/
#define KBD_DATA_PORT 0x60
#define KBD_CTRL_PORT 0x64
/*
* Controller commands
*/
#define KBD_READ_MODE 0x20
#define KBD_WRITE_MODE 0x60
#define KBD_SELF_TEST 0xAA
#define KBD_LINE_TEST 0xAB
#define KBD_CTRL_ENABLE 0xAE
/*
* Keyboard commands
*/
#define KBD_ENABLE 0xF4
#define KBD_DISABLE 0xF5
#define KBD_RESET 0xFF
/*
* Keyboard responces
*/
#define KBD_ACK 0xFA
#define KBD_BATCC 0xAA
/*
* Controller status register bits
*/
#define KBD_OBF 0x01
#define KBD_IBF 0x02
#define KBD_GTO 0x40
#define KBD_PERR 0x80
/*
* LED bits
*/
#define KBD_LED_SCROLL 0x01
#define KBD_LED_NUM 0x02
#define KBD_LED_CAPS 0x04

View File

@@ -0,0 +1,39 @@
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "Keyboard Device Driver\0"
VALUE "FileVersion", "0.0.4\0"
VALUE "InternalName", "keyboard\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "keyboard.sys\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@@ -0,0 +1,70 @@
# $Id: makefile,v 1.8 1999/12/18 10:17:42 ea Exp $
#
#
TARGET=keyboard
OBJECTS = $(TARGET).o $(TARGET).coff ../../../ntoskrnl/ntoskrnl.a
BASE_CFLAGS = -I../../../include
all: $(TARGET).sys
.phony: all
clean:
- $(RM) $(TARGET).o
- $(RM) $(TARGET).coff
- $(RM) junk.tmp
- $(RM) base.tmp
- $(RM) temp.exp
- $(RM) $(TARGET).sys
.phony: clean
floppy: $(FLOPPY_DIR)/drivers/$(TARGET).sys
$(FLOPPY_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
ifeq ($(DOSCLI),yes)
$(CP) $(TARGET).sys $(FLOPPY_DIR)\drivers\$(TARGET).sys
else
$(CP) $(TARGET).sys $(FLOPPY_DIR)/drivers/$(TARGET).sys
endif
dist: ../../../$(DIST_DIR)/drivers/$(TARGET).sys
../../../$(DIST_DIR)/drivers/$(TARGET).sys: $(TARGET).sys
ifeq ($(DOSCLI),yes)
$(CP) $(TARGET).sys ..\..\..\$(DIST_DIR)\drivers\$(TARGET).sys
else
$(CP) $(TARGET).sys ../../../$(DIST_DIR)/drivers/$(TARGET).sys
endif
$(TARGET).sys: $(OBJECTS)
$(CC) \
-specs=../../svc_specs \
-mdll \
-o junk.tmp \
-Wl,--defsym,_end=end \
-Wl,--defsym,_edata=__data_end__ \
-Wl,--defsym,_etext=etext \
-Wl,--base-file,base.tmp \
$(OBJECTS)
- $(RM) junk.tmp
$(DLLTOOL) \
--dllname $(TARGET).sys \
--base-file base.tmp \
--output-exp temp.exp \
--kill-at
- $(RM) base.tmp
$(CC) \
--verbose \
-Wl,--image-base,0x10000 \
-Wl,-e,_DriverEntry@8 \
-Wl,temp.exp \
-specs=../../svc_specs \
-mdll \
-o $(TARGET).sys \
$(OBJECTS)
- $(RM) temp.exp
include ../../../rules.mak

Some files were not shown because too many files have changed in this diff Show More