2003-06-27 06:08:04 +02:00
|
|
|
/*
|
|
|
|
* Win32 processes
|
|
|
|
*
|
|
|
|
* Copyright 1996, 1998 Alexandre Julliard
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "wine/port.h"
|
|
|
|
|
|
|
|
#include "wine/winbase16.h"
|
|
|
|
#include "wine/winuser16.h"
|
2003-08-28 21:57:35 +02:00
|
|
|
#include "thread.h"
|
2003-06-27 06:08:04 +02:00
|
|
|
#include "wine/server.h"
|
|
|
|
#include "wine/debug.h"
|
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(process);
|
|
|
|
|
|
|
|
/* Process flags */
|
|
|
|
#define PDB32_DEBUGGED 0x0001 /* Process is being debugged */
|
|
|
|
#define PDB32_WIN16_PROC 0x0008 /* Win16 process */
|
|
|
|
#define PDB32_DOS_PROC 0x0010 /* Dos process */
|
|
|
|
#define PDB32_CONSOLE_PROC 0x0020 /* Console process */
|
|
|
|
#define PDB32_FILE_APIS_OEM 0x0040 /* File APIs are OEM */
|
|
|
|
#define PDB32_WIN32S_PROC 0x8000 /* Win32s process */
|
|
|
|
|
|
|
|
|
|
|
|
static DWORD shutdown_flags = 0;
|
|
|
|
static DWORD shutdown_priority = 0x280;
|
|
|
|
static DWORD process_dword;
|
|
|
|
static BOOL oem_file_apis;
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetProcessFlags (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI GetProcessFlags( DWORD processid )
|
|
|
|
{
|
|
|
|
IMAGE_NT_HEADERS *nt;
|
|
|
|
DWORD flags = 0;
|
|
|
|
|
|
|
|
if (processid && processid != GetCurrentProcessId()) return 0;
|
|
|
|
|
|
|
|
if ((nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress )))
|
|
|
|
{
|
|
|
|
if (nt->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
|
|
|
|
flags |= PDB32_CONSOLE_PROC;
|
|
|
|
}
|
|
|
|
if (!AreFileApisANSI()) flags |= PDB32_FILE_APIS_OEM;
|
|
|
|
if (IsDebuggerPresent()) flags |= PDB32_DEBUGGED;
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetProcessDword (KERNEL.485)
|
|
|
|
* GetProcessDword (KERNEL32.18)
|
|
|
|
* 'Of course you cannot directly access Windows internal structures'
|
|
|
|
*/
|
|
|
|
DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset )
|
|
|
|
{
|
|
|
|
DWORD x, y;
|
|
|
|
STARTUPINFOW siw;
|
|
|
|
|
|
|
|
TRACE("(%ld, %d)\n", dwProcessID, offset );
|
|
|
|
|
|
|
|
if (dwProcessID && dwProcessID != GetCurrentProcessId())
|
|
|
|
{
|
|
|
|
ERR("%d: process %lx not accessible\n", offset, dwProcessID);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ( offset )
|
|
|
|
{
|
|
|
|
case GPD_APP_COMPAT_FLAGS:
|
|
|
|
return GetAppCompatFlags16(0);
|
|
|
|
case GPD_LOAD_DONE_EVENT:
|
|
|
|
return 0;
|
|
|
|
case GPD_HINSTANCE16:
|
|
|
|
return GetTaskDS16();
|
|
|
|
case GPD_WINDOWS_VERSION:
|
|
|
|
return GetExeVersion16();
|
|
|
|
case GPD_THDB:
|
|
|
|
return (DWORD)NtCurrentTeb() - 0x10 /* FIXME */;
|
|
|
|
case GPD_PDB:
|
|
|
|
return (DWORD)NtCurrentTeb()->Peb;
|
|
|
|
case GPD_STARTF_SHELLDATA: /* return stdoutput handle from startupinfo ??? */
|
|
|
|
GetStartupInfoW(&siw);
|
|
|
|
return (DWORD)siw.hStdOutput;
|
|
|
|
case GPD_STARTF_HOTKEY: /* return stdinput handle from startupinfo ??? */
|
|
|
|
GetStartupInfoW(&siw);
|
|
|
|
return (DWORD)siw.hStdInput;
|
|
|
|
case GPD_STARTF_SHOWWINDOW:
|
|
|
|
GetStartupInfoW(&siw);
|
|
|
|
return siw.wShowWindow;
|
|
|
|
case GPD_STARTF_SIZE:
|
|
|
|
GetStartupInfoW(&siw);
|
|
|
|
x = siw.dwXSize;
|
|
|
|
if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
|
|
|
|
y = siw.dwYSize;
|
|
|
|
if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
|
|
|
|
return MAKELONG( x, y );
|
|
|
|
case GPD_STARTF_POSITION:
|
|
|
|
GetStartupInfoW(&siw);
|
|
|
|
x = siw.dwX;
|
|
|
|
if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
|
|
|
|
y = siw.dwY;
|
|
|
|
if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
|
|
|
|
return MAKELONG( x, y );
|
|
|
|
case GPD_STARTF_FLAGS:
|
|
|
|
GetStartupInfoW(&siw);
|
|
|
|
return siw.dwFlags;
|
|
|
|
case GPD_PARENT:
|
|
|
|
return 0;
|
|
|
|
case GPD_FLAGS:
|
|
|
|
return GetProcessFlags(0);
|
|
|
|
case GPD_USERDATA:
|
|
|
|
return process_dword;
|
|
|
|
default:
|
|
|
|
ERR("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 )
|
|
|
|
{
|
|
|
|
TRACE("(%ld, %d)\n", dwProcessID, offset );
|
|
|
|
|
|
|
|
if (dwProcessID && dwProcessID != GetCurrentProcessId())
|
|
|
|
{
|
|
|
|
ERR("%d: process %lx not accessible\n", offset, dwProcessID);
|
|
|
|
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:
|
|
|
|
case GPD_FLAGS:
|
|
|
|
ERR("Not allowed to modify offset %d\n", offset );
|
|
|
|
break;
|
|
|
|
case GPD_USERDATA:
|
|
|
|
process_dword = value;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
ERR("Unknown offset %d\n", offset );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ExitProcess (KERNEL.466)
|
|
|
|
*/
|
|
|
|
void WINAPI ExitProcess16( WORD status )
|
|
|
|
{
|
|
|
|
DWORD count;
|
|
|
|
ReleaseThunkLock( &count );
|
|
|
|
ExitProcess( status );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
* OpenProcess (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
HANDLE WINAPI OpenProcess( DWORD access, BOOL inherit, DWORD id )
|
|
|
|
{
|
|
|
|
HANDLE ret = 0;
|
|
|
|
SERVER_START_REQ( open_process )
|
|
|
|
{
|
|
|
|
req->pid = id;
|
|
|
|
req->access = access;
|
|
|
|
req->inherit = inherit;
|
|
|
|
if (!wine_server_call_err( req )) ret = reply->handle;
|
|
|
|
}
|
|
|
|
SERVER_END_REQ;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************
|
|
|
|
* MapProcessHandle (KERNEL.483)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI MapProcessHandle( HANDLE handle )
|
|
|
|
{
|
|
|
|
DWORD ret = 0;
|
|
|
|
SERVER_START_REQ( get_process_info )
|
|
|
|
{
|
|
|
|
req->handle = handle;
|
|
|
|
if (!wine_server_call_err( req )) ret = reply->pid;
|
|
|
|
}
|
|
|
|
SERVER_END_REQ;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* SetPriorityClass (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI SetPriorityClass( HANDLE hprocess, DWORD priorityclass )
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
SERVER_START_REQ( set_process_info )
|
|
|
|
{
|
|
|
|
req->handle = hprocess;
|
|
|
|
req->priority = priorityclass;
|
|
|
|
req->mask = SET_PROCESS_INFO_PRIORITY;
|
|
|
|
ret = !wine_server_call_err( req );
|
|
|
|
}
|
|
|
|
SERVER_END_REQ;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetPriorityClass (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI GetPriorityClass(HANDLE hprocess)
|
|
|
|
{
|
|
|
|
DWORD ret = 0;
|
|
|
|
SERVER_START_REQ( get_process_info )
|
|
|
|
{
|
|
|
|
req->handle = hprocess;
|
|
|
|
if (!wine_server_call_err( req )) ret = reply->priority;
|
|
|
|
}
|
|
|
|
SERVER_END_REQ;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* SetProcessAffinityMask (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI SetProcessAffinityMask( HANDLE hProcess, DWORD affmask )
|
|
|
|
{
|
|
|
|
BOOL ret;
|
|
|
|
SERVER_START_REQ( set_process_info )
|
|
|
|
{
|
|
|
|
req->handle = hProcess;
|
|
|
|
req->affinity = affmask;
|
|
|
|
req->mask = SET_PROCESS_INFO_AFFINITY;
|
|
|
|
ret = !wine_server_call_err( req );
|
|
|
|
}
|
|
|
|
SERVER_END_REQ;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
* GetProcessAffinityMask (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI GetProcessAffinityMask( HANDLE hProcess,
|
|
|
|
LPDWORD lpProcessAffinityMask,
|
|
|
|
LPDWORD lpSystemAffinityMask )
|
|
|
|
{
|
|
|
|
BOOL ret = FALSE;
|
|
|
|
SERVER_START_REQ( get_process_info )
|
|
|
|
{
|
|
|
|
req->handle = hProcess;
|
|
|
|
if (!wine_server_call_err( req ))
|
|
|
|
{
|
|
|
|
if (lpProcessAffinityMask) *lpProcessAffinityMask = reply->process_affinity;
|
|
|
|
if (lpSystemAffinityMask) *lpSystemAffinityMask = reply->system_affinity;
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SERVER_END_REQ;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetProcessVersion (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
DWORD WINAPI GetProcessVersion( DWORD processid )
|
|
|
|
{
|
|
|
|
IMAGE_NT_HEADERS *nt;
|
|
|
|
|
|
|
|
if (processid && processid != GetCurrentProcessId())
|
|
|
|
{
|
|
|
|
FIXME("should use ReadProcessMemory\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if ((nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress )))
|
|
|
|
return ((nt->OptionalHeader.MajorSubsystemVersion << 16) |
|
|
|
|
nt->OptionalHeader.MinorSubsystemVersion);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* SetProcessWorkingSetSize [KERNEL32.@]
|
|
|
|
* Sets the min/max working set sizes for a specified process.
|
|
|
|
*
|
|
|
|
* PARAMS
|
|
|
|
* hProcess [I] Handle to the process of interest
|
|
|
|
* minset [I] Specifies minimum working set size
|
|
|
|
* maxset [I] Specifies maximum working set size
|
|
|
|
*
|
|
|
|
* RETURNS STD
|
|
|
|
*/
|
|
|
|
BOOL WINAPI SetProcessWorkingSetSize(HANDLE hProcess, SIZE_T minset,
|
|
|
|
SIZE_T maxset)
|
|
|
|
{
|
|
|
|
FIXME("(%p,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
|
|
|
|
if(( minset == (SIZE_T)-1) && (maxset == (SIZE_T)-1)) {
|
|
|
|
/* Trim the working set to zero */
|
|
|
|
/* Swap the process out of physical RAM */
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetProcessWorkingSetSize (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI GetProcessWorkingSetSize(HANDLE hProcess, PSIZE_T minset,
|
|
|
|
PSIZE_T maxset)
|
|
|
|
{
|
|
|
|
FIXME("(%p,%p,%p): stub\n",hProcess,minset,maxset);
|
|
|
|
/* 32 MB working set size */
|
|
|
|
if (minset) *minset = 32*1024*1024;
|
|
|
|
if (maxset) *maxset = 32*1024*1024;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* SetProcessShutdownParameters (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI SetProcessShutdownParameters(DWORD level, DWORD flags)
|
|
|
|
{
|
|
|
|
FIXME("(%08lx, %08lx): partial stub.\n", level, flags);
|
|
|
|
shutdown_flags = flags;
|
|
|
|
shutdown_priority = level;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetProcessShutdownParameters (KERNEL32.@)
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
BOOL WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel, LPDWORD lpdwFlags )
|
|
|
|
{
|
|
|
|
*lpdwLevel = shutdown_priority;
|
|
|
|
*lpdwFlags = shutdown_flags;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetProcessPriorityBoost (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI GetProcessPriorityBoost(HANDLE hprocess,PBOOL pDisablePriorityBoost)
|
|
|
|
{
|
|
|
|
FIXME("(%p,%p): semi-stub\n", hprocess, pDisablePriorityBoost);
|
|
|
|
|
|
|
|
/* Report that no boost is present.. */
|
|
|
|
*pDisablePriorityBoost = FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* SetProcessPriorityBoost (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost)
|
|
|
|
{
|
|
|
|
FIXME("(%p,%d): stub\n",hprocess,disableboost);
|
|
|
|
/* Say we can do it. I doubt the program will notice that we don't. */
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* ReadProcessMemory (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI ReadProcessMemory( HANDLE process, LPCVOID addr, LPVOID buffer, SIZE_T size,
|
|
|
|
SIZE_T *bytes_read )
|
|
|
|
{
|
2003-07-08 23:18:45 +02:00
|
|
|
NTSTATUS status = NtReadVirtualMemory( process, addr, buffer, size, bytes_read );
|
|
|
|
if (status) SetLastError( RtlNtStatusToDosError(status) );
|
|
|
|
return !status;
|
2003-06-27 06:08:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* WriteProcessMemory (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPCVOID buffer, SIZE_T size,
|
|
|
|
SIZE_T *bytes_written )
|
|
|
|
{
|
2003-07-08 23:18:45 +02:00
|
|
|
NTSTATUS status = NtWriteVirtualMemory( process, addr, buffer, size, bytes_written );
|
|
|
|
if (status) SetLastError( RtlNtStatusToDosError(status) );
|
|
|
|
return !status;
|
2003-06-27 06:08:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* RegisterServiceProcess (KERNEL.491)
|
|
|
|
* RegisterServiceProcess (KERNEL32.@)
|
|
|
|
*
|
|
|
|
* A service process calls this function to ensure that it continues to run
|
|
|
|
* even after a user logged off.
|
|
|
|
*/
|
|
|
|
DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
|
|
|
|
{
|
|
|
|
/* I don't think that Wine needs to do anything in that function */
|
|
|
|
return 1; /* success */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* SetFileApisToOEM (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
VOID WINAPI SetFileApisToOEM(void)
|
|
|
|
{
|
|
|
|
oem_file_apis = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
* SetFileApisToANSI (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
VOID WINAPI SetFileApisToANSI(void)
|
|
|
|
{
|
|
|
|
oem_file_apis = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* AreFileApisANSI [KERNEL32.@] Determines if file functions are using ANSI
|
|
|
|
*
|
|
|
|
* RETURNS
|
|
|
|
* TRUE: Set of file functions is using ANSI code page
|
|
|
|
* FALSE: Set of file functions is using OEM code page
|
|
|
|
*/
|
|
|
|
BOOL WINAPI AreFileApisANSI(void)
|
|
|
|
{
|
|
|
|
return !oem_file_apis;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***********************************************************************
|
|
|
|
* GetCurrentProcess (KERNEL32.@)
|
|
|
|
*/
|
|
|
|
#undef GetCurrentProcess
|
|
|
|
HANDLE WINAPI GetCurrentProcess(void)
|
|
|
|
{
|
|
|
|
return (HANDLE)0xffffffff;
|
|
|
|
}
|