|
|
/*++
Copyright (c) 1993/4 Microsoft Corporation
Module Name:
Locks.c
Abstract:
This module implements the routines for the NetWare 16 bit support to perform the synchonization api's
Author:
Colin Watson [ColinW] 07-Dec-1993
Revision History:
--*/
#include "Procs.h"
UCHAR LockMode = 0;
BOOLEAN Tickle[MC];
NTSTATUS Sem( UCHAR Function, UCHAR Connection );
VOID Locks( USHORT Command ) /*++
Routine Description:
Implements all the locking operations
Arguments:
Command - supplies Applications AX.
Return Value:
Return status.
--*/ { UCHAR Function = Command & 0x00ff; USHORT Operation = Command & 0xff00; CONN_INDEX Connection; NTSTATUS status = STATUS_SUCCESS; PUCHAR Request; ULONG RequestLength; WORD Timeout;
if ( Operation != 0xCF00) {
//
// Connection does not need to be initialised for CF00 because
// we have to loop through all connections. Its harmful because
// a CF00 is created during ProcessExit(). If we call selectconnection
// and there is no server available this will make process exit
// really slow.
//
Connection = SelectConnectionInCWD(); if (Connection == 0xff) { setAL(0xff); return; }
if ( ServerHandles[Connection] == NULL ) {
status = OpenConnection( Connection );
if (!NT_SUCCESS(status)) { setAL((UCHAR)RtlNtStatusToDosError(status)); return; } } }
switch ( Operation ) {
case 0xBC00: // Log physical record
status = NwlibMakeNcp( GET_NT_HANDLE(), NWR_ANY_HANDLE_NCP(0x1A), 17, // RequestSize
0, // ResponseSize
"b_wwwww", Function, 6, // Leave space for NetWare handle
getCX(),getDX(), getSI(),getDI(), getBP()); break;
case 0xBD00: // Physical Unlock
status = NwlibMakeNcp( GET_NT_HANDLE(), NWR_ANY_HANDLE_NCP(0x1C), 15, // RequestSize
0, // ResponseSize
"b_wwww", Function, 6, // Leave space for NetWare handle
getCX(),getDX(), getSI(),getDI());
break;
case 0xBE00: // Clear physical record
status = NwlibMakeNcp( GET_NT_HANDLE(), NWR_ANY_HANDLE_NCP(0x1E), 15, // RequestSize
0, // ResponseSize
"b_wwww", Function, 6, // Leave space for NetWare handle
getCX(),getDX(), getSI(),getDI());
break;
case 0xC200: // Physical Lock set
status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x1B), 3, // RequestSize
0, // ResponseSize
"bw", Function, getBP()); break;
case 0xC300: // Release Physical Record Set
status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x1D), 0, // RequestSize
0, // ResponseSize
""); break;
case 0xC400: // Clear Physical Record Set
status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x1F), // Clear Physical Record Set
0, // RequestSize
0, // ResponseSize
""); break;
case 0xC500: // All Semaphore operations
status = Sem(Function, Connection); break;
case 0xC600: // Set/Get Lock mode
if (Function != 2) { LockMode = Function; }
setAL(LockMode); return; // avoid setting AL to status at the end of this routine
break;
case 0xCB00: // Lock File Set
if (LockMode == 0) { if (getDL()) { Timeout = 0xffff; } else { Timeout = 0; } } else { Timeout = getBP(); }
for (Connection = 0; Connection < MC; Connection++) { if (Tickle[Connection]) { status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x04), 2, // RequestSize
0, // ResponseSize
"w", Timeout); if (!NT_SUCCESS(status)) { break; } } } break;
case 0xCD00: // Release File Set
case 0xCF00: // Clear File Set
for (Connection = 0; Connection < MC; Connection++) { if (Tickle[Connection]) { status = NwlibMakeNcp( ServerHandles[Connection], (Operation == 0xCD00) ? NWR_ANY_F2_NCP(0x06): NWR_ANY_F2_NCP(0x08), 0, // RequestSize
0, // ResponseSize
""); if (!NT_SUCCESS(status)) { break; }
if (Operation == 0xCF00) { Tickle[Connection] = FALSE; } } }
break;
case 0xD000: // Log Logical Record
Request = GetVDMPointer ( (ULONG)((getDS() << 16)|getDX()), sizeof(UCHAR), IS_PROTECT_MODE());
RequestLength = Request[0] + 1;
Request = GetVDMPointer ( (ULONG)((getDS() << 16)|getDX()), RequestLength, IS_PROTECT_MODE());
status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x09), RequestLength + 5, // RequestSize
0, // ResponseSize
"bwbr", (LockMode) ? Function : 0, (LockMode) ? getBP() : 0, RequestLength, Request, RequestLength ); break;
case 0xD100: // Lock Logical Record Set
if (LockMode == 0) { if (getDL()) { Timeout = 0xffff; } else { Timeout = 0; } } else { Timeout = getBP(); }
status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x0A), 3, // RequestSize
0, // ResponseSize
"bw", (LockMode) ? Function : 0, Timeout); break;
case 0xD200: // Release File
case 0xD400: // Clear Logical Record
Request = GetVDMPointer ( (ULONG)((getDS() << 16)|getDX()), sizeof(UCHAR), IS_PROTECT_MODE());
RequestLength = Request[0]+1;
Request = GetVDMPointer ( (ULONG)((getDS() << 16)|getDX()), RequestLength, IS_PROTECT_MODE());
status = NwlibMakeNcp( ServerHandles[Connection], (Operation == 0xD200) ? NWR_ANY_F2_NCP(0x0C) : NWR_ANY_F2_NCP(0x0B), RequestLength+1, 0, // ResponseSize
"br", RequestLength, Request, RequestLength ); break;
case 0xD300: status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x13), 0, // RequestSize
0, // ResponseSize
""); break;
case 0xD500: // Clear Logical Record Set
status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x0E), 0, // RequestSize
0, // ResponseSize
""); break;
case 0xEB00: // Log File
case 0xEC00: // Release File
case 0xED00: // Clear File
{ UCHAR DirHandle; HANDLE Win32DirectoryHandle = 0; PUCHAR ptr;
Request = GetVDMPointer ( (ULONG)((getDS() << 16)|getDX()), 256 * sizeof(UCHAR), IS_PROTECT_MODE());
RequestLength = strlen(Request);
// Find DirHandle
ptr = Request; while ( (*ptr != 0) && (!IS_ASCII_PATH_SEPARATOR(*ptr)) && (*ptr != ':' )) { ptr++; }
if (IS_ASCII_PATH_SEPARATOR(*ptr)) { int ServerNameLength = (int) (ptr - Request); PUCHAR scanptr = ptr;
//
// Make sure there is a ":" further up the name otherwise
// we could confuse foo\bar.txt with a server called foo
//
while ( (*scanptr != 0) && (*scanptr != ':' )) { scanptr++; }
if (*scanptr) { //
// Name is of the form server\sys:foo\bar.txt
// set connection appropriately.
//
for (Connection = 0; Connection < MC ; Connection++ ) {
//
// Look for server foo avoiding foobar.
//
if ((pNwDosTable->ConnectionIdTable[Connection].ci_InUse == IN_USE) && (!memcmp( pNwDosTable->ServerNameTable[Connection], Request, ServerNameLength)) && (pNwDosTable->ServerNameTable[Connection][ServerNameLength] == '\0')) { break; // Connection is the correct server
} }
//
// Move Request to after the seperator and ptr to the ":"
//
RequestLength -= (ULONG) (ptr + sizeof(UCHAR) - Request); Request = ptr + sizeof(UCHAR); ptr = scanptr; } }
if (*ptr) {
//
// Name of form "sys:foo\bar.txt" this gives the server
// all the information required.
//
DirHandle = 0;
if (Request[1] == ':') {
UCHAR Drive = tolower(Request[0])-'a';
//
// Its a normal (redirected) drive k:foo\bar.txt.
// Use the drive tables to give the connection and handle.
//
Connection = pNwDosTable->DriveIdTable[ Drive ] - 1; DirHandle = pNwDosTable->DriveHandleTable[Drive];
if (DirHandle == 0) { DirHandle = (UCHAR)GetDirectoryHandle2(Drive); } Request += 2; // skip "k:"
RequestLength -= 2; }
} else {
WCHAR Curdir[256];
//
// Name of form "foo\bar.txt"
//
GetCurrentDirectory(sizeof(Curdir) / sizeof(WCHAR), Curdir);
Win32DirectoryHandle = CreateFileW( Curdir, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if (Win32DirectoryHandle != INVALID_HANDLE_VALUE) { DWORD BytesReturned;
if ( DeviceIoControl( Win32DirectoryHandle, IOCTL_NWR_RAW_HANDLE, NULL, 0, (PUCHAR)&DirHandle, sizeof(DirHandle), &BytesReturned, NULL ) == FALSE ) {
CloseHandle( Win32DirectoryHandle ); setAL(0xff); return;
}
} else {
setAL(0xff); return; } }
if (Operation == 0xEB00) { status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x03), RequestLength + 5, 0, // ResponseSize
"bbwbr", DirHandle, (LockMode) ? Function : 0, (LockMode) ? getBP() : 0, RequestLength, Request, RequestLength );
Tickle[Connection] = TRUE;
} else { status = NwlibMakeNcp( ServerHandles[Connection], (Operation == 0xEC00 ) ? NWR_ANY_F2_NCP(0x07) : NWR_ANY_F2_NCP(0x05), RequestLength + 2, 0, // ResponseSize
"bbr", DirHandle, RequestLength, Request, RequestLength ); }
if (Win32DirectoryHandle) { CloseHandle( Win32DirectoryHandle ); } } break;
}
if (!NT_SUCCESS(status)) { setAL((UCHAR)RtlNtStatusToDosError(status)); return; } else { setAL(0); } }
VOID InitLocks( VOID ) /*++
Routine Description:
Reset the Tickle internal variables
Arguments:
None.
Return Value:
None.
--*/ {
ZeroMemory( Tickle, sizeof(Tickle)); }
VOID ResetLocks( VOID ) /*++
Routine Description:
Reset the Locks for the current VDM. Called during process exit.
Arguments:
None.
Return Value:
None.
--*/ {
Locks(0xCF00); // Clear all File sets.
}
NTSTATUS Sem( UCHAR Function, UCHAR Connection ) /*++
Routine Description:
Build all NCPs for Semaphore support
Arguments:
Function - Supplies the subfunction from AL
Connection - Supplies the server for the request
Return Value:
None.
--*/ { PUCHAR Request; NTSTATUS status;
switch (Function) {
UCHAR Value; UCHAR OpenCount; WORD HandleHigh, HandleLow;
case 0: //OpenSemaphore
Request = GetVDMPointer ( (ULONG)((getDS() << 16)|getDX()), 256 * sizeof(UCHAR), IS_PROTECT_MODE());
NwPrint(("Nw16: OpenSemaphore\n"));
status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x20), Request[0] + 3, // RequestSize
5, // ResponseSize
"bbr|wwb", 0, getCL(), // Semaphore Value
Request, Request[0] + 1,
&HandleHigh, &HandleLow, &OpenCount);
if (NT_SUCCESS(status)) { setBL(OpenCount); setCX(HandleHigh); setDX(HandleLow); }
break;
case 1: // ExamineSemaphore
NwPrint(("Nw16: ExamineSemaphore\n")); status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x20), 5, // RequestSize
2, // ResponseSize
"bww|bb", 1, getCX(),getDX(),
&Value, &OpenCount);
if (NT_SUCCESS(status)) { setCX(Value); setDL(OpenCount); } break;
case 2: // WaitOnSemaphore
NwPrint(("Nw16: WaitOnSemaphore\n")); status = NwlibMakeNcp( ServerHandles[Connection], NWR_ANY_F2_NCP(0x20), 7, // RequestSize
0, // ResponseSize
"bwww", 2, getCX(),getDX(), getBP()); break;
case 3: // SignalSemaphore
NwPrint(("Nw16: SignalSemaphore\n")); case 4: // CloseSemaphore
if (Function == 4) { NwPrint(("Nw16: CloseSemaphore\n")); }
status = NwlibMakeNcp( // Close and Signal
ServerHandles[Connection], NWR_ANY_F2_NCP(0x20), 5, // RequestSize
0, // ResponseSize
"bww", Function, getCX(),getDX()); break;
default: NwPrint(("Nw16: Unknown Semaphore operation %d\n", Function)); status = STATUS_INVALID_PARAMETER; break; } return status; }
|