/**
 * @file winnt4.h
 * Copyright 2012, 2013 MinGW.org project
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
/* Created by Casper S. Hornstrup <chorns@users.sourceforge.net> */
#ifndef __WINNT4_H
#define __WINNT4_H
#pragma GCC system_header
#include <_mingw.h>

/*
 * Definitions only used in Windows NT 4.0 and earlier versions
 */

#ifdef __cplusplus
extern "C" {
#endif

typedef struct _ZONE_SEGMENT_HEADER {
  SINGLE_LIST_ENTRY  SegmentList;
  PVOID  Reserved;
} ZONE_SEGMENT_HEADER, *PZONE_SEGMENT_HEADER;

typedef struct _ZONE_HEADER {
  SINGLE_LIST_ENTRY  FreeList;
  SINGLE_LIST_ENTRY  SegmentList;
  ULONG  BlockSize;
  ULONG  TotalSegmentSize;
} ZONE_HEADER, *PZONE_HEADER;

static __inline PVOID
ExAllocateFromZone(
  /*IN*/ PZONE_HEADER  Zone)
{
  if (Zone->FreeList.Next)
    Zone->FreeList.Next = Zone->FreeList.Next->Next;
  return (PVOID) Zone->FreeList.Next;
}

NTOSAPI
NTSTATUS
DDKAPI
ExExtendZone(
  /*IN*/ PZONE_HEADER  Zone,
  /*IN*/ PVOID  Segment,
  /*IN*/ ULONG  SegmentSize);

static __inline PVOID
ExFreeToZone(
  /*IN*/ PZONE_HEADER  Zone,
  /*IN*/ PVOID  Block)
{
  ((PSINGLE_LIST_ENTRY) Block)->Next = Zone->FreeList.Next;
  Zone->FreeList.Next = ((PSINGLE_LIST_ENTRY) Block);
  return ((PSINGLE_LIST_ENTRY) Block)->Next;
}

NTOSAPI
NTSTATUS
DDKAPI
ExInitializeZone(
  /*IN*/ PZONE_HEADER  Zone,
  /*IN*/ ULONG  BlockSize,
  /*IN*/ PVOID  InitialSegment,
  /*IN*/ ULONG  InitialSegmentSize);

/*
 * PVOID
 * ExInterlockedAllocateFromZone(
 * IN PZONE_HEADER  Zone,
 * IN PKSPIN_LOCK  Lock)
 */
#define ExInterlockedAllocateFromZone(Zone, \
                              Lock) \
  ((PVOID) ExInterlockedPopEntryList(&Zone->FreeList, Lock))

NTOSAPI
NTSTATUS
DDKAPI
ExInterlockedExtendZone(
  /*IN*/ PZONE_HEADER  Zone,
  /*IN*/ PVOID  Segment,
  /*IN*/ ULONG  SegmentSize,
  /*IN*/ PKSPIN_LOCK  Lock);

NTOSAPI
PVOID
DDKAPI
ExInterlockedFreeToZone(
  /*IN*/ PZONE_HEADER  Zone,
  /*IN*/ PVOID  Block,
  /*IN*/ PKSPIN_LOCK  Lock);

/*
 * VOID
 * ExInitializeWorkItem(
 * IN PWORK_QUEUE_ITEM  Item,
 * IN PWORKER_THREAD_ROUTINE  Routine,
 * IN PVOID  Context)
 */
#define ExInitializeWorkItem(Item, \
                             Routine, \
                             Context) \
{ \
  (Item)->WorkerRoutine = Routine; \
  (Item)->Parameter = Context; \
  (Item)->List.Flink = NULL; \
}

/*
 * BOOLEAN
 * ExIsFullZone(
 * IN PZONE_HEADER  Zone)
 */
#define ExIsFullZone(Zone) \
  ((Zone)->FreeList.Next == (PSINGLE_LIST_ENTRY) NULL)

NTOSAPI
VOID
DDKAPI
ExQueueWorkItem(
  /*IN*/ PWORK_QUEUE_ITEM  WorkItem,
  /*IN*/ WORK_QUEUE_TYPE  QueueType);

NTOSAPI
BOOLEAN
DDKAPI
ExIsObjectInFirstZoneSegment(
  /*IN*/ PZONE_HEADER  Zone,
  /*IN*/ PVOID  Object);

NTOSAPI
VOID
DDKAPI
ExReleaseResource(
  /*IN*/ PERESOURCE  Resource);

#define ExAcquireResourceExclusive ExAcquireResourceExclusiveLite
#define ExAcquireResourceShared ExAcquireResourceSharedLite
#define ExConvertExclusiveToShared ExConvertExclusiveToSharedLite
#define ExDeleteResource ExDeleteResourceLite
#define ExInitializeResource ExInitializeResourceLite
#define ExIsResourceAcquiredExclusive ExIsResourceAcquiredExclusiveLite
#define ExIsResourceAcquiredShared ExIsResourceAcquiredSharedLite
#define ExIsResourceAcquired ExIsResourceAcquiredSharedLite
#define ExReleaseResourceForThread ExReleaseResourceForThreadLite

NTOSAPI
INTERLOCKED_RESULT
DDKAPI
ExInterlockedDecrementLong(
  /*IN*/ PLONG  Addend,
  /*IN*/ PKSPIN_LOCK  Lock);

NTOSAPI
ULONG
DDKAPI
ExInterlockedExchangeUlong(
  /*IN*/ PULONG  Target,
  /*IN*/ ULONG  Value,
  /*IN*/ PKSPIN_LOCK  Lock);

NTOSAPI
INTERLOCKED_RESULT
DDKAPI
ExInterlockedIncrementLong(
  /*IN*/ PLONG  Addend,
  /*IN*/ PKSPIN_LOCK  Lock);

NTOSAPI
PVOID
DDKAPI
HalAllocateCommonBuffer(
  /*IN*/ PADAPTER_OBJECT  AdapterObject,
  /*IN*/ ULONG  Length,
  /*OUT*/ PPHYSICAL_ADDRESS  LogicalAddress,
  /*IN*/ BOOLEAN  CacheEnabled);

NTOSAPI
NTSTATUS
DDKAPI
HalAssignSlotResources(
  /*IN*/ PUNICODE_STRING  RegistryPath,
  /*IN*/ PUNICODE_STRING  DriverClassName,
  /*IN*/ PDRIVER_OBJECT  DriverObject,
  /*IN*/ PDEVICE_OBJECT  DeviceObject,
  /*IN*/ INTERFACE_TYPE  BusType,
  /*IN*/ ULONG  BusNumber,
  /*IN*/ ULONG  SlotNumber,
  /*IN OUT*/ PCM_RESOURCE_LIST  *AllocatedResources);

NTOSAPI
VOID
DDKAPI
HalFreeCommonBuffer(
  /*IN*/ PADAPTER_OBJECT  AdapterObject,
  /*IN*/ ULONG  Length,
  /*IN*/ PHYSICAL_ADDRESS  LogicalAddress,
  /*IN*/ PVOID  VirtualAddress,
  /*IN*/ BOOLEAN  CacheEnabled);

NTOSAPI
PADAPTER_OBJECT
DDKAPI
HalGetAdapter(
  /*IN*/ PDEVICE_DESCRIPTION  DeviceDescription,
  /*IN OUT*/ PULONG  NumberOfMapRegisters);

NTOSAPI
ULONG
DDKAPI
HalGetBusData(
  /*IN*/ BUS_DATA_TYPE  BusDataType,
  /*IN*/ ULONG  BusNumber,
  /*IN*/ ULONG  SlotNumber,
  /*IN*/ PVOID  Buffer,
  /*IN*/ ULONG  Length);

NTOSAPI
ULONG
DDKAPI
HalGetBusDataByOffset(
  /*IN*/ BUS_DATA_TYPE  BusDataType,
  /*IN*/ ULONG  BusNumber,
  /*IN*/ ULONG  SlotNumber,
  /*IN*/ PVOID  Buffer,
  /*IN*/ ULONG  Offset,
  /*IN*/ ULONG  Length);

NTOSAPI
ULONG
DDKAPI
HalGetDmaAlignmentRequirement( 
  VOID);

NTOSAPI
ULONG
DDKAPI
HalGetInterruptVector(
  /*IN*/ INTERFACE_TYPE  InterfaceType,
  /*IN*/ ULONG  BusNumber,
  /*IN*/ ULONG  BusInterruptLevel,
  /*IN*/ ULONG  BusInterruptVector,
  /*OUT*/ PKIRQL  Irql,
  /*OUT*/ PKAFFINITY  Affinity);

NTOSAPI
ULONG
DDKAPI
HalReadDmaCounter(
  /*IN*/ PADAPTER_OBJECT  AdapterObject);

NTOSAPI
ULONG
DDKAPI
HalSetBusData(
  /*IN*/ BUS_DATA_TYPE  BusDataType,
  /*IN*/ ULONG  BusNumber,
  /*IN*/ ULONG  SlotNumber,
  /*IN*/ PVOID  Buffer,
  /*IN*/ ULONG  Length);

NTOSAPI
ULONG
DDKAPI
HalSetBusDataByOffset(
  /*IN*/ BUS_DATA_TYPE  BusDataType,
  /*IN*/ ULONG  BusNumber,
  /*IN*/ ULONG  SlotNumber,
  /*IN*/ PVOID  Buffer,
  /*IN*/ ULONG  Offset,
  /*IN*/ ULONG  Length);

NTOSAPI
BOOLEAN
DDKAPI
HalTranslateBusAddress(
  /*IN*/ INTERFACE_TYPE  InterfaceType,
  /*IN*/ ULONG  BusNumber,
  /*IN*/ PHYSICAL_ADDRESS  BusAddress,
  /*IN OUT*/ PULONG  AddressSpace,
  /*OUT*/ PPHYSICAL_ADDRESS  TranslatedAddress);

NTOSAPI
NTSTATUS
DDKAPI
IoAllocateAdapterChannel(
  /*IN*/ PADAPTER_OBJECT  AdapterObject,
  /*IN*/ PDEVICE_OBJECT  DeviceObject,
  /*IN*/ ULONG  NumberOfMapRegisters,
  /*IN*/ PDRIVER_CONTROL  ExecutionRoutine,
  /*IN*/ PVOID  Context);

NTOSAPI
NTSTATUS
DDKAPI
IoAssignResources(
  /*IN*/ PUNICODE_STRING  RegistryPath,
  /*IN*/ PUNICODE_STRING  DriverClassName  /*OPTIONAL*/,
  /*IN*/ PDRIVER_OBJECT  DriverObject,
  /*IN*/ PDEVICE_OBJECT  DeviceObject  /*OPTIONAL*/,
  /*IN*/ PIO_RESOURCE_REQUIREMENTS_LIST  RequestedResources,
  /*IN OUT*/ PCM_RESOURCE_LIST  *AllocatedResources);

NTOSAPI
NTSTATUS
DDKAPI
IoAttachDeviceByPointer(
  /*IN*/ PDEVICE_OBJECT  SourceDevice,
  /*IN*/ PDEVICE_OBJECT  TargetDevice);

NTOSAPI
BOOLEAN
DDKAPI
IoFlushAdapterBuffers(
  /*IN*/ PADAPTER_OBJECT  AdapterObject,
  /*IN*/ PMDL  Mdl,
  /*IN*/ PVOID  MapRegisterBase,
  /*IN*/ PVOID  CurrentVa,
  /*IN*/ ULONG  Length,
  /*IN*/ BOOLEAN  WriteToDevice);

NTOSAPI
VOID
DDKAPI
IoFreeAdapterChannel(
  /*IN*/ PADAPTER_OBJECT  AdapterObject);

NTOSAPI
VOID
DDKAPI
IoFreeMapRegisters(
  /*IN*/ PADAPTER_OBJECT  AdapterObject,
  /*IN*/ PVOID  MapRegisterBase,
  /*IN*/ ULONG  NumberOfMapRegisters);

NTOSAPI
PHYSICAL_ADDRESS
DDKAPI
IoMapTransfer(
  /*IN*/ PADAPTER_OBJECT  AdapterObject,
  /*IN*/ PMDL  Mdl,
  /*IN*/ PVOID  MapRegisterBase,
  /*IN*/ PVOID  CurrentVa,
  /*IN OUT*/ PULONG  Length,
  /*IN*/ BOOLEAN  WriteToDevice);

NTOSAPI
PMDL
DDKAPI
MmCreateMdl(
  /*IN*/ PMDL  MemoryDescriptorList  /*OPTIONAL*/,
  /*IN*/ PVOID  Base,
  /*IN*/ SIZE_T  Length);

NTOSAPI
BOOLEAN
DDKAPI
MmIsNonPagedSystemAddressValid(
  /*IN*/ PVOID  VirtualAddress);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlEnlargedIntegerMultiply(
  /*IN*/ LONG  Multiplicand,
  /*IN*/ LONG  Multiplier);

NTOSAPI
ULONG
DDKAPI
RtlEnlargedUnsignedDivide(
  /*IN*/ ULARGE_INTEGER  Dividend,
  /*IN*/ ULONG  Divisor,
  /*IN OUT*/ PULONG  Remainder);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlEnlargedUnsignedMultiply(
  /*IN*/ ULONG  Multiplicand,
  /*IN*/ ULONG  Multiplier);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlExtendedIntegerMultiply(
  /*IN*/ LARGE_INTEGER  Multiplicand,
  /*IN*/ LONG  Multiplier);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlExtendedLargeIntegerDivide(
  /*IN*/ LARGE_INTEGER  Dividend,
  /*IN*/ ULONG  Divisor,
  /*IN OUT*/ PULONG  Remainder);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlExtendedMagicDivide(
  /*IN*/ LARGE_INTEGER  Dividend,
  /*IN*/ LARGE_INTEGER  MagicDivisor,
  /*IN*/ CCHAR  ShiftCount);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlLargeIntegerAdd(
  /*IN*/ LARGE_INTEGER  Addend1,
  /*IN*/ LARGE_INTEGER  Addend2);

NTOSAPI
VOID
DDKAPI
RtlLargeIntegerAnd(
  /*IN OUT*/ LARGE_INTEGER  Result,
  /*IN*/ LARGE_INTEGER  Source,
  /*IN*/ LARGE_INTEGER  Mask);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlLargeIntegerArithmeticShift(
  /*IN*/ LARGE_INTEGER  LargeInteger,
  /*IN*/ CCHAR  ShiftCount);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlLargeIntegerDivide(
  /*IN*/ LARGE_INTEGER  Dividend,
  /*IN*/ LARGE_INTEGER  Divisor,
  /*IN OUT*/ PLARGE_INTEGER  Remainder);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerEqualTo(
  /*IN*/ LARGE_INTEGER  Operand1,
  /*IN*/ LARGE_INTEGER  Operand2);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerEqualToZero(
  /*IN*/ LARGE_INTEGER  Operand);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerGreaterOrEqualToZero(
  /*IN*/ LARGE_INTEGER  Operand);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerGreaterThan(
  /*IN*/ LARGE_INTEGER  Operand1,
  /*IN*/ LARGE_INTEGER  Operand2);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerGreaterThanOrEqualTo(
  /*IN*/ LARGE_INTEGER  Operand1,
  /*IN*/ LARGE_INTEGER  Operand2);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerGreaterThanZero(
  /*IN*/ LARGE_INTEGER  Operand);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerLessOrEqualToZero(
  /*IN*/ LARGE_INTEGER  Operand);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerLessThan(
  /*IN*/ LARGE_INTEGER  Operand1,
  /*IN*/ LARGE_INTEGER  Operand2);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerLessThanOrEqualTo(
  /*IN*/ LARGE_INTEGER  Operand1,
  /*IN*/ LARGE_INTEGER  Operand2);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerLessThanZero(
  /*IN*/ LARGE_INTEGER  Operand);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlLargeIntegerNegate(
  /*IN*/ LARGE_INTEGER  Subtrahend);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerNotEqualTo(
  /*IN*/ LARGE_INTEGER  Operand1,
  /*IN*/ LARGE_INTEGER  Operand2);

NTOSAPI
BOOLEAN
DDKAPI
RtlLargeIntegerNotEqualToZero(
  /*IN*/ LARGE_INTEGER  Operand);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlLargeIntegerShiftLeft(
  /*IN*/ LARGE_INTEGER  LargeInteger,
  /*IN*/ CCHAR  ShiftCount);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlLargeIntegerShiftRight(
  /*IN*/ LARGE_INTEGER  LargeInteger,
  /*IN*/ CCHAR  ShiftCount);

NTOSAPI
LARGE_INTEGER
DDKAPI
RtlLargeIntegerSubtract(
  /*IN*/ LARGE_INTEGER  Minuend,
  /*IN*/ LARGE_INTEGER  Subtrahend);


/*
 * ULONG
 * COMPUTE_PAGES_SPANNED(
 * IN PVOID  Va,
 * IN ULONG  Size)
 */
#define COMPUTE_PAGES_SPANNED(Va, \
                              Size) \
  (ADDRESS_AND_SIZE_TO_SPAN_PAGES(Va, Size))


/*
** Architecture specific functions
*/

#ifdef _X86_

NTOSAPI
INTERLOCKED_RESULT
DDKAPI
Exi386InterlockedIncrementLong(
  /*IN*/ PLONG  Addend);

NTOSAPI
INTERLOCKED_RESULT
DDKFASTAPI
Exfi386InterlockedIncrementLong(
  /*IN*/ PLONG  Addend);

NTOSAPI
INTERLOCKED_RESULT
DDKAPI
Exi386InterlockedDecrementLong(
  /*IN*/ PLONG  Addend);

NTOSAPI
INTERLOCKED_RESULT
DDKFASTAPI
Exfi386InterlockedDecrementLong(
  /*IN*/ PLONG  Addend);

NTOSAPI
ULONG
DDKAPI
Exi386InterlockedExchangeUlong(
  /*IN*/ PULONG  Target,
  /*IN*/ ULONG  Value);

NTOSAPI
ULONG
DDKFASTAPI
Exfi386InterlockedExchangeUlong(
  /*IN*/ PULONG  Target,
  /*IN*/ ULONG  Value);

#define ExInterlockedIncrementLong(Addend,Lock) Exfi386InterlockedIncrementLong(Addend)
#define ExInterlockedDecrementLong(Addend,Lock) Exfi386InterlockedDecrementLong(Addend)
#define ExInterlockedExchangeUlong(Target, Value, Lock) Exfi386InterlockedExchangeUlong(Target, Value)

#endif /* _X86_ */

#ifdef __cplusplus
}
#endif

#endif /* __WINNT4_H */
