RegQueryValueExW only brings back one value from registry - c++

I am querying the registry on Windows CE. I want to pull back the DhcpDNS value from the TcpIp area of the registry, which works.
What happens though, however, is if there is two values - displayed as "x.x.x.x" "x.x.x.x" in my CE registry editor - then it only brings back one of them. I am sure this is a silly mistake but I am unsure why it is happening.
Here is the code I am using
std::string ISAPIConfig::GetTcpIpRegSetting(const std::wstring &regEntryName)
{
HKEY hKey = 0;
HKEY root = HKEY_LOCAL_MACHINE;
LONG retVal = 0;
wchar_t buffer[3000];
DWORD bufferSize = 0;
DWORD dataType = 0;
std::string dataString = "";
//Open IP regkey
retVal = RegOpenKeyExW(root, L"Comm\\PCI\\FETCE6B1\\Parms\\TcpIp", 0, 0, &hKey);
//Pull out info we need
memset(buffer, 0, sizeof(buffer));
bufferSize = sizeof(buffer);
retVal = RegQueryValueExW(hKey, regEntryName.c_str(), 0, &dataType, reinterpret_cast<LPBYTE>(buffer), &bufferSize);
Unicode::UnicodeToAnsi(buffer, dataString);
return dataString;
}
void UnicodeToAnsi(const std::wstring &wideString, std::string &ansiString){
std::wostringstream converter;
std::ostringstream converted;
std::wstring::const_iterator loop;
for(loop = wideString.begin(); loop != wideString.end(); ++loop){
converted << converter.narrow((*loop));
}
ansiString = converted.str();
}

The value is a multi_sz, which is in the format:
{data}\0{data}\0\0
I don't know what the Unicode::UnicodeToAnsi does, but it's likely just looking for that first null terminator and stopping there. You have to parse past single nulls until you hit the double-null.
EDIT
You have to update your code - very likely your interfaces. Right now you're trying to returns a string for a multi_sz which, by definition, means multiple strings. you probably want to returns a string[] (though I'd probably opt to use a couple output parameters - one that's an array pointer and the other that is a element count).
You then need to loop through the data that came back from the RegQuery call, something maybe like this (off the top of my head, not tested or compiled):
TCHAR *p = buffer;
if(bufferSize > 0)
{
do
{
Unicode::UnicodeToAnsi(p, dataString);
// do something with dataString - store it in an array or whatever
p+= _tcslen(p);
} while((p-buffer) < bufferSize)
}

Related

safe convert uint8_t into wchar_t

This is my very first native extension between AIR and C++, and in C++ programming as well, so I am not sure where to look for help with type conversions.
From AIR side I receive a string in uint8_t (FRE... function call). I need to use this string for writing to registry, where wchar_t is expected.
I am not sure if I can simply make a type casting, or make new wchar[] array of the same size and copy characters or do I need to use someting like MultiByteToWideChar() to convert UTF-8 characters to wchar_t. Im not sure about the correct size of output array in this case.
...
FREObject retObj = NULL;
uint32_t strLength = 0;
const uint8_t *path8 = NULL;
// this is what I get from actionscript call
FREResult status = FREGetObjectAsUTF8(argv[ARG_PATH], &strLength, &path8);
if ((status != FRE_OK) || (strLength <= 0) || (path8 == NULL)) return retObj;
LONG hStatus;
HKEY hKey;
wchar_t *path;
// ??? how to copy uint_t into wchar_t
hStatus = RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_ALL_ACCESS, &hKey);
...
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cv;
std::wstring dst = cv.from_bytes(src);

MsiGetProductInfo() - "invalid parameter"

I want to get the install date of product:
DWORD max = 255;
WCHAR buffer[255];
std::wstring guidWString = S::WstrToStr(subKeys[i]); //from array of std::string
LPCWSTR guid = guidWString.c_str();
int err = MsiGetProductInfo(guid, INSTALLPROPERTY_INSTALLDATE, buffer, &max);
if(err == ERROR_SUCCESS){ //never success :(
info.date = S::WstrToStr(std::wstring(buffer));
}
But I always get the error code 87 (*ERROR_INVALID_PARAMETER*).
I don't see anything "invalid" here, according to the documentation:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa370130%28v=vs.85%29.aspx
I have checked that:
All variables are of good types, buffer size (DWORD max) is not null, equal to the size of my buffer.
I use a function to convert std::string (I have my GUID in std::string) to std::wstring (under debugger, all looks good, conversion works in many other places in code that use WinAPI and std::wstring).
I have tried with different GUID, all of them exists and works for asking register "manually". MsiGetProductInfo() returns that error ALWAYS.
I have also tried to just write GUID in code (L"{GUID-GO-EXACTLY-HERE}"), with the same result.
I just don't know where the problem is?

How can i tell the client to wait until it received all the data?

this is my first post. i am currently taking a networking class and i am required to write a client program that can download all emails from imap.gmail.com:993 to text files. i am required to write this program using winsock and openssl. I was able to connect to the server and fetch the emails. For emails with small data, i had no problem receiving it. But for emails with large data such as an images that is base64-decoded, i was able to download only a part of it.
so my question is How can i tell the client to wait until it received all the data from the server?
Here is what i have done so far:
void fetchMail(SSL *sslConnection,int lowerLimit, int UpperLimit)
{
SYSTEMTIME lt;
ofstream outfile;
GetLocalTime(&lt);
char szFile[MAX_PATH + 1];
char szPath[MAX_PATH+1];
char message[BUFSIZE];
char result[BUFSIZE];
::GetModuleFileName( NULL, szPath, MAX_PATH );
// Change file name to current full path
LPCTSTR psz = strchr( szPath, '\\');
if( psz != NULL )
{
szPath[psz-szPath] = '\0';
}
char szMailBox[MAX_PATH+1];
memset( szMailBox, 0, sizeof(szMailBox));
wsprintf( szMailBox, "%s\\inbox", szPath );
// Create a folder to store emails
::CreateDirectory( szMailBox, NULL );
for(int i = lowerLimit; i < UpperLimit; ++i)
{
// Create a folder to store emails
memset( szFile, 0, sizeof(szFile));
memset( result, 0, sizeof(result));
memset( message, 0, sizeof(message));
::sprintf(szFile,"%s\\%d%d%d%d%d%d.txt", szMailBox, lt.wHour, lt.wMinute,lt.wMinute,lt.wSecond, lt.wMilliseconds,i);
string Result;//string which will contain the result
stringstream convert; // stringstream used for the conversion
const char * num;
convert << i;//add the value of Number to the characters in the stream
Result = convert.str();//set Result to the content of the stream
num = Result.c_str();
strcpy(result, "tag FETCH ");
strcat(result, num);
strcat(result, " (BODY[TEXT])\r\n");
int n = 0;
cout << "\nFETCHING : \n";
SSL_write(sslConnection, result, strlen(result));
outfile.open(szFile );
SSL_read(sslConnection, message, sizeof(message)-1);
outfile <<message ;
outfile.close();
}
}
First of all some points on your code:
You use strcpy, strcat and all those unchecked, unsafe C functions. You might easily get buffer overflows and other kinds of errors. Consider to use C++ strings, vectors, arrays.
You do a lot of different things in that function, on different levels of abstraction. AFAICS only the two SSL_* function calls are really about fetching that mail. Consider to break out some functions to improve readability.
Now to your problem: Googling a bit about SSL_read, you will see that it returns an int, denoting how many bytes were actually read. You should use that return value - not only for this issue but also for error handling. If the mail data is longer than your buffer, the function will read until the buffer is filled and return its size. You should continue to call the function until all bytes have been read.

Trouble getting footage path after effects sdk

Having trouble with the after effects sdk.
Basically I'm looping through all of the footage project items and trying to get the footage path from them. Here's the code I have inside of the loop.
AEGP_ItemType itemType = NULL;
ERR(suites.ItemSuite6()->AEGP_GetNextProjItem(projH, itemH, &itemH));
if (itemH == NULL) {
break;
}
ERR(suites.ItemSuite6()->AEGP_GetItemType(itemH, &itemType));
if (itemType == AEGP_ItemType_FOOTAGE) {
numFootage++;
AEGP_FootageH footageH;
ERR(suites.FootageSuite5()->AEGP_GetMainFootageFromItem(itemH, &footageH));
A_char newItemName[AEGP_MAX_ITEM_NAME_SIZE] = {""};
wchar_t footagePath[AEGP_MAX_PATH_SIZE];
ERR(suites.ItemSuite6()->AEGP_GetItemName(itemH, newItemName));
AEGP_MemHandle pathH = NULL;
ERR(suites.FootageSuite5()->AEGP_GetFootagePath(footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &pathH));
ERR(suites.MemorySuite1()->AEGP_LockMemHandle(pathH, reinterpret_cast<void**>(&footagePath)));
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
const std::string utf8_string = converter.to_bytes(footagePath);
std::ofstream tempFile;
tempFile.open ("C:\\temp\\log1.txt");
tempFile << utf8_string;
tempFile.close();
ERR(suites.MemorySuite1()->AEGP_UnlockMemHandle(pathH));
ERR(suites.MemorySuite1()->AEGP_FreeMemHandle(pathH));
}
I'm getting the footagePath
I then convert the UTF-16 (wchar_t) pointer to a UTF-8 string
Then I write that UTF-8 string to a temp file and it always outputs the following.
펐㛻
Can I please have some guidance on this? Thanks!
I was able to figure out the answer.
http://forums.adobe.com/message/5112560#5112560
This is what was wrong.
It was because the executing code was in a loop and I wasn't allocating strings with the new operator.
This was the line that needed a new on it.
wchar_t footagePath[AEGP_MAX_PATH_SIZE];
Another piece of information that would have been useful to know is that not ALL footage items have paths.
If the don't have a path it will return empty string.
This is the code I ended up with.
if (itemType == AEGP_ItemType_FOOTAGE) {
A_char* newItemName = new A_char[AEGP_MAX_ITEM_NAME_SIZE];
ERR(suites.ItemSuite6()->AEGP_GetItemName(newItemH, newItemName));
AEGP_MemHandle nameH = NULL;
AEGP_FootageH footageH = NULL;
char* footagePathStr = new char[AEGP_MAX_PATH_SIZE];
ERR(suites.FootageSuite5()->AEGP_GetMainFootageFromItem(newItemH, &footageH));
if (footageH) {
suites.FootageSuite5()->AEGP_ GetFootagePath(footageH, 0, AEGP_FOOTAGE_MAIN_FILE_INDEX, &nameH);
if(nameH) {
tries++;
AEGP_MemSize size = 0;
A_UTF16Char *nameP = NULL;
suites.MemorySuite1()->AEGP_GetMemHandleSize(nameH, &size);
suites.MemorySuite1()->AEGP_LockMemHandle(nameH, (void **)&nameP);
std::wstring test = L"HELLO";
std::string output;
int len = WideCharToMultiByte(CP_OEMCP, 0, (LPCWSTR)nameP, -1, NULL, 0, NULL, NULL);
if (len > 1) {
footagePathStr = new char[len];
int len2 = WideCharToMultiByte(CP_OEMCP, 0, (LPCWSTR)nameP, -1, footagePathStr, len, NULL, NULL);
ERR(suites.MemorySuite1()->AEGP_UnlockMemHandle(nameH));
suites.MemorySuite1()->AEGP_FreeMemHandle(nameH);
}
}
}
}
You've already had the data as smarter std::wstring, why did you convert it to byte array and then force it as simple std::string? In general, you should avoid converting strings via byte arrays. My knowledge on C++ STDLIB is a few years off now, but the problem may be in that the std::string class may simply still not have any UTF8 support.
Do you really need to store it as utf8? If it is just for logging, try using ofwstream (the wide one), remove the conversion and the 'string' completely, and just write the 'wstring' directly to the stream instead.
Also, it is completely possible that everything went correctly, and it is just your FILE VIEWER that goes rabid. Examine your log file with hexeditor and check if the beginning of the file contains the Unicode format markers like 0xFFFE etc:
if it has some, and you wrote data in not-identical encoding as the markers indicate, then that's the problem
if it has none, then try adding correct markers. Maybe your file-viewer simply did not notice it is unicode-of-that-type and misread the file. Unicode markers help the readers to decode data properly.

C++ Read a Registry String Value in char* [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to compare strings
I want to Compare to registry string values and if they were the same an messagebox appears
Currently I'm using this functions , It returns the value correctly but whenever I want to compare them, The compare result is always wrong
char* GetRegistry(char* StringName)
{
DWORD dwType = REG_SZ;
HKEY hKey = 0;
char value[1024];
DWORD value_length = 1024;
const char* subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI\\Player";
RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey);
RegQueryValueEx(hKey, StringName, NULL, &dwType, (LPBYTE)&value, &value_length);
return value;
}
I use this to compare them
if (GetRegistry("First") == GetRegistry("Second"))
{
MessageBox(NULL,":|",":|",1);
}
But the MessageBox appears how ever The values are different
Any help is appreciated.
By using std::string, comparison would behave as you expected. Also that would fix another bug that the function returns a pointer to a local buffer.
std::string GetRegistry(const char* StringName)
{
....
return std::string(value);
}
GetRegistry() returns a char*, so you are actually comparing pointers with operator==.
You should use strcmp() to do raw C-like char* string comparisons, or better use a robust C++ string class, like CString or std::[w]string.
Here is a possible rewrite of your function using ATL's CString:
#include <atlbase.h>
#include <atlstr.h>
CString GetRegistry(LPCTSTR pszValueName)
{
// Try open registry key
HKEY hKey = NULL;
LPCTSTR pszSubkey = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI Extensions");
if ( RegOpenKey(HKEY_LOCAL_MACHINE, pszSubkey, &hKey) != ERROR_SUCCESS )
{
// Error:
// throw an exception or something...
//
// (In production code a custom C++ exception
// derived from std::runtime_error could be used)
AtlThrowLastWin32();
}
// Buffer to store string read from registry
TCHAR szValue[1024];
DWORD cbValueLength = sizeof(szValue);
// Query string value
if ( RegQueryValueEx(
hKey,
pszValueName,
NULL,
NULL,
reinterpret_cast<LPBYTE>(&szValue),
&cbValueLength)
!= ERROR_SUCCESS )
{
// Error
// throw an exception or something...
AtlThrowLastWin32();
}
// Create a CString from the value buffer
return CString(szValue);
}
And then you can call it like this:
if ( GetRegistry(_T("First")) == GetRegistry(_T("Second")) )
...
Note that this code will compile in both ANSI/MBCS and Unicode builds (it's based on Win32 TCHAR model).
You have a couple of problems with this source code.
First of all you have a function with a local variable, a variable on the stack, which is returning the address of that variable yet when the function returns, the variable disappears and the address is no longer valid.
The next problem is that you are not comparing the character strings. You are instead comparing the address returned by the function and if you get lucky, the address could be the same. Since you are calling the function twice in succession, you are getting lucky so the address is the same.
I suggest you do the following: (1) create two local character strings in your function which is calling the function GetRegistry() and (2) modify the GetRegistry() function so that it uses those buffers rather than its own. So the code would look something like:
char registryEntryOne[1024];
char registryEntryTwo[1024];
DWORD dwRegistryEntryOneLen;
DWORD dwRegistryEntryTwoLen;
registryEntryOne[0] = 0; // init the registry entry to zero length string
registryEntryTwo[0] = 0;
dwRegistryEntryOneLen = sizeof(registryEntryOne);
GetRegistry ("First", registryEntryOne, &dwRegistryEntryOneLen);
dwRegistryEntryTwoLen = sizeof(registryEntryTwo);
GetRegistry ("Second", registryEntryTwo, &dwRegistryEntryTwoLen);
// two strings are equal if:
// the lengths are the same
// at least one of the lengths is non-zero
// the bytes are the same in the same order
if (dwRegistryEntryOneLen && dwRegistryEntryOneLen == dwRegistryEntryTwoLen && memcmp (registryEntryOne, registryEntryTwo, dwRegistryEntryOneLen) == 0) {
// strings are equal
} else {
// strings are not equal
}
The GetRegistry() function would look something like:
char* GetRegistry(char* StringName, char *valueBuffer, DWORD *value_length)
{
DWORD dwType = REG_SZ;
HKEY hKey = 0;
const char* subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\MCI\\Player";
RegOpenKey(HKEY_LOCAL_MACHINE,subkey,&hKey);
RegQueryValueEx(hKey, StringName, NULL, &dwType, (LPBYTE)valueBuffer, value_length);
return valueBuffer;
}