Source code of Windows XP (NT5)
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.

1148 lines
32 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. ilogcat.cpp
  5. Abstract:
  6. Internal implementation for a logging category item.
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Darwin Ouyang (t-darouy) 30-Sept-1997
  11. --*/
  12. #include "StdAfx.h"
  13. #include "inode.h" // base class
  14. #include "iroot.h" // root item
  15. #include "idevice.h" // device item
  16. #include "idevices.h" // devices folder
  17. #include "faxcompd.h" // CFaxComponentData
  18. #include "faxcomp.h" // CFaxComponent
  19. #include "faxdataobj.h" // dataobject
  20. #include "faxstrt.h" // string table
  21. #include "ddevmain.h" // device settings
  22. #include "droutpri.h" // route extension priority
  23. #include "faxreg.h"
  24. #pragma hdrstop
  25. extern CStringTable * GlobalStringTable;
  26. CRITICAL_SECTION CInternalDevice::csDeviceLock = {0};
  27. // defines for context menu command ids
  28. #define SEND_CONTEXT_ITEM 11
  29. #define RECV_CONTEXT_ITEM 12
  30. // defines for toolbar button command ids
  31. #define CMD_PRI_UP 123
  32. #define CMD_PRI_DOWN 124
  33. // Generated with uuidgen. Each node must have a GUID associated with it.
  34. // This one is for the main root node.
  35. const GUID GUID_DeviceNode = /* de58ae00-4c0f-11d1-9083-00a0c90ab504 */
  36. {
  37. 0xde58ae00,
  38. 0x4c0f,
  39. 0x11d1,
  40. {0x90, 0x83, 0x00, 0xa0, 0xc9, 0x0a, 0xb5, 0x04}
  41. };
  42. ////////////////////////////////////////////////////////////////////////////////////////////////////
  43. ////////////////////////////////////////////////////////////////////////////////////////////////////
  44. ////////////////////////////////////////////////////////////////////////////////////////////////////
  45. ////////////////////////////////////////////////////////////////////////////////////////////////////
  46. //
  47. //
  48. // Constructor and destructor
  49. //
  50. //
  51. CInternalDevice::CInternalDevice(
  52. IN CInternalNode * pParent,
  53. IN CFaxComponentData * pCompData,
  54. IN HANDLE faxHandle,
  55. IN DWORD devID )
  56. : CInternalNode( pParent, pCompData ),
  57. dwDeviceId( devID ),
  58. hFaxServer( faxHandle ),
  59. pDeviceInfo( NULL ),
  60. myToolBar( NULL )
  61. /*++
  62. Routine Description:
  63. Constructor
  64. Arguments:
  65. pParent - pointer to parent node, in this case unused
  66. pCompData - pointer to IComponentData implementation for snapin global data
  67. Return Value:
  68. None.
  69. --*/
  70. {
  71. RetrieveNewInfo();
  72. DebugPrint(( TEXT("CInternalDevice Created") ));
  73. }
  74. CInternalDevice::~CInternalDevice()
  75. /*++
  76. Routine Description:
  77. Destructor
  78. Arguments:
  79. None.
  80. Return Value:
  81. None.
  82. --*/
  83. {
  84. if( myToolBar != NULL ) {
  85. myToolBar->Release();
  86. myToolBar = NULL ;
  87. }
  88. DebugPrint(( TEXT("CInternalDevice Destroyed") ));
  89. }
  90. ////////////////////////////////////////////////////////////////////////////////////////////////////
  91. ////////////////////////////////////////////////////////////////////////////////////////////////////
  92. ////////////////////////////////////////////////////////////////////////////////////////////////////
  93. ////////////////////////////////////////////////////////////////////////////////////////////////////
  94. //
  95. //
  96. // Custom Clipboard Format handlers.
  97. //
  98. //
  99. // clipboard format
  100. UINT CInternalDevice::s_cfFaxDevice = 0;
  101. UINT CInternalDevice::s_cfFaxServerDown = 0;
  102. #define CCF_FAX_DEVICE L"CF_FAX_DEVICE"
  103. #define CCF_FAX_SERVER_DOWN L"CF_FAX_SERVER_DOWN"
  104. // clipboard methods
  105. HRESULT
  106. CInternalDevice::DataObjectRegisterFormats()
  107. /*++
  108. Routine Description:
  109. Registers the custom clipboard formats for the device node.
  110. Arguments:
  111. None.
  112. Return Value:
  113. HRESULT which indicates SUCCEEDED() or FAILED()
  114. --*/
  115. {
  116. s_cfFaxDevice = RegisterClipboardFormat(CCF_FAX_DEVICE);
  117. s_cfFaxServerDown = RegisterClipboardFormat(CCF_FAX_SERVER_DOWN);
  118. return S_OK;
  119. }
  120. HRESULT
  121. CInternalDevice::DataObjectGetDataHere(
  122. IN FORMATETC __RPC_FAR *pFormatEtc,
  123. IN IStream * pstm )
  124. /*++
  125. Routine Description:
  126. Handles GetDataHere for custom clipboard formats specific to this
  127. particular node.
  128. The default implementation asserts since there should be no unhandled
  129. formats.
  130. Arguments:
  131. pFormatEtc - the FORMATETC struction indicating where and what the
  132. client is requesting
  133. pstm - the stream to write the data to.
  134. Return Value:
  135. HRESULT indicating SUCCEEDED() or FAILED()
  136. --*/
  137. {
  138. const CLIPFORMAT cf = pFormatEtc->cfFormat;
  139. HANDLE faxHandle = ((CInternalDevices *)m_pParentINode)->faxHandle;
  140. HRESULT hr = S_OK;
  141. LPTSTR tstr;
  142. BOOL temp;
  143. assert( faxHandle != NULL );
  144. assert( pDeviceInfo != NULL );
  145. if( cf == s_cfFaxDevice ) {
  146. // handle the device clipboard format
  147. pstm->Write( &(faxHandle), sizeof(HANDLE), NULL );
  148. pstm->Write( &(pDeviceInfo->DeviceId), sizeof(DWORD), NULL );
  149. tstr = m_pCompData->globalRoot->GetMachine();
  150. if( tstr != NULL ) {
  151. pstm->Write( tstr, (MAX_COMPUTERNAME_LENGTH+1) * sizeof( TCHAR ), NULL );
  152. } else {
  153. pstm->Write( &tstr, sizeof( NULL ), NULL );
  154. }
  155. } else if( cf == s_cfFaxServerDown ) {
  156. // handle the query server down format
  157. temp = m_pCompData->QueryRpcError();
  158. pstm->Write( &temp, sizeof( BOOL ), NULL );
  159. } else {
  160. hr = DV_E_FORMATETC;
  161. }
  162. return hr;
  163. }
  164. ////////////////////////////////////////////////////////////////////////////////////////////////////
  165. ////////////////////////////////////////////////////////////////////////////////////////////////////
  166. ////////////////////////////////////////////////////////////////////////////////////////////////////
  167. ////////////////////////////////////////////////////////////////////////////////////////////////////
  168. //
  169. //
  170. // Mandatory CInternalNode implementations.
  171. //
  172. //
  173. const GUID *
  174. CInternalDevice::GetNodeGUID()
  175. /*++
  176. Routine Description:
  177. Returns the node's associated GUID.
  178. Arguments:
  179. None.
  180. Return Value:
  181. A const pointer to a binary GUID.
  182. --*/
  183. {
  184. // DebugPrint(( TEXT("Trace: CInternalDevice::GetNodeGUID") ));
  185. return &GUID_DeviceNode;
  186. }
  187. const LPTSTR
  188. CInternalDevice::GetNodeDisplayName()
  189. /*++
  190. Routine Description:
  191. Returns a const TSTR pointer to the node's display name.
  192. Arguments:
  193. None.
  194. Return Value:
  195. A const pointer to a TSTR.
  196. --*/
  197. {
  198. // DebugPrint(( TEXT("Trace: CInternalDevice::GetNodeDisplayName") ));
  199. return (LPTSTR)pDeviceInfo->DeviceName;
  200. }
  201. const LONG_PTR
  202. CInternalDevice::GetCookie()
  203. /*++
  204. Routine Description:
  205. Returns the cookie for this node.
  206. Arguments:
  207. None.
  208. Return Value:
  209. A const long containing the cookie for the pointer,
  210. in this case, (long)this.
  211. --*/
  212. {
  213. // DebugPrint(( TEXT("Trace: CInternalDevice::GetCookie") ));
  214. DebugPrint(( TEXT("Device Node Cookie: 0x%p"), this ));
  215. return (LONG_PTR)this; // device node's cookie is the this pointer.
  216. }
  217. ////////////////////////////////////////////////////////////////////////////////////////////////////
  218. ////////////////////////////////////////////////////////////////////////////////////////////////////
  219. ////////////////////////////////////////////////////////////////////////////////////////////////////
  220. ////////////////////////////////////////////////////////////////////////////////////////////////////
  221. //
  222. //
  223. // IComponent over-rides
  224. //
  225. //
  226. HRESULT STDMETHODCALLTYPE CInternalDevice::ResultGetDisplayInfo(
  227. IN CFaxComponent * pComp,
  228. IN OUT RESULTDATAITEM __RPC_FAR *pResultDataItem)
  229. /*++
  230. Routine Description:
  231. This routine dispatches result pane GetDisplayInfo requests to the appropriate handlers
  232. in the mandatory implementations of the node, as well as handling special case data requests.
  233. Arguments:
  234. pComp - a pointer to the IComponent associated with this node.
  235. pResultDataItem - a pointer to the RESULTDATAITEM struct which needs to be filled in.
  236. Return Value:
  237. HRESULT indicating SUCCEEDED() or FAILED()
  238. --*/
  239. {
  240. // DebugPrint(( TEXT("Trace: CInternalDevice::ResultGetDisplayInfo") ));
  241. TCHAR buffer[ 20 ];
  242. HRESULT hr = S_OK;
  243. ZeroMemory( (PVOID)buffer, 20 * sizeof( TCHAR ) );
  244. assert(pResultDataItem != NULL);
  245. do {
  246. if( m_pCompData->QueryRpcError() == TRUE ) {
  247. // notify the parent of the failure
  248. ((CInternalDevices *)m_pParentINode)->NotifyFailure( pComp );
  249. hr = E_UNEXPECTED;
  250. break;
  251. }
  252. if( pResultDataItem->mask & RDI_STR ) {
  253. if( pResultDataItem->nCol == 0 ) {
  254. hr = RetrieveNewInfo();
  255. if( FAILED( hr ) ) {
  256. assert( FALSE );
  257. break;
  258. }
  259. pResultDataItem->str = GetNodeDisplayName();
  260. }
  261. if( pResultDataItem->nCol == 1 ) {
  262. if( pDeviceInfo->Flags & FPF_SEND ) {
  263. pResultDataItem->str = ::GlobalStringTable->GetString( IDS_YES );
  264. } else {
  265. pResultDataItem->str = ::GlobalStringTable->GetString( IDS_NO );
  266. }
  267. }
  268. if( pResultDataItem->nCol == 2 ) {
  269. if( pDeviceInfo->Flags & FPF_RECEIVE ) {
  270. pResultDataItem->str = ::GlobalStringTable->GetString( IDS_YES );
  271. } else {
  272. pResultDataItem->str = ::GlobalStringTable->GetString( IDS_NO );
  273. }
  274. }
  275. if( pResultDataItem->nCol == 3 ) {
  276. pResultDataItem->str = (LPTSTR)pDeviceInfo->Tsid;
  277. }
  278. if( pResultDataItem->nCol == 4 ) {
  279. pResultDataItem->str = (LPTSTR)pDeviceInfo->Csid;
  280. }
  281. if( pResultDataItem->nCol == 5 ) {
  282. pResultDataItem->str = GetStatusString( pDeviceInfo->State );
  283. }
  284. if( pResultDataItem->nCol == 6 ) {
  285. pResultDataItem->str = _itot( pDeviceInfo->Priority, buffer, 10 );
  286. }
  287. if( pResultDataItem->mask & RDI_IMAGE ) {
  288. pResultDataItem->nImage = GetNodeDisplayImage();
  289. }
  290. }
  291. } while( 0 );
  292. return hr;
  293. }
  294. ////////////////////////////////////////////////////////////////////////////////////////////////////
  295. ////////////////////////////////////////////////////////////////////////////////////////////////////
  296. ////////////////////////////////////////////////////////////////////////////////////////////////////
  297. ////////////////////////////////////////////////////////////////////////////////////////////////////
  298. //
  299. //
  300. // IExtendContextMenu event handlers
  301. //
  302. //
  303. HRESULT
  304. STDMETHODCALLTYPE
  305. CInternalDevice::ComponentContextMenuAddMenuItems(
  306. IN CFaxComponent * pComp,
  307. IN CFaxDataObject * piDataObject,
  308. IN LPCONTEXTMENUCALLBACK piCallback,
  309. IN OUT long __RPC_FAR *pInsertionAllowed)
  310. /*++
  311. Routine Description:
  312. Adds items to the context menu.
  313. Arguments:
  314. pComp - a pointer to the IComponent associated with this node.
  315. piDataObject - pointer to the dataobject associated with this node
  316. piCallback - a pointer to the IContextMenuCallback used to insert pages
  317. pInsertionAllowed - a set of flag indicating whether insertion is allowed.
  318. Return Value:
  319. HRESULT indicating SUCCEEDED() or FAILED()
  320. --*/
  321. {
  322. DebugPrint(( TEXT("Trace: CInternalDevice::ComponentContextMenuAddMenuItems") ));
  323. CONTEXTMENUITEM menuItem;
  324. HRESULT hr = S_OK;
  325. if( !( *pInsertionAllowed | CCM_INSERTIONALLOWED_TOP ) ) {
  326. assert( FALSE );
  327. return S_OK;
  328. }
  329. // build the submenu items
  330. ZeroMemory( ( void* )&menuItem, sizeof( menuItem ) );
  331. menuItem.strName = ::GlobalStringTable->GetString( IDS_DEVICE_SEND_EN );
  332. menuItem.strStatusBarText = ::GlobalStringTable->GetString( IDS_DEVICE_SEND_EN_DESC );
  333. menuItem.lCommandID = SEND_CONTEXT_ITEM;
  334. menuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP;
  335. if( pDeviceInfo->Flags & FPF_SEND ) {
  336. menuItem.fFlags = MF_ENABLED | MF_CHECKED;
  337. } else {
  338. menuItem.fFlags = MF_ENABLED;
  339. }
  340. menuItem.fSpecialFlags = 0;
  341. hr = piCallback->AddItem( &menuItem );
  342. if( FAILED(hr) ) {
  343. assert(FALSE);
  344. return hr;
  345. }
  346. ZeroMemory( ( void* )&menuItem, sizeof( menuItem ) );
  347. menuItem.strName = ::GlobalStringTable->GetString( IDS_DEVICE_RECV_EN );
  348. menuItem.strStatusBarText = ::GlobalStringTable->GetString( IDS_DEVICE_RECV_EN_DESC );
  349. menuItem.lCommandID = RECV_CONTEXT_ITEM;
  350. menuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP;
  351. if( pDeviceInfo->Flags & FPF_RECEIVE ) {
  352. menuItem.fFlags = MF_ENABLED | MF_CHECKED;
  353. } else {
  354. menuItem.fFlags = MF_ENABLED;
  355. }
  356. menuItem.fSpecialFlags = 0;
  357. hr = piCallback->AddItem( &menuItem );
  358. if( FAILED(hr) ) {
  359. assert(FALSE);
  360. return hr;
  361. }
  362. return hr;
  363. }
  364. HRESULT
  365. STDMETHODCALLTYPE
  366. CInternalDevice::ComponentContextMenuCommand(
  367. IN CFaxComponent * pComp,
  368. IN long lCommandID,
  369. IN CFaxDataObject * piDataObject)
  370. /*++
  371. Routine Description:
  372. Context menu event handler.
  373. Arguments:
  374. pComp - a pointer to the IComponent associated with this node.
  375. lCommandID - the command ID
  376. piDataObject - pointer to the dataobject associated with this node
  377. Return Value:
  378. HRESULT indicating SUCCEEDED() or FAILED()
  379. --*/
  380. {
  381. DebugPrint(( TEXT("Trace: CInternalDevice::ComponentContextMenuCommand") ));
  382. HRESULT hr = S_OK;
  383. assert( hFaxServer != NULL );
  384. do {
  385. // retrieve data
  386. hr = RetrieveNewInfo();
  387. if( FAILED( hr ) ) {
  388. assert( FALSE );
  389. break;
  390. }
  391. switch( lCommandID ) {
  392. case SEND_CONTEXT_ITEM:
  393. if( pDeviceInfo->Flags & FPF_SEND ) {
  394. pDeviceInfo->Flags = pDeviceInfo->Flags & (~FPF_SEND);
  395. } else {
  396. pDeviceInfo->Flags = pDeviceInfo->Flags | FPF_SEND;
  397. }
  398. break;
  399. case RECV_CONTEXT_ITEM:
  400. if( pDeviceInfo->Flags & FPF_RECEIVE ) {
  401. pDeviceInfo->Flags = pDeviceInfo->Flags & (~FPF_RECEIVE);
  402. } else {
  403. pDeviceInfo->Flags = pDeviceInfo->Flags | FPF_RECEIVE;
  404. }
  405. break;
  406. default:
  407. assert(FALSE);
  408. break;
  409. }
  410. // commit new settings
  411. hr = CommitNewInfo();
  412. if( FAILED( hr ) ) {
  413. break;
  414. }
  415. // fixup the service startup state
  416. ((CInternalDevices*)m_pParentINode)->CorrectServiceState();
  417. } while( 0 );
  418. // notify update
  419. pComp->m_pResultData->UpdateItem( hItemID );
  420. return hr;
  421. }
  422. ////////////////////////////////////////////////////////////////////////////////////////////////////
  423. ////////////////////////////////////////////////////////////////////////////////////////////////////
  424. ////////////////////////////////////////////////////////////////////////////////////////////////////
  425. ////////////////////////////////////////////////////////////////////////////////////////////////////
  426. //
  427. //
  428. // IExtendPropertySheet event handlers
  429. //
  430. //
  431. HRESULT
  432. STDMETHODCALLTYPE
  433. CInternalDevice::ComponentPropertySheetCreatePropertyPages(
  434. IN CFaxComponent * pComp,
  435. IN LPPROPERTYSHEETCALLBACK lpProvider,
  436. IN LONG_PTR handle,
  437. IN CFaxDataObject * lpIDataObject)
  438. /*++
  439. Routine Description:
  440. This routine adds device pages to the property sheet.
  441. Arguments:
  442. pComp - a pointer to the IComponent associated with this node.
  443. lpProvider - a pointer to the IPropertySheetCallback used to insert pages
  444. handle - a handle to route messages with
  445. lpIDataobject - pointer to the dataobject associated with this node
  446. Return Value:
  447. HRESULT indicating SUCCEEDED() or FAILED()
  448. --*/
  449. {
  450. DebugPrint(( TEXT("Trace: CInternalDevice::ComponentPropertySheetCreatePropertyPages") ));
  451. assert( lpIDataObject != NULL );
  452. assert( lpProvider != NULL );
  453. HRESULT hr;
  454. if( lpIDataObject == NULL || lpProvider == NULL ) {
  455. assert(FALSE);
  456. return E_POINTER;
  457. }
  458. pMyPropSheet = new CFaxDeviceSettingsPropSheet( ::GlobalStringTable->GetInstance(), handle, this, pComp );
  459. if (!pMyPropSheet) {
  460. return(E_OUTOFMEMORY);
  461. }
  462. hr = lpProvider->AddPage( pMyPropSheet->GetHandle() );
  463. return hr;
  464. }
  465. HRESULT
  466. STDMETHODCALLTYPE
  467. CInternalDevice::ComponentPropertySheetQueryPagesFor(
  468. IN CFaxComponent * pComp,
  469. IN CFaxDataObject * lpDataObject)
  470. /*++
  471. Routine Description:
  472. The implementation of this routine returns S_OK to indicate there are
  473. property pages to be added to the property sheet.
  474. Arguments:
  475. pComp - a pointer to the IComponent associated with this node.
  476. lpDataobject - pointer to the dataobject associated with this node
  477. Return Value:
  478. HRESULT indicating SUCCEEDED() or FAILED()
  479. --*/
  480. {
  481. DebugPrint(( TEXT("Trace: CInternalDevice::ComponentPropertySheetQueryPagesFor") ));
  482. return S_OK;
  483. }
  484. ////////////////////////////////////////////////////////////////////////////////////////////////////
  485. ////////////////////////////////////////////////////////////////////////////////////////////////////
  486. ////////////////////////////////////////////////////////////////////////////////////////////////////
  487. ////////////////////////////////////////////////////////////////////////////////////////////////////
  488. //
  489. //
  490. // Internal Event Handlers
  491. //
  492. //
  493. HRESULT
  494. CInternalDevice::ResultOnSelect(
  495. IN CFaxComponent* pComp,
  496. IN CFaxDataObject * lpDataObject,
  497. IN LPARAM arg,
  498. IN LPARAM param)
  499. /*++
  500. Routine Description:
  501. Event handler for the MMCN_SELECT message for the device node.
  502. Arguments:
  503. pComp - a pointer to the instance of IComponentData which this root node is associated with.
  504. lpDataObject - a pointer to the data object containing context information for this node.
  505. arg, param - the arguements of the message
  506. Return Value:
  507. HRESULT which indicates SUCCEEDED() or FAILED()
  508. --*/
  509. {
  510. BOOL bScope = LOWORD( arg );
  511. BOOL bSelect = HIWORD( arg );
  512. if( bSelect == TRUE ) {
  513. DebugPrint(( TEXT("++++++++++++++++++++++++++++ Device SELECT") ));
  514. pComp->m_pConsoleVerb->SetVerbState( MMC_VERB_PROPERTIES, ENABLED, TRUE );
  515. pComp->m_pConsoleVerb->SetDefaultVerb( MMC_VERB_PROPERTIES );
  516. } else {
  517. DebugPrint(( TEXT("---------------------------- Device DESELECT") ));
  518. // if the toolbar has not already been released
  519. if( pComp->m_pControlbar != NULL ) {
  520. pComp->m_pControlbar->Detach( myToolBar );
  521. }
  522. }
  523. return S_OK;
  524. }
  525. HRESULT
  526. CInternalDevice::ResultOnPropertyChange(
  527. IN CFaxComponent* pComp,
  528. IN CFaxDataObject * lpDataObject,
  529. IN LPARAM arg,
  530. IN LPARAM param)
  531. /*++
  532. Routine Description:
  533. Event handler for the MMCN_PROPERTY_CHANGE message for the device node.
  534. Arguments:
  535. pComp - a pointer to the instance of IComponentData which this root node is associated with.
  536. lpDataObject - a pointer to the data object containing context information for this node.
  537. arg, param - the arguements of the message
  538. Return Value:
  539. HRESULT which indicates SUCCEEDED() or FAILED()
  540. --*/
  541. {
  542. HRESULT hr = S_OK;
  543. do {
  544. hr = pComp->m_pResultData->UpdateItem( hItemID );
  545. if( FAILED( hr ) ) {
  546. break;
  547. }
  548. } while( 0 );
  549. return hr;
  550. }
  551. ////////////////////////////////////////////////////////////////////////////////////////////////////
  552. ////////////////////////////////////////////////////////////////////////////////////////////////////
  553. ////////////////////////////////////////////////////////////////////////////////////////////////////
  554. ////////////////////////////////////////////////////////////////////////////////////////////////////
  555. //
  556. //
  557. // IExtendControlbar - default implementations
  558. //
  559. //
  560. HRESULT
  561. CInternalDevice::ControlBarOnBtnClick(
  562. IN CFaxComponent* pComp,
  563. IN CFaxDataObject * lpDataObject,
  564. IN LPARAM param )
  565. /*++
  566. Routine Description:
  567. Handles a click on a toolbar button.
  568. Arguments:
  569. pComp - a pointer to the IComponent associated with this node.
  570. lpDataObject - pointer to the dataobject associated with this node
  571. param - the parameter for the message
  572. Return Value:
  573. HRESULT indicating SUCCEEDED() or FAILED()
  574. --*/
  575. {
  576. DebugPrint(( TEXT("Trace: CInternalDevice::ControlBarOnBtnClick") ));
  577. HRESULT hr = S_OK;
  578. assert( hFaxServer != NULL );
  579. do {
  580. hr = RetrieveNewInfo();
  581. if( FAILED( hr ) ) {
  582. break;
  583. }
  584. switch( param ) {
  585. case CMD_PRI_UP:
  586. DebugPrint(( TEXT(" ******************** Increase priority") ));
  587. if( pDeviceInfo->Priority > 1 ) {
  588. pDeviceInfo->Priority--;
  589. hr = CommitNewInfo();
  590. if( FAILED( hr ) ) {
  591. pDeviceInfo->Priority++;
  592. break;
  593. }
  594. }
  595. break;
  596. case CMD_PRI_DOWN:
  597. DebugPrint(( TEXT(" ******************** Decrease priority") ));
  598. if( pDeviceInfo->Priority < 1000 ) {
  599. pDeviceInfo->Priority++;
  600. hr = CommitNewInfo();
  601. if( FAILED( hr ) ) {
  602. pDeviceInfo->Priority--;
  603. break;
  604. }
  605. }
  606. break;
  607. }
  608. // BUGBUG for some reason, I need to do this twice for the sort to be correctly
  609. // done!!!! If I only do it one, the MMC sorts in reverse order for some reason?
  610. //
  611. // Ultimate kludge! Yuck.
  612. //
  613. pComp->m_pResultData->UpdateItem( hItemID );
  614. pComp->m_pResultData->Sort( 6, 0, NULL );
  615. pComp->m_pResultData->UpdateItem( hItemID );
  616. pComp->m_pResultData->Sort( 6, 0, NULL );
  617. } while( 0 );
  618. return hr;
  619. }
  620. HRESULT
  621. CInternalDevice::ControlBarOnSelect(
  622. IN CFaxComponent* pComp,
  623. IN LPARAM arg,
  624. IN CFaxDataObject * lpDataObject )
  625. /*++
  626. Routine Description:
  627. Adds and removes the toolbar when the node is clicked.
  628. Arguments:
  629. pComp - a pointer to the IComponent associated with this node.
  630. arg - the parameter for the message
  631. lpDataObject - pointer to the dataobject associated with this node
  632. Return Value:
  633. HRESULT indicating SUCCEEDED() or FAILED()
  634. --*/
  635. {
  636. DebugPrint(( TEXT("CInternalDevice::ControlBarOnSelect") ));
  637. BOOL bScope = (BOOL) LOWORD( arg );
  638. BOOL bSelect = (BOOL) HIWORD( arg );
  639. LPUNKNOWN lpUnk;
  640. HRESULT hr = S_OK;
  641. if( pComp == NULL ) {
  642. assert( FALSE );
  643. return E_POINTER;
  644. }
  645. MMCBUTTON buttons[] =
  646. {
  647. {
  648. 0,
  649. CMD_PRI_UP,
  650. TBSTATE_ENABLED,
  651. TBSTYLE_BUTTON,
  652. ::GlobalStringTable->GetString( IDS_BTN_RAISE_PRI ),
  653. ::GlobalStringTable->GetString( IDS_BTN_RAISE_PRI_TOOLTIP )
  654. },
  655. {
  656. 1,
  657. CMD_PRI_DOWN,
  658. TBSTATE_ENABLED,
  659. TBSTYLE_BUTTON,
  660. ::GlobalStringTable->GetString( IDS_BTN_LOWER_PRI ),
  661. ::GlobalStringTable->GetString( IDS_BTN_LOWER_PRI_TOOLTIP )
  662. }
  663. };
  664. if( bSelect == TRUE ) {
  665. DebugPrint(( TEXT("++++++++++++++++++++++++++++ Device Controlbar SELECT") ));
  666. // if the controlbar hasn't already been created, create it
  667. if( myToolBar == NULL ) {
  668. hr = pComp->m_pControlbar->Create( TOOLBAR, pComp, &lpUnk );
  669. if( FAILED( hr ) ) {
  670. assert( FALSE );
  671. return E_UNEXPECTED;
  672. }
  673. hr = lpUnk->QueryInterface( IID_IToolbar, (void **)&myToolBar );
  674. if( FAILED( hr ) ) {
  675. assert( FALSE );
  676. return E_UNEXPECTED;
  677. }
  678. lpUnk->Release();
  679. HBITMAP hbUp = LoadBitmap( ::GlobalStringTable->GetInstance(),
  680. MAKEINTRESOURCE( IDB_UP ) );
  681. assert( hbUp != NULL );
  682. HBITMAP hbDown = LoadBitmap( ::GlobalStringTable->GetInstance(),
  683. MAKEINTRESOURCE( IDB_DOWN ) );
  684. assert( hbDown != NULL );
  685. hr = myToolBar->AddBitmap( 1, hbUp, 16, 16, 0x00ff00ff );
  686. if( FAILED( hr ) ) {
  687. assert( FALSE );
  688. return hr;
  689. }
  690. hr = myToolBar->AddBitmap( 1, hbDown, 16, 16, 0x00ff00ff );
  691. if( FAILED( hr ) ) {
  692. assert( FALSE );
  693. return hr;
  694. }
  695. hr = myToolBar->AddButtons( 2, buttons );
  696. if( FAILED( hr ) ) {
  697. assert( FALSE );
  698. return hr;
  699. }
  700. }
  701. hr = pComp->m_pControlbar->Attach( TOOLBAR, myToolBar );
  702. } else {
  703. DebugPrint(( TEXT("--------------------------- Device Controlbar DESELECT") ));
  704. // detach the toolbar
  705. hr = pComp->m_pControlbar->Detach( myToolBar );
  706. }
  707. return hr;
  708. }
  709. ////////////////////////////////////////////////////////////////////////////////////////////////////
  710. ////////////////////////////////////////////////////////////////////////////////////////////////////
  711. ////////////////////////////////////////////////////////////////////////////////////////////////////
  712. ////////////////////////////////////////////////////////////////////////////////////////////////////
  713. //
  714. //
  715. // Internal Functions
  716. //
  717. //
  718. HRESULT
  719. CInternalDevice::RetrieveNewInfo()
  720. /*++
  721. Routine Description:
  722. Retrieves new device info.
  723. Arguments:
  724. None.
  725. Return Value:
  726. HRESULT which indicates SUCCEEDED() or FAILED()
  727. --*/
  728. {
  729. HANDLE portHandle = NULL;
  730. HRESULT hr = S_OK;
  731. EnterCriticalSection( &csDeviceLock );
  732. assert( hFaxServer != NULL );
  733. try {
  734. do {
  735. if( m_pCompData->QueryRpcError() ) {
  736. hr = E_UNEXPECTED;
  737. break;
  738. }
  739. // open the port
  740. if( !FaxOpenPort( hFaxServer, dwDeviceId, PORT_OPEN_QUERY, &portHandle ) ) {
  741. if (GetLastError() != ERROR_ACCESS_DENIED) {
  742. m_pCompData->NotifyRpcError( TRUE );
  743. assert(FALSE);
  744. }
  745. ::GlobalStringTable->SystemErrorMsg( GetLastError() );
  746. hr = E_UNEXPECTED;
  747. break;
  748. }
  749. // free the existing buffer
  750. if( pDeviceInfo != NULL ) {
  751. FaxFreeBuffer( (PVOID) pDeviceInfo );
  752. pDeviceInfo = NULL;
  753. }
  754. // get data
  755. if( !FaxGetPort( portHandle, &pDeviceInfo ) ) {
  756. if (GetLastError() != ERROR_ACCESS_DENIED) {
  757. m_pCompData->NotifyRpcError( TRUE );
  758. assert(FALSE);
  759. }
  760. ::GlobalStringTable->SystemErrorMsg( GetLastError() );
  761. hr = E_UNEXPECTED;
  762. break;
  763. }
  764. } while( 0 );
  765. } catch( ... ) {
  766. m_pCompData->NotifyRpcError( TRUE );
  767. assert(FALSE);
  768. ::GlobalStringTable->SystemErrorMsg( GetLastError() );
  769. hr = E_UNEXPECTED;
  770. }
  771. // close port
  772. if( portHandle != NULL ) {
  773. FaxClose( portHandle );
  774. }
  775. LeaveCriticalSection( &csDeviceLock );
  776. return hr;
  777. }
  778. HRESULT
  779. CInternalDevice::CommitNewInfo()
  780. /*++
  781. Routine Description:
  782. Writes out the current device state to the fax service.
  783. Arguments:
  784. None.
  785. Return Value:
  786. HRESULT which indicates SUCCEEDED() or FAILED()
  787. --*/
  788. {
  789. HANDLE portHandle = NULL;
  790. HRESULT hr = S_OK;
  791. DWORD ec = ERROR_SUCCESS;
  792. EnterCriticalSection( &csDeviceLock );
  793. assert( hFaxServer != NULL );
  794. try {
  795. do {
  796. if( m_pCompData->QueryRpcError() ) {
  797. hr = E_UNEXPECTED;
  798. break;
  799. }
  800. // open the port
  801. if( !FaxOpenPort( hFaxServer, dwDeviceId, PORT_OPEN_MODIFY, &portHandle ) ) {
  802. if (GetLastError() != ERROR_ACCESS_DENIED) {
  803. m_pCompData->NotifyRpcError( TRUE );
  804. assert(FALSE);
  805. }
  806. ::GlobalStringTable->SystemErrorMsg( GetLastError() );
  807. hr = E_UNEXPECTED;
  808. break;
  809. }
  810. // set data
  811. if( !FaxSetPort( portHandle, pDeviceInfo ) ) {
  812. ec = GetLastError();
  813. if (ec != ERROR_ACCESS_DENIED && ec != ERROR_DEVICE_IN_USE) {
  814. m_pCompData->NotifyRpcError( TRUE );
  815. assert(FALSE);
  816. }
  817. if (ec == ERROR_DEVICE_IN_USE)
  818. ::GlobalStringTable->PopUpMsg( NULL , IDS_DEVICE_INUSE, TRUE, 0 );
  819. else
  820. ::GlobalStringTable->SystemErrorMsg( ec );
  821. hr = E_UNEXPECTED;
  822. break;
  823. }
  824. FaxClose( portHandle );
  825. portHandle = NULL;
  826. // See if faxstat is running
  827. HWND hWndFaxStat = FindWindow(FAXSTAT_WINCLASS, NULL);
  828. if (hWndFaxStat) {
  829. if (SendMessage(hWndFaxStat, WM_FAXSTAT_MMC, (WPARAM) dwDeviceId, 0)) {
  830. ::GlobalStringTable->PopUpMsg( NULL, IDS_DEVICE_MANUALANSWER, FALSE, 0 );
  831. }
  832. }
  833. } while( 0 );
  834. } catch( ... ) {
  835. m_pCompData->NotifyRpcError( TRUE );
  836. assert(FALSE);
  837. ::GlobalStringTable->SystemErrorMsg( GetLastError() );
  838. hr = E_UNEXPECTED;
  839. }
  840. // close port
  841. if( portHandle != NULL ) {
  842. FaxClose( portHandle );
  843. }
  844. LeaveCriticalSection( &csDeviceLock );
  845. return hr;
  846. }
  847. ////////////////////////////////////////////////////////////////////////////////////////////////////
  848. ////////////////////////////////////////////////////////////////////////////////////////////////////
  849. ////////////////////////////////////////////////////////////////////////////////////////////////////
  850. ////////////////////////////////////////////////////////////////////////////////////////////////////
  851. //
  852. //
  853. // Utility Functions
  854. //
  855. //
  856. LPTSTR
  857. CInternalDevice::GetStatusString(
  858. DWORD state )
  859. /*++
  860. Routine Description:
  861. Returns the correct status description given a device state.
  862. Arguments:
  863. state - the state of the device
  864. Return Value:
  865. A LPTSTR to a buffer containing the description of the state. Do not free this string.
  866. --*/
  867. {
  868. int i;
  869. int j = 1;
  870. // this will break if the defines ever change!!
  871. for( i = 1; i <= 25; i++ ) {
  872. if( j & state ) {
  873. break;
  874. }
  875. j = j << 1; // shift left
  876. }
  877. if( i <= 24 && i > 0 ) {
  878. return ::GlobalStringTable->GetString( IDS_DEVICE_STATUS + i );
  879. } else {
  880. assert( FALSE );
  881. return ::GlobalStringTable->GetString( IDS_DEVICE_STATUS_UNKNOWN );
  882. }
  883. }