679 lines
18 KiB
C
679 lines
18 KiB
C
|
|
/*++
|
|
|
|
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;
|
|
}
|