Windows2003-3790/drivers/smartcrd/scutil/locklist.c
2020-09-30 16:53:55 +02:00

503 lines
9.4 KiB
C

/***************************************************************************
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;
}