diff --git a/03-Singleton.vcproj b/03-Singleton.vcproj new file mode 100644 index 0000000..ffc99c5 --- /dev/null +++ b/03-Singleton.vcproj @@ -0,0 +1,342 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/03-Singleton.vcxproj b/03-Singleton.vcxproj new file mode 100644 index 0000000..59c7afb --- /dev/null +++ b/03-Singleton.vcxproj @@ -0,0 +1,176 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {6519CE30-7D1C-4A57-AA09-35BAFD171AFD} + My03Singleton + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.40219.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + true + $(SolutionDir)$(Platform)\$(Configuration)\ + $(Platform)\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + true + Windows + MachineX86 + + + + + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX86 + + + + + X64 + + + Disabled + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + true + Windows + MachineX64 + + + + + X64 + + + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + true + Windows + true + true + MachineX64 + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/03-Singleton.vcxproj.user b/03-Singleton.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/03-Singleton.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Resource.h b/Resource.h index 1382402..ec2f013 100644 --- a/Resource.h +++ b/Resource.h @@ -1,21 +1,20 @@ //{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by ErrorShow.rc +// Microsoft Visual C++ generated include file. +// Used by Singleton.rc // -#define IDD_ERRORSHOW 101 -#define IDI_ERRORSHOW 102 -#define IDC_ERRORCODE 1000 -#define IDC_ERRORTEXT 1001 -#define IDC_ALWAYSONTOP 1002 -#define IDC_STATIC (-1) // all static controls +#define IDI_SINGLETON 102 +#define IDD_SINGLETON 129 +#define IDC_EDIT_DETAILS 1000 +#define IDC_STATIC -1 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 104 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1005 -#define _APS_NEXT_SYMED_VALUE 101 +#define _APS_NO_MFC 1 +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 110 #endif #endif diff --git a/Singleton.aps b/Singleton.aps new file mode 100644 index 0000000..1ec2e00 Binary files /dev/null and b/Singleton.aps differ diff --git a/Singleton.cpp b/Singleton.cpp new file mode 100644 index 0000000..cadc667 --- /dev/null +++ b/Singleton.cpp @@ -0,0 +1,238 @@ +/****************************************************************************** +Module: Singleton.cpp +Notices: Copyright (c) 2008 Jeffrey Richter & Christophe Nasarre +******************************************************************************/ + + +#include "resource.h" + +#include "..\CommonFiles\CmnHdr.h" /* See Appendix A. */ +#include +#include // for SID management +#include +#include + + + +/////////////////////////////////////////////////////////////////////////////// + + +// Main dialog +HWND g_hDlg; + +// Mutex, boundary and namespace used to detect previous running instance +HANDLE g_hSingleton = NULL; +HANDLE g_hBoundary = NULL; +HANDLE g_hNamespace = NULL; + +// Keep track whether or not the namespace was created or open for clean-up +BOOL g_bNamespaceOpened = FALSE; + +// Names of boundary and private namespace +PCTSTR g_szBoundary = TEXT("3-Boundary"); +PCTSTR g_szNamespace = TEXT("3-Namespace"); + + +#define DETAILS_CTRL GetDlgItem(g_hDlg, IDC_EDIT_DETAILS) + + +/////////////////////////////////////////////////////////////////////////////// + + +// Adds a string to the "Details" edit control +void AddText(PCTSTR pszFormat, ...) { + + va_list argList; + va_start(argList, pszFormat); + + TCHAR sz[20 * 1024]; + + Edit_GetText(DETAILS_CTRL, sz, _countof(sz)); + _vstprintf_s( + _tcschr(sz, TEXT('\0')), _countof(sz) - _tcslen(sz), + pszFormat, argList); + Edit_SetText(DETAILS_CTRL, sz); + va_end(argList); +} + + +/////////////////////////////////////////////////////////////////////////////// + + +void Dlg_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) { + + switch (id) { + case IDOK: + case IDCANCEL: + // User has clicked on the Exit button + // or dismissed the dialog with ESCAPE + EndDialog(hwnd, id); + break; + } +} + + +/////////////////////////////////////////////////////////////////////////////// + + +void CheckInstances() { + + // Create the boundary descriptor + g_hBoundary = CreateBoundaryDescriptor(g_szBoundary, 0); + + // Create a SID corresponding to the Local Administrator group + BYTE localAdminSID[SECURITY_MAX_SID_SIZE]; + PSID pLocalAdminSID = &localAdminSID; + DWORD cbSID = sizeof(localAdminSID); + if (!CreateWellKnownSid( + WinBuiltinAdministratorsSid, NULL, pLocalAdminSID, &cbSID) + ) { + AddText(TEXT("AddSIDToBoundaryDescriptor failed: %u\r\n"), + GetLastError()); + return; + } + + // Associate the Local Admin SID to the boundary descriptor + // --> only applications running under an administrator user + // will be able to access the kernel objects in the same namespace + if (!AddSIDToBoundaryDescriptor(&g_hBoundary, pLocalAdminSID)) { + AddText(TEXT("AddSIDToBoundaryDescriptor failed: %u\r\n"), + GetLastError()); + return; + } + + // Create the namespace for Local Administrators only + 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("Security Descriptor creation failed: %u\r\n"), GetLastError()); + return; + } + + g_hNamespace = + CreatePrivateNamespace(&sa, g_hBoundary, g_szNamespace); + + // Don't forget to release memory for the security descriptor + LocalFree(sa.lpSecurityDescriptor); + + + // Check the private namespace creation result + DWORD dwLastError = GetLastError(); + if (g_hNamespace == NULL) { + // Nothing to do if access is denied + // --> this code must run under a Local Administrator account + if (dwLastError == ERROR_ACCESS_DENIED) { + AddText(TEXT("Access denied when creating the namespace.\r\n")); + AddText(TEXT(" You must be running as Administrator.\r\n\r\n")); + return; + } else { + if (dwLastError == ERROR_ALREADY_EXISTS) { + // If another instance has already created the namespace, + // we need to open it instead. + AddText(TEXT("CreatePrivateNamespace failed: %u\r\n"), dwLastError); + g_hNamespace = OpenPrivateNamespace(g_hBoundary, g_szNamespace); + if (g_hNamespace == NULL) { + AddText(TEXT(" and OpenPrivateNamespace failed: %u\r\n"), + dwLastError); + return; + } else { + g_bNamespaceOpened = TRUE; + AddText(TEXT(" but OpenPrivateNamespace succeeded\r\n\r\n")); + } + } else { + AddText(TEXT("Unexpected error occured: %u\r\n\r\n"), + dwLastError); + return; + } + } + } + + // Try to create the mutex object with a name + // based on the private namespace + TCHAR szMutexName[64]; + StringCchPrintf(szMutexName, _countof(szMutexName), TEXT("%s\\%s"), + g_szNamespace, TEXT("Singleton")); + + g_hSingleton = CreateMutex(NULL, FALSE, szMutexName); + if (GetLastError() == ERROR_ALREADY_EXISTS) { + // There is already an instance of this Singleton object + AddText(TEXT("Another instance of Singleton is running:\r\n")); + AddText(TEXT("--> Impossible to access application features.\r\n")); + } else { + // First time the Singleton object is created + AddText(TEXT("First instance of Singleton:\r\n")); + AddText(TEXT("--> Access application features now.\r\n")); + } +} + + +/////////////////////////////////////////////////////////////////////////////// + + +BOOL Dlg_OnInitDialog(HWND hwnd, HWND hwndFocus, LPARAM lParam) { + + chSETDLGICONS(hwnd, IDI_SINGLETON); + + // Keep track of the main dialog window handle + g_hDlg = hwnd; + + // Check whether another instance is already running + CheckInstances(); + + return(TRUE); +} + + +/////////////////////////////////////////////////////////////////////////////// + + +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); + + // Show main window + DialogBox(hInstance, MAKEINTRESOURCE(IDD_SINGLETON), NULL, Dlg_Proc); + + // Don't forget to clean up and release kernel resources + if (g_hSingleton != NULL) { + CloseHandle(g_hSingleton); + } + + if (g_hNamespace != NULL) { + if (g_bNamespaceOpened) { // Open namespace + ClosePrivateNamespace(g_hNamespace, 0); + } else { // Created namespace + ClosePrivateNamespace(g_hNamespace, PRIVATE_NAMESPACE_FLAG_DESTROY); + } + } + + if (g_hBoundary != NULL) { + DeleteBoundaryDescriptor(g_hBoundary); + } + + return(0); +} + + +//////////////////////////////// End of File ////////////////////////////////// diff --git a/Singleton.ico b/Singleton.ico new file mode 100644 index 0000000..b96aa0e Binary files /dev/null and b/Singleton.ico differ diff --git a/Singleton.rc b/Singleton.rc new file mode 100644 index 0000000..8b4db2d --- /dev/null +++ b/Singleton.rc @@ -0,0 +1,111 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_SINGLETON ICON "Singleton.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SINGLETON DIALOGEX 0, 0, 195, 95 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_MINIMIZEBOX | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_APPWINDOW +CAPTION "Singleton" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "E&xit",IDOK,140,76,50,14 + EDITTEXT IDC_EDIT_DETAILS,4,5,186,67,ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_SINGLETON, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 188 + TOPMARGIN, 7 + BOTTOMMARGIN, 88 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED +