__PdxSerializeProcessData and __PdxUnserializeProcessData calls
[reactos.git] / posix / lib / psxdll / misc / pdata.c
1 /* $Id: pdata.c,v 1.1 2002/03/10 17:04:07 hyperion Exp $
2 */
3 /*
4 * COPYRIGHT: See COPYING in the top level directory
5 * PROJECT: ReactOS POSIX+ Subsystem
6 * FILE: subsys/psx/lib/psxdll/misc/pdata.c
7 * PURPOSE: Process data management
8 * PROGRAMMER: KJK::Hyperion <noog@libero.it>
9 * UPDATE HISTORY:
10 * 06/03/2002: Created
11 * 07/03/2002: Added __PdxUnserializeProcessData() (KJK::Hyperion
12 * <noog@libero.it>)
13 */
14
15 #include <ddk/ntddk.h>
16 #include <string.h>
17 #include <psx/fdtable.h>
18 #include <psx/pdata.h>
19 #include <psx/stdlib.h>
20 #include <psx/debug.h>
21
22 /* serialize a process data block in a contiguous, page-aligned block, suitable
23 for transfer across processes */
24 NTSTATUS
25 STDCALL
26 __PdxSerializeProcessData
27 (
28 IN __PPDX_PDATA ProcessData,
29 OUT __PPDX_SERIALIZED_PDATA *SerializedProcessData
30 )
31 {
32 __PPDX_SERIALIZED_PDATA pspdProcessData = 0;
33 NTSTATUS nErrCode;
34 PBYTE pBufferTail;
35 ULONG ulAllocSize = sizeof(__PDX_SERIALIZED_PDATA) - 1;
36 size_t *pnArgLengths;
37 size_t *pnEnvVarsLengths;
38 int nEnvVarsCount;
39 int i;
40
41 /* calculate buffer length */
42 /* FIXME please! this is the most inefficient way to do it */
43
44 /* argv */
45 pnArgLengths = __malloc(ProcessData->ArgCount * sizeof(size_t));
46
47 for(i = 0; i < ProcessData->ArgCount; i ++)
48 {
49 int nStrLen = strlen(ProcessData->ArgVect[i]) + 1;
50 ulAllocSize += nStrLen;
51 pnArgLengths[i] = nStrLen;
52
53 INFO
54 (
55 "argument %d: \"%s\", length %d\n",
56 i,
57 ProcessData->ArgVect[i],
58 nStrLen
59 );
60 }
61
62 /* environ */
63 pnEnvVarsLengths = 0;
64 nEnvVarsCount = 0;
65
66 for(i = 0; *(ProcessData->Environment)[i] != 0; i++)
67 {
68 int nStrLen = strlen(*(ProcessData->Environment)[i]) + 1;
69 ulAllocSize += nStrLen;
70
71 nEnvVarsCount ++;
72 __realloc(pnEnvVarsLengths, nEnvVarsCount * sizeof(size_t));
73 pnEnvVarsLengths[i] = nStrLen;
74
75 INFO
76 (
77 "environment variable %d: \"%s\", length %d\n",
78 i,
79 *(ProcessData->Environment)[i],
80 nStrLen
81 );
82 }
83
84 INFO("(%d environment variables were found)\n", nEnvVarsCount);
85
86 /* current directory */
87 ulAllocSize += ProcessData->CurDir.Length;
88 INFO
89 (
90 "current directory: \"%Z\", length %d\n",
91 &ProcessData->CurDir,
92 ProcessData->CurDir.Length
93 );
94
95 /* root directory */
96 ulAllocSize += ProcessData->RootPath.Length;
97 INFO
98 (
99 "root directory: \"%Z\", length %d\n",
100 &ProcessData->RootPath,
101 ProcessData->RootPath.Length
102 );
103
104 /* file descriptors table */
105 ulAllocSize += sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors;
106 INFO
107 (
108 "descriptors table contains %d allocated descriptors, combined length %d\n",
109 ProcessData->FdTable.AllocatedDescriptors,
110 sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors
111 );
112
113 /* extra descriptors data */
114 for(i = 0; ProcessData->FdTable.AllocatedDescriptors; i ++)
115 if(ProcessData->FdTable.Descriptors[i].ExtraData != NULL)
116 {
117 ulAllocSize += ProcessData->FdTable.Descriptors[i].ExtraDataSize;
118
119 INFO
120 (
121 "descriptor %d has %d bytes of associated data\n",
122 i,
123 ProcessData->FdTable.Descriptors[i].ExtraDataSize
124 );
125
126 }
127
128 /* allocate return block */
129 INFO("about to allocate %d bytes\n", ulAllocSize);
130
131 nErrCode = NtAllocateVirtualMemory
132 (
133 NtCurrentProcess(),
134 (PVOID *)&pspdProcessData,
135 0,
136 &ulAllocSize,
137 MEM_COMMIT,
138 PAGE_READWRITE
139 );
140
141 /* failure */
142 if(!NT_SUCCESS(nErrCode))
143 {
144 ERR("NtAllocateVirtualMemory() failed with status 0x%08X\n", nErrCode);
145 __free(pnArgLengths);
146 __free(pnEnvVarsLengths);
147 *SerializedProcessData = 0;
148 return;
149 }
150
151 INFO("%d bytes actually allocated\n", ulAllocSize);
152 pspdProcessData->AllocSize = ulAllocSize;
153
154 /* copy data */
155 /* static data */
156 memcpy(&pspdProcessData->ProcessData, ProcessData, sizeof(__PDX_PDATA));
157
158 /* buffers */
159 pBufferTail = &pspdProcessData->Buffer[0];
160 INFO("buffer tail begins at 0x%08X\n", pBufferTail);
161
162 /* argv */
163 pspdProcessData->ProcessData.ArgVect = 0;
164
165 for(i = 0; i < ProcessData->ArgCount; i ++)
166 {
167 INFO
168 (
169 "copying %d bytes of argument %d (\"%s\") to 0x%08X\n",
170 pnArgLengths[i],
171 i,
172 ProcessData->ArgVect[i],
173 pBufferTail
174 );
175
176 strncpy(pBufferTail, ProcessData->ArgVect[i], pnArgLengths[i]);
177 pBufferTail += pnArgLengths[i];
178
179 INFO
180 (
181 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
182 pnArgLengths[i],
183 pBufferTail
184 );
185
186 }
187
188 __free(pnArgLengths);
189
190 /* environ */
191 pspdProcessData->ProcessData.Environment = (char ***)nEnvVarsCount;
192
193 for(i = 0; i < nEnvVarsCount; i ++)
194 {
195 INFO
196 (
197 "copying %d bytes of environment variable %d (\"%s\") to 0x%08X\n",
198 pnEnvVarsLengths[i],
199 i,
200 ProcessData->Environment[i],
201 pBufferTail
202 );
203
204 strncpy(pBufferTail, *ProcessData->Environment[i], pnEnvVarsLengths[i]);
205 pBufferTail += pnEnvVarsLengths[i];
206
207 INFO
208 (
209 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
210 pnEnvVarsLengths[i],
211 pBufferTail
212 );
213 }
214
215 __free(pnEnvVarsLengths);
216
217 /* current directory */
218 INFO
219 (
220 "copying %d bytes of current directory (\"%Z\") to 0x%08X\n",
221 ProcessData->CurDir.Length,
222 &ProcessData->CurDir,
223 pBufferTail
224 );
225
226 memcpy(pBufferTail, ProcessData->CurDir.Buffer, ProcessData->CurDir.Length);
227 pBufferTail += ProcessData->CurDir.Length;
228
229 INFO
230 (
231 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
232 ProcessData->CurDir.Length,
233 pBufferTail
234 );
235
236 /* root directory */
237 INFO
238 (
239 "copying %d bytes of root directory (\"%Z\") to 0x%08X\n",
240 ProcessData->RootPath.Length,
241 &ProcessData->RootPath,
242 pBufferTail
243 );
244
245 memcpy
246 (
247 pBufferTail,
248 ProcessData->RootPath.Buffer,
249 ProcessData->RootPath.Length
250 );
251
252 pBufferTail += ProcessData->RootPath.Length;
253
254 INFO
255 (
256 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
257 ProcessData->RootPath.Length,
258 pBufferTail
259 );
260
261 /* file descriptors table */
262 /* save the offset to the descriptors array */
263 pspdProcessData->ProcessData.FdTable.Descriptors =
264 (PVOID)((ULONG)pBufferTail - (ULONG)pspdProcessData);
265
266 INFO
267 (
268 "descriptors table contains %d allocated descriptors, combined length %d\n",
269 ProcessData->FdTable.AllocatedDescriptors,
270 sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors
271 );
272
273 memcpy
274 (
275 pBufferTail,
276 ProcessData->FdTable.Descriptors,
277 sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors
278 );
279
280 pBufferTail +=
281 sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors;
282
283 INFO
284 (
285 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
286 sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors,
287 pBufferTail
288 );
289
290 /* extra descriptors data */
291 for(i = 0; ProcessData->FdTable.AllocatedDescriptors; i ++)
292 if(ProcessData->FdTable.Descriptors[i].ExtraData != 0)
293 {
294 INFO
295 (
296 "descriptor %d has %d bytes of associated data\n",
297 i,
298 ProcessData->FdTable.Descriptors[i].ExtraDataSize
299 );
300
301 memcpy
302 (
303 pBufferTail,
304 ProcessData->FdTable.Descriptors[i].ExtraData,
305 ProcessData->FdTable.Descriptors[i].ExtraDataSize
306 );
307
308 pBufferTail += ProcessData->FdTable.Descriptors[i].ExtraDataSize;
309
310 INFO
311 (
312 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
313 ProcessData->FdTable.Descriptors[i].ExtraDataSize,
314 pBufferTail
315 );
316 }
317
318 /* success */
319 *SerializedProcessData = pspdProcessData;
320 }
321
322 /* unserialize a process data block. Dynamic data will be moved into the default
323 heap */
324 NTSTATUS
325 STDCALL
326 __PdxUnserializeProcessData
327 (
328 IN OUT __PPDX_SERIALIZED_PDATA *SerializedProcessData,
329 OUT __PPDX_PDATA *ProcessData OPTIONAL
330 )
331 {
332 int i;
333 int nEnvVarsCount;
334 __PPDX_PDATA ppdReturnBlock;
335 BOOLEAN bInPlace;
336 PBYTE pBufferTail;
337
338 /* no return buffer */
339 if(NULL == ProcessData)
340 {
341 /* perform an in-place conversion */
342 ppdReturnBlock = &((*SerializedProcessData)->ProcessData);
343 bInPlace = TRUE;
344 }
345 else
346 {
347 /* use the provided return buffer */
348 ppdReturnBlock = *ProcessData;
349 bInPlace = FALSE;
350 }
351
352 /* non in-place conversion: copy static data */
353 if(!bInPlace)
354 {
355 memcpy(ppdReturnBlock, *SerializedProcessData, sizeof(*ppdReturnBlock));
356 }
357
358 pBufferTail = &((*SerializedProcessData)->Buffer[0]);
359
360 /* allocate arguments array */
361 ppdReturnBlock->ArgVect = __malloc(ppdReturnBlock->ArgCount * sizeof(char *));
362
363 /* duplicate arguments */
364 for(i = 0; i < ppdReturnBlock->ArgCount; i ++)
365 {
366 int nStrLen = strlen(pBufferTail) + 1;
367 ppdReturnBlock->ArgVect[i] = __malloc(nStrLen);
368 strncpy(ppdReturnBlock->ArgVect[i], pBufferTail, nStrLen);
369 pBufferTail += nStrLen;
370 }
371
372 /* allocate environment array */
373 nEnvVarsCount = ppdReturnBlock->Environment;
374 ppdReturnBlock->Environment = __malloc(nEnvVarsCount * sizeof(char *));
375
376 /* duplicate environment */
377 for(i = 0; i < nEnvVarsCount; i ++)
378 {
379 int nStrLen = strlen(pBufferTail) + 1;
380 ppdReturnBlock->Environment[i] = __malloc(nStrLen);
381 strncpy(ppdReturnBlock->Environment[i], pBufferTail, nStrLen);
382 pBufferTail += nStrLen;
383 }
384
385 /* static buffer for path conversions */
386 ppdReturnBlock->NativePathBuffer.Buffer = __malloc(0xFFFF);
387 ppdReturnBlock->NativePathBuffer.Length = 0;
388 ppdReturnBlock->NativePathBuffer.MaximumLength = 0xFFFF;
389
390 /* current directory */
391 ppdReturnBlock->CurDir.Buffer = __malloc(ppdReturnBlock->CurDir.Length);
392 ppdReturnBlock->CurDir.MaximumLength = ppdReturnBlock->CurDir.Length;
393 memcpy(ppdReturnBlock->CurDir.Buffer, pBufferTail, ppdReturnBlock->CurDir.Length);
394 pBufferTail += ppdReturnBlock->CurDir.Length;
395
396 /* root directory */
397 ppdReturnBlock->RootPath.Buffer = __malloc(ppdReturnBlock->RootPath.Length);
398 ppdReturnBlock->RootPath.MaximumLength = ppdReturnBlock->RootPath.Length;
399 memcpy(ppdReturnBlock->RootPath.Buffer, pBufferTail, ppdReturnBlock->RootPath.Length);
400 pBufferTail += ppdReturnBlock->RootPath.Length;
401
402 /* file descriptors table */
403 ppdReturnBlock->FdTable.Descriptors = __malloc(ppdReturnBlock->FdTable.AllocatedDescriptors * sizeof(__fildes_t));
404 memcpy(ppdReturnBlock->FdTable.Descriptors, pBufferTail, ppdReturnBlock->FdTable.AllocatedDescriptors * sizeof(__fildes_t));
405 pBufferTail += ppdReturnBlock->FdTable.AllocatedDescriptors * sizeof(__fildes_t);
406
407 for(i = 0; i < ppdReturnBlock->FdTable.AllocatedDescriptors; i ++)
408 {
409 if(ppdReturnBlock->FdTable.Descriptors[i].ExtraData != 0)
410 {
411 ppdReturnBlock->FdTable.Descriptors[i].ExtraData = __malloc(ppdReturnBlock->FdTable.Descriptors[i].ExtraDataSize);
412 memcpy(ppdReturnBlock->FdTable.Descriptors[i].ExtraData, pBufferTail, ppdReturnBlock->FdTable.Descriptors[i].ExtraDataSize);
413 pBufferTail += ppdReturnBlock->FdTable.Descriptors[i].ExtraDataSize;
414 }
415 }
416 }
417
418 /* EOF */
419