文章目录
- VS - regsvr32.exe的官方工程
- 概述
- 笔记
- 官方原版实现
- 自己封装一个函数来干活(注册/反注册 COM DLL)
- END
VS - regsvr32.exe的官方工程
概述
如果是要使用COM DLL, 必须先注册。
一般手工注册就要调用regsvr32.exe xx.dll
但是控制的不够细,且一般来说,也就只能通过安装程序来注册COM DLL.
如果是一个绿色版程序集合(e.g. 解压版的程序包),启动主程序后,先判断是否能正常操作COM DLL,如果不能,则自己先在程序实现里面,将解压包内自带的COM DLL先注册一下,再使用COM DLL。
如果是这种场景的话,用系统自带的regsvr32.exe来注册COM DLL, 显然不能达到目的。
即使加 /s 参数(静默),控制的也不够细。
在看资料,里面说道,regsvr32.exe 实际上就是执行COM DLL中的导出函数(DllRegisterServer/DllUnregisterServer)来实现COM DLL的注册和反注册。
就想看一下regsvr32.exe的实现。
翻硬盘时,居然看到微软官方开源库有这个工程的源码:P
那就可以直接看源码了,不用IDA了。
工程位置 - D:\3rd_prj\vs\VCSamples\VC2008Samples\MFC\controls\regsvr
微软官方开源库地址 - https://github.com/microsoft/VCSamples.git
笔记
官方原版实现
// regsvr.cpp : Program to invoke OLE self-registration on a DLL.
//
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.#include <windows.h>
#include <ole2.h>
#include <tchar.h>
#include <malloc.h>
#include <stdio.h>
#include "resource.h"#define FAIL_ARGS 1
#define FAIL_OLE 2
#define FAIL_LOAD 3
#define FAIL_ENTRY 4
#define FAIL_REG 5const TCHAR _szAppName[] = _T("RegSvr32");
const char _szDllRegSvr[] = "DllRegisterServer";
const char _szDllUnregSvr[] = "DllUnregisterServer";
HINSTANCE _hInstance;BOOL _bSilent;
BOOL _bConsole;#define SafePutts(string) ((stdout >= 0) ? _putts(string) : 0)void
FormatString2(LPTSTR lpszOut,int nOutSize,LPCTSTR lpszFormat,LPCTSTR lpsz1,LPCTSTR lpsz2)
{LPCTSTR pchSrc = lpszFormat;LPTSTR pchDest = lpszOut;while (*pchSrc != '\0') {if (pchSrc[0] == '%' && (pchSrc[1] >= '1' && pchSrc[1] <= '2')) {_tcscpy_s(pchDest, nOutSize, (LPCTSTR)(pchSrc[1] == '1' ? lpsz1 : lpsz2));pchDest += lstrlen(pchDest);pchSrc += 2;} else {if (_istlead(*pchSrc))*pchDest++ = *pchSrc++; // copy first of 2 bytes*pchDest++ = *pchSrc++;}}*pchDest = '\0';
}#define MAX_STRING 1024void
DisplayMessage(UINT ids,LPCTSTR pszArg1 = NULL,LPCTSTR pszArg2 = NULL,BOOL bUsage = FALSE,BOOL bInfo = FALSE)
{if (_bSilent && !_bConsole)return;TCHAR szFmt[MAX_STRING];LoadString(_hInstance, ids, szFmt, MAX_STRING);TCHAR szText[MAX_STRING];FormatString2(szText, MAX_STRING, szFmt, pszArg1, pszArg2);if (bUsage) {int cch = (int)_tcslen(szText);LoadString(_hInstance, IDS_USAGE, szText + cch, MAX_STRING - cch);}if (! _bSilent)MessageBox(NULL, szText, _szAppName,MB_TASKMODAL | (bInfo ? MB_ICONINFORMATION : MB_ICONEXCLAMATION));if (_bConsole) {TCHAR szMessage[MAX_STRING];FormatString2(szMessage, MAX_STRING, _T("%1: %2\n"), _szAppName, szText);SafePutts(szMessage);}
}inline void
Usage(UINT ids,LPCTSTR pszArg1 = NULL,LPCTSTR pszArg2 = NULL)
{DisplayMessage(ids, pszArg1, pszArg2, TRUE);
}inline void
Info(UINT ids,LPCTSTR pszArg1 = NULL,LPCTSTR pszArg2 = NULL)
{DisplayMessage(ids, pszArg1, pszArg2, FALSE, TRUE);
}#ifdef _UNICODE
int wmain(int argc, WCHAR *argv[])
#else // !_UNICODE
int main(int argc, char *argv[])
#endif
{int iReturn = 0;HRESULT (STDAPICALLTYPE * lpDllEntryPoint)(void);BOOL bVisualC = FALSE;BOOL bUnregister = FALSE;LPCSTR pszDllEntryPoint = _szDllRegSvr;LPTSTR ptszDllEntryPoint = NULL;LPCTSTR pszDllName = NULL;LPCTSTR pszTok;size_t EntryPointSize = 0;_hInstance = ::GetModuleHandle(NULL);// Parse command line arguments.int iTok;for (iTok = 1; iTok < argc; iTok++) {pszTok = argv[iTok];if ((pszTok[0] == '-') || (pszTok[0] == '/')) {switch (pszTok[1]) {case 'v':case 'V':bVisualC = TRUE;break;case 's':case 'S':_bSilent = TRUE;break;case 'u':case 'U':bUnregister = TRUE;pszDllEntryPoint = _szDllUnregSvr;break;case 'c':case 'C':_bConsole = TRUE;break;default:Usage(IDS_UNRECOGNIZEDFLAG, pszTok);return FAIL_ARGS;}} else {if (pszDllName == NULL) {pszDllName = pszTok;break;} else {Usage(IDS_EXTRAARGUMENT, pszTok);return FAIL_ARGS;}}}if (pszDllEntryPoint != NULL) {EntryPointSize = (1 + strlen(pszDllEntryPoint)) * (sizeof(TCHAR));ptszDllEntryPoint = (TCHAR *)_malloca(EntryPointSize); // _malloca may allocate memory on the heap, so we need to call _freea to clean the heap if used
#ifdef _UNICODEswprintf_s(ptszDllEntryPoint, EntryPointSize, _T("%hs"), pszDllEntryPoint);
#else // !_UNICODEstrcpy_s(ptszDllEntryPoint, EntryPointSize, pszDllEntryPoint);
#endif}if (pszDllName == NULL) {if (bVisualC)DisplayMessage(IDS_NOPROJECT);elseUsage(IDS_NODLLNAME);_freea(ptszDllEntryPoint);return FAIL_ARGS;}// Initialize OLE.if (FAILED(OleInitialize(NULL))) {DisplayMessage(IDS_OLEINITFAILED);_freea(ptszDllEntryPoint);return FAIL_OLE;}SetErrorMode(SEM_FAILCRITICALERRORS); // Make sure LoadLib fails.for (; iTok < argc; iTok++) {pszDllName = argv[iTok];// Load the library.HINSTANCE hLib = LoadLibraryEx(pszDllName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);if (hLib < (HINSTANCE)HINSTANCE_ERROR) {TCHAR szError[12];_stprintf_s(szError, 12, _T("0x%08lx"), GetLastError());DisplayMessage(IDS_LOADLIBFAILED, pszDllName, szError);iReturn = FAIL_LOAD;goto CleanupOle;}// Find the entry point.(FARPROC&)lpDllEntryPoint = GetProcAddress(hLib, pszDllEntryPoint);if (lpDllEntryPoint == NULL) {TCHAR szExt[_MAX_EXT];_tsplitpath_s(pszDllName, NULL, 0, NULL, 0, NULL, 0, szExt, _MAX_EXT);if ((_tcsicmp(szExt, _T(".dll")) != 0) && (_tcsicmp(szExt, _T(".ocx")) != 0))DisplayMessage(IDS_NOTDLLOROCX, pszDllName, ptszDllEntryPoint);elseDisplayMessage(IDS_NOENTRYPOINT, pszDllName, ptszDllEntryPoint);iReturn = FAIL_ENTRY;goto CleanupLibrary;}// Call the entry point.if (FAILED((*lpDllEntryPoint)())) {DisplayMessage(IDS_CALLFAILED, ptszDllEntryPoint, pszDllName);iReturn = FAIL_REG;goto CleanupLibrary;}Info(IDS_CALLSUCCEEDED, ptszDllEntryPoint, pszDllName);CleanupLibrary:FreeLibrary(hLib);}CleanupOle:OleUninitialize();_freea(ptszDllEntryPoint);return iReturn;
}
自己封装一个函数来干活(注册/反注册 COM DLL)
//! \file myRegsvr32.cpp
//! \brief 自己封装一个可以可以操作COM DLL注册/反注册的函数
//! \ref D:\3rd_prj\vs\VCSamples\VC2008Samples\MFC\controls\regsvr
//! \note https://github.com/microsoft/VCSamples.git//! \note exp prj env = vs2019 vc++ unicode x64 console#include <Windows.h>
#include <iostream>
#include <assert.h>bool com_dll_Reg_or_unReg(bool isReg, const TCHAR* pszComDllPathName);int wmain(int argc, WCHAR* argv[])
// int main(int argc, TCHAR** argv)
{bool b_rc = false;do {// argv[1] is COM DLL's path nameif (2 != argc){break;}// un register com dllb_rc = com_dll_Reg_or_unReg(false, argv[1]);assert(b_rc);// register com dllb_rc = com_dll_Reg_or_unReg(true, argv[1]);assert(b_rc);} while (false);return 0;
}bool com_dll_Reg_or_unReg(bool isReg, const TCHAR* pszComDllPathName)
{bool b_rc = false;bool b_com_init_ok = false;HRESULT hr = S_OK;HINSTANCE hLib = NULL;HRESULT(STDAPICALLTYPE * lpDllEntryPoint)(void);const CHAR* pszDllRegSvr = "DllRegisterServer";const CHAR* pszDllUnregSvr = "DllUnregisterServer";const CHAR* pszComDLLApiName = NULL;do {if (NULL == pszComDllPathName){break;}pszComDLLApiName = (isReg ? pszDllRegSvr : pszDllUnregSvr);hr = OleInitialize(NULL);if (FAILED(hr)) {break;}b_com_init_ok = true;SetErrorMode(SEM_FAILCRITICALERRORS); // Make sure LoadLib fails.// Load the library.hLib = LoadLibraryEx(pszComDllPathName, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);if (hLib < (HINSTANCE)HINSTANCE_ERROR) {break;}(FARPROC&)lpDllEntryPoint = GetProcAddress(hLib, pszComDLLApiName);if (NULL == lpDllEntryPoint) {break;}hr = (*lpDllEntryPoint)();if (FAILED(hr)) {break;}b_rc = true;} while (false);if (NULL != hLib){FreeLibrary(hLib);hLib = NULL;}if (b_com_init_ok){b_com_init_ok = false;OleUninitialize();}return b_rc;
}