Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

447 lines
7.5 KiB

/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
Buffer.c
Abstract:
This module contains routines to perform the actual buffering of data
for dpmi api translation support.
Author:
Dave Hastings (daveh) 30-Nov-1992
Revision History:
Neil Sandlin (neilsa) 31-Jul-1995 - Updates for the 486 emulator
--*/
#include "precomp.h"
#pragma hdrstop
#include "softpc.h"
PUCHAR
DpmiMapAndCopyBuffer(
PUCHAR Buffer,
USHORT BufferLength
)
/*++
Routine Description:
This routine selects the appropriate buffer for the translation,
and copies the high memory buffer to it.
Arguments:
Buffer -- Supplies buffer in high memory
BufferLength -- Supplies the length of the buffer
Return Value:
Returns a pointer to the translation buffer
--*/
{
PUCHAR NewBuffer;
//
// if the buffer is already in low memory, don't do anything
//
if ((ULONG)(Buffer + BufferLength - IntelBase) < MAX_V86_ADDRESS) {
return Buffer;
}
NewBuffer = DpmiAllocateBuffer(BufferLength);
CopyMemory(NewBuffer, Buffer, BufferLength);
return NewBuffer;
}
VOID
DpmiUnmapAndCopyBuffer(
PUCHAR Destination,
PUCHAR Source,
USHORT BufferLength
)
/*++
Routine Description:
This routine copies the information back to the high memory buffer
Arguments:
Destination -- Supplies the destination buffer
Source -- Supplies the source buffer
BufferLength -- Supplies the length of the information to copy
Return Value:
None.
--*/
{
//
// If the addresses are the same, don't do anything
//
if (Source == Destination) {
return;
}
CopyMemory(Destination, Source, BufferLength);
//
// Free the buffer
//
DpmiFreeBuffer(Source, BufferLength);
}
VOID
DpmiUnmapBuffer(
PUCHAR Buffer,
USHORT BufferLength
)
/*++
Routine Description:
This routine frees the buffer.
Arguments:
Buffer -- Supplies the buffer
Return Value:
None.
--*/
{
DpmiFreeBuffer(Buffer, BufferLength);
}
USHORT
DpmiCalcFcbLength(
PUCHAR FcbPointer
)
/*++
Routine Description:
This routine calculates the length of an FCB.
Arguments:
FcbPointer -- Supplies the Fcb
Return Value:
Length of the fcb in bytes
--*/
{
if (*FcbPointer == 0xFF) {
return 0x2c;
} else {
return 0x25;
}
}
PUCHAR
DpmiMapString(
USHORT StringSeg,
ULONG StringOff,
PWORD16 Length
)
/*++
Routine Description:
This routine maps an asciiz string to low memory
Arguments:
StringSeg -- Supplies the segment of the string
StringOff -- Supplies the offset of the string
Return Value:
Pointer to the buffered string
; NOTE:
; DOS has a tendency to look one byte past the end of the string "\"
; to look for ":\" followed by a zero. For this reason, we always
; map three extra bytes of every string.
--*/
{
USHORT CurrentChar = 0;
PUCHAR String;
ULONG Limit;
String = Sim32GetVDMPointer(
((ULONG)StringSeg << 16),
1,
TRUE
);
String += StringOff;
//
// Scan string for NULL
//
GET_SELECTOR_LIMIT(StringSeg, Limit);
Limit -= StringOff;
while (CurrentChar <= (USHORT)Limit) {
if (String[CurrentChar] == '\0') {
break;
}
CurrentChar++;
}
//
// If we didn't reach the end of the segment, we stopped because
// of the null, and need to include that in the string
//
if (CurrentChar < (USHORT)Limit) {
CurrentChar++;
}
//
// If we didn't find the end, copy 100h bytes
//
if ((String[CurrentChar] != '\0') && CurrentChar > 0x100) {
CurrentChar = 0x100;
}
//
// If there are 3 bytes after the string, copy the extra 3 bytes
//
if ((CurrentChar + 3) <= (USHORT)Limit) {
CurrentChar += 3;
}
//
// The length is one based. The index is zero based
//
*Length = CurrentChar + 1;
return DpmiMapAndCopyBuffer(String, (USHORT) (CurrentChar + 1));
}
VOID
DpmiUnmapString(
PUCHAR String,
USHORT Length
)
{
DpmiUnmapBuffer(String, Length);
return;
}
USHORT
DpmiSegmentToSelector(
USHORT Segment
)
/*++
Routine Description:
This routine converts a specfied segment to a Data selector. If there
is a approprate selector in the LDT, that is returned. If not a new
selector is created. This routine can only be called in protectedmode.
Arguments:
Segment -- Segment to convert
Return Value:
Selector for the specified segment
--*/
{
USHORT ClientAX, ClientBX, ClientCS, ClientIP, ClientDS, ClientES, Selector;
PWORD16 Stack;
VSAVEDSTATE State;
ASSERT(getMSW() & MSW_PE);
DpmiSaveSegmentsAndStack(&State);
ClientAX = getAX();
ClientBX = getBX();
ClientCS = getCS();
ClientIP = getIP();
ClientDS = getDS();
ClientES = getES();
DpmiSwitchToDosxStack(TRUE);
//
// Make room for return address
//
setSP(getSP() - 4);
//
// Push a return to a bop
//
Stack = (PWORD16)Sim32GetVDMPointer(
((ULONG)getSS() << 16) | getSP(),
1,
TRUE
);
*Stack = (USHORT)(RmBopFe & 0x0000FFFF);
*(Stack + 1) = DosxRmCodeSelector;
//
// Set up the parameters
//
setAX(Segment);
setBX(0xF2);
if (CurrentAppFlags & DPMI_32BIT) {
setBX(getBX() | 0xF000);
}
//
// Make the call
//
setES(0);
setCS((USHORT) (DosxSegmentToSelector >> 16));
setIP((USHORT) (DosxSegmentToSelector & 0xFFFF));
setDS(DosxPmDataSelector);
host_simulate();
if (!getCF()) {
Selector = getAX();
} else {
Selector = 0xFFF0; // Guaranteed non-existant GDT selector
}
DpmiSwitchFromDosxStack();
setAX(ClientAX);
setBX(ClientBX);
setIP(ClientIP);
setCS(ClientCS);
DpmiRestoreSegmentsAndStack();
return Selector;
}
PUCHAR
DpmiAllocateBuffer(
USHORT Length
)
/*++
Routine Description:
This routine allocates buffer space from the static buffer in low
memory.
Arguments:
Length -- Length of the buffer needed
Return Value:
Returns pointer to the buffer space allocated
--*/
{
//
// If the data fits in the small buffer, use it
//
if ((Length <= SMALL_XLAT_BUFFER_SIZE) && !SmallBufferInUse) {
SmallBufferInUse = TRUE;
return SmallXlatBuffer;
}
if (Length <= (LARGE_XLAT_BUFFER_SIZE - LargeBufferInUseCount)) {
LargeBufferInUseCount += Length;
return (LargeXlatBuffer + LargeBufferInUseCount - Length);
}
//
// Whoops! No buffer space available. Bomb with a predictable
// address.
//
ASSERT(0); // this is an internal error
return (PUCHAR)0xf00df00d;
}
VOID
DpmiFreeBuffer(
PUCHAR Buffer,
USHORT Length
)
/*++
Routine Description:
Frees buffer space allocated using DpmiAllocateBuffer
Arguments:
Buffer -- Supplies a pointer to the buffer allocated above
Length -- Length of the buffer allocated
Return Value:
None.
--*/
{
//
// Free the buffer
//
if (Buffer == SmallXlatBuffer) {
SmallBufferInUse = FALSE;
}
if ((Buffer >= LargeXlatBuffer) &&
(Buffer < (LargeXlatBuffer + LARGE_XLAT_BUFFER_SIZE))
) {
LargeBufferInUseCount -= Length;
}
}
VOID
DpmiFreeAllBuffers(
VOID
)
/*++
Routine Description:
This routine frees all of the currently allocated buffer space.
Arguments:
Return Value:
None.
--*/
{
SmallBufferInUse = FALSE;
LargeBufferInUseCount = 0;
}