Leaked source code of windows server 2003
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.

727 lines
18 KiB

  1. #define SRVDBG 1
  2. #define SRVKD 1
  3. #define NDIS40_MINIPORT 1
  4. #define NDIS_MINIPORT_DRIVER 1
  5. #define NT
  6. #include <nt.h>
  7. #include <ntrtl.h>
  8. #include <nturtl.h>
  9. #include <ntverp.h>
  10. #include <windef.h>
  11. #include <winbase.h>
  12. #include <ntosp.h>
  13. #include <wdbgexts.h>
  14. #include <stdlib.h>
  15. #include <raspptp.h>
  16. #include <bpool.h>
  17. typedef struct CTDI_DATA *PCTDI_DATA;
  18. typedef struct CTDI_DATA {
  19. LIST_ENTRY ListEntry;
  20. ULONG Signature;
  21. ULONG Type;
  22. REFERENCE_COUNT Reference;
  23. HANDLE hFile;
  24. PFILE_OBJECT pFileObject;
  25. NDIS_SPIN_LOCK Lock;
  26. BOOLEAN Closed;
  27. CTDI_EVENT_CONNECT_QUERY ConnectQueryCallback;
  28. CTDI_EVENT_CONNECT_COMPLETE ConnectCompleteCallback;
  29. CTDI_EVENT_DISCONNECT DisconnectCallback;
  30. CTDI_EVENT_RECEIVE RecvCallback;
  31. PVOID RecvContext;
  32. CTDI_EVENT_RECEIVE_DATAGRAM RecvDatagramCallback;
  33. CTDI_EVENT_SEND_COMPLETE SendCompleteCallback;
  34. CTDI_EVENT_QUERY_COMPLETE QueryCompleteCallback;
  35. CTDI_EVENT_SET_COMPLETE SetCompleteCallback;
  36. union {
  37. struct {
  38. PVOID Context;
  39. LIST_ENTRY ConnectList;
  40. ULONG NumConnection;
  41. } Listen;
  42. struct {
  43. PVOID Context;
  44. PCTDI_DATA LocalEndpoint;
  45. PVOID ConnectInfo;
  46. TA_IP_ADDRESS RemoteAddress;
  47. LIST_ENTRY ListEntry;
  48. ULONG DisconnectCount;
  49. union {
  50. BOOLEAN Disconnect;
  51. ULONG_PTR Padding1;
  52. };
  53. union {
  54. BOOLEAN Abort;
  55. ULONG_PTR Padding2;
  56. };
  57. } Connection;
  58. struct {
  59. BUFFERPOOL RxPool;
  60. } Datagram;
  61. };
  62. } CTDI_DATA, *PCTDI_DATA;
  63. #define CTDI_UNKNOWN 'NKNU'
  64. #define CTDI_ENDPOINT 'PDNE'
  65. #define CTDI_DATAGRAM 'MRGD'
  66. #define CTDI_LISTEN 'TSIL'
  67. #define CTDI_CONNECTION 'NNOC'
  68. WINDBG_EXTENSION_APIS ExtensionApis;
  69. EXT_API_VERSION ApiVersion = { 5, 0, EXT_API_VERSION_NUMBER, 0 };
  70. #define ERRPRT dprintf
  71. #define NL 1
  72. #define NONL 0
  73. USHORT SavedMajorVersion;
  74. USHORT SavedMinorVersion;
  75. BOOL ChkTarget; // is debuggee a CHK build?
  76. typedef struct
  77. {
  78. char Name[16];
  79. int Val;
  80. } DBG_LEVEL;
  81. /*
  82. * Print out an optional message, an ANSI_STRING, and maybe a new-line
  83. */
  84. BOOL
  85. PrintStringA( IN LPSTR msg OPTIONAL, IN PANSI_STRING pStr, IN BOOL nl )
  86. {
  87. PCHAR StringData;
  88. ULONG BytesRead;
  89. if( msg )
  90. dprintf( msg );
  91. if( pStr->Length == 0 ) {
  92. if( nl )
  93. dprintf( "\n" );
  94. return TRUE;
  95. }
  96. StringData = (PCHAR)LocalAlloc( LPTR, pStr->Length + 1 );
  97. if( StringData == NULL ) {
  98. ERRPRT( "Out of memory!\n" );
  99. return FALSE;
  100. }
  101. ReadMemory((ULONG)((ULONG_PTR) pStr->Buffer),
  102. StringData,
  103. pStr->Length,
  104. &BytesRead );
  105. if ( BytesRead ) {
  106. StringData[ pStr->Length ] = '\0';
  107. dprintf("%s%s", StringData, nl ? "\n" : "" );
  108. }
  109. LocalFree((HLOCAL)StringData);
  110. return BytesRead;
  111. }
  112. /*
  113. * Get 'size' bytes from the debuggee program at 'dwAddress' and place it
  114. * in our address space at 'ptr'. Use 'type' in an error printout if necessary
  115. */
  116. BOOL
  117. GetData( IN LPVOID ptr, IN DWORD_PTR dwAddress, IN ULONG size, IN PCSTR type )
  118. {
  119. BOOL b;
  120. ULONG BytesRead;
  121. ULONG count = size;
  122. while( size > 0 ) {
  123. if (count >= 3000)
  124. count = 3000;
  125. b = ReadMemory((ULONG) dwAddress, ptr, count, &BytesRead );
  126. if (!b || BytesRead != count ) {
  127. ERRPRT( "Unable to read %u bytes at %X, for %s\n", size, dwAddress, type );
  128. return FALSE;
  129. }
  130. dwAddress += count;
  131. size -= count;
  132. ptr = (LPVOID)((ULONG_PTR)ptr + count);
  133. }
  134. return TRUE;
  135. }
  136. /*
  137. * Follow a LIST_ENTRY list beginning with a head at dwListHeadAddr in the debugee's
  138. * address space. For each element in the list, print out the pointer value at 'offset'
  139. */
  140. BOOL
  141. PrintListEntryList( IN DWORD dwListHeadAddr, IN LONG offset )
  142. {
  143. LIST_ENTRY ListEntry;
  144. ULONG i=0;
  145. BOOL retval = TRUE;
  146. ULONG count = 20;
  147. if( !GetData( &ListEntry, dwListHeadAddr, sizeof( ListEntry ), "LIST_ENTRY" ) )
  148. return FALSE;
  149. while( count-- ) {
  150. if( (DWORD_PTR)ListEntry.Flink == dwListHeadAddr || (DWORD_PTR)ListEntry.Flink == 0 )
  151. break;
  152. if( !GetData( &ListEntry, (DWORD_PTR)ListEntry.Flink, (ULONG)sizeof( ListEntry ), "ListEntry" ) ) {
  153. retval = FALSE;
  154. break;
  155. }
  156. dprintf( "%16X%s", (DWORD_PTR)ListEntry.Flink + offset, (i && !(i&3)) ? "\n" : "" );
  157. i++;
  158. }
  159. if( count == 0 && (DWORD_PTR)ListEntry.Flink != dwListHeadAddr && ListEntry.Flink ) {
  160. dprintf( "\nTruncated list dump\n" );
  161. } else if( ! ( i && !(i&3) ) ) {
  162. dprintf( "\n" );
  163. }
  164. return retval;
  165. }
  166. /*
  167. * Print out a single HEX character
  168. */
  169. VOID
  170. PrintHexChar( IN UCHAR c )
  171. {
  172. dprintf( "%c%c", "0123456789abcdef"[ (c>>4)&0xf ], "0123456789abcdef"[ c&0xf ] );
  173. }
  174. /*
  175. * Print out 'buf' of 'cbuf' bytes as HEX characters
  176. */
  177. VOID
  178. PrintHexBuf( IN PUCHAR buf, IN ULONG cbuf )
  179. {
  180. while( cbuf-- ) {
  181. PrintHexChar( *buf++ );
  182. dprintf( " " );
  183. }
  184. }
  185. /*
  186. * Fetch the null terminated UNICODE string at dwAddress into buf
  187. */
  188. BOOL
  189. GetString( IN DWORD_PTR dwAddress, IN LPSTR buf, IN ULONG MaxChars )
  190. {
  191. do {
  192. if( !GetData( buf, dwAddress, sizeof( *buf ), "Character" ) )
  193. return FALSE;
  194. dwAddress += sizeof( *buf );
  195. } while( --MaxChars && *buf++ != '\0' );
  196. return TRUE;
  197. }
  198. char *mystrtok ( char *string, char * control )
  199. {
  200. static unsigned char *str;
  201. char *p, *s;
  202. if( string )
  203. str = string;
  204. if( str == NULL || *str == '\0' )
  205. return NULL;
  206. //
  207. // Skip leading delimiters...
  208. //
  209. for( ; *str; str++ ) {
  210. for( s=control; *s; s++ ) {
  211. if( *str == *s )
  212. break;
  213. }
  214. if( *s == '\0' )
  215. break;
  216. }
  217. //
  218. // Was it was all delimiters?
  219. //
  220. if( *str == '\0' ) {
  221. str = NULL;
  222. return NULL;
  223. }
  224. //
  225. // We've got a string, terminate it at first delimeter
  226. //
  227. for( p = str+1; *p; p++ ) {
  228. for( s = control; *s; s++ ) {
  229. if( *p == *s ) {
  230. s = str;
  231. *p = '\0';
  232. str = p+1;
  233. return s;
  234. }
  235. }
  236. }
  237. //
  238. // We've got a string that ends with the NULL
  239. //
  240. s = str;
  241. str = NULL;
  242. return s;
  243. }
  244. DECLARE_API( help )
  245. {
  246. int i;
  247. dprintf("PPTP extenstions:\n");
  248. dprintf(" version\n");
  249. dprintf(" ctdi dump tdi handles\n");
  250. dprintf(" calls [start [end]] dump call handles\n");
  251. dprintf(" ctls dump ctl handles\n");
  252. dprintf(" dbgmsgs dump debug log\n");
  253. dprintf(" mem dump allocations\n");
  254. }
  255. DECLARE_API( dbgmsgs )
  256. {
  257. DWORD p;
  258. DWORD Last, First;
  259. char DbgMsg[MAX_MSG_LEN];
  260. ULONG Read;
  261. char *DbgMsgs;
  262. if (!GetData(&Last,
  263. GetExpression("raspptp!Last"),
  264. sizeof(Last), "DWORD"))
  265. {
  266. dprintf("error\n");
  267. return;
  268. }
  269. if (!GetData(&First,
  270. GetExpression("raspptp!First"),
  271. sizeof(Last), "DWORD"))
  272. {
  273. dprintf("error\n");
  274. return;
  275. }
  276. DbgMsgs = (char *) GetExpression("raspptp!dbgmsgs");
  277. dprintf("\n\n");
  278. while (First != Last)
  279. {
  280. if (!GetString((DWORD_PTR) (DbgMsgs + First * MAX_MSG_LEN),
  281. DbgMsg, MAX_MSG_LEN))
  282. break;
  283. /*
  284. ReadMemory((ULONG) (DbgMsgs + First * MAX_MSG_LEN),
  285. DbgMsg, MAX_MSG_LEN, &Read); */
  286. dprintf("%s", DbgMsg);
  287. First++;
  288. if (First == DBG_MSG_CNT)
  289. First = 0;
  290. }
  291. }
  292. DECLARE_API( ctdi )
  293. {
  294. LIST_ENTRY ListEntry;
  295. PLIST_ENTRY ListHead;
  296. ULONG Count = 20;
  297. char argbuf[ MAX_PATH ];
  298. ListHead = (PLIST_ENTRY)GetExpression("raspptp!CtdiList");
  299. if (!GetData(&ListEntry,
  300. (ULONG_PTR)ListHead,
  301. sizeof(LIST_ENTRY),
  302. "LIST_ENTRY"))
  303. {
  304. dprintf("error\n");
  305. return;
  306. }
  307. while (Count-- && ListHead!=ListEntry.Flink)
  308. {
  309. CTDI_DATA Ctdi;
  310. UCHAR TypeStr[sizeof(ULONG)+1];
  311. if (!GetData(&Ctdi,
  312. (ULONG_PTR)ListEntry.Flink,
  313. sizeof(CTDI_DATA),
  314. "CTDI_DATA"))
  315. {
  316. dprintf("error\n");
  317. return;
  318. }
  319. memcpy(TypeStr, &Ctdi.Type, sizeof(ULONG));
  320. TypeStr[sizeof(ULONG)] = 0;
  321. dprintf("CTDI:%08x Sig:%08x Type:%s Refs:%d Handle:%08x FileObj:%08x Closed:%d\n",
  322. ListEntry.Flink, Ctdi.Signature, TypeStr, Ctdi.Reference.Count, Ctdi.hFile, Ctdi.pFileObject, Ctdi.Closed);
  323. switch (Ctdi.Type)
  324. {
  325. case CTDI_CONNECTION:
  326. dprintf(" Context:%08x Endpoint:%08x Disconnect/Abort:%x/%x\n",
  327. Ctdi.Connection.Context, Ctdi.Connection.LocalEndpoint,
  328. Ctdi.Connection.Disconnect, Ctdi.Connection.Abort);
  329. break;
  330. case CTDI_LISTEN:
  331. dprintf(" Context:%08x NumConn:%d\n",
  332. Ctdi.Listen.Context, Ctdi.Listen.NumConnection);
  333. break;
  334. default:
  335. break;
  336. }
  337. ListEntry = Ctdi.ListEntry;
  338. }
  339. }
  340. typedef struct MEM_HDR {
  341. LIST_ENTRY ListEntry;
  342. ULONG Size;
  343. CHAR File[12];
  344. ULONG Line;
  345. } MEM_HDR;
  346. DECLARE_API( mem )
  347. {
  348. LIST_ENTRY ListEntry;
  349. PLIST_ENTRY ListHead;
  350. ULONG TotalMem = 0;
  351. char argbuf[ MAX_PATH ];
  352. ListHead = (PLIST_ENTRY)GetExpression("raspptp!leAlloc");
  353. if (!GetData(&ListEntry,
  354. (ULONG_PTR)ListHead,
  355. sizeof(LIST_ENTRY),
  356. "LIST_ENTRY"))
  357. {
  358. dprintf("error\n");
  359. return;
  360. }
  361. while (ListHead!=ListEntry.Flink)
  362. {
  363. MEM_HDR Mem;
  364. UCHAR TypeStr[sizeof(ULONG)+1];
  365. if (!GetData(&Mem,
  366. (ULONG_PTR)ListEntry.Flink,
  367. sizeof(MEM_HDR),
  368. "MEM_HDR"))
  369. {
  370. dprintf("error\n");
  371. return;
  372. }
  373. dprintf("MEM:%08x Len:%5d File:%-15s Line:%d\n",
  374. ListEntry.Flink, Mem.Size, Mem.File, Mem.Line);
  375. TotalMem += Mem.Size;
  376. ListEntry = Mem.ListEntry;
  377. }
  378. dprintf("MEM: Total %d bytes\n", TotalMem);
  379. }
  380. PUCHAR CallState[] =
  381. {
  382. "STATE_CALL_INVALID",
  383. "STATE_CALL_CLOSED",
  384. "STATE_CALL_IDLE",
  385. "STATE_CALL_OFFHOOK",
  386. "STATE_CALL_OFFERING",
  387. "STATE_CALL_PAC_OFFERING",
  388. "STATE_CALL_PAC_WAIT",
  389. "STATE_CALL_DIALING",
  390. "STATE_CALL_PROCEEDING",
  391. "STATE_CALL_ESTABLISHED",
  392. "STATE_CALL_WAIT_DISCONNECT",
  393. "STATE_CALL_CLEANUP"
  394. };
  395. DECLARE_API( calls )
  396. {
  397. PPTP_ADAPTER Adapter;
  398. CALL_SESSION Call;
  399. ULONG_PTR pCall;
  400. ULONG_PTR pAdapter = GetExpression("raspptp!pgAdapter");
  401. ULONG i, StartCall=0, EndCall=0xffff;
  402. char argbuf[MAX_PATH];
  403. char arglist[2][MAX_PATH];
  404. if (args && *args)
  405. {
  406. char *p;
  407. strcpy(argbuf, args);
  408. i = 0;
  409. //parsing the arguments
  410. for (p = mystrtok( argbuf, " \t,;" );
  411. p && *p && i<2;
  412. p = mystrtok(NULL, " \t,;"))
  413. {
  414. strcpy(&arglist[i++][0],p);
  415. }
  416. if (i>0)
  417. {
  418. StartCall = EndCall = atoi(arglist[0]);
  419. }
  420. if (i>1)
  421. {
  422. EndCall = atoi(arglist[1]);
  423. }
  424. }
  425. if (!GetData(&pAdapter,
  426. pAdapter,
  427. sizeof(pAdapter),
  428. "PPTP_ADAPTER*"))
  429. {
  430. dprintf("error\n");
  431. return;
  432. }
  433. if (!pAdapter)
  434. {
  435. dprintf("no adapter\n");
  436. return;
  437. }
  438. if (!GetData(&Adapter,
  439. pAdapter,
  440. sizeof(Adapter),
  441. "PPTP_ADAPTER"))
  442. {
  443. dprintf("error\n");
  444. return;
  445. }
  446. dprintf("Adapter:%08x %d calls\n", pAdapter, Adapter.Info.Endpoints);
  447. for (i=StartCall; i<Adapter.Info.Endpoints && i<=EndCall; i++)
  448. {
  449. if (!GetData(&pCall,
  450. ((ULONG_PTR)Adapter.pCallArray)+i*sizeof(ULONG_PTR),
  451. sizeof(pCall),
  452. "CALL_SESSION*"))
  453. {
  454. dprintf("error\n");
  455. return;
  456. }
  457. if (pCall)
  458. {
  459. if (!GetData(&Call,
  460. pCall,
  461. sizeof(Call),
  462. "CALL_SESSION"))
  463. {
  464. dprintf("error\n");
  465. return;
  466. }
  467. dprintf("Call %d:%08x Ctl:%08x State:%s Inbound:%d Open:%d\n",
  468. i, pCall, Call.pCtl, CallState[Call.State], Call.Inbound, Call.Open);
  469. dprintf(" htCall:%08x DeviceId:%d SN:%d Link:%08x\n",
  470. Call.hTapiCall, Call.DeviceId, Call.SerialNumber, Call.NdisLinkContext);
  471. dprintf(" Remote->ID:%04x Seq:%08x Ack:%08x Addr:%08x\n",
  472. Call.Remote.CallId,
  473. Call.Remote.SequenceNumber,
  474. Call.Remote.AckNumber,
  475. Call.Remote.Address.Address[0].Address[0].in_addr);
  476. dprintf(" Packet->ID:%04x Seq:%08x Ack:%08x\n",
  477. Call.Packet.CallId,
  478. Call.Packet.SequenceNumber,
  479. Call.Packet.AckNumber);
  480. dprintf(" Close->Expedited:%d Checklist:%x\n",
  481. Call.Close.Expedited, Call.Close.Checklist);
  482. }
  483. else
  484. {
  485. dprintf("Call %d:freed\n", i);
  486. }
  487. }
  488. }
  489. PUCHAR CtlState[] =
  490. {
  491. "STATE_CTL_INVALID",
  492. "STATE_CTL_LISTEN",
  493. "STATE_CTL_DIALING",
  494. "STATE_CTL_WAIT_REQUEST",
  495. "STATE_CTL_WAIT_REPLY",
  496. "STATE_CTL_ESTABLISHED",
  497. "STATE_CTL_WAIT_STOP",
  498. "STATE_CTL_CLEANUP"
  499. };
  500. DECLARE_API( ctls )
  501. {
  502. PPTP_ADAPTER Adapter;
  503. LIST_ENTRY ListEntry;
  504. PLIST_ENTRY ListHead;
  505. char argbuf[ MAX_PATH ];
  506. ULONG_PTR pAdapter = GetExpression("raspptp!pgAdapter");
  507. if (!GetData(&pAdapter,
  508. pAdapter,
  509. sizeof(pAdapter),
  510. "PPTP_ADAPTER*"))
  511. {
  512. dprintf("error\n");
  513. return;
  514. }
  515. if (!pAdapter)
  516. {
  517. dprintf("no adapter\n");
  518. return;
  519. }
  520. if (!GetData(&Adapter,
  521. pAdapter,
  522. sizeof(Adapter),
  523. "PPTP_ADAPTER"))
  524. {
  525. dprintf("error\n");
  526. return;
  527. }
  528. ListHead = (PLIST_ENTRY)(((ULONG_PTR)&Adapter.ControlTunnelList) - ((ULONG_PTR)&Adapter) + pAdapter);
  529. ListEntry = Adapter.ControlTunnelList;
  530. while (ListHead!=ListEntry.Flink)
  531. {
  532. CONTROL_TUNNEL Ctl;
  533. if (!GetData(&Ctl,
  534. (ULONG_PTR)ListEntry.Flink,
  535. sizeof(CONTROL_TUNNEL),
  536. "CONTROL_TUNNEL"))
  537. {
  538. dprintf("error\n");
  539. return;
  540. }
  541. dprintf("CTL:%08x Sig:%08x State:%s Refs:%d Cleanup:%x Inbound:%d\n",
  542. ListEntry.Flink, Ctl.Signature, CtlState[Ctl.State], Ctl.Reference.Count, Ctl.Cleanup, Ctl.Inbound);
  543. ListEntry = Ctl.ListEntry;
  544. }
  545. }
  546. VOID
  547. DumpIrpList(LIST_ENTRY *pIrpList)
  548. {
  549. LIST_ENTRY IrpList, *pListEntry, ListEntry;
  550. IRP *pIrp;
  551. if (!GetData(&IrpList,
  552. (DWORD_PTR) pIrpList,
  553. sizeof(LIST_ENTRY), "LIST_ENTRY"))
  554. {
  555. return;
  556. }
  557. for (pListEntry = IrpList.Flink;
  558. pListEntry != pIrpList;
  559. pListEntry = ListEntry.Flink)
  560. {
  561. if (!GetData(&ListEntry,
  562. (DWORD_PTR) pListEntry,
  563. sizeof(LIST_ENTRY), "LIST_ENTRY"))
  564. {
  565. return;
  566. }
  567. pIrp = CONTAINING_RECORD(pListEntry, IRP, Tail.Overlay.ListEntry);
  568. dprintf(" %x\n", pIrp);
  569. }
  570. }
  571. VOID
  572. WinDbgExtensionDllInit(
  573. PWINDBG_EXTENSION_APIS lpExtensionApis,
  574. USHORT MajorVersion,
  575. USHORT MinorVersion
  576. )
  577. {
  578. ExtensionApis = *lpExtensionApis;
  579. SavedMajorVersion = MajorVersion;
  580. SavedMinorVersion = MinorVersion;
  581. ChkTarget = SavedMajorVersion == 0x0c ? TRUE : FALSE;
  582. }
  583. DECLARE_API( version )
  584. {
  585. #if DBG
  586. PCSTR kind = "Checked";
  587. #else
  588. PCSTR kind = "Free";
  589. #endif
  590. dprintf(
  591. "%s SMB Extension dll for Build %d debugging %s kernel for Build %d\n",
  592. kind,
  593. VER_PRODUCTBUILD,
  594. SavedMajorVersion == 0x0c ? "Checked" : "Free",
  595. SavedMinorVersion
  596. );
  597. }
  598. VOID
  599. CheckVersion(
  600. VOID
  601. )
  602. {
  603. #if DBG
  604. if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  605. dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
  606. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  607. }
  608. #else
  609. if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
  610. dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
  611. VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
  612. }
  613. #endif
  614. }
  615. LPEXT_API_VERSION
  616. ExtensionApiVersion(
  617. VOID
  618. )
  619. {
  620. return &ApiVersion;
  621. }