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.
1076 lines
28 KiB
1076 lines
28 KiB
// LCWizPgs.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "resource.h"
|
|
#include "LCWizPgs.h"
|
|
#include "LCWiz.h"
|
|
#include "LCWizSht.h"
|
|
#include <lmaccess.h>
|
|
#include <lmapibuf.h>
|
|
#include <lmerr.h>
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
IMPLEMENT_DYNCREATE(CLicCompWizPage1, CPropertyPage)
|
|
IMPLEMENT_DYNCREATE(CLicCompWizPage3, CPropertyPage)
|
|
IMPLEMENT_DYNCREATE(CLicCompWizPage4, CPropertyPage)
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CLicCompWizPage1 property page
|
|
|
|
CLicCompWizPage1::CLicCompWizPage1() : CPropertyPage(CLicCompWizPage1::IDD)
|
|
{
|
|
//{{AFX_DATA_INIT(CLicCompWizPage1)
|
|
m_nRadio = 0;
|
|
m_strText = _T("");
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
CLicCompWizPage1::~CLicCompWizPage1()
|
|
{
|
|
}
|
|
|
|
void CLicCompWizPage1::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CPropertyPage::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CLicCompWizPage1)
|
|
DDX_Control(pDX, IDC_WELCOME, m_wndWelcome);
|
|
DDX_Radio(pDX, IDC_RADIO_LOCAL_COMPUTER, m_nRadio);
|
|
DDX_Text(pDX, IDC_TEXT, m_strText);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CLicCompWizPage1, CPropertyPage)
|
|
//{{AFX_MSG_MAP(CLicCompWizPage1)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CLicCompWizPage1 property page
|
|
|
|
BOOL CLicCompWizPage1::OnSetActive()
|
|
{
|
|
((CLicCompWizSheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT);
|
|
|
|
return CPropertyPage::OnSetActive();
|
|
}
|
|
|
|
BOOL CLicCompWizPage1::OnInitDialog()
|
|
{
|
|
CPropertyPage::OnInitDialog();
|
|
|
|
m_strText.LoadString(IDS_TEXT_PAGE1);
|
|
|
|
// Get the font for the welcome static control and make the font bold.
|
|
CFont* pFont = m_wndWelcome.GetFont();
|
|
|
|
// Get the default GUI font if GetFont() fails.
|
|
if (pFont == NULL)
|
|
pFont = CFont::FromHandle((HFONT)::GetStockObject(DEFAULT_GUI_FONT));
|
|
|
|
LOGFONT lf;
|
|
|
|
if (pFont != NULL && pFont->GetLogFont(&lf))
|
|
{
|
|
// Add to the font weight to make it bold.
|
|
lf.lfWeight += BOLD_WEIGHT;
|
|
|
|
if (m_fontBold.CreateFontIndirect(&lf))
|
|
{
|
|
// Set the font for the static control.
|
|
m_wndWelcome.SetFont(&m_fontBold);
|
|
}
|
|
}
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
}
|
|
|
|
|
|
LRESULT CLicCompWizPage1::OnWizardNext()
|
|
{
|
|
UpdateData();
|
|
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
CLicCompWizSheet* pSheet = (CLicCompWizSheet*)GetParent();
|
|
|
|
pApp->IsRemote() = m_nRadio;
|
|
|
|
pApp->m_strEnterprise.Empty();
|
|
|
|
if (m_nRadio == 0)
|
|
{
|
|
if (::IsWindow(pSheet->m_Page3.m_hWnd))
|
|
{
|
|
pSheet->m_Page3.GetEnterpriseEdit().SetWindowText(_T(""));
|
|
}
|
|
|
|
return IDD_PROPPAGE4;
|
|
}
|
|
else
|
|
return CPropertyPage::OnWizardNext();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CLicCompWizPage3 property page
|
|
|
|
CLicCompWizPage3::CLicCompWizPage3()
|
|
: CPropertyPage(CLicCompWizPage3::IDD), m_bExpandedOnce(FALSE)
|
|
{
|
|
//{{AFX_DATA_INIT(CLicCompWizPage3)
|
|
//}}AFX_DATA_INIT
|
|
}
|
|
|
|
CLicCompWizPage3::~CLicCompWizPage3()
|
|
{
|
|
}
|
|
|
|
void CLicCompWizPage3::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CPropertyPage::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CLicCompWizPage3)
|
|
DDX_Control(pDX, IDC_TEXT_SELECT_DOMAIN, m_wndTextSelectDomain);
|
|
DDX_Control(pDX, IDC_TEXT_DOMAIN, m_wndTextDomain);
|
|
DDX_Control(pDX, IDC_EDIT_ENTERPRISE, m_wndEnterprise);
|
|
DDX_Control(pDX, IDC_TREE_NETWORK, m_wndTreeNetwork);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CLicCompWizPage3, CPropertyPage)
|
|
//{{AFX_MSG_MAP(CLicCompWizPage3)
|
|
ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_NETWORK, OnSelChangedTree)
|
|
ON_EN_CHANGE(IDC_EDIT_ENTERPRISE, OnChangeEditEnterprise)
|
|
ON_NOTIFY(NM_OUTOFMEMORY, IDC_TREE_NETWORK, OnNetworkTreeOutOfMemory)
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CLicCompWizPage3 message handlers
|
|
|
|
BOOL CLicCompWizPage3::OnSetActive()
|
|
{
|
|
BOOL bReturn = CPropertyPage::OnSetActive();
|
|
|
|
CLicCompWizSheet* pSheet = (CLicCompWizSheet*)GetParent();
|
|
|
|
// Do the default domain expansion only once.
|
|
if (!m_bExpandedOnce)
|
|
{
|
|
m_bExpandedOnce = TRUE;
|
|
m_wndTreeNetwork.PopulateTree();
|
|
}
|
|
|
|
pSheet->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
|
|
|
|
return bReturn;
|
|
}
|
|
|
|
void CLicCompWizPage3::OnSelChangedTree(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
|
|
|
|
ASSERT(pNMTreeView->itemNew.mask & TVIF_PARAM);
|
|
|
|
// Copy the remote name for the selected item into the edit control.
|
|
if (pNMTreeView->itemNew.mask & TVIF_PARAM)
|
|
{
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
|
|
int nImage, nSelectedImage;
|
|
|
|
nImage = nSelectedImage = 0;
|
|
|
|
m_wndTreeNetwork.GetItemImage(m_wndTreeNetwork.GetSelectedItem(), nImage, nSelectedImage);
|
|
|
|
// Set the enterprise name in the App object.
|
|
if (nImage == CNetTreeCtrl::IMG_ROOT)
|
|
pApp->m_strEnterprise.Empty();
|
|
else
|
|
pApp->m_strEnterprise = ((LPNETRESOURCE)pNMTreeView->itemNew.lParam)->lpRemoteName;
|
|
|
|
// Set the text in the edit control.
|
|
m_wndEnterprise.SetWindowText(pApp->m_strEnterprise);
|
|
|
|
// Select the text in the edit control.
|
|
m_wndEnterprise.SetSel(0, -1);
|
|
}
|
|
|
|
*pResult = 0;
|
|
}
|
|
|
|
void CLicCompWizPage3::OnChangeEditEnterprise()
|
|
{
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
|
|
m_wndEnterprise.GetWindowText(pApp->m_strEnterprise);
|
|
}
|
|
|
|
void CLicCompWizPage3::OnNetworkTreeOutOfMemory(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
UNREFERENCED_PARAMETER(pNMHDR);
|
|
|
|
m_wndTreeNetwork.NotifyThread(TRUE);
|
|
|
|
AfxMessageBox(IDS_MEM_ERROR, MB_OK | MB_ICONSTOP);
|
|
|
|
*pResult = 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CLicCompWizPage3 functions
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Global variables
|
|
|
|
extern TCHAR pszLicenseEvent[];
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Static member functions
|
|
|
|
UINT CLicCompWizPage4::GetLicenseInfo(LPVOID pParam)
|
|
{
|
|
// Create an event object to match that in the application object.
|
|
CEvent event(TRUE, TRUE, pszLicenseEvent);
|
|
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
CLicCompWizPage4* pPage = (CLicCompWizPage4*)pParam;
|
|
CLicCompWizSheet* pSheet = (CLicCompWizSheet*)pPage->GetParent();
|
|
CWaitCursor wc;
|
|
NTSTATUS status = STATUS_ACCESS_DENIED;
|
|
|
|
try
|
|
{
|
|
CString strText;
|
|
|
|
// Unsignal the event object.
|
|
event.ResetEvent();
|
|
|
|
// Reset the exit flag.
|
|
pApp->NotifyLicenseThread(FALSE);
|
|
|
|
// Disable the Back and Next buttons while the thread is running.
|
|
pSheet->SetWizardButtons(0);
|
|
|
|
LPBYTE lpbBuf = NULL;
|
|
LLS_HANDLE hLls = NULL;
|
|
DWORD dwTotalEntries, dwResumeHandle;
|
|
|
|
dwTotalEntries = dwResumeHandle = 0;
|
|
|
|
// Save the machine or domain name that the user typed.
|
|
CString strFocus = pApp->m_strEnterprise;
|
|
|
|
// Display a message indicating what the wizard is doing.
|
|
strText.LoadString(IDS_WORKING);
|
|
pPage->m_wndUnlicensedProducts.SetWindowText(strText);
|
|
strText.Empty(); // Avoids a memory leak.
|
|
|
|
// Connect to the license server.
|
|
status = ::LlsConnectEnterprise(const_cast<LPTSTR>((LPCTSTR)pApp->m_strEnterprise),
|
|
&hLls, 0, &lpbBuf);
|
|
|
|
if (NT_ERROR(status))
|
|
goto ErrorMessage;
|
|
|
|
// It's OK for the user to click the Back button now, so enable it.
|
|
pSheet->SetWizardButtons(PSWIZB_BACK);
|
|
|
|
if (lpbBuf != NULL)
|
|
{
|
|
PLLS_CONNECT_INFO_0 pllsci = (PLLS_CONNECT_INFO_0)lpbBuf;
|
|
|
|
// Reset the domain and enterprise server names.
|
|
pApp->m_strDomain = pllsci->Domain;
|
|
pApp->m_strEnterpriseServer = pllsci->EnterpriseServer;
|
|
|
|
// Free embedded pointers
|
|
//::LlsFreeMemory(pllsci->Domain);
|
|
//::LlsFreeMemory(pllsci->EnterpriseServer);
|
|
|
|
// Free memory allocated by the LLS API.
|
|
status = ::LlsFreeMemory(lpbBuf);
|
|
lpbBuf = NULL;
|
|
}
|
|
|
|
if (NT_SUCCESS(status))
|
|
{
|
|
// Display a message indicating what the wizard is doing.
|
|
strText.LoadString(IDS_ENUM_PRODUCTS);
|
|
pPage->m_wndUnlicensedProducts.SetWindowText(strText);
|
|
strText.Empty(); // Avoids a memory leak.
|
|
|
|
USHORT nProductCount = 0;
|
|
DWORD dwEntriesRead, dwTotalEntriesRead;
|
|
|
|
dwEntriesRead = dwTotalEntriesRead = 0;
|
|
|
|
// Build a list of all the products.
|
|
do
|
|
{
|
|
// Check the exit thread flag. The user may have clicked the Back button.
|
|
if (pApp->m_bExitLicenseThread)
|
|
goto ExitThread;
|
|
|
|
status = ::LlsProductEnum(hLls, 1, &lpbBuf, CLicCompWizPage4::LLS_PREFERRED_LENGTH,
|
|
&dwEntriesRead, &dwTotalEntries, &dwResumeHandle);
|
|
|
|
if (!NT_SUCCESS(status))
|
|
goto ErrorMessage;
|
|
|
|
dwTotalEntriesRead += dwEntriesRead;
|
|
|
|
PLLS_PRODUCT_INFO_1 pllspi = (PLLS_PRODUCT_INFO_1)lpbBuf;
|
|
|
|
while (dwEntriesRead--)
|
|
{
|
|
// Check the exit thread flag. The user may have clicked the Back button.
|
|
if (pApp->m_bExitLicenseThread)
|
|
goto ExitThread;
|
|
|
|
if ((LONG)pllspi->InUse > (LONG)pllspi->Purchased)
|
|
{
|
|
pPage->FillListCtrl(pllspi->Product, (WORD)pllspi->InUse, (WORD)pllspi->Purchased);
|
|
|
|
// Increment the unlicensed products counter.
|
|
nProductCount++;
|
|
}
|
|
|
|
// Free embedded pointer.
|
|
::LlsFreeMemory(pllspi->Product);
|
|
|
|
pllspi++;
|
|
}
|
|
|
|
// Free memory allocated by the LLS API.
|
|
status = ::LlsFreeMemory(lpbBuf);
|
|
lpbBuf = NULL;
|
|
|
|
ASSERT(NT_SUCCESS(status));
|
|
}
|
|
while (dwTotalEntries);
|
|
|
|
// Close the LLS handle.
|
|
status = ::LlsClose(hLls);
|
|
|
|
// Check the exit thread flag. The user may have clicked the Back button.
|
|
if (pApp->m_bExitLicenseThread)
|
|
goto ExitThread;
|
|
|
|
ASSERT(NT_SUCCESS(status));
|
|
|
|
// Show the user how many unlicensed products were found.
|
|
if (nProductCount)
|
|
{
|
|
strText.Format(IDS_UNLICENSED_PRODUCTS, pApp->m_strEnterpriseServer);
|
|
pPage->m_wndUnlicensedProducts.SetWindowText(strText);
|
|
|
|
// Make the static text box the appropriate size.
|
|
pPage->m_wndUnlicensedProducts.SetWindowPos(&CWnd::wndTop, 0, 0,
|
|
pPage->m_sizeSmallText.cx,
|
|
pPage->m_sizeSmallText.cy,
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
|
|
|
// Make sure the list control is visible.
|
|
pPage->m_wndProductList.ShowWindow(SW_SHOW);
|
|
|
|
// Make sure the print button is visible.
|
|
pPage->m_wndPrint.ShowWindow(SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
// Make the static text box the appropriate size.
|
|
pPage->m_wndUnlicensedProducts.SetWindowPos(&CWnd::wndTop, 0, 0,
|
|
pPage->m_sizeLargeText.cx,
|
|
pPage->m_sizeLargeText.cy,
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
|
|
|
// Display a message if no unlicensed products were found.
|
|
strText.LoadString(IDS_NO_UNLICENSED_PRODUCTS);
|
|
pPage->m_wndUnlicensedProducts.SetWindowText(strText);
|
|
}
|
|
|
|
// Enable the Back button.
|
|
pSheet->SetWizardButtons(PSWIZB_BACK);
|
|
|
|
CString strFinished;
|
|
CButton* pCancel = (CButton*)pSheet->GetDlgItem(IDCANCEL);
|
|
|
|
// Change the text on the cancel button to "Done."
|
|
strFinished.LoadString(IDS_DONE);
|
|
pCancel->SetWindowText(strFinished);
|
|
|
|
// Signal the event object.
|
|
event.SetEvent();
|
|
|
|
// Reset the pointer to the license thread.
|
|
pApp->m_pLicenseThread = NULL;
|
|
|
|
// Restore the normal cursor.
|
|
pPage->PostMessage(WM_SETCURSOR);
|
|
}
|
|
|
|
return 0;
|
|
|
|
ErrorMessage:
|
|
// Check the exit thread flag. The user may have clicked the Back button.
|
|
if (pApp->m_bExitLicenseThread)
|
|
goto ExitThread;
|
|
|
|
// Make the static text box the appropriate size.
|
|
pPage->m_wndUnlicensedProducts.SetWindowPos(&CWnd::wndTop, 0, 0,
|
|
pPage->m_sizeLargeText.cx,
|
|
pPage->m_sizeLargeText.cy,
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
|
|
|
// Create an error message based on the return value from LlsConnectEnterprise().
|
|
switch (status)
|
|
{
|
|
case STATUS_NO_SUCH_DOMAIN:
|
|
if (pApp->IsRemote())
|
|
strText.Format(IDS_BAD_DOMAIN_NAME, strFocus);
|
|
else
|
|
strText.LoadString(IDS_UNAVAILABLE);
|
|
break;
|
|
|
|
case STATUS_ACCESS_DENIED:
|
|
if (pApp->IsRemote())
|
|
strText.Format(IDS_ACCESS_DENIED, strFocus);
|
|
else
|
|
strText.LoadString(IDS_LOCAL_ACCESS_DENIED);
|
|
break;
|
|
|
|
case RPC_NT_SERVER_UNAVAILABLE:
|
|
strText.Format(IDS_SERVER_UNAVAILABLE);
|
|
break;
|
|
|
|
default:
|
|
if (pApp->IsRemote())
|
|
strText.Format(IDS_NO_LICENSE_INFO_REMOTE, strFocus);
|
|
else
|
|
strText.LoadString(IDS_NO_LICENSE_INFO_LOCAL);
|
|
}
|
|
|
|
// Display an error message if LlsProductEnum() fails.
|
|
pPage->m_wndUnlicensedProducts.SetWindowText(strText);
|
|
|
|
// Enable the Back button.
|
|
pSheet->SetWizardButtons(PSWIZB_BACK);
|
|
|
|
// Signal the event object.
|
|
event.SetEvent();
|
|
|
|
// Reset the pointer to the license thread.
|
|
pApp->m_pLicenseThread = NULL;
|
|
|
|
// Restore the normal cursor.
|
|
pPage->PostMessage(WM_SETCURSOR);
|
|
|
|
return 1;
|
|
|
|
ExitThread:
|
|
// Signal the event object.
|
|
event.SetEvent();
|
|
|
|
// Reset the pointer to the license thread.
|
|
pApp->m_pLicenseThread = NULL;
|
|
|
|
return 2;
|
|
}
|
|
catch(...)
|
|
{
|
|
// Signal the event object.
|
|
event.SetEvent();
|
|
|
|
CString strText;
|
|
|
|
// Display an error message.
|
|
strText.LoadString(IDS_GENERIC_ERROR);
|
|
pPage->m_wndUnlicensedProducts.SetWindowText(strText);
|
|
|
|
// Reset the pointer to the license thread.
|
|
pApp->m_pLicenseThread = NULL;
|
|
|
|
// Restore the normal cursor.
|
|
pPage->PostMessage(WM_SETCURSOR);
|
|
|
|
return 3;
|
|
}
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CLicCompWizPage4 property page
|
|
|
|
CLicCompWizPage4::CLicCompWizPage4()
|
|
: CPropertyPage(CLicCompWizPage4::IDD), m_ptPrint(0, 0), m_nHorzMargin(0),
|
|
m_nVertMargin(0),m_ptOrg(0, 0), m_ptExt(0, 0), m_sizeSmallText(0, 0),
|
|
m_sizeLargeText(0, 0)
|
|
{
|
|
//{{AFX_DATA_INIT(CLicCompWizPage4)
|
|
//}}AFX_DATA_INIT
|
|
|
|
m_strCancel.Empty();
|
|
m_pTabs = new INT[PRINT_COLUMNS];
|
|
}
|
|
|
|
CLicCompWizPage4::~CLicCompWizPage4()
|
|
{
|
|
if (m_pTabs != NULL)
|
|
delete[] m_pTabs;
|
|
}
|
|
|
|
void CLicCompWizPage4::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CPropertyPage::DoDataExchange(pDX);
|
|
//{{AFX_DATA_MAP(CLicCompWizPage4)
|
|
DDX_Control(pDX, IDC_FLAG_BMP, m_wndPicture);
|
|
DDX_Control(pDX, IDC_BUT_PRINT, m_wndPrint);
|
|
DDX_Control(pDX, IDC_TEXT_UNCOMP_PRODUCTS, m_wndUnlicensedProducts);
|
|
DDX_Control(pDX, IDC_LIST_PRODUCTS, m_wndProductList);
|
|
//}}AFX_DATA_MAP
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CLicCompWizPage4, CPropertyPage)
|
|
//{{AFX_MSG_MAP(CLicCompWizPage4)
|
|
ON_BN_CLICKED(IDC_BUT_PRINT, OnPrintButton)
|
|
ON_NOTIFY(NM_OUTOFMEMORY, IDC_LIST_PRODUCTS, OnListProductsOutOfMemory)
|
|
ON_WM_DESTROY()
|
|
ON_WM_SETCURSOR()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
void CLicCompWizPage4::PumpMessages()
|
|
{
|
|
// Must call Create() before using the dialog
|
|
ASSERT(m_hWnd!=NULL);
|
|
|
|
MSG msg;
|
|
|
|
try
|
|
{
|
|
// Handle dialog messages
|
|
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
if(!IsDialogMessage(&msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
}
|
|
catch(...)
|
|
{
|
|
TRACE(_T("Exception in CLicCompWizPage4::PumpMessages()\n"));
|
|
}
|
|
|
|
}
|
|
|
|
BOOL CLicCompWizPage4::FillListCtrl(LPTSTR pszProduct, WORD wInUse, WORD wPurchased)
|
|
{
|
|
TCHAR pszLicenses[BUFFER_SIZE];
|
|
|
|
::wsprintf(pszLicenses, _T("%u"), wInUse - wPurchased);
|
|
|
|
USHORT nIndex;
|
|
LV_ITEM lvi;
|
|
|
|
lvi.mask = LVIF_TEXT | LVIF_PARAM;
|
|
lvi.iItem = 0;
|
|
lvi.iSubItem = 0;
|
|
lvi.lParam = MAKELONG(wInUse, wPurchased);
|
|
lvi.pszText = pszProduct;
|
|
|
|
if ((nIndex = (USHORT)m_wndProductList.InsertItem(&lvi)) != (USHORT)-1)
|
|
{
|
|
m_wndProductList.SetItemText(nIndex, 1, pszLicenses);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CLicCompWizPage4::OnInitDialog()
|
|
{
|
|
CPropertyPage::OnInitDialog();
|
|
|
|
// Set the header text for the list control.
|
|
CRect rcList;
|
|
|
|
m_wndProductList.GetWindowRect(&rcList);
|
|
|
|
CString strColumnTitle;
|
|
LV_COLUMN lvc;
|
|
|
|
lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
|
|
USHORT nColumns = COLUMNS;
|
|
UINT uStringID[COLUMNS] = {IDS_PRODUCTS_LIST, IDS_LICENSES_LIST};
|
|
|
|
for (USHORT i = 0; i < nColumns; i++)
|
|
{
|
|
strColumnTitle.LoadString(uStringID[i]);
|
|
lvc.pszText = strColumnTitle.GetBuffer(strColumnTitle.GetLength());
|
|
lvc.cx = rcList.Width() / COLUMNS;
|
|
|
|
m_wndProductList.InsertColumn(i, &lvc);
|
|
|
|
strColumnTitle.ReleaseBuffer();
|
|
}
|
|
|
|
CLicCompWizSheet* pSheet = (CLicCompWizSheet*)GetParent();
|
|
|
|
// Store the text on the cancel button.
|
|
CButton* pCancel = (CButton*)pSheet->GetDlgItem(IDCANCEL);
|
|
pCancel->GetWindowText(m_strCancel);
|
|
|
|
CRect rcText;
|
|
|
|
// Create the large and small extents for the static text control.
|
|
m_wndUnlicensedProducts.GetWindowRect(&rcText);
|
|
|
|
m_sizeSmallText.cx = rcText.right - rcText.left;
|
|
m_sizeSmallText.cy = rcText.bottom - rcText.top;
|
|
|
|
// Make the large extents match those for the list control.
|
|
m_sizeLargeText.cx = rcList.right - rcList.left;
|
|
m_sizeLargeText.cy = rcList.bottom - rcList.top;
|
|
|
|
return TRUE; // return TRUE unless you set the focus to a control
|
|
// EXCEPTION: OCX Property Pages should return FALSE
|
|
}
|
|
|
|
void CLicCompWizPage4::OnListProductsOutOfMemory(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
UNREFERENCED_PARAMETER(pNMHDR);
|
|
|
|
AfxMessageBox(IDS_MEM_ERROR, MB_OK | MB_ICONSTOP);
|
|
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
|
|
// Let the license thread know it's supposed to quit.
|
|
pApp->NotifyLicenseThread(TRUE);
|
|
|
|
*pResult = 0;
|
|
}
|
|
|
|
void CLicCompWizPage4::OnPrintButton()
|
|
{
|
|
CDC dc;
|
|
CPrintDialog dlg(FALSE,
|
|
PD_ALLPAGES | PD_USEDEVMODECOPIESANDCOLLATE |
|
|
PD_NOPAGENUMS | PD_HIDEPRINTTOFILE |
|
|
PD_NOSELECTION,
|
|
this);
|
|
|
|
if (dlg.DoModal() == IDOK)
|
|
{
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
m_wndPrint.RedrawWindow();
|
|
|
|
DOCINFO di;
|
|
CString strDocName;
|
|
|
|
strDocName.Format(IDS_DOC_NAME, pApp->m_strEnterpriseServer);
|
|
|
|
di.cbSize = sizeof(DOCINFO);
|
|
di.lpszDocName = strDocName.GetBuffer(BUFFER_SIZE);
|
|
di.lpszOutput = NULL;
|
|
|
|
if (dc.Attach(dlg.GetPrinterDC()))
|
|
{
|
|
PrepareForPrinting(dc);
|
|
dc.StartDoc(&di);
|
|
PrintReport(dc);
|
|
dc.EndDoc();
|
|
dc.DeleteDC();
|
|
::GlobalFree(dlg.m_pd.hDevNames);
|
|
::GlobalFree(dlg.m_pd.hDevMode);
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CLicCompWizPage4::PrepareForPrinting(CDC& dc)
|
|
{
|
|
// Create various fonts...
|
|
CString strFont;
|
|
|
|
// Create a heading font.
|
|
strFont.LoadString(IDS_FONT_BOLD);
|
|
m_fontHeading.CreatePointFont(FONT_SIZE_HEADING, strFont, &dc);
|
|
|
|
// Create a bold, underlined header font.
|
|
strFont.LoadString(IDS_FONT_BOLD);
|
|
m_fontHeader.CreatePointFont(FONT_SIZE, strFont, &dc);
|
|
|
|
LOGFONT lf;
|
|
m_fontHeader.GetLogFont(&lf);
|
|
m_fontHeader.DeleteObject();
|
|
lf.lfUnderline = TRUE;
|
|
m_fontHeader.CreateFontIndirect(&lf);
|
|
|
|
// Create a footer font.
|
|
strFont.LoadString(IDS_FONT_BOLD);
|
|
m_fontFooter.CreatePointFont(FONT_SIZE_FOOTER, strFont, &dc);
|
|
|
|
// Create a default font.
|
|
strFont.LoadString(IDS_FONT);
|
|
m_fontNormal.CreatePointFont(FONT_SIZE, strFont, &dc);
|
|
|
|
// Get the text metrics for each font.
|
|
CFont* pOldFont = dc.SelectObject(&m_fontHeading);
|
|
dc.GetTextMetrics(&m_tmHeading);
|
|
|
|
dc.SelectObject(&m_fontHeader);
|
|
dc.GetTextMetrics(&m_tmHeader);
|
|
|
|
dc.SelectObject(&m_fontFooter);
|
|
dc.GetTextMetrics(&m_tmFooter);
|
|
|
|
dc.SelectObject(&m_fontNormal);
|
|
dc.GetTextMetrics(&m_tmNormal);
|
|
|
|
// Select the original font back in to the device context.
|
|
dc.SelectObject(pOldFont);
|
|
|
|
// Set the horizontal and vertical margins.
|
|
m_nHorzMargin = (LONG)(dc.GetDeviceCaps(LOGPIXELSX) * HORZ_MARGIN);
|
|
m_nVertMargin = (LONG)(dc.GetDeviceCaps(LOGPIXELSY) * VERT_MARGIN);
|
|
|
|
// Get the printable page offsets for the origin.
|
|
m_ptOrg.x = dc.GetDeviceCaps(PHYSICALOFFSETX);
|
|
m_ptOrg.y = dc.GetDeviceCaps(PHYSICALOFFSETY);
|
|
|
|
dc.SetWindowOrg(m_ptOrg);
|
|
|
|
m_ptOrg.x += m_nHorzMargin;
|
|
m_ptOrg.y += m_nVertMargin;
|
|
|
|
// Get the printable page offsets for the page extents.
|
|
m_ptExt.x = dc.GetDeviceCaps(PHYSICALWIDTH) - m_ptOrg.x;
|
|
m_ptExt.y = dc.GetDeviceCaps(PHYSICALHEIGHT) - m_ptOrg.y;
|
|
|
|
dc.SetViewportOrg(m_ptOrg);
|
|
|
|
CalculateTabs(dc);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CLicCompWizPage4::PrintReport(CDC& dc)
|
|
{
|
|
// Set the starting point for printing.
|
|
m_ptPrint.x = m_ptPrint.y = 0;
|
|
|
|
// Prepare to print a heading.
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
CString strHeading;
|
|
|
|
CFont* pOldFont = dc.SelectObject(&m_fontHeading);
|
|
strHeading.Format(IDS_DOC_NAME, pApp->m_strEnterpriseServer);
|
|
|
|
dc.StartPage();
|
|
|
|
CRect rc(m_ptPrint.x, m_ptPrint.y, m_ptExt.x - m_ptOrg.x, m_tmHeading.tmHeight);
|
|
|
|
// Calculate the size of the rectangle needed to draw the text.
|
|
m_ptPrint.y += dc.DrawText(strHeading, &rc, DT_EXTERNALLEADING | DT_CENTER | DT_WORDBREAK | DT_NOCLIP);
|
|
|
|
// Normalize the rectangle.
|
|
rc.NormalizeRect();
|
|
|
|
// Add a blank line below the heading.
|
|
m_ptPrint.y += m_tmHeading.tmHeight;
|
|
|
|
// Move the right side of the rectangle out to the right margin so text is properly centered.
|
|
rc.right = m_ptExt.x - m_ptOrg.x;
|
|
|
|
// Draw the text in the rectangle.
|
|
dc.DrawText(strHeading, &rc, DT_EXTERNALLEADING | DT_CENTER | DT_WORDBREAK | DT_NOCLIP);
|
|
|
|
dc.SelectObject(pOldFont);
|
|
|
|
PrintPages(dc, 100);
|
|
|
|
// Delete the fonts.
|
|
m_fontNormal.DeleteObject();
|
|
m_fontHeader.DeleteObject();
|
|
m_fontFooter.DeleteObject();
|
|
m_fontHeading.DeleteObject();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CLicCompWizPage4::PrintPageHeader(CDC& dc)
|
|
{
|
|
CFont* pOldFont = dc.SelectObject(&m_fontHeader);
|
|
|
|
dc.StartPage();
|
|
|
|
CString strHeader, strProducts, strLicenses, strPurchased, strUsed;
|
|
strProducts.LoadString(IDS_PRODUCTS);
|
|
strLicenses.LoadString(IDS_LICENSES);
|
|
strPurchased.LoadString(IDS_PURCHASED);
|
|
strUsed.LoadString(IDS_USED);
|
|
strHeader.Format(_T("%s\t%s\t%s\t%s"), strProducts, strLicenses,
|
|
strPurchased, strUsed);
|
|
|
|
dc.TabbedTextOut(m_ptPrint.x, m_ptPrint.y, strHeader, PRINT_COLUMNS, m_pTabs, 0);
|
|
|
|
m_ptPrint.y += ((m_tmHeader.tmHeight + m_tmHeader.tmExternalLeading) * 2);
|
|
|
|
dc.SelectObject(pOldFont);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CLicCompWizPage4::PrintPageFooter(CDC& dc, USHORT nPage)
|
|
{
|
|
CFont* pOldFont = dc.SelectObject(&m_fontFooter);
|
|
|
|
CString strFooter;
|
|
CTime time(CTime::GetCurrentTime());
|
|
|
|
strFooter.Format(IDS_PAGE_DATE, nPage, time.Format(IDS_FMT_DATE));
|
|
|
|
CRect rc(m_ptPrint.x, m_ptExt.y - m_nVertMargin, m_ptOrg.x, m_tmFooter.tmHeight);
|
|
|
|
// Calculate the size of the rectangle needed to draw the text.
|
|
m_ptPrint.y += dc.DrawText(strFooter, &rc, DT_CALCRECT | DT_EXTERNALLEADING | DT_CENTER | DT_WORDBREAK | DT_NOCLIP);
|
|
|
|
// Move the right side of the rectangle out to the right margin so text is properly centered.
|
|
rc.right = m_ptExt.x - m_ptOrg.x;
|
|
|
|
// Draw the text in the rectangle.
|
|
dc.DrawText(strFooter, &rc, DT_EXTERNALLEADING | DT_CENTER | DT_WORDBREAK | DT_NOCLIP);
|
|
|
|
dc.EndPage();
|
|
|
|
dc.SelectObject(pOldFont);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CLicCompWizPage4::PrintPages(CDC& dc, UINT nStart)
|
|
{
|
|
CFont* pOldFont = dc.SelectObject(&m_fontNormal);
|
|
|
|
UNREFERENCED_PARAMETER(nStart);
|
|
|
|
USHORT nPage = 1;
|
|
UINT nItems = m_wndProductList.GetItemCount();
|
|
|
|
// Print the initial header.
|
|
PrintPageHeader(dc);
|
|
|
|
DWORD dwParam = 0;
|
|
CString strTextOut;
|
|
|
|
for (UINT i = 0; i < nItems; i++)
|
|
{
|
|
dwParam = (DWORD)m_wndProductList.GetItemData(i);
|
|
|
|
CString strProduct = m_wndProductList.GetItemText(i, 0);
|
|
|
|
CSize sizeProduct = dc.GetTextExtent(strProduct);
|
|
|
|
if (sizeProduct.cx > m_pTabs[0] - (m_tmNormal.tmAveCharWidth * TAB_WIDTH))
|
|
TruncateText(dc, strProduct);
|
|
|
|
// Format the output text.
|
|
strTextOut.Format(_T("%s\t%s\t%u\t%u"), strProduct,
|
|
m_wndProductList.GetItemText(i, 1),
|
|
HIWORD(dwParam), LOWORD(dwParam));
|
|
|
|
dc.TabbedTextOut(m_ptPrint.x, m_ptPrint.y, strTextOut, PRINT_COLUMNS, m_pTabs, 0);
|
|
|
|
// Calculate the vertical position for the next line of text.
|
|
m_ptPrint.y += m_tmNormal.tmHeight + m_tmNormal.tmExternalLeading;
|
|
|
|
if ((m_ptPrint.y + m_ptOrg.y) >= m_ptExt.y)
|
|
{
|
|
PrintPageFooter(dc, nPage++);
|
|
|
|
// Reset the printing position.
|
|
m_ptPrint.y = 0;
|
|
|
|
PrintPageHeader(dc);
|
|
}
|
|
}
|
|
|
|
// Print the final footer.
|
|
PrintPageFooter(dc, (USHORT)nPage);
|
|
|
|
dc.SelectObject(pOldFont);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CLicCompWizPage4::TruncateText(CDC& dc, CString& strInput)
|
|
{
|
|
CString strText, strEllipsis;
|
|
|
|
USHORT nLen, nChars = 0;
|
|
UINT nMaxWidth = m_pTabs[0] - (m_tmNormal.tmAveCharWidth * TAB_WIDTH);
|
|
nLen = (USHORT)strInput.GetLength();
|
|
|
|
strEllipsis.LoadString(IDS_ELLIPSIS);
|
|
|
|
CSize sizeText = dc.GetTextExtent(strInput);
|
|
|
|
// Keep lopping off characters until the string is short enough.
|
|
while ((UINT)sizeText.cx > nMaxWidth)
|
|
{
|
|
strText = strInput.Left(nLen - nChars++);
|
|
sizeText = dc.GetTextExtent(strText);
|
|
}
|
|
|
|
// Remove the last characters and replace them with an ellipsis.
|
|
ASSERT(strText.GetLength() > strEllipsis.GetLength());
|
|
strInput = strText.Left(strText.GetLength() - strEllipsis.GetLength()) + strEllipsis;
|
|
}
|
|
|
|
BOOL CLicCompWizPage4::CalculateTabs(CDC& dc)
|
|
{
|
|
INT nTotalExt = 0;
|
|
INT nTabSize = TAB_WIDTH * m_tmHeader.tmAveCharWidth;
|
|
|
|
UINT uStrIds[] = {IDS_LICENSES, IDS_PURCHASED, IDS_USED};
|
|
|
|
m_pTabs[0] = 0;
|
|
|
|
for (USHORT i = 1; i < PRINT_COLUMNS; i++)
|
|
{
|
|
CString strText;
|
|
|
|
strText.LoadString(uStrIds[i - 1]);
|
|
// Get the text extent for each string.
|
|
m_pTabs[i] = dc.GetTextExtent(strText).cx;
|
|
// Keep a running total of the extents.
|
|
nTotalExt += m_pTabs[i];
|
|
}
|
|
|
|
// Add tab space between columns.
|
|
nTotalExt += nTabSize * (PRINT_COLUMNS - 2);
|
|
|
|
// The second column will begin at the difference between the right
|
|
// margin and the total extent.
|
|
m_pTabs[0] = m_ptExt.x - m_ptOrg.x - nTotalExt;
|
|
|
|
// Now set the actual tab positions in the array.
|
|
for (i = 1; i < PRINT_COLUMNS; i++)
|
|
{
|
|
m_pTabs[i] += m_pTabs[i - 1] + nTabSize;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LRESULT CLicCompWizPage4::OnWizardBack()
|
|
{
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
|
|
// Let the license thread know it's time to quit.
|
|
pApp->NotifyLicenseThread(TRUE);
|
|
|
|
CLicCompWizSheet* pSheet = (CLicCompWizSheet*)GetParent();
|
|
|
|
// Set the cancel button text back to "Cancel."
|
|
CButton* pCancel = (CButton*)pSheet->GetDlgItem(IDCANCEL);
|
|
pCancel->SetWindowText(m_strCancel);
|
|
|
|
if (pSheet->m_Page1.m_nRadio == 0)
|
|
return IDD_PROPPAGE1;
|
|
else
|
|
return CPropertyPage::OnWizardBack();
|
|
}
|
|
|
|
void CLicCompWizPage4::OnDestroy()
|
|
{
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
|
|
pApp->NotifyLicenseThread(TRUE);
|
|
PumpMessages();
|
|
|
|
CPropertyPage::OnDestroy();
|
|
}
|
|
|
|
BOOL CLicCompWizPage4::OnSetActive()
|
|
{
|
|
CLicCompWizSheet* pSheet = (CLicCompWizSheet*)GetParent();
|
|
|
|
pSheet->SetWizardButtons(PSWIZB_BACK);
|
|
|
|
// Hide the list control and clear it.
|
|
m_wndProductList.ShowWindow(SW_HIDE);
|
|
m_wndProductList.DeleteAllItems();
|
|
|
|
// Hide the print button.
|
|
m_wndPrint.ShowWindow(SW_HIDE);
|
|
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
|
|
// Make sure the last thread has terminated before starting a new one.
|
|
if (pApp->m_pLicenseThread != NULL)
|
|
{
|
|
pApp->NotifyLicenseThread(TRUE);
|
|
|
|
CEvent event(TRUE, TRUE, pszLicenseEvent);
|
|
CSingleLock lock(&event);
|
|
|
|
lock.Lock();
|
|
}
|
|
|
|
// Keep a pointer to the thread so we can find out if it's still running.
|
|
pApp->m_pLicenseThread = AfxBeginThread((AFX_THREADPROC)GetLicenseInfo, (LPVOID)this);
|
|
|
|
return CPropertyPage::OnSetActive();
|
|
}
|
|
|
|
LRESULT CLicCompWizPage3::OnWizardNext()
|
|
{
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
|
|
m_wndEnterprise.GetWindowText(pApp->m_strEnterprise);
|
|
|
|
// Trim off any white space in the enterprise name.
|
|
pApp->m_strEnterprise.TrimLeft();
|
|
pApp->m_strEnterprise.TrimRight();
|
|
|
|
if (pApp->m_strEnterprise.IsEmpty() ||
|
|
pApp->m_strEnterprise.Find(_T("\\\\")) != -1)
|
|
{
|
|
AfxMessageBox(IDS_SPECIFY_DOMAIN, MB_OK | MB_ICONEXCLAMATION);
|
|
return IDD;
|
|
}
|
|
|
|
return CPropertyPage::OnWizardNext();
|
|
}
|
|
|
|
BOOL CLicCompWizPage4::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
{
|
|
CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
|
|
|
|
if (pApp->m_pLicenseThread == NULL)
|
|
{
|
|
return CPropertyPage::OnSetCursor(pWnd, nHitTest, message);
|
|
}
|
|
else
|
|
{
|
|
// Restore the wait cursor if the thread is running.
|
|
RestoreWaitCursor();
|
|
|
|
return TRUE;
|
|
}
|
|
}
|