понедельник, 2 ноября 2015 г.

Пример создания именованных объектов ядра ОС в разных пространствах имён

Маленькая шпаргалка-пример на тему совместного использования именованных объектов ядра несколькими процессами. Показан вариант размещения именованных объектов ядра в глобальном, локальном и приватном пространствах имён.

Исходный код примера:

#include <Windows.h>
#include <iostream>
#include <aclapi.h>
#include <exception>
#include <tchar.h>

using namespace std;
void PrintErrorMsg(LPCTSTR prefix);

int main(int argc, TCHAR *argv[])
try {
    setlocale(LC_ALL, "Russian");

    HANDLE hGlobalMutex = CreateMutex(NULL, FALSE, L"Global\\G_Mutex");
    if (NULL == hGlobalMutex) {
        PrintErrorMsg(L"Global Mutex: ");
    }
    else {
        // Check the reason of success
        DWORD errCode = GetLastError();
        if (ERROR_ALREADY_EXISTS == errCode) {
            wcout << L"Named global mutex opened." << endl;
        }
        else {
            wcout << L"Named global mutex created." << endl;
        }
    }

    HANDLE hLocalMutex = CreateMutex(NULL, FALSE, L"Local\\L_Mutex");
    if (NULL == hLocalMutex) {
        PrintErrorMsg(L"Local Mutex: ");
    }
    else {
        // Check the reason of success
        DWORD errCode = GetLastError();
        if (ERROR_ALREADY_EXISTS == errCode) {
            wcout << L"Named local mutex opened." << endl;
        }
        else {
            wcout << L"Named local mutex created." << endl;
        }
    }

    LPCTSTR boundaryName = L"BushmanBoundary";
    HANDLE hBoundary = CreateBoundaryDescriptor(boundaryName, 0);
    HANDLE hNamespase = NULL;
    HANDLE hMutex = NULL;
    if (NULL == hBoundary) {
        PrintErrorMsg(L"CreateBoundaryDescriptor: ");
    }
    else {
        wcout << L"Boundary descriptor created." << endl;

        BYTE sid[SECURITY_MAX_SID_SIZE];
        ZeroMemory(sid, sizeof(sid));

        DWORD cbSID = sizeof(sid);
        BOOL result = CreateWellKnownSid(WinWorldSid, NULL, &sid, &cbSID);
        if (0 == result) {
            PrintErrorMsg(L"CreateWellKnownSid: ");
        }
        else {
            wcout << L"SID for boundary descriptor created." << endl;

            result = AddSIDToBoundaryDescriptor(&hBoundary, &sid);
            if (0 == result) {
                PrintErrorMsg(L"AddSIDToBoundaryDescriptor: ");
            }
            else {
                wcout << L"SID added to boundary descriptor." << endl;

                SECURITY_ATTRIBUTES sa = { 0 };
                sa.nLength = sizeof(sa);
                sa.bInheritHandle = FALSE;
                sa.lpSecurityDescriptor = NULL; // use the default value

                LPCTSTR ns = L"Local\\BushNamespace";

                hNamespase = CreatePrivateNamespace(&sa, hBoundary,
                    ns);
                if (NULL == hNamespase) {
                    // Check the reason of failure
                    DWORD errCode = GetLastError();
                    if (ERROR_ALREADY_EXISTS == errCode) {
                        hNamespase = OpenPrivateNamespace(hBoundary, ns);
                        if (NULL == hNamespase) {
                            PrintErrorMsg(L"OpenPrivateNamespace: ");
                        }
                        else {
                            wcout << L"Namespace opened." << endl;
                        }
                    }
                    else {
                        PrintErrorMsg(L"CreateNamespace: ");
                    }
                }
                else {
                    wcout << L"Namespace created." << endl;
                }
                if (NULL != hNamespase) {

                    hMutex = CreateMutex(NULL, FALSE,
                        L"Local\\BushNamespace\\BushMutex");

                    if (NULL == hMutex) {
                        PrintErrorMsg(L"CreateNamespaceMutex: ");
                    }
                    else {
                        // Check the reason of success
                        DWORD errCode = GetLastError();
                        if (ERROR_ALREADY_EXISTS == errCode) {
                            wcout << L"Named mutex in private namespace opened."
                                << endl;
                        }
                        else {
                            wcout << L"Named mutex in private namespace created."
                                << endl;
                        }
                    }
                }              
            }
        }
    }

    wcout << L"Press any char for exit..." << endl;
    wchar_t c;
    wcin >> c;

    if (NULL != hGlobalMutex) {
        CloseHandle(hGlobalMutex);
        hGlobalMutex = NULL;
    }

    if (NULL != hLocalMutex) {
        CloseHandle(hLocalMutex);
        hLocalMutex = NULL;
    }

    if (NULL == hMutex) {
        CloseHandle(hMutex);
        hMutex = NULL;
    }
    if (NULL != hNamespase) {
        ClosePrivateNamespace(hNamespase, 0);
        hNamespase = NULL;
    }
    if (NULL != hBoundary) {
        DeleteBoundaryDescriptor(hBoundary);
        hBoundary = NULL;
    }
}
catch (...) {
    wcerr << L"Unknown error." << endl;
    return 1;
}

void PrintErrorMsg(LPCTSTR prefix) {
    DWORD errCode = GetLastError();
    LPTSTR msg = NULL;
    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL, errCode, 0, (LPTSTR)&msg, 0, NULL);
    wcerr << prefix << msg << endl;
    HeapFree(GetProcessHeap(), 0, msg);
}


На скрине результат консольного вывода двух разных процессов:

В Process Explorer видим следующую картину (см. выделенное красным):


Смотрим WinObj, запустив её с правами администратора:



Комментариев нет: