|
|
//############################################################################
//#
//# Microsoft Windows
//# Copyright (C) Microsoft Corporation, 1992 - 1992.
//# All rights reserved.
//#
//############################################################################
//
//+----------------------------------------------------------------------------
// File: W4CTSUPP.CXX
//
// Contents: Contains support functions for docfile testing
//
// Command line: N/A
//
// Requires: must be linked with program containing function main()
//
// Notes: Compiled to create W4CTSUPP.LIB
//
// Created: RichE March 1992
//-----------------------------------------------------------------------------
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <direct.h>
#include <ctype.h>
#include <time.h>
#define __CRC32__
#include "w4ctsupp.hxx"
#include <dfdeb.hxx>
//char for separating FAT file name from extension
#define FILE_NAME_SEPARATOR '.'
//global array of interesting file sizes for IStream read/writes
USHORT ausSIZE_ARRAY[] = {0,1,2,255,256,257,511,512,513,2047,2048,2049,4095,4096,4097};
//test logging file pointer
static FILE *fileLogFile = NULL;
//should log be closed after every log write, modified by SetDebugMode()
static BOOL fCloseLogAfterWrite = FALSE;
//test name string for ErrExit and application use
char szTestName[MAX_TEST_NAME_LEN + 1] = "No Test Name Specified";
//random number seed used by test apps
USHORT usRandomSeed = 0;
//routing variable for standard out in tprintf and ErrExit calls
//can be changed from default of DEST_OUT
BYTE bDestOut = DEST_OUT;
//+----------------------------------------------------------------------------
// Function: Allocate, public
//
// Synopsis: allocate memory, exit with error if malloc failes
//
// Arguments: [cbBytesToAllocate] - size of memory block to allocate
//
// Returns: void pointer to block of memory allocated
//
// Created: RichE March 1992
//-----------------------------------------------------------------------------
void *Allocate(size_t cbBytesToAllocate) { void *pvMemPtr;
pvMemPtr = (void *) malloc(cbBytesToAllocate); if(pvMemPtr == NULL) { ErrExit(DEST_ERR, ERR, "Unable to allocate %u bytes of memory\n", cbBytesToAllocate); }
return pvMemPtr; }
//+----------------------------------------------------------------------------
// Function: MakePath, public
//
// Synopsis: makes a sub-directory at end of specified path
//
// Effects: For each char in pszDirToMake, if it's a '\', make the destination
// directory at the level accumulated in pszPathBuf, else append
// the next letter of the dest path to pszPathBuf. After the loop,
// attempt to _mkdir a final time (since the path probably won't
// end with a '\').
//
// Arguments: [pszDirToMake] - full directory path name to make
//
// Returns: TRUE if all directories in path were made OK, otherwise FALSE
//
// Created: RichE January 1992
//-----------------------------------------------------------------------------
BOOL MakePath(char *pszDirToMake) { #ifdef DBCS
char *pszDirToMakeSav = pszDirToMake; #endif
char *pcDestPathSoFar; char *pszPathBuf; int iRc;
pszPathBuf = (char *) Allocate(_MAX_PATH + 1); pcDestPathSoFar = pszPathBuf;
//
//while not at end of path string, if this char is a back slash, make
//the directory up to the slash. in either case, copy the next char
//into the accumulated path buffer.
//
while (*pszDirToMake) { if (*pszDirToMake == '\\') { *pcDestPathSoFar = NIL; iRc = _mkdir(pszPathBuf); tprintf(bDestOut, "Trying to make directory %s, returned %d\n", pszPathBuf, iRc); } #ifdef DBCS
#ifdef _MAC
if (iskanji (*pszDirToMake)) // iskanji is in dbcsutil.cpp
#else
if (IsDBCSLeadbyte (*pszDirToMake)) #endif
*pcDestPathSoFar++ = *pszDirToMake++; #endif
*pcDestPathSoFar++ = *pszDirToMake++; }
//
//if the last char wasn't a back slash, the last part of the path hasn't
//been made so make it.
//
#ifdef DBCS
#ifdef _MAC
DecLpch (pszDirToMakeSav, pszDirToMake); #else
pszDirToMake = AnsiPrev (pszDirToMakeSav, pszDirToMake); #endif // MAC
if (*pszDirToMake != '\\') #else
if (*(--pszDirToMake) != '\\') #endif
{ *pcDestPathSoFar = NIL; iRc = _mkdir(pszPathBuf); tprintf(bDestOut, "Trying to make directory %s, returned %d\n", pszPathBuf, iRc); }
free(pszPathBuf);
return (iRc == 0) ? TRUE : FALSE; }
//+----------------------------------------------------------------------------
// Function: SetDebugMode, public
//
// Synopsis: sets debugging mode and program exit control and tprintf routing
//
// Effects: Sets exit control to 'no exit when complete.' depending upon
// the char passed, in calls debug macro to set appropriate
// debug mode. If no debug is specified, sets program exit
// control to 'exit when complete' and sets flag to close log
// file after every log write. If a debug mode other than
// none is specified, redirects default output destination to
// DEST_LOG instead of DEST_OUT. Also sets capture buffer to
// unlimited size
//
// Arguments: [DebugMode] - single character representing desired mode
//
// Modifiles: [fCloseLogAfterWrite] - if running in non-debug mode, close
// log file after every write
//
// Created: RichE April 1992
//-----------------------------------------------------------------------------
void SetDebugMode(char DebugMode) { SET_DISPLAY_BUF_SIZE;
NO_EXIT_WHEN_DONE;
switch(DebugMode) { case 'a': DEBUG_ALL; bDestOut = DEST_LOG; break;
case 'n': DEBUG_NONE; EXIT_WHEN_DONE; //fCloseLogAfterWrite = TRUE;
break;
case 'd': DEBUG_DOCFILE; bDestOut = DEST_LOG; break;
case 'm': DEBUG_MSF; bDestOut = DEST_LOG; break;
case 'i': default: DEBUG_INTERNAL_ERRORS; bDestOut = DEST_LOG; break;
} }
//+----------------------------------------------------------------------------
// Function: ErrExit, public
//
// Synopsis: allows error output to any combo of stdout, stderr, and logfile
//
// Effects: depending upon flags passed in, will display (via vfprintf)
// error output to any combination of stdout, stderr, and a user-
// supplied log file. if output destination is a log file,
// will open the log file if not already open and set
// all output to the error output destination as well.
// prints docfile error message based on error code, or
// generic error message is error is undefined. prints error
// return code, prints FAIL message using extern global [szTestName]
// (defined in calling test) and exits with error code.
//
// Arguments: [bOutputDest] - bit flags specifying where output goes
// valid flags defined in W4CTSUPP.HXX
// [ErrCode] - error code to use in exit() function
// [fmt] - vfprintf formatting string
// [...] - parameters to vfprintf function
//
// Created: RichE March 1992
//-----------------------------------------------------------------------------
void ErrExit(BYTE bOutputDest, SCODE ErrCode, char *fmt, ...) { USHORT iErrIndex = 0;
struct { SCODE scErrCode; char *pszErrMessage; } aszErrMessages[] = {S_FALSE, "S_FALSE", STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION", STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND", STG_E_TOOMANYOPENFILES, "STG_E_TOOMANYOPENFILES", STG_E_ACCESSDENIED, "STG_E_ACCESSDENIED", STG_E_INVALIDHANDLE, "STG_E_INVALIDHANDLE", STG_E_INSUFFICIENTMEMORY, "STG_E_INSUFFICIENTMEMORY", STG_E_INVALIDPOINTER, "STG_E_INVALIDPOINTER", STG_E_NOMOREFILES, "STG_E_NOMOREFILES", STG_E_WRITEFAULT, "STG_E_WRITEFAULT", STG_E_READFAULT, "STG_E_READFAULT", STG_E_LOCKVIOLATION, "STG_E_LOCKVIOLATION", STG_E_FILEALREADYEXISTS, "STG_E_FILEALREADYEXISTS", STG_E_INVALIDPARAMETER, "STG_E_INVALIDPARAMETER", STG_E_MEDIUMFULL, "STG_E_MEDIUMFULL", STG_E_ABNORMALAPIEXIT, "STG_E_ABNORMALAPIEXIT", STG_E_INVALIDHEADER, "STG_E_INVALIDHEADER", STG_E_INVALIDNAME, "STG_E_INVALIDNAME", STG_E_UNKNOWN, "STG_E_UNKNOWN", STG_E_UNIMPLEMENTEDFUNCTION, "STG_E_UNIMPLEMENTEDFUNCTION", STG_E_INVALIDFLAG, "STG_E_INVALIDFLAG", STG_E_INUSE, "STG_E_INUSE", STG_E_NOTCURRENT, "STG_E_NOTCURRENT", STG_E_REVERTED, "STG_E_REVERTED", STG_S_CONVERTED, "STG_S_CONVERTED", ERR, "GENERIC_ERROR" };
va_list args;
va_start(args, fmt);
//if dest is log file, open log file if not already open
//and set all output to DEST_ERR as well.
if (bOutputDest & DEST_LOG) { bOutputDest |= DEST_ERR;
if (fileLogFile == NULL) { LogFile(NULL, LOG_OPEN); }
vfprintf(fileLogFile, fmt, args);
if (fCloseLogAfterWrite == TRUE) { LogFile(NULL, LOG_CLOSE); } }
if (bOutputDest & DEST_OUT) { vfprintf(stdout, fmt, args); }
if (bOutputDest & DEST_ERR) { vfprintf(stderr, fmt, args); }
va_end(args);
tprintf(bOutputDest, "Return code %lu (0x%08lX), ", ErrCode, ErrCode);
//lookup error in struct table and print error message
while (aszErrMessages[iErrIndex].scErrCode != ErrCode) { if (aszErrMessages[iErrIndex].scErrCode == ERR) { break; } else { iErrIndex++; } }
tprintf(bOutputDest, "%s\n", aszErrMessages[iErrIndex].pszErrMessage);
tprintf(bOutputDest, "FAIL: %s\n", szTestName);
exit((int) ErrCode); }
//+----------------------------------------------------------------------------
// Function: tprintf, public
//
// Synopsis: allows output to any combo of stdout, stderr, and logfile
//
// Effects: depending upon flags passed in, will display (via vfprintf)
// output to any combination of stdout, stderr, and a user-
// supplied log file. if output destination is a log file,
// will open the log file if not already open and set
// all output to the error output destination as well.
//
// Arguments: [bOutputDest] - bit flags specifying where output goes
// valid flags defined in W4CTSUPP.HXX
// [fmt] - vfprintf formatting string
// [...] - parameters to vfprintf function
//
// Created: RichE March 1992
//-----------------------------------------------------------------------------
void tprintf(BYTE bOutputDest, char *fmt, ...) { va_list args;
va_start(args, fmt);
//if dest is log file, open log file if not already open
//and set all output to DEST_ERR as well.
if (bOutputDest & DEST_LOG) { bOutputDest |= DEST_ERR;
if (fileLogFile == NULL) { LogFile(NULL, LOG_OPEN); }
vfprintf(fileLogFile, fmt, args);
if (fCloseLogAfterWrite == TRUE) { LogFile(NULL, LOG_CLOSE); } }
if (bOutputDest & DEST_OUT) { vfprintf(stdout, fmt, args); }
if (bOutputDest & DEST_ERR) { vfprintf(stderr, fmt, args); }
va_end(args); }
//+----------------------------------------------------------------------------
// Function: LogFile, public
//
// Synopsis: opens or closed specified file for logging via tprintf and errexit
//
// Effects: the specfied file is opened via fopen for logging purposes when
// [bLogFileAction] = LOG_OPEN and closed for LOG_CLOSE. The
// calling application should open the LogFile via a LOG_INIT
// call which will define the routine to call to ensure that the
// log file is closed upon completion and set the log file name.
//
// Modifies: [fileLogFile] - the global variable defined at top of this file
// will contain a pointer to the log file stream on exit.
//
// Arguments: [pszLogFileName] - pathname of file for logging purposes
// [bLogFileAction] - whether to open or close the log file
//
// Notes: [pszLogReOpenName] is the filename to use for opening the log
// file. In non-debug runs, the log file is closed after every
// log write and re-opened before the next write.
//
// Created: RichE March 1992
//-----------------------------------------------------------------------------
void LogFile(char *pszLogFileName, BYTE bLogFileAction) { static char *pszLogReOpenName = NULL; static BOOL fFirstInitCall = FALSE; char *pszTestDataDir;
switch (bLogFileAction) { case LOG_INIT: if (pszLogFileName == NULL) { ErrExit(DEST_ERR, ERR, "No filename specified for LOG_INIT\n"); }
if (fileLogFile != NULL) { fclose(fileLogFile); free(pszLogReOpenName); }
pszLogReOpenName = (char *) Allocate(strlen(pszLogFileName)+1); strcpy(pszLogReOpenName, pszLogFileName);
if (fFirstInitCall == FALSE) { //register function to call on program exit
//
atexit(MakeSureThatLogIsClosed); fFirstInitCall = TRUE;
//
//change to dir specified by DFDATA env variable, if it's set
//
if (pszTestDataDir = getenv("DFDATA")) { _chdir(pszTestDataDir); } }
break;
case LOG_OPEN: if (fileLogFile != NULL) { ErrExit(DEST_ERR,ERR,"Can't open log file %s, log is already open!", pszLogReOpenName); }
if (pszLogReOpenName == NULL) { pszLogReOpenName = (char *) Allocate(strlen(LOG_DEFAULT_NAME)+1); strcpy(pszLogReOpenName, LOG_DEFAULT_NAME); }
if ((fileLogFile = fopen(pszLogReOpenName, "w")) == NULL) { ErrExit(DEST_ERR, ERR, "Error opening log file %s\n", pszLogReOpenName); }
break;
case LOG_CLOSE: if (fileLogFile != NULL) { fflush(fileLogFile); fclose(fileLogFile); } else { tprintf(DEST_ERR,"Warning: can't close log file %s, log isn't open!", pszLogReOpenName); }
break;
default: ErrExit(DEST_ERR,ERR,"Invalid parameter to LogFile() function!"); } }
//+----------------------------------------------------------------------------
// Function: MakeSureThatLogFileIsClosed
//
// Synopsis: closes log file on exit
//
// Effects: immediately flushes all file buffers, and then calls Logfile to
// close the test log file. upon abnormal exit (GP fault), this saves most
// of the log information.
//
// Created: RichE March 1992
//-----------------------------------------------------------------------------
void MakeSureThatLogIsClosed(void) { //fflush(fileLogFile);
LogFile(NULL, LOG_CLOSE);
}
//+----------------------------------------------------------------------------
// Function: MakeSingle, public
//
// Synopsis: converts TCHAR string to single character string
//
// Arguments: [pszSingleName] - pointer to TCHAR string
// [ptcsWideName] - buffer to hold returned single-wide string
//
// Modifies: [pszSingleName] - on exit holds single-wide character string
//
// Created: RichE March 1992
//-----------------------------------------------------------------------------
void MakeSingle(char *pszSingleName, TCHAR *ptcsWideName) { #ifdef UNICODE
USHORT cusBufLen = (tcslen(ptcsWideName)+1) * sizeof(TCHAR);
if (_fwcstombs(pszSingleName, ptcsWideName, cusBufLen) == -1) { ErrExit(DEST_LOG, ERR, "Error converting TCHAR string to single wide\n"); } #else
strcpy(pszSingleName, ptcsWideName); #endif
}
//+----------------------------------------------------------------------------
// Function: MakeWide, public
//
// Synopsis: converts single character string to multi-byte (TCHAR) string
//
// Arguments: [ptcsWideName] - buffer to hold returned TCHAR string
// [pszSingleName] - pointer to single wide string
//
// Modifies: [ptcsWideName] - on exit holds wide character string
//
// Created: RichE March 1992
//-----------------------------------------------------------------------------
void MakeWide(TCHAR *ptcsWideName, char *pszSingleName) { #ifdef UNICODE
USHORT cusBufLen = (strlen(pszSingleName)+1) * sizeof(TCHAR);
if (_fmbstowcs(ptcsWideName, pszSingleName, cusBufLen) == -1) { ErrExit(DEST_LOG, ERR, "Error converting name %s to TCHAR string\n", pszSingleName); } #else
strcpy(ptcsWideName, pszSingleName); #endif
}
|