i new to c++, need help. I am unable to start Elevation using CoCreateInstanceAsAdmin. why it fails. someone please help. Entire code is given below.
ITestCom.dll
common.h
#ifndef _COMMON_H
#define _COMMON_H
#include <ObjBase.h>
DEFINE_GUID(CLSID_TestCom,
0x6a75080d, 0x86fc, 0x45ca, 0x82, 0xb9, 0xa, 0x2e, 0xf, 0x48, 0x20, 0x72);
DEFINE_GUID(IIDTestCom,
0x8e6c7162, 0x4d3a, 0x4280, 0xa4, 0xff, 0x33, 0xd2, 0x3f, 0x5e, 0x1b, 0x6f);
DECLARE_INTERFACE_(IID_IIDTestCom, IUnknown)
{
STDMETHOD (HelloWorld)()PURE;
};
#endif
ITestCom.cpp
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#define INITGUID
#include <ObjBase.h>
#include <sddl.h>
#include "common.h"
#include <tchar.h>
#include <OleCtl.h>
#include "ITestCom.h"
#define MAX_STRING_LENGTH 255
#define GUID_SIZE 128
HANDLE g_Module;
HMODULE g_hModule = NULL;
ULONG g_cObjects = 0;
ULONG g_cLocks = 0;
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
if (DLL_PROCESS_ATTACH == ul_reason_for_call)
g_Module = hModule;
return TRUE;
}
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
HRESULT hr = NOERROR;
CTestComFactory *cf = NULL;
if(CLSID_TestCom == rclsid)
{
cf = new CTestComFactory();
if (NULL == cf)
return E_OUTOFMEMORY;
hr = cf->QueryInterface(riid,ppv);
if(FAILED(hr))
{
delete cf;
cf=NULL;
return hr;
}
}
else
hr = CLASS_E_CLASSNOTAVAILABLE;
return hr;
}
BOOL ServerCanUnloadNow(void)
{
if (0==g_cObjects && 0 == g_cLocks)
return TRUE;
else
return FALSE;
}
STDAPI DllCanUnloadNow(void)
{
if(ServerCanUnloadNow()) return S_OK;
else
return S_FALSE;
}
STDAPI DllRegisterServer(void)
{
BOOL bOK;
TCHAR szModulePath[MAXPATH +1];
TCHAR szCLSID[GUID_SIZE+1];
TCHAR szAppID[GUID_SIZE+1];
TCHAR szCLSIDKey[MAX_STRING_LENGTH+1];
TCHAR szAppIDKey[MAX_STRING_LENGTH + 1];
TCHAR szLocal[MAX_STRING_LENGTH + 1];
WCHAR wszGUID[GUID_SIZE+1];
GetModuleFileName((HMODULE)g_Module,szModulePath,MAX_STRING_LENGTH);
StringFromGUID2(CLSID_TestCom,wszGUID,sizeof(wszGUID)/sizeof(wchar_t));
_tcscpy(szCLSID,wszGUID);
StringFromGUID2(IIDTestCom,wszGUID,sizeof(wszGUID)/sizeof(wchar_t));
_tcscpy(szAppID,wszGUID);
_tcscpy(szCLSIDKey,_T("CLSID\\"));
_tcscat(szCLSIDKey,szCLSID);
_tcscpy(szAppIDKey,_T("AppID\\"));
_tcscat(szAppIDKey,szAppID);
_tcscpy(szLocal,_T("@"));
_tcscat(szLocal,szModulePath);
_tcscat(szLocal,_T(",-101"));
bOK = SetRegKeyValue(HKEY_CLASSES_ROOT,szCLSIDKey, NULL, NULL, _T("ITestCom In-Proc Server"));
bOK = SetRegKeyValue(HKEY_CLASSES_ROOT,szAppIDKey,NULL,NULL,_T(""));
bOK = SetOTSRegValue(HKEY_CLASSES_ROOT,szAppIDKey);
bOK = SetRegKeyValue(HKEY_CLASSES_ROOT,szAppIDKey,NULL,_T("DllSurrogate"),_T(""));
bOK = SetRegKeyValue(HKEY_CLASSES_ROOT,szCLSIDKey,NULL,_T("LocalizedString"),szLocal);
bOK = SetRegKeyValue(HKEY_CLASSES_ROOT,szCLSIDKey,NULL,_T("AppID"),szAppID);
if (bOK)
bOK = SetRegKeyValue(HKEY_CLASSES_ROOT,szCLSIDKey,_T("InProcServer32"),NULL,szModulePath);
bOK = SetRegKeyValue(HKEY_CLASSES_ROOT,szCLSIDKey,_T("Elevation"),_T("Enabled"),_T("1"),REG_DWORD);
if(bOK)
bOK = SetRegKeyValue(HKEY_CLASSES_ROOT,szCLSIDKey,_T("InProcServer32"),_T("ThreadingModel"),_T("Apartment"));
if (bOK)
return NOERROR;
else
return SELFREG_E_CLASS;
}
BOOL SetRegKeyValue(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszSubKey, LPTSTR lpszNamedValue, LPTSTR lpszValue, DWORD dwType)
{
BOOL bOK = FALSE;
long lErrorCode;
HKEY hKey;
TCHAR szKey[MAX_STRING_LENGTH + 1];
_tcscpy(szKey,lpszKey);
if (NULL != lpszSubKey)
{
_tcscat(szKey,_T("\\"));
_tcscat(szKey,lpszSubKey);
}
lErrorCode = RegCreateKeyEx(hKeyRoot,szKey,0,NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,NULL);
if (ERROR_SUCCESS==lErrorCode)
{
lErrorCode = RegSetValueExW(hKey, lpszNamedValue, 0 , dwType,(BYTE*)lpszValue,(_tcslen(lpszValue)+1)*sizeof(TCHAR));
if(ERROR_SUCCESS == lErrorCode)
bOK = TRUE;
RegCloseKey(hKey);
}
return bOK;
}
STDAPI DllUnregisterServer(void)
{
long lErrorCode;
TCHAR szCLSID[GUID_SIZE+1];
TCHAR szCLSIDKey[MAX_STRING_LENGTH +1];
TCHAR szInprocServer32Key[MAX_STRING_LENGTH+1];
wchar_t wszGUID[GUID_SIZE+1];
StringFromGUID2(CLSID_TestCom,wszGUID,sizeof(wszGUID)/sizeof(wchar_t));
_tcscpy(szCLSID,wszGUID);
_tcscpy(szCLSIDKey, _T("CLSID\\"));
_tcscat(szCLSIDKey, szCLSID);
_tcscpy(szInprocServer32Key,szCLSIDKey);
_tcscat(szInprocServer32Key,_T("\\InProcServer32"));
lErrorCode= RegDeleteKey(HKEY_CLASSES_ROOT,szInprocServer32Key);
if(ERROR_SUCCESS == lErrorCode)
lErrorCode = RegDeleteKey(HKEY_CLASSES_ROOT,szCLSIDKey);
if(ERROR_SUCCESS == lErrorCode)
return NOERROR;
else
return SELFREG_E_CLASS;
}
STDMETHODIMP CTestIID::QueryInterface(REFIID riid, LPVOID *ppv)
{
*ppv = NULL;
if (IID_IUnknown == riid)
*ppv = (LPVOID)(IUnknown *) this;
else if(IIDTestCom == riid)
*ppv = (LPVOID)(IID_IIDTestCom *) this;
else
return E_NOINTERFACE;
AddRef();
return NOERROR;
}
STDMETHODIMP_(ULONG)CTestIID::AddRef(void)
{
return ++m_refcnt;
}
STDMETHODIMP_(ULONG)CTestIID::Release(void)
{
--m_refcnt;
if(0==m_refcnt)
{
delete this;
return 0;
}
return m_refcnt;
}
STDMETHODIMP CTestIID::HelloWorld()
{
MessageBox(NULL,_T("Wow: I am Inside COM"),_T("COM Test For Elevation"),MB_OK);
return S_OK;
}
STDMETHODIMP CTestComFactory::QueryInterface(REFIID riid, LPVOID *ppv)
{
*ppv = NULL;
if(IID_IUnknown == riid)
*ppv=(LPVOID)(IUnknown *)this;
else if(IID_IClassFactory == riid)
*ppv = (LPVOID)(IClassFactory *) this;
else
return E_NOINTERFACE;
AddRef();
return NOERROR;
}
STDMETHODIMP_(ULONG)CTestComFactory::AddRef(void)
{
return ++m_refcnt;
}
STDMETHODIMP_(ULONG)CTestComFactory::Release(void)
{
--m_refcnt;
if (0==m_refcnt)
{
delete this;
return 0;
}
return m_refcnt;
}
STDMETHODIMP CTestComFactory::LockServer(BOOL bLock)
{
if(bLock)g_cLocks++;
else g_cLocks--;
return NOERROR;
}
STDMETHODIMP CTestComFactory::CreateInstance(IUnknown *pUnknownOuter, REFIID riid, LPVOID *ppv)
{
HRESULT hr;
CTestIID *pIID = NULL;
*ppv = NULL;
if (NULL != pUnknownOuter)
return CLASS_E_NOAGGREGATION;
pIID = new CTestIID();
if (NULL==pIID)
return E_OUTOFMEMORY;
hr = pIID->QueryInterface(riid,ppv);
if (FAILED(hr))
{
delete pIID;
pIID = NULL;
return hr;
}
g_cObjects++;
return NOERROR;
}
BOOL GetAccessPermissionsForUACServer(SECURITY_DESCRIPTOR **ppSD)
{
LPTSTR lptszSDDL = _T("O:BAG:BAD:(A;;0x3;;;IU)(A;;0x3;;;SY)");
SECURITY_DESCRIPTOR *pSD = NULL;
*ppSD = NULL;
if (ConvertStringSecurityDescriptorToSecurityDescriptor(lptszSDDL, SDDL_REVISION_1, (PSECURITY_DESCRIPTOR *)&pSD, NULL))
{
*ppSD = pSD;
return TRUE;
}
return FALSE;
}
HRESULT SetOTSRegValue(HKEY hKey, LPCWSTR tszKeyName){
HRESULT hr = S_OK;
SECURITY_DESCRIPTOR * psd = NULL;
HKEY hSubKey = NULL;
DWORD err = 0;
if(!GetAccessPermissionsForUACServer(&psd)){
hr = E_ACCESSDENIED;
goto cleanup;
}
err = RegCreateKeyEx(hKey, tszKeyName,0, NULL,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,
NULL, &hSubKey, NULL);
if(err != ERROR_SUCCESS){
hr = HRESULT_FROM_WIN32(err);
goto cleanup;
}
if(!SetAccessPermissions(hSubKey, psd)){
hr = E_ACCESSDENIED;
goto cleanup;
}
cleanup:
RegCloseKey(hSubKey);
LocalFree(psd);
return hr;
}
BOOL SetAccessPermissions(HKEY hKey, PSECURITY_DESCRIPTOR pSD)
{
BOOL bResult = FALSE;
DWORD dwLen = GetSecurityDescriptorLength(pSD);
LONG lResult;
lResult = RegSetValueEx(hKey,
_T("AccessPermission"),
0,
REG_BINARY,
(BYTE*)pSD,
dwLen);
if (lResult != ERROR_SUCCESS) goto done;
bResult = TRUE;
done:
return bResult;
}
ITestCom.h
#ifndef ITEST_COM_H
#define ITEST_COM_H
#define MAXPATH 255
#define MAX_STRING_LENGTH 255
#define GUID_SIZE 128
#include "common.h"
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppvOut);
STDAPI DllCanUnloadNow(void);
STDAPI DllRegisterServer(void);
STDAPI DllUnregisterServer(void);
BOOL GetAccessPermissionsForUACServer(SECURITY_DESCRIPTOR **ppSD);
BOOL SetAccessPermissions(HKEY hKey, PSECURITY_DESCRIPTOR pSD);
HRESULT SetOTSRegValue(HKEY hKey, LPCWSTR tszKeyName);
BOOL SetRegKeyValue(HKEY hKeyRoot, LPTSTR lpszKey, LPTSTR lpszSubKey, LPTSTR lpszNamedValue, LPTSTR lpszValue, DWORD dwType = REG_SZ);
class CTestComFactory: public IClassFactory
{
private:
int m_refcnt;
public:
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv);
STDMETHODIMP_ (ULONG) AddRef(void);
STDMETHODIMP_ (ULONG) Release(void);
STDMETHODIMP CreateInstance(IUnknown *pk, REFIID riid, void **ppv);
STDMETHODIMP LockServer(BOOL fLock);
CTestComFactory(){m_refcnt=0;}
~CTestComFactory(){}
};
class CTestIID: public IID_IIDTestCom
{
private:
int m_refcnt;
public:
CTestIID(){m_refcnt=0;}
~CTestIID(){};
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv);
STDMETHODIMP_ (ULONG) AddRef(void);
STDMETHODIMP_ (ULONG) Release(void);
STDMETHOD (HelloWorld)();
};
#endif
myclient.exe
myclient.cpp
#include <iostream>
#define INITGUID
#include <ObjBase.h>
#include<conio.h>
#include"common.h"
#include<strsafe.h>
using namespace std;
HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void ** ppv)
{
BIND_OPTS3 bo;
WCHAR wszCLSID[50];
WCHAR wszMonikerName[300];
StringFromGUID2(rclsid, wszCLSID, sizeof(wszCLSID)/sizeof(wszCLSID[0]));
HRESULT hr = StringCchPrintf(wszMonikerName, sizeof(wszMonikerName)/sizeof(wszMonikerName[0]), L"Elevation:Administrator!new:%s", wszCLSID);
if (FAILED(hr))
return hr;
memset(&bo, 0, sizeof(bo));
bo.cbStruct = sizeof(bo);
bo.hwnd = hwnd;
bo.dwClassContext = CLSCTX_LOCAL_SERVER;
return CoGetObject(wszMonikerName, &bo, riid, ppv);
}
void wmain()
{
wcout<<"Main: Entry"<<endl;
IClassFactory *pcf;
IUnknown *pUnk;
IID_IIDTestCom *pTest,*aTest;
HRESULT hr;
wcout<<"Calling CoInitialize"<<endl;
hr = CoInitialize(NULL);
if (FAILED(hr))
{
wcout<<"CoInitalized : Failed"<<endl;
_getche();
exit(-1);
}
wcout<<"CoInitalize Done"<<endl;
wcout<<"Calling CoGetClassObject" <<endl;
hr = CoGetClassObject(CLSID_TestCom,CLSCTX_INPROC_SERVER,NULL,IID_IClassFactory,(void**)&pcf);
if(FAILED(hr))
{
wcout<<"CoGetClassObject Failed"<<endl;
_getche();
exit(-1);
}
wcout<<"CoGetClassObject Done"<<endl;
_getche();
wcout<<"pcf->CreateInstance"<<endl;
hr = pcf->CreateInstance(NULL,IIDTestCom,(void**)&pTest);
if(FAILED(hr))
{
wcout<<"pcf->CreateInstance Failed"<<endl;
_getche();
exit(-1);
}
wcout<<"pcf->CreateInstance done"<<endl;
_getche();
wcout<<"Calling Function "<<endl;
hr = CoCreateInstanceAsAdmin((HWND)GetModuleHandle(NULL),CLSID_TestCom,IIDTestCom,(void**)&pTest);
if(FAILED(hr))
{
wcout<<"Failed to CreateInstance As Admin"<<endl;
_getche();
exit(-1);
}
pTest->HelloWorld();
}
Regards,
Vishal
|