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.

728 lines
17 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. faxcompd.cpp
  5. Abstract:
  6. This file contains my implementation of IComponentData.
  7. Environment:
  8. WIN32 User Mode
  9. Author:
  10. Darwin Ouyang (t-darouy) 30-Sept-1997
  11. --*/
  12. // faxcompdata.cpp : Implementation of CFaxComponentData
  13. #include "stdafx.h"
  14. #include "faxadmin.h"
  15. #include "faxcomp.h"
  16. #include "faxcompd.h"
  17. #include "faxdataobj.h"
  18. #include "faxhelper.h"
  19. #include "faxstrt.h"
  20. #include "iroot.h"
  21. #include "idevice.h"
  22. #pragma hdrstop
  23. ////////////////////////////////////////////////////////////////////////////////////////////////////
  24. ////////////////////////////////////////////////////////////////////////////////////////////////////
  25. ////////////////////////////////////////////////////////////////////////////////////////////////////
  26. ////////////////////////////////////////////////////////////////////////////////////////////////////
  27. //
  28. //
  29. // Constructor and destructor
  30. //
  31. //
  32. CFaxComponentData::CFaxComponentData()
  33. /*++
  34. Routine Description:
  35. Constructor.
  36. Arguments:
  37. None.
  38. Return Value:
  39. None.
  40. --*/
  41. {
  42. m_pUnknown = NULL; // IUnknown
  43. m_pConsoleNameSpace = NULL; // IConsoleNameSpace
  44. m_pConsole = NULL; // IConsole
  45. m_pImageList = NULL; // IImageList
  46. m_pControlbar = NULL; // IControlbar
  47. m_FaxHandle = NULL; // Fax connection handle;
  48. m_bRpcErrorHasHappened = TRUE; // Fax server is down until we connect.
  49. m_dwPropSheetCount = 0;
  50. DebugPrint(( TEXT( "FaxComponentData Created" ) ));
  51. globalRoot = new CInternalRoot( NULL, this );
  52. assert( globalRoot != NULL );
  53. // Initialize the critical section.
  54. InitializeCriticalSection( &GlobalCriticalSection );
  55. InitializeCriticalSection( &CInternalDevice::csDeviceLock );
  56. }
  57. CFaxComponentData::~CFaxComponentData()
  58. /*++
  59. Routine Description:
  60. Destructor.
  61. Arguments:
  62. None.
  63. Return Value:
  64. None.
  65. --*/
  66. {
  67. assert( globalRoot != NULL );
  68. if( globalRoot != NULL ) {
  69. delete globalRoot;
  70. }
  71. DebugPrint(( TEXT( "FaxComponentData Destroyed" ) ));
  72. }
  73. ////////////////////////////////////////////////////////////////////////////////////////////////////
  74. ////////////////////////////////////////////////////////////////////////////////////////////////////
  75. ////////////////////////////////////////////////////////////////////////////////////////////////////
  76. ////////////////////////////////////////////////////////////////////////////////////////////////////
  77. //
  78. //
  79. // CFaxComponentData implementation
  80. //
  81. //
  82. HRESULT
  83. STDMETHODCALLTYPE
  84. CFaxComponentData::Initialize(
  85. IN LPUNKNOWN pUnknown)
  86. /*++
  87. Routine Description:
  88. This routine initializes IComponentData by querying
  89. for needed interfaces.
  90. Arguments:
  91. pUnknown - the console's IUnknown interface.
  92. Return Value:
  93. HRESULT indicating SUCCEEDED() or FAILED()
  94. --*/
  95. {
  96. HRESULT hr;
  97. DebugPrint(( TEXT("Trace: CFaxComponentData::Initialize") ));
  98. do {
  99. assert(globalRoot != NULL );
  100. if(globalRoot == NULL ) {
  101. hr = E_UNEXPECTED;
  102. break;
  103. }
  104. assert(pUnknown != NULL);
  105. if( pUnknown == NULL ) {
  106. hr = E_POINTER;
  107. break;
  108. }
  109. // MMC should only call ::Initialize once!
  110. assert(m_pUnknown == NULL);
  111. if( m_pUnknown != NULL ) {
  112. hr = E_UNEXPECTED;
  113. break;
  114. }
  115. m_pUnknown = pUnknown;
  116. m_pUnknown->AddRef();
  117. // retrieve and store away all the interface pointers I might want
  118. //
  119. // Get pointer to IConsole
  120. //
  121. hr = pUnknown->QueryInterface(IID_IConsole, (VOID**)(&m_pConsole));
  122. assert( SUCCEEDED(hr) );
  123. if( FAILED( hr ) ) {
  124. break;
  125. }
  126. //
  127. // Get pointer to IConsoleNameSpace
  128. //
  129. hr = pUnknown->QueryInterface(IID_IConsoleNameSpace, (VOID**)(&m_pConsoleNameSpace));
  130. assert( SUCCEEDED(hr) );
  131. if( FAILED( hr ) ) {
  132. break;
  133. }
  134. //
  135. // Get pointer to IImageList for scope pane
  136. //
  137. //hr = pUnknown->QueryInterface(IID_IImageList, (VOID**)(&m_pImageList));
  138. hr = m_pConsole->QueryScopeImageList( &m_pImageList );
  139. assert( SUCCEEDED(hr) );
  140. if( FAILED( hr ) ) {
  141. break;
  142. }
  143. // setup my images in the imagelist
  144. hr = InsertIconsIntoImageList( m_pImageList );
  145. assert( SUCCEEDED(hr) );
  146. if( FAILED( hr ) ) {
  147. break;
  148. }
  149. } while( 0 );
  150. // damage control
  151. if( FAILED( hr ) ) {
  152. if( m_pUnknown != NULL ) {
  153. m_pUnknown->Release();
  154. m_pUnknown = NULL;
  155. }
  156. if( m_pConsole != NULL ) {
  157. m_pConsole->Release();
  158. m_pConsole = NULL;
  159. }
  160. if( m_pConsoleNameSpace != NULL ) {
  161. m_pConsoleNameSpace->Release();
  162. m_pConsoleNameSpace = NULL;
  163. }
  164. if( m_pImageList != NULL ) {
  165. m_pImageList->Release();
  166. m_pImageList = NULL;
  167. }
  168. }
  169. return hr;
  170. }
  171. HRESULT
  172. STDMETHODCALLTYPE
  173. CFaxComponentData::CreateComponent(
  174. OUT LPCOMPONENT __RPC_FAR *ppComponent)
  175. /*++
  176. Routine Description:
  177. This routine creates and returns an IComponent interface.
  178. Arguments:
  179. ppComponent - the new IComponent is returned here.
  180. Return Value:
  181. HRESULT indicating SUCCEEDED() or FAILED()
  182. --*/
  183. {
  184. HRESULT hr = S_OK;
  185. CFaxComponent * temp = NULL;
  186. DebugPrint(( TEXT("Trace: CFaxComponentData::CreateComponent") ));
  187. //
  188. // MMC asks us for a pointer to the IComponent interface
  189. //
  190. if( ppComponent != NULL ) {
  191. temp = new CComObject<CFaxComponent>;
  192. if( temp == NULL ) {
  193. return E_OUTOFMEMORY;
  194. }
  195. temp->SetOwner( this );
  196. *ppComponent = temp;
  197. (*ppComponent)->AddRef();
  198. } else {
  199. hr = E_POINTER;
  200. }
  201. return hr;
  202. }
  203. HRESULT
  204. STDMETHODCALLTYPE
  205. CFaxComponentData::Notify(
  206. IN LPDATAOBJECT lpDataObject,
  207. IN MMC_NOTIFY_TYPE event,
  208. IN LPARAM arg,
  209. IN LPARAM param)
  210. /*++
  211. Routine Description:
  212. This routine dispatches events sent to the IComponentData
  213. interface using the cookie extracted from the DataObject.
  214. The cookie stored is a pointer to the class that implements behavior for
  215. that subfolder. So we delegate all the messages by taking the cookie
  216. casting it to a pointer to a folder, and invoking the notify method.
  217. Arguments:
  218. lpDataobject - the data object
  219. event - the event type
  220. arg, param - event arguments
  221. Return Value:
  222. HRESULT indicating SUCCEEDED() or FAILED()
  223. --*/
  224. {
  225. HRESULT hr = S_OK;
  226. CFaxDataObject * dataObject = NULL;
  227. LONG_PTR cookie;
  228. // DebugPrint(( TEXT("Trace: CFaxComponentData::Notify") ));
  229. if( lpDataObject != NULL) {
  230. dataObject = ExtractOwnDataObject( lpDataObject );
  231. if( dataObject == NULL ) {
  232. return E_UNEXPECTED;
  233. }
  234. cookie = dataObject->GetCookie();
  235. if( cookie == NULL) {
  236. // my static node
  237. hr = globalRoot->ScopeNotify( this, dataObject, event, arg, param );
  238. } else {
  239. // cast the cookie to a pointer
  240. try {
  241. hr = ((CInternalNode *)cookie)->ScopeNotify( this, dataObject, event, arg, param );
  242. } catch ( ... ) {
  243. DebugPrint(( TEXT("Invalid Cookie: 0x%08x"), cookie ));
  244. assert( FALSE ); // got passed an INVALID COOKIE!?!?!?!?
  245. hr = E_UNEXPECTED;
  246. }
  247. }
  248. } else {
  249. // some events do not pass a lpDataObject
  250. // if we want to handle these event, we
  251. // have to do it here
  252. if( event == MMCN_PROPERTY_CHANGE ) {
  253. if( param != NULL ) {
  254. try {
  255. hr = ((CInternalNode *)param)->ScopeNotify( this, NULL, event, arg, param );
  256. } catch ( ... ) {
  257. DebugPrint(( TEXT("Invalid Cookie") ));
  258. assert( FALSE ); // got passed an INVALID COOKIE!?!?!?!?
  259. hr = E_UNEXPECTED;
  260. }
  261. }
  262. }
  263. }
  264. return hr;
  265. }
  266. HRESULT
  267. STDMETHODCALLTYPE
  268. CFaxComponentData::Destroy(
  269. void )
  270. /*++
  271. Routine Description:
  272. This method releases all the aquired console interface in preperation
  273. for the snapin being destroyed.
  274. Arguments:
  275. None.
  276. Return Value:
  277. HRESULT indicating SUCCEEDED() or FAILED()
  278. --*/
  279. {
  280. DebugPrint(( TEXT("Trace: CFaxComponentData::Destroy") ));
  281. // the prop sheet count should never be negative
  282. assert( QueryPropSheetCount() >= 0 );
  283. // check to see if any property sheets are up
  284. while( QueryPropSheetCount() > 0 ) {
  285. DebugPrint(( TEXT("Trace: QueryPropSheetCount() %d "), QueryPropSheetCount() ));
  286. // don't allow deletion
  287. GlobalStringTable->PopUpMsg( NULL, IDS_PROP_SHEET_STILL_UP, TRUE, NULL );
  288. }
  289. // Free interfaces
  290. if( m_pUnknown != NULL ) {
  291. m_pUnknown->Release();
  292. m_pUnknown = NULL;
  293. }
  294. if( m_pConsole != NULL ) {
  295. m_pConsole->Release();
  296. m_pConsole = NULL;
  297. }
  298. if( m_pConsoleNameSpace != NULL ) {
  299. m_pConsoleNameSpace->Release();
  300. m_pConsoleNameSpace = NULL;
  301. }
  302. if( m_pImageList != NULL ) {
  303. m_pImageList->Release();
  304. m_pImageList = NULL;
  305. }
  306. if( m_pControlbar != NULL ) {
  307. m_pControlbar->Release();
  308. m_pControlbar = NULL;
  309. }
  310. return S_OK;
  311. }
  312. HRESULT
  313. STDMETHODCALLTYPE
  314. CFaxComponentData::QueryDataObject(
  315. IN MMC_COOKIE cookie,
  316. IN DATA_OBJECT_TYPES type,
  317. OUT LPDATAOBJECT __RPC_FAR *ppDataObject)
  318. /*++
  319. Routine Description:
  320. This method dispatches DataObjects requests to the appropriate
  321. nodes using the cookie.
  322. Arguments:
  323. cookie - the cookie for the associated node
  324. type - the type of the cookie
  325. ppDataobject - a pointer to the new data object is stored here
  326. Return Value:
  327. HRESULT indicating SUCCEEDED() or FAILED()
  328. --*/
  329. {
  330. // DebugPrint(( TEXT("Trace: CFaxComponentData::QueryDataObject") ));
  331. HRESULT hr = S_OK;
  332. if( cookie == NULL ) {
  333. hr = globalRoot->ScopeQueryDataObject( this, cookie, type, ppDataObject );
  334. } else {
  335. try {
  336. hr = ((CInternalNode *)cookie)->ScopeQueryDataObject( this, cookie, type, ppDataObject );
  337. } catch ( ... ) {
  338. DebugPrint(( TEXT("Invalid Cookie: 0x%08x"), cookie ));
  339. assert( FALSE ); // got passed an INVALID COOKIE!?!?!?!?
  340. hr = E_UNEXPECTED;
  341. }
  342. }
  343. return hr;
  344. }
  345. HRESULT
  346. STDMETHODCALLTYPE
  347. CFaxComponentData::GetDisplayInfo(
  348. IN OUT SCOPEDATAITEM __RPC_FAR *pScopeDataItem)
  349. /*++
  350. Routine Description:
  351. This method dispatches DisplayInfo requests to the appropriate
  352. nodes using the cookie in pScopeDataItem.
  353. Arguments:
  354. pScopeDataItem - struct containing information about the scope item.
  355. Return Value:
  356. HRESULT indicating SUCCEEDED() or FAILED()
  357. --*/
  358. {
  359. // DebugPrint(( TEXT("Trace: CFaxComponentData::GetDisplayInfo") ));
  360. LONG_PTR cookie;
  361. HRESULT hr = S_OK;
  362. assert(pScopeDataItem != NULL);
  363. if( pScopeDataItem == NULL ) {
  364. return E_POINTER;
  365. }
  366. cookie = pScopeDataItem->lParam;
  367. if( cookie == NULL ) {
  368. // our top node
  369. hr = globalRoot->ScopeGetDisplayInfo( this, pScopeDataItem);
  370. } else {
  371. // another node
  372. try {
  373. hr = ((CInternalNode *)cookie)->ScopeGetDisplayInfo( this, pScopeDataItem);
  374. } catch ( ... ) {
  375. DebugPrint(( TEXT("Invalid Cookie: 0x%08x"), cookie ));
  376. assert( FALSE ); // got passed an INVALID COOKIE!?!?!?!?
  377. hr = E_UNEXPECTED;
  378. }
  379. }
  380. return hr;
  381. }
  382. /////////////////////////////////////////////////////////////////////////////
  383. // CompareObjects
  384. //
  385. // Compares two objects.
  386. HRESULT
  387. STDMETHODCALLTYPE
  388. CFaxComponentData::CompareObjects(
  389. IN LPDATAOBJECT lpDataObjectA,
  390. IN LPDATAOBJECT lpDataObjectB)
  391. /*++
  392. Routine Description:
  393. This method compares two data object to see if they correspond to
  394. the same object by comparing the cookies.
  395. Arguments:
  396. lpDataObjectA - object A
  397. lpDataObjectB - object B
  398. Return Value:
  399. HRESULT indicating S_OK or S_FALSE. E_UNEXPECTED for an error.
  400. --*/
  401. {
  402. DebugPrint(( TEXT("Trace: CFaxComponentData::CompareObjects") ));
  403. CFaxDataObject * aOBJ = ExtractOwnDataObject( lpDataObjectA );
  404. CFaxDataObject * bOBJ = ExtractOwnDataObject( lpDataObjectB );
  405. if( aOBJ == NULL || bOBJ == NULL ) {
  406. return E_UNEXPECTED;
  407. }
  408. if( aOBJ->GetCookie() == bOBJ->GetCookie() ) {
  409. return S_OK;
  410. } else {
  411. return S_FALSE;
  412. }
  413. }
  414. ////////////////////////////////////////////////////////////////////////////////////////////////////
  415. ////////////////////////////////////////////////////////////////////////////////////////////////////
  416. ////////////////////////////////////////////////////////////////////////////////////////////////////
  417. ////////////////////////////////////////////////////////////////////////////////////////////////////
  418. //
  419. //
  420. // Internal Methods
  421. //
  422. //
  423. HRESULT
  424. CFaxComponentData::InsertIconsIntoImageList(
  425. IN LPIMAGELIST pImageList )
  426. /*++
  427. Routine Description:
  428. Takes an image list and inserts the standard set of icons into it
  429. Add any new node images you want here and also don't forget to assign them
  430. new ids.
  431. Arguments:
  432. pImageList - the image list into which icons are to be inserted.
  433. Return Value:
  434. HRESULT indicating SUCCEEDED() or FAILED()
  435. --*/
  436. {
  437. HICON hIcon = NULL;
  438. HRESULT hr = S_OK;
  439. WORD resID = IDI_NODEICON;
  440. do {
  441. // set generic node icon
  442. // the defined values are stored in resource.h
  443. hr = InsertSingleIconIntoImageList( IDI_NODEICON, IDI_NODEICON, pImageList );
  444. if( FAILED( hr ) ) {
  445. break;
  446. }
  447. // set more icons here
  448. //
  449. //
  450. for( resID = IDI_COVERPG; resID < LAST_ICON; resID++ ) {
  451. hr = InsertSingleIconIntoImageList( resID, resID, pImageList );
  452. if( FAILED( hr ) ) {
  453. break;
  454. }
  455. }
  456. if( FAILED( hr ) ) {
  457. break;
  458. }
  459. } while( 0 );
  460. return hr;
  461. }
  462. HRESULT
  463. CFaxComponentData::InsertSingleIconIntoImageList(
  464. IN WORD resID,
  465. IN long assignedIndex,
  466. IN LPIMAGELIST pImageList )
  467. /*++
  468. Routine Description:
  469. Takes an image list and inserts a single icon into it
  470. using the resource ID and index specified.
  471. Arguments:
  472. resID - the resource ID
  473. assignedIndex - the index assigned to the icon
  474. pImageList - the image list into which icons are to be inserted.
  475. Return Value:
  476. HRESULT indicating SUCCEEDED() or FAILED()
  477. --*/
  478. {
  479. HICON hIcon = NULL;
  480. HRESULT hr = S_OK;
  481. do {
  482. hIcon = LoadIcon( ::GlobalStringTable->GetInstance(), MAKEINTRESOURCE( resID ) );
  483. assert( hIcon != NULL );
  484. if( hIcon == NULL ) {
  485. hr = E_UNEXPECTED;
  486. break;
  487. }
  488. hr = pImageList->ImageListSetIcon( (LONG_PTR *)hIcon, assignedIndex );
  489. assert( SUCCEEDED( hr ) );
  490. if( FAILED( hr ) ) {
  491. break;
  492. }
  493. } while( 0 );
  494. return hr;
  495. }
  496. BOOL
  497. CFaxComponentData::QueryRpcError()
  498. /*++
  499. Routine Description:
  500. Queries the state of the RPC connection.
  501. The critical section is probably needed because this function can be called from
  502. the property sheets which run in a different thread.
  503. Arguments:
  504. None.
  505. Return Value:
  506. BOOL indicating TRUE if the RPC connection has encountered an error.
  507. --*/
  508. {
  509. BOOL temp;
  510. EnterCriticalSection(&GlobalCriticalSection);
  511. temp = m_bRpcErrorHasHappened;
  512. // other stuff might go in here someday
  513. LeaveCriticalSection(&GlobalCriticalSection);
  514. return temp;
  515. }
  516. void
  517. CFaxComponentData::NotifyRpcError(
  518. IN BOOL bRpcErrorHasHappened )
  519. /*++
  520. Routine Description:
  521. Informs all the members of the snapin that the RPC connection is dead and
  522. the server state is indeterminate
  523. The critical section is probably needed because this function can be called from
  524. the property sheets which run in a different thread.
  525. Arguments:
  526. BOOL indicating TRUE if the RPC connection has encountered an error.
  527. Return Value:
  528. None.
  529. --*/
  530. {
  531. EnterCriticalSection(&GlobalCriticalSection);
  532. // handle server down events here
  533. // other stuff might go in here someday
  534. m_bRpcErrorHasHappened = bRpcErrorHasHappened;
  535. LeaveCriticalSection(&GlobalCriticalSection);
  536. }