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.

958 lines
22 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. api.c
  5. Abstract:
  6. This module implements the boot bebugger platform independent remote APIs.
  7. Author:
  8. Mark Lucovsky (markl) 31-Aug-1990
  9. Revision History:
  10. --*/
  11. #include "bd.h"
  12. VOID
  13. BdGetVersion(
  14. IN PDBGKD_MANIPULATE_STATE64 m
  15. )
  16. /*++
  17. Routine Description:
  18. This function returns to the caller a general information packet
  19. that contains useful information to a debugger. This packet is also
  20. used for a debugger to determine if the writebreakpointex and
  21. readbreakpointex apis are available.
  22. Arguments:
  23. m - Supplies the state manipulation message.
  24. Return Value:
  25. None.
  26. --*/
  27. {
  28. STRING messageHeader;
  29. messageHeader.Length = sizeof(*m);
  30. messageHeader.Buffer = (PCHAR)m;
  31. RtlZeroMemory(&m->u.GetVersion64, sizeof(m->u.GetVersion64));
  32. //
  33. // the current build number
  34. //
  35. // - 4 - tells the debugger this is a "special" OS - the boot loader.
  36. // The boot loader has a lot of special cases associated with it, like
  37. // the lack of the DebuggerDataBlock, lack of ntoskrnl, etc ...
  38. //
  39. m->u.GetVersion64.MinorVersion = (short)NtBuildNumber;
  40. m->u.GetVersion64.MajorVersion = 0x400 |
  41. (short)((NtBuildNumber >> 28) & 0xFFFFFFF);
  42. //
  43. // Kd protocol version number.
  44. //
  45. m->u.GetVersion64.ProtocolVersion = DBGKD_64BIT_PROTOCOL_VERSION2;
  46. m->u.GetVersion64.Flags = DBGKD_VERS_FLAG_DATA;
  47. #if defined(_M_IX86)
  48. m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_I386;
  49. #elif defined(_M_MRX000)
  50. m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_R4000;
  51. #elif defined(_M_ALPHA)
  52. m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_ALPHA;
  53. #elif defined(_M_PPC)
  54. m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_POWERPC;
  55. #elif defined(_IA64_)
  56. m->u.GetVersion64.MachineType = IMAGE_FILE_MACHINE_IA64;
  57. m->u.GetVersion64.Flags |= DBGKD_VERS_FLAG_PTR64;
  58. #else
  59. #error( "unknown target machine" );
  60. #endif
  61. m->u.GetVersion64.MaxPacketType = (UCHAR)(PACKET_TYPE_KD_FILE_IO + 1);;
  62. m->u.GetVersion64.MaxStateChange = (UCHAR)(DbgKdLoadSymbolsStateChange + 1);;
  63. m->u.GetVersion64.MaxManipulate = (UCHAR)(DbgKdSetBusDataApi + 1);
  64. //
  65. // address of the loader table
  66. //
  67. m->u.GetVersion64.PsLoadedModuleList = 0;
  68. m->u.GetVersion64.KernBase = 0;
  69. //m->u.GetVersion64.ThCallbackStack = 0;
  70. //m->u.GetVersion64.KiCallUserMode = 0;
  71. //m->u.GetVersion64.KeUserCallbackDispatcher = 0;
  72. //m->u.GetVersion64.NextCallback = 0;
  73. #if defined(_X86_)
  74. //m->u.GetVersion64.FramePointer = 0;
  75. #endif
  76. //m->u.GetVersion64.BreakpointWithStatus = 0;
  77. m->u.GetVersion64.DebuggerDataList = 0;
  78. //
  79. // the usual stuff
  80. //
  81. m->ReturnStatus = STATUS_SUCCESS;
  82. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  83. &messageHeader,
  84. NULL);
  85. return;
  86. }
  87. VOID
  88. BdGetContext(
  89. IN PDBGKD_MANIPULATE_STATE64 m,
  90. IN PSTRING AdditionalData,
  91. IN PCONTEXT Context
  92. )
  93. /*++
  94. Routine Description:
  95. This function is called in response of a get context state
  96. manipulation message. Its function is to return the current
  97. context.
  98. Arguments:
  99. m - Supplies the state manipulation message.
  100. AdditionalData - Supplies any additional data for the message.
  101. Context - Supplies the current context.
  102. Return Value:
  103. None.
  104. --*/
  105. {
  106. PDBGKD_GET_CONTEXT a = &m->u.GetContext;
  107. STRING MessageHeader;
  108. m->ReturnStatus = STATUS_SUCCESS;
  109. AdditionalData->Length = sizeof(CONTEXT);
  110. BdCopyMemory(AdditionalData->Buffer, (PCHAR)Context, sizeof(CONTEXT));
  111. //
  112. // Send reply packet.
  113. //
  114. MessageHeader.Length = sizeof(*m);
  115. MessageHeader.Buffer = (PCHAR)m;
  116. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  117. &MessageHeader,
  118. AdditionalData);
  119. return;
  120. }
  121. VOID
  122. BdSetContext(
  123. IN PDBGKD_MANIPULATE_STATE64 m,
  124. IN PSTRING AdditionalData,
  125. IN PCONTEXT Context
  126. )
  127. /*++
  128. Routine Description:
  129. This function is called in response of a set context state
  130. manipulation message. Its function is set the current
  131. context.
  132. Arguments:
  133. m - Supplies the state manipulation message.
  134. AdditionalData - Supplies any additional data for the message.
  135. Context - Supplies the current context.
  136. Return Value:
  137. None.
  138. --*/
  139. {
  140. PDBGKD_SET_CONTEXT a = &m->u.SetContext;
  141. STRING MessageHeader;
  142. m->ReturnStatus = STATUS_SUCCESS;
  143. BdCopyMemory((PCHAR)Context, AdditionalData->Buffer, sizeof(CONTEXT));
  144. //
  145. // Send reply packet.
  146. //
  147. MessageHeader.Length = sizeof(*m);
  148. MessageHeader.Buffer = (PCHAR)m;
  149. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  150. &MessageHeader,
  151. NULL);
  152. }
  153. VOID
  154. BdReadVirtualMemory(
  155. IN PDBGKD_MANIPULATE_STATE64 m,
  156. IN PSTRING AdditionalData,
  157. IN PCONTEXT Context
  158. )
  159. /*++
  160. Routine Description:
  161. This function is called in response to a read virtual memory 32-bit
  162. state manipulation message. Its function is to read virtual memory
  163. and return.
  164. Arguments:
  165. m - Supplies a pointer to the state manipulation message.
  166. AdditionalData - Supplies a pointer to a descriptor for the data to read.
  167. Context - Supplies a pointer to the current context.
  168. Return Value:
  169. None.
  170. --*/
  171. {
  172. ULONG Length;
  173. STRING MessageHeader;
  174. //
  175. // Trim the transfer count to fit in a single message.
  176. //
  177. Length = min(m->u.ReadMemory.TransferCount,
  178. PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64));
  179. //
  180. // Move the data to the destination buffer.
  181. //
  182. AdditionalData->Length = (USHORT)BdMoveMemory((PCHAR)AdditionalData->Buffer,
  183. (PCHAR)m->u.ReadMemory.TargetBaseAddress,
  184. Length);
  185. //
  186. // If all the data is read, then return a success status. Otherwise,
  187. // return an unsuccessful status.
  188. //
  189. m->ReturnStatus = STATUS_SUCCESS;
  190. if (Length != AdditionalData->Length) {
  191. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  192. }
  193. //
  194. // Set the actual number of bytes read, initialize the message header,
  195. // and send the reply packet to the host debugger.
  196. //
  197. m->u.ReadMemory.ActualBytesRead = AdditionalData->Length;
  198. MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
  199. MessageHeader.Buffer = (PCHAR)m;
  200. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  201. &MessageHeader,
  202. AdditionalData);
  203. return;
  204. }
  205. VOID
  206. BdWriteVirtualMemory(
  207. IN PDBGKD_MANIPULATE_STATE64 m,
  208. IN PSTRING AdditionalData,
  209. IN PCONTEXT Context
  210. )
  211. /*++
  212. Routine Description:
  213. This function is called in response of a write virtual memory 32-bit
  214. state manipulation message. Its function is to write virtual memory
  215. and return.
  216. Arguments:
  217. m - Supplies a pointer to the state manipulation message.
  218. AdditionalData - Supplies a pointer to a descriptor for the data to write.
  219. Context - Supplies a pointer to the current context.
  220. Return Value:
  221. None.
  222. --*/
  223. {
  224. ULONG Length;
  225. STRING MessageHeader;
  226. //
  227. // Move the data to the destination buffer.
  228. //
  229. Length = BdMoveMemory((PCHAR)m->u.WriteMemory.TargetBaseAddress,
  230. (PCHAR)AdditionalData->Buffer,
  231. AdditionalData->Length);
  232. //
  233. // If all the data is written, then return a success status. Otherwise,
  234. // return an unsuccessful status.
  235. //
  236. m->ReturnStatus = STATUS_SUCCESS;
  237. if (Length != AdditionalData->Length) {
  238. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  239. }
  240. //
  241. // Set the actual number of bytes written, initialize the message header,
  242. // and send the reply packet to the host debugger.
  243. //
  244. m->u.WriteMemory.ActualBytesWritten = Length;
  245. MessageHeader.Length = sizeof(DBGKD_MANIPULATE_STATE64);
  246. MessageHeader.Buffer = (PCHAR)m;
  247. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  248. &MessageHeader,
  249. NULL);
  250. return;
  251. }
  252. VOID
  253. BdWriteBreakpoint(
  254. IN PDBGKD_MANIPULATE_STATE64 m,
  255. IN PSTRING AdditionalData,
  256. IN PCONTEXT Context
  257. )
  258. /*++
  259. Routine Description:
  260. This function is called in response of a write breakpoint state
  261. manipulation message. Its function is to write a breakpoint
  262. and return a handle to the breakpoint.
  263. Arguments:
  264. m - Supplies the state manipulation message.
  265. AdditionalData - Supplies any additional data for the message.
  266. Context - Supplies the current context.
  267. Return Value:
  268. None.
  269. --*/
  270. {
  271. PDBGKD_WRITE_BREAKPOINT64 a = &m->u.WriteBreakPoint;
  272. STRING MessageHeader;
  273. a->BreakPointHandle = BdAddBreakpoint(a->BreakPointAddress);
  274. if (a->BreakPointHandle != 0) {
  275. m->ReturnStatus = STATUS_SUCCESS;
  276. } else {
  277. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  278. }
  279. //
  280. // Send reply packet.
  281. //
  282. MessageHeader.Length = sizeof(*m);
  283. MessageHeader.Buffer = (PCHAR)m;
  284. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  285. &MessageHeader,
  286. NULL);
  287. return;
  288. }
  289. VOID
  290. BdRestoreBreakpoint(
  291. IN PDBGKD_MANIPULATE_STATE64 m,
  292. IN PSTRING AdditionalData,
  293. IN PCONTEXT Context
  294. )
  295. /*++
  296. Routine Description:
  297. This function is called in response of a restore breakpoint state
  298. manipulation message. Its function is to restore a breakpoint
  299. using the specified handle.
  300. Arguments:
  301. m - Supplies the state manipulation message.
  302. AdditionalData - Supplies any additional data for the message.
  303. Context - Supplies the current context.
  304. Return Value:
  305. None.
  306. --*/
  307. {
  308. PDBGKD_RESTORE_BREAKPOINT a = &m->u.RestoreBreakPoint;
  309. STRING MessageHeader;
  310. if (BdDeleteBreakpoint(a->BreakPointHandle)) {
  311. m->ReturnStatus = STATUS_SUCCESS;
  312. } else {
  313. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  314. }
  315. //
  316. // Send reply packet.
  317. //
  318. MessageHeader.Length = sizeof(*m);
  319. MessageHeader.Buffer = (PCHAR)m;
  320. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  321. &MessageHeader,
  322. NULL);
  323. }
  324. VOID
  325. BdReadPhysicalMemory(
  326. IN PDBGKD_MANIPULATE_STATE64 m,
  327. IN PSTRING AdditionalData,
  328. IN PCONTEXT Context
  329. )
  330. /*++
  331. Routine Description:
  332. This function is called in response to a read physical memory
  333. state manipulation message. Its function is to read physical memory
  334. and return.
  335. Arguments:
  336. m - Supplies the state manipulation message.
  337. AdditionalData - Supplies any additional data for the message.
  338. Context - Supplies the current context.
  339. Return Value:
  340. None.
  341. --*/
  342. {
  343. PDBGKD_READ_MEMORY64 a = &m->u.ReadMemory;
  344. ULONG Length;
  345. STRING MessageHeader;
  346. PVOID VirtualAddress;
  347. PHYSICAL_ADDRESS Source;
  348. PUCHAR Destination;
  349. USHORT NumberBytes;
  350. USHORT BytesLeft;
  351. //
  352. // Trim transfer count to fit in a single message.
  353. //
  354. Length = min(a->TransferCount,
  355. PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64));
  356. //
  357. // Since the BdTranslatePhysicalAddress only maps in one physical
  358. // page at a time, we need to break the memory move up into smaller
  359. // moves which don't cross page boundaries. There are two cases we
  360. // need to deal with. The area to be moved may start and end on the
  361. // same page, or it may start and end on different pages (with an
  362. // arbitrary number of pages in between)
  363. //
  364. Source.QuadPart = (ULONG_PTR)a->TargetBaseAddress;
  365. Destination = AdditionalData->Buffer;
  366. BytesLeft = (USHORT)Length;
  367. if(PAGE_ALIGN((PUCHAR)a->TargetBaseAddress) ==
  368. PAGE_ALIGN((PUCHAR)(a->TargetBaseAddress)+Length)) {
  369. //
  370. // Memory move starts and ends on the same page.
  371. //
  372. VirtualAddress=BdTranslatePhysicalAddress(Source);
  373. if (VirtualAddress == NULL) {
  374. AdditionalData->Length = 0;
  375. } else {
  376. AdditionalData->Length = (USHORT)BdMoveMemory(Destination,
  377. VirtualAddress,
  378. BytesLeft);
  379. BytesLeft -= AdditionalData->Length;
  380. }
  381. } else {
  382. //
  383. // Memory move spans page boundaries
  384. //
  385. VirtualAddress=BdTranslatePhysicalAddress(Source);
  386. if (VirtualAddress == NULL) {
  387. AdditionalData->Length = 0;
  388. } else {
  389. NumberBytes = (USHORT)(PAGE_SIZE - BYTE_OFFSET(VirtualAddress));
  390. AdditionalData->Length = (USHORT)BdMoveMemory(Destination,
  391. VirtualAddress,
  392. NumberBytes);
  393. Source.LowPart += NumberBytes;
  394. Destination += NumberBytes;
  395. BytesLeft -= NumberBytes;
  396. while(BytesLeft > 0) {
  397. //
  398. // Transfer a full page or the last bit,
  399. // whichever is smaller.
  400. //
  401. VirtualAddress = BdTranslatePhysicalAddress(Source);
  402. if (VirtualAddress == NULL) {
  403. break;
  404. } else {
  405. NumberBytes = (USHORT) ((PAGE_SIZE < BytesLeft) ? PAGE_SIZE : BytesLeft);
  406. AdditionalData->Length += (USHORT)BdMoveMemory(
  407. Destination,
  408. VirtualAddress,
  409. NumberBytes);
  410. Source.LowPart += NumberBytes;
  411. Destination += NumberBytes;
  412. BytesLeft -= NumberBytes;
  413. }
  414. }
  415. }
  416. }
  417. if (Length == AdditionalData->Length) {
  418. m->ReturnStatus = STATUS_SUCCESS;
  419. } else {
  420. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  421. }
  422. a->ActualBytesRead = AdditionalData->Length;
  423. //
  424. // Send reply packet.
  425. //
  426. MessageHeader.Length = sizeof(*m);
  427. MessageHeader.Buffer = (PCHAR)m;
  428. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  429. &MessageHeader,
  430. AdditionalData);
  431. return;
  432. }
  433. VOID
  434. BdWritePhysicalMemory(
  435. IN PDBGKD_MANIPULATE_STATE64 m,
  436. IN PSTRING AdditionalData,
  437. IN PCONTEXT Context
  438. )
  439. /*++
  440. Routine Description:
  441. This function is called in response to a write physical memory
  442. state manipulation message. Its function is to write physical memory
  443. and return.
  444. Arguments:
  445. m - Supplies the state manipulation message.
  446. AdditionalData - Supplies any additional data for the message.
  447. Context - Supplies the current context.
  448. Return Value:
  449. None.
  450. --*/
  451. {
  452. PDBGKD_WRITE_MEMORY64 a = &m->u.WriteMemory;
  453. ULONG Length;
  454. STRING MessageHeader;
  455. PVOID VirtualAddress;
  456. PHYSICAL_ADDRESS Destination;
  457. PUCHAR Source;
  458. USHORT NumberBytes;
  459. USHORT BytesLeft;
  460. MessageHeader.Length = sizeof(*m);
  461. MessageHeader.Buffer = (PCHAR)m;
  462. //
  463. // Since the BdTranslatePhysicalAddress only maps in one physical
  464. // page at a time, we need to break the memory move up into smaller
  465. // moves which don't cross page boundaries. There are two cases we
  466. // need to deal with. The area to be moved may start and end on the
  467. // same page, or it may start and end on different pages (with an
  468. // arbitrary number of pages in between)
  469. //
  470. Destination.QuadPart = (ULONG_PTR)a->TargetBaseAddress;
  471. Source = AdditionalData->Buffer;
  472. BytesLeft = (USHORT) a->TransferCount;
  473. if(PAGE_ALIGN(Destination.QuadPart) ==
  474. PAGE_ALIGN(Destination.QuadPart+BytesLeft)) {
  475. //
  476. // Memory move starts and ends on the same page.
  477. //
  478. VirtualAddress=BdTranslatePhysicalAddress(Destination);
  479. Length = (USHORT)BdMoveMemory(VirtualAddress,
  480. Source,
  481. BytesLeft);
  482. BytesLeft -= (USHORT) Length;
  483. } else {
  484. //
  485. // Memory move spans page boundaries
  486. //
  487. VirtualAddress=BdTranslatePhysicalAddress(Destination);
  488. NumberBytes = (USHORT) (PAGE_SIZE - BYTE_OFFSET(VirtualAddress));
  489. Length = (USHORT)BdMoveMemory(VirtualAddress,
  490. Source,
  491. NumberBytes);
  492. Source += NumberBytes;
  493. Destination.LowPart += NumberBytes;
  494. BytesLeft -= NumberBytes;
  495. while(BytesLeft > 0) {
  496. //
  497. // Transfer a full page or the last bit, whichever is smaller.
  498. //
  499. VirtualAddress = BdTranslatePhysicalAddress(Destination);
  500. NumberBytes = (USHORT) ((PAGE_SIZE < BytesLeft) ? PAGE_SIZE : BytesLeft);
  501. Length += (USHORT)BdMoveMemory(VirtualAddress,
  502. Source,
  503. NumberBytes);
  504. Source += NumberBytes;
  505. Destination.LowPart += NumberBytes;
  506. BytesLeft -= NumberBytes;
  507. }
  508. }
  509. if (Length == AdditionalData->Length) {
  510. m->ReturnStatus = STATUS_SUCCESS;
  511. } else {
  512. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  513. }
  514. a->ActualBytesWritten = Length;
  515. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  516. &MessageHeader,
  517. NULL);
  518. return;
  519. }
  520. NTSTATUS
  521. BdWriteBreakPointEx(
  522. IN PDBGKD_MANIPULATE_STATE64 m,
  523. IN PSTRING AdditionalData,
  524. IN PCONTEXT Context
  525. )
  526. /*++
  527. Routine Description:
  528. This function is called in response of a write breakpoint state 'ex'
  529. manipulation message. Its function is to clear breakpoints, write
  530. new breakpoints, and continue the target system. The clearing of
  531. breakpoints is conditional based on the presence of breakpoint handles.
  532. The setting of breakpoints is conditional based on the presence of
  533. valid, non-zero, addresses. The continueing of the target system
  534. is conditional based on a non-zero continuestatus.
  535. This api allows a debugger to clear breakpoints, add new breakpoint,
  536. and continue the target system all in one api packet. This reduces the
  537. amount of traffic across the wire and greatly improves source stepping.
  538. Arguments:
  539. m - Supplies the state manipulation message.
  540. AdditionalData - Supplies any additional data for the message.
  541. Context - Supplies the current context.
  542. Return Value:
  543. None.
  544. --*/
  545. {
  546. PDBGKD_BREAKPOINTEX a = &m->u.BreakPointEx;
  547. PDBGKD_WRITE_BREAKPOINT64 b;
  548. STRING MessageHeader;
  549. ULONG i;
  550. DBGKD_WRITE_BREAKPOINT64 BpBuf[BREAKPOINT_TABLE_SIZE];
  551. MessageHeader.Length = sizeof(*m);
  552. MessageHeader.Buffer = (PCHAR)m;
  553. //
  554. // verify that the packet size is correct
  555. //
  556. if (AdditionalData->Length !=
  557. a->BreakPointCount*sizeof(DBGKD_WRITE_BREAKPOINT64)) {
  558. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  559. BdSendPacket(
  560. PACKET_TYPE_KD_STATE_MANIPULATE,
  561. &MessageHeader,
  562. AdditionalData
  563. );
  564. return m->ReturnStatus;
  565. }
  566. BdMoveMemory((PUCHAR)BpBuf,
  567. AdditionalData->Buffer,
  568. a->BreakPointCount*sizeof(DBGKD_WRITE_BREAKPOINT64));
  569. //
  570. // assume success
  571. //
  572. m->ReturnStatus = STATUS_SUCCESS;
  573. //
  574. // loop thru the breakpoint handles passed in from the debugger and
  575. // clear any breakpoint that has a non-zero handle
  576. //
  577. b = BpBuf;
  578. for (i=0; i<a->BreakPointCount; i++,b++) {
  579. if (b->BreakPointHandle) {
  580. if (!BdDeleteBreakpoint(b->BreakPointHandle)) {
  581. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  582. }
  583. b->BreakPointHandle = 0;
  584. }
  585. }
  586. //
  587. // loop thru the breakpoint addesses passed in from the debugger and
  588. // add any new breakpoints that have a non-zero address
  589. //
  590. b = BpBuf;
  591. for (i=0; i<a->BreakPointCount; i++,b++) {
  592. if (b->BreakPointAddress) {
  593. b->BreakPointHandle = BdAddBreakpoint( b->BreakPointAddress );
  594. if (!b->BreakPointHandle) {
  595. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  596. }
  597. }
  598. }
  599. //
  600. // send back our response
  601. //
  602. BdMoveMemory(AdditionalData->Buffer,
  603. (PUCHAR)BpBuf,
  604. a->BreakPointCount*sizeof(DBGKD_WRITE_BREAKPOINT64));
  605. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  606. &MessageHeader,
  607. AdditionalData);
  608. //
  609. // return the caller's continue status value. if this is a non-zero
  610. // value the system is continued using this value as the continuestatus.
  611. //
  612. return a->ContinueStatus;
  613. }
  614. VOID
  615. BdRestoreBreakPointEx(
  616. IN PDBGKD_MANIPULATE_STATE64 m,
  617. IN PSTRING AdditionalData,
  618. IN PCONTEXT Context
  619. )
  620. /*++
  621. Routine Description:
  622. This function is called in response of a restore breakpoint state 'ex'
  623. manipulation message. Its function is to clear a list of breakpoints.
  624. Arguments:
  625. m - Supplies the state manipulation message.
  626. AdditionalData - Supplies any additional data for the message.
  627. Context - Supplies the current context.
  628. Return Value:
  629. None.
  630. --*/
  631. {
  632. PDBGKD_BREAKPOINTEX a = &m->u.BreakPointEx;
  633. PDBGKD_RESTORE_BREAKPOINT b;
  634. STRING MessageHeader;
  635. ULONG i;
  636. DBGKD_RESTORE_BREAKPOINT BpBuf[BREAKPOINT_TABLE_SIZE];
  637. MessageHeader.Length = sizeof(*m);
  638. MessageHeader.Buffer = (PCHAR)m;
  639. //
  640. // verify that the packet size is correct
  641. //
  642. if (AdditionalData->Length !=
  643. a->BreakPointCount*sizeof(DBGKD_RESTORE_BREAKPOINT)) {
  644. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  645. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  646. &MessageHeader,
  647. AdditionalData);
  648. return;
  649. }
  650. BdMoveMemory((PUCHAR)BpBuf,
  651. AdditionalData->Buffer,
  652. a->BreakPointCount*sizeof(DBGKD_RESTORE_BREAKPOINT));
  653. //
  654. // assume success
  655. //
  656. m->ReturnStatus = STATUS_SUCCESS;
  657. //
  658. // loop thru the breakpoint handles passed in from the debugger and
  659. // clear any breakpoint that has a non-zero handle
  660. //
  661. b = BpBuf;
  662. for (i=0; i<a->BreakPointCount; i++,b++) {
  663. if (!BdDeleteBreakpoint(b->BreakPointHandle)) {
  664. m->ReturnStatus = STATUS_UNSUCCESSFUL;
  665. }
  666. }
  667. //
  668. // send back our response
  669. //
  670. BdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
  671. &MessageHeader,
  672. AdditionalData);
  673. return;
  674. }