FindResource() fails to find data even though data is in exe - c++
I have been all over this one, and I am just plumb stuck. I have been building a project and I want to embed a text file as a resource into the executable. I understand all the basics of how this "should" work, but for some reason it is not. So, let me start from what I have so far and maybe the problem can be pinned down.
There are two functions here, the first, EnumResNameProc was an attempt to debug the problem my self, the second, LoadFileInResource is the function I am trying to get working.
It is a little messy because I was in the middle of building it when I starting having problems.
The exact issue is, FindResourceExA is returning NULL, and I am lost as to the exact reason. I know it is an error, and the return code is 1813, "Resource Not Found".
I have other resources in this project, I have a version node, a mainifest node, (of which, I am not directly reading) I have an icon node (that I am applying to my window system menu icon) and a bitmap (that I am loading as a texture.). These all have defined types, for example, the type for the Bitmap is 12. Now, I am attempting to load a text file, with is a 'user defined' type of 10. I know the data is INSIDE the executable, because if I open it in a text editor... (yes, I tried that) it is present, so, it is being included.
the first function was an attempt to walk through all the file resources in an attempt to locate the data. It found types 2, 3, 14, 16 and 24., but not 10. I have ruled out these other types as being the above mentioned resources. (bitmap=2), (icon=3), (RT_ICON(3)+RT_ICON_GROUP(11)=14) (version=16), (manifest=24). User defined should be type 10, and it didn't find it.
My Resources.rc file includes the following:
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDR_textfile1 textfile ".\\Data\\World.txt"
This defines the file to be loaded, (again, I know this works, I can see the text of the code IN the executable.)
My resources.h file defines the following:
#define IDR_textfile1 102
So, it is being defined, included, built, and all the other resources work, and yet, FindResourceExA returns NULL on this. All the include files are lined up, (i'd get warnings and errors if it was not.)
So, the question is, am I calling FindResourceExA correctly? it is defined as:
WINBASEAPI HRSRC WINAPI FindResourceExA(HINSTANCE,LPCSTR,LPCSTR,WORD);
well, I have tried for HINSTANCE, null, hInstance passed to be my Windows in WinMain, even GetModuleHandleA's results, no dice.
For LPCSTR, which is the resource ID, I have tried what you see, MAKEINTRESOURCE(IDR_textfile1), and I have tried hard coding the ID number as well, in this case, 102. No dice.
For the type, I have tired other variations, the correct value according to Microsoft should be 10. That's why I crated the EnumResNameProc, trying to see what other IDs exist, from 0 to 500, and all I got back was the ones listed above, on the off chance something was defined funny. No Dice.
I have tried both FindResourceExA FindResourceA (with and without the 'Ex')
No Dice.
I know it is there, I have learned more then I care to about this function, but it won't find it, and I am at a loss at what else to try.
As for development environment, I am using MinGW+Eclipse+CDT, and using winres from the GCC tools to build the resource object file. I have looked for bugs in winres to see if it is doing something funny on binary types. (that's what undefined are considered, even though I am loading a text file.) oh, I also tried re-saving the file as ANSI, UTF-8, and UNICODE in case the binary format of the text mattered.
I am at a loss, I don't know what else to try. I know the data is there, I just don't why it won't access it. The Windows API call can't either see the data, or the data is encoded in a screwey way and so it doesn't access it.
What else can I try?
BOOL CALLBACK EnumResNameProc (
HMODULE hModule,
LPCTSTR lpszType,
LPTSTR lpszName,
LONG_PTR lParam)
{
std::cerr << "WTF INFO BEGIN here! \n";
// std::string info = lpszName;
int a = lParam;
std::cerr << "We found something: " << a << std::endl;
MessageBoxA ( NULL, lpszName, (LPCSTR) "Found: ", MB_OK);
std::cerr << "WTF INFO END here! \n";
return true;
}
void LoadFileInResource( HINSTANCE hInstance,
int name,
int type,
DWORD size,
const char* data)
{
// HMODULE handle = GetModuleHandleA(NULL);
for (int a = 0;a<500;a++) {
EnumResourceNamesA(hInstance, MAKEINTRESOURCE(a),
(ENUMRESNAMEPROCA) & EnumResNameProc, (LONG_PTR) a);
}
HRSRC rc = FindResourceExA(hInstance,
MAKEINTRESOURCE(IDR_textfile1),
MAKEINTRESOURCE(10),
MAKELANGID(LANG_NEUTRAL,
SUBLANG_NEUTRAL));
if (rc == NULL) {
DWORD fup = GetLastError();
MessageBoxA ( NULL, (LPCSTR) "Crap not loaded.", (LPCSTR) "Error", MB_OK);
std::cerr << "Crap not loaded, ERR: " << fup << std::endl;
}
// MessageBoxA ( NULL, (LPCSTR) " Test ", (LPCSTR) "Found: ", MB_OK);
HGLOBAL rcData = LoadResource(hInstance, rc);
// data = static_cast<const char*>(LockResource(rcData));
data = (const char*) LockResource(rcData);
size = SizeofResource(hInstance, rc);
std::cout << "Res size = " << (long) size << std::endl;
std::cout << "data =" << data << :: std::endl;
// wsprintf(szMsg,"Values loaded : %d, %d, %d\nSize = %d",
// pmem->Value1,pmem->Value2,pmem->Value3);
// MessageBox(hWnd, szMsg,lpszAppName,MB_OK);
}
IDR_textfile1 textfile ".\\Data\\World.txt"
You declared the resource type as "textfile". Which is fine but that's a string, not a number. So using MAKEINTRESOURCE() for the resource type isn't going to help you find it, that's why EnumResourceNames doesn't find it back. Fix:
IDR_textfile1 RC_DATA ".\\Data\\World.txt"
And
HRSRC rc = FindResourceEx(hInstance,
MAKEINTRESOURCE(RC_DATA),
MAKEINTRESOURCE(IDR_textfile1),
MAKELANGID(LANG_NEUTRAL,
SUBLANG_NEUTRAL));
or if you want to use your original approach:
HRSRC rc = FindResourceEx(hInstance,
L"textfile",
MAKEINTRESOURCE(IDR_textfile1),
MAKELANGID(LANG_NEUTRAL,
SUBLANG_NEUTRAL));
The call to FindResourceExA is wrong, resource type is passed in the second parameter and id in the third.
FindResourceEx at MSDN
Related
Read the file version of a dll in C: The system cannot find the file specified
I am new in the forum but I have already found a lot of help for my other projects. I am using Visual Studio 2019 and I have created a .rc file which contains the file version and a few other things. These information are displayed in the Properties window of the my dll correctly. I have created a function void PrintVersion(TCHAR* pszFilePath, void (*printFunc)(const char*, ...)); which receives the file path and a pointer to my logger function. Inside that function I want to read the file version and print it to the logger. But my logger returns Error in GetFileVersionInfoSize: The system cannot find the file specified. My function call does look like this: TCHAR* filename = L"mydll.dll"; PrintVersion(filename, gPrintFunc); And the function is implemented as follows: // Read the version of the dll and write it to the logger void PrintVersion(TCHAR* pszFilePath, void (*printFunc)(const char*, ...)) { DWORD dwSize = 0; DWORD verHandle = 0; BYTE* pbVersionInfo = NULL; VS_FIXEDFILEINFO* pFileInfo = NULL; UINT puLenFileInfo = 0; // Get the size of the version information. This is done to check if the file is avaialbe // If the size is zero then a error occured dwSize = GetFileVersionInfoSize(pszFilePath, &verHandle); if (dwSize == 0) { gPrintFunc("Error in GetFileVersionInfoSize: "); PrintLastErrorString(gPrintFunc); return; } // Create some memory for the file version info pbVersionInfo = malloc(dwSize); // Store the information into pbVersionInfo #pragma warning(suppress : 6387) if (!GetFileVersionInfo(pszFilePath, verHandle, dwSize, pbVersionInfo)) { gPrintFunc("Error in GetFileVersionInfo: "); PrintLastErrorString(gPrintFunc); free(pbVersionInfo); return; } // Make the information easier accessable in pFileInfo #pragma warning(suppress : 6387) if (!VerQueryValue(pbVersionInfo, TEXT("\\"), (LPVOID*)&pFileInfo, &puLenFileInfo)) { gPrintFunc("Error in VerQueryValue: "); PrintLastErrorString(gPrintFunc); free(pbVersionInfo); return; } // pFileInfo->dwFileVersionMS and pFileInfo->dwFileVersionLS contain the software version // Major2B.Minor2B.Revision2B.Build2B gPrintFunc("File Version of %s: %d.%d.%d.%d\n", pszFilePath, (pFileInfo->dwFileVersionMS >> 16) & 0xffff, (pFileInfo->dwFileVersionMS >> 0) & 0xffff, (pFileInfo->dwFileVersionLS >> 16) & 0xffff, (pFileInfo->dwFileVersionLS >> 0) & 0xffff ); // Free up the reserved memory free(pbVersionInfo); } // Used for receiving the last WIN32 error and write it to the logger void PrintLastErrorString(void (*printFunc)(const char*, ...)) { // Get the error id of the last error DWORD iLastError; iLastError = GetLastError(); //Ask Win32 to give us the string version of that message ID. //The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be). LPSTR messageBuffer = NULL; size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, iLastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); gPrintFunc("%s\n", messageBuffer); return; } I created that function by combining a few different C++ and C# examples from this forum. I am not familiar with the TCHAR* datatype. I assume that the problem has maybe something to do with the filename string. Further I am not able to print the filename to the logger with the %s format placeholder. In this case only the first letter of the filename is displayed. One further info. Before I copied that code to the dll. I created a small console application. And in this case it was possible to read the file version of the exe. I also tried to specify the complete path of the dll. The dll and the exe, which uses the dll are in the same directory. Maybe someone can help me :) BR
Thank you for your answers. I changed now the character set to: Use Unicode Character Set and now it works as expected.
C++ Win32 - Getting App Name using PID and Executable Path
I'd like to get the name of an application on Windows. Currently I'm using EnumProcesses() to enumerate all processes and receive a list of PIDs. Then I'm looping through all PIDs, each iteration looks like this, when aProcess[i] is the current PID: HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, aProcesses[i]); std::string processName = get_process_name(proc); My get_process_name(proc) function uses GetModuleFileNameEx to get the executable path and GetProcessImageFileName in order to retrieve the name of the executable file. What I want to retrieve is basically the App Name, as it is displayed in the Windows Task Manager. I've looked throughout Win32 API's documentation and could not find a clue on how to achieve this. I've tried looking for other ways such as Windows Shell tasklist but it outputs different things, for example- Google Chrome: Image Name: chrome.exe PID: 84 Session Name: Console I'd really appreciate any thought on the matter, whether it be the Win32 API or some other way I can implement through C++ code.
You can do this with GetFileVersionInfoA and VerQueryValueA. You just need to follow the example given in the VerQueryValueA document. Here is my sample: struct LANGANDCODEPAGE { WORD wLanguage; WORD wCodePage; } *lpTranslate; int main() { HANDLE handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION , FALSE, 2140); //Modify pid to the pid of your application if (!handle) return 0; wchar_t pszFile[MAX_PATH] = L""; DWORD len = MAX_PATH; QueryFullProcessImageName(handle, 0, pszFile, &len); UINT dwBytes, cbTranslate; DWORD dwSize = GetFileVersionInfoSize(pszFile, (DWORD*)&dwBytes); if (dwSize == 0) return 0; LPVOID lpData = (LPVOID)malloc(dwSize); ZeroMemory(lpData, dwSize); if (GetFileVersionInfo(pszFile, 0, dwSize, lpData)) { VerQueryValue(lpData, L"\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &cbTranslate); wchar_t strSubBlock[MAX_PATH] = { 0 }; wchar_t* lpBuffer; for (int i = 0; i < (cbTranslate / sizeof(struct LANGANDCODEPAGE)); i++) { StringCchPrintf(strSubBlock,50, L"\\StringFileInfo\\%04x%04x\\FileDescription", lpTranslate[i].wLanguage, lpTranslate[i].wCodePage); VerQueryValue(lpData, strSubBlock, (void**)&lpBuffer, &dwBytes); std::wcout << lpBuffer << std::endl; } } if(lpData) free(lpData); if (handle) CloseHandle(handle); return 0; } And it works for me:
I think what you want are the "version" resources embedded in the PE file (the executables.) You seem to be familiar with using Win32 API, so I'm just going to give you some hints. You have to use LoadLibraryEx to load the EXE file (the Ex suffix is to enable passing the LOAD_LIBRARY_AS_DATAFILE flag,) and then call EnumResourceTypes (also see EnumResourceNames) to enumerate all the resource types/resources in the file, and find what you are looking for and then extract the data with LoadResource. The resource type you want is RT_VERSION. I'm sure I'm omitting a lot of details (as per usual for Win32 programming,) and there might not be a need for enumeration at all; in which case you may want to call FindResource or FindResourceEx directly (if there is a fixed name for this particular resource.) As further clarification, this gives you the date you see if you right-click on the EXE file (not the shortcut) in Windows Explorer and select "Properties", then go to the "Details" tab. If that information is indeed what you want (e.g. the "File description" field) then the above method should give you the data.
FindWindowA() returns 0 and when i check the error code with GetLastError() it's also 0 (ERROR_SUCCESS)
This is a segment out of a dll injection code i'm writing. I'm using FindWindowA() to get a HWND to the window procces defined in INJ_PROC_NAME. The problem is that the function always returns 0 and when I check the error with GetLastError() it also returns 0. I can't tell what's the problem because the error code doesn't give me the correct information about the error. HWND Hwnd = FindWindowA(NULL, INJ_PROC_NAME); if (Hwnd == NULL) { std::cout << "Couldn't find window named \"" << INJ_PROC_NAME << "\": error-" << GetLastError() << std::endl; getchar(); return -1; } This is the output: Couldn't find window named "notepad.exe": error-0 Is this a known issue? I wasn't able to find any information about it in Microsoft's documentation or in stack overflow. I just can't figure this one out... edit: Obviously, notepad is open when i run the program.
Most likely the error gets clobberd somewhere in std::cout. Try this: if (Hwnd == NULL) { DWORD error = GetLastError(); // first thing we retrieve the error std::cout << "Couldn't find window named \"" << INJ_PROC_NAME << "\": error-" << error << std::endl; getchar(); return -1; } Saving the error number right after the failure as shown above must be done anyway. But the true reason why FindWindow does not succeed is because it is not looking for the process name, but for the window title which is something like Untitled - Notepad. Otherwise if FindWindow does not find the window, the last error is in deed not set in spite of what the the Microsoft documentation pretends. Conclusion Using FindWindow is probably not the best approach, you should rather enumerate processes as described in this Microsoft documentation.
How to close a SYSTEM_HANDLE (or some open file handle in another process)
I am trying to create an application that closes open file handles of other processes. Aside from the fact that this causes instabilities in applications, I would like to proceed with this exercise. I have been successful in enumerating processes that have open handles or locks to particular files using this example (download link). Put simply, I am left with either a SYSTEM_HANDLE object or a duplicate of it (of type HANDLE): SYSTEM_HANDLE handle = handleInfo->Handles[i]; HANDLE dupHandle = NULL; if (!NT_SUCCESS(NtDuplicateObject(processHandle, (HANDLE)handle.Handle, GetCurrentProcess(), &dupHandle, 0, 0, 0))) { continue; } I have tried closing the SYSTEM_HANDLE with no luck: wcout << "Found " << fullPath << " in process " << process << "." << endl; if (CloseHandle((HANDLE)handle.Handle)) { wcout << "Closed handle successfully." << endl; } The SYSTEM_HANDLE structure is defined as: typedef struct _SYSTEM_HANDLE { ULONG ProcessId; BYTE ObjectTypeNumber; BYTE Flags; USHORT Handle; PVOID Object; ACCESS_MASK GrantedAccess; } SYSTEM_HANDLE, *PSYSTEM_HANDLE; The application lies to me because it prints out "Closed handle successfully.", yet when I enumerate open handles of it again, this handle shows up. If, for example, I use an application like LockHunter to close the handle, if I enumerate it again, it does not show up. How can I close this handle?
I should have read my own link a little bit better, as wj32 clearly states: (Step 3: Closing remote handles) To close handles opened by other processes, you simply call DuplicateHandle with DUPLICATE_CLOSE_SOURCE (1) specified in the options parameter (it's documented on the MSDN page for DuplicateHandle, so go read it). You can specify NULL for the target process handle and target handle parameters. For example: DuplicateHandle(handleToTheRemoteProcess, theRemoteHandle, NULL, NULL, 0, FALSE, 0x1); Although in my case, judging from the code, NtDuplicateObject should do the same trick if I pass in DUPLICATE_CLOSE_SOURCE.
GetWindowText() returning empty string and strange error
I'm using the following code inside a global CBT hook procedure: TCHAR title[256]; int getT = GetWindowText(hWnd, title, 256); if (getT == 0) { int err = GetLastError(); logFile << "Error GetWindowText(): " << err << endl; } else { logFile << "getT = " << getT << endl; } The problem is that for certain windows the GetWindowText() function works just fine and I get the correct window title, but for some others it returns 0 and I get an empty string. The GetLastError() returns 183 which is ERROR_ALREADY_EXISTS: Cannot create a file when that file already exists. The error is not random: I always get it with the same kind of window opened by the same application, but for all the other windows it seems to work fine.
You might not have the rights to retrieve text from certain windows on Windows Vista and above. My guess is that ERROR_ALREADY_EXISTS comes from your log file when you print "Error GetWindowText(): ". You should get the error code first before doing anything else. Another possibility is that the window returns 0 from its WM_GETTEXT handler without setting the last error. As GetWindowText documentation states, if you call it on a window belonging to the same process, it retrieves the text by sending this message. Since you are calling the function from a hook, you might be in the same process.