📄 svcproc.cxx
字号:
}static void SaveWindowPosition(HWND hWnd){ RECT r; GetWindowRect(hWnd, &r); PConfig cfg(ServiceSimulationSectionName); cfg.SetInteger(WindowLeftKey, r.left); cfg.SetInteger(WindowTopKey, r.top); cfg.SetInteger(WindowRightKey, r.right); cfg.SetInteger(WindowBottomKey, r.bottom);}LPARAM PServiceProcess::WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){#ifdef _DEBUG static DWORD allocationNumber;#endif switch (msg) { case WM_CREATE : controlWindow = hWnd; break; case WM_DESTROY : if (debugWindow == (HWND)-1) { PNotifyIconData nid(hWnd, NIF_TIP); nid.Delete(); // This removes the systray icon } controlWindow = debugWindow = NULL; PostQuitMessage(0); break; case WM_ENDSESSION : if (wParam && (debugMode || lParam != ENDSESSION_LOGOFF) && debugWindow != (HWND)-1) OnStop(); return 0; case WM_MOVE : if (debugWindow != NULL) SaveWindowPosition(hWnd); break; case WM_SIZE : if (debugWindow != NULL && debugWindow != (HWND)-1) { SaveWindowPosition(hWnd); MoveWindow(debugWindow, 0, 0, LOWORD(lParam), HIWORD(lParam), TRUE); } break; case WM_INITMENUPOPUP : { int enableItems = MF_BYCOMMAND|(debugMode ? MF_ENABLED : MF_GRAYED); for (int i = PSystemLog::Fatal; i < PSystemLog::NumLogLevels; i++) { CheckMenuItem((HMENU)wParam, LogLevelBaseMenuID+i, MF_BYCOMMAND|MF_UNCHECKED); EnableMenuItem((HMENU)wParam, LogLevelBaseMenuID+i, enableItems); } CheckMenuItem((HMENU)wParam, LogLevelBaseMenuID+GetLogLevel(), MF_BYCOMMAND|MF_CHECKED); enableItems = MF_BYCOMMAND|(debugMode ? MF_GRAYED : MF_ENABLED); EnableMenuItem((HMENU)wParam, SvcCmdBaseMenuID+SvcCmdStart, enableItems); EnableMenuItem((HMENU)wParam, SvcCmdBaseMenuID+SvcCmdStop, enableItems); EnableMenuItem((HMENU)wParam, SvcCmdBaseMenuID+SvcCmdPause, enableItems); EnableMenuItem((HMENU)wParam, SvcCmdBaseMenuID+SvcCmdResume, enableItems); DWORD start, finish; if (debugWindow != NULL && debugWindow != (HWND)-1) SendMessage(debugWindow, EM_GETSEL, (WPARAM)&start, (LPARAM)&finish); else start = finish = 0; enableItems = MF_BYCOMMAND|(start == finish ? MF_GRAYED : MF_ENABLED); EnableMenuItem((HMENU)wParam, CopyMenuID, enableItems); EnableMenuItem((HMENU)wParam, CutMenuID, enableItems); EnableMenuItem((HMENU)wParam, DeleteMenuID, enableItems); enableItems = MF_BYCOMMAND|(IsServiceRunning(this) ? MF_ENABLED : MF_GRAYED); EnableMenuItem((HMENU)wParam, ControlMenuID, enableItems); break; } case WM_COMMAND : switch (wParam) { case ExitMenuID : DestroyWindow(hWnd); break; case ControlMenuID : if (IsServiceRunning(this)) OnControl(); break; case HideMenuID : ShowWindow(hWnd, SW_HIDE); break;#if PMEMORY_CHECK case MarkMenuID : allocationNumber = PMemoryHeap::GetAllocationRequest(); break; case DumpMenuID : PMemoryHeap::DumpObjectsSince(allocationNumber); break; case StatsMenuID : PMemoryHeap::DumpStatistics(); break; case ValidateMenuID : PMemoryHeap::ValidateHeap(); break;#endif case CopyMenuID : if (debugWindow != NULL && debugWindow != (HWND)-1) SendMessage(debugWindow, WM_COPY, 0, 0); break; case CutMenuID : if (debugWindow != NULL && debugWindow != (HWND)-1) SendMessage(debugWindow, WM_CUT, 0, 0); break; case DeleteMenuID : if (debugWindow != NULL && debugWindow != (HWND)-1) SendMessage(debugWindow, WM_CLEAR, 0, 0); break; case SelectAllMenuID : if (debugWindow != NULL && debugWindow != (HWND)-1) SendMessage(debugWindow, EM_SETSEL, 0, -1); break; case OutputToMenuID : if (debugWindow != NULL && debugWindow != (HWND)-1) { char fileBuffer[_MAX_PATH]; OPENFILENAME fileDlgInfo; memset(&fileDlgInfo, 0, sizeof(fileDlgInfo)); fileDlgInfo.lStructSize = sizeof(fileDlgInfo); fileDlgInfo.hwndOwner = hWnd; fileDlgInfo.hInstance = hInstance; fileBuffer[0] = '\0'; fileDlgInfo.lpstrFile = fileBuffer; char customFilter[100]; strcpy(customFilter, "All Files"); memcpy(&customFilter[strlen(customFilter)+1], "*.*\0", 5); fileDlgInfo.lpstrCustomFilter = customFilter; fileDlgInfo.nMaxCustFilter = sizeof(customFilter); fileDlgInfo.nMaxFile = sizeof(fileBuffer); fileDlgInfo.Flags = OFN_ENABLEHOOK|OFN_HIDEREADONLY|OFN_NOVALIDATE|OFN_EXPLORER|OFN_CREATEPROMPT; fileDlgInfo.lCustData = (DWORD)this; if (GetSaveFileName(&fileDlgInfo)) { if (systemLogFileName != fileBuffer) { systemLogFileName = fileBuffer; PFile::Remove(systemLogFileName); PConfig cfg(ServiceSimulationSectionName); cfg.SetString(SystemLogFileNameKey, systemLogFileName); DebugOutput("Sending all system log output to \"" + systemLogFileName + "\".\n"); PError << "Logging started for \"" << GetName() << "\" version " << GetVersion(TRUE) << endl; } } } break; case WindowOutputMenuID : if (!systemLogFileName) { PError << "Logging stopped." << endl; DebugOutput("System log output to \"" + systemLogFileName + "\" stopped.\n"); systemLogFileName = PString(); PConfig cfg(ServiceSimulationSectionName); cfg.SetString(SystemLogFileNameKey, ""); } break; default : if (wParam >= LogLevelBaseMenuID+PSystemLog::Fatal && wParam < LogLevelBaseMenuID+PSystemLog::NumLogLevels) { SetLogLevel((PSystemLog::Level)(wParam-LogLevelBaseMenuID));#if PTRACING PTrace::SetLevel(wParam-LogLevelBaseMenuID-PSystemLog::Warning);#endif } else if (wParam >= SvcCmdBaseMenuID && wParam < SvcCmdBaseMenuID+NumSvcCmds) { const char * cmdname = ServiceCommandNames[wParam-SvcCmdBaseMenuID]; if (wParam == SvcCmdBaseMenuID+SvcCmdVersion || MessageBox(hWnd, cmdname & GetName() & "?", GetName(), MB_ICONQUESTION|MB_YESNO) == IDYES) ProcessCommand(cmdname); } } break; // Notification of event over sysTray icon case UWM_SYSTRAY : switch (lParam) { case WM_MOUSEMOVE : // update status of process for tool tips if no buttons down if (wParam == SYSTRAY_ICON_ID) { PNotifyIconData nid(hWnd, NIF_TIP, GetName() & (IsServiceRunning(this) ? "is" : "not") & "running."); nid.Modify(); // Modify tooltip } break; // Click on icon - display message case WM_LBUTTONDBLCLK : if (IsServiceRunning(this)) OnControl(); else { SetForegroundWindow(hWnd); // Our MessageBox pops up in front MessageBox(hWnd, "Service is not running!", GetName(), MB_TASKMODAL); } break; // Popup menu case WM_RBUTTONUP : POINT pt; GetCursorPos(&pt); HMENU menu = CreatePopupMenu(); AppendMenu(menu, MF_STRING, ControlMenuID, "&Open Properties"); AppendMenu(menu, MF_SEPARATOR, 0, NULL); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdVersion, "&Version"); if (IsServiceRunning(this)) { MENUITEMINFO inf; inf.cbSize = sizeof(inf); inf.fMask = MIIM_STATE; inf.fState = MFS_DEFAULT; SetMenuItemInfo(menu, ControlMenuID, FALSE, &inf); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdStop, "&Stop Service"); } else { EnableMenuItem(menu, ControlMenuID, MF_GRAYED); AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdStart, "&Start Service"); } AppendMenu(menu, MF_STRING, SvcCmdBaseMenuID+SvcCmdNoTray, "&Tray Icon"); CheckMenuItem(menu, SvcCmdBaseMenuID+SvcCmdNoTray, TrayIconRegistry(this, CheckTrayIcon) ? MF_CHECKED : MF_UNCHECKED); AppendMenu(menu, MF_SEPARATOR, 0, NULL); AppendMenu(menu, MF_STRING, ExitMenuID, "&Close"); /* SetForegroundWindow and the ensuing null PostMessage is a workaround for a Windows 95 bug (see MSKB article Q135788, http://www.microsoft.com/kb/articles/q135/7/88.htm, I think). In typical Microsoft style this bug is listed as "by design". SetForegroundWindow also causes our MessageBox to pop up in front of any other application's windows. */ SetForegroundWindow(hWnd); /* We specifiy TPM_RETURNCMD, so TrackPopupMenu returns the menu selection instead of returning immediately and our getting a WM_COMMAND with the selection. You don't have to do it this way. */ WndProc(hWnd, WM_COMMAND, TrackPopupMenu(menu, // Popup menu to track TPM_RETURNCMD | // Return menu code TPM_RIGHTBUTTON, // Track right mouse button? pt.x, pt.y, // screen coordinates 0, // reserved hWnd, // owner NULL), // LPRECT user can click in without dismissing menu 0); PostMessage(hWnd, 0, 0, 0); // see above DestroyMenu(menu); // Delete loaded menu and reclaim its resources break; } } return DefWindowProc(hWnd, msg, wParam, lParam);}void PServiceProcess::DebugOutput(const char * out){ if (controlWindow == NULL) return; if (debugWindow == NULL || debugWindow == (HWND)-1) { for (PINDEX i = 0; i < 3; i++) { const char * tab = strchr(out, '\t'); if (tab == NULL) break; out = tab+1; } MessageBox(controlWindow, out, GetName(), MB_TASKMODAL); return; } if (!IsWindowVisible(controlWindow)) ShowWindow(controlWindow, SW_SHOWDEFAULT); int len = strlen(out); int max = isWin95 ? 32000 : 128000; while (GetWindowTextLength(debugWindow)+len >= max) { SendMessage(debugWindow, WM_SETREDRAW, FALSE, 0); DWORD start, finish; SendMessage(debugWindow, EM_GETSEL, (WPARAM)&start, (LPARAM)&finish); SendMessage(debugWindow, EM_SETSEL, 0, SendMessage(debugWindow, EM_LINEINDEX, 1, 0)); SendMessage(debugWindow, EM_REPLACESEL, FALSE, (DWORD)""); SendMessage(debugWindow, EM_SETSEL, start, finish); SendMessage(debugWindow, WM_SETREDRAW, TRUE, 0); } SendMessage(debugWindow, EM_SETSEL, max, max); char * lf; const char * prev = out; while ((lf = strchr(prev, '\n')) != NULL) { if (*(lf-1) == '\r') prev = lf+1; else { *lf++ = '\0'; SendMessage(debugWindow, EM_REPLACESEL, FALSE, (DWORD)out); SendMessage(debugWindow, EM_REPLACESEL, FALSE, (DWORD)"\r\n"); prev = out = lf; } } if (*out != '\0') SendMessage(debugWindow, EM_REPLACESEL, FALSE, (DWORD)out);}void PServiceProcess::StaticMainEntry(DWORD argc, LPTSTR * argv){ Current().MainEntry(argc, argv);}void PServiceProcess::MainEntry(DWORD argc, LPTSTR * argv){ // SERVICE_STATUS members that don't change status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; status.dwServiceSpecificExitCode = 0; // register our service control handler: statusHandle = RegisterServiceCtrlHandler(GetName(), StaticControlEntry); if (statusHandle == NULL) return; // report the status to Service Control Manager. if (!ReportStatus(SERVICE_START_PENDING, NO_ERROR, 1, 20000)) return; // create the stop event object. The control handler function signals // this event when it receives the "stop" control code. terminationEvent = CreateEvent(NULL, TRUE, FALSE, (const char *)GetName()); if (terminationEvent == NULL) return; startedEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (startedEvent == NULL) return; GetArguments().SetArgs(argc, argv); // start the thread that performs the work of the service. threadHandle = (HANDLE)_beginthread(StaticThreadEntry, 0, this); if (threadHandle != (HANDLE)-1) { while (WaitForSingleObject(startedEvent, 10000) == WAIT_TIMEOUT) { if (!ReportStatus(SERVICE_START_PENDING, NO_ERROR, 1, 20000)) return; } // Wait here for the end WaitForSingleObject(terminationEvent, INFINITE); } CloseHandle(startedEvent); CloseHandle(terminationEvent); ReportStatus(SERVICE_STOPPED, 0);}void PServiceProcess::StaticThreadEntry(void * arg){ ((PServiceProcess *)arg)->ThreadEntry();}void PServiceProcess::ThreadEntry(){ activeThreadMutex.Wait(); threadId = GetCurrentThreadId(); threadHandle = GetCurrentThread(); activeThreads.SetAt(threadId, this); activeThreadMutex.Signal(); SetTerminationValue(1); if (OnStart()) { if (!debugMode) SetEvent(startedEvent); ReportStatus(SERVICE_RUNNING); SetTerminationValue(0); Main(); ReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 1, 30000); } SetEvent(terminationEvent);}void PServiceProcess::StaticControlEntry(DWORD code){ Current().ControlEntry(code);}void PServiceProcess::ControlEntry(DWORD code){ switch (code) { case SERVICE_CONTROL_PAUSE : // Pause the service if it is running. if (status.dwCurrentState != SERVICE_RUNNING) ReportStatus(status.dwCurrentState); else { if (OnPause()) ReportStatus(SERVICE_PAUSED); } break; case SERVICE_CONTROL_CONTINUE : // Resume the paused service. if (status.dwCurrentState == SERVICE_PAUSED) OnContinue(); ReportStatus(status.dwCurrentState); break; case SERVICE_CONTROL_STOP : // Stop the service. // Report the status, specifying the checkpoint and waithint, before // setting the termination event. ReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 1, 30000); OnStop(); SetEvent(terminationEvent); break; case SERVICE_CONTROL_INTERROGATE : // Update the service status. default : ReportStatus(status.dwCurrentState); }}BOOL PServiceProcess::ReportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwCheckPoint, DWORD dwWaitHint){ // Disable control requests until the service is started. if (dwCurrentState == SERVICE_START_PENDING) status.dwControlsAccepted = 0; else status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; // These SERVICE_STATUS members are set from parameters. status.dwCurrentState = dwCurrentState; status.dwWin32ExitCode = dwWin32ExitCode; status.dwCheckPoint = dwCheckPoint; status.dwWaitHint = dwWaitHint; if (debugMode || isWin95)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -