blob: c5d66e659a493bf9bc027082935a9d77b3fdf629 [file] [log] [blame]
/*
* 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);
}