📄 mainmod.cpp
字号:
/*++
--*/
STDMETHODIMP_(int) CStore::CompareItem
(
HREPLITEM hItem1, // Points to the handle of first object. This handle is guaranteed to be created by IReplStore::FindFirstObject or IReplStore::FindNextObject
HREPLITEM hItem2 // Points to the handle of second object. This handle is guaranteed to be created by IReplStore::FindFirstObject or IReplStore::FindNextObject
)
{
CItem *pItem1 = (CItem *)hItem1;
CItem *pItem2 = (CItem *)hItem2;
if ( pItem1->m_uid == pItem2->m_uid )
return 0;
if ( pItem1->m_uid < pItem2->m_uid )
return -1;
return 1;
}
/*++
--*/
STDMETHODIMP_(BOOL) CStore::IsItemChanged
(
HREPLFLD hFolder, // Handle of a folder
HREPLITEM hItem, // Handle of an object
HREPLITEM hItemComp // Handle of the object used for comparison, could be NULL
)
{
CFolder *pFolder = (CFolder *)hFolder;
CItem *pItem = (CItem *)hItem;
CItem *pItemComp = (CItem *)hItemComp;
BOOL fChanged = FALSE;
if ( pItemComp )
fChanged = CompareFileTime( &pItem->m_ftModified, &pItemComp->m_ftModified );
else
{
PSTOCK pStock;
// read the modification time stamp from the object into ft
Lock();
pStock = FindStock( pItem->m_uid );
fChanged = pStock && CompareFileTime( &pItem->m_ftModified, &pStock->ftLastModified );
Unlock();
}
return fChanged;
}
/*++
--*/
STDMETHODIMP_(BOOL) CStore::IsItemReplicated
(
HREPLFLD hFolder, // Handle of a folder
HREPLITEM hItem // Handle of an object
)
{
CFolder *pFolder = (CFolder *)hFolder;
CItem *pItem = (CItem *)hItem;
PSTOCK pStock;
char cSym;
// hItem can be passed NULL.
if ( pItem == NULL )
return TRUE;
// check if pItem should be replicated using information stored both in pFolder & pItem
Lock();
pStock = FindStock( pItem->m_uid );
if ( pStock )
cSym = pStock->szSym[0];
Unlock();
if ( !pStock ) return FALSE;
switch ( v_uSyncOpt )
{
case SO_ALL: return TRUE;
case SO_AM: return cSym >= 'A' && cSym <= 'M';
case SO_NZ: return cSym >= 'N' && cSym <= 'Z';
}
return FALSE;
}
/*++
--*/
STDMETHODIMP_(void) CStore::UpdateItem
(
HREPLFLD hFolder, // Handle of a folder
HREPLITEM hItemDst, // Handle of the destination object
HREPLITEM hItemSrc // Handle to the source object, could be NULL.
)
{
CFolder *pFolder = (CFolder *)hFolder;
CItem *pItemDst = (CItem *)hItemDst;
CItem *pItemSrc = (CItem *)hItemSrc;
if ( pItemSrc )
{
pItemDst->m_ftModified = pItemSrc->m_ftModified;
}
else
{
// Update the time stamp stored in the given handle
Lock();
PSTOCK pStock = FindStock( pItemDst->m_uid );
if ( pStock )
pItemDst->m_ftModified = pStock->ftLastModified;
Unlock();
}
}
//
// ==================== UI related routines =====================
//
/*++
--*/
STDMETHODIMP CStore::GetConflictInfo( PCONFINFO pConfInfo )
{
// make sure we have the right version of OBJUIDATA
if ( pConfInfo->cbStruct != sizeof( CONFINFO ) )
return E_INVALIDARG;
lstrcpy( pConfInfo->szLocalName, "Stock" );
lstrcpy( pConfInfo->szRemoteName, "Stock" );
CItem *pLocalItem = (CItem *)pConfInfo->hLocalItem;
CItem *pRemoteItem = (CItem *)pConfInfo->hRemoteItem;
PSTOCK pLocalStock, pRemoteStock;
Lock();
pLocalStock = FindStock( pLocalItem->m_uid );
pRemoteStock = FindStock( pRemoteItem->m_uid );
if ( pLocalStock && pRemoteStock )
{
// resolve the conflict automatically if two stocks are considered identical
if ( !lstrcmpi( pLocalStock->szCompany, pRemoteStock->szCompany ) &&
!lstrcmpi( pLocalStock->szSym, pRemoteStock->szSym ) &&
!lstrcmpi( pLocalStock->szLastPrice, pRemoteStock->szLastPrice ) &&
!lstrcmpi( pLocalStock->szPurDate, pRemoteStock->szPurDate ) &&
!lstrcmpi( pLocalStock->szPurPrice, pRemoteStock->szPurPrice ) )
{
Unlock();
return RERR_IGNORE;
}
}
if ( pLocalStock )
wsprintf( pConfInfo->szLocalDesc, "%s\r\nPrice: %s\r\nPur. Price: %s",
pLocalStock->szCompany, pLocalStock->szLastPrice,
pLocalStock->szPurPrice, pLocalStock->szCompany );
if ( pRemoteStock )
wsprintf( pConfInfo->szRemoteDesc, "%s\r\nPrice: %s\r\nPur. Price: %s",
pRemoteStock->szCompany, pRemoteStock->szLastPrice,
pRemoteStock->szPurPrice, pRemoteStock->szCompany );
Unlock();
return NOERROR;
}
STDMETHODIMP CStore::DoOptionsDialog(HWND hwndParent, LPCSTR lpszObjType, IReplNotify * pntfy)
{
HRESULT hr = NOERROR;
v_pStore = this;
lstrcpy( v_szStockFile, m_szStockFile );
lstrcpy( v_szDBVol, "" );
//
// Note: Unable to call QueryDevice since the SSP may not have been enabled.
//
if ( DialogBox( v_hInst, TEXT( "SyncOptDlg" ), hwndParent, (DLGPROC)dlgSyncOpt ) == IDOK )
{
hr = NOERROR;
}
else
{
hr = RERR_CANCEL;
}
return hr;
}
BOOL CALLBACK dlgSyncOpt( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
if ( v_uSyncOpt == SO_AM )
CheckDlgButton( hDlg, IDC_SYNC_AM, TRUE );
else if ( v_uSyncOpt == SO_NZ )
CheckDlgButton( hDlg, IDC_SYNC_NZ, TRUE );
else
CheckDlgButton( hDlg, IDC_SYNC_ALL, TRUE );
SetDlgItemText( hDlg, IDC_DB_VOL, v_szDBVol );
SetDlgItemText( hDlg, IDC_FILE, v_pStore->m_szStockFile );
return TRUE;
case WM_COMMAND:
switch( LOWORD( wParam ) )
{
case IDOK:
if ( IsDlgButtonChecked( hDlg, IDC_SYNC_AM ) )
v_uSyncOpt = SO_AM;
else if ( IsDlgButtonChecked( hDlg, IDC_SYNC_NZ ) )
v_uSyncOpt = SO_NZ;
else
v_uSyncOpt = SO_ALL;
GetDlgItemText( hDlg, IDC_FILE, v_szStockFile, sizeof( v_szStockFile ) );
EndDialog( hDlg, IDOK );
break;
case IDCANCEL:
EndDialog( hDlg, IDCANCEL );
break;
};
break;
}
return FALSE;
}
/*++
--*/
STDMETHODIMP CStore::ActivateDialog
(
UINT uDlg, // Which dialog should be actiavted
HWND hwndParent, // Handle of the window that should be used as parent for the dialog
HREPLFLD hFolder, // Points to a valid STD for the folder
IEnumReplItem *penum // Points to a enumerator of object STD for objects stored in the folder
)
{
HRESULT hr;
SDREQUEST sd;
WCHAR wszDBVol[ MAX_PATH ];
if ( uDlg != OPTIONS_DIALOG )
return E_NOTIMPL;
v_pStore = this;
lstrcpy( v_szStockFile, m_szStockFile );
// call device to get the database volume name, the QueryDevice will return error if no device is connected
memset( wszDBVol, 0, sizeof( wszDBVol ) );
memset( &sd, 0, sizeof( sd ) );
lstrcpy( sd.szObjType, SZ_STOCKPOR );
sd.fSet = FALSE; // we are reading data from device
sd.uCode = 1; // we can have up to 8 different code
sd.lpbData = (LPBYTE)wszDBVol; // we are passing a buffer to the call,
// we can also pass NULL, in which case,
// we must free the buffer using GlobalFree after we are done
sd.cbData = sizeof( wszDBVol );
hr = m_pNotify->QueryDevice( QDC_SYNC_DATA, (LPVOID *)&sd );
if ( hr == RERR_NO_DEVICE )
lstrcpy( v_szDBVol, "<Device is not connected>" );
else if ( FAILED( hr ) )
lstrcpy( v_szDBVol, "<Erroring reading data from device>" );
else if ( wszDBVol[0] == 0 )
lstrcpy( v_szDBVol, "System Volume" );
else
{
// need to convert Unicode
WideCharToMultiByte( CP_ACP, 0, wszDBVol, -1, v_szDBVol, sizeof( v_szDBVol ) - 1, NULL, NULL );
}
if ( DialogBox( v_hInst, TEXT( "SyncOptDlg" ), hwndParent, (DLGPROC)dlgSyncOpt ) == IDOK )
{
// see if the stock file is changed, and if the new file is valid
if ( lstrcmpi( v_szStockFile, m_szStockFile ) && GetFileAttributes( v_szStockFile ) != (DWORD)-1 )
{
// save the new file into registry
HKEY hKey;
// get the correct registry key for stock sync options
if ( SUCCEEDED( m_pNotify->QueryDevice( ( m_uFlags & ISF_SELECTED_DEVICE )? QDC_SEL_DEVICE_KEY : QDC_CON_DEVICE_KEY, (LPVOID *)&hKey ) ) )
{
// read the hKey for the stock portfolio file to sync
RegSetValueEx( hKey, "Stock File", NULL, REG_SZ, (const LPBYTE)v_szStockFile, lstrlen( v_szStockFile ) + 1 );
RegSetValueEx( hKey, "Sync Option", NULL, REG_DWORD, (const LPBYTE)&v_uSyncOpt, sizeof( v_uSyncOpt ) );
RegCloseKey( hKey );
// ask ActiveSync service manager to unload service providers so the new option can be applied
return RERR_UNLOAD;
}
}
return NOERROR;
}
return RERR_CANCEL;
}
/*++
--*/
STDMETHODIMP CStore::GetObjTypeUIData
(
HREPLFLD hFolder, // Input, points to a STD of a folder that stores the object
POBJUIDATA pData // Output, points to a OBJUIDATA structure.
)
{
// make sure we have the right version of OBJUIDATA
if ( pData->cbStruct != sizeof( OBJUIDATA ) )
return E_INVALIDARG;
pData->hIconLarge = (HICON)LoadImage( v_hInst, MAKEINTRESOURCE( IDI_ICON ), IMAGE_ICON, 32, 32, 0 );
pData->hIconSmall = (HICON)LoadImage( v_hInst, MAKEINTRESOURCE( IDI_ICON ), IMAGE_ICON, 16, 16, 0 );
lstrcpy( pData->szName, "Stock Portfolio Data" );
lstrcpy( pData->szTypeText, "Database" );
lstrcpy( pData->szPlTypeText, "Databases" );
lstrcpy( pData->szSyncText, m_szStockFile );
return E_NOTIMPL;
}
LPSTR MakeMapObjName( LPSTR lpszFile )
{
static char v_szMapObjName[ MAX_PATH ];
UINT ix;
LPSTR lpsz;
for ( ix = 0, lpsz = lpszFile; *lpsz; ix++, lpsz++ )
{
if ( *lpsz >= 'a' && *lpsz <= 'z' )
v_szMapObjName[ix] = *lpsz - 'a' + 'A';
else if ( *lpsz >= 'A' && *lpsz <= 'Z' )
v_szMapObjName[ix] = *lpsz;
else
v_szMapObjName[ix] = 'A';
}
v_szMapObjName[ix] = 0;
return v_szMapObjName;
}
/*++
HRESULT CStore::Open
Open the file named by m_szStockFile
--*/
HRESULT CStore::Open( BOOL fCreateNew )
{
// is it open already?
if ( m_hFile != INVALID_HANDLE_VALUE )
return NOERROR;
BOOL fNewFile = ( GetFileAttributes( m_szStockFile ) == (DWORD)-1 );
HRESULT hr = fNewFile && !fCreateNew? E_FAIL : NOERROR;
if ( FAILED( hr ) ) goto Exit;
// need to create this file if it doesn't exist
if ( fNewFile )
m_hFile = CreateFile( m_szStockFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
else
m_hFile = CreateFile( m_szStockFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( m_hFile == INVALID_HANDLE_VALUE )
{
hr = E_FAIL;
goto Exit;
}
m_hMapObj = CreateFileMapping( m_hFile, NULL, PAGE_READWRITE, 0, sizeof( PORTFILE ), MakeMapObjName( m_szStockFile ) );
if ( m_hMapObj == NULL )
{
hr = E_FAIL;
goto Exit;
}
// Get a pointer to the file-mapped shared memory:
m_pStocks = (PPORTFILE)MapViewOfFile( m_hMapObj, FILE_MAP_WRITE, 0, 0, 0 );
if ( m_pStocks == NULL )
{
hr = E_FAIL;
goto Exit;
}
// Get the Mutex
if ( !m_hMutex )
m_hMutex = CreateMutex( NULL, FALSE, SZ_MUTEX );
if ( !m_hMutex )
{
hr = E_FAIL;
goto Exit;
}
if ( fNewFile )
{
Lock();
ClearStruct( *m_pStocks );
m_pStocks->uVer1 = PORTFILE_VERSION;
m_pStocks->uVer2 = PORTFILE_VERSION;
m_pStocks->uidCurrStock = 1;
FlushViewOfFile( 0, sizeof( PORTFILE ) );
Unlock();
}
else
{
Lock();
if ( m_pStocks->uVer1 != PORTFILE_VERSION || m_pStocks->uVer2 != PORTFILE_VERSION )
{
hr = E_UNEXPECTED;
Unlock();
goto Exit;
}
Unlock();
}
Exit:
return hr;
}
/*++
HRESULT CStore::Close
Close the file named by m_szStockFile
--*/
HRESULT CStore::Close( void )
{
if ( m_hMutex )
{
CloseHandle( m_hMutex );
m_hMutex = NULL;
}
if ( m_pStocks )
{
UnmapViewOfFile( m_pStocks );
m_pStocks = NULL;
}
if ( m_hMapObj )
{
CloseHandle( m_hMapObj );
m_hMapObj = NULL;
}
if ( m_hFile != INVALID_HANDLE_VALUE )
{
CloseHandle( m_hFile );
m_hFile = INVALID_HANDLE_VALUE;
}
return NOERROR;
}
/*++
PSTOCK CStore::FindStock
Find a stock using the stock ID, return NULL if not found.
m_pStocks must be protected by the mutex before calling this routine and
before finish using the pointer it returns
--*/
PSTOCK CStore::FindStock( UINT uidStock, PUINT puix )
{
UINT ix;
for ( ix = 0; ix < m_pStocks->cStocks; ix++ )
if ( m_pStocks->rgStocks[ix].uidStock == uidStock )
break;
if ( puix )
*puix = ix < m_pStocks->cStocks? ix : (UINT)-1;
return ix < m_pStocks->cStocks? m_pStocks->rgStocks + ix: NULL;
}
/*++
--*/
PITEM CStore::MakeNewItem( UINT uidStock )
{
PITEM pItem = new CItem;
PSTOCK pStock;
if ( pItem )
{
pItem->m_uid = uidStock;
// set the time stamp if we can
Lock();
pStock = FindStock( uidStock );
if ( pStock )
pItem->m_ftModified = pStock->ftLastModified;
Unlock();
}
return pItem;
}
//
// Function called when the SSP is enabled in the ActiveSync options dialog
//
HRESULT WINAPI OnSSPEnable(HWND hwnd)
{
MessageBox(hwnd, "StockPor- OnEnable", "StockPor", MB_OK);
return S_OK;
}
//
// Function called when the SSP is disabled in the ActiveSync options dialog
//
HRESULT WINAPI OnSSPDisable(HWND hwnd)
{
MessageBox(hwnd, "StockPor- OnDisable", "StockPor", MB_OK);
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -