Example #1
0
void printOutReply( etherPacket_t * pstr_reply, const struct timeval str_delay )
{
    /* strings to print out results in a clean way */
    char tch_replySrcIp[IP_ADDR_SIZE+1]      = "", 
         tch_replySrcHwAddr[MAC_ADDR_SIZE+1] = "", 
         tch_replyHwAddr[MAC_ADDR_SIZE+1]    = "", 
         tch_replyAddrIp[IP_ADDR_SIZE+1]     = "";
	
    /* If received packet is a RARP reply */
    if ( pstr_reply->us_ethType == htons( ETH_TYPE_RARP ) )
    {
        /* we craft strings to print results using received packet */
        parse( pstr_reply, tch_replySrcIp, tch_replySrcHwAddr, tch_replyHwAddr, tch_replyAddrIp );

#define OPERATION(o) ( ( o == htons(RARP_OPCODE_REPLY) ) ? "Reply" : "Request" )
        fprintf( stdout, "%s received from %s (%s) : %s is at %s ", 
                OPERATION( pstr_reply->str_packet.us_opcode ), 
                tch_replySrcIp, tch_replySrcHwAddr, tch_replyHwAddr, tch_replyAddrIp );
        printTime_ms( str_delay );
        fprintf( stdout, "\n" );
    }
    else
    {
#define __MAC(i) (pstr_reply->tuc_senderHwAddr[(i)])
        fprintf( stdout, "Unknown packet received (ether type = 0x%04x) from %02x:%02x:%02x:%02x:%02x:%02x ", 
                ntohs( pstr_reply->us_ethType ), 
                __MAC(0), __MAC(1), __MAC(2), __MAC(3), __MAC(4), __MAC(5) );
        printTime_ms( str_delay );
        fprintf( stdout, "\n" ); 
    }
}
Example #2
0
static int i2c_stm32_transfer(struct device *dev, struct i2c_msg *msg,
			      u8_t num_msgs, u16_t slave)
{
	struct i2c_stm32_data *data = DEV_DATA(dev);
#if defined(CONFIG_I2C_STM32_V1)
	const struct i2c_stm32_config *cfg = DEV_CFG(dev);
	I2C_TypeDef *i2c = cfg->i2c;
#endif
	struct i2c_msg *current, *next;
	int ret = 0;

	/* Check for validity of all messages, to prevent having to abort
	 * in the middle of a transfer
	 */
	current = msg;

	/*
	 * Set I2C_MSG_RESTART flag on first message in order to send start
	 * condition
	 */
	current->flags |= I2C_MSG_RESTART;

	for (u8_t i = 1; i <= num_msgs; i++) {
		/* Maximum length of a single message is 255 Bytes */
		if (current->len > 255) {
			ret = -EINVAL;
			break;
		}

		if (i < num_msgs) {
			next = current + 1;

			/*
			 * Restart condition between messages
			 * of different directions is required
			 */
			if (OPERATION(current) != OPERATION(next)) {
				if (!(next->flags & I2C_MSG_RESTART)) {
					ret = -EINVAL;
					break;
				}
			}

			/* Stop condition is only allowed on last message */
			if (current->flags & I2C_MSG_STOP) {
				ret = -EINVAL;
				break;
			}
		} else {
			/* Stop condition is required for the last message */
			current->flags |= I2C_MSG_STOP;
		}

		current++;
	}

	if (ret) {
		return ret;
	}

	/* Send out messages */
	k_sem_take(&data->bus_mutex, K_FOREVER);
#if defined(CONFIG_I2C_STM32_V1)
	LL_I2C_Enable(i2c);
#endif

	current = msg;

	while (num_msgs > 0) {
		u8_t *next_msg_flags = NULL;

		if (num_msgs > 1) {
			next = current + 1;
			next_msg_flags = &(next->flags);
		}

		if ((current->flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) {
			ret = stm32_i2c_msg_write(dev, current, next_msg_flags,
						  slave);
		} else {
			ret = stm32_i2c_msg_read(dev, current, next_msg_flags,
						 slave);
		}

		if (ret < 0) {
			break;
		}

		current++;
		num_msgs--;
	}
#if defined(CONFIG_I2C_STM32_V1)
	LL_I2C_Disable(i2c);
#endif
	k_sem_give(&data->bus_mutex);
	return ret;
}
Example #3
0
parse()
{
	char		*values[MAXDEPTH];	/*    value stack	 */
	short		states[MAXDEPTH];	/*    state stack	 */
	register short	*yyps;		/* pointer to state stack	 */
	register short	*act;		/* pointer to performing action	 */
	register int	state;		/* current parser state		 */
	register int	next_state;
	register int	token;		/* current input token number	 */
	register int	i;
	register int	errorflag;	/* error recovery flag		 */

	state = 0;
	token = -1;
	errorflag = 0;
	yyps = &states[-1];
	yypv = &values[-1];

stack:
	*++yyps = state;	/* push state into state stack */
	*++yypv = yyval;	/* push value into value stack */
new_state:
	/* set act to point to the parsing actions for the new state */
	i = yypact[state + 1];
	act = &yyact[i];

next_action:		/* get the next action, and perform it */
	next_state = ACTION(*act);
	switch (OPERATION(*act++))	/* switch on operation */
	{
	  case SKIP:
		if (token < 0)	/* get next token */
			token = lex();
		if (next_state != token)
			act++;
		goto next_action;	/* get next action */

	  case SHIFT:		/* goto next_state */
		state = next_state;
		yyval = yylval;	/* $i = value of last token */
		token = -1;
		if (errorflag)
			errorflag--;
		goto stack;	/* stack new state and value */

	  case REDUCE:		/* rule next_state */
		yyps -= yyr2[next_state];	/* pop state stack */
		yypv -= yyr2[next_state];	/* pop value stack */
		yyval = yypv[1];		/* $$ = $1	   */

		if (yyactr(next_state))
			 goto abort;

		/* consult goto table to find next state */
		i = yyr1[next_state];
		i = yypgo[i];
		act = &yygo[i];
		next_state = *yyps;
		for ( ; *act != next_state && *act >= 0; act += 2)
			continue;
		state = act[1];
		goto stack;  /* stack new state and value */

	  case ACCEPT:
		return (0);

	  case ERROR:		/* attempt to resume parsing */
		switch (errorflag)
		{
		  case 0:	/* brand new syntax error */
			amxerror(88);

		  case 1:	 /* incompletely recovered error, try again */
			errorflag = 2;

			/* find a state where "error" is a legal SHIFT */
			while (yyps >= states)
			{
				/* search yyps actions */
				i = *yyps;
				i = yypact[i + 1];
				act = &yyact[i];
				for ( ; OPERATION(*act) == SKIP; act += 2)
					if (*act == SHIFT_ON_ERROR)
						goto found;

				/* the current yyps has no shift */
				/* on "error", pop stack	 */
				yyps--;
				yypv--;
			}

			/* there is no state on the stack */
			/* with an error shift ... abort  */
abort:
			return (1);

found:	/* we have a state with a shift on "error", resume parsing */
			state =  ACTION(act[1]);
			goto stack;

		  case 2:	/* no shift yet; clobber input char */
				/* don't discard EOF; quit          */
			if (!token)
				goto abort;
			token = -1;
			goto new_state;   /* try again in the same state */

		}
	}

	/*NOTREACHED*/
}
Example #4
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);
}