update for HEAD-2003091401
[reactos.git] / lib / ntdll / rtl / ppb.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/ntdll/rtl/ppb.c
6  * PURPOSE:         Process parameters functions
7  * PROGRAMMER:      Ariadne ( ariadne@xs4all.nl)
8  * UPDATE HISTORY:
9  *                  Created 01/11/98
10  */
11
12 /* INCLUDES ****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <ntdll/ldr.h>
16 #include <napi/teb.h>
17 #include <ntdll/base.h>
18 #include <ntdll/rtl.h>
19
20 #define NDEBUG
21 #include <ntdll/ntdll.h>
22
23 /* MACROS ****************************************************************/
24
25 #define NORMALIZE(x,addr)   {if(x) x=(VOID*)((ULONG)(x)+(ULONG)(addr));}
26 #define DENORMALIZE(x,addr) {if(x) x=(VOID*)((ULONG)(x)-(ULONG)(addr));}
27 #define ALIGN(x,align)      (((ULONG)(x)+(align)-1UL)&(~((align)-1UL)))
28
29
30 /* FUNCTIONS ****************************************************************/
31
32 /*
33  * @implemented
34  */
35 VOID STDCALL
36 RtlAcquirePebLock(VOID)
37 {
38    PPEB Peb = NtCurrentPeb ();
39    Peb->FastPebLockRoutine (Peb->FastPebLock);
40 }
41
42
43 /*
44  * @implemented
45  */
46 VOID STDCALL
47 RtlReleasePebLock(VOID)
48 {
49    PPEB Peb = NtCurrentPeb ();
50    Peb->FastPebUnlockRoutine (Peb->FastPebLock);
51 }
52
53 static inline VOID
54 RtlpCopyParameterString(PWCHAR *Ptr,
55                         PUNICODE_STRING Destination,
56                         PUNICODE_STRING Source,
57                         ULONG Size)
58 {
59    Destination->Length = Source->Length;
60    Destination->MaximumLength = Size ? Size : Source->MaximumLength;
61    Destination->Buffer = (PWCHAR)(*Ptr);
62    if (Source->Length)
63      memmove (Destination->Buffer, Source->Buffer, Source->Length);
64    Destination->Buffer[Destination->Length / sizeof(WCHAR)] = 0;
65    *Ptr += Destination->MaximumLength/sizeof(WCHAR);
66 }
67
68
69 /*
70  * @implemented
71  */
72 NTSTATUS STDCALL
73 RtlCreateProcessParameters(PRTL_USER_PROCESS_PARAMETERS *ProcessParameters,
74                            PUNICODE_STRING ImagePathName,
75                            PUNICODE_STRING DllPath,
76                            PUNICODE_STRING CurrentDirectory,
77                            PUNICODE_STRING CommandLine,
78                            PWSTR Environment,
79                            PUNICODE_STRING WindowTitle,
80                            PUNICODE_STRING DesktopInfo,
81                            PUNICODE_STRING ShellInfo,
82                            PUNICODE_STRING RuntimeInfo)
83 {
84    NTSTATUS Status = STATUS_SUCCESS;
85    PRTL_USER_PROCESS_PARAMETERS Param = NULL;
86    ULONG RegionSize = 0;
87    ULONG Length = 0;
88    PWCHAR Dest;
89    UNICODE_STRING EmptyString;
90    HANDLE CurrentDirectoryHandle;
91    HANDLE ConsoleHandle;
92    ULONG ConsoleFlags;
93
94    DPRINT ("RtlCreateProcessParameters\n");
95
96    RtlAcquirePebLock();
97
98    EmptyString.Length = 0;
99    EmptyString.MaximumLength = sizeof(WCHAR);
100    EmptyString.Buffer = L"";
101
102    if (NtCurrentPeb()->ProcessParameters)
103      {
104         if (DllPath == NULL)
105           DllPath = &NtCurrentPeb()->ProcessParameters->DllPath;
106         if (Environment == NULL)
107           Environment  = NtCurrentPeb()->ProcessParameters->Environment;
108         if (CurrentDirectory == NULL)
109           CurrentDirectory = &NtCurrentPeb()->ProcessParameters->CurrentDirectoryName;
110         CurrentDirectoryHandle = NtCurrentPeb()->ProcessParameters->CurrentDirectoryHandle;
111         ConsoleHandle = NtCurrentPeb()->ProcessParameters->hConsole;
112         ConsoleFlags = NtCurrentPeb()->ProcessParameters->ProcessGroup;
113      }
114    else
115      {
116         if (DllPath == NULL)
117           DllPath = &EmptyString;
118         if (CurrentDirectory == NULL)
119           CurrentDirectory = &EmptyString;
120         CurrentDirectoryHandle = NULL;
121         ConsoleHandle = NULL;
122         ConsoleFlags = 0;
123      }
124
125    if (CommandLine == NULL)
126      CommandLine = &EmptyString;
127    if (WindowTitle == NULL)
128      WindowTitle = &EmptyString;
129    if (DesktopInfo == NULL)
130      DesktopInfo = &EmptyString;
131    if (ShellInfo == NULL)
132      ShellInfo = &EmptyString;
133    if (RuntimeInfo == NULL)
134      RuntimeInfo = &EmptyString;
135
136    /* size of process parameter block */
137    Length = sizeof(RTL_USER_PROCESS_PARAMETERS);
138
139    /* size of current directory buffer */
140    Length += (MAX_PATH * sizeof(WCHAR));
141
142    /* add string lengths */
143    Length += ALIGN(DllPath->MaximumLength, sizeof(ULONG));
144    Length += ALIGN(ImagePathName->Length + sizeof(WCHAR), sizeof(ULONG));
145    Length += ALIGN(CommandLine->Length + sizeof(WCHAR), sizeof(ULONG));
146    Length += ALIGN(WindowTitle->MaximumLength, sizeof(ULONG));
147    Length += ALIGN(DesktopInfo->MaximumLength, sizeof(ULONG));
148    Length += ALIGN(ShellInfo->MaximumLength, sizeof(ULONG));
149    Length += ALIGN(RuntimeInfo->MaximumLength, sizeof(ULONG));
150
151    /* Calculate the required block size */
152    RegionSize = ROUNDUP(Length, PAGE_SIZE);
153
154    Status = NtAllocateVirtualMemory(NtCurrentProcess(),
155                                     (PVOID*)&Param,
156                                     0,
157                                     &RegionSize,
158                                     MEM_RESERVE | MEM_COMMIT,
159                                     PAGE_READWRITE);
160    if (!NT_SUCCESS(Status))
161      {
162         RtlReleasePebLock();
163         return Status;
164      }
165
166    DPRINT ("Process parameters allocated\n");
167
168    Param->AllocationSize = RegionSize;
169    Param->Size = Length;
170    Param->Flags = PPF_NORMALIZED;
171    Param->Environment = Environment;
172    Param->CurrentDirectoryHandle = CurrentDirectoryHandle;
173    Param->hConsole = ConsoleHandle;
174    Param->ProcessGroup = ConsoleFlags;
175
176    Dest = (PWCHAR)(((PBYTE)Param) + sizeof(RTL_USER_PROCESS_PARAMETERS));
177
178    /* copy current directory */
179    RtlpCopyParameterString(&Dest,
180                            &Param->CurrentDirectoryName,
181                            CurrentDirectory,
182                            MAX_PATH * sizeof(WCHAR));
183
184    /* make sure the current directory has a trailing backslash */
185    if (Param->CurrentDirectoryName.Length > 0)
186      {
187         ULONG Length;
188
189         Length = Param->CurrentDirectoryName.Length / sizeof(WCHAR);
190         if (Param->CurrentDirectoryName.Buffer[Length-1] != L'\\')
191           {
192              Param->CurrentDirectoryName.Buffer[Length] = L'\\';
193              Param->CurrentDirectoryName.Buffer[Length + 1] = 0;
194              Param->CurrentDirectoryName.Length += sizeof(WCHAR);
195           }
196      }
197
198    /* copy dll path */
199    RtlpCopyParameterString(&Dest,
200                            &Param->DllPath,
201                            DllPath,
202                            0);
203
204    /* copy image path name */
205    RtlpCopyParameterString(&Dest,
206                            &Param->ImagePathName,
207                            ImagePathName,
208                            ImagePathName->Length + sizeof(WCHAR));
209
210    /* copy command line */
211    RtlpCopyParameterString(&Dest,
212                            &Param->CommandLine,
213                            CommandLine,
214                            CommandLine->Length + sizeof(WCHAR));
215
216    /* copy title */
217    RtlpCopyParameterString(&Dest,
218                            &Param->WindowTitle,
219                            WindowTitle,
220                            0);
221
222    /* copy desktop */
223    RtlpCopyParameterString(&Dest,
224                            &Param->DesktopInfo,
225                            DesktopInfo,
226                            0);
227
228    /* copy shell info */
229    RtlpCopyParameterString(&Dest,
230                            &Param->ShellInfo,
231                            ShellInfo,
232                            0);
233
234    /* copy runtime info */
235    RtlpCopyParameterString(&Dest,
236                            &Param->RuntimeInfo,
237                            RuntimeInfo,
238                            0);
239
240    RtlDeNormalizeProcessParams(Param);
241    *ProcessParameters = Param;
242    RtlReleasePebLock();
243
244    return STATUS_SUCCESS;
245 }
246
247 /*
248  * @implemented
249  */
250 NTSTATUS STDCALL
251 RtlDestroyProcessParameters(PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
252 {
253    ULONG RegionSize = 0;
254
255    return NtFreeVirtualMemory (NtCurrentProcess (),
256                         (PVOID)ProcessParameters,
257                         &RegionSize,
258                         MEM_RELEASE);
259 }
260
261 /*
262  * denormalize process parameters (Pointer-->Offset)
263  *
264  * @implemented
265  */
266 PRTL_USER_PROCESS_PARAMETERS STDCALL
267 RtlDeNormalizeProcessParams(PRTL_USER_PROCESS_PARAMETERS Params)
268 {
269    if (Params && (Params->Flags & PPF_NORMALIZED))
270      {
271         DENORMALIZE(Params->CurrentDirectoryName.Buffer, Params);
272         DENORMALIZE(Params->DllPath.Buffer, Params);
273         DENORMALIZE(Params->ImagePathName.Buffer, Params);
274         DENORMALIZE(Params->CommandLine.Buffer, Params);
275         DENORMALIZE(Params->WindowTitle.Buffer, Params);
276         DENORMALIZE(Params->DesktopInfo.Buffer, Params);
277         DENORMALIZE(Params->ShellInfo.Buffer, Params);
278         DENORMALIZE(Params->RuntimeInfo.Buffer, Params);
279
280         Params->Flags &= ~PPF_NORMALIZED;
281      }
282
283    return Params;
284 }
285
286 /*
287  * normalize process parameters (Offset-->Pointer)
288  *
289  * @implemented
290  */
291 PRTL_USER_PROCESS_PARAMETERS STDCALL
292 RtlNormalizeProcessParams(PRTL_USER_PROCESS_PARAMETERS Params)
293 {
294    if (Params && !(Params->Flags & PPF_NORMALIZED))
295      {
296         NORMALIZE(Params->CurrentDirectoryName.Buffer, Params);
297         NORMALIZE(Params->DllPath.Buffer, Params);
298         NORMALIZE(Params->ImagePathName.Buffer, Params);
299         NORMALIZE(Params->CommandLine.Buffer, Params);
300         NORMALIZE(Params->WindowTitle.Buffer, Params);
301         NORMALIZE(Params->DesktopInfo.Buffer, Params);
302         NORMALIZE(Params->ShellInfo.Buffer, Params);
303         NORMALIZE(Params->RuntimeInfo.Buffer, Params);
304
305         Params->Flags |= PPF_NORMALIZED;
306      }
307
308    return Params;
309 }
310
311 /* EOF */