net.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*
  2. * Copyright 2007 Tim Schwartz
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with this library; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  17. */
  18. #include <windows.h>
  19. #include <lm.h>
  20. #include <wine/debug.h>
  21. #include "resources.h"
  22. WINE_DEFAULT_DEBUG_CHANNEL(net);
  23. #define NET_START 0001
  24. #define NET_STOP 0002
  25. static int output_write(const WCHAR* str, int len)
  26. {
  27. DWORD ret, count;
  28. ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), str, len, &count, NULL);
  29. if (!ret)
  30. {
  31. DWORD lenA;
  32. char* strA;
  33. /* On Windows WriteConsoleW() fails if the output is redirected. So fall
  34. * back to WriteFile(), assuming the console encoding is still the right
  35. * one in that case.
  36. */
  37. lenA = WideCharToMultiByte(GetConsoleOutputCP(), 0, str, len,
  38. NULL, 0, NULL, NULL);
  39. strA = HeapAlloc(GetProcessHeap(), 0, lenA);
  40. if (!strA)
  41. return 0;
  42. WideCharToMultiByte(GetConsoleOutputCP(), 0, str, len, strA, lenA,
  43. NULL, NULL);
  44. WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), strA, lenA, &count, FALSE);
  45. HeapFree(GetProcessHeap(), 0, strA);
  46. }
  47. return count;
  48. }
  49. static int output_vprintf(const WCHAR* fmt, va_list va_args)
  50. {
  51. WCHAR str[8192];
  52. int len;
  53. len = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, fmt, 0, 0, str, ARRAY_SIZE(str), &va_args);
  54. if (len == 0 && GetLastError() != ERROR_NO_WORK_DONE)
  55. WINE_FIXME("Could not format string: le=%u, fmt=%s\n", GetLastError(), wine_dbgstr_w(fmt));
  56. else
  57. output_write(str, len);
  58. return 0;
  59. }
  60. static int WINAPIV output_printf(const WCHAR* fmt, ...)
  61. {
  62. va_list arguments;
  63. va_start(arguments, fmt);
  64. output_vprintf(fmt, arguments);
  65. va_end(arguments);
  66. return 0;
  67. }
  68. static int WINAPIV output_string(int msg, ...)
  69. {
  70. WCHAR fmt[8192];
  71. va_list arguments;
  72. LoadStringW(GetModuleHandleW(NULL), msg, fmt, ARRAY_SIZE(fmt));
  73. va_start(arguments, msg);
  74. output_vprintf(fmt, arguments);
  75. va_end(arguments);
  76. return 0;
  77. }
  78. static BOOL output_error_string(DWORD error)
  79. {
  80. LPWSTR pBuffer;
  81. if (FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM |
  82. FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  83. NULL, error, 0, (LPWSTR)&pBuffer, 0, NULL))
  84. {
  85. output_write(pBuffer, lstrlenW(pBuffer));
  86. LocalFree(pBuffer);
  87. return TRUE;
  88. }
  89. return FALSE;
  90. }
  91. static BOOL net_use(int argc, const WCHAR* argv[])
  92. {
  93. USE_INFO_2 *buffer, *connection;
  94. DWORD read, total, resume_handle, rc, i;
  95. WCHAR* status[STRING_RECONN-STRING_OK+1];
  96. resume_handle = 0;
  97. buffer = NULL;
  98. if(argc<3)
  99. {
  100. HMODULE hmod = GetModuleHandleW(NULL);
  101. /* Load the status strings */
  102. for (i = 0; i < ARRAY_SIZE(status); i++)
  103. {
  104. status[i] = HeapAlloc(GetProcessHeap(), 0, 1024 * sizeof(**status));
  105. LoadStringW(hmod, STRING_OK+i, status[i], 1024);
  106. }
  107. do {
  108. rc = NetUseEnum(NULL, 2, (BYTE **) &buffer, 2048, &read, &total, &resume_handle);
  109. if (rc != ERROR_MORE_DATA && rc != ERROR_SUCCESS)
  110. {
  111. break;
  112. }
  113. if(total == 0)
  114. {
  115. output_string(STRING_NO_ENTRIES);
  116. break;
  117. }
  118. output_string(STRING_USE_HEADER);
  119. for (i = 0, connection = buffer; i < read; ++i, ++connection)
  120. output_string(STRING_USE_ENTRY, status[connection->ui2_status], connection->ui2_local,
  121. connection->ui2_remote, connection->ui2_refcount);
  122. if (buffer != NULL) NetApiBufferFree(buffer);
  123. } while (rc == ERROR_MORE_DATA);
  124. /* Release the status strings */
  125. for (i = 0; i < ARRAY_SIZE(status); i++)
  126. HeapFree(GetProcessHeap(), 0, status[i]);
  127. return TRUE;
  128. }
  129. return FALSE;
  130. }
  131. static BOOL net_enum_services(void)
  132. {
  133. SC_HANDLE SCManager;
  134. LPENUM_SERVICE_STATUS_PROCESSW services;
  135. DWORD size, i, count, resume;
  136. BOOL success = FALSE;
  137. SCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  138. if(!SCManager)
  139. {
  140. output_string(STRING_NO_SCM);
  141. return FALSE;
  142. }
  143. EnumServicesStatusExW(SCManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_ACTIVE, NULL, 0, &size, &count, NULL, NULL);
  144. if(GetLastError() != ERROR_MORE_DATA)
  145. {
  146. output_error_string(GetLastError());
  147. goto end;
  148. }
  149. services = HeapAlloc(GetProcessHeap(), 0, size);
  150. resume = 0;
  151. if(!EnumServicesStatusExW(SCManager, SC_ENUM_PROCESS_INFO, SERVICE_WIN32, SERVICE_ACTIVE, (LPBYTE)services, size, &size, &count, &resume, NULL))
  152. {
  153. output_error_string(GetLastError());
  154. goto end;
  155. }
  156. output_string(STRING_RUNNING_HEADER);
  157. for(i = 0; i < count; i++)
  158. {
  159. output_printf(L" %1\n", services[i].lpDisplayName);
  160. WINE_TRACE("service=%s state=%d controls=%x\n",
  161. wine_dbgstr_w(services[i].lpServiceName),
  162. services[i].ServiceStatusProcess.dwCurrentState,
  163. services[i].ServiceStatusProcess.dwControlsAccepted);
  164. }
  165. success = TRUE;
  166. end:
  167. CloseServiceHandle(SCManager);
  168. return success;
  169. }
  170. static BOOL StopService(SC_HANDLE SCManager, SC_HANDLE serviceHandle)
  171. {
  172. LPENUM_SERVICE_STATUSW dependencies = NULL;
  173. DWORD buffer_size = 0;
  174. DWORD count = 0, counter;
  175. BOOL result;
  176. SC_HANDLE dependent_serviceHandle;
  177. SERVICE_STATUS_PROCESS ssp;
  178. result = EnumDependentServicesW(serviceHandle, SERVICE_ACTIVE, dependencies, buffer_size, &buffer_size, &count);
  179. if(!result && (GetLastError() == ERROR_MORE_DATA))
  180. {
  181. dependencies = HeapAlloc(GetProcessHeap(), 0, buffer_size);
  182. if(EnumDependentServicesW(serviceHandle, SERVICE_ACTIVE, dependencies, buffer_size, &buffer_size, &count))
  183. {
  184. for(counter = 0; counter < count; counter++)
  185. {
  186. output_string(STRING_STOP_DEP, dependencies[counter].lpDisplayName);
  187. dependent_serviceHandle = OpenServiceW(SCManager, dependencies[counter].lpServiceName, SC_MANAGER_ALL_ACCESS);
  188. if(dependent_serviceHandle)
  189. {
  190. result = StopService(SCManager, dependent_serviceHandle);
  191. CloseServiceHandle(dependent_serviceHandle);
  192. }
  193. if(!result) output_string(STRING_CANT_STOP, dependencies[counter].lpDisplayName);
  194. }
  195. }
  196. }
  197. if(result) result = ControlService(serviceHandle, SERVICE_CONTROL_STOP, (LPSERVICE_STATUS)&ssp);
  198. HeapFree(GetProcessHeap(), 0, dependencies);
  199. return result;
  200. }
  201. static BOOL net_service(int operation, const WCHAR* service_name)
  202. {
  203. SC_HANDLE SCManager, serviceHandle;
  204. BOOL result = FALSE;
  205. WCHAR service_display_name[4096];
  206. DWORD buffer_size;
  207. SCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
  208. if(!SCManager)
  209. {
  210. output_string(STRING_NO_SCM);
  211. return FALSE;
  212. }
  213. serviceHandle = OpenServiceW(SCManager, service_name, SC_MANAGER_ALL_ACCESS);
  214. if(!serviceHandle)
  215. {
  216. output_string(STRING_NO_SVCHANDLE);
  217. CloseServiceHandle(SCManager);
  218. return FALSE;
  219. }
  220. buffer_size = ARRAY_SIZE(service_display_name);
  221. GetServiceDisplayNameW(SCManager, service_name, service_display_name, &buffer_size);
  222. if (!service_display_name[0]) lstrcpyW(service_display_name, service_name);
  223. switch(operation)
  224. {
  225. case NET_START:
  226. output_string(STRING_START_SVC, service_display_name);
  227. result = StartServiceW(serviceHandle, 0, NULL);
  228. if(result) output_string(STRING_START_SVC_SUCCESS, service_display_name);
  229. else
  230. {
  231. if (!output_error_string(GetLastError()))
  232. output_string(STRING_START_SVC_FAIL, service_display_name);
  233. }
  234. break;
  235. case NET_STOP:
  236. output_string(STRING_STOP_SVC, service_display_name);
  237. result = StopService(SCManager, serviceHandle);
  238. if(result) output_string(STRING_STOP_SVC_SUCCESS, service_display_name);
  239. else
  240. {
  241. if (!output_error_string(GetLastError()))
  242. output_string(STRING_STOP_SVC_FAIL, service_display_name);
  243. }
  244. break;
  245. }
  246. CloseServiceHandle(serviceHandle);
  247. CloseServiceHandle(SCManager);
  248. return result;
  249. }
  250. static BOOL arg_is(const WCHAR* str1, const WCHAR* str2)
  251. {
  252. return CompareStringW(LOCALE_USER_DEFAULT, NORM_IGNORECASE, str1, -1, str2, -1) == CSTR_EQUAL;
  253. }
  254. int __cdecl wmain(int argc, const WCHAR* argv[])
  255. {
  256. if (argc < 2)
  257. {
  258. output_string(STRING_USAGE);
  259. return 1;
  260. }
  261. if(arg_is(argv[1], L"help"))
  262. {
  263. if(argc > 3)
  264. {
  265. output_string(STRING_USAGE);
  266. return 1;
  267. }
  268. if(argc == 2)
  269. output_string(STRING_USAGE);
  270. else if(arg_is(argv[2], L"start"))
  271. output_string(STRING_START_USAGE);
  272. else if(arg_is(argv[2], L"stop"))
  273. output_string(STRING_STOP_USAGE);
  274. else
  275. output_string(STRING_USAGE);
  276. }
  277. else if(arg_is(argv[1], L"start"))
  278. {
  279. if(argc > 3)
  280. {
  281. output_string(STRING_START_USAGE);
  282. return 1;
  283. }
  284. if (argc == 2)
  285. {
  286. if (!net_enum_services())
  287. return 1;
  288. }
  289. else if(arg_is(argv[2], L"/help"))
  290. output_string(STRING_START_USAGE);
  291. else if(!net_service(NET_START, argv[2]))
  292. return 1;
  293. }
  294. else if(arg_is(argv[1], L"stop"))
  295. {
  296. if(argc != 3)
  297. {
  298. output_string(STRING_STOP_USAGE);
  299. return 1;
  300. }
  301. if(arg_is(argv[2], L"/help"))
  302. output_string(STRING_STOP_USAGE);
  303. else if(!net_service(NET_STOP, argv[2]))
  304. return 1;
  305. }
  306. else if(arg_is(argv[1], L"use"))
  307. {
  308. if(!net_use(argc, argv)) return 1;
  309. }
  310. else
  311. output_string(STRING_USAGE);
  312. return 0;
  313. }