⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mainmod.cpp

📁 Activesync Mobile 的同步软件开发例子
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            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 + -