2273 lines
60 KiB
C++
2273 lines
60 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1997.
|
|
//
|
|
// File: Objmgr.cpp
|
|
//
|
|
// Contents: Keeps track of dialog objects and
|
|
// application lifetime
|
|
//
|
|
// Classes:
|
|
//
|
|
// Notes:
|
|
//
|
|
// History: 05-Nov-97 rogerg Created.
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
#include "precomp.h"
|
|
|
|
STDAPI DisplayOptions(HWND hwndOwner); // OneStop.dll Export
|
|
|
|
CSingletonNetApi gSingleNetApiObj; // Global singleton NetApi object
|
|
|
|
CRITICAL_SECTION g_LockCountCriticalSection; // Critical Section fo Object Mgr
|
|
OBJECTMGRDATA g_ObjectMgrData; // Global Object Mgr Data
|
|
extern OSVERSIONINFOA g_OSVersionInfo; // osVersionInfo, setup by WinMain.
|
|
|
|
#ifdef _DEBUG
|
|
DWORD g_ThreadCount = 0;
|
|
#endif // _DEBUG
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CreateDlgThread, public
|
|
//
|
|
// Synopsis: Called to Create a new Dlg Thread
|
|
//
|
|
// Arguments: [dlgType] - Type of Dialog to create
|
|
// [nCmdShow] - How to display the Dialog.
|
|
// [ppDlg] - on success returns a pointer to the new dialog
|
|
// [pdwThreadID] - on Success Id of thread that was created.
|
|
// [phThread] - Handle to newly created thread.
|
|
//
|
|
// Returns: Appropriate return codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CreateDlgThread(DLGTYPE dlgType,REFCLSID rclsid,int nCmdShow,CBaseDlg **ppDlg,
|
|
DWORD *pdwThreadID,HANDLE *phThread)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
HANDLE hNewThread = NULL;
|
|
DlgThreadArgs ThreadArgs;
|
|
|
|
*phThread = NULL;
|
|
*ppDlg = NULL;
|
|
|
|
ThreadArgs.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
|
|
|
if (ThreadArgs.hEvent)
|
|
{
|
|
ThreadArgs.dlgType = dlgType;
|
|
ThreadArgs.clsid = rclsid;
|
|
ThreadArgs.pDlg = NULL;
|
|
ThreadArgs.nCmdShow = nCmdShow;
|
|
ThreadArgs.hr = E_UNEXPECTED;
|
|
|
|
hNewThread = CreateThread(NULL,0,DialogThread,&ThreadArgs,0,pdwThreadID);
|
|
|
|
if (hNewThread)
|
|
{
|
|
WaitForSingleObject(ThreadArgs.hEvent,INFINITE);
|
|
if (NOERROR == ThreadArgs.hr)
|
|
{
|
|
*phThread = hNewThread;
|
|
*ppDlg = ThreadArgs.pDlg;
|
|
hr = NOERROR;
|
|
}
|
|
else
|
|
{
|
|
CloseHandle(hNewThread);
|
|
hr = ThreadArgs.hr;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = GetLastError();
|
|
}
|
|
|
|
CloseHandle(ThreadArgs.hEvent);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: DialogThread, public
|
|
//
|
|
// Synopsis: ThreadProc for a new Dlg Thread
|
|
// !!!Warning - Must always ensure event in ThreadArg gets set.
|
|
//
|
|
// Arguments: [lpArg] - Pointer to DialogThreadArgs
|
|
//
|
|
// Returns: Appropriate return codes. Sets hr value in
|
|
// ThreadArgs before setting event object
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD WINAPI DialogThread( LPVOID lpArg )
|
|
{
|
|
MSG msg;
|
|
HRESULT hr;
|
|
HRESULT hrCoInitialize;
|
|
DWORD cRefs;
|
|
HWND hwndDlg;
|
|
DlgThreadArgs *pThreadArgs = (DlgThreadArgs *) lpArg;
|
|
|
|
pThreadArgs->hr = NOERROR;
|
|
|
|
hrCoInitialize = CoInitialize(NULL);
|
|
|
|
switch (pThreadArgs->dlgType)
|
|
{
|
|
case DLGTYPE_CHOICE:
|
|
pThreadArgs->pDlg = new CChoiceDlg(pThreadArgs->clsid);
|
|
break;
|
|
case DLGTYPE_PROGRESS:
|
|
pThreadArgs->pDlg = new CProgressDlg(pThreadArgs->clsid);
|
|
break;
|
|
default:
|
|
pThreadArgs->pDlg = NULL;
|
|
AssertSz(0,"Unknown Dialog Type");
|
|
break;
|
|
}
|
|
|
|
// need to do a PeekMessage and then set an event to make sure
|
|
// a message loop is created before the first PostMessage is sent.
|
|
|
|
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
|
|
|
|
// initialize the dialog box before returning to main thread.
|
|
if (NULL == pThreadArgs->pDlg ||
|
|
FALSE == pThreadArgs->pDlg->Initialize(GetCurrentThreadId(),pThreadArgs->nCmdShow)
|
|
|| (FAILED(hrCoInitialize)) )
|
|
{
|
|
|
|
if (pThreadArgs->pDlg)
|
|
pThreadArgs->pDlg->PrivReleaseDlg(RELEASEDLGCMDID_DESTROY);
|
|
|
|
pThreadArgs->hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
hwndDlg = pThreadArgs->pDlg->GetHwnd();
|
|
}
|
|
|
|
hr = pThreadArgs->hr;
|
|
#ifdef _DEBUG
|
|
++g_ThreadCount;
|
|
#endif // _DEBUG
|
|
|
|
cRefs = AddRefOneStopLifetime(FALSE /* !External */); // make sure we stay alive for lifetime of thread.
|
|
Assert(cRefs > 1); // someone else should also have a lock during dialog creation.
|
|
|
|
// let the caller know the thread is done initializing.
|
|
if (pThreadArgs->hEvent)
|
|
SetEvent(pThreadArgs->hEvent);
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
// sit in loop receiving messages.
|
|
while (GetMessage(&msg, NULL, 0, 0))
|
|
{
|
|
if (!IsDialogMessage(hwndDlg,&msg))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hrCoInitialize))
|
|
CoUninitialize();
|
|
|
|
|
|
#ifdef _DEBUG
|
|
--g_ThreadCount;
|
|
#endif // _DEBUG
|
|
|
|
ReleaseOneStopLifetime(FALSE /* !External */);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FindDialog, private
|
|
//
|
|
// Synopsis: Looks to see if there is an existing dialog
|
|
// matching the type and clsid. If not and fCreate is true a
|
|
// new dialog will be made. If fCreate is false
|
|
// and no dialog is found S_FALSE will be returned.
|
|
//
|
|
// Arguments: [rclcisd] - clsid of choice dialog
|
|
// [fCreate] - If true and no choice dialog found a new one will
|
|
// be created.
|
|
// [nCmdShow] - How to Create the dialog
|
|
// [pChoiceDlg] - On Success is a pointer to the new Choice Dialog.
|
|
//
|
|
// Returns: Appropriate return codes.
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Feb-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI FindDialog(DLGTYPE dlgType,REFCLSID rclsid,BOOL fCreate,int nCmdShow,CBaseDlg **pDlg)
|
|
{
|
|
DLGLISTITEM *pDlgListItem;
|
|
HWND hwnd = NULL;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
*pDlg = NULL;
|
|
|
|
cCritSect.Enter();
|
|
|
|
pDlgListItem = g_ObjectMgrData.DlgList;
|
|
|
|
// look for existing.
|
|
while (pDlgListItem)
|
|
{
|
|
if (rclsid == pDlgListItem->clsid
|
|
&& dlgType == pDlgListItem->dlgType)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
}
|
|
|
|
if (pDlgListItem)
|
|
{
|
|
Assert((pDlgListItem->cRefs > 0) || (pDlgListItem->cLocks > 0) );
|
|
|
|
++pDlgListItem->cRefs;
|
|
*pDlg = pDlgListItem->pDlg;
|
|
}
|
|
|
|
|
|
// didn't find a match if fCreate is set then try to create one.
|
|
if (TRUE == fCreate && NULL == *pDlg)
|
|
{
|
|
CBaseDlg *pNewDlg;
|
|
DLGLISTITEM *pNewDlgListItem;
|
|
DWORD dwThreadID;
|
|
pNewDlgListItem = (DLGLISTITEM *) ALLOC(sizeof(DLGLISTITEM));
|
|
|
|
|
|
if (NULL != pNewDlgListItem)
|
|
{
|
|
HRESULT hr;
|
|
HANDLE hThread;
|
|
|
|
cCritSect.Leave();
|
|
hr = CreateDlgThread(dlgType,rclsid,nCmdShow,&pNewDlg,&dwThreadID,&hThread);
|
|
cCritSect.Enter();
|
|
|
|
if (NOERROR == hr )
|
|
{
|
|
// its possible that while we had the lock count released a request
|
|
// for the same dialog came through so rescan to make sure we
|
|
// don't have a match
|
|
|
|
pDlgListItem = g_ObjectMgrData.DlgList;
|
|
|
|
// look for existing.
|
|
while (pDlgListItem)
|
|
{
|
|
if (rclsid == pDlgListItem->clsid
|
|
&& dlgType == pDlgListItem->dlgType)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
}
|
|
|
|
// if found a match then incrmement its cRef,
|
|
// delete the new one we just created,
|
|
// and return a pointer to the one in the list
|
|
// else add new dialog to the list.
|
|
if (pDlgListItem)
|
|
{
|
|
// delete our newly create dialog and structure.
|
|
CloseHandle(hThread);
|
|
FREE(pNewDlgListItem);
|
|
pNewDlg->ReleaseDlg(RELEASEDLGCMDID_DESTROY);
|
|
|
|
// increment found dialog and set the out param
|
|
Assert(pDlgListItem->cRefs > 0);
|
|
++pDlgListItem->cRefs;
|
|
*pDlg = pDlgListItem->pDlg;
|
|
}
|
|
else
|
|
{
|
|
// iniitalize the structure.
|
|
pNewDlgListItem->dlgType = dlgType;
|
|
pNewDlgListItem->cRefs = 1;
|
|
pNewDlgListItem->cLocks = 0;
|
|
pNewDlgListItem->clsid = rclsid;
|
|
pNewDlgListItem->pDlg = pNewDlg;
|
|
pNewDlgListItem->dwThreadID = dwThreadID;
|
|
pNewDlgListItem->hThread = hThread;
|
|
pNewDlgListItem->fHasReleaseDlgCmdId = FALSE;
|
|
pNewDlgListItem->wCommandID = RELEASEDLGCMDID_DEFAULT;
|
|
|
|
*pDlg = pNewDlg;
|
|
|
|
// now add to the beginning of the list.
|
|
pNewDlgListItem->pDlgNextListItem = g_ObjectMgrData.DlgList;
|
|
g_ObjectMgrData.DlgList = pNewDlgListItem;
|
|
|
|
++g_ObjectMgrData.LockCountInternal; // increment the LockCount
|
|
}
|
|
}
|
|
else
|
|
{
|
|
FREE(pNewDlgListItem);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// if found an existing dialog, update the z-Order
|
|
if (*pDlg)
|
|
{
|
|
hwnd = (*pDlg)->GetHwnd();
|
|
}
|
|
|
|
cCritSect.Leave();
|
|
|
|
if (hwnd)
|
|
{
|
|
BASEDLG_SHOWWINDOW(hwnd,nCmdShow);
|
|
}
|
|
|
|
return *pDlg ? S_OK : S_FALSE;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddRefDialog, private
|
|
//
|
|
// Synopsis: Looks to see if there is an existing dialog
|
|
// matching the type and clsid and puts an addref on it.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate return codes.
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Feb-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) AddRefDialog(DLGTYPE dlgType,REFCLSID rclsid,CBaseDlg *pDlg)
|
|
{
|
|
DLGLISTITEM dlgListDummy;
|
|
DLGLISTITEM *pDlgListItem = &dlgListDummy;
|
|
ULONG cRefs = 1;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
cCritSect.Enter();
|
|
|
|
pDlgListItem = g_ObjectMgrData.DlgList;
|
|
|
|
// look for existing.
|
|
while (pDlgListItem)
|
|
{
|
|
if (rclsid == pDlgListItem->clsid
|
|
&& dlgType == pDlgListItem->dlgType)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
}
|
|
|
|
if (pDlgListItem)
|
|
{
|
|
// since only allow one choice at a time Dlg should always match.
|
|
Assert(pDlgListItem->pDlg == pDlg);
|
|
|
|
cRefs = ++pDlgListItem->cRefs;
|
|
}
|
|
else
|
|
{
|
|
cCritSect.Leave();
|
|
AssertSz(0,"Addref Called on invalid DLG");
|
|
cCritSect.Enter();
|
|
}
|
|
|
|
|
|
cCritSect.Leave();
|
|
return cRefs;
|
|
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReleaseDialog, private
|
|
//
|
|
// Synopsis: Looks to see if there is an existing dialog
|
|
// matching the type and clsid and calls release on it..
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate return codes.
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Feb-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) ReleaseDialog(DLGTYPE dlgType,REFCLSID rclsid,CBaseDlg *pDlg,BOOL fForce)
|
|
{
|
|
DLGLISTITEM dlgListDummy;
|
|
DLGLISTITEM *pDlgListItem = &dlgListDummy;
|
|
ULONG cRefs = 0;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
|
|
cCritSect.Enter();
|
|
|
|
pDlgListItem->pDlgNextListItem = g_ObjectMgrData.DlgList;
|
|
|
|
// look for existing.
|
|
while (pDlgListItem->pDlgNextListItem)
|
|
{
|
|
if (dlgType == pDlgListItem->pDlgNextListItem->dlgType
|
|
&& rclsid == pDlgListItem->pDlgNextListItem->clsid)
|
|
{
|
|
DLGLISTITEM *pDlgListMatch;
|
|
DWORD cRefs;
|
|
|
|
pDlgListMatch = pDlgListItem->pDlgNextListItem;
|
|
|
|
Assert(pDlgListMatch->pDlg == pDlg);
|
|
|
|
cRefs = --pDlgListMatch->cRefs;
|
|
Assert(0 <= ((LONG) cRefs));
|
|
|
|
// 2/23/98 rogerg changed cLocks to go to zero if
|
|
// flocks is set in case the cancel (which is the only button to set force)
|
|
// release comes in before a an object that just needs to keep the dialog alive.
|
|
|
|
if (fForce)
|
|
pDlgListMatch->cLocks = 0;
|
|
|
|
if (0 >= cRefs && (0 == pDlgListMatch->cLocks || fForce) )
|
|
{
|
|
HANDLE hThread;
|
|
|
|
// remove the item from the list.
|
|
pDlgListItem->pDlgNextListItem = pDlgListMatch->pDlgNextListItem;
|
|
g_ObjectMgrData.DlgList = dlgListDummy.pDlgNextListItem;
|
|
|
|
cCritSect.Leave();
|
|
|
|
// we should have always set the callback
|
|
Assert(TRUE == pDlgListMatch->fHasReleaseDlgCmdId);
|
|
|
|
pDlgListMatch->pDlg->ReleaseDlg(pDlgListMatch->wCommandID);
|
|
pDlgListMatch->fHasReleaseDlgCmdId = FALSE;
|
|
hThread = pDlgListMatch->hThread;
|
|
|
|
FREE(pDlgListMatch);
|
|
ReleaseOneStopLifetime(FALSE /* !External */); // release the ServerCount
|
|
|
|
CloseHandle(hThread);
|
|
|
|
}
|
|
else
|
|
{
|
|
cCritSect.Leave();
|
|
}
|
|
|
|
return cRefs;
|
|
}
|
|
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
}
|
|
|
|
// if got here and didn't find let us know
|
|
Assert(0);
|
|
cCritSect.Leave();
|
|
|
|
return cRefs; // we return zero if can't find the item.
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SetReleaseDlgCmdId, private
|
|
//
|
|
// Synopsis: Sets the releaseCmdId for the specified dialog.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate return codes.
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Feb-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI SetReleaseDlgCmdId(DLGTYPE dlgType,REFCLSID rclsid,CBaseDlg *pDlg,WORD wCommandId)
|
|
{
|
|
HRESULT hr;
|
|
DLGLISTITEM *pDlgListItem;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
cCritSect.Enter();
|
|
|
|
pDlgListItem = g_ObjectMgrData.DlgList;
|
|
|
|
// look for existing.
|
|
while (pDlgListItem)
|
|
{
|
|
if (rclsid == pDlgListItem->clsid
|
|
&& dlgType == pDlgListItem->dlgType)
|
|
{
|
|
|
|
// should only ever be one choice dialog in the list
|
|
Assert(pDlg == pDlgListItem->pDlg);
|
|
|
|
// if there is already a cmdId associated don't replace it
|
|
pDlgListItem->fHasReleaseDlgCmdId = TRUE;
|
|
pDlgListItem->wCommandID = wCommandId;
|
|
hr = NOERROR;
|
|
|
|
cCritSect.Leave();
|
|
return hr;
|
|
}
|
|
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
}
|
|
|
|
cCritSect.Leave();
|
|
Assert(0); // object wasn't found for some reason.
|
|
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FindChoiceDialog, public
|
|
//
|
|
// Synopsis: Looks to see if there is an existing choice dialog
|
|
// matching the clsid. If not and fCreate is true a
|
|
// new choice dialog will be made. If fCreate is false
|
|
// and no dialog is found S_FALSE will be returned.
|
|
//
|
|
// Arguments: [rclcisd] - clsid of choice dialog
|
|
// [fCreate] - If true and no choice dialog found a new one will
|
|
// be created.
|
|
// [nCmdShow] - How to Create the dialog
|
|
// [pChoiceDlg] - On Success is a pointer to the new Choice Dialog.
|
|
//
|
|
// Returns: Appropriate return codes.
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI FindChoiceDialog(REFCLSID rclsid,BOOL fCreate,int nCmdShow,CChoiceDlg **pChoiceDlg)
|
|
{
|
|
|
|
return FindDialog(DLGTYPE_CHOICE,rclsid,fCreate,nCmdShow,(CBaseDlg**) pChoiceDlg);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReleaseChoiceDialog, public
|
|
//
|
|
// Synopsis: Releases the ChoiceDialog matching the clsid
|
|
// and Dialog Ptr. If it finds a match, and the
|
|
// refcount decrements to zero the dialog if first
|
|
// removed from the list and then its ReleaseDlg
|
|
// method is called.
|
|
//
|
|
// Arguments: [rclcisd] - clsid of choice dialog
|
|
// [pChoiceDlg] - Ptr to the Choice dialog
|
|
//
|
|
// Returns: Appropriate return codes.
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) ReleaseChoiceDialog(REFCLSID rclsid,CChoiceDlg *pChoiceDlg)
|
|
{
|
|
|
|
return ReleaseDialog(DLGTYPE_CHOICE,rclsid,pChoiceDlg,FALSE);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddRefChoiceDialog, public
|
|
//
|
|
// Synopsis: puts an Addref of the choice dialog
|
|
//
|
|
// Arguments: [rclsid] - Identifies the choice dialog
|
|
// [pChoiceDlg] - Ptr to the choice dialog
|
|
//
|
|
// Returns: New Reference count
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) AddRefChoiceDialog(REFCLSID rclsid,CChoiceDlg *pChoiceDlg)
|
|
{
|
|
return AddRefDialog(DLGTYPE_CHOICE,rclsid,pChoiceDlg);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SetChoiceReleaseDlgCmdId, public
|
|
//
|
|
// Synopsis: Sets the CommandId to be used inthe
|
|
// ReleaseDlg is call when the dialog is destroyed.
|
|
//
|
|
// Arguments: [rclcisd] - clsid of choice dialog
|
|
// [pChoiceDlg] - Ptr to the Choice dialog
|
|
// [wCommandId] - CommandId to pass to ReleaseDlg
|
|
//
|
|
// Returns: Appropriate return codes.
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI SetChoiceReleaseDlgCmdId(REFCLSID rclsid,CChoiceDlg *pChoiceDlg,WORD wCommandId)
|
|
{
|
|
return SetReleaseDlgCmdId(DLGTYPE_CHOICE,rclsid,pChoiceDlg,wCommandId);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FindProgressDialog, public
|
|
//
|
|
// Synopsis: Looks to see if there is an existing progress dialog.
|
|
// If not and fCreate is true a new progress dialog will be made.
|
|
// If fCreate is false and no dialog is found S_FALSE will be returned.
|
|
//
|
|
// Arguments: [fCreate] - If true and no choice dialog found a new one will
|
|
// be created.
|
|
// [nCmdShow] - How to display the dialog
|
|
// [pProgressDlg] - On Success is a pointer to the new Progress Dialog.
|
|
//
|
|
// Returns: Appropriate return codes.
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI FindProgressDialog(REFCLSID rclsid,BOOL fCreate,int nCmdShow,CProgressDlg **pProgressDlg)
|
|
{
|
|
return FindDialog(DLGTYPE_PROGRESS,rclsid,fCreate,nCmdShow,(CBaseDlg **) pProgressDlg);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReleaseProgressDialog, public
|
|
//
|
|
// Synopsis: Releases the Progress dialog matching the Dialog Ptr.
|
|
// If it finds a match, and the
|
|
// refcount decrements to zero the dialog if first
|
|
// removed from the list and then its ReleaseDlg
|
|
// method is called.
|
|
//
|
|
// Arguments: [fForce] - if refs gos to zero releases the dialog
|
|
// even if there is a lock on it.
|
|
// [pProgressDlg] - Ptr to the Progress dialog
|
|
//
|
|
// Returns: New Reference count.
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) ReleaseProgressDialog(REFCLSID rclsid,CProgressDlg *pProgressDlg,BOOL fForce)
|
|
{
|
|
return ReleaseDialog(DLGTYPE_PROGRESS,rclsid,pProgressDlg,fForce);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddRefProgressDialog, public
|
|
//
|
|
// Synopsis: puts an Addref of the progress dialog
|
|
//
|
|
// Arguments: [fForce] - if refs gos to zero releases the dialog
|
|
// even if there is a lock on it.
|
|
// [pProgressDlg] - Ptr to the Progress dialog
|
|
//
|
|
// Returns: New Reference count
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) AddRefProgressDialog(REFCLSID clsid,CProgressDlg *pProgressDlg)
|
|
{
|
|
return AddRefDialog(DLGTYPE_PROGRESS,clsid,pProgressDlg);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SetProgressReleaseDlgCmdId, public
|
|
//
|
|
// Synopsis: Sets the Callback for the Progress dialog that
|
|
// is called when the Progress dialog has been removed
|
|
// from the list.
|
|
//
|
|
// Arguments: [pProgressDlg] - Ptr to the Progress dialog
|
|
// [wCommandId] - CommandId to pass to ReleaseDlg
|
|
//
|
|
// Returns: Appropriate Error codes
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI SetProgressReleaseDlgCmdId(REFCLSID clsid,CProgressDlg *pProgressDlg,WORD wCommandId)
|
|
{
|
|
return SetReleaseDlgCmdId(DLGTYPE_PROGRESS,clsid,pProgressDlg,wCommandId);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: LockProgressDialog, public
|
|
//
|
|
// Synopsis: Add/Removes Lock on the Progress Dialog.
|
|
// When there is a lock on the Progress Dialog
|
|
// it won't go away when the reference count
|
|
// goes to zero.
|
|
//
|
|
// !!Dialog will not go away if lock count
|
|
// goes to zero even if cRefs are currently zero
|
|
//
|
|
//
|
|
// Arguments: [pProgressDlg] - Ptr to the Progress dialog
|
|
// [fLock] - BOOL whether to lock/unlocK
|
|
//
|
|
// Returns: Appropriate Error codes
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
// History 09-Dec-98 rogerg Change so lock was a bool instead of refcount
|
|
// to have same behavior as release with force flag
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI LockProgressDialog(REFCLSID clsid,CProgressDlg *pProgressDlg,BOOL fLock)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
DLGLISTITEM *pDlgListItem;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
|
|
cCritSect.Enter();
|
|
|
|
pDlgListItem = g_ObjectMgrData.DlgList;
|
|
|
|
// look for existing.
|
|
while (pDlgListItem)
|
|
{
|
|
if (DLGTYPE_PROGRESS == pDlgListItem->dlgType
|
|
&& clsid == pDlgListItem->clsid)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
}
|
|
|
|
if (pDlgListItem)
|
|
{
|
|
if (fLock)
|
|
{
|
|
pDlgListItem->cLocks = 1;
|
|
}
|
|
else
|
|
{
|
|
pDlgListItem->cLocks = 0;
|
|
}
|
|
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
AssertSz(0,"Dialog Not found in Lock");
|
|
}
|
|
|
|
cCritSect.Leave();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ShowOptionsDialog, public
|
|
//
|
|
// Synopsis: Displays the options dialog. If one is already displayed
|
|
// it just brings it to the foreground.
|
|
//
|
|
// Arguments: [hwndParent] - Use as parent if dialog doesn't already exist
|
|
//
|
|
// Returns: Appropriate Error codes
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 24-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI ShowOptionsDialog(HWND hwndParent)
|
|
{
|
|
DlgSettingsArgs ThreadArgs;
|
|
HRESULT hr = E_FAIL;
|
|
HANDLE hNewThread = NULL;
|
|
DWORD dwThreadId;
|
|
|
|
|
|
ThreadArgs.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
|
|
|
|
if (ThreadArgs.hEvent)
|
|
{
|
|
ThreadArgs.hwndParent = hwndParent;
|
|
ThreadArgs.dwParentThreadId = GetCurrentThreadId();
|
|
|
|
hr = NOERROR;
|
|
|
|
hNewThread = CreateThread(NULL,0,SettingsThread,&ThreadArgs,0,&dwThreadId);
|
|
|
|
if (hNewThread)
|
|
{
|
|
WaitForSingleObject(ThreadArgs.hEvent,INFINITE);
|
|
CloseHandle(hNewThread); // we'll let the thread take care of itself
|
|
}
|
|
|
|
CloseHandle(ThreadArgs.hEvent);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SettingsThread, private
|
|
//
|
|
// Synopsis: Worker thread for displaying the settings dialog.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns:
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 24-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
DWORD WINAPI SettingsThread( LPVOID lpArg )
|
|
{
|
|
DlgSettingsArgs *pThreadArgs = (DlgSettingsArgs *) lpArg;
|
|
HWND hwndParent;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
hwndParent = pThreadArgs->hwndParent;
|
|
|
|
// see if we are already in a DisplayOptions Dialog
|
|
// and if so just return,
|
|
|
|
AddRefOneStopLifetime(FALSE /* !External */);
|
|
|
|
// Increment settings ref count
|
|
cCritSect.Enter();
|
|
++g_ObjectMgrData.dwSettingsLockCount;
|
|
cCritSect.Leave();
|
|
|
|
// attach the thread input with the creating thread so focus works correctly.
|
|
AttachThreadInput(GetCurrentThreadId(),pThreadArgs->dwParentThreadId,TRUE);
|
|
|
|
// let the caller know the thread is done initializing.
|
|
if (pThreadArgs->hEvent)
|
|
SetEvent(pThreadArgs->hEvent);
|
|
|
|
DisplayOptions(hwndParent); // exported in the OneStop Dll.
|
|
|
|
// decrement the settings lock count
|
|
cCritSect.Enter();
|
|
--g_ObjectMgrData.dwSettingsLockCount;
|
|
cCritSect.Leave();
|
|
|
|
ReleaseOneStopLifetime(FALSE /* !External */);
|
|
|
|
return 0;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegisterOneStopCLSIDs, private
|
|
//
|
|
// Synopsis: Registers the Clsids associated with the OneStop app
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate Error codes
|
|
//
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI RegisterOneStopCLSIDs()
|
|
{
|
|
LPCLASSFACTORY pClassFact;
|
|
HRESULT hr = E_OUTOFMEMORY;
|
|
|
|
pClassFact = (LPCLASSFACTORY) new CClassFactory();
|
|
|
|
if (pClassFact)
|
|
{
|
|
hr = CoRegisterClassObject(CLSID_SyncMgrp,pClassFact,CLSCTX_LOCAL_SERVER,
|
|
REGCLS_MULTIPLEUSE,&g_ObjectMgrData.dwRegClassFactCookie);
|
|
|
|
if (NOERROR != hr)
|
|
{
|
|
// on longon the rpc server may not yet be available and on
|
|
// logoff we get the wrong server identity. Don't assert on these
|
|
// since we know about the cases.
|
|
if (HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) != hr
|
|
&& CO_E_WRONG_SERVER_IDENTITY != hr)
|
|
{
|
|
AssertSz(0,"Class Factory Registration failed");
|
|
}
|
|
|
|
g_ObjectMgrData.dwRegClassFactCookie = 0;
|
|
}
|
|
else
|
|
{
|
|
g_ObjectMgrData.fRegClassFactCookieValid = TRUE;
|
|
}
|
|
|
|
pClassFact->Release(); // Release our reference on the ClassFactory.
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: MakeWinstaDesktopName, public
|
|
//
|
|
// Synopsis: Stole main code from Ole32 remote.cxx to generate
|
|
// a unique eventName based on session and desktop..
|
|
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate Error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 18-Dec-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI MakeWinstaDesktopName(LPCWSTR pszPreceding,LPWSTR *ppszResultString)
|
|
{
|
|
HWINSTA hWinsta;
|
|
HDESK hDesk;
|
|
WCHAR wszWinsta[32];
|
|
WCHAR wszDesktop[32];
|
|
LPWSTR pwszWinsta;
|
|
LPWSTR pwszDesktop;
|
|
LPWSTR _pwszWinstaDesktop; // out param
|
|
DWORD Length;
|
|
BOOL Status;
|
|
HRESULT hr;
|
|
DWORD dwResult;
|
|
DWORD dwPrecedingSize;
|
|
|
|
|
|
if (!ppszResultString)
|
|
{
|
|
Assert(ppszResultString);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*ppszResultString = NULL;;
|
|
|
|
// if not on flavor of NT return an error
|
|
if (VER_PLATFORM_WIN32_NT != g_OSVersionInfo.dwPlatformId)
|
|
{
|
|
AssertSz(0,"MakeWinstaDesktopName called on unsupported platform");
|
|
return E_FAIL;
|
|
}
|
|
|
|
hWinsta = GetProcessWindowStation();
|
|
|
|
if ( ! hWinsta )
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
hDesk = GetThreadDesktop(GetCurrentThreadId());
|
|
|
|
if ( ! hDesk )
|
|
return HRESULT_FROM_WIN32(GetLastError());
|
|
|
|
pwszWinsta = wszWinsta;
|
|
pwszDesktop = wszDesktop;
|
|
|
|
Length = sizeof(wszWinsta);
|
|
|
|
Status = GetUserObjectInformation(
|
|
hWinsta,
|
|
UOI_NAME,
|
|
pwszWinsta,
|
|
Length,
|
|
&Length );
|
|
|
|
if ( ! Status )
|
|
{
|
|
dwResult = GetLastError();
|
|
if ( ERROR_INSUFFICIENT_BUFFER != dwResult)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwResult);
|
|
goto WinstaDesktopExit;
|
|
}
|
|
|
|
pwszWinsta = (LPWSTR) ALLOC( Length );
|
|
if ( ! pwszWinsta )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto WinstaDesktopExit;
|
|
}
|
|
|
|
Status = GetUserObjectInformation(
|
|
hWinsta,
|
|
UOI_NAME,
|
|
pwszWinsta,
|
|
Length,
|
|
&Length );
|
|
|
|
if ( ! Status )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto WinstaDesktopExit;
|
|
}
|
|
}
|
|
|
|
Length = sizeof(wszDesktop);
|
|
|
|
Status = GetUserObjectInformation(
|
|
hDesk,
|
|
UOI_NAME,
|
|
pwszDesktop,
|
|
Length,
|
|
&Length );
|
|
|
|
if ( ! Status )
|
|
{
|
|
dwResult = GetLastError();
|
|
if ( dwResult != ERROR_INSUFFICIENT_BUFFER )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(dwResult);
|
|
goto WinstaDesktopExit;
|
|
}
|
|
|
|
pwszDesktop = (LPWSTR) ALLOC( Length );
|
|
if ( ! pwszDesktop )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto WinstaDesktopExit;
|
|
}
|
|
|
|
Status = GetUserObjectInformation(
|
|
hDesk,
|
|
UOI_NAME,
|
|
pwszDesktop,
|
|
Length,
|
|
&Length );
|
|
|
|
if ( ! Status )
|
|
{
|
|
hr = HRESULT_FROM_WIN32(GetLastError());
|
|
goto WinstaDesktopExit;
|
|
}
|
|
}
|
|
|
|
dwPrecedingSize = pszPreceding ? lstrlen(pszPreceding) + 1 : 0;
|
|
|
|
_pwszWinstaDesktop =
|
|
(WCHAR *) ALLOC( (dwPrecedingSize
|
|
+ lstrlen(pwszWinsta) + 1
|
|
+ lstrlen(pwszDesktop) + 1) * sizeof(WCHAR) );
|
|
|
|
if ( _pwszWinstaDesktop )
|
|
{
|
|
*_pwszWinstaDesktop = NULL;
|
|
|
|
if (pszPreceding)
|
|
{
|
|
lstrcat(_pwszWinstaDesktop,pszPreceding);
|
|
lstrcat( _pwszWinstaDesktop, L"_" );
|
|
}
|
|
|
|
lstrcat(_pwszWinstaDesktop, pwszWinsta );
|
|
lstrcat( _pwszWinstaDesktop, L"_" );
|
|
lstrcat(_pwszWinstaDesktop, pwszDesktop );
|
|
hr = NOERROR;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
WinstaDesktopExit:
|
|
|
|
if ( pwszWinsta != wszWinsta )
|
|
{
|
|
FREE( pwszWinsta );
|
|
}
|
|
|
|
if ( pwszDesktop != wszDesktop )
|
|
{
|
|
FREE( pwszDesktop );
|
|
}
|
|
|
|
if (NOERROR == hr)
|
|
{
|
|
*ppszResultString = _pwszWinstaDesktop;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RegisterOneStopClassFactory, public
|
|
//
|
|
// Synopsis: Handles the ClassFactory registration
|
|
// along with the associated race conditions.
|
|
//
|
|
// if class factory isn't already registered, then go ahead and register now.
|
|
// there is the case the between the time we see if there is a class factory
|
|
// and the CoCreateInstance is called it could go away. If this happens, another
|
|
// instance of Onestop.exe is launched and everything will work properly.
|
|
|
|
// Arguments: [fForce] - When true the ClassFactory is registered even if there
|
|
// is an existing event object.
|
|
//
|
|
// Returns: Appropriate Error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
const WCHAR SZ_CFACTORYEVENTNAME[] = TEXT("{6295DF2D-35EE-11d1-8707-00C04FD93327}CFactEvent");
|
|
|
|
STDAPI RegisterOneStopClassFactory(BOOL fForce)
|
|
{
|
|
HRESULT hr = NOERROR; // only report error is actual call to register CFact Failed.
|
|
LPWSTR pEventName;
|
|
BOOL fExistingInstance = FALSE;
|
|
|
|
if (( VER_PLATFORM_WIN32_NT != g_OSVersionInfo.dwPlatformId)
|
|
|| (NOERROR != MakeWinstaDesktopName(SZ_CFACTORYEVENTNAME,&pEventName)) )
|
|
{
|
|
pEventName = (LPWSTR) SZ_CFACTORYEVENTNAME;
|
|
}
|
|
|
|
// this should only ever be called on MainThread so don't
|
|
// need to lock
|
|
Assert(g_ObjectMgrData.dwMainThreadID == GetCurrentThreadId());
|
|
Assert(NULL == g_ObjectMgrData.hClassRegisteredEvent);
|
|
|
|
g_ObjectMgrData.hClassRegisteredEvent = CreateEvent(NULL,TRUE,FALSE,pEventName);
|
|
Assert(g_ObjectMgrData.hClassRegisteredEvent);
|
|
|
|
// if got the event and not a force see if there is an existing instance.
|
|
if (g_ObjectMgrData.hClassRegisteredEvent && !fForce)
|
|
{
|
|
if (ERROR_ALREADY_EXISTS == GetLastError())
|
|
{
|
|
// object already existed and the force flag isn't set
|
|
// it means we can use the existing registered object.
|
|
CloseHandle(g_ObjectMgrData.hClassRegisteredEvent);
|
|
g_ObjectMgrData.hClassRegisteredEvent = NULL;
|
|
hr = NOERROR;
|
|
fExistingInstance = TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
// If fForce is set or these isn't an existing class
|
|
// go ahead and register.
|
|
if (fForce || (!fExistingInstance && g_ObjectMgrData.hClassRegisteredEvent))
|
|
{
|
|
// force on an event already existing is a state that
|
|
// should only occur if EXE was launched twice with the embedding flag.
|
|
// This shouldn't happen under normal conditions so assert.
|
|
// so we can catch any cases that we didn't get the event
|
|
// and the force flag is set.
|
|
|
|
Assert(g_ObjectMgrData.hClassRegisteredEvent);
|
|
|
|
hr = RegisterOneStopCLSIDs();
|
|
|
|
if (NOERROR != hr)
|
|
{
|
|
if (g_ObjectMgrData.hClassRegisteredEvent)
|
|
{
|
|
CloseHandle(g_ObjectMgrData.hClassRegisteredEvent);
|
|
g_ObjectMgrData.hClassRegisteredEvent = NULL;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (pEventName && (SZ_CFACTORYEVENTNAME != pEventName))
|
|
{
|
|
FREE(pEventName);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: AddRefOneStopLifetime, public
|
|
//
|
|
// Synopsis: Adds a Reference to the applications
|
|
|
|
// Arguments:
|
|
//
|
|
// Returns: New total Reference count including both
|
|
// internal and external locks.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) AddRefOneStopLifetime(BOOL fExternal)
|
|
{
|
|
DWORD cRefs;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
// Increment ref count
|
|
cCritSect.Enter();
|
|
|
|
if (fExternal)
|
|
{
|
|
++g_ObjectMgrData.LockCountExternal;
|
|
}
|
|
else
|
|
{
|
|
++g_ObjectMgrData.LockCountInternal;
|
|
}
|
|
|
|
cRefs = g_ObjectMgrData.LockCountExternal + g_ObjectMgrData.LockCountInternal;
|
|
|
|
cCritSect.Leave();
|
|
|
|
Assert(0 < cRefs);
|
|
|
|
return cRefs;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReleaseOneStopLifetime, public
|
|
//
|
|
// Synopsis: Releases a Reference to the applications
|
|
// If the refcount goes to zero the classfactory
|
|
// is revoked an a quit message is posted to the
|
|
// main thread
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: New Reference count including internal and
|
|
// external locks.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) ReleaseOneStopLifetime(BOOL fExternal)
|
|
{
|
|
DWORD cRefsExternal;
|
|
DWORD cRefsInternal;
|
|
BOOL fForceClose;
|
|
DLGLISTITEM *pDlgListItem;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
|
|
cCritSect.Enter();
|
|
|
|
if (fExternal)
|
|
{
|
|
--g_ObjectMgrData.LockCountExternal;
|
|
}
|
|
else
|
|
{
|
|
--g_ObjectMgrData.LockCountInternal;
|
|
}
|
|
|
|
|
|
cRefsInternal = g_ObjectMgrData.LockCountInternal;
|
|
cRefsExternal = g_ObjectMgrData.LockCountExternal;
|
|
fForceClose = g_ObjectMgrData.fCloseAll;
|
|
|
|
pDlgListItem = g_ObjectMgrData.DlgList;
|
|
|
|
|
|
Assert(0 <= ((LONG) cRefsInternal));
|
|
Assert(0 <= ((LONG) cRefsExternal));
|
|
|
|
if( (0 >= cRefsInternal)
|
|
&& (0 >= cRefsExternal || fForceClose)
|
|
&& (FALSE == g_ObjectMgrData.fDead) )
|
|
{
|
|
HANDLE hRegisteredEvent;
|
|
HWND hwndMainThreadMsg;
|
|
DWORD dwRegClassFactCookie;
|
|
BOOL fRegClassFactCookieValid;
|
|
|
|
Assert(0 == pDlgListItem); // all dialogs should have been released.
|
|
Assert(0 == g_ObjectMgrData.dwSettingsLockCount); // settings dialogs should be gone.
|
|
|
|
g_ObjectMgrData.fDead = TRUE;
|
|
|
|
hRegisteredEvent = g_ObjectMgrData.hClassRegisteredEvent;
|
|
g_ObjectMgrData.hClassRegisteredEvent = NULL;
|
|
|
|
hwndMainThreadMsg = g_ObjectMgrData.hWndMainThreadMsg;
|
|
g_ObjectMgrData.hWndMainThreadMsg = NULL;
|
|
|
|
dwRegClassFactCookie = g_ObjectMgrData.dwRegClassFactCookie;
|
|
g_ObjectMgrData.dwRegClassFactCookie = 0;
|
|
|
|
fRegClassFactCookieValid = g_ObjectMgrData.fRegClassFactCookieValid;
|
|
g_ObjectMgrData.fRegClassFactCookieValid = FALSE;
|
|
|
|
cCritSect.Leave();
|
|
|
|
if (NULL != hRegisteredEvent)
|
|
{
|
|
CloseHandle(hRegisteredEvent); // release our registration event.
|
|
}
|
|
|
|
// we need to revoke the classfactory on the thread that registered it.
|
|
// Send a message back to the thread that registered the event.
|
|
|
|
if (fRegClassFactCookieValid)
|
|
{
|
|
SendMessage(hwndMainThreadMsg,WM_CFACTTHREAD_REVOKE,dwRegClassFactCookie,0);
|
|
}
|
|
|
|
// if lockcount is still zero then post the quitmessage
|
|
// else someone came in during our revoke and we
|
|
// need to wait for the refcount to hit zero again.
|
|
|
|
cCritSect.Enter();
|
|
|
|
cRefsInternal = g_ObjectMgrData.LockCountInternal;
|
|
cRefsExternal = g_ObjectMgrData.LockCountExternal;
|
|
|
|
if ( (0 >= cRefsInternal)
|
|
&& (0 >= cRefsExternal || fForceClose) )
|
|
{
|
|
DWORD dwMainThreadID;
|
|
HANDLE hThread = NULL;
|
|
|
|
dwMainThreadID = g_ObjectMgrData.dwMainThreadID;
|
|
|
|
// its possible the quite is occuring on a thread other than
|
|
// the main thread. If this is the case send the handle of the thread
|
|
// along with the quit message to the main thread can wait for this
|
|
// thread to exit.
|
|
|
|
#ifdef _THREADSHUTDOWN
|
|
if (dwMainThreadID != GetCurrentThreadId())
|
|
{
|
|
HANDLE hCurThread;
|
|
HANDLE hProcess;
|
|
|
|
hCurThread = GetCurrentThread();
|
|
hProcess = GetCurrentProcess();
|
|
|
|
if (!DuplicateHandle(hProcess,hCurThread,hProcess,&hThread,
|
|
0,FALSE,DUPLICATE_SAME_ACCESS) )
|
|
{
|
|
hThread = NULL; // don't rely on DupHandle to set this to null on error.
|
|
}
|
|
|
|
}
|
|
#endif // _THREADSHUTDOWN
|
|
|
|
// shut down the main thread
|
|
cCritSect.Leave();
|
|
PostMessage(hwndMainThreadMsg,WM_MAINTHREAD_QUIT,0,(LPARAM) /* hThread */ 0);
|
|
cCritSect.Enter();
|
|
}
|
|
else
|
|
{
|
|
g_ObjectMgrData.fDead = FALSE;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
cCritSect.Leave();
|
|
|
|
return (cRefsExternal + cRefsInternal);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: IsOneStopDlgMessage, public
|
|
//
|
|
// Synopsis: Called in messageloop to determine if message
|
|
// should be handled by a dialog
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: TRUE - The item was processed.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#ifdef _UNUSED
|
|
|
|
BOOL IsOneStopDlgMessage(MSG *msg)
|
|
{
|
|
DLGLISTITEM *pDlgListItem;
|
|
DWORD dwThreadID = GetCurrentThreadId();
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,dwThreadID);
|
|
HWND hwnd = NULL;
|
|
|
|
|
|
cCritSect.Enter();
|
|
|
|
// see if we have a dialog in this thread.
|
|
pDlgListItem = g_ObjectMgrData.DlgList;
|
|
while (pDlgListItem)
|
|
{
|
|
|
|
if (pDlgListItem->pDlg
|
|
&& dwThreadID == pDlgListItem->dwThreadID)
|
|
{
|
|
hwnd = pDlgListItem->pDlg->GetHwnd();
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
break;
|
|
}
|
|
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
}
|
|
|
|
#if DEBUG
|
|
|
|
// we should only ever have one registered dialog per thread
|
|
// loop through remaining dialogs and if find a match assert
|
|
|
|
while (pDlgListItem)
|
|
{
|
|
|
|
if (pDlgListItem->pDlg
|
|
&& dwThreadID == pDlgListItem->dwThreadID)
|
|
{
|
|
AssertSz(0,"Multiple dialogs in thread");
|
|
break;
|
|
}
|
|
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
}
|
|
|
|
|
|
|
|
#endif // DEBUG
|
|
|
|
cCritSect.Leave();
|
|
|
|
if (hwnd && IsDialogMessage(hwnd,msg))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#endif // _UNUSED
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: InitObjectManager, public
|
|
//
|
|
// Synopsis: Must be called from Main thread before any
|
|
// new threads, dialogs are created or the class factory
|
|
// is registered.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate Error Codes.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 17-Nov-97 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI InitObjectManager(CMsgServiceHwnd *pMsgService)
|
|
{
|
|
// initialize critical section for our lock count.
|
|
InitializeCriticalSection(&g_LockCountCriticalSection);
|
|
|
|
g_ObjectMgrData.dwMainThreadID = GetCurrentThreadId();
|
|
g_ObjectMgrData.hWndMainThreadMsg = pMsgService->GetHwnd();
|
|
|
|
g_ObjectMgrData.DlgList = NULL;
|
|
g_ObjectMgrData.hClassRegisteredEvent = NULL;
|
|
g_ObjectMgrData.dwRegClassFactCookie = 0;
|
|
g_ObjectMgrData.fRegClassFactCookieValid = FALSE;
|
|
g_ObjectMgrData.LockCountInternal = 0;
|
|
g_ObjectMgrData.LockCountExternal = 0;
|
|
g_ObjectMgrData.fCloseAll = FALSE;
|
|
g_ObjectMgrData.dwSettingsLockCount = 0;
|
|
g_ObjectMgrData.dwHandlerPropertiesLockCount = 0;
|
|
g_ObjectMgrData.fDead = FALSE;
|
|
|
|
// Initialize autodial support
|
|
g_ObjectMgrData.eAutoDialState = eQuiescedOff;
|
|
g_ObjectMgrData.fRasAutoDial = FALSE;
|
|
g_ObjectMgrData.fWininetAutoDial = FALSE;
|
|
g_ObjectMgrData.fFirstSyncItem = FALSE;
|
|
g_ObjectMgrData.cNestedStartCalls = 0;
|
|
|
|
Assert(NULL != g_ObjectMgrData.hWndMainThreadMsg);
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: RequestIdleLock, public
|
|
//
|
|
// Synopsis: request to see if an new Idle can be started.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: NOERROR - if Idle should be continued
|
|
// S_FALSE - if another Idle is already in progreaa.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 23-Feb-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI RequestIdleLock()
|
|
{
|
|
HRESULT hr;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
cCritSect.Enter();
|
|
|
|
if (g_ObjectMgrData.fIdleHandlerRunning)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
hr = NOERROR;
|
|
g_ObjectMgrData.fIdleHandlerRunning = TRUE;
|
|
}
|
|
|
|
cCritSect.Leave();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReleaseIdleLock, public
|
|
//
|
|
// Synopsis: Informs ObjectMgr that the Idle is done processing.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate error codes.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 23-Feb-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI ReleaseIdleLock()
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
cCritSect.Enter();
|
|
|
|
// note okay for this to already be FALSE in case progress receives
|
|
// an offidle before release. Call this when idle progress is
|
|
// released as safety in case offidle isn't working properly.
|
|
|
|
g_ObjectMgrData.fIdleHandlerRunning = FALSE;
|
|
|
|
cCritSect.Leave();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ObjMgr_HandleQueryEndSession, public
|
|
//
|
|
// Synopsis: Called by main thread so knows how to respond to WN_QUERYENDSESSION.
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: S_OK - if system can shutdown
|
|
// S_FALSE - if hould fail the query. On an S_FALSE the out params
|
|
// are filled, hwnd with parent hwnd of any message box and MessageID
|
|
// with the appropriate messageID to display.
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 21-May-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI ObjMgr_HandleQueryEndSession(HWND *phwnd,UINT *puMessageId,BOOL *pfLetUserDecide)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BOOL fProgressDialog = FALSE;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
cCritSect.Enter();
|
|
|
|
*phwnd = NULL;
|
|
*pfLetUserDecide = FALSE;
|
|
|
|
// if there are any settings dialogs then we can't quit
|
|
if (g_ObjectMgrData.dwSettingsLockCount > 0)
|
|
{
|
|
*phwnd = NULL;
|
|
*puMessageId = IDS_SETTINGSQUERYENDSESSION;
|
|
hr = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
DLGLISTITEM *pDlgListItem;
|
|
BOOL fDontShutdown = FALSE; // set when find match
|
|
HWND hwnd;
|
|
UINT uMessageId;
|
|
BOOL fLetUserDecide;
|
|
|
|
|
|
// loop through dialogs asking if they can shutdown.
|
|
// first dialog find that doesn't give choice return
|
|
// if the dialog says to let user decide continue looping
|
|
// until hit end or find a dialog that doesn't give choice since
|
|
// not giving choice takes precedence.
|
|
|
|
// see if there is a progress dialog other than idle and if so stop the logoff.
|
|
pDlgListItem = g_ObjectMgrData.DlgList;
|
|
|
|
// loop through the choice dialogs to see if
|
|
while (pDlgListItem)
|
|
{
|
|
|
|
if ( (pDlgListItem->pDlg)
|
|
&& (S_FALSE == pDlgListItem->pDlg->QueryCanSystemShutdown(&hwnd,&uMessageId,&fLetUserDecide) ) )
|
|
{
|
|
// if first dialog find we can't shutdown or fLetUserDecide isn't set
|
|
// then upate the out params
|
|
|
|
if (!fDontShutdown || !fLetUserDecide)
|
|
{
|
|
*phwnd = hwnd;
|
|
*puMessageId = uMessageId;
|
|
*pfLetUserDecide = fLetUserDecide;
|
|
|
|
fProgressDialog = (pDlgListItem->dlgType == DLGTYPE_PROGRESS) ? TRUE : FALSE;
|
|
}
|
|
|
|
fDontShutdown = TRUE;
|
|
|
|
// if this dialog doesn't allow the use choice then break
|
|
if (!fLetUserDecide)
|
|
{
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
}
|
|
|
|
if (fDontShutdown)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
cCritSect.Leave();
|
|
|
|
// if can't shutdown and it is a progress dialog then make sure
|
|
// the dialog is not minimized;
|
|
if (fProgressDialog && (NULL != *phwnd) )
|
|
{
|
|
BASEDLG_SHOWWINDOW(*phwnd,SW_SHOWNORMAL);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ObjMgr_AddRefHandlerPropertiesLockCount, public
|
|
//
|
|
// Synopsis: Called by choice dialog to change the global lock count
|
|
// of open handler properties dialogs
|
|
//
|
|
// Arguments: dwNumRefs - number of references to increment
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 21-May-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) ObjMgr_AddRefHandlerPropertiesLockCount(DWORD dwNumRefs)
|
|
{
|
|
ULONG cRefs;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
Assert(0 != dwNumRefs); // catch people passing on 0 since doesn't make sense.
|
|
|
|
cCritSect.Enter();
|
|
|
|
g_ObjectMgrData.dwHandlerPropertiesLockCount += dwNumRefs;
|
|
cRefs = g_ObjectMgrData.dwHandlerPropertiesLockCount;
|
|
|
|
cCritSect.Leave();
|
|
|
|
return cRefs;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ObjMgr_ReleaseHandlerPropertiesLockCount, public
|
|
//
|
|
// Synopsis: Called by choice dialog to change the global lock count
|
|
// of open handler properties dialogs
|
|
//
|
|
// Arguments: dwNumRefs - number of references to decrement
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 21-May-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI_(ULONG) ObjMgr_ReleaseHandlerPropertiesLockCount(DWORD dwNumRefs)
|
|
{
|
|
DWORD cRefs;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
Assert(0 != dwNumRefs); // catch people passing on 0 since doesn't make sense.
|
|
|
|
cCritSect.Enter();
|
|
|
|
g_ObjectMgrData.dwHandlerPropertiesLockCount -= dwNumRefs;
|
|
cRefs = g_ObjectMgrData.dwHandlerPropertiesLockCount;
|
|
|
|
cCritSect.Leave();
|
|
|
|
Assert( ((LONG) cRefs) >= 0);
|
|
|
|
if ( ((LONG) cRefs) < 0)
|
|
{
|
|
cRefs = 0;
|
|
}
|
|
|
|
return cRefs;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ObjMgr_CloseAll, public
|
|
//
|
|
// Synopsis: Called by main thread when an END_SESSION occurs. Loops throug
|
|
// dialogs posting a close to them
|
|
//
|
|
// Arguments:
|
|
//
|
|
// Returns: Appropriate error codes
|
|
//
|
|
// Modifies:
|
|
//
|
|
// History: 21-May-98 rogerg Created.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI ObjMgr_CloseAll()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HWND hwndDlg;
|
|
DLGLISTITEM *pDlgListItem;
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
|
|
|
|
// Put on Addref to hold alive until done with loop. and also
|
|
// toggle lifetime in case launched with /embedding and
|
|
// no references on self.
|
|
|
|
AddRefOneStopLifetime(FALSE /* !External */);
|
|
|
|
cCritSect.Enter();
|
|
// see if there is a progress dialog other than idle and if so stop the logoff.
|
|
pDlgListItem = g_ObjectMgrData.DlgList;
|
|
|
|
// look for existing.
|
|
while (pDlgListItem)
|
|
{
|
|
Assert(pDlgListItem->pDlg);
|
|
|
|
if (pDlgListItem->pDlg)
|
|
{
|
|
hwndDlg = pDlgListItem->pDlg->GetHwnd();
|
|
|
|
Assert(hwndDlg);
|
|
|
|
if (NULL != hwndDlg)
|
|
{
|
|
PostMessage(hwndDlg,WM_BASEDLG_HANDLESYSSHUTDOWN,0,0);
|
|
}
|
|
}
|
|
|
|
pDlgListItem = pDlgListItem->pDlgNextListItem;
|
|
}
|
|
|
|
// set the CloseAll flag so Release knows to ignore any
|
|
// external refCounts
|
|
g_ObjectMgrData.fCloseAll = TRUE;
|
|
|
|
cCritSect.Leave();
|
|
|
|
ReleaseOneStopLifetime(FALSE /* !External */);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetAutoDialState
|
|
//
|
|
// Synopsis: Reads the current auto dial state of the machine/process
|
|
//
|
|
// History: 18-Jul-98 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI GetAutoDialState()
|
|
{
|
|
LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
|
|
|
|
if (NULL != pNetApi )
|
|
{
|
|
BOOL fEnabled;
|
|
|
|
pNetApi->RasGetAutodial( fEnabled );
|
|
g_ObjectMgrData.fRasAutoDial = fEnabled;
|
|
|
|
pNetApi->InternetGetAutodial( fEnabled );
|
|
g_ObjectMgrData.fWininetAutoDial = fEnabled;
|
|
}
|
|
|
|
if ( pNetApi != NULL )
|
|
pNetApi->Release();
|
|
|
|
if ( g_ObjectMgrData.fRasAutoDial || g_ObjectMgrData.fWininetAutoDial )
|
|
g_ObjectMgrData.eAutoDialState = eQuiescedOn;
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: LokEnableAutoDial
|
|
//
|
|
// Synopsis: Enables Ras and Wininet autodialing
|
|
//
|
|
// History: 18-Jul-98 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI LokEnableAutoDial()
|
|
{
|
|
LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
|
|
|
|
if (NULL != pNetApi )
|
|
{
|
|
if ( g_ObjectMgrData.fRasAutoDial )
|
|
pNetApi->RasSetAutodial( TRUE );
|
|
|
|
if ( g_ObjectMgrData.fWininetAutoDial )
|
|
pNetApi->InternetSetAutodial( TRUE );
|
|
}
|
|
|
|
if ( pNetApi != NULL )
|
|
pNetApi->Release();
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: LokDisableAutoDial
|
|
//
|
|
// Synopsis: Disables Ras and Wininet autodialing
|
|
//
|
|
// History: 18-Jul-98 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI LokDisableAutoDial()
|
|
{
|
|
LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
|
|
|
|
if (NULL != pNetApi )
|
|
{
|
|
if ( g_ObjectMgrData.fRasAutoDial )
|
|
pNetApi->RasSetAutodial( FALSE );
|
|
|
|
if ( g_ObjectMgrData.fWininetAutoDial )
|
|
pNetApi->InternetSetAutodial( FALSE );
|
|
}
|
|
|
|
if ( pNetApi != NULL )
|
|
pNetApi->Release();
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: BeginSyncSession
|
|
//
|
|
// Synopsis: Called at the beginning of actual synchronization to setup
|
|
// autodial support.
|
|
//
|
|
// History: 18-Jul-98 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI BeginSyncSession()
|
|
{
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
cCritSect.Enter();
|
|
|
|
if ( g_ObjectMgrData.cNestedStartCalls == 0 )
|
|
{
|
|
Assert( g_ObjectMgrData.eAutoDialState == eQuiescedOn
|
|
|| g_ObjectMgrData.eAutoDialState == eQuiescedOff );
|
|
|
|
g_ObjectMgrData.fFirstSyncItem = TRUE;
|
|
}
|
|
|
|
g_ObjectMgrData.cNestedStartCalls++;
|
|
|
|
cCritSect.Leave();
|
|
|
|
return NOERROR;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: EndSyncSession
|
|
//
|
|
// Synopsis: Called at the end of actual synchronization to cleanup
|
|
// autodial support.
|
|
//
|
|
// History: 28-Jul-98 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI EndSyncSession()
|
|
{
|
|
HRESULT hr = E_UNEXPECTED;
|
|
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
cCritSect.Enter();
|
|
|
|
Assert( g_ObjectMgrData.cNestedStartCalls > 0 );
|
|
Assert( g_ObjectMgrData.eAutoDialState != eQuiescedOn );
|
|
|
|
g_ObjectMgrData.cNestedStartCalls--;
|
|
|
|
if ( g_ObjectMgrData.cNestedStartCalls == 0 )
|
|
{
|
|
if ( g_ObjectMgrData.eAutoDialState == eAutoDialOn )
|
|
g_ObjectMgrData.eAutoDialState = eQuiescedOn;
|
|
else if ( g_ObjectMgrData.eAutoDialState == eAutoDialOff )
|
|
{
|
|
//
|
|
// Reset autodial state to enabled now that all synch has completed.
|
|
// What to do if hr is set to error code ?
|
|
//
|
|
hr = LokEnableAutoDial();
|
|
|
|
g_ObjectMgrData.eAutoDialState = eQuiescedOn;
|
|
}
|
|
//
|
|
// If the state is eQuiescedOff then do nothing
|
|
//
|
|
}
|
|
|
|
cCritSect.Leave();
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ApplySyncItemDialState
|
|
//
|
|
// Synopsis: Set the auto dial requirements of each handler as it is being
|
|
// prepared for syncing.
|
|
//
|
|
// Arguments: [fAutoDialDisable] -- Should autodial be disabled for this
|
|
// handler ?
|
|
//
|
|
// History: 28-Jul-98 SitaramR Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI ApplySyncItemDialState( BOOL fAutoDialDisable )
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
|
|
cCritSect.Enter();
|
|
|
|
if ( g_ObjectMgrData.fFirstSyncItem )
|
|
{
|
|
//
|
|
// Read whether autodial state is on or off, before we modify it
|
|
//
|
|
GetAutoDialState();
|
|
|
|
Assert( g_ObjectMgrData.eAutoDialState == eQuiescedOn
|
|
|| g_ObjectMgrData.eAutoDialState == eQuiescedOff );
|
|
|
|
if ( g_ObjectMgrData.eAutoDialState == eQuiescedOn )
|
|
{
|
|
if ( fAutoDialDisable )
|
|
{
|
|
hr = LokDisableAutoDial();
|
|
g_ObjectMgrData.eAutoDialState = eAutoDialOff;
|
|
}
|
|
else
|
|
g_ObjectMgrData.eAutoDialState = eAutoDialOn;
|
|
}
|
|
|
|
g_ObjectMgrData.fFirstSyncItem = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if ( !fAutoDialDisable
|
|
&& g_ObjectMgrData.eAutoDialState == eAutoDialOff )
|
|
{
|
|
hr = LokEnableAutoDial();
|
|
g_ObjectMgrData.eAutoDialState = eAutoDialOn;
|
|
}
|
|
}
|
|
|
|
cCritSect.Leave();
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSingletonNetApi::~CSingletonNetApi
|
|
//
|
|
// Synopsis: Destructor
|
|
//
|
|
// History: 31-Jul-1998 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
CSingletonNetApi::~CSingletonNetApi()
|
|
{
|
|
CLock lock(this);
|
|
lock.Enter();
|
|
|
|
Assert(NULL == m_pNetApi);
|
|
|
|
if ( m_pNetApi != 0 )
|
|
{
|
|
m_pNetApi->Release();
|
|
m_pNetApi = 0;
|
|
}
|
|
|
|
lock.Leave();
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
//
|
|
// Method: CSingletonNetApi::GetNetApiObj
|
|
//
|
|
// Synopsis: Returns a pointer to NetApi object
|
|
//
|
|
// History: 31-Jul-1998 SitaramR Created
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
|
|
LPNETAPI CSingletonNetApi::GetNetApiObj()
|
|
{
|
|
CLock lock(this);
|
|
lock.Enter();
|
|
|
|
if ( m_pNetApi == 0 )
|
|
{
|
|
if (NOERROR != MobsyncGetClassObject(MOBSYNC_CLASSOBJECTID_NETAPI,(void **) &m_pNetApi))
|
|
{
|
|
m_pNetApi = NULL;
|
|
}
|
|
}
|
|
|
|
if ( m_pNetApi )
|
|
m_pNetApi->AddRef();
|
|
|
|
lock.Leave();
|
|
|
|
return m_pNetApi;
|
|
}
|
|
|
|
|
|
void CSingletonNetApi::DeleteNetApiObj()
|
|
{
|
|
CLock lock(this);
|
|
lock.Enter();
|
|
|
|
if ( m_pNetApi )
|
|
{
|
|
DWORD cRefs;
|
|
|
|
cRefs = m_pNetApi->Release();
|
|
Assert(0 == cRefs);
|
|
|
|
m_pNetApi = NULL;
|
|
}
|
|
|
|
lock.Leave();
|
|
|
|
}
|
|
|