1 /* 2 * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 // Disable too-long symbol warnings 26 #pragma warning ( disable : 4786 ) 27 28 #include "libInfo.hpp" 29 #include "nt4internals.hpp" 30 #include "isNT4.hpp" 31 #include "toolHelp.hpp" 32 #include <assert.h> 33 34 using namespace std; 35 36 typedef void LibInfoImplFunc(DWORD pid, vector<LibInfo>& info); 37 38 static void libInfoImplNT4(DWORD pid, vector<LibInfo>& info); 39 static void libInfoImplToolHelp(DWORD pid, vector<LibInfo>& info); 40 41 void 42 libInfo(DWORD pid, vector<LibInfo>& info) { 43 static LibInfoImplFunc* impl = NULL; 44 45 if (impl == NULL) { 46 // See which operating system we're on 47 impl = (isNT4() ? &libInfoImplNT4 : &libInfoImplToolHelp); 48 } 49 50 assert(impl != NULL); 51 52 (*impl)(pid, info); 53 } 54 55 static ULONG 56 ModuleCount(NT4::PDEBUG_BUFFER db) { 57 return db->ModuleInformation ? *PULONG(db->ModuleInformation) : 0; 58 } 59 60 #define MAX2(a, b) (((a) < (b)) ? (b) : (a)) 61 62 static void 63 libInfoImplNT4(DWORD pid, vector<LibInfo>& info) { 64 static EnumProcessModulesFunc* enumFunc = NULL; 65 static GetModuleFileNameExFunc* fnFunc = NULL; 66 static GetModuleInformationFunc* infoFunc = NULL; 67 68 if (enumFunc == NULL) { 69 HMODULE dll = loadPSAPIDLL(); 70 71 enumFunc = (EnumProcessModulesFunc*) GetProcAddress(dll, "EnumProcessModules"); 72 fnFunc = (GetModuleFileNameExFunc*) GetProcAddress(dll, "GetModuleFileNameExA"); 73 infoFunc = (GetModuleInformationFunc*) GetProcAddress(dll, "GetModuleInformation"); 74 75 assert(enumFunc != NULL); 76 assert(fnFunc != NULL); 77 assert(infoFunc != NULL); 78 } 79 80 static HMODULE* mods = new HMODULE[256]; 81 static int numMods = 256; 82 83 if (mods == NULL) { 84 mods = new HMODULE[numMods]; 85 if (mods == NULL) { 86 return; 87 } 88 } 89 90 bool done = false; 91 92 HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); 93 if (proc == NULL) { 94 return; 95 } 96 97 do { 98 DWORD bufSize = numMods * sizeof(HMODULE); 99 DWORD neededSize; 100 101 if (!(*enumFunc)(proc, mods, bufSize, &neededSize)) { 102 // Enum failed 103 CloseHandle(proc); 104 return; 105 } 106 107 int numFetched = neededSize / sizeof(HMODULE); 108 109 if (numMods < numFetched) { 110 // Grow buffer 111 numMods = MAX2(numFetched, 2 * numMods); 112 delete[] mods; 113 mods = new HMODULE[numMods]; 114 if (mods == NULL) { 115 CloseHandle(proc); 116 return; 117 } 118 } else { 119 char filename[MAX_PATH]; 120 MODULEINFO modInfo; 121 122 // Iterate through and fetch each one's info 123 for (int i = 0; i < numFetched; i++) { 124 if (!(*fnFunc)(proc, mods[i], filename, MAX_PATH)) { 125 CloseHandle(proc); 126 return; 127 } 128 129 if (!(*infoFunc)(proc, mods[i], &modInfo, sizeof(MODULEINFO))) { 130 CloseHandle(proc); 131 return; 132 } 133 134 info.push_back(LibInfo(string(filename), (void*) modInfo.lpBaseOfDll)); 135 } 136 137 done = true; 138 } 139 } while (!done); 140 141 CloseHandle(proc); 142 return; 143 } 144 145 void 146 libInfoImplToolHelp(DWORD pid, vector<LibInfo>& info) { 147 using namespace ToolHelp; 148 149 static CreateToolhelp32SnapshotFunc* snapshotFunc = NULL; 150 static Module32FirstFunc* firstFunc = NULL; 151 static Module32NextFunc* nextFunc = NULL; 152 153 if (snapshotFunc == NULL) { 154 HMODULE dll = loadDLL(); 155 156 snapshotFunc = 157 (CreateToolhelp32SnapshotFunc*) GetProcAddress(dll, 158 "CreateToolhelp32Snapshot"); 159 160 firstFunc = (Module32FirstFunc*) GetProcAddress(dll, 161 "Module32First"); 162 163 nextFunc = (Module32NextFunc*) GetProcAddress(dll, 164 "Module32Next"); 165 166 assert(snapshotFunc != NULL); 167 assert(firstFunc != NULL); 168 assert(nextFunc != NULL); 169 } 170 171 HANDLE snapshot = (*snapshotFunc)(TH32CS_SNAPMODULE, pid); 172 if (snapshot == (HANDLE) -1) { 173 // Error occurred during snapshot 174 return; 175 } 176 177 // Iterate 178 MODULEENTRY32 module; 179 if ((*firstFunc)(snapshot, &module)) { 180 do { 181 info.push_back(LibInfo(string(module.szExePath), (void*) module.modBaseAddr)); 182 } while ((*nextFunc)(snapshot, &module)); 183 } 184 185 CloseHandle(snapshot); 186 }