_Use_decl_annotations_ NTSTATUS TreeSampleCreateSecureDeviceContext( WDFDEVICE MasterDevice ) /*++ Routine Description: This routine is called when the secure environment is first started. Arguments: MasterDevice - Supplies a handle to the master device object. DeviceContext - Supplies a pointer to store any context information required for future calls. Return Value: NTSTATUS code. --*/ { WDF_OBJECT_ATTRIBUTES ContextAttributes; PTREE_SAMPLE_DEVICE_CONTEXT MasterContext; NTSTATUS Status; DECLARE_CONST_UNICODE_STRING(SymbolicLink, L"\\DosDevices\\SampleTrEEDriver"); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ContextAttributes, TREE_SAMPLE_DEVICE_CONTEXT); Status = WdfObjectAllocateContext(MasterDevice, &ContextAttributes, &MasterContext); if (!NT_SUCCESS(Status)) { goto TreeSampleCreateSecureDeviceContextEnd; } MasterContext->MasterDevice = MasterDevice; // // Create a symbolic link so that usermode program can access master device. // Status = WdfDeviceCreateSymbolicLink(MasterDevice, &SymbolicLink); if (!NT_SUCCESS(Status)) { goto TreeSampleCreateSecureDeviceContextEnd; } TreeSampleCreateSecureDeviceContextEnd: return Status; }
NTSTATUS HwSimInitialize( _In_ WDFDEVICE Device ) /*++ Routine Description: This routine initializes the hardware simulator Arguments: Device - Handle to the framework device object Return Value: An NTSTATUS value representing success or failure of the function. --*/ { NTSTATUS status; WDF_OBJECT_ATTRIBUTES objectAttributes; PHWSIM_CONTEXT devCtx; Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Entry\n"); // // Allocate our context for this device // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&objectAttributes, HWSIM_CONTEXT); status = WdfObjectAllocateContext((WDFOBJECT) Device, &objectAttributes, (PVOID*) &devCtx); if (FALSE == NT_SUCCESS(status)) { Trace(TRACE_LEVEL_ERROR, "%!FUNC! - WdfObjectAllocateContext failed with %!status!", status); goto exit; } devCtx->FirstD0Entry = TRUE; status = STATUS_SUCCESS; Trace(TRACE_LEVEL_INFORMATION, "%!FUNC! Exit\n"); exit: return status; }
VOID NdisProtEvtIoWrite( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length ) /*++ Routine Description: Dispatch routine to handle Request_MJ_WRITE. Arguments: Queue - Default queue handle Request - Handle to the read/write request Lenght - Length of the data buffer associated with the request. The default property of the queue is to not dispatch zero lenght read & write requests to the driver and complete is with status success. So we will never get a zero length request. Return Value: VOID --*/ { ULONG DataLength; NTSTATUS NtStatus; PNDISPROT_OPEN_CONTEXT pOpenContext; PNET_BUFFER_LIST pNetBufferList; NDISPROT_ETH_HEADER UNALIGNED *pEthHeader; PVOID CancelId; ULONG SendFlags = 0; PMDL pMdl = NULL; WDFFILEOBJECT fileObject; PREQUEST_CONTEXT reqContext; WDF_OBJECT_ATTRIBUTES attributes; UNREFERENCED_PARAMETER(Queue); fileObject = WdfRequestGetFileObject(Request); pOpenContext = GetFileObjectContext(fileObject)->OpenContext; do { // // Create a context to track the length of transfer and NDIS packet // associated with this request. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT); NtStatus = WdfObjectAllocateContext(Request, &attributes, &reqContext); if(!NT_SUCCESS(NtStatus)){ DEBUGP(DL_WARN, ("Write: WdfObjectAllocateContext failed: %x\n", NtStatus)); NtStatus = STATUS_INVALID_HANDLE; break; } reqContext->Length = (ULONG) Length; if (pOpenContext == NULL) { DEBUGP(DL_WARN, ("Write: FileObject %p not yet associated with a device\n", fileObject)); NtStatus = STATUS_INVALID_HANDLE; break; } NPROT_STRUCT_ASSERT(pOpenContext, oc); NtStatus = WdfRequestRetrieveInputWdmMdl(Request, &pMdl); if (!NT_SUCCESS(NtStatus)) { DEBUGP(DL_FATAL, ("Write: WdfRequestRetrieveInputWdmMdl failed %x\n", NtStatus)); break; } // // Try to get a virtual address for the MDL. // pEthHeader = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority | MdlMappingNoExecute); if (pEthHeader == NULL) { DEBUGP(DL_FATAL, ("Write: MmGetSystemAddr failed for" " Request %p, MDL %p\n", Request, pMdl)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; } // // Sanity-check the length. // DataLength = MmGetMdlByteCount(pMdl); if (DataLength < sizeof(NDISPROT_ETH_HEADER)) { DEBUGP(DL_WARN, ("Write: too small to be a valid packet (%d bytes)\n", DataLength)); NtStatus = STATUS_BUFFER_TOO_SMALL; break; } if (DataLength > (pOpenContext->MaxFrameSize + sizeof(NDISPROT_ETH_HEADER))) { DEBUGP(DL_WARN, ("Write: Open %p: data length (%d)" " larger than max frame size (%d)\n", pOpenContext, DataLength, pOpenContext->MaxFrameSize)); NtStatus = STATUS_INVALID_BUFFER_SIZE; break; } // // To prevent applications from sending packets with spoofed // mac address, we will do the following check to make sure the source // address in the packet is same as the current MAC address of the NIC. // if ((WdfRequestGetRequestorMode(Request) == UserMode) && !NPROT_MEM_CMP(pEthHeader->SrcAddr, pOpenContext->CurrentAddress, NPROT_MAC_ADDR_LEN)) { DEBUGP(DL_WARN, ("Write: Failing with invalid Source address")); NtStatus = STATUS_INVALID_PARAMETER; break; } NPROT_ACQUIRE_LOCK(&pOpenContext->Lock, FALSE); if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NPROTO_BIND_FLAGS, NPROTO_BIND_ACTIVE)) { NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); DEBUGP(DL_FATAL, ("Write: Open %p is not bound" " or in low power state\n", pOpenContext)); NtStatus = STATUS_INVALID_HANDLE; break; } if ((pOpenContext->State == NdisprotPaused) || (pOpenContext->State == NdisprotPausing)) { NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); DEBUGP(DL_INFO, ("Device is paused.\n")); NtStatus = STATUS_UNSUCCESSFUL; break; } NPROT_ASSERT(pOpenContext->SendNetBufferListPool != NULL); pNetBufferList = NdisAllocateNetBufferAndNetBufferList( pOpenContext->SendNetBufferListPool, sizeof(NPROT_SEND_NETBUFLIST_RSVD), //Request control offset delta 0, // back fill size pMdl, 0, // Data offset DataLength); if (pNetBufferList == NULL) { NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); DEBUGP(DL_FATAL, ("Write: open %p, failed to alloc send net buffer list\n", pOpenContext)); NtStatus = STATUS_INSUFFICIENT_RESOURCES; break; } pOpenContext->PendedSendCount++; NPROT_REF_OPEN(pOpenContext); // pended send // // Initialize the NetBufferList ref count. This NetBufferList will be freed // when this count goes to zero. // NPROT_SEND_NBL_RSVD(pNetBufferList)->RefCount = 1; // // We set up a cancel ID on each send NetBufferList (which maps to a Write IRP), // and save the NetBufferList pointer in the IRP. If the IRP gets cancelled, we use // NdisCancelSendNetBufferLists() to cancel the NetBufferList. // // Note that this sample code does not implement the cancellation logic. An actual // driver may find value in implementing this. // CancelId = NPROT_GET_NEXT_CANCEL_ID(); NDIS_SET_NET_BUFFER_LIST_CANCEL_ID(pNetBufferList, CancelId); reqContext->NetBufferList = (PVOID)pNetBufferList; NPROT_RELEASE_LOCK(&pOpenContext->Lock, FALSE); // // Set a back pointer from the packet to the IRP. // NPROT_REQUEST_FROM_SEND_NBL(pNetBufferList) = Request; NtStatus = STATUS_PENDING; pNetBufferList->SourceHandle = pOpenContext->BindingHandle; NPROT_ASSERT (pMdl->Next == NULL); SendFlags |= NDIS_SEND_FLAGS_CHECK_FOR_LOOPBACK; NdisSendNetBufferLists( pOpenContext->BindingHandle, pNetBufferList, NDIS_DEFAULT_PORT_NUMBER, SendFlags); } while (FALSE); if (NtStatus != STATUS_PENDING) { WdfRequestComplete(Request, NtStatus); } return; }
VOID NonPnpEvtDeviceIoInCallerContext( IN WDFDEVICE Device, IN WDFREQUEST Request ) /*++ Routine Description: This I/O in-process callback is called in the calling threads context/address space before the request is subjected to any framework locking or queueing scheme based on the device pnp/power or locking attributes set by the driver. The process context of the calling app is guaranteed as long as this driver is a top-level driver and no other filter driver is attached to it. This callback is only required if you are handling method-neither IOCTLs, or want to process requests in the context of the calling process. Driver developers should avoid defining neither IOCTLs and access user buffers, and use much safer I/O tranfer methods such as buffered I/O or direct I/O. Arguments: Device - Handle to a framework device object. Request - Handle to a framework request object. Framework calls PreProcess callback only for Read/Write/ioctls and internal ioctl requests. Return Value: VOID --*/ { NTSTATUS status = STATUS_SUCCESS; PREQUEST_CONTEXT reqContext = NULL; WDF_OBJECT_ATTRIBUTES attributes; WDF_REQUEST_PARAMETERS params; size_t inBufLen, outBufLen; PVOID inBuf, outBuf; PAGED_CODE(); WDF_REQUEST_PARAMETERS_INIT(¶ms); WdfRequestGetParameters(Request, ¶ms ); TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Entered NonPnpEvtDeviceIoInCallerContext %p \n", Request); // // Check to see whether we have recevied a METHOD_NEITHER IOCTL. if not // just send the request back to framework because we aren't doing // any pre-processing in the context of the calling thread process. // if(!(params.Type == WdfRequestTypeDeviceControl && params.Parameters.DeviceIoControl.IoControlCode == IOCTL_NONPNP_METHOD_NEITHER)) { // // Forward it for processing by the I/O package // status = WdfDeviceEnqueueRequest(Device, Request); if( !NT_SUCCESS(status) ) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error forwarding Request 0x%x", status); goto End; } return; } TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "EvtIoPreProcess: received METHOD_NEITHER ioctl \n"); // // In this type of transfer, the I/O manager assigns the user input // to Type3InputBuffer and the output buffer to UserBuffer of the Irp. // The I/O manager doesn't copy or map the buffers to the kernel // buffers. // status = WdfRequestRetrieveUnsafeUserInputBuffer(Request, 0, &inBuf, &inBufLen); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfRequestRetrieveUnsafeUserInputBuffer failed 0x%x", status); goto End; } status = WdfRequestRetrieveUnsafeUserOutputBuffer(Request, 0, &outBuf, &outBufLen); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfRequestRetrieveUnsafeUserOutputBuffer failed 0x%x", status); goto End; } // // Allocate a context for this request so that we can store the memory // objects created for input and output buffer. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, REQUEST_CONTEXT); status = WdfObjectAllocateContext(Request, &attributes, &reqContext); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfObjectAllocateContext failed 0x%x", status); goto End; } // // WdfRequestProbleAndLockForRead/Write function checks to see // whether the caller in the right thread context, creates an MDL, // probe and locks the pages, and map the MDL to system address // space and finally creates a WDFMEMORY object representing this // system buffer address. This memory object is associated with the // request. So it will be freed when the request is completed. If we // are accessing this memory buffer else where, we should store these // pointers in the request context. // #pragma prefast(suppress:6387, "If inBuf==NULL at this point, then inBufLen==0") status = WdfRequestProbeAndLockUserBufferForRead(Request, inBuf, inBufLen, &reqContext->InputMemoryBuffer); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfRequestProbeAndLockUserBufferForRead failed 0x%x", status); goto End; } #pragma prefast(suppress:6387, "If outBuf==NULL at this point, then outBufLen==0") status = WdfRequestProbeAndLockUserBufferForWrite(Request, outBuf, outBufLen, &reqContext->OutputMemoryBuffer); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfRequestProbeAndLockUserBufferForWrite failed 0x%x", status); goto End; } // // Finally forward it for processing by the I/O package // status = WdfDeviceEnqueueRequest(Device, Request); if(!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_IOCTL, "Error WdfDeviceEnqueueRequest failed 0x%x", status); goto End; } return; End: TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "EvtIoPreProcess failed %x \n", status); WdfRequestComplete(Request, status); return; }
NTSTATUS NfcCxEvtDeviceInitialize( _In_ PNFCCX_DRIVER_GLOBALS NfcCxGlobals, _In_ WDFDEVICE Device ) /*++ Routine Description: This routine is called by the CX client to indicate that a device initialization is required. Arguments: NfcCxGlobal - CX global pointer Device - WDF device to initialize Return Value: NTSTATUS --*/ { NTSTATUS status = STATUS_SUCCESS; WDF_OBJECT_ATTRIBUTES fdoAttributes; WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS idleSettings; WDF_IO_QUEUE_CONFIG queueConfig; PNFCCX_FDO_CONTEXT fdoContext; WDFQUEUE queue; PNFCCX_CLIENT_GLOBALS nfcCxClientGlobal; WDF_OBJECT_ATTRIBUTES objectAttrib; TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); if (!VerifyPrivateGlobals(NfcCxGlobals)) { TRACE_LINE(LEVEL_ERROR, "Invalid CX global pointer"); status = STATUS_INVALID_PARAMETER; goto Done; } nfcCxClientGlobal = GetPrivateGlobals(NfcCxGlobals); // // Create class extension device context // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&fdoAttributes, NFCCX_FDO_CONTEXT); fdoAttributes.EvtCleanupCallback = NfcCxFdoContextCleanup; status = WdfObjectAllocateContext(Device, &fdoAttributes, (PVOID*)&fdoContext); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "Failed to allocate the client context"); goto Done; } fdoContext->Device = Device; fdoContext->NfpRadioInterfaceCreated = FALSE; fdoContext->NfpPowerOffSystemOverride = FALSE; fdoContext->NfpPowerOffPolicyOverride = FALSE; fdoContext->NfpPowerPolicyReferences = 0; fdoContext->SERadioInterfaceCreated = FALSE; fdoContext->SEPowerOffSystemOverride = FALSE; fdoContext->SEPowerOffPolicyOverride = FALSE; fdoContext->SEPowerPolicyReferences = 0; fdoContext->NfcCxClientGlobal = nfcCxClientGlobal; status = NfcCxFdoReadCxDriverRegistrySettings(&fdoContext->LogNciDataMessages); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "NfcCxFdoReadCxDriverRegistrySettings failed, %!STATUS!", status); goto Done; } WDF_OBJECT_ATTRIBUTES_INIT(&objectAttrib); objectAttrib.ParentObject = Device; status = WdfWaitLockCreate(&objectAttrib, &fdoContext->PowerPolicyWaitLock); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "Failed to create the PowerPolicy WaitLock, %!STATUS!", status); goto Done; } // // Register I/O callbacks to tell the framework that you are interested // in handling IRP_MJ_DEVICE_CONTROL requests. // // In case a specific handler is not specified for one of these, // the request will be dispatched to the EvtIoDefault handler, if any. // If there is no EvtIoDefault handler, the request will be failed with // STATUS_INVALID_DEVICE_REQUEST. // // WdfIoQueueDispatchParallel means that we are capable of handling // all the I/O request simultaneously and we are responsible for protecting // data that could be accessed by these callbacks simultaneously. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel); // // Our default queue is non power managed. Based on the request and the Radio on/off // state, we forward the request to the power managed queue to wake the system as // appropriate // queueConfig.PowerManaged = WdfFalse; queueConfig.EvtIoDeviceControl = NfcCxEvtDefaultIoControl; WDF_OBJECT_ATTRIBUTES_INIT(&objectAttrib); objectAttrib.ParentObject = Device; status = WdfIoQueueCreate(Device, &queueConfig, &objectAttrib, &queue ); if (!NT_SUCCESS (status)) { TRACE_LINE(LEVEL_ERROR, "WdfIoQueueCreate failed %!STATUS!", status); goto Done; } fdoContext->DefaultQueue = queue; // // Our internal queue is non power managed because we need to send IO during. // D0Entry/D0Exit routines. It is the default queue for SelfIoTarget requests. // WDF_IO_QUEUE_CONFIG_INIT(&queueConfig, WdfIoQueueDispatchParallel); queueConfig.PowerManaged = WdfFalse; queueConfig.EvtIoDeviceControl = NfcCxEvtSelfIoControl; WDF_OBJECT_ATTRIBUTES_INIT(&objectAttrib); objectAttrib.ParentObject = Device; status = WdfIoQueueCreate(Device, &queueConfig, &objectAttrib, &queue ); if (!NT_SUCCESS (status)) { TRACE_LINE(LEVEL_ERROR, "WdfIoQueueCreate failed %!STATUS!", status); goto Done; } fdoContext->SelfQueue = queue; // // Assign our internal queue as the default queue for the SelfIoTarget. Any IO // sent to the SelfIoTarget would be dispatched from this queue. // status = WdfIoTargetSelfAssignDefaultIoQueue(WdfDeviceGetSelfIoTarget(Device), fdoContext->SelfQueue); if (!NT_SUCCESS (status)) { TRACE_LINE(LEVEL_ERROR, "WdfIoTargetSelfAssignDefaultIoQueue failed %!STATUS!", status); goto Done; } status = NfcCxFdoCreate(fdoContext); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "Failed to create the Fdo context failed %!STATUS!", status); goto Done; } if (NFC_CX_DEVICE_MODE_NCI == fdoContext->NfcCxClientGlobal->Config.DeviceMode) { // // Read the FDO's persisted settings from the registry // status = NfcCxFdoReadPersistedDeviceRegistrySettings(fdoContext); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "NfcCxFdoReadPersistedDeviceRegistrySettings, %!STATUS!", status); goto Done; } // // Log all settings that could have been overridden from the registry. // EventWriteDevicePersistedRegistrySettings(fdoContext->NfpPowerOffPolicyOverride, fdoContext->NfpPowerOffSystemOverride, fdoContext->SEPowerOffPolicyOverride, fdoContext->SEPowerOffSystemOverride); // // Check the currently required power state // fdoContext->NfpRadioState = (!fdoContext->NfpPowerOffPolicyOverride && !fdoContext->NfpPowerOffSystemOverride); fdoContext->SERadioState = (!fdoContext->SEPowerOffPolicyOverride && !fdoContext->SEPowerOffSystemOverride); } // // The class extension is the default power policy owner. This option allows the client // to now be the power policy owner // if (fdoContext->NfcCxClientGlobal->Config.IsPowerPolicyOwner == WdfUseDefault) { fdoContext->NfcCxClientGlobal->Config.IsPowerPolicyOwner = WdfFalse; } if (fdoContext->NfcCxClientGlobal->Config.IsPowerPolicyOwner == WdfFalse) { // // Set the idle power policy to put the device to Dx if the device is not used // for the specified IdleTimeout time. Since this is a non wakeable device we // tell the framework that we cannot wake ourself if we sleep in S0. Only // way the device can be brought to D0 is if the device recieves an I/O from // the system. // WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&idleSettings, IdleCannotWakeFromS0); idleSettings.IdleTimeoutType = fdoContext->NfcCxClientGlobal->Config.PowerIdleType; idleSettings.IdleTimeout = fdoContext->NfcCxClientGlobal->Config.PowerIdleTimeout; status = WdfDeviceAssignS0IdleSettings(Device, &idleSettings); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "WdfDeviceAssignS0IdleSettings failed %!STATUS!", status); goto Done; } } Done: TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); TRACE_LOG_NTSTATUS_ON_FAILURE(status); return status; }
/*++ Routine Description: Process mailbox property request. Arguments: DeviceContextPtr - Pointer to device context DataInPtr - Pointer to property data DataSize - Data size for input and output is the expected to be the same Request - WDF request object associated with this mailbox transaction Return Value: NTSTATUS --*/ _Use_decl_annotations_ NTSTATUS RpiqMailboxProperty ( DEVICE_CONTEXT* DeviceContextPtr, VOID* DataInPtr, ULONG DataSize, ULONG Channel, WDFREQUEST Request ) { NTSTATUS status; PHYSICAL_ADDRESS highAddress; PHYSICAL_ADDRESS lowAddress = { 0 }; PHYSICAL_ADDRESS boundaryAddress = { 0 }; PHYSICAL_ADDRESS addrProperty; RPIQ_REQUEST_CONTEXT* requestContextPtr; PAGED_CODE(); highAddress.QuadPart = HEX_1_G; if (DataInPtr == NULL || DataSize < sizeof(MAILBOX_HEADER)) { status = STATUS_INVALID_PARAMETER; goto End; } { WDF_OBJECT_ATTRIBUTES wdfObjectAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE( &wdfObjectAttributes, RPIQ_REQUEST_CONTEXT); wdfObjectAttributes.EvtCleanupCallback = RpiqRequestContextCleanup; status = WdfObjectAllocateContext( Request, &wdfObjectAttributes, &requestContextPtr); if (!NT_SUCCESS(status)) { RPIQ_LOG_WARNING( "WdfObjectAllocateContext() failed %!STATUS!)", status); goto End; } } // Firmware expects mailbox request to be in contiguous memory requestContextPtr->PropertyMemory = MmAllocateContiguousNodeMemory( DataSize, lowAddress, highAddress, boundaryAddress, PAGE_NOCACHE | PAGE_READWRITE, MM_ANY_NODE_OK); if (requestContextPtr->PropertyMemory == NULL) { RPIQ_LOG_ERROR("RpiqMailboxProperty fail to allocate memory"); status = STATUS_INSUFFICIENT_RESOURCES; goto End; } requestContextPtr->PropertyMemorySize = DataSize; addrProperty = MmGetPhysicalAddress(requestContextPtr->PropertyMemory); RtlCopyMemory(requestContextPtr->PropertyMemory, DataInPtr, DataSize); status = RpiqMailboxWrite( DeviceContextPtr, Channel, addrProperty.LowPart + OFFSET_DIRECT_SDRAM, Request); if (!NT_SUCCESS(status)) { RPIQ_LOG_ERROR("RpiqMailboxWrite failed %!STATUS!", status); goto End; } End: return status; }
NTSTATUS NfcCxSCPresentAbsentDispatcherSetRequest( _In_ PNFCCX_FDO_CONTEXT FdoContext, _In_ PNFCCX_SC_PRESENT_ABSENT_DISPATCHER Dispatcher, _In_ WDFREQUEST Request ) /*++ Routine Description: Stores a request in the dispatcher. If a request is already pending in the dispatcher, the new request will be completed with STATUS_DEVICE_BUSY. Arguments: FdoContext - Pointer to the FDO Context Dispatcher - Pointer to the Dispatcher. Request - The request to store in the dispatcher. Return Value: NTSTATUS --*/ { NTSTATUS status; bool powerReferenceAcquired = false; bool cancelCallbackSet = false; TRACE_FUNCTION_ENTRY(LEVEL_VERBOSE); WDFFILEOBJECT fileObject = WdfRequestGetFileObject(Request); PNFCCX_FILE_CONTEXT fileContext = NfcCxFileGetContext(fileObject); // Pre-check if there is a current request. if (ReadPointerAcquire((void**)&Dispatcher->CurrentRequest) != nullptr) { status = STATUS_DEVICE_BUSY; TRACE_LINE(LEVEL_ERROR, "An Is Present/Absent request is already pending. %!STATUS!", status); goto Done; } // Allocate and initialize the request context PNFCCX_SC_REQUEST_CONTEXT requestContext = nullptr; WDF_OBJECT_ATTRIBUTES contextAttributes; WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&contextAttributes, NFCCX_SC_REQUEST_CONTEXT); status = WdfObjectAllocateContext(Request, &contextAttributes, (void**)&requestContext); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "Failed to set request's context. %!STATUS!", status); goto Done; } requestContext->Dispatcher = Dispatcher; // Add a power reference (if required). if (Dispatcher->PowerManaged) { status = NfcCxPowerFileAddReference(FdoContext->Power, fileContext, NfcCxPowerReferenceType_Proximity); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_VERBOSE, "Failed to acquire power reference. %!STATUS!", status); goto Done; } powerReferenceAcquired = true; } // Setup cancel callback. status = WdfRequestMarkCancelableEx(Request, NfcCxSCPresentAbsentDispatcherRequestCanceled); if (!NT_SUCCESS(status)) { TRACE_LINE(LEVEL_ERROR, "Failed to set request canceled callback. %!STATUS!", status); goto Done; } // Add a ref-count to the request, which is owned by the cancel callback. WdfObjectReference(Request); cancelCallbackSet = true; // Try to set the current request. void* previousRequest = InterlockedCompareExchangePointer((void**)&Dispatcher->CurrentRequest, /*exchange*/ Request, /*compare*/ nullptr); // Check if we already have a pending request. if (previousRequest != nullptr) { status = STATUS_DEVICE_BUSY; TRACE_LINE(LEVEL_ERROR, "An Is Present/Absent request is already pending. %!STATUS!", status); goto Done; } Done: if (!NT_SUCCESS(status)) { if (cancelCallbackSet) { NTSTATUS unmarkStatus = WdfRequestUnmarkCancelable(Request); if (unmarkStatus != STATUS_CANCELLED) { // Cancel callback will not be called. // So release cancel callback's request ref-count. WdfObjectDereference(Request); } } if (powerReferenceAcquired) { NfcCxPowerFileRemoveReference(FdoContext->Power, fileContext, NfcCxPowerReferenceType_Proximity); } } TRACE_FUNCTION_EXIT_NTSTATUS(LEVEL_VERBOSE, status); return status; }
NTSTATUS RegistersCreate( _In_ WDFDEVICE Device, _In_ PCM_PARTIAL_RESOURCE_DESCRIPTOR RegistersResource ) /*++ Routine Description: Helper function to map the memory resources to the HW registers. Arguments: Device - Wdf device object corresponding to the FDO RegisterResource - Raw resource for the memory Return Value: Appropriate NTSTATUS value --*/ { NTSTATUS Status; PREGISTERS_CONTEXT Context; WDF_OBJECT_ATTRIBUTES Attributes; TraceEntry(); PAGED_CODE(); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&Attributes, REGISTERS_CONTEXT); Status = WdfObjectAllocateContext(Device, &Attributes, &Context); if (Status == STATUS_OBJECT_NAME_EXISTS) { // // In the case of a resource rebalance, the context allocated // previously still exists. // Status = STATUS_SUCCESS; RtlZeroMemory(Context, sizeof(*Context)); } CHK_NT_MSG(Status, "Failed to allocate context for registers"); Context->RegisterBase = MmMapIoSpaceEx( RegistersResource->u.Memory.Start, RegistersResource->u.Memory.Length, PAGE_NOCACHE | PAGE_READWRITE); if (Context->RegisterBase == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; CHK_NT_MSG(Status, "MmMapIoSpaceEx failed"); } Context->RegistersLength = RegistersResource->u.Memory.Length; End: TraceExit(); return Status; }
VOID SimSensorAddReadRequest ( _In_ WDFDEVICE Device, _In_ WDFREQUEST ReadRequest ) /*++ Routine Description: Handles IOCTL_THERMAL_READ_TEMPERATURE. If the request can be satisfied, it is completed immediately. Else, adds request to pending request queue. Arguments: Device - Supplies a handle to the device that received the request. ReadRequest - Supplies a handle to the request. --*/ { ULONG BytesReturned; PREAD_REQUEST_CONTEXT Context; WDF_OBJECT_ATTRIBUTES ContextAttributes; PFDO_DATA DevExt; LARGE_INTEGER ExpirationTime; size_t Length; BOOLEAN LockHeld; PULONG RequestTemperature; NTSTATUS Status; ULONG Temperature; WDFTIMER Timer; WDF_OBJECT_ATTRIBUTES TimerAttributes; WDF_TIMER_CONFIG TimerConfig; PTHERMAL_WAIT_READ ThermalWaitRead; DebugEnter(); PAGED_CODE(); DevExt = GetDeviceExtension(Device); BytesReturned = 0; LockHeld = FALSE; Status = WdfRequestRetrieveInputBuffer(ReadRequest, sizeof(THERMAL_WAIT_READ), &ThermalWaitRead, &Length); if (!NT_SUCCESS(Status) || Length != sizeof(THERMAL_WAIT_READ)) { // // This request is malformed, bail. // WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned); goto AddReadRequestEnd; } if (ThermalWaitRead->Timeout != -1 /* INFINITE */ ) { // // Estimate the system time this request will expire at. // KeQuerySystemTime(&ExpirationTime); ExpirationTime.QuadPart += ThermalWaitRead->Timeout * 10000; } else { // // Value which indicates the request never expires. // ExpirationTime.QuadPart = -1LL /* INFINITE */; } // // Handle the immediate timeout case in the fast path. // Temperature = SimSensorReadVirtualTemperature(Device); if (SimSensorAreConstraintsSatisfied(Temperature, ThermalWaitRead->LowTemperature, ThermalWaitRead->HighTemperature, ExpirationTime)) { Status = WdfRequestRetrieveOutputBuffer(ReadRequest, sizeof(ULONG), &RequestTemperature, &Length); if(NT_SUCCESS(Status) && Length == sizeof(ULONG)) { *RequestTemperature = Temperature; BytesReturned = sizeof(ULONG); } else { Status = STATUS_INVALID_PARAMETER; DebugPrint(SIMSENSOR_ERROR, "WdfRequestRetrieveOutputBuffer() Failed. 0x%x", Status); } WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned); } else { WdfWaitLockAcquire(DevExt->QueueLock, NULL); LockHeld = TRUE; // // Create a context to store request-specific information. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&ContextAttributes, READ_REQUEST_CONTEXT); Status = WdfObjectAllocateContext(ReadRequest, &ContextAttributes, &Context); if(!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfObjectAllocateContext() Failed. 0x%x", Status); WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned); goto AddReadRequestEnd; } Context->ExpirationTime.QuadPart = ExpirationTime.QuadPart; Context->LowTemperature = ThermalWaitRead->LowTemperature; Context->HighTemperature = ThermalWaitRead->HighTemperature; if(Context->ExpirationTime.QuadPart != -1LL /* INFINITE */ ) { // // This request eventually expires, create a timer to complete it. // WDF_TIMER_CONFIG_INIT(&TimerConfig, SimSensorExpiredRequestTimer); WDF_OBJECT_ATTRIBUTES_INIT(&TimerAttributes); TimerAttributes.ExecutionLevel = WdfExecutionLevelPassive; TimerAttributes.SynchronizationScope = WdfSynchronizationScopeNone; TimerAttributes.ParentObject = Device; Status = WdfTimerCreate(&TimerConfig, &TimerAttributes, &Timer); if(!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfTimerCreate() Failed. 0x%x", Status); WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned); goto AddReadRequestEnd; } WdfTimerStart(Timer, WDF_REL_TIMEOUT_IN_MS(ThermalWaitRead->Timeout)); } Status = WdfRequestForwardToIoQueue(ReadRequest, DevExt->PendingRequestQueue); if(!NT_SUCCESS(Status)) { DebugPrint(SIMSENSOR_ERROR, "WdfRequestForwardToIoQueue() Failed. 0x%x", Status); WdfRequestCompleteWithInformation(ReadRequest, Status, BytesReturned); goto AddReadRequestEnd; } // // Force a rescan of the queue to update the interrupt thresholds. // SimSensorScanPendingQueue(Device); } AddReadRequestEnd: if(LockHeld == TRUE) { WdfWaitLockRelease(DevExt->QueueLock); } DebugExitStatus(Status); }