Keep the posix module buildable, and add some CVS sugar for easier scanning.
[reactos.git] / posix / lib / psxdll / misc / pdata.c
1 /* $Id: pdata.c,v 1.6 2002/12/26 18:14:36 robd 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 * 11/03/2002: Added __PdxProcessDataToProcessParameters()
14 * (KJK::Hyperion <noog@libero.it>)
15 */
16
17 #include <ddk/ntddk.h>
18 #include <string.h>
19 #include <unistd.h>
20 #include <psx/fdtable.h>
21 #include <psx/pdata.h>
22 #include <psx/stdlib.h>
23 #include <psx/debug.h>
24
25 NTSTATUS
26 STDCALL
27 __PdxProcessDataToProcessParameters
28 (
29 OUT PRTL_USER_PROCESS_PARAMETERS *ProcessParameters,
30 IN __PPDX_PDATA ProcessData,
31 IN PUNICODE_STRING ImageFile
32 )
33 {
34 NTSTATUS nErrCode;
35 UNICODE_STRING wstrEmpty = {0, 0, NULL};
36 UNICODE_STRING wstrCommandLine = {0, 0, NULL};
37 __fildes_t * fdDescriptor;
38 int i;
39
40 /* RtlInitUnicodeString(&wstrEmpty, L""); */
41 /* TODO: error checking */
42
43 /* build the command line string from argument count and argument vector */
44 if(ProcessData->ArgVect)
45 {
46 BOOL bQuoteArg;
47 BOOL bFirstArg;
48 ANSI_STRING strArgument;
49 PWCHAR pwcBufferTail;
50
51 for(i = 0; i < ProcessData->ArgCount; i ++)
52 {
53 RtlInitAnsiString(&strArgument, ProcessData->ArgVect[i]);
54
55 bFirstArg = (i == 0);
56 bQuoteArg = (strchr(strArgument.Buffer, ' ') != 0);
57
58 /* allocate buffer space for the argument, a blank space if the argument is
59 not the first, and two quotes if the argument contains a space */
60 /* TODO: check this operation for overflow */
61 wstrCommandLine.MaximumLength +=
62 (strArgument.Length + (bFirstArg ? 0 : 1) + (bQuoteArg ? 2 : 0)) *
63 sizeof(WCHAR);
64
65 if(bFirstArg)
66 {
67 wstrCommandLine.Buffer = __malloc(wstrCommandLine.MaximumLength);
68 }
69 else
70 {
71 wstrCommandLine.Buffer =
72 __realloc(wstrCommandLine.Buffer, wstrCommandLine.MaximumLength);
73 }
74
75 /* buffer tail */
76 pwcBufferTail =
77 (PWCHAR)((ULONG)wstrCommandLine.Buffer + wstrCommandLine.Length);
78
79 /* append the separator if the argument isn't the first */
80 if(!bFirstArg)
81 {
82 *pwcBufferTail = L' ';
83 pwcBufferTail ++;
84 }
85
86 /* append the opening quote if the argument contains spaces */
87 if(bQuoteArg)
88 {
89 *pwcBufferTail = L'"';
90 pwcBufferTail ++;
91 }
92
93 mbstowcs(pwcBufferTail, strArgument.Buffer, strArgument.Length);
94
95 /* append closing quote */
96 if(bQuoteArg)
97 {
98 pwcBufferTail = (PWCHAR)((ULONG)pwcBufferTail + strArgument.Length * sizeof(WCHAR));
99 *pwcBufferTail = L'"';
100 }
101
102 wstrCommandLine.Length = wstrCommandLine.MaximumLength;
103 }
104 }
105
106 nErrCode = RtlCreateProcessParameters
107 (
108 ProcessParameters,
109 ImageFile,
110 NULL,
111 &wstrEmpty,
112 &wstrCommandLine,
113 0,
114 &wstrEmpty,
115 &wstrEmpty,
116 &wstrEmpty,
117 &wstrEmpty
118 );
119
120 /* standard input handle */
121 fdDescriptor = __fdtable_entry_get(&ProcessData->FdTable, STDIN_FILENO);
122
123 if(fdDescriptor != NULL)
124 (*ProcessParameters)->hStdInput = fdDescriptor->FileHandle;
125
126 /* standard output handle */
127 fdDescriptor = __fdtable_entry_get(&ProcessData->FdTable, STDOUT_FILENO);
128
129 if(fdDescriptor != NULL)
130 (*ProcessParameters)->hStdOutput = fdDescriptor->FileHandle;
131
132 /* standard error handle */
133 fdDescriptor = __fdtable_entry_get(&ProcessData->FdTable, STDERR_FILENO);
134
135 if(fdDescriptor != NULL)
136 (*ProcessParameters)->hStdError = fdDescriptor->FileHandle;
137
138 /* POSIX+ and NT environments are incompatible, we set the environment to
139 nothing */
140 (*ProcessParameters)->Environment = NULL;
141
142 /*
143 typedef struct _RTL_USER_PROCESS_PARAMETERS {
144 ULONG AllocationSize;
145 ULONG Size;
146 ULONG Flags;
147 ULONG DebugFlags;
148 HANDLE hConsole;
149 ULONG ProcessGroup;
150 HANDLE hStdInput;
151 HANDLE hStdOutput;
152 HANDLE hStdError;
153 UNICODE_STRING CurrentDirectoryName;
154 HANDLE CurrentDirectoryHandle;
155 UNICODE_STRING DllPath;
156 UNICODE_STRING ImagePathName;
157 UNICODE_STRING CommandLine;
158 PWSTR Environment;
159 ULONG dwX;
160 ULONG dwY;
161 ULONG dwXSize;
162 ULONG dwYSize;
163 ULONG dwXCountChars;
164 ULONG dwYCountChars;
165 ULONG dwFillAttribute;
166 ULONG dwFlags;
167 ULONG wShowWindow;
168 UNICODE_STRING WindowTitle;
169 UNICODE_STRING DesktopInfo;
170 UNICODE_STRING ShellInfo;
171 UNICODE_STRING RuntimeInfo;
172 } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS;
173 */
174 (*ProcessParameters)->hConsole = (PVOID)-1;
175 (*ProcessParameters)->Flags = 0;
176
177 return (STATUS_SUCCESS);
178 }
179
180 /* serialize a process data block in a contiguous, page-aligned block, suitable
181 for transfer across processes */
182 NTSTATUS
183 STDCALL
184 __PdxSerializeProcessData
185 (
186 IN __PPDX_PDATA ProcessData,
187 OUT __PPDX_SERIALIZED_PDATA *SerializedProcessData
188 )
189 {
190 __PPDX_SERIALIZED_PDATA pspdProcessData = 0;
191 NTSTATUS nErrCode;
192 PBYTE pBufferTail;
193 ULONG ulAllocSize = sizeof(__PDX_SERIALIZED_PDATA) - 1;
194 size_t *pnArgLengths;
195 size_t *pnEnvVarsLengths;
196 int nEnvVarsCount;
197 int i;
198
199 /* calculate buffer length */
200 /* FIXME please! this is the most inefficient way to do it */
201
202 /* argv */
203 INFO("serializing arguments\n");
204
205 if(ProcessData->ArgVect != 0)
206 {
207 pnArgLengths = __malloc(ProcessData->ArgCount * sizeof(size_t));
208
209 for(i = 0; i < ProcessData->ArgCount; i ++)
210 {
211 int nStrLen;
212
213 if(ProcessData->ArgVect[i] == 0)
214 {
215 INFO("argument %d is NULL\n", i);
216 pnArgLengths[i] = 0;
217 continue;
218 }
219
220 nStrLen = strlen(ProcessData->ArgVect[i]) + 1;
221 ulAllocSize += nStrLen;
222 pnArgLengths[i] = nStrLen;
223
224 INFO
225 (
226 "argument %d: \"%s\", length %d\n",
227 i,
228 ProcessData->ArgVect[i],
229 nStrLen
230 );
231 }
232
233 }
234 else
235 INFO("arguments vector is NULL\n");
236
237 /* environ */
238 pnEnvVarsLengths = NULL;
239 nEnvVarsCount = 0;
240
241 if(ProcessData->Environment == 0)
242 INFO("pointer to environ is NULL\n");
243 else if((ProcessData->Environment) == 0)
244 INFO("environ is NULL\n");
245 else
246 {
247 for(i = 0; *(ProcessData->Environment)[i] != 0; i++)
248 {
249 int nStrLen = strlen(*(ProcessData->Environment)[i]) + 1;
250 ulAllocSize += nStrLen;
251
252 nEnvVarsCount ++;
253 __realloc(pnEnvVarsLengths, nEnvVarsCount * sizeof(size_t));
254 pnEnvVarsLengths[i] = nStrLen;
255
256 INFO
257 (
258 "environment variable %d: \"%s\", length %d\n",
259 i,
260 *(ProcessData->Environment)[i],
261 nStrLen
262 );
263 }
264
265 INFO("(%d environment variables were found)\n", nEnvVarsCount);
266 }
267
268 /* current directory */
269 ulAllocSize += ProcessData->CurDir.Length;
270
271 INFO
272 (
273 "current directory: \"%.*ls\"\n",
274 ProcessData->CurDir.Length / sizeof(WCHAR),
275 ProcessData->CurDir.Buffer
276 );
277
278 /* root directory */
279 ulAllocSize += ProcessData->RootPath.Length;
280
281 INFO
282 (
283 "root directory: \"%.*ls\"\n",
284 ProcessData->RootPath.Length / sizeof(WCHAR),
285 ProcessData->RootPath.Buffer
286 );
287
288 /* file descriptors table */
289 ulAllocSize += sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors;
290 INFO
291 (
292 "descriptors table contains %d allocated descriptors, combined length %d\n",
293 ProcessData->FdTable.AllocatedDescriptors,
294 sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors
295 );
296
297 /* extra descriptors data */
298 for(i = 0; ProcessData->FdTable.AllocatedDescriptors; i ++)
299 if(ProcessData->FdTable.Descriptors[i].ExtraData != NULL)
300 {
301 ulAllocSize += ProcessData->FdTable.Descriptors[i].ExtraDataSize;
302
303 INFO
304 (
305 "descriptor %d has %d bytes of associated data\n",
306 i,
307 ProcessData->FdTable.Descriptors[i].ExtraDataSize
308 );
309
310 }
311
312 /* allocate return block */
313 INFO("about to allocate %d bytes\n", ulAllocSize);
314
315 nErrCode = NtAllocateVirtualMemory
316 (
317 NtCurrentProcess(),
318 (PVOID *)&pspdProcessData,
319 0,
320 &ulAllocSize,
321 MEM_COMMIT,
322 PAGE_READWRITE
323 );
324
325 /* failure */
326 if(!NT_SUCCESS(nErrCode))
327 {
328 ERR("NtAllocateVirtualMemory() failed with status 0x%08X\n", nErrCode);
329 __free(pnArgLengths);
330 __free(pnEnvVarsLengths);
331 *SerializedProcessData = 0;
332 return nErrCode;
333 }
334
335 INFO("%d bytes actually allocated\n", ulAllocSize);
336 pspdProcessData->AllocSize = ulAllocSize;
337
338 /* copy data */
339 /* static data */
340 memcpy(&pspdProcessData->ProcessData, ProcessData, sizeof(__PDX_PDATA));
341
342 /* buffers */
343 pBufferTail = &pspdProcessData->Buffer[0];
344 INFO("buffer tail begins at 0x%08X\n", pBufferTail);
345
346 /* argv */
347 pspdProcessData->ProcessData.ArgVect = 0;
348
349 for(i = 0; i < ProcessData->ArgCount; i ++)
350 {
351 INFO
352 (
353 "copying %d bytes of argument %d (\"%s\") to 0x%08X\n",
354 pnArgLengths[i],
355 i,
356 ProcessData->ArgVect[i],
357 pBufferTail
358 );
359
360 strncpy(pBufferTail, ProcessData->ArgVect[i], pnArgLengths[i]);
361 pBufferTail += pnArgLengths[i];
362
363 INFO
364 (
365 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
366 pnArgLengths[i],
367 pBufferTail
368 );
369
370 }
371
372 __free(pnArgLengths);
373
374 /* environ */
375 pspdProcessData->ProcessData.Environment = (char ***)nEnvVarsCount;
376
377 for(i = 0; i < nEnvVarsCount; i ++)
378 {
379 INFO
380 (
381 "copying %d bytes of environment variable %d (\"%s\") to 0x%08X\n",
382 pnEnvVarsLengths[i],
383 i,
384 ProcessData->Environment[i],
385 pBufferTail
386 );
387
388 strncpy(pBufferTail, *ProcessData->Environment[i], pnEnvVarsLengths[i]);
389 pBufferTail += pnEnvVarsLengths[i];
390
391 INFO
392 (
393 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
394 pnEnvVarsLengths[i],
395 pBufferTail
396 );
397 }
398
399 __free(pnEnvVarsLengths);
400
401 /* current directory */
402 INFO
403 (
404 "copying %d bytes of current directory (\"%.*ls\") to 0x%08X\n",
405 ProcessData->CurDir.Length,
406 ProcessData->CurDir.Length / sizeof(WCHAR),
407 ProcessData->CurDir.Buffer,
408 pBufferTail
409 );
410
411 memcpy(pBufferTail, ProcessData->CurDir.Buffer, ProcessData->CurDir.Length);
412 pBufferTail += ProcessData->CurDir.Length;
413
414 INFO
415 (
416 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
417 ProcessData->CurDir.Length,
418 pBufferTail
419 );
420
421 /* root directory */
422 INFO
423 (
424 "copying %d bytes of root directory (\"%.*ls\") to 0x%08X\n",
425 ProcessData->RootPath.Length,
426 ProcessData->RootPath.Length / sizeof(WCHAR),
427 ProcessData->RootPath.Buffer,
428 pBufferTail
429 );
430
431 memcpy
432 (
433 pBufferTail,
434 ProcessData->RootPath.Buffer,
435 ProcessData->RootPath.Length
436 );
437
438 pBufferTail += ProcessData->RootPath.Length;
439
440 INFO
441 (
442 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
443 ProcessData->RootPath.Length,
444 pBufferTail
445 );
446
447 /* file descriptors table */
448 /* save the offset to the descriptors array */
449 pspdProcessData->ProcessData.FdTable.Descriptors =
450 (PVOID)((ULONG)pBufferTail - (ULONG)pspdProcessData);
451
452 INFO
453 (
454 "descriptors table contains %d allocated descriptors, combined length %d\n",
455 ProcessData->FdTable.AllocatedDescriptors,
456 sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors
457 );
458
459 memcpy
460 (
461 pBufferTail,
462 ProcessData->FdTable.Descriptors,
463 sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors
464 );
465
466 pBufferTail +=
467 sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors;
468
469 INFO
470 (
471 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
472 sizeof(__fildes_t) * ProcessData->FdTable.AllocatedDescriptors,
473 pBufferTail
474 );
475
476 /* extra descriptors data */
477 for(i = 0; ProcessData->FdTable.AllocatedDescriptors; i ++)
478 if(ProcessData->FdTable.Descriptors[i].ExtraData != 0)
479 {
480 INFO
481 (
482 "descriptor %d has %d bytes of associated data\n",
483 i,
484 ProcessData->FdTable.Descriptors[i].ExtraDataSize
485 );
486
487 memcpy
488 (
489 pBufferTail,
490 ProcessData->FdTable.Descriptors[i].ExtraData,
491 ProcessData->FdTable.Descriptors[i].ExtraDataSize
492 );
493
494 pBufferTail += ProcessData->FdTable.Descriptors[i].ExtraDataSize;
495
496 INFO
497 (
498 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
499 ProcessData->FdTable.Descriptors[i].ExtraDataSize,
500 pBufferTail
501 );
502 }
503
504 /* success */
505 *SerializedProcessData = pspdProcessData;
506
507 return (STATUS_SUCCESS);
508 }
509
510 /* unserialize a process data block. Dynamic data will be moved into the default
511 heap */
512 NTSTATUS
513 STDCALL
514 __PdxUnserializeProcessData
515 (
516 IN OUT __PPDX_SERIALIZED_PDATA *SerializedProcessData,
517 OUT __PPDX_PDATA *ProcessData OPTIONAL
518 )
519 {
520 int i;
521 int nEnvVarsCount;
522 __PPDX_PDATA ppdReturnBlock;
523 BOOLEAN bInPlace;
524 PBYTE pBufferTail;
525
526 /* no return buffer */
527 if(NULL == ProcessData)
528 {
529 /* perform an in-place conversion */
530 ppdReturnBlock = &((*SerializedProcessData)->ProcessData);
531 bInPlace = TRUE;
532 }
533 else
534 {
535 /* use the provided return buffer */
536 ppdReturnBlock = *ProcessData;
537 bInPlace = FALSE;
538 }
539
540 /* non in-place conversion: copy static data */
541 if(!bInPlace)
542 {
543 memcpy(ppdReturnBlock, *SerializedProcessData, sizeof(*ppdReturnBlock));
544 }
545
546 pBufferTail = &((*SerializedProcessData)->Buffer[0]);
547
548 /* allocate arguments array */
549 ppdReturnBlock->ArgVect = __malloc(ppdReturnBlock->ArgCount * sizeof(char *));
550
551 /* duplicate arguments */
552 for(i = 0; i < ppdReturnBlock->ArgCount; i ++)
553 {
554 int nStrLen = strlen(pBufferTail) + 1;
555 ppdReturnBlock->ArgVect[i] = __malloc(nStrLen);
556 strncpy(ppdReturnBlock->ArgVect[i], pBufferTail, nStrLen);
557 pBufferTail += nStrLen;
558 }
559
560 /* allocate environment array */
561 nEnvVarsCount = ppdReturnBlock->Environment;
562 ppdReturnBlock->Environment = __malloc(nEnvVarsCount * sizeof(char *));
563
564 /* duplicate environment */
565 for(i = 0; i < nEnvVarsCount; i ++)
566 {
567 int nStrLen = strlen(pBufferTail) + 1;
568 ppdReturnBlock->Environment[i] = __malloc(nStrLen);
569 strncpy(ppdReturnBlock->Environment[i], pBufferTail, nStrLen);
570 pBufferTail += nStrLen;
571 }
572
573 /* static buffer for path conversions */
574 ppdReturnBlock->NativePathBuffer.Buffer = __malloc(0xFFFF);
575 ppdReturnBlock->NativePathBuffer.Length = 0;
576 ppdReturnBlock->NativePathBuffer.MaximumLength = 0xFFFF;
577
578 /* current directory */
579 ppdReturnBlock->CurDir.Buffer = __malloc(ppdReturnBlock->CurDir.Length);
580 ppdReturnBlock->CurDir.MaximumLength = ppdReturnBlock->CurDir.Length;
581 memcpy(ppdReturnBlock->CurDir.Buffer, pBufferTail, ppdReturnBlock->CurDir.Length);
582 pBufferTail += ppdReturnBlock->CurDir.Length;
583
584 /* root directory */
585 ppdReturnBlock->RootPath.Buffer = __malloc(ppdReturnBlock->RootPath.Length);
586 ppdReturnBlock->RootPath.MaximumLength = ppdReturnBlock->RootPath.Length;
587 memcpy(ppdReturnBlock->RootPath.Buffer, pBufferTail, ppdReturnBlock->RootPath.Length);
588 pBufferTail += ppdReturnBlock->RootPath.Length;
589
590 /* file descriptors table */
591 ppdReturnBlock->FdTable.Descriptors = __malloc(ppdReturnBlock->FdTable.AllocatedDescriptors * sizeof(__fildes_t));
592 memcpy(ppdReturnBlock->FdTable.Descriptors, pBufferTail, ppdReturnBlock->FdTable.AllocatedDescriptors * sizeof(__fildes_t));
593 pBufferTail += ppdReturnBlock->FdTable.AllocatedDescriptors * sizeof(__fildes_t);
594
595 for(i = 0; i < ppdReturnBlock->FdTable.AllocatedDescriptors; i ++)
596 {
597 if(ppdReturnBlock->FdTable.Descriptors[i].ExtraData != 0)
598 {
599 ppdReturnBlock->FdTable.Descriptors[i].ExtraData = __malloc(ppdReturnBlock->FdTable.Descriptors[i].ExtraDataSize);
600 memcpy(ppdReturnBlock->FdTable.Descriptors[i].ExtraData, pBufferTail, ppdReturnBlock->FdTable.Descriptors[i].ExtraDataSize);
601 pBufferTail += ppdReturnBlock->FdTable.Descriptors[i].ExtraDataSize;
602 }
603 }
604 }
605
606 /* EOF */
607