diff --git a/include/kf/FltCommunicationPort.h b/include/kf/FltCommunicationPort.h index 793e27e..ad2f1f8 100644 --- a/include/kf/FltCommunicationPort.h +++ b/include/kf/FltCommunicationPort.h @@ -2,6 +2,7 @@ #include "ObjectAttributes.h" #include "ScopeExit.h" #include "VariableSizeStruct.h" +#include "IWinApi.h" namespace kf { @@ -69,7 +70,7 @@ namespace kf class FltCommunicationPort { public: - FltCommunicationPort() : m_filter(), m_port() + FltCommunicationPort(IWinApi& api) : m_api(api), m_filter(), m_port() { } @@ -85,26 +86,26 @@ namespace kf m_filter = filter; PSECURITY_DESCRIPTOR securityDescriptor = nullptr; - NTSTATUS status = ::FltBuildDefaultSecurityDescriptor(&securityDescriptor, FLT_PORT_ALL_ACCESS); + NTSTATUS status = m_api.FltBuildDefaultSecurityDescriptor(&securityDescriptor, FLT_PORT_ALL_ACCESS); if (!NT_SUCCESS(status)) { return status; } - SCOPE_EXIT{ ::FltFreeSecurityDescriptor(securityDescriptor); }; + SCOPE_EXIT{ m_api.FltFreeSecurityDescriptor(securityDescriptor); }; VariableSizeStruct lowIntegrityAce; VariableSizeStruct sacl; if (allowNonAdmins) { - status = RtlSetDaclSecurityDescriptor(securityDescriptor, true, nullptr, false); + status = m_api.RtlSetDaclSecurityDescriptor(securityDescriptor, true, nullptr, false); if (!NT_SUCCESS(status)) { return status; } - const auto lowMandatorySidLength = RtlLengthSid(SeExports->SeLowMandatorySid); + const auto lowMandatorySidLength = m_api.RtlLengthSid(SeExports->SeLowMandatorySid); status = lowIntegrityAce.emplace(FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart) + lowMandatorySidLength); if (!NT_SUCCESS(status)) { @@ -114,7 +115,7 @@ namespace kf lowIntegrityAce->Header.AceType = SYSTEM_MANDATORY_LABEL_ACE_TYPE; lowIntegrityAce->Header.AceSize = static_cast(FIELD_OFFSET(SYSTEM_MANDATORY_LABEL_ACE, SidStart) + lowMandatorySidLength); lowIntegrityAce->Mask = 0; - status = RtlCopySid(lowMandatorySidLength, &lowIntegrityAce->SidStart, SeExports->SeLowMandatorySid); + status = m_api.RtlCopySid(lowMandatorySidLength, &lowIntegrityAce->SidStart, SeExports->SeLowMandatorySid); if (!NT_SUCCESS(status)) { return status; @@ -126,19 +127,19 @@ namespace kf { return status; } - status = RtlCreateAcl(sacl.get(), saclSize, ACL_REVISION); + status = m_api.RtlCreateAcl(sacl.get(), saclSize, ACL_REVISION); if (!NT_SUCCESS(status)) { return status; } - status = RtlAddAce(sacl.get(), ACL_REVISION, 0, static_cast(lowIntegrityAce.get()), lowIntegrityAce->Header.AceSize); + status = m_api.RtlAddAce(sacl.get(), ACL_REVISION, 0, static_cast(lowIntegrityAce.get()), lowIntegrityAce->Header.AceSize); if (!NT_SUCCESS(status)) { return status; } - status = RtlSetSaclSecurityDescriptor(securityDescriptor, true, sacl.get(), false); + status = m_api.RtlSetSaclSecurityDescriptor(securityDescriptor, true, sacl.get(), false); if (!NT_SUCCESS(status)) { return status; @@ -147,14 +148,14 @@ namespace kf ObjectAttributes oa(&name, securityDescriptor); - return ::FltCreateCommunicationPort(filter, &m_port, &oa, this, connectNotify, disconnectNotify, messageNotify, maxConnections); + return m_api.FltCreateCommunicationPort(filter, &m_port, &oa, this, connectNotify, disconnectNotify, messageNotify, maxConnections); } void close() { if (m_port) { - ::FltCloseCommunicationPort(m_port); + m_api.FltCloseCommunicationPort(m_port); m_port = nullptr; } @@ -175,7 +176,7 @@ namespace kf { ASSERT(serverPortCookie); auto self = static_cast(serverPortCookie); - return Handler::onConnect(self->m_filter, clientPort, connectionContext, connectionContextLength, reinterpret_cast(connectionCookie)); + return Handler::onConnect(self->m_filter, clientPort, connectionContext, connectionContextLength, reinterpret_cast(connectionCookie), self->m_api); } static VOID FLTAPI disconnectNotify( @@ -214,15 +215,15 @@ namespace kf { if (inputBufferLength) { - inputMdl = IoAllocateMdl(inputBuffer, inputBufferLength, false, false, nullptr); + inputMdl = handler->m_api.IoAllocateMdl(inputBuffer, inputBufferLength, false, false, nullptr); if (!inputMdl) { return STATUS_INSUFFICIENT_RESOURCES; } - MmProbeAndLockPages(inputMdl, KernelMode, IoReadAccess); + handler->m_api.MmProbeAndLockPages(inputMdl, KernelMode, IoReadAccess); - inputBuffer = MmGetSystemAddressForMdlSafe(inputMdl, NormalPagePriority | MdlMappingNoExecute | MdlMappingNoWrite); + inputBuffer = handler->m_api.MmGetSystemAddressForMdlSafe(inputMdl, NormalPagePriority | MdlMappingNoExecute | MdlMappingNoWrite); if (!inputBuffer) { return STATUS_INSUFFICIENT_RESOURCES; @@ -231,15 +232,15 @@ namespace kf if (outputBufferLength) { - outputMdl = IoAllocateMdl(outputBuffer, outputBufferLength, false, false, nullptr); + outputMdl = handler->m_api.IoAllocateMdl(outputBuffer, outputBufferLength, false, false, nullptr); if (!outputMdl) { return STATUS_INSUFFICIENT_RESOURCES; } - MmProbeAndLockPages(outputMdl, KernelMode, IoWriteAccess); + handler->m_api.MmProbeAndLockPages(outputMdl, KernelMode, IoWriteAccess); - outputBuffer = MmGetSystemAddressForMdlSafe(outputMdl, NormalPagePriority | MdlMappingNoExecute); + outputBuffer = handler->m_api.MmGetSystemAddressForMdlSafe(outputMdl, NormalPagePriority | MdlMappingNoExecute); if (!outputBuffer) { return STATUS_INSUFFICIENT_RESOURCES; @@ -258,16 +259,16 @@ namespace kf // Cleanup // - auto freeMdl = [](PMDL& mdl) + auto freeMdl = [&handler](PMDL& mdl) { if (mdl) { if (FlagOn(mdl->MdlFlags, MDL_PAGES_LOCKED)) { - MmUnlockPages(mdl); + handler->m_api.MmUnlockPages(mdl); } - IoFreeMdl(mdl); + handler->m_api.IoFreeMdl(mdl); mdl = nullptr; } }; @@ -281,5 +282,6 @@ namespace kf private: PFLT_FILTER m_filter; PFLT_PORT m_port; + IWinApi& m_api; }; } // namespace diff --git a/include/kf/IWinApi.h b/include/kf/IWinApi.h new file mode 100644 index 0000000..26bc0e8 --- /dev/null +++ b/include/kf/IWinApi.h @@ -0,0 +1,50 @@ +#pragma once + +namespace kf +{ + //////////////////////////////////////////////////// + // Interface for Windows API calls + class IWinApi + { + public: + virtual NTSTATUS FltBuildDefaultSecurityDescriptor(PSECURITY_DESCRIPTOR* sd, ACCESS_MASK access) = 0; + + virtual VOID FltFreeSecurityDescriptor(PSECURITY_DESCRIPTOR sd) = 0; + + virtual NTSTATUS FltCreateCommunicationPort( + PFLT_FILTER filter, + PFLT_PORT* serverPort, + POBJECT_ATTRIBUTES oa, + PVOID serverPortCookie, + PFLT_CONNECT_NOTIFY connectNotify, + PFLT_DISCONNECT_NOTIFY disconnectNotify, + PFLT_MESSAGE_NOTIFY messageNotify, + LONG maxConnections) = 0; + + virtual VOID FltCloseCommunicationPort(PFLT_PORT port) = 0; + + virtual VOID FltCloseClientPort(PFLT_FILTER filter, PFLT_PORT* port) = 0; + + virtual NTSTATUS RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR sd, BOOLEAN daclPresent, PACL dacl, BOOLEAN daclDefaulted) = 0; + + virtual NTSTATUS RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR sd, BOOLEAN saclPresent, PACL sacl, BOOLEAN saclDefaulted) = 0; + + virtual ULONG RtlLengthSid(PSID sid) = 0; + + virtual NTSTATUS RtlCopySid(ULONG len, PSID dest, PSID src) = 0; + + virtual NTSTATUS RtlCreateAcl(PACL acl, ULONG size, ULONG rev) = 0; + + virtual NTSTATUS RtlAddAce(PACL acl, ULONG rev, ULONG start, PVOID ace, ULONG aceSize) = 0; + + virtual PMDL IoAllocateMdl(PVOID va, ULONG len, BOOLEAN secondary, BOOLEAN chargeQuota, PIRP irp) = 0; + + virtual VOID IoFreeMdl(PMDL mdl) = 0; + + virtual VOID MmProbeAndLockPages(PMDL mdl, KPROCESSOR_MODE mode, LOCK_OPERATION op) = 0; + + virtual VOID MmUnlockPages(PMDL mdl) = 0; + + virtual PVOID MmGetSystemAddressForMdlSafe(PMDL mdl, ULONG priority) = 0; + }; +} \ No newline at end of file diff --git a/include/kf/WinApi.h b/include/kf/WinApi.h new file mode 100644 index 0000000..e674181 --- /dev/null +++ b/include/kf/WinApi.h @@ -0,0 +1,98 @@ +#pragma once +#include "IWinApi.h" + +namespace kf +{ + ////////////////////////////////////////////////////////////////////////// + // Wrapper for Windows API calls to allow mocking in unit tests + class WinApi : public IWinApi + { + public: + NTSTATUS FltBuildDefaultSecurityDescriptor(PSECURITY_DESCRIPTOR* sd, ACCESS_MASK access) + { + return ::FltBuildDefaultSecurityDescriptor(sd, access); + } + + VOID FltFreeSecurityDescriptor(PSECURITY_DESCRIPTOR sd) + { + ::FltFreeSecurityDescriptor(sd); + } + NTSTATUS FltCreateCommunicationPort( + PFLT_FILTER filter, + PFLT_PORT* serverPort, + POBJECT_ATTRIBUTES oa, + PVOID serverPortCookie, + PFLT_CONNECT_NOTIFY connectNotify, + PFLT_DISCONNECT_NOTIFY disconnectNotify, + PFLT_MESSAGE_NOTIFY messageNotify, + LONG maxConnections) + { + return ::FltCreateCommunicationPort(filter, serverPort, oa, serverPortCookie, connectNotify, disconnectNotify, messageNotify, maxConnections); + } + + VOID FltCloseCommunicationPort(PFLT_PORT port) + { + ::FltCloseCommunicationPort(port); + } + + VOID FltCloseClientPort(PFLT_FILTER filter, PFLT_PORT* port) + { + ::FltCloseClientPort(filter, port); + } + + NTSTATUS RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR sd, BOOLEAN daclPresent, PACL dacl, BOOLEAN daclDefaulted) + { + return ::RtlSetDaclSecurityDescriptor(sd, daclPresent, dacl, daclDefaulted); + } + + NTSTATUS RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR sd, BOOLEAN saclPresent, PACL sacl, BOOLEAN saclDefaulted) + { + return ::RtlSetSaclSecurityDescriptor(sd, saclPresent, sacl, saclDefaulted); + } + + ULONG RtlLengthSid(PSID sid) + { + return ::RtlLengthSid(sid); + } + + NTSTATUS RtlCopySid(ULONG len, PSID dest, PSID src) + { + return ::RtlCopySid(len, dest, src); + } + + NTSTATUS RtlCreateAcl(PACL acl, ULONG size, ULONG rev) + { + return ::RtlCreateAcl(acl, size, rev); + } + + NTSTATUS RtlAddAce(PACL acl, ULONG rev, ULONG start, PVOID ace, ULONG aceSize) + { + return ::RtlAddAce(acl, rev, start, ace, aceSize); + } + + PMDL IoAllocateMdl(PVOID va, ULONG len, BOOLEAN secondary, BOOLEAN chargeQuota, PIRP irp) + { + return ::IoAllocateMdl(va, len, secondary, chargeQuota, irp); + } + + VOID IoFreeMdl(PMDL mdl) + { + ::IoFreeMdl(mdl); + } + + VOID MmProbeAndLockPages(PMDL mdl, KPROCESSOR_MODE mode, LOCK_OPERATION op) + { + ::MmProbeAndLockPages(mdl, mode, op); + } + + VOID MmUnlockPages(PMDL mdl) + { + ::MmUnlockPages(mdl); + } + + PVOID MmGetSystemAddressForMdlSafe(PMDL mdl, ULONG priority) + { + return ::MmGetSystemAddressForMdlSafe(mdl, priority); + } + }; +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6dccd52..42bcc16 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -59,6 +59,8 @@ wdk_add_driver(kf-test WINVER NTDDI_WIN10 STL AutoSpinLockTest.cpp EResourceSharedLockTest.cpp RecursiveAutoSpinLockTest.cpp + FltCommunicationPortTest.cpp + WinApiMock.h ) target_link_libraries(kf-test kf::kf kmtest::kmtest) diff --git a/test/FltCommunicationPortTest.cpp b/test/FltCommunicationPortTest.cpp new file mode 100644 index 0000000..40106af --- /dev/null +++ b/test/FltCommunicationPortTest.cpp @@ -0,0 +1,185 @@ +#include "pch.h" +#include "WinApiMock.h" +#include + +namespace +{ + class SampleHandler + { + public: + static NTSTATUS onConnect( + PFLT_FILTER filter, + PFLT_PORT clientPort, + _In_reads_bytes_opt_(connectionContextLength) PVOID connectionContext, + ULONG connectionContextLength, + _Outptr_ SampleHandler** handler, + _In_ kf::IWinApi& api) + { + UNREFERENCED_PARAMETER(connectionContext); + UNREFERENCED_PARAMETER(connectionContextLength); + *handler = new(PagedPool) SampleHandler(filter, clientPort, api); + + return *handler ? STATUS_SUCCESS : STATUS_INSUFF_SERVER_RESOURCES; + } + + void onDisconnect() + { + delete this; + } + + NTSTATUS onMessage(_In_reads_bytes_opt_(inputBufferLength) PVOID inputBuffer, + _In_ ULONG inputBufferLength, + _Out_writes_bytes_to_opt_(outputBufferLength, *returnOutputBufferLength) PVOID outputBuffer, + _In_ ULONG outputBufferLength, + _Out_ PULONG returnOutputBufferLength) + { + UNREFERENCED_PARAMETER(inputBuffer); + UNREFERENCED_PARAMETER(inputBufferLength); + UNREFERENCED_PARAMETER(outputBuffer); + UNREFERENCED_PARAMETER(outputBufferLength); + *returnOutputBufferLength = 0; + + return STATUS_SUCCESS; + } + + private: + SampleHandler(PFLT_FILTER filter, PFLT_PORT clientPort, kf::IWinApi& api) : m_filter(filter), m_clientPort(clientPort), m_api(api) + { + } + + ~SampleHandler() + { + m_api.FltCloseClientPort(m_filter, &m_clientPort); + } + + public: + kf::IWinApi& m_api; + + private: + PFLT_FILTER m_filter; + PFLT_PORT m_clientPort; + }; +} + +SCENARIO("FltCommunicationPort creation and cleanup with mocks") +{ + GIVEN("WinApiMock and FltCommunicationPort instance") + { + WinApiMock apiMock; + kf::FltCommunicationPort port(apiMock); + + UNICODE_STRING name{}; + PFLT_FILTER filter = reinterpret_cast(1); + + WHEN("create() is called with valid parameters") + { + NTSTATUS status = port.create(filter, name, 1); + + THEN("Port is created successful and cleanup frees descriptor") + { + REQUIRE_NT_SUCCESS(status); + } + } + + WHEN("create() fails due to FltBuildDefaultSecurityDescriptor") + { + apiMock.m_funcs.FltBuildDefaultSecurityDescriptor = [](PSECURITY_DESCRIPTOR*, ACCESS_MASK) { + return STATUS_INSUFFICIENT_RESOURCES; + }; + + NTSTATUS status = port.create(filter, name, 1); + + THEN("create() returns status of the failure") + { + REQUIRE(status == STATUS_INSUFFICIENT_RESOURCES); + } + } + + WHEN("create() fails due to FltCreateCommunicationPort") + { + apiMock.m_funcs.FltCreateCommunicationPort = + [](auto, PFLT_PORT* serverPort, auto, auto, auto, auto, auto, auto) { + *serverPort = nullptr; + return STATUS_INSUFF_SERVER_RESOURCES; + }; + + static bool freeCalled = false; + apiMock.m_funcs.FltFreeSecurityDescriptor = [](PSECURITY_DESCRIPTOR) { freeCalled = true; }; + + NTSTATUS status = port.create(filter, name, 1); + + THEN("create() returns status of the failure and frees the descriptor") + { + REQUIRE(status == STATUS_INSUFF_SERVER_RESOURCES); + REQUIRE(freeCalled); + } + } + + WHEN("create() called with allowNonAdmins triggers ACL/SACL setup and fails") + { + apiMock.m_funcs.RtlSetDaclSecurityDescriptor = [](auto, auto, auto, auto) { return STATUS_ACCESS_DENIED; }; + + NTSTATUS status = port.create(filter, name, 1, true); + + THEN("create() returns status error") + { + REQUIRE(status == STATUS_ACCESS_DENIED); + } + } + + WHEN("Closing twice does not crash") + { + port.create(filter, name, 1); + port.close(); + port.close(); + + THEN("no crash occurs") + { + } + } + + WHEN("close() is called without prior create") + { + port.close(); + + THEN("no crash occurs") + { + } + } + + WHEN("Creating port after it was closed") + { + REQUIRE_NT_SUCCESS(port.create(filter, name, 1)); + port.close(); + + NTSTATUS status2 = port.create(filter, name, 1); + THEN("Second create() succeeds after close()") + { + REQUIRE_NT_SUCCESS(status2); + } + } + } + + GIVEN("Successfully created FltCommunicationPort") + { + WinApiMock apiMock; + static bool freeCalled = false; + apiMock.m_funcs.FltCloseCommunicationPort = [](PFLT_PORT) { freeCalled = true; }; + + { + kf::FltCommunicationPort port(apiMock); + UNICODE_STRING name{}; + PFLT_FILTER filter = reinterpret_cast(1); + + REQUIRE_NT_SUCCESS(port.create(filter, name, 1)); + } + + WHEN("FltCreateCommunicationPort goes out of scope") + { + THEN("FltCreateCommunicationPort closes the port") + { + REQUIRE(freeCalled); + } + } + } +} diff --git a/test/WinApiMock.h b/test/WinApiMock.h new file mode 100644 index 0000000..f8dfb95 --- /dev/null +++ b/test/WinApiMock.h @@ -0,0 +1,155 @@ +#pragma once +#include + +struct WinApiMockFuncs +{ + NTSTATUS(*FltCreateCommunicationPort)( + PFLT_FILTER, PFLT_PORT* serverPort, POBJECT_ATTRIBUTES, PVOID, + PFLT_CONNECT_NOTIFY, PFLT_DISCONNECT_NOTIFY, PFLT_MESSAGE_NOTIFY, LONG) = + [](PFLT_FILTER, PFLT_PORT* serverPort, POBJECT_ATTRIBUTES, PVOID, + PFLT_CONNECT_NOTIFY, PFLT_DISCONNECT_NOTIFY, PFLT_MESSAGE_NOTIFY, LONG) + { + *serverPort = reinterpret_cast(1); + return STATUS_SUCCESS; + }; + + NTSTATUS(*FltBuildDefaultSecurityDescriptor)(PSECURITY_DESCRIPTOR*, ACCESS_MASK) = + [](PSECURITY_DESCRIPTOR*, ACCESS_MASK) + { + return STATUS_SUCCESS; + }; + + VOID(*FltFreeSecurityDescriptor)(PSECURITY_DESCRIPTOR) = [](PSECURITY_DESCRIPTOR) {}; + + VOID(*FltCloseCommunicationPort)(PFLT_PORT) = [](PFLT_PORT) {}; + + VOID(*FltCloseClientPort)(PFLT_FILTER, PFLT_PORT*) = [](PFLT_FILTER, PFLT_PORT*) {}; + + NTSTATUS(*RtlSetDaclSecurityDescriptor)(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN) = + [](PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN) { return STATUS_SUCCESS; }; + + NTSTATUS(*RtlSetSaclSecurityDescriptor)(PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN) = + [](PSECURITY_DESCRIPTOR, BOOLEAN, PACL, BOOLEAN) { return STATUS_SUCCESS; }; + + ULONG(*RtlLengthSid)(PSID) = [](PSID) { return static_cast(0); }; + + NTSTATUS(*RtlCopySid)(ULONG, PSID, PSID) = + [](ULONG, PSID, PSID) { return STATUS_SUCCESS; }; + + NTSTATUS(*RtlCreateAcl)(PACL, ULONG, ULONG) = + [](PACL, ULONG, ULONG) { return STATUS_SUCCESS; }; + + NTSTATUS(*RtlAddAce)(PACL, ULONG, ULONG, PVOID, ULONG) = + [](PACL, ULONG, ULONG, PVOID, ULONG) { return STATUS_SUCCESS; }; + + PMDL(*IoAllocateMdl)(PVOID, ULONG, BOOLEAN, BOOLEAN, PIRP) = + [](PVOID, ULONG, BOOLEAN, BOOLEAN, PIRP) { return reinterpret_cast(1); }; + + VOID(*IoFreeMdl)(PMDL) = + [](PMDL) {}; + + VOID(*MmProbeAndLockPages)(PMDL, KPROCESSOR_MODE, LOCK_OPERATION) = + [](PMDL, KPROCESSOR_MODE, LOCK_OPERATION) {}; + + VOID(*MmUnlockPages)(PMDL) = + [](PMDL) {}; + + PVOID(*MmGetSystemAddressForMdlSafe)(PMDL, ULONG) = + [](PMDL, ULONG) { return reinterpret_cast(1); }; +}; + + +class WinApiMock : public kf::IWinApi +{ +public: + NTSTATUS FltBuildDefaultSecurityDescriptor(PSECURITY_DESCRIPTOR* sd, ACCESS_MASK access) + { + return m_funcs.FltBuildDefaultSecurityDescriptor(sd, access); + } + + VOID FltFreeSecurityDescriptor(PSECURITY_DESCRIPTOR sd) + { + m_funcs.FltFreeSecurityDescriptor(sd); + } + + NTSTATUS FltCreateCommunicationPort( + PFLT_FILTER filter, + PFLT_PORT* serverPort, + POBJECT_ATTRIBUTES oa, + PVOID serverPortCookie, + PFLT_CONNECT_NOTIFY connectNotify, + PFLT_DISCONNECT_NOTIFY disconnectNotify, + PFLT_MESSAGE_NOTIFY messageNotify, + LONG maxConnections) + { + return m_funcs.FltCreateCommunicationPort(filter, serverPort, oa, serverPortCookie, connectNotify, disconnectNotify, messageNotify, maxConnections); + } + + VOID FltCloseCommunicationPort(PFLT_PORT port) + { + m_funcs.FltCloseCommunicationPort(port); + } + + VOID FltCloseClientPort(PFLT_FILTER filter, PFLT_PORT* port) + { + m_funcs.FltCloseClientPort(filter, port); + } + + NTSTATUS RtlSetDaclSecurityDescriptor(PSECURITY_DESCRIPTOR sd, BOOLEAN daclPresent, PACL dacl, BOOLEAN daclDefaulted) + { + return m_funcs.RtlSetDaclSecurityDescriptor(sd, daclPresent, dacl, daclDefaulted); + } + + NTSTATUS RtlSetSaclSecurityDescriptor(PSECURITY_DESCRIPTOR sd, BOOLEAN saclPresent, PACL sacl, BOOLEAN saclDefaulted) + { + return m_funcs.RtlSetSaclSecurityDescriptor(sd, saclPresent, sacl, saclDefaulted); + } + + ULONG RtlLengthSid(PSID sid) + { + return m_funcs.RtlLengthSid(sid); + } + + NTSTATUS RtlCopySid(ULONG len, PSID dest, PSID src) + { + return m_funcs.RtlCopySid(len, dest, src); + } + + NTSTATUS RtlCreateAcl(PACL acl, ULONG size, ULONG rev) + { + return m_funcs.RtlCreateAcl(acl, size, rev); + } + + NTSTATUS RtlAddAce(PACL acl, ULONG rev, ULONG start, PVOID ace, ULONG aceSize) + { + return m_funcs.RtlAddAce(acl, rev, start, ace, aceSize); + } + + PMDL IoAllocateMdl(PVOID va, ULONG len, BOOLEAN secondary, BOOLEAN chargeQuota, PIRP irp) + { + return m_funcs.IoAllocateMdl(va, len, secondary, chargeQuota, irp); + } + + VOID IoFreeMdl(PMDL mdl) + { + m_funcs.IoFreeMdl(mdl); + } + + VOID MmProbeAndLockPages(PMDL mdl, KPROCESSOR_MODE mode, LOCK_OPERATION op) + { + m_funcs.MmProbeAndLockPages(mdl, mode, op); + } + + VOID MmUnlockPages(PMDL mdl) + { + m_funcs.MmUnlockPages(mdl); + } + + PVOID MmGetSystemAddressForMdlSafe(PMDL mdl, ULONG priority) + { + return m_funcs.MmGetSystemAddressForMdlSafe(mdl, priority); + } + +public: + WinApiMockFuncs m_funcs; +}; diff --git a/test/pch.h b/test/pch.h index b5c57a3..7b886ff 100644 --- a/test/pch.h +++ b/test/pch.h @@ -3,6 +3,7 @@ #include #include #include +#include // TODO: move this default implementation to kf