views:

341

answers:

2

Hi!

I created a .dll which should work like the RunAs command. The only difference is, that it should read from registry. My problem is, that i need to reed 3 values from the registry, but i can't. It reads the first, than it fails at the second one (Password) with error code 2, which means "The system cannot find the file specified". If i query only for domain and username then it is ok, if i query only for password then it it still succeeds, but if i want to query all three then it fails. Can someone tell me, what i am doing wrong?

Heres my code:

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  A: 

Though it doesn't directly relate to the problem you're asking about, I think the first step toward diagnosing the problem is to get rid of some of the duplication in your code. Right now, it's almost impossible to be sure that all the queries even work the same way. A good example of why it would probably be better if programming editors didn't have cut or (particularly) paste commands at all. I think I'd start with code more like this:

#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

I've tried this with a number of different paths/items in my registry, and haven't been able to duplicate the problem you ask about. I'm not sure whether that means the code works better or not though -- I don't have the same registry entries you're looking at since I don't have that particular software installed.

Jerry Coffin
@Jerry: Thank you very much for your help. I tried your code too, and it works perfectly, but in this case it was easier to put two line in my code, than rewrite the whole. Unfortunately, i can accept only one solution so this time it goes for rich, but thank you again :)
kampi
+1  A: 

I think I can see why. You need to initialize dwBufSize each time before you call RegQueryValueEx. This function returns the number bytes copied to buf.

You will find the function returns ERROR_MORE_DATA. You've made the mistake of using GetLastError(). Don't do that. The Reg functions return an error code directly.

richb
Hi! Thank you very much. This was my problem. I needed just to initialize dwBufSize before every query. Thank you very much
kampi