int TestFuncDebug() { /* log the function entry log. */ LogFuncEntry(); LogTrace("Trace log %s %f", "Test", 1.066f); LogDebug("Debug level log" ); LogInfo("Info level log %d" , 0); LogWarn("Warn level log" ); LogError("Error level log" ); LogFatal("Fatal level log" ); if(1) { /* log the function exit. */ LogFuncExit(); return 0; } else { /* log the function exit. */ LogFuncExit(); return -1; } }
VOID otLwfEventProcessingIndicateAddressChange( _In_ PMS_FILTER pFilter, _In_ MIB_NOTIFICATION_TYPE NotificationType, _In_ PIN6_ADDR pAddr ) { LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p", pFilter); NT_ASSERT(pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_RADIO_MODE); POTLWF_ADDR_EVENT Event = FILTER_ALLOC_MEM(pFilter->FilterHandle, sizeof(OTLWF_ADDR_EVENT)); if (Event == NULL) { LogWarning(DRIVER_DEFAULT, "Failed to alloc new OTLWF_ADDR_EVENT"); } else { Event->NotificationType = NotificationType; Event->Address = *pAddr; // Add the event to the queue NdisAcquireSpinLock(&pFilter->EventsLock); InsertTailList(&pFilter->AddressChangesHead, &Event->Link); NdisReleaseSpinLock(&pFilter->EventsLock); // Set the event to indicate we have a new address to process KeSetEvent(&pFilter->EventWorkerThreadProcessAddressChanges, 0, FALSE); } LogFuncExit(DRIVER_DEFAULT); }
void otLwfTunUninitialize( _In_ PMS_FILTER pFilter ) { LogFuncEntry(DRIVER_DEFAULT); // Clean up worker thread if (pFilter->TunWorkerThread) { LogInfo(DRIVER_DEFAULT, "Stopping tunnel worker thread and waiting for it to complete."); // Send event to shutdown worker thread KeSetEvent(&pFilter->TunWorkerThreadStopEvent, 0, FALSE); // Wait for worker thread to finish KeWaitForSingleObject( pFilter->TunWorkerThread, Executive, KernelMode, FALSE, NULL ); // Free worker thread ObDereferenceObject(pFilter->TunWorkerThread); pFilter->TunWorkerThread = NULL; LogInfo(DRIVER_DEFAULT, "Tunnel worker thread cleaned up."); } LogFuncExit(DRIVER_DEFAULT); }
_Use_decl_annotations_ VOID FilterCancelOidRequest( NDIS_HANDLE FilterModuleContext, PVOID RequestId ) /*++ Routine Description: Cancels an OID request If your filter driver does not intercept and hold onto any OID requests, then you do not need to implement this routine. You may simply omit it. Furthermore, if the filter only holds onto OID requests so it can pass down a clone (the most common case) the filter does not need to implement this routine; NDIS will then automatically request that the lower-level filter/miniport cancel your cloned OID. Most filters do not need to implement this routine. Arguments: FilterModuleContext - our filter RequestId - identifies the request(s) to cancel --*/ { PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; PNDIS_OID_REQUEST Request = NULL; POTLWF_REQUEST_CONTEXT Context; PNDIS_OID_REQUEST OriginalRequest = NULL; BOOLEAN bFalse = FALSE; LogFuncEntryMsg(DRIVER_OID, "Filter: %p, RequestId: %p", FilterModuleContext, RequestId); FILTER_ACQUIRE_LOCK(&pFilter->PendingOidRequestLock, bFalse); Request = pFilter->PendingOidRequest; if (Request != NULL) { Context = (POTLWF_REQUEST_CONTEXT)(&Request->SourceReserved[0]); OriginalRequest = (*Context); } if ((OriginalRequest != NULL) && (OriginalRequest->RequestId == RequestId)) { FILTER_RELEASE_LOCK(&pFilter->PendingOidRequestLock, bFalse); NdisFCancelOidRequest(pFilter->FilterHandle, RequestId); } else { FILTER_RELEASE_LOCK(&pFilter->PendingOidRequestLock, bFalse); } LogFuncExit(DRIVER_OID); }
_Use_decl_annotations_ VOID FilterDetach( NDIS_HANDLE FilterModuleContext ) /*++ Routine Description: Filter detach routine. This is a required function that will deallocate all the resources allocated during FilterAttach. NDIS calls FilterAttach to remove a filter instance from a filter stack. Arguments: FilterModuleContext - pointer to the filter context area. Return Value: None. NOTE: Called at PASSIVE_LEVEL and the filter is in paused state --*/ { PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p", FilterModuleContext); // Filter must be in paused state and pretty much inactive NT_ASSERT(pFilter->State == FilterPaused); NT_ASSERT(pFilter->DeviceStatus == OTLWF_DEVICE_STATUS_UNINTIALIZED); // // Detach must not fail, so do not put any code here that can possibly fail. // // Remove this Filter from the global list NdisAcquireSpinLock(&FilterListLock); RemoveEntryList(&pFilter->FilterModuleLink); NdisReleaseSpinLock(&FilterListLock); // Unregister from address change notifications CancelMibChangeNotify2(pFilter->AddressChangeHandle); pFilter->AddressChangeHandle = NULL; // Close the registry key if (pFilter->InterfaceRegKey) { ZwClose(pFilter->InterfaceRegKey); pFilter->InterfaceRegKey = NULL; } // Free the memory allocated NdisFreeMemory(pFilter, 0, 0); LogFuncExit(DRIVER_DEFAULT); }
_Use_decl_annotations_ VOID FilterStatus( NDIS_HANDLE FilterModuleContext, PNDIS_STATUS_INDICATION StatusIndication ) /*++ Routine Description: Status indication handler Arguments: FilterModuleContext - our filter context StatusIndication - the status being indicated NOTE: called at <= DISPATCH_LEVEL FILTER driver may call NdisFIndicateStatus to generate a status indication to all higher layer modules. --*/ { PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p, IndicateStatus: %8x", FilterModuleContext, StatusIndication->StatusCode); if (StatusIndication->StatusCode == NDIS_STATUS_LINK_STATE) { PNDIS_LINK_STATE LinkState = (PNDIS_LINK_STATE)StatusIndication->StatusBuffer; LogInfo(DRIVER_DEFAULT, "Filter: %p, MediaConnectState: %u", FilterModuleContext, LinkState->MediaConnectState); // Cache the link state from the miniport memcpy(&pFilter->MiniportLinkState, LinkState, sizeof(NDIS_LINK_STATE)); } NdisFIndicateStatus(pFilter->FilterHandle, StatusIndication); LogFuncExit(DRIVER_DEFAULT); }
void otPlatSettingsInit(otInstance *otCtx) { NT_ASSERT(otCtx); PMS_FILTER pFilter = otCtxToFilter(otCtx); DECLARE_CONST_UNICODE_STRING(SubKeyName, L"OpenThread"); OBJECT_ATTRIBUTES attributes; ULONG disposition; LogFuncEntry(DRIVER_DEFAULT); InitializeObjectAttributes( &attributes, (PUNICODE_STRING)&SubKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, pFilter->InterfaceRegKey, NULL); // Create/Open the 'OpenThread' sub key NTSTATUS status = ZwCreateKey( &pFilter->otSettingsRegKey, KEY_ALL_ACCESS, &attributes, 0, NULL, REG_OPTION_NON_VOLATILE, &disposition); NT_ASSERT(NT_SUCCESS(status)); if (!NT_SUCCESS(status)) { LogError(DRIVER_DEFAULT, "ZwCreateKey for 'OpenThread' key failed, %!STATUS!", status); } LogFuncExit(DRIVER_DEFAULT); }
// Worker thread for processing all tunnel events _Use_decl_annotations_ VOID otLwfTunWorkerThread( PVOID Context ) { PMS_FILTER pFilter = (PMS_FILTER)Context; NT_ASSERT(pFilter); LogFuncEntry(DRIVER_DEFAULT); PKEVENT WaitEvents[] = { &pFilter->TunWorkerThreadStopEvent, &pFilter->TunWorkerThreadAddressChangedEvent }; LogFuncExit(DRIVER_DEFAULT); while (true) { // Wait for event to stop or process event to fire NTSTATUS status = KeWaitForMultipleObjects( ARRAYSIZE(WaitEvents), (PVOID*)WaitEvents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); // If it is the first event, then we are shutting down. Exit loop and terminate thread if (status == STATUS_WAIT_0) { LogInfo(DRIVER_DEFAULT, "Received tunnel worker thread shutdown event."); break; } else if (status == STATUS_WAIT_0 + 1) // TunWorkerThreadAddressChangedEvent fired { PVOID DataBuffer = NULL; const uint8_t* value_data_ptr = NULL; spinel_size_t value_data_len = 0; // Query the current addresses status = otLwfCmdGetProp( pFilter, &DataBuffer, SPINEL_PROP_IPV6_ADDRESS_TABLE, SPINEL_DATATYPE_DATA_S, &value_data_ptr, &value_data_len); if (NT_SUCCESS(status)) { uint32_t aNotifFlags = 0; otLwfTunAddressesUpdated(pFilter, value_data_ptr, value_data_len, &aNotifFlags); // Send notification if (aNotifFlags != 0) { PFILTER_NOTIFICATION_ENTRY NotifEntry = FILTER_ALLOC_NOTIF(pFilter); if (NotifEntry) { RtlZeroMemory(NotifEntry, sizeof(FILTER_NOTIFICATION_ENTRY)); NotifEntry->Notif.InterfaceGuid = pFilter->InterfaceGuid; NotifEntry->Notif.NotifType = OTLWF_NOTIF_STATE_CHANGE; NotifEntry->Notif.StateChangePayload.Flags = aNotifFlags; otLwfIndicateNotification(NotifEntry); } } } else { LogWarning(DRIVER_DEFAULT, "Failed to query addresses, %!STATUS!", status); } if (DataBuffer) FILTER_FREE_MEM(DataBuffer); } else { LogWarning(DRIVER_DEFAULT, "Unexpected wait result, %!STATUS!", status); } } PsTerminateSystemThread(STATUS_SUCCESS); }
_Use_decl_annotations_ VOID FilterOidRequestComplete( NDIS_HANDLE FilterModuleContext, PNDIS_OID_REQUEST Request, NDIS_STATUS Status ) /*++ Routine Description: Notification that an OID request has been completed If this filter sends a request down to a lower layer, and the request is pended, the FilterOidRequestComplete routine is invoked when the request is complete. Most requests we've sent are simply clones of requests received from a higher layer; all we need to do is complete the original higher request. However, if this filter driver sends original requests down, it must not attempt to complete a pending request to the higher layer. Arguments: FilterModuleContext - our filter context area NdisRequest - the completed request Status - completion status --*/ { PMS_FILTER pFilter = (PMS_FILTER)FilterModuleContext; PNDIS_OID_REQUEST OriginalRequest; POTLWF_REQUEST_CONTEXT Context; BOOLEAN bFalse = FALSE; LogFuncEntryMsg(DRIVER_OID, "Filter: %p, Request %p", FilterModuleContext, Request); Context = (POTLWF_REQUEST_CONTEXT)(&Request->SourceReserved[0]); OriginalRequest = (*Context); // // This is an internal request // if (OriginalRequest == NULL) { otLwfInternalRequestComplete(pFilter, Request, Status); LogFuncExit(DRIVER_OID); return; } FILTER_ACQUIRE_LOCK(&pFilter->PendingOidRequestLock, bFalse); ASSERT(pFilter->PendingOidRequest == Request); pFilter->PendingOidRequest = NULL; FILTER_RELEASE_LOCK(&pFilter->PendingOidRequestLock, bFalse); // // Copy the information from the returned request to the original request // switch(Request->RequestType) { case NdisRequestMethod: OriginalRequest->DATA.METHOD_INFORMATION.OutputBufferLength = Request->DATA.METHOD_INFORMATION.OutputBufferLength; OriginalRequest->DATA.METHOD_INFORMATION.BytesRead = Request->DATA.METHOD_INFORMATION.BytesRead; OriginalRequest->DATA.METHOD_INFORMATION.BytesNeeded = Request->DATA.METHOD_INFORMATION.BytesNeeded; OriginalRequest->DATA.METHOD_INFORMATION.BytesWritten = Request->DATA.METHOD_INFORMATION.BytesWritten; break; case NdisRequestSetInformation: OriginalRequest->DATA.SET_INFORMATION.BytesRead = Request->DATA.SET_INFORMATION.BytesRead; OriginalRequest->DATA.SET_INFORMATION.BytesNeeded = Request->DATA.SET_INFORMATION.BytesNeeded; break; case NdisRequestQueryInformation: case NdisRequestQueryStatistics: default: OriginalRequest->DATA.QUERY_INFORMATION.BytesWritten = Request->DATA.QUERY_INFORMATION.BytesWritten; OriginalRequest->DATA.QUERY_INFORMATION.BytesNeeded = Request->DATA.QUERY_INFORMATION.BytesNeeded; break; } (*Context) = NULL; LogVerbose(DRIVER_OID, "Freeing (cloned) Oid Request %p", Request); NdisFreeCloneOidRequest(pFilter->FilterHandle, Request); LogVerbose(DRIVER_OID, "Completing (external) Oid Request %p", OriginalRequest); NdisFOidRequestComplete(pFilter->FilterHandle, OriginalRequest, Status); LogFuncExit(DRIVER_OID); }
void otPlatSettingsWipe(otInstance *otCtx) { NT_ASSERT(otCtx); PMS_FILTER pFilter = otCtxToFilter(otCtx); LogFuncEntry(DRIVER_DEFAULT); // Delete all subkeys of 'OpenThread' if (pFilter->otSettingsRegKey) { NTSTATUS status = STATUS_SUCCESS; ULONG index = 0; UCHAR keyInfo[sizeof(KEY_BASIC_INFORMATION) + 64]; while (status == STATUS_SUCCESS) { ULONG size = sizeof(keyInfo); status = ZwEnumerateKey( pFilter->otSettingsRegKey, index, KeyBasicInformation, keyInfo, size, &size); bool deleted = false; if (NT_SUCCESS(status)) { HANDLE subKey = NULL; OBJECT_ATTRIBUTES attributes; PKEY_BASIC_INFORMATION pKeyInfo = (PKEY_BASIC_INFORMATION)keyInfo; UNICODE_STRING subKeyName = { (USHORT)pKeyInfo->NameLength, (USHORT)pKeyInfo->NameLength, pKeyInfo->Name }; InitializeObjectAttributes( &attributes, &subKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, pFilter->otSettingsRegKey, NULL); // Open the sub key status = ZwOpenKey( &subKey, KEY_ALL_ACCESS, &attributes); if (NT_SUCCESS(status)) { // Delete the key status = ZwDeleteKey(subKey); if (!NT_SUCCESS(status)) { LogError(DRIVER_DEFAULT, "ZwDeleteKey for subkey failed, %!STATUS!", status); } else { deleted = true; } // Close handle ZwClose(subKey); } else { LogError(DRIVER_DEFAULT, "ZwOpenKey for subkey failed, %!STATUS!", status); } } // Only increment index if we didn't delete if (!deleted) { index++; } } } LogFuncExit(DRIVER_DEFAULT); }
VOID otLwfEventProcessingStop( _In_ PMS_FILTER pFilter ) { PLIST_ENTRY Link = NULL; LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p", pFilter); // By this point, we have disabled the Data Path, so no more // NBLs should be queued up. // Clean up worker thread if (pFilter->EventWorkerThread) { LogInfo(DRIVER_DEFAULT, "Stopping event processing worker thread and waiting for it to complete."); // Send event to shutdown worker thread KeSetEvent(&pFilter->EventWorkerThreadStopEvent, 0, FALSE); // Wait for worker thread to finish KeWaitForSingleObject( pFilter->EventWorkerThread, Executive, KernelMode, FALSE, NULL ); // Free worker thread ObDereferenceObject(pFilter->EventWorkerThread); pFilter->EventWorkerThread = NULL; LogInfo(DRIVER_DEFAULT, "Event processing worker thread cleaned up."); } // Clean up any left over events if (pFilter->AddressChangesHead.Flink) { Link = pFilter->AddressChangesHead.Flink; while (Link != &pFilter->AddressChangesHead) { POTLWF_ADDR_EVENT Event = CONTAINING_RECORD(Link, OTLWF_ADDR_EVENT, Link); Link = Link->Flink; // Delete the event NdisFreeMemory(Event, 0, 0); } } // Clean up any left over events if (pFilter->NBLsHead.Flink) { Link = pFilter->NBLsHead.Flink; while (Link != &pFilter->NBLsHead) { POTLWF_NBL_EVENT Event = CONTAINING_RECORD(Link, OTLWF_NBL_EVENT, Link); Link = Link->Flink; otLwfCompleteNBLs(pFilter, FALSE, Event->NetBufferLists, STATUS_CANCELLED); // Delete the event NdisFreeMemory(Event, 0, 0); } } // Clean up any left over events if (pFilter->MacFramesHead.Flink) { Link = pFilter->MacFramesHead.Flink; while (Link != &pFilter->MacFramesHead) { POTLWF_MAC_FRAME_EVENT Event = CONTAINING_RECORD(Link, OTLWF_MAC_FRAME_EVENT, Link); Link = Link->Flink; // Delete the event NdisFreeMemory(Event, 0, 0); } } // Reinitialize the list head InitializeListHead(&pFilter->AddressChangesHead); InitializeListHead(&pFilter->NBLsHead); InitializeListHead(&pFilter->MacFramesHead); if (pFilter->EventIrpListHead.Flink) { FILTER_ACQUIRE_LOCK(&pFilter->EventsLock, FALSE); // Clean up any left over IRPs Link = pFilter->EventIrpListHead.Flink; while (Link != &pFilter->EventIrpListHead) { PIRP Irp = CONTAINING_RECORD(Link, IRP, Tail.Overlay.ListEntry); Link = Link->Flink; // Before we are allowed to complete the pending IRP, we must remove the cancel routine KIRQL irql; IoAcquireCancelSpinLock(&irql); IoSetCancelRoutine(Irp, NULL); IoReleaseCancelSpinLock(irql); Irp->IoStatus.Status = STATUS_CANCELLED; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); } // Reinitialize the list head InitializeListHead(&pFilter->EventIrpListHead); FILTER_RELEASE_LOCK(&pFilter->EventsLock, FALSE); } LogFuncExit(DRIVER_DEFAULT); }