NDIS_STATUS otLwfTunInitialize( _In_ PMS_FILTER pFilter ) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; HANDLE threadHandle = NULL; LogFuncEntry(DRIVER_DEFAULT); NT_ASSERT(pFilter->DeviceCapabilities & OTLWF_DEVICE_CAP_THREAD_1_0); KeInitializeEvent( &pFilter->TunWorkerThreadStopEvent, SynchronizationEvent, // auto-clearing event FALSE // event initially non-signalled ); KeInitializeEvent( &pFilter->TunWorkerThreadAddressChangedEvent, SynchronizationEvent, // auto-clearing event FALSE // event initially non-signalled ); // Start the worker thread Status = PsCreateSystemThread( &threadHandle, // ThreadHandle THREAD_ALL_ACCESS, // DesiredAccess NULL, // ObjectAttributes NULL, // ProcessHandle NULL, // ClientId otLwfTunWorkerThread, // StartRoutine pFilter // StartContext ); if (!NT_SUCCESS(Status)) { LogError(DRIVER_DEFAULT, "PsCreateSystemThread failed, %!STATUS!", Status); goto error; } // Grab the object reference to the worker thread Status = ObReferenceObjectByHandle( threadHandle, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &pFilter->TunWorkerThread, NULL ); if (!NT_VERIFYMSG("ObReferenceObjectByHandle can't fail with a valid kernel handle", NT_SUCCESS(Status))) { LogError(DRIVER_DEFAULT, "ObReferenceObjectByHandle failed, %!STATUS!", Status); KeSetEvent(&pFilter->TunWorkerThreadStopEvent, IO_NO_INCREMENT, FALSE); } // Make sure to enable RLOC passthrough Status = otLwfCmdSetProp( pFilter, SPINEL_PROP_THREAD_RLOC16_DEBUG_PASSTHRU, SPINEL_DATATYPE_BOOL_S, TRUE ); if (!NT_SUCCESS(Status)) { LogError(DRIVER_DEFAULT, "Enabling RLOC pass through failed, %!STATUS!", Status); goto error; } // TODO - Query other values and capabilities error: if (!NT_SUCCESS(Status)) { otLwfTunUninitialize(pFilter); } LogFuncExitNDIS(DRIVER_DEFAULT, Status); return Status; }
NTSTATUS otLwfEventProcessingStart( _In_ PMS_FILTER pFilter ) { NTSTATUS status = STATUS_SUCCESS; HANDLE threadHandle = NULL; LogFuncEntryMsg(DRIVER_DEFAULT, "Filter: %p, TimeIncrement = %u", pFilter, KeQueryTimeIncrement()); pFilter->NextAlarmTickCount.QuadPart = 0; NT_ASSERT(pFilter->EventWorkerThread == NULL); if (pFilter->EventWorkerThread != NULL) { status = STATUS_ALREADY_REGISTERED; goto error; } // Make sure to reset the necessary events KeResetEvent(&pFilter->EventWorkerThreadStopEvent); KeResetEvent(&pFilter->SendNetBufferListComplete); KeResetEvent(&pFilter->EventWorkerThreadEnergyScanComplete); // Start the worker thread status = PsCreateSystemThread( &threadHandle, // ThreadHandle THREAD_ALL_ACCESS, // DesiredAccess NULL, // ObjectAttributes NULL, // ProcessHandle NULL, // ClientId otLwfEventWorkerThread, // StartRoutine pFilter // StartContext ); if (!NT_SUCCESS(status)) { LogError(DRIVER_DEFAULT, "PsCreateSystemThread failed, %!STATUS!", status); goto error; } // Grab the object reference to the worker thread status = ObReferenceObjectByHandle( threadHandle, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, &pFilter->EventWorkerThread, NULL ); if (!NT_VERIFYMSG("ObReferenceObjectByHandle can't fail with a valid kernel handle", NT_SUCCESS(status))) { LogError(DRIVER_DEFAULT, "ObReferenceObjectByHandle failed, %!STATUS!", status); KeSetEvent(&pFilter->EventWorkerThreadStopEvent, IO_NO_INCREMENT, FALSE); } ZwClose(threadHandle); error: if (!NT_SUCCESS(status)) { ExSetTimerResolution(0, FALSE); } LogFuncExitNT(DRIVER_DEFAULT, status); return status; }