mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
638 lines
17 KiB
638 lines
17 KiB
/*++
|
|
|
|
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;
|
|
}
|