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.
2965 lines
90 KiB
2965 lines
90 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 "setupids.h"
|
|
#include "resource.h"
|
|
#include "genpage.h"
|
|
|
|
#include "chooser.h"
|
|
#include "misc.h"
|
|
|
|
#include "csdisp.h" // picker
|
|
#include <esent.h> // database error
|
|
#include <aclui.h>
|
|
#include <winldap.h>
|
|
#include "csldap.h"
|
|
|
|
#include <atlimpl.cpp>
|
|
|
|
#define __dwFILE__ __dwFILE_CERTMMC_COMPDATA_CPP__
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
|
|
struct FOLDER_DATA
|
|
{
|
|
FOLDER_TYPES type;
|
|
UINT iNameRscID;
|
|
};
|
|
static FOLDER_DATA SvrFuncFolderData[] =
|
|
{
|
|
{SERVERFUNC_CRL_PUBLICATION, IDS_CERTS_REVOKED},
|
|
{SERVERFUNC_ISSUED_CERTIFICATES, IDS_CERTS_ISSUED},
|
|
{SERVERFUNC_PENDING_CERTIFICATES, IDS_CERTS_PENDING},
|
|
{SERVERFUNC_FAILED_CERTIFICATES, IDS_CERTS_FAILED},
|
|
{SERVERFUNC_ALIEN_CERTIFICATES, IDS_CERTS_IMPORTED},
|
|
{SERVERFUNC_ISSUED_CRLS, IDS_CRL_TITLE},
|
|
};
|
|
// keep this enum in synch with SvrFuncFolderData[]
|
|
enum ENUM_FOLDERS
|
|
{
|
|
ENUM_FOLDER_CRL=0,
|
|
ENUM_FOLDER_ISSUED,
|
|
ENUM_FOLDER_PENDING,
|
|
ENUM_FOLDER_FAILED,
|
|
ENUM_FOLDER_ALIEN,
|
|
ENUM_FOLDER_CRLS,
|
|
};
|
|
|
|
|
|
|
|
// Array of view items to be inserted into the context menu.
|
|
// keep this enum in synch with viewItems[]
|
|
enum ENUM_TASK_STARTSTOP_ITEMS
|
|
{
|
|
ENUM_TASK_START=0,
|
|
ENUM_TASK_STOP,
|
|
ENUM_TASK_SEPERATOR,
|
|
};
|
|
|
|
MY_CONTEXTMENUITEM taskStartStop[] =
|
|
{
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_STARTSERVER, CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, 0
|
|
},
|
|
IDS_TASKMENU_STARTSERVICE,
|
|
IDS_TASKMENU_STATUSBAR_STARTSERVICE,
|
|
CA_ACCESS_ADMIN,
|
|
},
|
|
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_STOPSERVER, CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, 0
|
|
},
|
|
IDS_TASKMENU_STOPSERVICE,
|
|
IDS_TASKMENU_STATUSBAR_STOPSERVICE,
|
|
CA_ACCESS_ADMIN,
|
|
},
|
|
|
|
{
|
|
{ NULL, NULL, 0, 0, 0 },
|
|
IDS_EMPTY,
|
|
IDS_EMPTY,
|
|
},
|
|
};
|
|
|
|
|
|
// Array of view items to be inserted into the context menu.
|
|
// WARNING: keep this enum in synch with taskItems[]
|
|
enum ENUM_TASK_ITEMS
|
|
{
|
|
ENUM_TASK_CRLPUB=0,
|
|
ENUM_TASK_ATTREXTS_CRL,
|
|
ENUM_TASK_ATTREXTS_ISS,
|
|
ENUM_TASK_ATTREXTS_PEND,
|
|
ENUM_TASK_ATTREXTS_FAIL,
|
|
ENUM_TASK_DUMP_ASN_CRLPUB,
|
|
ENUM_TASK_DUMP_ASN_ISS,
|
|
ENUM_TASK_DUMP_ASN_PEND,
|
|
ENUM_TASK_DUMP_ASN_FAIL,
|
|
ENUM_TASK_DUMP_ASN_ALIEN,
|
|
ENUM_TASK_DUMP_ASN_CRL,
|
|
ENUM_TASK_SEPERATOR1,
|
|
ENUM_TASK_SEPERATOR4,
|
|
ENUM_TASK_SUBMIT_REQUEST,
|
|
ENUM_TASK_REVOKECERT,
|
|
ENUM_TASK_RESUBMITREQ,
|
|
ENUM_TASK_DENYREQ,
|
|
ENUM_TASK_RESUBMITREQ2,
|
|
ENUM_TASK_SEPERATOR2,
|
|
ENUM_TASK_BACKUP,
|
|
ENUM_TASK_RESTORE,
|
|
ENUM_TASK_SEPERATOR3,
|
|
ENUM_TASK_INSTALL,
|
|
ENUM_TASK_REQUEST,
|
|
ENUM_TASK_ROLLOVER,
|
|
};
|
|
|
|
TASKITEM taskItems[] =
|
|
{
|
|
|
|
{ SERVERFUNC_CRL_PUBLICATION,
|
|
0,
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_PUBLISHCRL, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_PUBLISHCRL,
|
|
IDS_TASKMENU_STATUSBAR_PUBLISHCRL,
|
|
CA_ACCESS_ADMIN,
|
|
}
|
|
},
|
|
|
|
/////////////////////
|
|
// BEGIN ATTR/EXT
|
|
{ SERVERFUNC_CRL_PUBLICATION, // where
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_VIEW_ATTR_EXT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_VIEWATTREXT,
|
|
IDS_TASKMENU_STATUSBAR_VIEWATTREXT,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
{ SERVERFUNC_ISSUED_CERTIFICATES, // where
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_VIEW_ATTR_EXT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_VIEWATTREXT,
|
|
IDS_TASKMENU_STATUSBAR_VIEWATTREXT,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
{ SERVERFUNC_PENDING_CERTIFICATES, // where
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_VIEW_ATTR_EXT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_VIEWATTREXT,
|
|
IDS_TASKMENU_STATUSBAR_VIEWATTREXT,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
{ SERVERFUNC_FAILED_CERTIFICATES, // where
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_VIEW_ATTR_EXT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_VIEWATTREXT,
|
|
IDS_TASKMENU_STATUSBAR_VIEWATTREXT,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
|
|
// END ATTR/EXT
|
|
/////////////////////
|
|
|
|
/////////////////////
|
|
// BEGIN ENUM_TASK_DUMP_ASN*
|
|
{ SERVERFUNC_CRL_PUBLICATION, // where
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_DUMPASN,
|
|
IDS_TASKMENU_STATUSBAR_DUMPASN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
{ SERVERFUNC_ISSUED_CERTIFICATES, // where
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_DUMPASN,
|
|
IDS_TASKMENU_STATUSBAR_DUMPASN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
{ SERVERFUNC_PENDING_CERTIFICATES, // where
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_DUMPASN,
|
|
IDS_TASKMENU_STATUSBAR_DUMPASN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
{ SERVERFUNC_FAILED_CERTIFICATES, // where
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_DUMPASN,
|
|
IDS_TASKMENU_STATUSBAR_DUMPASN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
{ SERVERFUNC_ALIEN_CERTIFICATES, // where
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_DUMPASN,
|
|
IDS_TASKMENU_STATUSBAR_DUMPASN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
{ SERVERFUNC_ISSUED_CRLS, // where
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_DUMP_ASN, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_DUMPASN,
|
|
IDS_TASKMENU_STATUSBAR_DUMPASN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
// END ENUM_TASK_DUMP_ASN*
|
|
/////////////////////
|
|
|
|
|
|
// seperator
|
|
{ SERVERFUNC_ALL_FOLDERS,
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
0, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, CCM_SPECIAL_SEPARATOR
|
|
},
|
|
IDS_EMPTY,
|
|
IDS_EMPTY,
|
|
}
|
|
},
|
|
|
|
// seperator
|
|
{ SERVER_INSTANCE,
|
|
0, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
0, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, CCM_SPECIAL_SEPARATOR
|
|
},
|
|
IDS_EMPTY,
|
|
IDS_EMPTY,
|
|
}
|
|
},
|
|
|
|
{ SERVER_INSTANCE,
|
|
0,
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_SUBMITREQUEST, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_SUBMITREQUEST,
|
|
IDS_TASKMENU_STATUSBAR_SUBMITREQUEST,
|
|
CA_ACCESS_ENROLL,
|
|
}
|
|
},
|
|
|
|
{ SERVERFUNC_ISSUED_CERTIFICATES,
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_REVOKECERT, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_REVOKECERT,
|
|
IDS_TASKMENU_STATUSBAR_REVOKECERT,
|
|
CA_ACCESS_OFFICER,
|
|
}
|
|
},
|
|
|
|
{ SERVERFUNC_PENDING_CERTIFICATES,
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_RESUBMITREQUEST, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_RESUBMIT,
|
|
IDS_TASKMENU_STATUSBAR_RESUBMIT,
|
|
CA_ACCESS_OFFICER,
|
|
}
|
|
},
|
|
|
|
{ SERVERFUNC_PENDING_CERTIFICATES,
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_DENYREQUEST, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_DENYREQUEST,
|
|
IDS_TASKMENU_STATUSBAR_DENYREQUEST,
|
|
CA_ACCESS_OFFICER,
|
|
}
|
|
},
|
|
|
|
{ SERVERFUNC_FAILED_CERTIFICATES,
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_RESUBMITREQUEST, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_RESUBMIT,
|
|
IDS_TASKMENU_STATUSBAR_RESUBMIT,
|
|
CA_ACCESS_OFFICER,
|
|
}
|
|
},
|
|
|
|
// seperator
|
|
{ SERVERFUNC_ALL_FOLDERS,
|
|
0, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
0, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, CCM_SPECIAL_SEPARATOR
|
|
},
|
|
IDS_EMPTY,
|
|
IDS_EMPTY,
|
|
}
|
|
},
|
|
|
|
{ SERVER_INSTANCE,
|
|
TASKITEM_FLAG_LOCALONLY,
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_BACKUP_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_BACKUP,
|
|
IDS_TASKMENU_STATUSBAR_BACKUP,
|
|
CA_ACCESS_OPERATOR,
|
|
}
|
|
},
|
|
|
|
{ SERVER_INSTANCE,
|
|
TASKITEM_FLAG_LOCALONLY,
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_RESTORE_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_RESTORE,
|
|
IDS_TASKMENU_STATUSBAR_RESTORE,
|
|
CA_ACCESS_OPERATOR,
|
|
}
|
|
},
|
|
|
|
// seperator
|
|
{ SERVER_INSTANCE,
|
|
0,
|
|
{
|
|
{
|
|
L"", L"",
|
|
0, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, CCM_SPECIAL_SEPARATOR
|
|
},
|
|
IDS_EMPTY,
|
|
IDS_EMPTY,
|
|
}
|
|
},
|
|
|
|
|
|
{ SERVER_INSTANCE,
|
|
0,
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_INSTALL_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_INSTALL_CA,
|
|
IDS_TASKMENU_STATUSBAR_INSTALL_CA,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // not based on roles, enable for all roles
|
|
}
|
|
},
|
|
|
|
{ SERVER_INSTANCE,
|
|
0,
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_REQUEST_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_ENABLED, 0
|
|
},
|
|
IDS_TASKMENU_REQUEST_CA,
|
|
IDS_TASKMENU_STATUSBAR_REQUEST_CA,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // not based on roles, enable for all roles
|
|
}
|
|
},
|
|
|
|
{ SERVER_INSTANCE,
|
|
TASKITEM_FLAG_LOCALONLY,
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_ROLLOVER_CA, CCM_INSERTIONPOINTID_PRIMARY_TASK, MF_GRAYED, 0
|
|
},
|
|
IDS_TASKMENU_ROLLOVER,
|
|
IDS_TASKMENU_STATUSBAR_ROLLOVER,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // not based on roles, enable for all roles
|
|
}
|
|
},
|
|
|
|
|
|
{ NONE,
|
|
FALSE,
|
|
{
|
|
{ NULL, NULL, 0, 0, 0 },
|
|
IDS_EMPTY,
|
|
IDS_EMPTY,
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
// Array of view items to be inserted into the context menu.
|
|
// keep this enum in synch with topItems[]
|
|
enum ENUM_TOP_ITEMS
|
|
{
|
|
ENUM_TOP_REVOKEDOPEN=0,
|
|
ENUM_TOP_ISSUEDOPEN,
|
|
ENUM_TOP_ALIENOPEN,
|
|
ENUM_RETARGET_SNAPIN,
|
|
};
|
|
|
|
TASKITEM topItems[] =
|
|
{
|
|
|
|
{ SERVERFUNC_CRL_PUBLICATION,
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_VIEW_CERT_PROPERTIES, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, CCM_SPECIAL_DEFAULT_ITEM
|
|
},
|
|
IDS_TOPMENU_OPEN,
|
|
IDS_TOPMENU_STATUSBAR_OPEN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
|
|
{ SERVERFUNC_ISSUED_CERTIFICATES,
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_VIEW_CERT_PROPERTIES, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, CCM_SPECIAL_DEFAULT_ITEM
|
|
},
|
|
IDS_TOPMENU_OPEN,
|
|
IDS_TOPMENU_STATUSBAR_OPEN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
|
|
{ SERVERFUNC_ALIEN_CERTIFICATES,
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_VIEW_CERT_PROPERTIES, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, CCM_SPECIAL_DEFAULT_ITEM
|
|
},
|
|
IDS_TOPMENU_OPEN,
|
|
IDS_TOPMENU_STATUSBAR_OPEN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
|
|
{ SERVERFUNC_ISSUED_CRLS,
|
|
TASKITEM_FLAG_RESULTITEM, // dwFlags
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_VIEW_CERT_PROPERTIES, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, CCM_SPECIAL_DEFAULT_ITEM
|
|
},
|
|
IDS_TOPMENU_OPEN,
|
|
IDS_TOPMENU_STATUSBAR_OPEN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
|
|
{
|
|
MACHINE_INSTANCE,
|
|
0,
|
|
{
|
|
{
|
|
L"", L"",
|
|
IDC_RETARGET_SNAPIN, CCM_INSERTIONPOINTID_PRIMARY_TOP, MF_ENABLED, 0
|
|
},
|
|
IDS_RETARGET_SNAPIN,
|
|
IDS_STATUSBAR_RETARGET_SNAPIN,
|
|
CA_ACCESS_MASKROLES|CA_ACCESS_READ, // any role with read acccess
|
|
}
|
|
},
|
|
|
|
{ NONE,
|
|
0,
|
|
{
|
|
{ NULL, NULL, 0, 0, 0 },
|
|
IDS_EMPTY,
|
|
IDS_EMPTY,
|
|
}
|
|
}
|
|
};
|
|
|
|
BOOL g_fCertViewOnly = TRUE;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IComponentData implementation
|
|
|
|
DEBUG_DECLARE_INSTANCE_COUNTER(CComponentDataImpl);
|
|
|
|
CComponentDataImpl::CComponentDataImpl()
|
|
: m_bIsDirty(TRUE), m_pScope(NULL), m_pConsole(NULL)
|
|
#if DBG
|
|
, m_bInitializedCD(false), m_bDestroyedCD(false)
|
|
#endif
|
|
{
|
|
DEBUG_INCREMENT_INSTANCE_COUNTER(CComponentDataImpl);
|
|
|
|
m_dwFlagsPersist = 0;
|
|
|
|
m_pStaticRoot = NULL;
|
|
m_pCurSelFolder = NULL;
|
|
|
|
m_fScopeAlreadyEnumerated = FALSE;
|
|
m_fSchemaWasResolved = FALSE; // resolve schema once per load
|
|
m_fCertView = TRUE;
|
|
|
|
// checked in ::Initialize, ::CreatePropertyPages
|
|
m_pCertMachine = new CertSvrMachine;
|
|
|
|
m_cLastKnownSchema = 0;
|
|
m_rgcstrLastKnownSchema = NULL;
|
|
m_rgltypeLastKnownSchema = NULL;
|
|
m_rgfindexedLastKnownSchema = NULL;
|
|
|
|
m_dwNextViewIndex = 0;
|
|
}
|
|
|
|
CComponentDataImpl::~CComponentDataImpl()
|
|
{
|
|
DEBUG_DECREMENT_INSTANCE_COUNTER(CComponentDataImpl);
|
|
|
|
ASSERT(m_pScope == NULL);
|
|
ASSERT(!m_bInitializedCD || m_bDestroyedCD);
|
|
|
|
// Delete enumerated scope items
|
|
// note: we don't own pCA memory, m_pCertMachine does
|
|
POSITION pos = m_scopeItemList.GetHeadPosition();
|
|
while (pos)
|
|
delete m_scopeItemList.GetNext(pos);
|
|
m_scopeItemList.RemoveAll();
|
|
|
|
m_pCurSelFolder = NULL;
|
|
m_fScopeAlreadyEnumerated = FALSE;
|
|
|
|
if (m_pCertMachine)
|
|
m_pCertMachine->Release();
|
|
|
|
m_cLastKnownSchema = 0;
|
|
if (m_rgcstrLastKnownSchema)
|
|
delete [] m_rgcstrLastKnownSchema;
|
|
if (m_rgltypeLastKnownSchema)
|
|
delete [] m_rgltypeLastKnownSchema;
|
|
if (m_rgfindexedLastKnownSchema)
|
|
delete [] m_rgfindexedLastKnownSchema;
|
|
}
|
|
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CComponentDataImpl::AddRef()
|
|
{
|
|
return InterlockedIncrement((LONG *) &_cRefs);
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG)
|
|
CComponentDataImpl::Release()
|
|
{
|
|
ULONG cRefsTemp;
|
|
|
|
cRefsTemp = InterlockedDecrement((LONG *)&_cRefs);
|
|
|
|
if (0 == cRefsTemp)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
return cRefsTemp;
|
|
}
|
|
|
|
int CComponentDataImpl::FindColIdx(IN LPCWSTR szHeading)
|
|
{
|
|
for (DWORD dw=0; dw<m_cLastKnownSchema; dw++)
|
|
{
|
|
if (m_rgcstrLastKnownSchema[dw].IsEqual(szHeading))
|
|
return dw;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
HRESULT CComponentDataImpl::GetDBSchemaEntry(
|
|
IN int iIndex,
|
|
OUT OPTIONAL LPCWSTR* pszHeading,
|
|
OUT OPTIONAL LONG* plType,
|
|
OUT OPTIONAL BOOL* pfIndexed)
|
|
{
|
|
if (m_cLastKnownSchema<= (DWORD)iIndex)
|
|
return HRESULT_FROM_WIN32(ERROR_INVALID_INDEX);
|
|
|
|
if (pszHeading)
|
|
*pszHeading = m_rgcstrLastKnownSchema[iIndex];
|
|
if (plType)
|
|
*plType = m_rgltypeLastKnownSchema[iIndex];
|
|
if (pfIndexed)
|
|
*pfIndexed = m_rgfindexedLastKnownSchema[iIndex];
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CComponentDataImpl::SetDBSchema(
|
|
IN CString* rgcstr,
|
|
LONG* rgtype,
|
|
BOOL* rgfIndexed,
|
|
DWORD cEntries)
|
|
{
|
|
if (m_rgcstrLastKnownSchema)
|
|
delete [] m_rgcstrLastKnownSchema;
|
|
m_rgcstrLastKnownSchema = rgcstr;
|
|
|
|
if (m_rgltypeLastKnownSchema)
|
|
delete [] m_rgltypeLastKnownSchema;
|
|
m_rgltypeLastKnownSchema = rgtype;
|
|
|
|
if (m_rgfindexedLastKnownSchema)
|
|
delete [] m_rgfindexedLastKnownSchema;
|
|
m_rgfindexedLastKnownSchema = rgfIndexed;
|
|
|
|
m_cLastKnownSchema = cEntries;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CComponentDataImpl::Initialize(LPUNKNOWN pUnknown)
|
|
{
|
|
// NOTA BENE: Init is called when a snap-in is being
|
|
// created and has items to enumerate in the scope pane ... NOT BEFORE
|
|
// Example: Add/Remove snapin, Add...
|
|
// -> CComponentDataImpl will get called for CreatePropertyPages() before ::Initialize is called
|
|
|
|
#if DBG
|
|
m_bInitializedCD = true;
|
|
#endif
|
|
|
|
ASSERT(pUnknown != NULL);
|
|
HRESULT hr;
|
|
|
|
LPIMAGELIST lpScopeImage = NULL;
|
|
CBitmap bmpResultStrip16x16, bmpResultStrip32x32;
|
|
|
|
g_pResources = new CLocalizedResources;
|
|
if (NULL == g_pResources)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
_JumpError(hr, Ret, "Alloc Resources");
|
|
}
|
|
|
|
// Load resources
|
|
if (!g_pResources->Load())
|
|
{
|
|
hr = GetLastError();
|
|
_JumpError(hr, Ret, "Load Resources");
|
|
}
|
|
|
|
// create a per-instance id (failure not fatal)
|
|
ResetPersistedColumnInformation();
|
|
|
|
// MMC should only call ::Initialize once!
|
|
|
|
// m_pCertMachine created in constructor, but verified here
|
|
ASSERT(m_pCertMachine != NULL);
|
|
_JumpIfOutOfMemory(hr, Ret, m_pCertMachine);
|
|
|
|
// MMC should only call ::Initialize once!
|
|
ASSERT(m_pScope == NULL);
|
|
hr = pUnknown->QueryInterface(IID_IConsoleNameSpace2, reinterpret_cast<void**>(&m_pScope));
|
|
_JumpIfError(hr, Ret, "QueryInterface IID_IConsoleNameSpace2");
|
|
|
|
// add the images for the scope tree
|
|
hr = pUnknown->QueryInterface(IID_IConsole2, reinterpret_cast<void**>(&m_pConsole));
|
|
ASSERT(hr == S_OK);
|
|
_JumpIfError(hr, Ret, "QueryInterface IID_IConsole2");
|
|
|
|
hr = m_pConsole->QueryScopeImageList(&lpScopeImage);
|
|
ASSERT(hr == S_OK);
|
|
_JumpIfError(hr, Ret, "QueryScopeImageList");
|
|
|
|
if ( (NULL == bmpResultStrip16x16.LoadBitmap(IDB_16x16)) ||
|
|
(NULL == bmpResultStrip32x32.LoadBitmap(IDB_32x32)) )
|
|
{
|
|
hr = S_FALSE;
|
|
_JumpError(hr, Ret, "LoadBitmap");
|
|
}
|
|
|
|
// Load the bitmaps from the dll
|
|
lpScopeImage->ImageListSetStrip(reinterpret_cast<LONG_PTR *>(static_cast<HBITMAP>(bmpResultStrip16x16)),
|
|
reinterpret_cast<LONG_PTR *>(static_cast<HBITMAP>(bmpResultStrip32x32)),
|
|
0, RGB(255, 0, 255));
|
|
_JumpIfError(hr, Ret, "ImageListSetStrip");
|
|
|
|
|
|
Ret:
|
|
if (lpScopeImage)
|
|
lpScopeImage->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CComponentDataImpl::Destroy()
|
|
{
|
|
// release all references to the console here
|
|
ASSERT(m_bInitializedCD);
|
|
#if DBG
|
|
m_bDestroyedCD = true;
|
|
#endif
|
|
|
|
SAFE_RELEASE(m_pScope);
|
|
SAFE_RELEASE(m_pConsole);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CComponentDataImpl::CreateComponent(LPCOMPONENT* ppComponent)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ASSERT(ppComponent != NULL);
|
|
|
|
CComObject<CSnapin>* pObject;
|
|
CComObject<CSnapin>::CreateInstance(&pObject);
|
|
ASSERT(pObject != NULL);
|
|
_JumpIfOutOfMemory(hr, Ret, pObject);
|
|
|
|
// Store IComponentData
|
|
pObject->SetIComponentData(this);
|
|
pObject->SetViewID(m_dwNextViewIndex++);
|
|
|
|
hr = pObject->QueryInterface(IID_IComponent,
|
|
reinterpret_cast<void**>(ppComponent));
|
|
Ret:
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CComponentDataImpl::Notify(LPDATAOBJECT lpDataObject, MMC_NOTIFY_TYPE event, LPARAM arg, LPARAM param)
|
|
{
|
|
ASSERT(m_pScope != NULL);
|
|
HRESULT hr = S_OK;
|
|
INTERNAL* pInternal = NULL;
|
|
MMC_COOKIE cookie = NULL;
|
|
|
|
// handle events with (NULL == lpDataObject)
|
|
switch(event)
|
|
{
|
|
case MMCN_PROPERTY_CHANGE:
|
|
{
|
|
// Notification from property page "notify change"
|
|
//
|
|
// arg == fIsScopeItem
|
|
// lParam == page param value
|
|
// return value unused
|
|
|
|
if (param == CERTMMC_PROPERTY_CHANGE_REFRESHVIEWS)
|
|
{
|
|
m_pConsole->UpdateAllViews(
|
|
lpDataObject,
|
|
0,
|
|
0);
|
|
}
|
|
|
|
goto Ret;
|
|
}
|
|
|
|
default: // all others
|
|
break;
|
|
}
|
|
|
|
|
|
pInternal = ExtractInternalFormat(lpDataObject);
|
|
if (pInternal == NULL)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
cookie = pInternal->m_cookie;
|
|
FREE_DATA(pInternal);
|
|
|
|
switch(event)
|
|
{
|
|
case MMCN_PASTE:
|
|
DBGPRINT((DBG_SS_CERTMMC, "CComponentDataImpl::MMCN_PASTE"));
|
|
break;
|
|
|
|
case MMCN_DELETE:
|
|
hr = OnDelete(cookie);
|
|
break;
|
|
|
|
case MMCN_REMOVE_CHILDREN:
|
|
hr = OnRemoveChildren(arg);
|
|
break;
|
|
|
|
case MMCN_RENAME:
|
|
hr = OnRename(cookie, arg, param);
|
|
break;
|
|
|
|
case MMCN_EXPAND:
|
|
hr = OnExpand(lpDataObject, arg, param);
|
|
break;
|
|
|
|
case MMCN_PRELOAD:
|
|
{
|
|
if (NULL == cookie)
|
|
{
|
|
// base node
|
|
|
|
// this call gave us time to load our dynamic base nodename (Certification Authority on %ws)
|
|
DisplayProperRootNodeName((HSCOPEITEM)arg);
|
|
}
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Ret:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CComponentDataImpl::DisplayProperRootNodeName(HSCOPEITEM hRoot)
|
|
{
|
|
// hRoot not optional
|
|
if (hRoot == NULL)
|
|
return E_POINTER;
|
|
|
|
// if static root not yet set, save it (CASE: load from file)
|
|
if (m_pStaticRoot == NULL)
|
|
m_pStaticRoot = hRoot;
|
|
|
|
// let us have time to load our dynamic base nodename (Certification Authority on %ws)
|
|
SCOPEDATAITEM item;
|
|
item.mask = SDI_STR;
|
|
item.ID = hRoot;
|
|
|
|
CString cstrMachineName;
|
|
CString cstrDisplayStr, cstrFormatStr, cstrMachine;
|
|
|
|
cstrFormatStr.LoadString(IDS_NODENAME_FORMAT);
|
|
if (m_pCertMachine->m_strMachineName.IsEmpty())
|
|
cstrMachine.LoadString(IDS_LOCALMACHINE);
|
|
else
|
|
cstrMachine = m_pCertMachine->m_strMachineName;
|
|
|
|
if (!cstrFormatStr.IsEmpty())
|
|
{
|
|
cstrMachineName.Format(cstrFormatStr, cstrMachine);
|
|
item.displayname = (LPWSTR)(LPCWSTR)cstrMachineName;
|
|
}
|
|
else
|
|
{
|
|
// protect against null formatstring
|
|
item.displayname = (LPWSTR)(LPCWSTR)cstrMachine;
|
|
}
|
|
m_pScope->SetItem (&item);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CComponentDataImpl::QueryDataObject(MMC_COOKIE cookie, DATA_OBJECT_TYPES type, LPDATAOBJECT* ppDataObject)
|
|
{
|
|
#ifdef _DEBUG
|
|
if (cookie == 0)
|
|
{
|
|
ASSERT(type != CCT_RESULT);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(type == CCT_SCOPE);
|
|
|
|
DWORD dwItemType = *reinterpret_cast<DWORD*>(cookie);
|
|
ASSERT((dwItemType == SCOPE_LEVEL_ITEM) || (dwItemType == CA_LEVEL_ITEM));
|
|
}
|
|
#endif
|
|
|
|
return _QueryDataObject(cookie, type, MAXDWORD, this, ppDataObject);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//// ISnapinHelp interface
|
|
STDMETHODIMP CComponentDataImpl::GetHelpTopic(LPOLESTR* lpCompiledHelpFile)
|
|
{
|
|
if (lpCompiledHelpFile == NULL)
|
|
return E_POINTER;
|
|
|
|
UINT cbWindows = 0;
|
|
WCHAR szWindows[MAX_PATH];
|
|
szWindows[0] = L'\0';
|
|
|
|
cbWindows = GetSystemWindowsDirectory(szWindows, MAX_PATH);
|
|
if (cbWindows == 0)
|
|
return S_FALSE;
|
|
cbWindows++; // include null term
|
|
cbWindows *= sizeof(WCHAR); // make this bytes, not chars
|
|
|
|
*lpCompiledHelpFile = (LPOLESTR) CoTaskMemAlloc(sizeof(HTMLHELP_COLLECTION_FILENAME) + cbWindows);
|
|
if (*lpCompiledHelpFile == NULL)
|
|
return E_OUTOFMEMORY;
|
|
myRegisterMemFree(*lpCompiledHelpFile, CSM_COTASKALLOC); // this is freed by mmc, not our tracking
|
|
|
|
|
|
USES_CONVERSION;
|
|
wcscpy(*lpCompiledHelpFile, T2OLE(szWindows));
|
|
wcscat(*lpCompiledHelpFile, T2OLE(HTMLHELP_COLLECTION_FILENAME));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// tells of other topics my chm links to
|
|
STDMETHODIMP CComponentDataImpl::GetLinkedTopics(LPOLESTR* lpCompiledHelpFiles)
|
|
{
|
|
if (lpCompiledHelpFiles == NULL)
|
|
return E_POINTER;
|
|
|
|
UINT cbWindows = 0;
|
|
WCHAR szWindows[MAX_PATH];
|
|
szWindows[0] = L'\0';
|
|
|
|
cbWindows = GetSystemWindowsDirectory(szWindows, MAX_PATH);
|
|
if (cbWindows == 0)
|
|
return S_FALSE;
|
|
cbWindows++; // include null term
|
|
cbWindows *= sizeof(WCHAR); // make this bytes, not chars
|
|
|
|
*lpCompiledHelpFiles = (LPOLESTR) CoTaskMemAlloc(sizeof(HTMLHELP_COLLECTIONLINK_FILENAME) + cbWindows);
|
|
if (*lpCompiledHelpFiles == NULL)
|
|
return E_OUTOFMEMORY;
|
|
myRegisterMemFree(*lpCompiledHelpFiles, CSM_COTASKALLOC); // this is freed by mmc, not our tracking
|
|
|
|
|
|
USES_CONVERSION;
|
|
wcscpy(*lpCompiledHelpFiles, T2OLE(szWindows));
|
|
wcscat(*lpCompiledHelpFiles, T2OLE(HTMLHELP_COLLECTIONLINK_FILENAME));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//// IPersistStream interface members
|
|
|
|
STDMETHODIMP CComponentDataImpl::GetClassID(CLSID *pClassID)
|
|
{
|
|
ASSERT(pClassID != NULL);
|
|
|
|
// Copy the CLSID for this snapin
|
|
*pClassID = CLSID_Snapin;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CComponentDataImpl::IsDirty()
|
|
{
|
|
// Always save / Always dirty.
|
|
return ThisIsDirty() ? S_OK : S_FALSE;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CComponentDataImpl::Load(IStream *pStm)
|
|
{
|
|
ASSERT(pStm);
|
|
ASSERT(m_bInitializedCD);
|
|
|
|
// Read the string
|
|
BOOL fMachineOverrideFound = FALSE;
|
|
DWORD dwVer;
|
|
|
|
CertSvrCA* pDummyCA = NULL;
|
|
HRESULT hr;
|
|
|
|
// read version
|
|
hr = ReadOfSize(pStm, &dwVer, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "Read dwVer");
|
|
|
|
// flags is version-dependent
|
|
if (VER_CCOMPDATA_SAVE_STREAM_3 == dwVer)
|
|
{
|
|
// version 3 includes file flags
|
|
|
|
hr = ReadOfSize(pStm, &m_dwFlagsPersist, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "Read m_dwFlagsPersist");
|
|
}
|
|
else if (VER_CCOMPDATA_SAVE_STREAM_2 != dwVer)
|
|
{
|
|
// not version 2 or 3
|
|
return STG_E_OLDFORMAT;
|
|
}
|
|
|
|
// load machine data
|
|
hr = m_pCertMachine->Load(pStm);
|
|
_JumpIfError(hr, Ret, "Load m_pCertMachine")
|
|
|
|
if (m_dwFlagsPersist & CCOMPDATAIMPL_FLAGS_ALLOW_MACHINE_OVERRIDE)
|
|
{
|
|
// override m_pCertMachine->m_strMachineName (not to be persisted)
|
|
LPWSTR lpCommandLine = GetCommandLine(); // no need to free
|
|
DBGPRINT((DBG_SS_CERTMMC, "CComponentData::Load: Command line switch override enabled. Searching command line(%ws)\n", lpCommandLine));
|
|
|
|
LPWSTR pszMachineStart, pszMachineEnd;
|
|
|
|
// search for "/machine" in cmd line
|
|
_wcsupr(lpCommandLine); // convert to uppercase
|
|
pszMachineStart = wcsstr(lpCommandLine, WSZ_MACHINE_OVERRIDE_SWITCH);
|
|
|
|
do // not a loop
|
|
{
|
|
if (NULL == pszMachineStart) // user did not override
|
|
break;
|
|
|
|
pszMachineStart += WSZARRAYSIZE(WSZ_MACHINE_OVERRIDE_SWITCH); // skip past "/machine:"
|
|
|
|
//
|
|
// Found the hint switch
|
|
//
|
|
pszMachineEnd = wcschr(pszMachineStart, L' '); // look for first space char, call this end
|
|
if (NULL == pszMachineEnd)
|
|
pszMachineEnd = &pszMachineStart[wcslen(pszMachineStart)]; // space not found in this string;
|
|
|
|
m_pCertMachine->m_strMachineName = pszMachineStart;
|
|
m_pCertMachine->m_strMachineName.SetAt(SAFE_SUBTRACT_POINTERS(pszMachineEnd, pszMachineStart), L'\0');
|
|
|
|
DBGPRINT((DBG_SS_CERTMMC, "CComponentData::Load: Found machinename (%ws)\n", m_pCertMachine->m_strMachineName));
|
|
fMachineOverrideFound = TRUE;
|
|
|
|
} while (0);
|
|
}
|
|
|
|
if (!fMachineOverrideFound)
|
|
{
|
|
// Get CA count
|
|
DWORD dwNumCAs;
|
|
hr = ReadOfSize(pStm, &dwNumCAs, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "Load dwNumCAs");
|
|
|
|
// for each CA, get folder data
|
|
for (DWORD dwCA=0; dwCA< dwNumCAs; dwCA++)
|
|
{
|
|
CString cstrThisCA;
|
|
|
|
hr = CStringLoad(cstrThisCA, pStm);
|
|
_JumpIfError(hr, Ret, "CStringLoad");
|
|
|
|
// create a dummy CA with the correct common name; we'll fix this later (see Synch CA)
|
|
pDummyCA = new CertSvrCA(m_pCertMachine);
|
|
_JumpIfOutOfMemory(hr, Ret, pDummyCA);
|
|
|
|
pDummyCA->m_strCommonName = cstrThisCA;
|
|
|
|
if (VER_CCOMPDATA_SAVE_STREAM_2 < dwVer)
|
|
{
|
|
m_fSchemaWasResolved = FALSE; // resolve schema once per CComponentData load
|
|
|
|
// LOAD last known schema
|
|
hr = ReadOfSize(pStm, &m_cLastKnownSchema, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "Load m_cLastKnownSchema");
|
|
|
|
// alloc
|
|
if (m_cLastKnownSchema != 0)
|
|
{
|
|
m_rgcstrLastKnownSchema = new CString[m_cLastKnownSchema];
|
|
_JumpIfOutOfMemory(hr, Ret, m_rgcstrLastKnownSchema);
|
|
|
|
for (unsigned int i=0; i<m_cLastKnownSchema; i++)
|
|
{
|
|
hr = CStringLoad(m_rgcstrLastKnownSchema[i], pStm);
|
|
_JumpIfError(hr, Ret, "Load m_rgcstrLastKnownSchema");
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
// find out how many folders are in the stream under this CA
|
|
DWORD dwNumFolders=0;
|
|
hr = ReadOfSize(pStm, &dwNumFolders, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "Load dwNumFolders");
|
|
|
|
// load each of these
|
|
for(DWORD dwCount=0; dwCount<dwNumFolders; dwCount++)
|
|
{
|
|
CFolder* pFolder = new CFolder();
|
|
_JumpIfOutOfMemory(hr, Ret, pFolder);
|
|
|
|
// point at previously constructed dummy ca; we'll fix this later
|
|
pFolder->m_pCertCA = pDummyCA;
|
|
|
|
hr = pFolder->Load(pStm);
|
|
_JumpIfError(hr, Ret, "Load CFolder");
|
|
|
|
m_scopeItemList.AddTail(pFolder);
|
|
}
|
|
pDummyCA = NULL; // owned by at least one folder
|
|
}
|
|
}
|
|
|
|
// version-dependent info
|
|
if (VER_CCOMPDATA_SAVE_STREAM_2 < dwVer)
|
|
{
|
|
// per-instance guid for identifying columns uniquely
|
|
hr = ReadOfSize(pStm, &m_guidInstance, sizeof(GUID));
|
|
_JumpIfError(hr, Ret, "ReadOfSize instance guid");
|
|
|
|
hr = ReadOfSize(pStm, &m_dwNextViewIndex, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "ReadOfSize view index");
|
|
}
|
|
|
|
Ret:
|
|
if (pDummyCA)
|
|
delete pDummyCA;
|
|
|
|
ClearDirty();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP CComponentDataImpl::Save(IStream *pStm, BOOL fClearDirty)
|
|
{
|
|
ASSERT(pStm);
|
|
ASSERT(m_bInitializedCD);
|
|
|
|
HRESULT hr;
|
|
DWORD dwVer;
|
|
DWORD dwCA;
|
|
DWORD dwNumCAs;
|
|
|
|
#if DBG_CERTSRV
|
|
bool fSaveConsole = false;
|
|
|
|
LPWSTR lpCommandLine = GetCommandLine(); // no need to free
|
|
_wcsupr(lpCommandLine); // convert to uppercase
|
|
fSaveConsole = (NULL!=wcsstr(lpCommandLine, L"/certsrv_saveconsole"));
|
|
#endif
|
|
|
|
// Write the version
|
|
dwVer = VER_CCOMPDATA_SAVE_STREAM_3;
|
|
hr = WriteOfSize(pStm, &dwVer, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "Save dwVer");
|
|
|
|
// write dwFlags (a VERSION 3 addition)
|
|
hr = WriteOfSize(pStm, &m_dwFlagsPersist, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "pStm->Write m_dwFlagsPersist");
|
|
|
|
#if DBG_CERTSRV
|
|
if(fSaveConsole)
|
|
m_pCertMachine->m_strMachineNamePersist.Empty();
|
|
#endif
|
|
|
|
hr = m_pCertMachine->Save(pStm, fClearDirty);
|
|
_JumpIfError(hr, Ret, "Save m_pCertMachine");
|
|
|
|
// save CA count
|
|
dwNumCAs = m_pCertMachine->GetCaCount();
|
|
hr = WriteOfSize(pStm, &dwNumCAs, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "pStm->Write dwNumCAs");
|
|
|
|
// for each CA, save folder info
|
|
for (dwCA=0; dwCA < dwNumCAs; dwCA++)
|
|
{
|
|
DWORD dwNumFolders=0;
|
|
CString cstrThisCA, cstrThisCASave;
|
|
cstrThisCASave = cstrThisCA = m_pCertMachine->GetCaCommonNameAtPos(dwCA);
|
|
|
|
#if DBG_CERTSRV
|
|
if(fSaveConsole)
|
|
cstrThisCASave.Empty();
|
|
#endif
|
|
hr = CStringSave(cstrThisCASave, pStm, fClearDirty);
|
|
_JumpIfError(hr, Ret, "CStringSave");
|
|
|
|
// SAVE last known schema
|
|
hr = WriteOfSize(pStm, &m_cLastKnownSchema, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "pStm->Write m_cLastKnownSchema");
|
|
|
|
for (unsigned int i=0; i<m_cLastKnownSchema; i++)
|
|
{
|
|
hr = CStringSave(m_rgcstrLastKnownSchema[i], pStm, fClearDirty);
|
|
_JumpIfError(hr, Ret, "CStringSave");
|
|
}
|
|
|
|
// walk through every folder, find how many folders to save
|
|
POSITION pos = m_scopeItemList.GetHeadPosition();
|
|
while(pos)
|
|
{
|
|
CFolder* pFolder = m_scopeItemList.GetNext(pos);
|
|
if (pFolder->GetCA()->m_strCommonName.IsEqual(cstrThisCA))
|
|
dwNumFolders++;
|
|
}
|
|
|
|
// write how many folders under this CA
|
|
hr = WriteOfSize(pStm, &dwNumFolders, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "pStm->Write dwNumFolders");
|
|
|
|
pos = m_scopeItemList.GetHeadPosition();
|
|
while(pos)
|
|
{
|
|
CFolder* pFolder = m_scopeItemList.GetNext(pos);
|
|
if (pFolder->GetCA()->m_strCommonName.IsEqual(cstrThisCA))
|
|
{
|
|
hr = pFolder->Save(pStm, fClearDirty);
|
|
_JumpIfError(hr, Ret, "Save CFolder");
|
|
}
|
|
}
|
|
}
|
|
|
|
// per-instance guid for identifying columns uniquely
|
|
hr = WriteOfSize(pStm, &m_guidInstance, sizeof(GUID));
|
|
_JumpIfError(hr, Ret, "WriteOfSize instance guid");
|
|
|
|
hr = WriteOfSize(pStm, &m_dwNextViewIndex, sizeof(DWORD));
|
|
_JumpIfError(hr, Ret, "WriteOfSize view index");
|
|
|
|
Ret:
|
|
if (fClearDirty)
|
|
ClearDirty();
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CComponentDataImpl::GetSizeMax(ULARGE_INTEGER *pcbSize)
|
|
{
|
|
ASSERT(pcbSize);
|
|
|
|
int iTotalSize=0;
|
|
|
|
// version
|
|
iTotalSize = sizeof(DWORD) + sizeof(m_dwFlagsPersist);
|
|
|
|
// machine info
|
|
int iSize;
|
|
m_pCertMachine->GetSizeMax(&iSize);
|
|
iTotalSize += iSize;
|
|
|
|
// CA count
|
|
iTotalSize += sizeof(DWORD);
|
|
|
|
DWORD dwNumCAs = m_pCertMachine->GetCaCount();
|
|
for (DWORD dwCA=0; dwCA < dwNumCAs; dwCA++)
|
|
{
|
|
CString cstrThisCA;
|
|
cstrThisCA = m_pCertMachine->GetCaCommonNameAtPos(dwCA);
|
|
CStringGetSizeMax(cstrThisCA, &iSize);
|
|
iTotalSize += iSize;
|
|
|
|
// Number of folders under this CA
|
|
iTotalSize += sizeof(DWORD);
|
|
|
|
// walk through every folder, find how many folders to save
|
|
POSITION pos = m_scopeItemList.GetHeadPosition();
|
|
while(pos)
|
|
{
|
|
CFolder* pFolder = m_scopeItemList.GetNext(pos);
|
|
if (pFolder->GetCA()->m_strCommonName.IsEqual(cstrThisCA))
|
|
{
|
|
// folder size
|
|
pFolder->GetSizeMax(&iSize);
|
|
iTotalSize += iSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
// per-instance guid for identifying columns uniquely
|
|
iTotalSize += sizeof(GUID);
|
|
|
|
// next View Index to assign
|
|
iTotalSize += sizeof(DWORD);
|
|
|
|
|
|
// size of string to be saved
|
|
pcbSize->QuadPart = iTotalSize;
|
|
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//// Notify handlers for IComponentData
|
|
|
|
HRESULT
|
|
CComponentDataImpl::OnDelete(
|
|
MMC_COOKIE /* cookie */ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
CComponentDataImpl::OnRemoveChildren(
|
|
LPARAM /* arg */ )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
VOID SetCertView()
|
|
{
|
|
LPWSTR lpCommandLine = GetCommandLine(); // no need to free
|
|
LPWSTR pwsz;
|
|
DWORD dw;
|
|
static BOOL s_fFirst = TRUE;
|
|
#define wszCOMMANDLINEE L"/E"
|
|
|
|
if (s_fFirst)
|
|
{
|
|
// search for "/e" in cmd line
|
|
_wcsupr(lpCommandLine); // convert to uppercase
|
|
pwsz = wcsstr(lpCommandLine, wszCOMMANDLINEE);
|
|
|
|
do // not a loop
|
|
{
|
|
if (NULL == pwsz) // user did not override
|
|
break;
|
|
|
|
pwsz += WSZARRAYSIZE(wszCOMMANDLINEE); // skip past "/e"
|
|
if (L'\0' != *pwsz && L' ' != *pwsz)
|
|
break;
|
|
g_fCertViewOnly = FALSE;
|
|
} while (0);
|
|
if (g_fCertViewOnly && NULL != getenv("certsrv_crl"))
|
|
g_fCertViewOnly = FALSE;
|
|
if (g_fCertViewOnly &&
|
|
S_OK == myGetCertRegDWValue(NULL, NULL, NULL, L"CRL", &dw) &&
|
|
0 != dw)
|
|
g_fCertViewOnly = FALSE;
|
|
s_fFirst = FALSE;
|
|
}
|
|
}
|
|
|
|
HRESULT CComponentDataImpl::OnRename(MMC_COOKIE cookie, LPARAM arg, LPARAM param)
|
|
{
|
|
// cookie is cookie
|
|
// arg is fRenamed (ask for permission/notify of rename)
|
|
// param (szNewName)
|
|
|
|
CFolder* pFolder = reinterpret_cast<CFolder*>(cookie);
|
|
BOOL fRenamed = (BOOL)arg;
|
|
|
|
if (!fRenamed)
|
|
{
|
|
if (pFolder)
|
|
return S_FALSE; // don't allow children to be renamed
|
|
else
|
|
return S_OK; // allow root to be renamed
|
|
}
|
|
|
|
LPOLESTR pszNewName = reinterpret_cast<LPOLESTR>(param);
|
|
if (pszNewName == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (pFolder)
|
|
{
|
|
ASSERT(pFolder != NULL);
|
|
if (pFolder == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
pFolder->SetName(pszNewName);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CComponentDataImpl::OnExpand(LPDATAOBJECT lpDataObject, LPARAM arg, LPARAM param)
|
|
{
|
|
if (arg == TRUE)
|
|
{
|
|
// Did Initialize get called?
|
|
ASSERT(m_pScope != NULL);
|
|
|
|
EnumerateScopePane(lpDataObject, param);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT CComponentDataImpl::SynchDisplayedCAList(LPDATAOBJECT lpDataObject)
|
|
{
|
|
HRESULT hr;
|
|
BOOL fFound;
|
|
POSITION pos, nextpos;
|
|
DWORD dwKnownCAs;
|
|
|
|
m_fScopeAlreadyEnumerated = TRUE; // don't need to refresh view automagically from enum if we get here
|
|
|
|
// should never get here otherwise
|
|
ASSERT(m_pStaticRoot);
|
|
if (NULL == m_pStaticRoot)
|
|
return E_POINTER;
|
|
|
|
// select root node, delete all items in UI underneath (we'll readd if necessary)
|
|
hr = m_pConsole->SelectScopeItem(m_pStaticRoot);
|
|
_PrintIfError2(hr, "SelectScopeItem", hr);
|
|
|
|
hr = m_pScope->DeleteItem(m_pStaticRoot, FALSE); // remove everything from UI
|
|
_PrintIfError2(hr, "DeleteItem", hr);
|
|
|
|
|
|
// build knowledge of current CAs
|
|
// note: this may orphan some pCAs, but we'll catch it during cleanup
|
|
HWND hwndMain = NULL;
|
|
hr = m_pConsole->GetMainWindow(&hwndMain);
|
|
if (hr != S_OK)
|
|
hwndMain = NULL; // this should work
|
|
|
|
// this hr gets returned after we're done
|
|
hr = m_pCertMachine->PrepareData(hwndMain);
|
|
|
|
// don't fail out if PrepareData fails -- we still need to
|
|
// make the snapin state reflect no known nodes!
|
|
ASSERT((hr == S_OK) || (0 == m_pCertMachine->GetCaCount()) ); // make sure m_pCertMachine zeros itself
|
|
|
|
// Tasks
|
|
// #1: Remove folders in m_scopeItemList for CAs that no longer exist in m_pCertMachine.m_rgpCAList[]
|
|
|
|
// #2: Add folders to m_scopeItemList for CAs that now exist in m_pCertMachine.m_rgpCAList[]
|
|
|
|
// Task #1
|
|
// scour m_scopeItemList for entries we already know about, delete stale folders
|
|
|
|
for (pos = m_scopeItemList.GetHeadPosition(); (NULL != pos); )
|
|
{
|
|
// ASSERTION: every folder has an associated m_pCertCA
|
|
ASSERT(NULL != m_scopeItemList.GetAt(pos)->m_pCertCA);
|
|
|
|
nextpos = pos; // save next position off
|
|
fFound = FALSE;
|
|
|
|
// for each scope item, walk through m_rgpCAList looking for current
|
|
for (dwKnownCAs=0; dwKnownCAs<(DWORD)m_pCertMachine->m_CAList.GetSize(); dwKnownCAs++)
|
|
{
|
|
if (m_scopeItemList.GetAt(pos)->m_pCertCA->m_strCommonName.IsEqual(m_pCertMachine->GetCaCommonNameAtPos(dwKnownCAs)))
|
|
{
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
CFolder* pFolder = m_scopeItemList.GetAt(pos);
|
|
ASSERT(pFolder); // this should never happen
|
|
if (pFolder == NULL)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, Ret, "GetAt");
|
|
}
|
|
|
|
if (fFound)
|
|
{
|
|
// always point to latest pCA:
|
|
// NOTE: this allows for load to populate us with dummy CAs!
|
|
pFolder->m_pCertCA = m_pCertMachine->GetCaAtPos(dwKnownCAs);
|
|
|
|
// if base node, do insert (other nodes get inserted during Expand() notification)
|
|
if (SERVER_INSTANCE == pFolder->GetType())
|
|
BaseFolderInsertIntoScope(pFolder, pFolder->m_pCertCA);
|
|
|
|
// fwd to next elt
|
|
m_scopeItemList.GetNext(pos);
|
|
}
|
|
else // !fFound
|
|
{
|
|
// delete immediately from m_scopeItemList
|
|
m_scopeItemList.GetNext(nextpos);
|
|
|
|
delete pFolder; // destroy the elt
|
|
m_scopeItemList.RemoveAt(pos);
|
|
|
|
pos = nextpos; // restore next position
|
|
}
|
|
}
|
|
|
|
// Task #2
|
|
// scour m_pCertMachine[] for new entries, create default folders
|
|
|
|
for (dwKnownCAs=0; dwKnownCAs<(DWORD)m_pCertMachine->m_CAList.GetSize(); dwKnownCAs++)
|
|
{
|
|
fFound = FALSE;
|
|
for (pos = m_scopeItemList.GetHeadPosition(); (NULL != pos); m_scopeItemList.GetNext(pos))
|
|
{
|
|
if (m_scopeItemList.GetAt(pos)->m_pCertCA->m_strCommonName.IsEqual(m_pCertMachine->GetCaCommonNameAtPos(dwKnownCAs)))
|
|
{
|
|
fFound = TRUE;
|
|
break; // if matches something in the refreshed list, we're fine
|
|
}
|
|
}
|
|
|
|
// found?
|
|
if (!fFound)
|
|
{
|
|
CertSvrCA* pCA;
|
|
CFolder* pFolder;
|
|
|
|
pCA = m_pCertMachine->GetCaAtPos(dwKnownCAs);
|
|
if (NULL == pCA)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, Ret, "m_pCertMachine->GetCaAtPos(iCAPos)");
|
|
}
|
|
|
|
// create base node, add to list, insert into scope pane
|
|
pFolder = new CFolder();
|
|
_JumpIfOutOfMemory(hr, Ret, pFolder);
|
|
|
|
m_scopeItemList.AddTail(pFolder);
|
|
|
|
hr = BaseFolderInsertIntoScope(pFolder, pCA);
|
|
_JumpIfError(hr, Ret, "BaseFolderInsertIntoScope");
|
|
|
|
// and create all template folders underneath
|
|
hr = CreateTemplateFolders(pCA);
|
|
_JumpIfError(hr, Ret, "CreateTemplateFolders");
|
|
}
|
|
else
|
|
{
|
|
// no need to do anything, ca is already known & inserted into scope
|
|
}
|
|
}
|
|
|
|
|
|
// BOGDANT
|
|
|
|
// Task #3
|
|
// for each CA, offer to do any one-time per-CA upgrades
|
|
for (dwKnownCAs=0; dwKnownCAs<(DWORD)m_pCertMachine->m_CAList.GetSize(); dwKnownCAs++)
|
|
{
|
|
CertSvrCA* pCA;
|
|
|
|
pCA = m_pCertMachine->GetCaAtPos(dwKnownCAs);
|
|
if (NULL == pCA)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, Ret, "m_pCertMachine->GetCaAtPos(iCAPos)");
|
|
}
|
|
|
|
if (pCA->FDoesSecurityNeedUpgrade())
|
|
{
|
|
bool fUserHasWriteAccess = false;
|
|
CString cstrMsg, cstrTitle;
|
|
cstrMsg.LoadString(IDS_W2K_SECURITY_UPGRADE_DESCR);
|
|
cstrTitle.LoadString(IDS_W2K_UPGRADE_DETECTED_TITLE);
|
|
|
|
hr = CurrentUserCanInstallCA(fUserHasWriteAccess);
|
|
_JumpIfError(hr, Ret, "IsUserDomainAdministrator");
|
|
|
|
if (fUserHasWriteAccess)
|
|
{
|
|
// ask to upgrade security
|
|
|
|
// confirm this action
|
|
CString cstrTmp;
|
|
cstrTmp.LoadString(IDS_CONFIRM_W2K_SECURITY_UPGRADE);
|
|
cstrMsg += cstrTmp;
|
|
|
|
int iRet;
|
|
if ((S_OK == m_pConsole->MessageBox(cstrMsg, cstrTitle, MB_YESNO, &iRet)) &&
|
|
(iRet == IDYES))
|
|
{
|
|
// do stuff
|
|
hr = pCA->FixEnrollmentObject();
|
|
_JumpIfError(hr, error, "FixEnrollmentObject");
|
|
|
|
hr = AddCAMachineToCertPublishers();
|
|
_JumpIfError(hr, error, "AddCAMachineToCertPublishers");
|
|
|
|
if(pCA->FIsAdvancedServer())
|
|
{
|
|
hr = AddCAMachineToPreWin2kGroup();
|
|
_JumpIfError(hr, error, "AddCAMachineToPreWin2kGroup");
|
|
}
|
|
|
|
if(RestartService(hwndMain, pCA->m_pParentMachine))
|
|
m_pConsole->UpdateAllViews(
|
|
lpDataObject,
|
|
0,
|
|
0);
|
|
|
|
error:
|
|
if (hr != S_OK)
|
|
DisplayGenericCertSrvError(m_pConsole, hr);
|
|
else
|
|
{
|
|
hr = pCA->CleanSetupStatusBits(
|
|
SETUP_W2K_SECURITY_NOT_UPGRADED_FLAG);
|
|
_PrintIfError(hr,
|
|
"Failed to clear SETUP_W2K_SECURITY_NOT_UPGRADED_FLAG setup flag");
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// just warn
|
|
CString cstrTmp;
|
|
cstrTmp.LoadString(IDS_BLOCK_W2K_SECURITY_UPGRADE);
|
|
cstrMsg += cstrTmp;
|
|
|
|
m_pConsole->MessageBoxW(cstrMsg, cstrTitle, MB_OK, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Ret:
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CComponentDataImpl::BaseFolderInsertIntoScope(CFolder* pFolder, CertSvrCA* pCA)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
int nImage;
|
|
|
|
HSCOPEITEM pParent = m_pStaticRoot; // we'll always be initialized by this time if parent exists
|
|
ASSERT(m_pStaticRoot);
|
|
if (NULL == m_pStaticRoot)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, Ret, "m_pStaticRoot");
|
|
}
|
|
|
|
if ((NULL == pFolder) || (NULL == pCA))
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, Ret, "NULL ptr");
|
|
}
|
|
|
|
|
|
if (pCA->m_strCommonName.IsEmpty())
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, Ret, "m_strCommonName");
|
|
}
|
|
|
|
if (m_pCertMachine->IsCertSvrServiceRunning())
|
|
nImage = IMGINDEX_CERTSVR_RUNNING;
|
|
else
|
|
nImage = IMGINDEX_CERTSVR_STOPPED;
|
|
|
|
pFolder->SetScopeItemInformation(nImage, nImage);
|
|
pFolder->SetProperties(
|
|
pCA->m_strCommonName,
|
|
SCOPE_LEVEL_ITEM,
|
|
SERVER_INSTANCE,
|
|
TRUE);
|
|
|
|
pFolder->m_pCertCA = pCA; // fill this in as root
|
|
|
|
// Set the parent
|
|
pFolder->m_ScopeItem.mask |= SDI_PARENT;
|
|
pFolder->m_ScopeItem.relativeID = pParent;
|
|
|
|
// Set the folder as the cookie
|
|
pFolder->m_ScopeItem.mask |= SDI_PARAM;
|
|
pFolder->m_ScopeItem.lParam = reinterpret_cast<LPARAM>(pFolder);
|
|
pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder));
|
|
|
|
// insert SCOPE_LEVEL_ITEM into scope pane
|
|
m_pScope->InsertItem(&pFolder->m_ScopeItem);
|
|
|
|
|
|
// Note - On return, the ID member of 'm_ScopeItem'
|
|
// contains the handle to the newly inserted item!
|
|
ASSERT(pFolder->m_ScopeItem.ID != NULL);
|
|
Ret:
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CComponentDataImpl::CreateTemplateFolders(CertSvrCA* pCA)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
SetCertView();
|
|
|
|
// add all template folders under it
|
|
for (int iUnder=0; iUnder < ARRAYLEN(SvrFuncFolderData); iUnder++)
|
|
{
|
|
// skip alien if svr doesn't support
|
|
if ((iUnder==ENUM_FOLDER_ALIEN) && !pCA->FDoesServerAllowForeignCerts())
|
|
continue;
|
|
|
|
if ((iUnder==ENUM_FOLDER_CRLS) && g_fCertViewOnly)
|
|
continue;
|
|
|
|
CString cstrRsc;
|
|
cstrRsc.LoadString(SvrFuncFolderData[iUnder].iNameRscID);
|
|
|
|
CFolder* pFolder;
|
|
pFolder = new CFolder();
|
|
_JumpIfOutOfMemory(hr, Ret, pFolder);
|
|
|
|
pFolder->m_pCertCA = pCA;
|
|
pFolder->SetScopeItemInformation(IMGINDEX_FOLDER, IMGINDEX_FOLDER_OPEN);
|
|
pFolder->SetProperties(
|
|
cstrRsc,
|
|
CA_LEVEL_ITEM,
|
|
SvrFuncFolderData[iUnder].type,
|
|
FALSE);
|
|
|
|
m_scopeItemList.AddTail(pFolder);
|
|
}
|
|
|
|
Ret:
|
|
return hr;
|
|
}
|
|
|
|
|
|
void CComponentDataImpl::EnumerateScopePane(LPDATAOBJECT lpDataObject, HSCOPEITEM pParent)
|
|
{
|
|
ASSERT(m_pScope != NULL); // make sure we QI'ed for the interface
|
|
ASSERT(lpDataObject != NULL);
|
|
|
|
INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
|
|
if (pInternal == NULL)
|
|
return;
|
|
|
|
MMC_COOKIE cookie = pInternal->m_cookie;
|
|
|
|
FREE_DATA(pInternal);
|
|
|
|
// Enumerate the scope pane
|
|
// return the folder object that represents the cookie
|
|
// Note - for large list, use dictionary
|
|
CFolder* pStatic = FindObject(cookie);
|
|
if (pStatic)
|
|
ASSERT(!pStatic->IsEnumerated());
|
|
|
|
if (NULL == cookie)
|
|
{
|
|
if (!m_fScopeAlreadyEnumerated) // if base node and we've never inserted nodes
|
|
{
|
|
// TASK: expand machine node
|
|
|
|
// Note - Each cookie in the scope pane represents a folder.
|
|
// Cache the HSCOPEITEM of the static root.
|
|
ASSERT(pParent != NULL);
|
|
m_pStaticRoot = pParent; // add/remove: EXPAND case
|
|
|
|
// synch folder list if asking to expand machine node
|
|
// SyncDisplayedCAList adds all necessary folders
|
|
HRESULT hr = SynchDisplayedCAList(lpDataObject);
|
|
if (hr != S_OK)
|
|
{
|
|
HWND hwnd;
|
|
DWORD dwErr2 = m_pConsole->GetMainWindow(&hwnd);
|
|
ASSERT(dwErr2 == ERROR_SUCCESS);
|
|
if (dwErr2 != ERROR_SUCCESS)
|
|
hwnd = NULL; // should work
|
|
|
|
if (((HRESULT)RPC_S_SERVER_UNAVAILABLE) == hr)
|
|
{
|
|
DisplayCertSrvErrorWithContext(hwnd, hr, IDS_SERVER_UNAVAILABLE);
|
|
}
|
|
else if(HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION)==hr ||
|
|
((HRESULT)ERROR_OLD_WIN_VERSION)==hr)
|
|
{
|
|
DisplayCertSrvErrorWithContext(hwnd, hr, IDS_OLD_CA);
|
|
}
|
|
else
|
|
{
|
|
DisplayCertSrvErrorWithContext(hwnd, hr, IDS_CANNOT_OPEN_CERT_SERVICES);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// TASK: expand non-machine node
|
|
if (NULL == pStatic)
|
|
return;
|
|
|
|
switch(pStatic->GetType())
|
|
{
|
|
case SERVER_INSTANCE:
|
|
{
|
|
// TASK: expand CA instance node
|
|
|
|
POSITION pos = m_scopeItemList.GetHeadPosition();
|
|
while(pos)
|
|
{
|
|
CFolder* pFolder;
|
|
pFolder = m_scopeItemList.GetNext(pos);
|
|
if (pFolder==NULL)
|
|
break;
|
|
|
|
// only expand folders that belong under the SERVER_INSTANCE
|
|
if (pFolder->m_itemType != CA_LEVEL_ITEM)
|
|
continue;
|
|
|
|
// and only those under the correct CA
|
|
if (pFolder->m_pCertCA != pStatic->m_pCertCA)
|
|
continue;
|
|
|
|
// Set the parent
|
|
pFolder->m_ScopeItem.relativeID = pParent;
|
|
|
|
// Set the folder as the cookie
|
|
pFolder->m_ScopeItem.mask |= SDI_PARAM;
|
|
pFolder->m_ScopeItem.lParam = reinterpret_cast<LPARAM>(pFolder);
|
|
pFolder->SetCookie(reinterpret_cast<MMC_COOKIE>(pFolder));
|
|
m_pScope->InsertItem(&pFolder->m_ScopeItem);
|
|
|
|
// Note - On return, the ID member of 'm_ScopeItem'
|
|
// contains the handle to the newly inserted item!
|
|
ASSERT(pFolder->m_ScopeItem.ID != NULL);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
// TASK: expand nodes with no folders under them
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
CFolder* CComponentDataImpl::FindObject(MMC_COOKIE cookie)
|
|
{
|
|
CFolder* pFolder = NULL;
|
|
POSITION pos = m_scopeItemList.GetHeadPosition();
|
|
|
|
while(pos)
|
|
{
|
|
pFolder = m_scopeItemList.GetNext(pos);
|
|
|
|
if (*pFolder == cookie)
|
|
return pFolder;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
STDMETHODIMP CComponentDataImpl::GetDisplayInfo(SCOPEDATAITEM* pScopeDataItem)
|
|
{
|
|
ASSERT(pScopeDataItem != NULL);
|
|
if (pScopeDataItem == NULL)
|
|
return E_POINTER;
|
|
|
|
CFolder* pFolder = reinterpret_cast<CFolder*>(pScopeDataItem->lParam);
|
|
|
|
if ((pScopeDataItem->mask & SDI_STR) && (pFolder != NULL))
|
|
{
|
|
pScopeDataItem->displayname = pFolder->m_pszName;
|
|
}
|
|
|
|
// I was told by Ravi Rudrappa that these notifications
|
|
// would never be given. If it is given, move UpdateScopeIcons()
|
|
// functionality here!!!
|
|
ASSERT(0 == (pScopeDataItem->mask & SDI_IMAGE));
|
|
ASSERT(0 == (pScopeDataItem->mask & SDI_OPENIMAGE));
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CComponentDataImpl::CompareObjects(LPDATAOBJECT lpDataObjectA, LPDATAOBJECT lpDataObjectB)
|
|
{
|
|
if (lpDataObjectA == NULL || lpDataObjectB == NULL)
|
|
return E_POINTER;
|
|
|
|
HRESULT hr = S_FALSE;
|
|
|
|
// Make sure both data object are mine
|
|
INTERNAL* pA = ExtractInternalFormat(lpDataObjectA);
|
|
INTERNAL* pB = ExtractInternalFormat(lpDataObjectA);
|
|
|
|
if (pA != NULL && pB != NULL)
|
|
hr = (*pA == *pB) ? S_OK : S_FALSE;
|
|
|
|
|
|
FREE_DATA(pA);
|
|
FREE_DATA(pB);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IExtendPropertySheet Implementation
|
|
|
|
STDMETHODIMP CComponentDataImpl::CreatePropertyPages(LPPROPERTYSHEETCALLBACK lpProvider,
|
|
LONG_PTR handle,
|
|
LPDATAOBJECT lpIDataObject)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Look at the data object and determine if this an extension or a primary
|
|
ASSERT(lpIDataObject != NULL);
|
|
|
|
PropertyPage* pBasePage;
|
|
|
|
INTERNAL* pInternal = ExtractInternalFormat(lpIDataObject);
|
|
if (pInternal == NULL)
|
|
return S_OK;
|
|
|
|
switch (pInternal->m_type)
|
|
{
|
|
case CCT_SNAPIN_MANAGER:
|
|
{
|
|
CChooseMachinePropPage* pPage = new CChooseMachinePropPage();
|
|
_JumpIfOutOfMemory(hr, Ret, pPage);
|
|
|
|
// this alloc might have failed (should be in ctor)
|
|
_JumpIfOutOfMemory(hr, Ret, m_pCertMachine);
|
|
|
|
pPage->SetCaption(IDS_SCOPE_MYCOMPUTER);
|
|
|
|
// Initialize state of object
|
|
pPage->InitMachineName(NULL);
|
|
|
|
// point to our member vars
|
|
pPage->SetOutputBuffers(
|
|
&m_pCertMachine->m_strMachineNamePersist,
|
|
&m_pCertMachine->m_strMachineName,
|
|
&m_dwFlagsPersist);
|
|
|
|
pBasePage = pPage;
|
|
|
|
// Object gets deleted when the page is destroyed
|
|
ASSERT(lpProvider != NULL);
|
|
|
|
ASSERT(pBasePage != NULL);
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
|
|
lpProvider->AddPage(hPage);
|
|
|
|
break;
|
|
}
|
|
case CCT_SCOPE:
|
|
{
|
|
// if not base scope
|
|
if (0 != pInternal->m_cookie)
|
|
{
|
|
// switch on folder type
|
|
CFolder* pFolder = GetParentFolder(pInternal);
|
|
ASSERT(pFolder != NULL);
|
|
if (pFolder == NULL)
|
|
{
|
|
hr = E_POINTER;
|
|
_JumpError(hr, Ret, "GetParentFolder");
|
|
}
|
|
|
|
switch(pFolder->m_type)
|
|
{
|
|
case SERVER_INSTANCE:
|
|
{
|
|
//1
|
|
CSvrSettingsGeneralPage* pControlPage = new CSvrSettingsGeneralPage(pFolder->m_pCertCA);
|
|
if (pControlPage != NULL)
|
|
{
|
|
pControlPage->m_hConsoleHandle = handle; // only do this on primary
|
|
pBasePage = pControlPage;
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
|
|
//2
|
|
{
|
|
CSvrSettingsPolicyPage* pPage = new CSvrSettingsPolicyPage(pControlPage);
|
|
if (pPage != NULL)
|
|
{
|
|
pBasePage = pPage;
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
}
|
|
|
|
//3
|
|
{
|
|
CSvrSettingsExitPage* pPage = new CSvrSettingsExitPage(pControlPage);
|
|
if (pPage != NULL)
|
|
{
|
|
pBasePage = pPage;
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
}
|
|
|
|
//4
|
|
{
|
|
// Centralized extensions page available only in whistler
|
|
if (pFolder->m_pCertCA->m_pParentMachine->FIsWhistlerMachine())
|
|
{
|
|
|
|
CSvrSettingsExtensionPage* pPage = new CSvrSettingsExtensionPage(pFolder->m_pCertCA, pControlPage);
|
|
if (pPage != NULL)
|
|
{
|
|
pBasePage = pPage;
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
}
|
|
}
|
|
|
|
//5
|
|
{
|
|
CSvrSettingsStoragePage* pPage = new CSvrSettingsStoragePage(pControlPage);
|
|
if (pPage != NULL)
|
|
{
|
|
pBasePage = pPage;
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
}
|
|
//6
|
|
{
|
|
// restricted officers available only in whistler advanced server
|
|
if(pFolder->m_pCertCA->m_pParentMachine->FIsWhistlerMachine() && pFolder->m_pCertCA->FIsAdvancedServer())
|
|
{
|
|
CSvrSettingsCertManagersPage* pPage =
|
|
new CSvrSettingsCertManagersPage(pControlPage);
|
|
if (pPage != NULL)
|
|
{
|
|
pBasePage = pPage;
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
}
|
|
}
|
|
//7
|
|
{
|
|
// audit available only in whistler
|
|
if(pFolder->m_pCertCA->m_pParentMachine->FIsWhistlerMachine())
|
|
{
|
|
CSvrSettingsAuditFilterPage* pPage =
|
|
new CSvrSettingsAuditFilterPage(pControlPage);
|
|
if (pPage != NULL)
|
|
{
|
|
pBasePage = pPage;
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
}
|
|
}
|
|
//8
|
|
{
|
|
// audit available only in whistler advanced server, enterprise
|
|
if(pFolder->m_pCertCA->m_pParentMachine->FIsWhistlerMachine() && pFolder->m_pCertCA->FIsAdvancedServer() && IsEnterpriseCA(pFolder->m_pCertCA->GetCAType()) )
|
|
{
|
|
CSvrSettingsKRAPage* pPage = new CSvrSettingsKRAPage(
|
|
pFolder->m_pCertCA,
|
|
pControlPage);
|
|
if (pPage != NULL)
|
|
{
|
|
pBasePage = pPage;
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
}
|
|
}
|
|
//9
|
|
{
|
|
// if error, don't display this page
|
|
LPSECURITYINFO pCASecurity = NULL;
|
|
|
|
hr = CreateCASecurityInfo(pFolder->m_pCertCA, &pCASecurity);
|
|
_PrintIfError(hr, "CreateCASecurityInfo");
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
// allow proppages to clean up security info
|
|
pControlPage->SetAllocedSecurityInfo(pCASecurity);
|
|
|
|
HPROPSHEETPAGE hPage = CreateSecurityPage(pCASecurity);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
}
|
|
|
|
hr = S_OK;
|
|
break;
|
|
}// end case SERVER_INSTANCE
|
|
case SERVERFUNC_CRL_PUBLICATION:
|
|
{
|
|
//1
|
|
CCRLPropPage* pControlPage = new CCRLPropPage(pFolder->m_pCertCA);
|
|
if (pControlPage != NULL)
|
|
{
|
|
pControlPage->m_hConsoleHandle = handle;
|
|
pBasePage = pControlPage;
|
|
|
|
// Object gets deleted when the page is destroyed
|
|
ASSERT(lpProvider != NULL);
|
|
|
|
ASSERT(pBasePage != NULL);
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
//2
|
|
{
|
|
CCRLViewPage* pPage = new CCRLViewPage(pControlPage);
|
|
if (pPage != NULL)
|
|
{
|
|
pBasePage = pPage;
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pBasePage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
hr = myHLastError();
|
|
_JumpError(hr, Ret, "CreatePropertySheetPage");
|
|
}
|
|
|
|
lpProvider->AddPage(hPage);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
} // end switch(pFolder->m_type)
|
|
|
|
} // end switch(scope)
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Ret:
|
|
FREE_DATA(pInternal);
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CComponentDataImpl::QueryPagesFor(LPDATAOBJECT lpDataObject)
|
|
{
|
|
BOOL bResult = FALSE;
|
|
|
|
INTERNAL* pInternal = ExtractInternalFormat(lpDataObject);
|
|
if (NULL == pInternal)
|
|
return S_FALSE;
|
|
|
|
if (pInternal->m_cookie != NULL)
|
|
{
|
|
CFolder* pFolder = GetParentFolder(pInternal);
|
|
if (pFolder != NULL)
|
|
{
|
|
switch(pFolder->m_type)
|
|
{
|
|
case SERVER_INSTANCE:
|
|
case SERVERFUNC_CRL_PUBLICATION:
|
|
bResult = TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// say YES to snapin manager
|
|
if (CCT_SNAPIN_MANAGER == pInternal->m_type)
|
|
bResult = TRUE;
|
|
}
|
|
|
|
FREE_DATA(pInternal);
|
|
return (bResult) ? S_OK : S_FALSE;
|
|
|
|
// Look at the data object and see if it an item in the scope pane
|
|
// return IsScopePaneNode(lpDataObject) ? S_OK : S_FALSE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// IExtendContextMenu implementation
|
|
//
|
|
STDMETHODIMP CComponentDataImpl::AddMenuItems(LPDATAOBJECT pDataObject,
|
|
LPCONTEXTMENUCALLBACK pContextMenuCallback,
|
|
LONG *pInsertionAllowed)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TASKITEM* pm = NULL;
|
|
|
|
// Note - snap-ins need to look at the data object and determine
|
|
// in what context, menu items need to be added. They must also
|
|
// observe the insertion allowed flags to see what items can be
|
|
// added.
|
|
|
|
|
|
INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
|
|
if (NULL == pInternal)
|
|
return S_OK;
|
|
|
|
BOOL fResultItem = (pInternal->m_type == CCT_RESULT);
|
|
BOOL fMultiSel = IsMMCMultiSelectDataObject(pDataObject);
|
|
|
|
CFolder* pFolder;
|
|
if (!fResultItem)
|
|
pFolder = GetParentFolder(pInternal);
|
|
else
|
|
{
|
|
// GetParent might work, but doesn't for virtual items...
|
|
ASSERT(m_pCurSelFolder);
|
|
pFolder = m_pCurSelFolder;
|
|
}
|
|
|
|
FOLDER_TYPES folderType = NONE;
|
|
if (pFolder == NULL)
|
|
folderType = MACHINE_INSTANCE;
|
|
else
|
|
folderType = pFolder->GetType();
|
|
|
|
// Loop through and add each of the "topItems"
|
|
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TOP)
|
|
{
|
|
// don't do for multisel
|
|
if (!fMultiSel)
|
|
{
|
|
pm = (TASKITEM*) LocalAlloc(LMEM_FIXED, sizeof(topItems));
|
|
_JumpIfAllocFailed(pm, Ret);
|
|
|
|
memcpy(pm, topItems, sizeof(topItems));
|
|
|
|
// Disable retarget if we haven't yet clicked on the static root. Otherwise,
|
|
// DisplayProperRootNodeName handles load-from-file
|
|
// MMCN_EXPAND handles add/remove and expanded
|
|
pm[ENUM_RETARGET_SNAPIN].myitem.item.fFlags = m_pStaticRoot ? MFS_ENABLED : MFS_GRAYED;
|
|
|
|
for (TASKITEM* pm1=pm; pm1->myitem.item.strName; pm1++)
|
|
{
|
|
// does it match scope/result type?
|
|
if (fResultItem != ((pm1->dwFlags & TASKITEM_FLAG_RESULTITEM) != 0) )
|
|
continue;
|
|
|
|
// does it match area it should be in?
|
|
// for each task, insert if matches the current folder
|
|
if ((pm1->type != SERVERFUNC_ALL_FOLDERS) && (folderType != pm1->type))
|
|
continue;
|
|
|
|
hr = pContextMenuCallback->AddItem(&pm1->myitem.item);
|
|
_JumpIfError(hr, Ret, "AddItem");
|
|
}
|
|
|
|
LocalFree(pm);
|
|
pm = NULL;
|
|
}
|
|
}
|
|
|
|
// this is the end of the line if folder nonexistant
|
|
if (pFolder == NULL)
|
|
goto Ret;
|
|
|
|
// Loop through and add each of the view items
|
|
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_VIEW)
|
|
{
|
|
}
|
|
|
|
if (*pInsertionAllowed & CCM_INSERTIONALLOWED_TASK)
|
|
{
|
|
// ptr to tasks
|
|
pm = (TASKITEM*) LocalAlloc(LMEM_FIXED, sizeof(taskItems));
|
|
_JumpIfAllocFailed(pm, Ret);
|
|
|
|
memcpy(pm, taskItems, sizeof(taskItems));
|
|
|
|
BOOL fRunningLocally = m_pCertMachine->IsLocalMachine();
|
|
BOOL fSvcRunning = m_pCertMachine->IsCertSvrServiceRunning();
|
|
if ( IsAllowedStartStop(pFolder, m_pCertMachine) )
|
|
AddStartStopTasks(pFolder, pContextMenuCallback, fSvcRunning);
|
|
|
|
// only fixup on server instance
|
|
if (folderType == SERVER_INSTANCE)
|
|
{
|
|
// fixup entries depending on install type/state
|
|
if (IsRootCA(pFolder->GetCA()->GetCAType())) // root ca?
|
|
{
|
|
pm[ENUM_TASK_INSTALL].myitem.item.fFlags = MFS_HIDDEN; // not available
|
|
pm[ENUM_TASK_REQUEST].myitem.item.fFlags = MFS_HIDDEN; // not available
|
|
pm[ENUM_TASK_ROLLOVER].myitem.item.fFlags = MFS_ENABLED;
|
|
}
|
|
else // sub ca
|
|
{
|
|
if (pFolder->GetCA()->FIsRequestOutstanding())
|
|
pm[ENUM_TASK_INSTALL].myitem.item.fFlags = MFS_ENABLED;
|
|
else
|
|
pm[ENUM_TASK_INSTALL].myitem.item.fFlags = MFS_HIDDEN;
|
|
|
|
if (pFolder->GetCA()->FIsIncompleteInstallation()) // incomplete
|
|
{
|
|
pm[ENUM_TASK_REQUEST].myitem.item.fFlags = MFS_ENABLED;
|
|
pm[ENUM_TASK_ROLLOVER].myitem.item.fFlags = MFS_HIDDEN; // not available
|
|
}
|
|
else // complete install
|
|
{
|
|
pm[ENUM_TASK_REQUEST].myitem.item.fFlags = MFS_HIDDEN; // not available
|
|
pm[ENUM_TASK_ROLLOVER].myitem.item.fFlags = MFS_ENABLED;
|
|
}
|
|
}
|
|
|
|
static bool fIsMember;
|
|
static bool fIsMemberChecked = false;
|
|
|
|
if(!fIsMemberChecked)
|
|
{
|
|
hr = myIsCurrentUserBuiltinAdmin(&fIsMember);
|
|
if(S_OK==hr)
|
|
{
|
|
fIsMemberChecked = true;
|
|
}
|
|
}
|
|
|
|
// Hide renew/install CA cert item if not local admin or if we
|
|
// failed to figure it out. Ignore the error.
|
|
|
|
// !!! Post Whistler when we get renew CA cert to work for non
|
|
// local admin we should change the code here to hide the item
|
|
// based on the role that is allowed to do it.
|
|
if(S_OK != hr || !fIsMember)
|
|
{
|
|
pm[ENUM_TASK_ROLLOVER].myitem.item.fFlags = MFS_HIDDEN;
|
|
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
|
|
// don't allow properties on multisel
|
|
pm[ENUM_TASK_ATTREXTS_CRL].myitem.item.fFlags = fMultiSel ? MFS_HIDDEN : MFS_ENABLED;
|
|
pm[ENUM_TASK_ATTREXTS_ISS].myitem.item.fFlags = fMultiSel ? MFS_HIDDEN : MFS_ENABLED;
|
|
pm[ENUM_TASK_ATTREXTS_PEND].myitem.item.fFlags = fMultiSel ? MFS_HIDDEN : MFS_ENABLED;
|
|
pm[ENUM_TASK_ATTREXTS_FAIL].myitem.item.fFlags = fMultiSel ? MFS_HIDDEN : MFS_ENABLED;
|
|
|
|
// disable based on roles
|
|
for(TASKITEM* pm1=pm; pm1->myitem.item.strName; pm1++)
|
|
{
|
|
if((pm1->myitem.item.fFlags == MFS_ENABLED) &&
|
|
!((pm1->myitem.dwRoles) & (pFolder->m_pCertCA->GetMyRoles())))
|
|
pm1->myitem.item.fFlags = MFS_GRAYED;
|
|
}
|
|
|
|
// insert all other tasks per folder
|
|
for (TASKITEM* pm1=pm; pm1->myitem.item.strName; pm1++)
|
|
{
|
|
// does it match scope/result type?
|
|
if (fResultItem != ((pm1->dwFlags & TASKITEM_FLAG_RESULTITEM) != 0))
|
|
continue;
|
|
|
|
// are we remote, and is it marked localonly? (not yes/no like other tests here)
|
|
if (((pm1->dwFlags & TASKITEM_FLAG_LOCALONLY)) && (!fRunningLocally))
|
|
continue;
|
|
|
|
// does it match area it should be in?
|
|
// for each task, insert if matches the current folder
|
|
if ((pm1->type != SERVERFUNC_ALL_FOLDERS) && (folderType != pm1->type))
|
|
continue;
|
|
|
|
// is this task supposed to be hidden?
|
|
if (MFS_HIDDEN == pm1->myitem.item.fFlags)
|
|
continue;
|
|
|
|
hr = pContextMenuCallback->AddItem(&pm1->myitem.item);
|
|
_JumpIfError(hr, Ret, "AddItem");
|
|
}
|
|
|
|
LocalFree(pm);
|
|
pm = NULL;
|
|
}
|
|
|
|
Ret:
|
|
LOCAL_FREE(pm);
|
|
FREE_DATA(pInternal);
|
|
return hr;
|
|
}
|
|
|
|
|
|
BOOL CComponentDataImpl::AddStartStopTasks(
|
|
CFolder *pFolder,
|
|
LPCONTEXTMENUCALLBACK pContextMenuCallback,
|
|
BOOL fSvcRunning)
|
|
{
|
|
HRESULT hr;
|
|
MY_CONTEXTMENUITEM* pm = taskStartStop;
|
|
|
|
bool fUserCanStart = (pm[ENUM_TASK_START].dwRoles) & (pFolder->m_pCertCA->GetMyRoles())?
|
|
true:false;
|
|
bool fUserCanStop = (pm[ENUM_TASK_STOP].dwRoles) & (pFolder->m_pCertCA->GetMyRoles())?
|
|
true:false;
|
|
|
|
pm[ENUM_TASK_START].item.fFlags =
|
|
(fSvcRunning || !fUserCanStart)?
|
|
MF_GRAYED : MF_ENABLED;
|
|
hr = pContextMenuCallback->AddItem(&pm[ENUM_TASK_START].item);
|
|
_JumpIfError(hr, Ret, "AddItem");
|
|
|
|
pm[ENUM_TASK_STOP].item.fFlags =
|
|
(fSvcRunning && fUserCanStop)?
|
|
MF_ENABLED : MF_GRAYED;
|
|
hr = pContextMenuCallback->AddItem(&pm[ENUM_TASK_STOP].item);
|
|
_JumpIfError(hr, Ret, "AddItem");
|
|
|
|
Ret:
|
|
return (hr == ERROR_SUCCESS);
|
|
}
|
|
|
|
STDMETHODIMP CComponentDataImpl::Command(LONG nCommandID, LPDATAOBJECT pDataObject)
|
|
{
|
|
// Note - snap-ins need to look at the data object and determine
|
|
// in what context the command is being called.
|
|
HRESULT dwErr = S_OK;
|
|
|
|
INTERNAL* pInternal = ExtractInternalFormat(pDataObject);
|
|
ASSERT(pInternal);
|
|
if (NULL == pInternal)
|
|
return S_OK;
|
|
|
|
BOOL fMustRefresh = FALSE;
|
|
BOOL fPopup = TRUE;
|
|
|
|
CFolder* pFolder = GetParentFolder(pInternal);
|
|
|
|
// Handle each of the commands.
|
|
switch (nCommandID)
|
|
{
|
|
case IDC_STOPSERVER:
|
|
{
|
|
HWND hwndMain;
|
|
dwErr = m_pConsole->GetMainWindow(&hwndMain);
|
|
|
|
if (dwErr == S_OK)
|
|
dwErr = m_pCertMachine->CertSvrStartStopService(hwndMain, FALSE);
|
|
|
|
|
|
// notify views: refresh service toolbar buttons
|
|
fMustRefresh = TRUE;
|
|
break;
|
|
}
|
|
case IDC_STARTSERVER:
|
|
{
|
|
HWND hwndMain;
|
|
dwErr = m_pConsole->GetMainWindow(&hwndMain);
|
|
|
|
if (S_OK == dwErr)
|
|
dwErr = m_pCertMachine->CertSvrStartStopService(hwndMain, TRUE);
|
|
|
|
|
|
// check for ERROR_INSTALL_SUSPEND or HR(ERROR_INSTALL_SUSPEND)!!
|
|
if ((((HRESULT)ERROR_INSTALL_SUSPEND) == dwErr) || (HRESULT_FROM_WIN32(ERROR_INSTALL_SUSPEND) == dwErr))
|
|
{
|
|
CString cstrMsg, cstrTitle;
|
|
cstrMsg.LoadString(IDS_COMPLETE_HIERARCHY_INSTALL_MSG);
|
|
cstrTitle.LoadString(IDS_MSG_TITLE);
|
|
|
|
CertSvrCA* pCA;
|
|
|
|
for (DWORD i=0; i<m_pCertMachine->GetCaCount(); i++)
|
|
{
|
|
pCA = m_pCertMachine->GetCaAtPos(i);
|
|
|
|
// search for any/all incomplete hierarchies
|
|
if (pCA->FIsIncompleteInstallation())
|
|
{
|
|
int iRet;
|
|
WCHAR sz[512];
|
|
wsprintf(sz, (LPCWSTR)cstrMsg, (LPCWSTR)pCA->m_strCommonName, (LPCWSTR)pCA->m_strServer);
|
|
|
|
m_pConsole->MessageBox(
|
|
sz,
|
|
cstrTitle,
|
|
MB_YESNO,
|
|
&iRet);
|
|
|
|
if (IDYES != iRet)
|
|
break;
|
|
|
|
dwErr = CARequestInstallHierarchyWizard(pCA, hwndMain, FALSE, FALSE);
|
|
if (dwErr != S_OK)
|
|
{
|
|
// fPopup = FALSE;// sometimes no notification -- better to have 2 dlgs
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// my responsibility to start the service again
|
|
if (dwErr == S_OK)
|
|
dwErr = m_pCertMachine->CertSvrStartStopService(hwndMain, TRUE);
|
|
}
|
|
else if ((((HRESULT)ERROR_FILE_NOT_FOUND) == dwErr) || (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == dwErr))
|
|
{
|
|
// file not found error could be related to policy module
|
|
WCHAR const *pwsz = myGetErrorMessageText(dwErr, TRUE);
|
|
CString cstrFullMessage = pwsz;
|
|
if (NULL != pwsz)
|
|
{
|
|
LocalFree(const_cast<WCHAR *>(pwsz));
|
|
}
|
|
cstrFullMessage += L"\n\n";
|
|
|
|
CString cstrHelpfulMessage;
|
|
cstrHelpfulMessage.LoadString(IDS_POSSIBLEERROR_NO_POLICY_MODULE);
|
|
cstrFullMessage += cstrHelpfulMessage;
|
|
|
|
CString cstrTitle;
|
|
cstrTitle.LoadString(IDS_MSG_TITLE);
|
|
|
|
int iRet;
|
|
m_pConsole->MessageBox(
|
|
cstrFullMessage,
|
|
cstrTitle,
|
|
MB_OK,
|
|
&iRet);
|
|
|
|
dwErr = ERROR_SUCCESS;
|
|
}
|
|
|
|
// notify views: refresh service toolbar buttons
|
|
fMustRefresh = TRUE;
|
|
break;
|
|
}
|
|
case IDC_PUBLISHCRL:
|
|
{
|
|
ASSERT(pInternal->m_type != CCT_RESULT);
|
|
if (NULL == pFolder)
|
|
break;
|
|
|
|
HWND hwnd;
|
|
dwErr = m_pConsole->GetMainWindow(&hwnd);
|
|
ASSERT(dwErr == ERROR_SUCCESS);
|
|
if (dwErr != ERROR_SUCCESS)
|
|
hwnd = NULL; // should work
|
|
|
|
dwErr = PublishCRLWizard(pFolder->m_pCertCA, hwnd);
|
|
break;
|
|
|
|
// no refresh
|
|
}
|
|
case IDC_BACKUP_CA:
|
|
{
|
|
HWND hwnd;
|
|
dwErr = m_pConsole->GetMainWindow(&hwnd);
|
|
// NULL should work
|
|
if (S_OK != dwErr)
|
|
hwnd = NULL;
|
|
|
|
if (NULL == pFolder)
|
|
break;
|
|
|
|
dwErr = CABackupWizard(pFolder->GetCA(), hwnd);
|
|
|
|
// refresh the status of the CA -- may have started it during this operation
|
|
fMustRefresh = TRUE;
|
|
break;
|
|
}
|
|
case IDC_RESTORE_CA:
|
|
{
|
|
HWND hwnd;
|
|
dwErr = m_pConsole->GetMainWindow(&hwnd);
|
|
// NULL should work
|
|
if (S_OK != dwErr)
|
|
hwnd = NULL;
|
|
|
|
if (NULL == pFolder)
|
|
break;
|
|
|
|
dwErr = CARestoreWizard(pFolder->GetCA(), hwnd);
|
|
|
|
if ((myJetHResult(JET_errDatabaseDuplicate) == dwErr) ||
|
|
HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) == dwErr)
|
|
{
|
|
DisplayCertSrvErrorWithContext(hwnd, dwErr, IDS_ERR_RESTORE_OVER_EXISTING_DATABASE);
|
|
dwErr = S_OK;
|
|
}
|
|
|
|
if (HRESULT_FROM_WIN32(ERROR_DIRECTORY) == dwErr)
|
|
{
|
|
DisplayCertSrvErrorWithContext(hwnd, dwErr, IDS_ERR_RESTORE_OUT_OF_ORDER);
|
|
dwErr = S_OK;
|
|
}
|
|
|
|
// refresh after restore
|
|
fMustRefresh = TRUE;
|
|
|
|
break;
|
|
}
|
|
case IDC_SUBMITREQUEST:
|
|
{
|
|
HWND hwnd;
|
|
WCHAR szCmdLine[MAX_PATH], szSysDir[MAX_PATH];
|
|
|
|
STARTUPINFO sStartup;
|
|
ZeroMemory(&sStartup, sizeof(sStartup));
|
|
PROCESS_INFORMATION sProcess;
|
|
ZeroMemory(&sProcess, sizeof(sProcess));
|
|
sStartup.cb = sizeof(sStartup);
|
|
|
|
dwErr = m_pConsole->GetMainWindow(&hwnd);
|
|
// NULL should work
|
|
if (S_OK != dwErr)
|
|
hwnd = NULL;
|
|
|
|
if (NULL == pFolder)
|
|
break;
|
|
|
|
|
|
if (0 == GetSystemDirectory(szSysDir, ARRAYSIZE(szSysDir)))
|
|
{
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// exec "certutil -dump szReqFile szTempFile"
|
|
wsprintf(szCmdLine, L"%ws\\certreq.exe -config \"%ws\"", szSysDir, (LPCWSTR)pFolder->GetCA()->m_strConfig);
|
|
wcscat(szSysDir, L"\\certreq.exe");
|
|
|
|
if (!CreateProcess(
|
|
szSysDir, // exe
|
|
szCmdLine, // full cmd line
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
CREATE_NO_WINDOW,
|
|
NULL,
|
|
NULL,
|
|
&sStartup,
|
|
&sProcess))
|
|
{
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
|
|
dwErr = S_OK;
|
|
break;
|
|
}
|
|
case IDC_INSTALL_CA:
|
|
case IDC_REQUEST_CA:
|
|
case IDC_ROLLOVER_CA:
|
|
{
|
|
HWND hwnd;
|
|
dwErr = m_pConsole->GetMainWindow(&hwnd);
|
|
// NULL should work
|
|
if (S_OK != dwErr)
|
|
hwnd = NULL;
|
|
|
|
if (NULL == pFolder)
|
|
{
|
|
dwErr = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
dwErr = CARequestInstallHierarchyWizard(pFolder->GetCA(), hwnd, (nCommandID==IDC_ROLLOVER_CA), TRUE);
|
|
if (S_OK != dwErr)
|
|
{
|
|
// low level lib had popup
|
|
// fPopup = FALSE; // sometimes no notification -- better to have 2 dlgs
|
|
}
|
|
|
|
// notify views: refresh service toolbar buttons
|
|
fMustRefresh = TRUE;
|
|
|
|
break;
|
|
}
|
|
case IDC_RETARGET_SNAPIN:
|
|
{
|
|
HWND hwnd;
|
|
dwErr = m_pConsole->GetMainWindow(&hwnd);
|
|
// NULL should work
|
|
if (S_OK != dwErr)
|
|
hwnd = NULL;
|
|
|
|
// this should be base folder ONLY
|
|
if(pFolder != NULL)
|
|
{
|
|
dwErr = E_POINTER;
|
|
break;
|
|
}
|
|
|
|
CString strMachineNamePersist, strMachineName;
|
|
CChooseMachinePropPage* pPage = new CChooseMachinePropPage(); // autodelete proppage -- don't delete
|
|
if (pPage == NULL)
|
|
{
|
|
dwErr = E_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
|
|
pPage->SetCaption(IDS_SCOPE_MYCOMPUTER);
|
|
|
|
// Initialize state of object
|
|
pPage->InitMachineName(NULL);
|
|
|
|
// populate UI
|
|
strMachineNamePersist = m_pCertMachine->m_strMachineNamePersist;
|
|
strMachineName = m_pCertMachine->m_strMachineName;
|
|
|
|
// point to our member vars
|
|
pPage->SetOutputBuffers(
|
|
&strMachineNamePersist,
|
|
&strMachineName,
|
|
&m_dwFlagsPersist);
|
|
|
|
ASSERT(pPage != NULL);
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(&pPage->m_psp);
|
|
if (hPage == NULL)
|
|
{
|
|
dwErr = E_UNEXPECTED;
|
|
break;
|
|
}
|
|
|
|
PROPSHEETHEADER sPsh;
|
|
ZeroMemory(&sPsh, sizeof(sPsh));
|
|
sPsh.dwSize = sizeof(sPsh);
|
|
sPsh.dwFlags = PSH_WIZARD;
|
|
sPsh.hwndParent = hwnd;
|
|
sPsh.hInstance = g_hInstance;
|
|
sPsh.nPages = 1;
|
|
sPsh.phpage = &hPage;
|
|
|
|
dwErr = (DWORD) PropertySheet(&sPsh);
|
|
if (dwErr == (HRESULT)-1)
|
|
{
|
|
// error
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
if (dwErr == (HRESULT)0)
|
|
{
|
|
// cancel
|
|
break;
|
|
}
|
|
|
|
// we've grabbed the user's choice by now, finish retargetting
|
|
CertSvrMachine* pOldMachine = m_pCertMachine;
|
|
m_pCertMachine = new CertSvrMachine;
|
|
if (NULL == m_pCertMachine)
|
|
{
|
|
m_pCertMachine = pOldMachine;
|
|
break; // bail!
|
|
}
|
|
|
|
// copy to machine object
|
|
m_pCertMachine->m_strMachineNamePersist = strMachineNamePersist;
|
|
m_pCertMachine->m_strMachineName = strMachineName;
|
|
|
|
dwErr = DisplayProperRootNodeName(m_pStaticRoot); // fix display
|
|
_PrintIfError(dwErr, "DisplayProperRootNodeName");
|
|
|
|
dwErr = SynchDisplayedCAList(pDataObject); // add/remove folders
|
|
_PrintIfError(dwErr, "SynchDisplayedCAList");
|
|
|
|
// after Synch, we remove old machine -- there are no references left to it
|
|
if (pOldMachine)
|
|
pOldMachine->Release();
|
|
|
|
fMustRefresh = TRUE; // update folder icons, descriptions
|
|
|
|
break;
|
|
}
|
|
default:
|
|
ASSERT(FALSE); // Unknown command!
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
FREE_DATA(pInternal);
|
|
|
|
if ((dwErr != ERROR_SUCCESS) &&
|
|
(dwErr != ERROR_CANCELLED) &&
|
|
(dwErr != HRESULT_FROM_WIN32(ERROR_CANCELLED)) &&
|
|
(dwErr != HRESULT_FROM_WIN32(ERROR_NOT_READY))
|
|
&& fPopup)
|
|
{
|
|
HWND hwnd;
|
|
DWORD dwErr2 = m_pConsole->GetMainWindow(&hwnd);
|
|
ASSERT(dwErr2 == ERROR_SUCCESS);
|
|
if (dwErr2 != ERROR_SUCCESS)
|
|
hwnd = NULL; // should work
|
|
|
|
if (((HRESULT)RPC_S_SERVER_UNAVAILABLE) == dwErr)
|
|
{
|
|
DisplayCertSrvErrorWithContext(hwnd, dwErr, IDS_SERVER_UNAVAILABLE);
|
|
}
|
|
else if(HRESULT_FROM_WIN32(ERROR_OLD_WIN_VERSION)==dwErr ||
|
|
((HRESULT)ERROR_OLD_WIN_VERSION)==dwErr)
|
|
{
|
|
DisplayCertSrvErrorWithContext(hwnd, dwErr, IDS_OLD_CA);
|
|
}
|
|
else
|
|
{
|
|
DisplayGenericCertSrvError(hwnd, dwErr);
|
|
}
|
|
}
|
|
|
|
// only do this once
|
|
if (fMustRefresh)
|
|
{
|
|
// notify views: refresh service toolbar buttons
|
|
m_pConsole->UpdateAllViews(
|
|
pDataObject,
|
|
0,
|
|
0);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CComponentDataImpl::UpdateScopeIcons()
|
|
{
|
|
CFolder* pFolder;
|
|
POSITION pos;
|
|
|
|
int nImage;
|
|
|
|
// walk through our internal list, modify, and resend to scope
|
|
pos = m_scopeItemList.GetHeadPosition();
|
|
while(pos)
|
|
{
|
|
pFolder = m_scopeItemList.GetNext(pos);
|
|
ASSERT(pFolder);
|
|
if (NULL == pFolder)
|
|
break;
|
|
|
|
// only modify server instances
|
|
if (pFolder->GetType() != SERVER_INSTANCE)
|
|
continue;
|
|
|
|
if (pFolder->m_pCertCA->m_pParentMachine->IsCertSvrServiceRunning())
|
|
nImage = IMGINDEX_CERTSVR_RUNNING;
|
|
else
|
|
nImage = IMGINDEX_CERTSVR_STOPPED;
|
|
|
|
// folder currently has these values defined, right?
|
|
ASSERT(pFolder->m_ScopeItem.mask & SDI_IMAGE);
|
|
ASSERT(pFolder->m_ScopeItem.mask & SDI_OPENIMAGE);
|
|
|
|
// These are the only values we wish to reset
|
|
pFolder->m_ScopeItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
|
|
|
|
pFolder->m_ScopeItem.nImage = nImage;
|
|
pFolder->m_ScopeItem.nOpenImage = nImage;
|
|
|
|
// and send these changes back to scope
|
|
m_pScope->SetItem(&pFolder->m_ScopeItem);
|
|
}
|
|
|
|
return;
|
|
}
|