Image File Disk Driver Blocking on Filter Manager

Good day to All,

I’ve a Windows 2000 virtual disk driver which redirects SCSI reads and writes to Zw[Read|Write]File().

Attaching the image file as a disk in the Windows 7 installation environment works. I can begin to install Windows 7 to the image file. But part of the way through the installation, the virtual disk’s I/O hangs. The IRPs have all been queued to the virtual disk’s own thread. Here’s where it’s blocked:

84f1f688 8acbfb15 nt!KiSwapContext+0x26
84f1f6c0 8acbe403 nt!KiSwapThread+0x266
84f1f6e8 8acb82cf nt!KiCommitThreadWait+0x1df
84f1f764 8ac837b7 nt!KeWaitForSingleObject+0x393
84f1f7a0 8aceca4e nt!MiWaitForCollidedFaultComplete+0x135
84f1f804 8ace193f nt!MiResolveTransitionFault+0x3d9
84f1f888 8acd7d56 nt!MiDispatchFault+0x61f
84f1f914 8ac975f8 nt!MmAccessFault+0x157c
84f1f914 83e816a4 nt!KiTrap0E+0xdc
84f1f99c 83e7bb35 fileinfo!FIStreamGet
84f1fa04 83e48aeb fileinfo!FIPreReadWriteCallback+0xf1
84f1fa70 83e4b17b fltmgr!FltpPerformPreCallbacks+0x34d
84f1fa88 83e5dc37 fltmgr!FltpPassThroughFastIo+0x3d
84f1facc 8aea0b32 fltmgr!FltpFastIoRead+0x163
84f1fb60 8ac9442a nt!NtReadFile+0x2d5
84f1fb60 8ac92ef9 nt!KiFastCallEntry+0x12a
84f1fbfc 840086c8 nt!ZwReadFile+0x11
84f1fc44 84004612 wvblk32!WvFilediskIo_+0x158 [c:\src\winvblock\src\winvblock\filedisk\filedisk.c @ 358]
84f1fc68 84005a4b wvblk32!WvlDiskIo+0x32 [c:\src\winvblock\src\winvblock\libdisk\libdisk.c @ 345]
84f1fcc8 840053ef wvblk32!WvlDiskScsiReadWrite_+0x3cb [c:\src\winvblock\src\winvblock\libdisk\scsi.c @ 225]
84f1fd00 84008d20 wvblk32!WvlDiskScsi+0xef [c:\src\winvblock\src\winvblock\libdisk\scsi.c @ 424]
84f1fd30 84009567 wvblk32!WvFilediskThread_+0x110 [c:\src\winvblock\src\winvblock\filedisk\filedisk.c @ 643]
84f1fd50 8ae5f66d wvblk32!WvlThreadWrapper+0xb7 [c:\src\winvblock\src\winvblock\libthread\libthread.c @ 87]
84f1fd90 8ad110d9 nt!PspSystemThreadStartup+0x9e
00000000 00000000 nt!KiThreadStartup+0x19

When I look at the queue, there are a few IRPs in there, so the installation process(es) might have an asynchronous aspect.

I am unsure as to why the driver is blocking, but my guess would be that the filter manager has already locked a lock once for the virtual disc I/O, then the lock is still locked when this driver is attempting the “inner” I/O to the image file.

Does anyone have an experience, suggestions, or wisdom that might help the driver to prevent this blocking? The driver is intended to support >= Windows 2000.

Thank you for your attention!

You have a collided page fault, so this thread is waiting for the in page
operation to happen in another thread. The question then is why the thread
servicing the page fault is it not making forward progress. Have you found
the other thread yet? !stacks 2 can help.

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

wrote in message news:xxxxx@ntdev…

Good day to All,

I’ve a Windows 2000 virtual disk driver which redirects SCSI reads and
writes to Zw[Read|Write]File().

Attaching the image file as a disk in the Windows 7 installation environment
works. I can begin to install Windows 7 to the image file. But part of the
way through the installation, the virtual disk’s I/O hangs. The IRPs have
all been queued to the virtual disk’s own thread. Here’s where it’s
blocked:

84f1f688 8acbfb15 nt!KiSwapContext+0x26
84f1f6c0 8acbe403 nt!KiSwapThread+0x266
84f1f6e8 8acb82cf nt!KiCommitThreadWait+0x1df
84f1f764 8ac837b7 nt!KeWaitForSingleObject+0x393
84f1f7a0 8aceca4e nt!MiWaitForCollidedFaultComplete+0x135
84f1f804 8ace193f nt!MiResolveTransitionFault+0x3d9
84f1f888 8acd7d56 nt!MiDispatchFault+0x61f
84f1f914 8ac975f8 nt!MmAccessFault+0x157c
84f1f914 83e816a4 nt!KiTrap0E+0xdc
84f1f99c 83e7bb35 fileinfo!FIStreamGet
84f1fa04 83e48aeb fileinfo!FIPreReadWriteCallback+0xf1
84f1fa70 83e4b17b fltmgr!FltpPerformPreCallbacks+0x34d
84f1fa88 83e5dc37 fltmgr!FltpPassThroughFastIo+0x3d
84f1facc 8aea0b32 fltmgr!FltpFastIoRead+0x163
84f1fb60 8ac9442a nt!NtReadFile+0x2d5
84f1fb60 8ac92ef9 nt!KiFastCallEntry+0x12a
84f1fbfc 840086c8 nt!ZwReadFile+0x11
84f1fc44 84004612 wvblk32!WvFilediskIo_+0x158
[c:\src\winvblock\src\winvblock\filedisk\filedisk.c @ 358]
84f1fc68 84005a4b wvblk32!WvlDiskIo+0x32
[c:\src\winvblock\src\winvblock\libdisk\libdisk.c @ 345]
84f1fcc8 840053ef wvblk32!WvlDiskScsiReadWrite_+0x3cb
[c:\src\winvblock\src\winvblock\libdisk\scsi.c @ 225]
84f1fd00 84008d20 wvblk32!WvlDiskScsi+0xef
[c:\src\winvblock\src\winvblock\libdisk\scsi.c @ 424]
84f1fd30 84009567 wvblk32!WvFilediskThread_+0x110
[c:\src\winvblock\src\winvblock\filedisk\filedisk.c @ 643]
84f1fd50 8ae5f66d wvblk32!WvlThreadWrapper+0xb7
[c:\src\winvblock\src\winvblock\libthread\libthread.c @ 87]
84f1fd90 8ad110d9 nt!PspSystemThreadStartup+0x9e
00000000 00000000 nt!KiThreadStartup+0x19

When I look at the queue, there are a few IRPs in there, so the installation
process(es) might have an asynchronous aspect.

I am unsure as to why the driver is blocking, but my guess would be that the
filter manager has already locked a lock once for the virtual disc I/O, then
the lock is still locked when this driver is attempting the “inner” I/O to
the image file.

Does anyone have an experience, suggestions, or wisdom that might help the
driver to prevent this blocking? The driver is intended to support >=
Windows 2000.

Thank you for your attention!

Ah, I see (a bit more). Thanks! I have no idea how to find the other thread, but will try to find out! There are a lot of threads. :S

Well, well… What have we here…?: WinPEpge.sys

A page-file is created on the virtual disk. That explains that. Cannot page in while already blocked doing I/O to the virtual disk, I suppose. Hmm…

Thanks again!

What is the preferred method for facilitating paging where the page I/O will pass through Zw[ReadWrite]File() ? Is there one? Since ZwXxxFile() could be serviced by any number of drivers, and any driver might have pageable sections, it doesn’t seem at all likely that there’s a way to instruct Windows not to page particular drivers’ memory out to a device which… Depends on those drivers.

This has me wondering if the native .VHD support in Windows 7 builds a map of sectors for the .VHD file and uses those, instead of file I/O (which might pass through non-disk drivers which pageable sections).

Would anyone care to share how they have addressed this paging predicament in their own virtual disk drivers? If so, then I’d certainly appreciate it.

Well first paging I/O doesn’t pass through the Zw[ReadWrite]File()
calls. Second drivers have to indicate they are in the paging path and
then the system will not page them. Take a look at the disk filter
example in the WDK to see what needs to be done.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

“xxxxx@YRDSB.Edu.On.Ca” wrote in
message news:xxxxx@ntdev:

> What is the preferred method for facilitating paging where the page I/O will pass through Zw[ReadWrite]File() ? Is there one? Since ZwXxxFile() could be serviced by any number of drivers, and any driver might have pageable sections, it doesn’t seem at all likely that there’s a way to instruct Windows not to page particular drivers’ memory out to a device which… Depends on those drivers.
>
> This has me wondering if the native .VHD support in Windows 7 builds a map of sectors for the .VHD file and uses those, instead of file I/O (which might pass through non-disk drivers which pageable sections).
>
> Would anyone care to share how they have addressed this paging predicament in their own virtual disk drivers? If so, then I’d certainly appreciate it.

Thanks, Don.

I apologize. What I meant was that the paging I/O to my virtual disk would have to eventually be serviced by Zw[Read|Write]File(), so I’m wondering if anyone has a similar situation that they’ve dealt with “properly” or at least successfully.

  • Virtual disk depends on Zw[Read|Write]File()
  • Zw[Read|Write]File() depends on FS drivers, filters, etc.
  • One of these has a piece that gets paged out
  • A time comes when that piece needs to be paged back in… From the virtual disk

I’ll have a look at the sample you’ve recommended.

It’s not very typical to have a paging file on the disk in this type of
driver. And by not having a paging file on your virtual disk you break the
circular dependency (i.e. you trigger a paging I/O to a different disk). I
don’t have much experience with them, but according to this article even
native boot VHDs don’t support having a paging file on them:

http://technet.microsoft.com/en-us/library/dd440865(WS.10).aspx

If you do want to support this for some reason, you have two issues:

  1. Determining if a particular I/O is paging I/O or not at the volume/disk
    layer. You’ll either need a file system filter assist on this or you’ll need
    to keep track of the sectors that make up the paging file

  2. Sending paging I/Os to the FSD to deal with the paging operations (i.e.
    IRP_MJ_READ requests with the IRP_PAGING_IO bit set). You can’t do this with
    the Zw APIs and paging I/O has some special rules that you’ll need to figure
    out and obey.

If I were you I’d spend some time researching to see if I could avoid
getting the paging file on the virtual disk. If it’s possible to hook into
whatever support they’re using for native boot you’ll be much happier.

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

wrote in message news:xxxxx@ntdev…

Thanks, Don.

I apologize. What I meant was that the paging I/O to my virtual disk would
have to eventually be serviced by Zw[Read|Write]File(), so I’m wondering if
anyone has a similar situation that they’ve dealt with “properly” or at
least successfully.

  • Virtual disk depends on Zw[Read|Write]File()
  • Zw[Read|Write]File() depends on FS drivers, filters, etc.
  • One of these has a piece that gets paged out
  • A time comes when that piece needs to be paged back in… From the virtual
    disk

I’ll have a look at the sample you’ve recommended.

That was a fantastic response, Scott, and I truly appreciate it. For now, the driver can live with the same limitations as you point out in Microsoft’s article for .VHDs. A paging feature can wait for later, if it’s even possible.

For your #1, keeping track of the sectors that make up the paging file seems like it could be [at least a bit of] a memory burden. For your #2, I’m not 100% sure what I’d use instead of Zw[Read|Write]File(), so that’d take some thinking. Back-burner, then!

>For your #1, keeping track of the sectors that make up the paging file seems >like it could be [at least a bit of] a memory burden. For your #2, I’m not >100% sure what I’d use instead of Zw[Read|Write]File(), so that’d take some >thinking.
In general, your design is not good. Virtual disk works in the storage stack and should perform disk block, not file system, I/Os. Otherwise, the driver may get recursive operations which happened to you.

Igor Sharovar

Thanks for the feed-back, Igor.

Even admitting what you pointed out, I’m not sure how else to provide a virtual disk for an image file located on a network filesystem. Microsoft appears to support .VHDs over SMB; this is a similar feature, in my opinion.

But alas, even by preventing page-files on the virtual disk, the driver still gets stuck:

kd> !thread 80de0338
THREAD 80de0338 Cid 0004.067c Teb: 00000000 Win32Thread: 00000000 WAIT: (Executive) KernelMode Non-Alertable
870e68bc NotificationEvent
Not impersonating
DeviceMap 84c060a8
Owning Process 807b23b8 Image: System
Wait Start TickCount 235043 Ticks: 4 (0:00:00:00.062)
Context Switch Count 26548
UserTime 00:00:00.000
KernelTime 00:00:21.203
Win32 Start Address wvblk32!WvlThreadWrapper (0x840144e0)
Stack Init 870e6fd0 Current 870e6798 Base 870e7000 Limit 870e4000 Call 0
Priority 8 BasePriority 8 PriorityDecrement 0 IoPriority 2 PagePriority 5
ChildEBP RetAddr Args to Child
870e67b0 8acc2b15 80de0338 00000000 8ad7dd20 nt!KiSwapContext+0x26 (FPO: [Uses EBP] [0,0,4])
870e67e8 8acc1403 80de03f8 80de0338 870e68bc nt!KiSwapThread+0x266
870e6810 8acbb2cf 80de0338 80de03f8 00000063 nt!KiCommitThreadWait+0x1df
870e688c 8ace0bba 870e68bc 00000000 00000000 nt!KeWaitForSingleObject+0x393
870e68f0 83f55a22 80df7e40 00001c00 00000001 nt!CcCanIWrite+0x1d6
870e6a18 83e52fec 80df7e40 8096cfa4 00001c00 Ntfs!NtfsCopyWriteA+0x46 (FPO: [Non-Fpo])
870e6a4c 83e531bb 00000004 00000000 8096cf9c fltmgr!FltpPerformFastIoCall+0x22e (FPO: [Non-Fpo])
870e6a78 83e65dcf 000e6a9c 80df7e40 83e65c6c fltmgr!FltpPassThroughFastIo+0x7d (FPO: [Non-Fpo])
870e6abc 8ae923f7 80df7e40 870e6b04 00001c00 fltmgr!FltpFastIoWrite+0x163 (FPO: [Non-Fpo])
870e6b60 8ac9742a 80a19d90 00000000 00000000 nt!NtWriteFile+0x342
870e6b60 8ac96895 80a19d90 00000000 00000000 nt!KiFastCallEntry+0x12a (FPO: [0,3] TrapFrame @ 870e6b8c)
870e6bfc 840136c4 800009e4 00000000 00000000 nt!ZwWriteFile+0x11 (FPO: [9,0,0])
870e6c44 8400f612 80e0ef18 00000001 001c3d88 wvblk32!WvFilediskIo_+0x124 (FPO: [Non-Fpo]) (CONV: stdcall) [c:\src\winvblock\src\winvblock\filedisk\filedisk.c @ 347]
870e6c68 84010ae0 80e0ef18 00000001 001c3d88 wvblk32!WvlDiskIo+0x32 (FPO: [Non-Fpo]) (CONV: stdcall) [c:\src\winvblock\src\winvblock\libdisk\libdisk.c @ 345]
870e6cc8 8401040f 80e0ef18 80e540a8 80e918b4 wvblk32!WvlDiskScsiReadWrite_+0x440 (FPO: [Non-Fpo]) (CONV: stdcall) [c:\src\winvblock\src\winvblock\libdisk\scsi.c @ 239]
870e6d00 84013d50 80e0ee08 80e540a8 80e0ef18 wvblk32!WvlDiskScsi+0xef (FPO: [Non-Fpo]) (CONV: stdcall) [c:\src\winvblock\src\winvblock\libdisk\scsi.c @ 424]
870e6d30 84014597 80e0ef80 8401775c 8401775c wvblk32!WvFilediskThread_+0x110 (FPO: [Non-Fpo]) (CONV: stdcall) [c:\src\winvblock\src\winvblock\filedisk\filedisk.c @ 644]
870e6d50 8ae6266d 80e0ef80 41c1faf1 00000000 wvblk32!WvlThreadWrapper+0xb7 (FPO: [Non-Fpo]) (CONV: stdcall) [c:\src\winvblock\src\winvblock\libthread\libthread.c @ 87]
870e6d90 8ad140d9 840144e0 80e0ef80 00000000 nt!PspSystemThreadStartup+0x9e
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x19

I don’t see any other threads waiting in the list in the DISPATCHER_HEADER @ 0x870E68BC.

You again stuck on file system level.
Usually the lower level interface of virtual disks connected directly to drivers which serves hardware. For example, I worked on a project which designed a virtual disk. The virtual disk keeps all data on network server. All communication done by using UDP. The lower edge of the virtual disk was connected to a NDIS Protocol driver, which was part of the project.
You probably could develop some stuff for network file system, which is already represented by a virtual disk. But it could be done either on user mode or the file system filters. You are trying to develop another virtual disk which is resizing below the file system on which you want to communicate. It is not good design.

Igor Sharovar

>In general, your design is not good. Virtual disk works in the storage

stack and should perform disk block, not file system, I/Os. Otherwise, >the
driver may get recursive operations which happened to you.

This is a file backed disk, I’d say it’s a bad design to NOT go through the
file system. Doing block I/O would means that you would bypass the file
system and all file system filters, which means that you lose the ability to
do things like encrypt/compress the disk. Try playing with the VHD support
in Windows, it is effectively the same thing that the OP is trying to
accomplish (and it does in fact use the FSD to perform I/O on its disk
file).

-scott


Scott Noone
Consulting Associate
OSR Open Systems Resources, Inc.
http://www.osronline.com

You’re trying to do a cached I/O but the cache is full so you block. Imagine
the scenario, the cache is full so the Cache Manager sends a non-cached I/O
to the disk with data from the cache to make some room. Your driver turns
this into a cached I/O, which blocks waiting for room in the cache.

The solution is that you need to use non-cached I/O when you write to the
file backing your disk.

-scott


Scott Noone
Consulting Associate
OSR Open Systems Resources, Inc.
http://www.osronline.com

Hope to see you at the next OSR kernel debugging class February 14th in
Columbia, MD!

wrote in message news:xxxxx@ntdev…

Thanks for the feed-back, Igor.

Even admitting what you pointed out, I’m not sure how else to provide a
virtual disk for an image file located on a network filesystem. Microsoft
appears to support .VHDs over SMB; this is a similar feature, in my opinion.

But alas, even by preventing page-files on the virtual disk, the driver
still gets stuck:

kd> !thread 80de0338
THREAD 80de0338 Cid 0004.067c Teb: 00000000 Win32Thread: 00000000 WAIT:
(Executive) KernelMode Non-Alertable
870e68bc NotificationEvent
Not impersonating
DeviceMap 84c060a8
Owning Process 807b23b8 Image: System
Wait Start TickCount 235043 Ticks: 4 (0:00:00:00.062)
Context Switch Count 26548
UserTime 00:00:00.000
KernelTime 00:00:21.203
Win32 Start Address wvblk32!WvlThreadWrapper (0x840144e0)
Stack Init 870e6fd0 Current 870e6798 Base 870e7000 Limit 870e4000 Call 0
Priority 8 BasePriority 8 PriorityDecrement 0 IoPriority 2 PagePriority 5
ChildEBP RetAddr Args to Child
870e67b0 8acc2b15 80de0338 00000000 8ad7dd20 nt!KiSwapContext+0x26 (FPO:
[Uses EBP] [0,0,4])
870e67e8 8acc1403 80de03f8 80de0338 870e68bc nt!KiSwapThread+0x266
870e6810 8acbb2cf 80de0338 80de03f8 00000063 nt!KiCommitThreadWait+0x1df
870e688c 8ace0bba 870e68bc 00000000 00000000
nt!KeWaitForSingleObject+0x393
870e68f0 83f55a22 80df7e40 00001c00 00000001 nt!CcCanIWrite+0x1d6
870e6a18 83e52fec 80df7e40 8096cfa4 00001c00 Ntfs!NtfsCopyWriteA+0x46
(FPO: [Non-Fpo])
870e6a4c 83e531bb 00000004 00000000 8096cf9c
fltmgr!FltpPerformFastIoCall+0x22e (FPO: [Non-Fpo])
870e6a78 83e65dcf 000e6a9c 80df7e40 83e65c6c
fltmgr!FltpPassThroughFastIo+0x7d (FPO: [Non-Fpo])
870e6abc 8ae923f7 80df7e40 870e6b04 00001c00 fltmgr!FltpFastIoWrite+0x163
(FPO: [Non-Fpo])
870e6b60 8ac9742a 80a19d90 00000000 00000000 nt!NtWriteFile+0x342
870e6b60 8ac96895 80a19d90 00000000 00000000 nt!KiFastCallEntry+0x12a
(FPO: [0,3] TrapFrame @ 870e6b8c)
870e6bfc 840136c4 800009e4 00000000 00000000 nt!ZwWriteFile+0x11 (FPO:
[9,0,0])
870e6c44 8400f612 80e0ef18 00000001 001c3d88 wvblk32!WvFilediskIo_+0x124
(FPO: [Non-Fpo]) (CONV: stdcall)
[c:\src\winvblock\src\winvblock\filedisk\filedisk.c @ 347]
870e6c68 84010ae0 80e0ef18 00000001 001c3d88 wvblk32!WvlDiskIo+0x32 (FPO:
[Non-Fpo]) (CONV: stdcall) [c:\src\winvblock\src\winvblock\libdisk\libdisk.c
@ 345]
870e6cc8 8401040f 80e0ef18 80e540a8 80e918b4
wvblk32!WvlDiskScsiReadWrite_+0x440 (FPO: [Non-Fpo]) (CONV: stdcall)
[c:\src\winvblock\src\winvblock\libdisk\scsi.c @ 239]
870e6d00 84013d50 80e0ee08 80e540a8 80e0ef18 wvblk32!WvlDiskScsi+0xef
(FPO: [Non-Fpo]) (CONV: stdcall)
[c:\src\winvblock\src\winvblock\libdisk\scsi.c @ 424]
870e6d30 84014597 80e0ef80 8401775c 8401775c
wvblk32!WvFilediskThread_+0x110 (FPO: [Non-Fpo]) (CONV: stdcall)
[c:\src\winvblock\src\winvblock\filedisk\filedisk.c @ 644]
870e6d50 8ae6266d 80e0ef80 41c1faf1 00000000 wvblk32!WvlThreadWrapper+0xb7
(FPO: [Non-Fpo]) (CONV: stdcall)
[c:\src\winvblock\src\winvblock\libthread\libthread.c @ 87]
870e6d90 8ad140d9 840144e0 80e0ef80 00000000
nt!PspSystemThreadStartup+0x9e
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x19

I don’t see any other threads waiting in the list in the DISPATCHER_HEADER @
0x870E68BC.

>This is a file backed disk, I’d say it’s a bad design to NOT go through the file >system. Doing block I/O would means that you would bypass the file system >and all file system filters, which means that you lose the ability to do things >like encrypt/compress the disk. Try playing with the VHD support in Windows, >it is effectively the same thing that the OP is trying to accomplish (and it does >in fact use the FSD to perform I/O on its disk file).

I was confused with OP design where he implemented virtual disk. I thought he implemented a virtual disk in storage stack because in beginning of the post he mentioned
"I’ve a Windows 2000 virtual disk driver which redirects SCSI reads and writes to Zw[Read|Write]File(). "
It means means that his virtual disk performs block I/O. And doing file operations from storage stack is not good things.
I was mention the project, I worked, which supports also Windows 2000. And VHD is not available in Win2000.

Igor Sharovar

Igor:

The driver I was having troubles with is part of a [very] small suite of drivers. One of the drivers is an AoE driver and the other provides read-only virtual disks over HTTP. I agree with you that there are some good ways to have virtual disks over the network besides an image file on a share. I thank you for sharing your relevant experiences.

As an aside and in regards to “VHD is not available in Win2000,” that’s a goal for this driver. Flat .VHDs (a sector-by-sector image with a footer) should currently be supported by this driver. It’s difficult to avoid the block I/O -> file I/O in this scenario, but I certainly welcome suggestions, such as the already-mentioned sector map for the file (though it’d have to be a fixed size and’d have to have a fixed position and’d have to be determined as being on a non-network FS).

Scott:

Thank you (and OSR)[1] once more for your x-ray vision; FILE_NO_INTERMEDIATE_BUFFERING certainly does the trick. In retrospect, it seems silly that it was previously missing.

Yay, OSR’s NTDEV!

  • Shao Miller

[1] https://github.com/Sha0/winvblock/commit/75615a1c90f817ac756883910f0f3c19daa333c4