我知道,當我寫下這個標題的時候,肯定一大波人會過來嘲諷:都什麼年代了,還XP?

道理我都懂,但是XP在中國依然百之十幾個點的佔有率。裡面最多的就是政企單位。這些電腦配置不好,比較古老了,而且關鍵是很多配套的軟體只有xp版本。讓他們升級系統?想法很好,但誰出錢找那些配套工具的廠商呢,更何況很多年久失修的軟體的廠商可能早就倒閉不見了,人都找不到。

哈哈,其實我說了這麼大堆,只是個藉口。真實原因是有不少公司願意出錢購買chrome支持xp的技術解決方案。我這纔有動力研究了一番。

進入正題。要支持xp,要解決幾個點:

補上或改掉xp下沒有的系統api。

修改部分api調用參數。否則xp下可能出錯。

修改部分流程,解決一些例如字體顯示問題、聲音播放不了等問題。

修改一些編譯參數,主要是為瞭解決TLS問題

整個做下來,如果對chromium非常熟悉,大概1個半月可以搞定。技術難度不算很大,最麻煩的是有很多小坑要去調試找原因,這是最蛋疼的。

先看第一點,這個比較好辦。把編譯好的文件拿xp下看下就知道缺了哪些api。

目前有三類:

1,讀寫鎖,條件變數相關。

這個是chromium裡面用的最多的xp下沒有的api。我的解決方案是自己擼了一套山寨版的api,介面和原型完全和windows原版一樣。例如AcquireSRWLockExclusive、AcquireSRWLockShared這些。參考了部分ReactOS的代碼(但要吐槽一下,那個代碼是有bug的。我跑起來後各種斷言錯誤)。過程比較麻煩的一點是一定要多測試,因為涉及到多線程的東西很容易藏隱藏的bug。

另外就是要誇一下windows的新api設計,讀寫鎖和條件變數都是共用了一套機制,調用了內核的NtkeyWaitxxx系列api。而且數據結構設計成只有一個指針大小的變數,利用位運算,小心翼翼的榨乾每個位的價值,而且不用event和其他鎖就搞定了,十分簡潔高效。這點我看其他人實現都是要用event什麼的模仿,顯得比較笨重了。

2,d2d、d3d系列。

這部分我直接砍掉了。不影響。因為d2d可以用GDI,D3D可以走angle或者swiftshader。這裡誇一下谷歌,居然把swiftshader收購了。swiftshader是一個很古老的軟體渲染器,以前是給windows或者機頂盒系統做軟渲染的。谷歌果然財大氣粗,為了能實現全平臺全硬體利用起3D加速,真是無所不用其極。給我的感覺就是為了造一部汽車,就先買了一座鐵礦。話說回來,chromium的渲染走的是opengl,但這個在windows下驅動支持的各種問題,所以谷歌會用angle把opengl轉發給D3D。如果D3D啟動有問題(這個很常見,很多垃圾顯卡對硬體加速支持的各種bug,為此谷歌做了個顯卡黑名單在chromium裏,碰到了關閉硬體渲染),就走純軟體渲染,也就是swiftshader。swiftshader和angle編譯出來都是libGLESv2.dll介面都一樣。哪個可用就用哪個,非常爽。

3,其他雜項類api。

這個很多,有GetIfTable2,有InitPropVariantFromCLSID、RaiseFailFastException、GetUserDefaultLocaleName、SHGetPropertyStoreForWindow等等。這些其實比較好辦,就是找到以前版本chromium是用哪個老api,然後替換回去就行。這類api太多了,就不在贅述。

把api全部替換完,只是萬裏長徵第一步。下一步就是修復各種流程上的bug。

下面挑幾個點講下。

首先是字體渲染。操蛋的谷歌把老GDI渲染全部幹掉,走DWrite渲染。更操蛋的是幹掉就算了,還把代碼都刪了。其實完全可以判斷下版本走哪個分支的。因為據我所知,dw在某些win7可能都還有點小bug。但谷歌是完全不管了。估計認為這些老系統沒必要支持吧。所以針對這個問題,需要找到當年的patch,再把gdi渲染補充回來。

然後是聲音播放不了。這個也是幹掉了老的wavexxxx系列api導致。補充回來即可

再然後是srcuildconfigwinBUILD.gn裏記得加上/Zc:threadSafeInit-

原因是xp的動態tls實現的不完善。需要全部關閉掉vs的動態tls機制。但這會帶來一個問題,就是有些地方可能有多線程競爭問題。這就需要一個個的修改。地方比較多,就不說了。

還有個點,就是如果要支持xp sp2,還會碰到個大麻煩,就是vs的xp工具集,編譯出來的runtime,是要依賴某個xp sp2沒有的api。這個我頭痛了幾天。最後想到個很簡單的辦法,就是所有dll都編譯成md模式,然後把concrt14.dll做一個IAT HOOK,重定向kernel32.dll到我寫的一個轉發dll裏。裡面再實現那個api即可。要支持sp1也可以用這種方式。但sp1實在太少人用了,我估計全國可能都沒有一千人,就不折騰sp1了。

此外,還有個大麻煩是沙箱。其實如果你對安全性要求不高,完全可以關閉沙箱。但我比較追求完美(其實是任務要求,蛤蛤),最後還是把沙箱跑起來了。沙箱裡面很多地方是根據系統來做hook。有些hook在xp下要去掉。

最後,還有些小問題要修復,例如netcertcert_verify_proc_win.cc裏要去掉ssl error的檢查,防止載入不了https網站、file_enumerator_win.cc要修改下調用參數等等。這些大家調試一遍就知道了,比較簡單。

整個過程基本就是這樣,當然還有非常非常多的細節需要拿代碼來講,這裡就懶得展開了。如果大家有興趣也可以私信我交流。

總之,這種事情是個苦力活(尤其是編譯和調試chromium,那叫一個慢啊,最後我實在受不了,直接花了幾千塊加內存加SSD)。不過看在金錢的份上,我忍了……zhic


推薦閱讀:
相關文章