How to prevent BSOD while closing Application

Hello to all.
I hope I am correct here and someone can help me…

I wrote a win32 console application, which is communicating with wdm audio driver via cancle safe queue.
I installed two instances of the wdm driver to communicate with them in the application.
To communicate with the drivers in the application software I create two thread instances.

In the Thread I do following:

DWORD Class::Thread(argv)
{
Handle hFile = CreateFile(argv…);
DeviceIoControl(hFile);
while()
{
create Handle
ReadFileEx(Handle);
}
CancleIO(hFile);
CloseHandle(hFile);
return 0;
}

In the main() I create the instances:
int main()
{
vector<Thread> threadVector;

for(size_t i = 0; i < NumberOfDevices, i++)
{
Thread* thread = new Thread(…, DevicePathString);
threadVector.push_back(thread);
}



for(size_t i = 0; i < NumberOfDevices, i++)
{
threadVector.at(i)->join();
}
for(size_t i = 0; i < NumberOfDevices, i++)
{
threadVector.pop_back();
}



return 0;
}

The Application is running as expected.
But, when I close the application I get an BSOD.
When I have only one thread instance the application works without BSOD.
So the application runs and closes as expected.
But with two thread instances I always get a BSOD.
Can some help me to solve the problem?

Thank you for reading :smile:
Best Regards

You need to provide the !analyze -v output.

Hello Scott,
thank you for answer.

Here the output of !analyze -v:
SYSTEM_THREAD_EXCEPTION_NOT_HANDLED (7e)
This is a very common bugcheck. Usually the exception address pinpoints
the driver/function that caused the problem. Always note this address
as well as the link date of the driver/image that contains this address.
Arguments:
Arg1: ffffffffc0000005, The exception code that was not handled
Arg2: 0000000000760074, The address that the exception occurred at
Arg3: ffffd000fa8b5838, Exception Record Address
Arg4: ffffd000fa8b5050, Context Record Address

Debugging Details:

KEY_VALUES_STRING: 1

Key  : AV.Fault
Value: Execute




FAULTING_IP:
+0
00000000`00760074 ?? ???

EXCEPTION_RECORD: ffffd000fa8b5838 – (.exr 0xffffd000fa8b5838)
ExceptionAddress: 0000000000760074
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000008
Parameter[1]: 0000000000760074
Attempt to execute non-executable address 0000000000760074

CONTEXT: ffffd000fa8b5050 – (.cxr 0xffffd000fa8b5050)
rax=0000000000760074 rbx=0000000000000001 rcx=ffffe001b1c09ca0
rdx=ffffe001b37a3010 rsi=ffffe001b1c09df0 rdi=ffffc0016c4b8640
rip=0000000000760074 rsp=ffffd000fa8b5a78 rbp=0000000000000000
r8=ffffc0016c4b8640 r9=00000000000007ff r10=0000000000000565
r11=fffff80073276000 r12=0000000000000200 r13=ffffe001b37a3010
r14=ffffe001b1c09ca0 r15=0000000000000000
iopl=0 nv up ei pl zr na po nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00010246
0000000000760074 ?? ??? Resetting default scope ... ... ... FOLLOWUP_IP: portcls!PnpStartDevice+b5 fffff801298df305 8be8 mov ebp,eax

BUGCHECK_STR: AV

EXECUTE_ADDRESS: 760074

FAILED_INSTRUCTION_ADDRESS:
+0
00000000`00760074 ?? ???

EXCEPTION_CODE_STR: c0000005

EXCEPTION_PARAMETER1: 0000000000000008

EXCEPTION_PARAMETER2: 0000000000760074

ANALYSIS_SESSION_HOST: PC-Name

ANALYSIS_SESSION_TIME: 03-31-2019 23:22:17.0962

ANALYSIS_VERSION: 10.0.18317.1001 amd64fre

LAST_CONTROL_TRANSFER: from fffff801298df305 to 0000000000760074

STACK_TEXT:
ffffd000fa8b5a78 fffff801298df305 : 0000000000000001 ffffe001b1c09df0 0000000000000000 0000000000000000 : 0x760074
ffffd000fa8b5a80 fffff801298e35ad : ffffc0016c4b8640 ffffc0016c7a0230 0000000000000000 fffff80073608300 : portcls!PnpStartDevice+0xb5
ffffd000fa8b5ae0 fffff80073360c40 : ffffe001b11a1040 fffff80073608340 fffff80073608340 0000000000000000 : portcls!EnqueuedIoWorkItemCallback+0x2d
ffffd000fa8b5b10 fffff80073348359 : fffff80073608200 ffffe001b11a1040 fffff80073360b50 fffff80000000000 : nt!IopProcessWorkItem+0xf0
ffffd000fa8b5b80 fffff800732bca45 : 00000005bd9b3fff 0000000000000080 ffffe001b0238700 ffffe001b11a1040 : nt!ExpWorkerThread+0xe9
ffffd000fa8b5c10 fffff800733bdae6 : fffff80073592180 ffffe001b11a1040 fffff800732bca04 0000000000000000 : nt!PspSystemThreadStartup+0x41
ffffd000fa8b5c60 0000000000000000 : ffffd000fa8b6000 ffffd000fa8b0000 0000000000000000 0000000000000000 : nt!KiStartSystemThread+0x16
THREAD_SHA1_HASH_MOD_FUNC: 722f895aa5b3783406e3107c397ca3cb94f3bf39

THREAD_SHA1_HASH_MOD_FUNC_OFFSET: a18df68580ee42a3a920633d87ee414f74ce020b

THREAD_SHA1_HASH_MOD: 5d112629ade7a1d553eb32e933cf7bdcdcb5826e

FAULT_INSTR_CODE: 8b48e88b

SYMBOL_STACK_INDEX: 1

SYMBOL_NAME: portcls!PnpStartDevice+b5

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: portcls

IMAGE_NAME: portcls.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 56fa301a

STACK_COMMAND: .cxr 0xffffd000fa8b5050 ; kb

BUCKET_ID_FUNC_OFFSET: b5

FAILURE_BUCKET_ID: AV_BAD_IP_portcls!PnpStartDevice

BUCKET_ID: AV_BAD_IP_portcls!PnpStartDevice

PRIMARY_PROBLEM_CLASS: AV_BAD_IP_portcls!PnpStartDevice



FAILURE_ID_HASH_STRING: km:av_bad_ip_portcls!pnpstartdevice

FAILURE_ID_HASH: {45c27a80-23fc-c0eb-1ea1-db488e476447}

Followup: MachineOwner

Best Regards

So it looks like somebody’s buggy WDM driver is installed? Or even several buggy drivers? That’s what you want to fix.

– pa

On Mar 31, 2019, at 2:34 PM, Mark_Sukram wrote:
>
> FAULTING_IP:
> +0
> 00000000`00760074 ?? ???
> EXCEPTION_RECORD: ffffd000fa8b5838 – (.exr 0xffffd000fa8b5838)
> ExceptionAddress: 0000000000760074
> ExceptionCode: c0000005 (Access violation)
> ExceptionFlags: 00000000
> NumberParameters: 2
> Parameter[0]: 0000000000000008
> Parameter[1]: 0000000000760074
> Attempt to execute non-executable address 0000000000760074

So, someone attempted to jump into a Unicode string, or someone overwrote a return address with a Unicode string. If you’re using Unicode strings in your driver, check for over overruns.

Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.

Hello.
Thank you for yours answers.
I’m very embarrassed, but I accidentally posted the wrong memory.dmp. I am very sorry. :s :frowning:


Here is the correct one:

SYSTEM_SERVICE_EXCEPTION (3b)
An exception happened while executing a system service routine.
Arguments:
Arg1: 00000000c0000005, Exception code that caused the bugcheck
Arg2: fffff8083e657089, Address of the instruction which caused the bugcheck
Arg3: ffffe70bda1267c0, Address of the context record for the exception that caused the bugcheck
Arg4: 0000000000000000, zero.

Debugging Details:

KEY_VALUES_STRING: 1

PROCESSES_ANALYSIS: 1

SERVICE_ANALYSIS: 1

STACKHASH_ANALYSIS: 1

TIMELINE_ANALYSIS: 1

DUMP_CLASS: 1

DUMP_QUALIFIER: 401
DUMP_TYPE: 1

BUGCHECK_P1: c0000005

BUGCHECK_P2: fffff8083e657089

BUGCHECK_P3: ffffe70bda1267c0

BUGCHECK_P4: 0

EXCEPTION_CODE: (NTSTATUS) 0xc0000005 -

FAULTING_IP:
ks!KsDispatchIrp+179
fffff808`3e657089 488b08 mov rcx,qword ptr [rax]

CONTEXT: ffffe70bda1267c0 – (.cxr 0xffffe70bda1267c0)
rax=0000000100000000 rbx=ffffd58e41c56e08 rcx=0000000000000002
rdx=fffff8083e657089 rsi=ffffd58e41c56bd0 rdi=ffffd58e421b2510
rip=fffff8083e657089 rsp=ffffe70bda1271b0 rbp=ffffd58e421b2510
r8=fffff8083e630000 r9=ffffd58e42c83490 r10=0000000000000000
r11=0000000000000000 r12=ffffd58e446c1580 r13=0000000000000001
r14=ffffd58e42c83400 r15=ffffd58e4216adb0
iopl=0 nv up ei ng nz na pe nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00010282
ks!KsDispatchIrp+0x179:
fffff8083e657089 488b08 mov rcx,qword ptr [rax] ds:002b:0000000100000000=???
Resetting default scope

BUGCHECK_STR: 0x3B_c0000005




BLACKBOXBSD: 1 (!blackboxbsd)

BLACKBOXPNP: 1 (!blackboxpnp)


LAST_CONTROL_TRANSFER: from fffff8083ebb5b66 to fffff8083e657089

STACK_TEXT:
ffffe70bda1271b0 fffff8083ebb5b66 : fffff801a97ff180 ffffe70bda127440 ffff89898132fb00 fffff801a9d8e32e : ks!KsDispatchIrp+0x179
ffffe70bda127270 fffff8083e842711 : ffffe70bda1273b0 ffffd58e41c56e50 ffffd58e4216af80 fffff801a9b7d7e6 : portcls!PcDispatchIrp+0x66
ffffe70bda1272e0 fffff801a9b3be69 : ffffd58e421b2510 ffffd58e41c56bd0 0000000000000000 ffffd58e41c56bd0 : BasicDriver!xxx_Itf_Close+0xb1 [xxx\basicdriver\uicommunication.cpp @ 104]
ffffe70bda127320 fffff8083e86164d : ffffd58e41c56bd0 ffffd58e41c56e50 0000000000000000 fffff801a9bc7ee5 : nt!IofCallDriver+0x59
ffffe70bda127360 fffff8083e861023 : ffffd58e42c83490 ffffd58e41c56bd0 0000000000000000 0000000000000000 : ksthunk!CKernelFilterDevice::DispatchIrp+0x21d
ffffe70bda1273c0 fffff801a9b3be69 : ffffd58e446c3400 fffff801a9b3c135 ffffd58e446c3080 fffff801a9b9bfa8 : ksthunk!CKernelFilterDevice::DispatchIrpBridge+0x13
ffffe70bda1273f0 fffff801a9f6a574 : ffffd58e42c83490 0000000000000001 ffffd58e41c56bd0 fffff801a9ae0fc3 : nt!IofCallDriver+0x59
ffffe70bda127430 fffff801a9fa1bc0 : 0000000000000001 0000000000000000 ffffd58e40313c60 ffffd58e41c56bd0 : nt!IopDeleteFile+0x124
ffffe70bda1274b0 fffff801a9b38086 : 0000000000000000 0000000000000000 0000000000000001 ffffd58e42c83490 : nt!ObpRemoveObjectRoutine+0x80
ffffe70bda127510 fffff801a9f97599 : 00000000ffff8011 ffffd58e40313c60 ffffd58e00000000 0000000000007fef : nt!ObfDereferenceObjectWithTag+0xc6
ffffe70bda127550 fffff801aa02a1b5 : ffffd58e446c0098 fffff801a9b35ecd ffffd58e446c0060 0000000000000f9c : nt!ObCloseHandleTableEntry+0x259
ffffe70bda127690 fffff801a9ff6899 : ffffd58e446c0060 00000000c000013a ffffd58e446c1878 ffffffffffffff01 : nt!ExSweepHandleTable+0xc5
ffffe70bda127740 fffff801a9f4a331 : ffffffffffffffff ffffd58e446c1580 ffffd58e446c1580 ffffd58e00000000 : nt!ObKillProcess+0x35
ffffe70bda127770 fffff801a9f58d8c : ffffd58e446c1580 ffff89898041da60 ffffe70bda127988 0000000000000000 : nt!PspRundownSingleProcess+0x121
ffffe70bda1277f0 fffff801aa03d803 : 00000000c000013a fffff801a97ff101 0000006bea637000 fffff801a9b39b9b : nt!PspExitThread+0x5ac
ffffe70bda1278f0 fffff801a9b3d370 : 0000000000000000 0000000000000000 0000000000000000 0000006bea8fde50 : nt!KiSchedulerApcTerminate+0x33
ffffe70bda127930 fffff801a9c51150 : 00000000000002f0 ffffe70bda1279c0 00000000c9e0ff00 ffffd58e00000000 : nt!KiDeliverApc+0x3a0
ffffe70bda1279c0 fffff801a9c5d7ea : ffffd58e446c3080 0000000000000000 0000000000000000 ffffd58e448ae080 : nt!KiInitiateUserApc+0x70
ffffe70bda127b00 00007ffcd631aa24 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : nt!KiSystemServiceExit+0x9f
0000006bea8fddf8 0000000000000000 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : 0x00007ffc`d631aa24

THREAD_SHA1_HASH_MOD_FUNC: 8cc8cd909cdb9251d786596e41fca21845b00be1

THREAD_SHA1_HASH_MOD_FUNC_OFFSET: 3f1990a8cbd0314eff460c5cae5664460ae538ee

THREAD_SHA1_HASH_MOD: 6b8a00592a4d647a6d1cf8a7e9ed1037e4c30d98

FOLLOWUP_IP:
ks!KsDispatchIrp+179
fffff808`3e657089 488b08 mov rcx,qword ptr [rax]

FAULT_INSTR_CODE: 48088b48

SYMBOL_STACK_INDEX: 0

SYMBOL_NAME: ks!KsDispatchIrp+179

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: ks

IMAGE_NAME: ks.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 2f031644

STACK_COMMAND: .cxr 0xffffe70bda1267c0 ; kb

BUCKET_ID_FUNC_OFFSET: 179

FAILURE_BUCKET_ID: 0x3B_c0000005_ks!KsDispatchIrp

BUCKET_ID: 0x3B_c0000005_ks!KsDispatchIrp

PRIMARY_PROBLEM_CLASS: 0x3B_c0000005_ks!KsDispatchIrp




ANALYSIS_SOURCE: KM

FAILURE_ID_HASH_STRING: km:0x3b_c0000005_ks!ksdispatchirp

FAILURE_ID_HASH: {3a0df23c-5454-3a6c-c068-d3a61101b8fa}

Followup: MachineOwner

kd> !blackboxbsd
Stream size mismatch (expected = 168, read = 136)
kd> !blackboxpnp
PnpActivityId : {00000000-0000-0000-0000-000000000000}
PnpActivityTime : 131986613096869018
PnpEventInformation: 6
PnpEventInProgress : 0
PnpProblemCode : 53
PnpVetoType : 0
DeviceId : PCI\VEN_8086&DEV_10D3&SUBSYS_07D015AD&REV_00\000C29FFFFE1D73B00
VetoString :

kd> .cxr 0xffffe70bda1267c0
rax=0000000100000000 rbx=ffffd58e41c56e08 rcx=0000000000000002
rdx=fffff8083e657089 rsi=ffffd58e41c56bd0 rdi=ffffd58e421b2510
rip=fffff8083e657089 rsp=ffffe70bda1271b0 rbp=ffffd58e421b2510
r8=fffff8083e630000 r9=ffffd58e42c83490 r10=0000000000000000
r11=0000000000000000 r12=ffffd58e446c1580 r13=0000000000000001
r14=ffffd58e42c83400 r15=ffffd58e4216adb0
iopl=0 nv up ei ng nz na pe nc
cs=0010 ss=0018 ds=002b es=002b fs=0053 gs=002b efl=00010282
ks!KsDispatchIrp+0x179:
fffff8083e657089 488b08 mov rcx,qword ptr [rax] ds:002b:0000000100000000=???


Here is the part of code of the uicommunication.cpp, the call stack mentions:

NTSTATUS xxx_Itf_Close(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{

NTSTATUS NtStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION pIoStack = IoGetCurrentIrpStackLocation(Irp);
if(pIoStack->FileObject->FsContext == (PVOID)fileContext)
{
    DbgPrint("xxx_Itf_Close: call DISCONNECT_WSK");
    fileContext = (PFILE_CONTEXT)pIoStack->FileObject->FsContext;
    ExFreePoolWithTag(fileContext, TAG);
    Irp->IoStatus.Information = 0;
    Irp->IoStatus.Status = NtStatus;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    DbgPrint("xxx_Itf_Close Called if condition == 123 \r\n");
}
else
{
    NtStatus = PcDispatchIrp(DeviceObject, Irp);   //Line 104
    DbgPrint("xxx_Itf_Close Called NtStatus is %d \r\n", NtStatus);
}
 return NtStatus;

}

Line 104 is the following code: NtStatus = PcDispatchIrp(DeviceObject, Irp); //Line 104

@Tim_Roberts I checked my settings in Visual Studio concerning unicode. The setting is, that the files are stored in unicode style.

Best Regards

Hello.
After a debug session using the app store variant of WinDbg the problem is solved, for my opinion.
For each instance of a driver and an access to the driver the fileContext needs to be stored.
Because I didn’t do that, FsContext has an other value than fileContext, and therefore the if condition always goes to the else case.
To solve the problem I created an array of PFILE_CONTEXT fileContext[3]; for the two installed drivers.
I also have two counter, which counts up and down every time the Create or Close function will be called.
Everything seems to me to work fine.

Now I have two questions:

  1. Is it a good idea to use dynamic memory allocation in this part of code instead of using the fileContext array?
    I’m not sure, because with dynamic memory allocation I am independent of the installed number of driver instances.
    On the other hand if the memory is not correct allocated or freed a BSOD would happen.
    What is your experience in such a case?
  2. Maybe you’ve seen, that the array has a size of ‘3’ but I only have two installed drivers. Usually the fileContext array should have the size of ‘2’.
    If I set the size of fileContext array to ‘2’ and I start to debug the application within Visual Studio the debug process starts correctly.
    If I stop to debug I get a BSOD.
    If I set the size of fileContext array to ‘3’ I can debug and close the process without BSOD.
    Further: I can start and close the application, if I start the *.exe directly by for example double click the file.
    This works independently if the the *.exe file was compiled as ‘debug’ or ‘release’.
    Can someone explain to me why the fileContext array needs to be one element bigger than installed driver instances?

I hope my questions are understandable written. If not, please, feel free to ask.

Best Regards

On Apr 7, 2019, at 5:55 AM, Mark_Sukram wrote:
>
> For each instance of a driver and an access to the driver the fileContext needs to be stored.

I can’t tell what you mean by this. A single driver instance can have many open file handles. This is especially true in a kernel streaming driver, where you get one open file handle for the filter and at least one open file handle for each pin.

Kernel streaming uses the device and file contexts for its own purposes. To be a good neighbor, you have to find ways to work around that. There is a well defined way for you to add your own device context info after the end of the class driver’s info, and you can use FsContext2 instead of FsContext to track your own file context.

> To solve the problem I created an array of PFILE_CONTEXT fileContext[3]; for the two installed drivers.
> I also have two counter, which counts up and down every time the Create or Close function will be called.

Where did you store that? In a global? For what purpose?

> 1. Is it a good idea to use dynamic memory allocation in this part of code instead of using the fileContext array?
> I’m not sure, because with dynamic memory allocation I am independent of the installed number of driver insances.
> On the other hand if the memory is not correct allocated or freed a BSOD would happen.
> What is your experience in such a case?

It is just not that hard to handle memory allocation. Just make sure you don’t crash if the allocation fails, but you’re only talking about a few bytes here. The danger is insignificant.

> 2. Maybe you’ve seen, that the array has a size of ‘3’ but I only have two installed drivers. Usually the fileContext array should have the size of ‘2’.
> If I set the size of fileContext array to ‘2’ and I start to debug the application within Visual Studio the debug process starts correctly.
> If I stop to debug I get a BSOD.

And did you investigate why you got the crash? Your description makes it sound like you are debugging at random — just change a constant and see if the crash stops, without trying to figure out exactly why there was a crash. That’s not good software engineering.

> Can someone explain to me why the fileContext array needs to be one element bigger than installed driver instances?

As I said, one driver instance will often have multiple file handles, especially with streaming drivers.

Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.