|
|
// MSInfo.cpp : Implementation of DLL Exports, main application object
// and Registry Object Map. All registry information (apart from
// MIDL) lives here.
//
// Copyright (c) 1998-1999 Microsoft Corporation
#include "stdafx.h"
#include "resource.h"
#include "initguid.h"
// This hack is required because we may be building in an environment
// which doesn't have a late enough version of rpcndr.h
#if __RPCNDR_H_VERSION__ < 440
#define __RPCNDR_H_VERSION__ 440
#define MIDL_INTERFACE(x) interface
#endif
#include "MSInfo.h"
#include "DataObj.h"
#include "CompData.h"
#include "About.h"
#include "Toolset.h"
#include "Dispatch.h"
#include "MSInfo_i.c"
static LPCTSTR cszBasePath = _T("Software\\Microsoft\\MMC"); static LPCTSTR cszBaseSnapinPath = _T("Software\\Microsoft\\MMC\\Snapins"); static LPCTSTR cszBaseNodeTypePath = _T("Software\\Microsoft\\MMC\\NodeTypes"); static LPCTSTR cszNameString = _T("NameString"); static LPCTSTR cszProvider = _T("Provider"); static LPCTSTR cszVersion = _T("Version"); static LPCTSTR cszAbout = _T("About"); static LPCTSTR cszStandAlone = _T("StandAlone"); static LPCTSTR cszNodeTypes = _T("NodeTypes"); static LPCTSTR cszExtensions = _T("Extensions"); static LPCTSTR cszNameSpace = _T("NameSpace"); static LPCTSTR cszTask = _T("Task");
static LPCTSTR cszMSInfoBaseKey = _T("Software\\Microsoft\\Shared Tools"); static LPCTSTR cszMSInfoSubKey = _T("MSInfo"); static LPCTSTR cszMSInfoKey = _T("Software\\Microsoft\\Shared Tools\\MSInfo"); static LPCTSTR cszPathValue = _T("Path"); static LPCTSTR cszRunKey = _T("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\msinfo32.exe"); static LPCTSTR cszRunRootKey = _T("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths"); static LPCTSTR cszRunSubKey = _T("msinfo32.exe");
static LPCTSTR cszNFOExtension = _T(".nfo"); static LPCTSTR cszOLERegistration = _T("MSInfo.Document"); static LPCTSTR cszDefaultIconKey = _T("DefaultIcon");
static LPCTSTR cszCLSIDKey = _T("CLSID"); static LPCTSTR cszShellKey = _T("shell"); static LPCTSTR cszOpenCommandKey = _T("open\\command"); static LPCTSTR cszPrintCommandKey = _T("print\\command"); static LPCTSTR cszPrintToKey = _T("printto\\command");
// note trailing quotes on file path
static LPCTSTR cszMSInfoPath = _T("Microsoft Shared\\MSInfo\\MSInfo32.exe\""); static LPCTSTR cszDefaultIconValue = _T("Microsoft Shared\\MSInfo\\MSInfo32.exe\",0"); static LPCTSTR cszOpenCommand = _T("Microsoft Shared\\MSInfo\\MSInfo32.exe\" /msinfo_file \"%1\"");
// these are never referenced
static LPCTSTR cszMSInfoDir = _T("Common Files\\Microsoft Shared\\MSInfo\\"); static LPCTSTR cszPrintToCommand = _T("Common Files\\Microsoft Shared\\MSInfo\\MSInfo32.exe /pt \"%1\" \"%2\" \"%3\" \"%4\""); //static LPCTSTR cszPrintCommand = _T("Common Files\\Microsoft Shared\\MSInfo\\MSInfo32.exe /p \"%1\"");
//a-kjaw
static LPCTSTR cszPrintCommand = _T("Microsoft Shared\\MSInfo\\MSInfo32.exe\" /p \"%1\""); //a-kjaw
// Nodes we extend
static LPCTSTR cszCompMgrNode = _T("{476E6448-AAFF-11D0-B944-00C04FD8D5B0}");
CComModule _Module;
/*
* Object Map of Registered objects, allowing the Active Template Library to * register our CLSIDs. */ BEGIN_OBJECT_MAP(ObjectMap) OBJECT_ENTRY(CLSID_MSInfo, CSystemInfoScopePrimary) OBJECT_ENTRY(CLSID_Extension, CSystemInfoScopeExtension) OBJECT_ENTRY(CLSID_About, CAboutImpl) OBJECT_ENTRY(CLSID_SystemInfo, CMSInfo) END_OBJECT_MAP()
/*
* The MSInfo application object. * * History: a-jsari 10/1/97 Initial version. */ class CMSInfoApp : public CWinApp { public: virtual BOOL InitInstance(); virtual int ExitInstance(); };
CMSInfoApp theApp;
/*
* InitInstance - Initialize an instance of the application. * * History: a-jsari 10/1/97 Initial version. */
extern void LoadDialogResources(); BOOL CMSInfoApp::InitInstance() { _Module.Init(ObjectMap, m_hInstance); LoadDialogResources(); // loads dialog strings from resources
return CWinApp::InitInstance(); }
/*
* ExitInstance - Deconstruct an instance of the application. * * History: a-jsari 10/1/97 Initial version. */ int CMSInfoApp::ExitInstance() { _Module.Term(); return CWinApp::ExitInstance(); }
/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); return (AfxDllCanUnloadNow()==S_OK && _Module.GetLockCount()==0) ? S_OK : S_FALSE; }
/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { return _Module.GetClassObject(rclsid, riid, ppv); }
/*
* RegOpenMMCRoot - Open CRegKey * * History: a-jsari 9/9/97 Initial version */ static inline long RegOpenMMCRoot(CRegKey *pcrkMMCRoot) { return pcrkMMCRoot->Open(HKEY_LOCAL_MACHINE, cszBasePath); }
/*
* RegOpenMMCSnapinRoot - Return MMC's registry Snapin root * * History: a-jsari 9/9/97 Initial version */ static inline long RegOpenMMCSnapinRoot(CRegKey *pcrkSnapinRoot) { return pcrkSnapinRoot->Open(HKEY_LOCAL_MACHINE, cszBaseSnapinPath); }
/*
* RegOpenMMCNodeTypeRoot - Return MMC's registry NodeType root * * History: a-jsari 9/9/97 Initial version */ static inline long RegOpenMMCNodeTypeRoot(CRegKey *pcrkNodeTypesRoot) { return pcrkNodeTypesRoot->Open(HKEY_LOCAL_MACHINE, cszBaseNodeTypePath); }
/*
* RegisterStandaloneSnapin() - Do all registration for the Standalone * portion of the snapin. * * History: a-jsari 9/9/97 Initial version * * Note: Would require AFX_MANAGE_STATE, except that the calling function * handles it. */ static inline HRESULT RegisterStandaloneSnapin() { CRegKey crkRoot; CRegKey crkClsid; CRegKey crkIterator; CString szResourceLoader;
HRESULT hr = E_FAIL;
do { // HKEY_CLASSES_ROOT\.nfo
long lRegOpenResult = crkRoot.Create(HKEY_CLASSES_ROOT, cszNFOExtension); if (lRegOpenResult != ERROR_SUCCESS) break; lRegOpenResult = crkRoot.SetValue(cszOLERegistration); if (lRegOpenResult != ERROR_SUCCESS) break; crkRoot.Close();
// HKEY_CLASSES_ROOT\MSInfo.Document
lRegOpenResult = crkRoot.Create(HKEY_CLASSES_ROOT, cszOLERegistration); if (lRegOpenResult != ERROR_SUCCESS) break; // This originally set the default value for the key to "msinfo.document", which
// is what would show up in the UI for a description of the NFO filetype. Fixing
// this to load the string from a resource (bug 10442).
//
// lRegOpenResult = crkRoot.SetValue(cszOLERegistration);
// if (lRegOpenResult != ERROR_SUCCESS) break;
CString strDescription; strDescription.LoadString(IDS_NFODESCRIPTION); crkRoot.SetValue((LPCTSTR)strDescription); lRegOpenResult = crkIterator.Create(crkRoot, cszCLSIDKey); if (lRegOpenResult != ERROR_SUCCESS) break; lRegOpenResult = crkIterator.SetValue(cszClsidMSInfoSnapin); if (lRegOpenResult != ERROR_SUCCESS) break; crkIterator.Close();
TCHAR szWindowsPath[MAX_PATH]; DWORD dwSize; CString szPathValue; dwSize = sizeof(szWindowsPath); lRegOpenResult = crkIterator.Open(HKEY_LOCAL_MACHINE, cszWindowsCurrentKey); if (lRegOpenResult != ERROR_SUCCESS) break; lRegOpenResult = crkIterator.QueryValue(szWindowsPath, cszCommonFilesValue, &dwSize); if (lRegOpenResult != ERROR_SUCCESS) break; lRegOpenResult = crkIterator.Create(crkRoot, cszDefaultIconKey); if (lRegOpenResult != ERROR_SUCCESS) break; szPathValue = _T("\""); szPathValue += szWindowsPath; szPathValue += _T("\\"); szPathValue += cszDefaultIconValue; lRegOpenResult = crkIterator.SetValue(szPathValue); if (lRegOpenResult != ERROR_SUCCESS) break; crkIterator.Close(); lRegOpenResult = crkRoot.Create(crkRoot, cszShellKey); if (lRegOpenResult != ERROR_SUCCESS) break; lRegOpenResult = crkIterator.Create(crkRoot, cszOpenCommandKey); if (lRegOpenResult != ERROR_SUCCESS) break;
szPathValue = _T("\""); szPathValue += szWindowsPath; szPathValue += _T("\\"); szPathValue += cszOpenCommand;
lRegOpenResult = crkIterator.SetValue(szPathValue); if (lRegOpenResult != ERROR_SUCCESS) break; crkIterator.Close(); //crkRoot.Close();
//a-kjaw
lRegOpenResult = crkIterator.Create(crkRoot, cszPrintCommandKey); if (lRegOpenResult != ERROR_SUCCESS) break; szPathValue = _T("\""); szPathValue += szWindowsPath; szPathValue += _T("\\"); szPathValue += cszPrintCommand;
lRegOpenResult = crkIterator.SetValue(szPathValue); if (lRegOpenResult != ERROR_SUCCESS) break; crkIterator.Close(); crkRoot.Close(); //a-kjaw
// HKEY_LOCAL_MACHINE\Software\Microsoft\MMC\Snapins
lRegOpenResult = RegOpenMMCSnapinRoot(&crkRoot);
// FIX: This fail should behave differently (registering the DLL
// w/o MMC registered).
if (lRegOpenResult != ERROR_SUCCESS) break; // {45ac8c63-23e2-11e1-a696-00c04fd58bc3}
lRegOpenResult = crkClsid.Create(crkRoot, cszClsidMSInfoSnapin); if (lRegOpenResult != ERROR_SUCCESS) break; // NameString = REG_SZ "Microsoft System Information"
VERIFY(szResourceLoader.LoadString(IDS_DESCRIPTION)); lRegOpenResult = crkClsid.SetValue(szResourceLoader, cszNameString); if (lRegOpenResult != ERROR_SUCCESS) break; // About = REG_SZ "{45ac8c65-23e2-11e1-a696-00c04fd58bc3}"
lRegOpenResult = crkClsid.SetValue(cszClsidAboutMSInfo, cszAbout); if (lRegOpenResult != ERROR_SUCCESS) break; // Provider = REG_SZ "Microsoft Corporation"
VERIFY(szResourceLoader.LoadString(IDS_COMPANY)); lRegOpenResult = crkClsid.SetValue(szResourceLoader, cszProvider); if (lRegOpenResult != ERROR_SUCCESS) break; // Version = REG_SZ "5.0"
VERIFY(szResourceLoader.LoadString(IDS_VERSION)); lRegOpenResult = crkClsid.SetValue(szResourceLoader, cszVersion); if (lRegOpenResult != ERROR_SUCCESS) break; // StandAlone
lRegOpenResult = crkIterator.Create(crkClsid, cszStandAlone); if (lRegOpenResult != ERROR_SUCCESS) break; // NodeTypes
lRegOpenResult = crkIterator.Create(crkClsid, cszNodeTypes); if (lRegOpenResult != ERROR_SUCCESS) break; // {45ac8c66-23e2-11e1-a696-00c04fd58bc3}
CRegKey crkNodeType; lRegOpenResult = crkNodeType.Create(crkIterator, cszNodeTypeStatic); if (lRegOpenResult != ERROR_SUCCESS) break;
// Replace the SnapinRoot with the NodeType root;
// work from the new base.
// HKEY_LOCAL_MACHINE\Software\Microsoft\MMC\NodeTypes
lRegOpenResult = RegOpenMMCNodeTypeRoot(&crkRoot); if (lRegOpenResult != ERROR_SUCCESS) break; // {45ac8c66-23e2-11e1-a696-00c04fd58bc3}
// = REG_SZ "Microsoft System Information Root"
VERIFY(szResourceLoader.LoadString(IDS_NODEDESCRIPTION)); lRegOpenResult = crkRoot.SetKeyValue(cszNodeTypeStatic, szResourceLoader); if (lRegOpenResult != ERROR_SUCCESS) break; hr = S_OK; } while (0); return hr; }
/*
* HRESULT UnregisterStandaloneSnapin - Remove all registry entries for * the standalone portion of the snapin. * * History: a-jsari 9/9/97 Initial version. */ static inline HRESULT UnregisterStandaloneSnapin() { CRegKey crkSnapinRoot;
// Remove HKEY_CLASSES_ROOT\.nfo
long lRegOpenResult = crkSnapinRoot.Open(HKEY_CLASSES_ROOT, NULL); if (lRegOpenResult != ERROR_SUCCESS) { if (lRegOpenResult != ERROR_FILE_NOT_FOUND) return E_FAIL; } else { lRegOpenResult = crkSnapinRoot.RecurseDeleteKey(cszNFOExtension); // It's not really an error to not find a key we were deleting anyhow.
if (lRegOpenResult != ERROR_SUCCESS && lRegOpenResult != ERROR_FILE_NOT_FOUND) { return E_FAIL; } crkSnapinRoot.Close(); }
// Remove HKEY_CLASSES_ROOT\MSInfo.Document
lRegOpenResult = crkSnapinRoot.Open(HKEY_CLASSES_ROOT, NULL); if (lRegOpenResult != ERROR_SUCCESS) { if (lRegOpenResult != ERROR_FILE_NOT_FOUND) return E_FAIL; } else { lRegOpenResult = crkSnapinRoot.RecurseDeleteKey(cszOLERegistration); // It's not really an error to not find a key we were deleting anyhow.
if (lRegOpenResult != ERROR_SUCCESS && lRegOpenResult != ERROR_FILE_NOT_FOUND) { return E_FAIL; } crkSnapinRoot.Close(); }
lRegOpenResult = RegOpenMMCSnapinRoot(&crkSnapinRoot); if (lRegOpenResult != ERROR_SUCCESS) { if (lRegOpenResult != ERROR_FILE_NOT_FOUND) return E_FAIL; } else { // Just recursively delete our root. Extensions will be automatically
// deleted as well.
lRegOpenResult = crkSnapinRoot.RecurseDeleteKey(cszClsidMSInfoSnapin); // It's not really an error to not find a key we were deleting anyhow.
if (lRegOpenResult != ERROR_SUCCESS && lRegOpenResult != ERROR_FILE_NOT_FOUND) { return E_FAIL; } }
lRegOpenResult = RegOpenMMCNodeTypeRoot(&crkSnapinRoot); if (lRegOpenResult != ERROR_SUCCESS) { if (lRegOpenResult != ERROR_FILE_NOT_FOUND) return E_FAIL; } else { lRegOpenResult = crkSnapinRoot.RecurseDeleteKey(cszNodeTypeStatic);
ASSERT(lRegOpenResult == ERROR_SUCCESS); // It's not really an error to not find a key we were deleting anyhow.
if (lRegOpenResult != ERROR_SUCCESS && lRegOpenResult != ERROR_FILE_NOT_FOUND) { return E_FAIL; } } return S_OK; }
/*
* OpenExtendKeyForNodeType - Return in pcrkExtension the Registry Key for * HKEY_LOCAL_MACHINE\Software\Microsoft\MMC\NodeTypes\ * cszNodeTypeGuid (GUID string) \Extensions * If fCreateIfNonextistent is TRUE, the Extensions key (only) is created * if it doesn't exist. * * Return Codes: * S_OK - All operations succeeded. * E_FAIL - A critical registry operation failed. * E_ABORT - The GUID string could not be opened, or * the Extensions key could not be opened (and * fCreateIfNonexistent is FALSE). * * History: a-jsari 9/18/97 Initial version */ static inline HRESULT OpenExtendKeyForNodeType(LPCTSTR cszNodeTypeGuid, CRegKey *pcrkExtension, BOOL fCreateIfNonexistent = TRUE) { CRegKey crkRoot; CRegKey crkNodeToExtend;
ASSERT(pcrkExtension != NULL); long lRegOpenResult = RegOpenMMCNodeTypeRoot(&crkRoot); if (lRegOpenResult != ERROR_SUCCESS) return E_FAIL; // Not finding the proper nodetype is a different kind of error
// than not finding MMC, or not creating a new one.
if (fCreateIfNonexistent) { lRegOpenResult = crkNodeToExtend.Create(crkRoot, cszNodeTypeGuid); if (lRegOpenResult != ERROR_SUCCESS) return E_FAIL; lRegOpenResult = pcrkExtension->Create(crkNodeToExtend, cszExtensions); } else { lRegOpenResult = crkNodeToExtend.Open(crkRoot, cszNodeTypeGuid); if (lRegOpenResult != ERROR_SUCCESS) return E_ABORT; lRegOpenResult = pcrkExtension->Open(crkNodeToExtend, cszExtensions); if (lRegOpenResult == ERROR_FILE_NOT_FOUND) return E_ABORT; } if (lRegOpenResult != ERROR_SUCCESS) return E_FAIL; return S_OK; }
/*
* ExtendNode - Does all registry extension required for the NodeType * cszNodeTypeGuid. * * Return Codes: * S_OK - Upon successful completion, or if cszNodeTypeGuid can't * be found. * E_FAIL - If MMC cannot be found or NodeTypeGuid can't be opened. * * History: a-jsari 9/9/97 Initial version */ static HRESULT ExtendNode(LPCTSTR cszNodeTypeGuid) { CRegKey crkExtension; CRegKey crkIterator; CString szResourceLoader;
HRESULT hrOpenExtension = OpenExtendKeyForNodeType(cszNodeTypeGuid, &crkExtension, TRUE); // Don't return an error if we can't open the cszNodeTypeGuid
if (hrOpenExtension != S_OK) return hrOpenExtension == E_ABORT ? S_OK : hrOpenExtension;
// NameSpace
// {GUID} = "System Information Extension"
long lRegOpenResult = crkIterator.Create(crkExtension, cszNameSpace); if (lRegOpenResult != ERROR_SUCCESS) return E_FAIL; VERIFY(szResourceLoader.LoadString(IDS_EXTENSIONDESCRIPTION)); lRegOpenResult = crkIterator.SetValue(szResourceLoader, cszClsidMSInfoExtension); if (lRegOpenResult != ERROR_SUCCESS) return E_FAIL; // Task
// {GUID} = "System Information Extension"
lRegOpenResult = crkIterator.Create(crkExtension, cszTask); if (lRegOpenResult != ERROR_SUCCESS) return E_FAIL; lRegOpenResult = crkIterator.SetValue(szResourceLoader, cszClsidMSInfoExtension); return S_OK; }
/*
* HRESULT UnregisterNode - Remove all registry entries for a specific * Nodetype. * * Return Codes: * S_OK - If all of the essential nodes are found. * E_FAIL - If any of the path to the keys to remove fail to be found. * * History: a-jsari 9/9/97 Initial version. */ static HRESULT UnregisterNode(LPCTSTR cszNodeTypeGuid) { CRegKey crkExtension; CRegKey crkIterator;
HRESULT hrOpenExtension = OpenExtendKeyForNodeType(cszNodeTypeGuid, &crkExtension); ASSERT(hrOpenExtension == S_OK); // Don't return an error if we can't open the cszNodeTypeGuid
if (hrOpenExtension != S_OK) return (hrOpenExtension == E_ABORT) ? S_OK : hrOpenExtension; long lRegOpenResult = crkIterator.Open(crkExtension, cszNameSpace); if (lRegOpenResult != ERROR_SUCCESS) return (lRegOpenResult == ERROR_FILE_NOT_FOUND) ? S_OK : E_FAIL; lRegOpenResult = crkIterator.DeleteValue(cszClsidMSInfoExtension);
// It's not really an error to not find a key we were deleting anyhow.
if (lRegOpenResult != ERROR_SUCCESS && lRegOpenResult != ERROR_FILE_NOT_FOUND) { return E_FAIL; } return S_OK; }
/*
* RegisterExtensionSnapin - Do all registration required for the extension side * of the snapin. * * History: a-jsari 9/9/97 Initial version */ static inline HRESULT RegisterExtensionSnapin() { const HRESULT hrErrorReturn = E_FAIL;
CRegKey crkRoot; CRegKey crkClsid; CRegKey crkIterator; CString szResourceLoader;
// HKEY_LOCAL_MACHINE\Software\Microsoft\MMC\Snapins
long lRegOpenResult = RegOpenMMCSnapinRoot(&crkRoot);
// FIX: This fail should behave differently (registering the DLL
// w/o MMC registered).
if (lRegOpenResult != ERROR_SUCCESS) return hrErrorReturn; // {45ac8c63-23e2-11e1-a696-00c04fd58bc3}
lRegOpenResult = crkClsid.Create(crkRoot, cszClsidMSInfoExtension); if (lRegOpenResult != ERROR_SUCCESS) return hrErrorReturn; // NameString = REG_SZ "System Information Extension"
VERIFY(szResourceLoader.LoadString(IDS_EXTENSIONDESCRIPTION)); lRegOpenResult = crkClsid.SetValue(szResourceLoader, cszNameString); if (lRegOpenResult != ERROR_SUCCESS) return hrErrorReturn; // Provider = REG_SZ "Microsoft Corporation"
VERIFY(szResourceLoader.LoadString(IDS_COMPANY)); lRegOpenResult = crkClsid.SetValue(szResourceLoader, cszProvider); if (lRegOpenResult != ERROR_SUCCESS) return hrErrorReturn; // Version = REG_SZ "5.0"
VERIFY(szResourceLoader.LoadString(IDS_VERSION)); lRegOpenResult = crkClsid.SetValue(szResourceLoader, cszVersion); if (lRegOpenResult != ERROR_SUCCESS) return hrErrorReturn;
// Register our about interface CLSID under the "About" value, so when
// we're being added as an extension, our information shows up.
lRegOpenResult = crkClsid.SetValue(cszClsidAboutMSInfo, cszAbout); if (lRegOpenResult != ERROR_SUCCESS) return hrErrorReturn;
// NodeTypes
lRegOpenResult = crkIterator.Create(crkClsid, cszNodeTypes); if (lRegOpenResult != ERROR_SUCCESS) return hrErrorReturn; // {45ac8c66-23e2-11e1-a696-00c04fd58bc3}
CRegKey crkNodeType; lRegOpenResult = crkNodeType.Create(crkIterator, cszNodeTypeStatic); if (lRegOpenResult != ERROR_SUCCESS) return hrErrorReturn;
// We no longer want to extend the computer management node (138503).
// So we won't make this call to create the extension key. Also, we'll
// delete it if it exists.
//
// HRESULT hrExtend = ExtendNode(cszCompMgrNode);
// ASSERT(hrExtend == S_OK);
// return hrExtend;
CRegKey crkCompmgmtExtension; if (SUCCEEDED(OpenExtendKeyForNodeType(cszCompMgrNode, &crkCompmgmtExtension, TRUE))) { CRegKey crkNameSpace, crkTaskPad;
if (ERROR_SUCCESS == crkNameSpace.Open((HKEY)crkCompmgmtExtension, cszNameSpace)) crkNameSpace.DeleteValue(cszClsidMSInfoExtension);
if (ERROR_SUCCESS == crkTaskPad.Open((HKEY)crkCompmgmtExtension, cszTask)) crkTaskPad.DeleteValue(cszClsidMSInfoExtension); }
return S_OK; }
/*
* UnregisterExtensionSnapin - Unregister the extension part of the snapin. * * History: a-jsari 9/9/97 Initial version */ static inline HRESULT UnregisterExtensionSnapin() { CRegKey crkSnapinRoot;
long lRegOpenResult = RegOpenMMCSnapinRoot(&crkSnapinRoot); if (lRegOpenResult != ERROR_SUCCESS) { if (lRegOpenResult != ERROR_FILE_NOT_FOUND) return E_FAIL; } else { // CHECK: Is this appropriate for potential extensions (probably)
lRegOpenResult = crkSnapinRoot.RecurseDeleteKey(cszClsidMSInfoExtension);
ASSERT(lRegOpenResult == ERROR_SUCCESS); // It's not really an error to not find a key we were deleting anyhow.
if (lRegOpenResult != ERROR_SUCCESS && lRegOpenResult != ERROR_FILE_NOT_FOUND) { return E_FAIL; } }
HRESULT hrUnregister = UnregisterNode(cszCompMgrNode); return hrUnregister; }
/*
* RegisterPaths - Perform registration for path items * * History: a-jsari 12/4/97 Initial version. */ static inline HRESULT RegisterPaths() { CRegKey crkSnapinRoot; CRegKey crkProgramFilesKey; TCHAR szBuffer[MAX_PATH]; CString strPath; DWORD dwSize; long lResult;
do { // Register MSInfo's Windows App Path.
lResult = crkSnapinRoot.Open(HKEY_LOCAL_MACHINE, cszMSInfoKey); ASSERT(lResult == ERROR_SUCCESS); if (lResult != ERROR_SUCCESS) break; dwSize = sizeof(szBuffer); // Get the Path registry value into szBuffer
lResult = crkSnapinRoot.QueryValue(szBuffer, cszPathValue, &dwSize); if (lResult != ERROR_SUCCESS) { // The path can't be read from the registry; register it.
lResult = crkProgramFilesKey.Open(HKEY_LOCAL_MACHINE, cszWindowsCurrentKey); ASSERT(lResult == ERROR_SUCCESS); if (lResult != ERROR_SUCCESS) break; dwSize = sizeof(szBuffer); lResult = crkProgramFilesKey.QueryValue(szBuffer, cszCommonFilesValue, &dwSize); ASSERT(lResult == ERROR_SUCCESS); if (lResult != ERROR_SUCCESS) break;
// Remove the quotes from around the path. Bug #363834.
// strPath = "\"";
strPath = CString(_T("")); strPath += szBuffer; strPath += _T("\\"); strPath += cszMSInfoPath;
// Remove the quotes from around the path to mimic the behaviour of MSInfo 4.10
// (so that apps which used this key to launch MSInfo will continue to work). Bug #363834.
if (strPath.Right(1) == CString(_T("\""))) strPath = strPath.Left(strPath.GetLength() - 1);
// Set the path value: Path = <Path to MSInfo32.exe>
lResult = crkSnapinRoot.SetValue(strPath, cszPathValue); ASSERT(lResult == ERROR_SUCCESS); if (lResult != ERROR_SUCCESS) break; } else { // Read the path from the previously registered location and set the variable
// equal to it.
strPath = szBuffer;
// Remove the quotes from around the path. Bug #363834.
if (strPath.Left(1) == CString(_T("\""))) { strPath = strPath.Right(strPath.GetLength() - 1); if (strPath.Right(1) == CString(_T("\""))) strPath = strPath.Left(strPath.GetLength() - 1);
lResult = crkSnapinRoot.SetValue(strPath, cszPathValue); } }
// Bug #363834 - we still want quotes around the string when it's written elsewhere in the registry.
if (strPath.Left(1) != CString(_T("\""))) strPath = _T("\"") + strPath;
if (strPath.Right(1) != CString(_T("\""))) strPath += _T("\"");
lResult = crkSnapinRoot.Create(HKEY_LOCAL_MACHINE, cszRunKey); ASSERT(lResult == ERROR_SUCCESS); if (lResult != ERROR_SUCCESS) break; lResult = crkSnapinRoot.SetValue(strPath); ASSERT(lResult == ERROR_SUCCESS); if (lResult != ERROR_SUCCESS) break; int iValue = strPath.ReverseFind((TCHAR)'\\'); strPath = strPath.Left(iValue); strPath += "\"";
lResult = crkSnapinRoot.SetValue(strPath, cszPathValue); ASSERT(lResult == ERROR_SUCCESS); if (lResult != ERROR_SUCCESS) break;
#if 0
// We are now assuming that the path to MSInfo will be registered by some
// outside agent, presumably setup.
// Register the Path in the MSInfo directory
lResult = crkSnapinRoot.Open(HKEY_LOCAL_MACHINE, cszMSInfoKey); ASSERT(lResult == ERROR_SUCCESS); if (lResult != ERROR_SUCCESS) break; // Reuse the saved szPath value.
lResult = crkSnapinRoot.SetValue(szPath, cszPathValue); ASSERT(lResult == ERROR_SUCCESS); #endif
} while (FALSE); return HRESULT_FROM_WIN32(lResult); }
/*
* UnregisterPaths - Remove registry entries for path items. * * History: a-jsari 12/4/97 Initial version */ static inline HRESULT UnregisterPaths() { CRegKey crkRootKey; long lResult;
do { // Remove the App Path
lResult = crkRootKey.Open(HKEY_LOCAL_MACHINE, cszRunRootKey); if (lResult != ERROR_SUCCESS) break; lResult = crkRootKey.DeleteSubKey(cszRunSubKey); ASSERT(lResult == ERROR_SUCCESS); if (lResult != ERROR_SUCCESS) break;
// Unregister the MSInfo Key
lResult = crkRootKey.Open(HKEY_LOCAL_MACHINE, cszMSInfoBaseKey); ASSERT(lResult == ERROR_SUCCESS); if (lResult != ERROR_SUCCESS) break; lResult = crkRootKey.DeleteSubKey(cszMSInfoSubKey); ASSERT(lResult == ERROR_SUCCESS); } while (FALSE); return HRESULT_FROM_WIN32(lResult); }
/*
* DllRegisterServer - Registers the snapin in * HKEY_LOCAL_MACHINE\Software\Microsoft\MMC * HKEY_LOCAL_MACHINE\Software\Classes\MSInfo.* * HKEY_CLASSES_ROOT\CLSID\{45AC8C6...} * * History: a-jsari 9/9/97 Initial version. */ STDAPI DllRegisterServer(void) { long lToolResult; if ((lToolResult = CToolList::Register(TRUE)) != ERROR_SUCCESS) return HRESULT_FROM_WIN32(lToolResult); AFX_MANAGE_STATE(AfxGetStaticModuleState()); HRESULT hrRegister = RegisterStandaloneSnapin(); if (hrRegister != S_OK) return hrRegister; hrRegister = RegisterExtensionSnapin(); if (hrRegister != S_OK) return hrRegister; hrRegister = RegisterPaths(); if (hrRegister != S_OK) return hrRegister; // Registers object and all interfaces in typelib
#if 0
// This version has been failing
return _Module.RegisterServer(TRUE); #else
// So use this method.
return _Module.RegisterServer(FALSE); #endif
}
/*
* DllUnregisterServer - Removes entries from the system registry * * History: a-jsari 9/9/97 Initial version. */ STDAPI DllUnregisterServer(void) { HRESULT hrReturn = S_OK; long lToolResult;
if ((lToolResult = CToolList::Register(FALSE)) != ERROR_SUCCESS) hrReturn = HRESULT_FROM_WIN32(lToolResult); HRESULT hrUnregister = UnregisterStandaloneSnapin(); if (hrUnregister != S_OK) hrReturn = hrUnregister; hrUnregister = UnregisterExtensionSnapin(); if (hrUnregister != S_OK) hrReturn = hrUnregister; hrUnregister = UnregisterPaths(); if (hrUnregister != S_OK) hrReturn = hrUnregister; _Module.UnregisterServer(); return hrReturn; }
//-----------------------------------------------------------------------------
// Implementation for the CMSInfoLog class, used to keep a log of MSInfo
// activities.
//
// This global variable can be used elsewhere in the snap-in to write log
// entries. Only one should be created.
//-----------------------------------------------------------------------------
CMSInfoLog msiLog;
//-----------------------------------------------------------------------------
// The constructor needs to read the logging state information from the
// registry.
//-----------------------------------------------------------------------------
CMSInfoLog::CMSInfoLog() { m_pLogFile = NULL; m_strEndMarker = _T("###"); // see note in OpenLogFile
ReadLoggingStatus(); }
//-----------------------------------------------------------------------------
// The destructor needs to close the file (if it was ever created and opened).
// Also, this is a good place to put the exit MSInfo log entry.
//-----------------------------------------------------------------------------
CMSInfoLog::~CMSInfoLog() { if (this->IsLogging()) this->WriteLog(CMSInfoLog::BASIC, _T("EXIT MSInfo\r\n"));
try { if (m_pLogFile) { // Advance past the marker we wrote.
m_pLogFile->Seek(m_strEndMarker.GetLength() * sizeof(TCHAR), CFile::current);
// If we aren't at the end of the file, then we've at some point wrapped
// to the beginning and are overwriting entries. To make it so there are
// no incomplete entries, write spaces until the end of the file or until
// we find a '\r' character.
DWORD dwLength = m_pLogFile->GetLength(); DWORD dwPosition = m_pLogFile->GetPosition(); if (dwPosition < dwLength) { DWORD dwBytesRead = 0; TCHAR cRead;
do { if (m_pLogFile->Read((void *) &cRead, sizeof(TCHAR)) < sizeof(TCHAR)) break; dwBytesRead += sizeof(TCHAR); } while (cRead && cRead != _T('\r') && (dwPosition + dwBytesRead) < dwLength);
if (dwBytesRead) { m_pLogFile->Seek(dwBytesRead * -1, CFile::current);
// Write the spaces (but don't overwrite the '\r' character).
if (cRead == _T('\0') || cRead == _T('\r')) dwBytesRead -= sizeof(TCHAR); WriteSpaces(dwBytesRead / sizeof(TCHAR)); } }
m_pLogFile->Close(); delete m_pLogFile; m_pLogFile = NULL; } } catch (CFileException *e) { // Some sort of file error - turn off logging.
m_fLoggingEnabled = FALSE; m_iLoggingMask = 0; } }
//-----------------------------------------------------------------------------
// These two WriteLog functions are for writing a log entry directly to the
// file. The second (with two string parameters) assumes that the first
// string is a format with a '%s' and the second is the replacement string.
//
// The iType parameter is used to indicate what sort of log entry this is.
// The const int values from the class definition should be used.
//
// If fContinuation is TRUE, then this write is to terminate a log entry which
// spans an operation, and should not have a timestamp added.
//-----------------------------------------------------------------------------
BOOL CMSInfoLog::WriteLog(int iType, const CString & strMessage, BOOL fContinuation) { if (!OpenLogFile()) return FALSE;
if ((m_iLoggingMask & iType) == 0) return FALSE;
CString strWorking(strMessage);
// If this isn't the continuation of a previous log entry, then
// possibly add a timestamp.
if (!fContinuation && m_fTimestamp) { CTime time = CTime::GetCurrentTime(); strWorking = time.Format(_T("%Y-%m-%d %H:%M:%S ")) + strWorking; }
return WriteLogInternal(strWorking); }
BOOL CMSInfoLog::WriteLog(int iType, const CString & strFormat, const CString & strReplace1) { CString strCombined;
strCombined.Format(strFormat, strReplace1); return WriteLog(iType, strCombined); } //-----------------------------------------------------------------------------
// This function is called each time a log entry is written, to insure that
// the log file is open. If we can't open the file, or shouldn't be logging in
// the first place, this function should return FALSE.
//-----------------------------------------------------------------------------
BOOL CMSInfoLog::OpenLogFile() { if (!m_fLoggingEnabled) return FALSE;
if (m_pLogFile == NULL) { m_pLogFile = new CFile; if (m_pLogFile == NULL) return FALSE;
try { if (!m_pLogFile->Open(m_strFilename, CFile::modeCreate | CFile::modeNoTruncate | CFile::modeReadWrite)) { delete m_pLogFile; m_pLogFile = NULL; m_fLoggingEnabled = FALSE; m_iLoggingMask = 0; return FALSE; }
// Move to the right place in the file. If the file is empty, we're
// already there. If not, look for the end marker (from the last time
// we added log entries). If there is one, we should be positioned over
// its first character. Otherwise, just move to the end of the file.
if (m_pLogFile->GetLength() != 0) { // IMPORTANT NOTE: We assume here (for efficiency) that the end
// marker is structured so that we don't need to back up when
// searching the file. For example, no markers of the form "aaab".
TCHAR cRead; int iMarker = 0;
while (iMarker != m_strEndMarker.GetLength()) { if (m_pLogFile->Read((void *) &cRead, sizeof(TCHAR)) < sizeof(TCHAR)) break;
if (cRead != m_strEndMarker[iMarker]) iMarker = 0;
if (cRead == m_strEndMarker[iMarker]) iMarker++; }
if (iMarker == m_strEndMarker.GetLength()) m_pLogFile->Seek(m_strEndMarker.GetLength() * sizeof(TCHAR) * -1, CFile::current); else m_pLogFile->SeekToEnd(); } } catch (CFileException *e) { // Some sort of file error - turn off logging.
m_fLoggingEnabled = FALSE; m_iLoggingMask = 0; return FALSE; } }
return TRUE; }
//-----------------------------------------------------------------------------
// This function reads information about logging (what to log, where to log,
// etc.) out of the registry.
//-----------------------------------------------------------------------------
void CMSInfoLog::ReadLoggingStatus() { m_fLoggingEnabled = FALSE; m_fTimestamp = TRUE; m_strFilename = _T(""); m_iLoggingMask = 0; m_dwMaxFileSize = 32 * 1024;
CString strRegkey = CString(cszMSInfoKey) + CString(_T("\\Logging")); CRegKey regkey;
if (ERROR_SUCCESS == regkey.Open(HKEY_LOCAL_MACHINE, strRegkey, KEY_READ)) { DWORD dwTemp;
dwTemp = 0; if (ERROR_SUCCESS == regkey.QueryValue(dwTemp, _T("LogMask"))) m_iLoggingMask = (int) dwTemp;
dwTemp = 0; if (ERROR_SUCCESS == regkey.QueryValue(dwTemp, _T("LogFileMaxSize"))) m_dwMaxFileSize = dwTemp;
dwTemp = 0; if (ERROR_SUCCESS == regkey.QueryValue(dwTemp, _T("LogTimestamp"))) m_fTimestamp = (dwTemp) ? TRUE : FALSE;
TCHAR szFilename[MAX_PATH]; dwTemp = MAX_PATH; if (ERROR_SUCCESS == regkey.QueryValue(szFilename, _T("LogFilename"), &dwTemp)) m_strFilename = szFilename;
regkey.Close(); }
m_fLoggingEnabled = ((m_iLoggingMask != 0) && !m_strFilename.IsEmpty()); }
//-----------------------------------------------------------------------------
// Write a string to the log file. We should be positioned before the end
// marker in the file. Overwrite this, and add the end marker onto the end
// of the string we are writing.
//
// If we are too close to the maximum file size, then fill the rest of the
// file (to that point) with spaces, and wrap to the start of the file.
//
// After we've written the output, back up so that we are positioned over the
// start of the end marker.
//-----------------------------------------------------------------------------
BOOL CMSInfoLog::WriteLogInternal(const CString & strMessage) { CString strTerminated = strMessage + m_strEndMarker; DWORD dwLength = strTerminated.GetLength() * sizeof(TCHAR);
if (m_pLogFile == NULL) return FALSE;
try { // If we are too close to the max size of the file, write spaces to that
// size and start from the beginning.
DWORD dwPosition = m_pLogFile->GetPosition(); if (m_dwMaxFileSize && ((dwPosition + dwLength) > m_dwMaxFileSize)) { WriteSpaces((m_dwMaxFileSize - dwPosition) / sizeof(TCHAR)); m_pLogFile->SeekToBegin(); }
// Write the string to the file.
m_pLogFile->Write((const void *) (LPCTSTR) strTerminated, strTerminated.GetLength() * sizeof(TCHAR));
// Finally, back up over the terminating characters.
m_pLogFile->Seek(m_strEndMarker.GetLength() * sizeof(TCHAR) * -1, CFile::current); } catch (CFileException *e) { // Some sort of file error - turn off logging.
m_fLoggingEnabled = FALSE; m_iLoggingMask = 0; }
return TRUE; }
//-----------------------------------------------------------------------------
// Write the specified number of spaces to the file. (Note, this will already
// be inside an exeption handling block from the caller.)
//-----------------------------------------------------------------------------
void CMSInfoLog::WriteSpaces(DWORD dwCount) { TCHAR * szSpaceBuffer = NULL; szSpaceBuffer = new TCHAR[dwCount]; if (szSpaceBuffer) { _tcsnset(szSpaceBuffer, _T(' '), dwCount); m_pLogFile->Write((const void *) (LPCTSTR) szSpaceBuffer, dwCount * sizeof(TCHAR)); delete [] szSpaceBuffer; } }
|