/*++ 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" #include "..\softpc.new\host\inc\host_rrr.h" #include "..\softpc.new\host\inc\nt_uis.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); } 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 or NULL in error case ; 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, NewString = NULL; ULONG Limit; BOOL SetNull = FALSE; String = VdmMapFlat(StringSeg, StringOff, VDM_PM); // // Scan string for NULL // GET_SHADOW_SELECTOR_LIMIT(StringSeg, Limit); if (Limit == 0 || StringOff >= Limit) { return NULL; } Limit -= StringOff; while (CurrentChar <= (USHORT)Limit) { if (String[CurrentChar] == '\0') { break; } CurrentChar++; } if (CurrentChar > (USHORT)Limit) { // // If we didn't find the end, move CurrentChar back to the end // of the segmen and only copy 100h bytes maximum. // SetNull = TRUE; CurrentChar--; if (CurrentChar > 0x100) { CurrentChar = 0x100; } } // // CurrentChar points to the last char that we need to copy and // most importantly CurrentChar is still within the segment. // ASSERT (CurrentChar <= (USHORT)Limit); // // If there are 3 bytes after the string, copy the extra 3 bytes // if ((CurrentChar + 3) <= (USHORT)Limit) { CurrentChar += 3; } else { CurrentChar = (USHORT)Limit; } // // The length is one based. The index is zero based // *Length = CurrentChar + 1; NewString = DpmiMapAndCopyBuffer(String, (USHORT) (CurrentChar + 1)); if (SetNull) { NewString[CurrentChar] = '\0'; } return NewString; } 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 Note, this routine never fails. If we are out of buffer space, this is considered as a BugCheck condition for NTVDM. NtVdm will be terminated. --*/ { // // 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. // This is an internal error. Terminate ntvdm. // ASSERT(0); // this is an internal error DisplayErrorTerm(EHS_FUNC_FAILED,GetLastError(),__FILE__,__LINE__); 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; }