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

📄 mainmod.cpp

📁 Activesync Mobile 的同步软件开发例子
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************\
*       This is a part of the Microsoft Source Code Samples.
*       Copyright (C) 1993-1997 Microsoft Corporation.
*       All rights reserved.
*       This source code is only intended as a supplement to
*       Microsoft Development Tools and/or WinHelp documentation.
*       See these sources for detailed information regarding the
*       Microsoft samples programs.
\******************************************************************************/

/*++

Module Name:
    
      mainmod.cpp

Abstract:

    Implementation of IReplStore

--*/

#include <windows.h>
#include "mainmod.h"

#define EXIT_ON_FAIL(hr)                                                            \
        if (FAILED (hr))                                                             \
        {                                                                               \
            goto Exit;                                                                  \
        }           \
        else


HINSTANCE       v_hInst;
static char     v_szStockFile[ MAX_PATH ];
static char     v_szDBVol[ MAX_PATH ]; 
static UINT     v_uSyncOpt;
static CStore   *v_pStore;

BOOL WINAPI DllMain ( HANDLE hInstDll, ULONG ulReason, LPVOID lpReserved )
{
    switch( ulReason )
    {
    case DLL_PROCESS_ATTACH :
        v_hInst = (HINSTANCE)hInstDll;
        break;

    case DLL_PROCESS_DETACH:
        break;

    case DLL_THREAD_ATTACH:
        break;

    case DLL_THREAD_DETACH:
        break;

    }
    return TRUE;
}


//
//  ============ Required OLE implementation for InProc servers ======================
//
// CClassFactory object creates CStore objects

class CClassFactory : public IClassFactory 
{
private:
    LONG    m_cRef; 

public:
    CClassFactory( void ) : m_cRef( 0 ) {};

    virtual STDMETHODIMP            QueryInterface( REFIID iid, LPVOID* ppv);
    virtual STDMETHODIMP_(ULONG)    AddRef(); 
    virtual STDMETHODIMP_(ULONG)    Release();

    // IClassFactory members
    virtual STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID*);
    virtual STDMETHODIMP LockServer(BOOL);
};


// Count number of objects and number of locks
static LONG v_cObj = 0;
static LONG v_cLock = 0;

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)  
{
    if (!IsEqualIID(riid, IID_IUnknown) && !IsEqualIID(riid, IID_IClassFactory))
        return CLASS_E_CLASSNOTAVAILABLE;

    //return our IClassFactory for CStore objects
    *ppv = (LPVOID)new CClassFactory();
    if ( NULL == *ppv ) 
        return E_OUTOFMEMORY;

    //AddRef the object through any interface we return
    ((LPUNKNOWN)*ppv)->AddRef();

    return NOERROR;
}

STDAPI DllCanUnloadNow(void)  
{
    return ResultFromScode( 0L == v_cObj && 0 == v_cLock? S_OK : S_FALSE );
}

HRESULT CreateValue (HKEY hkeyParent, char * szKey, char * szValueName, DWORD dwType, 
                     void * pValue, DWORD dwLength)
{
    HRESULT hr      =   E_UNEXPECTED;
    LONG    lResult;
    HKEY    hkey    =   NULL;



    // create or open hkeyParent\szKey
    lResult = ::RegCreateKeyEx (hkeyParent, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, 
                                KEY_ALL_ACCESS, NULL, &hkey, NULL);
    hr = HRESULT_FROM_WIN32 (lResult);
    EXIT_ON_FAIL (hr);

    
    // create hkeyParent\szKey\szValueName = pValue
    lResult = ::RegSetValueEx (hkey, szValueName, 0, dwType, reinterpret_cast <BYTE *> (pValue), dwLength);
    hr = HRESULT_FROM_WIN32 (lResult);
    EXIT_ON_FAIL (hr);

    
    // success 
    hr = S_OK;


Exit:
    // close key
    lResult = ::RegCloseKey (hkey);
    if (SUCCEEDED (hr))  // only overwrite hr if we haven't already failed above
    {
        hr = HRESULT_FROM_WIN32 (lResult);
    }

    return hr;
}




//
//  DllRegisterServer 
//  Called to register the provider with desktop sync
//
STDAPI DllRegisterServer (void)
{
    LONG    lResult;
    HRESULT hr                      =   E_UNEXPECTED;
    HKEY    hkey                    =   NULL;
    char    szKey[1024];
    char    szTemp[1024];
    HKEY    hkeyGuidProvider        =   NULL;
    char    szFilename[_MAX_PATH];
    DWORD   dwDisabled;
    DWORD   dwVersion;


    // open HKCR\CLSID
    lResult = ::RegOpenKeyEx (HKEY_CLASSES_ROOT, "CLSID", 0, KEY_ALL_ACCESS, &hkey);
    hr = HRESULT_FROM_WIN32 (lResult);
    EXIT_ON_FAIL (hr);


    // create HKCR\CLSID\{guid}
    lResult = ::RegCreateKeyEx (hkey, SZ_GUID_SYNCSAMPLE, 0, NULL, REG_OPTION_NON_VOLATILE, 
                                KEY_ALL_ACCESS, NULL, &hkeyGuidProvider, NULL);
    hr = HRESULT_FROM_WIN32 (lResult);
    EXIT_ON_FAIL (hr);

    // close HKCR\CLSID
    lResult = ::RegCloseKey (hkey);
    hr = HRESULT_FROM_WIN32 (lResult);
    EXIT_ON_FAIL (hr);


    // create HKCR\CLSID\{guid}, default value = store name
    lResult = ::RegSetValueEx (hkeyGuidProvider, NULL, 0, REG_SZ, (BYTE *) SZ_NAME, ::strlen (SZ_NAME) + 1);
    hr = HRESULT_FROM_WIN32 (lResult);
    EXIT_ON_FAIL (hr);

    
    // create HKCR\CLSID\{guid}\InprocServer32, default value = (path to this DLL)
    lResult = ::GetModuleFileName (v_hInst, szFilename, _MAX_PATH);
    if (lResult == 0)
    {
        hr = E_OUTOFMEMORY;
        goto Exit;
    }
    
    hr = ::CreateValue (hkeyGuidProvider, "InprocServer32", NULL, REG_SZ, szFilename, ::strlen (szFilename) + 1);
    EXIT_ON_FAIL (hr);


    // create HKCR\CLSID\{our guid}\ProgID, default value = (progid)
    hr = ::CreateValue (hkeyGuidProvider, "ProgID", NULL, REG_SZ, SZ_STORE_PROG_ID, ::strlen (SZ_STORE_PROG_ID) + 1);
    EXIT_ON_FAIL (hr);

    
    // create HKCR\(prog id), default value = (SZ_NAME)
    // create HKCR\(prog id), "Display Name" = 
    // create HKCR\(prog id), "Version" = 0x00030000    // version 3 or better allows settings
                                                        // to be configured during partnership wiz
    hr = ::CreateValue (HKEY_CLASSES_ROOT, SZ_STORE_PROG_ID, NULL, REG_SZ, SZ_NAME, ::strlen (SZ_NAME) + 1);
    EXIT_ON_FAIL (hr);

    hr = ::CreateValue (HKEY_CLASSES_ROOT, SZ_STORE_PROG_ID, "Display Name", REG_SZ, SZ_DISPLAY_NAME, ::strlen(SZ_DISPLAY_NAME) + 1);
    EXIT_ON_FAIL (hr);

    dwVersion = 0x00030000;
    hr = ::CreateValue (HKEY_CLASSES_ROOT, SZ_STORE_PROG_ID, "Version", REG_DWORD, &dwVersion, sizeof (dwVersion));
    EXIT_ON_FAIL (hr);

    // create HKCR\(prog id)\CLSID, default value = (GUID)
    ::wsprintf (szKey, "%s\\CLSID", SZ_STORE_PROG_ID);
    hr = ::CreateValue (HKEY_CLASSES_ROOT, szKey, NULL, REG_SZ, SZ_GUID_SYNCSAMPLE, ::strlen (SZ_GUID_SYNCSAMPLE) + 1);
    EXIT_ON_FAIL (hr);

    //
    //  Available on PocketPC and Smartphone only

    // create HKLM\SOFTWARE\Microsoft\Windows CE Services\SpecialDefaults\PocketPC\
    //        Services\Synchronization\Objects\(SZ_NAME), (multiple values)
    ::wsprintf (szKey, "SOFTWARE\\Microsoft\\Windows CE Services\\SpecialDefaults\\PocketPC\\"
                       "Services\\Synchronization\\Objects\\%s", SZ_NAME);
    
    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, NULL, REG_SZ, SZ_NAME, ::strlen (SZ_NAME) + 1);
    EXIT_ON_FAIL (hr);
    
    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, "Store", REG_SZ, SZ_STORE_PROG_ID, ::strlen (SZ_STORE_PROG_ID) + 1);
    EXIT_ON_FAIL (hr);
    
    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, "Display Name", REG_SZ, SZ_DISPLAY_NAME, ::strlen (SZ_DISPLAY_NAME) + 1);
    EXIT_ON_FAIL (hr);

    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, "Plural Name", REG_SZ, SZ_PLURAL_NAME, ::strlen (SZ_PLURAL_NAME) + 1);
    EXIT_ON_FAIL (hr);

    dwDisabled = 0;
    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, "Disabled", REG_DWORD, &dwDisabled, sizeof (dwDisabled));
    EXIT_ON_FAIL (hr);

    ::wsprintf (szTemp, "%s,-%d", szFilename, IDI_ICON);
    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, "DefaultIcon", REG_SZ, szTemp, ::strlen (szTemp) + 1);
    EXIT_ON_FAIL (hr);


    // create HKLM\SOFTWARE\Microsoft\Windows CE Services\SpecialDefaults\SmartPhone\
    //        Services\Synchronization\Objects\(SZ_NAME), (multiple values)
    ::wsprintf (szKey, "SOFTWARE\\Microsoft\\Windows CE Services\\SpecialDefaults\\SmartPhone\\"
                       "Services\\Synchronization\\Objects\\%s", SZ_NAME);
    
    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, NULL, REG_SZ, SZ_NAME, ::strlen (SZ_NAME) + 1);
    EXIT_ON_FAIL (hr);
    
    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, "Store", REG_SZ, SZ_STORE_PROG_ID, ::strlen (SZ_STORE_PROG_ID) + 1);
    EXIT_ON_FAIL (hr);

    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, "Display Name", REG_SZ, SZ_DISPLAY_NAME, ::strlen (SZ_DISPLAY_NAME) + 1);
    EXIT_ON_FAIL (hr);

    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, "Plural Name", REG_SZ, SZ_PLURAL_NAME, ::strlen (SZ_PLURAL_NAME) + 1);
    EXIT_ON_FAIL (hr);

    dwDisabled = 0;
    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, "Disabled", REG_DWORD, &dwDisabled, sizeof (dwDisabled));
    EXIT_ON_FAIL (hr);

    ::wsprintf (szTemp, "%s,-%d", szFilename, IDI_ICON);
    hr = ::CreateValue (HKEY_LOCAL_MACHINE, szKey, "DefaultIcon", REG_SZ, szTemp, ::strlen (szTemp) + 1);
    EXIT_ON_FAIL (hr);

    hr = S_OK;

Exit:
    return hr;
}





STDAPI DllUnregisterServer (void)
{
    char    szKey[1024];



    ::wsprintf (szKey, "CLSID\\%s\\ProgID", SZ_GUID_SYNCSAMPLE);
    ::RegDeleteKey (HKEY_CLASSES_ROOT, szKey);


    ::wsprintf (szKey, "CLSID\\%s\\InprocServer32", SZ_GUID_SYNCSAMPLE);
    ::RegDeleteKey (HKEY_CLASSES_ROOT, szKey);


    ::wsprintf (szKey, "CLSID\\%s", SZ_GUID_SYNCSAMPLE);
    ::RegDeleteKey (HKEY_CLASSES_ROOT, szKey);


    ::wsprintf (szKey, "%s\\CLSID", SZ_STORE_PROG_ID);
    ::RegDeleteKey (HKEY_CLASSES_ROOT, szKey);


    ::RegDeleteKey (HKEY_CLASSES_ROOT, SZ_STORE_PROG_ID);


    ::wsprintf (szKey, "SOFTWARE\\Microsoft\\Windows CE Services\\SpecialDefaults\\PocketPC\\"
                       "Services\\Synchronization\\Objects\\%s", SZ_NAME);
    ::RegDeleteKey (HKEY_LOCAL_MACHINE, szKey);


    ::wsprintf (szKey, "SOFTWARE\\Microsoft\\Windows CE Services\\SpecialDefaults\\SmartPhone\\"
                       "Services\\Synchronization\\Objects\\%s", SZ_NAME);
    ::RegDeleteKey (HKEY_LOCAL_MACHINE, szKey);
    
    return S_OK;
}





STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, LPVOID* ppv)  
{
    *ppv=NULL;
    if ( IsEqualIID( riid, IID_IUnknown ) || IsEqualIID( riid, IID_IClassFactory ) )
        *ppv=(LPVOID)this;

    if( NULL != *ppv )  
    {
        ((LPUNKNOWN)*ppv)->AddRef();
        return NOERROR;
    }
    return E_NOINTERFACE;
}

STDMETHODIMP_(ULONG) CClassFactory::AddRef( void )
{
    ULONG urc;
    urc = (ULONG)InterlockedIncrement( &m_cRef );
    return(urc);
}

STDMETHODIMP_(ULONG) CClassFactory::Release()
{
    ULONG urc;
    urc = (ULONG)InterlockedDecrement( &m_cRef ); 
    if (urc == 0 ) 
        delete this;

    return urc;
}

STDMETHODIMP CClassFactory::CreateInstance( LPUNKNOWN pUnkOuter, REFIID riid, LPVOID* ppvObj )
{
    CStore  *pObj;
    HRESULT hr;
    DWORD   dwLastError = 0;
    
    *ppvObj = NULL;
    hr = E_OUTOFMEMORY;

    if ( NULL != pUnkOuter && !IsEqualIID( riid, IID_IUnknown ) )
        return E_NOINTERFACE;

    pObj = new CStore( pUnkOuter );
    if ( NULL == pObj ) 
        return E_OUTOFMEMORY;

    hr = pObj->QueryInterface( riid, ppvObj );

    InterlockedIncrement( &v_cObj );

    if ( FAILED( hr ) ) 
    {
        delete pObj; // <-- this destroys LastError
        if( dwLastError )
            SetLastError( dwLastError );
    }

    return hr;
}


STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
{
    if (fLock)
        InterlockedIncrement( &v_cLock );
    else     
        InterlockedDecrement( &v_cLock );

    return NOERROR;
}



//
// ================== Basic Implementation of IReplStore ====================
//

/*++
--*/
CStore::CStore( LPUNKNOWN pUnkOuter )
{
    m_cRef          = 0;
    m_pUnkOuter     = pUnkOuter;
    m_uFlags        = 0;
    m_pObjHandler   = new CDataHandler( this );
    m_rgpItems      = NULL;
    m_ixCurrItem    = 0;
    m_cItems        = 0;

    lstrcpy( m_szStockFile, SZ_DEFAULT_PORTFILE );
    m_hFile         = INVALID_HANDLE_VALUE;
    m_hMapObj       = NULL;
    m_hMutex        = NULL;
    m_pStocks       = NULL;

    m_hListen       = NULL;
    m_hKillListen   = CreateEvent( NULL, FALSE, FALSE, NULL );
    m_hStockChg     = CreateEvent( NULL, FALSE, FALSE, SZ_CHANGE_EVENT );
}

/*++
--*/
CStore::~CStore()
{
    CloseHandle( m_hKillListen );
    CloseHandle( m_hStockChg );

    delete m_pObjHandler;
    InterlockedDecrement( &v_cObj );
}


//
// ==================== IUnknown Implementation ===========================
//

/*++
--*/
STDMETHODIMP CStore::QueryInterface( REFIID iid, LPVOID  *ppvObj )
{
    *ppvObj = NULL;   // set to NULL, in case we fail.

    if ( IsEqualIID( iid, IID_IUnknown ) )
        *ppvObj = (void*)this;
    else if ( IsEqualIID( iid, IID_IReplStore ) )
        *ppvObj = (void*)(IReplStore *)this;
    else if ( IsEqualIID( iid, IID_IReplStore2 ) )
        *ppvObj = (void*)(IReplStore2 *)this;
    else if ( m_pUnkOuter )
        return m_pUnkOuter->QueryInterface( iid, ppvObj );

    if ( *ppvObj )
    {
        ((IUnknown *)(*ppvObj))->AddRef();
        return NOERROR;
    }
    return E_NOINTERFACE;
}

/*++
--*/
STDMETHODIMP_(ULONG) CStore::AddRef()
{
    ULONG   urc;

    if ( m_pUnkOuter )
        urc = m_pUnkOuter->AddRef();
    else
        urc = (ULONG)InterlockedIncrement( &m_cRef );
    return urc;
}

/*++
--*/
STDMETHODIMP_(ULONG) CStore::Release()
{
    ULONG   urc;

    if ( m_pUnkOuter )
        urc = m_pUnkOuter->Release();
    else
    {
        urc =(ULONG)InterlockedDecrement( &m_cRef );
        if ( urc == 0 )
            delete this;
    }
    return urc;
}

//
// ================= thread listening to the changes/deletes in the Stock Portfolio app
//
DWORD WINAPI Listen( LPVOID pvStore )
{
    CStore  *pStore = (CStore *)pvStore;
    DWORD   dwObj;
    HANDLE  rgHandles[] = { pStore->m_hKillListen, pStore->m_hStockChg };
    UINT    ix, jx;

    for ( ;; )
    {
        dwObj = WaitForMultipleObjects( 2, rgHandles, FALSE, INFINITE );

        // will quit this thread for any other value
        if ( dwObj != WAIT_OBJECT_0 + 1 )
            break;

        if ( !pStore->m_pNotify ) continue;

        // get the change/delete log from the Stock Portfolio app
        pStore->Lock();
        for ( ix = 0; ix < pStore->m_pStocks->cChg; ix++ )
        {
            // check if this change is deleted too

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -