mirror of
https://github.com/arehnman/yttrium-virtio-gpu.git
synced 2026-11-07 02:06:32 +00:00
balloon: (related to bz#1082999) add device events handling.
A new implementation of the balloon's service which add handling of device insertion and removal. It also prepare the service to work with a new method of write request in the driver.
This commit is contained in:
1 parent
0dcf4e6737
commit
f542c3f14d
8 files changed
+264
-278
No files matched your search
+165
-36
@@ -1,61 +1,184 @@
|
||||
#include "device.h"
|
||||
#include "public.h"
|
||||
#include "utils.h"
|
||||
#include "memstat.h"
|
||||
|
||||
#include <dbt.h>
|
||||
#include <setupapi.h>
|
||||
#include <tchar.h>
|
||||
|
||||
CDevice::CDevice()
|
||||
{
|
||||
m_hDevice = INVALID_HANDLE_VALUE;
|
||||
m_pMemStat = NULL;
|
||||
m_hService = NULL;
|
||||
m_hThread = NULL;
|
||||
m_evtTerminate = NULL;
|
||||
m_evtWrite = NULL;
|
||||
}
|
||||
|
||||
CDevice::~CDevice()
|
||||
{
|
||||
BALLOON_STAT stat[VIRTIO_BALLOON_S_NR];
|
||||
if (m_hDevice != INVALID_HANDLE_VALUE) {
|
||||
memset(stat, -1, sizeof(BALLOON_STAT) * VIRTIO_BALLOON_S_NR);
|
||||
Write(stat, VIRTIO_BALLOON_S_NR);
|
||||
CloseHandle(m_hDevice);
|
||||
m_hDevice = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
Fini();
|
||||
}
|
||||
|
||||
BOOL CDevice::Init()
|
||||
BOOL CDevice::Init(SERVICE_STATUS_HANDLE hService)
|
||||
{
|
||||
PWCHAR DevicePath = NULL;
|
||||
if ((DevicePath = GetDevicePath((LPGUID)&GUID_DEVINTERFACE_BALLOON)) != NULL) {
|
||||
m_hDevice = CreateFile(
|
||||
DevicePath,
|
||||
GENERIC_WRITE,
|
||||
0,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
NULL
|
||||
);
|
||||
m_pMemStat = new CMemStat();
|
||||
if (!m_pMemStat || !m_pMemStat->Init()) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_hDevice != INVALID_HANDLE_VALUE) {
|
||||
PrintMessage("Open balloon device");
|
||||
return TRUE;
|
||||
m_evtTerminate = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (!m_evtTerminate) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_evtWrite = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
if (!m_evtWrite) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_hService = hService;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID CDevice::Fini()
|
||||
{
|
||||
Stop();
|
||||
|
||||
if (m_evtWrite) {
|
||||
CloseHandle(m_evtWrite);
|
||||
m_evtWrite = NULL;
|
||||
}
|
||||
|
||||
if (m_evtTerminate) {
|
||||
CloseHandle(m_evtTerminate);
|
||||
m_evtTerminate = NULL;
|
||||
}
|
||||
|
||||
m_hService = NULL;
|
||||
|
||||
delete m_pMemStat;
|
||||
m_pMemStat = NULL;
|
||||
}
|
||||
|
||||
DWORD CDevice::Run()
|
||||
{
|
||||
PWCHAR DevicePath = GetDevicePath((LPGUID)&GUID_DEVINTERFACE_BALLOON);
|
||||
if (DevicePath == NULL) {
|
||||
PrintMessage("File not found.");
|
||||
return ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
HANDLE hDevice = CreateFile(DevicePath, GENERIC_WRITE, 0, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
|
||||
|
||||
free(DevicePath);
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
||||
PrintMessage("Failed to create file.");
|
||||
return GetLastError();
|
||||
}
|
||||
|
||||
DEV_BROADCAST_HANDLE filter;
|
||||
HDEVNOTIFY devnotify;
|
||||
|
||||
ZeroMemory(&filter, sizeof(filter));
|
||||
filter.dbch_size = sizeof(filter);
|
||||
filter.dbch_devicetype = DBT_DEVTYP_HANDLE;
|
||||
filter.dbch_handle = hDevice;
|
||||
|
||||
devnotify = RegisterDeviceNotification(m_hService, &filter,
|
||||
DEVICE_NOTIFY_SERVICE_HANDLE);
|
||||
|
||||
if (!devnotify) {
|
||||
DWORD err = GetLastError();
|
||||
PrintMessage("Failed to register handle notification.");
|
||||
CloseHandle(hDevice);
|
||||
return err;
|
||||
}
|
||||
|
||||
WriteLoop(hDevice);
|
||||
|
||||
UnregisterDeviceNotification(devnotify);
|
||||
CloseHandle(hDevice);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
VOID CDevice::WriteLoop(HANDLE hDevice)
|
||||
{
|
||||
HANDLE waitfor[] = { m_evtTerminate, m_evtWrite };
|
||||
OVERLAPPED ovlp;
|
||||
DWORD timeout;
|
||||
DWORD written;
|
||||
DWORD waitrc;
|
||||
BOOL writerc;
|
||||
|
||||
ZeroMemory(&ovlp, sizeof(ovlp));
|
||||
ovlp.hEvent = m_evtWrite;
|
||||
|
||||
while (1) {
|
||||
// The old version of the balloon driver didn't block write requests
|
||||
// until stats were requested. So in order not to consume too much CPU
|
||||
// we keep the old 1s delay behavior and switch to infinite wait only
|
||||
// if write result is pending.
|
||||
timeout = 1000;
|
||||
|
||||
if (m_pMemStat->Update()) {
|
||||
writerc = WriteFile(hDevice, m_pMemStat->GetBuffer(),
|
||||
m_pMemStat->GetSize(), NULL, &ovlp);
|
||||
if (!writerc && (GetLastError() == ERROR_IO_PENDING)) {
|
||||
timeout = INFINITE;
|
||||
}
|
||||
}
|
||||
|
||||
waitrc = WaitForMultipleObjects(sizeof(waitfor) / sizeof(waitfor[0]),
|
||||
waitfor, FALSE, timeout);
|
||||
|
||||
if (waitrc == WAIT_OBJECT_0) {
|
||||
break;
|
||||
}
|
||||
else if (waitrc == WAIT_OBJECT_0 + 1) {
|
||||
if (!GetOverlappedResult(hDevice, &ovlp, &written, FALSE) ||
|
||||
(written != m_pMemStat->GetSize()))
|
||||
{
|
||||
PrintMessage("Failed to write stats.");
|
||||
}
|
||||
}
|
||||
}
|
||||
PrintMessage("Cannot find balloon device");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL CDevice::Write(PBALLOON_STAT pstat, int nr)
|
||||
BOOL CDevice::Start()
|
||||
{
|
||||
BOOL res = FALSE;
|
||||
ULONG ret = 0;
|
||||
res = WriteFile(m_hDevice, pstat, sizeof(BALLOON_STAT) * nr, &ret, NULL);
|
||||
if (!res) {
|
||||
PrintMessage("Cannot write balloon device");
|
||||
} else if ( ret != sizeof(BALLOON_STAT) * nr) {
|
||||
PrintMessage("Write balloon device error");
|
||||
ret = FALSE;
|
||||
DWORD tid;
|
||||
|
||||
if (!m_hThread) {
|
||||
m_hThread = CreateThread(NULL, 0,
|
||||
(LPTHREAD_START_ROUTINE)DeviceThread, (LPVOID)this, 0, &tid);
|
||||
}
|
||||
return res;
|
||||
|
||||
return (m_hThread != NULL);
|
||||
}
|
||||
|
||||
VOID CDevice::Stop()
|
||||
{
|
||||
if (m_hThread) {
|
||||
SetEvent(m_evtTerminate);
|
||||
if (WaitForSingleObject(m_hThread, 1000) == WAIT_TIMEOUT) {
|
||||
TerminateThread(m_hThread, 0);
|
||||
}
|
||||
CloseHandle(m_hThread);
|
||||
m_hThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD WINAPI CDevice::DeviceThread(LPDWORD lParam)
|
||||
{
|
||||
CDevice* pDev = reinterpret_cast<CDevice*>(lParam);
|
||||
return pDev->Run();
|
||||
}
|
||||
|
||||
PTCHAR CDevice::GetDevicePath( IN LPGUID InterfaceGuid )
|
||||
{
|
||||
@@ -64,6 +187,7 @@ PTCHAR CDevice::GetDevicePath( IN LPGUID InterfaceGuid )
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData = NULL;
|
||||
ULONG Length, RequiredLength = 0;
|
||||
BOOL bResult;
|
||||
PTCHAR DevicePath;
|
||||
|
||||
HardwareDeviceInfo = SetupDiGetClassDevs(
|
||||
InterfaceGuid,
|
||||
@@ -130,5 +254,10 @@ PTCHAR CDevice::GetDevicePath( IN LPGUID InterfaceGuid )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return DeviceInterfaceDetailData->DevicePath;
|
||||
DevicePath = _tcsdup(DeviceInterfaceDetailData->DevicePath);
|
||||
|
||||
SetupDiDestroyDeviceInfoList(HardwareDeviceInfo);
|
||||
LocalFree(DeviceInterfaceDetailData);
|
||||
|
||||
return DevicePath;
|
||||
}
|
||||
+17
-13
@@ -1,26 +1,30 @@
|
||||
#ifndef DEVICE_H
|
||||
#define DEVICE_H
|
||||
|
||||
#define INITGUID
|
||||
|
||||
#include <windows.h>
|
||||
#include <strsafe.h>
|
||||
#include <setupapi.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "public.h"
|
||||
#include <wtypes.h>
|
||||
|
||||
class CMemStat;
|
||||
|
||||
class CDevice {
|
||||
public:
|
||||
CDevice();
|
||||
~CDevice();
|
||||
BOOL Init();
|
||||
BOOL Write(PBALLOON_STAT pstat, int nr);
|
||||
BOOL Init(SERVICE_STATUS_HANDLE hService);
|
||||
VOID Fini();
|
||||
BOOL Start();
|
||||
VOID Stop();
|
||||
|
||||
protected:
|
||||
HANDLE m_hDevice;
|
||||
PTCHAR GetDevicePath( IN LPGUID InterfaceGuid );
|
||||
PTCHAR GetDevicePath(IN LPGUID InterfaceGuid);
|
||||
DWORD Run();
|
||||
private:
|
||||
static DWORD WINAPI DeviceThread(LPDWORD lParam);
|
||||
VOID WriteLoop(HANDLE hDevice);
|
||||
CMemStat* m_pMemStat;
|
||||
SERVICE_STATUS_HANDLE m_hService;
|
||||
HANDLE m_hThread;
|
||||
HANDLE m_evtTerminate;
|
||||
HANDLE m_evtWrite;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+3
-21
@@ -1,30 +1,16 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <tchar.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "service.h"
|
||||
|
||||
LPWSTR ServiceName = L"BalloonService";
|
||||
LPWSTR DisplayName = L"Balloon Service";
|
||||
|
||||
CService srvc;
|
||||
|
||||
void __stdcall Handler(DWORD ctlcode)
|
||||
{
|
||||
CService::HandlerThunk(&srvc, ctlcode);
|
||||
}
|
||||
|
||||
void __stdcall ServiceMain(DWORD argc, TCHAR* argv[])
|
||||
{
|
||||
srvc.m_StatusHandle = RegisterServiceCtrlHandler(argv[0], (LPHANDLER_FUNCTION) Handler);
|
||||
CService::ServiceMainThunk(&srvc, argc, argv);
|
||||
}
|
||||
|
||||
SERVICE_TABLE_ENTRY serviceTable[] =
|
||||
{
|
||||
{ ServiceName, (LPSERVICE_MAIN_FUNCTION) ServiceMain},
|
||||
{ NULL, NULL}
|
||||
};
|
||||
|
||||
void __stdcall HandlerEx(DWORD ctlcode, DWORD evtype, PVOID evdata, PVOID context)
|
||||
{
|
||||
CService::HandlerExThunk((CService*) context, ctlcode, evtype, evdata);
|
||||
@@ -59,10 +45,6 @@ wmain(
|
||||
ServiceRun();
|
||||
} else if (_tcsicmp(L"-s", argv[1]) == 0) {
|
||||
ServiceControl(SERVICE_CONTROL_STOP);
|
||||
} else if (_tcsicmp(L"-p", argv[1]) == 0) {
|
||||
ServiceControl(SERVICE_CONTROL_PAUSE);
|
||||
} else if (_tcsicmp(L"-c", argv[1]) == 0) {
|
||||
ServiceControl(SERVICE_CONTROL_CONTINUE);
|
||||
} else if (_tcsicmp(L"status", argv[1]) == 0) {
|
||||
SC_HANDLE scm, service;
|
||||
scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
|
||||
|
||||
+14
-17
@@ -6,6 +6,7 @@ CMemStat::CMemStat()
|
||||
initialized = FALSE;
|
||||
locator = NULL;
|
||||
service = NULL;
|
||||
memset(m_Stats, -1, sizeof(m_Stats));
|
||||
}
|
||||
|
||||
CMemStat::~CMemStat()
|
||||
@@ -90,7 +91,7 @@ BOOL CMemStat::Init()
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CMemStat::GetStatus(PBALLOON_STAT pStat)
|
||||
BOOL CMemStat::Update()
|
||||
{
|
||||
MEMORYSTATUSEX statex = {sizeof(statex)};
|
||||
CComPtr< IEnumWbemClassObject > enumerator;
|
||||
@@ -99,10 +100,6 @@ BOOL CMemStat::GetStatus(PBALLOON_STAT pStat)
|
||||
_variant_t var_val;
|
||||
HRESULT status = S_OK;
|
||||
UINT idx = 0;
|
||||
if(!pStat) {
|
||||
PrintMessage("Invalid pointer");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = service->ExecQuery(
|
||||
L"WQL",
|
||||
@@ -141,8 +138,8 @@ BOOL CMemStat::GetStatus(PBALLOON_STAT pStat)
|
||||
PrintMessage("Cannot get PagesInputPerSec");
|
||||
var_val.vt = -1;
|
||||
}
|
||||
pStat[idx].tag = VIRTIO_BALLOON_S_SWAP_IN;
|
||||
pStat[idx].val = (long)var_val;
|
||||
m_Stats[idx].tag = VIRTIO_BALLOON_S_SWAP_IN;
|
||||
m_Stats[idx].val = (long)var_val;
|
||||
idx++;
|
||||
|
||||
status = memory->Get(
|
||||
@@ -157,8 +154,8 @@ BOOL CMemStat::GetStatus(PBALLOON_STAT pStat)
|
||||
PrintMessage("Cannot get PagesOutputPerSec");
|
||||
var_val.vt = -1;
|
||||
}
|
||||
pStat[idx].tag = VIRTIO_BALLOON_S_SWAP_OUT;
|
||||
pStat[idx].val = (long)var_val;
|
||||
m_Stats[idx].tag = VIRTIO_BALLOON_S_SWAP_OUT;
|
||||
m_Stats[idx].val = (long)var_val;
|
||||
idx++;
|
||||
|
||||
status = memory->Get(
|
||||
@@ -173,8 +170,8 @@ BOOL CMemStat::GetStatus(PBALLOON_STAT pStat)
|
||||
PrintMessage("Cannot get PageReadsPerSec");
|
||||
var_val.vt = -1;
|
||||
}
|
||||
pStat[idx].tag = VIRTIO_BALLOON_S_MAJFLT;
|
||||
pStat[idx].val = (long)var_val;
|
||||
m_Stats[idx].tag = VIRTIO_BALLOON_S_MAJFLT;
|
||||
m_Stats[idx].val = (long)var_val;
|
||||
idx++;
|
||||
|
||||
status = memory->Get(
|
||||
@@ -189,18 +186,18 @@ BOOL CMemStat::GetStatus(PBALLOON_STAT pStat)
|
||||
PrintMessage("Cannot get PageFaultsPerSec");
|
||||
var_val.vt = -1;
|
||||
}
|
||||
pStat[idx].tag = VIRTIO_BALLOON_S_MINFLT;
|
||||
pStat[idx].val = (long)var_val;
|
||||
m_Stats[idx].tag = VIRTIO_BALLOON_S_MINFLT;
|
||||
m_Stats[idx].val = (long)var_val;
|
||||
idx++;
|
||||
|
||||
GlobalMemoryStatusEx(&statex);
|
||||
|
||||
pStat[idx].tag = VIRTIO_BALLOON_S_MEMFREE;
|
||||
pStat[idx].val = statex.ullAvailPhys;
|
||||
m_Stats[idx].tag = VIRTIO_BALLOON_S_MEMFREE;
|
||||
m_Stats[idx].val = statex.ullAvailPhys;
|
||||
idx++;
|
||||
|
||||
pStat[idx].tag = VIRTIO_BALLOON_S_MEMTOT;
|
||||
pStat[idx].val = statex.ullTotalPhys;
|
||||
m_Stats[idx].tag = VIRTIO_BALLOON_S_MEMTOT;
|
||||
m_Stats[idx].val = statex.ullTotalPhys;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
+11
-1
@@ -12,11 +12,21 @@ public:
|
||||
CMemStat();
|
||||
~CMemStat();
|
||||
BOOL Init();
|
||||
BOOL GetStatus(PBALLOON_STAT pstat);
|
||||
BOOL Update();
|
||||
|
||||
PVOID GetBuffer() {
|
||||
return m_Stats;
|
||||
}
|
||||
|
||||
size_t GetSize() {
|
||||
return sizeof(m_Stats);
|
||||
}
|
||||
|
||||
private:
|
||||
BOOL initialized;
|
||||
CComPtr< IWbemLocator > locator;
|
||||
CComPtr< IWbemServices > service;
|
||||
BALLOON_STAT m_Stats[VIRTIO_BALLOON_S_NR];
|
||||
};
|
||||
|
||||
#endif
|
||||
+49
-168
@@ -1,15 +1,16 @@
|
||||
#define INITGUID
|
||||
|
||||
#include "service.h"
|
||||
#include "utils.h"
|
||||
#include "device.h"
|
||||
#include "public.h"
|
||||
|
||||
CService::CService()
|
||||
{
|
||||
m_hDevNotify = NULL;
|
||||
m_evTerminate = NULL;
|
||||
m_evWakeUp = NULL;
|
||||
m_thHandle = NULL;
|
||||
m_bPauseService = FALSE;
|
||||
m_bRunningService = FALSE;
|
||||
m_StatusHandle = NULL;
|
||||
m_pMemStat = NULL;
|
||||
m_pDev = NULL;
|
||||
m_Status = SERVICE_STOPPED;
|
||||
}
|
||||
@@ -17,21 +18,12 @@ CService::CService()
|
||||
CService::~CService()
|
||||
{
|
||||
m_evTerminate = NULL;
|
||||
m_evWakeUp = NULL;
|
||||
m_thHandle = NULL;
|
||||
m_bPauseService = FALSE;
|
||||
m_bRunningService = FALSE;
|
||||
m_StatusHandle = NULL;
|
||||
m_pMemStat = NULL;
|
||||
m_pDev = NULL;
|
||||
m_Status = SERVICE_STOPPED;
|
||||
}
|
||||
|
||||
void __stdcall CService::HandlerThunk(CService* service, DWORD ctlcode)
|
||||
{
|
||||
service->ServiceCtrlHandler(ctlcode);
|
||||
}
|
||||
|
||||
DWORD __stdcall CService::HandlerExThunk(CService* service, DWORD ctlcode, DWORD evtype, PVOID evdata)
|
||||
{
|
||||
switch (ctlcode) {
|
||||
@@ -56,54 +48,11 @@ void __stdcall CService::ServiceMainThunk(CService* service, DWORD argc, TCHAR*
|
||||
|
||||
BOOL CService::InitService()
|
||||
{
|
||||
DWORD id;
|
||||
|
||||
m_thHandle = CreateThread(
|
||||
NULL,
|
||||
0,
|
||||
(LPTHREAD_START_ROUTINE) ServiceThread,
|
||||
(LPVOID)this,
|
||||
0,
|
||||
&id
|
||||
);
|
||||
|
||||
if (m_thHandle == NULL) {
|
||||
PrintMessage("Cannot create thread");
|
||||
return FALSE;
|
||||
}
|
||||
m_bRunningService = TRUE;
|
||||
m_Status = SERVICE_RUNNING;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD WINAPI CService::ServiceThread(LPDWORD lParam)
|
||||
{
|
||||
CService* service = (CService*)lParam;
|
||||
service->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CService::Run()
|
||||
{
|
||||
BALLOON_STAT stat[VIRTIO_BALLOON_S_NR];
|
||||
DWORD mSec;
|
||||
while (1) {
|
||||
mSec = 2000;
|
||||
memset(stat, -1, sizeof(BALLOON_STAT) * VIRTIO_BALLOON_S_NR);
|
||||
if (m_pMemStat->GetStatus(stat)) {
|
||||
EnterCriticalSection(&m_scWrite);
|
||||
if (m_pDev->Write(stat, VIRTIO_BALLOON_S_NR)) {
|
||||
mSec = 1000;
|
||||
}
|
||||
LeaveCriticalSection(&m_scWrite);
|
||||
}
|
||||
if (WaitForSingleObject(m_evWakeUp, mSec) == WAIT_OBJECT_0) {
|
||||
ResetEvent(m_evWakeUp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL CService::SendStatusToSCM(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
|
||||
{
|
||||
BOOL res;
|
||||
@@ -117,7 +66,6 @@ BOOL CService::SendStatusToSCM(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWOR
|
||||
} else {
|
||||
serviceStatus.dwControlsAccepted =
|
||||
SERVICE_ACCEPT_STOP |
|
||||
SERVICE_ACCEPT_PAUSE_CONTINUE |
|
||||
SERVICE_ACCEPT_SHUTDOWN;
|
||||
}
|
||||
|
||||
@@ -139,39 +87,11 @@ BOOL CService::SendStatusToSCM(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWOR
|
||||
return res;
|
||||
}
|
||||
|
||||
void CService::ResumeService()
|
||||
{
|
||||
m_bPauseService = FALSE;
|
||||
ResumeThread(m_thHandle);
|
||||
m_Status = SERVICE_RUNNING;
|
||||
}
|
||||
|
||||
void CService::PauseService()
|
||||
{
|
||||
BALLOON_STAT stat[VIRTIO_BALLOON_S_NR];
|
||||
if (m_bRunningService && !m_bPauseService && m_pDev) {
|
||||
memset(stat, -1, sizeof(BALLOON_STAT) * VIRTIO_BALLOON_S_NR);
|
||||
EnterCriticalSection(&m_scWrite);
|
||||
m_pDev->Write(stat, VIRTIO_BALLOON_S_NR);
|
||||
m_bPauseService = TRUE;
|
||||
SuspendThread(m_thHandle);
|
||||
LeaveCriticalSection(&m_scWrite);
|
||||
m_Status = SERVICE_PAUSED;
|
||||
}
|
||||
}
|
||||
|
||||
void CService::StopService()
|
||||
{
|
||||
if (m_bRunningService && m_pDev) {
|
||||
if (m_evWakeUp) {
|
||||
SetEvent(m_evWakeUp);
|
||||
if (WaitForSingleObject(m_thHandle, 1000) == WAIT_TIMEOUT) {
|
||||
TerminateThread(m_thHandle, 0);
|
||||
}
|
||||
}
|
||||
EnterCriticalSection(&m_scWrite);
|
||||
m_pDev->Stop();
|
||||
m_bRunningService = FALSE;
|
||||
LeaveCriticalSection(&m_scWrite);
|
||||
m_Status = SERVICE_STOPPED;
|
||||
}
|
||||
SetEvent(m_evTerminate);
|
||||
@@ -179,29 +99,23 @@ void CService::StopService()
|
||||
|
||||
void CService::terminate(DWORD error)
|
||||
{
|
||||
if (m_hDevNotify) {
|
||||
UnregisterDeviceNotification(m_hDevNotify);
|
||||
m_hDevNotify = NULL;
|
||||
}
|
||||
|
||||
if (m_evTerminate) {
|
||||
CloseHandle(m_evTerminate);
|
||||
m_evTerminate = NULL;
|
||||
}
|
||||
|
||||
if (m_evWakeUp) {
|
||||
CloseHandle(m_evWakeUp);
|
||||
}
|
||||
|
||||
DeleteCriticalSection(&m_scWrite);
|
||||
|
||||
if (m_StatusHandle) {
|
||||
SendStatusToSCM(SERVICE_STOPPED, error, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (m_thHandle) {
|
||||
CloseHandle(m_thHandle);
|
||||
}
|
||||
|
||||
delete m_pMemStat;
|
||||
delete m_pDev;
|
||||
}
|
||||
|
||||
|
||||
void CService::ServiceCtrlHandler(DWORD controlCode)
|
||||
{
|
||||
switch(controlCode)
|
||||
@@ -218,35 +132,6 @@ void CService::ServiceCtrlHandler(DWORD controlCode)
|
||||
StopService();
|
||||
return;
|
||||
|
||||
case SERVICE_CONTROL_PAUSE:
|
||||
if (m_bRunningService && !m_bPauseService) {
|
||||
m_Status = SERVICE_PAUSE_PENDING;
|
||||
SendStatusToSCM(
|
||||
m_Status,
|
||||
NO_ERROR,
|
||||
0,
|
||||
1,
|
||||
1000
|
||||
);
|
||||
|
||||
PauseService();
|
||||
}
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_CONTINUE:
|
||||
if (m_bRunningService && m_bPauseService) {
|
||||
m_Status = SERVICE_CONTINUE_PENDING;
|
||||
SendStatusToSCM(
|
||||
m_Status,
|
||||
NO_ERROR,
|
||||
0,
|
||||
1,
|
||||
1000
|
||||
);
|
||||
ResumeService();
|
||||
}
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
break;
|
||||
|
||||
@@ -261,7 +146,22 @@ void CService::ServiceCtrlHandler(DWORD controlCode)
|
||||
|
||||
DWORD CService::ServiceHandleDeviceChange(DWORD evtype, _DEV_BROADCAST_HEADER* dbhdr)
|
||||
{
|
||||
PrintMessage("ServiceHandleDeviceChange");
|
||||
switch (evtype)
|
||||
{
|
||||
case DBT_DEVICEARRIVAL:
|
||||
case DBT_DEVICEQUERYREMOVEFAILED:
|
||||
m_pDev->Start();
|
||||
break;
|
||||
|
||||
case DBT_DEVICEQUERYREMOVE:
|
||||
case DBT_DEVICEREMOVECOMPLETE:
|
||||
m_pDev->Stop();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -280,50 +180,39 @@ void CService::ServiceMain(DWORD argc, LPTSTR *argv)
|
||||
return;
|
||||
}
|
||||
|
||||
m_pMemStat = new CMemStat;
|
||||
if (!m_pMemStat || !m_pMemStat->Init()) {
|
||||
terminate(GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
m_pDev = new CDevice;
|
||||
if (!m_pDev || !m_pDev->Init()) {
|
||||
terminate(GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
res = SendStatusToSCM(SERVICE_START_PENDING, NO_ERROR, 0 , 1, 5000);
|
||||
if (!res) {
|
||||
terminate(GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
m_pDev = new CDevice();
|
||||
if (!m_pDev || !m_pDev->Init(m_StatusHandle) || !m_pDev->Start()) {
|
||||
terminate(GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
DEV_BROADCAST_DEVICEINTERFACE filter;
|
||||
|
||||
ZeroMemory(&filter, sizeof(filter));
|
||||
filter.dbcc_size = sizeof(filter);
|
||||
filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||
filter.dbcc_classguid = GUID_DEVINTERFACE_BALLOON;
|
||||
|
||||
m_hDevNotify = RegisterDeviceNotification(m_StatusHandle, &filter,
|
||||
DEVICE_NOTIFY_SERVICE_HANDLE);
|
||||
|
||||
if (!m_hDevNotify) {
|
||||
terminate(GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
m_evTerminate = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!m_evTerminate) {
|
||||
terminate(GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
m_evWakeUp = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
if (!m_evWakeUp) {
|
||||
terminate(GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
InitializeCriticalSection(&m_scWrite);
|
||||
|
||||
res = SendStatusToSCM(SERVICE_START_PENDING, NO_ERROR, 0 , 2, 1000);
|
||||
if (!res) {
|
||||
terminate(GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
res = SendStatusToSCM(SERVICE_START_PENDING, NO_ERROR, 0 , 3, 5000);
|
||||
if (!res) {
|
||||
terminate(GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
res = InitService();
|
||||
if (!res) {
|
||||
terminate(GetLastError());
|
||||
@@ -357,18 +246,10 @@ void CService::GetStatus(SC_HANDLE service)
|
||||
CurrentState = SERVICE_STOPPED;
|
||||
printf("Service STOPPED.\n");
|
||||
break;
|
||||
case SERVICE_PAUSED:
|
||||
CurrentState = SERVICE_PAUSED;
|
||||
printf("Service PAUSED.\n");
|
||||
break;
|
||||
case SERVICE_CONTINUE_PENDING:
|
||||
CurrentState = SERVICE_CONTINUE_PENDING;
|
||||
printf("Service is resuming...\n");
|
||||
break;
|
||||
case SERVICE_PAUSE_PENDING:
|
||||
CurrentState = SERVICE_PAUSE_PENDING;
|
||||
printf("Service is pausing...\n");
|
||||
break;
|
||||
case SERVICE_START_PENDING:
|
||||
CurrentState = SERVICE_START_PENDING;
|
||||
printf("Service is starting...\n");
|
||||
|
||||
+2
-13
@@ -4,9 +4,7 @@
|
||||
#include <windows.h>
|
||||
#include <dbt.h>
|
||||
|
||||
#include "memstat.h"
|
||||
#include "device.h"
|
||||
|
||||
class CDevice;
|
||||
|
||||
class CService
|
||||
{
|
||||
@@ -15,17 +13,12 @@ public:
|
||||
~CService();
|
||||
BOOL InitService();
|
||||
void GetStatus(SC_HANDLE service);
|
||||
static void __stdcall HandlerThunk(CService* service, DWORD ctlcode);
|
||||
static DWORD __stdcall HandlerExThunk(CService* service, DWORD ctlcode, DWORD evtype, PVOID evdata);
|
||||
static void __stdcall ServiceMainThunk(CService* service, DWORD argc, TCHAR* argv[]);
|
||||
SERVICE_STATUS_HANDLE m_StatusHandle;
|
||||
|
||||
private:
|
||||
static DWORD WINAPI ServiceThread( LPDWORD lParam);
|
||||
void Run();
|
||||
BOOL SendStatusToSCM(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint);
|
||||
void ResumeService();
|
||||
void PauseService();
|
||||
void StopService();
|
||||
void terminate(DWORD error);
|
||||
void ServiceCtrlHandler(DWORD controlCode);
|
||||
@@ -33,14 +26,10 @@ private:
|
||||
DWORD ServiceHandleDeviceChange(DWORD evtype, _DEV_BROADCAST_HEADER* dbhdr);
|
||||
DWORD ServiceHandlePowerEvent(DWORD evtype, DWORD flags);
|
||||
|
||||
HDEVNOTIFY m_hDevNotify;
|
||||
HANDLE m_evTerminate;
|
||||
HANDLE m_evWakeUp;
|
||||
HANDLE m_thHandle;
|
||||
BOOL m_bPauseService;
|
||||
BOOL m_bRunningService;
|
||||
DWORD m_Status;
|
||||
CRITICAL_SECTION m_scWrite;
|
||||
CMemStat* m_pMemStat;
|
||||
CDevice* m_pDev;
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
#include "strsafe.h"
|
||||
|
||||
extern LPWSTR ServiceName;
|
||||
extern LPWSTR DisplayName;
|
||||
|
||||
extern CService srvc;
|
||||
|
||||
static struct ErrEntry {
|
||||
@@ -69,8 +71,6 @@ void ShowUsage()
|
||||
printf("blnsvr -u\tUninstall service\n");
|
||||
printf("blnsvr -r\tRun service\n");
|
||||
printf("blnsvr -s\tStop service\n");
|
||||
printf("blnsvr -p\tPause service\n");
|
||||
printf("blnsvr -c\tResume service\n");
|
||||
printf("blnsvr status\tCurrent status\n");
|
||||
printf("\n");
|
||||
}
|
||||
@@ -100,7 +100,7 @@ BOOL InstallService()
|
||||
newService = CreateService(
|
||||
scm,
|
||||
ServiceName,
|
||||
ServiceName,
|
||||
DisplayName,
|
||||
SERVICE_ALL_ACCESS,
|
||||
SERVICE_WIN32_OWN_PROCESS,
|
||||
SERVICE_AUTO_START,
|
||||
@@ -263,12 +263,6 @@ BOOL ServiceControl(int ctrl)
|
||||
if (ctrl == SERVICE_CONTROL_STOP) {
|
||||
printf("Service is stopping...\n");
|
||||
res = ControlService(service, SERVICE_CONTROL_STOP, &status);
|
||||
} else if (ctrl == SERVICE_CONTROL_PAUSE) {
|
||||
printf("Service is pausing...\n");
|
||||
res = ControlService(service, SERVICE_CONTROL_PAUSE, &status);
|
||||
} else if (ctrl == SERVICE_CONTROL_CONTINUE) {
|
||||
printf("Service is resuming...\n");
|
||||
res = ControlService(service, SERVICE_CONTROL_CONTINUE, &status);
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
|
||||
Reference in new issue
Block a user