50feb7b4b2a43a80e044b319e15cae19d481cb1e
[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 VOID STDCALL
33 RtlAcquirePebLock(VOID)
34 {
35    PPEB Peb = NtCurrentPeb ();
36    Peb->FastPebLockRoutine (Peb->FastPebLock);
37 }
38
39
40 VOID STDCALL
41 RtlReleasePebLock(VOID)
42 {
43    PPEB Peb = NtCurrentPeb ();
44    Peb->FastPebUnlockRoutine (Peb->FastPebLock);
45 }
46
47 static inline VOID
48 RtlpCopyParameterString(PWCHAR *Ptr,
49                         PUNICODE_STRING Destination,
50                         PUNICODE_STRING Source,
51                         ULONG Size)
52 {
53    Destination->Length = Source->Length;
54    Destination->MaximumLength = Size ? Size : Source->MaximumLength;
55    Destination->Buffer = (PWCHAR)(*Ptr);
56    if (Source->Length)
57      memmove (Destination->Buffer, Source->Buffer, Source->Length);
58    Destination->Buffer[Destination->Length / sizeof(WCHAR)] = 0;
59    *Ptr += Destination->MaximumLength/sizeof(WCHAR);
60 }
61
62
63 NTSTATUS STDCALL
64 RtlCreateProcessParameters(PRTL_USER_PROCESS_PARAMETERS *ProcessParameters,
65                            PUNICODE_STRING ImagePathName,
66                            PUNICODE_STRING DllPath,
67                            PUNICODE_STRING CurrentDirectory,
68                            PUNICODE_STRING CommandLine,
69                            PWSTR Environment,
70                            PUNICODE_STRING WindowTitle,
71                            PUNICODE_STRING DesktopInfo,
72                            PUNICODE_STRING ShellInfo,
73                            PUNICODE_STRING RuntimeInfo)
74 {
75    NTSTATUS Status = STATUS_SUCCESS;
76    PRTL_USER_PROCESS_PARAMETERS Param = NULL;
77    ULONG RegionSize = 0;
78    ULONG Length = 0;
79    PWCHAR Dest;
80    UNICODE_STRING EmptyString;
81    HANDLE CurrentDirectoryHandle;
82    HANDLE ConsoleHandle;
83    ULONG ConsoleFlags;
84
85    DPRINT ("RtlCreateProcessParameters\n");
86
87    RtlAcquirePebLock();
88
89    EmptyString.Length = 0;
90    EmptyString.MaximumLength = sizeof(WCHAR);
91    EmptyString.Buffer = L"";
92
93    if (NtCurrentPeb()->ProcessParameters)
94      {
95         if (DllPath == NULL)
96           DllPath = &NtCurrentPeb()->ProcessParameters->DllPath;
97         if (Environment == NULL)
98           Environment  = NtCurrentPeb()->ProcessParameters->Environment;
99         if (CurrentDirectory == NULL)
100           CurrentDirectory = &NtCurrentPeb()->ProcessParameters->CurrentDirectoryName;\r
101         CurrentDirectoryHandle = NtCurrentPeb()->ProcessParameters->CurrentDirectoryHandle;\r
102         ConsoleHandle = NtCurrentPeb()->ProcessParameters->hConsole;\r
103         ConsoleFlags = NtCurrentPeb()->ProcessParameters->ProcessGroup;\r
104      }
105    else
106      {
107         if (DllPath == NULL)
108           DllPath = &EmptyString;
109         if (CurrentDirectory == NULL)
110           CurrentDirectory = &EmptyString;
111         CurrentDirectoryHandle = NULL;
112         ConsoleHandle = NULL;
113         ConsoleFlags = 0;
114      }
115
116    if (CommandLine == NULL)
117      CommandLine = &EmptyString;
118    if (WindowTitle == NULL)
119      WindowTitle = &EmptyString;
120    if (DesktopInfo == NULL)
121      DesktopInfo = &EmptyString;
122    if (ShellInfo == NULL)
123      ShellInfo = &EmptyString;
124    if (RuntimeInfo == NULL)
125      RuntimeInfo = &EmptyString;
126
127    /* size of process parameter block */
128    Length = sizeof(RTL_USER_PROCESS_PARAMETERS);
129
130    /* size of current directory buffer */
131    Length += (MAX_PATH * sizeof(WCHAR));
132
133    /* add string lengths */
134    Length += ALIGN(DllPath->MaximumLength, sizeof(ULONG));
135    Length += ALIGN(ImagePathName->Length + sizeof(WCHAR), sizeof(ULONG));
136    Length += ALIGN(CommandLine->Length + sizeof(WCHAR), sizeof(ULONG));
137    Length += ALIGN(WindowTitle->MaximumLength, sizeof(ULONG));
138    Length += ALIGN(DesktopInfo->MaximumLength, sizeof(ULONG));
139    Length += ALIGN(ShellInfo->MaximumLength, sizeof(ULONG));
140    Length += ALIGN(RuntimeInfo->MaximumLength, sizeof(ULONG));
141
142    /* Calculate the required block size */
143    RegionSize = ROUNDUP(Length, PAGE_SIZE);
144
145    Status = NtAllocateVirtualMemory(NtCurrentProcess(),
146                                     (PVOID*)&Param,
147                                     0,
148                                     &RegionSize,
149                                     MEM_RESERVE | MEM_COMMIT,
150                                     PAGE_READWRITE);
151    if (!NT_SUCCESS(Status))
152      {
153         RtlReleasePebLock();
154         return Status;
155      }
156
157    DPRINT ("Process parameters allocated\n");
158
159    Param->AllocationSize = RegionSize;\r
160    Param->Size = Length;\r
161    Param->Flags = PPF_NORMALIZED;
162    Param->Environment = Environment;
163    Param->CurrentDirectoryHandle = CurrentDirectoryHandle;\r
164    Param->hConsole = ConsoleHandle;\r
165    Param->ProcessGroup = ConsoleFlags;\r
166
167    Dest = (PWCHAR)(((PBYTE)Param) + sizeof(RTL_USER_PROCESS_PARAMETERS));
168
169    /* copy current directory */
170    RtlpCopyParameterString(&Dest,
171                            &Param->CurrentDirectoryName,\r
172                            CurrentDirectory,
173                            MAX_PATH * sizeof(WCHAR));
174
175    /* make sure the current directory has a trailing backslash */
176    if (Param->CurrentDirectoryName.Length > 0)\r
177      {
178         ULONG Length;
179
180         Length = Param->CurrentDirectoryName.Length / sizeof(WCHAR);\r
181         if (Param->CurrentDirectoryName.Buffer[Length-1] != L'\\')\r
182           {
183              Param->CurrentDirectoryName.Buffer[Length] = L'\\';\r
184              Param->CurrentDirectoryName.Buffer[Length + 1] = 0;\r
185              Param->CurrentDirectoryName.Length += sizeof(WCHAR);\r
186           }
187      }
188
189    /* copy dll path */
190    RtlpCopyParameterString(&Dest,
191                            &Param->DllPath,
192                            DllPath,
193                            0);
194
195    /* copy image path name */
196    RtlpCopyParameterString(&Dest,
197                            &Param->ImagePathName,
198                            ImagePathName,
199                            ImagePathName->Length + sizeof(WCHAR));
200
201    /* copy command line */
202    RtlpCopyParameterString(&Dest,
203                            &Param->CommandLine,
204                            CommandLine,
205                            CommandLine->Length + sizeof(WCHAR));
206
207    /* copy title */
208    RtlpCopyParameterString(&Dest,
209                            &Param->WindowTitle,
210                            WindowTitle,
211                            0);
212
213    /* copy desktop */
214    RtlpCopyParameterString(&Dest,
215                            &Param->DesktopInfo,
216                            DesktopInfo,
217                            0);
218
219    /* copy shell info */
220    RtlpCopyParameterString(&Dest,
221                            &Param->ShellInfo,
222                            ShellInfo,
223                            0);
224
225    /* copy runtime info */
226    RtlpCopyParameterString(&Dest,
227                            &Param->RuntimeInfo,
228                            RuntimeInfo,
229                            0);
230
231    RtlDeNormalizeProcessParams(Param);
232    *ProcessParameters = Param;
233    RtlReleasePebLock();
234
235    return STATUS_SUCCESS;
236 }
237
238 VOID STDCALL
239 RtlDestroyProcessParameters(PRTL_USER_PROCESS_PARAMETERS ProcessParameters)
240 {
241    ULONG RegionSize = 0;
242
243    NtFreeVirtualMemory (NtCurrentProcess (),
244                         (PVOID)ProcessParameters,
245                         &RegionSize,
246                         MEM_RELEASE);
247 }
248
249 /*
250  * denormalize process parameters (Pointer-->Offset)
251  */
252 PRTL_USER_PROCESS_PARAMETERS STDCALL
253 RtlDeNormalizeProcessParams(PRTL_USER_PROCESS_PARAMETERS Params)
254 {
255    if (Params && (Params->Flags & PPF_NORMALIZED))
256      {
257         DENORMALIZE(Params->CurrentDirectoryName.Buffer, Params);\r
258         DENORMALIZE(Params->DllPath.Buffer, Params);
259         DENORMALIZE(Params->ImagePathName.Buffer, Params);
260         DENORMALIZE(Params->CommandLine.Buffer, Params);
261         DENORMALIZE(Params->WindowTitle.Buffer, Params);
262         DENORMALIZE(Params->DesktopInfo.Buffer, Params);
263         DENORMALIZE(Params->ShellInfo.Buffer, Params);
264         DENORMALIZE(Params->RuntimeInfo.Buffer, Params);
265
266         Params->Flags &= ~PPF_NORMALIZED;
267      }
268
269    return Params;
270 }
271
272 /*
273  * normalize process parameters (Offset-->Pointer)
274  */
275 PRTL_USER_PROCESS_PARAMETERS STDCALL
276 RtlNormalizeProcessParams(PRTL_USER_PROCESS_PARAMETERS Params)
277 {
278    if (Params && !(Params->Flags & PPF_NORMALIZED))
279      {
280         NORMALIZE(Params->CurrentDirectoryName.Buffer, Params);\r
281         NORMALIZE(Params->DllPath.Buffer, Params);
282         NORMALIZE(Params->ImagePathName.Buffer, Params);
283         NORMALIZE(Params->CommandLine.Buffer, Params);
284         NORMALIZE(Params->WindowTitle.Buffer, Params);
285         NORMALIZE(Params->DesktopInfo.Buffer, Params);
286         NORMALIZE(Params->ShellInfo.Buffer, Params);
287         NORMALIZE(Params->RuntimeInfo.Buffer, Params);
288
289         Params->Flags |= PPF_NORMALIZED;
290      }
291
292    return Params;
293 }
294
295 /* EOF */