diff options
Diffstat (limited to 'private/os2/client/dllpmnt.c')
-rw-r--r-- | private/os2/client/dllpmnt.c | 1793 |
1 files changed, 1793 insertions, 0 deletions
diff --git a/private/os2/client/dllpmnt.c b/private/os2/client/dllpmnt.c new file mode 100644 index 000000000..384e60ada --- /dev/null +++ b/private/os2/client/dllpmnt.c @@ -0,0 +1,1793 @@ +/*++ + +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 */ |