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.
 
 
 
 
 
 

1501 lines
37 KiB

/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
remdlg.cpp
Abstract:
Remove licenses dialog implementation.
Author:
Jeff Parham (jeffparh) 13-Dec-1995
Revision History:
--*/
#include "stdafx.h"
#include "ccfapi.h"
#include "remdlg.h"
#include "utils.h"
#include "licobj.h"
#include "imagelst.h"
#include "nlicdlg.h"
#include <htmlhelp.h>
#include <strsafe.h> //include last
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// describes the list view layout
static LV_COLUMN_INFO g_removeColumnInfo =
{
0, 1, LVID_REMOVE_TOTAL_COLUMNS,
{{LVID_REMOVE_SERIAL_NUMBER, IDS_SERIAL_NUMBER, LVCX_REMOVE_SERIAL_NUMBER },
{LVID_REMOVE_PRODUCT_NAME, IDS_PRODUCT_NAME, LVCX_REMOVE_PRODUCT_NAME },
{LVID_REMOVE_LICENSE_MODE, IDS_LICENSE_MODE, LVCX_REMOVE_LICENSE_MODE },
{LVID_REMOVE_NUM_LICENSES, IDS_QUANTITY, LVCX_REMOVE_NUM_LICENSES },
{LVID_REMOVE_SOURCE, IDS_SOURCE, LVCX_REMOVE_SOURCE }},
};
CCertRemoveSelectDlg::CCertRemoveSelectDlg(CWnd* pParent /*=NULL*/)
: CDialog(CCertRemoveSelectDlg::IDD, pParent)
/*++
Routine Description:
Constructor for dialog.
Arguments:
pParent - owner window.
Return Values:
None.
--*/
{
//{{AFX_DATA_INIT(CCertRemoveSelectDlg)
m_nLicenses = 0;
//}}AFX_DATA_INIT
m_hLls = NULL;
m_bLicensesRefreshed = FALSE;
m_dwRemoveFlags = 0;
}
CCertRemoveSelectDlg::~CCertRemoveSelectDlg()
/*++
Routine Description:
Destructor for dialog.
Arguments:
None.
Return Values:
None.
--*/
{
if ( NULL != m_hLls )
{
LlsClose( m_hLls );
}
}
void CCertRemoveSelectDlg::DoDataExchange(CDataExchange* pDX)
/*++
Routine Description:
Called by framework to exchange dialog data.
Arguments:
pDX - data exchange object.
Return Values:
None.
--*/
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCertRemoveSelectDlg)
DDX_Control(pDX, IDC_SPIN_LICENSES, m_spinLicenses);
DDX_Control(pDX, IDC_CERTIFICATE_LIST, m_listCertificates);
DDX_Text(pDX, IDC_NUM_LICENSES, m_nLicenses);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCertRemoveSelectDlg, CDialog)
//{{AFX_MSG_MAP(CCertRemoveSelectDlg)
ON_BN_CLICKED(IDC_MY_HELP, OnHelp)
ON_NOTIFY(LVN_COLUMNCLICK, IDC_CERTIFICATE_LIST, OnColumnClickCertificateList)
ON_NOTIFY(LVN_GETDISPINFO, IDC_CERTIFICATE_LIST, OnGetDispInfoCertificateList)
ON_NOTIFY(UDN_DELTAPOS, IDC_SPIN_LICENSES, OnDeltaPosSpinLicenses)
ON_NOTIFY(NM_DBLCLK, IDC_CERTIFICATE_LIST, OnDblClkCertificateList)
ON_NOTIFY(NM_RETURN, IDC_CERTIFICATE_LIST, OnReturnCertificateList)
ON_WM_DESTROY()
ON_NOTIFY(NM_CLICK, IDC_CERTIFICATE_LIST, OnClickCertificateList)
ON_NOTIFY(LVN_KEYDOWN, IDC_CERTIFICATE_LIST, OnKeyDownCertificateList)
ON_BN_CLICKED(IDC_REFRESH, OnRefresh)
ON_MESSAGE( WM_HELP , OnHelpCmd )
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL CCertRemoveSelectDlg::OnInitDialog()
/*++
Routine Description:
Handler for WM_INITDIALOG.
Arguments:
None.
Return Values:
Returns false if focus set manually.
--*/
{
CDialog::OnInitDialog();
LoadImages();
m_listCertificates.SetImageList( &m_smallImages, LVSIL_SMALL );
::LvInitColumns( &m_listCertificates, &g_removeColumnInfo );
RefreshLicenses();
RefreshCertificateList();
UpdateSpinControlRange();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CCertRemoveSelectDlg::OnOK()
/*++
Routine Description:
Handler for BN_CLICKED of OK.
Arguments:
None.
Return Values:
None.
--*/
{
RemoveSelectedCertificate();
}
/*++
Routine Description:
Handler for pressing F1.
Arguments:
None.
Return Values:
Nothing significant.
--*/
LRESULT CCertRemoveSelectDlg::OnHelpCmd( WPARAM , LPARAM )
{
OnHelp();
return 0;
}
void CCertRemoveSelectDlg::OnHelp()
/*++
Routine Description:
Handler for help button click.
Arguments:
None.
Return Values:
None.
--*/
{
WinHelp( IDD, HELP_CONTEXT );
}
void CCertRemoveSelectDlg::WinHelp(DWORD dwData, UINT nCmd)
/*++
Routine Description:
Call WinHelp for this dialog.
Arguments:
dwData (DWORD)
nCmd (UINT)
Return Values:
None.
--*/
{
::HtmlHelp(m_hWnd, L"liceconcepts.chm", HH_DISPLAY_TOPIC, (DWORD_PTR)(L"LICE_Remove_dialog.htm"));
UNREFERENCED_PARAMETER(dwData);
UNREFERENCED_PARAMETER(nCmd);
/*
BOOL ok = ::WinHelp( m_hWnd, theApp.GetHelpFileName(), nCmd, dwData );
ASSERT( ok );
*/
}
void CCertRemoveSelectDlg::OnDestroy()
/*++
Routine Description:
Handler for WM_DESTROY.
Arguments:
None.
Return Values:
None.
--*/
{
ResetLicenses();
/*
::WinHelp( m_hWnd, theApp.GetHelpFileName(), HELP_QUIT, 0 );
*/
CDialog::OnDestroy();
}
void CCertRemoveSelectDlg::OnColumnClickCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
/*++
Routine Description:
Handler for LVN_COLUMNCLICK of certificate list view.
Arguments:
pNMHDR (NMHDR*)
pResult (LRESULT*)
Return Values:
None.
--*/
{
g_removeColumnInfo.bSortOrder = GetKeyState(VK_CONTROL) < 0;
g_removeColumnInfo.nSortedItem = ((NM_LISTVIEW*)pNMHDR)->iSubItem;
m_listCertificates.SortItems( CompareLicenses, 0 ); // use column info
*pResult = 0;
}
void CCertRemoveSelectDlg::OnGetDispInfoCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
/*++
Routine Description:
Handler for LVN_GETDISPINFO of certificate list view.
Arguments:
pNMHDR (NMHDR*)
pResult (LRESULT*)
Return Values:
None.
--*/
{
ASSERT(NULL != pNMHDR);
LV_ITEM* plvItem = &((LV_DISPINFO*)pNMHDR)->item;
ASSERT(plvItem);
CLicense* pLicense = (CLicense*)plvItem->lParam;
VALIDATE_OBJECT(pLicense, CLicense);
switch (plvItem->iSubItem)
{
case LVID_REMOVE_SERIAL_NUMBER:
plvItem->iImage = BMPI_CERTIFICATE;
{
CString strSerialNumber;
strSerialNumber.Format( TEXT("%ld"), (LONG) ( pLicense->m_dwCertificateID ) );
lstrcpyn( plvItem->pszText, strSerialNumber, plvItem->cchTextMax );
}
break;
case LVID_REMOVE_PRODUCT_NAME:
lstrcpyn( plvItem->pszText, pLicense->m_strProduct, plvItem->cchTextMax );
break;
case LVID_REMOVE_LICENSE_MODE:
lstrcpyn( plvItem->pszText, pLicense->GetAllowedModesString(), plvItem->cchTextMax );
break;
case LVID_REMOVE_NUM_LICENSES:
{
CString strLicenses;
strLicenses.Format( TEXT("%ld"), (LONG) ( pLicense->m_lQuantity ) );
lstrcpyn( plvItem->pszText, strLicenses, plvItem->cchTextMax );
}
break;
case LVID_REMOVE_SOURCE:
lstrcpyn( plvItem->pszText, pLicense->GetSourceDisplayName(), plvItem->cchTextMax );
break;
default:
ASSERT( FALSE );
break;
}
ASSERT(NULL != pResult);
*pResult = 0;
}
void CCertRemoveSelectDlg::OnDeltaPosSpinLicenses(NMHDR* pNMHDR, LRESULT* pResult)
/*++
Routine Description:
Handler for UDN_DELTAPOS of number of licenses.
Arguments:
pNMHDR (NMHDR*)
pResult (LRESULT*)
Return Values:
None.
--*/
{
if ( UpdateData(TRUE) ) // get data
{
ASSERT(NULL != pNMHDR);
m_nLicenses += ((NM_UPDOWN*)pNMHDR)->iDelta;
int nLow;
int nHigh;
m_spinLicenses.GetRange32( nLow, nHigh ); // BUG: 570335 changed GetRange to GetRange32.
if (m_nLicenses < nLow)
{
m_nLicenses = nLow;
::MessageBeep(MB_OK);
}
else if (m_nLicenses > nHigh )
{
m_nLicenses = nHigh;
::MessageBeep(MB_OK);
}
UpdateData(FALSE); // set data
}
ASSERT(NULL != pResult);
*pResult = 1; // handle ourselves...
}
void CCertRemoveSelectDlg::OnDblClkCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
/*++
Routine Description:
Handler for NM_DBLCLK of certificate list view.
Arguments:
pNMHDR (NMHDR*)
pResult (LRESULT*)
Return Values:
None.
--*/
{
RemoveSelectedCertificate();
UNREFERENCED_PARAMETER(pNMHDR);
ASSERT(NULL != pResult);
*pResult = 0;
}
void CCertRemoveSelectDlg::OnReturnCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
/*++
Routine Description:
Handler for NM_RETURN of certificate list view.
Arguments:
None.
Return Values:
None.
--*/
{
RemoveSelectedCertificate();
UNREFERENCED_PARAMETER(pNMHDR);
ASSERT(NULL != pResult);
*pResult = 0;
}
void CCertRemoveSelectDlg::ResetLicenses()
/*++
Routine Description:
Remove all licenses from internal list.
Arguments:
None.
Return Values:
None.
--*/
{
CLicense* pLicense;
int iLicense = (int)m_licenseArray.GetSize();
while (iLicense--)
{
if (NULL != (pLicense = (CLicense*)m_licenseArray[iLicense]))
{
ASSERT(pLicense->IsKindOf(RUNTIME_CLASS(CLicense)));
delete pLicense;
}
}
m_licenseArray.RemoveAll();
m_listCertificates.DeleteAllItems();
m_bLicensesRefreshed = FALSE;
}
BOOL CCertRemoveSelectDlg::RefreshLicenses()
/*++
Routine Description:
Refresh internal license list with data from license server.
Arguments:
None.
Return Values:
BOOL.
--*/
{
ResetLicenses();
if ( ConnectServer() )
{
NTSTATUS NtStatus;
DWORD ResumeHandle = 0L;
int iLicense = 0;
do
{
DWORD EntriesRead;
DWORD TotalEntries;
LPBYTE ReturnBuffer = NULL;
DWORD Level = LlsCapabilityIsSupported( m_hLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) ? 1 : 0;
BeginWaitCursor();
NtStatus = ::LlsLicenseEnum( m_hLls,
Level,
&ReturnBuffer,
LLS_PREFERRED_LENGTH,
&EntriesRead,
&TotalEntries,
&ResumeHandle );
EndWaitCursor();
if ( ( STATUS_SUCCESS == NtStatus )
|| ( STATUS_MORE_ENTRIES == NtStatus ) )
{
CLicense* pLicense;
PLLS_LICENSE_INFO_0 pLicenseInfo0;
PLLS_LICENSE_INFO_1 pLicenseInfo1;
pLicenseInfo0 = (PLLS_LICENSE_INFO_0)ReturnBuffer;
pLicenseInfo1 = (PLLS_LICENSE_INFO_1)ReturnBuffer;
while (EntriesRead--)
{
if ( ( m_strProductName.IsEmpty() || !m_strProductName.CompareNoCase( Level ? pLicenseInfo1->Product : pLicenseInfo0->Product ) )
&& ( m_strSourceToUse.IsEmpty() || !m_strSourceToUse.CompareNoCase( Level ? pLicenseInfo1->Source : TEXT("None") ) ) )
{
// we want to list this license
// have we seen this certificate yet?
for ( int i=0; i < m_licenseArray.GetSize(); i++ )
{
pLicense = (CLicense*) m_licenseArray[ i ];
VALIDATE_OBJECT( pLicense, CLicense );
if ( ( ( 1 == Level )
&& ( pLicense->m_dwCertificateID == pLicenseInfo1->CertificateID )
&& ( pLicense->m_dwAllowedModes == pLicenseInfo1->AllowedModes )
&& ( pLicense->m_dwMaxQuantity == pLicenseInfo1->MaxQuantity )
&& ( !pLicense->m_strSource.CompareNoCase( pLicenseInfo1->Source ) )
&& ( !pLicense->m_strProduct.CompareNoCase( pLicenseInfo1->Product ) )
&& ( !memcmp( pLicense->m_adwSecrets,
pLicenseInfo1->Secrets,
sizeof( pLicense->m_adwSecrets ) ) ) )
|| ( ( 0 == Level )
&& ( !pLicense->m_strProduct.CompareNoCase( pLicenseInfo0->Product ) ) ) )
{
// we've seen this certificate before; update the tally
pLicense->m_lQuantity += ( Level ? pLicenseInfo1->Quantity : pLicenseInfo0->Quantity );
break;
}
}
if ( i >= m_licenseArray.GetSize() )
{
// we haven't seen this certificate yet; create a new license for it
if ( 1 == Level )
{
pLicense = new CLicense( pLicenseInfo1->Product,
pLicenseInfo1->Vendor,
pLicenseInfo1->Admin,
pLicenseInfo1->Date,
pLicenseInfo1->Quantity,
pLicenseInfo1->Comment,
pLicenseInfo1->AllowedModes,
pLicenseInfo1->CertificateID,
pLicenseInfo1->Source,
pLicenseInfo1->ExpirationDate,
pLicenseInfo1->MaxQuantity,
pLicenseInfo1->Secrets );
::LlsFreeMemory( pLicenseInfo1->Product );
::LlsFreeMemory( pLicenseInfo1->Admin );
::LlsFreeMemory( pLicenseInfo1->Comment );
::LlsFreeMemory( pLicenseInfo1->Source );
}
else
{
ASSERT( 0 == Level );
pLicense = new CLicense( pLicenseInfo0->Product,
TEXT( "Microsoft" ),
pLicenseInfo0->Admin,
pLicenseInfo0->Date,
pLicenseInfo0->Quantity,
pLicenseInfo0->Comment );
::LlsFreeMemory( pLicenseInfo0->Product );
::LlsFreeMemory( pLicenseInfo0->Admin );
::LlsFreeMemory( pLicenseInfo0->Comment );
}
if ( NULL == pLicense )
{
NtStatus = ERROR_OUTOFMEMORY;
break;
}
m_licenseArray.Add( pLicense );
}
}
pLicenseInfo1++;
pLicenseInfo0++;
}
::LlsFreeMemory(ReturnBuffer);
}
} while ( STATUS_MORE_ENTRIES == NtStatus );
theApp.SetLastLlsError( NtStatus ); // called api
if ( STATUS_SUCCESS == NtStatus )
{
// add per server entries
LPTSTR pszServerName = m_strServerName.GetBuffer(0);
if ( NULL != pszServerName )
{
BeginWaitCursor();
HKEY hKeyLocalMachine;
NtStatus = RegConnectRegistry( pszServerName, HKEY_LOCAL_MACHINE, &hKeyLocalMachine );
if ( ERROR_SUCCESS != NtStatus )
{
theApp.SetLastError( NtStatus );
}
else
{
HKEY hKeyLicenseInfo;
NtStatus = RegOpenKeyEx( hKeyLocalMachine, TEXT( "SYSTEM\\CurrentControlSet\\Services\\LicenseInfo" ), 0, KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_SET_VALUE, &hKeyLicenseInfo );
if ( ERROR_SUCCESS != NtStatus )
{
theApp.SetLastError( NtStatus );
}
else
{
NTSTATUS ntEnum;
BOOL bFoundKey = FALSE;
DWORD iSubKey = 0;
// if the service is 3.51-style per server, add it to the list
do
{
TCHAR szKeyName[ 128 ];
DWORD cchKeyName = sizeof( szKeyName ) / sizeof( *szKeyName );
ntEnum = RegEnumKeyEx( hKeyLicenseInfo, iSubKey++, szKeyName, &cchKeyName, NULL, NULL, NULL, NULL );
if ( ERROR_SUCCESS == ntEnum )
{
HKEY hKeyProduct;
NtStatus = RegOpenKeyEx( hKeyLicenseInfo, szKeyName, 0, KEY_QUERY_VALUE | KEY_SET_VALUE, &hKeyProduct );
if ( ERROR_SUCCESS == NtStatus )
{
DWORD dwType;
TCHAR szDisplayName[ 128 ];
DWORD cbDisplayName = sizeof( szDisplayName );
NtStatus = RegQueryValueEx( hKeyProduct, TEXT( "DisplayName" ), NULL, &dwType, (LPBYTE) szDisplayName, &cbDisplayName );
if ( ERROR_SUCCESS == NtStatus )
{
// is this product secure?
BOOL bIsSecure = FALSE;
if ( LlsCapabilityIsSupported( m_hLls, LLS_CAPABILITY_SECURE_CERTIFICATES ) )
{
NtStatus = ::LlsProductSecurityGet( m_hLls, szDisplayName, &bIsSecure );
theApp.SetLastLlsError( NtStatus );
if ( STATUS_SUCCESS != NtStatus )
{
bIsSecure = FALSE;
}
}
if ( !bIsSecure )
{
#ifdef REMOVE_CONCURRENT_ONLY_IF_PER_SERVER_MODE
// not secure; is it in per server mode?
DWORD dwMode;
DWORD cbMode = sizeof( dwMode );
NtStatus = RegQueryValueEx( hKeyProduct, TEXT( "Mode" ), NULL, &dwType, (LPBYTE) &dwMode, &cbMode );
if ( ( ERROR_SUCCESS == NtStatus ) && dwMode )
{
// per server mode; add to list
#endif
DWORD dwConcurrentLimit;
DWORD cbConcurrentLimit = sizeof( dwConcurrentLimit );
NtStatus = RegQueryValueEx( hKeyProduct, TEXT( "ConcurrentLimit" ), NULL, &dwType, (LPBYTE) &dwConcurrentLimit, &cbConcurrentLimit );
if ( ( ERROR_SUCCESS == NtStatus )
&& ( 0 < dwConcurrentLimit )
&& ( m_strProductName.IsEmpty() || !m_strProductName.CompareNoCase( szDisplayName ) )
&& ( m_strSourceToUse.IsEmpty() || !m_strSourceToUse.CompareNoCase( TEXT("None") ) ) )
{
CLicense * pLicense = new CLicense( szDisplayName,
TEXT(""),
TEXT(""),
0,
dwConcurrentLimit,
TEXT(""),
LLS_LICENSE_MODE_ALLOW_PER_SERVER );
if ( NULL != pLicense )
{
m_licenseArray.Add( pLicense );
}
}
}
#ifdef REMOVE_CONCURRENT_ONLY_IF_PER_SERVER_MODE
}
#endif
}
RegCloseKey( hKeyProduct );
}
}
} while ( ERROR_SUCCESS == ntEnum );
RegCloseKey( hKeyLicenseInfo );
}
RegCloseKey( hKeyLocalMachine );
}
m_strServerName.ReleaseBuffer();
}
EndWaitCursor();
m_bLicensesRefreshed = TRUE;
// remove any entries from the list that aren't removable
for ( int i=0; i < m_licenseArray.GetSize(); )
{
CLicense* pLicense = (CLicense*) m_licenseArray[ i ];
VALIDATE_OBJECT( pLicense, CLicense );
if ( pLicense->m_lQuantity <= 0 )
{
delete pLicense;
m_licenseArray.RemoveAt( i );
}
else
{
i++;
}
}
}
else
{
theApp.DisplayLastError();
ResetLicenses();
}
}
return m_bLicensesRefreshed;
}
BOOL CCertRemoveSelectDlg::RefreshCertificateList()
/*++
Routine Description:
Refresh certificate list view from internal license list.
Arguments:
None.
Return Values:
BOOL.
--*/
{
BeginWaitCursor();
BOOL ok = ::LvRefreshObArray( &m_listCertificates, &g_removeColumnInfo, &m_licenseArray );
EndWaitCursor();
return ok;
}
int CALLBACK CompareLicenses(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
/*++
Routine Description:
Notification handler for LVM_SORTITEMS.
Arguments:
lParam1 - object to sort.
lParam2 - object to sort.
lParamSort - sort criteria.
Return Values:
Same as lstrcmp.
--*/
{
CLicense * pLic1 = (CLicense *) lParam1;
CLicense * pLic2 = (CLicense *) lParam2;
UNREFERENCED_PARAMETER(lParamSort);
VALIDATE_OBJECT( pLic1, CLicense );
VALIDATE_OBJECT( pLic2, CLicense );
int iResult;
switch (g_removeColumnInfo.nSortedItem)
{
case LVID_REMOVE_SERIAL_NUMBER:
iResult = pLic1->m_dwCertificateID - pLic2->m_dwCertificateID;
break;
case LVID_REMOVE_PRODUCT_NAME:
iResult = pLic1->m_strProduct.CompareNoCase( pLic2->m_strProduct );
break;
case LVID_REMOVE_NUM_LICENSES:
iResult = pLic1->m_lQuantity - pLic2->m_lQuantity;
break;
case LVID_REMOVE_SOURCE:
iResult = pLic1->GetSourceDisplayName().CompareNoCase( pLic2->GetSourceDisplayName() );
break;
default:
iResult = 0;
break;
}
return g_removeColumnInfo.bSortOrder ? -iResult : iResult;
}
void CCertRemoveSelectDlg::UpdateSpinControlRange()
/*++
Routine Description:
Update range of spin control for number of licenses.
Arguments:
None.
Return Values:
None.
--*/
{
CLicense * pLicense;
UpdateData( TRUE );
if (NULL != (pLicense = (CLicense*)::LvGetSelObj( &m_listCertificates )))
{
m_spinLicenses.SetRange32( 1, pLicense->m_lQuantity ); // BUG: 570335 changed SetRange to SetRange32.
m_nLicenses = pLicense->m_lQuantity;
GetDlgItem( IDOK )->EnableWindow( TRUE );
}
else
{
m_spinLicenses.SetRange32( 0, 0 ); // BUG: 570335 changed SetRange to SetRange32.
m_nLicenses = 0;
GetDlgItem( IDOK )->EnableWindow( FALSE );
}
UpdateData( FALSE );
}
DWORD
CatUnicodeAndAnsiStrings(
IN WCHAR const *pwszUnicode,
IN CHAR const *pszAnsi,
OUT CHAR **ppszStr)
/*
Description:
cat unicode str and ansi str into ansi str
Arguments:
pwszUicode - unicode string
pszAnsi - ansi string
ppszStr - pointer to return string, caller LocalFree it
Return:
if any error
*/
{
DWORD dwErr = ERROR_SUCCESS;
ASSERT(NULL != pwszUnicode &&
NULL != pszAnsi &&
NULL != ppszStr);
//init
*ppszStr = NULL;
size_t cb = wcslen(pwszUnicode) + strlen(pszAnsi) + 1;
CHAR *pszStr = (CHAR*)LocalAlloc(LMEM_FIXED, cb);
if (NULL == pszStr)
{
dwErr = ERROR_OUTOFMEMORY;
}
else
{
HRESULT hr;
hr = StringCbPrintfA(pszStr, cb, "%ls", pwszUnicode);
ASSERT(SUCCEEDED(hr));
hr = StringCchCatA(pszStr, cb, pszAnsi);
ASSERT(SUCCEEDED(hr));
*ppszStr = pszStr;
pszStr = NULL;
}
if (NULL != pszStr)
{
LocalFree(pszStr);
}
return dwErr;
}
DWORD CCertRemoveSelectDlg::RemoveSelectedCertificate()
/*++
Routine Description:
Remove the given number of licenses from the selected certificate.
Arguments:
None.
Return Values:
ERROR_SUCCESS
NT status code
Win error
--*/
{
NTSTATUS nt = STATUS_SUCCESS;
HRESULT hr;
size_t cch1, cch2, cch3;
if ( UpdateData( TRUE ) )
{
BOOL bDisplayError = TRUE;
CLicense * pLicense;
if (NULL == ( pLicense = (CLicense*)::LvGetSelObj( &m_listCertificates ) ) )
{
// no certificate selected
bDisplayError = FALSE;
}
else if ( ( m_nLicenses < 1 ) || ( m_nLicenses > pLicense->m_lQuantity ) )
{
// invalid number of licenses to remove
AfxMessageBox( IDS_REMOVE_INVALID_NUM_LICENSES, MB_ICONEXCLAMATION | MB_OK, 0 );
nt = ERROR_CANCELLED;
bDisplayError = FALSE;
}
else
{
CString strLicenses;
CString strConfirm;
strLicenses.Format( TEXT("%d"), m_nLicenses );
AfxFormatString2( strConfirm, IDS_REMOVE_CERTIFICATE_CONFIRM, strLicenses, pLicense->m_strProduct );
int nResponse = AfxMessageBox( strConfirm, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2 );
if ( IDYES != nResponse )
{
nt = ERROR_CANCELLED;
bDisplayError = FALSE;
}
else
{
// delete certificate
cch1 = 1 + m_strServerName.GetLength();
LPSTR pszAscServerName = (LPSTR) LocalAlloc( LMEM_FIXED, cch1);
cch2 = 1 + pLicense->m_strProduct.GetLength();
LPSTR pszAscProductName = (LPSTR) LocalAlloc( LMEM_FIXED, cch2);
cch3 = 1 + m_strVendor.GetLength();
LPSTR pszAscVendor = (LPSTR) LocalAlloc( LMEM_FIXED, cch3);
CString cstrClose;
cstrClose.LoadString( IDS_CLOSETEXT );
CWnd *pWnd = GetDlgItem( IDCANCEL );
if( pWnd != NULL )
{
pWnd->SetWindowText( cstrClose );
}
if ( ( NULL == pszAscServerName ) || ( NULL == pszAscProductName ) || ( NULL == pszAscVendor ) )
{
nt = ERROR_NOT_ENOUGH_MEMORY;
}
else
{
hr = StringCchPrintfA( pszAscServerName, cch1, "%ls", (LPCWSTR) m_strServerName );
ASSERT(SUCCEEDED(hr));
hr = StringCchPrintfA( pszAscProductName, cch2, "%ls", (LPCWSTR) pLicense->m_strProduct );
ASSERT(SUCCEEDED(hr));
hr = StringCchPrintfA( pszAscVendor, cch3, "%ls", (LPCWSTR) m_strVendor );
ASSERT(SUCCEEDED(hr));
LLS_LICENSE_INFO_1 lic;
nt = pLicense->CreateLicenseInfo( &lic );
if ( STATUS_SUCCESS == nt )
{
// only remove as many licenses as requested
lic.Quantity = m_nLicenses;
if ( !pLicense->m_strSource.CompareNoCase( TEXT( "None" ) ) )
{
nt = NoCertificateRemove( m_hWnd, pszAscServerName, m_dwRemoveFlags, 1, &lic );
bDisplayError = FALSE;
}
else
{
// get certificate source DLL path
CString strKeyName = TEXT( "Software\\LSAPI\\Microsoft\\CertificateSources\\" )
+ pLicense->m_strSource;
HKEY hKeySource;
nt = RegOpenKeyEx( HKEY_LOCAL_MACHINE, strKeyName, 0, KEY_READ, &hKeySource );
if ( ( ERROR_PATH_NOT_FOUND == nt ) || ( ERROR_FILE_NOT_FOUND == nt ) )
{
AfxMessageBox( IDS_CERT_SOURCE_NOT_AVAILABLE, MB_ICONSTOP | MB_OK, 0 );
nt = ERROR_CANCELLED;
bDisplayError = FALSE;
}
else if ( ERROR_SUCCESS == nt )
{
TCHAR szImagePath[ 1 + _MAX_PATH ];
DWORD cbImagePath = sizeof( szImagePath );
DWORD dwType;
nt = RegQueryValueEx( hKeySource, TEXT( "ImagePath" ), NULL, &dwType, (LPBYTE) szImagePath, &cbImagePath );
if ( ERROR_SUCCESS == nt )
{
TCHAR szExpandedImagePath[ 1 + _MAX_PATH ];
BOOL ok = ExpandEnvironmentStrings( szImagePath, szExpandedImagePath, sizeof( szExpandedImagePath ) / sizeof( *szExpandedImagePath ) );
if ( !ok )
{
nt = GetLastError();
}
else
{
// load certificate source DLL
HINSTANCE hDll = ::LoadLibrary( szExpandedImagePath );
if ( NULL == hDll )
{
nt = GetLastError();
}
else
{
// get certificate remove function
CHAR *pszExportName = NULL;
nt = CatUnicodeAndAnsiStrings(
pLicense->m_strSource,
"CertificateRemove",
&pszExportName);
if (ERROR_SUCCESS == nt)
{
ASSERT(NULL != pszExportName);
PCCF_REMOVE_API pRemoveFn;
pRemoveFn = (PCCF_REMOVE_API) GetProcAddress( hDll, pszExportName );
if ( NULL == pRemoveFn )
{
nt = GetLastError();
}
else
{
// remove certificate
nt = (*pRemoveFn)( m_hWnd, pszAscServerName, m_dwRemoveFlags, 1, &lic );
bDisplayError = FALSE;
}
::FreeLibrary( hDll );
LocalFree(pszExportName);
}
}
}
}
RegCloseKey( hKeySource );
}
}
pLicense->DestroyLicenseInfo( &lic );
}
}
if ( NULL != pszAscServerName ) LocalFree( pszAscServerName );
if ( NULL != pszAscProductName ) LocalFree( pszAscProductName );
if ( NULL != pszAscVendor ) LocalFree( pszAscVendor );
RefreshLicenses();
RefreshCertificateList();
UpdateSpinControlRange();
}
}
if ( bDisplayError && ( ERROR_SUCCESS != nt ) )
{
theApp.SetLastError( nt );
theApp.DisplayLastError();
}
}
return nt;
}
BOOL CCertRemoveSelectDlg::ConnectServer()
/*++
Routine Description:
Establish a connection to the license service on the target server.
Arguments:
None.
Return Values:
BOOL.
--*/
{
if ( NULL == m_hLls )
{
LPTSTR pszServerName;
if ( m_strServerName.IsEmpty() )
{
pszServerName = NULL;
}
else
{
pszServerName = m_strServerName.GetBuffer( 0 );
}
ConnectTo( pszServerName, &m_hLls );
if ( NULL != pszServerName )
{
m_strServerName.ReleaseBuffer();
}
}
if ( NULL == m_hLls )
{
theApp.DisplayLastError();
if ( ( NULL != m_hWnd ) && IsWindow( m_hWnd ) )
{
EndDialog( IDABORT );
}
}
return ( NULL != m_hLls );
}
NTSTATUS CCertRemoveSelectDlg::ConnectTo( LPTSTR pszServerName, PLLS_HANDLE phLls )
/*++
Routine Description:
Establish a connection to the license service on the given server.
Arguments:
pszServerName (CString)
The target server. An empty value indicates the local server.
phLls (PLLS_HANDLE)
On return, holds the handle to the standard LLS RPC.
Return Values:
STATUS_SUCCESS or NT status code.
--*/
{
NTSTATUS nt;
nt = ::LlsConnect( pszServerName, phLls );
theApp.SetLastLlsError( nt );
if ( STATUS_SUCCESS != nt )
{
*phLls = NULL;
}
return nt;
}
void CCertRemoveSelectDlg::OnClickCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
/*++
Routine Description:
Handler for NM_CLICK of certificate list view.
Arguments:
pNMHDR (NMHDR*)
pResult (LRESULT*)
Return Values:
None.
--*/
{
UpdateSpinControlRange();
UNREFERENCED_PARAMETER(pNMHDR);
ASSERT(NULL != pResult);
*pResult = 1; // not handled...
}
void CCertRemoveSelectDlg::OnKeyDownCertificateList(NMHDR* pNMHDR, LRESULT* pResult)
/*++
Routine Description:
Handler for LVN_KEYDOWN of certificate list view.
Arguments:
pNMHDR (NMHDR*)
pResult (LRESULT*)
Return Values:
None.
--*/
{
UpdateSpinControlRange();
UNREFERENCED_PARAMETER(pNMHDR);
ASSERT(NULL != pResult);
*pResult = 1; // not handled...
}
BOOL CCertRemoveSelectDlg::LoadImages()
/*++
Routine Description:
Load icons for the list view.
Arguments:
None.
Return Values:
BOOL.
--*/
{
BOOL bImagesLoaded = m_smallImages.Create( IDB_SMALL_ICONS, BMPI_SMALL_SIZE, 0, BMPI_RGB_BKGND );
ASSERT( bImagesLoaded );
return bImagesLoaded;
}
void CCertRemoveSelectDlg::OnRefresh()
/*++
Routine Description:
Handler for BN_CLICK of refresh button.
Arguments:
None.
Return Values:
None.
--*/
{
RefreshLicenses();
RefreshCertificateList();
UpdateSpinControlRange();
}
DWORD CCertRemoveSelectDlg::CertificateRemove( LPCSTR pszServerName, LPCSTR pszProductName, LPCSTR pszVendor, DWORD dwFlags, LPCSTR pszSourceToUse )
/*++
Routine Description:
Display a dialog allowing the user to remove one or more license
certificates from the system.
Arguments:
pszServerName (LPCSTR)
Name of the server on which licenses are to be removed. A NULL value
indicates the local server.
pszProductName (LPCSTR)
Product for which licenses are to be removed. A NULL value indicates
that the user should be allowed to remove licenses from any product.
pszVendor (LPCSTR)
Name of the vendor of the product. This value should be NULL if
pszProductName is NULL, and should be non-NULL if pszProductName is
non-NULL.
dwFlags (DWORD)
Certificate removal options. As of this writing, no flags are
supported.
pszSourceToUse (LPCSTR)
Name of the secure certificate source by which licenses are to be
removed, e.g., "Paper". A NULL value indicates that the user should
be allowed to remove licenses that were installed with any source.
Return Value:
ERROR_SUCCESS
Win error
--*/
{
m_strServerName = pszServerName ? pszServerName : "";
m_strProductName = pszProductName ? pszProductName : "";
m_strVendor = pszVendor ? pszVendor : "";
m_dwRemoveFlags = dwFlags;
m_strSourceToUse = pszSourceToUse ? pszSourceToUse : "";
DoModal();
return ERROR_SUCCESS;
}