/*++

    Copyright (c) Microsoft Corporation.  All rights reserved.

Rule Name:

    NdisAllocateNetBufferList_InitFail

Domain:

    ndis

Rule ID:

    Not Applicable

Description:

    This rule checks that NdisAllocateNetBufferAndNetBufferList and NdisFreeNetBufferList are called 
    in alternate order. The ultimate goal is to make sure all NetBufferAndNetBufferLists are freed
    when the initialization functions fails.

    The rule uses three different states. state changes when a NetBuffer is allocated or freed.
    If a NetBufferAndNetBufferList is still allocated when the Initialization functions fails. 
    
    Related Rule:

Help Link:

    https://go.microsoft.com/fwlink/?LinkId=507476

--*/


#include "slic_base.h"

state{
   enum {initial, allocated, free} s = initial;
}
watch NdisAllocateNetBufferAndNetBufferList.exit.$return;

NdisAllocateNetBufferAndNetBufferList.exit[guard $return]
{  
    if ($return != 0)
    {
        s = allocated;
    }
}

NdisFreeNetBufferList.exit[guard $1]
{
    if ( s == free)
    {
        abort "Freeing a NetBufferAndNetBufferList that was not allocated.";
    }
  
    s = free;
}

[fun_MINIPORT_INITIALIZE,
fun_FILTER_ATTACH,
fun_PROTOCOL_BIND_ADAPTER_EX].exit
{
    if (($return == NDIS_STATUS_FAILURE || $return == NDIS_STATUS_RESOURCES) && (s==allocated))
    {
        abort "$fname is failing but the driver has a NetBufferAndNetBufferList that is still allocated.";
    }
}
