天天看點

Win32彙編--操作系統資料庫

1.打開和關閉子鍵

   系統資料庫函數對系統資料庫的操作是通過句柄來完成的,與檔案操作一樣,在對某個鍵下的子鍵或者鍵值項進行操作之前,需要先将這個鍵打開,然後使用鍵句柄來引用這個鍵,在操作完畢以後再将鍵句柄關閉。系統資料庫的根鍵不需要打開,它們的句柄是固定不變的,要使用根鍵的時候隻要把這些句柄直接拿來用就是了,Windows.inc中已經預定義了它們的數值:

HKEY_CLASSES_ROOT                      equ 80000000h

HKEY_CURRENT_USER                      equ 80000001h

HKEY_LOCAL_MACHINE                     equ 80000002h

HKEY_USERS                              equ 80000003h

HKEY_PERFORMANCE_DATA                equ 80000004h

HKEY_CURRENT_CONFIG                    equ 80000005h

HKEY_DYN_DATA                           equ 80000006h

  在程式中可以随時将這些助記符當做句柄來引用對應的根鍵。在程式結束的時候,不需要關閉這些根鍵句柄。

  打開子鍵使用RegOpenKeyEx函數,在Win16中還存在一個RegOpenKey函數,雖然在Win32中這個函數仍然存在,但這僅是為了相容的目的而設定的。API手冊中推薦使用RegOpenKeyEx函數:

    invoke  RegOpenKeyEx,hKey,lpSubKey,dwOptions,samDesired,phkResult

  函數的hKey參數指定父鍵句柄,lpSubKey指向一個字元串,用來表示要打開的子鍵名稱,在系統中一個子鍵的全稱是以“根鍵\第1層子鍵\第2層子鍵\第n層子鍵”類型的字元串表示的,中間用“\”隔開,字元串的最後以0字元結束,這和目錄名的表示方法是很像的。

既然子鍵的全稱是這樣表示的,那麼要打開一個子鍵的時候,下面的兩種表示方法有什麼不同呢?

(1)父鍵=HKEY_LOCAL_MACHINE,子鍵=Software\RegTest\MySubkey

(2)父鍵=HKEY_LOCAL_MACHINE\Software,子鍵=RegTest\MySubkey

答案是:這兩種表示方法是完全相同的。在使用RegOpenKeyEx函數打開子鍵的時候,既可以将hKey參數設定為HKEY_LOCAL_MACHINE根鍵的句柄,并将lpSubKey參數指向“Software\RegTest\MySubkey”字元串;也可以将hKey參數設定為“HKEY_LOCAL_ MACHINE\Software”的句柄,将lpSubKey參數指向“RegTest\MySubkey”字元串,得到的結果是一樣的。但是,使用第一種方法時,hKey參數可以直接使用助記符HKEY_LOCAL_ MACHINE來表示,因為根鍵的句柄是固定的,不需要打開;而使用第二種方法時,還需要先打開“HKEY_LOCAL_MACHINE\Software”鍵來擷取它的句柄,是以具體使用哪種方法還要根據具體情況靈活選用。

函數的其他幾個參數的含義如下。

●   dwOptions參數——系統保留參數,必須指定為0。

●   samDesired參數——子鍵的打開方式,根據使用子鍵的方式,可以設定為下列取值的組合,隻有指定了打開的方式,才能在打開子鍵後進行相應的操作:

■   KEY_ALL_ACCESS——允許所有的存取。

■   KEY_CREATE_LINK——允許建立符号清單。

■   KEY_CREATE_SUB_KEY——允許建立下一層子鍵。

■   KEY_ENUMERATE_SUB_KEYS——允許枚舉下一層子鍵。

■   KEY_EXECUTE——允許讀操作。

■   KEY_QUERY_VALUE——允許查詢鍵值資料。

■   KEY_READ—KEY_QUERY_VALUE,KEY_ENUMERATE_SUB_KEYS和KEY_ NOTIFY的組合。

■   KEY_SET_VALUE——允許修改或建立鍵值資料。

■   KEY_WRITE——KEY_SET_VALUE和KEY_CREATE_SUB_KEY的組合。

●   phkResult參數——指向一個雙字變量,函數在這裡傳回打開的子鍵句柄。

  如果函數執行成功,傳回值是ERROR_SUCCESS,并且函數在phkResult參數指向的變量中傳回子鍵句柄。

當不再需要繼續使用鍵句柄的時候,可以使用RegCloseKey函數将它關閉:

    invoke  RegCloseKey,hKey

如果句柄被成功關閉,函數傳回ERROR_SUCCESS。

2.建立和删除子鍵

  建立一個子鍵可以使用RegCreateKeyEx函數:

    invoke  RegCreateKeyEx,hKey,lpSubKey,Reserved,lpClass,dwOptions,\

            samDesired,lpSecurityAttributes,phkResult,lpdwDisposition

  函數中與RegOpenKeyEx函數中同名參數的含義和用法是相同的,hKey也是用來指定父鍵句柄,lpSubKey指向要建立的子鍵名稱字元串,samDesired參數指明子鍵建立後的操作方式,phkResult指向用來傳回鍵句柄的雙字變量。

其餘一些參數的含義如下。

●   Reserved參數——保留參數,必須設定為0。

●   lpClass參數——為建立的子鍵定義一個類名,這個參數一般設定為NULL。

●   dwOptions參數——建立子鍵時的選項,它可以是以下取值之一:

■   REG_OPTION_NON_VOLATILE——預設值,子鍵被建立到系統資料庫檔案中。

■   REG_OPTION_VOLATILE——建立易失性的子鍵,子鍵被儲存在記憶體中,當系統重新啟動的時候,子鍵消失。這個選項僅對Windows NT系統有效,在9x系統中被忽略。

●   lpSecurityAttributes參數——指向一個SECURITY_ATTRIBUTES結構,用來指定鍵句柄的繼承性,如果句柄不需要被繼承,可以使用NULL。

●   lpdwDisposition參數——這個參數一般使用NULL。

  當需要建立的子鍵已經存在的時候,函數僅起到RegOpenKeyEx函數的作用;如果子鍵不存在,那麼函數将建立子鍵。如果函數執行成功,傳回值是ERROR_SUCCESS。

  如果要建立“HKEY_LOCAL_MACHINE\Key1\Key2\Key3”子鍵,既可以将hKey參數設定為HKEY_LOCAL_MACHINE,将lpSubKey參數指向“Key1\Key2\Key3”字元串;也可以先打開“HKEY_LOCAL_MACHINE\Key1”鍵,将hKey設定為打開的鍵句柄,然後将lpSubKey參數指向“Key2\Key3”字元串,這和RegOpenKeyEx函數中的用法是類似的。在第二種用法中,打開父鍵的時候注意要指定KEY_CREATE_SUB_KEY方式。

當被建立子鍵的上層鍵不存在的時候,函數連上層的子鍵一起建立。如上面的例子中,假如Key2也不存在,那麼函數先在“HKEY_LOCAL_MACHINE\Key1”下建立Key2,然後在Key2下繼續建立Key3。

_Reg.asm檔案中的大部分子程式首先用RegOpenKeyEx函數打開子鍵以便進行下一步操作,但是儲存鍵值用的_RegSetValue子程式中使用的是RegCreateKeyEx函數,這樣當子鍵已經存在的時候,函數僅打開它,如果子鍵不存在的話則建立子鍵。

删除子鍵使用RegDeleteKey函數:

    invoke  RegDeleteKey,hKey,lpSubKey

  hKey參數為父鍵句柄,lpSubKey參數指向要删除的子鍵名稱字元串。函數僅删除最後一層子鍵以及下面的全部鍵值項。比如在“HKEY_LOCAL_MACHINE\Key1\Key2\Key3”子鍵存在的情況下,當hKey指定為HKEY_LOCAL_MACHINE,lpSubKey指向“Key1\Key2\Key3”的時候,函數僅删除Key3子鍵,不會連同Key2,Key1全部删除。但如果Key3子鍵下有鍵值項的話,這些鍵值項會被一起删除。

如果要删除的子鍵下還存在下一層子鍵,比如上例中的Key3子鍵下還存在Key4子鍵,那麼對Key3子鍵進行删除時,Windows 9x和Windows NT系統的做法是不同的:在Windows 9x中,Key3子鍵本身、Key3子鍵下所有的鍵值項和下層子鍵(包括上面舉例的Key4)會被全部删除;而在Windows NT中,隻有在不存在下層子鍵的情況下删除才能成功,如果Key3子鍵下還存在Key4子鍵,那麼對Key3子鍵的删除是不會成功的。

應用程式不能直接在HKEY_LOCAL_MACHINE根鍵下面建立和删除子鍵,隻能在下一層由系統定義的子鍵下進行操作,如果要儲存配置資訊的話,使用者應用程式一般在HKEY_LOCAL_MACHINE\SOFTWARE子鍵下再建立自己的子鍵,然後将鍵值項儲存在自己的子鍵中。

3  管理鍵值

  配置資訊是存放在鍵值項中的,打開或者建立一個鍵的最終目的都是為了在鍵下面存取鍵值項,這就像磁盤上的目錄是用來合理組織和管理檔案用的,資料還是存放在檔案中的。當使用打開或者建立鍵的函數得到鍵句柄後,就可以通過它來存取鍵值項了。

3.1 設定鍵值項

在一個鍵下面設定和建立鍵值項使用RegSetValueEx函數:

    invoke  RegSetValueEx,hKey,lpValueName,Reserved,dwType,lpData,cbData

hKey參數指定一個鍵句柄,鍵值項将儲存在這個鍵下,lpValueName參數指向定義鍵值項名稱的字元串。假如lpValueName參數指向一個空串或者設定為NULL,并且設定的鍵值類型是REG_SZ的話,那麼函數設定的是鍵的預設值(圖15.2中所示的“預設”項)。

Reserved參數是保留的,必須設定為0。

dwType參數指出了要設定的鍵值資料的類型,可以使用的類型如表15.1所示。

lpData參數是一個指針,指向包含鍵值資料的緩沖區,cbData參數為要儲存的資料長度。緩沖區中的資料格式以及cbData參數指定的資料長度需要和dwType參數指出的鍵值類型相對應,比如要設定REG_SZ類型的鍵值項,就要将cbData參數設定為字元串的長度+1(加上尾部的0);同樣對于REG_MULTI_SZ類型的鍵值項來說,最後的兩個0的長度都必須包括到cbData參數中;對于REG_DWORD類型的鍵值項,需要将雙字資料放在緩沖區中并将cbData參數設定為4(不像其他函數一樣當參數是雙字的時候一般将雙字在參數中直接傳遞)。

當子鍵中的鍵值項不存在的時候,函數建立鍵值項;當鍵值項已經存在的時候,函數将新的鍵值資料寫入。如果鍵值資料儲存成功,函數傳回ERROR_SUCCESS。

雖然鍵值資料的最大長度沒有規定,其大小僅受限于可用的記憶體大小,應用程式甚至可以使用REG_BINARY格式的鍵值項将整個檔案都儲存到系統資料庫中,但在實際的使用中還是建議不要将大于2 KB的資料放到系統資料庫中,因為這将影響系統資料庫的使用效率。

要在一個鍵中建立或修改鍵值項,鍵的打開方式中必須包括KEY_SET_VALUE方式。

3.2  查詢鍵值資料

讀取鍵值項中的資料或者查詢鍵值項的屬性使用RegQueryValueEx函數,用法如下:

    invoke  RegQueryValueEx,hKey,lpValueName,lpReserved,\

            lpType,lpData,lpcbData

參數hKey和lpValueName用來指定要讀取的鍵值項所處的子鍵句柄和鍵值項的名稱, lpReserved參數是保留參數,必須使用0。lpData參數指向一個緩沖區,用來接收傳回的鍵值資料。

函數的其餘幾個參數使用時必須注意的是它們都是指向雙字變量的指針,這一點和使用RegSetValueEx函數時是不同的:

●   lpType參數——函數在這個參數指向的雙字變量中傳回讀取的鍵值類型,如果不需要傳回鍵值項的類型,可以将這個參數設定為NULL。

●   lpcbData參數——在調用的時候,程式必須在這個參數指向的雙字變量中放置緩沖區的長度(并不是直接用lpcbData參數指出緩沖區長度)。當函數傳回的時候,雙字變量被函數改為傳回到緩沖區中的資料的實際長度。

當函數執行成功的時候,函數的傳回值是ERROR_SUCCESS。當程式指定的緩沖區長度不足以容納傳回的資料的時候,函數的傳回值是ERROR_MORE_DATA,這時lpcbData參數指向的雙字變量中傳回需要的長度。

如果僅需要查詢鍵值長度而不需要傳回實際的資料,可以将lpData參數設定為NULL,但是lpcbData參數不能為NULL,這時函數會在lpcbData參數指向的雙字變量中傳回鍵值資料的長度。如果僅想查詢鍵值項的類型,也可以同時将lpcbData和lpData參數設定為NULL。在這些情況下如果函數查詢成功,傳回值也是ERROR_SUCCESS。

如果要在一個鍵中查詢鍵值資料的話,鍵的打開方式中必須包括KEY_QUERY_VALUE方式。

3.3  删除鍵值項

删除一個鍵值項的操作則比較簡單,使用RegDeleteValue函數就可以了:

    invoke  RegDeleteValue,hKey,lpValueName

hKey參數和lpValueName指定父鍵句柄和被删除鍵值項的名稱。惟一需要注意的是父鍵句柄的打開方式必須包括KEY_SET_VALUE。如果鍵值項被成功删除,則函數傳回ERROR_SUCCESS。

4  子鍵和鍵值的枚舉

  在實際的應用中往往需要對一個鍵下的子鍵或者鍵值項進行清單操作,就像在DOS系統下常用Dir指令一樣,這就要用到子鍵和鍵值的枚舉函數。在系統資料庫函數中,枚舉子鍵和枚舉鍵值項使用的函數是不一樣的,不像FindFirstFile等檔案清單函數那樣将檔案連同子目錄混在一起列出來。下面分别介紹這兩種函數。

4.1  枚舉子鍵

例子程式中枚舉子鍵和鍵值項的操作是在_EnumKey子程式中完成的,讀者可以參考一下相應的代碼,在這個子程式中,程式首先使用RegEnumKeyEx函數來枚舉子鍵:

    invoke  RegEnumKeyEx,hKey,dwIndex,lpName,lpcbName,lpReserved,\

            lpClass,lpcbClass,lpftLastWriteTime

hKey參數指定被枚舉的鍵句柄,dwIndex參數指定需要傳回資訊的子鍵索引編号,lpName指向一個緩沖區,函數在這裡傳回子鍵名稱,lpClass指向用于傳回子鍵類名的緩沖區,lpftLastWriteTime指向一個FILETIME結構,函數在這裡傳回子鍵上一次被寫入的時間。lpReserved參數是保留參數,必須設定為0。

要注意的是:lpcbName和lpcbClass指向兩個雙字變量,調用函數前,這兩個雙字變量中必須放入lpName和lpClass指定的緩沖區的長度,當函數傳回的時候,函數在裡面傳回實際傳回到緩沖區中的字元串的長度。如果函數執行成功,傳回值是ERROR_SUCCESS。

RegEnumKeyEx函數每次傳回一個子鍵的名稱資訊,是以要枚舉全部子鍵的話,必須用循環多次調用這個函數,并且每次将dwIndex參數指定的子鍵索引号遞增,當子鍵全部被枚舉後,繼續調用函數将得到一個ERROR_NO_MORE_ITEMS傳回值,這時就可以結束循環了。下面是循環的典型寫法:

                    .data

dwIndex         dd      ?

dwSize          dd      ?

szBuffer    db      256 dup (?)

                    .code

                    ... ...

            mov     dwIndex,0

            .while  TRUE

                    mov     dwSize,sizeof szBuffer

                    invoke  RegEnumKeyEx,hKey,dwIndex,addr szBuffer,addr dwSize,\

                            NULL,NULL,NULL,NULL

                    .break  .if eax == ERROR_NO_MORE_ITEMS

                   ;處理擷取的子鍵

                    inc dwIndex

        .endw

在循環開始前,程式初始化當做索引用的dwIndex變量,每次調用RegEnumKeyEx後将索引加1,當檢測到函數的傳回值是ERROR_NO_MORE_ITEMS的時候,使用 .break語句退出循環。程式不使用 .break .if eax != ERROR_SUCCESS語句當做結束循環的條件是因為:當出現緩沖區不夠長等意外情況時,函數的調用可能失敗,但是這時子鍵可能還沒有全部被枚舉,是以隻有判斷傳回值是ERROR_NO_MORE_ITEMS才能保證全部子鍵被枚舉。

每次調用函數之前,程式必須重新将dwSize變量的值設定為szBuffer緩沖區的大小,這是因為每次函數傳回時,dwSize中會變成傳回的子鍵名稱字元串的長度,如果不重新設定,下一次調用時函數就會将這個長度認為是緩存區的長度。

當進行枚舉子鍵操作時,父鍵的打開方式中必須包括KEY_ENUMERATE_SUB_KEYS方式(KEY_READ方式中已經包括KEY_ENUMERATE_SUB_KEYS)。

4.2  枚舉鍵值

RegEnumKeyEx函數僅枚舉一個鍵下面的全部子鍵,對鍵下面的鍵值項則不會去理會。如果要枚舉一個鍵下面的鍵值項,那麼必須使用RegEnumValue函數:

    invoke  RegEnumValue,hKey,dwIndex,lpValueName,lpcbValueName,\

            lpReserved,lpType,lpData,lpcbData

函數的hKey,dwIndex和lpReserved參數的使用同RegEnumKeyEx函數中的同名參數。其餘的一些參數中,lpValueName和lpData參數指向兩個緩存區,函數在裡面分别傳回鍵值項的名稱和資料。lpcbValueName和lpcbData參數指向兩個雙字變量,調用函數前裡面必須放入鍵值項名稱緩沖區和鍵值資料緩沖區的長度,函數傳回後這兩個變量的值被改為傳回到緩沖區中的資料長度。lpType參數則指向一個用于傳回鍵值資料類型的雙字變量。

如果不需要傳回鍵值資料,lpData和lpcbData參數可以設定為NULL,如果不需要傳回鍵值資料類型,lpType參數也可以設定為NULL。

下面是一段典型的用于枚舉鍵值項的循環代碼:

                    .data

dwType          dd      ?

dwNameSize      dd      ?

szName          db      256 dup (?)

dwDataSize      dd      ?

szData          db      256 dup (?)

                    .code

                    ...

            mov dwIndex,0

                    mov     dwNameSize,sizeof szName

                    mov     dwDataSize,sizeof szData

                    invoke  RegEnumValue,hKey,dwIndex,addr szName,\

                            addr dwNameSize,NULL,addr dwType,\

                            addr szData,addr dwDataSize

                    .break  .if eax == ERROR_NO_MORE_ITEMS

                   ;處理擷取的鍵值項

                    inc     dwIndex

這個循環的結構和使用RegEnumKeyEx函數的循環是大同小異的。

要進行枚舉鍵值項的操作,父鍵的打開方式中必須包括KEY_QUERY_VALUE方式。

4.3   查詢鍵屬性

在枚舉子鍵和鍵值項的時候往往會遇到這樣一個問題:系統資料庫函數對鍵值資料的長度并沒有限制,在預留緩沖區的時候如果申請太大的記憶體比較浪費,申請太小的記憶體則無法枚舉成功,對于傳回的子鍵名稱和鍵值項名稱也是如此。那麼,究竟該留多大的緩沖區呢?其實在枚舉之前可以先用RegQueryInfoKey函數檢視一下鍵的統計資訊。

 RegQueryInfoKey函數傳回的資訊有:一個鍵下面子鍵的數量、鍵值項的數量、子鍵名稱和鍵值名稱字元串的最大長度及鍵值資料的最大長度等。根據這些資訊,就能友善地申請足夠大的緩沖區來保證枚舉成功。函數還能傳回建立子鍵時指定的類名和最後一次寫入子鍵的時間等資訊。

RegQueryInfoKey函數的用法是:

    invoke  RegQueryInfoKey,hKey,lpClass,lpcbClass,lpReserved,\

            lpcSubKeys,lpcbMaxSubKeyLen,lpcbMaxClassLen,\

            lpcValues,lpcbMaxValueNameLen,lpcbMaxValueLen,\

            lpcbSecurityDescriptor,lpftLastWriteTime

函數的參數比較多,但并不複雜,各參數的含義是:

●   hKey—指定要擷取資訊的鍵句柄,鍵的打開方式中必須包括KEY_QUERY_VALUE。

●   lpClass——指向一個緩沖區,用來傳回建立鍵時指定的Class字元串。

●   lpcbClass——指向一個雙字變量,調用函數時變量中必須放入lpClass指定的緩沖區的長度,函數傳回時在這裡放入傳回到緩沖區中的字元串長度。

●   lpReserved——保留參數,必須設定為0。

●   lpcSubKeys——指向一個雙字,用來傳回鍵中的子鍵數量。

●   lpcbMaxSubKeyLen——指向一個雙字,用來傳回所有子鍵中最長的名稱字元串長度,傳回的長度不包括字元串結尾的0字元。

●   lpcbMaxClassLen——指向一個雙字,用來傳回所有子鍵中最長的Class字元串長度,傳回的長度不包括字元串結尾的0字元。

●   lpcValues——指向一個雙字,用來傳回鍵下面的鍵值項數量。

●   lpcbMaxValueNameLen——指向一個雙字,用來傳回所有鍵值項中最長的名稱字元串長度,傳回的長度不包括字元串結尾的0字元。

●   lpcbMaxValueLen——指向一個雙字,用來傳回所有鍵值資料的最大長度。

●   lpcbSecurityDescriptor——指向一個雙字,用來傳回安全描述符的長度。

●   lpftLastWriteTime——指向一個FILETIME結構,用來傳回最後一次修改鍵的時間。

可以看到,除hKey外其他的參數都是指針,指向用來傳回資料的變量或結構,如果不需要傳回某種資訊的話,可以将對應的指針參數設定為NULL。另外,所有傳回的最長名稱字元串長度中都不包括結尾的0字元。

除了前面介紹的函數外,系統中還存在一些不常用的系統資料庫函數,比如可以用RegLoadKey和RegReplaceKey 函數從指定的檔案中恢複系統資料庫的子鍵資訊,也可以通過RegSaveKey函數将鍵資訊儲存到指定的檔案中。另外,可以通過RegConnectRegistry等函數操作遠端系統資料庫。對于這些函數,本節就不詳細介紹了。

---------------------------------------------------------------------------------------------------------------------------------------

    為了讓讀者不經修改就可以将這些子程式用在其他程式中,将這些系統資料庫子程式放在一個單獨的_Reg.asm檔案中并在主程式中使用include語句包含進來,檔案内容如下:

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

; 查詢鍵值

_RegQueryValue  proc        _lpszKey,_lpszValueName,\

                            _lpszValue,_lpdwSize,_lpdwType

                local   @hKey,@dwReturn

                mov     @dwReturn,-1

                invoke  RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,\

                        KEY_QUERY_VALUE,addr @hKey

                .if     eax == ERROR_SUCCESS

                        invoke  RegQueryValueEx,@hKey,_lpszValueName,NULL,\

                                    _lpdwType,_lpszValue,_lpdwSize

                        mov     @dwReturn,eax

                        invoke  RegCloseKey,@hKey

                .endif

                mov     eax,@dwReturn

                ret

_RegQueryValue  endp

; 設定鍵值

_RegSetValue        proc        _lpszKey,_lpszValueName,_lpszValue,\

                            _dwValueType,_dwSize

                    local   @hKey

                invoke  RegCreateKey,HKEY_LOCAL_MACHINE,_lpszKey,addr @hKey

                    .if     eax == ERROR_SUCCESS

                            invoke  RegSetValueEx,@hKey,_lpszValueName,NULL,\

                                    _dwValueType,_lpszValue,_dwSize

                .endif

_RegSetValue        endp

; 建立子鍵

_RegCreateKey   proc    _lpszKey,_lpszSubKeyName

                local   @hKey,@hSubkey,@dwDisp

                        KEY_CREATE_SUB_KEY,addr @hKey

                        invoke  RegCreateKeyEx,@hKey,_lpszSubKeyName,NULL,\

                                    NULL,NULL,NULL,NULL,addr @hSubkey,addr @dwDisp

                            invoke  RegCloseKey,@hKey

                            invoke  RegCloseKey,@hSubkey

_RegCreateKey   endp

; 删除鍵值

_RegDelValue        proc        _lpszKey,_lpszValueName

                    invoke  RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,\

                            KEY_WRITE,addr @hKey

                        invoke  RegDeleteValue,@hKey,_lpszValueName

_RegDelValue        endp

; 删除子鍵

_RegDelSubKey   proc        _lpszKey,_lpszSubKeyName

                local   @hKey

                        KEY_WRITE,addr @hKey

                        invoke  RegDeleteKey,@hKey,_lpszSubKeyName

_RegDelSubKey   endp

form:http://blog.csdn.net/cyg0810/article/details/7771902

繼續閱讀