注:源码为学习《Windows核心编程》的一些尝试,非原创。若能有助于一二访客,幸甚。
/******************************************************************************* * File: ErrorShow.cpp * Time: 2013-04-16 * 描述: 修改试验原书同名程序 *******************************************************************************/ #include <Windows.h> #include <Windowsx.h> #include <tchar.h> #include "resource.h" // Always compiler using Unicode. #ifndef UNICODE #define UNICODE #endif #define chHANDLE_DLGMSG(hWnd, message, fn) \ case (message): return (SetDlgMsgResult(hWnd, uMsg, \ HANDLE_##message((hWnd), (wParam), (lParam), (fn)))) BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { return TRUE; } void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) { switch (id) { case IDOK: case IDCANCEL: EndDialog(hwnd, id); break; } } INT_PTR WINAPI Dlg_Proc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { chHANDLE_DLGMSG(hwnd, WM_COMMAND, Dlg_OnCommand); chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog); } return FALSE; } int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); DialogBox(hInstance, MAKEINTRESOURCE(IDD_SINGLETON), NULL, Dlg_Proc); return 0; }
// Main dialog HWND g_hDlg; // 添加一个字符串到编辑框 void AddText(PCTSTR pszFormat, ...) { /* VA_LIST的用法: *(1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针; *(2)然后用VA_START宏初始化变量刚定义的VA_LIST变量; *(3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的 * 类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数); *(4)最后用VA_END宏结束可变参数的获取。 */ va_list argList; va_start(argList, pszFormat); TCHAR sz[20 * 1024]; Edit_GetText(GetDlgItem(g_hDlg, IDC_EDIT_DETAILS), sz, _countof(sz)); _vstprintf_s(_tcschr(sz, TEXT('\0')), _countof(sz) - _tcslen(sz), pszFormat, argList); Edit_SetText(GetDlgItem(g_hDlg, IDC_EDIT_DETAILS), sz); va_end(argList); } BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { g_hDlg = hwnd; AddText(TEXT("a~z: \r\n")); for (char c = 'a'; c <= 'z'; c++) AddText(TEXT("%c "), c); return TRUE; }
void CheckInstances() { // 创建边界描述符 g_hBoundary = CreateBoundaryDescriptor(g_szBoundary, 0); // 创建一个对应于本地管理员组的安全描述符SID BYTE localAdminSID[SECURITY_MAX_SID_SIZE]; PSID pLocalAdminSID = &localAdminSID; DWORD cbSID = sizeof(localAdminSID); /* The CreateWellKnownSid function creates a SID for predefined aliases. BOOL WINAPI CreateWellKnownSid( __in WELL_KNOWN_SID_TYPE WellKnownSidType, __in_opt PSID DomainSid, __out_opt PSID pSid, __inout DWORD* cbSid ); Parameters WellKnownSidType Member of the WELL_KNOWN_SID_TYPE enumeration that specifies what the SID will identify. DomainSid A pointer to a SID that identifies the domain control to use when creating the SID. Pass NULL to use the local computer. pSid A pointer to memory where CreateWellKnownSid will store the new SID. cbSid A pointer to a DWORD that contains the number of bytes available at pSid. The CreateWellKnownSid function stores the number of bytes actually used at this location. */ if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, pLocalAdminSID, &cbSID)) { AddText(TEXT("添加安全描述符到边界描述符失败: %u\r\n"), GetLastError()); return; } // 将本地管理员组的安全描述符与边界描述符关联起来 // 只有管理员身份运行的应用程序能获得该命名空间下的内核对象 if (!AddSIDToBoundaryDescriptor(&g_hBoundary, pLocalAdminSID)) { AddText(TEXT("添加安全描述符到边界描述符失败: %u\r\n"), GetLastError()); return; } // 为本地管理员创建命名空间 SECURITY_ATTRIBUTES sa; sa.nLength = sizeof(sa); sa.bInheritHandle = FALSE; if (!ConvertStringSecurityDescriptorToSecurityDescriptor(TEXT("D:(A;;GA;;;BA)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL)) { AddText(TEXT("安全描述符创建失败: %u\r\n"), GetLastError()); return; } g_hNamespace = CreatePrivateNamespace(&sa, g_hBoundary, g_szNamespace); LocalFree(sa.lpSecurityDescriptor); // 检查私有命名空间创建是否成功 DWORD dwLastError = GetLastError(); // 创建失败 if (g_hNamespace == NULL) { // 如果被拒绝访问,则直接返回 // 这段代码必须在本地管理员账户运行 if (dwLastError == ERROR_ACCESS_DENIED) { AddText(TEXT("创建命名空间时访问被拒绝.\r\n")); AddText(TEXT(" 必须以管理员身份运行。\r\n\r\n")); return; } else { // 如果在该命名空间另一个实例已经被创建 if (dwLastError == ERROR_ALREADY_EXISTS) { AddText(TEXT("创建私有命名空间失败: %u\r\n"), dwLastError); g_hNamespace = OpenPrivateNamespace(g_hBoundary, g_szNamespace); if (g_hNamespace == NULL) { AddText(TEXT(" 并且打开私有命名空间失败: %u\r\n"), dwLastError); return; } else { g_bNamespaceOpened = TRUE; AddText(TEXT(" 但是打开私有命名空间成功\r\n\r\n")); } } else { AddText(TEXT("发生了未知的错误: %u\r\n\r\n"), dwLastError); return; } } } // 尝试创建命名互斥量对象 TCHAR szMutexName[64]; StringCchPrintf(szMutexName, _countof(szMutexName), TEXT("%s\\%s"), g_szNamespace, TEXT("单一实例")); g_hSingleton = CreateMutex(NULL, FALSE, szMutexName); if (GetLastError() == ERROR_ALREADY_EXISTS) { AddText(TEXT("单一实例应用程序另一个实例已经运行:\r\n")); AddText(TEXT("--> 不能访问应用程序功能.\r\n")); } else { AddText(TEXT("单一实例应用程序的第一个实例\r\n")); AddText(TEXT("--> 现在访问应用程序功能\r\n")); } }