📄 allusernode.cpp
字号:
#include "stdafx.h"
#include "AllUsernode.h"
#define STRSAFE_NO_DEPRECATE
#include <strsafe.h>
#include "comutil.h"
// {0BC9978F-2767-4748-8590-8E93349D524E}
static const GUID CAllUserNodeGUID_NODETYPE=
{ 0xbc9978f, 0x2767, 0x4748, { 0x85, 0x90, 0x8e, 0x93, 0x34, 0x9d, 0x52, 0x4e } };
const GUID* CAllUserNode::m_NODETYPE = &CAllUserNodeGUID_NODETYPE;
const OLECHAR* CAllUserNode::m_SZNODETYPE = OLESTR("0BC9978F-2767-4748-8590-8E93349D524E");
const OLECHAR* CAllUserNode::m_SZDISPLAY_NAME = OLESTR("本地用户");
const CLSID* CAllUserNode::m_SNAPIN_CLASSID = &CLSID_AuthorityMgr;
HRESULT CAllUserNode::OnExpand(BOOL bExpand, IConsole *pConsole, HSCOPEITEM parent)
{
if (!bExpand)
return S_OK;
m_scopeDataItem.ID = parent;
HSCOPEITEM hChild = NULL;
long cookie = 0;
CComQIPtr<IConsoleNameSpace, &IID_IConsoleNameSpace> spConsoleNameSpace(pConsole);
spConsoleNameSpace->GetChildItem(m_scopeDataItem.ID, &hChild, &cookie);
if (hChild != NULL)
spConsoleNameSpace->DeleteItem(m_scopeDataItem.ID, FALSE);
// cache the stuff
m_pConsoleNameSpace = spConsoleNameSpace;
m_scopeitem = parent;
if (m_bViewUpdated == false && m_running == false)
{
StartThread();
}
return S_OK;
//after this MMC calls GetDisplayInfo() which
//in ATL translates to GetScopePaneInfo()
}
BOOL CAllUserNode::InitChildren()
{
HRESULT hr;
IADsContainer *pCont;
CoInitialize(NULL);
////////////////////////////////
// 绑定到一个目录对象这里绑定到一个本地计算机
//目标计算机可能需要修改,或提供更灵活的机制自动得到本地计算机名和域名
//////////////////////////////////
hr = ADsGetObject(L"WinNT://WORKGROUP/XP", IID_IADsContainer, (void**) &pCont );
if ( !SUCCEEDED(hr) )
{
return FALSE;
}
///////////////////////////////////
// 建立过滤器
/////////////////////////////////
LPWSTR pszFilter[] = { L"user" };
DWORD dwNumber = sizeof( pszFilter ) /sizeof(LPWSTR);
VARIANT var;
hr = ADsBuildVarArrayStr( pszFilter, dwNumber, &var );
if ( !SUCCEEDED(hr) )
{
pCont->Release();
return hr;
}
///////////////////////////////////
// 设置过滤器
/////////////////////////////////
hr = pCont->put_Filter(var);
VariantClear(&var);
if (!SUCCEEDED(hr) )
{
pCont->Release();
return hr;
}
/////////////////////////////////
// 枚举所有用户对象,初试化所有用户对象节点
/////////////////////////////////
IEnumVARIANT *pEnum = NULL;
hr = ADsBuildEnumerator( pCont, &pEnum );
if ( SUCCEEDED(hr) )
{
VARIANT var;
VariantInit(&var);
ULONG lFetch;
IADs *pChild=NULL;
IADsMembers *pMembers=NULL;
IADsUser *pUser=NULL;
while( SUCCEEDED(ADsEnumerateNext( pEnum, 1, &var, &lFetch )) && lFetch == 1 )
{
hr = V_DISPATCH(&var)->QueryInterface( IID_IADs, (void**) &pChild );
if ( SUCCEEDED(hr) )
{
BSTR bstrName;
BSTR bstrClass;
// 得到用户目录对象的相关信息
pChild->get_Name(&bstrName);
pChild->get_Class(&bstrClass);
//BSTR bstrGUID;
//pChild->get_GUID(&bstrGUID);
BSTR bstrADsPath;
pChild->get_ADsPath(&bstrADsPath);
//*********************************************
//以下查询该用户的详细信息,包括全名,描述,用户所属于的所有组
//*********************************************
const size_t cchBuffer = 500;
static _TCHAR buf[cchBuffer];
StringCchPrintf(buf, cchBuffer, _T("%s,User"),_com_util::ConvertBSTRToString(bstrADsPath));
//注意下面的Ansi到unicode的字符转换
USES_CONVERSION;
hr=ADsGetObject((LPWSTR)A2W(buf),IID_IADsUser,(void**)&pUser);
if ( !SUCCEEDED(hr) )
{
return FALSE;
}
BSTR bstrFullName;
pUser->get_FullName(&bstrFullName);
BSTR bstrDes;
pUser->get_Description(&bstrDes);
//考虑到Windows NT对GUID的支持的特殊性,
//在此,采用ADsPath来代替GUID的作用
//对于ActiveDictionary,我们可以使用GUID来
//标识对象,因为,GUID一旦生成,将不再改变
//而ADsPath会因为用户名/组名改变引起变化
//造成程序数据的不一致
BSTR bstrGUID;
//pUser->get_GUID(&bstrGUID);
pUser->get_ADsPath(&bstrGUID);
//******************************************************
//以下得到该用户所有属于的组
//******************************************************
//清空buf,用于存储组的信息
StringCchPrintf(buf, cchBuffer, _T("%s"), _T(""));
hr=pUser->Groups(&pMembers);
if ( !SUCCEEDED(hr) )
{
return FALSE;
}
IUnknown *pUnk;
hr = pMembers->get__NewEnum(&pUnk);
if ( SUCCEEDED(hr) ){
IEnumVARIANT *pGroupEnum = NULL;
hr = pUnk->QueryInterface(IID_IEnumVARIANT,(void**)&pGroupEnum);
if ( SUCCEEDED(hr) ){
// 开始枚举
BSTR bstr;
VARIANT varGroup;
IADs *pADs;
ULONG lGroupFetch;
IDispatch *pDisp;
VariantInit(&varGroup);
hr = pGroupEnum->Next(1, &varGroup, &lGroupFetch);
while(hr == S_OK)
{
if (lGroupFetch == 1)
{
pDisp = V_DISPATCH(&varGroup);
pDisp->QueryInterface(IID_IADs, (void**)&pADs);
pADs->get_Name(&bstr);
if(strlen(buf)==0){//如果为第一个组
StringCchPrintf(buf, cchBuffer, _T("%s"),_com_util::ConvertBSTRToString(bstr));
}else{//不为第一个组时,添加到一前的组名前,用","分开
StringCchPrintf(buf, cchBuffer, _T("%s,%s"),buf,_com_util::ConvertBSTRToString(bstr));
}
SysFreeString(bstr);
pADs->Release();
}
VariantClear(&varGroup);
pDisp=NULL;
hr = pGroupEnum->Next(1, &varGroup, &lGroupFetch);
};
hr = pGroupEnum->Release();
}
}
//******************************************************
//以上得到该用户所有属于的组
//******************************************************
//名称
CComBSTR param_bstrName(bstrName);
//全名
CComBSTR param_bstrFullName(bstrFullName);
//描述
CComBSTR param_bstrDes(bstrDes);
//所属于的组
CComBSTR param_bstrGroups(buf);
m_vecItems.push_back(new CUserNode(param_bstrName.Detach(),
param_bstrFullName.Detach(),param_bstrDes.Detach(),param_bstrGroups.Detach(),bstrGUID));
// 释放变量
SysFreeString(bstrName);
SysFreeString(bstrClass);
pChild->Release();
}
VariantClear(&var);
}
}
if ( pEnum )
{
ADsFreeEnumerator( pEnum );
}
pCont->Release();
CoUninitialize();
//插入节点
for(int i=0; i<m_vecItems.size(); i++)
{
m_vecItems[i]->m_scopeDataItem.relativeID = m_scopeitem;
m_vecItems[i]->m_scopeDataItem.nImage=INDEX_USER;
m_vecItems[i]->m_scopeDataItem.nOpenImage=INDEX_USER;
hr=m_pConsoleNameSpace->InsertItem(&m_vecItems[i]->m_scopeDataItem);
_ASSERT( SUCCEEDED(hr) );
}
return true;
}
//线程体
DWORD WINAPI CAllUserNode::ThreadProc(
LPVOID lpParameter // thread data
)
{
CAllUserNode *pThis = ( CAllUserNode *)lpParameter;
EnterCriticalSection(&pThis->m_critSect);
pThis->m_running = true;
LeaveCriticalSection(&pThis->m_critSect);
pThis->InitChildren();
EnterCriticalSection(&pThis->m_critSect);
pThis->m_running = false;
pThis->m_bViewUpdated=true;
LeaveCriticalSection(&pThis->m_critSect);
return 0;
}
//启动线程
void CAllUserNode::StartThread()
{
EnterCriticalSection(&m_critSect);
m_thread = CreateThread(NULL, 0, ThreadProc, (void *)this, 0, &m_threadId);
LeaveCriticalSection(&m_critSect);
}
//结束线程
void CAllUserNode::StopThread()
{
EnterCriticalSection(&m_critSect);
m_running = false;
if (m_thread != NULL) {
// this is ugly, wait for 10 seconds, then kill the thread
DWORD res = WaitForSingleObject(m_thread, 10000);
if (res == WAIT_TIMEOUT)
TerminateThread(m_thread, 0);
CloseHandle(m_thread);
m_thread = NULL;
}
LeaveCriticalSection(&m_critSect);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -