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.

466 lines
14 KiB

  1. /*++
  2. Copyright (c) 1992-1993 Microsoft Corporation
  3. Module Name:
  4. dbgctrl.c
  5. Abstract:
  6. This module implements the NtDebugControl service
  7. Author:
  8. Chuck Lenzmeier (chuckl) 2-Dec-1992
  9. Environment:
  10. Kernel mode only.
  11. Revision History:
  12. --*/
  13. #include "exp.h"
  14. #pragma hdrstop
  15. #include "kdp.h"
  16. #if defined(ALLOC_PRAGMA)
  17. #pragma alloc_text(PAGE, NtSystemDebugControl)
  18. #endif
  19. NTSTATUS
  20. NtSystemDebugControl (
  21. IN SYSDBG_COMMAND Command,
  22. IN PVOID InputBuffer,
  23. IN ULONG InputBufferLength,
  24. OUT PVOID OutputBuffer,
  25. IN ULONG OutputBufferLength,
  26. OUT PULONG ReturnLength OPTIONAL
  27. )
  28. /*++
  29. Routine Description:
  30. This function controls the system debugger.
  31. Arguments:
  32. Command - The command to be executed. One of the following:
  33. SysDbgQueryTraceInformation
  34. SysDbgSetTracepoint
  35. SysDbgSetSpecialCall
  36. SysDbgClearSpecialCalls
  37. SysDbgQuerySpecialCalls
  38. InputBuffer - A pointer to a buffer describing the input data for
  39. the request, if any. The structure of this buffer varies
  40. depending upon Command.
  41. InputBufferLength - The length in bytes of InputBuffer.
  42. OutputBuffer - A pointer to a buffer that is to receive the output
  43. data for the request, if any. The structure of this buffer
  44. varies depending upon Command.
  45. OutputBufferLength - The length in bytes of OutputBuffer.
  46. ReturnLength - A optional pointer to a ULONG that is to receive the
  47. output data length for the request.
  48. Return Value:
  49. Returns one of the following status codes:
  50. STATUS_SUCCESS - normal, successful completion.
  51. STATUS_INVALID_INFO_CLASS - The Command parameter did not
  52. specify a valid value.
  53. STATUS_INFO_LENGTH_MISMATCH - The value of the Length field in the
  54. Parameters buffer was not correct.
  55. STATUS_ACCESS_VIOLATION - Either the Parameters buffer pointer
  56. or a pointer within the Parameters buffer specified an
  57. invalid address.
  58. STATUS_INSUFFICIENT_RESOURCES - Insufficient system resources exist
  59. for this request to complete.
  60. --*/
  61. {
  62. NTSTATUS status = STATUS_SUCCESS;
  63. ULONG length = 0;
  64. KPROCESSOR_MODE PreviousMode;
  65. PVOID LockedBuffer = NULL;
  66. PVOID LockVariable = NULL;
  67. PreviousMode = KeGetPreviousMode();
  68. if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode)) {
  69. return STATUS_ACCESS_DENIED;
  70. }
  71. //
  72. // Operate within a try block in order to catch errors.
  73. //
  74. try {
  75. //
  76. // Probe input and output buffers, if previous mode is not
  77. // kernel.
  78. //
  79. if ( PreviousMode != KernelMode ) {
  80. if ( InputBufferLength != 0 ) {
  81. ProbeForRead( InputBuffer, InputBufferLength, sizeof(ULONG) );
  82. }
  83. if ( OutputBufferLength != 0 ) {
  84. ProbeForWrite( OutputBuffer, OutputBufferLength, sizeof(ULONG) );
  85. }
  86. if ( ARGUMENT_PRESENT(ReturnLength) ) {
  87. ProbeForWriteUlong( ReturnLength );
  88. }
  89. }
  90. //
  91. // Switch on the command code.
  92. //
  93. switch ( Command ) {
  94. #if i386
  95. case SysDbgQueryTraceInformation:
  96. status = KdGetTraceInformation(
  97. OutputBuffer,
  98. OutputBufferLength,
  99. &length
  100. );
  101. break;
  102. case SysDbgSetTracepoint:
  103. if ( InputBufferLength != sizeof(DBGKD_MANIPULATE_STATE64) ) {
  104. return STATUS_INFO_LENGTH_MISMATCH;
  105. }
  106. KdSetInternalBreakpoint( InputBuffer );
  107. break;
  108. case SysDbgSetSpecialCall:
  109. if ( InputBufferLength != sizeof(PVOID) ) {
  110. return STATUS_INFO_LENGTH_MISMATCH;
  111. }
  112. KdSetSpecialCall( InputBuffer, NULL );
  113. break;
  114. case SysDbgClearSpecialCalls:
  115. KdClearSpecialCalls( );
  116. break;
  117. case SysDbgQuerySpecialCalls:
  118. status = KdQuerySpecialCalls(
  119. OutputBuffer,
  120. OutputBufferLength,
  121. &length
  122. );
  123. break;
  124. #endif
  125. case SysDbgBreakPoint:
  126. if (KdDebuggerEnabled) {
  127. DbgBreakPointWithStatus(DBG_STATUS_DEBUG_CONTROL);
  128. } else {
  129. status = STATUS_UNSUCCESSFUL;
  130. }
  131. break;
  132. case SysDbgQueryVersion:
  133. if (OutputBufferLength != sizeof(DBGKD_GET_VERSION64)) {
  134. return STATUS_INFO_LENGTH_MISMATCH;
  135. }
  136. KdpSysGetVersion((PDBGKD_GET_VERSION64)OutputBuffer);
  137. status = STATUS_SUCCESS;
  138. break;
  139. case SysDbgReadVirtual:
  140. if (InputBufferLength != sizeof(SYSDBG_VIRTUAL)) {
  141. return STATUS_INFO_LENGTH_MISMATCH;
  142. }
  143. {
  144. PSYSDBG_VIRTUAL Cmd = (PSYSDBG_VIRTUAL)InputBuffer;
  145. status = ExLockUserBuffer(Cmd->Buffer,
  146. Cmd->Request,
  147. &LockedBuffer,
  148. &LockVariable);
  149. if (!NT_SUCCESS(status)) {
  150. break;
  151. }
  152. status = KdpCopyMemoryChunks((ULONG_PTR)Cmd->Address,
  153. LockedBuffer,
  154. Cmd->Request, 0,
  155. 0,
  156. &length);
  157. }
  158. break;
  159. case SysDbgWriteVirtual:
  160. if (InputBufferLength != sizeof(SYSDBG_VIRTUAL)) {
  161. return STATUS_INFO_LENGTH_MISMATCH;
  162. }
  163. {
  164. PSYSDBG_VIRTUAL Cmd = (PSYSDBG_VIRTUAL)InputBuffer;
  165. status = ExLockUserBuffer(Cmd->Buffer,
  166. Cmd->Request,
  167. &LockedBuffer,
  168. &LockVariable);
  169. if (!NT_SUCCESS(status)) {
  170. break;
  171. }
  172. status = KdpCopyMemoryChunks((ULONG_PTR)Cmd->Address,
  173. LockedBuffer,
  174. Cmd->Request, 0,
  175. MMDBG_COPY_WRITE,
  176. &length);
  177. }
  178. break;
  179. case SysDbgReadPhysical:
  180. if (InputBufferLength != sizeof(SYSDBG_PHYSICAL)) {
  181. return STATUS_INFO_LENGTH_MISMATCH;
  182. }
  183. {
  184. PSYSDBG_PHYSICAL Cmd = (PSYSDBG_PHYSICAL)InputBuffer;
  185. status = ExLockUserBuffer(Cmd->Buffer,
  186. Cmd->Request,
  187. &LockedBuffer,
  188. &LockVariable);
  189. if (!NT_SUCCESS(status)) {
  190. break;
  191. }
  192. status = KdpCopyMemoryChunks(Cmd->Address.QuadPart,
  193. LockedBuffer,
  194. Cmd->Request, 0,
  195. MMDBG_COPY_PHYSICAL,
  196. &length);
  197. }
  198. break;
  199. case SysDbgWritePhysical:
  200. if (InputBufferLength != sizeof(SYSDBG_PHYSICAL)) {
  201. return STATUS_INFO_LENGTH_MISMATCH;
  202. }
  203. {
  204. PSYSDBG_PHYSICAL Cmd = (PSYSDBG_PHYSICAL)InputBuffer;
  205. status = ExLockUserBuffer(Cmd->Buffer,
  206. Cmd->Request,
  207. &LockedBuffer,
  208. &LockVariable);
  209. if (!NT_SUCCESS(status)) {
  210. break;
  211. }
  212. status = KdpCopyMemoryChunks(Cmd->Address.QuadPart,
  213. LockedBuffer,
  214. Cmd->Request, 0,
  215. MMDBG_COPY_WRITE |
  216. MMDBG_COPY_PHYSICAL,
  217. &length);
  218. }
  219. break;
  220. case SysDbgReadControlSpace:
  221. if (InputBufferLength != sizeof(SYSDBG_CONTROL_SPACE)) {
  222. return STATUS_INFO_LENGTH_MISMATCH;
  223. }
  224. {
  225. PSYSDBG_CONTROL_SPACE Cmd = (PSYSDBG_CONTROL_SPACE)InputBuffer;
  226. status = ExLockUserBuffer(Cmd->Buffer,
  227. Cmd->Request,
  228. &LockedBuffer,
  229. &LockVariable);
  230. if (!NT_SUCCESS(status)) {
  231. break;
  232. }
  233. status = KdpSysReadControlSpace(Cmd->Processor,
  234. Cmd->Address, LockedBuffer,
  235. Cmd->Request, &length);
  236. }
  237. break;
  238. case SysDbgWriteControlSpace:
  239. if (InputBufferLength != sizeof(SYSDBG_CONTROL_SPACE)) {
  240. return STATUS_INFO_LENGTH_MISMATCH;
  241. }
  242. {
  243. PSYSDBG_CONTROL_SPACE Cmd = (PSYSDBG_CONTROL_SPACE)InputBuffer;
  244. status = ExLockUserBuffer(Cmd->Buffer,
  245. Cmd->Request,
  246. &LockedBuffer,
  247. &LockVariable);
  248. if (!NT_SUCCESS(status)) {
  249. break;
  250. }
  251. status = KdpSysWriteControlSpace(Cmd->Processor,
  252. Cmd->Address, LockedBuffer,
  253. Cmd->Request, &length);
  254. }
  255. break;
  256. case SysDbgReadIoSpace:
  257. if (InputBufferLength != sizeof(SYSDBG_IO_SPACE)) {
  258. return STATUS_INFO_LENGTH_MISMATCH;
  259. }
  260. {
  261. PSYSDBG_IO_SPACE Cmd = (PSYSDBG_IO_SPACE)InputBuffer;
  262. status = KdpSysReadIoSpace(Cmd->InterfaceType,
  263. Cmd->BusNumber,
  264. Cmd->AddressSpace,
  265. Cmd->Address, Cmd->Buffer,
  266. Cmd->Request, &length);
  267. }
  268. break;
  269. case SysDbgWriteIoSpace:
  270. if (InputBufferLength != sizeof(SYSDBG_IO_SPACE)) {
  271. return STATUS_INFO_LENGTH_MISMATCH;
  272. }
  273. {
  274. PSYSDBG_IO_SPACE Cmd = (PSYSDBG_IO_SPACE)InputBuffer;
  275. status = KdpSysWriteIoSpace(Cmd->InterfaceType,
  276. Cmd->BusNumber,
  277. Cmd->AddressSpace,
  278. Cmd->Address, Cmd->Buffer,
  279. Cmd->Request, &length);
  280. }
  281. break;
  282. case SysDbgReadMsr:
  283. if (InputBufferLength != sizeof(SYSDBG_MSR)) {
  284. return STATUS_INFO_LENGTH_MISMATCH;
  285. }
  286. {
  287. PSYSDBG_MSR Cmd = (PSYSDBG_MSR)InputBuffer;
  288. status = KdpSysReadMsr(Cmd->Msr, &Cmd->Data);
  289. }
  290. break;
  291. case SysDbgWriteMsr:
  292. if (InputBufferLength != sizeof(SYSDBG_MSR)) {
  293. return STATUS_INFO_LENGTH_MISMATCH;
  294. }
  295. {
  296. PSYSDBG_MSR Cmd = (PSYSDBG_MSR)InputBuffer;
  297. status = KdpSysWriteMsr(Cmd->Msr, &Cmd->Data);
  298. }
  299. break;
  300. case SysDbgReadBusData:
  301. if (InputBufferLength != sizeof(SYSDBG_BUS_DATA)) {
  302. return STATUS_INFO_LENGTH_MISMATCH;
  303. }
  304. {
  305. PSYSDBG_BUS_DATA Cmd = (PSYSDBG_BUS_DATA)InputBuffer;
  306. status = KdpSysReadBusData(Cmd->BusDataType,
  307. Cmd->BusNumber, Cmd->SlotNumber,
  308. Cmd->Address, Cmd->Buffer,
  309. Cmd->Request, &length);
  310. }
  311. break;
  312. case SysDbgWriteBusData:
  313. if (InputBufferLength != sizeof(SYSDBG_BUS_DATA)) {
  314. return STATUS_INFO_LENGTH_MISMATCH;
  315. }
  316. {
  317. PSYSDBG_BUS_DATA Cmd = (PSYSDBG_BUS_DATA)InputBuffer;
  318. status = KdpSysWriteBusData(Cmd->BusDataType,
  319. Cmd->BusNumber, Cmd->SlotNumber,
  320. Cmd->Address, Cmd->Buffer,
  321. Cmd->Request, &length);
  322. }
  323. break;
  324. case SysDbgCheckLowMemory:
  325. status = KdpSysCheckLowMemory();
  326. break;
  327. default:
  328. //
  329. // Invalid Command.
  330. //
  331. status = STATUS_INVALID_INFO_CLASS;
  332. }
  333. if ( ARGUMENT_PRESENT(ReturnLength) ) {
  334. *ReturnLength = length;
  335. }
  336. }
  337. except ( EXCEPTION_EXECUTE_HANDLER ) {
  338. status = GetExceptionCode();
  339. }
  340. if (LockedBuffer) {
  341. ExUnlockUserBuffer(LockVariable);
  342. }
  343. return status;
  344. } // NtSystemDebugControl