我正在使用RegOpenKeyEx,RegDeleteKey和RegEnumKey实现递归注册表删除。
问题:: 虽然代码适用于Vista x86 / x64和Win 7 x86 / x64,但在XP上的某些密钥在HKCR中失败
问题区域:: 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 ;
}
有什么想法吗?
UPDATE ::
我还尝试了带有以下标志的samDesired参数
-KEY_READ
-KEY_READ | KEY_WRITE
-KEY_ENUMERATE_SUB_KEYS
-KEY_ENUMERATE_SUB_KEYS | DELETE
以上标志都不起作用: - (
答案 0 :(得分:1)
因为你不能使用带有句柄的RegDeleteKey用标志KEY_WOW64_32KEY打开。 有关信息,请参阅http://msdn.microsoft.com/en-us/library/aa384129(v=vs.85).aspx。 您必须使用相同键的RegDeleteKeyEx。
答案 1 :(得分:0)
您不能使用RegDeleteKey()
删除64位系统上的32位密钥。 The documentation尽可能多地说:
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(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;
}
话虽如此,请考虑使用RegDeleteTree()
或SHDeleteKey()
。让他们为你做递归。
答案 2 :(得分:0)
你可以这样做。将标志作为输入参数,并为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 ;
}