diff options
Diffstat (limited to 'private/ole32/stg/props/utest/rtlstub.cxx')
-rw-r--r-- | private/ole32/stg/props/utest/rtlstub.cxx | 783 |
1 files changed, 783 insertions, 0 deletions
diff --git a/private/ole32/stg/props/utest/rtlstub.cxx b/private/ole32/stg/props/utest/rtlstub.cxx new file mode 100644 index 000000000..3ad6cfaf9 --- /dev/null +++ b/private/ole32/stg/props/utest/rtlstub.cxx @@ -0,0 +1,783 @@ + + +//+============================================================================ +// +// File: RtlStub.cxx +// +// Purpose: +// This file provides some RTL routines which are also implemented +// in NTDLL. They are duplicated here so that we can build +// PropTest without linking to NTDLL, which doesn't exist +// on Win95. +// +//+============================================================================ + + + +#include "pch.cxx" // Brings in most other includes/defines/etc. + + +#define BSTRLEN(bstrVal) *((ULONG *) bstrVal - 1) + +// we use static array instead of string literals because some systems +// have 4 bytes string literals, and would not produce the correct result +// for REF's 2 byte Unicode convention +// +OLECHAR aocMap[CCH_MAP + 1] = {'a','b','c','d','e','f','g', + 'h','i','j','k','l','m','n', + 'o','p','q','r','s','t','u', + 'v','w','x','y','z', + '0','1','2','3','4','5','\0'}; + +GUID guidSummary = + { 0xf29f85e0, + 0x4ff9, 0x1068, + { 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9 } }; + +OLECHAR oszSummary[] = {'S','u','m','m','a','r','y', + 'I','n','f','o','r','m','a','t','i','o','n','\0'}; + +GUID guidDocumentSummary = + { 0xd5cdd502, + 0x2e9c, 0x101b, + { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } }; + +OLECHAR oszDocumentSummary[] = {'D','o','c','u','m','e','n','t', + 'S','u','m','m','a','r','y', + 'I','n','f','o','r','m','a','t','i','o','n', + '\0'}; + +// Note that user defined properties are placed in section 2 with the below +// GUID as the FMTID -- alas, we did not expect Office95 to actually use it. + +GUID guidDocumentSummarySection2 = + { 0xd5cdd505, + 0x2e9c, 0x101b, + { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } }; + +// *Global Info* + +GUID guidGlobalInfo = + { 0x56616F00, + 0xC154, 0x11ce, + { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } }; + +// *Image Contents* + +GUID guidImageContents = + { 0x56616500, + 0xC154, 0x11ce, + { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } }; + +// *Image Info* + +GUID guidImageInfo = + { 0x56616500, + 0xC154, 0x11ce, + { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } }; + + +//+-------------------------------------------------------------------------- +// Function: RtlGuidToPropertySetName +// +// Synopsis: Map property set GUID to null-terminated UNICODE name string. +// +// The awcname parameter is assumed to be a buffer with room for +// CWC_PROPSETSZ (28) UNICODE characters. The first character +// is always WC_PROPSET0 (0x05), as specified by the OLE Appendix +// B documentation. The colon character normally used as an NT +// stream name separator is not written to the caller's buffer. +// +// No error is possible. +// +// Arguments: IN GUID *pguid -- pointer to GUID to convert +// OUT OLECHAR aocname[] -- output string buffer +// +// Returns: count of non-NULL characters in the output string buffer +//--------------------------------------------------------------------------- + +ULONG PROPSYSAPI PROPAPI +RtlGuidToPropertySetName( + IN GUID const *pguid, + OUT OLECHAR aocname[]) +{ + ULONG cbitRemain = CBIT_BYTE; + OLECHAR *poc = aocname; + + BYTE *pb; + BYTE *pbEnd; + + *poc++ = OC_PROPSET0; + + // ----------------------- + // Check for special-cases + // ----------------------- + + // Note: CCH_PROPSET includes the OC_PROPSET0, and sizeof(osz...) + // includes the trailing '\0', so sizeof(osz...) is ok because the + // OC_PROPSET0 character compensates for the trailing NULL character. + + // Is this the SummaryInformation propset? + PROPASSERT(CCH_PROPSET >= sizeof(oszSummary)/sizeof(OLECHAR)); + + if (*pguid == guidSummary) + { + RtlCopyMemory(poc, oszSummary, sizeof(oszSummary)); + return(sizeof(oszSummary)/sizeof(OLECHAR)); + } + + // Is this The DocumentSummaryInformation or User-Defined propset? + PROPASSERT(CCH_PROPSET >= sizeof(oszDocumentSummary)/sizeof(OLECHAR)); + + if (*pguid == guidDocumentSummary || *pguid == guidDocumentSummarySection2) + { + RtlCopyMemory(poc, oszDocumentSummary, sizeof(oszDocumentSummary)); + return(sizeof(oszDocumentSummary)/sizeof(OLECHAR)); + } + + // Is this the Global Info propset? + PROPASSERT(CCH_PROPSET >= sizeof(oszGlobalInfo)/sizeof(OLECHAR)); + if (*pguid == guidGlobalInfo) + { + RtlCopyMemory(poc, oszGlobalInfo, cboszGlobalInfo); + return(cboszGlobalInfo/sizeof(OLECHAR)); + } + + // Is this the Image Contents propset? + PROPASSERT(CCH_PROPSET >= sizeof(oszImageContents)/sizeof(OLECHAR)); + if (*pguid == guidImageContents) + { + RtlCopyMemory(poc, oszImageContents, cboszImageContents); + return(cboszImageContents/sizeof(OLECHAR)); + } + + // Is this the Image Info propset? + PROPASSERT(CCH_PROPSET >= sizeof(oszImageInfo)/sizeof(OLECHAR)); + if (*pguid == guidImageInfo) + { + RtlCopyMemory(poc, oszImageInfo, cboszImageInfo); + return(cboszImageInfo/sizeof(OLECHAR)); + } + + + // ------------------------------ + // Calculate the string-ized GUID + // ------------------------------ + + // If this is a big-endian system, we need to convert + // the GUID to little-endian for the conversion. + +#if BIGENDIAN + GUID guidByteSwapped = *pguid; + PropByteSwap( &guidByteSwapped ); + pguid = &guidByteSwapped; +#endif + + // Point to the beginning and ending of the GUID + pb = (BYTE*) pguid; + pbEnd = pb + sizeof(*pguid); + + // Walk 'pb' through each byte of the GUID. + + while (pb < pbEnd) + { + ULONG i = *pb >> (CBIT_BYTE - cbitRemain); + + if (cbitRemain >= CBIT_CHARMASK) + { + *poc = MapChar(i); + if (cbitRemain == CBIT_BYTE && *poc >= (OLECHAR)'a' + && *poc <= ((OLECHAR)'z')) + { + *poc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a') ); + } + poc++; + cbitRemain -= CBIT_CHARMASK; + if (cbitRemain == 0) + { + pb++; + cbitRemain = CBIT_BYTE; + } + } + else + { + if (++pb < pbEnd) + { + i |= *pb << cbitRemain; + } + *poc++ = MapChar(i); + cbitRemain += CBIT_BYTE - CBIT_CHARMASK; + } + } // while (pb < pbEnd) + + *poc = OLESTR( '\0' ); + return(CCH_PROPSET); + +} + + +//+-------------------------------------------------------------------------- +// Function: RtlPropertySetNameToGuid +// +// Synopsis: Map non null-terminated UNICODE string to a property set GUID. +// +// If the name is not properly formed as per +// RtlGuidToPropertySetName(), STATUS_INVALID_PARAMETER is +// returned. The pguid parameter is assumed to point to a buffer +// with room for a GUID structure. +// +// Arguments: IN ULONG cocname -- count of OLECHARs in string to convert +// IN OLECHAR aocname[] -- input string to convert +// OUT GUID *pguid -- pointer to buffer for converted GUID +// +// Returns: NTSTATUS +//--------------------------------------------------------------------------- + +NTSTATUS PROPSYSAPI PROPAPI +RtlPropertySetNameToGuid( + IN ULONG cocname, + IN OLECHAR const aocname[], + OUT GUID *pguid) +{ + NTSTATUS Status = STATUS_INVALID_PARAMETER; + + OLECHAR const *poc = aocname; + + if (poc[0] == OC_PROPSET0) + { + // ----------------------- + // Check for Special-Cases + // ----------------------- + + // Note: cocname includes the OC_PROPSET0, and sizeof(osz...) + // includes the trailing OLESTR('\0'), but the comparison excludes both + // the leading OC_PROPSET0 and the trailing '\0'. + + // Is this SummaryInformation? + if (cocname == sizeof(oszSummary)/sizeof(OLECHAR) && + ocsnicmp(&poc[1], oszSummary, cocname - 1) == 0) + { + *pguid = guidSummary; + return(STATUS_SUCCESS); + } + + // Is this DocumentSummaryInformation? + if (cocname == sizeof(oszDocumentSummary)/sizeof(OLECHAR) && + ocsnicmp(&poc[1], oszDocumentSummary, cocname - 1) == 0) + { + *pguid = guidDocumentSummary; + return(STATUS_SUCCESS); + } + + // Is this Global Info? + if (cocname == cboszGlobalInfo/sizeof(OLECHAR) && + ocsnicmp(&poc[1], oszGlobalInfo, cocname - 1) == 0) + { + *pguid = guidGlobalInfo; + return(STATUS_SUCCESS); + } + + // Is this Image Info? + if (cocname == cboszImageInfo/sizeof(OLECHAR) && + ocsnicmp(&poc[1], oszImageInfo, cocname - 1) == 0) + { + *pguid = guidImageInfo; + return(STATUS_SUCCESS); + } + + // Is this Image Contents? + if (cocname == cboszImageContents/sizeof(OLECHAR) && + ocsnicmp(&poc[1], oszImageContents, cocname - 1) == 0) + { + *pguid = guidImageContents; + return(STATUS_SUCCESS); + } + + // ------------------ + // Calculate the GUID + // ------------------ + + // None of the special-cases hit, so we must calculate + // the GUID from the name. + + if (cocname == CCH_PROPSET) + { + ULONG cbit; + BYTE *pb = (BYTE *) pguid - 1; + + RtlZeroMemory(pguid, sizeof(*pguid)); + for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK) + { + ULONG cbitUsed = cbit % CBIT_BYTE; + ULONG cbitStored; + OLECHAR oc; + + if (cbitUsed == 0) + { + pb++; + } + + oc = *++poc - (OLECHAR)'A'; // assume upper case + // for wchar (unsigned) -ve values becomes a large number + // but for char, which is signed, -ve is -ve + if (oc > CALPHACHARS || oc < 0) + { + // oops, try lower case + oc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a')); + if (oc > CALPHACHARS || oc < 0) + { + // must be a digit + oc += ((OLECHAR)'a') - ((OLECHAR)'0') + CALPHACHARS; + if (oc > CHARMASK) + { + goto Exit; // invalid character + } + } + } + *pb |= (BYTE) (oc << cbitUsed); + + cbitStored = min(CBIT_BYTE - cbitUsed, CBIT_CHARMASK); + + // If the translated bits wouldn't all fit in the current byte + + if (cbitStored < CBIT_CHARMASK) + { + oc >>= CBIT_BYTE - cbitUsed; + + if (cbit + cbitStored == CBIT_GUID) + { + if (oc != 0) + { + goto Exit; // extra bits + } + break; + } + pb++; + + *pb |= (BYTE) oc; + } + } // for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK) + + Status = STATUS_SUCCESS; + + // If byte-swapping is necessary, do so now on the calculated + // GUID. + + PropByteSwap( pguid ); + + } // if (cocname == CCH_PROPSET) + } // if (poc[0] == OC_PROPSET0) + + + // ---- + // Exit + // ---- + +Exit: + + return(Status); +} + + + + +inline BOOLEAN +_Compare_VT_BOOL(VARIANT_BOOL bool1, VARIANT_BOOL bool2) +{ + // Allow any non-zero value to match any non-zero value + + return((bool1 == FALSE) == (bool2 == FALSE)); +} + + +BOOLEAN +_Compare_VT_CF(CLIPDATA *pclipdata1, CLIPDATA *pclipdata2) +{ + BOOLEAN fSame; + + if (pclipdata1 != NULL && pclipdata2 != NULL) + { + fSame = ( pclipdata1->cbSize == pclipdata2->cbSize + && + pclipdata1->ulClipFmt == pclipdata2->ulClipFmt ); + + if (fSame) + { + if (pclipdata1->pClipData != NULL && pclipdata2->pClipData != NULL) + { + fSame = memcmp( + pclipdata1->pClipData, + pclipdata2->pClipData, + CBPCLIPDATA(*pclipdata1) + ) == 0; + } + else + { + // They're the same if both are NULL, or if + // they have a zero length (if they have a zero + // length, either one may or may not be NULL, but they're + // still considered the same). + + fSame = pclipdata1->pClipData == pclipdata2->pClipData + || + CBPCLIPDATA(*pclipdata1) == 0; + } + } + } + else + { + fSame = pclipdata1 == pclipdata2; + } + return(fSame); +} + + +//+--------------------------------------------------------------------------- +// Function: RtlCompareVariants, public +// +// Synopsis: Compare two passed PROPVARIANTs -- case sensitive for strings +// +// Arguments: [CodePage] -- CodePage +// [pvar1] -- pointer to PROPVARIANT +// [pvar2] -- pointer to PROPVARIANT +// +// Returns: TRUE if identical, else FALSE +//--------------------------------------------------------------------------- + +#ifdef _MAC +EXTERN_C // The Mac linker doesn't seem to be able to export with C++ decorations +#endif + +BOOLEAN PROPSYSAPI PROPAPI +RtlCompareVariants( + USHORT CodePage, + PROPVARIANT const *pvar1, + PROPVARIANT const *pvar2) +{ + if (pvar1->vt != pvar2->vt) + { + return(FALSE); + } + + BOOLEAN fSame; + ULONG i; + + switch (pvar1->vt) + { + case VT_EMPTY: + case VT_NULL: + fSame = TRUE; + break; + +#ifdef PROPVAR_VT_I1 + case VT_I1: +#endif + case VT_UI1: + fSame = pvar1->bVal == pvar2->bVal; + break; + + case VT_I2: + case VT_UI2: + fSame = pvar1->iVal == pvar2->iVal; + break; + + case VT_BOOL: + fSame = _Compare_VT_BOOL(pvar1->boolVal, pvar2->boolVal); + break; + + case VT_I4: + case VT_UI4: + case VT_R4: + case VT_ERROR: + fSame = pvar1->lVal == pvar2->lVal; + break; + + case VT_I8: + case VT_UI8: + case VT_R8: + case VT_CY: + case VT_DATE: + case VT_FILETIME: + fSame = pvar1->hVal.HighPart == pvar2->hVal.HighPart + && + pvar1->hVal.LowPart == pvar2->hVal.LowPart; + break; + + case VT_CLSID: + fSame = memcmp(pvar1->puuid, pvar2->puuid, sizeof(CLSID)) == 0; + break; + + case VT_BLOB: + case VT_BLOB_OBJECT: + fSame = ( pvar1->blob.cbSize == pvar2->blob.cbSize ); + if (fSame) + { + fSame = memcmp( + pvar1->blob.pBlobData, + pvar2->blob.pBlobData, + pvar1->blob.cbSize) == 0; + } + break; + + case VT_CF: + fSame = _Compare_VT_CF(pvar1->pclipdata, pvar2->pclipdata); + break; + + case VT_BSTR: + if (pvar1->bstrVal != NULL && pvar2->bstrVal != NULL) + { + fSame = ( BSTRLEN(pvar1->bstrVal) == BSTRLEN(pvar2->bstrVal) ); + if (fSame) + { + fSame = memcmp( + pvar1->bstrVal, + pvar2->bstrVal, + BSTRLEN(pvar1->bstrVal)) == 0; + } + } + else + { + fSame = pvar1->bstrVal == pvar2->bstrVal; + } + break; + + case VT_LPSTR: + if (pvar1->pszVal != NULL && pvar2->pszVal != NULL) + { + fSame = strcmp(pvar1->pszVal, pvar2->pszVal) == 0; + } + else + { + fSame = pvar1->pszVal == pvar2->pszVal; + } + break; + + case VT_STREAM: + case VT_STREAMED_OBJECT: + case VT_STORAGE: + case VT_STORED_OBJECT: + case VT_LPWSTR: + if (pvar1->pwszVal != NULL && pvar2->pwszVal != NULL) + { + fSame = Prop_wcscmp(pvar1->pwszVal, pvar2->pwszVal) == 0; + } + else + { + fSame = pvar1->pwszVal == pvar2->pwszVal; + } + break; + +#ifdef PROPVAR_VT_I1 + case VT_VECTOR | VT_I1: +#endif + case VT_VECTOR | VT_UI1: + fSame = ( pvar1->caub.cElems == pvar2->caub.cElems ); + if (fSame) + { + fSame = memcmp( + pvar1->caub.pElems, + pvar2->caub.pElems, + pvar1->caub.cElems * sizeof(pvar1->caub.pElems[0])) == 0; + } + break; + + case VT_VECTOR | VT_I2: + case VT_VECTOR | VT_UI2: + fSame = ( pvar1->cai.cElems == pvar2->cai.cElems ); + if (fSame) + { + fSame = memcmp( + pvar1->cai.pElems, + pvar2->cai.pElems, + pvar1->cai.cElems * sizeof(pvar1->cai.pElems[0])) == 0; + } + break; + + case VT_VECTOR | VT_BOOL: + fSame = ( pvar1->cabool.cElems == pvar2->cabool.cElems ); + if (fSame) + { + for (i = 0; i < pvar1->cabool.cElems; i++) + { + fSame = _Compare_VT_BOOL( + pvar1->cabool.pElems[i], + pvar2->cabool.pElems[i]); + if (!fSame) + { + break; + } + } + } + break; + + case VT_VECTOR | VT_I4: + case VT_VECTOR | VT_UI4: + case VT_VECTOR | VT_R4: + case VT_VECTOR | VT_ERROR: + fSame = ( pvar1->cal.cElems == pvar2->cal.cElems ); + if (fSame) + { + fSame = memcmp( + pvar1->cal.pElems, + pvar2->cal.pElems, + pvar1->cal.cElems * sizeof(pvar1->cal.pElems[0])) == 0; + } + break; + + case VT_VECTOR | VT_I8: + case VT_VECTOR | VT_UI8: + case VT_VECTOR | VT_R8: + case VT_VECTOR | VT_CY: + case VT_VECTOR | VT_DATE: + case VT_VECTOR | VT_FILETIME: + fSame = ( pvar1->cah.cElems == pvar2->cah.cElems ); + if (fSame) + { + fSame = memcmp( + pvar1->cah.pElems, + pvar2->cah.pElems, + pvar1->cah.cElems * + sizeof(pvar1->cah.pElems[0])) == 0; + } + break; + + case VT_VECTOR | VT_CLSID: + fSame = ( pvar1->cauuid.cElems == pvar2->cauuid.cElems ); + if (fSame) + { + fSame = memcmp( + pvar1->cauuid.pElems, + pvar2->cauuid.pElems, + pvar1->cauuid.cElems * + sizeof(pvar1->cauuid.pElems[0])) == 0; + } + break; + + case VT_VECTOR | VT_CF: + fSame = ( pvar1->caclipdata.cElems == pvar2->caclipdata.cElems ); + if (fSame) + { + for (i = 0; i < pvar1->caclipdata.cElems; i++) + { + fSame = _Compare_VT_CF( + &pvar1->caclipdata.pElems[i], + &pvar2->caclipdata.pElems[i]); + if (!fSame) + { + break; + } + } + } + break; + + case VT_VECTOR | VT_BSTR: + fSame = ( pvar1->cabstr.cElems == pvar2->cabstr.cElems ); + if (fSame) + { + for (i = 0; i < pvar1->cabstr.cElems; i++) + { + if (pvar1->cabstr.pElems[i] != NULL && + pvar2->cabstr.pElems[i] != NULL) + { + fSame = ( BSTRLEN(pvar1->cabstr.pElems[i]) + == + BSTRLEN(pvar2->cabstr.pElems[i]) ); + if (fSame) + { + fSame = memcmp( + pvar1->cabstr.pElems[i], + pvar2->cabstr.pElems[i], + BSTRLEN(pvar1->cabstr.pElems[i])) == 0; + } + } + else + { + fSame = pvar1->cabstr.pElems[i] == pvar2->cabstr.pElems[i]; + } + if (!fSame) + { + break; + } + } + } + break; + + case VT_VECTOR | VT_LPSTR: + fSame = ( pvar1->calpstr.cElems == pvar2->calpstr.cElems ); + if (fSame) + { + for (i = 0; i < pvar1->calpstr.cElems; i++) + { + if (pvar1->calpstr.pElems[i] != NULL && + pvar2->calpstr.pElems[i] != NULL) + { + fSame = strcmp( + pvar1->calpstr.pElems[i], + pvar2->calpstr.pElems[i]) == 0; + } + else + { + fSame = pvar1->calpstr.pElems[i] == + pvar2->calpstr.pElems[i]; + } + if (!fSame) + { + break; + } + } + } + break; + + case VT_VECTOR | VT_LPWSTR: + fSame = ( pvar1->calpwstr.cElems == pvar2->calpwstr.cElems ); + if (fSame) + { + for (i = 0; i < pvar1->calpwstr.cElems; i++) + { + if (pvar1->calpwstr.pElems[i] != NULL && + pvar2->calpwstr.pElems[i] != NULL) + { + fSame = Prop_wcscmp( + pvar1->calpwstr.pElems[i], + pvar2->calpwstr.pElems[i]) == 0; + } + else + { + fSame = pvar1->calpwstr.pElems[i] == + pvar2->calpwstr.pElems[i]; + } + if (!fSame) + { + break; + } + } + } + break; + + case VT_VECTOR | VT_VARIANT: + fSame = ( pvar1->capropvar.cElems == pvar2->capropvar.cElems ); + if (fSame) + { + for (i = 0; i < pvar1->capropvar.cElems; i++) + { + fSame = RtlCompareVariants( + CodePage, + &pvar1->capropvar.pElems[i], + &pvar2->capropvar.pElems[i]); + if (!fSame) + { + break; + } + } + } + break; + + default: + PROPASSERT(!"Invalid type for PROPVARIANT Comparison"); + fSame = FALSE; + break; + + } + return(fSame); +} + |