Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2272 lines
60 KiB

//+-------------------------------------------------------------------------
//
// 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();
}