#include "ldrextrn.h" #ifdef PMNT #define INCL_32BIT #include "pmnt.h" extern PID PMNTPMShellPid; #endif /***LP ldrGetTgtMte - get target mte linear address * * Get MTE of module referenced by ordinal number passed. Use the * ordinal number to index into the import module pointers table. * * ENTRY modord - ordinal number of module referenced * pmte - pointer to mte * pptgtmte - pointer to target mte * * EXIT int - return code (NO_ERROR if successful) * ptgtmte - mte linear address * if mte == 0 reference to DOSCALLS * * This procedure performs the following steps: * * - Check that module ordinal number is within module pointer table * - Index into module pointer table and return linear address to mte */ APIRET ldrGetTgtMte(modord, pmte, pptgtmte) ushort_t modord; ldrmte_t *pmte; ldrmte_t **pptgtmte; { modord--; /* normalize ordinal */ if (modord < (ushort_t) pmte->mte_impmodcnt) { *pptgtmte = ((ldrmte_t *) ((ulong_t *) pmte->mte_modptrs)[modord]); return(NO_ERROR); } /* * set error = ERROR_BAD_EXE_FORMAT */ return(ERROR_BAD_EXE_FORMAT); } /***LP ldrGetEntAddr - get entry point address * * For a given ordinal number, this routine locates the * appropriate entry contained in the module's entry table. * It returns a 48-bit pointer for the specified entry point. * * ENTRY entord - ordinal number * pmte - pointer to target mte * ptaddr - pointer to return target address (off,sel,flags) * psrcste - pointer to source ste * psrcmte - pointer to source mte * * EXIT entry point address * global variable obj_ptr pointing to target segment * global variable entry_ptr pointing to entry table entry * * This procedure performs the following steps: * * - Check for zero ordinal number * - Normalize ordinal number * - Checks and handles installable file system mte entry points * - Checks and handles DOSCALLS mte entry points * - Locates the correct bundle for the given ordinal * - Creates the desired entry point address based on source and target */ APIRET ldrGetEntAddr(entord, pmte, ptaddr, psrcste, psrcmte) ushort_t entord; register ldrmte_t *pmte; register struct taddr_s *ptaddr; ldrste_t *psrcste; ldrmte_t *psrcmte; { int fcallgate; ulong_t objnum; ldrsmte_t *psmte; UNREFERENCED_PARAMETER(psrcmte); psmte = pmte->mte_swapmte; (ulong_t) ldrProcNameBuf = (ulong_t) entord; if (entord == 0) { return(ERROR_INVALID_ORDINAL); } #if PMNT /* * This process loads PMWIN.WinCreateMsgQueue() */ if (entord == 58 && 5 == (USHORT) *((PCHAR )pmte->mte_modname) && ! strncmp((PCHAR)(pmte->mte_modname+1),"PMWIN",5)) { CurrentThread->Process->Flags |= OS2_PROCESS_PMMSGQUE; } /* * This process loads PMNT.PMNTSetPMshellFlag(), thus it is PM Shell. */ else if (entord == 12 && 4 == (USHORT) *((PCHAR )pmte->mte_modname) && ! strncmp((PCHAR)(pmte->mte_modname+1),"PMNT",4)) { if (!PMNTPMShellPid) { PMNTPMShellPid = CurrentThread->Process->ProcessId; CurrentThread->Process->Flags |= OS2_PROCESS_IS_PMSHELL; } else { // Do not allow another PMshell return(ERROR_2ND_PMSHELL); } } #endif --entord; /* Normalize object number */ ptaddr->fflags = 0; /* Clear forwarder flags */ fcallgate = FALSE; /* assume not a callgate entry */ if (ldrIsNE(pmte)) { /* check for 16-bit module */ register ldrste_t *pste; register ldret_t *pbndl; ldrcte_t *pcte; ldrent_t *pent; /* * Find entry point, loop to determine which bundle the * ordinal number belongs too. */ pbndl = (ldret_t *) psmte->smte_enttab; while (TRUE) { /* find bundle ord is in */ if (pbndl->et_cnt == 0) { /* check for end of table */ return(ERROR_INVALID_ORDINAL); } if (entord < pbndl->et_cnt) /* is ord in this bundle? */ break; entord -= pbndl->et_cnt; pbndl = (ldret_t *)((char *) pbndl + ldrSkipEnts(pmte, pbndl->et_type, pbndl->et_cnt)); } if (pbndl->et_type == EMPTY) {/* check for empty bundle */ return(ERROR_INVALID_ORDINAL); } pent = (ldrent_t *)((char *) pbndl + ldrSkipEnts(pmte, pbndl->et_type, (uchar_t) entord)); pcte = (ldrcte_t *) pent; ptaddr->fflags |= FWD_ALIAS16; /* indicate tiled object */ if (pbndl->et_type == B16MOVABLE) { /* check for movable entry */ objnum = pcte->cte_obj; /* get target object */ if (objnum == B16ABSOLUTE) { /* if absolute entry */ ptaddr->toff = (ulong_t) pcte->cte_off; ptaddr->tsel = 0; ptaddr->tflags = pcte->cte_flags; return(NO_ERROR); } if (objnum > psmte->smte_objcnt) { return(ERROR_INVALID_SEGMENT_NUMBER); } pste = (ldrste_t *) psmte->smte_objtab + objnum - 1; ptaddr->toff = (ulong_t) pcte->cte_off; // // If the target object is a code segment which has IOPL (ring 2) // create call gate emulation // if ((pcte->cte_sel != 0) && (pcte->cte_sel != 0x3fcd) && ((psrcste == NULL) || // ldrDosGetProcAddress() calls with NULL (((psrcste->ste_flags & STE_SEGDPL) == STE_RING_3) && ((psrcste->ste_flags & STE_DATA) == 0))) // source is a code segment ) { ptaddr->fflags |= FWD_IOPL; ptaddr->toff = (ulong_t)pcte->cte_sel; ptaddr->tsel = FLATTOSEL(R2XFER_BASE); return(NO_ERROR); } } /* * check for absolute entry */ else if (pbndl->et_type == B16ABSOLUTE) { ptaddr->toff = (ulong_t) pent->ent_off; ptaddr->tsel = 0; ptaddr->tflags = pent->ent_flags; return(NO_ERROR); } else { /* entry is fixed */ if((ulong_t) pbndl->et_type > psmte->smte_objcnt) { return(ERROR_INVALID_SEGMENT_NUMBER); } /* * get target object */ pste = (ldrste_t *) psmte->smte_objtab + pbndl->et_type - 1; ptaddr->toff = (ulong_t) pent->ent_off; } ptaddr->tsel = pste->ste_selector | 7; ptaddr->tflags = pent->ent_flags; return(NO_ERROR); } return(NO_ERROR); } /***LP ldrGetOrdNum - get the ordinal number for procedure name * * Given a procedure name and a module table, checks to see if * the procedure is in the resident or nonresident table. If the * procedure is found in either of the tables, ldrGetOrdNum * returns the corresponding ordinal number. A 0 ordinal is * returned if the procedure is not found in either of the tables. * * ENTRY pmte - pointer to module table entry * pprocnam - pointer to procedure name * pentord - address to return ordinal number * fstring - flag to tell if null terminated * STRINGNULLTERM * STRINGPREPENDED * * EXIT if found * NO_ERROR * else * ERROR_NOT_ENOUGH_MEMORY * ERROR_PROC_NOT_FOUND */ APIRET ldrGetOrdNum(pmte, pprocnam, pentord, fstring) ldrmte_t *pmte; uchar_t *pprocnam; ushort_t *pentord; int fstring; { IO_STATUS_BLOCK IoStatusBlock; PIO_STATUS_BLOCK pIoStatusBlock = &IoStatusBlock; LARGE_INTEGER ByteOffset; PVOID MemoryAddress; ULONG RegionSize; ulong_t cbread; register ldrsmte_t *psmte; ushort_t proclen; char tname[MAX_PROC_LEN+1]; char *ptname; int rc = NO_ERROR; ptname = (char *) &tname; psmte = pmte->mte_swapmte; ldrProcNameBuf = (PUCHAR) (pprocnam + 1); ldrProcNameBufL = proclen = (USHORT) (pprocnam[0]); /* * Check for 32-bit module */ if (ldrIsLE(pmte)) { struct ExpHdr *pexpdir; ulong_t *pexpnameptrs; ushort_t *pexpordinals; if (fstring == STRINGNONNULL) { /* * Since the procedure name strings in a 32-bit module are in * the format of a null terminated string we need to convert * the 16-bit formated string of a length followed by string * to a null terminated string. */ proclen = pprocnam[0]; memcpy(pprocnam, pprocnam + 1, proclen); pprocnam[proclen] = '\0'; } pexpdir = (struct ExpHdr *) psmte->smte_expdir; pexpnameptrs = (ulong_t *) pexpdir->exp_name; pexpordinals = (ushort_t *) pexpdir->exp_ordinal; // rc = ldrBinarySearchOrd(psmte, // pprocnam, // pexpnameptrs, // pexpordinals, // pexpdir->exp_namecnt, // pentord); /* * Restore procedure name back to length followed by string. */ // if (fstring == STRINGNONNULL) { // ldrStrCpyB(pprocnam + 1, pprocnam, proclen); // pprocnam[0] = (uchar_t) proclen; // } return(rc); } /* * Check for null terminated string passed. If it is we were called * by ldrGetProcAddr and we may do this in place copy and not restore * it because it is from the stack of ldrGetProcAddr */ if (fstring == STRINGNULLTERM) { proclen = (ushort_t) strlen(pprocnam); strncpy(&ptname[1], pprocnam, proclen); ptname[0] = (uchar_t) proclen; } else { strncpy(ptname, pprocnam, proclen + 1); } /* * 16-bit module, first search the resident name table. */ if ((rc = ldrGetOrdNumSub((uchar_t *) psmte->smte_restab, ptname, pentord)) != ERROR_PROC_NOT_FOUND) { return(rc); } #if DBG IF_OL2_DEBUG ( FIXUP ) { if (fstring == STRINGNONNULL) { strncpy(&tname[0], &pprocnam[1], proclen); tname[proclen] = '\0'; DbgPrint( "Could not find Procedure %s in module %s in Resident name table\n", &tname, (char *) (pmte->mte_modname+1)); } else { DbgPrint( "Could not find Procedure %s in module %s in Resident name table\n", pprocnam, (char *) (pmte->mte_modname+1)); } if (fstring == STRINGNONNULL) { strncpy(ptname, pprocnam, proclen + 1); } } #endif /* * The procedure name was not found in the resident name table, * need to search the non-resident name table. * Do not do this for system dll's other than doscall */ if (pmte->mte_mflags & DOSMOD) { return(ERROR_PROC_NOT_FOUND); } RegionSize = psmte->smte_cbnrestab; MemoryAddress = 0; if ((rc = NtAllocateVirtualMemory(NtCurrentProcess(), &MemoryAddress, 0, &RegionSize, MEM_COMMIT, PAGE_READWRITE)) != NO_ERROR) { return(ERROR_PROC_NOT_FOUND); } /* * read the non-resident nametable from the file into non- * resident name table object. */ ByteOffset.LowPart = psmte->smte_nrestab; ByteOffset.HighPart = 0; cbread = psmte->smte_cbnrestab; if ((rc = NtReadFile(pmte->mte_sfn, 0, 0, 0, &IoStatusBlock, (void *) MemoryAddress, cbread, &ByteOffset, 0)) != 0) { return(ERROR_BAD_EXE_FORMAT); } if (IoStatusBlock.Information != cbread) { rc = ERROR_BAD_EXE_FORMAT; goto returnstatus; } /* * Now check if the procname is in the nonresident name table. */ rc = ldrGetOrdNumSub((uchar_t *) MemoryAddress, ptname, pentord); returnstatus: NtFreeVirtualMemory(NtCurrentProcess(), &MemoryAddress, &cbread, MEM_RELEASE); if (rc == NO_ERROR) return(rc); if (fstring == STRINGNONNULL) { strncpy(&ptname[0], &pprocnam[1], proclen); ptname[proclen] = '\0'; } #if DBG IF_OL2_DEBUG ( FIXUP ) { DbgPrint( "Could not find Procedure %s in module %s in Non-resident table\n", ptname, (char *) (pmte->mte_modname+1)); } #endif return(ERROR_PROC_NOT_FOUND); } /***LP ldrGetOrdNumSub - get the ordinal number for procedure name * * Given a procedure name and a resident or nonresident name table * containing the procedures exported by a module, checks to see * if the procedure is in the table. If the procedure is found * in the table, ldrGetOrdNumSub gets the corresponding ordinal * number. A 0 ordinal value is returned if the procedure is not * found in the table. The ordinal number for the module name string * is set to zero, therefore matching strings with a 0 ordinal number * are skipped. * * ENTRY pnt - pointer to resident or nonresident name table * pprocnam - pointer to procedure name * pentord - place to return ordinal * * EXIT if found * NO_ERROR * else * ERROR_PROC_NOT_FOUND * ERROR_BAD_EXE_FORMAT * * This procedure performs the following steps: * * - compare procedure name to each entry in table * - if ordinal number is 0 skip to next string * - return ordinal number if found */ APIRET ldrGetOrdNumSub(pnt, pprocnam, pentord) register uchar_t *pnt; register uchar_t *pprocnam; ushort_t *pentord; { register int len; /* * remove typeinfo from length */ while ((len = (int) (*pnt /*& ~NT_TYPEINFO*/)) != 0) { // YOSEFD: The using of the flag // harm the names that are longer // then 0x7F. The description string // can be longer. /* * include string size field */ if (memcmp(pnt, pprocnam, ++len) == 0) if ((*(ushort_t *) (pnt + len)) != 0) { /* * return ordinal number */ *pentord = *(ushort_t *)(pnt + len); return(NO_ERROR); } pnt += len + sizeof(ushort_t); /* skip to next string */ } return(ERROR_PROC_NOT_FOUND); /* end of table, return not found */ }