2013-05-08 3 views
0

사내에서 개발 한 다른 응용 프로그램에서 작성한 레지스트리 키 값에 크게 의존하는 Installshield 2012를 사용하여 만든 설치 프로그램이 있습니다. RegDBGetKeyValueEx Installscript API를 사용하여 값을 가져옵니다.레지스트리에서 값을 가져온 유효하지 않은/외래 문자

이 값은 백 슬래시가있는 디렉터리 경로입니다. 이 값은 설치 관리자의 TARGETDIR 역할을합니다.

문제는 내가 종종 외국 문자 (중국어, 일본어 또는 한국어)가 백 슬래시에 추가 된 것을 볼 수 있다는 것입니다. 이로 인해 내 TARGETDIR에 외래 문자가 포함됩니다. 이것은 설치를 오염시킵니다.

레지스트리 값을 잘못 번역 한 Installscript API의 버그라고 생각합니다.

문제의 근본 원인을 찾을 수 있도록 일부 입력 사항을 제공해주십시오.

편집 1 :

문제의 다른 응용 프로그램이 유니 코드를 지원하지 않습니다와 순수 ANSI 응용 프로그램입니다. 아무 데나 #define UNICODE가 지정되어 있지 않습니다. 또한 컴파일러 매개 변수를 확인하고 유니 코드와 관련이 없다는 것을 발견했습니다.

이 응용 프로그램은 하나의 레지스트리 키를 읽고 백 슬래시를 추가하고 다른 키를 업데이트합니다. 이 작업이 완료되면 내 설치 관리자는 다음 값을 가져옵니다.

if ((RegOpenKeyEx(HKEY_LOCAL_MACHINE, csVersKey, 0, KEY_READ|KEY_WRITE, &hKey) == ERROR_SUCCESS) && 
     (RegQueryValueEx(hKey, "BasePath", NULL, NULL, (unsigned char *)szTemp, &BufferSize) == ERROR_SUCCESS)) 
    { 
     m_reqPath = szTemp; 
     if (m_regPath.Right(1) != "\\") m_reqPath += "\\"; 
     m_reqMachinePath = m_reqPath + "\\" + m_reqMachine + "\\"; 
     m_reqHardwarePath = m_reqMachinePath + HARDWARE_DIRECTORY; 
     m_reqManualPath = m_reqMachinePath + MANUAL_DIRECTORY; 
     m_reqVersionPath = m_reqMachinePath + m_reqVersion + "\\"; 
     m_reqFirmwarePath = m_reqVersionPath + FIRMWARE_DIRECTORY; 
     m_RegVersDirectory = m_reqVersionPath + PROGRAM_DIRECTORY; 
     RegCloseKey(hKey); 
    } 

위의 코드에서 업데이트 된 값은 레지스트리에 기록됩니다. 이 값을 가져옵니다 의 InstallScript 코드는 다음과 같습니다

if ((RegDBKeyExist(szBaseKey^szRegKey) = 1) && (RegDBGetKeyValueEx(szBaseKey^szRegKey, "ReqPath", nTemp, szTemp, nvSize) = 0)) then 

편집 2 :

RegSetValueEx(hKey, LEICA_PATH, 0, REG_SZ, (const unsigned char*)m_reqLeicaPath.GetBuffer(m_reqLeicaPath.GetLength()), m_reqLeicaPath.GetLength()); 

내가 올바른 코드를 느낄 : 레지스트리 값이 설정되어

방법이 잘못된 것 같다 다음과 같아야합니다 :

RegSetValueEx(hKey, LEICA_PATH, 0, REG_SZ, (const unsigned char*)m_reqLeicaPath.GetBuffer(m_reqLeicaPath.GetLength()), m_reqLeicaPath.GetLength() + 1); 
+0

가 있습니까 당신은 확실히 집안의 다른 응용 프로그램에 의해 작성된 레지스트리 키의 가치가 올바른지? 한 번 내가 문자열 길이를 지정하여 문자열을 쓴 때 RegSetValueEx 함수에 문제가 있었는지 기억하고 cbData 매개 변수에 대한 문자열 길이 + 1 아닙니다. –

+0

레지스트리를 보면 외래 문자가 보이십니까? 그렇지 않다면 코드에서 잘못된 값을 읽고 해석 할 가능성이 있습니다. 실제 독서 코드를 보여줄 수 있습니까? –

+0

실제로 키에 아무 것도 쓰지 않을 때'KEY_WRITE' 액세스를 요청하는 이유는 무엇입니까? 'KEY_READ' 만 사용하거나'KEY_QUERY_VALUE' 만 사용하십시오. 요구하는 권한이 적을수록 엄격한 보안 환경에서 키를 열 가능성이 높아집니다. 또한'RegOpenKeyEx()'가 성공했지만'RegQueryValueEx()'가 실패하면 키 핸들이 누출됩니다. –

답변

1

레지스트리 데이터를 m_reqPath 변수에 할당 할 때이를 널로 끝나는 문자 데이터로 취급합니다. 그러나 RegQueryValueEx()으로 읽은 문자열 데이터는 이 아니며 데이터의 원래 작성자에 포함되지 않은 경우 null 종료가 보장 된이 아닙니다. 이것은 documentation에 분명히 명시되어 있습니다.

레지스트리에서 읽는 문자열 데이터가 이 아니고이 아닌 경우 버퍼의 끝에서 무작위 데이터를 복사하게 될 가능성이 있습니다. 그 가능성을 설명하기 위해 버퍼에 여분의 공간을 할당하고 실제로 읽은 데이터의 끝 부분에 자체 Null 터미네이터를 넣어야합니다. 데이터가 올바르게 null로 종료되면 터미네이터가 중복됩니다.

RegOpenKeyEx()이 성공했지만 RegQueryValueEx()이 실패하면 열린 레지스트리 키 핸들이 누출됩니다.

대신을 시도해보십시오

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, csVersKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) 
{ 
    char szTemp[257]; 
    DWORD BufferSize = 256; 

    if (RegQueryValueEx(hKey, "BasePath", NULL, NULL, (BYTE*)szTemp, &BufferSize) == ERROR_SUCCESS) 
    { 
     szTemp[BufferSize] = '\0'; 
     m_reqPath = szTemp; 
     ... 
    } 

    RegCloseKey(hKey); 
} 

가 모두이 문제를 방지하려면 대신 RegGetValue()를 사용, 당신을위한 null 종결 취급하는 :

char szTemp[257]; 
DWORD BufferSize = sizeof(szTemp); 

if (RegGetValue(HKEY_LOCAL_MACHINE, csVersKey, "BasePath", RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ | RRF_RT_REG_EXPAND_SZ, NULL, szTemp, &BufferSize) == ERROR_SUCCESS) 
{ 
    m_reqPath = szTemp; 
    ... 
} 

또는 :

if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, csVersKey, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) 
{ 
    char szTemp[257]; 
    DWORD BufferSize = sizeof(szTemp); 

    if (RegGetValue(hKey, NULL, "BasePath", RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ | RRF_RT_REG_EXPAND_SZ, NULL, szTemp, &BufferSize) == ERROR_SUCCESS) 
    { 
     m_reqPath = szTemp; 
     ... 
    } 

    RegCloseKey(hKey); 
} 
+0

예, 원래의'RegSetValueEx()'호출은 널 종결자를 생략했습니다. 이는 드문 일이 아니며, Microsoft가이 문제를 처리하기 위해'RegGetValue()'를 작성하여 프로그래머가 더 이상 걱정할 필요가없는 이유입니다. –

+0

Thanks Remy. 내 게시물을 업데이트했습니다. 마이클 왈츠 (Michael Walz)의 코멘트에 따르면 RegSetValueEx에 잘못된 바이트 수가 전달되었다는 것을 알았습니다. 나는 이것이 정확해야한다고 생각한다. [m_reqLeicaPath.GetLength() + 1]. 이 모든 유일한 문제는 이것이 중도 버그라는 것입니다. 이것은 일관되게 발생하지 않습니다. 문제를 재현 할 수 없었습니다. RegGetValue는 유망한 것으로 보인다. 나는 그것을 보았다. 이 응용 프로그램은 다른 사람의 책임이며 나는 그들이 변화를 강요하기 위해 강력한 사건을 제기해야합니다. – msiyer

0

일부 코드 페이지에서 통화 기호는 ASCII에서 백 슬래시와 동일한 바이트 값입니다. 당신이 유니 코드 기능을 사용한다면 이것은 문제가되지 않습니다.

자세한 내용은 http://www.siao2.com/2005/09/17/469941.aspx을 참조하십시오.

+0

Installshield 엔진은 유니 코드를 준수합니다. 백 슬래시에 외래 문자 _appended_가 표시됩니다. 백 슬래시는 문자로 대체되지 않습니다. – msiyer

관련 문제