2010-03-21 74 views
1

我創建了一個應該像RunAs命令一樣工作的.dll文件。唯一的區別是,它應該從註冊表中讀取。我的問題是,我需要從註冊表中取回3個值,但我不能。它讀取第一個,比第二個(密碼)失敗,錯誤代碼爲2,表示「系統找不到指定的文件」。如果我只查詢域和用戶名,那麼它是好的,如果我只查詢密碼然後它仍然成功,但如果我想查詢所有三個,那麼它失敗。有人可以告訴我,我做錯了什麼?如何正確讀取c中多個值的註冊表?

繼承人我的代碼:

HKEY hKey = 0; 
DWORD dwType = REG_SZ;  
DWORD dwBufSize = sizeof(buf); 
TCHAR szMsg [MAX_PATH + 32]; 
HANDLE handle; 
LPVOID lpMsgBuf; 

if(RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Kampi Corporation\\RunAs!"), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)  
{ 
    if(RegQueryValueEx(hKey, TEXT("Username"), 0, &dwType, (LPBYTE)buf, &dwBufSize) == ERROR_SUCCESS)   
    { 
     memset(szMsg, 0, sizeof(szMsg)); 
     wsprintf (szMsg, _T("%s"), buf); 
     mbstowcs(wuser, szMsg, 255); 
     RegCloseKey(hKey); 
    }   
    else 
    { 
     MessageBox (pCmdInfo->hwnd, "Can not query for Username key value!", _T("RunAs!"), MB_ICONERROR); 
     RegCloseKey(hKey); 
     return -1; 
    } 
} 
else 
{ 
    CSimpleShlExt::showerror(GetLastError(), pCmdInfo->hwnd, "RegOpenKeyEx failed for Username with error code :: "); 
    return -1; 
} 

if(RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Kampi Corporation\\RunAs!"), 0, KEY_QUERY_VALUE ,&hKey) == ERROR_SUCCESS)  
{ 
    if(RegQueryValueEx(hKey, TEXT("Password"), 0, &dwType, (LPBYTE)buf, &dwBufSize) == ERROR_SUCCESS)   
    { 
     memset(szMsg, 0, sizeof(szMsg)); 
     wsprintf (szMsg, _T("%s"), buf); 
     mbstowcs(wpass, szMsg, 255); 
     RegCloseKey(hKey); 
    }   
    else 
    { 
     char test[200]; 
     sprintf(test,"Can not query for Password key value! EC: %d",GetLastError()); 
     MessageBox (pCmdInfo->hwnd, test, _T("RunAs!"), MB_ICONERROR); 
     RegCloseKey(hKey); 
     return -1; 
    } 
} 
else 
{ 
    CSimpleShlExt::showerror(GetLastError(), pCmdInfo->hwnd, "RegOpenKeyEx failed for Password with error code :: "); 
    return -1; 
} 

if(RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Kampi Corporation\\RunAs!"), 0, KEY_QUERY_VALUE ,&hKey) == ERROR_SUCCESS)  
{ 
    if(RegQueryValueEx(hKey, TEXT("Domain"), 0, &dwType, (LPBYTE)buf, &dwBufSize) == ERROR_SUCCESS)   
    { 
     memset(szMsg, 0, sizeof(szMsg)); 
     wsprintf (szMsg, _T("%s"), buf); 
     mbstowcs(wdomain, szMsg, 255); 
     RegCloseKey(hKey); 
    }   
    else 
    { 
     sprintf(test,"Can not query for Password key value! EC: %d",GetLastError()); 
     MessageBox (pCmdInfo->hwnd, test, _T("RunAs!"), MB_ICONERROR); 
     RegCloseKey(hKey); 
     return -1; 
    } 
} 
else 
{ 
    CSimpleShlExt::showerror(GetLastError(), pCmdInfo->hwnd, "RegOpenKeyEx failed for Domain with error code :: "); 
    return -1; 
} 

回答

1

我想我明白了爲什麼。每次調用RegQueryValueEx之前,都需要初始化dwBufSize。該函數返回複製到buf的字節數。

你會發現函數返回ERROR_MORE_DATA。你犯了使用GetLastError()的錯誤。不要這樣做。 Reg函數直接返回錯誤代碼。

+0

嗨!非常感謝你。這是我的問題。我需要在每個查詢之前初始化dwBufSize。非常感謝你 – kampi 2010-03-22 04:07:06

4

雖然它並不直接涉及到你問這個問題,我覺得對診斷問題的第一步是在擺脫了一些重複的你的代碼。現在,幾乎不可能確定所有查詢甚至以相同的方式工作。一個很好的例子,說明爲什麼編程編輯沒有削減或(尤其是)粘貼命令可能會更好。我想我會用代碼開始更是這樣的:

#include <windows.h> 
#include <string> 
#include <sstream> 
#include <iostream> 
#include <exception> 
#include <iterator> 

namespace { 
void check(DWORD value, char const *op) { 
    if (value != ERROR_SUCCESS) { 
     std::ostringstream buf; 
     buf << op << " failed error code = " << value; 
     throw std::logic_error(buf.str().c_str()); 
    } 
} 

class reg_key { 
    HKEY key; 
public: 
    reg_key(wchar_t const *path, HKEY topkey = HKEY_CURRENT_USER, DWORD q=KEY_QUERY_VALUE) { 
     check(RegOpenKeyExW(topkey, path, 0, q, &key), "RegOpenKeyExW"); 
    } 
    operator HKEY() { return key; } 
    ~reg_key() { RegCloseKey(key); } 
}; 
} 

template <class outIt> 
void read_reg(wchar_t const *path, wchar_t const *name, outIt out) { 
    static const int buf_size = 256; 
    wchar_t buffer[buf_size]; 
    DWORD size = buf_size, type = REG_SZ; 
    reg_key key(path); 

    check(RegQueryValueExW(key, name, 0, &type, (LPBYTE)buffer, &size), "RegQueryValueExW"); 
    std::copy(buffer, buffer+wcslen(buffer), out); 
} 

#ifdef TEST 
int main() { 
    std::wstring code_page, font; 

    try { 
     read_reg(L"Software\\Microsoft\\CharMap", L"CodePage", std::back_inserter(code_page)); 
     read_reg(L"Software\\Microsoft\\CharMap", L"Font", std::back_inserter(font)); 
     std::wcout << "Code Page: " << code_page << "\n"; 
     std::wcout << "Font: " << font << std::endl; 
    } 
    catch (std::exception &e) { 
     MessageBox(NULL, e.what(), "Reading Registry failed", MB_ICONERROR); 
    } 
    return 0; 
} 
#endif 

我已經與一些在我的註冊表不同的路徑/項目嘗試這樣做,並沒有能夠複製你問這個問題。我不確定這是否意味着代碼可以更好地工作 - 但我沒有相同的註冊表項,因爲我沒有安裝特定的軟件。

+0

@Jerry:非常感謝您的幫助。我也嘗試了你的代碼,並且它完美地工作,但在這種情況下,在代碼中放置兩行比重寫整個代碼更容易。不幸的是,我只能接受一種解決方案,所以這一次它變得豐富,但再次感謝你:) – kampi 2010-03-22 04:10:15