ntdll: tape.c portability fixes.
[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
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%08lx,%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 : real data */
232                     memset(&pti, 0, sizeof(KERNEL_USER_TIMES));
233
234                     memcpy(ProcessInformation, &pti, sizeof(KERNEL_USER_TIMES));
235
236                     len = sizeof(KERNEL_USER_TIMES);
237                 }
238
239                 if (ProcessInformationLength > sizeof(KERNEL_USER_TIMES))
240                     ret = STATUS_INFO_LENGTH_MISMATCH;
241             }
242             else ret = STATUS_INFO_LENGTH_MISMATCH;
243         }
244         break;
245     case ProcessDebugPort:
246         /* "These are not the debuggers you are looking for." *
247          * set it to 0 aka "no debugger" to satisfy copy protections */
248         if (ProcessInformationLength == 4)
249         {
250             memset(ProcessInformation, 0, ProcessInformationLength);
251             len = 4;
252         }
253         else ret = STATUS_INFO_LENGTH_MISMATCH;
254         break;
255     case ProcessHandleCount:
256         if (ProcessInformationLength >= 4)
257         {
258             if (!ProcessInformation)
259                 ret = STATUS_ACCESS_VIOLATION;
260             else if (!ProcessHandle)
261                 ret = STATUS_INVALID_HANDLE;
262             else
263             {
264                 memset(ProcessInformation, 0, 4);
265
266
267                 len = 4;
268             }
269
270             if (ProcessInformationLength > 4)
271                 ret = STATUS_INFO_LENGTH_MISMATCH;
272          }
273          else ret = STATUS_INFO_LENGTH_MISMATCH;
274          break;
275     case ProcessWow64Information:
276         if (ProcessInformationLength == 4)
277         {
278             memset(ProcessInformation, 0, ProcessInformationLength);
279             len = 4;
280         }
281         else ret = STATUS_INFO_LENGTH_MISMATCH;
282         break;
283     default:
284         FIXME("(%p,info_class=%d,%p,0x%08lx,%p) Unknown information class\n",
285               ProcessHandle,ProcessInformationClass,
286               ProcessInformation,ProcessInformationLength,
287               ReturnLength);
288         ret = STATUS_INVALID_INFO_CLASS;
289         break;
290     }
291
292     if (ReturnLength) *ReturnLength = len;
293     
294     return ret;
295 }
296
297 /******************************************************************************
298  * NtSetInformationProcess [NTDLL.@]
299  * ZwSetInformationProcess [NTDLL.@]
300  */
301 NTSTATUS WINAPI NtSetInformationProcess(
302         IN HANDLE ProcessHandle,
303         IN PROCESSINFOCLASS ProcessInformationClass,
304         IN PVOID ProcessInformation,
305         IN ULONG ProcessInformationLength)
306 {
307     NTSTATUS ret = STATUS_SUCCESS;
308
309     switch (ProcessInformationClass)
310     {
311     case ProcessAffinityMask:
312         if (ProcessInformationLength != sizeof(DWORD_PTR)) return STATUS_INVALID_PARAMETER;
313         SERVER_START_REQ( set_process_info )
314         {
315             req->handle   = ProcessHandle;
316             req->affinity = *(PDWORD_PTR)ProcessInformation;
317             req->mask     = SET_PROCESS_INFO_AFFINITY;
318             ret = wine_server_call( req );
319         }
320         SERVER_END_REQ;
321         break;
322     case ProcessPriorityClass:
323         if (ProcessInformationLength != sizeof(PROCESS_PRIORITY_CLASS))
324             return STATUS_INVALID_PARAMETER;
325         else
326         {
327             PROCESS_PRIORITY_CLASS* ppc = ProcessInformation;
328
329             SERVER_START_REQ( set_process_info )
330             {
331                 req->handle   = ProcessHandle;
332                 /* FIXME Foreground isn't used */
333                 req->priority = ppc->PriorityClass;
334                 req->mask     = SET_PROCESS_INFO_PRIORITY;
335                 ret = wine_server_call( req );
336             }
337             SERVER_END_REQ;
338         }
339         break;
340     default:
341         FIXME("(%p,0x%08x,%p,0x%08lx) stub\n",
342               ProcessHandle,ProcessInformationClass,ProcessInformation,
343               ProcessInformationLength);
344         ret = STATUS_NOT_IMPLEMENTED;
345         break;
346     }
347     return ret;
348 }
349
350 /******************************************************************************
351  * NtFlushInstructionCache [NTDLL.@]
352  * ZwFlushInstructionCache [NTDLL.@]
353  */
354 NTSTATUS WINAPI NtFlushInstructionCache(
355         IN HANDLE ProcessHandle,
356         IN LPCVOID BaseAddress,
357         IN SIZE_T Size)
358 {
359 #ifdef __i386__
360     TRACE("%p %p %ld - no-op on x86\n", ProcessHandle, BaseAddress, Size );
361 #else
362     FIXME("%p %p %ld\n", ProcessHandle, BaseAddress, Size );
363 #endif
364     return STATUS_SUCCESS;
365 }
366
367 /******************************************************************
368  *              NtOpenProcess [NTDLL.@]
369  *              ZwOpenProcess [NTDLL.@]
370  */
371 NTSTATUS  WINAPI NtOpenProcess(PHANDLE handle, ACCESS_MASK access,
372                                const OBJECT_ATTRIBUTES* attr, const CLIENT_ID* cid)
373 {
374     NTSTATUS    status;
375
376     SERVER_START_REQ( open_process )
377     {
378         req->pid        = (process_id_t)cid->UniqueProcess;
379         req->access     = access;
380         req->attributes = attr ? attr->Attributes : 0;
381         status = wine_server_call( req );
382         if (!status) *handle = reply->handle;
383     }
384     SERVER_END_REQ;
385     return status;
386 }