I have some code that is supposed to write the content in file using WriteFile. The type of contents to be written in file are LPWSTR ie wchar_t *. The file will write ip, ssl and compression. Consider the following code:
#include <Windows.h>
#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
int main()
{
LPWSTR ip = NULL;
LPWSTR ssl = NULL;
LPWSTR comp = NULL;
wchar_t buffer[300];
HANDLE hFile;
BOOL bErrorFlag;
DWORD dwBytesToWrite = 0; //(DWORD)strlen(buffer);
DWORD dwBytesWritten = 0;
if(ip == NULL || wcslen(ip) == 0 )
{
ip = L"127.0.0.1";
}
if(ssl == NULL || wcslen(ssl) == 0)
{
ssl = L"False";
}
if(comp == NULL || wcslen(comp) == 0 )
{
comp = L"True";
}
wsprintf(buffer, L"{\n\"ip\": \"%ls\",\n\"ssl\": \"%ls\",\n\"compression\":\"%ls\"\n}",ip,ssl,comp);
//swprintf(buffer, 150, L"{\n\"ipaddress\": \"%ls\",\n\"ssl\": \"%ls\",\n\"compression\":\"%ls\"\n}",ip,ssl,comp);
std::wcout << buffer << std::endl;
dwBytesToWrite = (wcslen(buffer)) * sizeof(wchar_t);
hFile = CreateFile(L"C://SomeFolder//some_config.config", // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_ALWAYS, // always create new file
FILE_ATTRIBUTE_NORMAL, // normal file
NULL);
bErrorFlag = WriteFile(
hFile, // open file handle
buffer, // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL); // no overlapped structure
CloseHandle(hFile);
boost::property_tree::ptree pt;
try
{
boost::property_tree::read_json("C://SomeFolder//some_config.config", pt);
}
catch(std::exception &e)
{
std::cout << e.what();
}
try
{
std::cout << pt.get<std::string>("ip");
}
catch(std::exception &e)
{
std::cout << e.what();
}
}
The contents of the file will have
{
"ip": "127.0.0.1",
"ssl": "False",
"compression":"True"
}
But using read_json fails and gives error:
C://SomeFolder//some_config.config(1): expected object name
No such node (ip)
What is wrong in the code? Why can't the read_json reads the file written? If I am using WriteFile incorrectly, please correct me. Thanks.
You want to use wptree:
boost::property_tree::wptree pt;
boost::property_tree::read_json("C://SomeFolder//some_config.config", pt);
std::wcout << pt.get<std::wstring>(L"ip");
Note also L"ip" and wstring there.
Sidenote: you need const versions of the LPWSTR pointers (LPCWSTR? I guess) if you're assigning from string literals
Related
I am trying to add a new section to a portable executable, where I need to write some data, in this case an entire file.
The second file is able to parse itself and read the data from the section I created inside of it, but for some reason, it gets corrupted when I modify it using the code below.
The Imgur links are below: I'm sorry for the bad formatting :(
This messagebox should appear.
But I get this error message instead: "This app cannot run on your pc."
The new section gets added properly inside the PE:
The data inside the new section:
I can't really tell what is wrong here.
#include <iostream>
#include <Windows.h>
#include <ShlObj.h>
#include <Shlwapi.h>
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Shlwapi.lib")
DWORD align(DWORD size, DWORD align, DWORD addr) {
if (!(size % align))
return addr + size;
return addr + (size / align + 1) * align;
}
int main(int argc, char* argv[])
{
if (argc < 3)
{
std::cout << "Argomenti insufficienti.\n";
return 0;
}
char PathToSave[MAX_PATH];
if (SUCCEEDED(SHGetFolderPathA(NULL, CSIDL_COMMON_DOCUMENTS, NULL, 0, PathToSave)))
{
PathAppendA(PathToSave, "Bind.exe");
}
HANDLE fOutput = CreateFileA(PathToSave, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, NULL, NULL); // Unused
HANDLE FirstFile = CreateFileA(argv[5], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL); // File to read data from
if (FirstFile == INVALID_HANDLE_VALUE)
{
std::cout << "Impossibile aprire il file passato come primo argomento.\n";
return 0;
}
HANDLE SecFile = CreateFileA(argv[5], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); // File to write the read data in
if (SecFile == INVALID_HANDLE_VALUE)
{
std::cout << "Impossibile aprire il file passato come secondo argomento.\n";
return 0;
}
DWORD FirstFS = GetFileSize(FirstFile, 0); // First file dimension
DWORD SecondFS = GetFileSize(SecFile, 0); // Second file dimension
BYTE* FirstFB = (BYTE*)VirtualAlloc(NULL, FirstFS, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Allocates memory for the first file
BYTE* SecondFB = (BYTE*)VirtualAlloc(NULL, SecondFS, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Allocates memory for the second file
DWORD BytesRead = 0;
DWORD BytesWritten = 0;
if (bool Read = ReadFile(FirstFile, FirstFB, FirstFS, &BytesRead, NULL) == FALSE) // Reads the first file
{
std::cout << "Impossibile leggere primo file.\n";
return 0;
}
else
{
std::cout << "Letti " << BytesRead << " dal primo file.\n";
BytesRead = 0;
}
if (bool Read = ReadFile(SecFile, SecondFB, SecondFS, &BytesRead, NULL) == FALSE) // Reads the second file
{
std::cout << "Impossibile leggere secondo file.\n";
return 0;
}
else
{
std::cout << "Letti " << BytesRead << " bytes dal secondo file.\n";
BytesRead = 0;
}
/*
*
* The code is problematic beyond this point!
*
* SecondFB = Pointer to the second file's data buffer that needs to be modified by adding the new section.
* FirstFB = Pointer to the first file's data buffer that will be written inside the ".sdata" section.
* Both of them have been loaded in memory using VirtualAlloc.
*
* Ask me anything for further info and many, many thanks :D
*/
// Here I add a new section to the second file.
PIMAGE_DOS_HEADER sIDH = (IMAGE_DOS_HEADER*)SecondFB;
PIMAGE_NT_HEADERS sINH = (IMAGE_NT_HEADERS*)(SecondFB + sIDH->e_lfanew);
PIMAGE_FILE_HEADER sIFH = (PIMAGE_FILE_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(DWORD));
PIMAGE_OPTIONAL_HEADER sIOH = (PIMAGE_OPTIONAL_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER));
PIMAGE_SECTION_HEADER sISH = (PIMAGE_SECTION_HEADER)(SecondFB + sIDH->e_lfanew + sizeof(IMAGE_NT_HEADERS));
// Here I name the new section inside the file
ZeroMemory(sISH, sizeof(IMAGE_SECTION_HEADER));
CopyMemory(sISH[sIFH->NumberOfSections].Name, ".scode", 8);
/*
0xE00000E0 = IMAGE_SCN_MEM_WRITE |
IMAGE_SCN_CNT_CODE |
IMAGE_SCN_CNT_UNINITIALIZED_DATA |
IMAGE_SCN_MEM_EXECUTE |
IMAGE_SCN_CNT_INITIALIZED_DATA |
IMAGE_SCN_MEM_READ
*/
// Here all the required information gets filled in
sISH[sIFH->NumberOfSections].VirtualAddress = align(sISH[sIFH->NumberOfSections - 1].Misc.VirtualSize, sIOH->SectionAlignment, sISH[sIFH->NumberOfSections - 1].VirtualAddress);
sISH[sIFH->NumberOfSections].SizeOfRawData = align(FirstFS, sIOH->SectionAlignment, 0);
sISH[sIFH->NumberOfSections].Misc.VirtualSize = align(FirstFS, sIOH->SectionAlignment, 0);
sISH[sIFH->NumberOfSections].PointerToRawData = align(sISH[sIFH->NumberOfSections - 1].SizeOfRawData, sIOH->FileAlignment, sISH[sIFH->NumberOfSections - 1].PointerToRawData);
sISH[sIFH->NumberOfSections].Characteristics = 0xE00000E0;
// Here the changes are written to the second file
SetFilePointer(SecFile, sISH[sIFH->NumberOfSections].PointerToRawData + sISH[sIFH->NumberOfSections].SizeOfRawData, NULL, FILE_BEGIN);
SetEndOfFile(SecFile);
sIOH->SizeOfImage = sISH[sIFH->NumberOfSections].VirtualAddress + sISH[sIFH->NumberOfSections].Misc.VirtualSize;
sIFH->NumberOfSections += 1;
SetFilePointer(SecFile, 0, NULL, FILE_BEGIN);
BytesWritten = 0;
bool W = WriteFile(SecFile, SecondFB, SecondFS, &BytesWritten, NULL);
if (W == FALSE)
{
std::cout << "Impossibile aggiungere sezione alla stub.\n";
return 0;
}
else
{
std::cout << "Scritti " << BytesWritten << " bytes nella stub. (Aggiunta nuova sezione.)\n";
BytesWritten = 0;
}
// Here I write the data inside the new section
SetFilePointer(SecFile, sISH[sIFH->NumberOfSections - 1].PointerToRawData, 0, FILE_BEGIN);
if (bool Write = WriteFile(SecFile, FirstFB, FirstFS, &BytesWritten, NULL) == FALSE)
{
std::cout << "Impossibile aggiungere sezione alla stub.\n";
}
else
{
std::cout << "Scritti " << BytesWritten << " bytes nella stub.\n";
BytesWritten = 0;
}
// Here I close all the handles
VirtualFree(FirstFB, FirstFS, MEM_RELEASE);
CloseHandle(FirstFile);
VirtualFree(SecondFB, SecondFS, MEM_RELEASE);
CloseHandle(SecFile);
std::cout << "Binding completato.\n";
return 0;
}
The problem is in ZeroMemory(sISH, sizeof(IMAGE_SECTION_HEADER));
You removed the memory of the first section, which caused problems with the section structure of the exe. This is why the exe cannot run.
Solution:
=> ZeroMemory(&sISH[sIFH->NumberOfSections], sizeof(IMAGE_SECTION_HEADER)); //Clear the memory behind the last section
Don't forget to add FILE_SHARE_WRITE for the first CreateFileA, otherwise it will cause the second CreateFileA to fail to write.
=> HANDLE FirstFile = CreateFileA(argv[5], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL); // File to read data from
I'm trying to open a file on windows and check that the magic bytes match a windows PE32. If I run the code below and return just before the ReadFile call in the function problemFunction the code works fine and it prints 5a4d at the end of the main function. However if I return after the ReadFile call in problemFunction then I exit in the dos->e_magic != PIMAGE_DOS_HEADER check.
#include <Windows.h>
#include <winternl.h>
void problemFunction(HANDLE *fh) {
DWORD fileSize = GetFileSize(fh, NULL);
if (!fileSize) { CloseHandle(fh); exit(1); }
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
ReadFile(*fh, pByte, fileSize, &dw, NULL);
// could be wrong but i think i need to run SetFilePointer here but not sure on what to do.
return;
}
int main() {
const char* filepath = "C:\\windows\\file\\path\\to\\exe";
HANDLE fh = CreateFileA(filepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(fh == INVALID_HANDLE_VALUE) { CloseHandle(fh); exit(1); }
problemFunction(&fh);
DWORD fileSize = GetFileSize(fh, NULL);
if (!fileSize) { CloseHandle(fh); exit(1); }
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
ReadFile(fh, pByte, fileSize, &dw, NULL);
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pByte;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) { CloseHandle(fh); exit(1); }
// dos->e_magic should be 5a4d for MZ, windows PE
}
I assume i need to reset the file pointer after the problemFunction read call with something like
LONG reset = -sizeof(DWORD);
SetFilePointer(*fh, reset, NULL, FILE_END);
But i can't get it to work.
Thanks
There are a number of problems with your code.
problemFunction() is taking a HANDLE* pointer as input, but it is not dereferencing that pointer when passing it to GetFileSize() or CloseHandle(). But it is dereferencing the pointer when passing it to ReadFile().
You must be compiling your code with STRICT Type Checking turned off, otherwise your code would fail to compile. You should always compile with STRICT enabled.
HANDLE is a pointer type, so there is no need to pass it around by pointer, unless you are going to modify its value, which this code is not doing. So you should change problemFunction() to take a HANDLE as-is rather than taking a HANDLE* pointer.
Also, GetFileSize() does not return 0 on failure, like your code assumes. It actually returns INVALID_FILE_SIZE which is -1, ie 0XFFFFFFFF as a DWORD. This is clearly stated in the documentation:
If the function fails and lpFileSizeHigh is NULL, the return value is INVALID_FILE_SIZE. To get extended error information, call GetLastError.
But, most importantly, your 2nd call to ReadFile() inside of main() does not read what you are expecting because the 1st call to ReadFile() inside of problemFunction() has already read the data (and leaked it!), but you are not seeking the HANDLE back to the beginning of the file after that read so the 2nd call to ReadFile() can read it again. You are correct that you need to use SetFilePointer() for that.
With that said, try something more like this:
#include <Windows.h>
#include <winternl.h>
bool test(HANDLE fh) {
DWORD fileSize = GetFileSize(fh, NULL);
if (fileSize == INVALID_FILE_SIZE) {
return false;
}
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
if (!ReadFile(fh, pByte, fileSize, &dw, NULL)) {
delete[] pByte;
return false;
}
// use pByte as needed...
delete[] pByte;
if (SetFilePointer(fh, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
return false;
}
return true;
}
int main() {
const char* filepath = "C:\\windows\\file\\path\\to\\exe";
HANDLE fh = CreateFileA(filepath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) {
return 1;
}
if (!test(fh)) {
CloseHandle(fh);
return 1;
}
DWORD fileSize = GetFileSize(fh, NULL);
if (fileSize == INVALID_FILE_SIZE) {
CloseHandle(fh);
return 1;
}
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
if (!ReadFile(fh, pByte, fileSize, &dw, NULL) || dw < sizeof(IMAGE_DOS_HEADER)) {
CloseHandle(fh);
return 1;
}
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pByte;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
delete[] pByte;
CloseHandle(fh);
return 1;
}
...
delete[] pByte;
CloseHandle(fh);
return 0;
}
My goal is to get the current SetupPath of the installed Outlook Version.
I use the following code in order to achieve that:
HKEY hKey;
LONG lReturn = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\OUTLOOK.EXE"),
0L,
KEY_ALL_ACCESS,
&hKey);
if (lReturn == ERROR_SUCCESS)
{
CString strData;
DWORD dwSize = 1024;
DWORD dwType;
lReturn = RegQueryValueEx(hKey,
_T("Path"),
0L,
&dwType,
(BYTE *)strData.GetBufferSetLength((int)dwSize),
&dwSize);
if (lReturn == ERROR_SUCCESS)
{
cout << strData;
}
else {
cout << "Read DWORD failed";
}
}
else {
cout << "Open Key failed";
}
RegCloseKey(hKey);
But however this won't work. It fails at opening the Key.
EDIT
I found that the "open key failed" Output was simply an Acces Denied caused by non admin rights. But however if i run it in Admin mode the output is a Hexadecimal Value which will change everytime.
First, since you are using C++, consider making your coding life simpler, defining a simple class that automatically calls RegCloseKey() on the open key.
Then, when you open the key, consider the minimum flag you need for access: in particular, this sounds like KEY_READ in your case.
Moreover, I would call RegGetValue() instead of RegQueryValueEx(), as the former makes sure that the returned string is NUL-terminated (simplifying your code a little bit).
Moreover, when you print the CString, consider calling its GetString() method, to get the const wchar_t* C-style string pointer, instead of passing the CString object to cout.
Finally, I've simplified your code using wchar_t instead of TCHAR.
Compilable code follows (I used VS2015 and tested it on Windows 10):
#include <Windows.h>
#include <atlbase.h>
#include <atlstr.h>
#include <iostream>
using namespace std;
class ScopedKey
{
public:
explicit ScopedKey(HKEY hKey)
: m_hKey(hKey)
{
}
~ScopedKey()
{
::RegCloseKey(m_hKey);
}
HKEY Get() const
{
return m_hKey;
}
// Ban copy
ScopedKey(const ScopedKey&) = delete;
ScopedKey& operator=(const ScopedKey&) = delete;
private:
HKEY m_hKey;
};
int main()
{
constexpr int kExitOk = 0;
constexpr int kExitError = 1;
//
// Open the registry key
//
HKEY hKey;
LONG retCode = ::RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\OUTLOOK.EXE",
0,
KEY_READ,
&hKey
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegOpenKeyEx() failed; error code = " << retCode << '\n';
return kExitError;
}
// Auto-close the registry key
ScopedKey key(hKey);
//
// Get the size of the path string
//
const wchar_t* valueName = L"Path";
DWORD dataSizeInBytes = 0;
retCode = ::RegGetValue(
hKey,
nullptr,
valueName,
RRF_RT_REG_SZ,
nullptr,
nullptr,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
//
// Read the path string from the registry
//
const DWORD sizeInWchars = dataSizeInBytes / sizeof(wchar_t);
CStringW str;
wchar_t* buffer = str.GetBuffer(sizeInWchars);
retCode = ::RegGetValue(
hKey,
nullptr,
valueName,
RRF_RT_REG_SZ,
nullptr,
buffer,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
str.ReleaseBuffer();
wcout << L"Path = [" << str.GetString() << L"]\n";
// Auto-closed at end of scope
// ::RegCloseKey(hKey);
return kExitOk;
}
Output:
Path = [C:\Program Files (x86)\Microsoft Office\Root\Office16\]
In addition, you can even use RegGetValue() to automatically open (and close) the registry key for you, e.g.:
#include <Windows.h>
#include <atlbase.h>
#include <atlstr.h>
#include <iostream>
using namespace std;
int main()
{
constexpr int kExitOk = 0;
constexpr int kExitError = 1;
//
// Get the size of the path string
//
const wchar_t* subKey = L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\OUTLOOK.EXE";
const wchar_t* valueName = L"Path";
DWORD dataSizeInBytes = 0;
LONG retCode = ::RegGetValue(
HKEY_LOCAL_MACHINE,
subKey,
valueName,
RRF_RT_REG_SZ,
nullptr,
nullptr,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
//
// Read the path string from the registry
//
const DWORD sizeInWchars = dataSizeInBytes / sizeof(wchar_t);
CStringW str;
wchar_t* buffer = str.GetBuffer(sizeInWchars);
retCode = ::RegGetValue(
HKEY_LOCAL_MACHINE,
subKey,
valueName,
RRF_RT_REG_SZ,
nullptr,
buffer,
&dataSizeInBytes
);
if (retCode != ERROR_SUCCESS)
{
wcout << "RegGetValue() failed; error code = " << retCode << '\n';
return kExitError;
}
str.ReleaseBuffer();
wcout << L"Path = [" << str.GetString() << L"]\n";
return kExitOk;
}
I'm new to C++ and to WinCe developing.
I want to read a string from the registry and display with the MessageBox(). I have tried the following.
HKEY key;
if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\GPS Intermediate Driver\\Drivers\\SiRFStar3HW"), 0, KEY_READ, &key) != ERROR_SUCCESS)
{
MessageBox(NULL,L"Can't open the registry!",L"Error",MB_OK);
}
char value[5];
DWORD value_length=5;
DWORD type=REG_SZ;
RegQueryValueEx(key,(LPCTSTR)"Baud", NULL, &type, (LPBYTE)&value, &value_length);
wchar_t buffer[5];
_stprintf(buffer, _T("%i"), value);
::MessageBox(NULL,buffer,L"Value:",MB_OK);
::RegCloseKey(key);
So I know somethings wrong in here, but how can I solve?
Navigating the Win32 API can be a tricky business. The registry APIs are some of the more complicated. Here's a short program to demonstrate how to read a registry string.
#include <Windows.h>
#include <iostream>
#include <string>
using namespace std;
wstring ReadRegValue(HKEY root, wstring key, wstring name)
{
HKEY hKey;
if (RegOpenKeyEx(root, key.c_str(), 0, KEY_READ, &hKey) != ERROR_SUCCESS)
throw "Could not open registry key";
DWORD type;
DWORD cbData;
if (RegQueryValueEx(hKey, name.c_str(), NULL, &type, NULL, &cbData) != ERROR_SUCCESS)
{
RegCloseKey(hKey);
throw "Could not read registry value";
}
if (type != REG_SZ)
{
RegCloseKey(hKey);
throw "Incorrect registry value type";
}
wstring value(cbData/sizeof(wchar_t), L'\0');
if (RegQueryValueEx(hKey, name.c_str(), NULL, NULL, reinterpret_cast<LPBYTE>(&value[0]), &cbData) != ERROR_SUCCESS)
{
RegCloseKey(hKey);
throw "Could not read registry value";
}
RegCloseKey(hKey);
size_t firstNull = value.find_first_of(L'\0');
if (firstNull != string::npos)
value.resize(firstNull);
return value;
}
int wmain(int argc, wchar_t* argv[])
{
wcout << ReadRegValue(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", L"CommonFilesDir");
return 0;
}
Notes:
I don't have CE so this is a plain Win32 app, compiled for Unicode. I took that route because CE doesn't do ANSI characters.
I've taken advantage of a number of C++ features. Most significantly std::wstring. This makes string handling a cinch.
I've used exceptions for error handling. You could replace that with some other mechanism, but it served my purpose of keeping the error handling issues in the background.
Using exceptions makes closing the registry key slightly messy. A better solution would be to use an RAII class to wrap up the lifetime of the registry key. I've omitted that for simplicity, but in production code you would want to take that extra step.
Usually, RegQueryValueEx returns REG_SZ data that is null-terminated. This code deals with that by truncating beyond the first null character. In case the value returned is not null-terminated, that truncation won't happen, but the value will still be fine.
I've just printed to my console, but it would be trivial for you to call MessageBox. Like this: MessageBox(0, value.c_str(), L"Caption", MB_OK)
Here is a complete source code to read a key value of Registry and print it to the screen:
//Create C++ Win32 Project in Visual Studio
//Project -> "project" Properties->Configuration Properties->C/C++->Advanced->Show Includes : YES(/ showIncludes)
//Project -> "project" Properties->Configuration Properties->General->Project Defaults->Use of MFC : Use MFC in a shared DLL
#include <iostream>
#include <afx.h>
using namespace std;
int ReadRegistryKeyAttributes(CString ConstantKeyPath)
{
//Here ConstantKeyPath is considered as Registry Key Path to Read
HKEY MyRegistryKey;
if (RegOpenKeyEx(HKEY_CURRENT_USER, ConstantKeyPath, 0, KEY_READ, &MyRegistryKey) != ERROR_SUCCESS)
{
cout << "KeyOpen Failed" << endl;
return -1;
}
DWORD type = REG_DWORD;
DWORD cbData;
unsigned long size = 1024;
CString csVersionID;
csVersionID = _T("VersionID"); //Here VersionID is considered as Name of the Key
if (RegQueryValueEx(MyRegistryKey, csVersionID, NULL, &type, (LPBYTE)&cbData, &size) != ERROR_SUCCESS)
{
RegCloseKey(MyRegistryKey);
cout << "VersionID Key Attribute Reading Failed" << endl;
return -1; //Error
}
else
{
cout << "VersionID = " << cbData << endl; //Key value will be printed here.
}
return 1; //Success
}
int main()
{
int iResult;
CString KeyPath = _T("Software\\RCD_Technologies\\Rajib_Test");
iResult = ReadRegistryKeyAttributes(KeyPath);
if (iResult < 0)
{
cout << "ReadRegistryKeyAttributes operation Failed" << endl;
return -1;
}
cout << "<--- ReadRegistryKeyAttribute Operation Successfull -->" << endl;
getchar();
return 0;
}
Hope this example will be helpful who are seeking this problem.
This is untested (my device doesn't have your key/value), but compiles for CE and gives you the gist of how you do what you're after:
#include
int _tmain(int argc, _TCHAR* argv[])
{
HKEY key;
if(!RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
_T("System\\CurrentControlSet\\GPS Intermediate Driver\\Drivers\\SiRFStar3HW"),
0,
NULL,
&key))
{
MessageBox(NULL, _T("Failed to open key"), _T("Error"), 0);
return -1;
}
DWORD length;
// get the size - it's going to be 4 for a DWORD, but this shows how to deal with REG_SZ, etc
if(!RegQueryValueEx(
key,
_T("Baud"),
NULL,
NULL,
NULL,
&length))
{
MessageBox(NULL, _T("Failed to get buffer size"), _T("Error"), 0);
goto exit;
}
// allocate - again, if we know it's a DWORD, this could be simplified
BYTE *buffer = (BYTE*)LocalAlloc(LPTR, length);
// query
if(!RegQueryValueEx(
key,
_T("Baud"),
NULL, NULL,
buffer,
&length))
{
MessageBox(NULL, _T("Failed to get value data"), _T("Error"), 0);
goto exit;
}
// assuming "baud" is a DWORD, not a string
DWORD baud = *(DWORD*)buffer;
// build an output
TCHAR message[MAX_PATH];
_stprintf(message, _T("The baud value is %i"), baud);
MessageBox(NULL, message, _T("Success"), 0);
exit:
RegCloseKey(key);
return 0;
}
When using a char array you will need to set not the buffer but the pointer to the buffer, like this:
MessageBox(0,&buffer,"Value:",MB_OK);
just use RegQueryValueEx and put it in buf
simple question, I have problem with memmove() and memcpy() when i'm using it. I really don't understand what wrong with my code. by the way i use QT.
HANDLE hFile;
HANDLE hMapFile;
HANDLE hMapView;
hFile = CreateFileW((const wchar_t*) objPath.constData(), GENERIC_READ , 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE){
hMapFile = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapFile != INVALID_HANDLE_VALUE){
hMapView = MapViewOfFile(hMapFile, GENERIC_READ, 0, 0,0);
if (hMapView != INVALID_HANDLE_VALUE){
uint DefineWord;
memmove((void *) &DefineWord, hMapView,2); // <- always error right here
qDebug()<<DefineWord;
}
}
}
hMapView is not a pointer. memmove requires two pointers. Fix this by declaring hMapView properly. It should be a LPVOID.
MapViewOfFile returns a pointer, or NULL (0) when there is an error, not INVALID_HANDLE_VALUE (-1).
Edit: There was a lot of other problems with your code:
QString::constData() returns QChar*, not wchar_t*, you have to use QString::utf16() instead.
If CreateFileMappingW fails it returns NULL, not INVALID_HANDLE_VALUE.
MapViewOfFile access parameter is FILE_MAP_READ, not GENERIC_READ.
uint is often bigger than 2 bytes, so you should initialize the variable to 0 before memmove if you only read 2 bytes.
Here is a minimal code that should work (only tested on wineg++/wine):
#include <windows.h>
#include <QtCore/QString>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
int main(int argc, char const *argv[])
{
if (argc < 2) {
QTextStream(stdout) << "Usage :" << argv[0] << " filename" << endl;
return 1;
}
QString objPath(argv[1]);
// Qt source uses C-Style cast from utf16() to (wchar_t*),
// so it should be safe
HANDLE hFile = CreateFileW((const wchar_t *) objPath.utf16(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
qDebug() << qt_error_string();
} else {
HANDLE hMapFile = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (!hMapFile) {
qDebug() << qt_error_string();
} else {
void *pMapView = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (!pMapView) {
qDebug() << qt_error_string();
} else {
uint DefineWord = 0;
memmove((void *) &DefineWord, pMapView, 2);
qDebug() << DefineWord;
}
CloseHandle(hMapFile);
}
CloseHandle(hFile);
}
return 0;
}
PS: QString qt_error_string(int errorCode = -1) is an apparently undocumented Qt function that returns the error string of the last error (from the error code returned from GetLastError() or errno).
If you are using Qt, you can map a file to memory with QFile::map().
To do what your initial code was supposed to do, you only had to add 2 lines to the code sample you found (plus the error checking):
QFile file("foo");
if(!file.open(QFile::ReadOnly)) {
qDebug() << file.errorString();
} else {
uchar *memory = file.map(0, file.size());
if (!memory) {
qDebug() << file.errorString();
} else {
uint DefineWord = 0;
memmove(&DefineWord, memory, 2);
file.unmap();
}
}
by the way i use QT.
You aren't really using it in your example.
Qt has QFile::map method which can (and in my opinion should) be used instead of platform-specific MapViewOfFile.