PDC.H

/*++ 

Copyright 1992 - 1998 Microsoft Corporation

Module Name:

pdc.h

Abstract:

This is the main source file for the Windows/NT PDC API demonstration
program. This include file defines macros, data structures and procedure
prototypes for the code contained in the PDC.C source file.

--*/

//
// Include file for using the Win32 API
//

#include <windows.h>

//
// C Runtime include files used by the program.
//

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <malloc.h>
#include <sys\types.h>
#include <sys\stat.h>


//
// Macro definitions
//

//
// Useful rounding macros that the rounding amount is always a
// power of two.
//

#define ROUND_DOWN( Size, Amount ) ((DWORD)(Size) & ~((Amount) - 1))
#define ROUND_UP( Size, Amount ) (((DWORD)(Size) + ((Amount) - 1)) & ~((Amount) - 1))

//
// Pseudo keywords for documentation purposes.
//

#define IN
#define OUT
#define OPTIONAL

//
// Determine if an argument is present by testing a value of NULL
//

#define ARGUMENT_PRESENT( ArgumentPointer ) (\
(LPSTR)(ArgumentPointer) != (LPSTR)(NULL) )



//
// Calculate the address of the base of the structure given its type, and an
// address of a field within the structure.
//

#define CONTAINING_RECORD( address, type, field ) ((type *)( \
(PCHAR)(address) - \
(PCHAR)(&((type *)0)->field)))


//
// Virtual Buffer data structure and function prototypes.
//

typedef struct _VIRTUAL_BUFFER {
LPVOID Base;
ULONG PageSize;
LPVOID CommitLimit;
LPVOID ReserveLimit;
} VIRTUAL_BUFFER, *PVIRTUAL_BUFFER;

BOOL
CreateVirtualBuffer(
OUT PVIRTUAL_BUFFER Buffer,
IN DWORD CommitSize,
IN DWORD ReserveSize OPTIONAL
);

BOOL
ExtendVirtualBuffer(
IN PVIRTUAL_BUFFER Buffer,
IN LPVOID Address
);

BOOL
TrimVirtualBuffer(
IN PVIRTUAL_BUFFER Buffer
);

BOOL
FreeVirtualBuffer(
IN PVIRTUAL_BUFFER Buffer
);

int
VirtualBufferExceptionFilter(
IN DWORD ExceptionCode,
IN PEXCEPTION_POINTERS ExceptionInfo,
IN OUT PVIRTUAL_BUFFER Buffer
);


//
// Directory enumeration and file notification definitions.
//

typedef
VOID (*PDIRECTORY_ENUMERATE_ROUTINE)(
LPSTR Path,
PWIN32_FIND_DATA FindFileData,
PVOID EnumerateParameter
);

BOOL
EnumerateDirectoryTree(
LPSTR DirectoryPath,
PDIRECTORY_ENUMERATE_ROUTINE EnumerateRoutine,
PVOID EnumerateParameter
);

//
// Data structures private to the EnumerateDirectoryTree function.
//

typedef struct _ENUMERATE_DIRECTORY_STACK {
LPSTR PathEnd;
HANDLE FindHandle;
} ENUMERATE_DIRECTORY_STACK, *PENUMERATE_DIRECTORY_STACK;

#define MAX_DEPTH 256

typedef struct _ENUMERATE_DIRECTORY_STATE {
DWORD Depth;
ENUMERATE_DIRECTORY_STACK Stack[ MAX_DEPTH ];
CHAR Path[ MAX_PATH ];
} ENUMERATE_DIRECTORY_STATE, *PENUMERATE_DIRECTORY_STATE;



//
// Doubly-linked list manipulation routines. Implemented as macros
// but logically these are procedures.
//

//
// VOID
// InitializeListHead(
// PLIST_ENTRY ListHead
// );
//

#define InitializeListHead(ListHead) (\
(ListHead)->Flink = (ListHead)->Blink = (ListHead) )

//
// BOOLEAN
// IsListEmpty(
// PLIST_ENTRY ListHead
// );
//

#define IsListEmpty(ListHead) (\
( ((ListHead)->Flink == (ListHead)) ? TRUE : FALSE ) )

//
// PLIST_ENTRY
// RemoveHeadList(
// PLIST_ENTRY ListHead
// );
//

#define RemoveHeadList(ListHead) \
(ListHead)->Flink;\
{\
PLIST_ENTRY FirstEntry;\
FirstEntry = (ListHead)->Flink;\
FirstEntry->Flink->Blink = (ListHead);\
(ListHead)->Flink = FirstEntry->Flink;\
}

//
// VOID
// RemoveEntryList(
// PLIST_ENTRY Entry
// );
//

#define RemoveEntryList(Entry) {\
PLIST_ENTRY _EX_Entry;\
_EX_Entry = (Entry);\
_EX_Entry->Blink->Flink = _EX_Entry->Flink;\
_EX_Entry->Flink->Blink = _EX_Entry->Blink;\
}

//
// VOID
// InsertTailList(
// PLIST_ENTRY ListHead,
// PLIST_ENTRY Entry
// );
//

#define InsertTailList(ListHead,Entry) \
(Entry)->Flink = (ListHead);\
(Entry)->Blink = (ListHead)->Blink;\
(ListHead)->Blink->Flink = (Entry);\
(ListHead)->Blink = (Entry)

//
// VOID
// InsertHeadList(
// PLIST_ENTRY ListHead,
// PLIST_ENTRY Entry
// );
//

#define InsertHeadList(ListHead,Entry) \
(Entry)->Flink = (ListHead)->Flink;\
(Entry)->Blink = (ListHead);\
(ListHead)->Flink->Blink = (Entry);\
(ListHead)->Flink = (Entry)



//
// Worker thread definitions
//

typedef
VOID
(*PWORKER_ROUTINE)(
// IN PWORK_QUEUE_ITEM WorkItem
);

typedef struct _WORK_QUEUE {
CRITICAL_SECTION CriticalSection;
HANDLE Semaphore;
LIST_ENTRY Queue;
BOOL Terminating;
PWORKER_ROUTINE WorkerRoutine;
DWORD NumberOfWorkerThreads;
HANDLE WorkerThreads[ 1 ]; // Variable length array
} WORK_QUEUE, *PWORK_QUEUE;

typedef struct _WORK_QUEUE_ITEM {
LIST_ENTRY List;
DWORD Reason;
PWORK_QUEUE WorkQueue;
} WORK_QUEUE_ITEM, *PWORK_QUEUE_ITEM;

#define WORK_INITIALIZE_ITEM 0
#define WORK_ITEM 1
#define WORK_TERMINATE_ITEM 2

DWORD
WorkerThread(
LPVOID lpThreadParameter
);

PWORK_QUEUE
CreateWorkQueue(
IN DWORD NumberOfWorkerThreads,
IN PWORKER_ROUTINE WorkerRoutine
);

BOOL
QueueWorkItem(
IN OUT PWORK_QUEUE WorkQueue,
IN PWORK_QUEUE_ITEM WorkItem
);

VOID
DestroyWorkQueue(
IN OUT PWORK_QUEUE WorkQueue
);


//
// Main procedure prototypes
//

BOOL
ProcessCommandLineArguments(
int argc,
char *argv[]
);

VOID
QueueSearchFile(
LPSTR Path,
PWIN32_FIND_DATA FindFileData,
PVOID EnumerateParameter
);

typedef struct _SEARCH_REQUEST_STATE {
VIRTUAL_BUFFER Buffer;
LPSTR CurrentOutput;
} SEARCH_REQUEST_STATE, *PSEARCH_REQUEST_STATE;


typedef struct _SEARCH_REQUEST {
WORK_QUEUE_ITEM WorkItem;
DWORD FileSize;
LPSTR FileData;
HANDLE File;
OVERLAPPED OverlappedIO;
CHAR FullPathName[ 1 ]; // Variable length array
} SEARCH_REQUEST, *PSEARCH_REQUEST;


VOID
ProcessRequest(
IN PWORK_QUEUE_ITEM WorkItem
);

VOID
ProcessReadFileCompletion(
DWORD dwErrorCode,
DWORD dwNumberOfBytesTransfered,
LPOVERLAPPED lpOverlapped
);

VOID
ProcessSearchFile(
IN PSEARCH_REQUEST WorkerRequest,
IN PSEARCH_REQUEST_STATE State
);


//
// Global variables
//

DWORD TlsIndex;
INT NumberOfWorkerThreads;
BOOL Verbose;
BOOL IgnoreCase;
BOOL MappedFileIO;
BOOL ASyncIO;
BOOL SyncIO;
LPSTR DirectoryPath;
LPSTR SearchString;
DWORD SearchStringLength;
DWORD SearchedFileCount;
DWORD MatchedFileCount;
DWORD MatchedLineCount;
LONG OutstandingIOOperations;
HANDLE IoCompletedEvent;

typedef
int
(_CRTAPI1 *PCOMPARE_ROUTINE)(
IN const char *,
IN const char *,
IN size_t
);

PCOMPARE_ROUTINE SearchFunction;