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