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.
 
 
 
 
 
 

870 lines
19 KiB

/******************************Module*Header*******************************\
* Module Name: os.cxx *
* *
* Convenient functions to access the OS interface. *
* *
* Created: 29-Aug-1989 19:59:05 *
* Author: Charles Whitmer [chuckwh] *
* *
* Copyright (c) 1989,1990,1991 Microsoft Corporation *
\**************************************************************************/
#include "precomp.hxx"
/******************************Public*Routine******************************\
* EngGetProcessHandle
*
* Returns the current thread of the application.
*
* History:
* 24-Jan-1996 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
HANDLE APIENTRY EngGetProcessHandle()
{
return (HANDLE) NULL;
}
/******************************Public*Routine******************************\
* hsemCreate
*
* Create critical section.
*
* History:
* Wed 21-Oct-1992 -by- Patrick Haluptzok [patrickh]
* remove call to Pos wrapper, deallocate on failure.
*
* Mon 25-Sep-1989 22:37:24 -by- Charles Whitmer [chuckwh]
* Simplified the name.
*
* 09-Sep-1989 -by- Donald Sidoroff [donalds]
* Wrote it.
*
\**************************************************************************/
PERESOURCE hsemCreate()
{
PERESOURCE resource;
resource = (PERESOURCE) ExAllocatePoolWithTag(NonPagedPool,
sizeof(ERESOURCE),
'mesG');
if (resource)
{
if (!NT_SUCCESS(ExInitializeResourceLite(resource)))
{
ExFreePool(resource);
resource = NULL;
}
}
return resource;
}
/******************************Public*Routine******************************\
* hsemDestroy
*
* Delete Critical section.
*
* History:
* Wed 21-Oct-1992 -by- Patrick Haluptzok [patrickh]
* Remove wrapper.
*
* 29-Jul-1990 -by- Donald Sidoroff [donalds]
* Wrote it.
\**************************************************************************/
VOID hsemDestroy(PERESOURCE hsem)
{
ExDeleteResourceLite(hsem);
ExFreePool(hsem);
}
/******************************Public*Routine******************************\
* EngSetLastError
*
* Saves Error code passed in.
*
* History:
* Sat 31-Oct-1992 -by- Patrick Haluptzok [patrickh]
* Remove wrapper.
*
* 28-Oct-1992 -by- Bodin Dresevic [BodinD]
* Wrote it.
\**************************************************************************/
VOID EngSetLastError(ULONG iError)
{
PTEB pteb = NtCurrentTeb();
if (pteb)
pteb->LastErrorValue = iError;
#if DBG
PSZ psz;
switch (iError)
{
case ERROR_INVALID_HANDLE:
psz = "ERROR_INVALID_HANDLE";
break;
case ERROR_NOT_ENOUGH_MEMORY:
psz = "ERROR_NOT_ENOUGH_MEMORY";
break;
case ERROR_INVALID_PARAMETER:
psz = "ERROR_INVALID_PARAMETER";
break;
case ERROR_BUSY:
psz = "ERROR_BUSY";
break;
case ERROR_ARITHMETIC_OVERFLOW:
psz = "ERROR_ARITHMETIC_OVERFLOW";
break;
case ERROR_INVALID_FLAGS:
psz = "ERROR_INVALID_FLAGS";
break;
case ERROR_CAN_NOT_COMPLETE:
psz = "ERROR_CAN_NOT_COMPLETE";
break;
default:
psz = "unknown error code";
break;
}
// DbgPrint("GRE Err: %s = 0x%04X\n", psz, (USHORT) iError);
#endif
}
/******************************Public*Routine******************************\
*
* History:
* 27-Jun-1995 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
ULONG APIENTRY EngGetLastError()
{
ULONG ulError = 0;
PTEB pteb = NtCurrentTeb();
if (pteb)
ulError = pteb->LastErrorValue;
return(ulError);
}
/******************************Public*Routine******************************\
* GreLockDisplay()
*
* History:
* 01-Nov-1994 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
GreLockDisplay(
PDEVICE_LOCK devlock
)
{
VACQUIREDEVLOCK(devlock);
}
/******************************Public*Routine******************************\
* GreUnlockDisplay()
*
* History:
* 01-Nov-1994 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
GreUnlockDisplay(
PDEVICE_LOCK devlock
)
{
VRELEASEDEVLOCK(devlock);
}
/***************************************************************************\
* EngDebugPrint
*
* History:
* 02-Feb-1995 -by- Andre Vachon [andreva]
* Wrote it.
\***************************************************************************/
VOID
EngDebugPrint(
PCHAR StandardPrefix,
PCHAR DebugMessage,
va_list ap
)
{
char buffer[256];
int len;
//
// We prepend the STANDARD_DEBUG_PREFIX to each string, and
// append a new-line character to the end:
//
DbgPrint(StandardPrefix);
vsprintf(buffer, DebugMessage, ap);
DbgPrint(buffer);
}
/******************************Public*Routine******************************\
* EngDebugBreak()
*
* History:
* 16-Feb-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
EngDebugBreak(
VOID
)
{
DbgBreakPoint();
}
/******************************Public*Routine******************************\
* EngAllocMem()
*
* History:
* 27-May-1995 -by- Tom Zakrajsek [tomzak]
* Added a flags parameter to allow zeroing of memory.
*
* 02-Feb-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
PVOID
EngAllocMem(
ULONG fl,
ULONG cj,
ULONG tag
)
{
if (cj >= (PAGE_SIZE * 10000))
{
WARNING("EngAllocMem: temp buffer >= 10000 pages");
return(NULL);
}
if (fl & FL_ZERO_MEMORY) {
return PALLOCMEM(cj,tag);
} else {
return PALLOCNOZ(cj,tag);
}
}
/******************************Public*Routine******************************\
* EngFreeMem()
*
* History:
* 02-Feb-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
VOID
EngFreeMem(
PVOID pv
)
{
if (pv)
{
VFREEMEM(pv);
}
return;
}
/******************************Public*Routine******************************\
* EngProbeForRead()
*
* History:
* 02-Oct-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
VOID
EngProbeForRead(
PVOID Address,
ULONG Length,
ULONG Alignment
)
{
ProbeForRead(Address, Length, Alignment);
}
/******************************Public*Routine******************************\
* EngAllocUserMem()
*
* This routine allocates a piece of memory for USER mode and locks it
* down. A driver must be very careful with this memory as it is only
* valid for this process.
*
* History:
* 10-Sep-1995 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
PVOID
EngAllocUserMem(
ULONG cj,
ULONG tag
)
{
NTSTATUS status;
PVOID pv = NULL;
HANDLE hSecure;
// add two dwords so we have space to store the hSecure and tag.
cj += sizeof(ULONG) * 4;
status = ZwAllocateVirtualMemory(
NtCurrentProcess(),
&pv,
0,
&cj,
MEM_COMMIT | MEM_RESERVE,
PAGE_READWRITE);
if (NT_SUCCESS(status))
{
hSecure = MmSecureVirtualMemory(pv,cj,PAGE_READWRITE);
if (hSecure)
{
((PULONG)pv)[0] = 'xIDG';
((PULONG)pv)[1] = cj;
((PULONG)pv)[2] = tag;
((PULONG)pv)[3] = (ULONG)hSecure;
pv = (PBYTE)pv + sizeof(DWORD)*4;
}
else
{
ZwFreeVirtualMemory(
NtCurrentProcess(),
&pv,
&cj,
MEM_RELEASE);
}
}
return(pv);
}
/******************************Public*Routize******************************\
* EngSecureMem()
*
* History:
* 02-Oct-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
HANDLE
APIENTRY
EngSecureMem(
PVOID Address,
ULONG Length
)
{
return (MmSecureVirtualMemory(Address, Length, PAGE_READWRITE));
}
/******************************Public*Routine******************************\
* EngUnsecureMem()
*
* History:
* 02-Oct-1995 -by- Andre Vachon [andreva]
* Wrote it.
*
* Note: Forwarder only - no code needed
\**************************************************************************/
/******************************Public*Routine******************************\
* EngFreeUserMem()
*
* History:
* 10-Sep-1995 -by- Eric Kutter [erick]
* Wrote it.
\**************************************************************************/
VOID
EngFreeUserMem(
PVOID pv
)
{
if (pv)
{
pv = (PBYTE)pv - sizeof(DWORD)*4;
if (((PULONG)pv)[0] == 'xIDG') // GDIx
{
ULONG cj = ((PULONG)pv)[1];
HANDLE hSecure = (HANDLE)((PULONG)pv)[3];
NTSTATUS status;
MmUnsecureVirtualMemory(hSecure);
ZwFreeVirtualMemory(
NtCurrentProcess(),
&pv,
&cj,
MEM_RELEASE);
}
else
{
RIP("EngFreeUserMem passed bad pointer\n");
}
}
return;
}
/******************************Public*Routine******************************\
* EngCreateSemaphore()
*
* History:
* 22-Feb-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
HSEMAPHORE
EngCreateSemaphore(
VOID
)
{
return ((HSEMAPHORE)hsemCreate());
}
VOID
EngAcquireSemaphore(
HSEMAPHORE hsem
)
{
VACQUIRESEM((PERESOURCE)hsem);
}
VOID
EngReleaseSemaphore(
HSEMAPHORE hsem
)
{
VRELEASESEM((PERESOURCE)hsem);
}
VOID
EngDeleteSemaphore(
HSEMAPHORE hsem
)
{
hsemDestroy((PERESOURCE)hsem);
}
/******************************Public*Routine******************************\
* EngDeviceIoControl()
*
* History:
* 04-Feb-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
NTSTATUS
GreDeviceIoControl(
HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned
)
{
NTSTATUS Status;
IO_STATUS_BLOCK Iosb;
PIRP pIrp;
NTSTATUS retStatus = STATUS_NOT_IMPLEMENTED;
// KEVENT event;
//
// KeInitializeEvent(&event,
// SynchronizationEvent,
// FALSE);
pIrp = IoBuildDeviceIoControlRequest(
dwIoControlCode,
(PDEVICE_OBJECT) hDevice,
lpInBuffer,
nInBufferSize,
lpOutBuffer,
nOutBufferSize,
FALSE,
NULL,
&Iosb);
if (pIrp)
{
Status = IoCallDriver((PDEVICE_OBJECT) hDevice,
pIrp);
// No need to do this since all of our calls are
// synchronous.
//
// Status = KeWaitForSingleObject(&event,
// UserRequest,
// KernelMode,
// TRUE,
// NULL);
//
// Since the call is synchronous, the IO is always completed
// and the Status is the same as the Iosb.Status.
//
retStatus = Status;
*lpBytesReturned = Iosb.Information;
}
return (retStatus);
}
DWORD
EngDeviceIoControl(
HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned
)
{
DWORD retStatus;
NTSTATUS Status = GreDeviceIoControl(hDevice,
dwIoControlCode,
lpInBuffer,
nInBufferSize,
lpOutBuffer,
nOutBufferSize,
lpBytesReturned);
//
// Do the inverse translation to what the video port does
// so that we can have the original win32 status codes.
//
// Maybe, somehow, we can completely eliminate this double
// translation - but I don't care for now. It's just a bit
// longer on the very odd failiure case
//
switch (Status) {
case STATUS_SUCCESS:
retStatus = NO_ERROR;
break;
case STATUS_NOT_IMPLEMENTED:
retStatus = ERROR_INVALID_FUNCTION;
break;
case STATUS_INSUFFICIENT_RESOURCES:
retStatus = ERROR_NOT_ENOUGH_MEMORY;
break;
case STATUS_INVALID_PARAMETER:
retStatus = ERROR_INVALID_PARAMETER;
break;
case STATUS_BUFFER_TOO_SMALL:
retStatus = ERROR_INSUFFICIENT_BUFFER;
break;
case STATUS_BUFFER_OVERFLOW:
retStatus = ERROR_MORE_DATA;
break;
case STATUS_PENDING:
retStatus = ERROR_IO_PENDING;
break;
case STATUS_DEVICE_DOES_NOT_EXIST:
retStatus = ERROR_DEV_NOT_EXIST;
break;
default:
retStatus = Status;
break;
}
return retStatus;
}
//
// BUGBUG only temporary.
//
VOID
EngMultiByteToUnicodeN(
PWSTR UnicodeString,
ULONG MaxBytesInUnicodeString,
PULONG BytesInUnicodeString,
PCHAR MultiByteString,
ULONG BytesInMultiByteString
)
{
RtlMultiByteToUnicodeN(UnicodeString,
MaxBytesInUnicodeString,
BytesInUnicodeString,
MultiByteString,
BytesInMultiByteString);
}
VOID
EngUnicodeToMultiByteN(
PCHAR MultiByteString,
ULONG MaxBytesInMultiByteString,
PULONG BytesInMultiByteString,
PWSTR UnicodeString,
ULONG BytesInUnicodeString
)
{
RtlUnicodeToMultiByteN( MultiByteString,
MaxBytesInMultiByteString,
BytesInMultiByteString,
UnicodeString,
BytesInUnicodeString );
}
/******************************Public*Routine******************************\
* EngLoadImage
*
* Loads an image that a display of printers driver can then call to execute
* code
*
* History:
* 20-Sep-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
HANDLE
APIENTRY
EngLoadImage(
LPWSTR pwszDriver
)
{
BOOL bLoaded;
return (HANDLE) ldevLoadImage(pwszDriver, TRUE, &bLoaded);
}
/******************************Public*Routine******************************\
* EngFindImageProcAddress
*
* Returns the address of the specified functions in the module.
* Special DrvEnableDriver since it is the entry point.
*
* History:
* 20-Sep-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
PVOID
APIENTRY
EngFindImageProcAddress(
HANDLE hModule,
LPSTR lpProcName
)
{
PSYSTEM_GDI_DRIVER_INFORMATION pGdiDriverInfo = ((PLDEV)hModule)->pGdiDriverInfo;
PULONG NameTableBase;
ULONG NumberOfNames;
PULONG AddressTableBase;
ULONG i;
NameTableBase = (PULONG)((ULONG)pGdiDriverInfo->ImageAddress +
(ULONG)pGdiDriverInfo->ExportSectionPointer->AddressOfNames);
NumberOfNames = pGdiDriverInfo->ExportSectionPointer->NumberOfNames;
AddressTableBase = (PULONG)((ULONG)pGdiDriverInfo->ImageAddress +
(ULONG)pGdiDriverInfo->ExportSectionPointer->AddressOfFunctions);
if (!strncmp(lpProcName,
"DrvEnableDriver",
strlen(lpProcName)))
{
return (pGdiDriverInfo->EntryPoint);
}
for (i=0; i < NumberOfNames; i++)
{
if (!strncmp(lpProcName,
(PCHAR) (NameTableBase[i] + (ULONG)pGdiDriverInfo->ImageAddress),
strlen(lpProcName)))
{
return ((PVOID) ((ULONG)pGdiDriverInfo->ImageAddress +
AddressTableBase[i]));
}
}
return NULL;
}
/******************************Public*Routine******************************\
* EngUnoadImage
*
* Unloads an image loaded using EngLoadModule.
*
* History:
* 20-Sep-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
EngUnloadImage(
HANDLE hModule
)
{
ldevUnloadImage((PLDEV)hModule);
}
/******************************Public*Routine******************************\
* EngQueryPerformanceCounter
*
* Queries the performance counter.
*
* It would have been preferable to use 'KeQueryTickCount,' but has a
* resolution of about 10ms on an x86, which is not sufficient for
* getting an accurate measure of the time between vertical blanks, which
* is typically between 8ms and 17ms.
*
* NOTE: Use this routine sparingly, calling it as infrequently as possible!
* Calling this routine too frequently can degrade I/O performance
* for the calling driver and for the system as a whole.
*
* History:
* 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
EngQueryPerformanceCounter(
LONGLONG *pPerformanceCount
)
{
LARGE_INTEGER li;
li = KeQueryPerformanceCounter(NULL);
*pPerformanceCount = *((LONGLONG*) &li);
}
/******************************Public*Routine******************************\
* EngQueryPerformanceFrequency
*
* Queries the resolution of the performance counter.
*
* History:
* 3-Dec-1995 -by- J. Andrew Goossen [andrewgo]
* Wrote it.
\**************************************************************************/
VOID
APIENTRY
EngQueryPerformanceFrequency(
LONGLONG *pFrequency
)
{
KeQueryPerformanceCounter((LARGE_INTEGER*) pFrequency);
}
/******************************Public*Routine******************************\
* EngCopyMemory
*
* Stub to support broken 64 bit writes on a few machines
*
* History:
* 20-Oct-1995 -by- Andre Vachon [andreva]
* Wrote it.
\**************************************************************************/
#if defined(_MIPS_)
extern "C" {
__cdecl
void *
EngCopyMemory(void * dest, const void * src, size_t length)
{
return memcpy(dest, src, length);
}
__cdecl
void *
EngFillMemory(void * dest, int fill, size_t length)
{
return memset(dest, fill, length);
}
__cdecl
void
EngFillMemoryUlong(PVOID dest, ULONG length, ULONG fill)
{
RtlFillMemoryUlong(dest, length, fill);
}
}
#endif