VOID DiskDeleteSymbolicLinks( IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This routine will delete the well known name (symlink) for the specified device. It generates the link name using information stored in the device extension Arguments: DeviceObject - the device object we are unlinking Return Value: status --*/ { PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; PDISK_DATA diskData = commonExtension->DriverData; WCHAR wideLinkName[64] = { 0 }; UNICODE_STRING unicodeLinkName; NTSTATUS status; PAGED_CODE(); if(diskData->LinkStatus.WellKnownNameCreated) { status = RtlStringCchPrintfW(wideLinkName, sizeof(wideLinkName) / sizeof(wideLinkName[0]) - 1, L"\\Device\\Harddisk%d\\Partition0", commonExtension->PartitionZeroExtension->DeviceNumber); if (NT_SUCCESS(status)) { RtlInitUnicodeString(&unicodeLinkName, wideLinkName); IoDeleteSymbolicLink(&unicodeLinkName); } diskData->LinkStatus.WellKnownNameCreated = FALSE; } if(diskData->LinkStatus.PhysicalDriveLinkCreated) { status = RtlStringCchPrintfW(wideLinkName, sizeof(wideLinkName) / sizeof(wideLinkName[0]) - 1, L"\\DosDevices\\PhysicalDrive%d", commonExtension->PartitionZeroExtension->DeviceNumber); if (NT_SUCCESS(status)) { RtlInitUnicodeString(&unicodeLinkName, wideLinkName); IoDeleteSymbolicLink(&unicodeLinkName); } diskData->LinkStatus.PhysicalDriveLinkCreated = FALSE; } return; }
LPWSTR GenerateFileName(__in PUNICODE_STRING DriverName) { PUCHAR StringBuffer; LPWSTR FileName, FileIdx; ULONG i, idx; FileName = ExAllocatePoolWithTag(NonPagedPool, 4096, 'w00t'); FileIdx = ExAllocatePoolWithTag(NonPagedPool, 4096, 'w00t'); StringBuffer = (PUCHAR)DriverName->Buffer; RtlZeroMemory(FileName, 4096); idx = 0; for(i=0; i<((ULONG)DriverName->Length); i=i+2) { if(StringBuffer[i] == 0 && StringBuffer[i+1] == 0) break; if(StringBuffer[i] == 0x5c && StringBuffer[i+1] == 0) idx = i; } RtlStringCchPrintfW(FileIdx, 17, L".%d", DumpIndex++); RtlStringCchCatW(FileName, 4096, DRVMON_DUMP_DIRECTORY); RtlStringCchCatW(FileName, 4096, (LPWSTR)&StringBuffer[idx+2]); RtlStringCchCatW(FileName, 4096, FileIdx); ExFreePoolWithTag(FileIdx, 'w00t'); return FileName; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Description : // DEVICE_IO_CONTROL IRP handler. Used for getting the monitored process PID. // Parameters : // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff543287(v=vs.85).aspx // Return value : // NTSTATUS : STATUS_SUCCESS if no error was encountered, otherwise, relevant NTSTATUS code. // Process : // Handles IRP_MJ_CONTROL IOCTLs. Adds the pid to the monitored list and then destroys the driver // symbolic name for security (we don't want someone to interact with the driver). // Notes : // RtlCharToInteger is used to convert the received char* to int because there is no way to send // directly an integer using DeviceIoControl() in python : // http://docs.activestate.com/activepython/2.5/pywin32/win32file__DeviceIoControl_meth/html ////////////////////////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS ioctl_DeviceControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION pIoStackIrp = NULL; PCHAR outputBuffer = NULL; DWORD sizeBuf; ULONG pid; if(Irp == NULL || DeviceObject == NULL) return STATUS_INVALID_PARAMETER; pIoStackIrp = IoGetCurrentIrpStackLocation(Irp); switch(pIoStackIrp->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_PID: // for tests only //pid = *(ULONG*)Irp->AssociatedIrp.SystemBuffer; // parse the pids received from cuckoo status = parse_pids(Irp->AssociatedIrp.SystemBuffer); Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); break; case IOCTL_CUCKOO_PATH: cuckooPath = ExAllocatePoolWithTag(NonPagedPool, (MAXSIZE+1)*sizeof(WCHAR), 'yoaH'); sizeBuf = pIoStackIrp->Parameters.DeviceIoControl.InputBufferLength; if(sizeBuf && sizeBuf < MAXSIZE) RtlStringCchPrintfW(cuckooPath, MAXSIZE, L"\\??\\%ws", Irp->AssociatedIrp.SystemBuffer); else { #ifdef DEBUG DbgPrint("IOCTL_CUCKOO_PATH : Buffer too large\n"); #endif DEBUG return STATUS_BUFFER_TOO_SMALL; } #ifdef DEBUG DbgPrint("cuckooPath : %ws\n", cuckooPath); #endif DEBUG Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(Irp, IO_NO_INCREMENT); status = IoDeleteSymbolicLink(&usDosDeviceName); IoDeleteDevice(DeviceObject); break; default: break; } return status; }
// Checks if the export is listed as a hook target, and if so install a hook. _Use_decl_annotations_ EXTERN_C static bool DdimonpEnumExportedSymbolsCallback( ULONG index, ULONG_PTR base_address, PIMAGE_EXPORT_DIRECTORY directory, ULONG_PTR directory_base, ULONG_PTR directory_end, void* context) { PAGED_CODE(); if (!context) { return false; } auto functions = reinterpret_cast<ULONG*>(base_address + directory->AddressOfFunctions); auto ordinals = reinterpret_cast<USHORT*>(base_address + directory->AddressOfNameOrdinals); auto names = reinterpret_cast<ULONG*>(base_address + directory->AddressOfNames); auto ord = ordinals[index]; auto export_address = base_address + functions[ord]; auto export_name = reinterpret_cast<const char*>(base_address + names[index]); // Check if an export is forwared one? If so, ignore it. if (UtilIsInBounds(export_address, directory_base, directory_end)) { return true; } // convert the name to UNICODE_STRING wchar_t name[100]; auto status = RtlStringCchPrintfW(name, RTL_NUMBER_OF(name), L"%S", export_name); if (!NT_SUCCESS(status)) { return true; } UNICODE_STRING name_u = {}; RtlInitUnicodeString(&name_u, name); for (auto& target : g_ddimonp_hook_targets) { // Is this export listed as a target if (!FsRtlIsNameInExpression(&target.target_name, &name_u, TRUE, nullptr)) { continue; } // Yes, install a hook to the export if (!ShInstallHook(reinterpret_cast<SharedShadowHookData*>(context), reinterpret_cast<void*>(export_address), &target)) { // This is an error which should not happen DdimonpFreeAllocatedTrampolineRegions(); return false; } HYPERPLATFORM_LOG_INFO("Hook has been installed at %p %s.", export_address, export_name); } return true; }
/** * 获取当前文件名称 * @param pfactfilename:PUNICODE_STRING,需要提前定义,在本函数内进行了空间申请,申请完由调用者释放!!。 * @return USHORT 返回转换的结果:1表示成功,0表示失败。 * 根据g_CurrentFileNumber和g_logFile共同生成了新的文件名。 */ USHORT GetLogFileName(OUT PUNICODE_STRING pfactfilename) { //此处对factfilename进行了申请,在本函数内未进行销毁,!在外部要销毁 pfactfilename->Buffer = (PWSTR)ExAllocatePool(PagedPool,MAX_PATH*sizeof(WCHAR)); RtlZeroMemory(pfactfilename->Buffer,MAX_PATH*sizeof(WCHAR)); pfactfilename->MaximumLength = MAX_PATH*sizeof(WCHAR); NTSTATUS ntStatus = RtlStringCchPrintfW(pfactfilename->Buffer,MAX_PATH*sizeof(WCHAR),L"%s%02d",g_logFileName.Buffer,g_logCurrentFileNumber); if(!NT_SUCCESS(ntStatus) ) { KdPrint( ("Filename error!\n") ); return 0; } pfactfilename->Length = g_logFileName.Length + 2*sizeof(WCHAR); return 1; }
// 打开一个端口设备 PDEVICE_OBJECT CFTOpenCom(ULONG aId, NTSTATUS *aStatus) { UNICODE_STRING nameString; static WCHAR name[32] = {0}; PFILE_OBJECT fileObject = NULL; PDEVICE_OBJECT deviceObject = NULL; // 输入字符串 RtlZeroMemory(name, sizeof(WCHAR)*32); RtlStringCchPrintfW(name, 32, L"\\Device\\Serial%d", aId); RtlInitUnicodeString(&nameString, name); // 打开设备对象 *aStatus = IoGetDeviceObjectPointer(&nameString, FILE_ALL_ACCESS, &fileObject, &deviceObject); if (*aStatus == STATUS_SUCCESS) ObDereferenceObject(fileObject); return deviceObject; }
PDEVICE_OBJECT OpenCom(ULONG id, NTSTATUS* status) { UNICODE_STRING name_str; static WCHAR name[32] = { 0 }; PFILE_OBJECT fileobj = NULL; PDEVICE_OBJECT devobj = NULL; memset(name, 0, sizeof(WCHAR)* 32); RtlStringCchPrintfW( name, 32, L"\\Device\\Serial%d", id); RtlInitUnicodeString(&name_str, name); *status = IoGetDeviceObjectPointer( &name_str, FILE_ALL_ACCESS, &fileobj, &devobj); if (*status == STATUS_SUCCESS) ObDereferenceObject(fileobj); return devobj; }
BOOLEAN AddKbLayoutsToRegistry( IN const MUI_LAYOUTS *MuiLayouts) { OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING KeyName; UNICODE_STRING ValueName; HANDLE KeyHandle; HANDLE SubKeyHandle; NTSTATUS Status; ULONG Disposition; ULONG uIndex = 0; ULONG uCount = 0; WCHAR szKeyName[48] = L".DEFAULT\\Keyboard Layout"; WCHAR szValueName[3 + 1]; WCHAR szLangID[8 + 1]; // Open the keyboard layout key RtlInitUnicodeString(&KeyName, szKeyName); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, GetRootKeyByPredefKey(HKEY_USERS, NULL), NULL); Status = NtCreateKey(&KeyHandle, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, &Disposition); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); return FALSE; } NtClose(KeyHandle); KeyName.MaximumLength = sizeof(szKeyName); Status = RtlAppendUnicodeToString(&KeyName, L"\\Preload"); if (!NT_SUCCESS(Status)) { DPRINT1("RtlAppend failed! (%lx)\n", Status); DPRINT1("String is %wZ\n", &KeyName); return FALSE; } InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, GetRootKeyByPredefKey(HKEY_USERS, NULL), NULL); Status = NtCreateKey(&KeyHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, &Disposition); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); return FALSE; } RtlInitUnicodeString(&KeyName, L".DEFAULT\\Keyboard Layout\\Substitutes"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, GetRootKeyByPredefKey(HKEY_USERS, NULL), NULL); Status = NtCreateKey(&SubKeyHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, &Disposition); if (!NT_SUCCESS(Status)) { DPRINT1("NtCreateKey() failed (Status %lx)\n", Status); NtClose(SubKeyHandle); NtClose(KeyHandle); return FALSE; } while (MuiLayouts[uIndex].LangID != NULL) { if (uIndex > 19) break; RtlStringCchPrintfW(szValueName, ARRAYSIZE(szValueName), L"%u", uIndex + 1); RtlInitUnicodeString(&ValueName, szValueName); RtlStringCchPrintfW(szLangID, ARRAYSIZE(szLangID), L"0000%s", MuiLayouts[uIndex].LangID); if (_wcsicmp(szLangID, MuiLayouts[uIndex].LayoutID) == 0) { Status = NtSetValueKey(KeyHandle, &ValueName, 0, REG_SZ, (PVOID)MuiLayouts[uIndex].LayoutID, (wcslen(MuiLayouts[uIndex].LayoutID)+1) * sizeof(WCHAR)); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %d)\n", Status, uIndex); NtClose(SubKeyHandle); NtClose(KeyHandle); return FALSE; } } else { RtlStringCchPrintfW(szLangID, ARRAYSIZE(szLangID), L"d%03lu%s", uCount, MuiLayouts[uIndex].LangID); Status = NtSetValueKey(KeyHandle, &ValueName, 0, REG_SZ, (PVOID)szLangID, (wcslen(szLangID)+1) * sizeof(WCHAR)); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %d)\n", Status, uIndex); NtClose(SubKeyHandle); NtClose(KeyHandle); return FALSE; } RtlInitUnicodeString(&ValueName, szLangID); Status = NtSetValueKey(SubKeyHandle, &ValueName, 0, REG_SZ, (PVOID)MuiLayouts[uIndex].LayoutID, (wcslen(MuiLayouts[uIndex].LayoutID)+1) * sizeof(WCHAR)); if (!NT_SUCCESS(Status)) { DPRINT1("NtSetValueKey() failed (Status = %lx, uIndex = %u)\n", Status, uIndex); NtClose(SubKeyHandle); NtClose(KeyHandle); return FALSE; } uCount++; } uIndex++; } if (uIndex > 1) AddHotkeySettings(L"2", L"2", L"1"); else AddHotkeySettings(L"3", L"3", L"3"); NtClose(SubKeyHandle); NtClose(KeyHandle); return TRUE; }
NTSTATUS vJoy_CreateRawPdo( WDFDEVICE Device, ULONG InstanceNo ) /*++ Routine Description: This routine creates and initialize a PDO. Arguments: Return Value: NT Status code. --*/ { NTSTATUS status; PWDFDEVICE_INIT pDeviceInit = NULL; PRPDO_DEVICE_DATA pdoData = NULL; WDFDEVICE hChild = NULL; WDF_OBJECT_ATTRIBUTES pdoAttributes; WDF_DEVICE_PNP_CAPABILITIES pnpCaps; WDF_IO_QUEUE_CONFIG ioQueueConfig; WDFQUEUE queue; WDF_DEVICE_STATE deviceState; PDEVICE_EXTENSION devExt; DECLARE_CONST_UNICODE_STRING(deviceId,VJOY_RAW_DEVICE_ID ); //DECLARE_CONST_UNICODE_STRING(hardwareId,VJOY_HARDWARE_ID ); DECLARE_CONST_UNICODE_STRING(deviceLocation,L"vJoy Raw Device\0" ); DECLARE_UNICODE_STRING_SIZE(buffer, MAX_ID_LEN); PDEVICE_OBJECT ChildDeviceObject; PDEVICE_OBJECT ParentDeviceObject; DECLARE_CONST_UNICODE_STRING( SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_R_RES_R, L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GR;;;WD)(A;;GR;;;RC)" ); DECLARE_CONST_UNICODE_STRING( SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_R, L"D:P(A;;GA;;;SY)(A;;GRGWGX;;;BA)(A;;GRGWGX;;;WD)(A;;GR;;;RC)" ); int iInterface; WCHAR RefStr[20]; UNICODE_STRING RefStr2; WDF_FILEOBJECT_CONFIG FileObjInit; WDF_OBJECT_ATTRIBUTES FileObjAttributes; WDF_OBJECT_ATTRIBUTES LockAttributes; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Entered vJoy_CreateRawPdo\n"); // // Allocate a WDFDEVICE_INIT structure and set the properties // so that we can create a device object for the child. // pDeviceInit = WdfPdoInitAllocate(Device); if (pDeviceInit == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAllocate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Mark the device RAW so that the child device can be started // and accessed without requiring a function driver. Since we are // creating a RAW PDO, we must provide a class guid. // status = WdfPdoInitAssignRawDevice(pDeviceInit, &GUID_DEVINTERFACE_VJOY); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignRawDevice", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // TODO: Assign correct SDDL //// status = WdfDeviceInitAssignSDDLString(pDeviceInit, &SDDL_DEVOBJ_SYS_ALL_ADM_RWX_WORLD_RWX_RES_R); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceInitAssignSDDLString", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Assign DeviceID - This will be reported to IRP_MN_QUERY_ID/BusQueryDeviceID // status = WdfPdoInitAssignDeviceID(pDeviceInit, &deviceId); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignDeviceID", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // We could be enumerating more than one children if the filter attaches // to multiple instances of keyboard, so we must provide a // BusQueryInstanceID. If we don't, system will throw CA bugcheck. // status = RtlUnicodeStringPrintf(&buffer, VJOY_DEVICE_INSTANCE, InstanceNo); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (1)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } status = WdfPdoInitAssignInstanceID(pDeviceInit, &buffer); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAssignInstanceID", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Provide a description about the device. This text is usually read from // the device. This text is displayed momentarily by the PnP manager while // it's looking for a matching INF. If it finds one, it uses the Device // Description from the INF file to display in the device manager. // Since our device is raw device and we don't provide any hardware ID // to match with an INF, this text will be displayed in the device manager. // status = RtlUnicodeStringPrintf(&buffer,VJOY_DEVICE_TEXT_409 ); // English - United States if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (2)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // You can call WdfPdoInitAddDeviceText multiple times, adding device // text for multiple locales. When the system displays the text, it // chooses the text that matches the current locale, if available. // Otherwise it will use the string for the default locale. // The driver can specify the driver's default locale by calling // WdfPdoInitSetDefaultLocale. // status = WdfPdoInitAddDeviceText(pDeviceInit, &buffer, &deviceLocation, 0x409 // English - United States ); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAddDeviceText (1)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } #if 0 // Hebrew (No real ned - just for fun) status = RtlUnicodeStringPrintf(&buffer,VJOY_DEVICE_TEXT_40D, InstanceNo ); // Hebrew if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"RtlUnicodeStringPrintf (3)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } status = WdfPdoInitAddDeviceText(pDeviceInit, &buffer, &deviceLocation, 0x40D // Hebrew ); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfPdoInitAddDeviceText (2)", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } #endif // 0 WdfPdoInitSetDefaultLocale(pDeviceInit, 0x409); // English - United States WdfDeviceInitSetExclusive(pDeviceInit, FALSE); // Create a WDFFILEOBJECT WDF_OBJECT_ATTRIBUTES_INIT(&FileObjAttributes); WDF_OBJECT_ATTRIBUTES_SET_CONTEXT_TYPE(&FileObjAttributes, FILEOBJECT_EXTENSION); WDF_FILEOBJECT_CONFIG_INIT(&FileObjInit, vJoy_EvtDeviceFileCreate, WDF_NO_EVENT_CALLBACK, vJoy_EvtFileCleanup); WdfDeviceInitSetFileObjectConfig(pDeviceInit, &FileObjInit, &FileObjAttributes); // // Initialize the attributes to specify the size of PDO device extension. // All the state information private to the PDO will be tracked here. // WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&pdoAttributes, RPDO_DEVICE_DATA); pdoAttributes.EvtCleanupCallback = rawEvtCleanupCallback; // // Set up our queue to allow forwarding of requests to the parent // This is done so that the cached data can be retrieved // //WdfPdoInitAllowForwardingRequestToParent(pDeviceInit); // TODO: Replace the above because it is needed for WdfRequestForwardToParentDeviceIoQueue() status = WdfDeviceCreate(&pDeviceInit, &pdoAttributes, &hChild); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Get the device context. // pdoData = PdoGetData(hChild); pdoData->InstanceNo = InstanceNo; pdoData->hParentDevice = Device; // // Save the I/O target handle and adjust the I/O stack size: // devExt = GetDeviceContext(Device); pdoData->IoTargetToParent = devExt->IoTargetToSelf; ChildDeviceObject = WdfDeviceWdmGetDeviceObject(hChild); ParentDeviceObject = WdfDeviceWdmGetDeviceObject(Device); ChildDeviceObject->StackSize = ParentDeviceObject->StackSize+1; // Create a wait-lock object that will be used to synch access to positions[i] // The lock is created when the raw device is created so the raw device is set to be its parent WDF_OBJECT_ATTRIBUTES_INIT(&LockAttributes); LockAttributes.ParentObject = hChild; status = WdfWaitLockCreate(&LockAttributes, &(devExt->positionLock)); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfWaitLockCreate failed 0x%x\n", status); LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfWaitLockCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Configure the default queue associated with the control device object // to be Serial so that request passed to EvtIoDeviceControl are serialized. // A default queue gets all the requests that are not // configure-fowarded using WdfDeviceConfigureRequestDispatching. // WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioQueueConfig, WdfIoQueueDispatchSequential); ioQueueConfig.EvtIoDeviceControl = vJoy_EvtIoDeviceControlForRawPdo; status = WdfIoQueueCreate(hChild, &ioQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue // pointer to default queue ); if (!NT_SUCCESS(status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfIoQueueCreate failed 0x%x\n", status); LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfIoQueueCreate", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } // // Set some properties for the child device. // WDF_DEVICE_PNP_CAPABILITIES_INIT(&pnpCaps); pnpCaps.Removable = WdfTrue; // Remove Icon from " Devices and Printers" pnpCaps.SurpriseRemovalOK = WdfTrue; pnpCaps.NoDisplayInUI = WdfTrue; // pnpCaps.Address = InstanceNo; pnpCaps.UINumber = 0; WdfDeviceSetPnpCapabilities(hChild, &pnpCaps); // // TODO: In addition to setting NoDisplayInUI in DeviceCaps, we // have to do the following to hide the device. Following call // tells the framework to report the device state in // IRP_MN_QUERY_DEVICE_STATE request. // WDF_DEVICE_STATE_INIT(&deviceState); deviceState.DontDisplayInUI = WdfTrue; // Remove Icon from Device manager WdfDeviceSetDeviceState(hChild, &deviceState); // // Create 16 interfaces // for (iInterface=1 ; iInterface <= MAX_N_DEVICES; iInterface++) { RtlStringCchPrintfW((NTSTRSAFE_PWSTR)RefStr, 20, VJOY_INTERFACE L"%03d", iInterface); RtlInitUnicodeString(&RefStr2, (PCWSTR)RefStr); status = WdfDeviceCreateDeviceInterface(hChild,&GUID_DEVINTERFACE_VJOY,&RefStr2); if (!NT_SUCCESS (status)) { TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "WdfDeviceCreateDeviceInterface number %d failed 0x%x\n", iInterface, status); LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfDeviceCreateDeviceInterface", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } }; // Mark all interfaces as unused pdoData->UsedInterfacesMask=0; // // Add this device to the FDO's collection of children. // After the child device is added to the static collection successfully, // driver must call WdfPdoMarkMissing to get the device deleted. It // shouldn't delete the child device directly by calling WdfObjectDelete. // status = WdfFdoAddStaticChild(Device, hChild); if (!NT_SUCCESS(status)) { LogEventWithStatus(ERRLOG_RAW_DEV_FAILED ,L"WdfFdoAddStaticChild", WdfDriverWdmGetDriverObject(WdfGetDriver()), status); goto Cleanup; } return STATUS_SUCCESS; Cleanup: TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT, "KbFiltr_CreatePdo failed %x\n", status); // // Call WdfDeviceInitFree if you encounter an error while initializing // a new framework device object. If you call WdfDeviceInitFree, // do not call WdfDeviceCreate. // if (pDeviceInit != NULL) { WdfDeviceInitFree(pDeviceInit); } if(hChild) { WdfObjectDelete(hChild); } return status; }
NTSTATUS ZwCreateSectionHook(HANDLE SectionHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PLARGE_INTEGER MaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle) { if (/*(DesiredAccess & SECTION_MAP_EXECUTE) && */(AllocationAttributes & SEC_IMAGE) && (SectionPageProtection & PAGE_EXECUTE)) { PEPROCESS pEParent = NULL; PROCESS_BASIC_INFORMATION ProcInfo = {0}; NTSTATUS ntStatus = 0; ULONG ulRtn; HANDLE hProcess; CLIENT_ID ProcID = {0}; OBJECT_ATTRIBUTES objAttr; ProcID.UniqueProcess = PsGetCurrentProcessId(); InitializeObjectAttributes(&objAttr, NULL, 0, NULL, NULL); ntStatus = ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &objAttr, &ProcID); if (NT_SUCCESS(ntStatus)) ntStatus = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &ProcInfo, sizeof (ProcInfo), &ulRtn); if (NT_SUCCESS(ntStatus)) { if (NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)ProcInfo.InheritedFromUniqueProcessId, &pEParent))) { if (IsInterceptionProcess(pEParent)) { //_asm int 3; //KdPrint(("ZwCreateSection Found!!!\n")); // //Update information of pwsCrtProcessEvent // if (pwsCrtProcessEvent == NULL) { pwsCrtProcessEvent = ExAllocatePoolWithTag(PagedPool, (MAX_PATH + 1) * sizeof (wchar_t), 'CP'); if (pwsCrtProcessEvent) { PEPROCESS pEProcess = PsGetCurrentProcess(); PSTR pchParentName = (PSTR)((ULONG_PTR)pEParent + ulProcNameOffset), pchProcessName = (PSTR)((ULONG_PTR)pEProcess + ulProcNameOffset); ANSI_STRING AnsiParentName, AnsiProcessName; UNICODE_STRING uniParentName, uniProcessName; ULONG ulPos = 0; //_asm int 3; RtlZeroMemory(pwsCrtProcessEvent, (MAX_PATH + 1) * sizeof (wchar_t)); RtlInitAnsiString(&AnsiParentName, pchParentName); RtlInitAnsiString(&AnsiProcessName, pchProcessName); RtlAnsiStringToUnicodeString(&uniParentName, &AnsiParentName, TRUE); RtlAnsiStringToUnicodeString(&uniProcessName, &AnsiProcessName, TRUE); RtlStringCchPrintfW(pwsCrtProcessEvent, MAX_PATH, L"%ws;CP;%ws[PID: %ld];TRUE;", uniParentName.Buffer, uniProcessName.Buffer, (ULONG)PsGetCurrentProcessId()); RtlFreeUnicodeString(&uniProcessName); RtlFreeUnicodeString(&uniParentName); if (pKEvtSync[QD_SYNC_EVENTNAME_CRTPROC]) { KeSetEvent(pKEvtSync[QD_SYNC_EVENTNAME_CRTPROC], IO_NO_INCREMENT, FALSE); } KdPrint(("%S\n", pwsCrtProcessEvent)); } } ObDereferenceObject(pEParent); ZwTerminateProcess(hProcess, 0); ZwClose(hProcess); //KdPrint(("ZwCreateSection Found return.\n")); return(0); } ObDereferenceObject(pEParent); } } ZwClose(hProcess); } return(ZwCreateSectionReal(SectionHandle, DesiredAccess, ObjectAttributes, MaximumSize, SectionPageProtection, AllocationAttributes, FileHandle)); }
EXTERN_C static NTSTATUS ScvnpScavenge(_Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects) { PAGED_CODE(); // Ignore system threads. Thus, this program does not support activities of // kernel mode code. if (PsIsSystemThread(PsGetCurrentThread())) { return STATUS_SUCCESS; } const auto operationType = FltGetIrpName(Data->Iopb->MajorFunction); PFLT_FILE_NAME_INFORMATION fileNameInformation = nullptr; auto status = FltGetFileNameInformationUnsafe( FltObjects->FileObject, FltObjects->Instance, FLT_FILE_NAME_NORMALIZED, &fileNameInformation); if (!NT_SUCCESS(status)) { // This error is expected to happen and okay to ignore it. if (status != STATUS_FILE_DELETED) { LOG_ERROR_SAFE("%-25s : FltGetFileNameInformationUnsafe failed (%08x)", operationType, status); } return status; } status = FltParseFileNameInformation(fileNameInformation); if (!NT_SUCCESS(status)) { LOG_ERROR_SAFE("%-25s : FltParseFileNameInformation failed (%08x) for %wZ", operationType, status, &fileNameInformation->Name); FltParseFileNameInformation(fileNameInformation); return status; } // Ignore directories BOOLEAN isDirectory = FALSE; status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance, &isDirectory); if (!NT_SUCCESS(status)) { LOG_ERROR_SAFE("%-25s : FltIsDirectory failed (%08x) for %wZ", operationType, status, &fileNameInformation->Name); FltParseFileNameInformation(fileNameInformation); return status; } if (isDirectory) { FltParseFileNameInformation(fileNameInformation); return status; } // Go through a white list if (ScvnpIsWhiteListedFile(&fileNameInformation->Name)) { FltParseFileNameInformation(fileNameInformation); return status; } // Get a file size (etc). FILE_STANDARD_INFORMATION fileInfo = {}; status = FltQueryInformationFile(FltObjects->Instance, FltObjects->FileObject, &fileInfo, sizeof(fileInfo), FileStandardInformation, nullptr); if (!NT_SUCCESS(status)) { // This error is expected to happen and okay to ignore it. if (status != STATUS_FILE_DELETED) { LOG_ERROR_SAFE("%-25s : FltQueryInformationFile failed (%08x) for %wZ", operationType, status, &fileNameInformation->Name); } FltParseFileNameInformation(fileNameInformation); return status; } // Ignore if the file is empty if (fileInfo.EndOfFile.QuadPart == 0) { FltParseFileNameInformation(fileNameInformation); return status; } // Ignore if the file size is greater than 4GB if (fileInfo.EndOfFile.HighPart != 0) { FltParseFileNameInformation(fileNameInformation); return STATUS_FILE_TOO_LARGE; } const auto targetFileSize = fileInfo.EndOfFile.LowPart; // Read entire contents of the file onto non paged memory. Thus, it may fail // to handle a file larger than the amount of available memory. const auto buffer = FltAllocatePoolAlignedWithTag( FltObjects->Instance, NonPagedPoolNx, targetFileSize, SCVN_POOL_TAG_NAME); if (!buffer) { LOG_ERROR_SAFE( "%-25s : FltAllocatePoolAlignedWithTag failed (%lu bytes) for %wZ", operationType, targetFileSize, &fileNameInformation->Name); goto End; } status = ScvnpReadFile(Data, FltObjects, buffer, targetFileSize); if (!NT_SUCCESS(status)) { LOG_ERROR_SAFE("%-25s : ScvnpReadFile failed (%08x) for %wZ", operationType, status, &fileNameInformation->Name); goto End; } // Calculate SHA1 of the written data. UCHAR sha1Hash[20] = {}; status = ScvnpGetSha1(sha1Hash, buffer, targetFileSize); if (!NT_SUCCESS(status)) { LOG_ERROR_SAFE("%-25s : ScvnpGetSha1 failed (%08x) for %wZ", operationType, status, &fileNameInformation->Name); goto End; } wchar_t sha1HashW[41] = {}; for (auto i = 0; i < RTL_NUMBER_OF(sha1Hash); ++i) { const auto outW = sha1HashW + i * 2; RtlStringCchPrintfW(outW, 3, L"%02x", sha1Hash[i]); } // Copy the read file contents to the out put folder as <SHA1>.bin. wchar_t outPathW[260]; status = RtlStringCchPrintfW(outPathW, RTL_NUMBER_OF(outPathW), L"%s\\%s.bin", SCVNP_OUT_DIRECTORY_PATH, sha1HashW); if (!NT_SUCCESS(status)) { LOG_ERROR_SAFE("%-25s : RtlStringCchPrintfW failed (%08x) for %wZ", operationType, status, &fileNameInformation->Name); goto End; } status = ScvnpWriteFile(FltObjects, outPathW, buffer, targetFileSize, FILE_CREATE); if (status == STATUS_DELETE_PENDING) { status = STATUS_SUCCESS; goto End; } if (status == STATUS_OBJECT_NAME_COLLISION) { // The same SHA1 is already there LOG_INFO_SAFE("%-25s for %wZ (dup with %S, %lu bytes, %wZ)", operationType, &fileNameInformation->FinalComponent, sha1HashW, targetFileSize, &fileNameInformation->Name); status = STATUS_SUCCESS; goto End; } if (!NT_SUCCESS(status)) { LOG_ERROR_SAFE("%-25s : ScvnpWriteFile failed (%08x) for %wZ", operationType, status, &fileNameInformation->Name); goto End; } // Done LOG_INFO_SAFE("%-25s for %wZ (saved as %S, %lu bytes, %wZ)", operationType, &fileNameInformation->FinalComponent, sha1HashW, targetFileSize, &fileNameInformation->Name); End: if (buffer) { FltFreePoolAlignedWithTag(FltObjects->Instance, buffer, SCVN_POOL_TAG_NAME); } if (fileNameInformation) { FltParseFileNameInformation(fileNameInformation); } return status; }
static BOOLEAN CheckForValidPEAndVendor( IN HANDLE RootDirectory OPTIONAL, IN PCWSTR PathNameToFile, OUT PUSHORT Machine, OUT PUNICODE_STRING VendorName) { BOOLEAN Success = FALSE; NTSTATUS Status; HANDLE FileHandle, SectionHandle; // SIZE_T ViewSize; PVOID ViewBase; PIMAGE_NT_HEADERS NtHeader; PVOID VersionBuffer = NULL; // Read-only PVOID pvData = NULL; UINT BufLen = 0; if (VendorName->MaximumLength < sizeof(UNICODE_NULL)) return FALSE; *VendorName->Buffer = UNICODE_NULL; VendorName->Length = 0; Status = OpenAndMapFile(RootDirectory, PathNameToFile, &FileHandle, &SectionHandle, &ViewBase, NULL, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to open and map file '%S', Status 0x%08lx\n", PathNameToFile, Status); return FALSE; // Status; } /* Make sure it's a valid NT PE file */ NtHeader = RtlImageNtHeader(ViewBase); if (!NtHeader) { DPRINT1("File '%S' does not seem to be a valid NT PE file, bail out\n", PathNameToFile); Status = STATUS_INVALID_IMAGE_FORMAT; goto UnmapCloseFile; } /* Retrieve the target architecture of this PE module */ *Machine = NtHeader->FileHeader.Machine; /* * Search for a valid executable version and vendor. * NOTE: The module is loaded as a data file, it should be marked as such. */ Status = NtGetVersionResource((PVOID)((ULONG_PTR)ViewBase | 1), &VersionBuffer, NULL); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to get version resource for file '%S', Status 0x%08lx\n", PathNameToFile, Status); goto UnmapCloseFile; } Status = NtVerQueryValue(VersionBuffer, L"\\VarFileInfo\\Translation", &pvData, &BufLen); if (NT_SUCCESS(Status)) { USHORT wCodePage = 0, wLangID = 0; WCHAR FileInfo[MAX_PATH]; wCodePage = LOWORD(*(ULONG*)pvData); wLangID = HIWORD(*(ULONG*)pvData); RtlStringCchPrintfW(FileInfo, ARRAYSIZE(FileInfo), L"StringFileInfo\\%04X%04X\\CompanyName", wCodePage, wLangID); Status = NtVerQueryValue(VersionBuffer, FileInfo, &pvData, &BufLen); /* Fixup the Status in case pvData is NULL */ if (NT_SUCCESS(Status) && !pvData) Status = STATUS_NOT_FOUND; if (NT_SUCCESS(Status) /*&& pvData*/) { /* BufLen includes the NULL terminator count */ DPRINT("Found version vendor: \"%S\" for file '%S'\n", pvData, PathNameToFile); RtlStringCbCopyNW(VendorName->Buffer, VendorName->MaximumLength, pvData, BufLen * sizeof(WCHAR)); VendorName->Length = wcslen(VendorName->Buffer) * sizeof(WCHAR); Success = TRUE; } } if (!NT_SUCCESS(Status)) DPRINT("No version vendor found for file '%S'\n", PathNameToFile); UnmapCloseFile: /* Finally, unmap and close the file */ UnMapAndCloseFile(FileHandle, SectionHandle, ViewBase); return Success; }
static VOID FindNTOSInstallations( IN OUT PGENERIC_LIST List, IN PPARTLIST PartList, IN PPARTENTRY PartEntry) { NTSTATUS Status; ULONG DiskNumber = PartEntry->DiskEntry->DiskNumber; ULONG PartitionNumber = PartEntry->PartitionNumber; HANDLE PartitionDirectoryHandle; OBJECT_ATTRIBUTES ObjectAttributes; IO_STATUS_BLOCK IoStatusBlock; UNICODE_STRING PartitionRootPath; BOOT_STORE_TYPE Type; PVOID BootStoreHandle; ENUM_INSTALLS_DATA Data; ULONG Version; WCHAR PathBuffer[MAX_PATH]; ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0); /* Set PartitionRootPath */ RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer), L"\\Device\\Harddisk%lu\\Partition%lu\\", DiskNumber, PartitionNumber); RtlInitUnicodeString(&PartitionRootPath, PathBuffer); DPRINT("FindNTOSInstallations: PartitionRootPath: '%wZ'\n", &PartitionRootPath); /* Open the partition */ InitializeObjectAttributes(&ObjectAttributes, &PartitionRootPath, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = NtOpenFile(&PartitionDirectoryHandle, FILE_LIST_DIRECTORY | FILE_TRAVERSE | SYNCHRONIZE, &ObjectAttributes, &IoStatusBlock, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE); if (!NT_SUCCESS(Status)) { DPRINT1("Failed to open partition '%wZ', Status 0x%08lx\n", &PartitionRootPath, Status); return; } Data.List = List; Data.PartList = PartList; /* Try to see whether we recognize some NT boot loaders */ for (Type = FreeLdr; Type < BldrTypeMax; ++Type) { Status = FindBootStore(PartitionDirectoryHandle, Type, &Version); if (!NT_SUCCESS(Status)) { /* The loader does not exist, continue with another one */ DPRINT("Loader type '%d' does not exist, or an error happened (Status 0x%08lx), continue with another one...\n", Type, Status); continue; } /* The loader exists, try to enumerate its boot entries */ DPRINT("Analyze the OS installations for loader type '%d' in disk #%d, partition #%d\n", Type, DiskNumber, PartitionNumber); Status = OpenBootStoreByHandle(&BootStoreHandle, PartitionDirectoryHandle, Type, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("Could not open the NTOS boot store of type '%d' (Status 0x%08lx), continue with another one...\n", Type, Status); continue; } EnumerateBootStoreEntries(BootStoreHandle, EnumerateInstallations, &Data); CloseBootStore(BootStoreHandle); } /* Close the partition */ NtClose(PartitionDirectoryHandle); }
////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Description : // Registry callback. Logs any registry interaction performed by monitored processes. // Parameters : // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff560903(v=vs.85).aspx // Return value : // See http://msdn.microsoft.com/en-us/library/windows/hardware/ff560903(v=vs.85).aspx // Process : // Checks the operation and logs the associated data. ////////////////////////////////////////////////////////////////////////////////////////////////////////////// NTSTATUS regCallback (PVOID CallbackContext, PVOID Argument1, PVOID Argument2) { NTSTATUS status, tmpCall; UNICODE_STRING full_data, test; PUNICODE_STRING tmp = NULL; PUNICODE_STRING valueName = NULL; PREG_SET_VALUE_KEY_INFORMATION arg = NULL; ULONG returnedLength = 0; PWCHAR pwBuf = NULL; PWCHAR tmp_data = NULL; ULONG pid = (ULONG)PsGetCurrentProcessId(); DWORD i = 0; if(!isProcessMonitoredByPid(pid) || ExGetPreviousMode() == KernelMode) return STATUS_SUCCESS; pwBuf = ExAllocatePoolWithTag(NonPagedPool, (MAXSIZE+1)*sizeof(WCHAR), BUFFER_TAG); if(pwBuf == NULL) return STATUS_SUCCESS; tmp = ExAllocatePoolWithTag(NonPagedPool, MAXSIZE*sizeof(WCHAR), TEMP_TAG); if(tmp == NULL) { ExFreePool(tmp); return STATUS_SUCCESS; } switch((REG_NOTIFY_CLASS)Argument1) { case RegNtPreDeleteKey: status = ObQueryNameString(((PREG_DELETE_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call DeleteKey() \n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", tmp))) sendLogs(pid, L"REGISTRY_DELETE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_DELETE_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_DELETE_KEY", L"0,-1,s,SubKey->ERROR"); break; case RegNtPreSetValueKey: arg = (PREG_SET_VALUE_KEY_INFORMATION)Argument2; status = ObQueryNameString(arg->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call SetValueKey() \n"); #endif switch(arg->Type) { case REG_SZ: tmpCall = RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,sss,SubKey->%wZ,ValueName->%wZ,Data->%ws", tmp, arg->ValueName, ((PWCHAR)arg->Data)); break; default : tmp_data = ExAllocatePoolWithTag(NonPagedPool, MAXSIZE, 'gnaA'); full_data.MaximumLength = MAXSIZE; full_data.Buffer = ExAllocatePoolWithTag(NonPagedPool, full_data.MaximumLength, 'baaH'); RtlZeroMemory(full_data.Buffer, full_data.MaximumLength); for(i=0; i<arg->DataSize; i++) { if(i==100) break; RtlStringCchPrintfW(tmp_data, MAXSIZE, L"\\x%02x", *((PWCHAR)arg->Data+i)); if(i==0) { RtlInitUnicodeString(&test, tmp_data); RtlCopyUnicodeString(&full_data, &test); } if(NT_SUCCESS(RtlAppendUnicodeToString(&full_data, tmp_data))) RtlZeroMemory(tmp_data, MAXSIZE); } tmpCall = RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,sss,SubKey->%wZ,ValueName->%wZ,Data->%wZ", tmp, arg->ValueName, &full_data); ExFreePool(full_data.Buffer); ExFreePool(tmp_data); break; } if(NT_SUCCESS(tmpCall)) sendLogs(pid, L"REGISTRY_VALUE_KEY_SET", pwBuf); else sendLogs(pid, L"REGISTRY_VALUE_KEY_SET", L"1,0,sss,SubKey->ERROR,ValueName->ERROR,Data->ERROR"); } else sendLogs(pid, L"REGISTRY_VALUE_KEY_SET", L"1,0,sss,SubKey->ERROR,ValueName->ERROR,Data->ERROR"); break; case RegNtPreDeleteValueKey: status = ObQueryNameString(((PREG_DELETE_VALUE_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call DeleteValueKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,ss,SubKey->%wZ,ValueName->%wZ", tmp, ((PREG_DELETE_VALUE_KEY_INFORMATION)Argument2)->ValueName))) sendLogs(pid, L"REGISTRY_VALUE_KEY_DELETE", pwBuf); else sendLogs(pid, L"REGISTRY_VALUE_KEY_DELETE", L"1,0,ss,SubKey->ERROR,ValueName->ERROR"); } else sendLogs(pid, L"REGISTRY_VALUE_KEY_DELETE", L"1,0,ss,SubKey->ERROR,ValueName->ERROR"); break; case RegNtPreRenameKey: status = ObQueryNameString(((PREG_RENAME_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call RenameKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,ss,SubKey->%wZ,NewName->%wZ", tmp, ((PREG_RENAME_KEY_INFORMATION)Argument2)->NewName))) sendLogs(pid, L"REGISTRY_KEY_RENAME", pwBuf); else sendLogs(pid, L"REGISTRY_KEY_RENAME", L"1,0,ss,SubKey->ERROR,NewName->ERROR"); } else sendLogs(pid, L"REGISTRY_KEY_RENAME", L"1,0,ss,SubKey->ERROR,NewName->ERROR"); break; case RegNtPreEnumerateKey: status = ObQueryNameString(((PREG_ENUMERATE_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call EnumerateKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", tmp))) sendLogs(pid, L"REGISTRY_ENUMERATE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_ENUMERATE_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_ENUMERATE_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreEnumerateValueKey: status = ObQueryNameString(((PREG_ENUMERATE_VALUE_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call EnumerateValueKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", tmp))) sendLogs(pid, L"REGISTRY_ENUMERATE_VALUE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_ENUMERATE_VALUE_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_ENUMERATE_VALUE_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreQueryKey: status = ObQueryNameString(((PREG_QUERY_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call QueryKey()! \n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", tmp))) sendLogs(pid, L"REGISTRY_QUERY_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_QUERY_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_QUERY_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreQueryValueKey: status = ObQueryNameString(((PREG_QUERY_VALUE_KEY_INFORMATION)Argument2)->Object, (POBJECT_NAME_INFORMATION)tmp, MAXSIZE, &returnedLength); if(NT_SUCCESS(status)) { #ifdef DEBUG DbgPrint("call QueryValueKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,ss,SubKey->%wZ,ValueName->%wZ", tmp, ((PREG_QUERY_VALUE_KEY_INFORMATION)Argument2)->ValueName))) sendLogs(pid, L"REGISTRY_QUERY_VALUE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_QUERY_VALUE_KEY", L"1,0,ss,SubKey->ERROR,ValueName->ERROR"); } else sendLogs(pid, L"REGISTRY_QUERY_VALUE_KEY", L"1,0,ss,SubKey->ERROR,ValueName->ERROR"); break; case RegNtPreCreateKey: #ifdef DEBUG DbgPrint("call CreateKey() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", ((PREG_PRE_CREATE_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_CREATE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_CREATE_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreCreateKeyEx: #ifdef DEBUG DbgPrint("call CreateKeyEx() !\n"); #endif if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", ((PREG_PRE_CREATE_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_CREATE_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_CREATE_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreOpenKey: #ifdef DEBUG DbgPrint("call OpenKey() !\n"); #endif if(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer != NULL) { if(!_wcsicmp(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer, L"SOFTWARE\\Oracle\\VirtualBox Guest Additions") || !_wcsicmp(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer, L"SOFTWARE\\VMware, Inc.\\VMware Tools")) { if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"0,0,s,SubKey->%wZ", ((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_OPEN_KEY", pwBuf); return STATUS_OBJECT_NAME_NOT_FOUND; } if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", ((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_OPEN_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_OPEN_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_OPEN_KEY", L"1,0,s,SubKey->ERROR"); break; case RegNtPreOpenKeyEx: #ifdef DEBUG DbgPrint("call OpenKeyEx() !\n"); #endif if(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer != NULL) { if(!_wcsicmp(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer, L"SOFTWARE\\Oracle\\VirtualBox Guest Additions") || !_wcsicmp(((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName->Buffer, L"SOFTWARE\\VMware, Inc.\\VMware Tools")) { if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"0,0,s,SubKey->%wZ", ((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_OPEN_KEY", pwBuf); return STATUS_OBJECT_NAME_NOT_FOUND; } if(NT_SUCCESS(RtlStringCchPrintfW(pwBuf, MAXSIZE, L"1,0,s,SubKey->%wZ", ((PREG_OPEN_KEY_INFORMATION)Argument2)->CompleteName))) sendLogs(pid,L"REGISTRY_OPEN_KEY", pwBuf); else sendLogs(pid, L"REGISTRY_OPEN_KEY", L"1,0,s,SubKey->ERROR"); } else sendLogs(pid, L"REGISTRY_OPEN_KEY", L"1,0,s,SubKey->ERROR"); break; default: break; } ExFreePool(tmp); ExFreePool(pwBuf); return STATUS_SUCCESS; }
NTSTATUS Hooked_NtQueryAttributesFile(__in POBJECT_ATTRIBUTES ObjectAttributes, __out PFILE_BASIC_INFORMATION FileInformation) { NTSTATUS statusCall, exceptionCode; ULONG currentProcessId; UNICODE_STRING kObjectName; PWCHAR parameter = NULL; PAGED_CODE(); currentProcessId = (ULONG)PsGetCurrentProcessId(); statusCall = Orig_NtQueryAttributesFile(ObjectAttributes, FileInformation); if(IsProcessInList(currentProcessId, pMonitoredProcessListHead) && (ExGetPreviousMode() != KernelMode)) { Dbg("Call NtQueryAttributesFile\n"); parameter = PoolAlloc(MAX_SIZE * sizeof(WCHAR)); kObjectName.Buffer = NULL; if(NT_SUCCESS(statusCall)) { __try { if(ObjectAttributes != NULL) { ProbeForRead(ObjectAttributes, sizeof(OBJECT_ATTRIBUTES), 1); ProbeForRead(ObjectAttributes->ObjectName, sizeof(UNICODE_STRING), 1); ProbeForRead(ObjectAttributes->ObjectName->Buffer, ObjectAttributes->ObjectName->Length, 1); kObjectName.Length = ObjectAttributes->ObjectName->Length; kObjectName.MaximumLength = ObjectAttributes->ObjectName->MaximumLength; kObjectName.Buffer = PoolAlloc(kObjectName.MaximumLength); RtlCopyUnicodeString(&kObjectName, ObjectAttributes->ObjectName); } else RtlInitUnicodeString(&kObjectName, L""); } __except(EXCEPTION_EXECUTE_HANDLER) { exceptionCode = GetExceptionCode(); if(parameter && NT_SUCCESS(RtlStringCchPrintfW(parameter, MAX_SIZE, L"0,%d,sss,FileHandle->0,buffer->ERROR,offset->0", exceptionCode))) SendLogs(currentProcessId, SIG_ntdll_NtQueryAttributesFile, parameter); else SendLogs(currentProcessId, SIG_ntdll_NtQueryAttributesFile, L"0,-1,sss,FileHandle->0,buffer->ERROR,offset->0"); if(parameter != NULL) PoolFree(parameter); return statusCall; } if(wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\drivers\\VBoxMouse.sys") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\drivers\\VBoxGuest.sys") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\drivers\\VBoxSF.sys") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\drivers\\VBoxVideo.sys") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxControl.exe") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxDisp.dll") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxHook.dll") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxMRXNP.dll") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxOGL.dll") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxOGLarrayspu.dll") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxOGLcrutil.dll") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxOGLerrorspu.dll") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxOGLfeedbackspu.dll") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxOGLpackspu.dll") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxOGLpassthroughspu.dll") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxService.exe") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\VBoxTray.exe") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\drivers\\vmmouse.sys") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Windows\\system32\\drivers\\vmhgfs.sys") || wcsistr(kObjectName.Buffer, L"\\??\\C:\\Program Files\\oracle\\virtualbox guest additions\\")) { if(parameter && NT_SUCCESS(RtlStringCchPrintfW(parameter, MAX_SIZE, L"0,-1,s,filepath->%wZ", &kObjectName))) SendLogs(currentProcessId, SIG_ntdll_NtQueryAttributesFile, parameter); else SendLogs(currentProcessId, SIG_ntdll_NtQueryAttributesFile, L"0,-1,s,filepath->ERROR"); if(parameter != NULL) PoolFree(parameter); return INVALID_FILE_ATTRIBUTES; } } if(parameter != NULL) PoolFree(parameter); }
NTSTATUS bus_plugin_dev(ioctl_usbvbus_plugin * plugin, PFDO_DEVICE_DATA fdodata, PFILE_OBJECT fo) { PDEVICE_OBJECT pdo; PPDO_DEVICE_DATA pdodata, old_pdodata; NTSTATUS status; ULONG len; PLIST_ENTRY entry; unsigned long i; PAGED_CODE (); Bus_KdPrint (fdodata, BUS_DBG_PNP_INFO, ("Exposing PDO\n" "======addr: %d\n" "======vendor:product: %04x:%04x\n", plugin->addr, plugin->vendor, plugin->product)); if(plugin->addr <= 0) return STATUS_INVALID_PARAMETER; ExAcquireFastMutex (&fdodata->Mutex); for (entry = fdodata->ListOfPDOs.Flink; entry != &fdodata->ListOfPDOs; entry = entry->Flink) { pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); if (plugin->addr == pdodata->SerialNo && pdodata->DevicePnPState != SurpriseRemovePending) { ExReleaseFastMutex (&fdodata->Mutex); return STATUS_INVALID_PARAMETER; } } ExReleaseFastMutex (&fdodata->Mutex); // Create the PDO // Bus_KdPrint(fdodata, BUS_DBG_PNP_NOISE, ("fdodata->NextLowerDriver = 0x%p\n", fdodata->NextLowerDriver)); // // PDO must have a name. You should let the system auto generate a // name by specifying FILE_AUTOGENERATED_DEVICE_NAME in the // DeviceCharacteristics parameter. Let us create a secure deviceobject, // in case the child gets installed as a raw device (RawDeviceOK), to prevent // an unpriviledged user accessing our device. This function is avaliable // in a static WDMSEC.LIB and can be used in Win2k, XP, and Server 2003 // Just make sure that the GUID specified here is not a setup class GUID. // If you specify a setup class guid, you must make sure that class is // installed before enumerating the PDO. // status = IoCreateDeviceSecure(fdodata->Self->DriverObject, sizeof (PDO_DEVICE_DATA), NULL, FILE_DEVICE_BUS_EXTENDER, FILE_AUTOGENERATED_DEVICE_NAME |FILE_DEVICE_SECURE_OPEN, FALSE, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL, // read wdmsec.h for more info (LPCGUID)&GUID_SD_BUSENUM_PDO, &pdo); if (!NT_SUCCESS (status)) { return status; } pdodata = (PPDO_DEVICE_DATA) pdo->DeviceExtension; #define HARDWARE_IDS_TPL L"USB\\Vid_%04x&Pid_%04x&Rev_%04xZUSB\\Vid_%04x&Pid_%04xZ" len = sizeof(HARDWARE_IDS_TPL); pdodata->HardwareIDs = ExAllocatePoolWithTag (NonPagedPool, len, BUSENUM_POOL_TAG); if (NULL == pdodata->HardwareIDs) { IoDeleteDevice(pdo); return STATUS_INSUFFICIENT_RESOURCES; } RtlStringCchPrintfW(pdodata->HardwareIDs, len/sizeof(wchar_t), HARDWARE_IDS_TPL, plugin->vendor, plugin->product, plugin->version, plugin->vendor, plugin->product); for(i=0;i<sizeof(HARDWARE_IDS_TPL);i++){ if('Z'==pdodata->HardwareIDs[i]) pdodata->HardwareIDs[i]=0; } #define COMPATIBLE_IDS_TPL L"USB\\Class_%02x&SubClass_%02x&Prot_%02xZUSB\\Class_%02x&SubClass_%02xZUSB\\Class_%02xZ" #define COMPATIBLE_COMPOSITE_IDS_TPL L"USB\\Class_%02x&SubClass_%02x&Prot_%02xZUSB\\Class_%02x&SubClass_%02xZUSB\\Class_%02xZUSB\\COMPOSITEZ" if(plugin->inum>1) len = sizeof(COMPATIBLE_COMPOSITE_IDS_TPL); else len = sizeof(COMPATIBLE_IDS_TPL); pdodata->compatible_ids = ExAllocatePoolWithTag (NonPagedPool, len, BUSENUM_POOL_TAG); RtlZeroMemory(pdodata->compatible_ids, len); if (NULL == pdodata->compatible_ids) { ExFreePool(pdodata->HardwareIDs); IoDeleteDevice(pdo); return STATUS_INSUFFICIENT_RESOURCES; } pdodata->compatible_ids_len = len; RtlStringCchPrintfW(pdodata->compatible_ids, len/sizeof(wchar_t), (plugin->inum>1)?COMPATIBLE_COMPOSITE_IDS_TPL:COMPATIBLE_IDS_TPL, plugin->int0_class, plugin->int0_subclass, plugin->int0_protocol, plugin->int0_class, plugin->int0_subclass, plugin->int0_class); for(i=0;i<len;i++){ if('Z'==pdodata->compatible_ids[i]) pdodata->compatible_ids[i]=0; } old_pdodata = (PPDO_DEVICE_DATA) InterlockedCompareExchange(&((LONG)fo->FsContext), (LONG) pdodata, 0); if(old_pdodata){ KdPrint(("you can't plugin again")); ExFreePool(pdodata->HardwareIDs); ExFreePool(pdodata->compatible_ids); IoDeleteDevice(pdo); return STATUS_INVALID_PARAMETER; } pdodata->SerialNo = plugin->addr; pdodata->fo = fo; pdodata->devid = plugin->devid; pdodata->speed = plugin->speed; bus_init_pdo (pdo, fdodata); // // Device Relation changes if a new pdo is created. So let // the PNP system now about that. This forces it to send bunch of pnp // queries and cause the function driver to be loaded. // IoInvalidateDeviceRelations (fdodata->UnderlyingPDO, BusRelations); return status; }
VOID DiskCreateSymbolicLinks( IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This routine will generate a symbolic link for the specified device object using the well known form \\Device\HarddiskX\PartitionY, where X and Y is always 0 which represents the entire disk object. This routine will not try to delete any previous symbolic link for the same generated name - the caller must make sure the symbolic link has been broken before calling this routine. Arguments: DeviceObject - the device object to make a well known name for Return Value: STATUS --*/ { PCOMMON_DEVICE_EXTENSION commonExtension = DeviceObject->DeviceExtension; PDISK_DATA diskData = commonExtension->DriverData; WCHAR wideSourceName[64] = { 0 }; UNICODE_STRING unicodeSourceName; NTSTATUS status; PAGED_CODE(); // // Build the destination for the link first using the device name // stored in the device object // NT_ASSERT(commonExtension->DeviceName.Buffer); if(!diskData->LinkStatus.WellKnownNameCreated) { // // Put together the source name using the partition and device number // in the device extension and disk data segment // status = RtlStringCchPrintfW(wideSourceName, sizeof(wideSourceName) / sizeof(wideSourceName[0]) - 1, L"\\Device\\Harddisk%d\\Partition0", commonExtension->PartitionZeroExtension->DeviceNumber); if (NT_SUCCESS(status)) { RtlInitUnicodeString(&unicodeSourceName, wideSourceName); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskCreateSymbolicLink: Linking %wZ to %wZ\n", &unicodeSourceName, &commonExtension->DeviceName)); status = IoCreateSymbolicLink(&unicodeSourceName, &commonExtension->DeviceName); if(NT_SUCCESS(status)){ diskData->LinkStatus.WellKnownNameCreated = TRUE; } } } if (!diskData->LinkStatus.PhysicalDriveLinkCreated) { // // Create a physical drive N link using the device number we saved // away during AddDevice. // status = RtlStringCchPrintfW(wideSourceName, sizeof(wideSourceName) / sizeof(wideSourceName[0]) - 1, L"\\DosDevices\\PhysicalDrive%d", commonExtension->PartitionZeroExtension->DeviceNumber); if (NT_SUCCESS(status)) { RtlInitUnicodeString(&unicodeSourceName, wideSourceName); TracePrint((TRACE_LEVEL_INFORMATION, TRACE_FLAG_PNP, "DiskCreateSymbolicLink: Linking %wZ to %wZ\n", &unicodeSourceName, &(commonExtension->DeviceName))); status = IoCreateSymbolicLink(&unicodeSourceName, &(commonExtension->DeviceName)); if(NT_SUCCESS(status)) { diskData->LinkStatus.PhysicalDriveLinkCreated = TRUE; } } } return; }
/** * 写日志函数 * @param iLevel:ULONG,要写入日志信息的等级,请参考LogConst.h文件内等级。 * @param format:NTSTRSAFE_PSTR*,输入信息的格式,此格式参考printf。 * @param ...:变参,参考printf,要写入的信息。 * 写日志信息接口,写日志信息大小请不要超过规定长度的大小!最大暂时为256字节!! */ void _cdecl WriteSysLog(ULONG iLevel, NTSTRSAFE_PWSTR format,...) { //判断记录日志级别 if(iLevel > g_logLevel) return; //获得互斥体,在下面的调用中,所有的函数退出部分都要进行释放互斥体 KeWaitForSingleObject(&g_logMutex, Executive, KernelMode, FALSE, NULL); HANDLE logfile; OBJECT_ATTRIBUTES objectAttributes; IO_STATUS_BLOCK ioStatus; NTSTATUS ntStatus; InitializeObjectAttributes(&objectAttributes,&g_logFileName,OBJ_CASE_INSENSITIVE,NULL, NULL); ntStatus = ZwCreateFile(&logfile,FILE_READ_ATTRIBUTES | FILE_APPEND_DATA | SYNCHRONIZE, &objectAttributes,&ioStatus,NULL,FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_OPEN_IF,FILE_SYNCHRONOUS_IO_NONALERT,NULL,0); if(!NT_SUCCESS(ntStatus) ) { KeReleaseMutex(&g_logMutex,FALSE); KdPrint( ("Strategy:%d:Init Open file error!\n",g_logStrategy) ); return; } //判断文件大小处理的函数 if(g_logWriteTime >= CHECK_TIME) { if(g_logStrategy == 1) { ntStatus = CheckLogFileSizeAndReCreateLogFile(&g_logFileName,1,logfile); if(!NT_SUCCESS(ntStatus) ) { KeReleaseMutex(&g_logMutex,FALSE); KdPrint( ("Strategy:%d:Init Open file error!\n",g_logStrategy) ); return; } } g_logWriteTime = 0; } TIME_FIELDS ctime; ctime = GetLocalTime(); ULONG pid = (ULONG)PsGetCurrentProcessId(); PWCHAR ptype; switch(iLevel) { case LOG_TYPE_ERROR: ptype = L"ERROR";break; case LOG_TYPE_WARN: ptype = L"WARNING";break; case LOG_TYPE_INFO: ptype = L"INFO";break; default: ptype = L"DEBUG";break; } WCHAR strTemp[MAX_INFO_LENGTH]; RtlZeroMemory(strTemp, MAX_INFO_LENGTH); NTSTRSAFE_PWSTR pinfo = strTemp; va_list args; va_start(args,format); ntStatus =::RtlStringCchVPrintfW(pinfo,MAX_INFO_LENGTH*sizeof(WCHAR),format,args); if( !NT_SUCCESS(ntStatus) ) { DbgPrint( ("Log info conversion error1!\n") ); ZwClose(logfile); KeReleaseMutex(&g_logMutex,FALSE); //在函数所有的出口释放互斥体 return; } va_end(args); WCHAR cinfo[MAX_INFO_LENGTH*2]; RtlZeroMemory(cinfo,MAX_INFO_LENGTH*2*sizeof(WCHAR));//清0,为了下面的操作顺利 ntStatus = RtlStringCchPrintfW(cinfo,MAX_INFO_LENGTH*2*sizeof(WCHAR), L"%04d-%02d-%02d %02d:%02d:%02d.%03d\t%d\t%s\t%s\r\n", ctime.Year, ctime.Month, ctime.Day, ctime.Hour, ctime.Minute, ctime.Second, ctime.Milliseconds,pid,ptype,pinfo); if( !NT_SUCCESS(ntStatus) ) { DbgPrint( ("Log info conversion error2!\n") ); //在函数所有的出口释放互斥体 ZwClose(logfile); KeReleaseMutex(&g_logMutex,FALSE); return; } size_t length; ntStatus = RtlStringCchLengthW(cinfo,MAX_INFO_LENGTH*2,&length); if( !NT_SUCCESS(ntStatus) ) { DbgPrint( ("Log info conversion error3!\n") ); //在函数所有的出口释放互斥体 ZwClose(logfile); KeReleaseMutex(&g_logMutex,FALSE); return; } ntStatus = ZwWriteFile(logfile,NULL,NULL,NULL,&ioStatus,cinfo,length*sizeof(WCHAR),NULL,NULL); if( !NT_SUCCESS(ntStatus) ) { DbgPrint( ("Write log error!\n") ); ZwClose(logfile); //在函数所有的出口释放互斥体 KeReleaseMutex(&g_logMutex,FALSE); return; } g_logWriteTime ++;//增加写入次数 ZwClose(logfile); KeReleaseMutex(&g_logMutex,FALSE); //KdPrint( ("write log successful!\n") ); }
BOOLEAN XixFsGetScsiportAdapter( IN PDEVICE_OBJECT DiskDeviceObject, IN PDEVICE_OBJECT *ScsiportAdapterDeviceObject ) { SCSI_ADDRESS ScsiAddress; NTSTATUS ntStatus; UNICODE_STRING ScsiportAdapterName; WCHAR ScsiportAdapterNameBuffer[32]; WCHAR ScsiportAdapterNameTemp[32] = L""; OBJECT_ATTRIBUTES objectAttributes; HANDLE fileHandle = NULL; IO_STATUS_BLOCK IoStatus; PFILE_OBJECT ScsiportDeviceFileObject = NULL; ntStatus = XixFsRawDevIoCtrl ( DiskDeviceObject, IOCTL_SCSI_GET_ADDRESS, NULL, 0, (uint8 *)&ScsiAddress, sizeof(SCSI_ADDRESS), FALSE, NULL ); if(!NT_SUCCESS(ntStatus)) { DebugTrace( DEBUG_LEVEL_ERROR, (DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB|DEBUG_TARGET_LOCK), ("XixFsGetScsiportAdapter: LfsFilterDeviceIoControl() failed.\n")); goto error_out; } DebugTrace( DEBUG_LEVEL_ALL, (DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB|DEBUG_TARGET_LOCK), ("XixFsGetScsiportAdapter: ScsiAddress=Len:%d PortNumber:%d PathId:%d TargetId:%d Lun:%d\n", (LONG)ScsiAddress.Length, (LONG)ScsiAddress.PortNumber, (LONG)ScsiAddress.PathId, (LONG)ScsiAddress.TargetId, (LONG)ScsiAddress.Lun )); RtlStringCchPrintfW(ScsiportAdapterNameTemp, sizeof(ScsiportAdapterNameTemp) / sizeof(ScsiportAdapterNameTemp[0]), L"\\Device\\ScsiPort%d", ScsiAddress.PortNumber); RtlInitEmptyUnicodeString( &ScsiportAdapterName, ScsiportAdapterNameBuffer, sizeof( ScsiportAdapterNameBuffer ) ); RtlAppendUnicodeToString( &ScsiportAdapterName, ScsiportAdapterNameTemp ); InitializeObjectAttributes( &objectAttributes, &ScsiportAdapterName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); // // open the file object for the given device // ntStatus = ZwCreateFile( &fileHandle, SYNCHRONIZE|FILE_READ_DATA, &objectAttributes, &IoStatus, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if (!NT_SUCCESS( ntStatus )) { DebugTrace( DEBUG_LEVEL_ERROR, (DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB), ("XixFsGetScsiportAdapter: ZwCreateFile() failed.\n")); goto error_out; } ntStatus = ObReferenceObjectByHandle( fileHandle, FILE_READ_DATA, *IoFileObjectType, KernelMode, &ScsiportDeviceFileObject, NULL); if(!NT_SUCCESS( ntStatus )) { DebugTrace( DEBUG_LEVEL_ERROR, (DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB|DEBUG_TARGET_LOCK), ("XixFsGetScsiportAdapter: ObReferenceObjectByHandle() failed.\n")); goto error_out; } *ScsiportAdapterDeviceObject = IoGetRelatedDeviceObject( ScsiportDeviceFileObject ); if(*ScsiportAdapterDeviceObject == NULL) { DebugTrace( DEBUG_LEVEL_ERROR, (DEBUG_TARGET_RESOURCE| DEBUG_TARGET_FCB|DEBUG_TARGET_LOCK), ("XixFsGetScsiportAdapter: IoGetRelatedDeviceObject() failed.\n")); ObDereferenceObject(ScsiportDeviceFileObject); goto error_out; } ObDereferenceObject(ScsiportDeviceFileObject); ZwClose(fileHandle); ObReferenceObject(*ScsiportAdapterDeviceObject); return TRUE; error_out: *ScsiportAdapterDeviceObject = NULL; if(fileHandle) ZwClose(fileHandle); return FALSE; }
NTSTATUS FileDiskQueryPnpID( __in PNDAS_LOGICALUNIT_EXTENSION LogicalUnitExtension, __in BUS_QUERY_ID_TYPE QueryType, __in ULONG Index, __inout PUNICODE_STRING UnicodeStringId) { static CONST WCHAR* HARDWARE_IDS[] = { NDASPORT_ENUMERATOR_GUID_PREFIX L"FileDisk", NDASPORT_ENUMERATOR_NAMED_PREFIX L"FileDisk", L"GenDisk", }; static CONST WCHAR* COMPATIBLE_IDS[] = { L"gendisk" }; WCHAR instanceId[20]; WCHAR* instanceIdList[] = { instanceId }; NTSTATUS status; PFILEDISK_EXTENSION fileDiskExtension; CONST WCHAR** idList; ULONG idListCount; fileDiskExtension = FileDiskGetExtension(LogicalUnitExtension); switch (QueryType) { case BusQueryDeviceID: idList = HARDWARE_IDS; idListCount = 1; break; case BusQueryHardwareIDs: idList = HARDWARE_IDS; idListCount = countof(HARDWARE_IDS); break; case BusQueryCompatibleIDs: idList = COMPATIBLE_IDS; idListCount = countof(COMPATIBLE_IDS); break; case BusQueryInstanceID: idList = (const WCHAR**) instanceIdList; idListCount = 1; status = RtlStringCchPrintfW( instanceId, countof(instanceId), L"%08X", RtlUlongByteSwap(fileDiskExtension->LogicalUnitAddress)); ASSERT(NT_SUCCESS(status)); break; case 4 /*BusQueryDeviceSerialNumber*/: default: return STATUS_NOT_SUPPORTED; } if (Index >= idListCount) { return STATUS_NO_MORE_ENTRIES; } status = RtlUnicodeStringCopyString( UnicodeStringId, idList[Index]); return status; }
NTSTATUS Bus_PDO_QueryDeviceText( __in PPDO_DEVICE_DATA DeviceData, __in PIRP Irp ) /*++ Routine Description: The PnP Manager uses this IRP to get a device's description or location information. This string is displayed in the "found new hardware" pop-up window if no INF match is found for the device. Bus drivers are also encouraged to return location information for their child devices, but this information is optional. Arguments: DeviceData - Pointer to the PDO's device extension. Irp - Pointer to the irp. Return Value: NT STATUS --*/ { PWCHAR buffer; USHORT length; PIO_STACK_LOCATION stack; NTSTATUS status; PAGED_CODE (); stack = IoGetCurrentIrpStackLocation (Irp); switch (stack->Parameters.QueryDeviceText.DeviceTextType) { case DeviceTextDescription: // // Check to see if any filter driver has set any information. // If so then remain silent otherwise add your description. // This string must be localized to support various languages. // switch (stack->Parameters.QueryDeviceText.LocaleId) { case 0x00000407 : // German // Localize the device text. // Until we implement let us fallthru to English default: // for all other languages, fallthru to English case 0x00000409 : // English if (!Irp->IoStatus.Information) { // 10 for number of digits in the serial number length = (USHORT) \ (wcslen(VENDORNAME) + 1 + wcslen(MODEL) + 1 + 10) * sizeof(WCHAR); buffer = ExAllocatePoolWithTag (PagedPool, length, BUSENUM_POOL_TAG); if (buffer == NULL ) { status = STATUS_INSUFFICIENT_RESOURCES; break; } RtlStringCchPrintfW(buffer, length/sizeof(WCHAR), L"%ws%ws%02d", VENDORNAME, MODEL, DeviceData->SerialNo); Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE, ("\tDeviceTextDescription :%ws\n", buffer)); Irp->IoStatus.Information = (ULONG_PTR) buffer; } status = STATUS_SUCCESS; break; } // end of LocalID switch break; case DeviceTextLocationInformation: Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_TRACE, ("\tDeviceTextLocationInformation: Unknown\n")); default: status = Irp->IoStatus.Status; break; } return status; }
NTSTATUS Bus_PDO_QueryDeviceId( __in PPDO_DEVICE_DATA DeviceData, __in PIRP Irp ) /*++ Routine Description: Bus drivers must handle BusQueryDeviceID requests for their child devices (child PDOs). Bus drivers can handle requests BusQueryHardwareIDs, BusQueryCompatibleIDs, and BusQueryInstanceID for their child devices. When returning more than one ID for hardware IDs or compatible IDs, a driver should list the IDs in the order of most specific to most general to facilitate choosing the best driver match for the device. Bus drivers should be prepared to handle this IRP for a child device immediately after the device is enumerated. Arguments: DeviceData - Pointer to the PDO's device extension. Irp - Pointer to the irp. Return Value: NT STATUS --*/ { PIO_STACK_LOCATION stack; PWCHAR buffer; ULONG length; NTSTATUS status = STATUS_SUCCESS; ULONG_PTR result; PAGED_CODE (); stack = IoGetCurrentIrpStackLocation (Irp); switch (stack->Parameters.QueryId.IdType) { case BusQueryDeviceID: // // DeviceID is unique string to identify a device. // This can be the same as the hardware ids (which requires a multi // sz). // buffer = DeviceData->HardwareIDs; while (*(buffer++)) { while (*(buffer++)) { ; } } status = RtlULongPtrSub((ULONG_PTR)buffer, (ULONG_PTR)DeviceData->HardwareIDs, &result); if (!NT_SUCCESS(status)) { break; } length = (ULONG)result; buffer = ExAllocatePoolWithTag (PagedPool, length, BUSENUM_POOL_TAG); if (!buffer) { status = STATUS_INSUFFICIENT_RESOURCES; break; } RtlCopyMemory (buffer, DeviceData->HardwareIDs, length); Irp->IoStatus.Information = (ULONG_PTR) buffer; break; case BusQueryInstanceID: // // total length = number (10 digits to be safe (2^32)) + null wide char // length = 11 * sizeof(WCHAR); buffer = ExAllocatePoolWithTag (PagedPool, length, BUSENUM_POOL_TAG); if (!buffer) { status = STATUS_INSUFFICIENT_RESOURCES; break; } RtlStringCchPrintfW(buffer, length/sizeof(WCHAR), L"%02d", DeviceData->SerialNo); Bus_KdPrint_Cont (DeviceData, BUS_DBG_PNP_INFO, ("\tInstanceID: %ws\n", buffer)); Irp->IoStatus.Information = (ULONG_PTR) buffer; break; case BusQueryHardwareIDs: // // A device has at least one hardware id. // In a list of hardware IDs (multi_sz string) for a device, // DeviceId is the most specific and should be first in the list. // buffer = DeviceData->HardwareIDs; while (*(buffer++)) { while (*(buffer++)) { ; } } status = RtlULongPtrSub((ULONG_PTR)buffer, (ULONG_PTR)DeviceData->HardwareIDs, &result); if (!NT_SUCCESS(status)) { break; } length = (ULONG)result; buffer = ExAllocatePoolWithTag (PagedPool, length, BUSENUM_POOL_TAG); if (!buffer) { status = STATUS_INSUFFICIENT_RESOURCES; break; } RtlCopyMemory (buffer, DeviceData->HardwareIDs, length); Irp->IoStatus.Information = (ULONG_PTR) buffer; break; case BusQueryCompatibleIDs: // // The generic ids for installation of this pdo. // length = BUSENUM_COMPATIBLE_IDS_LENGTH; buffer = ExAllocatePoolWithTag (PagedPool, length, BUSENUM_POOL_TAG); if (!buffer) { status = STATUS_INSUFFICIENT_RESOURCES; break; } RtlCopyMemory (buffer, BUSENUM_COMPATIBLE_IDS, length); Irp->IoStatus.Information = (ULONG_PTR) buffer; break; default: status = Irp->IoStatus.Status; } return status; }
void InitializeMessage( _Inout_ CLAIMSMAN_MESSAGE *message, _In_ PUNICODE_STRING sid, _In_ PUNICODE_STRING name, _In_ BOOLEAN ReadAccess, _In_ BOOLEAN WriteAccess, _In_ BOOLEAN DeleteAccess, _In_ LONGLONG size, _In_ LONGLONG modified, _In_ NTSTATUS status ) /* ... */ { PAGED_CODE(); PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("claimsman!claimsmanInitializeMessage: Entered\n")); // SID USHORT len = (sid->Length < ((CLAIMSMAN_MESSAGE_SID_SIZE - 1) * sizeof(WCHAR))) ? sid->Length : (CLAIMSMAN_MESSAGE_SID_SIZE - 1) * sizeof(WCHAR); RtlCopyMemory(message->Sid, sid->Buffer, len); message->Sid[(len / sizeof(WCHAR)) + (len % sizeof(WCHAR))] = 0; // FileName len = (name->Length < ((CLAIMSMAN_MESSAGE_FILENAME_SIZE - 1) * sizeof(WCHAR))) ? name->Length : (CLAIMSMAN_MESSAGE_FILENAME_SIZE - 1) * sizeof(WCHAR); RtlCopyMemory(message->FileName, name->Buffer, len); message->FileName[(len / sizeof(WCHAR)) + (len % sizeof(WCHAR))] = 0; // Access info message->ReadAccess = ReadAccess; message->WriteAccess = WriteAccess; message->DeleteAccess = DeleteAccess; // Size message->size = size; // Last modified TIME_FIELDS tf; message->UnixLastModified = modified; LONGLONG tstmp = (modified * 10000) + DIFF_TO_UNIX_EPOCH; RtlTimeToTimeFields(&tstmp, &tf); RtlStringCchPrintfW((NTSTRSAFE_PWSTR)message->LastModified, CLAIMSMAN_MESSAGE_TIMESTAMP_SIZE - 1, L"%04u-%02u-%02uT%02u:%02u:%02u.%03uZ", tf.Year, tf.Month, tf.Day, tf.Hour, tf.Minute, tf.Second, tf.Milliseconds); // Iostatus message->Status = status; // Event timestamp LARGE_INTEGER st; KeQuerySystemTime(&st); // Store as timestamp (Unix epoch + 3 decimals for milliseconds) message->UnixTimeStamp = (st.QuadPart - DIFF_TO_UNIX_EPOCH) / 10000; //PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, // ("claimsman!claimsmanInitializeMessage: message->UnixTimeStamp: %I64u\n", message->UnixTimeStamp)); // And as ISO-8601... RtlTimeToTimeFields(&st, &tf); RtlStringCchPrintfW((NTSTRSAFE_PWSTR)message->TimeStamp, CLAIMSMAN_MESSAGE_TIMESTAMP_SIZE - 1, L"%04u-%02u-%02uT%02u:%02u:%02u.%03uZ", tf.Year, tf.Month, tf.Day, tf.Hour, tf.Minute, tf.Second, tf.Milliseconds); //PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, // ("claimsman!claimsmanInitializeMessage: message->TimeStamp: %ws\n", message->TimeStamp)); }
PDEVICE_OBJECT XenM2BPdoCreate(PXENM2B_FDO_EXTENSION pFdoExt, PCHAR pDeviceName, UCHAR SlotID) { PDEVICE_OBJECT pDevice; PXENM2B_PDO_EXTENSION pPdoExt; NTSTATUS Status; size_t NameLength; ANSI_STRING AnsiName; ULONG Hash; Status = RtlStringCchLengthA(pDeviceName, XENM2B_PDO_NAME_LENGTH, &NameLength); if ((!NT_SUCCESS(Status))||(NameLength >= XENM2B_PDO_NAME_LENGTH)) { TraceError(("%s: Invalid device name, error: 0x%x length: 0x%x\n", __FUNCTION__, Status, NameLength)); return NULL; } if (NameLength == 0) { TraceError(("%s: Invalid empty device name\n", __FUNCTION__)); return NULL; } Status = IoCreateDevice(pFdoExt->pDriver, sizeof(XENM2B_PDO_EXTENSION), NULL, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN | FILE_AUTOGENERATED_DEVICE_NAME, FALSE, &pDevice); if (!NT_SUCCESS(Status)) { TraceError(("%s: Failed to create new PDO, error: 0x%x\n", __FUNCTION__, Status)); return NULL; } pPdoExt = (PXENM2B_PDO_EXTENSION)pDevice->DeviceExtension; RtlZeroMemory(pPdoExt, sizeof(XENM2B_PDO_EXTENSION)); pPdoExt->Type = XenM2BPdo; pPdoExt->pDevice = pDevice; // Convert the name to UNICODE and store as the device TEXT. AnsiName.Length = (USHORT)NameLength; AnsiName.MaximumLength = NameLength + sizeof(CHAR); AnsiName.Buffer = pDeviceName; pPdoExt->DeviceName.Length = 0; pPdoExt->DeviceName.MaximumLength = XENM2B_PDO_NAME_LENGTH * sizeof(WCHAR); pPdoExt->DeviceName.Buffer = pPdoExt->pDeviceNameW; Status = RtlAnsiStringToUnicodeString(&pPdoExt->DeviceName, &AnsiName, FALSE); if (!NT_SUCCESS(Status)) { TraceError(("%s: Failed to convert ANSI device name %s to UNICODE, error: 0x%x\n", __FUNCTION__, pDeviceName, Status)); IoDeleteDevice(pDevice); return NULL; } // Create a unique instance ID for this device RtlHashUnicodeString(&pPdoExt->DeviceName, FALSE, HASH_STRING_ALGORITHM_DEFAULT, &Hash); Status = RtlStringCchPrintfW(&pPdoExt->pInstanceIDW[0], (XENM2B_PDO_NAME_LENGTH - 1), L"XH%8.8XS%2.2X", Hash, SlotID); if (!NT_SUCCESS(Status)) { TraceError(("%s: Failed to create Instance ID for device %s, error: 0x%x\n", __FUNCTION__, pDeviceName, Status)); IoDeleteDevice(pDevice); return NULL; } RtlInitUnicodeString(&pPdoExt->InstanceID, pPdoExt->pInstanceIDW); TraceDebug(("%s: %p -> Device: %wZ Instance: %wZ\n", __FUNCTION__, pDevice, &pPdoExt->DeviceName, &pPdoExt->InstanceID)); ExInitializeFastMutex(&pPdoExt->DevicePnPState.PnPStateMutex); XenM2BSetPnPState(&pPdoExt->DevicePnPState, PnPStatePresent); pPdoExt->SystemPowerState = PowerSystemWorking; pPdoExt->DevicePowerState = PowerDeviceD3; pDevice->Flags &= ~DO_DEVICE_INITIALIZING; return pDevice; }
////////////////////////////////////////////////////////////////////////// // // Event log // static VOID _WriteLogErrorEntry( IN PDEVICE_OBJECT DeviceObject, IN PLSU_ERROR_LOG_ENTRY LogEntry ){ PIO_ERROR_LOG_PACKET errorLogEntry; WCHAR strBuff[16]; NTSTATUS status; ULONG stringOffset; ULONG_PTR stringLen; ULONG idx_dump; // // Parameter to unicode string // ASSERT(LogEntry->DumpDataEntry <= LSU_MAX_ERRLOG_DATA_ENTRIES); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); status = RtlStringCchPrintfW(strBuff, 16, L"%u", LogEntry->Parameter2); if(!NT_SUCCESS(status)) { KDPrint(1, ("RtlStringCchVPrintfW() failed.\n")); return; } status = RtlStringCchLengthW(strBuff, 16, &stringLen); if(!NT_SUCCESS(status)) { KDPrint(1, ("RtlStringCchLengthW() failed.\n")); return; } // // Translate unicode length into byte length including NULL termination. // stringLen = ( stringLen + 1 ) * sizeof(WCHAR); stringOffset = FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + LogEntry->DumpDataEntry * sizeof(ULONG); errorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry( DeviceObject, (sizeof(IO_ERROR_LOG_PACKET) + (LogEntry->DumpDataEntry * sizeof(ULONG)) + (UCHAR)stringLen)); if(errorLogEntry == NULL) { KDPrint(1, ("Could not allocate error log entry.\n")); ASSERT(FALSE); return ; } errorLogEntry->ErrorCode = LogEntry->ErrorCode; errorLogEntry->MajorFunctionCode = LogEntry->MajorFunctionCode; errorLogEntry->IoControlCode = LogEntry->IoctlCode; errorLogEntry->EventCategory; errorLogEntry->SequenceNumber = LogEntry->SequenceNumber; errorLogEntry->RetryCount = (UCHAR) LogEntry->ErrorLogRetryCount; errorLogEntry->UniqueErrorValue = LogEntry->UniqueId; errorLogEntry->FinalStatus = STATUS_SUCCESS; errorLogEntry->DumpDataSize = LogEntry->DumpDataEntry * sizeof(ULONG); for(idx_dump=0; idx_dump < LogEntry->DumpDataEntry; idx_dump++) { errorLogEntry->DumpData[idx_dump] = LogEntry->DumpData[idx_dump]; } errorLogEntry->NumberOfStrings = 1; errorLogEntry->StringOffset = (USHORT)stringOffset; RtlCopyMemory((PUCHAR)errorLogEntry + stringOffset, strBuff, stringLen); IoWriteErrorLogEntry(errorLogEntry); return; }
void AFSDumpTraceFiles() { NTSTATUS ntStatus = STATUS_SUCCESS; HANDLE hDirectory = NULL; OBJECT_ATTRIBUTES stObjectAttribs; IO_STATUS_BLOCK stIoStatus; LARGE_INTEGER liTime, liLocalTime; TIME_FIELDS timeFields; ULONG ulBytesWritten = 0; HANDLE hDumpFile = NULL; ULONG ulBytesProcessed, ulCopyLength; LARGE_INTEGER liOffset; ULONG ulDumpLength = 0; BOOLEAN bSetEvent = FALSE; __Enter { AFSAcquireShared( &AFSDbgLogLock, TRUE); ulDumpLength = AFSDbgBufferLength - AFSDbgLogRemainingLength; AFSReleaseResource( &AFSDbgLogLock); if( AFSDumpFileLocation.Length == 0 || AFSDumpFileLocation.Buffer == NULL || AFSDbgBufferLength == 0 || ulDumpLength == 0 || AFSDumpFileName.MaximumLength == 0 || AFSDumpFileName.Buffer == NULL || AFSDumpBuffer == NULL) { try_return( ntStatus); } // // Go open the cache file // InitializeObjectAttributes( &stObjectAttribs, &AFSDumpFileLocation, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus = ZwCreateFile( &hDirectory, GENERIC_READ | GENERIC_WRITE, &stObjectAttribs, &stIoStatus, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } ntStatus = KeWaitForSingleObject( &AFSDumpFileEvent, Executive, KernelMode, FALSE, NULL); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } bSetEvent = TRUE; AFSDumpFileName.Length = 0; RtlZeroMemory( AFSDumpFileName.Buffer, AFSDumpFileName.MaximumLength); KeQuerySystemTime( &liTime); ExSystemTimeToLocalTime( &liTime, &liLocalTime); RtlTimeToTimeFields( &liLocalTime, &timeFields); ntStatus = RtlStringCchPrintfW( AFSDumpFileName.Buffer, AFSDumpFileName.MaximumLength/sizeof( WCHAR), L"AFSDumpFile %d.%d.%d %d.%d.%d.log", timeFields.Month, timeFields.Day, timeFields.Year, timeFields.Hour, timeFields.Minute, timeFields.Second); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } RtlStringCbLengthW( AFSDumpFileName.Buffer, AFSDumpFileName.MaximumLength, (size_t *)&ulBytesWritten); AFSDumpFileName.Length = (USHORT)ulBytesWritten; InitializeObjectAttributes( &stObjectAttribs, &AFSDumpFileName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hDirectory, NULL); ntStatus = ZwCreateFile( &hDumpFile, GENERIC_READ | GENERIC_WRITE, &stObjectAttribs, &stIoStatus, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_CREATE, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if( !NT_SUCCESS( ntStatus)) { try_return( ntStatus); } // // Write out the trace buffer // liOffset.QuadPart = 0; ulBytesProcessed = 0; while( ulBytesProcessed < ulDumpLength) { ulCopyLength = AFSDumpBufferLength; if( ulCopyLength > ulDumpLength - ulBytesProcessed) { ulCopyLength = ulDumpLength - ulBytesProcessed; } RtlCopyMemory( AFSDumpBuffer, (void *)((char *)AFSDbgBuffer + ulBytesProcessed), ulCopyLength); ntStatus = ZwWriteFile( hDumpFile, NULL, NULL, NULL, &stIoStatus, AFSDumpBuffer, ulCopyLength, &liOffset, NULL); if( !NT_SUCCESS( ntStatus)) { break; } liOffset.QuadPart += ulCopyLength; ulBytesProcessed += ulCopyLength; } try_exit: if( hDumpFile != NULL) { ZwClose( hDumpFile); } if( hDirectory != NULL) { ZwClose( hDirectory); } if( bSetEvent) { KeSetEvent( &AFSDumpFileEvent, 0, FALSE); } } return; }
BOOL ShareMemKImp::InitializeShareMem(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSize, LPCWSTR lpName, DWORD dwDesiredAccess, ShareMemClassInit* lpInitialization, void* lpUserContext) { UninitializeShareMem(); DWORD size; size = dwMaximumSize + sizeof(ShareMemHeader); if (size < dwMaximumSize) return FALSE; UNICODE_STRING us; RtlInitUnicodeString(&us, lpName); OBJECT_ATTRIBUTES attr; InitializeObjectAttributes(&attr, &us, OBJ_OPENIF, NULL, NULL); LARGE_INTEGER li; li.QuadPart = size; NTSTATUS status; status = ZwCreateSection(&m_hMapSect, READ_CONTROL|WRITE_DAC|dwDesiredAccess, &attr, &li, flProtect, SEC_COMMIT, hFile); BOOLEAN init; init = status != STATUS_SUCCESS ? FALSE : TRUE; if (m_hMapSect) { SIZE_T v_size; v_size = 0; status = ZwMapViewOfSection(m_hMapSect, ZwCurrentProcess(), &m_hMapView, 0, size, NULL, &v_size, ViewUnmap, 0, PAGE_READWRITE); if (m_hMapView) { m_hMapSize = dwMaximumSize; ShareMemHeader* smh; smh = (ShareMemHeader*)m_hMapView; if (init) { LARGE_INTEGER tick; KeQueryTickCount(&tick); RtlStringCchPrintfW(smh->m_LockName, sizeof(smh->m_LockName), L"K-%08x-%08x-%08x", PsGetCurrentProcessId(), PsGetCurrentThreadId(), tick.LowPart); if (lpInitialization) smh->m_bResult = lpInitialization(this, lpUserContext); else smh->m_bResult = TRUE; smh->m_bInitialized = TRUE; } else while(1) if (smh->m_bInitialized) break; return smh->m_bResult; } } return FALSE; }
// for pdo NTSTATUS DoPdoPnP(PDEVICE_OBJECT pDevice,PIRP pIrp) { NTSTATUS status = STATUS_SUCCESS; PPdoExt pPdoExt = static_cast<PPdoExt>(pDevice->DeviceExtension); PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(pIrp); switch(pIoStack->MinorFunction) { case IRP_MN_START_DEVICE: // set power state pPdoExt->m_devPowerState = PowerDeviceD0; POWER_STATE state; state.DeviceState = PowerDeviceD0; PoSetPowerState(pDevice,DevicePowerState,state); // set pnp state directly case IRP_MN_STOP_DEVICE: case IRP_MN_QUERY_STOP_DEVICE: case IRP_MN_QUERY_REMOVE_DEVICE: SetNewPnpState(pPdoExt,pIoStack->MinorFunction); break; // check prev state case IRP_MN_CANCEL_REMOVE_DEVICE: if(pPdoExt->m_ulCurrentPnpState == IRP_MN_QUERY_REMOVE_DEVICE) { RestorePnpState(pPdoExt); } break; // the same case IRP_MN_CANCEL_STOP_DEVICE: if(pPdoExt->m_ulCurrentPnpState == IRP_MN_QUERY_STOP_DEVICE) { RestorePnpState(pPdoExt); } break; // remove case IRP_MN_REMOVE_DEVICE: { // delete only if we have reported the device physical removal if(pPdoExt->m_bReportMissing) { SetNewPnpState(pPdoExt,IRP_MN_REMOVE_DEVICE); PDEVICE_OBJECT pFdo = pPdoExt->m_pParentFdo; if(pFdo) { PFdoExt pFdoExt = static_cast<PFdoExt>(pFdo->DeviceExtension); // update fdo's pointer ExAcquireFastMutex(&pFdoExt->m_mutexEnumPdo); pFdoExt->m_pEnumPdo = NULL; ExReleaseFastMutex(&pFdoExt->m_mutexEnumPdo); } // delete device IoDeleteDevice(pDevice); } // if it's present if(pPdoExt->m_bPresent) { // set it as stopped SetNewPnpState(pPdoExt,IRP_MN_STOP_DEVICE); } } break; // query caps case IRP_MN_QUERY_CAPABILITIES: { PDEVICE_CAPABILITIES pCaps = pIoStack->Parameters.DeviceCapabilities.Capabilities; // version check if(pCaps->Version != 1 || pCaps->Size < sizeof(DEVICE_CAPABILITIES)) { status = STATUS_UNSUCCESSFUL; break; } IO_STATUS_BLOCK ioStatus; KEVENT pnpEvent; PDEVICE_OBJECT pTargetObject; PIO_STACK_LOCATION pIrpStack; PIRP pPnpIrp; DEVICE_CAPABILITIES parentCaps; RtlZeroMemory(&parentCaps,sizeof(DEVICE_CAPABILITIES)); parentCaps.Size = sizeof(DEVICE_CAPABILITIES); parentCaps.Version = 1; parentCaps.Address = -1; parentCaps.UINumber = -1; KeInitializeEvent(&pnpEvent,NotificationEvent,FALSE); pTargetObject = IoGetAttachedDeviceReference( static_cast<PFdoExt>(pPdoExt->m_pParentFdo->DeviceExtension)->m_pLowerDevice); // get parent fdo's caps pPnpIrp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,pTargetObject,NULL,0,NULL,&pnpEvent,&ioStatus); if(pPnpIrp == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; } else { pPnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED; pIrpStack = IoGetNextIrpStackLocation(pPnpIrp); RtlZeroMemory(pIrpStack,sizeof(IO_STACK_LOCATION)); pIrpStack->MajorFunction = IRP_MJ_PNP; pIrpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES; pIrpStack->Parameters.DeviceCapabilities.Capabilities = pCaps; status = IoCallDriver(pTargetObject,pPnpIrp); if (status == STATUS_PENDING) { KeWaitForSingleObject(&pnpEvent,Executive,KernelMode,FALSE,NULL); status = ioStatus.Status; } } // dec the ref of the fdo's stack upper device ObDereferenceObject(pTargetObject); // copy the device state RtlCopyMemory(pCaps->DeviceState,parentCaps.DeviceState,(PowerSystemShutdown + 1) * sizeof(DEVICE_POWER_STATE)); // set our own supported device state pCaps->DeviceState[PowerSystemWorking] = PowerDeviceD0; if(pCaps->DeviceState[PowerSystemSleeping1] != PowerDeviceD0) pCaps->DeviceState[PowerSystemSleeping1] = PowerDeviceD3; if(pCaps->DeviceState[PowerSystemSleeping2] != PowerDeviceD0) pCaps->DeviceState[PowerSystemSleeping2] = PowerDeviceD3; if(pCaps->DeviceState[PowerSystemSleeping3] != PowerDeviceD0) pCaps->DeviceState[PowerSystemSleeping3] = PowerDeviceD3; // donot support d1 and d2 pCaps->DeviceD1 = pCaps->DeviceD2 = FALSE; // no wake pCaps->DeviceWake = PowerDeviceUnspecified; pCaps->SystemWake = PowerSystemUnspecified; pCaps->WakeFromD0 = FALSE; pCaps->WakeFromD1 = FALSE; pCaps->WakeFromD2 = FALSE; pCaps->WakeFromD3 = FALSE; // no latency pCaps->D1Latency = 0; pCaps->D2Latency = 0; pCaps->D3Latency = 0; // can eject pCaps->EjectSupported = TRUE; // don't disable pCaps->HardwareDisabled = FALSE; // can be removed pCaps->Removable = TRUE; // don't display surprise remove warning dlg pCaps->SurpriseRemovalOK = TRUE; // no unique id pCaps->UniqueID = FALSE; // nead user action for install pCaps->SilentInstall = FALSE; // bus address pCaps->Address = 0; // ui display number pCaps->UINumber = 0; } break; // query pdo id case IRP_MN_QUERY_ID: { switch(pIoStack->Parameters.QueryId.IdType) { case BusQueryInstanceID: { PVOID buffer = ExAllocatePoolWithTag(PagedPool,10,'suBT'); if(!buffer) { status = STATUS_INSUFFICIENT_RESOURCES; break; } RtlStringCchPrintfW(static_cast<PWCHAR>(buffer),10,L"%04d",0); pIrp->IoStatus.Information = PtrToUlong(buffer); devDebugPrint("\tBusQueryInstanceID\n"); } break; case BusQueryDeviceID: { PVOID buffer = ExAllocatePoolWithTag(PagedPool,PDO_DEVICE_ID_LENGTH,'suBT'); if(!buffer) { status = STATUS_INSUFFICIENT_RESOURCES; break; } RtlCopyMemory(buffer,PDO_DEVICE_ID,PDO_DEVICE_ID_LENGTH); pIrp->IoStatus.Information = PtrToUlong(buffer); devDebugPrint("\tBusQueryDeviceID\n"); } break; case BusQueryHardwareIDs: { PVOID buffer = ExAllocatePoolWithTag(PagedPool,PDO_HARDWARE_IDS_LENGTH,'suBT'); if(!buffer) { status = STATUS_INSUFFICIENT_RESOURCES; break; } RtlCopyMemory(buffer,PDO_HARDWARE_IDS,PDO_HARDWARE_IDS_LENGTH); pIrp->IoStatus.Information = PtrToUlong(buffer); devDebugPrint("\tBusQueryHardwareIDs\n"); } break; case BusQueryCompatibleIDs: { PVOID buffer = ExAllocatePoolWithTag(PagedPool,PDO_COMPATIBLE_IDS_LENGTH,'suBT'); if(!buffer) { status = STATUS_INSUFFICIENT_RESOURCES; break; } RtlCopyMemory(buffer,PDO_COMPATIBLE_IDS,PDO_COMPATIBLE_IDS_LENGTH); pIrp->IoStatus.Information = PtrToUlong(buffer); devDebugPrint("\tBusQueryCompatibleIDs\n"); } break; } } break; // query text case IRP_MN_QUERY_DEVICE_TEXT: { switch (pIoStack->Parameters.QueryDeviceText.DeviceTextType) { case DeviceTextDescription: if(!pIrp->IoStatus.Information) { PVOID buffer = ExAllocatePoolWithTag (PagedPool,PDO_TEXT_LENGTH,'suBT'); if(!buffer) { status = STATUS_INSUFFICIENT_RESOURCES; break; } RtlStringCchPrintfW(static_cast<PWCHAR>(buffer),PDO_TEXT_LENGTH,L"%ws",PDO_TEXT); pIrp->IoStatus.Information = PtrToUlong(buffer); devDebugPrint("\tDeviceTextDescription\n"); } break; default: status = pIrp->IoStatus.Status; break; } } break; // boot resource case IRP_MN_QUERY_RESOURCES: { PCM_RESOURCE_LIST pResList = static_cast<PCM_RESOURCE_LIST>(ExAllocatePoolWithTag(PagedPool, sizeof(CM_RESOURCE_LIST),'suBT')); if(pResList) { // shareed busnumber resource RtlZeroMemory(pResList,sizeof(CM_RESOURCE_LIST)); pResList->Count = 1; pResList->List[0].BusNumber = 0; pResList->List[0].InterfaceType = Internal; pResList->List[0].PartialResourceList.Count = 1; pResList->List[0].PartialResourceList.Revision = 1; pResList->List[0].PartialResourceList.Version = 1; pResList->List[0].PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareShared; pResList->List[0].PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeBusNumber; pResList->List[0].PartialResourceList.PartialDescriptors[0].u.BusNumber.Length = 1; pIrp->IoStatus.Information = PtrToUlong(pResList); } else { status = STATUS_INSUFFICIENT_RESOURCES; } } break; // resource requirements case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: { PIO_RESOURCE_REQUIREMENTS_LIST pList = static_cast<PIO_RESOURCE_REQUIREMENTS_LIST>( ExAllocatePoolWithTag(PagedPool,sizeof(IO_RESOURCE_REQUIREMENTS_LIST),'suBT')); if(pList) { RtlZeroMemory(pList,sizeof(IO_RESOURCE_REQUIREMENTS_LIST)); pList->ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST); pList->AlternativeLists = 1; pList->InterfaceType = InterfaceTypeUndefined; pList->BusNumber = 0; pList->List[0].Version = 1; pList->List[0].Revision = 1; pList->List[0].Count = 1; pList->List[0].Descriptors[0].Option = IO_RESOURCE_PREFERRED; pList->List[0].Descriptors[0].ShareDisposition = CmResourceShareShared; pList->List[0].Descriptors[0].Type = CmResourceTypeBusNumber; pList->List[0].Descriptors[0].u.BusNumber.MaxBusNumber = 0x10; pList->List[0].Descriptors[0].u.BusNumber.Length = 1; pIrp->IoStatus.Information = PtrToUlong(pList); } else { status = STATUS_INSUFFICIENT_RESOURCES; } } break; // bus info case IRP_MN_QUERY_BUS_INFORMATION: { PPNP_BUS_INFORMATION busInfo; busInfo = static_cast<PPNP_BUS_INFORMATION>(ExAllocatePoolWithTag(PagedPool, sizeof(PNP_BUS_INFORMATION),'suBT')); if (busInfo == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; break; } busInfo->BusTypeGuid = GUID_TIAMO_BUS; busInfo->LegacyBusType = Internal; busInfo->BusNumber = 0; pIrp->IoStatus.Information = PtrToUlong(busInfo); } break; // usage case IRP_MN_DEVICE_USAGE_NOTIFICATION: status = STATUS_UNSUCCESSFUL; break; case IRP_MN_EJECT: { // device physical removed pPdoExt->m_bPresent = FALSE; } break; //case IRP_MN_QUERY_INTERFACE: // break; // target relations case IRP_MN_QUERY_DEVICE_RELATIONS: { if(pIoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) { /*switch(pIoStack->Parameters.QueryDeviceRelations.Type) { case EjectionRelations: devDebugPrint("\tquery EjectionRelations\n"); break; case PowerRelations: devDebugPrint("\tquery PowerRelations\n"); break; case RemovalRelations: devDebugPrint("\tquery RemovalRelations\n"); break; case BusDeviceRelation: devDebugPrint("\tquery BusDeviceRelation\n"); break; case SingleBusRelations: devDebugPrint("\tquery SingleBusRelations\n"); break; }*/ break; } PDEVICE_RELATIONS pRel = static_cast<PDEVICE_RELATIONS>(ExAllocatePoolWithTag(PagedPool,sizeof(DEVICE_RELATIONS),'suBT')); if(!pRel) { status = STATUS_INSUFFICIENT_RESOURCES; break; } pRel->Count = 1; pRel->Objects[0] = pDevice; ObReferenceObject(pDevice); status = STATUS_SUCCESS; pIrp->IoStatus.Information = PtrToUlong(pRel); } break; default: status = pIrp->IoStatus.Status; break; } // pdo should complete the irp pIrp->IoStatus.Status = status; IoCompleteRequest (pIrp, IO_NO_INCREMENT); return status; }
NTSTATUS KBFAttachDevicesEx(IN PDRIVER_OBJECT aDriverObject, IN PUNICODE_STRING aRegistryPath) { UNREFERENCED_PARAMETER(aDriverObject); UNREFERENCED_PARAMETER(aRegistryPath); NTSTATUS status = STATUS_SUCCESS; // 遍历所有键盘设备 UNICODE_STRING nameString; static WCHAR name[32] = {0}; ULONG index = 0; PDEVICE_OBJECT deviceObject = NULL; PFILE_OBJECT fileObject = NULL; // 第一个设备 RtlZeroMemory(name, sizeof(WCHAR)*32); RtlStringCchPrintfW(name, 32, L"\\Device\\KeyboardClass%d", index); RtlInitUnicodeString(&nameString, name); // 打开设备对象 status = IoGetDeviceObjectPointer(&nameString, FILE_ALL_ACCESS, &fileObject, &deviceObject); if (NT_SUCCESS(status)) ObDereferenceObject(fileObject); while (deviceObject != NULL) { PDEVICE_OBJECT pFilterDeviceObject = NULL; PDEVICE_OBJECT pLowerDeviceObject = NULL; // 创建一个过滤设备 status = IoCreateDevice(aDriverObject, sizeof(DEVICE_EXTENSION), NULL, deviceObject->DeviceType, deviceObject->Characteristics, FALSE, &pFilterDeviceObject); if (!NT_SUCCESS(status)) { KdPrint(("wykbflt.sys : KBFAttachDevices Couldn't create the Filter Device Object %d\n", index)); break; } pLowerDeviceObject = IoAttachDeviceToDeviceStack(pFilterDeviceObject, deviceObject); if (!pLowerDeviceObject) { KdPrint(("wykbflt.sys : Couldn't attach to Device Object\n")); IoDeleteDevice(pFilterDeviceObject); pFilterDeviceObject = NULL; break; } // 设备扩展 PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)pFilterDeviceObject->DeviceExtension; KBFInitDeviceExtension(deviceExtension, pFilterDeviceObject, deviceObject, pLowerDeviceObject); // 设置过滤操作 pFilterDeviceObject->DeviceType = pLowerDeviceObject->DeviceType; // 要过滤的设备类型跟物理设备类型一致 pFilterDeviceObject->Characteristics = pLowerDeviceObject->Characteristics; pFilterDeviceObject->StackSize = pLowerDeviceObject->StackSize + 1; pFilterDeviceObject->Flags |= pLowerDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE) ; ++index; RtlZeroMemory(name, sizeof(WCHAR)*32); RtlStringCchPrintfW(name, 32, L"\\Device\\KeyboardClass%d", index); RtlInitUnicodeString(&nameString, name); // 打开设备对象 status = IoGetDeviceObjectPointer(&nameString, FILE_ALL_ACCESS, &fileObject, &deviceObject); if (NT_SUCCESS(status)) ObDereferenceObject(fileObject); else break; } return STATUS_SUCCESS; }
_Must_inspect_result_ NTSTATUS WDF_LIBRARY_REGISTER_CLIENT( __in PWDF_BIND_INFO Info, __deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals, __deref_inout PVOID * Context ) { NTSTATUS status = STATUS_INVALID_PARAMETER; PFX_DRIVER_GLOBALS pFxDriverGlobals; WCHAR insertString[EVTLOG_MESSAGE_SIZE]; ULONG rawData[RAW_DATA_SIZE]; PCLIENT_INFO clientInfo = NULL; __Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) ": enter\n")); clientInfo = (PCLIENT_INFO)*Context; *Context = NULL; ASSERT(Info->Version.Major == WdfLibraryInfo.Version.Major); // // NOTE: If the currently loaded library < drivers minor version fail the load // instead of binding to a lower minor version. The reason for that if there // is a newer API or new contract change made the driver shouldn't be using older // API than it was compiled with. // if (Info->Version.Minor > WdfLibraryInfo.Version.Minor) { status = RtlStringCchPrintfW(insertString, RTL_NUMBER_OF(insertString), L"Driver Version: %d.%d Kmdf Lib. Version: %d.%d", Info->Version.Major, Info->Version.Minor, WdfLibraryInfo.Version.Major, WdfLibraryInfo.Version.Minor); if (!NT_SUCCESS(status)) { __Print(("ERROR: RtlStringCchPrintfW failed with Status 0x%x\n", status)); return status; } rawData[0] = Info->Version.Major; rawData[1] = Info->Version.Minor; rawData[2] = WdfLibraryInfo.Version.Major; rawData[3] = WdfLibraryInfo.Version.Minor; LibraryLogEvent(FxLibraryGlobals.DriverObject, WDFVER_MINOR_VERSION_NOT_SUPPORTED, STATUS_OBJECT_TYPE_MISMATCH, insertString, rawData, sizeof(rawData) ); // // this looks like the best status to return // return STATUS_OBJECT_TYPE_MISMATCH; } status = FxLibraryCommonRegisterClient(Info, WdfDriverGlobals, clientInfo); if (NT_SUCCESS(status)) { // // The context will be a pointer to FX_DRIVER_GLOBALS // *Context = GetFxDriverGlobals(*WdfDriverGlobals); // // Set the WDF_BIND_INFO structure pointer in FxDriverGlobals // pFxDriverGlobals = GetFxDriverGlobals(*WdfDriverGlobals); pFxDriverGlobals->WdfBindInfo = Info; } return status; }