Windows 採用保護模式,應用程式無法直接存取硬體資源(I/O 埠、實體記憶體、中斷)。嘗試在 Ring 3 直接執行 IN/OUT 指令或寫入實體位址會觸發一般保護錯誤 (GPF) 甚至藍畫面。DLL 雖同樣運行於 Ring 3,但因可載入裝置驅動程式協助、或利用特定系統服務,成為實現受限硬體操作的常見跳板。本文探討 DLL 在硬體存取中的角色與實作策略。
純用戶模式 DLL **無法** 直接執行特權指令。實際解決方案通常包含:
DeviceIoControl 向驅動程式發送 IRP,驅動在 Ring 0 執行實際 I/O,再將結果回傳。這是正規、穩定、安全的做法(如 inpout32.dll 搭配 inpoutx64.sys)。VxD 或特定系統服務繞過保護,但 NT 核心嚴格禁止,現代作業系統已封鎖此類路徑。CreateFileMapping 搭配 \\.\\PhysicalMemory(需高權限且受限),或使用 MmMapIoSpace(需驅動)。// HWAccess.h
#ifdef HWACCESS_EXPORTS
#define HWAPI __declspec(dllexport)
#else
#define HWAPI __declspec(dllimport)
#endif
extern "C" {
HWAPI BOOL Initialize(); // 載入驅動、開啟裝置
HWAPI void Cleanup(); // 關閉裝置、卸載驅動
HWAPI BYTE ReadPortByte(WORD port);
HWAPI void WritePortByte(WORD port, BYTE value);
HWAPI BOOL ReadPhysicalMemory(DWORD physAddr, LPVOID buffer, DWORD size);
HWAPI BOOL WritePhysicalMemory(DWORD physAddr, LPCVOID buffer, DWORD size);
}
CreateFile("\\\\.\\MyDriver", ...) 取得驅動控制代碼。CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS))。{ WORD port; BYTE value; }。__stdcall,確保跨語言相容。Initialize/Cleanup 管理驅動生命週期,避免重複載入。IN/OUT,除非確定運行於 Win9x/虛擬化環境。WinRing0, InpOut32)而非自行造輪子。DLL 是連結用戶模式應用與核心模式驅動的橋樑,善用它能讓硬體存取程式碼模組化、可維護、跨語言複用,但核心風險永遠在驅動端,請謹慎設計。