| /* |
| * 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; |
| } |