|
|
/*++
Copyright (c) 1998-1999 Microsoft Corporation
Module Name:
t.c
Abstract:
Basic functionality tests for the RM APIs
Revision History:
Who When What -------- -------- ---------------------------------------------- josephj 01-13-99 Created
Notes:
--*/
#include "c.h"
#ifdef TESTPROGRAM
enum { LOCKLEVEL_GLOBALS=1, LOCKLEVEL_O1, LOCKLEVEL_O2 };
typedef struct { RM_OBJECT_HEADER Hdr; RM_LOCK Lock;
//
// Resources
//
BOOLEAN fInited1; // Resource1
BOOLEAN fInited2; // Resource2
//
// Groups
//
RM_GROUP Group;
} GLOBALS;
//================================ O1 Information ==================================
PRM_OBJECT_HEADER O1Create( PRM_OBJECT_HEADER pParentObject, PVOID pCreateParams, PRM_STACK_RECORD psr );
VOID O1Delete( PRM_OBJECT_HEADER Obj, PRM_STACK_RECORD psr );
//
// Hash table comparison function.
//
BOOLEAN O1CompareKey( PVOID pKey, PRM_HASH_LINK pItem );
//
// Hash generating function.
//
ULONG O1Hash( PVOID pKey );
typedef struct { RM_OBJECT_HEADER Hdr; RM_LOCK Lock; UINT Key; BOOLEAN fInited; } O1;
RM_HASH_INFO O1_HashInfo = { NULL, // pfnTableAllocator
NULL, // pfnTableDeallocator
O1CompareKey, // fnCompare
// Function to generate a ULONG-sized hash.
//
O1Hash // pfnHash
};
RM_STATIC_OBJECT_INFO O1_StaticInfo = { 0, // TypeUID
0, // TypeFlags
"O1", // TypeName
0, // Timeout
O1Create, O1Delete, NULL, // Verifier
0, // ResourceTable size
NULL, // ResourceTable
&O1_HashInfo, // pHashInfo
};
//================================ O2 Information ==================================
PRM_OBJECT_HEADER O2Create( PRM_OBJECT_HEADER pParentObject, PVOID pCreateParams, PRM_STACK_RECORD psr );
VOID O2Delete( PRM_OBJECT_HEADER Obj, PRM_STACK_RECORD psr );
//
// Hash table comparison function.
//
BOOLEAN O2CompareKey( PVOID pKey, PRM_HASH_LINK pItem );
//
// Hash generating function.
//
ULONG O2Hash( PVOID pKey );
typedef struct { RM_OBJECT_HEADER Hdr; RM_LOCK Lock; UINT Key; BOOLEAN fInited;
RM_TASK O2Task; } O2;
RM_HASH_INFO O2_HashInfo = { NULL, // pfnTableAllocator
NULL, // pfnTableDeallocator
O2CompareKey, // fnCompare
// Function to generate a ULONG-sized hash.
//
O2Hash // pfnHash
};
RM_STATIC_OBJECT_INFO O2_StaticInfo = { 0, // TypeUID
0, // TypeFlags
"O2", // TypeName
0, // Timeout
O2Create, O2Delete, NULL, //verifier
0, // ResourceTable size
NULL, // ResourceTable
&O2_HashInfo, // pHashInfo
};
//================================ GLOBALS (ROOT Object) Information =================
//
// List of fixed resources used by ArpGlobals
//
enum { RTYPE_GLOBAL_RESOURCE1, RTYPE_GLOBAL_RESOURCE2
}; // ARP_GLOBAL_RESOURCES;
RM_STATUS testResHandleGlobalResource1( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr );
RM_STATUS testResHandleGlobalResource2( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr ); VOID testTaskDelete ( PRM_OBJECT_HEADER pObj, PRM_STACK_RECORD psr );
//
// Identifies information pertaining to the use of the above resources.
// Following table MUST be in strict increasing order of the RTYPE_GLOBAL
// enum.
//
RM_RESOURCE_TABLE_ENTRY Globals_ResourceTable[] = { {RTYPE_GLOBAL_RESOURCE1, testResHandleGlobalResource1}, {RTYPE_GLOBAL_RESOURCE2, testResHandleGlobalResource2} };
RM_STATIC_OBJECT_INFO Globals_StaticInfo = { 0, // TypeUID
0, // TypeFlags
"Globals", // TypeName
0, // Timeout
NULL, // pfnCreate
NULL, // pfnDelete
NULL, // verifier
sizeof(Globals_ResourceTable)/sizeof(Globals_ResourceTable[1]), Globals_ResourceTable };
RM_STATIC_OBJECT_INFO Tasks_StaticInfo = { 0, // TypeUID
0, // TypeFlags
"TEST Task", // TypeName
0, // Timeout
NULL, // pfnCreate
testTaskDelete, // pfnDelete
NULL, // LockVerifier
0, // length of resource table
NULL // Resource Table
};
RM_STATIC_OBJECT_INFO O2Tasks_StaticInfo = { 0, // TypeUID
0, // TypeFlags
"O2 Task", // TypeName
0, // Timeout
NULL, // pfnCreate
NULL, // pfnDelete NULL because it's contained in O2.
NULL, // LockVerifier
0, // length of resource table
NULL // Resource Table
};
typedef struct { RM_TASK TskHdr; int i;
} T1_TASK;
typedef struct { RM_TASK TskHdr; int i;
} T2_TASK;
typedef struct { RM_TASK TskHdr; int i;
} T3_TASK;
typedef union { RM_TASK TskHdr; T1_TASK T1; T2_TASK T2; T3_TASK T3;
} TESTTASK;
GLOBALS Globals;
RM_STATUS init_globals( PRM_STACK_RECORD psr );
VOID deinit_globals( PRM_STACK_RECORD psr );
NDIS_STATUS Task1 ( IN struct _RM_TASK * pTask, IN RM_TASK_OPERATION Op, IN UINT_PTR UserParam, // Unused
IN PRM_STACK_RECORD pSR );
NDIS_STATUS Task2 ( IN struct _RM_TASK * pTask, IN RM_TASK_OPERATION Code, IN UINT_PTR UserParam, // Unused
IN PRM_STACK_RECORD pSR );
NDIS_STATUS Task3 ( IN struct _RM_TASK * pTask, IN RM_TASK_OPERATION Code, IN UINT_PTR UserParam, // Task to pend on.
IN PRM_STACK_RECORD pSR );
NDIS_STATUS TaskO2 ( IN struct _RM_TASK * pTask, IN RM_TASK_OPERATION Op, IN UINT_PTR UserParam, // Unused
IN PRM_STACK_RECORD pSR );
NDIS_STATUS TaskUnloadO2 ( IN struct _RM_TASK * pTask, IN RM_TASK_OPERATION Op, IN UINT_PTR UserParam, // Unused
IN PRM_STACK_RECORD pSR );
NDIS_STATUS AllocateTask( IN PRM_OBJECT_HEADER pParentObject, IN PFN_RM_TASK_HANDLER pfnHandler, IN UINT Timeout, IN const char * szDescription, OUT PRM_TASK *ppTask, IN PRM_STACK_RECORD pSR ) { TESTTASK *pTTask = ALLOCSTRUCT(TESTTASK); NDIS_STATUS Status = NDIS_STATUS_RESOURCES; *ppTask = NULL;
if (pTTask != NULL) {
RmInitializeTask( &(pTTask->TskHdr), pParentObject, pfnHandler, &Tasks_StaticInfo, szDescription, Timeout, pSR ); *ppTask = &(pTTask->TskHdr); Status = NDIS_STATUS_SUCCESS; }
return Status; }
VOID FreeTask( IN PRM_TASK pTask, IN PRM_STACK_RECORD pSR ) { FREE(pTask); }
PRM_OBJECT_HEADER O1Create( PRM_OBJECT_HEADER pParentObject, PVOID pCreateParams, PRM_STACK_RECORD psr ) { O1 * po1 = ALLOCSTRUCT(O1);
if (po1) { RmInitializeLock( &po1->Lock, LOCKLEVEL_O1 );
RmInitializeHeader( pParentObject, // NULL, // pParentObject,
&po1->Hdr, 123, &po1->Lock, &O1_StaticInfo, NULL, psr );
po1->Key = (UINT) (UINT_PTR) pCreateParams; } return &po1->Hdr; }
VOID O1Delete( PRM_OBJECT_HEADER Obj, PRM_STACK_RECORD psr ) { FREE(Obj); }
PRM_OBJECT_HEADER O2Create( PRM_OBJECT_HEADER pParentObject, PVOID pCreateParams, PRM_STACK_RECORD pSR ) { O2 * po2 = ALLOCSTRUCT(O2);
if (po2) { RmInitializeLock( &po2->Lock, LOCKLEVEL_O2 );
RmInitializeHeader( pParentObject, // NULL, // pParentObject,
&po2->Hdr, 234, &po2->Lock, &O2_StaticInfo, NULL, pSR );
RmInitializeTask( &(po2->O2Task), &po2->Hdr, TaskO2, &O2Tasks_StaticInfo, "TaskO2", 0, pSR ); po2->Key = (UINT) (UINT_PTR) pCreateParams; } return &po2->Hdr; }
VOID O2Delete( PRM_OBJECT_HEADER Obj, PRM_STACK_RECORD psr ) { FREE(Obj); }
RM_STATUS testResHandleGlobalResource1( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr ) { NDIS_STATUS Status = NDIS_STATUS_FAILURE; GLOBALS *pGlobals = CONTAINING_RECORD(pObj, GLOBALS, Hdr);
ENTER("GlobalResource1", 0xd7c1efbb);
if (Op == RM_RESOURCE_OP_LOAD) { TR_INFO(("LOADING RESOUCE1\n")); pGlobals->fInited1 = TRUE; Status = NDIS_STATUS_SUCCESS;
} else if (Op == RM_RESOURCE_OP_UNLOAD) { TR_INFO(("UNLOADING RESOUCE1\n"));
//
// Were unloading this "resource."
//
ASSERTEX(pGlobals->fInited1, pGlobals); pGlobals->fInited1 = FALSE;
// Always return success on unload.
//
Status = NDIS_STATUS_SUCCESS; } else { // Unexpected op code.
//
ASSERTEX(FALSE, pObj); }
EXIT() return Status; }
RM_STATUS testResHandleGlobalResource2( PRM_OBJECT_HEADER pObj, RM_RESOURCE_OPERATION Op, PVOID pvUserParams, PRM_STACK_RECORD psr ) { NDIS_STATUS Status = NDIS_STATUS_FAILURE; GLOBALS *pGlobals = CONTAINING_RECORD(pObj, GLOBALS, Hdr);
ENTER("GlobalResource2", 0xca85474f)
if (Op == RM_RESOURCE_OP_LOAD) { TR_INFO(("LOADING RESOUCE2\n")); pGlobals->fInited2 = TRUE; Status = NDIS_STATUS_SUCCESS;
} else if (Op == RM_RESOURCE_OP_UNLOAD) { TR_INFO(("UNLOADING RESOUCE2\n"));
//
// Were unloading this "resource."
//
ASSERTEX(pGlobals->fInited2, pGlobals); pGlobals->fInited2 = FALSE;
// Always return success on unload.
//
Status = NDIS_STATUS_SUCCESS; } else { // Unexpected op code.
//
ASSERTEX(FALSE, pObj); }
EXIT() return Status; }
RM_STATUS init_globals( PRM_STACK_RECORD psr ) { NDIS_STATUS Status;
//
// Initialize the global, statically-allocated object Globals;
//
RmInitializeLock( &Globals.Lock, LOCKLEVEL_GLOBALS );
RmInitializeHeader( NULL, // pParentObject,
&Globals.Hdr, 001, &Globals.Lock, &Globals_StaticInfo, NULL, psr );
//
// Load resource1
//
Status = RmLoadGenericResource( &Globals.Hdr, RTYPE_GLOBAL_RESOURCE1, psr );
if (!FAIL(Status)) { //
// Load resource1
//
Status = RmLoadGenericResource( &Globals.Hdr, RTYPE_GLOBAL_RESOURCE2, psr ); }
return Status; }
VOID deinit_globals( PRM_STACK_RECORD psr ) { RmUnloadGenericResource( &Globals.Hdr, RTYPE_GLOBAL_RESOURCE1, psr );
RmUnloadAllGenericResources( &Globals.Hdr, psr );
RmDeallocateObject( &Globals.Hdr, psr ); }
//
// Hash comparision function.
//
BOOLEAN O1CompareKey( PVOID pKey, PRM_HASH_LINK pItem ) { O1 *pO1 = CONTAINING_RECORD(pItem, O1, Hdr.HashLink); return *((UINT*)pKey) == pO1->Key; }
//
// Hash generating function.
//
ULONG O1Hash( PVOID pKey ) { return *(UINT*)pKey; }
//
// Hash comparision function.
//
BOOLEAN O2CompareKey( PVOID pKey, PRM_HASH_LINK pItem ) { O2 *pO2 = CONTAINING_RECORD(pItem, O2, Hdr.HashLink); return *((UINT*)pKey) == pO2->Key; }
//
// Hash generating function.
//
ULONG O2Hash( PVOID pKey ) { return *(UINT*)pKey; }
VOID testTaskDelete ( PRM_OBJECT_HEADER pObj, PRM_STACK_RECORD psr ) { printf("testTaskDelete: Called to delete obj %p\n", pObj); }
NDIS_STATUS Task1( IN struct _RM_TASK * pTask, IN RM_TASK_OPERATION Code, IN UINT_PTR UserParam, // Unused
IN PRM_STACK_RECORD pSR ) //
// DONE
//
{ NDIS_STATUS Status = NDIS_STATUS_FAILURE; O1* po1 = (O1*) RM_PARENT_OBJECT(pTask); ENTER("Task1", 0x4abf3903)
switch(Code) {
case RM_TASKOP_START: printf("Task1: START called\n"); Status = NDIS_STATUS_SUCCESS; break;
case RM_TASKOP_END: printf("Task1: END called\n"); Status = (NDIS_STATUS) UserParam; break;
default: { ASSERTEX(!"Unexpected task op", pTask); } break;
} // switch (Code)
RM_ASSERT_NOLOCKS(pSR); EXIT()
return Status; }
NDIS_STATUS Task2( IN struct _RM_TASK * pTask, IN RM_TASK_OPERATION Code, IN UINT_PTR UserParam, // Unused
IN PRM_STACK_RECORD pSR ) //
// DONE
//
{ NDIS_STATUS Status = NDIS_STATUS_FAILURE; O1* po1 = (O1*) RM_PARENT_OBJECT(pTask); ENTER("Task2", 0x6e65b76c)
// Following are the list of pending states for this task.
//
enum { PEND_OnStart };
switch(Code) {
case RM_TASKOP_START: {
printf("Task2: START called\n"); RmSuspendTask(pTask, PEND_OnStart, pSR); RM_ASSERT_NOLOCKS(pSR); Status = NDIS_STATUS_PENDING;
} break;
case RM_TASKOP_PENDCOMPLETE: {
switch(RM_PEND_CODE(pTask)) { case PEND_OnStart: { printf("Task2: PEND_OnStart complete\n"); Status = (NDIS_STATUS) UserParam; // Status of the completed operation can't itself be pending!
//
ASSERT(Status != NDIS_STATUS_PENDING); } // end case PEND_OnStart
break;
default: { ASSERTEX(!"Unknown pend op", pTask); } break;
} // end switch(RM_PEND_CODE(pTask))
} // case RM_TASKOP_PENDCOMPLETE
break;
case RM_TASKOP_END: { printf("Task2: END called\n"); Status = (NDIS_STATUS) UserParam;
} break;
default: { ASSERTEX(!"Unexpected task op", pTask); } break;
} // switch (Code)
RM_ASSERT_NOLOCKS(pSR); EXIT()
return Status; }
NDIS_STATUS Task3( IN struct _RM_TASK * pTask, IN RM_TASK_OPERATION Code, IN UINT_PTR UserParam, IN PRM_STACK_RECORD pSR ) { NDIS_STATUS Status = NDIS_STATUS_FAILURE; O1* po1 = (O1*) RM_PARENT_OBJECT(pTask); T3_TASK *pT3Task = (T3_TASK *) pTask; ENTER("Task3", 0x7e89bf6d)
// Following are the list of pending states for this task.
//
enum { PEND_OnStart };
printf ("pT3Task.i = %d\n", pT3Task->i);
switch(Code) {
case RM_TASKOP_START: { PRM_TASK pOtherTask = (PRM_TASK) UserParam;
printf("Task3: START called\n"); RmPendTaskOnOtherTask(pTask, PEND_OnStart, pOtherTask, pSR); RM_ASSERT_NOLOCKS(pSR); Status = NDIS_STATUS_PENDING;
} break;
case RM_TASKOP_PENDCOMPLETE: {
switch(RM_PEND_CODE(pTask)) { case PEND_OnStart: { printf("Task3: PEND_OnStart complete\n"); Status = (NDIS_STATUS) UserParam; // Status of the completed operation can't itself be pending!
//
ASSERT(Status != NDIS_STATUS_PENDING); } // end case PEND_OnStart
break;
default: { ASSERTEX(!"Unknown pend op", pTask); } break;
} // end switch(RM_PEND_CODE(pTask))
} // case RM_TASKOP_PENDCOMPLETE
break;
case RM_TASKOP_END: { printf("Task3: END called\n"); Status = (NDIS_STATUS) UserParam;
} break;
default: { ASSERTEX(!"Unexpected task op", pTask); } break;
} // switch (Code)
RM_ASSERT_NOLOCKS(pSR); EXIT()
return Status; }
NDIS_STATUS TaskO2( IN struct _RM_TASK * pTask, IN RM_TASK_OPERATION Code, IN UINT_PTR UserParam, // Unused
IN PRM_STACK_RECORD pSR ) //
// DONE
//
{ NDIS_STATUS Status = NDIS_STATUS_FAILURE; O2* po2 = (O2*) RM_PARENT_OBJECT(pTask); ENTER("TaskO2", 0xe10fbc33)
// Following are the list of pending states for this task.
//
enum { PEND_OnStart };
ASSERT(po2 == CONTAINING_RECORD(pTask, O2, O2Task));
switch(Code) {
case RM_TASKOP_START: {
printf("TaskO2: START called\n"); RmSuspendTask(pTask, PEND_OnStart, pSR); RM_ASSERT_NOLOCKS(pSR); Status = NDIS_STATUS_PENDING;
} break;
case RM_TASKOP_PENDCOMPLETE: {
switch(RM_PEND_CODE(pTask)) { case PEND_OnStart: { printf("TaskO2: PEND_OnStart complete\n"); Status = (NDIS_STATUS) UserParam; // Status of the completed operation can't itself be pending!
//
ASSERT(Status != NDIS_STATUS_PENDING); } // end case PEND_OnStart
break;
default: { ASSERTEX(!"Unknown pend op", pTask); } break;
} // end switch(RM_PEND_CODE(pTask))
} // case RM_TASKOP_PENDCOMPLETE
break;
case RM_TASKOP_END: { printf("TaskO2: END called\n"); Status = (NDIS_STATUS) UserParam;
} break;
default: { ASSERTEX(!"Unexpected task op", pTask); } break;
} // switch (Code)
RM_ASSERT_NOLOCKS(pSR); EXIT()
return Status; }
NDIS_STATUS TaskUnloadO2( IN struct _RM_TASK * pTask, IN RM_TASK_OPERATION Code, IN UINT_PTR UserParam, // Unused
IN PRM_STACK_RECORD pSR ) //
// DONE
//
{ NDIS_STATUS Status = NDIS_STATUS_FAILURE; O2* po2 = (O2*) RM_PARENT_OBJECT(pTask); ENTER("TaskUnloadO2", 0xa15314da)
// Following are the list of pending states for this task.
//
enum { PEND_OnStart };
switch(Code) {
case RM_TASKOP_START: {
printf("TaskTaskO2: START called\n"); RmPendTaskOnOtherTask(pTask, PEND_OnStart, &po2->O2Task, pSR); RmResumeTask(&po2->O2Task, 0, pSR); RM_ASSERT_NOLOCKS(pSR); Status = NDIS_STATUS_PENDING;
} break;
case RM_TASKOP_PENDCOMPLETE: {
switch(RM_PEND_CODE(pTask)) { case PEND_OnStart: { printf("TaskUnloadO2: PEND_OnStart complete\n"); Status = (NDIS_STATUS) UserParam; // Status of the completed operation can't itself be pending!
//
ASSERT(Status != NDIS_STATUS_PENDING); } // end case PEND_OnStart
break;
default: { ASSERTEX(!"Unknown pend op", pTask); } break;
} // end switch(RM_PEND_CODE(pTask))
} // case RM_TASKOP_PENDCOMPLETE
break;
case RM_TASKOP_END: { printf("TaskUnloadO2: END called\n");
// Actually free object po2 in group.
//
RmFreeObjectInGroup( &Globals.Group, &po2->Hdr, NULL, // pTask
pSR );
Status = (NDIS_STATUS) UserParam;
} break;
default: { ASSERTEX(!"Unexpected task op", pTask); } break;
} // switch (Code)
RM_ASSERT_NOLOCKS(pSR); EXIT()
return Status; }
struct { BOOLEAN fInited; PRM_GROUP pGroup;
// Following is a dummy stack record. It needs to be initialized before
// it can be used.
//
struct { RM_LOCKING_INFO rm_lock_array[4]; RM_STACK_RECORD sr;
RM_LOCK Lock; } SrInfo;
} gDummys;
void init_dummy_vars(void) { RM_STATUS Status; O2 * po2 = NULL; O2 * po2A = NULL; PRM_TASK pTask3a=NULL; PRM_TASK pTask3b=NULL; RM_DECLARE_STACK_RECORD(sr)
printf("\nEnter init_dummy_vars\n\n");;
// Must be done before any RM apis are used.
//
RmInitializeRm();
do { UINT Key = 1234; Status = init_globals(&sr); if (FAIL(Status)) break;
gDummys.fInited = TRUE;
// Initialize the dummy stack info and the lock for it to use.
//
{ // True Init
//
gDummys.SrInfo.sr.TmpRefs = 0; gDummys.SrInfo.sr.LockInfo.CurrentLevel = 0; gDummys.SrInfo.sr.LockInfo.pFirst = rm_lock_array; gDummys.SrInfo.sr.LockInfo.pNextFree = rm_lock_array; gDummys.SrInfo.sr.LockInfo.pLast = rm_lock_array + sizeof(rm_lock_array)/sizeof(*rm_lock_array) - 1; RM_INIT_DBG_STACK_RECORD(gDummys.SrInfo.sr, 0);
// Add some bogus temp refs.
//
gDummys.SrInfo.sr.TmpRefs = 0x123;
// Now initialize the lock...
RmInitializeLock( &gDummys.SrInfo.Lock, 0x345 // locklevel.
); // And lock
// WARNING: we use the private function rmLock defined internal
// to rm.c.
//
{ VOID rmLock( PRM_LOCK pLock, #if RM_EXTRA_CHECKING
UINT uLocID, PFNLOCKVERIFIER pfnVerifier, PVOID pVerifierContext, #endif //RM_EXTRA_CHECKING
PRM_STACK_RECORD pSR );
rmLock( &gDummys.SrInfo.Lock, #if RM_EXTRA_CHECKING
0, // uLocID,
NULL, // pfnVerifier,
NULL, // pVerifierContext,
#endif //RM_EXTRA_CHECKING
&gDummys.SrInfo.sr ); } }
RmInitializeGroup( &Globals.Hdr, &O2_StaticInfo, &Globals.Group, "O1 Group", &sr );
printf("Called RmInitializeGroup\n");
Status = RM_CREATE_AND_LOCK_OBJECT_IN_GROUP( &Globals.Group, &Key, // Key
(PVOID)Key, // CreateParams
(RM_OBJECT_HEADER**) &po2, NULL, // pfCreated
&sr);
if (FAIL(Status)) { printf("Create object in group failed!\n"); po2 = NULL; } else { UINT KeyA = 2345; printf("Create 1st object in group succeeded!\n");
UNLOCKOBJ(po2, &sr);
// Now start the O2Task, which will pend ...
//
Status = RmStartTask( &po2->O2Task, 0, // UserParam (unused)
&sr ); ASSERT(PEND(Status));
RmTmpDereferenceObject(&po2->Hdr, &sr); // Added in lookup.
Status = RM_CREATE_AND_LOCK_OBJECT_IN_GROUP( &Globals.Group, &KeyA, // Key
(PVOID)KeyA, // CreateParams
(RM_OBJECT_HEADER**) &po2A, NULL, // pfCreated
&sr);
if (FAIL(Status)) { printf("Create 2nd object in group failed!\n"); po2A = NULL; } else { printf("Create 2nd object in group succeeded!\n");
UNLOCKOBJ(po2A, &sr);
// Now start the O2Task, which will pend ...
//
Status = RmStartTask( &po2A->O2Task, 0, // UserParam (unused)
&sr ); ASSERT(PEND(Status));
RmTmpDereferenceObject(&po2A->Hdr, &sr); }
}
//
// Now let's start a couple of T3 tasks, to both pend on
// &po2->O2Task.
//
if (po2 != NULL) {
Status = AllocateTask( &po2->Hdr, // pParentObject
Task3, // pfnHandler
0, // Timeout
"Task3a", &pTask3a, &sr ); if (FAIL(Status)) { pTask3a = NULL; } else { Status = RmStartTask( pTask3a, (UINT_PTR) &po2->O2Task, // UserParam
&sr ); ASSERT(Status == NDIS_STATUS_PENDING); }
Status = AllocateTask( &po2->Hdr, // pParentObject
Task3, // pfnHandler
0, // Timeout
"Task3b", &pTask3b, &sr ); if (FAIL(Status)) { pTask3b = NULL; } else {
Status = RmStartTask( pTask3b, (UINT_PTR) &po2->O2Task, // UserParam
&sr ); ASSERT(Status == NDIS_STATUS_PENDING); }
// Add some log entries.
//
RmDbgLogToObject( &po2->Hdr, NULL, // szPrefix
"How now brown cow: pO2=%p, szDesc=%s\n", (UINT_PTR) po2, (UINT_PTR) po2->Hdr.szDescription, 0, 0, NULL, NULL );
RM_ASSERT_NOLOCKS(&sr);
}
printf( "DUMMY: pGroup=0x%p; po2=0x%p; po2A=0x%p\n", &Globals.Group, po2, po2A ); if (po2 && po2A) { printf( "DUMMY: po2->pTask=0x%p; po2A->pTask=0x%p\n", &po2->O2Task, &po2A->O2Task ); printf( "DUMMY: pTask3a=0x%p; pTask3b=0x%p; pSR=0x%p\n", pTask3a, pTask3b, &gDummys.SrInfo.sr ); }
gDummys.pGroup = &Globals.Group;
} while(FALSE);
RM_ASSERT_CLEAR(&sr);
printf("\nLeaving init_dummy_vars\n\n");; }
void delete_dummy_vars(void) { RM_STATUS Status; O1 * po1; RM_DECLARE_STACK_RECORD(sr)
printf("\nEnter delete_dummy_vars\n\n");;
do { if (!gDummys.fInited) break;
RmUnloadAllObjectsInGroup( gDummys.pGroup, AllocateTask, TaskUnloadO2, NULL, NULL, // pTask
0, // uTaskPendCode
&sr ); RmDeinitializeGroup( gDummys.pGroup, &sr );
deinit_globals(&sr);
} while(FALSE);
// Must be done after all RM apis are complete.
//
RmDeinitializeRm();
RM_ASSERT_CLEAR(&sr);
printf("\nLeaving delete_dummy_vars\n"); }
VOID NdisInitializeWorkItem( IN PNDIS_WORK_ITEM pWorkItem, IN NDIS_PROC Routine, IN PVOID Context ) { ZeroMemory(pWorkItem, sizeof(*pWorkItem)); pWorkItem->Context = Context; pWorkItem->Routine = Routine; }
VOID ApcProc_ScheduleWorkItem( ULONG_PTR Param ) { PNDIS_WORK_ITEM pWI = (PNDIS_WORK_ITEM) Param;
pWI->Routine(pWI, pWI->Context); }
NDIS_STATUS NdisScheduleWorkItem( IN PNDIS_WORK_ITEM WorkItem ) { DWORD dwRet = QueueUserAPC( ApcProc_ScheduleWorkItem, GetCurrentThread(), (UINT_PTR) WorkItem ); return dwRet ? NDIS_STATUS_SUCCESS: NDIS_STATUS_FAILURE; }
VOID NdisInitializeTimer( IN OUT PNDIS_TIMER pTimer, IN PNDIS_TIMER_FUNCTION TimerFunction, IN PVOID FunctionContext ) { ZeroMemory(pTimer, sizeof(*pTimer)); pTimer->hTimer = CreateWaitableTimer( NULL, // lpTimerAttributes
TRUE, // bManualReset
NULL //lpTimerName
); ASSERT(pTimer->hTimer != NULL); pTimer->pfnHandler = TimerFunction; pTimer->Context = FunctionContext; }
VOID CALLBACK TimerAPCProc_NdisSetTimer( LPVOID lpArgToCompletionRoutine, // data value
DWORD dwTimerLowValue, // timer low value
DWORD dwTimerHighValue // timer high value
) { PNDIS_TIMER pTimer = (PNDIS_TIMER) lpArgToCompletionRoutine;
pTimer->pfnHandler( NULL, // SystemSpecific1
pTimer->Context, // FunctionContext
NULL, // SystemSpecific2
NULL // SystemSpecific3
); }
VOID NdisSetTimer( IN PNDIS_TIMER pTimer, IN UINT MillisecondsToDelay ) { BOOL fRet; LARGE_INTEGER DueTime;
DueTime.QuadPart = Int32x32To64( (INT) MillisecondsToDelay, -10000 // convert to 100-nanosec, specify relative time
);
fRet = SetWaitableTimer( pTimer->hTimer, // handle to a timer object
&DueTime, // when timer will become signaled
0, // periodic timer interval
TimerAPCProc_NdisSetTimer, // completion routine
pTimer, // data for completion routine
FALSE // flag for resume state
); ASSERT(fRet); }
VOID NdisCancelTimer( IN PNDIS_TIMER Timer, OUT PBOOLEAN TimerCancelled ) { ASSERT(FALSE); }
#endif // TESTPROGRAM
|