Creating a file with the same name as registry - c++

I want to create a text file with the same name as a registry.
Say, I get the variable valueName, and I want it's value to be the name of a .txt file in C:\ How can I do that?
Almost final code:
void EnumerateValues(HKEY hKey, DWORD numValues)
{
for (DWORD dwIndex = 0; dwIndex < numValues; dwIndex++)
{BOOL bErrorFlag = FALSE;
char valueName[64];
DWORD valNameLen = sizeof(valueName);
DWORD dataType;
DWORD dataSize = 0;
DWORD retval = RegEnumValue(hKey, dwIndex, valueName, &valNameLen,
NULL, &dataType, NULL, &dataSize);
if (retval == ERROR_SUCCESS)
{//pregatesc calea
char* val = new char[strlen(valueName)];
sprintf(val, "C:\\%s.txt", valueName);
printf("S-a creat fisierul: %s\n", val);
//creez/suprascriu fisierul
HANDLE hFile;
hFile=CreateFile(val,GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ,
NULL, CREATE_ALWAYS , FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile == INVALID_HANDLE_VALUE)
{ printf("Eroare la creat fisierul %s!\n",val);
}
//sciru in fisier
char str[] = "Example text testing WriteFile";
DWORD bytesWritten=0;
DWORD dwBytesToWrite = (DWORD)strlen(str);
bErrorFlag=WriteFile(hFile, str, dwBytesToWrite, &bytesWritten, NULL);
if (FALSE == bErrorFlag)
{
printf("Eroare la scriere in fisier\n");
}
//inchid fisierul
CloseHandle(hFile);
}
//eroare regenumv
else printf("\nError RegEnumValue");
}
}

The fundamental problem is that you seem to want to convert a registry key, HKEY into a path. And there's no API to do that. You will need to keep track of the path and pass it to the function in the question, along with the HKEY.
You are passing uninitialized values to RegEnumValue, specifically dataSize. Since you don't care about the data, don't ask for it. Pass NULL for the data pointer, and zero for data size.
Your call to new is not allocating enough memory. You need space for the directory name, the file extension, and the null-terminator.
These problems are exacerbated by your complete neglect for error checking. That might sound harsh, but frankly you need some shock treatment. In order to be able to fail gracefully you need to check for errors. More pressing for you, in order to be able to debug code, you need to check for errors.
You've tagged the code C++ but write as if it were C. If you really are using C++ then you can use standard containers, std::string, avoid raw memory allocation and the result leaks. Yes, you code leaks as it stands.

first of all your program is more C like than C++, but if you want to solve this in C++ you can use stringstream in the following way:
std::stringstream stream;
stream << "C:\\";
stream << valueName;
stream << ".txt";
std::string filename(stream.str());
HANDLE hFile=CreateFile(filename.c_str() ,GENERIC_READ,FILE_SHARE_READ,
NULL, CREATE_NEW , FILE_ATTRIBUTE_NORMAL,NULL);
Also you need a include:
#include <sstream>

Related

how can I allocate an array on the stack if the size is not known at compile time?

I'm writing a c++ program with visual studio and I have written this code
DWORD GetProcIDByName(const char* procName) {
HANDLE hSnap;
BOOL done;
PROCESSENTRY32 procEntry;
ZeroMemory(&procEntry, sizeof(PROCESSENTRY32));
procEntry.dwSize = sizeof(PROCESSENTRY32);
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
done = Process32First(hSnap, &procEntry);
do {
/* here */ char file_str[sizeof(procEntry.szExeFile)];
int wc_convert = WideCharToMultiByte(CP_ACP, 0, procEntry.szExeFile, sizeof(procEntry.szExeFile), file_str, sizeof(file_str), NULL, NULL);
if (_strnicmp(file_str, procName, sizeof(file_str)) == 0) {
return procEntry.th32ProcessID;
}
} while (Process32Next(hSnap, &procEntry));
return 0;
}
in order to convert the value procEntry.szExeFile from a WCHAR* (wide unicode character array), to a standard char* to compare, I had to make a char* buffer for it. I wrote the line
char file_str[sizeof(procEntry.szExeFile)];
and realized later that I should use heap memory for this buffer that will change sizes depending on the process name, but I was surprised to see that my visual studio had no problem with this code and I was able to build it with no compiler errors. I haven't run it yet and I probably will not because I imagine if this runs there is a potential for buffer overflow and undefined behaviour
I don't have any issue, but I am curious about why I was able to write this code without getting a compiler error. If the process name is not known at compile time, how can I allocate this buffer on the stack?
The szExeFile field is not dynamic length. It is a fixed-length array of MAX_PATH characters, holding a null-terminated string.
Note that:
sizeof() reports a size in bytes
szExeFile is an array of wchar_t characters, in your case
wchar_t is 2 bytes in size on Windows.
So, when you declare your char[] array as char file_str[sizeof(procEntry.szExeFile)];, it will have a static compile-time size of MAX_PATH*2 chars. Which should be large enough to easily handle most conversions from wchar_t[] to char[] in this case.
BTW, your use of sizeof(procEntry.szExeFile) in the 4th parameter of WideCharToMultiByte() is wrong. That parameter expects a character count, not a byte count. Use lstrlenW(procEntry.szExeFile) or wcslen(procEntry.szExeFile) instead. Or just -1 to let WideCharToMultiByte() count the wide characters for you.
That being said, an easier solution is to use Process32FirstA()/Process32NextA() instead. Or, change your function to take a Unicode wchar_t string as input. Either way, then you won't have to convert the procEntry.szExeFile at all, just use it as-is.
Also, you are leaking the HANDLE from CreateToolhelp32Snapshot(), you need to call CloseHandle() when you are done using it.
Try this:
DWORD GetProcIDByName(const char* procName) {
DWORD dwProcessID = 0;
PROCESSENTRY32A procEntry = {};
procEntry.dwSize = sizeof(procEntry);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32FirstA(hSnap, &procEntry);
while (ok) {
if (_stricmp(procEntry.szExeFile, procName) == 0) {
dwProcessID = procEntry.th32ProcessID;
break;
}
ok = Process32NextA(hSnap, &procEntry);
}
CloseHandle(hSnap);
}
return dwProcessID;
}
Or this:
DWORD GetProcIDByName(const wchar_t* procName) {
DWORD dwProcessID = 0;
PROCESSENTRY32W procEntry = {};
procEntry.dwSize = sizeof(procEntry);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32FirstW(hSnap, &procEntry);
while (ok) {
if (_wcsicmp(procEntry.szExeFile, procName) == 0) {
dwProcessID = procEntry.th32ProcessID;
break;
}
ok = Process32NextW(hSnap, &procEntry);
}
CloseHandle(hSnap);
}
return dwProcessID;
}

Resource Data Doesnt Write to TextFile

void Extract(WORD wResId , LPSTR lpszOutputPath)
{
HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(wResId) , RT_RCDATA);
HGLOBAL hLoaded = LoadResource( NULL,hrsrc);
LPVOID lpLock = LockResource( hLoaded);
DWORD dwSize = SizeofResource(NULL, hrsrc);
HANDLE hFile = CreateFile("C://Windows//Darek//mylo.txt",GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
DWORD dwByteWritten;
char* cRes = (char*)malloc (dwSize);
memset(cRes,0,dwSize);
memcpy (cRes, cData, dwSize);
cRes[dwSize] = '\0';
FreeResource(hLoaded);
WriteFile(hFile, lpLock , dwSize , &dwByteWritten , NULL);
CloseHandle(hFile);
FreeResource(hLoaded);
}
Ok this creates the file correctly, but the extracted data doesnt seem to extract and write to the textFile,Any problems? i do not seem to understand why it doesnt extract and Write the data to the file.
Please Help.
You are allocating a memory block that is as large as the resource, zeroing it out (which is redundant), and copying something (what is cData pointing at? Maybe you meant lpLock instead?) into that memory, but then you are ignoring the allocated memory and leaking it. You are trying to write the content of lpLock to the file as-is, which is what you should be doing, but you are not doing any error handling at all. Chances are, your resource is missing, or otherwise not available for reading. That would account for your file being empty.
Try this instead:
void Extract(WORD wResId, LPSTR lpszOutputPath)
{
HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(wResId), RT_RCDATA);
if (!hrsrc)
{
// GetLastError() tells you why it failed...
return;
}
HGLOBAL hLoaded = LoadResource(NULL, hrsrc);
if (!hLoaded)
{
// GetLastError() tells you why it failed...
return;
}
DWORD dwSize = SizeofResource(NULL, hrsrc);
if ((dwSize == 0) && (GetLastError() != 0))
{
// GetLastError() tells you why it failed...
return;
}
LPVOID lpLock = LockResource(hLoaded);
if (!lpLock)
{
// GetLastError() tells you why it failed...
return;
}
HANDLE hFile = CreateFileA(lpszOutputPath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
// GetLastError() tells you why it failed...
return;
}
DWORD dwByteWritten;
if (!WriteFile(hFile, lpLock, dwSize, &dwByteWritten, NULL))
{
// GetLastError() tells you why it failed...
CloseHandle(hFile);
DeleteFileA(lpszOutputPath);
return;
}
CloseHandle(hFile);
}
If I had to guess (and please don't make people guess), FindResource() is most likely returning NULL. Make sure the second parameter actually matches the correct resource type for wResId. You cannot load any arbitrary resource using RT_RCDATA, you have to use the correct resource type. Only resources using the RCDATA type can be accessed using the RT_RCDATA parameter value. String resources might be stored using the RT_MESSAGETABLE or RT_STRING type instead, for instance. You can use EnumResourceTypes() and EnumResourceNames(), or an external resource editor/viewer tool, to find out what type the wResId resource is actually using.

C++ WriteFile only writing 4 bytes

Here's what I'm trying to achieve; I'm hooking onto the HttpSendRequest function (on Xbox it's XHttp) and trying dump the certificate that's in pcszHeaders which has the size of 0x1F0E.
Now the problem; it only seems to write 4 bytes, I've even tried allocating extra memory and setting each bit to 0 to see if it's the size of Headers and it continues to only write 4 bytes. I've been able to dump pcszHeaders remotely because I got the address whilst debugging but I need to dump it at run-time.
Something I notice whilst debugging - The address of pcszHeaders only shows in locals until it reaches;
printf("XHttpSendRequest: %s\n", "Creating Certificate.bin...");
Once it reaches the printf() above the address changes to 0x00000000 (bad ptr) but it still writes the first byte of correct data of pcszHeaders correctly but nothing more.
Here is the entire hook;
BOOL XHTTP_SEND_REQUEST_HOOK(
HINTERNET hRequest,
const CHAR *pcszHeaders,
DWORD dwHeadersLength,
const VOID *lpOptional,
DWORD dwOptionalLength,
DWORD dwTotalLength,
DWORD_PTR dwContext)
{
if(pcszHeaders != XHTTP_NO_ADDITIONAL_HEADERS)
{
printf("XHttpSendRequest: %s\n", "Creating Certificate.bin...");
// Setup expansion
doMountPath("Hdd:", "\\Device\\Harddisk0\\Partition1");
//create our file
HANDLE fileHandle = CreateFile("Hdd:\\Certificate.bin", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
//does file exist?
if(GetLastError()!=ERROR_ALREADY_EXISTS
||fileHandle!=INVALID_HANDLE_VALUE)
{
printf("XHttpSendRequest: %s\n", "Writing to file...");
DWORD wfbr;
//write to our file
if(WriteFile(fileHandle, pcszHeaders, 0x2000, &wfbr, NULL))
{
printf("XHttpSendRequest: %s\n", "File written!");
printf("%s\n", "Request has ended.");
CloseHandle(fileHandle);
return XHttpSendRequest(hRequest, pcszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext);
}
}
}
}
EDIT: I've changed the code slightly and I've copied pcszHeaders data into another section of memory that I've created and my pointers seems to have all the correct data and I've tried Writing it to file and it still only writes 4 bytes. I've even used sizeof() instead of hard-coded 0x2000.
pcszHeaders is a char* pointer. sizeof(pcszHeaders) is 4 in a 32bit app (8 in a 64bit app). You need to use the dwHeadersLength parameter instead, which tells you how many characters are in pcszHeaders.
Also, your GetLastError() check after CreateFile() is wrong. If CreateFile() fails for any reason other than ERROR_ALREADY_EXISTS, you are entering the code block and thus writing data to an invalid file handle. When using CREATE_NEW, CreateFile() returns INVALID_HANDLE_VALUE if the file already exists. You don't need to check GetLastError() for that, checking for INVALID_HANDLE_VALUE by itself is enough. If you want to overwrite the existing file, use CREATE_ALWAYS instead.
You are also leaking the file handle if WriteFile() fails.
And you are calling the original HttpSendRequest() only if you successfully write headers to your file. If there are no headers, or the create/write fails, you are not allowing the request to proceed. Is that what you really want?
Try this instead:
BOOL XHTTP_SEND_REQUEST_HOOK(
HINTERNET hRequest,
const CHAR *pcszHeaders,
DWORD dwHeadersLength,
const VOID *lpOptional,
DWORD dwOptionalLength,
DWORD dwTotalLength,
DWORD_PTR dwContext)
{
if (pcszHeaders != XHTTP_NO_ADDITIONAL_HEADERS)
{
printf("XHttpSendRequest: Creating Certificate.bin...\n");
// Setup expansion
doMountPath("Hdd:", "\\Device\\Harddisk0\\Partition1");
//create our file
HANDLE fileHandle = CreateFile("Hdd:\\Certificate.bin", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
//is file open?
if (fileHandle != INVALID_HANDLE_VALUE)
{
printf("XHttpSendRequest: Writing to file...\n");
DWORD wfbr;
//write to our file
if (WriteFile(fileHandle, pcszHeaders, dwHeadersLength, &wfbr, NULL))
printf("XHttpSendRequest: File written!\n");
else
printf("XHttpSendRequest: Error writing to file: %u\n", GetLastError());
CloseHandle(fileHandle);
}
else
printf("XHttpSendRequest: Error creating file: %u\n", GetLastError());
}
printf("Request has ended.\n");
return XHttpSendRequest(hRequest, pcszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext);
}
Finally the problem has been solved!
First I created an empty array for the data to be stored.
CHAR xtoken[0x2000];
memset(xtoken, 0, 0x2000);
The first part of the hook is to store the header data.
DWORD bufferLength = dwHeadersLength;
memcpy(xtoken, pcszHeaders, bufferLength);
I then write the data to file
WriteFile(fileHandle, (void*)&xtoken, bufferLength, &wfbr, NULL))
Success! I guess the problem was that parameter 2 of WriteFile() was incorrect.

WinAPI File In-/Output with std::strings instead of char arrays?

due to performance reasons I didn't feel like using fstream for just one time. Seems like a very bad idea to use WinAPI functions with a std::string instead of a plain char array. All in all I would like you to tell me why the following snippet just won't work (empty stBuffer stays empty) and what I'd need to do to get it fixed.
Thanks in advance!
std::size_t Get(const std::string &stFileName, std::string &stBuffer)
{
HANDLE hFile = ::CreateFileA(stFileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD dwBytesRead = 0;
if(hFile != INVALID_HANDLE_VALUE)
{
DWORD dwFileSize = ::GetFileSize(hFile, NULL);
stBuffer.reserve(dwFileSize + 1);
::ReadFile(hFile, &stBuffer[0], dwFileSize, &dwBytesRead, NULL);
stBuffer[dwFileSize] = '\0';
::CloseHandle(hFile);
}
return dwBytesRead;
}
Because a std::string can contain embedded '\0' characters, it has to keep track of its own length in a separate way.
Your problem is that std::string::reserve() does not change the length of the string. It just pre-allocates some memory for the string to grow into. The solution is to use std::string::resize() and let the WinAPI function overwrite the string contents.
As a side-note: Currently, it is not guaranteed that std::string uses a contiguous buffer, but to my knowledge, all current implementations do use a contiguous buffer and it will be a requirement in the next standard.
Consider difference between reserve() and resize() members. So the solution would be:
stBuffer.resize(dwFileSize + 1);

Trouble using ReadFile() to read a string from a text file

How can I make the code below to read correct text. In my text file has Hello welcome to C++, however at the end of the text, it has a new line. With the code below, my readBuffer always contains extra characters.
DWORD byteWritten;
int fileSize = 0;
//Use CreateFile to check if the file exists or not.
HANDLE hFile = CreateFile(myFile, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
BOOL readSuccess;
DWORD byteReading;
char readBuffer[256];
readSuccess = ReadFile(hFile, readBuffer, byteReading, &byteReading, NULL);
if(readSuccess == TRUE)
{
TCHAR myBuffer[256];
mbstowcs(myBuffer, readBuffer, 256);
if(_tcscmp(myBuffer, TEXT("Hello welcome to C++")) == 0)
{
FindClose(hFile);
CloseHandle(hFile);
WriteResultFile(TRUE, TEXT("success!"));
}
}
}
Thanks,
There are a few problems:
You're passing uninitialized data (byteReading) as the "# of bytes to read" parameter to ReadFile().
Depending on how you created the file, the file's contents may not have a terminating 0 byte. The code assumes that the terminator is present.
FindClose(hFile) doesn't make sense. CloseHandle(hFile) is all you need.
You need to call CloseHandle if CreateFile() succeeds. Currently, you call it only if you find the string you're looking for.
This isn't a bug, but it's helpful to zero-initialize your buffers. That makes it easier to see in the debugger exactly how much data is being read.
HANDLE hFile = CreateFile(myfile, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
BOOL readSuccess;
DWORD byteReading = 255;
char readBuffer[256];
readSuccess = ReadFile(hFile, readBuffer, byteReading, &byteReading, NULL);
readBuffer[byteReading] = 0;
if(readSuccess == TRUE)
{
TCHAR myBuffer[256];
mbstowcs(myBuffer, readBuffer, 256);
if(_tcscmp(myBuffer, TEXT("Hello welcome to C++")) == 0)
{
rv = 0;
}
}
CloseHandle(hFile);
}
I see two things:
byteReading isn't initialized
you are reading bytes so you have to terminate the string by 0.
CloseHandle is sufficient
Either remove the new line character from the file or use _tcsstr for checking the existence of the string "Hello Welcome to C++".