/*++ Copyright (c) 1998 Microsoft Corporation Module Name: grovctrl.cpp Abstract: SIS Groveler controller main function Authors: John Douceur, 1998 Environment: User Mode Revision History: --*/ #include "all.hxx" static _TCHAR *service_name = _T("Groveler"); static _TCHAR *service_path = _T("%SystemRoot%\\System32\\grovel.exe"); static const int num_actions = 3; static Action actions[num_actions] = { {_T("background"), 1, command_service, CMD_background, _T(" [drive_letter ...]")}, /* {_T("continue"), 1, control_service, CTRL_continue, _T("")},*/ {_T("foreground"), 1, command_service, CMD_foreground, _T(" [drive_letter ...]")}, /* {_T("install"), 3, install_service, 0, _T("")},*/ /* {_T("interact"), 3, set_service_interaction, TRUE, _T("")},*/ /* {_T("nointeract"), 1, set_service_interaction, FALSE, _T("")},*/ /* {_T("pause"), 1, control_service, CTRL_pause, _T("")},*/ /* {_T("remove"), 1, remove_service, 0, _T("")},*/ /* {_T("start"), 3, start_service, 0, _T("")},*/ /* {_T("stop"), 3, control_service, CTRL_stop, _T("")},*/ {_T("volscan"), 1, command_service, CMD_volscan, _T(" [drive_letter ...]")} }; static const int perf_value_count = 4; static _TCHAR *perf_tags[perf_value_count] = { _T("Library"), _T("Open"), _T("Collect"), _T("Close") }; static _TCHAR *perf_values[perf_value_count] = { _T("grovperf.dll"), _T("OpenGrovelerPerformanceData"), _T("CollectGrovelerPerformanceData"), _T("CloseGrovelerPerformanceData") }; void usage( _TCHAR *progname, _TCHAR *prefix = NULL) { if (prefix != NULL) { _ftprintf(stderr, _T("unrecognized or ambiguous command: %s\n\n"), prefix); } _ftprintf(stderr, _T("usage:\n")); for (int index = 0; index < num_actions; index++) { _TCHAR *arg = actions[index].arg; int min_chars = actions[index].min_character_count; _ftprintf(stderr, _T("\t%s %.*s[%s]%s\n"), progname, min_chars, arg, &arg[min_chars], actions[index].help); } } void display_error( DWORD err = 0) { void *buffer = 0; if (err == 0) { err = GetLastError(); } DWORD lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT); DWORD result = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err, lang, (LPTSTR) &buffer, 0, 0); if (result != 0) { ASSERT(buffer != 0); _ftprintf(stderr, (_TCHAR *)buffer); } else { _ftprintf(stderr, _T("error number = %d\n"), err); } if (buffer != 0) { LocalFree(buffer); } } extern "C" __cdecl _tmain(int argc, _TCHAR **argv) { if (argc < 2) { usage(argv[0]); return 1; } int arglen = _tcslen(argv[1]); for (int index = 0; index < num_actions; index++) { if (arglen >= actions[index].min_character_count && _tcsncicmp(argv[1], actions[index].arg, arglen) == 0) { break; } } if (index < num_actions) { Function function = actions[index].function; int flag = actions[index].flag; ASSERT(function != 0); int exit_code = (*function)(flag, argc - 2, &argv[2]); return exit_code; } else { usage(argv[0], argv[1]); return 1; } } //int //install_service( // int dummy, // int argc, // _TCHAR **argv) //{ // SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); // if (sc_manager == 0) // { // display_error(); // return 1; // } // SC_HANDLE service = CreateService(sc_manager, service_name, // service_name, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, // SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, service_path, // 0, 0, 0, 0, 0); // if (service == 0) // { // display_error(); // CloseServiceHandle(sc_manager); // return 1; // } // _ftprintf(stderr, _T("Service installed\n")); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); //#if DBG // load_counters(); //#endif // DBG // return 0; //} // //int remove_service( // int dummy, // int argc, // _TCHAR **argv) //{ //#if DBG // unload_counters(); //#endif // DBG // SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); // if (sc_manager == 0) // { // display_error(); // return 1; // } // SC_HANDLE service = // OpenService(sc_manager, service_name, SERVICE_ALL_ACCESS); // if (service == 0) // { // display_error(); // CloseServiceHandle(sc_manager); // return 1; // } // SERVICE_STATUS status; // int ok = QueryServiceStatus(service, &status); // if (ok && status.dwCurrentState != SERVICE_STOPPED) // { // ok = ControlService(service, SERVICE_CONTROL_STOP, &status); // while (ok && status.dwCurrentState == SERVICE_STOP_PENDING) // { // Sleep(100); // ok = QueryServiceStatus(service, &status); // } // if (!ok) // { // display_error(); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 1; // } // else if (status.dwCurrentState != SERVICE_STOPPED) // { // _ftprintf(stderr, // _T("Unable to stop service\nService not removed\n")); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 1; // } // } // ok = DeleteService(service); // if (!ok) // { // display_error(); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 1; // } // _ftprintf(stderr, _T("Service removed\n")); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 0; //} //int //set_service_interaction( // int interactive, // int argc, // _TCHAR **argv) //{ // SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); // if (sc_manager == 0) // { // display_error(); // return 1; // } // SC_LOCK sc_lock = LockServiceDatabase(sc_manager); // if (sc_lock == 0) // { // display_error(); // CloseServiceHandle(sc_manager); // return 1; // } // SC_HANDLE service = // OpenService(sc_manager, service_name, SERVICE_ALL_ACCESS); // if (service == 0) // { // display_error(); // UnlockServiceDatabase(sc_lock); // CloseServiceHandle(sc_manager); // return 1; // } // DWORD service_type = SERVICE_WIN32_OWN_PROCESS; // if (interactive) // { // service_type |= SERVICE_INTERACTIVE_PROCESS; // } // int ok = ChangeServiceConfig(service, service_type, // SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0); // if (!ok) // { // display_error(); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 1; // } // if (interactive) // { // _ftprintf(stderr, _T("Service configured for interaction\n")); // } // else // { // _ftprintf(stderr, _T("Service configured for no interaction\n")); // } // CloseServiceHandle(service); // UnlockServiceDatabase(sc_lock); // CloseServiceHandle(sc_manager); // return 0; //} //int start_service( // int dummy, // int argc, // _TCHAR **argv) //{ // SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); // if (sc_manager == 0) // { // display_error(); // return 1; // } // SC_HANDLE service = // OpenService(sc_manager, service_name, SERVICE_ALL_ACCESS); // if (service == 0) // { // display_error(); // CloseServiceHandle(sc_manager); // return 1; // } // SERVICE_STATUS status; // int ok = StartService(service, 0, 0); // if (!ok) // { // display_error(); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 1; // } // ok = QueryServiceStatus(service, &status); // while (ok && status.dwCurrentState == SERVICE_START_PENDING) // { // Sleep(100); // ok = QueryServiceStatus(service, &status); // } // if (!ok) // { // display_error(); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 1; // } // else if (status.dwCurrentState != SERVICE_RUNNING) // { // _ftprintf(stderr, _T("Service not started")); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 1; // } // _ftprintf(stderr, _T("Service started\n")); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 0; //} //int control_service( // int control, // int argc, // _TCHAR **argv) //{ // DWORD control_code; // DWORD pending_state; // DWORD target_state; // _TCHAR *good_message; // _TCHAR *bad_message; // switch (control) // { // case CTRL_stop: // control_code = SERVICE_CONTROL_STOP; // pending_state = SERVICE_STOP_PENDING; // target_state = SERVICE_STOPPED; // good_message = _T("Service stopped\n"); // bad_message = _T("Service not stopped\n"); // break; // case CTRL_pause: // control_code = SERVICE_CONTROL_PAUSE; // pending_state = SERVICE_PAUSE_PENDING; // target_state = SERVICE_PAUSED; // good_message = _T("Service paused\n"); // bad_message = _T("Service not paused\n"); // break; // case CTRL_continue: // control_code = SERVICE_CONTROL_CONTINUE; // pending_state = SERVICE_CONTINUE_PENDING; // target_state = SERVICE_RUNNING; // good_message = _T("Service continued\n"); // bad_message = _T("Service not continued\n"); // break; // default: // return 1; // } // SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); // if (sc_manager == 0) // { // display_error(); // return 1; // } // SC_HANDLE service = // OpenService(sc_manager, service_name, SERVICE_ALL_ACCESS); // if (service == 0) // { // display_error(); // CloseServiceHandle(sc_manager); // return 1; // } // SERVICE_STATUS status; // int ok = ControlService(service, control_code, &status); // while (ok && status.dwCurrentState == pending_state) // { // Sleep(100); // ok = QueryServiceStatus(service, &status); // } // if (!ok) // { // display_error(); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 1; // } // else if (status.dwCurrentState != target_state) // { // _ftprintf(stderr, bad_message); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 1; // } // _ftprintf(stderr, good_message); // CloseServiceHandle(service); // CloseServiceHandle(sc_manager); // return 0; //} int command_service( int command, int argc, _TCHAR **argv) { DWORD control_code; _TCHAR *message; switch (command) { case CMD_foreground: control_code = SERVICE_CONTROL_FOREGROUND; message = _T("Service mode set to foreground"); break; case CMD_background: control_code = SERVICE_CONTROL_BACKGROUND; message = _T("Service mode set to background"); break; case CMD_volscan: control_code = SERVICE_CONTROL_VOLSCAN; message = _T("Volume scan initiated"); break; default: return 1; } SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS); if (sc_manager == 0) { display_error(); return 1; } SC_HANDLE service = OpenService(sc_manager, service_name, SERVICE_ALL_ACCESS); if (service == 0) { display_error(); CloseServiceHandle(sc_manager); return 1; } int exit_code = 0; SERVICE_STATUS status; if (argc > 0) { for (int index = 0; index < argc; index++) { _TCHAR drive_letter = argv[index][0]; ASSERT(drive_letter != 0); if (drive_letter >= _T('a') && drive_letter <= _T('z') || drive_letter >= _T('A') && drive_letter <= _T('Z')) { DWORD drive_spec = SERVICE_CONTROL_PARTITION_MASK & (DWORD)(_totlower(drive_letter) - _T('a')); int ok = ControlService(service, control_code | drive_spec, &status); if (ok) { _ftprintf(stderr, _T("%s on drive %c\n"), message, drive_letter); } else { display_error(); exit_code++; } } else { _ftprintf(stderr, _T("Invalid drive letter: %c\n"), drive_letter); exit_code++; } } } else { int ok = ControlService(service, control_code | SERVICE_CONTROL_ALL_PARTITIONS, &status); if (ok) { _ftprintf(stderr, _T("%s on all drives\n"), message); } else { display_error(); exit_code++; } } CloseServiceHandle(service); CloseServiceHandle(sc_manager); return 0; } //int load_counters() //{ // HKEY grovperf_key = 0; // HKEY perflib_key = 0; // _TCHAR grovperf_path[1024]; // _stprintf(grovperf_path, // _T("SYSTEM\\CurrentControlSet\\Services\\%s\\Performance"), // service_name); // bool ok = Registry::write_string_set(HKEY_LOCAL_MACHINE, grovperf_path, // perf_value_count, perf_values, perf_tags); // if (!ok) // { // display_error(); // _ftprintf(stderr, _T("Unable to configure performance counters\n")); // return 1; // } // _ftprintf(stderr, _T("Adding counter names and explain text for %s\n"), // service_name); // try // { // Registry::open_key_ex(HKEY_LOCAL_MACHINE, grovperf_path, 0, // KEY_ALL_ACCESS, &grovperf_key); // Registry::open_key_ex(HKEY_LOCAL_MACHINE, // _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"), // 0, KEY_ALL_ACCESS, &perflib_key); // DWORD last_counter = 0; // DWORD ctr_size = sizeof(DWORD); // Registry::query_value_ex(perflib_key, _T("Last Counter"), 0, 0, // (BYTE *)&last_counter, &ctr_size); // DWORD last_help = 0; // ctr_size = sizeof(DWORD); // Registry::query_value_ex(perflib_key, _T("Last Help"), 0, 0, // (BYTE *)&last_help, &ctr_size); // DWORD current_counter; // DWORD current_help; // for (int language = 0; language < num_languages; language++) // { // HKEY lang_key = 0; // BYTE *counter_text = 0; // BYTE *help_text = 0; // try // { // Registry::open_key_ex(perflib_key, language_codes[language], 0, // KEY_ALL_ACCESS, &lang_key); // Registry::query_value_ex(lang_key, _T("Counter"), 0, 0, 0, // &ctr_size); // counter_text = // new BYTE[ctr_size + num_perf_counters * 64]; // Registry::query_value_ex(lang_key, _T("Counter"), 0, 0, // counter_text, &ctr_size); // DWORD help_size; // Registry::query_value_ex(lang_key, _T("Help"), 0, 0, 0, // &help_size); // help_text = new BYTE[help_size + num_perf_counters * 256]; // Registry::query_value_ex(lang_key, _T("Help"), 0, 0, // help_text, &help_size); // current_counter = last_counter; // current_help = last_help; // _TCHAR *counter_point = // (_TCHAR *)(counter_text + ctr_size - sizeof(_TCHAR)); // _TCHAR *help_point = // (_TCHAR *)(help_text + help_size - sizeof(_TCHAR)); // current_counter += 2; // int chars_written = // _stprintf(counter_point, _T("%d%c%s%c"), current_counter, // 0, object_info.text[language].counter_name, 0); // counter_point += chars_written; // ctr_size += chars_written * sizeof(_TCHAR); // current_help += 2; // chars_written = // _stprintf(help_point, _T("%d%c%s%c"), current_help, 0, // object_info.text[language].counter_help, 0); // help_point += chars_written; // help_size += chars_written * sizeof(_TCHAR); // for (int index = 0; index < num_perf_counters; index++) // { // current_counter += 2; // chars_written = _stprintf(counter_point, _T("%d%c%s%c"), // current_counter, 0, // counter_info[index].text[language].counter_name, 0); // counter_point += chars_written; // ctr_size += chars_written * sizeof(_TCHAR); // current_help += 2; // chars_written = _stprintf(help_point, _T("%d%c%s%c"), // current_help, 0, // counter_info[index].text[language].counter_help, 0); // help_point += chars_written; // help_size += chars_written * sizeof(_TCHAR); // } // Registry::set_value_ex(lang_key, _T("Counter"), 0, // REG_MULTI_SZ, counter_text, ctr_size); // Registry::set_value_ex(lang_key, _T("Help"), 0, // REG_MULTI_SZ, help_text, help_size); // delete[] counter_text; // delete[] help_text; // RegCloseKey(lang_key); // lang_key = 0; // _ftprintf(stderr, _T("Updating text for language %s\n"), // language_codes[language]); // } // catch (DWORD) // { // if (counter_text != 0) // { // delete[] counter_text; // counter_text = 0; // } // if (help_text != 0) // { // delete[] help_text; // help_text = 0; // } // if (lang_key != 0) // { // RegCloseKey(lang_key); // lang_key = 0; // } // } // } // Registry::set_value_ex(perflib_key, _T("Last Counter"), 0, REG_DWORD, // (BYTE *)¤t_counter, sizeof(DWORD)); // Registry::set_value_ex(perflib_key, _T("Last Help"), 0, REG_DWORD, // (BYTE *)¤t_help, sizeof(DWORD)); // DWORD first_counter = last_counter + 2; // DWORD first_help = last_help + 2; // Registry::set_value_ex(grovperf_key, _T("First Counter"), 0, REG_DWORD, // (BYTE *)&first_counter, sizeof(DWORD)); // Registry::set_value_ex(grovperf_key, _T("First Help"), 0, REG_DWORD, // (BYTE *)&first_help, sizeof(DWORD)); // Registry::set_value_ex(grovperf_key, _T("Last Counter"), 0, REG_DWORD, // (BYTE *)¤t_counter, sizeof(DWORD)); // Registry::set_value_ex(grovperf_key, _T("Last Help"), 0, REG_DWORD, // (BYTE *)¤t_help, sizeof(DWORD)); // Registry::close_key(grovperf_key); // grovperf_key = 0; // Registry::close_key(perflib_key); // perflib_key = 0; // } // catch (DWORD) // { // if (grovperf_key != 0) // { // RegCloseKey(grovperf_key); // grovperf_key = 0; // } // if (perflib_key != 0) // { // RegCloseKey(perflib_key); // perflib_key = 0; // } // _ftprintf(stderr, _T("Unable to configure performance counters\n")); // return 1; // } // return 0; //} //int unload_counters() //{ // STARTUPINFO startupinfo; // PROCESS_INFORMATION process_information; // startupinfo.cb = sizeof(STARTUPINFO); // startupinfo.lpReserved = 0; // startupinfo.lpDesktop = 0; // startupinfo.lpTitle = 0; // startupinfo.dwFlags = 0; // startupinfo.cbReserved2 = 0; // startupinfo.lpReserved2 = 0; // int pathlen = GetSystemDirectory(0, 0); // if (pathlen == 0) // { // display_error(); // return 1; // } // _TCHAR *command_line = new _TCHAR[pathlen + 64]; // pathlen = GetSystemDirectory(command_line, pathlen); // if (pathlen == 0) // { // delete[] command_line; // display_error(); // return 1; // } // _stprintf(&command_line[pathlen], _T("\\unlodctr.exe \"%s\""), // service_name); // BOOL ok = CreateProcess(0, command_line, // 0, 0, FALSE, 0, 0, 0, &startupinfo, &process_information); // if (!ok) // { // delete[] command_line; // display_error(); // return 1; // } // delete[] command_line; // DWORD result = WaitForSingleObject(process_information.hProcess, 5000); // _tprintf(_T("\n")); // if (result != WAIT_OBJECT_0) // { // return 1; // } // return 0; //}