now introducing the POSIX+ client DLL! (my first check-in, hope I don't f*** up something)

svn path=/trunk/; revision=2634
This commit is contained in:
KJK::Hyperion 2002-02-20 07:06:52 +00:00
parent 4e9d91b819
commit ad8ae0a2f5
43 changed files with 4239 additions and 0 deletions

117
posix/lib/psxdll/Makefile Normal file
View file

@ -0,0 +1,117 @@
# $Id:
PATH_TO_TOP = ../../../..
TARGET_TYPE = dynlink
TARGET_NAME = psxdll
TARGET_LFLAGS = -nostartfiles
TARGET_SDKLIBS = ntdll.a
TARGET_BASE = 0x68EB0000
TARGET_ENTRY = _DllMain@12
TARGET_CFLAGS = -W -nostdinc -nostdlib -fno-builtin -I$(PATH_TO_TOP)/subsys/psx/include -D__PSXDLL__ -D__PSX_DEBUG_WANT_ALL__
TARGET_OBJECTS = $(TARGET_NAME).o
TARGET_CLEAN = $(OBJECTS)
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk
OBJECTS_MISC = \
misc/main.o \
misc/interlock.o \
misc/safeobj.o \
misc/path.o \
misc/fdtable.o
OBJECTS_DIRENT = \
dirent/opendir.o \
dirent/readdir.o \
dirent/closedir.o
OBJECTS_DLFCN = \
dlfcn/dlopen.o \
dlfcn/dlclose.o \
dlfcn/dlsym.o \
dlfcn/dlerror.o
OBJECTS_ERRNO = \
errno/errno.o
OBJECTS_FCNTL = \
fcntl/open.o \
fcntl/fcntl.o
OBJECTS_LIBGEN = \
libgen/basename.o
OBJECTS_SCHED = \
sched/yield.o
OBJECTS_SIGNAL = \
pthread/kill.o \
signal/raise.o
OBJECTS_STDLIB = \
stdlib/abort.o \
stdlib/malloc.o \
stdlib/exit.o
OBJECTS_STRING = \
string/strdup.o \
string/strerror.o
OBJECTS_PTHREAD = \
pthread/create.o \
pthread/exit.o \
pthread/join.o \
pthread/mutex.o \
pthread/self.o
OBJECTS_SYS_UTSNAME = \
sys/utsname/uname.o
OBJECTS_UNISTD = \
unistd/close.o \
unistd/dup.o \
unistd/getcwd.o \
unistd/getpid.o \
unistd/getppid.o
OBJECTS = \
$(OBJECTS_MISC) \
$(OBJECTS_DIRENT) \
$(OBJECTS_DLFCN) \
$(OBJECTS_ERRNO) \
$(OBJECTS_FCNTL) \
$(OBJECTS_LIBGEN) \
$(OBJECTS_SCHED) \
$(OBJECTS_SIGNAL) \
$(OBJECTS_STDLIB) \
$(OBJECTS_STRING) \
$(OBJECTS_PTHREAD) \
$(OBJECTS_SYS_UTSNAME) \
$(OBJECTS_UNISTD)
DEP_OBJECTS = $(OBJECTS)
include $(TOOLS_PATH)/depend.mk
$(TARGET_NAME).o: $(OBJECTS)
$(LD) -r $(OBJECTS) -o $(TARGET_NAME).o
DTFLAGS = -k -l $@
$(TARGET_NAME).a: $(TARGET_NAME).def
$(DLLTOOL) \
$(DTFLAGS) \
-D $(TARGET_NAME).dll \
-d $(TARGET_NAME).def
# EOF

View file

@ -0,0 +1,36 @@
/* $Id: closedir.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/dirent/closedir.c
* PURPOSE: Close a directory stream
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 01/02/2002: Created
* 13/02/2002: KJK::Hyperion: modified to use file descriptors
*/
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <psx/dirent.h>
#include <psx/safeobj.h>
int closedir(DIR *dirp)
{
/* check the "magic" signature */
if(!__safeobj_validate(dirp, __IDIR_MAGIC))
{
errno = EBADF;
return (-1);
}
/* this will close the handle, deallocate the internal object and
invalidate the descriptor */
return (close(((struct __internal_DIR *)dirp)->fildes));
}
/* EOF */

View file

@ -0,0 +1,100 @@
/* $Id: opendir.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/dirent/opendir.c
* PURPOSE: Open a directory
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 27/01/2002: Created
* 13/02/2002: KJK::Hyperion: modified to use file descriptors
*/
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <wchar.h>
#include <errno.h>
#include <psx/debug.h>
#include <psx/stdlib.h>
#include <psx/dirent.h>
#include <psx/safeobj.h>
DIR *opendir(const char *dirname)
{
ANSI_STRING strDirName;
UNICODE_STRING wstrDirName;
DIR *pdData;
RtlInitAnsiString(&strDirName, (PCSZ)dirname);
RtlAnsiStringToUnicodeString(&wstrDirName, &strDirName, TRUE);
pdData = (DIR *)_Wopendir(wstrDirName.Buffer);
RtlFreeUnicodeString(&wstrDirName);
return (pdData);
}
DIR *_Wopendir(const wchar_t *dirname)
{
struct __internal_DIR *pidData;
int nFileNo;
/* allocate internal object */
pidData = __malloc(sizeof(*pidData));
/* allocation failed */
if(pidData == 0)
{
errno = ENOMEM;
return (0);
}
/* open the directory */
nFileNo = _Wopen(dirname, O_RDONLY | _O_DIRFILE);
/* failure */
if(nFileNo < 0)
{
__free(pidData);
return (0);
}
/* directory file descriptors must be closed on exec() */
if(fcntl(nFileNo, F_SETFD, FD_CLOEXEC) == -1)
WARN
(
"couldn't set FD_CLOEXEC flag on file number %u, errno %u",
nFileNo,
errno
);
/* associate the internal data to the file descriptor */
if(fcntl(nFileNo, F_SETXP, pidData) == -1)
WARN
(
"couldn't associate the object at 0x%X to the file number %u, errno %u",
pidData,
nFileNo,
errno
);
if(fcntl(nFileNo, F_SETXS, sizeof(*pidData)) == -1)
WARN
(
"couldn't set the extra data size of the file number %u, errno %u",
nFileNo,
errno
);
pidData->signature = __IDIR_MAGIC;
/* success */
return ((DIR *)pidData);
}
/* EOF */

View file

@ -0,0 +1,214 @@
/* $Id: readdir.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/dirent/readdir.c
* PURPOSE: Read directory
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 27/01/2002: Created
* 13/02/2002: KJK::Hyperion: modified to use file descriptors
*/
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stddef.h>
#include <dirent.h>
#include <psx/dirent.h>
#include <psx/debug.h>
#include <psx/errno.h>
#include <psx/safeobj.h>
#include <ddk/ntddk.h>
struct dirent *readdir(DIR *dirp)
{
struct _Wdirent *lpwdReturn;
struct __internal_DIR *pidData;
ANSI_STRING strFileName;
UNICODE_STRING wstrFileName;
NTSTATUS nErrCode;
/* call Unicode function */
lpwdReturn = _Wreaddir(dirp);
/* failure */
if(lpwdReturn == 0)
return (0);
/* get the internal data object */
pidData = ((struct __internal_DIR *)dirp);
/* create NT Unicode string from the Unicode dirent's buffer */
RtlInitUnicodeString(&wstrFileName, pidData->ent.de_unicode.d_name);
/* HACK: make the ANSI string point to the same buffer where the Unicode string is stored */
strFileName.Buffer = (PCSZ)&pidData->info.FileName[0];
strFileName.Length = 0;
strFileName.MaximumLength = MAX_PATH;
/* convert the filename to ANSI */
nErrCode = RtlUnicodeStringToAnsiString(&strFileName, &wstrFileName, FALSE);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
errno = __status_to_errno(nErrCode);
return (0);
}
/* make the ANSI dirent filename point to the ANSI buffer */
pidData->ent.de_ansi.d_name = strFileName.Buffer;
/* null-terminate the ANSI name */
pidData->ent.de_ansi.d_name[strFileName.Length] = 0;
/* success */
return (&(pidData->ent.de_ansi));
}
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
{
errno = ENOSYS;
return (0);
}
struct _Wdirent *_Wreaddir(DIR *dirp)
{
HANDLE hFile;
HANDLE hDir;
OBJECT_ATTRIBUTES oaFileAttribs;
UNICODE_STRING wstrFileName;
FILE_INTERNAL_INFORMATION fiiInfo;
IO_STATUS_BLOCK isbStatus;
NTSTATUS nErrCode;
struct __internal_DIR *pidData;
/* check the "magic" signature */
if(!__safeobj_validate(dirp, __IDIR_MAGIC))
{
errno = EINVAL;
return (0);
}
/* get internal data */
pidData = (struct __internal_DIR *)dirp;
/* get handle */
hDir = (HANDLE)fcntl(pidData->fildes, F_GETFH);
/* failure */
if(((int)hDir) == -1)
return (0);
/* read next directory entry */
nErrCode = NtQueryDirectoryFile
(
hDir,
NULL,
NULL,
NULL,
&isbStatus,
(PVOID)&pidData->info,
sizeof(pidData->info) + sizeof(WCHAR) * (MAX_PATH - 1),
FileDirectoryInformation,
TRUE,
NULL,
FALSE
);
/* failure or EOF */
if(!NT_SUCCESS(nErrCode))
{
if(nErrCode == (NTSTATUS)STATUS_NO_MORE_FILES)
return (0);
else
{
ERR("NtQueryDirectoryFile() failed with status 0x%08X", nErrCode);
errno = __status_to_errno(nErrCode);
return (0);
}
}
/* null-terminate the filename, just in case */
pidData->info.FileName[pidData->info.FileNameLength / sizeof(WCHAR)] = 0;
INFO("this entry: %ls", pidData->info.FileName);
#if 0
/* file inodes are not returned by NtQueryDirectoryFile, we have to open every file */
/* set file's object attributes */
wstrFileName.Length = pidData->info.FileNameLength;
wstrFileName.MaximumLength = sizeof(WCHAR) * MAX_PATH;
wstrFileName.Buffer = &pidData->info.FileName[0];
oaFileAttribs.Length = sizeof(OBJECT_ATTRIBUTES);
oaFileAttribs.RootDirectory = pidData->dirhandle;
oaFileAttribs.ObjectName = &wstrFileName;
oaFileAttribs.Attributes = 0;
oaFileAttribs.SecurityDescriptor = NULL;
oaFileAttribs.SecurityQualityOfService = NULL;
/* open the file */
nErrCode = NtOpenFile
(
&hFile,
FILE_READ_ATTRIBUTES,
&oaFileAttribs,
&isbStatus,
0,
FILE_SYNCHRONOUS_IO_NONALERT
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
ERR("NtOpenFile() failed with status %#X", nErrCode);
errno = __status_to_errno(nErrCode);
return (0);
}
/* get the internal information for the file */
nErrCode = NtQueryInformationFile
(
hFile,
&isbStatus,
&fiiInfo,
sizeof(FILE_INTERNAL_INFORMATION),
FileInternalInformation
);
/* close the handle (not needed anymore) */
NtClose(hFile);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
ERR("NtQueryInformationFile() failed with status %#X", nErrCode);
errno = __status_to_errno(nErrCode);
return (0);
}
/* return file inode */
pidData->ent.de_unicode.d_ino = (ino_t)fiiInfo.IndexNumber.QuadPart;
#endif
FIXME("file inodes currently hardcoded to 0");
pidData->ent.de_unicode.d_ino = 0;
/* return file name */
pidData->ent.de_unicode.d_name = &pidData->info.FileName[0];
/* success */
return &(pidData->ent.de_unicode);
}
int _Wreaddir_r(DIR *dirp, struct _Wdirent *entry, struct _Wdirent **result)
{
errno = ENOSYS;
return (0);
}
/* EOF */

View file

@ -0,0 +1,60 @@
/* $Id: dlclose.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/dlfcn/dlclose.c
* PURPOSE: Close a dlopen() object
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 19/12/2001: Created
*/
#include <ddk/ntddk.h>
#include <ntdll/rtl.h>
#include <ntdll/ldr.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <psx/debug.h>
#include <psx/dlfcn.h>
#include <psx/errno.h>
int dlclose(void *handle)
{
if(handle == 0)
{
ERR("invalid handle passed to dlclose");
__dl_set_last_error(EFAULT); /* FIXME? maybe EINVAL? */
return (-1);
}
if(((struct __dlobj *)handle)->global)
{
TODO("global symbol matching not implemented");
__dl_set_last_error(EINVAL);
return (-1);
}
else
{
NTSTATUS nErrCode = LdrUnloadDll(((struct __dlobj *)handle)->handle);
if(!NT_SUCCESS(nErrCode))
{
ERR("LdrUnloadDll(%#x) failed with status %d", ((struct __dlobj *)handle)->handle, nErrCode);
free(handle);
__dl_set_last_error(__status_to_errno(nErrCode));
return (-1);
}
}
free(handle);
return (0);
}
/* EOF */

View file

@ -0,0 +1,36 @@
/* $Id: dlerror.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/dlfcn/dlerror.c
* PURPOSE: Gain access to an executable object file
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 19/12/2001: Created
*/
#include <ddk/ntddk.h>
#include <ntdll/rtl.h>
#include <ntdll/ldr.h>
#include <dlfcn.h>
#include <string.h>
#include <psx/debug.h>
#include <psx/dlfcn.h>
#include <psx/errno.h>
static int __dl_last_error = 0;
void __dl_set_last_error(int err)
{
FIXME("dlfcn error handling not thread safe");
__dl_last_error = err;
}
char *dlerror(void)
{
return strerror(__dl_last_error);
}
/* EOF */

View file

@ -0,0 +1,129 @@
/* $Id: dlopen.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/dlfcn/dlopen.c
* PURPOSE: Gain access to an executable object file
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 19/12/2001: Created
*/
#include <ddk/ntddk.h>
#include <ntdll/rtl.h>
#include <ntdll/ldr.h>
#include <wchar.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <psx/dlfcn.h>
#include <psx/errno.h>
#include <psx/debug.h>
void *__wdlopen(const wchar_t *, int);
void *dlopen(const char *file, int mode)
{
/* TODO: ANSI-to-Unicode stubs like this need to be standardized in some way */
void * pRetVal;
ANSI_STRING strFile;
UNICODE_STRING wstrFile;
RtlInitAnsiString(&strFile, (LPSTR)file);
RtlAnsiStringToUnicodeString (&wstrFile, &strFile, TRUE);
pRetVal = __wdlopen((wchar_t *)wstrFile.Buffer, mode);
free(wstrFile.Buffer);
return pRetVal;
}
void *__wdlopen(const wchar_t *file, int mode)
{
NTSTATUS nErrCode;
UNICODE_STRING wstrNativePath;
struct __dlobj * pdloObject;
if(file == 0)
{
/* POSIX dynamic linking allows for global symbol matching */
pdloObject = (struct __dlobj *)malloc(sizeof(struct __dlobj));
TODO("\
move the global symbol matching semantics into the PE Loader \
(NTDLL Ldr family of calls), and just return a pointer to the module \
image\
");
pdloObject->global = 1;
return (pdloObject);
}
FIXME("\
LdrLoadDll() only accepts DOS paths - probably because the POSIX \
standard didn't specify dynamic linking interfaces at the time Windows NT \
was born \
");
#if 0
/* TODO: LdrLoadNtDll() or LdrLoadDllEx() (the former is preferrable, since
the latter is more likely to be implemented with different purposes from
Microsoft), accepting native NT paths */
if(wcschr(file, '/'L) != NULL)
{
/* TODO: RtlPosixPathNameToNtPathName_U */
if(!RtlPosixPathNameToNtPathName_U((LPWSTR)file, &wstrNativePath, NULL, NULL))
{
__dl_set_last_error(ENOENT);
return (NULL);
}
}
else
{
RtlInitUnicodeString(&wstrNativePath, (LPWSTR)file);
}
#endif
RtlInitUnicodeString(&wstrNativePath, (LPWSTR)file);
pdloObject = (struct __dlobj *)malloc(sizeof(struct __dlobj));
pdloObject->global = 0;
WARN("\
mode flags are not fully supported by Windows NT, due to the \
completely different semantics of dynamical linking (for \
example the global symbol matching is unsupported). This \
implementation will then behave as if mode was set to \
(RTLD_NOW | RTLD_GLOBAL), and fail if other flags are set.\
");
if(__dl_get_scope_flag(mode) == RTLD_LOCAL)
{
__dl_set_last_error(EINVAL);
return (NULL);
}
/* load the DLL */
nErrCode = LdrLoadDll
(
NULL,
0,
&wstrNativePath,
(PVOID*)&pdloObject->handle
);
if(!NT_SUCCESS(nErrCode))
{
__dl_set_last_error(__status_to_errno(nErrCode));
return (NULL);
}
return (pdloObject);
}
/* EOF */

View file

@ -0,0 +1,92 @@
/* $Id: dlsym.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/dlfcn/dlsym.c
* PURPOSE: Obtain the address of a symbol from a dlopen() object
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 19/12/2001: Created
*/
#include <ddk/ntddk.h>
#include <ntdll/rtl.h>
#include <ntdll/ldr.h>
#include <dlfcn.h>
#include <psx/dlfcn.h>
#include <psx/errno.h>
#include <psx/debug.h>
void *__dlsymn(void *, unsigned long int);
void *__dlsym(void *, int, const char *, unsigned long int);
void *dlsym(void *handle, const char *name)
{
return (__dlsym(handle, 1, name, 0));
}
void *__dlsymn(void *handle, unsigned long int ordinal)
{
return (__dlsym(handle, 0, 0, ordinal));
}
void *__dlsym(void *handle, int by_name, const char *name, unsigned long int ordinal)
{
struct __dlobj * pdloObject;
void * pProcAddr;
NTSTATUS nErrCode;
if(handle == RTLD_NEXT)
{
FIXME("implement RTLD_NEXT semantics");
return (NULL);
}
pdloObject = (struct __dlobj *) handle;
if(pdloObject->global)
{
FIXME("implement global symbol matching");
return (NULL);
}
if(by_name)
{
ANSI_STRING strName;
RtlInitAnsiString(&strName, (LPSTR)name);
nErrCode = LdrGetProcedureAddress
(
pdloObject->handle,
&strName,
0,
(PVOID *)&pProcAddr
);
}
else
{
nErrCode = LdrGetProcedureAddress
(
pdloObject->handle,
NULL,
ordinal,
(PVOID *)&pProcAddr
);
}
if(!NT_SUCCESS(nErrCode))
{
__dl_set_last_error(__status_to_errno(nErrCode));
return (NULL);
}
return pProcAddr;
}
/* EOF */

View file

@ -0,0 +1,25 @@
/* $Id: errno.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/errno/errno.c
* PURPOSE: Internal errno implementation
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 27/12/2001: Created
*/
#include <psx/debug.h>
#include <psx/errno.h>
static int __errno_storage = 0;
int * __PdxGetThreadErrNum(void)
{
FIXME("errno currently not thread-safe");
return (&__errno_storage);
}
/* EOF */

View file

@ -0,0 +1,311 @@
/* $Id: fcntl.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/fcntl/fcntl.c
* PURPOSE: File control
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 13/02/2002: Created
* 15/02/2002: Implemented fcntl() (KJK::Hyperion)
*/
#include <ddk/ntddk.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <psx/errno.h>
#include <psx/stdlib.h>
#include <psx/fdtable.h>
#include <psx/pdata.h>
#include <psx/debug.h>
int fcntl(int fildes, int cmd, ...)
{
__fdtable_t *pftFdTable;
__fildes_t *pfdDescriptor;
NTSTATUS nErrCode;
int nRetVal;
int nThirdArg;
void *pThirdArg;
va_list vlArgs;
/* lock the environment */
__PdxAcquirePdataLock();
/* get the file descriptors table */
pftFdTable = __PdxGetProcessData()->FdTable;
/* fildes is an invalid, closed or uninitialized descriptor */
if
(
fildes < 0 ||
fildes >= OPEN_MAX ||
__fdtable_entry_isavail(pftFdTable, fildes) == 0 ||
__fdtable_entry_get(pftFdTable, fildes) == 0
)
{
errno = EBADF;
__PdxReleasePdataLock();
return (-1);
}
/* get the file descriptor referenced by fildes */
pfdDescriptor = __fdtable_entry_get(pftFdTable, fildes);
/* get third argument as integer */
va_start(vlArgs, cmd);
nThirdArg = va_arg(vlArgs, int);
va_end(vlArgs);
/* get third argument as pointer */
va_start(vlArgs, cmd);
pThirdArg = va_arg(vlArgs, void *);
va_end(vlArgs);
/* initialize return value */
nRetVal = -1;
switch(cmd)
{
case F_DUPFD:
{
va_list vlArgs;
int nDupFileNo;
__fildes_t *pfdDupDescriptor;
/* allocate the duplicated descriptor */
nDupFileNo = __fdtable_entry_add(pftFdTable, nThirdArg, 0, &pfdDupDescriptor);
if(nDupFileNo)
break;
/* copy the open flags */
pfdDupDescriptor->OpenFlags = pfdDescriptor->OpenFlags;
/* clear the FD_CLOEXEC flag */
pfdDupDescriptor->FdFlags = pfdDescriptor->FdFlags & ~FD_CLOEXEC;
/* duplicate the extra data */
if(pfdDescriptor->ExtraDataSize != 0 && pfdDescriptor->ExtraData != 0)
{
/* allocate space for the duplicated extra data */
pfdDupDescriptor->ExtraDataSize = pfdDescriptor->ExtraDataSize;
pfdDupDescriptor->ExtraData = __malloc(pfdDupDescriptor->ExtraDataSize);
/* failure */
if(pfdDupDescriptor->ExtraData == 0)
{
errno = ENOMEM;
break;
}
/* copy the extra data */
memcpy(pfdDupDescriptor->ExtraData, pfdDescriptor->ExtraData, pfdDupDescriptor->ExtraDataSize);
INFO
(
"copied %u bytes from 0x%08X into 0x%08X",
pfdDupDescriptor->ExtraDataSize,
pfdDescriptor->ExtraData,
pfdDupDescriptor->ExtraData
);
}
/* duplicate the handle */
nErrCode = NtDuplicateObject
(
NtCurrentProcess(),
pfdDescriptor->FileHandle,
NtCurrentProcess(),
&pfdDupDescriptor->FileHandle,
0,
0,
DUPLICATE_SAME_ACCESS /* | DUPLICATE_SAME_ATTRIBUTES */
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
__free(pfdDupDescriptor->ExtraData);
errno = __status_to_errno(nErrCode);
break;
}
INFO
(
"duplicated handle 0x%08X into handle 0x%08X",
pfdDescriptor->FileHandle,
pfdDupDescriptor->FileHandle
);
/* return the duplicated file number */
nRetVal = nDupFileNo;
break;
}
case F_GETFD:
{
nRetVal = pfdDescriptor->FdFlags;
break;
}
case F_SETFD:
{
pfdDescriptor->FdFlags = nThirdArg;
nRetVal = 0;
break;
}
case F_GETFL:
{
nRetVal = pfdDescriptor->OpenFlags;
break;
}
case F_SETFL:
{
pfdDescriptor->OpenFlags = nThirdArg;
nRetVal = 0;
break;
}
case F_GETLK:
{
errno = EINVAL;
break;
}
case F_SETLK:
{
errno = EINVAL;
break;
}
case F_SETLKW:
{
errno = EINVAL;
break;
}
case F_NEWFD:
{
/* allocate a new descriptor */
nRetVal = __fdtable_entry_add(pftFdTable, fildes, (__fildes_t *)pThirdArg, 0);
break;
}
case F_DELFD:
{
/* invalid return pointer */
if(pThirdArg == 0)
{
errno = EINVAL;
break;
}
memcpy((__fildes_t *)pThirdArg, pfdDescriptor, sizeof(*pfdDescriptor));
/* remove file descriptor */
nRetVal = __fdtable_entry_remove(pftFdTable, fildes);
}
case F_GETALL:
{
/* invalid return pointer */
if(pThirdArg == 0)
{
errno = EINVAL;
break;
}
/* return a copy of the file descriptor */
memcpy((__fildes_t *)pThirdArg, pfdDescriptor, sizeof(*pfdDescriptor));
nRetVal = 0;
}
case F_SETALL:
{
/* invalid file descriptor to copy attributes from */
if(pThirdArg == 0)
{
errno = EINVAL;
break;
}
/* copy the attributes of file descriptor from the provided descriptor */
memcpy(pfdDescriptor, pThirdArg, sizeof(*pfdDescriptor));
nRetVal = 0;
}
case F_GETXP:
{
/* invalid return pointer */
if(pThirdArg == 0)
{
errno = EINVAL;
break;
}
/* return a pointer to the extra data associated to the descriptor */
*((void **)pThirdArg) = pfdDescriptor->ExtraData;
nRetVal = 0;
break;
}
case F_SETXP:
{
/* set the pointer to the extra data associated */
pfdDescriptor->ExtraData = pThirdArg;
nRetVal = 0;
break;
}
case F_GETXS:
{
nRetVal = pfdDescriptor->ExtraDataSize;
break;
}
case F_SETXS:
{
pfdDescriptor->ExtraDataSize = nThirdArg;
nRetVal = 0;
break;
}
case F_GETFH:
{
/* invalid return pointer */
if(pThirdArg == 0)
{
errno = EINVAL;
break;
}
/* return the handle associated to the descriptor */
*((void **)pThirdArg) = pfdDescriptor->FileHandle;
nRetVal = 0;
break;
}
case F_SETFH:
{
pfdDescriptor->FileHandle = pThirdArg;
nRetVal = 0;
break;
}
default:
errno = EINVAL;
}
/* unlock the environment */
__PdxReleasePdataLock();
return (nRetVal);
}
/* EOF */

View file

@ -0,0 +1,181 @@
/* $Id: open.c,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/fcntl/open.c
* PURPOSE: Open a file
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 04/02/2002: Created
*/
#include <ddk/ntddk.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <psx/path.h>
#include <psx/debug.h>
#include <psx/errno.h>
#include <psx/pdata.h>
int open(const char *path, int oflag, ...)
{
ANSI_STRING strPath;
UNICODE_STRING wstrPath;
int nRetVal;
RtlInitAnsiString(&strPath, (PCSZ)path);
RtlAnsiStringToUnicodeString(&wstrPath, &strPath, TRUE);
nRetVal = _Wopen(wstrPath.Buffer, oflag);
RtlFreeUnicodeString(&wstrPath);
return (nRetVal);
}
int _Wopen(const wchar_t *path, int oflag, ...)
{
OBJECT_ATTRIBUTES oaFileAttribs;
IO_STATUS_BLOCK isbStatus;
UNICODE_STRING wstrNativePath;
NTSTATUS nErrCode;
ULONG nDesiredAccess;
ULONG nCreateDisposition;
ULONG nCreateOptions;
HANDLE hFile;
#if 0
mode_t mFileMode;
#endif
int nFileNo;
__fdtable_t *pftTable;
__fildes_t fdDescriptor;
/* translate file access flag */
switch(oflag & O_ACCMODE)
{
case O_RDONLY:
{
nDesiredAccess = FILE_READ_ACCESS;
nCreateOptions = 0;
break;
}
case O_WRONLY:
{
nDesiredAccess = FILE_WRITE_ACCESS;
nCreateOptions = FILE_NON_DIRECTORY_FILE; /* required by the specification */
break;
}
case O_RDWR:
{
nDesiredAccess = FILE_READ_ACCESS | FILE_WRITE_ACCESS;
nCreateOptions = FILE_NON_DIRECTORY_FILE; /* required by the specification */
break;
}
default:
{
errno = EINVAL;
return (-1);
}
}
/* miscellaneous flags */
if((oflag & _O_DIRFILE) == _O_DIRFILE)
nCreateOptions |= FILE_DIRECTORY_FILE;
/* creation disposition */
if((oflag & O_CREAT) == O_CREAT)
if((oflag & O_EXCL) == O_EXCL)
nCreateDisposition = FILE_CREATE; /* O_CREAT + O_EXCL: create file, fail if file exists */
else
nCreateDisposition = FILE_OPEN_IF; /* O_CREAT: open file, create if file doesn't exist */
else if((oflag & O_TRUNC) == O_TRUNC)
nCreateDisposition = FILE_OVERWRITE; /* O_TRUNC: truncate existing file */
else
nCreateDisposition = FILE_OPEN; /* normal: open file, fail if file doesn't exist */
/* lock the environment */
__PdxAcquirePdataLock();
/* convert the path into a native path */
if(!__PdxPosixPathNameToNtPathName((LPWSTR)path, __PdxGetNativePathBuffer(), __PdxGetCurDir(), NULL))
{
__PdxReleasePdataLock();
return (-1);
}
/* set file generic object attributes */
oaFileAttribs.Length = sizeof(oaFileAttribs);
oaFileAttribs.RootDirectory = __PdxGetRootHandle();
oaFileAttribs.ObjectName = &wstrNativePath;
oaFileAttribs.Attributes = OBJ_INHERIT; /* child processes inherit all file descriptors */
oaFileAttribs.SecurityDescriptor = NULL;
oaFileAttribs.SecurityQualityOfService = NULL;
/* open or create the file */
nErrCode = NtCreateFile
(
&hFile,
nDesiredAccess | SYNCHRONIZE,
&oaFileAttribs,
&isbStatus,
NULL,
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nCreateDisposition,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
nCreateOptions
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
ERR("NtCreateFile() failed with status 0x%08X", nErrCode);
__PdxReleasePdataLock();
errno = __status_to_errno(nErrCode);
return (-1);
}
/* initialize descriptor constructor */
memset(&fdDescriptor, 0, sizeof(fdDescriptor));
fdDescriptor.FileHandle = hFile;
fdDescriptor.OpenFlags = oflag;
/* allocate a new file descriptor */
nFileNo = fcntl(0, F_NEWFD, &fdDescriptor);
/* unlock the environment */
__PdxReleasePdataLock();
/* could not allocate the file descriptor */
if(nFileNo < 0)
{
NtClose(hFile);
return (-1);
}
/* return the file number */
return (nFileNo);
}
int creat(const char *path, mode_t mode)
{
return (open(path, O_WRONLY | O_CREAT | O_TRUNC, mode));
}
int _Wcreat(const wchar_t *path, mode_t mode)
{
return (_Wopen(path, O_WRONLY | O_CREAT | O_TRUNC, mode));
}
/* EOF */

View file

@ -0,0 +1,114 @@
/* $Id: basename.c,v 1.1 2002/02/20 07:06:51 hyperion Exp $
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/libgen/basename.c
* PURPOSE: Return the last component of a pathname
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 15/02/2002: Created
*/
#include <sys/types.h>
#include <libgen.h>
#include <wchar.h>
#include <psx/path.h>
static const char *__basename_dot = ".";
static const wchar_t *__Wbasename_dot = L".";
char *basename(char *path)
{
char *pcTail;
size_t nStrLen;
/* null or empty string */
if(path == 0 && ((nStrLen = strlen(path)) == 0))
return ((char *)__basename_dot);
if(nStrLen == 1)
{
/* path is "/", return "/" */
if(IS_CHAR_DELIMITER_A(path[0]))
{
path[0] = '/';
path[1] = 0;
return (path);
}
/* path is a single character, return it */
else
{
return (path);
}
}
/* tail of the string (null terminator excluded) */
pcTail = &path[nStrLen - 1];
/* skip trailing slashes */
while(pcTail > path && IS_CHAR_DELIMITER_A(*pcTail))
pcTail --;
pcTail[1] = 0;
/* go backwards until a delimiter char or the beginning of the string */
while(pcTail >= path)
/* delimiter found, return the basename */
if(IS_CHAR_DELIMITER_A(*pcTail))
return (&pcTail[1]);
else
pcTail --;
/* return all the path */
return (path);
}
wchar_t *_Wbasename(wchar_t *path)
{
wchar_t *pwcTail;
size_t nStrLen;
/* null or empty string */
if(path == 0 && ((nStrLen = wcslen(path)) == 0))
return ((wchar_t *)__Wbasename_dot);
if(nStrLen == 1)
{
/* path is "/", return "/" */
if(IS_CHAR_DELIMITER_U(path[0]))
{
path[0] = L'/';
path[1] = 0;
return (path);
}
/* path is a single character, return it */
else
{
return (path);
}
}
/* tail of the string (null terminator excluded) */
pwcTail = &path[nStrLen - 1];
/* skip trailing slashes */
while(pwcTail > path && IS_CHAR_DELIMITER_U(*pwcTail))
pwcTail --;
pwcTail[1] = 0;
/* go backwards until a delimiter char or the beginning of the string */
while(pwcTail >= path)
/* delimiter found, return the basename */
if(IS_CHAR_DELIMITER_U(*pwcTail))
return (&pwcTail[1]);
else
pwcTail --;
/* return all the path */
return (path);
}
/* EOF */

View file

@ -0,0 +1,234 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/misc/fdtable.c
* PURPOSE: File descriptors table functions
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 12/02/2002: Created
*/
#include <string.h>
#include <errno.h>
#include <psx/fdtable.h>
#include <psx/stdlib.h>
#include <psx/debug.h>
#include <psx/safeobj.h>
int __fdtable_init(__fdtable_t * fdtable)
{
if(fdtable == 0)
{
errno = EINVAL;
return (-1);
}
memset(fdtable, 0, sizeof(*fdtable));
fdtable->Signature = __FDTABLE_MAGIC;
return (0);
}
int __fdtable_free(__fdtable_t * fdtable)
{
if(fdtable == 0)
{
errno = EINVAL;
return (-1);
}
__free(&fdtable->Descriptors);
memset(fdtable, 0, sizeof(*fdtable));
fdtable->Signature = MAGIC('B', 'A', 'A', 'D');
return (0);
}
int __fdtable_entry_isavail(__fdtable_t * fdtable, int fileno)
{
return ((fdtable->DescriptorsBitmap[fileno / 32] >> (fileno % 32)) % 2);
}
int __fdtable_entry_nextavail(__fdtable_t * fdtable, int fileno)
{
int nCurMapIndex;
int nUnusedIndex;
uint32_t nCurMapCell;
nUnusedIndex = fileno;
/* The file descriptors bitmap is an array of 32 bit unsigned integers (32 bit
integers were chosen for proper data alignment without padding). The array is
big enough to hold at least OPEN_MAX bits, that is it has OPEN_MAX / 32 cells
(see also the __fdtable_t definition in psx/fdtable.h). Bits correspond to
file numbers: if a bit is 1, the corresponding file number is in use, else
it's unused. Bit numbering is right-to-left wise, that is the rightmost (least
significative) bit of cell 0 corresponds to file number 0, the leftmost (most
significative) bit of cell 0 to file number 7, the leftmost bit of cell 1 to
file number 8, and so on
*/
/* NOTE: I'm sure the algorytm can be greatly optimized, but I prefer to privilege
readability - it allows for more maintenable code. Please don't pretend to
outsmart the compiler: such optimizations as performing divisions as bit shifts
are useless */
/* index of the bitmap cell containing nUnusedIndex */
nCurMapIndex = nUnusedIndex / 32;
/* get a copy of the bitmap cell containg nUnusedIndex, and shift it to the right
so that the rightmost (least significative) bit is the one referencing nUnusedIndex */
nCurMapCell = fdtable->DescriptorsBitmap[nCurMapIndex] >> (nUnusedIndex % 32);
while(1)
{
/* if the least significative bit of the current cell is 0, we've found an unused
fileno, and we return it */
if((nCurMapCell % 2) == 0)
return (nUnusedIndex);
/* on to next fileno */
nUnusedIndex ++;
/* this is NOT a failure. -1 with undefined errno means that no unused file
number exists */
if(nUnusedIndex >= OPEN_MAX)
return (-1);
/* this fileno is referenced in the next cell */
if((nUnusedIndex % 32) == 0)
{
nCurMapIndex ++;
nCurMapCell = fdtable->DescriptorsBitmap[nCurMapIndex];
}
/* on to next fileno (bit) in the current cell */
else
nCurMapCell >>= 1;
}
return (-1);
}
int __fdtable_entry_add(__fdtable_t * fdtable, int fileno, __fildes_t * fildes, __fildes_t ** newfd)
{
int nFileNo;
/* descriptors count reached OPEN_MAX */
if(fdtable->UsedDescriptors >= OPEN_MAX)
{
ERR("file descriptor table full");
errno = EMFILE;
return (-1);
}
/* base fileno less than zero: use the lowest unused fileno */
if(fileno < 0)
nFileNo = fdtable->LowestUnusedFileNo;
/* base fileno greater than or equal to zero: use the next available fileno */
else
nFileNo = __fdtable_entry_nextavail(fdtable, fileno);
INFO("lowest unused file number is %d", nFileNo);
/* descriptors count reached OPEN_MAX */
if(nFileNo < 0)
{
ERR("nFileNo is less than zero");
errno = EMFILE;
return (-1);
}
/* if the table doesn't have enough space for the next entry ... */
if(nFileNo >= fdtable->AllocatedDescriptors)
{
void * pTemp;
INFO
(
"growing the array from %lu to %lu bytes",
fdtable->AllocatedDescriptors * sizeof(*fdtable->Descriptors),
(nFileNo + 1) * sizeof(*fdtable->Descriptors)
);
/* ... try to increase the size of the table */
pTemp = __realloc
(
fdtable->Descriptors,
(nFileNo + 1) * sizeof(*fdtable->Descriptors)
);
/* reallocation failed */
if(pTemp == 0)
{
ERR("__realloc() failed");
errno = ENOMEM;
return (-1);
}
/* update the table */
fdtable->AllocatedDescriptors = nFileNo + 1;
fdtable->Descriptors = pTemp;
}
/* initialize descriptor */
if(fildes == 0)
memset(&fdtable->Descriptors[nFileNo], 0, sizeof(__fildes_t));
else
memcpy(&fdtable->Descriptors[nFileNo], fildes, sizeof(__fildes_t));
if(newfd != 0)
*newfd = &fdtable->Descriptors[nFileNo];
INFO
(
"file number %d: handle 0x%08X, open flags 0x%08X, flags 0x%08X, extra data size %u, extra data at 0x%08X",
nFileNo,
fdtable->Descriptors[nFileNo].FileHandle,
fdtable->Descriptors[nFileNo].OpenFlags,
fdtable->Descriptors[nFileNo].FdFlags,
fdtable->Descriptors[nFileNo].ExtraDataSize,
fdtable->Descriptors[nFileNo].ExtraData
);
INFO
(
"incrementing used descriptors count from %u to %u",
fdtable->UsedDescriptors,
fdtable->UsedDescriptors + 1
);
fdtable->UsedDescriptors ++;
INFO
(
"setting bit %u of cell %u of the bitmap to 1",
nFileNo % 32,
nFileNo / 32
);
fdtable->DescriptorsBitmap[nFileNo / 32] |= (1 << (nFileNo % 32));
fdtable->LowestUnusedFileNo = __fdtable_entry_nextavail(fdtable, nFileNo);
INFO("setting the lowest unused file number to %d", fdtable->LowestUnusedFileNo);
return (nFileNo);
}
int __fdtable_entry_remove(__fdtable_t * fdtable, int fileno)
{
return (-1);
}
__fildes_t *__fdtable_entry_get(__fdtable_t * fdtable, int fileno)
{
/* this fileno hasn't been allocated */
if(fileno >= fdtable->AllocatedDescriptors)
return (0);
return (&fdtable->Descriptors[fileno]);
}
/* EOF */

View file

@ -0,0 +1,83 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/misc/interlock.c
* PURPOSE: inter-locked increments/decrements
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 20/01/2002: Adapted from lib/kernel32/synch/intrlck.c
*/
/*
* NOTE by KJK::Hyperion: I do not understand what's behind these functions.
* Don't ask me how they work, or to fix errors in them.
* Please refer to the authors referenced in the original
* file, lib/kernel32/synch/intrlck.c
*/
/* TODO? move these in some shared library */
#include <psx/interlock.h>
int __interlock_inc(int * addend)
{
int ret = 0;
__asm__
(
" lock\n" /* for SMP systems */
" incl (%1)\n"
" je 2f\n"
" jl 1f\n"
" incl %0\n"
" jmp 2f\n"
"1: dec %0\n"
"2:\n"
:"=r" (ret):"r" (addend), "0" (0): "memory"
);
return (ret);
}
int __interlock_dec(int * addend)
{
int ret = 0;
__asm__
(
" lock\n" /* for SMP systems */
" decl (%1)\n"
" je 2f\n"
" jl 1f\n"
" incl %0\n"
" jmp 2f\n"
"1: dec %0\n"
"2:\n"
:"=r" (ret):"r" (addend), "0" (0): "memory"
);
return (ret);
}
int __interlock_add(int * addend, int increment)
{
int ret = 0;
__asm__
(
" lock\n" /* for SMP systems */
" xaddl %0,(%1)"
:"=r" (ret)
:"r" (addend), "0" (increment)
:"memory"
);
return (ret);
}
/* EOF */

View file

@ -0,0 +1,19 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/misc/main.c
* PURPOSE: psxdll.dll entry point
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 27/12/2001: Created
*/
int __stdcall DllMain(void *hinstDll, unsigned long int dwReason, void *reserved)
{
return (1);
}
/* EOF */

View file

@ -0,0 +1,460 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/misc/path.c
* PURPOSE: POSIX subsystem path utilities
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 31/01/2002: Created
*/
#include <ddk/ntddk.h>
#include <errno.h>
#include <string.h>
#include <psx/stdlib.h>
#include <psx/pdata.h>
#include <psx/path.h>
BOOLEAN
__PdxPosixPathGetNextComponent_U
(
IN UNICODE_STRING PathName,
IN OUT PUNICODE_STRING PathComponent,
OUT PBOOLEAN TrailingDelimiter OPTIONAL
)
{
int i, j;
USHORT l = PathName.Length / sizeof(WCHAR);
if(PathComponent->Buffer == 0)
i = 0;
else
i = ((ULONG)PathComponent->Buffer - (ULONG)PathName.Buffer + PathComponent->Length) / sizeof(WCHAR);
/* skip leading empty components */
while(1)
if(i >= l)
{
PathComponent->Length = PathComponent->MaximumLength = 0;
return (FALSE);
}
else if(IS_CHAR_DELIMITER_U(PathName.Buffer[i]))
i ++;
else
break;
if(i > l)
{
PathComponent->Length = PathComponent->MaximumLength = 0;
return (FALSE);
}
PathComponent->Buffer = &PathName.Buffer[i];
j = i + 1;
/* advance until the end of the string, or the next delimiter */
while(1)
{
if(j >= l)
{
if(TrailingDelimiter != 0)
*TrailingDelimiter = FALSE;
break;
}
else if (IS_CHAR_DELIMITER_U(PathName.Buffer[j]))
{
if(TrailingDelimiter != 0)
*TrailingDelimiter = TRUE;
break;
}
else
j ++;
}
PathComponent->Length = PathComponent->MaximumLength = (j - i) * sizeof(WCHAR);
return (TRUE);
}
BOOLEAN
__PdxPosixPathResolve_U
(
IN UNICODE_STRING PathName,
OUT PUNICODE_STRING ResolvedPathName,
IN WCHAR PathDelimiter OPTIONAL
)
{
UNICODE_STRING wstrThisComponent = {0, 0, NULL};
PWCHAR pwcCurPos;
PWCHAR pwcStartPos;
BOOLEAN bIsDirectory;
if(PathDelimiter == 0)
PathDelimiter = L'/';
/* start from the beginning of the return buffer */
pwcCurPos = ResolvedPathName->Buffer;
/* path begins with a delimiter (absolute path) */
if(IS_CHAR_DELIMITER_U(PathName.Buffer[0]))
{
/* put a delimiter in front of the return buffer */
*pwcCurPos = PathDelimiter;
/* move to next character */
pwcCurPos ++;
}
pwcStartPos = pwcCurPos;
/* repeat until the end of the path string */
while(__PdxPosixPathGetNextComponent_U(PathName, &wstrThisComponent, &bIsDirectory))
{
/* ".": skip */
if(IS_COMPONENT_DOT_U(wstrThisComponent))
continue;
/* "..": go back to the last component */
else if(IS_COMPONENT_DOTDOT_U(wstrThisComponent))
{
if(pwcCurPos == pwcStartPos)
continue;
/* skip the last (undefined) character */
pwcCurPos --;
/* down to the previous path delimiter */
do{ pwcCurPos --; }while(!IS_CHAR_DELIMITER_U(*pwcCurPos));
/* include the delimiter */
pwcCurPos ++;
}
else
{
/* copy this component into the return string */
memcpy
(
pwcCurPos,
wstrThisComponent.Buffer,
wstrThisComponent.Length
);
/* move the current position to the end of the string */
pwcCurPos = (PWCHAR)((PBYTE)pwcCurPos + wstrThisComponent.Length);
/* component had a trailing delimiter */
if(bIsDirectory)
{
/* append a delimiter */
*pwcCurPos = PathDelimiter;
/* on to next character */
pwcCurPos ++;
}
}
}
/* set the return string's length as the byte offset between the initial buffer
position and the current position */
ResolvedPathName->Length = ((ULONG)pwcCurPos - (ULONG)ResolvedPathName->Buffer);
return (TRUE);
}
BOOLEAN
__PdxPosixPathGetNextComponent_A
(
IN ANSI_STRING PathName,
IN OUT PANSI_STRING PathComponent,
OUT PBOOLEAN TrailingDelimiter OPTIONAL
)
{
int i, j;
if(PathComponent->Buffer == 0)
i = 0;
else
i = ((ULONG)PathComponent->Buffer - (ULONG)PathName.Buffer + PathComponent->Length);
/* skip leading empty components */
while(1)
if(i >= PathName.Length)
{
PathComponent->Length = PathComponent->MaximumLength = 0;
return (FALSE);
}
else if(IS_CHAR_DELIMITER_A(PathName.Buffer[i]))
i ++;
else
break;
if(i > PathName.Length)
{
PathComponent->Length = PathComponent->MaximumLength = 0;
return (FALSE);
}
PathComponent->Buffer = &PathName.Buffer[i];
j = i + 1;
/* advance until the end of the string, or the next delimiter */
while(1)
{
if(j >= PathName.Length)
{
if(TrailingDelimiter != 0)
*TrailingDelimiter = FALSE;
break;
}
else if (IS_CHAR_DELIMITER_A(PathName.Buffer[j]))
{
if(TrailingDelimiter != 0)
*TrailingDelimiter = TRUE;
break;
}
else
j ++;
}
PathComponent->Length = PathComponent->MaximumLength = j - i;
return (TRUE);
}
BOOLEAN
__PdxPosixPathResolve_A
(
IN ANSI_STRING PathName,
OUT PANSI_STRING ResolvedPathName,
IN CHAR PathDelimiter OPTIONAL
)
{
ANSI_STRING strThisComponent = {0, 0, NULL};
PCHAR pcCurPos;
PCHAR pcStartPos;
BOOLEAN bIsDirectory;
if(PathDelimiter == 0)
PathDelimiter = '/';
/* start from the beginning of the return buffer */
pcCurPos = ResolvedPathName->Buffer;
/* path begins with a delimiter (absolute path) */
if(IS_CHAR_DELIMITER_A(PathName.Buffer[0]))
{
/* put a delimiter in front of the return buffer */
*pcCurPos = PathDelimiter;
/* move to next character */
pcCurPos ++;
}
pcStartPos = pcCurPos;
/* repeat until the end of the path string */
while(__PdxPosixPathGetNextComponent_A(PathName, &strThisComponent, &bIsDirectory))
{
/* ".": skip */
if(IS_COMPONENT_DOT_A(strThisComponent))
continue;
/* "..": go back to the last component */
else if(IS_COMPONENT_DOTDOT_A(strThisComponent))
{
if(pcCurPos == pcStartPos)
continue;
/* skip the last (undefined) character */
pcCurPos --;
/* down to the previous path delimiter */
do{ pcCurPos --; }while(!IS_CHAR_DELIMITER_A(*pcCurPos));
/* include the delimiter */
pcCurPos ++;
}
else
{
/* copy this component into the return string */
strncpy
(
pcCurPos,
strThisComponent.Buffer,
strThisComponent.Length
);
/* move the current position to the end of the string */
pcCurPos = (PCHAR)((PBYTE)pcCurPos + strThisComponent.Length);
/* component had a trailing delimiter */
if(bIsDirectory)
{
/* append a delimiter */
*pcCurPos = PathDelimiter;
/* on to next character */
pcCurPos ++;
}
}
}
/* set the return string's length as the byte offset between the initial buffer
position and the current position */
ResolvedPathName->Length = ((ULONG)pcCurPos - (ULONG)ResolvedPathName->Buffer);
return (TRUE);
}
BOOLEAN
__PdxPosixPathNameToNtPathName
(
IN PWCHAR PosixPath,
OUT PUNICODE_STRING NativePath,
IN PUNICODE_STRING CurDir OPTIONAL,
IN PUNICODE_STRING RootDir OPTIONAL
)
{
UNICODE_STRING wstrPosixPath;
UNICODE_STRING wstrTempString;
/* parameter validation */
if
(
PosixPath == 0 ||
NativePath == 0 ||
NativePath->Buffer == 0 ||
NativePath->MaximumLength == 0 ||
(RootDir != 0 && RootDir->Buffer == 0)
)
{
errno = EINVAL;
return (FALSE);
}
RtlInitUnicodeString(&wstrPosixPath, PosixPath);
/* path is null */
if(0 == wstrPosixPath.Length)
{
errno = EINVAL;
return (FALSE);
}
/* first, copy the root path into the return buffer */
/* if no root dir passed by the caller... */
if(RootDir == 0)
/* return buffer too small */
if(NativePath->MaximumLength < sizeof(WCHAR))
{
errno = ENOBUFS;
return (FALSE);
}
/* set the first character to a backslash, and set length accordingly */
else
{
NativePath->Buffer[0] = L'\\';
NativePath->Length = sizeof(WCHAR);
}
/* ... else copy the root dir into the return buffer */
else
/* return buffer too small */
if(NativePath->MaximumLength < RootDir->Length)
{
errno = ENOBUFS;
return (FALSE);
}
/* copy the root directory into the return buffer, and set length */
else
{
memcpy(NativePath->Buffer, RootDir->Buffer, RootDir->Length);
NativePath->Length = RootDir->Length;
}
/* path is "/" - our work is done */
if(sizeof(WCHAR) == wstrPosixPath.Length && IS_CHAR_DELIMITER_U(wstrPosixPath.Buffer[0]))
return (TRUE);
/* temp string pointing to the tail of the return buffer */
wstrTempString.Length = 0;
wstrTempString.MaximumLength = NativePath->MaximumLength - NativePath->Length;
wstrTempString.Buffer = (PWCHAR)(((PBYTE)(NativePath->Buffer)) + NativePath->Length);
/* path begins with '/': absolute path. Append the resolved path to the return buffer */
if(IS_CHAR_DELIMITER_U(wstrPosixPath.Buffer[0]))
{
/* copy the resolved path in the return buffer */
__PdxPosixPathResolve_U(wstrPosixPath, &wstrTempString, L'\\');
return (TRUE);
}
else
{
UNICODE_STRING wstrAbsolutePath;
if(CurDir == 0)
CurDir = __PdxGetCurDir();
/* initialize the buffer for the absolute path */
wstrAbsolutePath.Length = 0;
wstrAbsolutePath.MaximumLength = 0xFFFF;
wstrAbsolutePath.Buffer = __malloc(0xFFFF);
/* if the current directory is not null... */
if(!(CurDir->Buffer == 0 || CurDir->Length == 0))
{
/* copy it into the absolute path buffer */
memcpy(wstrAbsolutePath.Buffer, CurDir->Buffer, CurDir->Length);
wstrAbsolutePath.Length += CurDir->Length;
}
/* not enough space to append an extra slash */
if((wstrAbsolutePath.MaximumLength - wstrAbsolutePath.Length) < (USHORT)sizeof(WCHAR))
{
__free(wstrAbsolutePath.Buffer);
NativePath->Length = 0;
errno = ENOBUFS;
return (FALSE);
}
/* append an extra slash */
wstrAbsolutePath.Buffer[wstrAbsolutePath.Length / sizeof(WCHAR)] = L'/';
wstrAbsolutePath.Length += sizeof(WCHAR);
/* not enough space to copy the relative path */
if((wstrAbsolutePath.MaximumLength - wstrAbsolutePath.Length) < wstrPosixPath.Length)
{
__free(wstrAbsolutePath.Buffer);
NativePath->Length = 0;
errno = ENOBUFS;
return (FALSE);
}
/* append the relative path to the absolute path */
memcpy(
(PWCHAR)(((PBYTE)wstrAbsolutePath.Buffer) + wstrAbsolutePath.Length),
wstrPosixPath.Buffer,
wstrPosixPath.Length
);
wstrAbsolutePath.Length += wstrPosixPath.Length;
/* resolve the path */
__PdxPosixPathResolve_U(wstrAbsolutePath, &wstrTempString, L'\\');
__free(wstrAbsolutePath.Buffer);
return (TRUE);
}
return (FALSE);
}
/* EOF */

View file

@ -0,0 +1,45 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/misc/safeobj.c
* PURPOSE: safe checking of user-provided objects
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 09/01/2002: Created
*/
#include <psx/safeobj.h>
#include <psx/debug.h>
int __safeobj_validate(void *obj, __magic_t refsignature)
{
if(obj == 0)
return (0);
else
{
/* cast the object to a magic number */
__magic_t mSignature = *((__magic_t *)obj);
ERRIF
(
mSignature != refsignature,
"invalid object at %X: signature is \"%c%c%c%c\", should be \"%c%c%c%c\"",
obj,
MAGIC_DECOMPOSE(refsignature),
MAGIC_DECOMPOSE(mSignature)
);
if(mSignature == refsignature)
/* signatures match: ok */
return (-1);
else
/* signatures mismatch: fail */
return (0);
}
}
/* EOF */

View file

@ -0,0 +1,15 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS POSIX+ Subsystem
* FILE:
* PURPOSE:
* PROGRAMMER:
* UPDATE HISTORY:
* : Created
*/
/* EOF */

143
posix/lib/psxdll/psxdll.def Normal file
View file

@ -0,0 +1,143 @@
; $Id: psxdll.def,v 1.1 2002/02/20 07:06:50 hyperion Exp $
;
; ReactOS POSIX Client Library
;
LIBRARY PSXDLL.DLL
EXPORTS
;dirent
opendir
readdir
closedir
;dlfcn
dlopen
dlclose
dlsym
dlerror
;errno
__PdxGetThreadErrNum
;fcntl
open
creat
fcntl
;libgen
basename
;misc
;path
__PdxPosixPathGetNextComponent_A
__PdxPosixPathGetNextComponent_U
__PdxPosixPathResolve_A
__PdxPosixPathResolve_U
__PdxPosixPathNameToNtPathName
;fdtable
__fdtable_init
__fdtable_free
__fdtable_entry_nextavail
__fdtable_entry_add
__fdtable_entry_remove
__fdtable_entry_get
;safeobj
__safeobj_validate
;pthread
pthread_create
pthread_exit
pthread_join
pthread_mutex_destroy
pthread_mutex_init
pthread_mutex_lock
pthread_mutex_trylock
pthread_mutex_unlock
pthread_mutex_getprioceiling
pthread_mutex_setprioceiling
pthread_mutexattr_destroy
pthread_mutexattr_getpshared
pthread_mutexattr_init
pthread_mutexattr_setpshared
pthread_mutexattr_gettype
pthread_mutexattr_settype
pthread_mutexattr_getprioceiling
pthread_mutexattr_getprotocol
pthread_mutexattr_setprioceiling
pthread_mutexattr_setprotocol
;sched
sched_yield
;signal
pthread_kill
raise
;stdio
printf
gets
;stdlib
abort
malloc
realloc
free
calloc
exit
;string
;forward-exports to NTDLL
memchr
memcmp
memcpy
memmove
memset
strcat
strchr
strcmp
strcpy
strcspn
strlen
strncat
strncmp
strncpy
strpbrk
strrchr
strspn
strstr
;implemented internally
strdup
;sys/utsname
uname
;unistd
close
dup
dup2
getcwd
getpid
getppid
;wchar
;forward-exports to NTDLL
wcscat
wcschr
wcscmp
wcscpy
wcscspn
wcslen
wcsncat
wcsncmp
wcsncpy
wcspbrk
wcsrchr
wcsspn
wcsstr
wcstol
wcstombs
wcstoul
;implemented internally
;EOF

143
posix/lib/psxdll/psxdll.edf Normal file
View file

@ -0,0 +1,143 @@
; $Id: psxdll.edf,v 1.1 2002/02/20 07:06:50 hyperion Exp $
;
; ReactOS POSIX Client Library
;
LIBRARY PSXDLL.DLL
EXPORTS
;dirent
opendir=opendir
readdir=readdir
closedir=closedir
;dlfcn
dlopen=dlopen
dlclose=dlclose
dlsym=dlsym
dlerror=dlerror
;errno
__PdxGetThreadErrNum=__PdxGetThreadErrNum
;fcntl
open=open
creat=creat
fcntl=fcntl
;libgen
basename=basename
;misc
;path
__PdxPosixPathGetNextComponent_A=__PdxPosixPathGetNextComponent_A
__PdxPosixPathGetNextComponent_U=__PdxPosixPathGetNextComponent_U
__PdxPosixPathResolve_A=__PdxPosixPathResolve_A
__PdxPosixPathResolve_U=__PdxPosixPathResolve_U
__PdxPosixPathNameToNtPathName=__PdxPosixPathNameToNtPathName
;fdtable
__fdtable_init=__fdtable_init
__fdtable_free=__fdtable_free
__fdtable_entry_nextavail=__fdtable_entry_nextavail
__fdtable_entry_add=__fdtable_entry_add
__fdtable_entry_remove=__fdtable_entry_remove
__fdtable_entry_get=__fdtable_entry_get
;safeobj
__safeobj_validate=__safeobj_validate
;pthread
pthread_create=pthread_create
pthread_exit=pthread_exit
pthread_join=pthread_join
pthread_mutex_destroy=pthread_mutex_destroy
pthread_mutex_init=pthread_mutex_init
pthread_mutex_lock=pthread_mutex_lock
pthread_mutex_trylock=pthread_mutex_trylock
pthread_mutex_unlock=pthread_mutex_unlock
pthread_mutex_getprioceiling=pthread_mutex_getprioceiling
pthread_mutex_setprioceiling=pthread_mutex_setprioceiling
pthread_mutexattr_destroy=pthread_mutexattr_destroy
pthread_mutexattr_getpshared=pthread_mutexattr_getpshared
pthread_mutexattr_init=pthread_mutexattr_init
pthread_mutexattr_setpshared=pthread_mutexattr_setpshared
pthread_mutexattr_gettype=pthread_mutexattr_gettype
pthread_mutexattr_settype=pthread_mutexattr_settype
pthread_mutexattr_getprioceiling=pthread_mutexattr_getprioceiling
pthread_mutexattr_getprotocol=pthread_mutexattr_getprotocol
pthread_mutexattr_setprioceiling=pthread_mutexattr_setprioceiling
pthread_mutexattr_setprotocol=pthread_mutexattr_setprotocol
;sched
sched_yield=sched_yield
;signal
pthread_kill=pthread_kill
raise=raise
;stdio
printf=MSVCRT.printf
gets=MSVCRT.gets
;stdlib
abort=abort
malloc=malloc
realloc=realloc
free=free
calloc=calloc
exit=exit
;string
;forward-exports to NTDLL
memchr=NTDLL.memchr
memcmp=NTDLL.memcmp
memcpy=NTDLL.memcpy
memmove=NTDLL.memmove
memset=NTDLL.memset
strcat=NTDLL.strcat
strchr=NTDLL.strchr
strcmp=NTDLL.strcmp
strcpy=NTDLL.strcpy
strcspn=NTDLL.strcspn
strlen=NTDLL.strlen
strncat=NTDLL.strncat
strncmp=NTDLL.strncmp
strncpy=NTDLL.strncpy
strpbrk=NTDLL.strpbrk
strrchr=NTDLL.strrchr
strspn=NTDLL.strspn
strstr=NTDLL.strstr
;implemented internally
strdup
;sys/utsname
uname=uname
;unistd
close=close
dup=dup
dup2=dup2
getcwd=getcwd
getpid=getpid
getppid=getppid
;wchar
;forward-exports to NTDLL
wcscat=NTDLL.wcscat
wcschr=NTDLL.wcschr
wcscmp=NTDLL.wcscmp
wcscpy=NTDLL.wcscpy
wcscspn=NTDLL.wcscspn
wcslen=NTDLL.wcslen
wcsncat=NTDLL.wcsncat
wcsncmp=NTDLL.wcsncmp
wcsncpy=NTDLL.wcsncpy
wcspbrk=NTDLL.wcspbrk
wcsrchr=NTDLL.wcsrchr
wcsspn=NTDLL.wcsspn
wcsstr=NTDLL.wcsstr
wcstol=NTDLL.wcstol
wcstombs=NTDLL.wcstombs
wcstoul=NTDLL.wcstoul
;implemented internally
;EOF

View file

@ -0,0 +1,39 @@
/* $Id: psxdll.rc,v 1.1 2002/02/20 07:06:50 hyperion Exp $
*/
#include <defines.h>
#include <reactos/resource.h>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
VS_VERSION_INFO VERSIONINFO
FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", RES_STR_COMPANY_NAME
VALUE "FileDescription", "Posix Client DLL\0"
VALUE "FileVersion", RES_STR_FILE_VERSION
VALUE "InternalName", "psxdll\0"
VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT
VALUE "OriginalFilename", "psxdll.dll\0"
VALUE "ProductName", RES_STR_PRODUCT_NAME
VALUE "ProductVersion", RES_STR_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View file

@ -0,0 +1,198 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/pthread/create.c
* PURPOSE: Thread creation
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 19/12/2001: Created
*/
#include <ddk/ntddk.h>
#include <string.h>
#include <sys/types.h>
#include <pthread.h>
#include <psx/debug.h>
#include <psx/errno.h>
#include <napi/i386/segment.h>
/* thread creation code adapted from kernel32's CreateRemoteThread() function */
static void __threadentry (void *(*start_routine)(void*), void *arg)
{
INFO("hello world! thread successfully created");
TODO("initialize thread data");
TODO("notify DLLs");
TODO("notify psxss");
INFO("about to call start routine at %#x with argument %#x", start_routine, arg);
pthread_exit(start_routine(arg));
}
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void*), void *arg)
{
HANDLE hThread;
OBJECT_ATTRIBUTES oaThreadAttrs;
CLIENT_ID ciId;
CONTEXT cxThreadContext;
INITIAL_TEB itInitialTeb;
BOOLEAN fSuspended;
ULONG nOldPageProtection;
NTSTATUS nErrCode;
/* initialize generic object attributes */
oaThreadAttrs.Length = sizeof(OBJECT_ATTRIBUTES);
oaThreadAttrs.RootDirectory = NULL;
oaThreadAttrs.ObjectName = NULL;
oaThreadAttrs.Attributes = 0;
oaThreadAttrs.SecurityDescriptor = NULL;
oaThreadAttrs.SecurityQualityOfService = NULL;
/* initialize thread attributes */
fSuspended = FALSE; /* FIXME? really needed? can we hardcode this to FALSE? */
/* stack attributes */
FIXME("stack size defaulted to 0x100000 - thread attributes ignored");
/* stack reserve size */
itInitialTeb.StackReserve = 0x100000;
/* stack commit size */
itInitialTeb.StackCommit = itInitialTeb.StackReserve - PAGESIZE;
/* guard page */
itInitialTeb.StackCommit += PAGESIZE;
/* reserve stack */
itInitialTeb.StackAllocate = NULL;
nErrCode = NtAllocateVirtualMemory
(
NtCurrentProcess(),
&itInitialTeb.StackAllocate,
0,
&itInitialTeb.StackReserve,
MEM_RESERVE,
PAGE_READWRITE
);
if(!NT_SUCCESS(nErrCode))
{
return (__status_to_errno(nErrCode)); /* FIXME? TODO? pthread specific error codes? */
}
itInitialTeb.StackBase = (PVOID)((ULONG)itInitialTeb.StackAllocate + itInitialTeb.StackReserve);
itInitialTeb.StackLimit = (PVOID)((ULONG)itInitialTeb.StackBase - itInitialTeb.StackCommit);
/* commit stack */
nErrCode = NtAllocateVirtualMemory
(
NtCurrentProcess(),
&itInitialTeb.StackLimit,
0,
&itInitialTeb.StackCommit,
MEM_COMMIT,
PAGE_READWRITE
);
if(!NT_SUCCESS(nErrCode))
{
NtFreeVirtualMemory
(
NtCurrentProcess(),
itInitialTeb.StackAllocate,
&itInitialTeb.StackReserve,
MEM_RELEASE
);
return (__status_to_errno(nErrCode));
}
/* protect guard page */
nErrCode = NtProtectVirtualMemory
(
NtCurrentProcess(),
itInitialTeb.StackLimit,
PAGESIZE,
PAGE_GUARD | PAGE_READWRITE,
&nOldPageProtection
);
if(!NT_SUCCESS(nErrCode))
{
NtFreeVirtualMemory
(
NtCurrentProcess(),
itInitialTeb.StackAllocate,
&itInitialTeb.StackReserve,
MEM_RELEASE
);
return (__status_to_errno(nErrCode));
}
/* initialize thread registers */
//#ifdef __i386__
memset(&cxThreadContext, 0, sizeof(CONTEXT));
cxThreadContext.Eip = (LONG)__threadentry;
cxThreadContext.SegGs = USER_DS;
cxThreadContext.SegFs = TEB_SELECTOR;
cxThreadContext.SegEs = USER_DS;
cxThreadContext.SegDs = USER_DS;
cxThreadContext.SegCs = USER_CS;
cxThreadContext.SegSs = USER_DS;
cxThreadContext.Esp = (ULONG)itInitialTeb.StackBase - 12;
cxThreadContext.EFlags = (1<<1) + (1<<9);
/* initialize call stack */
*((PULONG)((ULONG)itInitialTeb.StackBase - 4)) = (ULONG)arg; /* thread argument */
*((PULONG)((ULONG)itInitialTeb.StackBase - 8)) = (ULONG)start_routine; /* thread start routine */
*((PULONG)((ULONG)itInitialTeb.StackBase - 12)) = 0xDEADBEEF; /* "shouldn't see me" */
//#else
//#error Unsupported architecture
//#endif
INFO("about to create new thread - start routine at %#x, argument %#x", start_routine, arg);
/* create thread */
nErrCode = NtCreateThread
(
&hThread,
THREAD_ALL_ACCESS,
&oaThreadAttrs,
NtCurrentProcess(),
&ciId,
&cxThreadContext,
&itInitialTeb,
fSuspended
);
if(!NT_SUCCESS(nErrCode))
{
NtFreeVirtualMemory
(
NtCurrentProcess(),
itInitialTeb.StackAllocate,
&itInitialTeb.StackReserve,
MEM_RELEASE
);
return (__status_to_errno(nErrCode));
}
/* FIXME? should we return the thread handle or the thread id? */
if(thread != 0)
*thread = (pthread_t)&ciId.UniqueThread; /* for the moment, we return the id */
return (0);
}
/* EOF */

View file

@ -0,0 +1,78 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/pthread/exit.c
* PURPOSE: Thread termination
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 19/12/2001: Created
*/
#include <ddk/ntddk.h>
#include <ntdll/ldr.h>
#include <errno.h>
#include <stdlib.h>
#include <pthread.h>
#include <psx/debug.h>
void pthread_exit(void *value_ptr)
{
NTSTATUS nErrCode;
BOOLEAN fLastThread;
/* terminate process if this is the last thread of the current process */
nErrCode = NtQueryInformationThread
(
NtCurrentThread(),
ThreadAmILastThread,
&fLastThread,
sizeof(BOOLEAN),
NULL
);
if(NT_SUCCESS(nErrCode))
{
if(fLastThread)
{
INFO("this thread is the last in the current process - about to call exit(0)");
exit(0);
}
}
else
{
WARN
(
"NtQueryInformationThread(ThreadAmILastThread) failed with status %#x. \
Can't determine if the current thread is the last in the process. The process \
could hang",
nErrCode
);
}
TODO("Notify psxss of thread termination");
LdrShutdownThread(); /* detach DLLs */
/* kill this thread */
WARNIF(
sizeof(ULONG) < sizeof(typeof(value_ptr)),
"\
the value returned from the current thread will be truncated (pointers shorter \
than long integers on this architecture?) - expect trouble"
);
INFO("bye bye. Current thread about to die");
NtTerminateThread(NtCurrentThread(), (ULONG)value_ptr);
/* "The pthread_exit() function cannot return to its caller." */
NtDelayExecution(FALSE, NULL);
}
/* EOF */

View file

@ -0,0 +1,98 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/pthread/join.c
* PURPOSE: Wait for thread termination
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 19/12/2001: Created
*/
#include <ddk/ntddk.h>
#include <ntdll/ldr.h>
#include <errno.h>
#include <sys/types.h>
#include <pthread.h>
#include <psx/debug.h>
#include <psx/errno.h>
int pthread_join(pthread_t thread, void **value_ptr)
{
HANDLE hThread;
NTSTATUS nErrCode;
OBJECT_ATTRIBUTES oaThreadAttrs;
CLIENT_ID ciId;
THREAD_BASIC_INFORMATION tbiThreadInfo;
/* "[EDEADLK] A deadlock was detected or the value of thread specifies
the calling thread" */
if(thread == pthread_self())
return (EDEADLK);
/* initialize id */
ciId.UniqueProcess = (HANDLE)-1;
ciId.UniqueThread = (HANDLE)thread;
/* initialize object attributes */
oaThreadAttrs.Length = sizeof(OBJECT_ATTRIBUTES);
oaThreadAttrs.RootDirectory = NULL;
oaThreadAttrs.ObjectName = NULL;
oaThreadAttrs.Attributes = 0;
oaThreadAttrs.SecurityDescriptor = NULL;
oaThreadAttrs.SecurityQualityOfService = NULL;
/* open the thread */
nErrCode = NtOpenThread
(
&hThread,
SYNCHRONIZE | THREAD_QUERY_INFORMATION,
&oaThreadAttrs,
&ciId
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
return (__status_to_errno(nErrCode));
}
/* wait for thread termination */
nErrCode = NtWaitForSingleObject
(
hThread,
FALSE,
NULL
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
NtClose(hThread);
return (__status_to_errno(nErrCode));
}
/* get thread basic information (includes return code) */
nErrCode = NtQueryInformationThread
(
hThread,
ThreadBasicInformation,
&tbiThreadInfo,
sizeof(THREAD_BASIC_INFORMATION),
NULL
);
NtClose(hThread);
if(!value_ptr)
return (EFAULT);
*value_ptr = (void *)tbiThreadInfo.ExitStatus;
return (0);
}
/* EOF */

View file

@ -0,0 +1,22 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/pthread/kill.c
* PURPOSE: Send a signal to a thread
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 15/02/2002: Created
*/
#include <signal.h>
#include <errno.h>
int pthread_kill(pthread_t thread, int sig)
{
return (ENOSYS);
}
/* EOF */

View file

@ -0,0 +1,465 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/pthread/mutex.c
* PURPOSE: Mutex functions
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 19/12/2001: Created
*/
#include <ntos.h>
#include <ddk/ntddk.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <psx/debug.h>
#include <psx/pthread.h>
#include <psx/errno.h>
#include <psx/safeobj.h>
int pthread_mutex_init(pthread_mutex_t *mutex,
const pthread_mutexattr_t *attr)
{
struct __mutex *pmMutex;
struct __mutexattr *pmaMutexAttrs;
BOOL bShared;
OBJECT_ATTRIBUTES oaMutexAttrs;
NTSTATUS nErrCode;
/* invalid return buffer */
if(mutex == NULL)
return (EINVAL);
/* object still open */
if(__safeobj_validate(*mutex, __PTHREAD_MUTEX_MAGIC))
return (EBUSY);
if(attr == NULL)
{
/* use default attributes */
/* create new mutex object */
pmMutex = (struct __mutex *)malloc(sizeof(struct __mutex));
/* malloc() failure */
if(!pmMutex)
return (ENOMEM);
/* set the attributes */
bShared = FALSE;
pmMutex->type = PTHREAD_MUTEX_RECURSIVE;
}
else if(__safeobj_validate(*attr, __PTHREAD_MUTEX_ATTR_MAGIC))
{
/* use provided attributes */
/* create new mutex object */
pmMutex = (struct __mutex *)malloc(sizeof(struct __mutex));
/* malloc() failure */
if(!pmMutex)
return (ENOMEM);
/* get the attributes object */
pmaMutexAttrs = (struct __mutexattr *) *attr;
/* set the attributes */
bShared = (pmaMutexAttrs->pshared != PTHREAD_PROCESS_PRIVATE);
pmMutex->type = pmaMutexAttrs->type;
}
else
return (EINVAL);
/* necessary for the mutex to be considered valid later */
pmMutex->signature = __PTHREAD_MUTEX_MAGIC;
/* creation of the native mutex object */
pmMutex->handle = 0;
/* initialize generic object attributes */
oaMutexAttrs.Length = sizeof(OBJECT_ATTRIBUTES);
oaMutexAttrs.RootDirectory = NULL;
oaMutexAttrs.ObjectName = NULL;
oaMutexAttrs.Attributes = 0;
oaMutexAttrs.SecurityDescriptor = NULL;
oaMutexAttrs.SecurityQualityOfService = NULL;
/* process-exclusive mutex */
if(bShared)
oaMutexAttrs.Attributes |= OBJ_EXCLUSIVE;
/* try to create the object */
nErrCode = NtCreateMutant
(
&pmMutex->handle,
MUTANT_ALL_ACCESS,
&oaMutexAttrs,
FALSE
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
/* free the internal mutex object */
free(pmMutex);
/* return errno */
return (__status_to_errno(nErrCode));
}
/* return the pointer to the mutex */
*mutex = (pthread_mutex_t)pmMutex;
/* success */
return (0);
}
int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
struct __mutex *pmMutex;
NTSTATUS nErrCode;
MUTANT_BASIC_INFORMATION mbiMutexInfo;
/* invalid pointer or pointer to invalid object */
if(mutex == NULL || !__safeobj_validate(*mutex, __PTHREAD_MUTEX_MAGIC))
{
return (EINVAL);
}
pmMutex = (struct __mutex *)*mutex;
/* query the mutex's status */
nErrCode = NtQueryMutant
(
pmMutex->handle,
MutantBasicInformation,
&mbiMutexInfo,
sizeof(MUTANT_BASIC_INFORMATION),
NULL
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
return (__status_to_errno(nErrCode));
}
/* the thread is owned - cannot destroy it */
if(mbiMutexInfo.Count <= 0)
{
return (EBUSY);
}
/* try to close the handle */
nErrCode = NtClose(pmMutex->handle);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
return (__status_to_errno(nErrCode));
}
/* free the object, nil the pointer */
free(*mutex);
*mutex = NULL;
/* success */
return (0);
}
int pthread_mutex_lock(pthread_mutex_t *mutex)
{
struct __mutex * pmMutex;
NTSTATUS nErrCode;
/* invalid pointer or pointer to invalid object */
if(mutex == NULL || !__safeobj_validate(*mutex, __PTHREAD_MUTEX_MAGIC))
return (EINVAL);
pmMutex = (struct __mutex *)*mutex;
/* decide the behavior from the mutex type */
switch(pmMutex->type)
{
case PTHREAD_MUTEX_NORMAL:
{
/* unconditionally try to lock the mutex */
/* FIXME? should we "artificially" hang the thread if it's the mutex owner, since
NT mutexes always behave recursively? */
#if 0
if(0 /* mutex owner */ == pthread_self() */)
NtDelayExecution(FALSE, NULL);
#endif
nErrCode = NtWaitForSingleObject(pmMutex->handle, FALSE, NULL);
break;
}
case PTHREAD_MUTEX_ERRORCHECK:
{
/* prevent a thread from recursively locking the same mutex */
if(0 /* mutex owner */ == pthread_self()) /* FIXME: implement the correct logic */
return (EDEADLK);
else
nErrCode = NtWaitForSingleObject(pmMutex->handle, FALSE, NULL);
break;
}
case PTHREAD_MUTEX_RECURSIVE:
{
/* allow recursive locking */
/* ASSERT: this is the default behavior for NT */
nErrCode = NtWaitForSingleObject(pmMutex->handle, FALSE, NULL);
break;
}
default:
/* we should never reach this point */
INFO("you should never read this");
}
if(nErrCode == STATUS_ABANDONED)
{
FIXME("mutex abandoned, not sure on what to do: should we try to lock the mutex again?");
}
else if(!NT_SUCCESS(nErrCode))
{
return (__status_to_errno(nErrCode));
}
/* success */
return (0);
}
int pthread_mutex_trylock(pthread_mutex_t *mutex)
{
struct __mutex * pmMutex;
NTSTATUS nErrCode;
MUTANT_BASIC_INFORMATION mbiMutexInfo;
/* invalid pointer or pointer to invalid object */
if(mutex == NULL || !__safeobj_validate(*mutex, __PTHREAD_MUTEX_MAGIC))
return (EINVAL);
pmMutex = (struct __mutex *)*mutex;
/* query the mutex's status */
nErrCode = NtQueryMutant
(
pmMutex->handle,
MutantBasicInformation,
&mbiMutexInfo,
sizeof(MUTANT_BASIC_INFORMATION),
NULL
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
return (__status_to_errno(nErrCode));
}
/* mutex already locked */
if(mbiMutexInfo.Count <= 0)
return (EBUSY);
/* mutex not locked - mutex type attribute doesn't matter */
nErrCode = NtWaitForSingleObject(pmMutex->handle, FALSE, NULL);
if(!NT_SUCCESS(nErrCode))
{
return (__status_to_errno(nErrCode));
}
/* success */
return (0);
}
int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
struct __mutex * pmMutex;
NTSTATUS nErrCode;
/* invalid pointer or pointer to invalid object */
if(mutex == NULL || !__safeobj_validate(*mutex, __PTHREAD_MUTEX_MAGIC))
return (EINVAL);
pmMutex = (struct __mutex *)*mutex;
/* try to release the mutex */
nErrCode = NtReleaseMutant(pmMutex->handle, NULL);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
return (__status_to_errno(nErrCode));
}
/* success */
return (0);
}
/* mutex attributes routines */
int pthread_mutexattr_init(pthread_mutexattr_t *attr)
{
struct __mutexattr * pmaMutexAttrs;
/* invalid return pointer */
if(!attr)
return (EINVAL);
/* allocate internal structure for mutex attributes */
pmaMutexAttrs = (struct __mutexattr *)malloc(sizeof(struct __mutexattr));
/* failure */
if(pmaMutexAttrs == 0)
return (ENOMEM);
/* attribute defaults */
pmaMutexAttrs->pshared = PTHREAD_PROCESS_PRIVATE;
pmaMutexAttrs->type = PTHREAD_MUTEX_DEFAULT;
/* return the pointer to the attributes object */
*attr = (pthread_mutexattr_t)pmaMutexAttrs;
/* success */
return (0);
}
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
{
/* invalid pointer or pointer to invalid object */
if(attr == NULL || !__safeobj_validate(*attr, __PTHREAD_MUTEX_ATTR_MAGIC))
return (EINVAL);
/* deallocate internal structure */
free(*attr);
/* success */
return (0);
}
#define PTHREAD_MUTEXATTR_GET(PATTR,PVAR,FIELD) \
if( \
(PATTR) == NULL || \
(PVAR) == NULL || \
!__safeobj_validate(*(PATTR), __PTHREAD_MUTEX_ATTR_MAGIC) \
) \
return (EINVAL); \
else \
{ \
(*(PVAR)) = ((struct __mutexattr *)*(PATTR))->FIELD; \
return (0); \
}
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr,
int *pshared)
{
PTHREAD_MUTEXATTR_GET(attr, pshared, pshared)
}
int pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *type)
{
PTHREAD_MUTEXATTR_GET(attr, type, type)
}
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
int pshared)
{
/* invalid pointer or pointer to invalid object */
if(attr == NULL || !__safeobj_validate(*attr, __PTHREAD_MUTEX_ATTR_MAGIC))
return (EINVAL);
/* validate value */
switch(pshared)
{
case PTHREAD_PROCESS_SHARED: break;
case PTHREAD_PROCESS_PRIVATE: break;
default: return (EINVAL);
}
((struct __mutexattr *)*attr)->pshared = pshared;
return (0);
}
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
{
/* invalid pointer or pointer to invalid object */
if(attr == NULL || !__safeobj_validate(*attr, __PTHREAD_MUTEX_ATTR_MAGIC))
return (EINVAL);
/* validate value */
switch(type)
{
case PTHREAD_MUTEX_NORMAL: break;
case PTHREAD_MUTEX_ERRORCHECK: break;
case PTHREAD_MUTEX_RECURSIVE: break;
default: return (EINVAL);
}
((struct __mutexattr *)*attr)->type = type;
return (0);
}
/* STUBS */
int pthread_mutex_setprioceiling(pthread_mutex_t *mutex,
int prioceiling, int *old_ceiling)
{
TODO("realtime threads not currently implemented");
return (ENOSYS);
}
int pthread_mutex_getprioceiling(const pthread_mutex_t *mutex,
int *prioceiling)
{
TODO("realtime threads not currently implemented");
return (ENOSYS);
}
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr,
int *protocol)
{
TODO("realtime threads not currently implemented");
return (ENOSYS);
}
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr,
int protocol)
{
TODO("realtime threads not currently implemented");
return (ENOSYS);
}
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr,
int prioceiling)
{
TODO("realtime threads not currently implemented");
return (ENOSYS);
}
int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr,
int *prioceiling)
{
TODO("realtime threads not currently implemented");
return (ENOSYS);
}
/* EOF */

View file

@ -0,0 +1,23 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/pthread/self.c
* PURPOSE: get calling thread's ID
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 27/12/2001: Created
*/
#include <ddk/ntddk.h>
#include <sys/types.h>
#include <pthread.h>
pthread_t pthread_self(void)
{
return ((pthread_t)(NtCurrentTeb()->Cid).UniqueThread);
}
/* EOF */

View file

@ -0,0 +1,33 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/sched/yield.c
* PURPOSE: Yield processor
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 15/02/2002: Created
*/
#include <ddk/ntddk.h>
#include <sched.h>
#include <psx/errno.h>
int sched_yield(void)
{
NTSTATUS nErrCode;
nErrCode = NtYieldExecution();
if(!NT_SUCCESS(nErrCode))
{
errno = __status_to_errno(nErrCode);
return (-1);
}
return (0);
}
/* EOF */

View file

@ -0,0 +1,25 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/signal/raise.c
* PURPOSE: Send a signal to the executing process
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 15/02/2002: Created
*/
#include <signal.h>
#include <pthread.h>
#include <errno.h>
int raise(int sig)
{
/* returns zero if pthread_kill() returned zero, non-zero otherwise */
/* pthread_kill() returns the error number and doesn't set errno */
return (((errno = pthread_kill(pthread_self(), sig))) == 0 ? (0) : (1));
}
/* EOF */

View file

@ -0,0 +1,22 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/stdlib/abort.c
* PURPOSE: Generate an abnormal process abort
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 15/02/2002: Created
*/
#include <stdlib.h>
#include <signal.h>
void abort(void)
{
raise(SIGABRT);
}
/* EOF */

View file

@ -0,0 +1,51 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/stdlib/exit.c
* PURPOSE: Terminate a process
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 27/12/2001: Created
*/
#include <ddk/ntddk.h>
#include <stdlib.h>
#include <psx/debug.h>
void exit(int status)
{
TODO("call all functions registered with atexit()");
TODO("flush all output streams, close all open streams");
TODO("remove all files created by tmpfile()");
TODO("close all of the file descriptors, directory streams, conversion \
descriptors and message catalogue descriptors");
TODO("send SIGCHILD to the parent process");
TODO("set parent pid of children to pid of psxss");
TODO("detach each attached shared-memory segment");
TODO("for each semaphore for which the calling process has set a semadj \
value(), add the value to the semval of the semaphore.");
TODO("if the process is a controlling process, send SIGHUP to each process \
in the foreground process group...");
TODO("... and disassociate the terminal from the session");
TODO("if the exit causes a process group to become orphaned, and if any \
member of the newly-orphaned process group is stopped, send SIGHUP and \
SIGCONT to each process in the newly-orphaned process group");
TODO("all open named semaphores in the calling process are closed");
TODO("remove any memory locks");
TODO("destroy memory mappings");
TODO("close all open message queue descriptors");
#if 0
ExitProcess(status);
#endif
NtTerminateProcess(NtCurrentProcess(), status);
}
/* EOF */

View file

@ -0,0 +1,55 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/stdlib/malloc.c
* PURPOSE: Memory allocator
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 27/12/2001: Created
*/
#include <errno.h>
#include <psx/stdlib.h>
void * malloc(size_t size)
{
void * pTemp = __malloc(size);
if(!pTemp)
errno = ENOMEM;
return (pTemp);
}
void free(void * ptr)
{
__free(ptr);
}
void * calloc(size_t nelem, size_t elsize)
{
return (__malloc(nelem * elsize));
}
void * realloc(void * ptr, size_t size)
{
void * pTemp;
if(size == 0)
__free(ptr);
if(ptr == 0)
return __malloc(size);
pTemp = __realloc(ptr, size);
if(pTemp == 0)
errno = ENOMEM;
return (pTemp);
}
/* EOF */

View file

@ -0,0 +1,23 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/string/strcoll.c
* PURPOSE: string comparison using collating information
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 20/01/2002: Created
*/
#include <string.h>
#include <psx/debug.h>
int strcoll(const char *s1, const char *s2)
{
TODO("locale semantics currently unimplemented");
return (strcmp(s1, s2));
}
/* EOF */

View file

@ -0,0 +1,44 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/string/strdup.c
* PURPOSE: duplicate a string
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 21/01/2002: Created
*/
#include <string.h>
#include <stdlib.h>
#include <psx/debug.h>
char *strdup(const char *s1)
{
char *pchRetBuf;
int nStrLen;
HINT("strdup() is inefficient - consider dropping zero-terminated strings");
if (s1 == 0)
return 0;
nStrLen = strlen(s1);
/* allocate enough buffer space for s1 and the null terminator */
pchRetBuf = (char *) malloc(nStrLen + 1);
if (pchRetBuf == 0)
/* memory allocation failed */
return 0;
/* copy the string */
strcpy(pchRetBuf, s1);
return pchRetBuf;
}
/* EOF */

View file

@ -0,0 +1,27 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/string/strerror.c
* PURPOSE: Get error message string
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 20/01/2002: Created
*/
#include <errno.h>
#include <string.h>
#include <psx/debug.h>
static char *__errstr = "<strerror() unsupported>";
char *strerror(int errnum)
{
INFO("errnum %#x", errnum);
TODO("getting error string not currently implemented");
errno = EINVAL;
return (__errstr);
}
/* EOF */

View file

@ -0,0 +1,178 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: lib/psxdll/sys/utsname/uname.c
* PURPOSE: Get name of current system
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 19/12/2001: Created
*/
#include <ddk/ntddk.h>
#include <ntdll/rtl.h>
#include <string.h>
#include <sys/utsname.h>
#include <psx/stdlib.h>
#include <psx/debug.h>
#include <psx/errno.h>
int uname(struct utsname *name)
{
NTSTATUS nErrCode;
OBJECT_ATTRIBUTES oaKeyAttribs;
UNICODE_STRING wstrKeyPath;
UNICODE_STRING wstrValueName;
UNICODE_STRING wstrValueData;
ANSI_STRING strValueData;
PKEY_VALUE_PARTIAL_INFORMATION pkvpiKeyValue;
ULONG nKeyValueSize;
HANDLE hKey;
/* system name and version info are fixed strings, at the moment */ /* FIXME? */
strncpy(name->sysname, "ReactOS" , 255);
strncpy(name->release, "0.0" , 255);
strncpy(name->version, "pre-alpha", 255);
/* hardware identifier */
/* FIXME: this should definitely be determined programmatically */
strncpy(name->machine, "i386" , 255);
/* we use the active computer's name as the node name */
/* TODO: POSIX-style registry functions */
/* initialize the registry key path */
RtlInitUnicodeString(
&wstrKeyPath,
L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ActiveComputerName"
);
/* initialize object attributes */
oaKeyAttribs.Length = sizeof(OBJECT_ATTRIBUTES);
oaKeyAttribs.RootDirectory = NULL;
oaKeyAttribs.ObjectName = &wstrKeyPath;
oaKeyAttribs.Attributes = OBJ_CASE_INSENSITIVE /* | OBJ_OPENLINK | OBJ_OPENIF */ /* FIXME? */;
oaKeyAttribs.SecurityDescriptor = NULL;
oaKeyAttribs.SecurityQualityOfService = NULL;
/* open the key object */
nErrCode = NtOpenKey
(
&hKey,
KEY_QUERY_VALUE,
&oaKeyAttribs
);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
ERR("NtOpenKey() failed with status 0x%08X", nErrCode);
errno = __status_to_errno(nErrCode);
return (-1);
}
/* initialize the registry value name */
RtlInitUnicodeString(&wstrValueName, L"ComputerName");
/* fake query - null buffer and zero length to pre-fetch the appropriate buffer size */
nErrCode = NtQueryValueKey
(
hKey,
&wstrValueName,
KeyValuePartialInformation,
NULL,
0,
&nKeyValueSize
);
/* success */
if(nErrCode == (NTSTATUS)STATUS_BUFFER_TOO_SMALL)
{
/* allocate the appropriate buffer size */
if(nKeyValueSize < sizeof(KEY_VALUE_PARTIAL_INFORMATION)) /* just to be sure */
nKeyValueSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION);
pkvpiKeyValue = __malloc(nKeyValueSize);
}
/* failure */
else
{
ERR("NtQueryValueKey() failed with status 0x%08X", nErrCode);
NtClose(hKey);
errno = __status_to_errno(nErrCode);
return (-1);
}
/* query the value */
nErrCode = NtQueryValueKey
(
hKey,
&wstrValueName,
KeyValuePartialInformation,
pkvpiKeyValue,
nKeyValueSize,
&nKeyValueSize
);
/* close the key handle (not needed anymore) */
NtClose(hKey);
/* failure */
if(!NT_SUCCESS(nErrCode))
{
ERR("NtQueryValueKey() failed with status 0x%08X", nErrCode);
__free(pkvpiKeyValue);
errno = __status_to_errno(nErrCode);
return (-1);
}
/* make wstrValueData refer to the Data field of the key value information */
wstrValueData.Length = pkvpiKeyValue->DataLength;
wstrValueData.MaximumLength = wstrValueData.Length;
wstrValueData.Buffer = (PWCHAR)&(pkvpiKeyValue->Data[0]);
/* make strValueData refer to the nodename buffer */
strValueData.Length = 0;
strValueData.MaximumLength = 254;
strValueData.Buffer = name->nodename;
RtlUnicodeStringToAnsiString
(
&strValueData,
&wstrValueData,
FALSE
);
/* free the key value buffer */
__free(pkvpiKeyValue);
/* null-terminate the returned string */
name->nodename[strValueData.Length] = '0';
INFO
(
" \
name->sysname = \"%s\"\n\
tname->nodename = \"%s\"\n\
tname->release = \"%s\"\n\
tname->version = \"%s\"\n\
tname->machine = \"%s\"",
name->sysname,
name->nodename,
name->release,
name->version,
name->machine
);
/* success */
return (0);
}
/* EOF */

View file

@ -0,0 +1,42 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/unistd/close.c
* PURPOSE: Close a file descriptor
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 13/02/2002: Created
*/
#include <ddk/ntddk.h>
#include <unistd.h>
#include <fcntl.h>
#include <psx/errno.h>
#include <psx/stdlib.h>
#include <psx/fdtable.h>
int close(int fildes)
{
__fildes_t fdDescriptor;
NTSTATUS nErrCode;
if(fcntl(fildes, F_DELFD, &fdDescriptor) == -1)
return (-1);
__free(fdDescriptor.ExtraData);
nErrCode = NtClose(fdDescriptor.FileHandle);
if(!NT_SUCCESS(nErrCode))
{
errno = __status_to_errno(nErrCode);
return (-1);
}
return (0);
}
/* EOF */

View file

@ -0,0 +1,41 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/unistd/dup.c
* PURPOSE: Duplicate an open file descriptor
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 13/02/2002: Created
*/
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <fcntl.h>
int dup(int fildes)
{
return (fcntl(fildes, F_DUPFD, 0));
}
int dup2(int fildes, int fildes2)
{
if(fildes < 0 || fildes >= OPEN_MAX)
{
errno = EBADF;
return (-1);
}
/* TODO: check if fildes is valid */
if(fildes == fildes2)
return fildes2;
close(fildes2);
return (fcntl(fildes, F_DUPFD, fildes2));
}
/* EOF */

View file

@ -0,0 +1,89 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/unistd/getcwd.c
* PURPOSE: Get the pathname of the current working directory
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 01/02/2002: Created
*/
#include <ddk/ntddk.h>
#include <ntdll/rtl.h>
#include <unistd.h>
#include <stddef.h>
#include <wchar.h>
#include <psx/errno.h>
#include <psx/stdlib.h>
#include <psx/pdata.h>
wchar_t *_Wgetcwd(wchar_t *buf, size_t size)
{
PUNICODE_STRING pwstrCurDir;
__PdxAcquirePdataLock();
pwstrCurDir = __PdxGetCurDir();
if(size < (pwstrCurDir->Length / sizeof(WCHAR)))
{
__PdxReleasePdataLock();
errno = ERANGE;
return (0);
}
else
{
wcsncpy(buf, pwstrCurDir->Buffer, pwstrCurDir->Length);
__PdxReleasePdataLock();
return (buf);
}
}
char *getcwd(char *buf, size_t size)
{
PUNICODE_STRING pwstrCurDir;
__PdxAcquirePdataLock();
pwstrCurDir = __PdxGetCurDir();
if(size < (pwstrCurDir->Length / sizeof(WCHAR)))
{
__PdxReleasePdataLock();
errno = ERANGE;
return (0);
}
else
{
ANSI_STRING strBuffer;
NTSTATUS nErrCode;
strBuffer.Length = 0;
strBuffer.MaximumLength = size;
strBuffer.Buffer = buf;
nErrCode = RtlUnicodeStringToAnsiString
(
&strBuffer,
pwstrCurDir,
FALSE
);
__PdxReleasePdataLock();
if(!NT_SUCCESS(nErrCode))
{
errno = __status_to_errno(nErrCode);
return (0);
}
return (buf);
}
__PdxReleasePdataLock();
}
/* EOF */

View file

@ -0,0 +1,23 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/unistd/getpid.c
* PURPOSE: Get the process ID
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 15/02/2002: Created
*/
#include <ddk/ntddk.h>
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void)
{
return ((pid_t)NtCurrentTeb()->Cid.UniqueThread);
}
/* EOF */

View file

@ -0,0 +1,42 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: subsys/psx/lib/psxdll/unistd/getppid.c
* PURPOSE: Get the parent process ID
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 15/02/2002: Created
*/
#include <ddk/ntddk.h>
#include <sys/types.h>
#include <unistd.h>
#include <psx/errno.h>
pid_t getppid(void)
{
PROCESS_BASIC_INFORMATION pbiInfo;
NTSTATUS nErrCode;
nErrCode = NtQueryInformationProcess
(
NtCurrentProcess(),
ProcessBasicInformation,
&pbiInfo,
sizeof(pbiInfo),
NULL
);
if(!NT_SUCCESS(nErrCode))
{
errno = __status_to_errno(nErrCode);
return (0);
}
return (pbiInfo.InheritedFromUniqueProcessId);
}
/* EOF */

View file

@ -0,0 +1,49 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS POSIX+ Subsystem
* FILE: subsys/psx/lib/psxdll/unistd/read.c
* PURPOSE: Read from a file
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 15/02/2002: Created
*/
#include <ddk/ntddk.h>
#include <unistd.h>
#include <sys/types.h>
ssize_t read(int fildes, void *buf, size_t nbyte)
{
}
ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset)
{
HANDLE hFile;
NTSTATUS nErrCode;
IO_STATUS_BLOCK isbStatus;
/* get the file handle for the specified file descriptor */
if(fcntl(fildes, F_GETFH, &hFile) == -1)
return (-1);
/* read data from file */
nErrCode = NtReadFile
(
hFile,
NULL,
NULL,
NULL,
&isbStatus,
buf,
nbyte,
(PLARGE_INTEGER)&off_t,
NULL
);
return ((ssize_t)isbStatus.Information);
}
/* EOF */

View file

@ -0,0 +1,15 @@
/* $Id:
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS POSIX+ Subsystem
* FILE: subsys/psx/lib/psxdll/unistd/write.c
* PURPOSE: Write on a file
* PROGRAMMER: KJK::Hyperion <noog@libero.it>
* UPDATE HISTORY:
* 15/02/2002: Created
*/
/* EOF */