758 lines
21 KiB
C
758 lines
21 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 2000-2000 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
Init.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements Initialization routines
|
|||
|
the PGM Transport and other routines that are specific to the
|
|||
|
NT implementation of a driver.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Mohammad Shabbir Alam (MAlam) 3-30-2000
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#include <ntddtcp.h>
|
|||
|
|
|||
|
|
|||
|
//******************* Pageable Routine Declarations ****************
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, InitPgm)
|
|||
|
#pragma alloc_text(PAGE, InitStaticPgmConfig)
|
|||
|
#pragma alloc_text(PAGE, InitDynamicPgmConfig)
|
|||
|
#pragma alloc_text(PAGE, PgmReadRegistryParameters)
|
|||
|
#pragma alloc_text(PAGE, AllocateInitialPgmStructures)
|
|||
|
#pragma alloc_text(PAGE, PgmCreateDevice)
|
|||
|
#pragma alloc_text(PAGE, PgmDereferenceDevice)
|
|||
|
#endif
|
|||
|
//******************* Pageable Routine Declarations ****************
|
|||
|
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
InitStaticPgmConfig(
|
|||
|
IN PDRIVER_OBJECT DriverObject,
|
|||
|
IN PUNICODE_STRING RegistryPath
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the static values used by Pgm
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN DriverObject - Pointer to driver object created by the system.
|
|||
|
IN RegistryPath - Pgm driver's registry location
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Final status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the Static Configuration data structure
|
|||
|
//
|
|||
|
PgmZeroMemory (&PgmStaticConfig, sizeof(tPGM_STATIC_CONFIG));
|
|||
|
|
|||
|
//
|
|||
|
// get the file system process since we need to know this for
|
|||
|
// allocating and freeing handles
|
|||
|
//
|
|||
|
PgmStaticConfig.FspProcess = PsGetCurrentProcess();
|
|||
|
PgmStaticConfig.DriverObject = DriverObject; // save the driver object for event logging purposes
|
|||
|
|
|||
|
//
|
|||
|
// save the registry path for later use (to read the registry)
|
|||
|
//
|
|||
|
PgmStaticConfig.RegistryPath.MaximumLength = (USHORT) RegistryPath->MaximumLength;
|
|||
|
if (PgmStaticConfig.RegistryPath.Buffer = PgmAllocMem (RegistryPath->MaximumLength, PGM_TAG('0')))
|
|||
|
{
|
|||
|
RtlCopyUnicodeString(&PgmStaticConfig.RegistryPath, RegistryPath);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitStaticPgmConfig",
|
|||
|
"INSUFFICIENT_RESOURCES <%d> bytes\n", PgmStaticConfig.RegistryPath.MaximumLength);
|
|||
|
|
|||
|
return (STATUS_INSUFFICIENT_RESOURCES);
|
|||
|
}
|
|||
|
|
|||
|
ExInitializeNPagedLookasideList(&PgmStaticConfig.TdiLookasideList,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
sizeof (tTDI_SEND_CONTEXT),
|
|||
|
PGM_TAG('2'),
|
|||
|
TDI_LOOKASIDE_DEPTH);
|
|||
|
|
|||
|
ExInitializeNPagedLookasideList(&PgmStaticConfig.DebugMessagesLookasideList,
|
|||
|
NULL,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
(MAX_DEBUG_MESSAGE_LENGTH + 1),
|
|||
|
PGM_TAG('3'),
|
|||
|
DEBUG_MESSAGES_LOOKASIDE_DEPTH);
|
|||
|
|
|||
|
status = FECInitGlobals ();
|
|||
|
|
|||
|
if (!NT_SUCCESS (status))
|
|||
|
{
|
|||
|
ExDeleteNPagedLookasideList (&PgmStaticConfig.DebugMessagesLookasideList);
|
|||
|
ExDeleteNPagedLookasideList (&PgmStaticConfig.TdiLookasideList);
|
|||
|
PgmFreeMem (PgmStaticConfig.RegistryPath.Buffer);
|
|||
|
}
|
|||
|
|
|||
|
PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_INIT_PGM, "InitStaticPgmConfig",
|
|||
|
"FECInitGlobals returned <%x>\n", status);
|
|||
|
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
InitDynamicPgmConfig(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine initializes the dynamic values used by Pgm
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Final status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG i;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the Static Configuration data structure
|
|||
|
//
|
|||
|
PgmZeroMemory (&PgmDynamicConfig, sizeof(tPGM_DYNAMIC_CONFIG));
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the list heads before doing anything else since
|
|||
|
// we can access them anytime later
|
|||
|
//
|
|||
|
InitializeListHead (&PgmDynamicConfig.SenderAddressHead);
|
|||
|
InitializeListHead (&PgmDynamicConfig.ReceiverAddressHead);
|
|||
|
InitializeListHead (&PgmDynamicConfig.CurrentReceivers);
|
|||
|
InitializeListHead (&PgmDynamicConfig.CleanedUpAddresses);
|
|||
|
InitializeListHead (&PgmDynamicConfig.ClosedConnections);
|
|||
|
InitializeListHead (&PgmDynamicConfig.ConnectionsCreated);
|
|||
|
InitializeListHead (&PgmDynamicConfig.CleanedUpConnections);
|
|||
|
InitializeListHead (&PgmDynamicConfig.LocalInterfacesList);
|
|||
|
InitializeListHead (&PgmDynamicConfig.WorkerQList);
|
|||
|
|
|||
|
PgmDynamicConfig.ReceiversTimerTickCount = 1; // Init
|
|||
|
PgmDynamicConfig.SourcePort = (USHORT) GetRandomInteger (2000, 20000);
|
|||
|
|
|||
|
#if DBG
|
|||
|
for (i=0; i<MAXIMUM_PROCESSORS; i++)
|
|||
|
{
|
|||
|
PgmDynamicConfig.CurrentLockNumber[i] = 0;
|
|||
|
}
|
|||
|
#endif
|
|||
|
PgmInitLock (&PgmDynamicConfig, DCONFIG_LOCK);
|
|||
|
|
|||
|
KeInitializeEvent (&PgmDynamicConfig.LastWorkerItemEvent, NotificationEvent, TRUE);
|
|||
|
|
|||
|
PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_INIT_PGM, "InitDynamicPgmConfig",
|
|||
|
"STATUS_SUCCESS\n");
|
|||
|
|
|||
|
return (STATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
PgmOpenRegistryParameters(
|
|||
|
IN PUNICODE_STRING RegistryPath,
|
|||
|
OUT HANDLE *pConfigHandle,
|
|||
|
OUT HANDLE *pParametersHandle
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine reads any required registry parameters
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
OUT ppPgmDynamic -- non-NULL only if we have any registry valuies to read
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Final status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
OBJECT_ATTRIBUTES TmpObjectAttributes;
|
|||
|
NTSTATUS status;
|
|||
|
ULONG Disposition;
|
|||
|
UNICODE_STRING KeyName;
|
|||
|
PWSTR ParametersString = L"Parameters";
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
InitializeObjectAttributes (&TmpObjectAttributes,
|
|||
|
RegistryPath, // name
|
|||
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // attributes
|
|||
|
NULL, // root
|
|||
|
NULL); // security descriptor
|
|||
|
|
|||
|
status = ZwCreateKey (pConfigHandle,
|
|||
|
KEY_READ,
|
|||
|
&TmpObjectAttributes,
|
|||
|
0, // title index
|
|||
|
NULL, // class
|
|||
|
0, // create options
|
|||
|
&Disposition); // disposition
|
|||
|
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "PgmOpenRegistryParameters",
|
|||
|
"ZwCreateKey returned <%x>\n", status);
|
|||
|
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Open the Pgm key.
|
|||
|
//
|
|||
|
RtlInitUnicodeString (&KeyName, ParametersString);
|
|||
|
InitializeObjectAttributes (&TmpObjectAttributes,
|
|||
|
&KeyName, // name
|
|||
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // attributes
|
|||
|
*pConfigHandle, // root
|
|||
|
NULL); // security descriptor
|
|||
|
|
|||
|
status = ZwOpenKey (pParametersHandle, KEY_READ, &TmpObjectAttributes);
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "PgmOpenRegistryParameters",
|
|||
|
"ZwOpenKey returned <%x>\n", status);
|
|||
|
|
|||
|
ZwClose(*pConfigHandle);
|
|||
|
}
|
|||
|
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
ReadRegistryElement(
|
|||
|
IN HANDLE HandleToKey,
|
|||
|
IN PWSTR pwsValueName,
|
|||
|
OUT PUNICODE_STRING pucString
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is will read a string value given by pwsValueName, under a
|
|||
|
given Key (which must be open) - given by HandleToKey. This routine
|
|||
|
allocates memory for the buffer in the returned pucString, so the caller
|
|||
|
must deallocate that.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pwsValueName- the name of the value to read (i.e. IPAddress)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
pucString - the string returns the string read from the registry
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
ULONG BytesRead;
|
|||
|
NTSTATUS Status;
|
|||
|
UNICODE_STRING TempString;
|
|||
|
PKEY_VALUE_FULL_INFORMATION ReadValue = NULL;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// First, get the sizeof the string
|
|||
|
//
|
|||
|
RtlInitUnicodeString(&TempString, pwsValueName); // initilize the name of the value to read
|
|||
|
Status = ZwQueryValueKey (HandleToKey,
|
|||
|
&TempString, // string to retrieve
|
|||
|
KeyValueFullInformation,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&BytesRead); // get bytes to be read
|
|||
|
|
|||
|
if (((!NT_SUCCESS (Status)) &&
|
|||
|
(Status != STATUS_BUFFER_OVERFLOW) &&
|
|||
|
(Status != STATUS_BUFFER_TOO_SMALL)) ||
|
|||
|
(BytesRead == 0))
|
|||
|
{
|
|||
|
return (STATUS_UNSUCCESSFUL);
|
|||
|
}
|
|||
|
|
|||
|
if (ReadValue = (PKEY_VALUE_FULL_INFORMATION) PgmAllocMem (BytesRead, PGM_TAG('R')))
|
|||
|
{
|
|||
|
Status = ZwQueryValueKey (HandleToKey,
|
|||
|
&TempString, // string to retrieve
|
|||
|
KeyValueFullInformation,
|
|||
|
(PVOID)ReadValue, // returned info
|
|||
|
BytesRead,
|
|||
|
&BytesRead); // # of bytes returned
|
|||
|
|
|||
|
if ((NT_SUCCESS (Status)) &&
|
|||
|
(ReadValue->DataLength))
|
|||
|
{
|
|||
|
// move the read in data to the front of the buffer
|
|||
|
RtlMoveMemory ((PVOID) ReadValue, (((PUCHAR)ReadValue) + ReadValue->DataOffset), ReadValue->DataLength);
|
|||
|
RtlInitUnicodeString (pucString, (PWSTR) ReadValue);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
PgmFreeMem (ReadValue);
|
|||
|
Status = STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
return(Status);
|
|||
|
}
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
PgmReadRegistryParameters(
|
|||
|
IN PUNICODE_STRING RegistryPath,
|
|||
|
OUT tPGM_REGISTRY_CONFIG **ppPgmRegistryConfig
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine reads any required registry parameters
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
OUT ppPgmDynamic -- non-NULL only if we have any registry valuies to read
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Final status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
HANDLE PgmConfigHandle;
|
|||
|
HANDLE ParametersHandle;
|
|||
|
NTSTATUS status;
|
|||
|
tPGM_REGISTRY_CONFIG *pRegistryConfig;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (!(pRegistryConfig = PgmAllocMem (sizeof (tPGM_REGISTRY_CONFIG), PGM_TAG('0'))))
|
|||
|
{
|
|||
|
return (STATUS_INSUFFICIENT_RESOURCES);
|
|||
|
}
|
|||
|
|
|||
|
status = PgmOpenRegistryParameters (RegistryPath, &PgmConfigHandle, &ParametersHandle);
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "PgmReadRegistryParameters",
|
|||
|
"ZwOpenKey returned <%x>\n", status);
|
|||
|
|
|||
|
PgmFreeMem (pRegistryConfig);
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// zero out the Registry fields
|
|||
|
//
|
|||
|
PgmZeroMemory (pRegistryConfig, sizeof(tPGM_REGISTRY_CONFIG));
|
|||
|
|
|||
|
//
|
|||
|
// ***************************************
|
|||
|
// Now read all the registry needs we need
|
|||
|
//
|
|||
|
|
|||
|
status = ReadRegistryElement (ParametersHandle,
|
|||
|
PARAM_SENDER_FILE_LOCATION,
|
|||
|
&pRegistryConfig->ucSenderFileLocation);
|
|||
|
if (NT_SUCCESS (status))
|
|||
|
{
|
|||
|
pRegistryConfig->Flags |= PGM_REGISTRY_SENDER_FILE_SPECIFIED;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// End of list of entries to be read
|
|||
|
// ***************************************
|
|||
|
//
|
|||
|
|
|||
|
ZwClose(ParametersHandle);
|
|||
|
ZwClose(PgmConfigHandle);
|
|||
|
|
|||
|
PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_INIT_PGM, "PgmReadRegistryParameters",
|
|||
|
"STATUS_SUCCESS\n");
|
|||
|
|
|||
|
*ppPgmRegistryConfig = pRegistryConfig;
|
|||
|
|
|||
|
return (STATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
AllocateInitialPgmStructures(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine allocates any initial structures that may be required
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Final status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_INIT_PGM, "AllocateInitialPgmStructures",
|
|||
|
"STATUS_SUCCESS\n");
|
|||
|
|
|||
|
return (STATUS_SUCCESS);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
PgmCreateDevice(
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine allocates the Pgm device for clients to
|
|||
|
call into the Pgm driver.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Final status of the CreateDevice operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS Status;
|
|||
|
tPGM_DEVICE *pPgmDevice = NULL;
|
|||
|
UNICODE_STRING ucPgmDeviceExportName;
|
|||
|
UNICODE_STRING ucProtocolNumber;
|
|||
|
WCHAR wcProtocolNumber[10];
|
|||
|
USHORT PgmBindDeviceNameLength;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RtlInitUnicodeString (&ucPgmDeviceExportName, WC_PGM_DEVICE_EXPORT_NAME);
|
|||
|
PgmBindDeviceNameLength = sizeof(DD_RAW_IP_DEVICE_NAME) + 10;
|
|||
|
|
|||
|
Status = IoCreateDevice (PgmStaticConfig.DriverObject, // Driver Object
|
|||
|
sizeof(tPGM_DEVICE)+PgmBindDeviceNameLength, // Device Extension
|
|||
|
&ucPgmDeviceExportName, // Device Name
|
|||
|
FILE_DEVICE_NETWORK, // Device type 0x12
|
|||
|
FILE_DEVICE_SECURE_OPEN, // Device Characteristics
|
|||
|
FALSE, // Exclusive
|
|||
|
&pPgmDeviceObject);
|
|||
|
|
|||
|
if (!NT_SUCCESS (Status))
|
|||
|
{
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "PgmCreateDevice",
|
|||
|
"FAILed <%x> ExportDevice=%wZ\n", Status, &ucPgmDeviceExportName);
|
|||
|
|
|||
|
pgPgmDevice = NULL;
|
|||
|
return Status;
|
|||
|
}
|
|||
|
|
|||
|
pPgmDevice = (tPGM_DEVICE *) pPgmDeviceObject->DeviceExtension;
|
|||
|
|
|||
|
//
|
|||
|
// zero out the DeviceExtension
|
|||
|
//
|
|||
|
PgmZeroMemory (pPgmDevice, sizeof(tPGM_DEVICE)+PgmBindDeviceNameLength);
|
|||
|
|
|||
|
// put a verifier value into the structure so that we can check that
|
|||
|
// we are operating on the right data
|
|||
|
PgmInitLock (pPgmDevice, DEVICE_LOCK);
|
|||
|
pPgmDevice->Verify = PGM_VERIFY_DEVICE;
|
|||
|
PGM_REFERENCE_DEVICE (pPgmDevice, REF_DEV_CREATE, TRUE);
|
|||
|
|
|||
|
pPgmDevice->pPgmDeviceObject = pPgmDeviceObject;
|
|||
|
//
|
|||
|
// Save the raw IP device name as a counted string. The device
|
|||
|
// name is followed by a path separator then the protocol number
|
|||
|
// of interest.
|
|||
|
//
|
|||
|
pPgmDevice->ucBindName.Buffer = (PWSTR) &pPgmDevice->BindNameBuffer;
|
|||
|
pPgmDevice->ucBindName.Length = 0;
|
|||
|
pPgmDevice->ucBindName.MaximumLength = PgmBindDeviceNameLength;
|
|||
|
RtlAppendUnicodeToString (&pPgmDevice->ucBindName, DD_RAW_IP_DEVICE_NAME);
|
|||
|
pPgmDevice->ucBindName.Buffer[pPgmDevice->ucBindName.Length / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
|
|||
|
pPgmDevice->ucBindName.Length += sizeof(WCHAR);
|
|||
|
|
|||
|
ucProtocolNumber.Buffer = wcProtocolNumber;
|
|||
|
ucProtocolNumber.MaximumLength = sizeof (wcProtocolNumber);
|
|||
|
RtlIntegerToUnicodeString ((ULONG) IPPROTO_RM, 10, &ucProtocolNumber);
|
|||
|
|
|||
|
RtlAppendUnicodeStringToString (&pPgmDevice->ucBindName, &ucProtocolNumber);
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the event that will be used to signal the Device is ready to be deleted
|
|||
|
//
|
|||
|
KeInitializeEvent (&pPgmDevice->DeviceCleanedupEvent, NotificationEvent, FALSE);
|
|||
|
|
|||
|
//
|
|||
|
// Now open a control channel on top of Ip
|
|||
|
//
|
|||
|
Status = PgmTdiOpenControl (pPgmDevice);
|
|||
|
if (!NT_SUCCESS (Status))
|
|||
|
{
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "PgmCreateDevice",
|
|||
|
"PgmTdiOpenControl FAILed <%x>\n", Status);
|
|||
|
|
|||
|
IoDeleteDevice (pPgmDeviceObject);
|
|||
|
return (Status);
|
|||
|
}
|
|||
|
|
|||
|
// increase the stack size of our device object, over that of the transport
|
|||
|
// so that clients create Irps large enough
|
|||
|
// to pass on to the transport below.
|
|||
|
// In theory, we should just add 1 here, to account for our presence in the
|
|||
|
// driver chain.
|
|||
|
//
|
|||
|
pPgmDeviceObject->StackSize = pPgmDevice->pControlDeviceObject->StackSize + 1;
|
|||
|
|
|||
|
pPgmDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|||
|
pgPgmDevice = pPgmDevice;
|
|||
|
|
|||
|
PgmLog (PGM_LOG_INFORM_STATUS, DBG_INIT_PGM, "PgmCreateDevice",
|
|||
|
"Status=<%x> ExportDevice=%wZ\n", Status, &ucPgmDeviceExportName);
|
|||
|
|
|||
|
return (Status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
VOID
|
|||
|
PgmDereferenceDevice(
|
|||
|
IN OUT tPGM_DEVICE **ppPgmDevice,
|
|||
|
IN ULONG RefContext
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine dereferences the RefCount on the Pgm
|
|||
|
device extension and deletes the device if the RefCount
|
|||
|
goes down to 0.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN ppPgmDevice -- ptr to PgmDevice Extension
|
|||
|
IN RefContext -- the context for which this device extension was
|
|||
|
referenced earlier
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Final status of the set event operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
tPGM_DEVICE *pPgmDevice = *ppPgmDevice;
|
|||
|
KAPC_STATE ApcState;
|
|||
|
BOOLEAN fAttached;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
ASSERT (PGM_VERIFY_HANDLE (pPgmDevice, PGM_VERIFY_DEVICE));
|
|||
|
ASSERT (pPgmDevice->RefCount); // Check for too many derefs
|
|||
|
ASSERT (pPgmDevice->ReferenceContexts[RefContext]--);
|
|||
|
|
|||
|
if (--pPgmDevice->RefCount)
|
|||
|
{
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if (pPgmDevice->hControl)
|
|||
|
{
|
|||
|
//
|
|||
|
// This is only done at Load/Unload time, so we should
|
|||
|
// be currently in the System Process Context!
|
|||
|
//
|
|||
|
PgmAttachFsp (&ApcState, &fAttached, REF_FSP_DESTROY_DEVICE);
|
|||
|
|
|||
|
ObDereferenceObject (pPgmDevice->pControlFileObject);
|
|||
|
ZwClose (pPgmDevice->hControl);
|
|||
|
|
|||
|
pPgmDevice->pControlFileObject = NULL;
|
|||
|
pPgmDevice->hControl = NULL;
|
|||
|
|
|||
|
PgmDetachFsp (&ApcState, &fAttached, REF_FSP_DESTROY_DEVICE);
|
|||
|
}
|
|||
|
|
|||
|
PgmLog (PGM_LOG_INFORM_STATUS, DBG_INIT_PGM, "PgmDereferenceDevice",
|
|||
|
"Deleting pgPgmDevice=%x ...\n", pgPgmDevice);
|
|||
|
|
|||
|
IoDeleteDevice (pPgmDevice->pPgmDeviceObject);
|
|||
|
*ppPgmDevice = NULL;
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//----------------------------------------------------------------------------
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
InitPgm(
|
|||
|
IN PDRIVER_OBJECT DriverObject,
|
|||
|
IN PUNICODE_STRING RegistryPath
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called at DriverEntry to initialize all the
|
|||
|
Pgm parameters
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
IN DriverObject - Pointer to driver object created by the system.
|
|||
|
IN RegistryPath - Pgm driver's registry location
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - Final status of the set event operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
tPGM_REGISTRY_CONFIG *pPgmRegistry = NULL;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
status = InitStaticPgmConfig (DriverObject, RegistryPath);
|
|||
|
if (!NT_SUCCESS (status))
|
|||
|
{
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitPgm",
|
|||
|
"InitStaticPgmConfig returned <%x>\n", status);
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------------------------------------------------------------------
|
|||
|
|
|||
|
status = InitDynamicPgmConfig ();
|
|||
|
if (!NT_SUCCESS (status))
|
|||
|
{
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitPgm",
|
|||
|
"InitDynamicPgmConfig returned <%x>\n", status);
|
|||
|
CleanupInit (E_CLEANUP_STATIC_CONFIG);
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Read Registry configuration data
|
|||
|
//
|
|||
|
status = PgmReadRegistryParameters (RegistryPath, &pPgmRegistry);
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
//
|
|||
|
// There must have been some major problems with the registry read, so we will not load!
|
|||
|
//
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitPgm",
|
|||
|
"FAILed to read registry, status = <%x>\n", status);
|
|||
|
CleanupInit (E_CLEANUP_DYNAMIC_CONFIG);
|
|||
|
return (status);
|
|||
|
}
|
|||
|
ASSERT (pPgmRegistry);
|
|||
|
pPgmRegistryConfig = pPgmRegistry;
|
|||
|
|
|||
|
//---------------------------------------------------------------------------------------
|
|||
|
|
|||
|
//
|
|||
|
// Allocate the data structures we need at Init time
|
|||
|
//
|
|||
|
status = AllocateInitialPgmStructures ();
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
//
|
|||
|
// There must have been some major problems with the registry read, so we will not load!
|
|||
|
//
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitPgm",
|
|||
|
"FAILed to allocate initial structures = <%x>\n", status);
|
|||
|
CleanupInit (E_CLEANUP_REGISTRY_PARAMETERS);
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
//---------------------------------------------------------------------------------------
|
|||
|
//
|
|||
|
// Create the Pgm Device to be exported
|
|||
|
//
|
|||
|
status = PgmCreateDevice ();
|
|||
|
if (!NT_SUCCESS(status))
|
|||
|
{
|
|||
|
//
|
|||
|
// There must have been some major problems with the registry read, so we will not load!
|
|||
|
//
|
|||
|
PgmLog (PGM_LOG_ERROR, DBG_INIT_PGM, "InitPgm",
|
|||
|
"FAILed to create PgmDevice, status=<%x>\n", status);
|
|||
|
CleanupInit (E_CLEANUP_STRUCTURES);
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_INIT_PGM, "InitPgm",
|
|||
|
"SUCCEEDed!\n");
|
|||
|
|
|||
|
return (status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|