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.

1076 lines
28 KiB

  1. // LCWizPgs.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "resource.h"
  5. #include "LCWizPgs.h"
  6. #include "LCWiz.h"
  7. #include "LCWizSht.h"
  8. #include <lmaccess.h>
  9. #include <lmapibuf.h>
  10. #include <lmerr.h>
  11. #ifdef _DEBUG
  12. #undef THIS_FILE
  13. static char BASED_CODE THIS_FILE[] = __FILE__;
  14. #endif
  15. IMPLEMENT_DYNCREATE(CLicCompWizPage1, CPropertyPage)
  16. IMPLEMENT_DYNCREATE(CLicCompWizPage3, CPropertyPage)
  17. IMPLEMENT_DYNCREATE(CLicCompWizPage4, CPropertyPage)
  18. /////////////////////////////////////////////////////////////////////////////
  19. // CLicCompWizPage1 property page
  20. CLicCompWizPage1::CLicCompWizPage1() : CPropertyPage(CLicCompWizPage1::IDD)
  21. {
  22. //{{AFX_DATA_INIT(CLicCompWizPage1)
  23. m_nRadio = 0;
  24. m_strText = _T("");
  25. //}}AFX_DATA_INIT
  26. }
  27. CLicCompWizPage1::~CLicCompWizPage1()
  28. {
  29. }
  30. void CLicCompWizPage1::DoDataExchange(CDataExchange* pDX)
  31. {
  32. CPropertyPage::DoDataExchange(pDX);
  33. //{{AFX_DATA_MAP(CLicCompWizPage1)
  34. DDX_Control(pDX, IDC_WELCOME, m_wndWelcome);
  35. DDX_Radio(pDX, IDC_RADIO_LOCAL_COMPUTER, m_nRadio);
  36. DDX_Text(pDX, IDC_TEXT, m_strText);
  37. //}}AFX_DATA_MAP
  38. }
  39. BEGIN_MESSAGE_MAP(CLicCompWizPage1, CPropertyPage)
  40. //{{AFX_MSG_MAP(CLicCompWizPage1)
  41. //}}AFX_MSG_MAP
  42. END_MESSAGE_MAP()
  43. /////////////////////////////////////////////////////////////////////////////
  44. // CLicCompWizPage1 property page
  45. BOOL CLicCompWizPage1::OnSetActive()
  46. {
  47. ((CLicCompWizSheet*)GetParent())->SetWizardButtons(PSWIZB_NEXT);
  48. return CPropertyPage::OnSetActive();
  49. }
  50. BOOL CLicCompWizPage1::OnInitDialog()
  51. {
  52. CPropertyPage::OnInitDialog();
  53. m_strText.LoadString(IDS_TEXT_PAGE1);
  54. // Get the font for the welcome static control and make the font bold.
  55. CFont* pFont = m_wndWelcome.GetFont();
  56. // Get the default GUI font if GetFont() fails.
  57. if (pFont == NULL)
  58. pFont = CFont::FromHandle((HFONT)::GetStockObject(DEFAULT_GUI_FONT));
  59. LOGFONT lf;
  60. if (pFont != NULL && pFont->GetLogFont(&lf))
  61. {
  62. // Add to the font weight to make it bold.
  63. lf.lfWeight += BOLD_WEIGHT;
  64. if (m_fontBold.CreateFontIndirect(&lf))
  65. {
  66. // Set the font for the static control.
  67. m_wndWelcome.SetFont(&m_fontBold);
  68. }
  69. }
  70. return TRUE; // return TRUE unless you set the focus to a control
  71. // EXCEPTION: OCX Property Pages should return FALSE
  72. }
  73. LRESULT CLicCompWizPage1::OnWizardNext()
  74. {
  75. UpdateData();
  76. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  77. CLicCompWizSheet* pSheet = (CLicCompWizSheet*)GetParent();
  78. pApp->IsRemote() = m_nRadio;
  79. pApp->m_strEnterprise.Empty();
  80. if (m_nRadio == 0)
  81. {
  82. if (::IsWindow(pSheet->m_Page3.m_hWnd))
  83. {
  84. pSheet->m_Page3.GetEnterpriseEdit().SetWindowText(_T(""));
  85. }
  86. return IDD_PROPPAGE4;
  87. }
  88. else
  89. return CPropertyPage::OnWizardNext();
  90. }
  91. /////////////////////////////////////////////////////////////////////////////
  92. // CLicCompWizPage3 property page
  93. CLicCompWizPage3::CLicCompWizPage3()
  94. : CPropertyPage(CLicCompWizPage3::IDD), m_bExpandedOnce(FALSE)
  95. {
  96. //{{AFX_DATA_INIT(CLicCompWizPage3)
  97. //}}AFX_DATA_INIT
  98. }
  99. CLicCompWizPage3::~CLicCompWizPage3()
  100. {
  101. }
  102. void CLicCompWizPage3::DoDataExchange(CDataExchange* pDX)
  103. {
  104. CPropertyPage::DoDataExchange(pDX);
  105. //{{AFX_DATA_MAP(CLicCompWizPage3)
  106. DDX_Control(pDX, IDC_TEXT_SELECT_DOMAIN, m_wndTextSelectDomain);
  107. DDX_Control(pDX, IDC_TEXT_DOMAIN, m_wndTextDomain);
  108. DDX_Control(pDX, IDC_EDIT_ENTERPRISE, m_wndEnterprise);
  109. DDX_Control(pDX, IDC_TREE_NETWORK, m_wndTreeNetwork);
  110. //}}AFX_DATA_MAP
  111. }
  112. BEGIN_MESSAGE_MAP(CLicCompWizPage3, CPropertyPage)
  113. //{{AFX_MSG_MAP(CLicCompWizPage3)
  114. ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_NETWORK, OnSelChangedTree)
  115. ON_EN_CHANGE(IDC_EDIT_ENTERPRISE, OnChangeEditEnterprise)
  116. ON_NOTIFY(NM_OUTOFMEMORY, IDC_TREE_NETWORK, OnNetworkTreeOutOfMemory)
  117. //}}AFX_MSG_MAP
  118. END_MESSAGE_MAP()
  119. /////////////////////////////////////////////////////////////////////////////
  120. // CLicCompWizPage3 message handlers
  121. BOOL CLicCompWizPage3::OnSetActive()
  122. {
  123. BOOL bReturn = CPropertyPage::OnSetActive();
  124. CLicCompWizSheet* pSheet = (CLicCompWizSheet*)GetParent();
  125. // Do the default domain expansion only once.
  126. if (!m_bExpandedOnce)
  127. {
  128. m_bExpandedOnce = TRUE;
  129. m_wndTreeNetwork.PopulateTree();
  130. }
  131. pSheet->SetWizardButtons(PSWIZB_BACK | PSWIZB_NEXT);
  132. return bReturn;
  133. }
  134. void CLicCompWizPage3::OnSelChangedTree(NMHDR* pNMHDR, LRESULT* pResult)
  135. {
  136. NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
  137. ASSERT(pNMTreeView->itemNew.mask & TVIF_PARAM);
  138. // Copy the remote name for the selected item into the edit control.
  139. if (pNMTreeView->itemNew.mask & TVIF_PARAM)
  140. {
  141. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  142. int nImage, nSelectedImage;
  143. nImage = nSelectedImage = 0;
  144. m_wndTreeNetwork.GetItemImage(m_wndTreeNetwork.GetSelectedItem(), nImage, nSelectedImage);
  145. // Set the enterprise name in the App object.
  146. if (nImage == CNetTreeCtrl::IMG_ROOT)
  147. pApp->m_strEnterprise.Empty();
  148. else
  149. pApp->m_strEnterprise = ((LPNETRESOURCE)pNMTreeView->itemNew.lParam)->lpRemoteName;
  150. // Set the text in the edit control.
  151. m_wndEnterprise.SetWindowText(pApp->m_strEnterprise);
  152. // Select the text in the edit control.
  153. m_wndEnterprise.SetSel(0, -1);
  154. }
  155. *pResult = 0;
  156. }
  157. void CLicCompWizPage3::OnChangeEditEnterprise()
  158. {
  159. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  160. m_wndEnterprise.GetWindowText(pApp->m_strEnterprise);
  161. }
  162. void CLicCompWizPage3::OnNetworkTreeOutOfMemory(NMHDR* pNMHDR, LRESULT* pResult)
  163. {
  164. UNREFERENCED_PARAMETER(pNMHDR);
  165. m_wndTreeNetwork.NotifyThread(TRUE);
  166. AfxMessageBox(IDS_MEM_ERROR, MB_OK | MB_ICONSTOP);
  167. *pResult = 0;
  168. }
  169. /////////////////////////////////////////////////////////////////////////////
  170. // CLicCompWizPage3 functions
  171. /////////////////////////////////////////////////////////////////////////////
  172. // Global variables
  173. extern TCHAR pszLicenseEvent[];
  174. /////////////////////////////////////////////////////////////////////////////
  175. // Static member functions
  176. UINT CLicCompWizPage4::GetLicenseInfo(LPVOID pParam)
  177. {
  178. // Create an event object to match that in the application object.
  179. CEvent event(TRUE, TRUE, pszLicenseEvent);
  180. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  181. CLicCompWizPage4* pPage = (CLicCompWizPage4*)pParam;
  182. CLicCompWizSheet* pSheet = (CLicCompWizSheet*)pPage->GetParent();
  183. CWaitCursor wc;
  184. NTSTATUS status = STATUS_ACCESS_DENIED;
  185. try
  186. {
  187. CString strText;
  188. // Unsignal the event object.
  189. event.ResetEvent();
  190. // Reset the exit flag.
  191. pApp->NotifyLicenseThread(FALSE);
  192. // Disable the Back and Next buttons while the thread is running.
  193. pSheet->SetWizardButtons(0);
  194. LPBYTE lpbBuf = NULL;
  195. LLS_HANDLE hLls = NULL;
  196. DWORD dwTotalEntries, dwResumeHandle;
  197. dwTotalEntries = dwResumeHandle = 0;
  198. // Save the machine or domain name that the user typed.
  199. CString strFocus = pApp->m_strEnterprise;
  200. // Display a message indicating what the wizard is doing.
  201. strText.LoadString(IDS_WORKING);
  202. pPage->m_wndUnlicensedProducts.SetWindowText(strText);
  203. strText.Empty(); // Avoids a memory leak.
  204. // Connect to the license server.
  205. status = ::LlsConnectEnterprise(const_cast<LPTSTR>((LPCTSTR)pApp->m_strEnterprise),
  206. &hLls, 0, &lpbBuf);
  207. if (NT_ERROR(status))
  208. goto ErrorMessage;
  209. // It's OK for the user to click the Back button now, so enable it.
  210. pSheet->SetWizardButtons(PSWIZB_BACK);
  211. if (lpbBuf != NULL)
  212. {
  213. PLLS_CONNECT_INFO_0 pllsci = (PLLS_CONNECT_INFO_0)lpbBuf;
  214. // Reset the domain and enterprise server names.
  215. pApp->m_strDomain = pllsci->Domain;
  216. pApp->m_strEnterpriseServer = pllsci->EnterpriseServer;
  217. // Free embedded pointers
  218. //::LlsFreeMemory(pllsci->Domain);
  219. //::LlsFreeMemory(pllsci->EnterpriseServer);
  220. // Free memory allocated by the LLS API.
  221. status = ::LlsFreeMemory(lpbBuf);
  222. lpbBuf = NULL;
  223. }
  224. if (NT_SUCCESS(status))
  225. {
  226. // Display a message indicating what the wizard is doing.
  227. strText.LoadString(IDS_ENUM_PRODUCTS);
  228. pPage->m_wndUnlicensedProducts.SetWindowText(strText);
  229. strText.Empty(); // Avoids a memory leak.
  230. USHORT nProductCount = 0;
  231. DWORD dwEntriesRead, dwTotalEntriesRead;
  232. dwEntriesRead = dwTotalEntriesRead = 0;
  233. // Build a list of all the products.
  234. do
  235. {
  236. // Check the exit thread flag. The user may have clicked the Back button.
  237. if (pApp->m_bExitLicenseThread)
  238. goto ExitThread;
  239. status = ::LlsProductEnum(hLls, 1, &lpbBuf, CLicCompWizPage4::LLS_PREFERRED_LENGTH,
  240. &dwEntriesRead, &dwTotalEntries, &dwResumeHandle);
  241. if (!NT_SUCCESS(status))
  242. goto ErrorMessage;
  243. dwTotalEntriesRead += dwEntriesRead;
  244. PLLS_PRODUCT_INFO_1 pllspi = (PLLS_PRODUCT_INFO_1)lpbBuf;
  245. while (dwEntriesRead--)
  246. {
  247. // Check the exit thread flag. The user may have clicked the Back button.
  248. if (pApp->m_bExitLicenseThread)
  249. goto ExitThread;
  250. if ((LONG)pllspi->InUse > (LONG)pllspi->Purchased)
  251. {
  252. pPage->FillListCtrl(pllspi->Product, (WORD)pllspi->InUse, (WORD)pllspi->Purchased);
  253. // Increment the unlicensed products counter.
  254. nProductCount++;
  255. }
  256. // Free embedded pointer.
  257. ::LlsFreeMemory(pllspi->Product);
  258. pllspi++;
  259. }
  260. // Free memory allocated by the LLS API.
  261. status = ::LlsFreeMemory(lpbBuf);
  262. lpbBuf = NULL;
  263. ASSERT(NT_SUCCESS(status));
  264. }
  265. while (dwTotalEntries);
  266. // Close the LLS handle.
  267. status = ::LlsClose(hLls);
  268. // Check the exit thread flag. The user may have clicked the Back button.
  269. if (pApp->m_bExitLicenseThread)
  270. goto ExitThread;
  271. ASSERT(NT_SUCCESS(status));
  272. // Show the user how many unlicensed products were found.
  273. if (nProductCount)
  274. {
  275. strText.Format(IDS_UNLICENSED_PRODUCTS, pApp->m_strEnterpriseServer);
  276. pPage->m_wndUnlicensedProducts.SetWindowText(strText);
  277. // Make the static text box the appropriate size.
  278. pPage->m_wndUnlicensedProducts.SetWindowPos(&CWnd::wndTop, 0, 0,
  279. pPage->m_sizeSmallText.cx,
  280. pPage->m_sizeSmallText.cy,
  281. SWP_NOMOVE | SWP_NOZORDER);
  282. // Make sure the list control is visible.
  283. pPage->m_wndProductList.ShowWindow(SW_SHOW);
  284. // Make sure the print button is visible.
  285. pPage->m_wndPrint.ShowWindow(SW_SHOW);
  286. }
  287. else
  288. {
  289. // Make the static text box the appropriate size.
  290. pPage->m_wndUnlicensedProducts.SetWindowPos(&CWnd::wndTop, 0, 0,
  291. pPage->m_sizeLargeText.cx,
  292. pPage->m_sizeLargeText.cy,
  293. SWP_NOMOVE | SWP_NOZORDER);
  294. // Display a message if no unlicensed products were found.
  295. strText.LoadString(IDS_NO_UNLICENSED_PRODUCTS);
  296. pPage->m_wndUnlicensedProducts.SetWindowText(strText);
  297. }
  298. // Enable the Back button.
  299. pSheet->SetWizardButtons(PSWIZB_BACK);
  300. CString strFinished;
  301. CButton* pCancel = (CButton*)pSheet->GetDlgItem(IDCANCEL);
  302. // Change the text on the cancel button to "Done."
  303. strFinished.LoadString(IDS_DONE);
  304. pCancel->SetWindowText(strFinished);
  305. // Signal the event object.
  306. event.SetEvent();
  307. // Reset the pointer to the license thread.
  308. pApp->m_pLicenseThread = NULL;
  309. // Restore the normal cursor.
  310. pPage->PostMessage(WM_SETCURSOR);
  311. }
  312. return 0;
  313. ErrorMessage:
  314. // Check the exit thread flag. The user may have clicked the Back button.
  315. if (pApp->m_bExitLicenseThread)
  316. goto ExitThread;
  317. // Make the static text box the appropriate size.
  318. pPage->m_wndUnlicensedProducts.SetWindowPos(&CWnd::wndTop, 0, 0,
  319. pPage->m_sizeLargeText.cx,
  320. pPage->m_sizeLargeText.cy,
  321. SWP_NOMOVE | SWP_NOZORDER);
  322. // Create an error message based on the return value from LlsConnectEnterprise().
  323. switch (status)
  324. {
  325. case STATUS_NO_SUCH_DOMAIN:
  326. if (pApp->IsRemote())
  327. strText.Format(IDS_BAD_DOMAIN_NAME, strFocus);
  328. else
  329. strText.LoadString(IDS_UNAVAILABLE);
  330. break;
  331. case STATUS_ACCESS_DENIED:
  332. if (pApp->IsRemote())
  333. strText.Format(IDS_ACCESS_DENIED, strFocus);
  334. else
  335. strText.LoadString(IDS_LOCAL_ACCESS_DENIED);
  336. break;
  337. case RPC_NT_SERVER_UNAVAILABLE:
  338. strText.Format(IDS_SERVER_UNAVAILABLE);
  339. break;
  340. default:
  341. if (pApp->IsRemote())
  342. strText.Format(IDS_NO_LICENSE_INFO_REMOTE, strFocus);
  343. else
  344. strText.LoadString(IDS_NO_LICENSE_INFO_LOCAL);
  345. }
  346. // Display an error message if LlsProductEnum() fails.
  347. pPage->m_wndUnlicensedProducts.SetWindowText(strText);
  348. // Enable the Back button.
  349. pSheet->SetWizardButtons(PSWIZB_BACK);
  350. // Signal the event object.
  351. event.SetEvent();
  352. // Reset the pointer to the license thread.
  353. pApp->m_pLicenseThread = NULL;
  354. // Restore the normal cursor.
  355. pPage->PostMessage(WM_SETCURSOR);
  356. return 1;
  357. ExitThread:
  358. // Signal the event object.
  359. event.SetEvent();
  360. // Reset the pointer to the license thread.
  361. pApp->m_pLicenseThread = NULL;
  362. return 2;
  363. }
  364. catch(...)
  365. {
  366. // Signal the event object.
  367. event.SetEvent();
  368. CString strText;
  369. // Display an error message.
  370. strText.LoadString(IDS_GENERIC_ERROR);
  371. pPage->m_wndUnlicensedProducts.SetWindowText(strText);
  372. // Reset the pointer to the license thread.
  373. pApp->m_pLicenseThread = NULL;
  374. // Restore the normal cursor.
  375. pPage->PostMessage(WM_SETCURSOR);
  376. return 3;
  377. }
  378. }
  379. /////////////////////////////////////////////////////////////////////////////
  380. // CLicCompWizPage4 property page
  381. CLicCompWizPage4::CLicCompWizPage4()
  382. : CPropertyPage(CLicCompWizPage4::IDD), m_ptPrint(0, 0), m_nHorzMargin(0),
  383. m_nVertMargin(0),m_ptOrg(0, 0), m_ptExt(0, 0), m_sizeSmallText(0, 0),
  384. m_sizeLargeText(0, 0)
  385. {
  386. //{{AFX_DATA_INIT(CLicCompWizPage4)
  387. //}}AFX_DATA_INIT
  388. m_strCancel.Empty();
  389. m_pTabs = new INT[PRINT_COLUMNS];
  390. }
  391. CLicCompWizPage4::~CLicCompWizPage4()
  392. {
  393. if (m_pTabs != NULL)
  394. delete[] m_pTabs;
  395. }
  396. void CLicCompWizPage4::DoDataExchange(CDataExchange* pDX)
  397. {
  398. CPropertyPage::DoDataExchange(pDX);
  399. //{{AFX_DATA_MAP(CLicCompWizPage4)
  400. DDX_Control(pDX, IDC_FLAG_BMP, m_wndPicture);
  401. DDX_Control(pDX, IDC_BUT_PRINT, m_wndPrint);
  402. DDX_Control(pDX, IDC_TEXT_UNCOMP_PRODUCTS, m_wndUnlicensedProducts);
  403. DDX_Control(pDX, IDC_LIST_PRODUCTS, m_wndProductList);
  404. //}}AFX_DATA_MAP
  405. }
  406. BEGIN_MESSAGE_MAP(CLicCompWizPage4, CPropertyPage)
  407. //{{AFX_MSG_MAP(CLicCompWizPage4)
  408. ON_BN_CLICKED(IDC_BUT_PRINT, OnPrintButton)
  409. ON_NOTIFY(NM_OUTOFMEMORY, IDC_LIST_PRODUCTS, OnListProductsOutOfMemory)
  410. ON_WM_DESTROY()
  411. ON_WM_SETCURSOR()
  412. //}}AFX_MSG_MAP
  413. END_MESSAGE_MAP()
  414. void CLicCompWizPage4::PumpMessages()
  415. {
  416. // Must call Create() before using the dialog
  417. ASSERT(m_hWnd!=NULL);
  418. MSG msg;
  419. try
  420. {
  421. // Handle dialog messages
  422. while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  423. {
  424. if(!IsDialogMessage(&msg))
  425. {
  426. TranslateMessage(&msg);
  427. DispatchMessage(&msg);
  428. }
  429. }
  430. }
  431. catch(...)
  432. {
  433. TRACE(_T("Exception in CLicCompWizPage4::PumpMessages()\n"));
  434. }
  435. }
  436. BOOL CLicCompWizPage4::FillListCtrl(LPTSTR pszProduct, WORD wInUse, WORD wPurchased)
  437. {
  438. TCHAR pszLicenses[BUFFER_SIZE];
  439. ::wsprintf(pszLicenses, _T("%u"), wInUse - wPurchased);
  440. USHORT nIndex;
  441. LV_ITEM lvi;
  442. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  443. lvi.iItem = 0;
  444. lvi.iSubItem = 0;
  445. lvi.lParam = MAKELONG(wInUse, wPurchased);
  446. lvi.pszText = pszProduct;
  447. if ((nIndex = (USHORT)m_wndProductList.InsertItem(&lvi)) != (USHORT)-1)
  448. {
  449. m_wndProductList.SetItemText(nIndex, 1, pszLicenses);
  450. }
  451. return TRUE;
  452. }
  453. BOOL CLicCompWizPage4::OnInitDialog()
  454. {
  455. CPropertyPage::OnInitDialog();
  456. // Set the header text for the list control.
  457. CRect rcList;
  458. m_wndProductList.GetWindowRect(&rcList);
  459. CString strColumnTitle;
  460. LV_COLUMN lvc;
  461. lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
  462. lvc.fmt = LVCFMT_LEFT;
  463. USHORT nColumns = COLUMNS;
  464. UINT uStringID[COLUMNS] = {IDS_PRODUCTS_LIST, IDS_LICENSES_LIST};
  465. for (USHORT i = 0; i < nColumns; i++)
  466. {
  467. strColumnTitle.LoadString(uStringID[i]);
  468. lvc.pszText = strColumnTitle.GetBuffer(strColumnTitle.GetLength());
  469. lvc.cx = rcList.Width() / COLUMNS;
  470. m_wndProductList.InsertColumn(i, &lvc);
  471. strColumnTitle.ReleaseBuffer();
  472. }
  473. CLicCompWizSheet* pSheet = (CLicCompWizSheet*)GetParent();
  474. // Store the text on the cancel button.
  475. CButton* pCancel = (CButton*)pSheet->GetDlgItem(IDCANCEL);
  476. pCancel->GetWindowText(m_strCancel);
  477. CRect rcText;
  478. // Create the large and small extents for the static text control.
  479. m_wndUnlicensedProducts.GetWindowRect(&rcText);
  480. m_sizeSmallText.cx = rcText.right - rcText.left;
  481. m_sizeSmallText.cy = rcText.bottom - rcText.top;
  482. // Make the large extents match those for the list control.
  483. m_sizeLargeText.cx = rcList.right - rcList.left;
  484. m_sizeLargeText.cy = rcList.bottom - rcList.top;
  485. return TRUE; // return TRUE unless you set the focus to a control
  486. // EXCEPTION: OCX Property Pages should return FALSE
  487. }
  488. void CLicCompWizPage4::OnListProductsOutOfMemory(NMHDR* pNMHDR, LRESULT* pResult)
  489. {
  490. UNREFERENCED_PARAMETER(pNMHDR);
  491. AfxMessageBox(IDS_MEM_ERROR, MB_OK | MB_ICONSTOP);
  492. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  493. // Let the license thread know it's supposed to quit.
  494. pApp->NotifyLicenseThread(TRUE);
  495. *pResult = 0;
  496. }
  497. void CLicCompWizPage4::OnPrintButton()
  498. {
  499. CDC dc;
  500. CPrintDialog dlg(FALSE,
  501. PD_ALLPAGES | PD_USEDEVMODECOPIESANDCOLLATE |
  502. PD_NOPAGENUMS | PD_HIDEPRINTTOFILE |
  503. PD_NOSELECTION,
  504. this);
  505. if (dlg.DoModal() == IDOK)
  506. {
  507. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  508. m_wndPrint.RedrawWindow();
  509. DOCINFO di;
  510. CString strDocName;
  511. strDocName.Format(IDS_DOC_NAME, pApp->m_strEnterpriseServer);
  512. di.cbSize = sizeof(DOCINFO);
  513. di.lpszDocName = strDocName.GetBuffer(BUFFER_SIZE);
  514. di.lpszOutput = NULL;
  515. if (dc.Attach(dlg.GetPrinterDC()))
  516. {
  517. PrepareForPrinting(dc);
  518. dc.StartDoc(&di);
  519. PrintReport(dc);
  520. dc.EndDoc();
  521. dc.DeleteDC();
  522. ::GlobalFree(dlg.m_pd.hDevNames);
  523. ::GlobalFree(dlg.m_pd.hDevMode);
  524. }
  525. }
  526. }
  527. BOOL CLicCompWizPage4::PrepareForPrinting(CDC& dc)
  528. {
  529. // Create various fonts...
  530. CString strFont;
  531. // Create a heading font.
  532. strFont.LoadString(IDS_FONT_BOLD);
  533. m_fontHeading.CreatePointFont(FONT_SIZE_HEADING, strFont, &dc);
  534. // Create a bold, underlined header font.
  535. strFont.LoadString(IDS_FONT_BOLD);
  536. m_fontHeader.CreatePointFont(FONT_SIZE, strFont, &dc);
  537. LOGFONT lf;
  538. m_fontHeader.GetLogFont(&lf);
  539. m_fontHeader.DeleteObject();
  540. lf.lfUnderline = TRUE;
  541. m_fontHeader.CreateFontIndirect(&lf);
  542. // Create a footer font.
  543. strFont.LoadString(IDS_FONT_BOLD);
  544. m_fontFooter.CreatePointFont(FONT_SIZE_FOOTER, strFont, &dc);
  545. // Create a default font.
  546. strFont.LoadString(IDS_FONT);
  547. m_fontNormal.CreatePointFont(FONT_SIZE, strFont, &dc);
  548. // Get the text metrics for each font.
  549. CFont* pOldFont = dc.SelectObject(&m_fontHeading);
  550. dc.GetTextMetrics(&m_tmHeading);
  551. dc.SelectObject(&m_fontHeader);
  552. dc.GetTextMetrics(&m_tmHeader);
  553. dc.SelectObject(&m_fontFooter);
  554. dc.GetTextMetrics(&m_tmFooter);
  555. dc.SelectObject(&m_fontNormal);
  556. dc.GetTextMetrics(&m_tmNormal);
  557. // Select the original font back in to the device context.
  558. dc.SelectObject(pOldFont);
  559. // Set the horizontal and vertical margins.
  560. m_nHorzMargin = (LONG)(dc.GetDeviceCaps(LOGPIXELSX) * HORZ_MARGIN);
  561. m_nVertMargin = (LONG)(dc.GetDeviceCaps(LOGPIXELSY) * VERT_MARGIN);
  562. // Get the printable page offsets for the origin.
  563. m_ptOrg.x = dc.GetDeviceCaps(PHYSICALOFFSETX);
  564. m_ptOrg.y = dc.GetDeviceCaps(PHYSICALOFFSETY);
  565. dc.SetWindowOrg(m_ptOrg);
  566. m_ptOrg.x += m_nHorzMargin;
  567. m_ptOrg.y += m_nVertMargin;
  568. // Get the printable page offsets for the page extents.
  569. m_ptExt.x = dc.GetDeviceCaps(PHYSICALWIDTH) - m_ptOrg.x;
  570. m_ptExt.y = dc.GetDeviceCaps(PHYSICALHEIGHT) - m_ptOrg.y;
  571. dc.SetViewportOrg(m_ptOrg);
  572. CalculateTabs(dc);
  573. return TRUE;
  574. }
  575. BOOL CLicCompWizPage4::PrintReport(CDC& dc)
  576. {
  577. // Set the starting point for printing.
  578. m_ptPrint.x = m_ptPrint.y = 0;
  579. // Prepare to print a heading.
  580. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  581. CString strHeading;
  582. CFont* pOldFont = dc.SelectObject(&m_fontHeading);
  583. strHeading.Format(IDS_DOC_NAME, pApp->m_strEnterpriseServer);
  584. dc.StartPage();
  585. CRect rc(m_ptPrint.x, m_ptPrint.y, m_ptExt.x - m_ptOrg.x, m_tmHeading.tmHeight);
  586. // Calculate the size of the rectangle needed to draw the text.
  587. m_ptPrint.y += dc.DrawText(strHeading, &rc, DT_EXTERNALLEADING | DT_CENTER | DT_WORDBREAK | DT_NOCLIP);
  588. // Normalize the rectangle.
  589. rc.NormalizeRect();
  590. // Add a blank line below the heading.
  591. m_ptPrint.y += m_tmHeading.tmHeight;
  592. // Move the right side of the rectangle out to the right margin so text is properly centered.
  593. rc.right = m_ptExt.x - m_ptOrg.x;
  594. // Draw the text in the rectangle.
  595. dc.DrawText(strHeading, &rc, DT_EXTERNALLEADING | DT_CENTER | DT_WORDBREAK | DT_NOCLIP);
  596. dc.SelectObject(pOldFont);
  597. PrintPages(dc, 100);
  598. // Delete the fonts.
  599. m_fontNormal.DeleteObject();
  600. m_fontHeader.DeleteObject();
  601. m_fontFooter.DeleteObject();
  602. m_fontHeading.DeleteObject();
  603. return TRUE;
  604. }
  605. BOOL CLicCompWizPage4::PrintPageHeader(CDC& dc)
  606. {
  607. CFont* pOldFont = dc.SelectObject(&m_fontHeader);
  608. dc.StartPage();
  609. CString strHeader, strProducts, strLicenses, strPurchased, strUsed;
  610. strProducts.LoadString(IDS_PRODUCTS);
  611. strLicenses.LoadString(IDS_LICENSES);
  612. strPurchased.LoadString(IDS_PURCHASED);
  613. strUsed.LoadString(IDS_USED);
  614. strHeader.Format(_T("%s\t%s\t%s\t%s"), strProducts, strLicenses,
  615. strPurchased, strUsed);
  616. dc.TabbedTextOut(m_ptPrint.x, m_ptPrint.y, strHeader, PRINT_COLUMNS, m_pTabs, 0);
  617. m_ptPrint.y += ((m_tmHeader.tmHeight + m_tmHeader.tmExternalLeading) * 2);
  618. dc.SelectObject(pOldFont);
  619. return TRUE;
  620. }
  621. BOOL CLicCompWizPage4::PrintPageFooter(CDC& dc, USHORT nPage)
  622. {
  623. CFont* pOldFont = dc.SelectObject(&m_fontFooter);
  624. CString strFooter;
  625. CTime time(CTime::GetCurrentTime());
  626. strFooter.Format(IDS_PAGE_DATE, nPage, time.Format(IDS_FMT_DATE));
  627. CRect rc(m_ptPrint.x, m_ptExt.y - m_nVertMargin, m_ptOrg.x, m_tmFooter.tmHeight);
  628. // Calculate the size of the rectangle needed to draw the text.
  629. m_ptPrint.y += dc.DrawText(strFooter, &rc, DT_CALCRECT | DT_EXTERNALLEADING | DT_CENTER | DT_WORDBREAK | DT_NOCLIP);
  630. // Move the right side of the rectangle out to the right margin so text is properly centered.
  631. rc.right = m_ptExt.x - m_ptOrg.x;
  632. // Draw the text in the rectangle.
  633. dc.DrawText(strFooter, &rc, DT_EXTERNALLEADING | DT_CENTER | DT_WORDBREAK | DT_NOCLIP);
  634. dc.EndPage();
  635. dc.SelectObject(pOldFont);
  636. return TRUE;
  637. }
  638. BOOL CLicCompWizPage4::PrintPages(CDC& dc, UINT nStart)
  639. {
  640. CFont* pOldFont = dc.SelectObject(&m_fontNormal);
  641. UNREFERENCED_PARAMETER(nStart);
  642. USHORT nPage = 1;
  643. UINT nItems = m_wndProductList.GetItemCount();
  644. // Print the initial header.
  645. PrintPageHeader(dc);
  646. DWORD dwParam = 0;
  647. CString strTextOut;
  648. for (UINT i = 0; i < nItems; i++)
  649. {
  650. dwParam = (DWORD)m_wndProductList.GetItemData(i);
  651. CString strProduct = m_wndProductList.GetItemText(i, 0);
  652. CSize sizeProduct = dc.GetTextExtent(strProduct);
  653. if (sizeProduct.cx > m_pTabs[0] - (m_tmNormal.tmAveCharWidth * TAB_WIDTH))
  654. TruncateText(dc, strProduct);
  655. // Format the output text.
  656. strTextOut.Format(_T("%s\t%s\t%u\t%u"), strProduct,
  657. m_wndProductList.GetItemText(i, 1),
  658. HIWORD(dwParam), LOWORD(dwParam));
  659. dc.TabbedTextOut(m_ptPrint.x, m_ptPrint.y, strTextOut, PRINT_COLUMNS, m_pTabs, 0);
  660. // Calculate the vertical position for the next line of text.
  661. m_ptPrint.y += m_tmNormal.tmHeight + m_tmNormal.tmExternalLeading;
  662. if ((m_ptPrint.y + m_ptOrg.y) >= m_ptExt.y)
  663. {
  664. PrintPageFooter(dc, nPage++);
  665. // Reset the printing position.
  666. m_ptPrint.y = 0;
  667. PrintPageHeader(dc);
  668. }
  669. }
  670. // Print the final footer.
  671. PrintPageFooter(dc, (USHORT)nPage);
  672. dc.SelectObject(pOldFont);
  673. return TRUE;
  674. }
  675. void CLicCompWizPage4::TruncateText(CDC& dc, CString& strInput)
  676. {
  677. CString strText, strEllipsis;
  678. USHORT nLen, nChars = 0;
  679. UINT nMaxWidth = m_pTabs[0] - (m_tmNormal.tmAveCharWidth * TAB_WIDTH);
  680. nLen = (USHORT)strInput.GetLength();
  681. strEllipsis.LoadString(IDS_ELLIPSIS);
  682. CSize sizeText = dc.GetTextExtent(strInput);
  683. // Keep lopping off characters until the string is short enough.
  684. while ((UINT)sizeText.cx > nMaxWidth)
  685. {
  686. strText = strInput.Left(nLen - nChars++);
  687. sizeText = dc.GetTextExtent(strText);
  688. }
  689. // Remove the last characters and replace them with an ellipsis.
  690. ASSERT(strText.GetLength() > strEllipsis.GetLength());
  691. strInput = strText.Left(strText.GetLength() - strEllipsis.GetLength()) + strEllipsis;
  692. }
  693. BOOL CLicCompWizPage4::CalculateTabs(CDC& dc)
  694. {
  695. INT nTotalExt = 0;
  696. INT nTabSize = TAB_WIDTH * m_tmHeader.tmAveCharWidth;
  697. UINT uStrIds[] = {IDS_LICENSES, IDS_PURCHASED, IDS_USED};
  698. m_pTabs[0] = 0;
  699. for (USHORT i = 1; i < PRINT_COLUMNS; i++)
  700. {
  701. CString strText;
  702. strText.LoadString(uStrIds[i - 1]);
  703. // Get the text extent for each string.
  704. m_pTabs[i] = dc.GetTextExtent(strText).cx;
  705. // Keep a running total of the extents.
  706. nTotalExt += m_pTabs[i];
  707. }
  708. // Add tab space between columns.
  709. nTotalExt += nTabSize * (PRINT_COLUMNS - 2);
  710. // The second column will begin at the difference between the right
  711. // margin and the total extent.
  712. m_pTabs[0] = m_ptExt.x - m_ptOrg.x - nTotalExt;
  713. // Now set the actual tab positions in the array.
  714. for (i = 1; i < PRINT_COLUMNS; i++)
  715. {
  716. m_pTabs[i] += m_pTabs[i - 1] + nTabSize;
  717. }
  718. return TRUE;
  719. }
  720. LRESULT CLicCompWizPage4::OnWizardBack()
  721. {
  722. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  723. // Let the license thread know it's time to quit.
  724. pApp->NotifyLicenseThread(TRUE);
  725. CLicCompWizSheet* pSheet = (CLicCompWizSheet*)GetParent();
  726. // Set the cancel button text back to "Cancel."
  727. CButton* pCancel = (CButton*)pSheet->GetDlgItem(IDCANCEL);
  728. pCancel->SetWindowText(m_strCancel);
  729. if (pSheet->m_Page1.m_nRadio == 0)
  730. return IDD_PROPPAGE1;
  731. else
  732. return CPropertyPage::OnWizardBack();
  733. }
  734. void CLicCompWizPage4::OnDestroy()
  735. {
  736. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  737. pApp->NotifyLicenseThread(TRUE);
  738. PumpMessages();
  739. CPropertyPage::OnDestroy();
  740. }
  741. BOOL CLicCompWizPage4::OnSetActive()
  742. {
  743. CLicCompWizSheet* pSheet = (CLicCompWizSheet*)GetParent();
  744. pSheet->SetWizardButtons(PSWIZB_BACK);
  745. // Hide the list control and clear it.
  746. m_wndProductList.ShowWindow(SW_HIDE);
  747. m_wndProductList.DeleteAllItems();
  748. // Hide the print button.
  749. m_wndPrint.ShowWindow(SW_HIDE);
  750. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  751. // Make sure the last thread has terminated before starting a new one.
  752. if (pApp->m_pLicenseThread != NULL)
  753. {
  754. pApp->NotifyLicenseThread(TRUE);
  755. CEvent event(TRUE, TRUE, pszLicenseEvent);
  756. CSingleLock lock(&event);
  757. lock.Lock();
  758. }
  759. // Keep a pointer to the thread so we can find out if it's still running.
  760. pApp->m_pLicenseThread = AfxBeginThread((AFX_THREADPROC)GetLicenseInfo, (LPVOID)this);
  761. return CPropertyPage::OnSetActive();
  762. }
  763. LRESULT CLicCompWizPage3::OnWizardNext()
  764. {
  765. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  766. m_wndEnterprise.GetWindowText(pApp->m_strEnterprise);
  767. // Trim off any white space in the enterprise name.
  768. pApp->m_strEnterprise.TrimLeft();
  769. pApp->m_strEnterprise.TrimRight();
  770. if (pApp->m_strEnterprise.IsEmpty() ||
  771. pApp->m_strEnterprise.Find(_T("\\\\")) != -1)
  772. {
  773. AfxMessageBox(IDS_SPECIFY_DOMAIN, MB_OK | MB_ICONEXCLAMATION);
  774. return IDD;
  775. }
  776. return CPropertyPage::OnWizardNext();
  777. }
  778. BOOL CLicCompWizPage4::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  779. {
  780. CLicCompWizApp* pApp = (CLicCompWizApp*)AfxGetApp();
  781. if (pApp->m_pLicenseThread == NULL)
  782. {
  783. return CPropertyPage::OnSetCursor(pWnd, nHitTest, message);
  784. }
  785. else
  786. {
  787. // Restore the wait cursor if the thread is running.
  788. RestoreWaitCursor();
  789. return TRUE;
  790. }
  791. }