2017-09-28 15 views
-1

기본적으로 저는 프로그램 업데이트 관리자의 역할을하는 서비스를 가지고 있습니다. 이것은 사용자가 필요로하지 않는 자동 업데이트 프로그램을 만들어 내 노력에 모두 서명하는 것입니다 다른 Windows 서비스에서 생성 한 레지스트리 값을 읽거나 변경하려면 어떻게합니까?

그래서 설치 내 업데이트 관리자는 다음 코드를 사용하여 몇 가지 초기 레지스트리 값/구조를 만듭니다.

LPCWSTR strInITKeyName = L"SOFTWARE\\InIT\\"; 
DWORD rtime = 0; 
HKEY InITKey; 
LONG nInITError; 
nInITError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0, 0, &InITKey); 
if (ERROR_NO_MATCH == nInITError || ERROR_FILE_NOT_FOUND == nInITError) 
{ 
    std::cout << "Registry key not found. Setting up..." << std::endl; 
    long nError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &InITKey, NULL); 
    if (ERROR_SUCCESS != nError) 
     std::cout << "Error: Could not create registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nError << std::endl; 
    else 
    { 
     std::cout << "Successfully created registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl; 

     // See https://www.experts-exchange.com/questions/10171094/Using-RegSetKeySecurity.html for example 
     //SECURITY_DESCRIPTOR sd; 
     //PACL pDacl = NULL; 

     //RegSetKeySecurity(InITKey); 
    } 
} 
else if (nInITError == ERROR_ACCESS_DENIED) 
{ 
    long nError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0L, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &InITKey, NULL); 
    if (ERROR_SUCCESS != nError) 
     std::cout << "Error: Could not create registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nError << std::endl; 
    else 
     std::cout << "Successfully created registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl; 
} 
else if (ERROR_SUCCESS != nInITError) 
{ 
    std::cout << "Cannot open registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nInITError << std::endl; 
    rtime = 0; 
} 

// Generate guid 
// 
GUID guid; 
HRESULT hr = CoCreateGuid(&guid); 

// Convert the GUID to a string 
OLECHAR* guidString; 
StringFromCLSID(guid, &guidString); 

// Setup registry values 
// Sets clientguid value and ties to strInITKeyName 
std::wstring clientguid = guidString; // InITKey 
clientguid = clientguid.substr(1, 36); 

LONG nClientGUIDError = RegSetValueEx(InITKey, L"clientguid", NULL, REG_SZ, (const BYTE*)clientguid.c_str(), (clientguid.size() + 1) * sizeof(wchar_t)); 
if (nClientGUIDError) 
    std::cout << "Error: " << nClientGUIDError << " Could not set registry value: " << "clientguid" << std::endl; 
else 
    std::wcout << "Successfully set InIT clientguid to " << clientguid << std::endl; 

// ensure memory is freed 
::CoTaskMemFree(guidString); 
RegCloseKey(InITKey); 

제거되면 레지스트리 값이 삭제됩니다. 내 실제 프로그램은 해당 레지스트리 값 중 일부에 액세스해야하는 설치된 컴퓨터에서 실행되는 Windows 서비스입니다.

이전에는이 ​​업데이트 관리자가 없었으며 대신 실제 프로그램 서비스의 레지스트리 값을 설정했습니다. 읽기와 쓰기가 잘되었습니다. 그러나 업데이트 관리자가 이러한 초기 값을 설정하고 내 메인 윈도우 서비스에 액세스하려고합니다.

이렇게하려고 할 때마다 KEY_READ와 같은 모든 종류의 보안 토큰을 시도해도 ERROR_ACCESS_DENIED 오류가 발생했습니다. KEY_WOW64_64KEY 및 기타 여러 가지 조합으로 키를 열려고 시도 할 때 위에서 보았 듯이 토큰을 설정할 때 KEY_ALL_ACCESS를 실행하려고합니다. 나는 내가 잘 액세스 할 수 있어야한다고 생각하지만, 그것은 나를 허용하지 않습니다. 내가 올 수있는 유일한 결론은 어떻게 든 내 업데이트 관리자는 레지스트리의 키/값에 대한 소유권을가집니다.

기본 Windows 서비스에서이 레지스트리 파일에 액세스하려면 어떤 코드가 필요합니까?

(I가 업데이트 관리자 의 설치 코드 위의 볼에 생성 clientguid) 그 레지스트리 값을 액세스하기위한 내 현재 코드 :

// Log a service start message to the Application log. 
WriteEventLogEntry(L"InITService Starting in OnStart", EVENTLOG_INFORMATION_TYPE); 
this->m_ServiceLogger->info("Initialized logger bruh"); 

// Query clientguid from registry 
HKEY InITKey; 
std::wstring valuename; 

ULONG nError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\InIT\\", 0, KEY_READ || KEY_WOW64_64KEY, &InITKey); 

DWORD dwBufferSize = TOTALBYTES; 
DWORD cbData; 

WCHAR *wcBuffer = (WCHAR*)malloc(dwBufferSize); 
cbData = dwBufferSize; 
if (nError == ERROR_SUCCESS) 
    this->m_ServiceLogger->info("Getting reg"); 

if (nError == ERROR_SUCCESS) 
{ 
    std::wstring clientguid; 
    clientguid = L""; 
    valuename = L"clientguid"; 

    nError = RegQueryValueExW(HKEY_LOCAL_MACHINE, valuename.c_str(), 0, NULL, (LPBYTE) wcBuffer, &cbData); 

    while (nError == ERROR_MORE_DATA)  // Get a buffer that is big enough if not already 
    { 
     this->m_ServiceLogger->info("Increasing clientguid buffer size"); 
     dwBufferSize += BYTEINCREMENT; 
     wcBuffer = (WCHAR*) realloc(wcBuffer, dwBufferSize); 
     cbData = dwBufferSize; 

     nError = RegQueryValueExW(HKEY_LOCAL_MACHINE, valuename.c_str(), 0, NULL, (LPBYTE)wcBuffer, &cbData); 
    } 
    if (ERROR_SUCCESS == nError) 
    { 
     clientguid = wcBuffer; 
     std::string cg(clientguid.begin(), clientguid.end()); 
     this->m_ClientGuid = cg; 
     this->m_ServiceLogger->info("Clientguid yo: " + cg); 
    } 
    else if (nError = ERROR_ACCESS_DENIED) 
     this->m_ServiceLogger->info("ClientGUID: Access Denied"); 
    if (!this->checkRegistryValues()) 
    { 
     this->generateRegistry(); 
    } 
} 
else 
{ 
    std::stringstream errstr; 
    errstr << nError; 
    this->m_ServiceLogger->info("Error: " + errstr.str() + " RegOpenKeyEx failed"); 
} 

this->setSchedulingUtility(); // Hardcoded to set scheduled update at 1:00 AM 

WriteEventLogEntry(L"InITService Initialized Schedule in OnStart", EVENTLOG_INFORMATION_TYPE); 
this->m_ServiceLogger->info("Initialized ClientGUID: " + this->m_ClientGuid); 
this->m_ServiceLogger->info("Initialized CurrentVersion: " + this->m_CurrentVersion); 
this->m_ServiceLogger->info("Initialized WebServerURL: " + this->m_POSTAddress); 
this->m_ServiceLogger->flush(); 

RegCloseKey(InITKey); 

// Queue the main service function for execution in a worker thread. 
CThreadPool::QueueUserWorkItem(&CSampleService::ServiceWorkerThread, this); 

답변

1

RegOpenKeyEx()를 호출, 당신은 비트 OR을 (사용할 필요를 LOGICAL OR (||) 연산자 대신 |) 연산자를 사용하십시오. 변경 :

KEY_READ || KEY_WOW64_64KEY 

하려면 다음 업데이트 관리자가 RegOpenKeyEx()를 호출 할 때

KEY_READ | KEY_WOW64_64KEY 

그러나, 그것은 설정해야이 0으로 samDesired 매개 변수를 설정하는 것입니다, 모두에서 모든 액세스 권한을 지정하지 않는 최소한 KEY_SET_VALUE 이상이어야합니다. RegOpenKeyEx()이 실패하면 RegCreateKeyEx()을 호출하면 samDesiredKEY_ALL_ACCESS으로 설정됩니다. 그러지 마. 실제로 필요한 액세스 권한 만 사용하십시오 (KEY_SET_VALUE 등).

어쨌든 RegOpenKeyEx()RegCreateKeyEx()을 모두 호출 할 필요가 없습니다. 그저 혼자서 RegCreateKeyEx()으로 전화하십시오. 기존 키를 열고 존재하지 않는 키를 만듭니다. 그것의 dwDisposition 출력 매개 변수는 어떤 일이 일어 났는지 알려줍니다.

이 코드에는 다른 오류가 있습니다. HKEYRegQueryValueEx()에 잘못 입력하고 ERROR_ACCESS_DENIED 오류 코드가 올바르게 표시되지 않는지 확인하십시오 (== 비교 연산자 대신 = 지정 연산자 사용). 그리고 메모리 누출.

업데이트 관리자 :

대신 이와 비슷한 더 많은 것을 시도

LPCWSTR strInITKeyName = L"SOFTWARE\\InIT\\"; 
HKEY InITKey; 
DWORD dwDisposition; 

LONG nError = RegCreateKeyEx(HKEY_LOCAL_MACHINE, strInITKeyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE | KEY_WOW64_64KEY, NULL, &InITKey, &dwDisposition); 

if (ERROR_SUCCESS != nError) 
{ 
    std::cout << "Error: Could not open/create registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl << "\tERROR: " << nError << std::endl; 
} 
else 
{ 
    std::cout << "Successfully " << ((REG_CREATED_NEW_KEY == dwDisposition) ? "created" : "opened") << " registry key HKEY_LOCAL_MACHINE\\" << strInITKeyName << std::endl; 

    // Generate guid and convert to a string 
    // 
    std::wstring clientguid; 
    GUID guid; 

    HRESULT hr = CoCreateGuid(&guid); 
    if (FAILED(hr)) 
    { 
     std::cout << "Error: Could not generate clientguid" << std::endl << "\tERROR: " << (int)hr << std::endl; 
    } 
    else 
    { 
     WCHAR guidString[40] = {0}; 
     int len = StringFromGUID2(guid, guidString, 40); 
     if (len > 2) 
     { 
      // Sets clientguid value and ties to strInITKeyName 
      clientguid.assign(&guidString[1], len-2); 
     } 
    } 

    // Setup registry values 

    nError = RegSetValueEx(InITKey, L"clientguid", NULL, REG_SZ, (const BYTE*) clientguid.c_str(), (clientguid.size() + 1) * sizeof(wchar_t)); 
    if (ERROR_SUCCESS != nError) 
     std::cout << "Error: Could not set registry value: clientguid" << std::endl << "\tERROR: " << nError << std::endl; 
    else 
     std::wcout << "Successfully set InIT clientguid to " << clientguid << std::endl; 

    RegCloseKey(InITKey); 
} 

프로그램 서비스 :

... 

// Query clientguid from registry 
HKEY InITKey; 

LONG nError = RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\InIT\\", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &InITKey); 

if (ERROR_SUCCESS != nError) 
{ 
    std::stringstream errstr; 
    errstr << nError; 
    this->m_ServiceLogger->info("Error: " + errstr.str() + " RegOpenKeyEx failed"); 
} 
else 
{ 
    this->m_ServiceLogger->info("Getting reg"); 

    std::vector<BYTE> buffer(TOTALBYTES + sizeof(wchar_t), 0); // extra room for a null terminator, in case it is missing in the Registry data 
    DWORD cbData = TOTALBYTES; 

    do 
    { 
     nError = RegQueryValueExW(InITKey, L"clientguid", 0, NULL, &buffer[0], &cbData); 

     if (ERROR_MORE_DATA != nError) 
      break; 

     // Get a buffer that is big enough if not already 
     this->m_ServiceLogger->info("Resizing clientguid buffer"); 

     buffer.resize(cbData + sizeof(wchar_t)); 
    } 
    while (true); 

    if (ERROR_SUCCESS == nError) 
    { 
     std::wstring clientguid = (WCHAR*) &buffer[0]; 
     std::string cg(clientguid.begin(), clientguid.end()); 

     this->m_ClientGuid = cg; 
     this->m_ServiceLogger->info("Clientguid yo: " + cg); 
    } 
    else if (ERROR_ACCESS_DENIED == nError) 
    { 
     this->m_ServiceLogger->info("ClientGUID: Access Denied"); 
    } 
    else 
    { 
     std::stringstream errstr; 
     errstr << nError; 
     this->m_ServiceLogger->info("Error: " + errstr.str() + " RegQueryValueEx failed"); 
    } 

    RegCloseKey(InITKey); 

    if (!this->checkRegistryValues()) 
    { 
     this->generateRegistry(); 
    } 
} 

...