32位程式訪問64位系統的註冊表問題

來源:互聯網
上載者:User

總之,32位程式在64位系統上,只能訪問到一部分註冊表資訊,要想訪問全,簡單的做法就是用64位的程式。 下面是轉來的文章:

【原文地址:http://blog.sina.com.cn/s/blog_592fe54701008d8w.html】

1 簡介

當前電腦系統已經逐漸地從32位轉到64位,XP,2003,VISTA都有64位的版本。從目前而言,32位應用程式還是佔了絕大多數,但是也有部分應用程式既有32位版本,又有64位版本。為了保證32位程式可以順利運行在64位系統上,微軟提供了一套叫WOW64的類比機制。通常把這套系統稱為WOW64。從總體上來說,WOW64是一套基於使用者模式的動態連結程式庫,它可以把32位應用程式的發出的命令翻譯成64位系統可以接受的格式。從中可以大概地看出32位應用程式運行在64位系統上的方式。

 

當32位應用程式啟動並執行時候,首先會去啟動本地庫載入器(Native Library Loader)。載入器會識別出應用程式是32位的並且用特殊的方式來處理它。載入器會為32位應用程式建立起一個WOW64的類比環境並把控制權交給32位的Ntdll.dll。運行在32位應用程式和64位Ntdll.dll之間的WOW64類比環境會將32位應用程式的指令翻譯成64位Ntdll.dll可以接受的方式,並且它也可以把系統的指令翻譯成32位應用程式可以接受的方式。

2 如何判斷系統是64位
3 檔案系統的轉向

32位進程不能載入64位Dll,64位進程也不可以載入32位Dll。Windows的系統目錄包含了所有安裝的應用程式和它們的Dll檔案,根據我們所述的規則,它應該被分為給64位應用程式的目錄和給32位應用程式的目錄。如果不這樣,我們就無法區分32位和64位的Dll檔案。對於64位應用程式,其檔案通常被放在%windir%\system32和%programfiles%(比如:c:\program files)。對於32位應用程式,其檔案通常在%windir%\syswow64和C:\program files (x86)下面。如果我們用32位程式去訪問%windir%\system32,不管我們用寫入程式碼還是其它的方式,系統都會自動地給我們轉向到%windir%\syswow64下面。這種轉向對於每個32位應用程式預設都是開啟的。但是這種轉向對於我們來說並不總是需要的。那麼我們可以在C#裡面調用相關的API來關閉和開啟這種轉向。常用的函數有3個,Wow64DisableWow64FsRedirection(關閉系統轉向),Wow64RevertWow64FsRedirection(開啟系統轉向),Wow64EnableWow64FsRedirection(開啟系統轉向)。但是Wow64EnableWow64FsRedirection在嵌套使用的時候不可靠,所以通常用上面的Wow64RevertWow64FsRedirection來開啟檔案系統轉向功能。在C#中,我們可以利用DllImport直接調用這兩個函數。但是要注意到的是,在32位的Kernel.dll中是沒有這兩個函數的。那麼在C++中應該使用LoadLibrary來動態載入這兩個函數。否則會因為找不到這兩個函數而無法通過編譯。而且在目前的使用中,發現這兩個函數有一個小小的問題。如果我們在調用了Wow64DisableWow64FsRedirection後去調用Comdlg32.dll的GetOpenFileName函數,是無法調用成功的。但是也得不到Error的值。在C#中可以用如下的代碼關閉和開啟檔案的轉向。

聲明調用規則

[DllImport( "Kernel32.dll", CharSet=CharSet.Auto, SetLastError = true)] 
public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
[DllImport( "Kernel32.dll", CharSet=CharSet.Auto, SetLastError = true)] 
public static extern bool Wow64RevertWow64FsRedirection(IntPtr ptr);

關閉轉向

Wow64DisableWow64FsRedirection(ref Ptr);

開啟轉向

Wow64RevertWow64FsRedirection(Ptr);

要注意的是,關閉和開啟要成對出現。以免出現混亂的行為。

4 註冊表的轉向

為了防止註冊表鍵衝突,註冊表在某些鍵也分成了兩個部分。一部分是專門給64位系統訪問的,另一部分是專門給32位系統訪問的,放在Wow6432Node下面。當32位程式去訪問某些索引值的時候,和檔案轉向類似,系統也會自動地把程式的訪問轉向到Wow6432Node下面。Wow6432Node這個節點存在於HKEY_LOCAL_MACHINE和HKEY_CURRENT_USER下面。如果我們希望關閉這個轉向的話,可以通過上面的Wow64DisableWow64FsRedirection和RegOpenKeyEx方法辦到。RegOpenEx方法在C#中調用聲明方法如下:

[DllImport("Advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern uint RegOpenKeyEx( UIntPtr hKey,string lpSubKey, uint ulOptions,int samDesired,out IntPtr phkResult);

其中需要注意的是samDesired這個參數。這個參數可以取 KEY_ALL_ACCESS, KEY_QUERY_VALUE,  KEY_WOW64_64KEY等值(詳情可以查閱MSDN)。當我們已經關閉了檔案系統的轉向,那麼就可以利用:(KEY_QUERY_VALUE | KEY_WOW64_64KEY)來得到註冊表的完整存取。這個地方需要注意的是,在Vista下面,有一些登錄機碼是唯讀,如果用了KEY_ALL_ACCESS這個參數,就會出現“Access is denied” 這個錯誤(ErrorCode = 5)。因此,如果不是要寫入註冊表的話,最好不要使用KEY_ALL_ACCESS。我們可以用如下代碼來完全訪問註冊表。

        //use this function transfer the string key name to HKEY handle
        private static UIntPtr TransferKeyName(string keyName) 
        {
            UIntPtr HKEY_CLASSES_ROOT        = (UIntPtr)0x80000000;
            UIntPtr HKEY_CURRENT_USER        = (UIntPtr)0x80000001;
            UIntPtr HKEY_LOCAL_MACHINE    = (UIntPtr)0x80000002;
            UIntPtr HKEY_USERS                    = (UIntPtr)0x80000003;
            UIntPtr HKEY_CURRENT_CONFIG = (UIntPtr)0x80000005;

            switch(keyName)
            {
                case "HKEY_CLASSES_ROOT":
                    return HKEY_CLASSES_ROOT;
                case "HKEY_CURRENT_USER":
                    return HKEY_CURRENT_USER;
                case "HKEY_LOCAL_MACHINE":
                    return HKEY_LOCAL_MACHINE;
                case "HKEY_USERS":
                    return HKEY_USERS;
                case "HKEY_CURRENT_CONFIG":
                    return HKEY_CURRENT_CONFIG;
            }

            return HKEY_CLASSES_ROOT;
        }

        public static bool OpenRegKey(string keyName, string subKeyName)
        {
            UIntPtr hKey = TransferKeyName(keyName);
            UIntPtr phkResult = UIntPtr.Zero;
            int KEY_QUERY_VALUE    = (0x0001); 
            int KEY_WOW64_64KEY    = (0x0100);
            int KEY_ALL_WOW64        = (KEY_QUERY_VALUE | KEY_WOW64_64KEY);

            if(Is64bitOS && !IsWow64RedirectionEnabled) //The os is 64 bit and the FileRedirection is closed
            {                
                samDesired = KEY_ALL_WOW64;
            }

            if(RegOpenKeyEx(hKey, subKeyName,0,samDesired,out phkResult) == 0) //ERROR_SUCCESS=0
            {
                return true;
            }

            int errCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();

            return false;
        }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.