Uninstalling a Provider
The following sample code demonstrates the process required to remove a provider installation.
// Illustrates common tasks a provider might perform during uninstall: deleting
// a persistent provider and sublayer.
#include <windows.h>
#include <fwpmu.h>
#include <stdio.h>
#pragma comment(lib, "fwpuclnt.lib")
#define EXIT_ON_ERROR(fnName) \
if (result != ERROR_SUCCESS) \
{ \
printf(#fnName " = 0x%08X\n", result); \
goto CLEANUP; \
}
#define SESSION_NAME L"SDK Examples"
// 5fb216a8-e2e8-4024-b853-391a4168641e
const GUID PROVIDER_KEY =
{
0x5fb216a8,
0xe2e8,
0x4024,
{ 0xb8, 0x53, 0x39, 0x1a, 0x41, 0x68, 0x64, 0x1e }
};
DWORD Uninstall(
__in const GUID* providerKey,
__in const GUID* subLayerKey
)
{
DWORD result = ERROR_SUCCESS;
HANDLE engine = NULL;
FWPM_SESSION0 session;
memset(&session, 0, sizeof(session));
// The session name isn't required but may be useful for diagnostics.
session.displayData.name = SESSION_NAME;
// Set an infinite wait timeout, so we don't have to handle FWP_E_TIMEOUT
// errors while waiting to acquire the transaction lock.
session.txnWaitTimeoutInMSec = INFINITE;
// The authentication service should always be RPC_C_AUTHN_DEFAULT.
result = FwpmEngineOpen0(
NULL,
RPC_C_AUTHN_DEFAULT,
NULL,
&session,
&engine
);
EXIT_ON_ERROR(FwpmEngineOpen0);
// We delete the provider and sublayer from within a single transaction, so
// that we always leave the system in a consistent state even in error
// paths.
result = FwpmTransactionBegin0(engine, 0);
EXIT_ON_ERROR(FwpmTransactionBegin0);
// We have to delete the sublayer first since it references the provider. If
// we tried to delete the provider first, it would fail with FWP_E_IN_USE.
result = FwpmSubLayerDeleteByKey0(engine, subLayerKey);
if (result != FWP_E_SUBLAYER_NOT_FOUND)
{
// Ignore FWP_E_SUBLAYER_NOT_FOUND. This allows uninstall to succeed even
// if the current configuration is broken.
EXIT_ON_ERROR(FwpmSubLayerDeleteByKey0);
}
result = FwpmProviderDeleteByKey0(engine, providerKey);
if (result != FWP_E_PROVIDER_NOT_FOUND)
{
EXIT_ON_ERROR(FwpmProviderDeleteByKey0);
}
// Once all the deletes have succeeded, we commit the transaction to
// atomically delete all the objects.
result = FwpmTransactionCommit0(engine);
EXIT_ON_ERROR(FwpmTransactionCommit0);
CLEANUP:
// FwpmEngineClose0 accepts null engine handles, so we needn't precheck for
// null. Also, when closing an engine handle, any transactions still in
// progress are automatically aborted, so we needn't explicitly abort the
// transaction in error paths.
FwpmEngineClose0(engine);
return result;
}