How to get the class name of a window with C - c

Objective: Retrieve the class name of the current foreground window with plain C.
I have the following code to retrieve the class name:
PWSTR win_class = NULL;
GetClassNameW(hwnd,&win_class,MAX_PATH);
if(win_class != NULL)
free(win_class);
I am getting the following warnings:
warning C4047: 'function': 'LPWSTR' differs in levels of indirection
from 'PWSTR *' warning C4024: 'GetClassNameW': different types
for formal and actual parameter 2
I have two questions: How to solve those warnings, and how should I create an if condition to validate the result of the function GetClassName and set the value of win_class to "NOT FOUND" in case that the function does not find the class name?

The GetClassNameW() function does not allocate the memory needed for the returned class name - you have to do that (or simply provide automatic storage).
To check for success, simply test the return value of the function: if it succeeds, that will be the length of the class name string (in characters); if it fails, the value will be zero.
Here's a short, runnable program that gets the class name for the console window:
#include <Windows.h>
#include <stdio.h>
int main()
{
HWND hwnd = GetConsoleWindow();
wchar_t win_class[_MAX_PATH];
int status = GetClassNameW(hwnd, win_class, _MAX_PATH);
if (!status) wcscpy(win_class, L"NOT FOUND");
printf("%ls\n", win_class);
return 0;
}

When calling GetClassNameW(), you are passing a PWSTR* (wchar_t**) where a LPWSTR (wchar_t*) is expected. That is what the compiler is complaining about.
GetClassName() requires you to pre-allocate a character buffer and pass in a pointer to it, along with the buffer size. The function will not allocate a buffer and return a pointer back to you, like you are expecting. It will merely fill in your provided buffer as needed.
Try something more like this:
WCHAR win_class[256] = {0};
int win_class_len = 0;
HWND hwnd = GetForegroundWindow();
if (!hwnd)
{
// error handling as needed...
lstrcpyW(win_class, L"WINDOW NOT FOUND");
win_class_len = lstrlenW(win_class);
}
else
{
win_class_len = GetClassNameW(hwnd, win_class, 256);
if (win_class_len == 0)
{
DWORD err = GetLastError();
// error handling as needed...
lstrcpyW(win_class, L"CLASS NOT FOUND");
win_class_len = lstrlenW(win_class);
}
}
// use win_class as needed, up to win_class_len characters...

TCHAR is the universal char type working for Unicode and ANSI. GetClassName is the corresponding function replaced with GetClassNameA or GetClassNameW. If you need static string use TEXT() macro like TCHAR * s = TEXT("abc");
TCHAR win_class[MAX_PATH];
int res = GetClassName( hwnd, win_class, MAX_PATH );
if ( res > 0 )
// success
Your error is that win_class was unallocated (NULL) string pointer. GetClassName needs valid memory address of buffer.

You need to check if you function succseed. To do so, print the return value of the function.
Failiure will be presented by the value 0.

Related

Vulkan vkCreateInstance - Access violation writing location 0x0000000000000000

I am trying to write a basic program using Vulkan, but I keep getting a runtime error.
Exception thrown at 0x00007FFDC27A8DBE (vulkan-1.dll) in VulkanTest.exe: 0xC0000005: Access violation writing location 0x0000000000000000.
This seems to be a relatively common issue, resulting from a failure to initialize the arguments of the vkCreateInstance function. I have tried all of the solutions I found proposed to others, even initializing things I am fairly certain I don't need to, and I still haven't been able to solve the problem. The program is written in C using the MSVC compiler.
#include "stdio.h"
#include "SDL.h"
#include "vulkan\vulkan.h"
#include "System.h"
int main(int argc, char *argv[])
{
//Initialize SDL
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
printf("Error");
}
printf("Success");
//Initialize Vulkan
VkInstance VulkanInstance;
VkApplicationInfo VulkanApplicationInfo;
VulkanApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
VulkanApplicationInfo.pNext = 0;
VulkanApplicationInfo.pApplicationName = "VulkanTest";
VulkanApplicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
VulkanApplicationInfo.pEngineName = "VulkanTest";
VulkanApplicationInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
VulkanApplicationInfo.apiVersion = VK_API_VERSION_1_0;
VkInstanceCreateInfo VulkanCreateInfo = {0,0,0,0,0,0,0,0};
VulkanCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
VulkanCreateInfo.pNext = 0;
VulkanCreateInfo.pApplicationInfo = &VulkanApplicationInfo;
VulkanCreateInfo.enabledLayerCount = 1;
VulkanCreateInfo.ppEnabledLayerNames = "VK_LAYER_KHRONOS_validation";
vkEnumerateInstanceExtensionProperties(0, VulkanCreateInfo.enabledExtensionCount,
VulkanCreateInfo.ppEnabledExtensionNames);
//Create Vulkan Instance
if(vkCreateInstance(&VulkanCreateInfo, 0, &VulkanInstance) != VK_SUCCESS)
{
printf("Vulkan instance was not created");
}
//Create SDL Window
SDL_Window* window;
window = SDL_CreateWindow("VulkanTest", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 0, 0, SDL_WINDOW_VULKAN || SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_Delay(10000);
return 0;
}
Are you sure the call to vkCreateInstance() is what is crashing? I have not tried to debug the code you have shown (that is your job), but just looking at the calls that the code is making, it should be the call to vkEnumerateInstanceExtensionProperties() that is crashing (if it even compiles at all!).
The 2nd parameter of vkEnumerateInstanceExtensionProperties() expects a uint32_t* pointer, but you are passing in a uint32_t value (VulkanCreateInfo.enabledExtensionCount) that has been initialized to 0. So, that would make the pPropertyCount parameter be a NULL pointer (if it even compiles).
You are passing VulkanCreateInfo.ppEnabledExtensionNames in the 3rd parameter (if that even compiles), and ppEnabledExtensionNames has been initialized to NULL. Per the documentation for vkEnumerateInstanceExtensionProperties():
If pProperties is NULL, then the number of extensions properties available is returned in pPropertyCount. Otherwise, pPropertyCount must point to a variable set by the user to the number of elements in the pProperties array, and on return the variable is overwritten with the number of structures actually written to pProperties.
Since pPropertCount is NULL, vkEnumerateInstanceExtensionProperties() has nowhere to write the property count to! That would certainly cause an Access Violation trying to write to address 0x0000000000000000.
The documentation clears states:
pPropertyCount must be a valid pointer to a uint32_t value
On top of that, your call to vkEnumerateInstanceExtensionProperties() is just logically wrong anyway, because the 3rd parameter expects a pointer to an array of VkExtensionProperties structs, but VulkanCreateInfo.ppEnabledExtensionNames is a pointer to an array of const char* UTF-8 strings instead.
In other words, you should not be using vkEnumerateInstanceExtensionProperties() to initialize criteria for the call to vkCreateInstance(). You are completely misusing vkEnumerateInstanceExtensionProperties(). You probably meant to use SDL_Vulkan_GetInstanceExtensions() instead, eg:
uint32_t ExtensionCount = 0;
if (!SDL_Vulkan_GetInstanceExtensions(NULL, &ExtensionCount, NULL))
{
...
}
const char **ExtensionNames = (const char **) SDL_malloc(sizeof(const char *) * ExtensionCount);
if (!ExtensionNames)
{
...
}
if (!SDL_Vulkan_GetInstanceExtensions(NULL, &ExtensionCount, ExtensionNames))
{
SDL_free(ExtensionNames);
...
}
VulkanCreateInfo.enabledExtensionCount = ExtensionCount;
VulkanCreateInfo.ppEnabledExtensionNames = ExtensionNames;
if (vkCreateInstance(&VulkanCreateInfo, 0, &VulkanInstance) != VK_SUCCESS)
{
...
}
SDL_free(ExtensionNames);
...

How to return a string from GetOpenFileNameA

This is a function to open a file dialog in Windows and return a string with the file name:
#include <windows.h>
#include <commdlg.h>
#include <string.h>
char* openFileDlg(char FileTypes[]);
char* openFileDlg(char FileTypes[]){
OPENFILENAME ofn;
char szFile[260];
HWND hwnd;
HANDLE hf;
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
strcpy(ofn.lpstrFilter,FileTypes);
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if(GetOpenFileNameA(&ofn)){
char *toReturn;
sprintf(toReturn,"%s",ofn.lpstrFile);
return toReturn;
}
else{
return NULL;
}
}
When I call this function and open a file, the process ends and returns value 3 (which means there is an error). How can I do so that this function returns a string with the path of the selected file?
Edit: I've changed my code to this and it still doesn't work:
#include <windows.h>
#include <commdlg.h>
#include <string.h>
void openFileDlg(char *toReturn[],char FileTypes[]);
void openFileDlg(char *toReturn[],char FileTypes[]){
OPENFILENAME ofn;
/*
Code for the settings of the GetOpenFileNameA, irrelevant in this question.
If you really need to know what's here, look at the code above.
*/
if(GetOpenFileNameA(&ofn)){
strcpy(*toReturn,ofn.lpstrFile);
}
else{
sprintf(*toReturn,"");
}
}
I should also say that if I press the Cancel button in the open file dialog box instead of selecting a file, it works fine. After some tests, I've noticed that it's the line strcpy(*toReturn,ofn.lpstrFile); that causes the error.
The pointer variable toReturn doesn't point anywhere, using it in any way without initializing it (i.e. making it point somewhere valid and big enough) will lead to undefined behavior
You have two solutions really:
Allocate memory dynamically and return a pointer to that. This of course requires the caller to free the memory when done with it.
Have the function take another two arguments: A pointer to a buffer and the length of the buffer. Then copy the string into that buffer, and return a boolean "true" or "false" success/failure status.
I recommend solution number two.
On an unrelated note, there's no need to use the expensive sprintf function in your case, a simple strcpy (or strncpy if you go with the second solution) will do.
You also have to remember in both cases that strings in C have an actual length of one more than e.g. strlen reports, for the terminating '\0' character.
In general, if you want to return a string in C, I'd use one of the following methods:
1) pass in a string buffer for the method to write to:
int openFileDlg(char FileTypes[], char* toReturn, int bufLen) {
/* ... */
snprintf(toReturn, bufLen, /* what you want to print */);
return ERROR; // status-code
}
/* ... */
char errorBuf[80];
int result;
result = openFileDlg(..., errorBuf, sizeof(errorBuf));
2) allocate memory, expect caller to free it:
char* openFileDlg(char FileTypes[]) {
/* ... */
char *toReturn = malloc(/* big enough */);
sprintf(toReturn, /* what you want to print */);
return toReturn;
}
/* ... */
char* error = openFileDlg(...);
if (error) {
/* ... */
free(error);
}
personally, I'd prefer (1) because it's safer. Option (2) is nicer to the API of the function, but has a risk of memory leaks if you forget to free the returned buffer. In a bigger project (especially with multiple people working on it) this is a very real risk.
(I realise this is pretty much the same as Joachim's answer, but his went up as I was writing mine)
You did not allocate memory for your return value. If you know the length of ofn.lpstrFile you could do this:
char *toReturn = malloc( (sizeOfLpstrFile + 1) * sizeof(char)) ;
sprintf(toReturn,"%s",ofn.lpstrFile);
return toReturn;
Still I consider this a bad idea because the calling function will have to free the memory which is not obvious from the interface.

using writeprivateprofilestringw and readprivateprofilestringw in unicode not working

I try to write a push-pop like program using Read/WriteprivateprofilestringW functions and there are problems I don’t think I can see by myself. If you are kind please have a look at my lines and point me so I get it to run correctly.
When I run it with an already created file, the output of writeprivateprofilestringw's section field name is wrong. I think it’s because I’m using LPWSTR data type but nothing I tried solves it.
output:
[win32 app\Release\fonemeW.dic]
dictsionar=dicţionar
expected output:
[dictionar]
dictsionar=dicţionar
////////////////////////////////////////////////////////////////////////
//
// push word into dictionary
//
////////////////////////////////////////////////////////////////////////
void pushWordW(LPWSTR szWord, LPWSTR szFonems){
WCHAR* szDic=(WCHAR)calloc(MAX_PATH, sizeof(WCHAR));
LPWSTR sztemp=L"dictionar";
wcscpy(szDic, L"fonemeW.txt");
getDicFile(&szDic);
WritePrivateProfileStringW(L"dictionar", szFonems, szWord, szDic);
}
////////////////////////////////////////////////////////////////////////
//
// pull word from the dictionary as query fonem string
//
///////////////////////////////////////////////////////////////////////
void pullWordW(TCHAR* szWord[MAX_PATH], LPWSTR szFonems){
WCHAR* szDic=(WCHAR)calloc(MAX_PATH, sizeof(WCHAR));
wcscpy(szDic, L"fonemeW.dic");
getDicFile(&szDic);
GetPrivateProfileStringW(L"dictionar", szFonems, L"", szWord[0], 0, szDic);
if(wcslen(szWord[0])==0)
MessageBox(0, "Word not in the dictionar", "titlu popWordW", 0);
}
////////////////////////////////////////////////////////////////////////
//
// test the push-pop (from the dictionary) procedures
//
////////////////////////////////////////////////////////////////////////
void testPP(void){
LPWSTR szWord=L"dictionar";
szWord[3]=0x0163;
LPWSTR szFonem=L"dictsionar";
MessageBoxW(0, szWord, L"titlu testPP", 0);
pushWordW(szWord, szFonem);//push word into dictionar
wcscpy(szFonem, L"diade-muh");//query dictionar
pullWordW(&szWord, szFonem);//pop word from dictionary based on fonem transliteration
MessageBoxW(0, szWord, L"titlu testPP", 0);
}
edit i editted the declaration of szWord and there seems to be no problems anymore.
You did not show the implementation for getDicFile(), so I can only assume it works correctly (though the code will leak memory if getDicFile() returns a pointer to dynamically allocated memory).
I don't see any problem with the implementation of your pushWordW() function. It should not be using a filename as the INI section name. So this implies that you are actually passing an incorrect/corrupted pointer to the lpAppName parameter of WritePrivateProfileString().
However, I do see problems with the implementation of your pullWordW() and testPP() functions.
in testPP(), szWord initially points to a string literal, which is read-only. Thus, the statement szWord[3]=0x0163; should have caused a run-time error trying to write to read-only memory. So, either change the literal to L"dicţionar" so you do not need szWord[3]=0x0163; anymore, or else change the declaration of szWord to WCHAR[] instead of LPWSTR, or use malloc(), to allocate writable memory that the literal can then be copied into (in the latter case, don't forget to free() it when you are done using it).
in testPP(), szFonem initially points to a read-only string literal as well. Thus, the statement wcscpy(szFonem, L"diade-muh"); should similarly be causing a run-time error trying to write to read-only memory.
when testPP() calls pullWordW(), passing szWord using the & operator implies that pullWordW() is expected to update szWord with a new memory address pointing at the data returned by GetPrivateProfileStringW(). The problem is, GetPrivateProfileStringW() expects a pre-allocated buffer of writable memory to store the data into, but the pointer you are actually passing to it is a pointer to the read-only literal that szWord was initially set to. Again, it should be causing a run-time error. But it actually won't, because you are setting the nSize parameter of GetPrivateProfileStringW() to 0, telling it that there is no space available at the memory address for it to store data into. So no run-time errror. But, let's just say for the sake of argument that it could write data. pullWordW() is not updating its szWord parameter to point at any new memory address. And even if it did, who is responsible for allocating that memory, and who is responsible for freeing it? Your code is not defining those rules anywhere.
The fact that you are not encountering run-time errors that crash your app likely means that memory is being corrupted instead, in which case all bets are off.
Fix your code to use memory correctly. For example:
////////////////////////////////////////////////////////////////////////
//
// get dictionary filename
//
////////////////////////////////////////////////////////////////////////
bool getDicFile(LPWSTR szDic, int nDic){
// copy whatever your actual dictionary filename is...
return (wcscpy_s(szDic, nDic, L"fonemeW.dic") == 0);
}
////////////////////////////////////////////////////////////////////////
//
// push word into dictionary
//
////////////////////////////////////////////////////////////////////////
void pushWordW(LPWSTR szWord, LPWSTR szFonems){
WCHAR szDic[MAX_PATH+1];
if (getDicFile(szDic, MAX_PATH+1)){
WritePrivateProfileStringW(L"dictionar", szFonems, szWord, szDic);
}
}
////////////////////////////////////////////////////////////////////////
//
// pull word from the dictionary as query fonem string
//
///////////////////////////////////////////////////////////////////////
bool pullWordW(LPWSTR szWord, int nWord, LPWSTR szFonems){
LPWSTR szDic[MAX_PATH+1];
if (getDicFile(szDic, MAX_PATH+1)){
return (GetPrivateProfileStringW(L"dictionar", szFonems, L"", szWord, nWord, szDic) > 0);
}
return false;
}
////////////////////////////////////////////////////////////////////////
//
// test the push-pop (from the dictionary) procedures
//
////////////////////////////////////////////////////////////////////////
void testPP(void){
WCHAR szWord[256] = L"dictionar";
szWord[3]=0x0163;
WCHAR szFonem[12] = L"dictsionar";
MessageBoxW(0, szWord, L"titlu testPP", 0);
pushWordW(szWord, szFonem);//push word into dictionar
wcscpy_s(szFonem, 12, L"diade-muh");//query dictionar
if (pullWordW(szWord, 256, szFonem)){//pop word from dictionary based on fonem transliteration
MessageBoxW(0, szWord, L"titlu testPP", 0);
} else {
MessageBoxW(0, L"Word not in the dictionar", L"titlu popWordW", 0);
}
}

Tainted string in C

I'm running Coverity tool in my file operation function and getting the following error.
As you can see below, I'm using an snprintf() before passing this variable in question to the line number shown in the error message. I guess that some sanitization of the string has to be done as a part of that snprintf(). But still the warning is shown.
Error:TAINTED_STRING (TAINTED string "fn" was passed to a tainted string sink content.) [coverity]
char fn[100]; int id = 0;
char* id_str = getenv("ID");
if (id_str) {
id = atoi(id_str);
}
memset(fn, '\0', sizeof(fn));
snprintf(fn, 100, LOG_FILE, id);
if(fn[100-1] != '\0') {
fn[100-1] = '\0';
}
log_fp = fopen (fn, "a");
Any help would be highly appreciated.
Try the following:
char* id_str = getenv("ID");
if (id_str) {
id_str = strdup(id_str);
id = atoi(id_str);
free( id_str );
}
The fn string passed to fopen is tainted by an environment variable. Using strdup may act as "sanitizing".
Error:TAINTED_STRING is warning that (as far as Coverity can tell) some aspect of the behaviour is influenced by some external input and that the external input is not examined for 'safeness' before it influences execution.
In this particular example it would appear that Coverity is wrong because the value of LOG_FILE is "/log/test%d.log" and is used with an int in the snprintf, meaning that the content of char fn[100] is always well defined.
So a reasonable course of action would be to mark the error as a non-issue so that it is ignored on future runs.
Coverity wants to make sure you sanitize any string which is coming from outside of your program, be it getenv, argv, or from some file read.
You may have a function to sanitize the input(Tainted string) and have a comment provided by Coverty which tells Coverty that input string is sanitized and the SA warning will go away.
// coverity[ +tainted_string_sanitize_content : arg-0 ]
int sanitize_mystring(char* s)
{
// Do some string validation
if validated()
return SUCCESS;
else
return FAILED;
}
// coverity[ +tainted_string_sanitize_content : arg-0 ] is the line Coverty is looking
Hope this helps.

How do I embed and use resource files in a C program using VS11?

This is my first attempt at using a resource file. I have seen a lot of answers that apply to C# but not C. Any suggestions?
Assuming you mean the method used by Sysinternals and others to carry the drivers or needed DLLs (or even the x64 version of the program itself) in the resource section of a program (e.g. Sysinternals' Process Explorer), using Microsoft Visual C you can use this code:
BOOL ExtractResTo(HINSTANCE Instance, LPCTSTR BinResName, LPCTSTR NewPath, LPCTSTR ResType)
{
BOOL bResult = FALSE;
HRSRC hRsrc;
if(hRsrc = FindResource(HMODULE(Instance), BinResName, ResType))
{
HGLOBAL hGlob
if(HGLOBAL hGlob = LoadResource(Instance, hRsrc))
{
DWORD dwResSize = SizeofResource(Instance, hRsrc);
HANDLE hFileWrite = CreateFile(NewPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, 0);
if(hFileWrite != INVALID_HANDLE_VALUE)
__try
{
DWORD dwSizeWritten = 0;
bResult = (WriteFile(hFileWrite, LockResource(hGlob), dwResSize, &dwSizeWritten, NULL) && (dwSizeWritten == dwResSize));
}
__finally
{
CloseHandle(hFileWrite);
}
}
}
return bResult;
}
This saves the given resource (BinResName) of resource type (ResType) from the module (e.g. a DLL) Instance to file NewPath. Obviously if your C doesn't understand __try and __finally you'll have to adjust the code accordingly.
Taken from here (in SIDT.rar) and adjusted for C. The code is under the liberal BSD license according to the website.
Now if you wanted to get the pointer to the data (ppRes) and its size (pwdResSize):
BOOL GetResourcePointer(HINSTANCE Instance, LPCTSTR ResName, LPCTSTR ResType, LPVOID* ppRes, DWORD* pdwResSize)
{
// Check the pointers to which we want to write
if(ppRes && pdwResSize)
{
HRSRC hRsrc;
// Find the resource ResName of type ResType in the DLL/EXE described by Instance
if(hRsrc = FindResource((HMODULE)Instance, ResName, ResType))
{
HGLOBAL hGlob;
// Make sure it's in memory ...
if(hGlob = LoadResource(Instance, hRsrc))
{
// Now lock it to get a pointer
*ppRes = LockResource(hGlob);
// Also retrieve the size of the resource
*pdwResSize = SizeofResource(Instance, hRsrc);
// Return TRUE only if both succeeded
return (*ppRes && *pdwResSize);
}
}
}
// Failure means don't use the values in *ppRes and *pdwResSize
return FALSE;
}
Call like this:
LPVOID pResource;
DWORD pResourceSize;
if(GetResourcePointer(hInstance, _T("somename"), _T("sometype"), &pResource, &pResourceSize))
{
// use pResource and pResourceSize
// e.g. store into a string buffer or whatever you want to do with it ...
}
Note, this also works for resources with integer IDs. You can detect these by using the macro IS_INTRESOURCE.
The resource script, e.g. myresources.rc, itself is trivial:
#include <winnt.rh>
"somename" "sometype" "path\to\file\to\embed"
RCDATA instead of sometype is a reasonable choice
#include <winnt.rh> // for RCDATA to be known to rc.exe
"somename" RCDATA "path\to\file\to\embed"
... in which case you would adjust the above call to be:
GetResourcePointer(hInstance, _T("somename"), RT_RCDATA, &pResource, &pResourceSize)
Complete example making use of GetResourcePointer above. Let's say you have a pointer variable char* buf and you know your resource is actual text, then you need to make sure that it is zero-terminated when used as a string, that's all.
Resource script:
#include <winnt.rh>
"test" RCDATA "Test.txt"
The code accessing it
char* buf = NULL;
LPVOID pResource;
DWORD pResourceSize;
if(GetResourcePointer(hInstance, _T("test"), RT_RCDATA, &pResource, &pResourceSize))
{
if(buf = calloc(pResourceSize+1, sizeof(char)))
{
memcpy(buf, pResource, pResourceSize);
// Now use buf
free(buf);
}
}
Unless, of course you meant to simply link a .res file which works by passing it to the linker command line.

Resources