Ensure VarBstrCat handles null parms as per windows and actually does

the concatenation even for null args.
This commit is contained in:
Jason Edmeades 2002-07-05 01:22:03 +00:00 committed by Alexandre Julliard
parent 0bb6fdda90
commit daec720709

View File

@ -101,7 +101,7 @@ static char pBuffer[BUFFER_MAX];
* 400 then it is a leap year. * 400 then it is a leap year.
*/ */
/* /*
* Use 365 days/year and a manual calculation for leap year days * Use 365 days/year and a manual calculation for leap year days
* to keep arithmetic simple * to keep arithmetic simple
*/ */
@ -153,7 +153,7 @@ static const double DAYS_IN_ONE_YEAR = 365.0;
#define TOK_AMPM 0x2e #define TOK_AMPM 0x2e
typedef struct tagFORMATTOKEN { typedef struct tagFORMATTOKEN {
char *str; char *str;
BYTE tokenSize; BYTE tokenSize;
BYTE tokenId; BYTE tokenId;
int varTypeRequired; int varTypeRequired;
@ -354,7 +354,7 @@ static BOOL TmToDATE( struct tm* pTm, DATE *pDateOut )
* Note a leap year is one that is a multiple of 4 * Note a leap year is one that is a multiple of 4
* but not of a 100. Except if it is a multiple of * but not of a 100. Except if it is a multiple of
* 400 then it is a leap year. * 400 then it is a leap year.
* Copied + reversed functionality into TmToDate * Copied + reversed functionality into TmToDate
*/ */
*pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 ); *pDateOut += ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
*pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 ); *pDateOut -= ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
@ -502,7 +502,7 @@ BOOL DateToTm( DATE dateIn, DWORD dwFlags, struct tm* pTm )
* Note a leap year is one that is a multiple of 4 * Note a leap year is one that is a multiple of 4
* but not of a 100. Except if it is a multiple of * but not of a 100. Except if it is a multiple of
* 400 then it is a leap year. * 400 then it is a leap year.
* Copied + reversed functionality from TmToDate * Copied + reversed functionality from TmToDate
*/ */
nDay -= ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 ); nDay -= ( (pTm->tm_year - 1) / 4 ) - ( 1900 / 4 );
nDay += ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 ); nDay += ( (pTm->tm_year - 1) / 100 ) - ( 1900 / 100 );
@ -4359,7 +4359,7 @@ HRESULT WINAPI VarCyFromDate(DATE dateIn, CY* pcyOut) {
* FIXME: Never tested with decimal seperator other than '.' * FIXME: Never tested with decimal seperator other than '.'
*/ */
HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) { HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut) {
LPSTR pNewString = NULL; LPSTR pNewString = NULL;
char *decSep = NULL; char *decSep = NULL;
char *strPtr,*curPtr = NULL; char *strPtr,*curPtr = NULL;
@ -4376,7 +4376,7 @@ HRESULT WINAPI VarCyFromStr(OLECHAR *strIn, LCID lcid, ULONG dwFlags, CY *pcyOut
rc = GetLocaleInfoA(lcid, LOCALE_SDECIMAL, decSep, size); rc = GetLocaleInfoA(lcid, LOCALE_SDECIMAL, decSep, size);
TRACE("Decimal Seperator is '%s'\n", decSep); TRACE("Decimal Seperator is '%s'\n", decSep);
/* Now copy to temporary buffer, skipping any character except 0-9 and /* Now copy to temporary buffer, skipping any character except 0-9 and
the decimal seperator */ the decimal seperator */
curPtr = pBuffer; /* Current position in string being built */ curPtr = pBuffer; /* Current position in string being built */
strPtr = pNewString; /* Current position in supplied currenct string */ strPtr = pNewString; /* Current position in supplied currenct string */
@ -4568,7 +4568,7 @@ HRESULT WINAPI VarNumFromParseNum(NUMPARSE * pnumprs, BYTE * rgbDig,
VarCyFromInt( (int) xint, &V_UNION(pvar,cyVal) ); VarCyFromInt( (int) xint, &V_UNION(pvar,cyVal) );
TRACE("Calculated cy is %ld,%lu\n", V_UNION(pvar,cyVal).s.Hi, V_UNION(pvar,cyVal).s.Lo); TRACE("Calculated cy is %ld,%lu\n", V_UNION(pvar,cyVal).s.Hi, V_UNION(pvar,cyVal).s.Lo);
return VarCyFromInt( (int) xint, &V_UNION(pvar,cyVal) ); return VarCyFromInt( (int) xint, &V_UNION(pvar,cyVal) );
} }
FIXME("vtbitmask is unsupported %lx, int=%d\n",dwVtBits, (int) xint); FIXME("vtbitmask is unsupported %lx, int=%d\n",dwVtBits, (int) xint);
return E_FAIL; return E_FAIL;
@ -4916,18 +4916,22 @@ HRESULT WINAPI VarBstrCmp(BSTR left, BSTR right, LCID lcid, DWORD flags)
HRESULT WINAPI VarBstrCat(BSTR left, BSTR right, BSTR *out) HRESULT WINAPI VarBstrCat(BSTR left, BSTR right, BSTR *out)
{ {
BSTR result; BSTR result;
int size = 0;
TRACE("( %s %s %p )\n", debugstr_w(left), debugstr_w(right), out); TRACE("( %s %s %p )\n", debugstr_w(left), debugstr_w(right), out);
if( (!left) || (!right) || (!out) ) /* On Windows, NULL parms are still handled (as empty strings) */
return 0; if (left) size=size + lstrlenW(left);
if (right) size=size + lstrlenW(right);
result = SysAllocStringLen(left, lstrlenW(left)+lstrlenW(right)); if (out) {
lstrcatW(result,right); result = SysAllocStringLen(NULL, size);
*out = result;
*out = result; if (left) lstrcatW(result,left);
if (right) lstrcatW(result,right);
return 1; TRACE("result = %s, [%p]\n", debugstr_w(result), result);
}
return S_OK;
} }
/********************************************************************** /**********************************************************************
@ -4987,7 +4991,7 @@ HRESULT WINAPI VarCmp(LPVARIANT left, LPVARIANT right, LCID lcid, DWORD flags)
return VarBstrCmp(V_BSTR(left), V_BSTR(right), lcid, flags); return VarBstrCmp(V_BSTR(left), V_BSTR(right), lcid, flags);
} }
/* Integers - Ideally like to use VarDecCmp, but no Dec support yet /* Integers - Ideally like to use VarDecCmp, but no Dec support yet
Use LONGLONG to maximize ranges */ Use LONGLONG to maximize ranges */
lOk = TRUE; lOk = TRUE;
switch (V_VT(left)&VT_TYPEMASK) { switch (V_VT(left)&VT_TYPEMASK) {
@ -5137,7 +5141,7 @@ HRESULT WINAPI VarNot(LPVARIANT in, LPVARIANT result)
* <token> - Insert appropriate token * <token> - Insert appropriate token
* *
*/ */
HRESULT VarTokenizeFormatString(LPOLESTR format, LPBYTE rgbTok, HRESULT VarTokenizeFormatString(LPOLESTR format, LPBYTE rgbTok,
int cbTok, int iFirstDay, int iFirstWeek, int cbTok, int iFirstDay, int iFirstWeek,
LCID lcid, int *pcbActual) { LCID lcid, int *pcbActual) {
@ -5176,7 +5180,7 @@ HRESULT VarTokenizeFormatString(LPOLESTR format, LPBYTE rgbTok,
checkStr = 0; checkStr = 0;
while (checkStr>=0 && (formatTokens[checkStr].tokenSize != 0x00)) { while (checkStr>=0 && (formatTokens[checkStr].tokenSize != 0x00)) {
if (formatLeft >= formatTokens[checkStr].tokenSize && if (formatLeft >= formatTokens[checkStr].tokenSize &&
strncmp(formatTokens[checkStr].str, pFormatA, strncmp(formatTokens[checkStr].str, pFormatA,
formatTokens[checkStr].tokenSize) == 0) { formatTokens[checkStr].tokenSize) == 0) {
TRACE("match on '%s'\n", formatTokens[checkStr].str); TRACE("match on '%s'\n", formatTokens[checkStr].str);
@ -5273,7 +5277,7 @@ HRESULT VarTokenizeFormatString(LPOLESTR format, LPBYTE rgbTok,
return S_OK; return S_OK;
} }
/********************************************************************** /**********************************************************************
* VarFormatFromTokens [OLEAUT32.472] * VarFormatFromTokens [OLEAUT32.472]
* FIXME: No account of flags or iFirstDay etc * FIXME: No account of flags or iFirstDay etc
@ -5290,7 +5294,7 @@ HRESULT VarFormatFromTokens(LPVARIANT varIn, LPOLESTR format,
int size, whichToken; int size, whichToken;
VARIANTARG Variant; VARIANTARG Variant;
struct tm TM; struct tm TM;
TRACE("'%s', %p %lx %p only date support\n", pFormatA, pbTokCur, dwFlags, pbstrOut); TRACE("'%s', %p %lx %p only date support\n", pFormatA, pbTokCur, dwFlags, pbstrOut);
@ -5315,7 +5319,7 @@ HRESULT VarFormatFromTokens(LPVARIANT varIn, LPOLESTR format,
if (formatTokens[whichToken].tokenSize > 0 && if (formatTokens[whichToken].tokenSize > 0 &&
formatTokens[whichToken].varTypeRequired != 0) { formatTokens[whichToken].varTypeRequired != 0) {
VariantInit( &Variant ); VariantInit( &Variant );
if (Coerce( &Variant, lcid, dwFlags, varIn, if (Coerce( &Variant, lcid, dwFlags, varIn,
formatTokens[whichToken].varTypeRequired ) != S_OK) { formatTokens[whichToken].varTypeRequired ) != S_OK) {
HeapFree( GetProcessHeap(), 0, pFormatA ); HeapFree( GetProcessHeap(), 0, pFormatA );
return DISP_E_TYPEMISMATCH; return DISP_E_TYPEMISMATCH;
@ -5476,10 +5480,10 @@ HRESULT VarFormatFromTokens(LPVARIANT varIn, LPOLESTR format,
* VarFormat [OLEAUT32.469] * VarFormat [OLEAUT32.469]
* *
*/ */
HRESULT WINAPI VarFormat(LPVARIANT varIn, LPOLESTR format, HRESULT WINAPI VarFormat(LPVARIANT varIn, LPOLESTR format,
int firstDay, int firstWeek, ULONG dwFlags, int firstDay, int firstWeek, ULONG dwFlags,
BSTR *pbstrOut) { BSTR *pbstrOut) {
LPSTR pNewString = NULL; LPSTR pNewString = NULL;
HRESULT rc = S_OK; HRESULT rc = S_OK;
@ -5487,13 +5491,13 @@ HRESULT WINAPI VarFormat(LPVARIANT varIn, LPOLESTR format,
debugstr_w(format), firstDay, firstWeek, dwFlags); debugstr_w(format), firstDay, firstWeek, dwFlags);
TRACE("varIn:\n"); TRACE("varIn:\n");
dump_Variant(varIn); dump_Variant(varIn);
/* Get format string */ /* Get format string */
pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, format ); pNewString = HEAP_strdupWtoA( GetProcessHeap(), 0, format );
/* FIXME: Handle some simple pre-definted format strings : */ /* FIXME: Handle some simple pre-definted format strings : */
if (((V_VT(varIn)&VT_TYPEMASK) == VT_CY) && (lstrcmpiA(pNewString, "Currency") == 0)) { if (((V_VT(varIn)&VT_TYPEMASK) == VT_CY) && (lstrcmpiA(pNewString, "Currency") == 0)) {
/* Can't use VarBstrFromCy as it does not put currency sign on nor decimal places */ /* Can't use VarBstrFromCy as it does not put currency sign on nor decimal places */
double curVal; double curVal;
rc = VarR8FromCy(V_UNION(varIn,cyVal), &curVal); rc = VarR8FromCy(V_UNION(varIn,cyVal), &curVal);
@ -5506,28 +5510,26 @@ HRESULT WINAPI VarFormat(LPVARIANT varIn, LPOLESTR format,
*pbstrOut = StringDupAtoBstr( pBuffer ); *pbstrOut = StringDupAtoBstr( pBuffer );
} }
} }
} else if ((V_VT(varIn)&VT_TYPEMASK) == VT_DATE) { } else if ((V_VT(varIn)&VT_TYPEMASK) == VT_DATE) {
/* Attempt to do proper formatting! */ /* Attempt to do proper formatting! */
int firstToken = -1; int firstToken = -1;
rc = VarTokenizeFormatString(format, pBuffer, sizeof(pBuffer), firstDay, rc = VarTokenizeFormatString(format, pBuffer, sizeof(pBuffer), firstDay,
firstWeek, GetUserDefaultLCID(), &firstToken); firstWeek, GetUserDefaultLCID(), &firstToken);
if (rc==S_OK) { if (rc==S_OK) {
rc = VarFormatFromTokens(varIn, format, pBuffer, dwFlags, pbstrOut, GetUserDefaultLCID()); rc = VarFormatFromTokens(varIn, format, pBuffer, dwFlags, pbstrOut, GetUserDefaultLCID());
} }
} else { } else {
FIXME("Unsupported format!\n"); FIXME("Unsupported format!\n");
*pbstrOut = StringDupAtoBstr( "??" ); *pbstrOut = StringDupAtoBstr( "??" );
} }
/* Free allocated storage */ /* Free allocated storage */
HeapFree( GetProcessHeap(), 0, pNewString ); HeapFree( GetProcessHeap(), 0, pNewString );
TRACE("result: '%s'\n", debugstr_w(*pbstrOut)); TRACE("result: '%s'\n", debugstr_w(*pbstrOut));
return rc; return rc;
} }