Source code of Windows XP (NT5)
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.

416 lines
11 KiB

  1. /****************************************************************************
  2. Copyright (c) Microsoft Corporation 1997
  3. All rights reserved
  4. ***************************************************************************/
  5. #include <nt.h>
  6. #include <ntrtl.h>
  7. #include <nturtl.h>
  8. #include <windows.h>
  9. #include <assert.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include <time.h>
  14. #include <winsock2.h>
  15. #include <ntexapi.h>
  16. #include <devioctl.h>
  17. #include <stdlib.h>
  18. #include <rccxport.h>
  19. #include "rcclib.h"
  20. #include "error.h"
  21. //
  22. // Defines
  23. //
  24. #define MAX_REQUEST_SIZE (sizeof(RCC_REQUEST) + sizeof(DWORD))
  25. //
  26. // Global variables
  27. //
  28. ULONG GlobalBufferCurrentSize;
  29. char *GlobalBuffer;
  30. //
  31. // Prototypes
  32. //
  33. DWORD
  34. RCCNetReportEventA(
  35. DWORD EventID,
  36. DWORD EventType,
  37. DWORD NumStrings,
  38. DWORD DataLength,
  39. LPSTR *Strings,
  40. LPVOID Data
  41. );
  42. //
  43. //
  44. // Main routine
  45. //
  46. //
  47. int
  48. __cdecl
  49. main(
  50. int argc,
  51. char *argv[]
  52. )
  53. {
  54. NTSTATUS Status;
  55. HANDLE RCCHandle;
  56. DWORD Error;
  57. DWORD BytesReturned;
  58. DWORD ProcessId;
  59. PRCC_REQUEST Request;
  60. PRCC_RESPONSE Response;
  61. char *NewBuffer;
  62. DWORD ThisProcessId;
  63. DWORD MemoryLimit;
  64. //
  65. // Init the library routines
  66. //
  67. Error = RCCLibInit(&GlobalBuffer, &GlobalBufferCurrentSize);
  68. if (Error != ERROR_SUCCESS) {
  69. return -1;
  70. }
  71. //
  72. // Allocate memory for sending responses
  73. //
  74. Request = LocalAlloc(LPTR, MAX_REQUEST_SIZE);
  75. if (Request == NULL) {
  76. //
  77. // Log an error!
  78. //
  79. RCCLibExit(GlobalBuffer, GlobalBufferCurrentSize);
  80. RCCNetReportEventA(ERROR_RCCNET_INITIAL_ALLOC_FAILED, EVENTLOG_ERROR_TYPE, 0, 0, NULL, NULL);
  81. return -1;
  82. }
  83. //
  84. // Remember our process ID, so people cannot kill us.
  85. //
  86. ThisProcessId = GetCurrentProcessId();
  87. //
  88. // Open the Remote Command Console driver
  89. //
  90. RCCHandle = CreateFile("\\\\.\\RCC",
  91. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  92. FILE_SHARE_READ | FILE_SHARE_WRITE,
  93. NULL,
  94. OPEN_EXISTING, // create disposition.
  95. 0,
  96. 0
  97. );
  98. if (RCCHandle == INVALID_HANDLE_VALUE) {
  99. Error = GetLastError();
  100. RCCNetReportEventA(ERROR_RCCNET_OPEN_RCCDRIVER_FAILED,
  101. EVENTLOG_ERROR_TYPE,
  102. 0,
  103. 0,
  104. NULL,
  105. NULL
  106. );
  107. LocalFree(GlobalBuffer);
  108. LocalFree(Request);
  109. return -1;
  110. }
  111. while (1) {
  112. //
  113. // Send down an IOCTL for receiving data
  114. //
  115. if (!DeviceIoControl(RCCHandle,
  116. CTL_CODE(FILE_DEVICE_NETWORK, 0x1, METHOD_NEITHER, FILE_ANY_ACCESS),
  117. NULL,
  118. 0,
  119. Request,
  120. MAX_REQUEST_SIZE,
  121. &BytesReturned,
  122. NULL
  123. )) {
  124. Error = GetLastError();
  125. //
  126. // Log an error here!
  127. //
  128. RCCNetReportEventA(ERROR_RCCNET_RCV_FAILED, EVENTLOG_ERROR_TYPE, 0, sizeof(DWORD), NULL, &Error);
  129. continue;
  130. }
  131. //
  132. // It completed, so we have data in the buffer - verify it and process the message.
  133. //
  134. Response = (PRCC_RESPONSE)GlobalBuffer;
  135. Response->CommandSequenceNumber = Request->CommandSequenceNumber;
  136. Response->CommandCode = Request->CommandCode;
  137. switch (Request->CommandCode) {
  138. case RCC_CMD_TLIST:
  139. RetryTList:
  140. Response->Error = RCCLibGetTListInfo((PRCC_RSP_TLIST)(&(Response->Data[0])),
  141. GlobalBufferCurrentSize - sizeof(RCC_RESPONSE) + 1,
  142. &(Response->DataLength)
  143. );
  144. //
  145. // Try to get more memory, if not available, then just fail without out of memory error.
  146. //
  147. if (Response->Error == ERROR_OUTOFMEMORY) {
  148. Error = RCCLibIncreaseMemory(&GlobalBuffer, &GlobalBufferCurrentSize);
  149. if (Error == ERROR_SUCCESS) {
  150. goto RetryTList;
  151. }
  152. Response->DataLength = 0;
  153. }
  154. break;
  155. case RCC_CMD_KILL:
  156. RtlCopyMemory(&ProcessId, &(Request->Options[0]), sizeof(DWORD));
  157. if (ProcessId != ThisProcessId) {
  158. Response->Error = RCCLibKillProcess(ProcessId);
  159. } else {
  160. Response->Error = ERROR_INVALID_PARAMETER;
  161. }
  162. Response->DataLength = 0;
  163. break;
  164. case RCC_CMD_REBOOT:
  165. //
  166. // Send back an acknowledgement that we got the command before starting the reboot.
  167. //
  168. Response->Error = ERROR_SUCCESS;
  169. Response->DataLength = 0;
  170. break;
  171. case RCC_CMD_LOWER:
  172. RtlCopyMemory(&ProcessId, &(Request->Options[0]), sizeof(DWORD));
  173. if (ProcessId != ThisProcessId) {
  174. Response->Error = RCCLibLowerProcessPriority(ProcessId);
  175. } else {
  176. Response->Error = ERROR_INVALID_PARAMETER;
  177. }
  178. Response->DataLength = 0;
  179. break;
  180. case RCC_CMD_LIMIT:
  181. RtlCopyMemory(&ProcessId, &(Request->Options[0]), sizeof(DWORD));
  182. RtlCopyMemory(&MemoryLimit, &(Request->Options[sizeof(DWORD)]), sizeof(DWORD));
  183. if (ProcessId != ThisProcessId) {
  184. Response->Error = RCCLibLimitProcessMemory(ProcessId, MemoryLimit);
  185. } else {
  186. Response->Error = ERROR_INVALID_PARAMETER;
  187. }
  188. //
  189. // Send back an acknowledgement that we got the command before starting the reboot.
  190. //
  191. Response->Error = ERROR_SUCCESS;
  192. Response->DataLength = 0;
  193. break;
  194. case RCC_CMD_CRASHDUMP:
  195. Response->DataLength = 0;
  196. break;
  197. default:
  198. Response->Error = ERROR_INVALID_PARAMETER;
  199. Response->DataLength = 0;
  200. }
  201. //
  202. // Send back the response
  203. //
  204. if (!DeviceIoControl(RCCHandle,
  205. CTL_CODE(FILE_DEVICE_NETWORK, 0x2, METHOD_NEITHER, FILE_ANY_ACCESS),
  206. Response,
  207. Response->DataLength + sizeof(RCC_RESPONSE) - 1,
  208. NULL,
  209. 0,
  210. &BytesReturned,
  211. NULL
  212. )) {
  213. Error = GetLastError();
  214. //
  215. // Log an error here!
  216. //
  217. RCCNetReportEventA(ERROR_RCCNET_SEND_FAILED, EVENTLOG_ERROR_TYPE, 0, sizeof(DWORD), NULL, &Error);
  218. }
  219. //
  220. // If it was a reboot command, do that now.
  221. //
  222. if (Request->CommandCode == RCC_CMD_REBOOT) {
  223. NtShutdownSystem(ShutdownReboot);
  224. //
  225. // If we get here, then there was an error of some sort...
  226. //
  227. }
  228. //
  229. // If it was a bugcheck command, do that now.
  230. //
  231. if (Request->CommandCode == RCC_CMD_CRASHDUMP) {
  232. if (!DeviceIoControl(RCCHandle,
  233. CTL_CODE(FILE_DEVICE_NETWORK, 0x3, METHOD_NEITHER, FILE_ANY_ACCESS),
  234. NULL,
  235. 0,
  236. NULL,
  237. 0,
  238. &BytesReturned,
  239. NULL
  240. )) {
  241. Error = GetLastError();
  242. //
  243. // Log an error here!
  244. //
  245. RCCNetReportEventA(ERROR_RCCNET_SEND_FAILED, EVENTLOG_ERROR_TYPE, 0, sizeof(DWORD), NULL, &Error);
  246. }
  247. }
  248. }
  249. LocalFree(Request);
  250. return 1;
  251. }
  252. DWORD
  253. RCCNetReportEventA(
  254. DWORD EventID,
  255. DWORD EventType,
  256. DWORD NumStrings,
  257. DWORD DataLength,
  258. LPSTR *Strings,
  259. LPVOID Data
  260. )
  261. /*++
  262. Routine Description:
  263. This function writes the specified (EventID) log at the end of the
  264. eventlog.
  265. Arguments:
  266. EventID - The specific event identifier. This identifies the
  267. message that goes with this event.
  268. EventType - Specifies the type of event being logged. This
  269. parameter can have one of the following
  270. values:
  271. Value Meaning
  272. EVENTLOG_ERROR_TYPE Error event
  273. EVENTLOG_WARNING_TYPE Warning event
  274. EVENTLOG_INFORMATION_TYPE Information event
  275. NumStrings - Specifies the number of strings that are in the array
  276. at 'Strings'. A value of zero indicates no strings
  277. are present.
  278. DataLength - Specifies the number of bytes of event-specific raw
  279. (binary) data to write to the log. If cbData is
  280. zero, no event-specific data is present.
  281. Strings - Points to a buffer containing an array of null-terminated
  282. strings that are merged into the message before
  283. displaying to the user. This parameter must be a valid
  284. pointer (or NULL), even if cStrings is zero.
  285. Data - Buffer containing the raw data. This parameter must be a
  286. valid pointer (or NULL), even if cbData is zero.
  287. Return Value:
  288. Returns the WIN32 extended error obtained by GetLastError().
  289. NOTE : This function works slow since it calls the open and close
  290. eventlog source everytime.
  291. --*/
  292. {
  293. HANDLE EventlogHandle;
  294. DWORD ReturnCode;
  295. //
  296. // open eventlog section.
  297. //
  298. EventlogHandle = RegisterEventSourceW(NULL, L"RCCNet");
  299. if (EventlogHandle == NULL) {
  300. ReturnCode = GetLastError();
  301. goto Cleanup;
  302. }
  303. //
  304. // Log the error code specified
  305. //
  306. if(!ReportEventA(EventlogHandle,
  307. (WORD)EventType,
  308. 0, // event category
  309. EventID,
  310. NULL,
  311. (WORD)NumStrings,
  312. DataLength,
  313. Strings,
  314. Data
  315. )) {
  316. ReturnCode = GetLastError();
  317. goto Cleanup;
  318. }
  319. ReturnCode = ERROR_SUCCESS;
  320. Cleanup:
  321. if (EventlogHandle != NULL) {
  322. DeregisterEventSource(EventlogHandle);
  323. }
  324. return ReturnCode;
  325. }