//*************************************************************************** // // METHPROV.CPP // // Module: WBEM Method provider sample code // // Purpose: Defines the CMethodPro class. An object of this class is // created by the class factory for each connection. // // Copyright (c)1998 Microsoft Corporation, All Rights Reserved // //*************************************************************************** #include #include "methprov.h" #include #include #include #include "cominit.h" //*************************************************************************** // // CMethodPro::CMethodPro // CMethodPro::~CMethodPro // //*************************************************************************** CMethodPro::CMethodPro() { InterlockedIncrement(&g_cObj); return; } CMethodPro::~CMethodPro(void) { InterlockedDecrement(&g_cObj); return; } //*************************************************************************** // // CMethodPro::QueryInterface // CMethodPro::AddRef // CMethodPro::Release // // Purpose: IUnknown members for CMethodPro object. //*************************************************************************** STDMETHODIMP CMethodPro::QueryInterface(REFIID riid, PPVOID ppv) { *ppv=NULL; if (IID_IUnknown==riid || IID_IWbemServices == riid || IID_IWbemProviderInit==riid) if(riid== IID_IWbemServices){ *ppv=(IWbemServices*)this; } if(IID_IUnknown==riid || riid== IID_IWbemProviderInit){ *ppv=(IWbemProviderInit*)this; } if (NULL!=*ppv) { AddRef(); return NOERROR; } else return E_NOINTERFACE; } STDMETHODIMP_(ULONG) CMethodPro::AddRef(void) { return ++m_cRef; } STDMETHODIMP_(ULONG) CMethodPro::Release(void) { ULONG nNewCount = InterlockedDecrement((long *)&m_cRef); if (0L == nNewCount) delete this; return nNewCount; } /*********************************************************************** * * *CMethodPro::Initialize * * * *Purpose: This is the implementation of IWbemProviderInit. The method * * is need to initialize with CIMOM. * * * ***********************************************************************/ STDMETHODIMP CMethodPro::Initialize(LPWSTR pszUser, LONG lFlags, LPWSTR pszNamespace, LPWSTR pszLocale, IWbemServices *pNamespace, IWbemContext *pCtx, IWbemProviderInitSink *pInitSink) { m_pWbemSvcs=pNamespace; m_pWbemSvcs->AddRef(); //Let CIMOM know your initialized //=============================== pInitSink->SetStatus(WBEM_S_INITIALIZED,0); return WBEM_S_NO_ERROR; } /************************************************************************ * * *CMethodPro::ExecMethodAsync * * * *Purpose: This is the Async function implementation. * * The only method supported in this sample is GetUserID. It * * returns the user name and domain name of the thread in which * * the provider is called. The mof definition is * * * * [dynamic: ToInstance, provider("UserIDProvider")]class UserID * * { * * [implemented, static] * * void GetUserID( * * [out]string sDomain, * * [out] string sUser, * * [out] string dImpLevel, * * [out] string sPrivileges [], * * [out] boolean bPrivilegesEnabled []); * * }; * * * ************************************************************************/ STDMETHODIMP CMethodPro::ExecMethodAsync(const BSTR ObjectPath, const BSTR MethodName, long lFlags, IWbemContext* pCtx, IWbemClassObject* pInParams, IWbemObjectSink* pResultSink) { HRESULT hr = WBEM_E_FAILED; if (FAILED (WbemCoImpersonateClient ())) return WBEM_E_ACCESS_DENIED; IWbemClassObject * pClass = NULL; IWbemClassObject * pOutClass = NULL; IWbemClassObject* pOutParams = NULL; if(_wcsicmp(MethodName, L"GetUserID")) return WBEM_E_INVALID_PARAMETER; // Allocate some BSTRs BSTR ClassName = SysAllocString(L"UserID"); BSTR DomainOutputArgName = SysAllocString(L"sDomain"); BSTR UserOutputArgName = SysAllocString(L"sUser"); BSTR ImpOutputArgName = SysAllocString(L"sImpLevel"); BSTR PrivOutputArgName = SysAllocString(L"sPrivileges"); BSTR EnabledOutputArgName = SysAllocString(L"bPrivilegesEnabled"); BSTR retValName = SysAllocString(L"ReturnValue"); // Get the class object, this is hard coded and matches the class // in the MOF. A more sophisticated example would parse the // ObjectPath to determine the class and possibly the instance. hr = m_pWbemSvcs->GetObject(ClassName, 0, pCtx, &pClass, NULL); if(hr != S_OK) { pResultSink->SetStatus(0,hr, NULL, NULL); return WBEM_S_NO_ERROR; } // This method returns values, and so create an instance of the // output argument class. hr = pClass->GetMethod(MethodName, 0, NULL, &pOutClass); pOutClass->SpawnInstance(0, &pOutParams); // Get the user and domain from the thread token HANDLE hToken; HANDLE hThread = GetCurrentThread (); // Open thread token if (OpenThreadToken (hThread, TOKEN_QUERY, true, &hToken)) { DWORD dwRequiredSize = 0; DWORD dwLastError = 0; bool status = false; // Step 0 - get impersonation level SECURITY_IMPERSONATION_LEVEL secImpLevel; if (GetTokenInformation (hToken, TokenImpersonationLevel, &secImpLevel, sizeof (SECURITY_IMPERSONATION_LEVEL), &dwRequiredSize)) { VARIANT var; VariantInit (&var); var.vt = VT_BSTR; switch (secImpLevel) { case SecurityAnonymous: var.bstrVal = SysAllocString (L"Anonymous"); break; case SecurityIdentification: var.bstrVal = SysAllocString (L"Identification"); break; case SecurityImpersonation: var.bstrVal = SysAllocString (L"Impersonation"); break; case SecurityDelegation: var.bstrVal = SysAllocString (L"Delegation"); break; default: var.bstrVal = SysAllocString (L"Unknown"); break; } pOutParams->Put(ImpOutputArgName , 0, &var, 0); VariantClear (&var); } DWORD dwUSize = sizeof (TOKEN_USER); TOKEN_USER *tu = (TOKEN_USER *) new BYTE [dwUSize]; // Step 1 - get user info if (0 == GetTokenInformation (hToken, TokenUser, (LPVOID) tu, dwUSize, &dwRequiredSize)) { delete [] tu; dwUSize = dwRequiredSize; dwRequiredSize = 0; tu = (TOKEN_USER *) new BYTE [dwUSize]; if (!GetTokenInformation (hToken, TokenUser, (LPVOID) tu, dwUSize, &dwRequiredSize)) dwLastError = GetLastError (); else status = true; } if (status) { // Dig out the user info dwRequiredSize = BUFSIZ; char *userName = new char [dwRequiredSize]; char *domainName = new char [dwRequiredSize]; SID_NAME_USE eUse; LookupAccountSid (NULL, (tu->User).Sid, userName, &dwRequiredSize, domainName, &dwRequiredSize, &eUse); VARIANT var; VariantInit (&var); var.vt = VT_BSTR; wchar_t wUserName [BUFSIZ]; size_t len = mbstowcs( wUserName, userName, strlen (userName)); wUserName [len] = NULL; var.bstrVal = SysAllocString (wUserName); pOutParams->Put(UserOutputArgName , 0, &var, 0); SysFreeString (var.bstrVal); wchar_t wDomainName [BUFSIZ]; len = mbstowcs( wDomainName, domainName, strlen (domainName)); wDomainName [len] = NULL; var.bstrVal = SysAllocString (wDomainName); pOutParams->Put(DomainOutputArgName , 0, &var, 0); VariantClear (&var); delete [] userName; delete [] domainName; } delete [] tu; // Step 2 - get privilege info status = false; dwRequiredSize = 0; DWORD dwSize = sizeof (TOKEN_PRIVILEGES); TOKEN_PRIVILEGES *tp = (TOKEN_PRIVILEGES *) new BYTE [dwSize]; // Step 2 - get privilege info if (0 == GetTokenInformation (hToken, TokenPrivileges, (LPVOID) tp, dwSize, &dwRequiredSize)) { delete [] tp; dwSize = dwRequiredSize; dwRequiredSize = 0; tp = (TOKEN_PRIVILEGES *) new BYTE [dwSize]; if (!GetTokenInformation (hToken, TokenPrivileges, (LPVOID) tp, dwSize, &dwRequiredSize)) { dwLastError = GetLastError (); } else status = true; } else status = true; if (status) { SAFEARRAYBOUND rgsabound; rgsabound.cElements = tp->PrivilegeCount; rgsabound.lLbound = 0; SAFEARRAY *pPrivArray = SafeArrayCreate (VT_BSTR, 1, &rgsabound); SAFEARRAY *pEnabArray = SafeArrayCreate (VT_BOOL, 1, &rgsabound); for (ULONG i = 0; i < tp->PrivilegeCount; i++) { TCHAR name [BUFSIZ]; WCHAR wName [BUFSIZ]; DWORD dwRequiredSize = BUFSIZ; if (LookupPrivilegeName (NULL, &(tp->Privileges [i].Luid), name, &dwRequiredSize)) { VARIANT_BOOL enabled = (tp->Privileges [i].Attributes & (SE_PRIVILEGE_ENABLED | SE_PRIVILEGE_ENABLED_BY_DEFAULT)) ? VARIANT_TRUE : VARIANT_FALSE; mbstowcs (wName, name, strlen (name)); wName [dwRequiredSize] = NULL; BSTR bsName = SysAllocString (wName); SafeArrayPutElement (pPrivArray, (LONG*) &i, bsName); SafeArrayPutElement (pEnabArray, (LONG*) &i, &enabled); } } VARIANT var1; var1.vt = VT_ARRAY|VT_BSTR; var1.parray = pPrivArray; pOutParams->Put(PrivOutputArgName , 0, &var1, 0); VariantClear (&var1); var1.vt = VT_ARRAY|VT_BOOL; var1.parray = pEnabArray; pOutParams->Put(EnabledOutputArgName , 0, &var1, 0); VariantClear (&var1); } delete [] tp; CloseHandle (hToken); } CloseHandle (hThread); // Send the output object back to the client via the sink. Then // release the pointers and free the strings. hr = pResultSink->Indicate(1, &pOutParams); pOutParams->Release(); pOutClass->Release(); pClass->Release(); SysFreeString(ClassName); SysFreeString(DomainOutputArgName); SysFreeString(UserOutputArgName); SysFreeString(ImpOutputArgName); SysFreeString(PrivOutputArgName); SysFreeString(EnabledOutputArgName); SysFreeString(retValName); // all done now, set the status hr = pResultSink->SetStatus(0,WBEM_S_NO_ERROR,NULL,NULL); return WBEM_S_NO_ERROR; }