WinDbg 不僅可以用來 Debug User mode 的 process,還可以用來 Debug Kernel mode 的 Windows,基本上使用的方式必須有兩台電腦,或是 VM ,因為 你如果要做 local 的 Kernel Debug 的話,中斷點 hit 到的話,整台電腦應該就會 block 住,但是 local Kernel Debug 無法這麼做的。
既然要透過 remote 的方式來做 Kernel Debug,所以 Windows 提供了不少方法讓你連線到另一台電腦,包括 Serial cable (COM)、1394 cable、Network cable、USB cable …等等,其中 Serial cable & 1394 使用上的限制比較少,support 的平台也比較多,Network cable 與 USB cable 對硬體與平台的限制都不少,所以要確認你的硬體平台有支援的話,才可以透過 Network cable, USB cable 來做 debug。
14 1月 2015
11 12月 2013
[C/C++] 在 Windows 上 Build static libCURL library
libcurl 是個跨平台的 library ,支援非常多的 protocol,重點還是 open source!
以下就是簡單的 build 出一個 libcurl 的 static library 教學
build 完後,可以在 {libcurl extract dir}\builds 找到 lib 還有 header 檔
其他參數說明
加上放有 build 出的 .lib 的目錄
在 Project Property | Linker | Input | Additional Dependencies
加上 libcurl_a.lib or libcurl_a_debug.lib
在 Project Property | C/C++ | Preprocessor
加上 CURL_STATICLIB 這個 macro 才行
否則會出現類似這樣的錯誤訊息:
以下就是簡單的 build 出一個 libcurl 的 static library 教學
1. 首先 download libcurl 的 source code 壓縮檔
libCURL download page2. 在 command line 準備好 VC 的 compile 環境
"{VC Install Path}\VC\vcvarsall.bat" x86
設置完環境後,才能執行 namke3. 開始 build libcurl
cd {libcurl extract dir}\winbuild
nmake /f Makefile.vc mode=static DEBUG=yes MAXHINE=x86
mode = static 也可以是 dll ,只是我們目標是 static librarybuild 完後,可以在 {libcurl extract dir}\builds 找到 lib 還有 header 檔
其他參數說明
- VC=<6,7,8,9,10>
- VC版本(不一定要填)
- WITH_SSL=<dll or static>
- 使用OpenSSL詳細參閱,會有 License 問題
- ENABLE_WINSSL=<yes or no>
- Enable native 的 Windows SSL 功能
- 記得,如果要 enable 的話,ENABLE_SSPI一定也要 enable !
- GEN_PDB=<yes or no>
- 產生 .pdb 檔
- DEBUG=<yes or no>
- Debug or Release mode
- MACHINE=<x86 or x64>
- Target architecture
- RTLIBCFG
- 不指定就是 default,compile 參數會加上 /MD or /MDd (Multi-threaded)
- =static,compile 參數會加上 /MT or /MTd (Multi-threaded DLL)
4. VC project setting 設置
在 Project Property | Linker | General | Additional Library Directories加上放有 build 出的 .lib 的目錄
在 Project Property | Linker | Input | Additional Dependencies
加上 libcurl_a.lib or libcurl_a_debug.lib
在 Project Property | C/C++ | Preprocessor
加上 CURL_STATICLIB 這個 macro 才行
否則會出現類似這樣的錯誤訊息:
1>A.obj : error LNK2019: unresolved external symbol __imp__curl_global_init referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_slist_append referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_slist_free_all referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_strerror referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_init referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_setopt referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_perform referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z) 1>A.obj : error LNK2019: unresolved external symbol __imp__curl_easy_cleanup referenced in function "bool __cdecl DownloadProtectedKey(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?DownloadProtectedKey@@YA_NAAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V12@11@Z)
14 8月 2013
[Win32] 在C/C++中偵測精準的程式時間(Performance Time)
在Windows底下,要偵測精準的Perfromance Time,可以透過QueryPerformanceFrequency() & QueryPerformanceCounter() 來取得。
由於取得的時間存在LARGE_INTEGER的structure,要取出來計算所花費的時間需要多點程式碼才行。這邊寫了一個簡單的Wrapper Class,讓這個AutoQueryPerformance的instance life-time結束後,自行dump出所花費的時間。
Reference
由於取得的時間存在LARGE_INTEGER的structure,要取出來計算所花費的時間需要多點程式碼才行。這邊寫了一個簡單的Wrapper Class,讓這個AutoQueryPerformance的instance life-time結束後,自行dump出所花費的時間。
AutoQueryPerformance
#include "windows.h"
// Auto dump the life-time of AutoQueryPerformance
// Ex:
// {
// AutoQueryPerformance autoQuery("Test", true);
// ...
// } // it will dump message when @autoQuery destroy
class AutoQueryPerformance
{
public:
AutoQueryPerformance(const char* info, INT loop_count=1, BOOL autoDump=TRUE)
: m_count_time(0), m_loop_count(loop_count), m_auto(autoDump)
{
m_info = info;
::ZeroMemory(&m_cpu_freq, sizeof(LARGE_INTEGER));
::QueryPerformanceFrequency(&m_cpu_freq);
if( autoDump )
begin();
}
~AutoQueryPerformance()
{
pause();
if( autoDump )
printf("[AutoQueryPerformance][%s] spend time=%.4f", m_info.c_str(), getTime());
}
inline void begin()
{
::ZeroMemory(&m_start_clock, sizeof(LARGE_INTEGER));;
::QueryPerformanceCounter(&m_start_clock);
}
inline void pause()
{
::ZeroMemory(&m_cur_clock, sizeof(LARGE_INTEGER));
::QueryPerformanceCounter(&m_cur_clock);
m_count_time += m_cur_clock.QuadPart-m_start_clock.QuadPart;
}
inline void stop()
{
pause();
m_count_time = 0;
}
inline float getTime()
{
return (m_count_time/(float)m_cpu_freq.QuadPart) / m_loop_count;
}
private:
LARGE_INTEGER m_cpu_freq;
LARGE_INTEGER m_start_clock;
LARGE_INTEGER m_cur_clock;
LONGLONG m_count_time;
INT m_loop_count;//for for-loop to calculate correct average time
std::string m_info;
BOOL m_auto;
};
#define AUTO_QUERY_PERFORMANCE(x) AutoQueryPerformance __at_qp = AutoQueryPerformance(x);
使用範例
void TestingTotalTime(int loop_count)
{
AutoQueryPerformance ap("TestingTotalTime");
int sum = 0;
for(int i=0 ; i<loop_count; i++)
sum += i;
}
void TestingSingleTime(int loop_count)
{
AutoQueryPerformance ap("TestingSingleTime", loop_count);
for(int i=0 ; i<loop_count; i++)
//HeavyFunction call here;
}
Reference
- MSDN - QueryPerformanceFrequency
- MSDN - QueryPerformanceCounter
12 8月 2013
[Win32/COM] Use COM DLL without registered
依照Windows COM元件的使用方法,應該要將COM DLL註冊後,即可在程式中,以CoCreateInstance()帶入CLSID、IID就可以將該DLL自動load起來,創建該class的instance了。
但是在開發時,實際上總是沒這麼美好,註冊DLL其實是很麻煩的,新舊相容性,開發中的版本等等的問題,而走manifest其實可以避開註冊這條路,但是今天我需要寫一個COM module讓別人使用,而這個COM module在AP裡是走manifest的,所以不會被註冊,連帶的module會用到其他的Library也不走註冊這條路,而因為一些其他的原因,也不能將此Library寫入manifest裡,只能尋求其他途徑了。
由於COM的DLL都會link到一些基本的COM Library,所以是有一些export的API可以繞過註冊來create COM instance的,直接參考以下的Sample Code吧。
Reference:
但是在開發時,實際上總是沒這麼美好,註冊DLL其實是很麻煩的,新舊相容性,開發中的版本等等的問題,而走manifest其實可以避開註冊這條路,但是今天我需要寫一個COM module讓別人使用,而這個COM module在AP裡是走manifest的,所以不會被註冊,連帶的module會用到其他的Library也不走註冊這條路,而因為一些其他的原因,也不能將此Library寫入manifest裡,只能尋求其他途徑了。
由於COM的DLL都會link到一些基本的COM Library,所以是有一些export的API可以繞過註冊來create COM instance的,直接參考以下的Sample Code吧。
// {599D2F5F-BA8D-4009-941C-A5393EBD5C58}
DEFINE_GUID(CLSID_MyCOM,
0x599d2f5f, 0xba8d, 0x4009, 0x94, 0x1c, 0xa5, 0x39, 0x3e, 0xbd, 0x5c, 0x58);
// {4C452CB2-469C-4236-AE5C-F48A28EC0870}
DEFINE_GUID(IID_IMyCOM,
0x4c452cb2, 0x469c, 0x4236, 0xae, 0x5c, 0xf4, 0x8a, 0x28, 0xec, 0x8, 0x70);
HRESULT CreateInstance(IMyCOM** pMyCom)
{
HMODULE hDll = LoadLibrary("MY_COM.dll");//Need refine by your self
if(hDll)
{
//////////////////////////////////////////////////////////////////////////
// Initial COM instance without register
// Try to load COM DLL directly, and call DllGetClassObject to get IID_IClassFactory
// And Create COM instance by IID_IClassFactory
// -----------------------------------------------------------------------
// HRESULT hr = CoCreateInstance(CLSID_MyCOM,
// NULL,
// CLSCTX_INPROC_SERVER,
// IID_IMyCOM,
// (PVOID*)&pMyCom);
//////////////////////////////////////////////////////////////////////////
CComPtr<IClassFactory> spFactory;
// Get address of DllGetClassObject exported method
PDLLGETCLSOBJ pDllGetCLSObj = (PDLLGETCLSOBJ)GetProcAddress(hDll, "DllGetClassObject");
// Call DllGetClassObject and get the proper IClassFactory interface
HRESULT hr = pDllGetCLSObj(CLSID_MyCOM, IID_IClassFactory, reinterpret_cast<PVOID*>(&spFactory));
if( FAILED(hr) )
{
printf(__FUNCTION__" [Err] Can't get spFactory hr=%X", hr);
return E_FAIL;
}
// Create an instance of IMyCOM
hr = spFactory->CreateInstance(NULL, IID_IMyCOM, (PVOID*)pMyCom);
if( FAILED(hr) )
{
printf(__FUNCTION__" [Err] Init IMyCOM Fail! hr=%X", hr);
return E_FAIL;
}
}
else
{
return E_FAIL;
}
return S_OK;
}
Reference:
- StackOverflow - Windows/C++: how to use a COM dll which is not registered
25 5月 2013
[C/C++] 研究long long * float overflow 可能導致的誤差
最近看bug看到一個奇怪的現象,在64bit的AP執行時,long long * float會有誤差出現,但是32bit的AP卻沒有這樣子的問題出現,直覺上不是應該32bit的AP比較會有問題嗎!?
先來看一下 long long 跟 float ,long long的size是8個byte,float的size是4個byte
long long * float,compiler會將結果存到float的temp變數裡,此時誤差就可能會出現了,但是這個誤差是「有條件」地出現,並不是任何long long的數字乘上float都會產生誤差的
以一個簡單的程式來驗證是否會產生誤差
先來看一下 long long 跟 float ,long long的size是8個byte,float的size是4個byte
long long * float,compiler會將結果存到float的temp變數裡,此時誤差就可能會出現了,但是這個誤差是「有條件」地出現,並不是任何long long的數字乘上float都會產生誤差的
以一個簡單的程式來驗證是否會產生誤差
bool check_longlong(long long v1)
{
float f = 1.0f;
long long v2 = long long( v1 * f );
printf("ori value=%lld, new value=%lld, ori==new=%d", v1, v2, v1==v2);
return v1==v2;
}
int _tmain(int argc, _TCHAR* argv[])
{
check_longlong(0xF0000000000);//true - OK
check_longlong(0x0FFFFFFFFFF);//false - Error!
check_longlong(0x0FFFFFF);//true - OK
check_longlong(0x1FFFFFF);//false - Error!
return 0;
}
23 5月 2013
[C/C++] 取得LIB目前的DLL module path
如果寫了一個LIB or Cpp檔,讓多個DLL module include使用,該如果拿到目前DLL的module path?
GetModuleFileName() 參數hModule傳NULL的話,只能知道執行檔exe的路徑
要想知道自己在哪個DLL module的話,必須埋一些code才行
Reference :
GetModuleFileName() 參數hModule傳NULL的話,只能知道執行檔exe的路徑
要想知道自己在哪個DLL module的話,必須埋一些code才行
EXTERN_C IMAGE_DOS_HEADER __ImageBase
//...
WCHAR dll_path[MAX_PATH] = {0};
GetModuleFileNameW((HINSTANCE)&__ImageBase, dll_path, _MAX_PATH);
Reference :
- StackOverflow - Get Dll path at runtime
- MSDN - GetModuleFileName()
16 3月 2012
[Win32] Save Bitmap
Save Gdiplus::Bitmap
HRESULT GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
/*
format support :
"image/png"
"image/bmp"
"image/gif"
"image/jpeg"
"image/tiff"
*/
UINT num = 0; // number of image encoders
UINT size = 0; // size of the image encoder array in bytes
GetImageEncodersSize(&num, &size);
if(size == 0)
return E_FAIL; // Failure
ImageCodecInfo* pImageCodecInfo = NULL;
pImageCodecInfo = (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo == NULL)
return E_FAIL; // Failure
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j = 0; j < num; ++j)
{
if( wcscmp(pImageCodecInfo[j].MimeType, format) == 0 )
{
*pClsid = pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return S_OK; // Success
}
}
free(pImageCodecInfo);
return E_FAIL;
}
void SaveBitmap(Bitmap* bitmap)
{
// Get the CLSID of the JPEG encoder.
CLSID clsid;
GetEncoderClsid(L"image/jpeg", &clsid);
bitmap.Save(L"C:\\test.jpg", &clsid, NULL);
}

22 12月 2009
[Windows] Local time 轉 UTC
Window提供了 API 可以轉換時間的時區。
Reference:
- TzSpecificLocalTimeToSystemTime:Local time -> UTC
- SystemTimeToTzSpecificLocalTime :UTC -> Local time
SYSTEMTIME ConvertLocalTime2UTC(UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second)
{
SYSTEMTIME local, utc;
ZeroMemory(&local, sizeof(local));
local.wYear = year;
local.wMonth = month;
local.wDay = day;
local.wHour = hour;
local.wMinute = minute;
local.wSecond = second;
TzSpecificLocalTimeToSystemTime( NULL, &local, &utc );
printf("UTC Time =%d/%d/%d %d:%d:%d\n", utc.wYear, utc.wMonth, utc.wDay, utc.wHour, utc.wMinute, utc.wSecond);
printf("Local Time=%d/%d/%d %d:%d:%d\n", local.wYear, local.wMonth, local.wDay, local.wHour, local.wMinute, local.wSecond);
return utc;
}
SYSTEMTIME ConvertUTC2LocalTime(UINT year, UINT month, UINT day, UINT hour, UINT minute, UINT second)
{
SYSTEMTIME local, utc;
ZeroMemory(&utc, sizeof(utc));
utc.wYear = year;
utc.wMonth = month;
utc.wDay = day;
utc.wHour = hour;
utc.wMinute = minute;
utc.wSecond = second;
SystemTimeToTzSpecificLocalTime( NULL, &utc, &local );
printf("UTC Time =%d/%d/%d %d:%d:%d\n", utc.wYear, utc.wMonth, utc.wDay, utc.wHour, utc.wMinute, utc.wSecond);
printf("Local Time=%d/%d/%d %d:%d:%d\n", local.wYear, local.wMonth, local.wDay, local.wHour, local.wMinute, local.wSecond);
return local;
}Reference:
12 12月 2009
[Win32 API] String Conversion
在Windows底下做字串轉換其實還滿簡單的,在MFC的Library裡,提供了一些簡單的Marco可以用,就可以針對wstring, string, CComBSTR, BSTR之間做轉換了。需 Include AtlBase.h, AtlConv.h
以下是 ATL7.0 版 Marco、Class的命名規則
以下是 ATL3.0 舊版 Marco的命名規則
以下是 ATL7.0 版 Marco、Class的命名規則
CSourceType2[C]DestinationType[EX]
以下是 ATL3.0 舊版 Marco的命名規則
SourceType2[C]DestinationType[EX]
訂閱:
文章 (Atom)