How to: Parse a Stream from a Binary Property to Read the TZDEFINITION Structure
|
How to: Parse a Stream from a Binary Property to Read the TZDEFINITION Structure |
This topic shows how to read the TZDEFINITION structure from the persisted format stored in a binary property.
TZDEFINITION* BinToTZDEFINITION(ULONG cbDef, LPBYTE lpbDef)
{
if (!lpbDef) return NULL;
// Update this if parsing code is changed.
// This checks the size up to the flag member.
if (cbDef < 2*sizeof(BYTE) + 2*sizeof(WORD)) return NULL;
TZDEFINITION tzDef = {0};
TZRULE* lpRules = NULL;
LPBYTE lpPtr = lpbDef;
WORD cchKeyName = NULL;
WCHAR* szKeyName = NULL;
WORD i = 0;
BYTE bMajorVersion = *((BYTE*)lpPtr);
lpPtr += sizeof(BYTE);
BYTE bMinorVersion = *((BYTE*)lpPtr);
lpPtr += sizeof(BYTE);
// We only understand TZ_BIN_VERSION_MAJOR
if (TZ_BIN_VERSION_MAJOR != bMajorVersion) return NULL;
// We only understand if >= TZ_BIN_VERSION_MINOR
if (TZ_BIN_VERSION_MINOR > bMinorVersion) return NULL;
lpPtr += sizeof(WORD);
tzDef.wFlags = *((WORD*)lpPtr);
lpPtr += sizeof(WORD);
if (TZDEFINITION_FLAG_VALID_GUID & tzDef.wFlags)
{
if (lpbDef + cbDef - lpPtr < sizeof(GUID)) return NULL;
tzDef.guidTZID = *((GUID*)lpPtr);
lpPtr += sizeof(GUID);
}
if (TZDEFINITION_FLAG_VALID_KEYNAME & tzDef.wFlags)
{
if (lpbDef + cbDef - lpPtr < sizeof(WORD)) return NULL;
cchKeyName = *((WORD*)lpPtr);
lpPtr += sizeof(WORD);
if (cchKeyName)
{
if (lpbDef + cbDef - lpPtr < (BYTE)sizeof(WORD)*cchKeyName) return NULL;
szKeyName = (WCHAR*)lpPtr;
lpPtr += cchKeyName*sizeof(WORD);
}
}
if (lpbDef+ cbDef - lpPtr < sizeof(WORD)) return NULL;
tzDef.cRules = *((WORD*)lpPtr);
lpPtr += sizeof(WORD);
if (tzDef.cRules)
{
lpRules = new TZRULE[tzDef.cRules];
if (!lpRules) return NULL;
LPBYTE lpNextRule = lpPtr;
BOOL bRuleOK = false;
for (i = 0;i < tzDef.cRules;i++)
{
bRuleOK = false;
lpPtr = lpNextRule;
if (lpbDef + cbDef - lpPtr <
2*sizeof(BYTE) + 2*sizeof(WORD) + 3*sizeof(long) + 2*sizeof(SYSTEMTIME)) return NULL;
bRuleOK = true;
BYTE bRuleMajorVersion = *((BYTE*)lpPtr);
lpPtr += sizeof(BYTE);
BYTE bRuleMinorVersion = *((BYTE*)lpPtr);
lpPtr += sizeof(BYTE);
// We only understand TZ_BIN_VERSION_MAJOR
if (TZ_BIN_VERSION_MAJOR != bRuleMajorVersion) return NULL;
// We only understand if >= TZ_BIN_VERSION_MINOR
if (TZ_BIN_VERSION_MINOR > bRuleMinorVersion) return NULL;
WORD cbRule = *((WORD*)lpPtr);
lpPtr += sizeof(WORD);
lpNextRule = lpPtr + cbRule;
lpRules[i].wFlags = *((WORD*)lpPtr);
lpPtr += sizeof(WORD);
lpRules[i].stStart = *((SYSTEMTIME*)lpPtr);
lpPtr += sizeof(SYSTEMTIME);
lpRules[i].TZReg.lBias = *((long*)lpPtr);
lpPtr += sizeof(long);
lpRules[i].TZReg.lStandardBias = *((long*)lpPtr);
lpPtr += sizeof(long);
lpRules[i].TZReg.lDaylightBias = *((long*)lpPtr);
lpPtr += sizeof(long);
lpRules[i].TZReg.stStandardDate = *((SYSTEMTIME*)lpPtr);
lpPtr += sizeof(SYSTEMTIME);
lpRules[i].TZReg.stDaylightDate = *((SYSTEMTIME*)lpPtr);
lpPtr += sizeof(SYSTEMTIME);
}
if (!bRuleOK)
{
delete[] lpRules;
return NULL;
}
}
// After everything is read, allocate a structure and copy it in
size_t cbTZDef = sizeof(TZDEFINITION) +
sizeof(WCHAR)*(cchKeyName+1) +
sizeof(TZRULE)*tzDef.cRules;
TZDEFINITION* ptzDef = (TZDEFINITION*) new BYTE[cbTZDef];
if (ptzDef)
{
// Copy main struct over
*ptzDef = tzDef;
lpPtr = (LPBYTE) ptzDef;
lpPtr += sizeof(TZDEFINITION);
if (szKeyName)
{
ptzDef->pwszKeyName = (WCHAR*)lpPtr;
memcpy(lpPtr,szKeyName,cchKeyName*sizeof(WCHAR));
ptzDef->pwszKeyName[cchKeyName] = 0;
lpPtr += (cchKeyName+1)*sizeof(WCHAR);
}
if (ptzDef -> cRules && lpRules)
{
ptzDef -> rgRules = (TZRULE*)lpPtr;
for (i = 0;i < ptzdef -> cRules;i++)
{
ptzDef -> rgRules[i] = lpRules[i];
}
}
}
// Clean up lpRules
delete[] lpRules;
return ptzDef;
}
|
See Also
About Persisting TZDEFINITION to a Stream to Commit to a Binary Property
How to: Read Time Zone Properties from an Appointment