|
|
//+--------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: serial.cpp
//
// Contents: serial number string encode/decode implementation
//
//---------------------------------------------------------------------------
#include <pch.cpp>
#pragma hdrstop
#define __dwFILE__ __dwFILE_CERTCLIB_SERIAL_CPP__
HRESULT ObsoleteMultiByteIntegerToWszBuf( IN BOOL fOctetString, IN DWORD cbIn, IN BYTE const *pbIn, IN OUT DWORD *pcbOut, OPTIONAL OUT WCHAR *pwszOut) { return MultiByteIntegerToWszBuf( fOctetString, cbIn, pbIn, pcbOut, pwszOut); }
HRESULT ObsoleteMultiByteIntegerToBstr( IN BOOL fOctetString, IN DWORD cbIn, IN BYTE const *pbIn, OUT BSTR *pstrOut) { return MultiByteIntegerToBstr( fOctetString, cbIn, pbIn, pstrOut); }
BOOL AsciiToNibble( IN WCHAR wc, BYTE *pb) { BOOL fOk = TRUE;
do { wc -= L'0'; if (wc <= 9) { break; } wc += (WCHAR) (L'0' - L'a' + 10); if (wc <= 15) { break; } wc += L'a' - L'A'; if (wc <= 15) { break; } fOk = FALSE; } while (FALSE);
*pb = (BYTE) wc; return(fOk); }
__inline BOOL IsMultiByteSkipChar( IN WCHAR wc) { return(L' ' == wc || L'\t' == wc); }
// WszToMultiByteIntegerBuf - convert a big endian null-terminated ascii-hex
// encoded WCHAR string of even length to a little-endian integer blob.
// If fOctetString is TRUE, preserve endian order, as in a hex dump
HRESULT WszToMultiByteIntegerBuf( IN BOOL fOctetString, IN WCHAR const *pwszIn, IN OUT DWORD *pcbOut, OPTIONAL OUT BYTE *pbOut) { HRESULT hr; WCHAR const *pwsz; DWORD cbOut;
cbOut = 0; hr = E_INVALIDARG;
if (fOctetString) { for (pwsz = pwszIn; L'\0' != *pwsz; ) { BYTE blo, bhi;
while (IsMultiByteSkipChar(*pwsz)) { pwsz++; } if (!AsciiToNibble(*pwsz, &bhi)) { _JumpError2( hr, error, "WszToMultiByteInteger: bad string", E_INVALIDARG); } pwsz++;
while (IsMultiByteSkipChar(*pwsz)) { pwsz++; } if (!AsciiToNibble(*pwsz, &blo)) { _JumpError(hr, error, "WszToMultiByteInteger: bad string"); } pwsz++;
cbOut++; if (NULL != pbOut) { if (cbOut > *pcbOut) { hr = TYPE_E_BUFFERTOOSMALL; _JumpError(hr, error, "WszToMultiByteInteger: overflow"); } *pbOut++ = blo | (bhi << 4); } } } else { for (pwsz = &pwszIn[wcslen(pwszIn) - 1]; pwsz >= pwszIn; ) { BYTE blo, bhi;
while (pwsz >= pwszIn && IsMultiByteSkipChar(*pwsz)) { pwsz--; } if (pwsz < pwszIn) { break; } if (!AsciiToNibble(*pwsz, &blo)) { _JumpError(hr, error, "WszToMultiByteInteger: bad string"); } pwsz--;
while (pwsz >= pwszIn && IsMultiByteSkipChar(*pwsz)) { pwsz--; } if (pwsz < pwszIn || !AsciiToNibble(*pwsz, &bhi)) { _JumpError(hr, error, "WszToMultiByteInteger: bad string"); } pwsz--;
cbOut++; if (NULL != pbOut) { if (cbOut > *pcbOut) { hr = TYPE_E_BUFFERTOOSMALL; _JumpError(hr, error, "WszToMultiByteInteger: overflow"); } *pbOut++ = blo | (bhi << 4); } } } *pcbOut = cbOut; hr = S_OK;
error: return(hr); }
// WszToMultiByteInteger - convert a big endian null-terminated ascii-hex
// encoded WCHAR string of even length to a little-endian integer blob.
// If fOctetString is TRUE, preserve endian order, as in a hex dump
HRESULT WszToMultiByteInteger( IN BOOL fOctetString, IN WCHAR const *pwszIn, OUT DWORD *pcbOut, OUT BYTE **ppbOut) { HRESULT hr = S_OK;
*pcbOut = 0; *ppbOut = NULL;
while (TRUE) { hr = WszToMultiByteIntegerBuf(fOctetString, pwszIn, pcbOut, *ppbOut); if (S_OK != hr) { if (NULL != *ppbOut) { LocalFree(*ppbOut); *ppbOut = NULL; } _JumpError2(hr, error, "WszToMultiByteIntegerBuf", E_INVALIDARG); } if (NULL != *ppbOut) { break; } *ppbOut = (BYTE *) LocalAlloc(LMEM_FIXED, *pcbOut); if (NULL == *ppbOut) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } }
error: return(hr); }
HRESULT caTranslateFileTimePeriodToPeriodUnits( IN FILETIME const *pftGMT, IN BOOL fExact, OUT DWORD *pcPeriodUnits, OUT PERIODUNITS **prgPeriodUnits) { HRESULT hr; LLFILETIME llft; LONGLONG llRemain; DWORD i; DWORD cPeriodUnits; PERIODUNITS *rgPeriodUnits; #define IC_YEARS 0
#define IC_MONTHS 1
#define IC_WEEKS 2
#define IC_DAYS 3
#define IC_HOURS 4
#define IC_MINUTES 5
#define IC_SECONDS 6
#define IC_MAX 7
LONG alCount[IC_MAX]; static const enum ENUM_PERIOD s_aenumPeriod[] = { ENUM_PERIOD_YEARS, ENUM_PERIOD_MONTHS, ENUM_PERIOD_WEEKS, ENUM_PERIOD_DAYS, ENUM_PERIOD_HOURS, ENUM_PERIOD_MINUTES, ENUM_PERIOD_SECONDS, }; llft.ft = *pftGMT; if (0 <= llft.ll) { hr = E_INVALIDARG; _JumpError(hr, error, "Not a time period"); } llft.ll = -llft.ll; llft.ll /= CVT_BASE; // now in seconds
ZeroMemory(alCount, sizeof(alCount)); alCount[IC_DAYS] = (LONG) (llft.ll / (60 * 60 * 24));
llRemain = llft.ll - (LONGLONG) alCount[IC_DAYS] * (60 * 60 * 24); if (fExact || 4 > alCount[IC_DAYS]) // if less than 96 hrs
{ alCount[IC_HOURS] = (LONG) llRemain / (60 * 60); if (fExact || 2 > alCount[IC_HOURS]) // if less than 120 mins
{ alCount[IC_MINUTES] = ((LONG) llRemain / 60) % 60; if (fExact || 2 > alCount[IC_MINUTES]) // if less than 120 secs
{ alCount[IC_SECONDS] = (LONG) llRemain % 60; } } }
if (0 != alCount[IC_DAYS]) { if (0 == (alCount[IC_DAYS] % 365)) { alCount[IC_YEARS] = alCount[IC_DAYS] / 365; alCount[IC_DAYS] = 0; } else if (0 == (alCount[IC_DAYS] % 30)) { alCount[IC_MONTHS] = alCount[IC_DAYS] / 30; alCount[IC_DAYS] = 0; } else if (0 == (alCount[IC_DAYS] % 7)) { alCount[IC_WEEKS] = alCount[IC_DAYS] / 7; alCount[IC_DAYS] = 0; } } cPeriodUnits = 0; for (i = 0; i < IC_MAX; i++) { if (0 != alCount[i]) { cPeriodUnits++; } } if (0 == cPeriodUnits) { cPeriodUnits++; } rgPeriodUnits = (PERIODUNITS *) LocalAlloc( LMEM_FIXED, cPeriodUnits * sizeof(rgPeriodUnits[0])); if (NULL == rgPeriodUnits) { hr = E_OUTOFMEMORY; _JumpError(hr, error, "LocalAlloc"); } *pcPeriodUnits = cPeriodUnits; *prgPeriodUnits = rgPeriodUnits;
cPeriodUnits = 0; for (i = 0; i < IC_MAX; i++) { if (0 != alCount[i] || (0 == cPeriodUnits && i + 1 == IC_MAX)) { rgPeriodUnits[cPeriodUnits].lCount = alCount[i]; rgPeriodUnits[cPeriodUnits].enumPeriod = s_aenumPeriod[i]; cPeriodUnits++; } } CSASSERT(cPeriodUnits == *pcPeriodUnits); hr = S_OK;
error: return(hr); }
|