/*************************************************************
Driver's entry point
Parameters:
	as usual
Return value:
	SUCCESS or error code
*************************************************************/
NDIS_STATUS DriverEntry(PVOID DriverObject,PVOID RegistryPath)
{
	NDIS_STATUS status;
	NDIS_MINIPORT_CHARACTERISTICS chars;
	ParaNdis_DebugInitialize(DriverObject, RegistryPath);

	status = NDIS_STATUS_FAILURE;

	DEBUG_ENTRY(0);
	_LogOutString(0, __DATE__ " " __TIME__);

	NdisMInitializeWrapper(&DriverHandle,
						   DriverObject,
						   RegistryPath,
						   NULL
						   );

	if (DriverHandle)
	{
		NdisZeroMemory(&chars, sizeof(chars));
		//NDIS version of the miniport
		chars.MajorNdisVersion			= NDIS_MINIPORT_MAJOR_VERSION;
		chars.MinorNdisVersion			= NDIS_MINIPORT_MINOR_VERSION;
		//Init and destruction
		chars.InitializeHandler			= ParaNdis5_Initialize;
		chars.HaltHandler				= ParaNdis5_Halt;

		//Interrupt and DPC handling
		chars.HandleInterruptHandler	= ParaNdis5_HandleDPC;
		chars.ISRHandler				= ParaNdis5_MiniportISR;

		//Packet transfer - send path and notification on the send packet
		chars.SendPacketsHandler		= ParaNdis5_SendPackets;
		chars.ReturnPacketHandler		= ParaNdis5_ReturnPacket;

		//OID set\get
		chars.SetInformationHandler		= ParaNdis5_SetOID;
		chars.QueryInformationHandler	= ParaNdis5_QueryOID;

		//Reset
		chars.ResetHandler				= ParaNdis5_Reset;
		chars.CheckForHangHandler		= ParaNdis5_CheckForHang; //optional

#ifdef NDIS51_MINIPORT
		chars.CancelSendPacketsHandler	= ParaNdis5_CancelSendPackets;
		chars.PnPEventNotifyHandler		= ParaNdis5_PnPEventNotify;
		chars.AdapterShutdownHandler	= ParaNdis5_Shutdown;
#endif
		status = NdisMRegisterMiniport(
			DriverHandle,
			&chars,
			sizeof(chars));
	}

	if (status == NDIS_STATUS_SUCCESS)
	{
		NdisMRegisterUnloadHandler(DriverHandle, ParaVirtualNICUnload);
	}
	else if (DriverHandle)
	{
		DPrintf(0, ("NdisMRegisterMiniport failed"));
		NdisTerminateWrapper(DriverHandle, NULL);
	}
	else
	{
		DPrintf(0, ("NdisMInitializeWrapper failed"));
	}

	DEBUG_EXIT_STATUS(status ? 0 : 4, status);
	return status;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath)
{
    NDIS_STATUS                             status = NDIS_STATUS_FAILURE;
    NDIS_MINIPORT_DRIVER_CHARACTERISTICS    chars;
#ifdef DEBUG_TIMING
    LARGE_INTEGER TickCount;
    LARGE_INTEGER SysTime;
#endif DEBUG_TIMING

    ParaNdis_DebugInitialize();

    DEBUG_ENTRY(0);
    DPrintf(0, (__DATE__ " " __TIME__ "built %d.%d\n", NDIS_MINIPORT_MAJOR_VERSION, NDIS_MINIPORT_MINOR_VERSION));
#ifdef DEBUG_TIMING
    KeQueryTickCount(&TickCount);
    NdisGetCurrentSystemTime(&SysTime);
    DPrintf(0, ("\n%s>> CPU #%d, perf-counter %I64d, tick count %I64d, NDIS_sys_time %I64d\n", __FUNCTION__, KeGetCurrentProcessorNumber(), KeQueryPerformanceCounter(NULL).QuadPart,TickCount.QuadPart, SysTime.QuadPart));
#endif

    NdisZeroMemory(&chars, sizeof(chars));

    chars.Header.Type      = NDIS_OBJECT_TYPE_MINIPORT_DRIVER_CHARACTERISTICS;
    chars.Header.Revision  = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
    chars.Header.Size      = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_1;
    chars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
    chars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
    /* stupid thing, they are at least short */
    chars.MajorDriverVersion = (UCHAR)(PARANDIS_MAJOR_DRIVER_VERSION & 0xFF);
    chars.MinorDriverVersion = (UCHAR)(PARANDIS_MINOR_DRIVER_VERSION & 0xFF);

    // possible value for regular miniport NDIS_WDM_DRIVER - for USB or 1394
    // chars.Flags  = 0;

    chars.InitializeHandlerEx           = ParaNdis6_Initialize;
    chars.HaltHandlerEx                 = ParaNdis6_Halt;
    chars.UnloadHandler                 = ParaNdis6_Unload;
    chars.PauseHandler                  = ParaNdis6_Pause;
    chars.RestartHandler                = ParaNdis6_Restart;
    chars.OidRequestHandler             = ParaNdis6_OidRequest;
    chars.CancelOidRequestHandler       = ParaNdis6_OidCancelRequest;
    chars.SendNetBufferListsHandler     = ParaNdis6_SendNetBufferLists;
    chars.CancelSendHandler             = ParaNdis6_CancelSendNetBufferLists;
    chars.ReturnNetBufferListsHandler   = ParaNdis6_ReturnNetBufferLists;
    chars.CheckForHangHandlerEx         = ParaNdis6_CheckForHang;
    chars.ResetHandlerEx                = ParaNdis6_Reset;
    chars.ShutdownHandlerEx             = ParaNdis6_AdapterShutdown;
    chars.DevicePnPEventNotifyHandler   = ParaNdis6_DevicePnPEvent;
    chars.SetOptionsHandler             = ParaNdis6_SetOptions;

#if NDIS_SUPPORT_NDIS61
    chars.Header.Revision  = NDIS_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
    chars.Header.Size      = NDIS_SIZEOF_MINIPORT_DRIVER_CHARACTERISTICS_REVISION_2;
    chars.DirectOidRequestHandler       = ParaNdis6x_DirectOidRequest;
    chars.CancelDirectOidRequestHandler = ParaNdis6x_CancelDirectOidRequest;
#endif

    status = NdisMRegisterMiniportDriver(
            pDriverObject,
            pRegistryPath,
            NULL,
            &chars,
            &DriverHandle);

    if (status == NDIS_STATUS_SUCCESS)
    {
        RetrieveDriverConfiguration();
    }
    DEBUG_EXIT_STATUS(status ? 0 : 4, status);
    return status;
}