1 /* 2 * Copyright (c) 2000, 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 #include "procList.hpp" 26 #include "nt4internals.hpp" 27 #include "isNT4.hpp" 28 #include "toolHelp.hpp" 29 #include <assert.h> 30 31 using namespace std; 32 using namespace NT4; 33 34 typedef void ProcListImplFunc(ProcEntryList& processes); 35 36 void procListImplNT4(ProcEntryList& processes); 37 void procListImplToolHelp(ProcEntryList& processes); 38 39 ProcEntry::ProcEntry(ULONG pid, USHORT nameLength, WCHAR* name) { 40 this->pid = pid; 41 this->nameLength = nameLength; 42 this->name = new WCHAR[nameLength]; 43 memcpy(this->name, name, nameLength * sizeof(WCHAR)); 44 } 45 46 ProcEntry::ProcEntry(ULONG pid, USHORT nameLength, char* name) { 47 this->pid = pid; 48 this->nameLength = nameLength; 49 this->name = new WCHAR[nameLength]; 50 int j = 0; 51 for (int i = 0; i < nameLength; i++) { 52 // FIXME: what is the proper promotion from ASCII to UNICODE? 53 this->name[i] = name[i] & 0xFF; 54 } 55 } 56 57 ProcEntry::ProcEntry(const ProcEntry& arg) { 58 name = NULL; 59 copyFrom(arg); 60 } 61 62 ProcEntry& 63 ProcEntry::operator=(const ProcEntry& arg) { 64 copyFrom(arg); 65 return *this; 66 } 67 68 ProcEntry::~ProcEntry() { 69 delete[] name; 70 } 71 72 void 73 ProcEntry::copyFrom(const ProcEntry& arg) { 74 if (name != NULL) { 75 delete[] name; 76 } 77 pid = arg.pid; 78 nameLength = arg.nameLength; 79 name = new WCHAR[nameLength]; 80 memcpy(name, arg.name, nameLength * sizeof(WCHAR)); 81 } 82 83 ULONG 84 ProcEntry::getPid() { 85 return pid; 86 } 87 88 USHORT 89 ProcEntry::getNameLength() { 90 return nameLength; 91 } 92 93 WCHAR* 94 ProcEntry::getName() { 95 return name; 96 } 97 98 void 99 procList(ProcEntryList& processes) { 100 static ProcListImplFunc* impl = NULL; 101 102 if (impl == NULL) { 103 // See which operating system we're on 104 impl = (isNT4() ? &procListImplNT4 : &procListImplToolHelp); 105 } 106 107 assert(impl != NULL); 108 109 (*impl)(processes); 110 } 111 112 void 113 procListImplNT4(ProcEntryList& processes) { 114 using namespace NT4; 115 116 static ZwQuerySystemInformationFunc* query = NULL; 117 118 if (query == NULL) { 119 HMODULE ntDLL = loadNTDLL(); 120 query = 121 (ZwQuerySystemInformationFunc*) GetProcAddress(ntDLL, 122 "ZwQuerySystemInformation"); 123 assert(query != NULL); 124 } 125 126 ULONG n = 0x100; 127 PSYSTEM_PROCESSES sp = new SYSTEM_PROCESSES[n]; 128 while ((*query)(SystemProcessesAndThreadsInformation, 129 sp, n * sizeof(SYSTEM_PROCESSES), 0) == STATUS_INFO_LENGTH_MISMATCH) { 130 delete[] sp; 131 n *= 2; 132 sp = new SYSTEM_PROCESSES[n]; 133 } 134 135 bool done = false; 136 for (PSYSTEM_PROCESSES p = sp; !done; 137 p = PSYSTEM_PROCESSES(PCHAR(p) + p->NextEntryDelta)) { 138 processes.push_back(ProcEntry(p->ProcessId, 139 p->ProcessName.Length / 2, 140 p->ProcessName.Buffer)); 141 done = p->NextEntryDelta == 0; 142 } 143 } 144 145 void 146 procListImplToolHelp(ProcEntryList& processes) { 147 using namespace ToolHelp; 148 149 static CreateToolhelp32SnapshotFunc* snapshotFunc = NULL; 150 static Process32FirstFunc* firstFunc = NULL; 151 static Process32NextFunc* nextFunc = NULL; 152 153 if (snapshotFunc == NULL) { 154 HMODULE dll = loadDLL(); 155 156 snapshotFunc = 157 (CreateToolhelp32SnapshotFunc*) GetProcAddress(dll, 158 "CreateToolhelp32Snapshot"); 159 160 firstFunc = (Process32FirstFunc*) GetProcAddress(dll, 161 "Process32First"); 162 163 nextFunc = (Process32NextFunc*) GetProcAddress(dll, 164 "Process32Next"); 165 166 assert(snapshotFunc != NULL); 167 assert(firstFunc != NULL); 168 assert(nextFunc != NULL); 169 } 170 171 HANDLE snapshot = (*snapshotFunc)(TH32CS_SNAPPROCESS, 0 /* ignored */); 172 if (snapshot == (HANDLE) -1) { 173 // Error occurred during snapshot 174 return; 175 } 176 177 // Iterate 178 PROCESSENTRY32 proc; 179 if ((*firstFunc)(snapshot, &proc)) { 180 do { 181 // FIXME: could make this uniform to the NT version by cutting 182 // off the path name just before the executable name 183 processes.push_back(ProcEntry(proc.th32ProcessID, 184 strlen(proc.szExeFile), 185 proc.szExeFile)); 186 } while ((*nextFunc)(snapshot, &proc)); 187 } 188 189 CloseHandle(snapshot); 190 }