/*++

    Copyright (c) Microsoft Corporation.  All rights reserved.

Rule Name:

    ReqCompletionRoutine

Domain:

    wdf

Rule ID:

    Not Applicable

Description:

    Checks that a completion routine is set before a request is sent to an IOTarget.
        
    If a request is not sent synchronously or sent as send and forget, the driver
    should set a completion routine so that it can be informed once the request
    is completed by the IOTarget.
    
    Rule diagnostics:
    If a request is not sent synchronously or sent as send and forget, the driver
    should set a completion routine so that it can be informed once the request
    is completed by the IOTarget.


Help Link:

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

--*/




#include "slic_base.h"

state 
{
	enum {SET, NOTSET} completionRoutine = NOTSET;
}with guard(sdv_main,hrequest)

sdv_WdfRequestSetCompletionRoutine.entry[guard $1]
{
	if ($2==NULL)
	{
		completionRoutine=NOTSET;
	}
	else
	{
		completionRoutine=SET;	
	}
}

sdv_WdfRequestSend.entry[guard $1]
{	
	if (completionRoutine==NOTSET)
	{
		if ($3==NULL)
		{
			abort "Request sent without setting a completion routine";
		}
		else if ($3->Flags!=8 )
		{
			if ( !( $3->Flags==2 ||
					$3->Flags==3 ||
					$3->Flags==6 ||
					$3->Flags==7)
				)
				{
					abort "Request sent without setting completion routine.";
				}
		}
	}
}

/*

WDF_REQUEST_SEND_OPTION_TIMEOUT = 0x0000001
WDF_REQUEST_SEND_OPTION_SYNCHRONOUS = 0x0000002
WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE = 0x0000004 
WDF_REQUEST_SEND_OPTION_SEND_AND_FORGET = 0x0000008

We are interested in Sync and Send&forget sends

Sync:          Send& Forget
0010		1000
0011		1001
0110		1010
0111		1011
1010		1100
1011		1101
1110		1110
1111		1111



Send and forget flag (0x8) cannot be set with any other flags. Feasible options:

Sync:          Send& Forget
0010		1000
0011
0110
0111

If the reqSend is either Sync or Send& Forget, no need for completion routine.
Therefore we want: options->Flags !=
 0010		=2        	
0011		=3
0110		=6
0111		=7
1000		=8

*/
