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.

583 lines
15 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997 - 1998
  6. //
  7. // File: debug.c
  8. //
  9. //--------------------------------------------------------------------------
  10. #ifdef DBG
  11. #include "wdmsys.h"
  12. #pragma LOCKED_CODE
  13. #pragma LOCKED_DATA
  14. //-----------------------------------------------------------------------------
  15. // Globals that affect debug output:
  16. //-----------------------------------------------------------------------------
  17. //
  18. // NOTE: The documentation expects uiDebugBreakLevel to follow uiDebugLevel
  19. // in the data segment. Thus, do not put any variables between these two.
  20. //
  21. // Default to displaying all "Warning" messages
  22. UINT uiDebugLevel = DL_ERROR ; // This should be DL_WARNING
  23. // Default to breaking on all "Error" messages
  24. UINT uiDebugBreakLevel = DL_ERROR ;
  25. char szReturningErrorStr[]="Returning Status %X";
  26. VOID
  27. GetuiDebugLevel()
  28. {
  29. //
  30. // This should read from the registry!
  31. //
  32. uiDebugLevel=DL_ERROR; //FA_NOTE|FA_HARDWAREEVENT|DL_TRACE;
  33. }
  34. VOID wdmaudDbgBreakPoint()
  35. {
  36. DbgBreakPoint();
  37. }
  38. #define DEBUG_IT
  39. //
  40. // This routine will format the start of the string. But, before it does that
  41. // it will check to see if the user should even be seeing this message.
  42. //
  43. // uiMsgLevel is the flags in the code that classify the message. This value
  44. // is used if and only if the user is filtering on that class of messages.
  45. //
  46. UINT wdmaudDbgPreCheckLevel(UINT uiMsgLevel,char *pFunction, int iLine)
  47. {
  48. UINT uiRet=0;
  49. //
  50. // If path trap, tag it and move on.
  51. //
  52. if( (uiMsgLevel&DL_MASK) == DL_PATHTRAP ) {
  53. uiRet=1;
  54. } else {
  55. //
  56. // Read this like: if there is a bit set in the upper 3 bytes of the uiDebugLevel
  57. // variable, then the user is viewing messages of a specific type. We only
  58. // want to show those messages.
  59. //
  60. if( (uiDebugLevel&FA_MASK) )
  61. {
  62. //
  63. // Yes, the user filtering on a particular class of messages. Did
  64. // we find one to display? We look at the message flags to determine this.
  65. //
  66. if( (uiMsgLevel&FA_MASK) & (uiDebugLevel&FA_MASK) )
  67. {
  68. //
  69. // Yes, we found a message of the right class. Is it at the right
  70. // level for the user to see?
  71. //
  72. if( (uiMsgLevel&DL_MASK) <= (uiDebugLevel&DL_MASK) ) {
  73. // Yes.
  74. uiRet=1;
  75. }
  76. }
  77. //
  78. // But, we always want to break on DL_ERROR messages. So, if we get here
  79. // we want to break on particular output messages but we may not have found
  80. // one. Is this message a error message?
  81. //
  82. if( (uiMsgLevel&DL_MASK) == DL_ERROR )
  83. uiRet=1;
  84. } else {
  85. //
  86. // Now check to see if the return bit is set
  87. //
  88. if(uiMsgLevel&RT_RETURN)
  89. {
  90. // we're dealing with return statement in the code. We need to
  91. // figure out what our debug level is to see if this code gets
  92. // viewed or not.
  93. //
  94. switch(uiMsgLevel&RT_MASK)
  95. {
  96. case RT_ERROR:
  97. if( (uiDebugLevel&DL_MASK) >= DL_WARNING )
  98. {
  99. uiRet=1;
  100. }
  101. break;
  102. case RT_WARNING:
  103. if( (uiDebugLevel&DL_MASK) >= DL_TRACE )
  104. {
  105. uiRet=1;
  106. #ifdef DEBUG_IT
  107. DbgPrint("Yes Return Warning %X %X\n",(uiMsgLevel&RT_MASK),(uiDebugLevel&DL_MASK));
  108. #endif
  109. }
  110. break;
  111. case RT_INFO:
  112. case 0: //SUCCESS
  113. if( (uiDebugLevel&DL_MASK) >= DL_MAX )
  114. {
  115. uiRet=1;
  116. #ifdef DEBUG_IT
  117. DbgPrint("Yes Return Status %X %X\n",(uiMsgLevel&RT_MASK),(uiDebugLevel&DL_MASK));
  118. #endif
  119. }
  120. break;
  121. default:
  122. #ifdef DEBUG_IT
  123. DbgPrint("No Return %X&RT_MASK != %X&DL_MASK\n",(uiMsgLevel&RT_MASK),(uiDebugLevel&DL_MASK));
  124. #endif
  125. break;
  126. }
  127. } else {
  128. // The user is not viewing a specific type of message "class". Do we have
  129. // a message level worth displaying?
  130. if( (uiMsgLevel&DL_MASK) <= (uiDebugLevel&DL_MASK) )
  131. {
  132. // Yes.
  133. uiRet=1;
  134. }
  135. }
  136. }
  137. }
  138. // Now just check to see if we need to display on this call.
  139. if( uiRet )
  140. {
  141. // Yes. Every message needs to start where it's from!
  142. DbgPrint("WDMAUD.SYS %s(%d) ",pFunction, iLine);
  143. // Now lable it's type.
  144. switch(uiMsgLevel&DL_MASK)
  145. {
  146. case DL_ERROR:
  147. // for return status messages, the level is not set in the
  148. // uiMsgLevel in the normal way. Thus, we need to look for it.
  149. if( uiMsgLevel&RT_RETURN )
  150. {
  151. // we have a return message.
  152. switch(uiMsgLevel&RT_MASK )
  153. {
  154. case RT_ERROR:
  155. DbgPrint("Ret Error ");
  156. break;
  157. case RT_WARNING:
  158. DbgPrint("Ret Warning ");
  159. break;
  160. case RT_INFO:
  161. DbgPrint("Ret Info ");
  162. break;
  163. default:
  164. DbgPrint("Ret Suc ");
  165. break;
  166. }
  167. } else {
  168. DbgPrint("Error ");
  169. }
  170. break;
  171. case DL_WARNING:
  172. DbgPrint("Warning ");
  173. break;
  174. case DL_TRACE:
  175. DbgPrint("Trace ");
  176. break;
  177. case DL_MAX:
  178. DbgPrint("Max ");
  179. break;
  180. case DL_PATHTRAP:
  181. DbgPrint("Path Trap ");
  182. break;
  183. default:
  184. break;
  185. }
  186. // when uiRet is positive, we've displayed the header info. Tell the
  187. // macro that we're in display mode.
  188. }
  189. return uiRet;
  190. }
  191. UINT wdmaudDbgPostCheckLevel(UINT uiMsgLevel)
  192. {
  193. UINT uiRet=0;
  194. // Always finish the line.
  195. #ifdef HTTP
  196. DbgPrint(" &DL=%08X, see \\\\debugtips\\msgs\\wdmauds.htm\n",&uiDebugLevel);
  197. #else
  198. DbgPrint(" &DL=%08X\n",&uiDebugLevel);
  199. #endif
  200. //
  201. // uiDebugBreakLevel is set to DL_ERROR (0) by default. Any time we come
  202. // across an error message we will break in the debugger. If the user
  203. // wants to break on other messages, they can change uiDebugBreakLevel to
  204. // DL_WARNING, DL_TRACE or DL_MAX and break on any message of this level.
  205. //
  206. if( ( (uiMsgLevel&DL_MASK) <= uiDebugBreakLevel ) ||
  207. ( (uiMsgLevel&DL_MASK) == DL_PATHTRAP ) )
  208. {
  209. // The user wants to break on these messages.
  210. DbgBreakPoint();
  211. uiRet = 1;
  212. }
  213. return uiRet;
  214. }
  215. typedef struct _MSGS {
  216. ULONG ulMsg;
  217. char *pString;
  218. } ERROR_MSGS, *PERROR_MSGS;
  219. #define MAPERR(_msg_) {_msg_,#_msg_},
  220. ERROR_MSGS ReturnCodes[]={
  221. MAPERR(STATUS_OBJECT_NAME_NOT_FOUND)
  222. MAPERR(STATUS_UNSUCCESSFUL)
  223. MAPERR(STATUS_INVALID_PARAMETER)
  224. MAPERR(STATUS_NOT_FOUND)
  225. MAPERR(STATUS_INVALID_DEVICE_REQUEST)
  226. MAPERR(STATUS_TOO_LATE)
  227. MAPERR(STATUS_NO_SUCH_DEVICE)
  228. MAPERR(STATUS_NOT_SUPPORTED)
  229. MAPERR(STATUS_DEVICE_OFF_LINE)
  230. MAPERR(STATUS_PROPSET_NOT_FOUND)
  231. MAPERR(STATUS_BUFFER_TOO_SMALL)
  232. MAPERR(STATUS_INVALID_BUFFER_SIZE)
  233. {0,NULL},
  234. {0,"Not Mapped"}
  235. };
  236. char * wdmaudReturnString(ULONG ulMsg)
  237. {
  238. PERROR_MSGS pTable=ReturnCodes;
  239. while(pTable->pString != NULL)
  240. {
  241. if(pTable->ulMsg==ulMsg)
  242. return pTable->pString;
  243. pTable++;
  244. }
  245. pTable++;
  246. return pTable->pString;
  247. }
  248. //
  249. // Sometimes there are return codes that are expected other then SUCCESS. We
  250. // need to be able to filter on them rather then displaying them.
  251. //
  252. #define _INTSIZEOF(n) ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
  253. //#define va_start(ap,v) ap = (va_list)&v + _INTSIZEOF(v)
  254. #define va_start(ap,v) ap = (va_list)&v
  255. #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
  256. #define va_end(ap) ap = (va_list)0
  257. //
  258. // This routine simply walks the parameter list looking to see if status
  259. // matches any of the other parameters. Why? Well, sometimes error codes
  260. // are expected. Thus, you don't want to display an error if you are expecting
  261. // that error message.
  262. //
  263. // Do, to use this function, the first parameter represents how many unsigned long
  264. // parameters fallow. The first unsigned long "status" is that actual return
  265. // code. All the other unsigned longs are the exceptable error codes.
  266. //
  267. // wdmaudExclusionList(2, status, STATUS_INVALID_PARAMETER);
  268. //
  269. // wdmaudExlutionList(4, status, STATUS_INVALID_PARAMETER,
  270. // STATUS_NO_SUCH_DEVICE,
  271. // STATUS_INVALID_DEVICE_REQUEST);
  272. //
  273. // it returns 1 if status == any one of the supplied status codes. 0 otherwise.
  274. //
  275. int __cdecl wdmaudExclusionList(int lcount, unsigned long status,... )
  276. {
  277. int count,i;
  278. int iFound=0;
  279. unsigned long value;
  280. unsigned long rstatus;
  281. va_list arglist;
  282. va_start(arglist, lcount);
  283. count = va_arg(arglist, int);
  284. rstatus = va_arg(arglist, unsigned long);
  285. for(i=1; i<count; i++) {
  286. value = va_arg(arglist, unsigned long);
  287. if( rstatus == value )
  288. {
  289. iFound = 1; //It's in the list! show the error.
  290. break;
  291. }
  292. }
  293. va_end(arglist);
  294. return iFound;
  295. }
  296. /////////////////////////////////////////////////////////////////////////////
  297. //
  298. // These are helper routines so that no assumptions are made.
  299. //
  300. /////////////////////////////////////////////////////////////////////////////
  301. /////////////////////////////////////////////////////////////////////////////
  302. //
  303. // IsValidWdmaContext
  304. //
  305. // Validates that the pointer is a valid PWDMACONTEXT pointer.
  306. //
  307. BOOL
  308. IsValidWdmaContext(
  309. IN PWDMACONTEXT pWdmaContext
  310. )
  311. {
  312. NTSTATUS Status=STATUS_SUCCESS;
  313. try
  314. {
  315. if( pWdmaContext->dwSig != CONTEXT_SIGNATURE )
  316. {
  317. DPF(DL_ERROR|FA_ASSERT,("Invalid pWdmaContext->dwSig(%08X)",pWdmaContext->dwSig) );
  318. Status=STATUS_UNSUCCESSFUL;
  319. }
  320. }
  321. except (EXCEPTION_EXECUTE_HANDLER)
  322. {
  323. Status = GetExceptionCode();
  324. }
  325. if( NT_SUCCESS(Status) )
  326. {
  327. return TRUE;
  328. } else {
  329. DPFBTRAP();
  330. return FALSE;
  331. }
  332. }
  333. /////////////////////////////////////////////////////////////////////////////
  334. //
  335. // IsValidDeviceInfo
  336. //
  337. // Validates that the pointer is a LPDEVICEINFO type.
  338. //
  339. BOOL
  340. IsValidDeviceInfo(
  341. IN LPDEVICEINFO pDeviceInfo
  342. )
  343. {
  344. NTSTATUS Status=STATUS_SUCCESS;
  345. try
  346. {
  347. if( pDeviceInfo->DeviceNumber >= MAXNUMDEVS )
  348. {
  349. DPF(DL_ERROR|FA_ASSERT,("DeviceNumber(%d) >= MAXNUMDEVS(%d)",
  350. pDeviceInfo->DeviceNumber,MAXNUMDEVS) );
  351. Status=STATUS_UNSUCCESSFUL;
  352. }
  353. }
  354. except (EXCEPTION_EXECUTE_HANDLER)
  355. {
  356. Status = GetExceptionCode();
  357. }
  358. if( NT_SUCCESS(Status) )
  359. {
  360. return TRUE;
  361. } else {
  362. DPFBTRAP();
  363. return FALSE;
  364. }
  365. }
  366. /////////////////////////////////////////////////////////////////////////////
  367. //
  368. // ValidMixerObject
  369. //
  370. // Validates that the pointer is a MIXEROBJECT type.
  371. //
  372. BOOL
  373. IsValidMixerObject(
  374. IN PMIXEROBJECT pmxobj
  375. )
  376. {
  377. NTSTATUS Status=STATUS_SUCCESS;
  378. try
  379. {
  380. if( pmxobj->dwSig != MIXEROBJECT_SIGNATURE )
  381. {
  382. DPF(DL_ERROR|FA_ASSERT,("Invalid pmxobj->dwSig(%08X)",pmxobj->dwSig) );
  383. Status=STATUS_UNSUCCESSFUL;
  384. }
  385. if( pmxobj->pfo == NULL )
  386. {
  387. DPF(DL_ERROR|FA_ASSERT,("Invalid pmxobj->pfo(%08X)",pmxobj->pfo) );
  388. Status=STATUS_UNSUCCESSFUL;
  389. }
  390. if( !IsValidMixerDevice(pmxobj->pMixerDevice) )
  391. {
  392. DPF(DL_ERROR|FA_ASSERT,("Invalid pmxobj->pMixerDevice(%08X)",pmxobj->pMixerDevice) );
  393. Status=STATUS_UNSUCCESSFUL;
  394. }
  395. }
  396. except (EXCEPTION_EXECUTE_HANDLER)
  397. {
  398. DPFBTRAP();
  399. Status = GetExceptionCode();
  400. }
  401. if( NT_SUCCESS(Status) )
  402. {
  403. return TRUE;
  404. } else {
  405. return FALSE;
  406. }
  407. }
  408. /////////////////////////////////////////////////////////////////////////////
  409. //
  410. // ValidMixerDevice
  411. //
  412. // Validates that the pointer is a MIXERDEVICE type.
  413. //
  414. BOOL
  415. IsValidMixerDevice(
  416. IN PMIXERDEVICE pmxd
  417. )
  418. {
  419. NTSTATUS Status=STATUS_SUCCESS;
  420. try
  421. {
  422. if( pmxd->dwSig != MIXERDEVICE_SIGNATURE )
  423. {
  424. DPF(DL_ERROR|FA_ASSERT,("Invalid pmxd->dwSig(%08X)",pmxd->dwSig) );
  425. Status=STATUS_UNSUCCESSFUL;
  426. }
  427. if( !IsValidWdmaContext(pmxd->pWdmaContext) )
  428. {
  429. DPF(DL_ERROR|FA_ASSERT,("Invalid pmxd->pWdmaContext(%08X)",pmxd->pWdmaContext) );
  430. Status=STATUS_UNSUCCESSFUL;
  431. }
  432. if( pmxd->pfo == NULL )
  433. {
  434. DPF(DL_ERROR|FA_ASSERT,("fo NULL in MixerDevice") );
  435. Status=STATUS_UNSUCCESSFUL;
  436. }
  437. }
  438. except (EXCEPTION_EXECUTE_HANDLER)
  439. {
  440. Status = GetExceptionCode();
  441. }
  442. if( NT_SUCCESS(Status) )
  443. {
  444. return TRUE;
  445. } else {
  446. return FALSE;
  447. }
  448. }
  449. /////////////////////////////////////////////////////////////////////////////
  450. //
  451. // IsValidLine
  452. //
  453. // Validates that the pointer is a MXLLINE type.
  454. //
  455. BOOL
  456. IsValidLine(
  457. IN PMXLLINE pLine
  458. )
  459. {
  460. NTSTATUS Status=STATUS_SUCCESS;
  461. try
  462. {
  463. if( ( pLine->SourceId == INVALID_ID ) ||
  464. ( pLine->DestId == INVALID_ID ) )
  465. {
  466. DPF(DL_ERROR|FA_ASSERT,("Bad SourceId(%08X) or DestId(%08X)",
  467. pLine->SourceId,pLine->DestId ) );
  468. Status=STATUS_UNSUCCESSFUL;
  469. }
  470. }
  471. except (EXCEPTION_EXECUTE_HANDLER)
  472. {
  473. Status = GetExceptionCode();
  474. }
  475. if( NT_SUCCESS(Status) )
  476. {
  477. return TRUE;
  478. } else {
  479. DPFBTRAP();
  480. return FALSE;
  481. }
  482. }
  483. /////////////////////////////////////////////////////////////////////////////
  484. //
  485. // IsValidControl
  486. //
  487. // Validates that the pointer is a MXLCONTROL type.
  488. //
  489. BOOL
  490. IsValidControl(
  491. IN PMXLCONTROL pControl
  492. )
  493. {
  494. NTSTATUS Status=STATUS_SUCCESS;
  495. //
  496. // Hack for contrls that fail to disable change notifications
  497. //
  498. if( pControl == LIVE_CONTROL )
  499. {
  500. DPF(DL_WARNING|FA_NOTE,("Fake control in list!") );
  501. return Status;
  502. }
  503. try
  504. {
  505. if( pControl->Tag != CONTROL_TAG )
  506. {
  507. DPF(DL_ERROR|FA_ASSERT,("Invalid pControl(%08X)->Tag(%08X)",pControl,pControl->Tag) );
  508. Status=STATUS_UNSUCCESSFUL;
  509. }
  510. }
  511. except (EXCEPTION_EXECUTE_HANDLER)
  512. {
  513. Status = GetExceptionCode();
  514. }
  515. if( NT_SUCCESS(Status) )
  516. {
  517. return TRUE;
  518. } else {
  519. return FALSE;
  520. }
  521. }
  522. #endif