RegOpenKeyEx返回错误87又名“INVALID_PARAMETER”

我正在使用RegOpenKeyEx,RegDeleteKey和RegEnumKey实现recursionregistry删除。

问题::虽然代码对于Vista x86 / x64和Win 7 x86 / x64来说工作得很好,但是在HKCR的某些键上却无法使用XP

问题领域:: HKCR \ Installer \ Products \ SomeKey

错误代码:: 87(INVALID_PARAMETER)

奇怪的行为::当我使用REGEDIT打开密钥时删除密钥。

码::

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 ; } 

任何想法是什么?

更新::

我也尝试了samDesired参数以下标志

-KEY_READ

-KEY_READ | KEY_WRITE

-KEY_ENUMERATE_SUB_KEYS

-KEY_ENUMERATE_SUB_KEYS | 删除

上述标志都不起作用:-(

你可以这样做。 以标志作为输入参数并为RegOpenKeyEx传递一个标志,并在调用递归函数时再次传递一组标志。 我已经试过你的代码,它现在正在工作完美,虽然它不知道是什么导致了这个问题。

 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 ; } 

因为您无法使用RegDeleteKey,并且使用标志KEY_WOW64_32KEY打开了句柄。 有关信息,请参阅http://msdn.microsoft.com/en-us/library/aa384129(v=vs.85).aspx 。 您必须使用相同的密钥RegDeleteKeyEx。

您不能使用RegDeleteKey()删除64位系统上的32位密钥。 该文件说:

RegDeleteKey函数不能用于访问备用注册表视图。

您必须改用RegDeleteKeyEx()

尝试这样的事情:

 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(GetmoduleeHandle(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(GetmoduleeHandle(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; } 

据说,考虑使用RegDeleteTree()SHDeleteKey()来代替。 让他们为你做递归。