Windows核心编程1-天青

错误处理

FormatMessage

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DWORD dwError = ::GetDlgItemInt(hwnd, IDC_ERRORCODE, NULL, FALSE);
HLOCAL hlocal = NULL;
DWORD systemLocale = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL); //设置FormatMessage返回的语言
BOOL fOk = ::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, NULL, dwError, systemLocale, (PTSTR)&hlocal, 0, NULL);
if (!fOk) { //不成功还可能是网络相关错误
HMODULE hDll = ::LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
if (hDll != NULL) {
fOk = ::FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER, hDll, dwError, systemLocale, (PTSTR)&hlocal, 0, NULL);
::FreeLibrary(hDll);
};
};
if (fOk && (hlocal != NULL)) {
::SetDlgItemText(hwnd, IDC_ERRORTEXT, (PCTSTR)::LocalLock(hlocal));
::LocalFree(hlocal);
}
else
SetDlgItemText(hwnd, IDC_ERRORTEXT, TEXT("No text found for this error number,"));

内核对象

改变句柄标志

SetHandleInformation

改变内核对象句柄的继承标志。

1
2
3
4
5
BOOL SetHandleInformation(
HANDLE hObject,
DWORD dwMask,
DWORD dwFlags
)

GetHandleInformation

获取继承标志。

1
2
3
4
BOOL GetHandleInformation(
HANDLE hObject,
PDWORD pdwFlags
)

例子

1
2
3
4
5
6
7
8
9
SetHandleInformation(hObj,HANDLE_FLAG_INHERIT,HANDLE_FLAG_INHERIT);//打开内核对象句柄的继承
SetHandleInformation(hObj,HANLDE_FLAG_INHERIT,0);//关闭
SetHandleInformation(hObj,HANDLE_FLAG_PROTECT_FROM_CLOSE,HANDLE_FLAG_PROTECT_FROM_CLOSE);//该句柄不允许被关闭
SetHanldeInformation(hObj,HANDLE_FLAG_PROTECT_FROM_CLOSE,0);//设置允许被关闭

//核实一个句柄是否可以继承
DWORD dwFlags;
GetHandleInformation(hObj,&dwFlags);
BOOL fHandleIsInheritable=(0!=(dwFlags&HANDLE_FLAG_INHERIT));

ProcessIdToSessionId

获取某个进程在哪个终端服务会话中运行。有两种特殊命名空间,前缀“Global\\”为全局命名空间,前缀“Local\\”为当前会话命名空间。

1
2
3
4
5
6
DWORD processID=::GetCurrentProcessId();
DWORD sessionID;
if (::ProcessIdToSessionId(processID,&sessionID))
tprintf("%u--%u",processID,sessionID);
else
//没有足够权限 这里问题不大 用的自身ID

专有命名空间

CreateBoundaryDescriptor

创建边界描述符。

1
2
3
4
5
6
HANDLE CreateBoundaryDescriptor(
PCTSTR pszName,
//名称
DWORD dwFlags
//没啥用
)//返回伪句柄 得用DeleteBoundaryDescriptor销毁

AddSIDToBoundaryDescriptor

将一个特权用户组的SID与边界描述符关联起来,客户端应用程序将在这些用户上下文运行。

1
2
3
4
BOOL AddSIDToBoundaryDescriptor(
PHANDLE phBoundaryDescriptor,
PSID pRequiredSid
)

CreatePrivateNamespace

创建专有命名空间。

1
2
3
4
5
HANDLE CreatePrivateNamespace(
PSECURITY_ATTRIBUTES psa,
PVOID pvBoundaryDescriptor,
PCTSTR pszAliasPrefix
)//如果已存在返回NULL GetLastError=ERROR_ALREADY_EXISTS

OpenPrivateNamespace

打开现有专有命名空间。

1
2
3
4
HANDLE OpenPrivateNamespace(
PVOID pvBoundaryDescriptor,
PCTSTR pszAliasPrefix
)

ClosePrivateNamespace

关闭伪句柄。

1
2
3
4
5
BOOLEAN ClosePrivateNamespace(
HANDLE hNamespace,
DWORD dwFlags
//需要关闭后不可见设置NAMESPACE_FLAG_DESTROY
)

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <sddl.h>
#include <strsafe.h>
PCTSTR g_szBoundary = TEXT("3-Boundary");
PCTSTR g_szNamespace = TEXT("3-Namespace");
HANDLE g_hBoundary = NULL;
HANDLE g_hNamespace = NULL;
HANDLE g_hSingleton = NULL;
BOOL g_bNamespaceOpened = FALSE;
void CheckInstance(void) {
g_hBoundary = ::CreateBoundaryDescriptor(g_szBoundary, 0);
BYTE localAdminSID[SECURITY_MAX_SID_SIZE] = { 0 };
PSID pLocalAdminSID = &localAdminSID;
DWORD cbSID = sizeof(localAdminSID);
if (!::CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, pLocalAdminSID, &cbSID))
return;
if (!::AddSIDToBoundaryDescriptor(&g_hBoundary, pLocalAdminSID))
return;
SECURITY_ATTRIBUTES sa = { 0 };
sa.nLength = sizeof(sa);
sa.bInheritHandle = FALSE;
if (!::ConvertStringSecurityDescriptorToSecurityDescriptor(TEXT("D:(A;;GA;;;BA)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL)) //安全描述符字符串相关
return;
g_hNamespace = ::CreatePrivateNamespace(&sa, g_hBoundary, g_szNamespace);
::LocalFree(sa.lpSecurityDescriptor);
DWORD dwLastError = ::GetLastError();
if (g_hNamespace == NULL) {
if (dwLastError == ERROR_ACCESS_DENIED)
return;
else
if (dwLastError == ERROR_ALREADY_EXISTS) {
g_hNamespace = ::OpenPrivateNamespace(g_hBoundary, g_szNamespace);
if (g_hNamespace == NULL)
return;
else
g_bNamespaceOpened = TRUE;
}
else
return;
};
TCHAR szMutexName[64] = { 0 };
::StringCchPrintf(szMutexName, _countof(szMutexName), TEXT("%s\\%s"), g_szNamespace, TEXT("Singleton"));
g_hSingleton = ::CreateMutex(NULL, FALSE, szMutexName);
if (::GetLastError() == ERROR_ALREADY_EXISTS) {
//第二次启动实例
};
//第一次启动实例
//销毁
if (g_hSingleton != NULL)
::CloseHandle(g_hSingleton);
if (g_hNamespace != NULL) {
if (g_bNamespaceOpened)
::ClosePrivateNamespace(g_hNamespace, 0);
else
::ClosePrivateNamespace(g_hNamespace, PRIVATE_NAMESPACE_FLAG_DESTROY);
};
if (g_hBoundary != NULL)
::DeleteBoundaryDescriptor(g_hBoundary);
return;
};

复制对象句柄

DuplicateHandle

跨边界共享内核。

1
2
3
4
5
6
7
8
9
10
11
BOOL DuplicateHandle(
HANDLE hSourceProcessHandle,
HANDLE hSourceHandle,
HANDLE hTargetProcessHandle,
PHANDLE phTargetHandle,
DWORD dwDesiredAccess,
//如FILE_MAP_READ等
BOOL bInheritHandle,
DWORD dwOptions
//DUPLICATE_SAME_ACCESS忽略dwDesiredAccess并继承相同访问掩码 DUPLICATE_CLOSE_SOURCE关闭源进程句柄并转交
)

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) {
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
DWORD dwProcessIdT = 114514;
HANDLE hObjInProcessS = ::CreateMutex(NULL, FALSE, NULL);
HANDLE hProcessT = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessIdT);
HANDLE hObjInProcessT = NULL;
::DuplicateHandle(::GetCurrentProcess(), hObjInProcessS, hProcessT, &hObjInProcessT, 0, FALSE, DUPLICATE_SAME_ACCESS);
::CloseHandle(hProcessT);
::CloseHandle(hObjInProcessS);
//千万别在S进程中::CloseHandle(hObjInProcessT)
return 0;
};