Cannot read string from Windows registry - c++

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;
}

Related

How to get extended port information when enumerating ports using Windows API

I'm using some legacy code to enumerate ports on my machine:
#include <windows.h>
#include <devguid.h>
#include <setupapi.h>
#include <string>
#include <iostream>
#include <assert.h>
bool GetTextProperty( std::string& sProperty,
HDEVINFO dev,
_SP_DEVINFO_DATA* pDeviceInfoData,
DWORD prop )
{
char szBuf[MAX_PATH];
DWORD iPropertySize = 0;
if (SetupDiGetDeviceRegistryProperty(dev, pDeviceInfoData,
prop, 0L, (PBYTE) szBuf, MAX_PATH, &iPropertySize))
{
sProperty = szBuf;
assert( iPropertySize >= sProperty.size() + 1 );
return true;
}
return false;
}
inline bool readRegistryKeyValue( HKEY hKey, const std::string& key, std::string& value )
{
bool res = false;
CHAR szBuffer[512];
DWORD dwBufferSize = sizeof(szBuffer);
ULONG nError = RegQueryValueEx(hKey, key.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
if (ERROR_SUCCESS == nError)
{
value = szBuffer;
res = true;
}
return res;
}
void ListPorts()
{
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
DWORD i;
hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0L, 0L, DIGCF_PRESENT);
if ( hDevInfo == INVALID_HANDLE_VALUE )
{
//Medoc_ReportError(MEDOC_ERROR_HARDWARE_DRIVER_API_FAILED,
// &hDevInfo, sizeof hDevInfo);
assert( false );
}
else
{
// Enumerate through all devices in Set.
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData) != 0; i++)
{
char szBuf[MAX_PATH];
short wImageIdx = 0;
short wItem = 0;
DWORD iPropertySize;
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData,
SPDRP_FRIENDLYNAME, 0L, (PBYTE) szBuf, MAX_PATH, &iPropertySize))
{
std::cout << "Smart name: " << szBuf << std::endl;
HKEY hKey = SetupDiOpenDevRegKey(
hDevInfo,
&DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DEV,
KEY_READ );
if ( hKey )
{
std::string portName;
readRegistryKeyValue( hKey, "PortName", portName );
std::cout << "Port name: " << szBuf << std::endl;
for ( DWORD prop = 0; prop != SPDRP_MAXIMUM_PROPERTY; ++prop )
{
std::string temp;
GetTextProperty( temp, hDevInfo, &DeviceInfoData, prop );
std::cout << prop << " : " << temp << std::endl;
}
RegCloseKey(hKey);
}
}
}
}
// Cleanup
SetupDiDestroyDeviceInfoList(hDevInfo);
}
int main( int argc, char* argv[] )
{
ListPorts();
return 0;
}
Among other information, this gives me access to port name (COM*), type (FTDI for instance), VID and PID...
However, when I have many different devices based on a FTDI chip plugged, they all have the same information (SPDRP_HARDWAREID prperty reports FTDIBUS\COMPORT&VID_0403&PID_6015 or FTDIBUS\COMPORT&VID_0403&PID_6010). So I cannot discriminate who is who.
When I use a USB sniffer ("Device Monitoring Studio"), this one is able to report more relevant information withoutestablishing any connection to the ports:
Can this kind of extended information be accessed through Windows API to discriminate by name many devices using the same FTDI chip? Or must I use FTDI driver API to achieve this?
With the help of Ben Voigt and Simon Mourier, I could achieve this, here is the piece of code:
// More includes:
#include <initguid.h>
#include <devpkey.h>
#include <cfgmgr32.h>
// A new dependency:
#pragma comment (lib, "Cfgmgr32.lib")
bool GetDeviceProperty( const std::string& what,
DEVINST dev,
DEVPROPKEY prop )
{
char szDeviceBuf[MAX_PATH];
DEVPROPTYPE type;
ULONG iDevicePropertySize = MAX_PATH;
if ( CM_Get_DevNode_PropertyW(dev,
&prop,
&type,
(PBYTE) szDeviceBuf,
&iDevicePropertySize,
0) == CR_SUCCESS )
{
wchar_t* txt = (wchar_t*) szDeviceBuf;
std::wstring ws(txt);
std::cout << what << " : " << std::string(ws.begin(), ws.end()) << std::endl;
return true;
}
else
{
return false;
}
}
void ListPorts()
{
...
DEVINST devInstParent;
auto status = CM_Get_Parent(&devInstParent, DeviceInfoData.DevInst, 0);
if (status == CR_SUCCESS)
{
ShowDeviceProperty( "Bus reported device description", devInstParent, DEVPKEY_Device_BusReportedDeviceDesc );
ShowDeviceProperty( "Device description", devInstParent, DEVPKEY_Device_DeviceDesc );
}
else
{
continue;
}
...

Boost Property Tree Json Read for file containing LPWSTR

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

How can I read a key value of Registry and print it to the screen with the MessageBox()

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

Not getting correct feature report

I have asked a similar question previously, but 1. no one answered and 2. it is a bit different. I have managed to get the correct file Path and created a handler by using CreateFile. I have then tried to use the HidD_GetFeature() function, but when I print out the report, it is all in symbols - not letters, numbers or readable sign. Does anyone know why it is doing that?? Here's my code:
/*****************************Mainframe.cpp**************************************/
#include"DeviceManager.h"
int main()
{
int iQuit;
DeviceManager deviceManager;
//deviceManager.ListAllDevices();
deviceManager.GetDevice("8888", "0308");
std::cin >> iQuit;
return 0;
}
/***********************************DeviceManager.h***************************/
#include <windows.h>
//#include <hidsdi.h>
#include <setupapi.h>
#include <iostream>
#include <cfgmgr32.h>
#include <tchar.h>
#include <devpkey.h>
extern "C"{
#include <hidsdi.h>
}
//#pragma comment (lib, "setupapi.lib")
class DeviceManager
{
public:
DeviceManager();
~DeviceManager();
void ListAllDevices();
void GetDevice(std::string vid, std::string pid);
HANDLE PSMove;
byte reportBuffer[57];
GUID guid;
private:
HDEVINFO deviceInfoSet; //A list of all the devices
SP_DEVINFO_DATA deviceInfoData; //A device from deviceInfoSet
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
SP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailedData;
};
/********************************DeviceManager.cpp*********************************/
#include"DeviceManager.h"
DeviceManager::DeviceManager()
{
HidD_GetHidGuid(&guid);
deviceInfoSet = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT|DIGCF_DEVICEINTERFACE); //Gets all Devices
}
DeviceManager::~DeviceManager()
{
}
void DeviceManager::ListAllDevices()
{
DWORD deviceIndex = 0;
deviceInfoData.cbSize = sizeof(deviceInfoData);
while(SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, &deviceInfoData))
{
deviceInfoData.cbSize = sizeof(deviceInfoData);
ULONG tcharSize;
CM_Get_Device_ID_Size(&tcharSize, deviceInfoData.DevInst, 0);
TCHAR* deviceIDBuffer = new TCHAR[tcharSize]; //the device ID will be stored in this array, so the tcharSize needs to be big enough to hold all the info.
//Or we can use MAX_DEVICE_ID_LEN, which is 200
CM_Get_Device_ID(deviceInfoData.DevInst, deviceIDBuffer, MAX_PATH, 0); //gets the devices ID - a long string that looks like a file path.
/*
//SetupDiGetDevicePropertyKeys(deviceInfoSet, &deviceInfoData, &devicePropertyKey, NULL, 0, 0);
if( deviceIDBuffer[8]=='8' && deviceIDBuffer[9]=='8' && deviceIDBuffer[10]=='8' && deviceIDBuffer[11]=='8' && //VID
deviceIDBuffer[17]=='0' && deviceIDBuffer[18]=='3' && deviceIDBuffer[19]=='0' && deviceIDBuffer[20]=='8') //PID
{
std::cout << deviceIDBuffer << "\t<-- Playstation Move" << std::endl;
}
else
{
std::cout << deviceIDBuffer << std::endl;
}*/
std::cout << deviceIDBuffer << std::endl;
deviceIndex++;
}
}
void DeviceManager::GetDevice(std::string vid, std::string pid)
{
DWORD deviceIndex = 0;
deviceInfoData.cbSize = sizeof(deviceInfoData);
while(SetupDiEnumDeviceInfo(deviceInfoSet, deviceIndex, &deviceInfoData))
{
deviceInfoData.cbSize = sizeof(deviceInfoData);
ULONG IDSize;
CM_Get_Device_ID_Size(&IDSize, deviceInfoData.DevInst, 0);
TCHAR* deviceID = new TCHAR[IDSize];
CM_Get_Device_ID(deviceInfoData.DevInst, deviceID, MAX_PATH, 0);
if( deviceID[8]==vid.at(0) && deviceID[9]==vid.at(1) && deviceID[10]==vid.at(2) && deviceID[11]==vid.at(3) && //VID
deviceID[17]==pid.at(0) && deviceID[18]==pid.at(1) && deviceID[19]==pid.at(2) && deviceID[20]==pid.at(3)) //PID
{
DWORD deviceInterfaceIndex = 0;
deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
//HDEVINFO deviceInterfaceSet = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE);
if(SetupDiEnumDeviceInterfaces(deviceInfoSet, &deviceInfoData, &guid, deviceInterfaceIndex, &deviceInterfaceData))
{
deviceInterfaceData.cbSize = sizeof(deviceInterfaceData);
deviceInterfaceDetailedData.cbSize = sizeof(deviceInterfaceDetailedData);
DWORD requiredSize;
SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &requiredSize, &deviceInfoData); //Gets the size
SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, &deviceInterfaceDetailedData, requiredSize, NULL, NULL); //Sets the deviceInterfaceDetailedData
//std::cout << deviceInterfaceDetailedData.DevicePath << std::endl;
PSMove = CreateFile(deviceInterfaceDetailedData.DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
reportBuffer[0] = 0;
ULONG reportBufferLength = sizeof(reportBuffer);
HidD_GetFeature(PSMove, &reportBuffer, reportBufferLength);
std::cout << reportBuffer << std::endl;
//deviceInterfaceIndex++;
}
break;
}
deviceIndex++;
}
}
the HidD_GetFeature() function is at the bottom of this huge block of code.
UPDATE: I've managed to print the report now, but it is just a random 8 bit hex. Everytime I close the program down and run it again, it prints out different results. Why's that?
The ListAllDevices() function isn't displaying the info correctly because you're outputting a wchar_t* to std::cout. You need to use std::wcout for wide chars.

Writing string (REG_SZ) values to the registry in C++

I've got most of the code for writing a value to the windows registry, however when I change the path to a dummy key and value that I've set up for testing it fails. My code is below:
HKEY hKey;
LPCTSTR sk = TEXT("SOFTWARE\TestSoftware");
LONG openRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sk, 0, KEY_ALL_ACCESS , &hKey);
if (openRes==ERROR_SUCCESS) {
printf("Success opening key.");
} else {
printf("Error opening key.");
}
LPCTSTR value = TEXT("TestSoftwareKey");
LPCTSTR data = "TestData\0";
LONG setRes = RegSetValueEx (hKey, value, 0, REG_SZ, (LPBYTE)data, strlen(data)+1);
if (setRes == ERROR_SUCCESS) {
printf("Success writing to Registry.");
} else {
printf("Error writing to Registry.");
}
LONG closeOut = RegCloseKey(hKey);
if (closeOut == ERROR_SUCCESS) {
printf("Success closing key.");
} else {
printf("Error closing key.");
}
All three tests yield error statuses.
The part that confuses me is that I was able to run this code when pointing it at other portions of the registry. Any ideas?
thanks,
brian
I feel silly. The solution is that need to properly escape the slash in the string as follows:
LPCTSTR sk = TEXT("SOFTWARE\\TestSoftware");
Hopefully someone finds this useful...
HKEY OpenKey(HKEY hRootKey, char* strKey)
{
HKEY hKey;
LONG nError = RegOpenKeyEx(hRootKey, strKey, NULL, KEY_ALL_ACCESS, &hKey);
if (nError==ERROR_FILE_NOT_FOUND)
{
cout << "Creating registry key: " << strKey << endl;
nError = RegCreateKeyEx(hRootKey, strKey, NULL, NULL, REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL, &hKey, NULL);
}
if (nError)
cout << "Error: " << nError << " Could not find or create " << strKey << endl;
return hKey;
}
void SetintVal(HKEY hKey, LPCTSTR lpValue, DWORD data)
{
LONG nError = RegSetValueEx(hKey, lpValue, NULL, REG_DWORD, (LPBYTE)&data, sizeof(DWORD));
if (nError)
cout << "Error: " << nError << " Could not set registry value: " << (char*)lpValue << endl;
}
DWORD GetintVal(HKEY hKey, LPCTSTR lpValue)
{
DWORD data;
DWORD size = sizeof(data);
DWORD type = REG_DWORD;
LONG nError = RegQueryValueEx(hKey, lpValue, NULL, &type, (LPBYTE)&data, &size);
if (nError==ERROR_FILE_NOT_FOUND)
data = 0;
SetVal() is called.
else if (nError)
cout << "Error: " << nError << " Could not get registry value " << (char*)lpValue << endl;
return data;
}
BOOL SetcharVal(HKEY Key,char* subkey,char* StringName,char* Stringdata)
{
HKEY hKey = OpenKey(Key,subkey);
LONG openRes = RegOpenKeyEx(Key, subkey, 0, KEY_ALL_ACCESS , &hKey);
if (openRes==ERROR_SUCCESS) {
} else {
printf("Error opening key.");
}
LONG setRes = RegSetValueEx (hKey, StringName, 0, REG_SZ, (LPBYTE)Stringdata, strlen(Stringdata)+1);
if (setRes == ERROR_SUCCESS) {
} else {
printf("Error writing to Registry.");
}
LONG closeOut = RegCloseKey(hKey);
if (closeOut == ERROR_SUCCESS) {
} else {
printf("Error closing key.");
}
}
char* GetCharVal(HKEY Key,char* subkey,char* StringName)
{
DWORD dwType = REG_SZ;
HKEY hKey = 0;
char value[1024];
DWORD value_length = 1024;
RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey);
RegQueryValueEx(hKey, StringName, NULL, &dwType, (LPBYTE)&value, &value_length);
RegCloseKey(hKey);
return value;
}
I am using this code.
For UNICODE environment:
//Writing to registry
HKEY hKey;
LPCTSTR sk = TEXT("SOFTWARE\\Microsoft\\Windows");
LONG openRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE, sk, 0, KEY_ALL_ACCESS, &hKey);
if (openRes == ERROR_SUCCESS) {
printf("Success opening key.");
}
else {
printf("Error opening key.");
}
LPCTSTR value = TEXT("Sample");
WCHAR path[80] = TEXT("C:\\samples\\app.exe");
LONG setRes = RegSetValueEx(hKey, value, 0, REG_SZ, (LPBYTE)path, sizeof(path));
if (setRes == ERROR_SUCCESS) {
printf("Success writing to Registry.");
}
else {
printf("Error writing to Registry.");
}
LONG closeOut = RegCloseKey(hKey);
if (closeOut == ERROR_SUCCESS) {
printf("Success closing key.");
}
else {
printf("Error closing key.");
}