diff options
| author | karlf <[email protected]> | 2016-08-11 13:28:13 -0700 |
|---|---|---|
| committer | karlf <[email protected]> | 2016-08-11 13:28:13 -0700 |
| commit | 96eb96dfb613e4c745db6bd1f53a92fe7e2290fc (patch) | |
| tree | ad5f3ede5cbcd6b598677ce41bcf8318471bdd92 /TrEE | |
| parent | 687b274aa38fd05c8c26e3068932121876d7f745 (diff) | |
Updated for "Windows 10 Anniversary Update" (Version 1607)
Diffstat (limited to 'TrEE')
| -rw-r--r-- | TrEE/Miniport/SampleMiniport.c | 732 | ||||
| -rw-r--r-- | TrEE/Miniport/SampleMiniport.h | 30 | ||||
| -rw-r--r-- | TrEE/Miniport/SampleMiniport.rc | 14 | ||||
| -rw-r--r-- | TrEE/Miniport/TestService.c | 1332 | ||||
| -rw-r--r-- | TrEE/Miniport/TrEEMiniportSample.inf | bin | 0 -> 4652 bytes | |||
| -rw-r--r-- | TrEE/Miniport/TrEEMiniportSample.vcxproj | 241 | ||||
| -rw-r--r-- | TrEE/Miniport/TrEEMiniportSample.vcxproj.Filters | 34 | ||||
| -rw-r--r-- | TrEE/OSService/SampleOSService.c | 928 | ||||
| -rw-r--r-- | TrEE/OSService/SampleOSService.rc | 14 | ||||
| -rw-r--r-- | TrEE/OSService/TrEEOSServiceSample.inf | bin | 0 -> 4572 bytes | |||
| -rw-r--r-- | TrEE/OSService/TrEEOSServiceSample.vcxproj | 222 | ||||
| -rw-r--r-- | TrEE/OSService/TrEEOSServiceSample.vcxproj.Filters | 31 | ||||
| -rw-r--r-- | TrEE/Test/SampleTest.cpp | 836 | ||||
| -rw-r--r-- | TrEE/Test/TrEESampleTest.vcxproj | 256 | ||||
| -rw-r--r-- | TrEE/Test/TrEESampleTest.vcxproj.Filters | 22 | ||||
| -rw-r--r-- | TrEE/TrEESample.sln | 73 | ||||
| -rw-r--r-- | TrEE/inc/SampleOSService.h | 66 | ||||
| -rw-r--r-- | TrEE/inc/SampleSecureService.h | 72 |
18 files changed, 4903 insertions, 0 deletions
diff --git a/TrEE/Miniport/SampleMiniport.c b/TrEE/Miniport/SampleMiniport.c new file mode 100644 index 00000000..55bfa60a --- /dev/null +++ b/TrEE/Miniport/SampleMiniport.c @@ -0,0 +1,732 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + sample.c + +Abstract: + + This file demonstrates a simple TrEE miniport. + +Environment: + + Kernel mode + +--*/ + +#include <ntddk.h> +#include <wdf.h> +#include <initguid.h> +#include <wdmguid.h> +#include <ntstrsafe.h> +#include <TrustedRuntimeClx.h> +#include <ntefi.h> +#include <TrEEVariableService.h> +#include "sampleminiport.h" +#include <SampleSecureService.h> +#include <SampleOSService.h> + +#define SDDL_SAMPLE_TEST2_SERVICE L"D:P(A;;FRFW;;;WD)(A;;FRFW;;;RC)(A;;FRFW;;;AC)" + +// +// Driver entry point +// + +DRIVER_INITIALIZE DriverEntry; + +// +// Device callbacks +// + +EVT_WDF_DRIVER_UNLOAD DriverUnload; +EVT_WDF_DRIVER_DEVICE_ADD TreeSampleEvtAddDevice; + +// +// Class Extension callbacks +// + +EVT_TR_CREATE_SECURE_DEVICE_CONTEXT TreeSampleCreateSecureDeviceContext; +EVT_TR_DESTROY_SECURE_DEVICE_CONTEXT TreeSampleDestroySecureDeviceContext; +EVT_TR_PREPARE_HARDWARE_SECURE_ENVIRONMENT TreeSamplePrepareHardwareSecureEnvironment; +EVT_TR_RELEASE_HARDWARE_SECURE_ENVIRONMENT TreeSampleReleaseHardwareSecureEnvironment; +EVT_TR_CONNECT_SECURE_ENVIRONMENT TreeSampleConnectSecureEnvironment; +EVT_TR_DISCONNECT_SECURE_ENVIRONMENT TreeSampleDisconnectSecureEnvironment; +EVT_TR_ENUMERATE_SECURE_SERVICES TreeSampleEnumerateSecureServices; +EVT_TR_PROCESS_OTHER_DEVICE_IO TreeSampleProcessOtherDeviceIo; +EVT_TR_CREATE_SECURE_SERVICE_CONTEXT TreeSampleCreateSecureServiceContext; +EVT_TR_QUERY_SERVICE_CALLBACKS TreeSampleQueryServiceCallbacks; + +#pragma data_seg("PAGED") + +TR_SECURE_DEVICE_CALLBACKS TreeSampleCallbacks = { + TR_DEVICE_SERIALIZE_ALL_REQUESTS | + TR_DEVICE_STACK_RESERVE_8K, + + &TreeSampleCreateSecureDeviceContext, + &TreeSampleDestroySecureDeviceContext, + + &TreeSamplePrepareHardwareSecureEnvironment, + &TreeSampleReleaseHardwareSecureEnvironment, + + &TreeSampleConnectSecureEnvironment, + &TreeSampleDisconnectSecureEnvironment, + + &TreeSampleEnumerateSecureServices, + &TreeSampleProcessOtherDeviceIo, + + &TreeSampleQueryServiceCallbacks +}; + +#pragma data_seg() + +#pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(PAGE, DriverUnload) +#pragma alloc_text(PAGE, TreeSampleEvtAddDevice) +#pragma alloc_text(PAGE, TreeSampleCreateSecureDeviceContext) +#pragma alloc_text(PAGE, TreeSampleDestroySecureDeviceContext) +#pragma alloc_text(PAGE, TreeSamplePrepareHardwareSecureEnvironment) +#pragma alloc_text(PAGE, TreeSampleReleaseHardwareSecureEnvironment) +#pragma alloc_text(PAGE, TreeSampleEnumerateSecureServices) +#pragma alloc_text(PAGE, TreeSampleProcessOtherDeviceIo) +#pragma alloc_text(PAGE, TreeSampleQueryServiceCallbacks) + +_Use_decl_annotations_ +NTSTATUS +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath + ) + +/*++ + + Routine Description: + + This is the initialization routine for the device driver. This routine + creates the driver object for the TrEE miniport. + + Arguments: + + DriverObject - Supplies a pointer to driver object created by the + system. + + RegistryPath - Supplies a unicode string indentifying where the + parameters for this driver are located in the registry. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + WDFDRIVER Driver; + WDF_DRIVER_CONFIG DriverConfig; + NTSTATUS Status; + + Driver = NULL; + + // + // Create the WDF driver object + // + + WDF_DRIVER_CONFIG_INIT(&DriverConfig, TreeSampleEvtAddDevice); + DriverConfig.EvtDriverUnload = DriverUnload; + + Status = WdfDriverCreate(DriverObject, + RegistryPath, + WDF_NO_OBJECT_ATTRIBUTES, + &DriverConfig, + &Driver); + + if (!NT_SUCCESS(Status)) { + goto DriverEntryEnd; + } + + +DriverEntryEnd: + + return Status; +} + +_Use_decl_annotations_ +VOID +DriverUnload( + WDFDRIVER Driver + ) + +/*++ + + Routine Description: + + This is the cleanup function called when the driver is unloaded. + + Arguments: + + Driver - Supplies a handle to WDFDRIVER object created in DriverEntry. + + Return Value: + + None. + +--*/ + +{ + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Driver); +} + +_Use_decl_annotations_ +NTSTATUS +TreeSampleEvtAddDevice( + WDFDRIVER Driver, + PWDFDEVICE_INIT DeviceInit + ) + +/*++ + + Routine Description: + + This routine is called when the driver is being attached to a specific + device. + + Arguments: + + Driver - Supplies a handle to the framework driver object. + + DeviceInit - Supplies a pointer to the device initialization parameters. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + WDFDEVICE Device; + NTSTATUS Status; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Driver); + + Status = TrSecureDeviceHandoffMasterDeviceControl( + DeviceInit, + &TreeSampleCallbacks, + &Device); + + TrSecureDeviceLogMessage(Device, + STATUS_SEVERITY_INFORMATIONAL, + "Master device discovered\n"); + + return Status; +} + +_Use_decl_annotations_ +NTSTATUS +TreeSampleCreateSecureDeviceContext( + WDFDEVICE MasterDevice + ) + +/*++ + + Routine Description: + + This routine is called when the secure environment is first started. + + Arguments: + + MasterDevice - Supplies a handle to the master device object. + + DeviceContext - Supplies a pointer to store any context information + required for future calls. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + WDF_OBJECT_ATTRIBUTES ContextAttributes; + PTREE_SAMPLE_DEVICE_CONTEXT MasterContext; + NTSTATUS Status; + DECLARE_CONST_UNICODE_STRING(SymbolicLink, L"\\DosDevices\\SampleTrEEDriver"); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ContextAttributes, + TREE_SAMPLE_DEVICE_CONTEXT); + + Status = WdfObjectAllocateContext(MasterDevice, &ContextAttributes, &MasterContext); + if (!NT_SUCCESS(Status)) { + goto TreeSampleCreateSecureDeviceContextEnd; + } + + MasterContext->MasterDevice = MasterDevice; + + // + // Create a symbolic link so that usermode program can access master device. + // + Status = WdfDeviceCreateSymbolicLink(MasterDevice, &SymbolicLink); + if (!NT_SUCCESS(Status)) { + goto TreeSampleCreateSecureDeviceContextEnd; + } + +TreeSampleCreateSecureDeviceContextEnd: + return Status; +} + +_Use_decl_annotations_ +NTSTATUS +TreeSampleDestroySecureDeviceContext( + WDFDEVICE MasterDevice + ) + +/*++ + + Routine Description: + + This routine is called when the secure environment is no longer used. + + Arguments: + + MasterDevice - Supplies a handle to the master device object. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PTREE_SAMPLE_DEVICE_CONTEXT MasterContext; + + MasterContext = WdfObjectGet_TREE_SAMPLE_DEVICE_CONTEXT(MasterDevice); + + // + // No member needs cleanup here. ServiceCollection will be automatically + // reclaimed by the framework, since the parent object is going away. + // + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TreeSamplePrepareHardwareSecureEnvironment( + WDFDEVICE MasterDevice, + WDFCMRESLIST RawResources, + WDFCMRESLIST TranslatedResources + ) + +/*++ + + Routine Description: + + This routine is called to handle any resources used by a secure device. + + Arguments: + + MasterDevice - Supplies a handle to the master device object. + + DeviceContext - Supplies a pointer to the context. + + RawResources - Supplies a pointer to the raw resources. + + TranslatedResources - Supplies a pointer to the translated resources. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + UNREFERENCED_PARAMETER(MasterDevice); + UNREFERENCED_PARAMETER(RawResources); + UNREFERENCED_PARAMETER(TranslatedResources); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TreeSampleReleaseHardwareSecureEnvironment( + WDFDEVICE MasterDevice, + WDFCMRESLIST TranslatedResources + ) + +/*++ + + Routine Description: + + This routine is called to handle the displosal of any resources used by + a secure device. + + Arguments: + + MasterDevice - Supplies a handle to the master device object. + + DeviceContext - Supplies a pointer to the context. + + TranslatedResources - Supplies a pointer to the translated resources. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(MasterDevice); + UNREFERENCED_PARAMETER(TranslatedResources); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TreeSampleConnectSecureEnvironment( + WDFDEVICE MasterDevice + ) + +/*++ + + Routine Description: + + This routine is called when the secure environment should be prepared + for use either the first time or after a possible power state change. + + This routine must be marked as pagable, since it is called during power + state transition. + + Arguments: + + MasterDevice - Supplies a handle to the master device object. + + DeviceContext - Supplies a pointer to the context. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + UNREFERENCED_PARAMETER(MasterDevice); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TreeSampleDisconnectSecureEnvironment( + WDFDEVICE MasterDevice + ) + +/*++ + + Routine Description: + + This routine is called when the secure environment should be prepared + for a possible power state change. + + This routine must be marked as pagable, since it is called during power + state transition. + + Arguments: + + MasterDevice - Supplies a handle to the master device object. + + DeviceContext - Supplies a pointer to the context. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + UNREFERENCED_PARAMETER(MasterDevice); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TreeSampleEnumerateSecureServices( + WDFDEVICE MasterDevice, + ULONG Index, + PUCHAR SecureServiceDescription, + ULONG *DescriptionSize + ) + +/*++ + + Routine Description: + + This routine is called to enumerate the supported secure services + provided by this secure device. The zero-based Index parameter is used + to determine which secure service information is being requested for. + If Index is larger than the number of available services then + STATUS_NO_MORE_ENTRIES is returned to indicate the end of the list has + been reached. + + Arguments: + + MasterDevice - Supplies a handle to the master device object. + + DeviceContext - Supplies a pointer to the context. + + Index - Supplies the zero-based index for the secure service whose + description is being requested. + + SecureServiceDescription - Supplies a pointer to a buffer to hold the + secure service description. The description + is of type TR_SECURE_SERVICE. + + DescriptionSize - Supplies a pointer to the size in bytes of + SecureServiceDescription on input, and holds the + number of bytes required on output. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + ULONG DescriptionSizeRequired; + PTR_SECURE_SERVICE SecureService; + PTR_SECURE_SERVICE_EXTENSION ServiceExtension; + NTSTATUS Status; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(MasterDevice); + + SecureService = (PTR_SECURE_SERVICE)SecureServiceDescription; + switch (Index) { + case 0: + // + // [0] Test service + // Major version = 1 + // Minor version = 0 + // No OS dependencies + // Open to all except restricted code (default) + // + DescriptionSizeRequired = FIELD_OFFSET(TR_SECURE_SERVICE, Dependencies); + if (*DescriptionSize < DescriptionSizeRequired) { + Status = STATUS_BUFFER_TOO_SMALL; + goto TreeSampleEnumerateSecureServicesEnd; + } + + SecureService->DescriptionSize = DescriptionSizeRequired; + SecureService->ServiceGuid = GUID_SAMPLE_TEST_SERVICE; + SecureService->MajorVersion = 1; + SecureService->MinorVersion = 0; + SecureService->ExtensionOffset = 0; + SecureService->CountDependencies = 0; + + Status = STATUS_SUCCESS; + break; + + case 1: + // + // [1] Test2 service + // Major version = 1 + // Minor version = 0 + // OS dependency on GUID_ECHO_SERVICE and GUID_KERNEL_MEMORY_SERVICE + // Open to all including restricted code + // + DescriptionSizeRequired = FIELD_OFFSET(TR_SECURE_SERVICE, Dependencies) + + sizeof(TR_SECURE_DEPENDENCY_V1) * 2 + + sizeof(TR_SECURE_SERVICE_EXTENSION) + + sizeof(SDDL_SAMPLE_TEST2_SERVICE); + + if (*DescriptionSize < DescriptionSizeRequired) { + Status = STATUS_BUFFER_TOO_SMALL; + goto TreeSampleEnumerateSecureServicesEnd; + } + + SecureService->DescriptionSize = DescriptionSizeRequired; + SecureService->ServiceGuid = GUID_SAMPLE_TEST2_SERVICE; + SecureService->MajorVersion = 1; + SecureService->MinorVersion = 0; + SecureService->ExtensionOffset = FIELD_OFFSET(TR_SECURE_SERVICE, Dependencies) + + sizeof(TR_SECURE_DEPENDENCY_V1) * 2; + SecureService->CountDependencies = 2; + SecureService->Dependencies[0].Type = TRSecureOSDependency; + SecureService->Dependencies[0].Id = GUID_ECHO_SERVICE; + SecureService->Dependencies[0].MaxRequired = 1; + SecureService->Dependencies[1].Type = TRSecureOSDependency; + SecureService->Dependencies[1].Id = GUID_KERNEL_MEMORY_SERVICE; + SecureService->Dependencies[1].MaxRequired = 1; + ServiceExtension = (PTR_SECURE_SERVICE_EXTENSION)( + ((ULONG_PTR)SecureService) + + SecureService->ExtensionOffset); + + ServiceExtension->ExtensionVersion = TR_SECURE_SERVICE_EXTENSION_VERSION; + ServiceExtension->SecurityDescriptorStringOffset = SecureService->ExtensionOffset + + sizeof(TR_SECURE_SERVICE_EXTENSION); + RtlCopyMemory((PVOID)(((ULONG_PTR)SecureService) + ServiceExtension->SecurityDescriptorStringOffset), + SDDL_SAMPLE_TEST2_SERVICE, + sizeof(SDDL_SAMPLE_TEST2_SERVICE)); + + Status = STATUS_SUCCESS; + break; + + default: + DescriptionSizeRequired = 0; + Status = STATUS_NO_MORE_ENTRIES; + break; + } + +TreeSampleEnumerateSecureServicesEnd: + *DescriptionSize = DescriptionSizeRequired; + return Status; +} + +_Use_decl_annotations_ +VOID +TreeSampleProcessOtherDeviceIo( + WDFDEVICE MasterDevice, + WDFREQUEST Request + ) + +/*++ + + Routine Description: + + This routine is called when an unrecognized IO request is made to the + device. This can be used to process private calls directly to the + secure device. + + Arguments: + + MasterDevice - Supplies a handle to the master device object. + + DeviceContext - Supplies a pointer to the context. + + Request - Supplies a pointer to the WDF request object. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PWCHAR Buffer; + size_t BufferSize; + ULONG BytesWritten; + WDF_REQUEST_PARAMETERS Parameters; + NTSTATUS Status; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(MasterDevice); + + WDF_REQUEST_PARAMETERS_INIT(&Parameters); + WdfRequestGetParameters(Request, &Parameters); + BytesWritten = 0; + switch (Parameters.Parameters.DeviceIoControl.IoControlCode) { + case IOCTL_SAMPLE_DBGPRINT: + Status = WdfRequestRetrieveInputBuffer(Request, + 0, + (PVOID*)&Buffer, + &BufferSize); + + if (!NT_SUCCESS(Status)) { + goto TreeSampleProcessOtherDeviceIoEnd; + } + + // + // Must be NULL-terminated + // + if (Buffer[BufferSize / sizeof(WCHAR) - 1] != L'\0') { + Status = STATUS_INVALID_PARAMETER; + goto TreeSampleProcessOtherDeviceIoEnd; + } + + DbgPrintEx(DPFLTR_DEFAULT_ID, + DPFLTR_ERROR_LEVEL, + "[TrEEMiniportSample] %ws\n", + (PWSTR)Buffer); + + break; + + default: + Status = STATUS_INVALID_DEVICE_REQUEST; + } + +TreeSampleProcessOtherDeviceIoEnd: + WdfRequestCompleteWithInformation(Request, Status, BytesWritten); +} + +_Use_decl_annotations_ +PTR_SECURE_SERVICE_CALLBACKS +TreeSampleQueryServiceCallbacks( + WDFDEVICE MasterDevice, + LPGUID ServiceGuid + ) + +/*++ + + Routine Description: + + This routine is called when an unrecognized IO request is made to the + device. This can be used to process private calls directly to the + secure device. + + Arguments: + + MasterDevice - Supplies a handle to the master device object. + + DeviceContext - Supplies a pointer to the context. + + Request - Supplies a pointer to the WDF request object. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PTR_SECURE_SERVICE_CALLBACKS ServiceCallbacks; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(MasterDevice); + + if (IsEqualGUID(ServiceGuid, &GUID_SAMPLE_TEST_SERVICE)) { + + ServiceCallbacks = &TestServiceCallbacks; + + } else if (IsEqualGUID(ServiceGuid, &GUID_SAMPLE_TEST2_SERVICE)) { + + ServiceCallbacks = &Test2ServiceCallbacks; + + } else { + + ServiceCallbacks = NULL; + } + + return ServiceCallbacks; +} diff --git a/TrEE/Miniport/SampleMiniport.h b/TrEE/Miniport/SampleMiniport.h new file mode 100644 index 00000000..0be88b9b --- /dev/null +++ b/TrEE/Miniport/SampleMiniport.h @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + sample.h + +Abstract: + + The shared header file for the sample TrEE miniport driver. + +Environment: + + Kernel mode + +--*/ + +// +// Device context +// + +typedef struct _TREE_SAMPLE_DEVICE_CONTEXT { + WDFDEVICE MasterDevice; +} TREE_SAMPLE_DEVICE_CONTEXT, *PTREE_SAMPLE_DEVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE(TREE_SAMPLE_DEVICE_CONTEXT); + +TR_SECURE_SERVICE_CALLBACKS TestServiceCallbacks; +TR_SECURE_SERVICE_CALLBACKS Test2ServiceCallbacks;
\ No newline at end of file diff --git a/TrEE/Miniport/SampleMiniport.rc b/TrEE/Miniport/SampleMiniport.rc new file mode 100644 index 00000000..2741cb72 --- /dev/null +++ b/TrEE/Miniport/SampleMiniport.rc @@ -0,0 +1,14 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +#include <windows.h> +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Sample TREE Client Driver" +#define VER_INTERNALNAME_STR "TrEEMiniportSample.sys" + +#include "common.ver" + + diff --git a/TrEE/Miniport/TestService.c b/TrEE/Miniport/TestService.c new file mode 100644 index 00000000..ef465297 --- /dev/null +++ b/TrEE/Miniport/TestService.c @@ -0,0 +1,1332 @@ +#include <ntddk.h> +#include <wdf.h> +#include <initguid.h> +#include <wdmguid.h> +#include <TrustedRuntimeClx.h> +#include "SampleMiniport.h" +#include <SampleSecureService.h> +#include <SampleOSService.h> + +EVT_TR_CREATE_SECURE_SERVICE_CONTEXT TestServiceCreateSecureServiceContext; +EVT_TR_DESTROY_SECURE_SERVICE_CONTEXT TestServiceDestroySecureServiceContext; +EVT_TR_CONNECT_SECURE_SERVICE TestServiceConnectSecureService; +EVT_TR_DISCONNECT_SECURE_SERVICE TestServiceDisconnectSecureService; +EVT_TR_CREATE_SECURE_SERVICE_SESSION_CONTEXT TestServiceCreateSessionContext; +EVT_TR_DESTROY_SECURE_SERVICE_SESSION_CONTEXT TestServiceDestroySessionContext; +EVT_TR_PROCESS_SECURE_SERVICE_REQUEST TestServiceProcessSecureServiceRequest; +EVT_TR_CANCEL_SECURE_SERVICE_REQUEST TestServiceCancelSecureServiceRequest; +EVT_TR_PROCESS_OTHER_SECURE_SERVICE_IO TestServiceProcessOtherSecureServiceIo; + +EVT_TR_PROCESS_SECURE_SERVICE_REQUEST Test2ServiceProcessSecureServiceRequest; + +#pragma data_seg("PAGED") + +TR_SECURE_SERVICE_CALLBACKS TestServiceCallbacks = { + 0, + + &TestServiceCreateSecureServiceContext, + &TestServiceDestroySecureServiceContext, + + &TestServiceConnectSecureService, + &TestServiceDisconnectSecureService, + + &TestServiceCreateSessionContext, + &TestServiceDestroySessionContext, + + &TestServiceProcessSecureServiceRequest, + &TestServiceCancelSecureServiceRequest, + &TestServiceProcessOtherSecureServiceIo +}; + +TR_SECURE_SERVICE_CALLBACKS Test2ServiceCallbacks = { + 0, + + &TestServiceCreateSecureServiceContext, + &TestServiceDestroySecureServiceContext, + + &TestServiceConnectSecureService, + &TestServiceDisconnectSecureService, + + &TestServiceCreateSessionContext, + &TestServiceDestroySessionContext, + + &Test2ServiceProcessSecureServiceRequest, + &TestServiceCancelSecureServiceRequest, + &TestServiceProcessOtherSecureServiceIo +}; + +#pragma data_seg() + +typedef struct _TEST_SERVICE_CONTEXT { + GUID ServiceGuid; +} TEST_SERVICE_CONTEXT, *PTEST_SERVICE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE(TEST_SERVICE_CONTEXT); + +// +// Macro to convert between forced 64-bit pointers to native +// +#define TruncatePointer64(_Pointer) ((PVOID)(ULONG_PTR)(ULONG64)(_Pointer)) + +_Use_decl_annotations_ +NTSTATUS +TestServiceCreateSecureServiceContext( + WDFDEVICE MasterDevice, + LPCGUID ServiceGuid, + WDFDEVICE ServiceDevice + ) + +/*++ + + Routine Description: + + This routine is called when a secure service is being created. + + Arguments: + + MasterDevice - Supplies a handle to the master device object. + + ServiceGuid - Supplies GUID of the secure service. + + ServiceDevice - Supplies a handle to the new service device object + being created. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + WDF_OBJECT_ATTRIBUTES ContextAttributes; + PTEST_SERVICE_CONTEXT ServiceContext; + NTSTATUS Status; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(MasterDevice); + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ContextAttributes, + TEST_SERVICE_CONTEXT); + + Status = WdfObjectAllocateContext(ServiceDevice, + &ContextAttributes, + &ServiceContext); + + if (!NT_SUCCESS(Status)) { + goto TestServiceCreateSecureServiceContextEnd; + } + + ServiceContext->ServiceGuid = *ServiceGuid; + +TestServiceCreateSecureServiceContextEnd: + return Status; +} + +_Use_decl_annotations_ +NTSTATUS +TestServiceDestroySecureServiceContext( + WDFDEVICE ServiceDevice + ) + +/*++ + + Routine Description: + + This routine is called when a secure service is being destroyed. + + Arguments: + + ServiceDevice - Supplies a handle to the service device object. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TestServiceConnectSecureService( + WDFDEVICE ServiceDevice + ) + +/*++ + + Routine Description: + + This routine is called when a secure service is being used for the + first time or has returned from a power-state change. + + Arguments: + + ServiceDevice - Supplies a handle to the service device object. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TestServiceDisconnectSecureService( + WDFDEVICE ServiceDevice + ) + +/*++ + + Routine Description: + + This routine is called to disconnect a secure service in preparation + for a possible power-state change. + + Arguments: + + ServiceDevice - Supplies a handle to the service device object. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + UNREFERENCED_PARAMETER(ServiceDevice); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TestServiceCreateSessionContext( + WDFDEVICE ServiceDevice, + WDFOBJECT *SessionContextObject + ) + +/*++ + + Routine Description: + + This routine is called on creation of a new session to a secure + service. This can be used to track any state through multiple requests + from the same client. + + Arguments: + + ServiceDevice - Supplies a handle to the service device object. + + SessionContext - Supplies a pointer to hold any session state that may + be required for future calls. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + UNREFERENCED_PARAMETER(SessionContextObject); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TestServiceDestroySessionContext( + WDFDEVICE ServiceDevice, + WDFOBJECT *SessionContextObject + ) + +/*++ + + Routine Description: + + This routine is called on destruction a session. + + Arguments: + + ServiceDevice - Supplies a handle to the service device object. + + SessionContext - Supplies a pointer to the session context. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + UNREFERENCED_PARAMETER(SessionContextObject); + + return STATUS_SUCCESS; +} + +typedef +NTSTATUS +TREE_TEST_SERVICE_REQUEST_HANDLER( + _In_ WDFDEVICE ServiceDevice, + _In_ PTEST_SERVICE_CONTEXT ServiceContext, + _In_ PVOID RequestHandle, + _In_ KPRIORITY Priority, + _In_ PTR_SERVICE_REQUEST Request, + _In_ ULONG Flags, + _Out_ PULONG_PTR BytesWritten, + _Inout_opt_ PVOID* RequestContext + ); + +TREE_TEST_SERVICE_REQUEST_HANDLER TestServiceHelloWorld; +TREE_TEST_SERVICE_REQUEST_HANDLER TestServiceInterruptTime; +TREE_TEST_SERVICE_REQUEST_HANDLER TestServiceKernelOnly; +TREE_TEST_SERVICE_REQUEST_HANDLER TestServiceDelayedCompletion; + +TREE_TEST_SERVICE_REQUEST_HANDLER *TestServiceDispatch[] = { + NULL, + TestServiceHelloWorld, + TestServiceInterruptTime, + TestServiceKernelOnly, + TestServiceDelayedCompletion, +}; + +TREE_TEST_SERVICE_REQUEST_HANDLER Test2ServiceEchoTest; +TREE_TEST_SERVICE_REQUEST_HANDLER Test2ServiceTwiceReversed; + +TREE_TEST_SERVICE_REQUEST_HANDLER *Test2ServiceDispatch[] = { + NULL, + Test2ServiceEchoTest, + Test2ServiceTwiceReversed, +}; + +_Use_decl_annotations_ +NTSTATUS +TestServiceProcessSecureServiceRequest( + WDFDEVICE ServiceDevice, + WDFOBJECT SessionContextObject, + PVOID RequestHandle, + KPRIORITY Priority, + PTR_SERVICE_REQUEST Request, + ULONG Flags, + PULONG_PTR BytesWritten, + PVOID* RequestContext + ) + +/*++ + + Routine Description: + + This routine is called to process a request to the secure service. + This is typically the only way communication would be done to a secure + service. + + Arguments: + + ServiceDevice - Supplies a handle to the service device object. + + SessionContext - Supplies a pointer to the context. + + RequestHandle - Supplies a pointer to a request handle that will be + used if the operation completes asynchronously. + + Priority - Supplies the priority of the request. + + Request - Supplies a pointer to the data for the request. + + RequestorMode - Supplies where the request originated from. + + BytesWritten - Supplies a pointer to be filled out with the number of + bytes written. + + RequestContext - Supplies a pointer to a PVOID variable where + additional information needed to cancel the request. + It will be provided in TestServiceCancelSecureServiceRequest. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PTEST_SERVICE_CONTEXT ServiceContext; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(SessionContextObject); + UNREFERENCED_PARAMETER(RequestHandle); + UNREFERENCED_PARAMETER(Priority); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(RequestContext); + + *BytesWritten = 0; + if ((Request->FunctionCode == 0) || + (Request->FunctionCode >= sizeof(TestServiceDispatch)/sizeof(TestServiceDispatch[0]))) { + + return STATUS_INVALID_PARAMETER; + } + + ServiceContext = WdfObjectGet_TEST_SERVICE_CONTEXT(ServiceDevice); + return (*TestServiceDispatch[Request->FunctionCode])(ServiceDevice, + ServiceContext, + RequestHandle, + Priority, + Request, + Flags, + BytesWritten, + RequestContext); +} + +#pragma region Test service request handlers + +#define STR_HELLO_WORLD L"Hello, world!" + +_Use_decl_annotations_ +NTSTATUS +TestServiceHelloWorld( + WDFDEVICE ServiceDevice, + PTEST_SERVICE_CONTEXT ServiceContext, + PVOID RequestHandle, + KPRIORITY Priority, + PTR_SERVICE_REQUEST Request, + ULONG Flags, + PULONG_PTR BytesWritten, + PVOID* RequestContext + ) + +/*++ + + Routine Description: + + This routine will write classic L"Hello, world!" message to the output + buffer. If output buffer is too small, BytesWritten field in the + response struct will contain the required size. + + Arguments: + + ServiceContext - Supplies a pointer to service device context object. + + Refer to TestServiceProcessSecureServiceRequest for the rest. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + UNREFERENCED_PARAMETER(ServiceContext); + UNREFERENCED_PARAMETER(RequestHandle); + UNREFERENCED_PARAMETER(Priority); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(RequestContext); + + *BytesWritten = sizeof(STR_HELLO_WORLD); + if (Request->OutputBufferSize < sizeof(STR_HELLO_WORLD)) { + // + // STATUS_BUFFER_OVERFLOW must be used to make WDF forward the value of + // *BytesWritten to let Win32 caller know how large the output buffer + // should be. + // + return STATUS_BUFFER_OVERFLOW; + } + + RtlCopyMemory(Request->OutputBuffer, STR_HELLO_WORLD, sizeof(STR_HELLO_WORLD)); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TestServiceInterruptTime( + WDFDEVICE ServiceDevice, + PTEST_SERVICE_CONTEXT ServiceContext, + PVOID RequestHandle, + KPRIORITY Priority, + PTR_SERVICE_REQUEST Request, + ULONG Flags, + PULONG_PTR BytesWritten, + PVOID* RequestContext + ) + +/*++ + + Routine Description: + + This routine will write the value returned from + KeQueryInterruptTimePrecise in the output buffer. + + Arguments: + + ServiceContext - Supplies a pointer to service device context object. + + Refer to TestServiceProcessSecureServiceRequest for the rest. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + ULONG64 QpcTimestamp; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + UNREFERENCED_PARAMETER(ServiceContext); + UNREFERENCED_PARAMETER(RequestHandle); + UNREFERENCED_PARAMETER(Priority); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(RequestContext); + + *BytesWritten = sizeof(ULONG64); + if (Request->OutputBufferSize < sizeof(ULONG64)) { + // + // STATUS_BUFFER_OVERFLOW must be used to make WDF forward the value of + // *BytesWritten to let Win32 caller know how large the output buffer + // should be. + // + return STATUS_BUFFER_OVERFLOW; + } + + *(PULONG64)TruncatePointer64(Request->OutputBuffer) = KeQueryInterruptTimePrecise(&QpcTimestamp); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +TestServiceKernelOnly( + WDFDEVICE ServiceDevice, + PTEST_SERVICE_CONTEXT ServiceContext, + PVOID RequestHandle, + KPRIORITY Priority, + PTR_SERVICE_REQUEST Request, + ULONG Flags, + PULONG_PTR BytesWritten, + PVOID* RequestContext + ) + +/*++ + + Routine Description: + + This routine does nothing. However, if this request was sent from + usermode, it will complete with failure status code. + + Arguments: + + ServiceContext - Supplies a pointer to service device context object. + + Refer to TestServiceProcessSecureServiceRequest for the rest. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + UNREFERENCED_PARAMETER(ServiceContext); + UNREFERENCED_PARAMETER(RequestHandle); + UNREFERENCED_PARAMETER(Priority); + UNREFERENCED_PARAMETER(Request); + UNREFERENCED_PARAMETER(RequestContext); + + *BytesWritten = 0; + if (Flags & TR_SERVICE_REQUEST_FROM_USERMODE) { + return STATUS_ACCESS_DENIED; + + } else { + + return STATUS_SUCCESS; + } +} + +typedef struct _DELAYED_COMPLETION_TIMER_CONTEXT { + union { + PVOID RequestHandle; + WDFREQUEST Request; + } Request; + WDFWORKITEM WorkItem; + PVOID OutputBuffer; +} DELAYED_COMPLETION_TIMER_CONTEXT, *PDELAYED_COMPLETION_TIMER_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE(DELAYED_COMPLETION_TIMER_CONTEXT); + +EVT_WDF_TIMER DelayedCompletionTimerCallback; +EVT_WDF_WORKITEM DelayedCompletionWorkItemCallback; + +_Use_decl_annotations_ +VOID +DelayedCompletionTimerCallback( + WDFTIMER Timer + ) + +/*++ + + Routine Description: + + This routine is the callback for the timer used in delayed completion + request handler. It'll enqueue a work item to complete the request and + clean up resources. + + Arguments: + + Timer - Supplies a handle to the timer. + + Return Value: + + None. + +--*/ + +{ + PDELAYED_COMPLETION_TIMER_CONTEXT Context; + + Context = WdfObjectGet_DELAYED_COMPLETION_TIMER_CONTEXT(Timer); + WdfWorkItemEnqueue(Context->WorkItem); +} + +_Use_decl_annotations_ +VOID +DelayedCompletionWorkItemCallback( + WDFWORKITEM WorkItem + ) + +/*++ + + Routine Description: + + This routine is enqueued from delayed completion timer callback. Since + a timer cannot be deleted inside its handler, it is deleted here + instead. Also the request is completed here. + + Arguments: + + WorkItem - Supplies a handle to this work item. + + Return Value: + + None. + +--*/ + +{ + PDELAYED_COMPLETION_TIMER_CONTEXT Context; + WDFTIMER Timer; + + PAGED_CODE(); + + Timer = (WDFTIMER)WdfWorkItemGetParentObject(WorkItem); + Context = WdfObjectGet_DELAYED_COMPLETION_TIMER_CONTEXT(Timer); + *(PULONG)Context->OutputBuffer = 0x12345678; + + // + // The request couldn't have been canceled if we reach here. The + // cancellation routine tries to stop the timer and prevent callback from + // being called. If it succeeds, this routine never runs. If it fails, the + // request is not canceled. + // + TrSecureDeviceCompleteAsyncRequest(Context->Request.RequestHandle, + STATUS_SUCCESS, + sizeof(ULONG)); + + WdfObjectDelete(Timer); +} + +_Use_decl_annotations_ +NTSTATUS +TestServiceDelayedCompletion( + WDFDEVICE ServiceDevice, + PTEST_SERVICE_CONTEXT ServiceContext, + PVOID RequestHandle, + KPRIORITY Priority, + PTR_SERVICE_REQUEST Request, + ULONG Flags, + PULONG_PTR BytesWritten, + PVOID* RequestContext + ) + +/*++ + + Routine Description: + + This routine completes the request after specified delay. The delay is + given in input buffer as ULONG in units of milliseconds. When + completed, output buffer will contain 0x12345678 ULONG value. + + Arguments: + + ServiceContext - Supplies a pointer to service device context object. + + Refer to TestServiceProcessSecureServiceRequest for the rest. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + PDELAYED_COMPLETION_TIMER_CONTEXT Context; + NTSTATUS Status; + WDFTIMER Timer; + WDF_OBJECT_ATTRIBUTES TimerAttributes; + WDF_TIMER_CONFIG TimerConfig; + WDF_OBJECT_ATTRIBUTES WorkItemAttributes; + WDF_WORKITEM_CONFIG WorkItemConfig; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + UNREFERENCED_PARAMETER(ServiceContext); + UNREFERENCED_PARAMETER(RequestHandle); + UNREFERENCED_PARAMETER(Priority); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(BytesWritten); + UNREFERENCED_PARAMETER(RequestContext); + + if (Request->InputBufferSize < sizeof(ULONG)) { + return STATUS_INVALID_PARAMETER; + } + + if (Request->OutputBufferSize < sizeof(ULONG)) { + // + // STATUS_BUFFER_OVERFLOW must be used to make WDF forward the value of + // *BytesWritten to let Win32 caller know how large the output buffer + // should be. + // + *BytesWritten = sizeof(ULONG); + return STATUS_BUFFER_OVERFLOW; + } + + *BytesWritten = 0; + Timer = NULL; + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&TimerAttributes, DELAYED_COMPLETION_TIMER_CONTEXT); + WDF_TIMER_CONFIG_INIT(&TimerConfig, DelayedCompletionTimerCallback); + TimerAttributes.ExecutionLevel = WdfExecutionLevelDispatch; + TimerAttributes.ParentObject = ServiceDevice; + Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &Timer); + if (!NT_SUCCESS(Status)) { + goto TestServiceDelayedCompletionEnd; + } + + Context = WdfObjectGet_DELAYED_COMPLETION_TIMER_CONTEXT(Timer); + Context->Request.RequestHandle = RequestHandle; + Context->OutputBuffer = TruncatePointer64(Request->OutputBuffer); + + WDF_OBJECT_ATTRIBUTES_INIT(&WorkItemAttributes); + WDF_WORKITEM_CONFIG_INIT(&WorkItemConfig, DelayedCompletionWorkItemCallback); + WorkItemAttributes.ParentObject = Timer; + Status = WdfWorkItemCreate(&WorkItemConfig, &WorkItemAttributes, &Context->WorkItem); + if (!NT_SUCCESS(Status)) { + goto TestServiceDelayedCompletionEnd; + } + + // + // Set timer due after given delay + // + WdfTimerStart(Timer, WDF_REL_TIMEOUT_IN_MS(*(PULONG)TruncatePointer64(Request->InputBuffer))); + Status = STATUS_PENDING; + + // + // RequestContext stores the data that is needed when canceling the request + // + *RequestContext = (PVOID)Timer; + +TestServiceDelayedCompletionEnd: + if (!NT_SUCCESS(Status)) { + if (Timer != NULL) { + WdfObjectDelete(Timer); + } + + // + // WorkItem is automatically deleted when parent object (Timer) is + // destroyed. + // + } + + return Status; +} + +#pragma endregion + +_Use_decl_annotations_ +NTSTATUS +Test2ServiceProcessSecureServiceRequest( + WDFDEVICE ServiceDevice, + WDFOBJECT SessionContextObject, + PVOID RequestHandle, + KPRIORITY Priority, + PTR_SERVICE_REQUEST Request, + ULONG Flags, + PULONG_PTR BytesWritten, + PVOID* RequestContext + ) + +/*++ + + Routine Description: + + This routine is called to process a request to the secure service. + This is typically the only way communication would be done to a secure + service. + + Arguments: + + ServiceDevice - Supplies a handle to the service device object. + + SessionContext - Supplies a pointer to the context. + + RequestHandle - Supplies a pointer to a request handle that will be + used if the operation completes asynchronously. + + Priority - Supplies the priority of the request. + + Request - Supplies a pointer to the data for the request. + + RequestorMode - Supplies where the request originated from. + + BytesWritten - Supplies a pointer to be filled out with the number of + bytes written. + + RequestContext - Supplies a pointer to a PVOID variable where + additional information needed to cancel the request. + It will be provided in TestServiceCancelSecureServiceRequest. + This address is valid until the request is completed + or canceled. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PTEST_SERVICE_CONTEXT ServiceContext; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(SessionContextObject); + UNREFERENCED_PARAMETER(RequestHandle); + UNREFERENCED_PARAMETER(Priority); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(RequestContext); + + *BytesWritten = 0; + if ((Request->FunctionCode == 0) || + (Request->FunctionCode >= sizeof(Test2ServiceDispatch)/sizeof(Test2ServiceDispatch[0]))) { + + return STATUS_INVALID_PARAMETER; + } + + ServiceContext = WdfObjectGet_TEST_SERVICE_CONTEXT(ServiceDevice); + return (*Test2ServiceDispatch[Request->FunctionCode])(ServiceDevice, + ServiceContext, + RequestHandle, + Priority, + Request, + Flags, + BytesWritten, + RequestContext); +} + +#pragma region Test2 service request handlers + +_Use_decl_annotations_ +NTSTATUS +Test2ServiceEchoTest( + WDFDEVICE ServiceDevice, + PTEST_SERVICE_CONTEXT ServiceContext, + PVOID RequestHandle, + KPRIORITY Priority, + PTR_SERVICE_REQUEST Request, + ULONG Flags, + PULONG_PTR BytesWritten, + PVOID* RequestContext + ) +{ + TR_SERVICE_REQUEST OSServiceRequest = {0}; + NTSTATUS Status; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + UNREFERENCED_PARAMETER(ServiceContext); + UNREFERENCED_PARAMETER(RequestHandle); + UNREFERENCED_PARAMETER(Priority); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(RequestContext); + + OSServiceRequest.FunctionCode = ECHO_SERVICE_ECHO; + OSServiceRequest.InputBuffer = Request->InputBuffer; + OSServiceRequest.InputBufferSize = Request->InputBufferSize; + OSServiceRequest.OutputBuffer = Request->OutputBuffer; + OSServiceRequest.OutputBufferSize = Request->OutputBufferSize; + Status = TrSecureDeviceCallOSService(ServiceDevice, + &GUID_ECHO_SERVICE, + &OSServiceRequest, + BytesWritten); + + // + // OS service calls never returns STATUS_PENDING. No need to take care of + // asynchronous processing. + // + + NT_ASSERT(Status != STATUS_PENDING); + + return Status; +} + +_Use_decl_annotations_ +NTSTATUS +Test2ServiceTwiceReversed( + WDFDEVICE ServiceDevice, + PTEST_SERVICE_CONTEXT ServiceContext, + PVOID RequestHandle, + KPRIORITY Priority, + PTR_SERVICE_REQUEST Request, + ULONG Flags, + PULONG_PTR BytesWritten, + PVOID* RequestContext + ) +{ + PVOID TemporaryBuffer; + ULONG_PTR OSServiceBytesWritten; + TR_SERVICE_REQUEST OSServiceRequest = {0}; + NTSTATUS Status; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceContext); + UNREFERENCED_PARAMETER(Priority); + UNREFERENCED_PARAMETER(Flags); + UNREFERENCED_PARAMETER(RequestHandle); + UNREFERENCED_PARAMETER(RequestContext); + + TemporaryBuffer = NULL; + + *BytesWritten = (ULONG_PTR)(Request->InputBufferSize * 2); + if (Request->OutputBufferSize < Request->InputBufferSize * 2) { + // + // STATUS_BUFFER_OVERFLOW must be used to make WDF forward the value of + // *BytesWritten to let Win32 caller know how large the output buffer + // should be. + // + Status = STATUS_BUFFER_OVERFLOW; + goto TestServiceTwiceReversedEnd; + } + + TemporaryBuffer = ExAllocatePoolWithTag(PagedPool, + (SIZE_T)Request->InputBufferSize, + 'PMET'); + + if (TemporaryBuffer == NULL) { + *BytesWritten = 0; + Status = STATUS_INSUFFICIENT_RESOURCES; + goto TestServiceTwiceReversedEnd; + } + + OSServiceRequest.FunctionCode = ECHO_SERVICE_REVERSE; + OSServiceRequest.InputBuffer = Request->InputBuffer; + OSServiceRequest.InputBufferSize = Request->InputBufferSize; + OSServiceRequest.OutputBuffer = TemporaryBuffer; + OSServiceRequest.OutputBufferSize = Request->InputBufferSize; + Status = TrSecureDeviceCallOSService(ServiceDevice, + &GUID_ECHO_SERVICE, + &OSServiceRequest, + &OSServiceBytesWritten); + + NT_ASSERT(Status != STATUS_PENDING); + NT_ASSERT(OSServiceBytesWritten == Request->InputBufferSize); + + if (!NT_SUCCESS(Status)) { + goto TestServiceTwiceReversedEnd; + } + + OSServiceRequest.FunctionCode = ECHO_SERVICE_REPEAT; + OSServiceRequest.InputBuffer = TemporaryBuffer; + OSServiceRequest.InputBufferSize = Request->InputBufferSize; + OSServiceRequest.OutputBuffer = Request->OutputBuffer; + OSServiceRequest.OutputBufferSize = Request->InputBufferSize * 2; + Status = TrSecureDeviceCallOSService(ServiceDevice, + &GUID_ECHO_SERVICE, + &OSServiceRequest, + &OSServiceBytesWritten); + + NT_ASSERT(Status != STATUS_PENDING); + NT_ASSERT(OSServiceBytesWritten == Request->InputBufferSize * 2); + +TestServiceTwiceReversedEnd: + if (TemporaryBuffer != NULL) { + ExFreePool(TemporaryBuffer); + } + + return Status; +} + +#pragma endregion + +_Use_decl_annotations_ +VOID +TestServiceCancelSecureServiceRequest( + WDFDEVICE ServiceDevice, + WDFOBJECT SessionContextObject, + PVOID RequestHandle, + PVOID* RequestContext + ) + +/*++ + + Routine Description: + + This routine is called to cancel a request made via a previous call to + TestServiceProcessSecureServiceRequest. Note that cancellation is + best-effort, and on success would result in STATUS_CANCELLED being + returned from the original request. + + Arguments: + + ServiceDevice - Supplies a handle to the service device object. + + SessionContext - Supplies a pointer to the context. + + RequestHandle - Supplies the request handle for which a cancellation + is being requested. + + RequestContext - Supplies a pointer to a PVOID variable where + additional information needed to cancel the request + set in TestServiceProcessSecureServiceRequest. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + BOOLEAN Stopped; + WDFTIMER Timer; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + UNREFERENCED_PARAMETER(SessionContextObject); + + if (RequestContext != NULL) { + // + // This request is the delayed completion request. Try to cancel the + // request by stopping the timer. + // + Timer = (WDFTIMER)*RequestContext; + Stopped = WdfTimerStop(Timer, FALSE); + if (Stopped) { + // + // Complete the request with cancelled status. + // + TrSecureDeviceCompleteAsyncRequest(RequestHandle, STATUS_CANCELLED, 0); + WdfObjectDelete(Timer); + + } else { + // + // The timer routine is already running or completed. The request + // is going to be completed by timer and work item callback. + // + } + } else { + // + // There's nothing we can do for other types of request. + // + } + + return; +} + +typedef struct _OTHERIO_DELAYED_COMPLETION_CONTEXT { + WDFTIMER Timer; +} OTHERIO_DELAYED_COMPLETION_CONTEXT, *POTHERIO_DELAYED_COMPLETION_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE(OTHERIO_DELAYED_COMPLETION_CONTEXT); + +EVT_WDF_REQUEST_CANCEL OtherIoDelayedCompletionCancel; +EVT_WDF_WORKITEM OtherIoDelayedCompletionWorkItemCallback; + +_Use_decl_annotations_ +VOID +OtherIoDelayedCompletionCancel( + WDFREQUEST Request + ) + +/*++ + + Routine Description: + + This routine is called to cancel delayed completion request in other + service I/O. Other I/O path uses WDF request objects as it is, so we + cannot reuse TestServiceCancelSecureServiceRequest. + + Arguments: + + Request - Supplies a handle to the request to be canceled. + + Return Value: + + None. + +--*/ + +{ + + POTHERIO_DELAYED_COMPLETION_CONTEXT RequestContext; + BOOLEAN Stopped; + WDFTIMER Timer; + + PAGED_CODE(); + + RequestContext = WdfObjectGet_OTHERIO_DELAYED_COMPLETION_CONTEXT(Request); + Timer = RequestContext->Timer; + Stopped = WdfTimerStop(Timer, FALSE); + if (Stopped) { + WdfRequestComplete(Request, STATUS_CANCELLED); + + // + // RequestContext is no more valid from here. + // + WdfObjectDelete(Timer); + } +} + +_Use_decl_annotations_ +VOID +OtherIoDelayedCompletionWorkItemCallback( + WDFWORKITEM WorkItem + ) + +/*++ + + Routine Description: + + This routine is enqueued from delayed completion timer callback. Since + a timer cannot be deleted inside its handler, it is deleted here + instead. Also the request is completed here. + + Arguments: + + WorkItem - Supplies a handle to this work item. + + Return Value: + + None. + +--*/ + +{ + PDELAYED_COMPLETION_TIMER_CONTEXT Context; + NTSTATUS Status; + WDFTIMER Timer; + + PAGED_CODE(); + + Timer = (WDFTIMER)WdfWorkItemGetParentObject(WorkItem); + Context = WdfObjectGet_DELAYED_COMPLETION_TIMER_CONTEXT(Timer); + *(PULONG)Context->OutputBuffer = 0x12345678; + + Status = WdfRequestUnmarkCancelable(Context->Request.Request); + if (Status != STATUS_CANCELLED) { + WdfRequestCompleteWithInformation(Context->Request.Request, + STATUS_SUCCESS, + sizeof(ULONG)); + } + + WdfObjectDelete(Timer); +} + +_Use_decl_annotations_ +VOID +TestServiceProcessOtherSecureServiceIo( + WDFDEVICE ServiceDevice, + WDFOBJECT SessionContextObject, + WDFREQUEST Request + ) + +/*++ + + Routine Description: + + This routine is called when an unrecognized IO request is made to a + secure service. This can be used to process private calls. + + Arguments: + + ServiceDevice - Supplies a handle to the service device object. + + SessionContext - Supplies a pointer to the context. + + Request - Supplies a pointer to the WDF request object. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + WDF_REQUEST_PARAMETERS Parameters; + NTSTATUS Status; + PVOID InputBuffer; + PVOID OutputBuffer; + ULONG_PTR BytesWritten; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(ServiceDevice); + UNREFERENCED_PARAMETER(SessionContextObject); + + BytesWritten = 0; + + WDF_REQUEST_PARAMETERS_INIT(&Parameters); + WdfRequestGetParameters(Request, &Parameters); + switch (Parameters.Parameters.DeviceIoControl.IoControlCode) { + case IOCTL_TEST_DELAYED_COMPLETION: + { + POTHERIO_DELAYED_COMPLETION_CONTEXT RequestContext; + WDF_OBJECT_ATTRIBUTES RequestAttributes; + WDFTIMER Timer; + WDF_OBJECT_ATTRIBUTES TimerAttributes; + WDF_TIMER_CONFIG TimerConfig; + PDELAYED_COMPLETION_TIMER_CONTEXT TimerContext; + WDF_OBJECT_ATTRIBUTES WorkItemAttributes; + WDF_WORKITEM_CONFIG WorkItemConfig; + + Status = WdfRequestRetrieveInputBuffer(Request, + sizeof(ULONG), + &InputBuffer, + NULL); + + if (!NT_SUCCESS(Status)) { + goto TestServiceProcessOtherSecureServiceIoEnd; + } + + Status = WdfRequestRetrieveOutputBuffer(Request, + sizeof(ULONG), + &OutputBuffer, + NULL); + + if (!NT_SUCCESS(Status)) { + BytesWritten = sizeof(ULONG); + if (Status == STATUS_BUFFER_TOO_SMALL) { + // + // STATUS_BUFFER_OVERFLOW must be used to make WDF forward the value of + // *BytesWritten to let Win32 caller know how large the output buffer + // should be. + // + Status = STATUS_BUFFER_OVERFLOW; + } + + goto TestServiceProcessOtherSecureServiceIoEnd; + } + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( + &RequestAttributes, + OTHERIO_DELAYED_COMPLETION_CONTEXT); + + Status = WdfObjectAllocateContext(Request, + &RequestAttributes, + &RequestContext); + + if (!NT_SUCCESS(Status)) { + goto TestServiceProcessOtherSecureServiceIoEnd; + } + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( + &TimerAttributes, + DELAYED_COMPLETION_TIMER_CONTEXT); + + WDF_TIMER_CONFIG_INIT(&TimerConfig, DelayedCompletionTimerCallback); + TimerAttributes.ExecutionLevel = WdfExecutionLevelDispatch; + TimerAttributes.ParentObject = ServiceDevice; + Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &Timer); + if (!NT_SUCCESS(Status)) { + goto TestServiceProcessOtherSecureServiceIoEnd; + } + + RequestContext->Timer =Timer; + + TimerContext = WdfObjectGet_DELAYED_COMPLETION_TIMER_CONTEXT(Timer); + TimerContext->Request.Request = Request; + TimerContext->OutputBuffer = TruncatePointer64(OutputBuffer); + + WDF_OBJECT_ATTRIBUTES_INIT(&WorkItemAttributes); + WDF_WORKITEM_CONFIG_INIT(&WorkItemConfig, + OtherIoDelayedCompletionWorkItemCallback); + + WorkItemAttributes.ParentObject = Timer; + Status = WdfWorkItemCreate(&WorkItemConfig, + &WorkItemAttributes, + &TimerContext->WorkItem); + + if (!NT_SUCCESS(Status)) { + WdfObjectDelete(Timer); + goto TestServiceProcessOtherSecureServiceIoEnd; + } + + // + // Set timer due after given delay + // + WdfTimerStart(Timer, + WDF_REL_TIMEOUT_IN_MS( + *(PULONG)TruncatePointer64(InputBuffer))); + + WdfRequestMarkCancelable(Request, OtherIoDelayedCompletionCancel); + return; + } + + default: + Status = STATUS_INVALID_PARAMETER; + break; + } + +TestServiceProcessOtherSecureServiceIoEnd: + WdfRequestCompleteWithInformation(Request, Status, BytesWritten); +} diff --git a/TrEE/Miniport/TrEEMiniportSample.inf b/TrEE/Miniport/TrEEMiniportSample.inf Binary files differnew file mode 100644 index 00000000..c1ba30a2 --- /dev/null +++ b/TrEE/Miniport/TrEEMiniportSample.inf diff --git a/TrEE/Miniport/TrEEMiniportSample.vcxproj b/TrEE/Miniport/TrEEMiniportSample.vcxproj new file mode 100644 index 00000000..0876f610 --- /dev/null +++ b/TrEE/Miniport/TrEEMiniportSample.vcxproj @@ -0,0 +1,241 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|Arm"> + <Configuration>Debug</Configuration> + <Platform>Arm</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Arm"> + <Configuration>Release</Configuration> + <Platform>Arm</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{3B965B2A-2DDB-4998-9077-9A498A025FA5}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <TargetName>TrEEMiniportSample</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <TargetName>TrEEMiniportSample</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>TrEEMiniportSample</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>TrEEMiniportSample</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>TrEEMiniportSample</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>TrEEMiniportSample</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\treeclxstub.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\treeclxstub.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\treeclxstub.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\treeclxstub.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\treeclxstub.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(DDK_LIB_PATH)\treeclxstub.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="sampleminiport.c" /> + <ClCompile Include="TestService.c" /> + <ResourceCompile Include="sampleminiport.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/TrEE/Miniport/TrEEMiniportSample.vcxproj.Filters b/TrEE/Miniport/TrEEMiniportSample.vcxproj.Filters new file mode 100644 index 00000000..7a7caa08 --- /dev/null +++ b/TrEE/Miniport/TrEEMiniportSample.vcxproj.Filters @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{369B4A00-B5B6-4158-886B-B676FE70F762}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{2B3E08A5-0B2C-479D-9F39-45BE166BF0E5}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{DCB257CE-46C6-4A90-809D-497094D76086}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{294EE363-C76D-48F8-AA82-1E45F3DE6D3D}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="sampleminiport.c"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="TestService.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="sampleminiport.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/TrEE/OSService/SampleOSService.c b/TrEE/OSService/SampleOSService.c new file mode 100644 index 00000000..b75cfb88 --- /dev/null +++ b/TrEE/OSService/SampleOSService.c @@ -0,0 +1,928 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + sampleservice.c + +Abstract: + + This file demonstrates a simple service plugin for the TREE class extension driver. + +Environment: + + Kernel mode + +--*/ + +#include <ntddk.h> +#include <wdf.h> +#include <ntstrsafe.h> +#include <initguid.h> +#include <wdmguid.h> +#include <TrustedRuntimeClx.h> +#include <SampleOSService.h> + +typedef enum _SAMPLE_SERVICE_TYPE { + SampleServiceEcho, + SampleServiceKernelMemory +} SAMPLE_SERVICE_TYPE; + +typedef struct _SAMPLE_SERVICE_FILE_CONTEXT { + SAMPLE_SERVICE_TYPE ServiceType; +} SAMPLE_SERVICE_FILE_CONTEXT, *PSAMPLE_SERVICE_FILE_CONTEXT; + +WDF_DECLARE_CONTEXT_TYPE(SAMPLE_SERVICE_FILE_CONTEXT); + +typedef +NTSTATUS +SAMPLE_SERVICE_REQUEST_HANDLER( + _In_ ULONG FunctionCode, + _In_reads_bytes_(InputBufferLength) PVOID InputBuffer, + _In_ size_t InputBufferLength, + _Out_writes_bytes_to_(OutputBufferLength, *BytesWritten) PVOID OutputBuffer, + _In_ size_t OutputBufferLength, + _Out_ size_t* BytesWritten + ); + +// +// Driver entry point +// + +DRIVER_INITIALIZE DriverEntry; + +// +// Device callbacks +// + +EVT_WDF_DRIVER_UNLOAD DriverUnload; +EVT_WDF_DRIVER_DEVICE_ADD SampleServiceEvtAddDevice; +EVT_WDF_DEVICE_D0_ENTRY SampleServiceEvtD0Entry; +EVT_WDF_DEVICE_D0_EXIT SampleServiceEvtD0Exit; +EVT_WDF_DEVICE_FILE_CREATE SampleServiceEvtCreateFile; +EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL SampleServiceEvtInternalIoctl; +EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL SampleServiceEvtQuery; +EVT_WDF_IO_QUEUE_IO_INTERNAL_DEVICE_CONTROL SampleServiceEvtExecute; +SAMPLE_SERVICE_REQUEST_HANDLER SampleServiceEchoHandler; +SAMPLE_SERVICE_REQUEST_HANDLER SampleServiceKernelMemoryHandler; + +#pragma alloc_text(INIT, DriverEntry) +#pragma alloc_text(PAGE, DriverUnload) +#pragma alloc_text(PAGE, SampleServiceEvtAddDevice) +#pragma alloc_text(PAGE, SampleServiceEvtCreateFile) +#pragma alloc_text(PAGE, SampleServiceEvtInternalIoctl) +#pragma alloc_text(PAGE, SampleServiceEvtQuery) +#pragma alloc_text(PAGE, SampleServiceEvtExecute) +#pragma alloc_text(PAGE, SampleServiceEchoHandler) +#pragma alloc_text(PAGE, SampleServiceKernelMemoryHandler) + +#pragma data_seg("PAGED") + +DECLARE_CONST_UNICODE_STRING(GUID_ECHO_SERVICE_STRING, + L"{33C7FF13-50B0-454A-8BEB-F73EED6C0AF9}"); + +DECLARE_CONST_UNICODE_STRING(GUID_KERNEL_MEMORY_SERVICE_STRING, + L"{D28698A4-3B07-4F34-B65E-AE3DA6ACF2AC}"); + +#pragma data_seg() + +volatile ULONG RandomSeed; + +_Use_decl_annotations_ +NTSTATUS +DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath + ) + +/*++ + + Routine Description: + + This is the initialization routine for the device driver. This routine + creates the driver object for the sample OS service. + + Arguments: + + DriverObject - Pointer to driver object created by the system. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + WDFDRIVER Driver; + WDF_DRIVER_CONFIG DriverConfig; + NTSTATUS Status; + + Driver = NULL; + + // + // Create the WDF driver object + // + + WDF_DRIVER_CONFIG_INIT(&DriverConfig, SampleServiceEvtAddDevice); + DriverConfig.EvtDriverUnload = DriverUnload; + DriverConfig.DriverPoolTag = 'SOMS'; + + Status = WdfDriverCreate(DriverObject, + RegistryPath, + WDF_NO_OBJECT_ATTRIBUTES, + &DriverConfig, + &Driver); + + if (!NT_SUCCESS(Status)) { + goto DriverEntryEnd; + } + +DriverEntryEnd: + return Status; +} + +_Use_decl_annotations_ +VOID +DriverUnload( + WDFDRIVER Driver + ) + +/*++ + + Routine Description: + + This is the cleanup function called when the driver is unloaded. + + Arguments: + + Driver - Supplies a handle to WDFDRIVER object created in DriverEntry. + + Return Value: + + None. + +--*/ + +{ + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Driver); +} + +_Use_decl_annotations_ +NTSTATUS +SampleServiceEvtAddDevice( + WDFDRIVER Driver, + PWDFDEVICE_INIT DeviceInit + ) + +/*++ + + Routine Description: + + This routine is called when the driver is being attached to a specific + device. + + Arguments: + + Driver - Supplies a handle to the framework driver object. + + DeviceInit - Supplies a pointer to the device initialization parameters. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + WDFDEVICE Device; + WDF_FILEOBJECT_CONFIG FileConfig; + WDF_OBJECT_ATTRIBUTES ObjectAttributes; + WDF_PNPPOWER_EVENT_CALLBACKS PowerCallbacks; + WDFQUEUE Queue; + WDF_IO_QUEUE_CONFIG QueueConfig; + NTSTATUS Status; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Driver); + + WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered); + WdfDeviceInitSetDeviceType(DeviceInit, 32999); + WdfDeviceInitSetPowerNotPageable(DeviceInit); + + // + // Initialize file context and register file creation handler + // + + WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ObjectAttributes, + SAMPLE_SERVICE_FILE_CONTEXT); + + ObjectAttributes.ExecutionLevel = WdfExecutionLevelPassive; + WDF_FILEOBJECT_CONFIG_INIT(&FileConfig, + &SampleServiceEvtCreateFile, + WDF_NO_EVENT_CALLBACK, + WDF_NO_EVENT_CALLBACK); + + FileConfig.FileObjectClass = WdfFileObjectWdfCanUseFsContext; + WdfDeviceInitSetFileObjectConfig(DeviceInit, + &FileConfig, + &ObjectAttributes); + + // + // Device interface will be enabled/disabled in these callbacks + // + + WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PowerCallbacks); + PowerCallbacks.EvtDeviceD0Entry = SampleServiceEvtD0Entry; + PowerCallbacks.EvtDeviceD0Exit = SampleServiceEvtD0Exit; + + Status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &Device); + if (!NT_SUCCESS(Status)) { + goto SampleServiceEvtAddDeviceEnd; + } + + // + // Create a default queue to process requests + // + + WDF_OBJECT_ATTRIBUTES_INIT(&ObjectAttributes); + ObjectAttributes.ExecutionLevel = WdfExecutionLevelPassive; + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&QueueConfig, + WdfIoQueueDispatchParallel); + + QueueConfig.EvtIoInternalDeviceControl = SampleServiceEvtInternalIoctl; + Status = WdfIoQueueCreate(Device, + &QueueConfig, + &ObjectAttributes, + &Queue); + + if (!NT_SUCCESS(Status)) { + goto SampleServiceEvtAddDeviceEnd; + } + + // + // This tells TrEE driver that this OS service is available. Two services + // are served by this device, and they are distinguished by filename. + // + Status = WdfDeviceCreateDeviceInterface(Device, + &GUID_ECHO_SERVICE, + &GUID_ECHO_SERVICE_STRING); + + if (!NT_SUCCESS(Status)) { + goto SampleServiceEvtAddDeviceEnd; + } + + Status = WdfDeviceCreateDeviceInterface(Device, + &GUID_KERNEL_MEMORY_SERVICE, + &GUID_KERNEL_MEMORY_SERVICE_STRING); + + if (!NT_SUCCESS(Status)) { + goto SampleServiceEvtAddDeviceEnd; + } + +SampleServiceEvtAddDeviceEnd: + return Status; +} + +_Use_decl_annotations_ +NTSTATUS +SampleServiceEvtD0Entry( + WDFDEVICE Device, + WDF_POWER_DEVICE_STATE PreviousState + ) + +/*++ + + Routine Description: + + This routine is called when the device is coming back from a lower + power state to D0. + + Arguments: + + Device - Supplies a handle to device object. + + PreviousState - Supplies the power state the device was in. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + UNREFERENCED_PARAMETER(PreviousState); + + RandomSeed = (ULONG)(KeQueryInterruptTime() >> 8); + + WdfDeviceSetDeviceInterfaceState(Device, + &GUID_ECHO_SERVICE, + &GUID_ECHO_SERVICE_STRING, + TRUE); + + WdfDeviceSetDeviceInterfaceState(Device, + &GUID_KERNEL_MEMORY_SERVICE, + &GUID_KERNEL_MEMORY_SERVICE_STRING, + TRUE); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +NTSTATUS +SampleServiceEvtD0Exit( + WDFDEVICE Device, + WDF_POWER_DEVICE_STATE TargetState + ) + +/*++ + + Routine Description: + + This routine is called when the device is going down to a lower + power state. + + Arguments: + + Device - Supplies a handle to device object. + + PreviousState - Supplies the power state the device is going to. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + UNREFERENCED_PARAMETER(TargetState); + + WdfDeviceSetDeviceInterfaceState(Device, + &GUID_ECHO_SERVICE, + &GUID_ECHO_SERVICE_STRING, + FALSE); + + WdfDeviceSetDeviceInterfaceState(Device, + &GUID_KERNEL_MEMORY_SERVICE, + &GUID_KERNEL_MEMORY_SERVICE_STRING, + FALSE); + + return STATUS_SUCCESS; +} + +_Use_decl_annotations_ +VOID +SampleServiceEvtCreateFile( + WDFDEVICE Device, + WDFREQUEST Request, + WDFFILEOBJECT FileObject + ) + +/*++ + + Routine Description: + + This routine is called when the device is coming back from a lower + power state to D0. + + Arguments: + + Device - Supplies a handle to device object. + + PreviousState - Supplies the power state the device was in. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + PSAMPLE_SERVICE_FILE_CONTEXT FileContext; + UNICODE_STRING Filename; + NTSTATUS Status; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Device); + + FileContext = WdfObjectGet_SAMPLE_SERVICE_FILE_CONTEXT(FileObject); + Filename = *WdfFileObjectGetFileName(FileObject); + if (Filename.Buffer[0] == L'\\') { + ++Filename.Buffer; + Filename.Length -= sizeof(WCHAR); + Filename.MaximumLength -= sizeof(WCHAR); + } + + // + // Record what service is this create request is for + // + if (RtlCompareUnicodeString(&Filename, + &GUID_ECHO_SERVICE_STRING, + TRUE) == 0) { + + FileContext->ServiceType = SampleServiceEcho; + Status = STATUS_SUCCESS; + + } else if (RtlCompareUnicodeString(&Filename, + &GUID_KERNEL_MEMORY_SERVICE_STRING, + TRUE) == 0) { + + FileContext->ServiceType = SampleServiceKernelMemory; + Status = STATUS_SUCCESS; + + } else { + + Status = STATUS_OBJECT_NAME_NOT_FOUND; + } + + WdfRequestComplete(Request, Status); +} + +_Use_decl_annotations_ +VOID +SampleServiceEvtInternalIoctl( + WDFQUEUE Queue, + WDFREQUEST Request, + size_t OutputBufferLength, + size_t InputBufferLength, + ULONG IoControlCode + ) + +/*++ + + Routine Description: + + This routine is called when the device receives an OS service request + from TrEE class extension, which is sent as an internal device control + request. + + Arguments: + + Queue - Supplies a handle to the framework queue object that is + associated with the I/O request. + + Request - Supplies a handle to a framework request object. + + OutputBufferLength - Supplies the length of the request's output + buffer, if an output buffer is available. + + InputBufferLength - Supplies the length of the request's input buffer, + if an input buffer is available. + + IoControlCode - Supplies the driver-defined or system-defined I/O + control code (IOCTL) that is associated with the + request. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + PAGED_CODE(); + + switch (IoControlCode) { + case IOCTL_TR_SERVICE_QUERY: + SampleServiceEvtQuery(Queue, + Request, + OutputBufferLength, + InputBufferLength, + IoControlCode); + + return; + + case IOCTL_TR_EXECUTE_FUNCTION: + SampleServiceEvtExecute(Queue, + Request, + OutputBufferLength, + InputBufferLength, + IoControlCode); + + return; + + default: + WdfRequestComplete(Request, STATUS_INVALID_PARAMETER); + } +} + +_Use_decl_annotations_ +VOID +SampleServiceEvtQuery( + WDFQUEUE Queue, + WDFREQUEST Request, + size_t OutputBufferLength, + size_t InputBufferLength, + ULONG IoControlCode + ) + +/*++ + + Routine Description: + + This routine is called when the device receives a query request from + TrEE class extension. OS service provider fills up information about + the service. + + Arguments: + + Queue - Supplies a handle to the framework queue object that is + associated with the I/O request. + + Request - Supplies a handle to a framework request object. + + OutputBufferLength - Supplies the length of the request's output + buffer, if an output buffer is available. + + InputBufferLength - Supplies the length of the request's input buffer, + if an input buffer is available. + + IoControlCode - Supplies the driver-defined or system-defined I/O + control code (IOCTL) that is associated with the + request. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + PSAMPLE_SERVICE_FILE_CONTEXT FileContext; + WDFFILEOBJECT FileObject; + PTR_SERVICE_INFORMATION ServiceInformation; + NTSTATUS Status; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Queue); + UNREFERENCED_PARAMETER(InputBufferLength); + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(IoControlCode); + + FileObject = WdfRequestGetFileObject(Request); + FileContext = WdfObjectGet_SAMPLE_SERVICE_FILE_CONTEXT(FileObject); + Status = WdfRequestRetrieveOutputBuffer(Request, + sizeof(TR_SERVICE_INFORMATION), + (PVOID*)&ServiceInformation, + NULL); + + if (!NT_SUCCESS(Status)) { + goto SampleServiceEvtInternalQueryFail; + } + + ServiceInformation->InterfaceVersion = 1; + ServiceInformation->ServiceMajorVersion = 1; + ServiceInformation->ServiceMinorVersion = 1; + WdfRequestCompleteWithInformation(Request, + STATUS_SUCCESS, + sizeof(TR_SERVICE_INFORMATION)); + + return; + +SampleServiceEvtInternalQueryFail: + WdfRequestComplete(Request, Status); +} + +_Use_decl_annotations_ +VOID +SampleServiceEvtExecute( + WDFQUEUE Queue, + WDFREQUEST Request, + size_t OutputBufferLength, + size_t InputBufferLength, + ULONG IoControlCode + ) + +/*++ + + Routine Description: + + This routine is called when the device receives an OS service execute + request from TrEE miniport. + + Arguments: + + Queue - Supplies a handle to the framework queue object that is + associated with the I/O request. + + Request - Supplies a handle to a framework request object. + + OutputBufferLength - Supplies the length of the request's output + buffer, if an output buffer is available. + + InputBufferLength - Supplies the length of the request's input buffer, + if an input buffer is available. + + IoControlCode - Supplies the driver-defined or system-defined I/O + control code (IOCTL) that is associated with the + request. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + size_t BytesWritten; + PSAMPLE_SERVICE_FILE_CONTEXT FileContext; + WDFFILEOBJECT FileObject; + PTR_SERVICE_REQUEST ServiceRequest; + PTR_SERVICE_REQUEST_RESPONSE ServiceResponse; + NTSTATUS Status; + + PAGED_CODE(); + + UNREFERENCED_PARAMETER(Queue); + UNREFERENCED_PARAMETER(InputBufferLength); + UNREFERENCED_PARAMETER(OutputBufferLength); + UNREFERENCED_PARAMETER(IoControlCode); + + FileObject = WdfRequestGetFileObject(Request); + FileContext = WdfObjectGet_SAMPLE_SERVICE_FILE_CONTEXT(FileObject); + Status = WdfRequestRetrieveInputBuffer(Request, + sizeof(TR_SERVICE_REQUEST), + (PVOID*)&ServiceRequest, + NULL); + + if (!NT_SUCCESS(Status)) { + goto SampleServiceEvtInternalIoctlFail; + } + + Status = WdfRequestRetrieveOutputBuffer(Request, + sizeof(TR_SERVICE_REQUEST_RESPONSE), + (PVOID*)&ServiceResponse, + NULL); + + if (!NT_SUCCESS(Status)) { + goto SampleServiceEvtInternalIoctlFail; + } + + switch (FileContext->ServiceType) { + case SampleServiceEcho: + Status = SampleServiceEchoHandler(ServiceRequest->FunctionCode, + ServiceRequest->InputBuffer, + (size_t)ServiceRequest->InputBufferSize, + ServiceRequest->OutputBuffer, + (size_t)ServiceRequest->OutputBufferSize, + &BytesWritten); + + break; + + case SampleServiceKernelMemory: + Status = SampleServiceKernelMemoryHandler(ServiceRequest->FunctionCode, + ServiceRequest->InputBuffer, + (size_t)ServiceRequest->InputBufferSize, + ServiceRequest->OutputBuffer, + (size_t)ServiceRequest->OutputBufferSize, + &BytesWritten); + break; + + default: + // + // Shouldn't reach here + // + NT_ASSERT(FALSE); + + Status = STATUS_INVALID_PARAMETER; + goto SampleServiceEvtInternalIoctlFail; + } + + // + // Bytes written to the output buffer of the service request goes into here + // + ServiceResponse->BytesWritten = BytesWritten; + + // + // Number of bytes written to WDF request's output buffer is always + // sizeof(TR_SERVICE_REQUEST_RESPONSE) + // + WdfRequestCompleteWithInformation(Request, + Status, + sizeof(TR_SERVICE_REQUEST_RESPONSE)); + + return; + +SampleServiceEvtInternalIoctlFail: + WdfRequestComplete(Request, Status); +} + +_Use_decl_annotations_ +NTSTATUS +SampleServiceEchoHandler( + ULONG FunctionCode, + PVOID InputBuffer, + size_t InputBufferLength, + PVOID OutputBuffer, + size_t OutputBufferLength, + size_t* BytesWritten + ) + +/*++ + + Routine Description: + + This routine handles OS service requests sent to echo service. + + Arguments: + + FunctionCode - Supplies the function code of the request. + + InputBuffer - Supplies a pointer to the request's input buffer, + if an input buffer is available. + + InputBufferLength - Supplies the length of the request's input buffer, + if an input buffer is available. + + OutputBuffer - Supplies a pointer to the request's output buffer, + if an output buffer is available. + + OutputBufferLength - Supplies the length of the request's output + buffer, if an output buffer is available. + + BytesWritten - Supplies a pointer to the variable where number of bytes + actually written to the output buffer. In case the + output buffer is too small to contain all the data, the + required size will be written. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + ULONG Index; + NTSTATUS Status; + + PAGED_CODE(); + + switch (FunctionCode) { + case ECHO_SERVICE_ECHO: + if (OutputBufferLength < InputBufferLength) { + *BytesWritten = InputBufferLength; + Status = STATUS_BUFFER_OVERFLOW; + goto SampleServiceEchoHandlerEnd; + } + + RtlCopyMemory(OutputBuffer, InputBuffer, InputBufferLength); + *BytesWritten = InputBufferLength; + Status = STATUS_SUCCESS; + break; + + case ECHO_SERVICE_REPEAT: + *BytesWritten = 0; + while (OutputBufferLength >= InputBufferLength) { + RtlCopyMemory(OutputBuffer, InputBuffer, InputBufferLength); + + OutputBuffer = (PVOID)(((ULONG_PTR)OutputBuffer) + InputBufferLength); + OutputBufferLength -= InputBufferLength; + *BytesWritten += InputBufferLength; + } + + Status = STATUS_SUCCESS; + break; + + case ECHO_SERVICE_REVERSE: + if (OutputBufferLength < InputBufferLength) { + Status = STATUS_BUFFER_OVERFLOW; + goto SampleServiceEchoHandlerEnd; + } + + for (Index = 0; Index < InputBufferLength; ++Index) { + ((PUCHAR)OutputBuffer)[Index] = ((PUCHAR)InputBuffer)[InputBufferLength - Index - 1]; + } + + *BytesWritten = InputBufferLength; + Status = STATUS_SUCCESS; + break; + + default: + return STATUS_INVALID_PARAMETER; + } + +SampleServiceEchoHandlerEnd: + return Status; +} + +UCHAR ScratchMemory[1024]; + +NTSTATUS +SampleServiceKernelMemoryHandler( + _In_ ULONG FunctionCode, + _In_reads_bytes_(InputBufferLength) PVOID InputBuffer, + _In_ size_t InputBufferLength, + _Out_writes_bytes_to_(OuputBufferLength, *BytesWritten) PVOID OutputBuffer, + _In_ size_t OutputBufferLength, + _Out_ size_t* BytesWritten + ) + +/*++ + + Routine Description: + + This routine handles OS service requests sent to kernel memory service. + + Arguments: + + FunctionCode - Supplies the function code of the request. + + InputBuffer - Supplies a pointer to the request's input buffer, + if an input buffer is available. + + InputBufferLength - Supplies the length of the request's input buffer, + if an input buffer is available. + + OutputBuffer - Supplies a pointer to the request's output buffer, + if an output buffer is available. + + OutputBufferLength - Supplies the length of the request's output + buffer, if an output buffer is available. + + BytesWritten - Supplies a pointer to the variable where number of bytes + actually written to the output buffer. In case the + output buffer is too small to contain all the data, the + required size will be written. + + Return Value: + + NTSTATUS code. + +--*/ + +{ + + UCHAR PreviousValue; + NTSTATUS Status; + PKERNEL_MEMORY_SAFE_RANGE SafeRange; + PKERNEL_MEMORY_WRITE_BYTE WriteByte; + + PAGED_CODE(); + + switch (FunctionCode) { + case KERNEL_MEMORY_SERVICE_GET_SAFE_RANGE: + if (OutputBufferLength < sizeof(KERNEL_MEMORY_SAFE_RANGE)) { + *BytesWritten = sizeof(KERNEL_MEMORY_SAFE_RANGE); + Status = STATUS_BUFFER_OVERFLOW; + goto SampleServiceKernelMemoryHandlerEnd; + } + + SafeRange = (PKERNEL_MEMORY_SAFE_RANGE)OutputBuffer; + SafeRange->Base = (ULONG64)(ULONG_PTR)&ScratchMemory; + SafeRange->Length = sizeof(ScratchMemory); + *BytesWritten = sizeof(KERNEL_MEMORY_SAFE_RANGE); + Status = STATUS_SUCCESS; + break; + + case KERNEL_MEMORY_SERVICE_WRITE_BYTE: + if (InputBufferLength < sizeof(KERNEL_MEMORY_WRITE_BYTE)) { + Status = STATUS_INVALID_PARAMETER; + goto SampleServiceKernelMemoryHandlerEnd; + } + + if (OutputBufferLength < sizeof(UCHAR)) { + *BytesWritten = sizeof(UCHAR); + Status = STATUS_BUFFER_OVERFLOW; + goto SampleServiceKernelMemoryHandlerEnd; + } + + WriteByte = (PKERNEL_MEMORY_WRITE_BYTE)InputBuffer; + PreviousValue = *(PUCHAR)(ULONG_PTR)WriteByte->Address; + *(PUCHAR)(ULONG_PTR)WriteByte->Address = WriteByte->Value; + Status = STATUS_SUCCESS; + break; + + case KERNEL_MEMORY_SERVICE_READ_BYTE: + if (InputBufferLength < sizeof(ULONG64)) { + Status = STATUS_INVALID_PARAMETER; + goto SampleServiceKernelMemoryHandlerEnd; + } + + if (OutputBufferLength < sizeof(UCHAR)) { + *BytesWritten = sizeof(UCHAR); + Status = STATUS_BUFFER_OVERFLOW; + goto SampleServiceKernelMemoryHandlerEnd; + } + + *(PUCHAR)OutputBuffer = *(PUCHAR)(ULONG_PTR)*(PULONG64)InputBuffer; + Status = STATUS_SUCCESS; + break; + + default: + return STATUS_INVALID_PARAMETER; + } + +SampleServiceKernelMemoryHandlerEnd: + return Status; +} diff --git a/TrEE/OSService/SampleOSService.rc b/TrEE/OSService/SampleOSService.rc new file mode 100644 index 00000000..55dd3bef --- /dev/null +++ b/TrEE/OSService/SampleOSService.rc @@ -0,0 +1,14 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// +#include <windows.h> +#include <ntverp.h> + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_SYSTEM +#define VER_FILEDESCRIPTION_STR "Sample TREE Service Driver" +#define VER_INTERNALNAME_STR "TrEEOSServiceSample.sys" + +#include "common.ver" + + diff --git a/TrEE/OSService/TrEEOSServiceSample.inf b/TrEE/OSService/TrEEOSServiceSample.inf Binary files differnew file mode 100644 index 00000000..e14149b9 --- /dev/null +++ b/TrEE/OSService/TrEEOSServiceSample.inf diff --git a/TrEE/OSService/TrEEOSServiceSample.vcxproj b/TrEE/OSService/TrEEOSServiceSample.vcxproj new file mode 100644 index 00000000..d3afa66a --- /dev/null +++ b/TrEE/OSService/TrEEOSServiceSample.vcxproj @@ -0,0 +1,222 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|Arm"> + <Configuration>Debug</Configuration> + <Platform>Arm</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Arm"> + <Configuration>Release</Configuration> + <Platform>Arm</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{7661C397-614D-4562-9CC7-6178B246DB17}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <KMDF_VERSION_MAJOR>1</KMDF_VERSION_MAJOR> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{CF6545FF-8EA5-4A78-8776-59E492F8C276}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>KMDF</DriverType> + <PlatformToolset>WindowsKernelModeDriver10.0</PlatformToolset> + <ConfigurationType>Driver</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <TargetName>TrEEOSServiceSample</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <TargetName>TrEEOSServiceSample</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>TrEEOSServiceSample</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>TrEEOSServiceSample</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>TrEEOSServiceSample</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>TrEEOSServiceSample</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <ClCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="sampleosservice.c" /> + <ResourceCompile Include="sampleosservice.rc" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/TrEE/OSService/TrEEOSServiceSample.vcxproj.Filters b/TrEE/OSService/TrEEOSServiceSample.vcxproj.Filters new file mode 100644 index 00000000..61542807 --- /dev/null +++ b/TrEE/OSService/TrEEOSServiceSample.vcxproj.Filters @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{AB2DD0E2-5CC9-4127-B1D4-1DBD5877932E}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{A955E202-DE30-4FFA-B5B6-8149773C178D}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{A338803C-3BF5-4F17-BD90-3269E83E92C5}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{FFB2F3A5-5400-4D41-9B69-7A1B94C27388}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="sampleosservice.c"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ResourceCompile Include="sampleosservice.rc"> + <Filter>Resource Files</Filter> + </ResourceCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/TrEE/Test/SampleTest.cpp b/TrEE/Test/SampleTest.cpp new file mode 100644 index 00000000..89bd9471 --- /dev/null +++ b/TrEE/Test/SampleTest.cpp @@ -0,0 +1,836 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + sampletest.cpp + +Abstract: + + This file demonstrates I/O to TrEE secure services. + +Environment: + + User mode + +--*/ + +#pragma warning(disable:4127) + +#include <initguid.h> +#include <ntstatus.h> +#define WIN32_NO_STATUS +#include <Windows.h> +#include <winioctl.h> +#include <cfgmgr32.h> +#include <stdio.h> +#include <stdlib.h> + +typedef LONG NTSTATUS; + +#include <TrustedRT.h> +#include <SampleSecureService.h> +#include <SampleOSService.h> + +#define TEST_ASSERT(_Assertion, _Message, ...) do { \ + if (!(_Assertion)) { \ + wprintf(_Message L"\n", __VA_ARGS__); \ + Success = FALSE; \ + goto End; \ + }\ + } while (0) + +#define TEST_COMMENT(_Message, ...) wprintf(_Message L"\n", __VA_ARGS__) + +#define TEST_STRING L"This is a test string.\n" + +HANDLE +OpenServiceHandleByInterface( + _In_ LPCGUID ServiceGuid + ) + +/*++ + +Routine Description: + + This routine opens a handle to the service device specified the GUID using + PnP device interface. The device interface gives a symbolic link to the + service device that can be fed to CreateFile function. + +Arguments: + + ServiceGuid - Supplies the GUID of the service to open. + +Return Value: + + HANDLE to the secure service, NULL if error occurred. + +--*/ + +{ + CONFIGRET ConfigRet; + WCHAR InterfaceSymlink[1024]; + HANDLE ServiceHandle; + BOOL Success; + + ServiceHandle = INVALID_HANDLE_VALUE; + ConfigRet = CM_Get_Device_Interface_ListW( + const_cast<LPGUID>(ServiceGuid), + NULL, + InterfaceSymlink, + _countof(InterfaceSymlink), + CM_GET_DEVICE_INTERFACE_LIST_PRESENT + ); + + TEST_ASSERT(ConfigRet == CR_SUCCESS, L"GetDeviceInterface failed, configret=%d", ConfigRet); + TEST_COMMENT(L"Symlink=%ws", InterfaceSymlink); + + ServiceHandle = CreateFileW( + InterfaceSymlink, + FILE_READ_DATA | FILE_WRITE_DATA, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + + TEST_ASSERT(ServiceHandle != INVALID_HANDLE_VALUE, L"Service open failed"); + +End: + return ServiceHandle; +} + +HANDLE +OpenServiceHandleByFilename( + _In_ LPCGUID ServiceGuid + ) + +/*++ + +Routine Description: + + This routine opens a handle to the service device specified the GUID using + TrEE-namespace filename. The filename has format \\.\WindowsTrustedRT\{GUID}. + The filename is parsed in IRP_MJ_CREATE handler in TrEE class extension. + Then request is forwarded to corresponding service device. + +Arguments: + + ServiceGuid - Supplies the GUID of the service to open. + +Return Value: + + HANDLE to the secure service, NULL if error occurred. + +--*/ + +{ + WCHAR InterfaceGuid[1024]; + WCHAR InterfaceSymlink[1024]; + HANDLE ServiceHandle; + BOOL Success; + + ServiceHandle = INVALID_HANDLE_VALUE; + swprintf_s(InterfaceGuid, + L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", + ServiceGuid->Data1, + ServiceGuid->Data2, + ServiceGuid->Data3, + ServiceGuid->Data4[0], + ServiceGuid->Data4[1], + ServiceGuid->Data4[2], + ServiceGuid->Data4[3], + ServiceGuid->Data4[4], + ServiceGuid->Data4[5], + ServiceGuid->Data4[6], + ServiceGuid->Data4[7] + ); + + swprintf_s(InterfaceSymlink, L"\\\\.\\WindowsTrustedRT\\%ws", InterfaceGuid); + + TEST_COMMENT(L"Guid=%ws", InterfaceGuid); + TEST_COMMENT(L"Symlink=%ws", InterfaceSymlink); + + ServiceHandle = CreateFileW( + InterfaceSymlink, + FILE_READ_DATA | FILE_WRITE_DATA, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + + TEST_ASSERT(ServiceHandle != INVALID_HANDLE_VALUE, L"Service open failed"); + +End: + return ServiceHandle; +} + +BOOL +CallTrEEService( + _In_ HANDLE ServiceHandle, + _In_ ULONG FunctionCode, + _In_reads_bytes_(InputBufferLength) PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_writes_bytes_to_(OutputBufferLength, *BytesWritten) PVOID OutputBuffer, + _In_ ULONG OutputBufferLength, + _Out_ PULONG BytesWritten + ) + +/*++ + +Routine Description: + + This routine is a wrapper for DeviceIoControl to conveniently send TrEE + secure function requests. Input and output buffers are packed to TrEE + request structs and number of bytes written is unpacked from response + struct. + +Arguments: + + ServiceHandle - Supplies a handle to the secure service on which the + request is to be sent. + + FunctionCode - Supplies the function code of the request. + + InputBuffer - Supplies a pointer to the input buffer that contains the data + required to perform the operation + + InputBufferLength - Supplies the size of the input buffer, in bytes. + + OutputBuffer - Supplies a pointer to the output buffer that is to receive + the data returned by the operation. + + OutputBufferLength - Supplies the size of the output buffer, in bytes. + + BytesWritten - Supplies a pointer to a variable that receives the size of + the data stored in the output buffer, in bytes. + +Return Value: + + TRUE if successful. + +--*/ + +{ + TR_SERVICE_REQUEST Request; + TR_SERVICE_REQUEST_RESPONSE Response; + BOOL Success; + ULONG ResponseBytesWritten; + + Request.FunctionCode = FunctionCode; + Request.InputBuffer = InputBuffer; + Request.InputBufferSize = InputBufferLength; + Request.OutputBuffer = OutputBuffer; + Request.OutputBufferSize = OutputBufferLength; + + Success = DeviceIoControl(ServiceHandle, + IOCTL_TR_EXECUTE_FUNCTION, + &Request, + sizeof(Request), + &Response, + sizeof(Response), + &ResponseBytesWritten, + NULL); + + if (ResponseBytesWritten >= sizeof(Response)) { + *BytesWritten = (ULONG)Response.BytesWritten; + return Success; + + } else { + + *BytesWritten = 0; + return FALSE; + } +} + +typedef struct _ASYNC_TREE_CALL { + OVERLAPPED Overlapped; + TR_SERVICE_REQUEST Request; + TR_SERVICE_REQUEST_RESPONSE Response; +} ASYNC_TREE_CALL, *PASYNC_TREE_CALL; + +BOOL +CallTrEEServiceEx( + _In_ HANDLE ServiceHandle, + _In_ ULONG FunctionCode, + _In_reads_bytes_(InputBufferLength) PVOID InputBuffer, + _In_ ULONG InputBufferLength, + _Out_writes_bytes_to_(OutputBufferLength, *BytesWritten) PVOID OutputBuffer, + _In_ ULONG OutputBufferLength, + _Out_ PULONG BytesWritten, + _Deref_out_ PASYNC_TREE_CALL* pAsyncContext + ) + +/*++ + +Routine Description: + + This routine is a wrapper for DeviceIoControl similar to CallTrEEService, + except that it performs asynchronous I/O. + +Arguments: + + ServiceHandle - Supplies a handle to the secure service on which the + request is to be sent. The handle must have been opened + with FILE_FLAG_OVERLAPPED flag. + + FunctionCode - Supplies the function code of the request. + + InputBuffer - Supplies a pointer to the input buffer that contains the data + required to perform the operation + + InputBufferLength - Supplies the size of the input buffer, in bytes. + + OutputBuffer - Supplies a pointer to the output buffer that is to receive + the data returned by the operation. + + OutputBufferLength - Supplies the size of the output buffer, in bytes. + + BytesWritten - Supplies a pointer to a variable that receives the size of + the data stored in the output buffer, in bytes. + + pAsyncContext - Supplies a pointer to a variable that receives the pointer + to ASYNC_TREE_CALL which contains necessary input and + output buffer for the request and an OVERLAPPED struct to + track the progress of the request. + +Return Value: + + TRUE if the operation was completed synchronously and successfully. + + FALSE if the operation is undergoing asynchronously or has failed. Check + the value of GetLastError to distinguish the case. + +--*/ + +{ + PASYNC_TREE_CALL AsyncContext; + BOOL Success; + ULONG ResponseBytesWritten; + + AsyncContext = new ASYNC_TREE_CALL; + memset(AsyncContext, 0, sizeof(ASYNC_TREE_CALL)); + AsyncContext->Request.FunctionCode = FunctionCode; + AsyncContext->Request.InputBuffer = InputBuffer; + AsyncContext->Request.InputBufferSize = InputBufferLength; + AsyncContext->Request.OutputBuffer = OutputBuffer; + AsyncContext->Request.OutputBufferSize = OutputBufferLength; + AsyncContext->Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + *pAsyncContext = AsyncContext; + + Success = DeviceIoControl(ServiceHandle, + IOCTL_TR_EXECUTE_FUNCTION, + &AsyncContext->Request, + sizeof(TR_SERVICE_REQUEST), + &AsyncContext->Response, + sizeof(TR_SERVICE_REQUEST_RESPONSE), + &ResponseBytesWritten, + &AsyncContext->Overlapped); + + if (ResponseBytesWritten >= sizeof(TR_SERVICE_REQUEST_RESPONSE)) { + *BytesWritten = (ULONG)AsyncContext->Response.BytesWritten; + return Success; + + } else { + + *BytesWritten = 0; + return FALSE; + } +} + +VOID +CleanupAsyncTrEECallContext( + _In_ PASYNC_TREE_CALL AsyncContext + ) + +/*++ + +Routine Description: + + This routine cleans up the memory and resources used by ASYNC_TREE_CALL + struct returned from CallTrEEServiceEx function. + +Arguments: + + AsyncContext - Supplies a pointer to ASYNC_TREE_CALL struct returned from + CallTrEEServiceEx function. + +Return Value: + + None. + +--*/ + +{ + CloseHandle(AsyncContext->Overlapped.hEvent); + delete AsyncContext; +} + +int +__cdecl +wmain( + int argc, + const wchar_t** argv + ) +{ + DWORD BytesWritten; + HANDLE TestServiceHandle; + HANDLE Test2ServiceHandle; + HANDLE MasterDeviceHandle; + BOOL Success; + ULONG64 TestFlag; + + Success = TRUE; + TestServiceHandle = INVALID_HANDLE_VALUE; + Test2ServiceHandle = INVALID_HANDLE_VALUE; + MasterDeviceHandle = INVALID_HANDLE_VALUE; + + if (argc > 1) { + swscanf_s(argv[1], L"%I64x", &TestFlag); + + } else { + + TestFlag = ~0UI64; + } + + // + // Open the service using TrEE-namespace filename. + // + TestServiceHandle = OpenServiceHandleByFilename(&GUID_SAMPLE_TEST_SERVICE); + TEST_ASSERT(TestServiceHandle != INVALID_HANDLE_VALUE, L"Test service open failed"); + + if ((TestFlag & 0x1) != 0) { + TEST_COMMENT(L"\n::::: TEST_SERVICE_HELLO_WORLD"); + + wchar_t* HelloWorld; + + // + // First call the service with no output buffer to detect how large + // output buffer should be. + // + Success = CallTrEEService(TestServiceHandle, + TEST_SERVICE_HELLO_WORLD, + NULL, 0, + NULL, 0, + &BytesWritten); + + TEST_ASSERT(!Success, L"CallTrEEService (get size) unexpectedly succeeded"); + TEST_ASSERT(BytesWritten > 0, L"CallTrEEService (get size) returned 0 bytes required size"); + + // + // The request fails, but BytesWritten variable will contain the + // required size of output buffer. + // + HelloWorld = (wchar_t*)malloc(BytesWritten); + Success = CallTrEEService(TestServiceHandle, + TEST_SERVICE_HELLO_WORLD, + NULL, 0, + HelloWorld, BytesWritten, + &BytesWritten); + + TEST_ASSERT(Success, L"CallTrEEService (read data) failed (err=%d)", GetLastError()); + TEST_ASSERT(BytesWritten > 0, L"CallTrEEService (read data) returned 0 bytes written"); + + // + // The service will return classic "Hello, world!" message. + // + TEST_COMMENT(L"TEST_SERVICE_HELLO_WORLD returned: %ws", HelloWorld); + } + + if ((TestFlag & 0x2) != 0) { + TEST_COMMENT(L"\n::::: TEST_SERVICE_GET_INTERRUPT_TIME"); + + ULONG64 InterruptTime; + + Success = CallTrEEService(TestServiceHandle, + TEST_SERVICE_GET_INTERRUPT_TIME, + NULL, 0, + &InterruptTime, sizeof(InterruptTime), + &BytesWritten); + + TEST_ASSERT(Success, L"CallTrEEService (read data) failed (err=%d)", GetLastError()); + TEST_ASSERT(BytesWritten == sizeof(ULONG64), + L"CallTrEEService (read data) returned unexpected number of bytes (BytesWritten=%d)", + BytesWritten); + + TEST_COMMENT(L"TEST_SERVICE_GET_INTERRUPT_TIME returned: %I64x", InterruptTime); + } + + if ((TestFlag & 0x4) != 0) { + TEST_COMMENT(L"\n::::: TEST_SERVICE_KERNEL_ONLY"); + + DWORD Error; + + // + // This call is available only from kernel mode. The service will fail + // the request if it came from usermode. + // + Success = CallTrEEService(TestServiceHandle, + TEST_SERVICE_KERNEL_ONLY, + NULL, 0, + NULL, 0, + &BytesWritten); + + Error = GetLastError(); + + TEST_ASSERT(!Success, L"CallTrEEService unexpectedly succeeded"); + + TEST_COMMENT(L"TEST_SERVICE_KERNEL_ONLY failed with err=%d", Error); + } + + { + DWORD Error; + ULONG Input; + ULONG Output; + PASYNC_TREE_CALL AsyncContext; + + if ((TestFlag & 0x8) != 0) { + TEST_COMMENT(L"\n::::: TEST_SERVICE_DELAYED_COMPLETION(1500ms, synchronous wait)"); + Input = 1500; + Output = 0; + Success = CallTrEEService(TestServiceHandle, + TEST_SERVICE_DELAYED_COMPLETION, + &Input, sizeof(Input), + &Output, sizeof(Output), + &BytesWritten); + + TEST_ASSERT(Success, L"CallTrEEService failed (err=%d)", GetLastError()); + TEST_ASSERT(BytesWritten == sizeof(Output), + L"CallTrEEService returned unexpected number of bytes (BytesWritten=%d)", + BytesWritten); + + TEST_COMMENT(L"Output buffer contains: %08x", Output); + } + + if ((TestFlag & 0x10) != 0) { + TEST_COMMENT(L"\n::::: TEST_SERVICE_DELAYED_COMPLETION(5000ms, asynchronous wait)"); + Input = 5000; + Output = 0; + + // + // CallTrEEServiceEx is called to demonstrate asynchronous operation. + // + Success = CallTrEEServiceEx(TestServiceHandle, + TEST_SERVICE_DELAYED_COMPLETION, + &Input, sizeof(Input), + &Output, sizeof(Output), + &BytesWritten, + &AsyncContext); + + Error = GetLastError(); + + TEST_ASSERT(!Success, L"CallTrEEServiceEx unexpectedly succeeded"); + TEST_ASSERT(GetLastError() == ERROR_IO_PENDING, + L"CallTrEEServiceEx returned unexpected error code (err=%d)", + Error); + + while (true) { + TEST_COMMENT(L"Waiting for completion..."); + Error = WaitForSingleObject(AsyncContext->Overlapped.hEvent, 500); + + TEST_ASSERT((Error == STATUS_TIMEOUT) || (Error == STATUS_WAIT_0), + L"WaitForSingleObject returned unexpected value %d", + Error); + + if (Error == STATUS_WAIT_0) { + break; + } + } + + TEST_ASSERT(AsyncContext->Overlapped.Internal == STATUS_SUCCESS, + L"Request failed (NTSTATUS=%08x)", + (NTSTATUS)AsyncContext->Overlapped.Internal); + + // + // IOCTL's output buffer points to TR_SERVICE_REQUEST_RESPONSE. So this + // request's number of bytes written is always sizeof(TR_SERVICE_REQUEST_RESPONSE). + // + TEST_ASSERT(AsyncContext->Overlapped.InternalHigh == sizeof(TR_SERVICE_REQUEST_RESPONSE), + L"Request response size incorrect (BytesWritten=%u)", + (ULONG)AsyncContext->Overlapped.InternalHigh); + + // + // Number of bytes written to secure request's output buffer is + // returned in TR_SERVICE_REQUEST_RESPONSE::BytesWritten. + // + TEST_ASSERT(AsyncContext->Response.BytesWritten == sizeof(ULONG), + L"Number of bytes written to output buffer incorrect (BytesWritten=%u)", + (ULONG)AsyncContext->Response.BytesWritten); + + TEST_COMMENT(L"Output buffer contains: %08x", Output); + + CleanupAsyncTrEECallContext(AsyncContext); + } + + if ((TestFlag & 0x20) != 0) { + TEST_COMMENT(L"\n::::: TEST_SERVICE_DELAYED_COMPLETION(5000ms, asynchronous wait + cancel)"); + Input = 5000; + Output = 0; + Success = CallTrEEServiceEx(TestServiceHandle, + TEST_SERVICE_DELAYED_COMPLETION, + &Input, sizeof(Input), + &Output, sizeof(Output), + &BytesWritten, + &AsyncContext); + + Error = GetLastError(); + + TEST_ASSERT(!Success, L"CallTrEEServiceEx unexpectedly succeeded"); + TEST_ASSERT(GetLastError() == ERROR_IO_PENDING, + L"CallTrEEServiceEx returned unexpected error code (err=%d)", + Error); + + Sleep(1000); + + TEST_COMMENT(L"Cancelling..."); + + // + // The request is cancelled before it can be completed. + // + Success = CancelIoEx(TestServiceHandle, &AsyncContext->Overlapped); + + TEST_ASSERT(Success, L"CancelIoEx failed (err=%d)", GetLastError()); + + // + // When the cancellation is handled by the miniport driver, the request + // will have status STATUS_CANCELLED. + // + for (int i = 0; i < 10; ++i) { + TEST_COMMENT(L"Request status = %08x", + (NTSTATUS)AsyncContext->Overlapped.Internal); + + if ((NTSTATUS)AsyncContext->Overlapped.Internal == STATUS_CANCELLED) { + break; + } + + Sleep(20); + } + + TEST_ASSERT((NTSTATUS)AsyncContext->Overlapped.Internal == STATUS_CANCELLED, + L"Request not cancelled (NTSTATUS=%08x)", + (NTSTATUS)AsyncContext->Overlapped.Internal); + + CleanupAsyncTrEECallContext(AsyncContext); + } + } + + { + DWORD Error; + ULONG Input; + ULONG Output; + OVERLAPPED Overlapped; + + if ((TestFlag & 0x40) != 0) { + TEST_COMMENT(L"\n::::: IOCTL_TEST_DELAYED_COMPLETION(3000ms + async wait)"); + + memset(&Overlapped, 0, sizeof(Overlapped)); + Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + // + // Other I/O doesn't use TR_SERVICE_REQUEST structs. Use + // DeviceIocontrol and specify input and output buffers directly in + // parameters. + // + Input = 3000; + Output = 0; + Success = DeviceIoControl(TestServiceHandle, + IOCTL_TEST_DELAYED_COMPLETION, + &Input, sizeof(Input), + &Output, sizeof(Output), + &BytesWritten, + &Overlapped); + + Error = GetLastError(); + + TEST_ASSERT(!Success, L"CallTrEEServiceEx unexpectedly succeeded"); + TEST_ASSERT(GetLastError() == ERROR_IO_PENDING, + L"CallTrEEServiceEx returned unexpected error code (err=%d)", + Error); + + while (true) { + TEST_COMMENT(L"Waiting for completion..."); + Error = WaitForSingleObject(Overlapped.hEvent, 500); + + TEST_ASSERT((Error == STATUS_TIMEOUT) || (Error == STATUS_WAIT_0), + L"WaitForSingleObject returned unexpected value %d", + Error); + + if (Error == STATUS_WAIT_0) { + break; + } + } + + TEST_ASSERT(Overlapped.Internal == STATUS_SUCCESS, + L"Request failed (NTSTATUS=%08x)", + (NTSTATUS)Overlapped.Internal); + + // + // IOCTL's output buffer points to ULONG Output. + // + TEST_ASSERT(Overlapped.InternalHigh == sizeof(ULONG), + L"Request response size incorrect (BytesWritten=%u)", + (ULONG)Overlapped.InternalHigh); + + TEST_COMMENT(L"Output buffer contains: %08x", Output); + } + + if ((TestFlag & 0x80) != 0) { + TEST_COMMENT(L"\n::::: IOCTL_TEST_DELAYED_COMPLETION(5000ms, asynchronous wait + cancel)"); + Overlapped.Internal = 0; + Overlapped.InternalHigh = 0; + Overlapped.Offset = 0; + Overlapped.OffsetHigh = 0; + Overlapped.Pointer = 0; + Input = 5000; + Output = 0; + Success = DeviceIoControl(TestServiceHandle, + IOCTL_TEST_DELAYED_COMPLETION, + &Input, sizeof(Input), + &Output, sizeof(Output), + &BytesWritten, + &Overlapped); + + Error = GetLastError(); + + TEST_ASSERT(!Success, L"CallTrEEServiceEx unexpectedly succeeded"); + TEST_ASSERT(GetLastError() == ERROR_IO_PENDING, + L"CallTrEEServiceEx returned unexpected error code (err=%d)", + Error); + + Sleep(1000); + + TEST_COMMENT(L"Cancelling..."); + + // + // The request is cancelled before it can be completed. + // + Success = CancelIoEx(TestServiceHandle, &Overlapped); + + TEST_ASSERT(Success, L"CancelIoEx failed (err=%d)", GetLastError()); + + // + // When the cancellation is handled by the miniport driver, the request + // will have status STATUS_CANCELLED. + // + for (int i = 0; i < 10; ++i) { + TEST_COMMENT(L"Request status = %08x", + (NTSTATUS)Overlapped.Internal); + + if ((NTSTATUS)Overlapped.Internal == STATUS_CANCELLED) { + break; + } + + Sleep(20); + } + + TEST_ASSERT((NTSTATUS)Overlapped.Internal == STATUS_CANCELLED, + L"Request not cancelled (NTSTATUS=%08x)", + (NTSTATUS)Overlapped.Internal); + + CloseHandle(Overlapped.hEvent); + } + } + + // + // Open the service using PnP device interface. + // + Test2ServiceHandle = OpenServiceHandleByInterface(&GUID_SAMPLE_TEST2_SERVICE); + TEST_ASSERT(Test2ServiceHandle != INVALID_HANDLE_VALUE, L"Test2 service open failed"); + + { + char Input[64]; + size_t InputLength; + char Output[128]; + + if ((TestFlag & 0x100) != 0) + { + // + // This service talks to another driversin OS. Refer to + // miniport\TestService.c to see how the miniport driver sends requests + // to other drivers. + // + TEST_COMMENT(L"\n::::: TEST2_SERVICE_ECHO"); + + strcpy_s(Input, "Hello from usermode"); + InputLength = strlen(Input); + memset(Output, 0, sizeof(Output)); + Success = CallTrEEService(Test2ServiceHandle, + TEST2_SERVICE_ECHO, + Input, (ULONG)InputLength, + Output, sizeof(Output), + &BytesWritten); + + TEST_ASSERT(Success, L"CallTrEEService failed (err=%d)", GetLastError()); + TEST_ASSERT(BytesWritten == InputLength, + L"CallTrEEService returned unexpected number of bytes (BytesWritten=%d)", + BytesWritten); + + TEST_COMMENT(L"Output buffer contains: %hs", Output); + } + + if ((TestFlag & 0x200) != 0) + { + TEST_COMMENT(L"\n::::: TEST2_SERVICE_TWICE_REVERSED"); + + strcpy_s(Input, "Hello from usermode"); + InputLength = strlen(Input); + memset(Output, 0, sizeof(Output)); + Success = CallTrEEService(Test2ServiceHandle, + TEST2_SERVICE_ECHO_TWICE_REVERSED, + Input, (ULONG)InputLength, + Output, sizeof(Output), + &BytesWritten); + + TEST_ASSERT(Success, L"CallTrEEService failed (err=%d)", GetLastError()); + TEST_ASSERT(BytesWritten == InputLength * 2, + L"CallTrEEService returned unexpected number of bytes (BytesWritten=%d)", + BytesWritten); + + TEST_COMMENT(L"Output buffer contains: %hs", Output); + } + } + + // + // Open the master device using PnP device interface. + // + MasterDeviceHandle = CreateFileW(L"\\\\.\\SampleTrEEDriver", + FILE_READ_DATA | FILE_WRITE_DATA, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + + TEST_ASSERT(MasterDeviceHandle != INVALID_HANDLE_VALUE, L"Master device open failed"); + + if ((TestFlag & 0x400) != 0) + { + TEST_COMMENT(L"\n::::: IOCTL_SAMPLE_DBGPRINT"); + + Success = DeviceIoControl(MasterDeviceHandle, + IOCTL_SAMPLE_DBGPRINT, + TEST_STRING, sizeof(TEST_STRING), + NULL, 0, + &BytesWritten, + NULL); + + TEST_ASSERT(Success, L"CallTrEEService failed (err=%d)", GetLastError()); + } + +End: + if (TestServiceHandle != INVALID_HANDLE_VALUE) { + CloseHandle(TestServiceHandle); + } + + if (Test2ServiceHandle != INVALID_HANDLE_VALUE) { + CloseHandle(Test2ServiceHandle); + } + + if (MasterDeviceHandle != INVALID_HANDLE_VALUE) { + CloseHandle(MasterDeviceHandle); + } + + return 0; +}
\ No newline at end of file diff --git a/TrEE/Test/TrEESampleTest.vcxproj b/TrEE/Test/TrEESampleTest.vcxproj new file mode 100644 index 00000000..dbf5824f --- /dev/null +++ b/TrEE/Test/TrEESampleTest.vcxproj @@ -0,0 +1,256 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|Arm"> + <Configuration>Debug</Configuration> + <Platform>Arm</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Arm"> + <Configuration>Release</Configuration> + <Platform>Arm</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{DDA508B0-8C40-47C1-BC1C-AD6717E895EF}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{9F985327-DEA3-47CE-AF50-79656A8DBC68}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType /> + <PlatformToolset>WindowsApplicationForDrivers10.0</PlatformToolset> + <ConfigurationType>Application</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" /> + </ImportGroup> + <ItemGroup Label="WrappedTaskItems" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <TargetName>TrEESampleTest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <TargetName>TrEESampleTest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetName>TrEESampleTest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>TrEESampleTest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>TrEESampleTest</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>TrEESampleTest</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Arm'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(MINWIN_SDK_LIB_PATH)\ntdll.lib;$(MINCORE_SDK_LIB_PATH)\mincore.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Arm'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(MINWIN_SDK_LIB_PATH)\ntdll.lib;$(MINCORE_SDK_LIB_PATH)\mincore.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(MINWIN_SDK_LIB_PATH)\ntdll.lib;$(MINCORE_SDK_LIB_PATH)\mincore.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(MINWIN_SDK_LIB_PATH)\ntdll.lib;$(MINCORE_SDK_LIB_PATH)\mincore.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(MINWIN_SDK_LIB_PATH)\ntdll.lib;$(MINCORE_SDK_LIB_PATH)\mincore.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + <ExceptionHandling> + </ExceptionHandling> + </ClCompile> + <Midl> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </Midl> + <ResourceCompile> + <PreprocessorDefinitions>%(PreprocessorDefinitions);UNICODE;_UNICODE</PreprocessorDefinitions> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SDK_INC_PATH)</AdditionalIncludeDirectories> + </ResourceCompile> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(MINWIN_SDK_LIB_PATH)\ntdll.lib;$(MINCORE_SDK_LIB_PATH)\mincore.lib</AdditionalDependencies> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="sampletest.cpp" /> + </ItemGroup> + <ItemGroup> + <Inf Exclude="@(Inf)" Include="*.inf" /> + <FilesToPackage Include="$(TargetPath)" Condition="'$(ConfigurationType)'=='Driver' or '$(ConfigurationType)'=='DynamicLibrary'" /> + </ItemGroup> + <ItemGroup> + <None Exclude="@(None)" Include="*.txt;*.htm;*.html" /> + <None Exclude="@(None)" Include="*.ico;*.cur;*.bmp;*.dlg;*.rct;*.gif;*.jpg;*.jpeg;*.wav;*.jpe;*.tiff;*.tif;*.png;*.rc2" /> + <None Exclude="@(None)" Include="*.def;*.bat;*.hpj;*.asmx" /> + </ItemGroup> + <ItemGroup> + <ClInclude Exclude="@(ClInclude)" Include="*.h;*.hpp;*.hxx;*.hm;*.inl;*.xsd" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> +</Project>
\ No newline at end of file diff --git a/TrEE/Test/TrEESampleTest.vcxproj.Filters b/TrEE/Test/TrEESampleTest.vcxproj.Filters new file mode 100644 index 00000000..0bc02bf0 --- /dev/null +++ b/TrEE/Test/TrEESampleTest.vcxproj.Filters @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <Filter Include="Source Files"> + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;*</Extensions> + <UniqueIdentifier>{FCED4095-7FC8-465C-AD4F-CA121B97193C}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{0B33D33B-97F5-4885-913B-C98AD039C1DF}</UniqueIdentifier> + </Filter> + <Filter Include="Resource Files"> + <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms;man;xml</Extensions> + <UniqueIdentifier>{83A7795F-7EE2-4FE1-B6D6-3AC2B6337B4E}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="sampletest.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/TrEE/TrEESample.sln b/TrEE/TrEESample.sln new file mode 100644 index 00000000..45e6561d --- /dev/null +++ b/TrEE/TrEESample.sln @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Miniport", "Miniport", "{E3F88200-7D31-4C70-97A6-83885195E581}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OSService", "OSService", "{EF1FA66C-82A9-4572-ACC7-76DEBA085FF2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{420587AA-51DE-4966-B692-C428836BF8B2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TrEEMiniportSample", "Miniport\TrEEMiniportSample.vcxproj", "{C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TrEEOSServiceSample", "OSService\TrEEOSServiceSample.vcxproj", "{7661C397-614D-4562-9CC7-6178B246DB17}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TrEESampleTest", "Test\TrEESampleTest.vcxproj", "{DDA508B0-8C40-47C1-BC1C-AD6717E895EF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + Debug|Arm = Debug|Arm + Release|Arm = Release|Arm + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Debug|Win32.ActiveCfg = Debug|Win32 + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Debug|Win32.Build.0 = Debug|Win32 + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Release|Win32.ActiveCfg = Release|Win32 + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Release|Win32.Build.0 = Release|Win32 + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Debug|x64.ActiveCfg = Debug|x64 + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Debug|x64.Build.0 = Debug|x64 + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Release|x64.ActiveCfg = Release|x64 + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Release|x64.Build.0 = Release|x64 + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Debug|Arm.ActiveCfg = Debug|Arm + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Debug|Arm.Build.0 = Debug|Arm + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Release|Arm.ActiveCfg = Release|Arm + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C}.Release|Arm.Build.0 = Release|Arm + {7661C397-614D-4562-9CC7-6178B246DB17}.Debug|Win32.ActiveCfg = Debug|Win32 + {7661C397-614D-4562-9CC7-6178B246DB17}.Debug|Win32.Build.0 = Debug|Win32 + {7661C397-614D-4562-9CC7-6178B246DB17}.Release|Win32.ActiveCfg = Release|Win32 + {7661C397-614D-4562-9CC7-6178B246DB17}.Release|Win32.Build.0 = Release|Win32 + {7661C397-614D-4562-9CC7-6178B246DB17}.Debug|x64.ActiveCfg = Debug|x64 + {7661C397-614D-4562-9CC7-6178B246DB17}.Debug|x64.Build.0 = Debug|x64 + {7661C397-614D-4562-9CC7-6178B246DB17}.Release|x64.ActiveCfg = Release|x64 + {7661C397-614D-4562-9CC7-6178B246DB17}.Release|x64.Build.0 = Release|x64 + {7661C397-614D-4562-9CC7-6178B246DB17}.Debug|Arm.ActiveCfg = Debug|Arm + {7661C397-614D-4562-9CC7-6178B246DB17}.Debug|Arm.Build.0 = Debug|Arm + {7661C397-614D-4562-9CC7-6178B246DB17}.Release|Arm.ActiveCfg = Release|Arm + {7661C397-614D-4562-9CC7-6178B246DB17}.Release|Arm.Build.0 = Release|Arm + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Debug|Win32.ActiveCfg = Debug|Win32 + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Debug|Win32.Build.0 = Debug|Win32 + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Release|Win32.ActiveCfg = Release|Win32 + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Release|Win32.Build.0 = Release|Win32 + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Debug|x64.ActiveCfg = Debug|x64 + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Debug|x64.Build.0 = Debug|x64 + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Release|x64.ActiveCfg = Release|x64 + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Release|x64.Build.0 = Release|x64 + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Debug|Arm.ActiveCfg = Debug|Arm + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Debug|Arm.Build.0 = Debug|Arm + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Release|Arm.ActiveCfg = Release|Arm + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF}.Release|Arm.Build.0 = Release|Arm + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C1B22B3C-BE1A-40CE-82D0-8AE1628C297C} = {E3F88200-7D31-4C70-97A6-83885195E581} + {7661C397-614D-4562-9CC7-6178B246DB17} = {EF1FA66C-82A9-4572-ACC7-76DEBA085FF2} + {DDA508B0-8C40-47C1-BC1C-AD6717E895EF} = {420587AA-51DE-4966-B692-C428836BF8B2} + EndGlobalSection +EndGlobal diff --git a/TrEE/inc/SampleOSService.h b/TrEE/inc/SampleOSService.h new file mode 100644 index 00000000..57811456 --- /dev/null +++ b/TrEE/inc/SampleOSService.h @@ -0,0 +1,66 @@ +#pragma once + +// +// Echo service +// GUID {33C7FF13-50B0-454A-8BEB-F73EED6C0AF9} +// +DEFINE_GUID(GUID_ECHO_SERVICE, + 0x33c7ff13, 0x50b0, 0x454a, 0x8b, 0xeb, 0xf7, 0x3e, 0xed, 0x6c, 0xa, 0xf9); + +// +// Copies the content of input buffer to output buffer +// +#define ECHO_SERVICE_ECHO 1 + +// +// Repeats the content of input buffer to output buffer +// +#define ECHO_SERVICE_REPEAT 2 + +// +// Copies the bytes of input buffer to output buffer in reverse order +// +#define ECHO_SERVICE_REVERSE 3 + +// +// Kernel memory service +// {D28698A4-3B07-4F34-B65E-AE3DA6ACF2AC} +// +DEFINE_GUID(GUID_KERNEL_MEMORY_SERVICE, + 0xd28698a4, 0x3b07, 0x4f34, 0xb6, 0x5e, 0xae, 0x3d, 0xa6, 0xac, 0xf2, 0xac); + +// +// Get a safe range of kernel address space that can be read from +// +// Input: None +// Output: KERNEL_MEMORY_SAFE_RANGE +// + +typedef struct _KERNEL_MEMORY_SAFE_RANGE { + ULONG64 Base; + ULONG Length; +} KERNEL_MEMORY_SAFE_RANGE, *PKERNEL_MEMORY_SAFE_RANGE; + +#define KERNEL_MEMORY_SERVICE_GET_SAFE_RANGE 1 + +// +// Write a byte to kernel address space +// +// Input: KERNEL_MEMORY_WRITE_BYTE +// Output: Previous UCHAR value at the address +// + +typedef struct _KERNEL_MEMORY_WRITE_BYTE { + ULONG64 Address; + UCHAR Value; +} KERNEL_MEMORY_WRITE_BYTE, *PKERNEL_MEMORY_WRITE_BYTE; + +#define KERNEL_MEMORY_SERVICE_WRITE_BYTE 2 + +// +// Read a byte from kernel address space +// +// Input: ULONG64 address of kernel memory to read +// Output: UCHAR +// +#define KERNEL_MEMORY_SERVICE_READ_BYTE 3
\ No newline at end of file diff --git a/TrEE/inc/SampleSecureService.h b/TrEE/inc/SampleSecureService.h new file mode 100644 index 00000000..66ab6141 --- /dev/null +++ b/TrEE/inc/SampleSecureService.h @@ -0,0 +1,72 @@ +#pragma once + +// +// Sample test service +// {4AFA2AF5-0912-407B-8B12-AFFF4047672A} +// +DEFINE_GUID(GUID_SAMPLE_TEST_SERVICE, + 0x4afa2af5, 0x912, 0x407b, 0x8b, 0x12, 0xaf, 0xff, 0x40, 0x47, 0x67, 0x2a); + +// +// Writes classic L"Hello, world!" message to output buffer. +// +#define TEST_SERVICE_HELLO_WORLD 1 + +// +// Writes 64-bit timestamp returned from KeQueryInterruptTimePrecise to output +// buffer. +// +#define TEST_SERVICE_GET_INTERRUPT_TIME 2 + +// +// A request that is only available from kernel mode +// +// Input: None +// Output: None +#define TEST_SERVICE_KERNEL_ONLY 3 + +// +// The request will be completed asynchronously after given delay +// +// Input: ULONG (delay in msec) +// Output: ULONG (0x12345678) +#define TEST_SERVICE_DELAYED_COMPLETION 4 + +// +// Sample test service consuming sample OS service +// {D69482F9-7347-431A-8409-F625BEB3469D} +// +DEFINE_GUID(GUID_SAMPLE_TEST2_SERVICE, + 0xd69482f9, 0x7347, 0x431a, 0x84, 0x9, 0xf6, 0x25, 0xbe, 0xb3, 0x46, 0x9d); + +// +// Copies contents of input buffer to output buffer +// +#define TEST2_SERVICE_ECHO 1 + +// +// Copies contents of input buffer to output buffer twice, reversed +// +#define TEST2_SERVICE_ECHO_TWICE_REVERSED 2 + +// +// Other service I/O example +// + +// +// The request will be complete asynchronously after 1 second +// Input : NULL-terminated WCHAR[], size includes the terminating NULL character +// Output : None +// +#define IOCTL_TEST_DELAYED_COMPLETION CTL_CODE(FILE_DEVICE_TRUST_ENV, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) + +// +// Other device I/O example +// + +// +// Prints a string to debugger through DbgPrintEx +// Input : NULL-terminated WCHAR[], size includes the terminating NULL character +// Output : None +// +#define IOCTL_SAMPLE_DBGPRINT CTL_CODE(FILE_DEVICE_TRUST_ENV, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
\ No newline at end of file |
