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
11 KiB

  1. /*****************************************************************************
  2. *
  3. * Copyright (c) 1998-1999 Microsoft Corporation
  4. *
  5. * DBGAPI.C - NT specific debugging macros, etc.
  6. *
  7. * Author: Stan Adermann (stana)
  8. *
  9. * Created: 9/3/1998
  10. *
  11. *****************************************************************************/
  12. #if DBG
  13. #include "raspptp.h"
  14. #include <ntddk.h>
  15. #include <cxport.h>
  16. #include <stdio.h>
  17. #include <stdarg.h>
  18. #include <string.h>
  19. #include "dbgapi.h"
  20. #define UNICODE_STRING_CONST(x) {sizeof(L##x)-2, sizeof(L##x), L##x}
  21. ULONG DbgSettings = 0;
  22. ULONG DbgOutput = DBG_OUTPUT_BUFFER;
  23. CHAR DbgMsgs[DBG_MSG_CNT][MAX_MSG_LEN];
  24. ULONG First, Last;
  25. CTETimer DbgTimer;
  26. BOOLEAN TimerRunning;
  27. CTELock DbgLock;
  28. PIRP pDbgIrp;
  29. UCHAR *IrpBuf;
  30. ULONG IrpBufLen;
  31. ULONG IrpBufWritten;
  32. UCHAR CharTable[256];
  33. VOID DbgTimerExp(CTEEvent *Event, void *Arg);
  34. VOID
  35. DbgMsgInit()
  36. {
  37. ULONG i;
  38. pDbgIrp = NULL;
  39. First = 0;
  40. Last = 0;
  41. TimerRunning = FALSE;
  42. for (i=0; i<256; i++)
  43. {
  44. CharTable[i] = (UCHAR)((i>=' ') ? i : '.');
  45. }
  46. CharTable[0xfe] = '.'; // Debugger seems to get stuck when we print this.
  47. CTEInitLock(&DbgLock);
  48. CTEInitTimer(&DbgTimer);
  49. }
  50. VOID
  51. DbgMsgUninit()
  52. {
  53. CTELockHandle LockHandle;
  54. KIRQL Irql;
  55. CTEGetLock(&DbgLock, &LockHandle);
  56. if (pDbgIrp)
  57. {
  58. IoAcquireCancelSpinLock(&Irql);
  59. IoSetCancelRoutine(pDbgIrp, NULL);
  60. IoReleaseCancelSpinLock(Irql);
  61. pDbgIrp->IoStatus.Information = 0;
  62. pDbgIrp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  63. DbgPrint("Complete irp!\n");
  64. IoCompleteRequest(pDbgIrp, IO_NO_INCREMENT);
  65. pDbgIrp = NULL;
  66. }
  67. CTEFreeLock(&DbgLock, LockHandle);
  68. }
  69. VOID
  70. DbgMsg(CHAR *Format, ...)
  71. {
  72. va_list Args;
  73. CTELockHandle LockHandle;
  74. CHAR Temp[MAX_MSG_LEN];
  75. va_start(Args, Format);
  76. vsprintf(Temp, Format, Args);
  77. if (DbgOutput & DBG_OUTPUT_DEBUGGER)
  78. {
  79. DbgPrint("RASPPTP: ");
  80. DbgPrint(Temp);
  81. }
  82. if (DbgOutput & DBG_OUTPUT_BUFFER)
  83. {
  84. CTEGetLock(&DbgLock, &LockHandle);
  85. strcpy(DbgMsgs[Last], Temp);
  86. Last++;
  87. if (Last == DBG_MSG_CNT)
  88. Last = 0;
  89. if (First == Last)
  90. {
  91. First++;
  92. if (First == DBG_MSG_CNT)
  93. First = 0;
  94. }
  95. if (pDbgIrp && !TimerRunning)
  96. {
  97. CTEStartTimer(&DbgTimer, DBG_TIMER_INTERVAL,
  98. DbgTimerExp, NULL);
  99. TimerRunning = TRUE;
  100. }
  101. CTEFreeLock(&DbgLock, LockHandle);
  102. }
  103. va_end(Args);
  104. }
  105. NTSTATUS
  106. FillDbgIrp(UCHAR Msg[])
  107. {
  108. NTSTATUS Status = STATUS_PENDING;
  109. ULONG i;
  110. if ((IrpBufLen - IrpBufWritten) < MAX_MSG_LEN)
  111. {
  112. Status = STATUS_SUCCESS;
  113. }
  114. else
  115. {
  116. Msg[MAX_MSG_LEN - 1] = 0; // just to be sure
  117. i = 0;
  118. while (1)
  119. {
  120. IrpBuf[IrpBufWritten++] = Msg[i];
  121. if (Msg[i] == 0)
  122. break;
  123. i++;
  124. }
  125. }
  126. return Status;
  127. }
  128. VOID CancelDbgIrp(
  129. PDEVICE_OBJECT DeviceObject,
  130. PIRP pIrp)
  131. {
  132. // DbgPrint("CancelDbgIrp %x\n", pIrp);
  133. pDbgIrp = NULL;
  134. IoReleaseCancelSpinLock(pIrp->CancelIrql);
  135. pIrp->IoStatus.Status = STATUS_CANCELLED;
  136. pIrp->IoStatus.Information = 0;
  137. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  138. }
  139. NTSTATUS
  140. DbgMsgIrp(
  141. PIRP pIrp,
  142. PIO_STACK_LOCATION pIrpSp)
  143. {
  144. CTELockHandle LockHandle;
  145. NTSTATUS Status = STATUS_PENDING;
  146. if (pDbgIrp != NULL)
  147. return STATUS_DEVICE_BUSY;
  148. CTEGetLock(&DbgLock, &LockHandle);
  149. IrpBufLen = pIrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  150. IrpBufWritten = 0;
  151. if (IrpBufLen < MAX_MSG_LEN)
  152. {
  153. CTEFreeLock(&DbgLock, LockHandle);
  154. return STATUS_BUFFER_OVERFLOW;
  155. }
  156. IrpBuf = pIrp->AssociatedIrp.SystemBuffer;
  157. while (First != Last)
  158. {
  159. Status = FillDbgIrp(DbgMsgs[First]);
  160. if (Status == STATUS_SUCCESS)
  161. break;
  162. First++;
  163. if (First == DBG_MSG_CNT)
  164. First = 0;
  165. }
  166. if (Status == STATUS_SUCCESS)
  167. {
  168. pIrp->IoStatus.Information = IrpBufWritten;
  169. }
  170. else if (Status == STATUS_PENDING)
  171. {
  172. KIRQL Irql;
  173. PDRIVER_CANCEL PrevCancel;
  174. pDbgIrp = pIrp;
  175. IoMarkIrpPending(pIrp);
  176. IoAcquireCancelSpinLock(&Irql);
  177. PrevCancel = IoSetCancelRoutine(pIrp, CancelDbgIrp);
  178. CTEAssert(PrevCancel == NULL);
  179. IoReleaseCancelSpinLock(Irql);
  180. if (IrpBufWritten != 0)
  181. {
  182. CTEStartTimer(&DbgTimer, DBG_TIMER_INTERVAL,
  183. DbgTimerExp, NULL);
  184. TimerRunning = TRUE;
  185. }
  186. }
  187. CTEFreeLock(&DbgLock, LockHandle);
  188. //DbgPrint("DbgIrp status %x, bw %d, irp %x\n", Status, IrpBufWritten, pIrp);
  189. return Status;
  190. }
  191. VOID
  192. DbgTimerExp(CTEEvent *Event, void *Arg)
  193. {
  194. CTELockHandle LockHandle;
  195. PIRP pIrp;
  196. KIRQL Irql;
  197. //DbgPrint("Texp\n");
  198. if (pDbgIrp == NULL)
  199. {
  200. DbgPrint("DbgIrp is null\n");
  201. return;
  202. }
  203. IoAcquireCancelSpinLock(&Irql);
  204. IoSetCancelRoutine(pDbgIrp, NULL);
  205. IoReleaseCancelSpinLock(Irql);
  206. if (pDbgIrp->Cancel)
  207. {
  208. DbgPrint("DbgIrp is being canceled\n");
  209. pDbgIrp = NULL;
  210. return;
  211. }
  212. CTEGetLock(&DbgLock, &LockHandle);
  213. TimerRunning = FALSE;
  214. while (First != Last)
  215. {
  216. if (FillDbgIrp(DbgMsgs[First]) == STATUS_SUCCESS)
  217. break;
  218. First++;
  219. if (First == DBG_MSG_CNT)
  220. First = 0;
  221. }
  222. pIrp = pDbgIrp;
  223. pDbgIrp = NULL;
  224. CTEFreeLock(&DbgLock, LockHandle);
  225. pIrp->IoStatus.Information = IrpBufWritten;
  226. pIrp->IoStatus.Status = STATUS_SUCCESS;
  227. // DbgPrint("Comp bw %d, irp %x\n", IrpBufWritten, pIrp);
  228. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  229. }
  230. VOID DbgMemory(PVOID pMemory, ULONG Length, ULONG WordSize)
  231. {
  232. ULONG i, j;
  233. UCHAR AsciiData[17];
  234. for (i=0; i<Length; )
  235. {
  236. DbgMsg("%08x: ", pMemory);
  237. for (j=0; j<16 && i+j<Length; j++)
  238. {
  239. AsciiData[j] = CharTable[((PUCHAR)pMemory)[j]];
  240. }
  241. AsciiData[j] = '\0';
  242. for (j=0; j<16; j+=WordSize, i+=WordSize)
  243. {
  244. if (i<Length)
  245. {
  246. switch (WordSize)
  247. {
  248. case 1:
  249. DbgMsg("%02x ", *(PUCHAR)pMemory);
  250. break;
  251. case 2:
  252. DbgMsg("%04x ", *(PUSHORT)pMemory);
  253. break;
  254. case 4:
  255. DbgMsg("%08x ", *(PULONG)pMemory);
  256. break;
  257. }
  258. }
  259. else
  260. {
  261. DbgMsg("%*s ", WordSize*2, "");
  262. }
  263. pMemory = (PUCHAR)pMemory + WordSize;
  264. }
  265. DbgMsg(" %s\n", AsciiData);
  266. }
  267. }
  268. VOID DbgRegInit(PUNICODE_STRING pRegistryPath, ULONG DefaultDebug)
  269. {
  270. struct {
  271. KEY_VALUE_PARTIAL_INFORMATION Value;
  272. ULONG_PTR Filler;
  273. } DwordValue;
  274. ULONG InformationLength;
  275. OBJECT_ATTRIBUTES ObjectAttributes;
  276. HANDLE hReg;
  277. NTSTATUS Status;
  278. UNICODE_STRING DbgSettingsString = UNICODE_STRING_CONST("DbgSettings");
  279. UNICODE_STRING DbgOutputString = UNICODE_STRING_CONST("DbgOutput");
  280. UNICODE_STRING PromptString = UNICODE_STRING_CONST("Prompt");
  281. InitializeObjectAttributes(&ObjectAttributes,
  282. pRegistryPath,
  283. OBJ_CASE_INSENSITIVE,
  284. NULL,
  285. NULL);
  286. Status = ZwOpenKey(&hReg, MAXIMUM_ALLOWED, &ObjectAttributes);
  287. if (Status==STATUS_SUCCESS)
  288. {
  289. Status = ZwQueryValueKey(hReg,
  290. &DbgSettingsString,
  291. KeyValuePartialInformation,
  292. &DwordValue,
  293. sizeof(DwordValue),
  294. &InformationLength);
  295. if (Status==STATUS_SUCCESS)
  296. {
  297. DbgSettings = *(PULONG)DwordValue.Value.Data;
  298. }
  299. else
  300. {
  301. DbgSettings = DefaultDebug;
  302. }
  303. Status = ZwQueryValueKey(hReg,
  304. &DbgOutputString,
  305. KeyValuePartialInformation,
  306. &DwordValue,
  307. sizeof(DwordValue),
  308. &InformationLength);
  309. if (Status==STATUS_SUCCESS)
  310. {
  311. DbgOutput = *(PULONG)DwordValue.Value.Data;
  312. }
  313. Status = ZwQueryValueKey(hReg,
  314. &PromptString,
  315. KeyValuePartialInformation,
  316. &DwordValue,
  317. sizeof(DwordValue),
  318. &InformationLength);
  319. if (Status==STATUS_SUCCESS && DwordValue.Value.Data[0])
  320. {
  321. char Response[2];
  322. BOOLEAN ValidChar;
  323. extern ULONG AbortLoad;
  324. extern ULONG
  325. DbgPrompt(
  326. IN PCHAR Prompt,
  327. OUT PCHAR Response,
  328. IN ULONG MaximumResponseLength
  329. );
  330. do
  331. {
  332. ValidChar = TRUE;
  333. DbgPrompt("RASPPTP: Debugging: Full, Default, Minimal, Abort load, Break (FDMAB)? ",
  334. Response, sizeof(Response));
  335. switch (Response[0])
  336. {
  337. case 'A': case 'a':
  338. AbortLoad = TRUE;
  339. break;
  340. case 'B': case 'b':
  341. DbgBreakPoint();
  342. break;
  343. case 'M': case 'm':
  344. DbgSettings = DBG_ERROR|DBG_WARN;
  345. break;
  346. case 'D': case 'd':
  347. // Default already set. Leave untouched.
  348. break;
  349. case 'F': case 'f':
  350. DbgSettings =
  351. DBG_ERROR |
  352. DBG_WARN |
  353. DBG_FUNC |
  354. DBG_INIT |
  355. DBG_TX |
  356. DBG_RX |
  357. DBG_TDI |
  358. DBG_TUNNEL |
  359. DBG_CALL |
  360. DBG_NDIS |
  361. DBG_TAPI |
  362. DBG_THREAD |
  363. DBG_REF |
  364. 0;
  365. break;
  366. default:
  367. ValidChar = FALSE;
  368. break;
  369. }
  370. } while ( !ValidChar );
  371. }
  372. ZwClose(hReg);
  373. }
  374. }
  375. #endif