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);
|
||
}
|
||
|
||
|
||
|