/* * 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 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); }