windows-nt/Source/XPSP1/NT/base/subsys/posix/client/dllproc.c
2020-09-26 16:20:57 +08:00

1266 lines
28 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
dllproc.c
Abstract:
This module implements POSIX process structure APIs
Author:
Mark Lucovsky (markl) 27-Jun-1989
Revision History:
--*/
#include <sys\utsname.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <stdarg.h>
#ifdef _ALPHA_
#include "psxalpha.h"
#endif
#ifdef _MIPS_
#include "psxmips.h"
#endif
#ifdef _PPC_
#include "psxppc.h"
#endif
#ifdef _X86_
#include "psxi386.h"
#endif
#ifdef _IA64_
#include "psxia64.h"
#endif
#include "psxdll.h"
void
__cdecl
_exit(int status)
{
PSX_API_MSG m;
PPSX_EXIT_MSG args;
NTSTATUS st;
args = &m.u.Exit;
PSX_FORMAT_API_MSG(m, PsxExitApi, sizeof(*args));
args->ExitStatus = (ULONG)status;
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
if (!NT_SUCCESS(st)) {
KdPrint(("PSXDLL: _exit: 0x%x\n", st));
}
#endif
NtTerminateProcess(NtCurrentProcess(), 0);
}
gid_t
__cdecl
getegid(void)
{
PSX_API_MSG m;
PPSX_GETIDS_MSG args;
NTSTATUS st;
args = &m.u.GetIds;
PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
return args->EffectiveGid;
}
gid_t
__cdecl
getgid(void)
{
PSX_API_MSG m;
PPSX_GETIDS_MSG args;
NTSTATUS st;
args = &m.u.GetIds;
PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
return args->RealGid;
}
uid_t
__cdecl
geteuid(void)
{
PSX_API_MSG m;
PPSX_GETIDS_MSG args;
NTSTATUS st;
args = &m.u.GetIds;
PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
return args->EffectiveUid;
}
uid_t
__cdecl
getuid(void)
{
PSX_API_MSG m;
PPSX_GETIDS_MSG args;
NTSTATUS st;
args = &m.u.GetIds;
PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
return args->RealUid;
}
pid_t
__cdecl
getppid(void)
{
PSX_API_MSG m;
PPSX_GETIDS_MSG args;
NTSTATUS st;
args = &m.u.GetIds;
PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
return args->ParentPid;
}
pid_t
__cdecl
getpid(void)
{
PSX_API_MSG m;
PPSX_GETIDS_MSG args;
NTSTATUS st;
args = &m.u.GetIds;
PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
return args->Pid;
}
pid_t
__cdecl
getpgrp(void)
{
PSX_API_MSG m;
PPSX_GETIDS_MSG args;
NTSTATUS st;
args = &m.u.GetIds;
PSX_FORMAT_API_MSG(m, PsxGetIdsApi, sizeof(*args));
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
return args->GroupId;
}
pid_t
__cdecl
setsid(void)
{
PSX_API_MSG m;
NTSTATUS st;
PSX_FORMAT_API_MSG(m, PsxSetSidApi, 0);
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
if (m.Error) {
errno = m.Error;
return -1;
}
return (pid_t)m.ReturnValue;
}
int
__cdecl
setpgid(pid_t pid, pid_t pgid)
{
PSX_API_MSG m;
PPSX_SETPGROUPID_MSG args;
NTSTATUS st;
args = &m.u.SetPGroupId;
PSX_FORMAT_API_MSG(m, PsxSetPGroupIdApi, sizeof(*args));
args->Pid = pid;
args->Pgid = pgid;
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
if (m.Error) {
errno = (int)m.Error;
return -1;
}
return (int)m.ReturnValue;
}
pid_t
__cdecl
waitpid(pid_t pid, int *stat_loc, int options)
{
PSX_API_MSG m;
PPSX_WAITPID_MSG args;
NTSTATUS st;
args = &m.u.WaitPid;
PSX_FORMAT_API_MSG(m, PsxWaitPidApi, sizeof(*args));
args->Pid = pid;
args->Options = options;
for (;;) {
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
if (!NT_SUCCESS(st)) {
KdPrint(("PSXDLL: waitpid: 0x%x\n", st));
}
ASSERT(NT_SUCCESS(st));
#endif
if (EINTR == m.Error && SIGCONT == m.Signal) {
// We were stopped and then continued. Continue
// waiting.
PSX_FORMAT_API_MSG(m, PsxWaitPidApi, sizeof(*args));
continue;
}
if (m.Error) {
errno = (int)m.Error;
return -1;
}
if (NULL != stat_loc) {
try {
*stat_loc = args->StatLocValue;
} except (EXCEPTION_EXECUTE_HANDLER) {
errno = EFAULT;
m.ReturnValue = (ULONG)-1;
}
}
return (int)m.ReturnValue;
}
}
pid_t
__cdecl
wait(int *stat_loc)
{
PSX_API_MSG m;
PPSX_WAITPID_MSG args;
NTSTATUS st;
args = &m.u.WaitPid;
PSX_FORMAT_API_MSG(m, PsxWaitPidApi, sizeof(*args));
args->Pid = (pid_t)-1;
args->Options = (pid_t)0;
for (;;) {
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
if (!NT_SUCCESS(st)) {
KdPrint(("PSXDLL: wait: NtRequest: 0x%x\n", st));
}
ASSERT(NT_SUCCESS(st));
#endif
if (EINTR == m.Error && SIGCONT == m.Signal) {
// We were stopped and continued. Continue waiting.
PSX_FORMAT_API_MSG(m, PsxWaitPidApi, sizeof(*args));
continue;
}
if (m.Error) {
errno = (int)m.Error;
return -1;
}
if (ARGUMENT_PRESENT(stat_loc)) {
try {
*stat_loc = args->StatLocValue;
} except (EXCEPTION_EXECUTE_HANDLER) {
errno = EFAULT;
m.ReturnValue = (ULONG)-1;
}
}
return (int)m.ReturnValue;
}
}
pid_t
__cdecl
fork(void)
{
PSX_API_MSG m;
NTSTATUS st;
PPSX_FORK_MSG args;
PTEB ThreadInfo;
args = &m.u.Fork;
again:
PSX_FORMAT_API_MSG(m, PsxForkApi, sizeof(*args));
ThreadInfo = NtCurrentTeb();
args->StackBase = ThreadInfo->NtTib.StackBase;
args->StackLimit = ThreadInfo->NtTib.StackLimit;
args->StackAllocationBase = ThreadInfo->DeallocationStack;
#ifdef _IA64_
args->BStoreLimit = ThreadInfo->BStoreLimit;
#endif
try {
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
} except (EXCEPTION_EXECUTE_HANDLER) {
KdPrint(("PSXDLL: fork: took an exception\n"));
KdPrint(("PSXDLL: exception is 0x%x\n", GetExceptionCode()));
}
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
if (st == PSX_FORK_RETURN) {
st = PsxConnectToServer();
if (!NT_SUCCESS(st)) {
KdPrint(("PsxConnectToServer: 0x%x\n", st));
NtTerminateProcess(NtCurrentProcess(), 1);
ASSERT(0);
}
// take any pending signals now.
PdxNullPosixApi();
return 0;
}
if (EINTR == m.Error) {
// try again.
goto again;
}
if (m.Error) {
errno = (int)m.Error;
return -1;
}
return (int)m.ReturnValue;
}
//
// vexec -- Varargs exec program, called by execl*.
//
int
vexec(const char *path, const char *arg0, char * const envp[], va_list arglist)
{
NTSTATUS st;
PSX_API_MSG m;
PPSX_EXEC_MSG args;
char **ppch;
char *pch, *pcharg;
int i;
int retval = 0;
char *Args; // the args + env for the call
va_list save_arglist;
try {
if (0 == *path) {
errno = ENOENT;
return -1;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
errno = EFAULT;
retval = -1;
}
if (0 != retval) {
return retval;
}
args = &m.u.Exec;
PSX_FORMAT_API_MSG(m, PsxExecApi, sizeof(*args));
if (!PdxCanonicalize((PSZ)path, &args->Path, PdxHeap)) {
return -1;
}
Args = RtlAllocateHeap(PdxPortHeap, 0, ARG_MAX);
if (NULL == Args) {
errno = ENOMEM;
return -1;
}
args->Args = Args + PsxPortMemoryRemoteDelta;
//
// Port Memory Setup is same as for execve, see below.
//
//
// first we count the strings so we know how much space to leave
// for pointers.
//
save_arglist = arglist;
for (i = 0, pcharg = va_arg(arglist, char *); NULL != pcharg;
pcharg = va_arg(arglist, char *)) {
++i;
}
++i; // add one for arg0
for (ppch = (char **)envp; NULL != *ppch; ++ppch)
++i;
i += 2; // add space for the NULL pointers
pch = Args + sizeof(char *) * i;
if (pch > Args + ARG_MAX) {
RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
errno = E2BIG;
return -1;
}
ppch = (char **)Args;
arglist = save_arglist; // restart arglist
try {
pcharg = (char *)arg0;
while (NULL != pcharg) {
if (pch + strlen(pcharg) + 1 > Args + ARG_MAX) {
RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
errno = E2BIG;
return -1;
}
*ppch = pch - (ULONG_PTR)Args;
ppch++;
(void)strcpy(pch, pcharg);
pcharg = va_arg(arglist, char *);
pch += strlen(pch);
*pch++ = '\0';
}
*ppch = NULL;
ppch++;
while (NULL != *envp) {
if (pch + strlen(*envp) + 1 > Args + ARG_MAX) {
RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
errno = E2BIG;
return -1;
}
*ppch = pch - (ULONG_PTR)Args;
ppch++;
(void)strcpy(pch, *envp);
envp++;
pch += strlen(pch);
*pch++ = '\0';
}
*ppch = NULL;
} except (EXCEPTION_EXECUTE_HANDLER) {
errno = EFAULT;
retval = -1;
}
if (0 != retval) {
RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
return -1;
}
(void)NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
//
// If we get here, there's been an error.
//
errno = (int)m.Error;
RtlFreeHeap(PdxHeap, 0, (PVOID)&args->Path);
RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
return -1;
}
int
__cdecl
execve(const char *path, char * const argv[], char * const envp[])
{
NTSTATUS st;
PSX_API_MSG m;
PPSX_EXEC_MSG args;
PCHAR Args; // allocate args + environ
char **ppch;
char *pch;
int i;
int retval = 0;
try {
if (0 == strlen(path)) {
errno = ENOENT;
return -1;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
retval = -1;
errno = EFAULT;
}
if (0 != retval) {
return -1;
}
args = &m.u.Exec;
PSX_FORMAT_API_MSG(m, PsxExecApi, sizeof(*args));
if (!PdxCanonicalize((PSZ)path, &args->Path, PdxHeap)) {
return -1;
}
//
// Copy the caller's environment into view memory so that it may
// be transmitted to the "overlaid" process. We set up the port
// memory to look like:
//
// ClientPortMemory:
// argv[0]
// argv[1]
// ...
// NULL
// envp[0]
// envp[1]
// ...
// NULL
// <argv strings>
// <environ strings>
//
// The argv and envp pointers are converted to offsets relative to
// ClientPortMemory.
//
// Because we need all this memory for args and environ, we destroy
// the heap and recreate it if the call fails.
//
Args = RtlAllocateHeap(PdxPortHeap, 0, ARG_MAX);
if (NULL == Args) {
errno = ENOMEM;
return -1;
}
args->Args = Args + PsxPortMemoryRemoteDelta;
try {
// first we count the strings so we know how much space to leave
// for pointers.
for (i = 0, ppch = (char **)argv; NULL != *ppch; ++ppch)
++i;
for (ppch = (char **)envp; NULL != *ppch; ++ppch)
++i;
i += 2; // add space for the NULL pointers
pch = Args + sizeof(char *) * i;
if (pch > Args + ARG_MAX) {
RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
errno = E2BIG;
return -1;
}
ppch = (char **)Args;
while (NULL != *argv) {
if (pch + strlen(*argv) + 1 > Args + ARG_MAX) {
RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
errno = E2BIG;
return -1;
}
*ppch = pch - (ULONG_PTR)Args;
ppch++;
(void)strcpy(pch, *argv);
argv++;
pch += strlen(pch);
*pch++ = '\0';
}
*ppch = NULL;
ppch++;
while (NULL != *envp) {
if (pch + strlen(*envp) + 1 > Args + ARG_MAX) {
RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
errno = E2BIG;
return -1;
}
*ppch = pch - (ULONG_PTR)Args;
ppch++;
(void)strcpy(pch, *envp);
envp++;
pch += strlen(pch);
*pch++ = '\0';
}
*ppch = NULL;
} except (EXCEPTION_EXECUTE_HANDLER) {
retval = -1;
errno = EFAULT;
}
if (0 != retval) {
return -1;
}
(void)NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
//
// If we get here, there's been an error.
//
errno = (int)m.Error;
RtlFreeHeap(PdxHeap, 0, (PVOID)&args->Path);
RtlFreeHeap(PdxPortHeap, 0, (PVOID)Args);
return -1;
}
int
__cdecl
execv(const char *path, char * const argv[])
{
return execve(path, argv, environ);
}
int
__cdecl
execl(const char *path, const char *arg0, ...)
{
va_list args;
int retval;
va_start(args, arg0);
retval = vexec(path, arg0, environ, args);
va_end(args);
return retval;
}
int
__cdecl
execle(const char *path, const char *arg0, ...)
{
va_list args;
char * const *Env;
int retval;
va_start(args, arg0);
// Skip up to the NULL, then one more, to find environ.
do {
Env = va_arg(args, char * const *);
} while (NULL != Env);
Env = va_arg(args, char * const *);
va_end(args);
if (NULL == Env) {
return EINVAL;
}
// Restart the arglist traversal
va_start(args, arg0);
retval = vexec(path, arg0, Env, args);
va_end(args);
return retval;
}
int
__cdecl
execlp(const char *file, const char *arg0, ...)
{
char *pch;
char *path;
static char buf[PATH_MAX + 1];
va_list args;
int retval = 0;
BOOLEAN done = FALSE;
va_start(args, arg0);
//
// 1003.1-1990 (3.1.2.2): If the file argument contains a slash
// character, the file argument shall be used as the pathname for
// this file....
//
try {
if ('\0' == *file) {
errno = ENOENT;
va_end(args);
return -1;
}
if (NULL != (pch = strchr(file, '/'))) {
if (-1 == access(file, F_OK)) {
va_end(args);
return -1;
}
retval = vexec(file, arg0, environ, args);
va_end(args);
return retval;
}
} except (EXCEPTION_EXECUTE_HANDLER) {
errno = EFAULT;
retval = -1;
}
if (0 != retval) {
va_end(args);
return -1;
}
//
// ... Otherwise, the path prefix for this file is obtained by a
// search of the directories passed as the environment variable
// PATH.
//
if (NULL == (path = getenv("PATH"))) {
//
// The file name doesn't contain a slash, and we have
// no PATH. We just try for it in the current working
// directory, and will return ENOENT if it's not there.
//
retval = vexec(file, arg0, environ, args);
va_end(args);
return retval;
}
errno = 0;
do {
pch = strchr(path, ':');
if (NULL == pch) {
done = TRUE;
} else {
*pch = '\0';
}
if (strlen(path) + strlen(file) + 1 > PATH_MAX) {
if (pch) {
*pch = ':';
}
errno = ENAMETOOLONG;
va_end(args);
return -1;
}
strcpy(buf, path);
if (!done) {
*pch = ':';
path = pch + 1;
}
if (strlen(buf) > 0) {
// this case is "::" in the PATH
strcat(buf, "/");
}
strcat(buf, file);
// avoid trying to execute files that do not exist.
if (-1 != access(buf, F_OK)) {
(void)vexec(buf, arg0, environ, args);
break;
}
} while (!done);
va_end(args);
if (0 == errno) {
//
// We went all the way through the PATH without finding
// a file to exec. Since errno didn't get set by execve(),
// we set it here.
//
errno = ENOENT;
}
return -1;
}
int
__cdecl
execvp(const char *file, char * const argv[])
{
char *pch;
char *path;
static char buf[PATH_MAX + 1];
BOOLEAN done = FALSE;
int retval = 0;
//
// 1003.1-1990 (3.1.2.2): If the file argument contains a slash
// character, the file argument shall be used as the pathname for
// this file....
//
try {
if ('\0' == *file) {
errno = ENOENT;
return -1;
}
if (NULL != (pch = strchr(file, '/'))) {
if (-1 == access(file, F_OK)) {
return -1;
}
return execve(file, argv, environ);
}
} except (EXCEPTION_EXECUTE_HANDLER) {
errno = EFAULT;
retval = -1;
}
if (0 != retval) {
return -1;
}
//
// ... Otherwise, the path prefix for this file is obtained by a
// search of the directories passed as the environment variable
// PATH.
//
if (NULL == (path = getenv("PATH"))) {
return execve(file, argv, environ);
}
errno = 0;
do {
pch = strchr(path, ':');
if (NULL == pch) {
done = TRUE;
} else {
*pch = '\0';
}
if (strlen(path) + strlen(file) + 1 > PATH_MAX) {
if (pch) {
*pch = ':';
}
errno = ENAMETOOLONG;
return -1;
}
strcpy(buf, path);
if (!done) {
*pch = ':';
path = pch + 1;
}
if (strlen(buf) > 0) {
// this case is "::" in the PATH
strcat(buf, "/");
}
strcat(buf, file);
// avoid trying to execute files that do not exist
if (-1 != access(buf, F_OK)) {
(void)execve(buf, argv, environ);
break;
}
} while (!done);
if (0 == errno) {
//
// We went all the way through the PATH without finding
// a file to exec. Since errno didn't get set by execve(),
// we set it here.
//
errno = ENOENT;
}
return -1;
}
#define COMPUTERNAME_ROOT \
L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\ComputerName"
#define NON_VOLATILE_COMPUTERNAME L"ComputerName"
#define COMPUTERNAME_VALUE_NAME L"ComputerName"
#define VALUE_BUFFER_SIZE \
(sizeof(KEY_VALUE_PARTIAL_INFORMATION) \
+ (_POSIX_NAME_MAX * sizeof(WCHAR)))
int __cdecl
uname(struct utsname *name)
{
NTSTATUS Status;
SYSTEM_PROCESSOR_INFORMATION
ProcInfo;
UNICODE_STRING
KeyName,
Class,
ValueName,
Computer_U;
ANSI_STRING
Computer_A;
OBJECT_ATTRIBUTES
ObjectAttributes;
HANDLE hKey = NULL,
hSubKey = NULL;
WCHAR ValueBuf[VALUE_BUFFER_SIZE];
PKEY_VALUE_PARTIAL_INFORMATION
pKeyValueInfo = (PVOID)ValueBuf;
ULONG ValueLength;
char *pchProcType, // processor type
*pchNode = ""; // node name
int retval = 0;
Status = NtQuerySystemInformation(SystemProcessorInformation,
(PVOID)&ProcInfo, sizeof(ProcInfo), NULL);
if (!NT_SUCCESS(Status)) {
errno = PdxStatusToErrno(Status);
return -1;
}
switch (ProcInfo.ProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_INTEL:
if (ProcInfo.ProcessorLevel == 3) {
pchProcType = "i386";
} else if (ProcInfo.ProcessorLevel == 4) {
pchProcType = "i486";
} else if (ProcInfo.ProcessorLevel == 5) {
pchProcType = "Pentium";
} else {
pchProcType = "Intel Unknown";
}
break;
case PROCESSOR_ARCHITECTURE_IA64:
pchProcType = "IA64";
break;
case PROCESSOR_ARCHITECTURE_MIPS:
pchProcType = "R4000";
break;
case PROCESSOR_ARCHITECTURE_ALPHA:
if (ProcInfo.ProcessorLevel == 21064) {
pchProcType = "Alpha 21064";
} else if (ProcInfo.ProcessorLevel == 21164) {
pchProcType = "Alpha 21164";
} else {
pchProcType = "Alpha Unknown";
}
break;
case PROCESSOR_ARCHITECTURE_PPC:
if (ProcInfo.ProcessorLevel == 1) {
pchProcType = "PowerPC 601";
} else if (ProcInfo.ProcessorLevel == 3) {
pchProcType = "PowerPC 603";
} else if (ProcInfo.ProcessorLevel == 4) {
pchProcType = "PowerPC 604";
} else if (ProcInfo.ProcessorLevel == 6) {
pchProcType = "PowerPC 603+";
} else if (ProcInfo.ProcessorLevel == 9) {
pchProcType = "PowerPC 604+";
} else if (ProcInfo.ProcessorLevel == 20) {
pchProcType = "PowerPC 620";
} else {
pchProcType = "PowerPC Unknown";
}
break;
default:
pchProcType = "unknown";
break;
}
//
// Find the node name: this code lifted from
// windows/base/client/compname.c
//
RtlInitUnicodeString(&KeyName, COMPUTERNAME_ROOT);
InitializeObjectAttributes(&ObjectAttributes, &KeyName,
OBJ_CASE_INSENSITIVE, NULL, NULL);
Status = NtOpenKey(&hKey, KEY_READ, &ObjectAttributes);
if (!NT_SUCCESS(Status)) {
KdPrint(("PSXDLL: NtOpenKey: 0x%x\n", Status));
goto done;
}
RtlInitUnicodeString(&KeyName, NON_VOLATILE_COMPUTERNAME);
InitializeObjectAttributes(&ObjectAttributes, &KeyName,
OBJ_CASE_INSENSITIVE, hKey, NULL);
Status = NtOpenKey(&hSubKey, KEY_READ, &ObjectAttributes);
if (!NT_SUCCESS(Status)) {
KdPrint(("PSXDLL: NtOpenKey: 0x%x\n", Status));
goto done;
}
RtlInitUnicodeString(&ValueName, COMPUTERNAME_VALUE_NAME);
Status = NtQueryValueKey(hSubKey, &ValueName,
KeyValuePartialInformation,
(PVOID)pKeyValueInfo, VALUE_BUFFER_SIZE, &ValueLength);
ASSERT(ValueLength < VALUE_BUFFER_SIZE);
if (!NT_SUCCESS(Status)) {
KdPrint(("PSXDLL: NtQueryValueKey: 0x%x\n", Status));
goto done;
}
if (pKeyValueInfo->DataLength == 0) {
goto done;
}
Computer_U.Buffer = (PVOID)&pKeyValueInfo->Data;
Computer_U.Length = Computer_U.MaximumLength =
(USHORT)pKeyValueInfo->DataLength;
Status = RtlUnicodeStringToAnsiString(&Computer_A, &Computer_U, TRUE);
if (!NT_SUCCESS(Status)) {
goto done;
}
pchNode = Computer_A.Buffer;
done:
if (NULL != hSubKey) {
NtClose(hSubKey);
}
if (NULL != hKey) {
NtClose(hKey);
}
try {
strncpy((PCHAR)name->sysname, (PCHAR)UNAME_SYSNAME, sizeof(name->sysname));
strncpy((PCHAR)name->release, (PCHAR)UNAME_RELEASE, sizeof(name->release));
strncpy((PCHAR)name->version, (PCHAR)UNAME_VERSION, sizeof(name->version));
strncpy((PCHAR)name->nodename, (PCHAR)pchNode, sizeof(name->nodename));
strncpy((PCHAR)name->machine, (PCHAR)pchProcType, sizeof(name->machine));
} except (EXCEPTION_EXECUTE_HANDLER) {
errno = EFAULT;
retval = -1;
}
RtlFreeAnsiString(&Computer_A);
return retval;
}
char * __cdecl
getenv(const char *name)
{
char **ppch;
char *pch;
try {
for (ppch = environ; NULL != *ppch; ++ppch) {
if (NULL == (pch = strchr(*ppch, '='))) {
continue;
}
*pch = '\0'; // delete the equals
if (0 == strcmp(*ppch, name)) {
*pch = '=';
return pch + 1;
}
*pch = '=';
}
return NULL;
} except (EXCEPTION_EXECUTE_HANDLER) {
errno = EFAULT;
}
return NULL;
}
time_t __cdecl
time(time_t *tloc)
{
LARGE_INTEGER TimeOfDay;
ULONG PosixTime;
NtQuerySystemTime(&TimeOfDay);
if (RtlTimeToSecondsSince1970(&TimeOfDay, &PosixTime)) {
if (ARGUMENT_PRESENT(tloc)) {
try {
*tloc = PosixTime;
} except (EXCEPTION_EXECUTE_HANDLER) {
errno = EFAULT;
}
}
} else {
PosixTime = (ULONG)-1; // Time not within range of 1970 - 2105
}
return (time_t)PosixTime;
}
clock_t
__cdecl
times(struct tms *buffer)
{
PSX_API_MSG m;
PPSX_GETPROCESSTIMES_MSG args;
LARGE_INTEGER TimeOfDay;
ULONG Remainder;
NTSTATUS st;
int retval = 0;
args = &m.u.GetProcessTimes;
PSX_FORMAT_API_MSG(m, PsxGetProcessTimesApi, sizeof(*args));
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
if (m.Error) {
errno = (int)m.Error;
return -1;
}
try {
*buffer = args->ProcessTimes;
} except (EXCEPTION_EXECUTE_HANDLER) {
errno = EFAULT;
retval = -1;
}
if (0 != retval) {
return -1;
}
NtQuerySystemTime(&TimeOfDay);
TimeOfDay = RtlExtendedLargeIntegerDivide(TimeOfDay, 10000L,
&Remainder);
return TimeOfDay.LowPart;
}
long
__cdecl
sysconf(int name)
{
PSX_API_MSG m;
PPSX_SYSCONF_MSG args;
NTSTATUS st;
args = &m.u.Sysconf;
args->Name = name;
PSX_FORMAT_API_MSG(m, PsxSysconfApi, sizeof(*args));
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
if (0 != m.Error) {
errno = m.Error;
return -1;
}
return m.ReturnValue;
}
int
__cdecl
getgroups(int gidsetsize, gid_t *grouplist)
{
PSX_API_MSG m;
PPSX_GETGROUPS_MSG args;
NTSTATUS st;
args = &m.u.GetGroups;
args->GroupList = grouplist;
args->NGroups = gidsetsize;
//
// The Posix server will write group id's into the group
// array with NtWriteVirtualMemory, unless gidsetsize is
// 0. In that case, he returns the size required and does
// not try to write the list.
//
PSX_FORMAT_API_MSG(m, PsxGetGroupsApi, sizeof(*args));
st = NtRequestWaitReplyPort(PsxPortHandle, (PPORT_MESSAGE)&m,
(PPORT_MESSAGE)&m);
#ifdef PSX_MORE_ERRORS
ASSERT(NT_SUCCESS(st));
#endif
if (0 != m.Error) {
errno = m.Error;
return -1;
}
return m.ReturnValue;
}