windows-nt/Source/XPSP1/NT/com/ole32/stg/utils/df2t/w4ctsupp.cxx
2020-09-26 16:20:57 +08:00

590 lines
18 KiB
C++

//############################################################################
//#
//# 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
}