/*++ 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;iHandleTable[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;iParentHandleTable, FileSystemParameters->ParentTableLength, ParentProcessHandle, ChildProcessHandle, ChildProcess, pExecPgmMsg ); if (RetCode == NO_ERROR) { for (i=0;iu.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; }