Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Win32 processes |
| 3 | * |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 4 | * Copyright 1996, 1998 Alexandre Julliard |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 5 | * |
| 6 | * This library is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU Lesser General Public |
| 8 | * License as published by the Free Software Foundation; either |
| 9 | * version 2.1 of the License, or (at your option) any later version. |
| 10 | * |
| 11 | * This library is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 | * Lesser General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU Lesser General Public |
| 17 | * License along with this library; if not, write to the Free Software |
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 19 | */ |
| 20 | |
Alexandre Julliard | 5769d1d | 2002-04-26 19:05:15 +0000 | [diff] [blame] | 21 | #include "config.h" |
| 22 | #include "wine/port.h" |
| 23 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 24 | #include <assert.h> |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 25 | #include <ctype.h> |
| 26 | #include <errno.h> |
Alexandre Julliard | 2fe5777 | 2000-01-25 01:40:27 +0000 | [diff] [blame] | 27 | #include <fcntl.h> |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 28 | #include <stdlib.h> |
Alexandre Julliard | b445952 | 2000-04-15 21:00:55 +0000 | [diff] [blame] | 29 | #include <stdio.h> |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 30 | #include <string.h> |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 31 | #include <unistd.h> |
Ulrich Weigand | ed49003 | 1999-06-06 14:47:50 +0000 | [diff] [blame] | 32 | #include "wine/winbase16.h" |
Alexandre Julliard | 19ffe59 | 2001-12-17 22:10:24 +0000 | [diff] [blame] | 33 | #include "wine/winuser16.h" |
Ulrich Weigand | 237e8e9 | 1999-12-04 04:04:58 +0000 | [diff] [blame] | 34 | #include "wine/exception.h" |
Alexandre Julliard | 591832e | 2000-11-10 01:38:28 +0000 | [diff] [blame] | 35 | #include "wine/library.h" |
Alexandre Julliard | aef9a36 | 2000-10-03 04:19:16 +0000 | [diff] [blame] | 36 | #include "drive.h" |
Alexandre Julliard | 641ee76 | 1997-08-04 16:34:36 +0000 | [diff] [blame] | 37 | #include "module.h" |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 38 | #include "file.h" |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 39 | #include "heap.h" |
Alexandre Julliard | 23946ad | 1997-06-16 17:43:53 +0000 | [diff] [blame] | 40 | #include "thread.h" |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 41 | #include "winerror.h" |
Eric Pouech | 0b83d4c | 2001-11-23 23:04:58 +0000 | [diff] [blame] | 42 | #include "wincon.h" |
Alexandre Julliard | 37e9503 | 2001-07-19 00:39:09 +0000 | [diff] [blame] | 43 | #include "wine/server.h" |
Ulrich Weigand | 8a64b83 | 1999-10-23 14:15:33 +0000 | [diff] [blame] | 44 | #include "options.h" |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 45 | #include "wine/debug.h" |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 46 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 47 | WINE_DEFAULT_DEBUG_CHANNEL(process); |
| 48 | WINE_DECLARE_DEBUG_CHANNEL(relay); |
Alexandre Julliard | a061b84 | 2002-06-04 17:48:41 +0000 | [diff] [blame^] | 49 | WINE_DECLARE_DEBUG_CHANNEL(snoop); |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 50 | WINE_DECLARE_DEBUG_CHANNEL(win32); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 51 | |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 52 | struct _ENVDB; |
| 53 | |
| 54 | /* Win32 process database */ |
| 55 | typedef struct _PDB |
| 56 | { |
| 57 | LONG header[2]; /* 00 Kernel object header */ |
| 58 | HMODULE module; /* 08 Main exe module (NT) */ |
| 59 | void *event; /* 0c Pointer to an event object (unused) */ |
| 60 | DWORD exit_code; /* 10 Process exit code */ |
| 61 | DWORD unknown2; /* 14 Unknown */ |
| 62 | HANDLE heap; /* 18 Default process heap */ |
| 63 | HANDLE mem_context; /* 1c Process memory context */ |
| 64 | DWORD flags; /* 20 Flags */ |
| 65 | void *pdb16; /* 24 DOS PSP */ |
| 66 | WORD PSP_sel; /* 28 Selector to DOS PSP */ |
| 67 | WORD imte; /* 2a IMTE for the process module */ |
| 68 | WORD threads; /* 2c Number of threads */ |
| 69 | WORD running_threads; /* 2e Number of running threads */ |
| 70 | WORD free_lib_count; /* 30 Recursion depth of FreeLibrary calls */ |
| 71 | WORD ring0_threads; /* 32 Number of ring 0 threads */ |
| 72 | HANDLE system_heap; /* 34 System heap to allocate handles */ |
| 73 | HTASK task; /* 38 Win16 task */ |
| 74 | void *mem_map_files; /* 3c Pointer to mem-mapped files */ |
| 75 | struct _ENVDB *env_db; /* 40 Environment database */ |
| 76 | void *handle_table; /* 44 Handle table */ |
| 77 | struct _PDB *parent; /* 48 Parent process */ |
| 78 | void *modref_list; /* 4c MODREF list */ |
| 79 | void *thread_list; /* 50 List of threads */ |
| 80 | void *debuggee_CB; /* 54 Debuggee context block */ |
| 81 | void *local_heap_free; /* 58 Head of local heap free list */ |
| 82 | DWORD unknown4; /* 5c Unknown */ |
| 83 | CRITICAL_SECTION crit_section; /* 60 Critical section */ |
| 84 | DWORD unknown5[3]; /* 78 Unknown */ |
| 85 | void *console; /* 84 Console */ |
| 86 | DWORD tls_bits[2]; /* 88 TLS in-use bits */ |
| 87 | DWORD process_dword; /* 90 Unknown */ |
| 88 | struct _PDB *group; /* 94 Process group */ |
| 89 | void *exe_modref; /* 98 MODREF for the process EXE */ |
| 90 | void *top_filter; /* 9c Top exception filter */ |
| 91 | DWORD priority; /* a0 Priority level */ |
| 92 | HANDLE heap_list; /* a4 Head of process heap list */ |
| 93 | void *heap_handles; /* a8 Head of heap handles list */ |
| 94 | DWORD unknown6; /* ac Unknown */ |
| 95 | void *console_provider; /* b0 Console provider (??) */ |
| 96 | WORD env_selector; /* b4 Selector to process environment */ |
| 97 | WORD error_mode; /* b6 Error mode */ |
| 98 | HANDLE load_done_evt; /* b8 Event for process loading done */ |
| 99 | void *UTState; /* bc Head of Univeral Thunk list */ |
| 100 | DWORD unknown8; /* c0 Unknown (NT) */ |
| 101 | LCID locale; /* c4 Locale to be queried by GetThreadLocale (NT) */ |
| 102 | } PDB; |
| 103 | |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 104 | PDB current_process; |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 105 | |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 106 | /* Process flags */ |
| 107 | #define PDB32_DEBUGGED 0x0001 /* Process is being debugged */ |
| 108 | #define PDB32_WIN16_PROC 0x0008 /* Win16 process */ |
| 109 | #define PDB32_DOS_PROC 0x0010 /* Dos process */ |
| 110 | #define PDB32_CONSOLE_PROC 0x0020 /* Console process */ |
| 111 | #define PDB32_FILE_APIS_OEM 0x0040 /* File APIs are OEM */ |
| 112 | #define PDB32_WIN32S_PROC 0x8000 /* Win32s process */ |
| 113 | |
Alexandre Julliard | 9264300 | 2000-08-31 01:59:51 +0000 | [diff] [blame] | 114 | static char main_exe_name[MAX_PATH]; |
Eric Pouech | 8c03474 | 2001-08-06 17:48:17 +0000 | [diff] [blame] | 115 | static char *main_exe_name_ptr = main_exe_name; |
Alexandre Julliard | 8081e5a | 2001-01-05 04:08:07 +0000 | [diff] [blame] | 116 | static HANDLE main_exe_file; |
Dmitry Timoshkov | 1c2fa97 | 2002-04-09 01:38:41 +0000 | [diff] [blame] | 117 | static int main_create_flags; |
Alexandre Julliard | 214399f | 1999-02-21 18:35:27 +0000 | [diff] [blame] | 118 | |
Alexandre Julliard | 55e845d | 2002-05-23 19:40:18 +0000 | [diff] [blame] | 119 | static unsigned int server_startticks; |
Ulrich Weigand | 4d55035 | 1999-07-30 18:05:07 +0000 | [diff] [blame] | 120 | |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 121 | /* memory/environ.c */ |
Alexandre Julliard | 9d80215 | 2002-05-24 21:20:27 +0000 | [diff] [blame] | 122 | extern struct _ENVDB *ENV_InitStartupInfo( size_t info_size, char *main_exe_name, |
| 123 | size_t main_exe_size ); |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 124 | extern BOOL ENV_BuildCommandLine( char **argv ); |
| 125 | extern STARTUPINFOA current_startupinfo; |
| 126 | |
Alexandre Julliard | 7f187e5 | 2001-02-23 01:37:05 +0000 | [diff] [blame] | 127 | /* scheduler/pthread.c */ |
| 128 | extern void PTHREAD_init_done(void); |
| 129 | |
Alexandre Julliard | a061b84 | 2002-06-04 17:48:41 +0000 | [diff] [blame^] | 130 | extern void RELAY_InitDebugLists(void); |
Alexandre Julliard | 751625e | 2000-12-12 00:50:19 +0000 | [diff] [blame] | 131 | extern BOOL MAIN_MainInit(void); |
| 132 | |
Alexandre Julliard | 6478164 | 2002-02-02 18:13:50 +0000 | [diff] [blame] | 133 | typedef WORD (WINAPI *pUserSignalProc)( UINT, DWORD, DWORD, HMODULE16 ); |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 134 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 135 | /*********************************************************************** |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 136 | * PROCESS_CallUserSignalProc |
| 137 | * |
| 138 | * FIXME: Some of the signals aren't sent correctly! |
| 139 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 140 | * The exact meaning of the USER signals is undocumented, but this |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 141 | * should cover the basic idea: |
| 142 | * |
| 143 | * USIG_DLL_UNLOAD_WIN16 |
| 144 | * This is sent when a 16-bit module is unloaded. |
| 145 | * |
| 146 | * USIG_DLL_UNLOAD_WIN32 |
| 147 | * This is sent when a 32-bit module is unloaded. |
| 148 | * |
| 149 | * USIG_DLL_UNLOAD_ORPHANS |
| 150 | * This is sent after the last Win3.1 module is unloaded, |
| 151 | * to allow removal of orphaned menus. |
| 152 | * |
| 153 | * USIG_FAULT_DIALOG_PUSH |
| 154 | * USIG_FAULT_DIALOG_POP |
| 155 | * These are called to allow USER to prepare for displaying a |
| 156 | * fault dialog, even though the fault might have happened while |
| 157 | * inside a USER critical section. |
| 158 | * |
| 159 | * USIG_THREAD_INIT |
| 160 | * This is called from the context of a new thread, as soon as it |
| 161 | * has started to run. |
| 162 | * |
| 163 | * USIG_THREAD_EXIT |
| 164 | * This is called, still in its context, just before a thread is |
| 165 | * about to terminate. |
| 166 | * |
| 167 | * USIG_PROCESS_CREATE |
| 168 | * This is called, in the parent process context, after a new process |
| 169 | * has been created. |
| 170 | * |
| 171 | * USIG_PROCESS_INIT |
| 172 | * This is called in the new process context, just after the main thread |
| 173 | * has started execution (after the main thread's USIG_THREAD_INIT has |
| 174 | * been sent). |
| 175 | * |
| 176 | * USIG_PROCESS_LOADED |
| 177 | * This is called after the executable file has been loaded into the |
| 178 | * new process context. |
| 179 | * |
| 180 | * USIG_PROCESS_RUNNING |
| 181 | * This is called immediately before the main entry point is called. |
| 182 | * |
| 183 | * USIG_PROCESS_EXIT |
| 184 | * This is called in the context of a process that is about to |
| 185 | * terminate (but before the last thread's USIG_THREAD_EXIT has |
| 186 | * been sent). |
| 187 | * |
| 188 | * USIG_PROCESS_DESTROY |
| 189 | * This is called after a process has terminated. |
| 190 | * |
| 191 | * |
| 192 | * The meaning of the dwFlags bits is as follows: |
| 193 | * |
| 194 | * USIG_FLAGS_WIN32 |
| 195 | * Current process is 32-bit. |
| 196 | * |
| 197 | * USIG_FLAGS_GUI |
| 198 | * Current process is a (Win32) GUI process. |
| 199 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 200 | * USIG_FLAGS_FEEDBACK |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 201 | * Current process needs 'feedback' (determined from the STARTUPINFO |
| 202 | * flags STARTF_FORCEONFEEDBACK / STARTF_FORCEOFFFEEDBACK). |
| 203 | * |
| 204 | * USIG_FLAGS_FAULT |
| 205 | * The signal is being sent due to a fault. |
| 206 | */ |
Alexandre Julliard | 8ff37b8 | 2001-06-06 20:24:12 +0000 | [diff] [blame] | 207 | void PROCESS_CallUserSignalProc( UINT uCode, HMODULE16 hModule ) |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 208 | { |
Ulrich Weigand | 2e65876 | 1999-04-11 12:06:04 +0000 | [diff] [blame] | 209 | DWORD dwFlags = 0; |
Alexandre Julliard | 19ffe59 | 2001-12-17 22:10:24 +0000 | [diff] [blame] | 210 | HMODULE user; |
| 211 | pUserSignalProc proc; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 212 | |
Alexandre Julliard | 19ffe59 | 2001-12-17 22:10:24 +0000 | [diff] [blame] | 213 | if (!(user = GetModuleHandleA( "user32.dll" ))) return; |
| 214 | if (!(proc = (pUserSignalProc)GetProcAddress( user, "UserSignalProc" ))) return; |
Alexandre Julliard | 8ff37b8 | 2001-06-06 20:24:12 +0000 | [diff] [blame] | 215 | |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 216 | /* Determine dwFlags */ |
| 217 | |
Alexandre Julliard | 19ffe59 | 2001-12-17 22:10:24 +0000 | [diff] [blame] | 218 | if ( !(current_process.flags & PDB32_WIN16_PROC) ) dwFlags |= USIG_FLAGS_WIN32; |
| 219 | if ( !(current_process.flags & PDB32_CONSOLE_PROC) ) dwFlags |= USIG_FLAGS_GUI; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 220 | |
| 221 | if ( dwFlags & USIG_FLAGS_GUI ) |
| 222 | { |
| 223 | /* Feedback defaults to ON */ |
Alexandre Julliard | 19ffe59 | 2001-12-17 22:10:24 +0000 | [diff] [blame] | 224 | if ( !(current_startupinfo.dwFlags & STARTF_FORCEOFFFEEDBACK) ) |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 225 | dwFlags |= USIG_FLAGS_FEEDBACK; |
| 226 | } |
| 227 | else |
| 228 | { |
| 229 | /* Feedback defaults to OFF */ |
Alexandre Julliard | 19ffe59 | 2001-12-17 22:10:24 +0000 | [diff] [blame] | 230 | if (current_startupinfo.dwFlags & STARTF_FORCEONFEEDBACK) |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 231 | dwFlags |= USIG_FLAGS_FEEDBACK; |
| 232 | } |
| 233 | |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 234 | /* Call USER signal proc */ |
| 235 | |
Alexandre Julliard | 8ff37b8 | 2001-06-06 20:24:12 +0000 | [diff] [blame] | 236 | if ( uCode == USIG_THREAD_INIT || uCode == USIG_THREAD_EXIT ) |
Alexandre Julliard | 19ffe59 | 2001-12-17 22:10:24 +0000 | [diff] [blame] | 237 | proc( uCode, GetCurrentThreadId(), dwFlags, hModule ); |
Alexandre Julliard | 8ff37b8 | 2001-06-06 20:24:12 +0000 | [diff] [blame] | 238 | else |
Alexandre Julliard | 19ffe59 | 2001-12-17 22:10:24 +0000 | [diff] [blame] | 239 | proc( uCode, GetCurrentProcessId(), dwFlags, hModule ); |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 240 | } |
| 241 | |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 242 | |
| 243 | /*********************************************************************** |
| 244 | * get_basename |
| 245 | */ |
| 246 | inline static const char *get_basename( const char *name ) |
| 247 | { |
| 248 | char *p; |
| 249 | |
| 250 | if ((p = strrchr( name, '/' ))) name = p + 1; |
| 251 | if ((p = strrchr( name, '\\' ))) name = p + 1; |
| 252 | return name; |
| 253 | } |
| 254 | |
| 255 | |
| 256 | /*********************************************************************** |
| 257 | * open_exe_file |
| 258 | * |
| 259 | * Open an exe file, taking load order into account. |
| 260 | * Returns the file handle or 0 for a builtin exe. |
| 261 | */ |
| 262 | static HANDLE open_exe_file( const char *name ) |
| 263 | { |
| 264 | enum loadorder_type loadorder[LOADORDER_NTYPES]; |
| 265 | HANDLE handle; |
| 266 | int i; |
| 267 | |
| 268 | SetLastError( ERROR_FILE_NOT_FOUND ); |
| 269 | MODULE_GetLoadOrder( loadorder, name, TRUE ); |
| 270 | |
| 271 | for(i = 0; i < LOADORDER_NTYPES; i++) |
| 272 | { |
| 273 | if (loadorder[i] == LOADORDER_INVALID) break; |
| 274 | switch(loadorder[i]) |
| 275 | { |
| 276 | case LOADORDER_DLL: |
| 277 | TRACE( "Trying native exe %s\n", debugstr_a(name) ); |
| 278 | if ((handle = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ, |
| 279 | NULL, OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE) |
| 280 | return handle; |
| 281 | if (GetLastError() != ERROR_FILE_NOT_FOUND) return INVALID_HANDLE_VALUE; |
| 282 | break; |
| 283 | case LOADORDER_BI: |
| 284 | TRACE( "Trying built-in exe %s\n", debugstr_a(name) ); |
| 285 | if (wine_dll_load_main_exe( get_basename(name), NULL, 0, 1 )) return 0; |
| 286 | break; |
| 287 | default: |
| 288 | break; |
| 289 | } |
| 290 | } |
| 291 | return INVALID_HANDLE_VALUE; |
| 292 | } |
| 293 | |
| 294 | |
| 295 | /*********************************************************************** |
| 296 | * find_exe_file |
| 297 | * |
| 298 | * Open an exe file, and return the full name and file handle. |
| 299 | * Returns FALSE if file could not be found. |
| 300 | * If file exists but cannot be opened, returns TRUE and set handle to INVALID_HANDLE_VALUE. |
| 301 | * If file is a builtin exe, returns TRUE and sets handle to 0. |
| 302 | */ |
| 303 | static BOOL find_exe_file( const char *name, char *buffer, int buflen, HANDLE *handle ) |
| 304 | { |
| 305 | enum loadorder_type loadorder[LOADORDER_NTYPES]; |
| 306 | int i; |
| 307 | |
| 308 | TRACE("looking for %s\n", debugstr_a(name) ); |
| 309 | |
| 310 | if (SearchPathA( NULL, name, ".exe", buflen, buffer, NULL )) |
| 311 | { |
| 312 | *handle = open_exe_file( buffer ); |
| 313 | return TRUE; |
| 314 | } |
| 315 | |
| 316 | /* no such file in path, try builtin with .exe extension */ |
| 317 | |
| 318 | lstrcpynA( buffer, get_basename(name), buflen ); |
| 319 | if (!strchr( buffer, '.' )) |
| 320 | { |
| 321 | char *p = buffer + strlen(buffer); |
| 322 | lstrcpynA( p, ".exe", buflen - (p - buffer) ); |
| 323 | } |
| 324 | |
| 325 | MODULE_GetLoadOrder( loadorder, buffer, TRUE ); |
| 326 | for (i = 0; i < LOADORDER_NTYPES; i++) |
| 327 | { |
| 328 | if (loadorder[i] == LOADORDER_BI) |
| 329 | { |
| 330 | TRACE( "Trying built-in exe %s\n", debugstr_a(buffer) ); |
| 331 | if (wine_dll_load_main_exe( buffer, NULL, 0, 1 )) |
| 332 | { |
| 333 | *handle = 0; |
| 334 | return TRUE; |
| 335 | } |
| 336 | break; |
| 337 | } |
| 338 | if (loadorder[i] == LOADORDER_INVALID) break; |
| 339 | } |
| 340 | |
| 341 | /* no builtin found, try native without extension in case it is a Unix app */ |
| 342 | |
| 343 | if (SearchPathA( NULL, name, NULL, buflen, buffer, NULL )) |
| 344 | { |
| 345 | TRACE( "Trying native/Unix binary %s\n", debugstr_a(buffer) ); |
| 346 | if ((*handle = CreateFileA( buffer, GENERIC_READ, FILE_SHARE_READ, |
| 347 | NULL, OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE) |
| 348 | return TRUE; |
| 349 | } |
| 350 | return FALSE; |
| 351 | } |
| 352 | |
| 353 | |
Alexandre Julliard | a4bc5a2 | 2001-02-16 19:08:19 +0000 | [diff] [blame] | 354 | /*********************************************************************** |
Alexandre Julliard | a3e0cfc | 2000-07-16 18:21:34 +0000 | [diff] [blame] | 355 | * process_init |
| 356 | * |
| 357 | * Main process initialisation code |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 358 | */ |
Alexandre Julliard | a3e0cfc | 2000-07-16 18:21:34 +0000 | [diff] [blame] | 359 | static BOOL process_init( char *argv[] ) |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 360 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 361 | BOOL ret; |
Alexandre Julliard | 6543a65 | 2002-03-29 18:28:56 +0000 | [diff] [blame] | 362 | size_t info_size = 0; |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 363 | |
Alexandre Julliard | a3e0cfc | 2000-07-16 18:21:34 +0000 | [diff] [blame] | 364 | /* store the program name */ |
| 365 | argv0 = argv[0]; |
| 366 | |
Alexandre Julliard | 214399f | 1999-02-21 18:35:27 +0000 | [diff] [blame] | 367 | /* Fill the initial process structure */ |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 368 | current_process.exit_code = STILL_ACTIVE; |
| 369 | current_process.threads = 1; |
| 370 | current_process.running_threads = 1; |
| 371 | current_process.ring0_threads = 1; |
| 372 | current_process.group = ¤t_process; |
| 373 | current_process.priority = 8; /* Normal */ |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 374 | |
| 375 | /* Setup the server connection */ |
Alexandre Julliard | 8859d77 | 2001-03-01 22:13:49 +0000 | [diff] [blame] | 376 | CLIENT_InitServer(); |
Alexandre Julliard | 214399f | 1999-02-21 18:35:27 +0000 | [diff] [blame] | 377 | |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 378 | /* Retrieve startup info from the server */ |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 379 | SERVER_START_REQ( init_process ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 380 | { |
Alexandre Julliard | 914406f | 2000-11-14 01:54:49 +0000 | [diff] [blame] | 381 | req->ldt_copy = &wine_ldt_copy; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 382 | req->ppid = getppid(); |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 383 | if ((ret = !wine_server_call_err( req ))) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 384 | { |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 385 | main_exe_file = reply->exe_file; |
| 386 | main_create_flags = reply->create_flags; |
| 387 | info_size = reply->info_size; |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 388 | server_startticks = reply->server_start; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 389 | current_startupinfo.hStdInput = reply->hstdin; |
| 390 | current_startupinfo.hStdOutput = reply->hstdout; |
| 391 | current_startupinfo.hStdError = reply->hstderr; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 392 | } |
| 393 | } |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 394 | SERVER_END_REQ; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 395 | if (!ret) return FALSE; |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 396 | |
Alexandre Julliard | 7f187e5 | 2001-02-23 01:37:05 +0000 | [diff] [blame] | 397 | /* Create the process heap */ |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 398 | current_process.heap = HeapCreate( HEAP_GROWABLE, 0, 0 ); |
Alexandre Julliard | 96c08d8 | 1999-02-28 13:27:56 +0000 | [diff] [blame] | 399 | |
Dmitry Timoshkov | 1c2fa97 | 2002-04-09 01:38:41 +0000 | [diff] [blame] | 400 | if (main_create_flags == 0 && |
Eric Pouech | 0b83d4c | 2001-11-23 23:04:58 +0000 | [diff] [blame] | 401 | current_startupinfo.hStdInput == 0 && |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 402 | current_startupinfo.hStdOutput == 0 && |
Eric Pouech | 0b83d4c | 2001-11-23 23:04:58 +0000 | [diff] [blame] | 403 | current_startupinfo.hStdError == 0) |
| 404 | { |
| 405 | /* no parent, and no new console requested, create a simple console with bare handles to |
| 406 | * unix stdio input & output streams (aka simple console) |
| 407 | */ |
Alexandre Julliard | be367c7 | 2002-05-30 20:40:02 +0000 | [diff] [blame] | 408 | HANDLE handle; |
| 409 | wine_server_fd_to_handle( 0, GENERIC_READ|SYNCHRONIZE, TRUE, &handle ); |
| 410 | SetStdHandle( STD_INPUT_HANDLE, handle ); |
| 411 | wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, TRUE, &handle ); |
| 412 | SetStdHandle( STD_OUTPUT_HANDLE, handle ); |
| 413 | wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, TRUE, &handle ); |
| 414 | SetStdHandle( STD_ERROR_HANDLE, handle ); |
Eric Pouech | 0b83d4c | 2001-11-23 23:04:58 +0000 | [diff] [blame] | 415 | } |
Dmitry Timoshkov | 1c2fa97 | 2002-04-09 01:38:41 +0000 | [diff] [blame] | 416 | else if (!(main_create_flags & (DETACHED_PROCESS|CREATE_NEW_CONSOLE))) |
Eric Pouech | 0b83d4c | 2001-11-23 23:04:58 +0000 | [diff] [blame] | 417 | { |
| 418 | SetStdHandle( STD_INPUT_HANDLE, current_startupinfo.hStdInput ); |
| 419 | SetStdHandle( STD_OUTPUT_HANDLE, current_startupinfo.hStdOutput ); |
| 420 | SetStdHandle( STD_ERROR_HANDLE, current_startupinfo.hStdError ); |
| 421 | } |
| 422 | |
Alexandre Julliard | 7f187e5 | 2001-02-23 01:37:05 +0000 | [diff] [blame] | 423 | /* Now we can use the pthreads routines */ |
| 424 | PTHREAD_init_done(); |
| 425 | |
Alexandre Julliard | b445952 | 2000-04-15 21:00:55 +0000 | [diff] [blame] | 426 | /* Copy the parent environment */ |
Alexandre Julliard | 9d80215 | 2002-05-24 21:20:27 +0000 | [diff] [blame] | 427 | if (!(current_process.env_db = ENV_InitStartupInfo( info_size, main_exe_name, |
| 428 | sizeof(main_exe_name) ))) |
Alexandre Julliard | 6543a65 | 2002-03-29 18:28:56 +0000 | [diff] [blame] | 429 | return FALSE; |
Alexandre Julliard | f016752 | 1999-03-21 19:26:25 +0000 | [diff] [blame] | 430 | |
Alexandre Julliard | a3e0cfc | 2000-07-16 18:21:34 +0000 | [diff] [blame] | 431 | /* Parse command line arguments */ |
Alexandre Julliard | 9d80215 | 2002-05-24 21:20:27 +0000 | [diff] [blame] | 432 | OPTIONS_ParseOptions( !info_size ? argv : NULL ); |
Alexandre Julliard | a3e0cfc | 2000-07-16 18:21:34 +0000 | [diff] [blame] | 433 | |
Eric Pouech | 0b83d4c | 2001-11-23 23:04:58 +0000 | [diff] [blame] | 434 | ret = MAIN_MainInit(); |
Alexandre Julliard | a061b84 | 2002-06-04 17:48:41 +0000 | [diff] [blame^] | 435 | if (TRACE_ON(relay) || TRACE_ON(snoop)) RELAY_InitDebugLists(); |
Eric Pouech | 0b83d4c | 2001-11-23 23:04:58 +0000 | [diff] [blame] | 436 | |
Eric Pouech | 0b83d4c | 2001-11-23 23:04:58 +0000 | [diff] [blame] | 437 | return ret; |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 438 | } |
| 439 | |
| 440 | |
| 441 | /*********************************************************************** |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 442 | * start_process |
| 443 | * |
| 444 | * Startup routine of a new process. Runs on the new process stack. |
| 445 | */ |
| 446 | static void start_process(void) |
| 447 | { |
Alexandre Julliard | 42cc2bd | 2000-06-07 03:49:41 +0000 | [diff] [blame] | 448 | int debugged, console_app; |
Alexandre Julliard | 42cc2bd | 2000-06-07 03:49:41 +0000 | [diff] [blame] | 449 | LPTHREAD_START_ROUTINE entry; |
Alexandre Julliard | e087508 | 2000-11-08 04:33:20 +0000 | [diff] [blame] | 450 | WINE_MODREF *wm; |
Alexandre Julliard | ac2e4f1 | 2001-10-25 19:52:12 +0000 | [diff] [blame] | 451 | HFILE main_file = main_exe_file; |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 452 | |
Alexandre Julliard | e087508 | 2000-11-08 04:33:20 +0000 | [diff] [blame] | 453 | /* use original argv[0] as name for the main module */ |
| 454 | if (!main_exe_name[0]) |
| 455 | { |
| 456 | if (!GetLongPathNameA( full_argv0, main_exe_name, sizeof(main_exe_name) )) |
| 457 | lstrcpynA( main_exe_name, full_argv0, sizeof(main_exe_name) ); |
| 458 | } |
| 459 | |
Alexandre Julliard | ac2e4f1 | 2001-10-25 19:52:12 +0000 | [diff] [blame] | 460 | if (main_file) |
| 461 | { |
| 462 | UINT drive_type = GetDriveTypeA( main_exe_name ); |
| 463 | /* don't keep the file handle open on removable media */ |
| 464 | if (drive_type == DRIVE_REMOVABLE || drive_type == DRIVE_CDROM) main_file = 0; |
| 465 | } |
| 466 | |
Alexandre Julliard | e087508 | 2000-11-08 04:33:20 +0000 | [diff] [blame] | 467 | /* Retrieve entry point address */ |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 468 | entry = (LPTHREAD_START_ROUTINE)((char*)current_process.module + |
| 469 | PE_HEADER(current_process.module)->OptionalHeader.AddressOfEntryPoint); |
| 470 | console_app = (PE_HEADER(current_process.module)->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI); |
Dmitry Timoshkov | 1c2fa97 | 2002-04-09 01:38:41 +0000 | [diff] [blame] | 471 | if (console_app) |
| 472 | { |
| 473 | current_process.flags |= PDB32_CONSOLE_PROC; |
| 474 | if (main_create_flags & CREATE_NEW_CONSOLE) AllocConsole(); |
| 475 | } |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 476 | |
Alexandre Julliard | 42cc2bd | 2000-06-07 03:49:41 +0000 | [diff] [blame] | 477 | /* Signal the parent process to continue */ |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 478 | SERVER_START_REQ( init_process_done ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 479 | { |
Alexandre Julliard | aeb5660 | 2002-03-22 00:21:23 +0000 | [diff] [blame] | 480 | req->module = (void *)current_process.module; |
| 481 | req->module_size = PE_HEADER(current_process.module)->OptionalHeader.SizeOfImage; |
Alexandre Julliard | ad29b90 | 2001-01-05 22:24:15 +0000 | [diff] [blame] | 482 | req->entry = entry; |
Eric Pouech | 8c03474 | 2001-08-06 17:48:17 +0000 | [diff] [blame] | 483 | /* API requires a double indirection */ |
| 484 | req->name = &main_exe_name_ptr; |
Alexandre Julliard | ac2e4f1 | 2001-10-25 19:52:12 +0000 | [diff] [blame] | 485 | req->exe_file = main_file; |
Alexandre Julliard | ad29b90 | 2001-01-05 22:24:15 +0000 | [diff] [blame] | 486 | req->gui = !console_app; |
Alexandre Julliard | aeb5660 | 2002-03-22 00:21:23 +0000 | [diff] [blame] | 487 | wine_server_add_data( req, main_exe_name, strlen(main_exe_name) ); |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 488 | wine_server_call( req ); |
| 489 | debugged = reply->debugged; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 490 | } |
| 491 | SERVER_END_REQ; |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 492 | |
Alexandre Julliard | 42cc2bd | 2000-06-07 03:49:41 +0000 | [diff] [blame] | 493 | /* Install signal handlers; this cannot be done before, since we cannot |
| 494 | * send exceptions to the debugger before the create process event that |
| 495 | * is sent by REQ_INIT_PROCESS_DONE */ |
| 496 | if (!SIGNAL_Init()) goto error; |
Alexandre Julliard | 7fe09bc | 2000-06-03 04:49:40 +0000 | [diff] [blame] | 497 | |
Alexandre Julliard | e087508 | 2000-11-08 04:33:20 +0000 | [diff] [blame] | 498 | /* create the main modref and load dependencies */ |
Alexandre Julliard | ad29b90 | 2001-01-05 22:24:15 +0000 | [diff] [blame] | 499 | if (!(wm = PE_CreateModule( current_process.module, main_exe_name, 0, 0, FALSE ))) |
Alexandre Julliard | e087508 | 2000-11-08 04:33:20 +0000 | [diff] [blame] | 500 | goto error; |
| 501 | wm->refCount++; |
| 502 | |
Alexandre Julliard | ac2e4f1 | 2001-10-25 19:52:12 +0000 | [diff] [blame] | 503 | if (main_exe_file) CloseHandle( main_exe_file ); /* we no longer need it */ |
| 504 | |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 505 | MODULE_DllProcessAttach( NULL, (LPVOID)1 ); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 506 | |
Alexandre Julliard | 4e951ea | 2000-11-08 22:47:53 +0000 | [diff] [blame] | 507 | /* Note: The USIG_PROCESS_CREATE signal is supposed to be sent in the |
| 508 | * context of the parent process. Actually, the USER signal proc |
| 509 | * doesn't really care about that, but it *does* require that the |
| 510 | * startup parameters are correctly set up, so that GetProcessDword |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 511 | * works. Furthermore, before calling the USER signal proc the |
Alexandre Julliard | 4e951ea | 2000-11-08 22:47:53 +0000 | [diff] [blame] | 512 | * 16-bit stack must be set up, which it is only after TASK_Create |
| 513 | * in the case of a 16-bit process. Thus, we send the signal here. |
| 514 | */ |
| 515 | PROCESS_CallUserSignalProc( USIG_PROCESS_CREATE, 0 ); |
| 516 | PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 ); |
| 517 | PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0 ); |
| 518 | PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0 ); |
Alexandre Julliard | 42cc2bd | 2000-06-07 03:49:41 +0000 | [diff] [blame] | 519 | /* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */ |
| 520 | if (console_app) PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 ); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 521 | |
Francois Gouget | e17d1a3 | 2001-05-08 00:13:38 +0000 | [diff] [blame] | 522 | if (TRACE_ON(relay)) |
| 523 | DPRINTF( "%08lx:Starting process %s (entryproc=%p)\n", |
| 524 | GetCurrentThreadId(), main_exe_name, entry ); |
Alexandre Julliard | 42cc2bd | 2000-06-07 03:49:41 +0000 | [diff] [blame] | 525 | if (debugged) DbgBreakPoint(); |
| 526 | /* FIXME: should use _PEB as parameter for NT 3.5 programs ! |
| 527 | * Dunno about other OSs */ |
Alexandre Julliard | 973ce4a | 2000-08-25 22:02:14 +0000 | [diff] [blame] | 528 | SetLastError(0); /* clear error code */ |
Alexandre Julliard | 42cc2bd | 2000-06-07 03:49:41 +0000 | [diff] [blame] | 529 | ExitThread( entry(NULL) ); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 530 | |
Alexandre Julliard | 42cc2bd | 2000-06-07 03:49:41 +0000 | [diff] [blame] | 531 | error: |
| 532 | ExitProcess( GetLastError() ); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 533 | } |
| 534 | |
| 535 | |
| 536 | /*********************************************************************** |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 537 | * PROCESS_InitWine |
| 538 | * |
| 539 | * Wine initialisation: load and start the main exe file. |
| 540 | */ |
Alexandre Julliard | 105b0f4 | 2001-01-06 01:55:49 +0000 | [diff] [blame] | 541 | void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win16_exe_file ) |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 542 | { |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 543 | char error[100]; |
Alexandre Julliard | e087508 | 2000-11-08 04:33:20 +0000 | [diff] [blame] | 544 | DWORD stack_size = 0; |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 545 | |
| 546 | /* Initialize everything */ |
Alexandre Julliard | a3e0cfc | 2000-07-16 18:21:34 +0000 | [diff] [blame] | 547 | if (!process_init( argv )) exit(1); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 548 | |
Alexandre Julliard | 702b158 | 2002-05-16 23:16:01 +0000 | [diff] [blame] | 549 | argv++; /* remove argv[0] (wine itself) */ |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 550 | |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 551 | TRACE( "starting process name=%s file=%x argv[0]=%s\n", |
| 552 | debugstr_a(main_exe_name), main_exe_file, debugstr_a(argv[0]) ); |
| 553 | |
Alexandre Julliard | 9264300 | 2000-08-31 01:59:51 +0000 | [diff] [blame] | 554 | if (!main_exe_name[0]) |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 555 | { |
Alexandre Julliard | 702b158 | 2002-05-16 23:16:01 +0000 | [diff] [blame] | 556 | if (!argv[0]) OPTIONS_Usage(); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 557 | |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 558 | if (!find_exe_file( argv[0], main_exe_name, sizeof(main_exe_name), &main_exe_file )) |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 559 | { |
Alexandre Julliard | 702b158 | 2002-05-16 23:16:01 +0000 | [diff] [blame] | 560 | MESSAGE( "%s: cannot find '%s'\n", argv0, argv[0] ); |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 561 | ExitProcess(1); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 562 | } |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 563 | if (main_exe_file == INVALID_HANDLE_VALUE) |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 564 | { |
| 565 | MESSAGE( "%s: cannot open '%s'\n", argv0, main_exe_name ); |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 566 | ExitProcess(1); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 567 | } |
| 568 | } |
| 569 | |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 570 | if (!main_exe_file) /* no file handle -> Winelib app */ |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 571 | { |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 572 | TRACE( "starting Winelib app %s\n", debugstr_a(main_exe_name) ); |
| 573 | if (wine_dll_load_main_exe( get_basename(main_exe_name), error, sizeof(error), 0 )) |
| 574 | goto found; |
| 575 | MESSAGE( "%s: cannot open builtin library for '%s': %s\n", argv0, main_exe_name, error ); |
| 576 | ExitProcess(1); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 577 | } |
| 578 | |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 579 | switch( MODULE_GetBinaryType( main_exe_file )) |
| 580 | { |
| 581 | case BINARY_UNKNOWN: |
| 582 | MESSAGE( "%s: cannot determine executable type for '%s'\n", argv0, main_exe_name ); |
| 583 | ExitProcess(1); |
| 584 | case BINARY_PE_EXE: |
| 585 | TRACE( "starting Win32 binary %s\n", debugstr_a(main_exe_name) ); |
| 586 | if ((current_process.module = PE_LoadImage( main_exe_file, main_exe_name, 0 ))) goto found; |
| 587 | MESSAGE( "%s: could not load '%s' as Win32 binary\n", argv0, main_exe_name ); |
| 588 | ExitProcess(1); |
| 589 | case BINARY_PE_DLL: |
| 590 | MESSAGE( "%s: '%s' is a DLL, not an executable\n", argv0, main_exe_name ); |
| 591 | ExitProcess(1); |
| 592 | case BINARY_WIN16: |
| 593 | case BINARY_DOS: |
| 594 | TRACE( "starting Win16/DOS binary %s\n", debugstr_a(main_exe_name) ); |
| 595 | NtCurrentTeb()->tibflags &= ~TEBF_WIN32; |
| 596 | current_process.flags |= PDB32_WIN16_PROC; |
| 597 | strcpy( win16_exe_name, main_exe_name ); |
| 598 | main_exe_name[0] = 0; |
| 599 | *win16_exe_file = main_exe_file; |
| 600 | main_exe_file = 0; |
| 601 | _EnterWin16Lock(); |
| 602 | goto found; |
| 603 | case BINARY_OS216: |
| 604 | MESSAGE( "%s: '%s' is an OS/2 binary, not supported\n", argv0, main_exe_name ); |
| 605 | ExitProcess(1); |
| 606 | case BINARY_UNIX_EXE: |
| 607 | MESSAGE( "%s: '%s' is a Unix binary, not supported\n", argv0, main_exe_name ); |
| 608 | ExitProcess(1); |
| 609 | case BINARY_UNIX_LIB: |
| 610 | { |
| 611 | DOS_FULL_NAME full_name; |
| 612 | const char *name = main_exe_name; |
| 613 | |
| 614 | TRACE( "starting Winelib app %s\n", debugstr_a(main_exe_name) ); |
| 615 | if (DOSFS_GetFullName( name, TRUE, &full_name )) name = full_name.long_name; |
| 616 | CloseHandle( main_exe_file ); |
| 617 | main_exe_file = 0; |
| 618 | if (wine_dlopen( name, RTLD_NOW, error, sizeof(error) )) goto found; |
| 619 | MESSAGE( "%s: could not load '%s': %s\n", argv0, main_exe_name, error ); |
| 620 | ExitProcess(1); |
| 621 | } |
| 622 | } |
Alexandre Julliard | 591832e | 2000-11-10 01:38:28 +0000 | [diff] [blame] | 623 | |
| 624 | found: |
Alexandre Julliard | 3581865 | 2001-06-07 22:29:03 +0000 | [diff] [blame] | 625 | /* build command line */ |
Alexandre Julliard | 702b158 | 2002-05-16 23:16:01 +0000 | [diff] [blame] | 626 | if (!ENV_BuildCommandLine( argv )) goto error; |
Alexandre Julliard | 3581865 | 2001-06-07 22:29:03 +0000 | [diff] [blame] | 627 | |
| 628 | /* create 32-bit module for main exe */ |
| 629 | if (!(current_process.module = BUILTIN32_LoadExeModule( current_process.module ))) goto error; |
| 630 | stack_size = PE_HEADER(current_process.module)->OptionalHeader.SizeOfStackReserve; |
| 631 | |
Alexandre Julliard | e087508 | 2000-11-08 04:33:20 +0000 | [diff] [blame] | 632 | /* allocate main thread stack */ |
Alexandre Julliard | 9ee9eff | 2001-02-28 05:29:50 +0000 | [diff] [blame] | 633 | if (!THREAD_InitStack( NtCurrentTeb(), stack_size )) goto error; |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 634 | |
Alexandre Julliard | e087508 | 2000-11-08 04:33:20 +0000 | [diff] [blame] | 635 | /* switch to the new stack */ |
| 636 | SYSDEPS_SwitchToThreadStack( start_process ); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 637 | |
Alexandre Julliard | b445952 | 2000-04-15 21:00:55 +0000 | [diff] [blame] | 638 | error: |
| 639 | ExitProcess( GetLastError() ); |
| 640 | } |
| 641 | |
| 642 | |
| 643 | /*********************************************************************** |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 644 | * build_argv |
| 645 | * |
| 646 | * Build an argv array from a command-line. |
| 647 | * The command-line is modified to insert nulls. |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 648 | * 'reserved' is the number of args to reserve before the first one. |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 649 | */ |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 650 | static char **build_argv( char *cmdline, int reserved ) |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 651 | { |
Francois Gouget | 5ee3879 | 2001-09-20 19:05:11 +0000 | [diff] [blame] | 652 | int argc; |
| 653 | char** argv; |
| 654 | char *arg,*s,*d; |
| 655 | int in_quotes,bcount; |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 656 | |
Francois Gouget | 5ee3879 | 2001-09-20 19:05:11 +0000 | [diff] [blame] | 657 | argc=reserved+1; |
| 658 | bcount=0; |
| 659 | in_quotes=0; |
| 660 | s=cmdline; |
| 661 | while (1) { |
| 662 | if (*s=='\0' || ((*s==' ' || *s=='\t') && !in_quotes)) { |
| 663 | /* space */ |
| 664 | argc++; |
| 665 | /* skip the remaining spaces */ |
| 666 | while (*s==' ' || *s=='\t') { |
| 667 | s++; |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 668 | } |
Francois Gouget | 5ee3879 | 2001-09-20 19:05:11 +0000 | [diff] [blame] | 669 | if (*s=='\0') |
| 670 | break; |
| 671 | bcount=0; |
| 672 | continue; |
| 673 | } else if (*s=='\\') { |
| 674 | /* '\', count them */ |
| 675 | bcount++; |
| 676 | } else if ((*s=='"') && ((bcount & 1)==0)) { |
| 677 | /* unescaped '"' */ |
| 678 | in_quotes=!in_quotes; |
| 679 | bcount=0; |
| 680 | } else { |
| 681 | /* a regular character */ |
| 682 | bcount=0; |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 683 | } |
Francois Gouget | 5ee3879 | 2001-09-20 19:05:11 +0000 | [diff] [blame] | 684 | s++; |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 685 | } |
Francois Gouget | 5ee3879 | 2001-09-20 19:05:11 +0000 | [diff] [blame] | 686 | argv=malloc(argc*sizeof(*argv)); |
| 687 | if (!argv) |
| 688 | return NULL; |
| 689 | |
| 690 | arg=d=s=cmdline; |
| 691 | bcount=0; |
| 692 | in_quotes=0; |
| 693 | argc=reserved; |
| 694 | while (*s) { |
| 695 | if ((*s==' ' || *s=='\t') && !in_quotes) { |
| 696 | /* Close the argument and copy it */ |
| 697 | *d=0; |
| 698 | argv[argc++]=arg; |
| 699 | |
| 700 | /* skip the remaining spaces */ |
| 701 | do { |
| 702 | s++; |
| 703 | } while (*s==' ' || *s=='\t'); |
| 704 | |
| 705 | /* Start with a new argument */ |
| 706 | arg=d=s; |
| 707 | bcount=0; |
| 708 | } else if (*s=='\\') { |
| 709 | /* '\\' */ |
| 710 | *d++=*s++; |
| 711 | bcount++; |
| 712 | } else if (*s=='"') { |
| 713 | /* '"' */ |
| 714 | if ((bcount & 1)==0) { |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 715 | /* Preceeded by an even number of '\', this is half that |
Francois Gouget | 5ee3879 | 2001-09-20 19:05:11 +0000 | [diff] [blame] | 716 | * number of '\', plus a '"' which we discard. |
| 717 | */ |
| 718 | d-=bcount/2; |
| 719 | s++; |
| 720 | in_quotes=!in_quotes; |
| 721 | } else { |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 722 | /* Preceeded by an odd number of '\', this is half that |
Francois Gouget | 5ee3879 | 2001-09-20 19:05:11 +0000 | [diff] [blame] | 723 | * number of '\' followed by a '"' |
| 724 | */ |
| 725 | d=d-bcount/2-1; |
| 726 | *d++='"'; |
| 727 | s++; |
| 728 | } |
| 729 | bcount=0; |
| 730 | } else { |
| 731 | /* a regular character */ |
| 732 | *d++=*s++; |
| 733 | bcount=0; |
| 734 | } |
| 735 | } |
| 736 | if (*arg) { |
| 737 | *d='\0'; |
| 738 | argv[argc++]=arg; |
| 739 | } |
| 740 | argv[argc]=NULL; |
| 741 | |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 742 | return argv; |
| 743 | } |
| 744 | |
| 745 | |
| 746 | /*********************************************************************** |
| 747 | * build_envp |
| 748 | * |
| 749 | * Build the environment of a new child process. |
| 750 | */ |
Alexandre Julliard | aef9a36 | 2000-10-03 04:19:16 +0000 | [diff] [blame] | 751 | static char **build_envp( const char *env, const char *extra_env ) |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 752 | { |
| 753 | const char *p; |
| 754 | char **envp; |
Alexandre Julliard | aef9a36 | 2000-10-03 04:19:16 +0000 | [diff] [blame] | 755 | int count = 0; |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 756 | |
Alexandre Julliard | aef9a36 | 2000-10-03 04:19:16 +0000 | [diff] [blame] | 757 | if (extra_env) for (p = extra_env; *p; count++) p += strlen(p) + 1; |
| 758 | for (p = env; *p; count++) p += strlen(p) + 1; |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 759 | count += 3; |
Alexandre Julliard | aef9a36 | 2000-10-03 04:19:16 +0000 | [diff] [blame] | 760 | |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 761 | if ((envp = malloc( count * sizeof(*envp) ))) |
| 762 | { |
| 763 | extern char **environ; |
| 764 | char **envptr = envp; |
| 765 | char **unixptr = environ; |
Alexandre Julliard | aef9a36 | 2000-10-03 04:19:16 +0000 | [diff] [blame] | 766 | /* first the extra strings */ |
| 767 | if (extra_env) for (p = extra_env; *p; p += strlen(p) + 1) *envptr++ = (char *)p; |
| 768 | /* then put PATH, HOME and WINEPREFIX from the unix env */ |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 769 | for (unixptr = environ; unixptr && *unixptr; unixptr++) |
| 770 | if (!memcmp( *unixptr, "PATH=", 5 ) || |
| 771 | !memcmp( *unixptr, "HOME=", 5 ) || |
| 772 | !memcmp( *unixptr, "WINEPREFIX=", 11 )) *envptr++ = *unixptr; |
| 773 | /* now put the Windows environment strings */ |
| 774 | for (p = env; *p; p += strlen(p) + 1) |
| 775 | { |
| 776 | if (memcmp( p, "PATH=", 5 ) && |
| 777 | memcmp( p, "HOME=", 5 ) && |
| 778 | memcmp( p, "WINEPREFIX=", 11 )) *envptr++ = (char *)p; |
| 779 | } |
| 780 | *envptr = 0; |
| 781 | } |
| 782 | return envp; |
| 783 | } |
| 784 | |
| 785 | |
| 786 | /*********************************************************************** |
Andreas Mohr | 9714152 | 2000-09-02 23:18:16 +0000 | [diff] [blame] | 787 | * exec_wine_binary |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 788 | * |
| 789 | * Locate the Wine binary to exec for a new Win32 process. |
| 790 | */ |
| 791 | static void exec_wine_binary( char **argv, char **envp ) |
| 792 | { |
| 793 | const char *path, *pos, *ptr; |
| 794 | |
Jeremy White | 51e4657 | 2000-10-25 20:28:22 +0000 | [diff] [blame] | 795 | /* first, try for a WINELOADER environment variable */ |
| 796 | argv[0] = getenv("WINELOADER"); |
| 797 | if (argv[0]) |
| 798 | execve( argv[0], argv, envp ); |
| 799 | |
| 800 | /* next, try bin directory */ |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 801 | argv[0] = BINDIR "/wine"; |
| 802 | execve( argv[0], argv, envp ); |
| 803 | |
| 804 | /* now try the path of argv0 of the current binary */ |
Alexandre Julliard | a3e0cfc | 2000-07-16 18:21:34 +0000 | [diff] [blame] | 805 | if (!(argv[0] = malloc( strlen(full_argv0) + 6 ))) return; |
| 806 | if ((ptr = strrchr( full_argv0, '/' ))) |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 807 | { |
Alexandre Julliard | a3e0cfc | 2000-07-16 18:21:34 +0000 | [diff] [blame] | 808 | memcpy( argv[0], full_argv0, ptr - full_argv0 ); |
| 809 | strcpy( argv[0] + (ptr - full_argv0), "/wine" ); |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 810 | execve( argv[0], argv, envp ); |
| 811 | } |
| 812 | free( argv[0] ); |
| 813 | |
| 814 | /* now search in the Unix path */ |
| 815 | if ((path = getenv( "PATH" ))) |
| 816 | { |
| 817 | if (!(argv[0] = malloc( strlen(path) + 6 ))) return; |
| 818 | pos = path; |
| 819 | for (;;) |
| 820 | { |
| 821 | while (*pos == ':') pos++; |
| 822 | if (!*pos) break; |
| 823 | if (!(ptr = strchr( pos, ':' ))) ptr = pos + strlen(pos); |
| 824 | memcpy( argv[0], pos, ptr - pos ); |
| 825 | strcpy( argv[0] + (ptr - pos), "/wine" ); |
| 826 | execve( argv[0], argv, envp ); |
| 827 | pos = ptr; |
| 828 | } |
| 829 | } |
| 830 | free( argv[0] ); |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 831 | } |
| 832 | |
| 833 | |
| 834 | /*********************************************************************** |
| 835 | * fork_and_exec |
| 836 | * |
| 837 | * Fork and exec a new Unix process, checking for errors. |
| 838 | */ |
Marcus Meissner | dad7091 | 2000-07-16 15:42:22 +0000 | [diff] [blame] | 839 | static int fork_and_exec( const char *filename, char *cmdline, |
| 840 | const char *env, const char *newdir ) |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 841 | { |
| 842 | int fd[2]; |
| 843 | int pid, err; |
Alexandre Julliard | aef9a36 | 2000-10-03 04:19:16 +0000 | [diff] [blame] | 844 | char *extra_env = NULL; |
| 845 | |
| 846 | if (!env) |
| 847 | { |
| 848 | env = GetEnvironmentStringsA(); |
| 849 | extra_env = DRIVE_BuildEnv(); |
| 850 | } |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 851 | |
| 852 | if (pipe(fd) == -1) |
| 853 | { |
| 854 | FILE_SetDosError(); |
| 855 | return -1; |
| 856 | } |
| 857 | fcntl( fd[1], F_SETFD, 1 ); /* set close on exec */ |
| 858 | if (!(pid = fork())) /* child */ |
| 859 | { |
Alexandre Julliard | aa04a6f | 2002-04-29 19:34:06 +0000 | [diff] [blame] | 860 | char **argv = build_argv( cmdline, filename ? 0 : 1 ); |
Alexandre Julliard | aef9a36 | 2000-10-03 04:19:16 +0000 | [diff] [blame] | 861 | char **envp = build_envp( env, extra_env ); |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 862 | close( fd[0] ); |
Marcus Meissner | dad7091 | 2000-07-16 15:42:22 +0000 | [diff] [blame] | 863 | |
Alexandre Julliard | aef9a36 | 2000-10-03 04:19:16 +0000 | [diff] [blame] | 864 | if (newdir) chdir(newdir); |
Marcus Meissner | dad7091 | 2000-07-16 15:42:22 +0000 | [diff] [blame] | 865 | |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 866 | if (argv && envp) |
| 867 | { |
Alexandre Julliard | aa04a6f | 2002-04-29 19:34:06 +0000 | [diff] [blame] | 868 | if (!filename) exec_wine_binary( argv, envp ); |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 869 | else execve( filename, argv, envp ); |
| 870 | } |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 871 | err = errno; |
| 872 | write( fd[1], &err, sizeof(err) ); |
| 873 | _exit(1); |
| 874 | } |
| 875 | close( fd[1] ); |
| 876 | if ((pid != -1) && (read( fd[0], &err, sizeof(err) ) > 0)) /* exec failed */ |
| 877 | { |
| 878 | errno = err; |
| 879 | pid = -1; |
| 880 | } |
| 881 | if (pid == -1) FILE_SetDosError(); |
| 882 | close( fd[0] ); |
Alexandre Julliard | aef9a36 | 2000-10-03 04:19:16 +0000 | [diff] [blame] | 883 | if (extra_env) HeapFree( GetProcessHeap(), 0, extra_env ); |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 884 | return pid; |
| 885 | } |
| 886 | |
| 887 | |
| 888 | /*********************************************************************** |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 889 | * create_process |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 890 | * |
| 891 | * Create a new process. If hFile is a valid handle we have an exe |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 892 | * file, otherwise it is a Winelib app. |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 893 | */ |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 894 | static BOOL create_process( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCSTR env, |
| 895 | LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, |
| 896 | BOOL inherit, DWORD flags, LPSTARTUPINFOA startup, |
| 897 | LPPROCESS_INFORMATION info, LPCSTR unixdir ) |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 898 | { |
Alexandre Julliard | 9d80215 | 2002-05-24 21:20:27 +0000 | [diff] [blame] | 899 | BOOL ret, success = FALSE; |
Alexandre Julliard | e9936d9 | 2001-01-26 00:22:26 +0000 | [diff] [blame] | 900 | HANDLE process_info; |
Alexandre Julliard | 6543a65 | 2002-03-29 18:28:56 +0000 | [diff] [blame] | 901 | startup_info_t startup_info; |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 902 | |
Alexandre Julliard | 6543a65 | 2002-03-29 18:28:56 +0000 | [diff] [blame] | 903 | /* fill the startup info structure */ |
| 904 | |
| 905 | startup_info.size = sizeof(startup_info); |
| 906 | /* startup_info.filename_len is set below */ |
| 907 | startup_info.cmdline_len = cmd_line ? strlen(cmd_line) : 0; |
| 908 | startup_info.desktop_len = startup->lpDesktop ? strlen(startup->lpDesktop) : 0; |
| 909 | startup_info.title_len = startup->lpTitle ? strlen(startup->lpTitle) : 0; |
| 910 | startup_info.x = startup->dwX; |
| 911 | startup_info.y = startup->dwY; |
| 912 | startup_info.cx = startup->dwXSize; |
| 913 | startup_info.cy = startup->dwYSize; |
| 914 | startup_info.x_chars = startup->dwXCountChars; |
| 915 | startup_info.y_chars = startup->dwYCountChars; |
| 916 | startup_info.attribute = startup->dwFillAttribute; |
| 917 | startup_info.cmd_show = startup->wShowWindow; |
| 918 | startup_info.flags = startup->dwFlags; |
| 919 | |
Alexandre Julliard | 9264300 | 2000-08-31 01:59:51 +0000 | [diff] [blame] | 920 | /* create the process on the server side */ |
| 921 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 922 | SERVER_START_REQ( new_process ) |
Alexandre Julliard | c23b1ee | 2000-06-01 22:48:39 +0000 | [diff] [blame] | 923 | { |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 924 | char buf[MAX_PATH]; |
Alexandre Julliard | 6543a65 | 2002-03-29 18:28:56 +0000 | [diff] [blame] | 925 | LPCSTR nameptr; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 926 | |
Alexandre Julliard | 9264300 | 2000-08-31 01:59:51 +0000 | [diff] [blame] | 927 | req->inherit_all = inherit; |
| 928 | req->create_flags = flags; |
Alexandre Julliard | 6543a65 | 2002-03-29 18:28:56 +0000 | [diff] [blame] | 929 | req->use_handles = (startup->dwFlags & STARTF_USESTDHANDLES) != 0; |
Alexandre Julliard | 9264300 | 2000-08-31 01:59:51 +0000 | [diff] [blame] | 930 | req->exe_file = hFile; |
| 931 | if (startup->dwFlags & STARTF_USESTDHANDLES) |
| 932 | { |
| 933 | req->hstdin = startup->hStdInput; |
| 934 | req->hstdout = startup->hStdOutput; |
| 935 | req->hstderr = startup->hStdError; |
| 936 | } |
| 937 | else |
| 938 | { |
| 939 | req->hstdin = GetStdHandle( STD_INPUT_HANDLE ); |
| 940 | req->hstdout = GetStdHandle( STD_OUTPUT_HANDLE ); |
| 941 | req->hstderr = GetStdHandle( STD_ERROR_HANDLE ); |
| 942 | } |
Alexandre Julliard | 9264300 | 2000-08-31 01:59:51 +0000 | [diff] [blame] | 943 | |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 944 | if (GetLongPathNameA( filename, buf, MAX_PATH )) |
| 945 | nameptr = buf; |
| 946 | else |
| 947 | nameptr = filename; |
| 948 | |
Alexandre Julliard | 6543a65 | 2002-03-29 18:28:56 +0000 | [diff] [blame] | 949 | startup_info.filename_len = strlen(nameptr); |
| 950 | wine_server_add_data( req, &startup_info, sizeof(startup_info) ); |
| 951 | wine_server_add_data( req, nameptr, startup_info.filename_len ); |
| 952 | wine_server_add_data( req, cmd_line, startup_info.cmdline_len ); |
| 953 | wine_server_add_data( req, startup->lpDesktop, startup_info.desktop_len ); |
| 954 | wine_server_add_data( req, startup->lpTitle, startup_info.title_len ); |
| 955 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 956 | ret = !wine_server_call_err( req ); |
| 957 | process_info = reply->info; |
Alexandre Julliard | c23b1ee | 2000-06-01 22:48:39 +0000 | [diff] [blame] | 958 | } |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 959 | SERVER_END_REQ; |
Alexandre Julliard | 9264300 | 2000-08-31 01:59:51 +0000 | [diff] [blame] | 960 | if (!ret) return FALSE; |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 961 | |
| 962 | /* fork and execute */ |
| 963 | |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 964 | if (fork_and_exec( NULL, cmd_line, env, unixdir ) == -1) |
Alexandre Julliard | d7c4e4d | 2001-11-06 22:27:41 +0000 | [diff] [blame] | 965 | { |
| 966 | CloseHandle( process_info ); |
| 967 | return FALSE; |
| 968 | } |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 969 | |
Alexandre Julliard | e9936d9 | 2001-01-26 00:22:26 +0000 | [diff] [blame] | 970 | /* wait for the new process info to be ready */ |
| 971 | |
Alexandre Julliard | 9d80215 | 2002-05-24 21:20:27 +0000 | [diff] [blame] | 972 | WaitForSingleObject( process_info, INFINITE ); |
| 973 | SERVER_START_REQ( get_new_process_info ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 974 | { |
Alexandre Julliard | 9d80215 | 2002-05-24 21:20:27 +0000 | [diff] [blame] | 975 | req->info = process_info; |
| 976 | req->pinherit = (psa && (psa->nLength >= sizeof(*psa)) && psa->bInheritHandle); |
| 977 | req->tinherit = (tsa && (tsa->nLength >= sizeof(*tsa)) && tsa->bInheritHandle); |
| 978 | if ((ret = !wine_server_call_err( req ))) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 979 | { |
Alexandre Julliard | 9d80215 | 2002-05-24 21:20:27 +0000 | [diff] [blame] | 980 | info->dwProcessId = (DWORD)reply->pid; |
| 981 | info->dwThreadId = (DWORD)reply->tid; |
| 982 | info->hProcess = reply->phandle; |
| 983 | info->hThread = reply->thandle; |
| 984 | success = reply->success; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 985 | } |
Alexandre Julliard | 9d80215 | 2002-05-24 21:20:27 +0000 | [diff] [blame] | 986 | } |
| 987 | SERVER_END_REQ; |
| 988 | |
| 989 | if (ret && !success) /* new process failed to start */ |
| 990 | { |
| 991 | DWORD exitcode; |
| 992 | if (GetExitCodeProcess( info->hProcess, &exitcode )) SetLastError( exitcode ); |
| 993 | CloseHandle( info->hThread ); |
| 994 | CloseHandle( info->hProcess ); |
| 995 | ret = FALSE; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 996 | } |
Alexandre Julliard | e9936d9 | 2001-01-26 00:22:26 +0000 | [diff] [blame] | 997 | CloseHandle( process_info ); |
Alexandre Julliard | 9d80215 | 2002-05-24 21:20:27 +0000 | [diff] [blame] | 998 | return ret; |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 999 | } |
| 1000 | |
| 1001 | |
Alexandre Julliard | 3536316 | 2002-05-22 21:32:49 +0000 | [diff] [blame] | 1002 | /************************************************************************* |
| 1003 | * get_file_name |
| 1004 | * |
| 1005 | * Helper for CreateProcess: retrieve the file name to load from the |
| 1006 | * app name and command line. Store the file name in buffer, and |
| 1007 | * return a possibly modified command line. |
| 1008 | * Also returns a handle to the opened file if it's a Windows binary. |
| 1009 | */ |
| 1010 | static LPSTR get_file_name( LPCSTR appname, LPSTR cmdline, LPSTR buffer, |
| 1011 | int buflen, HANDLE *handle ) |
| 1012 | { |
| 1013 | char *name, *pos, *ret = NULL; |
| 1014 | const char *p; |
| 1015 | |
| 1016 | /* if we have an app name, everything is easy */ |
| 1017 | |
| 1018 | if (appname) |
| 1019 | { |
| 1020 | /* use the unmodified app name as file name */ |
| 1021 | lstrcpynA( buffer, appname, buflen ); |
| 1022 | *handle = open_exe_file( buffer ); |
| 1023 | if (!(ret = cmdline)) |
| 1024 | { |
| 1025 | /* no command-line, create one */ |
| 1026 | if ((ret = HeapAlloc( GetProcessHeap(), 0, strlen(appname) + 3 ))) |
| 1027 | sprintf( ret, "\"%s\"", appname ); |
| 1028 | } |
| 1029 | return ret; |
| 1030 | } |
| 1031 | |
| 1032 | if (!cmdline) |
| 1033 | { |
| 1034 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 1035 | return NULL; |
| 1036 | } |
| 1037 | |
| 1038 | /* first check for a quoted file name */ |
| 1039 | |
| 1040 | if ((cmdline[0] == '"') && ((p = strchr( cmdline + 1, '"' )))) |
| 1041 | { |
| 1042 | int len = p - cmdline - 1; |
| 1043 | /* extract the quoted portion as file name */ |
| 1044 | if (!(name = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) return NULL; |
| 1045 | memcpy( name, cmdline + 1, len ); |
| 1046 | name[len] = 0; |
| 1047 | |
| 1048 | if (find_exe_file( name, buffer, buflen, handle )) |
| 1049 | ret = cmdline; /* no change necessary */ |
| 1050 | goto done; |
| 1051 | } |
| 1052 | |
| 1053 | /* now try the command-line word by word */ |
| 1054 | |
| 1055 | if (!(name = HeapAlloc( GetProcessHeap(), 0, strlen(cmdline) + 1 ))) return NULL; |
| 1056 | pos = name; |
| 1057 | p = cmdline; |
| 1058 | |
| 1059 | while (*p) |
| 1060 | { |
| 1061 | do *pos++ = *p++; while (*p && *p != ' '); |
| 1062 | *pos = 0; |
| 1063 | if (find_exe_file( name, buffer, buflen, handle )) |
| 1064 | { |
| 1065 | ret = cmdline; |
| 1066 | break; |
| 1067 | } |
| 1068 | } |
| 1069 | |
| 1070 | if (!ret || !strchr( name, ' ' )) goto done; /* no change necessary */ |
| 1071 | |
| 1072 | /* now build a new command-line with quotes */ |
| 1073 | |
| 1074 | if (!(ret = HeapAlloc( GetProcessHeap(), 0, strlen(cmdline) + 3 ))) goto done; |
| 1075 | sprintf( ret, "\"%s\"%s", name, p ); |
| 1076 | |
| 1077 | done: |
| 1078 | HeapFree( GetProcessHeap(), 0, name ); |
| 1079 | return ret; |
| 1080 | } |
| 1081 | |
| 1082 | |
| 1083 | /********************************************************************** |
| 1084 | * CreateProcessA (KERNEL32.@) |
| 1085 | */ |
| 1086 | BOOL WINAPI CreateProcessA( LPCSTR app_name, LPSTR cmd_line, LPSECURITY_ATTRIBUTES process_attr, |
| 1087 | LPSECURITY_ATTRIBUTES thread_attr, BOOL inherit, |
| 1088 | DWORD flags, LPVOID env, LPCSTR cur_dir, |
| 1089 | LPSTARTUPINFOA startup_info, LPPROCESS_INFORMATION info ) |
| 1090 | { |
| 1091 | BOOL retv = FALSE; |
| 1092 | HANDLE hFile = 0; |
| 1093 | const char *unixdir = NULL; |
| 1094 | DOS_FULL_NAME full_dir; |
| 1095 | char name[MAX_PATH]; |
| 1096 | LPSTR tidy_cmdline; |
| 1097 | |
| 1098 | /* Process the AppName and/or CmdLine to get module name and path */ |
| 1099 | |
| 1100 | TRACE("app %s cmdline %s\n", debugstr_a(app_name), debugstr_a(cmd_line) ); |
| 1101 | |
| 1102 | if (!(tidy_cmdline = get_file_name( app_name, cmd_line, name, sizeof(name), &hFile ))) |
| 1103 | return FALSE; |
| 1104 | if (hFile == INVALID_HANDLE_VALUE) goto done; |
| 1105 | |
| 1106 | /* Warn if unsupported features are used */ |
| 1107 | |
| 1108 | if (flags & NORMAL_PRIORITY_CLASS) |
| 1109 | FIXME("(%s,...): NORMAL_PRIORITY_CLASS ignored\n", name); |
| 1110 | if (flags & IDLE_PRIORITY_CLASS) |
| 1111 | FIXME("(%s,...): IDLE_PRIORITY_CLASS ignored\n", name); |
| 1112 | if (flags & HIGH_PRIORITY_CLASS) |
| 1113 | FIXME("(%s,...): HIGH_PRIORITY_CLASS ignored\n", name); |
| 1114 | if (flags & REALTIME_PRIORITY_CLASS) |
| 1115 | FIXME("(%s,...): REALTIME_PRIORITY_CLASS ignored\n", name); |
| 1116 | if (flags & CREATE_NEW_PROCESS_GROUP) |
| 1117 | FIXME("(%s,...): CREATE_NEW_PROCESS_GROUP ignored\n", name); |
| 1118 | if (flags & CREATE_UNICODE_ENVIRONMENT) |
| 1119 | FIXME("(%s,...): CREATE_UNICODE_ENVIRONMENT ignored\n", name); |
| 1120 | if (flags & CREATE_SEPARATE_WOW_VDM) |
| 1121 | FIXME("(%s,...): CREATE_SEPARATE_WOW_VDM ignored\n", name); |
| 1122 | if (flags & CREATE_SHARED_WOW_VDM) |
| 1123 | FIXME("(%s,...): CREATE_SHARED_WOW_VDM ignored\n", name); |
| 1124 | if (flags & CREATE_DEFAULT_ERROR_MODE) |
| 1125 | FIXME("(%s,...): CREATE_DEFAULT_ERROR_MODE ignored\n", name); |
| 1126 | if (flags & CREATE_NO_WINDOW) |
| 1127 | FIXME("(%s,...): CREATE_NO_WINDOW ignored\n", name); |
| 1128 | if (flags & PROFILE_USER) |
| 1129 | FIXME("(%s,...): PROFILE_USER ignored\n", name); |
| 1130 | if (flags & PROFILE_KERNEL) |
| 1131 | FIXME("(%s,...): PROFILE_KERNEL ignored\n", name); |
| 1132 | if (flags & PROFILE_SERVER) |
| 1133 | FIXME("(%s,...): PROFILE_SERVER ignored\n", name); |
| 1134 | if (startup_info->lpDesktop) |
| 1135 | FIXME("(%s,...): startup_info->lpDesktop %s ignored\n", |
| 1136 | name, debugstr_a(startup_info->lpDesktop)); |
| 1137 | if (startup_info->dwFlags & STARTF_RUNFULLSCREEN) |
| 1138 | FIXME("(%s,...): STARTF_RUNFULLSCREEN ignored\n", name); |
| 1139 | if (startup_info->dwFlags & STARTF_FORCEONFEEDBACK) |
| 1140 | FIXME("(%s,...): STARTF_FORCEONFEEDBACK ignored\n", name); |
| 1141 | if (startup_info->dwFlags & STARTF_FORCEOFFFEEDBACK) |
| 1142 | FIXME("(%s,...): STARTF_FORCEOFFFEEDBACK ignored\n", name); |
| 1143 | if (startup_info->dwFlags & STARTF_USEHOTKEY) |
| 1144 | FIXME("(%s,...): STARTF_USEHOTKEY ignored\n", name); |
| 1145 | |
| 1146 | if (cur_dir) |
| 1147 | { |
| 1148 | if (DOSFS_GetFullName( cur_dir, TRUE, &full_dir )) |
| 1149 | unixdir = full_dir.long_name; |
| 1150 | } |
| 1151 | else |
| 1152 | { |
| 1153 | char buf[MAX_PATH]; |
| 1154 | if (GetCurrentDirectoryA(sizeof(buf),buf)) |
| 1155 | { |
| 1156 | if (DOSFS_GetFullName( buf, TRUE, &full_dir )) unixdir = full_dir.long_name; |
| 1157 | } |
| 1158 | } |
| 1159 | |
| 1160 | info->hThread = info->hProcess = 0; |
| 1161 | info->dwProcessId = info->dwThreadId = 0; |
| 1162 | |
| 1163 | /* Determine executable type */ |
| 1164 | |
| 1165 | if (!hFile) /* builtin exe */ |
| 1166 | { |
| 1167 | TRACE( "starting %s as Winelib app\n", debugstr_a(name) ); |
| 1168 | retv = create_process( 0, name, tidy_cmdline, env, process_attr, thread_attr, |
| 1169 | inherit, flags, startup_info, info, unixdir ); |
| 1170 | goto done; |
| 1171 | } |
| 1172 | |
| 1173 | switch( MODULE_GetBinaryType( hFile )) |
| 1174 | { |
| 1175 | case BINARY_PE_EXE: |
| 1176 | case BINARY_WIN16: |
| 1177 | case BINARY_DOS: |
| 1178 | TRACE( "starting %s as Windows binary\n", debugstr_a(name) ); |
| 1179 | retv = create_process( hFile, name, tidy_cmdline, env, process_attr, thread_attr, |
| 1180 | inherit, flags, startup_info, info, unixdir ); |
| 1181 | break; |
| 1182 | case BINARY_OS216: |
| 1183 | FIXME( "%s is OS/2 binary, not supported\n", debugstr_a(name) ); |
| 1184 | SetLastError( ERROR_BAD_EXE_FORMAT ); |
| 1185 | break; |
| 1186 | case BINARY_PE_DLL: |
| 1187 | TRACE( "not starting %s since it is a dll\n", debugstr_a(name) ); |
| 1188 | SetLastError( ERROR_BAD_EXE_FORMAT ); |
| 1189 | break; |
| 1190 | case BINARY_UNIX_LIB: |
| 1191 | TRACE( "%s is a Unix library, starting as Winelib app\n", debugstr_a(name) ); |
| 1192 | retv = create_process( hFile, name, tidy_cmdline, env, process_attr, thread_attr, |
| 1193 | inherit, flags, startup_info, info, unixdir ); |
| 1194 | break; |
| 1195 | case BINARY_UNIX_EXE: |
| 1196 | case BINARY_UNKNOWN: |
| 1197 | { |
| 1198 | /* unknown file, try as unix executable */ |
| 1199 | |
| 1200 | DOS_FULL_NAME full_name; |
| 1201 | const char *unixfilename = name; |
| 1202 | |
| 1203 | TRACE( "starting %s as Unix binary\n", debugstr_a(name) ); |
| 1204 | if (DOSFS_GetFullName( name, TRUE, &full_name )) unixfilename = full_name.long_name; |
| 1205 | retv = (fork_and_exec( unixfilename, tidy_cmdline, env, unixdir ) != -1); |
| 1206 | } |
| 1207 | break; |
| 1208 | } |
| 1209 | CloseHandle( hFile ); |
| 1210 | |
| 1211 | done: |
| 1212 | if (tidy_cmdline != cmd_line) HeapFree( GetProcessHeap(), 0, tidy_cmdline ); |
| 1213 | return retv; |
| 1214 | } |
| 1215 | |
| 1216 | |
| 1217 | /********************************************************************** |
| 1218 | * CreateProcessW (KERNEL32.@) |
| 1219 | * NOTES |
| 1220 | * lpReserved is not converted |
| 1221 | */ |
| 1222 | BOOL WINAPI CreateProcessW( LPCWSTR app_name, LPWSTR cmd_line, LPSECURITY_ATTRIBUTES process_attr, |
| 1223 | LPSECURITY_ATTRIBUTES thread_attr, BOOL inherit, DWORD flags, |
| 1224 | LPVOID env, LPCWSTR cur_dir, LPSTARTUPINFOW startup_info, |
| 1225 | LPPROCESS_INFORMATION info ) |
| 1226 | { |
| 1227 | BOOL ret; |
| 1228 | STARTUPINFOA StartupInfoA; |
| 1229 | |
| 1230 | LPSTR app_nameA = HEAP_strdupWtoA (GetProcessHeap(),0,app_name); |
| 1231 | LPSTR cmd_lineA = HEAP_strdupWtoA (GetProcessHeap(),0,cmd_line); |
| 1232 | LPSTR cur_dirA = HEAP_strdupWtoA (GetProcessHeap(),0,cur_dir); |
| 1233 | |
| 1234 | memcpy (&StartupInfoA, startup_info, sizeof(STARTUPINFOA)); |
| 1235 | StartupInfoA.lpDesktop = HEAP_strdupWtoA (GetProcessHeap(),0,startup_info->lpDesktop); |
| 1236 | StartupInfoA.lpTitle = HEAP_strdupWtoA (GetProcessHeap(),0,startup_info->lpTitle); |
| 1237 | |
| 1238 | TRACE_(win32)("(%s,%s,...)\n", debugstr_w(app_name), debugstr_w(cmd_line)); |
| 1239 | |
| 1240 | if (startup_info->lpReserved) |
| 1241 | FIXME_(win32)("StartupInfo.lpReserved is used, please report (%s)\n", |
| 1242 | debugstr_w(startup_info->lpReserved)); |
| 1243 | |
| 1244 | ret = CreateProcessA( app_nameA, cmd_lineA, process_attr, thread_attr, |
| 1245 | inherit, flags, env, cur_dirA, &StartupInfoA, info ); |
| 1246 | |
| 1247 | HeapFree( GetProcessHeap(), 0, cur_dirA ); |
| 1248 | HeapFree( GetProcessHeap(), 0, cmd_lineA ); |
| 1249 | HeapFree( GetProcessHeap(), 0, StartupInfoA.lpDesktop ); |
| 1250 | HeapFree( GetProcessHeap(), 0, StartupInfoA.lpTitle ); |
| 1251 | |
| 1252 | return ret; |
| 1253 | } |
| 1254 | |
| 1255 | |
Alexandre Julliard | 5b4f3e8 | 2000-05-01 16:24:22 +0000 | [diff] [blame] | 1256 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1257 | * ExitProcess (KERNEL32.@) |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 1258 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1259 | void WINAPI ExitProcess( DWORD status ) |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 1260 | { |
Alexandre Julliard | 12f29b5 | 2000-03-17 15:16:57 +0000 | [diff] [blame] | 1261 | MODULE_DllProcessDetach( TRUE, (LPVOID)1 ); |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 1262 | SERVER_START_REQ( terminate_process ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1263 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1264 | /* send the exit code to the server */ |
| 1265 | req->handle = GetCurrentProcess(); |
| 1266 | req->exit_code = status; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1267 | wine_server_call( req ); |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1268 | } |
| 1269 | SERVER_END_REQ; |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 1270 | exit( status ); |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 1271 | } |
| 1272 | |
Ulrich Weigand | c319c66 | 1999-05-22 16:18:36 +0000 | [diff] [blame] | 1273 | /*********************************************************************** |
Patrik Stridvall | 15a3b74 | 2001-04-27 18:03:51 +0000 | [diff] [blame] | 1274 | * ExitProcess (KERNEL.466) |
Ulrich Weigand | c319c66 | 1999-05-22 16:18:36 +0000 | [diff] [blame] | 1275 | */ |
| 1276 | void WINAPI ExitProcess16( WORD status ) |
| 1277 | { |
Alexandre Julliard | ab68797 | 2000-11-15 23:41:46 +0000 | [diff] [blame] | 1278 | DWORD count; |
| 1279 | ReleaseThunkLock( &count ); |
Ulrich Weigand | c319c66 | 1999-05-22 16:18:36 +0000 | [diff] [blame] | 1280 | ExitProcess( status ); |
| 1281 | } |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 1282 | |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 1283 | /****************************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 1284 | * TerminateProcess (KERNEL32.@) |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 1285 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1286 | BOOL WINAPI TerminateProcess( HANDLE handle, DWORD exit_code ) |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 1287 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1288 | NTSTATUS status = NtTerminateProcess( handle, exit_code ); |
| 1289 | if (status) SetLastError( RtlNtStatusToDosError(status) ); |
| 1290 | return !status; |
Alexandre Julliard | 85ed45e | 1998-08-22 19:03:56 +0000 | [diff] [blame] | 1291 | } |
| 1292 | |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1293 | |
| 1294 | /*********************************************************************** |
Patrik Stridvall | 15a3b74 | 2001-04-27 18:03:51 +0000 | [diff] [blame] | 1295 | * GetProcessDword (KERNEL.485) |
| 1296 | * GetProcessDword (KERNEL32.18) |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1297 | * 'Of course you cannot directly access Windows internal structures' |
| 1298 | */ |
| 1299 | DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset ) |
| 1300 | { |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1301 | DWORD x, y; |
| 1302 | |
Alexandre Julliard | e8c6a08 | 1999-05-02 14:33:41 +0000 | [diff] [blame] | 1303 | TRACE_(win32)("(%ld, %d)\n", dwProcessID, offset ); |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1304 | |
| 1305 | if (dwProcessID && dwProcessID != GetCurrentProcessId()) |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 1306 | { |
| 1307 | ERR("%d: process %lx not accessible\n", offset, dwProcessID); |
| 1308 | return 0; |
| 1309 | } |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1310 | |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 1311 | switch ( offset ) |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1312 | { |
| 1313 | case GPD_APP_COMPAT_FLAGS: |
Alexandre Julliard | 7d5bc5c | 2001-01-15 20:09:09 +0000 | [diff] [blame] | 1314 | return GetAppCompatFlags16(0); |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1315 | |
| 1316 | case GPD_LOAD_DONE_EVENT: |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1317 | return current_process.load_done_evt; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1318 | |
| 1319 | case GPD_HINSTANCE16: |
Alexandre Julliard | 7d5bc5c | 2001-01-15 20:09:09 +0000 | [diff] [blame] | 1320 | return GetTaskDS16(); |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1321 | |
| 1322 | case GPD_WINDOWS_VERSION: |
Alexandre Julliard | 7d5bc5c | 2001-01-15 20:09:09 +0000 | [diff] [blame] | 1323 | return GetExeVersion16(); |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1324 | |
| 1325 | case GPD_THDB: |
Alexandre Julliard | 0a860a0 | 1999-06-22 11:43:42 +0000 | [diff] [blame] | 1326 | return (DWORD)NtCurrentTeb() - 0x10 /* FIXME */; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1327 | |
| 1328 | case GPD_PDB: |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1329 | return (DWORD)¤t_process; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1330 | |
| 1331 | case GPD_STARTF_SHELLDATA: /* return stdoutput handle from startupinfo ??? */ |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1332 | return current_startupinfo.hStdOutput; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1333 | |
| 1334 | case GPD_STARTF_HOTKEY: /* return stdinput handle from startupinfo ??? */ |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1335 | return current_startupinfo.hStdInput; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1336 | |
| 1337 | case GPD_STARTF_SHOWWINDOW: |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1338 | return current_startupinfo.wShowWindow; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1339 | |
| 1340 | case GPD_STARTF_SIZE: |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1341 | x = current_startupinfo.dwXSize; |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 1342 | if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16; |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1343 | y = current_startupinfo.dwYSize; |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 1344 | if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1345 | return MAKELONG( x, y ); |
| 1346 | |
| 1347 | case GPD_STARTF_POSITION: |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1348 | x = current_startupinfo.dwX; |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 1349 | if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16; |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1350 | y = current_startupinfo.dwY; |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 1351 | if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1352 | return MAKELONG( x, y ); |
| 1353 | |
| 1354 | case GPD_STARTF_FLAGS: |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1355 | return current_startupinfo.dwFlags; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1356 | |
Ulrich Weigand | 2e65876 | 1999-04-11 12:06:04 +0000 | [diff] [blame] | 1357 | case GPD_PARENT: |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 1358 | return 0; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1359 | |
| 1360 | case GPD_FLAGS: |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1361 | return current_process.flags; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1362 | |
| 1363 | case GPD_USERDATA: |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1364 | return current_process.process_dword; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1365 | |
| 1366 | default: |
Alexandre Julliard | e8c6a08 | 1999-05-02 14:33:41 +0000 | [diff] [blame] | 1367 | ERR_(win32)("Unknown offset %d\n", offset ); |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1368 | return 0; |
| 1369 | } |
| 1370 | } |
| 1371 | |
| 1372 | /*********************************************************************** |
| 1373 | * SetProcessDword (KERNEL.484) |
| 1374 | * 'Of course you cannot directly access Windows internal structures' |
| 1375 | */ |
| 1376 | void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value ) |
| 1377 | { |
Alexandre Julliard | e8c6a08 | 1999-05-02 14:33:41 +0000 | [diff] [blame] | 1378 | TRACE_(win32)("(%ld, %d)\n", dwProcessID, offset ); |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1379 | |
| 1380 | if (dwProcessID && dwProcessID != GetCurrentProcessId()) |
Alexandre Julliard | c192ba2 | 2000-05-29 21:25:10 +0000 | [diff] [blame] | 1381 | { |
| 1382 | ERR("%d: process %lx not accessible\n", offset, dwProcessID); |
| 1383 | return; |
| 1384 | } |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1385 | |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 1386 | switch ( offset ) |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1387 | { |
| 1388 | case GPD_APP_COMPAT_FLAGS: |
| 1389 | case GPD_LOAD_DONE_EVENT: |
| 1390 | case GPD_HINSTANCE16: |
| 1391 | case GPD_WINDOWS_VERSION: |
| 1392 | case GPD_THDB: |
| 1393 | case GPD_PDB: |
| 1394 | case GPD_STARTF_SHELLDATA: |
| 1395 | case GPD_STARTF_HOTKEY: |
| 1396 | case GPD_STARTF_SHOWWINDOW: |
| 1397 | case GPD_STARTF_SIZE: |
| 1398 | case GPD_STARTF_POSITION: |
| 1399 | case GPD_STARTF_FLAGS: |
Ulrich Weigand | 2e65876 | 1999-04-11 12:06:04 +0000 | [diff] [blame] | 1400 | case GPD_PARENT: |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1401 | case GPD_FLAGS: |
Alexandre Julliard | e8c6a08 | 1999-05-02 14:33:41 +0000 | [diff] [blame] | 1402 | ERR_(win32)("Not allowed to modify offset %d\n", offset ); |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1403 | break; |
| 1404 | |
| 1405 | case GPD_USERDATA: |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 1406 | current_process.process_dword = value; |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1407 | break; |
| 1408 | |
| 1409 | default: |
Alexandre Julliard | e8c6a08 | 1999-05-02 14:33:41 +0000 | [diff] [blame] | 1410 | ERR_(win32)("Unknown offset %d\n", offset ); |
Ulrich Weigand | 8139c30 | 1999-04-01 11:43:05 +0000 | [diff] [blame] | 1411 | break; |
| 1412 | } |
| 1413 | } |
| 1414 | |
| 1415 | |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 1416 | /********************************************************************* |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 1417 | * OpenProcess (KERNEL32.@) |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 1418 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1419 | HANDLE WINAPI OpenProcess( DWORD access, BOOL inherit, DWORD id ) |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 1420 | { |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1421 | HANDLE ret = 0; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 1422 | SERVER_START_REQ( open_process ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1423 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1424 | req->pid = (void *)id; |
| 1425 | req->access = access; |
| 1426 | req->inherit = inherit; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1427 | if (!wine_server_call_err( req )) ret = reply->handle; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1428 | } |
| 1429 | SERVER_END_REQ; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1430 | return ret; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1431 | } |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 1432 | |
Ulrich Weigand | c319c66 | 1999-05-22 16:18:36 +0000 | [diff] [blame] | 1433 | /********************************************************************* |
| 1434 | * MapProcessHandle (KERNEL.483) |
| 1435 | */ |
| 1436 | DWORD WINAPI MapProcessHandle( HANDLE handle ) |
| 1437 | { |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1438 | DWORD ret = 0; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 1439 | SERVER_START_REQ( get_process_info ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1440 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1441 | req->handle = handle; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1442 | if (!wine_server_call_err( req )) ret = (DWORD)reply->pid; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1443 | } |
| 1444 | SERVER_END_REQ; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1445 | return ret; |
Ulrich Weigand | c319c66 | 1999-05-22 16:18:36 +0000 | [diff] [blame] | 1446 | } |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1447 | |
Alexandre Julliard | 9ea19e5 | 1997-01-01 17:29:55 +0000 | [diff] [blame] | 1448 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1449 | * SetPriorityClass (KERNEL32.@) |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 1450 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1451 | BOOL WINAPI SetPriorityClass( HANDLE hprocess, DWORD priorityclass ) |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 1452 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1453 | BOOL ret; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 1454 | SERVER_START_REQ( set_process_info ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1455 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1456 | req->handle = hprocess; |
| 1457 | req->priority = priorityclass; |
| 1458 | req->mask = SET_PROCESS_INFO_PRIORITY; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1459 | ret = !wine_server_call_err( req ); |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1460 | } |
| 1461 | SERVER_END_REQ; |
| 1462 | return ret; |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 1463 | } |
| 1464 | |
| 1465 | |
| 1466 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1467 | * GetPriorityClass (KERNEL32.@) |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 1468 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1469 | DWORD WINAPI GetPriorityClass(HANDLE hprocess) |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 1470 | { |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1471 | DWORD ret = 0; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 1472 | SERVER_START_REQ( get_process_info ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1473 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1474 | req->handle = hprocess; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1475 | if (!wine_server_call_err( req )) ret = reply->priority; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1476 | } |
| 1477 | SERVER_END_REQ; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1478 | return ret; |
Alexandre Julliard | 62a8b43 | 1999-01-19 17:48:23 +0000 | [diff] [blame] | 1479 | } |
| 1480 | |
| 1481 | |
| 1482 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1483 | * SetProcessAffinityMask (KERNEL32.@) |
Alexandre Julliard | 62a8b43 | 1999-01-19 17:48:23 +0000 | [diff] [blame] | 1484 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1485 | BOOL WINAPI SetProcessAffinityMask( HANDLE hProcess, DWORD affmask ) |
Alexandre Julliard | 62a8b43 | 1999-01-19 17:48:23 +0000 | [diff] [blame] | 1486 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1487 | BOOL ret; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 1488 | SERVER_START_REQ( set_process_info ) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1489 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1490 | req->handle = hProcess; |
| 1491 | req->affinity = affmask; |
| 1492 | req->mask = SET_PROCESS_INFO_AFFINITY; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1493 | ret = !wine_server_call_err( req ); |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1494 | } |
| 1495 | SERVER_END_REQ; |
| 1496 | return ret; |
Alexandre Julliard | 62a8b43 | 1999-01-19 17:48:23 +0000 | [diff] [blame] | 1497 | } |
| 1498 | |
| 1499 | /********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 1500 | * GetProcessAffinityMask (KERNEL32.@) |
Alexandre Julliard | 62a8b43 | 1999-01-19 17:48:23 +0000 | [diff] [blame] | 1501 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1502 | BOOL WINAPI GetProcessAffinityMask( HANDLE hProcess, |
Alexandre Julliard | 62a8b43 | 1999-01-19 17:48:23 +0000 | [diff] [blame] | 1503 | LPDWORD lpProcessAffinityMask, |
| 1504 | LPDWORD lpSystemAffinityMask ) |
| 1505 | { |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1506 | BOOL ret = FALSE; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 1507 | SERVER_START_REQ( get_process_info ) |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1508 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1509 | req->handle = hProcess; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1510 | if (!wine_server_call_err( req )) |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1511 | { |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1512 | if (lpProcessAffinityMask) *lpProcessAffinityMask = reply->process_affinity; |
| 1513 | if (lpSystemAffinityMask) *lpSystemAffinityMask = reply->system_affinity; |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1514 | ret = TRUE; |
| 1515 | } |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1516 | } |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1517 | SERVER_END_REQ; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1518 | return ret; |
Alexandre Julliard | c6c0944 | 1997-01-12 18:32:19 +0000 | [diff] [blame] | 1519 | } |
| 1520 | |
| 1521 | |
| 1522 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1523 | * GetProcessVersion (KERNEL32.@) |
Alexandre Julliard | 23946ad | 1997-06-16 17:43:53 +0000 | [diff] [blame] | 1524 | */ |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1525 | DWORD WINAPI GetProcessVersion( DWORD processid ) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1526 | { |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1527 | IMAGE_NT_HEADERS *nt; |
Alexandre Julliard | 23946ad | 1997-06-16 17:43:53 +0000 | [diff] [blame] | 1528 | |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1529 | if (processid && processid != GetCurrentProcessId()) |
Andreas Mohr | a6d83eb | 2000-12-27 04:02:46 +0000 | [diff] [blame] | 1530 | { |
| 1531 | FIXME("should use ReadProcessMemory\n"); |
| 1532 | return 0; |
| 1533 | } |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1534 | if ((nt = RtlImageNtHeader( current_process.module ))) |
| 1535 | return ((nt->OptionalHeader.MajorSubsystemVersion << 16) | |
| 1536 | nt->OptionalHeader.MinorSubsystemVersion); |
| 1537 | return 0; |
Alexandre Julliard | 23946ad | 1997-06-16 17:43:53 +0000 | [diff] [blame] | 1538 | } |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1539 | |
| 1540 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1541 | * GetProcessFlags (KERNEL32.@) |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 1542 | */ |
Alexandre Julliard | 0623a6f | 1998-01-18 18:01:49 +0000 | [diff] [blame] | 1543 | DWORD WINAPI GetProcessFlags( DWORD processid ) |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 1544 | { |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1545 | if (processid && processid != GetCurrentProcessId()) return 0; |
| 1546 | return current_process.flags; |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 1547 | } |
| 1548 | |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1549 | |
Alexandre Julliard | e658d82 | 1997-11-30 17:45:40 +0000 | [diff] [blame] | 1550 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 1551 | * SetProcessWorkingSetSize [KERNEL32.@] |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 1552 | * Sets the min/max working set sizes for a specified process. |
| 1553 | * |
| 1554 | * PARAMS |
| 1555 | * hProcess [I] Handle to the process of interest |
| 1556 | * minset [I] Specifies minimum working set size |
| 1557 | * maxset [I] Specifies maximum working set size |
| 1558 | * |
| 1559 | * RETURNS STD |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1560 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1561 | BOOL WINAPI SetProcessWorkingSetSize(HANDLE hProcess,DWORD minset, |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1562 | DWORD maxset) |
| 1563 | { |
Dimitrie O. Paun | dd03cc1 | 1999-12-08 03:56:23 +0000 | [diff] [blame] | 1564 | FIXME("(0x%08x,%ld,%ld): stub - harmless\n",hProcess,minset,maxset); |
Alexandre Julliard | 908464d | 2000-11-01 03:11:12 +0000 | [diff] [blame] | 1565 | if(( minset == (DWORD)-1) && (maxset == (DWORD)-1)) { |
Alexandre Julliard | d30dfd2 | 1998-09-27 18:28:36 +0000 | [diff] [blame] | 1566 | /* Trim the working set to zero */ |
| 1567 | /* Swap the process out of physical RAM */ |
| 1568 | } |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 1569 | return TRUE; |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1570 | } |
| 1571 | |
| 1572 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1573 | * GetProcessWorkingSetSize (KERNEL32.@) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1574 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1575 | BOOL WINAPI GetProcessWorkingSetSize(HANDLE hProcess,LPDWORD minset, |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1576 | LPDWORD maxset) |
| 1577 | { |
Dimitrie O. Paun | dd03cc1 | 1999-12-08 03:56:23 +0000 | [diff] [blame] | 1578 | FIXME("(0x%08x,%p,%p): stub\n",hProcess,minset,maxset); |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1579 | /* 32 MB working set size */ |
| 1580 | if (minset) *minset = 32*1024*1024; |
| 1581 | if (maxset) *maxset = 32*1024*1024; |
| 1582 | return TRUE; |
| 1583 | } |
| 1584 | |
| 1585 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1586 | * SetProcessShutdownParameters (KERNEL32.@) |
James Sutherland | 577db37 | 1998-11-08 15:09:08 +0000 | [diff] [blame] | 1587 | * |
| 1588 | * CHANGED - James Sutherland (JamesSutherland@gmx.de) |
| 1589 | * Now tracks changes made (but does not act on these changes) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1590 | */ |
Andreas Mohr | d398aac | 2000-08-21 20:17:56 +0000 | [diff] [blame] | 1591 | static DWORD shutdown_flags = 0; |
| 1592 | static DWORD shutdown_priority = 0x280; |
| 1593 | |
| 1594 | BOOL WINAPI SetProcessShutdownParameters(DWORD level, DWORD flags) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1595 | { |
Andreas Mohr | d398aac | 2000-08-21 20:17:56 +0000 | [diff] [blame] | 1596 | FIXME("(%08lx, %08lx): partial stub.\n", level, flags); |
| 1597 | shutdown_flags = flags; |
| 1598 | shutdown_priority = level; |
Alexandre Julliard | a845b88 | 1998-06-01 10:44:35 +0000 | [diff] [blame] | 1599 | return TRUE; |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1600 | } |
| 1601 | |
James Sutherland | 577db37 | 1998-11-08 15:09:08 +0000 | [diff] [blame] | 1602 | |
| 1603 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1604 | * GetProcessShutdownParameters (KERNEL32.@) |
James Sutherland | 577db37 | 1998-11-08 15:09:08 +0000 | [diff] [blame] | 1605 | * |
| 1606 | */ |
Andreas Mohr | d398aac | 2000-08-21 20:17:56 +0000 | [diff] [blame] | 1607 | BOOL WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel, LPDWORD lpdwFlags ) |
James Sutherland | 577db37 | 1998-11-08 15:09:08 +0000 | [diff] [blame] | 1608 | { |
Andreas Mohr | d398aac | 2000-08-21 20:17:56 +0000 | [diff] [blame] | 1609 | *lpdwLevel = shutdown_priority; |
| 1610 | *lpdwFlags = shutdown_flags; |
| 1611 | return TRUE; |
James Sutherland | 577db37 | 1998-11-08 15:09:08 +0000 | [diff] [blame] | 1612 | } |
Andreas Mohr | d398aac | 2000-08-21 20:17:56 +0000 | [diff] [blame] | 1613 | |
| 1614 | |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1615 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1616 | * SetProcessPriorityBoost (KERNEL32.@) |
Marcus Meissner | 05e2d3b | 1998-10-24 11:18:59 +0000 | [diff] [blame] | 1617 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1618 | BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost) |
Marcus Meissner | 05e2d3b | 1998-10-24 11:18:59 +0000 | [diff] [blame] | 1619 | { |
Dimitrie O. Paun | dd03cc1 | 1999-12-08 03:56:23 +0000 | [diff] [blame] | 1620 | FIXME("(%d,%d): stub\n",hprocess,disableboost); |
Marcus Meissner | 05e2d3b | 1998-10-24 11:18:59 +0000 | [diff] [blame] | 1621 | /* Say we can do it. I doubt the program will notice that we don't. */ |
| 1622 | return TRUE; |
| 1623 | } |
| 1624 | |
Alexandre Julliard | 8b8828f | 1999-11-12 21:39:14 +0000 | [diff] [blame] | 1625 | |
Marcus Meissner | 05e2d3b | 1998-10-24 11:18:59 +0000 | [diff] [blame] | 1626 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1627 | * ReadProcessMemory (KERNEL32.@) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1628 | */ |
Alexandre Julliard | 8b8828f | 1999-11-12 21:39:14 +0000 | [diff] [blame] | 1629 | BOOL WINAPI ReadProcessMemory( HANDLE process, LPCVOID addr, LPVOID buffer, DWORD size, |
| 1630 | LPDWORD bytes_read ) |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1631 | { |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1632 | DWORD res; |
Alexandre Julliard | 8b8828f | 1999-11-12 21:39:14 +0000 | [diff] [blame] | 1633 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1634 | SERVER_START_REQ( read_process_memory ) |
Alexandre Julliard | 8b8828f | 1999-11-12 21:39:14 +0000 | [diff] [blame] | 1635 | { |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1636 | req->handle = process; |
| 1637 | req->addr = (void *)addr; |
| 1638 | wine_server_set_reply( req, buffer, size ); |
| 1639 | if ((res = wine_server_call_err( req ))) size = 0; |
Alexandre Julliard | 8b8828f | 1999-11-12 21:39:14 +0000 | [diff] [blame] | 1640 | } |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1641 | SERVER_END_REQ; |
| 1642 | if (bytes_read) *bytes_read = size; |
| 1643 | return !res; |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1644 | } |
| 1645 | |
Alexandre Julliard | 8b8828f | 1999-11-12 21:39:14 +0000 | [diff] [blame] | 1646 | |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 1647 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1648 | * WriteProcessMemory (KERNEL32.@) |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 1649 | */ |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1650 | BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPCVOID buffer, DWORD size, |
Alexandre Julliard | eef7025 | 1999-11-13 19:54:54 +0000 | [diff] [blame] | 1651 | LPDWORD bytes_written ) |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 1652 | { |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1653 | static const int zero; |
| 1654 | unsigned int first_offset, last_offset, first_mask, last_mask; |
| 1655 | DWORD res; |
Alexandre Julliard | eef7025 | 1999-11-13 19:54:54 +0000 | [diff] [blame] | 1656 | |
| 1657 | if (!size) |
| 1658 | { |
| 1659 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 1660 | return FALSE; |
| 1661 | } |
Alexandre Julliard | eef7025 | 1999-11-13 19:54:54 +0000 | [diff] [blame] | 1662 | |
| 1663 | /* compute the mask for the first int */ |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1664 | first_mask = ~0; |
Alexandre Julliard | eef7025 | 1999-11-13 19:54:54 +0000 | [diff] [blame] | 1665 | first_offset = (unsigned int)addr % sizeof(int); |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1666 | memset( &first_mask, 0, first_offset ); |
Alexandre Julliard | eef7025 | 1999-11-13 19:54:54 +0000 | [diff] [blame] | 1667 | |
| 1668 | /* compute the mask for the last int */ |
| 1669 | last_offset = (size + first_offset) % sizeof(int); |
| 1670 | last_mask = 0; |
| 1671 | memset( &last_mask, 0xff, last_offset ? last_offset : sizeof(int) ); |
| 1672 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1673 | SERVER_START_REQ( write_process_memory ) |
Alexandre Julliard | eef7025 | 1999-11-13 19:54:54 +0000 | [diff] [blame] | 1674 | { |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1675 | req->handle = process; |
| 1676 | req->addr = (char *)addr - first_offset; |
| 1677 | req->first_mask = first_mask; |
| 1678 | req->last_mask = last_mask; |
| 1679 | if (first_offset) wine_server_add_data( req, &zero, first_offset ); |
| 1680 | wine_server_add_data( req, buffer, size ); |
| 1681 | if (last_offset) wine_server_add_data( req, &zero, sizeof(int) - last_offset ); |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1682 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1683 | if ((res = wine_server_call_err( req ))) size = 0; |
Alexandre Julliard | eef7025 | 1999-11-13 19:54:54 +0000 | [diff] [blame] | 1684 | } |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1685 | SERVER_END_REQ; |
| 1686 | if (bytes_written) *bytes_written = size; |
| 1687 | { |
| 1688 | char dummy[32]; |
| 1689 | DWORD read; |
| 1690 | ReadProcessMemory( process, addr, dummy, sizeof(dummy), &read ); |
| 1691 | } |
| 1692 | return !res; |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 1693 | } |
| 1694 | |
Alexandre Julliard | eef7025 | 1999-11-13 19:54:54 +0000 | [diff] [blame] | 1695 | |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 1696 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1697 | * RegisterServiceProcess (KERNEL.491) |
| 1698 | * RegisterServiceProcess (KERNEL32.@) |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1699 | * |
| 1700 | * A service process calls this function to ensure that it continues to run |
| 1701 | * even after a user logged off. |
| 1702 | */ |
Alexandre Julliard | a0d7731 | 1998-09-13 16:32:00 +0000 | [diff] [blame] | 1703 | DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType) |
Alexandre Julliard | 02e9008 | 1998-01-04 17:49:09 +0000 | [diff] [blame] | 1704 | { |
| 1705 | /* I don't think that Wine needs to do anything in that function */ |
| 1706 | return 1; /* success */ |
| 1707 | } |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 1708 | |
| 1709 | /*********************************************************************** |
Patrik Stridvall | dae8de6 | 2001-06-13 20:13:18 +0000 | [diff] [blame] | 1710 | * GetExitCodeProcess [KERNEL32.@] |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 1711 | * |
| 1712 | * Gets termination status of specified process |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 1713 | * |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 1714 | * RETURNS |
| 1715 | * Success: TRUE |
| 1716 | * Failure: FALSE |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 1717 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 1718 | BOOL WINAPI GetExitCodeProcess( |
Patrik Stridvall | 2b3aa61 | 2000-12-01 23:58:28 +0000 | [diff] [blame] | 1719 | HANDLE hProcess, /* [in] handle to the process */ |
| 1720 | LPDWORD lpExitCode) /* [out] address to receive termination status */ |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 1721 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1722 | BOOL ret; |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 1723 | SERVER_START_REQ( get_process_info ) |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1724 | { |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1725 | req->handle = hProcess; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1726 | ret = !wine_server_call_err( req ); |
| 1727 | if (ret && lpExitCode) *lpExitCode = reply->exit_code; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1728 | } |
Alexandre Julliard | 9c2370b | 2000-08-30 00:00:48 +0000 | [diff] [blame] | 1729 | SERVER_END_REQ; |
Alexandre Julliard | ebe29ef | 1999-06-26 08:43:26 +0000 | [diff] [blame] | 1730 | return ret; |
Alexandre Julliard | 46ea8b3 | 1998-05-03 19:01:20 +0000 | [diff] [blame] | 1731 | } |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 1732 | |
Alexandre Julliard | 62a8b43 | 1999-01-19 17:48:23 +0000 | [diff] [blame] | 1733 | |
Alexandre Julliard | f90efa9 | 1998-06-14 15:24:15 +0000 | [diff] [blame] | 1734 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1735 | * SetErrorMode (KERNEL32.@) |
Alexandre Julliard | 0a860a0 | 1999-06-22 11:43:42 +0000 | [diff] [blame] | 1736 | */ |
| 1737 | UINT WINAPI SetErrorMode( UINT mode ) |
| 1738 | { |
Alexandre Julliard | 52900c8 | 2000-08-09 22:33:42 +0000 | [diff] [blame] | 1739 | UINT old = current_process.error_mode; |
| 1740 | current_process.error_mode = mode; |
Alexandre Julliard | 0a860a0 | 1999-06-22 11:43:42 +0000 | [diff] [blame] | 1741 | return old; |
| 1742 | } |
Alexandre Julliard | 114830e | 2000-04-11 20:01:59 +0000 | [diff] [blame] | 1743 | |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 1744 | |
Dmitry Timoshkov | 9ec9c2b | 2001-03-05 20:10:43 +0000 | [diff] [blame] | 1745 | /************************************************************************** |
| 1746 | * SetFileApisToOEM (KERNEL32.@) |
| 1747 | */ |
| 1748 | VOID WINAPI SetFileApisToOEM(void) |
| 1749 | { |
| 1750 | current_process.flags |= PDB32_FILE_APIS_OEM; |
| 1751 | } |
| 1752 | |
| 1753 | |
| 1754 | /************************************************************************** |
| 1755 | * SetFileApisToANSI (KERNEL32.@) |
| 1756 | */ |
| 1757 | VOID WINAPI SetFileApisToANSI(void) |
| 1758 | { |
| 1759 | current_process.flags &= ~PDB32_FILE_APIS_OEM; |
| 1760 | } |
| 1761 | |
| 1762 | |
| 1763 | /****************************************************************************** |
| 1764 | * AreFileApisANSI [KERNEL32.@] Determines if file functions are using ANSI |
| 1765 | * |
| 1766 | * RETURNS |
| 1767 | * TRUE: Set of file functions is using ANSI code page |
| 1768 | * FALSE: Set of file functions is using OEM code page |
| 1769 | */ |
| 1770 | BOOL WINAPI AreFileApisANSI(void) |
| 1771 | { |
| 1772 | return !(current_process.flags & PDB32_FILE_APIS_OEM); |
| 1773 | } |
| 1774 | |
| 1775 | |
Alexandre Julliard | 55e845d | 2002-05-23 19:40:18 +0000 | [diff] [blame] | 1776 | /*********************************************************************** |
| 1777 | * GetTickCount (USER.13) |
| 1778 | * GetCurrentTime (USER.15) |
| 1779 | * GetTickCount (KERNEL32.@) |
| 1780 | * GetSystemMSecCount (SYSTEM.6) |
| 1781 | * |
| 1782 | * Returns the number of milliseconds, modulo 2^32, since the start |
| 1783 | * of the wineserver. |
| 1784 | */ |
| 1785 | DWORD WINAPI GetTickCount(void) |
| 1786 | { |
| 1787 | struct timeval t; |
| 1788 | gettimeofday( &t, NULL ); |
| 1789 | return ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - server_startticks; |
| 1790 | } |
| 1791 | |
| 1792 | |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 1793 | /********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1794 | * TlsAlloc [KERNEL32.@] Allocates a TLS index. |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 1795 | * |
| 1796 | * Allocates a thread local storage index |
| 1797 | * |
| 1798 | * RETURNS |
| 1799 | * Success: TLS Index |
| 1800 | * Failure: 0xFFFFFFFF |
| 1801 | */ |
| 1802 | DWORD WINAPI TlsAlloc( void ) |
| 1803 | { |
| 1804 | DWORD i, mask, ret = 0; |
| 1805 | DWORD *bits = current_process.tls_bits; |
| 1806 | RtlAcquirePebLock(); |
| 1807 | if (*bits == 0xffffffff) |
| 1808 | { |
| 1809 | bits++; |
| 1810 | ret = 32; |
| 1811 | if (*bits == 0xffffffff) |
| 1812 | { |
| 1813 | RtlReleasePebLock(); |
| 1814 | SetLastError( ERROR_NO_MORE_ITEMS ); |
| 1815 | return 0xffffffff; |
| 1816 | } |
| 1817 | } |
| 1818 | for (i = 0, mask = 1; i < 32; i++, mask <<= 1) if (!(*bits & mask)) break; |
| 1819 | *bits |= mask; |
| 1820 | RtlReleasePebLock(); |
Aric Stewart | d5a2698 | 2001-10-03 18:40:10 +0000 | [diff] [blame] | 1821 | NtCurrentTeb()->tls_array[ret+i] = 0; /* clear the value */ |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 1822 | return ret + i; |
| 1823 | } |
| 1824 | |
| 1825 | |
| 1826 | /********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1827 | * TlsFree [KERNEL32.@] Releases a TLS index. |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 1828 | * |
| 1829 | * Releases a thread local storage index, making it available for reuse |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 1830 | * |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 1831 | * RETURNS |
| 1832 | * Success: TRUE |
| 1833 | * Failure: FALSE |
| 1834 | */ |
| 1835 | BOOL WINAPI TlsFree( |
| 1836 | DWORD index) /* [in] TLS Index to free */ |
| 1837 | { |
| 1838 | DWORD mask = (1 << (index & 31)); |
| 1839 | DWORD *bits = current_process.tls_bits; |
| 1840 | if (index >= 64) |
| 1841 | { |
| 1842 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 1843 | return FALSE; |
| 1844 | } |
| 1845 | if (index >= 32) bits++; |
| 1846 | RtlAcquirePebLock(); |
| 1847 | if (!(*bits & mask)) /* already free? */ |
| 1848 | { |
| 1849 | RtlReleasePebLock(); |
| 1850 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 1851 | return FALSE; |
| 1852 | } |
| 1853 | *bits &= ~mask; |
| 1854 | NtCurrentTeb()->tls_array[index] = 0; |
| 1855 | /* FIXME: should zero all other thread values */ |
| 1856 | RtlReleasePebLock(); |
| 1857 | return TRUE; |
| 1858 | } |
| 1859 | |
| 1860 | |
| 1861 | /********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1862 | * TlsGetValue [KERNEL32.@] Gets value in a thread's TLS slot |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 1863 | * |
| 1864 | * RETURNS |
| 1865 | * Success: Value stored in calling thread's TLS slot for index |
| 1866 | * Failure: 0 and GetLastError returns NO_ERROR |
| 1867 | */ |
| 1868 | LPVOID WINAPI TlsGetValue( |
| 1869 | DWORD index) /* [in] TLS index to retrieve value for */ |
| 1870 | { |
| 1871 | if (index >= 64) |
| 1872 | { |
| 1873 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 1874 | return NULL; |
| 1875 | } |
| 1876 | SetLastError( ERROR_SUCCESS ); |
| 1877 | return NtCurrentTeb()->tls_array[index]; |
| 1878 | } |
| 1879 | |
| 1880 | |
| 1881 | /********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1882 | * TlsSetValue [KERNEL32.@] Stores a value in the thread's TLS slot. |
Alexandre Julliard | becb9a3 | 2000-12-11 03:48:15 +0000 | [diff] [blame] | 1883 | * |
| 1884 | * RETURNS |
| 1885 | * Success: TRUE |
| 1886 | * Failure: FALSE |
| 1887 | */ |
| 1888 | BOOL WINAPI TlsSetValue( |
| 1889 | DWORD index, /* [in] TLS index to set value for */ |
| 1890 | LPVOID value) /* [in] Value to be stored */ |
| 1891 | { |
| 1892 | if (index >= 64) |
| 1893 | { |
| 1894 | SetLastError( ERROR_INVALID_PARAMETER ); |
| 1895 | return FALSE; |
| 1896 | } |
| 1897 | NtCurrentTeb()->tls_array[index] = value; |
| 1898 | return TRUE; |
| 1899 | } |
| 1900 | |
| 1901 | |
Alexandre Julliard | 114830e | 2000-04-11 20:01:59 +0000 | [diff] [blame] | 1902 | /*********************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1903 | * GetCurrentProcess (KERNEL32.@) |
Alexandre Julliard | 114830e | 2000-04-11 20:01:59 +0000 | [diff] [blame] | 1904 | */ |
| 1905 | #undef GetCurrentProcess |
| 1906 | HANDLE WINAPI GetCurrentProcess(void) |
| 1907 | { |
| 1908 | return 0xffffffff; |
| 1909 | } |