Skip to content

Instantly share code, notes, and snippets.

@udaken
Last active February 4, 2023 14:03
Show Gist options
  • Save udaken/37b5e79d7d00e6516c10d7dab88db64f to your computer and use it in GitHub Desktop.
Save udaken/37b5e79d7d00e6516c10d7dab88db64f to your computer and use it in GitHub Desktop.

静的リンクライブラリからDLLのHMODULE(HINSTANCE)を取得する

下記から。
https://blogs.msdn.microsoft.com/oldnewthing/20041025-00/?p=37483

EXTERN_C IMAGE_DOS_HEADER __ImageBase;
#define HINST_THISCOMPONENT ((HINSTANCE)&__ImageBase)

CRTのメモリーリーク検出

https://msdn.microsoft.com/ja-jp/library/x98tx3cf.aspx

#define _CRTDBG_MAP_ALLOC 
#include <stdlib.h> 
#include <crtdbg.h>  
...
void main()
{
			_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
      ...
}

HRESULTからWin32のエラーコードに変換する

下記から。
https://blogs.msdn.microsoft.com/oldnewthing/20061103-07/?p=29133

constexpr BOOL WIN32_FROM_HRESULT(HRESULT hr, OUT DWORD *pdwWin32) noexcept
{
	if ((hr & 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, 0)) {
		*pdwWin32 = HRESULT_CODE(hr);
		return TRUE;
	}
	else if (hr == S_OK) {
		*pdwWin32 = HRESULT_CODE(hr);
		return TRUE;
	}
	return FALSE;
}

constexpr DWORD WIN32_FROM_HRESULT(HRESULT hr) noexcept
{
	DWORD dwError = 65535;
	WIN32_FROM_HRESULT(hr, &dwError);
	return dwError;
}

エラーコードの相互変換

from \ to HRESULT Win32 NTSTATUS
HRESULT - WIN32_FROM_HRESULT N/A
Win32 HRESULT_FROM_WIN32 function
_Translates_Win32_to_HRESULT_ inline function
__HRESULT_FROM_WIN32 macro
- N/A
NTSTATUS HRESULT_FROM_NT RtlNtStatusToDosError -

MSVC(VC++)でプロパティを実現する

https://msdn.microsoft.com/ja-jp/library/yhfk0thd.aspx

__declspec( property( get=get_func_name ) ) declarator  
__declspec( property( put=put_func_name ) ) declarator  
__declspec( property( get=get_func_name, put=put_func_name ) ) declarator  

ちなみにdeclarator では、decltype(get_foo()) foo; のようにメンバー関数の戻り値を型に使用できないので、メンバー毎に型を指定する必要がある。

Windows XPで高精度のシステム時刻を取得する

それっぽいソース。

void MyGetSystemTimePreciseAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
{
	union filetymeunion
	{
		FILETIME ft;
		LONG64 QuadPart;
	};

	static volatile LONG firsttime = 0;
	static LARGE_INTEGER Frequency = { 0 };
	static CRITICAL_SECTION cs;
	static LARGE_INTEGER lastTick;

	static filetymeunion lastTime = { 0 };
	filetymeunion now;

	if (InterlockedCompareExchange(&firsttime, 1, 0) == 0)
	{
		QueryPerformanceFrequency(&Frequency);
		InitializeCriticalSection(&cs);
		firsttime = 2;
	}

	while (firsttime != 2)
	{
		// nop
	}

	GetSystemTimeAsFileTime(&now.ft);

	EnterCriticalSection(&cs);

	if (lastTime.QuadPart == now.QuadPart)
	{
		// same time
		LARGE_INTEGER currentTick;
		QueryPerformanceCounter(&currentTick);

		LONGLONG diff = currentTick.QuadPart - lastTick.QuadPart;

		diff *= 10000000;  // 100 nano second
		diff /= Frequency.QuadPart;
		now.QuadPart += diff;
	}
	else
	{
		QueryPerformanceCounter(&lastTick);
	}
	LeaveCriticalSection(&cs);
	*lpSystemTimeAsFileTime = now.ft;
}

Windows XP でGetThreadId()関数

それっぽいソース

//#if (_WIN32_WINNT < 0x0502)
static DWORD
WINAPI
GetThreadId(
	_In_ HANDLE Thread
)
{

	typedef struct _THREAD_BASIC_INFORMATION {
		NTSTATUS                ExitStatus;
		PVOID                   TebBaseAddress;
		CLIENT_ID               ClientId;
		KAFFINITY               AffinityMask;
		KPRIORITY               Priority;
		KPRIORITY               BasePriority;
	} THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;

	THREADINFOCLASS ThreadBasicInformation = static_cast<THREADINFOCLASS>(0);
	ULONG ReturnLength;
	THREAD_BASIC_INFORMATION info;
	
	typedef  NTSTATUS
	(NTAPI *NtQueryInformationThread) (
		IN HANDLE ThreadHandle,
		IN THREADINFOCLASS ThreadInformationClass,
		OUT PVOID ThreadInformation,
		IN ULONG ThreadInformationLength,
		OUT PULONG ReturnLength OPTIONAL
		);
	NtQueryInformationThread fp = (NtQueryInformationThread)::GetProcAddress(::LoadLibraryA("Ntdll.dll"), "NtQueryObject");
	NTSTATUS status = fp(Thread, ThreadBasicInformation, &info, sizeof(info), NULL);
	if (NT_SUCCESS(status))
		return reinterpret_cast<DWORD>(info.ClientId.UniqueThread);
	else
	{
		typedef ULONG
		(NTAPI *RtlNtStatusToDosError) (
		   NTSTATUS Status
		   );
		RtlNtStatusToDosError fp = (RtlNtStatusToDosError)::GetProcAddress(::LoadLibraryA("Ntdll.dll"), "RtlNtStatusToDosError");
		::SetLastError(fp(status));
		return 0;
	}
}
//#endif // _WIN32_WINNT >= 0x0502

マイナー?な同期関数/非同期処理

https://msdn.microsoft.com/en-us/library/windows/desktop/ms686360(v=vs.85).aspx

APC(user-mode asynchronous procedure call)

スレッドにAPC関数を紐づけて(APCキュー)、特定の関数(SleepEx, SignalObjectAndWait, WaitForSingleObjectEx, WaitForMultipleObjectsEx, or MsgWaitForMultipleObjectsEx)の引数でalertableを指定した場合に、APC関数がコールバックされる。
以下の理由により、非常に使いづらい。

  • APC関数明示的なトリガーを必要とする。
  • APC関数が実行している間は、呼び出し元に復帰しない。
    SleepEx で指定したミリ秒よりAPC関数の実行に時間がかかっても、APC関数が中断されることはない。
  • ExitThread または TerminateThread でスレッドを終了するとAPC関数は呼び出されない。

セクション共有

DLLに特定のセクションを用意することで、ロードするEXE間で共有メモリ扱いすることができる

#pragma comment(linker, "/section:.shared,rws")
#pragma data_seg(".shared")
SomeClass g_value = SomeClass();
#pragma data_seg()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment