331 lines
9.7 KiB
C
331 lines
9.7 KiB
C
|
/*
|
||
|
* Win32 processes
|
||
|
*
|
||
|
* Copyright 1996 Alexandre Julliard
|
||
|
*/
|
||
|
|
||
|
#include <assert.h>
|
||
|
#include "process.h"
|
||
|
#include "heap.h"
|
||
|
#include "task.h"
|
||
|
#include "winerror.h"
|
||
|
|
||
|
PDB32 *pCurrentProcess = NULL;
|
||
|
|
||
|
#define HTABLE_SIZE 0x30 /* Handle table initial size */
|
||
|
#define HTABLE_INC 0x10 /* Handle table increment */
|
||
|
|
||
|
#define BOOT_HTABLE_SIZE 5
|
||
|
|
||
|
static HANDLE_ENTRY boot_handles[BOOT_HTABLE_SIZE];
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_AllocHandleTable
|
||
|
*/
|
||
|
static HANDLE_TABLE *PROCESS_AllocHandleTable( PDB32 *process )
|
||
|
{
|
||
|
HANDLE_TABLE *table = HeapAlloc( process->system_heap, HEAP_ZERO_MEMORY,
|
||
|
sizeof(HANDLE_TABLE) +
|
||
|
(HTABLE_SIZE-1) * sizeof(HANDLE_ENTRY) );
|
||
|
if (!table) return NULL;
|
||
|
table->count = HTABLE_SIZE;
|
||
|
return table;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_GrowHandleTable
|
||
|
*/
|
||
|
static BOOL32 PROCESS_GrowHandleTable( PDB32 *process )
|
||
|
{
|
||
|
HANDLE_TABLE *table = process->handle_table;
|
||
|
table = HeapReAlloc( process->system_heap, HEAP_ZERO_MEMORY, table,
|
||
|
sizeof(HANDLE_TABLE) +
|
||
|
(table->count+HTABLE_INC-1) * sizeof(HANDLE_ENTRY) );
|
||
|
if (!table) return FALSE;
|
||
|
table->count += HTABLE_INC;
|
||
|
process->handle_table = table;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_AllocBootHandle
|
||
|
*
|
||
|
* Allocate a handle from the boot table.
|
||
|
*/
|
||
|
static HANDLE32 PROCESS_AllocBootHandle( K32OBJ *ptr, DWORD flags )
|
||
|
{
|
||
|
HANDLE32 h;
|
||
|
for (h = 0; h < BOOT_HTABLE_SIZE; h++)
|
||
|
if (!boot_handles[h].ptr) break;
|
||
|
assert( h < BOOT_HTABLE_SIZE );
|
||
|
K32OBJ_IncCount( ptr );
|
||
|
boot_handles[h].flags = flags;
|
||
|
boot_handles[h].ptr = ptr;
|
||
|
return h + 1; /* Avoid handle 0 */
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_CloseBootHandle
|
||
|
*
|
||
|
* Close a handle from the boot table.
|
||
|
*/
|
||
|
static BOOL32 PROCESS_CloseBootHandle( HANDLE32 handle )
|
||
|
{
|
||
|
HANDLE_ENTRY *entry = &boot_handles[handle - 1];
|
||
|
assert( (handle > 0) && (handle <= BOOT_HTABLE_SIZE) );
|
||
|
assert( entry->ptr );
|
||
|
K32OBJ_DecCount( entry->ptr );
|
||
|
entry->flags = 0;
|
||
|
entry->ptr = NULL;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_GetBootObjPtr
|
||
|
*
|
||
|
* Get a handle ptr from the boot table.
|
||
|
*/
|
||
|
static K32OBJ *PROCESS_GetBootObjPtr( HANDLE32 handle, K32OBJ_TYPE type )
|
||
|
{
|
||
|
K32OBJ *ptr;
|
||
|
|
||
|
assert( (handle > 0) && (handle <= BOOT_HTABLE_SIZE) );
|
||
|
ptr = boot_handles[handle - 1].ptr;
|
||
|
assert (ptr && (ptr->type == type));
|
||
|
K32OBJ_IncCount( ptr );
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_SetBootObjPtr
|
||
|
*
|
||
|
* Set a handle ptr from the boot table.
|
||
|
*/
|
||
|
static BOOL32 PROCESS_SetBootObjPtr( HANDLE32 handle, K32OBJ *ptr, DWORD flags)
|
||
|
{
|
||
|
K32OBJ *old_ptr;
|
||
|
|
||
|
assert( (handle > 0) && (handle <= BOOT_HTABLE_SIZE) );
|
||
|
K32OBJ_IncCount( ptr );
|
||
|
if ((old_ptr = boot_handles[handle - 1].ptr)) K32OBJ_DecCount( old_ptr );
|
||
|
boot_handles[handle - 1].flags = flags;
|
||
|
boot_handles[handle - 1].ptr = ptr;
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_AllocHandle
|
||
|
*
|
||
|
* Allocate a handle for a kernel object and increment its refcount.
|
||
|
*/
|
||
|
HANDLE32 PROCESS_AllocHandle( K32OBJ *ptr, DWORD flags )
|
||
|
{
|
||
|
HANDLE32 h;
|
||
|
HANDLE_ENTRY *entry;
|
||
|
|
||
|
assert( ptr );
|
||
|
if (!pCurrentProcess) return PROCESS_AllocBootHandle( ptr, flags );
|
||
|
EnterCriticalSection( &pCurrentProcess->crit_section );
|
||
|
K32OBJ_IncCount( ptr );
|
||
|
entry = pCurrentProcess->handle_table->entries;
|
||
|
for (h = 0; h < pCurrentProcess->handle_table->count; h++, entry++)
|
||
|
if (!entry->ptr) break;
|
||
|
if ((h < pCurrentProcess->handle_table->count) ||
|
||
|
PROCESS_GrowHandleTable( pCurrentProcess ))
|
||
|
{
|
||
|
entry->flags = flags;
|
||
|
entry->ptr = ptr;
|
||
|
LeaveCriticalSection( &pCurrentProcess->crit_section );
|
||
|
return h + 1; /* Avoid handle 0 */
|
||
|
}
|
||
|
LeaveCriticalSection( &pCurrentProcess->crit_section );
|
||
|
SetLastError( ERROR_OUTOFMEMORY );
|
||
|
K32OBJ_DecCount( ptr );
|
||
|
return INVALID_HANDLE_VALUE32;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_GetObjPtr
|
||
|
*
|
||
|
* Retrieve a pointer to a kernel object and increments its reference count.
|
||
|
* The refcount must be decremented when the pointer is no longer used.
|
||
|
*/
|
||
|
K32OBJ *PROCESS_GetObjPtr( HANDLE32 handle, K32OBJ_TYPE type )
|
||
|
{
|
||
|
K32OBJ *ptr = NULL;
|
||
|
if (!pCurrentProcess) return PROCESS_GetBootObjPtr( handle, type );
|
||
|
EnterCriticalSection( &pCurrentProcess->crit_section );
|
||
|
if ((handle > 0) && (handle <= pCurrentProcess->handle_table->count))
|
||
|
{
|
||
|
ptr = pCurrentProcess->handle_table->entries[handle - 1].ptr;
|
||
|
if (ptr && ((type == K32OBJ_UNKNOWN) || (ptr->type == type)))
|
||
|
K32OBJ_IncCount( ptr );
|
||
|
else ptr = NULL;
|
||
|
}
|
||
|
LeaveCriticalSection( &pCurrentProcess->crit_section );
|
||
|
if (!ptr) SetLastError( ERROR_INVALID_HANDLE );
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_SetObjPtr
|
||
|
*
|
||
|
* Change the object pointer of a handle, and increment the refcount.
|
||
|
* Use with caution!
|
||
|
*/
|
||
|
BOOL32 PROCESS_SetObjPtr( HANDLE32 handle, K32OBJ *ptr, DWORD flags )
|
||
|
{
|
||
|
BOOL32 ret = TRUE;
|
||
|
K32OBJ *old_ptr = NULL;
|
||
|
|
||
|
if (!pCurrentProcess) return PROCESS_SetBootObjPtr( handle, ptr, flags );
|
||
|
EnterCriticalSection( &pCurrentProcess->crit_section );
|
||
|
if ((handle > 0) && (handle <= pCurrentProcess->handle_table->count))
|
||
|
{
|
||
|
HANDLE_ENTRY*entry = &pCurrentProcess->handle_table->entries[handle-1];
|
||
|
old_ptr = entry->ptr;
|
||
|
K32OBJ_IncCount( ptr );
|
||
|
entry->flags = flags;
|
||
|
entry->ptr = ptr;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
SetLastError( ERROR_INVALID_HANDLE );
|
||
|
ret = FALSE;
|
||
|
}
|
||
|
LeaveCriticalSection( &pCurrentProcess->crit_section );
|
||
|
if (old_ptr) K32OBJ_DecCount( old_ptr );
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*********************************************************************
|
||
|
* CloseHandle (KERNEL32.23)
|
||
|
*/
|
||
|
BOOL32 CloseHandle( HANDLE32 handle )
|
||
|
{
|
||
|
BOOL32 ret = FALSE;
|
||
|
K32OBJ *ptr = NULL;
|
||
|
|
||
|
if (!pCurrentProcess) return PROCESS_CloseBootHandle( handle );
|
||
|
EnterCriticalSection( &pCurrentProcess->crit_section );
|
||
|
if ((handle > 0) && (handle <= pCurrentProcess->handle_table->count))
|
||
|
{
|
||
|
HANDLE_ENTRY*entry = &pCurrentProcess->handle_table->entries[handle-1];
|
||
|
if ((ptr = entry->ptr))
|
||
|
{
|
||
|
entry->flags = 0;
|
||
|
entry->ptr = NULL;
|
||
|
ret = TRUE;
|
||
|
}
|
||
|
}
|
||
|
LeaveCriticalSection( &pCurrentProcess->crit_section );
|
||
|
if (!ret) SetLastError( ERROR_INVALID_HANDLE );
|
||
|
if (ptr) K32OBJ_DecCount( ptr );
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_Create
|
||
|
*/
|
||
|
PDB32 *PROCESS_Create(void)
|
||
|
{
|
||
|
PDB32 *pdb = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY, sizeof(PDB32) );
|
||
|
if (!pdb) return NULL;
|
||
|
pdb->header.type = K32OBJ_PROCESS;
|
||
|
pdb->header.refcount = 1;
|
||
|
pdb->exit_code = 0x103; /* STILL_ACTIVE */
|
||
|
pdb->threads = 1;
|
||
|
pdb->running_threads = 1;
|
||
|
pdb->ring0_threads = 1;
|
||
|
pdb->system_heap = SystemHeap;
|
||
|
pdb->parent = pCurrentProcess;
|
||
|
pdb->group = pdb;
|
||
|
pdb->priority = 8; /* Normal */
|
||
|
InitializeCriticalSection( &pdb->crit_section );
|
||
|
if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) goto error;
|
||
|
if (!(pdb->env_DB = HeapAlloc(pdb->heap, HEAP_ZERO_MEMORY, sizeof(ENVDB))))
|
||
|
goto error;
|
||
|
if (!(pdb->handle_table = PROCESS_AllocHandleTable( pdb ))) goto error;
|
||
|
pdb->heap_list = pdb->heap;
|
||
|
return pdb;
|
||
|
|
||
|
error:
|
||
|
if (pdb->env_DB) HeapFree( pdb->heap, 0, pdb->env_DB );
|
||
|
if (pdb->handle_table) HeapFree( pdb->system_heap, 0, pdb->handle_table );
|
||
|
if (pdb->heap) HeapDestroy( pdb->heap );
|
||
|
DeleteCriticalSection( &pdb->crit_section );
|
||
|
HeapFree( SystemHeap, 0, pdb );
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* PROCESS_Destroy
|
||
|
*/
|
||
|
void PROCESS_Destroy( K32OBJ *ptr )
|
||
|
{
|
||
|
PDB32 *pdb = (PDB32 *)ptr;
|
||
|
HANDLE32 handle;
|
||
|
assert( ptr->type == K32OBJ_PROCESS );
|
||
|
|
||
|
/* Close all handles */
|
||
|
for (handle = 0; handle < pdb->handle_table->count; handle++)
|
||
|
if (pdb->handle_table->entries[handle].ptr) CloseHandle( handle );
|
||
|
|
||
|
/* Free everything */
|
||
|
|
||
|
ptr->type = K32OBJ_UNKNOWN;
|
||
|
HeapFree( pdb->heap, 0, pdb->env_DB );
|
||
|
HeapFree( pdb->system_heap, 0, pdb->handle_table );
|
||
|
HeapDestroy( pdb->heap );
|
||
|
DeleteCriticalSection( &pdb->crit_section );
|
||
|
HeapFree( SystemHeap, 0, pdb );
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* ExitProcess (KERNEL32.100)
|
||
|
*/
|
||
|
void ExitProcess( DWORD status )
|
||
|
{
|
||
|
TASK_KillCurrentTask( status );
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* GetCurrentProcess (KERNEL32.198)
|
||
|
*/
|
||
|
HANDLE32 GetCurrentProcess(void)
|
||
|
{
|
||
|
return 0x7fffffff;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* GetCurrentProcessId (KERNEL32.199)
|
||
|
*/
|
||
|
DWORD GetCurrentProcessId(void)
|
||
|
{
|
||
|
return (DWORD)pCurrentProcess;
|
||
|
}
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
* GetProcessHeap (KERNEL32.259)
|
||
|
*/
|
||
|
HANDLE32 GetProcessHeap(void)
|
||
|
{
|
||
|
if (!pCurrentProcess) return SystemHeap; /* For the boot-up code */
|
||
|
return pCurrentProcess->heap;
|
||
|
}
|