硬體支援概況

在 Wine 中接取硬體,主要有兩種模式。

一、直接介接 Linux 的 API,像是 X11, SANE, V4L, ALSA 等等。目前少數實做的硬體介接模擬功能有圖形 (winex11.drv, winequartz.drv) 、音效以及輸入裝置 (keyboard, mouse, joystick, twain/sane) 等模擬層。另外 Wine 提供了 IoCode/Operation Code 轉譯功能,容許 Windows 程式直接存取硬體,這包含 Serial Communications[2] 以及 CDROM/ATAPI, TAPE 支援。

二、另外一種則是類似 NdisWrapper,直接載入並使用 Windows 驅動程式。目前而言負責載入 Windows 驅動程式的 NTDLL 中均未實做 NtLoadDriver, ZwLoadDriver 等函式細節,只宣告為 Stub Function. 因此即便驅動程式安裝程式可以順利安裝、註冊相關驅動程式 DLLs, Wine 也不會載入這些驅動程式。

目前 Wine (1.3.19) 並沒有模擬載入底層驅動程式

Smart Card Support

Smart Card 支援問題是最常被詢問的問題之一,依據 MSDNSmart Card Subsystem 設計,可以分為以下數層

  • Smart Card Service Providers
  • Resource Manager
  • Specific Smart Card Reader Driver
  • Smart Card Reader Helper Library

驅動讀卡機是最基本的功能。參考 Microsoft Class Drivers for USB CCID Smart Cards結構說明,驅動程式有兩類,一是 CCID 相容硬體或 USB 廠商所提供的驅動程式。而其上應用程式可用 Smart card resource manager (winscard.dll) 來下達 PC/SC 指令。

如上所述,Wine 並不會載入驅動程式。winscard.dll 目前也只是 stubbed functions.

不過 IDRIXMounir IDRASSI 開發了介接 PCSC-Lite/pcscd,使 Smart card resource manager 可以透過 PCSC-Lite 提供 PC/SC Services.

USB Support

理論上,user-mode 的 USB 驅動程式也可以透過轉譯直接存取 USB 設備,只要該軟體未使用 ntoskrnl.exe, hal.dll, usbd.sys 以外的功能。目前官方 Wine source tree 只在 usbd.sys 中實做查詢 USB Devices 功能。

Etersoft 的 Alexander Morozov 則已利用 libusb 實做 USB 功能,提供一些需要使用 USB hardware token 進行硬體保護的軟體使用。這些功能未整合到 Wine 主程式。相關程式碼位於 ftp://ftp.etersoft.ru/pub/people/amorozov/usb,使用時需要手動在 registry 中加入 vendor id/product id 設定

簡介

自從 Wine 1.0 2008 年六月釋出之後,便開始以兩、三周為週期,開始固定的釋出新版。Wine 是針對 POSIX 相容的作業系統所設計,目前 Wine 已經被移植許多平臺上,除了 Linux 外,也可以在 Solaris, FreeBSD, x86 版本的 Mac OS 上使用。經過長期的開發與社羣支援,目前在 Appdb 中已有超過一萬六千個軟體測試報告,其中有將近 3000 筆是屬於高度可用 (Platinum List) 的軟體。

在 Appdb 中仍有大量的軟體存在執行的問題,造成使用困擾,甚至無法使用。這與 Wine 的設計有關,Wine 跟 Dosboxzsnes 不同,既不是模擬器,也不是虛擬機器。它是以軟體方式模擬出 Windows® 作業系統所需的軟體架構 (Software Stack),理論上只新增一層 software layer 會比虛擬化成本低廉。

雖然 Wine 計劃經過十幾年發展,但是市面上目前為止沒有任何書籍介紹 Wine 及其程式架構,開發者只能參考少數幾份線上文件Wiki 來理解 Wine 的程式架構。本文稍加介紹 Wine 的相關設計。

軟體架構與初始化簡介

根據 Wine Developer’s Guide,軟體架構如下

要在 UNIX 中模擬一個 Windows® 作業系統,有許多差異需要克服,且 Wine 為了開源授權的合法性,並不對 Windows® 本身進行反組譯,而是用黑箱測試法所開發出來,並參照開發文件逐步實做所有的 Win32 APIs。問題在與 Win32 API 文件並沒有完全開放,不同版本作業系統間,也有些微行為上的差異。然而 Windows® 有著為數不少缺乏文件的 APIs. 甚至錯誤的 API 反應等等,Wine 都需要一一的實踐。加上仍有一些未開放的低階 API,以及一些缺乏文件的協定或設計,Wine 計劃可以說是以血淚走過來的開發工作。

以 Wine 模擬 Windows® 最重要的功能之一就是 Wine server, 它基本上是提供作業系統核心模擬的功能,負責 Inter-Process Communication (IPC), synchronization 與 process/thread management 等等工作。Wine server 是一個獨立的程序,每次啟動任何 Windows 程式前,它會優先被叫起。若出現了什麼問題,也要確保砍掉 (kill) 它後,才能乾淨的重新執行。

而在 Wine preloader 載入 .COM / NE / DLLPE 前,由於每個程序都將使用自己的記憶體空間,Wine 要先依照不同的執行檔格式需求建立 Memory layout,為了能夠在 Linux 中製造出跟 Win32 一樣的記憶體位置,除了試圖將相關的 DLLs 載到正確的記憶體位置 。Wine 也要避免 dynamic linker 預先把 Wine 所需的函式庫配置 (mapping) 到錯誤的位址,於是修改預設的 ELF 初始化程序,以 syscall 將相關的函式庫配置到正確的位置。

另外在 Windows® 中,每個 process 或 thread 有一塊資料結構稱做 Environment Block (PEB – Process Environment block or TEB – Thread Environment Block),這些資料中包含了 TLS slots, message queue, error code (SEH, Structured Exception Handling) 等等,這塊資料結構提供了 Windowing, Threading 以及錯誤處理等所需資訊。在建立 PEB/TEB 後,才初始化 process heap,載入執行檔,依照執行檔指示建立 stack,最後才將控制權交給執行檔的 EntryPoint

上述工作均由 NTDLL/KERNEL32 處置,NTDLL/KERNEL32 也會負責傳遞執行序資訊給 Wine Server. 至於啟動後的 Graphics Device Interface 與 X11 的圖形界面轉換由 GDI32 處理。 USER32 則實做 Windowing and Messaging subsystem. 像是一些狀態列顯示等功能,都已經實做完成。

例外一個值得一提的是錯誤處理的機制,在 Windows 上 exception handling 的方式比 Linux 中複雜許多。以 STATUS_ACCESS_VIOLATION / Segmentation fault 為例子,在 Linux 中只是吐一個 SIGSEGV 錯誤,在 Windows 中則會吐出一個 Exception,還會帶上錯誤位址 (faulting address) 等資訊,也可在 SEH 中指定 handler function 來處理錯誤事件。在 Linux 中,並沒有所謂的 system exception interface,Wine 為了模擬出 Windows 的錯誤處理機制,是將 exception 轉為 signal 來模擬。

除了上述幾個主要的核心程式外,Wine 也實做了許多軟體原件,像是 CryptographyDirectShow FrameworkDirect3D shader -> GL mapper, Network protocol stacks, DirectSound (ALSA, OSS), DirectInput, DirectShow, DirectDraw, Direct3D 等等。甚至連 MSHTML / IE 都已經以 Gecko Engine 實做。

目前 Wine 在編譯時 已經支援 64 bits 也支援 WoW64 來跑 32 bits 程式。

開發模式

Wine 是用 git 管理,任何人都可以隨意 commit patches, test cases 到 patches mailing list 上,經過公開的 code review 後就會再下一次 release 中被合併。如果有任何技術上的疑問,則會被提到開發論壇進行討論,有歧異或暫時無法解決的問題,會被彙整到問題追蹤系統中,是相當透明開放、平等的開發模式。

由於 Wine 是完全重製 Win32 APIs, 且是黑箱測試開發模式,難免會出現修東壞西的悲慘現象。為了避免舊問題在新版中重現,Wine 設計了一套測試方法,來作 Regression Testing,藉此確保軟體品質。不過這個方法只能測試功能性的問題,難免還是避免不了一些圖形界面的變異。

Wine 計劃授權原本是採用 MIT,但在市場高度期待,出現了數家不同的公司為不同的平臺提供服務,社羣為了避免多家營利公司商業競爭造成開發資源分散,2002 三月後已經改成 LGPL.

也由於授權開放,Wine 的開發成果如 D3D 也被整合到 VirtualBox 中。另外像是想重新實做開源Windows® XP/2003 的 ReactOS 計劃,其軟體層也使用 Wine Libraries。一般開發者也可以用 Winelib 作為跨平臺的函式庫,在 Linux 上將程式移植到 Win32 平臺上。 (類似 mingw)

目前在 Linux 上,Wine 對於音效支援,只有 OSS 與 ALSA。社羣已有 PulseAudio,但由於開發團隊策略上的考量,希望朝向支援 OpenAL 的方向,因此尚未被整合到官方版本。至於在 MacOS 上,其圖形界面驅動程式還是 winex11.drv ,需要使用 X Server 才能使用,OS X 上 的 Quartz 在 2010 時曾經有一部分實做,但已停止開發,功能也暫時無法使用。

使用現況

目前 Wine 計劃處在一個尷尬的狀態。Wine 已經完成很大部分的 Win32 Libraries. 但仍有尚未實做的部分,為了能夠順利使用,使用者仍必須使用 Microsoft  函式庫 (以下稱為 native)。又因為已高度實做 Wine 的函式庫 (以下稱為 build-in)往往有不相容 native 函式庫的問題。也因此使用者現階段而言並不容易只使用一套 Wine 設定來套用所有的 Win32 應用程式。

結局就是造成使用 Wine 執行 Win32 程式時,常需要搭配不同的函式庫。例如這一版本需要 native 的 yyy.dll 配合 build-in 的 zzz.dll,另外一套軟體卻可以只用 build-in dll 執行。

如果軟體出現相容性問題,不再像初期一樣,只要靠換 Win32 Libraries 就可以排除,因為每個原生函式庫有高度相依性。由於安裝軟體時,常常需要用到一些 Microsoft 的程式碼,或者偶爾也許要微調一下 Windows Registry Keys 才能順利安裝。因此常需要透過特定到程序才能成功安裝,因此網路上有許多第三方工具。最常用也最知名的就是 Winetricks.

雖然 Wine 已經開始有些像是 PicasaTeamViewer 等等的商用軟體應用,以 Wine 直接提供原生 Win32 程式給 Linux 平臺。但他們的做法,都是隨贈一套已調整完成的 Wine 系統。

由於 Wine 執行環境可以安裝在不同的 sandbox,因此系統中可以有多套不同的 Wine 同時執行。這種技巧叫做 bottle. 使用者可以透過不同的環境變數,來設定 Wine 所要使用的設定檔路徑,載入 Win32 程式時,也會啟動不同的 wine server,不同的 bottle 會是獨立的執行環境,可作不同設定或安裝不同版本的函式庫。

使用者可以透過環境變數或第三方工具,來測試配置各種不同的軟體,在 Linux 上可以使用今年剛發表的 wibom。在 MacOS 平臺上,由於編譯的困難性,可以使用 Wineskin 之類的工具來協助安裝管理 Win32 系統。此外,像是 CrossoverBordeaux 等公司也提供商業版的友善界面與預先調整好的安裝工具等服務。

Appdb 上已經有眾多程式資料,何不試試能否在 Linux 執行看看你最喜歡的 Windows 程式呢? 🙂

趁著前陣子 WoW 在超商特價每張遊戲主程式光碟 9 元,且可申請一個月免費試玩時,拿了一份回來。試著在 Linux 上以 Wine 安裝。

安裝過程不時有選單無法正常顯示中文,不過大致都不妨礙安裝。比較麻煩的是,由於 3D 顯示不正確的緣故,有許多選單根本無法辨識,必須稍加猜測才能成功安裝。安裝好之後,光是 WoW 整個軟體就佔了 9.2G.

軟體裝好,為了顯示卡的問題花了不少時間偵錯。我的顯示卡是 Intel Corporation Mobile 945GM/GMS, 943/940GML Express Integrated Graphics Controller [8086:27a2] (rev 03),Xorg driver 則是 xserver-xorg-video-i810 2:2.3.2-2+lenny2。

透過 glxinfo 查詢 direct rendering 是可用的。

$ glxinfo | grep rendering
direct rendering: Yes

glxgears 的速度也大約在 935 FPS.

$ glxgears
4678 frames in 5.0 seconds = 935.525 FPS
4709 frames in 5.0 seconds = 941.694 FPS
4658 frames in 5.0 seconds = 931.461 FPS

945GM 的效能本來就不特別好,光是在 Windows 下就頗吃力,何況是在 Linux/Wine. 很多人建議更改 WTF/Config.wtf,將 gxApi 設定為 OpenGL,具聞由於 WoW 預設使用 DirectX,在 nVidia 顯示卡上運作時常不正確。

不過我剛裝好,以預設 DirectX 啟動時,連登入畫面都無法顯示,馬上就退出程式。改以 OpenGL,雖然可以進入畫面,但是登入到主場景時,會有 Mesa 7.0.4 implementation error 的錯誤,並退出軟體。

Mesa 7.0.4 implementation error: i915_program_error: Exceeded max nr indirect texture lookups

最後的解決方法是改為使用 DirectX 啟動,並修改 Xorg.conf 的 Device section 將預設的顯示卡共享記憶體改大,

Option          "LinearAlloc" "65536"

於是就可以順利進行遊戲。但是效能其差無比,經過測試,遊戲下速度只有 7-2 FPS,根本不堪使用,要玩遊戲還是找張好顯卡吧。

上次用 Wine 1.0-rc1 測試了一下 KKBOX,由於上次測試時使用 Wine 實做的 ShDocVwMsHtml 等元件。由於無法透過內嵌的網頁登入,因此大部份某些功能無法順利使用。

但你若先將 Microsoft Media Player 與 Microsoft Internet Explorer 裝進 Wine 中,就可以順利執行起 KKBOX 了!安裝過的過程十分繁複,因此我其實是透過 wine-doorsIEs4Linux 才安裝成功。由於 IEs4Linux 預設會安裝一個獨立的 wine 系統,並把軟體預設安裝 $HOME/.ies4linux,因此必須稍加修改 IEs4Linux,以便強迫它安裝到正確的 wine 目錄。然後再重新安裝執行一次 KKBOX 即可成功啟動啦。

使用狀況倒是沒有甚麼問題,可聽取線上串流,離線下載由於尚未購買月卡,還無法測試。目前的一點點小問題是,左邊的選單還是亂碼,一般下拉式選單倒是沒有問題。此外嵌於軟體首頁的 Flash-based MV 會有嚴重閃爍的問題。

這是在 wine 1.0-rc1 與 wine 1.0-rc2 上測試。待有善心人士整理 Step by Step HOWTO. 或者乾脆整理成單鍵安裝程式吧。

這個月底,將是 Wine 計畫成立十五週年!Wine 也將終於在十五年後釋出 1.0 版 !!

這兩三年,由於 Google 的積極參與 (Google 的其中一個產品 Picasa for Linux 是基於 Wine 所開發),許多程式如 Adobe PhotoshopAdobe Flash 都已經可以在 Wine 上面成功執行,相容性已經有大幅度的改善

因此我也試著再度玩起 Wine,試著裝了 wine, wine-doorsIEs4Linux,幾個主要的軟體、元件如 DCOM 98, MSXML 3/4, GDIPlus, Visual C++ runtime library 6, Internet Explorer, Micrsoft Media Player 9 等倒是沒有問題。

前些時候裝了 Sling Player, 以及 Macromedia 的 Dreamweaver 8, Fireworks 8 (可透過 winedoors 直接安裝) 大致上也可以運作。

接下來又測試一些台灣使用者常用的 Windows 程式,如 Foxy, GOGOBOX 與 KKBOX 等,則碰了些無法使用的障礙。雖說安裝都沒有問題。

首先是 Foxy (請別作道德勸說,這純粹是測試相容性),安裝時提示畫面,中文會顯示亂碼,但是可以成功的安裝,且系統也會自動設定啟動選單。但是啟動後,系統會出現以下錯誤訊息:

Unhandled exception: page fault on read access to 0x00000020 in 32-bit code (0x00422cb4).

過了啟動畫面後,無論如何都無法進到主程式,只好先回報到類似的問題上,稍後再求解。

另外一個測試的軟體是 GOGOBOX,安裝也沒有任何問題,也可以啟動主程式後登入系統。也可以進行「累積里程」的行為。但是 GOGOBOX 的使用是先從網頁上下載安裝檔,然後在點選網頁上得連結時,透過 ActiveX 元件將下載網址傳給主程式。

在進行點選連結時,Internet Explorer 可以叫起 GOGOBOX 主程式,但是軟體會不停的提示「GOGOBOX 檔案傳送管理員沒有設置好,或是新版本已問世。要現在設置/更新嗎?」,卻始終無法正確的把下載檔案傳進 GOGOBOX 主程式。殘念。

另外一個測試的軟體則是 KKBOX,安裝的過程中也沒有異狀,執行後可以進到主程式,雖說選單是亂碼。但是由於無法退出軟體啟動時的 Panel,也就是中間的「註冊」、「登入」提示畫面。那個畫面是嵌入一個瀏覽器元件,理論上按下「註冊」,系統應該開啟一個註冊網頁,若按下登入,系統應該提示一個登入對話視窗。

然而,此時按下註冊或其他網址,軟體毫無反應。應該是 shdocvw 未實做完全的緣故。若按下「登入」畫面,軟體則出現 “Unhandled exception: page fault on read access to 0x0100bbf8″,然後退出視窗。

要讓這些在中文微軟視窗使用者流行的軟體在 Linux 上順暢執行,還有許多功夫要下阿。

為了可以在 GNU/Debian Linux 上看 HBO, 非凡電視台跟一些台灣的節目,只好重新再裝了 Wine。以便可以收看裝在高雄親戚家 Sling Box 轉出來的視訊。

參考 How To Run SlingPlayer on Linux OS 一文,步驟十分簡單。

  • 先裝了 Debian sid 的 wine 0.9.59-1
  • 再裝了SlingPlayer Dependencies package 中的檔案,把 qcap.dll, quartz.dll, msxml3.dll 與 msxml3r.dll 丟進 windows\system32。
  • 然後 regsrv32.exe 註冊 msxml3.dll 檔。還得將 msxml3, qcap, quartz 設定為 strictly native。

另外一個問題是執行時,wine 會抱怨 GdipDrawPieI, GdipDrawPolygon unimplemented,顯然是 Wine 的 GdiPlus 實做尚未齊全,解決方法是先偷 DLL-Files.com 上得檔案來用,丟進 system32 後就可以執行沒有問題了。

SlingPlayer 成了少數我會再 Linux 上執行的私有軟體之一。要不是找不到成本低廉的多媒體個人電腦,我才不想用Sling Box 呢。

附註: 在 Windows 上測試時,出了 Error: 0x80072AFC,結果發現是網路斷線,花了我五分鐘才查出來
(If you encountered Error: 0x80072AFC with SlingPlayer, check your network setting and cable. It’s probably beaause SilingPlayer can not reach SlingMedia’s server.)