1990 lines
55 KiB
C++
1990 lines
55 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
// File: Invoke.cpp
|
|
//
|
|
// Contents: Handles invocation cases, ENS, Schedule, etc.
|
|
//
|
|
// Classes: CSynchronizeInvoke
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "precomp.h"
|
|
|
|
// Review - Need to figure out logon logic. This just prevents ConnectionMade
|
|
// events from being handled while we are in logon. If IsNetworkAlive becomse async
|
|
// or someone calls IsNetworkAlive before us we will sync the same items twice.
|
|
BOOL g_InAutoSync = FALSE;
|
|
extern OSVERSIONINFOA g_OSVersionInfo; // osVersionInfo, setup by WinMain.
|
|
extern HINSTANCE g_hInst; // current instance
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::CSynchronizeInvoke, public
|
|
//
|
|
// Synopsis: Constructor
|
|
// Increments the applications lifetime
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CSynchronizeInvoke::CSynchronizeInvoke()
|
|
{
|
|
m_cRef = 1;
|
|
m_pUnkOuter = &m_Unknown; // only support our unknown for know.
|
|
m_pITypeInfoLogon = NULL;
|
|
m_pITypeInfoNetwork = NULL;
|
|
|
|
m_Unknown.SetParent(this);
|
|
|
|
#ifdef _SENS
|
|
m_PrivSensNetwork.SetParent(this);
|
|
m_PrivSensLogon.SetParent(this);
|
|
#endif // _SENS
|
|
|
|
AddRefOneStopLifetime(TRUE /*External*/);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::~CSynchronizeInvoke, public
|
|
//
|
|
// Synopsis: Destructor
|
|
// Decrements the applications lifetime
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CSynchronizeInvoke::~CSynchronizeInvoke()
|
|
{
|
|
|
|
if (m_pITypeInfoLogon)
|
|
{
|
|
m_pITypeInfoLogon->Release();
|
|
m_pITypeInfoLogon = NULL;
|
|
}
|
|
|
|
if (m_pITypeInfoNetwork)
|
|
{
|
|
m_pITypeInfoNetwork->Release();
|
|
m_pITypeInfoNetwork = NULL;
|
|
}
|
|
|
|
ReleaseOneStopLifetime(TRUE /*External*/);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::QueryInterface, public
|
|
//
|
|
// Synopsis: Standard QueryInterface
|
|
//
|
|
// Arguments: [iid] - Interface ID
|
|
// [ppvObj] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::QueryInterface(REFIID riid, LPVOID FAR *ppv)
|
|
{
|
|
return m_pUnkOuter->QueryInterface(riid,ppv);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::AddRef, public
|
|
//
|
|
// Synopsis: Add reference
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSynchronizeInvoke::AddRef()
|
|
{
|
|
return m_pUnkOuter->AddRef();
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSychrononizeInvoke::Release, public
|
|
//
|
|
// Synopsis: Release reference
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSynchronizeInvoke::Release()
|
|
{
|
|
return m_pUnkOuter->Release();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::UpdateItems, public
|
|
//
|
|
// Synopsis: Handles a programmatic UpdateItems call.
|
|
//
|
|
// !!Warning - Liveness relies on a dialog being created
|
|
// before return or we could go away when the
|
|
// caler releases our interface.
|
|
//
|
|
// Arguments: [dwInvokeFlags] - InvokeFlags
|
|
// [rclsid] - clsid of handler to load
|
|
// [cbCookie] - Size of cookie data
|
|
// [lpCookie] - Ptr to cookie data.
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::UpdateItems(DWORD dwInvokeFlags,REFCLSID rclsid,
|
|
DWORD cbCookie,const BYTE*lpCookie)
|
|
{
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
CHndlrQueue * pHndlrQueue = NULL;
|
|
HANDLERINFO *pHandlerID;
|
|
JOBINFO *pJobInfo = NULL;
|
|
BOOL fReg;
|
|
DWORD dwRegistrationFlags;
|
|
int nCmdShow = (dwInvokeFlags & SYNCMGRINVOKE_MINIMIZED) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL;
|
|
|
|
// when a new UpdateItems come through do the following
|
|
// 1 - If should display choices see if existing choice dialog or create a new one
|
|
// and then add the new items to the choice queue
|
|
|
|
// 2 - If shouldn't display choices see if existing progress or create a new one
|
|
// and then add the items to the progress queue.
|
|
|
|
// behavior - If already an Update All choice dialog just pull it to the Front
|
|
// If Already an UpdateAll progress bar bring it to the front
|
|
// If Progress Bar but doesn't already contain an updateAll create the choice dialog.
|
|
|
|
#if _ZAWTRACK
|
|
LogZawTrack(dwInvokeFlags); // Track any invokes.
|
|
#endif _ZAWTRACK
|
|
|
|
pHndlrQueue = new CHndlrQueue(QUEUETYPE_CHOICE,NULL); // we don't use stored preferences on invoke so doesn't matter what pass in as the connection
|
|
|
|
if (NULL == pHndlrQueue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
return hr;
|
|
}
|
|
|
|
// attempt to initialize the queue
|
|
hr = pHndlrQueue->AddQueueJobInfo(
|
|
SYNCMGRFLAG_INVOKE | SYNCMGRFLAG_MAYBOTHERUSER,
|
|
0,NULL,NULL,FALSE,&pJobInfo);
|
|
|
|
fReg = RegGetHandlerRegistrationInfo(rclsid,&dwRegistrationFlags);
|
|
Assert(fReg || (0 == dwRegistrationFlags));
|
|
|
|
if ((NOERROR == hr) && NOERROR == pHndlrQueue->AddHandler(&pHandlerID,pJobInfo,dwRegistrationFlags))
|
|
{
|
|
hr = pHndlrQueue->CreateServer(pHandlerID,&rclsid);
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
hr = pHndlrQueue->Initialize(pHandlerID,0,SYNCMGRFLAG_INVOKE | SYNCMGRFLAG_MAYBOTHERUSER,
|
|
cbCookie,lpCookie);
|
|
}
|
|
|
|
}
|
|
|
|
// can release our reference on the job info
|
|
if (pJobInfo)
|
|
{
|
|
pHndlrQueue->ReleaseJobInfoExt(pJobInfo);
|
|
pJobInfo = NULL;
|
|
}
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
DWORD cbNumItemsAdded;
|
|
|
|
hr = pHndlrQueue->AddHandlerItemsToQueue(pHandlerID,&cbNumItemsAdded);
|
|
|
|
if (SYNCMGRINVOKE_STARTSYNC & dwInvokeFlags)
|
|
{
|
|
// if start invoke need to add the handlers items to the queue before
|
|
// transferring
|
|
|
|
|
|
if (NOERROR == hr && pHndlrQueue->AreAnyItemsSelectedInQueue())
|
|
{
|
|
CProgressDlg *pProgressDlg;
|
|
|
|
|
|
hr = FindProgressDialog(GUID_NULL,TRUE,nCmdShow,&pProgressDlg);
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
hr = pProgressDlg->TransferQueueData(pHndlrQueue);
|
|
ReleaseProgressDialog(GUID_NULL,pProgressDlg,FALSE);
|
|
}
|
|
|
|
}
|
|
|
|
pHndlrQueue->FreeAllHandlers(); // done with our queue.
|
|
|
|
pHndlrQueue->Release();
|
|
pHndlrQueue = NULL;
|
|
|
|
}
|
|
else
|
|
{
|
|
CChoiceDlg *pChoiceDlg;
|
|
|
|
// Bring up the Choice dialog, Let choice dialog actually addes the hanlder items
|
|
// if there are any so in the future we can async fill in the choices
|
|
|
|
hr = FindChoiceDialog(rclsid,TRUE,nCmdShow,&pChoiceDlg);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
|
|
if (FALSE == pChoiceDlg->SetQueueData(rclsid,pHndlrQueue) ) {
|
|
pHndlrQueue->FreeAllHandlers();
|
|
|
|
pHndlrQueue->Release();
|
|
|
|
pHndlrQueue = NULL;
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
|
|
ReleaseChoiceDialog(rclsid,pChoiceDlg);
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if initialize failed and have a queue release it now.
|
|
|
|
if (pHndlrQueue)
|
|
{
|
|
pHndlrQueue->FreeAllHandlers();
|
|
pHndlrQueue->Release();
|
|
pHndlrQueue = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
// if we successfully added a jobinfo to the queue release our reference.
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::UpdateAll, public
|
|
//
|
|
// Synopsis: Handles a programmatic UpdateAll call.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::UpdateAll(void)
|
|
{
|
|
SCODE sc = S_OK;
|
|
TCHAR pConnectName[RAS_MaxEntryName + 1];
|
|
TCHAR *pConnectionNameArray;
|
|
|
|
if (!LoadString(g_hInst, IDS_LAN_CONNECTION, pConnectName, ARRAY_SIZE(pConnectName)))
|
|
{
|
|
sc = GetLastError();
|
|
return sc;
|
|
}
|
|
pConnectionNameArray = pConnectName;
|
|
|
|
// Review - Do we Need proper connection or do we always just
|
|
// use the last items selected in a manual sync regardless
|
|
// of the current connection
|
|
|
|
return PrivUpdateAll(0,SYNCMGRFLAG_MANUAL | SYNCMGRFLAG_MAYBOTHERUSER,0,NULL,
|
|
1,&pConnectionNameArray,NULL,FALSE,NULL,0,0,FALSE);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::Logon, public
|
|
//
|
|
// Synopsis: Handles a Logon notification
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::Logon()
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
|
|
RegSetUserDefaults(); // Make Sure the UserDefaults are up to date
|
|
|
|
// if on Win9x just call IsNetworkAlive and rely on ConnectionMade
|
|
// events coming through. Can't just do this yet on NT 5.0 because
|
|
// not garanteed to get connectionMades on each logon.
|
|
|
|
if (VER_PLATFORM_WIN32_NT != g_OSVersionInfo.dwPlatformId)
|
|
{
|
|
LPNETAPI pNetApi;
|
|
DWORD dwFlags;
|
|
|
|
pNetApi = gSingleNetApiObj.GetNetApiObj();
|
|
|
|
if (pNetApi)
|
|
{
|
|
pNetApi->IsNetworkAlive(&dwFlags);
|
|
pNetApi->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = PrivHandleAutoSync(SYNCMGRFLAG_CONNECT | SYNCMGRFLAG_MAYBOTHERUSER);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::Logoff, public
|
|
//
|
|
// Synopsis: Handles a Logoff notification
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::Logoff()
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
|
|
RegSetUserDefaults(); // Make Sure the UserDefaults are up to date
|
|
|
|
hr = PrivHandleAutoSync(SYNCMGRFLAG_PENDINGDISCONNECT | SYNCMGRFLAG_MAYBOTHERUSER);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::Schedule, public
|
|
//
|
|
// Synopsis: Handles a shceduled notification
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
const TCHAR c_szTrayWindow[] = TEXT("Shell_TrayWnd");
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::Schedule(WCHAR *pszTaskName)
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
TCHAR szConnectionName[RAS_MaxEntryName + 1];
|
|
TCHAR *pszConnectionName = szConnectionName;
|
|
CONNECTIONSETTINGS ConnectionSettings;
|
|
|
|
if (!pszTaskName)
|
|
{
|
|
Assert(pszTaskName);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
|
|
// on Win9x Task Scheduler is on a per Machine basis and can fire before
|
|
// a user has logged on or Cancels the logon dialog. Check for if
|
|
// really logged on by seeing if the Shell Tray Window is present.
|
|
|
|
if (VER_PLATFORM_WIN32_WINDOWS == g_OSVersionInfo.dwPlatformId)
|
|
{
|
|
if (NULL == FindWindow(c_szTrayWindow, NULL))
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
}
|
|
|
|
// validate this is a valid schedule and if no registry data for
|
|
// it then delete the .job file.
|
|
// Get the UserName key from the TaskName itself since on NT schedules
|
|
// can fire if User provided as Password as a different user thant the
|
|
// current user.
|
|
|
|
int OffsetToUserName = lstrlen(WSZGUID_IDLESCHEDULE)
|
|
+ 1; // +1 for _ char between guid and user name.
|
|
WCHAR *pszDomainAndUser = pszTaskName + OffsetToUserName;
|
|
HKEY hkeySchedSync,hkeyDomainUser,hkeySchedName;
|
|
LONG lRegResult;
|
|
|
|
hkeySchedSync = hkeyDomainUser = hkeySchedName = NULL;
|
|
|
|
// open up keys ourselves so
|
|
lRegResult = RegOpenKeyEx (HKEY_LOCAL_MACHINE,SCHEDSYNC_REGKEY,0,KEY_READ, &hkeySchedSync);
|
|
|
|
if (ERROR_SUCCESS == lRegResult)
|
|
{
|
|
lRegResult = RegOpenKeyEx (hkeySchedSync,pszDomainAndUser,0,KEY_READ, &hkeyDomainUser);
|
|
}
|
|
|
|
if (ERROR_SUCCESS == lRegResult)
|
|
{
|
|
lRegResult = RegOpenKeyEx (hkeyDomainUser,pszTaskName,0,KEY_READ, &hkeySchedName);
|
|
}
|
|
|
|
// close up the keys
|
|
if (hkeySchedName) RegCloseKey(hkeySchedName);
|
|
if (hkeyDomainUser) RegCloseKey(hkeyDomainUser);
|
|
if (hkeySchedSync) RegCloseKey(hkeySchedSync);
|
|
|
|
// if any of the keys are bad then nix the TS file and return;
|
|
if ( ERROR_FILE_NOT_FOUND == lRegResult)
|
|
{
|
|
// TODO: Call function to delete this .job file when
|
|
// it is implemented for now just let it fire each time.
|
|
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
// assert is just so it fires if a new Error code occurs
|
|
// so we make sure we handle it properly
|
|
|
|
Assert(ERROR_SUCCESS == lRegResult);
|
|
|
|
|
|
// Now see if on Win9x schedule applies to the current User and if not just
|
|
// bail.
|
|
|
|
if (VER_PLATFORM_WIN32_NT != g_OSVersionInfo.dwPlatformId)
|
|
{
|
|
TCHAR szDomainUserName[MAX_DOMANDANDMACHINENAMESIZE];
|
|
|
|
GetDefaultDomainAndUserName(szDomainUserName,TEXT("_"), MAX_DOMANDANDMACHINENAMESIZE);
|
|
|
|
// !!!using strnicmp just since it is not case sensitive. Can switch
|
|
// to add verify that the lstrcmpi funciton works but I don't want
|
|
// to risk this for IE ship (rogerg)
|
|
|
|
if (0 != strnicmp(szDomainUserName,pszDomainAndUser,lstrlen(szDomainUserName)) )
|
|
{
|
|
return NOERROR;
|
|
}
|
|
}
|
|
|
|
|
|
// check to see if this is really and idle and if so foward on to Idle
|
|
// method
|
|
|
|
WCHAR *pszSchedCookieIdle = WSZGUID_IDLESCHEDULE;
|
|
int comparelength = (sizeof(WSZGUID_IDLESCHEDULE)/sizeof(WCHAR)) -1; // don't compare null
|
|
|
|
|
|
// set the Idle flag instead
|
|
// Note: the strnicmp function is a method on this class not the runtime call.
|
|
if (0 == strnicmp(pszSchedCookieIdle,pszTaskName,comparelength))
|
|
{
|
|
return Idle();
|
|
}
|
|
|
|
|
|
// finally made it past verification if you can get a Connection
|
|
// you can run the schedule.
|
|
|
|
if (RegGetSchedConnectionName(pszTaskName,pszConnectionName,ARRAY_SIZE(szConnectionName)))
|
|
{
|
|
BOOL fCanMakeConnection = FALSE;
|
|
DWORD cbCookie = (lstrlen(pszTaskName) + 1)*(sizeof(WCHAR)/sizeof(BYTE));
|
|
|
|
|
|
|
|
// if this is a valid schedule then go ahead and read in the settings
|
|
// by default don't let the connection be made.
|
|
|
|
lstrcpy(ConnectionSettings.pszConnectionName,pszConnectionName);
|
|
if (RegGetSchedSyncSettings(&ConnectionSettings,pszTaskName))
|
|
{
|
|
fCanMakeConnection = ConnectionSettings.dwMakeConnection;
|
|
}
|
|
|
|
|
|
|
|
// if this schedule can't make the connectione then
|
|
// check to see if the conneciton is available and if
|
|
// it isn't bail here.
|
|
|
|
BOOL fConnectionAvailable = FALSE;
|
|
|
|
if (!fCanMakeConnection)
|
|
{
|
|
if (S_OK == ConnectObj_IsConnectionAvailable(pszConnectionName))
|
|
{
|
|
fConnectionAvailable = TRUE;
|
|
}
|
|
}
|
|
|
|
// add to the queue and let the main progress determine if
|
|
// can handle the schedule.
|
|
|
|
if (fCanMakeConnection || fConnectionAvailable)
|
|
{
|
|
// on a schedule we pass in the schedule name for the cookie data.
|
|
hr = PrivUpdateAll(SYNCMGRINVOKE_STARTSYNC | SYNCMGRINVOKE_MINIMIZED,SYNCMGRFLAG_SCHEDULED,
|
|
cbCookie,(BYTE *) pszTaskName,1,&pszConnectionName,pszTaskName,fCanMakeConnection,NULL,0,0,FALSE);
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
AssertSz(0,"Schedule has no Connection");
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::Idle, public
|
|
//
|
|
// Synopsis: Handles an Idle Notifications
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 20-Feb-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::Idle()
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
|
|
// request the idle Lock, If someone already has it then just return.
|
|
if (NOERROR == (hr = RequestIdleLock()))
|
|
{
|
|
|
|
hr = RunIdle();
|
|
|
|
// if an error occured setting things up or nothing to do
|
|
// then release our idle lock.
|
|
if (NOERROR != hr)
|
|
{
|
|
ReleaseIdleLock();
|
|
}
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::RunIdle, public
|
|
//
|
|
// Synopsis: Runs an Idle.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 20-Feb-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::RunIdle()
|
|
{
|
|
// for not just run the Idle as a Connect
|
|
return PrivHandleAutoSync(SYNCMGRFLAG_IDLE);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::RasPendingDisconnect, private
|
|
//
|
|
// Synopsis: Handles a programmatic Ras Pending Disconnect calls.
|
|
//
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::RasPendingDisconnect(DWORD cbConnectionName,
|
|
const BYTE *lpConnectionName)
|
|
{
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
CONNECTIONOBJ *pConnectionObj;
|
|
|
|
// Thread with class factory is FreeThreaded so can block the return
|
|
// until update is complete.
|
|
|
|
// find connection object for this item so know its liveness.
|
|
hr = ConnectObj_FindConnectionObj( (TCHAR*) lpConnectionName,TRUE,&pConnectionObj);
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
HANDLE hRasPendingEvent;
|
|
|
|
|
|
if (NOERROR == (hr = ConnectObj_GetConnectionObjCompletionEvent(pConnectionObj,&hRasPendingEvent)))
|
|
{
|
|
|
|
hr = PrivAutoSyncOnConnection(SYNCMGRFLAG_PENDINGDISCONNECT | SYNCMGRFLAG_MAYBOTHERUSER,
|
|
1,(TCHAR **) &lpConnectionName,hRasPendingEvent);
|
|
|
|
|
|
// if successfully invoked the connection then wait for the event
|
|
// object to get set,
|
|
|
|
if (NOERROR == hr && hRasPendingEvent)
|
|
{
|
|
WaitForSingleObject(hRasPendingEvent,INFINITE); // review if can determine a timeout
|
|
}
|
|
else
|
|
{
|
|
// !!!!on failure call close the Connection to make sure
|
|
// the object gets cleaned up in case the progress queue didn't get kicked off.
|
|
// If someone is currently using a connection they will be closed which is
|
|
// the same as if autosync wasn't selected and the User chose to
|
|
// close while a sync was in progress.
|
|
|
|
ConnectObj_CloseConnection(pConnectionObj);
|
|
}
|
|
|
|
// Release our hold on the Connection.
|
|
ConnectObj_ReleaseConnectionObj(pConnectionObj);
|
|
|
|
if (hRasPendingEvent)
|
|
{
|
|
CloseHandle(hRasPendingEvent);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: QueryLoadHandlerOnEvent, private
|
|
//
|
|
// Synopsis: Determines if Handle needs to be loaded for the specified
|
|
// Event and Connection.
|
|
//
|
|
//
|
|
// Arguments: [pszClsid] - clsid of handler
|
|
// [dwSyncFlags] - SyncFlags to pass onto initialize
|
|
// [cbNumConnectionNames] - Number of ConnectionNames in array
|
|
// [ppConnectionNames] - array of connection names.
|
|
//
|
|
// Returns: TRUE - handler needs to be loaded
|
|
// FALSE - handler doesn't need to be loaded.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 24-Aug-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL QueryLoadHandlerOnEvent(TCHAR *pszClsid,DWORD dwSyncFlags,DWORD dwRegistrationFlags,
|
|
DWORD cbNumConnectionNames,TCHAR **ppConnectionNames)
|
|
{
|
|
BOOL fLoadHandler = TRUE;
|
|
DWORD dwSyncEvent = dwSyncFlags & SYNCMGRFLAG_EVENTMASK;
|
|
|
|
// see if handler is registered for the event
|
|
// if it is then we always load it. If its not the User had to have checked an item
|
|
if (
|
|
( (dwSyncEvent == SYNCMGRFLAG_IDLE) && !(dwRegistrationFlags & SYNCMGRREGISTERFLAG_IDLE) )
|
|
|| ( (dwSyncEvent == SYNCMGRFLAG_CONNECT) && !(dwRegistrationFlags & SYNCMGRREGISTERFLAG_CONNECT) )
|
|
|| ( (dwSyncEvent == SYNCMGRFLAG_PENDINGDISCONNECT) && !(dwRegistrationFlags & SYNCMGRREGISTERFLAG_PENDINGDISCONNECT) )
|
|
)
|
|
{
|
|
DWORD cbCurConnectionName;
|
|
|
|
fLoadHandler = FALSE;
|
|
|
|
for (cbCurConnectionName = 0 ; cbCurConnectionName < cbNumConnectionNames;cbCurConnectionName++)
|
|
{
|
|
fLoadHandler |= RegQueryLoadHandlerOnEvent(pszClsid,dwSyncFlags,ppConnectionNames[cbCurConnectionName]);
|
|
}
|
|
}
|
|
|
|
return fLoadHandler;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::PrivUpdateAll, private
|
|
//
|
|
// Synopsis: Handles a programmatic UpdateAll call.
|
|
//
|
|
// !!Warning - Liveness relies on a dialog being created
|
|
// before return or we could go away when the
|
|
// caler releases our interface.
|
|
//
|
|
// Arguments: [dwInvokeFlags] - InvokeFlags
|
|
// [dwSyncFlags] - SyncFlags to pass onto initialize
|
|
// [pszConnectionName] - array of connection names.
|
|
// [pszScheduleName] - Name of schedule that was fired if a scheduled event.
|
|
//
|
|
// Returns: S_OK/NOERROR - If handled result
|
|
// S_FALSE - if nothing to do (such as no items selected on Idle).
|
|
// error codes - if errors occured
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::PrivUpdateAll(DWORD dwInvokeFlags,DWORD dwSyncFlags,
|
|
DWORD cbCookie,const BYTE *lpCooke,
|
|
DWORD cbNumConnectionNames,TCHAR **ppConnectionNames,
|
|
TCHAR *pszScheduleName,BOOL fCanMakeConnection,HANDLE hRasPendingDisconnect,
|
|
ULONG ulIdleRetryMinutes,ULONG ulDelayIdleShutDownTime,BOOL fRetryEnabled)
|
|
{
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
CHndlrQueue * pHndlrQueue = NULL;
|
|
CLSID clsidChoice = GUID_NULL;
|
|
CChoiceDlg *pChoiceDlg = NULL;
|
|
JOBINFO *pJobInfo = NULL;
|
|
int nCmdShow = (dwInvokeFlags & SYNCMGRINVOKE_MINIMIZED) ? SW_SHOWMINIMIZED : SW_SHOWNORMAL;
|
|
DWORD dwSyncEvent = (dwSyncFlags & SYNCMGRFLAG_EVENTMASK);
|
|
|
|
// On an UpdateAll
|
|
// 1 - see if there is an existing UpdateAll choice, If so bring to foreground
|
|
// 2 - Bring up update All choice dialog.
|
|
|
|
// behavior - If already an Update All choice dialog just pull it to the Front
|
|
// If Already an UpdateAll progress bar bring it to the front
|
|
// If Progress Bar but doesn't already contain an updateAll create the choice dialog.
|
|
|
|
#if _ZAWTRACK
|
|
LogZawTrack(dwSyncFlags); // Track any invokes.
|
|
#endif _ZAWTRACK
|
|
|
|
Assert(NULL != ppConnectionNames && cbNumConnectionNames >= 1);
|
|
Assert(NULL == pszScheduleName || (SYNCMGRFLAG_SCHEDULED == dwSyncEvent)
|
|
|| (SYNCMGRFLAG_IDLE == dwSyncEvent) ); // review, temporary for idle.
|
|
|
|
pHndlrQueue = new CHndlrQueue(QUEUETYPE_CHOICE,NULL);
|
|
|
|
if (NULL == pHndlrQueue)
|
|
return E_OUTOFMEMORY;
|
|
|
|
hr = pHndlrQueue->AddQueueJobInfo(dwSyncFlags,cbNumConnectionNames,
|
|
ppConnectionNames,pszScheduleName,fCanMakeConnection
|
|
,&pJobInfo);
|
|
|
|
// loop through the reg getting the handlers and trying to
|
|
// create them.
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
TCHAR lpName[256];
|
|
DWORD cbName = 256;
|
|
HKEY hkOneStop;
|
|
CLSID clsid;
|
|
HANDLERINFO *pHandlerID;
|
|
BOOL fItemsInQueue = FALSE;
|
|
|
|
hkOneStop = RegGetHandlerTopLevelKey(KEY_READ);
|
|
|
|
if (hkOneStop)
|
|
{
|
|
DWORD dwIndex = 0;
|
|
|
|
|
|
while ( ERROR_SUCCESS == RegEnumKey(hkOneStop,dwIndex,
|
|
lpName,cbName) )
|
|
{
|
|
if (NOERROR == CLSIDFromString(lpName,&clsid) )
|
|
{
|
|
BOOL fReg;
|
|
DWORD dwRegistrationFlags;
|
|
BOOL fLoadHandler = TRUE;
|
|
|
|
fReg = RegGetHandlerRegistrationInfo(clsid,&dwRegistrationFlags);
|
|
Assert(fReg || (0 == dwRegistrationFlags));
|
|
|
|
//For scheduled, see if there are any items on this handler,
|
|
|
|
if ((SYNCMGRINVOKE_STARTSYNC & dwInvokeFlags) &&
|
|
(SYNCMGRFLAG_SCHEDULED == dwSyncEvent))
|
|
{
|
|
fLoadHandler = RegSchedHandlerItemsChecked(lpName, ppConnectionNames[0],pszScheduleName);
|
|
}
|
|
else if (SYNCMGRINVOKE_STARTSYNC & dwInvokeFlags)
|
|
{
|
|
fLoadHandler = QueryLoadHandlerOnEvent(lpName,dwSyncFlags,dwRegistrationFlags,
|
|
cbNumConnectionNames,ppConnectionNames);
|
|
}
|
|
|
|
if (fLoadHandler)
|
|
{
|
|
if (NOERROR == pHndlrQueue->AddHandler(&pHandlerID,pJobInfo,dwRegistrationFlags))
|
|
{
|
|
pHndlrQueue->CreateServer(pHandlerID,&clsid);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
dwIndex++;
|
|
}
|
|
|
|
RegCloseKey(hkOneStop);
|
|
}
|
|
|
|
// Initialize the items.
|
|
|
|
CLSID pHandlerClsid;
|
|
|
|
while (NOERROR == pHndlrQueue->FindFirstHandlerInState(HANDLERSTATE_INITIALIZE,GUID_NULL,&pHandlerID,&pHandlerClsid))
|
|
{
|
|
pHndlrQueue->Initialize(pHandlerID,0,dwSyncFlags,
|
|
cbCookie,lpCooke);
|
|
}
|
|
|
|
// can release jobinfo since handlers need to hold their own addref.
|
|
if (pJobInfo)
|
|
{
|
|
pHndlrQueue->ReleaseJobInfoExt(pJobInfo);
|
|
pJobInfo = NULL;
|
|
}
|
|
|
|
// if start invoke need to add the handlers items to the queue before
|
|
// transferring
|
|
|
|
while (NOERROR == pHndlrQueue->FindFirstHandlerInState(HANDLERSTATE_ADDHANDLERTEMS,GUID_NULL,&pHandlerID,&pHandlerClsid))
|
|
{
|
|
DWORD cbNumItemsAdded;
|
|
|
|
hr = pHndlrQueue->AddHandlerItemsToQueue(pHandlerID,&cbNumItemsAdded);
|
|
|
|
// if an item was added, then there are items in the queue
|
|
if (cbNumItemsAdded)
|
|
{
|
|
fItemsInQueue = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Move handlers that won't establish connections to end
|
|
// of handler list.
|
|
//
|
|
pHndlrQueue->SortHandlersByConnection();
|
|
|
|
if (SYNCMGRINVOKE_STARTSYNC & dwInvokeFlags)
|
|
{
|
|
CProgressDlg *pProgressDlg;
|
|
CLSID clsid_Progress = GUID_NULL;
|
|
|
|
// For Idle we want to use the idle progress dialog
|
|
// currently progress dialog relies on some globals so
|
|
// need to change that first before checking this in
|
|
if (SYNCMGRFLAG_IDLE == dwSyncEvent)
|
|
{
|
|
clsid_Progress = GUID_PROGRESSDLGIDLE;
|
|
}
|
|
|
|
// if not items are selected, just free the queue.
|
|
// Review - it would be better to always call Progress and progress
|
|
// itself not show until there are items to synchronize
|
|
if (pHndlrQueue->AreAnyItemsSelectedInQueue())
|
|
{
|
|
|
|
hr = FindProgressDialog(clsid_Progress,TRUE,nCmdShow,&pProgressDlg);
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
// for an Idle we now request the defaults for retryIdle
|
|
// and delay shutdown, and change the queue order
|
|
// based on the last item
|
|
if (SYNCMGRFLAG_IDLE == dwSyncEvent)
|
|
{
|
|
CLSID clsidLastHandler;
|
|
|
|
pProgressDlg->SetIdleParams(ulIdleRetryMinutes,
|
|
ulDelayIdleShutDownTime,fRetryEnabled);
|
|
|
|
if (NOERROR == GetLastIdleHandler(&clsidLastHandler))
|
|
{
|
|
pHndlrQueue->ScrambleIdleHandlers(clsidLastHandler);
|
|
}
|
|
}
|
|
|
|
hr = pProgressDlg->TransferQueueData(pHndlrQueue);
|
|
ReleaseProgressDialog(clsid_Progress,pProgressDlg,FALSE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE; // return S_FALSE IF NOTHING TO DO.
|
|
}
|
|
|
|
|
|
pHndlrQueue->FreeAllHandlers(); // done with our queue.
|
|
|
|
pHndlrQueue->Release();
|
|
pHndlrQueue = NULL;
|
|
|
|
}
|
|
else
|
|
{
|
|
CChoiceDlg *pChoiceDlg;
|
|
BOOL fDontShowIfNoItems = (
|
|
(SYNCMGRFLAG_CONNECT == dwSyncEvent)
|
|
|| (SYNCMGRFLAG_PENDINGDISCONNECT == dwSyncEvent ) );
|
|
|
|
// if the choice has been requested by a logon/logoff event and
|
|
// there aren't any items in the queue for the User to choose then
|
|
// if you want to turn on the code to now display anything
|
|
// turn on this If statement. For now we always show the choice.
|
|
|
|
if (1 /* !fDontShowIfNoItems || fItemsInQueue */)
|
|
{
|
|
|
|
// Bring up the Choice dialog, Let choice dialog actually addes the hanlder items
|
|
// if there are any so in the future we can async fill in the choices
|
|
|
|
hr = FindChoiceDialog(clsidChoice,TRUE,nCmdShow,&pChoiceDlg);
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
if (FALSE == pChoiceDlg->SetQueueData(clsidChoice,pHndlrQueue) )
|
|
{
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
else
|
|
{
|
|
pHndlrQueue = NULL; // set queue to NULL since Choice dialog owns it now.
|
|
}
|
|
|
|
ReleaseChoiceDialog(clsidChoice,pChoiceDlg);
|
|
}
|
|
}
|
|
|
|
// release our queue if still have it otherwise choice owns it.
|
|
if (pHndlrQueue)
|
|
{
|
|
pHndlrQueue->FreeAllHandlers();
|
|
pHndlrQueue->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::PrivHandleAutoSync, private
|
|
//
|
|
// Synopsis: Handles an AutoSync Update. Figures out what connections
|
|
// if any are active and invoke an AutoSync on each one.
|
|
//
|
|
// Arguments: [dwSyncFlags] - SyncFlags to pass onto initialize
|
|
//
|
|
// Returns: S_OK - sync was started
|
|
// S_FALSE - nothing to do
|
|
// appropriate error codes.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::PrivHandleAutoSync(DWORD dwSyncFlags)
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
DWORD dwFlags = 0;
|
|
BOOL fAlive = FALSE;
|
|
LPNETAPI pNetApi = NULL;
|
|
DWORD cbNumWanConnections = 0;
|
|
LPRASCONN pRasConn = NULL;
|
|
|
|
pNetApi = gSingleNetApiObj.GetNetApiObj();
|
|
|
|
if (NULL == pNetApi)
|
|
return S_FALSE;
|
|
|
|
g_InAutoSync = TRUE;
|
|
|
|
if (fAlive = pNetApi->IsNetworkAlive(&dwFlags))
|
|
{
|
|
TCHAR **pConnections; // array of connection names. End with NULL;
|
|
ULONG ulConnectionCount = 0;
|
|
|
|
if (NETWORK_ALIVE_LAN & dwFlags)
|
|
{
|
|
// We curently don't care about these error results.
|
|
// PrivAutoSyncOnConnection(dwSyncFlags,LANCONNECTIONNAME,NULL);
|
|
// Review what we want this to do.
|
|
ulConnectionCount += 1;
|
|
}
|
|
|
|
// loop through Ras Connections.
|
|
if ( NETWORK_ALIVE_WAN & dwFlags)
|
|
{
|
|
if (NOERROR == pNetApi->GetWanConnections(&cbNumWanConnections,&pRasConn)
|
|
&& (NULL != pRasConn) )
|
|
{
|
|
ulConnectionCount += cbNumWanConnections;
|
|
}
|
|
else
|
|
{
|
|
cbNumWanConnections = 0;
|
|
pRasConn = NULL;
|
|
}
|
|
}
|
|
// allocate array buffer for connections + 1 more for NULL
|
|
if (ulConnectionCount
|
|
&& (pConnections = (TCHAR **) ALLOC(sizeof(TCHAR *)*(ulConnectionCount + 1))))
|
|
{
|
|
TCHAR **pCurConnection = pConnections;
|
|
TCHAR *pLanConnection = NULL;
|
|
// initialize the array.
|
|
|
|
if (NETWORK_ALIVE_LAN & dwFlags)
|
|
{
|
|
pLanConnection = (TCHAR *) ALLOC(sizeof(TCHAR )*(MAX_PATH + 1));
|
|
|
|
if (pLanConnection)
|
|
{
|
|
if (LoadString(g_hInst, IDS_LAN_CONNECTION, pLanConnection, MAX_PATH))
|
|
{
|
|
*pCurConnection = pLanConnection;
|
|
++pCurConnection;
|
|
}
|
|
}
|
|
}
|
|
|
|
while (cbNumWanConnections)
|
|
{
|
|
cbNumWanConnections--;
|
|
*pCurConnection = pRasConn[cbNumWanConnections].szEntryName;
|
|
++pCurConnection;
|
|
}
|
|
|
|
*pCurConnection = NULL; // set the last connection to NULL;
|
|
|
|
// now autosync these puppies
|
|
hr = PrivAutoSyncOnConnection(dwSyncFlags,ulConnectionCount,pConnections,NULL);
|
|
|
|
if (pLanConnection)
|
|
{
|
|
FREE(pLanConnection);
|
|
}
|
|
|
|
if (pRasConn)
|
|
{
|
|
pNetApi->FreeWanConnections(pRasConn);
|
|
}
|
|
|
|
if (pConnections)
|
|
{
|
|
FREE(pConnections);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
g_InAutoSync = FALSE;
|
|
|
|
if ( pNetApi != NULL )
|
|
pNetApi->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::PrivAutoSyncOnConnection, private
|
|
//
|
|
// Synopsis: Handles an AutoSync Update. Given the SyncFlags and Connection
|
|
// determines if anything should be done on this connection
|
|
// and if so invokes it.
|
|
//
|
|
// Arguments: [dwSyncFlags] - SyncFlags to pass onto initialize
|
|
// [ppConnectionNames] - array of connectnames that apply to this request
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 08-Dec-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::PrivAutoSyncOnConnection(DWORD dwSyncFlags,DWORD cbNumConnectionNames,
|
|
TCHAR **ppConnectionNames,HANDLE hRasPendingEvent)
|
|
{
|
|
CONNECTIONSETTINGS ConnectSettings;
|
|
DWORD dwSyncEvent;
|
|
TCHAR **ppWorkerConnectionNames = NULL;
|
|
DWORD cbNumWorkerConnections = 0;
|
|
DWORD cbIndexCheck;
|
|
DWORD dwPromptMeFirst = 0;
|
|
ULONG ulIdleRetryMinutes;
|
|
ULONG ulDelayIdleShutDownTime;
|
|
BOOL fRetryEnabled = FALSE;
|
|
HRESULT hr = S_FALSE;
|
|
|
|
// assert there is at least one connection in the request
|
|
Assert(NULL != ppConnectionNames && cbNumConnectionNames >= 1);
|
|
|
|
if (NULL == ppConnectionNames || 0 == cbNumConnectionNames )
|
|
return S_FALSE;
|
|
|
|
if (NULL ==
|
|
(ppWorkerConnectionNames = (TCHAR **) ALLOC(sizeof(TCHAR**) * cbNumConnectionNames)))
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
dwSyncEvent = (dwSyncFlags & SYNCMGRFLAG_EVENTMASK);
|
|
|
|
// loop through all the connections and move any of the ones that
|
|
// are valid into our ppWorkerConnections name array.
|
|
|
|
TCHAR **ppCurWorkerConnectionNamesIndex = ppWorkerConnectionNames;
|
|
TCHAR **ppConnectionsNameIndex = ppConnectionNames;
|
|
|
|
for (cbIndexCheck = 0; cbIndexCheck < cbNumConnectionNames; cbIndexCheck++)
|
|
{
|
|
|
|
lstrcpy(ConnectSettings.pszConnectionName,*ppConnectionsNameIndex);
|
|
|
|
// See if should do anything on this connection.
|
|
if (RegGetSyncSettings(SYNCMGRFLAG_IDLE == dwSyncEvent
|
|
? SYNCTYPE_IDLE : SYNCTYPE_AUTOSYNC,&ConnectSettings))
|
|
{
|
|
if ( (((SYNCMGRFLAG_CONNECT == dwSyncEvent) && ConnectSettings.dwLogon))
|
|
||(((SYNCMGRFLAG_PENDINGDISCONNECT == dwSyncEvent) && ConnectSettings.dwLogoff))
|
|
||(((SYNCMGRFLAG_IDLE == dwSyncEvent) && ConnectSettings.dwIdleEnabled))
|
|
)
|
|
{
|
|
*ppCurWorkerConnectionNamesIndex = *ppConnectionsNameIndex;
|
|
++ppCurWorkerConnectionNamesIndex;
|
|
++cbNumWorkerConnections;
|
|
|
|
// update the variables for connection, for autosync if dwPromptMeFirst
|
|
// is set on any match connection
|
|
switch (dwSyncEvent)
|
|
{
|
|
case SYNCMGRFLAG_IDLE:
|
|
|
|
// minimum retry idle values win.
|
|
if (1 == cbNumWorkerConnections ||
|
|
ConnectSettings.ulIdleRetryMinutes < ulIdleRetryMinutes)
|
|
{
|
|
ulIdleRetryMinutes = ConnectSettings.ulIdleRetryMinutes;
|
|
}
|
|
|
|
|
|
// maximum wait for shutdown wins.
|
|
if (1 == cbNumWorkerConnections ||
|
|
ConnectSettings.ulDelayIdleShutDownTime > ulDelayIdleShutDownTime)
|
|
{
|
|
ulDelayIdleShutDownTime = ConnectSettings.ulDelayIdleShutDownTime;
|
|
}
|
|
|
|
// if any connection has retry after xxx minutes set to bool then retry
|
|
if (ConnectSettings.dwRepeatSynchronization)
|
|
{
|
|
fRetryEnabled = TRUE;
|
|
}
|
|
|
|
break;
|
|
case SYNCMGRFLAG_PENDINGDISCONNECT:
|
|
case SYNCMGRFLAG_CONNECT:
|
|
// if any connection is set to prompt then prompt.
|
|
if (ConnectSettings.dwPromptMeFirst)
|
|
{
|
|
dwPromptMeFirst = ConnectSettings.dwPromptMeFirst;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
++ppConnectionsNameIndex;
|
|
}
|
|
|
|
|
|
// if we found any connections to actually do work on start the sync off.
|
|
if (cbNumWorkerConnections > 0)
|
|
{
|
|
DWORD dwInvokeFlag = 0;
|
|
|
|
switch (dwSyncEvent)
|
|
{
|
|
case SYNCMGRFLAG_IDLE:
|
|
dwInvokeFlag |= SYNCMGRINVOKE_MINIMIZED | SYNCMGRINVOKE_STARTSYNC;
|
|
break;
|
|
case SYNCMGRFLAG_PENDINGDISCONNECT:
|
|
case SYNCMGRFLAG_CONNECT:
|
|
if (!dwPromptMeFirst)
|
|
{
|
|
dwInvokeFlag |= SYNCMGRINVOKE_STARTSYNC;
|
|
}
|
|
break;
|
|
default:
|
|
AssertSz(0,"Unknown SyncEvent");
|
|
break;
|
|
}
|
|
|
|
// perform the Update
|
|
hr = PrivUpdateAll(dwInvokeFlag,dwSyncFlags,0,NULL,
|
|
cbNumWorkerConnections,
|
|
ppWorkerConnectionNames,NULL,FALSE,hRasPendingEvent,
|
|
ulIdleRetryMinutes,
|
|
ulDelayIdleShutDownTime,fRetryEnabled);
|
|
}
|
|
|
|
if (ppWorkerConnectionNames)
|
|
{
|
|
FREE(ppWorkerConnectionNames);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// default Unknown implementation
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::CPrivUnknown::QueryInterface, public
|
|
//
|
|
// Synopsis: Standard QueryInterface
|
|
//
|
|
// Arguments: [iid] - Interface ID
|
|
// [ppvObj] - Object return
|
|
//
|
|
// Returns: Appropriate status code
|
|
//
|
|
// Modifies: [ppvObj]
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivUnknown::QueryInterface(REFIID riid, LPVOID FAR *ppv)
|
|
{
|
|
*ppv = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
{
|
|
*ppv = this;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IPrivSyncMgrSynchronizeInvoke))
|
|
{
|
|
*ppv = (IPrivSyncMgrSynchronizeInvoke *) m_pSynchInvoke;
|
|
}
|
|
#ifdef _SENS
|
|
|
|
|
|
else if (IsEqualIID(riid, IID_ISensNetwork))
|
|
{
|
|
*ppv = (ISensNetwork *) &(m_pSynchInvoke->m_PrivSensNetwork);
|
|
}
|
|
|
|
else if (IsEqualIID(riid, IID_ISensLogon))
|
|
{
|
|
*ppv = (ISensLogon *) &(m_pSynchInvoke->m_PrivSensLogon);
|
|
}
|
|
|
|
// in final this shouldn't return anything until LCE change, change
|
|
// depending on which interface we want to test.
|
|
|
|
else if (IsEqualIID(riid, IID_IDispatch))
|
|
{
|
|
*ppv = &(m_pSynchInvoke->m_PrivSensLogon);
|
|
}
|
|
#endif // _SENS
|
|
|
|
if (*ppv)
|
|
{
|
|
m_pSynchInvoke->m_pUnkOuter->AddRef();
|
|
return NOERROR;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::CPrivUnknown::AddRef, public
|
|
//
|
|
// Synopsis: Add reference
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSynchronizeInvoke::CPrivUnknown::AddRef()
|
|
{
|
|
ULONG cRefs;
|
|
|
|
cRefs = InterlockedIncrement((LONG *)& m_pSynchInvoke->m_cRef);
|
|
return cRefs;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSychrononizeInvoke::CPrivUnknown::Release, public
|
|
//
|
|
// Synopsis: Release reference
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSynchronizeInvoke::CPrivUnknown::Release()
|
|
{
|
|
ULONG cRefs;
|
|
|
|
cRefs = InterlockedDecrement( (LONG *) &m_pSynchInvoke->m_cRef);
|
|
|
|
if (0 == cRefs)
|
|
{
|
|
delete m_pSynchInvoke;
|
|
}
|
|
|
|
return cRefs;
|
|
}
|
|
|
|
|
|
|
|
#ifdef _SENS
|
|
|
|
// SENS Network connect Interfaces
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensNetwork::QueryInterface(REFIID riid, LPVOID FAR *ppv)
|
|
{
|
|
return m_pSynchInvoke->m_pUnkOuter->QueryInterface(riid,ppv);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::AddRef, public
|
|
//
|
|
// Synopsis: Add reference
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSynchronizeInvoke::CPrivSensNetwork::AddRef()
|
|
{
|
|
return m_pSynchInvoke->m_pUnkOuter->AddRef();
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSychrononizeInvoke::Release, public
|
|
//
|
|
// Synopsis: Release reference
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSynchronizeInvoke::CPrivSensNetwork::Release()
|
|
{
|
|
return m_pSynchInvoke->m_pUnkOuter->Release();
|
|
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensNetwork::GetTypeInfoCount(
|
|
UINT *pCountITypeInfo
|
|
)
|
|
{
|
|
*pCountITypeInfo = 1;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensNetwork::GetTypeInfo(
|
|
UINT iTypeInfo,
|
|
LCID lcid,
|
|
ITypeInfo **ppITypeInfo
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (iTypeInfo != 0)
|
|
{
|
|
return DISP_E_BADINDEX;
|
|
}
|
|
|
|
if (NOERROR == (hr = m_pSynchInvoke->GetNetworkTypeInfo()))
|
|
{
|
|
// if got a typelib addref it and hand it out.
|
|
m_pSynchInvoke->m_pITypeInfoNetwork->AddRef();
|
|
*ppITypeInfo = m_pSynchInvoke->m_pITypeInfoNetwork;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensNetwork::GetIDsOfNames(
|
|
REFIID riid,
|
|
LPOLESTR *arrNames,
|
|
UINT cNames,
|
|
LCID lcid,
|
|
DISPID *arrDispIDs)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NOERROR == (hr = m_pSynchInvoke->GetNetworkTypeInfo()))
|
|
{
|
|
hr = m_pSynchInvoke->m_pITypeInfoNetwork->GetIDsOfNames(
|
|
arrNames,
|
|
cNames,
|
|
arrDispIDs
|
|
);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensNetwork::Invoke(
|
|
DISPID dispID,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
WORD wFlags,
|
|
DISPPARAMS *pDispParams,
|
|
VARIANT *pvarResult,
|
|
EXCEPINFO *pExecpInfo,
|
|
UINT *puArgErr
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NOERROR == (hr = m_pSynchInvoke->GetNetworkTypeInfo()))
|
|
{
|
|
hr = m_pSynchInvoke->m_pITypeInfoNetwork->Invoke(
|
|
(IDispatch*) this,
|
|
dispID,
|
|
wFlags,
|
|
pDispParams,
|
|
pvarResult,
|
|
pExecpInfo,
|
|
puArgErr);
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensNetwork::ConnectionMade(
|
|
BSTR bstrConnection,
|
|
ULONG ulType,
|
|
LPSENS_QOCINFO pQOCInfo
|
|
)
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
TCHAR pszConnectionName[RAS_MaxEntryName + 1];
|
|
TCHAR *pConnectionNameArray;
|
|
#ifndef _UNICODE
|
|
BOOL fUsedDefaultChar;
|
|
#endif // _UNICODE
|
|
|
|
if (g_InAutoSync) // Review logic, for now if in logon just return.
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
RegSetUserDefaults(); // Make Sure the UserDefaults are up to date
|
|
|
|
// if Lan connection use our hardcoded value, else use the
|
|
// connection name given to use.
|
|
|
|
if (ulType & NETWORK_ALIVE_LAN)
|
|
{
|
|
LoadString(g_hInst, IDS_LAN_CONNECTION, pszConnectionName,ARRAY_SIZE(pszConnectionName));
|
|
}
|
|
else
|
|
{
|
|
|
|
#ifdef _UNICODE
|
|
lstrcpy(pszConnectionName , bstrConnection);
|
|
#else
|
|
WideCharToMultiByte(CP_ACP ,0,bstrConnection,-1,
|
|
pszConnectionName,ARRAY_SIZE(pszConnectionName),NULL,&fUsedDefaultChar);
|
|
|
|
#endif // _UNICODE
|
|
|
|
}
|
|
pConnectionNameArray = pszConnectionName;
|
|
|
|
if (pszConnectionName)
|
|
{
|
|
hr = m_pSynchInvoke->PrivAutoSyncOnConnection(SYNCMGRFLAG_CONNECT | SYNCMGRFLAG_MAYBOTHERUSER,1,
|
|
&pConnectionNameArray,
|
|
NULL);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensNetwork::ConnectionMadeNoQOCInfo(
|
|
BSTR bstrConnection,
|
|
ULONG ulType
|
|
)
|
|
{
|
|
TCHAR *pszConnectionName;
|
|
#ifndef _UNICODE
|
|
TCHAR szwConnection[RAS_MaxEntryName + 1];
|
|
BOOL fUsedDefaultChar;
|
|
#endif // _UNICODE
|
|
|
|
AssertSz(0,"ConnectionMadeNoQOCInfo called");
|
|
|
|
#ifdef _UNICODE
|
|
pszConnectionName = bstrConnection;
|
|
#else
|
|
WideCharToMultiByte(CP_ACP ,0,bstrConnection,-1,
|
|
szwConnection,ARRAY_SIZE(szwConnection),NULL,&fUsedDefaultChar);
|
|
|
|
pszConnectionName = szwConnection;
|
|
#endif // _UNICODE
|
|
|
|
|
|
|
|
// m_pSynchInvoke->PrivAutoSyncOnConnection(SYNCMGRFLAG_CONNECT,pszConnectionName,
|
|
// NULL);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensNetwork::ConnectionLost(
|
|
BSTR bstrConnection,
|
|
ULONG ulType
|
|
)
|
|
{
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensNetwork::BeforeDisconnect(
|
|
BSTR bstrConnection,
|
|
ULONG ulType
|
|
)
|
|
{
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensNetwork::DestinationReachable(
|
|
BSTR bstrDestination,
|
|
BSTR bstrConnection,
|
|
ULONG ulType,
|
|
LPSENS_QOCINFO pQOCInfo
|
|
)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensNetwork::DestinationReachableNoQOCInfo(
|
|
BSTR bstrDestination,
|
|
BSTR bstrConnection,
|
|
ULONG ulType
|
|
)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
// ISensLogon/Logoff Events
|
|
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensLogon::QueryInterface(REFIID riid, LPVOID FAR *ppv)
|
|
{
|
|
return m_pSynchInvoke->m_pUnkOuter->QueryInterface(riid,ppv);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::AddRef, public
|
|
//
|
|
// Synopsis: Add reference
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSynchronizeInvoke::CPrivSensLogon::AddRef()
|
|
{
|
|
return m_pSynchInvoke->m_pUnkOuter->AddRef();
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSychrononizeInvoke::Release, public
|
|
//
|
|
// Synopsis: Release reference
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP_(ULONG) CSynchronizeInvoke::CPrivSensLogon::Release()
|
|
{
|
|
return m_pSynchInvoke->m_pUnkOuter->Release();
|
|
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensLogon::GetTypeInfoCount(
|
|
UINT *pCountITypeInfo
|
|
)
|
|
{
|
|
*pCountITypeInfo = 1;
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensLogon::GetTypeInfo(
|
|
UINT iTypeInfo,
|
|
LCID lcid,
|
|
ITypeInfo **ppITypeInfo
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (iTypeInfo != 0)
|
|
{
|
|
return DISP_E_BADINDEX;
|
|
}
|
|
|
|
if (NOERROR == (hr = m_pSynchInvoke->GetLogonTypeInfo()))
|
|
{
|
|
// if got a typelib addref it and hand it out.
|
|
m_pSynchInvoke->m_pITypeInfoLogon->AddRef();
|
|
*ppITypeInfo = m_pSynchInvoke->m_pITypeInfoLogon;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensLogon::GetIDsOfNames(
|
|
REFIID riid,
|
|
LPOLESTR *arrNames,
|
|
UINT cNames,
|
|
LCID lcid,
|
|
DISPID *arrDispIDs)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NOERROR == (hr = m_pSynchInvoke->GetLogonTypeInfo()))
|
|
{
|
|
hr = m_pSynchInvoke->m_pITypeInfoLogon->GetIDsOfNames(
|
|
arrNames,
|
|
cNames,
|
|
arrDispIDs
|
|
);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CSynchronizeInvoke::CPrivSensLogon::Invoke(
|
|
DISPID dispID,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
WORD wFlags,
|
|
DISPPARAMS *pDispParams,
|
|
VARIANT *pvarResult,
|
|
EXCEPINFO *pExecpInfo,
|
|
UINT *puArgErr
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (NOERROR == (hr = m_pSynchInvoke->GetLogonTypeInfo()))
|
|
{
|
|
hr = m_pSynchInvoke->m_pITypeInfoLogon->Invoke(
|
|
(IDispatch*) this,
|
|
dispID,
|
|
wFlags,
|
|
pDispParams,
|
|
pvarResult,
|
|
pExecpInfo,
|
|
puArgErr);
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensLogon::Logon(BSTR bstrUserName)
|
|
{
|
|
|
|
m_pSynchInvoke->Logon();
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensLogon::Logoff(BSTR bstrUserName)
|
|
{
|
|
|
|
m_pSynchInvoke->Logoff();
|
|
|
|
return NOERROR;
|
|
|
|
}
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensLogon::Startup(BSTR bstrUserName)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensLogon::StartShell(BSTR bstrUserName)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensLogon::Shutdown(BSTR bstrUserName)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensLogon::DisplayLock(BSTR bstrUserName)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensLogon::DisplayUnlock(BSTR bstrUserName)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensLogon::StartScreenSaver(BSTR bstrUserName)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::CPrivSensLogon::StopScreenSaver(BSTR bstrUserName)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::GetLogonTypeInfo, private
|
|
//
|
|
// Synopsis: Loads the TypeInfo object for the Sens
|
|
// Logon Information.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: NOERROR if successfully loaded the TypeInfo.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::GetLogonTypeInfo()
|
|
{
|
|
HRESULT hr;
|
|
ITypeLib *pITypeLib;
|
|
|
|
if (m_pITypeInfoLogon)
|
|
return NOERROR;
|
|
|
|
hr = LoadRegTypeLib(
|
|
LIBID_SensEvents,
|
|
1 /* MAJOR_VER */ ,
|
|
0 /* MINOR_VER */ ,
|
|
0 /* DEFAULT_LCID */,
|
|
&pITypeLib
|
|
);
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
|
|
hr = pITypeLib->GetTypeInfoOfGuid(
|
|
IID_ISensLogon,
|
|
&m_pITypeInfoLogon
|
|
);
|
|
|
|
pITypeLib->Release();
|
|
}
|
|
|
|
|
|
if (NOERROR != hr)
|
|
{
|
|
m_pITypeInfoLogon = NULL; // don't rely on call not to leave this alone.
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CSynchronizeInvoke::GetNetworkTypeInfo, private
|
|
//
|
|
// Synopsis: Loads the TypeInfo object for the Sens
|
|
// Network Information.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: NOERROR if successfully loaded the TypeInfo.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//+---------------------------------------------------------------------------
|
|
|
|
STDMETHODIMP CSynchronizeInvoke::GetNetworkTypeInfo()
|
|
{
|
|
HRESULT hr;
|
|
ITypeLib *pITypeLib;
|
|
|
|
if (m_pITypeInfoNetwork)
|
|
return NOERROR;
|
|
|
|
|
|
hr = LoadRegTypeLib(
|
|
LIBID_SensEvents,
|
|
1 /* MAJOR_VER */ ,
|
|
0 /* MINOR_VER */ ,
|
|
0 /* DEFAULT_LCID */,
|
|
&pITypeLib
|
|
);
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
|
|
hr = pITypeLib->GetTypeInfoOfGuid(
|
|
IID_ISensNetwork,
|
|
&m_pITypeInfoNetwork
|
|
);
|
|
|
|
pITypeLib->Release();
|
|
}
|
|
|
|
if (NOERROR != hr)
|
|
{
|
|
m_pITypeInfoNetwork = NULL; // don't rely on call not to leave this alone.
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif // _SENS
|