https://bugs.winehq.org/show_bug.cgi?id=48986 --- Comment #1 from Anastasius Focht <focht(a)gmx.net> --- Hello folks, some tidbits on why this API is called. Currently Wine doesn't implement the concept of Windows kernel IRQL (priority level) by design. IRQL is a pretty important topic for all code that executes in kernel space. Kernel drivers need to follow general rules when/what code can be called, depending on current IRQL, usage of synchronization primitives etc. I'm not going repeat common knowledge here since you can read a lot about this topic in various online resources. Windows x86_64 stores the current IRQL in control register CR8. A read of CR8 register equals to 'KeGetCurrentIrql()'. With Vanguard's 'vgk.sys' you'll see a lot of this: --- snip --- ... 00c8:trace:seh:raise_exception code=c0000096 flags=0 addr=0x11233c1 ip=11233c1 tid=00c8 00c8:trace:seh:raise_exception rax=000000005fd75f32 rbx=00000000000fccc8 rcx=0000000000000000 rdx=000000000000004a 00c8:trace:seh:raise_exception rsi=0000000000cef8dc rdi=00000000000fccc8 rbp=0000000000cef660 rsp=0000000000cef560 00c8:trace:seh:raise_exception r8=0000000000e2e320 r9=0000000000ceee92 r10=0000000000000000 r11=0000000000cef7b0 00c8:trace:seh:raise_exception r12=00000000000fcb60 r13=00007fffffea4000 r14=0000000000000004 r15=0000000000000000 00c8:trace:seh:call_vectored_handlers calling handler at 0x22ce30 code=c0000096 flags=0 00c8:trace:int:emulate_instruction mov cr8,rax at 11233c1 00c8:trace:int:vectored_handler next instruction rip=11233c5 00c8:trace:int:vectored_handler rax=0000000000000000 rbx=00000000000fccc8 rcx=0000000000000000 rdx=000000000000004a 00c8:trace:int:vectored_handler rsi=0000000000cef8dc rdi=00000000000fccc8 rbp=0000000000cef660 rsp=0000000000cef560 00c8:trace:int:vectored_handler r8=0000000000e2e320 r9=0000000000ceee92 r10=0000000000000000 r11=0000000000cef7b0 00c8:trace:int:vectored_handler r12=00000000000fcb60 r13=00000000ffea4000 r14=0000000000000004 r15=0000000000000000 00c8:trace:seh:call_vectored_handlers handler at 0x22ce30 returned ffffffff ... --- snip --- Disassembly from exception site (with obfuscation in between): --- snip --- ... 00000000011233C1 | mov rax,cr8 | KeGetCurrentIrql 00000000011233C5 | clc | 00000000011233C6 | cmp edx,ebx | 00000000011233C8 | sub r15d,r15d | 00000000011233CB | cmp cl,EE | 00000000011233CE | test al,al | >= APC_LEVEL? 00000000011233D0 | jne vgk.E1F250 | 00000000011233D6 | mov rax,FFFFF78000000014 | PASSIVE_LEVEL 00000000011233E0 | lea rdx,qword ptr ss:[rsp+68] | 00000000011233E5 | not cx | 00000000011233E8 | movsxd rcx,r8d | 00000000011233EB | lea rcx,qword ptr ss:[rsp+60] | 00000000011233F0 | jmp vgk.11233F5 | 00000000011233F5 | mov rax,qword ptr ds:[rax] | 00000000011233F8 | mov qword ptr ss:[rsp+60],rax | 00000000011233FD | call qword ptr ds:[<&RtlSystemTime...>] | ... 0000000000E1F250 | mov rcx,qword ptr ss:[rbp+130] | 0000000000E1F257 | xor rcx,rsp | 0000000000E1F25A | call vgk.E2D670 | 0000000000E1F25F | add rsp,248 | 0000000000E1F266 | pop r15 | 0000000000E1F268 | pop r14 | 0000000000E1F26A | pop r13 | 0000000000E1F26C | pop r12 | 0000000000E1F26E | pop rdi | 0000000000E1F26F | pop rsi | 0000000000E1F270 | pop rbx | 0000000000E1F271 | pop rbp | 0000000000E1F272 | ret | ... --- snip --- It's used in the logging sequence, when the driver wants to write encrypted data to log file. I've found a kernel driver on github that shows how it's intended to be used in this case: https://github.com/veracrypt/VeraCrypt/blob/94d3a1919c8eee4d7bfd7280ee496447... --- snip --- NTSTATUS SendDeviceIoControlRequest (PDEVICE_OBJECT deviceObject, ULONG ioControlCode, void *inputBuffer, int inputBufferSize, void *outputBuffer, int outputBufferSize) { IO_STATUS_BLOCK ioStatusBlock; NTSTATUS status; PIRP irp; KEVENT event; if ((KeGetCurrentIrql() >= APC_LEVEL) || VC_KeAreAllApcsDisabled()) { SendDeviceIoControlRequestWorkItemArgs args; PIO_WORKITEM workItem = IoAllocateWorkItem (RootDeviceObject); if (!workItem) return STATUS_INSUFFICIENT_RESOURCES; args.deviceObject = deviceObject; args.ioControlCode = ioControlCode; args.inputBuffer = inputBuffer; args.inputBufferSize = inputBufferSize; args.outputBuffer = outputBuffer; args.outputBufferSize = outputBufferSize; KeInitializeEvent (&args.WorkItemCompletedEvent, SynchronizationEvent, FALSE); IoQueueWorkItem (workItem, SendDeviceIoControlRequestWorkItemRoutine, DelayedWorkQueue, &args); KeWaitForSingleObject (&args.WorkItemCompletedEvent, Executive, KernelMode, FALSE, NULL); IoFreeWorkItem (workItem); return args.Status; } KeInitializeEvent (&event, NotificationEvent, FALSE); irp = IoBuildDeviceIoControlRequest (ioControlCode, deviceObject, inputBuffer, inputBufferSize, outputBuffer, outputBufferSize, FALSE, &event, &ioStatusBlock); if (!irp) return STATUS_INSUFFICIENT_RESOURCES; ObReferenceObject (deviceObject); status = IoCallDriver (deviceObject, irp); if (status == STATUS_PENDING) { KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL); status = ioStatusBlock.Status; } ObDereferenceObject (deviceObject); return status; } --- snip --- Wine currently returns hard-coded PASSIVE_LEVEL = KIRQL(0). https://source.winehq.org/git/wine.git/blob/26b26a2e0efcb776e7b0115f15580d25... This is ok and the code seems to work as intended. There will be cases in future where we probably need a tracking of "fake" KIRQL and sync with CR8 emulation. If we would return APC_LEVEL = KIRQL(1) or even DISPATCH_LEVEL = KIRQL(2) in CR8 emulation, the call to KeAreAllApcsDisabled() wouldn't be made and no logging functions would be executed. Regards -- Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.