diff options
| author | J M Rossy <[email protected]> | 2015-07-29 15:40:09 -0700 |
|---|---|---|
| committer | J M Rossy <[email protected]> | 2015-07-29 16:34:40 -0700 |
| commit | 5d61a4a79a1e96dc5d9af1e5e712c84507307544 (patch) | |
| tree | 49ed270893578cd18758b74ffcca16dc7ab948d6 /pos/drivers | |
| parent | 5d41613e26e147d2300c786bb2b34cb4b4067a25 (diff) | |
Samples update for public Windows 10 release
Fix #2 Enabling WPP Recorder in Sensors Samples causes errors
Fix #4 Add back fixed KMDOD sample
Add new BarcodeScanner sample in pos folder
Add new MagneticStripeReader sample in pos folder
Add new SynpaticsTouch sample in input folder
Add new Power Engine Plugin sample in pofx folder
Add new DeviceMft sample in avstream folder
Add new AvsCamera sample in root
Add new SimBatt sample in root
Add other pre-existing samples not yet released for Win10
Diffstat (limited to 'pos/drivers')
38 files changed, 3119 insertions, 0 deletions
diff --git a/pos/drivers/MagneticStripeReader/Device.cpp b/pos/drivers/MagneticStripeReader/Device.cpp new file mode 100644 index 00000000..85932fb2 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/Device.cpp @@ -0,0 +1,101 @@ +#include <pch.h> + +#include "File.h" +#include "PosEvents.h" +#include "Ioctl.h" +#include "IoRead.h" + +/* +** Driver TODO: Complete the implementation of EvtDriverDeviceAdd for your specific device. +** +** WDF calls this callback when a device instance is added to the driver. Good drivers will do a lot of +** work here to set up everything necessary, such as adding callbacks for PNP power state changes. +** This function defines an IO queue for handling DeviceIoControl and file read requests, both of which are +** important to the POS magnetic stripe reader model. +** +** Note that this is not a complete device add implementation, as the PNP power callbacks are not handled. +** Additionally, driver writers may wish to set up additional queues to serialize device property requests +** (see Ioctl.cpp for more info). +*/ +NTSTATUS EvtDriverDeviceAdd(_In_ WDFDRIVER /* UnusedDriver */, _Inout_ PWDFDEVICE_INIT DeviceInit) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_FILEOBJECT_CONFIG fileConfig; + WDF_OBJECT_ATTRIBUTES deviceAttributes; + WDF_OBJECT_ATTRIBUTES fileAttributes; + WDFDEVICE device; + + // Handle file events + WDF_FILEOBJECT_CONFIG_INIT( + &fileConfig, + EvtDeviceFileCreate, + EvtFileClose, + WDF_NO_EVENT_CALLBACK + ); + + WDF_OBJECT_ATTRIBUTES_INIT(&fileAttributes); + WdfDeviceInitSetFileObjectConfig( + DeviceInit, + &fileConfig, + &fileAttributes + ); + + // Create Device + WDF_OBJECT_ATTRIBUTES_INIT(&deviceAttributes); + status = WdfDeviceCreate( + &DeviceInit, + &deviceAttributes, + &device + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // Create a device interface for POS Magnetic Stripe Reader so that the device can be enumerated + status = WdfDeviceCreateDeviceInterface( + device, + &GUID_DEVINTERFACE_POS_MSR, + NULL + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // Initialize the POS library + POS_CX_ATTRIBUTES posCxAttributes; + POS_CX_ATTRIBUTES_INIT(&posCxAttributes); + posCxAttributes.EvtDeviceOwnershipChange = EvtDeviceOwnershipChange; + + status = PosCxInit(device, &posCxAttributes); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // Set up an IO queue to handle DeviceIoControl and ReadFile + WDF_IO_QUEUE_CONFIG queueConfig; + WDF_OBJECT_ATTRIBUTES attributes; + WDFQUEUE queue; + + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchSequential); + queueConfig.EvtIoDeviceControl = EvtIoDeviceControl; + queueConfig.EvtIoRead = EvtIoRead; + + // Call us in PASSIVE_LEVEL + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ExecutionLevel = WdfExecutionLevelPassive; + + status = WdfIoQueueCreate( + device, + &queueConfig, + &attributes, + &queue + ); + + return status; +} diff --git a/pos/drivers/MagneticStripeReader/Device.h b/pos/drivers/MagneticStripeReader/Device.h new file mode 100644 index 00000000..df9ad409 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/Device.h @@ -0,0 +1,3 @@ +#pragma once + +EVT_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd; diff --git a/pos/drivers/MagneticStripeReader/Driver.cpp b/pos/drivers/MagneticStripeReader/Driver.cpp new file mode 100644 index 00000000..5bcf2f33 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/Driver.cpp @@ -0,0 +1,54 @@ +#include <pch.h> + +#include "Device.h" + +// Forward declaration +VOID EvtDriverCleanup(_In_ WDFOBJECT DriverObject); + +/* +** Driver TODO: +** +** This is the main entry point of the driver. POS APIs require that the driver sets up additional data in device add. +** +** Note that your driver may have additional configuration to do in this function, and it should not be assumed that this sample is complete. +*/ +NTSTATUS DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath + ) +{ + WDF_DRIVER_CONFIG config; + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.EvtCleanupCallback = EvtDriverCleanup; + + WDF_DRIVER_CONFIG_INIT( + &config, + EvtDriverDeviceAdd + ); + + status = WdfDriverCreate( + DriverObject, + RegistryPath, + &attributes, + &config, + WDF_NO_HANDLE + ); + + return status; +} + +/* +** Driver TODO: +** +** This is the cleanup callback for the driver (as set above in DriverEntry). +** PosCx requires no cleanup at this point. +*/ +_Use_decl_annotations_ +VOID EvtDriverCleanup(WDFOBJECT /* UnusedDriverObject */) +{ + // Do any cleanup needed here + return; +} diff --git a/pos/drivers/MagneticStripeReader/File.cpp b/pos/drivers/MagneticStripeReader/File.cpp new file mode 100644 index 00000000..d9cf815d --- /dev/null +++ b/pos/drivers/MagneticStripeReader/File.cpp @@ -0,0 +1,37 @@ +#include <pch.h> + +/* +** Driver TODO: +** +** WDF calls this callback when a file handle is opened to the driver. Your implementation may require additional setup (such as creating a +** file-handle-based context structure). PosCxOpen must be called during this callback. +*/ +VOID EvtDeviceFileCreate(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDFFILEOBJECT FileObject) +{ + NTSTATUS status = PosCxOpen(Device, FileObject, MSR_INTERFACE_TAG); + + if (!NT_SUCCESS(status)) + { + // This should only fail in rare cases, but the failure will prevent all PosCx functions from performing correctly + } + + WdfRequestComplete(Request, status); +} + +/* +** Driver TODO: +** +** WDF calls this callback when a file handle to the driver is closed. Your implementation may require additional cleanup, but +** PosCxClose must be called during this callback. +*/ +VOID EvtFileClose(_In_ WDFFILEOBJECT FileObject) +{ + WDFDEVICE device = WdfFileObjectGetDevice(FileObject); + + NTSTATUS status = PosCxClose(device, FileObject); + + if (!NT_SUCCESS(status)) + { + // This will only fail if PosCxInit wasn't called successfully in EvtDriverDeviceAdd, or if PosCxOpen failed in EvtDeviceFileCreate + } +}
\ No newline at end of file diff --git a/pos/drivers/MagneticStripeReader/File.h b/pos/drivers/MagneticStripeReader/File.h new file mode 100644 index 00000000..73f815e0 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/File.h @@ -0,0 +1,4 @@ +#pragma once + +EVT_WDF_DEVICE_FILE_CREATE EvtDeviceFileCreate; +EVT_WDF_FILE_CLOSE EvtFileClose; diff --git a/pos/drivers/MagneticStripeReader/IoRead.cpp b/pos/drivers/MagneticStripeReader/IoRead.cpp new file mode 100644 index 00000000..c19ee743 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/IoRead.cpp @@ -0,0 +1,41 @@ +#include <pch.h> + +/* +** Driver TODO: Add logic to EvtIoRead to handle read requests from applications that don't use the Windows.Devices.PointOfService APIs. +** +** This is the callback for the IO queue that handles file read requests. In the POS magnetic +** stripe reader model, the application will always queue a read request in order to receive events +** such as the data received event, or the release-claim requested event. +** +** Note that apps that are developed against the Windows.Devices.PointOfService APIs will always +** expect event data to be returned by read requests. It is up to the driver to determine the +** behavior of ReadFile when the driver is opened by other types of applications. +*/ +VOID EvtIoRead(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length) +{ + NTSTATUS status; + WDFDEVICE device = WdfIoQueueGetDevice(Queue); + WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request); + + UNREFERENCED_PARAMETER(Length); + + // Check the flag that may have been set by PosCxMarkPosApp in Ioctl.cpp. + if (!PosCxIsPosApp(device, fileObject)) + { + // An application has opened a handle to this device without using the Windows.Devices.PointOfService APIs. + // You may change this to handle the read request differently. + + // In this example, just complete the read request with a failure. + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); + } + else + { + // If this returns success, it has taken ownership of Request + status = PosCxGetPendingEvent(device, Request); + + if (!NT_SUCCESS(status)) + { + WdfRequestComplete(Request, status); + } + } +}
\ No newline at end of file diff --git a/pos/drivers/MagneticStripeReader/IoRead.h b/pos/drivers/MagneticStripeReader/IoRead.h new file mode 100644 index 00000000..20f7dcdd --- /dev/null +++ b/pos/drivers/MagneticStripeReader/IoRead.h @@ -0,0 +1,3 @@ +#pragma once + +EVT_WDF_IO_QUEUE_IO_READ EvtIoRead;
\ No newline at end of file diff --git a/pos/drivers/MagneticStripeReader/Ioctl.cpp b/pos/drivers/MagneticStripeReader/Ioctl.cpp new file mode 100644 index 00000000..dd8ffb62 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/Ioctl.cpp @@ -0,0 +1,878 @@ +#include <pch.h> + +NTSTATUS ProcessRetrieveDeviceAuthentication(_In_ WDFDEVICE Device, _In_ WDFFILEOBJECT FileObject, _In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information); +NTSTATUS ProcessAuthenticateDevice(_In_ WDFDEVICE Device, _In_ WDFFILEOBJECT FileObject, _In_ WDFREQUEST Request); +NTSTATUS ProcessDeauthenticateDevice(_In_ WDFDEVICE Device, _In_ WDFFILEOBJECT FileObject, _In_ WDFREQUEST Request); +NTSTATUS ProcessUpdateKey(_In_ WDFDEVICE Device, _In_ WDFFILEOBJECT FileObject, _In_ WDFREQUEST Request); +NTSTATUS ProcessGetPropertyRequest(_In_ WDFREQUEST Request, _In_ size_t InputBufferLength, _Inout_ ULONG_PTR* Information); +NTSTATUS ProcessSetPropertyRequest(_In_ WDFREQUEST Request, _In_ size_t InputBufferLength, _Inout_ ULONG_PTR* Information); +NTSTATUS ProcessRetrieveStatisticsRequest(_In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _Inout_ ULONG_PTR* Information); +NTSTATUS ProcessResetStatisticsRequest(_In_ WDFREQUEST Request); +NTSTATUS ProcessUpdateStatisticsRequest(_In_ WDFREQUEST Request); +NTSTATUS ProcessCheckHealthRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information); +NTSTATUS ProcessGetDeviceBasicsRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information); + +/* +** Driver TODO: Complete the implementation of EvtIoDeviceControl for your specific device (if necessary) +** +** WDF calls this callback when a device instance is added to the driver. Good drivers will do a lot of +** work here to set up everything necessary, such as adding callbacks for PNP power state changes. +** This function defines an IO queue for handling DeviceIoControl and file read requests, both of which are +** important to the POS magnetic stripe reader model. +** +** Note that this is not a complete device add implementation, as the PNP power callbacks are not handled. +** Additionally, driver writers may wish to set up additional queues to serialize device property requests +** (see Ioctl.cpp for more info). +*/ +VOID EvtIoDeviceControl(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode) +{ + UNREFERENCED_PARAMETER(Queue); + + NTSTATUS status = STATUS_SUCCESS; + ULONG_PTR information = 0; + WDFDEVICE device = WdfIoQueueGetDevice(Queue); + WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request); + + // These are the set of IOCTLs that your device should handle to work with the Windows.Devices.PointOfService APIs. + switch (IoControlCode) + { + // The first three IOCTLs shouldn't require additional processing other than handing them off to PosCx + case IOCTL_POINT_OF_SERVICE_CLAIM_DEVICE: + status = PosCxClaimDevice(device, Request); + break; + + case IOCTL_POINT_OF_SERVICE_RELEASE_DEVICE: + status = PosCxReleaseDevice(device, fileObject); + break; + + case IOCTL_POINT_OF_SERVICE_RETAIN_DEVICE: + status = PosCxRetainDevice(device, Request); + break; + + + case IOCTL_POINT_OF_SERVICE_MSR_RETRIEVE_DEVICE_AUTHENTICATION: + status = ProcessRetrieveDeviceAuthentication(device, fileObject, Request, &information); + break; + + case IOCTL_POINT_OF_SERVICE_MSR_AUTHENTICATE_DEVICE: + status = ProcessAuthenticateDevice(device, fileObject, Request); + break; + + case IOCTL_POINT_OF_SERVICE_MSR_DEAUTHENTICATE_DEVICE: + status = ProcessDeauthenticateDevice(device, fileObject, Request); + break; + + case IOCTL_POINT_OF_SERVICE_MSR_UPDATE_KEY: + status = ProcessUpdateKey(device, fileObject, Request); + break; + + case IOCTL_POINT_OF_SERVICE_GET_PROPERTY: + status = ProcessGetPropertyRequest(Request, InputBufferLength, &information); + break; + + case IOCTL_POINT_OF_SERVICE_SET_PROPERTY: + status = ProcessSetPropertyRequest(Request, InputBufferLength, &information); + break; + + case IOCTL_POINT_OF_SERVICE_RETRIEVE_STATISTICS: + status = ProcessRetrieveStatisticsRequest(Request, OutputBufferLength, &information); + break; + + case IOCTL_POINT_OF_SERVICE_RESET_STATISTICS: + status = ProcessResetStatisticsRequest(Request); + break; + + case IOCTL_POINT_OF_SERVICE_UPDATE_STATISTICS: + status = ProcessUpdateStatisticsRequest(Request); + break; + + case IOCTL_POINT_OF_SERVICE_CHECK_HEALTH: + status = ProcessCheckHealthRequest(Request, &information); + break; + + // The Get Device Basics IOCTL is always the first IOCTL called by an application using the Windows.Devices.PointOfService APIs. + // Use it to determine when to call PosCxMarkPosApp (see notes about apps marked this way in IoRead.cpp) + case IOCTL_POINT_OF_SERVICE_GET_DEVICE_BASICS: + status = ProcessGetDeviceBasicsRequest(Request, &information); + (void)PosCxMarkPosApp(device, fileObject, TRUE); + break; + + default: + // Your device may support additional IOCTLs. In this sample, we return failure for anything else. + status = STATUS_NOT_SUPPORTED; + break; + } + + if (status != STATUS_PENDING) + { + WdfRequestCompleteWithInformation(Request, status, information); + } +} + +/* +** Driver TODO: Add code to handle various get-property cases. +** +** Implement this function to handle requests for the device authentication information. +** This should be step 1 in authenticating or deauthenticating the device. +*/ +NTSTATUS ProcessRetrieveDeviceAuthentication(_In_ WDFDEVICE Device, _In_ WDFFILEOBJECT FileObject, _In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information) +{ + // If the caller is not the device owner, fail the request + if (!PosCxIsDeviceOwner(Device, FileObject)) + { + return STATUS_ACCESS_DENIED; + } + + *Information = (ULONG_PTR)sizeof(MSR_RETRIEVE_DEVICE_AUTHENTICATION_DATA); + + PMSR_RETRIEVE_DEVICE_AUTHENTICATION_DATA reqBufferPtr; + size_t reqBufferSize; + NTSTATUS status = WdfRequestRetrieveOutputBuffer( + Request, + sizeof(MSR_RETRIEVE_DEVICE_AUTHENTICATION_DATA), + reinterpret_cast<PVOID*>(&reqBufferPtr), + &reqBufferSize + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // TODO: Fill in the reqBufferPtr with the authentication information for your device. + + return status; +} + +/* +** Driver TODO: Add code to handle various get-property cases. +** +** Implement this function to handle requests to authenticate your device. +** This is step 2 in authenticating the device. +*/ +NTSTATUS ProcessAuthenticateDevice(_In_ WDFDEVICE Device, _In_ WDFFILEOBJECT FileObject, _In_ WDFREQUEST Request) +{ + // If the caller is not the device owner, fail the request + if (!PosCxIsDeviceOwner(Device, FileObject)) + { + return STATUS_ACCESS_DENIED; + } + + PMSR_AUTHENTICATE_DEVICE reqBufferPtr; + size_t reqBufferSize; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(MSR_AUTHENTICATE_DEVICE), + reinterpret_cast<PVOID*>(&reqBufferPtr), + &reqBufferSize + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // TODO: Send the authentication information to the device + + return status; +} + +/* +** Driver TODO: Add code to handle various get-property cases. +** +** Implement this function to handle requests to deauthenticate your device. +** This is step 2 in deauthenticating the device. +*/ +NTSTATUS ProcessDeauthenticateDevice(_In_ WDFDEVICE Device, _In_ WDFFILEOBJECT FileObject, _In_ WDFREQUEST Request) +{ + // If the caller is not the device owner, fail the request + if (!PosCxIsDeviceOwner(Device, FileObject)) + { + return STATUS_ACCESS_DENIED; + } + + PMSR_DEAUTHENTICATE_DEVICE reqBufferPtr; + size_t reqBufferSize; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(MSR_DEAUTHENTICATE_DEVICE), + reinterpret_cast<PVOID*>(&reqBufferPtr), + &reqBufferSize + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // TODO: Send the deauthentication information to the device + + return status; +} + +/* +** Driver TODO: Add code to handle various get-property cases. +** +** Implement this function to handle requests to update the key in your device. +*/ +NTSTATUS ProcessUpdateKey(_In_ WDFDEVICE Device, _In_ WDFFILEOBJECT FileObject, _In_ WDFREQUEST Request) +{ + // If the caller is not the device owner, fail the request + if (!PosCxIsDeviceOwner(Device, FileObject)) + { + return STATUS_ACCESS_DENIED; + } + + PMSR_UPDATE_KEY reqBufferPtr; + size_t reqBufferSize; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(MSR_UPDATE_KEY), + reinterpret_cast<PVOID*>(&reqBufferPtr), + &reqBufferSize + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // TODO: Send the updated key information to the device + + return status; +} + +/* +** Driver TODO: Add code to handle various get-property cases. +** +** Implement this function to handle property get requests. +*/ +NTSTATUS ProcessGetPropertyRequest(_In_ WDFREQUEST Request, _In_ size_t InputBufferLength, _Inout_ ULONG_PTR* Information) +{ + if (Information == nullptr || Request == nullptr || InputBufferLength < sizeof(PosPropertyId)) + { + return STATUS_INVALID_PARAMETER; + } + + // POS properties are identified by the property ID that's transmitted in the input buffer. + PosPropertyId* propertyId; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(PosPropertyId), + reinterpret_cast<PVOID*>(&propertyId), + nullptr + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // All get properties will need access to the output buffer in order to return results. + // The minimum size returned is a UINT32 + void* outputBuffer; + size_t outputBufferLength; + status = WdfRequestRetrieveOutputBuffer( + Request, + sizeof(UINT32), + &outputBuffer, + &outputBufferLength + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // Handle this set of readable properties + switch (*propertyId) + { + case PosPropertyId::IsEnabled: + // BOOL result, true when the app has called SetProperty(IsEnabled) = TRUE + { + BOOL isEnabled = TRUE; // Get this value from device context or by querying the device + *((BOOL*)outputBuffer) = isEnabled; + *Information = sizeof(BOOL); + } + break; + + case PosPropertyId::IsDisabledOnDataReceived: + // BOOL result, true when the app has called SetProperty(IsDisabledOnDataReceived) = TRUE + { + BOOL isDisabledOnDataReceived = TRUE; // Get this value from device context or by querying the device + *((BOOL*)outputBuffer) = isDisabledOnDataReceived; + *Information = sizeof(BOOL); + } + break; + + case PosPropertyId::MagneticStripeReaderIsDecodeDataEnabled: + // BOOL result, true when the app has called SetProperty(MagneticStripeReaderIsDecodeDataEnabled) = TRUE + { + BOOL isDecodeDataEnabled = TRUE; // Get this value from device context or by querying the device + *((BOOL*)outputBuffer) = isDecodeDataEnabled; + *Information = sizeof(BOOL); + } + break; + + case PosPropertyId::MagneticStripeReaderCapabilities: + { + // PosMagneticStripeReaderCapabilitiesType result + // These capabilities are likely hard-coded for the specific device. In this case, example values are provided and should + // be replaced with values that match your hardware + PosMagneticStripeReaderCapabilitiesType capabilities; + capabilities.PowerReportingType = DriverUnifiedPosPowerReportingType::Standard; + capabilities.IsStatisticsReportingSupported = TRUE; + capabilities.IsStatisticsUpdatingSupported = TRUE; + capabilities.CardAuthenticationLength = 0; + capabilities.SupportedEncryptionAlgorithms = MsrDataEncryption::MsrDataEncryption_AES; + capabilities.AuthenticationLevel = DriverMagneticStripeReaderAuthenticationLevel::Optional; + capabilities.IsIsoSupported = TRUE; + capabilities.IsJisOneSupported = TRUE; + capabilities.IsJisTwoSupported = TRUE; + capabilities.IsTrackDataMaskingSupported = TRUE; + capabilities.IsTransmitSentinelsSupported = TRUE; + size_t bytesToCopy = sizeof(PosMagneticStripeReaderCapabilitiesType); + if (outputBufferLength < bytesToCopy) + { + bytesToCopy = outputBufferLength; + status = STATUS_BUFFER_OVERFLOW; + } + memcpy(outputBuffer, &capabilities, bytesToCopy); + *Information = bytesToCopy; + } + break; + + case PosPropertyId::MagneticStripeReaderSupportedCardTypes: + { + // Supported card types. The API understands Bank and AAMVA, but additional, device-specific values can be added as well + // This property is typically hard coded based on the device type + MSR_SUPPORTED_CARD_TYPES supportedCardTypes; + RtlZeroMemory(&supportedCardTypes, sizeof(MSR_SUPPORTED_CARD_TYPES)); + supportedCardTypes.Count = 2; + supportedCardTypes.CardTypes[0] = (unsigned int)MsrCardType::MsrCardType_Bank; + supportedCardTypes.CardTypes[1] = (unsigned int)MsrCardType::MsrCardType_Aamva; + size_t bytesToCopy = sizeof(MSR_SUPPORTED_CARD_TYPES); + if (outputBufferLength < bytesToCopy) + { + bytesToCopy = outputBufferLength; + status = STATUS_BUFFER_OVERFLOW; + } + memcpy(outputBuffer, &supportedCardTypes, bytesToCopy); + *Information = bytesToCopy; + } + break; + + case PosPropertyId::MagneticStripeReaderDeviceAuthenticationProtocol: + { + // Returns whether the device supports challenge/response authentication or not. + *((MsrAuthenticationProtocolType*)outputBuffer) = MsrAuthenticationProtocolType::MsrAuthenticationProtocolType_ChallengeResponse; + *Information = sizeof(MsrAuthenticationProtocolType); + } + break; + + case PosPropertyId::MagneticStripeReaderErrorReportingType: + { + // Returns whether the device should report errors at the card or track level. + // This value is typically retrieved from the device context based on a prior SetProperty(MagneticStripeReaderErrorReportingType) + *((MsrErrorReportingType*)outputBuffer) = MsrErrorReportingType::MsrErrorReportingType_CardLevel; + *Information = sizeof(MsrErrorReportingType); + } + break; + + case PosPropertyId::MagneticStripeReaderTracksToRead: + { + // typically this value is saved in the device context to track which tracks the application wants to read from the card + MsrTrackIds tracksToRead = (MsrTrackIds)(MsrTrackIds::MsrTrackIds_Track1 | MsrTrackIds::MsrTrackIds_Track2); + *((MsrTrackIds*)outputBuffer) = tracksToRead; + *Information = sizeof(MsrTrackIds); + } + break; + + case PosPropertyId::MagneticStripeReaderIsTransmitSentinelsEnabled: + { + // BOOL property. True if the data that is sent to the application will include start/end sentinals or not + // This property can return STATUS_NOT_SUPPORTED if the IsTransmitSentinelsSupported capability is FALSE + // Otherwise, the boolean that's returned should be captured from the device context or from the device itself + BOOL isTransmitSentinelsEnabled = TRUE; + *((BOOL*)outputBuffer) = isTransmitSentinelsEnabled; + *Information = sizeof(BOOL); + } + break; + + case PosPropertyId::MagneticStripeReaderIsDeviceAuthenticated: + { + // BOOL property. True if the the authentication process has been successful + // This value should come from the device context or from the device itself + BOOL isAuthenticated = TRUE; + *((BOOL*)outputBuffer) = isAuthenticated; + *Information = sizeof(BOOL); + } + break; + + case PosPropertyId::MagneticStripeReaderDataEncryptionAlgorithm: + { + // Returns the encryption algorithm used to decrypt the card data + // If the device supports multiple algorithms, it should store the current one in the device context and use that value here + // (or retrieve the value from the device itself) + MsrDataEncryption currentEncryptionAlgorithm = MsrDataEncryption::MsrDataEncryption_AES; + *((MsrDataEncryption*)outputBuffer) = currentEncryptionAlgorithm; + } + break; + + default: + // no other readable properties for magnetic stripe reader + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +/* +** Driver TODO: Add code to handle various set-property cases. +** +** Implement this function to handle property set requests. +*/ +NTSTATUS ProcessSetPropertyRequest(_In_ WDFREQUEST Request, _In_ size_t InputBufferLength, _Inout_ ULONG_PTR* Information) +{ + if (Information == nullptr || Request == nullptr || InputBufferLength < sizeof(PosPropertyId)) + { + return STATUS_INVALID_PARAMETER; + } + + // POS properties are identified by the property ID that's transmitted in the input buffer. + // The data that is used to set the property immediately follows the property ID, so the input buffer must be big enough to contain both. + PosPropertyId* propertyId; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(PosPropertyId), + reinterpret_cast<PVOID*>(&propertyId), + nullptr + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + size_t argumentLength = InputBufferLength - sizeof(PosPropertyId); + void* argumentData = (void*)(propertyId + 1); + + // Handle this set of writable properties + switch (*propertyId) + { + case PosPropertyId::IsEnabled: + // BOOL value + if (argumentLength >= sizeof(BOOL)) + { + // The driver should use this value to ensure the device is ready to take data. + // The value may also need to be cached in a device context object so that it can be returned in GetProperty(IsEnabled) + BOOL isEnabled = *((BOOL*)argumentData); + UNREFERENCED_PARAMETER(isEnabled); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + case PosPropertyId::IsDisabledOnDataReceived: + // BOOL value + if (argumentLength >= sizeof(BOOL)) + { + // Typically this value will get cached in the device context so that, when + // an MSR read occurs, the driver can disable the device. + BOOL isDisabledOnDataReceived = *((BOOL*)argumentData); + UNREFERENCED_PARAMETER(isDisabledOnDataReceived); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + case PosPropertyId::MagneticStripeReaderIsDecodeDataEnabled: + // BOOL value + if (argumentLength >= sizeof(BOOL)) + { + // Typically this value will get cached in the device context so that, when + // an MSR read occurs, the driver can decode the raw data to get the scan data label. + BOOL isDecodeDataEnabled = *((BOOL*)argumentData); + UNREFERENCED_PARAMETER(isDecodeDataEnabled); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + case PosPropertyId::MagneticStripeReaderErrorReportingType: + // MsrErrorReportingType value + if (argumentLength >= sizeof(MsrErrorReportingType)) + { + // Typically this value will get cached in the device context so that, when + // a failed MSR read occurs, the driver can report the error correctly + MsrErrorReportingType errorReporting = *((MsrErrorReportingType*)argumentData); + UNREFERENCED_PARAMETER(errorReporting); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + case PosPropertyId::MagneticStripeReaderTracksToRead: + // MsrTrackIds value + if (argumentLength >= sizeof(MsrErrorReportingType)) + { + // This value will either be sent to the device to limit the tracks that are read, + // or cached in the device context so that the driver can only report the given tracks + // during an MSR read. + MsrTrackIds tracksToRead = *((MsrTrackIds*)argumentData); + UNREFERENCED_PARAMETER(tracksToRead); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + case PosPropertyId::MagneticStripeReaderIsTransmitSentinelsEnabled: + // BOOL value + if (argumentLength >= sizeof(BOOL)) + { + // This value will either be sent to the device to enable or disable sending sentinel data, + // or cached in the device context so that the driver can insert or remove the sentinel data during an MSR read. + BOOL isTransmitSentinelsEnabled = *((BOOL*)argumentData); + UNREFERENCED_PARAMETER(isTransmitSentinelsEnabled); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + case PosPropertyId::MagneticStripeReaderDataEncryptionAlgorithm: + // MsrDataEncryption value + if (argumentLength >= sizeof(MsrDataEncryption)) + { + // This property may be rejected if the SupportedEncryptionAlgorithms capability indicates that no encryption is supported. + // Otherwise it should set the current decryption algorithm (either by sending it to the device or by caching it for use + // by the driver during an MSR read). + MsrDataEncryption encryptionAlgorithm = *((MsrDataEncryption*)argumentData); + UNREFERENCED_PARAMETER(encryptionAlgorithm); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + default: + // no other writable properties for magnetic stripe reader + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +/* +** Driver TODO: Replace the data in the ProcessRetrieveStatisticsRequest with your own statistics data +** +** Implement this function to handle retrieve statistics requests. +*/ +NTSTATUS ProcessRetrieveStatisticsRequest(_In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _Inout_ ULONG_PTR* Information) +{ + if (Information == nullptr || Request == nullptr) + { + return STATUS_INVALID_PARAMETER; + } + + struct + { + PosStatisticsHeader Header; + PosValueStatisticsEntry Entries[1]; + } StatisticsData; + + StatisticsData.Header.DataLength = sizeof(StatisticsData); + wcscpy_s(StatisticsData.Header.DeviceInformation.DeviceCategory, L"MSR"); + wcscpy_s(StatisticsData.Header.DeviceInformation.FirmwareRevision, L"<eg, 1.1>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.InstallationDate, L"<installation date>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.Interface, L"<eg, USB>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.ManufactureDate, L"<eg, 2015/03/17>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.ManufacturerName, L"<eg, Conteso>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.MechanicalRevision, L"<eg, 2.0a>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.ModelName, L"<eg, MSR Model M>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.SerialNumber, L"<eg, 12345>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.UnifiedPOSVersion, L"1.14"); + StatisticsData.Header.EntryCount = 1; + wcscpy_s(StatisticsData.Entries[0].EntryName, L"<device specific statistics value>"); + StatisticsData.Entries[0].Value = (LONG)1; + + // This IOCTL is called twice by the Windows.Devices.PointOfService APIs + // The first time will just retrieve the header to determine how big the buffer needs to be. + PVOID outputBuffer; + NTSTATUS status = WdfRequestRetrieveOutputBuffer( + Request, + sizeof(PosStatisticsHeader), + &outputBuffer, + nullptr + ); + + if (!NT_SUCCESS(status)) + { + *Information = sizeof(StatisticsData); + return status; + } + + if (OutputBufferLength == sizeof(PosStatisticsHeader)) + { + memcpy(outputBuffer, &(StatisticsData.Header), sizeof(PosStatisticsHeader)); + *Information = sizeof(PosStatisticsHeader); + } + else if (OutputBufferLength < sizeof(StatisticsData)) + { + *Information = sizeof(StatisticsData); + status = STATUS_BUFFER_TOO_SMALL; + } + else + { + memcpy(outputBuffer, &StatisticsData, sizeof(StatisticsData)); + *Information = sizeof(StatisticsData); + } + + return status; +} + +/* +** Driver TODO: loop over statisticsEntry[0]...statisticsEntry[inputBuffer->EntryCount - 1] and reset each statistics value named +** +** Implement this function to handle statistics reset requests. +*/ +NTSTATUS ProcessResetStatisticsRequest(_In_ WDFREQUEST Request) +{ + if (Request == nullptr) + { + return STATUS_INVALID_PARAMETER; + } + + // The input buffer must be PosStatisticsHeader followed by one or more PosValueStatisticsEntry (where the value is ignored, just the name is used to + // reset the statistics value). + PosStatisticsHeader* inputBuffer; + size_t totalLength; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(PosStatisticsHeader), + (PVOID*)&inputBuffer, + &totalLength); + + if (!NT_SUCCESS(status)) + { + return status; + } + + if (inputBuffer->DataLength > totalLength) + { + return STATUS_BUFFER_TOO_SMALL; + } + + size_t entryLength = inputBuffer->DataLength - sizeof(PosStatisticsHeader); + if ( + entryLength % sizeof(PosValueStatisticsEntry) || + (entryLength / sizeof(PosValueStatisticsEntry)) != inputBuffer->EntryCount || + inputBuffer->EntryCount == 0 + ) + { + return STATUS_INVALID_PARAMETER; + } + + PosValueStatisticsEntry* statisticsEntry = (PosValueStatisticsEntry*) (inputBuffer + 1); + + for (UINT32 index = 0; index < inputBuffer->EntryCount; ++index) + { + // reset this value: + statisticsEntry[index].EntryName; + } + + return STATUS_SUCCESS; +} + +/* +** Driver TODO: loop over statisticsEntry[0]...statisticsEntry[inputBuffer->EntryCount - 1] and update each statistics value named +** +** Implement this function to handle statistics update requests. +*/ +NTSTATUS ProcessUpdateStatisticsRequest(_In_ WDFREQUEST Request) +{ + if (Request == nullptr) + { + return STATUS_INVALID_PARAMETER; + } + + // The input buffer must be PosStatisticsHeader followed by one or more PosValueStatisticsEntry + PosStatisticsHeader* inputBuffer; + size_t totalLength; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(PosStatisticsHeader), + (PVOID*)&inputBuffer, + &totalLength); + + if (!NT_SUCCESS(status)) + { + return status; + } + + if (inputBuffer->DataLength > totalLength) + { + return STATUS_BUFFER_TOO_SMALL; + } + + size_t entryLength = inputBuffer->DataLength - sizeof(PosStatisticsHeader); + if ( + entryLength % sizeof(PosValueStatisticsEntry) || + (entryLength / sizeof(PosValueStatisticsEntry)) != inputBuffer->EntryCount || + inputBuffer->EntryCount == 0 + ) + { + return STATUS_INVALID_PARAMETER; + } + + PosValueStatisticsEntry* statisticsEntry = (PosValueStatisticsEntry*)(inputBuffer + 1); + + for (UINT32 index = 0; index < inputBuffer->EntryCount; ++index) + { + // update the statistics entry: + statisticsEntry[index].EntryName; + // with the value: + statisticsEntry[index].Value; + } + + return STATUS_SUCCESS; +} + +/* +** Driver TODO: Add code to ProcessCheckHealthRequest to handle different health check cases. The result should be a localized string that is returned to the user in the output buffer of the IOCTL. +** +** Implement this function to handle health check requests. +*/ +NTSTATUS ProcessCheckHealthRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information) +{ + if (Information == nullptr || Request == nullptr) + { + return STATUS_INVALID_PARAMETER; + } + + DriverUnifiedPosHealthCheckLevel* level; + + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(DriverUnifiedPosHealthCheckLevel), + (PVOID*)&level, + nullptr); + + if (!NT_SUCCESS(status)) + { + return status; + } + + PosStringType* outputBuffer; + size_t outputBufferLength; + status = WdfRequestRetrieveOutputBuffer( + Request, + sizeof(PosStringType), + (void**)(&outputBuffer), + &outputBufferLength + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + switch (*level) + { + case DriverUnifiedPosHealthCheckLevel::POSInternal: + case DriverUnifiedPosHealthCheckLevel::External: + case DriverUnifiedPosHealthCheckLevel::Interactive: + { + // Handle the specific health check level, depending on the applicability to your device. + // Return the result as a string that the user can use to determine whether the device is + // operational or needs attention. + LPCWSTR result = L"OK"; + size_t lengthInBytes = wcslen(result) * sizeof(WCHAR); + status = RtlSizeTToUInt32(lengthInBytes, &(outputBuffer->DataLengthInBytes)); + if (NT_SUCCESS(status)) + { + *Information = sizeof(PosStringType); + if (outputBufferLength >= sizeof(PosStringType)+outputBuffer->DataLengthInBytes) + { + void* outputStringStart = (void*)(outputBuffer + 1); + memcpy(outputStringStart, result, outputBuffer->DataLengthInBytes); + *Information += outputBuffer->DataLengthInBytes; + } + else + { + status = STATUS_BUFFER_OVERFLOW; + } + } + } + break; + default: + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +/* +** Driver TODO: +** +** Implement this function to handle the initial handshake IOCTL for Windows.Devices.PointOfService API <-> Driver communication. +** This sample will likely work for most cases. +*/ +NTSTATUS ProcessGetDeviceBasicsRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information) +{ + if (Information == nullptr || Request == nullptr) + { + return STATUS_INVALID_PARAMETER; + } + + UINT32* runtimeVersion; + PosDeviceBasicsType* outputData; + + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(UINT32), + (PVOID*)&runtimeVersion, + nullptr); + + if (!NT_SUCCESS(status)) + { + return status; + } + + status = WdfRequestRetrieveOutputBuffer( + Request, + sizeof(PosDeviceBasicsType), + (PVOID*)&outputData, + nullptr); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // Tell the runtime what version of the POS IOCTL interface this driver supports so that + // it won't send IOCTLs that the driver doesn't support. + outputData->Version = POS_DRIVER_VERSION; + // This is a magnetic stripe reader driver + outputData->DeviceType = PosDeviceType::PosDeviceType_MagneticStripeReader; + // This value will be used to set the initial ReadFile buffer size. A small size that is + // likely to cover most of the data events is suggested. The runtime will grow the ReadFile + // buffer size as needed. + outputData->RecommendedBufferSize = 128; + + *Information = sizeof(PosDeviceBasicsType); + + return STATUS_SUCCESS; +} diff --git a/pos/drivers/MagneticStripeReader/Ioctl.h b/pos/drivers/MagneticStripeReader/Ioctl.h new file mode 100644 index 00000000..55f629f6 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/Ioctl.h @@ -0,0 +1,3 @@ +#pragma once + +EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControl; diff --git a/pos/drivers/MagneticStripeReader/MagneticStripeReader.sln b/pos/drivers/MagneticStripeReader/MagneticStripeReader.sln new file mode 100644 index 00000000..f1209ca7 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/MagneticStripeReader.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleMagneticStripeReaderDrv", "SampleMagneticStripeReaderDrv.vcxproj", "{F9DEC69D-2609-48DF-BE52-A0099482FB40}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F9DEC69D-2609-48DF-BE52-A0099482FB40}.Debug|Win32.ActiveCfg = Debug|Win32 + {F9DEC69D-2609-48DF-BE52-A0099482FB40}.Debug|Win32.Build.0 = Debug|Win32 + {F9DEC69D-2609-48DF-BE52-A0099482FB40}.Release|Win32.ActiveCfg = Release|Win32 + {F9DEC69D-2609-48DF-BE52-A0099482FB40}.Release|Win32.Build.0 = Release|Win32 + {F9DEC69D-2609-48DF-BE52-A0099482FB40}.Debug|x64.ActiveCfg = Debug|x64 + {F9DEC69D-2609-48DF-BE52-A0099482FB40}.Debug|x64.Build.0 = Debug|x64 + {F9DEC69D-2609-48DF-BE52-A0099482FB40}.Release|x64.ActiveCfg = Release|x64 + {F9DEC69D-2609-48DF-BE52-A0099482FB40}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/pos/drivers/MagneticStripeReader/PosEvents.cpp b/pos/drivers/MagneticStripeReader/PosEvents.cpp new file mode 100644 index 00000000..501a1a22 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/PosEvents.cpp @@ -0,0 +1,50 @@ +#include <pch.h> + +/* +** Driver TODO: Add code to EvtDeviceOwnershipChange to reset the device state to a default. +** +** PosCx calls this callback to signal that the ownership of the device has transitioned from one file handle +** to another. When this happens, app developers expect that the settings for the device are restored to a +** "default" state, so the driver should do what is necessary to satisfy that expectation here. +** +*/ +VOID EvtDeviceOwnershipChange(_In_ WDFDEVICE Device, _In_opt_ WDFFILEOBJECT OldOwnerFileObj, _In_opt_ WDFFILEOBJECT NewOwnerFileObj) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(OldOwnerFileObj); + UNREFERENCED_PARAMETER(NewOwnerFileObj); + + // This function signals that ownership has transitioned from one file handle to another (typically from one app to another). + // As a result, the driver is expected to reset all settings to a default state. +} + +/* +** Driver TODO: +** +** This part of the sample demonstrates how the driver will return data to the runtime. How this method would be called depends +** on the driver implementation. +*/ +VOID EvtOnMsrScanDataRetrieved(_In_ WDFDEVICE Device) +{ + // Events that the runtime can handle for a magnetic stripe reader device are: + // PosEventType::MagneticStripeReaderDataReceived -- the standard event with MSR data + // PosEventType::MagneticStripeReaderErrorOccurred -- an event that should be sent if an error occured while scanning data + // PosEventType::StatusUpdated -- an event to indicate changes to power state + // + // Additionally, the following event is sent to the runtime, but is handled entirely by PosCx + // PosEventType::ReleaseDeviceRequested + + // The following shows an example of sending MSR data + + MSR_DATA_RECEIVED dataReceivedEventInfo; + + // Fill in all the fields in MSR_DATA_RECEIVED + + // This call actually pends the data to be send to the WinRT APIs. + NTSTATUS status = PosCxPutPendingEvent(Device, MSR_INTERFACE_TAG, PosEventType::MagneticStripeReaderDataReceived, sizeof(dataReceivedEventInfo), &dataReceivedEventInfo, POS_CX_EVENT_ATTR_DATA); + + if (!NT_SUCCESS(status)) + { + // This should only happen in rare cases such as out of memory (or that the device or interface tag isn't found). The driver should most likely drop the event. + } +}
\ No newline at end of file diff --git a/pos/drivers/MagneticStripeReader/PosEvents.h b/pos/drivers/MagneticStripeReader/PosEvents.h new file mode 100644 index 00000000..817b3ad1 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/PosEvents.h @@ -0,0 +1,3 @@ +#pragma once + +EVT_POS_CX_DEVICE_OWNERSHIP_CHANGE EvtDeviceOwnershipChange; diff --git a/pos/drivers/MagneticStripeReader/README.md b/pos/drivers/MagneticStripeReader/README.md new file mode 100644 index 00000000..5530f60c --- /dev/null +++ b/pos/drivers/MagneticStripeReader/README.md @@ -0,0 +1,7 @@ +Magnetic Stripe Reader Driver Sample +==================================== +This sample serves as a template for creating a new Magnetic Stripe Reader driver. + +This sample uses UMDF 2.0 and enables basic functionality such as claiming and enabling the device for exclusive access. + +It serves as an example of how to include the libraries necessary to develop a PointOfService driver. Once a driver is developed using this template it can be compiled for, deployed, and used on x86, amd64, and ARM platforms.
\ No newline at end of file diff --git a/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.inf b/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.inf new file mode 100644 index 00000000..f3401127 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.inf @@ -0,0 +1,78 @@ +; +; SampleMagneticStripeReaderDrv.inf +; + +[Version] +Signature="$Windows NT$" +Class=Sample ; +ClassGuid={60B92AD1-5773-4FF7-82E3-9F83198325D6} ; +Provider=Standard,NT$ARCH$ +CatalogFile=SampleMagneticStripeReaderDrv.cat +DriverVer=06/25/2015,14.29.18.671 + +[Manufacturer] +%ManufacturerName%=Standard,NT$ARCH$ + +[Standard.NT$ARCH$] +%DeviceName%=MyDevice_Install, Root\SampleMagneticStripeReaderDrv ; + + +[ClassInstall32] +AddReg=SampleClass_RegistryAdd + +[SampleClass_RegistryAdd] +HKR,,,,%ClassName% +HKR,,Icon,,"-10" + +[SourceDisksFiles] +SampleMagneticStripeReaderDrv.dll=1 + +[SourceDisksNames] +1 = %DiskName% + +; =================== UMDF Device ================================== + +[MyDevice_Install.NT] +CopyFiles=UMDriverCopy + +[MyDevice_Install.NT.hw] + +[MyDevice_Install.NT.Services] +AddService=WUDFRd,0x000001fa,WUDFRD_ServiceInstall + +[MyDevice_Install.NT.CoInstallers] +AddReg=CoInstallers_AddReg + +[MyDevice_Install.NT.Wdf] +UmdfService=SampleMagneticStripeReaderDrv,SampleMagneticStripeReaderDrv_Install +UmdfServiceOrder=SampleMagneticStripeReaderDrv + +[SampleMagneticStripeReaderDrv_Install] +UmdfLibraryVersion=2.15.0 +ServiceBinary=%12%\UMDF\SampleMagneticStripeReaderDrv.dll +UmdfExtensions=PosCx0102 + +[WUDFRD_ServiceInstall] +DisplayName = %WudfRdDisplayName% +ServiceType = 1 +StartType = 3 +ErrorControl = 1 +ServiceBinary = %12%\WUDFRd.sys + +[CoInstallers_AddReg] +HKR,,CoInstallers32,0x00010000,"WUDFCoinstaller.dll" + +[DestinationDirs] +UMDriverCopy=12,UMDF ; copy to drivers\umdf + +[UMDriverCopy] +SampleMagneticStripeReaderDrv.dll + +; =================== Generic ================================== + +[Strings] +ManufacturerName="" ; +ClassName="Samples" ; +DiskName = "SampleMagneticStripeReaderDrv Installation Disk" +WudfRdDisplayName="Windows Driver Foundation - User-mode Driver Framework Reflector" +DeviceName="SampleMagneticStripeReaderDrv Device" diff --git a/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.vcxproj b/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.vcxproj new file mode 100644 index 00000000..a23fdcfb --- /dev/null +++ b/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.vcxproj @@ -0,0 +1,252 @@ +<?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> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{FA5835C3-4B1D-4B48-BE8E-2A9B5764932E}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{F3A9F934-71E7-434E-B9F4-486EF2F9B1D5}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>UMDF</DriverType> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>UMDF</DriverType> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>UMDF</DriverType> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>UMDF</DriverType> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <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|x64'"> + <TargetName>SampleMagneticStripeReaderDrv</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>SampleMagneticStripeReaderDrv</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>SampleMagneticStripeReaderDrv</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>SampleMagneticStripeReaderDrv</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\pos\1.1\poscxstub.lib</AdditionalDependencies> + <ModuleDefinitionFile>exports.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\pos\1.1\poscxstub.lib</AdditionalDependencies> + <ModuleDefinitionFile>exports.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\pos\1.1\poscxstub.lib</AdditionalDependencies> + <ModuleDefinitionFile>exports.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\pos\1.1\poscxstub.lib</AdditionalDependencies> + <ModuleDefinitionFile>exports.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="Device.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="Driver.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="File.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="Ioctl.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="IoRead.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="pchsrc.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Create</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="PosEvents.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + </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/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.vcxproj.Filters b/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.vcxproj.Filters new file mode 100644 index 00000000..6721e14e --- /dev/null +++ b/pos/drivers/MagneticStripeReader/SampleMagneticStripeReaderDrv.vcxproj.Filters @@ -0,0 +1,47 @@ +<?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>{52A5F13E-45A2-4076-ABBD-A9DD641BD180}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{BA08299B-8F7E-482D-9464-D2E1E3718EB8}</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>{BD45DA3A-8FEB-4DD6-BB19-6D73802A80B8}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{664C5380-85E0-4C11-B14E-3C7A80180599}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Device.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Driver.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="File.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Ioctl.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="IoRead.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="pchsrc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="PosEvents.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <None Include="exports.def"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/pos/drivers/MagneticStripeReader/exports.def b/pos/drivers/MagneticStripeReader/exports.def new file mode 100644 index 00000000..22dad17c --- /dev/null +++ b/pos/drivers/MagneticStripeReader/exports.def @@ -0,0 +1,2 @@ +LIBRARY "SampleMagneticStripeReaderDrv.dll" + diff --git a/pos/drivers/MagneticStripeReader/pch.h b/pos/drivers/MagneticStripeReader/pch.h new file mode 100644 index 00000000..5807e362 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/pch.h @@ -0,0 +1,23 @@ +#pragma once + +#include <windows.h> +#include <initguid.h> +#include <wdf.h> +#include <ntintsafe.h> + +#include "PointOfServiceCommonTypes.h" +#include "PointOfServiceDriverInterface.h" + +#include "PosCx.h" + +#include <new> + +#ifdef __cplusplus +extern "C" { +#endif +DRIVER_INITIALIZE DriverEntry; +#ifdef __cplusplus +} +#endif + +#define MSR_INTERFACE_TAG ((ULONG) '0RSM') diff --git a/pos/drivers/MagneticStripeReader/pchsrc.cpp b/pos/drivers/MagneticStripeReader/pchsrc.cpp new file mode 100644 index 00000000..17305716 --- /dev/null +++ b/pos/drivers/MagneticStripeReader/pchsrc.cpp @@ -0,0 +1 @@ +#include "pch.h"
\ No newline at end of file diff --git a/pos/drivers/barcodescanner/BarcodeScanner.sln b/pos/drivers/barcodescanner/BarcodeScanner.sln new file mode 100644 index 00000000..1072df65 --- /dev/null +++ b/pos/drivers/barcodescanner/BarcodeScanner.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SampleBarcodeScannerDrv", "SampleBarcodeScannerDrv.vcxproj", "{30F6FA25-B31E-46B0-AFBB-2AC9BA3319F0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {30F6FA25-B31E-46B0-AFBB-2AC9BA3319F0}.Debug|Win32.ActiveCfg = Debug|Win32 + {30F6FA25-B31E-46B0-AFBB-2AC9BA3319F0}.Debug|Win32.Build.0 = Debug|Win32 + {30F6FA25-B31E-46B0-AFBB-2AC9BA3319F0}.Release|Win32.ActiveCfg = Release|Win32 + {30F6FA25-B31E-46B0-AFBB-2AC9BA3319F0}.Release|Win32.Build.0 = Release|Win32 + {30F6FA25-B31E-46B0-AFBB-2AC9BA3319F0}.Debug|x64.ActiveCfg = Debug|x64 + {30F6FA25-B31E-46B0-AFBB-2AC9BA3319F0}.Debug|x64.Build.0 = Debug|x64 + {30F6FA25-B31E-46B0-AFBB-2AC9BA3319F0}.Release|x64.ActiveCfg = Release|x64 + {30F6FA25-B31E-46B0-AFBB-2AC9BA3319F0}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/pos/drivers/barcodescanner/Device.cpp b/pos/drivers/barcodescanner/Device.cpp new file mode 100644 index 00000000..d122e60a --- /dev/null +++ b/pos/drivers/barcodescanner/Device.cpp @@ -0,0 +1,101 @@ +#include <pch.h> + +#include "File.h" +#include "PosEvents.h" +#include "Ioctl.h" +#include "IoRead.h" + +/* +** Driver TODO: Complete the implementation of EvtDriverDeviceAdd for your specific device. +** +** WDF calls this callback when a device instance is added to the driver. Good drivers will do a lot of +** work here to set up everything necessary, such as adding callbacks for PNP power state changes. +** This function defines an IO queue for handling DeviceIoControl and file read requests, both of which are +** important to the POS barcode scanner model. +** +** Note that this is not a complete device add implementation, as the PNP power callbacks are not handled. +** Additionally, driver writers may wish to set up additional queues to serialize device property requests +** (see Ioctl.cpp for more info). +*/ +NTSTATUS EvtDriverDeviceAdd(_In_ WDFDRIVER /* UnusedDriver */, _Inout_ PWDFDEVICE_INIT DeviceInit) +{ + NTSTATUS status = STATUS_SUCCESS; + WDF_FILEOBJECT_CONFIG fileConfig; + WDF_OBJECT_ATTRIBUTES deviceAttributes; + WDF_OBJECT_ATTRIBUTES fileAttributes; + WDFDEVICE device; + + // Handle file events + WDF_FILEOBJECT_CONFIG_INIT( + &fileConfig, + EvtDeviceFileCreate, + EvtFileClose, + WDF_NO_EVENT_CALLBACK + ); + + WDF_OBJECT_ATTRIBUTES_INIT(&fileAttributes); + WdfDeviceInitSetFileObjectConfig( + DeviceInit, + &fileConfig, + &fileAttributes + ); + + // Create Device + WDF_OBJECT_ATTRIBUTES_INIT(&deviceAttributes); + status = WdfDeviceCreate( + &DeviceInit, + &deviceAttributes, + &device + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // Create a device interface for POS Barcode Scanner so that the device can be enumerated + status = WdfDeviceCreateDeviceInterface( + device, + &GUID_DEVINTERFACE_POS_SCANNER, + NULL + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // Initialize the POS library + POS_CX_ATTRIBUTES posCxAttributes; + POS_CX_ATTRIBUTES_INIT(&posCxAttributes); + posCxAttributes.EvtDeviceOwnershipChange = EvtDeviceOwnershipChange; + + status = PosCxInit(device, &posCxAttributes); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // Set up an IO queue to handle DeviceIoControl and ReadFile + WDF_IO_QUEUE_CONFIG queueConfig; + WDF_OBJECT_ATTRIBUTES attributes; + WDFQUEUE queue; + + WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchSequential); + queueConfig.EvtIoDeviceControl = EvtIoDeviceControl; + queueConfig.EvtIoRead = EvtIoRead; + + // Call us in PASSIVE_LEVEL + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.ExecutionLevel = WdfExecutionLevelPassive; + + status = WdfIoQueueCreate( + device, + &queueConfig, + &attributes, + &queue + ); + + return status; +} diff --git a/pos/drivers/barcodescanner/Device.h b/pos/drivers/barcodescanner/Device.h new file mode 100644 index 00000000..df9ad409 --- /dev/null +++ b/pos/drivers/barcodescanner/Device.h @@ -0,0 +1,3 @@ +#pragma once + +EVT_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd; diff --git a/pos/drivers/barcodescanner/Driver.cpp b/pos/drivers/barcodescanner/Driver.cpp new file mode 100644 index 00000000..5bcf2f33 --- /dev/null +++ b/pos/drivers/barcodescanner/Driver.cpp @@ -0,0 +1,54 @@ +#include <pch.h> + +#include "Device.h" + +// Forward declaration +VOID EvtDriverCleanup(_In_ WDFOBJECT DriverObject); + +/* +** Driver TODO: +** +** This is the main entry point of the driver. POS APIs require that the driver sets up additional data in device add. +** +** Note that your driver may have additional configuration to do in this function, and it should not be assumed that this sample is complete. +*/ +NTSTATUS DriverEntry( + PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath + ) +{ + WDF_DRIVER_CONFIG config; + NTSTATUS status = STATUS_SUCCESS; + WDF_OBJECT_ATTRIBUTES attributes; + + WDF_OBJECT_ATTRIBUTES_INIT(&attributes); + attributes.EvtCleanupCallback = EvtDriverCleanup; + + WDF_DRIVER_CONFIG_INIT( + &config, + EvtDriverDeviceAdd + ); + + status = WdfDriverCreate( + DriverObject, + RegistryPath, + &attributes, + &config, + WDF_NO_HANDLE + ); + + return status; +} + +/* +** Driver TODO: +** +** This is the cleanup callback for the driver (as set above in DriverEntry). +** PosCx requires no cleanup at this point. +*/ +_Use_decl_annotations_ +VOID EvtDriverCleanup(WDFOBJECT /* UnusedDriverObject */) +{ + // Do any cleanup needed here + return; +} diff --git a/pos/drivers/barcodescanner/File.cpp b/pos/drivers/barcodescanner/File.cpp new file mode 100644 index 00000000..43f100ee --- /dev/null +++ b/pos/drivers/barcodescanner/File.cpp @@ -0,0 +1,37 @@ +#include <pch.h> + +/* +** Driver TODO: +** +** WDF calls this callback when a file handle is opened to the driver. Your implementation may require additional setup (such as creating a +** file-handle-based context structure). PosCxOpen must be called during this callback. +*/ +VOID EvtDeviceFileCreate(_In_ WDFDEVICE Device, _In_ WDFREQUEST Request, _In_ WDFFILEOBJECT FileObject) +{ + NTSTATUS status = PosCxOpen(Device, FileObject, SCANNER_INTERFACE_TAG); + + if (!NT_SUCCESS(status)) + { + // This should only fail in rare cases, but the failure will prevent all PosCx functions from performing correctly + } + + WdfRequestComplete(Request, status); +} + +/* +** Driver TODO: +** +** WDF calls this callback when a file handle to the driver is closed. Your implementation may require additional cleanup, but +** PosCxClose must be called during this callback. +*/ +VOID EvtFileClose(_In_ WDFFILEOBJECT FileObject) +{ + WDFDEVICE device = WdfFileObjectGetDevice(FileObject); + + NTSTATUS status = PosCxClose(device, FileObject); + + if (!NT_SUCCESS(status)) + { + // This will only fail if PosCxInit wasn't called successfully in EvtDriverDeviceAdd, or if PosCxOpen failed in EvtDeviceFileCreate + } +}
\ No newline at end of file diff --git a/pos/drivers/barcodescanner/File.h b/pos/drivers/barcodescanner/File.h new file mode 100644 index 00000000..73f815e0 --- /dev/null +++ b/pos/drivers/barcodescanner/File.h @@ -0,0 +1,4 @@ +#pragma once + +EVT_WDF_DEVICE_FILE_CREATE EvtDeviceFileCreate; +EVT_WDF_FILE_CLOSE EvtFileClose; diff --git a/pos/drivers/barcodescanner/IoRead.cpp b/pos/drivers/barcodescanner/IoRead.cpp new file mode 100644 index 00000000..4f188d89 --- /dev/null +++ b/pos/drivers/barcodescanner/IoRead.cpp @@ -0,0 +1,41 @@ +#include <pch.h> + +/* +** Driver TODO: Add logic to EvtIoRead to handle read requests from applications that don't use the Windows.Devices.PointOfService APIs. +** +** This is the callback for the IO queue that handles file read requests. In the POS barcode +** scanner model, the application will always queue a read request in order to receive events +** such as the data received event, or the release-claim requested event. +** +** Note that apps that are developed against the Windows.Devices.PointOfService APIs will always +** expect event data to be returned by read requests. It is up to the driver to determine the +** behavior of ReadFile when the driver is opened by other types of applications. +*/ +VOID EvtIoRead(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t Length) +{ + NTSTATUS status; + WDFDEVICE device = WdfIoQueueGetDevice(Queue); + WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request); + + UNREFERENCED_PARAMETER(Length); + + // Check the flag that may have been set by PosCxMarkPosApp in Ioctl.cpp. + if (!PosCxIsPosApp(device, fileObject)) + { + // An application has opened a handle to this device without using the Windows.Devices.PointOfService APIs. + // You may change this to handle the read request differently. + + // In this example, just complete the read request with a failure. + WdfRequestComplete(Request, STATUS_UNSUCCESSFUL); + } + else + { + // If this returns success, it has taken ownership of Request + status = PosCxGetPendingEvent(device, Request); + + if (!NT_SUCCESS(status)) + { + WdfRequestComplete(Request, status); + } + } +}
\ No newline at end of file diff --git a/pos/drivers/barcodescanner/IoRead.h b/pos/drivers/barcodescanner/IoRead.h new file mode 100644 index 00000000..20f7dcdd --- /dev/null +++ b/pos/drivers/barcodescanner/IoRead.h @@ -0,0 +1,3 @@ +#pragma once + +EVT_WDF_IO_QUEUE_IO_READ EvtIoRead;
\ No newline at end of file diff --git a/pos/drivers/barcodescanner/Ioctl.cpp b/pos/drivers/barcodescanner/Ioctl.cpp new file mode 100644 index 00000000..e9c01dff --- /dev/null +++ b/pos/drivers/barcodescanner/Ioctl.cpp @@ -0,0 +1,720 @@ +#include <pch.h> + +NTSTATUS ProcessGetPropertyRequest(_In_ WDFREQUEST Request, _In_ size_t InputBufferLength, _Inout_ ULONG_PTR* Information); +NTSTATUS ProcessSetPropertyRequest(_In_ WDFREQUEST Request, _In_ size_t InputBufferLength, _Inout_ ULONG_PTR* Information); +NTSTATUS ProcessRetrieveStatisticsRequest(_In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _Inout_ ULONG_PTR* Information); +NTSTATUS ProcessResetStatisticsRequest(_In_ WDFREQUEST Request); +NTSTATUS ProcessUpdateStatisticsRequest(_In_ WDFREQUEST Request); +NTSTATUS ProcessCheckHealthRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information); +NTSTATUS ProcessGetDeviceBasicsRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information); + +/* +** Driver TODO: Complete the implementation of EvtIoDeviceControl for your specific device (if necessary) +** +** WDF calls this callback when a device instance is added to the driver. Good drivers will do a lot of +** work here to set up everything necessary, such as adding callbacks for PNP power state changes. +** This function defines an IO queue for handling DeviceIoControl and file read requests, both of which are +** important to the POS barcode scanner model. +** +** Note that this is not a complete device add implementation, as the PNP power callbacks are not handled. +** Additionally, driver writers may wish to set up additional queues to serialize device property requests +** (see Ioctl.cpp for more info). +*/ +VOID EvtIoDeviceControl(_In_ WDFQUEUE Queue, _In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _In_ size_t InputBufferLength, _In_ ULONG IoControlCode) +{ + UNREFERENCED_PARAMETER(Queue); + + NTSTATUS status = STATUS_SUCCESS; + ULONG_PTR information = 0; + WDFDEVICE device = WdfIoQueueGetDevice(Queue); + WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request); + + // These are the set of IOCTLs that your device should handle to work with the Windows.Devices.PointOfService APIs. + switch (IoControlCode) + { + // The first three IOCTLs shouldn't require additional processing other than handing them off to PosCx + case IOCTL_POINT_OF_SERVICE_CLAIM_DEVICE: + status = PosCxClaimDevice(device, Request); + break; + + case IOCTL_POINT_OF_SERVICE_RELEASE_DEVICE: + status = PosCxReleaseDevice(device, fileObject); + break; + + case IOCTL_POINT_OF_SERVICE_RETAIN_DEVICE: + status = PosCxRetainDevice(device, Request); + break; + + + case IOCTL_POINT_OF_SERVICE_GET_PROPERTY: + status = ProcessGetPropertyRequest(Request, InputBufferLength, &information); + break; + + case IOCTL_POINT_OF_SERVICE_SET_PROPERTY: + status = ProcessSetPropertyRequest(Request, InputBufferLength, &information); + break; + + case IOCTL_POINT_OF_SERVICE_RETRIEVE_STATISTICS: + status = ProcessRetrieveStatisticsRequest(Request, OutputBufferLength, &information); + break; + + case IOCTL_POINT_OF_SERVICE_RESET_STATISTICS: + status = ProcessResetStatisticsRequest(Request); + break; + + case IOCTL_POINT_OF_SERVICE_UPDATE_STATISTICS: + status = ProcessUpdateStatisticsRequest(Request); + break; + + case IOCTL_POINT_OF_SERVICE_CHECK_HEALTH: + status = ProcessCheckHealthRequest(Request, &information); + break; + + // The Get Device Basics IOCTL is always the first IOCTL called by an application using the Windows.Devices.PointOfService APIs. + // Use it to determine when to call PosCxMarkPosApp (see notes about apps marked this way in IoRead.cpp) + case IOCTL_POINT_OF_SERVICE_GET_DEVICE_BASICS: + status = ProcessGetDeviceBasicsRequest(Request, &information); + (void)PosCxMarkPosApp(device, fileObject, TRUE); + break; + + default: + // Your device may support additional IOCTLs. In this sample, we return failure for anything else. + status = STATUS_NOT_SUPPORTED; + break; + } + + if (status != STATUS_PENDING) + { + WdfRequestCompleteWithInformation(Request, status, information); + } +} + +/* +** Driver TODO: Add code to handle various get-property cases. +** +** Implement this function to handle property get requests. +*/ +NTSTATUS ProcessGetPropertyRequest(_In_ WDFREQUEST Request, _In_ size_t InputBufferLength, _Inout_ ULONG_PTR* Information) +{ + if (Information == nullptr || Request == nullptr || InputBufferLength < sizeof(PosPropertyId)) + { + return STATUS_INVALID_PARAMETER; + } + + // POS properties are identified by the property ID that's transmitted in the input buffer. + PosPropertyId* propertyId; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(PosPropertyId), + reinterpret_cast<PVOID*>(&propertyId), + nullptr + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // All get properties will need access to the output buffer in order to return results. + // The minimum size returned is a UINT32 + void* outputBuffer; + size_t outputBufferLength; + status = WdfRequestRetrieveOutputBuffer( + Request, + sizeof(UINT32), + &outputBuffer, + &outputBufferLength + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // Handle this set of readable properties + switch (*propertyId) + { + case PosPropertyId::IsEnabled: + // BOOL result, true when the app has called SetProperty(IsEnabled) = TRUE + { + BOOL isEnabled = TRUE; // Get this value from device context or by querying the device + *((BOOL*)outputBuffer) = isEnabled; + *Information = sizeof(BOOL); + } + break; + + case PosPropertyId::IsDisabledOnDataReceived: + // BOOL result, true when the app has called SetProperty(IsDisabledOnDataReceived) = TRUE + { + BOOL isDisabledOnDataReceived = TRUE; // Get this value from device context or by querying the device + *((BOOL*)outputBuffer) = isDisabledOnDataReceived; + *Information = sizeof(BOOL); + } + break; + + case PosPropertyId::BarcodeScannerIsDecodeDataEnabled: + // BOOL result, true when the app has called SetProperty(BarcodeScannerIsDecodeDataEnabled) = TRUE + { + BOOL isDecodeDataEnabled = TRUE; // Get this value from device context or by querying the device + *((BOOL*)outputBuffer) = isDecodeDataEnabled; + *Information = sizeof(BOOL); + } + break; + + case PosPropertyId::BarcodeScannerCapabilities: + { + // PosBarcodeScannerCapabilitiesType2 result + // These capabilities are likely hard-coded for the specific device + PosBarcodeScannerCapabilitiesType2 capabilities; + capabilities.PosBarcodeScannerCapabilities.IsImagePreviewSupported = TRUE; + capabilities.PosBarcodeScannerCapabilities.IsStatisticsReportingSupported = TRUE; + capabilities.PosBarcodeScannerCapabilities.IsStatisticsUpdatingSupported = TRUE; + capabilities.PosBarcodeScannerCapabilities.PowerReportingType = DriverUnifiedPosPowerReportingType::Standard; + capabilities.IsSoftwareTriggerSupported = TRUE; + size_t bytesToCopy = sizeof(PosBarcodeScannerCapabilitiesType2); + if (outputBufferLength < bytesToCopy) + { + bytesToCopy = outputBufferLength; + status = STATUS_BUFFER_OVERFLOW; + } + memcpy(outputBuffer, &capabilities, bytesToCopy); + *Information = bytesToCopy; + } + break; + + case PosPropertyId::BarcodeScannerSupportedSymbologies: + { + // Returns a length-prefixed array of symbologies + BarcodeSymbology exampleSymbologies[] = { BarcodeSymbology::Upca, BarcodeSymbology::Ean13, BarcodeSymbology::Pdf417 }; + UINT32* outputData = (UINT32*)outputBuffer; + size_t copiedDataLength = 0; + if (outputBufferLength >= sizeof(UINT32)) + { + *outputData = ARRAYSIZE(exampleSymbologies); + copiedDataLength += sizeof(UINT32); + } + for (UINT32 index = 0; index < ARRAYSIZE(exampleSymbologies); ++index) + { + if (copiedDataLength + sizeof(UINT32) > outputBufferLength) + { + break; + } + // Ensure the output array elements are stored as UINT32s + outputData[index + 1] = (UINT32)exampleSymbologies[index]; + copiedDataLength += sizeof(UINT32); + } + *Information = copiedDataLength; + } + break; + + case PosPropertyId::BarcodeScannerSupportedProfiles: + { + // Profiles are sets of settings that can be applied together. This property returns an encoded array of profile names + LPCWSTR exampleProfiles[] = { L"Profile1", L"Profile2" }; + + if (outputBufferLength >= sizeof(PosProfileType)) + { + PosProfileType* header = (PosProfileType*)outputBuffer; + header->BufferSize = sizeof(PosProfileType); + header->ProfileCount = 0; + + *Information = header->BufferSize; + + for (UINT32 profileIndex = 0; profileIndex < ARRAYSIZE(exampleProfiles); ++profileIndex) + { + UINT32 stringLen; + if (!NT_SUCCESS(status = RtlSizeTToUInt32(wcslen(exampleProfiles[profileIndex]), &stringLen))) + { + break; + } + + UINT32 stringLenInBytes = stringLen*sizeof(WCHAR); + + // If there's enough room in the output buffer, we can use the previous length as the starting point to copy the profile string + UINT32 previousLength = header->BufferSize; + + // each string has it's own header (that just contains the string length in bytes) + header->BufferSize += sizeof(PosStringType); + header->BufferSize += stringLenInBytes; + ++(header->ProfileCount); + + if (outputBufferLength >= header->BufferSize) + { + // There's enough room for this string + PosStringType* stringHeader = (PosStringType*)((BYTE*)outputBuffer + previousLength); + stringHeader->DataLengthInBytes = stringLenInBytes; + + WCHAR* stringStart = (WCHAR*)((BYTE*)outputBuffer + previousLength + sizeof(PosStringType)); + + // memcpy because we don't null terminate these strings + memcpy(stringStart, exampleProfiles[profileIndex], stringLenInBytes); + + *Information = header->BufferSize; + } + } + + if (header->BufferSize > outputBufferLength) + { + status = STATUS_BUFFER_OVERFLOW; + } + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + } + + break; + default: + // no other readable properties for barcode scanner + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +/* +** Driver TODO: Add code to handle various set-property cases. +** +** Implement this function to handle property set requests. +*/ +NTSTATUS ProcessSetPropertyRequest(_In_ WDFREQUEST Request, _In_ size_t InputBufferLength, _Inout_ ULONG_PTR* Information) +{ + if (Information == nullptr || Request == nullptr || InputBufferLength < sizeof(PosPropertyId)) + { + return STATUS_INVALID_PARAMETER; + } + + // POS properties are identified by the property ID that's transmitted in the input buffer. + // The data that is used to set the property immediately follows the property ID, so the input buffer must be big enough to contain both. + PosPropertyId* propertyId; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(PosPropertyId), + reinterpret_cast<PVOID*>(&propertyId), + nullptr + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + size_t argumentLength = InputBufferLength - sizeof(PosPropertyId); + void* argumentData = (void*)(propertyId + 1); + + // Handle this set of writable properties + switch (*propertyId) + { + case PosPropertyId::IsEnabled: + // BOOL value + if (argumentLength >= sizeof(BOOL)) + { + // The driver should use this value to ensure the device is ready to take data. + // The value may also need to be cached in a device context object so that it can be returned in GetProperty(IsEnabled) + BOOL isEnabled = *((BOOL*)argumentData); + UNREFERENCED_PARAMETER(isEnabled); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + case PosPropertyId::IsDisabledOnDataReceived: + // BOOL value + if (argumentLength >= sizeof(BOOL)) + { + // Typically this value will get cached in the device context so that, when + // a barcode scan occurs, the driver can disable the device. + BOOL isDisabledOnDataReceived = *((BOOL*)argumentData); + UNREFERENCED_PARAMETER(isDisabledOnDataReceived); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + case PosPropertyId::BarcodeScannerIsDecodeDataEnabled: + // BOOL value + if (argumentLength >= sizeof(BOOL)) + { + // Typically this value will get cached in the device context so that, when + // a barcode scan occurs, the driver can decode the raw data to get the scan data label. + BOOL isDecodeDataEnabled = *((BOOL*)argumentData); + UNREFERENCED_PARAMETER(isDecodeDataEnabled); + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + case PosPropertyId::BarcodeScannerActiveSymbologies: + // UINT32 array with length prefix value + if (argumentLength >= sizeof(UINT32)) + { + UINT32 symbologyCount = *((UINT32*)argumentData); + + // knowing the number of symbology values in the input buffer, we know how big the buffer should be. + // Add 1 to count to include the count value itself. + UINT32 requiredArgumentLength = (symbologyCount + 1) * sizeof(UINT32); + + if (argumentLength >= requiredArgumentLength) + { + // The driver can copy this array into the device context, so that it can look up the symbology + // of an incoming scan to see whether its valid to pass on to the application. + // Alternatively, if the hardware supports restricting the data to specific symbologies, the + // driver can do that now. + for (UINT32 index = 0; index < symbologyCount; ++index) + { + BarcodeSymbology symbologyValue = (BarcodeSymbology)((UINT32*)argumentData)[index + 1]; + UNREFERENCED_PARAMETER(symbologyValue); + } + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + } + else + { + status = STATUS_BUFFER_TOO_SMALL; + } + break; + + case PosPropertyId::BarcodeScannerActiveProfile: + // PosStringType value (length prefixed wide string) + if (argumentLength >= sizeof(PosStringType)) + { + PosStringType* header = (PosStringType*)argumentData; + if (argumentLength >= (sizeof(PosStringType)+header->DataLengthInBytes)) + { + WCHAR* profileName = (WCHAR*)(header + 1); + size_t profileLength = header->DataLengthInBytes / sizeof(WCHAR); + + // Determine the profile requested and apply the settings if found + if (!wcsncmp(L"Profile1", profileName, profileLength)) + { + // For example, apply Profile1 settings + } + } + } + break; + + default: + // no other writable properties for barcode scanner + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +/* +** Driver TODO: Replace the data in the ProcessRetrieveStatisticsRequest with your own statistics data +** +** Implement this function to handle retrieve statistics requests. +*/ +NTSTATUS ProcessRetrieveStatisticsRequest(_In_ WDFREQUEST Request, _In_ size_t OutputBufferLength, _Inout_ ULONG_PTR* Information) +{ + if (Information == nullptr || Request == nullptr) + { + return STATUS_INVALID_PARAMETER; + } + + struct + { + PosStatisticsHeader Header; + PosValueStatisticsEntry Entries[1]; + } StatisticsData; + + StatisticsData.Header.DataLength = sizeof(StatisticsData); + wcscpy_s(StatisticsData.Header.DeviceInformation.DeviceCategory, L"Scanner"); + wcscpy_s(StatisticsData.Header.DeviceInformation.FirmwareRevision, L"<eg, 1.1>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.InstallationDate, L"<installation date>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.Interface, L"<eg, USB>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.ManufactureDate, L"<eg, 2015/03/17>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.ManufacturerName, L"<eg, Conteso>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.MechanicalRevision, L"<eg, 2.0a>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.ModelName, L"<eg, Scanner III>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.SerialNumber, L"<eg, 12345>"); + wcscpy_s(StatisticsData.Header.DeviceInformation.UnifiedPOSVersion, L"1.14"); + StatisticsData.Header.EntryCount = 1; + wcscpy_s(StatisticsData.Entries[0].EntryName, L"<device specific statistics value>"); + StatisticsData.Entries[0].Value = (LONG)1; + + // This IOCTL is called twice by the Windows.Devices.PointOfService APIs + // The first time will just retrieve the header to determine how big the buffer needs to be. + PVOID outputBuffer; + NTSTATUS status = WdfRequestRetrieveOutputBuffer( + Request, + sizeof(PosStatisticsHeader), + &outputBuffer, + nullptr + ); + + if (!NT_SUCCESS(status)) + { + *Information = sizeof(StatisticsData); + return status; + } + + if (OutputBufferLength == sizeof(PosStatisticsHeader)) + { + memcpy(outputBuffer, &(StatisticsData.Header), sizeof(PosStatisticsHeader)); + *Information = sizeof(PosStatisticsHeader); + } + else if (OutputBufferLength < sizeof(StatisticsData)) + { + *Information = sizeof(StatisticsData); + status = STATUS_BUFFER_TOO_SMALL; + } + else + { + memcpy(outputBuffer, &StatisticsData, sizeof(StatisticsData)); + *Information = sizeof(StatisticsData); + } + + return status; +} + +/* +** Driver TODO: loop over statisticsEntry[0]...statisticsEntry[inputBuffer->EntryCount - 1] and reset each statistics value named +** +** Implement this function to handle statistics reset requests. +*/ +NTSTATUS ProcessResetStatisticsRequest(_In_ WDFREQUEST Request) +{ + if (Request == nullptr) + { + return STATUS_INVALID_PARAMETER; + } + + // The input buffer must be PosStatisticsHeader followed by one or more PosValueStatisticsEntry (where the value is ignored, just the name is used to + // reset the statistics value). + PosStatisticsHeader* inputBuffer; + size_t totalLength; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(PosStatisticsHeader), + (PVOID*)&inputBuffer, + &totalLength); + + if (!NT_SUCCESS(status)) + { + return status; + } + + if (inputBuffer->DataLength > totalLength) + { + return STATUS_BUFFER_TOO_SMALL; + } + + size_t entryLength = inputBuffer->DataLength - sizeof(PosStatisticsHeader); + if ( + entryLength % sizeof(PosValueStatisticsEntry) || + (entryLength / sizeof(PosValueStatisticsEntry)) != inputBuffer->EntryCount || + inputBuffer->EntryCount == 0 + ) + { + return STATUS_INVALID_PARAMETER; + } + + PosValueStatisticsEntry* statisticsEntry = (PosValueStatisticsEntry*) (inputBuffer + 1); + + for (UINT32 index = 0; index < inputBuffer->EntryCount; ++index) + { + // reset this value: + statisticsEntry[index].EntryName; + } + + return STATUS_SUCCESS; +} + +/* +** Driver TODO: loop over statisticsEntry[0]...statisticsEntry[inputBuffer->EntryCount - 1] and update each statistics value named +** +** Implement this function to handle statistics update requests. +*/ +NTSTATUS ProcessUpdateStatisticsRequest(_In_ WDFREQUEST Request) +{ + if (Request == nullptr) + { + return STATUS_INVALID_PARAMETER; + } + + // The input buffer must be PosStatisticsHeader followed by one or more PosValueStatisticsEntry + PosStatisticsHeader* inputBuffer; + size_t totalLength; + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(PosStatisticsHeader), + (PVOID*)&inputBuffer, + &totalLength); + + if (!NT_SUCCESS(status)) + { + return status; + } + + if (inputBuffer->DataLength > totalLength) + { + return STATUS_BUFFER_TOO_SMALL; + } + + size_t entryLength = inputBuffer->DataLength - sizeof(PosStatisticsHeader); + if ( + entryLength % sizeof(PosValueStatisticsEntry) || + (entryLength / sizeof(PosValueStatisticsEntry)) != inputBuffer->EntryCount || + inputBuffer->EntryCount == 0 + ) + { + return STATUS_INVALID_PARAMETER; + } + + PosValueStatisticsEntry* statisticsEntry = (PosValueStatisticsEntry*)(inputBuffer + 1); + + for (UINT32 index = 0; index < inputBuffer->EntryCount; ++index) + { + // update the statistics entry: + statisticsEntry[index].EntryName; + // with the value: + statisticsEntry[index].Value; + } + + return STATUS_SUCCESS; +} + +/* +** Driver TODO: Add code to ProcessCheckHealthRequest to handle different health check cases. The result should be a localized string that is returned to the user in the output buffer of the IOCTL. +** +** Implement this function to handle health check requests. +*/ +NTSTATUS ProcessCheckHealthRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information) +{ + if (Information == nullptr || Request == nullptr) + { + return STATUS_INVALID_PARAMETER; + } + + DriverUnifiedPosHealthCheckLevel* level; + + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(DriverUnifiedPosHealthCheckLevel), + (PVOID*)&level, + nullptr); + + if (!NT_SUCCESS(status)) + { + return status; + } + + PosStringType* outputBuffer; + size_t outputBufferLength; + status = WdfRequestRetrieveOutputBuffer( + Request, + sizeof(PosStringType), + (void**)(&outputBuffer), + &outputBufferLength + ); + + if (!NT_SUCCESS(status)) + { + return status; + } + + switch (*level) + { + case DriverUnifiedPosHealthCheckLevel::POSInternal: + case DriverUnifiedPosHealthCheckLevel::External: + case DriverUnifiedPosHealthCheckLevel::Interactive: + { + // Handle the specific health check level, depending on the applicability to your device. + // Return the result as a string that the user can use to determine whether the device is + // operational or needs attention. + LPCWSTR result = L"OK"; + size_t lengthInBytes = wcslen(result) * sizeof(WCHAR); + status = RtlSizeTToUInt32(lengthInBytes, &(outputBuffer->DataLengthInBytes)); + if (NT_SUCCESS(status)) + { + *Information = sizeof(PosStringType); + if (outputBufferLength >= sizeof(PosStringType)+outputBuffer->DataLengthInBytes) + { + void* outputStringStart = (void*)(outputBuffer + 1); + memcpy(outputStringStart, result, outputBuffer->DataLengthInBytes); + *Information += outputBuffer->DataLengthInBytes; + } + else + { + status = STATUS_BUFFER_OVERFLOW; + } + } + } + break; + + default: + return STATUS_INVALID_PARAMETER; + } + + return STATUS_SUCCESS; +} + +/* +** Driver TODO: +** +** Implement this function to handle the initial handshake IOCTL for Windows.Devices.PointOfService API <-> Driver communication. +** This sample will likely work for most cases. +*/ +NTSTATUS ProcessGetDeviceBasicsRequest(_In_ WDFREQUEST Request, _Inout_ ULONG_PTR* Information) +{ + if (Information == nullptr || Request == nullptr) + { + return STATUS_INVALID_PARAMETER; + } + + UINT32* runtimeVersion; + PosDeviceBasicsType* outputData; + + NTSTATUS status = WdfRequestRetrieveInputBuffer( + Request, + sizeof(UINT32), + (PVOID*)&runtimeVersion, + nullptr); + + if (!NT_SUCCESS(status)) + { + return status; + } + + if (*runtimeVersion < POS_VERSION_1_2) + { + // This runtime was for earlier versions of windows and doesn't support software trigger + } + + status = WdfRequestRetrieveOutputBuffer( + Request, + sizeof(PosDeviceBasicsType), + (PVOID*)&outputData, + nullptr); + + if (!NT_SUCCESS(status)) + { + return status; + } + + // Tell the runtime what version of the POS IOCTL interface this driver supports so that + // it won't send IOCTLs that the driver doesn't support. + outputData->Version = POS_DRIVER_VERSION; + // This is a barcode scanner driver + outputData->DeviceType = PosDeviceType::PosDeviceType_BarcodeScanner; + // This value will be used to set the initial ReadFile buffer size. A small size that is + // likely to cover most of the data events is suggested. The runtime will grow the ReadFile + // buffer size as needed. + outputData->RecommendedBufferSize = 128; + + *Information = sizeof(PosDeviceBasicsType); + + return STATUS_SUCCESS; +} diff --git a/pos/drivers/barcodescanner/Ioctl.h b/pos/drivers/barcodescanner/Ioctl.h new file mode 100644 index 00000000..55f629f6 --- /dev/null +++ b/pos/drivers/barcodescanner/Ioctl.h @@ -0,0 +1,3 @@ +#pragma once + +EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControl; diff --git a/pos/drivers/barcodescanner/PosEvents.cpp b/pos/drivers/barcodescanner/PosEvents.cpp new file mode 100644 index 00000000..1d2443bb --- /dev/null +++ b/pos/drivers/barcodescanner/PosEvents.cpp @@ -0,0 +1,97 @@ +#include <pch.h> + +/* +** Driver TODO: Add code to EvtDeviceOwnershipChange to reset the device state to a default. +** +** PosCx calls this callback to signal that the ownership of the device has transitioned from one file handle +** to another. When this happens, app developers expect that the settings for the device are restored to a +** "default" state, so the driver should do what is necessary to satisfy that expectation here. +** +*/ +VOID EvtDeviceOwnershipChange(_In_ WDFDEVICE Device, _In_opt_ WDFFILEOBJECT OldOwnerFileObj, _In_opt_ WDFFILEOBJECT NewOwnerFileObj) +{ + UNREFERENCED_PARAMETER(Device); + UNREFERENCED_PARAMETER(OldOwnerFileObj); + UNREFERENCED_PARAMETER(NewOwnerFileObj); + + // This function signals that ownership has transitioned from one file handle to another (typically from one app to another). + // As a result, the driver is expected to reset all settings to a default state. +} + +/* +** Driver TODO: +** +** This part of the sample demonstrates how the driver will return data to the runtime. How this method would be called depends +** on the driver implementation. +*/ +VOID EvtOnBarcodeScanDataRetrieved(_In_ WDFDEVICE Device) +{ + // Events that the runtime can handle for a barcode scanner device are: + // PosEventType::BarcodeScannerDataReceived -- the standard event with barcode scan data + // PosEventType::BarcodeScannerErrorOccurred -- an event that should be sent if an error occured while scanning data + // PosEventType::BarcodeScannerImagePreviewReceived -- an event that sends a complete .bmp image to the runtime for imagers + // PosEventType::BarcodeScannerTriggerPressed -- an event indicating that the trigger on the device has been pushed and the device is looking for data + // PosEventType::BarcodeScannerTriggerReleased -- an event indicating that the trigger on the device has been released and the device is no longer looking for data + // PosEventType::StatusUpdated -- an event to indicate changes to power state + // + // Additionally, the following event is sent to the runtime, but is handled entirely by PosCx + // PosEventType::ReleaseDeviceRequested + + // The following shows an example of sending barcode scan data + WCHAR exampleData[] = L"]0A12345"; + WCHAR exampleDataLabel[] = L"12345"; + + // total size is the struct plus the size of the two strings (minus the null terminators which aren't transmitted). + size_t totalSize = sizeof(PosBarcodeScannerDataReceivedEventData) + sizeof(exampleData) - sizeof(WCHAR) + sizeof(exampleDataLabel) - sizeof(WCHAR); + + + // PosCx supports two methods of pending the event data -- one where it takes the WDFMEMORY for the event, and the other where it creates it + // The subtle difference between the two is that the one that takes the WDFMEMORY must have the event header information already added. + // + // Since that's the case with the PosBarcodeScannerDataReceivedEventData data structure, barcode scanner drivers should create the WDFMEMORY objects + // and pass them to PosCx. + + WDF_OBJECT_ATTRIBUTES Attributes; + WDF_OBJECT_ATTRIBUTES_INIT(&Attributes); + Attributes.ParentObject = Device; + + BYTE* eventData = nullptr; + WDFMEMORY eventMemory = NULL; + NTSTATUS status = WdfMemoryCreate( + &Attributes, + NonPagedPoolNx, + (ULONG)'eSOP', + totalSize, + &eventMemory, + (PVOID*)&eventData + ); + + if (!NT_SUCCESS(status)) + { + // handle out of memory error + return; + } + + PosBarcodeScannerDataReceivedEventData* eventHeader = (PosBarcodeScannerDataReceivedEventData*)eventData; + eventHeader->Header.EventType = PosEventType::BarcodeScannerDataReceived; + eventHeader->Header.DataLength = (UINT32)totalSize; + eventHeader->DataType = BarcodeSymbology::Ean13; + + // These use memcpy because wcscpy would append the null terminator and the event data doesn't use it + BYTE* eventScanData = eventData + sizeof(PosBarcodeScannerDataReceivedEventData); + size_t exampleDataByteCount = sizeof(exampleData) - sizeof(WCHAR); + memcpy(eventScanData, exampleData, exampleDataByteCount); + BYTE* eventLabelData = eventScanData + exampleDataByteCount; + size_t exampleLabelByteCount = sizeof(exampleDataLabel) - sizeof(WCHAR); + memcpy(eventLabelData, exampleDataLabel, exampleLabelByteCount); + + + // This call actually pends the data to be send to the WinRT APIs. + status = PosCxPutPendingEventMemory(Device, SCANNER_INTERFACE_TAG, eventMemory, POS_CX_EVENT_ATTR_DATA); + + if (!NT_SUCCESS(status)) + { + // This should only happen in rare cases such as out of memory (or that the device or interface tag isn't found). The driver should most likely drop the event. + WdfObjectDelete(eventMemory); + } +}
\ No newline at end of file diff --git a/pos/drivers/barcodescanner/PosEvents.h b/pos/drivers/barcodescanner/PosEvents.h new file mode 100644 index 00000000..66ff095a --- /dev/null +++ b/pos/drivers/barcodescanner/PosEvents.h @@ -0,0 +1,3 @@ +#pragma once + +EVT_POS_CX_DEVICE_OWNERSHIP_CHANGE EvtDeviceOwnershipChange;
\ No newline at end of file diff --git a/pos/drivers/barcodescanner/README.md b/pos/drivers/barcodescanner/README.md new file mode 100644 index 00000000..8df934b3 --- /dev/null +++ b/pos/drivers/barcodescanner/README.md @@ -0,0 +1,7 @@ +Barcode Scanner Driver Sample +==================================== +This sample serves as a template for creating a new Barcode Scanner driver. + +This sample uses UMDF 2.0 and enables basic functionality such as claiming and enabling the device for exclusive access. + +It serves as an example of how to include the libraries necessary to develop a PointOfService driver. Once a driver is developed using this template it can be compiled for, deployed, and used on x86, amd64, and ARM platforms.
\ No newline at end of file diff --git a/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.inf b/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.inf new file mode 100644 index 00000000..9d32732f --- /dev/null +++ b/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.inf @@ -0,0 +1,78 @@ +; +; SampleBarcodeScannerDrv.inf +; + +[Version] +Signature="$Windows NT$" +Class=Sample ; +ClassGuid={70DF6E9F-68AA-4E29-AF0C-5AE9DB219214} ; +Provider=Standard,NT$ARCH$ +CatalogFile=SampleBarcodeScannerDrv.cat +DriverVer=06/25/2015,14.29.18.671 + +[Manufacturer] +%ManufacturerName%=Standard,NT$ARCH$ + +[Standard.NT$ARCH$] +%DeviceName%=MyDevice_Install, Root\SampleBarcodeScannerDrv ; + + +[ClassInstall32] +AddReg=SampleClass_RegistryAdd + +[SampleClass_RegistryAdd] +HKR,,,,%ClassName% +HKR,,Icon,,"-10" + +[SourceDisksFiles] +SampleBarcodeScannerDrv.dll=1 + +[SourceDisksNames] +1 = %DiskName% + +; =================== UMDF Device ================================== + +[MyDevice_Install.NT] +CopyFiles=UMDriverCopy + +[MyDevice_Install.NT.hw] + +[MyDevice_Install.NT.Services] +AddService=WUDFRd,0x000001fa,WUDFRD_ServiceInstall + +[MyDevice_Install.NT.CoInstallers] +AddReg=CoInstallers_AddReg + +[MyDevice_Install.NT.Wdf] +UmdfService=SampleBarcodeScannerDrv,SampleBarcodeScannerDrv_Install +UmdfServiceOrder=SampleBarcodeScannerDrv + +[SampleBarcodeScannerDrv_Install] +UmdfLibraryVersion=2.15.0 +ServiceBinary=%12%\UMDF\SampleBarcodeScannerDrv.dll +UmdfExtensions=PosCx0102 + +[WUDFRD_ServiceInstall] +DisplayName = %WudfRdDisplayName% +ServiceType = 1 +StartType = 3 +ErrorControl = 1 +ServiceBinary = %12%\WUDFRd.sys + +[CoInstallers_AddReg] +HKR,,CoInstallers32,0x00010000,"WUDFCoinstaller.dll" + +[DestinationDirs] +UMDriverCopy=12,UMDF ; copy to drivers\umdf + +[UMDriverCopy] +SampleBarcodeScannerDrv.dll + +; =================== Generic ================================== + +[Strings] +ManufacturerName="" ; +ClassName="Samples" ; +DiskName = "SampleBarcodeScannerDrv Installation Disk" +WudfRdDisplayName="Windows Driver Foundation - User-mode Driver Framework Reflector" +DeviceName="SampleBarcodeScannerDrv Device" diff --git a/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.vcxproj b/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.vcxproj new file mode 100644 index 00000000..cf354ec3 --- /dev/null +++ b/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.vcxproj @@ -0,0 +1,252 @@ +<?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> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{E08242CA-297F-4C12-A99F-EC78245117F5}</ProjectGuid> + <RootNamespace>$(MSBuildProjectName)</RootNamespace> + <UMDF_VERSION_MAJOR>2</UMDF_VERSION_MAJOR> + <Configuration Condition="'$(Configuration)' == ''">Debug</Configuration> + <Platform Condition="'$(Platform)' == ''">Win32</Platform> + <SampleGuid>{294BDD9E-A272-4E3A-804F-5C117FC85E08}</SampleGuid> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>UMDF</DriverType> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>UMDF</DriverType> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>False</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>UMDF</DriverType> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetVersion>Windows10</TargetVersion> + <UseDebugLibraries>True</UseDebugLibraries> + <DriverTargetPlatform>Desktop</DriverTargetPlatform> + <DriverType>UMDF</DriverType> + <PlatformToolset>WindowsUserModeDriver10.0</PlatformToolset> + <ConfigurationType>DynamicLibrary</ConfigurationType> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <PropertyGroup> + <OutDir>$(IntDir)</OutDir> + </PropertyGroup> + <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|x64'"> + <TargetName>SampleBarcodeScannerDrv</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <TargetName>SampleBarcodeScannerDrv</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <TargetName>SampleBarcodeScannerDrv</TargetName> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <TargetName>SampleBarcodeScannerDrv</TargetName> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <EntryPointSymbol Condition="'$(Platform)'=='win32'">_DllMainCRTStartup@12</EntryPointSymbol> + <EntryPointSymbol Condition="'$(Platform)'!='win32'">_DllMainCRTStartup</EntryPointSymbol> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <ExceptionHandling>Sync</ExceptionHandling> + <TreatWarningAsError>true</TreatWarningAsError> + <WarningLevel>Level4</WarningLevel> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ClCompile> + <ResourceCompile> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </ResourceCompile> + <Midl> + <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(DDK_INC_PATH);$(SDK_INC_PATH)\pos\1.1;..\inc</AdditionalIncludeDirectories> + </Midl> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\pos\1.1\poscxstub.lib</AdditionalDependencies> + <ModuleDefinitionFile>exports.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\pos\1.1\poscxstub.lib</AdditionalDependencies> + <ModuleDefinitionFile>exports.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\pos\1.1\poscxstub.lib</AdditionalDependencies> + <ModuleDefinitionFile>exports.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <Link> + <AdditionalDependencies>%(AdditionalDependencies);$(SDK_LIB_PATH)\pos\1.1\poscxstub.lib</AdditionalDependencies> + <ModuleDefinitionFile>exports.def</ModuleDefinitionFile> + </Link> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="Device.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="Driver.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="File.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="Ioctl.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="IoRead.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="pchsrc.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Create</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + <ClCompile Include="PosEvents.cpp"> + <AdditionalIncludeDirectories>;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreCompiledHeaderFile>pch.h</PreCompiledHeaderFile> + <PreCompiledHeader>Use</PreCompiledHeader> + <PreCompiledHeaderOutputFile>$(IntDir)\pch.h.pch</PreCompiledHeaderOutputFile> + </ClCompile> + </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/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.vcxproj.Filters b/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.vcxproj.Filters new file mode 100644 index 00000000..4268199b --- /dev/null +++ b/pos/drivers/barcodescanner/SampleBarcodeScannerDrv.vcxproj.Filters @@ -0,0 +1,47 @@ +<?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>{47F49773-F319-4591-B32D-BA38E9E75F22}</UniqueIdentifier> + </Filter> + <Filter Include="Header Files"> + <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions> + <UniqueIdentifier>{74AA7E37-6BDE-408A-AF19-36CBA1A80849}</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>{58E2BE2E-4AAA-48F9-95E8-65E24E014E15}</UniqueIdentifier> + </Filter> + <Filter Include="Driver Files"> + <Extensions>inf;inv;inx;mof;mc;</Extensions> + <UniqueIdentifier>{E145DF39-11C3-4472-BDA5-35448FA78D69}</UniqueIdentifier> + </Filter> + </ItemGroup> + <ItemGroup> + <ClCompile Include="Device.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Driver.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="File.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="Ioctl.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="IoRead.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="pchsrc.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="PosEvents.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <None Include="exports.def"> + <Filter>Source Files</Filter> + </None> + </ItemGroup> +</Project>
\ No newline at end of file diff --git a/pos/drivers/barcodescanner/exports.def b/pos/drivers/barcodescanner/exports.def new file mode 100644 index 00000000..a391d3b8 --- /dev/null +++ b/pos/drivers/barcodescanner/exports.def @@ -0,0 +1,2 @@ +LIBRARY "SampleBarcodeScannerDrv.dll" + diff --git a/pos/drivers/barcodescanner/pch.h b/pos/drivers/barcodescanner/pch.h new file mode 100644 index 00000000..b8afbb38 --- /dev/null +++ b/pos/drivers/barcodescanner/pch.h @@ -0,0 +1,23 @@ +#pragma once + +#include <windows.h> +#include <initguid.h> +#include <wdf.h> +#include <ntintsafe.h> + +#include "PointOfServiceCommonTypes.h" +#include "PointOfServiceDriverInterface.h" + +#include "PosCx.h" + +#include <new> + +#ifdef __cplusplus +extern "C" { +#endif +DRIVER_INITIALIZE DriverEntry; +#ifdef __cplusplus +} +#endif + +#define SCANNER_INTERFACE_TAG ((ULONG) '0SCB') diff --git a/pos/drivers/barcodescanner/pchsrc.cpp b/pos/drivers/barcodescanner/pchsrc.cpp new file mode 100644 index 00000000..17305716 --- /dev/null +++ b/pos/drivers/barcodescanner/pchsrc.cpp @@ -0,0 +1 @@ +#include "pch.h"
\ No newline at end of file |
