Deep Clone injection (Outbound network) doesn't work

Im hooking FWPM_LAYER_OUTBOUND_IPPACKET_V4, and the filter is empty there, so I should capture every single packet going outside. The problem Deep Cloning and injection WITHOUT Modification doesn’t work for me, I get invoked in the completion function and things seems ok, also I have registered a callout at FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD Layer, just to see if my injected packets are getting discarded for any reason, but nothing shows up in there .

(Am I looking at the correct discard layer ? )

What I get is any browsing or any network activity stops, like the packets are not even making it through .

void
TLInspectOutboundNetworkClassify(
In const FWPS_INCOMING_VALUES* inFixedValues,
In const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
Inout_opt void* layerData,
In const FWPS_FILTER* filter,
In UINT64 flowContext,
Inout FWPS_CLASSIFY_OUT* classifyOut
)
{
FWPS_PACKET_INJECTION_STATE packetState;

packetState = FwpsQueryPacketInjectionState(
gNetworkInjectionHandle,
layerData,
NULL
);

if ((packetState == FWPS_PACKET_INJECTED_BY_SELF) ||
(packetState == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF))
{
classifyOut->actionType = FWP_ACTION_PERMIT;
if (filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT)
{
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
}
return;
}

classifyOut->actionType = FWP_ACTION_BLOCK;
classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;

//classifyOut->actionType = FWP_ACTION_PERMIT;

PNET_BUFFER_LIST pClonedNBL = NULL, pOrgNBL = layerData;

NTSTATUS status = STATUS_SUCCESS;

status = FwpsAllocateCloneNetBufferList(
pOrgNBL,
NULL,
NULL,
0,
&pClonedNBL
);

if (!NT_SUCCESS(status))
{
if (pClonedNBL != NULL)
{
FwpsFreeCloneNetBufferList(pClonedNBL, 0);
}
return;
}

PNET_BUFFER_LIST pNewNbl = NULL;
PNET_BUFFER pNetBuffer = NULL;

const UINT32 BUFFER_SIZE = 2048;
for (pNetBuffer = NET_BUFFER_LIST_FIRST_NB(pClonedNBL);
pNetBuffer != NULL;
pNetBuffer = NET_BUFFER_NEXT_NB(pNetBuffer))
{
BYTE* pBuffer = 0;

HLPR_NEW_ARRAY(pBuffer,BYTE,BUFFER_SIZE,‘TAG5’);

if (pBuffer == 0) continue;

PVOID pContiguousData = 0;
PVOID pBuffer_IPHEADER = NULL;
PVOID pBuffer_TRANSPORTHEADER = NULL;

pBuffer_IPHEADER = ExAllocatePoolWithTag(NonPagedPool, 400, ‘TAG1’);
pBuffer_TRANSPORTHEADER = ExAllocatePoolWithTag(NonPagedPool, 400, ‘TAG2’);

PVOID pBuffer_PAYLOAD = ExAllocatePoolWithTag(NonPagedPool, 1500, ‘TAG3’);
UINT32 ip = 0, transport = 0;

///////////////////////////////////////////
//////////// IP HEADER ////////////////////
if (pNetBuffer != NULL)
{
pContiguousData = NdisGetDataBuffer(pNetBuffer,
inMetaValues->ipHeaderSize,
pBuffer,
1,
0);

if (pContiguousData == NULL)
{
status = STATUS_NO_MEMORY;
return;
}

if (pContiguousData != NULL)
RtlCopyMemory(pBuffer_IPHEADER, pContiguousData, inMetaValues->ipHeaderSize);

NdisAdvanceNetBufferDataStart(pNetBuffer, inMetaValues->ipHeaderSize, 0, NULL);
ip = inMetaValues->ipHeaderSize;
pContiguousData = NULL;

}
///////////////////////////////////////////
//////////// TRANSPORT HEADER /////////////
if (pNetBuffer != NULL)
{
pContiguousData = NdisGetDataBuffer(pNetBuffer,
inMetaValues->transportHeaderSize,
pBuffer,
1,
0);

if (pContiguousData != NULL)
RtlCopyMemory(pBuffer_TRANSPORTHEADER, pContiguousData, inMetaValues->transportHeaderSize);

NdisAdvanceNetBufferDataStart(pNetBuffer, inMetaValues->transportHeaderSize, FALSE, NULL);

transport = inMetaValues->transportHeaderSize;
pContiguousData = NULL;
}
///////////////////////////////////////////
//////////// PAYLOAD// ////////////////////
if (pNetBuffer != NULL)
{
pContiguousData = NdisGetDataBuffer(pNetBuffer,
NET_BUFFER_DATA_LENGTH(pNetBuffer),
pBuffer,
1,
0);

if (pContiguousData != NULL)
RtlCopyMemory(pBuffer_PAYLOAD, pContiguousData, NET_BUFFER_DATA_LENGTH(pNetBuffer));

pContiguousData = NULL;
}
PMDL p1 = NULL, p2 = NULL, p3 = NULL;
p1 = IoAllocateMdl(pBuffer_IPHEADER, inMetaValues->ipHeaderSize, FALSE, FALSE, NULL);
if(p1 != NULL) MmBuildMdlForNonPagedPool(p1);

inMetaValues->ipHeaderSize;
p2 = IoAllocateMdl(pBuffer_TRANSPORTHEADER, inMetaValues->transportHeaderSize, FALSE, FALSE, NULL);
if (p2 != NULL) MmBuildMdlForNonPagedPool(p1);

inMetaValues->transportHeaderSize;
p3 = IoAllocateMdl(pBuffer_PAYLOAD, NET_BUFFER_DATA_LENGTH(pNetBuffer), FALSE, FALSE, NULL);
if (p3 != NULL) MmBuildMdlForNonPagedPool(p1);

p1->Next = p2;
p2->Next = p3;

if ( p1 == NULL || p2 == NULL || p3 == NULL)
{
status = STATUS_NO_MEMORY;
return;
}

status = FwpsAllocateNetBufferAndNetBufferList(g_pNDISPoolData->nblPoolHandle, 0, 0, p1, 0,
NET_BUFFER_DATA_LENGTH(pNetBuffer) + inMetaValues->transportHeaderSize + inMetaValues->ipHeaderSize, &pNewNbl);
if (!NT_SUCCESS(status))
return;

if (p1 != NULL) IoFreeMdl(p1);
if (p2 != NULL) IoFreeMdl(p2);
if (p3 != NULL) IoFreeMdl(p3);

HLPR_DELETE_ARRAY(pBuffer, ‘TAG5’);
ExFreePoolWithTag(pBuffer_IPHEADER, ‘TAG1’);
ExFreePoolWithTag(pBuffer_TRANSPORTHEADER, ‘TAG2’);
ExFreePoolWithTag(pBuffer_PAYLOAD, ‘TAG3’);

if (pNetBuffer != NULL)
NdisRetreatNetBufferDataStart(pNetBuffer, transport + ip, FALSE, NULL);

}

status = FwpsInjectNetworkSendAsync0(
gNetworkInjectionHandle,
NULL,
0,
UNSPECIFIED_COMPARTMENT_ID,//inMetaValues->compartmentId, //
pNewNbl,
TLInspectNetworkInjectComplete,
NULL
);

if (pClonedNBL != NULL)
{
FwpsFreeCloneNetBufferList(pClonedNBL, 0);
}

return;
}