summaryrefslogtreecommitdiffstats
path: root/private/os2/client/conrqust.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--private/os2/client/conrqust.c449
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;
+}
+