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.
502 lines
9.4 KiB
502 lines
9.4 KiB
/***************************************************************************
|
|
|
|
Copyright (c) 2002 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
locklist.H
|
|
|
|
Abstract:
|
|
|
|
Private interface for Smartcard Driver Utility Library
|
|
|
|
Environment:
|
|
|
|
Kernel Mode Only
|
|
|
|
Notes:
|
|
|
|
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
|
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
|
|
PURPOSE.
|
|
|
|
Copyright (c) 2001 Microsoft Corporation. All Rights Reserved.
|
|
|
|
|
|
Revision History:
|
|
|
|
05/14/2002 : created
|
|
|
|
Authors:
|
|
|
|
Randy Aull
|
|
|
|
|
|
****************************************************************************/
|
|
|
|
#include "pch.h"
|
|
#include "irplist.h"
|
|
|
|
void
|
|
LockedList_Init(
|
|
PLOCKED_LIST LockedList,
|
|
PKSPIN_LOCK ListLock
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initializes a LOCKED_LIST structure
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to a LOCKED_LIST structure
|
|
|
|
ListLock - Pointer to a SPIN_LOCK for the locked list
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
--*/
|
|
{
|
|
InitializeListHead(&LockedList->ListHead);
|
|
KeInitializeSpinLock(&LockedList->SpinLock);
|
|
LockedList->ListLock = ListLock;
|
|
LockedList->Count = 0;
|
|
}
|
|
|
|
void
|
|
LockedList_EnqueueHead(
|
|
PLOCKED_LIST LockedList,
|
|
PLIST_ENTRY ListEntry
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enqueue a List entry at the head of the locked list.
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to a LOCKED_LIST structure
|
|
|
|
ListEntry - Pointer to a LIST_ENTRY structure
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
--*/
|
|
{
|
|
KIRQL irql;
|
|
|
|
LL_LOCK(LockedList, &irql);
|
|
InsertHeadList(&LockedList->ListHead, ListEntry);
|
|
LockedList->Count++;
|
|
LL_UNLOCK(LockedList, irql) ;
|
|
}
|
|
|
|
void
|
|
LockedList_EnqueueTail(
|
|
PLOCKED_LIST LockedList,
|
|
PLIST_ENTRY ListEntry
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enqueue a List entry at the tail of the locked list.
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to a LOCKED_LIST structure
|
|
|
|
ListEntry - Pointer to a LIST_ENTRY structure
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
--*/
|
|
{
|
|
KIRQL irql;
|
|
|
|
LL_LOCK(LockedList, &irql);
|
|
|
|
InsertTailList(&LockedList->ListHead, ListEntry);
|
|
LockedList->Count++;
|
|
LL_UNLOCK(LockedList, irql) ;
|
|
}
|
|
|
|
void
|
|
LockedList_EnqueueAfter(
|
|
PLOCKED_LIST LockedList,
|
|
PLIST_ENTRY Entry,
|
|
PLIST_ENTRY Location
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Enqueue a List entry at a specific point in the LockedList.
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to a LOCKED_LIST structure
|
|
|
|
Entry - Pointer to a LIST_ENTRY structure
|
|
|
|
Location - Pointer to a LIST_ENTRY already contained in the LockedList
|
|
|
|
Return Value:
|
|
|
|
VOID
|
|
|
|
Notes:
|
|
|
|
It the Location is NULL, the entry is added to the tail of the list
|
|
|
|
--*/
|
|
{
|
|
if (Location == NULL) {
|
|
LL_ADD_TAIL(LockedList, Entry);
|
|
}
|
|
else {
|
|
Entry->Flink = Location->Flink;
|
|
Location->Flink->Blink = Entry;
|
|
|
|
Location->Flink = Entry;
|
|
Entry->Blink = Location;
|
|
|
|
LockedList->Count++;
|
|
}
|
|
}
|
|
|
|
PLIST_ENTRY
|
|
LockedList_RemoveHead(
|
|
PLOCKED_LIST LockedList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Remove the head LIST_ENTRY from a LockedList.
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to a LOCKED_LIST structure
|
|
|
|
Return Value:
|
|
|
|
PLIST_ENTRY - Pointer to the head list of the Locked List
|
|
|
|
NULL - if the Locked List is empty
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY ple;
|
|
KIRQL irql;
|
|
|
|
ple = NULL;
|
|
|
|
LL_LOCK(LockedList, &irql);
|
|
|
|
if (!IsListEmpty(&LockedList->ListHead)) {
|
|
ple = RemoveHeadList(&LockedList->ListHead);
|
|
LockedList->Count--;
|
|
}
|
|
|
|
LL_UNLOCK(LockedList, irql);
|
|
|
|
return ple;
|
|
}
|
|
|
|
PLIST_ENTRY
|
|
LockedList_RemoveEntryLocked(
|
|
PLOCKED_LIST LockedList,
|
|
PLIST_ENTRY Entry)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Remove a specific entry from the LockedList. Assumes that the caller has
|
|
acquired the spinlock
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to a LOCKED_LIST structure
|
|
|
|
Entry - Pointer to a LIST_ENTRY structure
|
|
|
|
|
|
Return Value:
|
|
|
|
PLIST_ENTRY - Pointer to the Entry.
|
|
|
|
--*/
|
|
{
|
|
|
|
ASSERT(!IsListEmpty(&LockedList->ListHead));
|
|
ASSERT(LockedList->Count > 0);
|
|
|
|
RemoveEntryList(Entry);
|
|
LockedList->Count--;
|
|
|
|
return Entry;
|
|
}
|
|
|
|
PLIST_ENTRY
|
|
LockedList_RemoveEntry(
|
|
PLOCKED_LIST LockedList,
|
|
PLIST_ENTRY Entry
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Remove a specific entry from the LockedList
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to a LOCKED_LIST structure
|
|
|
|
Entry - Pointer to a LIST_ENTRY structure
|
|
|
|
|
|
Return Value:
|
|
|
|
PLIST_ENTRY - Pointer to the Entry.
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY ple;
|
|
KIRQL irql;
|
|
|
|
LL_LOCK(LockedList, &irql);
|
|
ple = LockedList_RemoveEntryLocked(LockedList, Entry);
|
|
LL_UNLOCK(LockedList, irql);
|
|
|
|
return ple;
|
|
}
|
|
|
|
LONG
|
|
LockedList_GetCount(
|
|
PLOCKED_LIST LockedList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Obtains the number of Entries in the LockedList
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to a LOCKED_LIST structure
|
|
|
|
|
|
Return Value:
|
|
|
|
LONG - Number of elements in the LockedList
|
|
|
|
--*/
|
|
{
|
|
LONG count;
|
|
KIRQL irql;
|
|
|
|
LL_LOCK(LockedList, &irql);
|
|
count = LockedList->Count;
|
|
LL_UNLOCK(LockedList, irql) ;
|
|
|
|
return count;
|
|
}
|
|
|
|
LONG
|
|
LockedList_Drain(
|
|
PLOCKED_LIST LockedList,
|
|
PLIST_ENTRY DrainListHead
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Drains the elements from the LockedList into the DrainListHead and
|
|
returns the number of elements
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to a LOCKED_LIST structure
|
|
|
|
DrainListHead - Pointer to a LIST_ENTRY
|
|
|
|
|
|
Return Value:
|
|
|
|
LONG - Number of elements drained from LockedList into the DrainListHead
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY ple;
|
|
LONG count;
|
|
KIRQL irql;
|
|
|
|
count = 0;
|
|
|
|
InitializeListHead(DrainListHead);
|
|
|
|
LL_LOCK(LockedList, &irql);
|
|
|
|
while (!IsListEmpty(&LockedList->ListHead)) {
|
|
ple = RemoveHeadList(&LockedList->ListHead);
|
|
LockedList->Count--;
|
|
|
|
InsertTailList(DrainListHead, ple);
|
|
count++;
|
|
}
|
|
|
|
ASSERT(LockedList->Count == 0);
|
|
ASSERT(IsListEmpty(&LockedList->ListHead));
|
|
|
|
LL_UNLOCK(LockedList, irql) ;
|
|
|
|
return count;
|
|
}
|
|
|
|
BOOLEAN
|
|
List_Process(
|
|
PLIST_ENTRY ListHead,
|
|
PFNLOCKED_LIST_PROCESS Process,
|
|
PVOID ProcessContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Iterate over the list, call the process function for each element.
|
|
|
|
Arguments:
|
|
|
|
ListHead - Pointer to a LIST_ENTRY
|
|
|
|
Process - Callback function for each element in the list. If the callback
|
|
returns FALSE we break out of the iteration.
|
|
|
|
ProcessContext - Context for the callback, supplied by the caller
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE - Walked over the entire list
|
|
FALSE - Process function returned FALSE and stopped iteration
|
|
|
|
--*/
|
|
{
|
|
PLIST_ENTRY ple;
|
|
BOOLEAN result;
|
|
|
|
//
|
|
// We return if we iterated over the entire list.
|
|
//
|
|
result = TRUE;
|
|
|
|
for (ple = ListHead->Flink; ple != ListHead; ple = ple->Flink) {
|
|
//
|
|
// If the Process callback wants to stop iterating over the list, then
|
|
// it will return FALSE.
|
|
//
|
|
result = Process(ProcessContext, ple);
|
|
if (result == FALSE) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
BOOLEAN
|
|
LockedList_ProcessLocked(
|
|
PLOCKED_LIST LockedList,
|
|
PFNLOCKED_LIST_PROCESS Process,
|
|
PVOID ProcessContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Iterate over the list, call the process function for each element. Assumes
|
|
the LockedList spinlock is acquired by the caller
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to the LOCKED_LIST
|
|
|
|
Process - Callback function for each element in the list. If the callback
|
|
returns FALSE we break out of the iteration.
|
|
|
|
ProcessContext - Context for the callback, supplied by the caller
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE - Walked over the entire list
|
|
FALSE - Process function returned FALSE and stopped iteration
|
|
|
|
--*/
|
|
{
|
|
return List_Process(&LockedList->ListHead, Process, ProcessContext);
|
|
}
|
|
|
|
BOOLEAN
|
|
LockedList_Process(
|
|
PLOCKED_LIST LockedList,
|
|
BOOLEAN LockAtPassive,
|
|
PFNLOCKED_LIST_PROCESS Process,
|
|
PVOID ProcessContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Iterate over the list, call the process function for each element.
|
|
|
|
Arguments:
|
|
|
|
LockedList - Pointer to the LOCKED_LIST
|
|
|
|
LockAtPassive - If
|
|
|
|
Process - Callback function for each element in the list. If the callback
|
|
returns FALSE we break out of the iteration.
|
|
|
|
ProcessContext - Context for the callback, supplied by the caller
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE - Walked over the entire list
|
|
FALSE - Process function returned FALSE and stopped iteration
|
|
|
|
--*/
|
|
{
|
|
KIRQL irql;
|
|
BOOLEAN result;
|
|
|
|
if (LockAtPassive) {
|
|
LL_LOCK(LockedList, &irql);
|
|
}
|
|
else {
|
|
LL_LOCK_AT_DPC(LockedList);
|
|
}
|
|
|
|
result = List_Process(&LockedList->ListHead, Process, ProcessContext);
|
|
|
|
if (LockAtPassive) {
|
|
LL_UNLOCK(LockedList, irql);
|
|
}
|
|
else {
|
|
LL_UNLOCK_FROM_DPC(LockedList);
|
|
}
|
|
|
|
return result;
|
|
}
|