Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1156 lines
32 KiB

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
dllinit.c
Abstract:
This module contains the initialization code for the OS/2 Subsystem
Client DLL.
Author:
Steve Wood (stevewo) 22-Aug-1989
Environment:
User Mode only
Revision History:
--*/
#define INCL_OS2V20_ALL
#include "os2dll.h"
#include "os2dll16.h"
#include "conrqust.h"
#include "os2nls.h"
#include "os2win.h"
/*
* Local prototypes
*/
NTSTATUS
Od2SetGlobalInfoSel();
VOID
Od2FixupEnvironmentFromSM( VOID );
VOID
EntryFlat(VOID);
VOID
Od2DosExit(
ULONG ExitAction,
ULONG ExitResult,
ULONG ExitReason
);
VOID
Od2RaiseStackException( VOID );
NTSTATUS Od2InitSem();
//
// GLobal Os2dll variables: see definition in ..\inc\os2dll.h
//
ULONG Od2GlobalInfoSeg;
ULONG Os2Debug;
SYSTEM_BASIC_INFORMATION Od2NtSysInfo;
PVOID Od2Heap;
PVOID Od2TiledHeap;
PVOID Od2Environment;
ULONG Od2EnvCommandOffset;
ULONG Od2BootDrive;
ULONG Od2SystemDrive;
HANDLE Od2PortHandle;
PVOID Od2PortHeap;
ULONG Od2PortMemoryRemoteDelta;
POD2_PROCESS Od2Process;
POD2_THREAD Od2Thread1;
HANDLE Od2DeviceDirectory;
PSZ Od2LibPath;
USHORT Od2LibPathLength;
POD2_MSGFILE Od2MsgFile;
PUCHAR Od2SystemRoot;
ULONG Od2Start16Stack;
ULONG Od2Start16DS;
OD2_SIG_HANDLER_REC SigHandlerRec;
POD2_SIG_HANDLER_REC pSigHandlerRec = &SigHandlerRec;
OD2_VEC_HANDLER_REC VecHandlerRec = {0,0,0,0,0,0,0};
POD2_VEC_HANDLER_REC pVecHandlerRec = &VecHandlerRec;
ULONG Od2ExecPgmErrorText;
ULONG Od2ExecPgmErrorTextLength;
char ErrorBuffer[50];
ULONG Od2Saved16Stack;
ULONG Od2SessionNumber;
extern HANDLE Ow2hOs2srvPort;
//
// Program Name Info set in os2ses\os2.c
//
extern char Od2PgmFullPathBuf[];
extern PSZ Od2PgmFilePath;
extern ULONG Od2PgmFullPathBufLength;
extern PSZ Od2CommandLinePtr; // set by startprocess os2ses\ntinitss.c
PPEB_OS2_DATA PebOs2Data;
BOOLEAN
Od2ProcessIsDetached(VOID)
{
return(Od2Process->Pib.Type == PT_DETACHED);
}
VOID
_Od2InfiniteSleep(VOID);
//
// Infinite alertable delay. Used in the thread that wait to be terminated.
// SuspendThread can't be used due to design bug in NT: assincronious suspend
// may be denggerous - the process lock in kernel might be owned by the thread.
//
VOID
Od2InfiniteSleep(VOID)
{
LARGE_INTEGER timeout;
NTSTATUS Status;
// TEB isn't restored and it can be invalid. Don't use it.
// Od2Process can be free already, don't use it too.
Status = NtTestAlert();
#if DBG
IF_OD2_DEBUG( TASKING ) {
DbgPrint("Od2InfiniteSleep, NtTestAlert Status=%x\n",
Status);
}
#endif // DBG
timeout.LowPart = 0;
timeout.HighPart = 0x80000000; // Infinity
//
// The delay must be alertable to allow context change. If the context wasn't
// changed, continue to wait.
//
while (TRUE)
{
Status = NtDelayExecution(
TRUE, // alertable
&timeout);
#if DBG
IF_OD2_DEBUG( TASKING ) {
DbgPrint("Od2InfiniteSleep, NtDelayExecution Status=%x\n",
Status);
}
#endif // DBG
}
}
BOOLEAN
Od2InitCreateProcessMessage(
OUT PSCREQ_CREATE pCreate
)
/*++
Routine Description:
This function is the part of DLL initialization routines for the
OS/2 Emulation Subsystem Client DLL to be done before calling os2srv
to CreateProcess.
Arguments:
pCreate- A message to os2srv to put parameter values in.
Return Value:
False if initialization failed else return True.
--*/
{
NTSTATUS Status;
PPEB Peb;
ULONG RegionSize;
//
// Get the Peb address. Allocate the OS/2 subsystem specific portion
// within the Peb. This structure will be filled in by the server
// process as part of the connect logic.
//
Peb = NtCurrentPeb();
if (!Peb->SubSystemData)
{
Peb->SubSystemData = RtlAllocateHeap( Peb->ProcessHeap, 0,
sizeof( PEB_OS2_DATA )
);
if (!Peb->SubSystemData)
{
#if DBG
KdPrint(("Od2InitCreateProcessMessage: out of memory, fail load\n"));
#endif
ASSERT( FALSE );
return FALSE;
}
PebOs2Data = (PPEB_OS2_DATA)Peb->SubSystemData;
PebOs2Data->Length = sizeof( PEB_OS2_DATA );
} else
{
PebOs2Data = RtlAllocateHeap( Peb->ProcessHeap, 0,
sizeof( PEB_OS2_DATA )
);
if (!PebOs2Data)
{
#if DBG
KdPrint(("Od2InitCreateProcessMessage: out of memory, fail load\n"));
#endif
ASSERT( FALSE );
return FALSE;
}
PebOs2Data->Length = sizeof( PEB_OS2_DATA );
}
//
// Allocate space for the heap that will be used to contain the
// data structures maintained by the OS/2 Client DLL. The heap will
// grow dynamically.
// Also, create a heap for tiled objects (semaphores) the value for this
// HeapBase must be in the first 512 meg of the address space.
// The reason is that when this heap is used to create Semaphores we
// need to be able to do CRMA on them for 16-bit programs.
//
Od2Environment = (PVOID) OD2TILEDHEAP_BASE;
RegionSize = OD2TILEDHEAP_SIZE;
Status = NtAllocateVirtualMemory( NtCurrentProcess(),
(PVOID *)&Od2Environment,
0,
&RegionSize,
MEM_RESERVE,
PAGE_READWRITE
);
if ( !NT_SUCCESS( Status ) )
{
#if DBG
KdPrint(("Od2InitCreateProcessMessage: out of memory, fail load\n"));
#endif
return( FALSE );
}
Od2TiledHeap = RtlCreateHeap( HEAP_GROWABLE,
Od2Environment,
OD2TILEDHEAP_SIZE,
4 * 1024,
0,
NULL
);
if (Od2TiledHeap == NULL)
{
#if DBG
KdPrint(("Od2InitCreateProcessMessage: out of memory, fail load\n"));
ASSERT( FALSE );
#endif
return( FALSE );
}
//
// Create a heap for the OS/2 client non-tiled objects.
//
Od2Heap = RtlCreateHeap( HEAP_GROWABLE,
NULL,
64 * 1024, // Initial size of heap is 64K
4 * 1024,
0,
NULL
);
if (Od2Heap == NULL)
{
#if DBG
KdPrint(("Od2InitCreateProcessMessage: out of memory, fail load\n"));
ASSERT( FALSE );
#endif
return( FALSE );
}
//
// Initialize the Od2Process and Od2Thread1 variables
//
Status = Od2InitializeTask();
if (!NT_SUCCESS( Status ))
{
#if DBG
KdPrint(("Od2InitCreateProcessMessage: Error %lx at Od2InitializeTask, Fail Loading\n", Status));
ASSERT( FALSE );
#endif
return( FALSE );
}
//#if (sizeof(PEB_OS2_DATA) > (12*sizoef(ULONG)))
//#err PEB_OS2_DATA is larger than place in SCREQ_CREATE, please update sesport.h
//#endif
pCreate->d.In.SignalDeliverer = (PVOID)_Od2SignalDeliverer;
pCreate->d.In.ExitListDispatcher = (PVOID)_Od2ExitListDispatcher;
pCreate->d.In.InfiniteSleep = (PVOID)_Od2InfiniteSleep;
pCreate->d.In.FreezeThread = (PVOID)_Od2FreezeThread;
pCreate->d.In.UnfreezeThread = (PVOID)_Od2UnfreezeThread;
pCreate->d.In.VectorHandler = (PVOID) pVecHandlerRec;
pCreate->d.In.CritSectionAddr = (PVOID) EntryFlat;
pCreate->d.In.ClientPib = (PVOID)&Od2Process->Pib;
pCreate->d.In.ClientOs2Tib = (PVOID)&Od2Thread1->Os2Tib;
pCreate->d.In.InitialPebOs2Length = PebOs2Data->Length;
return( TRUE );
}
VOID
Od2HandleCreateProcessRespond(
IN PSCREQ_CREATE pCreate
)
/*++
Routine Description:
This function is the part of DLL initialization routines for the
OS/2 Emulation Subsystem Client DLL to be done after calling os2srv
to CreateProcess (using the info returns from the server).
Arguments:
pCreate- A message from os2srv to get parameter values from.
--*/
{
ULONG Priority;
//
// Save the priority set by the server...
//
Priority = Od2Thread1->Os2Tib.Priority;
RtlZeroMemory( &Od2Thread1->Os2Tib, sizeof( Od2Thread1->Os2Tib ) );
Od2Thread1->Os2Tib.ThreadId = pCreate->d.Out.Os2TibThreadId;
Od2Thread1->Os2Tib.Priority = Priority;
Od2Thread1->Os2Tib.Version = pCreate->d.Out.Os2TibVersion;
RtlZeroMemory( &Od2Process->Pib, sizeof( Od2Process->Pib ) );
Od2Process->Pib.ProcessId = (PID)pCreate->d.Out.PibProcessId;
Od2Process->Pib.ParentProcessId = (PID)pCreate->d.Out.PibParentProcessId;
Od2Process->Pib.ImageFileHandle = (HMODULE)pCreate->d.Out.PibImageFileHandle;
Od2Process->Pib.Status = pCreate->d.Out.PibStatus;
Od2Process->Pib.Type = pCreate->d.Out.PibType;
RtlMoveMemory( PebOs2Data,
&pCreate->d.Out.InitialPebOs2Data[0],
PebOs2Data->Length
);
Od2BootDrive = pCreate->d.Out.BootDrive;
Od2SystemDrive = pCreate->d.Out.SystemDrive;
Od2DeviceDirectory = pCreate->d.Out.DeviceDirectory;
CtrlPortHandle = pCreate->d.Out.CtrlPortHandle;
Od2SessionNumber = pCreate->d.Out.SessionNumber;
Od2GlobalInfoSeg = (ULONG)pCreate->d.Out.GInfoAddr;
}
BOOLEAN
Od2DllInitialize(
IN PVOID DllHandle,
IN ULONG Reason,
IN PCONTEXT Context OPTIONAL
)
/*++
Routine Description:
This function is the DLL initialization routine for the OS/2 Emulation
Subsystem Client DLL. This function gets control when the applications
links to this DLL are snapped.
Arguments:
Context - Supplies an optional context buffer that will be restored
after all DLL initialization has been completed. If this
parameter is NULL then this is a dynamic snap of this module.
Otherwise this is a static snap prior to the user process
gaining control.
Return Value:
False if initialization failed else return True.
History:
Nov-5-1992 - Yaron Shamir - os2dll.dll vanishes. Ths code become part of os2.exe.
This routine is called directly from os2ses\os2.c
--*/
{
NTSTATUS Status;
PCHAR CommandLine;
PCH src, dst, s;
APIRET RetCode;
SECURITY_QUALITY_OF_SERVICE DynamicQos;
BOOLEAN RootProcessInSession;
ULONG RegionSize;
PSZ Win32CurDirs;
ULONG Win32CurDirsIndex;
Status = STATUS_SUCCESS;
// DbgBreakPoint();
if ( Reason == DLL_PROCESS_ATTACH ) {
//
// Setup error buffer for 16-bit loading errors
//
Od2ExecPgmErrorText = (ULONG) &ErrorBuffer;
Od2ExecPgmErrorTextLength = 0;
//
// Set up the security quality of service parameters to use over the
// port. Use the most efficient (least overhead) - which is dynamic
// rather than static tracking.
//
DynamicQos.ImpersonationLevel = SecurityImpersonation;
DynamicQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
DynamicQos.EffectiveOnly = TRUE;
//
// Remember our DLL handle in a global variable.
//
// Od2DllHandle = (HMODULE)DllHandle;
//
// Save away system information in a global variable
//
Status = NtQuerySystemInformation( SystemBasicInformation,
&Od2NtSysInfo,
sizeof( Od2NtSysInfo ),
NULL
);
if (!NT_SUCCESS( Status )) {
#if DBG
KdPrint(("Od2DllInitialize: Error %lx at NtQuerySystemInformation,Fail Loading\n",
Status));
#endif
ASSERT( FALSE );
return( FALSE );
}
//
// Allocate the OS/2 Environment block and fill it in with the strings
// ser get from win32. The format of the OS/2 Environment block is:
//
// <Environment Strings>
// '\0'
// <Full Path Name of Image File>
// '\0'
// <Command String>
// <Argument Strings>
// '\0'
//
// where <Environment Strings> contains zero or more null terminated
// strings of the format NAME=value
//
// <Full Path Name of Image File> is a null terminated string
// that specifies the full path of the image file that was loaded
// into this process.
//
// <Command String> is a null terminated string that represents
// first token on the command line. Typically, the full path of
// the image file was derived from this string by defaulting the
// extenstion and search the PATH environment variable for the
// image file.
//
// <Argument Strings> contains zero or more null terminated
// strings that represent the arguments to the program. By
// convention, the OS/2 Command Processor (CMD.EXE) passes a
// single argument string that is everything after the command
// name.
//
// '\0' are explicit, extra, null characters used to separate the
// sections of the environment block. They are in addition to the
// null characters used to terminate the strings in each section.
//
Od2Environment = (PVOID) OD2ENVIRONMENT_BASE;
//
// get the environment variables from win32, and copy/edit them
// in the tiled segment starting at OD2ENVIRONMENT_BASE
//
Win32CurDirs = s = (PSZ)GetEnvironmentStrings();
dst = Od2Environment;
//
// 1st measure the size of commitment needed, and commit it
//
//
// watch for the current directories (appear in environment
// in the form "=C:=C:\foo"
//
Win32CurDirsIndex = (ULONG)-1;
while (*s) {
if (*s == '=') {
Win32CurDirsIndex = s - Win32CurDirs;
break;
}
s++;
while (*s++) {
}
}
if (Win32CurDirsIndex != (ULONG)-1) {
src = NULL;
while (*s) {
if (src == NULL && *s != '='){
src = s;
}
s++;
while (*s++) {
}
}
if (src == NULL) {
src = s;
}
} else {
Win32CurDirsIndex = 0;
src = Win32CurDirs;
}
//
// reserve 64K for environment (one tiled segment)
//
RegionSize = _64K;
Status = NtAllocateVirtualMemory( NtCurrentProcess(),
(PVOID *)&Od2Environment,
0,
&RegionSize,
MEM_RESERVE,
PAGE_READWRITE
);
if ( !NT_SUCCESS( Status ) ) {
#if DBG
KdPrint(("Od2DllInitialize: out of memory, fail load\n"));
#endif
return( FALSE );
}
//
// commit enough memory to hold initial environment
//
RegionSize = (s - src) + Win32CurDirsIndex + CCHMAXPATH * 2; // 500 extra for additions
Status = NtAllocateVirtualMemory( NtCurrentProcess(),
(PVOID *)&Od2Environment,
0,
&RegionSize,
MEM_COMMIT,
PAGE_READWRITE
);
if ( !NT_SUCCESS( Status ) ) {
#if DBG
KdPrint(("Od2DllInitialize: out of memory, fail load\n"));
#endif
return( FALSE );
}
if (Win32CurDirsIndex != 0) {
RtlMoveMemory(dst, Win32CurDirs, Win32CurDirsIndex);
dst += Win32CurDirsIndex;
}
if ((src - s) != 0) {
RtlMoveMemory(dst, src, (s - src));
dst += (s - src);
}
*dst++ = 0; // terminate the environment block
//
// Copy the image file name if one was given.
//
strncpy( dst, Od2PgmFullPathBuf, Od2PgmFullPathBufLength);
dst+= Od2PgmFullPathBufLength;
*dst++ = '\0'; // null to terminate image file name
//
// Copy the command line argument strings.
//
CommandLine = dst;
strcpy(CommandLine, Od2CommandLinePtr);
//
// put 2 NULLs at the end of the command line
//
dst += strlen(CommandLine) + 1;
*dst = '\0';
//
// null to terminate first token of command line.
//
dst = CommandLine;
#ifdef DBCS
// MSKK Apr.12.1993 V-AkihiS
// Support charaters which code are greater than 0x80
// (i.e. DBCS).
while ((UCHAR)*dst > ' ') {
#else
while (*dst > ' ') {
#endif
dst++;
}
*dst = '\0';
Od2PortHandle = Ow2hOs2srvPort;
strncpy( Od2Process->ApplName,
Od2PgmFilePath,
OS2_MAX_APPL_NAME);
Od2LibPath = RtlAllocateHeap( Od2Heap, 0, CCHMAXPATH);
if (!Od2LibPath)
{
#if DBG
KdPrint(("OS2: Od2DllInitialize: out of heap memory, fail load\n"));
#endif
ASSERT( FALSE );
return FALSE;
}
Od2LibPathLength = (USHORT)
GetEnvironmentVariableA("Os2LibPath", Od2LibPath, CCHMAXPATH);
//
// Find if new session
//
Status = Od2InitializeSessionPort(&RootProcessInSession);
if (!NT_SUCCESS( Status )){
#if DBG
KdPrint(( "OS2: Unable to connect to OS2 Subsystem - Status == %X\n",
Status));
#endif
return( FALSE );
}
//
// Initialize the NLS support
//
RetCode = Od2InitNls(PebOs2Data->CodePage,
RootProcessInSession);
if (RetCode){
#if DBG
KdPrint(("OS2: Od2DllInitialize: RetCode %d at Od2InitNIs, Fail Loading\n",
RetCode));
#endif
return( FALSE );
}
//
// Initialize the file system
//
if (PebOs2Data->StartedBySm) {
RetCode = Od2InitializeFileSystemForSM(
PebOs2Data->InitialDefaultDrive,
PebOs2Data->StdIn,
PebOs2Data->StdOut,
PebOs2Data->StdErr
);
} else if (RootProcessInSession) {
RetCode = Od2InitializeFileSystemForChildSM(
PebOs2Data->SizeOfInheritedHandleTable,
PebOs2Data->InitialDefaultDrive
);
}
else {
RetCode = Od2InitializeFileSystemForExec(
PebOs2Data->SizeOfInheritedHandleTable,
PebOs2Data->InitialDefaultDrive
);
}
Od2Process->ErrorAction =
OD2_ENABLE_ACCESS_VIO_POPUP | OD2_ENABLE_HARD_ERROR_POPUP;
if (RetCode) {
#if DBG
KdPrint(("OS2: Od2DllInitialize: RetCode %d at Od2InitializeFileSystem, Fail Loading\n",
RetCode));
#endif
return( FALSE );
}
Od2InitializeThread( Od2Thread1 ); // Status always SUCCESS
//
// Store the address of the environment block and imbedded command line
// in the OS/2 Process Information Block (PIB)
//
Od2Process->Pib.Environment = Od2Environment;
Od2Process->Pib.CommandLine = CommandLine;
//
// FIX, FIX - The following variables need to be inherited via the
// pConnectionInformation->InitialPebOs2Data structure
//
Od2Process->VerifyFlag = TRUE;
Od2Process->MaximumFileHandles = 20;
Status = Od2InitSem();
if (!NT_SUCCESS( Status ))
{
#if DBG
KdPrint(("Od2InitDllInitialize: Error %lx at Od2InitSem, Fail Loading\n", Status));
ASSERT( FALSE );
#endif
return( FALSE );
}
//
// Initialize the Timers component.
//
Status = Od2InitializeTimers();
if (!NT_SUCCESS( Status )){
#if DBG
ASSERT( FALSE );
KdPrint(("Od2DllInitialize: Error %lx at Od2InitializeTimers, Fail Loading\n",
Status));
#endif
return( FALSE );
}
//
// Initialize the Netbios component.
//
Od2NetbiosInitialize();
//
// Initialize the Disk IoCtl component.
//
Od2DiskIOInitialize();
//
// Initialize the system message file.
//
Status = Od2InitializeMessageFile();
if (!NT_SUCCESS( Status )){
#if DBG
ASSERT( FALSE );
KdPrint(("Od2DllInitialize: Error %lx at Od2InitializeMessageFile, Fail Loading\n",
Status));
#endif
return( FALSE );
}
Od2FixupEnvironmentFromSM();
//
// FIX, FIX - when we get DLLs, then DLL Initialization procedures
// need to get called at this point.
//
if (ARGUMENT_PRESENT( Context )) {
PebOs2Data->ClientStartAddress = (PVOID)CONTEXT_TO_PROGRAM_COUNTER(Context);
CONTEXT_TO_PROGRAM_COUNTER(Context) = (PVOID)Od2ProcessStartup;
}
if (!NT_SUCCESS(Od2SetGlobalInfoSel())){
#if DBG
KdPrint(("DosGetInfoSeg: failed\n"));
#endif
return(FALSE);
}
}
if (!NT_SUCCESS( Status ))
return( FALSE );
else
return( TRUE );
}
VOID
Od2FixupEnvironmentFromSM( VOID )
{
UCHAR c;
PCHAR src, dst;
BOOLEAN InKeyword;
src = Od2Process->Pib.Environment;
dst = src;
while (*src) {
InKeyword = TRUE;
while (c = *src) {
if (!InKeyword) {
if (c == '\\') {
if (!_strnicmp( src, "\\BootDevice", 11 )) {
*dst++ = (CHAR) ('A' + Od2BootDrive);
*dst++ = ':';
src += 11;
if (*src != '\\') {
*dst++ = '\\';
}
continue;
}
else
if (!_strnicmp( src, "\\SystemDisk", 11 )) {
*dst++ = (CHAR) ('A' + Od2SystemDrive);
*dst++ = ':';
src += 11;
if (*src != '\\') {
*dst++ = '\\';
}
continue;
}
}
}
else
if (c == '=') {
InKeyword = FALSE;
}
else
if (c >= 'a' && c <= 'z') {
c = c - (UCHAR)'a' + (UCHAR)'A';
}
#ifdef DBCS
// MSKK Mar.24.1993 V-AkihiS
if (Ow2NlsIsDBCSLeadByte(c, SesGrp->DosCP)) {
*dst++ = c;
src++;
if (*src) {
*dst++ = *src++;
}
}
else {
*dst++ = c;
src++;
}
#else
*dst++ = c;
src++;
#endif
}
*dst++ = c;
src++;
}
*dst++ = '\0';
src++;
while (c = *src) {
if (c == '\\') {
if (!_strnicmp( src, "\\BootDevice", 11 )) {
*dst++ = (CHAR) ('A' + Od2BootDrive);
*dst++ = ':';
src += 11;
if (*src != '\\') {
*dst++ = '\\';
}
}
else
if (!_strnicmp( src, "\\SystemDisk", 11 )) {
*dst++ = (CHAR) ('A' + Od2SystemDrive);
*dst++ = ':';
src += 11;
if (*src != '\\') {
*dst++ = '\\';
}
}
else {
#ifdef DBCS
// MSKK Mar.24.1993 V-AkihiS
if (Ow2NlsIsDBCSLeadByte(c, SesGrp->DosCP)) {
*dst++ = c;
src++;
if (*src) {
*dst++ = *src++;
}
}
else {
*dst++ = c;
src++;
}
#else
*dst++ = c;
src++;
#endif
}
}
else {
#ifdef DBCS
// MSKK Mar.24.1993 V-AkihiS
if (Ow2NlsIsDBCSLeadByte(c, SesGrp->DosCP)) {
*dst++ = c;
src++;
if (*src) {
*dst++ = *src++;
}
}
else {
*dst++ = c;
src++;
}
#else
*dst++ = c;
src++;
#endif
}
}
*dst++ = c;
src = Od2Process->Pib.CommandLine;
Od2Process->Pib.CommandLine = dst;
while (*src) {
while (c = *src) {
if (c == '\\') {
if (!_strnicmp( src, "\\BootDevice", 11 )) {
*dst++ = (CHAR) ('A' + Od2BootDrive);
*dst++ = ':';
src += 11;
if (*src != '\\') {
*dst++ = '\\';
}
}
else
if (!_strnicmp( src, "\\SystemDisk", 11 )) {
*dst++ = (CHAR) ('A' + Od2SystemDrive);
*dst++ = ':';
src += 11;
if (*src != '\\') {
*dst++ = '\\';
}
}
else {
#ifdef DBCS
// MSKK Mar.24.1993 V-AkihiS
if (Ow2NlsIsDBCSLeadByte(c, SesGrp->DosCP)) {
*dst++ = c;
src++;
if (*src) {
*dst++ = *src++;
}
}
else {
*dst++ = c;
src++;
}
#else
*dst++ = c;
src++;
#endif
}
}
else {
#ifdef DBCS
// MSKK Mar.24.1993 V-AkihiS
if (Ow2NlsIsDBCSLeadByte(c, SesGrp->DosCP)) {
*dst++ = c;
src++;
if (*src) {
*dst++ = *src++;
}
}
else {
*dst++ = c;
src++;
}
#else
*dst++ = c;
src++;
#endif
}
}
*dst++ = c;
src++;
}
*dst++ = '\0';
}
/**** Currently this routine is not in use - don't remove for now (11-5-92 YaronS)
ULONG
Od2ProcessException(
IN PEXCEPTION_POINTERS ExceptionInfo,
OUT PEXCEPTION_RECORD ExceptionRecord
)
{
PTEB ThreadInfo;
NTSTATUS Status, ExceptionCode;
ULONG RegionSize;
ULONG CurrentStackLimit;
ULONG GuardPageLimit;
#if DBG
IF_OD2_DEBUG( EXCEPTIONS ) {
KdPrint(("entering Od2ProcessException\n"));
}
#endif
ExceptionCode = ExceptionInfo->ExceptionRecord->ExceptionCode;
// copy exception record to caller's buffer
RtlMoveMemory(ExceptionRecord,ExceptionInfo->ExceptionRecord,sizeof(EXCEPTION_RECORD));
if ((XCPT_FATAL_EXCEPTION & ExceptionCode) == XCPT_FATAL_EXCEPTION) {
//
// if this is a PTERM, the thread has already been notified of its
// impending death, so kill it.
// otherwise, call DosExit for the thread.
//
if (ExceptionCode != XCPT_PROCESS_TERMINATE &&
ExceptionCode != XCPT_ASYNC_PROCESS_TERMINATE) {
//
// if this was a signal, acknowledge it.
//
if (ExceptionCode == XCPT_SIGNAL) {
ULONG Signal;
Signal = ExceptionRecord->ExceptionInformation[0];
Od2AcknowledgeSignalException(Signal);
}
// Od2DosExit(EXIT_PROCESS,
// ERROR_PROTECTION_VIOLATION, // FIX, FIX - decode status
// TC_TRAP);
// ASSERT (FALSE); // we should never get here
}
return EXCEPTION_EXECUTE_HANDLER;
}
else {
if (ExceptionCode == XCPT_GUARD_PAGE_VIOLATION) {
ThreadInfo = NtCurrentTeb();
//
// make sure that exception address is within stack range.
// if it isn't, we continue execution. this is because we're
// the last possible handler and this is not a fatal exception.
//
CurrentStackLimit = (ULONG) ThreadInfo->NtTib.StackLimit;
if ((ExceptionInfo->ExceptionRecord->ExceptionInformation[1] >=
(ULONG)ThreadInfo->NtTib.StackBase) ||
(ExceptionInfo->ExceptionRecord->ExceptionInformation[1] <
CurrentStackLimit)) {
return (ULONG)EXCEPTION_CONTINUE_EXECUTION;
}
GuardPageLimit = ROUND_DOWN_TO_PAGES(ExceptionInfo->ExceptionRecord->ExceptionInformation[1]) - Od2NtSysInfo.PageSize;
//
// verify that we haven't exceeded our stack
//
if (CurrentStackLimit > GuardPageLimit) {
Od2RaiseStackException();
return (ULONG)EXCEPTION_CONTINUE_EXECUTION;
}
//
// commit new guard page
//
RegionSize = Od2NtSysInfo.PageSize;
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
(PVOID *) &GuardPageLimit,
0,
&RegionSize,
MEM_COMMIT,
PAGE_READWRITE | PAGE_GUARD);
if (Status != STATUS_SUCCESS) {
Od2RaiseStackException();
}
}
return (ULONG)EXCEPTION_CONTINUE_EXECUTION;
}
}
********/
VOID
Od2ExceptionHandler(
IN PEXCEPTION_RECORD ExceptionRecord
)
{
NTSTATUS ExceptionCode;
OS2_API_MSG m;
POS2_TERMINATETHREAD_MSG a = &m.u.TerminateThread;
ExceptionCode = ExceptionRecord->ExceptionCode;
if (ExceptionCode == XCPT_PROCESS_TERMINATE ||
ExceptionCode == XCPT_ASYNC_PROCESS_TERMINATE) {
//
// Remove high bit to indicate loader error
//
a->ExitResult = ~0x80000000 & Od2Process->ResultCodes.ExitResult;
Od2CallSubsystem( &m, NULL, Oi2TerminateThread, 0 );
}
else {
// ASSERT (FALSE);
}
}
VOID
Od2ProcessStartup(
IN PPEB Peb
)
{
PULONG BadPointer = (PULONG)1;
PFNPROCESS StartAddress;
// Call 32 bit Entry Point. If it returns, then
// exit the process with the return value as the exit code.
//
StartAddress = (PFNPROCESS)(PebOs2Data->ClientStartAddress);
// try {
DosExit( EXIT_PROCESS, (*StartAddress)( Peb ));
//
// If DosExit fails, then force an exception.
//
*BadPointer = 0;
// }
// except( Od2ProcessException(GetExceptionInformation(),&ExceptionRecord) ) {
// Od2ExceptionHandler(&ExceptionRecord);
// }
}