📄 mainmod.cpp
字号:
for ( jx = 0; jx < pStore->m_pStocks->cDel && pStore->m_pStocks->rgidChg[ix] != pStore->m_pStocks->rgidDel[jx]; jx++ );
if ( jx >= pStore->m_pStocks->cDel )
{
PITEM pItem = pStore->MakeNewItem( pStore->m_pStocks->rgidChg[ ix ] );
if ( pItem &&
FAILED( pStore->m_pNotify->OnItemNotify( RNC_MODIFIED, SZ_STORE_PROG_ID, SZ_STOCKPOR, (HREPLITEM)pItem, 0 ) ) )
delete pItem;
}
}
for ( ix = 0; ix < pStore->m_pStocks->cDel; ix++ )
{
PITEM pItem = pStore->MakeNewItem( pStore->m_pStocks->rgidDel[ ix ] );
if ( pItem &&
FAILED( pStore->m_pNotify->OnItemNotify( RNC_DELETED, SZ_STORE_PROG_ID, SZ_STOCKPOR, (HREPLITEM)pItem, 0 ) ) )
delete pItem;
}
pStore->m_pStocks->cChg = pStore->m_pStocks->cDel = 0;
pStore->Unlock();
}
return 0;
}
//
// ==================== IReplStore Implementation ===========================
//
/*++
--*/
STDMETHODIMP CStore::Initialize
(
IReplNotify *pNotify,
UINT uFlags // either ISF_SELECTED_DEVICE or ISF_REMOTE_CONNECTED
)
{
LONG lErr;
HKEY hRootKey;
DWORD dw, dwSize;
char szFile[ MAX_PATH * 2 ];
HRESULT hr = NOERROR;
m_uFlags = uFlags;
m_pNotify = pNotify;
// get the correct registry key for stock sync options
hr = m_pNotify->QueryDevice( ( uFlags & ISF_SELECTED_DEVICE )? QDC_SEL_DEVICE_KEY : QDC_CON_DEVICE_KEY, (LPVOID *)&hRootKey );
if ( FAILED( hr ) )
goto Exit;
// read the registry for the stock portfolio file to sync
dw = REG_SZ;
dwSize = sizeof( szFile );
lErr = RegQueryValueEx( hRootKey, "Stock File", NULL, &dw, (const LPBYTE)szFile, &dwSize );
if ( lErr == ERROR_SUCCESS )
lstrcpy( m_szStockFile, szFile );
// read the registry for sync option
dwSize = sizeof( v_uSyncOpt );
v_uSyncOpt = SO_ALL;
RegQueryValueEx( hRootKey, "Sync Option", NULL, &dw, (const LPBYTE)&v_uSyncOpt, &dwSize );
RegCloseKey( hRootKey );
hr = Open( TRUE );
// do not show any blocking UI (like the message box) if we are connected remotely
if ( FAILED( hr ) && !( uFlags & ISF_REMOTE_CONNECTED ) )
{
wsprintf( szFile, "Unable to open Stock Portfolio file %s for synchronization. Error Code: 0x%X", m_szStockFile, hr );
MessageBox( m_pNotify->GetWindow( 0 ), szFile, "Synchronization Error", MB_OK | MB_ICONSTOP );
}
Exit:
if ( SUCCEEDED( hr ) )
m_uFlags |= ISF_INITIALIZED;
return hr;
}
/*++
--*/
STDMETHODIMP CStore::GetStoreInfo
(
PSTOREINFO pInfo // pointers to the STOREINFO structure
)
{
if ( pInfo->cbStruct != sizeof( STOREINFO ) )
return E_INVALIDARG;
pInfo->uFlags = SCF_SINGLE_THREAD;
// ProgId of the store
lstrcpy( pInfo->szProgId, SZ_STORE_PROG_ID );
lstrcpy( pInfo->szStoreDesc, "Stock Portfolio" );
// done here if store is not yet initialized
if ( !( m_uFlags & ISF_INITIALIZED ) )
return NOERROR;
// construct something that uniquely identifies the store
pInfo->cbStoreId = lstrlen( m_szStockFile ) + 1;
if ( pInfo->cbStoreId > pInfo->cbMaxStoreId )
return E_OUTOFMEMORY;
if ( pInfo->lpbStoreId == NULL )
return E_POINTER;
memcpy( pInfo->lpbStoreId, m_szStockFile, lstrlen( m_szStockFile ) + 1 );
return NOERROR;
}
/*++
--*/
STDMETHODIMP_(int) CStore::CompareStoreIDs
(
LPBYTE lpbID1, // points to the first store ID
UINT cbID1, // size of the first store ID
LPBYTE lpbID2, // points to the second store ID
UINT cbID2 // size of the second store ID
)
{
if ( cbID1 < cbID2 )
return -1;
if ( cbID1 > cbID2 )
return 1;
return memcmp( lpbID1, lpbID2, cbID1 );
}
/*++
--*/
STDMETHODIMP CStore::ReportStatus
(
HREPLFLD hFolder, // Handle of the folder this status applies to. NULL if status applies to all folders
HREPLITEM hItem, // Handle of the object this status applies to. NULL if status applies to all objects
UINT uStatus, // See RSC_xxx defined in cesync.h for all possibble code
UINT uParam // Additional information about the status, based on uStatus code
)
{
switch( uStatus )
{
case RSC_INTERRUPT: // client should abort whatever it's doing now
break;
case RSC_BEGIN_SYNC: // ActiveSync service manager is about to start
break;
case RSC_END_SYNC: // ActiveSync service manager is about to end
break;
case RSC_BEGIN_CHECK: // FindFirstItem is about to be called, followed by FindNextItem
break;
case RSC_END_CHECK: // FindItemClose has been called
break;
case RSC_DATE_CHANGED: // System Date has changed
break;
case RSC_RELEASE: // ActiveSync service manager is about to release the service provider
// close file
Close();
// wait for the listen thread to die
if ( m_hListen )
{
SetEvent( m_hKillListen );
WaitForSingleObject( m_hListen, 10000 );
CloseHandle( m_hListen );
m_hListen = NULL;
};
break;
case RSC_REMOTE_SYNC: // Indicates if remote sync is about to start. uParam will TRUE if all sync
// will be remote until this status is reported again with uParam set to FALSE
break;
case RSC_BEGIN_SYNC_OBJ: // ActiveSync service manager is about to start on an object type. uReserved is a pointer to a IEnumReplItem
break;
case RSC_END_SYNC_OBJ: // ActiveSync service manager is about to end on an object type.
break;
case RSC_OBJ_TYPE_ENABLED: // ActiveSync service manager of the given object is enabled, hFolder is indeed a pointer to a string (object type name)
break;
case RSC_OBJ_TYPE_DISABLED: // ActiveSync service manager of the given object is disabled, hFolder is indeed a pointer to a string (object type name)
break;
case RSC_BEGIN_BATCH_WRITE: // A series of SetPacket will be called on a number of objects, this is the right time for some service providers to start a transaction
break;
case RSC_END_BATCH_WRITE: // above write ends, this is the right time for some service providers to commit the transaction
break;
case RSC_CONNECTION_CHG: // connection status has changed. uParam is TRUE if connection established. FALSE otherwise.
break;
case RSC_WRITE_OBJ_FAILED: // failed writing an object on the device. uParam is the HRESULT code.
break;
case RSC_DELETE_OBJ_FAILED: // failed deleting an object on the device. uParam is the HRESULT code.
break;
}
return NOERROR;
}
//
// ==================== Object management routines =====================
//
/*++
--*/
STDMETHODIMP_(UINT) CStore::ObjectToBytes
(
HREPLOBJ hObject,
LPBYTE lpb // Points to a buffer where the array of bytes should be store. Could be NULL.
)
{
LPBYTE lpbStart = lpb;
CReplObject *pObject = (CReplObject *)hObject;
CFolder *pFolder = (CFolder *)pObject;
CItem *pItem = (CItem *)pObject;
if ( lpbStart )
*lpb = OBJECT_VERSION;
lpb++;
if ( lpbStart )
*(PUINT)lpb = pObject->m_uType;
lpb += sizeof( pObject->m_uType );
switch( pObject->m_uType )
{
case OT_FOLDER:
break;
case OT_ITEM:
if ( lpbStart )
*(PUINT)lpb = pItem->m_uid;
lpb += sizeof( pItem->m_uid );
if ( lpbStart )
*(FILETIME *)lpb = pItem->m_ftModified;
lpb += sizeof( pItem->m_ftModified );
break;
}
return lpb - lpbStart;
}
/*++
--*/
STDMETHODIMP_(HREPLOBJ) CStore::BytesToObject
(
LPBYTE lpb, // Points to a buffer where the array of bytes should be store. Could be NULL.
UINT cb // size of the buffer
)
{
CReplObject *pObject = NULL;
CFolder *pFolder;
CItem *pItem;
BYTE bVersion = *lpb++;
UINT uType = *(PUINT)lpb;
lpb += sizeof( uType );
if ( bVersion != OBJECT_VERSION )
{
// convert the data based on bVersion
}
switch( uType )
{
case OT_FOLDER:
pObject = pFolder = new CFolder;
break;
case OT_ITEM:
pObject = pItem = new CItem;
pItem->m_uid = *(PUINT)lpb;
lpb += sizeof( pItem->m_uid );
pItem->m_ftModified = *(FILETIME *)lpb;
lpb += sizeof( pItem->m_ftModified );
break;
}
return (HREPLOBJ)pObject;
}
/*++
--*/
STDMETHODIMP_(void) CStore::FreeObject
(
HREPLOBJ hObject // handler of the object whose contents need to be freed
)
{
delete (CReplObject *)hObject;
}
/*++
--*/
STDMETHODIMP_(BOOL) CStore::CopyObject
(
HREPLOBJ hObjSrc, // handle to the source object
HREPLOBJ hObjDst // handle to the destination object
)
{
CReplObject *pObjSrc = (CReplObject *)hObjSrc;
CReplObject *pObjDst = (CReplObject *)hObjDst;
if ( pObjSrc->m_uType != pObjDst->m_uType )
return FALSE;
switch( pObjSrc->m_uType )
{
case OT_ITEM:
((CItem *)pObjDst)->m_uid = ((CItem *)pObjSrc)->m_uid;
((CItem *)pObjDst)->m_ftModified = ((CItem *)pObjSrc)->m_ftModified;
break;
case OT_FOLDER:
break;
}
return TRUE;
}
/*++
--*/
STDMETHODIMP CStore::IsValidObject
(
HREPLFLD hFolder, // handle of the folder where this item belongs
HREPLITEM hItem, // handle of the object, could be NULL
UINT uFlags // Reserved. Must be 0.
)
{
CFolder *pFolder = (CFolder *)hFolder;
CItem *pItem = (CItem *)hItem;
PSTOCK pStock;
if ( pFolder )
{
if ( pFolder->m_uType != OT_FOLDER )
return HRESULT_FROM_WIN32( ERROR_INVALID_HANDLE );
}
if ( pItem )
{
if ( pItem->m_uType != OT_ITEM )
return HRESULT_FROM_WIN32( ERROR_INVALID_HANDLE );
Lock();
pStock = FindStock( pItem->m_uid );
Unlock();
if ( !pStock )
return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
}
return NOERROR;
}
//
// ============= folder related routines ================
//
/*++
--*/
STDMETHODIMP CStore::GetFolderInfo
(
LPCSTR lpszName, // Name of the object type. It's taken from the registry.
HREPLFLD *phFolder, // Output pointers, points to the handle of the new folder
IUnknown **ppObjHandler // Output pointers, points to the object handler of this object type
)
{
CFolder *pFolder = (CFolder *)*phFolder;
BOOL fNew = (pFolder == NULL);
// either set up the new CFolder class (when fNew is TRUE) or reinitialize the class (when fNew is FALSE)
if ( fNew )
pFolder = new CFolder;
*phFolder = (HREPLFLD)pFolder;
*ppObjHandler = m_pObjHandler;
// we need only to set m_fChange to TRUE here since IsFolderChanged need only to return TRUE once
pFolder->m_fChanged = TRUE;
return NOERROR;
}
/*++
--*/
STDMETHODIMP CStore::IsFolderChanged
(
HREPLFLD hFolder, // Handle of the folder
BOOL *pfChanged // Points to a Boolean that will be set to TRUE if folder is changed
)
{
// since we support real time detection of changes/deletes, we can simply return FALSE here.
if ( pfChanged )
*pfChanged = ((CFolder *)hFolder)->m_fChanged;
((CFolder *)hFolder)->m_fChanged = FALSE;
return NOERROR;
}
//
// ============= Enumeration of folder objects ================
//
/*++
--*/
STDMETHODIMP CStore::FindFirstItem
(
HREPLFLD hFolder, // handle to a folder
HREPLITEM *phItem, // Output, points to the handle of the new object
BOOL *pfExist // Output, points to a boolean value that will be set to TRUE if there is an object in the folder
)
{
UINT ix;
CFolder *pFolder = (CFolder *)hFolder;
// file should be opened by now and make sure enumeration is not nested
if ( m_hFile == INVALID_HANDLE_VALUE || m_rgpItems )
return E_UNEXPECTED;
// take a snap shot of the stock allocate and allocate all items at once
Lock();
m_ixCurrItem = 0;
m_cItems = m_pStocks->cStocks;
m_rgpItems = new PITEM[ m_cItems ];
if ( !m_rgpItems )
{
Unlock();
return E_OUTOFMEMORY;
}
for ( ix = 0; ix < m_cItems; ix++ )
{
m_rgpItems[ix] = new CItem;
if ( !m_rgpItems[ix] )
{
Unlock();
return E_OUTOFMEMORY;
}
m_rgpItems[ix]->m_uid = m_pStocks->rgStocks[ix].uidStock;
m_rgpItems[ix]->m_ftModified = m_pStocks->rgStocks[ix].ftLastModified;
}
// we don't need change/delete log any more
m_pStocks->cChg = m_pStocks->cDel = 0;
Unlock();
return FindNextItem( hFolder, phItem, pfExist );
}
/*++
--*/
STDMETHODIMP CStore::FindNextItem
(
HREPLFLD hFolder, // handle to a folder
HREPLITEM *phItem, // Output, points to the handle of the new object
BOOL *pfExist // Output, points to a boolean value that will be set to TRUE if there is an object in the folder
)
{
CFolder *pFolder = (CFolder *)hFolder;
if ( pfExist )
*pfExist = FALSE;
if ( !m_rgpItems )
return E_UNEXPECTED;
if ( m_ixCurrItem < m_cItems )
{
*phItem = (HREPLITEM)m_rgpItems[ m_ixCurrItem ];
// now ActiveSync service manager owns the handle, reset ours to NULL so it won't be deleted
m_rgpItems[ m_ixCurrItem ] = NULL;
m_ixCurrItem++;
if ( pfExist )
*pfExist = TRUE;
}
return NOERROR;
}
/*++
--*/
STDMETHODIMP CStore::FindItemClose
(
HREPLFLD hFolder // handle to a folder
)
{
DWORD dw;
if ( !m_rgpItems )
return E_UNEXPECTED;
delete [] m_rgpItems;
m_rgpItems = NULL;
// spawn a second thread to listen to changes, if we haven't do so already
if ( !m_hListen )
m_hListen = CreateThread( NULL, 0, Listen, (LPVOID)this, 0, &dw );
return NOERROR;
}
//
// ================== object related routines ================
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -