1 /* $Id: pdata.c,v 1.3 2002/03/21 22:43:13 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
35 UNICODE_STRING wstrEmpty
= {0, 0, NULL
};
36 UNICODE_STRING wstrCommandLine
= {0, 0, NULL
};
37 __fildes_t
* fdDescriptor
;
40 /* RtlInitUnicodeString(&wstrEmpty, L""); */
41 /* TODO: error checking */
43 /* build the command line string from argument count and argument vector */
44 if(ProcessData
->ArgVect
)
48 ANSI_STRING strArgument
;
51 for(i
= 0; i
< ProcessData
->ArgCount
; i
++)
53 RtlInitAnsiString(&strArgument
, ProcessData
->ArgVect
[i
]);
56 bQuoteArg
= (strchr(strArgument
.Buffer
, ' ') != 0);
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)) *
67 wstrCommandLine
.Buffer
= __malloc(wstrCommandLine
.MaximumLength
);
71 wstrCommandLine
.Buffer
=
72 __realloc(wstrCommandLine
.Buffer
, wstrCommandLine
.MaximumLength
);
77 (PWCHAR
)((ULONG
)wstrCommandLine
.Buffer
+ wstrCommandLine
.Length
);
79 /* append the separator if the argument isn't the first */
82 *pwcBufferTail
= L
' ';
86 /* append the opening quote if the argument contains spaces */
89 *pwcBufferTail
= L
'"';
93 mbstowcs(pwcBufferTail
, strArgument
.Buffer
, strArgument
.Length
);
95 /* append closing quote */
98 pwcBufferTail
= (PWCHAR
)((ULONG
)pwcBufferTail
+ strArgument
.Length
* sizeof(WCHAR
));
99 *pwcBufferTail
= L
'"';
102 wstrCommandLine
.Length
= wstrCommandLine
.MaximumLength
;
106 nErrCode
= RtlCreateProcessParameters
120 /* standard input handle */
121 fdDescriptor
= __fdtable_entry_get(&ProcessData
->FdTable
, STDIN_FILENO
);
123 if(fdDescriptor
!= NULL
)
124 (*ProcessParameters
)->InputHandle
= fdDescriptor
->FileHandle
;
126 /* standard output handle */
127 fdDescriptor
= __fdtable_entry_get(&ProcessData
->FdTable
, STDOUT_FILENO
);
129 if(fdDescriptor
!= NULL
)
130 (*ProcessParameters
)->OutputHandle
= fdDescriptor
->FileHandle
;
132 /* standard error handle */
133 fdDescriptor
= __fdtable_entry_get(&ProcessData
->FdTable
, STDERR_FILENO
);
135 if(fdDescriptor
!= NULL
)
136 (*ProcessParameters
)->ErrorHandle
= fdDescriptor
->FileHandle
;
138 /* POSIX+ and NT environments are incompatible, we set the environment to
140 (*ProcessParameters
)->Environment
= NULL
;
142 (*ProcessParameters
)->ConsoleHandle
= (PVOID
)-1;
143 (*ProcessParameters
)->ConsoleFlags
= 0;
145 return (STATUS_SUCCESS
);
148 /* serialize a process data block in a contiguous, page-aligned block, suitable
149 for transfer across processes */
152 __PdxSerializeProcessData
154 IN __PPDX_PDATA ProcessData
,
155 OUT __PPDX_SERIALIZED_PDATA
*SerializedProcessData
158 __PPDX_SERIALIZED_PDATA pspdProcessData
= 0;
161 ULONG ulAllocSize
= sizeof(__PDX_SERIALIZED_PDATA
) - 1;
162 size_t *pnArgLengths
;
163 size_t *pnEnvVarsLengths
;
167 /* calculate buffer length */
168 /* FIXME please! this is the most inefficient way to do it */
171 INFO("serializing arguments\n");
173 if(ProcessData
->ArgVect
!= 0)
175 pnArgLengths
= __malloc(ProcessData
->ArgCount
* sizeof(size_t));
177 for(i
= 0; i
< ProcessData
->ArgCount
; i
++)
181 if(ProcessData
->ArgVect
[i
] == 0)
183 INFO("argument %d is NULL\n", i
);
188 nStrLen
= strlen(ProcessData
->ArgVect
[i
]) + 1;
189 ulAllocSize
+= nStrLen
;
190 pnArgLengths
[i
] = nStrLen
;
194 "argument %d: \"%s\", length %d\n",
196 ProcessData
->ArgVect
[i
],
203 INFO("arguments vector is NULL\n");
206 pnEnvVarsLengths
= NULL
;
209 if(ProcessData
->Environment
== 0)
210 INFO("pointer to environ is NULL\n");
211 else if((ProcessData
->Environment
) == 0)
212 INFO("environ is NULL\n");
215 for(i
= 0; *(ProcessData
->Environment
)[i
] != 0; i
++)
217 int nStrLen
= strlen(*(ProcessData
->Environment
)[i
]) + 1;
218 ulAllocSize
+= nStrLen
;
221 __realloc(pnEnvVarsLengths
, nEnvVarsCount
* sizeof(size_t));
222 pnEnvVarsLengths
[i
] = nStrLen
;
226 "environment variable %d: \"%s\", length %d\n",
228 *(ProcessData
->Environment
)[i
],
233 INFO("(%d environment variables were found)\n", nEnvVarsCount
);
236 /* current directory */
237 ulAllocSize
+= ProcessData
->CurDir
.Length
;
241 "current directory: \"%.*ls\"\n",
242 ProcessData
->CurDir
.Length
/ sizeof(WCHAR
),
243 ProcessData
->CurDir
.Buffer
247 ulAllocSize
+= ProcessData
->RootPath
.Length
;
251 "root directory: \"%.*ls\"\n",
252 ProcessData
->RootPath
.Length
/ sizeof(WCHAR
),
253 ProcessData
->RootPath
.Buffer
256 /* file descriptors table */
257 ulAllocSize
+= sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
;
260 "descriptors table contains %d allocated descriptors, combined length %d\n",
261 ProcessData
->FdTable
.AllocatedDescriptors
,
262 sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
265 /* extra descriptors data */
266 for(i
= 0; ProcessData
->FdTable
.AllocatedDescriptors
; i
++)
267 if(ProcessData
->FdTable
.Descriptors
[i
].ExtraData
!= NULL
)
269 ulAllocSize
+= ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
;
273 "descriptor %d has %d bytes of associated data\n",
275 ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
280 /* allocate return block */
281 INFO("about to allocate %d bytes\n", ulAllocSize
);
283 nErrCode
= NtAllocateVirtualMemory
286 (PVOID
*)&pspdProcessData
,
294 if(!NT_SUCCESS(nErrCode
))
296 ERR("NtAllocateVirtualMemory() failed with status 0x%08X\n", nErrCode
);
297 __free(pnArgLengths
);
298 __free(pnEnvVarsLengths
);
299 *SerializedProcessData
= 0;
303 INFO("%d bytes actually allocated\n", ulAllocSize
);
304 pspdProcessData
->AllocSize
= ulAllocSize
;
308 memcpy(&pspdProcessData
->ProcessData
, ProcessData
, sizeof(__PDX_PDATA
));
311 pBufferTail
= &pspdProcessData
->Buffer
[0];
312 INFO("buffer tail begins at 0x%08X\n", pBufferTail
);
315 pspdProcessData
->ProcessData
.ArgVect
= 0;
317 for(i
= 0; i
< ProcessData
->ArgCount
; i
++)
321 "copying %d bytes of argument %d (\"%s\") to 0x%08X\n",
324 ProcessData
->ArgVect
[i
],
328 strncpy(pBufferTail
, ProcessData
->ArgVect
[i
], pnArgLengths
[i
]);
329 pBufferTail
+= pnArgLengths
[i
];
333 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
340 __free(pnArgLengths
);
343 pspdProcessData
->ProcessData
.Environment
= (char ***)nEnvVarsCount
;
345 for(i
= 0; i
< nEnvVarsCount
; i
++)
349 "copying %d bytes of environment variable %d (\"%s\") to 0x%08X\n",
352 ProcessData
->Environment
[i
],
356 strncpy(pBufferTail
, *ProcessData
->Environment
[i
], pnEnvVarsLengths
[i
]);
357 pBufferTail
+= pnEnvVarsLengths
[i
];
361 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
367 __free(pnEnvVarsLengths
);
369 /* current directory */
372 "copying %d bytes of current directory (\"%.*ls\") to 0x%08X\n",
373 ProcessData
->CurDir
.Length
,
374 ProcessData
->CurDir
.Length
/ sizeof(WCHAR
),
375 ProcessData
->CurDir
.Buffer
,
379 memcpy(pBufferTail
, ProcessData
->CurDir
.Buffer
, ProcessData
->CurDir
.Length
);
380 pBufferTail
+= ProcessData
->CurDir
.Length
;
384 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
385 ProcessData
->CurDir
.Length
,
392 "copying %d bytes of root directory (\"%.*ls\") to 0x%08X\n",
393 ProcessData
->RootPath
.Length
,
394 ProcessData
->RootPath
.Length
/ sizeof(WCHAR
),
395 ProcessData
->RootPath
.Buffer
,
402 ProcessData
->RootPath
.Buffer
,
403 ProcessData
->RootPath
.Length
406 pBufferTail
+= ProcessData
->RootPath
.Length
;
410 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
411 ProcessData
->RootPath
.Length
,
415 /* file descriptors table */
416 /* save the offset to the descriptors array */
417 pspdProcessData
->ProcessData
.FdTable
.Descriptors
=
418 (PVOID
)((ULONG
)pBufferTail
- (ULONG
)pspdProcessData
);
422 "descriptors table contains %d allocated descriptors, combined length %d\n",
423 ProcessData
->FdTable
.AllocatedDescriptors
,
424 sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
430 ProcessData
->FdTable
.Descriptors
,
431 sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
435 sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
;
439 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
440 sizeof(__fildes_t
) * ProcessData
->FdTable
.AllocatedDescriptors
,
444 /* extra descriptors data */
445 for(i
= 0; ProcessData
->FdTable
.AllocatedDescriptors
; i
++)
446 if(ProcessData
->FdTable
.Descriptors
[i
].ExtraData
!= 0)
450 "descriptor %d has %d bytes of associated data\n",
452 ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
458 ProcessData
->FdTable
.Descriptors
[i
].ExtraData
,
459 ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
462 pBufferTail
+= ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
;
466 "buffer tail increased by %d bytes, new tail at 0x%08X\n",
467 ProcessData
->FdTable
.Descriptors
[i
].ExtraDataSize
,
473 *SerializedProcessData
= pspdProcessData
;
475 return (STATUS_SUCCESS
);
478 /* unserialize a process data block. Dynamic data will be moved into the default
482 __PdxUnserializeProcessData
484 IN OUT __PPDX_SERIALIZED_PDATA
*SerializedProcessData
,
485 OUT __PPDX_PDATA
*ProcessData OPTIONAL
490 __PPDX_PDATA ppdReturnBlock
;
494 /* no return buffer */
495 if(NULL
== ProcessData
)
497 /* perform an in-place conversion */
498 ppdReturnBlock
= &((*SerializedProcessData
)->ProcessData
);
503 /* use the provided return buffer */
504 ppdReturnBlock
= *ProcessData
;
508 /* non in-place conversion: copy static data */
511 memcpy(ppdReturnBlock
, *SerializedProcessData
, sizeof(*ppdReturnBlock
));
514 pBufferTail
= &((*SerializedProcessData
)->Buffer
[0]);
516 /* allocate arguments array */
517 ppdReturnBlock
->ArgVect
= __malloc(ppdReturnBlock
->ArgCount
* sizeof(char *));
519 /* duplicate arguments */
520 for(i
= 0; i
< ppdReturnBlock
->ArgCount
; i
++)
522 int nStrLen
= strlen(pBufferTail
) + 1;
523 ppdReturnBlock
->ArgVect
[i
] = __malloc(nStrLen
);
524 strncpy(ppdReturnBlock
->ArgVect
[i
], pBufferTail
, nStrLen
);
525 pBufferTail
+= nStrLen
;
528 /* allocate environment array */
529 nEnvVarsCount
= ppdReturnBlock
->Environment
;
530 ppdReturnBlock
->Environment
= __malloc(nEnvVarsCount
* sizeof(char *));
532 /* duplicate environment */
533 for(i
= 0; i
< nEnvVarsCount
; i
++)
535 int nStrLen
= strlen(pBufferTail
) + 1;
536 ppdReturnBlock
->Environment
[i
] = __malloc(nStrLen
);
537 strncpy(ppdReturnBlock
->Environment
[i
], pBufferTail
, nStrLen
);
538 pBufferTail
+= nStrLen
;
541 /* static buffer for path conversions */
542 ppdReturnBlock
->NativePathBuffer
.Buffer
= __malloc(0xFFFF);
543 ppdReturnBlock
->NativePathBuffer
.Length
= 0;
544 ppdReturnBlock
->NativePathBuffer
.MaximumLength
= 0xFFFF;
546 /* current directory */
547 ppdReturnBlock
->CurDir
.Buffer
= __malloc(ppdReturnBlock
->CurDir
.Length
);
548 ppdReturnBlock
->CurDir
.MaximumLength
= ppdReturnBlock
->CurDir
.Length
;
549 memcpy(ppdReturnBlock
->CurDir
.Buffer
, pBufferTail
, ppdReturnBlock
->CurDir
.Length
);
550 pBufferTail
+= ppdReturnBlock
->CurDir
.Length
;
553 ppdReturnBlock
->RootPath
.Buffer
= __malloc(ppdReturnBlock
->RootPath
.Length
);
554 ppdReturnBlock
->RootPath
.MaximumLength
= ppdReturnBlock
->RootPath
.Length
;
555 memcpy(ppdReturnBlock
->RootPath
.Buffer
, pBufferTail
, ppdReturnBlock
->RootPath
.Length
);
556 pBufferTail
+= ppdReturnBlock
->RootPath
.Length
;
558 /* file descriptors table */
559 ppdReturnBlock
->FdTable
.Descriptors
= __malloc(ppdReturnBlock
->FdTable
.AllocatedDescriptors
* sizeof(__fildes_t
));
560 memcpy(ppdReturnBlock
->FdTable
.Descriptors
, pBufferTail
, ppdReturnBlock
->FdTable
.AllocatedDescriptors
* sizeof(__fildes_t
));
561 pBufferTail
+= ppdReturnBlock
->FdTable
.AllocatedDescriptors
* sizeof(__fildes_t
);
563 for(i
= 0; i
< ppdReturnBlock
->FdTable
.AllocatedDescriptors
; i
++)
565 if(ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraData
!= 0)
567 ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraData
= __malloc(ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraDataSize
);
568 memcpy(ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraData
, pBufferTail
, ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraDataSize
);
569 pBufferTail
+= ppdReturnBlock
->FdTable
.Descriptors
[i
].ExtraDataSize
;