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

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