Getfriendlyname of a secondary monitor - c++

I need to get device name of a secondary monitor. However when I simply try to retrieve device name, the output is DISPLAY1, DISPLAYV1 and etc.
However I require the name displayed when we check the screen resolution like the Displayname mentioned here:
Firstly I am not sure from where I can obtain this string. On reading a bit I guess it is the friendlyname of the device. However I am not sure since on calling EnumDisplaySetting() has been giving me Unhandled Exception: Could not access memory location when this function is called. So I have not been able to verify what the friendly name is exactly. And I believe that the unhandled exception is caused due to improper allocation of memory to the DISPLAY_DEVICE for driverextra in the DISPLAY_DEVICE. I believe this is because of this:
The function fails if iModeNum is greater than the index of the display device's last graphics mode.
mentioned here
Also I did not understand how much memory needs to be allocated to to
DISPLAY_DEVICE->dmDriverExtra as it has been mention in the same link:
Before calling EnumDisplaySettings, set the dmSize member to sizeof(DEVMODE), and set the dmDriverExtra member to indicate the size, in bytes, of the additional space available to receive private driver data.
So my question is manifold:
1) How much memory needs to be allocated to dmDriverExtra?
2) Is friendlyname the right parameter I need for accessing the name provided in the Display Tab in screen resolution. Or if not what other parameter do I need?
3) Is this unhandled exception caused due to improper memory allocation or is there some other reason for this?
4) Are there any other ways to get access to friendlyname of the secondary monitor?

Updated
I switched to using The PhysicalMonitorAPI instead of GetMonitorInfo. I've combined by original solution with the first. This produces more reasonable output that you would expect (e.g. "Dell UH2313" instead of "\.\Display1").
Technically, you should allocate the array of monitors instead of using a hardcoded array - but I've never seen where dwCount will get initialized to anything greater than 1.
This program compiles just fine in Visual Studio, but you'll need to link with dxva2.lib to pick up the definitions for the PhysicalMonitor APIs.
#include <Windows.h>
#include <PhysicalMonitorEnumerationAPI.h>
#include <string>
#include <iostream>
#include <stdio.h>
BOOL __stdcall MyMonitorEnumProc
(
_In_ HMONITOR hMonitor,
_In_ HDC hdcMonitor,
_In_ LPRECT lprcMonitor,
_In_ LPARAM dwData
)
{
DWORD dwCount = 0;
std::wstring strName(L"Unknown monitor name");
PHYSICAL_MONITOR monitors[100] = {};
MONITORINFOEX info = {};
info.cbSize = sizeof(info);
if (GetMonitorInfo(hMonitor, (LPMONITORINFO)&info))
{
strName = info.szDevice;
}
if (GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &dwCount) && (dwCount > 0) && (dwCount < ARRAYSIZE(monitors)))
{
if (GetPhysicalMonitorsFromHMONITOR(hMonitor, dwCount, monitors))
{
strName = monitors[0].szPhysicalMonitorDescription;
DestroyPhysicalMonitors(dwCount, monitors);
}
}
std::wcout << L"Monitor: " << strName << std::endl;
return TRUE;
}
void printMonitorNames()
{
EnumDisplayMonitors(NULL, NULL, MyMonitorEnumProc, NULL);
}
int _tmain(int argc, _TCHAR* argv[])
{
printMonitorNames();
return 0;
}
And it's a good bet that the MyMonitorEnumProc will get invoked first for the primary monitor. All other monitors get enumerated next.

Related

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.

Why can't the entry point of a dll be found within my program? PE file

I'm trying to create a mod loader for an 18 year old game to help me get better at c++. Right now I'm just trying to inject a dll into the same process of the mod loader. The sample dll just prints some text to the command window but doesn't. I think that the code that I have loading the entry point of the dll is not working because everything works up until I call the entry point function of my sample dll within my ModLoader.exe, and Visual Studio just throws an Access Violation. I poked through the memory viewer in debug mode within visual studio to try and see where my ModLoader program thinks the dll entry point is located within the dll but the address just points to a bunch of zeros. I recently learned the PE file format and tried to understand all the code that I wrote when I was following a tutorial on Youtube on how to do this, so forgive me for my inexperience I'm just trying to learn. The other code that I do not show is me locating and finding the target process, reading the dll binary, getting the headers from the dll, me allocating space on the target process for the dll, and finally me writing all of the section header data into the target process. I can provide any other code that y'all would like to see!
Injector.h
using ModLoader_LoadLibrary = HINSTANCE(WINAPI*)(const char* filename);
using ModLoader_GetProcAddress = UINT_PTR(WINAPI*)(HINSTANCE module, const char* procName);
using ModLoader_DllEntry = BOOL(WINAPI*)(HINSTANCE dll, DWORD reason, LPVOID reserved);
struct ModLoader_ManualMapping_Data
{
ModLoader_LoadLibrary ML_LoadLibrary; //Function pointer to the windows load library function
ModLoader_GetProcAddress ML_ProcAddress; //Function pointer to a function to be called
HINSTANCE ML_Module; //dll instance
};
Injector.cpp : Shellcode function that'll run alongside the target executable
void __stdcall Shellcode(ModLoader_ManualMapping_Data* data)
{
if (!data)
return;
BYTE* pData = reinterpret_cast<BYTE*>(data);
IMAGE_OPTIONAL_HEADER& optHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(pData + reinterpret_cast<IMAGE_DOS_HEADER*>(pData)->e_lfanew)->OptionalHeader;
auto loadLibrary = data->ML_LoadLibrary;
auto procAddress = data->ML_ProcAddress;
auto dllLoad = reinterpret_cast<ModLoader_DllEntry>(pData + optHeader.AddressOfEntryPoint); //Loads entry point func from dll
BYTE* locationDelta = pData - optHeader.ImageBase; //pData = the new address | ImageBase = preferred address -> Get the difference between the two to add to every address in the relocation table
if (locationDelta) //THIS DOES NOT GET RAN
{
//Adds the delta value to all addresses within the base relocation table
}
//Import table
if (optHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
{
IMAGE_IMPORT_DESCRIPTOR* imgImport = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*>(pData
+ optHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (imgImport->Name) //THIS DOES NOT GET RAN B\C imgImport is all zeros.
{
//Loops through import table
}
}
if (optHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size) //THIS DOES NOT GET RAN
{
//Calls the callback functions within dll
}
dllLoad(reinterpret_cast<HINSTANCE>(pData), DLL_PROCESS_ATTACH, nullptr); //PROBLEM: ACCESS VIOLATION
}
Injector.cpp : bool ManualMapping(HANDLE process, const char* dllFilepath)
-- This function is called in main.cpp.
The srcData variable is just the binary contents of the dll
ModLoader_ManualMapping_Data loadData = { 0 };
loadData.ML_LoadLibrary = LoadLibraryA;
loadData.ML_ProcAddress = reinterpret_cast<ModLoader_GetProcAddress>(GetProcAddress);
memcpy(srcData, &loadData, sizeof(loadData));
WriteProcessMemory(process, locOfDll, srcData, 0x1000, nullptr);
void* shellCodeBase = VirtualAllocEx(process, nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); //Allocates 0x1000 bytes in the process memory for the shellcode
WriteProcessMemory(process, shellCodeBase, Shellcode, 0x1000, nullptr); //Injects the Shellcode function into the process
HANDLE thread = nullptr;
thread = CreateRemoteThread(process, nullptr, 0, reinterpret_cast<PTHREAD_START_ROUTINE>(shellCodeBase), locOfDll, 0, nullptr); //Runs
Finally the sample dll code
#include <Windows.h>
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD reason_for_call, LPVOID lpReserved)
{
switch (reason_for_call)
{
case DLL_PROCESS_ATTACH:
OutputDebugStringA("Injected!");
break;
}
return TRUE;
}
EDIT
After rewriting all the code and looking at it all day I finally figured it out. I just had to make sure that the parameters were right when I called dllLoad!

SystemParametersInfo sets background to solid color rather than actually setting the picture

I have tried all of the solution specified on these posts:
How to change the windows 10 wallpaper with C++?
How to change desktop background using VC++
SystemParametersInfo sets wallpaper completly black (using SPI_SETDESKWALLPAPER)
And i still cant seem to be able to get it working.... heres my code:
const wchar_t* path = L"C:\\imagge.png";
bool result = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (void*)path, SPIF_UPDATEINIFILE);
std::cout << result;
Also if i specify a path that aint valid it still prints 1(true) when it clearly states on docs SPI_SETDESKWALLPAPER bit that it should return 0(false) if theirs a problem
Also i have tried calling printing out GetLastError(); and it returns 0....
Note When the SPI_SETDESKWALLPAPER flag is used, SystemParametersInfo
returns TRUE unless there is an error (like when the specified file
doesn't exist).
IInspectable suggested using IDesktopWallpaper interface
And i got it working!
Heres my code:
int main() {
std::wstring x = L"C:\\Users\\danie\\OneDrive\\Pictures\\pixelArt\\Sample.png";
HRESULT ad;
CoInitialize(NULL);
IDesktopWallpaper* p;
if(SUCCEEDED(CoCreateInstance(__uuidof(DesktopWallpaper), 0, CLSCTX_LOCAL_SERVER, __uuidof(IDesktopWallpaper), (void**)&p))) {
ad = p->SetWallpaper(NULL, x.c_str());
p->Release();
}
CoUninitialize();
return 0;
}

Windows HOME - SHGet(Known)FolderPath

I'm trying to write a function to get the Windows-equivalent of HOME. My C skills are rusty, so don't mind that my example code does not compile. I'm trying to use SHGetKnownFolderPath on Windows Vista and newer, and SHGetFolderPath on Server 2003 and older. Since I expect to encounter users running Windows XP (as it is still the number one deployed version of Windows), I am going to avoid having a reference to SHGetKnownFolderPath in the symbol table (as this would lead to a binary that won't even load on XP). I know to LoadLibrary() shell32 and to GetProcAddress() from there, but my skills on doing function pointers are, well, crap, to say the least.
When I write features, and they are difficult to handle, I isolate them into an separate example file. The broken example I have so far is:
#include <windows.h>
#include <stdio.h>
// Pointerizing this Vista-and-later call for XP/2000 compat, etc.
typedef HRESULT (WINAPI* lpSHGetKnownFolderPath)(
REFKNOWNFOLDERID rfid,
DWORD dwFlags,
HANDLE hToken,
PWSTR *ppszPath
) lpSHGetKnownFolderPath;
int main(int argc, char *argv[])
{
// SHGet(Known)FolderPath() method.
HMODULE hndl_shell32;
lpSHGetKnownFolderPath pSHGetKnownFolderPath;
hndl_shell32 = LoadLibrary("shell32");
pSHGetKnownFolderPath = GetProcAddress(hndl_shell32, "SHGetKnownFolderPathW");
if(pSHGetKnownFolderPath != NULL) {
} else {
}
}
My question is this: Knowing that I'm doing this wrong, how would I go about doing this right? And an explanation as to how to do it right in the future would be appreciated. Thanks.
Here is a small application that shows how to use LoadLibrary() and GetProcAddress() with advice provided in comments:
#include <windows.h>
#include <stdio.h>
#include <shlobj.h>
/* The name of the function pointer type is
'lpSHGetKnownFolderPath', no need for
additional token after ')'. */
typedef HRESULT (WINAPI* lpSHGetKnownFolderPath)(
REFKNOWNFOLDERID rfid,
DWORD dwFlags,
HANDLE hToken,
PWSTR *ppszPath
);
int main()
{
HMODULE hndl_shell32;
lpSHGetKnownFolderPath pSHGetKnownFolderPath;
/* Always check the return value of LoadLibrary. */
hndl_shell32 = LoadLibrary("shell32");
if (NULL != hndl_shell32)
{
/* There is no 'SHGetKnownFolderPathW()'.
You need to cast return value of 'GetProcAddress()'. */
pSHGetKnownFolderPath = (lpSHGetKnownFolderPath)
GetProcAddress(hndl_shell32, "SHGetKnownFolderPath");
if(pSHGetKnownFolderPath != NULL)
{
PWSTR user_dir = 0;
if (SUCCEEDED(pSHGetKnownFolderPath(
FOLDERID_Profile,
0,
NULL,
&user_dir)))
{
/* Use 'user_dir' - remember to:
CoTaskMemFree(user_dir);
when no longer required.
*/
}
}
else
{
fprintf(stderr, "Failed to locate function: %d\n",
GetLastError());
}
/* Always match LoadLibrary with FreeLibrary.
If FreeLibrary() results in the shell32.dll
being unloaded 'pSHGetKnownFolderPath' is
no longer valid.
*/
FreeLibrary(hndl_shell32);
}
else
{
fprintf(stderr, "Failed to load shell32.dll: %d\n", GetLastError());
}
return 0;
}
This was compiled on Windows XP.
Output on Windows XP:
Failed to locate function: 127
where 127 means The specified procedure could not be found.
Output on Windows Vista:
C:\Users\admin
You can always use getenv("HOMEDRIVE") and getenv("HOMEPATH") and concatenate the results.
std::string home = std::string(getenv("HOMEDRIVE")) + getenv("HOMEPATH");
The Windows equivalent of HOME is USERPROFILE. It is an ordinary environment variable just like in Linux. You can make the following call to retrieve it:
char *profilepath = getenv("USERPROFILE");

FindResource() fails to find data even though data is in exe

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