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