/*++ Copyright (c) 1997 Microsoft Corporation Module Name: ilogcat.cpp Abstract: Internal implementation for a logging category item. Environment: WIN32 User Mode Author: Darwin Ouyang (t-darouy) 30-Sept-1997 --*/ #include "StdAfx.h" #include "inode.h" // base class #include "iroot.h" // root item #include "idevice.h" // device item #include "idevices.h" // devices folder #include "faxcompd.h" // CFaxComponentData #include "faxcomp.h" // CFaxComponent #include "faxdataobj.h" // dataobject #include "faxstrt.h" // string table #include "ddevmain.h" // device settings #include "droutpri.h" // route extension priority #include "faxreg.h" #pragma hdrstop extern CStringTable * GlobalStringTable; CRITICAL_SECTION CInternalDevice::csDeviceLock = {0}; // defines for context menu command ids #define SEND_CONTEXT_ITEM 11 #define RECV_CONTEXT_ITEM 12 // defines for toolbar button command ids #define CMD_PRI_UP 123 #define CMD_PRI_DOWN 124 // Generated with uuidgen. Each node must have a GUID associated with it. // This one is for the main root node. const GUID GUID_DeviceNode = /* de58ae00-4c0f-11d1-9083-00a0c90ab504 */ { 0xde58ae00, 0x4c0f, 0x11d1, {0x90, 0x83, 0x00, 0xa0, 0xc9, 0x0a, 0xb5, 0x04} }; //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // // // Constructor and destructor // // CInternalDevice::CInternalDevice( IN CInternalNode * pParent, IN CFaxComponentData * pCompData, IN HANDLE faxHandle, IN DWORD devID ) : CInternalNode( pParent, pCompData ), dwDeviceId( devID ), hFaxServer( faxHandle ), pDeviceInfo( NULL ), myToolBar( NULL ) /*++ Routine Description: Constructor Arguments: pParent - pointer to parent node, in this case unused pCompData - pointer to IComponentData implementation for snapin global data Return Value: None. --*/ { RetrieveNewInfo(); DebugPrint(( TEXT("CInternalDevice Created") )); } CInternalDevice::~CInternalDevice() /*++ Routine Description: Destructor Arguments: None. Return Value: None. --*/ { if( myToolBar != NULL ) { myToolBar->Release(); myToolBar = NULL ; } DebugPrint(( TEXT("CInternalDevice Destroyed") )); } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // // // Custom Clipboard Format handlers. // // // clipboard format UINT CInternalDevice::s_cfFaxDevice = 0; UINT CInternalDevice::s_cfFaxServerDown = 0; #define CCF_FAX_DEVICE L"CF_FAX_DEVICE" #define CCF_FAX_SERVER_DOWN L"CF_FAX_SERVER_DOWN" // clipboard methods HRESULT CInternalDevice::DataObjectRegisterFormats() /*++ Routine Description: Registers the custom clipboard formats for the device node. Arguments: None. Return Value: HRESULT which indicates SUCCEEDED() or FAILED() --*/ { s_cfFaxDevice = RegisterClipboardFormat(CCF_FAX_DEVICE); s_cfFaxServerDown = RegisterClipboardFormat(CCF_FAX_SERVER_DOWN); return S_OK; } HRESULT CInternalDevice::DataObjectGetDataHere( IN FORMATETC __RPC_FAR *pFormatEtc, IN IStream * pstm ) /*++ Routine Description: Handles GetDataHere for custom clipboard formats specific to this particular node. The default implementation asserts since there should be no unhandled formats. Arguments: pFormatEtc - the FORMATETC struction indicating where and what the client is requesting pstm - the stream to write the data to. Return Value: HRESULT indicating SUCCEEDED() or FAILED() --*/ { const CLIPFORMAT cf = pFormatEtc->cfFormat; HANDLE faxHandle = ((CInternalDevices *)m_pParentINode)->faxHandle; HRESULT hr = S_OK; LPTSTR tstr; BOOL temp; assert( faxHandle != NULL ); assert( pDeviceInfo != NULL ); if( cf == s_cfFaxDevice ) { // handle the device clipboard format pstm->Write( &(faxHandle), sizeof(HANDLE), NULL ); pstm->Write( &(pDeviceInfo->DeviceId), sizeof(DWORD), NULL ); tstr = m_pCompData->globalRoot->GetMachine(); if( tstr != NULL ) { pstm->Write( tstr, (MAX_COMPUTERNAME_LENGTH+1) * sizeof( TCHAR ), NULL ); } else { pstm->Write( &tstr, sizeof( NULL ), NULL ); } } else if( cf == s_cfFaxServerDown ) { // handle the query server down format temp = m_pCompData->QueryRpcError(); pstm->Write( &temp, sizeof( BOOL ), NULL ); } else { hr = DV_E_FORMATETC; } return hr; } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // // // Mandatory CInternalNode implementations. // // const GUID * CInternalDevice::GetNodeGUID() /*++ Routine Description: Returns the node's associated GUID. Arguments: None. Return Value: A const pointer to a binary GUID. --*/ { // DebugPrint(( TEXT("Trace: CInternalDevice::GetNodeGUID") )); return &GUID_DeviceNode; } const LPTSTR CInternalDevice::GetNodeDisplayName() /*++ Routine Description: Returns a const TSTR pointer to the node's display name. Arguments: None. Return Value: A const pointer to a TSTR. --*/ { // DebugPrint(( TEXT("Trace: CInternalDevice::GetNodeDisplayName") )); return (LPTSTR)pDeviceInfo->DeviceName; } const LONG_PTR CInternalDevice::GetCookie() /*++ Routine Description: Returns the cookie for this node. Arguments: None. Return Value: A const long containing the cookie for the pointer, in this case, (long)this. --*/ { // DebugPrint(( TEXT("Trace: CInternalDevice::GetCookie") )); DebugPrint(( TEXT("Device Node Cookie: 0x%p"), this )); return (LONG_PTR)this; // device node's cookie is the this pointer. } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // // // IComponent over-rides // // HRESULT STDMETHODCALLTYPE CInternalDevice::ResultGetDisplayInfo( IN CFaxComponent * pComp, IN OUT RESULTDATAITEM __RPC_FAR *pResultDataItem) /*++ Routine Description: This routine dispatches result pane GetDisplayInfo requests to the appropriate handlers in the mandatory implementations of the node, as well as handling special case data requests. Arguments: pComp - a pointer to the IComponent associated with this node. pResultDataItem - a pointer to the RESULTDATAITEM struct which needs to be filled in. Return Value: HRESULT indicating SUCCEEDED() or FAILED() --*/ { // DebugPrint(( TEXT("Trace: CInternalDevice::ResultGetDisplayInfo") )); TCHAR buffer[ 20 ]; HRESULT hr = S_OK; ZeroMemory( (PVOID)buffer, 20 * sizeof( TCHAR ) ); assert(pResultDataItem != NULL); do { if( m_pCompData->QueryRpcError() == TRUE ) { // notify the parent of the failure ((CInternalDevices *)m_pParentINode)->NotifyFailure( pComp ); hr = E_UNEXPECTED; break; } if( pResultDataItem->mask & RDI_STR ) { if( pResultDataItem->nCol == 0 ) { hr = RetrieveNewInfo(); if( FAILED( hr ) ) { assert( FALSE ); break; } pResultDataItem->str = GetNodeDisplayName(); } if( pResultDataItem->nCol == 1 ) { if( pDeviceInfo->Flags & FPF_SEND ) { pResultDataItem->str = ::GlobalStringTable->GetString( IDS_YES ); } else { pResultDataItem->str = ::GlobalStringTable->GetString( IDS_NO ); } } if( pResultDataItem->nCol == 2 ) { if( pDeviceInfo->Flags & FPF_RECEIVE ) { pResultDataItem->str = ::GlobalStringTable->GetString( IDS_YES ); } else { pResultDataItem->str = ::GlobalStringTable->GetString( IDS_NO ); } } if( pResultDataItem->nCol == 3 ) { pResultDataItem->str = (LPTSTR)pDeviceInfo->Tsid; } if( pResultDataItem->nCol == 4 ) { pResultDataItem->str = (LPTSTR)pDeviceInfo->Csid; } if( pResultDataItem->nCol == 5 ) { pResultDataItem->str = GetStatusString( pDeviceInfo->State ); } if( pResultDataItem->nCol == 6 ) { pResultDataItem->str = _itot( pDeviceInfo->Priority, buffer, 10 ); } if( pResultDataItem->mask & RDI_IMAGE ) { pResultDataItem->nImage = GetNodeDisplayImage(); } } } while( 0 ); return hr; } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // // // IExtendContextMenu event handlers // // HRESULT STDMETHODCALLTYPE CInternalDevice::ComponentContextMenuAddMenuItems( IN CFaxComponent * pComp, IN CFaxDataObject * piDataObject, IN LPCONTEXTMENUCALLBACK piCallback, IN OUT long __RPC_FAR *pInsertionAllowed) /*++ Routine Description: Adds items to the context menu. Arguments: pComp - a pointer to the IComponent associated with this node. piDataObject - pointer to the dataobject associated with this node piCallback - a pointer to the IContextMenuCallback used to insert pages pInsertionAllowed - a set of flag indicating whether insertion is allowed. Return Value: HRESULT indicating SUCCEEDED() or FAILED() --*/ { DebugPrint(( TEXT("Trace: CInternalDevice::ComponentContextMenuAddMenuItems") )); CONTEXTMENUITEM menuItem; HRESULT hr = S_OK; if( !( *pInsertionAllowed | CCM_INSERTIONALLOWED_TOP ) ) { assert( FALSE ); return S_OK; } // build the submenu items ZeroMemory( ( void* )&menuItem, sizeof( menuItem ) ); menuItem.strName = ::GlobalStringTable->GetString( IDS_DEVICE_SEND_EN ); menuItem.strStatusBarText = ::GlobalStringTable->GetString( IDS_DEVICE_SEND_EN_DESC ); menuItem.lCommandID = SEND_CONTEXT_ITEM; menuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP; if( pDeviceInfo->Flags & FPF_SEND ) { menuItem.fFlags = MF_ENABLED | MF_CHECKED; } else { menuItem.fFlags = MF_ENABLED; } menuItem.fSpecialFlags = 0; hr = piCallback->AddItem( &menuItem ); if( FAILED(hr) ) { assert(FALSE); return hr; } ZeroMemory( ( void* )&menuItem, sizeof( menuItem ) ); menuItem.strName = ::GlobalStringTable->GetString( IDS_DEVICE_RECV_EN ); menuItem.strStatusBarText = ::GlobalStringTable->GetString( IDS_DEVICE_RECV_EN_DESC ); menuItem.lCommandID = RECV_CONTEXT_ITEM; menuItem.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP; if( pDeviceInfo->Flags & FPF_RECEIVE ) { menuItem.fFlags = MF_ENABLED | MF_CHECKED; } else { menuItem.fFlags = MF_ENABLED; } menuItem.fSpecialFlags = 0; hr = piCallback->AddItem( &menuItem ); if( FAILED(hr) ) { assert(FALSE); return hr; } return hr; } HRESULT STDMETHODCALLTYPE CInternalDevice::ComponentContextMenuCommand( IN CFaxComponent * pComp, IN long lCommandID, IN CFaxDataObject * piDataObject) /*++ Routine Description: Context menu event handler. Arguments: pComp - a pointer to the IComponent associated with this node. lCommandID - the command ID piDataObject - pointer to the dataobject associated with this node Return Value: HRESULT indicating SUCCEEDED() or FAILED() --*/ { DebugPrint(( TEXT("Trace: CInternalDevice::ComponentContextMenuCommand") )); HRESULT hr = S_OK; assert( hFaxServer != NULL ); do { // retrieve data hr = RetrieveNewInfo(); if( FAILED( hr ) ) { assert( FALSE ); break; } switch( lCommandID ) { case SEND_CONTEXT_ITEM: if( pDeviceInfo->Flags & FPF_SEND ) { pDeviceInfo->Flags = pDeviceInfo->Flags & (~FPF_SEND); } else { pDeviceInfo->Flags = pDeviceInfo->Flags | FPF_SEND; } break; case RECV_CONTEXT_ITEM: if( pDeviceInfo->Flags & FPF_RECEIVE ) { pDeviceInfo->Flags = pDeviceInfo->Flags & (~FPF_RECEIVE); } else { pDeviceInfo->Flags = pDeviceInfo->Flags | FPF_RECEIVE; } break; default: assert(FALSE); break; } // commit new settings hr = CommitNewInfo(); if( FAILED( hr ) ) { break; } // fixup the service startup state ((CInternalDevices*)m_pParentINode)->CorrectServiceState(); } while( 0 ); // notify update pComp->m_pResultData->UpdateItem( hItemID ); return hr; } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // // // IExtendPropertySheet event handlers // // HRESULT STDMETHODCALLTYPE CInternalDevice::ComponentPropertySheetCreatePropertyPages( IN CFaxComponent * pComp, IN LPPROPERTYSHEETCALLBACK lpProvider, IN LONG_PTR handle, IN CFaxDataObject * lpIDataObject) /*++ Routine Description: This routine adds device pages to the property sheet. Arguments: pComp - a pointer to the IComponent associated with this node. lpProvider - a pointer to the IPropertySheetCallback used to insert pages handle - a handle to route messages with lpIDataobject - pointer to the dataobject associated with this node Return Value: HRESULT indicating SUCCEEDED() or FAILED() --*/ { DebugPrint(( TEXT("Trace: CInternalDevice::ComponentPropertySheetCreatePropertyPages") )); assert( lpIDataObject != NULL ); assert( lpProvider != NULL ); HRESULT hr; if( lpIDataObject == NULL || lpProvider == NULL ) { assert(FALSE); return E_POINTER; } pMyPropSheet = new CFaxDeviceSettingsPropSheet( ::GlobalStringTable->GetInstance(), handle, this, pComp ); if (!pMyPropSheet) { return(E_OUTOFMEMORY); } hr = lpProvider->AddPage( pMyPropSheet->GetHandle() ); return hr; } HRESULT STDMETHODCALLTYPE CInternalDevice::ComponentPropertySheetQueryPagesFor( IN CFaxComponent * pComp, IN CFaxDataObject * lpDataObject) /*++ Routine Description: The implementation of this routine returns S_OK to indicate there are property pages to be added to the property sheet. Arguments: pComp - a pointer to the IComponent associated with this node. lpDataobject - pointer to the dataobject associated with this node Return Value: HRESULT indicating SUCCEEDED() or FAILED() --*/ { DebugPrint(( TEXT("Trace: CInternalDevice::ComponentPropertySheetQueryPagesFor") )); return S_OK; } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // // // Internal Event Handlers // // HRESULT CInternalDevice::ResultOnSelect( IN CFaxComponent* pComp, IN CFaxDataObject * lpDataObject, IN LPARAM arg, IN LPARAM param) /*++ Routine Description: Event handler for the MMCN_SELECT message for the device node. Arguments: pComp - a pointer to the instance of IComponentData which this root node is associated with. lpDataObject - a pointer to the data object containing context information for this node. arg, param - the arguements of the message Return Value: HRESULT which indicates SUCCEEDED() or FAILED() --*/ { BOOL bScope = LOWORD( arg ); BOOL bSelect = HIWORD( arg ); if( bSelect == TRUE ) { DebugPrint(( TEXT("++++++++++++++++++++++++++++ Device SELECT") )); pComp->m_pConsoleVerb->SetVerbState( MMC_VERB_PROPERTIES, ENABLED, TRUE ); pComp->m_pConsoleVerb->SetDefaultVerb( MMC_VERB_PROPERTIES ); } else { DebugPrint(( TEXT("---------------------------- Device DESELECT") )); // if the toolbar has not already been released if( pComp->m_pControlbar != NULL ) { pComp->m_pControlbar->Detach( myToolBar ); } } return S_OK; } HRESULT CInternalDevice::ResultOnPropertyChange( IN CFaxComponent* pComp, IN CFaxDataObject * lpDataObject, IN LPARAM arg, IN LPARAM param) /*++ Routine Description: Event handler for the MMCN_PROPERTY_CHANGE message for the device node. Arguments: pComp - a pointer to the instance of IComponentData which this root node is associated with. lpDataObject - a pointer to the data object containing context information for this node. arg, param - the arguements of the message Return Value: HRESULT which indicates SUCCEEDED() or FAILED() --*/ { HRESULT hr = S_OK; do { hr = pComp->m_pResultData->UpdateItem( hItemID ); if( FAILED( hr ) ) { break; } } while( 0 ); return hr; } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // // // IExtendControlbar - default implementations // // HRESULT CInternalDevice::ControlBarOnBtnClick( IN CFaxComponent* pComp, IN CFaxDataObject * lpDataObject, IN LPARAM param ) /*++ Routine Description: Handles a click on a toolbar button. Arguments: pComp - a pointer to the IComponent associated with this node. lpDataObject - pointer to the dataobject associated with this node param - the parameter for the message Return Value: HRESULT indicating SUCCEEDED() or FAILED() --*/ { DebugPrint(( TEXT("Trace: CInternalDevice::ControlBarOnBtnClick") )); HRESULT hr = S_OK; assert( hFaxServer != NULL ); do { hr = RetrieveNewInfo(); if( FAILED( hr ) ) { break; } switch( param ) { case CMD_PRI_UP: DebugPrint(( TEXT(" ******************** Increase priority") )); if( pDeviceInfo->Priority > 1 ) { pDeviceInfo->Priority--; hr = CommitNewInfo(); if( FAILED( hr ) ) { pDeviceInfo->Priority++; break; } } break; case CMD_PRI_DOWN: DebugPrint(( TEXT(" ******************** Decrease priority") )); if( pDeviceInfo->Priority < 1000 ) { pDeviceInfo->Priority++; hr = CommitNewInfo(); if( FAILED( hr ) ) { pDeviceInfo->Priority--; break; } } break; } // BUGBUG for some reason, I need to do this twice for the sort to be correctly // done!!!! If I only do it one, the MMC sorts in reverse order for some reason? // // Ultimate kludge! Yuck. // pComp->m_pResultData->UpdateItem( hItemID ); pComp->m_pResultData->Sort( 6, 0, NULL ); pComp->m_pResultData->UpdateItem( hItemID ); pComp->m_pResultData->Sort( 6, 0, NULL ); } while( 0 ); return hr; } HRESULT CInternalDevice::ControlBarOnSelect( IN CFaxComponent* pComp, IN LPARAM arg, IN CFaxDataObject * lpDataObject ) /*++ Routine Description: Adds and removes the toolbar when the node is clicked. Arguments: pComp - a pointer to the IComponent associated with this node. arg - the parameter for the message lpDataObject - pointer to the dataobject associated with this node Return Value: HRESULT indicating SUCCEEDED() or FAILED() --*/ { DebugPrint(( TEXT("CInternalDevice::ControlBarOnSelect") )); BOOL bScope = (BOOL) LOWORD( arg ); BOOL bSelect = (BOOL) HIWORD( arg ); LPUNKNOWN lpUnk; HRESULT hr = S_OK; if( pComp == NULL ) { assert( FALSE ); return E_POINTER; } MMCBUTTON buttons[] = { { 0, CMD_PRI_UP, TBSTATE_ENABLED, TBSTYLE_BUTTON, ::GlobalStringTable->GetString( IDS_BTN_RAISE_PRI ), ::GlobalStringTable->GetString( IDS_BTN_RAISE_PRI_TOOLTIP ) }, { 1, CMD_PRI_DOWN, TBSTATE_ENABLED, TBSTYLE_BUTTON, ::GlobalStringTable->GetString( IDS_BTN_LOWER_PRI ), ::GlobalStringTable->GetString( IDS_BTN_LOWER_PRI_TOOLTIP ) } }; if( bSelect == TRUE ) { DebugPrint(( TEXT("++++++++++++++++++++++++++++ Device Controlbar SELECT") )); // if the controlbar hasn't already been created, create it if( myToolBar == NULL ) { hr = pComp->m_pControlbar->Create( TOOLBAR, pComp, &lpUnk ); if( FAILED( hr ) ) { assert( FALSE ); return E_UNEXPECTED; } hr = lpUnk->QueryInterface( IID_IToolbar, (void **)&myToolBar ); if( FAILED( hr ) ) { assert( FALSE ); return E_UNEXPECTED; } lpUnk->Release(); HBITMAP hbUp = LoadBitmap( ::GlobalStringTable->GetInstance(), MAKEINTRESOURCE( IDB_UP ) ); assert( hbUp != NULL ); HBITMAP hbDown = LoadBitmap( ::GlobalStringTable->GetInstance(), MAKEINTRESOURCE( IDB_DOWN ) ); assert( hbDown != NULL ); hr = myToolBar->AddBitmap( 1, hbUp, 16, 16, 0x00ff00ff ); if( FAILED( hr ) ) { assert( FALSE ); return hr; } hr = myToolBar->AddBitmap( 1, hbDown, 16, 16, 0x00ff00ff ); if( FAILED( hr ) ) { assert( FALSE ); return hr; } hr = myToolBar->AddButtons( 2, buttons ); if( FAILED( hr ) ) { assert( FALSE ); return hr; } } hr = pComp->m_pControlbar->Attach( TOOLBAR, myToolBar ); } else { DebugPrint(( TEXT("--------------------------- Device Controlbar DESELECT") )); // detach the toolbar hr = pComp->m_pControlbar->Detach( myToolBar ); } return hr; } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // // // Internal Functions // // HRESULT CInternalDevice::RetrieveNewInfo() /*++ Routine Description: Retrieves new device info. Arguments: None. Return Value: HRESULT which indicates SUCCEEDED() or FAILED() --*/ { HANDLE portHandle = NULL; HRESULT hr = S_OK; EnterCriticalSection( &csDeviceLock ); assert( hFaxServer != NULL ); try { do { if( m_pCompData->QueryRpcError() ) { hr = E_UNEXPECTED; break; } // open the port if( !FaxOpenPort( hFaxServer, dwDeviceId, PORT_OPEN_QUERY, &portHandle ) ) { if (GetLastError() != ERROR_ACCESS_DENIED) { m_pCompData->NotifyRpcError( TRUE ); assert(FALSE); } ::GlobalStringTable->SystemErrorMsg( GetLastError() ); hr = E_UNEXPECTED; break; } // free the existing buffer if( pDeviceInfo != NULL ) { FaxFreeBuffer( (PVOID) pDeviceInfo ); pDeviceInfo = NULL; } // get data if( !FaxGetPort( portHandle, &pDeviceInfo ) ) { if (GetLastError() != ERROR_ACCESS_DENIED) { m_pCompData->NotifyRpcError( TRUE ); assert(FALSE); } ::GlobalStringTable->SystemErrorMsg( GetLastError() ); hr = E_UNEXPECTED; break; } } while( 0 ); } catch( ... ) { m_pCompData->NotifyRpcError( TRUE ); assert(FALSE); ::GlobalStringTable->SystemErrorMsg( GetLastError() ); hr = E_UNEXPECTED; } // close port if( portHandle != NULL ) { FaxClose( portHandle ); } LeaveCriticalSection( &csDeviceLock ); return hr; } HRESULT CInternalDevice::CommitNewInfo() /*++ Routine Description: Writes out the current device state to the fax service. Arguments: None. Return Value: HRESULT which indicates SUCCEEDED() or FAILED() --*/ { HANDLE portHandle = NULL; HRESULT hr = S_OK; DWORD ec = ERROR_SUCCESS; EnterCriticalSection( &csDeviceLock ); assert( hFaxServer != NULL ); try { do { if( m_pCompData->QueryRpcError() ) { hr = E_UNEXPECTED; break; } // open the port if( !FaxOpenPort( hFaxServer, dwDeviceId, PORT_OPEN_MODIFY, &portHandle ) ) { if (GetLastError() != ERROR_ACCESS_DENIED) { m_pCompData->NotifyRpcError( TRUE ); assert(FALSE); } ::GlobalStringTable->SystemErrorMsg( GetLastError() ); hr = E_UNEXPECTED; break; } // set data if( !FaxSetPort( portHandle, pDeviceInfo ) ) { ec = GetLastError(); if (ec != ERROR_ACCESS_DENIED && ec != ERROR_DEVICE_IN_USE) { m_pCompData->NotifyRpcError( TRUE ); assert(FALSE); } if (ec == ERROR_DEVICE_IN_USE) ::GlobalStringTable->PopUpMsg( NULL , IDS_DEVICE_INUSE, TRUE, 0 ); else ::GlobalStringTable->SystemErrorMsg( ec ); hr = E_UNEXPECTED; break; } FaxClose( portHandle ); portHandle = NULL; // See if faxstat is running HWND hWndFaxStat = FindWindow(FAXSTAT_WINCLASS, NULL); if (hWndFaxStat) { if (SendMessage(hWndFaxStat, WM_FAXSTAT_MMC, (WPARAM) dwDeviceId, 0)) { ::GlobalStringTable->PopUpMsg( NULL, IDS_DEVICE_MANUALANSWER, FALSE, 0 ); } } } while( 0 ); } catch( ... ) { m_pCompData->NotifyRpcError( TRUE ); assert(FALSE); ::GlobalStringTable->SystemErrorMsg( GetLastError() ); hr = E_UNEXPECTED; } // close port if( portHandle != NULL ) { FaxClose( portHandle ); } LeaveCriticalSection( &csDeviceLock ); return hr; } //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////////// // // // Utility Functions // // LPTSTR CInternalDevice::GetStatusString( DWORD state ) /*++ Routine Description: Returns the correct status description given a device state. Arguments: state - the state of the device Return Value: A LPTSTR to a buffer containing the description of the state. Do not free this string. --*/ { int i; int j = 1; // this will break if the defines ever change!! for( i = 1; i <= 25; i++ ) { if( j & state ) { break; } j = j << 1; // shift left } if( i <= 24 && i > 0 ) { return ::GlobalStringTable->GetString( IDS_DEVICE_STATUS + i ); } else { assert( FALSE ); return ::GlobalStringTable->GetString( IDS_DEVICE_STATUS_UNKNOWN ); } }