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.

862 lines
21 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // File: smarshal.cxx
  4. //
  5. // Synopsis: Source code for Interface Marshaling stress test main
  6. // driver functions. Source for individual tests is in
  7. // testvar.cxx
  8. //
  9. // History: 21-Aug-95 Rickhi Created
  10. //
  11. //--------------------------------------------------------------------
  12. #include <smarshal.hxx>
  13. //+-------------------------------------------------------------------
  14. //
  15. // Globals:
  16. //
  17. //--------------------------------------------------------------------
  18. BOOL gfVerbose = FALSE; // print execution messages
  19. BOOL gfDebug = FALSE; // print debug messages
  20. DWORD giThreadModel = OPF_INITAPARTMENT; // threading model to use
  21. int giTestVar = 0; // test variation to run
  22. int giHighestTestVar = 2; // highest test var supported
  23. int gicReps = 5; // number of repetitions of each test
  24. int gicThreads = 1; // number of threads to use on each test
  25. //+-------------------------------------------------------------------
  26. //
  27. // Private Function ProtoTypes:
  28. //
  29. //--------------------------------------------------------------------
  30. HRESULT DoIfOperation(DWORD dwFlags, INTERFACEPARAMS *pIFD);
  31. void DisplayHelp(void);
  32. BOOL GetSwitch(CHAR *pCmdParam, CHAR *pszSwitch);
  33. BOOL GetSwitchInt(CHAR *pCmdParam, CHAR *pszSwitch, int *pInt);
  34. BOOL ParseCmdLine(int argc, char **argv);
  35. int _cdecl main(int argc, char **argv);
  36. BOOL FreeWaitForEvent(HANDLE hEvent);
  37. BOOL AptWaitForEvent(HANDLE hEvent);
  38. STDAPI_(LPSTREAM) CreateMemStm(DWORD cb, LPHANDLE phdl);
  39. //+-------------------------------------------------------------------
  40. //
  41. // Misc:
  42. //
  43. //--------------------------------------------------------------------
  44. #ifndef _CAIRO_
  45. // COM initialization flags; passed to CoInitialize.
  46. typedef enum tagCOINIT
  47. {
  48. COINIT_MULTITHREADED = 0, // OLE calls objects on any thread.
  49. COINIT_SINGLETHREADED = 1, // OLE calls objects on single thread.
  50. COINIT_APARTMENTTHREADED = 2 // Apartment model
  51. } COINIT;
  52. WINOLEAPI CoInitializeEx(LPVOID pvReserved, DWORD);
  53. #endif
  54. //+-------------------------------------------------------------------
  55. //
  56. // Function: main
  57. //
  58. // Synopsis: Entry point to EXE. Parse the command line, then run
  59. // whatever test variations were selected.
  60. //
  61. // Notes: The test variation code is in testvars.cxx.
  62. // The rest of this file is helper routines.
  63. //
  64. //--------------------------------------------------------------------
  65. int _cdecl main(int argc, char **argv)
  66. {
  67. // parse the command line
  68. BOOL fRes = ParseCmdLine(argc, argv);
  69. if (fRes)
  70. {
  71. // run the selected test variations
  72. switch (giTestVar)
  73. {
  74. case 1: fRes = TestVar1();
  75. break;
  76. case 2: fRes = TestVar2();
  77. break;
  78. default: break;
  79. }
  80. }
  81. // check the results
  82. CHKTESTRESULT(fRes, "Marshal Stress Tests");
  83. return 0;
  84. }
  85. //+-------------------------------------------------------------------
  86. //
  87. // Function: ParseCmdLine
  88. //
  89. // Synopsis: parses the execution parameters
  90. //
  91. //--------------------------------------------------------------------
  92. BOOL ParseCmdLine(int argc, char **argv)
  93. {
  94. BOOL fDontRun = (argc == 1) ? TRUE : FALSE;
  95. // the first parameter is the EXE name, skip it.
  96. argc--;
  97. argv++;
  98. for (int i=0; i<argc; i++, argv++)
  99. {
  100. if (GetSwitch(*argv, "v"))
  101. {
  102. // run verbose
  103. gfVerbose = TRUE;
  104. }
  105. else if (GetSwitch(*argv, "d"))
  106. {
  107. // run debug mode
  108. gfVerbose = TRUE;
  109. gfDebug = TRUE;
  110. }
  111. else if (GetSwitch(*argv, "h") || GetSwitch(*argv, "?"))
  112. {
  113. // help wanted
  114. fDontRun = TRUE;
  115. }
  116. else if (GetSwitchInt(*argv, "var:", &giTestVar))
  117. {
  118. // selected test variation, ensure the variation is valid
  119. if (giTestVar > giHighestTestVar)
  120. {
  121. ERROUT("Unknown Test Variation:%x\n", giTestVar);
  122. fDontRun = TRUE;
  123. }
  124. }
  125. else if (GetSwitchInt(*argv, "reps:", &gicReps))
  126. {
  127. ; // selected repetition count
  128. }
  129. else if (GetSwitchInt(*argv, "threads:", &gicThreads))
  130. {
  131. ; // selected thread count
  132. }
  133. else if (GetSwitch(*argv, "model:apt"))
  134. {
  135. // run apartment model
  136. giThreadModel = OPF_INITAPARTMENT;
  137. }
  138. else if (GetSwitch(*argv, "model:free"))
  139. {
  140. // run freethreaded model
  141. giThreadModel = OPF_INITFREE;
  142. }
  143. else
  144. {
  145. // unknown switch, show help
  146. ERROUT("Unknown command line switch:<%s>\n", *argv);
  147. fDontRun = TRUE;
  148. }
  149. }
  150. if (fDontRun)
  151. {
  152. // help is wanted
  153. DisplayHelp();
  154. return FALSE;
  155. }
  156. // success, run the test
  157. return TRUE;
  158. }
  159. //+-------------------------------------------------------------------
  160. //
  161. // Function: DisplayHelp
  162. //
  163. // Synopsis: displays a command line help message
  164. //
  165. //--------------------------------------------------------------------
  166. void DisplayHelp(void)
  167. {
  168. printf("\nCommand Line Switches for Marshal Stress Test:\n\n");
  169. printf("-d - debug mode\n");
  170. printf("-v - verbose mode\n");
  171. printf("-h | -? - display this help message\n\n");
  172. printf("-model:[apt|free] - threading model to use for test\n");
  173. printf("-var:# - test variation to execute 1-%x\n", giHighestTestVar);
  174. printf("-threads:# - number of threads per variation\n");
  175. printf("-reps:# - number of repetitions of the test\n");
  176. printf("\n");
  177. }
  178. //+-------------------------------------------------------------------
  179. //
  180. // Function: GetSwitch
  181. //
  182. // Synopsis: returns TRUE if the specified cmd line switch is set.
  183. //
  184. //--------------------------------------------------------------------
  185. BOOL GetSwitch(CHAR *pCmdParam, CHAR *pszSwitch)
  186. {
  187. if (*pCmdParam == '-' || *pCmdParam == '/')
  188. {
  189. pCmdParam++;
  190. return (!stricmp(pCmdParam, pszSwitch));
  191. }
  192. return FALSE;
  193. }
  194. //+-------------------------------------------------------------------
  195. //
  196. // Function: GetSwitchInt
  197. //
  198. // Synopsis: returns TRUE if the specified cmd line switch is set,
  199. // and sets the value of that switch.
  200. //
  201. //--------------------------------------------------------------------
  202. BOOL GetSwitchInt(CHAR *pCmdParam, CHAR *pszSwitch, int *pInt)
  203. {
  204. if (*pCmdParam == '-' || *pCmdParam == '/')
  205. {
  206. pCmdParam++;
  207. int len = strlen(pszSwitch);
  208. if (!strnicmp(pCmdParam, pszSwitch, len))
  209. {
  210. pCmdParam += len;
  211. *pInt = atoi(pCmdParam);
  212. return TRUE;
  213. }
  214. }
  215. return FALSE;
  216. }
  217. //+-------------------------------------------------------------------
  218. //
  219. // Function: CHKRESULT
  220. //
  221. // Synopsis: prints a failure message if the result code indicates
  222. // failure., and success message only in verbose mode.
  223. //
  224. //--------------------------------------------------------------------
  225. void CHKRESULT(HRESULT hr, CHAR *pszOperation)
  226. {
  227. if (FAILED(hr))
  228. {
  229. printf("FAILED hr:%x Op:%s\n", hr, pszOperation);
  230. }
  231. else if (gfVerbose)
  232. {
  233. printf("PASSED hr:%x Op:%s\n", hr, pszOperation);
  234. }
  235. }
  236. //+-------------------------------------------------------------------
  237. //
  238. // Function: CHKOP
  239. //
  240. // Synopsis: prints a failure message if the result code indicates
  241. // failure, and success message only in debug mode.
  242. //
  243. //--------------------------------------------------------------------
  244. void CHKOP(HRESULT hr, CHAR *pszOperation)
  245. {
  246. if (FAILED(hr))
  247. {
  248. printf("FAILED hr:%x Op:%s\n", hr, pszOperation);
  249. }
  250. else if (gfDebug)
  251. {
  252. printf("PASSED hr:%x Op:%s\n", hr, pszOperation);
  253. }
  254. }
  255. //+-------------------------------------------------------------------
  256. //
  257. // Function: CHKTESTRESULT
  258. //
  259. // Synopsis: prints a pass or fail message
  260. //
  261. //--------------------------------------------------------------------
  262. void CHKTESTRESULT(BOOL fRes, CHAR *pszMsg)
  263. {
  264. if (fRes)
  265. printf("%s PASSED\n", pszMsg);
  266. else
  267. printf("%s FAILED\n", pszMsg);
  268. }
  269. //+-------------------------------------------------------------------
  270. //
  271. // Function: GetEvent / ReleaseEvent
  272. //
  273. // Synopsis: allocates or releases an event
  274. //
  275. // CODEWORK: cache these for frequent use
  276. //
  277. //--------------------------------------------------------------------
  278. HANDLE GetEvent()
  279. {
  280. HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  281. if (hEvent == NULL)
  282. {
  283. ERROUT("GetEvent FAILED\n");
  284. }
  285. DBGOUT("CreateEvent hEvent:%x\n", hEvent);
  286. return hEvent;
  287. }
  288. void ReleaseEvent(HANDLE hEvent)
  289. {
  290. if (hEvent)
  291. {
  292. DBGOUT("ReleaseEvent hEvent:%x\n", hEvent);
  293. CloseHandle(hEvent);
  294. }
  295. }
  296. //+-------------------------------------------------------------------
  297. //
  298. // Function: WaitForEvent
  299. //
  300. // Synopsis: waits on the given event (if there is one) for a
  301. // certain amount of time, returns FALSE if timedout.
  302. //
  303. //--------------------------------------------------------------------
  304. BOOL WaitForEvent(HANDLE hEvent)
  305. {
  306. if (hEvent)
  307. {
  308. // CODEWORK: base off the Threading Model
  309. return (TRUE) ? AptWaitForEvent(hEvent) :
  310. FreeWaitForEvent(hEvent);
  311. }
  312. return TRUE;
  313. }
  314. //+-------------------------------------------------------------------
  315. //
  316. // Function: FreeWaitForEvent
  317. //
  318. // Synopsis: FreeThreaded version of WaitForEvent. Waits on the
  319. // given event.
  320. //
  321. //--------------------------------------------------------------------
  322. BOOL FreeWaitForEvent(HANDLE hEvent)
  323. {
  324. DBGOUT("FreeWaitForEvent hEvent:%x\n", hEvent);
  325. if (WaitForSingleObject(hEvent, 30000) == WAIT_TIMEOUT)
  326. {
  327. ERROUT("WaitForSingleObject TimedOut");
  328. return FALSE;
  329. }
  330. return TRUE;
  331. }
  332. //+-------------------------------------------------------------------
  333. //
  334. // Function: AptWaitForEvent
  335. //
  336. // Synopsis: Apartment model version of WaitForEvent. Waits on the
  337. // given event. Dispatches all incoming windows messages
  338. // while waiting.
  339. //
  340. //--------------------------------------------------------------------
  341. BOOL AptWaitForEvent(HANDLE hEvent)
  342. {
  343. DBGOUT("AptWaitForEvent hEvent:%x\n", hEvent);
  344. while (1)
  345. {
  346. HANDLE arEvent[] = {hEvent};
  347. DWORD dwWakeReason = MsgWaitForMultipleObjects(1, arEvent, FALSE,
  348. 1000, QS_ALLINPUT);
  349. if (dwWakeReason == WAIT_OBJECT_0)
  350. {
  351. // event was signalled. exit.
  352. break;
  353. }
  354. else
  355. {
  356. // check for and dispatch any messages that have arrived
  357. MSG msg;
  358. while (PeekMessage(&msg, 0, WM_NULL, WM_NULL, PM_REMOVE))
  359. {
  360. DispatchMessage(&msg);
  361. }
  362. }
  363. }
  364. return TRUE;
  365. }
  366. //+-------------------------------------------------------------------
  367. //
  368. // Function: SignalEvent
  369. //
  370. // Synopsis: signals an event (if there is one)
  371. //
  372. //--------------------------------------------------------------------
  373. void SignalEvent(HANDLE hEvent)
  374. {
  375. if (hEvent)
  376. {
  377. DBGOUT("SignalEvent hEvent:%x\n", hEvent);
  378. SetEvent(hEvent);
  379. }
  380. }
  381. //+-------------------------------------------------------------------
  382. //
  383. // Function: GetStream / ReleaseStream
  384. //
  385. // Synopsis: allocates or releases a Stream
  386. //
  387. // CODEWORK: cache these for frequent use
  388. // CODEWORK: use CStreamOnFile for cross process/machine marshaling.
  389. //
  390. //--------------------------------------------------------------------
  391. IStream * GetStream(void)
  392. {
  393. IStream *pStm = CreateMemStm(600, NULL);
  394. if (pStm == NULL)
  395. {
  396. ERROUT("ERROR: GetStream FAILED\n");
  397. }
  398. DBGOUT("GetStream pStm:%x\n", pStm);
  399. return pStm;
  400. }
  401. void ReleaseStream(IStream *pStm)
  402. {
  403. if (pStm)
  404. {
  405. DBGOUT("ReleaseStream pStm:%x\n", pStm);
  406. pStm->Release();
  407. }
  408. }
  409. //+-------------------------------------------------------------------
  410. //
  411. // Function: ResetStream
  412. //
  413. // Synopsis: resets a steam back to the start
  414. //
  415. //--------------------------------------------------------------------
  416. HRESULT ResetStream(IStream *pStm)
  417. {
  418. DBGOUT("ResetStream pStm:%x\n", pStm);
  419. LARGE_INTEGER libMove;
  420. libMove.LowPart = 0;
  421. libMove.HighPart = 0;
  422. HRESULT hr = pStm->Seek(libMove, STREAM_SEEK_SET, 0);
  423. if (FAILED(hr))
  424. {
  425. ERROUT("ERROR: ResetStream FAILED hr:%x\n",hr);
  426. }
  427. return hr;
  428. }
  429. //+-------------------------------------------------------------------
  430. //
  431. // Function: GetInterface / ReleaseInterface
  432. //
  433. // Synopsis: allocates or releases an object interface
  434. //
  435. //--------------------------------------------------------------------
  436. IUnknown *GetInterface(void)
  437. {
  438. IUnknown *punk = (IUnknown *) new CTestUnk();
  439. if (punk == NULL)
  440. {
  441. ERROUT("ERROR: GetInterface FAILED\n");
  442. }
  443. DBGOUT("GetInterface punk:%x\n", punk);
  444. return punk;
  445. }
  446. void ReleaseInterface(IUnknown *punk)
  447. {
  448. if (punk)
  449. {
  450. DBGOUT("ReleaseInterface punk:%x\n", punk);
  451. punk->Release();
  452. }
  453. }
  454. //+-------------------------------------------------------------------
  455. //
  456. // Function: GenericExecute
  457. //
  458. // Synopsis: run all the parameter blocks on different threads
  459. // simultaneously.
  460. //
  461. //--------------------------------------------------------------------
  462. BOOL GenericExecute(ULONG cEPs, EXECPARAMS *pEP[])
  463. {
  464. BOOL fRes = TRUE;
  465. DBGOUT("Start GenericExecute cEPs:%x\n", cEPs);
  466. HANDLE hThread[50];
  467. // launch a thread to run each command block
  468. for (ULONG i=0; i<cEPs; i++)
  469. {
  470. // launch a thread to execute the parameter block
  471. DWORD dwThreadId;
  472. hThread[i] = CreateThread(NULL, 0,
  473. WorkerThread,
  474. pEP[i],
  475. 0,
  476. &dwThreadId);
  477. }
  478. // signal all the threads to start their work
  479. for (i=0; i<cEPs; i++)
  480. {
  481. SignalEvent(pEP[i]->hEventThreadStart);
  482. }
  483. // wait for all the threads to complete their work
  484. for (i=0; i<cEPs; i++)
  485. {
  486. if (pEP[i]->hEventThreadDone)
  487. {
  488. WaitForSingleObject(pEP[i]->hEventThreadDone, 60000);
  489. }
  490. }
  491. // signal all the threads to exit
  492. for (i=0; i<cEPs; i++)
  493. {
  494. HANDLE hEventThreadExit = pEP[i]->hEventThreadExit;
  495. pEP[i]->hEventThreadExit = NULL;// set to NULL so only the thread will
  496. // release it, genericcleanup wont.
  497. SignalEvent(hEventThreadExit);
  498. }
  499. // wait for all the threads to exit
  500. for (i=0; i<cEPs; i++)
  501. {
  502. WaitForSingleObject(hThread[i], 5000);
  503. CloseHandle(hThread[i]);
  504. }
  505. DBGOUT("Done GenericExecute fRes:%x\n", fRes);
  506. return fRes;
  507. }
  508. //+-------------------------------------------------------------------
  509. //
  510. // Function: GenericCleanup
  511. //
  512. // Synopsis: clean all the parameter blocks
  513. //
  514. //--------------------------------------------------------------------
  515. void GenericCleanup(ULONG cEPs, EXECPARAMS *pEP[])
  516. {
  517. DBGOUT("GenericCleanup\n");
  518. // delete the execution parameter blocks
  519. for (ULONG i=0; i<cEPs; i++)
  520. {
  521. ReleaseExecParam(pEP[i]);
  522. // CODEWORK: get results from the parameter block?
  523. }
  524. }
  525. //+-------------------------------------------------------------------
  526. //
  527. // Function: WorkerThread
  528. //
  529. // Synopsis: entry point for thread that executes a series of
  530. // interface commands
  531. //
  532. //--------------------------------------------------------------------
  533. DWORD _stdcall WorkerThread(void *params)
  534. {
  535. DBGOUT("StartWorkerThread TID:%x pEP:%x\n", GetCurrentThreadId(), params);
  536. EXECPARAMS *pEP = (EXECPARAMS *)params;
  537. if (pEP == NULL)
  538. {
  539. return E_OUTOFMEMORY;
  540. }
  541. HRESULT hr = S_OK;
  542. // Initialize OLE for this thread.
  543. if (pEP->dwFlags & OPF_INITAPARTMENT)
  544. {
  545. hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  546. }
  547. else
  548. {
  549. hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
  550. }
  551. if (FAILED(hr))
  552. {
  553. ERROUT("ERROR: CoInitializeEx FAILED\n");
  554. return hr;
  555. }
  556. // wait for signal to start the test
  557. if (!WaitForEvent(pEP->hEventThreadStart))
  558. {
  559. return E_OUTOFMEMORY; // BUGBUG
  560. }
  561. // loop for the number of reps requested
  562. for (ULONG iRep = 0; iRep < pEP->cReps; iRep++)
  563. {
  564. // wait for the start signal
  565. if (!WaitForEvent(pEP->hEventRepStart))
  566. {
  567. return E_OUTOFMEMORY; // BUGBUG
  568. }
  569. MSGOUT(" TID:%x Rep:%x of %x\n",
  570. GetCurrentThreadId(), iRep, pEP->cReps);
  571. // loop for the number of INTERFACEPARAMSs, performing
  572. // the requested operation(s) on each interface.
  573. for (ULONG iIP=0; iIP < pEP->cIPs; iIP++)
  574. {
  575. hr = DoIfOperation(pEP->dwFlags, &(pEP->aIP[iIP]));
  576. }
  577. // signal the completion event
  578. SignalEvent(pEP->hEventRepDone);
  579. }
  580. // signal the thread completion event. Cant touch pEP after this
  581. // point in time since the main thread may delete it. We extract
  582. // the ThreadExit event and NULL it in the parameter block so that
  583. // the main thread wont release it. We release it after the event
  584. // has been signaled.
  585. HANDLE hEventThreadExit = pEP->hEventThreadExit;
  586. SignalEvent(pEP->hEventThreadDone);
  587. // wait on the thread exit event. This allows other threads to
  588. // complete their work (eg unmarshaling/Releasing interfaces on
  589. // object in this thread.
  590. WaitForEvent(hEventThreadExit);
  591. ReleaseEvent(hEventThreadExit);
  592. // uninitialize OLE for this thread
  593. CoUninitialize();
  594. DBGOUT("ExitWorkerThread TID:%x hr:%x\n", GetCurrentThreadId(), hr);
  595. return hr;
  596. }
  597. //+-------------------------------------------------------------------
  598. //
  599. // Function: DoIfOperation
  600. //
  601. // Synopsis: executes one interface operation
  602. //
  603. //--------------------------------------------------------------------
  604. HRESULT DoIfOperation(DWORD dwFlags, INTERFACEPARAMS *pIP)
  605. {
  606. // find the interface pointers and IID in the params
  607. IUnknown *punk = pIP->punk;
  608. IStream *pStm = pIP->pStm;
  609. REFIID riid = pIP->iid;
  610. HRESULT hr = S_OK;
  611. DBGOUT("DoIfOperation Oper:%x pUnk:%x pStm:%x\n", dwFlags, punk, pStm);
  612. // wait for the start signal
  613. if (!WaitForEvent(pIP->hEventStart))
  614. {
  615. return -1;
  616. }
  617. // do the requested operation(s) on the interface
  618. if (dwFlags & OPF_MARSHAL)
  619. {
  620. // marshal the interface into the stream
  621. ResetStream(pStm);
  622. hr = CoMarshalInterface(pStm, riid, punk, 0, NULL, MSHLFLAGS_NORMAL);
  623. CHKOP(hr, "CoMarshalInterface");
  624. }
  625. if (dwFlags & OPF_DISCONNECT)
  626. {
  627. hr = CoDisconnectObject(punk, 0);
  628. CHKOP(hr, "CoDisconnectObject");
  629. }
  630. if (dwFlags & OPF_RELEASEMARSHALDATA)
  631. {
  632. // call RMD on the stream
  633. ResetStream(pStm);
  634. hr = CoReleaseMarshalData(pStm);
  635. CHKOP(hr, "CoReleaseMarshalData");
  636. }
  637. if (dwFlags & OPF_UNMARSHAL)
  638. {
  639. // unmarshal the interface from the stream
  640. ResetStream(pStm);
  641. hr = CoUnmarshalInterface(pStm, riid, (void **)&punk);
  642. CHKOP(hr, "CoUnmarshalInterface");
  643. }
  644. if (dwFlags & OPF_RELEASE)
  645. {
  646. // release the interface pointer (if there is one).
  647. if (punk != NULL)
  648. {
  649. ULONG cRefs = punk->Release();
  650. }
  651. }
  652. SignalEvent(pIP->hEventDone);
  653. DBGOUT("DoIfOperation Oper:%x hr:%x\n", dwFlags, hr);
  654. return hr;
  655. }
  656. //+-------------------------------------------------------------------
  657. //
  658. // Function: CreateExecParam
  659. //
  660. // Synopsis: allocates an exec parameter packet for the given # of
  661. // INTERFACEPARAMSs.
  662. //
  663. //--------------------------------------------------------------------
  664. EXECPARAMS *CreateExecParam(ULONG cIP)
  665. {
  666. // allocate memory
  667. ULONG ulSize = sizeof(EXECPARAMS) + (cIP * sizeof(INTERFACEPARAMS));
  668. EXECPARAMS *pEP = (EXECPARAMS *) new BYTE[ulSize];
  669. if (pEP == NULL)
  670. {
  671. DBGOUT("CreateExecParams OOM\n");
  672. return NULL;
  673. }
  674. // zero fill the packet
  675. memset((BYTE*)pEP, 0, ulSize);
  676. pEP->cIPs = cIP;
  677. DBGOUT("CreateExecParam pEP:%x\n", pEP);
  678. return pEP;
  679. }
  680. //+-------------------------------------------------------------------
  681. //
  682. // Function: FillExecParam
  683. //
  684. // Synopsis: fills an exec parameter packet
  685. //
  686. //--------------------------------------------------------------------
  687. void FillExecParam(EXECPARAMS *pEP, DWORD dwFlags, ULONG cReps,
  688. HANDLE hEventRepStart, HANDLE hEventRepDone,
  689. HANDLE hEventThreadStart, HANDLE hEventThreadDone)
  690. {
  691. DBGOUT("FillExecParam pEP:%x\n", pEP);
  692. pEP->dwFlags = dwFlags;
  693. pEP->hEventThreadStart = hEventThreadStart;
  694. pEP->hEventThreadDone = hEventThreadDone;
  695. pEP->hEventThreadExit = GetEvent();
  696. pEP->cReps = cReps;
  697. pEP->hEventRepStart = hEventRepStart;
  698. pEP->hEventRepDone = hEventRepDone;
  699. }
  700. //+-------------------------------------------------------------------
  701. //
  702. // Function: ReleaseExecParam
  703. //
  704. // Synopsis: releases an exec parameter packet
  705. //
  706. //--------------------------------------------------------------------
  707. void ReleaseExecParam(EXECPARAMS *pEP)
  708. {
  709. DBGOUT("ReleaseExecParam pEP:%x\n", pEP);
  710. if (!pEP)
  711. return;
  712. // release the events.
  713. ReleaseEvent(pEP->hEventThreadStart);
  714. ReleaseEvent(pEP->hEventThreadDone);
  715. ReleaseEvent(pEP->hEventThreadExit);
  716. ReleaseEvent(pEP->hEventRepStart);
  717. ReleaseEvent(pEP->hEventRepDone);
  718. // release the interface parameter blocks
  719. for (ULONG i=0; i<pEP->cIPs; i++)
  720. {
  721. ReleaseInterfaceParam(&(pEP->aIP[i]));
  722. }
  723. // free the memory
  724. delete pEP;
  725. }
  726. //+-------------------------------------------------------------------
  727. //
  728. // Function: FillInterfaceParam
  729. //
  730. // Synopsis: fills default info into the interface parms
  731. //
  732. //--------------------------------------------------------------------
  733. void FillInterfaceParam(INTERFACEPARAMS *pIP, REFIID riid, IUnknown *punk,
  734. IStream *pStm, HANDLE hEventStart, HANDLE hEventDone)
  735. {
  736. DBGOUT("FillInterfaceParam pIP:%x\n", pIP);
  737. pIP->iid = riid;
  738. pIP->punk = punk;
  739. pIP->pStm = pStm;
  740. pIP->hEventStart = hEventStart;
  741. pIP->hEventDone = hEventDone;
  742. }
  743. //+-------------------------------------------------------------------
  744. //
  745. // Function: ReleaseInterfaceParam
  746. //
  747. // Synopsis: releases an interface parameter packet
  748. //
  749. //--------------------------------------------------------------------
  750. void ReleaseInterfaceParam(INTERFACEPARAMS *pIP)
  751. {
  752. DBGOUT("ReleaseInterfaceParam pIP:%x\n", pIP);
  753. if (!pIP)
  754. return;
  755. // release the interfaces
  756. ReleaseInterface(pIP->punk);
  757. ReleaseInterface(pIP->pStm);
  758. // release the events
  759. ReleaseEvent(pIP->hEventStart);
  760. ReleaseEvent(pIP->hEventDone);
  761. }