mirror of https://github.com/tongzx/nt5src
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.
404 lines
10 KiB
404 lines
10 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
lpc.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the code necessary to support sites using
|
|
lpc upcalls from the dfs driver.
|
|
|
|
Author:
|
|
|
|
Jim Harper (JHarper) 11-Dec-97
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "dfsprocs.h"
|
|
#include "dfslpc.h"
|
|
#include <dfssrv.h>
|
|
#pragma hdrstop
|
|
|
|
#include "fsctrl.h"
|
|
#include "ipsup.h"
|
|
|
|
typedef struct {
|
|
WORK_QUEUE_ITEM WorkQueueItem;
|
|
} DFS_CONNECT_ARG, *PDFS_CONNECT_ARG;
|
|
|
|
typedef struct {
|
|
WORK_QUEUE_ITEM WorkQueueItem;
|
|
DFS_IPADDRESS IpAddress;
|
|
} DFS_REQUEST_ARG, *PDFS_REQUEST_ARG;
|
|
|
|
VOID
|
|
DfsLpcConnect (
|
|
IN PDFS_CONNECT_ARG DfsConnectArg
|
|
);
|
|
|
|
#define Dbg 0x2000
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text( PAGE, DfsLpcConnect )
|
|
#pragma alloc_text( PAGE, DfsLpcIpRequest )
|
|
#pragma alloc_text( PAGE, DfsLpcDomRequest )
|
|
#pragma alloc_text( PAGE, DfsLpcDisconnect )
|
|
#endif
|
|
|
|
VOID
|
|
DfsLpcConnect (
|
|
IN PDFS_CONNECT_ARG DfsConnectArg)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
SECURITY_QUALITY_OF_SERVICE dynamicQos;
|
|
PDFS_LPC_INFO pLpcInfo = &DfsData.DfsLpcInfo;
|
|
|
|
DebugTrace(+1, Dbg, "DfsLpcConnect(Name=%wZ)\n",
|
|
&pLpcInfo->LpcPortName);
|
|
DebugTrace( 0, Dbg, "DfsLpcConnect(Handle=0x%x)\n",
|
|
&pLpcInfo->LpcPortHandle);
|
|
|
|
PAGED_CODE();
|
|
|
|
dynamicQos.Length = sizeof(SECURITY_QUALITY_OF_SERVICE);
|
|
dynamicQos.ImpersonationLevel = SecurityAnonymous;
|
|
dynamicQos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
|
|
dynamicQos.EffectiveOnly = TRUE;
|
|
|
|
ExAcquireResourceExclusiveLite( &pLpcInfo->LpcPortResource, TRUE );
|
|
|
|
ASSERT(pLpcInfo->LpcPortName.Buffer != NULL);
|
|
|
|
pLpcInfo->LpcPortState = LPC_STATE_INITIALIZED;
|
|
|
|
status = NtConnectPort(
|
|
&pLpcInfo->LpcPortHandle,
|
|
&pLpcInfo->LpcPortName,
|
|
&dynamicQos,
|
|
NULL, // ClientView
|
|
NULL, // ServerView
|
|
NULL, // MaxMessageLength
|
|
NULL, // ConnectionInformation
|
|
NULL // ConnectionInformationLength
|
|
);
|
|
|
|
DebugTrace(-1, Dbg, "DfsLpcConnect: NtConnectPort returned 0x%x\n", ULongToPtr( status ));
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
pLpcInfo->LpcPortState = LPC_STATE_UNINITIALIZED;
|
|
if ( pLpcInfo->LpcPortHandle != NULL ) {
|
|
NtClose( pLpcInfo->LpcPortHandle);
|
|
pLpcInfo->LpcPortHandle = NULL;
|
|
}
|
|
if (pLpcInfo->LpcPortName.Buffer != NULL) {
|
|
ExFreePool(pLpcInfo->LpcPortName.Buffer);
|
|
RtlInitUnicodeString(&pLpcInfo->LpcPortName, NULL);
|
|
}
|
|
}
|
|
|
|
ExReleaseResourceLite( &pLpcInfo->LpcPortResource );
|
|
ExFreePool(DfsConnectArg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
DfsLpcIpRequest (
|
|
PDFS_IPADDRESS pIpAddress)
|
|
{
|
|
NTSTATUS status;
|
|
DFSSRV_REQUEST_MESSAGE requestMessage;
|
|
DFSSRV_REPLY_MESSAGE replyMessage;
|
|
PDFS_LPC_INFO pLpcInfo = &DfsData.DfsLpcInfo;
|
|
|
|
PAGED_CODE();
|
|
|
|
requestMessage.Message.GetSiteName.IpAddress = *pIpAddress;
|
|
|
|
//
|
|
// Set up the message to send over the port.
|
|
//
|
|
|
|
requestMessage.PortMessage.u1.s1.DataLength =
|
|
(USHORT)( sizeof(requestMessage) - sizeof(PORT_MESSAGE) );
|
|
requestMessage.PortMessage.u1.s1.TotalLength = sizeof(requestMessage);
|
|
requestMessage.PortMessage.u2.ZeroInit = 0;
|
|
requestMessage.MessageType = DFSSRV_MESSAGE_GET_SITE_NAME;
|
|
|
|
//
|
|
// Send the message and wait for a response message.
|
|
//
|
|
|
|
status = NtRequestWaitReplyPort(
|
|
pLpcInfo->LpcPortHandle,
|
|
(PPORT_MESSAGE)&requestMessage,
|
|
(PPORT_MESSAGE)&replyMessage
|
|
);
|
|
|
|
if ( !NT_SUCCESS(status) ) {
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Check the status returned in the reply.
|
|
//
|
|
|
|
status = replyMessage.Message.Result.Status;
|
|
|
|
exit:
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
DfsLpcDomRequest (
|
|
PUNICODE_STRING pFtName)
|
|
{
|
|
NTSTATUS status;
|
|
DFSSRV_REQUEST_MESSAGE requestMessage;
|
|
DFSSRV_REPLY_MESSAGE replyMessage;
|
|
PDFS_LPC_INFO pLpcInfo = &DfsData.DfsLpcInfo;
|
|
|
|
PAGED_CODE();
|
|
|
|
if ( pFtName->Length > ((MAX_FTNAME_LEN - 1) * sizeof(WCHAR))) {
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
RtlZeroMemory(requestMessage.Message.GetFtDfs.FtName, MAX_FTNAME_LEN * sizeof(WCHAR));
|
|
RtlCopyMemory(requestMessage.Message.GetFtDfs.FtName, pFtName->Buffer, pFtName->Length);
|
|
|
|
//
|
|
// Set up the message to send over the port.
|
|
//
|
|
|
|
requestMessage.PortMessage.u1.s1.DataLength =
|
|
(USHORT)( sizeof(requestMessage) - sizeof(PORT_MESSAGE) );
|
|
requestMessage.PortMessage.u1.s1.TotalLength = sizeof(requestMessage);
|
|
requestMessage.PortMessage.u2.ZeroInit = 0;
|
|
requestMessage.MessageType = DFSSRV_MESSAGE_GET_DOMAIN_REFERRAL;
|
|
|
|
//
|
|
// Send the message and wait for a response message.
|
|
//
|
|
|
|
status = NtRequestWaitReplyPort(
|
|
pLpcInfo->LpcPortHandle,
|
|
(PPORT_MESSAGE)&requestMessage,
|
|
(PPORT_MESSAGE)&replyMessage
|
|
);
|
|
|
|
if ( !NT_SUCCESS(status) ) {
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Check the status returned in the reply.
|
|
//
|
|
|
|
status = replyMessage.Message.Result.Status;
|
|
|
|
exit:
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
DfsLpcSpcRequest(
|
|
PUNICODE_STRING pSpcName,
|
|
ULONG TypeFlags)
|
|
{
|
|
NTSTATUS status;
|
|
DFSSRV_REQUEST_MESSAGE requestMessage;
|
|
DFSSRV_REPLY_MESSAGE replyMessage;
|
|
PDFS_LPC_INFO pLpcInfo = &DfsData.DfsLpcInfo;
|
|
|
|
PAGED_CODE();
|
|
|
|
if ( pSpcName->Length > ((MAX_SPCNAME_LEN - 1) * sizeof(WCHAR))) {
|
|
pSpcName = NULL;
|
|
}
|
|
|
|
RtlZeroMemory(requestMessage.Message.GetSpcName.SpcName, MAX_SPCNAME_LEN * sizeof(WCHAR));
|
|
|
|
if (pSpcName != NULL) {
|
|
RtlCopyMemory(requestMessage.Message.GetSpcName.SpcName, pSpcName->Buffer, pSpcName->Length);
|
|
}
|
|
requestMessage.Message.GetSpcName.Flags = TypeFlags;
|
|
|
|
//
|
|
// Set up the message to send over the port.
|
|
//
|
|
|
|
requestMessage.PortMessage.u1.s1.DataLength =
|
|
(USHORT)( sizeof(requestMessage) - sizeof(PORT_MESSAGE) );
|
|
requestMessage.PortMessage.u1.s1.TotalLength = sizeof(requestMessage);
|
|
requestMessage.PortMessage.u2.ZeroInit = 0;
|
|
requestMessage.MessageType = DFSSRV_MESSAGE_GET_SPC_ENTRY;
|
|
|
|
//
|
|
// Send the message and wait for a response message.
|
|
//
|
|
|
|
status = NtRequestWaitReplyPort(
|
|
pLpcInfo->LpcPortHandle,
|
|
(PPORT_MESSAGE)&requestMessage,
|
|
(PPORT_MESSAGE)&replyMessage
|
|
);
|
|
|
|
if ( !NT_SUCCESS(status) ) {
|
|
goto exit;
|
|
}
|
|
|
|
//
|
|
// Check the status returned in the reply.
|
|
//
|
|
|
|
status = replyMessage.Message.Result.Status;
|
|
|
|
exit:
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
DfsLpcDisconnect ( )
|
|
{
|
|
NTSTATUS status;
|
|
PDFS_LPC_INFO pLpcInfo = &DfsData.DfsLpcInfo;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Acquire exclusive access to the port resource, to prevent new
|
|
// requests from being started.
|
|
//
|
|
|
|
ExAcquireResourceExclusiveLite( &pLpcInfo->LpcPortResource, TRUE );
|
|
|
|
pLpcInfo->LpcPortState = LPC_STATE_UNINITIALIZED;
|
|
|
|
if (pLpcInfo->LpcPortHandle != NULL) {
|
|
NtClose( pLpcInfo->LpcPortHandle);
|
|
pLpcInfo->LpcPortHandle = NULL;
|
|
}
|
|
|
|
if (pLpcInfo->LpcPortName.Buffer != NULL) {
|
|
ExFreePool(pLpcInfo->LpcPortName.Buffer);
|
|
RtlInitUnicodeString(&pLpcInfo->LpcPortName, NULL);
|
|
}
|
|
|
|
ExReleaseResourceLite( &pLpcInfo->LpcPortResource );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
PktFsctrlDfsSrvConnect(
|
|
IN PIRP Irp,
|
|
IN PVOID InputBuffer,
|
|
IN ULONG InputBufferLength)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
PDFS_SRV_DFSSRV_CONNECT_ARG arg;
|
|
PDFS_CONNECT_ARG DfsConnectArg = NULL;
|
|
PDFS_LPC_INFO pLpcInfo = &DfsData.DfsLpcInfo;
|
|
|
|
STD_FSCTRL_PROLOGUE(DfsFsctrlDfsSrvConnect, TRUE, FALSE);
|
|
|
|
if (InputBufferLength < sizeof(DFS_SRV_DFSSRV_CONNECT_ARG)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto exit_with_status;
|
|
}
|
|
|
|
//
|
|
// unmarshal the arguments...
|
|
//
|
|
|
|
arg = (PDFS_SRV_DFSSRV_CONNECT_ARG) InputBuffer;
|
|
|
|
OFFSET_TO_POINTER(arg->PortName.Buffer, arg);
|
|
|
|
if (!UNICODESTRING_IS_VALID(arg->PortName, InputBuffer, InputBufferLength)) {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
goto exit_with_status;
|
|
}
|
|
|
|
DfsConnectArg = ExAllocatePoolWithTag(
|
|
NonPagedPool,
|
|
sizeof(DFS_CONNECT_ARG),
|
|
' sfD');
|
|
|
|
|
|
if (DfsConnectArg == NULL) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto exit_with_status;
|
|
}
|
|
|
|
ExAcquireResourceExclusiveLite( &pLpcInfo->LpcPortResource, TRUE );
|
|
|
|
#if 0
|
|
if (pLpcInfo->LpcPortName.Buffer != NULL) {
|
|
ExFreePool(pLpcInfo->LpcPortName.Buffer);
|
|
RtlInitUnicodeString(&pLpcInfo->LpcPortName, NULL);
|
|
}
|
|
if ( pLpcInfo->LpcPortHandle != NULL ) {
|
|
NtClose( pLpcInfo->LpcPortHandle);
|
|
pLpcInfo->LpcPortHandle = NULL;
|
|
}
|
|
#endif
|
|
|
|
pLpcInfo->LpcPortName.Buffer = ExAllocatePoolWithTag(
|
|
PagedPool,
|
|
arg->PortName.Length,
|
|
' sfD');
|
|
|
|
if (pLpcInfo->LpcPortName.Buffer == NULL) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
ExFreePool(DfsConnectArg);
|
|
ExReleaseResourceLite( &pLpcInfo->LpcPortResource );
|
|
goto exit_with_status;
|
|
}
|
|
|
|
pLpcInfo->LpcPortName.Length = arg->PortName.Length;
|
|
pLpcInfo->LpcPortName.MaximumLength = arg->PortName.Length;
|
|
|
|
RtlCopyMemory(
|
|
pLpcInfo->LpcPortName.Buffer,
|
|
arg->PortName.Buffer,
|
|
arg->PortName.Length);
|
|
|
|
ExInitializeWorkItem(
|
|
&DfsConnectArg->WorkQueueItem,
|
|
DfsLpcConnect,
|
|
DfsConnectArg);
|
|
|
|
ExQueueWorkItem( &DfsConnectArg->WorkQueueItem, CriticalWorkQueue );
|
|
|
|
pLpcInfo->LpcPortState = LPC_STATE_INITIALIZING;
|
|
|
|
ExReleaseResourceLite( &pLpcInfo->LpcPortResource );
|
|
|
|
exit_with_status:
|
|
|
|
DfsCompleteRequest( Irp, status );
|
|
|
|
DebugTrace(-1, Dbg, "DfsFsctrlDfsSrvConnect: Exit -> %08lx\n", ULongToPtr( status ) );
|
|
|
|
return status;
|
|
}
|