Source code of Windows XP (NT5)
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

/*++
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;
}