Question about inverted call

I see it now. My apologies.

In cusbcom::MixerSet, you are calling IoCsqRemoveNextIrp. From the stack trace, which is not always 100% accurate, it looks like you have passed a null pointer as the CSQ. What does that code look like?

Well MixerSet is called from user mode the same why like I do it in the DispatchIO major function which is working.
That was just for testing because I was sure this works.

Actually my goal is to trigger the completione from within the USB completione callback somehow.

But the CODE:

PDEVICE_EXTENSION devExtension1 = (PDEVICE_EXTENSION)m_pFdo->DeviceExtension;
if (devExtension1)
{
	PIRP p = IoCsqRemoveNextIrp(&devExtension1->CancelSafeQueue, NULL);
	if (p)
	{
		DbgPrintEx(DPFLTR_IHVAUDIO_ID, 0, "is it Christmas? :-) \n");
	}
}

It look like the CSQ pointer gets lost somehow and I have no idea why. As I said, in my m_pFdo->DeviceExtension I have another pointer to a struct which is 100% valid and working.
I create and add this structure in my StartDevice function which I call in my DispatchPnp
So it is realy weird to me …

This is how it look like if I break in with the debugger.
:-/

https://postimg.cc/kDXjG5xw

OK it is indeed weird, at least for me…

What I did I changed DeviceExtention struct and put the CSQ on top of it. And suddenly it worked…
So I started to move the CSQ stuff line by line until I see what is causing this.

It is the:

IO_REMOVE_LOCK RemoveLock;
Which will cause that the DeviceExtention gets corrupted somehow.

typedef struct _DEVICE_EXTENSION {

ULONG flags;							// flags
LONG handles;							// # open handles
PDEVICE_OBJECT DeviceObject;			// device object this extension belongs to
PDEVICE_OBJECT LowerDeviceObject;		// next lower driver in same stack
PDEVICE_OBJECT Pdo;						// the PDO

PDRIVER_OBJECT DriverObject;			// our own driver object


UNICODE_STRING devname;					// name of this device

DEVSTATE state;							// current state of device
DEVSTATE prevstate;						// state prior to removal query
DEVICE_POWER_STATE devpower;			// current device power state
SYSTEM_POWER_STATE syspower;			// current system power state
DEVICE_CAPABILITIES devcaps;			// copy of most recent device capabilities

LIST_ENTRY		PendingIrpQueue;
//  SpinLock to protect access to the queue
KSPIN_LOCK		QueueLock;
IO_CSQ			CancelSafeQueue;
KSEMAPHORE		IrpQueueSemaphore;

IO_REMOVE_LOCK RemoveLock;			// removal control locking structure

PDEVICE_OBJECT Child[MAX_CHILD];		// child devices
ULONG ChildCnt;

// This parent device suballocates its I/O resources by exporting
// a direct-call interface to the SUBALLOC upper filter. These are
// the resources that will be assigned to the child devices:

LONG			WdmIFrefcnt;	// reference count for interfaces


PVOID			ComAdapter;
PDMA_ADAPTER	pDmaAdapter;
ULONG			ulNumOfMap;
ULONG			savedSamplerate;

UNICODE_STRING	InterfaceNameCnt;

} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

So now I checked the REMOVE_LOCK and found this with the comment:

// Currently, the support routines for managing the device remove lock aren't
// defined in the WDM.H or implemented in Windows 98. The following declarations
// provide equivalent functionality on all WDM platforms by means of a private
// implementation in RemoveLock.cpp

typedef struct _REMOVE_LOCK {
	LONG usage;					// reference count
	BOOLEAN removing;			// true if removal is pending
	KEVENT evRemove;			// event to wait on
	} REMOVE_LOCK, *PREMOVE_LOCK;

VOID InitializeRemoveLock(PREMOVE_LOCK lock, ULONG tag, ULONG minutes, ULONG maxcount);
   NTSTATUS AcquireRemoveLock(PREMOVE_LOCK lock, PVOID tag);
   VOID ReleaseRemoveLock(PREMOVE_LOCK lock, PVOID tag);
   VOID ReleaseRemoveLockAndWait(PREMOVE_LOCK lock, PVOID tag);

And the code there for:

#pragma PAGEDCODE

VOID InitializeRemoveLock(PREMOVE_LOCK lock, ULONG tag, ULONG minutes, ULONG maxcount)
	{							// InitializeRemoveLock
	PAGED_CODE();
	KeInitializeEvent(&lock->evRemove, NotificationEvent, FALSE);
	lock->usage = 1;
	lock->removing = FALSE;
	}							// InitializeRemoveLock

///////////////////////////////////////////////////////////////////////////////

#pragma LOCKEDCODE

NTSTATUS AcquireRemoveLock(PREMOVE_LOCK lock, PVOID tag)
	{							// AcquireRemoveLock
	LONG usage = InterlockedIncrement(&lock->usage);
	if (lock->removing)
		{						// removal in progress
		if (InterlockedDecrement(&lock->usage) == 0)
			KeSetEvent(&lock->evRemove, 0, FALSE);
		return STATUS_DELETE_PENDING;
		}						// removal in progress
	return STATUS_SUCCESS;
	}							// AcquireRemoveLock

///////////////////////////////////////////////////////////////////////////////

VOID ReleaseRemoveLock(PREMOVE_LOCK lock, PVOID tag)
	{							// ReleaseRemoveLock
	if (InterlockedDecrement(&lock->usage) == 0)
		KeSetEvent(&lock->evRemove, 0, FALSE);
	}							// ReleaseRemoveLock

///////////////////////////////////////////////////////////////////////////////

#pragma PAGEDCODE

VOID ReleaseRemoveLockAndWait(PREMOVE_LOCK lock, PVOID tag)
	{							// ReleaseRemoveLockAndWait
	PAGED_CODE();
	lock->removing = TRUE;
	ReleaseRemoveLock(lock, tag);
	ReleaseRemoveLock(lock, NULL);
	KeWaitForSingleObject(&lock->evRemove, Executive, KernelMode, FALSE, NULL);
	}							// ReleaseRemoveLockAndWait

Also interesting is the no other pointer and structs below the IO_REMOVE_LOCK are compromised.

And as it is told in the documentation this is initialized in the AddDevice function. At the same point as I initialize my CSQ.

Any idea what I’m doing wrong here?
I can of course change the order in the struct but that seem more, hiding an obviously issue.

OK I removed this “private” code from above and now it will used the code from wdm.h instead.
It seems that the “private” code and wdm.h code mixed up somehow!?
It is now working without puting the IO_REMOVE_LOCK below the CSQ…

Ohh well…

Thanks for pointing me in the right direction and helping me debugging this!

I realy appreciate it!

Regards,
K. Weller

I have a lot of old code out there that also had to have struct and function and enum definitions pasted into code. This is entirely MSFT’s fault for the utter mess that the header files were in for around 20 years. Things have gotten better. Every one of those is a fragile defect waiting to explode.