Add support for specific EOI PIC command.
[wine] / dlls / kernel / process.c
1 /*
2  * Win32 processes
3  *
4  * Copyright 1996, 1998 Alexandre Julliard
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
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include "wine/winbase16.h"
25 #include "wine/winuser16.h"
26 #include "thread.h"
27 #include "wine/server.h"
28 #include "wine/debug.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(process);
31
32 /* Process flags */
33 #define PDB32_DEBUGGED      0x0001  /* Process is being debugged */
34 #define PDB32_WIN16_PROC    0x0008  /* Win16 process */
35 #define PDB32_DOS_PROC      0x0010  /* Dos process */
36 #define PDB32_CONSOLE_PROC  0x0020  /* Console process */
37 #define PDB32_FILE_APIS_OEM 0x0040  /* File APIs are OEM */
38 #define PDB32_WIN32S_PROC   0x8000  /* Win32s process */
39
40
41 static DWORD shutdown_flags = 0;
42 static DWORD shutdown_priority = 0x280;
43 static DWORD process_dword;
44 static BOOL oem_file_apis;
45
46
47 /***********************************************************************
48  *           GetProcessFlags    (KERNEL32.@)
49  */
50 DWORD WINAPI GetProcessFlags( DWORD processid )
51 {
52     IMAGE_NT_HEADERS *nt;
53     DWORD flags = 0;
54
55     if (processid && processid != GetCurrentProcessId()) return 0;
56
57     if ((nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress )))
58     {
59         if (nt->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_CUI)
60             flags |= PDB32_CONSOLE_PROC;
61     }
62     if (!AreFileApisANSI()) flags |= PDB32_FILE_APIS_OEM;
63     if (IsDebuggerPresent()) flags |= PDB32_DEBUGGED;
64     return flags;
65 }
66
67
68 /***********************************************************************
69  *           GetProcessDword    (KERNEL.485)
70  *           GetProcessDword    (KERNEL32.18)
71  * 'Of course you cannot directly access Windows internal structures'
72  */
73 DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset )
74 {
75     DWORD               x, y;
76     STARTUPINFOW        siw;
77
78     TRACE("(%ld, %d)\n", dwProcessID, offset );
79
80     if (dwProcessID && dwProcessID != GetCurrentProcessId())
81     {
82         ERR("%d: process %lx not accessible\n", offset, dwProcessID);
83         return 0;
84     }
85
86     switch ( offset )
87     {
88     case GPD_APP_COMPAT_FLAGS:
89         return GetAppCompatFlags16(0);
90     case GPD_LOAD_DONE_EVENT:
91         return 0;
92     case GPD_HINSTANCE16:
93         return GetTaskDS16();
94     case GPD_WINDOWS_VERSION:
95         return GetExeVersion16();
96     case GPD_THDB:
97         return (DWORD)NtCurrentTeb() - 0x10 /* FIXME */;
98     case GPD_PDB:
99         return (DWORD)NtCurrentTeb()->Peb;
100     case GPD_STARTF_SHELLDATA: /* return stdoutput handle from startupinfo ??? */
101         GetStartupInfoW(&siw);
102         return (DWORD)siw.hStdOutput;
103     case GPD_STARTF_HOTKEY: /* return stdinput handle from startupinfo ??? */
104         GetStartupInfoW(&siw);
105         return (DWORD)siw.hStdInput;
106     case GPD_STARTF_SHOWWINDOW:
107         GetStartupInfoW(&siw);
108         return siw.wShowWindow;
109     case GPD_STARTF_SIZE:
110         GetStartupInfoW(&siw);
111         x = siw.dwXSize;
112         if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
113         y = siw.dwYSize;
114         if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
115         return MAKELONG( x, y );
116     case GPD_STARTF_POSITION:
117         GetStartupInfoW(&siw);
118         x = siw.dwX;
119         if ( (INT)x == CW_USEDEFAULT ) x = CW_USEDEFAULT16;
120         y = siw.dwY;
121         if ( (INT)y == CW_USEDEFAULT ) y = CW_USEDEFAULT16;
122         return MAKELONG( x, y );
123     case GPD_STARTF_FLAGS:
124         GetStartupInfoW(&siw);
125         return siw.dwFlags;
126     case GPD_PARENT:
127         return 0;
128     case GPD_FLAGS:
129         return GetProcessFlags(0);
130     case GPD_USERDATA:
131         return process_dword;
132     default:
133         ERR("Unknown offset %d\n", offset );
134         return 0;
135     }
136 }
137
138 /***********************************************************************
139  *           SetProcessDword    (KERNEL.484)
140  * 'Of course you cannot directly access Windows internal structures'
141  */
142 void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value )
143 {
144     TRACE("(%ld, %d)\n", dwProcessID, offset );
145
146     if (dwProcessID && dwProcessID != GetCurrentProcessId())
147     {
148         ERR("%d: process %lx not accessible\n", offset, dwProcessID);
149         return;
150     }
151
152     switch ( offset )
153     {
154     case GPD_APP_COMPAT_FLAGS:
155     case GPD_LOAD_DONE_EVENT:
156     case GPD_HINSTANCE16:
157     case GPD_WINDOWS_VERSION:
158     case GPD_THDB:
159     case GPD_PDB:
160     case GPD_STARTF_SHELLDATA:
161     case GPD_STARTF_HOTKEY:
162     case GPD_STARTF_SHOWWINDOW:
163     case GPD_STARTF_SIZE:
164     case GPD_STARTF_POSITION:
165     case GPD_STARTF_FLAGS:
166     case GPD_PARENT:
167     case GPD_FLAGS:
168         ERR("Not allowed to modify offset %d\n", offset );
169         break;
170     case GPD_USERDATA:
171         process_dword = value;
172         break;
173     default:
174         ERR("Unknown offset %d\n", offset );
175         break;
176     }
177 }
178
179
180 /***********************************************************************
181  *           ExitProcess   (KERNEL.466)
182  */
183 void WINAPI ExitProcess16( WORD status )
184 {
185     DWORD count;
186     ReleaseThunkLock( &count );
187     ExitProcess( status );
188 }
189
190
191 /*********************************************************************
192  *           OpenProcess   (KERNEL32.@)
193  */
194 HANDLE WINAPI OpenProcess( DWORD access, BOOL inherit, DWORD id )
195 {
196     HANDLE ret = 0;
197     SERVER_START_REQ( open_process )
198     {
199         req->pid     = id;
200         req->access  = access;
201         req->inherit = inherit;
202         if (!wine_server_call_err( req )) ret = reply->handle;
203     }
204     SERVER_END_REQ;
205     return ret;
206 }
207
208
209 /*********************************************************************
210  *           MapProcessHandle   (KERNEL.483)
211  */
212 DWORD WINAPI MapProcessHandle( HANDLE handle )
213 {
214     DWORD ret = 0;
215     SERVER_START_REQ( get_process_info )
216     {
217         req->handle = handle;
218         if (!wine_server_call_err( req )) ret = reply->pid;
219     }
220     SERVER_END_REQ;
221     return ret;
222 }
223
224
225 /***********************************************************************
226  *           SetPriorityClass   (KERNEL32.@)
227  */
228 BOOL WINAPI SetPriorityClass( HANDLE hprocess, DWORD priorityclass )
229 {
230     BOOL ret;
231     SERVER_START_REQ( set_process_info )
232     {
233         req->handle   = hprocess;
234         req->priority = priorityclass;
235         req->mask     = SET_PROCESS_INFO_PRIORITY;
236         ret = !wine_server_call_err( req );
237     }
238     SERVER_END_REQ;
239     return ret;
240 }
241
242
243 /***********************************************************************
244  *           GetPriorityClass   (KERNEL32.@)
245  */
246 DWORD WINAPI GetPriorityClass(HANDLE hprocess)
247 {
248     DWORD ret = 0;
249     SERVER_START_REQ( get_process_info )
250     {
251         req->handle = hprocess;
252         if (!wine_server_call_err( req )) ret = reply->priority;
253     }
254     SERVER_END_REQ;
255     return ret;
256 }
257
258
259 /***********************************************************************
260  *          SetProcessAffinityMask   (KERNEL32.@)
261  */
262 BOOL WINAPI SetProcessAffinityMask( HANDLE hProcess, DWORD affmask )
263 {
264     BOOL ret;
265     SERVER_START_REQ( set_process_info )
266     {
267         req->handle   = hProcess;
268         req->affinity = affmask;
269         req->mask     = SET_PROCESS_INFO_AFFINITY;
270         ret = !wine_server_call_err( req );
271     }
272     SERVER_END_REQ;
273     return ret;
274 }
275
276
277 /**********************************************************************
278  *          GetProcessAffinityMask    (KERNEL32.@)
279  */
280 BOOL WINAPI GetProcessAffinityMask( HANDLE hProcess,
281                                       LPDWORD lpProcessAffinityMask,
282                                       LPDWORD lpSystemAffinityMask )
283 {
284     BOOL ret = FALSE;
285     SERVER_START_REQ( get_process_info )
286     {
287         req->handle = hProcess;
288         if (!wine_server_call_err( req ))
289         {
290             if (lpProcessAffinityMask) *lpProcessAffinityMask = reply->process_affinity;
291             if (lpSystemAffinityMask) *lpSystemAffinityMask = reply->system_affinity;
292             ret = TRUE;
293         }
294     }
295     SERVER_END_REQ;
296     return ret;
297 }
298
299
300 /***********************************************************************
301  *           GetProcessVersion    (KERNEL32.@)
302  */
303 DWORD WINAPI GetProcessVersion( DWORD processid )
304 {
305     IMAGE_NT_HEADERS *nt;
306
307     if (processid && processid != GetCurrentProcessId())
308     {
309         FIXME("should use ReadProcessMemory\n");
310         return 0;
311     }
312     if ((nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress )))
313         return ((nt->OptionalHeader.MajorSubsystemVersion << 16) |
314                 nt->OptionalHeader.MinorSubsystemVersion);
315     return 0;
316 }
317
318
319 /***********************************************************************
320  *              SetProcessWorkingSetSize        [KERNEL32.@]
321  * Sets the min/max working set sizes for a specified process.
322  *
323  * PARAMS
324  *    hProcess [I] Handle to the process of interest
325  *    minset   [I] Specifies minimum working set size
326  *    maxset   [I] Specifies maximum working set size
327  *
328  * RETURNS  STD
329  */
330 BOOL WINAPI SetProcessWorkingSetSize(HANDLE hProcess, SIZE_T minset,
331                                      SIZE_T maxset)
332 {
333     FIXME("(%p,%ld,%ld): stub - harmless\n",hProcess,minset,maxset);
334     if(( minset == (SIZE_T)-1) && (maxset == (SIZE_T)-1)) {
335         /* Trim the working set to zero */
336         /* Swap the process out of physical RAM */
337     }
338     return TRUE;
339 }
340
341 /***********************************************************************
342  *           GetProcessWorkingSetSize    (KERNEL32.@)
343  */
344 BOOL WINAPI GetProcessWorkingSetSize(HANDLE hProcess, PSIZE_T minset,
345                                      PSIZE_T maxset)
346 {
347     FIXME("(%p,%p,%p): stub\n",hProcess,minset,maxset);
348     /* 32 MB working set size */
349     if (minset) *minset = 32*1024*1024;
350     if (maxset) *maxset = 32*1024*1024;
351     return TRUE;
352 }
353
354
355 /***********************************************************************
356  *           SetProcessShutdownParameters    (KERNEL32.@)
357  */
358 BOOL WINAPI SetProcessShutdownParameters(DWORD level, DWORD flags)
359 {
360     FIXME("(%08lx, %08lx): partial stub.\n", level, flags);
361     shutdown_flags = flags;
362     shutdown_priority = level;
363     return TRUE;
364 }
365
366
367 /***********************************************************************
368  * GetProcessShutdownParameters                 (KERNEL32.@)
369  *
370  */
371 BOOL WINAPI GetProcessShutdownParameters( LPDWORD lpdwLevel, LPDWORD lpdwFlags )
372 {
373     *lpdwLevel = shutdown_priority;
374     *lpdwFlags = shutdown_flags;
375     return TRUE;
376 }
377
378
379 /***********************************************************************
380  *           GetProcessPriorityBoost    (KERNEL32.@)
381  */
382 BOOL WINAPI GetProcessPriorityBoost(HANDLE hprocess,PBOOL pDisablePriorityBoost)
383 {
384     FIXME("(%p,%p): semi-stub\n", hprocess, pDisablePriorityBoost);
385     
386     /* Report that no boost is present.. */
387     *pDisablePriorityBoost = FALSE;
388     
389     return TRUE;
390 }
391
392 /***********************************************************************
393  *           SetProcessPriorityBoost    (KERNEL32.@)
394  */
395 BOOL WINAPI SetProcessPriorityBoost(HANDLE hprocess,BOOL disableboost)
396 {
397     FIXME("(%p,%d): stub\n",hprocess,disableboost);
398     /* Say we can do it. I doubt the program will notice that we don't. */
399     return TRUE;
400 }
401
402
403 /***********************************************************************
404  *              ReadProcessMemory (KERNEL32.@)
405  */
406 BOOL WINAPI ReadProcessMemory( HANDLE process, LPCVOID addr, LPVOID buffer, SIZE_T size,
407                                SIZE_T *bytes_read )
408 {
409     NTSTATUS status = NtReadVirtualMemory( process, addr, buffer, size, bytes_read );
410     if (status) SetLastError( RtlNtStatusToDosError(status) );
411     return !status;
412 }
413
414
415 /***********************************************************************
416  *           WriteProcessMemory                 (KERNEL32.@)
417  */
418 BOOL WINAPI WriteProcessMemory( HANDLE process, LPVOID addr, LPCVOID buffer, SIZE_T size,
419                                 SIZE_T *bytes_written )
420 {
421     NTSTATUS status = NtWriteVirtualMemory( process, addr, buffer, size, bytes_written );
422     if (status) SetLastError( RtlNtStatusToDosError(status) );
423     return !status;
424 }
425
426
427 /***********************************************************************
428  *              RegisterServiceProcess (KERNEL.491)
429  *              RegisterServiceProcess (KERNEL32.@)
430  *
431  * A service process calls this function to ensure that it continues to run
432  * even after a user logged off.
433  */
434 DWORD WINAPI RegisterServiceProcess(DWORD dwProcessId, DWORD dwType)
435 {
436     /* I don't think that Wine needs to do anything in that function */
437     return 1; /* success */
438 }
439
440
441 /**************************************************************************
442  *              SetFileApisToOEM   (KERNEL32.@)
443  */
444 VOID WINAPI SetFileApisToOEM(void)
445 {
446     oem_file_apis = TRUE;
447 }
448
449
450 /**************************************************************************
451  *              SetFileApisToANSI   (KERNEL32.@)
452  */
453 VOID WINAPI SetFileApisToANSI(void)
454 {
455     oem_file_apis = FALSE;
456 }
457
458
459 /******************************************************************************
460  * AreFileApisANSI [KERNEL32.@]  Determines if file functions are using ANSI
461  *
462  * RETURNS
463  *    TRUE:  Set of file functions is using ANSI code page
464  *    FALSE: Set of file functions is using OEM code page
465  */
466 BOOL WINAPI AreFileApisANSI(void)
467 {
468     return !oem_file_apis;
469 }
470
471
472 /***********************************************************************
473  *           GetCurrentProcess   (KERNEL32.@)
474  */
475 #undef GetCurrentProcess
476 HANDLE WINAPI GetCurrentProcess(void)
477 {
478     return (HANDLE)0xffffffff;
479 }