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.
1793 lines
42 KiB
1793 lines
42 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dllpmnt.c
|
|
|
|
Abstract:
|
|
|
|
This module contains various calls needed internally for PM/NT
|
|
|
|
Author:
|
|
|
|
Patrick Questembert (PatrickQ) 20-July-1992
|
|
|
|
Revision History:
|
|
|
|
Patrick Questembert (PatrickQ) 13-Oct-1993:
|
|
Add support for 2nd frame buffer selector.
|
|
|
|
--*/
|
|
|
|
#if PMNT /* If not for PMNT build, yield just an empty file */
|
|
|
|
#define INCL_OS2V20_ERRORS
|
|
#include "os2dll.h"
|
|
#include "os2dll16.h"
|
|
#include "crt/stdio.h"
|
|
#include "crt/stdlib.h"
|
|
#include "os2sub.h"
|
|
|
|
#define INCL_32BIT
|
|
#include "pmnt.h"
|
|
#include "os2win.h"
|
|
#include "sesport.h"
|
|
|
|
#include "os2crt.h"
|
|
|
|
#include <ntexapi.h>
|
|
|
|
extern APIRET DosSemRequest(HSEM hsem, LONG lTimeout);
|
|
extern APIRET PMNTAllocLDTSelector(ULONG BaseAddress, ULONG cbSize, PSEL pSel);
|
|
extern APIRET VioGetConfig(ULONG usConfigId,PVIOCONFIGINFO Config,ULONG hVio);
|
|
extern APIRET VioGetCp(ULONG usReserved,PUSHORT pIdCodePage,ULONG hVio);
|
|
extern APIRET PMNTIsSessionRoot(void);
|
|
extern VOID PMNTRemoveCloseMenuItem(void); // os2ses\os2.c
|
|
|
|
extern LONG ScreenX;
|
|
extern LONG ScreenY;
|
|
BOOLEAN PMNTRegisteredDisplayAdapter = FALSE;
|
|
extern HANDLE Ow2ForegroundWindow;
|
|
|
|
ULONG PMFlags = 0;
|
|
ULONG PMSubprocSem32;
|
|
|
|
HANDLE hPMNTDevice = NULL;
|
|
|
|
BOOLEAN
|
|
SetProcessShutdownParameters(
|
|
DWORD dwLevel,
|
|
DWORD dwFlags
|
|
);
|
|
|
|
// Defined in public\sdk\inc\winuser.h
|
|
#define SW_HIDE 0
|
|
|
|
BOOLEAN
|
|
ShowWindow(
|
|
HANDLE hWnd,
|
|
int nCmdShow);
|
|
|
|
APIRET
|
|
InitPMNTDevice()
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
STRING NameString;
|
|
UNICODE_STRING UnicodeString;
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
RtlInitString( &NameString, PMNTDD_DEVICE_NAME );
|
|
|
|
Status = RtlAnsiStringToUnicodeString(&UnicodeString,
|
|
&NameString,
|
|
TRUE );
|
|
ASSERT( NT_SUCCESS( Status ) );
|
|
|
|
InitializeObjectAttributes( &ObjectAttributes,
|
|
&UnicodeString,
|
|
0,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = NtOpenFile( &hPMNTDevice,
|
|
SYNCHRONIZE, // | FILE_READ_DATA | FILE_WRITE_DATA,
|
|
// FILE_READ_DATA | FILE_WRITE_DATA,
|
|
&ObjectAttributes,
|
|
&IoStatus,
|
|
0,
|
|
FILE_SYNCHRONOUS_IO_NONALERT
|
|
);
|
|
|
|
RtlFreeUnicodeString( &UnicodeString );
|
|
|
|
if ( !NT_SUCCESS( Status ) )
|
|
{
|
|
KdPrint(("InitPMNTDevice: NtOpenFile failed, ret=%x\n", Status));
|
|
return (Status);
|
|
}
|
|
|
|
return( NO_ERROR );
|
|
}
|
|
|
|
APIRET
|
|
PMNTRegisterDisplayAdapter(
|
|
PMNT_IOPM_DATA *pMemory,
|
|
PMNT_IOPM_DATA *pPorts,
|
|
ULONG col,
|
|
ULONG row)
|
|
{
|
|
ULONG MemoryStructSize, PortsStructSize;
|
|
PVOID AdapterInfo;
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
ScreenX = (LONG)col;
|
|
ScreenY = (LONG)row;
|
|
PMNTRegisteredDisplayAdapter = TRUE;
|
|
|
|
MemoryStructSize = FIELD_OFFSET(PMNT_IOPM_DATA,Entry)
|
|
+ sizeof(pMemory->Entry[0]) * pMemory->NumEntries;
|
|
PortsStructSize = FIELD_OFFSET(PMNT_IOPM_DATA,Entry)
|
|
+ sizeof(pPorts->Entry[0]) * pPorts->NumEntries;
|
|
|
|
// Allocate room for both structures
|
|
AdapterInfo = (PVOID)RtlAllocateHeap(Od2Heap, 0,
|
|
MemoryStructSize + PortsStructSize);
|
|
|
|
if (AdapterInfo == NULL)
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTRegisterDisplayAdapter: failed to allocate memory for structure\n");
|
|
DbgPrint(" MemoryStructSize=%x, PortsStructSize=%x\n",
|
|
MemoryStructSize,
|
|
PortsStructSize);
|
|
#endif
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
//Copy memory structure
|
|
RtlMoveMemory(AdapterInfo,
|
|
pMemory,
|
|
MemoryStructSize);
|
|
//Copy ports structure
|
|
RtlMoveMemory((char *)AdapterInfo + MemoryStructSize,
|
|
pPorts,
|
|
PortsStructSize);
|
|
|
|
if (hPMNTDevice == NULL)
|
|
{
|
|
if (InitPMNTDevice() != NO_ERROR)
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTRegisterDisplayAdapter: failed to open PMNTDD.SYS\n");
|
|
#endif
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
}
|
|
}
|
|
|
|
Status = NtDeviceIoControlFile( hPMNTDevice,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_PMNTDD_REGISTER_HARDWARE,
|
|
(void *)AdapterInfo, // input buffer
|
|
MemoryStructSize + PortsStructSize, // in buffer length
|
|
NULL, // out buffer
|
|
0 // out buffer length
|
|
);
|
|
|
|
RtlFreeHeap(Od2Heap, 0, AdapterInfo);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTRegisterDisplayAdapter: failed to perform IOCTL, Status=%x\n",
|
|
Status);
|
|
#endif
|
|
return ERROR_ACCESS_DENIED;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
APIRET
|
|
PMNTIOMap()
|
|
{
|
|
ULONG DummyHandle = 0L;
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
if (hPMNTDevice == NULL)
|
|
{
|
|
if (InitPMNTDevice() != NO_ERROR)
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTRegisterDisplayAdapter: failed to open PMNTDD.SYS\n");
|
|
#endif
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
}
|
|
}
|
|
|
|
Status = NtDeviceIoControlFile( hPMNTDevice,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_PMNTDD_IO_MAP,
|
|
(void *)&DummyHandle, // input buffer
|
|
sizeof(DummyHandle), // in buffer length
|
|
NULL, // out buffer
|
|
0 // out buffer length
|
|
);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
return NO_ERROR;
|
|
else
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTIOMap: NtDeviceIoControl failed, Status=%x\n",
|
|
Status);
|
|
#endif
|
|
return (Or2MapNtStatusToOs2Error(Status, ERROR_ACCESS_DENIED));
|
|
}
|
|
}
|
|
|
|
// Remembers the screen selector returned by PMNTDD.SYS. If PMNTMemMap() is
|
|
// called twice within the same process, the selector will be returned without
|
|
// calling PMNTDD.SYS again
|
|
SEL ScreenSelector = 0;
|
|
|
|
APIRET
|
|
PMNTMemMap(
|
|
PSEL pSel)
|
|
{
|
|
ULONG RequestedVirtualAddresses[2];
|
|
PMNT_MEMMAP_RESULTS ResultVirtualAddresses[2];
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
if (ScreenSelector != 0)
|
|
{
|
|
try
|
|
{
|
|
Od2ProbeForWrite(pSel, sizeof(SEL), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
Od2ExitGP();
|
|
}
|
|
#if DBG
|
|
DbgPrint("PMNTMemMap called 2nd time for process - returning saved selector %x\n",
|
|
ScreenSelector);
|
|
#endif
|
|
*pSel = ScreenSelector;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Specify 2 virtual addresses, in case the display adapter has 2 frame
|
|
// buffer sections instead of one. The resulting virtual addresses structure
|
|
// will indicate how many are actually needed (a 2nd virtual address of 0
|
|
// will indicate that only one is needed).
|
|
RequestedVirtualAddresses[0] = PMDISPLAY_BASE1;
|
|
RequestedVirtualAddresses[1] = PMDISPLAY_BASE2;
|
|
|
|
if (hPMNTDevice == NULL)
|
|
{
|
|
if (InitPMNTDevice() != NO_ERROR)
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNT_IOCTL: failed to open PMNTDD\n");
|
|
#endif
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
}
|
|
}
|
|
|
|
Status = NtDeviceIoControlFile( hPMNTDevice,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
IOCTL_PMNTDD_MEM_MAP,
|
|
(void *)&RequestedVirtualAddresses,// input buffer
|
|
sizeof(RequestedVirtualAddresses), // in buffer length
|
|
(void *)ResultVirtualAddresses, // out buffer
|
|
sizeof(ResultVirtualAddresses) // out buffer length
|
|
);
|
|
|
|
if NT_SUCCESS(Status)
|
|
{
|
|
APIRET rc;
|
|
|
|
try
|
|
{
|
|
Od2ProbeForWrite(pSel, sizeof(SEL), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
Od2ExitGP();
|
|
}
|
|
|
|
// Allocate a LDT selector for the first selector. It is expected that
|
|
// first VirtualAddress is PMDISPLAY_BASE1 (+ some offset if address
|
|
// wasn't 64K-aligned)
|
|
|
|
rc = PMNTAllocLDTSelector(
|
|
ResultVirtualAddresses[0].VirtualAddress,
|
|
ResultVirtualAddresses[0].Length,
|
|
pSel);
|
|
if (rc != NO_ERROR)
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTDDIoctl: Error, PMNTAllocLDTSelector#1 failed\n");
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
else
|
|
{
|
|
ScreenSelector = *pSel; // Remember for next time !
|
|
// Is there a 2nd selector to map ?
|
|
if (ResultVirtualAddresses[1].VirtualAddress != 0)
|
|
{
|
|
SEL DummySEL; // Just to keep PMNTAllocLDTSelector happy
|
|
|
|
// Allocate a LDT selector for the 2nd selector. It is expected
|
|
// that the 2nd VirtualAddress is PMDISPLAY_BASE2 (+ some
|
|
// offset if address wasn't 64K-aligned)
|
|
|
|
rc = PMNTAllocLDTSelector(
|
|
ResultVirtualAddresses[1].VirtualAddress,
|
|
ResultVirtualAddresses[1].Length,
|
|
&DummySEL);
|
|
#if DBG
|
|
if (rc != NO_ERROR)
|
|
{
|
|
DbgPrint("PMNTDDIoctl: Error, PMNTAllocLDTSelector#2 failed\n");
|
|
}
|
|
#endif
|
|
|
|
return rc;
|
|
}
|
|
else
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTMemMap: IOCTL to PMNTDD.SYS failed, Status=%x\n",
|
|
Status);
|
|
#endif
|
|
return (Or2MapNtStatusToOs2Error(Status, ERROR_ACCESS_DENIED));
|
|
}
|
|
}
|
|
|
|
APIRET
|
|
PMNTDDIoctl(
|
|
ULONG request,
|
|
PVOID input_buffer,
|
|
ULONG input_buffer_length,
|
|
PVOID output_buffer,
|
|
ULONG output_buffer_length
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
|
|
if (hPMNTDevice == NULL)
|
|
{
|
|
if (InitPMNTDevice() != NO_ERROR)
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNT_IOCTL: failed to open PMNTDD\n");
|
|
#endif
|
|
|
|
return ERROR_ACCESS_DENIED;
|
|
}
|
|
}
|
|
|
|
Status = NtDeviceIoControlFile( hPMNTDevice,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
request,
|
|
input_buffer,
|
|
input_buffer_length,
|
|
output_buffer,
|
|
output_buffer_length
|
|
);
|
|
|
|
if NT_SUCCESS(Status)
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
return (Or2MapNtStatusToOs2Error(Status, ERROR_ACCESS_DENIED));
|
|
}
|
|
}
|
|
|
|
APIRET
|
|
PMNTIoctl(
|
|
ULONG request,
|
|
PVOID input_pointer,
|
|
PVOID output_pointer
|
|
)
|
|
{
|
|
PMNT_IOCTL_DD_IOCTL_PARAMS *ptr;
|
|
|
|
UNREFERENCED_PARAMETER(output_pointer);
|
|
|
|
switch (request)
|
|
{
|
|
//PatrickQ 12-29-95 Hook for the CBA to make WIN32 Console window invisible
|
|
case PMNT_IOCTL_HIDE_WIN32_WINDOW:
|
|
if (!ShowWindow(Ow2ForegroundWindow, SW_HIDE))
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTIoctl: ShowWindow(%x) failed\n", Ow2ForegroundWindow);
|
|
#endif
|
|
}
|
|
break;
|
|
case PMNT_IOCTL_DD_IOCTL: /* PMNTDD IOCTL's */
|
|
ptr = (PMNT_IOCTL_DD_IOCTL_PARAMS *)input_pointer;
|
|
// BUGBUG - Check input & output pointers against advertised length
|
|
return (PMNTDDIoctl(
|
|
CTL_CODE((unsigned long)PMNTDD_DEVICE_TYPE, ptr->Request,, METHOD_BUFFERED, FILE_ANY_ACCESS), /* Request */
|
|
FARPTRTOFLAT(ptr->InputBuffer),
|
|
ptr->InputBufferLength,
|
|
FARPTRTOFLAT(ptr->OutputBuffer),
|
|
ptr->OutputBufferLength
|
|
));
|
|
|
|
#if DBG
|
|
case PMNT_IOCTL_DUMP_SEGMENT_TABLE:
|
|
{
|
|
OS2_API_MSG m;
|
|
P_LDRDUMPSEGMENTS_MSG a = &m.u.LdrDumpSegments;
|
|
|
|
Od2CallSubsystem( &m, NULL, Ol2LdrDumpSegments, sizeof( *a ) );
|
|
return NO_ERROR;
|
|
}
|
|
#endif
|
|
default:
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
//PatrickQ - so that break statements above don't return random return-code
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID
|
|
validate_user_str(
|
|
char **ptr)
|
|
{
|
|
if (*ptr == NULL)
|
|
{
|
|
*ptr = "(null)";
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
int tmp;
|
|
tmp = strlen(*ptr);
|
|
}
|
|
except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DbgPrint("PMNTDbgPrint: warning - illegal string parameter - %x:%x\n",
|
|
FLATTOSEL(*ptr),
|
|
(ULONG)ptr & 0xFFFF);
|
|
*ptr = "(illegal string)";
|
|
return;
|
|
}
|
|
}
|
|
|
|
APIRET
|
|
PMNTDbgPrompt(
|
|
PCHAR MessageStr,
|
|
PCHAR OutputStr,
|
|
ULONG Len
|
|
)
|
|
{
|
|
try
|
|
{
|
|
if (MessageStr == NULL)
|
|
return (DbgPrompt("", OutputStr, Len));
|
|
else
|
|
return (DbgPrompt(MessageStr, OutputStr, Len));
|
|
}
|
|
except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
Od2ExitGP();
|
|
}
|
|
return NO_ERROR;
|
|
}
|
|
|
|
void
|
|
PMNTDbgPrint(
|
|
char *str,
|
|
ULONG l1,
|
|
ULONG l2,
|
|
ULONG l3,
|
|
ULONG l4
|
|
)
|
|
{
|
|
ULONG r1, r2, r3, r4;
|
|
char *ptr=str, percent=0;
|
|
int param=1, i, str_length;
|
|
char *print_buffer = NULL;
|
|
char tmp_buf[512];
|
|
|
|
//So that we can see what has been sprintf'ed before problem
|
|
for (i=0; i<512; i++) tmp_buf[i]='\0';
|
|
|
|
// Using sprintf() because richer in formats. Also, DbgPrint hits a break-
|
|
// point when called with bad pointer.
|
|
|
|
//Validate string itself
|
|
try
|
|
{
|
|
str_length = strlen(str);
|
|
}
|
|
except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DbgPrint("PMNTDbgPrint: illegal string - %x:%x",
|
|
FLATTOSEL(str),
|
|
(ULONG)str & 0xFFFF);
|
|
return;
|
|
}
|
|
|
|
// Look for %s (need to xlate address if that's the case)
|
|
while (*ptr)
|
|
{
|
|
if (*ptr == '%')
|
|
{
|
|
percent = !percent;
|
|
}
|
|
else if (percent)
|
|
{
|
|
percent = 0;
|
|
if (*ptr == 's')
|
|
{
|
|
switch (param)
|
|
{
|
|
case 1:
|
|
r1 = (ULONG)FARPTRTOFLAT(l1);
|
|
validate_user_str(&(char *)r1);
|
|
break;
|
|
case 2:
|
|
r2 = (ULONG)FARPTRTOFLAT(l2);
|
|
validate_user_str(&(char *)r2);
|
|
break;
|
|
case 3:
|
|
r3 = (ULONG)FARPTRTOFLAT(l3);
|
|
validate_user_str(&(char *)r3);
|
|
break;
|
|
case 4:
|
|
r4 = (ULONG)FARPTRTOFLAT(l4);
|
|
validate_user_str(&(char *)r4);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (param)
|
|
{
|
|
case 1:
|
|
r1 = l1;
|
|
break;
|
|
case 2:
|
|
r2 = l2;
|
|
break;
|
|
case 3:
|
|
r3 = l3;
|
|
break;
|
|
case 4:
|
|
r4 = l4;
|
|
break;
|
|
}
|
|
}
|
|
param++;
|
|
}
|
|
ptr++;
|
|
}
|
|
|
|
try
|
|
{
|
|
int i;
|
|
|
|
if (str_length >= 512)
|
|
{
|
|
print_buffer = RtlAllocateHeap(Od2Heap, 0, str_length + 1);
|
|
sprintf(print_buffer, str, r1, r2, r3, r4);
|
|
for (i=0; i<str_length;)
|
|
{
|
|
strncpy(tmp_buf, print_buffer + i, 256);
|
|
// strncpy() doesn't append a \0 when count is reached
|
|
tmp_buf[256] = '\0';
|
|
i += 256; // may be less at the end of the string but we just
|
|
// need to make i > str_length so that's fine
|
|
DbgPrint(tmp_buf);
|
|
}
|
|
RtlFreeHeap(Od2Heap, 0, print_buffer);
|
|
}
|
|
else
|
|
{
|
|
sprintf(tmp_buf, str, r1, r2, r3, r4);
|
|
DbgPrint(tmp_buf);
|
|
}
|
|
}
|
|
except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
DbgPrint("PMNTDbgPrint: access violation calling sprintf()\n");
|
|
DbgPrint("str = %x:%x, l1=%x, l2=%x, l3=%x, l4=%x\n",
|
|
FLATTOSEL(str),
|
|
(ULONG)str & 0xFFFF,
|
|
l1,
|
|
l2,
|
|
l3,
|
|
l4);
|
|
DbgPrint("tmp_buf=%s, r1=%x, r2=%x, r3=%x, r4=%x\n",
|
|
tmp_buf,
|
|
r1,
|
|
r2,
|
|
r3,
|
|
r4);
|
|
if (print_buffer != NULL)
|
|
RtlFreeHeap(Od2Heap, 0, print_buffer);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Just to resolve entry. This call is used by DISPLAY.DLL:
|
|
- called by pmdisp\egafam\egavga\egainit.asm, ring3_VioGetPSAddress()
|
|
- ring3_VioGetPSAddress() is called (indirectly, via a ring3_GetPSAddress()
|
|
ULONG variable) by pmdisp\egafam\cellblt.asm, DeviceSetAVIOFont2() routine
|
|
*/
|
|
ULONG
|
|
VioGetPSAddress(void)
|
|
{
|
|
KdPrint(("VioGetPSAddress: not implemented yet\n"));
|
|
|
|
return 0L;
|
|
}
|
|
|
|
VOID
|
|
DosSetFgnd(
|
|
ULONG Level,
|
|
ULONG Tid
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(Level);
|
|
UNREFERENCED_PARAMETER(Tid);
|
|
|
|
// KdPrint(("DosSetFgnd(%d,%d): not implemented yet\n",
|
|
// Level, Tid));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
DosSystemService(void)
|
|
{
|
|
KdPrint(("DosSystemService (DOSCALLS.88): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
APIRET
|
|
VioRedrawSize(
|
|
PULONG pRedrawSize)
|
|
{
|
|
try
|
|
{
|
|
*pRedrawSize = 0xFFFFFFFF;
|
|
} except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
Od2ExitGP();
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
APIRET
|
|
PMNTGetPgmName(
|
|
PSZ Buffer,
|
|
ULONG BufferLength)
|
|
{
|
|
Od2ProbeForWrite(Buffer,BufferLength,1);
|
|
if (BufferLength > 1)
|
|
{
|
|
strncpy(Buffer,Od2Process->ApplName,BufferLength);
|
|
Buffer[BufferLength-1]='\0';
|
|
}
|
|
else
|
|
{
|
|
if (BufferLength == 1) Buffer[0]='\0';
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
extern ULONG Ow2bNewSession;
|
|
|
|
DECLARE_HANDLE(HKEY);
|
|
typedef HKEY *PHKEY;
|
|
#define HKEY_LOCAL_MACHINE (( HKEY ) 0x80000002 )
|
|
typedef ACCESS_MASK REGSAM;
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegOpenKeyExA (
|
|
HKEY hKey,
|
|
LPCSTR lpSubKey,
|
|
DWORD ulOptions,
|
|
REGSAM samDesired,
|
|
PHKEY phkResult
|
|
);
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegQueryValueExA (
|
|
HKEY hKey,
|
|
LPCSTR lpValueName,
|
|
PULONG lpReserved,
|
|
PULONG lpType,
|
|
PBYTE lpData,
|
|
PULONG lpcbData
|
|
);
|
|
|
|
LONG
|
|
APIENTRY
|
|
RegCloseKey (
|
|
HKEY hKey
|
|
);
|
|
|
|
#define PMSHELL_TITLE_LEN 40
|
|
|
|
APIRET
|
|
PMNTSetConsoleTitle(
|
|
PSZ Buffer)
|
|
{
|
|
CHAR BufferTmp[PMSHELL_TITLE_LEN];
|
|
DWORD cb;
|
|
DWORD type;
|
|
HKEY hkey;
|
|
|
|
try
|
|
{
|
|
Od2ProbeForRead(Buffer,1,1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTSetConsoleTile: error, bad pointer parameter\n");
|
|
#endif
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
// Note that the code below also takes care that the Print Manager won't
|
|
// set the console title unless started independently because if PMSPOOL
|
|
// was started by PMShell, it won't be a new session
|
|
|
|
if (OS2SS_IS_NEW_SESSION( Ow2bNewSession )) {
|
|
if (ProcessIsPMShell()) {
|
|
if (!RegOpenKeyExA(
|
|
HKEY_LOCAL_MACHINE,
|
|
"SOFTWARE\\Microsoft\\OS/2 Subsystem for NT\\1.0\\PMSHELL",
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&hkey
|
|
))
|
|
{
|
|
DWORD RemoveCloseMenuItem = 0;
|
|
|
|
// Found key SOFTWARE\Microsoft\OS/2 Subsystem for NT\1.0\PMSHELL
|
|
cb = PMSHELL_TITLE_LEN-1;
|
|
if (!RegQueryValueExA(
|
|
hkey,
|
|
"Title",
|
|
NULL,
|
|
&type,
|
|
BufferTmp,
|
|
&cb
|
|
))
|
|
{
|
|
BufferTmp[cb] = '\0';
|
|
Buffer = BufferTmp;
|
|
}
|
|
|
|
cb = sizeof(DWORD);
|
|
if (!RegQueryValueExA(
|
|
hkey,
|
|
"RemoveCloseMenuItem",
|
|
NULL,
|
|
&type,
|
|
&RemoveCloseMenuItem,
|
|
&cb
|
|
))
|
|
{
|
|
if (RemoveCloseMenuItem)
|
|
{
|
|
// PatrickQ 5/2/96.This option means we don't want to
|
|
// allow user to select the close system menu option
|
|
// on PMShell - Required by CBA
|
|
PMNTRemoveCloseMenuItem();
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
if (Buffer != BufferTmp) {
|
|
Buffer = "PM Shell";
|
|
}
|
|
}
|
|
|
|
|
|
if (SetConsoleTitleA(Buffer))
|
|
return(NO_ERROR);
|
|
else
|
|
return(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
APIRET
|
|
PMNTSetPMShellFlag()
|
|
{
|
|
|
|
if (!ProcessIsPMShell())
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTSetPMShellFlag: internal error, flag wasn't set !!!\n");
|
|
#endif
|
|
SetPMShellFlag();
|
|
}
|
|
|
|
// Let PMShell go down first on logoff/shutdown
|
|
// Default priority for apps is 0x280
|
|
SetProcessShutdownParameters(0x290L, 0);
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
APIRET
|
|
PMNTSetSubprocSem(HSEM hsem)
|
|
{
|
|
|
|
PMSubprocSem32 = (ULONG)hsem;
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
ULONG
|
|
FindWindowA(
|
|
PSZ lpClassName ,
|
|
PSZ lpWindowName);
|
|
|
|
ULONG
|
|
PMNTGetOurWindow()
|
|
{
|
|
DWORD SavedTitleLength = 0;
|
|
UCHAR SavedTitle[256];
|
|
NTSTATUS Status;
|
|
PROCESS_BASIC_INFORMATION ProcessInfo;
|
|
UCHAR UniqueTitle[256] = { 'O', 'S', '2' , 'S', 'S', ':', '\0' };
|
|
ULONG Hwnd = 0;
|
|
DWORD StartingMsec;
|
|
|
|
// No need to figure out our window handle for non-root OS/2 ss programs
|
|
if (!PMNTIsSessionRoot())
|
|
return (0);
|
|
|
|
/**********************************
|
|
* Save the current Console title *
|
|
**********************************/
|
|
|
|
SavedTitleLength = GetConsoleTitleA(SavedTitle,256);
|
|
|
|
if (SavedTitleLength == 0)
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTGetOurWindow: GetConsoleTitle failed, error=0x%x\n",
|
|
GetLastError());
|
|
#endif
|
|
return (0);
|
|
}
|
|
|
|
SavedTitle[255]='\0';
|
|
|
|
Status = NtQueryInformationProcess(
|
|
NtCurrentProcess(),
|
|
ProcessBasicInformation,
|
|
(PVOID)(&ProcessInfo),
|
|
sizeof(ProcessInfo),
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTGetOurWindow: NtQueryInformationProcess failed, Status == %X\n",
|
|
Status);
|
|
#endif // DBG
|
|
return (0);
|
|
}
|
|
|
|
// Make a string out of the PID
|
|
ltoa(ProcessInfo.UniqueProcessId,
|
|
UniqueTitle+strlen(UniqueTitle),
|
|
16);
|
|
|
|
if (!SetConsoleTitleA(UniqueTitle))
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTGetOurWindow: SetConsoleTitle failed, error=0x%x\n",
|
|
GetLastError());
|
|
#endif
|
|
return (0);
|
|
}
|
|
|
|
//PQPQ 12/28/95 - Just try to find the window once. If you fail, don't worry
|
|
// about it. The loop previously used to get the window handle created a
|
|
// problem with Yosef's fix for the CBA to allow turning DosStartSession
|
|
// calls into background execution in the same session. This happened
|
|
// because sibling processes reset the console title to other strings so we
|
|
// failed to find the temporary string among the existing windows.
|
|
Hwnd = (ULONG)FindWindowA("ConsoleWindowClass", UniqueTitle);
|
|
|
|
|
|
#if 0 //PQPQ
|
|
StartingMsec = GetTickCount();
|
|
while (!(Hwnd = (ULONG)FindWindowA("ConsoleWindowClass", UniqueTitle)))
|
|
{
|
|
// Don't spend more than 60 seconds trying to get the window handle
|
|
if ((GetTickCount() - StartingMsec) > 60000)
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTGetOurWindow: giving up on trying to find our window handle, error=0x%x\n",
|
|
GetLastError());
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
#endif //PQPQ
|
|
|
|
/*****************************
|
|
* Restore the Console title *
|
|
*****************************/
|
|
|
|
if (!SetConsoleTitleA(SavedTitle))
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTGetOurWindow: SetConsoleTitle(%s) failed, error=0x%x\n",
|
|
SavedTitle,
|
|
GetLastError());
|
|
#endif
|
|
}
|
|
return (Hwnd);
|
|
}
|
|
|
|
APIRET
|
|
PMNTQueryScreenSize(PUSHORT xRight, PUSHORT yTop)
|
|
{
|
|
if (!PMNTRegisteredDisplayAdapter)
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTQueryScreenSize: ERROR, called before PMNTRegisterDisplayAdapter() !\n");
|
|
#endif
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
try
|
|
{
|
|
*xRight = (USHORT)ScreenX;
|
|
*yTop = (USHORT)ScreenY;
|
|
} except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
return (ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
APIRET
|
|
PMNTProcessIsPMShell()
|
|
{
|
|
return(ProcessIsPMShell());
|
|
}
|
|
|
|
#pragma pack(1)
|
|
// OS/2 structure => aligned to 1
|
|
typedef struct _WHOISINFO { /* whois */
|
|
USHORT segNum;
|
|
USHORT mte;
|
|
char names[ 256 ];
|
|
} WHOISINFO;
|
|
#pragma pack()
|
|
|
|
APIRET
|
|
PMNTIdentifyCodeSelector(
|
|
SEL Sel,
|
|
WHOISINFO *pWhois)
|
|
{
|
|
OS2_API_MSG m;
|
|
P_LDRIDENTIFYCODESELECTOR_MSG a = &m.u.LdrIdentifyCodeSelector;
|
|
POS2_CAPTURE_HEADER CaptureBuffer;
|
|
|
|
try
|
|
{
|
|
Od2ProbeForWrite(pWhois, sizeof(WHOISINFO), 1);
|
|
} except( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
Od2ExitGP();
|
|
}
|
|
|
|
CaptureBuffer = Od2AllocateCaptureBuffer(
|
|
1,
|
|
0,
|
|
256
|
|
);
|
|
|
|
if (CaptureBuffer == NULL)
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTIdentifyCodeSelector: Od2AllocateCaptureBuffer failed\n");
|
|
#endif
|
|
return NO_ERROR;
|
|
}
|
|
|
|
Od2CaptureMessageString( CaptureBuffer,
|
|
NULL,
|
|
0,
|
|
256,
|
|
&a->ModName
|
|
);
|
|
|
|
a->sel = Sel;
|
|
|
|
Od2CallSubsystem( &m, CaptureBuffer, Op2IdentifyCodeSelector, sizeof( *a ) );
|
|
|
|
pWhois->segNum = a->segNum;
|
|
pWhois->mte = a->mte;
|
|
// Do not exceed size of names field (256)
|
|
strncpy(pWhois->names, a->ModName.Buffer, 256);
|
|
|
|
Od2FreeCaptureBuffer( CaptureBuffer );
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID
|
|
PMNTGetSystemTime(
|
|
PULONG pTime)
|
|
{
|
|
LARGE_INTEGER tm;
|
|
NTSTATUS Status;
|
|
|
|
Status = NtQuerySystemTime(
|
|
&tm
|
|
);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
#if DBG
|
|
DbgPrint("PMNTGetSystemTime: failed, Status=%x\n", Status);
|
|
#endif
|
|
*pTime = 0;
|
|
return;
|
|
}
|
|
|
|
*pTime = tm.LowPart / 10000L;
|
|
}
|
|
|
|
APIRET
|
|
PMNTVioGetConfig( IN ULONG usConfigId, // this is no longer reserved value
|
|
IN OUT PVIOCONFIGINFO Config,
|
|
IN ULONG hVio)
|
|
{
|
|
return(VioGetConfig(usConfigId,Config,hVio));
|
|
}
|
|
|
|
APIRET
|
|
PMNTVioGetCp( IN ULONG usReserved,
|
|
OUT PUSHORT pIdCodePage,
|
|
IN ULONG hVio)
|
|
{
|
|
return(VioGetCp(usReserved,pIdCodePage,hVio));
|
|
}
|
|
|
|
VOID
|
|
DosSysTrace(void)
|
|
{
|
|
KdPrint(("DosSysTrace (DOSCALLS.90): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
APIRET
|
|
DosSMPause()
|
|
{
|
|
KdPrint(("DosSMPause (SESMGR.26): not implemented yet\n"));
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
APIRET
|
|
MouInitReal(PSZ pszDriverName)
|
|
{
|
|
UNREFERENCED_PARAMETER(pszDriverName);
|
|
|
|
#if DBG
|
|
//
|
|
// bvscalls may call it from bvsdinit.c during VioShellInit()
|
|
// anyway as metioned in the programmer's reference:
|
|
// "The function is used only by the task manager"
|
|
// which we do not implement
|
|
//
|
|
if (!ProcessIsPMShell()) {
|
|
DbgPrint("MouInitReal (MOUCALLS.27): not implemented yet\n");
|
|
}
|
|
#endif
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
#if 0
|
|
// Spring cleaning - APIs no longer needed
|
|
VOID
|
|
QHKeybdHandle(void)
|
|
{
|
|
KdPrint(("QHKeybdHandle (SESMGR.34): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
QHMouseHandle(void)
|
|
{
|
|
KdPrint(("QHMouseHandle (SESMGR.35): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
DosIRamSemWake(void)
|
|
{
|
|
KdPrint(("DosIRamSemWake (DOSCALLS.125): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
// DOSCALLS.18
|
|
APIRET
|
|
DosISemRequest(
|
|
IN HSEM hsem,
|
|
IN LONG lTimeout
|
|
)
|
|
{
|
|
return DosSemRequest(hsem, lTimeout);
|
|
}
|
|
|
|
VOID
|
|
DosUnknownApi54(void)
|
|
{
|
|
KdPrint(("DosUknownApi54 (DOSCALLS.54): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
DosUnknownApi90(void)
|
|
{
|
|
KdPrint(("DosUknownApi90 (DOSCALLS.90): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
DosUnknownApi105(void)
|
|
{
|
|
KdPrint(("DosUknownApi105 (DOSCALLS.105): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
DosICopy(void)
|
|
{
|
|
KdPrint(("DosICopy (DOSCALLS.200): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
DosGiveSegList(void)
|
|
{
|
|
KdPrint(("DosGiveSegList (DOSCALLS.209): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
VioSSWSwitch(void)
|
|
{
|
|
KdPrint(("VioSSWSwitch (VIOCALLS.36): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
/* MOUCALLS.10 */
|
|
APIRET
|
|
MouSetHotKey(
|
|
IN ULONG p1,
|
|
IN ULONG p2,
|
|
IN ULONG hMou)
|
|
{
|
|
KdPrint(("MouSetHotKey (%x, %x, %x): not implemented yet\n", p1, p2, hMou));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
APIRET
|
|
KbdFree(
|
|
IN ULONG hkbd) //BUGBUG - not necessarily correct prototype, just a guess
|
|
{
|
|
KdPrint(("KbdFree (%x): not implemented yet\n",hkbd));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
APIRET
|
|
MouFree(
|
|
IN ULONG hMou) //BUGBUG - not necessarily correct prototype, just a guess
|
|
{
|
|
KdPrint(("MouFree (%x): not implemented yet\n",hMou));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
APIRET
|
|
VioFree(
|
|
IN ULONG hVio) //BUGBUG - not necessarily correct prototype, just a guess
|
|
{
|
|
KdPrint(("VioFree (%x): not implemented yet\n",hVio));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
/* DOSCALLS.55 */
|
|
APIRET
|
|
DosSGSwitchMe(
|
|
IN ULONG p1,
|
|
IN ULONG p2)
|
|
{
|
|
KdPrint(("DosSGSwitchMe(%d,%d): not implemented yet\n", p1, p2));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID
|
|
KbdSwitchFgnd(void)
|
|
{
|
|
KdPrint(("KbdSwitchFgnd (KBDCALLS.19): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
/* MOUCALLS.5 */
|
|
APIRET
|
|
MouShellInit(void)
|
|
{
|
|
KdPrint(("MouShellInit (MOUCALLS.5): not implemented yet\n"));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// VIOCALLS.54
|
|
APIRET
|
|
VioShellInit(
|
|
ULONG addr)
|
|
{
|
|
KdPrint(("VioShellInit (%x): not implemented yet\n", addr));
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
VOID
|
|
VioRestore(void)
|
|
{
|
|
KdPrint(("VioRestore (VIOCALLS.41): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
VioSave(void)
|
|
{
|
|
KdPrint(("VioSave (VIOCALLS.20): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
VioSRFunBlock(void)
|
|
{
|
|
KdPrint(("VioSRFunBlock (VIOCALLS.16): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
VioSRFBlock(void)
|
|
{
|
|
KdPrint(("VioSRFBlock (VIOCALLS.17): not implemented yet\n"));
|
|
return;
|
|
}
|
|
|
|
#endif // 0
|
|
|
|
#ifdef JAPAN // MSKK [ShigeO] Aug 10, 1993 Win32 font on PM/NT
|
|
|
|
/***************************************************************\
|
|
* FontHandles
|
|
*
|
|
* History:
|
|
* Aug 11, 1993 ShigeO Created
|
|
\***************************************************************/
|
|
#define MAX_FONTS 32
|
|
HANDLE ahFont[MAX_FONTS];
|
|
ULONG ulFontCount;
|
|
|
|
/***************************************************************\
|
|
* GetFontHandle()
|
|
*
|
|
* History:
|
|
* Aug 11, 1993 ShigeO Created
|
|
\***************************************************************/
|
|
HANDLE GetFontHandle(
|
|
ULONG ulFont)
|
|
{
|
|
if(ulFont && (ulFont <= ulFontCount)) {
|
|
return ahFont[ulFont-1];
|
|
}
|
|
return (HANDLE)0;
|
|
}
|
|
|
|
/***************************************************************\
|
|
* PutFontHandle()
|
|
*
|
|
* History:
|
|
* Aug 10, 1993 ShigeO Created
|
|
\***************************************************************/
|
|
ULONG PutFontHandle(
|
|
HANDLE hFont)
|
|
{
|
|
if(hFont && (ulFontCount < MAX_FONTS)) {
|
|
ahFont[ulFontCount++] = hFont;
|
|
return ulFontCount;
|
|
}
|
|
return 0L;
|
|
}
|
|
|
|
/***************************************************************\
|
|
* GetFontID()
|
|
*
|
|
* History:
|
|
* Aug 10, 1993 ShigeO Created
|
|
\***************************************************************/
|
|
ULONG GetFontID(
|
|
VOID)
|
|
{
|
|
if(ulFontCount < MAX_FONTS) {
|
|
return ulFontCount+1;
|
|
}
|
|
return 0L;
|
|
}
|
|
|
|
/***************************************************************\
|
|
* SelectFont()
|
|
*
|
|
* History:
|
|
* Aug 10, 1993 ShigeO Created
|
|
\***************************************************************/
|
|
HANDLE
|
|
SelectFont(
|
|
HANDLE hFont)
|
|
{
|
|
static HANDLE hFontPrev = (HANDLE)0;
|
|
static HANDLE hDC = (HANDLE)0;
|
|
HANDLE hFontTmp;
|
|
|
|
if(hFont == hFontPrev) {
|
|
return hDC;
|
|
}
|
|
if(!hDC && (!(hDC = CreateDCA("DISPLAY", NULL, NULL, NULL)))) {
|
|
return (HANDLE)0;
|
|
}
|
|
hFontTmp = SelectObject(hDC, hFont);
|
|
if(!hFontTmp || hFontTmp == (HANDLE)0xFFFFFFFFL) {
|
|
return (HANDLE)0;
|
|
}
|
|
hFontPrev = hFont;
|
|
return hDC;
|
|
}
|
|
|
|
/***************************************************************\
|
|
* PMNTCreateFontIndirect()
|
|
*
|
|
* History:
|
|
* Aug 10, 1993 ShigeO Created
|
|
\***************************************************************/
|
|
ULONG
|
|
PMNTCreateFontIndirect(
|
|
PVOID lplf)
|
|
{
|
|
HANDLE hFont;
|
|
|
|
if(!GetFontID()) {
|
|
return 0L;
|
|
}
|
|
if(!(hFont = CreateFontIndirectA(lplf))) {
|
|
return 0L;
|
|
}
|
|
return PutFontHandle(hFont);
|
|
}
|
|
|
|
/***************************************************************\
|
|
* PMNTGetTextMetrics()
|
|
*
|
|
* History:
|
|
* Aug 10, 1993 ShigeO Created
|
|
\***************************************************************/
|
|
ULONG
|
|
PMNTGetTextMetrics(
|
|
ULONG ulFont,
|
|
PVOID lptm)
|
|
{
|
|
HANDLE hDC;
|
|
HANDLE hFont;
|
|
|
|
if(!(hFont = GetFontHandle(ulFont))) {
|
|
return 0L;
|
|
}
|
|
if(!(hDC = SelectFont(hFont))) {
|
|
return 0L;
|
|
}
|
|
if(!(GetTextMetricsA(hDC, lptm))) {
|
|
return 0L;
|
|
}
|
|
return 1L;
|
|
}
|
|
|
|
/***************************************************************\
|
|
* PMNTGetFontBitmap()
|
|
*
|
|
* History:
|
|
* Aug 10, 1993 ShigeO Created
|
|
\***************************************************************/
|
|
ULONG
|
|
PMNTGetStringBitmap(
|
|
ULONG ulFont,
|
|
LPCSTR lpszStr,
|
|
UINT cbStr,
|
|
UINT cbData,
|
|
PVOID lpSB)
|
|
{
|
|
HANDLE hDC;
|
|
HANDLE hFont;
|
|
|
|
if(!(hFont = GetFontHandle(ulFont))) {
|
|
return 0L;
|
|
}
|
|
if(!(hDC = SelectFont(hFont))) {
|
|
return 0L;
|
|
}
|
|
if(!(GetStringBitmapA(hDC, lpszStr, cbStr, cbData, lpSB))) {
|
|
return 0L;
|
|
}
|
|
return 1L;
|
|
}
|
|
|
|
#endif // JAPAN
|
|
|
|
HANDLE hPMNTVDMEvent;
|
|
#ifndef PMNT_DAYTONA
|
|
HANDLE hPMNTVDMEvent1;
|
|
HANDLE hPMNTVDMEventReady;
|
|
#endif // not PMNT_DAYTONA
|
|
|
|
HANDLE
|
|
__stdcall
|
|
CreateEventW(
|
|
PVOID lpEventAttributes,
|
|
BOOL bManualReset,
|
|
BOOL bInitialState,
|
|
PVOID lpName
|
|
);
|
|
|
|
BOOLEAN
|
|
Os2InitializeVDMEvents()
|
|
{
|
|
//
|
|
// Create the global subsystem PMShell synchronization Nt event
|
|
// (create in the unsignalled state - when PMShell comes up, it will
|
|
// signal it)
|
|
//
|
|
|
|
hPMNTVDMEvent = CreateEventW(NULL,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
|
|
#ifndef PMNT_DAYTONA
|
|
|
|
//
|
|
// Create the 2nd global subsystem PMShell synchronization Nt event
|
|
// (create in the unsignalled state - when PMShell comes up, it will
|
|
// signal it)
|
|
//
|
|
|
|
hPMNTVDMEvent1 = CreateEventW(NULL,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
|
|
|
|
hPMNTVDMEventReady = CreateEventW(NULL,
|
|
FALSE,
|
|
FALSE,
|
|
NULL);
|
|
#endif // not PMNT_DAYTONA
|
|
|
|
if ((hPMNTVDMEvent == NULL)
|
|
#ifndef PMNT_DAYTONA
|
|
|| (hPMNTVDMEvent1 == NULL) || (hPMNTVDMEvent == NULL)
|
|
#endif // not PMNT_DAYTONA
|
|
)
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2InitializeVDMEvent: error at CreateEvent\n");
|
|
#endif
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
Os2WaitForVDMThread(HANDLE hEvent)
|
|
{
|
|
ULONG rc;
|
|
if (hEvent == 0)
|
|
hEvent = hPMNTVDMEvent; // Use default value
|
|
|
|
if(rc = WaitForSingleObject(hEvent, INFINITE))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2WaitForVDMThread: WaitForSingleObject(%x, INFINITE) failed, rc = %d\n",
|
|
hEvent, rc);
|
|
#endif // DBG
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#ifndef PMNT_DAYTONA
|
|
BOOLEAN
|
|
Os2WaitForVDMThreadReady()
|
|
{
|
|
ULONG rc;
|
|
|
|
if(rc = WaitForSingleObject(hPMNTVDMEventReady, INFINITE))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2WaitForVDMThread: WaitForSingleObject(hPMNTVDMEventReady, INFINITE) failed, rc = %d\n",
|
|
rc);
|
|
#endif // DBG
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
#endif // not PMNT_DAYTONA
|
|
|
|
extern HANDLE hStartHardwareEvent;
|
|
extern HANDLE hEndHardwareEvent;
|
|
|
|
BOOL
|
|
__stdcall
|
|
SetEvent(
|
|
HANDLE hEvent
|
|
);
|
|
|
|
#ifndef PMNT_DAYTONA
|
|
VOID
|
|
Os2VDMGetStartThread(
|
|
IN PVOID Parameter
|
|
)
|
|
{
|
|
ULONG rc;
|
|
|
|
// Notify the creator of this thread that we are alive and about to wait for
|
|
// the Console
|
|
if(!SetEvent(hPMNTVDMEventReady))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMGetStartThread: SetEvent(hPMNTVDMEventReady) failed, error=%x\n",
|
|
GetLastError());
|
|
#endif // DBG
|
|
ExitThread(1L);
|
|
}
|
|
|
|
// Wait for Console
|
|
if (rc = WaitForSingleObject(hStartHardwareEvent, INFINITE))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMGetStartThread: WaitForSingleObject(hStartHardwareEvent, INFINITE) failed, rc = %d\n",
|
|
rc);
|
|
#endif // DBG
|
|
ExitThread(rc);
|
|
}
|
|
|
|
// Release PMNTGetFullScreen
|
|
if (!SetEvent((Parameter == NULL) ? hPMNTVDMEvent:(HANDLE)Parameter))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMGetStartThread: SetEvent(%x) failed, error=%x\n",
|
|
(Parameter == NULL) ? hPMNTVDMEvent:(HANDLE)Parameter,
|
|
GetLastError());
|
|
#endif // DBG
|
|
ExitThread(1L);
|
|
}
|
|
|
|
ExitThread(0L);
|
|
}
|
|
#endif // not PMNT_DAYTONA
|
|
|
|
/*****************************************************************************
|
|
* Os2VDMThread: *
|
|
* Created & used by PMNTSetFullScreen(). It will handle the handshake with *
|
|
* the Console for the first transaction which indicates we have received *
|
|
* the control of the screen, i.e. right after going full-screen. *
|
|
*****************************************************************************/
|
|
VOID
|
|
Os2VDMThread(
|
|
IN PVOID Parameter
|
|
)
|
|
{
|
|
ULONG rc;
|
|
#ifndef PMNT_DAYTONA
|
|
DWORD Status;
|
|
HANDLE ThreadHandle = NULL;
|
|
ULONG Tid;
|
|
#endif // not PMNT_DAYTONA
|
|
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread: waiting for getting hardware\n");
|
|
#endif // DBG
|
|
|
|
if (rc = WaitForSingleObject(hStartHardwareEvent, INFINITE))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread: WaitForSingleObject(hStartHardwareEvent, INFINITE) #1 failed, rc = %d\n",
|
|
rc);
|
|
#endif // DBG
|
|
ExitThread(rc);
|
|
}
|
|
|
|
#ifdef PMNT_DAYTONA
|
|
if (!SetEvent(hEndHardwareEvent))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread: SetEvent(hEndHardwareEvent) #1 failed, error=%x\n",
|
|
GetLastError());
|
|
#endif // DBG
|
|
ExitThread(1L);
|
|
}
|
|
|
|
if (rc = WaitForSingleObject(hStartHardwareEvent, INFINITE))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread: WaitForSingleObject(hStartHardwareEvent, INFINITE) #2 failed, rc = %d\n",
|
|
rc);
|
|
#endif // DBG
|
|
ExitThread(rc);
|
|
}
|
|
if (!SetEvent(hEndHardwareEvent))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread: SetEvent(hEndHardwareEvent) #2 failed, error=%x\n",
|
|
GetLastError());
|
|
#endif // DBG
|
|
ExitThread(1L);
|
|
}
|
|
#else // not PMNT_DAYTONA
|
|
// Create a thread that will wait on the StartHardware event before
|
|
// we release the Console. This will prevent the Console from
|
|
// setting the event twice without letting us sense it twice
|
|
|
|
ThreadHandle = CreateThread( NULL,
|
|
0,
|
|
(PFNTHREAD)Os2VDMGetStartThread,
|
|
hPMNTVDMEvent1,
|
|
0,
|
|
&Tid);
|
|
|
|
if (ThreadHandle)
|
|
{
|
|
// Free memory associated with the thread object
|
|
Status = NtClose(ThreadHandle);
|
|
#if DBG
|
|
if (!(Status >= 0))
|
|
{
|
|
DbgPrint("Os2VDMThread: NtClose(%x) failed, status=%x\n",
|
|
ThreadHandle, Status);
|
|
}
|
|
#endif // DBG
|
|
|
|
// Wait till Os2VDMGetStartThread has started and is just about to
|
|
// call WaitForSingleObject(hStartHardwareEvent, INFINITE)
|
|
if (!Os2WaitForVDMThreadReady())
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread: Os2WaitForVDMThread isn't useful, ThreadHandle = NULL\n");
|
|
#endif // DBG
|
|
ThreadHandle = NULL;
|
|
}
|
|
#if DBG
|
|
else
|
|
DbgPrint("Os2VDMThread: Os2VDMGetStartThread is ready\n");
|
|
#endif // DBG
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
DbgPrint("Os2VDMThread: CreateThread for Os2VDMGetStartThread failed, error=%x\n",
|
|
GetLastError());
|
|
}
|
|
#endif // DBG
|
|
|
|
// Now we can safely notify the Console
|
|
if (!SetEvent(hEndHardwareEvent))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread: SetEvent(hEndHardwareEvent) fail, error=%x\n",
|
|
GetLastError());
|
|
#endif
|
|
ExitThread(1L);
|
|
}
|
|
|
|
if (ThreadHandle != NULL)
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread waiting for Os2VDMGetStartThread()\n");
|
|
#endif
|
|
// Wait for Os2VDMGetStartThread() to get events from the
|
|
// Console signifying we went full-screen
|
|
if (!Os2WaitForVDMThread(hPMNTVDMEvent1))
|
|
{
|
|
ExitThread(1L);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (rc = WaitForSingleObject(hStartHardwareEvent, INFINITE))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread: WaitForSingleObject(hStartHardwareEvent, INFINITE) #2 failed, rc = %d\n",
|
|
rc);
|
|
#endif
|
|
ExitThread(1L);
|
|
}
|
|
}
|
|
#endif // not PMNT_DAYTONA
|
|
|
|
// Release PMNTSetFullScreen
|
|
if (!SetEvent(hPMNTVDMEvent))
|
|
{
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread: SetEvent(hPMNTVDMEvent) fail, error=%x\n",
|
|
GetLastError());
|
|
#endif
|
|
ExitThread(1L);
|
|
}
|
|
|
|
#if DBG
|
|
DbgPrint("Os2VDMThread: wait for getting hardware done !\n");
|
|
#endif
|
|
|
|
ExitThread(0L);
|
|
}
|
|
|
|
#endif /* PMNT */
|