NTSTATUS CmpDoFileSetSize( PHHIVE Hive, ULONG FileType, ULONG FileSize, ULONG OldFileSize ) /*++ Routine Description: This routine sets the size of a file. It must not return until the size is guaranteed. It is environment specific. Must be running in the context of the cmp worker thread. Arguments: Hive - Hive we are doing I/O for FileType - which supporting file to use FileSize - 32 bit value to set the file's size to OldFileSize - old file size, in order to determine if this is a shrink; - ignored if file type is not primary, or hive doesn't use the mapped views technique Return Value: FALSE if failure TRUE if success --*/ { PCMHIVE CmHive; HANDLE FileHandle; NTSTATUS Status; FILE_END_OF_FILE_INFORMATION FileInfo; IO_STATUS_BLOCK IoStatus; BOOLEAN oldFlag; LARGE_INTEGER FileOffset; // where the mapping starts ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0); CmHive = (PCMHIVE)Hive; FileHandle = CmHive->FileHandles[FileType]; if (FileHandle == NULL) { return TRUE; } // // disable hard error popups, to avoid self deadlock on bogus devices // oldFlag = IoSetThreadHardErrorMode(FALSE); FileInfo.EndOfFile.HighPart = 0L; if( FileType == HFILE_TYPE_PRIMARY ) { FileInfo.EndOfFile.LowPart = ROUND_UP(FileSize, CM_FILE_GROW_INCREMENT); } else { FileInfo.EndOfFile.LowPart = FileSize; } ASSERT_PASSIVE_LEVEL(); Status = ZwSetInformationFile( FileHandle, &IoStatus, (PVOID)&FileInfo, sizeof(FILE_END_OF_FILE_INFORMATION), FileEndOfFileInformation ); if (NT_SUCCESS(Status)) { ASSERT(IoStatus.Status == Status); } else { // // set debugging info // CmRegistryIODebug.Action = CmpIoFileSetSize; CmRegistryIODebug.Handle = FileHandle; CmRegistryIODebug.Status = Status; #if DBG DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CmpFileSetSize:\tHandle=%08lx OldLength = %08lx NewLength=%08lx \n", FileHandle, OldFileSize, FileSize); #endif if( (Status == STATUS_DISK_FULL) && ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock) ) { DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Disk is full while attempting to grow file %lx; will flush upon lock release\n",FileHandle); CmpFlushOnLockRelease = TRUE;; } } // // restore hard error popups mode // IoSetThreadHardErrorMode(oldFlag); // // purge // if( HiveWritesThroughCache(Hive,FileType) && (OldFileSize > FileSize)) { // // first we have to unmap any possible mapped views in the last 256K window // to avoid deadlock on CcWaitOnActiveCount inside CcPurgeCacheSection call below // ULONG Offset = FileSize & (~(_256K - 1)); // // we are not allowed to shrink in shared mode. // ASSERT_HIVE_WRITER_LOCK_OWNED((PCMHIVE)Hive); while( Offset < OldFileSize ) { CmpUnmapCmViewSurroundingOffset((PCMHIVE)Hive,Offset); Offset += CM_VIEW_SIZE; } // // we need to take extra precaution here and unmap the very last view too // FileOffset.HighPart = 0; FileOffset.LowPart = FileSize; // // This is a shrink; Inform cache manager of the change of the size // CcPurgeCacheSection( ((PCMHIVE)Hive)->FileObject->SectionObjectPointer, (PLARGE_INTEGER)(((ULONG_PTR)(&FileOffset)) + 1), OldFileSize - FileSize, FALSE ); // // Flush out this view to clear out the Cc dirty hints // CcFlushCache( ((PCMHIVE)Hive)->FileObject->SectionObjectPointer, (PLARGE_INTEGER)(((ULONG_PTR)(&FileOffset)) + 1),/*we are private writers*/ OldFileSize - FileSize,NULL); } return Status; }
_IRQL_requires_same_ inline VOID KrnlHlprClassifyDataReleaseLocalCopy(_Inout_ CLASSIFY_DATA* pClassifyData) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> KrnlHlprClassifyDataReleaseLocalCopy()\n"); #endif /// DBG NT_ASSERT(pClassifyData); KrnlHlprFwpsClassifyOutDestroyLocalCopy((FWPS_CLASSIFY_OUT**)&(pClassifyData->pClassifyOut)); pClassifyData->flowContext = 0; KrnlHlprFwpsFilterDestroyLocalCopy((FWPS_FILTER**)&(pClassifyData->pFilter)); #if(NTDDI_VERSION >= NTDDI_WIN7) if(pClassifyData->classifyContextHandle) FwpsReleaseClassifyHandle(pClassifyData->classifyContextHandle); #endif /// (NTDDI_VERSION >= NTDDI_WIN7) if(pClassifyData->pPacket) { if(pClassifyData->pClassifyValues) { if(pClassifyData->pClassifyValues->layerId == FWPS_LAYER_STREAM_V4 || pClassifyData->pClassifyValues->layerId == FWPS_LAYER_STREAM_V4_DISCARD || pClassifyData->pClassifyValues->layerId == FWPS_LAYER_STREAM_V6 || pClassifyData->pClassifyValues->layerId == FWPS_LAYER_STREAM_V6_DISCARD) KrnlHlprFwpsStreamCalloutIOPacketDestroyLocalCopy((FWPS_STREAM_CALLOUT_IO_PACKET**)&(pClassifyData->pPacket)); else if(pClassifyData->chainedNBL) { BOOLEAN isDispatch = (KeGetCurrentIrql() == DISPATCH_LEVEL) ? TRUE : FALSE; UINT32 numChainedNBLs = pClassifyData->numChainedNBLs; for(NET_BUFFER_LIST* pCurrentNBL = (NET_BUFFER_LIST*)pClassifyData->pPacket; pCurrentNBL && numChainedNBLs; numChainedNBLs--) { NET_BUFFER_LIST* pNextNBL = NET_BUFFER_LIST_NEXT_NBL(pCurrentNBL); FwpsDereferenceNetBufferList(pCurrentNBL, isDispatch); pCurrentNBL = pNextNBL; #if DBG InterlockedDecrement64((LONG64*)&(g_OutstandingNBLReferences)); #endif /// DBG } } else { BOOLEAN isDispatch = (KeGetCurrentIrql() == DISPATCH_LEVEL) ? TRUE : FALSE; FwpsDereferenceNetBufferList((NET_BUFFER_LIST*)pClassifyData->pPacket, isDispatch); #if DBG InterlockedDecrement64((LONG64*)&(g_OutstandingNBLReferences)); #endif /// DBG } } pClassifyData->pPacket = 0; } KrnlHlprFwpsIncomingMetadataValuesDestroyLocalCopy((FWPS_INCOMING_METADATA_VALUES**)&(pClassifyData->pMetadataValues)); if(pClassifyData->pClassifyValues) KrnlHlprFwpsIncomingValuesDestroyLocalCopy((FWPS_INCOMING_VALUES**)&(pClassifyData->pClassifyValues)); RtlZeroMemory(pClassifyData, sizeof(CLASSIFY_DATA)); #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- KrnlHlprClassifyDataReleaseLocalCopy()\n"); #endif /// DBG return; }
NTSTATUS TriggerPendAuthorizationOutOfBand(_In_ const FWPS_INCOMING_VALUES* pClassifyValues, _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata, _Inout_opt_ VOID* pLayerData, _In_opt_ const VOID* pClassifyContext, _In_ const FWPS_FILTER* pFilter, _In_ UINT64 flowContext, _In_ FWPS_CLASSIFY_OUT* pClassifyOut, _Inout_opt_ INJECTION_DATA* pInjectionData, _Inout_ PEND_DATA* pPendData, _In_ PC_PEND_AUTHORIZATION_DATA* pPCData) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> TriggerPendAuthorizationOutOfBand()\n"); #endif /// DBG NT_ASSERT(pClassifyValues); NT_ASSERT(pMetadata); NT_ASSERT(pFilter); NT_ASSERT(pClassifyOut); NT_ASSERT(pPendData); NT_ASSERT(pPCData); NTSTATUS status = STATUS_SUCCESS; CLASSIFY_DATA* pClassifyData = 0; #pragma warning(push) #pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy status = KrnlHlprClassifyDataCreateLocalCopy(&pClassifyData, pClassifyValues, pMetadata, pLayerData, pClassifyContext, pFilter, flowContext, pClassifyOut); HLPR_BAIL_ON_FAILURE(status); #pragma warning(pop) if(pPCData->useWorkItems || pPCData->delay) { /// introducing the delay requires PASSIVE_LEVEL, so force use of a Work Item status = KrnlHlprWorkItemQueue(g_pWDMDevice, PendAuthorizationWorkItemRoutine, pClassifyData, pPendData, (VOID*)pInjectionData); } else { if(pPCData->useThreadedDPC) status = KrnlHlprThreadedDPCQueue(PendAuthorizationDeferredProcedureCall, pClassifyData, pPendData, pInjectionData); else status = KrnlHlprDPCQueue(PendAuthorizationDeferredProcedureCall, pClassifyData, pPendData, pInjectionData); } HLPR_BAIL_ON_FAILURE(status); pClassifyOut->actionType = FWP_ACTION_BLOCK; HLPR_BAIL_LABEL: if(status != STATUS_SUCCESS) { if(pClassifyData) KrnlHlprClassifyDataDestroyLocalCopy(&pClassifyData); } #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- TriggerPendAuthorizationOutOfBand() [status: %#x]\n", status); #endif /// DBG return status; }
/////////////////////////////////////////////////////////////////////////////// /// /// Driver entry /// /////////////////////////////////////////////////////////////////////////////// NTSTATUS DriverEntry( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) { NTSTATUS Status; UNICODE_STRING NtDeviceName = RTL_CONSTANT_STRING(QD_NT_DEVICE_NAME); UNICODE_STRING DosDevicesLinkName = RTL_CONSTANT_STRING(QD_DOS_DEVICES_LINK_NAME); BOOLEAN SymLinkCreated = FALSE; PQD_COMM_CONTROL_DEVICE_EXTENSION controlExt; UNREFERENCED_PARAMETER(RegistryPath); // Request NX Non-Paged Pool when available ExInitializeDriverRuntime(DrvRtPoolNxOptIn); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "QuietDragon: DriverEntry: Driver loaded\n"); // // Initialize globals. // // // Create our device object. // // TODO Consider using IoCreateDeviceSecure Status = IoCreateDevice( DriverObject, // pointer to driver object sizeof(QD_COMM_CONTROL_DEVICE_EXTENSION), // device extension size &NtDeviceName, // device name FILE_DEVICE_UNKNOWN, // device type 0, // device characteristics FALSE, // not exclusive &g_CommDeviceObject); // returned device object pointer if (!NT_SUCCESS(Status)) { goto Exit; } TD_ASSERT(g_CommDeviceObject == DriverObject->DeviceObject); // // Set dispatch routines. // DriverObject->MajorFunction[IRP_MJ_CREATE] = TdDeviceCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = TdDeviceClose; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TdDeviceCleanup; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TdDeviceControl; DriverObject->DriverUnload = TdDeviceUnload; // // Set up the device extension // controlExt = (PQD_COMM_CONTROL_DEVICE_EXTENSION)g_CommDeviceObject->DeviceExtension; controlExt->MagicNumber = QD_COMM_CONTROL_EXTENSION_MAGIC_NUMBER; InitializeListHead(&controlExt->ProcessQueue); ExInitializeFastMutex(&controlExt->ProcessQueueLock); InitializeListHead(&controlExt->RequestQueue); ExInitializeFastMutex(&controlExt->RequestQueueLock); ExInitializeFastMutex(&controlExt->DecisionDataLock); controlExt->DecisionData = (PCONTROL_PROC_INTERNAL)ExAllocatePoolWithTag(NonPagedPool, sizeof(CONTROL_PROC_INTERNAL)*QD_MAX_PROCS, 'SRdd'); RtlZeroMemory(controlExt->DecisionData, sizeof(CONTROL_PROC_INTERNAL)*QD_MAX_PROCS); // Init DecisionData for (USHORT i = 0; i < QD_MAX_PROCS; i++) { PCONTROL_PROC_INTERNAL control_proc = &(controlExt->DecisionData[i]); control_proc->StartTime.QuadPart = 0; KeInitializeEvent(&(control_proc->DecisionEvent), NotificationEvent, FALSE); } // // Create a link in the Win32 namespace. // Status = IoCreateSymbolicLink(&DosDevicesLinkName, &NtDeviceName); if (!NT_SUCCESS(Status)) { goto Exit; } SymLinkCreated = TRUE; // // Set process create routines. // Status = PsSetCreateProcessNotifyRoutineEx( MyCreateProcessNotifyRoutine, FALSE ); if (!NT_SUCCESS(Status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "QuietDragon: DriverEntry: PsSetCreateProcessNotifyRoutineEx returned 0x%x\n", Status); goto Exit; } gProcessNotifyRoutine_isSet = TRUE; Exit: if (!NT_SUCCESS(Status)) { if (gProcessNotifyRoutine_isSet == TRUE) { Status = PsSetCreateProcessNotifyRoutineEx( MyCreateProcessNotifyRoutine, TRUE ); TD_ASSERT(Status == STATUS_SUCCESS); gProcessNotifyRoutine_isSet = FALSE; } if (SymLinkCreated == TRUE) { IoDeleteSymbolicLink(&DosDevicesLinkName); } if (g_CommDeviceObject != NULL) { IoDeleteDevice(g_CommDeviceObject); } } return Status; }
NTSTATUS KrnlHlprClassifyDataAcquireLocalCopy(_Inout_ CLASSIFY_DATA* pClassifyData, _In_ const FWPS_INCOMING_VALUES* pClassifyValues, _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata, _In_opt_ VOID* pPacket, _In_opt_ const VOID* pClassifyContext, _In_ const FWPS_FILTER* pFilter, _In_ const UINT64 flowContext, _In_ FWPS_CLASSIFY_OUT* pClassifyOut) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> KrnlHlprClassifyDataAcquireLocalCopy()\n"); #endif /// DBG NT_ASSERT(pClassifyData); NT_ASSERT(pClassifyValues); NT_ASSERT(pMetadata); NT_ASSERT(pFilter); NT_ASSERT(pClassifyOut); NTSTATUS status = STATUS_SUCCESS; pClassifyData->pClassifyValues = KrnlHlprFwpsIncomingValuesCreateLocalCopy(pClassifyValues); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pClassifyValues, status); pClassifyData->pMetadataValues = KrnlHlprFwpsIncomingMetadataValuesCreateLocalCopy(pMetadata); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pMetadataValues, status); if(pPacket) { if(pClassifyValues->layerId == FWPS_LAYER_STREAM_V4 || pClassifyValues->layerId == FWPS_LAYER_STREAM_V4_DISCARD || pClassifyValues->layerId == FWPS_LAYER_STREAM_V6 || pClassifyValues->layerId == FWPS_LAYER_STREAM_V6_DISCARD) { pClassifyData->pPacket = KrnlHlprFwpsStreamCalloutIOPacketCreateLocalCopy((FWPS_STREAM_CALLOUT_IO_PACKET*)pPacket); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pPacket, status); } #if(NTDDI_VERSION >= NTDDI_WIN7) /// LayerData at the FWPM_LAYER_ALE_{BIND/CONNECT}_REDIRECT_V{4/6} is obtained via KrnlHlprRedirectDataCreate() else if(pClassifyValues->layerId == FWPS_LAYER_ALE_CONNECT_REDIRECT_V4 || pClassifyValues->layerId == FWPS_LAYER_ALE_CONNECT_REDIRECT_V6 || pClassifyValues->layerId == FWPS_LAYER_ALE_BIND_REDIRECT_V4 || pClassifyValues->layerId == FWPS_LAYER_ALE_BIND_REDIRECT_V6) { pClassifyData->pPacket = 0; } #endif /// (NTDDI_VERSION >= NTDDI_WIN7) else { if(NET_BUFFER_LIST_NEXT_NBL((NET_BUFFER_LIST*)pPacket)) { pClassifyData->chainedNBL = TRUE; pClassifyData->numChainedNBLs = 1; } if(pClassifyData->chainedNBL && ( /// The IPPACKET and IPFORWARD Layers allow for Fragment Grouping if the option is enabled pClassifyValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V4 || pClassifyValues->layerId == FWPS_LAYER_INBOUND_IPPACKET_V6 || pClassifyValues->layerId == FWPS_LAYER_IPFORWARD_V4 || pClassifyValues->layerId == FWPS_LAYER_IPFORWARD_V6 #if(NTDDI_VERSION >= NTDDI_WIN8) /// The NDIS layers allow for batched NBLs provided the callout was registered with FWP_CALLOUT_FLAG_ALLOW_L2_BATCH_CLASSIFY set || pClassifyValues->layerId == FWPS_LAYER_INBOUND_MAC_FRAME_ETHERNET || pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_MAC_FRAME_ETHERNET || pClassifyValues->layerId == FWPS_LAYER_INBOUND_MAC_FRAME_NATIVE || pClassifyValues->layerId == FWPS_LAYER_OUTBOUND_MAC_FRAME_NATIVE || pClassifyValues->layerId == FWPS_LAYER_INGRESS_VSWITCH_ETHERNET || pClassifyValues->layerId == FWPS_LAYER_EGRESS_VSWITCH_ETHERNET #endif /// (NTDDI_VERSION >= NTDDI_WIN8) )) { for(NET_BUFFER_LIST* pCurrentNBL = (NET_BUFFER_LIST*)pPacket; pCurrentNBL; pClassifyData->numChainedNBLs++) { NET_BUFFER_LIST* pNextNBL = NET_BUFFER_LIST_NEXT_NBL(pCurrentNBL); FwpsReferenceNetBufferList(pCurrentNBL, TRUE); pCurrentNBL = pNextNBL; #if DBG InterlockedIncrement64((LONG64*)&(g_OutstandingNBLReferences)); #endif /// DBG } pClassifyData->pPacket = pPacket; } else { /// Otherwise we expect to receive a single NBL NT_ASSERT(NET_BUFFER_LIST_NEXT_NBL((NET_BUFFER_LIST*)pPacket) == 0); FwpsReferenceNetBufferList((NET_BUFFER_LIST*)pPacket, TRUE); pClassifyData->pPacket = pPacket; #if DBG InterlockedIncrement64((LONG64*)&(g_OutstandingNBLReferences)); #endif /// DBG } } } #if(NTDDI_VERSION >= NTDDI_WIN7) if(pClassifyContext) { /// ClassifyHandle for these layers is obtained in REDIRECT_DATA if(pClassifyValues->layerId != FWPS_LAYER_ALE_CONNECT_REDIRECT_V4 && pClassifyValues->layerId != FWPS_LAYER_ALE_CONNECT_REDIRECT_V6 && pClassifyValues->layerId != FWPS_LAYER_ALE_BIND_REDIRECT_V4 && pClassifyValues->layerId != FWPS_LAYER_ALE_BIND_REDIRECT_V6) { status = FwpsAcquireClassifyHandle((VOID*)pClassifyContext, 0, &(pClassifyData->classifyContextHandle)); HLPR_BAIL_ON_FAILURE(status); } } #else UNREFERENCED_PARAMETER(pClassifyContext); #endif /// (NTDDI_VERSION >= NTDDI_WIN7) if(pFilter) { pClassifyData->pFilter = KrnlHlprFwpsFilterCreateLocalCopy(pFilter); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pFilter, status); } pClassifyData->flowContext = flowContext; if(pClassifyOut) { pClassifyData->pClassifyOut = KrnlHlprFwpsClassifyOutCreateLocalCopy(pClassifyOut); HLPR_BAIL_ON_NULL_POINTER_WITH_STATUS(pClassifyData->pClassifyOut, status); } HLPR_BAIL_LABEL: if(status != STATUS_SUCCESS) KrnlHlprClassifyDataReleaseLocalCopy(pClassifyData); #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- KrnlHlprClassifyDataAcquireLocalCopy() [status: %#x]\n", status); #endif /// DBG return status; }
NTSTATUS SwdmDispatchPnP( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { IO_STACK_LOCATION* pStk; DEVICE_EXTENSION* pCtx; ULONG MinorCode; NTSTATUS Status = STATUS_SUCCESS; DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MJ_PNP Received : Begin\n" ); pStk = IoGetCurrentIrpStackLocation(Irp); pCtx = (DEVICE_EXTENSION*)DeviceObject->DeviceExtension; IoAcquireRemoveLock( &pCtx->RemoveLock, Irp); MinorCode = pStk->MinorFunction; DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Minor code: 0x%x\n", MinorCode ); switch( MinorCode ) { case IRP_MN_START_DEVICE: DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MN_START_DEVICE Received : Begin\r\n"); Status = StartDevice( DeviceObject, Irp ); DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MN_START_DEVICE Received : End\r\n"); break; case IRP_MN_STOP_DEVICE: DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MN_STOP_DEVICE Received : Begin\r\n"); Status = StopDevice( DeviceObject, Irp ); DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MN_STOP_DEVICE Received : End\r\n"); break; case IRP_MN_REMOVE_DEVICE: DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MN_REMOVE_DEVICE Received : Begin\r\n"); Status = RemoveDevice( DeviceObject, Irp ); DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MN_REMOVE_DEVICE Received : End\r\n"); break; case IRP_MN_QUERY_CAPABILITIES : DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MN_QUERY_CAPABILITIES Received : Begin\r\n"); Status = QueryCapability( DeviceObject, Irp ); DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MN_QUERY_CAPABILITIES Received : End\r\n"); break; case IRP_MN_QUERY_BUS_INFORMATION: DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MN_QUERY_BUS_INFORMATION Received : Begin\n"); Status = QueryBus( DeviceObject, Irp ); break; default: break; } IoReleaseRemoveLock( &pCtx->RemoveLock, Irp); if (NT_SUCCESS(Status)) { CompleteRequest( Irp, STATUS_SUCCESS, 0); } DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "IRP_MJ_PNP Received : End\r\n"); return Status; }
void _printk(const char * func, const char * format, ...) { int ret = 0; va_list args; char * buf = (char *) ExAllocateFromNPagedLookasideList(&drbd_printk_msg); if (!buf) { return; } RtlZeroMemory(buf, MAX_ELOG_BUF); va_start(args, format); ret = vsprintf(buf, format, args); // DRBD_DOC: improve vsnprintf va_end(args); int length = strlen(buf); if (length > MAX_ELOG_BUF) { length = MAX_ELOG_BUF - 1; buf[MAX_ELOG_BUF - 1] = 0; } else { // TODO: chekc min? } ULONG msgid = PRINTK_INFO; int level_index = format[1] - '0'; int printLevel = 0; CHAR szTempBuf[MAX_ELOG_BUF] = ""; BOOLEAN bSysEventLog = FALSE; BOOLEAN bServiceLog = FALSE; BOOLEAN bDbgLog = FALSE; extern atomic_t g_syslog_lv_min; extern atomic_t g_svclog_lv_min; extern atomic_t g_dbglog_lv_min; ASSERT((level_index >= 0) && (level_index < 8)); #ifdef _WIN32_WPP DoTraceMessage(TRCINFO, "%s", buf); WriteEventLogEntryData(msgids[level_index], 0, 0, 1, L"%S", buf + 3); DbgPrintEx(FLTR_COMPONENT, DPFLTR_INFO_LEVEL, "WDRBD_INFO: [%s] %s", func, buf + 3); ExFreeToNPagedLookasideList(&drbd_printk_msg, buf); #else // to write system event log. if (level_index <= atomic_read(&g_syslog_lv_min)) bSysEventLog = TRUE; // to send to drbd service. if (level_index <= atomic_read(&g_svclog_lv_min)) bServiceLog = TRUE; // to print through debugger. if (level_index <= atomic_read(&g_dbglog_lv_min)) bDbgLog = TRUE; // nothing to log. if (!bSysEventLog && !bServiceLog && !bDbgLog) { ExFreeToNPagedLookasideList(&drbd_printk_msg, buf); return; } if (bSysEventLog) { save_to_system_event(buf, length, level_index); } switch (level_index) { case KERN_EMERG_NUM: case KERN_ALERT_NUM: case KERN_CRIT_NUM: printLevel = DPFLTR_ERROR_LEVEL; sprintf(szTempBuf, "<%d>%s: [%s] %s", level_index, "WDRBD_FATA", func, buf + 3); break; case KERN_ERR_NUM: printLevel = DPFLTR_ERROR_LEVEL; sprintf(szTempBuf, "<%d>%s: [%s] %s", level_index, "WDRBD_ERRO", func, buf + 3); break; case KERN_WARNING_NUM: printLevel = DPFLTR_WARNING_LEVEL; sprintf(szTempBuf, "<%d>%s: [%s] %s", level_index, "WDRBD_WARN", func, buf + 3); break; case KERN_NOTICE_NUM: case KERN_INFO_NUM: printLevel = DPFLTR_INFO_LEVEL; sprintf(szTempBuf, "<%d>%s: [%s] %s", level_index, "WDRBD_INFO", func, buf + 3); break; case KERN_DEBUG_NUM: printLevel = DPFLTR_TRACE_LEVEL; sprintf(szTempBuf, "<%d>%s: [%s] %s", level_index, "WDRBD_TRAC", func, buf + 3); break; default: printLevel = DPFLTR_TRACE_LEVEL; sprintf(szTempBuf, "<%d>%s: [%s] %s", level_index, "WDRBD_UNKN", func, buf + 3); break; } strcpy_s(buf, MAX_ELOG_BUF, szTempBuf); if (bDbgLog) DbgPrintEx(FLTR_COMPONENT, printLevel, buf + 3); #ifdef _WIN32_LOGLINK if (FALSE == bServiceLog || FALSE == LogLink_IsUsable() || STATUS_SUCCESS != LogLink_QueueBuffer(buf)) { // buf will be freed by loglink sender thread if it's queued, otherwise free it here. ExFreeToNPagedLookasideList(&drbd_printk_msg, buf); } #else // WriteEventLogEntryData(msgids[level_index], 0, 0, 1, L"%S", buf + 3); //old style DbgPrintEx(FLTR_COMPONENT, DPFLTR_INFO_LEVEL, "WDRBD_INFO: [%s] %s", func, buf + 3); ExFreeToNPagedLookasideList(&drbd_printk_msg, buf); #endif #endif }
NTSTATUS DriverEntry ( _In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath ) /*++ Routine Description: This routine is called by the operating system to initialize the driver. It allocates a device object, initializes the supported Io callbacks, and creates a symlink to make the device accessible to Win32. It gets the registry callback version and stores it in the global variables g_MajorVersion and g_MinorVersion. It also calls CreateKTMResourceManager to create a resource manager that is used in the transaction samples. Arguments: DriverObject - Supplies the system control object for this test driver. RegistryPath - The string location of the driver's corresponding services key in the registry. Return value: Success or appropriate failure code. --*/ { NTSTATUS Status; UNICODE_STRING NtDeviceName; UNICODE_STRING DosDevicesLinkName; UNICODE_STRING DeviceSDDLString; UNREFERENCED_PARAMETER(RegistryPath); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "RegFltr: DriverEntry()\n"); DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "RegFltr: Use ed nt!Kd_IHVDRIVER_Mask 8 to enable more detailed printouts\n"); // // Create our device object. // RtlInitUnicodeString(&NtDeviceName, NT_DEVICE_NAME); RtlInitUnicodeString(&DeviceSDDLString, DEVICE_SDDL); // TODO(H): 看下这个函数 Status = IoCreateDeviceSecure( DriverObject, // pointer to driver object 0, // device extension size &NtDeviceName, // device name FILE_DEVICE_UNKNOWN, // device type 0, // device characteristics TRUE, // not exclusive &DeviceSDDLString, // SDDL string specifying access NULL, // device class guid &g_DeviceObj); // returned device object pointer if (!NT_SUCCESS(Status)) { return Status; } // // Set dispatch routines. // DriverObject->MajorFunction[IRP_MJ_CREATE] = DeviceCreate; DriverObject->MajorFunction[IRP_MJ_CLOSE] = DeviceClose; DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DeviceCleanup; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl; DriverObject->DriverUnload = DeviceUnload; // // Create a link in the Win32 namespace. // RtlInitUnicodeString(&DosDevicesLinkName, DOS_DEVICES_LINK_NAME); Status = IoCreateSymbolicLink(&DosDevicesLinkName, &NtDeviceName); if (!NT_SUCCESS(Status)) { IoDeleteDevice(DriverObject->DeviceObject); return Status; } // // Get callback version. // // TODO(H): CmGetCallbackVersion(&g_MajorVersion, &g_MinorVersion); InfoPrint("Callback version %u.%u", g_MajorVersion, g_MinorVersion); // // Some variations depend on knowing if the OS is win8 or above // DetectOSVersion(); // // Set up KTM resource manager and pass in RMCallback as our // callback routine. // Status = CreateKTMResourceManager(RMCallback, NULL); if (NT_SUCCESS(Status)) { g_RMCreated = TRUE; } // // Initialize the callback context list // InitializeListHead(&g_CallbackCtxListHead); ExInitializeFastMutex(&g_CallbackCtxListLock); g_NumCallbackCtxListEntries = 0; return STATUS_SUCCESS; }
NTSTATUS KrnlHlprNDISPoolDataPopulate(_Inout_ NDIS_POOL_DATA* pNDISPoolData, _In_opt_ UINT32 memoryTag) /* WFPSAMPLER_NDIS_POOL_TAG */ { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> KrnlHlprNDISPoolDataPopulate()\n"); #endif /// DBG NT_ASSERT(pNDISPoolData); NTSTATUS status = STATUS_SUCCESS; NET_BUFFER_LIST_POOL_PARAMETERS nblPoolParameters = {0}; NET_BUFFER_POOL_PARAMETERS nbPoolParameters = {0}; pNDISPoolData->ndisHandle = NdisAllocateGenericObject(0, memoryTag, 0); if(pNDISPoolData->ndisHandle == 0) { status = STATUS_INVALID_HANDLE; DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprNDISPoolDataPopulate : NdisAllocateGenericObject() [status: %#x]\n", status); HLPR_BAIL; } nblPoolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; nblPoolParameters.Header.Revision = NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; nblPoolParameters.Header.Size = NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1; nblPoolParameters.fAllocateNetBuffer = TRUE; nblPoolParameters.DataSize = 0; nblPoolParameters.PoolTag = memoryTag; pNDISPoolData->nblPoolHandle = NdisAllocateNetBufferListPool(pNDISPoolData->ndisHandle, &nblPoolParameters); if(pNDISPoolData->nblPoolHandle == 0) { status = STATUS_INVALID_HANDLE; DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprNDISPoolDataPopulate : NdisAllocateNetBufferListPool() [status: %#x]\n", status); HLPR_BAIL; } nbPoolParameters.Header.Type = NDIS_OBJECT_TYPE_DEFAULT; nbPoolParameters.Header.Revision = NET_BUFFER_POOL_PARAMETERS_REVISION_1; nbPoolParameters.Header.Size = NDIS_SIZEOF_NET_BUFFER_POOL_PARAMETERS_REVISION_1; nbPoolParameters.PoolTag = memoryTag; nbPoolParameters.DataSize = 0; pNDISPoolData->nbPoolHandle = NdisAllocateNetBufferPool(pNDISPoolData->ndisHandle, &nbPoolParameters); if(pNDISPoolData->nbPoolHandle == 0) { status = STATUS_INVALID_HANDLE; DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! KrnlHlprNDISPoolDataPopulate : NdisAllocateNetBufferPool() [status: %#x]\n", status); HLPR_BAIL; } HLPR_BAIL_LABEL: if(status != STATUS_SUCCESS) KrnlHlprNDISPoolDataPurge(pNDISPoolData); #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- KrnlHlprNDISPoolDataPopulate()\n"); #endif /// DBG return status; }
NTSTATUS SmplDeviceCreateDevice( _Inout_ PWDFDEVICE_INIT DeviceInit ) /*++ Routine Description: Worker routine called to create a device and its software resources. Arguments: DeviceInit - Pointer to an opaque init structure. Memory for this structure will be freed by the framework when the WdfDeviceCreate succeeds. So don't access the structure after that point. Return Value: NTSTATUS --*/ { WDF_OBJECT_ATTRIBUTES deviceAttributes; PDEVICE_CONTEXT deviceContext; WDF_PNPPOWER_EVENT_CALLBACKS PnpPowerEventCallbacks; WDFDEVICE device; NTSTATUS status; PAGED_CODE(); WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT); deviceAttributes.SynchronizationScope = WdfSynchronizationScopeQueue; WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&PnpPowerEventCallbacks); PnpPowerEventCallbacks.EvtDevicePrepareHardware = SmplDeviceEvtPrepareHardware; PnpPowerEventCallbacks.EvtDeviceReleaseHardware = SmplDeviceEvtReleaseHardware; PnpPowerEventCallbacks.EvtDeviceD0Entry = SmplDeviceEvtD0Entry; PnpPowerEventCallbacks.EvtDeviceD0Exit = SmplDeviceEvtD0Exit; WdfDeviceInitSetPnpPowerEventCallbacks( DeviceInit, &PnpPowerEventCallbacks); status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device); if (NT_SUCCESS(status)) { // // Get the device context and initialize it. DeviceGetContext is an // inline function generated by WDF_DECLARE_CONTEXT_TYPE macro in the // device.h header file. This function will do the type checking and return // the device context. If you pass a wrong object handle // it will return NULL and assert if run under framework verifier mode. // deviceContext = DeviceGetContext(device); // // Create a device interface so that applications can find and talk // to us. // status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_SMPLDEVICE, NULL); if (NT_SUCCESS(status)) { // // Initialize the I/O Package and any Queues // status = SmplDeviceQueueInitialize(device); } if (NT_SUCCESS(status)) { WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS PowerPolicyIdleSettings; WDF_DEVICE_POWER_POLICY_IDLE_SETTINGS_INIT(&PowerPolicyIdleSettings, IdleCannotWakeFromS0); PowerPolicyIdleSettings.IdleTimeoutType = SystemManagedIdleTimeout; status = WdfDeviceAssignS0IdleSettings(device, &PowerPolicyIdleSettings); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"WdfDeviceAssignS0IdleSettings failed! 0x%x\n", status); } } if (NT_SUCCESS(status)) { SmplPoFxSingleComponentInitialize(device); } if (NT_SUCCESS(status)) { WDFINTERRUPT Interrupt; WDF_INTERRUPT_CONFIG Configuration; WDF_INTERRUPT_CONFIG_INIT(&Configuration, SmplInterruptEvtIsr, SmplInterruptEvtDpc); Configuration.EvtInterruptEnable = SmplInterruptEvtEnable; Configuration.EvtInterruptDisable = SmplInterruptEvtDisable; status = WdfInterruptCreate(device, &Configuration, WDF_NO_OBJECT_ATTRIBUTES, &Interrupt); if (!NT_SUCCESS(status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234, "WdfInterruptCreate failed! 0x%x\n", status); } } } return status; }
NTSTATUS KrnlHlprThreadedDPCQueue(_In_ KDEFERRED_ROUTINE* pDPCFn, _In_ CLASSIFY_DATA* pClassifyData, _In_ REDIRECT_DATA* pRedirectData, _In_opt_ VOID* pContext) /* 0 */ { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> KrnlHlprThreadedDPCQueue()\n"); #endif /// DBG NT_ASSERT(pDPCFn); NT_ASSERT(pClassifyData); NT_ASSERT(pRedirectData); NTSTATUS status = STATUS_SUCCESS; DPC_DATA* pDPCData = 0; #pragma warning(push) #pragma warning(disable: 6014) /// pDPCData will be freed by caller status = KrnlHlprDPCDataCreate(&pDPCData, pClassifyData, pRedirectData, pContext); HLPR_BAIL_ON_FAILURE(status); #pragma warning(pop) KeInitializeThreadedDpc(&(pDPCData->kdpc), pDPCFn, 0); KeInsertQueueDpc(&(pDPCData->kdpc), pDPCData, 0); HLPR_BAIL_LABEL: #pragma warning(push) #pragma warning(disable: 6001) /// pDPCData initialized with call to KrnlHlprDPCDataCreate if(status != STATUS_SUCCESS && pDPCData) KrnlHlprDPCDataDestroy(&pDPCData); #pragma warning(pop) #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- KrnlHlprThreadedDPCQueue() [status: %#x]\n", status); #endif /// DBG return status; }
BOOLEAN CmpFileFlush ( PHHIVE Hive, ULONG FileType, PLARGE_INTEGER FileOffset, ULONG Length ) /*++ Routine Description: This routine performs a flush on a file handle. Arguments: Hive - Hive we are doing I/O for FileType - which supporting file to use FileOffset - If this parameter is supplied (not NULL), then only the byte range specified by FileOffset and Length are flushed. Length - Defines the length of the byte range to flush, starting at FileOffset. This parameter is ignored if FileOffset is specified as NULL. Return Value: FALSE if failure TRUE if success Note: FileOffset and Length are only taken into account when FileType == HFILE_TYPE_PRIMARY and the hive uses the mapped-views method. --*/ { NTSTATUS status; IO_STATUS_BLOCK IoStatus; PCMHIVE CmHive; HANDLE FileHandle; ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0); CmHive = (PCMHIVE)Hive; FileHandle = CmHive->FileHandles[FileType]; if (FileHandle == NULL) { return TRUE; } if (CmpNoWrite) { return TRUE; } CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"CmpFileFlush:\n\tHandle = %08lx\n", FileHandle)); ASSERT_PASSIVE_LEVEL(); if( HiveWritesThroughCache(Hive,FileType) == TRUE ) { // // OK, we need to flush using CcFlushCache // CcFlushCache (CmHive->FileObject->SectionObjectPointer,(PLARGE_INTEGER)((ULONG_PTR)FileOffset + 1)/*we are private writers*/,Length,&IoStatus); status = IoStatus.Status; if( !NT_SUCCESS(status) ) { goto Error; } } // // we have to do that regardless, to make sure the disk cache makes it to the disk. // status = ZwFlushBuffersFile( FileHandle, &IoStatus ); if (NT_SUCCESS(status)) { ASSERT(IoStatus.Status == status); return TRUE; } else { Error: // // set debugging info // CmRegistryIODebug.Action = CmpIoFileFlush; CmRegistryIODebug.Handle = FileHandle; CmRegistryIODebug.Status = status; #if DBG DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CmpFileFlush:\tFailure1: status = %08lx IoStatus = %08lx\n",status,IoStatus.Status); #endif return FALSE; } }
BOOLEAN CmpFileWrite( PHHIVE Hive, ULONG FileType, PCMP_OFFSET_ARRAY offsetArray, ULONG offsetArrayCount, PULONG FileOffset ) /*++ Routine Description: This routine writes an array of buffers out to a file. It is environment specific. NOTE: We assume the handle is opened for asynchronous access, and that we, and not the IO system, are keeping the offset pointer. NOTE: Only 32bit offsets are supported, even though the underlying IO system on NT supports 64 bit offsets. Arguments: Hive - Hive we are doing I/O for FileType - which supporting file to use offsetArray - array of structures where each structure holds a 32bit offset into the Hive file and pointer the a buffer written to that file offset. offsetArrayCount - number of elements in the offsetArray. FileOffset - returns the file offset after the last write to the file. Return Value: FALSE if failure TRUE if success --*/ { NTSTATUS status; LARGE_INTEGER Offset; PCMHIVE CmHive; HANDLE FileHandle; ULONG LengthToWrite; LONG WaitBufferCount = 0; LONG idx; ULONG arrayCount = 0; PVOID DataBuffer = NULL; // W4 only ULONG DataLength; BOOLEAN ret_val = TRUE; PCM_WRITE_BLOCK WriteBlock = NULL; if (CmpNoWrite) { return TRUE; } ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0); CmHive = (PCMHIVE)Hive; FileHandle = CmHive->FileHandles[FileType]; if (FileHandle == NULL) { return TRUE; } CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"CmpFileWrite:\n")); CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"\tHandle=%08lx ", FileHandle)); // // decide whether we wait for IOs to complete or just issue them and // rely on the CcFlushCache to do the job // // Bring pages being written into memory first to allow disk to write // buffer contiguously. try { for (idx = 0; (ULONG) idx < offsetArrayCount; idx++) { char * start = offsetArray[idx].DataBuffer; char * end = (char *) start + offsetArray[idx].DataLength; while (start < end) { // perftouchbuffer globally declared so that compiler won't try // to remove it and this loop (if its smart enough?). perftouchbuffer += (ULONG) *start; start += PAGE_SIZE; } } } except (EXCEPTION_EXECUTE_HANDLER) { // // we might get STATUS_IN_PAGE_ERROR // CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpFileWrite has raised :%08lx\n",GetExceptionCode())); return FALSE; } WriteBlock = (PCM_WRITE_BLOCK)ExAllocatePool(NonPagedPool,sizeof(CM_WRITE_BLOCK)); if( WriteBlock == NULL ) { return FALSE; } for (idx = 0; idx < MAXIMUM_WAIT_OBJECTS; idx++) { WriteBlock->EventHandles[idx] = NULL; #if DBG WriteBlock->EventObjects[idx] = NULL; #endif } // // We'd really like to just call the filesystems and have them do // the right thing. But the filesystem will attempt to lock our // entire buffer into memory, and that may fail for large requests. // So we split our reads into 64k chunks and call the filesystem for // each one. // ASSERT_PASSIVE_LEVEL(); arrayCount = 0; DataLength = 0; // This outer loop is hit more than once if the MAXIMUM_WAIT_OBJECTS limit // is hit before the offset array is drained. while (arrayCount < offsetArrayCount) { WaitBufferCount = 0; // This loop fills the wait buffer. while ((arrayCount < offsetArrayCount) && (WaitBufferCount < MAXIMUM_WAIT_OBJECTS)) { // If data length isn't zero than the wait buffer filled before the // buffer in the last offsetArray element was sent to write file. if (DataLength == 0) { *FileOffset = offsetArray[arrayCount].FileOffset; DataBuffer = offsetArray[arrayCount].DataBuffer; DataLength = offsetArray[arrayCount].DataLength; // // Detect attempt to read off end of 2gig file // (this should be irrelevant) // if ((0xffffffff - *FileOffset) < DataLength) { CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpFileWrite: runoff\n")); status = STATUS_INVALID_PARAMETER_5; goto Error_Exit; } } // else still more to write out of last buffer. while ((DataLength > 0) && (WaitBufferCount < MAXIMUM_WAIT_OBJECTS)) { // // Convert ULONG to Large // Offset.LowPart = *FileOffset; Offset.HighPart = 0L; // // trim request down if necessary. // if (DataLength > MAX_FILE_IO) { LengthToWrite = MAX_FILE_IO; } else { LengthToWrite = DataLength; } // Previously created events are reused. if (WriteBlock->EventHandles[WaitBufferCount] == NULL) { status = CmpCreateEvent(SynchronizationEvent, &(WriteBlock->EventHandles[WaitBufferCount]), &(WriteBlock->EventObjects[WaitBufferCount])); if (!NT_SUCCESS(status)) { // Make sure we don't try to clean this up. WriteBlock->EventHandles[WaitBufferCount] = NULL; goto Error_Exit; } CmpSetHandleProtection(WriteBlock->EventHandles[WaitBufferCount],TRUE); } status = ZwWriteFile(FileHandle, WriteBlock->EventHandles[WaitBufferCount], NULL, // apcroutine NULL, // apccontext &(WriteBlock->IoStatus[WaitBufferCount]), DataBuffer, LengthToWrite, &Offset, NULL); if (!NT_SUCCESS(status)) { goto Error_Exit; } WaitBufferCount++; // // adjust offsets // *FileOffset = Offset.LowPart + LengthToWrite; DataLength -= LengthToWrite; DataBuffer = (PVOID)((PCHAR)DataBuffer + LengthToWrite); } // while (DataLength > 0 && WaitBufferCount < MAXIMUM_WAIT_OBJECTS) arrayCount++; } // while (arrayCount < offsetArrayCount && // WaitBufferCount < MAXIMUM_WAIT_OBJECTS) status = KeWaitForMultipleObjects(WaitBufferCount, WriteBlock->EventObjects, WaitAll, Executive, KernelMode, FALSE, NULL, WriteBlock->WaitBlockArray); if (!NT_SUCCESS(status)) goto Error_Exit; for (idx = 0; idx < WaitBufferCount; idx++) { if (!NT_SUCCESS(WriteBlock->IoStatus[idx].Status)) { status = WriteBlock->IoStatus[idx].Status; ret_val = FALSE; goto Done; } } // There may still be more to do if the last element held a big buffer // and the wait buffer filled before it was all sent to the file. if (DataLength > 0) { arrayCount--; } } // while (arrayCount < offsetArrayCount) ret_val = TRUE; goto Done; Error_Exit: // // set debugging info // CmRegistryIODebug.Action = CmpIoFileWrite; CmRegistryIODebug.Handle = FileHandle; CmRegistryIODebug.Status = status; #if DBG DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CmpFileWrite: error exiting %d\n", status); #endif // // if WaitBufferCount > 0 then we have successfully issued // some I/Os, but not all of them. This is an error, but we // cannot return from this routine until all the successfully // issued I/Os have completed. // if (WaitBufferCount > 0) { // // only if we decided that we want to wait for the write to complete // (log files and hives not using the mapped views technique) // status = KeWaitForMultipleObjects(WaitBufferCount, WriteBlock->EventObjects, WaitAll, Executive, KernelMode, FALSE, NULL, WriteBlock->WaitBlockArray); } ret_val = FALSE; Done: idx = 0; // Clean up open event handles and objects. while ((idx < MAXIMUM_WAIT_OBJECTS) && (WriteBlock->EventHandles[idx] != NULL)) { ASSERT( WriteBlock->EventObjects[idx] ); ObDereferenceObject(WriteBlock->EventObjects[idx]); CmCloseHandle(WriteBlock->EventHandles[idx]); idx++; } if( WriteBlock != NULL ) { ExFreePool(WriteBlock); } return ret_val; }
BOOLEAN CmpFileRead ( PHHIVE Hive, ULONG FileType, PULONG FileOffset, PVOID DataBuffer, ULONG DataLength ) /*++ Routine Description: This routine reads in a buffer from a file. It is environment specific. NOTE: We assume the handle is opened for asynchronous access, and that we, and not the IO system, are keeping the offset pointer. NOTE: Only 32bit offsets are supported, even though the underlying IO system on NT supports 64 bit offsets. Arguments: Hive - Hive we are doing I/O for FileType - which supporting file to use FileOffset - pointer to variable providing 32bit offset on input, and receiving new 32bit offset on output. DataBuffer - pointer to buffer DataLength - length of buffer Return Value: FALSE if failure TRUE if success --*/ { NTSTATUS status; LARGE_INTEGER Offset; IO_STATUS_BLOCK IoStatus; PCMHIVE CmHive; HANDLE FileHandle; ULONG LengthToRead; HANDLE eventHandle = NULL; PKEVENT eventObject = NULL; ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0); CmHive = (PCMHIVE)Hive; FileHandle = CmHive->FileHandles[FileType]; if (FileHandle == NULL) { return TRUE; } CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"CmpFileRead:\n")); CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"\tHandle=%08lx Offset=%08lx ", FileHandle, *FileOffset)); CmKdPrintEx((DPFLTR_CONFIG_ID,CML_IO,"Buffer=%p Length=%08lx\n", DataBuffer, DataLength)); // // Detect attempt to read off end of 2gig file (this should be irrelevant) // if ((0xffffffff - *FileOffset) < DataLength) { CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpFileRead: runoff\n")); return FALSE; } status = CmpCreateEvent( SynchronizationEvent, &eventHandle, &eventObject); if (!NT_SUCCESS(status)) return FALSE; // // We'd really like to just call the filesystems and have them do // the right thing. But the filesystem will attempt to lock our // entire buffer into memory, and that may fail for large requests. // So we split our reads into 64k chunks and call the filesystem for // each one. // ASSERT_PASSIVE_LEVEL(); while (DataLength > 0) { // // Convert ULONG to Large // Offset.LowPart = *FileOffset; Offset.HighPart = 0L; // // trim request down if necessary. // if (DataLength > MAX_FILE_IO) { LengthToRead = MAX_FILE_IO; } else { LengthToRead = DataLength; } status = ZwReadFile( FileHandle, eventHandle, NULL, // apcroutine NULL, // apccontext &IoStatus, DataBuffer, LengthToRead, &Offset, NULL // key ); if (STATUS_PENDING == status) { status = KeWaitForSingleObject(eventObject, Executive, KernelMode, FALSE, NULL); ASSERT(STATUS_SUCCESS == status); status = IoStatus.Status; } // // adjust offsets // *FileOffset = Offset.LowPart + LengthToRead; DataLength -= LengthToRead; DataBuffer = (PVOID)((PCHAR)DataBuffer + LengthToRead); if (NT_SUCCESS(status)) { ASSERT(IoStatus.Status == status); if (IoStatus.Information != LengthToRead) { CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpFileRead:\n\t")); CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"Failure1: status = %08lx ", status)); CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"IoInformation = %08lx\n", IoStatus.Information)); ObDereferenceObject(eventObject); ZwClose(eventHandle); CmRegistryIODebug.Action = CmpIoFileRead; CmRegistryIODebug.Handle = FileHandle; #if defined(_WIN64) CmRegistryIODebug.Status = (ULONG)IoStatus.Information - LengthToRead; #else CmRegistryIODebug.Status = (ULONG)&IoStatus; #endif return FALSE; } } else { // // set debugging info // CmRegistryIODebug.Action = CmpIoFileRead; CmRegistryIODebug.Handle = FileHandle; CmRegistryIODebug.Status = status; #if DBG DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"CmpFileRead:\tFailure2: status = %08lx IoStatus = %08lx\n", status, IoStatus.Status); #endif ObDereferenceObject(eventObject); ZwClose(eventHandle); return FALSE; } } ObDereferenceObject(eventObject); ZwClose(eventHandle); return TRUE; }
NTSTATUS RosKmAdapter::QueryAdapterInfo( IN_CONST_PDXGKARG_QUERYADAPTERINFO pQueryAdapterInfo) { NTSTATUS Status = STATUS_INVALID_PARAMETER; DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, "RosKmdQueryAdapterInfo Type=%d\n", pQueryAdapterInfo->Type); switch (pQueryAdapterInfo->Type) { case DXGKQAITYPE_UMDRIVERPRIVATE: { if (pQueryAdapterInfo->OutputDataSize < sizeof(ROSADAPTERINFO)) { Status = STATUS_INVALID_PARAMETER; break; } ROSADAPTERINFO* pRosAdapterInfo = (ROSADAPTERINFO*)pQueryAdapterInfo->pOutputData; pRosAdapterInfo->m_version = ROSD_VERSION; pRosAdapterInfo->m_wddmVersion = m_WDDMVersion; // Software APCI device only claims an interrupt resource pRosAdapterInfo->m_isSoftwareDevice = (m_flags.m_isVC4 != 1); RtlCopyMemory( pRosAdapterInfo->m_deviceId, m_deviceId, m_deviceIdLength); Status = STATUS_SUCCESS; } break; case DXGKQAITYPE_DRIVERCAPS: { if (pQueryAdapterInfo->OutputDataSize < sizeof(DXGK_DRIVERCAPS)) { Status = STATUS_INVALID_PARAMETER; break; } DXGK_DRIVERCAPS *pDriverCaps = (DXGK_DRIVERCAPS *)pQueryAdapterInfo->pOutputData; // // HighestAcceptableAddress // pDriverCaps->HighestAcceptableAddress.QuadPart = -1; // // TODO[bhouse] MaxAllocationListSlotId // // // TODO[bhouse] ApertureSegmentCommitLimit // // // TODO[bhouse] MaxPointerWidth // // // TODO[bhouse] MaxPointerHeight // // // TODO[bhouse] PointerCaps // // // TODO[bhouse] InterruptMessageNumber // // // TODO[bhouse] NumberOfSwizzlingRanges // // // TODO[bhouse] MaxOverlays // // // TODO[bhouse] GammarRampCaps // // // TODO[bhouse] PresentationCaps // pDriverCaps->PresentationCaps.SupportKernelModeCommandBuffer = FALSE; pDriverCaps->PresentationCaps.SupportSoftwareDeviceBitmaps = TRUE; // // Cap used for DWM off case, screen to screen blt is slow // pDriverCaps->PresentationCaps.NoScreenToScreenBlt = TRUE; pDriverCaps->PresentationCaps.NoOverlapScreenBlt = TRUE; // // Allow 16Kx16K (2 << (11 + 3)) texture(redirection device bitmap) // pDriverCaps->PresentationCaps.MaxTextureWidthShift = 3; pDriverCaps->PresentationCaps.MaxTextureHeightShift = 3; // // TODO[bhouse] MaxQueueFlipOnVSync // // // TODO[bhouse] FlipCaps // // // Use SW flip queue for flip with interval of 1 or more // #if 1 pDriverCaps->FlipCaps.FlipOnVSyncMmIo = 1; #endif // // TODO[bhouse] SchedulingCaps // #if 1 pDriverCaps->SchedulingCaps.MultiEngineAware = 1; #endif // // Set scheduling caps to indicate support for cancelling DMA buffer // #if 1 pDriverCaps->SchedulingCaps.CancelCommandAware = 1; #endif // // Set scheduling caps to indicate driver is preemption aware // #if 1 pDriverCaps->SchedulingCaps.PreemptionAware = 1; #endif // // TODO[bhouse] MemoryManagementCaps // #if 1 pDriverCaps->MemoryManagementCaps.CrossAdapterResource = 1; #endif // // TODO[bhouse] GpuEngineTopology // pDriverCaps->GpuEngineTopology.NbAsymetricProcessingNodes = m_NumNodes; // // TODO[bhouse] WDDMVersion // Documentation states that we should not set this value if WDDM 1.3 // pDriverCaps->WDDMVersion = m_WDDMVersion; // // TODO[bhouse] VirtualAddressCaps // // // TODO[bhouse] DmaBufferCaps // // // TODO[bhouse] PreemptionCaps // #if 1 pDriverCaps->PreemptionCaps.GraphicsPreemptionGranularity = D3DKMDT_GRAPHICS_PREEMPTION_PRIMITIVE_BOUNDARY; pDriverCaps->PreemptionCaps.ComputePreemptionGranularity = D3DKMDT_COMPUTE_PREEMPTION_DISPATCH_BOUNDARY; #endif // // TODO[bhouse] SupportNonVGA // // // TODO[bhouse] SupportSmoothRotation // // // TODO[bhouse] SupportPerEngineTDR // #if 1 pDriverCaps->SupportPerEngineTDR = 1; #endif // // TODO[bhouse] SupportDirectFlip // #if 1 pDriverCaps->SupportDirectFlip = 1; #endif // // TODO[bhouse] SupportMultiPlaneOverlay // // // Support SupportRuntimePowerManagement // pDriverCaps->SupportRuntimePowerManagement = 1; // // TODO[bhouse] SupportSurpriseRemovalInHibernation // // // TODO[bhouse] HybridDiscrete // // // TODO[bhouse] MaxOverlayPlanes // Status = STATUS_SUCCESS; } break; case DXGKQAITYPE_QUERYSEGMENT3: { if (pQueryAdapterInfo->OutputDataSize < sizeof(DXGK_QUERYSEGMENTOUT3)) { Status = STATUS_INVALID_PARAMETER; break; } DXGK_QUERYSEGMENTOUT3 *pSegmentInfo = (DXGK_QUERYSEGMENTOUT3*)pQueryAdapterInfo->pOutputData; Status = STATUS_SUCCESS; if (!pSegmentInfo[0].pSegmentDescriptor) { pSegmentInfo->NbSegment = 2; } else { DXGK_SEGMENTDESCRIPTOR3 *pSegmentDesc = pSegmentInfo->pSegmentDescriptor; // // Private data size should be the maximum of UMD and KMD and the same size must // be reported in DxgkDdiCreateContext for paging engine // pSegmentInfo->PagingBufferPrivateDataSize = sizeof(ROSUMDDMAPRIVATEDATA2); pSegmentInfo->PagingBufferSegmentId = ROSD_SEGMENT_APERTURE; pSegmentInfo->PagingBufferSize = PAGE_SIZE; // // Fill out aperture segment descriptor // memset(&pSegmentDesc[0], 0, sizeof(pSegmentDesc[0])); pSegmentDesc[0].Flags.Aperture = TRUE; // // TODO[bhouse] What does marking it CacheCoherent mean? What are the side effects? // What happens if we don't mark CacheCoherent? // pSegmentDesc[0].Flags.CacheCoherent = TRUE; // // TODO[bhouse] BaseAddress should never be used. Do we need to set this still? // pSegmentDesc[0].BaseAddress.QuadPart = ROSD_SEGMENT_APERTURE_BASE_ADDRESS; // // Our fake apperture is not really visible and doesn't need to be. We // still need to lie that it is visible reporting a bad physical address // that will never be used. // // TODO[bhouse] Investigate why we have to lie. // pSegmentDesc[0].CpuTranslatedAddress.QuadPart = 0xFFFFFFFE00000000; pSegmentDesc[0].Flags.CpuVisible = TRUE; pSegmentDesc[0].Size = kApertureSegmentSize; pSegmentDesc[0].CommitLimit = kApertureSegmentSize; // // Setup local video memory segment // memset(&pSegmentDesc[1], 0, sizeof(pSegmentDesc[1])); pSegmentDesc[1].BaseAddress.QuadPart = 0LL; // Gpu base physical address pSegmentDesc[1].Flags.CpuVisible = true; pSegmentDesc[1].Flags.CacheCoherent = true; pSegmentDesc[1].CpuTranslatedAddress = RosKmdGlobal::s_videoMemoryPhysicalAddress; // cpu base physical address pSegmentDesc[1].Size = RosKmdGlobal::s_videoMemorySize; } } break; case DXGKQAITYPE_NUMPOWERCOMPONENTS: { if (pQueryAdapterInfo->OutputDataSize != sizeof(UINT)) { Status = STATUS_INVALID_PARAMETER; break; } // // Support only one 3D engine(s). // *(reinterpret_cast<UINT*>(pQueryAdapterInfo->pOutputData)) = GetNumPowerComponents(); Status = STATUS_SUCCESS; } break; case DXGKQAITYPE_POWERCOMPONENTINFO: { if (pQueryAdapterInfo->InputDataSize != sizeof(UINT) || pQueryAdapterInfo->OutputDataSize < sizeof(DXGK_POWER_RUNTIME_COMPONENT)) { Status = STATUS_INVALID_PARAMETER; break; } ULONG ComponentIndex = *(reinterpret_cast<UINT*>(pQueryAdapterInfo->pInputData)); DXGK_POWER_RUNTIME_COMPONENT* pPowerComponent = reinterpret_cast<DXGK_POWER_RUNTIME_COMPONENT*>(pQueryAdapterInfo->pOutputData); Status = GetPowerComponentInfo(ComponentIndex, pPowerComponent); } break; case DXGKQAITYPE_HISTORYBUFFERPRECISION: { UINT NumStructures = pQueryAdapterInfo->OutputDataSize / sizeof(DXGKARG_HISTORYBUFFERPRECISION); for (UINT i = 0; i < NumStructures; i++) { DXGKARG_HISTORYBUFFERPRECISION *pHistoryBufferPrecision = ((DXGKARG_HISTORYBUFFERPRECISION *)pQueryAdapterInfo->pOutputData) + i; pHistoryBufferPrecision->PrecisionBits = 64; } Status = STATUS_SUCCESS; } break; default: // NT_ASSERT(FALSE); break; } return Status; }
NTSTATUS __stdcall RosKmContext::DdiRender( IN_CONST_HANDLE hContext, INOUT_PDXGKARG_RENDER pRender) { DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, "RosKmdRender hAdapter=%lx\n", hContext); RosKmContext *pRosKmContext = (RosKmContext *)hContext; pRosKmContext; pRender->MultipassOffset; pRender->DmaBufferSegmentId; pRender->DmaBufferPhysicalAddress; pRender->pDmaBufferPrivateData; pRender->DmaBufferPrivateDataSize; // Copy command buffer NT_ASSERT(pRender->DmaSize >= pRender->CommandLength); __try { memcpy(pRender->pDmaBuffer, pRender->pCommand, pRender->CommandLength); } __except (EXCEPTION_EXECUTE_HANDLER) { return STATUS_INVALID_PARAMETER; } // Check to command buffer header GpuCommand * pCmdBufHeader = (GpuCommand *)pRender->pDmaBuffer; if (pCmdBufHeader->m_commandId != Header) { return STATUS_ILLEGAL_INSTRUCTION; } // Copy path list NT_ASSERT(pRender->PatchLocationListOutSize >= pRender->PatchLocationListInSize); D3DDDI_PATCHLOCATIONLIST * pPatchLocationList = pRender->pPatchLocationListOut; __try { for (UINT i = 0; i < pRender->PatchLocationListInSize; i++) { pPatchLocationList[i] = pRender->pPatchLocationListIn[i]; } } __except (EXCEPTION_EXECUTE_HANDLER) { return STATUS_INVALID_PARAMETER; } // Must update pPatchLocationListOut to reflect what space was used pRender->pPatchLocationListOut += pRender->PatchLocationListInSize; // Perform pre-patch PBYTE pDmaBuf = (BYTE *)pCmdBufHeader; for (UINT i = 0; i < pRender->PatchLocationListInSize; i++) { auto patch = &pPatchLocationList[i]; NT_ASSERT(patch->AllocationIndex < pRender->AllocationListSize); auto allocation = &pRender->pAllocationList[patch->AllocationIndex]; if (allocation->SegmentId != 0) { RosKmdDeviceAllocation * pRosKmdDeviceAllocation = (RosKmdDeviceAllocation *)allocation->hDeviceSpecificAllocation; DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, "Pre-patch RosKmdDeviceAllocation %lx at %lx\n", pRosKmdDeviceAllocation, allocation->PhysicalAddress); DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, "Pre-patch buffer offset %lx allocation offset %lx\n", patch->PatchOffset, patch->AllocationOffset); // Patch in dma buffer NT_ASSERT(allocation->SegmentId == ROSD_SEGMENT_VIDEO_MEMORY); if (pCmdBufHeader->m_commandBufferHeader.m_swCommandBuffer) { *((PHYSICAL_ADDRESS *)(pDmaBuf + patch->PatchOffset)) = allocation->PhysicalAddress; } else { // Patch HW command buffer } } } // Record DMA buffer information ROSDMABUFINFO * pDmaBufInfo = (ROSDMABUFINFO *)pRender->pDmaBufferPrivateData; pDmaBufInfo->m_DmaBufState.m_Value = 0; pDmaBufInfo->m_DmaBufState.m_Render = 1; pDmaBufInfo->m_DmaBufState.m_bSwCommandBuffer = pCmdBufHeader->m_commandBufferHeader.m_swCommandBuffer; pDmaBufInfo->m_pDmaBuffer = (PBYTE)pRender->pDmaBuffer; pDmaBufInfo->m_DmaBufferSize = pRender->DmaSize; // Must update pDmaBuffer to reflect what space we used pRender->pDmaBuffer = (char *)pRender->pDmaBuffer + pRender->CommandLength; return STATUS_SUCCESS; }
NTSTATUS QueryCapability( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION pStk; PDEVICE_EXTENSION pCtx; NTSTATUS Status; KEVENT event; ULONG IdxPwrState; DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Query Device Capability....\r\n"); DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Ready to pass IRP down\r\n"); pStk = IoGetCurrentIrpStackLocation(Irp); pCtx = DeviceObject->DeviceExtension; KeInitializeEvent(&event, NotificationEvent, FALSE); IoCopyCurrentIrpStackLocationToNext(Irp); IoSetCompletionRoutine( Irp, (PIO_COMPLETION_ROUTINE)CompletionQueryCapability, (PVOID)&event,//pCtx, TRUE, TRUE, TRUE); Status = IoCallDriver( pCtx->NextDeviceObject, Irp); KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); if (NT_SUCCESS(Irp->IoStatus.Status)) { pStk = IoGetCurrentIrpStackLocation(Irp); pCtx = (DEVICE_EXTENSION*)DeviceObject->DeviceExtension; pCtx->pdc = *pStk->Parameters.DeviceCapabilities.Capabilities; Global_PowerInfo_Ptr->SupportQueryCapability = TRUE; Global_PowerInfo_Ptr->DeviceD1 = pCtx->pdc.DeviceD1; Global_PowerInfo_Ptr->DeviceD2 = pCtx->pdc.DeviceD1; Global_PowerInfo_Ptr->WakeFromD0 = pCtx->pdc.WakeFromD0; Global_PowerInfo_Ptr->WakeFromD1 = pCtx->pdc.WakeFromD1; Global_PowerInfo_Ptr->WakeFromD2 = pCtx->pdc.WakeFromD2; Global_PowerInfo_Ptr->WakeFromD3 = pCtx->pdc.WakeFromD3; Global_PowerInfo_Ptr->DeviceWake = pCtx->pdc.DeviceWake; Global_PowerInfo_Ptr->SystemWake = pCtx->pdc.SystemWake; for (IdxPwrState = 0; IdxPwrState < PowerSystemMaximum; IdxPwrState++) { Global_PowerInfo_Ptr->DeviceState[IdxPwrState] = pCtx->pdc.DeviceState[IdxPwrState]; } } else { DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "Failed to handle IRP_MN_QUERY_CAPABILITIES"); } return Irp->IoStatus.Status; }
/////////////////////////////////////////////////////////////////////////////// // Initialization of component level power management. /////////////////////////////////////////////////////////////////////////////// VOID SmplPoFxSingleComponentInitialize( _In_ WDFDEVICE Device ) { WDF_POWER_FRAMEWORK_SETTINGS Settings; PO_FX_COMPONENT Component; PO_FX_COMPONENT_IDLE_STATE IdleStates[FSTATE_COUNT]; NTSTATUS Status; // // Initialization // RtlZeroMemory(&Component, sizeof(Component)); RtlZeroMemory(&IdleStates, sizeof(IdleStates)); // // The transition latency and residency requirement values used here are for // illustration purposes only. The driver should use values that are // appropriate for its device. // // // F0 // IdleStates[0].TransitionLatency = 0; IdleStates[0].ResidencyRequirement = 0; IdleStates[0].NominalPower = 0; // // F1 // IdleStates[1].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(200); IdleStates[1].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(3); IdleStates[1].NominalPower = 0; // // F2 // IdleStates[2].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(400); IdleStates[2].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(6); IdleStates[2].NominalPower = 0; // // F3 // IdleStates[3].TransitionLatency = WDF_ABS_TIMEOUT_IN_MS(DEEPEST_FSTATE_LATENCY_IN_MS); IdleStates[3].ResidencyRequirement = WDF_ABS_TIMEOUT_IN_SEC(DEEPEST_FSTATE_RESIDENCY_IN_SEC); IdleStates[3].NominalPower = 0; // // Component 0 (the only component) // Component.IdleStateCount = FSTATE_COUNT; Component.IdleStates = IdleStates; WDF_POWER_FRAMEWORK_SETTINGS_INIT(&Settings); Settings.EvtDeviceWdmPostPoFxRegisterDevice = SmplDeviceEvtWdmPostPoFxRegisterDevice; Settings.Component = &Component; Settings.ComponentActiveConditionCallback = SmplPoFxComponentActiveConditionCallback; Settings.ComponentIdleConditionCallback = SmplPoFxComponentIdleConditionCallback; Settings.ComponentIdleStateCallback = SmplPoFxComponentIdleStateCallback; Settings.PoFxDeviceContext = (PVOID) Device; Status = WdfDeviceWdmAssignPowerFrameworkSettings(Device, &Settings); if (FALSE == NT_SUCCESS(Status)) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"WdfDeviceWdmAssignPowerFrameworkSettings failed! 0x%x\n", Status); } } // end SmplPoFxSingleComponentInitialize
_IRQL_requires_same_ VOID ClassifyPendAuthorization(_In_ const FWPS_INCOMING_VALUES* pClassifyValues, _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata, _Inout_opt_ VOID* pNetBufferList, _In_ const FWPS_FILTER* pFilter, _In_ UINT64 flowContext, _Inout_ FWPS_CLASSIFY_OUT* pClassifyOut) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> ClassifyPendAuthorization()\n"); #endif /// DBG NT_ASSERT(pClassifyValues); NT_ASSERT(pMetadata); NT_ASSERT(pFilter); NT_ASSERT(pClassifyOut); NT_ASSERT(pClassifyValues->layerId == FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V4 || pClassifyValues->layerId == FWPS_LAYER_ALE_RESOURCE_ASSIGNMENT_V6 || pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_LISTEN_V4 || pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_LISTEN_V6 || pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 || pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6 || pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 || pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6); NT_ASSERT(pFilter->providerContext); NT_ASSERT(pFilter->providerContext->type == FWPM_GENERAL_CONTEXT); NT_ASSERT(pFilter->providerContext->dataBuffer); NT_ASSERT(pFilter->providerContext->dataBuffer->size == sizeof(PC_PEND_AUTHORIZATION_DATA)); NT_ASSERT(pFilter->providerContext->dataBuffer->data); NTSTATUS status = STATUS_SUCCESS; PC_PEND_AUTHORIZATION_DATA* pPendAuthorizationData = (PC_PEND_AUTHORIZATION_DATA*)pFilter->providerContext->dataBuffer->data; /// AUTH_CONNECT's completeOperation will trigger a Reauthorization if(KrnlHlprFwpsIncomingValueConditionFlagsAreSet(pClassifyValues, FWP_CONDITION_FLAG_IS_REAUTHORIZE)) { if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE) pClassifyOut->actionType = pPendAuthorizationData->finalAction; } else { BOOLEAN actionSet = FALSE; if(pClassifyOut->rights & FWPS_RIGHT_ACTION_WRITE) { INJECTION_DATA* pInjectionData = 0; PEND_DATA* pPendData = 0; #pragma warning(push) #pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy status = KrnlHlprInjectionDataCreate(&pInjectionData, pClassifyValues, pMetadata, (NET_BUFFER_LIST*)pNetBufferList); HLPR_BAIL_ON_FAILURE(status); #pragma warning(pop) /// AUTH_RECV_ACCEPT's injection will be indicative of PERMIT if(pInjectionData->injectionState == FWPS_PACKET_INJECTED_BY_SELF) { pClassifyOut->actionType = pPendAuthorizationData->finalAction; actionSet = TRUE; } else { #pragma warning(push) #pragma warning(disable: 6014) /// pInjectionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy status = KrnlHlprPendDataCreate(&pPendData, pMetadata, (NET_BUFFER_LIST*)pNetBufferList, pFilter); HLPR_BAIL_ON_FAILURE(status); #pragma warning(pop) status = TriggerPendAuthorizationOutOfBand(pClassifyValues, pMetadata, pNetBufferList, 0, pFilter, flowContext, pClassifyOut, pInjectionData, pPendData, pPendAuthorizationData); } HLPR_BAIL_LABEL: if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! ClassifyPendAuthorization() [status: %#x]\n", status); if(pInjectionData) KrnlHlprInjectionDataDestroy(&pInjectionData); if(pPendData) KrnlHlprPendDataDestroy(&pPendData); } if(!actionSet) { pClassifyOut->actionType = FWP_ACTION_BLOCK; pClassifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB; } } } #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- ClassifyPendAuthorization()\n"); #endif /// DBG return; }
NTSTATUS ReinjectPendedPacket( IN PENDED_PACKET *packet, IN FLOW_DATA *flowData) { NTSTATUS status; UINT32 flags; NET_BUFFER_LIST* netBufferList = NULL; FLOW_DATA *flowCtx; ULONG dataLength; if(packet->dataLength == 0 || packet->data == NULL) { return STATUS_UNSUCCESSFUL; } packet->mdl = IoAllocateMdl( packet->data, packet->dataLength, FALSE, FALSE, NULL); if (packet->mdl == NULL) { status = STATUS_NO_MEMORY; goto Exit; } MmBuildMdlForNonPagedPool(packet->mdl); status = FwpsAllocateNetBufferAndNetBufferList( gNetBufferListPool, 0, 0, packet->mdl, 0, packet->dataLength, &netBufferList); if(!NT_SUCCESS(status)) { goto Exit; } flags = packet->flags; dataLength = packet->dataLength; flowCtx = packet->flowContext; #ifdef DEBUG debugPacket(packet); DbgPrintEx( DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, "\n localCtr=%d, remoteCtr=%d\n", flowCtx->localCounter, flowCtx->remoteCounter); #endif // Keep correct sequence numbers // (Assume every reinjection is successful, otherwise synchronous injection is // needed for consistent sequence numbers implementation) if(flags & FWPS_STREAM_FLAG_SEND) { flowCtx->localCounter += dataLength; } else if(flags & FWPS_STREAM_FLAG_RECEIVE) { flowCtx->remoteCounter += dataLength; } else { #ifdef DEBUG DbgBreakPoint(); #endif } status = FwpsStreamInjectAsync( gInjectionHandle, NULL, 0, flowData->flowHandle, gStreamCalloutIdV4, FWPS_LAYER_STREAM_V4, flags, netBufferList, packet->dataLength, StreamInjectCompletionFn, packet); if (!NT_SUCCESS(status)) { goto Exit; } // Ownership transferred netBufferList = NULL; packet = NULL; Exit: if (netBufferList != NULL) { FwpsFreeNetBufferList(netBufferList); } if (packet != NULL) { FreePendedPacket(packet); } return status; }
/////////////////////////////////////////////////////////////////////////////// /// /// This function handles 'control' irp. /// /////////////////////////////////////////////////////////////////////////////// NTSTATUS TdDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION IrpStack; ULONG Ioctl; NTSTATUS Status; UNREFERENCED_PARAMETER(DeviceObject); Status = STATUS_SUCCESS; IrpStack = IoGetCurrentIrpStackLocation(Irp); Ioctl = IrpStack->Parameters.DeviceIoControl.IoControlCode; DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "TdDeviceControl: entering - ioctl code 0x%x\n", Ioctl); // Sanity check: Check the size of the request if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(COMM_REQUEST)) { // Wrong size DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "TdDeviceControl: Wrong size request\n"); Irp->IoStatus.Status = STATUS_BUFFER_OVERFLOW; Irp->IoStatus.Information = sizeof(COMM_REQUEST); IoCompleteRequest(Irp, IO_NO_INCREMENT); return STATUS_BUFFER_OVERFLOW; } switch (Ioctl) { case QD_IOCTL_GET_NEW_PROCESSES: DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "TdDeviceControl: recieved QD_IOCTL_GET_NEW_PROCESSES\n"); // Process it Status = ProcessIoctl_GetNewProcesses(Irp); // // Complete the irp and return. // Irp->IoStatus.Status = Status; if (STATUS_PENDING != Status) { IoCompleteRequest(Irp, IO_NO_INCREMENT); } break; case QD_IOCTL_CONTROLLER_PROCESS_DECISION: DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "TdDeviceControl: recieved QD_IOCTL_CONTROLLER_PROCESS_DECISION\n"); // Process it Status = ProcessIoctl_ControllerProcessDecision(Irp); // // Complete the irp and return. // Irp->IoStatus.Status = Status; IoCompleteRequest(Irp, IO_NO_INCREMENT); break; default: // // Invalid request operation // DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "TdDeviceControl: unrecognized ioctl code 0x%x\n", Ioctl); Status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = Status; Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); } DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "TdDeviceControl leaving - status 0x%x\n", Status); return Status; }
NTSTATUS Mouse_Hook(IN PDRIVER_OBJECT driverObject) { ULONG i; int found = 1; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION stack; UNICODE_STRING uniMouseDeviceName; PFILE_OBJECT mouseFileObject; PDEVICE_OBJECT MouseDeviceObject; ULONG counter; HANDLE hDir; OBJECT_ATTRIBUTES oa; UNICODE_STRING uniOa; PVOID pBuffer; PVOID pContext; ULONG RetLen; PDIRECTORY_BASIC_INFORMATION pDirBasicInfo; UNICODE_STRING uniMouseDrv; char* mouseclsNum; char arMouseCls[0x10]; WCHAR tmpNameBuffer[512]; DbgPrint("Running Mouse_Create."); RtlInitUnicodeString(&uniOa, L"\\Device"); InitializeObjectAttributes( &oa,&uniOa, OBJ_CASE_INSENSITIVE,NULL,NULL); status = ZwOpenDirectoryObject( &hDir,DIRECTORY_ALL_ACCESS,&oa); if(!NT_SUCCESS(status)) return status; pBuffer = ExAllocatePool(PagedPool, ALLOC_SIZE); pContext = ExAllocatePool(PagedPool, ALLOC_SIZE); // pBuffer = ExAllocatePoolWithTag(PagedPool, ALLOC_SIZE, Tag); // pContext = ExAllocatePoolWithTag(PagedPool, ALLOC_SIZE, Tag); memset(pBuffer, 0, ALLOC_SIZE); memset(pContext, 0, ALLOC_SIZE); memset(arMouseCls, 0, 0x10); counter = 0; g_Mouseclsnum = 0; while(TRUE) { status = ZwQueryDirectoryObject(hDir,pBuffer,ALLOC_SIZE,TRUE,FALSE,pContext,&RetLen); if(!NT_SUCCESS(status)) break; pDirBasicInfo = (PDIRECTORY_BASIC_INFORMATION)pBuffer; pDirBasicInfo->ObjectName.Length -= 2; RtlInitUnicodeString(&uniMouseDrv, L"PointerClass"); if(RtlCompareUnicodeString( &pDirBasicInfo->ObjectName, &uniMouseDrv,FALSE) == 0){ mouId = (ULONG)(*(char *)(pDirBasicInfo->ObjectName.Buffer+pDirBasicInfo->ObjectName.Length)); mouId -= 0x30; pDirBasicInfo->ObjectName.Length += 2; RtlInitUnicodeString(&uniMouseDeviceName, pDirBasicInfo->ObjectName.Buffer); found = 1; break; } pDirBasicInfo->ObjectName.Length += 2; } ExFreePool(pBuffer); ExFreePool(pContext); ZwClose(hDir); if( found == 0 ) return status; DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,"Mouse_Hook ----> mouId[%d].\n", mouId); swprintf(tmpNameBuffer, L"\\Device\\%s", uniMouseDeviceName.Buffer); RtlInitUnicodeString(&uniMouseDeviceName, tmpNameBuffer); status = My_IoGetDeviceObjectPointer(&uniMouseDeviceName, FILE_ALL_ACCESS, &mouseFileObject,&MouseDeviceObject); if(NT_SUCCESS(status)) { g_MouseDeviceObject = MouseDeviceObject; ObDereferenceObject(mouseFileObject); g_OldReadFunction = g_MouseDeviceObject->DriverObject->MajorFunction[IRP_MJ_READ]; g_MouseDeviceObject->DriverObject->MajorFunction[IRP_MJ_READ] = Mouse_HookProc; g_OldInternalDeviceFunction = g_MouseDeviceObject->DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL]; g_MouseDeviceObject->DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = Mouse_IO_InternalIoctl; DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,"Mouse_Create ----> Mouse_HookProc success.\n"); } return status; }
/////////////////////////////////////////////////////////////////////////////// // Private local helper function that parses the translated resource list // and extracts the data needed for the port address. /////////////////////////////////////////////////////////////////////////////// NTSTATUS SmplDeviceHwResourcesGet( IN WDFDEVICE Device, IN WDFCMRESLIST ResourcesTranslated ) { NTSTATUS Status = STATUS_SUCCESS; ULONG index = 0; PCM_PARTIAL_RESOURCE_DESCRIPTOR pCMResourceDescPartial; PDEVICE_CONTEXT pSmplDeviceContext = NULL; pSmplDeviceContext = DeviceGetContext(Device); DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"SmplDeviceHwResourcesGet >>\n"); if (NULL != pSmplDeviceContext) { for (index = 0; index < WdfCmResourceListGetCount(ResourcesTranslated); index++) { pCMResourceDescPartial = WdfCmResourceListGetDescriptor(ResourcesTranslated, index); if (NULL == pCMResourceDescPartial) { DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"pCMResourceDescPartial is NULL!!!\n"); return STATUS_DEVICE_CONFIGURATION_ERROR; } switch (pCMResourceDescPartial->Type) { case CmResourceTypeMemory: // // Handle memory resources here. // DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"CmResourceTypeMemory Desc\n"); break; case CmResourceTypePort: // // Handle port resources here. // DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"CmResourceTypePort 0x%x %d\n", pCMResourceDescPartial->u.Port.Start.LowPart, pCMResourceDescPartial->u.Port.Length); pSmplDeviceContext->pPortAddress = (PUCHAR) pCMResourceDescPartial->u.Port.Start.LowPart; pSmplDeviceContext->PortAddressLength = pCMResourceDescPartial->u.Port.Length; break; case CmResourceTypeInterrupt: // // Handle interrupt resources here. // DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"CmResourceTypeInterrupt\n"); break; default: // // Ignore all other descriptors. // DbgPrintEx(DPFLTR_IHVDRIVER_ID, 1234,"CmResourceType unknown\n"); break; } // end switch } // end for loop } // end if return Status; } // end SmplDeviceHwResourcesGet
_Use_decl_annotations_ VOID TreeSampleProcessOtherDeviceIo( WDFDEVICE MasterDevice, WDFREQUEST Request ) /*++ Routine Description: This routine is called when an unrecognized IO request is made to the device. This can be used to process private calls directly to the secure device. Arguments: MasterDevice - Supplies a handle to the master device object. DeviceContext - Supplies a pointer to the context. Request - Supplies a pointer to the WDF request object. Return Value: NTSTATUS code. --*/ { PWCHAR Buffer; size_t BufferSize; ULONG BytesWritten; WDF_REQUEST_PARAMETERS Parameters; NTSTATUS Status; PAGED_CODE(); UNREFERENCED_PARAMETER(MasterDevice); WDF_REQUEST_PARAMETERS_INIT(&Parameters); WdfRequestGetParameters(Request, &Parameters); BytesWritten = 0; switch (Parameters.Parameters.DeviceIoControl.IoControlCode) { case IOCTL_SAMPLE_DBGPRINT: Status = WdfRequestRetrieveInputBuffer(Request, 0, (PVOID*)&Buffer, &BufferSize); if (!NT_SUCCESS(Status)) { goto TreeSampleProcessOtherDeviceIoEnd; } // // Must be NULL-terminated // if (Buffer[BufferSize / sizeof(WCHAR) - 1] != L'\0') { Status = STATUS_INVALID_PARAMETER; goto TreeSampleProcessOtherDeviceIoEnd; } DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, "[TrEEMiniportSample] %ws\n", (PWSTR)Buffer); break; default: Status = STATUS_INVALID_DEVICE_REQUEST; } TreeSampleProcessOtherDeviceIoEnd: WdfRequestCompleteWithInformation(Request, Status, BytesWritten); }
NTSTATUS KrnlHlprClassifyDataCreateLocalCopy(_Outptr_ CLASSIFY_DATA** ppClassifyData, _In_ const FWPS_INCOMING_VALUES* pClassifyValues, _In_ const FWPS_INCOMING_METADATA_VALUES* pMetadata, _In_opt_ VOID* pPacket, _In_opt_ const VOID* pClassifyContext, _In_ const FWPS_FILTER* pFilter, _In_ const UINT64 flowContext, _In_ FWPS_CLASSIFY_OUT* pClassifyOut) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> KrnlHlprClassifyDataCreateLocalCopy()\n"); #endif /// DBG NT_ASSERT(ppClassifyData); NT_ASSERT(pClassifyValues); NT_ASSERT(pMetadata); NT_ASSERT(pFilter); NT_ASSERT(pClassifyOut); NTSTATUS status = STATUS_SUCCESS; HLPR_NEW(*ppClassifyData, CLASSIFY_DATA, WFPSAMPLER_SYSLIB_TAG); HLPR_BAIL_ON_ALLOC_FAILURE(*ppClassifyData, status); status = KrnlHlprClassifyDataAcquireLocalCopy(*ppClassifyData, pClassifyValues, pMetadata, pPacket, pClassifyContext, pFilter, flowContext, pClassifyOut); HLPR_BAIL_LABEL: #pragma warning(push) #pragma warning(disable: 6001) /// *ppClassifyData initialized with call to HLPR_NEW & KrnlHlprClassifyDataAcquireLocalCopy if(status != STATUS_SUCCESS && *ppClassifyData) KrnlHlprClassifyDataDestroyLocalCopy(ppClassifyData); #pragma warning(pop) #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> KrnlHlprClassifyDataCreateLocalCopy() [status: %#x]\n", status); #endif /// DBG return status; }
void RosKmAdapter::PatchDmaBuffer( ROSDMABUFINFO* pDmaBufInfo, CONST DXGK_ALLOCATIONLIST* pAllocationList, UINT allocationListSize, CONST D3DDDI_PATCHLOCATIONLIST* pPatchLocationList, UINT patchAllocationList) { PBYTE pDmaBuf = (PBYTE)pDmaBufInfo->m_pDmaBuffer; for (UINT i = 0; i < patchAllocationList; i++) { auto patch = &pPatchLocationList[i]; allocationListSize; NT_ASSERT(patch->AllocationIndex < allocationListSize); auto allocation = &pAllocationList[patch->AllocationIndex]; RosKmdDeviceAllocation * pRosKmdDeviceAllocation = (RosKmdDeviceAllocation *)allocation->hDeviceSpecificAllocation; if (allocation->SegmentId != 0) { DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, "Patch RosKmdDeviceAllocation %lx at %lx\n", pRosKmdDeviceAllocation, allocation->PhysicalAddress); DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, "Patch buffer offset %lx allocation offset %lx\n", patch->PatchOffset, patch->AllocationOffset); // Patch in dma buffer NT_ASSERT(allocation->SegmentId == ROSD_SEGMENT_VIDEO_MEMORY); if (pDmaBufInfo->m_DmaBufState.m_bSwCommandBuffer) { PHYSICAL_ADDRESS allocAddress; allocAddress.QuadPart = allocation->PhysicalAddress.QuadPart + (LONGLONG)patch->AllocationOffset; *((PHYSICAL_ADDRESS *)(pDmaBuf + patch->PatchOffset)) = allocAddress; } else { // Patch HW command buffer #if VC4 UINT physicalAddress = RosKmdGlobal::s_videoMemoryPhysicalAddress.LowPart + allocation->PhysicalAddress.LowPart + patch->AllocationOffset; switch (patch->SlotId) { case VC4_SLOT_RT_BINNING_CONFIG: pDmaBufInfo->m_RenderTargetPhysicalAddress = physicalAddress; break; case VC4_SLOT_TILE_ALLOCATION_MEMORY: *((UINT *)(pDmaBuf + patch->PatchOffset)) = m_tileAllocationMemoryPhysicalAddress + m_busAddressOffset; break; case VC4_SLOT_TILE_STATE_DATA_ARRAY: *((UINT *)(pDmaBuf + patch->PatchOffset)) = m_tileStateDataArrayPhysicalAddress + m_busAddressOffset; break; case VC4_SLOT_NV_SHADER_STATE: case VC4_SLOT_BRANCH: case VC4_SLOT_GL_SHADER_STATE: case VC4_SLOT_FS_UNIFORM_ADDRESS: case VC4_SLOT_VS_UNIFORM_ADDRESS: case VC4_SLOT_CS_UNIFORM_ADDRESS: // When PrePatch happens in DdiRender, DMA buffer physical // address is not available, so DMA buffer self-reference // patches are handled in SubmitCommand break; default: *((UINT *)(pDmaBuf + patch->PatchOffset)) = physicalAddress + m_busAddressOffset; } #endif } } } }
NTSTATUS PerformPendAuthorization(_Inout_ CLASSIFY_DATA** ppClassifyData, _Inout_ PEND_DATA** ppPendData, _Inout_ INJECTION_DATA** ppInjectionData) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> PerformPendAuthorization()\n"); #endif /// DBG NT_ASSERT(ppClassifyData); NT_ASSERT(ppPendData); NT_ASSERT(ppInjectionData); NT_ASSERT(*ppClassifyData); NT_ASSERT(*ppPendData); NTSTATUS status = STATUS_SUCCESS; NET_BUFFER_LIST* pNBL = (*ppPendData)->pNBL; UINT32 finalAction = (*ppPendData)->pPendAuthorizationData->finalAction; UINT32 delay = (*ppPendData)->pPendAuthorizationData->delay; BOOLEAN reInjected = FALSE; if(delay && KeGetCurrentIrql() < DISPATCH_LEVEL) KrnlHlprWorkItemSleep(delay); #pragma warning(push) #pragma warning(disable: 6001) /// *ppPendData initialized prior to call to this function /// Completes the Pend KrnlHlprPendDataDestroy(ppPendData); #pragma warning(pop) if(pNBL && finalAction == FWP_ACTION_PERMIT) { status = PrvCloneAuthorizedNBLAndInject(ppClassifyData, ppInjectionData); if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! PerformPendAuthorization : PrvCloneAuthorizedNBLAndInject() [status: %#x]\n", status); } else reInjected = TRUE; } #pragma warning(push) #pragma warning(disable: 6001) /// *ppClassifyData initialized prior to call to this function if(!reInjected) KrnlHlprClassifyDataDestroyLocalCopy(ppClassifyData); #pragma warning(pop) #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- PerformPendAuthorization() [status: %#x]\n", status); #endif /// DBG return status; };
NTSTATUS RosKmAdapter::BuildPagingBuffer( IN_PDXGKARG_BUILDPAGINGBUFFER pArgs) { NTSTATUS Status = STATUS_SUCCESS; PBYTE pDmaBufStart = (PBYTE)pArgs->pDmaBuffer; PBYTE pDmaBufPos = (PBYTE)pArgs->pDmaBuffer; // // hAllocation is NULL for operation on DMA buffer and pages mapped into aperture // // // If there is insufficient space left in DMA buffer, we should return // STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER. // switch (pArgs->Operation) { case DXGK_OPERATION_MAP_APERTURE_SEGMENT: { if (pArgs->MapApertureSegment.SegmentId == kApertureSegmentId) { size_t pageIndex = pArgs->MapApertureSegment.OffsetInPages; size_t pageCount = pArgs->MapApertureSegment.NumberOfPages; NT_ASSERT(pageIndex + pageCount <= kApertureSegmentPageCount); size_t mdlPageOffset = pArgs->MapApertureSegment.MdlOffset; PMDL pMdl = pArgs->MapApertureSegment.pMdl; for (UINT i = 0; i < pageCount; i++) { m_aperturePageTable[pageIndex + i] = MmGetMdlPfnArray(pMdl)[mdlPageOffset + i]; } } } break; case DXGK_OPERATION_UNMAP_APERTURE_SEGMENT: { if (pArgs->MapApertureSegment.SegmentId == kApertureSegmentId) { size_t pageIndex = pArgs->MapApertureSegment.OffsetInPages; size_t pageCount = pArgs->MapApertureSegment.NumberOfPages; NT_ASSERT(pageIndex + pageCount <= kApertureSegmentPageCount); while (pageCount--) { m_aperturePageTable[pageIndex++] = 0; } } } break; case DXGK_OPERATION_FILL: { RosKmdAllocation * pRosKmdAllocation = (RosKmdAllocation *)pArgs->Fill.hAllocation; pRosKmdAllocation; DbgPrintEx(DPFLTR_IHVVIDEO_ID, DPFLTR_TRACE_LEVEL, "Filling at %lx with %lx size %lx\n", pArgs->Fill.Destination.SegmentAddress, pArgs->Fill.FillPattern, pArgs->Fill.FillSize); if (pArgs->DmaSize < sizeof(DXGKARG_BUILDPAGINGBUFFER)) { return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER; } else { *((DXGKARG_BUILDPAGINGBUFFER *)pArgs->pDmaBuffer) = *pArgs; pDmaBufPos += sizeof(DXGKARG_BUILDPAGINGBUFFER); } } break; case DXGK_OPERATION_DISCARD_CONTENT: { // do nothing } break; case DXGK_OPERATION_TRANSFER: { if (pArgs->DmaSize < sizeof(DXGKARG_BUILDPAGINGBUFFER)) { return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER; } else { *((DXGKARG_BUILDPAGINGBUFFER *)pArgs->pDmaBuffer) = *pArgs; pDmaBufPos += sizeof(DXGKARG_BUILDPAGINGBUFFER); } } break; default: { NT_ASSERT(false); m_ErrorHit.m_UnSupportedPagingOp = 1; Status = STATUS_SUCCESS; } break; } // // Update pDmaBuffer to point past the last byte used. pArgs->pDmaBuffer = pDmaBufPos; // Record DMA buffer information only when it is newly used ROSDMABUFINFO * pDmaBufInfo = (ROSDMABUFINFO *)pArgs->pDmaBufferPrivateData; if (pDmaBufInfo && (pArgs->DmaSize == ROSD_PAGING_BUFFER_SIZE)) { pDmaBufInfo->m_DmaBufState.m_Value = 0; pDmaBufInfo->m_DmaBufState.m_bPaging = 1; pDmaBufInfo->m_pDmaBuffer = pDmaBufStart; pDmaBufInfo->m_DmaBufferSize = pArgs->DmaSize; } return Status; }
NTSTATUS PrvCloneAuthorizedNBLAndInject(_Inout_ CLASSIFY_DATA** ppClassifyData, _Inout_ INJECTION_DATA** ppInjectionData) { #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " ---> PrvCloneAuthorizedNBLAndInject()\n"); #endif /// DBG NT_ASSERT(ppClassifyData); NT_ASSERT(ppInjectionData); NT_ASSERT(*ppClassifyData); NT_ASSERT(*ppInjectionData); NTSTATUS status = STATUS_SUCCESS; FWPS_INCOMING_VALUES* pClassifyValues = (FWPS_INCOMING_VALUES*)(*ppClassifyData)->pClassifyValues; FWPS_INCOMING_METADATA_VALUES* pMetadata = (FWPS_INCOMING_METADATA_VALUES*)(*ppClassifyData)->pMetadataValues; UINT32 bytesRetreated = 0; COMPARTMENT_ID compartmentID = UNSPECIFIED_COMPARTMENT_ID; BOOLEAN isInbound = FALSE; NET_BUFFER_LIST* pNetBufferList = 0; PEND_AUTHORIZATION_COMPLETION_DATA* pCompletionData = 0; FWPS_TRANSPORT_SEND_PARAMS* pSendParams = 0; BYTE* pRemoteAddress = 0; #pragma warning(push) #pragma warning(disable: 6014) /// pCompletionData will be freed in completionFn using PendAuthorizationCompletionDataDestroy HLPR_NEW(pCompletionData, PEND_AUTHORIZATION_COMPLETION_DATA, WFPSAMPLER_CALLOUT_DRIVER_TAG); HLPR_BAIL_ON_ALLOC_FAILURE(pCompletionData, status); HLPR_NEW(pSendParams, FWPS_TRANSPORT_SEND_PARAMS, WFPSAMPLER_CALLOUT_DRIVER_TAG); HLPR_BAIL_ON_ALLOC_FAILURE(pSendParams, status); #pragma warning(pop) KeInitializeSpinLock(&(pCompletionData->spinLock)); pCompletionData->performedInline = FALSE; pCompletionData->pClassifyData = *ppClassifyData; pCompletionData->pInjectionData = *ppInjectionData; pCompletionData->pSendParams = pSendParams; /// Responsibility for freeing this memory has been transferred to the pCompletionData *ppClassifyData = 0; *ppInjectionData = 0; pSendParams = 0; if(pCompletionData->pInjectionData->direction == FWP_DIRECTION_INBOUND) isInbound = TRUE; if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata, FWPS_METADATA_FIELD_COMPARTMENT_ID)) compartmentID = (COMPARTMENT_ID)pMetadata->compartmentId; if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata, FWPS_METADATA_FIELD_IP_HEADER_SIZE)) bytesRetreated = pMetadata->ipHeaderSize; if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata, FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE)) bytesRetreated += pMetadata->transportHeaderSize; if(pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V4 || pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_RECV_ACCEPT_V6) { if(isInbound) /// NBL offset is at the start of the transport header ... { if(bytesRetreated) { /// so retreat (size of IP Header) to clone the whole NBL status = NdisRetreatNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket), bytesRetreated, 0, 0); if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! PrvCloneAuthorizedNBLAndInject: NdisRetreatNetBufferDataStart() [status: %#x]\n", status); HLPR_BAIL; } } } } else if(pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V4 || pClassifyValues->layerId == FWPS_LAYER_ALE_AUTH_CONNECT_V6) { /// NBL offset is at the Transport Header, and no IP Header is present yet bytesRetreated = 0; isInbound = FALSE; } else { status = STATUS_FWP_INCOMPATIBLE_LAYER; HLPR_BAIL; } status = FwpsAllocateCloneNetBufferList((NET_BUFFER_LIST*)(pCompletionData->pClassifyData->pPacket), g_pNDISPoolData->nblPoolHandle, g_pNDISPoolData->nbPoolHandle, 0, &pNetBufferList); if(bytesRetreated) { /// Advance the NBL offset so we are back at the expected position in the NET_BUFFER_LIST NdisAdvanceNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB((NET_BUFFER_LIST*)pCompletionData->pClassifyData->pPacket), bytesRetreated, FALSE, 0); } if(status != STATUS_SUCCESS) { DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_ERROR_LEVEL, " !!!! PrvCloneAuthorizedNBLAndInject : FwpsAllocateCloneNetBufferList() [status: %#x]\n", status); HLPR_BAIL; } if(isInbound) { FWP_VALUE* pInterfaceIndex = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues, &FWPM_CONDITION_INTERFACE_INDEX); FWP_VALUE* pSubInterfaceIndex = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues, &FWPM_CONDITION_SUB_INTERFACE_INDEX); IF_INDEX interfaceIndex = 0; IF_INDEX subInterfaceIndex = 0; if(pInterfaceIndex && pInterfaceIndex->type == FWP_UINT32) interfaceIndex = (IF_INDEX)pInterfaceIndex->uint32; if(pSubInterfaceIndex && pSubInterfaceIndex->type == FWP_UINT32) subInterfaceIndex = (IF_INDEX)pSubInterfaceIndex->uint32; status = FwpsInjectTransportReceiveAsync(pCompletionData->pInjectionData->injectionHandle, pCompletionData->pInjectionData->injectionContext, 0, 0, pCompletionData->pInjectionData->addressFamily, compartmentID, interfaceIndex, subInterfaceIndex, pNetBufferList, CompletePendAuthorization, pCompletionData); } else { UINT64 endpointHandle = 0; FWP_VALUE* pAddressValue = 0; if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata, FWPS_METADATA_FIELD_TRANSPORT_ENDPOINT_HANDLE)) endpointHandle = pMetadata->transportEndpointHandle; pAddressValue = KrnlHlprFwpValueGetFromFwpsIncomingValues(pClassifyValues, &FWPM_CONDITION_IP_REMOTE_ADDRESS); if(pAddressValue) { if(pCompletionData->pInjectionData->addressFamily == AF_INET) { UINT32 tempAddress = htonl(pAddressValue->uint32); #pragma warning(push) #pragma warning(disable: 6014) /// pRemoteAddress will be freed in completionFn using PendAuthorizationCompletionDataDestroy HLPR_NEW_ARRAY(pRemoteAddress, BYTE, IPV4_ADDRESS_SIZE, WFPSAMPLER_CALLOUT_DRIVER_TAG); HLPR_BAIL_ON_ALLOC_FAILURE(pRemoteAddress, status); #pragma warning(pop) RtlCopyMemory(pRemoteAddress, &tempAddress, IPV4_ADDRESS_SIZE); } else { #pragma warning(push) #pragma warning(disable: 6014) /// pRemoteAddress will be freed in completionFn using PendAuthorizationCompletionDataDestroy HLPR_NEW_ARRAY(pRemoteAddress, BYTE, IPV6_ADDRESS_SIZE, WFPSAMPLER_CALLOUT_DRIVER_TAG); HLPR_BAIL_ON_ALLOC_FAILURE(pRemoteAddress, status); #pragma warning(pop) RtlCopyMemory(pRemoteAddress, pAddressValue->byteArray16->byteArray16, IPV6_ADDRESS_SIZE); if(FWPS_IS_METADATA_FIELD_PRESENT(pMetadata, FWPS_METADATA_FIELD_REMOTE_SCOPE_ID)) pCompletionData->pSendParams->remoteScopeId = pMetadata->remoteScopeId; } pCompletionData->pSendParams->remoteAddress = pRemoteAddress; } pCompletionData->refCount = KrnlHlprNBLGetRequiredRefCount(pNetBufferList); status = FwpsInjectTransportSendAsync(pCompletionData->pInjectionData->injectionHandle, pCompletionData->pInjectionData->injectionContext, endpointHandle, 0, pCompletionData->pSendParams, pCompletionData->pInjectionData->addressFamily, compartmentID, pNetBufferList, CompletePendAuthorization, pCompletionData); } HLPR_BAIL_LABEL: if(status != STATUS_SUCCESS) { if(pNetBufferList) { FwpsFreeCloneNetBufferList(pNetBufferList, 0); pNetBufferList = 0; } if(pCompletionData) PendAuthorizationCompletionDataDestroy(&pCompletionData, TRUE); } #if DBG DbgPrintEx(DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, " <--- PrvCloneAuthorizedNBLAndInject() [status: %#x]\n", status); #endif /// DBG return status; }
NTSTATUS TdProtectNameCallback ( _In_ PTD_PROTECTNAME_INPUT pProtectName ) { NTSTATUS Status = STATUS_SUCCESS; if (!pProtectName) { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "ObCallbackTest: TdProtectNameCallback: name to protect/filter NULL pointer\n" ); } else { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: TdProtectNameCallback: entering name to protect/filter %ls\n", pProtectName->Name ); } KeAcquireGuardedMutex (&TdCallbacksMutex); // Need to copy out the name and then set the flag to filter // This will allow process creation to watch for the process to be created and get the PID // and then prevent any other process from opening up that PID to terminate memcpy(TdwProtectName, pProtectName->Name, sizeof(TdwProtectName)); DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: name copied %ls\n", TdwProtectName ); // Need to enable the OB callbacks // once the process is matched to a newly created process, the callbacks will protect the process if (bCallbacksInstalled == FALSE) { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: TdProtectNameCallback: installing callbacks\n" ); // Setup the Ob Registration calls CBOperationRegistrations[0].ObjectType = PsProcessType; CBOperationRegistrations[0].Operations |= OB_OPERATION_HANDLE_CREATE; CBOperationRegistrations[0].Operations |= OB_OPERATION_HANDLE_DUPLICATE; CBOperationRegistrations[0].PreOperation = CBTdPreOperationCallback; CBOperationRegistrations[0].PostOperation = CBTdPostOperationCallback; CBOperationRegistrations[1].ObjectType = PsThreadType; CBOperationRegistrations[1].Operations |= OB_OPERATION_HANDLE_CREATE; CBOperationRegistrations[1].Operations |= OB_OPERATION_HANDLE_DUPLICATE; CBOperationRegistrations[1].PreOperation = CBTdPreOperationCallback; CBOperationRegistrations[1].PostOperation = CBTdPostOperationCallback; RtlInitUnicodeString (&CBAltitude, L"1000"); CBObRegistration.Version = OB_FLT_REGISTRATION_VERSION; CBObRegistration.OperationRegistrationCount = 2; CBObRegistration.Altitude = CBAltitude; CBObRegistration.RegistrationContext = &CBCallbackRegistration; CBObRegistration.OperationRegistration = CBOperationRegistrations; Status = ObRegisterCallbacks ( &CBObRegistration, &pCBRegistrationHandle // save the registration handle to remove callbacks later ); if (!NT_SUCCESS (Status)) { DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "ObCallbackTest: installing OB callbacks failed status 0x%x\n", Status ); KeReleaseGuardedMutex (&TdCallbacksMutex); // Release the lock before exit goto Exit; } bCallbacksInstalled = TRUE; } KeReleaseGuardedMutex (&TdCallbacksMutex); DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: TdProtectNameCallback: name to protect/filter %ls\n", TdwProtectName ); Exit: DbgPrintEx ( DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "ObCallbackTest: TdProtectNameCallback: exiting status 0x%x\n", Status ); return Status; }