4 * Copyright 1996, 1998 Alexandre Julliard
11 #include "wine/winbase16.h"
27 #include "debugtools.h"
29 DECLARE_DEBUG_CHANNEL(process
)
30 DECLARE_DEBUG_CHANNEL(relay
)
31 DECLARE_DEBUG_CHANNEL(win32
)
34 /* The initial process PDB */
35 static PDB initial_pdb
;
37 static PDB
*PROCESS_First
= &initial_pdb
;
39 /***********************************************************************
42 void PROCESS_WalkProcess(void)
48 MESSAGE( " pid PDB #th modref module \n" );
51 if (pdb
== &initial_pdb
)
54 name
= (pdb
->exe_modref
) ? pdb
->exe_modref
->shortname
: "";
56 MESSAGE( " %8p %8p %5d %8p %s\n", pdb
->server_pid
, pdb
,
57 pdb
->threads
, pdb
->exe_modref
, name
);
63 /***********************************************************************
66 * FIXME: This works only while running all processes in the same
67 * address space (or, at least, the initial process is mapped
68 * into all address spaces as is KERNEL32 in Windows 95)
71 PDB
*PROCESS_Initial(void)
76 /***********************************************************************
79 * Check if a handle is to the current process
81 BOOL
PROCESS_IsCurrent( HANDLE handle
)
83 struct get_process_info_request
*req
= get_req_buffer();
85 return (!server_call( REQ_GET_PROCESS_INFO
) &&
86 (req
->pid
== PROCESS_Current()->server_pid
));
90 /***********************************************************************
93 * Convert a process id to a PDB, making sure it is valid.
95 PDB
*PROCESS_IdToPDB( DWORD id
)
99 if (!id
) return PROCESS_Current();
103 if ((DWORD
)pdb
->server_pid
== id
) return pdb
;
106 SetLastError( ERROR_INVALID_PARAMETER
);
111 /***********************************************************************
112 * PROCESS_CallUserSignalProc
114 * FIXME: Some of the signals aren't sent correctly!
116 * The exact meaning of the USER signals is undocumented, but this
117 * should cover the basic idea:
119 * USIG_DLL_UNLOAD_WIN16
120 * This is sent when a 16-bit module is unloaded.
122 * USIG_DLL_UNLOAD_WIN32
123 * This is sent when a 32-bit module is unloaded.
125 * USIG_DLL_UNLOAD_ORPHANS
126 * This is sent after the last Win3.1 module is unloaded,
127 * to allow removal of orphaned menus.
129 * USIG_FAULT_DIALOG_PUSH
130 * USIG_FAULT_DIALOG_POP
131 * These are called to allow USER to prepare for displaying a
132 * fault dialog, even though the fault might have happened while
133 * inside a USER critical section.
136 * This is called from the context of a new thread, as soon as it
137 * has started to run.
140 * This is called, still in its context, just before a thread is
141 * about to terminate.
143 * USIG_PROCESS_CREATE
144 * This is called, in the parent process context, after a new process
148 * This is called in the new process context, just after the main thread
149 * has started execution (after the main thread's USIG_THREAD_INIT has
152 * USIG_PROCESS_LOADED
153 * This is called after the executable file has been loaded into the
154 * new process context.
156 * USIG_PROCESS_RUNNING
157 * This is called immediately before the main entry point is called.
160 * This is called in the context of a process that is about to
161 * terminate (but before the last thread's USIG_THREAD_EXIT has
164 * USIG_PROCESS_DESTROY
165 * This is called after a process has terminated.
168 * The meaning of the dwFlags bits is as follows:
171 * Current process is 32-bit.
174 * Current process is a (Win32) GUI process.
176 * USIG_FLAGS_FEEDBACK
177 * Current process needs 'feedback' (determined from the STARTUPINFO
178 * flags STARTF_FORCEONFEEDBACK / STARTF_FORCEOFFFEEDBACK).
181 * The signal is being sent due to a fault.
183 static void PROCESS_CallUserSignalProcHelper( UINT uCode
, DWORD dwThreadOrProcessId
,
184 HMODULE hModule
, DWORD flags
, DWORD startup_flags
)
188 /* Determine dwFlags */
190 if ( !(flags
& PDB32_WIN16_PROC
) ) dwFlags
|= USIG_FLAGS_WIN32
;
192 if ( !(flags
& PDB32_CONSOLE_PROC
) ) dwFlags
|= USIG_FLAGS_GUI
;
194 if ( dwFlags
& USIG_FLAGS_GUI
)
196 /* Feedback defaults to ON */
197 if ( !(startup_flags
& STARTF_FORCEOFFFEEDBACK
) )
198 dwFlags
|= USIG_FLAGS_FEEDBACK
;
202 /* Feedback defaults to OFF */
203 if (startup_flags
& STARTF_FORCEONFEEDBACK
)
204 dwFlags
|= USIG_FLAGS_FEEDBACK
;
207 /* Convert module handle to 16-bit */
209 if ( HIWORD( hModule
) )
210 hModule
= MapHModuleLS( hModule
);
212 /* Call USER signal proc */
214 if ( Callout
.UserSignalProc
)
215 Callout
.UserSignalProc( uCode
, dwThreadOrProcessId
, dwFlags
, hModule
);
218 /* Call USER signal proc for the current thread/process */
219 void PROCESS_CallUserSignalProc( UINT uCode
, HMODULE hModule
)
221 DWORD dwThreadOrProcessId
;
223 /* Get thread or process ID */
224 if ( uCode
== USIG_THREAD_INIT
|| uCode
== USIG_THREAD_EXIT
)
225 dwThreadOrProcessId
= GetCurrentThreadId();
227 dwThreadOrProcessId
= GetCurrentProcessId();
229 PROCESS_CallUserSignalProcHelper( uCode
, dwThreadOrProcessId
, hModule
,
230 PROCESS_Current()->flags
,
231 PROCESS_Current()->env_db
->startup_info
->dwFlags
);
235 /***********************************************************************
236 * PROCESS_CreateEnvDB
238 * Create the env DB for a newly started process.
240 static BOOL
PROCESS_CreateEnvDB(void)
242 struct init_process_request
*req
= get_req_buffer();
243 STARTUPINFOA
*startup
;
246 PDB
*pdb
= PROCESS_Current();
248 /* Allocate the env DB */
250 if (!(env_db
= HeapAlloc( pdb
->heap
, HEAP_ZERO_MEMORY
, sizeof(ENVDB
) )))
252 pdb
->env_db
= env_db
;
253 InitializeCriticalSection( &env_db
->section
);
255 /* Allocate and fill the startup info */
256 if (!(startup
= HeapAlloc( pdb
->heap
, HEAP_ZERO_MEMORY
, sizeof(STARTUPINFOA
) )))
258 env_db
->startup_info
= startup
;
260 /* Retrieve startup info from the server */
262 if (server_call( REQ_INIT_PROCESS
)) return FALSE
;
263 startup
->dwFlags
= req
->start_flags
;
264 startup
->wShowWindow
= req
->cmd_show
;
265 env_db
->hStdin
= startup
->hStdInput
= req
->hstdin
;
266 env_db
->hStdout
= startup
->hStdOutput
= req
->hstdout
;
267 env_db
->hStderr
= startup
->hStdError
= req
->hstderr
;
268 lstrcpynA( cmd_line
, req
->cmdline
, sizeof(cmd_line
) );
270 /* Copy the parent environment */
272 if (!ENV_InheritEnvironment( pdb
, req
->env_ptr
)) return FALSE
;
274 /* Copy the command line */
276 if (!(pdb
->env_db
->cmd_line
= HEAP_strdupA( pdb
->heap
, 0, cmd_line
)))
283 /***********************************************************************
286 * Free a PDB and all associated storage.
288 void PROCESS_FreePDB( PDB
*pdb
)
290 PDB
**pptr
= &PROCESS_First
;
292 ENV_FreeEnvironment( pdb
);
293 while (*pptr
&& (*pptr
!= pdb
)) pptr
= &(*pptr
)->next
;
294 if (*pptr
) *pptr
= pdb
->next
;
295 if (pdb
->heap
&& (pdb
->heap
!= pdb
->system_heap
)) HeapDestroy( pdb
->heap
);
296 HeapFree( SystemHeap
, 0, pdb
);
300 /***********************************************************************
303 * Allocate and fill a PDB structure.
304 * Runs in the context of the parent process.
306 static PDB
*PROCESS_CreatePDB( PDB
*parent
, BOOL inherit
)
308 PDB
*pdb
= HeapAlloc( SystemHeap
, HEAP_ZERO_MEMORY
, sizeof(PDB
) );
310 if (!pdb
) return NULL
;
311 pdb
->exit_code
= 0x103; /* STILL_ACTIVE */
313 pdb
->running_threads
= 1;
314 pdb
->ring0_threads
= 1;
315 pdb
->system_heap
= SystemHeap
;
316 pdb
->parent
= parent
;
318 pdb
->priority
= 8; /* Normal */
319 pdb
->heap
= pdb
->system_heap
; /* will be changed later on */
320 pdb
->next
= PROCESS_First
;
321 pdb
->winver
= 0xffff; /* to be determined */
327 /***********************************************************************
330 BOOL
PROCESS_Init(void)
335 /* Start the server */
336 server_fd
= CLIENT_InitServer();
338 /* Fill the initial process structure */
339 initial_pdb
.exit_code
= 0x103; /* STILL_ACTIVE */
340 initial_pdb
.threads
= 1;
341 initial_pdb
.running_threads
= 1;
342 initial_pdb
.ring0_threads
= 1;
343 initial_pdb
.group
= &initial_pdb
;
344 initial_pdb
.priority
= 8; /* Normal */
345 initial_pdb
.flags
= PDB32_WIN16_PROC
;
346 initial_pdb
.winver
= 0xffff; /* to be determined */
348 /* Initialize virtual memory management */
349 if (!VIRTUAL_Init()) return FALSE
;
351 /* Create the initial thread structure and socket pair */
352 if (!(teb
= THREAD_CreateInitialThread( &initial_pdb
, server_fd
))) return FALSE
;
354 /* Remember TEB selector of initial process for emergency use */
355 SYSLEVEL_EmergencyTeb
= teb
->teb_sel
;
357 /* Create the system heap */
358 if (!(SystemHeap
= HeapCreate( HEAP_GROWABLE
, 0x10000, 0 ))) return FALSE
;
359 initial_pdb
.system_heap
= initial_pdb
.heap
= SystemHeap
;
361 /* Create the environment DB of the first process */
362 if (!PROCESS_CreateEnvDB()) return FALSE
;
364 /* Create the SEGPTR heap */
365 if (!(SegptrHeap
= HeapCreate( HEAP_WINE_SEGPTR
, 0, 0 ))) return FALSE
;
367 /* Initialize the first process critical section */
368 InitializeCriticalSection( &initial_pdb
.crit_section
);
374 /***********************************************************************
377 * Startup routine of a new process. Called in the context of the new process.
379 void PROCESS_Start(void)
382 LPTHREAD_START_ROUTINE entry
= NULL
;
383 PDB
*pdb
= PROCESS_Current();
384 NE_MODULE
*pModule
= NE_GetPtr( pdb
->module
);
385 OFSTRUCT
*ofs
= (OFSTRUCT
*)((char*)(pModule
) + (pModule
)->fileinfo
);
386 IMAGE_OPTIONAL_HEADER
*header
= !pModule
->module32
? NULL
:
387 &PE_HEADER(pModule
->module32
)->OptionalHeader
;
389 /* Get process type */
390 enum { PROC_DOS
, PROC_WIN16
, PROC_WIN32
} type
;
391 if ( pdb
->flags
& PDB32_DOS_PROC
)
393 else if ( pdb
->flags
& PDB32_WIN16_PROC
)
398 /* Initialize the critical section */
399 InitializeCriticalSection( &pdb
->crit_section
);
401 /* Create the heap */
402 if (!(pdb
->heap
= HeapCreate( HEAP_GROWABLE
,
403 header
? header
->SizeOfHeapReserve
: 0x10000,
404 header
? header
->SizeOfHeapCommit
: 0 )))
406 pdb
->heap_list
= pdb
->heap
;
408 /* Create the environment db */
409 if (!PROCESS_CreateEnvDB()) goto error
;
411 /* Create a task for this process */
412 if (pdb
->env_db
->startup_info
->dwFlags
& STARTF_USESHOWWINDOW
)
413 cmdShow
= pdb
->env_db
->startup_info
->wShowWindow
;
414 if (!TASK_Create( pModule
, pdb
->hInstance
, pdb
->hPrevInstance
, cmdShow
))
417 /* Note: The USIG_PROCESS_CREATE signal is supposed to be sent in the
418 * context of the parent process. Actually, the USER signal proc
419 * doesn't really care about that, but it *does* require that the
420 * startup parameters are correctly set up, so that GetProcessDword
421 * works. Furthermore, before calling the USER signal proc the
422 * 16-bit stack must be set up, which it is only after TASK_Create
423 * in the case of a 16-bit process. Thus, we send the signal here.
426 /* Load USER32.DLL before calling UserSignalProc (relay debugging!) */
427 LoadLibraryA( "USER32.DLL" );
429 PROCESS_CallUserSignalProc( USIG_PROCESS_CREATE
, 0 );
431 PROCESS_CallUserSignalProc( USIG_THREAD_INIT
, 0 ); /* for initial thread */
433 PROCESS_CallUserSignalProc( USIG_PROCESS_INIT
, 0 );
435 /* Signal the parent process to continue */
436 SetEvent( pdb
->load_done_evt
);
437 CloseHandle( pdb
->load_done_evt
);
438 pdb
->load_done_evt
= INVALID_HANDLE_VALUE
;
440 /* Perform Win32 specific process initialization */
441 if ( type
== PROC_WIN32
)
443 /* Send the debug event to the debugger */
444 entry
= (LPTHREAD_START_ROUTINE
)RVA_PTR(pModule
->module32
,
445 OptionalHeader
.AddressOfEntryPoint
);
446 if (pdb
->flags
& PDB32_DEBUGGED
)
447 DEBUG_SendCreateProcessEvent( -1 /*FIXME*/, pModule
->module32
, entry
);
449 /* Create 32-bit MODREF */
450 if (!PE_CreateModule( pModule
->module32
, ofs
, 0, FALSE
)) goto error
;
452 /* Increment EXE refcount */
453 assert( pdb
->exe_modref
);
454 pdb
->exe_modref
->refCount
++;
456 /* Initialize thread-local storage */
460 PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED
, 0 ); /* FIXME: correct location? */
462 if ( (pdb
->flags
& PDB32_CONSOLE_PROC
) || (pdb
->flags
& PDB32_DOS_PROC
) )
465 if ( type
== PROC_WIN32
)
467 EnterCriticalSection( &pdb
->crit_section
);
468 MODULE_DllProcessAttach( pdb
->exe_modref
, (LPVOID
)1 );
469 LeaveCriticalSection( &pdb
->crit_section
);
472 /* Now call the entry point */
473 PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING
, 0 );
478 TRACE_(relay
)( "Starting DOS process\n" );
480 ERR_(relay
)( "DOSVM_Enter returned; should not happen!\n" );
484 TRACE_(relay
)( "Starting Win16 process\n" );
486 ERR_(relay
)( "TASK_CallToStart returned; should not happen!\n" );
490 TRACE_(relay
)( "Starting Win32 process (entryproc=%p)\n", entry
);
491 ExitProcess( entry(NULL
) );
495 ExitProcess( GetLastError() );
499 /***********************************************************************
502 * Create a new process database and associated info.
504 PDB
*PROCESS_Create( NE_MODULE
*pModule
, LPCSTR cmd_line
, LPCSTR env
,
505 HINSTANCE16 hInstance
, HINSTANCE16 hPrevInstance
,
506 LPSECURITY_ATTRIBUTES psa
, LPSECURITY_ATTRIBUTES tsa
,
507 BOOL inherit
, DWORD flags
, STARTUPINFOA
*startup
,
508 PROCESS_INFORMATION
*info
)
510 HANDLE handles
[2], load_done_evt
= INVALID_HANDLE_VALUE
;
511 DWORD exitcode
, size
;
513 struct new_process_request
*req
= get_req_buffer();
515 PDB
*parent
= PROCESS_Current();
516 PDB
*pdb
= PROCESS_CreatePDB( parent
, inherit
);
518 if (!pdb
) return NULL
;
519 info
->hThread
= info
->hProcess
= INVALID_HANDLE_VALUE
;
521 /* Create the process on the server side */
523 req
->inherit
= (psa
&& (psa
->nLength
>= sizeof(*psa
)) && psa
->bInheritHandle
);
524 req
->inherit_all
= inherit
;
525 req
->create_flags
= flags
;
526 req
->start_flags
= startup
->dwFlags
;
527 if (startup
->dwFlags
& STARTF_USESTDHANDLES
)
529 req
->hstdin
= startup
->hStdInput
;
530 req
->hstdout
= startup
->hStdOutput
;
531 req
->hstderr
= startup
->hStdError
;
535 req
->hstdin
= GetStdHandle( STD_INPUT_HANDLE
);
536 req
->hstdout
= GetStdHandle( STD_OUTPUT_HANDLE
);
537 req
->hstderr
= GetStdHandle( STD_ERROR_HANDLE
);
539 req
->cmd_show
= startup
->wShowWindow
;
540 req
->env_ptr
= (void*)env
; /* FIXME: hack */
541 lstrcpynA( req
->cmdline
, cmd_line
, server_remaining(req
->cmdline
) );
542 if (server_call( REQ_NEW_PROCESS
)) goto error
;
543 pdb
->server_pid
= req
->pid
;
544 info
->hProcess
= req
->handle
;
545 info
->dwProcessId
= (DWORD
)pdb
->server_pid
;
547 if ((flags
& DEBUG_PROCESS
) ||
548 ((parent
->flags
& PDB32_DEBUGGED
) && !(flags
& DEBUG_ONLY_THIS_PROCESS
)))
549 pdb
->flags
|= PDB32_DEBUGGED
;
551 if (pModule
->module32
) /* Win32 process */
553 IMAGE_OPTIONAL_HEADER
*header
= &PE_HEADER(pModule
->module32
)->OptionalHeader
;
554 size
= header
->SizeOfStackReserve
;
555 if (header
->Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_CUI
)
556 pdb
->flags
|= PDB32_CONSOLE_PROC
;
558 else if (!pModule
->dos_image
) /* Win16 process */
561 pdb
->flags
|= PDB32_WIN16_PROC
;
563 else /* DOS process */
566 pdb
->flags
|= PDB32_DOS_PROC
;
569 /* Create the main thread */
571 if (!(teb
= THREAD_Create( pdb
, 0L, size
, hInstance
== 0, tsa
, &server_thandle
)))
573 info
->hThread
= server_thandle
;
574 info
->dwThreadId
= (DWORD
)teb
->tid
;
575 teb
->startup
= PROCESS_Start
;
577 /* Create the load-done event */
578 load_done_evt
= CreateEventA( NULL
, TRUE
, FALSE
, NULL
);
579 DuplicateHandle( GetCurrentProcess(), load_done_evt
,
580 info
->hProcess
, &pdb
->load_done_evt
, 0, TRUE
, DUPLICATE_SAME_ACCESS
);
582 /* Pass module/instance to new process (FIXME: hack) */
583 pdb
->module
= pModule
->self
;
584 pdb
->hInstance
= hInstance
;
585 pdb
->hPrevInstance
= hPrevInstance
;
586 SYSDEPS_SpawnThread( teb
);
588 /* Wait until process is initialized (or initialization failed) */
589 handles
[0] = info
->hProcess
;
590 handles
[1] = load_done_evt
;
592 switch ( WaitForMultipleObjects( 2, handles
, FALSE
, INFINITE
) )
595 ERR_(process
)( "WaitForMultipleObjects failed\n" );
599 /* Child initialization code returns error condition as exitcode */
600 if ( GetExitCodeProcess( info
->hProcess
, &exitcode
) )
601 SetLastError( exitcode
);
605 /* Get 16-bit task up and running */
606 if ( pdb
->flags
& PDB32_WIN16_PROC
)
608 /* Post event to start the task */
609 PostEvent16( pdb
->task
);
611 /* If we ourselves are a 16-bit task, we Yield() directly. */
612 if ( parent
->flags
& PDB32_WIN16_PROC
)
618 CloseHandle( load_done_evt
);
619 load_done_evt
= INVALID_HANDLE_VALUE
;
624 if (load_done_evt
!= INVALID_HANDLE_VALUE
) CloseHandle( load_done_evt
);
625 if (info
->hThread
!= INVALID_HANDLE_VALUE
) CloseHandle( info
->hThread
);
626 if (info
->hProcess
!= INVALID_HANDLE_VALUE
) CloseHandle( info
->hProcess
);
627 PROCESS_FreePDB( pdb
);
632 /***********************************************************************
633 * ExitProcess (KERNEL32.100)
635 void WINAPI
ExitProcess( DWORD status
)
637 EnterCriticalSection( &PROCESS_Current()->crit_section
);
638 MODULE_DllProcessDetach( TRUE
, (LPVOID
)1 );
639 LeaveCriticalSection( &PROCESS_Current()->crit_section
);
642 TerminateProcess( GetCurrentProcess(), status
);
645 /***********************************************************************
646 * ExitProcess16 (KERNEL.466)
648 void WINAPI
ExitProcess16( WORD status
)
650 SYSLEVEL_ReleaseWin16Lock();
651 ExitProcess( status
);
654 /******************************************************************************
655 * TerminateProcess (KERNEL32.684)
657 BOOL WINAPI
TerminateProcess( HANDLE handle
, DWORD exit_code
)
659 struct terminate_process_request
*req
= get_req_buffer();
660 req
->handle
= handle
;
661 req
->exit_code
= exit_code
;
662 return !server_call( REQ_TERMINATE_PROCESS
);
666 /***********************************************************************
667 * GetProcessDword (KERNEL32.18) (KERNEL.485)
668 * 'Of course you cannot directly access Windows internal structures'
670 DWORD WINAPI
GetProcessDword( DWORD dwProcessID
, INT offset
)
672 PDB
*process
= PROCESS_IdToPDB( dwProcessID
);
676 TRACE_(win32
)("(%ld, %d)\n", dwProcessID
, offset
);
677 if ( !process
) return 0;
681 case GPD_APP_COMPAT_FLAGS
:
682 pTask
= (TDB
*)GlobalLock16( process
->task
);
683 return pTask
? pTask
->compat_flags
: 0;
685 case GPD_LOAD_DONE_EVENT
:
686 return process
->load_done_evt
;
688 case GPD_HINSTANCE16
:
689 pTask
= (TDB
*)GlobalLock16( process
->task
);
690 return pTask
? pTask
->hInstance
: 0;
692 case GPD_WINDOWS_VERSION
:
693 pTask
= (TDB
*)GlobalLock16( process
->task
);
694 return pTask
? pTask
->version
: 0;
697 if ( process
!= PROCESS_Current() ) return 0;
698 return (DWORD
)NtCurrentTeb() - 0x10 /* FIXME */;
701 return (DWORD
)process
;
703 case GPD_STARTF_SHELLDATA
: /* return stdoutput handle from startupinfo ??? */
704 return process
->env_db
->startup_info
->hStdOutput
;
706 case GPD_STARTF_HOTKEY
: /* return stdinput handle from startupinfo ??? */
707 return process
->env_db
->startup_info
->hStdInput
;
709 case GPD_STARTF_SHOWWINDOW
:
710 return process
->env_db
->startup_info
->wShowWindow
;
712 case GPD_STARTF_SIZE
:
713 x
= process
->env_db
->startup_info
->dwXSize
;
714 if ( x
== CW_USEDEFAULT
) x
= CW_USEDEFAULT16
;
715 y
= process
->env_db
->startup_info
->dwYSize
;
716 if ( y
== CW_USEDEFAULT
) y
= CW_USEDEFAULT16
;
717 return MAKELONG( x
, y
);
719 case GPD_STARTF_POSITION
:
720 x
= process
->env_db
->startup_info
->dwX
;
721 if ( x
== CW_USEDEFAULT
) x
= CW_USEDEFAULT16
;
722 y
= process
->env_db
->startup_info
->dwY
;
723 if ( y
== CW_USEDEFAULT
) y
= CW_USEDEFAULT16
;
724 return MAKELONG( x
, y
);
726 case GPD_STARTF_FLAGS
:
727 return process
->env_db
->startup_info
->dwFlags
;
730 return (DWORD
)process
->parent
->server_pid
;
733 return process
->flags
;
736 return process
->process_dword
;
739 ERR_(win32
)("Unknown offset %d\n", offset
);
744 /***********************************************************************
745 * SetProcessDword (KERNEL.484)
746 * 'Of course you cannot directly access Windows internal structures'
748 void WINAPI
SetProcessDword( DWORD dwProcessID
, INT offset
, DWORD value
)
750 PDB
*process
= PROCESS_IdToPDB( dwProcessID
);
752 TRACE_(win32
)("(%ld, %d)\n", dwProcessID
, offset
);
753 if ( !process
) return;
757 case GPD_APP_COMPAT_FLAGS
:
758 case GPD_LOAD_DONE_EVENT
:
759 case GPD_HINSTANCE16
:
760 case GPD_WINDOWS_VERSION
:
763 case GPD_STARTF_SHELLDATA
:
764 case GPD_STARTF_HOTKEY
:
765 case GPD_STARTF_SHOWWINDOW
:
766 case GPD_STARTF_SIZE
:
767 case GPD_STARTF_POSITION
:
768 case GPD_STARTF_FLAGS
:
771 ERR_(win32
)("Not allowed to modify offset %d\n", offset
);
775 process
->process_dword
= value
;
779 ERR_(win32
)("Unknown offset %d\n", offset
);
785 /***********************************************************************
786 * GetCurrentProcess (KERNEL32.198)
788 HANDLE WINAPI
GetCurrentProcess(void)
790 return CURRENT_PROCESS_PSEUDOHANDLE
;
794 /*********************************************************************
795 * OpenProcess (KERNEL32.543)
797 HANDLE WINAPI
OpenProcess( DWORD access
, BOOL inherit
, DWORD id
)
800 struct open_process_request
*req
= get_req_buffer();
802 req
->pid
= (void *)id
;
803 req
->access
= access
;
804 req
->inherit
= inherit
;
805 if (!server_call( REQ_OPEN_PROCESS
)) ret
= req
->handle
;
809 /*********************************************************************
810 * MapProcessHandle (KERNEL.483)
812 DWORD WINAPI
MapProcessHandle( HANDLE handle
)
815 struct get_process_info_request
*req
= get_req_buffer();
816 req
->handle
= handle
;
817 if (!server_call( REQ_GET_PROCESS_INFO
)) ret
= (DWORD
)req
->pid
;
821 /***********************************************************************
822 * GetCurrentProcessId (KERNEL32.199)
824 DWORD WINAPI
GetCurrentProcessId(void)
826 return (DWORD
)PROCESS_Current()->server_pid
;
830 /***********************************************************************
831 * GetProcessHeap (KERNEL32.259)
833 HANDLE WINAPI
GetProcessHeap(void)
835 PDB
*pdb
= PROCESS_Current();
836 return pdb
->heap
? pdb
->heap
: SystemHeap
;
840 /***********************************************************************
841 * GetThreadLocale (KERNEL32.295)
843 LCID WINAPI
GetThreadLocale(void)
845 return PROCESS_Current()->locale
;
849 /***********************************************************************
850 * SetPriorityClass (KERNEL32.503)
852 BOOL WINAPI
SetPriorityClass( HANDLE hprocess
, DWORD priorityclass
)
854 struct set_process_info_request
*req
= get_req_buffer();
855 req
->handle
= hprocess
;
856 req
->priority
= priorityclass
;
857 req
->mask
= SET_PROCESS_INFO_PRIORITY
;
858 return !server_call( REQ_SET_PROCESS_INFO
);
862 /***********************************************************************
863 * GetPriorityClass (KERNEL32.250)
865 DWORD WINAPI
GetPriorityClass(HANDLE hprocess
)
868 struct get_process_info_request
*req
= get_req_buffer();
869 req
->handle
= hprocess
;
870 if (!server_call( REQ_GET_PROCESS_INFO
)) ret
= req
->priority
;
875 /***********************************************************************
876 * SetProcessAffinityMask (KERNEL32.662)
878 BOOL WINAPI
SetProcessAffinityMask( HANDLE hProcess
, DWORD affmask
)
880 struct set_process_info_request
*req
= get_req_buffer();
881 req
->handle
= hProcess
;
882 req
->affinity
= affmask
;
883 req
->mask
= SET_PROCESS_INFO_AFFINITY
;
884 return !server_call( REQ_SET_PROCESS_INFO
);
887 /**********************************************************************
888 * GetProcessAffinityMask (KERNEL32.373)
890 BOOL WINAPI
GetProcessAffinityMask( HANDLE hProcess
,
891 LPDWORD lpProcessAffinityMask
,
892 LPDWORD lpSystemAffinityMask
)
895 struct get_process_info_request
*req
= get_req_buffer();
896 req
->handle
= hProcess
;
897 if (!server_call( REQ_GET_PROCESS_INFO
))
899 if (lpProcessAffinityMask
) *lpProcessAffinityMask
= req
->process_affinity
;
900 if (lpSystemAffinityMask
) *lpSystemAffinityMask
= req
->system_affinity
;
907 /***********************************************************************
908 * GetStdHandle (KERNEL32.276)
910 HANDLE WINAPI
GetStdHandle( DWORD std_handle
)
912 PDB
*pdb
= PROCESS_Current();
916 case STD_INPUT_HANDLE
: return pdb
->env_db
->hStdin
;
917 case STD_OUTPUT_HANDLE
: return pdb
->env_db
->hStdout
;
918 case STD_ERROR_HANDLE
: return pdb
->env_db
->hStderr
;
920 SetLastError( ERROR_INVALID_PARAMETER
);
921 return INVALID_HANDLE_VALUE
;
925 /***********************************************************************
926 * SetStdHandle (KERNEL32.506)
928 BOOL WINAPI
SetStdHandle( DWORD std_handle
, HANDLE handle
)
930 PDB
*pdb
= PROCESS_Current();
931 /* FIXME: should we close the previous handle? */
934 case STD_INPUT_HANDLE
:
935 pdb
->env_db
->hStdin
= handle
;
937 case STD_OUTPUT_HANDLE
:
938 pdb
->env_db
->hStdout
= handle
;
940 case STD_ERROR_HANDLE
:
941 pdb
->env_db
->hStderr
= handle
;
944 SetLastError( ERROR_INVALID_PARAMETER
);
948 /***********************************************************************
949 * GetProcessVersion (KERNEL32)
951 DWORD WINAPI
GetProcessVersion( DWORD processid
)
954 PDB
*pdb
= PROCESS_IdToPDB( processid
);
957 if (!(pTask
= (TDB
*)GlobalLock16( pdb
->task
))) return 0;
958 return (pTask
->version
&0xff) | (((pTask
->version
>>8) & 0xff)<<16);
961 /***********************************************************************
962 * GetProcessFlags (KERNEL32)
964 DWORD WINAPI
GetProcessFlags( DWORD processid
)
966 PDB
*pdb
= PROCESS_IdToPDB( processid
);
971 /***********************************************************************
972 * SetProcessWorkingSetSize [KERNEL32.662]
973 * Sets the min/max working set sizes for a specified process.
976 * hProcess [I] Handle to the process of interest
977 * minset [I] Specifies minimum working set size
978 * maxset [I] Specifies maximum working set size
982 BOOL WINAPI
SetProcessWorkingSetSize(HANDLE hProcess
,DWORD minset
,
985 FIXME_(process
)("(0x%08x,%ld,%ld): stub - harmless\n",hProcess
,minset
,maxset
);
986 if(( minset
== -1) && (maxset
== -1)) {
987 /* Trim the working set to zero */
988 /* Swap the process out of physical RAM */
993 /***********************************************************************
994 * GetProcessWorkingSetSize (KERNEL32)
996 BOOL WINAPI
GetProcessWorkingSetSize(HANDLE hProcess
,LPDWORD minset
,
999 FIXME_(process
)("(0x%08x,%p,%p): stub\n",hProcess
,minset
,maxset
);
1000 /* 32 MB working set size */
1001 if (minset
) *minset
= 32*1024*1024;
1002 if (maxset
) *maxset
= 32*1024*1024;
1006 /***********************************************************************
1007 * SetProcessShutdownParameters (KERNEL32)
1009 * CHANGED - James Sutherland (JamesSutherland@gmx.de)
1010 * Now tracks changes made (but does not act on these changes)
1011 * NOTE: the definition for SHUTDOWN_NORETRY was done on guesswork.
1012 * It really shouldn't be here, but I'll move it when it's been checked!
1014 #define SHUTDOWN_NORETRY 1
1015 static unsigned int shutdown_noretry
= 0;
1016 static unsigned int shutdown_priority
= 0x280L
;
1017 BOOL WINAPI
SetProcessShutdownParameters(DWORD level
,DWORD flags
)
1019 if (flags
& SHUTDOWN_NORETRY
)
1020 shutdown_noretry
= 1;
1022 shutdown_noretry
= 0;
1023 if (level
> 0x100L
&& level
< 0x3FFL
)
1024 shutdown_priority
= level
;
1027 ERR_(process
)("invalid priority level 0x%08lx\n", level
);
1034 /***********************************************************************
1035 * GetProcessShutdownParameters (KERNEL32)
1038 BOOL WINAPI
GetProcessShutdownParameters( LPDWORD lpdwLevel
,
1041 (*lpdwLevel
) = shutdown_priority
;
1042 (*lpdwFlags
) = (shutdown_noretry
* SHUTDOWN_NORETRY
);
1045 /***********************************************************************
1046 * SetProcessPriorityBoost (KERNEL32)
1048 BOOL WINAPI
SetProcessPriorityBoost(HANDLE hprocess
,BOOL disableboost
)
1050 FIXME_(process
)("(%d,%d): stub\n",hprocess
,disableboost
);
1051 /* Say we can do it. I doubt the program will notice that we don't. */
1055 /***********************************************************************
1056 * ReadProcessMemory (KERNEL32)
1057 * FIXME: check this, if we ever run win32 binaries in different addressspaces
1058 * ... and add a sizecheck
1060 BOOL WINAPI
ReadProcessMemory( HANDLE hProcess
, LPCVOID lpBaseAddress
,
1061 LPVOID lpBuffer
, DWORD nSize
,
1062 LPDWORD lpNumberOfBytesRead
)
1064 memcpy(lpBuffer
,lpBaseAddress
,nSize
);
1065 if (lpNumberOfBytesRead
) *lpNumberOfBytesRead
= nSize
;
1069 /***********************************************************************
1070 * WriteProcessMemory (KERNEL32)
1071 * FIXME: check this, if we ever run win32 binaries in different addressspaces
1072 * ... and add a sizecheck
1074 BOOL WINAPI
WriteProcessMemory(HANDLE hProcess
, LPVOID lpBaseAddress
,
1075 LPVOID lpBuffer
, DWORD nSize
,
1076 LPDWORD lpNumberOfBytesWritten
)
1078 memcpy(lpBaseAddress
,lpBuffer
,nSize
);
1079 if (lpNumberOfBytesWritten
) *lpNumberOfBytesWritten
= nSize
;
1083 /***********************************************************************
1084 * RegisterServiceProcess (KERNEL, KERNEL32)
1086 * A service process calls this function to ensure that it continues to run
1087 * even after a user logged off.
1089 DWORD WINAPI
RegisterServiceProcess(DWORD dwProcessId
, DWORD dwType
)
1091 /* I don't think that Wine needs to do anything in that function */
1092 return 1; /* success */
1095 /***********************************************************************
1096 * GetExitCodeProcess [KERNEL32.325]
1098 * Gets termination status of specified process
1104 BOOL WINAPI
GetExitCodeProcess(
1105 HANDLE hProcess
, /* [I] handle to the process */
1106 LPDWORD lpExitCode
) /* [O] address to receive termination status */
1109 struct get_process_info_request
*req
= get_req_buffer();
1110 req
->handle
= hProcess
;
1111 if (!server_call( REQ_GET_PROCESS_INFO
))
1113 if (lpExitCode
) *lpExitCode
= req
->exit_code
;
1120 /***********************************************************************
1121 * GetProcessHeaps [KERNEL32.376]
1123 DWORD WINAPI
GetProcessHeaps(DWORD nrofheaps
,HANDLE
*heaps
) {
1124 FIXME_(win32
)("(%ld,%p), incomplete implementation.\n",nrofheaps
,heaps
);
1127 heaps
[0] = GetProcessHeap();
1128 /* ... probably SystemHeap too ? */
1131 /* number of available heaps */
1136 /***********************************************************************
1137 * SetErrorMode (KERNEL32.486)
1139 UINT WINAPI
SetErrorMode( UINT mode
)
1141 UINT old
= PROCESS_Current()->error_mode
;
1142 PROCESS_Current()->error_mode
= mode
;