I am trying out WCT and I want to call GetThreadWaitChain, I had some previous questions on this topic, but I've got recently strange behavior. As I am calling GetThreadWaitChain fuction my Visual Studio hangs with prompt message:
vhost32.exe has stopped working
Output windows message:
The program '[9068] testWCT.vshost.exe' has exited with code -1073740940 (0xc0000374).
Every time I am getting to that function my visual studio hangs...
GetThreadWaitChain documentation:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms679364(v=vs.85).aspx
This is my code:
internal void CollectWaitInformation(ClrThread thread)
{
var g_WctHandle = OpenThreadWaitChainSession(0, 0);
uint threadID = thread.OSThreadId;
WAITCHAIN_NODE_INFO[] NodeInfoArray = new WAITCHAIN_NODE_INFO[16];
int isCycle = 0;
int count = 16;
// Make a synchronous WCT call to retrieve the wait chain.
bool result = GetThreadWaitChain(g_WctHandle,
IntPtr.Zero,
WCTP_GETINFO_ALL_FLAGS,
threadID, ref count, NodeInfoArray, out isCycle);
if (!result)
{
//error
}
//Finaly ...
CloseSession(g_WctHandle);
}
[DllImport("Advapi32.dll")]
public static extern IntPtr OpenThreadWaitChainSession(OpenThreadChainFlags Flags, DWORD callback);
[DllImport("Advapi32.dll")]
public static extern bool GetThreadWaitChain(
IntPtr WctHandle,
IntPtr Context,
UInt32 Flags,
uint ThreadId,
ref int NodeCount,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)]
[In, Out]
WAITCHAIN_NODE_INFO[] NodeInfoArray,
out int IsCycle
);
[StructLayout(LayoutKind.Sequential)]
public struct WAITCHAIN_NODE_INFO
{
public WCT_OBJECT_TYPE ObjectType;
public WCT_OBJECT_STATUS ObjectStatus;
public struct LockObject
{
string ObjectName;
LARGE_INTEGER Timeout;
BOOL Alertable;
}
public struct ThreadObject
{
DWORD ProcessId;
DWORD ThreadId;
DWORD WaitTime;
DWORD ContextSwitches;
}
}
}
I've tried to run C++ code on the same process, which I took from MSDN:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681418(v=vs.85).aspx
And all I've got is: 0x57 error on all threads as a result. Which is ERROR_INVALID_PARAMETER accordingly to MSDN:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx
Which is weird cause I didn't changed the C++ code..
Previous question on the same topic:
WCT GetThreadWaitChain call allways return false
I declared the WAITCHAIN_NODE_INFO struct in a wrong way (my union was wrong) this is the original structure:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681422(v=vs.85).aspx
As soon as I declared it right, the heap corruption stopped and everything worked...
Related
I'm trying to wrap the new Windows 10 ProjFS features in C#. The first steps, as outlined on MSDN, work fine: I set up a directory as my virtualization root, and then register my projection provider including its callbacks as follows:
static void Main(string[] args)
{
// Create and mark clean directory as virtualization root.
const string directory = #"C:\test_projfs"; // Warning: Deleted to get clean directory.
if (Directory.Exists(directory))
Directory.Delete(directory);
Directory.CreateDirectory(directory);
Guid guid = Guid.NewGuid();
Marshal.ThrowExceptionForHR(PrjMarkDirectoryAsPlaceholder(directory, null, IntPtr.Zero,
ref guid));
// Set up the callback table for the projection provider.
PrjCallbacks callbackTable = new PrjCallbacks
{
StartDirectoryEnumerationCallback = StartDirectoryEnumerationCallback,
EndDirectoryEnumerationCallback = EndDirectoryEnumerationCallback,
GetDirectoryEnumerationCallback = GetDirectoryEnumerationCallback,
GetPlaceholderInfoCallback = GetPlaceholderInfoCallback,
GetFileDataCallback = GetFileDataCallback
};
// Start the projection provider.
IntPtr instanceHandle = IntPtr.Zero;
Marshal.ThrowExceptionForHR(PrjStartVirtualizing(directory, ref callbackTable,
IntPtr.Zero, IntPtr.Zero, ref instanceHandle));
// Keep a test console application running.
Console.ReadLine();
}
// Managed callbacks, simply returning S_OK for now.
static int StartDirectoryEnumerationCallback(ref PrjCallbackData callbackData, ref Guid enumerationId)
{
return 0;
}
static int EndDirectoryEnumerationCallback(ref PrjCallbackData callbackData, ref Guid enumerationId) => 0;
static int GetDirectoryEnumerationCallback(ref PrjCallbackData callbackData, ref Guid enumerationId, string searchExpression, IntPtr dirEntryBufferHandle) => 0;
static int GetPlaceholderInfoCallback(ref PrjCallbackData callbackData) => 0;
static int GetFileDataCallback(ref PrjCallbackData callbackData, ulong byteOffset, uint length) => 0;
The native declarations are as follows (sorry about the fact this code block can be scrolled - the basics are quite a lot to wrap already):
// Methods to mark directory as virtualization root, and start the projection provider.
[DllImport("ProjectedFSLib.dll", CharSet = CharSet.Unicode)]
static extern int PrjMarkDirectoryAsPlaceholder(string rootPathName,
string targetPathName, IntPtr versionInfo, ref Guid virtualizationInstanceID);
[DllImport("ProjectedFSLib.dll", CharSet = CharSet.Unicode)]
static extern int PrjStartVirtualizing(string virtualizationRootPath,
ref PrjCallbacks callbacks, IntPtr instanceContext, IntPtr options,
ref IntPtr namespaceVirtualizationContext);
// Structure configuring the projection provider callbacks.
[StructLayout(LayoutKind.Sequential)]
struct PrjCallbacks
{
public PrjStartDirectoryEnumerationCb StartDirectoryEnumerationCallback;
public PrjEndDirectoryEnumerationCb EndDirectoryEnumerationCallback;
public PrjGetDirectoryEnumerationCb GetDirectoryEnumerationCallback;
public PrjGetPlaceholderInfoCb GetPlaceholderInfoCallback;
public PrjGetFileDataCb GetFileDataCallback;
public PrjQueryFileNameCb QueryFileNameCallback;
public PrjNotificationCb NotificationCallback;
public PrjCancelCommandCb CancelCommandCallback;
}
// Callback signatures.
delegate int PrjStartDirectoryEnumerationCb(ref PrjCallbackData callbackData, ref Guid enumerationId);
delegate int PrjEndDirectoryEnumerationCb(ref PrjCallbackData callbackData, ref Guid enumerationId);
delegate int PrjGetDirectoryEnumerationCb(ref PrjCallbackData callbackData, ref Guid enumerationId, string searchExpression, IntPtr dirEntryBufferHandle);
delegate int PrjGetPlaceholderInfoCb(ref PrjCallbackData callbackData);
delegate int PrjGetFileDataCb(ref PrjCallbackData callbackData, ulong byteOffset, uint length);
delegate int PrjQueryFileNameCb(ref PrjCallbackData callbackData);
delegate int PrjNotificationCb(ref PrjCallbackData callbackData, bool isDirectory, int notification, string destinationFileName, IntPtr operationParameters);
delegate int PrjCancelCommandCb(ref PrjCallbackData callbackData);
// Callback data passed to each of the callbacks above.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct PrjCallbackData
{
public uint Size;
public uint Flags;
public IntPtr NamespaceVirtualizationContext;
public int CommandId;
public Guid FileId;
public Guid DataStreamId;
public string FilePathName;
public IntPtr VersionInfo;
public uint TriggeringProcessId;
public string TriggeringProcessImageFileName;
public IntPtr InstanceContext;
}
However, I seem to have done something wrong when marshalling a structure passed from the OS to the callbacks, as it results in the managed app immediately stopping without a managed exception, and only logging a heap corruption error code in the Windows event viewer.
In detail, I receive the PRJ_START_DIRECTORY_ENUMERATION_CB callback (PrjStartDirectoryEnumerationCb in my code) to start enumerating my directories. It passes a pointer to a PRJ_CALLBACK_DATA struct along (PrjCallbackData in my code).
Now, while I apparently receive the struct nicely into my managed callback, with all values making sense down to the last member InstanceContext, the application crashes immediately upon trying to return the value 0 (S_OK).
static int StartDirectoryEnumerationCallback(ref PrjCallbackData callbackData, ref Guid enumerationId)
{
return 0; // Crashes here or when stepping out of this method.
}
I tried to nail down where my error lies, but due to debugging immediately stopping without any exception (I'm not filtering out any), I didn't get far. I realized that when I change the callback to dumbly accept an IntPtr instead of a ref PrjCallbackData, the application doesn't crash.
static int StartDirectoryEnumerationCallback(IntPtr callbackData, ref Guid enumerationId)
{
return 0; // No crash executing this with IntPtr passed in.
}
delegate int PrjStartDirectoryEnumerationCb(IntPtr callbackData, ref Guid enumerationId);
Logically, this doesn't get me far without the important info accessible by me.
Am I missing a step here? Is mapping a struct as simple like that not possible directly?
If of interest, the event viewer entry looks follows. I'm running the application with .NET Framework 4.6 in a new-style C# project file (which should explain the "dotnet.exe" executable name). If additional information is required, I'm happy to provide it.
Faulting application name: dotnet.exe, version: 2.1.26919.1, time stamp: 0x5ba1bb46
Faulting module name: ntdll.dll, version: 10.0.17763.1, time stamp: 0xa369e897
Exception code: 0xc0000374
Fault offset: 0x00000000000fb349
Faulting process id: 0xfa8
Faulting application start time: 0x01d46d623aee076d
Faulting application path: C:\Program Files\dotnet\dotnet.exe
Faulting module path: C:\WINDOWS\SYSTEM32\ntdll.dll
Report Id: adcfba5c-dfd4-428d-8eb5-81aceada1983
Faulting package full name:
Faulting package-relative application ID:
Note that if you want to try the sample code above, you have to install the Projected Filesystem feature in Windows 10 1809, and compile it as x64 (there are no native libraries for x86 / AnyCPU configurations).
As Simon commented, only having an IntPtr in the signature instead of the structure and then using Marshal.PtrToStructure<PrjCallbackData>(callbackData) to retrieve a copy of the structure passed to my callback works fine.
Alternatively, Hans' solution with using IntPtr for the string fields in the structure (and keeping the structure in the signature) also works, but leaves me with no simple access to the string data.
Luckily, I do not have to write anything back to this structure, otherwise I'd run into problems writing it back to the original, and not the copy of the structure, so Simon's solution is sufficient here.
In case full code coverage is of interest, the repository is found here.
So I'm getting this error that looks as though it's a corrupted garbage collection:
Application Crashes With "Internal Error In The .NET Runtime"
The full error is:
The process was terminated due to an internal error in the .NET Runtime at IP 71C571C8 (71B20000) with exit code 80131506.
It's running on:
Framework Version: v4.0.30319
This occurs inconsistently when running this function repeatedly:
public static int GetMdiTitledChildWindows(IntPtr parentWindow)
{
IntPtr mdiClient = FindWindowEx(parentWindow, IntPtr.Zero, MdiClient, "");
List<IntPtr> handles = new List<IntPtr>();
EnumChildWindows(mdiClient, (hwnd, param) =>
{
handles.Add(hwnd);
return true;
}, IntPtr.Zero);
int counter = 0;
foreach (IntPtr handle in handles)
{
StringBuilder builder = new StringBuilder();
GetWindowText(handle, builder, GetWindowTextLength(handle)+1);
if (builder.Length > 0)
{
counter++;
}
}
return counter;
}
Where FindWindowEx(), EnumChildWindows() and GetWindowText() are all p/invoke signatures defined similarly to this:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
The error only seems to occur after I've run the method many times, however, this doesn't happen consistently. Sometimes it works, sometimes it doesn't.
Any suggestions on how to fix this?
So I solved my issue with the help of a generous benefactor on Discord.
The problem was that I was passing a lambda to a p/invoke as a delegate:
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
So every time the unmanaged WinAPI call called-back into my delegate, the GC had the opportunity to run, if it did, it collected my lambda causing this crash. This wouldn't necessarily happen, hence why my method worked most of the time and crashed inconsistently.
The solution was to add a reference to the lambda that would prevent the GC from collecting it (although I went whole-hog and made it a local function because belt and braces):
public static int GetMdiTitledChildWindows(IntPtr parentWindow)
{
IntPtr mdiClient = FindWindowEx(parentWindow, IntPtr.Zero, MdiClient, "");
List<IntPtr> handles = new List<IntPtr>();
bool addToList(IntPtr hwnd, IntPtr param)
{
handles.Add(hwnd);
return true;
}
EnumWindowsProc gcHolder = addToList;
EnumChildWindows(mdiClient, gcHolder, IntPtr.Zero);
int counter = 0;
foreach (IntPtr handle in handles)
{
int textLength = GetWindowTextLength(handle) + 1;
StringBuilder builder = new StringBuilder(textLength);
GetWindowText(handle, builder, textLength);
if (builder.Length > 0)
{
counter++;
}
}
return counter;
}
The application now works as expected.
I have a problem while I trying to call WinAPI functions from C# code. I have lots of imports, many of them works fine, but some of them not and leading to unexpected break main program, without any message, exception type, nothing, just fell down all its windows and exit.
I have two ways in code: via my developed library, where is more of winapi calls and I'm lazy to code specific structures, pointers, etc, and direct import from user32.dll, like this:
[DllImport(#"tradeInterop.dll")]
public static extern void ChooseInstrumentByMouse(UInt32 hwnd, int baseX, int baseY, int idx, int _isDown);
[DllImport(#"tradeInterop.dll")]
public static extern void PutNumber(int num);
[DllImport(#"tradeInterop.dll")]
public static extern void PutRefresh();
[DllImport(#"user32.dll")]
public static extern UInt32 FindWindow(string sClass, string sWindow);
[DllImport(#"user32.dll")]
public static extern int GetWindowRect(uint hwnd, out RECT lpRect);
[DllImport(#"user32.dll")]
public static extern int SetWindowPos(uint hwnd, uint nouse, int x, int y, int cx, int cy, uint flags);
[DllImport(#"user32.dll")]
public static extern int LockSetForegroundWindow(uint uLockCode);
[DllImport(#"user32.dll")]
public static extern int SetForegroundWindow(uint hwnd);
[DllImport(#"user32.dll")]
public static extern int ShowWindow(uint hwnd, int cmdShow);
[DllImport(#"tradeInterop.dll")]
public static extern ulong PixelColor(uint hwnd, int winX, int winY); //tried (signed) long and both ints as return type, same result (WINAPI says DWORD as unsigned long, what about 64-bit assembly where compiled both lib and program?
public struct RECT
{
public int Left;
public int Top; ...
As I said, many of this calls works perfectly, but have problem of last two of them: ShowWindow() and PixelColor() with following code:
extern "C" __declspec(dllexport) COLORREF __stdcall PixelColor(unsigned hwnd, int winX, int winY)
{
LPPOINT point;
point->x = winX;
point->y = winY;
ClientToScreen((HWND) hwnd, point);
HDC dc = GetDC(NULL);
COLORREF colorPx = GetPixel(dc, point->x, point->y);
ReleaseDC(NULL, dc);
return colorPx;
}
So, while I try to call directly imported ShowWindow() function, or library which calls api function(s), I got a program crash
Is there any way how to debug external libraries and its results?
What I¨m doing wrong?
Thanks a lot
You have several options for debugging issues.
Enable unmanaged code debugging in Visual Studio. Note: VS 2010 Express does not support mixed managed/unmanaged debugging. (Instructions)
Use WinDbg. This would be my personal favorite option for debugging mixed applications. It is an incredibly powerful tool. Admittedly the learning curve is a little steep, but it's well worth the effort.
Use an external/third party debugger like OllyDbg. (As suggested by MrDywar)
The P/Invoke problems:
As IInspectable pointed out HWND should be passed to unmanaged code using IntPtr.
Windows API data types are well defined. DWORD is always 32 bit. Also, LONG (all caps) is not the same as long (lower case).
The C++ Problems:
As mentioned by IInspectable, the LPPOINT is never initialized, so when you call ClientToScreen() you're accessing uninitialized stack garbage as a pointer, and assigning values. To Fix it you could:
Allocate the memory (your favorite scheme here, LocalAlloc, GlobalAlloc, malloc, calloc.
Make the declaration POINT point;, assign values using point.x & point.y, and use it in the function call as &point.
Make the first parameter's type HWND. The API types, even though they are ultimately typedefs, carry extra meaning with them.
This is not a particular function about EasyHook but about hooking in general. I want to hook a function with this signature:
public: int __thiscall Connection_t::Send(unsigned int,unsigned int,void const *)
This is clearly unmanaged code and I'm trying to hook it with my managed c# code using EasyHook.But I think it's not EasyHook causing problems here but my knowlegde on calling conventions etc...
This is how I define DllImport and delete:
public static int Send_Hooked(uint connection, uint size, IntPtr pDataBlock)
{
return Send(connection, size, pDataBlock);
}
[DllImport("Connection.dll", EntryPoint = "?Send#Connection_t##QAEHIIPBX#Z", CallingConvention = CallingConvention.ThisCall)]
static extern int Send(uint connection, uint size, IntPtr pDataBlock);
[UnmanagedFunctionPointer(CallingConvention.ThisCall, CharSet = CharSet.Unicode, SetLastError = true)]
delegate int DSend(uint connection, uint size, IntPtr pDataBlock);
But the hooked programm keeps on crashing as soon as I inject the hook - no big surprise. I supppose it's a problem of the calling convention and that my hooking-function somehow interferes with the stack of the hooked programm.
So I had a look at another project who do hook the same function but with detours in c++ (the hooking part):
Func = (int (__stdcall *)(unsigned int, unsigned short, void const ))::GetProcAddress(::GetModuleHandle("Connection.dll"), "?Send#Connection_t##QAEHIIPBX#Z");
PVOID DetourPtr;
PVOID TargetPtr;
DetourTransactionBegin();
DetourAttachEx(&Func, SendConnectionHook, &Trampoline, &TargetPtr, &DetourPtr );
DetourTransactionCommit();
And the called function:
__declspec(naked) void SendConnectionHook (CPU_CONTEXT saved_regs, void * ret_addr, WORD arg1, DWORD arg2, DWORD arg3)
{
DWORD edi_value;
DWORD old_last_error;
__asm
{
pushad; /* first "argument", which is also used to store registers */
push ecx; /* padding so that ebp+8 refers to the first "argument" */
/* set up standard prologue */
push ebp;
mov ebp, esp;
sub esp, __LOCAL_SIZE;
}
edi_value = saved_regs.edi;
old_last_error = GetLastError();
OnConnectionSend((void *) saved_regs.ecx, (unsigned char *) arg3, arg2);
SetLastError(old_last_error);
__asm
{
/* standard epilogue */
mov esp, ebp;
pop ebp;
pop ecx; /* clear padding */
popad; /* clear first "argument" */
jmp [Trampoline];
}
}
(Target assembly and c++ example are both compiled with visual c++). I guess I'll have to save some registers and repair the stack before I call the original function? Or any other idea what I'm doing wrong here?
You are trying to hook a C++ class instance method. It has a hidden argument, this. This argument is commonly passed through the ECX register with the __this calling convention. That's what you see that Detours version doing.
Getting this right is quite untrivial, the CPU register values must be preserved early, ECX in particular. That requires a stub that uses machine code, no machine code in a managed stub of course. I doubt that EasyHook has any support for it, it certainly isn't promised in the feature list.
Looks like i figured it out. #Hans Passant was right: I have to save the hidden this argument. EasyHook does actually take care for everything but this (like cleaning up the .net stuff). As this is the first argument i simply did add it to my function (connection is my this reference):
public static int Send_Hooked(IntPtr connection, uint unknown, uint size, IntPtr pDataBlock)
{
return Send(connection, unknown, size, pDataBlock);
}
[DllImport("Connection.dll", EntryPoint = "?Send#Connection_t##QAEHIIPBX#Z", CallingConvention = CallingConvention.ThisCall)]
static extern int Send(IntPtr connection, uint unknown, uint size, IntPtr pDataBlock);
[UnmanagedFunctionPointer(CallingConvention.ThisCall, CharSet = CharSet.Unicode, SetLastError = true)]
delegate int DSend(IntPtr connection, uint unknown, uint size, IntPtr pDataBlock);
Can't really explain why this does work (also I think I did understand most of it :) I really should go back and learn some more assembler/compiling theory.
I want to send keyboard input to a window in another process, without bringing that window to the foreground. I can use PostMessage to fake the WM_KEYDOWN and WM_KEYUP; all I need to know is which window handle should receive the keyboard input -- i.e., something like GetFocus, but for another, non-active application.
The GetGUIThreadInfo API looks promising -- it returns an hwndFocus for another app. But I've had no luck getting it to work from C# on my 64-bit OS. I've copied (and then further tweaked) the declarations from pinvoke.net, but all I ever get back is a generic error code (more details below).
I am setting cbSize before I call GetGUIThreadInfo, so I've avoided the most obvious potential problem.
I'm running 64-bit Vista, so I don't know whether the problem is that I'm not using the API correctly, or that it works differently in 64-bit -- I have yet to find a code sample that specifically says it works successfully in Win64.
Here's sample code. I'm using GetWindowThreadProcessId as recommended, so I don't think the problem has to do with mixing thread IDs with thread handles:
[StructLayout(LayoutKind.Sequential)]
internal struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential)]
internal class GuiThreadInfo
{
public int cbSize;
public uint flags;
public IntPtr hwndActive;
public IntPtr hwndFocus;
public IntPtr hwndCapture;
public IntPtr hwndMenuOwner;
public IntPtr hwndMoveSize;
public IntPtr hwndCaret;
public Rect rcCaret;
}
[DllImport("user32.dll")]
internal static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
[DllImport("user32.dll", SetLastError = true)]
internal static extern bool GetGUIThreadInfo(uint idThread, ref GuiThreadInfo lpgui);
IntPtr GetFocusedHandleFromProcessWithWindow(IntPtr window)
{
var threadId = GetWindowThreadProcessId(window, IntPtr.Zero);
var info = new GuiThreadInfo();
info.cbSize = Marshal.SizeOf(info);
if (!GetGUIThreadInfo(threadId, ref info))
throw new Win32Exception();
return info.hwndFocus;
}
window is a valid window handle; GetWindowThreadProcessId returns a nonzero thread handle. But the call to GetGUIThreadInfo always returns false, and the exception message is always "The parameter is incorrect".
Just in case the problem was that GetGUIThreadInfo somehow doesn't have a 64-bit version, I tried changing all the 8-byte IntPtrs in the GuiThreadInfo declaration to 4-byte ints, but I still got the same error.
Does anyone have a working C# sample of GetGUIThreadInfo on Win64? Or, is there another way to find what the focused child-window handle would be in another app, without making that app active?
I haven't looked at it too closely but one thing jumps out. In your GetGUIThreadInfo call you pass the GUIThreadInfo structure by ref but you've defined it as a class so you are sending a reference by ref, in other words a pointer to a pointer. Either change your GUIThreadInfo to a struct or remove the ref on the parameter and add [In, Out] attributes.