WinCE恢復默認HIVE註冊表的方法

當Wince使用了HIVE註冊表後,每次用戶的註冊表改動將得到保存,但是在某些應用場合需要將註冊表還原成爲出廠的默認設置,通常要求能夠在AP中通過點擊一個按鈕來實現這種clean boot。使用我前面的文章的方法配置的HIVE系統註冊表和HIVE用戶註冊表分別保存在/HDD/Document and Setting/system.hv 中和 /HDD/Document and Setting/default/user.hv中,每次系統在啓動到加載HIVE系統註冊表之前都會先檢查保存在/HDD中的文件的存在和合法性,如果不滿足要求系統將會用binfs中的缺省文件創建新的system.hv和user.hv文件於/HDD中,根據這個特性我先試圖在WinCE運行起來後刪除這兩個hv文件,但是由於WinCE已經事先加載了它們,刪除被禁止,只有採用其他的方法。
重新研究了基於HIVE註冊表的WinCE的啓動過程發現,系統在完成了第一階段也就是加載完了boot.hv+binfs之後和加載系統HIVE註冊表之前,filesys.exe都會調用OEMIoControl來查詢是否需要清除保存在block設備上的hv文件,其CODE代碼爲IOCTL_HAL_GET_HIVE_CLEAN_FLAG,它的輸入參數lpInBuf固定爲HIVECLEANFLAG_SYSTEM或HIVECLEANFLAG_USERS,filesys.exe會分別用這兩種參數調用兩次IOCTL_HAL_GET_HIVE_CLEAN_FLAG,第一次用HIVECLEANFLAG_SYSTEM來問OEM是否需要清除system.hv,第二次用HIVECLEANFLAG_USERS做參數來查詢是否要清除user.hv,如果返回的lpOutBuf中的值爲TRUE則做清除操作,如果爲False則保留block設備上的註冊表文件。
所以我們要做的就是實現和IOCTL_HAL_GET_HIVE_CLEAN_FLAG相對應的OEMIoControl源碼(假設由OALIoCtlBGetHiveCleanFlag()這個function來實現),加入對是否需要清除註冊表的判定條件並告知filesys.exe即可。現在棘手的問題是如何讓AP通知OALIoCtlBGetHiveCleanFlag()該不該清除註冊表,因爲OALIoCtlBGetHiveCleanFlag()只能在指定的時候由filesys.exe去調用,AP的運行只能在OALIoCtlBGetHiveCleanFlag()運行完之後。
後來終於想到可以使用共享內存空間來實現,我們可以在物理內存中保留出一塊不會被其他模塊佔用的空間,在這個空間放置兩個BOOL變量分別來保存system和user的hv清除的標誌符,缺省它們都爲False,OALIoCtlBGetHiveCleanFlag()讀到Flase則認爲不清註冊表,AP在需要的時候將這兩個標誌符置爲True,接下來就是要重新啓動到OALIoCtlBGetHiveCleanFlag()函數被調用的地方,由於標誌符號是保存在RAM中的,斷電會丟失,還好有個方法可以讓系統復位而又能保存RAM中的內容,那就是Reset,所以讓AP在設置完標誌符後馬上調用Reset指令就可以完美實現Clean boot了。
提供相關代碼作爲參考:
BOOL OALIoCtlBGetHiveCleanFlag(   // 一般在IOCTL.C中實現
       UINT32 code, VOID *lpInBuf , UINT32 nInBufSize, VOID *lpOutBuf,
       UINT32 nOutBufSize , UINT32 *pOutSize)
{
BSP_ARGS *pArgs = (BSP_ARGS*)IMAGE_SHARE_ARGS_UA_START; //保留的共享RAM空間的虛擬地址
if (!lpInBuf || (nInBufSize != sizeof(DWORD)) || !lpOutBuf || (nOutBufSize != sizeof(BOOL)))
 {
     SetLastError(ERROR_INVALID_PARAMETER);
     return FALSE;
 }
else
{
     DWORD *pdwFlags = (DWORD*)lpInBuf;
     BOOL *pfClean = (BOOL*)lpOutBuf;
    if (*pdwFlags == HIVECLEANFLAG_SYSTEM) {
          if(*pfClean = pArgs->bcleansystemhive) //判斷是否清除system.hv
                   RETAILMSG(1, (TEXT("OEM: cleaning system hive/r/n")));
               else
                   RETAILMSG(1, (TEXT("OEM: Not cleaning system hive/r/n")));
          *pfClean = pArgs->bcleansystemhive;
               pArgs->bcleansystemhive=FALSE; //一定在執行完後設置爲默認的false否則常規reset都會清空註冊表
     } else if (*pdwFlags == HIVECLEANFLAG_USERS) {
     if(*pfClean = pArgs->bcleanuserhive) //判斷是否清除user.hv
                   RETAILMSG(1, (TEXT("OEM: cleaning user hive/r/n")));
               else
                   RETAILMSG(1, (TEXT("OEM: Not cleaning user hive/r/n")));
                 *pfClean = pArgs->bcleanuserhive;
                   pArgs->bcleanuserhive=FALSE; //restore to default
     }
 }
return TRUE;
}
 
AP中的實現代碼如下:
Void On_CleanBoot()
{
BSP_ARGS* pArgs = (BSP_ARGS*)IMAGE_SHARE_ARGS_UA_START; //保留的共享RAM空間的虛擬地址
pArgs->bcleansystemhive=TRUE;         //設置system.hv清空標誌符
pArgs->bcleanuserhive=TRUE;            //設置user.hv清空標誌符
ReSet();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章