summaryrefslogtreecommitdiffstats
path: root/private/os2/server/srvfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/os2/server/srvfile.c')
-rw-r--r--private/os2/server/srvfile.c638
1 files changed, 638 insertions, 0 deletions
diff --git a/private/os2/server/srvfile.c b/private/os2/server/srvfile.c
new file mode 100644
index 000000000..c37e53b76
--- /dev/null
+++ b/private/os2/server/srvfile.c
@@ -0,0 +1,638 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ srvfile.c
+
+Abstract:
+
+ Support for copying file system variables during exec
+
+Author:
+
+ Therese Stowell (thereses) 6-Nov-1989
+
+Revision History:
+
+--*/
+
+#define INCL_OS2V20_FILESYS
+#define INCL_OS2V20_ERRORS
+#include "os2srv.h"
+
+NTSTATUS
+DeviceAddShare(
+ IN ULONG DesiredAccess,
+ IN ULONG DesiredShareAccess,
+ IN OUT PSHARE_ACCESS ShareAccess
+ );
+
+NTSTATUS
+DeviceDupShare(
+ IN ULONG DesiredAccess,
+ IN ULONG DesiredShareAccess,
+ IN OUT PSHARE_ACCESS ShareAccess
+ );
+
+NTSTATUS
+DeviceRemoveShare(
+ IN ULONG DesiredAccess,
+ IN ULONG DesiredShareAccess,
+ IN OUT PSHARE_ACCESS ShareAccess
+ );
+
+SHARE_ACCESS DeviceSharer[NUMBER_OF_DEVICES];
+
+
+APIRET
+DupHandleTable(
+ IN PFILE_HANDLE ParentHandleTable,
+ IN ULONG ParentTableLength,
+ IN HANDLE ParentProcess, // NT process handle
+ IN HANDLE ChildProcess, // NT process handle
+ POS2_PROCESS Process, // OS/2 child process
+ IN POS2_DOSEXECPGM_MSG pExecPgmMsg
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called during an exec. It reads the handle table of
+ the parent and then creates the handle table for the child by duping
+ any inheritable handles and clearing some flags (as OS/2 does). The
+ resulting table will be read by the child process.
+
+Arguments:
+
+ ParentHandleTable - pointer to parent handle table
+
+ ParentTableLength - length of parent handle table
+
+ ParentProcess - NT process handle of parent
+
+ ChildProcess - NT process handle of child
+
+ Process - OS/2 child process
+
+ pExecPgmMsg - DosExecPgm message:
+
+ CmdLineFlag - flag to process the file handle
+
+ 1 - change StdOut to NULL
+ 2 - change StdOut to RedirectedFileName
+
+ RedirectedFileName - file name for STD_OUT (1)
+
+Return Value:
+
+ ??
+
+--*/
+
+{
+ NTSTATUS Status;
+ ULONG i, CmdLineFlag = pExecPgmMsg->CmdLineFlag;
+ ULONG BytesRead;
+
+ Process->HandleTableLength = ParentTableLength;
+ Process->HandleTable = (PFILE_HANDLE)RtlAllocateHeap( Os2Heap, 0,
+ ParentTableLength * sizeof(FILE_HANDLE)
+ );
+ if (Process->HandleTable == NULL) {
+#if DBG
+ KdPrint(( "Os2DupHandleTable, no memory in Os2Heap\n" ));
+#endif
+ return(ERROR_NOT_ENOUGH_MEMORY);
+ }
+
+ Status = NtReadVirtualMemory( ParentProcess,
+ ParentHandleTable,
+ Process->HandleTable,
+ ParentTableLength * sizeof(FILE_HANDLE),
+ &BytesRead
+ );
+ if ((!NT_SUCCESS(Status)) || (BytesRead != ParentTableLength * sizeof(FILE_HANDLE))) {
+ RtlFreeHeap(Os2Heap,0,Process->HandleTable);
+ return ERROR_INVALID_HANDLE;
+ }
+
+ for (i=0;i<ParentTableLength;i++)
+ {
+ if ((i == 1) && CmdLineFlag )
+ {
+ if (CmdLineFlag & REDIR_NUL)
+ {
+ Process->HandleTable[1].IoVectorType = NulVectorType;
+ Process->HandleTable[1].FileType = FILE_TYPE_DEV;
+ Process->HandleTable[1].DeviceAttribute = DEVICE_ATTRIBUTE_NUL | DEVICE_ATTRIBUTE_CHAR | 0x80;
+ /* 0x80 stands for LEVEL 1 which makes it OS/2 1.x compatible */
+ //Process->HandleTable[1].NtHandle =
+ Process->HandleTable[1].Flags = FILE_HANDLE_ALLOCATED | FILE_HANDLE_VALID |
+ OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE;
+ } else if (CmdLineFlag & REDIR_FILE)
+ {
+
+ Process->HandleTable[1].IoVectorType = FileVectorType;
+ Process->HandleTable[1].FileType = pExecPgmMsg->RedirectedFileType;
+ Process->HandleTable[1].DeviceAttribute = 0;
+ Process->HandleTable[1].NtHandle = pExecPgmMsg->hRedirectedFile;
+ Process->HandleTable[1].Flags = FILE_HANDLE_ALLOCATED | FILE_HANDLE_VALID |
+ OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYNONE;
+ }
+ } else
+
+ if ((Process->HandleTable[i].Flags & FILE_HANDLE_ALLOCATED) &&
+ (!(Process->HandleTable[i].Flags & OPEN_FLAGS_NOINHERIT))) {
+ //
+ // all NT handles are non-inherited. to inherit OS/2 handles, dup handles to
+ // child.
+ //
+ if (Process->HandleTable[i].IoVectorType == MonitorVectorType)
+ {
+ continue;
+ }
+
+ // For VIO-devices, NtHandle field holds an OS2.EXE handle.
+ // Od2InitializeFileSystemForExec(fileinit.c) will handle it.
+
+ if ((Process->HandleTable[i].IoVectorType != ConVectorType) &&
+ (Process->HandleTable[i].IoVectorType != KbdVectorType) &&
+ (Process->HandleTable[i].IoVectorType != MouseVectorType) &&
+ (Process->HandleTable[i].IoVectorType != ScreenVectorType) &&
+ (Process->HandleTable[i].IoVectorType != RemoteVectorType))
+ {
+
+ Status = NtDuplicateObject(ParentProcess,
+ Process->HandleTable[i].NtHandle,
+ ChildProcess,
+ &(Process->HandleTable[i].NtHandle),
+ (ACCESS_MASK) NULL,
+ OBJ_CASE_INSENSITIVE,
+ DUPLICATE_SAME_ACCESS
+ );
+ // if dup fails, the child process will die and the system will release all
+ // the already-duped handles.
+
+// if (!NT_SUCCESS(Status)) {
+// RtlFreeHeap(Os2Heap,0,Process->HandleTable);
+// return ERROR_INVALID_HANDLE; // BUGBUG bogus error value
+// }
+
+ }
+ // os2 clears the write-through flag when duping the handle table
+
+ Process->HandleTable[i].Flags &= ~(OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_NO_CACHE);
+ }
+ else {
+ Process->HandleTable[i].Flags = FILE_HANDLE_FREE;
+ }
+ }
+ return( NO_ERROR );
+}
+
+
+APIRET
+InitializeFileSystemForExec(
+ IN POS2_FILE_SYSTEM_PARAMETERS FileSystemParameters,
+ IN HANDLE ParentProcessHandle, // NT process handle
+ IN HANDLE ChildProcessHandle, // NT process handle
+ POS2_PROCESS ParentProcess, // OS/2 parent process
+ POS2_PROCESS ChildProcess, // OS/2 child process
+ IN POS2_DOSEXECPGM_MSG pExecPgmMsg
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called during an exec. It calls the routines to
+ initialize various components of the filesystem.
+
+Arguments:
+
+ FileSystemParameters - values needed to initialize the file system
+
+ ParentProcessHandle - NT process handle to parent process
+
+ ChildProcessHandle - NT process handle to child process
+
+ ParentProcess - OS/2 parent process
+
+ ChildProcess - OS/2 child process
+
+ pExecPgmMsg - the message passed from the client
+
+Return Value:
+
+ ??
+
+--*/
+
+{
+ APIRET RetCode;
+
+ RetCode = DupHandleTable(FileSystemParameters->ParentHandleTable,
+ FileSystemParameters->ParentTableLength,
+ ParentProcessHandle,
+ ChildProcessHandle,
+ ChildProcess,
+ pExecPgmMsg
+ );
+ return RetCode;
+}
+
+
+BOOLEAN
+Os2InternalCopyHandleTable(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called during an exec by the child process. It copies
+ the handle table into the child's context.
+
+Arguments:
+
+ t - calling thread
+
+ m - message
+
+Return Value:
+
+ TRUE - create a return message
+
+--*/
+
+{
+ POS2_COPYHANDLETABLE_MSG a = &m->u.CopyHandleTable;
+ NTSTATUS Status;
+ ULONG BytesWritten;
+
+// DbgBreakPoint();
+ Status = NtWriteVirtualMemory( t->Process->ProcessHandle,
+ a->ChildHandleTable,
+ t->Process->HandleTable,
+ a->ChildTableLength * sizeof(FILE_HANDLE),
+ &BytesWritten
+ );
+
+ RtlFreeHeap(Os2Heap,0,t->Process->HandleTable);
+ if ((!NT_SUCCESS(Status)) || (BytesWritten != a->ChildTableLength * sizeof(FILE_HANDLE))) {
+ m->ReturnedErrorValue = ERROR_INVALID_HANDLE; // BUGBUG bogus error value
+ return( TRUE );
+ }
+ m->ReturnedErrorValue = NO_ERROR;
+ return( TRUE );
+}
+
+
+VOID
+InitializeFileSystemForSesMgr(
+ IN POS2_PROCESS Process
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called during an create session. It allocates space
+ for the current directory table and initializes each entry to the
+ root directory.
+
+Arguments:
+
+ Process - process being created
+
+Return Value:
+
+ none.
+
+--*/
+
+{
+ int i;
+
+ for (i=0;i<NUMBER_OF_DEVICES;i++) {
+ DeviceSharer[i].OpenCount = 0;
+ DeviceSharer[i].Readers = 0;
+ DeviceSharer[i].Writers = 0;
+ DeviceSharer[i].Deleters = 0;
+ DeviceSharer[i].SharedRead = 0;
+ DeviceSharer[i].SharedWrite = 0;
+ DeviceSharer[i].SharedDelete = 0;
+ }
+}
+
+
+APIRET
+InitializeFileSystemForChildSesMgr(
+ IN POS2_FILE_SYSTEM_PARAMETERS FileSystemParameters,
+ IN HANDLE ParentProcessHandle, // NT process handle
+ IN HANDLE ChildProcessHandle, // NT process handle
+ POS2_PROCESS ParentProcess, // OS/2 parent process
+ POS2_PROCESS ChildProcess, // OS/2 child process
+ IN POS2_DOSEXECPGM_MSG pExecPgmMsg
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called during an create session of a child session.
+ It calls the routines to initialize various components of the filesystem.
+
+Arguments:
+
+ FileSystemParameters - values needed to initialize the file system
+
+ ParentProcessHandle - NT process handle to parent process
+
+ ChildProcessHandle - NT process handle to child process
+
+ ParentProcess - OS/2 parent process
+
+ ChildProcess - OS/2 child process
+
+ pExecPgmMsg - the message passed from the client
+
+Return Value:
+
+ ??
+
+--*/
+
+{
+ APIRET RetCode;
+ int i;
+
+ RetCode = DupHandleTable(FileSystemParameters->ParentHandleTable,
+ FileSystemParameters->ParentTableLength,
+ ParentProcessHandle,
+ ChildProcessHandle,
+ ChildProcess,
+ pExecPgmMsg
+ );
+
+ if (RetCode == NO_ERROR) {
+
+ for (i=0;i<NUMBER_OF_DEVICES;i++) {
+ DeviceSharer[i].OpenCount = 0;
+ DeviceSharer[i].Readers = 0;
+ DeviceSharer[i].Writers = 0;
+ DeviceSharer[i].Deleters = 0;
+ DeviceSharer[i].SharedRead = 0;
+ DeviceSharer[i].SharedWrite = 0;
+ DeviceSharer[i].SharedDelete = 0;
+ }
+ }
+ return RetCode;
+}
+
+
+BOOLEAN
+Os2InternalDeviceShare(
+ IN POS2_THREAD t,
+ IN POS2_API_MSG m
+ )
+
+/*++
+
+Routine Description:
+
+ This routine is called to add, dup, or remove the sharing of a particular
+ device.
+
+Arguments:
+
+ t - calling thread
+
+ m - message
+
+Return Value:
+
+ TRUE - create a return message
+
+--*/
+
+{
+ POS2_SHARE_MSG a = &m->u.DeviceShare;
+ PSHARE_ACCESS ShareRecord;
+
+ UNREFERENCED_PARAMETER(t);
+ if (a->VectorType > MAXIMUM_DEVICE_VECTOR_TYPE) {
+ ASSERT (FALSE);
+ m->ReturnedErrorValue = (ULONG)STATUS_INVALID_PARAMETER;
+ return TRUE;
+ }
+ ShareRecord = &DeviceSharer[a->VectorType];
+
+ switch (a->Operation) {
+ case AddShare:
+ m->ReturnedErrorValue = DeviceAddShare(a->DesiredAccess,
+ a->ShareAccess,
+ ShareRecord
+ );
+ break;
+ case DupShare:
+ m->ReturnedErrorValue = DeviceDupShare(a->DesiredAccess,
+ a->ShareAccess,
+ ShareRecord
+ );
+ break;
+ case RemoveShare:
+ m->ReturnedErrorValue = DeviceRemoveShare(a->DesiredAccess,
+ a->ShareAccess,
+ ShareRecord
+ );
+ break;
+ default:
+ ASSERT (FALSE);
+ m->ReturnedErrorValue = (ULONG)STATUS_INVALID_PARAMETER;
+ break;
+ }
+ return TRUE;
+}
+
+NTSTATUS
+DeviceAddShare(
+ IN ULONG DesiredAccess,
+ IN ULONG DesiredShareAccess,
+ IN OUT PSHARE_ACCESS ShareAccess
+ )
+
+{
+ ULONG Ocount;
+ ULONG ReadAccess;
+ ULONG WriteAccess;
+ ULONG DeleteAccess;
+ ULONG SharedRead;
+ ULONG SharedWrite;
+ ULONG SharedDelete;
+
+ //
+ // Set the access type in the file object for the current accessor.
+ // Note that reading and writing attributes are not included in the
+ // access check.
+ //
+
+ ReadAccess = (DesiredAccess & (READ_CONTROL | FILE_EXECUTE
+ | FILE_READ_DATA | FILE_READ_EA)) != 0;
+ WriteAccess = (DesiredAccess & (WRITE_DAC | WRITE_OWNER
+ | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA)) != 0;
+ DeleteAccess = (DesiredAccess & DELETE) != 0;
+
+ SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
+ SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
+ SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
+
+ //
+ // Now check to see whether or not the desired accesses are compatible
+ // with the way that the file is currently open.
+ //
+
+ Ocount = ShareAccess->OpenCount;
+
+ if ( (ReadAccess && (ShareAccess->SharedRead < Ocount))
+ ||
+ (WriteAccess && (ShareAccess->SharedWrite < Ocount))
+ ||
+ (DeleteAccess && (ShareAccess->SharedDelete < Ocount))
+ ||
+ ((ShareAccess->Readers != 0) && !SharedRead)
+ ||
+ ((ShareAccess->Writers != 0) && !SharedWrite)
+ ||
+ ((ShareAccess->Deleters != 0) && !SharedDelete)
+ ) {
+
+ //
+ // The check failed. Simply return to the caller indicating that the
+ // current open cannot access the file.
+ //
+
+ return STATUS_SHARING_VIOLATION;
+
+ } else {
+
+ //
+ // The check was successful. Update the counter information in the
+ // shared access structure for this open request if the caller
+ // specified that it should be updated.
+ //
+
+ ShareAccess->OpenCount++;
+
+ ShareAccess->Readers += ReadAccess;
+ ShareAccess->Writers += WriteAccess;
+ ShareAccess->Deleters += DeleteAccess;
+
+ ShareAccess->SharedRead += SharedRead;
+ ShareAccess->SharedWrite += SharedWrite;
+ ShareAccess->SharedDelete += SharedDelete;
+
+ return STATUS_SUCCESS;
+ }
+}
+
+NTSTATUS
+DeviceDupShare(
+ IN ULONG DesiredAccess,
+ IN ULONG DesiredShareAccess,
+ IN OUT PSHARE_ACCESS ShareAccess
+ )
+
+{
+ ULONG ReadAccess;
+ ULONG WriteAccess;
+ ULONG DeleteAccess;
+ ULONG SharedRead;
+ ULONG SharedWrite;
+ ULONG SharedDelete;
+
+ //
+ // Set the access type in the file object for the current accessor.
+ // Note that reading and writing attributes are not included in the
+ // access check.
+ //
+
+ ReadAccess = (DesiredAccess & (READ_CONTROL | FILE_EXECUTE
+ | FILE_READ_DATA | FILE_READ_EA)) != 0;
+ WriteAccess = (DesiredAccess & (WRITE_DAC | WRITE_OWNER
+ | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA)) != 0;
+ DeleteAccess = (DesiredAccess & DELETE) != 0;
+
+ SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
+ SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
+ SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
+
+#if DBG
+ if (ShareAccess->OpenCount == 0)
+ ASSERT (FALSE);
+#endif
+ ShareAccess->OpenCount++;
+
+ ShareAccess->Readers += ReadAccess;
+ ShareAccess->Writers += WriteAccess;
+ ShareAccess->Deleters += DeleteAccess;
+
+ ShareAccess->SharedRead += SharedRead;
+ ShareAccess->SharedWrite += SharedWrite;
+ ShareAccess->SharedDelete += SharedDelete;
+
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+DeviceRemoveShare(
+ IN ULONG DesiredAccess,
+ IN ULONG DesiredShareAccess,
+ IN OUT PSHARE_ACCESS ShareAccess
+ )
+
+{
+ ULONG ReadAccess;
+ ULONG WriteAccess;
+ ULONG DeleteAccess;
+ ULONG SharedRead;
+ ULONG SharedWrite;
+ ULONG SharedDelete;
+
+ //
+ // Set the access type in the file object for the current accessor.
+ // Note that reading and writing attributes are not included in the
+ // access check.
+ //
+
+ ReadAccess = (DesiredAccess & (READ_CONTROL | FILE_EXECUTE
+ | FILE_READ_DATA | FILE_READ_EA)) != 0;
+ WriteAccess = (DesiredAccess & (WRITE_DAC | WRITE_OWNER
+ | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA)) != 0;
+ DeleteAccess = (DesiredAccess & DELETE) != 0;
+
+ SharedRead = (DesiredShareAccess & FILE_SHARE_READ) != 0;
+ SharedWrite = (DesiredShareAccess & FILE_SHARE_WRITE) != 0;
+ SharedDelete = (DesiredShareAccess & FILE_SHARE_DELETE) != 0;
+
+//#if DBG
+// if (ShareAccess->OpenCount == 0)
+// ASSERT (FALSE);
+//#endif
+ ShareAccess->OpenCount--;
+
+ ShareAccess->Readers -= ReadAccess;
+ ShareAccess->Writers -= WriteAccess;
+ ShareAccess->Deleters -= DeleteAccess;
+
+ ShareAccess->SharedRead -= SharedRead;
+ ShareAccess->SharedWrite -= SharedWrite;
+ ShareAccess->SharedDelete -= SharedDelete;
+
+ return STATUS_SUCCESS;
+}