addmonitor win32 call fails with lasterror 5 - winapi

I have created a very small win32 console application (AddPrintMonitor.exe) that does nothing more than makes a call to AddMonitor. Here is a small snippet:
MONITOR_INFO_2 m_MonitorInfo2;
m_MonitorInfo2.pName = lpMonitorName;
TCHAR env[12] = TEXT("Windows x64");
m_MonitorInfo2.pEnvironment = env;
m_MonitorInfo2.pDLLName = lpDllName;
if ( !AddMonitor(NULL, 2, (LPBYTE) &m_MonitorInfo2) )
{
DWORD error = GetLastError();
std::cout << "Last error = " << error << "\n";
return PRINTER_ERR_API;
}
When I run this as a member of the Administrators group is fails. GetLastError() returns 5. When I run it as "The Administrator" it succeeds with no issues. I am running on Windows 7 x64. I am trying to install the redmonnt.dll and I do have the 64 bit version of that dll. This task is part of a larger install for a PostScript driver. I've only isolated out the AddMonitor portion to eliminate other external issues.
Error 5 is an access violation or security issue. My first question is why can't a member of the administrators group carry out this function call? What's the difference between the actual administrator and a member of the administrators group given this context?
Other details to note. I am using InstallShield 12 (old) for my Printer installation (addmonitor is only part). I am adding a monitor, port, driver and printer all through win32 function calls. Prior to running my AddPrinterMonitor.exe I made sure that the redmonnt.dll does exist in the system32 directory. Actually, whether the dll is present there or not makes no difference for the error I see. I did see posts about setting SeLoadDriverPrivilege. This is a dead end for me as I checked and the administrators group can Load/Unload device drivers.
Also, I am using win32 calls to get this done. This worked (I mean all of it worked) without any problems on Win2K, WinXP and Windows Server 2003. With the newer OS's like Windows 7 there are several difficulties. Is there a better way that I've overlooked? I been very frustrated trying to get this to work, so I've begun to question the approach for Vista and higher.
More initialization code:
#define MONITOR_NAME "My Redirected Port"
#define MONITOR_FILE "redmonnt.dll"
MONITOR_NAME is passed to lpMonitorName and MONITOR_FILE is passed to lpDllName
thanks

Related

Asynchronous error with PCOMM V.14 Automation

I have some VBscripts that automate IBM Personal Communications
Since I have to use the version 14 (64 bits) sometimes I get errors:
If I use the function CreatObject the error is: The specified module could not be found.
If I use the Wscript method Wscript.CreateObject the error is: WScript.CreateObject: Could not create object named "PCOMM.autECLConnMgr.1"
I have tried 2 ProgID for each of the 4 DLL
"PCOMM.autECLConnMgr" or "PCOMM.autECLConnMgr.1" "PCOMM.autECLPS" or "PCOMM.autECLPS.1" "PCOMM.autECLConnList" or "PCOMM.autECLPS.1" "PCOMM.autECLOIA" or "PCOMM.autECLPS.1"
I'm using LENOVO workstations with Windows 10 Enterprise Build 1809 64 bits
And also tried
C:\Windows\SysWOW64\cscript and C:\Windows\System32\cscript
Both works and both sometimes return the errors
Also have tried 2 different workstations in spite of those machines have the same "image" of software...
With IBM PC Version 12 this didn't happen!
And here is my pain... The error happens just the first time the script runs... Then okay.
I even can't induce the error !!
Any hint would be appreciated.
João

Visual Studio 2013 Express MFC program could not work after Windows 10 update to 1903

These days I upgrade to Windows 10 to 1903, however, after that, my MFC program soon disappears after running up. The solution is composed of an MFC project and a DLL project, they are static linked.
Thank you all for paying attention to my question. So far the issue disappear, and below is the story.
1) I modified my code to dynamic link.
2) I got the message of System AccessViolationException when calling the second API of DLL.
3) I found think link. Programs randomly getting System.AccessViolationException
4) In the post, someone mentioned that change platform setting may solve it
5) So I change my platform setting to x64
6) It works
7) I continue to finish my work base on x64 and everything looks OK
8) However I was required to provide x32 version Orz
9) So I have to dig this question as very first priority
10) However, base on the modified source code, now x32 is able to run
Sorry there is not so many useful information.....
There is more information.
I tried to install VS2013 Express at another Win7 64bit PC, which is able to re-produce the phenomenon. It does not matter x86 or Win32 this time.
When Running "Local Windows Debugger," (or use hostkey of: F10, F11, F5)
the debug interface soon finish, with below log:
The program '[2576] test.exe: Native' has exited with code 1 (0x1).
However, in my code did not write any pattern like "return 1"
Below is the main function built-in
[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
// Enabling Windows XP visual effects before any controls are created
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it
Application::Run(gcnew Form_main());
return 0;
}

winUSB error (possible .inf issue)

I would really really appreciate some help with winUSB.
I followed all the steps that were listed in msdn website
http://msdn.microsoft.com/en-us/library/windows/hardware/hh450799(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/hardware/ff540174(v=vs.85).aspx
I tried to run it on Windows 7 with Visual Studio 2010. Even though it compiles with no errors, I cannot pass the function
SetupDiEnumDeviceInfo, and it errors out (I think error #259).
I don't know how to pass this error.
However I am not sure of the few steps in the process:
What does msdn talk about with "A signed catalog file for the package. This file is required to install WinUSB on x64 versions"? What is a signed catalog package? How do I set this?
It also talks about making some directory (For example, c:\UsbDevice) to put the .inf file in there ! But how does my VS project know that I am pointing to c:\UsbDevice, and how does it know what the name of the ".inf' file should be? what should I call the .inf file? And how to point the project to it?
Inside the .inf file there are two GUID numbers. I can get the Class GUID number by going to the Device Manager. But how do I set the Device Interface GUID?
Please help.
Is is possible that the error that I am getting is because I don't have one of the following items set up correctly?
Thanks,
--Rudy
I developed an application about 2 years ago that I needed to use WinUSB, it's not fresh in my mind but looking at my code now I can see that I did use this function: SetupDiEnumDeviceInfo, but as I remember it wasn't a problem for me.
As you probably know, the WinUSB is an API of Windows for you to communicate with an usb hardware. The hardware must have it's driver already, so, you have to know the GUID of your device
Answering your steps:
1. Signed catalog is the .cat file generated from an inf, you can genarate it using inf2cat.exe, it's somwhere in your machine. This is just a step for signing your winusb driver. To sign it you will need to submit your .inf and the .cat files for the WHQL (windows hardware quality labs) http://www.microsoft.com/whdc/whql/ , this is not important at this moment, I've never signed my WinUSB driver, and it works in the x64 machines with a inelegant warning saying that my WinUSB driver might be dangerous (despite it's not!)
2. The application you are developing doens't need to know where the .inf file is, the .inf file is meant to install the WinUSB driver, the application will communicate with the driver trough the GUID number of the device after the driver is properly installed. Here is part of the code that is necessary to connect to the device after the WinUSB driver is correctly installed.
LPGUID _lpGuid = (LPGUID) malloc (sizeof(GUID));
HRESULT result = CLSIDFromString (L"{A54E04AD-E06A-4A03-95BB-25AACC4E6CCA}", _lpGuid);
...
bResult = SetupDiEnumDeviceInterfaces(deviceInfo,
NULL,
_lpGuid,
0,
&interfaceData); //If the function succeeds
//the return value is nonzero.
// [1]
deviceInfo = SetupDiGetClassDevs(_lpGuid,
NULL, NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (deviceInfo == INVALID_HANDLE_VALUE)
{
//lblDispStatus->Caption = "Erro 1 - deviceInfo";
return false;
}
// [2]
interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
bResult = SetupDiEnumDeviceInterfaces(deviceInfo,
NULL,
_lpGuid,
0,
&interfaceData); //If the function succeeds
//the return value is nonzero.
InterfaceData is passed as reference, so you will have the ability to call the next function, that is SetupDiGetDeviceInterfaceDetail
3.Who developed the driver? He must know the GUIDs you need.
All I know from WinUSB I fount at the poor WinUSB documentation, you will need tons of patiante to read all their messy information. And for your unlucky, it's not fresh in my mind right know, I would have to take a deep look at this subject to help you more.
This page seems important at the point you are, take a look at this: http://msdn.microsoft.com/en-us/library/windows/hardware/ff540174%28v=vs.85%29.aspx

Visual Studio C++ RegOpenKeyEx() registry Access is denied error Windows 7 64 bit

I'm running a C++ program (which works great on 32 bit Win XP) on Windows 7 64 bit in debugger under Visual Studio 2010 and I am unable to open an existing registry key with the following code:
#define ACCESS (KEY_WRITE | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS)
HKEY hKey;
long dwErrorCode = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\MYTHING", 0, ACCESS|KEY_WOW64_64KEY, &hKey);
if (dwErrorCode != ERROR_SUCCESS)
{
// display error message
}
The error code returned is: 5 with the system message being "Access is Denied".
This does work if I run the Visual Studio 2010 as Admin, however I'd rather not have to do that. Can anybody offer a suggestion?
Update: I forgot to mention, what I am doing here is porting legacy code from Windows XP. As such, I don't have the option of changing the fundamental structure of how this software was written. Since the legacy code uses the registry, that is what the ported code must do also.
Also, I would rather not make changes to my specific computer -- since that means I would have to change every computer that I want to run this on. This could get messy as there are a lot of machines affected. For example, I don't want to turn off UAC for the entire machine.
Further update: I haven't found a solution that I'm happy with. Have decided to ignore error code 5 for purposes of debugging and that seems to be working well enough for now. I'm trying to understand how standard apps like Word, Firefox, etc appear to be using the registry for all kinds of settings and yet are not elevated nor do I have to give them special permissions to make changes to the registry?
Ok, I found the answer to my question so I'll post it here in case anybody else needs it for future reference. This thread turned out to be helpful even though it is actually on the topic of C#:
http://social.msdn.microsoft.com/Forums/da-DK/netfx64bit/thread/92f962d6-7f5e-4e62-ac0a-b8b0c9f552a3
Basically, I needed to change my permission to read the 32 bit registry instead of the 64 bit one like so:
HKEY hKey;
long dwErrorCode = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\MYTHING", 0, ACCESS|KEY_WOW64_32KEY, &hKey);
if (dwErrorCode != ERROR_SUCCESS)
{
// display error message
}
Voila, everything works now! Thanks for your efforts everyone.
Update: it turns out this didn't work as well on my other machine, which led me to discover that someone must have changed access rights to the 32 bit registry on one of my machines. So it is still necessary to give the User access rights to the registry key you want to work with.
You need to run the process in elevated mode, or turn off UAC. You can of course assign access rights to your specific registry key that allows you access.
I have faced same issue. I have solved using following:
LPCTSTR subKey = TEXT("Software\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\App Paths");
LONG openRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_WOW64_32KEY && KEY_ALL_ACCESS, &hKey);

LoadLibrary on OCX file fails in Windows 7 x64

I need to open a html help file from within a legacy windows application written in old version of C++ Builder. HtmlHelp is loaded via HtmlHelp.ocx, which I am loading via LoadLibrary.
This has worked fine for years, but it does not work anymore in Windows 7 x64. It might also fail under Windows7 x86, but I don't have any computer with this OS, so I can't try it out at the moment.
I am loading hhctrl.ocx dynamically as follows:
#define HHPathRegKey "CLSID\\{adb880a6-d8ff-11cf-9377-00aa003b7a11}\\InprocServer32"
bool THTMLHelper::LoadHtmlHelp()
{
HKEY HHKey;
DWORD PathSize = 255;
char Path[255];
bool R = false;
if (::RegOpenKeyExA(HKEY_CLASSES_ROOT, HHPathRegKey, 0, KEY_QUERY_VALUE, (void **)&HHKey) == ERROR_SUCCESS)
{
if (::RegQueryValueExA(HHKey, "", NULL, NULL, (LPBYTE)Path, &PathSize) == ERROR_SUCCESS)
{
//*****************************************
//LOADING FAILS HERE
//PATH IS %SystemRoot%\System32\hhctrl.ocx
//*****************************************
HHLibrary = ::LoadLibrary(Path);
if (HHLibrary != 0)
{
__HtmlHelp = (HTML_HELP_PROC) ::GetProcAddress(HHLibrary, "HtmlHelpA");
R = (__HtmlHelp != NULL);
if (!R)
{
::FreeLibrary(HHLibrary);
HHLibrary = 0;
}
}
}
::RegCloseKey(HHKey);
}
return R;
}
I checked if %SystemRoot%\System32\hhctrl.ocx exists on the Windows 7 system and it does.
Why does loading it via LoadLibrary fail? How can I work around this problem?
EDIT: GetLastError says (in German, so I am just translating): "Could not find file." But I debugged the function and the path is "%SystemRoot%\System32\hhctrl.ocx" and the file does exist.
Also, since two answers point in the direction of 64-bit vs 32-bit problems: My application is a 32 bit executable compiled in C++ Builder 5, so it should be a 32 bit process if I'm not mistaken. Or am I wrong to assume that?
Use ExpandEnvironmentStrings function to expand %SystemRoot%\System32\hhctrl.ocx to real path on user's intallation. 64bit OS will redirect expanded path to 32bit dll correctly.
You can't load 32bit dlls in a 64bit process, and visa versa. ActiveX controls are, of course, Dlls.
You can sometimes work around this by getting the 32bit ActiveX to load as an out-of-process server - its then hosted in a seperate 32bit (or 64bit) process as appropriate. This requires that the ActiveX onlyuses interfaces the system already knows how to marshal, and/or the project built 64bit AND 32bit versions of the proxy stub dll.
Depends is a tool that is very useful when you need to figure out why Dlls wont load. Of course, as a 32 bit application on a 64bit OS you need to know that 32 bit applications do NOT get access to %SYSTEMROOT%\System32 and, also do NOT read and write from HKCR directly. System32 actually contains the 64bit OS binaries, and HKCR contains the registry entries for 64bit apps.
A kernel process called 'reflection' redirects 32bit apps completely transparently to from System32 to %SYSTEMROOT%\SysWow64.
Likewise, registry access to HKEY_CLASSES_ROOT is redirected to `HKEY_CLASSES_ROOT\Wow6432Node'.
You need to know this of course, because explorer and regedit are 64bit processes and will happily show you the 64bit contents of System32 and HKCR. You need to explicitly navigate to the 32bit nodes to double check the view your 32bit process is going to get.
I have the exact same problem right now running W7 (x64).
I got it to work when I changed the "%SystemRoot%\System32\hhctrl.ocx" to "c:\windows\System32\hhctrl.ocx", but I guess I need to figure out why %SystemRoot% resolves wrong.
btw: I'm building a 32bit app on BCB2007.

Resources