diff options
Diffstat (limited to '')
-rw-r--r-- | private/os2/client/conrqust.c | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/private/os2/client/conrqust.c b/private/os2/client/conrqust.c new file mode 100644 index 000000000..1cf50262c --- /dev/null +++ b/private/os2/client/conrqust.c @@ -0,0 +1,449 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + conrqust.c + +Abstract: + + This module implements the OS/2 V2.0 console API calls + +Author: + + Avi Nathan (avin) 23-Jul-1991 + +Revision History: + + +--*/ + +#define INCL_OS2V20_ERRORS +#include "os2dll.h" +#include "conrqust.h" + + +extern PVOID Os2SessionCtrlDataBaseAddress; +extern HANDLE Od2StdHandleLockHandle; + +APIRET +DosSleep( + IN ULONG MilliSeconds + ); + +NTSTATUS +Od2AlertableWaitForSingleObject( + IN HANDLE handle + ); + +#if DBG +PSZ Od2ExecPgmTable[] = +{ + "RemoveConsoleThread", + "RestartConsoleThread", + "AddWin32ChildProcess", + "RemWin32ChildProcess", + "UnKnown" +}; +#endif + +APIRET +Od2SendExecPgmRequest( + IN EXECREQUESTNUMBER RequestType + ) +{ + SCREQUESTMSG Request; + NTSTATUS Status; + +#if DBG + IF_OD2_DEBUG( LPC ) + { + DbgPrint( "Od2SendExecPgmRequest: send %s(%u) request\n", + (RequestType > 3) ? Od2ExecPgmTable[4] : + Od2ExecPgmTable[RequestType], RequestType + ); + } +#endif + + Request.Request = WinCreateProcess; + Request.d.WinExecPgm.Request = RequestType; + + //PORT_MSG_TOTAL_LENGTH(Request) = sizeof(SCREQUESTMSG); + //PORT_MSG_DATA_LENGTH(Request) = sizeof(SCREQUESTMSG) - sizeof(PORT_MESSAGE); + PORT_MSG_TOTAL_LENGTH(Request) = FIELD_OFFSET( SCREQUESTMSG, d) + + sizeof(WINEXECPGM_MSG); + PORT_MSG_DATA_LENGTH(Request) = FIELD_OFFSET( SCREQUESTMSG, d) + + sizeof(WINEXECPGM_MSG) - sizeof(PORT_MESSAGE); + PORT_MSG_ZERO_INIT(Request) = 0L; + + Status = NtRequestWaitReplyPort( CtrlPortHandle, + (PPORT_MESSAGE) &Request, + (PPORT_MESSAGE) &Request); + + if (!NT_SUCCESS(Status)){ +#if DBG + DbgPrint( "Od2SendExecPgmRequest(%u): failure at NtRequestReplyPort %lx\n", + RequestType, Status); +#endif + return(Or2MapNtStatusToOs2Error( + Status,ERROR_ACCESS_DENIED)); + } + return(Request.Status); +} + + +APIRET +Od2RemoveConsoleThread() +{ + return(Od2SendExecPgmRequest(RemoveConsoleThread)); +} + + +APIRET +Od2RestartConsoleThread() +{ + return(Od2SendExecPgmRequest(RestartConsoleThread)); +} + + +APIRET +Od2AddWin32ChildProcess() +{ + return(Od2SendExecPgmRequest(AddWin32ChildProcess)); +} + + +APIRET +Od2RemoveWin32ChildProcess() +{ + return(Od2SendExecPgmRequest(RemWin32ChildProcess)); +} + + +APIRET +Od2CallRootProcessThruLPC( + IN OUT PSCREQUESTMSG Request, + IN PCH OutBuffer, + OUT PCH InBuffer, + IN HANDLE hSem, + IN ULONG ArgLength + ) +{ + NTSTATUS NtStatus; + APIRET Status; + ULONG *pLeng, MaxLen; + PCH InPtr = (PCH)Os2SessionCtrlDataBaseAddress; + + //PORT_MSG_TOTAL_LENGTH(*Request) = sizeof(SCREQUESTMSG); + //PORT_MSG_DATA_LENGTH(*Request) = sizeof(SCREQUESTMSG) - sizeof(PORT_MESSAGE); + PORT_MSG_TOTAL_LENGTH(*Request) = (CSHORT)(FIELD_OFFSET( SCREQUESTMSG, d) + + ArgLength); + PORT_MSG_DATA_LENGTH(*Request) = (CSHORT)(FIELD_OFFSET( SCREQUESTMSG, d) + + ArgLength - sizeof(PORT_MESSAGE)); + PORT_MSG_ZERO_INIT(*Request) = 0L; + +#if DBG + IF_OD2_DEBUG2(OS2_EXE, LPC) + { + DbgPrint("SendCtrlConsoleRequest: Request %u:%u, In %p, Out %p, hSem %lx\n", + Request->Request, Request->d.Prt.Request, OutBuffer, InBuffer, hSem); + } +#endif + + if (hSem != NULL) + { + Status = Od2AlertableWaitForSingleObject(hSem); + if ( Status ) + { + return(ERROR_VIO_INVALID_HANDLE); /* =>BUGBUG fix the error code */ + } + } + + if (Request->Request == KbdRequest || Request->Request == MouRequest || + Request->Request == MonRequest || Request->Request == PrtRequest) + { + if ((InBuffer != NULL) || (OutBuffer != NULL)) + { + MaxLen = OS2_CON_PORT_MSG_SIZE; + pLeng = &Request->d.Prt.d.Write.Length; + + if ( Request->Request == KbdRequest ) + { + pLeng = &Request->d.Kbd.Length; + MaxLen = OS2_KBD_PORT_MSG_SIZE; + InPtr += KBD_OFFSET; + } + + if ( *pLeng > MaxLen ) + { +#if DBG + IF_OD2_DEBUG( OS2_EXE ) + DbgPrint("SendCtrlConsoleRequest: length 0x%lx too long\n", + *pLeng); +#endif + *pLeng = MaxLen; + } + + if (OutBuffer != NULL) + { + RtlMoveMemory(InPtr, + OutBuffer, + *pLeng); + } + } + + NtStatus = NtRequestWaitReplyPort( CtrlPortHandle, + (PPORT_MESSAGE) Request, + (PPORT_MESSAGE) Request); + + if ( !NT_SUCCESS( NtStatus )) + { +#if DBG + DbgPrint( "OS2DLL: Unable to send CTRL request - Status == %X\n", + NtStatus); +#endif + + if (hSem != NULL) + { + NtReleaseMutant(hSem, NULL); + } + + return(ERROR_VIO_INVALID_HANDLE); // =>BUGBUG fix the error code + + } + ASSERT ( PORT_MSG_TYPE(*Request) == LPC_REPLY ); + + if ((InBuffer != NULL) && ! Request->Status ) + { + RtlMoveMemory(InBuffer, + InPtr, + *pLeng); + } + + } else + { +#if DBG + DbgPrint ("SendCtrlConsoleRequest: illegal request %lu\n", + Request->Request); + return( ERROR_INVALID_PARAMETER ); +#endif + } + + Status = Request->Status; + + if (hSem != NULL) + { + NtReleaseMutant(hSem, NULL); + } + + if ( Status == -2) + { + /* + * This call is from EventReleaseLPC + * terminate thread if not Thread1 + */ + + if (Od2CurrentThreadId() != 1); + { + DosSleep((ULONG)-1); + } + + Status = 0; + } + + return( Status ); +} + + +APIRET +SendCtrlConsoleRequest( + IN OUT PSCREQUESTMSG Request, + IN PCH OutBuffer, + OUT PCH InBuffer, + IN HANDLE hSem + ) +{ + + return (Od2CallRootProcessThruLPC( + Request, OutBuffer, InBuffer, hSem, sizeof(Request->d))); +} + + +APIRET +Od2LockCtrlRequestDataBuffer() +{ + APIRET Status; + + Status = Od2WaitForSingleObject( CtrlDataSemaphore, + TRUE, + NULL); + if ( Status ) + { + return(ERROR_VIO_INVALID_HANDLE); /* =>BUGBUG fix the error code */ + } +} + + +VOID +Od2UnlockCtrlRequestDataBuffer() +{ + NtReleaseSemaphore( CtrlDataSemaphore, + 1, + NULL); +} + +#if DBG +VOID +AcquireStdHandleLock( + IN PSZ CallingRoutine + ) +{ + PTEB Teb; + + IF_OD2_DEBUG( OS2_EXE ) + { + Teb = NtCurrentTeb(); + DbgPrint("entering AcquireStdHandleLock for client id %ld%ld in %s\n", + Teb->ClientId.UniqueProcess, + Teb->ClientId.UniqueThread, + CallingRoutine); + Od2WaitForSingleObject( Od2StdHandleLockHandle, TRUE, NULL ); + DbgPrint("leaving AcquireStdHandleLock for client id %ld%ld in %s\n", + Teb->ClientId.UniqueProcess, + Teb->ClientId.UniqueThread, + CallingRoutine); + } else + { + Od2WaitForSingleObject( Od2StdHandleLockHandle, TRUE, NULL ); + } +} + + +VOID +ReleaseStdHandleLock( + IN PSZ CallingRoutine + ) +{ + PTEB Teb; + + IF_OD2_DEBUG( OS2_EXE ) + { + Teb = NtCurrentTeb(); + DbgPrint("entering ReleaseStdHandleLock for client id %ld%ld in %s\n", + Teb->ClientId.UniqueProcess, + Teb->ClientId.UniqueThread, + CallingRoutine); + NtReleaseSemaphore( Od2StdHandleLockHandle, 1, NULL); + DbgPrint("leaving ReleaseStdHandleLock for client id %ld%ld in %s\n", + Teb->ClientId.UniqueProcess, + Teb->ClientId.UniqueThread, + CallingRoutine); + } else + { + NtReleaseSemaphore( Od2StdHandleLockHandle, 1, NULL); + } +} +#else +VOID +AcquireStdHandleLock() +{ + Od2WaitForSingleObject( Od2StdHandleLockHandle, TRUE, NULL ); +} + + +VOID +ReleaseStdHandleLock() +{ + NtReleaseSemaphore( Od2StdHandleLockHandle, 1, NULL); +} +#endif + + +APIRET +KbdDupLogHandle( + IN HANDLE hKbd + ) +{ + SCREQUESTMSG Request; + NTSTATUS Status; +#if DBG + PSZ RoutineName; + + RoutineName = "KbdDupLogHandle"; + + IF_OD2_DEBUG(KBD) + { + DbgPrint("%s: entering\n", RoutineName); + } +#endif + + /* + * prepare Message parameters & send request to server (OS2) + */ + + Request.Request = KbdRequest; + Request.d.Kbd.Request = KBDDupLogHandle; + Request.d.Kbd.hKbd = hKbd; + Status = SendCtrlConsoleRequest(&Request, + NULL, + NULL, + NULL); + + /* + * handle return status (free handle if failed, validate if successed) + */ + + if ( Status ) + { +#if DBG + IF_OD2_DEBUG( KBD ) + DbgPrint("%s: status %lx\n", RoutineName, Status); +#endif + return(Status); + } + + return NO_ERROR; +} + + +APIRET +Od2WaitForSingleObject( + IN HANDLE Semaphore, + IN BOOLEAN Alertable, + IN PLARGE_INTEGER TimeOut OPTIONAL + ) +{ + NTSTATUS NtStatus; + LARGE_INTEGER StartTimeStamp; + + do { + if (TimeOut) { + Od2StartTimeout(&StartTimeStamp); + } + NtStatus = NtWaitForSingleObject(Semaphore, + Alertable, + TimeOut); +#if DBG + if (NtStatus == STATUS_USER_APC) { + DbgPrint("[%d,%d] WARNING !!! Od2WaitForSingleObject was broken by APC\n", + Od2Process->Pib.ProcessId, + Od2CurrentThreadId() + ); + } +#endif + } while (NtStatus == STATUS_USER_APC && + (NtStatus = Od2ContinueTimeout(&StartTimeStamp, TimeOut)) == STATUS_SUCCESS + ); + + if (( !NT_SUCCESS(NtStatus) ) || + (NtStatus == STATUS_TIMEOUT) || + (NtStatus == STATUS_ABANDONED) || + (NtStatus == STATUS_ALERTED)) + { + return ERROR_SEM_TIMEOUT; + } + + return NO_ERROR; +} + |