Registering a Miniport intermediate driver.

Hi All,

I am trying to implement a miniport-intermediate driver. From MSDN documentation it is clear that I need to call NdisMRegisterMiniportDriver twice.

So the two calls to NdisRegisterMiniportDriver are as follows:

NdisZeroMemory(&MChars, sizeof(MChars));
MChars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,
MChars.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);
MChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
MChars.MajorNdisVersion = ATH_WLAN_NDIS_MAJOR_VERSION;
MChars.MinorNdisVersion = ATH_WLAN_NDIS_MINOR_VERSION;
MChars.CancelOidRequestHandler = Ar6kMpCancelRequest;
MChars.CancelSendHandler = Ar6kMpCancelSendNetBufferLists;
MChars.CheckForHangHandlerEx = Ar6kMpCheckForHang;
MChars.DevicePnPEventNotifyHandler = Ar6kMpDevicePnPEvent;
MChars.HaltHandlerEx = Ar6kMpHalt;
MChars.InitializeHandlerEx = Ar6kMpInitialize;
MChars.OidRequestHandler = Ar6kMpRequest;
MChars.PauseHandler = Ar6kMpPause;
MChars.ResetHandlerEx = Ar6kMpReset;
MChars.RestartHandler = Ar6kMpRestart;
MChars.ReturnNetBufferListsHandler = Ar6kMpReturnNetBufferLists;
MChars.SendNetBufferListsHandler = Ar6kMpSendNetBufferLists;
MChars.SetOptionsHandler = Ar6kMpSetOptions;
MChars.ShutdownHandlerEx = Ar6kMpAdapterShutdown;
MChars.UnloadHandler = DriverUnload;

MChars.MajorDriverVersion = ATH_MAJOR_DRIVER_VERSION;
MChars.MinorDriverVersion = ATH_MINOR_DRIVER_VERSION;

//
// Register the miniport driver with NDIS
//
Status = NdisMRegisterMiniportDriver(
pDriverObject,
RegistryPath,
GlobalDriverContext,
&MChars,
&GlobalDriverHandle
);
if ( Status != NDIS_STATUS_SUCCESS )
{
ATH_DISPLAY_MSG(“AR6K: ERROR - NdisMRegisterMiniport failed to register for STA %d.%d Miniport[Status %d]\r\n”,MChars.MajorNdisVersion,MChars.MinorNdisVersion,Status);
NdisMDeregisterMiniportDriver(GlobalDriverHandle);
}

NdisZeroMemory(&MApChars, sizeof(MApChars));

MApChars.Header.Type = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS,
MApChars.Header.Size = sizeof(NDIS_MINIPORT_DRIVER_CHARACTERISTICS);
MApChars.Header.Revision = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
MApChars.MajorNdisVersion = ATH_WLAN_NDIS_MAJOR_VERSION;
MApChars.MinorNdisVersion = ATH_WLAN_NDIS_MINOR_VERSION;
MApChars.CancelOidRequestHandler = Ar6kMpCancelRequestAP;
MApChars.CancelSendHandler = Ar6kMpCancelSendNetBufferListsAP;
MApChars.CheckForHangHandlerEx = Ar6kMpCheckForHangAP;
MApChars.DevicePnPEventNotifyHandler = Ar6kMpDevicePnPEventAP;
MApChars.HaltHandlerEx = Ar6kMpHaltAP;
MApChars.InitializeHandlerEx = Ar6kMpInitializeAP;
MApChars.OidRequestHandler = Ar6kMpRequestAP;
MApChars.PauseHandler = Ar6kMpPauseAP;
MApChars.ResetHandlerEx = Ar6kMpResetAP;
MApChars.RestartHandler = Ar6kMpRestartAP;
MApChars.ReturnNetBufferListsHandler = Ar6kMpReturnNetBufferListsAP;
MApChars.SendNetBufferListsHandler = Ar6kMpSendNetBufferListsAP;
MApChars.SetOptionsHandler = Ar6kMpSetOptionsAP;
MApChars.ShutdownHandlerEx = Ar6kMpAdapterShutdownAP;
MApChars.UnloadHandler = DriverUnloadAP;

MApChars.MajorDriverVersion = ATH_MAJOR_DRIVER_VERSION;
MApChars.MinorDriverVersion = ATH_MINOR_DRIVER_VERSION;

MApChars.Flags = NDIS_INTERMEDIATE_DRIVER;

Status = NdisMRegisterMiniportDriver(
pDriverObject,
RegistryPath,
GlobalDriverContextAP,
&MApChars,
&GlobalDriverHandleAP
);

The first call succeeds. The second call fails with NDIS_STATUS_RESOURCES.

Is there anything else apart from the above calls one needs to do for the API call to succeed?.

Open to any suggestions/responses.

Regards,
Balaji.

There are only 2 ways that NdisMRegisterMiniportDriver can fail with NDIS_STATUS_RESOURCES.

The first is kind of silly, and should be easy to rule out. NDIS calls your SetOptionsHandler within the context of NdisMRegisterMiniportDriver. If your SetOptionsHandler returns any failure code, then NdisMRegisterMiniportDriver will return that same code back to you. So set a breakpoint on your SetOptionsHandaler (looks like Ar6kMpSetOptionsAP) and make sure it’s not returning any error code.

The other (and much more likely) way that NdisMRegisterMiniportDriver can fail with NDIS_STATUS_RESOURCES is when NDIS tries to allocate a driver object extension on your DRIVER_OBJECT block. Just before the call to NdisMRegisterMiniportDriver, set a breakpoint on nt!IoAllocateDriverObjectExtension. Check what that function returns (on x86/amd64, it’s in the @eax register).

If it’s STATUS_OBJECT_NAME_COLLISION, then NDIS has already been registered on that driver object. The only time you’re allowed to register twice is if you have a single driver object that hosts IM virtual miniports and physical miniports. In that case, one call to NdisMRegisterMiniportDriver must have the NDIS_INTERMEDIATE_DRIVER flag set, and the other call must not have the NDIS_INTERMEDIATE_DRIVER flag set. (Double-check that NDIS_MINIPORT_DRIVER_CHARACTERISTICS::Flags definitely has 0x1 bit set in it.)

One other thing - it looks like your code now has a bug in the failure path here, probably due to you trying to reorder the registrations:

Status = NdisMRegisterMiniportDriver(
pDriverObject,
RegistryPath,
GlobalDriverContext,
&MChars,
&GlobalDriverHandle
);
if ( Status != NDIS_STATUS_SUCCESS )
{
NdisMDeregisterMiniportDriver(GlobalDriverHandle);
}