Error: 0x80004005 in HookManager. Why? [duplicate] - c#

This question already has answers here:
SetWindowsHookEx failing in .NET 4.0 on 32-bit machine with "module not found"?
(3 answers)
Closed 5 years ago.
This question is a follow on from: How do you disable system hotkeys in user32.dll? . I have not added it to chat because after googling, this appears to be an issue and I haven't found a solution which works. The error code seems to have multiple causes, one of which being a possibly corrupt dll. The fact that I can't figure out whether or not this is the case is a problem.
The code from this question comes from:
https://www.codeproject.com/articles/7294/processing-global-mouse-and-keyboard-hooks-in-c Look for the file "HookManager.Callbacks.cs"
Useful: https://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx
I keep getting the following error:
Error: System.ComponentModel.Win32Exception (0x80004005): The
specified module could not be found at
Gma.UserActivityMonitor.HookManager.EnsureSubscribedToGlobalKeyboardEvents()
in [REDACTED DIRECTORY]HookManager.Callbacks.cs:line 401
The code causing this:
private static void EnsureSubscribedToGlobalKeyboardEvents()
{
// install Keyboard hook only if it is not installed and must be installed
if (s_KeyboardHookHandle == 0)
{
//See comment of this field. To avoid GC to clean it up.
s_KeyboardDelegate = KeyboardHookProc;
//install hook
s_KeyboardHookHandle = SetWindowsHookEx(
WH_KEYBOARD_LL,
s_KeyboardDelegate,
Marshal.GetHINSTANCE(
Assembly.GetExecutingAssembly().GetModules()[0]),
0);
//If SetWindowsHookEx fails.
if (s_KeyboardHookHandle == 0)
{
//Returns the error code returned by the last unmanaged function called using platform invoke that has the DllImportAttribute.SetLastError flag set.
int errorCode = Marshal.GetLastWin32Error();
//do cleanup
//Initializes and throws a new instance of the Win32Exception class with the specified error.
throw new Win32Exception(errorCode); // this line is causing this
}
}
}
Unless I am mistaken, the culprit from the above code is:
s_KeyboardHookHandle = SetWindowsHookEx(
WH_KEYBOARD_LL,
s_KeyboardDelegate,
Marshal.GetHINSTANCE(
Assembly.GetExecutingAssembly().GetModules()[0]),
0);
So does anyone understand what the problem here is?
What have I tried?
I have tried previously re-creating the entire project and copy+pasting code in case any of the program's other files were corrupted (from copying to/from USB). I had believed the problem was fixed (though I might be mistaken). The problem is now back and what I previously thought would work is not working (re-creating the project).
I will try other solutions I find online, which relate to problems with Windows. If anyone can see anything wrong with the code, please let me know. Though the code came from a very reliable source and loads of people have used it so this seems unlikely.
https://social.msdn.microsoft.com/Forums/en-US/b7d1a35f-3759-4217-91ba-e4416ac19d78/how-do-you-fix-error-code-0x80004005?forum=jscript
I tried the solution which involved "regsvr32 jscript.dll" and "regsvr32 vbscript.dll". It didn't work.

You exchange last two parameters of SetWindowsHookEx(): third parameter should be set to IntPtr.Zero for same process and last one is thread.
You can as well pinvoke the thread id:
[DllImport("kernel32.dll")]
public static extern int GetCurrentThreadId();
SetWindowsHookEx(WH_KEYBOARD_LL, s_KeyboardDelegate, IntPtr.Zero, GetCurrentThreadId());

Related

I am getting C++ compilation issues while compiling my project

I am trying to implement the zoom sdk and want to prevent my screen to be captured and by screen shots for this purpose they have given some functions to be placed inside the project. When I place the code inside the function I start getting some errors and when I remove then the errors are gone.
The code which need to be placed inside the project is as follows:
BOOL CALLBACK EnumWindowsCB(HWND hwnd, LPARAM lParam)
{
SetWindowDisplayAffinity(hwnd, WDA_MONITOR);
return TRUE;
}
void CZoomSDKeDotNetWrap::DisableScreenRecord() {
DWORD pid = GetCurrentProcessId();
EnumWindows(EnumWindowsCB, pid);
uint8_t* func_data = (uint8_t*)GetProcAddress(GetModuleHandle(L"user32.dll"), "SetWindowDisplayAffinity");
}
Please let me know what these errors mean and how to resolve them.
The errors are:
enter image description here
You need to add a reference to the respective library(dll) you're using in the function you're trying to put inside the library.
As seen in your code above you're trying to use standard Windows libraries. Have you tried editing your project properties then linker input options to include user32.lib?
Thank you everyone who answered. Actually it was just because I was not using user32.lib library in the project when I added the errors got removed and it started working for me.

ICE: trying to add a local var with the same name, but different types. during [_RegisterClipboardFormat]

I have a PoC to use some existing Java-codebase in some UWP-app using the most current Visual Studio Community 19 version 16.3.2 and the latest released IKVM 8.1.7195.0. The app builds and runs fine in Debug-mode, but fails to build already in Release-mode with the following error:
MCG0004:InternalAssert Assert Failed: ICE: trying to add a local var
with the same name, but different types. during
[_RegisterClipboardFormat] Ams.Oms.Poc
RegisterClipboardFormat is part of IKVM:
#DllImportAttribute.Annotation(value = "user32.dll", EntryPoint = "RegisterClipboardFormat")
private native static int _RegisterClipboardFormat(String format);
#cli.System.Security.SecuritySafeCriticalAttribute.Annotation
private static int RegisterClipboardFormat(String format)
{
return _RegisterClipboardFormat(format);
}
https://github.com/ikvm-revived/ikvm/blob/master/openjdk/sun/awt/IkvmDataTransferer.java#L95
What I'm wondering is which local variable the error message is referring to? Might be something added implicitly or might have to do with String in Java vs. string in C#? OTOH that file is clearly named .java.
Didn't find much about the error message in general, only the following two links seems to be more interesting:
Variables having same name but different type
Why doesn't C# allow me to use the same variable name in different scopes?
So I'm currently even unsure where the message comes from, Visual Studio/C# directly or IKVM during running code during building Release-mode. I strongly suspect the error is coming from Visual Studio/C#, though.
Searching for the function itself doesn't reveal much of help as well:
Sorry, AWT is not a supported part of IKVM.
https://sourceforge.net/p/ikvm/bugs/225/
Others seemed to have the same problem, because CN1 simply disabled that code entirely in their fork of IKVM:
//#DllImportAttribute.Annotation(value = "user32.dll", EntryPoint = "RegisterClipboardFormat")
//private native static int _RegisterClipboardFormat(String format);
#cli.System.Security.SecuritySafeCriticalAttribute.Annotation
private static int RegisterClipboardFormat(String format)
{
throw new Error("Not implemented");
//return _RegisterClipboardFormat(format);
}
https://github.com/ams-ts-ikvm/cn1-ikvm-uwp/blob/master/openjdk/sun/awt/IkvmDataTransferer.java#L95
Any ideas? Thanks!
There seems to be a workaround by not changing any code at all: The settings of the Release-build contain a checkbox if to use the .NET native toolbox for the build, which is enabled by default. By disabling that the build succeeds without any code change and is as fast as the Debug-build again. Before changing that, the Release-build took a lot longer as well.
Don't know what that means regarding actually calling native code, if that fails or not, because my app doesn't use those. I guess it would fail, depending on if it works in Debug or not. Additionally, I'm not sure if the Windows store accepts such a modified Release-build, but as UWP-apps aren't forced to use native code at all, I guess there's a good chance things are going to work.

LibTiff.NET ReadDirectory is giving System.ObjectDisposedException Only During Unit Tests

Edit: FYI for future readers, this issue has been fixed as of version 2.3.606.0 of BitMiracle's LibTiff.NET.
I'm using BitMiracle's LibTiff.NET (version 2.3.605.0 and below) in my C# library (compiled at .NET 3.5 | x86) and keep getting this exception when I call ReadDirectory: System.ObjectDisposedException: Cannot write to a closed TextWriter
I realize that this seems to indicate that I have already disposed of my image before making the call...but I have not specifically done so. Is this a bug in the library or am I really missing something here?
Here is my code:
public static bool IsTiffBiTonal(String tiffFilePath)
{
VerifyFileExistence(tiffFilePath);
using (Tiff tiff = Tiff.Open(tiffFilePath, "r"))
{
do
{
if (tiff.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt() == 1)
{
continue;
}
return false;
}
while (tiff.ReadDirectory()); //Error occurs here
}
return true;
}
EDIT: Ok, I have more information after some further testing, this is only happening when I'm running my unit tests! Don't know why that would change anything though.
Because of other threads talking about unit testing and getting this same error when trying to write to the console (ObjectDisposedException when outputting to console) I realized that the LibTiff.NET library was trying to write to the error console. After looking through the source code, I found that this code:
using (TextWriter stderr = Console.Error)
{
...
}
Because they were wrapping all of the writes to the error out in a using, it was disposing of the Console.Error object after the first write to the error out. This caused my error on the second time around (ReadDirectory does what calling Next on a linked list does). So I removed the using and the problem was fixed!
TextWriter stderr = Console.Error;
...
So, the lesson here: don't dispose of your standard outputs :)
I've asked another question regarding why they were ever allowed to dispose of the standard output in unit tests but not in other situations here: .NET - Why is disposing of standard output only allowed during unit tests?. If you have any answers to the question...please post it there.

Problems accessing the Running Object Table

In my program I use the Running Object Table (ROT) to ensure only one instance of my program is running. Since I "inherit" that code from a developer who unfortunately left the company, I am the poor guy to solve the problems. The code works fine, but we have 3 customers (out of 39,000) who will get an AccessDeniedException. Every customer runs the software in user mode.
Any suggestions what could be wrong?
bool retVal = false;
IMoniker[] arrMoniker = new IMoniker[1];
IBindCtx bindCtx = null;
string displayName;
int hResult;
int mkSys;
Guid clsidRot;
bool guidCompare = false;
IntPtr number = IntPtr.Zero;
moreObjectsListed = false;
objectFromRot = null;
try
{
// check the objects in the running object table for fitting the specified class id
while ((retVal == false) && (0 == enumMoniker.Next(1, arrMoniker, number)))
{
hResult = CreateBindCtx(0, out bindCtx);
if (hResult == 0)
{
arrMoniker[0].IsSystemMoniker(out mkSys);
if (mkSys == 4)
{
try
{
// the display name is the class id of the object in the table
// --> AccessDeniedException raises here <--
arrMoniker[0].GetDisplayName(bindCtx, null, out displayName);
clsidRot = new Guid(displayName.Substring(1));
guidCompare = clsidRot.Equals(clsid);
}
catch(Exception) {}
// an object with fitting class id was found
if (guidCompare == true)
{
rot.IsRunning(arrMoniker[0]);
rot.GetObject(arrMoniker[0], out objectFromRot);
retVal = true;
}
}
}
}
}
finally
{
if (arrMoniker[0] != null)
{
moreObjectsListed = true;
Marshal.ReleaseComObject(arrMoniker[0]);
}
if (bindCtx != null)
{
Marshal.ReleaseComObject(bindCtx);
}
}
Edit: Here is the requested code for the registration of an object in the ROT:
internal static extern uint RegisterActiveObject([MarshalAs(UnmanagedType.IUnknown)]object pIUnknown, ref Guid refclsid, uint flags, out uint pdwRegister);
internal const uint ActiveObjectStrong = 0;
...
NativeMethods.RegisterActiveObject(this, ref guid, NativeMethods.ActiveObjectStrong, out this.runningObjectTableRegisteredId);
Edit 2:
First of all a big EXCUSE to all investigators, we don't get an AccessDeniedException it is an System.UnauthorizedAccessException (HRESULT: 0x80070005 (E_ACCESSDENIED)).
Second the answers to the questions of "investigator" Ken Brittain:
- SharePoint is not in the mix
- I'am shure to request the correct object from ROT
- Another hint maybe that 1 of the 3 problem (besides 39,000 working correctly) is running the apps on a WTS (Windows Terminal Server)
Edit 3:
Here is a stack-trace of one of those exceptions: (I've translated the stacktrace, because it was on a german machine)
System.UnauthorizedAccessException: Access denied (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
at System.Runtime.InteropServices.ComTypes.IRunningObjectTable.EnumRunning(IEnumMoniker& ppenumMoniker)
at Datev.Framework.DirectStart.RunningObjectTableClientManager..ctor()
The rest of the stack trace is in our code. Markable in this case is that the exception is raised in the constructor of our RunningObjectTableClientManager. Here is the code of that constructor:
private IRunningObjectTable rot;
private IEnumMoniker enumMoniker;
public RunningObjectTableClientManager()
{
int retVal = GetRunningObjectTable(0, out this.rot);
if (retVal == 0)
{
rot.EnumRunning(out this.enumMoniker);
}
}
In my experience the probability of a GUID collision, while possible appears unlikely, so it was not investigated. The first track I took was looking what could cause the AccessDeniedException. Working backward from there you can see that GetDisplayName does not explicitly throw this exception (or return anything similar).
So what does? Your code appears to be in C#. Unless I am mistaken using COM from C# will go through a primary interop. There are only two (2) interops that expose an IMoniker interface that I could find:
System.Runtime.InteropServices.ComTypes contains IMoniker
Microsoft.VisualStudio.OLE.Interop
contains one as well IMoniker
You are talking about an application so my gut tells me you are using the runtime version. Looking at the calls I could not find a call returning any form of an Access Denied HRESULT or simething similar. The VisualStudio interop does mention the following about access and trust: Using Libraries from Partially Trusted Code. This sounded like a path to follow and would apply if your are using the Visual Studio interops.
If you are using the runtime services namespace which is contained in the mscorlib.dll assembly (which according to this page .NET Framework Assemblies Callable by Partially Trusted Code is marked as callable partially trusted code) the explanation does not appear to apply.
So now what? I did a search for AccessDeniedException and found no supported implementation other than an Microsoft.Office.Server.ApplicationRegistry.Infrastructure.AccessDeniedException class that is marked as obsolete in MSDN. The class is filed under the SharePoint 2010 class library.
So here are my questions: Which interop are you using? Is SharePoint in the mix at all? I said previously GUID collision was not suspected but now I am questioning that assumption. Are you requesting the proper object from the ROT? Is this object running under another process (meaning not yours)?
From this site it appears it could be due to a registry setting or due to the security settings on an object registered in the table:
Check "HKLM\Software\Network OLE\Enabled". Fail the
request if zero.
Check "HKCU\Software\Network OLE\Enabled". Fail the
request if zero.
Before performing any operation against a ROT entry
(i.e., IRunningObjectTable::Revoke,
IRunningObjectTable::IsRunning,
IRunningObjectTable::GetObject,
IRunningObjectTable::NoteTimeChange,
IRunningObjectTable::GetTimeOfLastChange, or when
including an entry in an IEnumMoniker::Next of an
IEnumMoniker returned from
IRunningObjectTable::EnumRunning), check the call against
the SECURITY_DESCRIPTOR available from
IRunningObjectTable::Register. This will be either the
value returned by the object's
IActivationSecurity::GetSecurityDescriptor at the time of
IRunningObjectTable::Register or will have been taken
from "HKCU\Software\Network OLE\DefaultROTSecurity" or
"HKLM\Software\Network OLE\DefaultROTSecurity" at the
time of IRunningObjectTable::Register if the object did
not support IActivationSecurity.
Perhaps this isn't the answer you are looking for, but having inherited this code, have you stopped to question if this was even the right technique for your use case? This is the first time I've seen a C# app use Com Interop for something like preventing multiple app instances. I've never had good experiences with Com and found similar unexplained or undocumented exceptions.
Why not take a look at an alternative technique for preventing multiple application instances? I have used a Mutex in past solutions of mine and never had an issue. While I don't have my past code handy, this issue has been covered several times before on stackoverflow with some pretty good answers that have been peer reviewed and community edited.
For example 'What is a good pattern for using a Global Mutex in C#?' has a good community edited answer that seems to take into account all sorts of odd ball race conditions and thread/process terminations as well as the potential security issues.
So my recommendations would be to step away from Com Interop and grab a Mutex implementation instead.

Open a dialog box from a DLL

I have a Visual Studio 2008 solution with two projects: a C# Windows Forms application and a C++ DLL. The DLL opens a custom CFileDialog. Here is a toy version that demonstrates the problem, where the C# app is just a button to launch the dialog and a label to show its result:
DialogApp.cs:
...
public partial class Form1 : Form {
...
[DllImport("DialogDll.dll")]
static extern int OpenDialog();
...
private void button1_Click(object sender, EventArgs e) {
int r = OpenDialog();
label1.Text = r.ToString();
}
}
DialogDll.h:
extern "C" {
__declspec(dllexport) int __cdecl OpenDialog();
}
DialogDll.cpp:
#include <afxdlgs.h>
#include "DialogDll.h"
extern int __cdecl OpenDialog() {
CFileDialog d(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("All Files (*.*)|*.*||"), NULL);
if (d.DoModal() == IFOK) {
return 4;
} else {
return 9;
}
}
When I run this, I get an error about a debug assertion failing, asking to Abort|Retry|Ignore. The assertion is afxCurrentResourceHandle != NULL. How do I get rid of this problem? If I click Ignore, I get my dialog, and everything appears to work fine.
I've already tried following the instructions here:
http://msdn.microsoft.com/en-us/library/7a51wcfx.aspx
These directions say the problem is that a DLL doesn't have a CWinApp object, and I should add AFX_MANAGE_STATE(AfxGetStaticModuleState()) to the beginning of each function call. I did that, and had to resolve a linker issue by following the directions here, manually specifying the entry point for my DLL: http://social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/0b154e1c-141f-4567-bb24-1ac7c8ee2713/ (The parts about changing the order of the .libs didn't work for me.)
But now I'm getting another error:
LoaderLock was detected:
Attempting managed execution code inside OS Loader Lock. Do not attempt to run
managed code inside a DllMain or image initialization function since doing so
can cause the application to hang.
Good grief! Am I even going in the right direction? I've done years of programming, but I'm pretty new to the Windows platform. I think after all this work, my question is still pretty simple: How do I open a CFileDialog from my dll?
You are probably going in the right direction. I am assuming that you want/need to use MFC in your DLL.
The WinApp and MANAGE_STATE advice was good.
Are you throwing /clr or /clr:pure on any of your C++ source files? Why? Does your C++ DLL mix managed and native code together?
The fix for this trivial app is to not throw /clr. This will make all your C++ code native and ensure that you are not at risk of calling managed static initialisers from the loader lock.
Martyn
Please see comment above, but I would recommend as my answer:
Use System.Windows.Forms.OpenFileDialog instead OR
Use GetOpenFileName

Categories