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.
 
 
 
 
 
 

480 lines
12 KiB

//+--------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1996.
//
// File: util.cxx
//
// Contents: DRT support routines
//
//---------------------------------------------------------------
#include "headers.cxx"
#include <stdarg.h>
#ifdef _WIN32
#include <direct.h>
#include <io.h>
#else
#include "winio.hxx"
#endif
#define DEFAULT_DATA_DIR "."
BOOL fExitOnFail = TRUE;
char szOrigDir[_MAX_PATH] = ".";
// Preserve the current directory and change
// directory into the data directory
void SetData(void)
{
char *pszDataDir;
_getcwd(szOrigDir, _MAX_PATH);
pszDataDir = getenv("DRTDATA");
if (pszDataDir == NULL)
pszDataDir = DEFAULT_DATA_DIR;
_chdir(pszDataDir);
}
// Clean up the data directory
void CleanData(void)
{
_unlink(pszDRTDF);
}
// Restore the original directory
void UnsetData(void)
{
_chdir(szOrigDir);
}
// Output a message if fVerbose is true
void out(char *fmt, ...)
{
va_list args;
if (fVerbose)
{
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
}
// internal error print
void _errorprint (char *fmt, va_list args)
{
printf("** Fatal error **: ");
vprintf(fmt, args);
}
// error print
void errorprint (char *fmt, ...)
{
va_list args;
va_start (args, fmt);
_errorprint (fmt, args);
va_end (args);
}
// Print out an error message and terminate the DRT
void error(int code, char *fmt, ...)
{
va_list args;
va_start(args, fmt);
_errorprint (fmt, args);
va_end(args);
CleanData();
UnsetData();
exit(code);
}
// Converts a TCHAR string to a char pointer in a temporary buffer
// This implementation treats the conversion buffer as a circular
// buffer so more than one string can be held (depending on the size
// of the strings)
#define BUFSIZE 1024
char *OlecsOut(OLECHAR const *ptcs)
{
#ifdef OLEWIDECHAR
static char szBuffer[BUFSIZE];
static char *pszBuf = szBuffer;
char *pszTmp;
if (ptcs == NULL)
return NULL;
if (wcslen(ptcs) >= (size_t)(BUFSIZE-(pszBuf-szBuffer)))
pszBuf = szBuffer;
OLETOA(ptcs, pszBuf, BUFSIZE);
szBuffer[BUFSIZE-1] = 0;
pszTmp = pszBuf;
pszBuf += strlen(pszBuf)+1;
return pszTmp;
#else
return (char *)ptcs;
#endif
}
typedef struct
{
SCODE sc;
char *text;
} StatusCodeText;
static StatusCodeText scodes[] =
{
S_OK, "S_OK",
S_FALSE, "S_FALSE",
STG_E_INVALIDFUNCTION, "STG_E_INVALIDFUNCTION",
STG_E_FILENOTFOUND, "STG_E_FILENOTFOUND",
STG_E_PATHNOTFOUND, "STG_E_PATHNOTFOUND",
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_DISKISWRITEPROTECTED, "STG_E_DISKISWRITEPROTECTED",
STG_E_SEEKERROR, "STG_E_SEEKERROR",
STG_E_WRITEFAULT, "STG_E_WRITEFAULT",
STG_E_READFAULT, "STG_E_READFAULT",
STG_E_SHAREVIOLATION, "STG_E_SHAREVIOLATION",
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_E_CANTSAVE, "STG_E_CANTSAVE",
STG_E_OLDFORMAT, "STG_E_OLDFORMAT",
STG_E_OLDDLL, "STG_E_OLDDLL",
STG_E_SHAREREQUIRED, "STG_E_SHAREREQUIRED",
STG_E_NOTFILEBASEDSTORAGE, "STG_E_NOTFILEBASEDSTORAGE",
STG_S_CONVERTED, "STG_S_CONVERTED"
};
#define NSCODETEXT (sizeof(scodes)/sizeof(scodes[0]))
// Convert a status code to text
char *ScText(SCODE sc)
{
int i;
for (i = 0; i<NSCODETEXT; i++)
if (scodes[i].sc == sc)
return scodes[i].text;
return "?";
}
// Output a call result and check for failure
HRESULT Result(HRESULT hr)
{
SCODE sc;
sc = DfGetScode(hr);
out(" - %s (0x%lX)\n", ScText(sc), sc);
if (FAILED(sc) && fExitOnFail)
error(EXIT_BADSC, "Unexpected call failure\n");
return hr;
}
// Perform Result() when the expectation is failure
HRESULT IllResult(char *pszText, HRESULT hr)
{
SCODE sc;
sc = DfGetScode(hr);
out("%s - %s (0x%lX)\n", pszText, ScText(sc), sc);
if (SUCCEEDED(sc) && fExitOnFail)
error(EXIT_BADSC, "Unexpected call success\n");
return hr;
}
// Check whether a given storage has a certain
// structure or not
// Structure is given as a string with elements:
// <Type><Name><Options>[,...]
// Type - d for docfile and s for stream
// Name - Characters up to a '(' or ','
// Options - For a docfile, you can specify a recursive check
// in parentheses
//
// Example: dDocfile(sStream,dDocfile)
char *VerifyStructure(IStorage *pstg, char *pszStructure)
{
char szName[CWCSTORAGENAME], *psz;
IStorage *pstgChild;
char chType;
SCODE sc;
CStrList sl;
SStrEntry *pse;
IEnumSTATSTG *penm;
STATSTG stat;
OLECHAR atcName[CWCSTORAGENAME];
if (FAILED(sc = DfGetScode(pstg->EnumElements(0, NULL, 0, &penm))))
error(EXIT_BADSC, "VerifyStructure: Unable to create enumerator - "
"%s (0x%lX)\n", ScText(sc), sc);
for (;;)
{
sc = DfGetScode(penm->Next(1, &stat, NULL));
if (sc == S_FALSE)
break;
else if (FAILED(sc))
error(EXIT_BADSC, "VerifyStructure: Unable to enumerate - "
"%s (0x%lX)\n", ScText(sc), sc);
pse = sl.Add(stat.pwcsName);
if (pse == NULL)
error(EXIT_OOM, "VerifyStructure: Unable to allocate string\n");
pse->user.dw = stat.type;
drtMemFree(stat.pwcsName);
}
penm->Release();
while (*pszStructure && *pszStructure != ')')
{
chType = *pszStructure++;
psz = szName;
while (*pszStructure && *pszStructure != '(' &&
*pszStructure != ')' && *pszStructure != ',')
*psz++ = *pszStructure++;
*psz = 0;
ATOOLE(szName, atcName, CWCSTORAGENAME);
pse = sl.Find(atcName);
if (pse == NULL)
error(EXIT_BADSC, "VerifyStructure: '%s' not found\n", szName);
switch(chType)
{
case 'd':
if (pse->user.dw != STGTY_STORAGE)
error(EXIT_BADSC, "VerifyStructure: '%s' is not a storage\n",
szName);
sc = DfGetScode(pstg->OpenStorage(atcName, NULL,
STGP(STGM_READWRITE), NULL,
0, &pstgChild));
if (FAILED(sc))
error(EXIT_BADSC, "VerifyStructure: can't open storage "
"'%s' - %s\n", szName, ScText(sc));
if (*pszStructure == '(')
pszStructure = VerifyStructure(pstgChild, pszStructure+1)+1;
pstgChild->Release();
break;
case 's':
if (pse->user.dw != STGTY_STREAM)
error(EXIT_BADSC, "VerifyStructure: '%s' is not a stream\n",
szName);
break;
}
sl.Remove(pse);
if (*pszStructure == ',')
pszStructure++;
}
for (pse = sl.GetHead(); pse; pse = pse->pseNext)
error(EXIT_BADSC, "VerifyStructure: additional member '%s'\n",
OlecsOut(pse->atc));
return pszStructure;
}
// Creates a structure using the same syntax
// as VerifyStructure
char *CreateStructure(IStorage *pstg, char *pszStructure)
{
char szName[CWCSTORAGENAME], *psz;
IStorage *pstgChild;
IStream *pstmChild;
char chType;
SCODE sc;
OLECHAR atcName[CWCSTORAGENAME];
while (*pszStructure && *pszStructure != ')')
{
chType = *pszStructure++;
psz = szName;
while (*pszStructure && *pszStructure != '(' &&
*pszStructure != ')' && *pszStructure != ',')
*psz++ = *pszStructure++;
*psz = 0;
ATOOLE(szName, atcName, CWCSTORAGENAME);
switch(chType)
{
case 'd':
sc = DfGetScode(pstg->CreateStorage(atcName, STGP(STGM_READWRITE),
0, 0, &pstgChild));
if (FAILED(sc))
error(EXIT_BADSC, "CreateStructure: can't create storage "
"'%s' - %s\n", szName, ScText(sc));
if (*pszStructure == '(')
pszStructure = CreateStructure(pstgChild, pszStructure+1)+1;
pstgChild->Release();
break;
case 's':
sc = DfGetScode(pstg->CreateStream(atcName, STMP(STGM_READWRITE),
0, 0, &pstmChild));
if (FAILED(sc))
error(EXIT_BADSC, "CreateStructure: can't create stream "
"'%s' - %s\n", szName, ScText(sc));
pstmChild->Release();
break;
}
if (*pszStructure == ',')
pszStructure++;
}
pstg->Commit(0);
return pszStructure;
}
// Verifies the fields of a STATSTG
void VerifyStat(STATSTG *pstat, OLECHAR *ptcsName, DWORD type, DWORD grfMode)
{
if (ptcsName == NULL)
{
if (pstat->pwcsName != NULL)
error(EXIT_BADSC, "Stat name should be NULL - is %p\n",
pstat->pwcsName);
}
else if (olecscmp(pstat->pwcsName, ptcsName))
error(EXIT_BADSC, "Stat name mismatch - has '%s' vs. '%s'\n",
OlecsOut(pstat->pwcsName), OlecsOut(ptcsName));
if (pstat->type != type)
error(EXIT_BADSC, "Stat type mismatch - has %lu vs. %lu\n",
pstat->type, type);
if (pstat->grfMode != grfMode)
error(EXIT_BADSC, "Stat mode mismatch - has 0x%lX vs. 0x%lX\n",
pstat->grfMode, grfMode);
}
// Checks on a file's existence
BOOL Exists(OLECHAR* ocsFile)
{
char pszFile[_MAX_PATH];
TTOS(ocsFile, pszFile, _tcslen(ocsFile)+1);
FILE *f=fopen(pszFile, "r");
BOOL fExists= (f!=NULL);
if (f!=NULL) fclose(f);
return (fExists);
}
// Gets a file's length
ULONG Length(OLECHAR *ocsFile)
{
ULONG cb;
char pszFile[_MAX_PATH];
TTOS(ocsFile, pszFile, _tcslen(ocsFile)+1);
FILE *f=fopen(pszFile, "r");
if (!f)
error(EXIT_BADSC, "Length: Unable to open '%s'\n", pszFile);
int rcode=fseek(f, 0, SEEK_END);
if (rcode!=0)
error(EXIT_BADSC, "Length: Unable to get length for '%s'\n",
pszFile);
cb= (ULONG) ftell(f);
fclose(f);
return cb;
}
// Equality for FILETIME
BOOL IsEqualTime(FILETIME ttTime, FILETIME ttCheck)
{
#ifdef _UNIX
#ifdef LONGLONG
#error "LONGLONG should not be defined"
#else
#define LONGLONG time_t
#endif
#endif
// File times can be off by as much as 2 seconds due to FAT rounding
LONGLONG tmTime = *(LONGLONG *)&ttTime;
LONGLONG tmCheck = *(LONGLONG *)&ttCheck;
LONGLONG tmDelta = tmTime - tmCheck;
#ifdef _UNIX
#undef LONGLONG
#endif
#ifndef _UNIX
return tmDelta < 20000000i64 && tmDelta > -2i64 ;
#else
return tmDelta < 2; // time_t is in seconds
#endif
}
// Get a fully qualified path for a file name
void GetFullPath(TCHAR *ocsFile, TCHAR *ocsPath, int len)
{
char pszPath[_MAX_PATH+1], pszFile[_MAX_PATH+1];
TTOS(ocsFile, pszFile, _tcslen(ocsFile)+1);
_fullpath(pszPath, pszFile, len);
STOT(pszPath, ocsPath, strlen(pszPath)+1);
}
// Memory helper functions
HRESULT drtMemAlloc(ULONG ulcb, void **ppv)
{
HRESULT hr;
IMalloc *pMalloc = NULL;
if (SUCCEEDED(DfGetScode(hr = CoGetMalloc(MEMCTX_TASK, &pMalloc))))
{
*ppv = pMalloc->Alloc(ulcb);
pMalloc->Release();
if (*ppv == NULL)
return ResultFromScode(E_OUTOFMEMORY);
}
return hr;
}
void drtMemFree(void *pv)
{
IMalloc FAR* pMalloc;
if (SUCCEEDED(GetScode(CoGetMalloc(MEMCTX_TASK, &pMalloc))))
{
pMalloc->Free(pv);
pMalloc->Release();
}
}
#ifdef _MSC_VER
#pragma pack(1)
#endif
struct SplitGuid
{
DWORD dw1;
WORD w1;
WORD w2;
BYTE b[8];
};
#ifdef _MSC_VER
#pragma pack()
#endif
char *GuidText(GUID const *pguid)
{
static char buf[39];
SplitGuid *psg = (SplitGuid *)pguid;
sprintf(buf, "{%08lX-%04hX-%04hX-%02X%02X-%02X%02X%02X%02X%02X%02X}",
psg->dw1, psg->w1, psg->w2, psg->b[0], psg->b[1], psg->b[2],
psg->b[3], psg->b[4], psg->b[5], psg->b[6], psg->b[7]);
return buf;
}