原文:http://hi.baidu.com/pwcrab/blog/item/8fce6003ef4396e808fa9394.html
我們的程式運作時需要設定一些環境變量,但是在某客戶那裡,
使用者環境中可擴充值 %SystemRoot% 沒有被展開。 調查發現原因如下:
系統資料庫中有兩種類型的鍵:
REG_SZ
REG_EXPAND_SZ
如果上面一種鍵的值中存在可擴充占位符%xxx%的話是不會被解釋的
但是如果下面一種鍵的值中存在%xxx%的話該部分會被系統解釋。
以上的描述可以在相關資料中查到。
系統環境變量存放位置
HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001/Control/Session Manager/Environment
将TEMP TMP的鍵類型修改為REG_SZ,值設定為 c:/testProj/service/%SystemRoot%
發現該值無法被展開。是以問題的已查明。
為什麼使用者系統的存放系統環境變量的健值類型會被修改為REG_SZ(預設的都是REG_EXPAND_SZ型)
,這個原因不明,但是,由相關經曆如msn更新導緻系統中某個鍵類型變成REG_SZ
導緻我們的軟體無法安裝。
系統資料庫鍵類型REG_SZ和REG_EXPAND_SZ引發的BUG(續)--“CurrentControlSet”和“ControlSet00?”
原文: http://hi.baidu.com/pwcrab/blog/item/c52aa39ba6ca6db1c8eaf471.html
這個問題原因查明了,确定修改方案時又遇到了新的問題。
一般機器中,控制系統啟動的有三個系統資料庫項,在HKEY_LOCAL_MACHINE/SYSTEM下,存在着 CurrentControlSet、ControlSet001、ControlSet002這三個子鍵,他們包含的内容似乎一樣,而且修改一個其它也 會發生變化,那麼到底修改哪一個才是合理的呢。那麼就讓我們首先了解這三個系統資料庫項吧,下面的内容來自于: bbs.mcafeefans.com.cn/viewthread.php?tid=1482106
一、先了解一下控制系統啟動的三個系統資料庫項
在HKEY_LOCAL_MACHINE/SYSTEM下,存在着CurrentControlSet、ControlSet001、 ControlSet002這三個子鍵,他們是與系統啟動有關的三個項,裡面記錄着作業系統配置的資訊,包括了系統控制、驅動、服務等資訊。
ControlSet001是系統預設的配置資訊,但是為了避免序号混亂,windows啟動時會從ControlSet001複制一份副本,作為操作系 統目前的配置資訊,也就是CurrentControlSet。那麼ControlSet002是什麼呢?當作業系統每成功啟動一次,都将 CurrentControlSet和ControlSet001中的配置資訊複制到ControlSet002中,ControlSet002就成了 “最近一次成功啟動的配置資訊”,也就是啟動時按F8之後,你所看到的選項“最後一次正常啟動的配置”。
二、為什麼編寫規則禁止對HKML下“/SYSTEM/CurrentControlSet/Control/SafeBoot/**”作寫入、建立、删除之後,仍然可以在該項下寫入、建立、删除鍵和值呢?
根據為什麼水哥的國慶規則根本鎖不住安全模式的系統資料庫項帖 中麥粉_幽芸提供的資訊可以知道,如果我們編寫規則禁止對HKML下“/SYSTEM/**/SafeBoot/**”作寫入、建立、删除之後,HKML /SYSTEM/CurrentControlSet/Control/SafeBoot/下就不能寫入、建立、删除了,并且出現如下日志:
2007-10-28 8:01:36 已由通路保護規則禁止 LYM/hp C:/WINDOWS/regedit.exe /REGISTRY/MACHINE/SYSTEM/ControlSet001/Control/SafeBoot/新值 #1 使用者定義的規則:444 已阻止的操作: 建立
明顯的能看出,咖啡禁止操作是對HKML/SYSTEM/ControlSet001/Control/SafeBoot/鍵而不是對HKML/ SYSTEM/CurrentControlSet/Control/SafeBoot/鍵的。根據這些資訊,結合上面第一點中所說我作如下猜測: ControlSet001是真的系統配置資訊,而CurrentControlSet隻是ControlSet001的一個鏡像。 我們要修改啟動配置,實際上修改的是ControlSet001,當我們似乎是在CurrentControlSet下寫資訊時,實際上首先寫的是 ControlSet001,又或者在CurrentControlSet下寫入的資訊隻在記憶體中先作緩存,然後寫入ControlSet001,而實際 并未在CurrentControlSet下寫入資訊;而後CurrentControlSet作為鏡像映射ControlSet001内的資訊,隻有讀取的操作,于是CurrentControlSet被更新了,得到了面向使用者的配置資訊,因為隻有讀取,是以也不存在被規則阻擋了。
三、如何解決問題?
當然,上面的隻是我的猜測。而現在的實際情況就是,根據幽芸提供的日志,我們清楚看出,當我們在CurrentControlSet下寫資訊的時候,阻擋 ControlSet001操作的規則報警了,我們在CurrentControlSet下寫資訊的時候,作了在ControlSet001下寫資訊這一 操作。
無論你是否認同我的猜測,問題都将以下面的方式得到解決:
編寫系統資料庫保護規則,命名為“保護安全模式免被破壞”,包含程序為*,要保護的項是HKLM下的/SYSTEM/ControlSet001/Control/SafeBoot/**,阻止的操作為寫入、建立、删除。
然後/SYSTEM/CurrentControlSet/Control/SafeBoot/下的修改将不能實作了。
四、補充
在網上找到的資料,大家請看,關于使用了“最近一次的正确配置”之後會發生的事情:
HKLM/system系統資料庫項中還有一個select的子項,其中有幾個整數鍵,分别是:
“Current”資料項目表示 Windows XP 在這次啟動過程中使用的控件組。
“Default”資料項目表示 Windows XP 在下次啟動時将使用的控件組,它與這次啟動使用的控件組相同。
“LastKnownGood ”資料項目表示您在啟動過程中選擇“最近一次的正确配置”時 Windows XP 将使用的控件組。
“Failed”資料項表示 Windows XP 在其中儲存失敗啟動産生的資料的控件組。 此控件組在使用者第一次調用“最近一次的正确配置”選項之前并不實際存在。
對應上面四個值,系統預設時其順序是:001、001、002、無;
第一次使用“lastknowngood”後:002、002、003、001
第二次使用“lastknowngood”後:003、003、004、002(之前的備份001被002覆寫掉,001組消失)
第三次使用“lastknowngood”後:004、004、001、003(002被003覆寫,而當004要生成新的“lastknowngood”時,001正好可用,于是001重生,002消失)
當大家使用了“最近一次的正确配置”之後,ControlSet001被認為時錯誤的配置被封存起來(001記錄在在Failed中,不使用了),而用ControlSet002啟動,相應生成ControlSet003作為“最近一次的正确配置”,002取代了001的位置,003又取代了002的位置。按上面所說,這些ControlSet會循環使用,最多也就4個,分别為001、002、003、004。
為了改善保護效果,避免因為使用“最近一次的正确配置”之後,保護ControlSet001就不起作用(因為002取代了001的位置了),是以對保護的項作更改,更改成:要保護的項是HKLM下的/SYSTEM/ControlSet00*/Control/SafeBoot/**。這樣就可以了。
五、關于ControlSet001、ControlSet002以及CurrentControlSet
下午跟笑笑讨論了很久的問題,關于“CurrentControlSet”和“ControlSet00?”這兩個鍵,究竟他們是怎樣的關系呢?為什麼更 改ControlSet001的内容和權限,CurrentControlSet就會作同樣的修改呢?反之也是這樣,為什麼呢?
晚上我在微軟官網找到了些資訊,相信大家會有興趣的,位址是http://support.microsoft.com/kb/100010/zh-cn。
當然,内容都是英文……那麼我對部分重要資訊作一下解釋。
大家應該會看到這麼一段:
引用:
ControlSet001 may be the last control set you booted with, while ControlSet002 could be what is known as the last known good control set, or the control set that last successfully booted Windows NT. The CurrentControlSet subkey is really a pointer to one of the ControlSetXXX keys.
說的是,ControlSet001是你最後 成功啟動的控制配置,而ControlSet002就是最後一次正确的控制配置,或者說是最後一次使作業系統成功啟動的控制配置。 CurrentControlSet呢,就是一個指向其中一個ControlSetXXX(XXX=001或002或003或004)的一個鍵(pointer=指向者)。
那麼為什麼CurrentControlSet寫入不被咖啡阻擋就清楚了,下面說說我的了解,不過未必正确,劍榮說的很有參考價值,因為我也不明白他說的是什麼,請劍榮解釋一下了。
我對“在CurrentControlSet寫入不被國慶版預設規則阻擋”的了解:因為我們在CurrentControlSet上的操作,其實其實是指 向ControlSetXXX(根據情況不痛,XXX會不同,原因請參考第四點),在CurrentControlSet上的寫入操作,将被指向 ControlSetXXX,在ControlSetXXX寫入以後,CurrentControlSet将讀取ControlSetXXX的資訊,因為 CurrentControlSet是指向ControlSetXXX的,他就好像一個鏡像,顯示ControlSetXXX裡的東西。
那麼為什麼要設定CurrentControlSet鍵呢?這麼麻煩還要指向。我在http://support.microsoft.com/kb/308559/zh-cn上找到了答案,這次是中文的了。
Windows XP 提供 ControlSet001 的副本,名為 CurrentControlSet,這樣,應用程式就不必考慮在啟動過程中用幾号控件組。
引用:
啟動的資訊并不是每次都是ControlSet001的,而根據你系統是否有出現過錯誤啟動的情況,還可能會是ControlSet002、ControlSet003或ControlSet004, 而CurrentControlSet作為對本次正确啟動的控制配置的指向者,使得應用程式不必考慮在下一次啟動過程中用的是幾号控件組,友善了程式,應 用程式不必根據情況自己判斷應該寫入哪号的ControlSet,而是向CurrentControlSet寫入資訊就可以了,因為 CurrentControlSet會履行指向的職責。
