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.

1370 lines
31 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: fdtipc.cpp
  6. * Content: Implements the IPC calls for the full duplex test
  7. * History:
  8. * Date By Reason
  9. * ============
  10. * 08/26/99 pnewson created
  11. * 04/19/2000 pnewson Error handling cleanup
  12. * 06/28/2000 rodtoll Prefix Bug #38022
  13. * 03/01/2002 simonpow Bug #550054. Fixed CreateProcess calls to specifiy
  14. * both app name and command line
  15. ***************************************************************************/
  16. #include "dxvtlibpch.h"
  17. #undef DPF_SUBCOMP
  18. #define DPF_SUBCOMP DN_SUBCOMP_VOICE
  19. // static helper functions for this file
  20. HRESULT DoReceive(
  21. SFDTestCommand* pfdtc,
  22. HANDLE hEvent,
  23. HANDLE hReplyEvent,
  24. LPVOID lpvShMemPtr);
  25. HRESULT DoReply(HRESULT hr, HANDLE hReplyEvent, LPVOID lpvShMemPtr);
  26. #undef DPF_MODNAME
  27. #define DPF_MODNAME "CSupervisorIPC::CSupervisorIPC"
  28. CSupervisorIPC::CSupervisorIPC()
  29. : m_fInitComplete(FALSE)
  30. , m_hFullDuplexEvent(NULL)
  31. , m_hFullDuplexMutex(NULL)
  32. , m_hFullDuplexReplyEvent(NULL)
  33. , m_hFullDuplexShMemHandle(NULL)
  34. , m_hPriorityEvent(NULL)
  35. , m_hPriorityMutex(NULL)
  36. , m_hPriorityReplyEvent(NULL)
  37. , m_hPriorityShMemHandle(NULL)
  38. , m_lpvFullDuplexShMemPtr(NULL)
  39. , m_lpvPriorityShMemPtr(NULL)
  40. {
  41. ZeroMemory(&m_piFullDuplex, sizeof(PROCESS_INFORMATION));
  42. ZeroMemory(&m_piPriority, sizeof(PROCESS_INFORMATION));
  43. return;
  44. }
  45. #undef DPF_MODNAME
  46. #define DPF_MODNAME "CSupervisorIPC::Init"
  47. HRESULT CSupervisorIPC::Init()
  48. {
  49. LONG lRet;
  50. HRESULT hr;
  51. DPF_ENTER();
  52. if (!DNInitializeCriticalSection(&m_csLock))
  53. {
  54. return DVERR_OUTOFMEMORY;
  55. }
  56. DNEnterCriticalSection(&m_csLock);
  57. if (m_fInitComplete != FALSE)
  58. {
  59. hr = DVERR_GENERIC;
  60. goto error_cleanup;
  61. }
  62. // create the event objects - make sure they don't already
  63. // exist!
  64. m_hPriorityEvent = CreateEvent(NULL, FALSE, FALSE, gc_szPriorityEventName);
  65. lRet = GetLastError();
  66. if (m_hPriorityEvent == NULL)
  67. {
  68. hr = DVERR_GENERIC;
  69. goto error_cleanup;
  70. }
  71. if (lRet == ERROR_ALREADY_EXISTS)
  72. {
  73. hr = DVERR_GENERIC;
  74. goto error_cleanup;
  75. }
  76. m_hFullDuplexEvent = CreateEvent(NULL, FALSE, FALSE, gc_szFullDuplexEventName);
  77. lRet = GetLastError();
  78. if (m_hFullDuplexEvent == NULL)
  79. {
  80. hr = DVERR_GENERIC;
  81. goto error_cleanup;
  82. }
  83. if (lRet == ERROR_ALREADY_EXISTS)
  84. {
  85. hr = DVERR_GENERIC;
  86. goto error_cleanup;
  87. }
  88. m_hPriorityReplyEvent = CreateEvent(NULL, FALSE, FALSE, gc_szPriorityReplyEventName);
  89. lRet = GetLastError();
  90. if (m_hPriorityReplyEvent == NULL)
  91. {
  92. hr = DVERR_GENERIC;
  93. goto error_cleanup;
  94. }
  95. if (lRet == ERROR_ALREADY_EXISTS)
  96. {
  97. hr = DVERR_GENERIC;
  98. goto error_cleanup;
  99. }
  100. m_hFullDuplexReplyEvent = CreateEvent(NULL, FALSE, FALSE, gc_szFullDuplexReplyEventName);
  101. lRet = GetLastError();
  102. if (m_hFullDuplexReplyEvent == NULL)
  103. {
  104. hr = DVERR_GENERIC;
  105. goto error_cleanup;
  106. }
  107. if (lRet == ERROR_ALREADY_EXISTS)
  108. {
  109. hr = DVERR_GENERIC;
  110. goto error_cleanup;
  111. }
  112. // create the shared memory blocks
  113. m_hPriorityShMemHandle = CreateFileMapping(
  114. INVALID_HANDLE_VALUE,
  115. NULL,
  116. PAGE_READWRITE,
  117. 0,
  118. gc_dwPriorityShMemSize,
  119. gc_szPriorityShMemName);
  120. lRet = GetLastError();
  121. if (m_hPriorityShMemHandle == NULL)
  122. {
  123. hr = DVERR_GENERIC;
  124. goto error_cleanup;
  125. }
  126. if (lRet == ERROR_ALREADY_EXISTS)
  127. {
  128. hr = DVERR_GENERIC;
  129. goto error_cleanup;
  130. }
  131. m_lpvPriorityShMemPtr = MapViewOfFile(
  132. m_hPriorityShMemHandle,
  133. FILE_MAP_WRITE,
  134. 0,
  135. 0,
  136. gc_dwPriorityShMemSize);
  137. if (m_lpvPriorityShMemPtr == NULL)
  138. {
  139. hr = DVERR_GENERIC;
  140. goto error_cleanup;
  141. }
  142. m_hFullDuplexShMemHandle = CreateFileMapping(
  143. INVALID_HANDLE_VALUE,
  144. NULL,
  145. PAGE_READWRITE,
  146. 0,
  147. gc_dwFullDuplexShMemSize,
  148. gc_szFullDuplexShMemName);
  149. lRet = GetLastError();
  150. if (m_hFullDuplexShMemHandle == NULL)
  151. {
  152. hr = DVERR_GENERIC;
  153. goto error_cleanup;
  154. }
  155. if (lRet == ERROR_ALREADY_EXISTS)
  156. {
  157. hr = DVERR_GENERIC;
  158. goto error_cleanup;
  159. }
  160. m_lpvFullDuplexShMemPtr = MapViewOfFile(
  161. m_hFullDuplexShMemHandle,
  162. FILE_MAP_WRITE,
  163. 0,
  164. 0,
  165. gc_dwFullDuplexShMemSize);
  166. if (m_lpvFullDuplexShMemPtr == NULL)
  167. {
  168. hr = DVERR_GENERIC;
  169. goto error_cleanup;
  170. }
  171. // create the send mutexes
  172. m_hPriorityMutex = CreateMutex(NULL, FALSE, gc_szPrioritySendMutex);
  173. lRet = GetLastError();
  174. if (m_hPriorityMutex == NULL)
  175. {
  176. hr = DVERR_GENERIC;
  177. goto error_cleanup;
  178. }
  179. if (lRet == ERROR_ALREADY_EXISTS)
  180. {
  181. hr = DVERR_GENERIC;
  182. goto error_cleanup;
  183. }
  184. m_hFullDuplexMutex = CreateMutex(NULL, FALSE, gc_szFullDuplexSendMutex);
  185. lRet = GetLastError();
  186. if (m_hFullDuplexMutex == NULL)
  187. {
  188. hr = DVERR_GENERIC;
  189. goto error_cleanup;
  190. }
  191. if (lRet == ERROR_ALREADY_EXISTS)
  192. {
  193. hr = DVERR_GENERIC;
  194. goto error_cleanup;
  195. }
  196. m_fInitComplete = TRUE;
  197. DNLeaveCriticalSection(&m_csLock);
  198. DPF_EXIT();
  199. return S_OK;
  200. error_cleanup:
  201. if (m_hFullDuplexMutex != NULL)
  202. {
  203. CloseHandle(m_hFullDuplexMutex);
  204. m_hFullDuplexMutex = NULL;
  205. }
  206. if (m_hPriorityMutex != NULL)
  207. {
  208. CloseHandle(m_hPriorityMutex);
  209. m_hPriorityMutex = NULL;
  210. }
  211. if (m_lpvFullDuplexShMemPtr != NULL)
  212. {
  213. UnmapViewOfFile(m_lpvFullDuplexShMemPtr);
  214. m_lpvFullDuplexShMemPtr = NULL;
  215. }
  216. if (m_hFullDuplexShMemHandle != NULL)
  217. {
  218. CloseHandle(m_hFullDuplexShMemHandle);
  219. m_hFullDuplexShMemHandle = NULL;
  220. }
  221. if (m_lpvPriorityShMemPtr != NULL)
  222. {
  223. UnmapViewOfFile(m_lpvPriorityShMemPtr);
  224. m_lpvPriorityShMemPtr = NULL;
  225. }
  226. if (m_hPriorityShMemHandle != NULL)
  227. {
  228. CloseHandle(m_hPriorityShMemHandle);
  229. m_hPriorityShMemHandle = NULL;
  230. }
  231. if (m_hFullDuplexReplyEvent != NULL)
  232. {
  233. CloseHandle(m_hFullDuplexReplyEvent);
  234. m_hFullDuplexReplyEvent = NULL;
  235. }
  236. if (m_hPriorityReplyEvent != NULL)
  237. {
  238. CloseHandle(m_hPriorityReplyEvent);
  239. m_hPriorityReplyEvent = NULL;
  240. }
  241. if (m_hFullDuplexEvent != NULL)
  242. {
  243. CloseHandle(m_hFullDuplexEvent);
  244. m_hFullDuplexEvent = NULL;
  245. }
  246. if (m_hPriorityEvent != NULL)
  247. {
  248. CloseHandle(m_hPriorityEvent);
  249. m_hPriorityEvent = NULL;
  250. }
  251. DNLeaveCriticalSection(&m_csLock);
  252. DPF_EXIT();
  253. return hr;
  254. }
  255. #undef DPF_MODNAME
  256. #define DPF_MODNAME "CSupervisorIPC::Deinit"
  257. HRESULT CSupervisorIPC::Deinit()
  258. {
  259. LONG lRet;
  260. HRESULT hr = DV_OK;
  261. DPF_ENTER();
  262. DNEnterCriticalSection(&m_csLock);
  263. if (m_fInitComplete != TRUE)
  264. {
  265. hr = DVERR_NOTINITIALIZED;
  266. }
  267. m_fInitComplete = FALSE;
  268. if (m_hFullDuplexMutex != NULL)
  269. {
  270. CloseHandle(m_hFullDuplexMutex);
  271. m_hFullDuplexMutex = NULL;
  272. }
  273. if (m_hPriorityMutex != NULL)
  274. {
  275. CloseHandle(m_hPriorityMutex);
  276. m_hPriorityMutex = NULL;
  277. }
  278. if (m_lpvFullDuplexShMemPtr != NULL)
  279. {
  280. UnmapViewOfFile(m_lpvFullDuplexShMemPtr);
  281. m_lpvFullDuplexShMemPtr = NULL;
  282. }
  283. if (m_hFullDuplexShMemHandle != NULL)
  284. {
  285. CloseHandle(m_hFullDuplexShMemHandle);
  286. m_hFullDuplexShMemHandle = NULL;
  287. }
  288. if (m_lpvPriorityShMemPtr != NULL)
  289. {
  290. UnmapViewOfFile(m_lpvPriorityShMemPtr);
  291. m_lpvPriorityShMemPtr = NULL;
  292. }
  293. if (m_hPriorityShMemHandle != NULL)
  294. {
  295. CloseHandle(m_hPriorityShMemHandle);
  296. m_hPriorityShMemHandle = NULL;
  297. }
  298. if (m_hFullDuplexReplyEvent != NULL)
  299. {
  300. CloseHandle(m_hFullDuplexReplyEvent);
  301. m_hFullDuplexReplyEvent = NULL;
  302. }
  303. if (m_hPriorityReplyEvent != NULL)
  304. {
  305. CloseHandle(m_hPriorityReplyEvent);
  306. m_hPriorityReplyEvent = NULL;
  307. }
  308. if (m_hFullDuplexEvent != NULL)
  309. {
  310. CloseHandle(m_hFullDuplexEvent);
  311. m_hFullDuplexEvent = NULL;
  312. }
  313. if (m_hPriorityEvent != NULL)
  314. {
  315. CloseHandle(m_hPriorityEvent);
  316. m_hPriorityEvent = NULL;
  317. }
  318. DNLeaveCriticalSection(&m_csLock);
  319. DNDeleteCriticalSection(&m_csLock);
  320. DPF_EXIT();
  321. return hr;
  322. }
  323. #undef DPF_MODNAME
  324. #define DPF_MODNAME "CSupervisorIPC::SendToPriority"
  325. HRESULT CSupervisorIPC::SendToPriority(const SFDTestCommand *pfdtc)
  326. {
  327. HRESULT hr;
  328. DPF_ENTER();
  329. DNEnterCriticalSection(&m_csLock);
  330. hr = DoSend(
  331. pfdtc,
  332. m_piPriority.hProcess,
  333. m_hPriorityEvent,
  334. m_hPriorityReplyEvent,
  335. m_lpvPriorityShMemPtr,
  336. m_hPriorityMutex);
  337. DNLeaveCriticalSection(&m_csLock);
  338. DPF_EXIT();
  339. return hr;
  340. }
  341. #undef DPF_MODNAME
  342. #define DPF_MODNAME "CSupervisorIPC::SendToFullDuplex"
  343. HRESULT CSupervisorIPC::SendToFullDuplex(const SFDTestCommand *pfdtc)
  344. {
  345. HRESULT hr;
  346. DPF_ENTER();
  347. DNEnterCriticalSection(&m_csLock);
  348. hr = DoSend(
  349. pfdtc,
  350. m_piFullDuplex.hProcess,
  351. m_hFullDuplexEvent,
  352. m_hFullDuplexReplyEvent,
  353. m_lpvFullDuplexShMemPtr,
  354. m_hFullDuplexMutex);
  355. DNLeaveCriticalSection(&m_csLock);
  356. DPF_EXIT();
  357. return hr;
  358. }
  359. #undef DPF_MODNAME
  360. #define DPF_MODNAME "CSupervisorIPC::DoSend"
  361. HRESULT CSupervisorIPC::DoSend(
  362. const SFDTestCommand* pfdtc,
  363. HANDLE hProcess,
  364. HANDLE hEvent,
  365. HANDLE hReplyEvent,
  366. LPVOID lpvShMemPtr,
  367. HANDLE hMutex)
  368. {
  369. DWORD dwRet;
  370. LONG lRet;
  371. HRESULT hr;
  372. HANDLE hWaitArray[2];
  373. BOOL fHaveMutex = FALSE;
  374. DPF_ENTER();
  375. // grab the mutex
  376. dwRet = WaitForSingleObject(hMutex, gc_dwSendMutexTimeout);
  377. if (dwRet != WAIT_OBJECT_0)
  378. {
  379. if (dwRet == WAIT_TIMEOUT)
  380. {
  381. DPFX(DPFPREP, DVF_ERRORLEVEL, "Timed out waiting for send mutex");
  382. hr = DVERR_TIMEOUT;
  383. goto error_cleanup;
  384. }
  385. lRet = GetLastError();
  386. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error waiting for send mutex, code: %i", lRet);
  387. hr = DVERR_WIN32;
  388. goto error_cleanup;
  389. }
  390. fHaveMutex = TRUE;
  391. // copy the command into shared memory
  392. CopyMemory(lpvShMemPtr, pfdtc, pfdtc->dwSize);
  393. // signal the event
  394. if (!SetEvent(hEvent))
  395. {
  396. lRet = GetLastError();
  397. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to set event, code: %i", lRet);
  398. hr = DVERR_WIN32;
  399. goto error_cleanup;
  400. }
  401. // Wait for the reply event - note that we only expect the
  402. // supervisor process to call this function, and therefore
  403. // we don't check for directsound events occuring during this
  404. // time.
  405. // Also, wait on the process handle, if the process we are sending
  406. // to exits, we'll want to continue right away, not wait for a timeout.
  407. hWaitArray[0] = hReplyEvent;
  408. hWaitArray[1] = hProcess;
  409. dwRet = WaitForMultipleObjects(2, hWaitArray, FALSE, gc_dwCommandReplyTimeout);
  410. switch(dwRet)
  411. {
  412. case WAIT_OBJECT_0:
  413. // The other process replied, move along.
  414. break;
  415. case WAIT_OBJECT_0+1:
  416. // The other process exited!
  417. DPFX(DPFPREP, DVF_ERRORLEVEL, "Process exited while waiting for reply");
  418. hr = DVERR_TIMEOUT;
  419. goto error_cleanup;
  420. case WAIT_TIMEOUT:
  421. // The other process did not reply in a reasonable amount of time.
  422. DPFX(DPFPREP, DVF_ERRORLEVEL, "Timed out waiting for reply to command");
  423. hr = DVERR_TIMEOUT;
  424. goto error_cleanup;
  425. default:
  426. // No idea what happened here...
  427. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error waiting for reply event, code: %i", dwRet);
  428. hr = DVERR_GENERIC;
  429. goto error_cleanup;
  430. }
  431. // get the reply code (an HRESULT) from shared memory
  432. hr = *(HRESULT*)lpvShMemPtr;
  433. // release the mutex
  434. if (!ReleaseMutex(hMutex))
  435. {
  436. lRet = GetLastError();
  437. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error releasing mutex, code: %i", lRet);
  438. hr = DVERR_GENERIC;
  439. goto error_cleanup;
  440. }
  441. DPF_EXIT();
  442. return hr;
  443. error_cleanup:
  444. if (hMutex != NULL)
  445. {
  446. ReleaseMutex(hMutex);
  447. }
  448. DPF_EXIT();
  449. return hr;
  450. }
  451. #undef DPF_MODNAME
  452. #define DPF_MODNAME "CSupervisorIPC::StartPriorityProcess"
  453. HRESULT CSupervisorIPC::StartPriorityProcess()
  454. {
  455. STARTUPINFO si;
  456. DPF_ENTER();
  457. TCHAR szCmdLine[128];
  458. TCHAR szAppName[_MAX_PATH+1];
  459. DNEnterCriticalSection(&m_csLock);
  460. ZeroMemory(&si, sizeof(si));
  461. si.cb = sizeof(si);
  462. BuildLaunchAppName(szAppName);
  463. _tcsncpy( szCmdLine, gc_szPriorityCommand, 127 );
  464. szCmdLine[127] = 0;
  465. if (!CreateProcess(
  466. szAppName,
  467. szCmdLine,
  468. NULL,
  469. NULL,
  470. FALSE,
  471. 0,
  472. NULL,
  473. NULL,
  474. &si,
  475. &m_piPriority))
  476. {
  477. m_piPriority.hProcess = NULL;
  478. m_piPriority.hThread = NULL;
  479. DNLeaveCriticalSection(&m_csLock);
  480. DPF_EXIT();
  481. return DVERR_WIN32;
  482. }
  483. // don't need the thread handle
  484. if (!CloseHandle(m_piPriority.hThread))
  485. {
  486. m_piPriority.hThread = NULL;
  487. DNLeaveCriticalSection(&m_csLock);
  488. DPF_EXIT();
  489. return DVERR_WIN32;
  490. }
  491. DNLeaveCriticalSection(&m_csLock);
  492. DPF_EXIT();
  493. return S_OK;
  494. }
  495. #undef DPF_MODNAME
  496. #define DPF_MODNAME "CSupervisorIPC::WaitOnChildren"
  497. HRESULT CSupervisorIPC::WaitOnChildren()
  498. {
  499. HANDLE rghChildren[2];
  500. DWORD dwRet;
  501. LONG lRet;
  502. HRESULT hr = DV_OK;
  503. BOOL fRet;
  504. DPF_ENTER();
  505. DNEnterCriticalSection(&m_csLock);
  506. rghChildren[0] = m_piPriority.hProcess;
  507. rghChildren[1] = m_piFullDuplex.hProcess;
  508. DNLeaveCriticalSection(&m_csLock);
  509. dwRet = WaitForMultipleObjects(2, rghChildren, TRUE, gc_dwChildWaitTimeout);
  510. if (dwRet == WAIT_TIMEOUT)
  511. {
  512. DPFX(DPFPREP, DVF_ERRORLEVEL, "WaitForMultipleObjects timed out waiting on child process handles");
  513. DPF_EXIT();
  514. return DVERR_CHILDPROCESSFAILED;
  515. }
  516. else if (dwRet == WAIT_OBJECT_0 || dwRet == WAIT_OBJECT_0 + 1)
  517. {
  518. // This is the expected behavior. The processes shut down
  519. // gracefully. Close and NULL out our handles to them.
  520. // Note that just because the process shut down gracefully,
  521. // that does not mean that it did not have an error. The
  522. // process returns an HRESULT for it's exit code. Check it.
  523. // Note that this code assumes HRESULTS are DWORDS. Hopefully
  524. // this won't break in Win64!
  525. DNEnterCriticalSection(&m_csLock);
  526. fRet = GetExitCodeProcess(m_piPriority.hProcess, (LPDWORD)&hr);
  527. if (!fRet || FAILED(hr))
  528. {
  529. lRet = GetLastError();
  530. CloseHandle(m_piPriority.hProcess);
  531. CloseHandle(m_piFullDuplex.hProcess);
  532. m_piPriority.hProcess = NULL;
  533. m_piFullDuplex.hProcess = NULL;
  534. DNLeaveCriticalSection(&m_csLock);
  535. if (!fRet && SUCCEEDED(hr))
  536. {
  537. DPFX(DPFPREP, DVF_ERRORLEVEL, "GetExitCodeProcess failed, lRet: %i", lRet);
  538. DPF_EXIT();
  539. return DVERR_GENERIC;
  540. }
  541. DPFX(DPFPREP, DVF_ERRORLEVEL, "Priority Process exited with error code, hr: %i", hr);
  542. DPF_EXIT();
  543. return hr;
  544. }
  545. if (!CloseHandle(m_piPriority.hProcess))
  546. {
  547. lRet = GetLastError();
  548. CloseHandle(m_piFullDuplex.hProcess);
  549. m_piPriority.hProcess = NULL;
  550. m_piFullDuplex.hProcess = NULL;
  551. DNLeaveCriticalSection(&m_csLock);
  552. DPFX(DPFPREP, DVF_ERRORLEVEL, "CloseHandle failed, lRet: %i", lRet);
  553. DPF_EXIT();
  554. return DVERR_GENERIC;
  555. }
  556. fRet = GetExitCodeProcess(m_piFullDuplex.hProcess, (LPDWORD)&hr);
  557. if (!fRet || FAILED(hr))
  558. {
  559. lRet = GetLastError();
  560. CloseHandle(m_piFullDuplex.hProcess);
  561. m_piPriority.hProcess = NULL;
  562. m_piFullDuplex.hProcess = NULL;
  563. DNLeaveCriticalSection(&m_csLock);
  564. if (!fRet && SUCCEEDED(hr))
  565. {
  566. DPFX(DPFPREP, DVF_ERRORLEVEL, "GetExitCodeProcess failed, lRet: %i", lRet);
  567. DPF_EXIT();
  568. return DVERR_GENERIC;
  569. }
  570. DPFX(DPFPREP, DVF_ERRORLEVEL, "FullDuplex Process exited with error code, hr: %i", hr);
  571. DPF_EXIT();
  572. return hr;
  573. }
  574. if (!CloseHandle(m_piFullDuplex.hProcess))
  575. {
  576. lRet = GetLastError();
  577. m_piPriority.hProcess = NULL;
  578. m_piFullDuplex.hProcess = NULL;
  579. DNLeaveCriticalSection(&m_csLock);
  580. DPFX(DPFPREP, DVF_ERRORLEVEL, "CloseHandle failed, lRet: %i", lRet);
  581. DPF_EXIT();
  582. return DVERR_GENERIC;
  583. }
  584. m_piPriority.hProcess = NULL;
  585. m_piFullDuplex.hProcess = NULL;
  586. DNLeaveCriticalSection(&m_csLock);
  587. DPF_EXIT();
  588. return DV_OK;
  589. }
  590. else
  591. {
  592. // Not sure what happened...
  593. DPF_EXIT();
  594. return DVERR_GENERIC;
  595. }
  596. }
  597. #undef DPF_MODNAME
  598. #define DPF_MODNAME "CSupervisorIPC::TerminateChildProcesses"
  599. HRESULT CSupervisorIPC::TerminateChildProcesses()
  600. {
  601. LONG lRet;
  602. HRESULT hr = DV_OK;
  603. DPF_ENTER();
  604. // The child processes did not exit gracefully. So now
  605. // we get to kill them off rudely. Note that this
  606. // function may be called at any time, including when
  607. // there are no child processes running.
  608. DNEnterCriticalSection(&m_csLock);
  609. if (m_piPriority.hProcess != NULL)
  610. {
  611. if (!TerminateProcess(m_piPriority.hProcess, 0))
  612. {
  613. lRet = GetLastError();
  614. DPFX(DPFPREP, DVF_ERRORLEVEL, "TerminateProcess failed on priority process, code: %i", lRet);
  615. if (!CloseHandle(m_piPriority.hProcess))
  616. {
  617. lRet = GetLastError();
  618. DPFX(DPFPREP, DVF_ERRORLEVEL, "CloseHandle failed on priority process handle, code: %i", lRet);
  619. }
  620. m_piPriority.hProcess = NULL;
  621. hr = DVERR_GENERIC;
  622. }
  623. if (!CloseHandle(m_piPriority.hProcess))
  624. {
  625. lRet = GetLastError();
  626. DPFX(DPFPREP, DVF_ERRORLEVEL, "CloseHandle failed on priority process handle, code: %i", lRet);
  627. hr = DVERR_GENERIC;
  628. }
  629. m_piPriority.hProcess = NULL;
  630. }
  631. if (m_piFullDuplex.hProcess != NULL)
  632. {
  633. if (!TerminateProcess(m_piFullDuplex.hProcess, 0))
  634. {
  635. lRet = GetLastError();
  636. DPFX(DPFPREP, DVF_ERRORLEVEL, "TerminateProcess failed on full duplex process, code: %i", lRet);
  637. hr = DVERR_GENERIC;
  638. }
  639. if (!CloseHandle(m_piFullDuplex.hProcess))
  640. {
  641. lRet = GetLastError();
  642. DPFX(DPFPREP, DVF_ERRORLEVEL, "CloseHandle failed on full duplex process handle, code: %i", lRet);
  643. hr = DVERR_GENERIC;
  644. }
  645. m_piFullDuplex.hProcess = NULL;
  646. }
  647. DNLeaveCriticalSection(&m_csLock);
  648. DPF_EXIT();
  649. return hr;
  650. }
  651. #undef DPF_MODNAME
  652. #define DPF_MODNAME "CSupervisorIPC::StartFullDuplexProcess"
  653. HRESULT CSupervisorIPC::StartFullDuplexProcess()
  654. {
  655. STARTUPINFO si;
  656. TCHAR szCmdLine[128];
  657. TCHAR szAppName[MAX_PATH+1];
  658. DPF_ENTER();
  659. DNEnterCriticalSection(&m_csLock);
  660. ZeroMemory(&si, sizeof(si));
  661. si.cb = sizeof(si);
  662. BuildLaunchAppName(szAppName);
  663. _tcsncpy( szCmdLine, gc_szFullDuplexCommand, 127 );
  664. if (!CreateProcess(
  665. szAppName,
  666. szCmdLine,
  667. NULL,
  668. NULL,
  669. FALSE,
  670. 0,
  671. NULL,
  672. NULL,
  673. &si,
  674. &m_piFullDuplex))
  675. {
  676. m_piFullDuplex.hProcess = NULL;
  677. m_piFullDuplex.hThread = NULL;
  678. DNLeaveCriticalSection(&m_csLock);
  679. DPF_EXIT();
  680. return DVERR_WIN32;
  681. }
  682. // don't need the thread handle
  683. if (!CloseHandle(m_piFullDuplex.hThread))
  684. {
  685. m_piFullDuplex.hThread = NULL;
  686. DNLeaveCriticalSection(&m_csLock);
  687. DPF_EXIT();
  688. return DVERR_WIN32;
  689. }
  690. DNLeaveCriticalSection(&m_csLock);
  691. DPF_EXIT();
  692. return S_OK;
  693. }
  694. #undef DPF_MODNAME
  695. #define DPF_MODNAME "CSupervisorIPC::WaitForStartupSignals"
  696. HRESULT CSupervisorIPC::WaitForStartupSignals()
  697. {
  698. HANDLE rghEvents[2];
  699. DWORD dwRet;
  700. HRESULT hr;
  701. LONG lRet;
  702. // wait to be signaled by both child processes, indicating that
  703. // they are ready to go.
  704. DNEnterCriticalSection(&m_csLock);
  705. rghEvents[0] = m_hPriorityReplyEvent;
  706. rghEvents[1] = m_hFullDuplexReplyEvent;
  707. DNLeaveCriticalSection(&m_csLock);
  708. dwRet = WaitForMultipleObjects(2, rghEvents, TRUE, gc_dwChildStartupTimeout);
  709. if (dwRet != WAIT_OBJECT_0 && dwRet != WAIT_OBJECT_0 + 1)
  710. {
  711. if (dwRet == WAIT_TIMEOUT)
  712. {
  713. DPFX(DPFPREP, DVF_ERRORLEVEL, "Timeout waiting for child processes to startup");
  714. return DVERR_TIMEOUT;
  715. }
  716. else
  717. {
  718. lRet = GetLastError();
  719. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error waiting for signals from child processes, code: %i", lRet);
  720. return DVERR_WIN32;
  721. }
  722. }
  723. return DV_OK;
  724. }
  725. #undef DPF_MODNAME
  726. #define DPF_MODNAME "CSupervisorIPC::BuildAppName"
  727. void CSupervisorIPC::BuildLaunchAppName(TCHAR * wszFullPath)
  728. {
  729. GetSystemDirectory(wszFullPath, MAX_PATH);
  730. DWORD dwAppNameFullPathLen=_tcslen(wszFullPath);
  731. if (wszFullPath[dwAppNameFullPathLen-1]!='\\')
  732. wszFullPath[dwAppNameFullPathLen++]='\\';
  733. wszFullPath[dwAppNameFullPathLen++]=0;
  734. _tcsncat(wszFullPath, gc_szLaunchAppName, MAX_PATH-dwAppNameFullPathLen);
  735. }
  736. #undef DPF_MODNAME
  737. #define DPF_MODNAME "CPriorityIPC::CPriorityIPC"
  738. CPriorityIPC::CPriorityIPC()
  739. : m_fInitComplete(FALSE)
  740. , m_hPriorityEvent(NULL)
  741. , m_hPriorityMutex(NULL)
  742. , m_hPriorityReplyEvent(NULL)
  743. , m_hPriorityShMemHandle(NULL)
  744. , m_lpvPriorityShMemPtr(NULL)
  745. {
  746. return;
  747. }
  748. #undef DPF_MODNAME
  749. #define DPF_MODNAME "CPriorityIPC::Init"
  750. HRESULT CPriorityIPC::Init()
  751. {
  752. LONG lRet;
  753. HRESULT hr;
  754. DPF_ENTER();
  755. if (!DNInitializeCriticalSection(&m_csLock))
  756. {
  757. return DVERR_OUTOFMEMORY;
  758. }
  759. DNEnterCriticalSection(&m_csLock);
  760. if (m_fInitComplete == TRUE)
  761. {
  762. DPFX(DPFPREP, DVF_ERRORLEVEL, "CPriorityIPC::Init - already initialized");
  763. hr = DVERR_INITIALIZED;
  764. goto error_cleanup;
  765. }
  766. m_hPriorityEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, gc_szPriorityEventName);
  767. if (m_hPriorityEvent == NULL)
  768. {
  769. lRet = GetLastError();
  770. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open Priority event, code: %i", lRet);
  771. hr = DVERR_GENERIC;
  772. goto error_cleanup;
  773. }
  774. m_hPriorityReplyEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, gc_szPriorityReplyEventName);
  775. if (m_hPriorityReplyEvent == NULL)
  776. {
  777. lRet = GetLastError();
  778. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open Priority Reply event, code: %i", lRet);
  779. hr = DVERR_GENERIC;
  780. goto error_cleanup;
  781. }
  782. m_hPriorityShMemHandle = OpenFileMapping(FILE_MAP_WRITE, FALSE, gc_szPriorityShMemName);
  783. if (m_hPriorityShMemHandle == NULL)
  784. {
  785. lRet = GetLastError();
  786. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open Priority FileMapping object, code: %i", lRet);
  787. hr = DVERR_GENERIC;
  788. goto error_cleanup;
  789. }
  790. m_lpvPriorityShMemPtr = MapViewOfFile(
  791. m_hPriorityShMemHandle,
  792. FILE_MAP_WRITE,
  793. 0,
  794. 0,
  795. gc_dwPriorityShMemSize);
  796. if (m_lpvPriorityShMemPtr == NULL)
  797. {
  798. lRet = GetLastError();
  799. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to Map view of Priority FileMapping object, code: %i", lRet);
  800. hr = DVERR_GENERIC;
  801. goto error_cleanup;
  802. }
  803. m_fInitComplete = TRUE;
  804. DNLeaveCriticalSection(&m_csLock);
  805. DPF_EXIT();
  806. return S_OK;
  807. error_cleanup:
  808. if (m_lpvPriorityShMemPtr != NULL)
  809. {
  810. UnmapViewOfFile(m_lpvPriorityShMemPtr);
  811. m_lpvPriorityShMemPtr = NULL;
  812. }
  813. if (m_hPriorityShMemHandle != NULL)
  814. {
  815. CloseHandle(m_hPriorityShMemHandle);
  816. m_hPriorityShMemHandle = NULL;
  817. }
  818. if (m_hPriorityReplyEvent != NULL)
  819. {
  820. CloseHandle(m_hPriorityReplyEvent);
  821. m_hPriorityReplyEvent = NULL;
  822. }
  823. if (m_hPriorityEvent != NULL)
  824. {
  825. CloseHandle(m_hPriorityEvent);
  826. m_hPriorityEvent = NULL;
  827. }
  828. DNLeaveCriticalSection(&m_csLock);
  829. DPF_EXIT();
  830. return hr;
  831. }
  832. #undef DPF_MODNAME
  833. #define DPF_MODNAME "CPriorityIPC::Deinit"
  834. HRESULT CPriorityIPC::Deinit()
  835. {
  836. LONG lRet;
  837. HRESULT hr = DV_OK;
  838. DPF_ENTER();
  839. DNEnterCriticalSection(&m_csLock);
  840. if (m_fInitComplete != TRUE)
  841. {
  842. DPFX(DPFPREP, DVF_ERRORLEVEL, "CPriorityIPC::Deinit called on uninitialized object");
  843. hr = DVERR_NOTINITIALIZED;
  844. }
  845. m_fInitComplete = FALSE;
  846. if (m_lpvPriorityShMemPtr != NULL)
  847. {
  848. UnmapViewOfFile(m_lpvPriorityShMemPtr);
  849. m_lpvPriorityShMemPtr = NULL;
  850. }
  851. if (m_hPriorityShMemHandle != NULL)
  852. {
  853. CloseHandle(m_hPriorityShMemHandle);
  854. m_hPriorityShMemHandle = NULL;
  855. }
  856. if (m_hPriorityReplyEvent != NULL)
  857. {
  858. CloseHandle(m_hPriorityReplyEvent);
  859. m_hPriorityReplyEvent = NULL;
  860. }
  861. if (m_hPriorityEvent != NULL)
  862. {
  863. CloseHandle(m_hPriorityEvent);
  864. m_hPriorityEvent = NULL;
  865. }
  866. DNLeaveCriticalSection(&m_csLock);
  867. DNDeleteCriticalSection(&m_csLock);
  868. DPF_EXIT();
  869. return hr;
  870. }
  871. #undef DPF_MODNAME
  872. #define DPF_MODNAME "CPriorityIPC::SignalParentReady"
  873. HRESULT CPriorityIPC::SignalParentReady()
  874. {
  875. BOOL fRet;
  876. LONG lRet;
  877. DPF_ENTER();
  878. DNEnterCriticalSection(&m_csLock);
  879. fRet = SetEvent(m_hPriorityReplyEvent);
  880. if (!fRet)
  881. {
  882. lRet = GetLastError();
  883. DPFX(DPFPREP, 0, "Error Setting Priority Reply Event, code: %i", lRet);
  884. DPF_EXIT();
  885. return DVERR_WIN32;
  886. }
  887. DNLeaveCriticalSection(&m_csLock);
  888. DPF_EXIT();
  889. return DV_OK;
  890. }
  891. #undef DPF_MODNAME
  892. #define DPF_MODNAME "CPriorityIPC::Receive"
  893. HRESULT CPriorityIPC::Receive(SFDTestCommand* pfdtc)
  894. {
  895. HRESULT hr;
  896. DPF_ENTER();
  897. DNEnterCriticalSection(&m_csLock);
  898. hr = DoReceive(pfdtc, m_hPriorityEvent, m_hPriorityReplyEvent, m_lpvPriorityShMemPtr);
  899. DNLeaveCriticalSection(&m_csLock);
  900. DPF_EXIT();
  901. return hr;
  902. }
  903. #undef DPF_MODNAME
  904. #define DPF_MODNAME "CPriorityIPC::Reply"
  905. HRESULT CPriorityIPC::Reply(HRESULT hr)
  906. {
  907. DPF_ENTER();
  908. DNEnterCriticalSection(&m_csLock);
  909. hr = DoReply(hr, m_hPriorityReplyEvent, m_lpvPriorityShMemPtr);
  910. DNLeaveCriticalSection(&m_csLock);
  911. DPF_EXIT();
  912. return hr;
  913. }
  914. #undef DPF_MODNAME
  915. #define DPF_MODNAME "CFullDuplexIPC::CFullDuplexIPC"
  916. CFullDuplexIPC::CFullDuplexIPC()
  917. : m_fInitComplete(FALSE)
  918. , m_hFullDuplexEvent(NULL)
  919. , m_hFullDuplexMutex(NULL)
  920. , m_hFullDuplexReplyEvent(NULL)
  921. , m_hFullDuplexShMemHandle(NULL)
  922. , m_lpvFullDuplexShMemPtr(NULL)
  923. {
  924. return;
  925. }
  926. #undef DPF_MODNAME
  927. #define DPF_MODNAME "CFullDuplexIPC::Init"
  928. HRESULT CFullDuplexIPC::Init()
  929. {
  930. LONG lRet;
  931. HRESULT hr;
  932. DPF_ENTER();
  933. if (!DNInitializeCriticalSection(&m_csLock))
  934. {
  935. return DVERR_OUTOFMEMORY;
  936. }
  937. DNEnterCriticalSection(&m_csLock);
  938. if (m_fInitComplete != FALSE)
  939. {
  940. DPFX(DPFPREP, DVF_ERRORLEVEL, "CFullDuplexIPC::Init - already initialized");
  941. hr = DVERR_INITIALIZED;
  942. goto error_cleanup;
  943. }
  944. m_hFullDuplexEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, gc_szFullDuplexEventName);
  945. if (m_hFullDuplexEvent == NULL)
  946. {
  947. lRet = GetLastError();
  948. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open FullDuplex event, code: %i", lRet);
  949. hr = DVERR_GENERIC;
  950. goto error_cleanup;
  951. }
  952. m_hFullDuplexReplyEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, gc_szFullDuplexReplyEventName);
  953. if (m_hFullDuplexReplyEvent == NULL)
  954. {
  955. lRet = GetLastError();
  956. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open FullDuplex Reply event, code: %i", lRet);
  957. hr = DVERR_GENERIC;
  958. goto error_cleanup;
  959. }
  960. m_hFullDuplexShMemHandle = OpenFileMapping(FILE_MAP_WRITE, FALSE, gc_szFullDuplexShMemName);
  961. if (m_hFullDuplexShMemHandle == NULL)
  962. {
  963. lRet = GetLastError();
  964. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to open FullDuplex FileMapping object, code: %i", lRet);
  965. hr = DVERR_GENERIC;
  966. goto error_cleanup;
  967. }
  968. m_lpvFullDuplexShMemPtr = MapViewOfFile(
  969. m_hFullDuplexShMemHandle,
  970. FILE_MAP_WRITE,
  971. 0,
  972. 0,
  973. gc_dwFullDuplexShMemSize);
  974. if (m_lpvFullDuplexShMemPtr == NULL)
  975. {
  976. lRet = GetLastError();
  977. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to Map view of FullDuplex FileMapping object, code: %i", lRet);
  978. hr = DVERR_GENERIC;
  979. goto error_cleanup;
  980. }
  981. m_fInitComplete = TRUE;
  982. DNLeaveCriticalSection(&m_csLock);
  983. DPF_EXIT();
  984. return S_OK;
  985. error_cleanup:
  986. if (m_lpvFullDuplexShMemPtr != NULL)
  987. {
  988. UnmapViewOfFile(m_lpvFullDuplexShMemPtr);
  989. m_lpvFullDuplexShMemPtr = NULL;
  990. }
  991. if (m_hFullDuplexShMemHandle != NULL)
  992. {
  993. CloseHandle(m_hFullDuplexShMemHandle);
  994. m_hFullDuplexShMemHandle = NULL;
  995. }
  996. if (m_hFullDuplexReplyEvent != NULL)
  997. {
  998. CloseHandle(m_hFullDuplexReplyEvent);
  999. m_hFullDuplexReplyEvent = NULL;
  1000. }
  1001. if (m_hFullDuplexEvent != NULL)
  1002. {
  1003. CloseHandle(m_hFullDuplexEvent);
  1004. m_hFullDuplexEvent = NULL;
  1005. }
  1006. DNLeaveCriticalSection(&m_csLock);
  1007. DPF_EXIT();
  1008. return hr;
  1009. }
  1010. #undef DPF_MODNAME
  1011. #define DPF_MODNAME "CFullDuplexIPC::Deinit"
  1012. HRESULT CFullDuplexIPC::Deinit()
  1013. {
  1014. LONG lRet;
  1015. HRESULT hr = DV_OK;
  1016. DPF_ENTER();
  1017. DNEnterCriticalSection(&m_csLock);
  1018. if (m_fInitComplete != TRUE)
  1019. {
  1020. DPFX(DPFPREP, DVF_ERRORLEVEL, "CFullDuplexIPC::Deinit called on uninitialized object");
  1021. hr = DVERR_NOTINITIALIZED;
  1022. }
  1023. m_fInitComplete = FALSE;
  1024. if (m_lpvFullDuplexShMemPtr != NULL)
  1025. {
  1026. UnmapViewOfFile(m_lpvFullDuplexShMemPtr);
  1027. m_lpvFullDuplexShMemPtr = NULL;
  1028. }
  1029. if (m_hFullDuplexShMemHandle != NULL)
  1030. {
  1031. CloseHandle(m_hFullDuplexShMemHandle);
  1032. m_hFullDuplexShMemHandle = NULL;
  1033. }
  1034. if (m_hFullDuplexReplyEvent != NULL)
  1035. {
  1036. CloseHandle(m_hFullDuplexReplyEvent);
  1037. m_hFullDuplexReplyEvent = NULL;
  1038. }
  1039. if (m_hFullDuplexEvent != NULL)
  1040. {
  1041. CloseHandle(m_hFullDuplexEvent);
  1042. m_hFullDuplexEvent = NULL;
  1043. }
  1044. DNLeaveCriticalSection(&m_csLock);
  1045. DNDeleteCriticalSection(&m_csLock);
  1046. DPF_EXIT();
  1047. return hr;
  1048. }
  1049. #undef DPF_MODNAME
  1050. #define DPF_MODNAME "CFullDuplexIPC::SignalParentReady"
  1051. HRESULT CFullDuplexIPC::SignalParentReady()
  1052. {
  1053. BOOL fRet;
  1054. LONG lRet;
  1055. DPF_ENTER();
  1056. DNEnterCriticalSection(&m_csLock);
  1057. fRet = SetEvent(m_hFullDuplexReplyEvent);
  1058. if (!fRet)
  1059. {
  1060. lRet = GetLastError();
  1061. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error Setting FullDuplex Event, code: %i", lRet);
  1062. DPF_EXIT();
  1063. return DVERR_WIN32;
  1064. }
  1065. DNLeaveCriticalSection(&m_csLock);
  1066. DPF_EXIT();
  1067. return DV_OK;
  1068. }
  1069. #undef DPF_MODNAME
  1070. #define DPF_MODNAME "CFullDuplexIPC::Receive"
  1071. HRESULT CFullDuplexIPC::Receive(SFDTestCommand* pfdtc)
  1072. {
  1073. HRESULT hr;
  1074. DPF_ENTER();
  1075. DNEnterCriticalSection(&m_csLock);
  1076. hr = DoReceive(pfdtc, m_hFullDuplexEvent, m_hFullDuplexReplyEvent, m_lpvFullDuplexShMemPtr);
  1077. DNLeaveCriticalSection(&m_csLock);
  1078. DPF_EXIT();
  1079. return hr;
  1080. }
  1081. #undef DPF_MODNAME
  1082. #define DPF_MODNAME "CFullDuplexIPC::Reply"
  1083. HRESULT CFullDuplexIPC::Reply(HRESULT hrReply)
  1084. {
  1085. HRESULT hr;
  1086. DPF_ENTER();
  1087. DNEnterCriticalSection(&m_csLock);
  1088. hr = DoReply(hrReply, m_hFullDuplexReplyEvent, m_lpvFullDuplexShMemPtr);
  1089. DNLeaveCriticalSection(&m_csLock);
  1090. DPF_EXIT();
  1091. return hr;
  1092. }
  1093. #undef DPF_MODNAME
  1094. #define DPF_MODNAME "DoReceive"
  1095. HRESULT DoReceive(
  1096. SFDTestCommand* pfdtc,
  1097. HANDLE hEvent,
  1098. HANDLE hReplyEvent,
  1099. LPVOID lpvShMemPtr)
  1100. {
  1101. DWORD dwRet;
  1102. LONG lRet;
  1103. DPF_ENTER();
  1104. dwRet = WaitForSingleObject(hEvent, gc_dwCommandReceiveTimeout);
  1105. switch (dwRet)
  1106. {
  1107. case WAIT_OBJECT_0:
  1108. // this is the expected signal, continue
  1109. break;
  1110. case WAIT_FAILED:
  1111. lRet = GetLastError();
  1112. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error waiting for event, code: %i", lRet);
  1113. DPF_EXIT();
  1114. return DVERR_WIN32;
  1115. case WAIT_TIMEOUT:
  1116. DPFX(DPFPREP, DVF_ERRORLEVEL, "Timed out waiting to receive command");
  1117. DPF_EXIT();
  1118. return DVERR_TIMEOUT;
  1119. default:
  1120. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unknown error waiting for event");
  1121. DPF_EXIT();
  1122. return DVERR_UNKNOWN;
  1123. }
  1124. // Copy the command from shared memory to the caller's
  1125. // buffer. Ensure the caller's buffer is large enough
  1126. if (pfdtc->dwSize < ((SFDTestCommand*)lpvShMemPtr)->dwSize)
  1127. {
  1128. // reply to both the sender and receiver that the
  1129. // buffer was not large enough! We already have an
  1130. // error, so ingore the return code from the reply
  1131. // call
  1132. DoReply(DVERR_BUFFERTOOSMALL, hReplyEvent, lpvShMemPtr);
  1133. DPF_EXIT();
  1134. return DVERR_BUFFERTOOSMALL;
  1135. }
  1136. CopyMemory(pfdtc, lpvShMemPtr, ((SFDTestCommand*)lpvShMemPtr)->dwSize);
  1137. // Let the caller know how much was copied
  1138. pfdtc->dwSize = ((SFDTestCommand*)lpvShMemPtr)->dwSize;
  1139. // all done.
  1140. DPF_EXIT();
  1141. return S_OK;
  1142. }
  1143. #undef DPF_MODNAME
  1144. #define DPF_MODNAME "DoReply"
  1145. HRESULT DoReply(HRESULT hr, HANDLE hReplyEvent, LPVOID lpvShMemPtr)
  1146. {
  1147. LONG lRet;
  1148. DPF_ENTER();
  1149. // Copy the return code to shared memory
  1150. *((HRESULT*)lpvShMemPtr) = hr;
  1151. // Signal that we have replied
  1152. if (!SetEvent(hReplyEvent))
  1153. {
  1154. lRet = GetLastError();
  1155. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to set event, code: %i", lRet);
  1156. DPF_EXIT();
  1157. return DVERR_WIN32;
  1158. }
  1159. DPF_EXIT();
  1160. return S_OK;
  1161. }