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.
 
 
 
 
 
 

443 lines
10 KiB

//
// connlist.c
//
// Handles a linked list which will keep track of all the TCLIENT2 handles.
//
// Why is this needed?
//
// I am using SetTimer() callbacks to keep track of idled scripts.
// The problem is, there is no way for me to tell exactly which
// handle executed which timer. The only way to do this is to keep
// a list of all the handles, and their associated timer id.
//
// Copyright (C) 2001 Microsoft Corporation
//
// Author: a-devjen (Devin Jenson)
//
// 03-08-2001 - Fixed bug regarding last node on list not being cleaned.
#include "connlist.h"
// Linked handle list
typedef struct _ConnList
{
struct _ConnList *Next;
struct _ConnList *Prev;
HANDLE Handle;
UINT_PTR TimerId;
DWORD msStartTime;
} ConnList;
// This is the global variable, representing the head of the list
ConnList *Head = NULL;
// This queue is used to prevent two threads from messing
// with the list at the same time
CRITICAL_SECTION ListQueue;
// Indicates the number of items in the list
DWORD ItemCount;
DWORD AccessCount;
// Internal function prototypes
void T2ConnList_EnterQueue(void);
void T2ConnList_LeaveQueue(void);
// T2ConnList_EnterQueue
//
// A "safe" critical section - no critical section needed.
//
// No return value.
void T2ConnList_EnterQueue(void)
{
if (ItemCount == 0 && AccessCount == 0)
InitializeCriticalSection(&ListQueue);
++AccessCount;
EnterCriticalSection(&ListQueue);
}
// T2ConnList_LeaveQueue
//
// A "safe" critical section - critical section automatically
// deletes itself when no longer needed.
//
// No return value.
void T2ConnList_LeaveQueue(void)
{
LeaveCriticalSection(&ListQueue);
--AccessCount;
if (ItemCount == 0 && AccessCount == 0)
DeleteCriticalSection(&ListQueue);
}
// T2ConnList_AddHandle
//
// Adds a new handle to the connection list. Additionally
// this will also set the TimerId and msStartTime properties
// for the new entry.
//
// Returns TRUE if the handle was successfully added.
// FALSE otherwise.
BOOL T2ConnList_AddHandle(HANDLE Handle, UINT_PTR TimerId, DWORD msStartTime)
{
ConnList *Node;
// Sanity check
if (Handle == NULL || Handle == INVALID_HANDLE_VALUE)
return FALSE;
// Get access to the list
T2ConnList_EnterQueue();
Node = Head;
// Loop through each item, ensuring the item does not already exist
for (; Node != NULL && Node->Handle != Handle; Node = Node->Next);
// If we didn't reach the end of the list, it already exists
if (Node != NULL) {
// Simply modify the parameters instead of adding it
Node->TimerId = TimerId;
Node->msStartTime = msStartTime;
// Release access from the list
T2ConnList_LeaveQueue();
return TRUE;
}
// It doesn't exist, allocate a new node for the handle
Node = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (ConnList));
if (Node == NULL) {
// Allocation failed, release access from the list
T2ConnList_LeaveQueue();
return FALSE;
}
// Begin adding it to the list by setting the new node at the head
if (Head != NULL)
Head->Prev = Node;
Node->Next = Head;
Head = Node;
// Record the parameters
Node->Handle = Handle;
Node->TimerId = TimerId;
Node->msStartTime = msStartTime;
// Increment the number of handles in the list
++ItemCount;
// Release access from the list and return
T2ConnList_LeaveQueue();
return TRUE;
}
// T2ConnList_RemoveHandle
//
// Removes a handle from the list if it exists.
//
// No return value.
void T2ConnList_RemoveHandle(HANDLE Handle)
{
ConnList *Node;
// Sanity check
if (Handle == NULL || Handle == INVALID_HANDLE_VALUE)
return;
// Gain access to the list
T2ConnList_EnterQueue();
Node = Head;
// First find the handle in the list
for (; Node != NULL && Node->Handle != Handle; Node = Node->Next);
// If the Node pointer is NULL, then the handle didn't exist
if (Node == NULL) {
// Just release access from the list, and return
T2ConnList_LeaveQueue();
return;
}
// Handle found, now unlink it from the list
if (Node->Next != NULL)
Node->Next->Prev = Node->Prev;
if (Node->Prev != NULL)
Node->Prev->Next = Node->Next;
// Costin and Hammad's Fix!! Yay!!
if (Node == Head)
Head = Node->Next;
// Free the handle itself
HeapFree(GetProcessHeap(), 0, Node);
// Decrement the handle count in the list
--ItemCount;
// Release access from the list
T2ConnList_LeaveQueue();
}
// T2ConnList_GetData
//
// Gets any non-null pointer parameters for the specified
// handle from the list.
//
// Returns TRUE if the handle was found, FALSE otherwise.
BOOL T2ConnList_GetData(HANDLE Handle, UINT_PTR *TimerId, DWORD *msStartTime)
{
ConnList *Node;
// Gain access to the list
T2ConnList_EnterQueue();
Node = Head;
// First find the handle in the list
for (; Node != NULL && Node->Handle != Handle; Node = Node->Next);
// If the Node pointer is NULL, then the handle didn't exist
if (Node == NULL) {
// Just release access from the list, and return an error
T2ConnList_LeaveQueue();
return FALSE;
}
// Simply enter in the parameters
if (TimerId != NULL)
*TimerId = Node->TimerId;
if (msStartTime != NULL)
*msStartTime = Node->msStartTime;
// Release access from the list, and return success
T2ConnList_LeaveQueue();
return TRUE;
}
// T2ConnList_SetData
//
// Sets/changes all of the handle's parameters.
//
// Returns TRUE if the handle was found, FALSE otherwise.
BOOL T2ConnList_SetData(HANDLE Handle, UINT_PTR TimerId, DWORD msStartTime)
{
ConnList *Node;
// Gain access to the list
T2ConnList_EnterQueue();
Node = Head;
// First find the handle in the list
for (; Node != NULL && Node->Handle != Handle; Node = Node->Next);
// If the Node pointer is NULL, then the handle didn't exist
if (Node == NULL) {
// Just release access from the list, and return an error
T2ConnList_LeaveQueue();
return FALSE;
}
// Change the parameters
Node->TimerId = TimerId;
Node->msStartTime = msStartTime;
// Release access from the list, and return success
T2ConnList_LeaveQueue();
return TRUE;
}
// T2ConnList_SetTimerId
//
// Sets the timer id parameter of the specified handle.
//
// Returns TRUE on success and FALSE on failure.
BOOL T2ConnList_SetTimerId(HANDLE Handle, UINT_PTR TimerId)
{
ConnList *Node;
// Gain access to the list
T2ConnList_EnterQueue();
Node = Head;
// First find the handle in the list
for (; Node != NULL && Node->Handle != Handle; Node = Node->Next);
// If the Node pointer is NULL, then the handle didn't exist
if (Node == NULL) {
// Just release access from the list, and return an error
T2ConnList_LeaveQueue();
return FALSE;
}
// Change it
Node->TimerId = TimerId;
// Release access from the list, and return success
T2ConnList_LeaveQueue();
return TRUE;
}
// T2ConnList_SetStartTime
//
// Sets the start time parameter of the specified handle.
//
// Returns TRUE on success and FALSE on failure.
BOOL T2ConnList_SetStartTime(HANDLE Handle, DWORD msStartTime)
{
ConnList *Node;
// Gain access to the list
T2ConnList_EnterQueue();
Node = Head;
// First find the handle in the list
for (; Node != NULL && Node->Handle != Handle; Node = Node->Next);
// If the Node pointer is NULL, then the handle didn't exist
if (Node == NULL) {
// Just release access from the list, and return an error
T2ConnList_LeaveQueue();
return FALSE;
}
// Change it
Node->msStartTime = msStartTime;
// Release access from the list, and return success
T2ConnList_LeaveQueue();
return TRUE;
}
// T2ConnList_FindHandleByTimerId
//
// Finds the first handle with the specified matching timer id.
//
// Returns the handle on success, or NULL if a handle
// with the specified timer id did not existed.
HANDLE T2ConnList_FindHandleByTimerId(UINT_PTR TimerId)
{
HANDLE Handle;
ConnList *Node;
// Gain access to the list
T2ConnList_EnterQueue();
Node = Head;
// Find the first matching timer in the list
for (; Node != NULL && Node->TimerId != TimerId; Node = Node->Next);
// If the Node pointer is NULL, then a handle didn't exist
if (Node == NULL) {
// Just release access from the list, and return an error
T2ConnList_LeaveQueue();
return NULL;
}
// Found a handle, record it
Handle = Node->Handle;
// Release access from the list and return our found handle
T2ConnList_LeaveQueue();
return Handle;
}
// T2ConnList_FindHandleByStartTime
//
// Finds the first handle with the specified matching start time.
//
// Returns the handle on success, or NULL if a handle
// with the specified start time did not exist.
HANDLE T2ConnList_FindHandleByStartTime(DWORD msStartTime)
{
HANDLE Handle;
ConnList *Node;
// Gain access to the list
T2ConnList_EnterQueue();
Node = Head;
// Find the first matching start time in the list
for (; Node != NULL && Node->msStartTime != msStartTime;
Node = Node->Next);
// If the Node pointer is NULL, then a handle didn't exist
if (Node == NULL) {
// Just release access from the list, and return an error
T2ConnList_LeaveQueue();
return NULL;
}
// Found a handle, record it
Handle = Node->Handle;
// Release access from the list and return our found handle
T2ConnList_LeaveQueue();
return Handle;
}