diff options
Diffstat (limited to 'private/os2/server/srvfile.c')
-rw-r--r-- | private/os2/server/srvfile.c | 638 |
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; +} |