Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

717 lines
21 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. grovctrl.cpp
  5. Abstract:
  6. SIS Groveler controller main function
  7. Authors:
  8. John Douceur, 1998
  9. Environment:
  10. User Mode
  11. Revision History:
  12. --*/
  13. #include "all.hxx"
  14. static _TCHAR *service_name = _T("Groveler");
  15. static _TCHAR *service_path = _T("%SystemRoot%\\System32\\grovel.exe");
  16. static const int num_actions = 3;
  17. static Action actions[num_actions] =
  18. {
  19. {_T("background"), 1, command_service, CMD_background, _T(" [drive_letter ...]")},
  20. /* {_T("continue"), 1, control_service, CTRL_continue, _T("")},*/
  21. {_T("foreground"), 1, command_service, CMD_foreground, _T(" [drive_letter ...]")},
  22. /* {_T("install"), 3, install_service, 0, _T("")},*/
  23. /* {_T("interact"), 3, set_service_interaction, TRUE, _T("")},*/
  24. /* {_T("nointeract"), 1, set_service_interaction, FALSE, _T("")},*/
  25. /* {_T("pause"), 1, control_service, CTRL_pause, _T("")},*/
  26. /* {_T("remove"), 1, remove_service, 0, _T("")},*/
  27. /* {_T("start"), 3, start_service, 0, _T("")},*/
  28. /* {_T("stop"), 3, control_service, CTRL_stop, _T("")},*/
  29. {_T("volscan"), 1, command_service, CMD_volscan, _T(" [drive_letter ...]")}
  30. };
  31. static const int perf_value_count = 4;
  32. static _TCHAR *perf_tags[perf_value_count] =
  33. {
  34. _T("Library"),
  35. _T("Open"),
  36. _T("Collect"),
  37. _T("Close")
  38. };
  39. static _TCHAR *perf_values[perf_value_count] =
  40. {
  41. _T("grovperf.dll"),
  42. _T("OpenGrovelerPerformanceData"),
  43. _T("CollectGrovelerPerformanceData"),
  44. _T("CloseGrovelerPerformanceData")
  45. };
  46. void
  47. usage(
  48. _TCHAR *progname,
  49. _TCHAR *prefix = NULL)
  50. {
  51. if (prefix != NULL)
  52. {
  53. _ftprintf(stderr, _T("unrecognized or ambiguous command: %s\n\n"),
  54. prefix);
  55. }
  56. _ftprintf(stderr, _T("usage:\n"));
  57. for (int index = 0; index < num_actions; index++)
  58. {
  59. _TCHAR *arg = actions[index].arg;
  60. int min_chars = actions[index].min_character_count;
  61. _ftprintf(stderr, _T("\t%s %.*s[%s]%s\n"), progname, min_chars,
  62. arg, &arg[min_chars], actions[index].help);
  63. }
  64. }
  65. void
  66. display_error(
  67. DWORD err = 0)
  68. {
  69. void *buffer = 0;
  70. if (err == 0)
  71. {
  72. err = GetLastError();
  73. }
  74. DWORD lang = MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT);
  75. DWORD result = FormatMessage(
  76. FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM
  77. | FORMAT_MESSAGE_IGNORE_INSERTS, 0, err, lang, (LPTSTR) &buffer, 0, 0);
  78. if (result != 0)
  79. {
  80. ASSERT(buffer != 0);
  81. _ftprintf(stderr, (_TCHAR *)buffer);
  82. }
  83. else
  84. {
  85. _ftprintf(stderr, _T("error number = %d\n"), err);
  86. }
  87. if (buffer != 0)
  88. {
  89. LocalFree(buffer);
  90. }
  91. }
  92. extern "C" __cdecl _tmain(int argc, _TCHAR **argv)
  93. {
  94. if (argc < 2)
  95. {
  96. usage(argv[0]);
  97. return 1;
  98. }
  99. int arglen = _tcslen(argv[1]);
  100. for (int index = 0; index < num_actions; index++)
  101. {
  102. if (arglen >= actions[index].min_character_count &&
  103. _tcsncicmp(argv[1], actions[index].arg, arglen) == 0)
  104. {
  105. break;
  106. }
  107. }
  108. if (index < num_actions)
  109. {
  110. Function function = actions[index].function;
  111. int flag = actions[index].flag;
  112. ASSERT(function != 0);
  113. int exit_code = (*function)(flag, argc - 2, &argv[2]);
  114. return exit_code;
  115. }
  116. else
  117. {
  118. usage(argv[0], argv[1]);
  119. return 1;
  120. }
  121. }
  122. //int
  123. //install_service(
  124. // int dummy,
  125. // int argc,
  126. // _TCHAR **argv)
  127. //{
  128. // SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
  129. // if (sc_manager == 0)
  130. // {
  131. // display_error();
  132. // return 1;
  133. // }
  134. // SC_HANDLE service = CreateService(sc_manager, service_name,
  135. // service_name, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
  136. // SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, service_path,
  137. // 0, 0, 0, 0, 0);
  138. // if (service == 0)
  139. // {
  140. // display_error();
  141. // CloseServiceHandle(sc_manager);
  142. // return 1;
  143. // }
  144. // _ftprintf(stderr, _T("Service installed\n"));
  145. // CloseServiceHandle(service);
  146. // CloseServiceHandle(sc_manager);
  147. //#if DBG
  148. // load_counters();
  149. //#endif // DBG
  150. // return 0;
  151. //}
  152. //
  153. //int remove_service(
  154. // int dummy,
  155. // int argc,
  156. // _TCHAR **argv)
  157. //{
  158. //#if DBG
  159. // unload_counters();
  160. //#endif // DBG
  161. // SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
  162. // if (sc_manager == 0)
  163. // {
  164. // display_error();
  165. // return 1;
  166. // }
  167. // SC_HANDLE service =
  168. // OpenService(sc_manager, service_name, SERVICE_ALL_ACCESS);
  169. // if (service == 0)
  170. // {
  171. // display_error();
  172. // CloseServiceHandle(sc_manager);
  173. // return 1;
  174. // }
  175. // SERVICE_STATUS status;
  176. // int ok = QueryServiceStatus(service, &status);
  177. // if (ok && status.dwCurrentState != SERVICE_STOPPED)
  178. // {
  179. // ok = ControlService(service, SERVICE_CONTROL_STOP, &status);
  180. // while (ok && status.dwCurrentState == SERVICE_STOP_PENDING)
  181. // {
  182. // Sleep(100);
  183. // ok = QueryServiceStatus(service, &status);
  184. // }
  185. // if (!ok)
  186. // {
  187. // display_error();
  188. // CloseServiceHandle(service);
  189. // CloseServiceHandle(sc_manager);
  190. // return 1;
  191. // }
  192. // else if (status.dwCurrentState != SERVICE_STOPPED)
  193. // {
  194. // _ftprintf(stderr,
  195. // _T("Unable to stop service\nService not removed\n"));
  196. // CloseServiceHandle(service);
  197. // CloseServiceHandle(sc_manager);
  198. // return 1;
  199. // }
  200. // }
  201. // ok = DeleteService(service);
  202. // if (!ok)
  203. // {
  204. // display_error();
  205. // CloseServiceHandle(service);
  206. // CloseServiceHandle(sc_manager);
  207. // return 1;
  208. // }
  209. // _ftprintf(stderr, _T("Service removed\n"));
  210. // CloseServiceHandle(service);
  211. // CloseServiceHandle(sc_manager);
  212. // return 0;
  213. //}
  214. //int
  215. //set_service_interaction(
  216. // int interactive,
  217. // int argc,
  218. // _TCHAR **argv)
  219. //{
  220. // SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
  221. // if (sc_manager == 0)
  222. // {
  223. // display_error();
  224. // return 1;
  225. // }
  226. // SC_LOCK sc_lock = LockServiceDatabase(sc_manager);
  227. // if (sc_lock == 0)
  228. // {
  229. // display_error();
  230. // CloseServiceHandle(sc_manager);
  231. // return 1;
  232. // }
  233. // SC_HANDLE service =
  234. // OpenService(sc_manager, service_name, SERVICE_ALL_ACCESS);
  235. // if (service == 0)
  236. // {
  237. // display_error();
  238. // UnlockServiceDatabase(sc_lock);
  239. // CloseServiceHandle(sc_manager);
  240. // return 1;
  241. // }
  242. // DWORD service_type = SERVICE_WIN32_OWN_PROCESS;
  243. // if (interactive)
  244. // {
  245. // service_type |= SERVICE_INTERACTIVE_PROCESS;
  246. // }
  247. // int ok = ChangeServiceConfig(service, service_type,
  248. // SERVICE_NO_CHANGE, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0);
  249. // if (!ok)
  250. // {
  251. // display_error();
  252. // CloseServiceHandle(service);
  253. // CloseServiceHandle(sc_manager);
  254. // return 1;
  255. // }
  256. // if (interactive)
  257. // {
  258. // _ftprintf(stderr, _T("Service configured for interaction\n"));
  259. // }
  260. // else
  261. // {
  262. // _ftprintf(stderr, _T("Service configured for no interaction\n"));
  263. // }
  264. // CloseServiceHandle(service);
  265. // UnlockServiceDatabase(sc_lock);
  266. // CloseServiceHandle(sc_manager);
  267. // return 0;
  268. //}
  269. //int start_service(
  270. // int dummy,
  271. // int argc,
  272. // _TCHAR **argv)
  273. //{
  274. // SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
  275. // if (sc_manager == 0)
  276. // {
  277. // display_error();
  278. // return 1;
  279. // }
  280. // SC_HANDLE service =
  281. // OpenService(sc_manager, service_name, SERVICE_ALL_ACCESS);
  282. // if (service == 0)
  283. // {
  284. // display_error();
  285. // CloseServiceHandle(sc_manager);
  286. // return 1;
  287. // }
  288. // SERVICE_STATUS status;
  289. // int ok = StartService(service, 0, 0);
  290. // if (!ok)
  291. // {
  292. // display_error();
  293. // CloseServiceHandle(service);
  294. // CloseServiceHandle(sc_manager);
  295. // return 1;
  296. // }
  297. // ok = QueryServiceStatus(service, &status);
  298. // while (ok && status.dwCurrentState == SERVICE_START_PENDING)
  299. // {
  300. // Sleep(100);
  301. // ok = QueryServiceStatus(service, &status);
  302. // }
  303. // if (!ok)
  304. // {
  305. // display_error();
  306. // CloseServiceHandle(service);
  307. // CloseServiceHandle(sc_manager);
  308. // return 1;
  309. // }
  310. // else if (status.dwCurrentState != SERVICE_RUNNING)
  311. // {
  312. // _ftprintf(stderr, _T("Service not started"));
  313. // CloseServiceHandle(service);
  314. // CloseServiceHandle(sc_manager);
  315. // return 1;
  316. // }
  317. // _ftprintf(stderr, _T("Service started\n"));
  318. // CloseServiceHandle(service);
  319. // CloseServiceHandle(sc_manager);
  320. // return 0;
  321. //}
  322. //int control_service(
  323. // int control,
  324. // int argc,
  325. // _TCHAR **argv)
  326. //{
  327. // DWORD control_code;
  328. // DWORD pending_state;
  329. // DWORD target_state;
  330. // _TCHAR *good_message;
  331. // _TCHAR *bad_message;
  332. // switch (control)
  333. // {
  334. // case CTRL_stop:
  335. // control_code = SERVICE_CONTROL_STOP;
  336. // pending_state = SERVICE_STOP_PENDING;
  337. // target_state = SERVICE_STOPPED;
  338. // good_message = _T("Service stopped\n");
  339. // bad_message = _T("Service not stopped\n");
  340. // break;
  341. // case CTRL_pause:
  342. // control_code = SERVICE_CONTROL_PAUSE;
  343. // pending_state = SERVICE_PAUSE_PENDING;
  344. // target_state = SERVICE_PAUSED;
  345. // good_message = _T("Service paused\n");
  346. // bad_message = _T("Service not paused\n");
  347. // break;
  348. // case CTRL_continue:
  349. // control_code = SERVICE_CONTROL_CONTINUE;
  350. // pending_state = SERVICE_CONTINUE_PENDING;
  351. // target_state = SERVICE_RUNNING;
  352. // good_message = _T("Service continued\n");
  353. // bad_message = _T("Service not continued\n");
  354. // break;
  355. // default:
  356. // return 1;
  357. // }
  358. // SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
  359. // if (sc_manager == 0)
  360. // {
  361. // display_error();
  362. // return 1;
  363. // }
  364. // SC_HANDLE service =
  365. // OpenService(sc_manager, service_name, SERVICE_ALL_ACCESS);
  366. // if (service == 0)
  367. // {
  368. // display_error();
  369. // CloseServiceHandle(sc_manager);
  370. // return 1;
  371. // }
  372. // SERVICE_STATUS status;
  373. // int ok = ControlService(service, control_code, &status);
  374. // while (ok && status.dwCurrentState == pending_state)
  375. // {
  376. // Sleep(100);
  377. // ok = QueryServiceStatus(service, &status);
  378. // }
  379. // if (!ok)
  380. // {
  381. // display_error();
  382. // CloseServiceHandle(service);
  383. // CloseServiceHandle(sc_manager);
  384. // return 1;
  385. // }
  386. // else if (status.dwCurrentState != target_state)
  387. // {
  388. // _ftprintf(stderr, bad_message);
  389. // CloseServiceHandle(service);
  390. // CloseServiceHandle(sc_manager);
  391. // return 1;
  392. // }
  393. // _ftprintf(stderr, good_message);
  394. // CloseServiceHandle(service);
  395. // CloseServiceHandle(sc_manager);
  396. // return 0;
  397. //}
  398. int command_service(
  399. int command,
  400. int argc,
  401. _TCHAR **argv)
  402. {
  403. DWORD control_code;
  404. _TCHAR *message;
  405. switch (command)
  406. {
  407. case CMD_foreground:
  408. control_code = SERVICE_CONTROL_FOREGROUND;
  409. message = _T("Service mode set to foreground");
  410. break;
  411. case CMD_background:
  412. control_code = SERVICE_CONTROL_BACKGROUND;
  413. message = _T("Service mode set to background");
  414. break;
  415. case CMD_volscan:
  416. control_code = SERVICE_CONTROL_VOLSCAN;
  417. message = _T("Volume scan initiated");
  418. break;
  419. default:
  420. return 1;
  421. }
  422. SC_HANDLE sc_manager = OpenSCManager(0, 0, SC_MANAGER_ALL_ACCESS);
  423. if (sc_manager == 0)
  424. {
  425. display_error();
  426. return 1;
  427. }
  428. SC_HANDLE service =
  429. OpenService(sc_manager, service_name, SERVICE_ALL_ACCESS);
  430. if (service == 0)
  431. {
  432. display_error();
  433. CloseServiceHandle(sc_manager);
  434. return 1;
  435. }
  436. int exit_code = 0;
  437. SERVICE_STATUS status;
  438. if (argc > 0)
  439. {
  440. for (int index = 0; index < argc; index++)
  441. {
  442. _TCHAR drive_letter = argv[index][0];
  443. ASSERT(drive_letter != 0);
  444. if (drive_letter >= _T('a') && drive_letter <= _T('z')
  445. || drive_letter >= _T('A') && drive_letter <= _T('Z'))
  446. {
  447. DWORD drive_spec = SERVICE_CONTROL_PARTITION_MASK &
  448. (DWORD)(_totlower(drive_letter) - _T('a'));
  449. int ok = ControlService(service,
  450. control_code | drive_spec, &status);
  451. if (ok)
  452. {
  453. _ftprintf(stderr, _T("%s on drive %c\n"),
  454. message, drive_letter);
  455. }
  456. else
  457. {
  458. display_error();
  459. exit_code++;
  460. }
  461. }
  462. else
  463. {
  464. _ftprintf(stderr, _T("Invalid drive letter: %c\n"),
  465. drive_letter);
  466. exit_code++;
  467. }
  468. }
  469. }
  470. else
  471. {
  472. int ok = ControlService(service,
  473. control_code | SERVICE_CONTROL_ALL_PARTITIONS, &status);
  474. if (ok)
  475. {
  476. _ftprintf(stderr, _T("%s on all drives\n"), message);
  477. }
  478. else
  479. {
  480. display_error();
  481. exit_code++;
  482. }
  483. }
  484. CloseServiceHandle(service);
  485. CloseServiceHandle(sc_manager);
  486. return 0;
  487. }
  488. //int load_counters()
  489. //{
  490. // HKEY grovperf_key = 0;
  491. // HKEY perflib_key = 0;
  492. // _TCHAR grovperf_path[1024];
  493. // _stprintf(grovperf_path,
  494. // _T("SYSTEM\\CurrentControlSet\\Services\\%s\\Performance"),
  495. // service_name);
  496. // bool ok = Registry::write_string_set(HKEY_LOCAL_MACHINE, grovperf_path,
  497. // perf_value_count, perf_values, perf_tags);
  498. // if (!ok)
  499. // {
  500. // display_error();
  501. // _ftprintf(stderr, _T("Unable to configure performance counters\n"));
  502. // return 1;
  503. // }
  504. // _ftprintf(stderr, _T("Adding counter names and explain text for %s\n"),
  505. // service_name);
  506. // try
  507. // {
  508. // Registry::open_key_ex(HKEY_LOCAL_MACHINE, grovperf_path, 0,
  509. // KEY_ALL_ACCESS, &grovperf_key);
  510. // Registry::open_key_ex(HKEY_LOCAL_MACHINE,
  511. // _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib"),
  512. // 0, KEY_ALL_ACCESS, &perflib_key);
  513. // DWORD last_counter = 0;
  514. // DWORD ctr_size = sizeof(DWORD);
  515. // Registry::query_value_ex(perflib_key, _T("Last Counter"), 0, 0,
  516. // (BYTE *)&last_counter, &ctr_size);
  517. // DWORD last_help = 0;
  518. // ctr_size = sizeof(DWORD);
  519. // Registry::query_value_ex(perflib_key, _T("Last Help"), 0, 0,
  520. // (BYTE *)&last_help, &ctr_size);
  521. // DWORD current_counter;
  522. // DWORD current_help;
  523. // for (int language = 0; language < num_languages; language++)
  524. // {
  525. // HKEY lang_key = 0;
  526. // BYTE *counter_text = 0;
  527. // BYTE *help_text = 0;
  528. // try
  529. // {
  530. // Registry::open_key_ex(perflib_key, language_codes[language], 0,
  531. // KEY_ALL_ACCESS, &lang_key);
  532. // Registry::query_value_ex(lang_key, _T("Counter"), 0, 0, 0,
  533. // &ctr_size);
  534. // counter_text =
  535. // new BYTE[ctr_size + num_perf_counters * 64];
  536. // Registry::query_value_ex(lang_key, _T("Counter"), 0, 0,
  537. // counter_text, &ctr_size);
  538. // DWORD help_size;
  539. // Registry::query_value_ex(lang_key, _T("Help"), 0, 0, 0,
  540. // &help_size);
  541. // help_text = new BYTE[help_size + num_perf_counters * 256];
  542. // Registry::query_value_ex(lang_key, _T("Help"), 0, 0,
  543. // help_text, &help_size);
  544. // current_counter = last_counter;
  545. // current_help = last_help;
  546. // _TCHAR *counter_point =
  547. // (_TCHAR *)(counter_text + ctr_size - sizeof(_TCHAR));
  548. // _TCHAR *help_point =
  549. // (_TCHAR *)(help_text + help_size - sizeof(_TCHAR));
  550. // current_counter += 2;
  551. // int chars_written =
  552. // _stprintf(counter_point, _T("%d%c%s%c"), current_counter,
  553. // 0, object_info.text[language].counter_name, 0);
  554. // counter_point += chars_written;
  555. // ctr_size += chars_written * sizeof(_TCHAR);
  556. // current_help += 2;
  557. // chars_written =
  558. // _stprintf(help_point, _T("%d%c%s%c"), current_help, 0,
  559. // object_info.text[language].counter_help, 0);
  560. // help_point += chars_written;
  561. // help_size += chars_written * sizeof(_TCHAR);
  562. // for (int index = 0; index < num_perf_counters; index++)
  563. // {
  564. // current_counter += 2;
  565. // chars_written = _stprintf(counter_point, _T("%d%c%s%c"),
  566. // current_counter, 0,
  567. // counter_info[index].text[language].counter_name, 0);
  568. // counter_point += chars_written;
  569. // ctr_size += chars_written * sizeof(_TCHAR);
  570. // current_help += 2;
  571. // chars_written = _stprintf(help_point, _T("%d%c%s%c"),
  572. // current_help, 0,
  573. // counter_info[index].text[language].counter_help, 0);
  574. // help_point += chars_written;
  575. // help_size += chars_written * sizeof(_TCHAR);
  576. // }
  577. // Registry::set_value_ex(lang_key, _T("Counter"), 0,
  578. // REG_MULTI_SZ, counter_text, ctr_size);
  579. // Registry::set_value_ex(lang_key, _T("Help"), 0,
  580. // REG_MULTI_SZ, help_text, help_size);
  581. // delete[] counter_text;
  582. // delete[] help_text;
  583. // RegCloseKey(lang_key);
  584. // lang_key = 0;
  585. // _ftprintf(stderr, _T("Updating text for language %s\n"),
  586. // language_codes[language]);
  587. // }
  588. // catch (DWORD)
  589. // {
  590. // if (counter_text != 0)
  591. // {
  592. // delete[] counter_text;
  593. // counter_text = 0;
  594. // }
  595. // if (help_text != 0)
  596. // {
  597. // delete[] help_text;
  598. // help_text = 0;
  599. // }
  600. // if (lang_key != 0)
  601. // {
  602. // RegCloseKey(lang_key);
  603. // lang_key = 0;
  604. // }
  605. // }
  606. // }
  607. // Registry::set_value_ex(perflib_key, _T("Last Counter"), 0, REG_DWORD,
  608. // (BYTE *)&current_counter, sizeof(DWORD));
  609. // Registry::set_value_ex(perflib_key, _T("Last Help"), 0, REG_DWORD,
  610. // (BYTE *)&current_help, sizeof(DWORD));
  611. // DWORD first_counter = last_counter + 2;
  612. // DWORD first_help = last_help + 2;
  613. // Registry::set_value_ex(grovperf_key, _T("First Counter"), 0, REG_DWORD,
  614. // (BYTE *)&first_counter, sizeof(DWORD));
  615. // Registry::set_value_ex(grovperf_key, _T("First Help"), 0, REG_DWORD,
  616. // (BYTE *)&first_help, sizeof(DWORD));
  617. // Registry::set_value_ex(grovperf_key, _T("Last Counter"), 0, REG_DWORD,
  618. // (BYTE *)&current_counter, sizeof(DWORD));
  619. // Registry::set_value_ex(grovperf_key, _T("Last Help"), 0, REG_DWORD,
  620. // (BYTE *)&current_help, sizeof(DWORD));
  621. // Registry::close_key(grovperf_key);
  622. // grovperf_key = 0;
  623. // Registry::close_key(perflib_key);
  624. // perflib_key = 0;
  625. // }
  626. // catch (DWORD)
  627. // {
  628. // if (grovperf_key != 0)
  629. // {
  630. // RegCloseKey(grovperf_key);
  631. // grovperf_key = 0;
  632. // }
  633. // if (perflib_key != 0)
  634. // {
  635. // RegCloseKey(perflib_key);
  636. // perflib_key = 0;
  637. // }
  638. // _ftprintf(stderr, _T("Unable to configure performance counters\n"));
  639. // return 1;
  640. // }
  641. // return 0;
  642. //}
  643. //int unload_counters()
  644. //{
  645. // STARTUPINFO startupinfo;
  646. // PROCESS_INFORMATION process_information;
  647. // startupinfo.cb = sizeof(STARTUPINFO);
  648. // startupinfo.lpReserved = 0;
  649. // startupinfo.lpDesktop = 0;
  650. // startupinfo.lpTitle = 0;
  651. // startupinfo.dwFlags = 0;
  652. // startupinfo.cbReserved2 = 0;
  653. // startupinfo.lpReserved2 = 0;
  654. // int pathlen = GetSystemDirectory(0, 0);
  655. // if (pathlen == 0)
  656. // {
  657. // display_error();
  658. // return 1;
  659. // }
  660. // _TCHAR *command_line = new _TCHAR[pathlen + 64];
  661. // pathlen = GetSystemDirectory(command_line, pathlen);
  662. // if (pathlen == 0)
  663. // {
  664. // delete[] command_line;
  665. // display_error();
  666. // return 1;
  667. // }
  668. // _stprintf(&command_line[pathlen], _T("\\unlodctr.exe \"%s\""),
  669. // service_name);
  670. // BOOL ok = CreateProcess(0, command_line,
  671. // 0, 0, FALSE, 0, 0, 0, &startupinfo, &process_information);
  672. // if (!ok)
  673. // {
  674. // delete[] command_line;
  675. // display_error();
  676. // return 1;
  677. // }
  678. // delete[] command_line;
  679. // DWORD result = WaitForSingleObject(process_information.hProcess, 5000);
  680. // _tprintf(_T("\n"));
  681. // if (result != WAIT_OBJECT_0)
  682. // {
  683. // return 1;
  684. // }
  685. // return 0;
  686. //}