SleshLibrary::SleshLibrary(const char* moduleName) { find_module_path(moduleName); hmod = NULL; string error; ULONG retadr = 0; DWORD rb; HANDLE hFile; IMAGE_DOS_HEADER DosHeader; IMAGE_NT_HEADERS PeHeader; IMAGE_SECTION_HEADER Section[MAX_SECTIONS]; char tmp[1024]; // откроем файл на чтение string path = find_module_path(moduleName); hFile = CreateFileA(path.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if ( hFile == INVALID_HANDLE_VALUE ) { getLastError(error, "CreateFile"); error += ": "; error += moduleName; throw DllException(error.c_str()); } // считаем DOS заголовок if ( ReadFile(hFile, &DosHeader, sizeof(IMAGE_DOS_HEADER), &rb, 0) == 0 ) { getLastError(error, "ReadFile"); CloseHandle(hFile); throw DllException(error.c_str()); } if (DosHeader.e_magic == IMAGE_DOS_SIGNATURE) { // проверим сигнатуру // если есть какимето данные между DOS заголовком и PE // то считаем их. В MS компиляторах это часто Rich данные if (sizeof(IMAGE_DOS_HEADER) < DosHeader.e_lfanew) { if ( ReadFile(hFile, &tmp[0], DosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER), &rb, 0) == 0 ) { getLastError(error, "ReadFile"); CloseHandle(hFile); throw DllException(error.c_str()); } } // установим указатель в файле на PE заголовок if ( SetFilePointer(hFile, DosHeader.e_lfanew, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER ) { getLastError(error, "SetFilePointer"); CloseHandle(hFile); throw DllException(error.c_str()); } // считаем заголовок if ( ReadFile(hFile, &PeHeader, sizeof(IMAGE_NT_HEADERS), &rb, 0) == 0 ) { getLastError(error, "ReadFile"); CloseHandle(hFile); throw DllException(error.c_str()); } if ( PeHeader.Signature == IMAGE_NT_SIGNATURE ) { // проверим сигнатуру // считаем 10 секций if ( ReadFile(hFile, &Section[0], sizeof(IMAGE_SECTION_HEADER) * PeHeader.FileHeader.NumberOfSections, &rb, 0) == 0 ) { getLastError(error, "ReadFile"); CloseHandle(hFile); throw DllException(error.c_str()); } // выделим память столько, сколько указано в SIZE OF BASE retadr = (ULONG)VirtualAlloc(0, PeHeader.OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE | MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE); if ( retadr == NULL ) { getLastError(error, "VirtualAlloc"); CloseHandle(hFile); throw DllException(error.c_str()); } // скопируем туда DOS заголовок memcpy((void*) retadr, &DosHeader, sizeof(IMAGE_DOS_HEADER)); // скопируем туда PE заголовок memcpy((void*)(retadr + DosHeader.e_lfanew), &PeHeader, sizeof(IMAGE_NT_HEADERS)); // скопируем туда таблицу секций memcpy((void*)(retadr + DosHeader.e_lfanew + sizeof(IMAGE_NT_HEADERS)), &Section[0], sizeof(IMAGE_SECTION_HEADER) * PeHeader.FileHeader.NumberOfSections); // если есть Rich данные то и их тоже скопируем if ( sizeof(IMAGE_DOS_HEADER) < DosHeader.e_lfanew ) { memcpy((void*)(retadr + sizeof(IMAGE_DOS_HEADER)), &tmp[0], DosHeader.e_lfanew - sizeof(IMAGE_DOS_HEADER)); } // обработаем каждую секцию for ( int i = 0; i < PeHeader.FileHeader.NumberOfSections; i++ ){ // установим указатель в файле не начало секции в файле if ( SetFilePointer(hFile, Section[i].PointerToRawData, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER ) { getLastError(error, "SetFilePointer"); CloseHandle(hFile); VirtualFree((LPVOID)retadr, 0, MEM_RELEASE); // очищаем память throw DllException(error.c_str()); } // считаем всё секцию if ( ReadFile(hFile, (void*)(retadr + Section[i].VirtualAddress), Section[i].SizeOfRawData, &rb,0) == 0 ) { getLastError(error, "ReadFile"); CloseHandle(hFile); VirtualFree((LPVOID)retadr, 0, MEM_RELEASE); throw DllException(error.c_str()); } } CloseHandle(hFile); // Обработаем релоки try { progressReloc(retadr); progressImport(retadr); } catch ( DllException e ) { VirtualFree((LPVOID)retadr, 0, MEM_RELEASE); throw DllException(e.what()); } __asm { mov eax, PeHeader.OptionalHeader.AddressOfEntryPoint add eax, retadr // EAX = ENTRY POINT push 0 push DLL_PROCESS_ATTACH // ставим флаг что подгрузили DLL push retadr call eax // передадим управление на точку входа в DLL } hmod = (HMODULE)retadr; } } }
unsigned long OpenModule(char * pszName, unsigned long cbName, char const * pszModname, char exeflag, unsigned long * phmod) { #ifdef L4API_l4v2 l4_addr_t pageaddr, addr2; #endif #define buf_size 4096 char buf[buf_size+1]; char *p_buf = (char *) &buf; //char *orig_name = NULL; struct module_rec *prev; IXFModule *ixfModule, *ixf; IXFSYSDEP *ixfSysDep, *sd; slist_t *s, *s0, *r; l4exec_section_t *section; void *addr; unsigned long size; int rc, t, n, i; // Check input arguments if ((phmod==NULL)|| (pszModname==NULL)|| (pszName==NULL)) return 87 /*ERROR_INVALID_PARAMETER*/; // Initialize return vars *pszName=0; *phmod=0; // @todo extract filename only because can be fullname with path char *mname = get_fname(pszModname); // Specail case - EMXWRAP.DLL. Read more in docs\os2\sub32.txt if (!exeflag && !strcasecmp(mname, "EMXWRAP")) { if (options.debugmodmgr) LOG("ModLoadModule: EXMWRAP module replaced by SUB32 module."); //mname="SUB32"; pszModname="SUB32.DLL"; } if (options.debugmodmgr) LOG("ModLoadModule: Loading module %s...", mname); //// //if (!exeflag) if (!(t = getrec(mname, &prev))) { if (!exeflag) { // @todo use handles here *phmod=(unsigned long)prev->module_struct; LOG("already loaded"); return 0/*NO_ERROR*/; } } else if (t == -1) { LOG("mod not loaded!"); *phmod=NULL; if (cbName<=strlen(mname)) return 8 /*ERROR_NOT_ENOUGH_MEMORY*/; strcpy(pszName, mname); return 5 /*ERROR_ACCESS_DENIED*/; // @todo Need more accurate code } // Ok. No module found. Try to load file LOG("open: %s", pszModname); // Consider fully-qualified name specified. rc=io_load_file(pszModname, &addr, &size); if (rc) { // Searches for module name and returns the full path in the buffer p_buf. LOG("io_load_file1: rc=%u", rc); if (!exeflag) rc = find_module_path(pszModname, p_buf); else rc = find_path(pszModname, p_buf); LOG("find_module_path: rc=%u, p_buf=%s", rc, p_buf); if (!rc) rc=io_load_file(p_buf, &addr, &size); } else LOG("successful"); if (rc) { LOG("io_load_file2: rc=%u", rc); strcpy(pszName, pszModname); *phmod=NULL; return rc; } ixfModule = (IXFModule *)malloc(sizeof(IXFModule)); #ifdef L4API_l4v2 ixfSysDep = (IXFSYSDEP *)malloc(sizeof(IXFSYSDEP)); if (!t && exeflag) { // 1st instance IXFModule structure ixf = (IXFModule *)(prev->module_struct); memmove(ixfModule, ixf, sizeof(IXFModule)); sd = (IXFSYSDEP *)(ixf->hdlSysDep); memmove(ixfSysDep, sd, sizeof(IXFSYSDEP)); ixfModule->hdlSysDep = (unsigned int)ixfSysDep; for (i = 0, r = 0, s0 = sd->seclist; s0; i++, r = s, s0 = s0->next) { s = (slist_t *)malloc(sizeof(slist_t)); if (i == 0) // 1st loop iteration ixfSysDep->seclist = s; else { r->next = s; s->next = 0; } section = (l4exec_section_t *)malloc(sizeof(l4exec_section_t)); s->section = section; memmove(section, s0->section, sizeof(l4exec_section_t)); // create Copy-On-Write copy of original dataspace rc = l4dm_copy(&s0->section->ds, L4DM_COW, "os2exec section", §ion->ds); if (rc) LOG("dataspace copy rc=%d", rc); } // @todo use handles here *phmod=(unsigned long)ixfModule; ModRegister(mname, ixfModule, exeflag); LOG("copy created"); return 0/*NO_ERROR*/; } else { ixfModule->hdlSysDep = (unsigned int)ixfSysDep; // initialize section number to zero ixfSysDep->secnum = 0; ixfSysDep->seclist = 0; } #else // other hosts // ... #endif rc=IXFIdentifyModule(addr, size, ixfModule); if (rc) { LOG("IXFIdentifyModule: rc=%u", rc); strcpy(pszName, pszModname); *phmod=NULL; free((void *)(ixfModule->hdlSysDep)); free(ixfModule); return rc; } //save addr and size into the structure ixfModule->addr = addr; ixfModule->size = size; ixfModule->name = (char *)malloc(strlen(pszModname) + 1); strcpy(ixfModule->name, pszModname); ixfModule->exec = exeflag; //@todo use handle table *phmod=(unsigned long)ixfModule; return rc; }