/* * 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" #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 ) { NTSTATUS status = NtReadVirtualMemory( process, addr, buffer, size, bytes_read ); if (status) SetLastError( RtlNtStatusToDosError(status) ); return !status; } /*********************************************************************** * WriteProcessMemory (KERNEL32.@) */ BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPCVOID buffer, SIZE_T size, SIZE_T *bytes_written ) { NTSTATUS status = NtWriteVirtualMemory( process, addr, buffer, size, bytes_written ); if (status) SetLastError( RtlNtStatusToDosError(status) ); return !status; } /*********************************************************************** * 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; }