1 /* $Id: pdata.c,v 1.2 2002/03/11 20:45:07 hyperion Exp $
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>
11 * 07/03/2002: Added __PdxUnserializeProcessData() (KJK::Hyperion
13 * 11/03/2002: Added __PdxProcessDataToProcessParameters()
14 * (KJK::Hyperion <noog@libero.it>)
17 #include <ddk/ntddk.h>
20 #include <psx/fdtable.h>
21 #include <psx/pdata.h>
22 #include <psx/stdlib.h>
23 #include <psx/debug.h>
27 __PdxProcessDataToProcessParameters
29 OUT PRTL_USER_PROCESS_PARAMETERS
*ProcessParameters
,
30 IN __PPDX_PDATA ProcessData
,
31 IN PUNICODE_STRING ImageFile
34 UNICODE_STRING wstrEmpty
= {0, 0, NULL
};
35 UNICODE_STRING wstrCommandLine
= {0, 0, NULL
};
37 __fildes_t
* fdDescriptor
;
40 /* TODO: error checking */
42 /* build the command line string from argument count and argument vector */
43 if(ProcessData
->ArgVect
)
47 ANSI_STRING strArgument
;
50 for(i
= 0; i
< ProcessData
->ArgCount
; i
++)
52 RtlInitAnsiString(&strArgument
, ProcessData
->ArgVect
[i
]);
55 bQuoteArg
= (strchr(strArgument
.Buffer
, ' ') != 0);
57 /* allocate buffer space for the argument, a blank space if the argument is
58 not the first, and two quotes if the argument contains a space */
59 /* TODO: check this operation for overflow */
60 wstrCommandLine
.MaximumLength
+=
61 (strArgument
.Length
+ (bFirstArg
? 0 : 1) + (bQuoteArg
? 2 : 0)) *
66 wstrCommandLine
.Buffer
= __malloc(wstrCommandLine
.MaximumLength
);
70 wstrCommandLine
.Buffer
=
71 __realloc(wstrCommandLine
.Buffer
, wstrCommandLine
.MaximumLength
);
76 (PWCHAR
)((ULONG
)wstrCommandLine
.Buffer
+ wstrCommandLine
.Length
);
78 /* append the separator if the argument isn't the first */
81 *pwcBufferTail
= L
' ';
85 /* append the opening quote if the argument contains spaces */
88 *pwcBufferTail
= L
'"';
92 mbstowcs(pwcBufferTail
, strArgument
.Buffer
, strArgument
.Length
);
94 /* append closing quote */
97 pwcBufferTail
= (PWCHAR
)((ULONG
)pwcBufferTail
+ strArgument
.Length
* sizeof(WCHAR
));
98 *pwcBufferTail
= L
'"';
101 wstrCommandLine
.Length
= wstrCommandLine
.MaximumLength
;
106 wstrCommandLine
.MaximumLength
= wstrCommandLine
.Length
+ sizeof(WCHAR
);
107 wstrCommandLine
.Buffer
= __realloc(wstrCommandLine
.Buffer
, wstrCommandLine
.MaximumLength
);
108 wstrCommandLine
.Buffer
[wstrCommandLine
.Length
/ sizeof(WCHAR
)] = 0;
110 INFO("command line is \"%ls\"\n", wstrCommandLine
.Buffer
);
113 RtlCreateProcessParameters
127 /* standard input handle */
128 fdDescriptor
= __fdtable_entry_get(&ProcessData
->FdTable
, STDIN_FILENO
);
130 if(fdDescriptor
!= NULL
)
131 (*ProcessParameters
)->InputHandle
= fdDescriptor
->FileHandle
;
133 /* standard output handle */
134 fdDescriptor
= __fdtable_entry_get(&ProcessData
->FdTable
, STDOUT_FILENO
);
136 if(fdDescriptor
!= NULL
)
137 (*ProcessParameters
)->OutputHandle
= fdDescriptor
->FileHandle
;
139 /* standard error handle */
140 fdDescriptor
= __fdtable_entry_get(&ProcessData
->FdTable
, STDERR_FILENO
);
142 if(fdDescriptor
!= NULL
)
143 (*ProcessParameters
)->ErrorHandle
= fdDescriptor
->FileHandle
;
145 /* POSIX+ and NT environments are incompatible, we set the environment to
147 (*ProcessParameters
)->Environment
= NULL
;
149 (*ProcessParameters
)->ConsoleHandle
= (PVOID
)-1;
150 (*ProcessParameters
)->ConsoleFlags
= 0;
152 return (STATUS_SUCCESS
);
155 /* serialize a process data block in a contiguous, page-aligned block, suitable
156 for transfer across processes */
159 __PdxSerializeProcessData
161 IN __PPDX_PDATA ProcessData
,
162 OUT __PPDX_SERIALIZED_PDATA
*SerializedProcessData
165 __PPDX_SERIALIZED_PDATA pspdProcessData
= 0;
168 ULONG ulAllocSize
= sizeof(__PDX_SERIALIZED_PDATA
) - 1;
169 size_t *pnArgLengths
;
170 size_t *pnEnvVarsLengths
;
174 /* calculate buffer length */
175 /* FIXME please! this is the most inefficient way to do it */
178 INFO("serializing arguments\n");
180 if(ProcessData
->ArgVect
!= 0)
182 pnArgLengths
= __malloc(ProcessData
->ArgCount
* sizeof(size_t));
184 for(i
= 0; i
< ProcessData
->ArgCount
; i
++)
188 if(ProcessData
->ArgVect
[i
] == 0)
190 INFO("argument %d is NULL\n", i
);
195 nStrLen
= strlen(ProcessData
->ArgVect
[i
]) + 1;
196 ulAllocSize
+= nStrLen
;
197 pnArgLengths
[i
] = nStrLen
;
201 "argument %d: \"%s\", length %d\n",
203 ProcessData
->ArgVect
[i
],
210 INFO("arguments vector is NULL\n");
213 pnEnvVarsLengths
= NULL
;
216 if(ProcessData
->Environment
== 0)
217 INFO("pointer to environ is NULL\n");
218 else if((ProcessData
->Environment
) == 0)
219 INFO("environ is NULL\n");
222 for(i
= 0; *(ProcessData
->Environment
)[i
] != 0; i
++)
224 int nStrLen
= strlen(*(ProcessData
->Environment
)[i
]) + 1;
225 ulAllocSize
+= nStrLen
;
228 __realloc(pnEnvVarsLengths
, nEnvVarsCount
* sizeof(size_t));
229 pnEnvVarsLengths
[i
] = nStrLen
;
233 "environment variable %d: \"%s\", length %d\n",
235 *(ProcessData
->Environment
)[i
],
240 INFO("(%d environment variables were found)\n", nEnvVarsCount
);
243 /* current directory */
244 ulAllocSize
+= ProcessData
->CurDir
.Length
;
248 "current directory: \"%.*ls\"\n",
249 ProcessData
->CurDir
.Length
/ sizeof(WCHAR
),
250 ProcessData
->CurDir
.Buffer
254 ulAllocSize
+= ProcessData
->RootPath
.Length
;
258 "root directory: \"%.*ls\"\n",
259 ProcessData
->RootPath
.Length
/ sizeof(WCHAR
),
260 ProcessData
->RootPath
.Buffer
263 /* file descriptors table */
264 ulAllocSize
+= sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
;
267 "descriptors table contains %d allocated descriptors, combined length %d\n",
268 ProcessData
->FdTable
.AllocatedDescriptors
,
269 sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
272 /* extra descriptors data */
273 for(i
= 0; ProcessData
->FdTable
.AllocatedDescriptors
; i
++)
274 if(ProcessData
->FdTable
.Descriptors
[i
].ExtraData
!= NULL
)
276 ulAllocSize
+= ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
;
280 "descriptor %d has %d bytes of associated data\n",
282 ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
287 /* allocate return block */
288 INFO("about to allocate %d bytes\n", ulAllocSize
);
290 nErrCode
= NtAllocateVirtualMemory
293 (PVOID
*)&pspdProcessData
,
301 if(!NT_SUCCESS(nErrCode
))
303 ERR("NtAllocateVirtualMemory() failed with status 0x%08X\n", nErrCode
);
304 __free(pnArgLengths
);
305 __free(pnEnvVarsLengths
);
306 *SerializedProcessData
= 0;
310 INFO("%d bytes actually allocated\n", ulAllocSize
);
311 pspdProcessData
->AllocSize
= ulAllocSize
;
315 memcpy(&pspdProcessData
->ProcessData
, ProcessData
, sizeof(__PDX_PDATA
));
318 pBufferTail
= &pspdProcessData
->Buffer
[0];
319 INFO("buffer tail begins at 0x%08X\n", pBufferTail
);
322 pspdProcessData
->ProcessData
.ArgVect
= 0;
324 for(i
= 0; i
< ProcessData
->ArgCount
; i
++)
328 "copying %d bytes of argument %d (\"%s\") to 0x%08X\n",
331 ProcessData
->ArgVect
[i
],
335 strncpy(pBufferTail
, ProcessData
->ArgVect
[i
], pnArgLengths
[i
]);
336 pBufferTail
+= pnArgLengths
[i
];
340 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
347 __free(pnArgLengths
);
350 pspdProcessData
->ProcessData
.Environment
= (char ***)nEnvVarsCount
;
352 for(i
= 0; i
< nEnvVarsCount
; i
++)
356 "copying %d bytes of environment variable %d (\"%s\") to 0x%08X\n",
359 ProcessData
->Environment
[i
],
363 strncpy(pBufferTail
, *ProcessData
->Environment
[i
], pnEnvVarsLengths
[i
]);
364 pBufferTail
+= pnEnvVarsLengths
[i
];
368 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
374 __free(pnEnvVarsLengths
);
376 /* current directory */
379 "copying %d bytes of current directory (\"%.*ls\") to 0x%08X\n",
380 ProcessData
->CurDir
.Length
,
381 ProcessData
->CurDir
.Length
/ sizeof(WCHAR
),
382 ProcessData
->CurDir
.Buffer
,
386 memcpy(pBufferTail
, ProcessData
->CurDir
.Buffer
, ProcessData
->CurDir
.Length
);
387 pBufferTail
+= ProcessData
->CurDir
.Length
;
391 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
392 ProcessData
->CurDir
.Length
,
399 "copying %d bytes of root directory (\"%.*ls\") to 0x%08X\n",
400 ProcessData
->RootPath
.Length
,
401 ProcessData
->RootPath
.Length
/ sizeof(WCHAR
),
402 ProcessData
->RootPath
.Buffer
,
409 ProcessData
->RootPath
.Buffer
,
410 ProcessData
->RootPath
.Length
413 pBufferTail
+= ProcessData
->RootPath
.Length
;
417 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
418 ProcessData
->RootPath
.Length
,
422 /* file descriptors table */
423 /* save the offset to the descriptors array */
424 pspdProcessData
->ProcessData
.FdTable
.Descriptors
=
425 (PVOID
)((ULONG
)pBufferTail
- (ULONG
)pspdProcessData
);
429 "descriptors table contains %d allocated descriptors, combined length %d\n",
430 ProcessData
->FdTable
.AllocatedDescriptors
,
431 sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
437 ProcessData
->FdTable
.Descriptors
,
438 sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
442 sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
;
446 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
447 sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
,
451 /* extra descriptors data */
452 for(i
= 0; ProcessData
->FdTable
.AllocatedDescriptors
; i
++)
453 if(ProcessData
->FdTable
.Descriptors
[i
].ExtraData
!= 0)
457 "descriptor %d has %d bytes of associated data\n",
459 ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
465 ProcessData
->FdTable
.Descriptors
[i
].ExtraData
,
466 ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
469 pBufferTail
+= ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
;
473 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
474 ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
,
480 *SerializedProcessData
= pspdProcessData
;
483 /* unserialize a process data block. Dynamic data will be moved into the default
487 __PdxUnserializeProcessData
489 IN OUT __PPDX_SERIALIZED_PDATA
*SerializedProcessData
,
490 OUT __PPDX_PDATA
*ProcessData OPTIONAL
495 __PPDX_PDATA ppdReturnBlock
;
499 /* no return buffer */
500 if(NULL
== ProcessData
)
502 /* perform an in-place conversion */
503 ppdReturnBlock
= &((*SerializedProcessData
)->ProcessData
);
508 /* use the provided return buffer */
509 ppdReturnBlock
= *ProcessData
;
513 /* non in-place conversion: copy static data */
516 memcpy(ppdReturnBlock
, *SerializedProcessData
, sizeof(*ppdReturnBlock
));
519 pBufferTail
= &((*SerializedProcessData
)->Buffer
[0]);
521 /* allocate arguments array */
522 ppdReturnBlock
->ArgVect
= __malloc(ppdReturnBlock
->ArgCount
* sizeof(char *));
524 /* duplicate arguments */
525 for(i
= 0; i
< ppdReturnBlock
->ArgCount
; i
++)
527 int nStrLen
= strlen(pBufferTail
) + 1;
528 ppdReturnBlock
->ArgVect
[i
] = __malloc(nStrLen
);
529 strncpy(ppdReturnBlock
->ArgVect
[i
], pBufferTail
, nStrLen
);
530 pBufferTail
+= nStrLen
;
533 /* allocate environment array */
534 nEnvVarsCount
= ppdReturnBlock
->Environment
;
535 ppdReturnBlock
->Environment
= __malloc(nEnvVarsCount
* sizeof(char *));
537 /* duplicate environment */
538 for(i
= 0; i
< nEnvVarsCount
; i
++)
540 int nStrLen
= strlen(pBufferTail
) + 1;
541 ppdReturnBlock
->Environment
[i
] = __malloc(nStrLen
);
542 strncpy(ppdReturnBlock
->Environment
[i
], pBufferTail
, nStrLen
);
543 pBufferTail
+= nStrLen
;
546 /* static buffer for path conversions */
547 ppdReturnBlock
->NativePathBuffer
.Buffer
= __malloc(0xFFFF);
548 ppdReturnBlock
->NativePathBuffer
.Length
= 0;
549 ppdReturnBlock
->NativePathBuffer
.MaximumLength
= 0xFFFF;
551 /* current directory */
552 ppdReturnBlock
->CurDir
.Buffer
= __malloc(ppdReturnBlock
->CurDir
.Length
);
553 ppdReturnBlock
->CurDir
.MaximumLength
= ppdReturnBlock
->CurDir
.Length
;
554 memcpy(ppdReturnBlock
->CurDir
.Buffer
, pBufferTail
, ppdReturnBlock
->CurDir
.Length
);
555 pBufferTail
+= ppdReturnBlock
->CurDir
.Length
;
558 ppdReturnBlock
->RootPath
.Buffer
= __malloc(ppdReturnBlock
->RootPath
.Length
);
559 ppdReturnBlock
->RootPath
.MaximumLength
= ppdReturnBlock
->RootPath
.Length
;
560 memcpy(ppdReturnBlock
->RootPath
.Buffer
, pBufferTail
, ppdReturnBlock
->RootPath
.Length
);
561 pBufferTail
+= ppdReturnBlock
->RootPath
.Length
;
563 /* file descriptors table */
564 ppdReturnBlock
->FdTable
.Descriptors
= __malloc(ppdReturnBlock
->FdTable
.AllocatedDescriptors
* sizeof(__fildes_t
));
565 memcpy(ppdReturnBlock
->FdTable
.Descriptors
, pBufferTail
, ppdReturnBlock
->FdTable
.AllocatedDescriptors
* sizeof(__fildes_t
));
566 pBufferTail
+= ppdReturnBlock
->FdTable
.AllocatedDescriptors
* sizeof(__fildes_t
);
568 for(i
= 0; i
< ppdReturnBlock
->FdTable
.AllocatedDescriptors
; i
++)
570 if(ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraData
!= 0)
572 ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraData
= __malloc(ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraDataSize
);
573 memcpy(ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraData
, pBufferTail
, ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraDataSize
);
574 pBufferTail
+= ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraDataSize
;