* Copyright 1998 Ulrich Weigand
*/
+
+/* Note: the heap data structures are based on what Pietrek describes in his
+ * book 'Windows 95 System Programming Secrets'. The layout is not exactly
+ * the same, but could be easily adapted if it turns out some programs
+ * require it.
+ */
+
#include <string.h>
#include <ddk/ntddk.h>
#include <ntdll/rtl.h>
#define NDEBUG
#include <ntdll/ntdll.h>
-CRITICAL_SECTION ProcessHeapsLock;
+#define DPRINTF DPRINT
+#define ERR DPRINT
+#define SetLastError(x)
+#define WARN DPRINT
+#define TRACE DPRINT
+#define WARN_ON(x) (1)
+
+#ifdef NDEBUG
+#define TRACE_ON(x) (0)
+#define assert(x)
+#else
+#define TRACE_ON(x) (1)
+#define assert(x)
+#endif
+
+
+static CRITICAL_SECTION RtlpProcessHeapsListLock;
-/* Note: the heap data structures are based on what Pietrek describes in his
- * book 'Windows 95 System Programming Secrets'. The layout is not exactly
- * the same, but could be easily adapted if it turns out some programs
- * require it.
- */
typedef struct tagARENA_INUSE
{
DWORD size; /* Block size; must be the first field */
WORD threadId; /* Allocating thread id */
WORD magic; /* Magic number */
- DWORD callerEIP; /* EIP of caller upon allocation */
+ void *callerEIP; /* EIP of caller upon allocation */
} ARENA_INUSE;
typedef struct tagARENA_FREE
#define ARENA_INUSE_FILLER 0x55
#define ARENA_FREE_FILLER 0xaa
+#define QUIET 1 /* Suppress messages */
+#define NOISY 0 /* Report all errors */
+
#define HEAP_NB_FREE_LISTS 4 /* Number of free lists */
/* Max size of the blocks on the free lists */
CRITICAL_SECTION critSection; /* Critical section for serialization */
DWORD flags; /* Heap flags */
DWORD magic; /* Magic number */
+ void *private; /* Private pointer for the user of the heap */
} HEAP;
#define HEAP_MAGIC ((DWORD)('H' | ('E'<<8) | ('A'<<16) | ('P'<<24)))
#define HEAP_DEF_SIZE 0x110000 /* Default heap size = 1Mb + 64Kb */
#define HEAP_MIN_BLOCK_SIZE (8+sizeof(ARENA_FREE)) /* Min. heap block size */
+#define COMMIT_MASK 0xffff /* bitmask for commit/decommit granularity */
+#if 0
+HANDLE SystemHeap = 0;
+HANDLE SegptrHeap = 0;
+#endif
+
+#ifdef __WINE__
+SYSTEM_HEAP_DESCR *SystemHeapDescr = 0;
+#endif
+
+#if 0
+static HEAP *processHeap; /* main process heap */
+static HEAP *firstHeap; /* head of secondary heaps list */
+#endif
+
+#if 0
+/* address where we try to map the system heap */
+#define SYSTEM_HEAP_BASE ((void*)0x65430000)
+#endif
+
+static BOOL HEAP_IsRealArena( HANDLE heap, DWORD flags, LPCVOID block, BOOL quiet );
+
+#ifdef __GNUC__
+#define GET_EIP() (__builtin_return_address(0))
+#define SET_EIP(ptr) ((ARENA_INUSE*)(ptr) - 1)->callerEIP = GET_EIP()
+#else
+#define GET_EIP() 0
+#define SET_EIP(ptr) /* nothing */
+#endif /* __GNUC__ */
/***********************************************************************
* HEAP_Dump
SUBHEAP *subheap;
char *ptr;
- DPRINT( "Heap: %08lx\n", (DWORD)heap );
- DPRINT( "Next: %08lx Sub-heaps: %08lx",
+ DPRINTF( "Heap: %08lx\n", (DWORD)heap );
+ DPRINTF( "Next: %08lx Sub-heaps: %08lx",
(DWORD)heap->next, (DWORD)&heap->subheap );
subheap = &heap->subheap;
while (subheap->next)
{
- DPRINT( " -> %08lx", (DWORD)subheap->next );
+ DPRINTF( " -> %08lx", (DWORD)subheap->next );
subheap = subheap->next;
}
- DPRINT( "\nFree lists:\n Block Stat Size Id\n" );
+ DPRINTF( "\nFree lists:\n Block Stat Size Id\n" );
for (i = 0; i < HEAP_NB_FREE_LISTS; i++)
- DPRINT( "%08lx free %08lx %04x prev=%08lx next=%08lx\n",
+ DPRINTF( "%08lx free %08lx %04x prev=%08lx next=%08lx\n",
(DWORD)&heap->freeList[i].arena, heap->freeList[i].arena.size,
heap->freeList[i].arena.threadId,
(DWORD)heap->freeList[i].arena.prev,
while (subheap)
{
DWORD freeSize = 0, usedSize = 0, arenaSize = subheap->headerSize;
- DPRINT( "\n\nSub-heap %08lx: size=%08lx committed=%08lx\n",
+ DPRINTF( "\n\nSub-heap %08lx: size=%08lx committed=%08lx\n",
(DWORD)subheap, subheap->size, subheap->commitSize );
- DPRINT( "\n Block Stat Size Id\n" );
+ DPRINTF( "\n Block Stat Size Id\n" );
ptr = (char*)subheap + subheap->headerSize;
while (ptr < (char *)subheap + subheap->size)
{
if (*(DWORD *)ptr & ARENA_FLAG_FREE)
{
ARENA_FREE *pArena = (ARENA_FREE *)ptr;
- DPRINT( "%08lx free %08lx %04x prev=%08lx next=%08lx\n",
+ DPRINTF( "%08lx free %08lx %04x prev=%08lx next=%08lx\n",
(DWORD)pArena, pArena->size & ARENA_SIZE_MASK,
pArena->threadId, (DWORD)pArena->prev,
(DWORD)pArena->next);
else if (*(DWORD *)ptr & ARENA_FLAG_PREV_FREE)
{
ARENA_INUSE *pArena = (ARENA_INUSE *)ptr;
- DPRINT( "%08lx Used %08lx %04x back=%08lx EIP=%08lx\n",
+ DPRINTF( "%08lx Used %08lx %04x back=%08lx EIP=%p\n",
(DWORD)pArena, pArena->size & ARENA_SIZE_MASK,
pArena->threadId, *((DWORD *)pArena - 1),
pArena->callerEIP );
else
{
ARENA_INUSE *pArena = (ARENA_INUSE *)ptr;
- DPRINT( "%08lx used %08lx %04x EIP=%08lx\n",
+ DPRINTF( "%08lx used %08lx %04x EIP=%p\n",
(DWORD)pArena, pArena->size & ARENA_SIZE_MASK,
pArena->threadId, pArena->callerEIP );
ptr += sizeof(*pArena) + (pArena->size & ARENA_SIZE_MASK);
usedSize += pArena->size & ARENA_SIZE_MASK;
}
}
- DPRINT( "\nTotal: Size=%08lx Committed=%08lx Free=%08lx Used=%08lx Arenas=%08lx (%ld%%)\n\n",
+ DPRINTF( "\nTotal: Size=%08lx Committed=%08lx Free=%08lx Used=%08lx Arenas=%08lx (%ld%%)\n\n",
subheap->size, subheap->commitSize, freeSize, usedSize,
arenaSize, (arenaSize * 100) / subheap->size );
subheap = subheap->next;
HEAP *heapPtr = (HEAP *)heap;
if (!heapPtr || (heapPtr->magic != HEAP_MAGIC))
{
- DbgPrint(heap, "Invalid heap %08x!\n", heap );
- for(;;);
-// SetLastError( ERROR_INVALID_HANDLE );
+ ERR("Invalid heap %08x!\n", heap );
+ SetLastError( ERROR_INVALID_HANDLE );
return NULL;
}
- if (!RtlValidateHeap( heap, 0, NULL ))
+ if (TRACE_ON(heap) && !HEAP_IsRealArena( heap, 0, NULL, NOISY ))
{
HEAP_Dump( heapPtr );
- DbgPrint("NTDLL:%s:%d: assertion failed\n",__FILE__,__LINE__);
- for(;;);
-// SetLastError( ERROR_INVALID_HANDLE );
+ assert( FALSE );
+ SetLastError( ERROR_INVALID_HANDLE );
return NULL;
}
return heapPtr;
*
* Make sure the heap storage is committed up to (not including) ptr.
*/
-static BOOL HEAP_Commit( SUBHEAP *subheap, void *ptr )
+static inline BOOL HEAP_Commit( SUBHEAP *subheap, void *ptr )
{
- DWORD size = (DWORD)((char *)ptr - (char *)subheap);
- ULONG commitsize;
- PVOID address;
- NTSTATUS Status;
+ DWORD size = (DWORD)((char *)ptr - (char *)subheap);
+ NTSTATUS Status;
+ PVOID address;
+ ULONG commitsize;
- size = (size + 0xfff) & 0xfffff000; /* Align size on a page boundary */
- if (size > subheap->size) size = subheap->size;
- if (size <= subheap->commitSize) return TRUE;
- commitsize = size - subheap->commitSize;
- address = (PVOID)((char *)subheap + subheap->commitSize);
- Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
- &address,
- 0,
- &commitsize,
- MEM_COMMIT,
- PAGE_EXECUTE_READWRITE);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("ZwAllocateVirtualMemory failed\n");
- for(;;);
- return(FALSE);
- }
- subheap->commitSize = size;
- return TRUE;
+ size = (size + COMMIT_MASK) & ~COMMIT_MASK;
+ if (size > subheap->size) size = subheap->size;
+ if (size <= subheap->commitSize) return TRUE;
+
+ address = (PVOID)((char *)subheap + subheap->commitSize);
+ commitsize = size - subheap->commitSize;
+#if 1
+ Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+ &address,
+ 0,
+ &commitsize,
+ MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
+ if (!NT_SUCCESS(Status))
+#else
+ if (!VirtualAlloc( (char *)subheap + subheap->commitSize,
+ size - subheap->commitSize, MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE))
+#endif
+ {
+ WARN("Could not commit %08lx bytes at %08lx for heap %08lx\n",
+ size - subheap->commitSize,
+ (DWORD)((char *)subheap + subheap->commitSize),
+ (DWORD)subheap->heap );
+ return FALSE;
+ }
+ subheap->commitSize = size;
+ return TRUE;
}
*
* If possible, decommit the heap storage from (including) 'ptr'.
*/
-static BOOL HEAP_Decommit( SUBHEAP *subheap, void *ptr )
+static inline BOOL HEAP_Decommit( SUBHEAP *subheap, void *ptr )
{
DWORD size = (DWORD)((char *)ptr - (char *)subheap);
- PVOID freebase;
- ULONG freesize;
- NTSTATUS Status;
-
- size = (size + 0xfff) & 0xfffff000; /* Align size on a page boundary */
+ PVOID address;
+ ULONG decommitsize;
+ NTSTATUS Status;
+ /* round to next block and add one full block */
+ size = ((size + COMMIT_MASK) & ~COMMIT_MASK) + COMMIT_MASK + 1;
if (size >= subheap->commitSize) return TRUE;
- freebase = (PVOID)((char *)subheap + size);
- freesize = subheap->commitSize - size;
- Status = ZwFreeVirtualMemory(NtCurrentProcess(),
- &freebase,
- &freesize,
- MEM_DECOMMIT);
- if (!NT_SUCCESS(Status))
- {
- DbgPrint("Could not decommit %08lx bytes at %08lx for heap %08lx\n",
+
+#if 1
+ address = (PVOID)((char *)subheap + size);
+ decommitsize = subheap->commitSize - size;
+ Status = ZwFreeVirtualMemory(NtCurrentProcess(),
+ &address,
+ &decommitsize,
+ MEM_DECOMMIT);
+ if (!NT_SUCCESS(Status));
+#else
+ if (!VirtualFree( (char *)subheap + size,
+ subheap->commitSize - size, MEM_DECOMMIT ))
+#endif
+ {
+ WARN("Could not decommit %08lx bytes at %08lx for heap %08lx\n",
subheap->commitSize - size,
(DWORD)((char *)subheap + size),
(DWORD)subheap->heap );
- for(;;);
return FALSE;
}
subheap->commitSize = size;
/* Create a free arena */
pFree = (ARENA_FREE *)ptr;
+#if 0
+ pFree->threadId = GetCurrentTask();
+#else
+ pFree->threadId = (DWORD)NtCurrentTeb()->Cid.UniqueThread;
+#endif
pFree->magic = ARENA_FREE_MAGIC;
/* If debugging, erase the freed block content */
- if (1) // DEBUGGING
+ if (TRACE_ON(heap))
{
char *pEnd = (char *)ptr + size;
if (pEnd > (char *)subheap + subheap->commitSize)
pNext->next->prev = pNext->prev;
pNext->prev->next = pNext->next;
size += (pNext->size & ARENA_SIZE_MASK) + sizeof(*pNext);
- if (1) // DEBUGGING
+ if (TRACE_ON(heap))
memset( pNext, ARENA_FREE_FILLER, sizeof(ARENA_FREE) );
}
if (pPrev) pPrev->next = subheap->next;
/* Free the memory */
subheap->magic = 0;
- ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&subheap, 0, MEM_RELEASE );
+#if 0
+ if (subheap->selector) FreeSelector16( subheap->selector );
+#endif
+#if 0
+ VirtualFree( subheap, 0, MEM_RELEASE );
+#else
+ ZwFreeVirtualMemory(NtCurrentProcess(),
+ (PVOID*)&subheap,
+ 0,
+ MEM_RELEASE);
+#endif
return;
}
/* Decommit the end of the heap */
- HEAP_Decommit( subheap, pFree + 1 );
+#if 0
+ if (!(subheap->heap->flags & HEAP_WINE_SHARED)) HEAP_Decommit( subheap, pFree + 1 );
+#endif
}
static BOOL HEAP_InitSubHeap( HEAP *heap, LPVOID address, DWORD flags,
DWORD commitSize, DWORD totalSize )
{
- SUBHEAP *subheap = (SUBHEAP *)address;
- FREE_LIST_ENTRY *pEntry;
- int i;
- NTSTATUS Status;
+ SUBHEAP *subheap = (SUBHEAP *)address;
+ WORD selector = 0;
+ FREE_LIST_ENTRY *pEntry;
+ int i;
+ NTSTATUS Status;
/* Commit memory */
- Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
- &address,
- 0,
- (PULONG)&commitSize,
- MEM_COMMIT,
- PAGE_EXECUTE_READWRITE);
+#if 0
+ if (flags & HEAP_WINE_SHARED)
+ commitSize = totalSize; /* always commit everything in a shared heap */
+#endif
+#if 0
+ if (!VirtualAlloc(address, commitSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE))
+#else
+ Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+ &address,
+ 0,
+ (PULONG)&commitSize,
+ MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(Status))
+#endif
{
- DbgPrint("Could not commit %08lx bytes for sub-heap %08lx\n",
+ WARN("Could not commit %08lx bytes for sub-heap %08lx\n",
commitSize, (DWORD)address );
- for(;;);
return FALSE;
}
+ /* Allocate a selector if needed */
+#if 0
+ if (flags & HEAP_WINE_SEGPTR)
+ {
+ selector = SELECTOR_AllocBlock( address, totalSize,
+ (flags & (HEAP_WINE_CODESEG|HEAP_WINE_CODE16SEG))
+ ? SEGMENT_CODE : SEGMENT_DATA,
+ (flags & HEAP_WINE_CODESEG) != 0, FALSE );
+ if (!selector)
+ {
+ ERR("Could not allocate selector\n" );
+ return FALSE;
+ }
+ }
+#endif
+
/* Fill the sub-heap structure */
subheap->heap = heap;
+ subheap->selector = selector;
subheap->size = totalSize;
subheap->commitSize = commitSize;
subheap->magic = SUBHEAP_MAGIC;
/* Initialize critical section */
RtlInitializeCriticalSection( &heap->critSection );
+#if 0
+ if (!SystemHeap) MakeCriticalSectionGlobal( &heap->critSection );
+#endif
}
/* Create the first free block */
* Create a sub-heap of the given size.
* If heap == NULL, creates a main heap.
*/
-static SUBHEAP *HEAP_CreateSubHeap(PVOID BaseAddress,
- HEAP *heap,
- DWORD flags,
- DWORD commitSize,
- DWORD totalSize )
+static SUBHEAP *HEAP_CreateSubHeap(PVOID BaseAddress,
+ HEAP *heap, DWORD flags,
+ DWORD commitSize, DWORD totalSize )
{
LPVOID address;
+ NTSTATUS Status;
/* Round-up sizes on a 64K boundary */
- totalSize = (totalSize + 0xffff) & 0xffff0000;
- commitSize = (commitSize + 0xffff) & 0xffff0000;
- if (!commitSize) commitSize = 0x10000;
- if (totalSize < commitSize) totalSize = commitSize;
+#if 0
+ if (flags & HEAP_WINE_SEGPTR)
+ {
+ totalSize = commitSize = 0x10000; /* Only 64K at a time for SEGPTRs */
+ }
+ else
+#else
+ if (1)
+#endif
+ {
+ totalSize = (totalSize + 0xffff) & 0xffff0000;
+ commitSize = (commitSize + 0xffff) & 0xffff0000;
+ if (!commitSize) commitSize = 0x10000;
+ if (totalSize < commitSize) totalSize = commitSize;
+ }
/* Allocate the memory block */
-
- address = BaseAddress;
- ZwAllocateVirtualMemory(NtCurrentProcess(),
- &address,
- 0,
- (PULONG)&totalSize,
- MEM_RESERVE,
- PAGE_EXECUTE_READWRITE);
+
+#if 0
+ if (!(address = VirtualAlloc( NULL, totalSize,
+ MEM_RESERVE, PAGE_EXECUTE_READWRITE )))
+#else
+ address = BaseAddress;
+ Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+ &address,
+ 0,
+ (PULONG)&totalSize,
+ MEM_RESERVE,
+ PAGE_EXECUTE_READWRITE);
+ if (!NT_SUCCESS(Status))
+#endif
+ {
+ WARN("Could not VirtualAlloc %08lx bytes\n",
+ totalSize );
+ return NULL;
+ }
/* Initialize subheap */
if (!HEAP_InitSubHeap( heap? heap : (HEAP *)address,
address, flags, commitSize, totalSize ))
{
- ZwFreeVirtualMemory(NtCurrentProcess(), address, 0, MEM_RELEASE );
+#if 0
+ VirtualFree( address, 0, MEM_RELEASE );
+#else
+ ZwFreeVirtualMemory(NtCurrentProcess(),
+ address,
+ 0,
+ MEM_RELEASE);
+#endif
return NULL;
}
if (!(heap->flags & HEAP_GROWABLE))
{
- DbgPrint("Not enough space in heap %08lx for %08lx bytes\n",
+ WARN("Not enough space in heap %08lx for %08lx bytes\n",
(DWORD)heap, size );
return NULL;
}
max( HEAP_DEF_SIZE, size ) )))
return NULL;
- DPRINT("created new sub-heap %08lx of %08lx bytes for heap %08lx\n",
+ TRACE("created new sub-heap %08lx of %08lx bytes for heap %08lx\n",
(DWORD)subheap, size, (DWORD)heap );
*ppSubHeap = subheap;
/* Check magic number */
if (pArena->magic != ARENA_FREE_MAGIC)
{
- DbgPrint("Heap %08lx: invalid free arena magic for %08lx (%x)\n",
- (DWORD)subheap->heap, (DWORD)pArena, &pArena->magic );
- for(;;);
+ ERR("Heap %08lx: invalid free arena magic for %08lx\n",
+ (DWORD)subheap->heap, (DWORD)pArena );
return FALSE;
}
/* Check size flags */
if (!(pArena->size & ARENA_FLAG_FREE) ||
(pArena->size & ARENA_FLAG_PREV_FREE))
{
- DbgPrint("Heap %08lx: bad flags %lx for free arena %08lx\n",
+ ERR("Heap %08lx: bad flags %lx for free arena %08lx\n",
(DWORD)subheap->heap, pArena->size & ~ARENA_SIZE_MASK, (DWORD)pArena );
- for(;;);
}
/* Check arena size */
if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) > heapEnd)
{
- DbgPrint("Heap %08lx: bad size %08lx for free arena %08lx\n",
+ ERR("Heap %08lx: bad size %08lx for free arena %08lx\n",
(DWORD)subheap->heap, (DWORD)pArena->size & ARENA_SIZE_MASK, (DWORD)pArena );
- for(;;);
return FALSE;
}
/* Check that next pointer is valid */
if (!HEAP_IsValidArenaPtr( subheap->heap, pArena->next ))
{
- DbgPrint("Heap %08lx: bad next ptr %08lx for arena %08lx\n",
+ ERR("Heap %08lx: bad next ptr %08lx for arena %08lx\n",
(DWORD)subheap->heap, (DWORD)pArena->next, (DWORD)pArena );
- for(;;);
return FALSE;
}
/* Check that next arena is free */
if (!(pArena->next->size & ARENA_FLAG_FREE) ||
(pArena->next->magic != ARENA_FREE_MAGIC))
{
- DPRINT("Heap %08lx: next arena %08lx invalid for %08lx\n",
+ ERR("Heap %08lx: next arena %08lx invalid for %08lx\n",
(DWORD)subheap->heap, (DWORD)pArena->next, (DWORD)pArena );
return FALSE;
}
/* Check that prev pointer is valid */
if (!HEAP_IsValidArenaPtr( subheap->heap, pArena->prev ))
{
- DbgPrint("Heap %08lx: bad prev ptr %08lx for arena %08lx\n",
+ ERR("Heap %08lx: bad prev ptr %08lx for arena %08lx\n",
(DWORD)subheap->heap, (DWORD)pArena->prev, (DWORD)pArena );
- for(;;);
return FALSE;
}
/* Check that prev arena is free */
if (!(pArena->prev->size & ARENA_FLAG_FREE) ||
(pArena->prev->magic != ARENA_FREE_MAGIC))
{
- DbgPrint("Heap %08lx: prev arena %08lx invalid for %08lx\n",
+ ERR("Heap %08lx: prev arena %08lx invalid for %08lx\n",
(DWORD)subheap->heap, (DWORD)pArena->prev, (DWORD)pArena );
- for(;;);
return FALSE;
}
/* Check that next block has PREV_FREE flag */
if (!(*(DWORD *)((char *)(pArena + 1) +
(pArena->size & ARENA_SIZE_MASK)) & ARENA_FLAG_PREV_FREE))
{
- DbgPrint("Heap %08lx: free arena %08lx next block has no PREV_FREE flag\n",
+ ERR("Heap %08lx: free arena %08lx next block has no PREV_FREE flag\n",
(DWORD)subheap->heap, (DWORD)pArena );
- for(;;);
return FALSE;
}
/* Check next block back pointer */
if (*((ARENA_FREE **)((char *)(pArena + 1) +
(pArena->size & ARENA_SIZE_MASK)) - 1) != pArena)
{
- DbgPrint("Heap %08lx: arena %08lx has wrong back ptr %08lx\n",
+ ERR("Heap %08lx: arena %08lx has wrong back ptr %08lx\n",
(DWORD)subheap->heap, (DWORD)pArena,
*((DWORD *)((char *)(pArena+1)+ (pArena->size & ARENA_SIZE_MASK)) - 1));
- for(;;);
return FALSE;
}
}
/***********************************************************************
* HEAP_ValidateInUseArena
*/
-static BOOL HEAP_ValidateInUseArena( SUBHEAP *subheap, ARENA_INUSE *pArena )
+static BOOL HEAP_ValidateInUseArena( SUBHEAP *subheap, ARENA_INUSE *pArena, BOOL quiet )
{
char *heapEnd = (char *)subheap + subheap->size;
/* Check magic number */
if (pArena->magic != ARENA_INUSE_MAGIC)
{
- DbgPrint("Heap %08lx: invalid in-use arena magic for %08lx (%x)\n",
- (DWORD)subheap->heap, (DWORD)pArena, &pArena->magic );
- for(;;);
+ if (quiet == NOISY) {
+ ERR("Heap %08lx: invalid in-use arena magic for %08lx\n",
+ (DWORD)subheap->heap, (DWORD)pArena );
+ if (TRACE_ON(heap))
+ HEAP_Dump( subheap->heap );
+ } else if (WARN_ON(heap)) {
+ WARN("Heap %08lx: invalid in-use arena magic for %08lx\n",
+ (DWORD)subheap->heap, (DWORD)pArena );
+ if (TRACE_ON(heap))
+ HEAP_Dump( subheap->heap );
+ }
return FALSE;
}
/* Check size flags */
if (pArena->size & ARENA_FLAG_FREE)
{
- DbgPrint("Heap %08lx: bad flags %lx for in-use arena %08lx\n",
+ ERR("Heap %08lx: bad flags %lx for in-use arena %08lx\n",
(DWORD)subheap->heap, pArena->size & ~ARENA_SIZE_MASK, (DWORD)pArena );
- for(;;);
}
/* Check arena size */
if ((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) > heapEnd)
{
- DbgPrint("Heap %08lx: bad size %08lx for in-use arena %08lx\n",
+ ERR("Heap %08lx: bad size %08lx for in-use arena %08lx\n",
(DWORD)subheap->heap, (DWORD)pArena->size & ARENA_SIZE_MASK, (DWORD)pArena );
- for(;;);
return FALSE;
}
/* Check next arena PREV_FREE flag */
if (((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK) < heapEnd) &&
(*(DWORD *)((char *)(pArena + 1) + (pArena->size & ARENA_SIZE_MASK)) & ARENA_FLAG_PREV_FREE))
{
- DbgPrint("Heap %08lx: in-use arena %08lx next block has PREV_FREE flag\n",
+ ERR("Heap %08lx: in-use arena %08lx next block has PREV_FREE flag\n",
(DWORD)subheap->heap, (DWORD)pArena );
- for(;;);
return FALSE;
}
/* Check prev free arena */
/* Check prev pointer */
if (!HEAP_IsValidArenaPtr( subheap->heap, pPrev ))
{
- DbgPrint("Heap %08lx: bad back ptr %08lx for arena %08lx\n",
+ ERR("Heap %08lx: bad back ptr %08lx for arena %08lx\n",
(DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena );
- for(;;);
return FALSE;
}
/* Check that prev arena is free */
if (!(pPrev->size & ARENA_FLAG_FREE) ||
(pPrev->magic != ARENA_FREE_MAGIC))
{
- DbgPrint("Heap %08lx: prev arena %08lx invalid for in-use %08lx\n",
+ ERR("Heap %08lx: prev arena %08lx invalid for in-use %08lx\n",
(DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena );
- for(;;);
return FALSE;
}
/* Check that prev arena is really the previous block */
if ((char *)(pPrev + 1) + (pPrev->size & ARENA_SIZE_MASK) != (char *)pArena)
{
- DbgPrint("Heap %08lx: prev arena %08lx is not prev for in-use %08lx\n",
+ ERR("Heap %08lx: prev arena %08lx is not prev for in-use %08lx\n",
(DWORD)subheap->heap, (DWORD)pPrev, (DWORD)pArena );
- for(;;);
return FALSE;
}
}
if (!heapPtr) return 0;
flags |= heapPtr->flags;
- if (!(flags & HEAP_NO_SERIALIZE)) RtlLockHeap( heap );
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
ret = (((subheap = HEAP_FindSubHeap( heapPtr, ptr )) != NULL) &&
(((char *)ptr >= (char *)subheap + subheap->headerSize
+ sizeof(ARENA_INUSE))));
- if (!(flags & HEAP_NO_SERIALIZE)) RtlUnlockHeap( heap );
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+ return ret;
+}
+
+
+
+
+/***********************************************************************
+ * HEAP_IsRealArena [Internal]
+ * Validates a block is a valid arena.
+ *
+ * RETURNS
+ * TRUE: Success
+ * FALSE: Failure
+ */
+static BOOL HEAP_IsRealArena(
+ HANDLE heap, /* [in] Handle to the heap */
+ DWORD flags, /* [in] Bit flags that control access during operation */
+ LPCVOID block, /* [in] Optional pointer to memory block to validate */
+ BOOL quiet /* [in] Flag - if true, HEAP_ValidateInUseArena
+ * does not complain */
+) {
+ SUBHEAP *subheap;
+ HEAP *heapPtr = (HEAP *)(heap);
+ BOOL ret = TRUE;
+
+ if (!heapPtr || (heapPtr->magic != HEAP_MAGIC))
+ {
+ ERR("Invalid heap %08x!\n", heap );
+ return FALSE;
+ }
+
+ flags &= HEAP_NO_SERIALIZE;
+ flags |= heapPtr->flags;
+ /* calling HeapLock may result in infinite recursion, so do the critsect directly */
+ if (!(flags & HEAP_NO_SERIALIZE))
+ RtlEnterCriticalSection( &heapPtr->critSection );
+
+ if (block)
+ {
+ /* Only check this single memory block */
+
+ /* The following code is really HEAP_IsInsideHeap *
+ * with serialization already done. */
+ if (!(subheap = HEAP_FindSubHeap( heapPtr, block )) ||
+ ((char *)block < (char *)subheap + subheap->headerSize
+ + sizeof(ARENA_INUSE)))
+ {
+ if (quiet == NOISY)
+ ERR("Heap %08lx: block %08lx is not inside heap\n",
+ (DWORD)heap, (DWORD)block );
+ else if (WARN_ON(heap))
+ WARN("Heap %08lx: block %08lx is not inside heap\n",
+ (DWORD)heap, (DWORD)block );
+ ret = FALSE;
+ } else
+ ret = HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)block - 1, quiet );
+
+ if (!(flags & HEAP_NO_SERIALIZE))
+ RtlLeaveCriticalSection( &heapPtr->critSection );
+ return ret;
+ }
+
+ subheap = &heapPtr->subheap;
+ while (subheap && ret)
+ {
+ char *ptr = (char *)subheap + subheap->headerSize;
+ while (ptr < (char *)subheap + subheap->size)
+ {
+ if (*(DWORD *)ptr & ARENA_FLAG_FREE)
+ {
+ if (!HEAP_ValidateFreeArena( subheap, (ARENA_FREE *)ptr )) {
+ ret = FALSE;
+ break;
+ }
+ ptr += sizeof(ARENA_FREE) + (*(DWORD *)ptr & ARENA_SIZE_MASK);
+ }
+ else
+ {
+ if (!HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)ptr, NOISY )) {
+ ret = FALSE;
+ break;
+ }
+ ptr += sizeof(ARENA_INUSE) + (*(DWORD *)ptr & ARENA_SIZE_MASK);
+ }
+ }
+ subheap = subheap->next;
+ }
+
+ if (!(flags & HEAP_NO_SERIALIZE))
+ RtlLeaveCriticalSection( &heapPtr->critSection );
return ret;
}
PVOID Unknown,
PRTL_HEAP_DEFINITION Definition)
{
- SUBHEAP *subheap;
-
- /* Allocate the heap block */
-
- DPRINT("RtlCreateHeap(flags %x, BaseAddress %x, initialSize %x, "
- "maxSize %x\n)",flags,BaseAddress,initialSize, maxSize);
+ SUBHEAP *subheap;
+ ULONG i;
+ /* Allocate the heap block */
+
if (!maxSize)
{
maxSize = HEAP_DEF_SIZE;
flags |= HEAP_GROWABLE;
}
- if (!(subheap = HEAP_CreateSubHeap(BaseAddress,
- NULL,
- flags,
- initialSize,
- maxSize)))
+ if (!(subheap = HEAP_CreateSubHeap( BaseAddress, NULL, flags, initialSize, maxSize )))
{
-// SetLastError( ERROR_OUTOFMEMORY );
- DbgPrint("RtlCreateHeap() = %x\n",0);
+ SetLastError( ERROR_OUTOFMEMORY );
return 0;
}
- DPRINT("RtlCreateHeap() = %x\n",subheap);
-
+#if 0
+ /* link it into the per-process heap list */
+ if (processHeap)
+ {
+ HEAP *heapPtr = subheap->heap;
+ RtlEnterCriticalSection( &processHeap->critSection );
+ heapPtr->next = firstHeap;
+ firstHeap = heapPtr;
+ RtlLeaveCriticalSection( &processHeap->critSection );
+ }
+ else /* assume the first heap we create is the process main heap */
+ {
+ processHeap = subheap->heap;
+ }
+#else
+ RtlEnterCriticalSection (&RtlpProcessHeapsListLock);
+ for (i = 0; i < NtCurrentPeb ()->NumberOfHeaps; i++)
+ {
+ if (NtCurrentPeb ()->ProcessHeaps[i] == NULL)
+ {
+ NtCurrentPeb()->ProcessHeaps[i] = (PVOID)subheap;
+ break;
+ }
+ }
+ RtlLeaveCriticalSection (&RtlpProcessHeapsListLock);
+#endif
+
return (HANDLE)subheap;
}
* TRUE: Success
* FALSE: Failure
*/
-BOOL STDCALL RtlDestroyHeap(
- HANDLE heap /* [in] Handle of heap */
-) {
+BOOL STDCALL RtlDestroyHeap( HANDLE heap /* [in] Handle of heap */ )
+{
HEAP *heapPtr = HEAP_GetPtr( heap );
SUBHEAP *subheap;
-
- DPRINT("%08x\n", heap );
+ ULONG i;
+
+ TRACE("%08x\n", heap );
if (!heapPtr) return FALSE;
+#if 0
+ if (heapPtr == processHeap) /* cannot delete the main process heap */
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+ else /* remove it from the per-process list */
+ {
+ HEAP **pptr;
+ RtlEnterCriticalSection( &processHeap->critSection );
+ pptr = &firstHeap;
+ while (*pptr && *pptr != heapPtr) pptr = &(*pptr)->next;
+ if (*pptr) *pptr = (*pptr)->next;
+ RtlLeaveCriticalSection( &processHeap->critSection );
+ }
+#else
+ RtlEnterCriticalSection (&RtlpProcessHeapsListLock);
+ for (i = 0; i < NtCurrentPeb ()->NumberOfHeaps; i++)
+ {
+ if (NtCurrentPeb ()->ProcessHeaps[i] == heap)
+ {
+ NtCurrentPeb()->ProcessHeaps[i] = NULL;
+ break;
+ }
+ }
+ RtlLeaveCriticalSection (&RtlpProcessHeapsListLock);
+#endif
+
RtlDeleteCriticalSection( &heapPtr->critSection );
subheap = &heapPtr->subheap;
while (subheap)
{
SUBHEAP *next = subheap->next;
- ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID*)&subheap, 0, MEM_RELEASE );
+#if 0
+ if (subheap->selector) FreeSelector16( subheap->selector );
+ VirtualFree( subheap, 0, MEM_RELEASE );
+#else
+ ZwFreeVirtualMemory(NtCurrentProcess(),
+ (PVOID*)&subheap,
+ 0,
+ MEM_RELEASE);
+#endif
subheap = next;
}
return TRUE;
*/
PVOID STDCALL RtlAllocateHeap(
HANDLE heap, /* [in] Handle of private heap block */
- ULONG flags, /* [in] Heap allocation control flags */
+ ULONG flags, /* [in] Heap allocation control flags */
ULONG size /* [in] Number of bytes to allocate */
) {
ARENA_FREE *pArena;
ARENA_INUSE *pInUse;
SUBHEAP *subheap;
- HEAP *heapPtr = NULL;
+ HEAP *heapPtr = HEAP_GetPtr( heap );
/* Validate the parameters */
+ if (!heapPtr) return NULL;
flags &= HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY;
- flags |= ((HEAP*)heap)->flags;
- if (!(flags & HEAP_NO_SERIALIZE))
- {
- RtlLockHeap(heap);
- }
- heapPtr = HEAP_GetPtr(heap);
- if (heapPtr == NULL)
- {
- if (!(flags & HEAP_NO_SERIALIZE))
- {
- RtlUnlockHeap(heap);
- }
- }
+ flags |= heapPtr->flags;
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
size = (size + 3) & ~3;
if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE;
if (!(pArena = HEAP_FindFreeBlock( heapPtr, size, &subheap )))
{
- DPRINT("(%08x,%08lx,%08lx): returning NULL\n",
+ TRACE("(%08x,%08lx,%08lx): returning NULL\n",
heap, flags, size );
- if (!(flags & HEAP_NO_SERIALIZE)) RtlUnlockHeap( heap );
-// SetLastError( ERROR_COMMITMENT_LIMIT );
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+ SetLastError( ERROR_COMMITMENT_LIMIT );
return NULL;
}
pInUse = (ARENA_INUSE *)pArena;
pInUse->size = (pInUse->size & ~ARENA_FLAG_FREE)
+ sizeof(ARENA_FREE) - sizeof(ARENA_INUSE);
- pInUse->callerEIP = *((DWORD *)&heap - 1); /* hack hack */
-// pInUse->threadId = GetCurrentTask();
+ pInUse->callerEIP = GET_EIP();
+#if 0
+ pInUse->threadId = GetCurrentTask();
+#else
+ pInUse->threadId = (DWORD)NtCurrentTeb()->Cid.UniqueThread;
+#endif
pInUse->magic = ARENA_INUSE_MAGIC;
/* Shrink the block */
HEAP_ShrinkBlock( subheap, pInUse, size );
- if (flags & HEAP_ZERO_MEMORY) memset( pInUse + 1, 0, size );
- else if (1) memset( pInUse + 1, ARENA_INUSE_FILLER, size ); //DEBUGGING
-
- if (!(flags & HEAP_NO_SERIALIZE)) RtlUnlockHeap( heap );
+ if (flags & HEAP_ZERO_MEMORY)
+ memset( pInUse + 1, 0, pInUse->size & ARENA_SIZE_MASK );
+ else if (TRACE_ON(heap))
+ memset( pInUse + 1, ARENA_INUSE_FILLER, pInUse->size & ARENA_SIZE_MASK );
+
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
- DPRINT("(%08x,%08lx,%08lx): returning %08lx\n",
+ TRACE("(%08x,%08lx,%08lx): returning %08lx\n",
heap, flags, size, (DWORD)(pInUse + 1) );
return (LPVOID)(pInUse + 1);
}
) {
ARENA_INUSE *pInUse;
SUBHEAP *subheap;
- HEAP *heapPtr = NULL;
+ HEAP *heapPtr = HEAP_GetPtr( heap );
/* Validate the parameters */
- flags &= HEAP_NO_SERIALIZE;
- flags |= ((HEAP*)heap)->flags;
- if (!(flags & HEAP_NO_SERIALIZE))
- {
- RtlLockHeap( heap );
- }
- heapPtr = HEAP_GetPtr(heap);
- if (heapPtr == NULL)
- {
- if (!(flags & HEAP_NO_SERIALIZE))
- {
- RtlUnlockHeap(heap);
- }
- return(FALSE);
- }
- if (!ptr)
+ if (!heapPtr) return FALSE;
+ if (!ptr) /* Freeing a NULL ptr is doesn't indicate an error in Win2k */
{
- DPRINT("(%08x,%08lx,%08lx): asked to free NULL\n",
+ WARN("(%08x,%08lx,%08lx): asked to free NULL\n",
heap, flags, (DWORD)ptr );
+ return TRUE;
}
- if (!ptr || !RtlValidateHeap( heap, HEAP_NO_SERIALIZE, ptr ))
+
+ flags &= HEAP_NO_SERIALIZE;
+ flags |= heapPtr->flags;
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
+ if (!HEAP_IsRealArena( heap, HEAP_NO_SERIALIZE, ptr, QUIET ))
{
- if (!(flags & HEAP_NO_SERIALIZE)) RtlUnlockHeap( heap );
-// SetLastError( ERROR_INVALID_PARAMETER );
- DPRINT("(%08x,%08lx,%08lx): returning FALSE\n",
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+ SetLastError( ERROR_INVALID_PARAMETER );
+ TRACE("(%08x,%08lx,%08lx): returning FALSE\n",
heap, flags, (DWORD)ptr );
return FALSE;
}
subheap = HEAP_FindSubHeap( heapPtr, pInUse );
HEAP_MakeInUseBlockFree( subheap, pInUse );
- if (!(flags & HEAP_NO_SERIALIZE)) RtlUnlockHeap( heap );
-/* SetLastError( 0 ); */
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
- DPRINT("(%08x,%08lx,%08lx): returning TRUE\n",
+ TRACE("(%08x,%08lx,%08lx): returning TRUE\n",
heap, flags, (DWORD)ptr );
return TRUE;
}
* RETURNS
* Pointer to reallocated memory block
* NULL: Failure
- *
- * REVISIONS
- * Renamed RtlReAllocateHeap as in NT
*/
-LPVOID
-STDCALL
-RtlReAllocateHeap (
- HANDLE heap, /* [in] Handle of heap block */
- DWORD flags, /* [in] Heap reallocation flags */
- LPVOID ptr, /* [in] Address of memory to reallocate */
- DWORD size /* [in] Number of bytes to reallocate */
- )
-{
+LPVOID STDCALL RtlReAllocateHeap(
+ HANDLE heap, /* [in] Handle of heap block */
+ DWORD flags, /* [in] Heap reallocation flags */
+ LPVOID ptr, /* [in] Address of memory to reallocate */
+ DWORD size /* [in] Number of bytes to reallocate */
+) {
ARENA_INUSE *pArena;
DWORD oldSize;
HEAP *heapPtr;
size = (size + 3) & ~3;
if (size < HEAP_MIN_BLOCK_SIZE) size = HEAP_MIN_BLOCK_SIZE;
- if (!(flags & HEAP_NO_SERIALIZE)) RtlLockHeap( heap );
- if (!RtlValidateHeap( heap, HEAP_NO_SERIALIZE, ptr ))
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
+ if (!HEAP_IsRealArena( heap, HEAP_NO_SERIALIZE, ptr, QUIET ))
{
- if (!(flags & HEAP_NO_SERIALIZE)) RtlUnlockHeap( heap );
-// SetLastError( ERROR_INVALID_PARAMETER );
- DPRINT("(%08x,%08lx,%08lx,%08lx): returning NULL\n",
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+ SetLastError( ERROR_INVALID_PARAMETER );
+ TRACE("(%08x,%08lx,%08lx,%08lx): returning NULL\n",
heap, flags, (DWORD)ptr, size );
return NULL;
}
/* Check if we need to grow the block */
pArena = (ARENA_INUSE *)ptr - 1;
-// pArena->threadId = GetCurrentTask();
+#if 0
+ pArena->threadId = GetCurrentTask();
+#else
+ pArena->threadId = (DWORD)NtCurrentTeb()->Cid.UniqueThread;
+#endif
subheap = HEAP_FindSubHeap( heapPtr, pArena );
oldSize = (pArena->size & ARENA_SIZE_MASK);
if (size > oldSize)
if (!HEAP_Commit( subheap, (char *)pArena + sizeof(ARENA_INUSE)
+ size + HEAP_MIN_BLOCK_SIZE))
{
- if (!(flags & HEAP_NO_SERIALIZE)) RtlUnlockHeap( heap );
-// SetLastError( ERROR_OUTOFMEMORY );
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+ SetLastError( ERROR_OUTOFMEMORY );
return NULL;
}
HEAP_ShrinkBlock( subheap, pArena, size );
if ((flags & HEAP_REALLOC_IN_PLACE_ONLY) ||
!(pNew = HEAP_FindFreeBlock( heapPtr, size, &newsubheap )))
{
- if (!(flags & HEAP_NO_SERIALIZE)) RtlUnlockHeap( heap );
- // SetLastError( ERROR_OUTOFMEMORY );
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+ SetLastError( ERROR_OUTOFMEMORY );
return NULL;
}
pInUse = (ARENA_INUSE *)pNew;
pInUse->size = (pInUse->size & ~ARENA_FLAG_FREE)
+ sizeof(ARENA_FREE) - sizeof(ARENA_INUSE);
-// pInUse->threadId = GetCurrentTask();
+#if 0
+ pInUse->threadId = GetCurrentTask();
+#else
+ pInUse->threadId = (DWORD)NtCurrentTeb()->Cid.UniqueThread;
+#endif
pInUse->magic = ARENA_INUSE_MAGIC;
HEAP_ShrinkBlock( newsubheap, pInUse, size );
memcpy( pInUse + 1, pArena + 1, oldSize );
if (flags & HEAP_ZERO_MEMORY)
memset( (char *)(pArena + 1) + oldSize, 0,
(pArena->size & ARENA_SIZE_MASK) - oldSize );
- else if (1) // DEBUGGING
+ else if (TRACE_ON(heap))
memset( (char *)(pArena + 1) + oldSize, ARENA_INUSE_FILLER,
(pArena->size & ARENA_SIZE_MASK) - oldSize );
}
/* Return the new arena */
- pArena->callerEIP = *((DWORD *)&heap - 1); /* hack hack */
- if (!(flags & HEAP_NO_SERIALIZE)) RtlUnlockHeap( heap );
+ pArena->callerEIP = GET_EIP();
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
- DPRINT("(%08x,%08lx,%08lx,%08lx): returning %08lx\n",
+ TRACE("(%08x,%08lx,%08lx,%08lx): returning %08lx\n",
heap, flags, (DWORD)ptr, size, (DWORD)(pArena + 1) );
return (LPVOID)(pArena + 1);
}
*/
DWORD STDCALL RtlCompactHeap( HANDLE heap, DWORD flags )
{
+ SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
* HeapSize (KERNEL32.341)
* RETURNS
* Size in bytes of allocated memory
- * 0: Failure
+ * 0xffffffff: Failure
*/
DWORD STDCALL RtlSizeHeap(
HANDLE heap, /* [in] Handle of heap */
if (!heapPtr) return FALSE;
flags &= HEAP_NO_SERIALIZE;
flags |= heapPtr->flags;
- if (!(flags & HEAP_NO_SERIALIZE)) RtlLockHeap( heap );
- if (!RtlValidateHeap( heap, HEAP_NO_SERIALIZE, ptr ))
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
+ if (!HEAP_IsRealArena( heap, HEAP_NO_SERIALIZE, ptr, QUIET ))
{
-// SetLastError( ERROR_INVALID_PARAMETER );
+ SetLastError( ERROR_INVALID_PARAMETER );
ret = 0xffffffff;
}
else
ARENA_INUSE *pArena = (ARENA_INUSE *)ptr - 1;
ret = pArena->size & ARENA_SIZE_MASK;
}
- if (!(flags & HEAP_NO_SERIALIZE)) RtlUnlockHeap( heap );
+ if (!(flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
- DPRINT("(%08x,%08lx,%08lx): returning %08lx\n",
+ TRACE("(%08x,%08lx,%08lx): returning %08lx\n",
heap, flags, (DWORD)ptr, ret );
return ret;
}
DWORD flags, /* [in] Bit flags that control access during operation */
PVOID block /* [in] Optional pointer to memory block to validate */
) {
- SUBHEAP *subheap;
- HEAP *heapPtr = (HEAP *)(heap);
- if (!heapPtr || (heapPtr->magic != HEAP_MAGIC))
+ return HEAP_IsRealArena( heap, flags, block, QUIET );
+}
+
+
+/***********************************************************************
+ * HeapWalk (KERNEL32.344)
+ * Enumerates the memory blocks in a specified heap.
+ * See HEAP_Dump() for info on heap structure.
+ *
+ * TODO
+ * - handling of PROCESS_HEAP_ENTRY_MOVEABLE and
+ * PROCESS_HEAP_ENTRY_DDESHARE (needs heap.c support)
+ *
+ * RETURNS
+ * TRUE: Success
+ * FALSE: Failure
+ */
+#if 0
+BOOL STDCALL HeapWalk(
+ HANDLE heap, /* [in] Handle to heap to enumerate */
+ LPPROCESS_HEAP_ENTRY entry /* [out] Pointer to structure of enumeration info */
+) {
+ HEAP *heapPtr = HEAP_GetPtr(heap);
+ SUBHEAP *sub, *currentheap = NULL;
+ BOOL ret = FALSE;
+ char *ptr;
+ int region_index = 0;
+
+ if (!heapPtr || !entry)
{
- DPRINT("Invalid heap %08x!\n", heap );
- return FALSE;
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
}
- if (block)
+ if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlEnterCriticalSection( &heapPtr->critSection );
+
+ /* set ptr to the next arena to be examined */
+
+ if (!entry->lpData) /* first call (init) ? */
{
- /* Only check this single memory block */
- if (!(subheap = HEAP_FindSubHeap( heapPtr, block )) ||
- ((char *)block < (char *)subheap + subheap->headerSize
- + sizeof(ARENA_INUSE)))
+ TRACE("begin walking of heap 0x%08x.\n", heap);
+ /*HEAP_Dump(heapPtr);*/
+ currentheap = &heapPtr->subheap;
+ ptr = (char*)currentheap + currentheap->headerSize;
+ }
+ else
+ {
+ ptr = entry->lpData;
+ sub = &heapPtr->subheap;
+ while (sub)
+ {
+ if (((char *)ptr >= (char *)sub) &&
+ ((char *)ptr < (char *)sub + sub->size))
+ {
+ currentheap = sub;
+ break;
+ }
+ sub = sub->next;
+ region_index++;
+ }
+ if (currentheap == NULL)
+ {
+ ERR("no matching subheap found, shouldn't happen !\n");
+ SetLastError(ERROR_NO_MORE_ITEMS);
+ goto HW_end;
+ }
+
+ ptr += entry->cbData; /* point to next arena */
+ if (ptr > (char *)currentheap + currentheap->size - 1)
+ { /* proceed with next subheap */
+ if (!(currentheap = currentheap->next))
+ { /* successfully finished */
+ TRACE("end reached.\n");
+ SetLastError(ERROR_NO_MORE_ITEMS);
+ goto HW_end;
+ }
+ ptr = (char*)currentheap + currentheap->headerSize;
+ }
+ }
+
+ entry->wFlags = 0;
+ if (*(DWORD *)ptr & ARENA_FLAG_FREE)
+ {
+ ARENA_FREE *pArena = (ARENA_FREE *)ptr;
+
+ /*TRACE("free, magic: %04x\n", pArena->magic);*/
+
+ entry->lpData = pArena + 1;
+ entry->cbData = pArena->size & ARENA_SIZE_MASK;
+ entry->cbOverhead = sizeof(ARENA_FREE);
+ entry->wFlags = PROCESS_HEAP_UNCOMMITTED_RANGE;
+ }
+ else
+ {
+ ARENA_INUSE *pArena = (ARENA_INUSE *)ptr;
+
+ /*TRACE("busy, magic: %04x\n", pArena->magic);*/
+
+ entry->lpData = pArena + 1;
+ entry->cbData = pArena->size & ARENA_SIZE_MASK;
+ entry->cbOverhead = sizeof(ARENA_INUSE);
+ entry->wFlags = PROCESS_HEAP_ENTRY_BUSY;
+ /* FIXME: can't handle PROCESS_HEAP_ENTRY_MOVEABLE
+ and PROCESS_HEAP_ENTRY_DDESHARE yet */
+ }
+
+ entry->iRegionIndex = region_index;
+
+ /* first element of heap ? */
+ if (ptr == (char *)(currentheap + currentheap->headerSize))
+ {
+ entry->wFlags |= PROCESS_HEAP_REGION;
+ entry->Foo.Region.dwCommittedSize = currentheap->commitSize;
+ entry->Foo.Region.dwUnCommittedSize =
+ currentheap->size - currentheap->commitSize;
+ entry->Foo.Region.lpFirstBlock = /* first valid block */
+ currentheap + currentheap->headerSize;
+ entry->Foo.Region.lpLastBlock = /* first invalid block */
+ currentheap + currentheap->size;
+ }
+ ret = TRUE;
+
+HW_end:
+ if (!(heapPtr->flags & HEAP_NO_SERIALIZE)) RtlLeaveCriticalSection( &heapPtr->critSection );
+
+ return ret;
+}
+
+
+/***********************************************************************
+ * HEAP_CreateSystemHeap
+ *
+ * Create the system heap.
+ */
+BOOL HEAP_CreateSystemHeap(void)
+{
+ SYSTEM_HEAP_DESCR *descr;
+ HANDLE heap;
+ HEAP *heapPtr;
+ int created;
+
+ HANDLE map = CreateFileMappingA( INVALID_HANDLE_VALUE, NULL, SEC_COMMIT | PAGE_READWRITE,
+ 0, HEAP_DEF_SIZE, "__SystemHeap" );
+ if (!map) return FALSE;
+ created = (GetLastError() != ERROR_ALREADY_EXISTS);
+
+ if (!(heapPtr = MapViewOfFileEx( map, FILE_MAP_ALL_ACCESS, 0, 0, 0, SYSTEM_HEAP_BASE )))
+ {
+ /* pre-defined address not available, use any one */
+ fprintf( stderr, "Warning: system heap base address %p not available\n",
+ SYSTEM_HEAP_BASE );
+ if (!(heapPtr = MapViewOfFile( map, FILE_MAP_ALL_ACCESS, 0, 0, 0 )))
{
- DPRINT("Heap %08lx: block %08lx is not inside heap\n",
- (DWORD)heap, (DWORD)block );
+ CloseHandle( map );
return FALSE;
}
- return HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)block - 1 );
}
+ heap = (HANDLE)heapPtr;
- subheap = &heapPtr->subheap;
- while (subheap)
+ if (created) /* newly created heap */
{
- char *ptr = (char *)subheap + subheap->headerSize;
- while (ptr < (char *)subheap + subheap->size)
+ HEAP_InitSubHeap( heapPtr, heapPtr, HEAP_WINE_SHARED, 0, HEAP_DEF_SIZE );
+ HeapLock( heap );
+ descr = heapPtr->private = HeapAlloc( heap, HEAP_ZERO_MEMORY, sizeof(*descr) );
+ assert( descr );
+ }
+ else
+ {
+ /* wait for the heap to be initialized */
+ while (!heapPtr->private) Sleep(1);
+ HeapLock( heap );
+ /* remap it to the right address if necessary */
+ if (heapPtr->subheap.heap != heapPtr)
{
- if (*(DWORD *)ptr & ARENA_FLAG_FREE)
- {
- if (!HEAP_ValidateFreeArena( subheap, (ARENA_FREE *)ptr ))
- return FALSE;
- ptr += sizeof(ARENA_FREE) + (*(DWORD *)ptr & ARENA_SIZE_MASK);
- }
- else
+ void *base = heapPtr->subheap.heap;
+ HeapUnlock( heap );
+ UnmapViewOfFile( heapPtr );
+ if (!(heapPtr = MapViewOfFileEx( map, FILE_MAP_ALL_ACCESS, 0, 0, 0, base )))
{
- if (!HEAP_ValidateInUseArena( subheap, (ARENA_INUSE *)ptr ))
- return FALSE;
- ptr += sizeof(ARENA_INUSE) + (*(DWORD *)ptr & ARENA_SIZE_MASK);
+ fprintf( stderr, "Couldn't map system heap at the correct address (%p)\n", base );
+ CloseHandle( map );
+ return FALSE;
}
+ heap = (HANDLE)heapPtr;
+ HeapLock( heap );
}
- subheap = subheap->next;
+ descr = heapPtr->private;
+ assert( descr );
}
+ SystemHeap = heap;
+ SystemHeapDescr = descr;
+ HeapUnlock( heap );
+ CloseHandle( map );
return TRUE;
}
+#endif
HANDLE STDCALL RtlGetProcessHeap(VOID)
{
}
VOID
-RtlpInitProcessHeaps (PPEB Peb)
+RtlInitializeHeapManager (VOID)
{
- Peb->NumberOfHeaps = 0;
- Peb->MaximumNumberOfHeaps = (PAGESIZE - sizeof(PPEB)) / sizeof(HANDLE);
- Peb->ProcessHeaps = (PVOID)Peb + sizeof(PEB);
-
- RtlInitializeCriticalSection (&ProcessHeapsLock);
+ PPEB Peb;
+
+ Peb = NtCurrentPeb();
+
+ Peb->NumberOfHeaps = 0;
+ Peb->MaximumNumberOfHeaps = (PAGESIZE - sizeof(PPEB)) / sizeof(HANDLE);
+ Peb->ProcessHeaps = (PVOID)Peb + sizeof(PEB);
+
+ RtlInitializeCriticalSection (&RtlpProcessHeapsListLock);
}
NTSTATUS Status = STATUS_SUCCESS;
ULONG i;
- RtlEnterCriticalSection (&ProcessHeapsLock);
+ RtlEnterCriticalSection (&RtlpProcessHeapsListLock);
for (i = 0; i < NtCurrentPeb ()->NumberOfHeaps; i++)
{
break;
}
- RtlLeaveCriticalSection (&ProcessHeapsLock);
+ RtlLeaveCriticalSection (&RtlpProcessHeapsListLock);
return Status;
}
-
ULONG
STDCALL
RtlGetProcessHeaps (
{
ULONG Result = 0;
- RtlEnterCriticalSection (&ProcessHeapsLock);
+ RtlEnterCriticalSection (&RtlpProcessHeapsListLock);
if (NtCurrentPeb ()->NumberOfHeaps <= HeapCount)
{
Result * sizeof(HANDLE));
}
- RtlLeaveCriticalSection (&ProcessHeapsLock);
+ RtlLeaveCriticalSection (&RtlpProcessHeapsListLock);
return Result;
}
return Result;
}
-
-/* EOF */
-/* $Id: winlogon.c,v 1.5 1999/11/20 21:53:53 ekohl Exp $
+/* $Id: winlogon.c,v 1.6 2000/08/12 19:33:23 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
/* INCLUDES *****************************************************************/
-#include <ddk/ntddk.h>
-//#include <stdio.h>
+#include <ntos.h>
+#include <windows.h>
+#include <stdio.h>
+#include <lsass/ntsecapi.h>
#include <wchar.h>
/* GLOBALS ******************************************************************/
-HANDLE SM = INVALID_HANDLE_VALUE; /* SM API LPC port */
-HANDLE SasEvent = INVALID_HANDLE_VALUE; /* int 0x19 */
-
-
/* FUNCTIONS *****************************************************************/
-
-/***********************************************************************
- * SmTerminationRequestHandler
- */
-VOID
-STDCALL
-SmTerminationRequestHandler (VOID)
+BOOLEAN StartServices(VOID)
{
- /* Should winlogon perform any action
- * before committing suicide?
- */
- NtTerminateProcess(
- NtCurrentProcess(),
- 0
- );
+ HANDLE ServicesInitEvent;
+ BOOLEAN Result;
+ STARTUPINFO StartupInfo;
+ PROCESS_INFORMATION ProcessInformation;
+
+ ServicesInitEvent = CreateEvent(NULL,
+ TRUE,
+ FALSE,
+ "\\ServicesInitDone");
+
+ if (ServicesInitEvent == NULL)
+ {
+ DbgPrint("Failed to create services notification event\n");
+ return(FALSE);
+ }
+
+ /* Start the Win32 subsystem (csrss.exe) */
+ DbgPrint("WL: Executing services.exe\n");
+
+ StartupInfo.cb = sizeof(StartupInfo);
+ StartupInfo.lpReserved = NULL;
+ StartupInfo.lpDesktop = NULL;
+ StartupInfo.lpTitle = NULL;
+ StartupInfo.dwFlags = 0;
+ StartupInfo.cbReserved2 = 0;
+ StartupInfo.lpReserved2 = 0;
+
+ Result = CreateProcess("C:\\reactos\\system32\\services.exe",
+ NULL,
+ NULL,
+ NULL,
+ FALSE,
+ DETACHED_PROCESS,
+ NULL,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation);
+ if (!Result)
+ {
+ DbgPrint("WL: Failed to execute services\n");
+ return(FALSE);
+ }
+
+ DbgPrint("WL: Waiting for services\n");
+ WaitForSingleObject(ServicesInitEvent, INFINITE);
+
+ DbgPrint("WL: Finished waiting for services\n");
+ return(TRUE);
}
-
-/***********************************************************************
- * HasSystemGui
- *
- * DESCRIPTION
- * Call the Session Manager to know if user I/O is via a GUI or
- * via a CUI.
- *
- * RETURN VALUE
- * TRUE GUI active
- * FALSE CUI only
- */
-BOOL
-HasSystemGui (VOID)
+BOOLEAN StartLsass(VOID)
{
- /* FIXME: call smss.exe to know, since it
- * controls environment subsystem servers
- * waking up. ReactOS has only text mode
- * now, therefore we can answer (EA.19990608).
- */
- return FALSE; /* NO GUI */
+ HANDLE LsassInitEvent;
+ BOOLEAN Result;
+ STARTUPINFO StartupInfo;
+ PROCESS_INFORMATION ProcessInformation;
+
+ LsassInitEvent = CreateEvent(NULL,
+ TRUE,
+ FALSE,
+ "\\LsassInitDone");
+
+ if (LsassInitEvent == NULL)
+ {
+ DbgPrint("Failed to create lsass notification event\n");
+ return(FALSE);
+ }
+
+ /* Start the Win32 subsystem (csrss.exe) */
+ DbgPrint("WL: Executing lsass.exe\n");
+
+ StartupInfo.cb = sizeof(StartupInfo);
+ StartupInfo.lpReserved = NULL;
+ StartupInfo.lpDesktop = NULL;
+ StartupInfo.lpTitle = NULL;
+ StartupInfo.dwFlags = 0;
+ StartupInfo.cbReserved2 = 0;
+ StartupInfo.lpReserved2 = 0;
+
+ Result = CreateProcess("C:\\reactos\\system32\\lsass.exe",
+ NULL,
+ NULL,
+ NULL,
+ FALSE,
+ DETACHED_PROCESS,
+ NULL,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation);
+ if (!Result)
+ {
+ DbgPrint("WL: Failed to execute lsass\n");
+ return(FALSE);
+ }
+
+ DbgPrint("WL: Waiting for lsass\n");
+ WaitForSingleObject(LsassInitEvent, INFINITE);
+
+ DbgPrint("WL: Finished waiting for lsass\n");
+ return(TRUE);
}
-
-/***********************************************************************
- * HasSystemActiveSession
- *
- * DESCRIPTION
- * Call the Session Manager to know if there is already an active
- * session.
- *
- * RETURN VALUE
- * TRUE a session is active
- * FALSE no sessions
- */
-BOOL
-HasSystemActiveSession (VOID)
+VOID DoLoginUser(PCHAR Name, PCHAR Password)
{
- /* FIXME: call smss.exe to know */
- return FALSE; /* NO SESSIONS */
+ PROCESS_INFORMATION ProcessInformation;
+ STARTUPINFO StartupInfo;
+ BOOLEAN Result;
+
+ StartupInfo.cb = sizeof(StartupInfo);
+ StartupInfo.lpReserved = NULL;
+ StartupInfo.lpDesktop = NULL;
+ StartupInfo.lpTitle = NULL;
+ StartupInfo.dwFlags = 0;
+ StartupInfo.cbReserved2 = 0;
+ StartupInfo.lpReserved2 = 0;
+
+ Result = CreateProcess("C:\\reactos\\system32\\shell.exe",
+ NULL,
+ NULL,
+ NULL,
+ FALSE,
+ DETACHED_PROCESS,
+ NULL,
+ NULL,
+ &StartupInfo,
+ &ProcessInformation);
+ if (!Result)
+ {
+ DbgPrint("WL: Failed to execute user shell\n");
+ return;
+ }
+ WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
}
-
-/***********************************************************************
- * GuiLogin
- *
- * DESCRIPTION
- * Graphical login procedure
- *
- * NOTE
- * Read values from
- *
- * HKEY_LOCAL-MACHINE
- * SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon
- *
- */
-VOID
-GuiLogin (VOID)
+int STDCALL
+WinMain(HINSTANCE hInstance,
+ HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine,
+ int nShowCmd)
{
- /* FIXME: Open logon dialog */
-}
-
-
-/***********************************************************************
- * GuiMonitor
- *
- * DESCRIPTION
- * Graphical monitor procedure
- */
-VOID
-GuiMonitor (VOID)
-{
- /* FIXME: Open Monitor dialog */
-}
-
-
-/***********************************************************************
- * CuiLogin
- *
- * DESCRIPTION
- * Text mode (console) login procedure
- *
- * NOTE
- * Read values from
- *
- * HKEY_LOCAL-MACHINE
- * SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon
- *
- */
-VOID
-CuiLogin (VOID)
-{
- char username[255];
- char password[255];
-
- /* FIXME: to be used ntdll.dll only? */
- printf("Winlogon\n");
- printf("login: ");
- fgets(username, 255, stdin);
- printf("Password: ");
- fgets(password, 255, stdin);
- /*
- *
- */
- NtCreateProcess(
- L"\\\\??\\C:\\reactos\\system\\userinit.exe",
- );
- /*
- * Security issue: buffers are cleared.
- */
- NtZeroMemory(username, sizeof username);
- NtZeroMemory(password, sizeof password);
+#if 0
+ LSA_STRING ProcessName;
+ NTSTATUS Status;
+ HANDLE LsaHandle;
+ LSA_OPERATIONAL_MODE Mode;
+#endif
+ CHAR LoginPrompt[] = "login:";
+ CHAR PasswordPrompt[] = "password:";
+ ULONG Result;
+ CHAR LoginName[255];
+ CHAR Password[255];
+ ULONG i;
+
+ /*
+ * FIXME: Create WindowStations here. At the moment lsass and services
+ * share ours
+ */
+
+ StartLsass();
+ StartServices();
+
+ /* FIXME: What name does the real WinLogon use? */
+#if 0
+ RtlInitUnicodeString((PUNICODE_STRING)&ProcessName, L"WinLogon");
+ Status = LsaRegisterLogonProcess(&ProcessName, &LsaHandle, &Mode);
+ if (!NT_SUCCESS(Status))
+ {
+ DbgPrint("WL: Failed to connect to lsass\n");
+ return(1);
+ }
+#endif
+
+ /* smss wouldn't have created a console for us */
+ AllocConsole();
+
+ /* Main loop */
+ for (;;)
+ {
+ /* Display login prompt */
+ WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),
+ LoginPrompt,
+ wcslen(LoginPrompt),
+ &Result,
+ NULL);
+ i = 0;
+ do
+ {
+ ReadConsole(GetStdHandle(STD_INPUT_HANDLE),
+ &LoginName[i],
+ 1,
+ &Result,
+ NULL);
+ i++;
+ } while (LoginName[i - 1] != '\n');
+ LoginName[i - 1] = 0;
+
+ /* Display password prompt */
+ WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),
+ PasswordPrompt,
+ wcslen(PasswordPrompt),
+ &Result,
+ NULL);
+ i = 0;
+ do
+ {
+ ReadConsole(GetStdHandle(STD_INPUT_HANDLE),
+ &Password[i],
+ 1,
+ &Result,
+ NULL);
+ i++;
+ } while (Password[i - 1] != '\n');
+ Password[i - 1] =0;
+
+ DoLoginUser(LoginName, Password);
+ }
}
-
-
-/***********************************************************************
- * CuiMonitor
- *
- * DESCRIPTION
- * Text mode (console) Monitor procedure
- */
-VOID
-CuiMonitor (VOID)
-{
- WCHAR HostName [64];
- WCHAR UserName [64];
- WCHAR FormattedDate [64];
- WCHAR InputKey = L'\0';
-
- /* FIXME: query the system to get these info */
- wcscpy( HostName, L"BACH" );
- wcscpy( UserName, L"Administrator" );
-
- /* FIXME: use locale info to format */
- NtGetSystemTime(
- );
-
- /* Print info and Monitor menu */
- NtDisplayString(L"\
-ReactOS Security:\n\
-\tYou are logged on as %s/%s\n\
-\yLogon date: %s\n\n\
-Use the Task Manager to close an application that is not responding.\n\n\
-1) Lock Workstation\n\
-2) Change Password\n\
-3) Logoff...\n\
-4) Task Manager...\n\
-5) Shut Down...\n\
-6) Cancel\n\n? ",
- HostName,
- UserName,
- FormattedDate
- );
- while (TRUE)
- {
- /* FIXME: get a char and perform the requested action */
- switch (InputKey)
- {
- case L'1':
- DisplayString(L"Workstation locked...\n");
- return;
- case L'2':
- DisplayString(L"Changing Password:\n");
- return;
- case L'3':
- DisplayString(L"Logging off...\n");
- return;
- case L'4':
- DisplayString(L"Task Manager:\n");
- return;
- case L'5':
- DisplayString(L"Shutting Down:\n");
- DisplayString(L"1) Shutdown\n");
- DisplayString(L"2) Restart\n");
- DisplayString(L"3) Logoff\n");
- DisplayString(L"4) Cancel\n");
- return;
- case 27L: /* ESC */
- case L'6':
- return;
- default:
- DisplayString(L"Invalid key (1-6).\n");
- }
- }
-}
-
-
-HANDLE
-ConnectToSmApiPort(VOID)
-{
- HANDLE PortHandle;
- NTSTATUS Status = STATUS_SUCCESS;
- UNICODE_STRING SmApiPort;
- LPWSTR PortName = L"\\SmApiPort";
- OBJECT_ATTRIBUTES PortAttributes = {0};
-
- SmApiPort.Length = wcslen(PortName) * sizeof (WCHAR);
- SmApiPort.MaxLength = SmApiPort.Length + sizeof (WCHAR);
- SmApiPort.Buffer = PortName;
- Status = NtConnectPort(
- & PortHandle,
- & SmApiPort,
- & PortAttributes, /* FIXME: ? */
- 0, /* FIXME: ? */
- 0, /* FIXME: ? */
- 0, /* FIXME: ? */
- 0, /* FIXME: ? */
- 0x00010000 /* FIXME: ? */
- );
- return (NT_SUCCESS(Status))
- ? PortHandle
- : INVALID_HANDLE_VALUE;
-}
-
-
-/* Native process entry point */
-void
-NtProcessStartup( PSTARTUP_ARGUMENT StartupArgument )
-{
- NTSTATUS Status = STATUS_SUCCESS;
-
- /* FIXME: connnect to the Session Manager
- * for LPC calls
- */
- SM = ConnectToSmApiPort();
- if (INVALID_HANDLE_VALUE == SM)
- {
- NtTerminateProcess(
- NtCurrentProcess(),
- 0 /* FIXME: return a proper value to SM */
- );
- }
- /* FIXME: register a termination callback
- * for smss.exe
- */
- /* ??? register SmTerminationRequestHandler */
- /* FIXME: hook Ctrl+Alt+Del (int 0x19)
- * (SAS = Secure Attention Sequence)
- */
- /* ??? SasEvent = ? */
- while (TRUE)
- {
- /*
- * Make the main thread wait
- * for SAS indefinitely.
- */
- NtWaitForSingleObject(
- SasEvent
- /* ... */
- );
- /*
- * If there is no local session, begin
- * the logon procedure; otherwise open
- * the monitor dialog.
- */
- if (TRUE == HasSystemActiveSession())
- {
- /* MONITOR */
- if (TRUE == HasSystemGui())
- {
- /* GUI active: monitor in graphical mode */
- GuiMonitor();
- continue;
- }
- /* No GUI: monitor in text mode */
- CuiMonitor();
- continue;
- }
- /* LOGON */
- if (TRUE == HasSystemGui())
- {
- /* GUI active, login in graphical mode */
- GuiLogin();
- continue;
- }
- /* No GUI, login in console mode */
- CuiLogin();
- }
-}
-
-
-/* EOF */