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

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: Objmgr.cpp
  7. //
  8. // Contents: Keeps track of dialog objects and
  9. // application lifetime
  10. //
  11. // Classes:
  12. //
  13. // Notes:
  14. //
  15. // History: 05-Nov-97 rogerg Created.
  16. //
  17. //--------------------------------------------------------------------------
  18. #include "precomp.h"
  19. STDAPI DisplayOptions(HWND hwndOwner); // OneStop.dll Export
  20. CSingletonNetApi gSingleNetApiObj; // Global singleton NetApi object
  21. CRITICAL_SECTION g_LockCountCriticalSection; // Critical Section fo Object Mgr
  22. OBJECTMGRDATA g_ObjectMgrData; // Global Object Mgr Data
  23. extern OSVERSIONINFOA g_OSVersionInfo; // osVersionInfo, setup by WinMain.
  24. #ifdef _DEBUG
  25. DWORD g_ThreadCount = 0;
  26. #endif // _DEBUG
  27. //+---------------------------------------------------------------------------
  28. //
  29. // Function: CreateDlgThread, public
  30. //
  31. // Synopsis: Called to Create a new Dlg Thread
  32. //
  33. // Arguments: [dlgType] - Type of Dialog to create
  34. // [nCmdShow] - How to display the Dialog.
  35. // [ppDlg] - on success returns a pointer to the new dialog
  36. // [pdwThreadID] - on Success Id of thread that was created.
  37. // [phThread] - Handle to newly created thread.
  38. //
  39. // Returns: Appropriate return codes
  40. //
  41. // Modifies:
  42. //
  43. // History: 17-Nov-97 rogerg Created.
  44. //
  45. //----------------------------------------------------------------------------
  46. HRESULT CreateDlgThread(DLGTYPE dlgType,REFCLSID rclsid,int nCmdShow,CBaseDlg **ppDlg,
  47. DWORD *pdwThreadID,HANDLE *phThread)
  48. {
  49. HRESULT hr = E_FAIL;
  50. HANDLE hNewThread = NULL;
  51. DlgThreadArgs ThreadArgs;
  52. *phThread = NULL;
  53. *ppDlg = NULL;
  54. ThreadArgs.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  55. if (ThreadArgs.hEvent)
  56. {
  57. ThreadArgs.dlgType = dlgType;
  58. ThreadArgs.clsid = rclsid;
  59. ThreadArgs.pDlg = NULL;
  60. ThreadArgs.nCmdShow = nCmdShow;
  61. ThreadArgs.hr = E_UNEXPECTED;
  62. hNewThread = CreateThread(NULL,0,DialogThread,&ThreadArgs,0,pdwThreadID);
  63. if (hNewThread)
  64. {
  65. WaitForSingleObject(ThreadArgs.hEvent,INFINITE);
  66. if (NOERROR == ThreadArgs.hr)
  67. {
  68. *phThread = hNewThread;
  69. *ppDlg = ThreadArgs.pDlg;
  70. hr = NOERROR;
  71. }
  72. else
  73. {
  74. CloseHandle(hNewThread);
  75. hr = ThreadArgs.hr;
  76. }
  77. }
  78. else
  79. {
  80. hr = GetLastError();
  81. }
  82. CloseHandle(ThreadArgs.hEvent);
  83. }
  84. return hr;
  85. }
  86. //+---------------------------------------------------------------------------
  87. //
  88. // Function: DialogThread, public
  89. //
  90. // Synopsis: ThreadProc for a new Dlg Thread
  91. // !!!Warning - Must always ensure event in ThreadArg gets set.
  92. //
  93. // Arguments: [lpArg] - Pointer to DialogThreadArgs
  94. //
  95. // Returns: Appropriate return codes. Sets hr value in
  96. // ThreadArgs before setting event object
  97. //
  98. //
  99. // Modifies:
  100. //
  101. // History: 17-Nov-97 rogerg Created.
  102. //
  103. //----------------------------------------------------------------------------
  104. DWORD WINAPI DialogThread( LPVOID lpArg )
  105. {
  106. MSG msg;
  107. HRESULT hr;
  108. HRESULT hrCoInitialize;
  109. DWORD cRefs;
  110. HWND hwndDlg;
  111. DlgThreadArgs *pThreadArgs = (DlgThreadArgs *) lpArg;
  112. pThreadArgs->hr = NOERROR;
  113. hrCoInitialize = CoInitialize(NULL);
  114. switch (pThreadArgs->dlgType)
  115. {
  116. case DLGTYPE_CHOICE:
  117. pThreadArgs->pDlg = new CChoiceDlg(pThreadArgs->clsid);
  118. break;
  119. case DLGTYPE_PROGRESS:
  120. pThreadArgs->pDlg = new CProgressDlg(pThreadArgs->clsid);
  121. break;
  122. default:
  123. pThreadArgs->pDlg = NULL;
  124. AssertSz(0,"Unknown Dialog Type");
  125. break;
  126. }
  127. // need to do a PeekMessage and then set an event to make sure
  128. // a message loop is created before the first PostMessage is sent.
  129. PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
  130. // initialize the dialog box before returning to main thread.
  131. if (NULL == pThreadArgs->pDlg ||
  132. FALSE == pThreadArgs->pDlg->Initialize(GetCurrentThreadId(),pThreadArgs->nCmdShow)
  133. || (FAILED(hrCoInitialize)) )
  134. {
  135. if (pThreadArgs->pDlg)
  136. pThreadArgs->pDlg->PrivReleaseDlg(RELEASEDLGCMDID_DESTROY);
  137. pThreadArgs->hr = E_OUTOFMEMORY;
  138. }
  139. else
  140. {
  141. hwndDlg = pThreadArgs->pDlg->GetHwnd();
  142. }
  143. hr = pThreadArgs->hr;
  144. #ifdef _DEBUG
  145. ++g_ThreadCount;
  146. #endif // _DEBUG
  147. cRefs = AddRefOneStopLifetime(FALSE /* !External */); // make sure we stay alive for lifetime of thread.
  148. Assert(cRefs > 1); // someone else should also have a lock during dialog creation.
  149. // let the caller know the thread is done initializing.
  150. if (pThreadArgs->hEvent)
  151. SetEvent(pThreadArgs->hEvent);
  152. if (NOERROR == hr)
  153. {
  154. // sit in loop receiving messages.
  155. while (GetMessage(&msg, NULL, 0, 0))
  156. {
  157. if (!IsDialogMessage(hwndDlg,&msg))
  158. {
  159. TranslateMessage(&msg);
  160. DispatchMessage(&msg);
  161. }
  162. }
  163. }
  164. if (SUCCEEDED(hrCoInitialize))
  165. CoUninitialize();
  166. #ifdef _DEBUG
  167. --g_ThreadCount;
  168. #endif // _DEBUG
  169. ReleaseOneStopLifetime(FALSE /* !External */);
  170. return 0;
  171. }
  172. //+---------------------------------------------------------------------------
  173. //
  174. // Function: FindDialog, private
  175. //
  176. // Synopsis: Looks to see if there is an existing dialog
  177. // matching the type and clsid. If not and fCreate is true a
  178. // new dialog will be made. If fCreate is false
  179. // and no dialog is found S_FALSE will be returned.
  180. //
  181. // Arguments: [rclcisd] - clsid of choice dialog
  182. // [fCreate] - If true and no choice dialog found a new one will
  183. // be created.
  184. // [nCmdShow] - How to Create the dialog
  185. // [pChoiceDlg] - On Success is a pointer to the new Choice Dialog.
  186. //
  187. // Returns: Appropriate return codes.
  188. //
  189. //
  190. // Modifies:
  191. //
  192. // History: 17-Feb-98 rogerg Created.
  193. //
  194. //----------------------------------------------------------------------------
  195. STDAPI FindDialog(DLGTYPE dlgType,REFCLSID rclsid,BOOL fCreate,int nCmdShow,CBaseDlg **pDlg)
  196. {
  197. DLGLISTITEM *pDlgListItem;
  198. HWND hwnd = NULL;
  199. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  200. *pDlg = NULL;
  201. cCritSect.Enter();
  202. pDlgListItem = g_ObjectMgrData.DlgList;
  203. // look for existing.
  204. while (pDlgListItem)
  205. {
  206. if (rclsid == pDlgListItem->clsid
  207. && dlgType == pDlgListItem->dlgType)
  208. {
  209. break;
  210. }
  211. pDlgListItem = pDlgListItem->pDlgNextListItem;
  212. }
  213. if (pDlgListItem)
  214. {
  215. Assert((pDlgListItem->cRefs > 0) || (pDlgListItem->cLocks > 0) );
  216. ++pDlgListItem->cRefs;
  217. *pDlg = pDlgListItem->pDlg;
  218. }
  219. // didn't find a match if fCreate is set then try to create one.
  220. if (TRUE == fCreate && NULL == *pDlg)
  221. {
  222. CBaseDlg *pNewDlg;
  223. DLGLISTITEM *pNewDlgListItem;
  224. DWORD dwThreadID;
  225. pNewDlgListItem = (DLGLISTITEM *) ALLOC(sizeof(DLGLISTITEM));
  226. if (NULL != pNewDlgListItem)
  227. {
  228. HRESULT hr;
  229. HANDLE hThread;
  230. cCritSect.Leave();
  231. hr = CreateDlgThread(dlgType,rclsid,nCmdShow,&pNewDlg,&dwThreadID,&hThread);
  232. cCritSect.Enter();
  233. if (NOERROR == hr )
  234. {
  235. // its possible that while we had the lock count released a request
  236. // for the same dialog came through so rescan to make sure we
  237. // don't have a match
  238. pDlgListItem = g_ObjectMgrData.DlgList;
  239. // look for existing.
  240. while (pDlgListItem)
  241. {
  242. if (rclsid == pDlgListItem->clsid
  243. && dlgType == pDlgListItem->dlgType)
  244. {
  245. break;
  246. }
  247. pDlgListItem = pDlgListItem->pDlgNextListItem;
  248. }
  249. // if found a match then incrmement its cRef,
  250. // delete the new one we just created,
  251. // and return a pointer to the one in the list
  252. // else add new dialog to the list.
  253. if (pDlgListItem)
  254. {
  255. // delete our newly create dialog and structure.
  256. CloseHandle(hThread);
  257. FREE(pNewDlgListItem);
  258. pNewDlg->ReleaseDlg(RELEASEDLGCMDID_DESTROY);
  259. // increment found dialog and set the out param
  260. Assert(pDlgListItem->cRefs > 0);
  261. ++pDlgListItem->cRefs;
  262. *pDlg = pDlgListItem->pDlg;
  263. }
  264. else
  265. {
  266. // iniitalize the structure.
  267. pNewDlgListItem->dlgType = dlgType;
  268. pNewDlgListItem->cRefs = 1;
  269. pNewDlgListItem->cLocks = 0;
  270. pNewDlgListItem->clsid = rclsid;
  271. pNewDlgListItem->pDlg = pNewDlg;
  272. pNewDlgListItem->dwThreadID = dwThreadID;
  273. pNewDlgListItem->hThread = hThread;
  274. pNewDlgListItem->fHasReleaseDlgCmdId = FALSE;
  275. pNewDlgListItem->wCommandID = RELEASEDLGCMDID_DEFAULT;
  276. *pDlg = pNewDlg;
  277. // now add to the beginning of the list.
  278. pNewDlgListItem->pDlgNextListItem = g_ObjectMgrData.DlgList;
  279. g_ObjectMgrData.DlgList = pNewDlgListItem;
  280. ++g_ObjectMgrData.LockCountInternal; // increment the LockCount
  281. }
  282. }
  283. else
  284. {
  285. FREE(pNewDlgListItem);
  286. }
  287. }
  288. }
  289. // if found an existing dialog, update the z-Order
  290. if (*pDlg)
  291. {
  292. hwnd = (*pDlg)->GetHwnd();
  293. }
  294. cCritSect.Leave();
  295. if (hwnd)
  296. {
  297. BASEDLG_SHOWWINDOW(hwnd,nCmdShow);
  298. }
  299. return *pDlg ? S_OK : S_FALSE;
  300. }
  301. //+---------------------------------------------------------------------------
  302. //
  303. // Function: AddRefDialog, private
  304. //
  305. // Synopsis: Looks to see if there is an existing dialog
  306. // matching the type and clsid and puts an addref on it.
  307. //
  308. // Arguments:
  309. //
  310. // Returns: Appropriate return codes.
  311. //
  312. //
  313. // Modifies:
  314. //
  315. // History: 17-Feb-98 rogerg Created.
  316. //
  317. //----------------------------------------------------------------------------
  318. STDAPI_(ULONG) AddRefDialog(DLGTYPE dlgType,REFCLSID rclsid,CBaseDlg *pDlg)
  319. {
  320. DLGLISTITEM dlgListDummy;
  321. DLGLISTITEM *pDlgListItem = &dlgListDummy;
  322. ULONG cRefs = 1;
  323. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  324. cCritSect.Enter();
  325. pDlgListItem = g_ObjectMgrData.DlgList;
  326. // look for existing.
  327. while (pDlgListItem)
  328. {
  329. if (rclsid == pDlgListItem->clsid
  330. && dlgType == pDlgListItem->dlgType)
  331. {
  332. break;
  333. }
  334. pDlgListItem = pDlgListItem->pDlgNextListItem;
  335. }
  336. if (pDlgListItem)
  337. {
  338. // since only allow one choice at a time Dlg should always match.
  339. Assert(pDlgListItem->pDlg == pDlg);
  340. cRefs = ++pDlgListItem->cRefs;
  341. }
  342. else
  343. {
  344. cCritSect.Leave();
  345. AssertSz(0,"Addref Called on invalid DLG");
  346. cCritSect.Enter();
  347. }
  348. cCritSect.Leave();
  349. return cRefs;
  350. }
  351. //+---------------------------------------------------------------------------
  352. //
  353. // Function: ReleaseDialog, private
  354. //
  355. // Synopsis: Looks to see if there is an existing dialog
  356. // matching the type and clsid and calls release on it..
  357. //
  358. // Arguments:
  359. //
  360. // Returns: Appropriate return codes.
  361. //
  362. //
  363. // Modifies:
  364. //
  365. // History: 17-Feb-98 rogerg Created.
  366. //
  367. //----------------------------------------------------------------------------
  368. STDAPI_(ULONG) ReleaseDialog(DLGTYPE dlgType,REFCLSID rclsid,CBaseDlg *pDlg,BOOL fForce)
  369. {
  370. DLGLISTITEM dlgListDummy;
  371. DLGLISTITEM *pDlgListItem = &dlgListDummy;
  372. ULONG cRefs = 0;
  373. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  374. cCritSect.Enter();
  375. pDlgListItem->pDlgNextListItem = g_ObjectMgrData.DlgList;
  376. // look for existing.
  377. while (pDlgListItem->pDlgNextListItem)
  378. {
  379. if (dlgType == pDlgListItem->pDlgNextListItem->dlgType
  380. && rclsid == pDlgListItem->pDlgNextListItem->clsid)
  381. {
  382. DLGLISTITEM *pDlgListMatch;
  383. DWORD cRefs;
  384. pDlgListMatch = pDlgListItem->pDlgNextListItem;
  385. Assert(pDlgListMatch->pDlg == pDlg);
  386. cRefs = --pDlgListMatch->cRefs;
  387. Assert(0 <= ((LONG) cRefs));
  388. // 2/23/98 rogerg changed cLocks to go to zero if
  389. // flocks is set in case the cancel (which is the only button to set force)
  390. // release comes in before a an object that just needs to keep the dialog alive.
  391. if (fForce)
  392. pDlgListMatch->cLocks = 0;
  393. if (0 >= cRefs && (0 == pDlgListMatch->cLocks || fForce) )
  394. {
  395. HANDLE hThread;
  396. // remove the item from the list.
  397. pDlgListItem->pDlgNextListItem = pDlgListMatch->pDlgNextListItem;
  398. g_ObjectMgrData.DlgList = dlgListDummy.pDlgNextListItem;
  399. cCritSect.Leave();
  400. // we should have always set the callback
  401. Assert(TRUE == pDlgListMatch->fHasReleaseDlgCmdId);
  402. pDlgListMatch->pDlg->ReleaseDlg(pDlgListMatch->wCommandID);
  403. pDlgListMatch->fHasReleaseDlgCmdId = FALSE;
  404. hThread = pDlgListMatch->hThread;
  405. FREE(pDlgListMatch);
  406. ReleaseOneStopLifetime(FALSE /* !External */); // release the ServerCount
  407. CloseHandle(hThread);
  408. }
  409. else
  410. {
  411. cCritSect.Leave();
  412. }
  413. return cRefs;
  414. }
  415. pDlgListItem = pDlgListItem->pDlgNextListItem;
  416. }
  417. // if got here and didn't find let us know
  418. Assert(0);
  419. cCritSect.Leave();
  420. return cRefs; // we return zero if can't find the item.
  421. }
  422. //+---------------------------------------------------------------------------
  423. //
  424. // Function: SetReleaseDlgCmdId, private
  425. //
  426. // Synopsis: Sets the releaseCmdId for the specified dialog.
  427. //
  428. // Arguments:
  429. //
  430. // Returns: Appropriate return codes.
  431. //
  432. //
  433. // Modifies:
  434. //
  435. // History: 17-Feb-98 rogerg Created.
  436. //
  437. //----------------------------------------------------------------------------
  438. STDAPI SetReleaseDlgCmdId(DLGTYPE dlgType,REFCLSID rclsid,CBaseDlg *pDlg,WORD wCommandId)
  439. {
  440. HRESULT hr;
  441. DLGLISTITEM *pDlgListItem;
  442. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  443. cCritSect.Enter();
  444. pDlgListItem = g_ObjectMgrData.DlgList;
  445. // look for existing.
  446. while (pDlgListItem)
  447. {
  448. if (rclsid == pDlgListItem->clsid
  449. && dlgType == pDlgListItem->dlgType)
  450. {
  451. // should only ever be one choice dialog in the list
  452. Assert(pDlg == pDlgListItem->pDlg);
  453. // if there is already a cmdId associated don't replace it
  454. pDlgListItem->fHasReleaseDlgCmdId = TRUE;
  455. pDlgListItem->wCommandID = wCommandId;
  456. hr = NOERROR;
  457. cCritSect.Leave();
  458. return hr;
  459. }
  460. pDlgListItem = pDlgListItem->pDlgNextListItem;
  461. }
  462. cCritSect.Leave();
  463. Assert(0); // object wasn't found for some reason.
  464. return E_UNEXPECTED;
  465. }
  466. //+---------------------------------------------------------------------------
  467. //
  468. // Function: FindChoiceDialog, public
  469. //
  470. // Synopsis: Looks to see if there is an existing choice dialog
  471. // matching the clsid. If not and fCreate is true a
  472. // new choice dialog will be made. If fCreate is false
  473. // and no dialog is found S_FALSE will be returned.
  474. //
  475. // Arguments: [rclcisd] - clsid of choice dialog
  476. // [fCreate] - If true and no choice dialog found a new one will
  477. // be created.
  478. // [nCmdShow] - How to Create the dialog
  479. // [pChoiceDlg] - On Success is a pointer to the new Choice Dialog.
  480. //
  481. // Returns: Appropriate return codes.
  482. //
  483. //
  484. // Modifies:
  485. //
  486. // History: 17-Nov-97 rogerg Created.
  487. //
  488. //----------------------------------------------------------------------------
  489. STDAPI FindChoiceDialog(REFCLSID rclsid,BOOL fCreate,int nCmdShow,CChoiceDlg **pChoiceDlg)
  490. {
  491. return FindDialog(DLGTYPE_CHOICE,rclsid,fCreate,nCmdShow,(CBaseDlg**) pChoiceDlg);
  492. }
  493. //+---------------------------------------------------------------------------
  494. //
  495. // Function: ReleaseChoiceDialog, public
  496. //
  497. // Synopsis: Releases the ChoiceDialog matching the clsid
  498. // and Dialog Ptr. If it finds a match, and the
  499. // refcount decrements to zero the dialog if first
  500. // removed from the list and then its ReleaseDlg
  501. // method is called.
  502. //
  503. // Arguments: [rclcisd] - clsid of choice dialog
  504. // [pChoiceDlg] - Ptr to the Choice dialog
  505. //
  506. // Returns: Appropriate return codes.
  507. //
  508. //
  509. // Modifies:
  510. //
  511. // History: 17-Nov-97 rogerg Created.
  512. //
  513. //----------------------------------------------------------------------------
  514. STDAPI_(ULONG) ReleaseChoiceDialog(REFCLSID rclsid,CChoiceDlg *pChoiceDlg)
  515. {
  516. return ReleaseDialog(DLGTYPE_CHOICE,rclsid,pChoiceDlg,FALSE);
  517. }
  518. //+---------------------------------------------------------------------------
  519. //
  520. // Function: AddRefChoiceDialog, public
  521. //
  522. // Synopsis: puts an Addref of the choice dialog
  523. //
  524. // Arguments: [rclsid] - Identifies the choice dialog
  525. // [pChoiceDlg] - Ptr to the choice dialog
  526. //
  527. // Returns: New Reference count
  528. //
  529. //
  530. // Modifies:
  531. //
  532. // History: 17-Nov-97 rogerg Created.
  533. //
  534. //----------------------------------------------------------------------------
  535. STDAPI_(ULONG) AddRefChoiceDialog(REFCLSID rclsid,CChoiceDlg *pChoiceDlg)
  536. {
  537. return AddRefDialog(DLGTYPE_CHOICE,rclsid,pChoiceDlg);
  538. }
  539. //+---------------------------------------------------------------------------
  540. //
  541. // Function: SetChoiceReleaseDlgCmdId, public
  542. //
  543. // Synopsis: Sets the CommandId to be used inthe
  544. // ReleaseDlg is call when the dialog is destroyed.
  545. //
  546. // Arguments: [rclcisd] - clsid of choice dialog
  547. // [pChoiceDlg] - Ptr to the Choice dialog
  548. // [wCommandId] - CommandId to pass to ReleaseDlg
  549. //
  550. // Returns: Appropriate return codes.
  551. //
  552. //
  553. // Modifies:
  554. //
  555. // History: 17-Nov-97 rogerg Created.
  556. //
  557. //----------------------------------------------------------------------------
  558. STDAPI SetChoiceReleaseDlgCmdId(REFCLSID rclsid,CChoiceDlg *pChoiceDlg,WORD wCommandId)
  559. {
  560. return SetReleaseDlgCmdId(DLGTYPE_CHOICE,rclsid,pChoiceDlg,wCommandId);
  561. }
  562. //+---------------------------------------------------------------------------
  563. //
  564. // Function: FindProgressDialog, public
  565. //
  566. // Synopsis: Looks to see if there is an existing progress dialog.
  567. // If not and fCreate is true a new progress dialog will be made.
  568. // If fCreate is false and no dialog is found S_FALSE will be returned.
  569. //
  570. // Arguments: [fCreate] - If true and no choice dialog found a new one will
  571. // be created.
  572. // [nCmdShow] - How to display the dialog
  573. // [pProgressDlg] - On Success is a pointer to the new Progress Dialog.
  574. //
  575. // Returns: Appropriate return codes.
  576. //
  577. //
  578. // Modifies:
  579. //
  580. // History: 17-Nov-97 rogerg Created.
  581. //
  582. //----------------------------------------------------------------------------
  583. STDAPI FindProgressDialog(REFCLSID rclsid,BOOL fCreate,int nCmdShow,CProgressDlg **pProgressDlg)
  584. {
  585. return FindDialog(DLGTYPE_PROGRESS,rclsid,fCreate,nCmdShow,(CBaseDlg **) pProgressDlg);
  586. }
  587. //+---------------------------------------------------------------------------
  588. //
  589. // Function: ReleaseProgressDialog, public
  590. //
  591. // Synopsis: Releases the Progress dialog matching the Dialog Ptr.
  592. // If it finds a match, and the
  593. // refcount decrements to zero the dialog if first
  594. // removed from the list and then its ReleaseDlg
  595. // method is called.
  596. //
  597. // Arguments: [fForce] - if refs gos to zero releases the dialog
  598. // even if there is a lock on it.
  599. // [pProgressDlg] - Ptr to the Progress dialog
  600. //
  601. // Returns: New Reference count.
  602. //
  603. //
  604. // Modifies:
  605. //
  606. // History: 17-Nov-97 rogerg Created.
  607. //
  608. //----------------------------------------------------------------------------
  609. STDAPI_(ULONG) ReleaseProgressDialog(REFCLSID rclsid,CProgressDlg *pProgressDlg,BOOL fForce)
  610. {
  611. return ReleaseDialog(DLGTYPE_PROGRESS,rclsid,pProgressDlg,fForce);
  612. }
  613. //+---------------------------------------------------------------------------
  614. //
  615. // Function: AddRefProgressDialog, public
  616. //
  617. // Synopsis: puts an Addref of the progress dialog
  618. //
  619. // Arguments: [fForce] - if refs gos to zero releases the dialog
  620. // even if there is a lock on it.
  621. // [pProgressDlg] - Ptr to the Progress dialog
  622. //
  623. // Returns: New Reference count
  624. //
  625. //
  626. // Modifies:
  627. //
  628. // History: 17-Nov-97 rogerg Created.
  629. //
  630. //----------------------------------------------------------------------------
  631. STDAPI_(ULONG) AddRefProgressDialog(REFCLSID clsid,CProgressDlg *pProgressDlg)
  632. {
  633. return AddRefDialog(DLGTYPE_PROGRESS,clsid,pProgressDlg);
  634. }
  635. //+---------------------------------------------------------------------------
  636. //
  637. // Function: SetProgressReleaseDlgCmdId, public
  638. //
  639. // Synopsis: Sets the Callback for the Progress dialog that
  640. // is called when the Progress dialog has been removed
  641. // from the list.
  642. //
  643. // Arguments: [pProgressDlg] - Ptr to the Progress dialog
  644. // [wCommandId] - CommandId to pass to ReleaseDlg
  645. //
  646. // Returns: Appropriate Error codes
  647. //
  648. //
  649. // Modifies:
  650. //
  651. // History: 17-Nov-97 rogerg Created.
  652. //
  653. //----------------------------------------------------------------------------
  654. STDAPI SetProgressReleaseDlgCmdId(REFCLSID clsid,CProgressDlg *pProgressDlg,WORD wCommandId)
  655. {
  656. return SetReleaseDlgCmdId(DLGTYPE_PROGRESS,clsid,pProgressDlg,wCommandId);
  657. }
  658. //+---------------------------------------------------------------------------
  659. //
  660. // Function: LockProgressDialog, public
  661. //
  662. // Synopsis: Add/Removes Lock on the Progress Dialog.
  663. // When there is a lock on the Progress Dialog
  664. // it won't go away when the reference count
  665. // goes to zero.
  666. //
  667. // !!Dialog will not go away if lock count
  668. // goes to zero even if cRefs are currently zero
  669. //
  670. //
  671. // Arguments: [pProgressDlg] - Ptr to the Progress dialog
  672. // [fLock] - BOOL whether to lock/unlocK
  673. //
  674. // Returns: Appropriate Error codes
  675. //
  676. //
  677. // Modifies:
  678. //
  679. // History: 17-Nov-97 rogerg Created.
  680. // History 09-Dec-98 rogerg Change so lock was a bool instead of refcount
  681. // to have same behavior as release with force flag
  682. //
  683. //----------------------------------------------------------------------------
  684. STDAPI LockProgressDialog(REFCLSID clsid,CProgressDlg *pProgressDlg,BOOL fLock)
  685. {
  686. HRESULT hr = S_FALSE;
  687. DLGLISTITEM *pDlgListItem;
  688. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  689. cCritSect.Enter();
  690. pDlgListItem = g_ObjectMgrData.DlgList;
  691. // look for existing.
  692. while (pDlgListItem)
  693. {
  694. if (DLGTYPE_PROGRESS == pDlgListItem->dlgType
  695. && clsid == pDlgListItem->clsid)
  696. {
  697. break;
  698. }
  699. pDlgListItem = pDlgListItem->pDlgNextListItem;
  700. }
  701. if (pDlgListItem)
  702. {
  703. if (fLock)
  704. {
  705. pDlgListItem->cLocks = 1;
  706. }
  707. else
  708. {
  709. pDlgListItem->cLocks = 0;
  710. }
  711. hr = S_OK;
  712. }
  713. else
  714. {
  715. AssertSz(0,"Dialog Not found in Lock");
  716. }
  717. cCritSect.Leave();
  718. return hr;
  719. }
  720. //+---------------------------------------------------------------------------
  721. //
  722. // Function: ShowOptionsDialog, public
  723. //
  724. // Synopsis: Displays the options dialog. If one is already displayed
  725. // it just brings it to the foreground.
  726. //
  727. // Arguments: [hwndParent] - Use as parent if dialog doesn't already exist
  728. //
  729. // Returns: Appropriate Error codes
  730. //
  731. //
  732. // Modifies:
  733. //
  734. // History: 24-Nov-97 rogerg Created.
  735. //
  736. //----------------------------------------------------------------------------
  737. STDAPI ShowOptionsDialog(HWND hwndParent)
  738. {
  739. DlgSettingsArgs ThreadArgs;
  740. HRESULT hr = E_FAIL;
  741. HANDLE hNewThread = NULL;
  742. DWORD dwThreadId;
  743. ThreadArgs.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
  744. if (ThreadArgs.hEvent)
  745. {
  746. ThreadArgs.hwndParent = hwndParent;
  747. ThreadArgs.dwParentThreadId = GetCurrentThreadId();
  748. hr = NOERROR;
  749. hNewThread = CreateThread(NULL,0,SettingsThread,&ThreadArgs,0,&dwThreadId);
  750. if (hNewThread)
  751. {
  752. WaitForSingleObject(ThreadArgs.hEvent,INFINITE);
  753. CloseHandle(hNewThread); // we'll let the thread take care of itself
  754. }
  755. CloseHandle(ThreadArgs.hEvent);
  756. }
  757. return hr;
  758. }
  759. //+---------------------------------------------------------------------------
  760. //
  761. // Function: SettingsThread, private
  762. //
  763. // Synopsis: Worker thread for displaying the settings dialog.
  764. //
  765. // Arguments:
  766. //
  767. // Returns:
  768. //
  769. //
  770. // Modifies:
  771. //
  772. // History: 24-Nov-97 rogerg Created.
  773. //
  774. //----------------------------------------------------------------------------
  775. DWORD WINAPI SettingsThread( LPVOID lpArg )
  776. {
  777. DlgSettingsArgs *pThreadArgs = (DlgSettingsArgs *) lpArg;
  778. HWND hwndParent;
  779. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  780. hwndParent = pThreadArgs->hwndParent;
  781. // see if we are already in a DisplayOptions Dialog
  782. // and if so just return,
  783. AddRefOneStopLifetime(FALSE /* !External */);
  784. // Increment settings ref count
  785. cCritSect.Enter();
  786. ++g_ObjectMgrData.dwSettingsLockCount;
  787. cCritSect.Leave();
  788. // attach the thread input with the creating thread so focus works correctly.
  789. AttachThreadInput(GetCurrentThreadId(),pThreadArgs->dwParentThreadId,TRUE);
  790. // let the caller know the thread is done initializing.
  791. if (pThreadArgs->hEvent)
  792. SetEvent(pThreadArgs->hEvent);
  793. DisplayOptions(hwndParent); // exported in the OneStop Dll.
  794. // decrement the settings lock count
  795. cCritSect.Enter();
  796. --g_ObjectMgrData.dwSettingsLockCount;
  797. cCritSect.Leave();
  798. ReleaseOneStopLifetime(FALSE /* !External */);
  799. return 0;
  800. }
  801. //+---------------------------------------------------------------------------
  802. //
  803. // Function: RegisterOneStopCLSIDs, private
  804. //
  805. // Synopsis: Registers the Clsids associated with the OneStop app
  806. //
  807. // Arguments:
  808. //
  809. // Returns: Appropriate Error codes
  810. //
  811. //
  812. // Modifies:
  813. //
  814. // History: 17-Nov-97 rogerg Created.
  815. //
  816. //----------------------------------------------------------------------------
  817. STDAPI RegisterOneStopCLSIDs()
  818. {
  819. LPCLASSFACTORY pClassFact;
  820. HRESULT hr = E_OUTOFMEMORY;
  821. pClassFact = (LPCLASSFACTORY) new CClassFactory();
  822. if (pClassFact)
  823. {
  824. hr = CoRegisterClassObject(CLSID_SyncMgrp,pClassFact,CLSCTX_LOCAL_SERVER,
  825. REGCLS_MULTIPLEUSE,&g_ObjectMgrData.dwRegClassFactCookie);
  826. if (NOERROR != hr)
  827. {
  828. // on longon the rpc server may not yet be available and on
  829. // logoff we get the wrong server identity. Don't assert on these
  830. // since we know about the cases.
  831. if (HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) != hr
  832. && CO_E_WRONG_SERVER_IDENTITY != hr)
  833. {
  834. AssertSz(0,"Class Factory Registration failed");
  835. }
  836. g_ObjectMgrData.dwRegClassFactCookie = 0;
  837. }
  838. else
  839. {
  840. g_ObjectMgrData.fRegClassFactCookieValid = TRUE;
  841. }
  842. pClassFact->Release(); // Release our reference on the ClassFactory.
  843. }
  844. return hr;
  845. }
  846. //+---------------------------------------------------------------------------
  847. //
  848. // Function: MakeWinstaDesktopName, public
  849. //
  850. // Synopsis: Stole main code from Ole32 remote.cxx to generate
  851. // a unique eventName based on session and desktop..
  852. // Arguments:
  853. //
  854. // Returns: Appropriate Error codes
  855. //
  856. // Modifies:
  857. //
  858. // History: 18-Dec-98 rogerg Created.
  859. //
  860. //----------------------------------------------------------------------------
  861. STDAPI MakeWinstaDesktopName(LPCWSTR pszPreceding,LPWSTR *ppszResultString)
  862. {
  863. HWINSTA hWinsta;
  864. HDESK hDesk;
  865. WCHAR wszWinsta[32];
  866. WCHAR wszDesktop[32];
  867. LPWSTR pwszWinsta;
  868. LPWSTR pwszDesktop;
  869. LPWSTR _pwszWinstaDesktop; // out param
  870. DWORD Length;
  871. BOOL Status;
  872. HRESULT hr;
  873. DWORD dwResult;
  874. DWORD dwPrecedingSize;
  875. if (!ppszResultString)
  876. {
  877. Assert(ppszResultString);
  878. return E_INVALIDARG;
  879. }
  880. *ppszResultString = NULL;;
  881. // if not on flavor of NT return an error
  882. if (VER_PLATFORM_WIN32_NT != g_OSVersionInfo.dwPlatformId)
  883. {
  884. AssertSz(0,"MakeWinstaDesktopName called on unsupported platform");
  885. return E_FAIL;
  886. }
  887. hWinsta = GetProcessWindowStation();
  888. if ( ! hWinsta )
  889. return HRESULT_FROM_WIN32(GetLastError());
  890. hDesk = GetThreadDesktop(GetCurrentThreadId());
  891. if ( ! hDesk )
  892. return HRESULT_FROM_WIN32(GetLastError());
  893. pwszWinsta = wszWinsta;
  894. pwszDesktop = wszDesktop;
  895. Length = sizeof(wszWinsta);
  896. Status = GetUserObjectInformation(
  897. hWinsta,
  898. UOI_NAME,
  899. pwszWinsta,
  900. Length,
  901. &Length );
  902. if ( ! Status )
  903. {
  904. dwResult = GetLastError();
  905. if ( ERROR_INSUFFICIENT_BUFFER != dwResult)
  906. {
  907. hr = HRESULT_FROM_WIN32(dwResult);
  908. goto WinstaDesktopExit;
  909. }
  910. pwszWinsta = (LPWSTR) ALLOC( Length );
  911. if ( ! pwszWinsta )
  912. {
  913. hr = E_OUTOFMEMORY;
  914. goto WinstaDesktopExit;
  915. }
  916. Status = GetUserObjectInformation(
  917. hWinsta,
  918. UOI_NAME,
  919. pwszWinsta,
  920. Length,
  921. &Length );
  922. if ( ! Status )
  923. {
  924. hr = HRESULT_FROM_WIN32(GetLastError());
  925. goto WinstaDesktopExit;
  926. }
  927. }
  928. Length = sizeof(wszDesktop);
  929. Status = GetUserObjectInformation(
  930. hDesk,
  931. UOI_NAME,
  932. pwszDesktop,
  933. Length,
  934. &Length );
  935. if ( ! Status )
  936. {
  937. dwResult = GetLastError();
  938. if ( dwResult != ERROR_INSUFFICIENT_BUFFER )
  939. {
  940. hr = HRESULT_FROM_WIN32(dwResult);
  941. goto WinstaDesktopExit;
  942. }
  943. pwszDesktop = (LPWSTR) ALLOC( Length );
  944. if ( ! pwszDesktop )
  945. {
  946. hr = E_OUTOFMEMORY;
  947. goto WinstaDesktopExit;
  948. }
  949. Status = GetUserObjectInformation(
  950. hDesk,
  951. UOI_NAME,
  952. pwszDesktop,
  953. Length,
  954. &Length );
  955. if ( ! Status )
  956. {
  957. hr = HRESULT_FROM_WIN32(GetLastError());
  958. goto WinstaDesktopExit;
  959. }
  960. }
  961. dwPrecedingSize = pszPreceding ? lstrlen(pszPreceding) + 1 : 0;
  962. _pwszWinstaDesktop =
  963. (WCHAR *) ALLOC( (dwPrecedingSize
  964. + lstrlen(pwszWinsta) + 1
  965. + lstrlen(pwszDesktop) + 1) * sizeof(WCHAR) );
  966. if ( _pwszWinstaDesktop )
  967. {
  968. *_pwszWinstaDesktop = NULL;
  969. if (pszPreceding)
  970. {
  971. lstrcat(_pwszWinstaDesktop,pszPreceding);
  972. lstrcat( _pwszWinstaDesktop, L"_" );
  973. }
  974. lstrcat(_pwszWinstaDesktop, pwszWinsta );
  975. lstrcat( _pwszWinstaDesktop, L"_" );
  976. lstrcat(_pwszWinstaDesktop, pwszDesktop );
  977. hr = NOERROR;
  978. }
  979. else
  980. {
  981. hr = E_OUTOFMEMORY;
  982. }
  983. WinstaDesktopExit:
  984. if ( pwszWinsta != wszWinsta )
  985. {
  986. FREE( pwszWinsta );
  987. }
  988. if ( pwszDesktop != wszDesktop )
  989. {
  990. FREE( pwszDesktop );
  991. }
  992. if (NOERROR == hr)
  993. {
  994. *ppszResultString = _pwszWinstaDesktop;
  995. }
  996. return hr;
  997. }
  998. //+---------------------------------------------------------------------------
  999. //
  1000. // Function: RegisterOneStopClassFactory, public
  1001. //
  1002. // Synopsis: Handles the ClassFactory registration
  1003. // along with the associated race conditions.
  1004. //
  1005. // if class factory isn't already registered, then go ahead and register now.
  1006. // there is the case the between the time we see if there is a class factory
  1007. // and the CoCreateInstance is called it could go away. If this happens, another
  1008. // instance of Onestop.exe is launched and everything will work properly.
  1009. // Arguments: [fForce] - When true the ClassFactory is registered even if there
  1010. // is an existing event object.
  1011. //
  1012. // Returns: Appropriate Error codes
  1013. //
  1014. // Modifies:
  1015. //
  1016. // History: 17-Nov-97 rogerg Created.
  1017. //
  1018. //----------------------------------------------------------------------------
  1019. const WCHAR SZ_CFACTORYEVENTNAME[] = TEXT("{6295DF2D-35EE-11d1-8707-00C04FD93327}CFactEvent");
  1020. STDAPI RegisterOneStopClassFactory(BOOL fForce)
  1021. {
  1022. HRESULT hr = NOERROR; // only report error is actual call to register CFact Failed.
  1023. LPWSTR pEventName;
  1024. BOOL fExistingInstance = FALSE;
  1025. if (( VER_PLATFORM_WIN32_NT != g_OSVersionInfo.dwPlatformId)
  1026. || (NOERROR != MakeWinstaDesktopName(SZ_CFACTORYEVENTNAME,&pEventName)) )
  1027. {
  1028. pEventName = (LPWSTR) SZ_CFACTORYEVENTNAME;
  1029. }
  1030. // this should only ever be called on MainThread so don't
  1031. // need to lock
  1032. Assert(g_ObjectMgrData.dwMainThreadID == GetCurrentThreadId());
  1033. Assert(NULL == g_ObjectMgrData.hClassRegisteredEvent);
  1034. g_ObjectMgrData.hClassRegisteredEvent = CreateEvent(NULL,TRUE,FALSE,pEventName);
  1035. Assert(g_ObjectMgrData.hClassRegisteredEvent);
  1036. // if got the event and not a force see if there is an existing instance.
  1037. if (g_ObjectMgrData.hClassRegisteredEvent && !fForce)
  1038. {
  1039. if (ERROR_ALREADY_EXISTS == GetLastError())
  1040. {
  1041. // object already existed and the force flag isn't set
  1042. // it means we can use the existing registered object.
  1043. CloseHandle(g_ObjectMgrData.hClassRegisteredEvent);
  1044. g_ObjectMgrData.hClassRegisteredEvent = NULL;
  1045. hr = NOERROR;
  1046. fExistingInstance = TRUE;
  1047. }
  1048. }
  1049. // If fForce is set or these isn't an existing class
  1050. // go ahead and register.
  1051. if (fForce || (!fExistingInstance && g_ObjectMgrData.hClassRegisteredEvent))
  1052. {
  1053. // force on an event already existing is a state that
  1054. // should only occur if EXE was launched twice with the embedding flag.
  1055. // This shouldn't happen under normal conditions so assert.
  1056. // so we can catch any cases that we didn't get the event
  1057. // and the force flag is set.
  1058. Assert(g_ObjectMgrData.hClassRegisteredEvent);
  1059. hr = RegisterOneStopCLSIDs();
  1060. if (NOERROR != hr)
  1061. {
  1062. if (g_ObjectMgrData.hClassRegisteredEvent)
  1063. {
  1064. CloseHandle(g_ObjectMgrData.hClassRegisteredEvent);
  1065. g_ObjectMgrData.hClassRegisteredEvent = NULL;
  1066. }
  1067. }
  1068. }
  1069. if (pEventName && (SZ_CFACTORYEVENTNAME != pEventName))
  1070. {
  1071. FREE(pEventName);
  1072. }
  1073. return hr;
  1074. }
  1075. //+---------------------------------------------------------------------------
  1076. //
  1077. // Function: AddRefOneStopLifetime, public
  1078. //
  1079. // Synopsis: Adds a Reference to the applications
  1080. // Arguments:
  1081. //
  1082. // Returns: New total Reference count including both
  1083. // internal and external locks.
  1084. //
  1085. // Modifies:
  1086. //
  1087. // History: 17-Nov-97 rogerg Created.
  1088. //
  1089. //----------------------------------------------------------------------------
  1090. STDAPI_(ULONG) AddRefOneStopLifetime(BOOL fExternal)
  1091. {
  1092. DWORD cRefs;
  1093. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1094. // Increment ref count
  1095. cCritSect.Enter();
  1096. if (fExternal)
  1097. {
  1098. ++g_ObjectMgrData.LockCountExternal;
  1099. }
  1100. else
  1101. {
  1102. ++g_ObjectMgrData.LockCountInternal;
  1103. }
  1104. cRefs = g_ObjectMgrData.LockCountExternal + g_ObjectMgrData.LockCountInternal;
  1105. cCritSect.Leave();
  1106. Assert(0 < cRefs);
  1107. return cRefs;
  1108. }
  1109. //+---------------------------------------------------------------------------
  1110. //
  1111. // Function: ReleaseOneStopLifetime, public
  1112. //
  1113. // Synopsis: Releases a Reference to the applications
  1114. // If the refcount goes to zero the classfactory
  1115. // is revoked an a quit message is posted to the
  1116. // main thread
  1117. //
  1118. // Arguments:
  1119. //
  1120. // Returns: New Reference count including internal and
  1121. // external locks.
  1122. //
  1123. // Modifies:
  1124. //
  1125. // History: 17-Nov-97 rogerg Created.
  1126. //
  1127. //----------------------------------------------------------------------------
  1128. STDAPI_(ULONG) ReleaseOneStopLifetime(BOOL fExternal)
  1129. {
  1130. DWORD cRefsExternal;
  1131. DWORD cRefsInternal;
  1132. BOOL fForceClose;
  1133. DLGLISTITEM *pDlgListItem;
  1134. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1135. cCritSect.Enter();
  1136. if (fExternal)
  1137. {
  1138. --g_ObjectMgrData.LockCountExternal;
  1139. }
  1140. else
  1141. {
  1142. --g_ObjectMgrData.LockCountInternal;
  1143. }
  1144. cRefsInternal = g_ObjectMgrData.LockCountInternal;
  1145. cRefsExternal = g_ObjectMgrData.LockCountExternal;
  1146. fForceClose = g_ObjectMgrData.fCloseAll;
  1147. pDlgListItem = g_ObjectMgrData.DlgList;
  1148. Assert(0 <= ((LONG) cRefsInternal));
  1149. Assert(0 <= ((LONG) cRefsExternal));
  1150. if( (0 >= cRefsInternal)
  1151. && (0 >= cRefsExternal || fForceClose)
  1152. && (FALSE == g_ObjectMgrData.fDead) )
  1153. {
  1154. HANDLE hRegisteredEvent;
  1155. HWND hwndMainThreadMsg;
  1156. DWORD dwRegClassFactCookie;
  1157. BOOL fRegClassFactCookieValid;
  1158. Assert(0 == pDlgListItem); // all dialogs should have been released.
  1159. Assert(0 == g_ObjectMgrData.dwSettingsLockCount); // settings dialogs should be gone.
  1160. g_ObjectMgrData.fDead = TRUE;
  1161. hRegisteredEvent = g_ObjectMgrData.hClassRegisteredEvent;
  1162. g_ObjectMgrData.hClassRegisteredEvent = NULL;
  1163. hwndMainThreadMsg = g_ObjectMgrData.hWndMainThreadMsg;
  1164. g_ObjectMgrData.hWndMainThreadMsg = NULL;
  1165. dwRegClassFactCookie = g_ObjectMgrData.dwRegClassFactCookie;
  1166. g_ObjectMgrData.dwRegClassFactCookie = 0;
  1167. fRegClassFactCookieValid = g_ObjectMgrData.fRegClassFactCookieValid;
  1168. g_ObjectMgrData.fRegClassFactCookieValid = FALSE;
  1169. cCritSect.Leave();
  1170. if (NULL != hRegisteredEvent)
  1171. {
  1172. CloseHandle(hRegisteredEvent); // release our registration event.
  1173. }
  1174. // we need to revoke the classfactory on the thread that registered it.
  1175. // Send a message back to the thread that registered the event.
  1176. if (fRegClassFactCookieValid)
  1177. {
  1178. SendMessage(hwndMainThreadMsg,WM_CFACTTHREAD_REVOKE,dwRegClassFactCookie,0);
  1179. }
  1180. // if lockcount is still zero then post the quitmessage
  1181. // else someone came in during our revoke and we
  1182. // need to wait for the refcount to hit zero again.
  1183. cCritSect.Enter();
  1184. cRefsInternal = g_ObjectMgrData.LockCountInternal;
  1185. cRefsExternal = g_ObjectMgrData.LockCountExternal;
  1186. if ( (0 >= cRefsInternal)
  1187. && (0 >= cRefsExternal || fForceClose) )
  1188. {
  1189. DWORD dwMainThreadID;
  1190. HANDLE hThread = NULL;
  1191. dwMainThreadID = g_ObjectMgrData.dwMainThreadID;
  1192. // its possible the quite is occuring on a thread other than
  1193. // the main thread. If this is the case send the handle of the thread
  1194. // along with the quit message to the main thread can wait for this
  1195. // thread to exit.
  1196. #ifdef _THREADSHUTDOWN
  1197. if (dwMainThreadID != GetCurrentThreadId())
  1198. {
  1199. HANDLE hCurThread;
  1200. HANDLE hProcess;
  1201. hCurThread = GetCurrentThread();
  1202. hProcess = GetCurrentProcess();
  1203. if (!DuplicateHandle(hProcess,hCurThread,hProcess,&hThread,
  1204. 0,FALSE,DUPLICATE_SAME_ACCESS) )
  1205. {
  1206. hThread = NULL; // don't rely on DupHandle to set this to null on error.
  1207. }
  1208. }
  1209. #endif // _THREADSHUTDOWN
  1210. // shut down the main thread
  1211. cCritSect.Leave();
  1212. PostMessage(hwndMainThreadMsg,WM_MAINTHREAD_QUIT,0,(LPARAM) /* hThread */ 0);
  1213. cCritSect.Enter();
  1214. }
  1215. else
  1216. {
  1217. g_ObjectMgrData.fDead = FALSE;
  1218. }
  1219. }
  1220. cCritSect.Leave();
  1221. return (cRefsExternal + cRefsInternal);
  1222. }
  1223. //+---------------------------------------------------------------------------
  1224. //
  1225. // Function: IsOneStopDlgMessage, public
  1226. //
  1227. // Synopsis: Called in messageloop to determine if message
  1228. // should be handled by a dialog
  1229. //
  1230. // Arguments:
  1231. //
  1232. // Returns: TRUE - The item was processed.
  1233. //
  1234. // Modifies:
  1235. //
  1236. // History: 17-Nov-97 rogerg Created.
  1237. //
  1238. //----------------------------------------------------------------------------
  1239. #ifdef _UNUSED
  1240. BOOL IsOneStopDlgMessage(MSG *msg)
  1241. {
  1242. DLGLISTITEM *pDlgListItem;
  1243. DWORD dwThreadID = GetCurrentThreadId();
  1244. CCriticalSection cCritSect(&g_LockCountCriticalSection,dwThreadID);
  1245. HWND hwnd = NULL;
  1246. cCritSect.Enter();
  1247. // see if we have a dialog in this thread.
  1248. pDlgListItem = g_ObjectMgrData.DlgList;
  1249. while (pDlgListItem)
  1250. {
  1251. if (pDlgListItem->pDlg
  1252. && dwThreadID == pDlgListItem->dwThreadID)
  1253. {
  1254. hwnd = pDlgListItem->pDlg->GetHwnd();
  1255. pDlgListItem = pDlgListItem->pDlgNextListItem;
  1256. break;
  1257. }
  1258. pDlgListItem = pDlgListItem->pDlgNextListItem;
  1259. }
  1260. #if DEBUG
  1261. // we should only ever have one registered dialog per thread
  1262. // loop through remaining dialogs and if find a match assert
  1263. while (pDlgListItem)
  1264. {
  1265. if (pDlgListItem->pDlg
  1266. && dwThreadID == pDlgListItem->dwThreadID)
  1267. {
  1268. AssertSz(0,"Multiple dialogs in thread");
  1269. break;
  1270. }
  1271. pDlgListItem = pDlgListItem->pDlgNextListItem;
  1272. }
  1273. #endif // DEBUG
  1274. cCritSect.Leave();
  1275. if (hwnd && IsDialogMessage(hwnd,msg))
  1276. {
  1277. return TRUE;
  1278. }
  1279. return FALSE;
  1280. }
  1281. #endif // _UNUSED
  1282. //+---------------------------------------------------------------------------
  1283. //
  1284. // Function: InitObjectManager, public
  1285. //
  1286. // Synopsis: Must be called from Main thread before any
  1287. // new threads, dialogs are created or the class factory
  1288. // is registered.
  1289. //
  1290. // Arguments:
  1291. //
  1292. // Returns: Appropriate Error Codes.
  1293. //
  1294. // Modifies:
  1295. //
  1296. // History: 17-Nov-97 rogerg Created.
  1297. //
  1298. //----------------------------------------------------------------------------
  1299. STDAPI InitObjectManager(CMsgServiceHwnd *pMsgService)
  1300. {
  1301. // initialize critical section for our lock count.
  1302. InitializeCriticalSection(&g_LockCountCriticalSection);
  1303. g_ObjectMgrData.dwMainThreadID = GetCurrentThreadId();
  1304. g_ObjectMgrData.hWndMainThreadMsg = pMsgService->GetHwnd();
  1305. g_ObjectMgrData.DlgList = NULL;
  1306. g_ObjectMgrData.hClassRegisteredEvent = NULL;
  1307. g_ObjectMgrData.dwRegClassFactCookie = 0;
  1308. g_ObjectMgrData.fRegClassFactCookieValid = FALSE;
  1309. g_ObjectMgrData.LockCountInternal = 0;
  1310. g_ObjectMgrData.LockCountExternal = 0;
  1311. g_ObjectMgrData.fCloseAll = FALSE;
  1312. g_ObjectMgrData.dwSettingsLockCount = 0;
  1313. g_ObjectMgrData.dwHandlerPropertiesLockCount = 0;
  1314. g_ObjectMgrData.fDead = FALSE;
  1315. // Initialize autodial support
  1316. g_ObjectMgrData.eAutoDialState = eQuiescedOff;
  1317. g_ObjectMgrData.fRasAutoDial = FALSE;
  1318. g_ObjectMgrData.fWininetAutoDial = FALSE;
  1319. g_ObjectMgrData.fFirstSyncItem = FALSE;
  1320. g_ObjectMgrData.cNestedStartCalls = 0;
  1321. Assert(NULL != g_ObjectMgrData.hWndMainThreadMsg);
  1322. return NOERROR;
  1323. }
  1324. //+---------------------------------------------------------------------------
  1325. //
  1326. // Function: RequestIdleLock, public
  1327. //
  1328. // Synopsis: request to see if an new Idle can be started.
  1329. //
  1330. // Arguments:
  1331. //
  1332. // Returns: NOERROR - if Idle should be continued
  1333. // S_FALSE - if another Idle is already in progreaa.
  1334. //
  1335. // Modifies:
  1336. //
  1337. // History: 23-Feb-98 rogerg Created.
  1338. //
  1339. //----------------------------------------------------------------------------
  1340. STDAPI RequestIdleLock()
  1341. {
  1342. HRESULT hr;
  1343. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1344. cCritSect.Enter();
  1345. if (g_ObjectMgrData.fIdleHandlerRunning)
  1346. {
  1347. hr = S_FALSE;
  1348. }
  1349. else
  1350. {
  1351. hr = NOERROR;
  1352. g_ObjectMgrData.fIdleHandlerRunning = TRUE;
  1353. }
  1354. cCritSect.Leave();
  1355. return hr;
  1356. }
  1357. //+---------------------------------------------------------------------------
  1358. //
  1359. // Function: ReleaseIdleLock, public
  1360. //
  1361. // Synopsis: Informs ObjectMgr that the Idle is done processing.
  1362. //
  1363. // Arguments:
  1364. //
  1365. // Returns: Appropriate error codes.
  1366. //
  1367. // Modifies:
  1368. //
  1369. // History: 23-Feb-98 rogerg Created.
  1370. //
  1371. //----------------------------------------------------------------------------
  1372. STDAPI ReleaseIdleLock()
  1373. {
  1374. HRESULT hr = NOERROR;
  1375. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1376. cCritSect.Enter();
  1377. // note okay for this to already be FALSE in case progress receives
  1378. // an offidle before release. Call this when idle progress is
  1379. // released as safety in case offidle isn't working properly.
  1380. g_ObjectMgrData.fIdleHandlerRunning = FALSE;
  1381. cCritSect.Leave();
  1382. return hr;
  1383. }
  1384. //+---------------------------------------------------------------------------
  1385. //
  1386. // Function: ObjMgr_HandleQueryEndSession, public
  1387. //
  1388. // Synopsis: Called by main thread so knows how to respond to WN_QUERYENDSESSION.
  1389. //
  1390. // Arguments:
  1391. //
  1392. // Returns: S_OK - if system can shutdown
  1393. // S_FALSE - if hould fail the query. On an S_FALSE the out params
  1394. // are filled, hwnd with parent hwnd of any message box and MessageID
  1395. // with the appropriate messageID to display.
  1396. //
  1397. // Modifies:
  1398. //
  1399. // History: 21-May-98 rogerg Created.
  1400. //
  1401. //----------------------------------------------------------------------------
  1402. STDAPI ObjMgr_HandleQueryEndSession(HWND *phwnd,UINT *puMessageId,BOOL *pfLetUserDecide)
  1403. {
  1404. HRESULT hr = S_OK;
  1405. BOOL fProgressDialog = FALSE;
  1406. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1407. cCritSect.Enter();
  1408. *phwnd = NULL;
  1409. *pfLetUserDecide = FALSE;
  1410. // if there are any settings dialogs then we can't quit
  1411. if (g_ObjectMgrData.dwSettingsLockCount > 0)
  1412. {
  1413. *phwnd = NULL;
  1414. *puMessageId = IDS_SETTINGSQUERYENDSESSION;
  1415. hr = S_FALSE;
  1416. }
  1417. else
  1418. {
  1419. DLGLISTITEM *pDlgListItem;
  1420. BOOL fDontShutdown = FALSE; // set when find match
  1421. HWND hwnd;
  1422. UINT uMessageId;
  1423. BOOL fLetUserDecide;
  1424. // loop through dialogs asking if they can shutdown.
  1425. // first dialog find that doesn't give choice return
  1426. // if the dialog says to let user decide continue looping
  1427. // until hit end or find a dialog that doesn't give choice since
  1428. // not giving choice takes precedence.
  1429. // see if there is a progress dialog other than idle and if so stop the logoff.
  1430. pDlgListItem = g_ObjectMgrData.DlgList;
  1431. // loop through the choice dialogs to see if
  1432. while (pDlgListItem)
  1433. {
  1434. if ( (pDlgListItem->pDlg)
  1435. && (S_FALSE == pDlgListItem->pDlg->QueryCanSystemShutdown(&hwnd,&uMessageId,&fLetUserDecide) ) )
  1436. {
  1437. // if first dialog find we can't shutdown or fLetUserDecide isn't set
  1438. // then upate the out params
  1439. if (!fDontShutdown || !fLetUserDecide)
  1440. {
  1441. *phwnd = hwnd;
  1442. *puMessageId = uMessageId;
  1443. *pfLetUserDecide = fLetUserDecide;
  1444. fProgressDialog = (pDlgListItem->dlgType == DLGTYPE_PROGRESS) ? TRUE : FALSE;
  1445. }
  1446. fDontShutdown = TRUE;
  1447. // if this dialog doesn't allow the use choice then break
  1448. if (!fLetUserDecide)
  1449. {
  1450. break;
  1451. }
  1452. }
  1453. pDlgListItem = pDlgListItem->pDlgNextListItem;
  1454. }
  1455. if (fDontShutdown)
  1456. {
  1457. hr = S_FALSE;
  1458. }
  1459. }
  1460. cCritSect.Leave();
  1461. // if can't shutdown and it is a progress dialog then make sure
  1462. // the dialog is not minimized;
  1463. if (fProgressDialog && (NULL != *phwnd) )
  1464. {
  1465. BASEDLG_SHOWWINDOW(*phwnd,SW_SHOWNORMAL);
  1466. }
  1467. return hr;
  1468. }
  1469. //+---------------------------------------------------------------------------
  1470. //
  1471. // Function: ObjMgr_AddRefHandlerPropertiesLockCount, public
  1472. //
  1473. // Synopsis: Called by choice dialog to change the global lock count
  1474. // of open handler properties dialogs
  1475. //
  1476. // Arguments: dwNumRefs - number of references to increment
  1477. //
  1478. // Returns: Appropriate error codes
  1479. //
  1480. // Modifies:
  1481. //
  1482. // History: 21-May-98 rogerg Created.
  1483. //
  1484. //----------------------------------------------------------------------------
  1485. STDAPI_(ULONG) ObjMgr_AddRefHandlerPropertiesLockCount(DWORD dwNumRefs)
  1486. {
  1487. ULONG cRefs;
  1488. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1489. Assert(0 != dwNumRefs); // catch people passing on 0 since doesn't make sense.
  1490. cCritSect.Enter();
  1491. g_ObjectMgrData.dwHandlerPropertiesLockCount += dwNumRefs;
  1492. cRefs = g_ObjectMgrData.dwHandlerPropertiesLockCount;
  1493. cCritSect.Leave();
  1494. return cRefs;
  1495. }
  1496. //+---------------------------------------------------------------------------
  1497. //
  1498. // Function: ObjMgr_ReleaseHandlerPropertiesLockCount, public
  1499. //
  1500. // Synopsis: Called by choice dialog to change the global lock count
  1501. // of open handler properties dialogs
  1502. //
  1503. // Arguments: dwNumRefs - number of references to decrement
  1504. //
  1505. // Returns: Appropriate error codes
  1506. //
  1507. // Modifies:
  1508. //
  1509. // History: 21-May-98 rogerg Created.
  1510. //
  1511. //----------------------------------------------------------------------------
  1512. STDAPI_(ULONG) ObjMgr_ReleaseHandlerPropertiesLockCount(DWORD dwNumRefs)
  1513. {
  1514. DWORD cRefs;
  1515. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1516. Assert(0 != dwNumRefs); // catch people passing on 0 since doesn't make sense.
  1517. cCritSect.Enter();
  1518. g_ObjectMgrData.dwHandlerPropertiesLockCount -= dwNumRefs;
  1519. cRefs = g_ObjectMgrData.dwHandlerPropertiesLockCount;
  1520. cCritSect.Leave();
  1521. Assert( ((LONG) cRefs) >= 0);
  1522. if ( ((LONG) cRefs) < 0)
  1523. {
  1524. cRefs = 0;
  1525. }
  1526. return cRefs;
  1527. }
  1528. //+---------------------------------------------------------------------------
  1529. //
  1530. // Function: ObjMgr_CloseAll, public
  1531. //
  1532. // Synopsis: Called by main thread when an END_SESSION occurs. Loops throug
  1533. // dialogs posting a close to them
  1534. //
  1535. // Arguments:
  1536. //
  1537. // Returns: Appropriate error codes
  1538. //
  1539. // Modifies:
  1540. //
  1541. // History: 21-May-98 rogerg Created.
  1542. //
  1543. //----------------------------------------------------------------------------
  1544. STDAPI ObjMgr_CloseAll()
  1545. {
  1546. HRESULT hr = S_OK;
  1547. HWND hwndDlg;
  1548. DLGLISTITEM *pDlgListItem;
  1549. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1550. // Put on Addref to hold alive until done with loop. and also
  1551. // toggle lifetime in case launched with /embedding and
  1552. // no references on self.
  1553. AddRefOneStopLifetime(FALSE /* !External */);
  1554. cCritSect.Enter();
  1555. // see if there is a progress dialog other than idle and if so stop the logoff.
  1556. pDlgListItem = g_ObjectMgrData.DlgList;
  1557. // look for existing.
  1558. while (pDlgListItem)
  1559. {
  1560. Assert(pDlgListItem->pDlg);
  1561. if (pDlgListItem->pDlg)
  1562. {
  1563. hwndDlg = pDlgListItem->pDlg->GetHwnd();
  1564. Assert(hwndDlg);
  1565. if (NULL != hwndDlg)
  1566. {
  1567. PostMessage(hwndDlg,WM_BASEDLG_HANDLESYSSHUTDOWN,0,0);
  1568. }
  1569. }
  1570. pDlgListItem = pDlgListItem->pDlgNextListItem;
  1571. }
  1572. // set the CloseAll flag so Release knows to ignore any
  1573. // external refCounts
  1574. g_ObjectMgrData.fCloseAll = TRUE;
  1575. cCritSect.Leave();
  1576. ReleaseOneStopLifetime(FALSE /* !External */);
  1577. return hr;
  1578. }
  1579. //+---------------------------------------------------------------------------
  1580. //
  1581. // Function: GetAutoDialState
  1582. //
  1583. // Synopsis: Reads the current auto dial state of the machine/process
  1584. //
  1585. // History: 18-Jul-98 SitaramR Created
  1586. //
  1587. //----------------------------------------------------------------------------
  1588. STDAPI GetAutoDialState()
  1589. {
  1590. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  1591. if (NULL != pNetApi )
  1592. {
  1593. BOOL fEnabled;
  1594. pNetApi->RasGetAutodial( fEnabled );
  1595. g_ObjectMgrData.fRasAutoDial = fEnabled;
  1596. pNetApi->InternetGetAutodial( fEnabled );
  1597. g_ObjectMgrData.fWininetAutoDial = fEnabled;
  1598. }
  1599. if ( pNetApi != NULL )
  1600. pNetApi->Release();
  1601. if ( g_ObjectMgrData.fRasAutoDial || g_ObjectMgrData.fWininetAutoDial )
  1602. g_ObjectMgrData.eAutoDialState = eQuiescedOn;
  1603. return NOERROR;
  1604. }
  1605. //+---------------------------------------------------------------------------
  1606. //
  1607. // Function: LokEnableAutoDial
  1608. //
  1609. // Synopsis: Enables Ras and Wininet autodialing
  1610. //
  1611. // History: 18-Jul-98 SitaramR Created
  1612. //
  1613. //----------------------------------------------------------------------------
  1614. STDAPI LokEnableAutoDial()
  1615. {
  1616. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  1617. if (NULL != pNetApi )
  1618. {
  1619. if ( g_ObjectMgrData.fRasAutoDial )
  1620. pNetApi->RasSetAutodial( TRUE );
  1621. if ( g_ObjectMgrData.fWininetAutoDial )
  1622. pNetApi->InternetSetAutodial( TRUE );
  1623. }
  1624. if ( pNetApi != NULL )
  1625. pNetApi->Release();
  1626. return NOERROR;
  1627. }
  1628. //+---------------------------------------------------------------------------
  1629. //
  1630. // Function: LokDisableAutoDial
  1631. //
  1632. // Synopsis: Disables Ras and Wininet autodialing
  1633. //
  1634. // History: 18-Jul-98 SitaramR Created
  1635. //
  1636. //----------------------------------------------------------------------------
  1637. STDAPI LokDisableAutoDial()
  1638. {
  1639. LPNETAPI pNetApi = gSingleNetApiObj.GetNetApiObj();
  1640. if (NULL != pNetApi )
  1641. {
  1642. if ( g_ObjectMgrData.fRasAutoDial )
  1643. pNetApi->RasSetAutodial( FALSE );
  1644. if ( g_ObjectMgrData.fWininetAutoDial )
  1645. pNetApi->InternetSetAutodial( FALSE );
  1646. }
  1647. if ( pNetApi != NULL )
  1648. pNetApi->Release();
  1649. return NOERROR;
  1650. }
  1651. //+---------------------------------------------------------------------------
  1652. //
  1653. // Function: BeginSyncSession
  1654. //
  1655. // Synopsis: Called at the beginning of actual synchronization to setup
  1656. // autodial support.
  1657. //
  1658. // History: 18-Jul-98 SitaramR Created
  1659. //
  1660. //----------------------------------------------------------------------------
  1661. STDAPI BeginSyncSession()
  1662. {
  1663. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1664. cCritSect.Enter();
  1665. if ( g_ObjectMgrData.cNestedStartCalls == 0 )
  1666. {
  1667. Assert( g_ObjectMgrData.eAutoDialState == eQuiescedOn
  1668. || g_ObjectMgrData.eAutoDialState == eQuiescedOff );
  1669. g_ObjectMgrData.fFirstSyncItem = TRUE;
  1670. }
  1671. g_ObjectMgrData.cNestedStartCalls++;
  1672. cCritSect.Leave();
  1673. return NOERROR;
  1674. }
  1675. //+---------------------------------------------------------------------------
  1676. //
  1677. // Function: EndSyncSession
  1678. //
  1679. // Synopsis: Called at the end of actual synchronization to cleanup
  1680. // autodial support.
  1681. //
  1682. // History: 28-Jul-98 SitaramR Created
  1683. //
  1684. //----------------------------------------------------------------------------
  1685. STDAPI EndSyncSession()
  1686. {
  1687. HRESULT hr = E_UNEXPECTED;
  1688. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1689. cCritSect.Enter();
  1690. Assert( g_ObjectMgrData.cNestedStartCalls > 0 );
  1691. Assert( g_ObjectMgrData.eAutoDialState != eQuiescedOn );
  1692. g_ObjectMgrData.cNestedStartCalls--;
  1693. if ( g_ObjectMgrData.cNestedStartCalls == 0 )
  1694. {
  1695. if ( g_ObjectMgrData.eAutoDialState == eAutoDialOn )
  1696. g_ObjectMgrData.eAutoDialState = eQuiescedOn;
  1697. else if ( g_ObjectMgrData.eAutoDialState == eAutoDialOff )
  1698. {
  1699. //
  1700. // Reset autodial state to enabled now that all synch has completed.
  1701. // What to do if hr is set to error code ?
  1702. //
  1703. hr = LokEnableAutoDial();
  1704. g_ObjectMgrData.eAutoDialState = eQuiescedOn;
  1705. }
  1706. //
  1707. // If the state is eQuiescedOff then do nothing
  1708. //
  1709. }
  1710. cCritSect.Leave();
  1711. return hr;
  1712. }
  1713. //+---------------------------------------------------------------------------
  1714. //
  1715. // Function: ApplySyncItemDialState
  1716. //
  1717. // Synopsis: Set the auto dial requirements of each handler as it is being
  1718. // prepared for syncing.
  1719. //
  1720. // Arguments: [fAutoDialDisable] -- Should autodial be disabled for this
  1721. // handler ?
  1722. //
  1723. // History: 28-Jul-98 SitaramR Created
  1724. //
  1725. //----------------------------------------------------------------------------
  1726. STDAPI ApplySyncItemDialState( BOOL fAutoDialDisable )
  1727. {
  1728. HRESULT hr = NOERROR;
  1729. CCriticalSection cCritSect(&g_LockCountCriticalSection,GetCurrentThreadId());
  1730. cCritSect.Enter();
  1731. if ( g_ObjectMgrData.fFirstSyncItem )
  1732. {
  1733. //
  1734. // Read whether autodial state is on or off, before we modify it
  1735. //
  1736. GetAutoDialState();
  1737. Assert( g_ObjectMgrData.eAutoDialState == eQuiescedOn
  1738. || g_ObjectMgrData.eAutoDialState == eQuiescedOff );
  1739. if ( g_ObjectMgrData.eAutoDialState == eQuiescedOn )
  1740. {
  1741. if ( fAutoDialDisable )
  1742. {
  1743. hr = LokDisableAutoDial();
  1744. g_ObjectMgrData.eAutoDialState = eAutoDialOff;
  1745. }
  1746. else
  1747. g_ObjectMgrData.eAutoDialState = eAutoDialOn;
  1748. }
  1749. g_ObjectMgrData.fFirstSyncItem = FALSE;
  1750. }
  1751. else
  1752. {
  1753. if ( !fAutoDialDisable
  1754. && g_ObjectMgrData.eAutoDialState == eAutoDialOff )
  1755. {
  1756. hr = LokEnableAutoDial();
  1757. g_ObjectMgrData.eAutoDialState = eAutoDialOn;
  1758. }
  1759. }
  1760. cCritSect.Leave();
  1761. return hr;
  1762. }
  1763. //+-------------------------------------------------------------------------
  1764. //
  1765. // Method: CSingletonNetApi::~CSingletonNetApi
  1766. //
  1767. // Synopsis: Destructor
  1768. //
  1769. // History: 31-Jul-1998 SitaramR Created
  1770. //
  1771. //--------------------------------------------------------------------------
  1772. CSingletonNetApi::~CSingletonNetApi()
  1773. {
  1774. CLock lock(this);
  1775. lock.Enter();
  1776. Assert(NULL == m_pNetApi);
  1777. if ( m_pNetApi != 0 )
  1778. {
  1779. m_pNetApi->Release();
  1780. m_pNetApi = 0;
  1781. }
  1782. lock.Leave();
  1783. }
  1784. //+-------------------------------------------------------------------------
  1785. //
  1786. // Method: CSingletonNetApi::GetNetApiObj
  1787. //
  1788. // Synopsis: Returns a pointer to NetApi object
  1789. //
  1790. // History: 31-Jul-1998 SitaramR Created
  1791. //
  1792. //--------------------------------------------------------------------------
  1793. LPNETAPI CSingletonNetApi::GetNetApiObj()
  1794. {
  1795. CLock lock(this);
  1796. lock.Enter();
  1797. if ( m_pNetApi == 0 )
  1798. {
  1799. if (NOERROR != MobsyncGetClassObject(MOBSYNC_CLASSOBJECTID_NETAPI,(void **) &m_pNetApi))
  1800. {
  1801. m_pNetApi = NULL;
  1802. }
  1803. }
  1804. if ( m_pNetApi )
  1805. m_pNetApi->AddRef();
  1806. lock.Leave();
  1807. return m_pNetApi;
  1808. }
  1809. void CSingletonNetApi::DeleteNetApiObj()
  1810. {
  1811. CLock lock(this);
  1812. lock.Enter();
  1813. if ( m_pNetApi )
  1814. {
  1815. DWORD cRefs;
  1816. cRefs = m_pNetApi->Release();
  1817. Assert(0 == cRefs);
  1818. m_pNetApi = NULL;
  1819. }
  1820. lock.Leave();
  1821. }