Commit 8139c301 authored by Ulrich Weigand's avatar Ulrich Weigand Committed by Alexandre Julliard

Implemented PROCESS_CallUserSignalProc().

Send USER signals at various appropriate places. Moved [GS]etProcessDword() to scheduler/process.c.
parent 7c6cc49c
......@@ -102,6 +102,47 @@ typedef struct _PDB
#define PDB32_FILE_APIS_OEM 0x0040 /* File APIs are OEM */
#define PDB32_WIN32S_PROC 0x8000 /* Win32s process */
/* USER signal proc flags and codes */
/* See PROCESS_CallUserSignalProc for comments */
#define USIG_FLAGS_WIN32 0x0001
#define USIG_FLAGS_GUI 0x0002
#define USIG_FLAGS_FEEDBACK 0x0004
#define USIG_FLAGS_FAULT 0x0008
#define USIG_DLL_UNLOAD_WIN16 0x0001
#define USIG_DLL_UNLOAD_WIN32 0x0002
#define USIG_FAULT_DIALOG_PUSH 0x0003
#define USIG_FAULT_DIALOG_POP 0x0004
#define USIG_DLL_UNLOAD_ORPHANS 0x0005
#define USIG_THREAD_INIT 0x0010
#define USIG_THREAD_EXIT 0x0020
#define USIG_PROCESS_CREATE 0x0100
#define USIG_PROCESS_INIT 0x0200
#define USIG_PROCESS_EXIT 0x0300
#define USIG_PROCESS_DESTROY 0x0400
#define USIG_PROCESS_RUNNING 0x0500
#define USIG_PROCESS_LOADED 0x0600
/* [GS]etProcessDword offsets */
#define GPD_APP_COMPAT_FLAGS (-56)
#define GPD_LOAD_DONE_EVENT (-52)
#define GPD_HINSTANCE16 (-48)
#define GPD_WINDOWS_VERSION (-44)
#define GPD_THDB (-40)
#define GPD_PDB (-36)
#define GPD_STARTF_SHELLDATA (-32)
#define GPD_STARTF_HOTKEY (-28)
#define GPD_STARTF_SHOWWINDOW (-24)
#define GPD_STARTF_SIZE (-20)
#define GPD_STARTF_POSITION (-16)
#define GPD_STARTF_FLAGS (-12)
#define GPD_PARENT_PDB (- 8)
#define GPD_FLAGS (- 4)
#define GPD_USERDATA ( 0)
extern DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset );
void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value );
/* scheduler/environ.c */
extern BOOL ENV_BuildEnvironment( PDB *pdb );
extern BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env );
......@@ -113,6 +154,7 @@ extern PDB *PROCESS_Current(void);
extern BOOL PROCESS_IsCurrent( HANDLE handle );
extern PDB *PROCESS_Initial(void);
extern PDB *PROCESS_IdToPDB( DWORD id );
extern void PROCESS_CallUserSignalProc( UINT uCode, HMODULE hModule );
extern PDB *PROCESS_Create( struct _NE_MODULE *pModule,
LPCSTR cmd_line, LPCSTR env,
HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
......
......@@ -1088,8 +1088,10 @@ static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep )
/* Free the objects owned by the DLL module */
if (pTask && pTask->userhandler)
pTask->userhandler( hModule, USIG_DLL_UNLOAD, 0,
pTask->userhandler( hModule, USIG16_DLL_UNLOAD, 0,
pTask->hInstance, pTask->hQueue );
PROCESS_CallUserSignalProc( USIG_DLL_UNLOAD_WIN16, hModule );
}
else
call_wep = FALSE; /* We are freeing a task -> no more WEPs */
......
......@@ -617,15 +617,10 @@ static BOOL NE_InitDLL( TDB* pTask, NE_MODULE *pModule )
if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
(pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
/* Call USER signal handler. This is necessary to install a
* proper loader for HICON and HCURSOR resources that this DLL
* may contain. InitApp() does this for task modules. */
/* Call USER signal handler for Win3.1 compatibility. */
if (pTask && pTask->userhandler)
{
pTask->userhandler( pModule->self, USIG_DLL_LOAD, 0, pTask->hInstance,
pTask->hQueue );
}
pTask->userhandler( pModule->self, USIG16_DLL_LOAD, 0,
pTask->hInstance, pTask->hQueue );
if (!pModule->cs) return TRUE; /* no initialization code */
......
......@@ -238,6 +238,12 @@ static void TASK_CallToStart(void)
/* Terminate the stack frame chain */
memset(THREAD_STACK16( pTask->thdb ), '\0', sizeof(STACK16FRAME));
/* Call USER signal proc */
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 ); /* for initial thread */
PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0 );
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 );
if (pModule->flags & NE_FFLAGS_WIN32)
{
ERR( task, "Called for Win32 task!\n" );
......@@ -297,7 +303,7 @@ BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
HINSTANCE16 hPrevInstance, UINT16 cmdShow)
{
HTASK16 hTask;
TDB *pTask, *pInitialTask;
TDB *pTask;
LPSTR cmd_line;
WORD sp;
char *stack32Top;
......@@ -396,12 +402,6 @@ BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
pTask->dta = PTR_SEG_OFF_TO_SEGPTR( pTask->hPDB,
(int)&pTask->pdb.cmdLine - (int)&pTask->pdb );
/* Inherit default UserSignalHandler from initial process */
pInitialTask = (TDB *)GlobalLock16( PROCESS_Initial()->task );
if ( pInitialTask )
pTask->userhandler = pInitialTask->userhandler;
/* If we have a DGROUP/hInstance, use it for 16-bit stack */
if ( hInstance )
......@@ -571,9 +571,13 @@ void TASK_KillTask( HTASK16 hTask )
/* Perform USER cleanup */
if (pTask->userhandler)
pTask->userhandler( hCurrentTask, USIG_TERMINATION, 0,
pTask->userhandler( hTask, USIG16_TERMINATION, 0,
pTask->hInstance, pTask->hQueue );
PROCESS_CallUserSignalProc( USIG_PROCESS_EXIT, 0 );
PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 ); /* FIXME */
PROCESS_CallUserSignalProc( USIG_PROCESS_DESTROY, 0 );
if (nTaskCount <= 1)
{
TRACE(task, "this is the last task, exiting\n" );
......
......@@ -22,6 +22,7 @@
#include "pe_image.h"
#include "task.h"
#include "server.h"
#include "callback.h"
#include "debug.h"
......@@ -99,6 +100,123 @@ PDB *PROCESS_IdToPDB( DWORD id )
}
/***********************************************************************
* PROCESS_CallUserSignalProc
*
* FIXME: Some of the signals aren't sent correctly!
*
* The exact meaning of the USER signals is undocumented, but this
* should cover the basic idea:
*
* USIG_DLL_UNLOAD_WIN16
* This is sent when a 16-bit module is unloaded.
*
* USIG_DLL_UNLOAD_WIN32
* This is sent when a 32-bit module is unloaded.
*
* USIG_DLL_UNLOAD_ORPHANS
* This is sent after the last Win3.1 module is unloaded,
* to allow removal of orphaned menus.
*
* USIG_FAULT_DIALOG_PUSH
* USIG_FAULT_DIALOG_POP
* These are called to allow USER to prepare for displaying a
* fault dialog, even though the fault might have happened while
* inside a USER critical section.
*
* USIG_THREAD_INIT
* This is called from the context of a new thread, as soon as it
* has started to run.
*
* USIG_THREAD_EXIT
* This is called, still in its context, just before a thread is
* about to terminate.
*
* USIG_PROCESS_CREATE
* This is called, in the parent process context, after a new process
* has been created.
*
* USIG_PROCESS_INIT
* This is called in the new process context, just after the main thread
* has started execution (after the main thread's USIG_THREAD_INIT has
* been sent).
*
* USIG_PROCESS_LOADED
* This is called after the executable file has been loaded into the
* new process context.
*
* USIG_PROCESS_RUNNING
* This is called immediately before the main entry point is called.
*
* USIG_PROCESS_EXIT
* This is called in the context of a process that is about to
* terminate (but before the last thread's USIG_THREAD_EXIT has
* been sent).
*
* USIG_PROCESS_DESTROY
* This is called after a process has terminated.
*
*
* The meaning of the dwFlags bits is as follows:
*
* USIG_FLAGS_WIN32
* Current process is 32-bit.
*
* USIG_FLAGS_GUI
* Current process is a (Win32) GUI process.
*
* USIG_FLAGS_FEEDBACK
* Current process needs 'feedback' (determined from the STARTUPINFO
* flags STARTF_FORCEONFEEDBACK / STARTF_FORCEOFFFEEDBACK).
*
* USIG_FLAGS_FAULT
* The signal is being sent due to a fault.
*/
void PROCESS_CallUserSignalProc( UINT uCode, HMODULE hModule )
{
PDB *pdb = PROCESS_Current();
STARTUPINFOA *startup = pdb->env_db? pdb->env_db->startup_info : NULL;
DWORD dwFlags = 0, dwThreadOrProcessID;
/* Determine dwFlags */
if ( !(pdb->flags & PDB32_WIN16_PROC) )
dwFlags |= USIG_FLAGS_WIN32;
if ( !(pdb->flags & PDB32_CONSOLE_PROC) )
dwFlags |= USIG_FLAGS_GUI;
if ( dwFlags & USIG_FLAGS_GUI )
{
/* Feedback defaults to ON */
if ( !(startup && (startup->dwFlags & STARTF_FORCEOFFFEEDBACK)) )
dwFlags |= USIG_FLAGS_FEEDBACK;
}
else
{
/* Feedback defaults to OFF */
if ( startup && (startup->dwFlags & STARTF_FORCEONFEEDBACK) )
dwFlags |= USIG_FLAGS_FEEDBACK;
}
/* Get thread or process ID */
if ( uCode == USIG_THREAD_INIT || uCode == USIG_THREAD_EXIT )
dwThreadOrProcessID = GetCurrentThreadId();
else
dwThreadOrProcessID = GetCurrentProcessId();
/* Convert module handle to 16-bit */
if ( HIWORD( hModule ) )
hModule = MapHModuleLS( hModule );
/* Call USER signal proc */
if ( Callout.UserSignalProc )
Callout.UserSignalProc( uCode, dwThreadOrProcessID, dwFlags, hModule );
}
/***********************************************************************
* PROCESS_BuildEnvDB
......@@ -332,6 +450,8 @@ void PROCESS_Start(void)
NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
OFSTRUCT *ofs = (OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo);
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 ); /* for initial thread */
#if 0
/* Initialize the critical section */
......@@ -354,6 +474,8 @@ void PROCESS_Start(void)
#endif
PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0 );
/* Map system DLLs into this process (from initial process) */
/* FIXME: this is a hack */
pdb->modref_list = PROCESS_Initial()->modref_list;
......@@ -361,16 +483,21 @@ void PROCESS_Start(void)
/* Create 32-bit MODREF */
if (!PE_CreateModule( pModule->module32, ofs, 0, FALSE )) goto error;
PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0 ); /* FIXME: correct location? */
/* Initialize thread-local storage */
PE_InitTls();
if (PE_HEADER(pModule->module32)->OptionalHeader.Subsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI)
if ( pdb->flags & PDB32_CONSOLE_PROC )
AllocConsole();
/* Now call the entry point */
MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)1 );
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 );
entry = (LPTHREAD_START_ROUTINE)RVA_PTR(pModule->module32,
OptionalHeader.AddressOfEntryPoint);
TRACE(relay, "(entryproc=%p)\n", entry );
......@@ -432,6 +559,15 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
InitializeCriticalSection( &pdb->crit_section );
/* Setup process flags */
if ( !pModule->module32 )
pdb->flags |= PDB32_WIN16_PROC;
else if ( PE_HEADER(pModule->module32)->OptionalHeader.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_CUI )
pdb->flags |= PDB32_CONSOLE_PROC;
/* Create the heap */
if (pModule->module32)
......@@ -443,7 +579,6 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
{
size = 0x10000;
commit = 0;
pdb->flags |= PDB32_WIN16_PROC; /* This is a Win16 process */
}
if (!(pdb->heap = HeapCreate( HEAP_GROWABLE, size, commit ))) goto error;
pdb->heap_list = pdb->heap;
......@@ -531,6 +666,126 @@ BOOL WINAPI TerminateProcess( HANDLE handle, DWORD exit_code )
return !CLIENT_WaitReply( NULL, NULL, 0 );
}
/***********************************************************************
* GetProcessDword (KERNEL32.18) (KERNEL.485)
* 'Of course you cannot directly access Windows internal structures'
*/
DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset )
{
PDB *process = PROCESS_IdToPDB( dwProcessID );
TDB *pTask;
DWORD x, y;
TRACE( win32, "(%ld, %d)\n", dwProcessID, offset );
if ( !process ) return 0;
switch ( offset )
{
case GPD_APP_COMPAT_FLAGS:
pTask = (TDB *)GlobalLock16( process->task );
return pTask? pTask->compat_flags : 0;
case GPD_LOAD_DONE_EVENT:
return process->load_done_evt;
case GPD_HINSTANCE16:
pTask = (TDB *)GlobalLock16( process->task );
return pTask? pTask->hInstance : 0;
case GPD_WINDOWS_VERSION:
pTask = (TDB *)GlobalLock16( process->task );
return pTask? pTask->version : 0;
case GPD_THDB:
if ( process != PROCESS_Current() ) return 0;
return (DWORD)THREAD_Current();
case GPD_PDB:
return (DWORD)process;
case GPD_STARTF_SHELLDATA: /* return stdoutput handle from startupinfo ??? */
return process->env_db->startup_info->hStdOutput;
case GPD_STARTF_HOTKEY: /* return stdinput handle from startupinfo ??? */
return process->env_db->startup_info->hStdInput;
case GPD_STARTF_SHOWWINDOW:
return process->env_db->startup_info->wShowWindow;
case GPD_STARTF_SIZE:
x = process->env_db->startup_info->dwXSize;
if ( x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
y = process->env_db->startup_info->dwYSize;
if ( y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
return MAKELONG( x, y );
case GPD_STARTF_POSITION:
x = process->env_db->startup_info->dwX;
if ( x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
y = process->env_db->startup_info->dwY;
if ( y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
return MAKELONG( x, y );
case GPD_STARTF_FLAGS:
return process->env_db->startup_info->dwFlags;
case GPD_PARENT_PDB:
return (DWORD)process->parent;
case GPD_FLAGS:
return process->flags;
case GPD_USERDATA:
return process->process_dword;
default:
ERR( win32, "Unknown offset %d\n", offset );
return 0;
}
}
/***********************************************************************
* SetProcessDword (KERNEL.484)
* 'Of course you cannot directly access Windows internal structures'
*/
void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value )
{
PDB *process = PROCESS_IdToPDB( dwProcessID );
TRACE( win32, "(%ld, %d)\n", dwProcessID, offset );
if ( !process ) return;
switch ( offset )
{
case GPD_APP_COMPAT_FLAGS:
case GPD_LOAD_DONE_EVENT:
case GPD_HINSTANCE16:
case GPD_WINDOWS_VERSION:
case GPD_THDB:
case GPD_PDB:
case GPD_STARTF_SHELLDATA:
case GPD_STARTF_HOTKEY:
case GPD_STARTF_SHOWWINDOW:
case GPD_STARTF_SIZE:
case GPD_STARTF_POSITION:
case GPD_STARTF_FLAGS:
case GPD_PARENT_PDB:
case GPD_FLAGS:
ERR( win32, "Not allowed to modify offset %d\n", offset );
break;
case GPD_USERDATA:
process->process_dword = value;
break;
default:
ERR( win32, "Unknown offset %d\n", offset );
break;
}
}
/***********************************************************************
* GetCurrentProcess (KERNEL32.198)
*/
......
......@@ -154,10 +154,8 @@ void THREAD_FreeTHDB( THDB *thdb )
{
THDB **pptr = &THREAD_First;
/* cleanup the message queue, if there's one */
if (thdb->teb.queue)
USER_QueueCleanup( thdb->teb.queue );
PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 );
CloseHandle( thdb->event );
while (*pptr && (*pptr != thdb)) pptr = &(*pptr)->next;
if (*pptr) *pptr = thdb->next;
......@@ -281,6 +279,7 @@ static void THREAD_Start(void)
{
THDB *thdb = THREAD_Current();
LPTHREAD_START_ROUTINE func = (LPTHREAD_START_ROUTINE)thdb->entry_point;
PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 );
PE_InitTls();
MODULE_InitializeDLLs( 0, DLL_THREAD_ATTACH, NULL );
ExitThread( func( thdb->entry_arg ) );
......
......@@ -25,101 +25,6 @@ BOOL WINAPI WOWGetDescriptor(SEGPTR segptr,LPLDT_ENTRY ldtent)
return GetThreadSelectorEntry(GetCurrentThreadId(),segptr>>16,ldtent);
}
/***********************************************************************
* GetProcessDword (KERNEL32.18) (KERNEL.485)
* 'Of course you cannot directly access Windows internal structures'
*/
DWORD WINAPI GetProcessDword(DWORD processid,DWORD action)
{
PDB *process = processid? PROCESS_IdToPDB( processid )
: PROCESS_Current();
TDB *pTask;
action+=56;
TRACE(win32,"(%ld,%ld+0x38)\n",processid,action);
if (!process || action>56)
return 0;
switch (action) {
case 0: /* return app compat flags */
pTask = (TDB*)GlobalLock16(process->task);
if (!pTask)
return 0;
return pTask->compat_flags;
case 4: /* returns offset 0xb8 of process struct... dunno what it is */
return 0;
case 8: /* return hinstance16 */
pTask = (TDB*)GlobalLock16(process->task);
if (!pTask)
return 0;
return pTask->hInstance;
case 12:/* return expected windows version */
pTask = (TDB*)GlobalLock16(process->task);
if (!pTask)
return 0;
return pTask->version;
case 16:/* return uncrypted pointer to current thread */
return (DWORD)THREAD_Current();
case 20:/* return uncrypted pointer to process */
return (DWORD)process;
case 24:/* return stdoutput handle from startupinfo */
return (DWORD)(process->env_db->startup_info->hStdOutput);
case 28:/* return stdinput handle from startupinfo */
return (DWORD)(process->env_db->startup_info->hStdInput);
case 32:/* get showwindow flag from startupinfo */
return (DWORD)(process->env_db->startup_info->wShowWindow);
case 36:{/* return startup x and y sizes */
LPSTARTUPINFOA si = process->env_db->startup_info;
DWORD x,y;
x=si->dwXSize;if (x==0x80000000) x=0x8000;
y=si->dwYSize;if (y==0x80000000) y=0x8000;
return (y<<16)+x;
}
case 40:{/* return startup x and y */
LPSTARTUPINFOA si = process->env_db->startup_info;
DWORD x,y;
x=si->dwX;if (x==0x80000000) x=0x8000;
y=si->dwY;if (y==0x80000000) y=0x8000;
return (y<<16)+x;
}
case 44:/* return startup flags */
return process->env_db->startup_info->dwFlags;
case 48:/* return uncrypted pointer to parent process (if any) */
return (DWORD)process->parent;
case 52:/* return process flags */
return process->flags;
case 56:/* unexplored */
return process->process_dword;
default:
WARN(win32,"Unknown offset (%ld)\n",action);
return 0;
}
/* shouldn't come here */
}
/***********************************************************************
* SetProcessDword (KERNEL.484)
* 'Of course you cannot directly access Windows internal structures'
*/
VOID WINAPI SetProcessDword(DWORD processid,DWORD action,DWORD value)
{
PDB *process = processid? PROCESS_IdToPDB( processid )
: PROCESS_Current();
action+=56;
TRACE(win32,"(%ld,%ld+0x38)\n",processid,action);
if (!process || action>56) return;
switch (action) {
case 56: process->process_dword = value; break;
default:
FIXME(win32,"Unknown offset (%ld)\n",action);
break;
}
}
/***********************************************************************
* GetWin16DOSEnv (KERNEL32.34)
* Returns some internal value.... probably the default environment database?
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment