Beispiel #1
0
//+---------------------------------------------------------------
//
//  Member:     FatStream::Init
//
//  Synopsis:   Initialize the class.
//
//----------------------------------------------------------------
HRESULT FatStream::Init(HANDLE hfile, LPCTSTR pchFile)
{
    HRESULT hr = S_OK;

    _hfile = hfile;

    if(pchFile)
    {
        hr = _cstrFileName.Set(pchFile);
    }

    RRETURN(hr);
}
Beispiel #2
0
CString CUtils::GetFromRegistry(HKEY hLoc, const char * szKeyName, const char * szNodeName)
{
	HKEY hKey = NULL;
	char cszResult[MAX_PATH];
	CString szResult;
	DWORD dwSize = 255;

	if(RegOpenKeyEx(hLoc, szKeyName, NULL, KEY_READ, &hKey) == ERROR_SUCCESS)
	{
		DWORD dwType = REG_SZ;
		RegQueryValueEx(hKey, szNodeName, NULL, &dwType, (BYTE *)cszResult, &dwSize);
		szResult.Set(cszResult);
		RegCloseKey(hKey);
		return szResult;
	}
	return NULL;
}
Beispiel #3
0
/* 
 Message-id format:
   <file-path-relative-to-dataDir?xxx=yyy:zzz!1,2,3>
where:
   xxx   - part number (integer)
   xxx   - offset from which to read the files (integer)
   yyy   - size of file block to return (integer)
   1,2,3 - list of server ids, which have the article (optional),
           if the list is given and current server is not in the list
           the "article not found"-error is returned.
 Examples:
	<parchecker/testfile.dat?1=0:50000>	       - return first 50000 bytes starting from beginning
	<parchecker/testfile.dat?2=50000:50000>      - return 50000 bytes starting from offset 50000
	<parchecker/testfile.dat?2=50000:50000!2>    - article is missing on server 1
*/
void NntpProcessor::ServArticle()
{
	detail("[%i] Serving: %s", m_id, m_messageid);

	if (m_latency)
	{
		usleep(1000 * m_latency);
	}

	bool ok = false;

	const char* from = strchr(m_messageid, '?');
	const char* off = strchr(m_messageid, '=');
	const char* to = strchr(m_messageid, ':');
	const char* end = strchr(m_messageid, '>');
	const char* serv = strchr(m_messageid, '!');

	if (from && off && to && end)
	{
		m_filename.Set(m_messageid + 1, (int)(from - m_messageid - 1));
		m_part = atoi(from + 1);
		m_offset = atoll(off + 1);
		m_size = atoi(to + 1);

		ok = !serv || ServerInList(serv + 1);

		if (ok)
		{
			SendSegment();
			return;
		}

		if (!ok)
		{
			m_connection->WriteLine("430 No Such Article Found\r\n");
		}
	}
	else
	{
		m_connection->WriteLine("430 No Such Article Found (invalid message id format)\r\n");
	}
}
Beispiel #4
0
void CLuaVM::Pop(CString& str, CString strDefaultValue)
{
	int argType = lua_type(m_pVM, m_iStackIndex);
	if(argType == LUA_TSTRING || argType == LUA_TNUMBER)
	{
		size_t length = 0;
		str.Set(lua_tolstring(m_pVM, m_iStackIndex++, &length), length);
		return;
	} else {
		if(argType == LUA_TNONE || argType == LUA_TNIL)
		{
			str = strDefaultValue;              
			m_iStackIndex++;
			return;
		}
	}

	str = "";
	m_iStackIndex++;
}
Beispiel #5
0
bool CHttpClient::ParseHeaders(const char * szBuffer, int& iBufferSize, int& iHeaderSize)
{
    // Find amount of whitespace
    int iWhiteSpace = 0;

    for (int i = 0; i < iBufferSize; i++)
    {
        if (szBuffer[i] != ' ')
            break;

        // Increment the whitespace amount
        iWhiteSpace++;
    }

    // Increment the header size
    iHeaderSize += iWhiteSpace;

    // Ignore the version, status code and status message
    // Will be in format 'HTTP/1.0 200 OK\r\n'
    int iIgnore = strfind(szBuffer, iBufferSize, "\r\n", iHeaderSize);

    if (iIgnore == -1)
        return false;

    int iIgnoreSize = (iIgnore - iHeaderSize);

    // Increment the header size
    iHeaderSize += (iIgnoreSize + 2); // + 2 for '\r\n'

    // Find all headers
    int iNameSplit;
    int iValueSplit;

    while ((iNameSplit = strfind(szBuffer, iBufferSize, ": ", iHeaderSize, "\r\n")) != -1)
    {
        // Get the header name
        int iNameSize = (iNameSplit - iHeaderSize);
        CString strName;
        strName.Set((szBuffer + iHeaderSize), iNameSize);

        // Increment the header size
        iHeaderSize += (iNameSize + 2); // + 2 for '\r\n'

        // Find the value end
        iValueSplit = strfind(szBuffer, iBufferSize, "\r\n", iHeaderSize);

        // Did we not find a value end?
        if (iValueSplit == -1)
            return false;

        // Get the header value
        int iValueSize = (iValueSplit - iHeaderSize);
        CString strValue;
        strValue.Set((szBuffer + iHeaderSize), iValueSize);

        // Increment the header size
        iHeaderSize += (iValueSize + 2); // + 2 for '\r\n'

        // Add the header to the header map
        m_headerMap[strName] = strValue;
    }

    // Did we not get any headers?
    if (m_headerMap.empty())
        return false;

    // Ignore the '\r\n' after the headers
    iHeaderSize += 2;

    // Decrement the buffer size by the header size
    iBufferSize -= iHeaderSize;

    // Success
    return true;
}
Beispiel #6
0
//+---------------------------------------------------------------
//
//  Member:     PROPERTYDESC::HandleStyleComponentProperty, public
//
//  Synopsis:   Helper for getting/setting url style sheet properties...
//              url(string)
//
//  Arguments:  dwOpCode        -- encodes the incoming type (PROPTYPE_FLAG) in the upper WORD and
//                                 the opcode in the lower WORD (HANDLERPROP_FLAGS)
//                                 PROPTYPE_EMPTY means the 'native' type (long in this case)
//              pv              -- points to the 'media' the value is stored for the get and set
//              pObject         -- object owns the property
//              pSubObject      -- subobject storing the property (could be the main object)
//
//----------------------------------------------------------------
HRESULT PROPERTYDESC::HandleStyleComponentProperty(DWORD dwOpCode, void* pv, CBase* pObject, CVoid* pSubObject) const
{
    HRESULT hr = S_OK;
    VARIANT varDest;
    size_t nLenIn = (size_t) -1;
    DWORD dispid = GetBasicPropParams()->dispid;
    BSTR bstrTemp; // Used by some of the stream writers
    BOOL fTDPropertyValue=FALSE; // If this is a SET of a text-decoration sub-property, this is the value
    WORD wFlags = 0;

    if(ISSET(dwOpCode))
    {
        Assert(!(ISSTREAM(dwOpCode))); // we can't do this yet...
        switch(dispid)
        {
        case DISPID_A_TEXTDECORATIONNONE:
        case DISPID_A_TEXTDECORATIONUNDERLINE:
        case DISPID_A_TEXTDECORATIONOVERLINE:
        case DISPID_A_TEXTDECORATIONLINETHROUGH:
        case DISPID_A_TEXTDECORATIONBLINK:
            Assert(PROPTYPE(dwOpCode)==PROPTYPE_VARIANT && "Text-decoration subproperties must take variants!");
            Assert(V_VT((VARIANT*)pv)==VT_BOOL && "Text-decoration subproperties must take BOOLEANs!");
            fTDPropertyValue = !!((VARIANT*)pv)->boolVal;
            break;

        default:
            switch(PROPTYPE(dwOpCode))
            {
            case PROPTYPE_VARIANT:
                if(V_VT((VARIANT*)pv) == VT_BSTR)
                {
                    pv = (void*)V_BSTR((VARIANT*)pv);
                }
                else
                {
                    hr = VariantChangeTypeSpecial(&varDest, (VARIANT*)pv,  VT_BSTR);
                    if(hr)
                    {
                        goto Cleanup;
                    }
                    pv = V_BSTR(&varDest);
                }

                //intentional fallthrough
            case PROPTYPE_LPWSTR:
                switch(dispid)
                {
                case DISPID_A_BACKGROUNDIMAGE:
                case DISPID_A_LISTSTYLEIMAGE:
                case DISPID_A_FONTFACESRC:
                    nLenIn = ValidStyleUrl((TCHAR*)pv);
                    if(OPCODE(dwOpCode) == HANDLEPROP_VALUE)
                    {
                        if(!nLenIn && _tcsicmp((TCHAR*)pv, _T("none")))
                        {
                            hr = E_INVALIDARG;
                            goto Cleanup;
                        }
                    }
                    break;

                case DISPID_A_BEHAVIOR:
                    nLenIn = pv ? _tcslen((TCHAR*)pv) : 0;
                    break;
                }
                break;

            default:
                Assert(FALSE); // We shouldn't get here.
            }
            break;
        }

        switch(dispid)
        {
        case DISPID_A_LISTSTYLEIMAGE:
        case DISPID_A_BACKGROUNDIMAGE:
        case DISPID_A_FONTFACESRC:
        case DISPID_A_BEHAVIOR:
            if(nLenIn && (nLenIn!=(size_t)-1))
            {
                if(DISPID_A_BEHAVIOR == dispid)
                {
                    hr = HandleStringProperty(dwOpCode, (TCHAR*)pv, pObject, pSubObject);
                }
                else
                {
                    TCHAR* pch = (TCHAR*)pv;
                    TCHAR* psz = pch + 4;
                    TCHAR* quote = NULL;
                    TCHAR* pszEnd;
                    TCHAR terminator;

                    while(_istspace(*psz))
                    {
                        psz++;
                    }
                    if(*psz==_T('\'') || *psz==_T('"'))
                    {
                        quote = psz++;
                    }
                    nLenIn--; // Skip back over the ')' character - we know there is one, because ValidStyleUrl passed this string.
                    pszEnd = pch + nLenIn - 1;
                    while(_istspace(*pszEnd) && (pszEnd>psz))
                    {
                        pszEnd--;
                    }
                    if(quote && (*pszEnd==*quote))
                    {
                        pszEnd--;
                    }
                    terminator = *(pszEnd+1);
                    *(pszEnd+1) = _T('\0');
                    hr = HandleStringProperty(dwOpCode, psz, pObject, pSubObject);
                    *(pszEnd+1) = terminator;
                }
            }
            else
            {
                if(!pv || !*(TCHAR*)pv)
                {
                    // Empty string - delete the entry.
                    CAttrArray** ppAA = (CAttrArray**)pSubObject;

                    if(*ppAA)
                    {
                        (*ppAA)->FindSimpleAndDelete(dispid, CAttrValue::AA_StyleAttribute, NULL);
                    }
                }
                else if(!_tcsicmp((TCHAR*)pv, _T("none")))
                {
                    hr = HandleStringProperty(dwOpCode, (void*)_T(""), pObject, pSubObject);
                }
                else
                {
                    hr = E_INVALIDARG;
                }
            }
            break;

        case DISPID_A_BACKGROUND:
            hr = ParseBackgroundProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode),
                (TCHAR*)pv, (OPCODE(dwOpCode)==HANDLEPROP_VALUE));
            break;
        case DISPID_A_FONT:
            if(pv && FindSystemFontByName((TCHAR*)pv)!=sysfont_non_system)
            {
                hr = HandleStringProperty(dwOpCode, pv, pObject, pSubObject);
            }
            else
            {
                hr = ParseFontProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            }
            break;
        case DISPID_A_LAYOUTGRID:
            hr = ParseLayoutGridProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            break;
        case DISPID_A_TEXTAUTOSPACE:
            if(dwOpCode & HANDLEPROP_IMPORTANT)
            {
                wFlags |= CAttrValue::AA_Extra_Important;
            }
            if(dwOpCode & HANDLEPROP_IMPLIED)
            {
                wFlags |= CAttrValue::AA_Extra_Implied;
            }

            hr = ParseTextAutospaceProperty((CAttrArray**)pSubObject, (LPCTSTR)pv, wFlags);
            break;
        case DISPID_A_TEXTDECORATION:
            if(dwOpCode & HANDLEPROP_IMPORTANT)
            {
                wFlags |= CAttrValue::AA_Extra_Important;
            }
            if(dwOpCode & HANDLEPROP_IMPLIED)
            {
                wFlags |= CAttrValue::AA_Extra_Implied;
            }

            hr = ParseTextDecorationProperty((CAttrArray**)pSubObject, (LPCTSTR)pv, wFlags);
            break;
        case DISPID_A_TEXTDECORATIONNONE:
        case DISPID_A_TEXTDECORATIONUNDERLINE:
        case DISPID_A_TEXTDECORATIONOVERLINE:
        case DISPID_A_TEXTDECORATIONLINETHROUGH:
        case DISPID_A_TEXTDECORATIONBLINK:
            {
                VARIANT v;

                v.vt = VT_I4;
                v.lVal = 0;
                if(*((CAttrArray**)pSubObject))
                {
                    // See if we already have a text-decoration value
                    CAttrValue* pAV = (*((CAttrArray**)pSubObject))->Find(DISPID_A_TEXTDECORATION, CAttrValue::AA_Attribute);
                    if(pAV)
                    {
                        // We do!  Copy its value into our working variant
                        v.lVal = pAV->GetLong();
                    }
                }
                switch(dispid)
                {
                case DISPID_A_TEXTDECORATIONNONE:
                    if(fTDPropertyValue)
                    {
                        v.lVal = TD_NONE; // "none" clears all the other properties (unlike the other properties)
                    }
                    else
                    {
                        v.lVal &= ~TD_NONE;
                    }
                    break;
                case DISPID_A_TEXTDECORATIONUNDERLINE:
                    if(fTDPropertyValue)
                    {
                        v.lVal |= TD_UNDERLINE;
                    }
                    else
                    {
                        v.lVal &= ~TD_UNDERLINE;
                    }
                    break;
                case DISPID_A_TEXTDECORATIONOVERLINE:
                    if(fTDPropertyValue)
                    {
                        v.lVal |= TD_OVERLINE;
                    }
                    else
                    {
                        v.lVal &= ~TD_OVERLINE;
                    }
                    break;
                case DISPID_A_TEXTDECORATIONLINETHROUGH:
                    if(fTDPropertyValue)
                    {
                        v.lVal |= TD_LINETHROUGH;
                    }
                    else
                    {
                        v.lVal &= ~TD_LINETHROUGH;
                    }
                    break;
                case DISPID_A_TEXTDECORATIONBLINK:
                    if(fTDPropertyValue)
                    {
                        v.lVal |= TD_BLINK;
                    }
                    else
                    {
                        v.lVal &= ~TD_BLINK;
                    }
                    break;
                }
                if(dwOpCode & HANDLEPROP_IMPORTANT)
                {
                    wFlags |= CAttrValue::AA_Extra_Important;
                }
                if ( dwOpCode & HANDLEPROP_IMPLIED)
                {
                    wFlags |= CAttrValue::AA_Extra_Implied;
                }
                hr = CAttrArray::Set((CAttrArray**)pSubObject, DISPID_A_TEXTDECORATION, &v,
                    (PROPERTYDESC*)&s_propdescCStyletextDecoration, CAttrValue::AA_StyleAttribute, wFlags);
            }
            dispid = DISPID_A_TEXTDECORATION; // This is so we call OnPropertyChange for the right property below.
            break;

        case DISPID_A_MARGIN:
        case DISPID_A_PADDING:
            hr = ParseExpandProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv, dispid, TRUE);
            break;

        case DISPID_A_BORDERCOLOR:
        case DISPID_A_BORDERWIDTH:
        case DISPID_A_BORDERSTYLE:
            hr = ParseExpandProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv, dispid, FALSE);
            break;

        case DISPID_A_STYLETEXT:
            {
                LPTSTR lpszStyleText = (TCHAR*)pv;
                CAttrArray** ppAA = (CAttrArray**)pSubObject;

                if(*ppAA)
                {
                    (*ppAA)->Free();
                }

                if(lpszStyleText && *lpszStyleText)
                {
                    CStyle* pStyle = DYNCAST(CStyle, pObject);

                    Assert(pStyle);
                    pStyle->MaskPropertyChanges(TRUE);
                    AssertSz(FALSE, "must improve");
                    pStyle->MaskPropertyChanges(FALSE);
                }
            }
            break;

        case DISPID_A_BORDERTOP:
        case DISPID_A_BORDERRIGHT:
        case DISPID_A_BORDERBOTTOM:
        case DISPID_A_BORDERLEFT:
            hr = ParseAndExpandBorderSideProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv, dispid);
            break;

        case DISPID_A_BORDER:
            hr = ParseBorderProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            break;

        case DISPID_A_LISTSTYLE:
            hr = ParseListStyleProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            break;

        case DISPID_A_BACKGROUNDPOSITION:
            hr = ParseBackgroundPositionProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            break;

        case DISPID_A_CLIP:
            hr = ParseClipProperty((CAttrArray**)pSubObject, pObject, OPERATION(dwOpCode), (TCHAR*)pv);
            break;

        default:
            Assert("Attempting to set an unknown type of CStyleComponent!");
        }

        if(hr)
        {
            goto Cleanup;
        }
        else
        {
            // Note that dispid reflects the property that changed, not what was set -
            // e.g., textDecorationUnderline has been changed to textDecoration.
            if(dwOpCode & HANDLEPROP_AUTOMATION)
            {
                CBase::CLock Lock(pObject);
                hr = pObject->OnPropertyChange(dispid, GetdwFlags());
            }
        }
    }
    else
    {
        // GET value from data
        switch(OPCODE(dwOpCode))
        {
        case HANDLEPROP_STREAM:
            {
                IStream* pis = (IStream*)pv;

                switch(dispid)
                {
                case DISPID_A_LISTSTYLEIMAGE:
                case DISPID_A_BACKGROUNDIMAGE:
                case DISPID_A_BEHAVIOR:
                case DISPID_A_FONTFACESRC:
                    if((*(CAttrArray**)pSubObject)->Find(dispid, CAttrValue::AA_Attribute))
                    {
                        BSTR bstrSub;

                        hr = HandleStringProperty(HANDLEPROP_AUTOMATION|(PROPTYPE_BSTR<<16), 
                            &bstrSub, pObject, pSubObject);
                        if(hr == S_OK)
                        {
                            if(bstrSub && *bstrSub)
                            {   // This is a normal url.
                                hr = pis->Write(_T("url("), 4*sizeof(TCHAR), NULL);
                                if(!hr)
                                {
                                    hr = pis->Write(bstrSub, FormsStringLen(bstrSub)*sizeof(TCHAR), NULL);
                                    if(!hr)
                                    {
                                        hr = pis->Write(_T(")"), 1*sizeof(TCHAR), NULL);
                                    }
                                }
                            }
                            else
                            {   // We only get here if a NULL string was stored in the array; i.e., the value is NONE.
                                hr = pis->Write(_T("none"), 4*sizeof(TCHAR), NULL);
                            }
                            FormsFreeString(bstrSub);
                        }
                    }
                    break;

                case DISPID_A_BACKGROUND:
                    hr = WriteBackgroundStyleToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_TEXTAUTOSPACE:
                    // We need to cook up this property.
                    hr = WriteTextAutospaceToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_TEXTDECORATION:
                    // We need to cook up this property.
                    hr = WriteTextDecorationToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_BORDERTOP:
                case DISPID_A_BORDERRIGHT:
                case DISPID_A_BORDERBOTTOM:
                case DISPID_A_BORDERLEFT:
                    hr = WriteBorderSidePropertyToBSTR(dispid, *(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_BORDER:
                    hr = WriteBorderToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_MARGIN:
                case DISPID_A_PADDING:
                case DISPID_A_BORDERCOLOR:
                case DISPID_A_BORDERWIDTH:
                case DISPID_A_BORDERSTYLE:
                    hr = WriteExpandedPropertyToBSTR(dispid, *(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_LISTSTYLE:
                    hr = WriteListStyleToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_BACKGROUNDPOSITION:
                    hr = WriteBackgroundPositionToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(hr == S_OK)
                    {
                        hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        FormsFreeString(bstrTemp);
                    }
                    break;

                case DISPID_A_FONT:
                    if((*(CAttrArray**)pSubObject)->Find(DISPID_A_FONT, CAttrValue::AA_Attribute))
                    {
                        hr = HandleStringProperty(dwOpCode, pv, pObject, pSubObject);
                    }
                    else
                    {
                        // We need to cook up a "font" property.
                        hr = WriteFontToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                        if(!hr)
                        {
                            if(*bstrTemp)
                            {
                                hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                            }
                            FormsFreeString(bstrTemp);
                        }
                    }
                    break;
                case DISPID_A_LAYOUTGRID:
                    // We need to cook up a "layout grid" property.
                    hr = WriteLayoutGridToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(!hr)
                    {
                        if(*bstrTemp)
                        {
                            hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        }
                        FormsFreeString(bstrTemp);
                    }
                    break;
                case DISPID_A_CLIP:
                    // We need to cook up a "clip" property with the "rect" shape.
                    hr = WriteClipToBSTR(*(CAttrArray**)pSubObject, &bstrTemp);
                    if(!hr)
                    {
                        if(*bstrTemp)
                        {
                            hr = pis->Write(bstrTemp, FormsStringLen(bstrTemp)*sizeof(TCHAR), NULL);
                        }
                        FormsFreeString(bstrTemp);
                    }
                    break;
                case DISPID_A_STYLETEXT:
                    hr = WriteStyleToBSTR(pObject, *(CAttrArray**)pSubObject, &bstrTemp, FALSE);
                    if(!hr)
                    {
                        if(*bstrTemp)
                        {
                            hr = pis->Write(bstrTemp, _tcslen(bstrTemp)*sizeof(TCHAR), NULL);
                        }
                        FormsFreeString(bstrTemp);
                    }
                    break;
                }
            }
            break;
        default:
            {
                BSTR* pbstr;
                switch(PROPTYPE(dwOpCode))
                {
                case PROPTYPE_VARIANT:
                    V_VT((VARIANT*)pv) = VT_BSTR;
                    pbstr = &(((VARIANT*)pv)->bstrVal);
                    break;
                case PROPTYPE_BSTR:
                    pbstr = (BSTR*)pv;
                    break;
                default:
                    Assert("Can't get anything but a VARIANT or BSTR for style component properties!");
                    hr = S_FALSE;
                    goto Cleanup;
                }
                switch(dispid)
                {
                case DISPID_A_BACKGROUND:
                    hr = WriteBackgroundStyleToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;
                case DISPID_A_LISTSTYLEIMAGE:
                case DISPID_A_BACKGROUNDIMAGE:
                case DISPID_A_FONTFACESRC:
                case DISPID_A_BEHAVIOR:
                    {
                        CString cstr;
                        if((*(CAttrArray**)pSubObject)->Find(dispid, CAttrValue::AA_Attribute))
                        {
                            BSTR bstrSub;
                            hr = HandleStringProperty(HANDLEPROP_AUTOMATION|(PROPTYPE_BSTR<<16), 
                                &bstrSub, pObject, pSubObject);
                            if(hr == S_OK)
                            {
                                if(bstrSub && *bstrSub)
                                {
                                    // CONSIDER (alexz) using Format, to remove the memallocs here
                                    if(dispid != DISPID_A_BEHAVIOR)
                                    {
                                        cstr.Set(_T("url("));
                                    }

                                    cstr.Append(bstrSub);

                                    if(dispid != DISPID_A_BEHAVIOR)
                                    {
                                        cstr.Append(_T(")"));
                                    }
                                }
                                else
                                {
                                    // We only get here if a NULL string was stored in the array; i.e., the value is NONE.
                                    cstr.Set(_T("none"));
                                }
                                FormsFreeString(bstrSub);
                            }
                        }
                        hr = cstr.AllocBSTR(pbstr);
                    }
                    break;

                case DISPID_A_TEXTAUTOSPACE:
                    hr = WriteTextAutospaceToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;
                case DISPID_A_TEXTDECORATION:
                    hr = WriteTextDecorationToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_TEXTDECORATIONNONE:
                case DISPID_A_TEXTDECORATIONUNDERLINE:
                case DISPID_A_TEXTDECORATIONOVERLINE:
                case DISPID_A_TEXTDECORATIONLINETHROUGH:
                case DISPID_A_TEXTDECORATIONBLINK:
                    if(PROPTYPE(dwOpCode) != PROPTYPE_VARIANT)
                    {
                        Assert("Can't get/set text-decoration subproperties as anything but VARIANTs!");
                        hr = S_FALSE;
                        goto Cleanup;
                    }

                    V_VT((VARIANT*)pv) = VT_BOOL;
                    ((VARIANT*)pv)->boolVal = 0;

                    if(*((CAttrArray**)pSubObject))
                    {
                        // See if we already have a text-decoration value
                        CAttrValue* pAV = (*((CAttrArray**)pSubObject))->Find(DISPID_A_TEXTDECORATION, CAttrValue::AA_Attribute);
                        if(pAV)
                        {   // We do!  Copy its value into our working variant
                            long lVal = pAV->GetLong();

                            switch(dispid)
                            {
                            case DISPID_A_TEXTDECORATIONNONE:
                                lVal &= TD_NONE;
                                break;
                            case DISPID_A_TEXTDECORATIONUNDERLINE:
                                lVal &= TD_UNDERLINE;
                                break;
                            case DISPID_A_TEXTDECORATIONOVERLINE:
                                lVal &= TD_OVERLINE;
                                break;
                            case DISPID_A_TEXTDECORATIONLINETHROUGH:
                                lVal &= TD_LINETHROUGH;
                                break;
                            case DISPID_A_TEXTDECORATIONBLINK:
                                lVal &= TD_BLINK;
                                break;
                            }
                            if(lVal)
                            {
                                ((VARIANT*)pv)->boolVal = -1;
                            }
                        }
                    }
                    break;

                case DISPID_A_BORDERTOP:
                case DISPID_A_BORDERRIGHT:
                case DISPID_A_BORDERBOTTOM:
                case DISPID_A_BORDERLEFT:
                    hr = WriteBorderSidePropertyToBSTR(dispid, *(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_BORDER:
                    hr = WriteBorderToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_MARGIN:
                case DISPID_A_PADDING:
                case DISPID_A_BORDERCOLOR:
                case DISPID_A_BORDERWIDTH:
                case DISPID_A_BORDERSTYLE:
                    hr = WriteExpandedPropertyToBSTR(dispid, *(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_LISTSTYLE:
                    hr = WriteListStyleToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_BACKGROUNDPOSITION:
                    hr = WriteBackgroundPositionToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_FONT:
                    if((*(CAttrArray**)pSubObject)->Find(DISPID_A_FONT, CAttrValue::AA_Attribute))
                    {
                        hr = HandleStringProperty(dwOpCode, pv, pObject, pSubObject);
                    }
                    else
                    {
                        // We need to cook up a "font" property.
                        hr = WriteFontToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    }
                    break;

                case DISPID_A_LAYOUTGRID:
                    hr = WriteLayoutGridToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                case DISPID_A_STYLETEXT:
                    hr = WriteStyleToBSTR(pObject, *(CAttrArray**)pSubObject, pbstr, FALSE);
                    break;

                case DISPID_A_CLIP:
                    // We need to cook up a "clip" property with the "rect" shape.
                    hr = WriteClipToBSTR(*(CAttrArray**)pSubObject, pbstr);
                    break;

                default:
                    Assert("Unrecognized type being handled by CStyleUrl handler!" && FALSE);
                    break;
                }
                if(hr == S_FALSE)
                {
                    hr = FormsAllocString(_T(""), pbstr);
                }
            }
            break;
        }
    }

Cleanup:
    RRETURN1(hr, S_FALSE);
}