mirror of https://github.com/lianthony/NT4.0
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.
536 lines
14 KiB
536 lines
14 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dllmisc.c
|
|
|
|
Abstract:
|
|
|
|
This module implements some miscellaneous OS/2 V2.0 API Calls
|
|
|
|
Author:
|
|
|
|
Steve Wood (stevewo) 20-Sep-1989 (Adapted from URTL\alloc.c)
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#define INCL_OS2V20_DEVICE_SUPPORT
|
|
#define INCL_OS2V20_TASKING
|
|
#define INCL_OS2V20_ERRORS
|
|
#include "os2dll.h"
|
|
#include "conrqust.h"
|
|
#include "os2win.h"
|
|
|
|
extern BOOLEAN FPUinit_unmask;
|
|
|
|
#define HARDWARE_NODE L"\\Registry\\Machine\\Hardware"
|
|
#define WORK_SIZE 1024
|
|
#define KEY_VALUE_BUFFER_SIZE 20240
|
|
WCHAR workbuffer[WORK_SIZE];
|
|
UCHAR KeyValueBuffer[KEY_VALUE_BUFFER_SIZE];
|
|
UNICODE_STRING WorkName;
|
|
|
|
APIRET
|
|
DosQuerySysInfo(
|
|
IN ULONG SysInfoIndexStart,
|
|
IN ULONG SysInfoIndexEnd,
|
|
OUT PBYTE Buffer,
|
|
IN ULONG Length
|
|
)
|
|
{
|
|
ULONG SysInfoIndex;
|
|
ULONG Value;
|
|
PULONG ValueDest;
|
|
LARGE_INTEGER SystemTime;
|
|
LARGE_INTEGER LocalTime;
|
|
NTSTATUS Status;
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG( DEVICE_SUPPORT ) {
|
|
DbgPrint( "Entering DosQuerySysInfo( %ld, %ld, %lX, %ld )\n",
|
|
SysInfoIndexStart, SysInfoIndexEnd, Buffer, Length
|
|
);
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Validate the input parameters
|
|
//
|
|
|
|
if (SysInfoIndexStart > SysInfoIndexEnd ||
|
|
SysInfoIndexStart < 1 ||
|
|
SysInfoIndexEnd > QSV_MAXIMUM_INDEX
|
|
) {
|
|
return( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
if (Length < ((SysInfoIndexEnd - SysInfoIndexStart + 1) * sizeof( ULONG ))) {
|
|
return( ERROR_BUFFER_OVERFLOW );
|
|
}
|
|
|
|
//
|
|
// Get the requested information into the Value local varible.
|
|
//
|
|
|
|
try {
|
|
ValueDest = (PULONG)Buffer;
|
|
for (SysInfoIndex=SysInfoIndexStart;
|
|
SysInfoIndex<=SysInfoIndexEnd;
|
|
SysInfoIndex++
|
|
) {
|
|
switch( SysInfoIndex ) {
|
|
//
|
|
// Bogus path limitations inheritied from OS/2. Our implementation
|
|
// does not have any limitations, other than available memory. But
|
|
// tell them what they expect to hear from OS/2 anyway.
|
|
//
|
|
|
|
case QSV_MAX_PATH_LENGTH:
|
|
Value = CCHMAXPATH;
|
|
break;
|
|
|
|
|
|
//
|
|
// Bogus limitation on the number of text mode (e.g. ANSI terminal)
|
|
// application sessions. Our implementation does not have any
|
|
// limitations other than available memory. But tell them what
|
|
// they expected to hear from OS/2 anyway.
|
|
//
|
|
|
|
case QSV_MAX_TEXT_SESSIONS:
|
|
Value = 16;
|
|
break;
|
|
|
|
|
|
//
|
|
// Bogus limitation on the number of Presentation Manager
|
|
// application sessions. Our implementation does not have any
|
|
// limitations other than available memory. But tell them what
|
|
// they expected to hear from OS/2 anyway.
|
|
//
|
|
|
|
case QSV_MAX_PM_SESSIONS:
|
|
Value = 16;
|
|
break;
|
|
|
|
|
|
//
|
|
// Not relevant until we get a software DOS simulator for non-Intel
|
|
// machines.
|
|
//
|
|
|
|
case QSV_MAX_VDM_SESSIONS:
|
|
Value = 0; // Machine dependent
|
|
break;
|
|
|
|
|
|
//
|
|
// Return the index of the boot drive.
|
|
//
|
|
|
|
case QSV_BOOT_DRIVE:
|
|
Value = Od2BootDrive+1;
|
|
break;
|
|
|
|
|
|
//
|
|
// Our system always runs with dynamic priority, so always return
|
|
// true.
|
|
//
|
|
|
|
case QSV_DYN_PRI_VARIATION:
|
|
Value = TRUE;
|
|
break;
|
|
|
|
|
|
//
|
|
// Our system does not currently implement a MAXWAIT concept,
|
|
// although it will at some point implement priority shuffling
|
|
// as a fix for user mode priority inversion. For now return
|
|
// return the default OS/2 2.0 value
|
|
//
|
|
|
|
case QSV_MAX_WAIT:
|
|
Value = 100;
|
|
break;
|
|
|
|
|
|
//
|
|
// Our system only has a single quantum value, so return the
|
|
// same number for both Minimum and Maximum time slice. For
|
|
// now this number will be the OS/2 2.0 constant without regard
|
|
// to the quantum value that the NT kernel is using.
|
|
//
|
|
|
|
case QSV_MIN_SLICE:
|
|
case QSV_MAX_SLICE:
|
|
Value = 248;
|
|
break;
|
|
|
|
|
|
//
|
|
// Finally, a real number we can return. Return the physical
|
|
// page size from the NT System Information record. This
|
|
// is NOT the allocation granularity.
|
|
//
|
|
|
|
case QSV_PAGE_SIZE:
|
|
Value = Od2NtSysInfo.PageSize;
|
|
break;
|
|
|
|
|
|
//
|
|
// Major version number is 20
|
|
//
|
|
|
|
case QSV_VERSION_MAJOR:
|
|
Value = 20;
|
|
break;
|
|
|
|
|
|
//
|
|
// Minor version number is 10
|
|
//
|
|
|
|
case QSV_VERSION_MINOR:
|
|
Value = 10;
|
|
break;
|
|
|
|
|
|
//
|
|
// Revision number is 0 (what is this on Cruiser?)
|
|
// FIX, FIX
|
|
//
|
|
|
|
case QSV_VERSION_REVISION:
|
|
Value = 0;
|
|
break;
|
|
|
|
|
|
//
|
|
// Free running millisecond counter
|
|
// FIX, FIX - need to get real timer in PCR
|
|
//
|
|
|
|
case QSV_MS_COUNT:
|
|
NtQuerySystemTime( &SystemTime );
|
|
|
|
//
|
|
// Convert UTC to Local time
|
|
//
|
|
|
|
Status = RtlSystemTimeToLocalTime ( &SystemTime, &LocalTime);
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
return (Or2MapNtStatusToOs2Error(Status, ERROR_INVALID_PARAMETER ));
|
|
}
|
|
|
|
Value = LocalTime.LowPart / 10;
|
|
break;
|
|
|
|
//
|
|
// Low dword of time in seconds since January 1, 1970
|
|
//
|
|
|
|
case QSV_TIME_LOW:
|
|
NtQuerySystemTime( &SystemTime );
|
|
|
|
//
|
|
// Convert UTC to Local time
|
|
//
|
|
|
|
Status = RtlSystemTimeToLocalTime ( &SystemTime, &LocalTime);
|
|
if (!NT_SUCCESS( Status ))
|
|
{
|
|
return (Or2MapNtStatusToOs2Error(Status, ERROR_INVALID_PARAMETER ));
|
|
}
|
|
|
|
RtlTimeToSecondsSince1970( &LocalTime,
|
|
&Value
|
|
);
|
|
break;
|
|
|
|
//
|
|
// High dword of time in seconds since January 1, 1970
|
|
// FIX, FIX - late in 21st century this is non-zero
|
|
//
|
|
|
|
case QSV_TIME_HIGH:
|
|
Value = 0;
|
|
break;
|
|
|
|
//
|
|
// Physical memory on system
|
|
//
|
|
|
|
case QSV_TOTPHYSMEM:
|
|
Value = 1024 * Od2NtSysInfo.PageSize;
|
|
break;
|
|
|
|
//
|
|
// Resident memory on system
|
|
//
|
|
|
|
case QSV_TOTRESMEM: // FIX, FIX
|
|
Value = 128 * Od2NtSysInfo.PageSize;
|
|
break;
|
|
|
|
//
|
|
// Available memory for all processes
|
|
//
|
|
|
|
case QSV_TOTAVAILMEM: // FIX, FIX
|
|
Value = Od2NtSysInfo.MaximumUserModeAddress -
|
|
Od2NtSysInfo.MinimumUserModeAddress;
|
|
break;
|
|
|
|
//
|
|
// Avail private mem for calling proc
|
|
//
|
|
|
|
case QSV_MAXPRMEM:
|
|
Value = Od2NtSysInfo.MaximumUserModeAddress -
|
|
Od2NtSysInfo.MinimumUserModeAddress;
|
|
break;
|
|
|
|
//
|
|
// Avail shared mem for calling proc
|
|
//
|
|
|
|
case QSV_MAXSHMEM:
|
|
Value = Od2NtSysInfo.MaximumUserModeAddress -
|
|
Od2NtSysInfo.MinimumUserModeAddress;
|
|
break;
|
|
|
|
//
|
|
// Timer interval in tenths of ms
|
|
//
|
|
|
|
case QSV_TIMER_INTERVAL:
|
|
Value = Od2NtSysInfo.TimerResolution / 100;
|
|
break;
|
|
|
|
//
|
|
// max len of one component in a name
|
|
//
|
|
|
|
case QSV_MAX_COMP_LENGTH:
|
|
Value = CCHMAXCOMP;
|
|
break;
|
|
|
|
//
|
|
// Return an error if invalid index specified.
|
|
//
|
|
|
|
default:
|
|
return( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
//
|
|
// Now store the value in the caller's buffer
|
|
//
|
|
|
|
*ValueDest++ = (ULONG)Value;
|
|
}
|
|
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
//
|
|
// Return success
|
|
//
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
|
|
APIRET
|
|
DosBeep(
|
|
IN ULONG Frequency,
|
|
IN ULONG Duration
|
|
)
|
|
{
|
|
APIRET RetCode;
|
|
#if DBG
|
|
PSZ RoutineName;
|
|
|
|
RoutineName = "DosBeep";
|
|
IF_OD2_DEBUG( DEVICE_SUPPORT )
|
|
{
|
|
DbgPrint( "%s: Frequency %ld, Duration %ld\n",
|
|
RoutineName, Frequency, Duration);
|
|
}
|
|
#endif
|
|
|
|
if (( Frequency < 37 ) || ( Frequency >= 0x8000 ))
|
|
{
|
|
return (ERROR_INVALID_FREQUENCY);
|
|
}
|
|
|
|
if(!(RetCode = Ow2ConBeep(Frequency, Duration)))
|
|
{
|
|
RetCode = DosSleep(Duration);
|
|
} else
|
|
{
|
|
#if DBG
|
|
IF_OD2_DEBUG( DEVICE_SUPPORT )
|
|
{
|
|
DbgPrint( "%s: rc %lu\n", RoutineName, RetCode);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
return( RetCode );
|
|
}
|
|
|
|
|
|
APIRET
|
|
DosDevConfig(
|
|
OUT PVOID DeviceInformation,
|
|
IN ULONG DeviceInformationIndex
|
|
)
|
|
{
|
|
ULONG Value;
|
|
ULONG ValueLength = 1;
|
|
// SYSTEM_PROCESSOR_INFORMATION Info;
|
|
SYSTEM_DEVICE_INFORMATION SystemInfo;
|
|
HANDLE Handle;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING WorkName;
|
|
NTSTATUS status;
|
|
|
|
#if DBG
|
|
IF_OD2_DEBUG( DEVICE_SUPPORT ) {
|
|
DbgPrint( "Entering DosDevConfig( %lX, %ld )\n",
|
|
DeviceInformation, DeviceInformationIndex
|
|
);
|
|
}
|
|
#endif
|
|
|
|
switch ( DeviceInformationIndex ) {
|
|
|
|
case DDC_NUMBER_PRINTERS:
|
|
case DDC_NUMBER_RS232_PORTS:
|
|
case DDC_NUMBER_DISKETTE_DRIVES:
|
|
|
|
NtQuerySystemInformation(
|
|
SystemDeviceInformation,
|
|
&SystemInfo,
|
|
sizeof(SYSTEM_DEVICE_INFORMATION),
|
|
NULL
|
|
);
|
|
ValueLength = 2;
|
|
break;
|
|
}
|
|
|
|
switch ( DeviceInformationIndex ) {
|
|
|
|
case DDC_NUMBER_PRINTERS:
|
|
|
|
Value = SystemInfo.NumberOfParallelPorts;
|
|
break;
|
|
|
|
case DDC_NUMBER_RS232_PORTS:
|
|
|
|
Value = SystemInfo.NumberOfSerialPorts;
|
|
break;
|
|
|
|
case DDC_NUMBER_DISKETTE_DRIVES:
|
|
|
|
Value = SystemInfo.NumberOfFloppies;
|
|
break;
|
|
|
|
case DDC_MATH_COPROCESSOR:
|
|
|
|
RtlInitUnicodeString(&WorkName,
|
|
L"\\registry\\machine\\hardware\\description\\system\\floatingpointprocessor"
|
|
);
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&WorkName,
|
|
0,
|
|
(HANDLE) 0,
|
|
NULL);
|
|
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
|
|
status = NtOpenKey(&Handle,
|
|
MAXIMUM_ALLOWED,
|
|
&ObjectAttributes);
|
|
if (NT_SUCCESS(status)) {
|
|
FPUinit_unmask = TRUE;
|
|
Value = TRUE;
|
|
}
|
|
else {
|
|
Value = FALSE;
|
|
}
|
|
break;
|
|
|
|
case DDC_PC_SUBMODEL_TYPE:
|
|
|
|
Value = 0;
|
|
break;
|
|
|
|
case DDC_PC_MODEL_TYPE:
|
|
|
|
Value = 0xf8; // Return as a PS/2 Model 80
|
|
break;
|
|
|
|
case DDC_PRIMARY_DISPLAY_TYPE:
|
|
|
|
Value = 1; // Return as a non-monochrome display
|
|
break;
|
|
|
|
case DDC_COPROCESSORTYPE:
|
|
|
|
Value = 1;
|
|
break;
|
|
|
|
//
|
|
// Return an error if invalid index specified.
|
|
//
|
|
|
|
default:
|
|
return( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
//
|
|
// Now store the value in the caller's buffer using the correct
|
|
// alignment and size. Since this API does not have a Length parameter
|
|
// no checking is done to see if user buffer is big enough.
|
|
//
|
|
|
|
try {
|
|
switch ( ValueLength ) {
|
|
case 1:
|
|
*(PUCHAR)DeviceInformation = (UCHAR)Value;
|
|
break;
|
|
|
|
case 2:
|
|
*(PUSHORT)DeviceInformation = (USHORT)Value;
|
|
break;
|
|
|
|
case 4:
|
|
*(PULONG)DeviceInformation = (ULONG)Value;
|
|
break;
|
|
|
|
//
|
|
// Internal error if we get here
|
|
//
|
|
|
|
default:
|
|
DbgBreakPoint();
|
|
return( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|
Od2ExitGP();
|
|
}
|
|
|
|
//
|
|
// Return success
|
|
//
|
|
|
|
return( NO_ERROR );
|
|
}
|