windows-nt/Source/XPSP1/NT/net/1394/arp/kdext/t.c
2020-09-26 16:20:57 +08:00

1595 lines
24 KiB
C

/*++
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