//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1993. // // File: tutils.cxx // // Contents: Generic utilities for tests // // History: 06-Aug-93 DrewB Created // //---------------------------------------------------------------------------- #include "pch.cxx" #pragma hdrstop static BOOL fExitOnFail = TRUE; BOOL GetExitOnFail(void) { return fExitOnFail; } void SetExitOnFail(BOOL set) { fExitOnFail = set; } // Print out an error message and terminate void Fail(char *fmt, ...) { va_list args; args = va_start(args, fmt); fprintf(stderr, "** Fatal error **: "); vfprintf(stderr, fmt, args); va_end(args); EndTest(1); } 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_E_EXTANTMARSHALLINGS, "STG_E_EXTANTMARSHALLINGS", 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"; } // Output a call result and check for failure HRESULT Result(HRESULT hr, char *fmt, ...) { SCODE sc; va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); sc = GetScode(hr); printf(" - %s (0x%lX)\n", ScText(sc), sc); if (FAILED(sc) && fExitOnFail) Fail("Unexpected call failure\n"); return hr; } // Perform Result() when the expectation is failure HRESULT IllResult(HRESULT hr, char *fmt, ...) { SCODE sc; va_list args; va_start(args, fmt); vprintf(fmt, args); va_end(args); sc = GetScode(hr); printf(" - %s (0x%lX)\n", ScText(sc), sc); if (SUCCEEDED(sc) && fExitOnFail) Fail("Unexpected call success\n"); return hr; } char *TcsText(TCHAR *ptcs) { static char buf[256]; TTOA(ptcs, buf, 256); return buf; } char *FileTimeText(FILETIME *pft) { static char buf[80]; struct tm ctm; #ifndef FLAT WORD dosdate, dostime; if (CoFileTimeToDosDateTime(pft, &dosdate, &dostime)) { ctm.tm_sec = (dostime & 31)*2; ctm.tm_min = (dostime >> 5) & 63; ctm.tm_hour = dostime >> 11; ctm.tm_mday = dosdate & 31; ctm.tm_mon = ((dosdate >> 5) & 15)-1; ctm.tm_year = (dosdate >> 9)+80; ctm.tm_wday = 0; #else SYSTEMTIME st; if (FileTimeToSystemTime(pft, &st)) { ctm.tm_sec = st.wSecond; ctm.tm_min = st.wMinute; ctm.tm_hour = st.wHour; ctm.tm_mday = st.wDay; ctm.tm_mon = st.wMonth-1; ctm.tm_year = st.wYear-1900; ctm.tm_wday = st.wDayOfWeek; #endif ctm.tm_yday = 0; ctm.tm_isdst = 0; strcpy(buf, asctime(&ctm)); buf[strlen(buf)-1] = 0; } else sprintf(buf, "", pft->dwHighDateTime, pft->dwLowDateTime); return buf; } #pragma pack(1) struct SplitGuid { DWORD dw1; WORD w1; WORD w2; BYTE b[8]; }; #pragma pack() char *GuidText(GUID *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; } #define CROW 16 void BinText(ULONG cbSize, BYTE *pb) { ULONG cb, i; while (cbSize > 0) { cb = min(CROW, cbSize); cbSize -= cb; for (i = 0; i= 0x20 && pb[i] <= 0x7f) putchar(pb[i]); else putchar('.'); pb += cb; printf("'\n"); } } TCHAR *TestFile(TCHAR *ptcsName, char *pszFile) { char achFn[MAX_PATH]; char *dir, *file; int len; dir = getenv("DFDATA"); if (dir) strcpy(achFn, dir); else strcpy(achFn, "."); len = strlen(achFn); if (achFn[len-1] != '\\') achFn[len++] = '\\'; if (pszFile) { strcpy(achFn+len, pszFile); } else { file = getenv("DFFILE"); if (file) strcpy(achFn+len, file); else strcpy(achFn+len, "TEST.DFL"); } ATOT(achFn, ptcsName, MAX_PATH); return ptcsName+len; } #if WIN32 == 300 char *TestFormat(DWORD *pdwFmt, DWORD *pgrfMode) { char *fmt; fmt = getenv("STGFMT"); if (fmt == NULL || !strcmp(fmt, "doc")) { fmt = "document"; *pdwFmt = STGFMT_DOCUMENT; } else if (!strcmp(fmt, "file")) { fmt = "file"; *pdwFmt = STGFMT_FILE; } else { fmt = "directory"; *pdwFmt = STGFMT_DIRECTORY; *pgrfMode &= ~STGM_CREATE; } return fmt; } #endif BOOL CompareStatStg(STATSTG *pstat1, STATSTG *pstat2) { if (wcscmp(pstat1->pwcsName, pstat2->pwcsName) != 0) { printf("Names compared wrong: %ws and %ws\n", pstat1->pwcsName, pstat2->pwcsName); return FALSE; } if (pstat1->type != pstat2->type) { printf("Types compares wrong on %ws and %ws: %lu and %lu\n", pstat1->pwcsName, pstat2->pwcsName, pstat2->type, pstat2->type); return FALSE; } if (!IsEqualIID(pstat1->clsid, pstat2->clsid)) { printf("Class IDs for %ws and %ws compared bad\n", pstat1->pwcsName, pstat2->pwcsName); return FALSE; } if (pstat1->type == STGTY_STREAM) { if ((pstat1->cbSize).QuadPart != (pstat2->cbSize).QuadPart) { printf("Sizes for %ws and %ws compared bad: %lu and %lu\n", pstat1->pwcsName, pstat2->pwcsName, (pstat1->cbSize).LowPart, (pstat2->cbSize).LowPart); return FALSE; } } //Also check statebits and timestamps? return TRUE; } BOOL CompareStreams(IStream *pstm1, IStream *pstm2) { const ULONG BUFSIZE = 4096; BYTE buffer1[BUFSIZE]; BYTE buffer2[BUFSIZE]; ULONG cbRead1; ULONG cbRead2; STATSTG stat1; STATSTG stat2; LARGE_INTEGER li; li.QuadPart = 0; pstm1->Seek(li, STREAM_SEEK_SET, NULL); pstm2->Seek(li, STREAM_SEEK_SET, NULL); do { SCODE sc; sc = pstm1->Read(buffer1, BUFSIZE, &cbRead1); if (FAILED(sc)) { printf("Read failed with %lx\n", sc); return FALSE; } sc = pstm2->Read(buffer2, BUFSIZE, &cbRead2); if (FAILED(sc)) { printf("Read failed with %lx\n", sc); return FALSE; } if ((cbRead1 != cbRead2) || (memcmp(buffer1, buffer2, cbRead1) != 0)) { if (cbRead1 != cbRead2) { printf("Stream compare returned different bytes read: %lu and %lu\n", cbRead1, cbRead2); } else { printf("Data mismatch.\n"); } return FALSE; } } while (cbRead1 == BUFSIZE); return TRUE; } BOOL CompareStorages(IStorage *pstg1, IStorage *pstg2) { SCODE sc1, sc2, sc; IStorage *pstgChild1, *pstgChild2; IStream *pstmChild1, *pstmChild2; IEnumSTATSTG *penum1, *penum2; STATSTG stat1, stat2; pstg1->EnumElements(0, 0, 0, &penum1); pstg2->EnumElements(0, 0, 0, &penum2); do { ULONG celtFetched1, celtFetched2; sc1 = penum1->Next(1, &stat1, &celtFetched1); if (FAILED(sc1)) { printf("EnumElements 1 failed with %lx\n", sc1); return FALSE; } sc2 = penum2->Next(1, &stat2, &celtFetched2); if (FAILED(sc2) || (celtFetched1 != celtFetched2) || (sc1 != sc2)) { if (FAILED(sc2)) { printf("EnumElements 2 failed with %lx\n", sc2); } else { printf("Return code mismatch: %lx and %lx\n", sc1, sc2); } return FALSE; } if (celtFetched1 == 0) { //We're done. return TRUE; } if (!CompareStatStg(&stat1, &stat2)) { return FALSE; } //Items have compared OK so far. Now compare contents. if (stat1.type == STGTY_STREAM) { sc = pstg1->OpenStream(stat1.pwcsName, 0, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pstmChild1); if (FAILED(sc)) { printf("OpenStream on pstg1 for %ws failed with %lx\n", stat1.pwcsName, sc); return FALSE; } sc = pstg2->OpenStream(stat2.pwcsName, 0, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pstmChild2); if (FAILED(sc)) { printf("OpenStream on pstg2 for %ws failed with %lx\n", stat2.pwcsName, sc); return FALSE; } if (!CompareStreams(pstmChild1, pstmChild2)) { printf("Stream compare on %ws and %ws failed.\n", stat1.pwcsName, stat2.pwcsName); return FALSE; } pstmChild1->Release(); pstmChild2->Release(); } else { //Compare storages sc = pstg1->OpenStorage(stat1.pwcsName, NULL, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pstgChild1); if (FAILED(sc)) { printf("OpenStorage on pstg1 for %ws failed with %lx\n", stat1.pwcsName, sc); return FALSE; } sc = pstg2->OpenStorage(stat2.pwcsName, NULL, STGM_DIRECT | STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pstgChild2); if (FAILED(sc)) { printf("OpenStorage on pstg2 for %ws failed with %lx\n", stat2.pwcsName, sc); return FALSE; } if (!CompareStorages(pstgChild1, pstgChild2)) { printf("CompareStorages failed for %ws and %ws\n", stat1.pwcsName, stat2.pwcsName); return FALSE; } pstgChild1->Release(); pstgChild2->Release(); } //printf("Object %ws compared OK.\n", stat1.pwcsName); CoTaskMemFree(stat1.pwcsName); CoTaskMemFree(stat2.pwcsName); } while (sc1 != S_FALSE); return TRUE; }