创建具有管理员权限的COM对象

在Windows操作系统中,对于需要管理员权限才能执行的操作,如写入HKEY_LOCAL_MACHINE注册表,可以通过创建一个COM对象来实现。本文将介绍如何创建这样一个COM对象,并使用它来在需要管理员权限的情况下写入注册表。

如果应用程序是一个混合应用程序,即既有需要管理员权限的操作,也有不需要管理员权限的操作,那么本文将对非常有用。将通过创建一个COM对象,使得应用程序在需要时能够提升权限。

使用代码

在注册服务器之后,应用程序可以使用CElevatedRegistryWriter类来提升权限并随时写入注册表。

C++ CElevatedRegistryWriter writter(GetConsoleWindow()); if (writter.WriteString(_T( " Software\\Microsoft" ), _T( " Message" ), _T( " Hello World" )) && writter.WriteLong(_T( " Software\\Microsoft" ), _T( " MyValue" ), 100 )) { print( " All done!" ); }

阶段1:创建注册表COM对象

首先,创建一个新的ATL项目(将其命名为Elevator)。在ATL项目向导对话框中选择可执行文件(EXE)作为服务器类型。然后,向Elevator项目添加一个新类。选择ATL简单对象,并在添加类对话框中点击添加。

在ATL简单对象向导对话框中,将类命名为"LocalMachineWriter",然后点击完成。接下来,为接口ILocalMachineWriter添加一个新方法。将新方法命名为WriteString,并添加三个参数:path、var和value,它们都是BSTR类型,然后点击完成。

重复步骤6和7为WriteLong方法(value参数必须是LONG类型)。然后,修改CLocalMachineWriter::WriteString和CLocalMachineWriter::WriteLong的代码如下:

STDMETHODIMP CLocalMachineWriter::WriteString(BSTR path, BSTR var, BSTR value) { HKEY hk = NULL; if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ | KEY_WRITE, &hk)) return E_FAIL; bool nReturn = E_FAIL; if (ERROR_SUCCESS == RegSetValueEx(hk, var, 0, REG_SZ, (const BYTE*)value, (1 + (DWORD)_tcslen(value)) * sizeof(TCHAR))) nReturn = S_OK; RegCloseKey(hk); return nReturn; } STDMETHODIMP CLocalMachineWriter::WriteLong(BSTR path, BSTR var, LONG value) { HKEY hk = NULL; if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, path, 0, KEY_READ | KEY_WRITE, &hk)) return E_FAIL; bool nReturn = E_FAIL; if (ERROR_SUCCESS == RegSetValueEx(hk, var, 0, REG_DWORD, (const BYTE*)&value, sizeof(LONG))) nReturn = S_OK; RegCloseKey(hk); return nReturn; }

现在,需要使COM对象能够提升权限,通过向注册表添加两个条目。打开LocalMachineWriter.rgs并添加以下内容:

HKCR { Elevator.LocalMachineWriter.1 = s 'LocalMachineWriter Class' { CLSID = s '{E89BECE0-84AC-4EE0-BC26-835C269C166F}' } Elevator.LocalMachineWriter = s 'LocalMachineWriter Class' { CLSID = s '{E89BECE0-84AC-4EE0-BC26-835C269C166F}' CurVer = s 'Elevator.LocalMachineWriter.1' } NoRemove CLSID { ForceRemove {E89BECE0-84AC-4EE0-BC26-835C269C166F} = s 'LocalMachineWriter Class' { ProgID = s 'Elevator.LocalMachineWriter.1' VersionIndependentProgID = s 'Elevator.LocalMachineWriter' ForceRemove 'Programmable' LocalServer32 = s '%MODULE%' TypeLib' = s '{A38F2A11-AF97-4903-9DF3-F757291C9358}' val LocalizedString = s '@%MODULE%,-100' ForceRemove Elevation = s '' { val Enabled = d '1' } } } }

有关.rgs文件的信息,请参考此链接:http://msdn.microsoft.com/en-us/library/k32htktc.aspx。有关为什么要添加这些条目的信息,请参考此链接:http://msdn.microsoft.com/en-us/library/ms679687.aspx。

现在,编译COM对象。最后,需要注册COM对象,以便其他应用程序可以使用它。打开一个提升权限的Cmd(在执行CMD.exe时按下Ctrl+Shift键),转到Debug或Release目录,并使用/RegServer参数注册服务器:

完成了!已经创建了一个COM对象,使其能够写入本地计算机。现在,需要创建客户端代码,以提升的权限运行COM对象。

创建一个新的Win32控制台应用程序。将其命名为Client,并按OK。在Win32应用程序向导对话框中选择控制台应用程序,然后按完成。

修改StdAfx.h文件,包括Windows.h和comutil.h。

#include #include #ifdef _DEBUG #pragma comment(lib, "comsuppwd.lib") #else #pragma comment(lib, "comsuppw.lib") #endif

包括了ComUtil.h和库comsuppw,因为将使用_bstr_t类(http://msdn.microsoft.com/en-us/library/zthfhkd6(VS.71).aspx)。

从Elevator项目目录复制Elevator_i.c和Elevator_i.h到新客户端应用程序目录(这些文件是必要的,因为它们声明了接口和接口的GUID以及对象)。

向客户端应用程序添加一个新类:在添加类对话框中选择C++类。将新类命名为CElevatedRegistryWriter,并在通用C++类向导对话框中点击完成。

替换ElevatedRegistryWriter.h和ElevatedRegistryWriter.cpp的内容如下:

#pragma once #include "Elevator_i.h" class CElevatedRegistryWriter { HWND wndParent; ILocalMachineWriter* object; public: CElevatedRegistryWriter(HWND wndParent); ~CElevatedRegistryWriter(); bool WriteString(LPCTSTR path, LPCTSTR var, LPCTSTR value); bool WriteLong(LPCTSTR path, LPCTSTR var, LONG value); private: HRESULT CoCreateInstanceAsAdmin(HWND hwnd, REFCLSID rclsid, REFIID riid, __out void** ppv); }; #include "stdafx.h" #include "ElevatedRegistryWriter.h" int _tmain(int argc, _TCHAR* argv[]) { CoInitialize(NULL); MessageBox(NULL, _T("Accept to elevate"), _T("Testing elevation"), MB_OK); CElevatedRegistryWriter writter(GetConsoleWindow()); if (writter.WriteString(_T("Software\\Microsoft"), _T("Message"), _T("Hello World")) && writter.WriteLong(_T("Software\\Microsoft"), _T("MyValue"), 100)) {} CoUninitialize(); return 0; }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485