Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

670 lines
18 KiB

// This is a part of the Microsoft Management Console.
// Copyright (C) Microsoft Corporation, 1995 - 1999
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Management Console and related
// electronic documentation provided with the interfaces.
#include "stdafx.h"
#include "resource.h"
#include "initguid.h"
#include "misc.h"
#include <shlguid.h>
#include <shlobj.h>
#define __dwFILE__ __dwFILE_CERTMMC_SNAPIN_CPP__
#define WSZCERTMMC_DLL "certmmc.dll"
CComModule _Module;
HINSTANCE g_hInstance = NULL;
HMODULE g_hmodRichEdit = NULL;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_Snapin, CComponentDataPrimaryImpl)
OBJECT_ENTRY(CLSID_About, CSnapinAboutImpl)
END_OBJECT_MAP()
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
void CreateRegEntries();
void RemoveRegEntries();
void CreateProgramGroupLink();
void RemoveProgramGroupLink();
// #define CERTMMC_DEBUG_REGSVR
BOOL WINAPI
DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD dwReason, // reason for calling function
LPVOID /* lpvReserved */ )
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
{
g_hInstance = hinstDLL;
_Module.Init(ObjectMap, hinstDLL);
DisableThreadLibraryCalls(hinstDLL);
LogOpen(FALSE);
break;
}
case DLL_PROCESS_DETACH:
{
// last call process should do this
if (NULL != g_hmodRichEdit)
{
FreeLibrary(g_hmodRichEdit);
}
myFreeColumnDisplayNames();
myFreeResourceStrings("certmmc.dll");
delete g_pResources;
_Module.Term();
myRegisterMemDump();
LogClose();
DEBUG_VERIFY_INSTANCE_COUNT(CSnapin);
DEBUG_VERIFY_INSTANCE_COUNT(CComponentDataImpl);
break;
}
default:
break;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow(void)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
return (_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);
}
/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
CreateRegEntries();
CreateProgramGroupLink();
// registers object, typelib and all interfaces in typelib
return _Module.RegisterServer(FALSE);
}
/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
_Module.UnregisterServer();
RemoveRegEntries();
RemoveProgramGroupLink();
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////
// Register/UnRegister nodetypes, etc
typedef struct _REGVALUE
{
DWORD dwFlags;
WCHAR const *pwszKeyName; // NULL implies place value under CA name key
WCHAR const *pwszValueName;
WCHAR const *pwszValueString; // NULL implies use REG_DWORD value (dwValue)
DWORD dwValue;
} REGVALUE;
// Flags
#define CERTMMC_REG_DELKEY 1 // delete this key on removal
// Values Under "HKLM" from base to leaves
REGVALUE g_arvCA[] =
{
// main snapin uuid
#define IREG_SNAPINNAME 0
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1, NULL, NULL, 0},
#define IREG_SNAPINNAMESTRING 1
{ 0, wszREGKEYMGMTSNAPINUUID1, wszSNAPINNAMESTRING, NULL, 0},
#define IREG_SNAPINNAMESTRINGINDIRECT 2
{ 0, wszREGKEYMGMTSNAPINUUID1, wszSNAPINNAMESTRINGINDIRECT, NULL, 0},
{ 0, wszREGKEYMGMTSNAPINUUID1, wszSNAPINABOUT, wszSNAPINNODETYPE_ABOUT, 0},
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_STANDALONE, NULL, NULL, 0}
,
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES, NULL, NULL, 0},
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES_1, NULL, NULL, 0},
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES_2, NULL, NULL, 0},
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES_3, NULL, NULL, 0},
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES_4, NULL, NULL, 0},
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPINUUID1_NODETYPES_5, NULL, NULL, 0},
// register each snapin nodetype
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPIN_NODETYPES_1, NULL, wszREGCERTSNAPIN_NODETYPES_1, 0},
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPIN_NODETYPES_2, NULL, wszREGCERTSNAPIN_NODETYPES_2, 0},
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPIN_NODETYPES_3, NULL, wszREGCERTSNAPIN_NODETYPES_3, 0},
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPIN_NODETYPES_4, NULL, wszREGCERTSNAPIN_NODETYPES_4, 0},
{ CERTMMC_REG_DELKEY, wszREGKEYMGMTSNAPIN_NODETYPES_5, NULL, wszREGCERTSNAPIN_NODETYPES_5, 0},
{ 0, NULL, NULL, NULL, 0 }
};
HRESULT
InitRegEntries(
OPTIONAL IN OUT CString *pcstrName,
OPTIONAL IN OUT CString *pcstrNameString,
OPTIONAL IN OUT CString *pcstrNameStringIndirect)
{
HRESULT hr = S_OK;
WCHAR const *pwsz;
pwsz = NULL;
if (NULL != pcstrName)
{
pcstrName->LoadString(IDS_CERTMMC_SNAPINNAME);
if (pcstrName->IsEmpty())
{
hr = myHLastError();
_PrintError(hr, "LoadString");
}
else
{
pwsz = (LPCWSTR) *pcstrName;
}
}
g_arvCA[IREG_SNAPINNAME].pwszValueString = pwsz;
pwsz = NULL;
if (NULL != pcstrNameString)
{
pcstrNameString->LoadString(IDS_CERTMMC_SNAPINNAMESTRING);
if (pcstrNameString->IsEmpty())
{
hr = myHLastError();
_PrintError(hr, "LoadString");
}
else
{
pwsz = (LPCWSTR) *pcstrNameString;
}
}
g_arvCA[IREG_SNAPINNAMESTRING].pwszValueString = pwsz;
pwsz = NULL;
if (NULL != pcstrNameStringIndirect)
{
pcstrNameStringIndirect->Format(wszSNAPINNAMESTRINGINDIRECT_TEMPLATE, L"CertMMC.dll", IDS_CERTMMC_SNAPINNAMESTRING);
if (pcstrNameStringIndirect->IsEmpty())
{
hr = myHLastError();
_PrintError(hr, "LoadString");
}
else
{
pwsz = (LPCWSTR) *pcstrNameStringIndirect;
}
}
g_arvCA[IREG_SNAPINNAMESTRINGINDIRECT].pwszValueString = pwsz;
//error:
return(hr);
}
void CreateRegEntries()
{
DWORD err;
HKEY hKeyThisValue = NULL;
REGVALUE const *prv;
CString cstrName;
CString cstrNameString;
CString cstrNameStringIndirect;
InitRegEntries(&cstrName, &cstrNameString, &cstrNameStringIndirect);
// run until not creating key or value
for ( prv=g_arvCA;
!(NULL == prv->pwszValueName && NULL == prv->pwszKeyName);
prv++ )
{
DWORD dwDisposition;
ASSERT(NULL != prv->pwszKeyName);
if (NULL == prv->pwszKeyName)
continue;
#ifdef CERTMMC_DEBUG_REGSVR
CString cstr;
cstr.Format(L"RegCreateKeyEx: %ws\n", prv->pwszKeyName);
OutputDebugString((LPCWSTR)cstr);
#endif
err = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
prv->pwszKeyName,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hKeyThisValue,
&dwDisposition);
if (err != ERROR_SUCCESS)
goto error;
// for now, don't set any value if unnamed, unvalued string
// UNDONE: can't set unnamed dword!
if (NULL != prv->pwszValueName || NULL != prv->pwszValueString)
{
if (NULL != prv->pwszValueString)
{
#ifdef CERTMMC_DEBUG_REGSVR
CString cstr;
cstr.Format(L"RegSetValueEx: %ws : %ws\n", prv->pwszValueName, prv->pwszValueString);
OutputDebugString((LPCWSTR)cstr);
#endif
err = RegSetValueEx(
hKeyThisValue,
prv->pwszValueName,
0,
REG_SZ,
(const BYTE *) prv->pwszValueString,
WSZ_BYTECOUNT(prv->pwszValueString));
}
else
{
#ifdef CERTMMC_DEBUG_REGSVR
CString cstr;
cstr.Format(L"RegSetValueEx: %ws : %ul\n", prv->pwszValueName, prv->dwValue);
OutputDebugString((LPCWSTR)cstr);
#endif
err = RegSetValueEx(
hKeyThisValue,
prv->pwszValueName,
0,
REG_DWORD,
(const BYTE *) &prv->dwValue,
sizeof(prv->dwValue));
}
if (err != ERROR_SUCCESS)
goto error;
}
if (NULL != hKeyThisValue)
{
RegCloseKey(hKeyThisValue);
hKeyThisValue = NULL;
}
}
error:
if (hKeyThisValue)
RegCloseKey(hKeyThisValue);
InitRegEntries(NULL, NULL, NULL);
return;
}
void RemoveRegEntries()
{
REGVALUE const *prv;
// walk backwards through array until hit array start
for ( prv= (&g_arvCA[ARRAYLEN(g_arvCA)]) - 2; // goto zero-based end AND skip {NULL}
prv >= g_arvCA; // until we walk past beginning
prv-- ) // walk backwards
{
if (prv->dwFlags & CERTMMC_REG_DELKEY)
{
ASSERT(prv->pwszKeyName != NULL);
#ifdef CERTMMC_DEBUG_REGSVR
CString cstr;
cstr.Format(L"RegDeleteKey: %ws\n", prv->pwszKeyName);
OutputDebugString((LPCWSTR)cstr);
#endif
RegDeleteKey(
HKEY_LOCAL_MACHINE,
prv->pwszKeyName);
}
}
//error:
return;
}
#include <shlobj.h> // CSIDL_ #defines
#include <userenv.h>
#include <userenvp.h> // CreateLinkFile API
typedef struct _PROGRAMENTRY
{
UINT uiLinkName;
UINT uiDescription;
DWORD csidl; // special folder index
WCHAR const *pwszExeName;
WCHAR const *pwszArgs;
} PROGRAMENTRY;
PROGRAMENTRY const g_aProgramEntry[] = {
{
IDS_STARTMENU_CERTMMC_LINKNAME, // uiLinkName
IDS_STARTMENU_CERTMMC_DESCRIPTION, // uiDescription
CSIDL_COMMON_ADMINTOOLS, // "All Users\Start Menu\Programs\Administrative Tools"
L"certsrv.msc", // pwszExeName
L"", // pwszArgs
},
};
#define CPROGRAMENTRY ARRAYSIZE(g_aProgramEntry)
BOOL FFileExists(LPCWSTR szFile)
{
WIN32_FILE_ATTRIBUTE_DATA data;
return(
GetFileAttributesEx(szFile, GetFileExInfoStandard, &data) &&
!(FILE_ATTRIBUTE_DIRECTORY & data.dwFileAttributes)
);
}
HRESULT
DeleteMatchingLinks(
IN WCHAR const *pwszLinkDir, // C:\Documents...Administrative Tools
IN WCHAR const *pwszLinkPath, // C:\ " \Certification Authority.lnk
IN WCHAR const *pwszTargetPath, // C:\WINDOWS\system32\certsrv.msc
IN WCHAR const *pwszArgs,
IN WCHAR const *pwszDLLPath) // C:\WINDOWS\system32\certmmc.dll
{
HRESULT hr;
WCHAR *pwszPattern = NULL;
WCHAR *pwszFile = NULL;
HANDLE hf = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA wfd;
IShellLink *psl = NULL;
IPersistFile *ppf = NULL;
int i;
hr = myBuildPathAndExt(pwszLinkDir, L"*.lnk", NULL, &pwszPattern);
_JumpIfError(hr, error, "myBuildPathAndExt");
hf = FindFirstFile(pwszPattern, &wfd);
if (INVALID_HANDLE_VALUE == hf)
{
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
_JumpErrorStr2(hr, error, "no *.lnk files", pwszPattern, hr);
}
hr = HRESULT_FROM_WIN32(ERROR_DIRECTORY);
do {
WCHAR wszPath[MAX_PATH];
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
continue;
}
if (NULL != psl)
{
psl->Release();
psl = NULL;
}
if (NULL != ppf)
{
ppf->Release();
ppf = NULL;
}
if (NULL != pwszFile)
{
LocalFree(pwszFile);
pwszFile = NULL;
}
hr = myBuildPathAndExt(pwszLinkDir, wfd.cFileName, NULL, &pwszFile);
_JumpIfError(hr, error, "myBuildPathAndExt");
if (0 == mylstrcmpiL(pwszLinkPath, pwszFile))
{
continue; // skip exact match
}
// Get a pointer to the IShellLink interface.
hr = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *) &psl);
if (S_OK != hr)
psl = NULL;
_JumpIfError(hr, error, "CoCreateInstance");
// Query IShellLink for the IPersistFile interface for saving the
// shortcut in persistent storage.
hr = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (S_OK != hr)
ppf = NULL;
_JumpIfError(hr, error, "QI");
// Load the link by calling IPersistFile::Load.
hr = ppf->Load(pwszFile, STGM_READ);
_JumpIfError(hr, error, "Load");
hr = psl->GetPath(wszPath, ARRAYSIZE(wszPath), &wfd, SLGP_UNCPRIORITY);
_JumpIfError(hr, error, "GetPath");
if (0 != mylstrcmpiL(pwszTargetPath, wszPath))
{
continue; // different path: skip
}
hr = psl->GetArguments(wszPath, ARRAYSIZE(wszPath));
_JumpIfError(hr, error, "GetArguments");
if (0 != mylstrcmpiL(pwszArgs, wszPath))
{
continue; // different arguments: skip
}
hr = psl->GetIconLocation(wszPath, ARRAYSIZE(wszPath), &i);
_JumpIfError(hr, error, "GetIconLocation");
if (0 != mylstrcmpiL(pwszDLLPath, wszPath))
{
continue; // different icon DLL: skip
}
psl->Release();
psl = NULL;
ppf->Release();
ppf = NULL;
DeleteFile(pwszFile);
} while (FindNextFile(hf, &wfd));
hr = S_OK;
error:
if (INVALID_HANDLE_VALUE != hf)
{
FindClose(hf);
}
if (NULL != pwszFile)
{
LocalFree(pwszFile);
}
if (NULL != pwszPattern)
{
LocalFree(pwszPattern);
}
if (NULL != ppf)
{
ppf->Release();
}
if (NULL != psl)
{
psl->Release();
}
return(hr);
}
void CreateProgramGroupLink()
{
HRESULT hr;
PROGRAMENTRY const *ppe;
IShellLink *psl = NULL;
IPersistFile *ppf = NULL;
for (ppe = g_aProgramEntry; ppe < &g_aProgramEntry[CPROGRAMENTRY]; ppe++)
{
WCHAR wszPath[MAX_PATH];
CString strDLLPath, strPath, strDescr, strLinkName, strLinkPath;
LPWSTR pszTmp;
if (NULL == (pszTmp = strPath.GetBuffer(MAX_PATH)))
{
hr = E_OUTOFMEMORY;
_JumpError(hr, error, "GetBuffer");
}
GetSystemDirectory(pszTmp, MAX_PATH);
strPath += L"\\";
strDLLPath = strPath;
strDLLPath += WSZCERTMMC_DLL;
strPath += ppe->pwszExeName;
// don't create link for file that doesn't exist
if (!FFileExists(strPath))
continue;
strDescr.Format(L"@%s,-%d", strDLLPath.GetBuffer(), ppe->uiDescription);
hr = SHGetFolderPath(
NULL,
ppe->csidl,
NULL,
SHGFP_TYPE_CURRENT,
wszPath);
_JumpIfError(hr, error, "SHGetFolderPath(Administrative Tools)");
strLinkName.LoadString(ppe->uiLinkName);
strLinkPath.Format(L"%s\\%s.lnk", wszPath, strLinkName);
DeleteMatchingLinks(
wszPath,
strLinkPath,
strPath,
ppe->pwszArgs,
strDLLPath);
// Get a pointer to the IShellLink interface.
hr = CoCreateInstance(CLSID_ShellLink, NULL,
CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *) &psl);
if (S_OK != hr)
psl = NULL;
_JumpIfError(hr, error, "CoCreateInstance");
strPath += ppe->pwszArgs;
hr = psl->SetPath(strPath);
_JumpIfError(hr, error, "SetPath");
hr = psl->SetIconLocation(strDLLPath, 0);
_JumpIfError(hr, error, "SetIconLocation");
hr = psl->SetDescription(strDescr);
_JumpIfError(hr, error, "SetDescription");
// Query IShellLink for the IPersistFile interface for saving the
// shortcut in persistent storage.
hr = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (S_OK != hr)
ppf = NULL;
_JumpIfError(hr, error, "QI");
// Save the link by calling IPersistFile::Save.
hr = ppf->Save(strLinkPath.GetBuffer(), TRUE);
_JumpIfError(hr, error, "Save");
hr = SHSetLocalizedName(
strLinkPath.GetBuffer(),
strDLLPath,
ppe->uiLinkName);
_JumpIfError(hr, error, "SHSetLocalizedName");
ppf->Release();
ppf = NULL;
psl->Release();
psl = NULL;
}
hr = S_OK;
error:
if (NULL != ppf)
ppf->Release();
if (NULL != psl)
psl->Release();
return;
}
void RemoveProgramGroupLink()
{
HRESULT hr = S_OK;
PROGRAMENTRY const *ppe;
for (ppe = g_aProgramEntry; ppe < &g_aProgramEntry[CPROGRAMENTRY]; ppe++)
{
CString cstrLinkName;
cstrLinkName.LoadString(ppe->uiLinkName);
if (cstrLinkName.IsEmpty())
{
hr = myHLastError();
_PrintError(hr, "LoadString");
continue;
}
if (!DeleteLinkFile(
ppe->csidl, // CSIDL_*
NULL, // IN LPCSTR lpSubDirectory
(LPCWSTR)cstrLinkName, // IN LPCSTR lpFileName
FALSE)) // IN BOOL fDeleteSubDirectory
{
hr = myHLastError();
_PrintError2(hr, "DeleteLinkFile", hr);
}
}
//error:
_PrintIfError2(hr, "RemoveProgramGroupLink", hr);
return;
}