2011-12-06 1 views
5

SafeHandle을 처음 사용할 예정입니다.SafeHandle.DangerousGetHandle()이 "위험한"이유는 무엇입니까?

UIntPtr이 필요한이 P/Invoke 메서드를 호출해야합니다.

[DllImport("advapi32.dll", CharSet = CharSet.Auto)] 
    public static extern int RegOpenKeyEx(
     UIntPtr hKey, 
     string subKey, 
     int ulOptions, 
     int samDesired, 
     out UIntPtr hkResult); 

이 UIntPtr

는 .NET의 RegistryKey 클래스에서 파생됩니다. 나는 그래서 위의 P를 사용할 수있는 IntPtr입니다에 RegistryKey 클래스를 변환 위의 방법을 사용한다/호출 :

 private static IntPtr GetRegistryKeyHandle(RegistryKey rKey) 
     { 
      //Get the type of the RegistryKey 
      Type registryKeyType = typeof(RegistryKey); 

      //Get the FieldInfo of the 'hkey' member of RegistryKey 
      System.Reflection.FieldInfo fieldInfo = 
       registryKeyType.GetField("hkey", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); 

      //Get the handle held by hkey 
      if (fieldInfo != null) 
      { 
       SafeHandle handle = (SafeHandle)fieldInfo.GetValue(rKey); 

       //Get the unsafe handle 
       IntPtr dangerousHandle = handle.DangerousGetHandle();     
       return dangerousHandle; 
      } 
} 

질문 :

  1. 사용하지 않고 쓰기에 더 좋은 방법이 있나요 "안전하지 않은"핸들?
  2. 왜 안전하지 않은 핸들이 위험합니까?

답변

3

위험한 사실이다. 사용하는 RegistryKey 개체는 IntPtr을 사용하는 동안 가비지 수집 및 마무리 될 수 있습니다. 그래서 핸들 값이 무효화되어 코드가 무작위로 실패하게됩니다. 음, 좋아, 무작위로 실패하는 것은 위험한 일은 아니지만 장시간 핸들을 잡아두면 손잡이를 다시 열 수 있습니다. 무작위 실패 모드는 당신에게 그것에 대해 뭔가를하도록 격려하기에 충분해야합니다.

당신의 PInvoke 선언은 다음과 같이 확인 :

[DllImport("advapi32.dll", CharSet=CharSet.Auto)] 
internal static extern int RegOpenKeyEx(SafeRegistryHandle key, string subkey, 
    int options, int sam, out SafeRegistryHandle result); 

그래서 당신이 지속적으로 안전 손잡이 래퍼 클래스를 사용할 수 있습니다. 그에 따라 반사 코드를 조정하십시오.

+0

내 코드의 목적은 NETFX4의 64 비트 레지스트리 지원을 모방하는 것임을 언급하는 것을 잊어 버렸습니다. 우리는 NETFX 3.5 만 사용하므로 SafeRegistryHandle을 사용할 수 없습니다. – Ian

+0

SafeRandistryHandle의 기본 클래스 인 SafeHandleZeroOrMinusOneIsInvalid로 설정하면됩니다. 또는 이름을 입력하는 것을 싫어하면 그냥 평범한 SafeHandle (누가하지 않는가)입니다. –

4

RegistryKey는 핸들 속성이 있습니다. 따라서 사용할 수 있습니다

private static IntPtr GetRegistryKeyHandle(RegistryKey rKey) 
{ 
    return rKey.Handle.DangerousGetHandle; 
} 

사용중인 포인터가 더 이상 유효하지 않을 수 있으므로 잠재적으로 위험합니다. 핸들이 SetHandleAsInvalid와 유효하지 않은 것으로 표시되어있는 경우, DangerousGetHandle 여전히 원래의 잠재적 부실 핸들 값을 반환하기 때문에 보안 위험을 초래할 수있는 DangerousGetHandle 방법을 사용 MSDN

에서 인용. 반환 된 핸들은 언제든지 재활용 할 수 있습니다. 기껏해야, 이는 핸들이 갑자기 작동을 멈출 수 있음을 의미합니다. 최악의 경우 핸들이나 핸들이 나타내는 리소스가 신뢰할 수없는 코드에 노출되면 재사용 또는 반환 된 핸들에 대한 보안 보안 공격이 발생할 수 있습니다. 예를 들어, 신뢰할 수없는 호출자는 방금 반환 된 핸들의 데이터를 쿼리하고 완전히 관련없는 리소스에 대한 정보를받을 수 있습니다. DangerousGetHandle 메서드를 사용하는 방법에 대한 자세한 내용은 DangerousAddRef 및 DangerousRelease 메서드를 참조하십시오. 뭐

+0

내 코드의 목적은 NETFX4의 64 비트 레지스트리 지원을 모방하는 것임을 언급하는 것을 잊어 버렸습니다. NETFX 3.5 만 사용하므로 RegistryKey 클래스에 Handle 멤버가 없습니다. – Ian

관련 문제