跳到主要內容

發表文章

目前顯示的是有「DLL」標籤的文章

Windows DLL - Sign Certificate的問題

Problem SHA1在2016後還可以使用嗎? Current Status 經過查詢一些文章後,目前得知: 如果timestamp在2016年以前可以繼續使用,但Win7與Win2008只能用到2020年1月14號。 2016後建議使用SHA2,除了Win2003以前的系統。 目前測試Win10也可以使用2016年前sign的SHA1 driver。 Reference Practical Windows Code and Driver Signing Deprecation of SHA1 code signing certificates on Windows 其它 Sign Driver後無法正常啟動的問題 - SHA2

Windows DLL - 建立描述Event的DLL

Problem 一般應用程式在發送NT Event Log後,很可能會在EventLogViewer中,出現Event ID找不到對應描述的問題。 這是因為EventLog Viewer會載入以下Registry中EventMessageFile所帶的ResourceFile內容: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application\test-app (其中test-app為event source名稱,通常為應用程式名稱) 其中EventMessageFile所參考到的,可能會是一個.exe或.dll。而內容根本來源是 Message Text File ,是在編譯器連結期間,將Message Text File所產生的resource file給連結到.exe或.dll中。而我平常都是開發Java APP,所以我選擇產生一個專門描述Event的DLL來解決這個問題。接下來將教大家如何做到這件事情。 How to? 建立一個Win32 DLL Project 首先選擇建立一個Win32 Project。Application type選擇dll,且將additional option選為empty project。 新增一個Version Resource 在resource files上點擊右鍵新增resource。 新增Message Text File 將寫好的Messasge Text File給拖到Resource files中,至於內容怎寫可以參考: link 。 修改建置設定 因為不是一般的DLL程式,並沒有DLL ENTRY。所以要在Linker>Command Line>Additional options中加入/NOENTRY。 在編譯所需要的相關資源前,必須先編譯Message Text File。我們使用Pre-Build Event: mkdir "res" & mc.exe -A "messages.mc" -r "res" 將res資料夾加到編譯Resource中,要在Resource>General>Additional Include...

Windows DLL中共用的Class

Problem 前幾天有人問我為什麼他引用了自己的類別到dll中後,一直出現Link錯誤,後來發現其實和VC設定有關係。請參考下圖: 為了維護方便,我們會將共用的程式碼至於同一專案中。以上面的範例來說,DLLWithDef會使用Common中的Student類別,並將method匯出讓DLLClient使用。假設這個method原型如下,讓我們看看該怎麼做。 Student * createStudent ( string aName ) ; How to? DLL專案 在DLLWithDef專案中,有幾件事情要做: 新增method到匯出類別中,並include標頭檔。 #include "../Common/Student.h" class DLLWITHOUTDEF_API CDLLWitDef { public :   Student * createStudent ( ) { return new Student ( ) ; } ;   } ; 將Student.cpp與Student.h透過加入現有項目的方式,加入到DLLWithDef中。 將method加入.def檔中,宣告匯出symbol。如果你使用裝載期間動態連結,就不用做這個動作。 LIBRARY "DLLWithDef" EXPORTS createStudent Client專案 在DLLClient專案中,有幾件事情要做: 引用標頭檔並宣告method原型 #include "../Common/Student.h" typedef Student * ( * CreateStudent ) ( string name ) ; LPCWSTR hwdll_def = W2T ( L "DLLWithDef.dll" ) ; 將Student.cpp與Student.h透過加入現有項目的方式,加入到DLLClient專案中。做法與DLL專案相同。 撰寫程式(測試用): void testCreateStudent ( HMODULE hModule ) { CreateStudent fnCreateStudent = ( CreateStudent ) ...

Windows DLL的一堆疑問

我所遇到的都是延續前人所做好的dll,也因此對dll的使用宣告方式有疑惑。以下是我study MSDN與網路上文章後,做一些實驗的重點整理: .def與__declspec(dllexport) declspec(dllexport)的Client除了.dll還會使用到.h.lib,有問題的話編譯就不會過。而.def則是透過LoadLibrary去讀取對應的dll,使用完畢就要用FreeLibrary去釋放記憶體,JNA也是使用這種方式。以.def來說,如果dll內的函式宣告沒改變,只有功能增加,可以透過.def控制匯出序數,讓那你的Client應用程式不需要重新編譯。 declspec(dllexport)的Client寫起來就像call API一樣;.def要透過GetProcAddress去取得dll函數的位置去呼叫。 在支援x64的情況下,.def可以透過LoadLibrary去決定要讀取32-bit或64-bit版本,而declspec(dllexport)要透過前處理器與編譯參數去決定要參考的.lib。 對於一個dll專案來說,兩者是可以同時使用的。 Reference Windows程式設計 - 王艷平 編著 fastcall、cdecl與stdcall 這三個宣告叫呼叫慣例(Calling Conventions)。三者將參數放入Stack的順序皆為由左至右,但還有以下差異存在: 暫存器: fastcall會將第一個參數與第二個參數放入暫存器中,放在暫存器存取速度會比在stack中快,顧名思義它叫fastcall。cdecl與stdcall只會使用到stack。 清除Stack的時機: cdecl是由function caller清除stack;fastcall與stdcall則是由callee清除。也因此cdecl允許於不定參數。 VC++預設使用cdecl,Borland C++預設使用fastcall。另外有幾點需要注意: 匯出類別: 在32位元的呼叫慣例為thiscall,64為cdecl。 64-bit VS 32-bit: 32-bit會根據編譯器設定決定呼叫慣例,但64-bit不適用於這些編譯參數。 對於呼叫慣例,可以透過VC的dumpbin.exe /export看它的宣告方式: Reference 关于调用约定(cdecl、fast...

Windows DLL - 32-bit dll with 64-bit driver

前言 在64-bit作業系統上所使用的驅動程式,一定是64-bit,然而應用程式卻可能是32或64-bit。當32-bit應用程式傳值給驅動程式時是有可能會發生溢位的。主要原因是32與64-bit指標所佔用記憶體長度的不同。接下來我將透過Reference 1中的程式PhyMem,來告訴大家問題在哪與如何修改。(最後改完的程式碼恕我不提供) PhyMem介紹 這是一個中國人寫的程式。作用與WinIO相同,可以存取windows的io port與physical memory。這個程式包含pmdll、driver與test三個專案,分別產生dll、sys與exe。作者僅提供32-bit的版本,但只要修改編譯設定就可以讓它產生出64-bit的artifact。但如同我前言所說,如果你是32-bit的dll要存取64的sys該怎麼辦? 可以規定User在64-bit的OS用64-bit的應用程式就好了阿! 但是將一個32-bit應用程式改為64-bit的有這麼簡單嗎? 除此之外,中間傳遞的資料型態也會影響到正常功能。 設定driver專案 我開發環境是VC2008與DDK6000,下載Reference1的專案是無法直接編譯的,可以參考我的設定去修改編譯、連結參數。輸出檔可以看個人需求,根據32或64命名,或者是用同一個檔案名稱。 32-bit C/C++ > 一般 > 其它Include目錄($(DDKROOT)為設定於環境變數的DDK安裝目錄): $(DDKROOT)\inc\ddk";"$(DDKROOT)\inc\api";"$(DDKROOT)\inc\crt";"$(DDKROOT)\inc\crt\gl";"$(DDKROOT)\inc\crt\sys" 連結器 > 一般 > 其它程式庫目錄: $(DDKROOT)\lib\wnet\i386。 連結器 > 資訊清單檔: 將產生資訊清單與UAC選擇否,因為這不適用於driver。 連結器 > 進階 > 隨機化的基底位置: 選擇預設。 64-bit Reference1僅提供32-bit設定。64-bit可在建置>組態管理員中,新增x64平台,而設定檔可從win32複製過來修...

Windows DLL - How to use DLL?

Introduction 網路上能夠找到許多和DLL相關的教學。但我相信大家看了之後依然會存在許多疑問,或者想只要會用就好並不會去了解更深一層的意義。有時我會想: 別人所撰寫的API,我們是不是應該至少要去了解其原理或設計呢? 如果一直當個只懂Call API的Programmer,而沒去學習更多解決問題的方法,只要換個語言應該就和廢人無異了吧! 言歸正傳,今天這篇教學是特地寫給Albert兄的,教導大家DLL使用的兩種方法: 裝載期間動態連結與執行期間動態連結。 Write a DLL 寫DLL相當簡單。如果是VC的用戶,直接透過Wizard產生出DDL的專案,基本的Skeleton都有了。其中的2個重點如下: 匯出函式宣告與DLL檔定義。 匯出的函式我們必須使用_declspec(dllexport)或_declspec(dllimport)宣告,目的是為了讓裝載期間動態連結能夠找到DLL對應的函式。 #ifdef MYDLLHELLOWORLD_EXPORTS #define MYDLLHELLOWORLD_API __declspec(dllexport) #else #define MYDLLHELLOWORLD_API __declspec(dllimport) #endif   // Declare export functions MYDLLHELLOWORLD_API void showHelloWorldString ( LPCTSTR s ) ; 如果是在執行期間動態連結,如果不是使用__declspec(dllexport),我們就必須宣告def檔。VC中新增def的畫面如下: 接著將要匯出的函式加入def中: LIBRARY "DLLHelloWolrd" EXPORTS showHelloWorldString @ 1 在編譯之後,會產生DLLHelloWolrd.dll與DLLHelloWolrd.lib,這兩個檔案在使用DLL時是所被需要的。 裝載期間動態連結 使用裝載期間動態連結的重點如下: 將lib放置專案目錄下。 宣告_declspec(dllexport) void showHelloWorldString( LPCTSTR s)或_declspec(dllimport) void s...