20楼#
发布于:2002-05-15 16:38
fracker你给的工程文件好象不全,在source里的文件好多都没有,why?编译通不过!指点!! 用VC++ 6.0打开工程编译,source已经是个没有用的文件了,不过你要编译之前要先设置好VC++哦,好像也就是几个环境变量。 |
|
21楼#
发布于:2002-05-15 16:40
谢谢fracker的精彩回答。一定好好研究!! :cool: :cool:
|
|
|
22楼#
发布于:2002-05-15 16:49
哈哈~~原来大家都在为这个烦恼啊??我已经解决了~~~最早是得到胡老大的帮助啦!后来呢,看了一份代码!相信就是大家要的!大家看看就可以迎刃而解了~~~
/* NT compatible DLL loader * See also http://www.sch.bme.hu/~marosi/dllnt.html (Hungarian) * * Copyright (C) 1996 Istvan Marosi <recosoft@mail.matav.hu> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Seen best at TABS=4 */ #include \"includes.h\" #include \"dllnt.h\" /* typedefs for syntax colouring: (jed extension) } uint; } word; } ulong; } hdll; } proc; */ /* functions for syntax colouring: (jed extension) func open() func close() func read() func lseek() */ #define CAST(tt,vv) *((tt *)&vv) /***********************************************************************/ /* The library\'s main purpose is to load a Win32 DLL into memory. Also, * it may be compiled to write extensive commenting messages describing * the internal structure of the DLL. * * DLLs imported by the loaded DLL are automatically loaded and references * are resolved if found. If a reference (function) is not found, it is * substituted by a dummy one and no error code signalled. This dummy * function will write an informative run-time error message only when it * is called! (and the program will be immediately terminated...) * * Several macros are used for writing information to screen as the * program interprets the file. Generally the second parameter of these macros * are returned therefore it\'s easy for example to print interesting values * in expressions without disturbing the sructure of the program. * * Compile with these defines: * * -D_QUIET_ : don\'t write anything. This is the real DLLNT library code. * * -D_MESSAGES_ : write everything. Useful for examining contents of a dll * * neither : write last tag if something is failed. Almost real DLLNT * library, but writes error text, too. * * Conventions used in naming the macros: * * SuperPrefix: * __: not printed, just remembered and printed if later failed * * Prefix * <no>: the 2nd parameter is a number * TX: the 2nd parameter is a string * NULL: just an empty line * * Body: * TAG: returns the 2nd parameter as value * MSG: does not return a value * * Postfix: * INFO: no need to put OK after (if __TXMSG : even not remembered) * OKINFO: succeeds prev MSG [same line] (if __TXMSG : not remembered) * MAYBE: we are not sure, rather a warning -- only 1 param (type 2nd) * WARN: something strange, warning -- only 1 param (type 1st: text) * BAD: absolutely bad, give up -- no param */ #ifdef _QUIET_ # define __TAG(t,x) (x) # define __TAGINFO(t,x) (x) # define __TXTAG(t,tx) (tx) # define __TXTAGINFO(t,tx) (tx) # define __MSG(t,x) /**/ # define __MSGINFO(t,x) /**/ # define __MSGOKINFO(t,x) /**/ # define __TXMSG(t,tx) /**/ #else # define __TAG(t,x) (tag_ = 1, tag_t = t, tag_x = (uint)x, x) # define __TAGINFO(t,x) (tag_ = 1, tag_t = t, tag_x = (uint)x, x) # define __TXTAG(t,tx) (tag_ = 2, tag_t = t, tag_tx = tx) # define __TXTAGINFO(t,tx) (tag_ = 2, tag_t = t, tag_tx = tx) # define __MSG(t,x) (tag_ = 1, tag_t = t, tag_x = (uint)x) # define __MSGINFO(t,x) (tag_ = 1, tag_t = t, tag_x = (uint)x) # define __MSGOKINFO(t,x)(tag_ = 1, tag_t = t, tag_x = (uint)x) # define __TXMSG(t,tx) (tag_ = 2, tag_t = t, tag_tx = tx) #endif #define __TXMSGINFO(t,tx) /**/ #define __TXMSGOKINFO(t,tx) /**/ #define __NULLMSG /**/ #define __TAGMAYBE(x) (x) #ifdef _MESSAGES_ # define TAG(t,x) (CheckTag(t,(uint)x,1), x) # define TAGINFO(t,x) (CheckTag(t,(uint)x,0), x) # define TXTAG(t,tx) (CheckTxTag(t,tx,1), tx) # define TXTAGINFO(t,tx) (CheckTxTag(t,tx,0), tx) # define MSG(t,x) (CheckTag(t,(uint)x,1)) # define MSGINFO(t,x) (CheckTag(t,(uint)x,0)) # define MSGOKINFO(t,x) (CheckTag(t,(uint)x,-1)) # define TXMSG(t,tx) (CheckTxTag(t,tx,1)) # define TXMSGINFO(t,tx) (CheckTxTag(t,tx,0)) # define TXMSGOKINFO(t,tx) (CheckTxTag(t,tx,-1)) # define NULLMSG (CheckTag(NULL,0,1)) # define TAGMAYBE(x) (MaybeTag(), x) #else # define TAG __TAG # define TAGINFO __TAGINFO # define TXTAG __TXTAG # define TXTAGINFO __TXTAGINFO # define MSG __MSG # define MSGINFO __MSGINFO # define MSGOKINFO __MSGOKINFO # define TXMSG __TXMSG # define TXMSGINFO __TXMSGINFO # define TXMSGOKINFO __TXMSGOKINFO # define NULLMSG __NULLMSG # define TAGMAYBE __TAGMAYBE #endif #ifdef _QUIET_ #define MSGWARN(tx) /**/ #define MSGBAD /**/ #else #define MSGWARN(tx) (WarnTag(tx)) #define MSGBAD (BadTag()) #endif #ifndef _QUIET_ static int TagOk = 0, tag_ = 0; static int tag_x; static const char *tag_t; static const char *tag_tx; #endif /* Definition of COFF magic numbers, structures, and constant values: */ #define DOS_EXE 0x5a4d /* MZ */ #define PE_EXE 0x4550 /* PE */ #define COFF_PROC_I386 0x014c /* Coff magic */ #define COFF_DLL 0x2000 #define COFF_32_BIT 0x0100 #define COFF_EXEC 0x0002 /* valid, executable image */ #define COFF_BIG_ENDIAN 0x8000 #define COFF_NO_RELOCS 0x0001 /* should be loaded at preferred address */ #define COFF_NEEDED (COFF_DLL | COFF_32_BIT | COFF_EXEC) #define COFF_INVALID (COFF_BIG_ENDIAN | COFF_NO_RELOCS) #define OPT_NORMAL_EXE 0x010b /* Optional Header magic */ #define OPT_DATA_DIRS 0x0010 /* # of data directories */ #define MAX_PATH 260 /* max length of a filename */ #define MAX_DLLS 256 /* total allowed DLLs loaded */ #define PATH_SEP \'/\' #define S_PATH_SEP \"/\" #define VRA2A(type,vra) (type *)(pDll->DllBase + (vra)) /* Relocates a VRA */ #define VRA_A(type,vra) (type *)(DllBase + (vra)) /* Relocates a VRA */ /* In a created DLL VRAs contain the address itself: */ #define VRA_CR(type,vra) (type *)(vra) typedef struct { ulong VRA; /* address */ ulong Size; } datadir; /* COFF header */ typedef struct { short Machine; word nSections; long TimeStemp; ulong oSymTab; ulong nSymbols; word OptionSize; word Characteristic; /* Optional Header: */ /* Standard Fields: */ short Magic; char LinkVersion[2]; ulong CodeSize; ulong DataSize; ulong BssSize; ulong EntryPoint; ulong CodeBase; ulong DataBase; /* NT specific Fields: */ ulong ImageBase; ulong Alignment; ulong FileAlignment; short OsVersion[2]; /* 1.0 */ short DllVersion[2]; short SubSysVersion[2]; /* 4.0 */ long Reserved1; ulong ImageSize; ulong HeaderSize; long CheckSum; short SubSystem; short DllFlags; /* obsolate */ ulong StackReserve; ulong StackCommit; ulong HeapReserve; ulong HeapCommit; long Flags; /* obsolate */ ulong nDataDirs; /* Data Directories: */ datadir ExportTable; datadir ImportTable; datadir ResourceTable; datadir ExceptionTable; datadir SecurityTable; datadir RelocTable; datadir DebugData; datadir Copyright; datadir GlobalPtr; datadir TlsTable; /* ThreadLocalStorage */ datadir LoadConfigTable; datadir Reserved2[5]; } coff; /* Section record */ typedef struct { char Name[8]; ulong Size; /* effective size in memory */ ulong VRA; /* \"virtual\" relative address */ ulong RawSize; /* size in file */ ulong oRaw; ulong oRelocs; ulong oLineNums; word nRelocs; word nLineNums; long Flags; } section; #define S_TEXT 1 #define S_DATA 2 #define S_IMPORT 3 #define S_EXPORT 4 #define S_RELOC 5 #define S_DEBUG 6 /* coff.RelocTable : */ typedef struct { /* Relocation Block Header */ ulong PageVRA; ulong Size; } rblock; #define RELOC_TYPE 0xF000 #define RELOC_SKIP 0x0000 #define RELOC_32 0x3000 #define RELOC_OFFS 0x0FFF /* coff.ExportTable : */ typedef struct { /* Export Directory Table */ long ExportFlag; long TimeStemp; short Version[2]; ulong DllNameVRA; ulong OrdinalBase; ulong nExports; ulong nNames; /* == nOrdinals */ ulong ExportsVRA; ulong NamesVRA; ulong OrdinalsVRA; } etable; #define MAX_ORDINAL 0x0fff /* FIXME: * What is it in NT? Linux\'s start * address is 0x1000!! */ #define ORD_GAP 50 /* safety space for unordered * SetDllNTProc() calls */ /* coff.ImportTable : */ typedef struct { /* Import Directory Table */ ulong LookupsVRA; /* Import Lookup Table */ long TimeStemp; ulong ForwarderChainIndex; ulong DllNameVRA; ulong ImportsVRA; /* Import Address Table */ } itable; #define FLAG_ORDINAL 0x80000000 #define MASK_ORDINAL 0x7fffffff typedef struct { word OrdHint; char Name[1]; /* more then 1, for sure :) */ } procname; /* Main DLL housekeeping structure */ typedef struct { char Name[MAX_PATH]; char Path[MAX_PATH]; int Locks; /* 0, if not valid */ ulong DllBase; coff *pCoff; section *pSection; char *pImage; } dll; static struct { int nDll; dll *pDll[MAX_DLLS]; /* hdll is a 1 based index in this array*/ } AllDlls = {0, {NULL}}; #define OPC_PUSH_ECX \'\\x51\' /* push ecx (ecx: this pointer) */ #define OPC_CALL_REL_1 \'\\xe8\' /* call <proc_4_bytes> */ #define CALL1_SIZE (1+(1+4)) #define OPC_MOV_EAX_C_1 \'\\xb8\' /* mov eax,<const_4_bytes> */ #define OPC_CALL_EAX_1 \'\\xff\' /* call eax */ #define OPC_CALL_EAX_2 \'\\xd0\' /* 11 010 000 */ #define OPC_ADD_ESP_B_1 \'\\x83\' /* add esp,+04 */ #define OPC_ADD_ESP_B_2 \'\\xc4\' /* 11 000 100 */ #define OPC_POP_ECX \'\\x59\' /* pop ecx */ #define OPC_JMP_NEAR \'\\xe9\' /* jmp <pcrel_4_bytes> */ #define CALL2_SIZE ((1+4)+2+(2+1)+1+(1+4)) typedef struct { char Call1Instr[CALL1_SIZE]; char flOrd; /* true, if (ulong)FuncName is an ordinal */ char flMsg; /* true, if this is a message proc (will return) */ char *DllName; char *FuncName; char *Caller; char Call2Instr[CALL2_SIZE]; } dummy; #define DUMMYBLOCK 4096 /* enough for >100 dummies */ typedef struct s_dummyhead { struct s_dummyhead *Next; dummy *pNomore; dummy *pFree; } dummyhead; static dummyhead *pDummyChain = NULL; static const char **dllpathes = NULL; static char szPath[MAX_PATH]; static char szName[MAX_PATH]; /* Both can be global static. Used by LoadDllNT() and LoadImportedDlls(). * Both functions are (or at least are calling) recursive code, but these * arrays are used only till OpenDllHeader(), and later (in the recursive * cycle) can be reused to store tha names of recursed dlls. */ /*************************************************************************/ #ifndef _QUIET_ static void CheckTag(const char *tag, uint value, int NeedOK) { if (NeedOK == -1) fprintf(stderr, \" \"); else if (TagOk == 1) fprintf(stderr, \" OK\\n\"); if (tag) { fprintf(stderr, \"%s:\\t%04x\", tag, value); TagOk = NeedOK; } else { TagOk = 0; } if (TagOk != 1) fprintf(stderr, \"\\n\"); tag_ = 0; /* already printed */ } static void CheckTxTag(const char *tag, const char *text, int NeedOK) { if (NeedOK == -1) fprintf(stderr, \" \"); else if (TagOk == 1) fprintf(stderr, \" OK\\n\"); fprintf(stderr, \"%s:\\t%s\", tag, text); TagOk = NeedOK; if (TagOk != 1) fprintf(stderr, \"\\n\"); tag_ = 0; /* already printed */ } #endif #ifdef _MESSAGES_ static void MaybeTag(void) { if (tag_ == 1) CheckTag(tag_t, tag_x, 1); if (tag_ == 2) CheckTxTag(tag_t, tag_tx, 1); fprintf(stderr, \" ??\\n\"); TagOk = 0; } #endif #ifndef _QUIET_ static void WarnTag(const char *text) { if (tag_ == 1) CheckTag(tag_t, tag_x, 1); if (tag_ == 2) CheckTxTag(tag_t, tag_tx, 1); fprintf(stderr, \" %s\\n\", text); TagOk = 0; } static void BadTag(void) { if (tag_ == 1) CheckTag(tag_t, tag_x, 1); if (tag_ == 2) CheckTxTag(tag_t, tag_tx, 1); fprintf(stderr, \" BAD\\n\"); TagOk = 0; } #endif /**************************************************************/ /* Allocates READ-WRITE-EXECUTE space for the DLL image */ static char *AllocDllSpace(size_t Bytes) { return malloc(Bytes); } static void FreeDllSpace(char *pDll) { free(pDll); } static void lowerstrcpy(char *dest, const char *source) { uchar ch; for (; ch = (uchar)(*source++), ch > 0;) { /* COMMENT: this works for A..Z only, but it\'s not a problem now */ if (ch >= (uchar)\'A\' && ch <= (uchar)\'Z\') ch += (uchar)(\'a\' - \'A\'); *dest++ = (char)ch; } *dest++ = \'\\0\'; } static bool isAnyBadSection(coff *pC, section *pS) { int i; ulong offset = pC->CodeBase; int nS = pC->nSections; for (i=0; i<nS; i++) { if (__TAG(\"# of Relocs\", pS.nRelocs) != 0) return 1; if (__TAG(\"VRA\", pS.VRA) < offset) return 1; offset = pS.VRA; } __NULLMSG; return 0; } /* Opens the pDllName file and loads its headers to memory * If pDllName not found in pDllPath it tries to find * it in other places.. and changes *pDllPath */ static int OpenDllHeader(char *pDllPath, /* maybe written */ const char *pDllName, int *pFd, coff **ppCoff, section **ppSection) { char DllName[MAX_PATH]; int Fd; int RSize; int SSize; word DosHeader[0x20]; coff *pCoff; section *pSection; int pathindex = 0; for (;;) { DllName[0]=0; strncat(DllName, pDllPath, sizeof(DllName)-2); strcat(DllName, S_PATH_SEP); strncat(DllName, pDllName, sizeof(DllName)-1-strlen(DllName)); /* Well, no buffer overruns, but the name maybe strange :) */ Fd = open(DllName, O_RDONLY); if (Fd != -1) break; /* dll not found. Load it from the path: */ if (!dllpathes || !dllpathes[pathindex]) return DLL_NOTFOUND; pDllPath[0] = 0; strncat(pDllPath, dllpathes[pathindex++], MAX_PATH-1); } *pFd = Fd; RSize = read(Fd, (char *)DosHeader, sizeof(DosHeader)); if (RSize == -1) return DLL_EACCESS; if ( (RSize != sizeof(DosHeader)) || (__TAG(\"EXE Magic\", DosHeader[0]) != DOS_EXE) || (__TAG(\"PE Pointer\", DosHeader[0x1e]) == 0) || (lseek(Fd, DosHeader[0x1e], SEEK_SET) == -1) || (read(Fd, (char *)DosHeader, 4) != 4) || (__TAG(\"PE Magic\", DosHeader[0]) != PE_EXE) || (DosHeader[1] != 0)) { return DLL_UNKNOWN; } /* Now we are at the beginning of the COFF header */ __NULLMSG; pCoff = (coff *)malloc(sizeof(coff)); if (pCoff == NULL) return DLL_NOMEM; *ppCoff = pCoff; RSize = read(Fd, (char *)pCoff, sizeof(coff)); if (RSize == -1) return DLL_EACCESS; if ( (RSize != sizeof(coff)) || (__TAG(\"COFF Machine\", pCoff->Machine) != COFF_PROC_I386) || (__TAG(\"Option Size\", pCoff->OptionSize) == 0) /* not an exe */ || (__TAG(\"Needed Bits\", (pCoff->Characteristic & COFF_NEEDED)) != COFF_NEEDED ) || (__TAG(\"Invalid Bits\", (pCoff->Characteristic & COFF_INVALID)) != 0) || (__TAG(\"Optional Magic\", pCoff->Magic) != OPT_NORMAL_EXE) || (__TAG(\"Data Directories\", pCoff->nDataDirs) != OPT_DATA_DIRS)) { return DLL_UNKNOWN; } __NULLMSG; if ( /* (__TAG(\"Resources\", pCoff->ResourceTable.Size) != 0 ) ||*/ (__TAG(\"Exceptions\", pCoff->ExceptionTable.Size) != 0) || (__TAG(\"Securities\", pCoff->SecurityTable.Size) != 0) || (__TAG(\"TaskLocals\", pCoff->TlsTable.Size) != 0) || (__TAG(\"LoadConfigs\", pCoff->LoadConfigTable.Size) != 0)) { return DLL_NOTSUPP; } __NULLMSG; /* Coff header seems to be OK */ SSize = pCoff->nSections * sizeof(section); pSection = (section *)malloc(SSize); if (pSection == NULL) return DLL_NOMEM; *ppSection = pSection; RSize = read(Fd, (char *)pSection, SSize); if (RSize == -1) return DLL_EACCESS; if ( (RSize != SSize) || (isAnyBadSection(pCoff, pSection))) { return DLL_NOTSUPP; } /* Sections are OK */ return 0; } /* The return value of this function is NOT used for any serious purpose */ static int SectionKind(char *pSName) { __TXMSG(\"Section Name\", pSName); if (0 == strcmp(pSName,\".text\")) return S_TEXT; if (0 == strcmp(pSName,\".data\")) return S_DATA; if (0 == strcmp(pSName,\".idata\")) return S_IMPORT; if (0 == strcmp(pSName,\".edata\")) return S_EXPORT; if (0 == strcmp(pSName,\".reloc\")) return S_RELOC; return TAGMAYBE(S_DEBUG); } /* Loads all sections of the DLL to a newly allocated memory space */ static int ReadDllImage(int Fd, coff *pCoff, section *pSection, char **ppDll) { char *pDll; int i; int RSize; ulong FirstRelAddr = pCoff->CodeBase; /* typically 0x1000 */ ulong ISize = pCoff->ImageSize - FirstRelAddr; __MSGINFO(\"Code Base\", FirstRelAddr); __MSGINFO(\"Image Size\", ISize); __NULLMSG; // FIXME: mmap should be used instead of this stuff... pDll = AllocDllSpace(ISize); if (pDll == NULL) return DLL_NOMEM; *ppDll = pDll; for (i = 0; i < pCoff->nSections; i++) { char *pSectData; int SKind; uint FSize = pSection.RawSize; uint MSize = pSection.Size; SKind = SectionKind(pSection.Name); if (SKind == 0) return DLL_NOTSUPP; /* ????????? */ __MSGINFO(\"Mem Size\", MSize); __MSGINFO(\"Raw Size\", FSize); if (FSize) if (lseek(Fd, __TAGINFO(\"Raw Offset\", pSection.oRaw), SEEK_SET) == -1) return DLL_EACCESS; pSectData = pDll + (__TAGINFO(\"VRA\", pSection.VRA) - FirstRelAddr); if (FSize) { RSize = read(Fd, pSectData, FSize); if (RSize != (int)FSize) return DLL_EACCESS; } if (MSize > FSize) memset(pSectData + FSize, 0, MSize - FSize); /* BSS init */ __NULLMSG; } /* Image loaded to memory (Not relocated yet) */ return 0; } /* Relocates all references in DLL image loaded at DllBase */ static int RelocateImage(coff *pCoff, ulong DllBase) { ulong OldBase = pCoff->ImageBase; int Diff = DllBase - OldBase; rblock *pRBlock = VRA_A(rblock, pCoff->RelocTable.VRA); int sTotal = pCoff->RelocTable.Size; __MSGINFO(\"Reloc Size\", sTotal); while (sTotal > 0) { ulong PageRelAddr = pRBlock->PageVRA; int sPage = pRBlock->Size; word *pReloc = (word *)(pRBlock+1); /* pointer to relocation info word */ __MSGINFO(\"Reloc Block Size\", sPage); for (sPage -= sizeof(rblock); sPage > 0; sPage -= sizeof(word), pReloc++) { word RType = *pReloc & RELOC_TYPE; ulong RRelAddr = (ulong)(*pReloc & RELOC_OFFS) + PageRelAddr; long *p32bit = VRA_A(long, RRelAddr); if (RType == RELOC_SKIP) { __MSGINFO(\"Reloc Skip at\", RRelAddr); } else if (RType != RELOC_32) { __MSG(\"Reloc Type\", RType); return DLL_NOTSUPP; } else { /* Do the relocation: */ __MSGINFO(\"Relocate at\", RRelAddr); *p32bit += Diff; } } if (sPage < 0) { __MSG(\"Reloc Block Size\", sPage); return DLL_CORRUPT; } /* Step to next block: */ sTotal -= pRBlock->Size; pRBlock = (rblock *)pReloc; } if (sTotal < 0) { __MSG(\"Reloc Size\", sTotal); return DLL_CORRUPT; } __NULLMSG; return 0; } /* Finds an already loaded DLL, or returns a new handle. * New handles are returned even if there is a freed slot * between loaded DLLs. Freed slots are reused only after * all slots are \"dirty\" */ static bool isLoadedDll(const char *Name, hdll *pHDll) { int n; /* Name is already lowercase */ *pHDll = 0; for (n=0; n < AllDlls.nDll; n++) { dll *pDll = AllDlls.pDll[n]; if (pDll) { if (strcmp(Name, pDll->Name) == 0) { *pHDll = (hdll)(n+1); MSG(\"Handle Found\", n+1); return 1; } } else { if (*pHDll == 0) { /* This is the first already freed handle slot */ *pHDll = (hdll)(n+1); } } } if (n < MAX_DLLS) *pHDll = (hdll)(n+1); /* next new available slot */ /* if all handles are occupied, *pHDll is left 0 */ return 0; } static int LockDll(hdll HDll) { dll *pDll; pDll = AllDlls.pDll[(int)HDll-1]; pDll->Locks++; return pDll->Locks; } static int UnlockDll(hdll HDll) { dll *pDll; pDll = AllDlls.pDll[(int)HDll-1]; pDll->Locks--; return pDll->Locks; } static void RegisterDll(hdll HDll, dll *pDll) { AllDlls.pDll[(int)HDll-1] = pDll; if (AllDlls.nDll < MAX_DLLS) { AllDlls.nDll++; } pDll->Locks = 1; } static dll *UnregisterDll(hdll HDll) { dll *pDll; pDll = AllDlls.pDll[(int)HDll-1]; AllDlls.pDll[(int)HDll-1] = NULL; /* if (..last..) AllDlls.nDll--; * not done, because we don\'t reuse handles till we run out of them */ return pDll; } static dll *ValidDll(hdll HDll) { dll *pDll; if ( ((int)HDll < 1) || ((int)HDll > AllDlls.nDll) || ((pDll = AllDlls.pDll[(int)HDll-1]) == NULL) || (pDll->Locks == 0) /* ??? */ ) { return NULL; } return pDll; } static void DummyNull(void) { fprintf(stderr, \"\\nFatal error: Unbound Imported Procedure Called!\\n\"); exit(100); } static void DummyProcedure(char *Call1RetAddr, uint pushedECX, uint retaddr, uint Par1, uint Par2) { dummy *pDummy = (dummy *)(Call1RetAddr - CALL1_SIZE); if (pDummy->flMsg == 0) fprintf(stderr, \"\\nFatal error: \"); fprintf(stderr, \"`%s\'.\", pDummy->DllName); if (pDummy->flOrd) { fprintf(stderr, \"%i:0x%04x\", (int)pDummy->FuncName, (uint)pDummy->FuncName); } else { fprintf(stderr, pDummy->FuncName); } fprintf(stderr, \"(0x%04x[,0x%04x]) called by `%s\':0x%04x!\\n\", Par1, Par2, pDummy->Caller, retaddr); if (pDummy->flMsg == 0) exit(100); } static proc AllocDummy(char *ImportedDllName, ulong ImportedFunc, dll *pDll, proc OrigProc) { char *FuncName; char flOrd; dummy *pDummy; dummyhead *pAct, **ppLast; /* OrigProc == 0: * pDll wanted to import ImportedFunc from ImportedDllName, but couldn\'t */ /* OrigProc != 0: * We must create a message thunk which prints the name at run-time */ if (ImportedFunc & FLAG_ORDINAL) { FuncName = (char *)(ImportedFunc & MASK_ORDINAL); flOrd = 1; } else { ulong DllBase = pDll->DllBase; procname *pPN = VRA_A(procname, ImportedFunc); FuncName = pPN->Name; flOrd = 0; } for (ppLast = &pDummyChain; ; ) { pAct = *ppLast; if (pAct == NULL) { pAct = malloc(DUMMYBLOCK); if (pAct == NULL) { /* Well, just return a bare procedure */ if (OrigProc) { return OrigProc; } else { return DummyNull; } } pAct->Next = NULL; pAct->pNomore = (dummy*)(((char*)pAct) + DUMMYBLOCK); pAct->pFree = (dummy*)(pAct + 1); *ppLast = pAct; break; } else { if (pAct->pFree + 1 <= pAct->pNomore) { /* Suitable for at least one more dummy */ break; } } ppLast = &(pAct->Next); } pDummy = (pAct->pFree)++; pDummy->flOrd = flOrd; pDummy->flMsg = OrigProc ? 1 : 0; /* if OrigProc exists, a message thunk */ pDummy->DllName = ImportedDllName; pDummy->FuncName = FuncName; pDummy->Caller = pDll->Name; pDummy->Call1Instr[0] = OPC_PUSH_ECX; pDummy->Call1Instr[1] = OPC_CALL_REL_1; CAST(ulong, pDummy->Call1Instr[2]) = /* PC relative address of Call2Instr */ pDummy->Call2Instr - pDummy->Call1Instr - CALL1_SIZE; pDummy->Call2Instr[0] = OPC_MOV_EAX_C_1; CAST(proc, pDummy->Call2Instr[1]) = /* absolute address of DummyProcedure */ (proc)DummyProcedure; pDummy->Call2Instr[5] = OPC_CALL_EAX_1; pDummy->Call2Instr[6] = OPC_CALL_EAX_2; pDummy->Call2Instr[7] = OPC_ADD_ESP_B_1; pDummy->Call2Instr[8] = OPC_ADD_ESP_B_2; pDummy->Call2Instr[9] = 4; pDummy->Call2Instr[10] = OPC_POP_ECX; pDummy->Call2Instr[11] = OPC_JMP_NEAR; CAST(ulong, pDummy->Call2Instr[12]) = /* PC rel address of real procedure */ (char *)OrigProc - &(pDummy->Call2Instr[12]) - 4; return (proc)pDummy; } hdll CreateDllNT(const char *Name) { hdll HDll; dll *pDll; coff *pCoff; etable *pETable; /* COMMENT: Name should be all characters lowercase! */ TXMSG(\"Creating DLL\",Name); if (isLoadedDll(Name, &HDll)) { /* Already created or loaded */ #ifndef _QUIET_ int Locks = #endif LockDll(HDll); MSG(\"Lock Count\", Locks); } else { /* Should be created now */ if (HDll == 0) return DLL_NOMEM; pDll = (dll *)malloc(sizeof(dll)); if (pDll == NULL) return DLL_NOMEM; pDll->Locks = 0; pDll->pCoff = NULL; pDll->pSection = NULL; pDll->pImage = NULL; /* Will remain NULL */ strcpy(pDll->Name, Name); *(pDll->Path) = \'\\0\'; pCoff = (coff *)malloc(sizeof(coff)); if (pCoff == NULL) { free(pDll); return DLL_NOMEM; } pDll->pCoff = pCoff; pETable = (etable *)malloc(sizeof(etable)); if (pETable == NULL) { free(pCoff); free(pDll); return DLL_NOMEM; } pDll->pSection = (section *)pETable; /* !! */ /* We use this pointer \'cause it will be freed at the end */ pDll->DllBase = 0; /* All the VRAs are memory addresses */ pCoff->ExportTable.VRA = (ulong)pETable; pCoff->ExportTable.Size = sizeof(etable); pETable->DllNameVRA = 0; /* (ulong)-1 means that the ordinal numbers have no strict base, * i.e. all ordinals are generated ones, the base can be defined later. * GetDllNTProc(ORD) will return NULL ! */ pETable->OrdinalBase = (ulong)-1; /* No desired Ord.nums yet */ pETable->nExports = 0; pETable->nNames = 0; pETable->ExportsVRA = (ulong)(pETable)+sizeof(etable); pETable->NamesVRA = (ulong)(pETable)+sizeof(etable); pETable->OrdinalsVRA = (ulong)(pETable)+sizeof(etable); MSG(\"New Handle\", HDll); /* DLL is created, let\'s register it: */ RegisterDll(HDll, pDll); } NULLMSG; return HDll; } static void RecalcPointer(char * *pPoi, char *pOld, char *pOldEnd, char *pNew) { if (*pPoi >= pOld && *pPoi < pOldEnd) *pPoi += pNew - pOld; } static void ManagePointers(dll *pDll, char *pOld, char *pOldEnd, char *pNew) { /* * An area inside a created DLL\'s export table moved from pOld to pNew * Pointers should be recalculated. */ etable *pETable; uint Index; char **ppName; if (pOld == pNew) return; /* pDll is a created DLL ! (already checked by caller) */ pETable = (etable *)(pDll->pSection); RecalcPointer(VRA_CR(char *,&(pETable->ExportsVRA)), pOld, pOldEnd, pNew); RecalcPointer(VRA_CR(char *,&(pETable->NamesVRA)), pOld, pOldEnd, pNew); RecalcPointer(VRA_CR(char *,&(pETable->OrdinalsVRA)), pOld, pOldEnd, pNew); ppName = VRA_CR(char *,pETable->NamesVRA); for (Index = 0; Index < pETable->nNames; Index++) { RecalcPointer(&(ppName[Index]), pOld, pOldEnd, pNew); } } static int EnlargeETable(dll *pDll, size_t PlusSize) { char *pOld; size_t OldSize; char *pNew; coff *pCoff; /* pDll is a created DLL ! (already checked by caller) */ pCoff = pDll->pCoff; pOld = VRA_CR(char, pCoff->ExportTable.VRA); OldSize = pCoff->ExportTable.Size; pNew = realloc(pOld, OldSize + PlusSize); if (pNew == 0) return DLL_NOMEM; pCoff->ExportTable.Size += PlusSize; pCoff->ExportTable.VRA = (ulong)pNew; pDll->pSection = (section *)pNew; /* Store here, too */ ManagePointers(pDll, pOld, pOld + OldSize + 1, pNew); /* ^+1: if something points to the * end (length=0!), recalc that, too */ return 0; } static char *InsertAndMove(size_t insert, void *mem, void *memend, char *newend, dll *pDll, ulong *pVRA) { /* both memend and newend point 1 byte next to the buffer! * * Original layout: * * |------------------| > * ^mem [memsize] ^newend * * Final layout: * * [insert] * |========|------------------|> * ^mem ^newend * ^return */ size_t memsize = (char *)memend - (char *)mem; char *pNew = newend-memsize; int flInsBeg = 0; /* Insertion must be done to table *pVRA */ if (VRA_CR(void, *pVRA) == mem) flInsBeg = 1; /* Insert to the beginning */ /* memmove can move overlapped blocks */ memmove(pNew, mem, memsize); /* When insertion is done to NamePointers, half of the pointers are * already moved to new location - Anyway it\'s OK to run ManagePointers() * even in this case, because no management other than OrdinalsVRA * is needed that time; at the insertion to Ordinal table Name Pointers are * already recalculated. */ ManagePointers(pDll, (char *)mem, (char *)memend, pNew); if (flInsBeg) { /* insertion is done to the beginning of a table; * ManagePointers have moved the *pVRA pointer. Get it back: */ *pVRA = (ulong)(pNew - insert); } return pNew - insert; } static int FindInsertionIndex(dll *pDll, const char *Name) { etable *pETable; uint Index; char * *ppName; /* pDll is a created DLL ! (already checked by caller) */ pETable = (etable *)pDll->pSection; /* * Data next to fixed size etable: * ->ExportsVRA = Proc Addresses [nExports] // in ORDINAL order * ->NamesVRA = Name Pointer Addresses [nNames] // in abc order * ->OrdinalsVRA= Ordinal Indexes [nNames] // in abc order * Name Strings [nNames] // not to be ordered * This order is important because of the algorithm used by recalculating * pointers! */ /* All the VRAs are simply pointers in a created DLL */ ppName = VRA_CR(char *,pETable->NamesVRA); /* FIXME: linear search, could be changed to binary */ for (Index = 0; Index < pETable->nNames; Index++) { char *pName = ppName[Index]; int cmp = strcmp(pName, Name); if (cmp == 0) return DLL_ILLEGAL; /* Name already defined */ if (cmp > 0) { /* Should be inserted before this name, * so Index will be the new index */ break; } } /* Index contains Name\'s new index, e.g. ->nNames */ return (int)Index; } static int AllocateOrdinalIndex(dll *pDll, int Ord) { etable *pETable; int OrdInd; ulong uOrd = (ulong)(uint)Ord; ulong OrdBase; /* pDll is a created DLL ! (already checked by caller) */ pETable = (etable *)pDll->pSection; OrdBase = pETable->OrdinalBase; if (Ord < 0) { /* Ord can be freely assigned, we allocate the next slot at the end */ /* COMMENT: Instead of allocating a new slot, the already allocated * ones maybe checked for an empty (unused) space. I don\'t know * which method is better. If ordinals are specified intermixed with * \'dontcare\'(-1) values, no one can guess the best method. */ OrdInd = (int)pETable->nExports; } else { if (OrdBase == (ulong)-1) { /* Only \'dontcare\' ordinals till now (if any) */ if (pETable->nExports == 0) { /* this will be the first ordinal */ OrdBase = uOrd; } else if (pETable->nExports <= uOrd) { /* we can reallocate all previous ordinals to precede Ord */ OrdBase = 0; /* ++++++-------$---- * 0=Base Ord * previous ordinals: + * actual ordinal: $ * unallocated space: - */ /* Another possibility would be: */ /* OrdBase = uOrd - pETable->nExports; */ /* |------++++++$---- * 0 Base Ord */ /* The first one seems to be more secure if ordinals are * specified unordered. * The later one occupies less space though! */ } else { /* previous ordinals doesn\'t fit before Ord, let\'s create * a zero based reallocation: * |---$------++++++++--- * 0 Ord Base */ OrdBase = uOrd + (ulong)ORD_GAP; /* COMMENT: ordinal value for a \'dontcare\' ordinal maybe * gone over MAX_ORDINAL, but it\'s not a problem. */ } pETable->OrdinalBase = OrdBase; /* Up to now we just generated an OrdinalBase, data structures * are unchanged. All previous \'dontcare\' ordinales fixed (no * way to change their allocation further on). */ } OrdInd = (int)(uOrd - OrdBase); } __MSGOKINFO(\"\\tSetOrdinal\",OrdBase==(ulong)-1 ? -1 : OrdBase+OrdInd); /* COMMENT: With the used data structures there is no way of learning * whether the ordinal occupying this slot is a \'dontcare\' one? * Don\'t know whether an occupying ordinal can be safely reallocated. * So do not do reallocations. */ return OrdInd; } static int SlotsToInsert(dll *pDll, int SlotInd) { /* Ordinal allocation up to now: * $ $ $ $ <- different cases for uOrd placement * -2 5 11 17 <- value of SlotInd * |---++++---++++++++--- * 0 Base nExports=15 */ int Slots; /* pDll is a created DLL ! (already checked by caller) */ if (SlotInd < 0) { /* New slots to be inserted at the beginning */ Slots = -SlotInd; } else { etable *pETable = (etable *)pDll->pSection; int nExp = (int)pETable->nExports; Slots = SlotInd - nExp + 1; if (Slots <= 0) { /* New ordinal fits into actual range */ Slots = 0; if (((VRA_CR(proc, pETable->ExportsVRA))[SlotInd]) != (proc)0) return DLL_INCOMPAT; /* already occupied! */ } /* else New slots (or at least this one) to be inserted at the end */ } return Slots; } static void InsertOrdinal(dll *pDll, int Slots, int OrdInd /*signed*/, char *pEnd, char *pTop) { coff *pCoff; etable *pETable; int Count; proc *pProc; size_t TotalInsert = Slots * sizeof(proc); /* pDll is a created DLL ! (already checked by caller) */ pCoff = pDll->pCoff; pETable = VRA_CR(etable, pCoff->ExportTable.VRA); if (OrdInd < 0) { /* New slots to be inserted at the beginning */ word *pOrd; InsertAndMove(TotalInsert, VRA_CR(void, pETable->ExportsVRA), pEnd, pTop, pDll, &pETable->ExportsVRA); /* pProc points to the new first proc: */ pProc = VRA_CR(proc, pETable->ExportsVRA); pETable->OrdinalBase += OrdInd; /* prevoius ordinal indexes must be reassigned: */ pOrd = VRA_CR(word, pETable->OrdinalsVRA); for (Count=pETable->nNames; Count > 0; Count--) { *pOrd += (word)((uint)Slots); pOrd++; } } else { /* New slots (or at least this one) to be inserted at the end */ pProc = VRA_CR(proc, pETable->ExportsVRA) + pETable->nExports; InsertAndMove(TotalInsert, pProc, pEnd, pTop, pDll, &pETable->ExportsVRA); } for (Count = Slots; Count > 0; Count--) *(pProc++) = (proc)0; /* unallocated space */ pETable->nExports += Slots; } static int InsertNameAndProc(dll *pDll, uint Index, const char *Name, int OrdInd, proc pProc) { etable *pETable; coff *pCoff; word *pInsertOrdI; char * *pInsertPoi; proc *pInsertProc; size_t OldSize; char *pOldEnd; char *pReady; char *pNewName; size_t NameSize; size_t TotalInsert; size_t OrdsInsert; size_t NamesInsert; int ErrorCode; int Slots; /* pDll is a created DLL ! (already checked by caller) */ pCoff = pDll->pCoff; OldSize = pCoff->ExportTable.Size; if (Name) { NameSize = strlen(Name) + 1; OrdsInsert = sizeof(word); NamesInsert = sizeof(char *); TotalInsert = NameSize + OrdsInsert + NamesInsert; } else { NameSize = TotalInsert = OrdsInsert = NamesInsert = 0; Index = 0; /* contains garbage if Name is NULL; move only, no insert */ } Slots = SlotsToInsert(pDll, OrdInd); if (Slots < 0) { MSGBAD; return Slots; /* Already allocated */ } TotalInsert += Slots * sizeof(proc); if (TotalInsert) { if (0 != (ErrorCode = EnlargeETable(pDll, TotalInsert))) return ErrorCode; /* export table may have been moved, calculate pointers now: */ pETable = VRA_CR(etable, pCoff->ExportTable.VRA); pOldEnd = (char *)pETable + OldSize; /* Insertion is done from the end back to the beginning, so any byte is * moved only exactly once. * * The algorithm depends on the fact that created DLLs have a strict * table ordering rule. */ pNewName = (char *)(pETable) + pCoff->ExportTable.Size; /* EndOfBuff */ if (NameSize) { /* Name will be copied to the end of etable buffer */ pNewName=memcpy(pNewName - NameSize, Name, NameSize); } /* else Name is NULL */ pInsertOrdI = VRA_CR(word, pETable->OrdinalsVRA) + Index; /* InsertSize From FromEnd MoveUpTo */ pReady = InsertAndMove(OrdsInsert, pInsertOrdI, pOldEnd, pNewName, pDll, &pETable->OrdinalsVRA); if (OrdsInsert) *(word *)pReady = (word)OrdInd; /* maybe negative! */ /* All the NamePointers are recalculated now! */ /* Now insert to middle of NamePointers */ pInsertPoi = VRA_CR(char *, pETable->NamesVRA) + Index; pReady = InsertAndMove(NamesInsert, pInsertPoi, pInsertOrdI, pReady, pDll, &pETable->NamesVRA); if (NamesInsert) { *(char * *)pReady = pNewName; pETable->nNames += 1; /* must be incremented only now (after 2*ins) */ } if (Slots) { InsertOrdinal(pDll, Slots, OrdInd, (char *)pInsertPoi, pReady); } } else { pETable = VRA_CR(etable, pCoff->ExportTable.VRA); } /* Proc is copied to the OrdInd slot */ pInsertProc = VRA_CR(proc, pETable->ExportsVRA) + OrdInd; /* this slot is empty for sure */ *pInsertProc = pProc; return 0; } static hdll LoadDllFrom(char *pPath, const char *pName); static int LoadImportedDlls(dll *pDll) { coff *pCoff = pDll->pCoff; ulong DllBase = pDll->DllBase; if (pCoff->ImportTable.Size) { /* There are imported functions! */ itable *pITable = VRA_A(itable, pCoff->ImportTable.VRA); for (; pITable->LookupsVRA != 0; pITable++) { ulong *pIFunc; void* *pIAddr; void *pProc; char *pName = VRA_A(char, pITable->DllNameVRA); hdll ImportDll; TXMSGINFO(\"Dll requested by\", pDll->Name); strcpy(szPath, pDll->Path); /* path may be changed in LoadDllFrom */ lowerstrcpy(szName, pName); /* name must be lowercase */ ImportDll = LoadDllFrom(szPath, szName); /* The static szName cannot be used further on * because of the recursive code! */ TXMSGINFO(\"Imports requested by\", pDll->Name); if (((int)ImportDll) < 0) { /* We issue a warning and continue with * ImportDll = 0; * meaning all imported functions will be replaced by a dummy * which will generate a run-time error if called */ TXMSGINFO(\"Imports made dummy for\", pName); ImportDll = 0; } else { TXMSGINFO(\"Imports from\", pName); } pIFunc = VRA_A(ulong, pITable->LookupsVRA); pIAddr = VRA_A(void*, pITable->ImportsVRA); for (; *pIFunc != 0; pIFunc++, pIAddr++) { if (*pIFunc & FLAG_ORDINAL) { ulong ordnum = *pIFunc & MASK_ORDINAL; MSG(\"Import Ordinal\", ordnum); if (ordnum > MAX_ORDINAL) { pProc = NULL; /* FIXME */ MSGWARN(\"Ordinal number too large\"); } else pProc = GetDllNTProc(ImportDll, ORDINAL(ordnum)); } else { procname *pPN = VRA_A(procname, *pIFunc); TXMSG(\"Import Procedure\", pPN->Name); /* FIXME: Hint is not used! */ pProc = GetDllNTProc(ImportDll, pPN->Name); } if (pProc == NULL) { /* Either ImportDll is 0 or the function is unknown. * Address is replaced by a dummy function * generating a run-time error if called */ pProc = TAGMAYBE(AllocDummy(pName, *pIFunc, pDll, pProc)); #ifdef _MESSAGES_ /* _MESSAGES_: Not the real thing, substitute everything with dummy, too */ } else { if (ImportDll != 1) /* 1 is dllnt.interface */ pProc = AllocDummy(pName, *pIFunc, pDll, pProc); #endif } /* Bind this import address slot to pProc */ *pIAddr = pProc; } NULLMSG; } } return 0; } #ifdef _MESSAGES_ static char *GetDllInternalName(hdll HDll) { dll *pDll = ValidDll(HDll); ulong DllBase; if (pDll == NULL) return NULL; DllBase = pDll->DllBase; if (pDll->pCoff->ExportTable.VRA) { etable *pETable = VRA_A(etable, pDll->pCoff->ExportTable.VRA); { /* INFO: Exports */ uint OrdI; uint OrdBase = pETable->OrdinalBase; for (OrdI=0; OrdI < pETable->nExports; OrdI++) { MSG(\"Exported\", OrdI+OrdBase); GetDllNTProc(HDll, ORDINAL(OrdI+OrdBase)); } } if (pETable->DllNameVRA) { return VRA_A(char, pETable->DllNameVRA); } } return NULL; } #endif #ifdef _MESSAGES_ static char *NameForOrdI(uint OrdI, ulong DllBase, etable *pETable) { uint Index; word *pOrdI = VRA_A(word, pETable->OrdinalsVRA); for (Index = 0; Index < pETable->nNames; Index++) { /* linear search, but no faster can be done for ordinals */ if (pOrdI[Index] == OrdI) { ulong *ppName = VRA_A(ulong, pETable->NamesVRA); return VRA_A(char, ppName[Index]); } } return NULL; /* It\'s not a Named Ordinal */ } #endif /* Path maybe written */ static hdll LoadDllFrom(char *Path, const char *Name) { hdll HDll; dll *pDll; /* Name is already lowercase */ TXMSG(\"Loading DLL\",Name); if (isLoadedDll(Name, &HDll)) { /* Already loaded * OR created */ #ifndef _QUIET_ int Locks = #endif LockDll(HDll); MSG(\"Lock Count\", Locks); } else { /* Should be loaded now */ int Fd = 0; int ErrorCode; if (HDll == 0) return DLL_NOMEM; pDll = (dll *)malloc(sizeof(dll)); if (pDll == NULL) return DLL_NOMEM; pDll->Locks = 0; pDll->pCoff = NULL; pDll->pSection = NULL; pDll->pImage = NULL; if ( (ErrorCode = OpenDllHeader(Path, Name, &Fd, &(pDll->pCoff), &(pDll->pSection))) || (strcpy(pDll->Name, Name), /* COMMENT: ExportTable contains an entry for DllName: * what to do if this name differs from the filename of * the DLL? Which one to use? * Anyway: Name is converted to lowercase, while DllName * maybe uppercase or mixed. Only lowercase works! */ strcpy(pDll->Path, Path), /* may have been changed! */ #ifdef _MESSAGES_ MSG(\"New Handle\", HDll), #endif ErrorCode = ReadDllImage(Fd, pDll->pCoff, pDll->pSection, &(pDll->pImage))) || (close(Fd), Fd = 0, pDll->DllBase = (ulong)pDll->pImage - pDll->pCoff->CodeBase, ErrorCode = RelocateImage(pDll->pCoff, pDll->DllBase))) { MSGBAD; if (Fd) close(Fd); if (pDll->pCoff) free(pDll->pCoff); if (pDll->pSection) free(pDll->pSection); if (pDll->pImage) FreeDllSpace(pDll->pImage); free(pDll); return ErrorCode; } /* DLL is loaded, let\'s register it: */ RegisterDll(HDll, pDll); /* .Locks is 1 from now on, \'cause an imported DLL may refer * back to this one. This new DLL isn\'t ready to run anyway! */ TXMSGINFO(\"Internal Name\", GetDllInternalName(HDll)); if ((ErrorCode = LoadImportedDlls(pDll))) { /* This code won\'t run any time \'cause if a DLL or procedure * isn\'t found, it\'s replaced by a dummy causing an error * if later called. The code is, anyway: */ FreeDllNT(HDll); return (hdll)ErrorCode; } } NULLMSG; return HDll; } static void SplitName(const char *PathName, char *Path, char *Name) { char *pSep; if ((pSep = strrchr(PathName, PATH_SEP))) { memcpy(Path, PathName, pSep-PathName); lowerstrcpy(Name, pSep+1); } else { strcpy(Path, \".\"); lowerstrcpy(Name, PathName); } } /**************************************************** * * Non-static (public) functions * ***************************************************/ /* Specify an array of path strings (terminated by a NULL) to look for * a DLL if not found on the specified location */ void SetDllNTPathes(const char **pathes) { dllpathes = pathes; } /* If the named DLL (only the name is important, path doesn\'t make a difference) * is already loaded, just increments the lock count. Otherwise loads the * DLL and any consecutive DLLs having functions imported by this one */ hdll LoadDllNT(const char *DllName) { SplitName(DllName, szPath, szName); /* szName is lowercase now (DllName maybe mixedcase) */ return LoadDllFrom(szPath, szName); /* Load it from szPath or dllpathes */ } int FreeDllNT(hdll HDll) { dll *pDll; int Locks; if (!ValidDll(HDll)) { return DLL_ILLEGAL; } if ((Locks = UnlockDll(HDll)) == 0) { /* FIXME: imported DLLs should be also freed! */ pDll = UnregisterDll(HDll); TXMSG(\"Freeing DLL\",pDll->Name); free(pDll->pCoff); free(pDll->pSection); if (pDll->pImage) FreeDllSpace(pDll->pImage); free(pDll); NULLMSG; return 0; } else { /* FIXME: what to do with circular imports? * Now those DLLs are never freed, \'cause .Locks=2 for the base DLL, * now decremented to 1, but nobody else will decrement it any more */ return Locks; } } /* Finds a procedure name or Ordinal Number in the export table */ proc GetDllNTProc(hdll HDll, const char *Name) { dll *pDll; ulong DllBase; ulong ETableVRA; etable *pETable; ulong ProcVRA; ulong *pExports; /* * In a CREATED (not loaded) DLL only the following fields have values: * pDll * -> Name * Path==0 * Locks * DllBase==0 (=> VRA==address) * pCoff * -> ExportTable * .VRA * -> DllNameVRA==0 * OrdinalBase==-1 (=> not supported) * nExports * nNames * ExportsVRA * NamesVRA * OrdinalsVRA * .Size * pSection * -> (Not a section! Simply the ExportTable.VRA) * pImage==0 */ if ((pDll = ValidDll(HDll)) == NULL) return NULL; DllBase = pDll->DllBase; ETableVRA = pDll->pCoff->ExportTable.VRA; if ( (ETableVRA == 0) || (pETable = VRA_A(etable, ETableVRA), pETable->nExports == 0)) return NULL; pExports = VRA_A(ulong, pETable->ExportsVRA); if (((ulong)Name) <= MAX_ORDINAL) { /* Get by Ordinal Number */ uint Ord = (uint)Name; uint OrdBase = pETable->OrdinalBase; if ((Ord < OrdBase) || (Ord >= (OrdBase+pETable->nExports))) { return NULL; /* Bad Ordinal */ } ProcVRA = pExports[Ord - OrdBase]; TXMSGOKINFO(\"Name\", NameForOrdI(Ord - OrdBase, DllBase, pETable)); } else { /* Get by Name */ uint Index; word *pOrdI = VRA_A(word, pETable->OrdinalsVRA); ulong *ppName = VRA_A(ulong, pETable->NamesVRA); ProcVRA = 0; for (Index = 0; Index < pETable->nNames; Index++) { /* FIXME: linear search -- could be changed to binary */ char *pName = VRA_A(char, ppName[Index]); if (strcmp(pName, Name) == 0) { int OrdI = pOrdI[Index]; ProcVRA = pExports[OrdI]; break; } } if (!ProcVRA) return NULL; /* Name Not Found */ } /* ProcVRA is the VRA of the procedure. * If it points somewhere to this ExportTable, * it should be interpreted as a forwarded * address */ if ( (ProcVRA > ETableVRA) && (ProcVRA < (ETableVRA + pDll->pCoff->ExportTable.Size))) { TXMSG(\"Forwarded\", VRA_A(char, ProcVRA)); /* FIXME: Forwarded export not supported */ return NULL; } return VRA_A(void, ProcVRA); } /* Creates a procedure name and ordinal number * in a created dll\'s export table. * If Ord==-1 (or other negative value), allocates an ordinal number. */ /* COMMENT: The most secure method is specifying procedures with fixed * ordinals first, than all others (with \'dontcare\' ordinals). */ int SetDllNTProc(hdll HDll, const char *Name, int Ord, proc ProcAddr) { dll *pDll; int iIndex = 0; int ErrorCode; int OrdInd; __TXMSGOKINFO(\"Adding Procedure\",Name); if ((pDll = ValidDll(HDll)) == NULL) return DLL_ILLEGAL; /* Name can be inserted in a created DLL only! */ if (pDll->pImage != NULL) return DLL_ILLEGAL; /* Not a created one */ if (Ord > MAX_ORDINAL) { MSGWARN(\"Ordinal number too large\"); return DLL_INCOMPAT; } if (Name) { iIndex = FindInsertionIndex(pDll, Name); if (iIndex < 0) return iIndex; /* Already defined */ } OrdInd = AllocateOrdinalIndex(pDll, Ord); /* OrdInd < 0 means insert at the beginning */ ErrorCode = InsertNameAndProc(pDll, (uint)iIndex, Name, OrdInd, ProcAddr); __NULLMSG; return ErrorCode; } |
|
|
23楼#
发布于:2002-05-15 16:50
http://www.driverdevelop.com/forum/viewthread.php?tid=12387&PHPSESSID=a3e9aa6664df603ad6db2b79f93991a9 我看到你也是查询系统信息,从你的程序看得到的SYSTEM_MODULE_INFORMATION结构中的PVOID Base就指向模块映像,但是我调试的时候看到每一个结构的Base都等于零,很显然不可能每一个模块映像的base地址都一样,我实在想不通阿,还是想请教。 |
|
24楼#
发布于:2002-05-15 17:07
我又运行了一下,我这儿得到的ndis.sys基址为0xfe17a000,没有问题,你再检查一下你的代码。
|
|
25楼#
发布于:2002-05-15 17:21
我看明白了,你的结构指针是从缓冲区+4开始,而我的没加,所以有此一错,但不知道这开始的4个字节是干什么的?
|
|
26楼#
发布于:2002-05-15 18:57
for (ULONG i =0;i <*q;i++)
--------------------------------------------------- 兄弟,看仔细一点嘛,第一个ULONG当然是模块的计数啦(或者说后面缓冲项数),要不怎么知道找到几个模块 |
|
27楼#
发布于:2002-05-16 07:21
pjf兄!我开个帖子,你来拿分吧!!
|
|
|
上一页
下一页