📄 svcproc.cxx
字号:
*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); }}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;}///////////////////////////////////////////////////////////////////////////////// PServiceProcessPServiceProcess::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;}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; } debugMode = arguments.GetCount() > 0 && stricmp(arguments[0], "Debug") == 0; currentLogLevel = debugMode ? PSystemLog::Info : PSystemLog::Warning; if (!debugMode && arguments.GetCount() > 0) { for (PINDEX a = 0; a < arguments.GetCount(); a++) ProcessCommand(arguments[a]); if (controlWindow == NULL || controlWindow == (HWND)-1) return GetTerminationValue(); if (debugWindow != NULL && debugWindow != (HWND)-1) { ::SetLastError(0); PError << "Close window or select another command from the Control menu.\n" << endl; } MSG msg; while (GetMessage(&msg, NULL, 0, 0) != 0) { TranslateMessage(&msg); DispatchMessage(&msg); } return GetTerminationValue(); } if (!debugMode && !isWin95) { static SERVICE_TABLE_ENTRY dispatchTable[] = { { "", PServiceProcess::StaticMainEntry }, { NULL, NULL } }; dispatchTable[0].lpServiceName = (char *)(const char *)GetName(); if (StartServiceCtrlDispatcher(dispatchTable)) return GetTerminationValue(); PSystemLog::Output(PSystemLog::Fatal, "StartServiceCtrlDispatcher failed."); MessageBox(NULL, "Not run as a service!", GetName(), MB_TASKMODAL); return 1; } if (!CreateControlWindow(debugMode)) return 1; if (IsServiceRunning(this)) { MessageBox(NULL, "Service already running", GetName(), MB_TASKMODAL); return 3; } if (debugMode) { ::SetLastError(0); PError << "Service simulation started for \"" << GetName() << "\" version " << GetVersion(TRUE) << "\n" "Close window to terminate.\n" << endl; } terminationEvent = CreateEvent(NULL, TRUE, FALSE, GetName()); PAssertOS(terminationEvent != NULL); threadHandle = (HANDLE)_beginthread(StaticThreadEntry, 0, this); PAssertOS(threadHandle != (HANDLE)-1); SetTerminationValue(0); MSG msg; msg.message = WM_QUIT+1; //Want somethingthat is not WM_QUIT do { switch (MsgWaitForMultipleObjects(1, &terminationEvent, FALSE, INFINITE, QS_ALLINPUT)) { case WAIT_OBJECT_0+1 : while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message != WM_QUIT) { TranslateMessage(&msg); DispatchMessage(&msg); } } break; default : // This is a work around for '95 coming up with an erroneous error if (::GetLastError() == ERROR_INVALID_HANDLE && WaitForSingleObject(terminationEvent, 0) == WAIT_TIMEOUT) break; // Else fall into next case case WAIT_OBJECT_0 : if (!debugMode || controlWindow == NULL) msg.message = WM_QUIT; else { PError << "nService simulation stopped for \"" << GetName() << "\".\n\n" "Close window to terminate.\n" << endl; ResetEvent(terminationEvent); } } } while (msg.message != WM_QUIT); if (controlWindow != NULL) DestroyWindow(controlWindow); // Set thread ID for process to this thread activeThreadMutex.Wait(); activeThreads.SetAt(threadId, NULL); threadId = GetCurrentThreadId(); threadHandle = GetCurrentThread(); activeThreads.SetAt(threadId, this); activeThreadMutex.Signal(); OnStop(); return GetTerminationValue();}enum { ExitMenuID = 100, HideMenuID, ControlMenuID, CopyMenuID, CutMenuID, DeleteMenuID, SelectAllMenuID,#if PMEMORY_CHECK MarkMenuID, DumpMenuID, StatsMenuID, ValidateMenuID,#endif OutputToMenuID, WindowOutputMenuID, SvcCmdBaseMenuID = 1000, LogLevelBaseMenuID = 2000};static const char ServiceSimulationSectionName[] = "Service Simulation Parameters";static const char WindowLeftKey[] = "Window Left";static const char WindowTopKey[] = "Window Top";static const char WindowRightKey[] = "Window Right";static const char WindowBottomKey[] = "Window Bottom";static const char SystemLogFileNameKey[] = "System Log File Name";BOOL PServiceProcess::CreateControlWindow(BOOL createDebugWindow){ if (controlWindow != NULL) return TRUE; WNDCLASS wclass; wclass.style = CS_HREDRAW|CS_VREDRAW; wclass.lpfnWndProc = (WNDPROC)StaticWndProc; wclass.cbClsExtra = 0; wclass.cbWndExtra = 0; wclass.hInstance = hInstance; wclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(ICON_RESID)); wclass.hCursor = NULL; wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wclass.lpszMenuName = NULL; wclass.lpszClassName = GetName(); if (RegisterClass(&wclass) == 0) return FALSE; HMENU menubar = CreateMenu(); HMENU menu = CreatePopupMenu(); AppendMenu(menu, MF_STRING, OutputToMenuID, "&Output To..."); AppendMenu(menu, MF_STRING, WindowOutputMenuID, "&Output To Window"); AppendMenu(menu, MF_SEPARATOR, 0, NULL); AppendMenu(menu, MF_STRING, ControlMenuID, "&Control"); AppendMenu(menu, MF_STRING, HideMenuID, "&Hide"); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdVersion, "&Version"); AppendMenu(menu, MF_SEPARATOR, 0, NULL);#if PMEMORY_CHECK AppendMenu(menu, MF_STRING, MarkMenuID, "&Mark Memory"); AppendMenu(menu, MF_STRING, DumpMenuID, "&Dump Memory"); AppendMenu(menu, MF_STRING, StatsMenuID, "&Statistics"); AppendMenu(menu, MF_STRING, ValidateMenuID, "&Validate Heap"); AppendMenu(menu, MF_SEPARATOR, 0, NULL);#endif AppendMenu(menu, MF_STRING, ExitMenuID, "E&xit"); AppendMenu(menubar, MF_POPUP, (UINT)menu, "&File"); menu = CreatePopupMenu(); AppendMenu(menu, MF_STRING, CopyMenuID, "&Copy"); AppendMenu(menu, MF_STRING, CutMenuID, "C&ut"); AppendMenu(menu, MF_STRING, DeleteMenuID, "&Delete"); AppendMenu(menu, MF_SEPARATOR, 0, NULL); AppendMenu(menu, MF_STRING, SelectAllMenuID, "&Select All"); AppendMenu(menubar, MF_POPUP, (UINT)menu, "&Edit"); menu = CreatePopupMenu(); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdInstall, "&Install"); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdRemove, "&Remove"); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdDeinstall, "&Deinstall"); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdStart, "&Start"); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdStop, "S&top"); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdPause, "&Pause"); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdResume, "R&esume"); AppendMenu(menubar, MF_POPUP, (UINT)menu, "&Control"); menu = CreatePopupMenu(); AppendMenu(menu, MF_STRING, LogLevelBaseMenuID+PSystemLog::Fatal, "&Fatal Error"); AppendMenu(menu, MF_STRING, LogLevelBaseMenuID+PSystemLog::Error, "&Error"); AppendMenu(menu, MF_STRING, LogLevelBaseMenuID+PSystemLog::Warning, "&Warning"); AppendMenu(menu, MF_STRING, LogLevelBaseMenuID+PSystemLog::Info, "&Information"); AppendMenu(menu, MF_STRING, LogLevelBaseMenuID+PSystemLog::Debug, "&Debug"); AppendMenu(menu, MF_STRING, LogLevelBaseMenuID+PSystemLog::Debug2, "Debug &2"); AppendMenu(menu, MF_STRING, LogLevelBaseMenuID+PSystemLog::Debug3, "Debug &3"); AppendMenu(menubar, MF_POPUP, (UINT)menu, "&Log Level"); if (CreateWindow(GetName(), GetName(), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, menubar, hInstance, NULL) == NULL) return FALSE; if (createDebugWindow && debugWindow == NULL) { PConfig cfg(ServiceSimulationSectionName); int l = cfg.GetInteger(WindowLeftKey, -1); int t = cfg.GetInteger(WindowTopKey, -1); int r = cfg.GetInteger(WindowRightKey, -1); int b = cfg.GetInteger(WindowBottomKey, -1); if (l > 0 && t > 0 && r > 0 && b > 0) SetWindowPos(controlWindow, NULL, l, t, r-l, b-t, 0); debugWindow = CreateWindow("edit", "", WS_CHILD|WS_HSCROLL|WS_VSCROLL|WS_VISIBLE|WS_BORDER| ES_MULTILINE|ES_READONLY, 0, 0, 0, 0, controlWindow, (HMENU)10, hInstance, NULL); SendMessage(debugWindow, EM_SETLIMITTEXT, isWin95 ? 32000 : 128000, 0); DWORD TabStops[] = { DATE_WIDTH, DATE_WIDTH+THREAD_WIDTH, DATE_WIDTH+THREAD_WIDTH+LEVEL_WIDTH, DATE_WIDTH+THREAD_WIDTH+LEVEL_WIDTH+PROTO_WIDTH, DATE_WIDTH+THREAD_WIDTH+LEVEL_WIDTH+PROTO_WIDTH+ACTION_WIDTH, DATE_WIDTH+THREAD_WIDTH+LEVEL_WIDTH+PROTO_WIDTH+ACTION_WIDTH+32 // Standard tab width }; SendMessage(debugWindow, EM_SETTABSTOPS, PARRAYSIZE(TabStops), (LPARAM)(LPDWORD)TabStops); systemLogFileName = cfg.GetString(SystemLogFileNameKey); if (!systemLogFileName) { PFile::Remove(systemLogFileName); DebugOutput("Sending all system log output to \"" + systemLogFileName + "\".\n"); } } return TRUE;}LPARAM WINAPI PServiceProcess::StaticWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){ return Current().WndProc(hWnd, msg, wParam, lParam);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -