Leaked source code of windows server 2003
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.

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