Windows主题编程&内核对象

1.
一个进程在起先化时,系统以会他分配一个空的句子柄表,那个句子柄表仅供本对象下,不供用户对象同GDI对象下。进程在首赖

 
 初叶化时,该句柄表为空。句柄表是一个出于数据结构组成的高频组,包含一个根本对象指针,一个做客掩码和片标明。系统用索引来

 
 标识内核对象的信保存在过程句柄表中之具体地点,句柄值除为4不怕为找引值(针对不同版本的windows系统可能两样)。

2.
设留心内核对象回来值INVALID_HANDLE_VALUE(-1)和NULL(0)的区分,凡是用于创设基础对象的函数,在检查其的返值通常

   务必非常密切。一般只有CreateFile才再次来到INVALID_HANDLE_VALUE。

3.
于本对象,操作系统执行操作过程为:进程终止时,系统会自行扫描进程句柄表。即使这表中暴发另有效的记录项(即经过经过终

   
止前无关的靶子),操作系统会为大家关闭那些目的句柄(只要那么些目的的使用计数为0)。

  1. 经过共享内核对象机制

    (1). 对象句柄继承

           
 a.创造基础对象时拿SECURITY_ATTRIBUTES结构的bInheritHandle设为TRUE

           
 b.将CreateProcess参数的bInheritHandle设为TRUE,注:对象句柄的持续只碰面当生成子进程的时有

           
 c.子进程无法查看自己继续了其它目的句柄,在开发阶段最好用文档注脚

    (2). 改变句柄标志 

             SetHandleInformation(HANDLE hObject, DWORD dwMask, DWORD
dwFlags)

           
 五个根本标志HANDLE_FLAG_INHERIT和HANDLE_FLAG_PROTECT_FROM_CLOSE

     (3). 为目标命名

           许多(但不是浑)内核对象都可开展命名

     (4). 复制对象句柄

         
 从一个经过的语句柄表中取得一个记录项,然后以任何一个过程的句子柄表中开创是记录项的副本(DuplicateHandle)

  1. 实例

     

图片 1图片 2

typedef HANDLE (_stdcall* BOUNDARYDESCRIPTOR)(LPTSTR, DWORD);
BOUNDARYDESCRIPTOR CreateBoundaryDescriptor;

typedef BOOL (_stdcall* ADDSIDTOBOUNDARYDESCRIPTOR)(HANDLE *, PSID);
ADDSIDTOBOUNDARYDESCRIPTOR AddSIDToBoundaryDescriptor;

typedef HANDLE (_stdcall *CREATEPRIVATENAMESPACE)(LPSECURITY_ATTRIBUTES, LPVOID, LPCSTR);
CREATEPRIVATENAMESPACE CreatePrivateNamespace;

typedef HANDLE (_stdcall* OPENPRIVATENAMESPACE)(PVOID, LPCSTR);
OPENPRIVATENAMESPACE OpenPrivateNamespace;

void CSingletonDlg::CheckInstances()
{
    HMODULE hKernel = LoadLibrary("Kernel32.dll");

    if (hKernel)
    {
        CreateBoundaryDescriptor = (BOUNDARYDESCRIPTOR)GetProcAddress(hKernel, "CreateBoundaryDescriptorA");
        // 注意函数名AddSIDToBoundaryDescriptor后面没带'A'
        AddSIDToBoundaryDescriptor = (ADDSIDTOBOUNDARYDESCRIPTOR)GetProcAddress(hKernel, "AddSIDToBoundaryDescriptor"); 

        CreatePrivateNamespace = (CREATEPRIVATENAMESPACE)GetProcAddress(hKernel, "CreatePrivateNamespaceA");
        OpenPrivateNamespace = (OPENPRIVATENAMESPACE)GetProcAddress(hKernel, "OpenPrivateNamespaceA");
    }

    /*HANDLE */m_hBoundaryDescriptor = CreateBoundaryDescriptor("3-Boundary", 0);

    if (NULL == m_hBoundaryDescriptor)
    {
        // 创建边界描述符失败
        return;
    }

    // 为边界描述符关联一个SID
    BYTE localAdminSID[SECURITY_MAX_SID_SIZE];
    PSID pLocalAdminSID = &localAdminSID;
    DWORD cbSID = sizeof(localAdminSID);
    if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, pLocalAdminSID, &cbSID))
    {
        // 创建SID失败
        return;
    }

    if (!AddSIDToBoundaryDescriptor(&m_hBoundaryDescriptor, pLocalAdminSID))
    {
        // 链接边界描述符失败
        return;
    }

    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = FALSE;
    if (!ConvertStringSecurityDescriptorToSecurityDescriptor(
        TEXT("D:(A;;GA;;;BA)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL)) 
    {
            return;
    }

    // 创建命名空间
    /*HANDLE */m_hPrivateNameSpace = CreatePrivateNamespace(&sa, m_hBoundaryDescriptor, "3-Namespace");
    LocalFree(sa.lpSecurityDescriptor);

    // 检查已创建的命名空间:看是否有权限访问ERROR_ACCESS_DENIED和该命名空间是否存在ERROR_ALREADY_EXISTS
    DWORD dwLastErro = GetLastError();
    if (m_hPrivateNameSpace == NULL)
    {
        if (ERROR_ACCESS_DENIED == dwLastErro)
        {
            return;
        }
        else if (ERROR_ALREADY_EXISTS == dwLastErro)
        {
            m_hPrivateNameSpace = OpenPrivateNamespace(m_hBoundaryDescriptor, "3-Namespace");

            if (NULL == m_hPrivateNameSpace)
            {
                return;
            }
        }
    }

    // 创建互斥对象
    char cMutexName[MAX_PATH] = {0};
    StringCchPrintf(cMutexName, sizeof(MAX_PATH), "%s\\%s", "3-Namespace", "Single");
    g_hSingleton = CreateMutex(NULL, FALSE, cMutexName);

    if (GetLastError() == ERROR_ALREADY_EXISTS) 
    {
        AddText(TEXT("Another instance of Singleton is running:\r\n"));
        AddText(TEXT("--> Impossible to access application features.\r\n"));
    } else  
    {
        AddText(TEXT("First instance of Singleton:\r\n"));
        AddText(TEXT("--> Access application features now.\r\n"));
    }

    FreeLibrary(hKernel);
}

View Code

 

  1. 附录

    boundary 分界线;范围

    descriptor 描述符

    (1). HANDLE CreateBoundaryDescriptor(PCTSTR pszName, DWORD dwFlags)

          创造边界描述称

          第二只参数为日后保留,近年来没什么用,为0

         
函数重临的绝不是一个句柄,而是一个对用户情势社团的指针,结构面临包含了界线的定义,不要将再次来到的语句柄值传为

          CloseHandle,而若传被DeleteBoundaryDescriptor

    (2). BOOL AddSIDToBoundaryDescriptor(HANDLE *phBoundaryDescriptor,
PSID pRequireSid)

          将一个特权用户组的SID与边界描述称关联起来

    (3). HANDLE CreatePrivateNameSpace(PSECURITY_ATTRIBUTES, PVOID
pvBoundaryDescriptor, pszAliasPrefix)

         
对创建好的命名空间举行反省GetLastError(),ERROR_ACCESS_DENIED、ERROR_ALREADY_EXISTS

    (4). HANDLE OpenPrivateNameSpace( PVOID pvBoundaryDescriptor,
pszAliasPrefix)

    (5). ClosePrivateNameSpace(HANDLE hNamespace, DWORD dwFlags)

         
假设我们曾经创立了命名空间,而且未指望其以闭馆后依旧可见,可以就此PRIVATE_NAMESPACE_FLAG_DESTRPY作为次只参数,反的则为0

    (6). BOOL WINAPI CreateWellKnowSid()

          创立一个SID

          参数1:WellKnowSidType
SID类型,WELL_KNOW_SID_TYPE是枚举类型,它蕴含一名目繁多的安描述符类型

        参数2: _in_opt PSID DomainSid  
 指向创设了SID的地段的指针,为NULL时表示当地电脑

          参数3:_out_opt PSID pSid          指向存储SID地址

          参数4: _inout DWORD *cbSid      指向存储pSid的尺寸的地方   

相关文章