📄 svcproc.cxx
字号:
strncpy(szTip, tip, sizeof(szTip)-1);
szTip[sizeof(szTip)-1] = '\0';
uFlags |= NIF_TIP;
}
}
enum TrayIconRegistryCommand {
AddTrayIcon,
DelTrayIcon,
CheckTrayIcon
};
static BOOL TrayIconRegistry(PServiceProcess * svc, TrayIconRegistryCommand cmd)
{
HKEY key;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
0, KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
return FALSE;
DWORD err = 1;
DWORD type;
DWORD len;
PString str;
switch (cmd) {
case CheckTrayIcon :
err = RegQueryValueEx(key, svc->GetName(), 0, &type, NULL, &len);
break;
case AddTrayIcon :
str = "\"" + svc->GetFile() + "\" Tray";
err = RegSetValueEx(key, svc->GetName(), 0, REG_SZ,
(LPBYTE)(const char *)str, str.GetLength() + 1);
break;
case DelTrayIcon :
err = RegDeleteValue(key, (char *)(const char *)svc->GetName());
}
RegCloseKey(key);
return err == ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
// PSystemLog
void PSystemLog::Output(Level level, const char * msg)
{
PServiceProcess & process = PServiceProcess::Current();
if (level > process.GetLogLevel())
return;
DWORD err = ::GetLastError();
if (process.isWin95 || process.controlWindow != NULL) {
static HANDLE mutex = CreateMutex(NULL, FALSE, NULL);
WaitForSingleObject(mutex, INFINITE);
ostream * out;
if (!process.systemLogFileName)
out = new ofstream(process.systemLogFileName, ios::app);
else
out = new PStringStream;
PTime now;
*out << now.AsString("yyyy/MM/dd hh:mm:ss.uuu\t");
PThread * thread = PThread::Current();
if (thread == NULL)
*out << "ThreadID=0x"
<< setfill('0') << hex
<< setw(8) << GetCurrentThreadId()
<< setfill(' ') << dec;
else {
PString threadName = thread->GetThreadName();
if (threadName.GetLength() <= 23)
*out << setw(23) << threadName;
else
*out << threadName.Left(10) << "..." << threadName.Right(10);
}
*out << '\t';
if (level < 0)
*out << "Message";
else {
static const char * const levelName[4] = {
"Fatal error",
"Error",
"Warning",
"Info"
};
if (level < PARRAYSIZE(levelName))
*out << levelName[level];
else
*out << "Debug" << (level-Info);
}
*out << '\t' << msg;
if (level < Info && err != 0)
*out << " - error = " << err << endl;
else if (msg[0] == '\0' || msg[strlen(msg)-1] != '\n')
*out << endl;
if (process.systemLogFileName.IsEmpty())
process.DebugOutput(*(PStringStream*)out);
delete out;
ReleaseMutex(mutex);
SetLastError(0);
}
else {
// Use event logging to log the error.
HANDLE hEventSource = RegisterEventSource(NULL, process.GetName());
if (hEventSource == NULL)
return;
PString threadName;
PThread * thread = PThread::Current();
if (thread != NULL)
threadName = thread->GetThreadName();
else
threadName.sprintf("%u", GetCurrentThreadId());
char thrdbuf[16];
if (threadName.IsEmpty())
sprintf(thrdbuf, "0x%08X", thread);
else {
strncpy(thrdbuf, threadName, sizeof(thrdbuf)-1);
thrdbuf[sizeof(thrdbuf)-1] = '\0';
}
char errbuf[25];
if (level > StdError && level < Info && err != 0)
::sprintf(errbuf, "Error code = %d", err);
else
errbuf[0] = '\0';
LPCTSTR strings[4];
strings[0] = thrdbuf;
strings[1] = msg;
strings[2] = errbuf;
strings[3] = level != Fatal ? "" : " Program aborted.";
static const WORD levelType[Info+1] = {
EVENTLOG_INFORMATION_TYPE,
EVENTLOG_ERROR_TYPE,
EVENTLOG_ERROR_TYPE,
EVENTLOG_WARNING_TYPE
};
ReportEvent(hEventSource, // handle of event source
(WORD)(level < Info ? levelType[level+1]
: EVENTLOG_INFORMATION_TYPE), // event type
(WORD)(level+1), // event category
0x1000, // event ID
NULL, // current user's SID
PARRAYSIZE(strings), // number of strings
0, // no bytes of raw data
strings, // array of error strings
NULL); // no raw data
DeregisterEventSource(hEventSource);
}
}
#ifndef _DEBUG
#undef PMEMORY_CHECK
#endif
int PSystemLog::Buffer::overflow(int c)
{
if (pptr() >= epptr()) {
#if PMEMORY_CHECK
BOOL previousIgnoreAllocations = PMemoryHeap::SetIgnoreAllocations(TRUE);
#endif
int ppos = pptr() - pbase();
char * newptr = string.GetPointer(string.GetSize() + 10);
setp(newptr, newptr + string.GetSize() - 1);
pbump(ppos);
#if PMEMORY_CHECK
PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations);
#endif
}
if (c != EOF) {
*pptr() = (char)c;
pbump(1);
}
return 0;
}
int PSystemLog::Buffer::underflow()
{
return EOF;
}
int PSystemLog::Buffer::sync()
{
Level logLevel;
if (log->width() == 0 || (PTrace::GetOptions()&PTrace::SystemLogStream) == 0)
logLevel = log->logLevel;
else {
// Trace system sets the ios stream width as the last thing it does before
// doing a flush, which gets us here. SO now we can get a PTRACE looking
// exactly like a PSYSTEMLOG of appropriate level.
unsigned traceLevel = log->width() -1 + PSystemLog::Warning;
log->width(0);
if (traceLevel >= PSystemLog::NumLogLevels)
traceLevel = PSystemLog::NumLogLevels-1;
logLevel = (Level)traceLevel;
}
PSystemLog::Output(logLevel, string);
#if PMEMORY_CHECK
BOOL previousIgnoreAllocations = PMemoryHeap::SetIgnoreAllocations(TRUE);
#endif
string.SetSize(10);
char * base = string.GetPointer();
*base = '\0';
setp(base, base + string.GetSize() - 1);
#if PMEMORY_CHECK
PMemoryHeap::SetIgnoreAllocations(previousIgnoreAllocations);
#endif
return 0;
}
///////////////////////////////////////////////////////////////////////////////
// PServiceProcess
PServiceProcess::PServiceProcess(const char * manuf, const char * name,
WORD major, WORD minor, CodeStatus stat, WORD build)
: PProcess(manuf, name, major, minor, stat, build),
systemLogFileName(GetFile().GetDirectory() + GetName() + " Log.TXT")
{
controlWindow = debugWindow = NULL;
currentLogLevel = PSystemLog::Warning;
}
PServiceProcess & PServiceProcess::Current()
{
PServiceProcess & process = (PServiceProcess &)PProcess::Current();
PAssert(PIsDescendant(&process, PServiceProcess), "Not a service!");
return process;
}
const char * PServiceProcess::GetServiceDependencies() const
{
return "EventLog\0";
}
BOOL PServiceProcess::IsServiceProcess() const
{
return TRUE;
}
static BOOL IsServiceRunning(PServiceProcess * svc)
{
HANDLE hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, svc->GetName());
if (hEvent == NULL)
return ::GetLastError() == ERROR_ACCESS_DENIED;
CloseHandle(hEvent);
return TRUE;
}
#include <shellapi.h>
typedef int pid_t;
static int KillProcess(pid_t pid)
{
HANDLE hProc;
hProc=OpenProcess( PROCESS_TERMINATE|PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE,pid );
if(hProc)
{
if(TerminateProcess(hProc,0))
{
// process terminated
CloseHandle(hProc);
return 0;
}
CloseHandle(hProc);
}
return -1;
}
static BOOL IsProcessRunning( int pid )
{
HANDLE hProc;
hProc=OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE,pid );
if(hProc)
{
CloseHandle(hProc);
return TRUE;
}
return FALSE;
}
int PServiceProcess::_main(void * arg)
{
#if PMEMORY_CHECK
PMemoryHeap::SetIgnoreAllocations(TRUE);
#endif
PSetErrorStream(new PSystemLog(PSystemLog::StdError));
PTrace::SetStream(new PSystemLog(PSystemLog::Debug3));
PTrace::ClearOptions(PTrace::FileAndLine);
PTrace::SetOptions(PTrace::SystemLogStream);
PTrace::SetLevel(4);
#if PMEMORY_CHECK
PMemoryHeap::SetIgnoreAllocations(FALSE);
#endif
hInstance = (HINSTANCE)arg;
OSVERSIONINFO verinfo;
verinfo.dwOSVersionInfoSize = sizeof(verinfo);
GetVersionEx(&verinfo);
switch (verinfo.dwPlatformId) {
case VER_PLATFORM_WIN32_NT :
isWin95 = FALSE;
break;
case VER_PLATFORM_WIN32_WINDOWS :
isWin95 = TRUE;
break;
default :
PError << "Unsupported Win32 platform type!" << endl;
return 1;
}
if( (arguments.GetCount() > 0 && arguments[0].Find( '-' ) != P_MAX_INDEX) || arguments[0].IsEmpty() )
{
arguments.Parse("v-version."
"d-daemon."
"c-console."
"h-help."
"x-execute."
"p-pid-file:"
"H-handlemax:"
"i-ini-file:"
"k-kill."
"t-terminate."
"s-status."
"l-log-file:"
"u-uid:"
"g-gid:"
"C-core-size:"
"D-debug."
"P-http-port:"
"X-misc-param-1:"
"Y-misc-param-2:"
"Z-misc-param-3:");
}
if( arguments.HasOption( 'D' ) || arguments.HasOption( 'd' ) )
{
if( arguments.HasOption( 'p' ) )
{
PString argPID = arguments.GetOptionString( 'p' );
if( arguments.HasOption( 'k' ) )
{
/// kill the intance and exit
PTextFile pidFile( argPID );
PString str;
pidFile.ReadLine( str );
int pid = str.AsInteger();
KillProcess( pid );
return GetTerminationValue();
}else
{
if( argPID.IsEmpty() )
return GetTerminationValue();
{
PTextFile pidFile( argPID );
PString str;
pidFile.ReadLine( str );
int pid = str.AsInteger();
/// process is still running
if( IsProcessRunning( pid ) )
{
MessageBox(NULL, "Already have another daemon running!", GetName(), MB_TASKMODAL);
return GetTerminationValue();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -