winapi's LoadImage() alway returns NULL - c++

I've tried to load a bmp image using LoadImage() in order to display it, but I just can't find a way to load the image. Here is some code:
EDIT
as suggested, here is a runnable example
#include <windows.h>
#include <iostream>
#include <fstream>
std::string GetLastErrorAsString()
{
//Get the error message, if any.
DWORD errorMessageID = ::GetLastError();
if (errorMessageID == 0)
return std::string(); //No error message has been recorded
LPSTR messageBuffer = nullptr;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
//Free the buffer.
LocalFree(messageBuffer);
return message;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int iShow) {
std::ofstream file("output.txt");
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, L"C:\\yes.bmp", IMAGE_BITMAP, 300, 300, LR_LOADFROMFILE);
if (hBitmap == NULL) {
file << "error: " << GetLastErrorAsString().c_str() << std::endl;
return 1;
}
else {
file << "success." << std::endl;
}
return 0;
}
And this result is always NULL. If I put a wrong file name, the error message will be The system cannot find the file specified. but if the name is right, there is simply no error message.
I've tried to save the bmp file in 24 and 32 bits, I played with the LR_ flags, it doesn't change anything.
I also tried setting the HINSTANCE to the main's one, without any success.
I run this code once at the beginning of the main.
Thanks for your help, I hope I just misunderstood how this works

Related

Error writing to Windows 10 registry with WindowsAPI/C (strange situation)

I am trying to write to my Windows 10 registry, to include a program in Startup.
At the moment I have written the following code, which is not wroking:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winnt.h>
#include <winreg.h>
int main()
{
const TCHAR* path = TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run");
LPDWORD holdResult;
PHKEY hKey;
int lResult;
//lResult = RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_READ, &hKey);
lResult = RegCreateKeyExA(HKEY_CURRENT_USER, "myprogram", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &holdResult);
if (lResult != ERROR_SUCCESS)
{
if (lResult == ERROR_FILE_NOT_FOUND) {
printf("Key not found.\n");
return TRUE;
}
else {
printf("Error opening key.\n");
return FALSE;
}
}
printf("Key already existed or not: %p\n", holdResult);
char* szPath = "C:\\Users\\Myname\\Documents\\coolprogram.exe";
lResult = RegSetValueExA(hKey, "program", 0, REG_SZ,(LPBYTE)szPath, sizeof(wchar_t)*(wcslen(szPath)+1));
printf("Key successfully set or not: %d\n", lResult);
RegCloseKey(hKey);
return 0;
}
The strange thing is, although the code does not write anything to the registry, I get no error message, and the program executes as successful!
This is what gets printed to the terminal when I run the code:
Key already existed or not: 0000000000000002
Key successfully set or not: 0
So, the key had already been previously created, and was succesfully set, which did not happen, there is nothing in my registry.
I believe this is a permissions problem, because for some reason I cannot alter my registry permissions manually, even after setting myself as owner, it is impossible for me to allow "Full Control" to myself.
But I expected some sort of error, such as "ACCESS DENIED: INSUFFICIENT PERMISSIONS", but I am getting a success. Strange.
You are passing the wrong key path to RegCreateKeyEx(). You are trying to write your program value to HKCU\myprogram rather than to HKCU\SOFTWARE\Microsoft\...\Run.
You are also passing invalid pointers to RegCreateKeyEx(). Its last 2 parameters expect pointers to HKEY and DWORD variables, but you are passing in pointers to HKEY* and DWORD* variables instead.
You are also passing an incorrect parameter to RegSetValueExA(), too. You are giving it an ANSI string (OK, since it is an ANSI function), but are passing in a Unicode string length that is 2x the byte size of the actual ANSI string (bad).
In fact, your code shouldn't even compile as shown.
Try this instead:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <winnt.h>
#include <winreg.h>
int main()
{
const char* szKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run";
const char* szPath = "C:\\Users\\Myname\\Documents\\coolprogram.exe";
DWORD dwDisposition;
HKEY hKey;
LSTATUS lResult;
//lResult = RegOpenKeyExA(HKEY_CURRENT_USER, szKey, 0, KEY_QUERY_VALUE, &hKey);
lResult = RegCreateKeyExA(HKEY_CURRENT_USER, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, &dwDisposition);
if (lResult != ERROR_SUCCESS)
{
printf("Error creating key: %ld\n", lResult);
return 0;
}
printf("Key already existed or not: %lu\n", dwDisposition);
lResult = RegSetValueExA(hKey, "program", 0, REG_SZ, (LPBYTE)szPath, sizeof(TCHAR)*(strlen(szPath)+1));
printf("Key successfully set or not: %ld\n", lResult);
RegCloseKey(hKey);
return 0;
}

getting a "parse error before ','" on line 7

Trying to make a simple program that open a webpage when executed but I'm getting a parse error, and I don't know why.
#include <windows.h>
#include <shellapi.h>
bool open_browser()
{
HINSTANCE result = ShellExecuteA( HWND, "open", "http://www.reddit.com",
NULL, NULL, SW_SHOWNORMAL );
// Return whether or not we were successful.
return (result);
}
int main( )
{
open_browser();
return 0;
}
HWND is a type, not a value, so it's invalid as a function argument.
you are passing a type, instead you should pass an instance of the HWND type
HWND myhwnd = ::CreateWindowA("STATIC", "reddit", WS_VISIBLE, 0, 0, 400, 600, NULL, NULL, NULL, NULL);
HINSTANCE result = ShellExecuteA(myhwnd, "open", "http://www.reddit.com", NULL, NULL, SW_SHOWNORMAL);

Show path to a dll in a MessageBox husing handle

I load a dll with this command
HINSTANCE DllEconovent = LoadLibrary(_T("Econovent.dll"));
I want to get the path from where the dll is loaded from disk... In this fake case
C:\TFS_FWG\Acon\Oem\bin\Econovent.20140130_3200\Econovent64\Econovent.dll
And just show it with message box
MessageBox(_T("No valid ProcAddress"), _T("Error"), MB_ICONINFORMATION);
How is this done in the best way?
Have a look at GetModuleFileName: this function "retrieves the fully qualified path for the file that contains the specified module."
DWORD WINAPI GetModuleFileName(
_In_opt_ HMODULE hModule,
_Out_ LPTSTR lpFilename,
_In_ DWORD nSize
);
It should take in your HINSTANCE object and give you back a filename.
A simple example
int main()
{
HINSTANCE test = LoadLibrary("test.dll");
char buffer[MAX_PATH];
GetModuleFileName(test, buffer, MAX_PATH);
std::cout << buffer << std::endl;
return 0;
}
Adapting it to the MessageBox, just remove the line with std::cout and put
MessageBox(buffer, _T("Error"), MB_ICONINFORMATION);

WriteFile writes incorrectly

I'm trying to copy a file from resources to %localappdata%. I've something like this:
HINSTANCE hInstance = GetModuleHandle(NULL);
HANDLE hFile = INVALID_HANDLE_VALUE;
HRSRC hrsrc = FindResource(hInstance, MAKEINTRESOURCE(MSIE), RT_RCDATA);
HGLOBAL exeRes = LoadResource(hInstance, hrsrc);
DWORD size = SizeofResource(hInstance, hrsrc);
TCHAR szPath[MAX_PATH];
HANDLE hfile;
if(SUCCEEDED(SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, szPath))) {
PathAppend(szPath, TEXT("test.exe"));
hFile = CreateFile(szPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
}
LPVOID exePtr = LockResource(hrsrc);
DWORD exeWritten = 0;
BOOL writeResult = WriteFile(hFile, exePtr, size, &exeWritten, NULL);
cout << GetLastError() << endl;
BOOL closed = CloseHandle(hFile);
system("PAUSE");
return 0;
I'm able to locate the HRSRC and confirm the size using SizeofResource() just fine. CreateFile is in fact creating the file and returning the handle. GetLastError() reports that there are no errors. The amount of bytes written to disk is exactly right.
The output exe however is corrupted (the version of this file is incompatible with the version of Windows... blah blah) - it's lost its icon and everything. Looking at the original and the output file side-by-side in a hex editor it appears there's random data at the start of file.
What am I missing here?
Your LockResource is not correct. It should be passed the HGLOBAL exeRes you loaded previously.
LockResource(hrsrc);
should be
LockResource(exeRes);
From the MS documentation on LockResource() :
Do not try to lock a resource by using the handle returned by the FindResource or FindResourceEx function. Such a handle points to random data.
And as a side note, you may want to try cleaning up that loaded-and-locked resource when you're through with it.

Very strange GetOpenFileName problem

I seem to be having a very strange problem with GetOpenFileName.
It errors for no apparent reason, however, if I call CommDlgExtendedError() in the error check, the error never happens in the first place.
Here is my code:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
OPENFILENAME fm;
char flnm[MAX_PATH];
ZeroMemory(&fm, sizeof(fm));
fm.lStructSize = sizeof(OPENFILENAME);
fm.hwndOwner = NULL;
fm.lpstrFilter = "Text Files (*.txt)\0*.txt\0";
fm.lpstrFile = flnm;
fm.nMaxFile = MAX_PATH;
fm.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
fm.lpstrDefExt = "";
if(!GetOpenFileNameA(&fm))
{
MessageBoxA(NULL, "failed! :(", NULL, NULL);
}
return 0;
}
What's shown? "failed! :("
If I remove this check, I do see a file dialog. However, it doesn't work, and the filename box is pre-filled with random junk.
If I change to:
if(!GetOpenFileNameA(&fm))
{
DWORD dwErr = CommDlgExtendedError();
MessageBoxA(NULL, "failed! :(", NULL, NULL);
}
"failed! :(" is NOT shown. The file dialog shows and performs without issue.
What is going on!?!?
OPENFILENAME fm;
char flnm[MAX_PATH]; // nobody initialized me ...
ZeroMemory(&fm, sizeof(fm));
fm.lStructSize = sizeof(OPENFILENAME);
fm.hwndOwner = NULL;
fm.lpstrFilter = "Text Files (*.txt)\0*.txt\0";
fm.lpstrFile = flnm; // ... who knows what I am?
fm.nMaxFile = MAX_PATH;
fm.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
fm.lpstrDefExt = "";
if(!GetOpenFileNameA(&fm))
{
MessageBoxA(NULL, "failed! :(", NULL, NULL);
}
The documentation for lpstrFile states:
The file name used to initialize the File Name edit control. The first character of this buffer must be NULL if initialization is not necessary. When the GetOpenFileName or GetSaveFileName function returns successfully, this buffer contains the drive designator, path, file name, and extension of the selected file.
You are not initializing flnm and therein lies the problem. You can solve the problem by writing flnm[0] = '\0' before you call GetOpenFileName.