3 Stimmen

RegOpenKeyEx gibt Fehler 87 alias "INVALID_PARAMETER" zurück

Ich implementiere ein rekursives Löschen der Registrierung mit RegOpenKeyEx, RegDeleteKey und RegEnumKey.

Problem:: Obwohl der Code für Vista x86/x64 und Win 7 x86/x64 einwandfrei funktioniert, schlägt er unter XP bei einigen Schlüsseln in HKCR fehl

Problembereich:: HKCR \Installer\Products\SomeKey

Fehlercode:: 87 (UNGÜLTIGE_PARAMETER)

Seltsames Verhalten:: Löscht den Schlüssel in dem Moment, in dem ich den Schlüssel mit REGEDIT öffne.

Code::

static BOOL RcrsvRegDel( HKEY hKey, LPTSTR lpszSub )
{
BOOL    bRet = TRUE ;
LONG    lRet ;
DWORD   dwSize = MAX_PATH ;
TCHAR   szName[MAX_PATH] ;
TCHAR   szFullKey[MAX_PATH * 2] ;
HKEY    hKeySub = NULL ;
HRESULT hr = NULL ;

do{
    lRet = RegOpenKeyEx( hKey, lpszSub, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hKeySub ) ;
    printf("RegOpenKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
    if( lRet != ERROR_SUCCESS )
    {
        if( lRet == ERROR_FILE_NOT_FOUND )
        {
            bRet = TRUE ;
            break ;
        }
        else
        {
            bRet = FALSE ;
            break ;
        }
    }

    while( ERROR_NO_MORE_ITEMS != (lRet = RegEnumKeyEx(hKeySub, 0, szName, &dwSize, NULL, NULL, NULL, NULL)) )
    {
        bRet = RcrsvRegDel( hKeySub, szName) ;
        if( bRet == FALSE )
            break ;
    }

    if( hKeySub != NULL )
    {
        RegCloseKey(hKeySub) ;
        hKeySub = NULL ;
    }

    lRet = RegDeleteKey( hKey, lpszSub ) ;
    printf("RegDelKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
    if( lRet == ERROR_SUCCESS )
    {
        bRet = TRUE ;
        break ;
    }
}while(0) ;
return bRet ;
}

Haben Sie eine Idee, was hier los ist?

UPDATE::

Ich habe auch den Parameter samDesired mit folgenden Flags ausprobiert

-KEY_READ

-SCHLÜSSEL_LESEN | SCHLÜSSEL_SCHREIBEN

-SCHLÜSSEL_AUFZÄHLEN_UNTERSCHLÜSSEL

-KEY_ENUMERATE_SUB_KEYS | DELETE

Keines der oben genannten Flaggen funktioniert :-(

1voto

Serge Z Punkte 425

Weil Sie RegDeleteKey nicht verwenden können, wenn das Handle mit dem Flag KEY_WOW64_32KEY geöffnet wurde. siehe http://msdn.microsoft.com/en-us/library/aa384129(v=vs.85).aspx zur Information. Sie müssen RegDeleteKeyEx mit denselben Schlüsseln verwenden.

0voto

Remy Lebeau Punkte 498719

Sie können nicht verwenden RegDeleteKey() um einen 32-Bit-Schlüssel auf einem 64-Bit-System zu löschen. Die Dokumentation sagt so viel:

Die Funktion RegDeleteKey kann nicht verwendet werden, um auf eine alternative Registrierungsansicht zuzugreifen.

Sie müssen Folgendes verwenden RegDeleteKeyEx() stattdessen.

Versuchen Sie so etwas:

typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS)(HANDLE, PBOOL);
extern LPFN_ISWOW64PROCESS fnIsWow64Process;

typedef LONG (WINAPI *LPFN_REGDELETEKEYEX)(HKEY, LPCTSTR, REGSAM, DWORD);
extern LPFN_REGDELETEKEYEX fnRegDeleteKeyEx;

.

BOOL WINAPI IsWow64Process_Impl(HANDLE hHandle, PBOOL Wow64Process);
{
    *Wow64Process = FALSE;
    return TRUE;
}

BOOL WINAPI IsWow64Process_Stub(HANDLE hProcess, PBOOL Wow64Process)
{
    fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(GetModuleHandle(TEXT("kernel32")), "IsWow64Process");

    if ( NULL == fnIsWow64Process )
        fnIsWow64Process = &IsWow64Process_Impl;

    return fnIsWow64Process(hProcess, Wow64Process);
}

LONG WINAPI RegDeleteKeyEx_Impl(HKEY hKey, LPCTSTR lpSubKey, REGSAM samDesired, DWORD dwReserved)
{
    return RegDeleteKey( hKey, lpSubKey );
}

LONG WINAPI RegDeleteKeyEx_Stub(HKEY hKey, LPCTSTR lpSubKey, REGSAM samDesired, DWORD dwReserved)
{
    fnRegDeleteKeyEx = (LPFN_REGDELETEKEYEX) GetProcAddress(GetModuleHandle(TEXT("advapi32")),
        #ifdef UNICODE
        "RegDeleteKeyExW"
        #else
        "RegDeleteKeyExA"
        #endif
    );

    if ( NULL == fnRegDeleteKeyEx )
        fnRegDeleteKeyEx = &RegDeleteKeyEx_Impl;

    return fnRegDeleteKeyEx( hKey, lpSubKey, samDesired, dwReserved );
}

LPFN_ISWOW64PROCESS fnIsWow64Process = &IsWow64Process_Stub;
LPFN_REGDELETEKEYEX fnRegDeleteKeyEx = &RegDeleteKeyEx_Stub;

.

BOOL IsWin64()
{
    #if defined(_WIN64)
    return FALSE;  // 64-bit programs run only on Win64
    #elif defined(_WIN32)
    // 32-bit programs run on both 32-bit and 64-bit Windows so must sniff
    BOOL f64 = FALSE;
    return fnIsWow64Process(GetCurrentProcess(), &f64) && f64;
    #else
    return FALSE; // Win64 does not support Win16
    #endif
}

.

static BOOL RcrsvRegDel( HKEY hKey, LPTSTR lpszSub ) 
{ 
    BOOL    bRet = TRUE; 
    LONG    lRet; 
    DWORD   dwSize; 
    TCHAR   szName[MAX_PATH+1]; 
    HKEY    hKeySub = NULL; 

    REGSAM Wow64Flag = (IsWin64()) ? KEY_WOW64_32KEY : 0;

    lRet = RegOpenKeyEx( hKey, lpszSub, 0, KEY_ENUMERATE_SUB_KEYS | KEY_SET_VALUE | DELETE | Wow64Flag, &hKeySub ) ; 
    printf("RegOpenKey:: %S :: lRet = %ld\n", lpszSub, lRet) ; 

    if( lRet != ERROR_SUCCESS ) 
    {
        if ( lRet != ERROR_FILE_NOT_FOUND )
            bRet = FALSE; 
    }
    else
    {
        do
        {
            dwSize = MAX_PATH;
            lRet = RegEnumKeyEx( hKeySub, 0, szName, &dwSize, NULL, NULL, NULL, NULL );

            if ( lRet != ERROR_SUCCESS )
            {
                if ( lRet != ERROR_NO_MORE_ITEMS )
                    bRet = FALSE;

                break;
            }

            bRet = RcrsvRegDel( hKeySub, szName ); 
            if ( !bRet ) 
                break; 
        }
        while (1);

        RegCloseKey(hKeySub); 

        if ( bRet )
        {
            if ( Wow64Flag != 0 )
                lRet = fnRegDeleteKeyEx( hKey, lpszSub, Wow64Flag, 0 );
            else
                lRet = RegDeleteKey( hKey, lpszSub );
            printf("RegDelKey:: %S :: lRet = %ld\n", lpszSub, lRet) ; 

            if ( lRet != ERROR_SUCCESS )
                bRet = FALSE; 
        }
    }

    return bRet;
} 

Ziehen Sie daher die Verwendung von RegDeleteTree() o SHDeleteKey() stattdessen. Lassen Sie sie die Rekursion für Sie erledigen.

0voto

Abhineet Punkte 5130

Das können Sie so machen. Nehmen Sie die Flagge als Eingabeparameter und übergeben Sie eine Flagge für RegOpenKeyEx und wiederum einen Satz von Flaggen beim Aufruf der rekursiven Funktion. Ich habe Ihren Code ausprobiert und er funktioniert jetzt einwandfrei, obwohl ich nicht sicher bin, was das Problem verursacht hat.

static BOOL RcrsvRegDel( HKEY hKey, LPTSTR lpszSub, DWORD dwOpenFlags )
{
    BOOL    bRet = TRUE ;
    LONG    lRet ;
    DWORD   dwSize = MAX_PATH ;
    TCHAR   szName[MAX_PATH] ;
    HKEY    hKeySub = NULL ;
    HRESULT hr = NULL ;
    HANDLE  hProcess = NULL ;
    HANDLE  hToken = NULL ;

    do{
        bRet = SetPrivilege( SE_BACKUP_NAME, TRUE ) ;
        if( bRet == FALSE )
        {
            bRet = FALSE ;
            break ;
        }

        lRet = RegOpenKeyEx( hKey, lpszSub, 0, dwOpenFlags, &hKeySub ) ;
        if( lRet != ERROR_SUCCESS )
        {
            bRet = FALSE ;
            break ;
        }

        while( ERROR_NO_MORE_ITEMS != (lRet = RegEnumKeyEx(hKeySub, 0, szName, &dwSize, NULL, 
            NULL, NULL, NULL)) )
            if( !RcrsvRegDel(hKeySub, szName, dwOpenFlags) ) 
            {
                bRet = FALSE ;
                break ;
            }

        lRet = RegDeleteKey( hKey, lpszSub ) ;
        printf("RegDelKey:: %S :: lRet = %ld\n", lpszSub, lRet) ;
        if( lRet != ERROR_SUCCESS )
        {
            bRet = FALSE ;
            break ;
        }

        if( hKeySub != NULL )
        {
            RegCloseKey(hKeySub) ;
            hKeySub = NULL ;
        }
    }while(0) ;
    return bRet ;
}

static BOOL SetPrivilege( LPCTSTR lpszPrivilege, BOOL bEnablePrivilege ) 
{
    LUID    luid ;
    BOOL    bRet = TRUE ;
    HANDLE  hToken = NULL ;
    HANDLE  hProcess = NULL ;
    TOKEN_PRIVILEGES tp ;

    do{
        hProcess = GetCurrentProcess() ;
        if( 0 == OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken) )
        {
            bRet = FALSE ;
            break ;
        }

        if( !LookupPrivilegeValue(NULL, lpszPrivilege, &luid) )
        {
            bRet = FALSE ;
            break ;
        }

        tp.PrivilegeCount = 1 ;
        tp.Privileges[0].Luid = luid ;

        if( bEnablePrivilege )
            tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED ;
        else
            tp.Privileges[0].Attributes = 0 ;

        if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, 
            (PDWORD)NULL) )
        {
            bRet = FALSE ;
            break ;
        }

        if( ERROR_NOT_ALL_ASSIGNED == GetLastError() )
        {
            bRet = FALSE ;
            break ;
        }
    }while(0) ;
    if( hToken != NULL ) CloseHandle( hToken ) ;
    return bRet ;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X