Implementing DebugExtensionProvideValue corrupts WinDbg internal state?

I’m implementing DebugExtensionProvideValue in my extension so I can provide custom pseudo-registers. It works perfectly in CDB and it works fine initially in WinDbg but after stopping debugging and opening a new executable something happens and WinDbg ends up in a weird unusable state.

WinDbg prints “Unable to deliver callback, 3131” to the command window when you trigger the problem and after that all output is printed twice in the command window!

HRESULT CALLBACK DebugExtensionProvideValue(
PDEBUG_CLIENT Client, ULONG Flags,
IN PCWSTR Name, OUT PULONG64 Value,
OUT PULONG64 TypeModBase,
OUT PULONG TypeId, OUT PULONG TypeFlags)
{
HRESULT hr = HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
if (!Name || !Value || !TypeFlags)
{
hr = E_INVALIDARG;
}
else if (0 == lstrcmpiW(Name, L"$$test"))
{
*Value = 0xDeadCafeBabeBeefULL;
*TypeFlags = DEBUG_EXT_PVTYPE_IS_VALUE;
if (TypeId) *TypeId = 0; // Where are these types defined?
if (TypeModBase) *TypeModBase = 0;
hr = S_OK;
}
#if 0 // <– ** Setting this to != 0 fixes the problem **
Client->Release(); // This does not feel right but it does seem to be required!
#endif
return hr;
}

I’m not including DebugExtensionQueryValueNames and DebugExtensionInitialize here because they are pretty boilerplate but you can see them @ http://stackoverflow.com/q/37417335/3501

Reproducing the issue looks something like this:

Press Ctrl+E to open a executable, I’m going to open WinVer.exe
0:000> .load c:\test\myext.dll
0:000> ? @$$test
Evaluate expression: -2401039830915039505 = deadcafe`babebeef
0:000> $$ Press Shift+F5 to stop debugging
0:000> $$ Press Ctrl+E and open a executable again
Unable to deliver callback, 3131

If I release the IDebugClient passed to me in DebugExtensionProvideValue then the problem goes away but it feels so wrong and breaks all kinds of COM rules. I have tested multiple WinDbg versions, both 32 and 64-bit and they all act the same, no problems with the hack and the callback error without it.

Am I doing something wrong or is there a bug in DbgEng?

There is a bug in the dbgeng!ExtensionInfo::CallProvideValue method. It’s
not releasing DEBUG_CLIENT that it got from dbgeng!FindExtClient.


@AndreyBazhan
http://www.andreybazhan.com

xxxxx@microsoft.com is a better place to report windbg/dbgeng issues.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Andrey Bazhan
Sent: Saturday, May 28, 2016 7:25 AM
To: Kernel Debugging Interest List
Subject: Re:[windbg] Implementing DebugExtensionProvideValue corrupts WinDbg internal state?

There is a bug in the dbgeng!ExtensionInfo::CallProvideValue method. It’s not releasing DEBUG_CLIENT that it got from dbgeng!FindExtClient.


@AndreyBazhan
http://www.andreybazhan.com

It wasn’t a bug report :). Anyway, thanks for suggestion. I’ll try
xxxxx@microsoft.com again. (Hope this time it won’t be a “black hole”)

“Pavel Lebedinsky” wrote in message news:xxxxx@windbg…

xxxxx@microsoft.com is a better place to report windbg/dbgeng issues.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Andrey Bazhan
Sent: Saturday, May 28, 2016 7:25 AM
To: Kernel Debugging Interest List
Subject: Re:[windbg] Implementing DebugExtensionProvideValue corrupts WinDbg
internal state?

There is a bug in the dbgeng!ExtensionInfo::CallProvideValue method. It’s
not releasing DEBUG_CLIENT that it got from dbgeng!FindExtClient.


@AndreyBazhan
http://www.andreybazhan.com

Yeah it was not originally a bug report because I was not sure if I was doing everything correctly and there are no examples anywhere that implements it AFAIK. (The c++ helper library wraps it but the samples do not use this feature and none of the MS extensions seem to export it)

The problem if DbgEng is fixed is of course that I will then be responsible for a double Release(). The upside is that the function has a unused flags parameter so it would be possible to signal the change in behavior.

It would be nice if MS could confirm if there is a bug and add a note on MSDN. It would be even better if it also linked to some information about the TypeId output parameter…