//+------------------------------------------------------------------------- // // 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 #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 (S_OK == ThreadArgs.hr) { *phThread = hNewThread; *ppDlg = ThreadArgs.pDlg; hr = S_OK; } else { CloseHandle(hNewThread); hr = ThreadArgs.hr; } } else { hr = HRESULT_FROM_WIN32(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 = S_OK; 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 (S_OK == 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 (fCreate && NULL == *pDlg) { CBaseDlg *pNewDlg; DLGLISTITEM *pNewDlgListItem; DWORD dwThreadID; pNewDlgListItem = (DLGLISTITEM *) ALLOC(sizeof(DLGLISTITEM)); if (pNewDlgListItem) { HRESULT hr; HANDLE hThread; cCritSect.Leave(); hr = CreateDlgThread(dlgType,rclsid,nCmdShow,&pNewDlg,&dwThreadID,&hThread); cCritSect.Enter(); if (S_OK == 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; 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 0; // 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 = S_OK; 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 = S_OK; 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 (S_OK != 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 ULONG cchWinstaDesktop; DWORD Length; BOOL Status; HRESULT hr; DWORD dwResult; if (!ppszResultString) { Assert(ppszResultString); return E_INVALIDARG; } *ppszResultString = NULL;; 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; } } cchWinstaDesktop = (pszPreceding ? lstrlen(pszPreceding) + 1 : 0) + lstrlen(pwszWinsta) + 1 + lstrlen(pwszDesktop) + 1; _pwszWinstaDesktop = (WCHAR *) ALLOC(cchWinstaDesktop * sizeof(WCHAR)); if ( _pwszWinstaDesktop ) { *_pwszWinstaDesktop = NULL; if (pszPreceding) { StringCchCopy(_pwszWinstaDesktop, cchWinstaDesktop, pszPreceding); StringCchCat(_pwszWinstaDesktop, cchWinstaDesktop, L"_"); } StringCchCat(_pwszWinstaDesktop, cchWinstaDesktop, pwszWinsta ); StringCchCat(_pwszWinstaDesktop, cchWinstaDesktop, L"_" ); StringCchCat(_pwszWinstaDesktop, cchWinstaDesktop, pwszDesktop ); hr = S_OK; } else { hr = E_OUTOFMEMORY; } WinstaDesktopExit: if ( pwszWinsta != wszWinsta ) { FREE( pwszWinsta ); } if ( pwszDesktop != wszDesktop ) { FREE( pwszDesktop ); } if (S_OK == 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 = S_OK; // only report error is actual call to register CFact Failed. LPWSTR pEventName; BOOL fExistingInstance = FALSE; if (S_OK != 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 = S_OK; 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 (S_OK != 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 (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: 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. if (InitializeCriticalSectionAndSpinCount(&g_LockCountCriticalSection, 0)) { 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.dwWininetAutoDialMode = AUTODIAL_MODE_NEVER; g_ObjectMgrData.fFirstSyncItem = FALSE; g_ObjectMgrData.cNestedStartCalls = 0; Assert(g_ObjectMgrData.hWndMainThreadMsg); return S_OK; } return E_FAIL; } //+--------------------------------------------------------------------------- // // Function: RequestIdleLock, public // // Synopsis: request to see if an new Idle can be started. // // Arguments: // // Returns: S_OK - 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 = S_OK; 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 = S_OK; 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 && (*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(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(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 (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 ( pNetApi ) { BOOL fEnabled; DWORD dwMode; pNetApi->RasGetAutodial( fEnabled ); g_ObjectMgrData.fRasAutoDial = fEnabled; pNetApi->InternetGetAutodial( &dwMode ); g_ObjectMgrData.dwWininetAutoDialMode = dwMode; } if ( pNetApi ) pNetApi->Release(); if ( g_ObjectMgrData.fRasAutoDial || (AUTODIAL_MODE_NEVER != g_ObjectMgrData.dwWininetAutoDialMode )) g_ObjectMgrData.eAutoDialState = eQuiescedOn; return S_OK; } //+--------------------------------------------------------------------------- // // Function: LokEnableAutoDial // // Synopsis: Enables Ras and Wininet autodialing // // History: 18-Jul-98 SitaramR Created // 22-Mar-02 BrianAu Use inet autodial mode // //---------------------------------------------------------------------------- STDAPI LokEnableAutoDial() { LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj(); if ( pNetApi ) { if ( g_ObjectMgrData.fRasAutoDial ) pNetApi->RasSetAutodial( TRUE ); pNetApi->InternetSetAutodial( g_ObjectMgrData.dwWininetAutoDialMode ); } if ( pNetApi ) pNetApi->Release(); return S_OK; } //+--------------------------------------------------------------------------- // // Function: LokDisableAutoDial // // Synopsis: Disables Ras and Wininet autodialing // // History: 18-Jul-98 SitaramR Created // 22-Mar-02 BrianAu Use inet autodial mode // //---------------------------------------------------------------------------- STDAPI LokDisableAutoDial() { LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj(); if ( pNetApi ) { if ( g_ObjectMgrData.fRasAutoDial ) pNetApi->RasSetAutodial( FALSE ); pNetApi->InternetSetAutodial( AUTODIAL_MODE_NEVER ); pNetApi->Release(); } return S_OK; } //+--------------------------------------------------------------------------- // // 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 S_OK; } //+--------------------------------------------------------------------------- // // 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 = S_OK; 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 ) { 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 (S_OK != 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(); }