преобразовать std :: string в const BYTE * для RegSetValueEx () - PullRequest
4 голосов
/ 11 мая 2009

У меня есть функция, которая получает std :: string. Эта функция вызывает

RegSetValueEx

5-й параметр является значением значения реестра и ожидает переменную типа const BYTE *. Поэтому мне нужно преобразовать std :: string в const BYTE *, а также указать длину результирующего массива в качестве шестого параметра.

Я нашел способ сделать это, но это ужасно, и я не совсем понимаю, что происходит. Вот уменьшенная версия этой функции:

void function(const std::string& newValue)
{
    HKEY keyHandle;
    if(RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("some key"),0,KEY_ALL_ACCESS,&keyHandle) == ERROR_SUCCESS)
    {
        std::wstring wNewValue;
        wNewValue.assign(newValue.begin(),newValue.end());

        if (RegSetValueEx(keyHandle, TEXT("some value"), NULL, REG_SZ, (const BYTE*)(LPCTSTR)(wNewValue.c_str()), wNewValue.size()*2)==ERROR_SUCCESS)
        {
            //do something
        }
        RegCloseKey(keyHandle);
    }
}

Как вы можете видеть, я сначала создаю широкую строку (определен UNICODE), затем использую двойное приведение, и для длины я должен сделать * 2, иначе он установит только половину входной строки.

Является ли эта форма приведения нормальным / лучшим способом сделать это?

Почему * 2, что может быть лучше?

Ответы [ 4 ]

10 голосов
/ 11 мая 2009
void function(const std::string& newValue)
{
    HKEY keyHandle;
    if(RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("some key"),0,KEY_ALL_ACCESS,&keyHandle) == ERROR_SUCCESS)
    {

        if (RegSetValueExA(keyHandle, "some value", NULL, REG_SZ, (const BYTE*)newValue.c_str(), newValue.size() + 1)==ERROR_SUCCESS)
        {
                //do something
        }
        RegCloseKey(keyHandle);
    }
}

Я удалил часть, где вы конвертируете вашу строку в строку wstring, вместо этого вы будете явно использовать ANSI-версию RegSetValueEx.

цитата из замечаний RegSetValueEx в MSDN:

Если dwType - это REG_SZ, REG_MULTI_SZ, или REG_EXPAND_SZ типа и ANSI версия этой функции используется (либо путем явного вызова RegSetValueExA или не определяя UNICODE перед включением Windows.h файл), данные, на которые указывает Параметр lpData должен быть ANSI строка символов. Строка конвертируется в Unicode до того, как хранится в реестре.

Также обратите внимание, что параметр cbData должен также включать размер нулевого завершения.

3 голосов
/ 11 мая 2009

* 2 объясняется тем, что RegSetValueEx хочет знать количество записываемых байтов и каждый символ (wchar_t) в строке wstring шириной два байта Таким образом, полученный байтовый массив имеет двойной размер!

1 голос
/ 23 сентября 2011

Вы также можете скопировать строку Unicode в байтовый массив:

LPWSTR pData = L"SampleGrabber";
int dwSize = wcslen(pData)*sizeof(TCHAR);
BYTE slump[256];
memset((void*) slump, 0, 256*sizeof(BYTE));
memcpy((void*) slump, (const void *) pData, dwSize*sizeof(BYTE));

globit = RegSetValueEx(hKey, NULL, 0, REG_SZ, (const BYTE*) slump, dwSize);

Если вам не повезло писать код для устройства WINCE 5.0, и в нем не было части API-интерфейса regedit.

1 голос
/ 20 января 2011

Разве это не должно быть wNewValue.size()*2+2? +2 для нулевого символа? MSDN говорит: Размер информации, на которую указывает параметр lpData, в байтах. Если данные имеют тип REG_SZ, REG_EXPAND_SZ или REG_MULTI_SZ, cbData должен включать размер завершающего нулевого символа или символов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...