Visual C++ err: RegGetValueA could not be located - c++

Attempting to write a simple registry-check script in Visual Studio 2010, running on XP SP3 x86.
No errs are thrown on build, but on debug the program exits with the following error:
The procedure entry point RegGetValueA
could not be located in the dynamic
link library ADVAPI32.dll
Here is the entire code of the program.
// #define _WIN32_WINNT 0x0501
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
int main(int argc, char *argv[])
{
long reg = RegQueryValueEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", NULL,NULL,NULL,NULL);
// if (reg!=ERROR_SUCCESS) MessageBox(0, "Error Opening Registry Key", "Error", 0);
return 0;
}
The comments in the code above where added based on an answer by wmeyer.
When uncommented, the code does not exit with that error, but throws a different error:
Debugging information for Test5.exe
cannot be found or does not match.
Binary was not built with debug
information. Do you want to continue
debugging?
If I continue, the MessageBox pops up with "Error Opening Registry Key".
I have tried replacing the RegQueryValueEx function with the following three other methods, one at a time.
I KNOW THAT TWO OF THEM ARE VISTA ONLY, but I wanted to see if the error would be different.
It wasn't.
long reg = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_ALL_ACCESS, hKey);
// Vista+ PHKEY hKey;
long reg = RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", hKey);
long reg = RegGetValue(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", "", RRF_RT_ANY, NULL, NULL,NULL);
I've already lost hours trying to work out several other errors, such as "cannot convert parameter 1 from 'char' to 'LPCWSTR'" - which was solved by changing the configuration
and "Cannot find or open the PDB file", solved by changing the configuration.
So again, the question to be clear:
How do I deal with the error?
How did wmeyer's suggestion of adding a header to filter out Vista-only methods help, when the prog has no Vista methods to begin with? And why does the program still not work?
My computer definitely does have a advapi.dll file in Windows/syatem32.
EDIT:
Completely rewrote the question when the answers pointed out how unclear it was.
Originally I had assumed that Visual Studio 2010 is not backwards compatible with XP.
I've been forcefully told that is incorrect, but still can't get VS to work.

If you want your code to run in XP or an earlier system use RegQueryValueEx.
In any case, you should check the documentation first and then search Google. The Win32 API is very well documented, with details on retrieving data from the registry and supported OS information in every function's page, e.g. RegGetValue is supported in XP 64bit and later.

You should set _WIN32_WINNT to the Windows version you are targeting.
See here: http://msdn.microsoft.com/en-us/library/aa383745(v=vs.85).aspx#setting_winver_or__win32_winnt

Related

"unknown error" from std::error_code on Windows

I have a strange problem with system error messages obtained from std::error_code on Windows. When I build and run test program 1 (see below) using my locally installed Visual Studio, error messages for all system error codes come out as "unknown error". On the other hand, when building and running the same program on the same version of Visual Studio through Godbolt / Compiler Explorer, proper error messages are produced (see test program 1 and output below).
I tested this with Visual Studio 2022 version 17.3.3 (MSVC 19.33) on Windows 10.
I am using the community version of Visual Studio.
I have tried to build locally using the developer command prompt (cl test.cpp), using a Visual Studio console project (all settings at default), and using a Visual Studio CMake project (all settings at default). It makes no difference. In all cases, all error messages come out as "unknown error".
I am not experienced with Visual Studio, so I may definitely be making a very basic mistake.
Any advice as to how I can further diagnose the problem is also welcome.
Output from test program 1 (see below) when built and run through Godbolt / Compiler Explorer:
message = 'The directory is not empty.' (193331629)
Output from test program 1 (see below) when built and run locally:
message = 'unknown error' (193331629)
Output from test program 2 (see below) when built and run locally:
message = 'The directory is not empty.' (193331629)
Test program 1:
#include <windows.h>
#include <system_error>
#include <stdio.h>
int main()
{
std::error_code ec(ERROR_DIR_NOT_EMPTY, std::system_category());
printf("message = '%s' (%lld)\n", ec.message().c_str(), static_cast<long long>(_MSC_FULL_VER));
}
Test program 2 (for contrast):
#include <windows.h>
#include <stdio.h>
int main()
{
char buffer[256];
DWORD len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, ERROR_DIR_NOT_EMPTY, 0, buffer, 255, NULL);
while (len > 0 && (buffer[len - 1] == '\n' || buffer[len - 1] == '\r'))
--len;
buffer[len] = '\0';
printf("message = '%s' (%lld)\n", buffer, static_cast<long long>(_MSC_FULL_VER));
}
Ok, the problem in my case is that the system locale is set to "en-GB" and not "en-US".
If I pass language identifier 2057 (en-GB) to FormatMessage() I get no error message, but if I pass 1033 (en-US), I do.
So far, I have not been able to change the system-level locale, but even if it can be done, it seems rather suboptimal that system error messages fail to work if my system locale is set to "en-GB".
I wonder if there is a rational idea behind this behavior, or if it is just plain broken.
In any case, the solution in my case, I think, is to introduce a custom error category that invokes FormatMessage() with a language identifier of 0 (see https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-formatmessage), and then forward to the native system error categeory in the functions that deal with mapping to generic error condition.

TDM-GCC raises error: Undefined reference to a method I never called

This is with the compiler that comes with Dev-C++ when run on Windows 7, "TDM-GCC 4.9.2 64-bit Release". The same thing happens with the 64-bit version as well. The "add the following flags when calling the linker" in "Compiler Options" is set to -static-libgcc -lws2_32, and "add the following flags when calling the compiler" is std=c++11.
Unfortunately, I can't get much more information than that because this is a very, very locked down computer.
Once I get home, I'll test it there and edit in any new information.
A test file:
#include <windows.h>
#include <psapi.h>
#include <iostream>
int main() {
HANDLE h = GetCurrentProcess();
TCHAR name[100];
GetProcessImageFileName(h, name, 100);
std::cout << "Name is " << std::endl;
}
When compiled, it gives the following error:
C:\Users\[REDACTED]\AppData\Local\Temp\ccQz3L9P.o:test.cpp:(.text+0x2f): undefined reference to `GetProcessImageFileNameA'
As best as I can tell, it's calling GetProcessImageFileNameA instead of GetProcessImageFileName because of a #define in psapi.h:
#define GetProcessImageFileName __MINGW_NAME_AW(GetProcessImageFileName)
__MINGW_NAME_AW(func) is #defined in _mingw_unicode.h as func##A, which if I understand it correctly is where the new method name is coming from.
Back in psapi.h, DWORD WINAPI GetProcessImageFileNameA(HANDLE, LPSTR, DWORD); is declared, but I haven't found its definition anywhere, and Dev-C++ can't either. I'm fairly certain that's the problem.
How can I fix it? I'm open to anything, up to and including switching compilers or IDEs, as long as I can put whatever I use on a flash drive and carry it around with as little annoyance as possible, and that the end result doesn't require admin privileges to run.
GetProcessImageFileName is a windows API function and you need to link in the correct library to get to it.
It is defined as a macro to be either GetProcessImageFileNameA or GetProcessImageFileNameW depending whether you are compiling "wide" or "narrow".
The Win32 API has Unicode and ascii versions of each function (at least the functions that take strings). In general, the ascii version converts the characters to Unicode and calls the other implantation internally.
you need to link Psapi.lib or Kernel32.lib into your project. I am not sure about your compiler but in VC++ you add #pragma comment(lib, "Psapi.Lib") to your code or add Psapi.lib in additional libraries of project properties.
Sam

How to migrate a program with Common Controls from Visual C++ 6.0 to Visual C++ 2010 (on 64-bit machine)

I am attempting to migrate a Visual C++ 6.0 program (originally written on a Windows NT machine) to Visual C++ 2010 for use on my 64-bit Windows 7 PC. The program compiles fine but there is a runtime assertion failure which yeilds the following output in the debugger:
CoCreateInstance of OLE control {F9043C85-F6F2-101A-A3C9-08002B2F49FB}
failed.
Result code: 0x80040154
Is the control is properly registered?
Warning: Resource items and Win32 Z-order lists are out of sync. Tab
order may be not defined well.
Warning: CreateDlgControls failed during dialog init.
The failed assertion is on line 925 of occcont.cpp:
ASSERT(IsWindow(pTemp->m_hWnd));
I understand from http://dynamicsuser.net/forums/p/25968/140697.aspx that the Microsoft Common Dialog Control v6.0 might not be registered. I registered it with Regsrv32.exe and restarted windows but the error persists.
My goal is to tell whether this old program can work with new tools--not to actually rewrite the old program (though that will come later). Is it possible to make the old program run on my newer machine?
EDIT: Addition of the code which causes the assertion failure
BOOL CCameraSimulationApp::InitInstance()
{
AfxEnableControlContainer();
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
INITCOMMONCONTROLSEX InitCtrlEx;
InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
InitCtrlEx.dwICC = ICC_PROGRESS_CLASS;
if (!InitCommonControlsEx(&InitCtrlEx))
{
printf("Common Controls failed to initialize");//debug
}
CCameraSimulationDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
...
0x80040154 is REGDB_E_CLASSNOTREG. That means that the class has not been registered.
{F9043C85-F6F2-101A-A3C9-08002B2F49FB} is the Commom Dialog Control.
So, it seems that that control is not registered. You attempted to register it but I'd guess that you registered the 64 bit version. You are likely compiling a 32 bit program and so need to register the 32 bit version.
regsvr32 C:\Windows\SysWOW64\ComDlg32.ocx
Make sure you do this whilst elevated. That said, I would expect the control to be registered out of the box.
Finally, it's 2015 now and you should not be using this control anymore. Try to wean yourself onto something more modern.
I'd also comment that there's no need for you to re-compile the program. To start with I'd concentrate on getting your existing executable to work on the new machine.

The procedure entry point _gxx_personality_v0 could not be located in the dynamic link library libstdc++-6.dll Error

Yesterday I decided to download, install, and attempt to use Allegro 5. I also downloaded Code::Blocks 12.11 w/ the MinGW compiler. I set up everything and installed everything correctly (or so I thought) and tried to run a sample code to see if it would work:
#include <stdio.h>
#include <allegro5/allegro.h>
int main(int argc, char **argv){
ALLEGRO_DISPLAY *display = NULL;
if(!al_init()) {
fprintf(stderr, "failed to initialize allegro!\n");
return -1;
}
display = al_create_display(640, 480);
if(!display) {
fprintf(stderr, "failed to create display!\n");
return -1;
}
al_clear_to_color(al_map_rgb(0,0,0));
al_flip_display();
al_rest(10.0);
al_destroy_display(display);
return 0;
}
When I attempt to compile and run the program an error message box appears saying "The procedure entry point _gxx_personality_v0 could not be located in the dynamic link library libstdc++-6.dll." I searched the web for about an hour trying to find a fix for this problem, like I do for most things, but I came up empty handed. I'm wondering if anyone has any ideas for any fixes to this problem, if so, let me know ASAP! Thanks in advance!
__gxx_personality_v0 is used in the exception handling of the C++ library. MinGW can support a couple different exception models on the x86: sjlj (setjmp/longjmp) or DWARF (DW2). As far as I know, which model will be used is compiled into the compiler - it's not something that can be selected with a command line option.
The sjlj exception model will link to __gxx_personality_sj0, the DW2 exception model links to __gxx_personality_v0. It seems like your compiler is building for the dw2 exception model, but at runtime it's finding a libstdc++-6.dll that was built with the sjlj model. See if you have multiple versions of libstdc++-6.dll on youR system, and see if copying another one to the same directory as your program fixes the problem.
You can use nm libstdc++-6.dll | grep personality to see which exception 'personality' the DLL is using.
I ran into this as well. Did some searching, someone mentioned paying attention to whether or not you were in Debug or Release Mode. This applies to Code::Blocks specifically. I found I was in Debug Mode. I changed that to Release Mode and my program compiled and ran.
I am troubled by this though... It seems to me it should work in both modes, so how do I fix it so that it will? I have no answer there. Maybe someone will comment with the solution. In the meantime, compile and run in Release Mode instead of Debug Mode.
I just did a little mad science, removed the libstdc++6.dll from MinGW/bin and put it in another folder. Then I copied over the same file from Gimp/bin. No more linker error, instead I get an error that says the application failed to start :( Still compiles and runs in Release Mode though.

Access Windows Registry in C++ with CRegKey

I tried to access the Windows Registry with this Code:
CRegKey key;
LPTSTR szBuffer = new TCHAR[50];
ULONG cchBuffer = 257;
key.Open(HKEY_CURRENT_USER, L"HARDWARE", KEY_READ);
ULONG chars;
CString str;
if (key.QueryStringValue(L"Test", 0, &chars) == ERROR_SUCCESS)
{
key.QueryStringValue(L"Test", str.GetBuffer(chars), &chars);
str.ReleaseBuffer();
}
key.Close();
It returned an Error of the Microsoft Visual C++ Runtime Library:
Debug Assertation Failed!
Program: ...
File: C:\Program Files\Microsoft Visual Studio
11.0\VC\ATLMFC\INCLUDE\altbase.h Line: 6146
Expression: m_hkey != 0
For information Blah blah
After pressing Ignore it crashes.
I'm not sure what compiler is used because I (think I have) configured Qt Creator to use Visual C++ but the output Directory os called ..._._MinGW_Qt_SDK_DEBUG
What to do now?
I don't have a Windows machine nearby, but I think that there is no subkey named HARDWARE into HKEY_CURRENT_USER: it is into HKEY_LOCAL_MACHINE.
That, added to the fact that you are not checking the Open call for errors suggests that what you really want to do is:
key.Open(HKEY_LOCAL_MACHINE, L"HARDWARE", KEY_READ);
Anyway, it is always a good idea to handle the error, just in case.