server/ntdll: Simplistic implementation of NtQueryObject(ObjectBasicInformation).
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23
24 #include <stdarg.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29
30 #include "ntstatus.h"
31 #define WIN32_NO_STATUS
32 #include "wine/debug.h"
33 #include "windef.h"
34 #include "winternl.h"
35 #include "ntdll_misc.h"
36 #include "wine/server.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
39
40 /*
41  *      Process object
42  */
43
44 /******************************************************************************
45  *  NtTerminateProcess                  [NTDLL.@]
46  *
47  *  Native applications must kill themselves when done
48  */
49 NTSTATUS WINAPI NtTerminateProcess( HANDLE handle, LONG exit_code )
50 {
51     NTSTATUS ret;
52     BOOL self;
53     SERVER_START_REQ( terminate_process )
54     {
55         req->handle    = handle;
56         req->exit_code = exit_code;
57         ret = wine_server_call( req );
58         self = !ret && reply->self;
59     }
60     SERVER_END_REQ;
61     if (self) exit( exit_code );
62     return ret;
63 }
64
65 /******************************************************************************
66  *  RtlGetCurrentPeb  [NTDLL.@]
67  *
68  */
69 PEB * WINAPI RtlGetCurrentPeb(void)
70 {
71     return NtCurrentTeb()->Peb;
72 }
73
74 #define UNIMPLEMENTED_INFO_CLASS(c) \
75     case c: \
76         FIXME("(process=%p) Unimplemented information class: " #c "\n", ProcessHandle); \
77         ret = STATUS_INVALID_INFO_CLASS; \
78         break
79
80 /******************************************************************************
81 *  NtQueryInformationProcess            [NTDLL.@]
82 *  ZwQueryInformationProcess            [NTDLL.@]
83 *
84 */
85 NTSTATUS WINAPI NtQueryInformationProcess(
86         IN HANDLE ProcessHandle,
87         IN PROCESSINFOCLASS ProcessInformationClass,
88         OUT PVOID ProcessInformation,
89         IN ULONG ProcessInformationLength,
90         OUT PULONG ReturnLength)
91 {
92     NTSTATUS ret = STATUS_SUCCESS;
93     ULONG len = 0;
94
95     TRACE("(%p,0x%08x,%p,0x%08x,%p)\n",
96           ProcessHandle,ProcessInformationClass,
97           ProcessInformation,ProcessInformationLength,
98           ReturnLength);
99
100     switch (ProcessInformationClass) 
101     {
102     UNIMPLEMENTED_INFO_CLASS(ProcessQuotaLimits);
103     UNIMPLEMENTED_INFO_CLASS(ProcessBasePriority);
104     UNIMPLEMENTED_INFO_CLASS(ProcessRaisePriority);
105     UNIMPLEMENTED_INFO_CLASS(ProcessExceptionPort);
106     UNIMPLEMENTED_INFO_CLASS(ProcessAccessToken);
107     UNIMPLEMENTED_INFO_CLASS(ProcessLdtInformation);
108     UNIMPLEMENTED_INFO_CLASS(ProcessLdtSize);
109     UNIMPLEMENTED_INFO_CLASS(ProcessDefaultHardErrorMode);
110     UNIMPLEMENTED_INFO_CLASS(ProcessIoPortHandlers);
111     UNIMPLEMENTED_INFO_CLASS(ProcessPooledUsageAndLimits);
112     UNIMPLEMENTED_INFO_CLASS(ProcessWorkingSetWatch);
113     UNIMPLEMENTED_INFO_CLASS(ProcessUserModeIOPL);
114     UNIMPLEMENTED_INFO_CLASS(ProcessEnableAlignmentFaultFixup);
115     UNIMPLEMENTED_INFO_CLASS(ProcessPriorityClass);
116     UNIMPLEMENTED_INFO_CLASS(ProcessWx86Information);
117     UNIMPLEMENTED_INFO_CLASS(ProcessAffinityMask);
118     UNIMPLEMENTED_INFO_CLASS(ProcessPriorityBoost);
119     UNIMPLEMENTED_INFO_CLASS(ProcessDeviceMap);
120     UNIMPLEMENTED_INFO_CLASS(ProcessSessionInformation);
121     UNIMPLEMENTED_INFO_CLASS(ProcessForegroundInformation);
122     UNIMPLEMENTED_INFO_CLASS(ProcessImageFileName);
123     UNIMPLEMENTED_INFO_CLASS(ProcessLUIDDeviceMapsEnabled);
124     UNIMPLEMENTED_INFO_CLASS(ProcessBreakOnTermination);
125     UNIMPLEMENTED_INFO_CLASS(ProcessDebugObjectHandle);
126     UNIMPLEMENTED_INFO_CLASS(ProcessDebugFlags);
127     UNIMPLEMENTED_INFO_CLASS(ProcessHandleTracing);
128
129     case ProcessBasicInformation:
130         {
131             PROCESS_BASIC_INFORMATION pbi;
132
133             if (ProcessInformationLength >= sizeof(PROCESS_BASIC_INFORMATION))
134             {
135                 if (!ProcessInformation)
136                     ret = STATUS_ACCESS_VIOLATION;
137                 else if (!ProcessHandle)
138                     ret = STATUS_INVALID_HANDLE;
139                 else
140                 {
141                     SERVER_START_REQ(get_process_info)
142                     {
143                         req->handle = ProcessHandle;
144                         if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
145                         {
146                             pbi.ExitStatus = reply->exit_code;
147                             pbi.PebBaseAddress = (DWORD)reply->peb;
148                             pbi.AffinityMask = reply->affinity;
149                             pbi.BasePriority = reply->priority;
150                             pbi.UniqueProcessId = reply->pid;
151                             pbi.InheritedFromUniqueProcessId = reply->ppid;
152                         }
153                     }
154                     SERVER_END_REQ;
155
156                     memcpy(ProcessInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION));
157
158                     len = sizeof(PROCESS_BASIC_INFORMATION);
159                 }
160
161                 if (ProcessInformationLength > sizeof(PROCESS_BASIC_INFORMATION))
162                     ret = STATUS_INFO_LENGTH_MISMATCH;
163             }
164             else ret = STATUS_INFO_LENGTH_MISMATCH;
165         }
166         break;
167     case ProcessIoCounters:
168         {
169             IO_COUNTERS pii;
170
171             if (ProcessInformationLength >= sizeof(IO_COUNTERS))
172             {
173                 if (!ProcessInformation)
174                     ret = STATUS_ACCESS_VIOLATION;
175                 else if (!ProcessHandle)
176                     ret = STATUS_INVALID_HANDLE;
177                 else
178                 {
179                     /* FIXME : real data */
180                     memset(&pii, 0 , sizeof(IO_COUNTERS));
181
182                     memcpy(ProcessInformation, &pii, sizeof(IO_COUNTERS));
183
184                     len = sizeof(IO_COUNTERS);
185                 }
186
187                 if (ProcessInformationLength > sizeof(IO_COUNTERS))
188                     ret = STATUS_INFO_LENGTH_MISMATCH;
189             }
190             else ret = STATUS_INFO_LENGTH_MISMATCH;
191         }
192         break;
193     case ProcessVmCounters:
194         {
195             VM_COUNTERS pvmi;
196
197             if (ProcessInformationLength >= sizeof(VM_COUNTERS))
198             {
199                 if (!ProcessInformation)
200                     ret = STATUS_ACCESS_VIOLATION;
201                 else if (!ProcessHandle)
202                     ret = STATUS_INVALID_HANDLE;
203                 else
204                 {
205                     /* FIXME : real data */
206                     memset(&pvmi, 0 , sizeof(VM_COUNTERS));
207
208                     memcpy(ProcessInformation, &pvmi, sizeof(VM_COUNTERS));
209
210                     len = sizeof(VM_COUNTERS);
211                 }
212
213                 if (ProcessInformationLength > sizeof(VM_COUNTERS))
214                     ret = STATUS_INFO_LENGTH_MISMATCH;
215             }
216             else ret = STATUS_INFO_LENGTH_MISMATCH;
217         }
218         break;
219     case ProcessTimes:
220         {
221             KERNEL_USER_TIMES pti;
222
223             if (ProcessInformationLength >= sizeof(KERNEL_USER_TIMES))
224             {
225                 if (!ProcessInformation)
226                     ret = STATUS_ACCESS_VIOLATION;
227                 else if (!ProcessHandle)
228                     ret = STATUS_INVALID_HANDLE;
229                 else
230                 {
231                     /* FIXME : User- and KernelTime have to be implemented */
232                     memset(&pti, 0, sizeof(KERNEL_USER_TIMES));
233
234                     SERVER_START_REQ(get_process_info)
235                     {
236                       req->handle = ProcessHandle;
237                       if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
238                       {
239                           NTDLL_from_server_abstime(&pti.CreateTime, &reply->start_time);
240                           NTDLL_from_server_abstime(&pti.ExitTime, &reply->end_time);
241                       }
242                     }
243                     SERVER_END_REQ;
244
245                     memcpy(ProcessInformation, &pti, sizeof(KERNEL_USER_TIMES));
246
247                     len = sizeof(KERNEL_USER_TIMES);
248                 }
249
250                 if (ProcessInformationLength > sizeof(KERNEL_USER_TIMES))
251                     ret = STATUS_INFO_LENGTH_MISMATCH;
252             }
253             else ret = STATUS_INFO_LENGTH_MISMATCH;
254         }
255         break;
256     case ProcessDebugPort:
257         /* "These are not the debuggers you are looking for." *
258          * set it to 0 aka "no debugger" to satisfy copy protections */
259         if (ProcessInformationLength == 4)
260         {
261             memset(ProcessInformation, 0, ProcessInformationLength);
262             len = 4;
263         }
264         else ret = STATUS_INFO_LENGTH_MISMATCH;
265         break;
266     case ProcessHandleCount:
267         if (ProcessInformationLength >= 4)
268         {
269             if (!ProcessInformation)
270                 ret = STATUS_ACCESS_VIOLATION;
271             else if (!ProcessHandle)
272                 ret = STATUS_INVALID_HANDLE;
273             else
274             {
275                 memset(ProcessInformation, 0, 4);
276
277
278                 len = 4;
279             }
280
281             if (ProcessInformationLength > 4)
282                 ret = STATUS_INFO_LENGTH_MISMATCH;
283          }
284          else ret = STATUS_INFO_LENGTH_MISMATCH;
285          break;
286     case ProcessWow64Information:
287         if (ProcessInformationLength == 4)
288         {
289             memset(ProcessInformation, 0, ProcessInformationLength);
290             len = 4;
291         }
292         else ret = STATUS_INFO_LENGTH_MISMATCH;
293         break;
294     default:
295         FIXME("(%p,info_class=%d,%p,0x%08x,%p) Unknown information class\n",
296               ProcessHandle,ProcessInformationClass,
297               ProcessInformation,ProcessInformationLength,
298               ReturnLength);
299         ret = STATUS_INVALID_INFO_CLASS;
300         break;
301     }
302
303     if (ReturnLength) *ReturnLength = len;
304     
305     return ret;
306 }
307
308 /******************************************************************************
309  * NtSetInformationProcess [NTDLL.@]
310  * ZwSetInformationProcess [NTDLL.@]
311  */
312 NTSTATUS WINAPI NtSetInformationProcess(
313         IN HANDLE ProcessHandle,
314         IN PROCESSINFOCLASS ProcessInformationClass,
315         IN PVOID ProcessInformation,
316         IN ULONG ProcessInformationLength)
317 {
318     NTSTATUS ret = STATUS_SUCCESS;
319
320     switch (ProcessInformationClass)
321     {
322     case ProcessAffinityMask:
323         if (ProcessInformationLength != sizeof(DWORD_PTR)) return STATUS_INVALID_PARAMETER;
324         SERVER_START_REQ( set_process_info )
325         {
326             req->handle   = ProcessHandle;
327             req->affinity = *(PDWORD_PTR)ProcessInformation;
328             req->mask     = SET_PROCESS_INFO_AFFINITY;
329             ret = wine_server_call( req );
330         }
331         SERVER_END_REQ;
332         break;
333     case ProcessPriorityClass:
334         if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
335             return STATUS_INVALID_PARAMETER;
336         else
337         {
338             PROCESS_PRIORITY_CLASS* ppc = ProcessInformation;
339
340             SERVER_START_REQ( set_process_info )
341             {
342                 req->handle   = ProcessHandle;
343                 /* FIXME Foreground isn't used */
344                 req->priority = ppc->PriorityClass;
345                 req->mask     = SET_PROCESS_INFO_PRIORITY;
346                 ret = wine_server_call( req );
347             }
348             SERVER_END_REQ;
349         }
350         break;
351     default:
352         FIXME("(%p,0x%08x,%p,0x%08x) stub\n",
353               ProcessHandle,ProcessInformationClass,ProcessInformation,
354               ProcessInformationLength);
355         ret = STATUS_NOT_IMPLEMENTED;
356         break;
357     }
358     return ret;
359 }
360
361 /******************************************************************************
362  * NtFlushInstructionCache [NTDLL.@]
363  * ZwFlushInstructionCache [NTDLL.@]
364  */
365 NTSTATUS WINAPI NtFlushInstructionCache(
366         IN HANDLE ProcessHandle,
367         IN LPCVOID BaseAddress,
368         IN SIZE_T Size)
369 {
370 #ifdef __i386__
371     TRACE("%p %p %ld - no-op on x86\n", ProcessHandle, BaseAddress, Size );
372 #else
373     FIXME("%p %p %ld\n", ProcessHandle, BaseAddress, Size );
374 #endif
375     return STATUS_SUCCESS;
376 }
377
378 /******************************************************************
379  *              NtOpenProcess [NTDLL.@]
380  *              ZwOpenProcess [NTDLL.@]
381  */
382 NTSTATUS  WINAPI NtOpenProcess(PHANDLE handle, ACCESS_MASK access,
383                                const OBJECT_ATTRIBUTES* attr, const CLIENT_ID* cid)
384 {
385     NTSTATUS    status;
386
387     SERVER_START_REQ( open_process )
388     {
389         req->pid        = (process_id_t)cid->UniqueProcess;
390         req->access     = access;
391         req->attributes = attr ? attr->Attributes : 0;
392         status = wine_server_call( req );
393         if (!status) *handle = reply->handle;
394     }
395     SERVER_END_REQ;
396     return status;
397 }