Use the same defaults for modules with and without an explicit path.
[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 #define UNIMPLEMENTED_INFO_CLASS(c) \
64     case c: \
65         FIXME("(process=%p) Unimplemented information class: " #c "\n", ProcessHandle); \
66         ret = STATUS_INVALID_INFO_CLASS; \
67         break
68
69 /******************************************************************************
70 *  NtQueryInformationProcess            [NTDLL.@]
71 *  ZwQueryInformationProcess            [NTDLL.@]
72 *
73 */
74 NTSTATUS WINAPI NtQueryInformationProcess(
75         IN HANDLE ProcessHandle,
76         IN PROCESSINFOCLASS ProcessInformationClass,
77         OUT PVOID ProcessInformation,
78         IN ULONG ProcessInformationLength,
79         OUT PULONG ReturnLength)
80 {
81     NTSTATUS ret = STATUS_SUCCESS;
82     ULONG len = 0;
83
84     TRACE("(%p,0x%08x,%p,0x%08lx,%p)\n",
85           ProcessHandle,ProcessInformationClass,
86           ProcessInformation,ProcessInformationLength,
87           ReturnLength);
88
89     switch (ProcessInformationClass) 
90     {
91     UNIMPLEMENTED_INFO_CLASS(ProcessQuotaLimits);
92     UNIMPLEMENTED_INFO_CLASS(ProcessBasePriority);
93     UNIMPLEMENTED_INFO_CLASS(ProcessRaisePriority);
94     UNIMPLEMENTED_INFO_CLASS(ProcessExceptionPort);
95     UNIMPLEMENTED_INFO_CLASS(ProcessAccessToken);
96     UNIMPLEMENTED_INFO_CLASS(ProcessLdtInformation);
97     UNIMPLEMENTED_INFO_CLASS(ProcessLdtSize);
98     UNIMPLEMENTED_INFO_CLASS(ProcessDefaultHardErrorMode);
99     UNIMPLEMENTED_INFO_CLASS(ProcessIoPortHandlers);
100     UNIMPLEMENTED_INFO_CLASS(ProcessPooledUsageAndLimits);
101     UNIMPLEMENTED_INFO_CLASS(ProcessWorkingSetWatch);
102     UNIMPLEMENTED_INFO_CLASS(ProcessUserModeIOPL);
103     UNIMPLEMENTED_INFO_CLASS(ProcessEnableAlignmentFaultFixup);
104     UNIMPLEMENTED_INFO_CLASS(ProcessPriorityClass);
105     UNIMPLEMENTED_INFO_CLASS(ProcessWx86Information);
106     UNIMPLEMENTED_INFO_CLASS(ProcessAffinityMask);
107     UNIMPLEMENTED_INFO_CLASS(ProcessPriorityBoost);
108     UNIMPLEMENTED_INFO_CLASS(ProcessDeviceMap);
109     UNIMPLEMENTED_INFO_CLASS(ProcessSessionInformation);
110     UNIMPLEMENTED_INFO_CLASS(ProcessForegroundInformation);
111     UNIMPLEMENTED_INFO_CLASS(ProcessImageFileName);
112     UNIMPLEMENTED_INFO_CLASS(ProcessLUIDDeviceMapsEnabled);
113     UNIMPLEMENTED_INFO_CLASS(ProcessBreakOnTermination);
114     UNIMPLEMENTED_INFO_CLASS(ProcessDebugObjectHandle);
115     UNIMPLEMENTED_INFO_CLASS(ProcessDebugFlags);
116     UNIMPLEMENTED_INFO_CLASS(ProcessHandleTracing);
117
118     case ProcessBasicInformation:
119         {
120             PROCESS_BASIC_INFORMATION pbi;
121
122             if (ProcessInformationLength >= sizeof(PROCESS_BASIC_INFORMATION))
123             {
124                 if (!ProcessInformation)
125                     ret = STATUS_ACCESS_VIOLATION;
126                 else if (!ProcessHandle)
127                     ret = STATUS_INVALID_HANDLE;
128                 else
129                 {
130                     SERVER_START_REQ(get_process_info)
131                     {
132                         req->handle = ProcessHandle;
133                         if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
134                         {
135                             pbi.ExitStatus = reply->exit_code;
136                             pbi.PebBaseAddress = (DWORD)reply->peb;
137                             pbi.AffinityMask = reply->process_affinity;
138                             pbi.BasePriority = reply->priority;
139                             pbi.UniqueProcessId = reply->pid;
140                             pbi.InheritedFromUniqueProcessId = reply->ppid;
141                         }
142                     }
143                     SERVER_END_REQ;
144
145                     memcpy(ProcessInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION));
146
147                     len = sizeof(PROCESS_BASIC_INFORMATION);
148                 }
149
150                 if (ProcessInformationLength > sizeof(PROCESS_BASIC_INFORMATION))
151                     ret = STATUS_INFO_LENGTH_MISMATCH;
152             }
153             else ret = STATUS_INFO_LENGTH_MISMATCH;
154         }
155         break;
156     case ProcessIoCounters:
157         {
158             IO_COUNTERS pii;
159
160             if (ProcessInformationLength >= sizeof(IO_COUNTERS))
161             {
162                 if (!ProcessInformation)
163                     ret = STATUS_ACCESS_VIOLATION;
164                 else if (!ProcessHandle)
165                     ret = STATUS_INVALID_HANDLE;
166                 else
167                 {
168                     /* FIXME : real data */
169                     memset(&pii, 0 , sizeof(IO_COUNTERS));
170
171                     memcpy(ProcessInformation, &pii, sizeof(IO_COUNTERS));
172
173                     len = sizeof(IO_COUNTERS);
174                 }
175
176                 if (ProcessInformationLength > sizeof(IO_COUNTERS))
177                     ret = STATUS_INFO_LENGTH_MISMATCH;
178             }
179             else ret = STATUS_INFO_LENGTH_MISMATCH;
180         }
181         break;
182     case ProcessVmCounters:
183         {
184             VM_COUNTERS pvmi;
185
186             if (ProcessInformationLength >= sizeof(VM_COUNTERS))
187             {
188                 if (!ProcessInformation)
189                     ret = STATUS_ACCESS_VIOLATION;
190                 else if (!ProcessHandle)
191                     ret = STATUS_INVALID_HANDLE;
192                 else
193                 {
194                     /* FIXME : real data */
195                     memset(&pvmi, 0 , sizeof(VM_COUNTERS));
196
197                     memcpy(ProcessInformation, &pvmi, sizeof(VM_COUNTERS));
198
199                     len = sizeof(VM_COUNTERS);
200                 }
201
202                 if (ProcessInformationLength > sizeof(VM_COUNTERS))
203                     ret = STATUS_INFO_LENGTH_MISMATCH;
204             }
205             else ret = STATUS_INFO_LENGTH_MISMATCH;
206         }
207         break;
208     case ProcessTimes:
209         {
210             KERNEL_USER_TIMES pti;
211
212             if (ProcessInformationLength >= sizeof(KERNEL_USER_TIMES))
213             {
214                 if (!ProcessInformation)
215                     ret = STATUS_ACCESS_VIOLATION;
216                 else if (!ProcessHandle)
217                     ret = STATUS_INVALID_HANDLE;
218                 else
219                 {
220                     /* FIXME : real data */
221                     memset(&pti, 0, sizeof(KERNEL_USER_TIMES));
222
223                     memcpy(ProcessInformation, &pti, sizeof(KERNEL_USER_TIMES));
224
225                     len = sizeof(KERNEL_USER_TIMES);
226                 }
227
228                 if (ProcessInformationLength > sizeof(KERNEL_USER_TIMES))
229                     ret = STATUS_INFO_LENGTH_MISMATCH;
230             }
231             else ret = STATUS_INFO_LENGTH_MISMATCH;
232         }
233         break;
234     case ProcessDebugPort:
235         /* "These are not the debuggers you are looking for." *
236          * set it to 0 aka "no debugger" to satisfy copy protections */
237         if (ProcessInformationLength == 4)
238         {
239             memset(ProcessInformation, 0, ProcessInformationLength);
240             len = 4;
241         }
242         else ret = STATUS_INFO_LENGTH_MISMATCH;
243         break;
244     case ProcessHandleCount:
245         if (ProcessInformationLength >= 4)
246         {
247             if (!ProcessInformation)
248                 ret = STATUS_ACCESS_VIOLATION;
249             else if (!ProcessHandle)
250                 ret = STATUS_INVALID_HANDLE;
251             else
252             {
253                 memset(ProcessInformation, 0, 4);
254
255
256                 len = 4;
257             }
258
259             if (ProcessInformationLength > 4)
260                 ret = STATUS_INFO_LENGTH_MISMATCH;
261          }
262          else ret = STATUS_INFO_LENGTH_MISMATCH;
263          break;
264     case ProcessWow64Information:
265         if (ProcessInformationLength == 4)
266         {
267             memset(ProcessInformation, 0, ProcessInformationLength);
268             len = 4;
269         }
270         else ret = STATUS_INFO_LENGTH_MISMATCH;
271         break;
272     default:
273         FIXME("(%p,info_class=%d,%p,0x%08lx,%p) Unknown information class\n",
274               ProcessHandle,ProcessInformationClass,
275               ProcessInformation,ProcessInformationLength,
276               ReturnLength);
277         ret = STATUS_INVALID_INFO_CLASS;
278         break;
279     }
280
281     if (ReturnLength) *ReturnLength = len;
282     
283     return ret;
284 }
285
286 /******************************************************************************
287  * NtSetInformationProcess [NTDLL.@]
288  * ZwSetInformationProcess [NTDLL.@]
289  */
290 NTSTATUS WINAPI NtSetInformationProcess(
291         IN HANDLE ProcessHandle,
292         IN PROCESSINFOCLASS ProcessInformationClass,
293         IN PVOID ProcessInformation,
294         IN ULONG ProcessInformationLength)
295 {
296     FIXME("(%p,0x%08x,%p,0x%08lx) stub\n",
297           ProcessHandle,ProcessInformationClass,ProcessInformation,ProcessInformationLength);
298     return 0;
299 }
300
301 /******************************************************************************
302  * NtFlushInstructionCache [NTDLL.@]
303  * ZwFlushInstructionCache [NTDLL.@]
304  */
305 NTSTATUS WINAPI NtFlushInstructionCache(
306         IN HANDLE ProcessHandle,
307         IN LPCVOID BaseAddress,
308         IN ULONG Size)
309 {
310 #ifdef __i386__
311     TRACE("%p %p %ld - no-op on x86\n", ProcessHandle, BaseAddress, Size );
312 #else
313     FIXME("%p %p %ld\n", ProcessHandle, BaseAddress, Size );
314 #endif
315     return STATUS_SUCCESS;
316 }
317
318 /******************************************************************
319  *              NtOpenProcess [NTDLL.@]
320  *              ZwOpenProcess [NTDLL.@]
321  */
322 NTSTATUS  WINAPI NtOpenProcess(PHANDLE handle, ACCESS_MASK access,
323                                const OBJECT_ATTRIBUTES* attr, const CLIENT_ID* cid)
324 {
325     NTSTATUS    status;
326
327     SERVER_START_REQ( open_process )
328     {
329         req->pid     = (DWORD)cid->UniqueProcess;
330         req->access  = access;
331         req->inherit = attr && (attr->Attributes & OBJ_INHERIT);
332         status = wine_server_call( req );
333         if (!status) *handle = reply->handle;
334     }
335     SERVER_END_REQ;
336     return status;
337 }