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.

580 lines
15 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: newdpf.c
  6. * Content: new debug printf
  7. *@@BEGIN_MSINTERNAL
  8. * History:
  9. * Date By Reason
  10. * ==== == ======
  11. * 10-oct-95 jeffno initial implementation
  12. *@@END_MSINTERNAL
  13. *
  14. ***************************************************************************/
  15. #if defined(DEBUG) || defined(DBG)
  16. #ifdef IS_16
  17. #define OUTPUTDEBUGSTRING OutputDebugString
  18. #define GETPROFILESTRING GetProfileString
  19. #define GETPROFILEINT GetProfileInt
  20. #define WSPRINTF wsprintf
  21. #define WVSPRINTF wvsprintf
  22. #define LSTRLEN lstrlen
  23. #else
  24. #define OUTPUTDEBUGSTRING OutputDebugStringA
  25. #define GETPROFILESTRING GetProfileStringA
  26. #define GETPROFILEINT GetProfileIntA
  27. #define WSPRINTF wsprintfA
  28. #define WVSPRINTF wvsprintfA
  29. #define LSTRLEN lstrlenA
  30. #endif
  31. #include "dpf.h"
  32. #undef DEBUG_TOPIC
  33. #define DEBUG_TOPIC(flag,name) {#flag,name,TRUE},
  34. static
  35. struct {
  36. char cFlag[4];
  37. char cName[64];
  38. BOOL bOn;
  39. } DebugTopics[] = {
  40. {"","Filler",FALSE},
  41. {"A","API Usage",TRUE},
  42. #include "DBGTOPIC.H"
  43. {"","End",FALSE}
  44. };
  45. #ifndef DPF_MODULE_NAME
  46. #define DPF_MODULE_NAME ""
  47. #endif
  48. static DWORD bDetailOn = 1;
  49. static BOOL bInited=FALSE;
  50. static BOOL bAllowMisc=TRUE;
  51. static bBreakOnAsserts=FALSE;
  52. static bPrintLineNumbers=FALSE;
  53. static bPrintFileNames=FALSE;
  54. static bPrintExecutableName=FALSE;
  55. static bPrintTID=FALSE;
  56. static bPrintPID=FALSE;
  57. static bIndentOnMessageLevel=FALSE;
  58. static bPrintTopicsAndLevels=FALSE;
  59. static bPrintModuleName=TRUE;
  60. static bPrintFunctionName=FALSE;
  61. static bRespectColumns=FALSE;
  62. static bPrintAPIStats=FALSE;
  63. static bPrintAllTopics=TRUE;
  64. static DWORD dwFileLineTID=0;
  65. static char cFile[100];
  66. static char cFnName[100];
  67. static DWORD dwLineNo;
  68. static bMute=FALSE;
  69. static BOOL bLogging=FALSE; // whether to use the logging VxD instead of dumping.
  70. DPF_PROC_STATS ProcStats[MAX_PROC_ORDINAL];
  71. #ifdef cplusplus
  72. extern "C" {
  73. #endif
  74. void mystrncpy(char * to,char * from,int n)
  75. {
  76. for(;n;n--)
  77. *(to++)=*(from++);
  78. }
  79. char * mystrrchr(char * in,char c)
  80. {
  81. char * last=0;
  82. while (*in)
  83. {
  84. if (*in == c)
  85. last = in;
  86. in++;
  87. }
  88. return last;
  89. }
  90. char Junk[]="DPF_MODNAME undef'd";
  91. char * DPF_MODNAME = Junk;
  92. int DebugSetFileLineEtc(LPSTR szFile, DWORD dwLineNumber, LPSTR szFnName)
  93. {
  94. if (!(bPrintFileNames||bPrintLineNumbers||bPrintFunctionName))
  95. {
  96. return 1;
  97. }
  98. #ifdef WIN32
  99. dwFileLineTID = GetCurrentThreadId();
  100. #endif
  101. mystrncpy (cFile,szFile,sizeof(cFile));
  102. mystrncpy (cFnName,szFnName,sizeof(cFnName));
  103. dwLineNo = dwLineNumber;
  104. return 1;
  105. }
  106. /*
  107. BOOL DeviceIoControl(
  108. HANDLE hDevice, // handle to device of interest
  109. DWORD dwIoControlCode, // control code of operation to perform
  110. LPVOID lpInBuffer, // pointer to buffer to supply input data
  111. DWORD nInBufferSize, // size of input buffer
  112. LPVOID lpOutBuffer, // pointer to buffer to receive output data
  113. DWORD nOutBufferSize, // size of output buffer
  114. LPDWORD lpBytesReturned, // pointer to variable to receive output byte count
  115. LPOVERLAPPED lpOverlapped // pointer to overlapped structure for asynchronous operation
  116. );
  117. */
  118. #define MAX_STRING 240
  119. #define LOG_SIZE 2000
  120. #define FIRST_DEBUG_PROC 100
  121. #define OPEN_DEBUGLOG (FIRST_DEBUG_PROC)
  122. #define WRITE_DEBUGLOG (FIRST_DEBUG_PROC+1)
  123. HANDLE hDPLAY_VxD=0;
  124. typedef struct _LOGENTRY {
  125. CHAR debuglevel;
  126. CHAR str[1];
  127. } LOGENTRY, *PLOGENTRY;
  128. typedef struct {
  129. UINT nLogEntries;
  130. UINT nCharsPerLine;
  131. } IN_LOGINIT, *PIN_LOGINIT;
  132. typedef struct {
  133. UINT hr;
  134. } OUT_LOGINIT, *POUT_LOGINIT;
  135. typedef struct {
  136. CHAR debuglevel;
  137. CHAR str[1];
  138. } IN_LOGWRITE, *PIN_LOGWRITE;
  139. typedef struct {
  140. UINT hr;
  141. } OUT_LOGWRITE, *POUT_LOGWRITE;
  142. static void LogString( LPSTR str )
  143. {
  144. char logstring[MAX_STRING+sizeof(LOGENTRY)];
  145. int i=0;
  146. PLOGENTRY pLogEntry=(PLOGENTRY)logstring;
  147. UINT rc;
  148. UINT cbRet;
  149. if(hDPLAY_VxD && str){
  150. while(str[i])i++;
  151. pLogEntry->debuglevel=0;
  152. memcpy(pLogEntry->str,str,i+1);
  153. DeviceIoControl(hDPLAY_VxD,WRITE_DEBUGLOG,pLogEntry,i+sizeof(LOGENTRY), &rc, sizeof(rc), &cbRet, NULL);
  154. }
  155. }
  156. static void dumpStr( LPSTR str )
  157. {
  158. /*
  159. * Have to warm the string, since OutputDebugString is buried
  160. * deep enough that it won't page the string in before reading it.
  161. */
  162. int i=0;
  163. if (str)
  164. while(str[i])
  165. i++;
  166. if(bLogging!=2)
  167. {
  168. OUTPUTDEBUGSTRING( str );
  169. OUTPUTDEBUGSTRING("\n");
  170. }
  171. if(bLogging)
  172. {
  173. LogString(str);
  174. }
  175. }
  176. void DebugPrintfInit(void)
  177. {
  178. signed int lDebugLevel;
  179. int i;
  180. char cTopics[100];
  181. #ifndef PROF_SECT
  182. #define PROF_SECT "DirectDraw"
  183. #endif
  184. bDetailOn=1;
  185. for (i=0;i<LAST_TOPIC;i++)
  186. DebugTopics[i].bOn=FALSE;
  187. //ZeroMemory(ProcStats,sizeof(ProcStats));
  188. GETPROFILESTRING( "DirectX", DPF_CONTROL_LINE, "DefaultTopics", cTopics, sizeof(cTopics) );
  189. if (!strcmp(cTopics,"DefaultTopics"))
  190. {
  191. DebugSetTopicsAndLevels("");
  192. bAllowMisc=TRUE;
  193. bPrintAllTopics=TRUE;
  194. lDebugLevel = (signed int) GETPROFILEINT( PROF_SECT, "debug", 0 );
  195. bLogging = (signed int) GETPROFILEINT( PROF_SECT, "log" , 0);
  196. if (lDebugLevel <0)
  197. {
  198. if (lDebugLevel < -9)
  199. lDebugLevel=-9;
  200. bDetailOn |= (1<<(-lDebugLevel));
  201. }
  202. else
  203. {
  204. for (i=0;i<= (lDebugLevel<10?lDebugLevel:10);i++)
  205. bDetailOn |= 1<<i;
  206. }
  207. if(bLogging){
  208. hDPLAY_VxD = CreateFileA("\\\\.\\DPLAY",0,0,0,0,0,0);
  209. if(hDPLAY_VxD){
  210. IN_LOGINIT In;
  211. OUT_LOGINIT Out;
  212. UINT cbRet;
  213. In.nCharsPerLine=MAX_STRING;
  214. In.nLogEntries=5000;
  215. DeviceIoControl(hDPLAY_VxD,OPEN_DEBUGLOG,&In,sizeof(In), &Out, sizeof(Out), &cbRet, NULL);
  216. }
  217. }
  218. }
  219. else
  220. {
  221. DebugSetTopicsAndLevels(cTopics);
  222. if (!strcmp(cTopics,"?") && !bInited)
  223. {
  224. dumpStr("--------------" DPF_MODULE_NAME " Debug Output Control -------------");
  225. dumpStr("Each character on the control line controls a topic, a detail");
  226. dumpStr("level or an extra info. E.g. 0-36A@ means print detail levels 0");
  227. dumpStr("through 3 and 6 for topic A with source file name and line numbers.");
  228. dumpStr("The extra info control characters are:");
  229. dumpStr(" !: Break on asserts");
  230. dumpStr(" ^: Print TID of calling thread");
  231. dumpStr(" #: Print PID of calling process");
  232. dumpStr(" >: Indent on message detail levels");
  233. dumpStr(" &: Print the topic and detail level of each message");
  234. dumpStr(" =: Print function name");
  235. dumpStr(" +: Print all topics, including topic-less");
  236. dumpStr(" / or -: do not allow topic-less messages");
  237. dumpStr(" @ or $: Print source filename and line number of DPF");
  238. dumpStr("Topics for this module are:");
  239. for(i=0;strcmp(DebugTopics[i].cName,"End");i++)
  240. {
  241. OUTPUTDEBUGSTRING(" ");
  242. OUTPUTDEBUGSTRING(DebugTopics[i].cFlag);
  243. OUTPUTDEBUGSTRING(": ");
  244. dumpStr(DebugTopics[i].cName);
  245. }
  246. dumpStr("Tip: Use 0-3A to get debug info about API calls");
  247. }
  248. }
  249. bInited=TRUE;
  250. }
  251. /*
  252. *
  253. * The full output can be:
  254. * Module:(Executable,TxNNNN,PxNN):FunctionName:"file.c",#nnn(AAnn) Messagemessagemessage
  255. * or, if indentation turned on:
  256. * Module:(Executable,TxNNNN,PxNN):FunctionName:"file.c",#nnn(AAnn) Messagemessagemessage
  257. */
  258. int DebugPrintf(DWORD dwDetail, ...)
  259. {
  260. #define MSGBUFFERSIZE 1000
  261. char cMsg[MSGBUFFERSIZE];
  262. char cTopics[20];
  263. DWORD arg;
  264. LPSTR szFormat;
  265. BOOL bAllowed=FALSE;
  266. BOOL bMiscMessage=TRUE;
  267. int i;
  268. va_list ap;
  269. if (!bInited)
  270. DebugPrintfInit();
  271. if(bLogging != 2){
  272. //error checking:
  273. if (dwDetail >= 10)
  274. return 1;
  275. if ( (bDetailOn & (1<<dwDetail)) == 0 )
  276. return 1;
  277. if (bMute)
  278. return 1;
  279. }
  280. va_start(ap,dwDetail);
  281. WSPRINTF(cTopics,"%d",dwDetail);
  282. while ( (arg = va_arg(ap,DWORD)) <256 )
  283. {
  284. if (arg>0 && arg < LAST_TOPIC)
  285. {
  286. bMiscMessage=FALSE;
  287. if (DebugTopics[arg].bOn)
  288. bAllowed = TRUE;
  289. }
  290. }
  291. if (bMiscMessage)
  292. if (bAllowMisc || dwDetail == 0)
  293. bAllowed=TRUE;
  294. if ( bPrintAllTopics )
  295. bAllowed=TRUE;
  296. if (!bAllowed)
  297. return FALSE;
  298. szFormat = (LPSTR) arg;
  299. cMsg[0]=0;
  300. /*
  301. * Add the module name first
  302. */
  303. if (bPrintModuleName)
  304. {
  305. WSPRINTF( cMsg+strlen(cMsg),DPF_MODULE_NAME ":" );
  306. }
  307. if (bPrintExecutableName || bPrintTID || bPrintPID)
  308. WSPRINTF( cMsg+strlen(cMsg),"(");
  309. #ifdef WIN32
  310. #if 0
  311. /*
  312. * deleted due to RIP in GetModuleFilename on debug windows when win16 lock held
  313. */
  314. if (bPrintExecutableName)
  315. {
  316. GetModuleFileName(NULL,str,256);
  317. if (mystrrchr(str,'\\'))
  318. WSPRINTF(cMsg+strlen(cMsg),"%12s",mystrrchr(str,'\\')+1);
  319. }
  320. #endif
  321. if (bPrintPID)
  322. {
  323. if (bPrintExecutableName)
  324. strcat(cMsg,",");
  325. WSPRINTF( cMsg+strlen(cMsg),"Px%02x",GetCurrentProcessId());
  326. }
  327. if (bPrintTID)
  328. {
  329. if (bPrintExecutableName || bPrintPID)
  330. strcat(cMsg,",");
  331. WSPRINTF( cMsg+strlen(cMsg),"Tx%04x",GetCurrentThreadId());
  332. }
  333. if (bPrintExecutableName || bPrintTID || bPrintPID)
  334. WSPRINTF( cMsg+strlen(cMsg),"):");
  335. #endif
  336. if (bPrintFunctionName)
  337. {
  338. WSPRINTF( cMsg+strlen(cMsg),cFnName);
  339. }
  340. if (bPrintFileNames || bPrintLineNumbers)
  341. {
  342. if (mystrrchr(cFile,'\\'))
  343. WSPRINTF( cMsg+strlen(cMsg),":%12s",mystrrchr(cFile,'\\')+1 );
  344. else
  345. WSPRINTF( cMsg+strlen(cMsg),":%12s",cFile);
  346. WSPRINTF( cMsg+strlen(cMsg),"@%d",dwLineNo);
  347. }
  348. if (bPrintTopicsAndLevels)
  349. {
  350. WSPRINTF( cMsg+strlen(cMsg),"(%3s)",cTopics);
  351. }
  352. if (cMsg[strlen(cMsg)-1] != ':')
  353. WSPRINTF( cMsg+strlen(cMsg),":");
  354. if (bIndentOnMessageLevel)
  355. {
  356. for(i=0;(DWORD)i<dwDetail;i++)
  357. strcat(cMsg," ");
  358. }
  359. WVSPRINTF( cMsg+LSTRLEN( cMsg ), szFormat, ap);
  360. if (bAllowed)
  361. dumpStr( cMsg );
  362. va_end(ap);
  363. return 1;
  364. }
  365. void DebugSetMute(BOOL bMuteFlag)
  366. {
  367. bMute=bMuteFlag;
  368. }
  369. void DebugEnterAPI(char *pFunctionName , LPDWORD pIface)
  370. {
  371. // 7/28/2000(a-JiTay): IA64: Use %p format specifier for 32/64-bit pointers and handles.
  372. DebugPrintf(2,A,"%p->%s",pIface,pFunctionName);
  373. }
  374. void DebugSetTopicsAndLevels(char * cTopics)
  375. {
  376. int i;
  377. int j;
  378. bAllowMisc=TRUE;
  379. bBreakOnAsserts=FALSE;
  380. bPrintLineNumbers=FALSE;
  381. bPrintFileNames=FALSE;
  382. bPrintExecutableName=FALSE;
  383. bPrintTID=FALSE;
  384. bPrintPID=FALSE;
  385. bIndentOnMessageLevel=FALSE;
  386. bPrintTopicsAndLevels=FALSE;
  387. bPrintFunctionName=FALSE;
  388. bPrintAPIStats=FALSE;
  389. bPrintAllTopics=FALSE;
  390. bDetailOn=1; /* always print detail level 0*/
  391. for (i=0;(DWORD)i<strlen(cTopics);i++)
  392. {
  393. switch (cTopics[i])
  394. {
  395. case '/':
  396. case '-':
  397. bAllowMisc=FALSE;
  398. break;
  399. case '!':
  400. bBreakOnAsserts=TRUE;
  401. break;
  402. case '@':
  403. bPrintLineNumbers=TRUE;
  404. break;
  405. case '$':
  406. bPrintFileNames=TRUE;
  407. break;
  408. #if 0
  409. /*
  410. * Currently deleted because GetModuleFilename causes a RIP on debug windows when the win16
  411. * lock is held.
  412. */
  413. case '?':
  414. bPrintExecutableName=TRUE;
  415. break;
  416. #endif
  417. case '^':
  418. bPrintTID=TRUE;
  419. break;
  420. case '#':
  421. bPrintPID=TRUE;
  422. break;
  423. case '>':
  424. bIndentOnMessageLevel=TRUE;
  425. break;
  426. case '&':
  427. bPrintTopicsAndLevels=TRUE;
  428. break;
  429. case '=':
  430. bPrintFunctionName=TRUE;
  431. break;
  432. case '%':
  433. bPrintAPIStats=TRUE;
  434. break;
  435. case '+':
  436. bPrintAllTopics=TRUE;
  437. break;
  438. default:
  439. if (cTopics[i]>='0' && cTopics[i]<='9')
  440. {
  441. if (cTopics[i+1]=='-')
  442. {
  443. if (cTopics[i+2]>='0' && cTopics[i+2]<='9')
  444. {
  445. for(j=cTopics[i]-'0';j<=cTopics[i+2]-'0';j++)
  446. bDetailOn |= 1<<j;
  447. i+=2;
  448. }
  449. }
  450. else
  451. bDetailOn |= 1<<(cTopics[i]-'0');
  452. }
  453. else
  454. {
  455. for(j=0;j<LAST_TOPIC;j++)
  456. if (cTopics[i]==DebugTopics[j].cFlag[0])
  457. DebugTopics[j].bOn=TRUE;
  458. }
  459. } //end switch
  460. }
  461. }
  462. /*
  463. * NOTE: I don't want to get into error checking for buffer overflows when
  464. * trying to issue an assertion failure message. So instead I just allocate
  465. * a buffer that is "bug enough" (I know, I know...)
  466. */
  467. #define ASSERT_BUFFER_SIZE 512
  468. #define ASSERT_BANNER_STRING "************************************************************"
  469. #define ASSERT_BREAK_SECTION "BreakOnAssert"
  470. #define ASSERT_BREAK_DEFAULT FALSE
  471. #define ASSERT_MESSAGE_LEVEL 0
  472. void _DDAssert( LPCSTR szFile, int nLine, LPCSTR szCondition )
  473. {
  474. char buffer[ASSERT_BUFFER_SIZE];
  475. /*
  476. * Build the debug stream message.
  477. */
  478. WSPRINTF( buffer, "ASSERTION FAILED! File %s Line %d: %s", szFile, nLine, szCondition );
  479. /*
  480. * Actually issue the message. These messages are considered error level
  481. * so they all go out at error level priority.
  482. */
  483. dprintf( ASSERT_MESSAGE_LEVEL, ASSERT_BANNER_STRING );
  484. dprintf( ASSERT_MESSAGE_LEVEL, buffer );
  485. dprintf( ASSERT_MESSAGE_LEVEL, ASSERT_BANNER_STRING );
  486. /*
  487. * Should we drop into the debugger?
  488. */
  489. if( bBreakOnAsserts || GETPROFILEINT( PROF_SECT, ASSERT_BREAK_SECTION, ASSERT_BREAK_DEFAULT ) )
  490. {
  491. /*
  492. * Into the debugger we go...
  493. */
  494. DEBUG_BREAK();
  495. }
  496. }
  497. #ifdef cplusplus
  498. }
  499. #endif
  500. #endif //defined debug