/* 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 = (struct module_find*)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; DWORD timestamp; timestamp = ~mf->dw1; size = ~mf->dw2; hFile = CreateFileW(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); if (hFile == INVALID_HANDLE_VALUE) return FALSE; if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) { if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) { IMAGE_NT_HEADERS* nth = RtlImageNtHeader((HMODULE)mapping); 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_DYLIB: FIXME("try to fetch module info to verify this is the correct file\n"); 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; matched++; switch (pdb_lookup.kind) { case PDB_JG: if (mf->guid) { WARN("Found %s, but wrong PDB version\n", debugstr_w(buffer)); } else if (pdb_lookup.u.jg.timestamp == mf->dw1) matched++; else WARN("Found %s, but wrong signature: %08x %08x\n", debugstr_w(buffer), pdb_lookup.u.jg.timestamp, mf->dw1); break; case PDB_DS: if (!mf->guid) { WARN("Found %s, but wrong PDB version\n", debugstr_w(buffer)); } else if (!memcmp(&pdb_lookup.u.ds.guid, mf->guid, sizeof(GUID))) matched++; else WARN("Found %s, but wrong GUID: %s %s\n", debugstr_w(buffer), debugstr_guid(&pdb_lookup.u.ds.guid), debugstr_guid(mf->guid)); break; } if (pdb_lookup.age != mf->dw2) { matched--; WARN("Found %s, but wrong age: %08x %08x\n", debugstr_w(buffer), pdb_lookup.age, mf->dw2); } } 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, 0); if (hFile == INVALID_HANDLE_VALUE) return FALSE; if ((hMap = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) { if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL) { const IMAGE_SEPARATE_DEBUG_HEADER* hdr; hdr = (const IMAGE_SEPARATE_DEBUG_HEADER*)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; }
/* 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 conventions as for SymFindFileInPathProc) */ static BOOL CALLBACK sffip_cb(LPCSTR buffer, void* 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 = CreateFileA(buffer, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) return FALSE; if ((hMap = CreateFileMappingA(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", 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: %08lx %08lx\n", buffer, checksum, (DWORD_PTR)s->id); return FALSE; } } else { WARN("Couldn't read %s\n", buffer); return FALSE; } break; case DMT_PDB: { struct pdb_lookup pdb_lookup; pdb_lookup.filename = buffer; 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", buffer); return FALSE; } if (pdb_lookup.u.jg.timestamp != (DWORD_PTR)s->id) { WARN("Found %s, but wrong signature: %08lx %08lx\n", 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", buffer); return FALSE; } if (memcmp(&pdb_lookup.u.ds.guid, (GUID*)s->id, sizeof(GUID))) { WARN("Found %s, but wrong GUID: %s %s\n", 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: %08lx %08lx\n", 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)((char*)buffer, s->user); }