/*++ Copyright (c) 1994-95 Microsoft Corporation Module Name: lmoddlg.cpp Abstract: Licensing mode dialog. Author: Don Ryan (donryan) 28-Feb-1995 Environment: User Mode - Win32 Revision History: Jeff Parham (jeffparh) 16-Jan-1996 o Ported to CCF API to add/remove licenses, incl. removing edit box for number of licenses and replacing with Add/Remove Licenses buttons. o Added warning of possible loss when switching license modes. --*/ #include "stdafx.h" #include "llsmgr.h" #include "lmoddlg.h" #include "psrvdlg.h" #include "pseatdlg.h" #include "srvldlg.h" #include "lviodlg.h" #include static TCHAR szServerServiceNameNew[] = _T("Windows Server"); static TCHAR szServerServiceNameOld2[] = _T("Windows NT Server"); static TCHAR szServerServiceNameOld[] = _T("File and Print Service"); #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif BEGIN_MESSAGE_MAP(CLicensingModeDialog, CDialog) //{{AFX_MSG_MAP(CLicensingModeDialog) ON_BN_CLICKED(IDC_MODE_RADIO_PER_SEAT, OnModePerSeat) ON_BN_CLICKED(IDC_MODE_RADIO_PER_SERVER, OnModePerServer) ON_EN_UPDATE(IDC_MODE_LICENSES, OnUpdateQuantity) ON_COMMAND(ID_HELP, OnHelp) //}}AFX_MSG_MAP ON_BN_CLICKED(IDC_MODE_ADD_PER_SERVER, OnAddPerServer) ON_BN_CLICKED(IDC_MODE_REMOVE_PER_SERVER, OnRemovePerServer) END_MESSAGE_MAP() CLicensingModeDialog::CLicensingModeDialog(CWnd* pParent /*=NULL*/) : CDialog(CLicensingModeDialog::IDD, pParent) /*++ Routine Description: Constructor for dialog. Arguments: pParent - owner window. Return Values: None. --*/ { //{{AFX_DATA_INIT(CLicensingModeDialog) m_nLicenses = 0; m_strPerSeatStatic = _T(""); m_strSupportsStatic = _T(""); //}}AFX_DATA_INIT m_pService = NULL; m_bAreCtrlsInitialized = FALSE; m_fUpdateHint = UPDATE_INFO_NONE; } void CLicensingModeDialog::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(CLicensingModeDialog) DDX_Control(pDX, IDOK, m_okBtn); DDX_Control(pDX, IDC_MODE_LICENSES, m_licEdit); DDX_Text(pDX, IDC_MODE_LICENSES, m_nLicenses); DDV_MinMaxDWord(pDX, m_nLicenses, 0, 999999); DDX_Text(pDX, IDC_MODE_STATIC_PER_SEAT, m_strPerSeatStatic); DDX_Text(pDX, IDC_MODE_STATIC_SUPPORTS, m_strSupportsStatic); DDX_Control(pDX, IDC_MODE_RADIO_PER_SEAT, m_perSeatBtn); DDX_Control(pDX, IDC_MODE_RADIO_PER_SERVER, m_perServerBtn); //}}AFX_DATA_MAP DDX_Control(pDX, IDC_MODE_ADD_PER_SERVER, m_addPerServerBtn); DDX_Control(pDX, IDC_MODE_REMOVE_PER_SERVER, m_removePerServerBtn); } void CLicensingModeDialog::InitDialog(CService* pService) /*++ Routine Description: Initializes dialog. Arguments: pService - service object. Return Values: None. --*/ { VALIDATE_OBJECT(pService, CService); m_pService = pService; BSTR bstrDisplayName = m_pService->GetDisplayName(); m_strServiceName = bstrDisplayName; SysFreeString(bstrDisplayName); } void CLicensingModeDialog::InitCtrls() /*++ Routine Description: Initializes dialog controls. Arguments: None. Return Values: None. --*/ { m_licEdit.LimitText(6); if (m_pService->IsPerServer()) { OnModePerServer(); } else { OnModePerSeat(); } m_bAreCtrlsInitialized = TRUE; } BOOL CLicensingModeDialog::OnInitDialog() /*++ Routine Description: Message handler for WM_INITDIALOG. Arguments: None. Return Values: Returns false if focus set manually. --*/ { AfxFormatString1( m_strPerSeatStatic, IDS_LICENSING_MODE_1, m_strServiceName ); AfxFormatString1( m_strSupportsStatic, IDS_LICENSING_MODE_2, m_strServiceName ); CDialog::OnInitDialog(); PostMessage(WM_COMMAND, ID_INIT_CTRLS); return TRUE; } void CLicensingModeDialog::OnModePerSeat() /*++ Routine Description: Changing mode to per seat. Arguments: None. Return Values: None. --*/ { m_perSeatBtn.SetCheck(1); m_perServerBtn.SetCheck(0); ::SafeEnableWindow(&m_addPerServerBtn, &m_okBtn, CDialog::GetFocus(), FALSE); ::SafeEnableWindow(&m_removePerServerBtn, &m_okBtn, CDialog::GetFocus(), FALSE); m_licEdit.Clear(); if (m_pService->IsPerServer()) { if (m_pService->IsReadOnly()) { CLicensingViolationDialog vioDlg; if (vioDlg.DoModal() != IDOK) { OnModePerServer(); return; // bail... } } if ( ( 0 != GetDlgItemInt( IDC_MODE_LICENSES, NULL, FALSE ) ) && ( IDYES != AfxMessageBox( IDP_CONFIRM_TO_PER_SEAT, MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2 ) ) ) { OnModePerServer(); return; // bail... } } } void CLicensingModeDialog::OnModePerServer() /*++ Routine Description: Changing mode to per server. Arguments: None. Return Values: None. --*/ { m_perSeatBtn.SetCheck(0); m_perServerBtn.SetCheck(1); ::SafeEnableWindow(&m_addPerServerBtn, &m_okBtn, CDialog::GetFocus(), TRUE); ::SafeEnableWindow(&m_removePerServerBtn, &m_okBtn, CDialog::GetFocus(), TRUE); UpdatePerServerLicenses(); if (!m_pService->IsPerServer()) { if (m_pService->IsReadOnly()) { CLicensingViolationDialog vioDlg; if (vioDlg.DoModal() != IDOK) { OnModePerSeat(); return; // bail... } } if ( IDYES != AfxMessageBox( IDP_CONFIRM_TO_PER_SERVER, MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2 ) ) { OnModePerSeat(); return; // bail... } } } void CLicensingModeDialog::OnOK() /*++ Routine Description: Update registry. Arguments: None. Return Values: None. --*/ { BOOL bUpdateRegistry = TRUE; if (m_perSeatBtn.GetCheck()) { if (m_pService->IsPerServer()) { CPerSeatLicensingDialog perSeatDlg; perSeatDlg.m_strProduct = m_strServiceName; if (perSeatDlg.DoModal() != IDOK) return; // bail... } else { bUpdateRegistry = FALSE; } } else if (m_perServerBtn.GetCheck()) { if (!UpdateData(TRUE)) return; // bail... if (!m_pService->IsPerServer()) { if (!m_nLicenses && (!m_strServiceName.CompareNoCase(szServerServiceNameNew) || !m_strServiceName.CompareNoCase(szServerServiceNameOld2) || !m_strServiceName.CompareNoCase(szServerServiceNameOld))) { CServerLicensingDialog srvlDlg; if (srvlDlg.DoModal() != IDOK) return; // bail... } else { CString strLicenses; CPerServerLicensingDialog perServerDlg; perServerDlg.m_strProduct = m_strServiceName; strLicenses.Format(_T("%ld"), m_nLicenses); perServerDlg.m_strLicenses = strLicenses; if (perServerDlg.DoModal() != IDOK) return; // bail... } } else { bUpdateRegistry = FALSE; } } if (bUpdateRegistry) { long Status; #ifdef CONFIG_THROUGH_REGISTRY DWORD dwValue; BOOL bIsRegistryUpdated = FALSE; HKEY hkeyService = m_pService->GetRegKey(); dwValue = (m_perSeatBtn.GetCheck() || (m_perServerBtn.GetCheck() != m_pService->IsPerServer())) ? 0x1 : 0x0; Status = RegSetValueEx( hkeyService, REG_VALUE_FLIP, 0, REG_DWORD, (PBYTE)&dwValue, sizeof(DWORD) ); if (Status == ERROR_SUCCESS) { m_fUpdateHint |= UPDATE_LICENSE_MODE; // update... m_pService->m_bIsReadOnly = (dwValue == 0x1); // update... dwValue = m_perSeatBtn.GetCheck() ? 0x0 : 0x1; Status = RegSetValueEx( hkeyService, REG_VALUE_MODE, 0, REG_DWORD, (PBYTE)&dwValue, sizeof(DWORD) ); if (Status == ERROR_SUCCESS) { m_pService->m_bIsPerServer = (dwValue == 0x1); // update... bIsRegistryUpdated = TRUE; } } if (hkeyService) { RegCloseKey(hkeyService); } if (!bIsRegistryUpdated) { theApp.DisplayStatus(::GetLastError()); return; // bail... } #else CServer* pServer = (CServer*)MKOBJ(m_pService->GetParent()); if ( pServer && pServer->ConnectLls() ) // JonN 5/5/00 PREFIX 112122 { BSTR pKeyName = m_pService->GetName(); if ( NULL == pKeyName ) { Status = STATUS_NO_MEMORY; } else { PLLS_LOCAL_SERVICE_INFO_0 pServiceInfo = NULL; Status = ::LlsLocalServiceInfoGet( pServer->GetLlsHandle(), pKeyName, 0, (LPBYTE *) &pServiceInfo ); if ( NT_SUCCESS( Status ) ) { pServiceInfo->FlipAllow = (m_perSeatBtn.GetCheck() || (m_perServerBtn.GetCheck() != m_pService->IsPerServer())) ? 0x1 : 0x0; pServiceInfo->Mode = m_perSeatBtn.GetCheck() ? 0x0 : 0x1; Status = ::LlsLocalServiceInfoSet( pServer->GetLlsHandle(), pKeyName, 0, (LPBYTE) pServiceInfo ); if ( NT_SUCCESS( Status ) ) { m_fUpdateHint |= UPDATE_LICENSE_MODE; // update... m_pService->m_bIsReadOnly = ( 0x1 == pServiceInfo->FlipAllow ); // update... m_pService->m_bIsPerServer = ( 0x1 == pServiceInfo->Mode ); // update... } ::LlsFreeMemory( pServiceInfo->KeyName ); ::LlsFreeMemory( pServiceInfo->DisplayName ); ::LlsFreeMemory( pServiceInfo->FamilyDisplayName ); ::LlsFreeMemory( pServiceInfo ); } if ( IsConnectionDropped( Status ) ) { pServer->DisconnectLls(); } SysFreeString( pKeyName ); } } else { Status = LlsGetLastStatus(); } LlsSetLastStatus( Status ); if ( !NT_SUCCESS( Status ) ) { theApp.DisplayStatus( Status ); return; // bail... } #endif } EndDialog(IDOK); return; } void CLicensingModeDialog::OnCancel() /*++ Routine Description: Update registry. Arguments: None. Return Values: None. --*/ { if (m_nLicenses > (LONG) 999999) { UpdateData( TRUE ); } else { EndDialog( 0 ); } return; } BOOL CLicensingModeDialog::OnCommand(WPARAM wParam, LPARAM lParam) /*++ Routine Description: Message handler for WM_COMMAND. Arguments: wParam - message specific. lParam - message specific. Return Values: Returns true if message processed. --*/ { if (wParam == ID_INIT_CTRLS) { if (!m_bAreCtrlsInitialized) { InitCtrls(); } return TRUE; // processed... } return CDialog::OnCommand(wParam, lParam); } void CLicensingModeDialog::OnDeltaPosSpin(NMHDR* pNMHDR, LRESULT* pResult) /*++ Routine Description: Notification handler for UDN_DELTAPOS. Arguments: pNMHDR - notification header. pResult - return code. Return Values: None. --*/ { UpdateData(TRUE); // get data m_nLicenses += ((NM_UPDOWN*)pNMHDR)->iDelta; if (m_nLicenses < 0) { m_nLicenses = 0; ::MessageBeep(MB_OK); } else if (m_nLicenses > 999999) { m_nLicenses = 999999; ::MessageBeep(MB_OK); } UpdateData(FALSE); // set data *pResult = 1; // handle ourselves... } void CLicensingModeDialog::OnUpdateQuantity() /*++ Routine Description: Message handler for EN_UPDATE. Arguments: None. Return Values: None. --*/ { if (m_licEdit.IsWindowEnabled()) { long nLicensesOld = m_nLicenses; if (!UpdateData(TRUE)) { m_nLicenses = nLicensesOld; UpdateData(FALSE); m_licEdit.SetFocus(); m_licEdit.SetSel(0,-1); ::MessageBeep(MB_OK); } } } void CLicensingModeDialog::OnHelp() /*++ Routine Description: Help button support. Arguments: None. Return Values: None. --*/ { CDialog::OnCommandHelp(0, 0L); } void CLicensingModeDialog::OnAddPerServer() /*++ Routine Description: Add per server licenses button support. Arguments: None. Return Values: None. --*/ { HRESULT hr; size_t cch1, cch2; CServer* pServer = (CServer*)MKOBJ(m_pService->GetParent()); BSTR pszUniServerName = pServer->GetName(); BSTR pszUniProductName = m_pService->GetDisplayName(); if ( ( NULL == pszUniServerName ) || ( NULL == pszUniProductName ) ) { theApp.DisplayStatus( STATUS_NO_MEMORY ); } else { cch1 = 1 + lstrlen( pszUniServerName ); cch2 = 1 + lstrlen( pszUniProductName ); LPSTR pszAscServerName = (LPSTR) LocalAlloc( LMEM_FIXED, cch1 ); LPSTR pszAscProductName = (LPSTR) LocalAlloc( LMEM_FIXED, cch2 ); if ( ( NULL == pszAscServerName ) || ( NULL == pszAscProductName ) ) { theApp.DisplayStatus( STATUS_NO_MEMORY ); } else { hr = StringCchPrintfA( pszAscServerName, cch1, "%ls", pszUniServerName ); ASSERT(SUCCEEDED(hr)); hr = StringCchPrintfA( pszAscProductName, cch2, "%ls", pszUniProductName ); ASSERT(SUCCEEDED(hr)); DWORD dwError = CCFCertificateEnterUI( m_hWnd, pszAscServerName, pszAscProductName, "Microsoft", CCF_ENTER_FLAG_PER_SERVER_ONLY, NULL ); if ( ERROR_SUCCESS == dwError ) { m_fUpdateHint |= UPDATE_INFO_SERVICES | UPDATE_INFO_PRODUCTS; // update... UpdatePerServerLicenses(); } } if ( NULL != pszAscServerName ) { LocalFree( pszAscServerName ); } if ( NULL != pszAscProductName ) { LocalFree( pszAscProductName ); } } if ( NULL != pszUniServerName ) { SysFreeString( pszUniServerName ); } if ( NULL != pszUniProductName ) { SysFreeString( pszUniProductName ); } } void CLicensingModeDialog::OnRemovePerServer() /*++ Routine Description: Remove per server licenses button support. Arguments: None. Return Values: None. --*/ { HRESULT hr; size_t cch1, cch2; CServer* pServer = (CServer*)MKOBJ(m_pService->GetParent()); BSTR pszUniServerName = pServer->GetName(); BSTR pszUniProductName = m_pService->GetDisplayName(); if ( ( NULL == pszUniServerName ) || ( NULL == pszUniProductName ) ) { theApp.DisplayStatus( STATUS_NO_MEMORY ); } else { cch1 = 1 + lstrlen( pszUniServerName ); cch2 = 1 + lstrlen( pszUniProductName ); LPSTR pszAscServerName = (LPSTR) LocalAlloc( LMEM_FIXED, cch1 ); LPSTR pszAscProductName = (LPSTR) LocalAlloc( LMEM_FIXED, cch2 ); if ( ( NULL == pszAscServerName ) || ( NULL == pszAscProductName ) ) { theApp.DisplayStatus( STATUS_NO_MEMORY ); } else { hr = StringCchPrintfA( pszAscServerName, cch1, "%ls", pszUniServerName ); ASSERT(SUCCEEDED(hr)); hr = StringCchPrintfA( pszAscProductName, cch2, "%ls", pszUniProductName ); ASSERT(SUCCEEDED(hr)); CCFCertificateRemoveUI( m_hWnd, pszAscServerName, pszAscProductName, "Microsoft", NULL, NULL ); m_fUpdateHint |= UPDATE_INFO_SERVERS | UPDATE_INFO_SERVICES | UPDATE_LICENSE_DELETED; // update... UpdatePerServerLicenses(); } if ( NULL != pszAscServerName ) LocalFree( pszAscServerName ); if ( NULL != pszAscProductName ) LocalFree( pszAscProductName ); } if ( NULL != pszUniServerName ) SysFreeString( pszUniServerName ); if ( NULL != pszUniProductName ) SysFreeString( pszUniProductName ); } void CLicensingModeDialog::UpdatePerServerLicenses() /*++ Routine Description: Update the concurrent limit setting from the registry. Arguments: None. Return Values: None. --*/ { HRESULT hr; size_t cch; BeginWaitCursor(); CServer* pServer = (CServer*)MKOBJ(m_pService->GetParent()); if ( pServer == NULL ) { theApp.DisplayStatus( STATUS_NO_MEMORY ); return; } BSTR pszUniServerName = pServer->GetName(); BSTR pszUniProductName = m_pService->GetDisplayName(); if ( ( NULL == pszUniServerName ) || ( NULL == pszUniProductName ) ) { theApp.DisplayStatus( STATUS_NO_MEMORY ); } else { cch = 3 + lstrlen( pszUniServerName ); LPTSTR pszUniNetServerName = (LPTSTR) LocalAlloc( LMEM_FIXED, sizeof( TCHAR) * cch ); if ( NULL == pszUniNetServerName ) { theApp.DisplayStatus( STATUS_NO_MEMORY ); } else { hr = StringCchPrintf( pszUniNetServerName, cch, TEXT("%ls%ls"), (TEXT('\\') == *pszUniServerName) ? TEXT("") : TEXT("\\\\"), pszUniServerName ); ASSERT(SUCCEEDED(hr)); LLS_HANDLE hLls; DWORD dwError = LlsConnect( pszUniNetServerName, &hLls ); if ( ERROR_SUCCESS == dwError ) { DWORD dwConcurrentLimit; dwError = LlsProductLicensesGet( hLls, pszUniProductName, LLS_LICENSE_MODE_PER_SERVER, &dwConcurrentLimit ); LlsClose( hLls ); if ( ERROR_SUCCESS == dwError ) { m_pService->m_lPerServerLimit = dwConcurrentLimit; } } if ( ERROR_SUCCESS != dwError ) { #ifdef CONFIG_THROUGH_REGISTRY HKEY hkeyService = m_pService->GetRegKey(); DWORD dwConcurrentLimit; DWORD dwType; DWORD cb = sizeof( dwConcurrentLimit ); DWORD dwError = RegQueryValueEx( hkeyService, REG_VALUE_LIMIT, NULL, &dwType, (LPBYTE) &dwConcurrentLimit, &cb ); ASSERT( ERROR_SUCCESS == dwError ); if ( ERROR_SUCCESS == dwError ) { m_pService->m_lPerServerLimit = dwConcurrentLimit; } RegCloseKey( hkeyService ); #else NTSTATUS Status; if ( pServer->ConnectLls() ) { BSTR pKeyName = m_pService->GetName(); if ( NULL == pKeyName ) { Status = STATUS_NO_MEMORY; } else { PLLS_LOCAL_SERVICE_INFO_0 pServiceInfo = NULL; Status = ::LlsLocalServiceInfoGet( pServer->GetLlsHandle(), pKeyName, 0, (LPBYTE *) &pServiceInfo ); if ( NT_SUCCESS( Status ) ) { m_pService->m_lPerServerLimit = pServiceInfo->ConcurrentLimit; ::LlsFreeMemory( pServiceInfo->KeyName ); ::LlsFreeMemory( pServiceInfo->DisplayName ); ::LlsFreeMemory( pServiceInfo->FamilyDisplayName ); ::LlsFreeMemory( pServiceInfo ); } if ( IsConnectionDropped( Status ) ) { pServer->DisconnectLls(); } SysFreeString( pKeyName ); } } else { Status = LlsGetLastStatus(); } LlsSetLastStatus( Status ); if ( !NT_SUCCESS( Status ) ) { theApp.DisplayStatus( Status ); return; // bail... } #endif } } if ( NULL != pszUniNetServerName ) { LocalFree( pszUniNetServerName ); } } if ( NULL != pszUniServerName ) { SysFreeString( pszUniServerName ); } if ( NULL != pszUniProductName ) { SysFreeString( pszUniProductName ); } EndWaitCursor(); m_nLicenses = m_pService->m_lPerServerLimit; UpdateData(FALSE); }