--- /dev/null
+# $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
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
\ No newline at end of file
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $Id:
+ */
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS POSIX+ Subsystem
+ * FILE:
+ * PURPOSE:
+ * PROGRAMMER:
+ * UPDATE HISTORY:
+ * : Created
+ */
+
+
+/* EOF */
+
--- /dev/null
+; $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
--- /dev/null
+; $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
--- /dev/null
+/* $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
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+
--- /dev/null
+/* $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 */
+