Can I Read Windows Registry From Windows Service in VC++? - visual-c++

Can I Read Windows Registry From Windows Service in VC++ ?
I have written code to read from Registry in MFC Application.It works fine but the same code does not work in Windows Service project.
My code looks like this:
TCHAR szPasswordDecrypted[32] = _T("");
TCHAR* szEncryptPwd = NULL ;
HKEY hKey = NULL;
TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name
DWORD cbName; // size of name string
TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name
DWORD cchClassName = MAX_PATH; // size of class string
DWORD cSubKeys=0; // number of subkeys
DWORD cbMaxSubKey; // longest subkey size
DWORD cchMaxClass; // longest class string
DWORD cValues; // number of values for key
DWORD cchMaxValue; // longest value name
DWORD cbMaxValueData; // longest value data
DWORD cbSecurityDescriptor; // size of security descriptor
FILETIME ftLastWriteTime; // last write time
DWORD i, retCode;
long lg = RegOpenKeyEx( HKEY_CURRENT_USER,
TEXT("SOFTWARE\\NetworkDriveSolution"),
0,
KEY_READ,
&hKey
);
// Get the class name and the value count.
retCode = RegQueryInfoKey(
hKey, // key handle
achClass, // buffer for class name
&cchClassName, // size of class string
NULL, // reserved
&cSubKeys, // number of subkeys
&cbMaxSubKey, // longest subkey size
&cchMaxClass, // longest class string
&cValues, // number of values for this key
&cchMaxValue, // longest value name
&cbMaxValueData, // longest value data
&cbSecurityDescriptor, // security descriptor
&ftLastWriteTime); // last write time

HKEY_CURRENT_USER refers to the user the process is running as. Your service will likely run as LocalSystem, not as you. Best bet is to store information under HKEY_LOCAL_MACHINE.

You must use HKEY_LOCAL_MACHINE. You must have time calculation in this service.
As well you must use Registry APIs. Mainly RegNotifyChangeKeyValue(..) to monitor change of event.

Related

How can I get the value of a registry key in c++ without an access violation?

Hey I'm new to C++ and I am trying to find out if a specified registry index exists. I have to check multiple locations due to the possibility of the software being run on a 64bit machine and being under the WOW6432Node key instead of the usual position. When RegQueryValueExA (using visual c++ 6.0 on xp so I can't use a newer function) is run it should return a Boolean of true if the key exists, (I'll deal with getting the value of the key later). However on run it generates access violation 0xc00005. Any ideas whats gone wrong?
bool FindAndRemoveUninstall(string path){
bool result;
result = RegQueryValueExA(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC"), NULL, NULL, NULL, (unsigned long *)MAX_PATH);
if (result= ERROR_SUCCESS){
cout <<" is a 32 bit program\n";
//path= Value in key
}
result = RegQueryValueEx(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC"), NULL, NULL, NULL, (unsigned long *)MAX_PATH);
if (result= ERROR_SUCCESS){
cout << " is 64 bit program\n";
//path= Value in key
}
return true;
}
You have multiple problems.
The last parameter to RegQueryValueExA is documented as
lpcbData [in, out, optional]
A pointer to a variable that specifies the size of the buffer pointed to by the lpData parameter,
But you are not passing a pointer to a variable. You are passing (unsigned long *)MAX_PATH, which is a garbage pointer. When the operating system tries to store the result into the pointer, it takes an access violation. You need to pass a pointer to a variable, like the documentation says.
The next problem is that you are calling the A function (explicit ANSI) but using the TEXT macro (adaptive character set). Make up your mind which model you are using (ANSI or adaptive) and choose one model or the other. Let's assume you explicit ANSI.
The next problem is that you didn't specify an output buffer, so you don't actually retrieve the path.
Another problem is that the RegQueryValueExA function does not return a bool; it returns an error code.
Yet another problem is that your if test contains an assignment, so it does not actually test anything.
Another problem is that you didn't specify a way for the function to return the path to the caller. Let's assume you want the result to be returned in the path parameter.
Yet another problem is that you have the 32-bit and 64-bit cases reversed.
Also, you are using '\n' instead of std::endl.
The eight problem is that your function returns true even if it didn't do anything.
And the ninth problem is that the function says FindAndRemove, and it finds, but doesn't remove.
bool FindUninstall(string& path){ // parameter passed by reference, fix function name
LONG result; // change variable type
char buffer[MAX_PATH]; // provide an output buffer
DWORD bufferSize = MAX_PATH; // and a variable to specify the buffer size / receive the data size
result = RegQueryValueExA(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC", NULL, NULL, (LPBYTE)buffer, &bufferSize); // remove TEXT macro, pass the buffer and buffer size
if (result== ERROR_SUCCESS){ // fix comparison
cout <<" is a 64 bit program" << std::endl; // fix message
path = buffer;
return true; // stop once we have an answer
}
buffersize = MAX_PATH; // reset for next query
result = RegQueryValueEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ABC", NULL, NULL, (LPBYTE)buffer, &bufferSize); // remove TEXT macro, pass the buffer and buffer size
if (result== ERROR_SUCCESS){ // fix comparison
cout << " is 32 bit program" << std::endl; // fix message
path = buffer;
return true; // stop once we have an answer
}
return false; // nothing found
}
Since you are new to C++, I would recommend that you get some experience with C++ doing simpler projects before diving into more complicated things like this.

How to send integer as a string with WriteFile for serialport

I want to send an integer as a string buffer to a serial port with WriteFile. This data value is result from the sensor, this data max has 2 characters.
I have tried to convert with itoa
for example:
DWORD nbytes;
int a,b,c;
a=10;
char *tempa ="";
tempa = itoa(a, tempa,0);
if(!WriteFile( hnd_serial, a, 2, &nbytes, NULL )){MessageBox(L"Write Com Port fail!");return;}
This code is not working.
Unhandled exception at 0x1024d496 (msvcr100d.dll) in ENVSConfig.exe: 0xC0000094: Integer division by zero.
Also I have tried the suggestion from this website:
convert int to string but still does not working to.
Is there any clue to do this?
You are not using itoa properly, you need to allocate space for your string, you need to provide a proper radix (this is where your divide-by-zero error is happening) and finally you need to use the buffer, not your original a value, as the buffer in your write.
Try the following:
DWORD nbytes;
int a,b,c;
a = 10;
char tempa[64]; // Randomly picked 64 characters as the max size
itoa(a, tempa, 10);
if(!WriteFile(hnd_serial, tempa, 2, &nbytes, NULL))
{
MessageBox(L"Write Com Port fail!");
return;
}

Converting an int or String to a char array on Arduino

I am getting an int value from one of the analog pins on my Arduino. How do I concatenate this to a String and then convert the String to a char[]?
It was suggested that I try char msg[] = myString.getChars();, but I am receiving a message that getChars does not exist.
To convert and append an integer, use operator += (or member function concat):
String stringOne = "A long integer: ";
stringOne += 123456789;
To get the string as type char[], use toCharArray():
char charBuf[50];
stringOne.toCharArray(charBuf, 50)
In the example, there is only space for 49 characters (presuming it is terminated by null). You may want to make the size dynamic.
Overhead
The cost of bringing in String (it is not included if not used anywhere in the sketch), is approximately 1212 bytes of program memory (flash) and 48 bytes RAM.
This was measured using Arduino IDE version 1.8.10 (2019-09-13) for an Arduino Leonardo sketch.
Risk
There must be sufficient free RAM available. Otherwise, the result may be lockup/freeze of the application or other strange behaviour (UB).
Just as a reference, below is an example of how to convert between String and char[] with a dynamic length -
// Define
String str = "This is my string";
// Length (with one extra character for the null terminator)
int str_len = str.length() + 1;
// Prepare the character array (the buffer)
char char_array[str_len];
// Copy it over
str.toCharArray(char_array, str_len);
Yes, this is painfully obtuse for something as simple as a type conversion, but somehow it's the easiest way.
You can convert it to char* if you don't need a modifiable string by using:
(char*) yourString.c_str();
This would be very useful when you want to publish a String variable via MQTT in arduino.
None of that stuff worked. Here's a much simpler way .. the label str is the pointer to what IS an array...
String str = String(yourNumber, DEC); // Obviously .. get your int or byte into the string
str = str + '\r' + '\n'; // Add the required carriage return, optional line feed
byte str_len = str.length();
// Get the length of the whole lot .. C will kindly
// place a null at the end of the string which makes
// it by default an array[].
// The [0] element is the highest digit... so we
// have a separate place counter for the array...
byte arrayPointer = 0;
while (str_len)
{
// I was outputting the digits to the TX buffer
if ((UCSR0A & (1<<UDRE0))) // Is the TX buffer empty?
{
UDR0 = str[arrayPointer];
--str_len;
++arrayPointer;
}
}
With all the answers here, I'm surprised no one has brought up using itoa already built in.
It inserts the string representation of the integer into the given pointer.
int a = 4625;
char cStr[5]; // number of digits + 1 for null terminator
itoa(a, cStr, 10); // int value, pointer to string, base number
Or if you're unsure of the length of the string:
int b = 80085;
int len = String(b).length();
char cStr[len + 1]; // String.length() does not include the null terminator
itoa(b, cStr, 10); // or you could use String(b).toCharArray(cStr, len);

Convert hex to int

I've seen lots of answers to this, but I cannot seem to get any to work. I think I'm getting confused between variable types. I have an input from NetworkStream that is put a hex code into a String^. I need to take part of this string, convert it to a number (presumably int) so I can add some arithemetic, then output the reult on the form. The code I have so far:
String^ msg; // gets filled later, e.g. with "A55A6B0550000000FFFBDE0030C8"
String^ test;
//I have selected the relevant part of the string, e.g. 5A
test = msg->Substring(2, 2);
//I have tried many different routes to extract the numverical value of the
//substring. Below are some of them:
std::stringstream ss;
hexInt = 0;
//Works if test is string, not String^ but then I can't output it later.
ss << sscanf(test.c_str(), "%x", &hexInt);
//--------
sprintf(&hexInt, "%d", test);
//--------
//And a few others that I've deleted after they don't work at all.
//Output:
this->textBox1->AppendText("Display numerical value after a bit of math");
Any help with this would be greatly appreciated.
Chris
Does this help?
String^ hex = L"5A";
int converted = System::Convert::ToInt32(hex, 16);
The documentation for the Convert static method used is on the MSDN.
You need to stop thinking about using the standard C++ library with managed types. The .Net BCL is really very good...
Hope this helps:
/*
the method demonstrates converting hexadecimal values,
which are broken into low and high bytes.
*/
int main(){
//character buffer
char buf[1];
buf[0]= 0x06; //buffer initialized to some hex value
buf[1]= 0xAE; //buffer initialized to some hex value
int number=0;
//number generated by binary shift of high byte and its OR with low byte
number = 0xFFFF&((buf[1]<<8)|buf[0]);
printf("%x",number); //this prints AE06
printf(ā€œ%dā€,number); //this prints the integer equivalent
getch();
}

How to generify data for "mov" instruction?

I need to understand just 1 single instruction and accordingly I need to generify the things.
I need to pass structures (Objects of User Defined Data Types) at runtime using following assembly code.
Where Following is User Defined Data Type namely WESContext :
typedef struct CWESContext
{
BSTR UserName;
BSTR MachineIP;
BSTR Certificate;
BSTR BrowserClienthandle;//Its the handle of the BrowserClient or Java Application Level Object
BSTR SessionID;
BSTR TaskID;// name of the original task
long LocaleID;//The location of the ultimate Caller
long FeatureID;//The feature ID mapping to some feature available in WESFW
long SessionTypeID;//Itmay be; Browser CLient Session, OPC Client Session, Authenticated OPC Clients session(as they have more rights), WESFWSystemClient.
SYSTEMTIME TimeStamp;//the time the original task was executed
DWORD Priority; //task priority of the original task
struct WESProductCategory
{
BSTR ProductCategoryName;
int serialNo;
struct WESDimensions
{
int weight;
struct WESVolume
{
int length;
int heigth;
int width;
} oVolume;
BSTR tempHeight;
BSTR otherUnknownDimensions;
} oDimensions;
} oWESProductCategory;
} CWESContext;
I have created the block enough of size WESContext and filled it with sample data.
int sizeOfWESContext = sizeof(CWESContext);
void *pWESContext = malloc(sizeOfWESContext);
void *pGenericPtr = pWESContext;
memset(pWESContext,0,sizeOfWESContext);
BSTR *bstrUserName = (BSTR*)pGenericPtr;
*bstrUserName = SysAllocString(CT2OLE(CA2T(results.at(0).c_str())));
bstrUserName++;
pGenericPtr = bstrUserName;
BSTR *bstrMachineIp = (BSTR*)pGenericPtr;
*bstrMachineIp = SysAllocString(CT2OLE(CA2T(results.at(1).c_str())));
bstrMachineIp++;
pGenericPtr = bstrMachineIp;
BSTR *bstrCertificate = (BSTR*)pGenericPtr;
*bstrCertificate = SysAllocString(CT2OLE(CA2T(results.at(2).c_str())));
bstrCertificate++;
pGenericPtr = bstrCertificate;
.....................
so on so forth...............
If I call it by passing this as object:
Calling Normaly :
MyCallableMethodUDT(((CWESContext)pWESContext));
Now following assembly i just pulled from Dissasembly view of Visual Studio while debugging.
mov esi,dword ptr [pWESContext]
sub esp,58h
mov ecx,16h
mov edi,esp
rep movs dword ptr es:[edi],dword ptr [esi]
I just need to understand 3rd line..
AS I increase members inside my User Defined Structure (i.e here WESContext) it increases but I am unable to conclude how it increases....? I need to generify this instruction so that whatever the Object is and whatever the size and whatever kind of data it contains....it should get pass by calling it with writing assembly instruction as written above.
Regards,
Usman
ecx is used as the count for the number of dwords to be copied by the rep movs instructions in line 5. It's copying data from the starting address pointed to by esi to the location starting at edi.
The value in ecx would be the size of the data that is being copied.

Resources