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.

1569 lines
39 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : CoverPages.cpp //
  3. // //
  4. // DESCRIPTION : The implementation of fax cover pages node. //
  5. // //
  6. // AUTHOR : yossg //
  7. // //
  8. // HISTORY : //
  9. // Feb 9 2000 yossg Create //
  10. // Oct 17 2000 yossg //
  11. // //
  12. // Copyright (C) 2000 Microsoft Corporation All Rights Reserved //
  13. /////////////////////////////////////////////////////////////////////////////
  14. #include "StdAfx.h"
  15. #include "snapin.h"
  16. #include "FaxServer.h"
  17. #include "FaxServerNode.h"
  18. #include "CoverPages.h"
  19. #include "oaidl.h"
  20. #include "Icons.h"
  21. #include <faxreg.h>
  22. #include <commdlg.h>
  23. #include "CovNotifyWnd.h"
  24. #include <FaxUtil.h>
  25. //////////////////////////////////////////////////////////////
  26. // {4D0480C7-3DE2-46ca-B03F-5C018DF1AF4D}
  27. static const GUID CFaxCoverPagesNodeGUID_NODETYPE =
  28. { 0x4d0480c7, 0x3de2, 0x46ca, { 0xb0, 0x3f, 0x5c, 0x1, 0x8d, 0xf1, 0xaf, 0x4d } };
  29. const GUID* CFaxCoverPagesNode::m_NODETYPE = &CFaxCoverPagesNodeGUID_NODETYPE;
  30. const OLECHAR* CFaxCoverPagesNode::m_SZNODETYPE = OLESTR("4D0480C7-3DE2-46ca-B03F-5C018DF1AF4D");
  31. const CLSID* CFaxCoverPagesNode::m_SNAPIN_CLASSID = &CLSID_Snapin;
  32. //
  33. // Static members
  34. //
  35. CColumnsInfo CFaxCoverPagesNode::m_ColsInfo;
  36. HANDLE CFaxCoverPagesNode::m_hStopNotificationThreadEvent = NULL;
  37. /*
  38. - CFaxCoverPagesNode::Init
  39. -
  40. * Purpose:
  41. * Create Event for shut down notification.
  42. *
  43. * Arguments:
  44. *
  45. * Return:
  46. * OLE error code
  47. */
  48. HRESULT CFaxCoverPagesNode::Init()
  49. {
  50. DEBUG_FUNCTION_NAME(_T("CFaxCoverPagesNode::Init"));
  51. HRESULT hRc = S_OK;
  52. DWORD ec = ERROR_SUCCESS;
  53. //
  54. // Get Sever Cover-page Dir for the current administrated server
  55. //
  56. CComBSTR bstrServerName = ((CFaxServerNode *)GetRootNode())->GetServerName();
  57. if (!bstrServerName)
  58. {
  59. DebugPrintEx(DEBUG_ERR, TEXT("Out of memory. Failed to get server name."));
  60. hRc = E_OUTOFMEMORY;
  61. goto Exit;
  62. }
  63. if(!GetServerCpDir(bstrServerName,
  64. m_pszCovDir,
  65. sizeof(m_pszCovDir)/sizeof(m_pszCovDir[0]) //*//
  66. )
  67. )
  68. {
  69. ec = GetLastError();
  70. if (ERROR_FILE_NOT_FOUND == ec)
  71. {
  72. DebugPrintEx(
  73. DEBUG_ERR,
  74. _T("Failed to find Server Cover-Page Dir. (ec : %ld)"), ec);
  75. }
  76. else
  77. {
  78. DebugPrintEx(
  79. DEBUG_ERR,
  80. _T("Failed to get Server Cover-Page Dir. (ec : %ld)"), ec);
  81. }
  82. hRc = HRESULT_FROM_WIN32(ec);
  83. goto Exit;
  84. }
  85. //
  86. // Create the shutdown event. This event will be signaled when the app is
  87. // about to quit.
  88. //
  89. if (NULL != m_hStopNotificationThreadEvent) // can happen while retargeting
  90. {
  91. hRc = RestartNotificationThread();
  92. if (S_OK != hRc)
  93. {
  94. DebugPrintEx(
  95. DEBUG_ERR,
  96. _T("Fail to RestartNotificationThread."));
  97. }
  98. }
  99. else //first time here.
  100. {
  101. m_hStopNotificationThreadEvent = CreateEvent (NULL, // No security
  102. TRUE, // Manual reset
  103. FALSE, // Starts clear
  104. NULL); // Unnamed
  105. if (NULL == m_hStopNotificationThreadEvent)
  106. {
  107. ec = GetLastError ();
  108. DebugPrintEx(
  109. DEBUG_ERR,
  110. TEXT("Fail to CreateEvent."));
  111. //CR: NodeMsgBox(IDS_FAIL2CREATE_EVENT);
  112. hRc = HRESULT_FROM_WIN32(ec);
  113. goto Exit;
  114. }
  115. }
  116. Exit:
  117. return hRc;
  118. }
  119. /*
  120. - CFaxCoverPagesNode::InsertColumns
  121. -
  122. * Purpose:
  123. * Adds columns to the default result pane.
  124. *
  125. * Arguments:
  126. * [in] pHeaderCtrl - IHeaderCtrl in the console-provided default result view pane
  127. *
  128. * Return:
  129. * OLE error code
  130. */
  131. HRESULT
  132. CFaxCoverPagesNode::InsertColumns(IHeaderCtrl *pHeaderCtrl)
  133. {
  134. DEBUG_FUNCTION_NAME( _T("CFaxCoverPagesNode::InsertColumns"));
  135. HRESULT hRc = S_OK;
  136. static ColumnsInfoInitData ColumnsInitData[] =
  137. {
  138. {IDS_COVERPAGES_COL1, FXS_NORMAL_COLUMN_WIDTH},
  139. {IDS_COVERPAGES_COL2, FXS_NORMAL_COLUMN_WIDTH},
  140. {IDS_COVERPAGES_COL3, FXS_NORMAL_COLUMN_WIDTH},
  141. {LAST_IDS, 0}
  142. };
  143. hRc = m_ColsInfo.InsertColumnsIntoMMC(pHeaderCtrl,
  144. _Module.GetResourceInstance(),
  145. ColumnsInitData);
  146. CHECK_RETURN_VALUE_AND_PRINT_DEBUG (_T("m_ColsInfo.InsertColumnsIntoMMC"))
  147. Cleanup:
  148. return(hRc);
  149. }
  150. /*
  151. - CFaxCoverPagesNode::PopulateResultChildrenList
  152. -
  153. * Purpose:
  154. * Create the FaxInboundRoutingMethods children nodes
  155. *
  156. * Arguments:
  157. *
  158. * Return:
  159. * OLE error code
  160. */
  161. HRESULT CFaxCoverPagesNode::PopulateResultChildrenList()
  162. {
  163. DEBUG_FUNCTION_NAME( _T("CFaxCoverPagesNode::PopulateResultChildrenList"));
  164. HRESULT hRc = S_OK;
  165. CFaxCoverPageNode * pCoverPage = NULL;
  166. WCHAR szFileName[MAX_PATH+1];
  167. size_t itFullDirectoryPathLen;
  168. TCHAR* pFullDirectoryPathEnd; //pointer to the NULL after dir path with '\'
  169. WIN32_FIND_DATA findData;
  170. DWORD ec;
  171. BOOL bFindRes;
  172. HANDLE hFile = INVALID_HANDLE_VALUE;
  173. szFileName[0]= 0;
  174. ATLASSERT (NULL != m_pszCovDir );
  175. ATLASSERT ( wcslen(m_pszCovDir) < (MAX_PATH - sizeof(FAX_COVER_PAGE_FILENAME_EXT)/sizeof(WCHAR) - 1) );
  176. //
  177. // Create cover page mask
  178. //
  179. wcscpy(szFileName, m_pszCovDir);
  180. wcscat(szFileName, FAX_PATH_SEPARATOR_STR);
  181. itFullDirectoryPathLen = wcslen(szFileName);
  182. pFullDirectoryPathEnd = wcschr(szFileName, L'\0');
  183. wcscat(szFileName, FAX_COVER_PAGE_MASK);
  184. //
  185. // Find First File
  186. //
  187. hFile = FindFirstFile(szFileName, &findData);
  188. if(INVALID_HANDLE_VALUE == hFile)
  189. {
  190. ec = GetLastError();
  191. if(ERROR_FILE_NOT_FOUND != ec)
  192. {
  193. hRc = HRESULT_FROM_WIN32(ec);
  194. DebugPrintEx(
  195. DEBUG_ERR,
  196. _T("FindFirstFile Failed. (ec: %ld)"),
  197. ec);
  198. goto Error;
  199. }
  200. else
  201. {
  202. DebugPrintEx( DEBUG_MSG,
  203. _T("No server cover pages were found."));
  204. goto Exit;
  205. }
  206. }
  207. //
  208. // while loop - add cover pages to the result pane view
  209. //
  210. bFindRes = TRUE;
  211. while(bFindRes)
  212. {
  213. if(itFullDirectoryPathLen + _tcslen(findData.cFileName) < MAX_PATH )
  214. {
  215. _tcsncpy(pFullDirectoryPathEnd, findData.cFileName, MAX_PATH - itFullDirectoryPathLen);
  216. if (IsValidCoverPage(szFileName))
  217. {
  218. //
  219. // add the cover page to result pane
  220. //
  221. pCoverPage = NULL;
  222. pCoverPage = new CFaxCoverPageNode(this, m_pComponentData);
  223. if (!pCoverPage)
  224. {
  225. hRc = E_OUTOFMEMORY;
  226. NodeMsgBox(IDS_MEMORY);
  227. DebugPrintEx(
  228. DEBUG_ERR,
  229. _T("Out of memory. (hRc: %08X)"),
  230. hRc);
  231. goto Error;
  232. }
  233. else
  234. {
  235. //
  236. // Init
  237. //
  238. pCoverPage->InitParentNode(this);
  239. hRc = pCoverPage->Init(&findData);
  240. if (FAILED(hRc))
  241. {
  242. DebugPrintEx(
  243. DEBUG_ERR,
  244. _T("Fail to init cover page. (hRc: %08X)"),
  245. hRc);
  246. // done by called func NodeMsgBox(IDS_FAIL2INIT_COVERPAGE_DATA);
  247. goto Error;
  248. }
  249. //
  250. // add to list
  251. //
  252. hRc = this->AddChildToList(pCoverPage);
  253. if (FAILED(hRc))
  254. {
  255. DebugPrintEx(
  256. DEBUG_ERR,
  257. _T("Fail to add property page for General Tab. (hRc: %08X)"),
  258. hRc);
  259. NodeMsgBox(IDS_FAIL2ADD_COVERPAGE);
  260. goto Error;
  261. }
  262. else
  263. {
  264. pCoverPage = NULL;
  265. }
  266. }
  267. }
  268. else
  269. {
  270. DebugPrintEx(
  271. DEBUG_ERR,
  272. _T("File %ws was found to be an invalid *.cov file."), pFullDirectoryPathEnd);
  273. }
  274. }
  275. else
  276. {
  277. DebugPrintEx(
  278. DEBUG_ERR,
  279. _T("The file %ws path is too long"), pFullDirectoryPathEnd);
  280. }
  281. //
  282. // Find Next File
  283. //
  284. bFindRes = FindNextFile(hFile, &findData);
  285. if(!bFindRes)
  286. {
  287. ec = GetLastError();
  288. if (ERROR_NO_MORE_FILES == ec)
  289. {
  290. break;
  291. }
  292. else
  293. {
  294. DebugPrintEx(
  295. DEBUG_ERR,
  296. _T("FindNexTFile Failed. (ec: %ld)"),
  297. ec);
  298. hRc = HRESULT_FROM_WIN32(ec);
  299. goto Exit;
  300. }
  301. }
  302. } //while(bFindRes)
  303. //
  304. // Create the Server's Cover-Page Directory listener notification thread
  305. //
  306. if (m_bIsFirstPopulateCall)
  307. {
  308. m_NotifyWin = new CFaxCoverPageNotifyWnd(this);
  309. if (!m_NotifyWin)
  310. {
  311. hRc = E_OUTOFMEMORY;
  312. NodeMsgBox(IDS_MEMORY);
  313. DebugPrintEx(
  314. DEBUG_ERR,
  315. TEXT("Out of memory."));
  316. goto Exit;
  317. }
  318. RECT rcRect;
  319. ZeroMemory(&rcRect, sizeof(rcRect));
  320. HWND hWndNotify = m_NotifyWin->Create(NULL,
  321. rcRect,
  322. NULL, //LPCTSTR szWindowName
  323. WS_POPUP, //DWORD dwStyle
  324. 0x0,
  325. 0);
  326. if (!(::IsWindow(hWndNotify)))
  327. {
  328. DebugPrintEx(
  329. DEBUG_ERR,
  330. _T("Failed to create window."));
  331. hWndNotify = NULL;
  332. delete m_NotifyWin;
  333. m_NotifyWin = NULL;
  334. goto Exit;
  335. }
  336. hRc = StartNotificationThread();
  337. if( S_OK != hRc)
  338. {
  339. //DbgPrint by Called Func.
  340. m_NotifyWin->DestroyWindow();
  341. delete m_NotifyWin;
  342. m_NotifyWin = NULL;
  343. goto Exit;
  344. }
  345. //
  346. // Update boolean member
  347. //
  348. m_bIsFirstPopulateCall = FALSE;
  349. DebugPrintEx(
  350. DEBUG_MSG,
  351. _T("Succeed to create server cover-page directory listener thread and to create notification window"));
  352. }
  353. ATLASSERT(S_OK == hRc);
  354. goto Exit;
  355. Error:
  356. ATLASSERT(S_OK != hRc);
  357. if ( NULL != pCoverPage )
  358. {
  359. delete pCoverPage;
  360. pCoverPage = NULL;
  361. }
  362. //
  363. // Get rid of what we had.
  364. //
  365. {
  366. // Delete each node in the list of children
  367. int iSize = m_ResultChildrenList.GetSize();
  368. for (int j = 0; j < iSize; j++)
  369. {
  370. pCoverPage = (CFaxCoverPageNode *)
  371. m_ResultChildrenList[j];
  372. ATLASSERT(pCoverPage);
  373. delete pCoverPage;
  374. pCoverPage = NULL;
  375. }
  376. // Empty the list
  377. m_ResultChildrenList.RemoveAll();
  378. // We no longer have a populated list.
  379. m_bResultChildrenListPopulated = FALSE;
  380. }
  381. Exit:
  382. if (INVALID_HANDLE_VALUE != hFile)
  383. {
  384. if (!FindClose(hFile))
  385. {
  386. DebugPrintEx(
  387. DEBUG_MSG,
  388. _T("Failed to FindClose()(ec: %ld)"),
  389. GetLastError());
  390. }
  391. }
  392. return hRc;
  393. }
  394. /*
  395. - CFaxCoverPagesNode::SetVerbs
  396. -
  397. * Purpose:
  398. * What verbs to enable/disable when this object is selected
  399. *
  400. * Arguments:
  401. * [in] pConsoleVerb - MMC ConsoleVerb interface
  402. *
  403. * Return:
  404. * OLE Error code
  405. */
  406. HRESULT CFaxCoverPagesNode::SetVerbs(IConsoleVerb *pConsoleVerb)
  407. {
  408. HRESULT hRc = S_OK;
  409. //
  410. // We want the default verb to be expand node children
  411. //
  412. hRc = pConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN);
  413. return hRc;
  414. }
  415. /*
  416. - CFaxCoverPagesNode::OnRefresh
  417. -
  418. * Purpose:
  419. * Called when refreshing the object.
  420. *
  421. * Arguments:
  422. *
  423. * Return:
  424. * OLE error code
  425. */
  426. /* virtual */HRESULT
  427. CFaxCoverPagesNode::OnRefresh(LPARAM arg,
  428. LPARAM param,
  429. IComponentData *pComponentData,
  430. IComponent * pComponent,
  431. DATA_OBJECT_TYPES type)
  432. {
  433. DEBUG_FUNCTION_NAME( _T("CFaxCoverPagesNode::OnRefresh"));
  434. HRESULT hRc = S_OK;
  435. //
  436. // Call the base class (do also repopulate)
  437. //
  438. hRc = CBaseFaxOutboundRulesNode::OnRefresh(arg,
  439. param,
  440. pComponentData,
  441. pComponent,
  442. type);
  443. if ( FAILED(hRc) )
  444. {
  445. DebugPrintEx(
  446. DEBUG_ERR,
  447. _T("Fail to call base class's OnRefresh. (hRc: %08X)"),
  448. hRc);
  449. goto Exit;
  450. }
  451. Exit:
  452. return hRc;
  453. }
  454. /*
  455. - CFaxCoverPagesNode::DoRefresh
  456. -
  457. * Purpose:
  458. * Refresh the view
  459. *
  460. * Arguments:
  461. * [in] pRoot - The root node
  462. *
  463. * Return:
  464. * OLE Error code
  465. */
  466. HRESULT
  467. CFaxCoverPagesNode::DoRefresh(CSnapInObjectRootBase *pRoot)
  468. {
  469. CComPtr<IConsole> spConsole;
  470. //
  471. // Repopulate children
  472. //
  473. RepopulateResultChildrenList();
  474. if (pRoot)
  475. {
  476. //
  477. // Get the console pointer
  478. //
  479. ATLASSERT(pRoot->m_nType == 1 || pRoot->m_nType == 2);
  480. if (pRoot->m_nType == 1)
  481. {
  482. //
  483. // m_ntype == 1 means the IComponentData implementation
  484. //
  485. CSnapin *pCComponentData = static_cast<CSnapin *>(pRoot);
  486. spConsole = pCComponentData->m_spConsole;
  487. }
  488. else
  489. {
  490. //
  491. // m_ntype == 2 means the IComponent implementation
  492. //
  493. CSnapinComponent *pCComponent = static_cast<CSnapinComponent *>(pRoot);
  494. spConsole = pCComponent->m_spConsole;
  495. }
  496. }
  497. else
  498. {
  499. ATLASSERT(m_pComponentData);
  500. spConsole = m_pComponentData->m_spConsole;
  501. }
  502. ATLASSERT(spConsole);
  503. spConsole->UpdateAllViews(NULL, NULL, NULL);
  504. return S_OK;
  505. }
  506. HRESULT
  507. CFaxCoverPagesNode::DoRefresh()
  508. {
  509. DEBUG_FUNCTION_NAME( _T("CFaxCoverPagesNode::DoRefresh()"));
  510. HRESULT hRc = S_OK;
  511. CComPtr<IConsole> spConsole;
  512. //
  513. // Repopulate children
  514. //
  515. ATLASSERT( m_pComponentData != NULL );
  516. ATLASSERT( m_pComponentData->m_spConsole != NULL );
  517. hRc = m_pComponentData->m_spConsole->UpdateAllViews( NULL, NULL, FXS_HINT_DELETE_ALL_RSLT_ITEMS);
  518. if (FAILED(hRc))
  519. {
  520. DebugPrintEx( DEBUG_ERR,
  521. _T("Unexpected error - Fail to UpdateAllViews (clear)."));
  522. NodeMsgBox(IDS_FAIL2REFRESH_THEVIEW);
  523. }
  524. RepopulateResultChildrenList();
  525. hRc = m_pComponentData->m_spConsole->UpdateAllViews( NULL, NULL, NULL);
  526. if (FAILED(hRc))
  527. {
  528. DebugPrintEx( DEBUG_ERR,
  529. _T("Unexpected error - Fail to UpdateAllViews."));
  530. NodeMsgBox(IDS_FAIL2REFRESH_THEVIEW);
  531. }
  532. return hRc;
  533. }
  534. /*
  535. - CFaxCoverPagesNode::OnNewCoverPage
  536. -
  537. * Purpose:
  538. *
  539. *
  540. * Arguments:
  541. * [out] bHandled - Do we handle it?
  542. * [in] pRoot - The root node
  543. *
  544. * Return:
  545. * OLE Error code
  546. */
  547. HRESULT
  548. CFaxCoverPagesNode::OnNewCoverPage(bool &bHandled, CSnapInObjectRootBase *pRoot)
  549. {
  550. DEBUG_FUNCTION_NAME( _T("CFaxCoverPagesNode::OnNewCoverPage"));
  551. UNREFERENCED_PARAMETER (pRoot);
  552. UNREFERENCED_PARAMETER (bHandled);
  553. DWORD ec = ERROR_SUCCESS;
  554. ec = OpenCoverPageEditor(CComBSTR(L""));
  555. if (ERROR_SUCCESS != ec)
  556. {
  557. DebugPrintEx(
  558. DEBUG_ERR,
  559. _T("Fail to OpenCoverPageEditor. (ec : %ld)"), ec);
  560. return HRESULT_FROM_WIN32( ec );
  561. }
  562. return S_OK;
  563. }
  564. /*
  565. - CFaxCoverPagesNode::OpenCoverPageEditor
  566. -
  567. * Purpose:
  568. * Delete cover page
  569. *
  570. * Arguments:
  571. * [in] bstrFileName - The cover page file name
  572. *
  573. * Assumption:
  574. * Setup prepares a shortcut to the cover page editor in the
  575. * registry "App Path". Due to this fact ShellExecute needs only the
  576. * file name of the editor and not its full path.
  577. * Return:
  578. * Standard Win32 error code
  579. */
  580. DWORD
  581. CFaxCoverPagesNode::OpenCoverPageEditor( BSTR bstrFileName)
  582. {
  583. DEBUG_FUNCTION_NAME(_T("CFaxCoverPagesNode::OpenCoverPageEditor"));
  584. DWORD dwRes = ERROR_SUCCESS;
  585. CComBSTR bstrCovEditor;
  586. HINSTANCE hCovEditor;
  587. //
  588. // get cover pages editor file
  589. //
  590. bstrCovEditor = FAX_COVER_IMAGE_NAME;
  591. if (!bstrCovEditor)
  592. {
  593. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  594. DebugPrintEx(
  595. DEBUG_ERR,
  596. _T("Failed to allocate string - out of memory"));
  597. goto Exit;
  598. }
  599. //
  600. // start cover page editor
  601. //
  602. hCovEditor = ShellExecute( NULL,
  603. TEXT("open"), // Command
  604. bstrCovEditor,
  605. (bstrFileName && lstrlen(bstrFileName)) ? // Do we have a file name?
  606. bstrFileName : // YES - use it as command line argument
  607. TEXT("/Common"), // NO - start the CP editor in the common CP folder
  608. m_pszCovDir,
  609. SW_RESTORE
  610. );
  611. if( (DWORD_PTR)hCovEditor <= 32 )
  612. {
  613. // ShellExecute fail
  614. dwRes = PtrToUlong(hCovEditor);
  615. DebugPrintEx(
  616. DEBUG_ERR,
  617. _T("Failed to run ShellExecute. (ec : %ld)"), dwRes);
  618. goto Exit;
  619. }
  620. ATLASSERT( ERROR_SUCCESS == dwRes);
  621. Exit:
  622. return dwRes;
  623. }
  624. /*
  625. - CFaxCoverPagesNode::OnAddCoverPageFile
  626. -
  627. * Purpose:
  628. *
  629. *
  630. * Arguments:
  631. * [out] bHandled - Do we handle it?
  632. * [in] pRoot - The root node
  633. *
  634. * Return:
  635. * OLE Error code
  636. */
  637. HRESULT
  638. CFaxCoverPagesNode::OnAddCoverPageFile(bool &bHandled, CSnapInObjectRootBase *pRoot)
  639. {
  640. DEBUG_FUNCTION_NAME( _T("CFaxCoverPagesNode::OnAddCoverPageFile"));
  641. HRESULT hRc = S_OK;
  642. DWORD ec = ERROR_SUCCESS;
  643. //
  644. // Function Call: browse and copy a cover page
  645. //
  646. if (!BrowseAndCopyCoverPage(
  647. m_pszCovDir,
  648. FAX_COVER_PAGE_EXT_LETTERS
  649. )
  650. )
  651. {
  652. DebugPrintEx(
  653. DEBUG_MSG,
  654. _T("BrowseAndCopyCoverPage Canceled by user or Failed."));
  655. return S_OK; //error is teated in the called func. MMC continue as usual.
  656. }
  657. else //Success
  658. {
  659. //
  660. // Repopulate: refresh the entire cover page result pane view
  661. //
  662. DoRefresh(pRoot);
  663. }
  664. return S_OK;
  665. }
  666. /*
  667. - CFaxCoverPagesNode::BrowseAndCopyCoverPage
  668. -
  669. * Purpose:
  670. * Presents a common file open dialog for the purpose of selecting a file name
  671. *
  672. * Arguments:
  673. * [in] pInitialDir - server cover page directory path
  674. * [in] pCovPageExtensionLetters - cover page's 3 leeters extension
  675. *
  676. * Return:
  677. * TRUE - got a good file name, user pressed the OK button to override file, file was copy
  678. * FALSE - got nothing or user pressed the CANCEL button, or error occures.
  679. *
  680. * the FileName is changed to have the selected file name.
  681. */
  682. BOOL
  683. CFaxCoverPagesNode::BrowseAndCopyCoverPage(
  684. LPTSTR pInitialDir,
  685. LPWSTR pCovPageExtensionLetters
  686. )
  687. {
  688. DEBUG_FUNCTION_NAME( _T("CFaxCoverPagesNode::BrowseAndCopyCoverPage"));
  689. DWORD dwError = ERROR_SUCCESS;
  690. HRESULT ret = S_OK;
  691. WCHAR filter[FXS_MAX_TITLE_LEN] = {0};
  692. WCHAR filename[MAX_PATH];
  693. WCHAR ftitle[MAX_PATH];
  694. WCHAR title[FXS_MAX_TITLE_LEN];
  695. TCHAR szDestinationFilePath[MAX_PATH] = {0};
  696. TCHAR szServerCoverPagePath[MAX_PATH];
  697. LPTSTR pExtension;
  698. LPTSTR pFilename;
  699. INT n;
  700. OPENFILENAME of;
  701. //
  702. // (1) Init
  703. //
  704. //
  705. // Check in parameters
  706. //
  707. ATLASSERT( NULL != pInitialDir && 0 != pInitialDir[0] );
  708. ATLASSERT( NULL != pInitialDir && sizeof(FAX_COVER_PAGE_EXT_LETTERS)/sizeof(WCHAR) != _tcslen(pCovPageExtensionLetters) );
  709. //
  710. // Prepare parameters for the copy operation (later)
  711. //
  712. n = _tcslen(pInitialDir);
  713. wcscpy(szServerCoverPagePath , pInitialDir);
  714. //
  715. // Prepare the OPENFILE structure fields
  716. //
  717. // Compose the file-type filter string
  718. if (::LoadString(_Module.GetResourceInstance(), IDS_CP_FILETYPE, title, FXS_MAX_TITLE_LEN) == 0)
  719. {
  720. NodeMsgBox(IDS_MEMORY);
  721. return FALSE;
  722. }
  723. _snwprintf(filter,
  724. ARR_SIZE(filter)-1,
  725. TEXT("%s (%s)%c%s%c%c"),
  726. title,
  727. FAX_COVER_PAGE_MASK,
  728. NUL,
  729. FAX_COVER_PAGE_MASK,
  730. NUL,
  731. NUL);
  732. if (::LoadString(_Module.GetResourceInstance(), IDS_BROWSE_COVERPAGE, title, FXS_MAX_TITLE_LEN) == 0)
  733. {
  734. NodeMsgBox(IDS_MEMORY);
  735. return FALSE;
  736. }
  737. filename[0] = NUL;
  738. ftitle[0] = NUL;
  739. //
  740. // Init the OPENFILE structure
  741. //
  742. of.lStructSize = sizeof( OPENFILENAME );
  743. of.hwndOwner = NULL;
  744. of.hInstance = GetModuleHandle( NULL );
  745. of.lpstrFilter = filter;
  746. of.lpstrCustomFilter = NULL;
  747. of.nMaxCustFilter = 0;
  748. of.nFilterIndex = 1;
  749. of.lpstrFile = filename;
  750. of.nMaxFile = MAX_PATH;
  751. of.lpstrFileTitle = ftitle;
  752. of.nMaxFileTitle = MAX_PATH;
  753. of.lpstrInitialDir = pInitialDir;
  754. of.lpstrTitle = title;
  755. of.Flags = OFN_EXPLORER | OFN_HIDEREADONLY |
  756. OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; //OFN_ENABLEHOOK ;
  757. of.nFileOffset = 0;
  758. of.nFileExtension = 0;
  759. of.lpstrDefExt = pCovPageExtensionLetters;
  760. of.lCustData = 0;
  761. of.lpfnHook = NULL; //BrowseHookProc;
  762. of.lpTemplateName = NULL;
  763. //
  764. // (2) Call the "Open File" dialog
  765. //
  766. if (! GetOpenFileName(&of))
  767. {
  768. DebugPrintEx(
  769. DEBUG_MSG,
  770. _T("GetOpenFileName was canceled by user."));
  771. return FALSE;
  772. }
  773. //
  774. // (3) Check the output of the source path, filename and extension
  775. //
  776. //
  777. // a. Make sure the selected filename has the correct extension
  778. //
  779. //
  780. // Find the filename portion given a filename:
  781. // return a pointer to the '.' character if successful
  782. // NULL if there is no extension
  783. //
  784. pFilename = &filename[of.nFileOffset];
  785. pExtension = _tcsrchr(filename, _T('.'));
  786. if (
  787. (pExtension == NULL)
  788. ||
  789. (_tcsicmp(pExtension, FAX_COVER_PAGE_FILENAME_EXT) != EQUAL_STRING)
  790. )
  791. {
  792. NodeMsgBox(IDS_BAD_CP_EXTENSION);
  793. return FALSE;
  794. }
  795. //
  796. // b. Check if the selected file directory is the
  797. // default server cover page directory
  798. //
  799. if (_tcsnicmp(filename, szServerCoverPagePath, n) == EQUAL_STRING)
  800. {
  801. NodeMsgBox(IDS_CP_DUPLICATE); //YESNO
  802. // Work was already done. We are leaving...
  803. goto Exit;
  804. }
  805. //
  806. // The check if the selected file is already inside the
  807. // cover page directory is done with the copy operation itself.
  808. //
  809. //
  810. // The check if the destination cover page directory exists done
  811. // while the copy operation itself.
  812. //
  813. //
  814. // (4) Copy the selected cover page file to the Server Cover page directory
  815. //
  816. //
  817. // a. prepare from pSelected the destination path
  818. //
  819. if (n + 1 + _tcslen(pFilename) >= MAX_PATH || pFilename >= pExtension)
  820. {
  821. NodeMsgBox(IDS_FILENAME_TOOLONG);
  822. return FALSE;
  823. }
  824. _snwprintf(szDestinationFilePath,
  825. ARR_SIZE(szDestinationFilePath)-1,
  826. TEXT("%s%s%s%c"),
  827. szServerCoverPagePath,
  828. FAX_PATH_SEPARATOR_STR,
  829. pFilename,
  830. NUL);
  831. //
  832. // b. Copy the selected cover page file
  833. // to the server cover page default directory
  834. //
  835. if (!CopyFile(filename, szDestinationFilePath, TRUE))
  836. {
  837. dwError = GetLastError();
  838. if ( ERROR_FILE_EXISTS == dwError)
  839. {
  840. DebugPrintEx(DEBUG_MSG,
  841. _T("Copy cover page already exists at destination."));
  842. ret = NodeMsgBox(IDS_CP_DUP_YESNO, MB_YESNO | MB_ICONQUESTION );
  843. if ((HRESULT)IDYES == ret)
  844. {
  845. //Copy any way
  846. if (!CopyFile(filename, szDestinationFilePath, FALSE))
  847. {
  848. dwError = GetLastError();
  849. DebugPrintEx(DEBUG_ERR,
  850. _T("Copy cover page Failed (ec = %ld)."), dwError);
  851. NodeMsgBox(IDS_FAILED2COPY_COVERPAGE);
  852. return FALSE;
  853. }
  854. DebugPrintEx(DEBUG_MSG,
  855. _T("Copy cover page done any way."));
  856. }
  857. else //ret == IDNO
  858. {
  859. DebugPrintEx(DEBUG_MSG,
  860. _T("Copy cover page was canceled by user due to file existance at destination."));
  861. //lets stay friends even after this operation cancel..
  862. return TRUE;
  863. }
  864. } //dwError != ERROR_FILE_EXISTS
  865. else
  866. {
  867. DebugPrintEx(DEBUG_ERR,
  868. _T("Copy cover page Failed (ec = %ld)."), dwError);
  869. NodeMsgBox(IDS_FAILED2COPY_COVERPAGE);
  870. return FALSE;
  871. }
  872. }
  873. Exit:
  874. return TRUE;
  875. }
  876. /*
  877. - CFaxCoverPagesNode::DeleteCoverPage
  878. -
  879. * Purpose:
  880. * Delete cover page
  881. *
  882. * Arguments:
  883. * [in] bstrName - The cover page full path
  884. * [in] pChildNode - The node to be deleted
  885. *
  886. * Return:
  887. * OLE Error code
  888. */
  889. HRESULT
  890. CFaxCoverPagesNode::DeleteCoverPage(BSTR bstrName, CFaxCoverPageNode *pChildNode)
  891. {
  892. DEBUG_FUNCTION_NAME(_T("CFaxCoverPagesNode::DeleteRule"));
  893. HRESULT hRc = S_OK;
  894. DWORD ec = ERROR_SUCCESS;
  895. ATLASSERT(bstrName);
  896. ATLASSERT(pChildNode);
  897. if (!DeleteFile(bstrName))
  898. {
  899. ec = GetLastError();
  900. DebugPrintEx(
  901. DEBUG_ERR,
  902. _T("Fail to DeleteFile. (ec: %ld)"),
  903. ec);
  904. goto Error;
  905. }
  906. //
  907. // Remove from MMC result pane
  908. //
  909. ATLASSERT(pChildNode);
  910. hRc = RemoveChild(pChildNode);
  911. if (FAILED(hRc))
  912. {
  913. DebugPrintEx(
  914. DEBUG_ERR,
  915. TEXT("Fail to remove rule. (hRc: %08X)"),
  916. hRc);
  917. //NodeMsgBox by Caller func.
  918. return hRc;
  919. }
  920. //
  921. // Call the group destructor
  922. //
  923. delete pChildNode;
  924. ATLASSERT(S_OK == hRc);
  925. DebugPrintEx( DEBUG_MSG,
  926. _T("The rule was removed successfully."));
  927. goto Exit;
  928. Error:
  929. ATLASSERT(ERROR_SUCCESS != ec);
  930. hRc = HRESULT_FROM_WIN32(ec);
  931. //NodeMsgBox by Caller func.;
  932. Exit:
  933. return hRc;
  934. }
  935. /*
  936. - CFaxCoverPagesNode::InitDisplayName
  937. -
  938. * Purpose:
  939. * To load the node's Displayed-Name string.
  940. *
  941. * Arguments:
  942. *
  943. * Return:
  944. * OLE error code
  945. */
  946. HRESULT CFaxCoverPagesNode::InitDisplayName()
  947. {
  948. DEBUG_FUNCTION_NAME(_T("CFaxCoverPagesNode::InitDisplayName"));
  949. HRESULT hRc = S_OK;
  950. if (!m_bstrDisplayName.LoadString(_Module.GetResourceInstance(),
  951. IDS_DISPLAY_STR_COVERPAGES))
  952. {
  953. hRc = E_OUTOFMEMORY;
  954. goto Error;
  955. }
  956. ATLASSERT( S_OK == hRc);
  957. goto Exit;
  958. Error:
  959. ATLASSERT( S_OK != hRc);
  960. m_bstrDisplayName = L"";
  961. DebugPrintEx(
  962. DEBUG_ERR,
  963. TEXT("Fail to Load server name string."));
  964. NodeMsgBox(IDS_MEMORY);
  965. Exit:
  966. return hRc;
  967. }
  968. /*
  969. - CFaxCoverPagesNode::NotifyThreadProc
  970. -
  971. * Purpose:
  972. * To load the node's Displaed-Name string.
  973. *
  974. * Arguments:
  975. * [in] - pointer to the Fax Cover-Pages Node
  976. * Return:
  977. * WIN32 error code
  978. */
  979. DWORD WINAPI CFaxCoverPagesNode::NotifyThreadProc ( LPVOID lpParameter)
  980. {
  981. DEBUG_FUNCTION_NAME(_T("CFaxCoverPagesNode::NotifyThreadProc"));
  982. DWORD dwRes = ERROR_SUCCESS;
  983. HRESULT hRc = S_OK;
  984. CFaxCoverPagesNode *pCovFolder = (CFaxCoverPagesNode *)lpParameter;
  985. ATLASSERT (pCovFolder);
  986. HANDLE hWaitHandles[2];
  987. DWORD dwNotifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME |
  988. FILE_NOTIFY_CHANGE_SIZE |
  989. FILE_NOTIFY_CHANGE_LAST_WRITE;
  990. //
  991. // register for a first folder notification
  992. //
  993. hWaitHandles[0] = FindFirstChangeNotification(
  994. pCovFolder->m_pszCovDir,
  995. FALSE,
  996. dwNotifyFilter);
  997. if(INVALID_HANDLE_VALUE == hWaitHandles[0])
  998. {
  999. dwRes = GetLastError();
  1000. DebugPrintEx(
  1001. DEBUG_ERR,
  1002. _T("Failed to FindFirstChangeNotification. (ec : %ld)"),
  1003. dwRes);
  1004. return dwRes;
  1005. }
  1006. while(TRUE)
  1007. {
  1008. hWaitHandles[1] = m_hStopNotificationThreadEvent;
  1009. if (NULL == hWaitHandles[1])
  1010. {
  1011. //
  1012. // We're shutting down
  1013. //
  1014. goto Exit;
  1015. }
  1016. //
  1017. // wait for folder notification or shutdown
  1018. //
  1019. dwRes = WaitForMultipleObjects(2, hWaitHandles, FALSE, INFINITE);
  1020. switch (dwRes)
  1021. {
  1022. case WAIT_OBJECT_0:
  1023. //
  1024. // folder notification
  1025. //
  1026. if(NULL != pCovFolder->m_NotifyWin && pCovFolder->m_NotifyWin->IsWindow())
  1027. {
  1028. if ( !pCovFolder->m_NotifyWin->PostMessage(WM_NEW_COV))
  1029. {
  1030. DebugPrintEx(DEBUG_ERR,
  1031. _T("Fail to PostMessage"));
  1032. // do not exit. continue!
  1033. }
  1034. }
  1035. break;
  1036. case WAIT_OBJECT_0 + 1:
  1037. //
  1038. // Shutdown is now in progress
  1039. //
  1040. DebugPrintEx(
  1041. DEBUG_MSG,
  1042. _T("Shutdown in progress"));
  1043. dwRes = ERROR_SUCCESS;
  1044. goto Exit;
  1045. case WAIT_FAILED:
  1046. dwRes = GetLastError();
  1047. DebugPrintEx(
  1048. DEBUG_ERR,
  1049. _T("Failed to WaitForMultipleObjects. (ec : %ld)"),
  1050. dwRes);
  1051. goto Exit;
  1052. case WAIT_TIMEOUT:
  1053. DebugPrintEx(
  1054. DEBUG_ERR,
  1055. _T("Reach WAIT_TIMEOUT in INFINITE wait!"));
  1056. ATLASSERT(FALSE);
  1057. goto Exit;
  1058. default:
  1059. DebugPrintEx(
  1060. DEBUG_ERR,
  1061. _T("Failed. Unexpected error (ec : %ld)"),
  1062. dwRes);
  1063. ATLASSERT(0);
  1064. goto Exit;
  1065. }
  1066. //
  1067. // register for a next folder notification
  1068. //
  1069. if(!FindNextChangeNotification(hWaitHandles[0]))
  1070. {
  1071. dwRes = GetLastError();
  1072. DebugPrintEx(
  1073. DEBUG_ERR,
  1074. _T("Failed to FindNextChangeNotification (ec : %ld)"),
  1075. dwRes);
  1076. goto Exit;
  1077. }
  1078. }
  1079. Exit:
  1080. //
  1081. // close notification handel
  1082. //
  1083. if(!FindCloseChangeNotification(hWaitHandles[0]))
  1084. {
  1085. dwRes = GetLastError();
  1086. DebugPrintEx(
  1087. DEBUG_ERR,
  1088. _T("Failed to FindCloseChangeNotification. (ec : %ld)"),
  1089. dwRes);
  1090. }
  1091. return dwRes;
  1092. } // NotifyThreadProc
  1093. /*
  1094. - CFaxCoverPagesNode::StartNotificationThread
  1095. -
  1096. * Purpose:
  1097. * Start the server cover page directory listning thread.
  1098. *
  1099. * Arguments:
  1100. *
  1101. * Return:
  1102. * OLE Error code
  1103. */
  1104. HRESULT CFaxCoverPagesNode::StartNotificationThread()
  1105. {
  1106. DEBUG_FUNCTION_NAME(_T("CFaxCoverPagesNode::StartNotificationThread"));
  1107. HRESULT hRc = S_OK;
  1108. DWORD ec = ERROR_SUCCESS;
  1109. //
  1110. // create thread
  1111. //
  1112. DWORD dwThreadId;
  1113. m_hNotifyThread = CreateThread (
  1114. NULL, // No security
  1115. 0, // Default stack size
  1116. NotifyThreadProc,// Thread procedure
  1117. (LPVOID)this, // Parameter
  1118. 0, // Normal creation
  1119. &dwThreadId // We must have a thread id for win9x
  1120. );
  1121. if (NULL == m_hNotifyThread)
  1122. {
  1123. ec = GetLastError ();
  1124. DebugPrintEx(
  1125. DEBUG_ERR,
  1126. _T("Fail to CreateThread. (ec: %ld)"),
  1127. ec);
  1128. hRc = HRESULT_FROM_WIN32(ec);
  1129. goto Exit;
  1130. }
  1131. Exit:
  1132. return hRc;
  1133. }
  1134. /*
  1135. - CFaxCoverPagesNode::StopNotificationThread
  1136. -
  1137. * Purpose:
  1138. * Stop the server cover page directory listning thread.
  1139. *
  1140. * Arguments:
  1141. *
  1142. * Return:
  1143. * OLE Error code
  1144. */
  1145. HRESULT CFaxCoverPagesNode::StopNotificationThread()
  1146. {
  1147. DEBUG_FUNCTION_NAME(_T("CFaxCoverPagesNode::StopNotificationThread"));
  1148. HRESULT hRc = S_OK;
  1149. //
  1150. // Signal the event telling all our thread the app. is shutting down
  1151. //
  1152. SetEvent (m_hStopNotificationThreadEvent);
  1153. //
  1154. // wait for the thread
  1155. //
  1156. if (NULL != m_hNotifyThread )
  1157. {
  1158. DWORD dwWaitRes = WaitForSingleObject(m_hNotifyThread, INFINITE);
  1159. switch(dwWaitRes)
  1160. {
  1161. case WAIT_OBJECT_0:
  1162. //Success
  1163. DebugPrintEx(
  1164. DEBUG_MSG,
  1165. _T("Succeed to WaitForSingleObject from notify thread. (ec : %ld)"));
  1166. break;
  1167. case WAIT_FAILED:
  1168. dwWaitRes = GetLastError();
  1169. if (ERROR_INVALID_HANDLE != dwWaitRes)
  1170. {
  1171. DebugPrintEx(
  1172. DEBUG_ERR,
  1173. _T("Failed to WaitForSingleObject. (ec : %ld)"),
  1174. dwWaitRes);
  1175. hRc = E_FAIL;
  1176. }
  1177. break;
  1178. case WAIT_TIMEOUT:
  1179. DebugPrintEx(
  1180. DEBUG_ERR,
  1181. _T("WAIT_TIMEOUT - Failed to WaitForSingleObject. (ec : %ld)"),
  1182. dwWaitRes);
  1183. hRc = E_FAIL;
  1184. ATLASSERT(FALSE);
  1185. break;
  1186. default:
  1187. DebugPrintEx(
  1188. DEBUG_ERR,
  1189. _T("Failed to WaitForSingleObject. (ec : %ld)"),
  1190. dwWaitRes);
  1191. hRc = E_FAIL;
  1192. break;
  1193. }
  1194. CloseHandle (m_hNotifyThread);
  1195. m_hNotifyThread = NULL;
  1196. }
  1197. return hRc;
  1198. }
  1199. /*
  1200. - CFaxCoverPagesNode::RestartNotificationThread
  1201. -
  1202. * Purpose:
  1203. * Restart the server cover page directory listning thread.
  1204. *
  1205. * Arguments:
  1206. *
  1207. * Return:
  1208. * OLE Error code
  1209. */
  1210. HRESULT CFaxCoverPagesNode::RestartNotificationThread()
  1211. {
  1212. DEBUG_FUNCTION_NAME(_T("CFaxCoverPagesNode::RestartNotificationThread"));
  1213. HRESULT hRc = S_OK;
  1214. //
  1215. // Stop
  1216. //
  1217. hRc = StopNotificationThread();
  1218. if (S_OK != hRc)
  1219. {
  1220. //DbgMsg And MsgBox by called func.
  1221. goto Exit;
  1222. }
  1223. //
  1224. // Reset Shutdown Event handle
  1225. //
  1226. if (m_hStopNotificationThreadEvent)
  1227. {
  1228. ResetEvent (m_hStopNotificationThreadEvent);
  1229. }
  1230. //
  1231. // Start
  1232. //
  1233. hRc = StartNotificationThread();
  1234. if (S_OK != hRc)
  1235. {
  1236. //DbgMsg And MsgBox by called func.
  1237. goto Exit;
  1238. }
  1239. Exit:
  1240. return hRc;
  1241. }
  1242. /*
  1243. +
  1244. + CFaxCoverPagesNode::OnShowContextHelp
  1245. *
  1246. * Purpose:
  1247. * Overrides CSnapinNode::OnShowContextHelp.
  1248. *
  1249. * Arguments:
  1250. *
  1251. * Return:
  1252. - OLE error code
  1253. -
  1254. */
  1255. HRESULT CFaxCoverPagesNode::OnShowContextHelp(
  1256. IDisplayHelp* pDisplayHelp, LPOLESTR helpFile)
  1257. {
  1258. return DisplayContextHelp(pDisplayHelp, helpFile, HLP_COVER_PAGES);
  1259. }
  1260. ///////////////////////////////////////////////////////////////////
  1261. /*
  1262. - CFaxCoverPagesNode::UpdateMenuState
  1263. -
  1264. * Purpose:
  1265. * Overrides the ATL CSnapInItemImpl::UpdateMenuState
  1266. * which only have one line inside it "return;"
  1267. * This function implements the grayed\ungrayed view for the
  1268. * the Enable and the Disable menus.
  1269. *
  1270. * Arguments:
  1271. * [in] id - unsigned int with the menu IDM value
  1272. * [out] pBuf - string
  1273. * [out] flags - pointer to flags state combination unsigned int
  1274. *
  1275. * Return:
  1276. * no return value - void function
  1277. */
  1278. void CFaxCoverPagesNode::UpdateMenuState(UINT id, LPTSTR pBuf, UINT *flags)
  1279. {
  1280. DEBUG_FUNCTION_NAME( _T("CFaxCoverPagesNode::UpdateMenuState"));
  1281. UNREFERENCED_PARAMETER (pBuf);
  1282. switch (id)
  1283. {
  1284. case IDM_NEW_COVERPAGE:
  1285. *flags = IsFaxComponentInstalled(FAX_COMPONENT_CPE) ? MF_ENABLED : MF_GRAYED;
  1286. break;
  1287. default:
  1288. break;
  1289. }
  1290. return;
  1291. }