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.

589 lines
18 KiB

  1. //############################################################################
  2. //#
  3. //# Microsoft Windows
  4. //# Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //# All rights reserved.
  6. //#
  7. //############################################################################
  8. //
  9. //+----------------------------------------------------------------------------
  10. // File: W4CTSUPP.CXX
  11. //
  12. // Contents: Contains support functions for docfile testing
  13. //
  14. // Command line: N/A
  15. //
  16. // Requires: must be linked with program containing function main()
  17. //
  18. // Notes: Compiled to create W4CTSUPP.LIB
  19. //
  20. // Created: RichE March 1992
  21. //-----------------------------------------------------------------------------
  22. #include <stdarg.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <direct.h>
  26. #include <ctype.h>
  27. #include <time.h>
  28. #define __CRC32__
  29. #include "w4ctsupp.hxx"
  30. #include <dfdeb.hxx>
  31. //char for separating FAT file name from extension
  32. #define FILE_NAME_SEPARATOR '.'
  33. //global array of interesting file sizes for IStream read/writes
  34. USHORT ausSIZE_ARRAY[] = {0,1,2,255,256,257,511,512,513,2047,2048,2049,4095,4096,4097};
  35. //test logging file pointer
  36. static FILE *fileLogFile = NULL;
  37. //should log be closed after every log write, modified by SetDebugMode()
  38. static BOOL fCloseLogAfterWrite = FALSE;
  39. //test name string for ErrExit and application use
  40. char szTestName[MAX_TEST_NAME_LEN + 1] = "No Test Name Specified";
  41. //random number seed used by test apps
  42. USHORT usRandomSeed = 0;
  43. //routing variable for standard out in tprintf and ErrExit calls
  44. //can be changed from default of DEST_OUT
  45. BYTE bDestOut = DEST_OUT;
  46. //+----------------------------------------------------------------------------
  47. // Function: Allocate, public
  48. //
  49. // Synopsis: allocate memory, exit with error if malloc failes
  50. //
  51. // Arguments: [cbBytesToAllocate] - size of memory block to allocate
  52. //
  53. // Returns: void pointer to block of memory allocated
  54. //
  55. // Created: RichE March 1992
  56. //-----------------------------------------------------------------------------
  57. void *Allocate(size_t cbBytesToAllocate)
  58. {
  59. void *pvMemPtr;
  60. pvMemPtr = (void *) malloc(cbBytesToAllocate);
  61. if(pvMemPtr == NULL)
  62. {
  63. ErrExit(DEST_ERR, ERR, "Unable to allocate %u bytes of memory\n",
  64. cbBytesToAllocate);
  65. }
  66. return pvMemPtr;
  67. }
  68. //+----------------------------------------------------------------------------
  69. // Function: MakePath, public
  70. //
  71. // Synopsis: makes a sub-directory at end of specified path
  72. //
  73. // Effects: For each char in pszDirToMake, if it's a '\', make the destination
  74. // directory at the level accumulated in pszPathBuf, else append
  75. // the next letter of the dest path to pszPathBuf. After the loop,
  76. // attempt to _mkdir a final time (since the path probably won't
  77. // end with a '\').
  78. //
  79. // Arguments: [pszDirToMake] - full directory path name to make
  80. //
  81. // Returns: TRUE if all directories in path were made OK, otherwise FALSE
  82. //
  83. // Created: RichE January 1992
  84. //-----------------------------------------------------------------------------
  85. BOOL MakePath(char *pszDirToMake)
  86. {
  87. #ifdef DBCS
  88. char *pszDirToMakeSav = pszDirToMake;
  89. #endif
  90. char *pcDestPathSoFar;
  91. char *pszPathBuf;
  92. int iRc;
  93. pszPathBuf = (char *) Allocate(_MAX_PATH + 1);
  94. pcDestPathSoFar = pszPathBuf;
  95. //
  96. //while not at end of path string, if this char is a back slash, make
  97. //the directory up to the slash. in either case, copy the next char
  98. //into the accumulated path buffer.
  99. //
  100. while (*pszDirToMake)
  101. {
  102. if (*pszDirToMake == '\\')
  103. {
  104. *pcDestPathSoFar = NIL;
  105. iRc = _mkdir(pszPathBuf);
  106. tprintf(bDestOut, "Trying to make directory %s, returned %d\n",
  107. pszPathBuf, iRc);
  108. }
  109. #ifdef DBCS
  110. #ifdef _MAC
  111. if (iskanji (*pszDirToMake)) // iskanji is in dbcsutil.cpp
  112. #else
  113. if (IsDBCSLeadbyte (*pszDirToMake))
  114. #endif
  115. *pcDestPathSoFar++ = *pszDirToMake++;
  116. #endif
  117. *pcDestPathSoFar++ = *pszDirToMake++;
  118. }
  119. //
  120. //if the last char wasn't a back slash, the last part of the path hasn't
  121. //been made so make it.
  122. //
  123. #ifdef DBCS
  124. #ifdef _MAC
  125. DecLpch (pszDirToMakeSav, pszDirToMake);
  126. #else
  127. pszDirToMake = AnsiPrev (pszDirToMakeSav, pszDirToMake);
  128. #endif // MAC
  129. if (*pszDirToMake != '\\')
  130. #else
  131. if (*(--pszDirToMake) != '\\')
  132. #endif
  133. {
  134. *pcDestPathSoFar = NIL;
  135. iRc = _mkdir(pszPathBuf);
  136. tprintf(bDestOut, "Trying to make directory %s, returned %d\n",
  137. pszPathBuf, iRc);
  138. }
  139. free(pszPathBuf);
  140. return (iRc == 0) ? TRUE : FALSE;
  141. }
  142. //+----------------------------------------------------------------------------
  143. // Function: SetDebugMode, public
  144. //
  145. // Synopsis: sets debugging mode and program exit control and tprintf routing
  146. //
  147. // Effects: Sets exit control to 'no exit when complete.' depending upon
  148. // the char passed, in calls debug macro to set appropriate
  149. // debug mode. If no debug is specified, sets program exit
  150. // control to 'exit when complete' and sets flag to close log
  151. // file after every log write. If a debug mode other than
  152. // none is specified, redirects default output destination to
  153. // DEST_LOG instead of DEST_OUT. Also sets capture buffer to
  154. // unlimited size
  155. //
  156. // Arguments: [DebugMode] - single character representing desired mode
  157. //
  158. // Modifiles: [fCloseLogAfterWrite] - if running in non-debug mode, close
  159. // log file after every write
  160. //
  161. // Created: RichE April 1992
  162. //-----------------------------------------------------------------------------
  163. void SetDebugMode(char DebugMode)
  164. {
  165. SET_DISPLAY_BUF_SIZE;
  166. NO_EXIT_WHEN_DONE;
  167. switch(DebugMode)
  168. {
  169. case 'a':
  170. DEBUG_ALL;
  171. bDestOut = DEST_LOG;
  172. break;
  173. case 'n':
  174. DEBUG_NONE;
  175. EXIT_WHEN_DONE;
  176. //fCloseLogAfterWrite = TRUE;
  177. break;
  178. case 'd':
  179. DEBUG_DOCFILE;
  180. bDestOut = DEST_LOG;
  181. break;
  182. case 'm':
  183. DEBUG_MSF;
  184. bDestOut = DEST_LOG;
  185. break;
  186. case 'i':
  187. default:
  188. DEBUG_INTERNAL_ERRORS;
  189. bDestOut = DEST_LOG;
  190. break;
  191. }
  192. }
  193. //+----------------------------------------------------------------------------
  194. // Function: ErrExit, public
  195. //
  196. // Synopsis: allows error output to any combo of stdout, stderr, and logfile
  197. //
  198. // Effects: depending upon flags passed in, will display (via vfprintf)
  199. // error output to any combination of stdout, stderr, and a user-
  200. // supplied log file. if output destination is a log file,
  201. // will open the log file if not already open and set
  202. // all output to the error output destination as well.
  203. // prints docfile error message based on error code, or
  204. // generic error message is error is undefined. prints error
  205. // return code, prints FAIL message using extern global [szTestName]
  206. // (defined in calling test) and exits with error code.
  207. //
  208. // Arguments: [bOutputDest] - bit flags specifying where output goes
  209. // valid flags defined in W4CTSUPP.HXX
  210. // [ErrCode] - error code to use in exit() function
  211. // [fmt] - vfprintf formatting string
  212. // [...] - parameters to vfprintf function
  213. //
  214. // Created: RichE March 1992
  215. //-----------------------------------------------------------------------------
  216. void ErrExit(BYTE bOutputDest, SCODE ErrCode, char *fmt, ...)
  217. {
  218. USHORT iErrIndex = 0;
  219. struct
  220. {
  221. SCODE scErrCode;
  222. char *pszErrMessage;
  223. } aszErrMessages[] = {S_FALSE, "S_FALSE",
  224. STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
  225. STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
  226. STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES",
  227. STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED",
  228. STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE",
  229. STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY",
  230. STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER",
  231. STG_E_NOMOREFILES, "STG_E_NOMOREFILES",
  232. STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
  233. STG_E_READFAULT, "STG_E_READFAULT",
  234. STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION",
  235. STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS",
  236. STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER",
  237. STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL",
  238. STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT",
  239. STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER",
  240. STG_E_INVALIDNAME, "STG_E_INVALIDNAME",
  241. STG_E_UNKNOWN, "STG_E_UNKNOWN",
  242. STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION",
  243. STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG",
  244. STG_E_INUSE, "STG_E_INUSE",
  245. STG_E_NOTCURRENT, "STG_E_NOTCURRENT",
  246. STG_E_REVERTED, "STG_E_REVERTED",
  247. STG_S_CONVERTED, "STG_S_CONVERTED",
  248. ERR, "GENERIC_ERROR"
  249. };
  250. va_list args;
  251. va_start(args, fmt);
  252. //if dest is log file, open log file if not already open
  253. //and set all output to DEST_ERR as well.
  254. if (bOutputDest & DEST_LOG)
  255. {
  256. bOutputDest |= DEST_ERR;
  257. if (fileLogFile == NULL)
  258. {
  259. LogFile(NULL, LOG_OPEN);
  260. }
  261. vfprintf(fileLogFile, fmt, args);
  262. if (fCloseLogAfterWrite == TRUE)
  263. {
  264. LogFile(NULL, LOG_CLOSE);
  265. }
  266. }
  267. if (bOutputDest & DEST_OUT)
  268. {
  269. vfprintf(stdout, fmt, args);
  270. }
  271. if (bOutputDest & DEST_ERR)
  272. {
  273. vfprintf(stderr, fmt, args);
  274. }
  275. va_end(args);
  276. tprintf(bOutputDest, "Return code %lu (0x%08lX), ", ErrCode, ErrCode);
  277. //lookup error in struct table and print error message
  278. while (aszErrMessages[iErrIndex].scErrCode != ErrCode)
  279. {
  280. if (aszErrMessages[iErrIndex].scErrCode == ERR)
  281. {
  282. break;
  283. }
  284. else
  285. {
  286. iErrIndex++;
  287. }
  288. }
  289. tprintf(bOutputDest, "%s\n", aszErrMessages[iErrIndex].pszErrMessage);
  290. tprintf(bOutputDest, "FAIL: %s\n", szTestName);
  291. exit((int) ErrCode);
  292. }
  293. //+----------------------------------------------------------------------------
  294. // Function: tprintf, public
  295. //
  296. // Synopsis: allows output to any combo of stdout, stderr, and logfile
  297. //
  298. // Effects: depending upon flags passed in, will display (via vfprintf)
  299. // output to any combination of stdout, stderr, and a user-
  300. // supplied log file. if output destination is a log file,
  301. // will open the log file if not already open and set
  302. // all output to the error output destination as well.
  303. //
  304. // Arguments: [bOutputDest] - bit flags specifying where output goes
  305. // valid flags defined in W4CTSUPP.HXX
  306. // [fmt] - vfprintf formatting string
  307. // [...] - parameters to vfprintf function
  308. //
  309. // Created: RichE March 1992
  310. //-----------------------------------------------------------------------------
  311. void tprintf(BYTE bOutputDest, char *fmt, ...)
  312. {
  313. va_list args;
  314. va_start(args, fmt);
  315. //if dest is log file, open log file if not already open
  316. //and set all output to DEST_ERR as well.
  317. if (bOutputDest & DEST_LOG)
  318. {
  319. bOutputDest |= DEST_ERR;
  320. if (fileLogFile == NULL)
  321. {
  322. LogFile(NULL, LOG_OPEN);
  323. }
  324. vfprintf(fileLogFile, fmt, args);
  325. if (fCloseLogAfterWrite == TRUE)
  326. {
  327. LogFile(NULL, LOG_CLOSE);
  328. }
  329. }
  330. if (bOutputDest & DEST_OUT)
  331. {
  332. vfprintf(stdout, fmt, args);
  333. }
  334. if (bOutputDest & DEST_ERR)
  335. {
  336. vfprintf(stderr, fmt, args);
  337. }
  338. va_end(args);
  339. }
  340. //+----------------------------------------------------------------------------
  341. // Function: LogFile, public
  342. //
  343. // Synopsis: opens or closed specified file for logging via tprintf and errexit
  344. //
  345. // Effects: the specfied file is opened via fopen for logging purposes when
  346. // [bLogFileAction] = LOG_OPEN and closed for LOG_CLOSE. The
  347. // calling application should open the LogFile via a LOG_INIT
  348. // call which will define the routine to call to ensure that the
  349. // log file is closed upon completion and set the log file name.
  350. //
  351. // Modifies: [fileLogFile] - the global variable defined at top of this file
  352. // will contain a pointer to the log file stream on exit.
  353. //
  354. // Arguments: [pszLogFileName] - pathname of file for logging purposes
  355. // [bLogFileAction] - whether to open or close the log file
  356. //
  357. // Notes: [pszLogReOpenName] is the filename to use for opening the log
  358. // file. In non-debug runs, the log file is closed after every
  359. // log write and re-opened before the next write.
  360. //
  361. // Created: RichE March 1992
  362. //-----------------------------------------------------------------------------
  363. void LogFile(char *pszLogFileName, BYTE bLogFileAction)
  364. {
  365. static char *pszLogReOpenName = NULL;
  366. static BOOL fFirstInitCall = FALSE;
  367. char *pszTestDataDir;
  368. switch (bLogFileAction)
  369. {
  370. case LOG_INIT:
  371. if (pszLogFileName == NULL)
  372. {
  373. ErrExit(DEST_ERR, ERR, "No filename specified for LOG_INIT\n");
  374. }
  375. if (fileLogFile != NULL)
  376. {
  377. fclose(fileLogFile);
  378. free(pszLogReOpenName);
  379. }
  380. pszLogReOpenName = (char *) Allocate(strlen(pszLogFileName)+1);
  381. strcpy(pszLogReOpenName, pszLogFileName);
  382. if (fFirstInitCall == FALSE)
  383. {
  384. //register function to call on program exit
  385. //
  386. atexit(MakeSureThatLogIsClosed);
  387. fFirstInitCall = TRUE;
  388. //
  389. //change to dir specified by DFDATA env variable, if it's set
  390. //
  391. if (pszTestDataDir = getenv("DFDATA"))
  392. {
  393. _chdir(pszTestDataDir);
  394. }
  395. }
  396. break;
  397. case LOG_OPEN:
  398. if (fileLogFile != NULL)
  399. {
  400. ErrExit(DEST_ERR,ERR,"Can't open log file %s, log is already open!",
  401. pszLogReOpenName);
  402. }
  403. if (pszLogReOpenName == NULL)
  404. {
  405. pszLogReOpenName = (char *) Allocate(strlen(LOG_DEFAULT_NAME)+1);
  406. strcpy(pszLogReOpenName, LOG_DEFAULT_NAME);
  407. }
  408. if ((fileLogFile = fopen(pszLogReOpenName, "w")) == NULL)
  409. {
  410. ErrExit(DEST_ERR, ERR, "Error opening log file %s\n",
  411. pszLogReOpenName);
  412. }
  413. break;
  414. case LOG_CLOSE:
  415. if (fileLogFile != NULL)
  416. {
  417. fflush(fileLogFile);
  418. fclose(fileLogFile);
  419. }
  420. else
  421. {
  422. tprintf(DEST_ERR,"Warning: can't close log file %s, log isn't open!",
  423. pszLogReOpenName);
  424. }
  425. break;
  426. default:
  427. ErrExit(DEST_ERR,ERR,"Invalid parameter to LogFile() function!");
  428. }
  429. }
  430. //+----------------------------------------------------------------------------
  431. // Function: MakeSureThatLogFileIsClosed
  432. //
  433. // Synopsis: closes log file on exit
  434. //
  435. // Effects: immediately flushes all file buffers, and then calls Logfile to
  436. // close the test log file. upon abnormal exit (GP fault), this saves most
  437. // of the log information.
  438. //
  439. // Created: RichE March 1992
  440. //-----------------------------------------------------------------------------
  441. void MakeSureThatLogIsClosed(void)
  442. {
  443. //fflush(fileLogFile);
  444. LogFile(NULL, LOG_CLOSE);
  445. }
  446. //+----------------------------------------------------------------------------
  447. // Function: MakeSingle, public
  448. //
  449. // Synopsis: converts TCHAR string to single character string
  450. //
  451. // Arguments: [pszSingleName] - pointer to TCHAR string
  452. // [ptcsWideName] - buffer to hold returned single-wide string
  453. //
  454. // Modifies: [pszSingleName] - on exit holds single-wide character string
  455. //
  456. // Created: RichE March 1992
  457. //-----------------------------------------------------------------------------
  458. void MakeSingle(char *pszSingleName, TCHAR *ptcsWideName)
  459. {
  460. #ifdef UNICODE
  461. USHORT cusBufLen = (tcslen(ptcsWideName)+1) * sizeof(TCHAR);
  462. if (_fwcstombs(pszSingleName, ptcsWideName, cusBufLen) == -1)
  463. {
  464. ErrExit(DEST_LOG, ERR, "Error converting TCHAR string to single wide\n");
  465. }
  466. #else
  467. strcpy(pszSingleName, ptcsWideName);
  468. #endif
  469. }
  470. //+----------------------------------------------------------------------------
  471. // Function: MakeWide, public
  472. //
  473. // Synopsis: converts single character string to multi-byte (TCHAR) string
  474. //
  475. // Arguments: [ptcsWideName] - buffer to hold returned TCHAR string
  476. // [pszSingleName] - pointer to single wide string
  477. //
  478. // Modifies: [ptcsWideName] - on exit holds wide character string
  479. //
  480. // Created: RichE March 1992
  481. //-----------------------------------------------------------------------------
  482. void MakeWide(TCHAR *ptcsWideName, char *pszSingleName)
  483. {
  484. #ifdef UNICODE
  485. USHORT cusBufLen = (strlen(pszSingleName)+1) * sizeof(TCHAR);
  486. if (_fmbstowcs(ptcsWideName, pszSingleName, cusBufLen) == -1)
  487. {
  488. ErrExit(DEST_LOG, ERR, "Error converting name %s to TCHAR string\n", pszSingleName);
  489. }
  490. #else
  491. strcpy(ptcsWideName, pszSingleName);
  492. #endif
  493. }