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.

1594 lines
26 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. t.c
  5. Abstract:
  6. Basic functionality tests for the RM APIs
  7. Revision History:
  8. Who When What
  9. -------- -------- ----------------------------------------------
  10. josephj 01-13-99 Created
  11. Notes:
  12. --*/
  13. #include "c.h"
  14. #ifdef TESTPROGRAM
  15. enum
  16. {
  17. LOCKLEVEL_GLOBALS=1,
  18. LOCKLEVEL_O1,
  19. LOCKLEVEL_O2
  20. };
  21. typedef struct
  22. {
  23. RM_OBJECT_HEADER Hdr;
  24. RM_LOCK Lock;
  25. //
  26. // Resources
  27. //
  28. BOOLEAN fInited1; // Resource1
  29. BOOLEAN fInited2; // Resource2
  30. //
  31. // Groups
  32. //
  33. RM_GROUP Group;
  34. } GLOBALS;
  35. //================================ O1 Information ==================================
  36. PRM_OBJECT_HEADER
  37. O1Create(
  38. PRM_OBJECT_HEADER pParentObject,
  39. PVOID pCreateParams,
  40. PRM_STACK_RECORD psr
  41. );
  42. VOID
  43. O1Delete(
  44. PRM_OBJECT_HEADER Obj,
  45. PRM_STACK_RECORD psr
  46. );
  47. //
  48. // Hash table comparison function.
  49. //
  50. BOOLEAN
  51. O1CompareKey(
  52. PVOID pKey,
  53. PRM_HASH_LINK pItem
  54. );
  55. //
  56. // Hash generating function.
  57. //
  58. ULONG
  59. O1Hash(
  60. PVOID pKey
  61. );
  62. typedef struct
  63. {
  64. RM_OBJECT_HEADER Hdr;
  65. RM_LOCK Lock;
  66. UINT Key;
  67. BOOLEAN fInited;
  68. } O1;
  69. RM_HASH_INFO
  70. O1_HashInfo =
  71. {
  72. NULL, // pfnTableAllocator
  73. NULL, // pfnTableDeallocator
  74. O1CompareKey, // fnCompare
  75. // Function to generate a ULONG-sized hash.
  76. //
  77. O1Hash // pfnHash
  78. };
  79. RM_STATIC_OBJECT_INFO
  80. O1_StaticInfo =
  81. {
  82. 0, // TypeUID
  83. 0, // TypeFlags
  84. "O1", // TypeName
  85. 0, // Timeout
  86. O1Create,
  87. O1Delete,
  88. NULL, // Verifier
  89. 0, // ResourceTable size
  90. NULL, // ResourceTable
  91. &O1_HashInfo, // pHashInfo
  92. };
  93. //================================ O2 Information ==================================
  94. PRM_OBJECT_HEADER
  95. O2Create(
  96. PRM_OBJECT_HEADER pParentObject,
  97. PVOID pCreateParams,
  98. PRM_STACK_RECORD psr
  99. );
  100. VOID
  101. O2Delete(
  102. PRM_OBJECT_HEADER Obj,
  103. PRM_STACK_RECORD psr
  104. );
  105. //
  106. // Hash table comparison function.
  107. //
  108. BOOLEAN
  109. O2CompareKey(
  110. PVOID pKey,
  111. PRM_HASH_LINK pItem
  112. );
  113. //
  114. // Hash generating function.
  115. //
  116. ULONG
  117. O2Hash(
  118. PVOID pKey
  119. );
  120. typedef struct
  121. {
  122. RM_OBJECT_HEADER Hdr;
  123. RM_LOCK Lock;
  124. UINT Key;
  125. BOOLEAN fInited;
  126. RM_TASK O2Task;
  127. } O2;
  128. RM_HASH_INFO
  129. O2_HashInfo =
  130. {
  131. NULL, // pfnTableAllocator
  132. NULL, // pfnTableDeallocator
  133. O2CompareKey, // fnCompare
  134. // Function to generate a ULONG-sized hash.
  135. //
  136. O2Hash // pfnHash
  137. };
  138. RM_STATIC_OBJECT_INFO
  139. O2_StaticInfo =
  140. {
  141. 0, // TypeUID
  142. 0, // TypeFlags
  143. "O2", // TypeName
  144. 0, // Timeout
  145. O2Create,
  146. O2Delete,
  147. NULL, //verifier
  148. 0, // ResourceTable size
  149. NULL, // ResourceTable
  150. &O2_HashInfo, // pHashInfo
  151. };
  152. //================================ GLOBALS (ROOT Object) Information =================
  153. //
  154. // List of fixed resources used by ArpGlobals
  155. //
  156. enum
  157. {
  158. RTYPE_GLOBAL_RESOURCE1,
  159. RTYPE_GLOBAL_RESOURCE2
  160. }; // ARP_GLOBAL_RESOURCES;
  161. RM_STATUS
  162. testResHandleGlobalResource1(
  163. PRM_OBJECT_HEADER pObj,
  164. RM_RESOURCE_OPERATION Op,
  165. PVOID pvUserParams,
  166. PRM_STACK_RECORD psr
  167. );
  168. RM_STATUS
  169. testResHandleGlobalResource2(
  170. PRM_OBJECT_HEADER pObj,
  171. RM_RESOURCE_OPERATION Op,
  172. PVOID pvUserParams,
  173. PRM_STACK_RECORD psr
  174. );
  175. VOID
  176. testTaskDelete (
  177. PRM_OBJECT_HEADER pObj,
  178. PRM_STACK_RECORD psr
  179. );
  180. //
  181. // Identifies information pertaining to the use of the above resources.
  182. // Following table MUST be in strict increasing order of the RTYPE_GLOBAL
  183. // enum.
  184. //
  185. RM_RESOURCE_TABLE_ENTRY
  186. Globals_ResourceTable[] =
  187. {
  188. {RTYPE_GLOBAL_RESOURCE1, testResHandleGlobalResource1},
  189. {RTYPE_GLOBAL_RESOURCE2, testResHandleGlobalResource2}
  190. };
  191. RM_STATIC_OBJECT_INFO
  192. Globals_StaticInfo =
  193. {
  194. 0, // TypeUID
  195. 0, // TypeFlags
  196. "Globals", // TypeName
  197. 0, // Timeout
  198. NULL, // pfnCreate
  199. NULL, // pfnDelete
  200. NULL, // verifier
  201. sizeof(Globals_ResourceTable)/sizeof(Globals_ResourceTable[1]),
  202. Globals_ResourceTable
  203. };
  204. RM_STATIC_OBJECT_INFO
  205. Tasks_StaticInfo =
  206. {
  207. 0, // TypeUID
  208. 0, // TypeFlags
  209. "TEST Task", // TypeName
  210. 0, // Timeout
  211. NULL, // pfnCreate
  212. testTaskDelete, // pfnDelete
  213. NULL, // LockVerifier
  214. 0, // length of resource table
  215. NULL // Resource Table
  216. };
  217. RM_STATIC_OBJECT_INFO
  218. O2Tasks_StaticInfo =
  219. {
  220. 0, // TypeUID
  221. 0, // TypeFlags
  222. "O2 Task", // TypeName
  223. 0, // Timeout
  224. NULL, // pfnCreate
  225. NULL, // pfnDelete NULL because it's contained in O2.
  226. NULL, // LockVerifier
  227. 0, // length of resource table
  228. NULL // Resource Table
  229. };
  230. typedef struct
  231. {
  232. RM_TASK TskHdr;
  233. int i;
  234. } T1_TASK;
  235. typedef struct
  236. {
  237. RM_TASK TskHdr;
  238. int i;
  239. } T2_TASK;
  240. typedef struct
  241. {
  242. RM_TASK TskHdr;
  243. int i;
  244. } T3_TASK;
  245. typedef union
  246. {
  247. RM_TASK TskHdr;
  248. T1_TASK T1;
  249. T2_TASK T2;
  250. T3_TASK T3;
  251. } TESTTASK;
  252. GLOBALS Globals;
  253. RM_STATUS
  254. init_globals(
  255. PRM_STACK_RECORD psr
  256. );
  257. VOID
  258. deinit_globals(
  259. PRM_STACK_RECORD psr
  260. );
  261. NDIS_STATUS
  262. Task1 (
  263. IN struct _RM_TASK * pTask,
  264. IN RM_TASK_OPERATION Op,
  265. IN UINT_PTR UserParam, // Unused
  266. IN PRM_STACK_RECORD pSR
  267. );
  268. NDIS_STATUS
  269. Task2 (
  270. IN struct _RM_TASK * pTask,
  271. IN RM_TASK_OPERATION Code,
  272. IN UINT_PTR UserParam, // Unused
  273. IN PRM_STACK_RECORD pSR
  274. );
  275. NDIS_STATUS
  276. Task3 (
  277. IN struct _RM_TASK * pTask,
  278. IN RM_TASK_OPERATION Code,
  279. IN UINT_PTR UserParam, // Task to pend on.
  280. IN PRM_STACK_RECORD pSR
  281. );
  282. NDIS_STATUS
  283. TaskO2 (
  284. IN struct _RM_TASK * pTask,
  285. IN RM_TASK_OPERATION Op,
  286. IN UINT_PTR UserParam, // Unused
  287. IN PRM_STACK_RECORD pSR
  288. );
  289. NDIS_STATUS
  290. TaskUnloadO2 (
  291. IN struct _RM_TASK * pTask,
  292. IN RM_TASK_OPERATION Op,
  293. IN UINT_PTR UserParam, // Unused
  294. IN PRM_STACK_RECORD pSR
  295. );
  296. NDIS_STATUS
  297. AllocateTask(
  298. IN PRM_OBJECT_HEADER pParentObject,
  299. IN PFN_RM_TASK_HANDLER pfnHandler,
  300. IN UINT Timeout,
  301. IN const char * szDescription,
  302. OUT PRM_TASK *ppTask,
  303. IN PRM_STACK_RECORD pSR
  304. )
  305. {
  306. TESTTASK *pTTask = ALLOCSTRUCT(TESTTASK);
  307. NDIS_STATUS Status = NDIS_STATUS_RESOURCES;
  308. *ppTask = NULL;
  309. if (pTTask != NULL)
  310. {
  311. RmInitializeTask(
  312. &(pTTask->TskHdr),
  313. pParentObject,
  314. pfnHandler,
  315. &Tasks_StaticInfo,
  316. szDescription,
  317. Timeout,
  318. pSR
  319. );
  320. *ppTask = &(pTTask->TskHdr);
  321. Status = NDIS_STATUS_SUCCESS;
  322. }
  323. return Status;
  324. }
  325. VOID
  326. FreeTask(
  327. IN PRM_TASK pTask,
  328. IN PRM_STACK_RECORD pSR
  329. )
  330. {
  331. FREE(pTask);
  332. }
  333. PRM_OBJECT_HEADER
  334. O1Create(
  335. PRM_OBJECT_HEADER pParentObject,
  336. PVOID pCreateParams,
  337. PRM_STACK_RECORD psr
  338. )
  339. {
  340. O1 * po1 = ALLOCSTRUCT(O1);
  341. if (po1)
  342. {
  343. RmInitializeLock(
  344. &po1->Lock,
  345. LOCKLEVEL_O1
  346. );
  347. RmInitializeHeader(
  348. pParentObject, // NULL, // pParentObject,
  349. &po1->Hdr,
  350. 123,
  351. &po1->Lock,
  352. &O1_StaticInfo,
  353. NULL,
  354. psr
  355. );
  356. po1->Key = (UINT) (UINT_PTR) pCreateParams;
  357. }
  358. return &po1->Hdr;
  359. }
  360. VOID
  361. O1Delete(
  362. PRM_OBJECT_HEADER Obj,
  363. PRM_STACK_RECORD psr
  364. )
  365. {
  366. FREE(Obj);
  367. }
  368. PRM_OBJECT_HEADER
  369. O2Create(
  370. PRM_OBJECT_HEADER pParentObject,
  371. PVOID pCreateParams,
  372. PRM_STACK_RECORD pSR
  373. )
  374. {
  375. O2 * po2 = ALLOCSTRUCT(O2);
  376. if (po2)
  377. {
  378. RmInitializeLock(
  379. &po2->Lock,
  380. LOCKLEVEL_O2
  381. );
  382. RmInitializeHeader(
  383. pParentObject, // NULL, // pParentObject,
  384. &po2->Hdr,
  385. 234,
  386. &po2->Lock,
  387. &O2_StaticInfo,
  388. NULL,
  389. pSR
  390. );
  391. RmInitializeTask(
  392. &(po2->O2Task),
  393. &po2->Hdr,
  394. TaskO2,
  395. &O2Tasks_StaticInfo,
  396. "TaskO2",
  397. 0,
  398. pSR
  399. );
  400. po2->Key = (UINT) (UINT_PTR) pCreateParams;
  401. }
  402. return &po2->Hdr;
  403. }
  404. VOID
  405. O2Delete(
  406. PRM_OBJECT_HEADER Obj,
  407. PRM_STACK_RECORD psr
  408. )
  409. {
  410. FREE(Obj);
  411. }
  412. RM_STATUS
  413. testResHandleGlobalResource1(
  414. PRM_OBJECT_HEADER pObj,
  415. RM_RESOURCE_OPERATION Op,
  416. PVOID pvUserParams,
  417. PRM_STACK_RECORD psr
  418. )
  419. {
  420. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  421. GLOBALS *pGlobals = CONTAINING_RECORD(pObj, GLOBALS, Hdr);
  422. ENTER("GlobalResource1", 0xd7c1efbb);
  423. if (Op == RM_RESOURCE_OP_LOAD)
  424. {
  425. TR_INFO(("LOADING RESOUCE1\n"));
  426. pGlobals->fInited1 = TRUE;
  427. Status = NDIS_STATUS_SUCCESS;
  428. }
  429. else if (Op == RM_RESOURCE_OP_UNLOAD)
  430. {
  431. TR_INFO(("UNLOADING RESOUCE1\n"));
  432. //
  433. // Were unloading this "resource."
  434. //
  435. ASSERTEX(pGlobals->fInited1, pGlobals);
  436. pGlobals->fInited1 = FALSE;
  437. // Always return success on unload.
  438. //
  439. Status = NDIS_STATUS_SUCCESS;
  440. }
  441. else
  442. {
  443. // Unexpected op code.
  444. //
  445. ASSERTEX(FALSE, pObj);
  446. }
  447. EXIT()
  448. return Status;
  449. }
  450. RM_STATUS
  451. testResHandleGlobalResource2(
  452. PRM_OBJECT_HEADER pObj,
  453. RM_RESOURCE_OPERATION Op,
  454. PVOID pvUserParams,
  455. PRM_STACK_RECORD psr
  456. )
  457. {
  458. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  459. GLOBALS *pGlobals = CONTAINING_RECORD(pObj, GLOBALS, Hdr);
  460. ENTER("GlobalResource2", 0xca85474f)
  461. if (Op == RM_RESOURCE_OP_LOAD)
  462. {
  463. TR_INFO(("LOADING RESOUCE2\n"));
  464. pGlobals->fInited2 = TRUE;
  465. Status = NDIS_STATUS_SUCCESS;
  466. }
  467. else if (Op == RM_RESOURCE_OP_UNLOAD)
  468. {
  469. TR_INFO(("UNLOADING RESOUCE2\n"));
  470. //
  471. // Were unloading this "resource."
  472. //
  473. ASSERTEX(pGlobals->fInited2, pGlobals);
  474. pGlobals->fInited2 = FALSE;
  475. // Always return success on unload.
  476. //
  477. Status = NDIS_STATUS_SUCCESS;
  478. }
  479. else
  480. {
  481. // Unexpected op code.
  482. //
  483. ASSERTEX(FALSE, pObj);
  484. }
  485. EXIT()
  486. return Status;
  487. }
  488. RM_STATUS
  489. init_globals(
  490. PRM_STACK_RECORD psr
  491. )
  492. {
  493. NDIS_STATUS Status;
  494. //
  495. // Initialize the global, statically-allocated object Globals;
  496. //
  497. RmInitializeLock(
  498. &Globals.Lock,
  499. LOCKLEVEL_GLOBALS
  500. );
  501. RmInitializeHeader(
  502. NULL, // pParentObject,
  503. &Globals.Hdr,
  504. 001,
  505. &Globals.Lock,
  506. &Globals_StaticInfo,
  507. NULL,
  508. psr
  509. );
  510. //
  511. // Load resource1
  512. //
  513. Status = RmLoadGenericResource(
  514. &Globals.Hdr,
  515. RTYPE_GLOBAL_RESOURCE1,
  516. psr
  517. );
  518. if (!FAIL(Status))
  519. {
  520. //
  521. // Load resource1
  522. //
  523. Status = RmLoadGenericResource(
  524. &Globals.Hdr,
  525. RTYPE_GLOBAL_RESOURCE2,
  526. psr
  527. );
  528. }
  529. return Status;
  530. }
  531. VOID
  532. deinit_globals(
  533. PRM_STACK_RECORD psr
  534. )
  535. {
  536. RmUnloadGenericResource(
  537. &Globals.Hdr,
  538. RTYPE_GLOBAL_RESOURCE1,
  539. psr
  540. );
  541. RmUnloadAllGenericResources(
  542. &Globals.Hdr,
  543. psr
  544. );
  545. RmDeallocateObject(
  546. &Globals.Hdr,
  547. psr
  548. );
  549. }
  550. //
  551. // Hash comparision function.
  552. //
  553. BOOLEAN
  554. O1CompareKey(
  555. PVOID pKey,
  556. PRM_HASH_LINK pItem
  557. )
  558. {
  559. O1 *pO1 = CONTAINING_RECORD(pItem, O1, Hdr.HashLink);
  560. return *((UINT*)pKey) == pO1->Key;
  561. }
  562. //
  563. // Hash generating function.
  564. //
  565. ULONG
  566. O1Hash(
  567. PVOID pKey
  568. )
  569. {
  570. return *(UINT*)pKey;
  571. }
  572. //
  573. // Hash comparision function.
  574. //
  575. BOOLEAN
  576. O2CompareKey(
  577. PVOID pKey,
  578. PRM_HASH_LINK pItem
  579. )
  580. {
  581. O2 *pO2 = CONTAINING_RECORD(pItem, O2, Hdr.HashLink);
  582. return *((UINT*)pKey) == pO2->Key;
  583. }
  584. //
  585. // Hash generating function.
  586. //
  587. ULONG
  588. O2Hash(
  589. PVOID pKey
  590. )
  591. {
  592. return *(UINT*)pKey;
  593. }
  594. VOID
  595. testTaskDelete (
  596. PRM_OBJECT_HEADER pObj,
  597. PRM_STACK_RECORD psr
  598. )
  599. {
  600. printf("testTaskDelete: Called to delete obj %p\n", pObj);
  601. }
  602. NDIS_STATUS
  603. Task1(
  604. IN struct _RM_TASK * pTask,
  605. IN RM_TASK_OPERATION Code,
  606. IN UINT_PTR UserParam, // Unused
  607. IN PRM_STACK_RECORD pSR
  608. )
  609. //
  610. // DONE
  611. //
  612. {
  613. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  614. O1* po1 = (O1*) RM_PARENT_OBJECT(pTask);
  615. ENTER("Task1", 0x4abf3903)
  616. switch(Code)
  617. {
  618. case RM_TASKOP_START:
  619. printf("Task1: START called\n");
  620. Status = NDIS_STATUS_SUCCESS;
  621. break;
  622. case RM_TASKOP_END:
  623. printf("Task1: END called\n");
  624. Status = (NDIS_STATUS) UserParam;
  625. break;
  626. default:
  627. {
  628. ASSERTEX(!"Unexpected task op", pTask);
  629. }
  630. break;
  631. } // switch (Code)
  632. RM_ASSERT_NOLOCKS(pSR);
  633. EXIT()
  634. return Status;
  635. }
  636. NDIS_STATUS
  637. Task2(
  638. IN struct _RM_TASK * pTask,
  639. IN RM_TASK_OPERATION Code,
  640. IN UINT_PTR UserParam, // Unused
  641. IN PRM_STACK_RECORD pSR
  642. )
  643. //
  644. // DONE
  645. //
  646. {
  647. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  648. O1* po1 = (O1*) RM_PARENT_OBJECT(pTask);
  649. ENTER("Task2", 0x6e65b76c)
  650. // Following are the list of pending states for this task.
  651. //
  652. enum
  653. {
  654. PEND_OnStart
  655. };
  656. switch(Code)
  657. {
  658. case RM_TASKOP_START:
  659. {
  660. printf("Task2: START called\n");
  661. RmSuspendTask(pTask, PEND_OnStart, pSR);
  662. RM_ASSERT_NOLOCKS(pSR);
  663. Status = NDIS_STATUS_PENDING;
  664. }
  665. break;
  666. case RM_TASKOP_PENDCOMPLETE:
  667. {
  668. switch(RM_PEND_CODE(pTask))
  669. {
  670. case PEND_OnStart:
  671. {
  672. printf("Task2: PEND_OnStart complete\n");
  673. Status = (NDIS_STATUS) UserParam;
  674. // Status of the completed operation can't itself be pending!
  675. //
  676. ASSERT(Status != NDIS_STATUS_PENDING);
  677. } // end case PEND_OnStart
  678. break;
  679. default:
  680. {
  681. ASSERTEX(!"Unknown pend op", pTask);
  682. }
  683. break;
  684. } // end switch(RM_PEND_CODE(pTask))
  685. } // case RM_TASKOP_PENDCOMPLETE
  686. break;
  687. case RM_TASKOP_END:
  688. {
  689. printf("Task2: END called\n");
  690. Status = (NDIS_STATUS) UserParam;
  691. }
  692. break;
  693. default:
  694. {
  695. ASSERTEX(!"Unexpected task op", pTask);
  696. }
  697. break;
  698. } // switch (Code)
  699. RM_ASSERT_NOLOCKS(pSR);
  700. EXIT()
  701. return Status;
  702. }
  703. NDIS_STATUS
  704. Task3(
  705. IN struct _RM_TASK * pTask,
  706. IN RM_TASK_OPERATION Code,
  707. IN UINT_PTR UserParam,
  708. IN PRM_STACK_RECORD pSR
  709. )
  710. {
  711. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  712. O1* po1 = (O1*) RM_PARENT_OBJECT(pTask);
  713. T3_TASK *pT3Task = (T3_TASK *) pTask;
  714. ENTER("Task3", 0x7e89bf6d)
  715. // Following are the list of pending states for this task.
  716. //
  717. enum
  718. {
  719. PEND_OnStart
  720. };
  721. printf ("pT3Task.i = %d\n", pT3Task->i);
  722. switch(Code)
  723. {
  724. case RM_TASKOP_START:
  725. {
  726. PRM_TASK pOtherTask = (PRM_TASK) UserParam;
  727. printf("Task3: START called\n");
  728. RmPendTaskOnOtherTask(pTask, PEND_OnStart, pOtherTask, pSR);
  729. RM_ASSERT_NOLOCKS(pSR);
  730. Status = NDIS_STATUS_PENDING;
  731. }
  732. break;
  733. case RM_TASKOP_PENDCOMPLETE:
  734. {
  735. switch(RM_PEND_CODE(pTask))
  736. {
  737. case PEND_OnStart:
  738. {
  739. printf("Task3: PEND_OnStart complete\n");
  740. Status = (NDIS_STATUS) UserParam;
  741. // Status of the completed operation can't itself be pending!
  742. //
  743. ASSERT(Status != NDIS_STATUS_PENDING);
  744. } // end case PEND_OnStart
  745. break;
  746. default:
  747. {
  748. ASSERTEX(!"Unknown pend op", pTask);
  749. }
  750. break;
  751. } // end switch(RM_PEND_CODE(pTask))
  752. } // case RM_TASKOP_PENDCOMPLETE
  753. break;
  754. case RM_TASKOP_END:
  755. {
  756. printf("Task3: END called\n");
  757. Status = (NDIS_STATUS) UserParam;
  758. }
  759. break;
  760. default:
  761. {
  762. ASSERTEX(!"Unexpected task op", pTask);
  763. }
  764. break;
  765. } // switch (Code)
  766. RM_ASSERT_NOLOCKS(pSR);
  767. EXIT()
  768. return Status;
  769. }
  770. NDIS_STATUS
  771. TaskO2(
  772. IN struct _RM_TASK * pTask,
  773. IN RM_TASK_OPERATION Code,
  774. IN UINT_PTR UserParam, // Unused
  775. IN PRM_STACK_RECORD pSR
  776. )
  777. //
  778. // DONE
  779. //
  780. {
  781. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  782. O2* po2 = (O2*) RM_PARENT_OBJECT(pTask);
  783. ENTER("TaskO2", 0xe10fbc33)
  784. // Following are the list of pending states for this task.
  785. //
  786. enum
  787. {
  788. PEND_OnStart
  789. };
  790. ASSERT(po2 == CONTAINING_RECORD(pTask, O2, O2Task));
  791. switch(Code)
  792. {
  793. case RM_TASKOP_START:
  794. {
  795. printf("TaskO2: START called\n");
  796. RmSuspendTask(pTask, PEND_OnStart, pSR);
  797. RM_ASSERT_NOLOCKS(pSR);
  798. Status = NDIS_STATUS_PENDING;
  799. }
  800. break;
  801. case RM_TASKOP_PENDCOMPLETE:
  802. {
  803. switch(RM_PEND_CODE(pTask))
  804. {
  805. case PEND_OnStart:
  806. {
  807. printf("TaskO2: PEND_OnStart complete\n");
  808. Status = (NDIS_STATUS) UserParam;
  809. // Status of the completed operation can't itself be pending!
  810. //
  811. ASSERT(Status != NDIS_STATUS_PENDING);
  812. } // end case PEND_OnStart
  813. break;
  814. default:
  815. {
  816. ASSERTEX(!"Unknown pend op", pTask);
  817. }
  818. break;
  819. } // end switch(RM_PEND_CODE(pTask))
  820. } // case RM_TASKOP_PENDCOMPLETE
  821. break;
  822. case RM_TASKOP_END:
  823. {
  824. printf("TaskO2: END called\n");
  825. Status = (NDIS_STATUS) UserParam;
  826. }
  827. break;
  828. default:
  829. {
  830. ASSERTEX(!"Unexpected task op", pTask);
  831. }
  832. break;
  833. } // switch (Code)
  834. RM_ASSERT_NOLOCKS(pSR);
  835. EXIT()
  836. return Status;
  837. }
  838. NDIS_STATUS
  839. TaskUnloadO2(
  840. IN struct _RM_TASK * pTask,
  841. IN RM_TASK_OPERATION Code,
  842. IN UINT_PTR UserParam, // Unused
  843. IN PRM_STACK_RECORD pSR
  844. )
  845. //
  846. // DONE
  847. //
  848. {
  849. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  850. O2* po2 = (O2*) RM_PARENT_OBJECT(pTask);
  851. ENTER("TaskUnloadO2", 0xa15314da)
  852. // Following are the list of pending states for this task.
  853. //
  854. enum
  855. {
  856. PEND_OnStart
  857. };
  858. switch(Code)
  859. {
  860. case RM_TASKOP_START:
  861. {
  862. printf("TaskTaskO2: START called\n");
  863. RmPendTaskOnOtherTask(pTask, PEND_OnStart, &po2->O2Task, pSR);
  864. RmResumeTask(&po2->O2Task, 0, pSR);
  865. RM_ASSERT_NOLOCKS(pSR);
  866. Status = NDIS_STATUS_PENDING;
  867. }
  868. break;
  869. case RM_TASKOP_PENDCOMPLETE:
  870. {
  871. switch(RM_PEND_CODE(pTask))
  872. {
  873. case PEND_OnStart:
  874. {
  875. printf("TaskUnloadO2: PEND_OnStart complete\n");
  876. Status = (NDIS_STATUS) UserParam;
  877. // Status of the completed operation can't itself be pending!
  878. //
  879. ASSERT(Status != NDIS_STATUS_PENDING);
  880. } // end case PEND_OnStart
  881. break;
  882. default:
  883. {
  884. ASSERTEX(!"Unknown pend op", pTask);
  885. }
  886. break;
  887. } // end switch(RM_PEND_CODE(pTask))
  888. } // case RM_TASKOP_PENDCOMPLETE
  889. break;
  890. case RM_TASKOP_END:
  891. {
  892. printf("TaskUnloadO2: END called\n");
  893. // Actually free object po2 in group.
  894. //
  895. RmFreeObjectInGroup(
  896. &Globals.Group,
  897. &po2->Hdr,
  898. NULL, // pTask
  899. pSR
  900. );
  901. Status = (NDIS_STATUS) UserParam;
  902. }
  903. break;
  904. default:
  905. {
  906. ASSERTEX(!"Unexpected task op", pTask);
  907. }
  908. break;
  909. } // switch (Code)
  910. RM_ASSERT_NOLOCKS(pSR);
  911. EXIT()
  912. return Status;
  913. }
  914. struct
  915. {
  916. BOOLEAN fInited;
  917. PRM_GROUP pGroup;
  918. // Following is a dummy stack record. It needs to be initialized before
  919. // it can be used.
  920. //
  921. struct
  922. {
  923. RM_LOCKING_INFO rm_lock_array[4];
  924. RM_STACK_RECORD sr;
  925. RM_LOCK Lock;
  926. } SrInfo;
  927. } gDummys;
  928. void init_dummy_vars(void)
  929. {
  930. RM_STATUS Status;
  931. O2 * po2 = NULL;
  932. O2 * po2A = NULL;
  933. PRM_TASK pTask3a=NULL;
  934. PRM_TASK pTask3b=NULL;
  935. RM_DECLARE_STACK_RECORD(sr)
  936. printf("\nEnter init_dummy_vars\n\n");;
  937. // Must be done before any RM apis are used.
  938. //
  939. RmInitializeRm();
  940. do
  941. {
  942. UINT Key = 1234;
  943. Status = init_globals(&sr);
  944. if (FAIL(Status)) break;
  945. gDummys.fInited = TRUE;
  946. // Initialize the dummy stack info and the lock for it to use.
  947. //
  948. {
  949. // True Init
  950. //
  951. gDummys.SrInfo.sr.TmpRefs = 0;
  952. gDummys.SrInfo.sr.LockInfo.CurrentLevel = 0;
  953. gDummys.SrInfo.sr.LockInfo.pFirst = rm_lock_array;
  954. gDummys.SrInfo.sr.LockInfo.pNextFree = rm_lock_array;
  955. gDummys.SrInfo.sr.LockInfo.pLast = rm_lock_array
  956. + sizeof(rm_lock_array)/sizeof(*rm_lock_array) - 1;
  957. RM_INIT_DBG_STACK_RECORD(gDummys.SrInfo.sr, 0);
  958. // Add some bogus temp refs.
  959. //
  960. gDummys.SrInfo.sr.TmpRefs = 0x123;
  961. // Now initialize the lock...
  962. RmInitializeLock(
  963. &gDummys.SrInfo.Lock,
  964. 0x345 // locklevel.
  965. );
  966. // And lock
  967. // WARNING: we use the private function rmLock defined internal
  968. // to rm.c.
  969. //
  970. {
  971. VOID
  972. rmLock(
  973. PRM_LOCK pLock,
  974. #if RM_EXTRA_CHECKING
  975. UINT uLocID,
  976. PFNLOCKVERIFIER pfnVerifier,
  977. PVOID pVerifierContext,
  978. #endif //RM_EXTRA_CHECKING
  979. PRM_STACK_RECORD pSR
  980. );
  981. rmLock(
  982. &gDummys.SrInfo.Lock,
  983. #if RM_EXTRA_CHECKING
  984. 0, // uLocID,
  985. NULL, // pfnVerifier,
  986. NULL, // pVerifierContext,
  987. #endif //RM_EXTRA_CHECKING
  988. &gDummys.SrInfo.sr
  989. );
  990. }
  991. }
  992. RmInitializeGroup(
  993. &Globals.Hdr,
  994. &O2_StaticInfo,
  995. &Globals.Group,
  996. "O1 Group",
  997. &sr
  998. );
  999. printf("Called RmInitializeGroup\n");
  1000. Status = RM_CREATE_AND_LOCK_OBJECT_IN_GROUP(
  1001. &Globals.Group,
  1002. &Key, // Key
  1003. (PVOID)Key, // CreateParams
  1004. (RM_OBJECT_HEADER**) &po2,
  1005. NULL, // pfCreated
  1006. &sr);
  1007. if (FAIL(Status))
  1008. {
  1009. printf("Create object in group failed!\n");
  1010. po2 = NULL;
  1011. }
  1012. else
  1013. {
  1014. UINT KeyA = 2345;
  1015. printf("Create 1st object in group succeeded!\n");
  1016. UNLOCKOBJ(po2, &sr);
  1017. // Now start the O2Task, which will pend ...
  1018. //
  1019. Status = RmStartTask(
  1020. &po2->O2Task,
  1021. 0, // UserParam (unused)
  1022. &sr
  1023. );
  1024. ASSERT(PEND(Status));
  1025. RmTmpDereferenceObject(&po2->Hdr, &sr); // Added in lookup.
  1026. Status = RM_CREATE_AND_LOCK_OBJECT_IN_GROUP(
  1027. &Globals.Group,
  1028. &KeyA, // Key
  1029. (PVOID)KeyA, // CreateParams
  1030. (RM_OBJECT_HEADER**) &po2A,
  1031. NULL, // pfCreated
  1032. &sr);
  1033. if (FAIL(Status))
  1034. {
  1035. printf("Create 2nd object in group failed!\n");
  1036. po2A = NULL;
  1037. }
  1038. else
  1039. {
  1040. printf("Create 2nd object in group succeeded!\n");
  1041. UNLOCKOBJ(po2A, &sr);
  1042. // Now start the O2Task, which will pend ...
  1043. //
  1044. Status = RmStartTask(
  1045. &po2A->O2Task,
  1046. 0, // UserParam (unused)
  1047. &sr
  1048. );
  1049. ASSERT(PEND(Status));
  1050. RmTmpDereferenceObject(&po2A->Hdr, &sr);
  1051. }
  1052. }
  1053. //
  1054. // Now let's start a couple of T3 tasks, to both pend on
  1055. // &po2->O2Task.
  1056. //
  1057. if (po2 != NULL)
  1058. {
  1059. Status = AllocateTask(
  1060. &po2->Hdr, // pParentObject
  1061. Task3, // pfnHandler
  1062. 0, // Timeout
  1063. "Task3a",
  1064. &pTask3a,
  1065. &sr
  1066. );
  1067. if (FAIL(Status))
  1068. {
  1069. pTask3a = NULL;
  1070. }
  1071. else
  1072. {
  1073. Status = RmStartTask(
  1074. pTask3a,
  1075. (UINT_PTR) &po2->O2Task, // UserParam
  1076. &sr
  1077. );
  1078. ASSERT(Status == NDIS_STATUS_PENDING);
  1079. }
  1080. Status = AllocateTask(
  1081. &po2->Hdr, // pParentObject
  1082. Task3, // pfnHandler
  1083. 0, // Timeout
  1084. "Task3b",
  1085. &pTask3b,
  1086. &sr
  1087. );
  1088. if (FAIL(Status))
  1089. {
  1090. pTask3b = NULL;
  1091. }
  1092. else
  1093. {
  1094. Status = RmStartTask(
  1095. pTask3b,
  1096. (UINT_PTR) &po2->O2Task, // UserParam
  1097. &sr
  1098. );
  1099. ASSERT(Status == NDIS_STATUS_PENDING);
  1100. }
  1101. // Add some log entries.
  1102. //
  1103. RmDbgLogToObject(
  1104. &po2->Hdr,
  1105. NULL, // szPrefix
  1106. "How now brown cow: pO2=%p, szDesc=%s\n",
  1107. (UINT_PTR) po2,
  1108. (UINT_PTR) po2->Hdr.szDescription,
  1109. 0,
  1110. 0,
  1111. NULL,
  1112. NULL
  1113. );
  1114. RM_ASSERT_NOLOCKS(&sr);
  1115. }
  1116. printf(
  1117. "DUMMY: pGroup=0x%p; po2=0x%p; po2A=0x%p\n",
  1118. &Globals.Group,
  1119. po2,
  1120. po2A
  1121. );
  1122. if (po2 && po2A)
  1123. {
  1124. printf(
  1125. "DUMMY: po2->pTask=0x%p; po2A->pTask=0x%p\n",
  1126. &po2->O2Task,
  1127. &po2A->O2Task
  1128. );
  1129. printf(
  1130. "DUMMY: pTask3a=0x%p; pTask3b=0x%p; pSR=0x%p\n",
  1131. pTask3a,
  1132. pTask3b,
  1133. &gDummys.SrInfo.sr
  1134. );
  1135. }
  1136. gDummys.pGroup = &Globals.Group;
  1137. } while(FALSE);
  1138. RM_ASSERT_CLEAR(&sr);
  1139. printf("\nLeaving init_dummy_vars\n\n");;
  1140. }
  1141. void delete_dummy_vars(void)
  1142. {
  1143. RM_STATUS Status;
  1144. O1 * po1;
  1145. RM_DECLARE_STACK_RECORD(sr)
  1146. printf("\nEnter delete_dummy_vars\n\n");;
  1147. do
  1148. {
  1149. if (!gDummys.fInited) break;
  1150. RmUnloadAllObjectsInGroup(
  1151. gDummys.pGroup,
  1152. AllocateTask,
  1153. TaskUnloadO2,
  1154. NULL,
  1155. NULL, // pTask
  1156. 0, // uTaskPendCode
  1157. &sr
  1158. );
  1159. RmDeinitializeGroup(
  1160. gDummys.pGroup,
  1161. &sr
  1162. );
  1163. deinit_globals(&sr);
  1164. } while(FALSE);
  1165. // Must be done after all RM apis are complete.
  1166. //
  1167. RmDeinitializeRm();
  1168. RM_ASSERT_CLEAR(&sr);
  1169. printf("\nLeaving delete_dummy_vars\n");
  1170. }
  1171. VOID
  1172. NdisInitializeWorkItem(
  1173. IN PNDIS_WORK_ITEM pWorkItem,
  1174. IN NDIS_PROC Routine,
  1175. IN PVOID Context
  1176. )
  1177. {
  1178. ZeroMemory(pWorkItem, sizeof(*pWorkItem));
  1179. pWorkItem->Context = Context;
  1180. pWorkItem->Routine = Routine;
  1181. }
  1182. VOID
  1183. ApcProc_ScheduleWorkItem(
  1184. ULONG_PTR Param
  1185. )
  1186. {
  1187. PNDIS_WORK_ITEM pWI = (PNDIS_WORK_ITEM) Param;
  1188. pWI->Routine(pWI, pWI->Context);
  1189. }
  1190. NDIS_STATUS
  1191. NdisScheduleWorkItem(
  1192. IN PNDIS_WORK_ITEM WorkItem
  1193. )
  1194. {
  1195. DWORD dwRet = QueueUserAPC(
  1196. ApcProc_ScheduleWorkItem,
  1197. GetCurrentThread(),
  1198. (UINT_PTR) WorkItem
  1199. );
  1200. return dwRet ? NDIS_STATUS_SUCCESS: NDIS_STATUS_FAILURE;
  1201. }
  1202. VOID
  1203. NdisInitializeTimer(
  1204. IN OUT PNDIS_TIMER pTimer,
  1205. IN PNDIS_TIMER_FUNCTION TimerFunction,
  1206. IN PVOID FunctionContext
  1207. )
  1208. {
  1209. ZeroMemory(pTimer, sizeof(*pTimer));
  1210. pTimer->hTimer = CreateWaitableTimer(
  1211. NULL, // lpTimerAttributes
  1212. TRUE, // bManualReset
  1213. NULL //lpTimerName
  1214. );
  1215. ASSERT(pTimer->hTimer != NULL);
  1216. pTimer->pfnHandler = TimerFunction;
  1217. pTimer->Context = FunctionContext;
  1218. }
  1219. VOID CALLBACK
  1220. TimerAPCProc_NdisSetTimer(
  1221. LPVOID lpArgToCompletionRoutine, // data value
  1222. DWORD dwTimerLowValue, // timer low value
  1223. DWORD dwTimerHighValue // timer high value
  1224. )
  1225. {
  1226. PNDIS_TIMER pTimer = (PNDIS_TIMER) lpArgToCompletionRoutine;
  1227. pTimer->pfnHandler(
  1228. NULL, // SystemSpecific1
  1229. pTimer->Context, // FunctionContext
  1230. NULL, // SystemSpecific2
  1231. NULL // SystemSpecific3
  1232. );
  1233. }
  1234. VOID
  1235. NdisSetTimer(
  1236. IN PNDIS_TIMER pTimer,
  1237. IN UINT MillisecondsToDelay
  1238. )
  1239. {
  1240. BOOL fRet;
  1241. LARGE_INTEGER DueTime;
  1242. DueTime.QuadPart = Int32x32To64(
  1243. (INT) MillisecondsToDelay,
  1244. -10000 // convert to 100-nanosec, specify relative time
  1245. );
  1246. fRet = SetWaitableTimer(
  1247. pTimer->hTimer, // handle to a timer object
  1248. &DueTime, // when timer will become signaled
  1249. 0, // periodic timer interval
  1250. TimerAPCProc_NdisSetTimer, // completion routine
  1251. pTimer, // data for completion routine
  1252. FALSE // flag for resume state
  1253. );
  1254. ASSERT(fRet);
  1255. }
  1256. VOID
  1257. NdisCancelTimer(
  1258. IN PNDIS_TIMER Timer,
  1259. OUT PBOOLEAN TimerCancelled
  1260. )
  1261. {
  1262. ASSERT(FALSE);
  1263. }
  1264. #endif // TESTPROGRAM