Replace the 'if (!cond) ; else code' construct with the standard 'do {
[wine] / dlls / ntdll / process.c
1 /*
2  * NT basis DLL
3  *
4  * This file contains the Nt* API functions of NTDLL.DLL.
5  * In the original ntdll.dll they all seem to just call int 0x2e (down to the NTOSKRNL)
6  *
7  * Copyright 1996-1998 Marcus Meissner
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include "wine/debug.h"
30
31 #include "windef.h"
32 #include "winternl.h"
33 #include "ntdll_misc.h"
34 #include "wine/server.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
37
38 /*
39  *      Process object
40  */
41
42 /******************************************************************************
43  *  NtTerminateProcess                  [NTDLL.@]
44  *
45  *  Native applications must kill themselves when done
46  */
47 NTSTATUS WINAPI NtTerminateProcess( HANDLE handle, LONG exit_code )
48 {
49     NTSTATUS ret;
50     BOOL self;
51     SERVER_START_REQ( terminate_process )
52     {
53         req->handle    = handle;
54         req->exit_code = exit_code;
55         ret = wine_server_call( req );
56         self = !ret && reply->self;
57     }
58     SERVER_END_REQ;
59     if (self) exit( exit_code );
60     return ret;
61 }
62
63 /******************************************************************************
64  *  RtlGetCurrentPeb  [NTDLL.@]
65  *
66  */
67 PEB * WINAPI RtlGetCurrentPeb(void)
68 {
69     return NtCurrentTeb()->Peb;
70 }
71
72 #define UNIMPLEMENTED_INFO_CLASS(c) \
73     case c: \
74         FIXME("(process=%p) Unimplemented information class: " #c "\n", ProcessHandle); \
75         ret = STATUS_INVALID_INFO_CLASS; \
76         break
77
78 /******************************************************************************
79 *  NtQueryInformationProcess            [NTDLL.@]
80 *  ZwQueryInformationProcess            [NTDLL.@]
81 *
82 */
83 NTSTATUS WINAPI NtQueryInformationProcess(
84         IN HANDLE ProcessHandle,
85         IN PROCESSINFOCLASS ProcessInformationClass,
86         OUT PVOID ProcessInformation,
87         IN ULONG ProcessInformationLength,
88         OUT PULONG ReturnLength)
89 {
90     NTSTATUS ret = STATUS_SUCCESS;
91     ULONG len = 0;
92
93     TRACE("(%p,0x%08x,%p,0x%08lx,%p)\n",
94           ProcessHandle,ProcessInformationClass,
95           ProcessInformation,ProcessInformationLength,
96           ReturnLength);
97
98     switch (ProcessInformationClass) 
99     {
100     UNIMPLEMENTED_INFO_CLASS(ProcessQuotaLimits);
101     UNIMPLEMENTED_INFO_CLASS(ProcessBasePriority);
102     UNIMPLEMENTED_INFO_CLASS(ProcessRaisePriority);
103     UNIMPLEMENTED_INFO_CLASS(ProcessExceptionPort);
104     UNIMPLEMENTED_INFO_CLASS(ProcessAccessToken);
105     UNIMPLEMENTED_INFO_CLASS(ProcessLdtInformation);
106     UNIMPLEMENTED_INFO_CLASS(ProcessLdtSize);
107     UNIMPLEMENTED_INFO_CLASS(ProcessDefaultHardErrorMode);
108     UNIMPLEMENTED_INFO_CLASS(ProcessIoPortHandlers);
109     UNIMPLEMENTED_INFO_CLASS(ProcessPooledUsageAndLimits);
110     UNIMPLEMENTED_INFO_CLASS(ProcessWorkingSetWatch);
111     UNIMPLEMENTED_INFO_CLASS(ProcessUserModeIOPL);
112     UNIMPLEMENTED_INFO_CLASS(ProcessEnableAlignmentFaultFixup);
113     UNIMPLEMENTED_INFO_CLASS(ProcessPriorityClass);
114     UNIMPLEMENTED_INFO_CLASS(ProcessWx86Information);
115     UNIMPLEMENTED_INFO_CLASS(ProcessAffinityMask);
116     UNIMPLEMENTED_INFO_CLASS(ProcessPriorityBoost);
117     UNIMPLEMENTED_INFO_CLASS(ProcessDeviceMap);
118     UNIMPLEMENTED_INFO_CLASS(ProcessSessionInformation);
119     UNIMPLEMENTED_INFO_CLASS(ProcessForegroundInformation);
120     UNIMPLEMENTED_INFO_CLASS(ProcessImageFileName);
121     UNIMPLEMENTED_INFO_CLASS(ProcessLUIDDeviceMapsEnabled);
122     UNIMPLEMENTED_INFO_CLASS(ProcessBreakOnTermination);
123     UNIMPLEMENTED_INFO_CLASS(ProcessDebugObjectHandle);
124     UNIMPLEMENTED_INFO_CLASS(ProcessDebugFlags);
125     UNIMPLEMENTED_INFO_CLASS(ProcessHandleTracing);
126
127     case ProcessBasicInformation:
128         {
129             PROCESS_BASIC_INFORMATION pbi;
130
131             if (ProcessInformationLength >= sizeof(PROCESS_BASIC_INFORMATION))
132             {
133                 if (!ProcessInformation)
134                     ret = STATUS_ACCESS_VIOLATION;
135                 else if (!ProcessHandle)
136                     ret = STATUS_INVALID_HANDLE;
137                 else
138                 {
139                     SERVER_START_REQ(get_process_info)
140                     {
141                         req->handle = ProcessHandle;
142                         if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
143                         {
144                             pbi.ExitStatus = reply->exit_code;
145                             pbi.PebBaseAddress = (DWORD)reply->peb;
146                             pbi.AffinityMask = reply->process_affinity;
147                             pbi.BasePriority = reply->priority;
148                             pbi.UniqueProcessId = reply->pid;
149                             pbi.InheritedFromUniqueProcessId = reply->ppid;
150                         }
151                     }
152                     SERVER_END_REQ;
153
154                     memcpy(ProcessInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION));
155
156                     len = sizeof(PROCESS_BASIC_INFORMATION);
157                 }
158
159                 if (ProcessInformationLength > sizeof(PROCESS_BASIC_INFORMATION))
160                     ret = STATUS_INFO_LENGTH_MISMATCH;
161             }
162             else ret = STATUS_INFO_LENGTH_MISMATCH;
163         }
164         break;
165     case ProcessIoCounters:
166         {
167             IO_COUNTERS pii;
168
169             if (ProcessInformationLength >= sizeof(IO_COUNTERS))
170             {
171                 if (!ProcessInformation)
172                     ret = STATUS_ACCESS_VIOLATION;
173                 else if (!ProcessHandle)
174                     ret = STATUS_INVALID_HANDLE;
175                 else
176                 {
177                     /* FIXME : real data */
178                     memset(&pii, 0 , sizeof(IO_COUNTERS));
179
180                     memcpy(ProcessInformation, &pii, sizeof(IO_COUNTERS));
181
182                     len = sizeof(IO_COUNTERS);
183                 }
184
185                 if (ProcessInformationLength > sizeof(IO_COUNTERS))
186                     ret = STATUS_INFO_LENGTH_MISMATCH;
187             }
188             else ret = STATUS_INFO_LENGTH_MISMATCH;
189         }
190         break;
191     case ProcessVmCounters:
192         {
193             VM_COUNTERS pvmi;
194
195             if (ProcessInformationLength >= sizeof(VM_COUNTERS))
196             {
197                 if (!ProcessInformation)
198                     ret = STATUS_ACCESS_VIOLATION;
199                 else if (!ProcessHandle)
200                     ret = STATUS_INVALID_HANDLE;
201                 else
202                 {
203                     /* FIXME : real data */
204                     memset(&pvmi, 0 , sizeof(VM_COUNTERS));
205
206                     memcpy(ProcessInformation, &pvmi, sizeof(VM_COUNTERS));
207
208                     len = sizeof(VM_COUNTERS);
209                 }
210
211                 if (ProcessInformationLength > sizeof(VM_COUNTERS))
212                     ret = STATUS_INFO_LENGTH_MISMATCH;
213             }
214             else ret = STATUS_INFO_LENGTH_MISMATCH;
215         }
216         break;
217     case ProcessTimes:
218         {
219             KERNEL_USER_TIMES pti;
220
221             if (ProcessInformationLength >= sizeof(KERNEL_USER_TIMES))
222             {
223                 if (!ProcessInformation)
224                     ret = STATUS_ACCESS_VIOLATION;
225                 else if (!ProcessHandle)
226                     ret = STATUS_INVALID_HANDLE;
227                 else
228                 {
229                     /* FIXME : real data */
230                     memset(&pti, 0, sizeof(KERNEL_USER_TIMES));
231
232                     memcpy(ProcessInformation, &pti, sizeof(KERNEL_USER_TIMES));
233
234                     len = sizeof(KERNEL_USER_TIMES);
235                 }
236
237                 if (ProcessInformationLength > sizeof(KERNEL_USER_TIMES))
238                     ret = STATUS_INFO_LENGTH_MISMATCH;
239             }
240             else ret = STATUS_INFO_LENGTH_MISMATCH;
241         }
242         break;
243     case ProcessDebugPort:
244         /* "These are not the debuggers you are looking for." *
245          * set it to 0 aka "no debugger" to satisfy copy protections */
246         if (ProcessInformationLength == 4)
247         {
248             memset(ProcessInformation, 0, ProcessInformationLength);
249             len = 4;
250         }
251         else ret = STATUS_INFO_LENGTH_MISMATCH;
252         break;
253     case ProcessHandleCount:
254         if (ProcessInformationLength >= 4)
255         {
256             if (!ProcessInformation)
257                 ret = STATUS_ACCESS_VIOLATION;
258             else if (!ProcessHandle)
259                 ret = STATUS_INVALID_HANDLE;
260             else
261             {
262                 memset(ProcessInformation, 0, 4);
263
264
265                 len = 4;
266             }
267
268             if (ProcessInformationLength > 4)
269                 ret = STATUS_INFO_LENGTH_MISMATCH;
270          }
271          else ret = STATUS_INFO_LENGTH_MISMATCH;
272          break;
273     case ProcessWow64Information:
274         if (ProcessInformationLength == 4)
275         {
276             memset(ProcessInformation, 0, ProcessInformationLength);
277             len = 4;
278         }
279         else ret = STATUS_INFO_LENGTH_MISMATCH;
280         break;
281     default:
282         FIXME("(%p,info_class=%d,%p,0x%08lx,%p) Unknown information class\n",
283               ProcessHandle,ProcessInformationClass,
284               ProcessInformation,ProcessInformationLength,
285               ReturnLength);
286         ret = STATUS_INVALID_INFO_CLASS;
287         break;
288     }
289
290     if (ReturnLength) *ReturnLength = len;
291     
292     return ret;
293 }
294
295 /******************************************************************************
296  * NtSetInformationProcess [NTDLL.@]
297  * ZwSetInformationProcess [NTDLL.@]
298  */
299 NTSTATUS WINAPI NtSetInformationProcess(
300         IN HANDLE ProcessHandle,
301         IN PROCESSINFOCLASS ProcessInformationClass,
302         IN PVOID ProcessInformation,
303         IN ULONG ProcessInformationLength)
304 {
305     NTSTATUS ret = STATUS_SUCCESS;
306
307     switch (ProcessInformationClass)
308     {
309     case ProcessPriorityClass:
310         if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
311             return STATUS_INVALID_PARAMETER;
312         else
313         {
314             PROCESS_PRIORITY_CLASS* ppc = ProcessInformation;
315
316             SERVER_START_REQ( set_process_info )
317             {
318                 req->handle   = ProcessHandle;
319                 /* FIXME Foreground isn't used */
320                 req->priority = ppc->PriorityClass;
321                 req->mask     = SET_PROCESS_INFO_PRIORITY;
322                 ret = wine_server_call( req );
323             }
324             SERVER_END_REQ;
325         }
326         break;
327     default:
328         FIXME("(%p,0x%08x,%p,0x%08lx) stub\n",
329               ProcessHandle,ProcessInformationClass,ProcessInformation,
330               ProcessInformationLength);
331         ret = STATUS_NOT_IMPLEMENTED;
332         break;
333     }
334     return ret;
335 }
336
337 /******************************************************************************
338  * NtFlushInstructionCache [NTDLL.@]
339  * ZwFlushInstructionCache [NTDLL.@]
340  */
341 NTSTATUS WINAPI NtFlushInstructionCache(
342         IN HANDLE ProcessHandle,
343         IN LPCVOID BaseAddress,
344         IN SIZE_T Size)
345 {
346 #ifdef __i386__
347     TRACE("%p %p %ld - no-op on x86\n", ProcessHandle, BaseAddress, Size );
348 #else
349     FIXME("%p %p %ld\n", ProcessHandle, BaseAddress, Size );
350 #endif
351     return STATUS_SUCCESS;
352 }
353
354 /******************************************************************
355  *              NtOpenProcess [NTDLL.@]
356  *              ZwOpenProcess [NTDLL.@]
357  */
358 NTSTATUS  WINAPI NtOpenProcess(PHANDLE handle, ACCESS_MASK access,
359                                const OBJECT_ATTRIBUTES* attr, const CLIENT_ID* cid)
360 {
361     NTSTATUS    status;
362
363     SERVER_START_REQ( open_process )
364     {
365         req->pid     = (DWORD)cid->UniqueProcess;
366         req->access  = access;
367         req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
368         status = wine_server_call( req );
369         if (!status) *handle = reply->handle;
370     }
371     SERVER_END_REQ;
372     return status;
373 }