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.
 
 
 
 
 
 

1107 lines
31 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
dllldr16.c
Abstract:
This module implements 32 equivalents of OS/2 V2.0 Loader
API Calls. These are called from 16->32 thunks (i386\doscalls.asm).
Author:
Yaron Shamir (YaronS) 22-Apr-1991
Revision History:
--*/
#include <stdlib.h>
#include <string.h>
#define INCL_OS2V20_MEMORY
#define INCL_OS2V20_ERRORS
#include "os2dll.h"
#include "os2dll16.h"
#include "os2tile.h"
#include <mi.h>
#include <ldrxport.h>
#ifdef DBCS
// MSKK Apr.19.1993 V-AkihiS
//
// OS/2 internal multibyte string function.
//
#include "dlldbcs.h"
#define strpbrk Od2MultiByteStrpbrk
#define strchr Od2MultiByteStrchr
#define strrchr Od2MultiByteStrrchr
#endif
extern int DosScanEnv(PSZ pszValName, PSZ *ppresult);
extern ldrlibi_t InitRecords[MAX_INIT_RECORDS];
extern ULONG Od2EnvCommandOffset;
extern ULONG GetFlatAddrOf16BitStack();
extern CHAR ResourceUsage[LDT_DISJOINT_ENTRIES];
#if DBG
extern USHORT Os2DebugSel;
#endif
#ifndef MAXPATHLEN
#define MAXPATHLEN 260
#endif
BOOLEAN
Od2ExpandOd2LibPathElements(
OUT PCHAR ExpandedString,
IN ULONG MaxSize
)
{
PCHAR TmpPtr;
PCHAR CurPathElement;
PCHAR EndOfOd2LibPath;
ULONG SizeCounter = 0;
ULONG Size;
ULONG FileFlags;
ULONG FileType;
APIRET RetCode;
STRING CanonicalPathElement;
CHAR PathElement[128];
ExpandedString[0] = '\0';
CurPathElement = strchr(Od2LibPath, '='); // skip the Os2LibPath= string
if (CurPathElement == NULL) {
CurPathElement = Od2LibPath;
}
else {
CurPathElement++; // In order to include the '='
}
EndOfOd2LibPath = Od2LibPath + Od2LibPathLength;
while (CurPathElement < EndOfOd2LibPath) {
TmpPtr = strchr(CurPathElement, ';');
if (TmpPtr == NULL) {
Size = strlen(CurPathElement);
if (Size == 0) {
break;
}
}
else {
Size = TmpPtr - CurPathElement;
if (Size == 0) {
CurPathElement++;
continue;
}
}
if (Size >= sizeof(PathElement)) {
// skip this path element - it is too big to handle
CurPathElement += Size + 1;
continue;
}
RtlMoveMemory(PathElement, CurPathElement, Size);
PathElement[Size] = '\0';
CurPathElement += Size + 1;
RetCode = Od2Canonicalize(PathElement,
CANONICALIZE_FILE_OR_DEV,
&CanonicalPathElement,
NULL,
&FileFlags,
&FileType
);
if (RetCode == NO_ERROR) {
#if DBG
IF_OD2_DEBUG( FILESYS ) {
DbgPrint("canonicalize returned %s\n",CanonicalPathElement.Buffer);
}
#endif
if (SizeCounter != 0) {
if ((SizeCounter + CanonicalPathElement.Length + 1) >= MaxSize) {
return(FALSE);
}
ExpandedString[SizeCounter++] = ';';
}
else {
if (SizeCounter + CanonicalPathElement.Length >= MaxSize) {
return(FALSE);
}
}
RtlMoveMemory(&ExpandedString[SizeCounter], CanonicalPathElement.Buffer,
CanonicalPathElement.Length);
SizeCounter += CanonicalPathElement.Length;
ExpandedString[SizeCounter] = '\0';
RtlFreeHeap(Od2Heap, 0, CanonicalPathElement.Buffer);
}
else {
#if DBG
IF_OD2_DEBUG( FILESYS ) {
DbgPrint("Od2ExpandOs2LibPathElements: Od2Canonicalize returned %d\n", RetCode);
}
#endif
}
}
return(TRUE);
}
BOOLEAN
Od2ExpandPathElements(
IN PSZ PathPtr,
OUT PCHAR ExpandedString,
IN ULONG MaxSize
)
{
PCHAR TmpPtr;
PCHAR CurPathElement;
PCHAR EndOfPath;
ULONG SizeCounter;
ULONG Size;
ULONG FileFlags;
ULONG FileType;
APIRET RetCode;
STRING CanonicalPathElement;
CHAR PathElement[CCHMAXPATH+14]; // 14 is for '\OS2SS\DRIVES\'
ExpandedString[0] = '\0';
//
// First thing to do is to add the current directory to the search PATH
//
RetCode = Od2Canonicalize(".",
CANONICALIZE_FILE_OR_DEV,
&CanonicalPathElement,
NULL,
&FileFlags,
&FileType
);
if (RetCode == NO_ERROR) {
#if DBG
IF_OD2_DEBUG( FILESYS ) {
DbgPrint("OS2: canonicalize . returned %s\n",CanonicalPathElement.Buffer);
}
#endif
if (CanonicalPathElement.Length >= MaxSize) {
return(FALSE);
}
RtlMoveMemory(ExpandedString, CanonicalPathElement.Buffer,
CanonicalPathElement.Length);
SizeCounter = CanonicalPathElement.Length;
ExpandedString[SizeCounter] = '\0';
RtlFreeHeap(Od2Heap, 0, CanonicalPathElement.Buffer);
}
else {
#if DBG
IF_OD2_DEBUG( FILESYS ) {
DbgPrint("OS2: Od2ExpandPathElements: Od2Canonicalize returned %d\n", RetCode);
}
#endif
return(FALSE);
}
CurPathElement = PathPtr;
EndOfPath = PathPtr + strlen(PathPtr);
while (CurPathElement < EndOfPath) {
TmpPtr = strchr(CurPathElement, ';');
if (TmpPtr == NULL) {
Size = strlen(CurPathElement);
if (Size == 0) {
break;
}
}
else {
Size = TmpPtr - CurPathElement;
if (Size == 0) {
CurPathElement++;
continue;
}
}
if (Size >= sizeof(PathElement)) {
// skip this path element - it is too big to handle
CurPathElement += Size + 1;
continue;
}
RtlMoveMemory(PathElement, CurPathElement, Size);
PathElement[Size] = '\0';
CurPathElement += Size + 1;
RetCode = Od2Canonicalize(PathElement,
CANONICALIZE_FILE_OR_DEV,
&CanonicalPathElement,
NULL,
&FileFlags,
&FileType
);
if (RetCode == NO_ERROR) {
#if DBG
IF_OD2_DEBUG( FILESYS ) {
DbgPrint("OS2: canonicalize returned %s\n",CanonicalPathElement.Buffer);
}
#endif
if ((SizeCounter + CanonicalPathElement.Length + 1) >= MaxSize) {
return(FALSE);
}
ExpandedString[SizeCounter++] = ';';
RtlMoveMemory(&ExpandedString[SizeCounter], CanonicalPathElement.Buffer,
CanonicalPathElement.Length);
SizeCounter += CanonicalPathElement.Length;
ExpandedString[SizeCounter] = '\0';
RtlFreeHeap(Od2Heap, 0, CanonicalPathElement.Buffer);
}
else {
#if DBG
IF_OD2_DEBUG( FILESYS ) {
DbgPrint("OS2: Od2ExpandPathElements: Od2Canonicalize returned %d\n", RetCode);
}
#endif
}
}
//#if DBG
// KdPrint(("The search PATH is: %s\n", ExpandedString));
//#endif
return(TRUE);
}
APIRET
DosLoadModuleNE(
IN PCHAR pszFailName,
IN ULONG cbFailName,
IN PCHAR pszModName,
OUT PUSHORT phMod
)
{
APIRET Rc;
OS2_API_MSG m;
P_LDRLOADMODULE_MSG a = &m.u.LdrLoadModule;
POS2_CAPTURE_HEADER CaptureBuffer;
STRING ModuleNameString;
STRING FailNameString;
STRING LibPathNameString;
// Remember that \OS2SS\DRIVES\ is added for each path element !
// Let's assume the smallest component is 5 chars long (like C:\X;)
// (although it could be less, like "." or "\")
// => we need to add 14 * (MAXPATHLEN/5) = MAXPATHLEN*3
CHAR ExpandedLibPath[MAXPATHLEN*4];
BOOLEAN MemAllocatedForModName;
ULONG FileFlags;
ULONG FileType;
ULONG Len;
ldrrei_t exec_info;
ldrrei_t *pexec_info = &exec_info;
ULONG NumOfInitRecords;
ULONG i;
ULONG RetCode;
ULONG FlatAddrOf16BitStack;
//
// Very tricky code. The EBX holds the flat address of the
// stack of the current running thread. This value is used by
// the init routine of the newly loaded DLL if it has no
// stack of its own. The EBX is initialized in client\i386\doscalls.asm
//
//_asm { mov FlatAddrOf16BitStack, ebx };
FlatAddrOf16BitStack = GetFlatAddrOf16BitStack();
//
// probe phmod pointer.
//
try {
Od2ProbeForWrite(phMod, sizeof(USHORT), 1);
if ((pszFailName != NULL) && (cbFailName > 0)) {
pszFailName[0] = 0;
pszFailName[cbFailName - 1] = 0;
}
Len = strlen(pszModName);
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
if (Len > 2) {
if (pszModName[1] == ':') {
if (Len >= CCHMAXPATH) {
//
// Check for any meta characters
//
if (strpbrk(pszModName, "*?") != NULL)
return(ERROR_INVALID_NAME);
else
return(ERROR_FILE_NOT_FOUND);
}
}
else {
if (Len >= (CCHMAXPATH-2)) {
//
// Store Modulename string to pszFailName
//
if ((pszFailName != NULL) && (cbFailName > 0)) {
Len = min(Len, cbFailName - 1);
RtlMoveMemory(pszFailName, pszModName, Len);
pszFailName[Len] = '\0';
}
//
// Check for any meta characters
//
if (strpbrk(pszModName, "*?") != NULL)
return(ERROR_INVALID_NAME);
else
return(ERROR_FILE_NOT_FOUND);
}
}
}
//
// Check for any meta characters
//
if (strpbrk(pszModName, "*?") != NULL) {
//
// Store Modulename string to pszFailName
//
if ((pszFailName != NULL) && (cbFailName > 0)) {
Len = min(Len, cbFailName - 1);
RtlMoveMemory(pszFailName, pszModName, Len);
pszFailName[Len] = '\0';
}
return(ERROR_INVALID_NAME);
}
if ((strchr(pszModName, '.') != NULL) &&
(strpbrk(pszModName, "\\/") == NULL)
) {
if ((pszFailName != NULL) && (cbFailName > 0)) {
Len = min(Len, cbFailName - 1);
RtlMoveMemory(pszFailName, pszModName, Len);
pszFailName[Len] = '\0';
}
return(ERROR_FILE_NOT_FOUND);
}
if (strpbrk(pszModName, ":\\/.") == NULL) {
RtlInitString(&ModuleNameString, pszModName);
MemAllocatedForModName = FALSE;
}
else {
Rc = Od2Canonicalize(pszModName,
CANONICALIZE_FILE_OR_DEV,
&ModuleNameString,
NULL,
&FileFlags,
&FileType
);
if (Rc != NO_ERROR) {
return(Rc);
}
MemAllocatedForModName = TRUE;
}
FailNameString.Buffer = NULL;
FailNameString.Length = 0;
FailNameString.MaximumLength = (USHORT)cbFailName;
if (FailNameString.MaximumLength == 0) {
FailNameString.MaximumLength++;
}
Od2ExpandOd2LibPathElements(ExpandedLibPath, sizeof(ExpandedLibPath));
RtlInitString(&LibPathNameString, ExpandedLibPath);
CaptureBuffer = Od2AllocateCaptureBuffer(
4,
0,
ModuleNameString.MaximumLength +
FailNameString.MaximumLength +
LibPathNameString.MaximumLength +
MAX_INIT_RECORDS * sizeof(ldrlibi_t)
);
if (CaptureBuffer == NULL) {
if (MemAllocatedForModName) {
RtlFreeHeap(Od2Heap, 0, ModuleNameString.Buffer);
}
return(ERROR_NOT_ENOUGH_MEMORY);
}
Od2CaptureMessageString( CaptureBuffer,
ModuleNameString.Buffer,
ModuleNameString.Length,
ModuleNameString.MaximumLength,
&a->ModuleName
);
if (MemAllocatedForModName) {
RtlFreeHeap(Od2Heap, 0, ModuleNameString.Buffer);
}
Od2CaptureMessageString( CaptureBuffer,
FailNameString.Buffer,
FailNameString.Length,
FailNameString.MaximumLength,
&a->FailName
);
Od2CaptureMessageString( CaptureBuffer,
LibPathNameString.Buffer,
LibPathNameString.Length,
LibPathNameString.MaximumLength,
&a->LibPathName
);
Od2CaptureMessageString( CaptureBuffer,
NULL,
0,
MAX_INIT_RECORDS * sizeof(ldrlibi_t),
&a->InitRecords
);
Od2CallSubsystem( &m, CaptureBuffer, Ol2LdrLoadModule, sizeof( *a ) );
Rc = m.ReturnedErrorValue;
if (Rc != NO_ERROR) {
if (pszFailName != NULL) {
RtlCopyMemory(pszFailName, a->FailName.Buffer, a->FailName.Length);
pszFailName[a->FailName.Length] = '\0';
}
}
else {
NumOfInitRecords = a->NumOfInitRecords;
RtlCopyMemory(InitRecords, a->InitRecords.Buffer,
NumOfInitRecords * sizeof(ldrlibi_t));
RtlCopyMemory(pexec_info, &a->ExecInfo, sizeof(exec_info));
pexec_info->ei_envsel = FLATTOSEL(Od2Environment);
pexec_info->ei_comoff = (USHORT)Od2EnvCommandOffset;
}
Od2FreeCaptureBuffer( CaptureBuffer );
#if DBG
IF_OD2_DEBUG ( LOADER ) {
DbgPrint("Values in exec_info:\n");
DbgPrint("ei_startaddr=%x\n", pexec_info->ei_startaddr); /* instruction pointer */
DbgPrint("ei_stackaddr=%x\n", pexec_info->ei_stackaddr); /* instruction pointer */
DbgPrint("ei_ds=%x\n", pexec_info->ei_ds); /* instruction pointer */
DbgPrint("ei_dgroupsize=%x\n", pexec_info->ei_dgroupsize); /* instruction pointer */
DbgPrint("ei_heapsize=%x\n", pexec_info->ei_heapsize); /* instruction pointer */
DbgPrint("ei_loadtype=%x\n", pexec_info->ei_loadtype); /* instruction pointer */
DbgPrint("ei_envsel=%x\n", pexec_info->ei_envsel); /* instruction pointer */
DbgPrint("ei_comoff=%x\n", pexec_info->ei_comoff); /* instruction pointer */
DbgPrint("ei_stacksize=%x\n", pexec_info->ei_stacksize); /* instruction pointer */
DbgPrint("ei_hmod=%x\n", pexec_info->ei_hmod); /* instruction pointer */
}
#endif
//#if DBG
// {
// OS2_API_MSG m;
// P_LDRDUMPSEGMENTS_MSG a = &m.u.LdrDumpSegments;
//
// DbgPrint("DosLoadModuleNE: dumping segments !\n");
//
// Od2CallSubsystem( &m, NULL, Ol2LdrDumpSegments, sizeof( *a ) );
// }
//#endif
if (Rc == NO_ERROR) {
//
// Go over all DLLs init routines
//
for (i = 0; i < NumOfInitRecords; i++) {
#if DBG
IF_OD2_DEBUG ( LOADER ) {
DbgPrint("=== Calling Init routine for module %s\n", pszModName);
}
#endif
if (InitRecords[i].stackaddr.ptr_sel == 0) {
#if DBG
IF_OD2_DEBUG ( LOADER ) {
DbgPrint("Replacing SS:SP of module\n");
}
#endif
InitRecords[i].stackaddr.ptr_sel = FLATTOSEL(FlatAddrOf16BitStack);
InitRecords[i].stackaddr.ptr_off = (USHORT)FlatAddrOf16BitStack;
}
#if DBG
IF_OD2_DEBUG ( LOADER ) {
DbgPrint("Values of libi:\n");
DbgPrint("startaddr=%x\n", InitRecords[i].startaddr); /* instruction pointer */
DbgPrint("stackaddr=%x\n", InitRecords[i].stackaddr); /* instruction pointer */
DbgPrint("ds=%x\n", InitRecords[i].ds); /* instruction pointer */
DbgPrint("heapsize=%x\n", InitRecords[i].heapsize); /* instruction pointer */
DbgPrint("handle=%x\n", InitRecords[i].handle); /* instruction pointer */
}
#endif
RetCode = ldrLibiInit(&InitRecords[i], pexec_info);
#if DBG
IF_OD2_DEBUG ( LOADER ) {
DbgPrint("=== Init routine returned %d\n", RetCode);
}
#endif
}
*phMod = (USHORT)a->ModuleHandle;
}
return (Rc);
}
APIRET
DosQueryModuleNameNE(
IN ULONG hMod,
IN ULONG cbBuf,
OUT PCHAR pchBuf
)
{
OS2_API_MSG m;
P_LDRGETMODULENAME_MSG a = &m.u.LdrGetModuleName;
POS2_CAPTURE_HEADER CaptureBuffer;
STRING ModuleNameString;
APIRET Rc;
//
// probe pchBuf pointer.
//
try {
Od2ProbeForWrite(pchBuf, cbBuf, 1);
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
if (cbBuf <= 1) {
return(ERROR_BAD_LENGTH);
}
ModuleNameString.Buffer = NULL;
ModuleNameString.Length = 0;
ModuleNameString.MaximumLength = (USHORT)cbBuf;
CaptureBuffer = Od2AllocateCaptureBuffer(
1,
0,
ModuleNameString.MaximumLength
);
if (CaptureBuffer == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
a->ModuleHandle = hMod;
Od2CaptureMessageString( CaptureBuffer,
ModuleNameString.Buffer,
ModuleNameString.Length,
ModuleNameString.MaximumLength,
&a->ModuleName
);
Od2CallSubsystem( &m, CaptureBuffer, Ol2LdrGetModuleName, sizeof( *a ) );
Rc = m.ReturnedErrorValue;
if (Rc == NO_ERROR) {
strcpy(pchBuf, a->ModuleName.Buffer);
}
Od2FreeCaptureBuffer( CaptureBuffer );
return(Rc);
}
APIRET
DosQueryModuleHandleNE(
IN PSZ pszModName,
OUT PUSHORT phMod
)
{
APIRET Rc;
OS2_API_MSG m;
P_LDRGETMODULEHANDLE_MSG a = &m.u.LdrGetModuleHandle;
POS2_CAPTURE_HEADER CaptureBuffer;
STRING ModuleNameString;
STRING LibPathNameString;
// Remember that \OS2SS\DRIVES\ is added for each path element !
// Let's assume the smallest component is 5 chars long (like C:\X;)
// (although it could be less, like "." or "\")
// => we need to add 14 * (MAXPATHLEN/5) = MAXPATHLEN*3
CHAR ExpandedLibPath[MAXPATHLEN*4];
BOOLEAN MemAllocatedForModName;
ULONG FileFlags;
ULONG FileType;
ULONG Len;
//
// probe phmod pointer.
//
try {
Len = strlen(pszModName);
Od2ProbeForWrite(phMod, sizeof(USHORT), 1);
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
//
// Check for any meta charaters
if (strpbrk(pszModName, "*?") != NULL) {
return(ERROR_INVALID_NAME);
}
if (strpbrk(pszModName, ":\\/.") == NULL) {
if (strcmp(pszModName,"DOSCALL1") == 0) {
RtlInitString(&ModuleNameString, "DOSCALLS");
MemAllocatedForModName = FALSE;
}
else {
RtlInitString(&ModuleNameString, pszModName);
MemAllocatedForModName = FALSE;
}
}
else {
Rc = Od2Canonicalize(pszModName,
CANONICALIZE_FILE_OR_DEV,
&ModuleNameString,
NULL,
&FileFlags,
&FileType
);
if (Rc != NO_ERROR) {
return(Rc);
}
MemAllocatedForModName = TRUE;
}
Od2ExpandOd2LibPathElements(ExpandedLibPath, sizeof(ExpandedLibPath));
RtlInitString(&LibPathNameString, ExpandedLibPath);
CaptureBuffer = Od2AllocateCaptureBuffer(
2,
0,
ModuleNameString.MaximumLength +
LibPathNameString.MaximumLength
);
if (CaptureBuffer == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
Od2CaptureMessageString( CaptureBuffer,
ModuleNameString.Buffer,
ModuleNameString.Length,
ModuleNameString.MaximumLength,
&a->ModuleName
);
if (MemAllocatedForModName == TRUE) {
RtlFreeHeap(Od2Heap, 0, ModuleNameString.Buffer);
}
Od2CaptureMessageString( CaptureBuffer,
LibPathNameString.Buffer,
LibPathNameString.Length,
LibPathNameString.MaximumLength,
&a->LibPathName
);
Od2CallSubsystem( &m, CaptureBuffer, Ol2LdrGetModuleHandle, sizeof( *a ) );
Rc = m.ReturnedErrorValue;
if (Rc == NO_ERROR) {
*phMod = (USHORT)a->ModuleHandle;
}
Od2FreeCaptureBuffer( CaptureBuffer );
return(Rc);
}
APIRET
DosGetProcAddrNE(
IN ULONG hMod,
IN PSZ pszProcName,
OUT PULONG pProcAddr
)
{
USHORT uTmp;
APIRET Rc;
OS2_API_MSG m;
P_LDRGETPROCADDR_MSG a = &m.u.LdrGetProcAddr;
POS2_CAPTURE_HEADER CaptureBuffer = NULL;
STRING ProcNameString;
BOOLEAN NameIsOrdinal;
//
// probe pprocaddr pointer.
//
try {
Od2ProbeForWrite(pProcAddr, sizeof(ULONG), 1);
//
// Check if flat address corresponds to selector index 0
//
if ((FLATTOSEL(pszProcName)) != 7) { // This is a text string
strlen((PCHAR) pszProcName);
if (*pszProcName == '#') {
a->ProcNameIsOrdinal = TRUE;
NameIsOrdinal = TRUE;
a->OrdinalNumber = atoi(pszProcName + 1);
}
else {
a->ProcNameIsOrdinal = FALSE;
NameIsOrdinal = FALSE;
RtlInitString(&ProcNameString, pszProcName);
}
}
else {
//
// Clear high bits of pszProcName and call
//
uTmp = (USHORT)pszProcName;
a->ProcNameIsOrdinal = TRUE;
NameIsOrdinal = TRUE;
a->OrdinalNumber = uTmp;
}
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
if (!NameIsOrdinal) {
CaptureBuffer = Od2AllocateCaptureBuffer(
1,
0,
ProcNameString.MaximumLength
);
if (CaptureBuffer == NULL) {
return(ERROR_NOT_ENOUGH_MEMORY);
}
Od2CaptureMessageString( CaptureBuffer,
ProcNameString.Buffer,
ProcNameString.Length,
ProcNameString.MaximumLength,
&a->ProcName
);
}
a->ModuleHandle = hMod;
Od2CallSubsystem( &m, CaptureBuffer, Ol2LdrGetProcAddr, sizeof( *a ) );
Rc = m.ReturnedErrorValue;
if (Rc == NO_ERROR) {
*pProcAddr = a->ProcAddr;
}
if (!NameIsOrdinal) {
Od2FreeCaptureBuffer( CaptureBuffer );
}
return(Rc);
}
APIRET
DosFreeModuleNE(
IN ULONG hMod
)
{
OS2_API_MSG m;
P_LDRFREEMODULE_MSG a = &m.u.LdrFreeModule;
APIRET Rc;
a->ModuleHandle = hMod;
Od2CallSubsystem( &m, NULL, Ol2LdrFreeModule, sizeof( *a ) );
Rc = m.ReturnedErrorValue;
return(Rc);
}
APIRET
DosQueryAppTypeNE(
IN PSZ pszAppName,
OUT PUSHORT pusType
)
{
OS2_API_MSG m;
P_LDRQAPPTYPE_MSG a = &m.u.LdrQAppType;
POS2_CAPTURE_HEADER CaptureBuffer;
STRING AppNameString;
STRING PathNameString;
// Remember that \OS2SS\DRIVES\ is added for each path element !
// Let's assume the smallest component is 5 chars long (like C:\X;)
// (although it could be less, like "." or "\")
// => we need to add 14 * (MAXPATHLEN/5) = MAXPATHLEN*3
CHAR ExpandedPath[MAXPATHLEN*4];
BOOLEAN MemAllocatedForAppName;
ULONG FileFlags;
ULONG FileType;
ULONG Len;
PSZ PathPtr;
APIRET Rc;
//
// probe pchBuf pointer.
//
try {
Len = strlen(pszAppName); // just to trigger GP read exception
Od2ProbeForWrite(pusType, sizeof(USHORT), 1);
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
if (Len > 2) {
if (pszAppName[1] == ':') {
if (Len >= CCHMAXPATH) {
return(ERROR_FILE_NOT_FOUND);
}
}
else {
if (Len >= (CCHMAXPATH-2)) {
return(ERROR_FILE_NOT_FOUND);
}
}
}
if (strpbrk(pszAppName, ":\\/") == NULL) {
RtlInitString(&AppNameString, pszAppName);
MemAllocatedForAppName = FALSE;
}
else {
Rc = Od2Canonicalize(pszAppName,
CANONICALIZE_FILE_OR_DEV,
&AppNameString,
NULL,
&FileFlags,
&FileType
);
if (Rc != NO_ERROR) {
return(Rc);
}
MemAllocatedForAppName = TRUE;
}
Rc = DosScanEnv("PATH", &PathPtr);
if (Rc != NO_ERROR) {
PathPtr = "";
}
Od2ExpandPathElements(PathPtr, ExpandedPath, sizeof(ExpandedPath));
RtlInitString(&PathNameString, ExpandedPath);
CaptureBuffer = Od2AllocateCaptureBuffer(
2,
0,
AppNameString.MaximumLength +
PathNameString.MaximumLength
);
if (CaptureBuffer == NULL) {
if (MemAllocatedForAppName) {
RtlFreeHeap(Od2Heap, 0, AppNameString.Buffer);
}
return(ERROR_NOT_ENOUGH_MEMORY);
}
Od2CaptureMessageString( CaptureBuffer,
AppNameString.Buffer,
AppNameString.Length,
AppNameString.MaximumLength,
&a->AppName
);
if (MemAllocatedForAppName) {
RtlFreeHeap(Od2Heap, 0, AppNameString.Buffer);
}
Od2CaptureMessageString( CaptureBuffer,
PathNameString.Buffer,
PathNameString.Length,
PathNameString.MaximumLength,
&a->PathName
);
Od2CallSubsystem( &m, CaptureBuffer, Ol2LdrQAppType, sizeof( *a ) );
Rc = m.ReturnedErrorValue;
if (Rc == NO_ERROR) {
*pusType = (USHORT)a->AppType;
}
Od2FreeCaptureBuffer( CaptureBuffer );
return(Rc);
}
APIRET
DosScanEnvNE(
IN PSZ pszValName,
OUT PSZ *ppresult
)
{
ULONG rc;
ULONG value;
//
// probe pprsult pointer.
//
try {
Od2ProbeForWrite(ppresult,sizeof(ULONG), 1);
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
if ((rc = DosScanEnv(pszValName, ppresult)) != NO_ERROR)
return(rc);
value = (ULONG) *ppresult;
*ppresult = (PSZ)(FLATTOFARPTR(value));
return (NO_ERROR);
}
APIRET
DosGetResourceNE(
ULONG hMod,
ULONG idType,
ULONG idName,
PSEL psel)
{
OS2_API_MSG m;
P_LDRGETRESOURCE_MSG a = &m.u.LdrGetResource;
APIRET Rc;
ULONG SegNo;
ULONG sel;
try {
Od2ProbeForWrite(psel, sizeof(USHORT), 1);
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
a->ModuleHandle = hMod;
a->ResourceType = idType;
a->ResourceName = idName;
AcquireTaskLock();
Od2CallSubsystem( &m, NULL, Ol2LdrGetResource, sizeof( *a ) );
Rc = m.ReturnedErrorValue;
if (Rc == NO_ERROR) {
*psel = (SEL)a->ResourceSel;
#if DBG
if ((Os2DebugSel != 0) && (*psel == Os2DebugSel))
{
DbgPrint("[%x,%x] DosGetResource returning sel=%x\n",
Od2Process->Pib.ProcessId,
Od2CurrentThreadId(),
*psel);
}
#endif
// This loop is for Long resources. It marks all segments of a resource.
sel = (*psel >> 3) - (0x2000 - LDT_DISJOINT_ENTRIES);
for (SegNo=0; SegNo<a->NumberOfSegments; SegNo++) {
ResourceUsage[sel]++;
sel =+ 8;
}
}
ReleaseTaskLock();
return(Rc);
}
APIRET
DosGetResource2NE(
ULONG hMod,
ULONG idType,
ULONG idName,
PVOID pData)
{
OS2_API_MSG m;
P_LDRGETRESOURCE_MSG a = &m.u.LdrGetResource;
APIRET Rc;
ULONG SegNo;
ULONG sel;
try {
Od2ProbeForWrite(pData, sizeof(ULONG), 1);
}
except( EXCEPTION_EXECUTE_HANDLER ) {
Od2ExitGP();
}
a->ModuleHandle = hMod;
a->ResourceType = idType;
a->ResourceName = idName;
AcquireTaskLock();
Od2CallSubsystem( &m, NULL, Ol2LdrGetResource, sizeof( *a ) );
Rc = m.ReturnedErrorValue;
if (Rc == NO_ERROR) {
*(PULONG)pData = a->ResourceAddr;
#if DBG
if ((Os2DebugSel != 0) && (((USHORT)(a->ResourceAddr >> 16)) == Os2DebugSel))
{
DbgPrint("[%x,%x] DosGetResource returning sel=%x\n",
Od2Process->Pib.ProcessId,
Od2CurrentThreadId(),
((USHORT)(a->ResourceAddr >> 16)));
}
#endif
// This loop is for Long resources. It marks all segments of a resource.
sel = (a->ResourceAddr >> 19) - (0x2000 - LDT_DISJOINT_ENTRIES);
for (SegNo=0; SegNo<a->NumberOfSegments; SegNo++) {
ResourceUsage[sel]++;
sel+=8;
}
// ResourceUsage[(a->ResourceAddr >> 19) - (0x2000 - LDT_DISJOINT_ENTRIES)]++;
}
ReleaseTaskLock();
return(Rc);
}
APIRET
DosFreeResourceNE(
PVOID pData)
{
OS2_API_MSG m;
P_LDRFREERESOURCE_MSG a = &m.u.LdrFreeResource;
SEL Sel;
USHORT ResourceIndex;
APIRET Rc;
a->ResourceAddr = (ULONG)pData;
Od2CallSubsystem( &m, NULL, Ol2LdrFreeResource, sizeof( *a ) );
Rc = m.ReturnedErrorValue;
#if DBG
if ((Os2DebugSel != 0) && ((USHORT)((ULONG)pData >> 16) == Os2DebugSel))
{
if (Rc == NO_ERROR)
DbgPrint("[%x,%x] DosFreeResource called on sel=%x (successfull)\n",
Od2Process->Pib.ProcessId,
Od2CurrentThreadId(),
(USHORT)((ULONG)pData >> 16));
else
DbgPrint("[%x,%x] DosFreeResource called on sel=%x, rc=%d\n",
Od2Process->Pib.ProcessId,
Od2CurrentThreadId(),
(USHORT)((ULONG)pData >> 16),
Rc);
}
#endif
if (Rc == NO_ERROR) {
Sel = FLATTOSEL(pData);
ResourceIndex = (Sel >> 3) - (0x2000 - LDT_DISJOINT_ENTRIES);
if (ResourceUsage[ResourceIndex] > 0) {
ResourceUsage[ResourceIndex]--;
}
else {
return(ERROR_ACCESS_DENIED);
}
}
return(Rc);
}