APR_DECLARE(apr_status_t) apr_shm_create_ex(apr_shm_t **m, apr_size_t reqsize, const char *file, apr_pool_t *pool, apr_int32_t flags) { static apr_size_t memblock = 0; HANDLE hMap, hFile; apr_status_t rv; apr_size_t size; apr_file_t *f; void *base; void *mapkey; DWORD err, sizelo, sizehi; reqsize += sizeof(memblock_t); if (!memblock) { SYSTEM_INFO si; GetSystemInfo(&si); memblock = si.dwAllocationGranularity; } /* Compute the granualar multiple of the pagesize */ size = memblock * (1 + (reqsize - 1) / memblock); sizelo = (DWORD)size; #ifdef _WIN64 sizehi = (DWORD)(size >> 32); #else sizehi = 0; #endif if (!file) { /* Do Anonymous, which must be passed as a duplicated handle */ #ifndef _WIN32_WCE hFile = INVALID_HANDLE_VALUE; #endif mapkey = NULL; } else { int global; /* Do file backed, which is not an inherited handle * While we could open APR_FOPEN_EXCL, it doesn't seem that Unix * ever did. Ignore that error here, but fail later when * we discover we aren't the creator of the file map object. */ rv = apr_file_open(&f, file, APR_FOPEN_READ | APR_FOPEN_WRITE | APR_FOPEN_BINARY | APR_FOPEN_CREATE, APR_FPROT_UREAD | APR_FPROT_UWRITE, pool); if ((rv != APR_SUCCESS) || ((rv = apr_os_file_get(&hFile, f)) != APR_SUCCESS)) { return rv; } rv = apr_file_trunc(f, size); /* res_name_from_filename turns file into a pseudo-name * without slashes or backslashes, and prepends the \global * or \local prefix on Win2K and later */ if (flags & APR_SHM_NS_GLOBAL) { global = 1; } else if (flags & APR_SHM_NS_LOCAL) { global = 0; } else { global = can_create_global_maps(); } mapkey = res_name_from_filename(file, global, pool); } #if APR_HAS_UNICODE_FS IF_WIN_OS_IS_UNICODE { hMap = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, sizehi, sizelo, mapkey); } #endif #if APR_HAS_ANSI_FS ELSE_WIN_OS_IS_ANSI { hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, sizehi, sizelo, mapkey); } #endif err = apr_get_os_error(); if (file) { apr_file_close(f); } if (hMap && APR_STATUS_IS_EEXIST(err)) { CloseHandle(hMap); return APR_EEXIST; } if (!hMap) { return err; } base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, size); if (!base) { CloseHandle(hMap); return apr_get_os_error(); } *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t)); (*m)->pool = pool; (*m)->hMap = hMap; (*m)->memblk = base; (*m)->size = size; (*m)->usrmem = (char*)base + sizeof(memblock_t); (*m)->length = reqsize - sizeof(memblock_t);; (*m)->memblk->length = (*m)->length; (*m)->memblk->size = (*m)->size; (*m)->filename = file ? apr_pstrdup(pool, file) : NULL; apr_pool_cleanup_register((*m)->pool, *m, shm_cleanup, apr_pool_cleanup_null); return APR_SUCCESS; }
/* checks that buffer (as found by matching the name) matches the info * (information is based on file type) * returns TRUE when file is found, FALSE to continue searching * (NB this is the opposite convention of SymFindFileInPathProc) */ static BOOL CALLBACK sffip_cb(PCWSTR buffer, PVOID user) { struct sffip* s = (struct sffip*)user; DWORD size, checksum; /* FIXME: should check that id/two/three match the file pointed * by buffer */ switch (s->kind) { case DMT_PE: { HANDLE hFile, hMap; void* mapping; DWORD timestamp; timestamp = ~(DWORD_PTR)s->id; size = ~s->two; hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) { if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) { IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping); timestamp = nth->FileHeader.TimeDateStamp; size = nth->OptionalHeader.SizeOfImage; UnmapViewOfFile(mapping); } CloseHandle(hMap); } CloseHandle(hFile); if (timestamp != (DWORD_PTR)s->id || size != s->two) { WARN("Found %s, but wrong size or timestamp\n", debugstr_w(buffer)); return FALSE; } } break; case DMT_ELF: if (elf_fetch_file_info(buffer, 0, &size, &checksum)) { if (checksum != (DWORD_PTR)s->id) { WARN("Found %s, but wrong checksums: %08x %08lx\n", debugstr_w(buffer), checksum, (DWORD_PTR)s->id); return FALSE; } } else { WARN("Couldn't read %s\n", debugstr_w(buffer)); return FALSE; } break; case DMT_PDB: { struct pdb_lookup pdb_lookup; char fn[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, buffer, -1, fn, MAX_PATH, NULL, NULL); pdb_lookup.filename = fn; if (!pdb_fetch_file_info(&pdb_lookup)) return FALSE; switch (pdb_lookup.kind) { case PDB_JG: if (s->flags & SSRVOPT_GUIDPTR) { WARN("Found %s, but wrong PDB version\n", debugstr_w(buffer)); return FALSE; } if (pdb_lookup.u.jg.timestamp != (DWORD_PTR)s->id) { WARN("Found %s, but wrong signature: %08x %08lx\n", debugstr_w(buffer), pdb_lookup.u.jg.timestamp, (DWORD_PTR)s->id); return FALSE; } break; case PDB_DS: if (!(s->flags & SSRVOPT_GUIDPTR)) { WARN("Found %s, but wrong PDB version\n", debugstr_w(buffer)); return FALSE; } if (memcmp(&pdb_lookup.u.ds.guid, (GUID*)s->id, sizeof(GUID))) { WARN("Found %s, but wrong GUID: %s %s\n", debugstr_w(buffer), debugstr_guid(&pdb_lookup.u.ds.guid), debugstr_guid((GUID*)s->id)); return FALSE; } break; } if (pdb_lookup.age != s->two) { WARN("Found %s, but wrong age: %08x %08x\n", debugstr_w(buffer), pdb_lookup.age, s->two); return FALSE; } } break; default: FIXME("What the heck??\n"); return FALSE; } /* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite * convention to stop/continue enumeration. sigh. */ return !(s->cb)((WCHAR*)buffer, s->user); }
int wmain() { HMODULE Module; HANDLE File = { 0 }; BYTE* MappedFile = { 0 }; BYTE* MappedFile_End = { 0 }; HANDLE FileMapping = { 0 }; ULARGE_INTEGER FileSize; DWORD Error = { 0 }; IMAGE_NT_HEADERS* NtHeaders = { 0 }; IMAGE_DOS_HEADER* DosHeader = { 0 }; size_t OffsetToPE = { 0 }; IMAGE_RESOURCE_DIRECTORY* TopDirectory = { 0 }; ULONG ResourcesSize = { 0 }; Module = LoadLibraryW(L".\\notepad.exe"); if (!EnumResourceTypesW(Module, EnumTypesProc, 0)) { DWORD Error = GetLastError(); wprintf(L"EnumResourceTypes failed %x\n", Error); } FreeLibrary(Module); File = CreateFileW(L".\\notepad.exe", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == File) { Error = GetLastError(); wprintf(L"CreateFile fails with error: %u", Error); goto Exit; } FileSize.LowPart = GetFileSize(File, &FileSize.HighPart); if ((FileSize.LowPart == -1) && ((Error = GetLastError()) != 0)) { wprintf(L"GetFileSize failed with error %u\n", Error); goto Exit; } if (FileSize.HighPart != 0) { wprintf(L"file too large\n"); goto Exit; } if (FileSize.QuadPart <= (sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS))) { wprintf(L"file too small\n"); goto Exit; } FileMapping = CreateFileMappingW(File, NULL, PAGE_READONLY, 0, 0, NULL); if (FileMapping == NULL) { Error = GetLastError(); wprintf(L"CreateFileMapping fails with error: %u", Error); goto Exit; } MappedFile = (BYTE*) MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0); if (MappedFile == NULL) goto Exit; wprintf(L"MappedFile:%p\n", MappedFile); MappedFile_End = (MappedFile + FileSize.QuadPart); DosHeader = (IMAGE_DOS_HEADER*) MappedFile; if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) { wprintf(L"invalid file"); goto Exit; } OffsetToPE = DosHeader->e_lfanew; if (OffsetToPE >= FileSize.QuadPart) { wprintf(L"invalid file"); goto Exit; } if ((OffsetToPE + sizeof(IMAGE_NT_HEADERS)) >= FileSize.QuadPart) { wprintf(L"invalid file"); goto Exit; } NtHeaders = (IMAGE_NT_HEADERS*) (MappedFile + OffsetToPE); if (NtHeaders->Signature != IMAGE_NT_SIGNATURE) { wprintf(L"invalid file"); goto Exit; } if (NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) { wprintf(L"invalid file"); goto Exit; } if (NtHeaders->OptionalHeader.NumberOfRvaAndSizes < IMAGE_DIRECTORY_ENTRY_RESOURCE) { wprintf(L"no resources"); goto Exit; } if (NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress == 0) { wprintf(L"no resources"); goto Exit; } if (NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size == 0) { wprintf(L"no resources"); goto Exit; } TopDirectory = (IMAGE_RESOURCE_DIRECTORY*) ImageDirectoryEntryToData(MappedFile, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &ResourcesSize); if (TopDirectory == NULL) { wprintf(L"no resources"); goto Exit; } DumpResourceDirectory(MappedFile, 0, TopDirectory, TopDirectory); Exit: if (MappedFile != NULL) UnmapViewOfFile(MappedFile); if (FileMapping != NULL) CloseHandle(FileMapping); if ((File != NULL) && (File != INVALID_HANDLE_VALUE)) CloseHandle(File); return 0; }
mapped_file::mapped_file(const string & fname, unsigned int io_open_mode, unsigned int create_size) : file_handle(0), map_handle(0), map_pointer(0) { #ifdef WIN32 string full_path = io::file::get_full_path(fname); // open file handle unsigned int win_open_mode = GENERIC_READ; if (io_open_mode & io::FILE_OPEN_WRITE) win_open_mode |= GENERIC_WRITE; if (file::exists(full_path)) { file_handle = CreateFileW(full_path.w_string(), win_open_mode, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (file_handle != INVALID_HANDLE_VALUE) create_size = GetFileSize(file_handle, 0); } else { if (create_size == 0) throw internal_exception(__FILE__, __LINE__, L"Must specify size for creating memory-mapped files."); file_handle = CreateFileW(full_path.w_string(), win_open_mode, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (file_handle != INVALID_HANDLE_VALUE) { unsigned char buf = 0; unsigned int written; SetFilePointer(file_handle, create_size-1, 0, FILE_BEGIN); WriteFile(file_handle, &buf, 1, (LPDWORD) &written, 0); SetFilePointer(file_handle, 0, 0, FILE_BEGIN); } } if (file_handle == INVALID_HANDLE_VALUE) throw io_exception(L"Unable to open %ls: %ls", full_path.w_string(), get_windows_error().w_string()); // create mapping string map_name = string::format(L"periapsis_mapped_file_%d", NUM_MAPPED_FILES++); if (io_open_mode & io::FILE_OPEN_WRITE) win_open_mode = PAGE_READWRITE; else win_open_mode = PAGE_READONLY; map_handle = CreateFileMappingW(file_handle, 0, win_open_mode, 0, create_size, map_name.w_string()); if (!map_handle) throw io_exception(L"Unable to create memory map for %ls: %ls", full_path.w_string(), get_windows_error().w_string()); // map file if (io_open_mode & io::FILE_OPEN_WRITE) win_open_mode = FILE_MAP_ALL_ACCESS; else win_open_mode = FILE_MAP_READ; map_pointer = MapViewOfFile(map_handle, win_open_mode, 0, 0, 0); if (!map_pointer) throw io_exception(L"Unable to create memory map for %ls: %ls", full_path.w_string(), get_windows_error().w_string()); map_size = create_size; #else #error Implement memory-mapped files! #endif } // mapped_file::mapped_file()
/* checks that buffer (as found by matching the name) matches the info * (information is based on file type) * returns TRUE when file is found, FALSE to continue searching * (NB this is the opposite convention of SymFindFileInPathProc) */ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user) { struct module_find* mf = user; DWORD size, checksum, timestamp; unsigned matched = 0; /* the matching weights: * +1 if a file with same name is found and is a decent file of expected type * +1 if first parameter and second parameter match */ /* FIXME: should check that id/two match the file pointed * by buffer */ switch (mf->kind) { case DMT_PE: { HANDLE hFile, hMap; void* mapping; timestamp = ~mf->dw1; size = ~mf->dw2; hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) { if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) { IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping); if (!nth) { UnmapViewOfFile(mapping); CloseHandle(hMap); CloseHandle(hFile); return FALSE; } matched++; timestamp = nth->FileHeader.TimeDateStamp; size = nth->OptionalHeader.SizeOfImage; UnmapViewOfFile(mapping); } CloseHandle(hMap); } CloseHandle(hFile); if (timestamp != mf->dw1) WARN("Found %s, but wrong timestamp\n", debugstr_w(buffer)); if (size != mf->dw2) WARN("Found %s, but wrong size\n", debugstr_w(buffer)); if (timestamp == mf->dw1 && size == mf->dw2) matched++; } break; case DMT_ELF: if (elf_fetch_file_info(buffer, 0, &size, &checksum)) { matched++; if (checksum == mf->dw1) matched++; else WARN("Found %s, but wrong checksums: %08x %08x\n", debugstr_w(buffer), checksum, mf->dw1); } else { WARN("Couldn't read %s\n", debugstr_w(buffer)); return FALSE; } break; case DMT_MACHO: if (macho_fetch_file_info(NULL, buffer, 0, 0, &size, &checksum)) { matched++; if (checksum == mf->dw1) matched++; else WARN("Found %s, but wrong checksums: %08x %08x\n", debugstr_w(buffer), checksum, mf->dw1); } else { WARN("Couldn't read %s\n", debugstr_w(buffer)); return FALSE; } break; case DMT_PDB: { struct pdb_lookup pdb_lookup; char fn[MAX_PATH]; WideCharToMultiByte(CP_ACP, 0, buffer, -1, fn, MAX_PATH, NULL, NULL); pdb_lookup.filename = fn; if (mf->guid) { pdb_lookup.kind = PDB_DS; pdb_lookup.timestamp = 0; pdb_lookup.guid = *mf->guid; } else { pdb_lookup.kind = PDB_JG; pdb_lookup.timestamp = mf->dw1; /* pdb_loopkup.guid = */ } pdb_lookup.age = mf->dw2; if (!pdb_fetch_file_info(&pdb_lookup, &matched)) return FALSE; } break; case DMT_DBG: { HANDLE hFile, hMap; void* mapping; timestamp = ~mf->dw1; hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != NULL) { if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) { const IMAGE_SEPARATE_DEBUG_HEADER* hdr; hdr = mapping; if (hdr->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE) { matched++; timestamp = hdr->TimeDateStamp; } UnmapViewOfFile(mapping); } CloseHandle(hMap); } CloseHandle(hFile); if (timestamp == mf->dw1) matched++; else WARN("Found %s, but wrong timestamp\n", debugstr_w(buffer)); } break; default: FIXME("What the heck??\n"); return FALSE; } if (matched > mf->matched) { strcpyW(mf->filename, buffer); mf->matched = matched; } /* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite * convention to stop/continue enumeration. sigh. */ return mf->matched == 2; }
int __cdecl main(int argc, char *argv[]) { const int MAPPINGSIZE = 2048; HANDLE hFileMapping; LPVOID lpMapViewAddress; char *p; int i; /* Initialize the PAL environment. */ if(0 != PAL_Initialize(argc, argv)) { return FAIL; } hFileMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, MAPPINGSIZE, NULL); if (hFileMapping == NULL) { Trace("ERROR:%u: CreateFileMappingW() failed\n", GetLastError()); Fail(""); } lpMapViewAddress = MapViewOfFile( hFileMapping, FILE_MAP_WRITE, /* access code */ 0, /* high order offset */ 0, /* low order offset */ MAPPINGSIZE); /* number of bytes for map */ if(NULL == lpMapViewAddress) { Trace("ERROR:%u: MapViewOfFile() failed.\n", GetLastError()); CloseHandle(hFileMapping); Fail(""); } p = (char *)lpMapViewAddress; for (i=0; i<MAPPINGSIZE; ++i) { /* Confirm that the memory is zero-initialized */ if (p[i] != 0) { Fail("MapViewOfFile() of pagefile didn't return 0-filled data " "(Offset %d has value 0x%x)\n", i, p[i]); } /* Confirm that it is writable */ *(char *)lpMapViewAddress = 0xcc; } /* Clean-up and Terminate the PAL. */ CloseHandle(hFileMapping); UnmapViewOfFile(lpMapViewAddress); PAL_Terminate(); return PASS; }
LRESULT WINAPI LresultFromObject( REFIID riid, WPARAM wParam, LPUNKNOWN pAcc ) { static const WCHAR atom_fmt[] = {'%','0','8','x',':','%','0','8','x',':','%','0','8','x',0}; static const LARGE_INTEGER seek_zero = {{0}}; WCHAR atom_str[sizeof(lresult_atom_prefix)/sizeof(WCHAR)+3*8+3]; IStream *stream; HANDLE mapping; STATSTG stat; HRESULT hr; ATOM atom; void *view; TRACE("%s %ld %p\n", debugstr_guid(riid), wParam, pAcc); if(wParam) FIXME("unsupported wParam = %lx\n", wParam); if(!pAcc) return E_INVALIDARG; hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); if(FAILED(hr)) return hr; hr = CoMarshalInterface(stream, riid, pAcc, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL); if(FAILED(hr)) { IStream_Release(stream); return hr; } hr = IStream_Seek(stream, seek_zero, STREAM_SEEK_SET, NULL); if(FAILED(hr)) { IStream_Release(stream); return hr; } hr = IStream_Stat(stream, &stat, STATFLAG_NONAME); if(FAILED(hr)) { CoReleaseMarshalData(stream); IStream_Release(stream); return hr; }else if(stat.cbSize.u.HighPart) { FIXME("stream size to big\n"); CoReleaseMarshalData(stream); IStream_Release(stream); return E_NOTIMPL; } mapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, stat.cbSize.u.HighPart, stat.cbSize.u.LowPart, NULL); if(!mapping) { CoReleaseMarshalData(stream); IStream_Release(stream); return hr; } view = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0); if(!view) { CloseHandle(mapping); CoReleaseMarshalData(stream); IStream_Release(stream); return E_FAIL; } hr = IStream_Read(stream, view, stat.cbSize.u.LowPart, NULL); UnmapViewOfFile(view); if(FAILED(hr)) { CloseHandle(mapping); hr = IStream_Seek(stream, seek_zero, STREAM_SEEK_SET, NULL); if(SUCCEEDED(hr)) CoReleaseMarshalData(stream); IStream_Release(stream); return hr; } memcpy(atom_str, lresult_atom_prefix, sizeof(lresult_atom_prefix)); sprintfW(atom_str+sizeof(lresult_atom_prefix)/sizeof(WCHAR), atom_fmt, GetCurrentProcessId(), HandleToUlong(mapping), stat.cbSize.u.LowPart); atom = GlobalAddAtomW(atom_str); if(!atom) { CloseHandle(mapping); hr = IStream_Seek(stream, seek_zero, STREAM_SEEK_SET, NULL); if(SUCCEEDED(hr)) CoReleaseMarshalData(stream); IStream_Release(stream); return E_FAIL; } IStream_Release(stream); return atom; }
/* ** Create the mutex and shared memory used for locking in the file ** descriptor pFile */ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){ WCHAR *zTok; WCHAR *zName = utf8ToUnicode(zFilename); BOOL bInit = TRUE; /* Initialize the local lockdata */ ZeroMemory(&pFile->local, sizeof(pFile->local)); /* Replace the backslashes from the filename and lowercase it ** to derive a mutex name. */ zTok = CharLowerW(zName); for (;*zTok;zTok++){ if (*zTok == '\\') *zTok = '_'; } /* Create/open the named mutex */ pFile->hMutex = CreateMutexW(NULL, FALSE, zName); if (!pFile->hMutex){ free(zName); return FALSE; } /* Acquire the mutex before continuing */ winceMutexAcquire(pFile->hMutex); /* Since the names of named mutexes, semaphores, file mappings etc are ** case-sensitive, take advantage of that by uppercasing the mutex name ** and using that as the shared filemapping name. */ CharUpperW(zName); pFile->hShared = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(winceLock), zName); /* Set a flag that indicates we're the first to create the memory so it ** must be zero-initialized */ if (GetLastError() == ERROR_ALREADY_EXISTS){ bInit = FALSE; } free(zName); /* If we succeeded in making the shared memory handle, map it. */ if (pFile->hShared){ pFile->shared = (winceLock*)MapViewOfFile(pFile->hShared, FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock)); /* If mapping failed, close the shared memory handle and erase it */ if (!pFile->shared){ CloseHandle(pFile->hShared); pFile->hShared = NULL; } } /* If shared memory could not be created, then close the mutex and fail */ if (pFile->hShared == NULL){ winceMutexRelease(pFile->hMutex); CloseHandle(pFile->hMutex); pFile->hMutex = NULL; return FALSE; } /* Initialize the shared memory if we're supposed to */ if (bInit) { ZeroMemory(pFile->shared, sizeof(winceLock)); } winceMutexRelease(pFile->hMutex); return TRUE; }
/****************************************************************** * pe_map_file * * Maps an PE file into memory (and checks it's a real PE file) */ static BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_type mt) { void* mapping; fmap->modtype = mt; fmap->u.pe.hMap = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL); if (fmap->u.pe.hMap == 0) return FALSE; fmap->u.pe.full_count = 0; fmap->u.pe.full_map = NULL; if (!(mapping = pe_map_full(fmap, NULL))) goto error; switch (mt) { case DMT_PE: { IMAGE_NT_HEADERS* nthdr; IMAGE_SECTION_HEADER* section; unsigned i; if (!(nthdr = RtlImageNtHeader(mapping))) goto error; memcpy(&fmap->u.pe.ntheader, nthdr, sizeof(fmap->u.pe.ntheader)); switch (nthdr->OptionalHeader.Magic) { case 0x10b: fmap->addr_size = 32; break; case 0x20b: fmap->addr_size = 64; break; default: return FALSE; } section = (IMAGE_SECTION_HEADER*) ((char*)&nthdr->OptionalHeader + nthdr->FileHeader.SizeOfOptionalHeader); fmap->u.pe.sect = HeapAlloc(GetProcessHeap(), 0, nthdr->FileHeader.NumberOfSections * sizeof(fmap->u.pe.sect[0])); if (!fmap->u.pe.sect) goto error; for (i = 0; i < nthdr->FileHeader.NumberOfSections; i++) { memcpy(&fmap->u.pe.sect[i].shdr, section + i, sizeof(IMAGE_SECTION_HEADER)); fmap->u.pe.sect[i].mapped = IMAGE_NO_MAP; } if (nthdr->FileHeader.PointerToSymbolTable && nthdr->FileHeader.NumberOfSymbols) { LARGE_INTEGER li; if (GetFileSizeEx(file, &li) && pe_is_valid_pointer_table(nthdr, mapping, li.QuadPart)) { /* FIXME ugly: should rather map the relevant content instead of copying it */ const char* src = (const char*)mapping + nthdr->FileHeader.PointerToSymbolTable + nthdr->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL); char* dst; DWORD sz = *(DWORD*)src; if ((dst = HeapAlloc(GetProcessHeap(), 0, sz))) memcpy(dst, src, sz); fmap->u.pe.strtable = dst; } else { WARN("Bad coff table... wipping out\n"); /* we have bad information here, wipe it out */ fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable = 0; fmap->u.pe.ntheader.FileHeader.NumberOfSymbols = 0; fmap->u.pe.strtable = NULL; } } else fmap->u.pe.strtable = NULL; } break; default: assert(0); goto error; } pe_unmap_full(fmap); return TRUE; error: pe_unmap_full(fmap); CloseHandle(fmap->u.pe.hMap); return FALSE; }
bool InitializeProfAPISharedObj() { gCAProfAPISharedMapFile = OpenFileMappingW(FILE_MAP_ALL_ACCESS, // read/write access FALSE, // do not inherit the name CPU_PROF_SHARED_OBJ); // name of mapping object if (!gCAProfAPISharedMapFile) { SECURITY_ATTRIBUTES secAttr; char secDesc[ SECURITY_DESCRIPTOR_MIN_LENGTH ]; secAttr.nLength = sizeof(secAttr); secAttr.bInheritHandle = FALSE; secAttr.lpSecurityDescriptor = &secDesc; bool bHasSD = false; OSVERSIONINFO osVersionInfo; osVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx(&osVersionInfo)) { if (osVersionInfo.dwMajorVersion >= 6) { // Vista, Longhorn or later; bHasSD = true; } } if (bHasSD) { PSECURITY_DESCRIPTOR pSD; PACL pSacl = nullptr; // not allocated BOOL fSaclPresent = FALSE; BOOL fSaclDefaulted = FALSE; ConvertStringSecurityDescriptorToSecurityDescriptorW(L"S:(ML;;NW;;;LW)", // this means "low integrity" SDDL_REVISION_1, &pSD, nullptr); GetSecurityDescriptorSacl(pSD, &fSaclPresent, &pSacl, &fSaclDefaulted); SetSecurityDescriptorSacl(secAttr.lpSecurityDescriptor, TRUE, pSacl, FALSE); } InitializeSecurityDescriptor(secAttr.lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(secAttr.lpSecurityDescriptor, TRUE, 0, FALSE); gCAProfAPISharedMapFile = CreateFileMappingW(INVALID_HANDLE_VALUE, &secAttr, // default security PAGE_READWRITE, // read/write access 0, // max. object size CPU_PROF_SHARED_MEM_SIZE, // buffer size CPU_PROF_SHARED_OBJ); // name of mapping object } if (gCAProfAPISharedMapFile) { return true; } else { return false; } }
CShareMemory::CShareMemory(LPCWSTR name,DWORD size,BOOL shareWrite):memfile(INVALID_HANDLE_VALUE) { filesize=size; DWORD dwRes; PSID pEveryoneSID = nullptr,pOwnerSID=nullptr; PACL pACL = nullptr; SECURITY_DESCRIPTOR SD; SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY SIDAuthOwner = SECURITY_CREATOR_SID_AUTHORITY; SECURITY_ATTRIBUTES sa; EXPLICIT_ACCESS *acclist=nullptr; __try { if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID)) { ATLTRACE("AllocateAndInitializeSid Error %u\n", GetLastError()); __leave; } int eacount=0; if(shareWrite) { eacount=1; acclist=(EXPLICIT_ACCESS *)calloc(eacount,sizeof(EXPLICIT_ACCESS)); if(acclist==nullptr) __leave; acclist[0].grfAccessPermissions = GENERIC_WRITE|GENERIC_READ; acclist[0].grfAccessMode = SET_ACCESS; acclist[0].grfInheritance= NO_INHERITANCE; acclist[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; acclist[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; acclist[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID; } else { eacount=2; acclist=(EXPLICIT_ACCESS *)calloc(eacount,sizeof(EXPLICIT_ACCESS)); if(acclist==nullptr) __leave; if(!AllocateAndInitializeSid(&SIDAuthOwner, 1, SECURITY_CREATOR_OWNER_RID, 0, 0, 0, 0, 0, 0, 0, &pOwnerSID)) { ATLTRACE("AllocateAndInitializeSid Error %u\n", GetLastError()); __leave; } acclist[0].grfAccessPermissions = GENERIC_READ; acclist[0].grfAccessMode = SET_ACCESS; acclist[0].grfInheritance= NO_INHERITANCE; acclist[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; acclist[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; acclist[0].Trustee.ptstrName = (LPTSTR) pEveryoneSID; acclist[1].grfAccessPermissions = GENERIC_READ|GENERIC_WRITE; acclist[1].grfAccessMode = SET_ACCESS; acclist[1].grfInheritance= NO_INHERITANCE; acclist[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; acclist[1].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; acclist[1].Trustee.ptstrName = (LPTSTR) pOwnerSID; } dwRes = SetEntriesInAcl(eacount, acclist, nullptr, &pACL); if (ERROR_SUCCESS != dwRes) { ATLTRACE("SetEntriesInAcl Error %u\n", GetLastError()); __leave; } // Initialize a security descriptor. if (!InitializeSecurityDescriptor(&SD, SECURITY_DESCRIPTOR_REVISION)) { ATLTRACE("InitializeSecurityDescriptor Error %u\n", GetLastError()); __leave; } // Add the ACL to the security descriptor. if (!SetSecurityDescriptorDacl(&SD, TRUE, // bDaclPresent flag pACL, FALSE)) // not a default DACL { ATLTRACE("SetSecurityDescriptorDacl Error %u\n", GetLastError()); __leave; } // Initialize a security attributes structure. sa.nLength = sizeof (SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = &SD; sa.bInheritHandle = FALSE; memfile=CreateFileMappingW(INVALID_HANDLE_VALUE,&sa,PAGE_READWRITE,0,filesize,name); if(memfile==INVALID_HANDLE_VALUE) __leave; if(GetLastError()==ERROR_ALREADY_EXISTS) ATLTRACE("file map exit\n"); p=MapViewOfFileEx(memfile,FILE_MAP_READ|FILE_MAP_WRITE,0,0,filesize,nullptr); } __finally { if (pEveryoneSID) FreeSid(pEveryoneSID); if (pOwnerSID) FreeSid(pOwnerSID); if (pACL) LocalFree(pACL); if(acclist) free(acclist); } }
int main(int argc, char *argv[]) { HANDLE map; bool srvr = true; if (argc > 1 && !strcmp(argv[1], "client")) { srvr = false; } HANDLE ev; /* create event */ if (srvr) { ev = CreateEventW(NULL, false, false, SHM_EVENT); } else { ev = OpenEventW(EVENT_ALL_ACCESS, false, SHM_EVENT); } if (ev == NULL) { printf("can't create/open event"); exit(1); } HANDLE mutex; if (srvr) { mutex = CreateMutex(NULL, false, SHM_MUTEX); } else { mutex = OpenMutex(SYNCHRONIZE, false, SHM_MUTEX); } if (mutex == NULL) { printf("mutex error\n"); exit(1); } /* Shared memory */ if (srvr) { map = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, SHM_NAME); } else { map = OpenFileMappingW(FILE_MAP_ALL_ACCESS, false, SHM_NAME); } if (map == NULL) { fprintf(stderr, "Can't get file mapping: %lu\n", GetLastError()); exit(1); } void *mem; mem = MapViewOfFile(map, FILE_MAP_ALL_ACCESS, 0, 0, 0); if (!mem) { fprintf(stderr, "MapViewOfFile() failed with %lu\n", GetLastError()); exit(2); } CloseHandle(map); struct my_mem *mm; mm = (struct my_mem *)mem; if (srvr == false) { /* writer */ printf("client\n"); mm->total = 4096; while(1) { int x = getchar(); WaitForSingleObject(mutex, INFINITE); printf("idx(%d) < total(%d)\n", mm->idx, mm->total); if (mm->idx < mm->total) { mm->arr[mm->idx] = x; mm->idx++; } SetEvent(ev); ReleaseMutex(mutex); /* end of file */ if (x < 0) break; } } else { /* reader */ while(1) { WaitForSingleObject(ev, INFINITE); WaitForSingleObject(mutex, INFINITE); int i; bool stop = false; for (i=0; i<mm->idx; i++) { if (mm->arr[i] < 0) stop = true; printf("%c", mm->arr[i]); } mm->idx = 0; ReleaseMutex(mutex); if (stop) break; } } UnmapViewOfFile(mem); CloseHandle(ev); CloseHandle(mutex); system("pause"); return 0; }
/*********************************************************************** * ImageGetDigestStream (IMAGEHLP.@) * * Gets a stream of bytes from a PE file over which a hash might be computed to * verify that the image has not changed. Useful for creating a certificate to * be added to the file with ImageAddCertificate. * * PARAMS * FileHandle [In] File for which to return a stream. * DigestLevel [In] Flags to control which portions of the file to return. * 0 is allowed, as is any combination of: * CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO: reports the entire * import section rather than selected portions of it. * CERT_PE_IMAGE_DIGEST_DEBUG_INFO: reports the debug section. * CERT_PE_IMAGE_DIGEST_RESOURCES: reports the resources section. * DigestFunction [In] Callback function. * DigestHandle [In] Handle passed as first parameter to DigestFunction. * * RETURNS * TRUE if successful. * FALSE if unsuccessful. GetLastError returns more about the error. * * NOTES * Only supports 32-bit PE files, not tested with any other format. * Reports data in the following order: * 1. The file headers are reported first * 2. Any code sections are reported next. * 3. The data (".data" and ".rdata") sections are reported next. * 4. The import section is reported next. * 5. If CERT_PE_IMAGE_DIGEST_DEBUG_INFO is set in DigestLevel, the debug section is * reported next. * 6. If CERT_PE_IMAGE_DIGEST_RESOURCES is set in DigestLevel, the resources section * is reported next. * * BUGS * CERT_PE_IMAGE_DIGEST_ALL_IMPORT_INFO must be specified, returns an error if not. */ BOOL WINAPI ImageGetDigestStream( HANDLE FileHandle, DWORD DigestLevel, DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle) { DWORD error = 0; BOOL ret = FALSE; DWORD offset, size, num_sections, fileSize; HANDLE hMap = INVALID_HANDLE_VALUE; BYTE *map = NULL; IMAGE_DOS_HEADER *dos_hdr; IMAGE_NT_HEADERS *nt_hdr; IMAGE_SECTION_HEADER *section_headers; TRACE("(%p, %d, %p, %p)\n", FileHandle, DigestLevel, DigestFunction, DigestHandle); /* Get the file size */ if( !FileHandle ) goto invalid_parameter; fileSize = GetFileSize( FileHandle, NULL ); if(fileSize == INVALID_FILE_SIZE ) goto invalid_parameter; /* map file */ hMap = CreateFileMappingW( FileHandle, NULL, PAGE_READONLY, 0, 0, NULL ); if( hMap == INVALID_HANDLE_VALUE ) goto invalid_parameter; map = MapViewOfFile( hMap, FILE_MAP_COPY, 0, 0, 0 ); if( !map ) goto invalid_parameter; /* Read the file header */ if( fileSize < sizeof(IMAGE_DOS_HEADER) ) goto invalid_parameter; dos_hdr = (IMAGE_DOS_HEADER *)map; if( dos_hdr->e_magic != IMAGE_DOS_SIGNATURE ) goto invalid_parameter; offset = dos_hdr->e_lfanew; if( !offset || offset > fileSize ) goto invalid_parameter; ret = DigestFunction( DigestHandle, map, offset ); if( !ret ) goto end; /* Read the NT header */ if( offset + sizeof(IMAGE_NT_HEADERS) > fileSize ) goto invalid_parameter; nt_hdr = (IMAGE_NT_HEADERS *)(map + offset); if( nt_hdr->Signature != IMAGE_NT_SIGNATURE ) goto invalid_parameter; /* It's clear why the checksum is cleared, but why only these size headers? */ nt_hdr->OptionalHeader.SizeOfInitializedData = 0; nt_hdr->OptionalHeader.SizeOfImage = 0; nt_hdr->OptionalHeader.CheckSum = 0; size = sizeof(nt_hdr->Signature) + sizeof(nt_hdr->FileHeader) + nt_hdr->FileHeader.SizeOfOptionalHeader; ret = DigestFunction( DigestHandle, map + offset, size ); if( !ret ) goto end; /* Read the section headers */ offset += size; num_sections = nt_hdr->FileHeader.NumberOfSections; size = num_sections * sizeof(IMAGE_SECTION_HEADER); if( offset + size > fileSize ) goto invalid_parameter; ret = DigestFunction( DigestHandle, map + offset, size ); if( !ret ) goto end; section_headers = (IMAGE_SECTION_HEADER *)(map + offset); IMAGEHLP_ReportCodeSections( section_headers, num_sections, map, fileSize, DigestFunction, DigestHandle ); IMAGEHLP_ReportSection( section_headers, num_sections, ".data", map, fileSize, DigestFunction, DigestHandle ); IMAGEHLP_ReportSection( section_headers, num_sections, ".rdata", map, fileSize, DigestFunction, DigestHandle ); IMAGEHLP_ReportImportSection( section_headers, num_sections, map, fileSize, DigestLevel, DigestFunction, DigestHandle ); if( DigestLevel & CERT_PE_IMAGE_DIGEST_DEBUG_INFO ) IMAGEHLP_ReportSection( section_headers, num_sections, ".debug", map, fileSize, DigestFunction, DigestHandle ); if( DigestLevel & CERT_PE_IMAGE_DIGEST_RESOURCES ) IMAGEHLP_ReportSection( section_headers, num_sections, ".rsrc", map, fileSize, DigestFunction, DigestHandle ); end: if( map ) UnmapViewOfFile( map ); if( hMap != INVALID_HANDLE_VALUE ) CloseHandle( hMap ); if( error ) SetLastError(error); return ret; invalid_parameter: error = ERROR_INVALID_PARAMETER; goto end; }
/*********************************************************************** * IMAGEHLP_RecalculateChecksum (INTERNAL) * * Update the NT header checksum for the specified file. */ static BOOL IMAGEHLP_RecalculateChecksum(HANDLE handle) { DWORD FileLength, count, HeaderSum, pe_offset, nt_hdr_size; IMAGE_NT_HEADERS32 nt_hdr32; IMAGE_NT_HEADERS64 nt_hdr64; LPVOID BaseAddress; HANDLE hMapping; DWORD *CheckSum; void *nt_hdr; int ret; BOOL r; TRACE("handle %p\n", handle); ret = IMAGEHLP_GetNTHeaders(handle, &pe_offset, &nt_hdr32, &nt_hdr64); if (ret == HDR_NT32) { CheckSum = &nt_hdr32.OptionalHeader.CheckSum; nt_hdr = &nt_hdr32; nt_hdr_size = sizeof(IMAGE_NT_HEADERS32); } else if (ret == HDR_NT64) { CheckSum = &nt_hdr64.OptionalHeader.CheckSum; nt_hdr = &nt_hdr64; nt_hdr_size = sizeof(IMAGE_NT_HEADERS64); } else return FALSE; hMapping = CreateFileMappingW(handle, NULL, PAGE_READONLY, 0, 0, NULL); if (!hMapping) return FALSE; BaseAddress = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); if (!BaseAddress) { CloseHandle(hMapping); return FALSE; } FileLength = GetFileSize(handle, NULL); *CheckSum = 0; CheckSumMappedFile(BaseAddress, FileLength, &HeaderSum, CheckSum); UnmapViewOfFile(BaseAddress); CloseHandle(hMapping); if (*CheckSum) { /* write the header back again */ count = SetFilePointer(handle, pe_offset, NULL, FILE_BEGIN); if (count == INVALID_SET_FILE_POINTER) return FALSE; count = 0; r = WriteFile(handle, nt_hdr, nt_hdr_size, &count, NULL); if (!r) return FALSE; if (count != nt_hdr_size) return FALSE; return TRUE; } return FALSE; }
static apr_status_t shm_attach_internal(apr_shm_t **m, const char *file, apr_pool_t *pool, int global) { HANDLE hMap; void *mapkey; void *base; /* res_name_from_filename turns file into a pseudo-name * without slashes or backslashes, and prepends the \global * or local prefix on Win2K and later */ mapkey = res_name_from_filename(file, global, pool); #if APR_HAS_UNICODE_FS IF_WIN_OS_IS_UNICODE { #ifndef _WIN32_WCE hMap = OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapkey); #else /* The WCE 3.0 lacks OpenFileMapping. So we emulate one with * opening the existing shmem and reading its size from the header */ hMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(apr_shm_t), mapkey); #endif } #endif #if APR_HAS_ANSI_FS ELSE_WIN_OS_IS_ANSI { hMap = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapkey); } #endif if (!hMap) { return apr_get_os_error(); } base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); if (!base) { CloseHandle(hMap); return apr_get_os_error(); } *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t)); (*m)->pool = pool; (*m)->memblk = base; /* Real (*m)->mem->size could be recovered with VirtualQuery */ (*m)->size = (*m)->memblk->size; #if _WIN32_WCE /* Reopen with real size */ UnmapViewOfFile(base); CloseHandle(hMap); hMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, (*m)->size, mapkey); if (!hMap) { return apr_get_os_error(); } base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); if (!base) { CloseHandle(hMap); return apr_get_os_error(); } #endif (*m)->hMap = hMap; (*m)->length = (*m)->memblk->length; (*m)->usrmem = (char*)base + sizeof(memblock_t); (*m)->filename = NULL; apr_pool_cleanup_register((*m)->pool, *m, shm_cleanup, apr_pool_cleanup_null); return APR_SUCCESS; }
HMODULE CustomLoadLibrary(const PWCHAR wszFullDllName, const PWCHAR wszBaseDllName, ULONG_PTR pDllBase) { // File handles HANDLE hFile = INVALID_HANDLE_VALUE; HANDLE hMap = NULL; PCHAR pFile = NULL; // PE headers PIMAGE_DOS_HEADER pDosHeader; PIMAGE_NT_HEADERS pNtHeader; PIMAGE_SECTION_HEADER pSectionHeader; // Library PCHAR pLibraryAddr = NULL; DWORD dwIdx; // Relocation PIMAGE_DATA_DIRECTORY pDataDir; PIMAGE_BASE_RELOCATION pBaseReloc; ULONG_PTR pReloc; DWORD dwNumRelocs; ULONG_PTR pInitialImageBase; PIMAGE_RELOC pImageReloc; // Import PIMAGE_IMPORT_DESCRIPTOR pImportDesc; PCHAR szDllName; SIZE_T stDllName; PWSTR wszDllName = NULL; PWCHAR wsRedir = NULL; PWSTR wszRedirName = NULL; SIZE_T stRedirName; SIZE_T stSize; HMODULE hModule; PIMAGE_THUNK_DATA pThunkData; FARPROC* pIatEntry; // clr.dll hotpatches itself at runtime for performance reasons, so skip it if (wcscmp(L"clr.dll", wszBaseDllName) == 0) goto cleanup; dprintf("[REFRESH] Opening file: %S", wszFullDllName); // ---- // Step 1: Map the file into memory // ---- hFile = CreateFileW(wszFullDllName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) goto cleanup; hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if (hMap == NULL) goto cleanup; pFile = (PCHAR)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0); if (pFile == NULL) goto cleanup; // ---- // Step 2: Parse the file headers and load it into memory // ---- pDosHeader = (PIMAGE_DOS_HEADER)pFile; pNtHeader = (PIMAGE_NT_HEADERS)(pFile + pDosHeader->e_lfanew); // allocate memory to copy DLL into dprintf("[REFRESH] Allocating memory for library"); pLibraryAddr = (PCHAR)VirtualAlloc(NULL, pNtHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // copy header dprintf("[REFRESH] Copying PE header into memory"); memcpy(pLibraryAddr, pFile, pNtHeader->OptionalHeader.SizeOfHeaders); // copy sections dprintf("[REFRESH] Copying PE sections into memory"); pSectionHeader = (PIMAGE_SECTION_HEADER)(pFile + pDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS)); for (dwIdx = 0; dwIdx < pNtHeader->FileHeader.NumberOfSections; dwIdx++) { memcpy(pLibraryAddr + pSectionHeader[dwIdx].VirtualAddress, pFile + pSectionHeader[dwIdx].PointerToRawData, pSectionHeader[dwIdx].SizeOfRawData); } // update our pointers to the loaded image pDosHeader = (PIMAGE_DOS_HEADER)pLibraryAddr; pNtHeader = (PIMAGE_NT_HEADERS)(pLibraryAddr + pDosHeader->e_lfanew); // ---- // Step 3: Calculate relocations // ---- dprintf("[REFRESH] Calculating file relocations"); pDataDir = &pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC]; pInitialImageBase = pNtHeader->OptionalHeader.ImageBase; // set the ImageBase to the already loaded module's base pNtHeader->OptionalHeader.ImageBase = pDllBase; // check if their are any relocations present if (pDataDir->Size) { // calculate the address of the first IMAGE_BASE_RELOCATION entry pBaseReloc = (PIMAGE_BASE_RELOCATION)(pLibraryAddr + pDataDir->VirtualAddress); // iterate through each relocation entry while ((PCHAR)pBaseReloc < (pLibraryAddr + pDataDir->VirtualAddress + pDataDir->Size) && pBaseReloc->SizeOfBlock) { // the VA for this relocation block pReloc = (ULONG_PTR)(pLibraryAddr + pBaseReloc->VirtualAddress); // number of entries in this relocation block dwNumRelocs = (pBaseReloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC); // first entry in the current relocation block pImageReloc = (PIMAGE_RELOC)((PCHAR)pBaseReloc + sizeof(IMAGE_BASE_RELOCATION)); // iterate through each entry in the relocation block while (dwNumRelocs--) { // perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required. // we subtract the initial ImageBase and add in the original dll base if (pImageReloc->type == IMAGE_REL_BASED_DIR64) { *(ULONG_PTR *)(pReloc + pImageReloc->offset) -= pInitialImageBase; *(ULONG_PTR *)(pReloc + pImageReloc->offset) += pDllBase; } else if (pImageReloc->type == IMAGE_REL_BASED_HIGHLOW) { *(DWORD *)(pReloc + pImageReloc->offset) -= (DWORD)pInitialImageBase; *(DWORD *)(pReloc + pImageReloc->offset) += (DWORD)pDllBase; } else if (pImageReloc->type == IMAGE_REL_BASED_HIGH) { *(WORD *)(pReloc + pImageReloc->offset) -= HIWORD(pInitialImageBase); *(WORD *)(pReloc + pImageReloc->offset) += HIWORD(pDllBase); } else if (pImageReloc->type == IMAGE_REL_BASED_LOW) { *(WORD *)(pReloc + pImageReloc->offset) -= LOWORD(pInitialImageBase); *(WORD *)(pReloc + pImageReloc->offset) += LOWORD(pDllBase); } // get the next entry in the current relocation block pImageReloc = (PIMAGE_RELOC)((PCHAR)pImageReloc + sizeof(IMAGE_RELOC)); } // get the next entry in the relocation directory pBaseReloc = (PIMAGE_BASE_RELOCATION)((PCHAR)pBaseReloc + pBaseReloc->SizeOfBlock); } } // ---- // Step 4: Update import table // ---- dprintf("[REFRESH] Resolving Import Address Table (IAT) "); pDataDir = &pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; if (pDataDir->Size) { pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pLibraryAddr + pDataDir->VirtualAddress); while (pImportDesc->Characteristics) { hModule = NULL; wszDllName = NULL; szDllName = (PCHAR)(pLibraryAddr + pImportDesc->Name); stDllName = strnlen(szDllName, MAX_PATH); wszDllName = (PWSTR)calloc(stDllName + 1, sizeof(WCHAR)); if (wszDllName == NULL) goto next_import; mbstowcs_s(&stSize, wszDllName, stDllName + 1, szDllName, stDllName); dprintf("[REFRESH] Loading library: %S", wszDllName); // If the DLL starts with api- or ext-, resolve the redirected name and load it if (_wcsnicmp(wszDllName, L"api-", 4) == 0 || _wcsnicmp(wszDllName, L"ext-", 4) == 0) { // wsRedir is not null terminated wsRedir = GetRedirectedName(wszBaseDllName, wszDllName, &stRedirName); if (wsRedir) { // Free the original wszDllName and allocate a new buffer for the redirected dll name free(wszDllName); wszDllName = (PWSTR)calloc(stRedirName + 1, sizeof(WCHAR)); if (wszDllName == NULL) goto next_import; memcpy(wszDllName, wsRedir, stRedirName * sizeof(WCHAR)); dprintf("[REFRESH] Redirected library: %S", wszDllName); } } // Load the module hModule = CustomGetModuleHandleW(wszDllName); // Ignore libraries that fail to load if (hModule == NULL) goto next_import; if (pImportDesc->OriginalFirstThunk) pThunkData = (PIMAGE_THUNK_DATA)(pLibraryAddr + pImportDesc->OriginalFirstThunk); else pThunkData = (PIMAGE_THUNK_DATA)(pLibraryAddr + pImportDesc->FirstThunk); pIatEntry = (FARPROC*)(pLibraryAddr + pImportDesc->FirstThunk); // loop through each thunk and resolve the import for(; DEREF(pThunkData); pThunkData++, pIatEntry++) { if (IMAGE_SNAP_BY_ORDINAL(pThunkData->u1.Ordinal)) *pIatEntry = CustomGetProcAddressEx(hModule, (PCHAR)IMAGE_ORDINAL(pThunkData->u1.Ordinal), wszDllName); else *pIatEntry = CustomGetProcAddressEx(hModule, ((PIMAGE_IMPORT_BY_NAME)(pLibraryAddr + DEREF(pThunkData)))->Name, wszDllName); } next_import: if (wszDllName != NULL) { free(wszDllName); wszDllName = NULL; } pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((PCHAR)pImportDesc + sizeof(IMAGE_IMPORT_DESCRIPTOR)); } } cleanup: if (pFile != NULL) UnmapViewOfFile(pFile); if (hMap != NULL) CloseHandle(hMap); if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile); return (HMODULE) pLibraryAddr; }
/************************************************************************* * ICO_ExtractIconExW [internal] * * NOTES * nIcons = 0: returns number of Icons in file * * returns * invalid file: -1 * failure:0; * success: number of icons in file (nIcons = 0) or nr of icons retrieved */ static UINT ICO_ExtractIconExW( LPCWSTR lpszExeFileName, HICON * RetPtr, INT nIconIndex, UINT nIcons, UINT cxDesired, UINT cyDesired, UINT *pIconId, UINT flags) { UINT ret = 0; UINT cx1, cx2, cy1, cy2; LPBYTE pData; DWORD sig; HANDLE hFile; UINT16 iconDirCount = 0, iconCount = 0; LPBYTE peimage; HANDLE fmapping; DWORD fsizeh,fsizel; WCHAR szExePath[MAX_PATH]; DWORD dwSearchReturn; TRACE("%s, %d, %d %p 0x%08x\n", debugstr_w(lpszExeFileName), nIconIndex, nIcons, pIconId, flags); dwSearchReturn = SearchPathW(NULL, lpszExeFileName, NULL, sizeof(szExePath) / sizeof(szExePath[0]), szExePath, NULL); if ((dwSearchReturn == 0) || (dwSearchReturn > sizeof(szExePath) / sizeof(szExePath[0]))) { WARN("File %s not found or path too long\n", debugstr_w(lpszExeFileName)); return -1; } hFile = CreateFileW(szExePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); if (hFile == INVALID_HANDLE_VALUE) return ret; fsizel = GetFileSize(hFile,&fsizeh); /* Map the file */ fmapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); CloseHandle(hFile); if (!fmapping) { WARN("CreateFileMapping error %ld\n", GetLastError() ); return 0xFFFFFFFF; } if (!(peimage = MapViewOfFile(fmapping, FILE_MAP_READ, 0, 0, 0))) { WARN("MapViewOfFile error %ld\n", GetLastError() ); CloseHandle(fmapping); return 0xFFFFFFFF; } CloseHandle(fmapping); cx1 = LOWORD(cxDesired); cx2 = HIWORD(cxDesired); cy1 = LOWORD(cyDesired); cy2 = HIWORD(cyDesired); if (pIconId) /* Invalidate first icon identifier */ *pIconId = 0xFFFFFFFF; if (!pIconId) /* if no icon identifier array present use the icon handle array as intermediate storage */ pIconId = (UINT*)RetPtr; sig = USER32_GetResourceTable(peimage, fsizel, &pData); #ifdef WINE /* ico file or NE exe/dll*/ if (sig==IMAGE_OS2_SIGNATURE || sig==1) /* .ICO file */ { BYTE *pCIDir = 0; NE_TYPEINFO *pTInfo = (NE_TYPEINFO*)(pData + 2); NE_NAMEINFO *pIconStorage = NULL; NE_NAMEINFO *pIconDir = NULL; LPicoICONDIR lpiID = NULL; ULONG uSize = 0; TRACE("-- OS2/icon Signature (0x%08x)\n", sig); if (pData == (BYTE*)-1) { pCIDir = ICO_GetIconDirectory(peimage, &lpiID, &uSize); /* check for .ICO file */ if (pCIDir) { iconDirCount = 1; iconCount = lpiID->idCount; TRACE("-- icon found %p 0x%08x 0x%08x 0x%08x\n", pCIDir, uSize, iconDirCount, iconCount); } } else while (pTInfo->type_id && !(pIconStorage && pIconDir)) { if (pTInfo->type_id == NE_RSCTYPE_GROUP_ICON) /* find icon directory and icon repository */ { iconDirCount = pTInfo->count; pIconDir = ((NE_NAMEINFO*)(pTInfo + 1)); TRACE("\tfound directory - %i icon families\n", iconDirCount); } if (pTInfo->type_id == NE_RSCTYPE_ICON) { iconCount = pTInfo->count; pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1)); TRACE("\ttotal icons - %i\n", iconCount); } pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO)); } if ((pIconStorage && pIconDir) || lpiID) /* load resources and create icons */ { if (nIcons == 0) { ret = iconDirCount; if (lpiID) /* *.ico file, deallocate heap pointer*/ HeapFree(GetProcessHeap(), 0, pCIDir); } else if (nIconIndex < iconDirCount) { UINT16 i, icon; if (nIcons > iconDirCount - nIconIndex) nIcons = iconDirCount - nIconIndex; for (i = 0; i < nIcons; i++) { /* .ICO files have only one icon directory */ if (lpiID == NULL) /* not *.ico */ pCIDir = USER32_LoadResource(peimage, pIconDir + i + nIconIndex, *(WORD*)pData, &uSize); pIconId[i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, cx1, cy1, flags); if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, cx2, cy2, flags); } if (lpiID) /* *.ico file, deallocate heap pointer*/ HeapFree(GetProcessHeap(), 0, pCIDir); for (icon = 0; icon < nIcons; icon++) { pCIDir = NULL; if (lpiID) pCIDir = ICO_LoadIcon(peimage, lpiID->idEntries + (int)pIconId[icon], &uSize); else for (i = 0; i < iconCount; i++) if (pIconStorage[i].id == ((int)pIconId[icon] | 0x8000) ) pCIDir = USER32_LoadResource(peimage, pIconStorage + i, *(WORD*)pData, &uSize); if (pCIDir) { RetPtr[icon] = CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000, cx1, cy1, flags); if (cx2 && cy2) RetPtr[++icon] = CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000, cx2, cy2, flags); } else RetPtr[icon] = 0; } ret = icon; /* return number of retrieved icons */ } } } #else if (sig == 1 || sig == 2) /* .ICO or .CUR file */ { TRACE("-- icon Signature (0x%08x)\n", sig); if (pData == (BYTE*)-1) { INT cx[2] = {cx1, cx2}, cy[2] = {cy1, cy2}; INT index; for(index = 0; index < 2; index++) { DWORD dataOffset; LPBYTE imageData; POINT hotSpot; LPICONIMAGE entry; dataOffset = get_best_icon_file_offset(peimage, fsizel, cx[index], cy[index], sig == 1, flags, sig == 1 ? NULL : &hotSpot); if (dataOffset) { HICON icon; WORD *cursorData = NULL; imageData = peimage + dataOffset; entry = (LPICONIMAGE)(imageData); if(sig == 2) { /* we need to prepend the bitmap data with hot spots for CreateIconFromResourceEx */ cursorData = HeapAlloc(GetProcessHeap(), 0, entry->icHeader.biSizeImage + 2 * sizeof(WORD)); if(!cursorData) continue; cursorData[0] = hotSpot.x; cursorData[1] = hotSpot.y; memcpy(cursorData + 2, imageData, entry->icHeader.biSizeImage); imageData = (LPBYTE)cursorData; } icon = CreateIconFromResourceEx(imageData, entry->icHeader.biSizeImage, sig == 1, 0x00030000, cx[index], cy[index], flags); if (icon) { RetPtr[index] = icon; iconCount = 1; } if(cursorData != NULL) HeapFree(GetProcessHeap(), 0, cursorData); } } } ret = iconCount; /* return number of retrieved icons */ } #endif /* end ico file */ /* exe/dll */ else if( sig == IMAGE_NT_SIGNATURE ) { BYTE *idata, *igdata; const IMAGE_RESOURCE_DIRECTORY *rootresdir, *iconresdir, *icongroupresdir; const IMAGE_RESOURCE_DATA_ENTRY *idataent, *igdataent; const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent; ULONG size; UINT i; rootresdir = RtlImageDirectoryEntryToData((HMODULE)peimage, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size); if (!rootresdir) { WARN("haven't found section for resource directory.\n"); goto end; } /* search for the group icon directory */ if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir))) { WARN("No Icongroupresourcedirectory!\n"); goto end; /* failure */ } iconDirCount = icongroupresdir->NumberOfNamedEntries + icongroupresdir->NumberOfIdEntries; /* only number of icons requested */ if( !pIconId ) { ret = iconDirCount; goto end; /* success */ } if( nIconIndex < 0 ) { /* search resource id */ int n = 0; int iId = abs(nIconIndex); const IMAGE_RESOURCE_DIRECTORY_ENTRY* xprdeTmp = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1); while(n<iconDirCount && xprdeTmp) { if(xprdeTmp->Id == iId) { nIconIndex = n; break; } n++; xprdeTmp++; } if (nIconIndex < 0) { WARN("resource id %d not found\n", iId); goto end; /* failure */ } } else { /* check nIconIndex to be in range */ if (nIconIndex >= iconDirCount) { WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount); goto end; /* failure */ } } /* assure we don't get too much */ if( nIcons > iconDirCount - nIconIndex ) nIcons = iconDirCount - nIconIndex; /* starting from specified index */ xresent = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1) + nIconIndex; for (i=0; i < nIcons; i++,xresent++) { const IMAGE_RESOURCE_DIRECTORY *resdir; /* go down this resource entry, name */ resdir = (const IMAGE_RESOURCE_DIRECTORY *)((const char *)rootresdir + xresent->OffsetToDirectory); /* default language (0) */ resdir = find_entry_default(resdir,rootresdir); igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir; /* lookup address in mapped image for virtual address */ igdata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, igdataent->OffsetToData, NULL); if (!igdata) { FIXME("no matching real address for icongroup!\n"); goto end; /* failure */ } pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx1, cy1, flags); if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx2, cy2, flags); } if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICON),rootresdir))) { WARN("No Iconresourcedirectory!\n"); goto end; /* failure */ } for (i=0; i<nIcons; i++) { const IMAGE_RESOURCE_DIRECTORY *xresdir; xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir); if( !xresdir ) { WARN("icon entry %d not found\n", LOWORD(pIconId[i])); RetPtr[i]=0; continue; } xresdir = find_entry_default(xresdir, rootresdir); idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir; idata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, idataent->OffsetToData, NULL); if (!idata) { WARN("no matching real address found for icondata!\n"); RetPtr[i]=0; continue; } RetPtr[i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx1, cy1, flags); if (cx2 && cy2) RetPtr[++i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx2, cy2, flags); } ret = i; /* return number of retrieved icons */ } /* if(sig == IMAGE_NT_SIGNATURE) */ end: UnmapViewOfFile(peimage); /* success */ return ret; }
/************************************************************************* * ICO_ExtractIconExW [internal] * * NOTES * nIcons = 0: returns number of Icons in file * * returns * invalid file: -1 * failure:0; * success: number of icons in file (nIcons = 0) or nr of icons retrieved */ static UINT ICO_ExtractIconExW( LPCWSTR lpszExeFileName, HICON * RetPtr, INT nIconIndex, UINT nIcons, UINT cxDesired, UINT cyDesired, UINT *pIconId, UINT flags) { UINT ret = 0; UINT cx1, cx2, cy1, cy2; LPBYTE pData; DWORD sig; HANDLE hFile; UINT16 iconDirCount = 0; //,iconCount = 0; LPBYTE peimage; HANDLE fmapping; DWORD fsizeh,fsizel; WCHAR szExePath[MAX_PATH]; DWORD dwSearchReturn; TRACE("%s, %d, %d %p 0x%08x\n", debugstr_w(lpszExeFileName), nIconIndex, nIcons, pIconId, flags); dwSearchReturn = SearchPathW(NULL, lpszExeFileName, NULL, sizeof(szExePath) / sizeof(szExePath[0]), szExePath, NULL); if ((dwSearchReturn == 0) || (dwSearchReturn > sizeof(szExePath) / sizeof(szExePath[0]))) { WARN("File %s not found or path too long\n", debugstr_w(lpszExeFileName)); return -1; } hFile = CreateFileW(szExePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0); if (hFile == INVALID_HANDLE_VALUE) return ret; fsizel = GetFileSize(hFile,&fsizeh); /* Map the file */ fmapping = CreateFileMappingW(hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL); CloseHandle(hFile); if (!fmapping) { WARN("CreateFileMapping error %ld\n", GetLastError() ); return 0xFFFFFFFF; } if (!(peimage = MapViewOfFile(fmapping, FILE_MAP_READ, 0, 0, 0))) { WARN("MapViewOfFile error %ld\n", GetLastError() ); CloseHandle(fmapping); return 0xFFFFFFFF; } CloseHandle(fmapping); cx1 = LOWORD(cxDesired); cx2 = HIWORD(cxDesired); cy1 = LOWORD(cyDesired); cy2 = HIWORD(cyDesired); if (pIconId) /* Invalidate first icon identifier */ *pIconId = 0xFFFFFFFF; if (!pIconId) /* if no icon identifier array present use the icon handle array as intermediate storage */ pIconId = (UINT*)RetPtr; sig = USER32_GetResourceTable(peimage, fsizel, &pData); /* ico file or NE exe/dll*/ #if 0 if (sig==IMAGE_OS2_SIGNATURE || sig==1) /* .ICO file */ { BYTE *pCIDir = 0; NE_TYPEINFO *pTInfo = (NE_TYPEINFO*)(pData + 2); NE_NAMEINFO *pIconStorage = NULL; NE_NAMEINFO *pIconDir = NULL; LPicoICONDIR lpiID = NULL; TRACE("-- OS2/icon Signature (0x%08lx)\n", sig); if (pData == (BYTE*)-1) { pCIDir = ICO_GetIconDirectory(peimage, &lpiID, &uSize); /* check for .ICO file */ if (pCIDir) { iconDirCount = 1; iconCount = lpiID->idCount; TRACE("-- icon found %p 0x%08lx 0x%08x 0x%08x\n", pCIDir, uSize, iconDirCount, iconCount); } } else while (pTInfo->type_id && !(pIconStorage && pIconDir)) { if (pTInfo->type_id == NE_RSCTYPE_GROUP_ICON) /* find icon directory and icon repository */ { iconDirCount = pTInfo->count; pIconDir = ((NE_NAMEINFO*)(pTInfo + 1)); TRACE("\tfound directory - %i icon families\n", iconDirCount); } if (pTInfo->type_id == NE_RSCTYPE_ICON) { iconCount = pTInfo->count; pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1)); TRACE("\ttotal icons - %i\n", iconCount); } pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO)); } if ((pIconStorage && pIconDir) || lpiID) /* load resources and create icons */ { if (nIcons == 0) { ret = iconDirCount; if (lpiID && pCIDir) /* *.ico file, deallocate heap pointer*/ HeapFree(GetProcessHeap(), 0, pCIDir); } else if (nIconIndex < iconDirCount) { UINT16 i, icon; if (nIcons > iconDirCount - nIconIndex) nIcons = iconDirCount - nIconIndex; for (i = 0; i < nIcons; i++) { /* .ICO files have only one icon directory */ if (lpiID == NULL) /* not *.ico */ pCIDir = USER32_LoadResource(peimage, pIconDir + i + nIconIndex, *(WORD*)pData, &uSize); pIconId[i] = LookupIconIdFromDirectoryEx(pCIDir, TRUE, (i & 1) ? cx2 : cx1, (i & 1) ? cy2 : cy1, flags); } if (lpiID && pCIDir) /* *.ico file, deallocate heap pointer*/ HeapFree(GetProcessHeap(), 0, pCIDir); for (icon = 0; icon < nIcons; icon++) { pCIDir = NULL; if (lpiID) pCIDir = ICO_LoadIcon(peimage, lpiID->idEntries + (int)pIconId[icon], &uSize); else for (i = 0; i < iconCount; i++) if (pIconStorage[i].id == ((int)pIconId[icon] | 0x8000) ) pCIDir = USER32_LoadResource(peimage, pIconStorage + i, *(WORD*)pData, &uSize); if (pCIDir) RetPtr[icon] = (HICON)CreateIconFromResourceEx(pCIDir, uSize, TRUE, 0x00030000, (icon & 1) ? cx2 : cx1, (icon & 1) ? cy2 : cy1, flags); else RetPtr[icon] = 0; } ret = icon; /* return number of retrieved icons */ } } } /* end ico file */ /* exe/dll */ else if( sig == IMAGE_NT_SIGNATURE ) #endif if( sig == IMAGE_NT_SIGNATURE ) { LPBYTE idata,igdata; PIMAGE_DOS_HEADER dheader; PIMAGE_NT_HEADERS pe_header; PIMAGE_SECTION_HEADER pe_sections; const IMAGE_RESOURCE_DIRECTORY *rootresdir,*iconresdir,*icongroupresdir; const IMAGE_RESOURCE_DATA_ENTRY *idataent,*igdataent; const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent; UINT i, j; dheader = (PIMAGE_DOS_HEADER)peimage; pe_header = (PIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew); /* it is a pe header, USER32_GetResourceTable checked that */ pe_sections = (PIMAGE_SECTION_HEADER)(((char*)pe_header) + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) + pe_header->FileHeader.SizeOfOptionalHeader); rootresdir = NULL; /* search for the root resource directory */ for (i=0;i<pe_header->FileHeader.NumberOfSections;i++) { if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) continue; if (fsizel < pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData) { FIXME("File %s too short (section is at %ld bytes, real size is %ld)\n", debugstr_w(lpszExeFileName), pe_sections[i].PointerToRawData+pe_sections[i].SizeOfRawData, fsizel ); goto end; } /* FIXME: doesn't work when the resources are not in a separate section */ if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) { rootresdir = (PIMAGE_RESOURCE_DIRECTORY)(peimage+pe_sections[i].PointerToRawData); break; } } if (!rootresdir) { WARN("haven't found section for resource directory.\n"); goto end; /* failure */ } /* search for the group icon directory */ if (!(icongroupresdir = find_entry_by_id(rootresdir, LOWORD(RT_GROUP_ICON), rootresdir))) { WARN("No Icongroupresourcedirectory!\n"); goto end; /* failure */ } iconDirCount = icongroupresdir->NumberOfNamedEntries + icongroupresdir->NumberOfIdEntries; /* only number of icons requested */ if( !pIconId ) { ret = iconDirCount; goto end; /* success */ } if( nIconIndex < 0 ) { /* search resource id */ int n = 0; int iId = abs(nIconIndex); const IMAGE_RESOURCE_DIRECTORY_ENTRY* xprdeTmp = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1); while(n<iconDirCount && xprdeTmp) { if(xprdeTmp->Id == iId) { nIconIndex = n; break; } n++; xprdeTmp++; } if (nIconIndex < 0) { WARN("resource id %d not found\n", iId); goto end; /* failure */ } } else { /* check nIconIndex to be in range */ if (nIconIndex >= iconDirCount) { WARN("nIconIndex %d is larger than iconDirCount %d\n",nIconIndex,iconDirCount); goto end; /* failure */ } } /* assure we don't get too much */ if( nIcons > iconDirCount - nIconIndex ) nIcons = iconDirCount - nIconIndex; /* starting from specified index */ xresent = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1) + nIconIndex; for (i=0; i < nIcons; i++,xresent++) { const IMAGE_RESOURCE_DIRECTORY *resdir; /* go down this resource entry, name */ resdir = (const IMAGE_RESOURCE_DIRECTORY*)((const char *)rootresdir+(xresent->OffsetToDirectory)); /* default language (0) */ resdir = find_entry_default(resdir,rootresdir); igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir; /* lookup address in mapped image for virtual address */ igdata = NULL; for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) { if (igdataent->OffsetToData < pe_sections[j].VirtualAddress) continue; if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData) continue; if (igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData+igdataent->Size > fsizel) { FIXME("overflow in PE lookup (%s has len %ld, have offset %ld), short file?\n", debugstr_w(lpszExeFileName), fsizel, igdataent->OffsetToData - pe_sections[j].VirtualAddress + pe_sections[j].PointerToRawData + igdataent->Size); goto end; /* failure */ } igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData); } if (!igdata) { FIXME("no matching real address for icongroup!\n"); goto end; /* failure */ } pIconId[i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx1, cy1, flags); if (cx2 && cy2) pIconId[++i] = LookupIconIdFromDirectoryEx(igdata, TRUE, cx2, cy2, flags); } if (!(iconresdir=find_entry_by_id(rootresdir,LOWORD(RT_ICON),rootresdir))) { WARN("No Iconresourcedirectory!\n"); goto end; /* failure */ } for (i=0; i<nIcons; i++) { const IMAGE_RESOURCE_DIRECTORY *xresdir; xresdir = find_entry_by_id(iconresdir, LOWORD(pIconId[i]), rootresdir); if (!xresdir) { WARN("icon entry %d not found\n", LOWORD(pIconId[i])); RetPtr[i]=0; continue; } xresdir = find_entry_default(xresdir, rootresdir); if (!xresdir) { WARN("icon entry %d not found\n", LOWORD(pIconId[i])); RetPtr[i]=0; continue; } idataent = (const IMAGE_RESOURCE_DATA_ENTRY*)xresdir; idata = NULL; /* map virtual to address in image */ for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) { if (idataent->OffsetToData < pe_sections[j].VirtualAddress) continue; if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData) continue; idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData); } if (!idata) { WARN("no matching real address found for icondata!\n"); RetPtr[i]=0; continue; } RetPtr[i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx1, cy1, flags); if (cx2 && cy2) RetPtr[++i] = CreateIconFromResourceEx(idata, idataent->Size, TRUE, 0x00030000, cx2, cy2, flags); } ret = i; /* return number of retrieved icons */ } /* if(sig == IMAGE_NT_SIGNATURE) */ end: UnmapViewOfFile(peimage); /* success */ return ret; }