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.

2307 lines
64 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: Msg.cpp
  7. //
  8. // Contents: Handles messages between threads
  9. //
  10. // Classes: CThreadMsgProxy
  11. //
  12. // Notes:
  13. //
  14. // History: 05-Nov-97 rogerg Created.
  15. //
  16. //--------------------------------------------------------------------------
  17. #include "precomp.h"
  18. extern HINSTANCE g_hInst;
  19. extern void UnitApplication();
  20. // globals for handling QueryEndSession
  21. HANDLE g_hEndSessionEvent = NULL; // created when an end session has occured.
  22. BOOL g_fShuttingDown = FALSE; // set when application begins to shutdown.(WM_QUIT)
  23. // global for keeping track of handler's threads. We create on Thread for each handler
  24. // CLSID
  25. STUBLIST *g_FirstStub = NULL; // pointer to first proxy in our list.
  26. CRITICAL_SECTION g_StubListCriticalSection; // Critical Section to use for adding proxy
  27. //+---------------------------------------------------------------------------
  28. //
  29. // Function: TerminateStub, public
  30. //
  31. // Synopsis: Called by proxy to terminate a Stub of the given Id.
  32. //
  33. // Arguments: [pStubID] - Identifies the stub.
  34. //
  35. // Returns: S_OK - Stub was terminated
  36. // S_FALSE or Error - Stub either was already terminated
  37. // or couldn't be found.
  38. //
  39. // Modifies:
  40. //
  41. // History: 17-Nov-98 rogerg Created.
  42. //
  43. //----------------------------------------------------------------------------
  44. HRESULT TerminateStub(STUBLIST *pStubID)
  45. {
  46. HRESULT hr = E_UNEXPECTED;
  47. STUBLIST *pStubList;
  48. CCriticalSection cCritSect(&g_StubListCriticalSection,GetCurrentThreadId());
  49. cCritSect.Enter();
  50. pStubList = g_FirstStub;
  51. while (pStubList)
  52. {
  53. if (pStubID == pStubList)
  54. {
  55. hr = pStubList->fStubTerminated ? S_FALSE : S_OK;
  56. pStubList->fStubTerminated = TRUE;
  57. break;
  58. }
  59. pStubList = pStubList->pNextStub;
  60. }
  61. cCritSect.Leave();
  62. AssertSz(SUCCEEDED(hr),"Didn't find StubID on Terminate");
  63. return hr;
  64. }
  65. //+---------------------------------------------------------------------------
  66. //
  67. // Function: DoesStubExist, public
  68. //
  69. // Synopsis: Called by proxy see if Stub Exists
  70. // or has been terminated
  71. //
  72. // Arguments: [pStubID] - Identifies the stub.
  73. //
  74. // Returns: S_OK - Stubs exists
  75. // S_FALSE - Stub hasn't been terminated.
  76. //
  77. // Modifies:
  78. //
  79. // History: 17-Nov-98 rogerg Created.
  80. //
  81. //----------------------------------------------------------------------------
  82. HRESULT DoesStubExist(STUBLIST *pStubID)
  83. {
  84. HRESULT hr = S_FALSE;
  85. STUBLIST *pStubList;
  86. CCriticalSection cCritSect(&g_StubListCriticalSection,GetCurrentThreadId());
  87. cCritSect.Enter();
  88. pStubList = g_FirstStub;
  89. while (pStubList)
  90. {
  91. if (pStubID == pStubList)
  92. {
  93. // if stub has already been terminated return S_FALSE
  94. hr = pStubList->fStubTerminated ? S_FALSE : S_OK;
  95. break;
  96. }
  97. pStubList = pStubList->pNextStub;
  98. }
  99. cCritSect.Leave();
  100. return hr;
  101. }
  102. //+---------------------------------------------------------------------------
  103. //
  104. // Function: CreateHandlerThread, public
  105. //
  106. // Synopsis: Called by client to create a new handler thread
  107. //
  108. // Arguments: [pThreadProxy] - on success returns a pointer to Proxy
  109. // [hwndDlg] = hwnd of Window to associate with this proxy
  110. //
  111. // Returns: Appropriate status code
  112. //
  113. // Modifies:
  114. //
  115. // History: 05-Nov-97 rogerg Created.
  116. //
  117. //----------------------------------------------------------------------------
  118. HRESULT CreateHandlerThread(CThreadMsgProxy **pThreadProxy, HWND hwndDlg, REFCLSID refClsid)
  119. {
  120. HRESULT hr = E_FAIL;
  121. HANDLE hThread = NULL;
  122. DWORD dwThreadId;
  123. HandlerThreadArgs ThreadArgs;
  124. STUBLIST *pStubList;
  125. BOOL fExistingStub = FALSE;
  126. CCriticalSection cCritSect(&g_StubListCriticalSection,GetCurrentThreadId());
  127. *pThreadProxy = new CThreadMsgProxy();
  128. if (NULL == *pThreadProxy)
  129. return E_OUTOFMEMORY;
  130. // lock the critical section and don't release it until the proxy
  131. // has been setup.
  132. cCritSect.Enter();
  133. // Look to see if there is already a thread for this handler's
  134. // clsid and if there is, reuse it, else create a new one.
  135. pStubList = g_FirstStub;
  136. while (pStubList)
  137. {
  138. if ((pStubList->clsidStub == refClsid) && (FALSE == pStubList->fStubTerminated))
  139. {
  140. fExistingStub = TRUE;
  141. break;
  142. }
  143. pStubList = pStubList->pNextStub;
  144. }
  145. // if found existing proxy then addref the cRefs and init the proxy
  146. // with the variables, else create a new one.
  147. if (fExistingStub)
  148. {
  149. ++(pStubList->cRefs); // bump up the cRefs
  150. hr = (*pThreadProxy)->InitProxy(pStubList->hwndStub,
  151. pStubList->ThreadIdStub,
  152. pStubList->hThreadStub,
  153. hwndDlg,
  154. pStubList->clsidStub,
  155. pStubList);
  156. }
  157. else
  158. {
  159. ThreadArgs.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  160. if (ThreadArgs.hEvent)
  161. {
  162. hThread = CreateThread(NULL, 0, HandlerThread, &ThreadArgs, 0, &dwThreadId);
  163. if (hThread)
  164. {
  165. WaitForSingleObject(ThreadArgs.hEvent,INFINITE);
  166. hr = ThreadArgs.hr;
  167. if (S_OK == hr)
  168. {
  169. STUBLIST *pNewStub;
  170. pNewStub = (STUBLIST*) ALLOC(sizeof(STUBLIST));
  171. if (pNewStub)
  172. {
  173. pNewStub->pNextStub = NULL;
  174. pNewStub->cRefs = 1;
  175. pNewStub->hwndStub = ThreadArgs.hwndStub;
  176. pNewStub->ThreadIdStub = dwThreadId;
  177. pNewStub->hThreadStub = hThread;
  178. pNewStub->clsidStub = refClsid;
  179. pNewStub->fStubTerminated = FALSE;
  180. if (NULL == g_FirstStub)
  181. {
  182. g_FirstStub = pNewStub;
  183. }
  184. else
  185. {
  186. pStubList = g_FirstStub;
  187. while (pStubList->pNextStub)
  188. {
  189. pStubList = pStubList->pNextStub;
  190. }
  191. pStubList->pNextStub = pNewStub;
  192. }
  193. (*pThreadProxy)->InitProxy(ThreadArgs.hwndStub,dwThreadId,hThread,hwndDlg,refClsid,pNewStub);
  194. }
  195. else
  196. {
  197. hr = E_OUTOFMEMORY;
  198. }
  199. }
  200. // if failed to create thread, initproxy or add it to global list, then bail
  201. if (S_OK != hr)
  202. {
  203. CloseHandle(hThread);
  204. }
  205. }
  206. else
  207. {
  208. hr = HRESULT_FROM_WIN32(GetLastError());
  209. }
  210. CloseHandle(ThreadArgs.hEvent);
  211. }
  212. }
  213. cCritSect.Leave();
  214. // if got this far either found our created a handler thread, now need
  215. // to initialize the the stub side to create a hndlrMsg for this
  216. // instance of the handler. will return a hdnlrmsg that must be passed
  217. // along with everycall.
  218. if ( (S_OK == hr) && (*pThreadProxy))
  219. {
  220. hr = (*pThreadProxy)->CreateNewHndlrMsg();
  221. // Review - if fail to create hndlr message, then
  222. // free proxy and return an error.
  223. }
  224. if (S_OK != hr)
  225. {
  226. if ((*pThreadProxy))
  227. {
  228. (*pThreadProxy)->Release();
  229. *pThreadProxy = NULL;
  230. }
  231. }
  232. return hr;
  233. }
  234. //+---------------------------------------------------------------------------
  235. //
  236. // Function: HandlerThread, public
  237. //
  238. // Synopsis: main proc for Handler thread
  239. //
  240. // Arguments: [lpArg] - Ptr to HandlerThreadArgs
  241. //
  242. // Returns: Appropriate status code
  243. //
  244. // Modifies:
  245. //
  246. // History: 05-Nov-97 rogerg Created.
  247. //
  248. //----------------------------------------------------------------------------
  249. DWORD WINAPI HandlerThread( LPVOID lpArg )
  250. {
  251. MSG msg;
  252. HRESULT hr;
  253. CThreadMsgStub *pThreadMsgStub = NULL;
  254. CMsgServiceHwnd *pMsgDlg;
  255. HRESULT hrOleInitialize;
  256. BOOL fMsgDlgInitialized = FALSE;
  257. HandlerThreadArgs *pThreadArgs = (HandlerThreadArgs *) lpArg;
  258. DWORD dwThreadID = GetCurrentThreadId();
  259. __try
  260. {
  261. pThreadArgs->hr = E_UNEXPECTED;
  262. // need to do a PeekMessage and then set an event to make sure
  263. // a message loop is created before the first PostMessage is sent.
  264. PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
  265. hrOleInitialize = CoInitialize(NULL);
  266. // create our message hwnd
  267. pMsgDlg = new CMsgServiceHwnd;
  268. if (pMsgDlg)
  269. {
  270. if (pMsgDlg->Initialize(dwThreadID,MSGHWNDTYPE_HANDLERTHREAD))
  271. {
  272. pThreadArgs->hwndStub = pMsgDlg->GetHwnd();
  273. fMsgDlgInitialized = TRUE;
  274. }
  275. }
  276. // set the approriate error
  277. if (fMsgDlgInitialized && SUCCEEDED(hrOleInitialize))
  278. hr = S_OK;
  279. else
  280. hr = E_UNEXPECTED;
  281. pThreadArgs->hr = hr;
  282. // let the caller know the thread is done initializing.
  283. if (pThreadArgs->hEvent)
  284. SetEvent(pThreadArgs->hEvent);
  285. if (S_OK == hr)
  286. {
  287. // sit in loop receiving messages.
  288. while (GetMessage(&msg, NULL, 0, 0))
  289. {
  290. TranslateMessage(&msg);
  291. DispatchMessage(&msg);
  292. }
  293. }
  294. if (SUCCEEDED(hrOleInitialize))
  295. {
  296. CoFreeUnusedLibraries();
  297. CoUninitialize();
  298. }
  299. }
  300. __except(QueryHandleException())
  301. {
  302. AssertSz(0,"Exception in Handler Thread.");
  303. }
  304. return 0;
  305. }
  306. //+---------------------------------------------------------------------------
  307. //
  308. // Member: CMsgServiceHwnd::HandleThreadMessage, public
  309. //
  310. // Synopsis: Responsible for determining the thread message that
  311. // was received and calling the proper handler routine
  312. //
  313. // Arguments: [pmsgInfo] - Ptr to MessagingInfo structure
  314. // [pgenMsg] - Ptr to Generic Message structure.
  315. //
  316. // Returns: Appropriate status code
  317. //
  318. // Modifies:
  319. //
  320. // History: 05-Nov-97 rogerg Created.
  321. //
  322. //----------------------------------------------------------------------------
  323. HRESULT CMsgServiceHwnd::HandleThreadMessage(MessagingInfo *pmsgInfo,GenericMsg *pgenMsg)
  324. {
  325. CHndlrMsg *pHndlrMsg;
  326. pgenMsg->hr = E_UNEXPECTED; // initialize the return result.
  327. // review, look up in linked list to validate.
  328. pHndlrMsg = pmsgInfo->pCHndlrMsg;
  329. m_fInOutCall = TRUE;
  330. switch (pgenMsg->ThreadMsg)
  331. {
  332. case ThreadMsg_Release:
  333. {
  334. MSGInitialize *pmsg = (MSGInitialize *) pgenMsg;
  335. ULONG cRefs;
  336. cRefs = pHndlrMsg->Release();
  337. Assert(0 == cRefs);
  338. m_pHndlrMsg = NULL; // review, change when done.
  339. pgenMsg->hr = S_OK;
  340. m_fInOutCall = FALSE;
  341. }
  342. break;
  343. case ThreadMsg_Initialize:
  344. {
  345. MSGInitialize *pmsg = (MSGInitialize *) pgenMsg;
  346. pgenMsg->hr = pHndlrMsg->Initialize(pmsg->dwReserved,pmsg->dwSyncFlags,
  347. pmsg->cbCookie,pmsg->lpCookie);
  348. }
  349. break;
  350. case ThreadMsg_GetHandlerInfo:
  351. {
  352. MSGGetHandlerInfo *pmsg = (MSGGetHandlerInfo *) pgenMsg;
  353. pgenMsg->hr = pHndlrMsg->GetHandlerInfo(pmsg->ppSyncMgrHandlerInfo);
  354. }
  355. break;
  356. case ThreadMsg_GetItemObject:
  357. {
  358. MSGGetItemObject *pmsg = (MSGGetItemObject *) pgenMsg;
  359. pgenMsg->hr = pHndlrMsg->GetItemObject(pmsg->ItemID,pmsg->riid, pmsg->ppv);
  360. }
  361. break;
  362. case ThreadMsg_ShowProperties:
  363. {
  364. MSGShowProperties *pmsg = (MSGShowProperties *) pgenMsg;
  365. pgenMsg->hr = pHndlrMsg->ShowProperties(pmsg->hWndParent,pmsg->ItemID);
  366. }
  367. break;
  368. case ThreadMsg_PrepareForSync:
  369. {
  370. MSGPrepareForSync *pmsg = (MSGPrepareForSync *) pgenMsg;
  371. HANDLE hEvent = pmsgInfo->hMsgEvent;
  372. pgenMsg->hr = pHndlrMsg->PrepareForSync(pmsg->cbNumItems,pmsg->pItemIDs,
  373. pmsg->hWndParent,pmsg->dwReserved);
  374. }
  375. break;
  376. case ThreadMsg_Synchronize:
  377. {
  378. MSGSynchronize *pmsg = (MSGSynchronize *) pgenMsg;
  379. HANDLE hEvent = pmsgInfo->hMsgEvent;
  380. pgenMsg->hr = pHndlrMsg->Synchronize(pmsg->hWndParent);
  381. }
  382. break;
  383. case ThreadMsg_SetItemStatus:
  384. {
  385. MSGSetItemStatus *pmsg = (MSGSetItemStatus *) pgenMsg;
  386. pgenMsg->hr = pHndlrMsg->SetItemStatus(pmsg->ItemID,pmsg->dwSyncMgrStatus);
  387. }
  388. break;
  389. case ThreadMsg_ShowError:
  390. {
  391. MSGShowConflicts *pmsg = (MSGShowConflicts *) pgenMsg;
  392. pgenMsg->hr = pHndlrMsg->ShowError(pmsg->hWndParent,pmsg->ErrorID);
  393. }
  394. break;
  395. case ThreadMsg_AddHandlerItems:
  396. {
  397. MSGAddItemHandler *pmsg = (MSGAddItemHandler *) pgenMsg;
  398. pgenMsg->hr = pHndlrMsg->AddHandlerItems(pmsg->hwndList,pmsg->pcbNumItems);
  399. }
  400. break;
  401. case ThreadMsg_CreateServer:
  402. {
  403. MSGCreateServer *pmsg = (MSGCreateServer *) pgenMsg;
  404. pgenMsg->hr = pHndlrMsg->CreateServer(pmsg->pCLSIDServer,pmsg->pHndlrQueue,pmsg->pHandlerId,pmsg->dwProxyThreadId);
  405. }
  406. break;
  407. case ThreadMsg_SetHndlrQueue:
  408. {
  409. MSGSetHndlrQueue *pmsg = (MSGSetHndlrQueue *) pgenMsg;
  410. pgenMsg->hr = pHndlrMsg->SetHndlrQueue(pmsg->pHndlrQueue,pmsg->pHandlerId,pmsg->dwProxyThreadId);
  411. }
  412. break;
  413. case ThreadMsg_SetupCallback:
  414. {
  415. MSGSetupCallback *pmsg = (MSGSetupCallback *) pgenMsg;
  416. pgenMsg->hr = pHndlrMsg->SetupCallback(pmsg->fSet);
  417. }
  418. break;
  419. default:
  420. AssertSz(0,"Unknown Thread Message");
  421. break;
  422. }
  423. m_fInOutCall = FALSE;
  424. return S_OK;
  425. }
  426. //+---------------------------------------------------------------------------
  427. //
  428. // Function: DopModalLoop, public
  429. //
  430. // Synopsis: Sit in message loop until the specified object
  431. // becomes or thread becomes signalled.
  432. //
  433. // Arguments: [hEvent] - Event to wait on
  434. // [hThread] - Thread that if it becomes signalled indicates thread
  435. // that is being called has died.
  436. // [hwndDlg] - hwnd of Dialog on thread we should check message for, can be null.
  437. // [fAllowIncomingCalls] - incoming Messages can be dispatched during out call.
  438. //
  439. // Returns: Appropriate status code
  440. //
  441. // Modifies:
  442. //
  443. // History: 05-Nov-97 rogerg Created.
  444. //
  445. //----------------------------------------------------------------------------
  446. HRESULT DoModalLoopoLD(HANDLE hEvent,HANDLE hThread,HWND hwndDlg,BOOL fAllowIncomingCalls,
  447. DWORD dwTimeout)
  448. {
  449. HRESULT hr = S_OK;
  450. DWORD dwWakeup;
  451. DWORD dwHandleCount;
  452. DWORD dwStartTime = GetTickCount();
  453. DWORD dwTimeoutValue;
  454. HANDLE handles[2];
  455. handles[0] = hEvent;
  456. handles[1] = hThread;
  457. dwHandleCount = (NULL == hThread) ? 1 : 2;
  458. dwTimeoutValue = dwTimeout; // initial call to wait is just the passed in vaulue
  459. // just sit in a loop until the message has been processed or the thread
  460. // we are calling dies
  461. // if no event to wait on just fall through
  462. if (NULL == hEvent)
  463. {
  464. do
  465. {
  466. if (fAllowIncomingCalls)
  467. {
  468. dwWakeup = MsgWaitForMultipleObjects(dwHandleCount,&handles[0],FALSE,dwTimeoutValue,QS_ALLINPUT);
  469. }
  470. else
  471. {
  472. dwWakeup = WaitForMultipleObjects(dwHandleCount,&handles[0],FALSE,dwTimeoutValue);
  473. }
  474. if (WAIT_OBJECT_0 == dwWakeup) // call was completed.
  475. {
  476. hr = S_OK;
  477. break;
  478. }
  479. else if ((WAIT_OBJECT_0 +1 == dwWakeup) && (2== dwHandleCount) )
  480. {
  481. // thread died within call.
  482. AssertSz(0,"Server Thread Terminated");
  483. hr = E_UNEXPECTED;
  484. break;
  485. }
  486. else if (WAIT_ABANDONED_0 == dwWakeup)
  487. {
  488. AssertSz(0,"Abandoned"); // this shouldn't ever happen
  489. hr = E_UNEXPECTED;
  490. break;
  491. }
  492. else if (WAIT_TIMEOUT == dwWakeup)
  493. {
  494. hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
  495. break;
  496. }
  497. else
  498. {
  499. MSG msg;
  500. // see if events are signalled themselves since can get into this
  501. // loop is items are in the queue even if events we are
  502. // waiting on are already set.
  503. if (WAIT_OBJECT_0 == WaitForSingleObject(hEvent,0))
  504. {
  505. hr = S_OK;
  506. break;
  507. }
  508. else if (hThread && (WAIT_OBJECT_0 == WaitForSingleObject(hThread,0)) )
  509. {
  510. AssertSz(0,"Server Thread Terminated");
  511. hr = E_UNEXPECTED;
  512. break;
  513. }
  514. // only grab out one peek message since dispatch could
  515. // cause another message to get placed in the queue.
  516. if (PeekMessage(&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE))
  517. {
  518. if ( (NULL == hwndDlg) || !IsDialogMessage(hwndDlg,&msg))
  519. {
  520. TranslateMessage((LPMSG) &msg);
  521. DispatchMessage((LPMSG) &msg);
  522. }
  523. }
  524. }
  525. // adjust the timeout value
  526. if (INFINITE == dwTimeout)
  527. {
  528. dwTimeoutValue = INFINITE;
  529. }
  530. else
  531. {
  532. DWORD dwCurTime = GetTickCount();
  533. // handle roll-over of GetTickCount. If this happens use has to wait
  534. // for the StartTime again. so user may have to wait twice as long
  535. // as originally anticipated.
  536. if (dwCurTime < dwStartTime)
  537. {
  538. dwStartTime = dwCurTime;
  539. }
  540. // if the elapsed time is greater than the timeout set the
  541. // timeout value to zero, else use the different/
  542. if (dwTimeout <= (dwCurTime - dwStartTime))
  543. {
  544. dwTimeoutValue = 0;
  545. }
  546. else
  547. {
  548. dwTimeoutValue = dwTimeout - (dwCurTime - dwStartTime);
  549. }
  550. }
  551. } while (1);
  552. }
  553. return hr;
  554. }
  555. //+---------------------------------------------------------------------------
  556. //
  557. // Function: DopModalLoop, public
  558. //
  559. // Synopsis: Sit in message loop until the specified object
  560. // becomes or thread becomes signalled.
  561. //
  562. // Arguments: [hEvent] - Event to wait on
  563. // [hThread] - Thread that if it becomes signalled indicates thread
  564. // that is being called has died.
  565. // [hwndDlg] - hwnd of Dialog on thread we should check message for, can be null.
  566. // [fAllowIncomingCalls] - incoming Messages can be dispatched during out call.
  567. //
  568. // Returns: Appropriate status code
  569. //
  570. // Modifies:
  571. //
  572. // History: 05-Nov-97 rogerg Created.
  573. //
  574. //----------------------------------------------------------------------------
  575. HRESULT DoModalLoop(HANDLE hEvent,HANDLE hThread,HWND hwndDlg,BOOL fAllowIncomingCalls,
  576. DWORD dwTimeout)
  577. {
  578. HRESULT hr = S_OK;
  579. DWORD dwWakeup;
  580. DWORD dwHandleCount;
  581. DWORD dwStartTime = GetTickCount();
  582. DWORD dwTimeoutValue;
  583. HANDLE handles[2];
  584. handles[0] = hEvent;
  585. handles[1] = hThread;
  586. Assert(hEvent);
  587. dwHandleCount = (NULL == hThread) ? 1 : 2;
  588. dwTimeoutValue = dwTimeout; // initial call to wait is just the passed in vaulue
  589. // just sit in a loop until the message has been processed or the thread
  590. // we are calling dies
  591. do
  592. {
  593. DWORD dwWaitValue;
  594. MSG msg;
  595. // check if hEvents are signalled yet
  596. if (WAIT_OBJECT_0 == (dwWaitValue = WaitForSingleObject(hEvent,0)) )
  597. {
  598. hr = S_OK;
  599. break;
  600. }
  601. else if ( (dwWaitValue != WAIT_ABANDONED)
  602. && hThread && (WAIT_OBJECT_0 == (dwWaitValue = WaitForSingleObject(hThread,0))) )
  603. {
  604. // possible on Release message event was set between the
  605. // time we checked for it and our thread event check.
  606. if (WAIT_OBJECT_0 == (dwWaitValue = WaitForSingleObject(hEvent,0)) )
  607. {
  608. hr = S_OK;
  609. }
  610. else
  611. {
  612. AssertSz(0,"Server Thread Terminated");
  613. hr = E_UNEXPECTED;
  614. }
  615. break;
  616. }
  617. // if come out af any of these calls with abandoned then assert and break;
  618. if (WAIT_ABANDONED == dwWaitValue)
  619. {
  620. AssertSz(0,"Abandoned"); // this shouldn't ever happen
  621. hr = E_UNEXPECTED;
  622. break;
  623. }
  624. // if not then either grab next PeekMessage or wait for objects depending
  625. if (fAllowIncomingCalls)
  626. {
  627. // Leave any completion posts in the queue until the call has returned.
  628. if (PeekMessage(&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE) )
  629. {
  630. dwWakeup = WAIT_OBJECT_0 + dwHandleCount; // set it to wait MsgWait would.
  631. Assert (msg.message != WM_QUIT);
  632. if ( (NULL == hwndDlg) || !IsDialogMessage(hwndDlg,&msg))
  633. {
  634. TranslateMessage((LPMSG) &msg);
  635. DispatchMessage((LPMSG) &msg);
  636. }
  637. }
  638. else
  639. {
  640. dwWakeup = MsgWaitForMultipleObjects(dwHandleCount,&handles[0],FALSE,dwTimeoutValue,QS_ALLINPUT);
  641. }
  642. }
  643. else
  644. {
  645. dwWakeup = WaitForMultipleObjects(dwHandleCount,&handles[0],FALSE,dwTimeoutValue);
  646. }
  647. if (WAIT_TIMEOUT == dwWakeup)
  648. {
  649. hr = HRESULT_FROM_WIN32(ERROR_TIMEOUT);
  650. break;
  651. }
  652. // update the timeout value
  653. if (INFINITE == dwTimeout)
  654. {
  655. dwTimeoutValue = INFINITE;
  656. }
  657. else
  658. {
  659. DWORD dwCurTime = GetTickCount();
  660. // handle roll-over of GetTickCount. If this happens use has to wait
  661. // for the StartTime again. so user may have to wait twice as long
  662. // as originally anticipated.
  663. if (dwCurTime < dwStartTime)
  664. {
  665. dwStartTime = dwCurTime;
  666. }
  667. // if the elapsed time is greater than the timeout set the
  668. // timeout value to zero, else use the different/
  669. if (dwTimeout <= (dwCurTime - dwStartTime))
  670. {
  671. dwTimeoutValue = 0;
  672. }
  673. else
  674. {
  675. dwTimeoutValue = dwTimeout - (dwCurTime - dwStartTime);
  676. }
  677. }
  678. } while (1);
  679. return hr;
  680. }
  681. //+---------------------------------------------------------------------------
  682. //
  683. // Member: CThreadMsgProxy::CThreadMsgProxy, public
  684. //
  685. // Synopsis: Constructor
  686. // Arguments:
  687. //
  688. // Returns:
  689. //
  690. // Modifies:
  691. //
  692. // History: 05-Nov-97 rogerg Created.
  693. //
  694. //----------------------------------------------------------------------------
  695. CThreadMsgProxy::CThreadMsgProxy()
  696. {
  697. m_Clsid = GUID_NULL;
  698. m_cRef = 1;
  699. m_hwndDlg = NULL;
  700. m_pCHndlrMsg = NULL;
  701. m_fTerminatedHandler = FALSE;
  702. m_hThreadStub = NULL;
  703. m_ThreadIdStub = 0;
  704. m_hwndStub = NULL;
  705. m_hwndDlg = NULL;
  706. m_ThreadIdProxy = 0;
  707. m_fNewHndlrQueue = FALSE;
  708. m_pHandlerId = 0;
  709. m_pHndlrQueue = NULL;
  710. m_dwNestCount = 0;
  711. m_fHaveCompletionCall = FALSE;
  712. }
  713. //+---------------------------------------------------------------------------
  714. //
  715. // Member: CThreadMsgProxy::~CThreadMsgProxy, public
  716. //
  717. // Synopsis: destructor
  718. // Arguments:
  719. //
  720. // Returns:
  721. //
  722. // Modifies:
  723. //
  724. // History: 03-Jun-98 rogerg Created.
  725. //
  726. //----------------------------------------------------------------------------
  727. CThreadMsgProxy::~CThreadMsgProxy()
  728. {
  729. Assert(0 == m_dwNestCount);
  730. Assert(NULL == m_pStubId);
  731. }
  732. //+---------------------------------------------------------------------------
  733. //
  734. // Member: CThreadMsgProxy::InitProxy, public
  735. //
  736. // Synopsis: Initializes member vars of Thread Proxy
  737. // Arguments: [hwndStub] - hwnd of the Stub to send messages too.
  738. // [ThreadId] - ThreadId of the Stub
  739. // [hThread] - Handle of the Stub Thread.
  740. //
  741. // Returns: !!!!This function should be written so it never fails.
  742. //
  743. // Modifies:
  744. //
  745. // History: 05-Nov-97 rogerg Created.
  746. //
  747. //----------------------------------------------------------------------------
  748. STDMETHODIMP CThreadMsgProxy::InitProxy(HWND hwndStub, DWORD ThreadId,HANDLE hThread,
  749. HWND hwndDlg,REFCLSID refClsid,
  750. STUBLIST *pStubId)
  751. {
  752. m_hwndStub = hwndStub;
  753. m_ThreadIdStub = ThreadId;
  754. m_hThreadStub = hThread;
  755. m_pStubId = pStubId;
  756. m_hwndDlg = hwndDlg;
  757. m_Clsid = refClsid;
  758. m_ThreadIdProxy = GetCurrentThreadId();
  759. return S_OK;
  760. }
  761. //+---------------------------------------------------------------------------
  762. //
  763. // Member: CThreadMsgProxy::DispatchMsg, public
  764. //
  765. // Synopsis: Dispatches the specified messge
  766. // Arguments: [pgenMsg] - Ptr to Generic Message structure.
  767. // [fAllowIncomingCalls] - incoming Messages can be dispatched during out call.
  768. //
  769. // Returns: Appropriate status code
  770. //
  771. // Modifies:
  772. //
  773. // History: 05-Nov-97 rogerg Created.
  774. //
  775. //----------------------------------------------------------------------------
  776. STDMETHODIMP CThreadMsgProxy::DispatchMsg(GenericMsg *pgenMsg,BOOL fAllowIncomingCalls,BOOL fAsync)
  777. {
  778. HRESULT hr = E_UNEXPECTED;
  779. MessagingInfo msgInfo;
  780. // if the hndlrmsg information needs to be updated update
  781. // it before sending requested message
  782. AssertSz(!m_fTerminatedHandler,"Dispatching Message on Terminated Thread");
  783. if (m_fTerminatedHandler)
  784. {
  785. return E_UNEXPECTED;
  786. }
  787. ++m_dwNestCount;
  788. msgInfo.hMsgEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  789. if (NULL == msgInfo.hMsgEvent)
  790. {
  791. --m_dwNestCount;
  792. return HRESULT_FROM_WIN32(GetLastError());
  793. }
  794. msgInfo.dwSenderThreadID = m_ThreadIdProxy;
  795. msgInfo.pCHndlrMsg = m_pCHndlrMsg;
  796. // Post the message to the handler thread.
  797. Assert(m_hwndStub);
  798. Assert(m_pCHndlrMsg);
  799. Assert(m_hThreadStub);
  800. Assert(m_pStubId);
  801. if (m_hwndStub && m_pCHndlrMsg && m_hThreadStub && m_pStubId)
  802. {
  803. BOOL fPostMessage;
  804. fPostMessage = PostMessage(m_hwndStub,WM_THREADMESSAGE,(WPARAM) &msgInfo, (LPARAM) pgenMsg);
  805. Assert(fPostMessage || m_pStubId->fStubTerminated);
  806. if (fPostMessage)
  807. {
  808. hr = DoModalLoop(msgInfo.hMsgEvent,m_hThreadStub,m_hwndDlg,fAllowIncomingCalls,INFINITE);
  809. }
  810. }
  811. CloseHandle(msgInfo.hMsgEvent);
  812. --m_dwNestCount;
  813. // if have a callback message then post. Note don't have this code for stub messages
  814. // since it doesn;t have any callbacks
  815. if (m_fHaveCompletionCall)
  816. {
  817. PostMessage(m_msgCompletion.hwnd,m_msgCompletion.message,m_msgCompletion.wParam,m_msgCompletion.lParam);
  818. m_fHaveCompletionCall = FALSE;
  819. }
  820. return (S_OK != hr) ? hr : pgenMsg->hr;
  821. }
  822. //+---------------------------------------------------------------------------
  823. //
  824. // Member: CThreadMsgProxy::DispatchsStubMsg, public
  825. //
  826. // Synopsis: Dispatches the specified Stub messge
  827. // Arguments: [pgenMsg] - Ptr to Generic Message structure.
  828. // [fAllowIncomingCalls] - incoming Messages can be dispatched during out call.
  829. //
  830. // Returns: Appropriate status code
  831. //
  832. // Modifies:
  833. //
  834. // History: 05-Nov-97 rogerg Created.
  835. //
  836. //----------------------------------------------------------------------------
  837. STDMETHODIMP CThreadMsgProxy::DispatchsStubMsg(GenericMsg *pgenMsg,BOOL fAllowIncomingCalls)
  838. {
  839. HRESULT hr = E_UNEXPECTED;
  840. MessagingInfo msgInfo;
  841. BOOL fPostMessage;
  842. AssertSz(!m_fTerminatedHandler,"Dispatching Stub Message on Terminated Thread");
  843. if (m_fTerminatedHandler)
  844. return E_UNEXPECTED;
  845. msgInfo.hMsgEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  846. if (NULL == msgInfo.hMsgEvent)
  847. return HRESULT_FROM_WIN32(GetLastError());
  848. m_dwNestCount++;
  849. msgInfo.dwSenderThreadID = m_ThreadIdProxy;
  850. // Post the message to the handler thread.
  851. Assert(m_hwndStub);
  852. Assert(m_hThreadStub);
  853. Assert(m_pStubId);
  854. if (m_hwndStub && m_hThreadStub && m_pStubId)
  855. {
  856. fPostMessage = PostMessage(m_hwndStub,WM_THREADSTUBMESSAGE,(WPARAM) &msgInfo, (LPARAM) pgenMsg);
  857. Assert(fPostMessage || (m_pStubId->fStubTerminated));
  858. if (fPostMessage)
  859. {
  860. hr = DoModalLoop(msgInfo.hMsgEvent,m_hThreadStub,m_hwndDlg,fAllowIncomingCalls,INFINITE);
  861. }
  862. }
  863. CloseHandle(msgInfo.hMsgEvent);
  864. m_dwNestCount--;
  865. Assert(FALSE == m_fHaveCompletionCall); // catch any stub calls that occur at same time as dispatch
  866. return (S_OK != hr) ? hr : pgenMsg->hr;
  867. }
  868. //+---------------------------------------------------------------------------
  869. //
  870. // Function: TerminateHandlerThread, public
  871. //
  872. // Synopsis: terminate the non-responsive handler thread
  873. //
  874. // Returns: Appropriate status code
  875. //
  876. // Modifies: m_hThreadStub;
  877. //
  878. // History: 02-Nov-98 susia Created.
  879. //
  880. //----------------------------------------------------------------------------
  881. STDMETHODIMP CThreadMsgProxy::TerminateHandlerThread(TCHAR *pszHandlerName,BOOL fPromptUser)
  882. {
  883. int iEndSession;
  884. TCHAR pszFormatString[MAX_PATH + 1],
  885. pszMessageText[MAX_PATH + 1],
  886. pszTitleString[MAX_STRING_RES + 1];
  887. AssertSz(!m_fTerminatedHandler,"Terminate Handler called twice on same Proxy");
  888. if (S_OK == DoesStubExist(m_pStubId))
  889. {
  890. BOOL bResult;
  891. // let use know of cases don't want to prompt user but haven't killed stub yet.
  892. Assert(fPromptUser);
  893. if (fPromptUser)
  894. {
  895. if (!pszHandlerName)
  896. {
  897. LoadString(g_hInst,IDS_NULL_HANDLERNOTRESPONDING,pszMessageText, MAX_PATH);
  898. }
  899. else
  900. {
  901. LoadString(g_hInst,IDS_HANDLERNOTRESPONDING,pszFormatString, MAX_PATH);
  902. StringCchPrintf(pszMessageText, ARRAYSIZE(pszMessageText), pszFormatString, pszHandlerName);
  903. }
  904. LoadString(g_hInst,IDS_SYNCMGR_ERROR,pszTitleString, MAX_STRING_RES);
  905. iEndSession = MessageBox(m_hwndDlg,pszMessageText,pszTitleString,
  906. MB_YESNO | MB_ICONERROR );
  907. if (IDYES != iEndSession)
  908. {
  909. return S_FALSE; //Yes will terminate the thread
  910. }
  911. }
  912. // make sure handler is still not responding.
  913. HRESULT fAllHandlerInstancesComplete = S_FALSE;
  914. if (m_pHndlrQueue)
  915. {
  916. fAllHandlerInstancesComplete = m_pHndlrQueue->IsAllHandlerInstancesCancelCompleted(m_Clsid);
  917. }
  918. // if no longer any instancesof this handler that aren't responding just ignore
  919. // the terminate.
  920. if (S_OK == fAllHandlerInstancesComplete)
  921. {
  922. return S_FALSE;
  923. }
  924. // mark the stubId as terminated
  925. TerminateStub(m_pStubId);
  926. // now terminate the thread.
  927. // CODE REVIEW:
  928. // NOTENOTE:
  929. // Danger Will Robinson - Danger Will Robinson - Danger Will Robinson
  930. // Maybe we can use something other than TerminateThread here ???
  931. bResult = TerminateThread (m_hThreadStub, 0);
  932. AssertSz(bResult,"Error Terminating Thread");
  933. }
  934. m_pStubId = NULL;
  935. // if get here means we should are terminating this thread
  936. m_fTerminatedHandler = TRUE;
  937. m_hThreadStub = 0; // set threadId of stub to zero.
  938. // set the proxy stubhwnd to NULL
  939. m_hwndStub = NULL;
  940. // if have a hndlrmsg tell it we are terminated and clear
  941. // out our member variable.
  942. if (m_pCHndlrMsg)
  943. {
  944. CHndlrMsg *pCHndlrMsg = m_pCHndlrMsg;
  945. m_pCHndlrMsg = NULL;
  946. pCHndlrMsg->ForceKillHandler();
  947. }
  948. return S_OK;
  949. }
  950. //+---------------------------------------------------------------------------
  951. //
  952. // Member: CThreadMsgProxy::CreateNewHndlrMsg, public
  953. //
  954. // Synopsis: Make a request to the stub to create a new
  955. // Handler Message object
  956. //
  957. // Arguments:
  958. // Returns: Appropriate status code
  959. //
  960. // Modifies:
  961. //
  962. // History: 05-Nov-97 rogerg Created.
  963. //
  964. //----------------------------------------------------------------------------
  965. STDMETHODIMP CThreadMsgProxy::CreateNewHndlrMsg()
  966. {
  967. HRESULT hr = S_OK;
  968. MSGSTUBCreateStub msg;
  969. msg.MsgGen.ThreadMsg = StubMsg_CreateNewStub;
  970. hr = DispatchsStubMsg( (GenericMsg *) &msg,TRUE);
  971. m_pCHndlrMsg = msg.pCHndlrMsg;
  972. return hr;
  973. }
  974. //+---------------------------------------------------------------------------
  975. //
  976. // Member: CThreadMsgProxy::ReleaseStub, public
  977. //
  978. // Synopsis: Informst the Stub thread that it is no longer needed.
  979. // Arguments:
  980. // Returns: Appropriate status code
  981. //
  982. // Modifies:
  983. //
  984. // History: 05-Nov-97 rogerg Created.
  985. //
  986. //----------------------------------------------------------------------------
  987. STDMETHODIMP CThreadMsgProxy::ReleaseStub()
  988. {
  989. HRESULT hr = S_OK;
  990. GenericMsg msg;
  991. msg.ThreadMsg = StubMsg_Release;
  992. hr = DispatchsStubMsg( (GenericMsg *) &msg,TRUE);
  993. return hr;
  994. }
  995. //+---------------------------------------------------------------------------
  996. //
  997. // Member: CThreadMsgProxy::QueryInterface, public
  998. //
  999. // Synopsis: Standard QueryInterface
  1000. //
  1001. // Arguments: [iid] - Interface ID
  1002. // [ppvObj] - Object return
  1003. //
  1004. // Returns: Always returns E_NOTIMPL;
  1005. //
  1006. // Modifies: [ppvObj]
  1007. //
  1008. // History: 05-Nov-97 rogerg Created.
  1009. //
  1010. //----------------------------------------------------------------------------
  1011. STDMETHODIMP CThreadMsgProxy::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  1012. {
  1013. AssertSz(0,"QI called on MsgProxy");
  1014. return E_NOTIMPL;
  1015. }
  1016. //+---------------------------------------------------------------------------
  1017. //
  1018. // Member: CThreadMsgProxy::AddRef, public
  1019. //
  1020. // Synopsis: Add reference
  1021. //
  1022. // History: 05-Nov-97 rogerg Created.
  1023. //
  1024. //----------------------------------------------------------------------------
  1025. STDMETHODIMP_(ULONG) CThreadMsgProxy::AddRef()
  1026. {
  1027. ULONG cRefs;
  1028. cRefs = InterlockedIncrement((LONG *)& m_cRef);
  1029. return cRefs;
  1030. }
  1031. //+---------------------------------------------------------------------------
  1032. //
  1033. // Member: CThreadMsgProxy::Release, public
  1034. //
  1035. // Synopsis: Release reference
  1036. // Must properly handle the case Release is
  1037. // called before the initialize method in case
  1038. // createing the handler thread fails.
  1039. //
  1040. // History: 05-Nov-97 rogerg Created.
  1041. //
  1042. //----------------------------------------------------------------------------
  1043. STDMETHODIMP_(ULONG) CThreadMsgProxy::Release()
  1044. {
  1045. HRESULT hr = S_OK;
  1046. GenericMsg msg;
  1047. ULONG cRefs;
  1048. cRefs = InterlockedDecrement( (LONG *) &m_cRef);
  1049. if (cRefs)
  1050. return cRefs;
  1051. if (m_hThreadStub && !m_fTerminatedHandler)
  1052. {
  1053. CCriticalSection cCritSect(&g_StubListCriticalSection,GetCurrentThreadId());
  1054. BOOL fLastRelease = FALSE;
  1055. BOOL fExistingStub = FALSE;
  1056. STUBLIST *pStubList;
  1057. // release the handler Thread.
  1058. msg.ThreadMsg = ThreadMsg_Release;
  1059. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,FALSE);
  1060. m_pCHndlrMsg = NULL;
  1061. // If the cRefs in our proxy list is zero
  1062. // then sit in loop until the ThreadStub Dies.
  1063. cCritSect.Enter();
  1064. pStubList = g_FirstStub;
  1065. while (pStubList)
  1066. {
  1067. if (pStubList->clsidStub == m_Clsid)
  1068. {
  1069. fExistingStub = TRUE;
  1070. break;
  1071. }
  1072. pStubList= pStubList->pNextStub;
  1073. }
  1074. Assert(fExistingStub); // their should always be an existing proxy
  1075. if (fExistingStub)
  1076. {
  1077. Assert(pStubList->cRefs > 0);
  1078. (pStubList->cRefs)--;
  1079. if (0 == pStubList->cRefs)
  1080. {
  1081. STUBLIST CurStub;
  1082. STUBLIST *pCurStub = &CurStub;
  1083. CurStub.pNextStub = g_FirstStub;
  1084. while (pCurStub->pNextStub)
  1085. {
  1086. if (pCurStub->pNextStub == pStubList)
  1087. {
  1088. pCurStub->pNextStub = pStubList->pNextStub;
  1089. g_FirstStub = CurStub.pNextStub;
  1090. FREE(pStubList);
  1091. break;
  1092. }
  1093. pCurStub = pCurStub->pNextStub;
  1094. }
  1095. fLastRelease = TRUE;
  1096. }
  1097. }
  1098. cCritSect.Leave();
  1099. if (fLastRelease)
  1100. {
  1101. // send the quit command to the stub,
  1102. if (S_OK == ReleaseStub())
  1103. {
  1104. // Review, what if stubthread never dies.
  1105. m_dwNestCount++;
  1106. DoModalLoop(m_hThreadStub,NULL,NULL,TRUE,INFINITE); // sit in loop until the stub thread dies
  1107. CloseHandle(m_hThreadStub);
  1108. m_dwNestCount--;
  1109. }
  1110. }
  1111. m_pStubId = NULL; // clear StubId
  1112. }
  1113. delete this;
  1114. return cRefs;
  1115. }
  1116. //+---------------------------------------------------------------------------
  1117. //
  1118. // Member: CThreadMsgProxy::Initialize, public
  1119. //
  1120. // Synopsis: Sends Initialize command to the Handler thread
  1121. // Arguments: [dwReserved] - reserved.
  1122. // [dwSyncFlags] - syncflags
  1123. // [cbCookie] - size of cookie data
  1124. // [lpCookie] - ptr to any cookie data
  1125. //
  1126. // Returns: Appropriate error code
  1127. //
  1128. // Modifies:
  1129. //
  1130. // History: 05-Nov-97 rogerg Created.
  1131. //
  1132. //----------------------------------------------------------------------------
  1133. STDMETHODIMP CThreadMsgProxy::Initialize(DWORD dwReserved,
  1134. DWORD dwSyncFlags,
  1135. DWORD cbCookie,
  1136. const BYTE *lpCookie)
  1137. {
  1138. HRESULT hr = S_OK;
  1139. MSGInitialize msg;
  1140. msg.MsgGen.ThreadMsg = ThreadMsg_Initialize;
  1141. // package up the parameters
  1142. msg.dwReserved = dwReserved;
  1143. msg.dwSyncFlags = dwSyncFlags;
  1144. msg.cbCookie = cbCookie;
  1145. msg.lpCookie = lpCookie;
  1146. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,FALSE);
  1147. return hr;
  1148. }
  1149. //+---------------------------------------------------------------------------
  1150. //
  1151. // Member: CThreadMsgProxy::GetHandlerInfo, public
  1152. //
  1153. // Synopsis: Sends GetHandler command to the Handler thread
  1154. // Arguments: [ppSyncMgrHandlerInfo] - pointer to SyncMgrHandlerInfo pointer
  1155. //
  1156. // Returns: Appropriate error code
  1157. //
  1158. // Modifies:
  1159. //
  1160. // History: 05-Nov-97 rogerg Created.
  1161. //
  1162. //----------------------------------------------------------------------------
  1163. STDMETHODIMP CThreadMsgProxy::GetHandlerInfo(LPSYNCMGRHANDLERINFO *ppSyncMgrHandlerInfo)
  1164. {
  1165. HRESULT hr = S_OK;
  1166. MSGGetHandlerInfo msg;
  1167. msg.MsgGen.ThreadMsg = ThreadMsg_Initialize;
  1168. // package up the parameters
  1169. msg.ppSyncMgrHandlerInfo = ppSyncMgrHandlerInfo;
  1170. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,FALSE);
  1171. return hr;
  1172. }
  1173. //+---------------------------------------------------------------------------
  1174. //
  1175. // Member: CThreadMsgProxy::EnumOfflineItems, public
  1176. //
  1177. // Synopsis: Sends Enum command to the Handler thread
  1178. // Should not be called. AddItems method
  1179. // should be called instead
  1180. //
  1181. // Arguments: [ppenumOfflineItems] - reserved.
  1182. //
  1183. // Returns: E_NOTIMPL;
  1184. //
  1185. // Modifies:
  1186. //
  1187. // History: 05-Nov-97 rogerg Created.
  1188. //
  1189. //----------------------------------------------------------------------------
  1190. STDMETHODIMP CThreadMsgProxy::EnumSyncMgrItems(ISyncMgrEnumItems **ppenumOfflineItems)
  1191. {
  1192. AssertSz(0,"EnumMethod Called on Proxy");
  1193. return E_NOTIMPL;
  1194. }
  1195. //+---------------------------------------------------------------------------
  1196. //
  1197. // Member: CThreadMsgProxy::GetItemObject, public
  1198. //
  1199. // Synopsis: Sends GetItemObject command to the Handler thread
  1200. // Arguments: [ItemID] - identifies the item.
  1201. // [riid] - requested interface
  1202. // [ppv] - On success, pointer to object
  1203. //
  1204. // Returns: Appropriate error code
  1205. //
  1206. // Modifies:
  1207. //
  1208. // History: 05-Nov-97 rogerg Created.
  1209. //
  1210. //----------------------------------------------------------------------------
  1211. STDMETHODIMP CThreadMsgProxy::GetItemObject(REFSYNCMGRITEMID ItemID,REFIID riid,void** ppv)
  1212. {
  1213. HRESULT hr = S_OK;
  1214. MSGGetItemObject msg;
  1215. msg.MsgGen.ThreadMsg = ThreadMsg_GetItemObject;
  1216. // package up the parameters
  1217. msg.ItemID = ItemID;
  1218. msg.riid = riid;
  1219. msg.ppv = ppv;
  1220. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,FALSE);
  1221. return hr;
  1222. }
  1223. //+---------------------------------------------------------------------------
  1224. //
  1225. // Member: CThreadMsgProxy::ShowProperties, public
  1226. //
  1227. // Synopsis: Sends ShowProperties command to the Handler thread
  1228. // Arguments: [hWndParent] - hwnd to use as parent of any dialogs
  1229. // [ItemID] - Identifies the Item
  1230. //
  1231. // Returns: Appropriate error code
  1232. //
  1233. // Modifies:
  1234. //
  1235. // History: 05-Nov-97 rogerg Created.
  1236. //
  1237. //----------------------------------------------------------------------------
  1238. STDMETHODIMP CThreadMsgProxy::ShowProperties(HWND hWndParent,REFSYNCMGRITEMID ItemID)
  1239. {
  1240. HRESULT hr = S_OK;
  1241. MSGShowProperties msg;
  1242. msg.MsgGen.ThreadMsg = ThreadMsg_ShowProperties;
  1243. // package up the parameters
  1244. msg.hWndParent = hWndParent;
  1245. msg.ItemID = ItemID;
  1246. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,TRUE);
  1247. return hr;
  1248. }
  1249. //+---------------------------------------------------------------------------
  1250. //
  1251. // Member: CThreadMsgProxy::SetProgressCallback, public
  1252. //
  1253. // Synopsis: Sends SetProgressCallback command to the Handler thread
  1254. // This method should not be called, SetupCallback method
  1255. // should be called instead
  1256. //
  1257. // Arguments: [lpCallBack] - Ptr to callback.
  1258. //
  1259. // Returns: Appropriate error code
  1260. //
  1261. // Modifies:
  1262. //
  1263. // History: 05-Nov-97 rogerg Created.
  1264. //
  1265. //----------------------------------------------------------------------------
  1266. STDMETHODIMP CThreadMsgProxy::SetProgressCallback(ISyncMgrSynchronizeCallback *lpCallBack)
  1267. {
  1268. AssertSz(0,"SetProgressCallback called on Proxy");
  1269. return E_NOTIMPL;
  1270. }
  1271. //+---------------------------------------------------------------------------
  1272. //
  1273. // Member: CThreadMsgProxy::PrepareForSync, public
  1274. //
  1275. // Synopsis: Sends PrepareForSync command to the Handler thread
  1276. //
  1277. // Arguments: [cbNumItems] - Number of items in the pItemIDs array.
  1278. // [pItemIDs] - array of item ids
  1279. // [hWndParent] - hwnd to use as the parent for any dialogs
  1280. // [dwReserved] - Reserved parameter.
  1281. //
  1282. // Returns: Appropriate error code
  1283. //
  1284. // Modifies:
  1285. //
  1286. // History: 05-Nov-97 rogerg Created.
  1287. //
  1288. //----------------------------------------------------------------------------
  1289. STDMETHODIMP CThreadMsgProxy::PrepareForSync(ULONG cbNumItems,SYNCMGRITEMID *pItemIDs,
  1290. HWND hWndParent,DWORD dwReserved)
  1291. {
  1292. HRESULT hr = S_OK;
  1293. MSGPrepareForSync msg;
  1294. msg.MsgGen.ThreadMsg = ThreadMsg_PrepareForSync;
  1295. // package up the parameters
  1296. msg.cbNumItems = cbNumItems;
  1297. msg.pItemIDs = pItemIDs;
  1298. msg.hWndParent = hWndParent;
  1299. msg.dwReserved = dwReserved;
  1300. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,TRUE);
  1301. return hr;
  1302. }
  1303. //+---------------------------------------------------------------------------
  1304. //
  1305. // Member: CThreadMsgProxy::Synchronize, public
  1306. //
  1307. // Synopsis: Sends Synchronize command to the Handler thread
  1308. //
  1309. // Arguments: [hWndParent] - hwnd to use as the parent for any dialogs
  1310. //
  1311. // Returns: Appropriate error code
  1312. //
  1313. // Modifies:
  1314. //
  1315. // History: 05-Nov-97 rogerg Created.
  1316. //
  1317. //----------------------------------------------------------------------------
  1318. STDMETHODIMP CThreadMsgProxy::Synchronize(HWND hWndParent)
  1319. {
  1320. HRESULT hr = S_OK;
  1321. MSGSynchronize msg;
  1322. msg.MsgGen.ThreadMsg = ThreadMsg_Synchronize;
  1323. // package up the parameters
  1324. msg.hWndParent = hWndParent;
  1325. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,TRUE);
  1326. return hr;
  1327. }
  1328. //+---------------------------------------------------------------------------
  1329. //
  1330. // Member: CThreadMsgProxy::SetItemStatus, public
  1331. //
  1332. // Synopsis: Sends SetItemStatus command to the Handler thread
  1333. //
  1334. // Arguments: [ItemID] - Identifies the item
  1335. // [dwSyncMgrStatus] - Status to set the item too.
  1336. //
  1337. // Returns: Appropriate error code
  1338. //
  1339. // Modifies:
  1340. //
  1341. // History: 05-Nov-97 rogerg Created.
  1342. //
  1343. //----------------------------------------------------------------------------
  1344. STDMETHODIMP CThreadMsgProxy::SetItemStatus(REFSYNCMGRITEMID ItemID,DWORD dwSyncMgrStatus)
  1345. {
  1346. HRESULT hr = S_OK;
  1347. MSGSetItemStatus msg;
  1348. msg.MsgGen.ThreadMsg = ThreadMsg_SetItemStatus;
  1349. // package up the parameters
  1350. msg.ItemID = ItemID;
  1351. msg.dwSyncMgrStatus = dwSyncMgrStatus;
  1352. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,FALSE);
  1353. return hr;
  1354. }
  1355. //+---------------------------------------------------------------------------
  1356. //
  1357. // Member: CThreadMsgProxy::ShowError, public
  1358. //
  1359. // Synopsis: Sends ShowError command to the Handler thread
  1360. //
  1361. // Arguments: [hWndParent] - hwnd to use as the parent for any dialogs
  1362. // [dwErrorID] - Identifies the Error.
  1363. //
  1364. // Returns: Appropriate error code
  1365. //
  1366. // Modifies:
  1367. //
  1368. // History: 05-Nov-97 rogerg Created.
  1369. //
  1370. //----------------------------------------------------------------------------
  1371. STDMETHODIMP CThreadMsgProxy::ShowError(HWND hWndParent,REFSYNCMGRERRORID ErrorID,ULONG *pcbNumItems,SYNCMGRITEMID **ppItemIDs)
  1372. {
  1373. HRESULT hr = S_OK;
  1374. MSGShowConflicts msg;
  1375. msg.MsgGen.ThreadMsg = ThreadMsg_ShowError;
  1376. // package up the parameters
  1377. msg.hWndParent = hWndParent;
  1378. msg.ErrorID = ErrorID;
  1379. msg.pcbNumItems = pcbNumItems;
  1380. msg.ppItemIDs = ppItemIDs;
  1381. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,TRUE);
  1382. return hr;
  1383. }
  1384. //+---------------------------------------------------------------------------
  1385. //
  1386. // Member: CThreadMsgProxy::CreateServer, public
  1387. //
  1388. // Synopsis: Sends CreateServer command to the Handler thread
  1389. //
  1390. // Arguments: [pCLSIDServer] - clsid of handler to create
  1391. // [pHndlrQueue] - Queue the handler belongs too.
  1392. // [wHandlerId] - ID assigned to this instance of the Handler
  1393. //
  1394. // Returns: Appropriate error code
  1395. //
  1396. // Modifies:
  1397. //
  1398. // History: 05-Nov-97 rogerg Created.
  1399. //
  1400. //----------------------------------------------------------------------------
  1401. STDMETHODIMP CThreadMsgProxy::CreateServer(const CLSID *pCLSIDServer,CHndlrQueue *pHndlrQueue,
  1402. HANDLERINFO *pHandlerId)
  1403. {
  1404. HRESULT hr = S_OK;
  1405. MSGCreateServer msg;
  1406. m_pHndlrQueue = pHndlrQueue;
  1407. m_pHandlerId = pHandlerId;
  1408. msg.MsgGen.ThreadMsg = ThreadMsg_CreateServer;
  1409. // package up the parameters
  1410. msg.pCLSIDServer = pCLSIDServer;
  1411. msg.pHndlrQueue = pHndlrQueue;
  1412. msg.pHandlerId = pHandlerId;
  1413. msg.dwProxyThreadId = m_ThreadIdProxy;
  1414. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,FALSE);
  1415. return hr;
  1416. }
  1417. //+---------------------------------------------------------------------------
  1418. //
  1419. // Member: CThreadMsgProxy::SetHndlrQueue, public
  1420. //
  1421. // Synopsis: Assigns a new queue to the Handler
  1422. //
  1423. // Arguments: [pHndlrQueue] - Queue the handler now belongs too.
  1424. // [wHandlerId] - ID assigned to this instance of the Handler
  1425. // [dwThreadIdProxy] - ThreadID the queue is in.
  1426. //
  1427. // Returns: Appropriate error code
  1428. //
  1429. // Modifies:
  1430. //
  1431. // History: 05-Nov-97 rogerg Created.
  1432. //
  1433. //----------------------------------------------------------------------------
  1434. STDMETHODIMP CThreadMsgProxy::SetHndlrQueue(CHndlrQueue *pHndlrQueue,
  1435. HANDLERINFO *pHandlerId,
  1436. DWORD dwThreadIdProxy)
  1437. {
  1438. HRESULT hr = S_OK;
  1439. MSGSetHndlrQueue msg;
  1440. AssertSz(0,"this shouldn't be called");
  1441. m_ThreadIdProxy = dwThreadIdProxy; // update the threadId the Proxy is on.
  1442. msg.MsgGen.ThreadMsg = ThreadMsg_SetHndlrQueue;
  1443. // package up the parameters
  1444. msg.pHndlrQueue = pHndlrQueue;
  1445. msg.pHandlerId = pHandlerId;
  1446. msg.dwProxyThreadId = dwThreadIdProxy;
  1447. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,FALSE);
  1448. return hr;
  1449. }
  1450. //+---------------------------------------------------------------------------
  1451. //
  1452. // Member: CThreadMsgProxy::AddHandlerItems, public
  1453. //
  1454. // Synopsis: Request Handler adds its items to the queue.
  1455. //
  1456. // Arguments: [hwndList] - Currently not used..
  1457. //
  1458. // Returns: Appropriate error code
  1459. //
  1460. // Modifies:
  1461. //
  1462. // History: 05-Nov-97 rogerg Created.
  1463. //
  1464. //----------------------------------------------------------------------------
  1465. STDMETHODIMP CThreadMsgProxy::AddHandlerItems(HWND hwndList,DWORD *pcbNumItems)
  1466. {
  1467. HRESULT hr = S_OK;
  1468. MSGAddItemHandler msg;
  1469. msg.MsgGen.ThreadMsg = ThreadMsg_AddHandlerItems;
  1470. // package up the parameters
  1471. msg.hwndList = hwndList;
  1472. msg.pcbNumItems = pcbNumItems;
  1473. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,FALSE);
  1474. return hr;
  1475. }
  1476. //+---------------------------------------------------------------------------
  1477. //
  1478. // Member: CThreadMsgProxy::SetupCallback, public
  1479. //
  1480. // Synopsis: Request stub sets up the Callback.
  1481. //
  1482. // Arguments: [fSet] - TRUE == set the callback, FALSE == revoke it.
  1483. //
  1484. // Returns: Appropriate error code
  1485. //
  1486. // Modifies:
  1487. //
  1488. // History: 05-Nov-97 rogerg Created.
  1489. //
  1490. //----------------------------------------------------------------------------
  1491. STDMETHODIMP CThreadMsgProxy::SetupCallback(BOOL fSet)
  1492. {
  1493. HRESULT hr = S_OK;
  1494. MSGSetupCallback msg;
  1495. AssertSz(0,"Shouldn't be called");
  1496. msg.MsgGen.ThreadMsg = ThreadMsg_SetupCallback;
  1497. // package up the parameters
  1498. msg.fSet = fSet;
  1499. hr = DispatchMsg( (GenericMsg *) &msg,TRUE,FALSE);
  1500. return hr;
  1501. }
  1502. //+---------------------------------------------------------------------------
  1503. //
  1504. // Member: CThreadMsgProxy::SetProxyParams, public
  1505. //
  1506. // Synopsis: informs server thread that the queue has been chagned
  1507. // on it..
  1508. //
  1509. // Arguments:
  1510. //
  1511. // Returns: Appropriate error code
  1512. //
  1513. // Modifies:
  1514. //
  1515. // History: 05-Nov-97 rogerg Created.
  1516. //
  1517. //----------------------------------------------------------------------------
  1518. STDMETHODIMP CThreadMsgProxy::SetProxyParams(HWND hwndDlg, DWORD ThreadIdProxy,
  1519. CHndlrQueue *pHndlrQueue,HANDLERINFO *pHandlerId )
  1520. {
  1521. m_hwndDlg = hwndDlg;
  1522. m_ThreadIdProxy = ThreadIdProxy;
  1523. m_pHndlrQueue = pHndlrQueue;
  1524. m_pHandlerId = pHandlerId;
  1525. Assert(m_pCHndlrMsg);
  1526. if (m_pCHndlrMsg)
  1527. {
  1528. m_pCHndlrMsg->SetHndlrQueue(pHndlrQueue,pHandlerId,m_ThreadIdProxy);
  1529. }
  1530. return S_OK;
  1531. }
  1532. //+---------------------------------------------------------------------------
  1533. //
  1534. // Member: CThreadMsgProxy::SetProxyCompletion, public
  1535. //
  1536. // Synopsis: sets values for any completion notification to
  1537. // post when returning from an out call
  1538. //
  1539. // Arguments:
  1540. //
  1541. // Returns: Appropriate error code
  1542. //
  1543. // Modifies:
  1544. //
  1545. // History: 05-Nov-97 rogerg Created.
  1546. //
  1547. //----------------------------------------------------------------------------
  1548. STDMETHODIMP CThreadMsgProxy::SetProxyCompletion(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
  1549. {
  1550. Assert(FALSE == m_fHaveCompletionCall); // should only ever have one.
  1551. if (m_fHaveCompletionCall) // if already have a completion fail.
  1552. return S_FALSE;
  1553. m_fHaveCompletionCall = TRUE;
  1554. m_msgCompletion.hwnd = hWnd;
  1555. m_msgCompletion.message = Msg;
  1556. m_msgCompletion.wParam = wParam;
  1557. m_msgCompletion.lParam = lParam;
  1558. return S_OK;
  1559. }
  1560. //+---------------------------------------------------------------------------
  1561. //
  1562. // Member: CMsgServiceHwnd::CMsgServiceHwnd, public
  1563. //
  1564. // Synopsis: Constructor
  1565. //
  1566. // Arguments:
  1567. //
  1568. // Returns:
  1569. //
  1570. // Modifies:
  1571. //
  1572. // History: 05-Nov-97 rogerg Created.
  1573. //
  1574. //----------------------------------------------------------------------------
  1575. CMsgServiceHwnd::CMsgServiceHwnd()
  1576. {
  1577. m_hwnd = NULL;
  1578. m_dwThreadID = -1;
  1579. m_pHndlrMsg = NULL;
  1580. m_fInOutCall = FALSE;
  1581. m_pMsgServiceQueue = NULL;
  1582. m_MsgHwndType = MSGHWNDTYPE_UNDEFINED;
  1583. }
  1584. //+---------------------------------------------------------------------------
  1585. //
  1586. // Member: CMsgServiceHwnd::~CMsgServiceHwnd, public
  1587. //
  1588. // Synopsis: Destructor
  1589. //
  1590. // Arguments:
  1591. //
  1592. // Returns:
  1593. //
  1594. // Modifies:
  1595. //
  1596. // History: 05-Nov-97 rogerg Created.
  1597. //
  1598. //----------------------------------------------------------------------------
  1599. CMsgServiceHwnd::~CMsgServiceHwnd()
  1600. {
  1601. }
  1602. //+---------------------------------------------------------------------------
  1603. //
  1604. // Member: CMsgServiceHwnd::Initialize, public
  1605. //
  1606. // Synopsis: Initializes the service HWND
  1607. //
  1608. // Arguments: [dwThreadID] - id of thread hwnd belongs too.
  1609. // [MsgHwndType] - type of MsgHwnd this is.
  1610. //
  1611. // Returns: TRUE on success, FALSE on failure
  1612. //
  1613. // Modifies:
  1614. //
  1615. // History: 05-Nov-97 rogerg Created.
  1616. //
  1617. //----------------------------------------------------------------------------
  1618. BOOL CMsgServiceHwnd::Initialize(DWORD dwThreadID,MSGHWNDTYPE MsgHwndType)
  1619. {
  1620. BOOL fInitialized = FALSE;
  1621. TCHAR szWinTitle[MAX_STRING_RES];
  1622. m_MsgHwndType = MsgHwndType;
  1623. LoadString(g_hInst, IDS_SYNCMGRNAME, szWinTitle, ARRAYSIZE(szWinTitle));
  1624. m_hwnd = CreateWindowEx(0,
  1625. TEXT(MSGSERVICE_HWNDCLASSNAME),
  1626. szWinTitle,
  1627. // must use WS_POPUP so the window does not get
  1628. // assigned a hot key by user.
  1629. WS_DISABLED | WS_POPUP,
  1630. CW_USEDEFAULT,
  1631. CW_USEDEFAULT,
  1632. CW_USEDEFAULT,
  1633. CW_USEDEFAULT,
  1634. NULL, // REVIEW, can we give it a parent to not show up.
  1635. NULL,
  1636. g_hInst,
  1637. this);
  1638. Assert(m_hwnd);
  1639. if (m_hwnd)
  1640. {
  1641. m_dwThreadID = dwThreadID;
  1642. fInitialized = TRUE;
  1643. }
  1644. if (!fInitialized)
  1645. {
  1646. Assert(NULL == m_pHndlrMsg);
  1647. }
  1648. // caller still needs to call Destroy if initialize returns false.
  1649. return fInitialized;
  1650. }
  1651. //+---------------------------------------------------------------------------
  1652. //
  1653. // Member: CMsgServiceHwnd::Destroy, public
  1654. //
  1655. // Synopsis: Destroys the ServiceHwnd
  1656. //
  1657. // Arguments:
  1658. // Returns:
  1659. //
  1660. // Modifies:
  1661. //
  1662. // History: 05-Nov-97 rogerg Created.
  1663. //
  1664. //----------------------------------------------------------------------------
  1665. void CMsgServiceHwnd::Destroy()
  1666. {
  1667. BOOL fDestroy;
  1668. // HANDLER m_pHndlrMsg will be destroyed by the Release HandleThreadMessage call
  1669. // only case that it shouldn't is if for some reason CreateThreadHndlr failed
  1670. Assert(NULL == m_pHndlrMsg);
  1671. if (m_pHndlrMsg)
  1672. {
  1673. m_pHndlrMsg->Release();
  1674. m_pHndlrMsg = NULL;
  1675. }
  1676. if (m_hwnd)
  1677. {
  1678. fDestroy = DestroyWindow(m_hwnd);
  1679. Assert(fDestroy);
  1680. }
  1681. delete this;
  1682. }
  1683. //+---------------------------------------------------------------------------
  1684. //
  1685. // Member: CMsgServiceHwnd::MsgThreadWndProc, public
  1686. //
  1687. // Synopsis: Servicer Side message handling window.
  1688. //
  1689. // Arguments:
  1690. // Returns:
  1691. //
  1692. // Modifies:
  1693. //
  1694. // History: 05-Nov-97 rogerg Created.
  1695. //
  1696. //----------------------------------------------------------------------------
  1697. LRESULT CALLBACK MsgThreadWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  1698. {
  1699. CMsgServiceHwnd *pThis = (CMsgServiceHwnd *) GetWindowLongPtr(hWnd, DWL_THREADWNDPROCCLASS);
  1700. if (pThis || (msg == WM_CREATE))
  1701. {
  1702. switch (msg)
  1703. {
  1704. case WM_CREATE :
  1705. {
  1706. CREATESTRUCT *pCreateStruct = (CREATESTRUCT *) lParam;
  1707. SetWindowLongPtr(hWnd, DWL_THREADWNDPROCCLASS,(LONG_PTR) pCreateStruct->lpCreateParams );
  1708. pThis = (CMsgServiceHwnd *) pCreateStruct->lpCreateParams ;
  1709. }
  1710. break;
  1711. case WM_DESTROY:
  1712. SetWindowLongPtr(hWnd, DWL_THREADWNDPROCCLASS,(LONG_PTR) NULL);
  1713. PostQuitMessage(0); // no longer need this thread
  1714. break;
  1715. case WM_THREADSTUBMESSAGE: // message send only to stub.
  1716. {
  1717. MessagingInfo *pmsgInfo = (MessagingInfo *) wParam;
  1718. GenericMsg *pgenMsg = (GenericMsg *) lParam;
  1719. Assert(MSGHWNDTYPE_HANDLERTHREAD == pThis->m_MsgHwndType);
  1720. pgenMsg->hr = E_UNEXPECTED;
  1721. switch(pgenMsg->ThreadMsg)
  1722. {
  1723. case StubMsg_Release:
  1724. // proxy is telling us there is no need to stick around
  1725. // any longer so post a quit message.
  1726. Assert(NULL == pThis->m_pHndlrMsg);
  1727. pThis->Destroy(); // no longer need this
  1728. pgenMsg->hr = S_OK;
  1729. break;
  1730. case StubMsg_CreateNewStub:
  1731. // proxy is telling us there is no need to stick around
  1732. // any longer so post a quit message.
  1733. pThis->m_pHndlrMsg = new CHndlrMsg;
  1734. ((MSGSTUBCreateStub *) pgenMsg)->pCHndlrMsg = pThis->m_pHndlrMsg;
  1735. pThis->m_pHndlrMsg = NULL;
  1736. pgenMsg->hr = S_OK;
  1737. break;
  1738. default:
  1739. AssertSz(0,"Unknown StubMessage");
  1740. break;
  1741. };
  1742. if (pmsgInfo->hMsgEvent)
  1743. {
  1744. SetEvent(pmsgInfo->hMsgEvent);
  1745. }
  1746. }
  1747. break;
  1748. case WM_THREADMESSAGE:
  1749. {
  1750. MessagingInfo *pmsgInfo = (MessagingInfo *) wParam;
  1751. GenericMsg *pgenMsg = (GenericMsg *) lParam;
  1752. Assert(MSGHWNDTYPE_HANDLERTHREAD == pThis->m_MsgHwndType);
  1753. pThis->HandleThreadMessage(pmsgInfo,pgenMsg);
  1754. // won't be an hEvent on an async call
  1755. if (pmsgInfo->hMsgEvent)
  1756. {
  1757. SetEvent(pmsgInfo->hMsgEvent);
  1758. }
  1759. // on an async call we free
  1760. }
  1761. break;
  1762. case WM_CFACTTHREAD_REVOKE:
  1763. {
  1764. Assert(MSGHWNDTYPE_MAINTHREAD == pThis->m_MsgHwndType);
  1765. HRESULT hr = CoRevokeClassObject((DWORD)wParam);
  1766. Assert(S_OK == hr);
  1767. }
  1768. break;
  1769. case WM_MAINTHREAD_QUIT: // handles shutdown of main thread.
  1770. {
  1771. HANDLE hThread = (HANDLE) lParam;
  1772. Assert(MSGHWNDTYPE_MAINTHREAD == pThis->m_MsgHwndType);
  1773. // set ShuttingDown Flag for race conditions with QueryEnd,
  1774. // before yielding.
  1775. g_fShuttingDown = TRUE;
  1776. // if there is an hThread that was passed wait until it goes away
  1777. Assert(0 == hThread); // we currently don't support this.
  1778. if (hThread)
  1779. {
  1780. WaitForSingleObject(hThread,INFINITE);
  1781. CloseHandle(hThread);
  1782. }
  1783. // if have a queryEndSession object state its okay to return now
  1784. // no need to cleanup window.
  1785. if (g_hEndSessionEvent)
  1786. {
  1787. HANDLE hEvent = g_hEndSessionEvent;
  1788. // g_hEndSessionEvent = NULL; // leave EndSession NON-Null since only need to handle one.
  1789. SetEvent(hEvent);
  1790. }
  1791. else
  1792. {
  1793. pThis->Destroy(); // Clean up this window.
  1794. }
  1795. }
  1796. break;
  1797. case WM_QUERYENDSESSION:
  1798. {
  1799. HWND hwndQueryParent;
  1800. UINT uiMessageID;
  1801. BOOL fLetUserDecide;
  1802. BOOL fReturn = TRUE;
  1803. // only handle this message if it is the main thread window
  1804. if (MSGHWNDTYPE_MAINTHREAD != pThis->m_MsgHwndType)
  1805. {
  1806. break;
  1807. }
  1808. if (!g_fShuttingDown
  1809. && (S_FALSE == ObjMgr_HandleQueryEndSession(&hwndQueryParent,&uiMessageID,&fLetUserDecide)))
  1810. {
  1811. TCHAR pszTitle[MAX_PATH];
  1812. TCHAR pszMessageText[MAX_PATH];
  1813. UINT uType; // style of messagebox.
  1814. int iEndSession;
  1815. LoadString(g_hInst,IDS_SYNCMGRNAME,pszTitle,sizeof(pszTitle)/sizeof(TCHAR));
  1816. LoadString(g_hInst,uiMessageID,pszMessageText,sizeof(pszMessageText)/sizeof(TCHAR));
  1817. if (fLetUserDecide)
  1818. {
  1819. uType = MB_YESNO | MB_ICONEXCLAMATION | MB_SETFOREGROUND;
  1820. }
  1821. else
  1822. {
  1823. uType = MB_OK | MB_ICONSTOP | MB_SETFOREGROUND;
  1824. }
  1825. iEndSession = MessageBox(hwndQueryParent, pszMessageText, pszTitle, uType);
  1826. if (!fLetUserDecide || IDYES != iEndSession)
  1827. {
  1828. fReturn = FALSE; // FALSE causes system to stop the shutdown.
  1829. }
  1830. }
  1831. // if we are going to allow shutdown cleanup our threads
  1832. // before returning since on Win9x its too late afterwards.
  1833. if (fReturn)
  1834. {
  1835. HANDLE hEndSessionEvent = NULL;
  1836. // its possible that another QUERYENDSESSION comes
  1837. // in while we are still shutting down. If already
  1838. // handling an end sessios or in WM_MAINTHREAD_QUIT just fall through
  1839. if (NULL == g_hEndSessionEvent && !g_fShuttingDown)
  1840. {
  1841. g_hEndSessionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  1842. hEndSessionEvent = g_hEndSessionEvent;
  1843. ObjMgr_CloseAll(); // start the process of closing down the dialogs.
  1844. Assert(hEndSessionEvent);
  1845. // wait until other threads have cleaned up so we know its safe to terminate.
  1846. if (hEndSessionEvent)
  1847. {
  1848. DoModalLoop(hEndSessionEvent ,NULL,NULL,TRUE,INFINITE);
  1849. CloseHandle(hEndSessionEvent);
  1850. }
  1851. }
  1852. }
  1853. return fReturn;
  1854. }
  1855. break;
  1856. default:
  1857. break;
  1858. }
  1859. }
  1860. return DefWindowProc(hWnd, msg, wParam, lParam);
  1861. }
  1862. //+---------------------------------------------------------------------------
  1863. //
  1864. // Function: InitMessageService, public
  1865. //
  1866. // Synopsis: Initializes our internal thread messaging service.
  1867. // Must be called before any Messagin is done.
  1868. //
  1869. // Arguments:
  1870. // Returns: S_OK if Service was successfully initialized.
  1871. //
  1872. // Modifies:
  1873. //
  1874. // History: 05-Nov-97 rogerg Created.
  1875. //
  1876. //----------------------------------------------------------------------------
  1877. STDAPI InitMessageService()
  1878. {
  1879. ATOM aWndClass = 0;
  1880. WNDCLASS xClass;
  1881. DWORD dwErr;
  1882. // initialize the proxy critical section
  1883. if (InitializeCriticalSectionAndSpinCount(&g_StubListCriticalSection, 0))
  1884. {
  1885. // Register windows class.we need for handling thread communication
  1886. xClass.style = 0;
  1887. xClass.lpfnWndProc = MsgThreadWndProc;
  1888. xClass.cbClsExtra = 0;
  1889. xClass.cbWndExtra = sizeof(PVOID); // room for class this ptr
  1890. xClass.hInstance = g_hInst;
  1891. xClass.hIcon = NULL;
  1892. xClass.hCursor = NULL;
  1893. xClass.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
  1894. xClass.lpszMenuName = NULL;
  1895. xClass.lpszClassName = TEXT(MSGSERVICE_HWNDCLASSNAME);
  1896. aWndClass = RegisterClass( &xClass );
  1897. dwErr = GetLastError();
  1898. Assert(aWndClass);
  1899. }
  1900. return (0 == aWndClass) ? S_FALSE : S_OK;
  1901. }