| /* |
| * Copyright 2000-2001 Sun Microsystems, Inc. All Rights Reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
| * CA 95054 USA or visit www.sun.com if you need additional information or |
| * have any questions. |
| * |
| */ |
| |
| #include "procList.hpp" |
| #include "nt4internals.hpp" |
| #include "isNT4.hpp" |
| #include "toolHelp.hpp" |
| #include <assert.h> |
| |
| using namespace std; |
| using namespace NT4; |
| |
| typedef void ProcListImplFunc(ProcEntryList& processes); |
| |
| void procListImplNT4(ProcEntryList& processes); |
| void procListImplToolHelp(ProcEntryList& processes); |
| |
| ProcEntry::ProcEntry(ULONG pid, USHORT nameLength, WCHAR* name) { |
| this->pid = pid; |
| this->nameLength = nameLength; |
| this->name = new WCHAR[nameLength]; |
| memcpy(this->name, name, nameLength * sizeof(WCHAR)); |
| } |
| |
| ProcEntry::ProcEntry(ULONG pid, USHORT nameLength, char* name) { |
| this->pid = pid; |
| this->nameLength = nameLength; |
| this->name = new WCHAR[nameLength]; |
| int j = 0; |
| for (int i = 0; i < nameLength; i++) { |
| // FIXME: what is the proper promotion from ASCII to UNICODE? |
| this->name[i] = name[i] & 0xFF; |
| } |
| } |
| |
| ProcEntry::ProcEntry(const ProcEntry& arg) { |
| name = NULL; |
| copyFrom(arg); |
| } |
| |
| ProcEntry& |
| ProcEntry::operator=(const ProcEntry& arg) { |
| copyFrom(arg); |
| return *this; |
| } |
| |
| ProcEntry::~ProcEntry() { |
| delete[] name; |
| } |
| |
| void |
| ProcEntry::copyFrom(const ProcEntry& arg) { |
| if (name != NULL) { |
| delete[] name; |
| } |
| pid = arg.pid; |
| nameLength = arg.nameLength; |
| name = new WCHAR[nameLength]; |
| memcpy(name, arg.name, nameLength * sizeof(WCHAR)); |
| } |
| |
| ULONG |
| ProcEntry::getPid() { |
| return pid; |
| } |
| |
| USHORT |
| ProcEntry::getNameLength() { |
| return nameLength; |
| } |
| |
| WCHAR* |
| ProcEntry::getName() { |
| return name; |
| } |
| |
| void |
| procList(ProcEntryList& processes) { |
| static ProcListImplFunc* impl = NULL; |
| |
| if (impl == NULL) { |
| // See which operating system we're on |
| impl = (isNT4() ? &procListImplNT4 : &procListImplToolHelp); |
| } |
| |
| assert(impl != NULL); |
| |
| (*impl)(processes); |
| } |
| |
| void |
| procListImplNT4(ProcEntryList& processes) { |
| using namespace NT4; |
| |
| static ZwQuerySystemInformationFunc* query = NULL; |
| |
| if (query == NULL) { |
| HMODULE ntDLL = loadNTDLL(); |
| query = |
| (ZwQuerySystemInformationFunc*) GetProcAddress(ntDLL, |
| "ZwQuerySystemInformation"); |
| assert(query != NULL); |
| } |
| |
| ULONG n = 0x100; |
| PSYSTEM_PROCESSES sp = new SYSTEM_PROCESSES[n]; |
| while ((*query)(SystemProcessesAndThreadsInformation, |
| sp, n * sizeof(SYSTEM_PROCESSES), 0) == STATUS_INFO_LENGTH_MISMATCH) { |
| delete[] sp; |
| n *= 2; |
| sp = new SYSTEM_PROCESSES[n]; |
| } |
| |
| bool done = false; |
| for (PSYSTEM_PROCESSES p = sp; !done; |
| p = PSYSTEM_PROCESSES(PCHAR(p) + p->NextEntryDelta)) { |
| processes.push_back(ProcEntry(p->ProcessId, |
| p->ProcessName.Length / 2, |
| p->ProcessName.Buffer)); |
| done = p->NextEntryDelta == 0; |
| } |
| } |
| |
| void |
| procListImplToolHelp(ProcEntryList& processes) { |
| using namespace ToolHelp; |
| |
| static CreateToolhelp32SnapshotFunc* snapshotFunc = NULL; |
| static Process32FirstFunc* firstFunc = NULL; |
| static Process32NextFunc* nextFunc = NULL; |
| |
| if (snapshotFunc == NULL) { |
| HMODULE dll = loadDLL(); |
| |
| snapshotFunc = |
| (CreateToolhelp32SnapshotFunc*) GetProcAddress(dll, |
| "CreateToolhelp32Snapshot"); |
| |
| firstFunc = (Process32FirstFunc*) GetProcAddress(dll, |
| "Process32First"); |
| |
| nextFunc = (Process32NextFunc*) GetProcAddress(dll, |
| "Process32Next"); |
| |
| assert(snapshotFunc != NULL); |
| assert(firstFunc != NULL); |
| assert(nextFunc != NULL); |
| } |
| |
| HANDLE snapshot = (*snapshotFunc)(TH32CS_SNAPPROCESS, 0 /* ignored */); |
| if (snapshot == (HANDLE) -1) { |
| // Error occurred during snapshot |
| return; |
| } |
| |
| // Iterate |
| PROCESSENTRY32 proc; |
| if ((*firstFunc)(snapshot, &proc)) { |
| do { |
| // FIXME: could make this uniform to the NT version by cutting |
| // off the path name just before the executable name |
| processes.push_back(ProcEntry(proc.th32ProcessID, |
| strlen(proc.szExeFile), |
| proc.szExeFile)); |
| } while ((*nextFunc)(snapshot, &proc)); |
| } |
| |
| CloseHandle(snapshot); |
| } |