void __cdecl _tmain(int argc, TCHAR *argv[]) { // If command-line parameter is "install", install the service. // Otherwise, the service is probably being started by the SCM. if (lstrcmpi(argv[1], TEXT("install")) == 0) { SvcInstall(); return; } // TO_DO: Add any additional services for the process to this table. SERVICE_TABLE_ENTRY DispatchTable[] = { { SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain }, { NULL, NULL } }; // This call returns when the service has stopped. // The process should simply terminate when the call returns. if (!StartServiceCtrlDispatcher(DispatchTable)) { SvcReportEvent(TEXT("StartServiceCtrlDispatcher")); } }
int main(int argc, char* argv[]) { if (argc == 1) { SERVICE_TABLE_ENTRY DispatchTable[] = { { SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain }, { nullptr, nullptr } }; if (!StartServiceCtrlDispatcher(DispatchTable)) { if (GetLastError() == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { fprintf(stderr, "This application should be run as a service\n"); } else { SvcReportWinFuncError(TEXT("StartServiceCtrlDispatcher")); } } return EXIT_SUCCESS; } else if (argc == 2) { std::string arg(argv[1]); if (arg == "--install") { return SvcInstall(); } else if (arg == "--delete") { SvcDelete(); return EXIT_SUCCESS; } else { fprintf(stderr, "Unrecognized argument\n"); } } else { fprintf(stderr, "Wrong number of arguments\n"); return EXIT_FAILURE; } }
VOID wmain(int argc, wchar_t *argv[], wchar_t *envp[]) { if (argc > 1) { AccountName = argv[1]; DebugOut("argv[1] = \"%S\"\n", argv[1]); } SERVICE_TABLE_ENTRY DispatchTable[] = { { SERVICE_NAME, ServiceStart }, { NULL, NULL } }; if (!StartServiceCtrlDispatcherW(DispatchTable)) { DWORD LastError = GetLastError(); if (LastError == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { for (;;) { printf("Service %S options:\n", SERVICE_NAME); printf("\t[1] - Install\n"); printf("\t[2] - Uninstall\n"); printf("\t[0] - Exit\n"); printf("Your choose: "); char action = getchar(); while (getchar() != '\n') {} switch (action) { case '1': SvcInstall(); break; case '2': SvcUninstall(); break; case '0': return; default: printf(">> Unrecongnized action\n"); break; } } } else DebugOut(">> StartServiceCtrlDispatcherW failed! (LastError=0x%x)\n", LastError); } }
int wmain(int argc, WCHAR **argv) { // If command-line parameter is "install", install the service // or upgrade if already installed // If command line parameter is "forceinstall", install the service // even if it is older than what is already installed. // If command-line parameter is "upgrade", upgrade the service // but do not install it if it is not already installed. // If command line parameter is "uninstall", uninstall the service. // Otherwise, the service is probably being started by the SCM. bool forceInstall = !lstrcmpi(argv[1], L"forceinstall"); if (!lstrcmpi(argv[1], L"install") || forceInstall) { WCHAR updatePath[MAX_PATH + 1]; if (GetLogDirectoryPath(updatePath)) { LogInit(updatePath, L"maintenanceservice-install.log"); } LOG(("Installing service")); SvcInstallAction action = InstallSvc; if (forceInstall) { action = ForceInstallSvc; LOG((" with force specified")); } LOG(("...\n")); if (!SvcInstall(action)) { LOG(("Could not install service (%d)\n", GetLastError())); LogFinish(); return 1; } LOG(("The service was installed successfully\n")); LogFinish(); return 0; } if (!lstrcmpi(argv[1], L"upgrade")) { WCHAR updatePath[MAX_PATH + 1]; if (GetLogDirectoryPath(updatePath)) { LogInit(updatePath, L"maintenanceservice-install.log"); } LOG(("Upgrading service if installed...\n")); if (!SvcInstall(UpgradeSvc)) { LOG(("Could not upgrade service (%d)\n", GetLastError())); LogFinish(); return 1; } LOG(("The service was upgraded successfully\n")); LogFinish(); return 0; } if (!lstrcmpi(argv[1], L"uninstall")) { WCHAR updatePath[MAX_PATH + 1]; if (GetLogDirectoryPath(updatePath)) { LogInit(updatePath, L"maintenanceservice-uninstall.log"); } LOG(("Uninstalling service...\n")); if (!SvcUninstall()) { LOG(("Could not uninstall service (%d)\n", GetLastError())); LogFinish(); return 1; } LOG(("The service was uninstalled successfully\n")); LogFinish(); return 0; } SERVICE_TABLE_ENTRYW DispatchTable[] = { { SVC_NAME, (LPSERVICE_MAIN_FUNCTIONW) SvcMain }, { NULL, NULL } }; // This call returns when the service has stopped. // The process should simply terminate when the call returns. if (!StartServiceCtrlDispatcherW(DispatchTable)) { LOG(("StartServiceCtrlDispatcher failed (%d)\n", GetLastError())); } return 0; }
/** * Installs or upgrades the SVC_NAME service. * If an existing service is already installed, we replace it with the * currently running process. * * @param action The action to perform. * @return TRUE if the service was installed/upgraded */ BOOL SvcInstall(SvcInstallAction action) { // Get a handle to the local computer SCM database with full access rights. nsAutoServiceHandle schSCManager(OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)); if (!schSCManager) { LOG(("Could not open service manager. (%d)\n", GetLastError())); return FALSE; } WCHAR newServiceBinaryPath[MAX_PATH + 1]; if (!GetModuleFileNameW(NULL, newServiceBinaryPath, sizeof(newServiceBinaryPath) / sizeof(newServiceBinaryPath[0]))) { LOG(("Could not obtain module filename when attempting to " "install service. (%d)\n", GetLastError())); return FALSE; } // Check if we already have the service installed. nsAutoServiceHandle schService(OpenServiceW(schSCManager, SVC_NAME, SERVICE_ALL_ACCESS)); DWORD lastError = GetLastError(); if (!schService && ERROR_SERVICE_DOES_NOT_EXIST != lastError) { // The service exists but we couldn't open it LOG(("Could not open service. (%d)\n", GetLastError())); return FALSE; } if (schService) { // The service exists but it may not have the correct permissions. // This could happen if the permissions were not set correctly originally // or have been changed after the installation. This will reset the // permissions back to allow limited user accounts. if (!SetUserAccessServiceDACL(schService)) { LOG(("Could not reset security ACE on service handle. It might not be " "possible to start the service. This error should never " "happen. (%d)\n", GetLastError())); } // The service exists and we opened it DWORD bytesNeeded; if (!QueryServiceConfigW(schService, NULL, 0, &bytesNeeded) && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { LOG(("Could not determine buffer size for query service config. (%d)\n", GetLastError())); return FALSE; } // Get the service config information, in particular we want the binary // path of the service. nsAutoArrayPtr<char> serviceConfigBuffer = new char[bytesNeeded]; if (!QueryServiceConfigW(schService, reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()), bytesNeeded, &bytesNeeded)) { LOG(("Could open service but could not query service config. (%d)\n", GetLastError())); return FALSE; } QUERY_SERVICE_CONFIGW &serviceConfig = *reinterpret_cast<QUERY_SERVICE_CONFIGW*>(serviceConfigBuffer.get()); // Check if we need to fix the service path BOOL servicePathWasWrong; static BOOL alreadyCheckedFixServicePath = FALSE; if (!alreadyCheckedFixServicePath) { if (!FixServicePath(schService, serviceConfig.lpBinaryPathName, servicePathWasWrong)) { LOG(("Could not fix service path. This should never happen. (%d)\n", GetLastError())); // True is returned because the service is pointing to // maintenanceservice_tmp.exe so it actually was upgraded to the // newest installed service. return TRUE; } else if (servicePathWasWrong) { // Now that the path is fixed we should re-attempt the install. // This current process' image path is maintenanceservice_tmp.exe. // The service used to point to maintenanceservice_tmp.exe. // The service was just fixed to point to maintenanceservice.exe. // Re-attempting an install from scratch will work as normal. alreadyCheckedFixServicePath = TRUE; LOG(("Restarting install action: %d\n", action)); return SvcInstall(action); } } // Ensure the service path is not quoted. We own this memory and know it to // be large enough for the quoted path, so it is large enough for the // unquoted path. This function cannot fail. PathUnquoteSpacesW(serviceConfig.lpBinaryPathName); // Obtain the existing maintenanceservice file's version number and // the new file's version number. Versions are in the format of // A.B.C.D. DWORD existingA, existingB, existingC, existingD; DWORD newA, newB, newC, newD; BOOL obtainedExistingVersionInfo = GetVersionNumberFromPath(serviceConfig.lpBinaryPathName, existingA, existingB, existingC, existingD); if (!GetVersionNumberFromPath(newServiceBinaryPath, newA, newB, newC, newD)) { LOG(("Could not obtain version number from new path\n")); return FALSE; } // Check if we need to replace the old binary with the new one // If we couldn't get the old version info then we assume we should // replace it. if (ForceInstallSvc == action || !obtainedExistingVersionInfo || (existingA < newA) || (existingA == newA && existingB < newB) || (existingA == newA && existingB == newB && existingC < newC) || (existingA == newA && existingB == newB && existingC == newC && existingD < newD)) { // We have a newer updater, so update the description from the INI file. UpdateServiceDescription(schService); schService.reset(); if (!StopService()) { return FALSE; } if (!wcscmp(newServiceBinaryPath, serviceConfig.lpBinaryPathName)) { LOG(("File is already in the correct location, no action needed for " "upgrade. The path is: \"%ls\"\n", newServiceBinaryPath)); return TRUE; } BOOL result = TRUE; // Attempt to copy the new binary over top the existing binary. // If there is an error we try to move it out of the way and then // copy it in. First try the safest / easiest way to overwrite the file. if (!CopyFileW(newServiceBinaryPath, serviceConfig.lpBinaryPathName, FALSE)) { LOG(("Could not overwrite old service binary file. " "This should never happen, but if it does the next upgrade will " "fix it, the service is not a critical component that needs to be " "installed for upgrades to work. (%d)\n", GetLastError())); // We rename the last 3 filename chars in an unsafe way. Manually // verify there are more than 3 chars for safe failure in MoveFileExW. const size_t len = wcslen(serviceConfig.lpBinaryPathName); if (len > 3) { // Calculate the temp file path that we're moving the file to. This // is the same as the proper service path but with a .old extension. LPWSTR oldServiceBinaryTempPath = new WCHAR[len + 1]; memset(oldServiceBinaryTempPath, 0, (len + 1) * sizeof (WCHAR)); wcsncpy(oldServiceBinaryTempPath, serviceConfig.lpBinaryPathName, len); // Rename the last 3 chars to 'old' wcsncpy(oldServiceBinaryTempPath + len - 3, L"old", 3); // Move the current (old) service file to the temp path. if (MoveFileExW(serviceConfig.lpBinaryPathName, oldServiceBinaryTempPath, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH)) { // The old binary is moved out of the way, copy in the new one. if (!CopyFileW(newServiceBinaryPath, serviceConfig.lpBinaryPathName, FALSE)) { // It is best to leave the old service binary in this condition. LOG(("ERROR: The new service binary could not be copied in." " The service will not be upgraded.\n")); result = FALSE; } else { LOG(("The new service binary was copied in by first moving the" " old one out of the way.\n")); } // Attempt to get rid of the old service temp path. if (DeleteFileW(oldServiceBinaryTempPath)) { LOG(("The old temp service path was deleted: %ls.\n", oldServiceBinaryTempPath)); } else { // The old temp path could not be removed. It will be removed // the next time the user can't copy the binary in or on uninstall. LOG(("WARNING: The old temp service path was not deleted.\n")); } } else { // It is best to leave the old service binary in this condition. LOG(("ERROR: Could not move old service file out of the way from:" " \"%ls\" to \"%ls\". Service will not be upgraded. (%d)\n", serviceConfig.lpBinaryPathName, oldServiceBinaryTempPath, GetLastError())); result = FALSE; } delete[] oldServiceBinaryTempPath; } else { // It is best to leave the old service binary in this condition. LOG(("ERROR: Service binary path was less than 3, service will" " not be updated. This should never happen.\n")); result = FALSE; } } else { LOG(("The new service binary was copied in.\n")); } // We made a copy of ourselves to the existing location. // The tmp file (the process of which we are executing right now) will be // left over. Attempt to delete the file on the next reboot. if (MoveFileExW(newServiceBinaryPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT)) { LOG(("Deleting the old file path on the next reboot: %ls.\n", newServiceBinaryPath)); } else { LOG(("Call to delete the old file path failed: %ls.\n", newServiceBinaryPath)); } return result; } // We don't need to copy ourselves to the existing location. // The tmp file (the process of which we are executing right now) will be // left over. Attempt to delete the file on the next reboot. MoveFileExW(newServiceBinaryPath, NULL, MOVEFILE_DELAY_UNTIL_REBOOT); // nothing to do, we already have a newer service installed return TRUE; } // If the service does not exist and we are upgrading, don't install it. if (UpgradeSvc == action) { // The service does not exist and we are upgrading, so don't install it return TRUE; } // Quote the path only if it contains spaces. PathQuoteSpacesW(newServiceBinaryPath); // The service does not already exist so create the service as on demand schService.own(CreateServiceW(schSCManager, SVC_NAME, SVC_DISPLAY_NAME, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, newServiceBinaryPath, NULL, NULL, NULL, NULL, NULL)); if (!schService) { LOG(("Could not create Windows service. " "This error should never happen since a service install " "should only be called when elevated. (%d)\n", GetLastError())); return FALSE; } if (!SetUserAccessServiceDACL(schService)) { LOG(("Could not set security ACE on service handle, the service will not " "be able to be started from unelevated processes. " "This error should never happen. (%d)\n", GetLastError())); } UpdateServiceDescription(schService); return TRUE; }
// // 函数: WndProc(HWND, UINT, WPARAM, LPARAM) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case MYWM_NOTIFYICON: if(lParam==WM_RBUTTONDOWN){ HMENU hMenu = LoadMenuW(hInst,MAKEINTRESOURCEW(IDR_MENU1)); HMENU hSubMenu = GetSubMenu(hMenu,0); POINT pos; GetCursorPos(&pos); SetForegroundWindow(hWnd); TrackPopupMenu(hSubMenu,TPM_LEFTALIGN,pos.x,pos.y,0,hWnd,NULL); DestroyMenu(hMenu); } break; case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // 分析菜单选择: switch (wmId) { case ID_EXIT: NOTIFYICONDATAW m_tnid; memset(&m_tnid,0,sizeof(m_tnid)); //OnCreate 函数中return 之前添加托盘生成代码 m_tnid.cbSize=sizeof(NOTIFYICONDATA); m_tnid.hWnd=hWnd; m_tnid.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP; m_tnid.uCallbackMessage=MYWM_NOTIFYICON; //用户定义的回调消息 wcscpy_s<128>(m_tnid.szTip,L"v-Judge-Kernel"); m_tnid.uID=NULL; HICON hIcon; hIcon=LoadIcon(hInst,MAKEINTRESOURCE(IDI_ICON2)); m_tnid.hIcon=hIcon; Shell_NotifyIconW(NIM_DELETE,&m_tnid); if(hIcon) DestroyIcon(hIcon); DestroyWindow(hWnd); break; case ID_UNINSTALL: if(IDYES == MessageBoxW(0,L"Are you sure to uninstall the service v-Judge_Kernel?",L"Warning!",MB_YESNO)){ if(SvcUninstall()) MessageBoxW(0,L"Successfully uninstall.",L"Message",MB_OK); else MessageBoxW(0,L"Unsuccessfully uninstall.",L"Message",MB_OK); } break; case ID_INSTALL: if(IDYES == MessageBoxW(0,L"Are you sure to install the service v-Judge_Kernel?",L"Warning!",MB_YESNO)){ if(SvcInstall()) MessageBoxW(0,L"Successfully install.",L"Message",MB_OK); else MessageBoxW(0,L"Unsuccessfully install.",L"Message",MB_OK); } break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: 在此添加任意绘图代码... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }