NTSYSAPI
NTSTATUS
NTAPI
ZwQuerySystemInformation
(
IN SYSTEM_INFORMATION_CLASS
SystemInformationClass,
IN OUT PVOID
SystemInformation,
IN ULONG
SystemInformationLength,
OUT PULONG ReturnLength
);
|
где
SystemInformationClass
– задает тип получаемой информации, нас интересует
SystemProcessesAndThreadsInformation;
SystemInformation
– указатель на буфер, принимающий запрошенную информацию;
SystemInformationLength
– задает длину приемного буфера в байтах;
ReturnLength –
указатель на переменную, в которую заносится количество байтов, записанных в
выходной буфер
Формат
информации о процессах и потоках описывается структурой SYSTEM_PROCESSES,
которая содержит почти всю информацию, отображаемую Task Manager. Ниже привeден
код функции EnumProcesses_NtApi, реализующей перечисление процессов с
использованием функции ZwQuerySystemInformation.
При вызове ZwQuerySystemInformation трудно заранее
определить, какой размер выходного буфера будет достаточным, поэтому мы начинам
с буфера размером 32K и увеличиваем его по необходимости.
1.5
Использование
cчетчиков производительности
Как уже
отмечалось, операционная система Windows NT с самого создания содержала
интерфейс для получения разнообразной информации о системе в виде счетчиков
производительности. Этот интерфейс является, скажем, далеко не интуитивным. Для
получения той или иной информации нужно прочитать из ключа реестра
HKEY_PERFORMANCE_DATA значение со специально сформированным именем. В
результате возвращается набор глубоко вложенных структур, многие из которых
переменного размера, и разбор этих данных требует определенной усидчивости.
Ситуация
изменилась в лучшую сторону с появлением в Windows NT 4.0 библиотеки
Performance Data Helper (PDH), которая предоставляет более удобный интерфейс к
данным производительности. Эта библиотека, однако, не входила в комплект
поставки Windows NT 4.0, она распространялась в составе Microsoft Platform SDK.
В Windows 2000 PDH.DLL присутствует по умолчанию.
Подробное
рассмотрение данных производительности выходит за рамки данной статьи, отметим
лишь, что система подсчета производительности в Windows NT определяет
понятие объекта, для которого осуществляется подсчет
производительности. Примерами объектов являются процессор и жесткий диск.
Каждый объект может иметь один или более экземпляров, и для каждого
объекта существует свой набор счетчиков производительности. Наша
задача состоит в перечислении всех экземпляров объекта с именем «Process» и
получении для каждого из них значения счетчика с именем «ID Process».
1.6
Использование Windows
Management Instrumentation
Windows
Management Instrumentation (WMI) является реализацией Mircrosoft для так называемой технологии Web-Based
Enterprise Management (WBEM). WBEM определяет унифицированную архитектуру, которая
позволяет получать данные от различных источников, построенных с помощью
различных технологий и платформ, и единообразно представлять эти данные. WBEM
основана на схеме общей информационной модели (Common Information Model, CIM),
которая является индустриальным стандартом, управляемым Distributed Management Task
Force (DMTF). WMI поставляется в составе Windows 2000, но также может быть
установлен на Windows 95/98/Me и Windows NT 4.0
Поскольку WMI
основана на технологии COM, это избавляет от необходимости явно загружать
требуемые библиотеки, как это делалось в предыдущих примерах. Этот же факт
требует инициализации библиотеки COM прежде чем будет вызвана функция
перечисления процессов. В приложении, созданном с использованием MFC, это можно
сделать с помощью функции AfxOleInit, в остальных случаях следует пользоваться
функциями CoInitialize или CoInitializeEx.
Кроме того,
использование WMI требует инициализации безопасности COM с помощью
функции CoInitializeSecurity
Заметим, что
как и метод с использованием счетчиков производительности, этот метод позволяет
перечислить процессы на другом компьютере, для чего нужно указать имя
компьютера в вызове IWbemLocator: ConnectServer.
2. Описание
программы
2.1 Описание алгоритма
Программа
была написана на Microsoft Visual Studio 2005, на языке С++, с использованием библиотек
классов MFC,
и функций Win32API.
При
запуске программы открывается окно:
Рисунок 2.1 – Окно программы
Сразу отображается список запущенных процес сов, построенный с
помощью функциии EnumProcesses_NtApi, реализующей перечисление процессов с
использованием функции ZwQuerySystemInformation.
Определение
времени запуска процесса осуществляется с помощью функции CreateTime_str.
При
нажатии левой кнопкой мыши на поля «ID» или «Name» осуществляется сортировка при помощи функции CMainFrame: OnList_ColumnClick,
и функции сортировки CMainFrame: SortCallback.
Рисунок 2.2 – Пример сортировки по названию
С помощью
кнопки Exit программа закрывается.
3. Инструкция
пользователя
3.1 Назначение продукта
Эта программа
предназначена для частного пользования, для определения процессов, запущенных
на компьютере, и времени их запуска.
3.2 Системные требования
Рекомендованные системные требования для компьютера:
Процессор: Intel Pentium III 0.8Ггц или выше;
ОЗУ: 128 Мб;
ПЗУ: 10 МБ;
Видео адаптер: Поддерживающий Directx 6.0 и выше;
ОС: Windows XP и выше
3.3 Запуск программы
Клиентское приложение
состоит из файла «pview.exe». При запуске этого файла открывается окно. Автоматически
загружается список запущенных приложений. При нажатии левой кнопкой мыши на «ID», список процессов,
сортируется по коду. При нажатии левой кнопкой мыши на «Name», список сортируется по названию.
Сортировать можно как по возрастанию, так и по убыванию.
В строке меню находится
кнопка «Exit», при нажатии на которую, программа закроется.
Выводы
В
ходе выполнения данного курсового проекта была разработана программа на языке
высокого уровня Visual C++. А также изучены возможности данного языка.
Систематизированы и закреплены практические
навыки использования ПК, программного обеспечения, существующих средств
обслуживания системных программистов, а также теоретические знания по основным
разделам курса «Операционные системы». Основное внимание уделено изучению
современных операционных систем.
В
ходе выполнения курсовой работы были использованы не только учебные средства,
но и исходники различных программ.
Получены
практические навыки работы в среде Microsoft Visual Studio.
Список литературы
1. Дейтел Х. Дейтел П. Как программировать на С++. «Бином» – Моква,
2004. – 1018 с.
2. Бондарев М.Ф. Липанов А.В. Путятин Е.П. Синельникова Т.Ф. Системное
программирование в современных операционных системах «Компания СМИТ» – Харьков,
2005. – 432 с.
3. Холзнер С. Visual С++. «Питер» – Санкт Петербург, 2006. – 580 с.
4. Павловская Т.А. С/С++. Программирование на языке
высокого уровня – СПб: Издательство «Питер», 2001. –464 с.
5. Саймон Р. Microsoft Windows API. Справочник системного
программиста. «Dia Soft» – Киев, 2004. – 1216 с.
6. http://rsdn.ru/
7. http://www.source-code.ru
8. http://www.codeguru.com
Приложение
Тексты файлов программы
·
enumproc.cpp
#include «stdafx.h»
#include «enumproc.h»
#include <tlhelp32.h>
#include <pdh.h>
#include <pdhmsg.h>
#include <comdef.h>
#include «SshWbemHelpers.h»
// Some definitions from NTDDK and other sources
//
typedef LONG NTSTATUS;
typedef LONG KPRIORITY;
#define NT_SUCCESS(Status) ((NTSTATUS) (Status) >= 0)
#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS) 0xC0000004L)
#define SystemProcessesAndThreadsInformation 5
typedef struct _CLIENT_ID {
DWORD UniqueProcess;
DWORD UniqueThread;
} CLIENT_ID;
typedef struct _UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING;
typedef struct _VM_COUNTERS {
SIZE_T PeakVirtualSize;
SIZE_T VirtualSize;
ULONG PageFaultCount;
SIZE_T PeakWorkingSetSize;
SIZE_T WorkingSetSize;
SIZE_T QuotaPeakPagedPoolUsage;
SIZE_T QuotaPagedPoolUsage;
SIZE_T QuotaPeakNonPagedPoolUsage;
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
} VM_COUNTERS;
typedef struct _SYSTEM_THREADS {
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER CreateTime;
ULONG WaitTime;
PVOID StartAddress;
CLIENT_ID ClientId;
KPRIORITY Priority;
KPRIORITY BasePriority;
ULONG ContextSwitchCount;
LONG State;
LONG WaitReason;
} SYSTEM_THREADS, * PSYSTEM_THREADS;
// Note that the size of the SYSTEM_PROCESSES structure
is different on
// NT 4 and Win2K, but we don't care about it, since we
don't access neither
// IoCounters member nor Threads array
typedef struct _SYSTEM_PROCESSES {
ULONG NextEntryDelta;
ULONG ThreadCount;
ULONG Reserved1 [6];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ProcessName;
KPRIORITY BasePriority;
ULONG ProcessId;
ULONG InheritedFromProcessId;
ULONG HandleCount;
ULONG Reserved2 [2];
VM_COUNTERS VmCounters;
#if _WIN32_WINNT >= 0x500
IO_COUNTERS IoCounters;
#endif
SYSTEM_THREADS Threads[1];
}
SYSTEM_PROCESSES, * PSYSTEM_PROCESSES;
// –
// EnumProcesses_NtApi
BOOL
WINAPI
EnumProcesses_NtApi (
IN LPCTSTR pszMachineName,
IN PFNENUMPROC pfnEnumProc,
IN LPARAM lParam
)
{
_UNUSED(pszMachineName);
_ASSERTE (pfnEnumProc!= NULL);
_ASSERTE (pszMachineName == NULL);
HINSTANCE hNtDll;
NTSTATUS (WINAPI * _ZwQuerySystemInformation) (UINT, PVOID,
ULONG, PULONG);
// get handle to NTDLL.DLL
hNtDll = GetModuleHandle (_T(«ntdll.dll»));
_ASSERTE (hNtDll!= NULL);
// find the address of ZwQuerySystemInformation
*(FARPROC *)&_ZwQuerySystemInformation =
GetProcAddress (hNtDll, «ZwQuerySystemInformation»);
if (_ZwQuerySystemInformation == NULL)
return SetLastError (ERROR_PROC_NOT_FOUND), FALSE;
// obtain a handle to the default process heap
HANDLE hHeap = GetProcessHeap();
FILETIME Local_CreateTime, MyCreateTime;
SYSTEMTIME System_CreateTime;
char CreateTime_str[55];
NTSTATUS Status;
ULONG cbBuffer = 0x8000;
PVOID pBuffer = NULL;
do
{
pBuffer = HeapAlloc (hHeap, 0, cbBuffer);
if (pBuffer == NULL)
return SetLastError (ERROR_NOT_ENOUGH_MEMORY), FALSE;
Status = _ZwQuerySystemInformation (
SystemProcessesAndThreadsInformation,
pBuffer, cbBuffer, NULL);
if (Status == STATUS_INFO_LENGTH_MISMATCH)
{
HeapFree (hHeap, 0, pBuffer);
cbBuffer *= 2;
}
else if (! NT_SUCCESS(Status))
{
HeapFree (hHeap, 0, pBuffer);
return SetLastError(Status), FALSE;
}
}
while (Status == STATUS_INFO_LENGTH_MISMATCH);
PSYSTEM_PROCESSES pProcesses = (PSYSTEM_PROCESSES) pBuffer;
for (;)
{
PCWSTR pszProcessName = pProcesses->ProcessName. Buffer;
MyCreateTime.dwHighDateTime = pProcesses->CreateTime. HighPart;
MyCreateTime.dwLowDateTime = pProcesses->CreateTime. LowPart;
if (MyCreateTime.dwLowDateTime!= 0 &&
MyCreateTime.dwHighDateTime!= 0)
{
FileTimeToLocalFileTime (&MyCreateTime,&Local_CreateTime);
FileTimeToSystemTime (&Local_CreateTime,&System_CreateTime);
sprintf (CreateTime_str, «%02u:%02u:%02u:%03u\0», System_CreateTime.wHour,
System_CreateTime.wMinute, System_CreateTime.wSecond, System_CreateTime.wMilliseconds);
}
else
{
sprintf (CreateTime_str, «00:00:00:000\0»);
}
if (pszProcessName == NULL)
pszProcessName = L «Idle»;
#ifdef _UNICODE
if (! pfnEnumProc (pProcesses->ProcessId, pszProcessName, CreateTime_str,
lParam))
break;
#else
CHAR szProcessName [MAX_PATH];
WideCharToMultiByte (CP_ACP, 0, pszProcessName, -1,
szProcessName, MAX_PATH, NULL, NULL);
if (! pfnEnumProc (pProcesses->ProcessId, szProcessName, CreateTime_str,
lParam))
break;
#endif
if (pProcesses->NextEntryDelta == 0)
break;
// find the address of the next process structure
pProcesses = (PSYSTEM_PROCESSES) (((LPBYTE) pProcesses)
+ pProcesses->NextEntryDelta);
}
HeapFree (hHeap, 0, pBuffer);
return TRUE;
}
·
mainfrm.cpp
#include «stdafx.h»
#include «pview.h»
#include «mainfrm.h»
#include «enumproc.h»
#include «secedit.h»
BEGIN_MESSAGE_MAP (CMainFrame, CFrameWnd)
ON_WM_CONTEXTMENU()
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_SETFOCUS()
ON_COMMAND (ID_VIEW_REFRESH, OnViewRefresh)
ON_COMMAND (ID_VIEW_APPLICATIONS, OnViewApplications)
ON_UPDATE_COMMAND_UI (ID_VIEW_APPLICATIONS,
OnViewApplications_Update)
ON_COMMAND (ID_VIEW_PROCESSES, OnViewProcesses)
ON_UPDATE_COMMAND_UI (ID_VIEW_PROCESSES,
OnViewProcesses_Update)
ON_COMMAND (ID_OPTIONS_ENUMPROC_TOOLHELP,
OnOptionsEnumprocToolhelp)
ON_UPDATE_COMMAND_UI (ID_OPTIONS_ENUMPROC_TOOLHELP,
OnOptionsEnumprocToolhelp_Update)
ON_COMMAND (ID_OPTIONS_ENUMPROC_NTAPI,
OnOptionsEnumprocNtapi)
ON_UPDATE_COMMAND_UI (ID_OPTIONS_ENUMPROC_NTAPI, OnOptionsEnumprocNtapi_Update)
ON_COMMAND (ID_OPTIONS_ENUMPROC_PERFDATA,
OnOptionsEnumprocPerfdata)
ON_UPDATE_COMMAND_UI (ID_OPTIONS_ENUMPROC_PERFDATA,
OnOptionsEnumprocPerfdata_Update)
ON_UPDATE_COMMAND_UI (ID_OPTIONS_DEBUG,
OnOptionsDebug_Update)
ON_COMMAND (ID_OPTIONS_DEBUG, OnOptionsDebug)
ON_COMMAND (ID_OPTIONS_ENUMPROC_WMI, OnOptionsEnumprocWmi)
ON_UPDATE_COMMAND_UI (ID_OPTIONS_ENUMPROC_WMI,
OnOptionsEnumprocWmi_Update)
ON_WM_TIMER()
ON_COMMAND (ID_ACTION_SECURITY, OnActionSecurity)
ON_UPDATE_COMMAND_UI (ID_ACTION_SECURITY,
OnActionSecurity_Update)
ON_WM_SYSCOLORCHANGE()
ON_NOTIFY (LVN_COLUMNCLICK, AFX_IDW_PANE_FIRST,
OnList_ColumnClick)
ON_NOTIFY (LVN_DELETEITEM, AFX_IDW_PANE_FIRST,
OnList_DeleteItem)
ON_COMMAND (ID_ABOUT, &CMainFrame: OnAbout)
END_MESSAGE_MAP()
// –
// CMainFrame
CMainFrame:CMainFrame()
{
m_bProcesses = -1;
m_nSortOrder = -1;
m_nAppsSortOrder = -1;
m_bShow16Bit = FALSE;
m_hVdmDbg = NULL;
m_pfnVDMEnumTaskWOWEx = NULL;
m_pfnVDMTerminateTaskWOW = NULL;
m_hPDH = NULL;
m_hPSAPI = NULL;
m_bWmiAvailable = NULL;
m_nRefreshPeriod = UPDATE_PERIOD_NORMAL;
m_bSedAvailable = FALSE;
//m_pfnIsAppHung = IsAppHung_SMTO;
m_dwWaitStart = 0;
m_osvi.dwOSVersionInfoSize = sizeof (m_osvi);
_VERIFY (GetVersionEx(&m_osvi));
}
// –
// ~CMainFrame
CMainFrame:~CMainFrame()
{
}
// –
// PreCreateWindow
BOOL
CMainFrame: PreCreateWindow (
CREATESTRUCT& cs
)
{
if (! CFrameWnd: PreCreateWindow(cs))
return FALSE;
cs.dwExStyle &= ~WS_EX_CLIENTEDGE;
cs.lpszClass = AfxRegisterWndClass (0, NULL, NULL,
AfxGetApp()->LoadIcon (IDR_MAINFRAME));
return TRUE;
}
// –
void
CMainFrame: OnContextMenu (
CWnd * pWnd,
)
{
if (pWnd!= &m_wndView)
return;
int nSel = m_wndView. GetNextItem (-1, LVNI_SELECTED);
if (nSel == -1)
return;
if (point.x == -1 && point.y == -1)
{
RECT rect;
m_wndView. GetItemRect (nSel, &rect, LVIR_BOUNDS);
m_wndView. ClientToScreen(&rect);
point.x = rect.left + 1;
point.y = rect.bottom + 1;
}
CMenu menu;
int nMenu = m_bProcesses? 0: 1;
menu. GetSubMenu(nMenu)->TrackPopupMenu (TPM_LEFTALIGN|TPM_LEFTBUTTON,
point.x, point.y, this);
}
// –
// OnCreate
int
CMainFrame: OnCreate (
CREATESTRUCT * pCreateStruct
)
{
OnSysColorChange();
RECT rcEmpty;
SetRectEmpty(&rcEmpty);
if (CFrameWnd: OnCreate(pCreateStruct) == -1)
return -1;
// create status bar
UINT nInd = ID_SEPARATOR;
if (! m_ImageList. Create (16, 16, ILC_COLOR32|ILC_MASK, 16,
16))
return -1;
// insert the default application icon into the image
list
m_ImageList. Add (LoadIcon(NULL, IDI_APPLICATION));
if (m_osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
m_hVdmDbg = LoadLibrary (_T(«vdmdbg.dll»));
if (m_hVdmDbg!= NULL)
{
m_pfnVDMEnumTaskWOWEx =
(VDMENUMTASKWOWEXPROC) GetProcAddress (m_hVdmDbg,
«VDMEnumTaskWOWEx»);
m_pfnVDMTerminateTaskWOW =
(VDMTERMINATETASKINWOWPROC) GetProcAddress (m_hVdmDbg,
«VDMTerminateTaskWOW»);
}
}
m_hPSAPI = LoadLibrary (_T(«psapi.dll»));
m_hPDH = LoadLibrary (_T(«pdh.dll»));
IWbemLocator * pLocator = NULL;
HRESULT hRes = CoCreateInstance (__uuidof(WbemLocator), NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IWbemLocator),
(PVOID *)&pLocator);
if (SUCCEEDED(hRes))
{
pLocator->Release();
m_bWmiAvailable = TRUE;
}
else
{
m_bWmiAvailable = FALSE;
}
m_bSedAvailable = CProcessSecInfo: IsDaclEditorAvailable();
m_nEnumProcMethod = (int) g_theApp. GetProfileInt (_T(«Settings»),
_T («EnumProcessesMethod»), ENUMPROCESSES_INVALID);
if (m_nEnumProcMethod == ENUMPROCESSES_PERFDATA &&
m_hPDH == NULL)
m_nEnumProcMethod = ENUMPROCESSES_INVALID;
if (m_nEnumProcMethod == ENUMPROCESSES_WMI &&
! m_bWmiAvailable)
m_nEnumProcMethod = ENUMPROCESSES_INVALID;
if (m_nEnumProcMethod == ENUMPROCESSES_INVALID)
{
if (m_osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
m_nEnumProcMethod = ENUMPROCESSES_TOOLHELP;
else
m_nEnumProcMethod = ENUMPROCESSES_NTAPI;
}
int bProcesses = (int) g_theApp. GetProfileInt (_T(«Settings»), _T
(«ProcessesMode»), 1);
m_nSortOrder = (int) g_theApp. GetProfileInt (_T(«Settings»),
_T («ProcessesSortOrder»), -1);
m_nAppsSortOrder = (int) g_theApp. GetProfileInt (_T(«Settings»),
_T («ApplicationsSortOrder»), -1);
m_bShow16Bit = (BOOL) g_theApp. GetProfileInt (_T(«Settings»),
_T («Show16Bit»), FALSE);
if (m_pfnVDMEnumTaskWOWEx == NULL ||
m_pfnVDMTerminateTaskWOW == NULL)
m_bShow16Bit = FALSE;
m_nRefreshPeriod = g_theApp. GetProfileInt (_T(«Settings»), _T
(«UpdateSpeed»), UPDATE_PERIOD_NORMAL);
if (m_nRefreshPeriod!= UPDATE_PERIOD_PAUSED)
SetTimer (1, m_nRefreshPeriod, NULL);
int bHung = (int) g_theApp. GetProfileInt (_T(«Settings»),_T («IsAppHung»),
0);
PBYTE pData = NULL;
UINT cbData = 0;
int * pnValues = NULL;
if (g_theApp. GetProfileBinary (_T(«Settings»), _T («ListView»),
&pData, &cbData))
{
if (cbData == 8 * sizeof(int))
{
pnValues = (int *) pData;
m_nProcColWidth[0] = pnValues[0];
m_nProcColWidth[1] = pnValues[1];
m_nAppsColWidth[0] = pnValues[2];
m_nAppsColWidth[1] = pnValues[3];
m_nProcColOrder[0] = pnValues[4];
m_nProcColOrder[1] = pnValues[5];
m_nAppsColOrder[0] = pnValues[6];
m_nAppsColOrder[1] = pnValues[7];
}
delete[] pData;
}
if (pnValues == NULL)
{
m_nProcColWidth[0] = LVSCW_AUTOSIZE_USEHEADER;
m_nProcColWidth[1] = LVSCW_AUTOSIZE_USEHEADER;
m_nAppsColWidth[0] = LVSCW_AUTOSIZE_USEHEADER;
m_nAppsColWidth[1] = LVSCW_AUTOSIZE_USEHEADER;
m_nProcColOrder[0] = 0;
m_nProcColOrder[1] = 1;
m_nAppsColOrder[0] = 0;
m_nAppsColOrder[1] = 1;
}
if (bProcesses)
OnViewProcesses();
else
OnViewApplications();
return 0;
}
// –
// OnDestroy
void
CMainFrame: OnDestroy()
{
SaveViewSettings();
g_theApp. WriteProfileInt (_T(«Settings»), _T («EnumProcessesMethod»),
m_nEnumProcMethod);
g_theApp. WriteProfileInt (_T(«Settings»), _T («ProcessesMode»),
m_bProcesses);
g_theApp. WriteProfileInt (_T(«Settings»), _T («ProcessesSortOrder»),
m_nSortOrder);
g_theApp. WriteProfileInt (_T(«Settings»), _T («ApplicationsSortOrder»),
m_nAppsSortOrder);
g_theApp. WriteProfileInt (_T(«Settings»), _T («Show16Bit»),
m_bShow16Bit);
g_theApp. WriteProfileInt (_T(«Settings»), _T («UpdateSpeed»),
m_nRefreshPeriod);
int nValues[8];
nValues[0] = m_nProcColWidth[0];
nValues[1] = m_nProcColWidth[1];
nValues[2] = m_nAppsColWidth[0];
nValues[3] = m_nAppsColWidth[1];
nValues[4] = m_nProcColOrder[0];
nValues[5] = m_nProcColOrder[1];
nValues[6] = m_nAppsColOrder[0];
nValues[7] = m_nAppsColOrder[1];
g_theApp. WriteProfileBinary (_T(«Settings»), _T («ListView»),
(LPBYTE) nValues, sizeof(nValues));
if (m_hVdmDbg!= NULL)
_VERIFY (FreeLibrary(m_hVdmDbg));
m_hVdmDbg = NULL;
m_pfnVDMEnumTaskWOWEx = NULL;
m_pfnVDMTerminateTaskWOW = NULL;
if (m_hPSAPI!= NULL)
_VERIFY (FreeLibrary(m_hPSAPI));
if (m_hPDH!= NULL)
_VERIFY (FreeLibrary(m_hPDH));
CFrameWnd: OnDestroy();
}
// –
// OnSetFocus
void
CMainFrame: OnSetFocus (
CWnd * pOldWnd
)
{
_UNUSED(pOldWnd);
// forward focus to the view window
m_wndView. SetFocus();
}
// –
// OnSysColorChange
void CMainFrame: OnSysColorChange()
{
CFrameWnd: OnSysColorChange();
if (m_bmSortUp.m_hObject!= NULL)
_VERIFY (m_bmSortUp. DeleteObject());
if (m_bmSortDown.m_hObject!= NULL)
_VERIFY (m_bmSortDown. DeleteObject());
_VERIFY (m_bmSortUp. LoadMappedBitmap (IDB_SORT_UP));
_VERIFY (m_bmSortDown. LoadMappedBitmap (IDB_SORT_DOWN));
}
// –
// OnTimer
void
CMainFrame: OnTimer (
UINT nIDEvent
)
{
_UNUSED(nIDEvent);
_ASSERTE (nIDEvent == 1);
OnViewRefresh();
}
// –
// OnActionSecurity
void
CMainFrame: OnActionSecurity()
{
int nSel = m_wndView. GetNextItem (-1, LVNI_SELECTED); _ASSERTE
(nSel!= -1);
CItemData * pData = (CItemData *) m_wndView. GetItemData(nSel);
_ASSERTE (_CrtIsValidHeapPointer(pData));
CProcessSecInfo SecInfo;
if (! SecInfo. EditDacl (m_hWnd, pData->dwProcessId,
pData->strName))
AfxThrowOleException (HRESULT_FROM_WIN32 (GetLastError()));
}
// –
// OnActionSecurity_Update
void
CMainFrame: OnActionSecurity_Update (CCmdUI * pCmdUI)
{
BOOL bEnable = FALSE;
if (m_bProcesses && m_bSedAvailable &&
m_strMachineName. IsEmpty())
{
int nSel = m_wndView. GetNextItem (-1, LVNI_SELECTED);
if (nSel!= -1)
{CItemData * pData = (CItemData *) m_wndView. GetItemData(nSel);
_ASSERTE (_CrtIsValidHeapPointer(pData));
Enable = pData->dwProcessId!= 0 &&
pData->dwWowTaskId == 0;
}
}
pCmdUI->Enable(bEnable);
}
// –
// OnViewApplications
void
CMainFrame: OnViewApplications()
{
if (m_bProcesses!= 0)
{
if (:IsWindow (m_wndView.m_hWnd))
{
SaveViewSettings();
m_wndView. DestroyWindow();
}
DWORD dwStyle;
// create a view to occupy the client area of the frame
dwStyle = WS_CHILD|WS_VISIBLE|LVS_REPORT|LVS_SHAREIMAGELISTS|
LVS_SHOWSELALWAYS|LVS_SINGLESEL;
RECT rcClient;
GetClientRect(&rcClient);
m_wndView. Create (dwStyle, rcClient, this,
AFX_IDW_PANE_FIRST);
m_wndView. ModifyStyleEx (0, WS_EX_CLIENTEDGE);
m_wndView. SetExtendedStyle (LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP);
m_wndView. SetImageList (&m_ImageList, LVSIL_SMALL);
RecalcLayout();
m_strMachineName. Empty();
// remove any colums currently in the list
while (m_wndView. DeleteColumn(0));
TCHAR szColumn[256];
// add two colums to the list control
AfxLoadString (IDS_APPS_TASK, szColumn, countof(szColumn));
m_wndView. InsertColumn (0, szColumn);
AfxLoadString (IDS_APPS_STATUS, szColumn, countof(szColumn));
m_wndView. InsertColumn (1, szColumn);
m_bProcesses = 0;
m_wndView. SetRedraw(FALSE);
m_wndView. SetColumnWidth (0, m_nAppsColWidth[0]);
m_wndView. SetColumnWidth (1, m_nAppsColWidth[1]);
m_wndView. SetColumnOrderArray (2, m_nAppsColOrder);
OnViewRefresh();
}
}
// –
// OnViewApplications_Update
void
CMainFrame: OnViewApplications_Update (CCmdUI * pCmdUI)
{
_ASSERTE (pCmdUI!= NULL);
pCmdUI->SetRadio (! m_bProcesses);
}
// –
// OnViewProcesses
void
CMainFrame: OnViewProcesses()
{
if (m_bProcesses!= 1)
{
if (:IsWindow (m_wndView.m_hWnd))
{
SaveViewSettings();
m_wndView. DestroyWindow();
}
DWORD dwStyle;
// create a view to occupy the client area of the frame
dwStyle = WS_CHILD|WS_VISIBLE|LVS_REPORT|LVS_SHAREIMAGELISTS|
LVS_SHOWSELALWAYS|LVS_SINGLESEL;
RECT rcClient;
GetClientRect(&rcClient);
m_wndView. Create (dwStyle, rcClient, this,
AFX_IDW_PANE_FIRST);
m_wndView. ModifyStyleEx (0, WS_EX_CLIENTEDGE);
m_wndView. SetExtendedStyle (LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP);
RecalcLayout();
TCHAR szColumn[256];
// add two colums to the list control
AfxLoadString (IDS_PROCESSES_ID, szColumn,
countof(szColumn));
m_wndView. InsertColumn (0, szColumn);
AfxLoadString (IDS_PROCESSES_NAME, szColumn,
countof(szColumn));
m_wndView. InsertColumn (1, szColumn);
AfxLoadString (IDS_PROCESSES_time, szColumn,
countof(szColumn));
m_wndView. InsertColumn (2, szColumn);
m_bProcesses = 1;
m_wndView. SetRedraw(FALSE);
m_wndView. SetColumnWidth (0, 103);
m_wndView. SetColumnWidth (1, 103);
m_wndView. SetColumnWidth (2, 103);
m_wndView. SetColumnOrderArray (2, m_nProcColOrder);
OnViewRefresh();
}
}
// –
// OnViewProcesses_Update
void CMainFrame: OnViewProcesses_Update (
CCmdUI * pCmdUI
)
{
_ASSERTE (pCmdUI!= NULL);
pCmdUI->SetRadio (m_bProcesses);
}
// –
// OnViewRefresh
//
// Handles View|Refresh menu command. Refreshes the
currently displayed
// information.
void
CMainFrame: OnViewRefresh()
{
int i;
if (m_nRefreshPeriod == UPDATE_PERIOD_PAUSED)
AfxGetApp()->BeginWaitCursor();
m_wndView. SetRedraw(FALSE);
// mark all items
int nCount = m_wndView. GetItemCount();
for (i = 0; i < nCount; i++)
{
CItemData * pData = (CItemData *) m_wndView. GetItemData(i);
pData->bDelete = TRUE;
}
try
{
if (m_bProcesses)
ListProcesses();
}
catch (CException * pe)
{
if (m_nRefreshPeriod!= UPDATE_PERIOD_PAUSED)
{
KillTimer(1);
m_nRefreshPeriod = UPDATE_PERIOD_PAUSED;
}
pe->ReportError();
pe->Delete();
}
// walk through the list and delete items which are
still marked
nCount = m_wndView. GetItemCount();
for (i = nCount – 1; i >= 0; i–)
{
CItemData * pData = (CItemData *) m_wndView. GetItemData(i);
_ASSERTE (pData!= NULL);
if (pData->bDelete)
m_wndView. DeleteItem(i);
}
m_wndView. SetRedraw(TRUE);
TCHAR szFormat[256];
TCHAR szTitle[256];
if (m_strMachineName. IsEmpty())
AfxLoadString (IDS_TITLE_LOCAL, szFormat, countof(szFormat));
else
AfxLoadString (IDS_TITLE_REMOTE, szFormat,
countof(szFormat));
wsprintf (szTitle, szFormat, (LPCTSTR) m_strMachineName);
SetWindowText(szTitle);
if (m_nRefreshPeriod == UPDATE_PERIOD_PAUSED)
AfxGetApp()->EndWaitCursor();
}
// –
// OnViewSpeedPaused_Update
void
CMainFrame: OnViewSpeedPaused_Update (
CCmdUI * pCmdUI
)
{
_ASSERTE (pCmdUI!= NULL);
pCmdUI->SetRadio (m_nRefreshPeriod ==
UPDATE_PERIOD_PAUSED);
}
// –
void
CMainFrame: OnOptionsEnumprocToolhelp()
{
m_nEnumProcMethod = ENUMPROCESSES_TOOLHELP;
OnViewRefresh();
}
// –
// OnOptionsEnumprocToolhelp_Update
void CMainFrame: OnOptionsEnumprocToolhelp_Update (CCmdUI*
pCmdUI)
{
_ASSERTE (pCmdUI!= NULL);
BOOL bEnable = (m_osvi.dwPlatformId == VER_PLATFORM_WIN32_NT &&
m_osvi.dwMajorVersion >= 5) || m_osvi.dwPlatformId ==
VER_PLATFORM_WIN32_WINDOWS;
pCmdUI->Enable (bEnable && m_strMachineName. IsEmpty());
pCmdUI->SetRadio (m_nEnumProcMethod ==
ENUMPROCESSES_TOOLHELP);
}
// –
// OnOptionsEnumprocNtapi
void CMainFrame: OnOptionsEnumprocNtapi()
{
m_nEnumProcMethod = ENUMPROCESSES_NTAPI;
OnViewRefresh();
}
// –
// OnOptionsEnumprocNtapi_Update
void
CMainFrame: OnOptionsEnumprocNtapi_Update (
CCmdUI * pCmdUI
)
{
_ASSERTE (pCmdUI!= NULL);
pCmdUI->Enable (m_osvi.dwPlatformId ==
VER_PLATFORM_WIN32_NT &&
m_strMachineName. IsEmpty());
pCmdUI->SetRadio (m_nEnumProcMethod ==
ENUMPROCESSES_NTAPI);
}
// –
// OnOptionsEnumprocPerfdata
void CMainFrame: OnOptionsEnumprocPerfdata()
{
m_nEnumProcMethod = ENUMPROCESSES_PERFDATA;
OnViewRefresh();
}
// –
// OnOptionsEnumprocPerfdata_Update
void
CMainFrame: OnOptionsEnumprocPerfdata_Update (
CCmdUI * pCmdUI
)
{
_ASSERTE (pCmdUI!= NULL);
pCmdUI->Enable (m_hPDH!= NULL);
pCmdUI->SetRadio (m_nEnumProcMethod ==
ENUMPROCESSES_PERFDATA);
}
// –
// OnOptionsEnumprocWmi
void
CMainFrame: OnOptionsEnumprocWmi()
{
m_nEnumProcMethod = ENUMPROCESSES_WMI;
OnViewRefresh();
}
// –
// OnOptionsEnumprocWmi_Update
void
CMainFrame: OnOptionsEnumprocWmi_Update (
CCmdUI * pCmdUI
)
{
_ASSERTE (pCmdUI!= NULL);
pCmdUI->Enable (m_bWmiAvailable!= NULL);
pCmdUI->SetRadio (m_nEnumProcMethod == ENUMPROCESSES_WMI);
}
// –
// OnOptionsDebug
void
CMainFrame: OnOptionsDebug()
{
TOKEN_PRIVILEGES tkp;
tkp. PrivilegeCount = 1;
LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &tkp. Privileges[0].Luid);
HANDLE hToken;
if (OpenProcessToken (GetCurrentProcess(), ЕOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES,&hToken))
{
AdjustTokenPrivileges (hToken, FALSE, &tkp,
sizeof(tkp), NULL, NULL);
CloseHandle(hToken);
}
OnViewRefresh();
}
// –
// OnOptionsDebug_Update
void
CMainFrame: OnOptionsDebug_Update (CCmdUI* pCmdUI)
{
_ASSERTE (pCmdUI!= NULL);
LUID Luid;
LookupPrivilegeValue (NULL, SE_DEBUG_NAME, &Luid);
if (m_osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
{}
else
pCmdUI->Enable(FALSE);
}
// –
// OnList_ColumnClick
void
CMainFrame: OnList_ColumnClick (
NMHDR * pNMHDR,
LRESULT * pResult
)
{
_UNUSED(pResult);
_ASSERTE (pNMHDR!= NULL);
_ASSERTE (pResult!= NULL);
NMLISTVIEW * pnmlv = (NMLISTVIEW *) pNMHDR;
if (m_bProcesses)
{
if (pnmlv->iSubItem == abs (m_nSortOrder) – 1)
m_nSortOrder = – m_nSortOrder;
else
m_nSortOrder = – (pnmlv->iSubItem + 1);
m_wndView. SortItems (SortCallback, m_nSortOrder);
SetSortMark (m_nSortOrder);
}
else
{
if (pnmlv->iSubItem == abs (m_nAppsSortOrder) – 1)
m_nAppsSortOrder = – m_nAppsSortOrder;
else
m_nAppsSortOrder = – (pnmlv->iSubItem + 1);
m_wndView. SortItems (AppsSortCallback, m_nAppsSortOrder);
SetSortMark (m_nAppsSortOrder);
}
}
// –
// OnList_DeleteItem
void
CMainFrame: OnList_DeleteItem (NMHDR * pNMHDR, LRESULT *
pResult)
{
_UNUSED(pResult);
_ASSERTE (pNMHDR!= NULL);
_ASSERTE (pResult!= NULL);
NMLISTVIEW * pnmlv = (NMLISTVIEW *) pNMHDR;
CItemData * pData = (CItemData *) m_wndView. GetItemData (pnmlv->iItem);
_ASSERTE (pData!= NULL);
delete pData;
}
// –
// SaveViewSettings
void
CMainFrame: SaveViewSettings()
{
if (m_bProcesses)
{
m_nProcColWidth[0] = m_wndView. GetColumnWidth(0);
m_nProcColWidth[1] = m_wndView. GetColumnWidth(1);
m_nProcColWidth[2] = m_wndView. GetColumnWidth(2);
m_wndView. GetColumnOrderArray (m_nProcColOrder, 2);
}
else
{
m_nAppsColWidth[0] = m_wndView. GetColumnWidth(0);
m_nAppsColWidth[1] = m_wndView. GetColumnWidth(1);
m_wndView. GetColumnOrderArray (m_nAppsColOrder, 2);
}
}
// –
// SetSortMark
void
CMainFrame: SetSortMark (int nOrder)
{
int nSubItem = abs(nOrder) – 1;
CHeaderCtrl& hdr = *m_wndView. GetHeaderCtrl();
int nCount = hdr. GetItemCount();
for (int i = 0; i < nCount; i++)
{
HDITEM hdi;
hdi.mask = HDI_FORMAT;
_VERIFY (hdr. GetItem (i, &hdi));
if (i!= nSubItem)
{
hdi.fmt &= ~(HDF_BITMAP|HDF_BITMAP_ON_RIGHT);
}
else
{
hdi.mask |= HDI_BITMAP;
hdi.fmt |= HDF_BITMAP|HDF_BITMAP_ON_RIGHT;
hdi.hbm = (nOrder > 0)? m_bmSortDown: m_bmSortUp;
}
_VERIFY (hdr. SetItem (i, &hdi));
}
}
// –
// SortCallback
int
CALLBACK
CMainFrame: SortCallback (LPARAM lParam1, LPARAM lParam2, LPARAM
lParamSort)
{
CItemData * pData1 = (CItemData *) lParam1;
CItemData * pData2 = (CItemData *) lParam2;
_ASSERTE (_CrtIsValidHeapPointer(pData1));
_ASSERTE (_CrtIsValidHeapPointer(pData2));
int nRes;
switch (abs(lParamSort))
{
// sort on process identifiers
case 1:
nRes = (int) pData2->dwProcessId – (int) pData1->dwProcessId;
break;
// sort on process names
case 2:
nRes = lstrcmpi (pData2->strName, pData1->strName);
break;
default:
_ASSERTE(0);
__assume(0);
}
if (lParamSort < 0)
nRes = – nRes;
if (nRes == 0)
nRes = (int) pData1->dwWowTaskId – (int) pData2->dwWowTaskId;
return nRes;
}
// –
// AppsSortCallback
int
CALLBACK
CMainFrame: AppsSortCallback (LPARAM lParam1, LPARAM lParam2,
LPARAM lParamSort)
{
CItemData * pData1 = (CItemData *) lParam1;
CItemData * pData2 = (CItemData *) lParam2;
_ASSERTE (_CrtIsValidHeapPointer(pData1));
_ASSERTE (_CrtIsValidHeapPointer(pData2));
int nRes;
switch (abs(lParamSort))
{
// sort on application names
case 1:
nRes = lstrcmpi (pData2->strName, pData1->strName);
break;
// sort on application status
case 2:
if (pData1->bRunning &&! pData2->bRunning)
nRes = 1;
else if (! pData1->bRunning &&
pData2->bRunning)
nRes = -1;
else
nRes = lstrcmpi (pData2->strName, pData1->strName);
break;
default:
_ASSERTE(0);
__assume(0);
}
if (lParamSort < 0)
nRes = – nRes;
return nRes;
}
// –
// ListProcesses
void
CMainFrame: ListProcesses()
{
PFNENUMPROCESSES pfnEnumProc = NULL;
// select enumeration function to use
switch (m_nEnumProcMethod)
{
case ENUMPROCESSES_TOOLHELP:
pfnEnumProc = EnumProcesses_ToolHelp;
break;
case ENUMPROCESSES_NTAPI:
pfnEnumProc = EnumProcesses_NtApi;
break;
case ENUMPROCESSES_PERFDATA:
pfnEnumProc = EnumProcesses_PerfData;
break;
case ENUMPROCESSES_WMI:
pfnEnumProc = EnumProcesses_Wmi;
break;
default:
_ASSERTE(0);
__assume(0);
}
_ASSERTE (pfnEnumProc!= NULL);
LPCTSTR pszMachineName = NULL;
if (! m_strMachineName. IsEmpty())
pszMachineName = m_strMachineName;
// call process enumeration function
if (! pfnEnumProc (pszMachineName, EnumProcessCallback,
(LPARAM) this))
AfxThrowOleException (HRESULT_FROM_WIN32 (GetLastError()));
m_wndView. SortItems (SortCallback, m_nSortOrder);
SetSortMark (m_nSortOrder);
}
// –
// EnumProcessCallback
BOOL
CALLBACK
CMainFrame: EnumProcessCallback (
DWORD dwProcessId,
LPCTSTR pszName,
char CreateTime_str[55],
LPARAM lParam
)
{
CMainFrame * pFrame = (CMainFrame *) lParam;
ASSERT_VALID(pFrame);
CListCtrl& wndView = pFrame->m_wndView;
CItemData * pData;
BOOL bFound = FALSE;
TCHAR szID[64];
wsprintf (szID, _T («%u (0x % X)»), dwProcessId,
dwProcessId);
// try to find the corresponding item in the list
int nCount = wndView. GetItemCount();
for (nItem = 0; nItem < nCount; nItem++)
{
pData = (CItemData *) wndView. GetItemData(nItem);
if (pData->dwProcessId == dwProcessId &&
pData->dwWowTaskId == 0 &&
pData->strName == pszName)
{
pData->bDelete = FALSE;
bFound = TRUE;
break;
}
}
if (! bFound)
{
pData = new CItemData (dwProcessId, DWORD(0));
nItem = wndView. InsertItem (LVIF_TEXT|LVIF_PARAM, nCount,
szID,
0, 0, -1, (LPARAM) pData);
if (nItem == -1)
{
delete pData;
return TRUE;
}
TCHAR szUnavailable[256];
if (pszName == NULL)
{
AfxLoadString (IDS_NAME_UNAVAILABLE, szUnavailable,
countof(szUnavailable));
pszName = szUnavailable;
}
pData->strName = pszName;
wndView. SetItemText (nItem, 1, pszName);
wndView. SetItemText (nItem, 2, CreateTime_str);
}
if (pFrame->m_bShow16Bit &&
(lstrcmpi (pszName, _T («NTVDM.EXE»)) == 0 ||
lstrcmpi (pszName, _T («NTVDM»)) == 0))
{
_ASSERTE (pFrame->m_pfnVDMEnumTaskWOWEx!= NULL);
pFrame->m_dwProcessId = dwProcessId;
}
return TRUE;
}
void CMainFrame: OnAbout()
{
DestroyWindow();
}