Coverage Report

Created: 2026-10-14 09:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/oox/source/ole/olehelper.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <oox/ole/olehelper.hxx>
21
22
#include <rtl/ustrbuf.hxx>
23
#include <sot/formats.hxx>
24
#include <sot/storage.hxx>
25
#include <osl/diagnose.h>
26
#include <oox/helper/binaryinputstream.hxx>
27
#include <oox/helper/binaryoutputstream.hxx>
28
#include <oox/helper/graphichelper.hxx>
29
#include <oox/token/properties.hxx>
30
#include <oox/token/tokens.hxx>
31
#include <oox/ole/axcontrol.hxx>
32
#include <oox/helper/propertymap.hxx>
33
#include <oox/helper/propertyset.hxx>
34
35
#include <com/sun/star/awt/XControlModel.hpp>
36
#include <com/sun/star/beans/XPropertySet.hpp>
37
#include <com/sun/star/form/FormComponentType.hpp>
38
#include <com/sun/star/form/XFormComponent.hpp>
39
#include <com/sun/star/frame/XFrame.hpp>
40
#include <com/sun/star/frame/XModel.hpp>
41
#include <com/sun/star/lang/XServiceInfo.hpp>
42
#include <com/sun/star/awt/Size.hpp>
43
#include <com/sun/star/uno/XComponentContext.hpp>
44
45
#include <tools/globname.hxx>
46
#include <unotools/streamwrap.hxx>
47
#include <comphelper/processfactory.hxx>
48
#include <utility>
49
50
namespace oox::ole {
51
52
using ::com::sun::star::form::XFormComponent;
53
using ::com::sun::star::awt::XControlModel;
54
using ::com::sun::star::awt::Size;
55
using ::com::sun::star::frame::XModel;
56
using ::com::sun::star::io::XOutputStream;
57
using ::com::sun::star::io::XInputStream;
58
using ::com::sun::star::beans::XPropertySet;
59
using ::com::sun::star::uno::Reference;
60
using ::com::sun::star::uno::UNO_QUERY;
61
using ::com::sun::star::uno::XComponentContext;
62
using ::com::sun::star::lang::XServiceInfo;
63
64
using namespace ::com::sun::star::form;
65
66
namespace {
67
68
const sal_uInt32 OLE_COLORTYPE_MASK         = 0xFF000000;
69
const sal_uInt32 OLE_COLORTYPE_CLIENT       = 0x00000000;
70
const sal_uInt32 OLE_COLORTYPE_PALETTE      = 0x01000000;
71
const sal_uInt32 OLE_COLORTYPE_BGR          = 0x02000000;
72
const sal_uInt32 OLE_COLORTYPE_SYSCOLOR     = 0x80000000;
73
74
const sal_uInt32 OLE_PALETTECOLOR_MASK      = 0x0000FFFF;
75
const sal_uInt32 OLE_SYSTEMCOLOR_MASK       = 0x0000FFFF;
76
77
/** Swaps the red and blue component of the passed color. */
78
sal_uInt32 lclSwapRedBlue( sal_uInt32 nColor )
79
2
{
80
2
    return static_cast< sal_uInt32 >( (nColor & 0xFF00FF00) | ((nColor & 0x0000FF) << 16) | ((nColor & 0xFF0000) >> 16) );
81
2
}
82
83
/** Returns the UNO RGB color from the passed encoded OLE BGR color. */
84
::Color lclDecodeBgrColor( sal_uInt32 nOleColor )
85
0
{
86
0
    return ::Color( ColorTransparency, lclSwapRedBlue( nOleColor ) & 0xFFFFFF );
87
0
}
88
89
const sal_uInt32 OLE_STDPIC_ID              = 0x0000746C;
90
91
struct GUIDCNamePair
92
{
93
    const char* sGUID;
94
    const char* sName;
95
};
96
97
struct IdCntrlData
98
{
99
    sal_Int16 nId;
100
    GUIDCNamePair aData;
101
};
102
103
const sal_Int16 TOGGLEBUTTON = -1;
104
const sal_Int16 FORMULAFIELD = -2;
105
106
typedef std::map< sal_Int16, GUIDCNamePair > GUIDCNamePairMap;
107
class classIdToGUIDCNamePairMap
108
{
109
    GUIDCNamePairMap mnIdToGUIDCNamePairMap;
110
    classIdToGUIDCNamePairMap();
111
public:
112
    static GUIDCNamePairMap& get();
113
};
114
115
classIdToGUIDCNamePairMap::classIdToGUIDCNamePairMap()
116
0
{
117
0
    static IdCntrlData const initialCntrlData[] =
118
0
    {
119
        // Command button MUST be at index 0
120
0
        { FormComponentType::COMMANDBUTTON,
121
0
             { AX_GUID_COMMANDBUTTON, "CommandButton"} ,
122
0
        },
123
        // Toggle button MUST be at index 1
124
0
        {  TOGGLEBUTTON,
125
0
           { AX_GUID_TOGGLEBUTTON, "ToggleButton"},
126
0
        },
127
0
        { FormComponentType::FIXEDTEXT,
128
0
             { AX_GUID_LABEL, "Label"},
129
0
        },
130
0
        {  FormComponentType::TEXTFIELD,
131
0
             { AX_GUID_TEXTBOX, "TextBox"},
132
0
        },
133
0
        {  FormComponentType::LISTBOX,
134
0
             { AX_GUID_LISTBOX, "ListBox"},
135
0
        },
136
0
        {  FormComponentType::COMBOBOX,
137
0
             { AX_GUID_COMBOBOX, "ComboBox"},
138
0
        },
139
0
        {  FormComponentType::CHECKBOX,
140
0
             { AX_GUID_CHECKBOX, "CheckBox"},
141
0
        },
142
0
        {  FormComponentType::RADIOBUTTON,
143
0
             { AX_GUID_OPTIONBUTTON, "OptionButton"},
144
0
        },
145
0
        {  FormComponentType::IMAGECONTROL,
146
0
             { AX_GUID_IMAGE, "Image"},
147
0
        },
148
0
        {  FormComponentType::DATEFIELD,
149
0
             { AX_GUID_TEXTBOX, "TextBox"},
150
0
        },
151
0
        {  FormComponentType::TIMEFIELD,
152
0
             { AX_GUID_TEXTBOX, "TextBox"},
153
0
        },
154
0
        {  FormComponentType::NUMERICFIELD,
155
0
             { AX_GUID_TEXTBOX, "TextBox"},
156
0
        },
157
0
        {  FormComponentType::CURRENCYFIELD,
158
0
             { AX_GUID_TEXTBOX, "TextBox"},
159
0
        },
160
0
        {  FormComponentType::PATTERNFIELD,
161
0
             { AX_GUID_TEXTBOX, "TextBox"},
162
0
        },
163
0
        {  FORMULAFIELD,
164
0
             { AX_GUID_TEXTBOX, "TextBox"},
165
0
        },
166
0
        {  FormComponentType::IMAGEBUTTON,
167
0
             { AX_GUID_COMMANDBUTTON, "CommandButton"},
168
0
        },
169
0
        {  FormComponentType::SPINBUTTON,
170
0
             { AX_GUID_SPINBUTTON, "SpinButton"},
171
0
        },
172
0
        {  FormComponentType::SCROLLBAR,
173
0
             { AX_GUID_SCROLLBAR, "ScrollBar"},
174
0
        }
175
0
    };
176
0
    int const length = std::size( initialCntrlData );
177
0
    IdCntrlData const * pData = initialCntrlData;
178
0
    for ( int index = 0; index < length; ++index, ++pData )
179
0
        mnIdToGUIDCNamePairMap[ pData->nId ] = pData->aData;
180
0
};
181
182
GUIDCNamePairMap& classIdToGUIDCNamePairMap::get()
183
0
{
184
0
    static classIdToGUIDCNamePairMap theInst;
185
0
    return theInst.mnIdToGUIDCNamePairMap;
186
0
}
187
188
template< typename Type >
189
void lclAppendHex( OUStringBuffer& orBuffer, Type nValue )
190
201k
{
191
201k
    const sal_Int32 nWidth = 2 * sizeof( Type );
192
201k
    static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
193
201k
    orBuffer.setLength( orBuffer.getLength() + nWidth );
194
786k
    for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 )
195
585k
        orBuffer[nCharIdx] = spcHexChars[ nValue & 0xF ];
196
201k
}
olehelper.cxx:void oox::ole::(anonymous namespace)::lclAppendHex<unsigned int>(rtl::OUStringBuffer&, unsigned int)
Line
Count
Source
190
18.2k
{
191
18.2k
    const sal_Int32 nWidth = 2 * sizeof( Type );
192
18.2k
    static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
193
18.2k
    orBuffer.setLength( orBuffer.getLength() + nWidth );
194
164k
    for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 )
195
146k
        orBuffer[nCharIdx] = spcHexChars[ nValue & 0xF ];
196
18.2k
}
olehelper.cxx:void oox::ole::(anonymous namespace)::lclAppendHex<unsigned short>(rtl::OUStringBuffer&, unsigned short)
Line
Count
Source
190
36.5k
{
191
36.5k
    const sal_Int32 nWidth = 2 * sizeof( Type );
192
36.5k
    static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
193
36.5k
    orBuffer.setLength( orBuffer.getLength() + nWidth );
194
182k
    for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 )
195
146k
        orBuffer[nCharIdx] = spcHexChars[ nValue & 0xF ];
196
36.5k
}
olehelper.cxx:void oox::ole::(anonymous namespace)::lclAppendHex<unsigned char>(rtl::OUStringBuffer&, unsigned char)
Line
Count
Source
190
146k
{
191
146k
    const sal_Int32 nWidth = 2 * sizeof( Type );
192
146k
    static const sal_Unicode spcHexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
193
146k
    orBuffer.setLength( orBuffer.getLength() + nWidth );
194
439k
    for( sal_Int32 nCharIdx = orBuffer.getLength() - 1, nCharEnd = nCharIdx - nWidth; nCharIdx > nCharEnd; --nCharIdx, nValue >>= 4 )
195
292k
        orBuffer[nCharIdx] = spcHexChars[ nValue & 0xF ];
196
146k
}
197
198
} // namespace
199
200
StdFontInfo::StdFontInfo() :
201
0
    mnHeight( 0 ),
202
0
    mnWeight( OLE_STDFONT_NORMAL ),
203
0
    mnCharSet( WINDOWS_CHARSET_ANSI ),
204
0
    mnFlags( 0 )
205
0
{
206
0
}
207
208
StdFontInfo::StdFontInfo( OUString aName, sal_uInt32 nHeight ) :
209
0
    maName(std::move( aName )),
210
0
    mnHeight( nHeight ),
211
0
    mnWeight( OLE_STDFONT_NORMAL ),
212
0
    mnCharSet( WINDOWS_CHARSET_ANSI ),
213
0
    mnFlags( 0 )
214
0
{
215
0
}
216
217
::Color OleHelper::decodeOleColor(
218
        const GraphicHelper& rGraphicHelper, sal_uInt32 nOleColor, bool bDefaultColorBgr )
219
0
{
220
0
    static const sal_Int32 spnSystemColors[] =
221
0
    {
222
0
        XML_scrollBar,      XML_background,     XML_activeCaption,  XML_inactiveCaption,
223
0
        XML_menu,           XML_window,         XML_windowFrame,    XML_menuText,
224
0
        XML_windowText,     XML_captionText,    XML_activeBorder,   XML_inactiveBorder,
225
0
        XML_appWorkspace,   XML_highlight,      XML_highlightText,  XML_btnFace,
226
0
        XML_btnShadow,      XML_grayText,       XML_btnText,        XML_inactiveCaptionText,
227
0
        XML_btnHighlight,   XML_3dDkShadow,     XML_3dLight,        XML_infoText,
228
0
        XML_infoBk
229
0
    };
230
231
0
    switch( nOleColor & OLE_COLORTYPE_MASK )
232
0
    {
233
0
        case OLE_COLORTYPE_CLIENT:
234
0
            return bDefaultColorBgr ? lclDecodeBgrColor( nOleColor ) : rGraphicHelper.getPaletteColor( nOleColor & OLE_PALETTECOLOR_MASK );
235
236
0
        case OLE_COLORTYPE_PALETTE:
237
0
            return rGraphicHelper.getPaletteColor( nOleColor & OLE_PALETTECOLOR_MASK );
238
239
0
        case OLE_COLORTYPE_BGR:
240
0
            return lclDecodeBgrColor( nOleColor );
241
242
0
        case OLE_COLORTYPE_SYSCOLOR:
243
0
            return rGraphicHelper.getSystemColor( STATIC_ARRAY_SELECT( spnSystemColors, nOleColor & OLE_SYSTEMCOLOR_MASK, XML_TOKEN_INVALID ), API_RGB_WHITE );
244
0
    }
245
0
    OSL_FAIL( "OleHelper::decodeOleColor - unknown color type" );
246
0
    return API_RGB_BLACK;
247
0
}
248
249
sal_uInt32 OleHelper::encodeOleColor( sal_Int32 nRgbColor )
250
2
{
251
2
    return OLE_COLORTYPE_BGR | lclSwapRedBlue( static_cast< sal_uInt32 >( nRgbColor & 0xFFFFFF ) );
252
2
}
253
254
void OleHelper::exportGuid( BinaryOutputStream& rOStr, const SvGlobalName& rId )
255
0
{
256
0
    rOStr.WriteUInt32( rId.GetCLSID().Data1 );
257
0
    rOStr.WriteUInt16( rId.GetCLSID().Data2 );
258
0
    rOStr.WriteUInt16( rId.GetCLSID().Data3 );
259
0
    rOStr.writeArray( rId.GetCLSID().Data4, 8 );
260
0
}
261
262
OUString OleHelper::importGuid( BinaryInputStream& rInStrm )
263
18.2k
{
264
18.2k
    OUStringBuffer aBuffer(40);
265
18.2k
    aBuffer.append( '{' );
266
18.2k
    lclAppendHex( aBuffer, rInStrm.readuInt32() );
267
18.2k
    aBuffer.append( '-' );
268
18.2k
    lclAppendHex( aBuffer, rInStrm.readuInt16() );
269
18.2k
    aBuffer.append( '-' );
270
18.2k
    lclAppendHex( aBuffer, rInStrm.readuInt16() );
271
18.2k
    aBuffer.append( '-' );
272
18.2k
    lclAppendHex( aBuffer, rInStrm.readuInt8() );
273
18.2k
    lclAppendHex( aBuffer, rInStrm.readuInt8() );
274
18.2k
    aBuffer.append( '-' );
275
128k
    for( int nIndex = 0; nIndex < 6; ++nIndex )
276
109k
        lclAppendHex( aBuffer, rInStrm.readuInt8() );
277
18.2k
    aBuffer.append( '}' );
278
18.2k
    return aBuffer.makeStringAndClear();
279
18.2k
}
280
281
bool OleHelper::importStdFont( StdFontInfo& orFontInfo, BinaryInputStream& rInStrm, bool bWithGuid )
282
0
{
283
0
    if( bWithGuid )
284
0
    {
285
0
        bool bIsStdFont = importGuid( rInStrm ) == OLE_GUID_STDFONT;
286
0
        OSL_ENSURE( bIsStdFont, "OleHelper::importStdFont - unexpected header GUID, expected StdFont" );
287
0
        if( !bIsStdFont )
288
0
            return false;
289
0
    }
290
291
0
    sal_uInt8 nVersion, nNameLen;
292
0
    nVersion = rInStrm.readuChar();
293
0
    orFontInfo.mnCharSet = rInStrm.readuInt16();
294
0
    orFontInfo.mnFlags = rInStrm.readuChar();
295
0
    orFontInfo.mnWeight = rInStrm.readuInt16();
296
0
    orFontInfo.mnHeight = rInStrm.readuInt32();
297
0
    nNameLen = rInStrm.readuChar();
298
    // according to spec the name is ASCII
299
0
    orFontInfo.maName = rInStrm.readCharArrayUC( nNameLen, RTL_TEXTENCODING_ASCII_US );
300
0
    OSL_ENSURE( nVersion <= 1, "OleHelper::importStdFont - wrong version" );
301
0
    return !rInStrm.isEof() && (nVersion <= 1);
302
0
}
303
304
bool OleHelper::importStdPic( StreamDataSequence& orGraphicData, BinaryInputStream& rInStrm )
305
0
{
306
0
    bool bIsStdPic = importGuid( rInStrm ) == OLE_GUID_STDPIC;
307
0
    OSL_ENSURE( bIsStdPic, "OleHelper::importStdPic - unexpected header GUID, expected StdPic" );
308
0
    if( !bIsStdPic )
309
0
        return false;
310
311
0
    sal_uInt32 nStdPicId;
312
0
    sal_Int32 nBytes;
313
0
    nStdPicId = rInStrm.readuInt32();
314
0
    nBytes = rInStrm.readInt32();
315
0
    OSL_ENSURE( nStdPicId == OLE_STDPIC_ID, "OleHelper::importStdPic - unexpected header version" );
316
0
    return !rInStrm.isEof() && (nStdPicId == OLE_STDPIC_ID) && (nBytes > 0) && (rInStrm.readData( orGraphicData, nBytes ) == nBytes);
317
0
}
318
319
static Reference< css::frame::XFrame > lcl_getFrame( const  Reference< css::frame::XModel >& rxModel )
320
16.6k
{
321
16.6k
    Reference< css::frame::XFrame > xFrame;
322
16.6k
    if ( rxModel.is() )
323
16.6k
    {
324
16.6k
        Reference< css::frame::XController > xController =  rxModel->getCurrentController();
325
16.6k
        xFrame =  xController.is() ? xController->getFrame() : nullptr;
326
16.6k
    }
327
16.6k
    return xFrame;
328
16.6k
}
329
330
0
OleFormCtrlExportHelper::OleFormCtrlExportHelper(  const Reference< XComponentContext >& rxCtx, const Reference< XModel >& rxDocModel, const Reference< XControlModel >& xCntrlModel ) : mpModel( nullptr ), maGrfHelper( rxCtx, lcl_getFrame( rxDocModel ), StorageRef() ), mxDocModel( rxDocModel ), mxControlModel( xCntrlModel )
331
0
{
332
    // try to get the guid
333
0
    Reference< css::beans::XPropertySet > xProps( xCntrlModel, UNO_QUERY );
334
0
    if ( !xProps.is() )
335
0
        return;
336
337
0
    sal_Int16 nClassId = 0;
338
0
    PropertySet aPropSet( mxControlModel );
339
0
    if ( !aPropSet.getProperty( nClassId, PROP_ClassId ) )
340
0
        return;
341
342
    /* pseudo ripped from legacy msocximex:
343
      "There is a truly horrible thing with EditControls and FormattedField
344
      Controls, they both pretend to have an EDITBOX ClassId for compatibility
345
      reasons, at some stage in the future hopefully there will be a proper
346
      FormulaField ClassId rather than this piggybacking two controls onto the
347
      same ClassId, cmc." - when fixed the fake FORMULAFIELD id entry
348
      and definition above can be removed/replaced
349
    */
350
0
    if ( nClassId == FormComponentType::TEXTFIELD)
351
0
    {
352
0
        Reference< XServiceInfo > xInfo( xCntrlModel,
353
0
            UNO_QUERY);
354
0
        if (xInfo->
355
0
            supportsService( u"com.sun.star.form.component.FormattedField"_ustr ) )
356
0
            nClassId = FORMULAFIELD;
357
0
    }
358
0
    else if ( nClassId == FormComponentType::COMMANDBUTTON )
359
0
    {
360
0
        bool bToggle = false;
361
0
        if ( aPropSet.getProperty( bToggle, PROP_Toggle ) && bToggle )
362
0
            nClassId = TOGGLEBUTTON;
363
0
    }
364
0
    else if ( nClassId == FormComponentType::CONTROL )
365
0
    {
366
0
        Reference< XServiceInfo > xInfo( xCntrlModel,
367
0
            UNO_QUERY);
368
0
        if (xInfo->supportsService(u"com.sun.star.form.component.ImageControl"_ustr ) )
369
0
            nClassId = FormComponentType::IMAGECONTROL;
370
0
    }
371
372
0
    GUIDCNamePairMap& cntrlMap = classIdToGUIDCNamePairMap::get();
373
0
    GUIDCNamePairMap::iterator it = cntrlMap.find( nClassId );
374
0
    if ( it != cntrlMap.end() )
375
0
    {
376
0
        aPropSet.getProperty(maName, PROP_Name );
377
0
        maTypeName = OUString::createFromAscii( it->second.sName );
378
0
        maFullName = "Microsoft Forms 2.0 " + maTypeName;
379
0
        mpControl.reset(new EmbeddedControl( maName ));
380
0
        maGUID = OUString::createFromAscii( it->second.sGUID );
381
0
        mpModel = mpControl->createModelFromGuid( maGUID );
382
0
    }
383
0
}
384
385
OleFormCtrlExportHelper::~OleFormCtrlExportHelper()
386
0
{
387
0
}
388
389
void OleFormCtrlExportHelper::exportName( const Reference< XOutputStream >& rxOut )
390
0
{
391
0
    oox::BinaryXOutputStream aOut( rxOut, false );
392
0
    aOut.writeUnicodeArray( maName );
393
0
    aOut.WriteInt32(0);
394
0
}
395
396
void OleFormCtrlExportHelper::exportCompObj( const Reference< XOutputStream >& rxOut )
397
0
{
398
0
    oox::BinaryXOutputStream aOut( rxOut, false );
399
0
    if ( mpModel )
400
0
        mpModel->exportCompObj( aOut );
401
0
}
402
403
void OleFormCtrlExportHelper::exportControl( const Reference< XOutputStream >& rxOut, const Size& rSize, bool bAutoClose )
404
0
{
405
0
    oox::BinaryXOutputStream aOut( rxOut, bAutoClose );
406
0
    if ( mpModel )
407
0
    {
408
0
        ::oox::ole::ControlConverter aConv(  mxDocModel, maGrfHelper );
409
0
        if(mpControl)
410
0
            mpControl->convertFromProperties( mxControlModel, aConv );
411
0
        mpModel->maSize.first = rSize.Width;
412
0
        mpModel->maSize.second = rSize.Height;
413
0
        mpModel->exportBinaryModel( aOut );
414
0
    }
415
0
}
416
417
16.6k
MSConvertOCXControls::MSConvertOCXControls( const Reference< css::frame::XModel >& rxModel ) : SvxMSConvertOCXControls( rxModel ), mxCtx( comphelper::getProcessComponentContext() ), maGrfHelper( mxCtx, lcl_getFrame( rxModel ), StorageRef() )
418
16.6k
{
419
16.6k
}
420
421
MSConvertOCXControls::~MSConvertOCXControls()
422
16.6k
{
423
16.6k
}
424
425
bool
426
MSConvertOCXControls::importControlFromStream( ::oox::BinaryInputStream& rInStrm, Reference< XFormComponent >& rxFormComp, std::u16string_view rGuidString )
427
18.2k
{
428
18.2k
    ::oox::ole::EmbeddedControl aControl( u"Unknown"_ustr );
429
18.2k
    if( ::oox::ole::ControlModelBase* pModel = aControl.createModelFromGuid( rGuidString  ) )
430
0
    {
431
0
        pModel->importBinaryModel( rInStrm );
432
0
        rxFormComp.set( mxCtx->getServiceManager()->createInstanceWithContext( pModel->getServiceName(), mxCtx ), UNO_QUERY );
433
0
        Reference< XControlModel > xCtlModel( rxFormComp, UNO_QUERY );
434
0
        ::oox::ole::ControlConverter aConv(  mxModel, maGrfHelper );
435
0
        aControl.convertProperties( xCtlModel, aConv );
436
0
    }
437
18.2k
    return rxFormComp.is();
438
18.2k
}
439
440
bool
441
MSConvertOCXControls::ReadOCXCtlsStream( rtl::Reference<SotStorageStream> const & rSrc1, Reference< XFormComponent > & rxFormComp,
442
                                   sal_Int32 nPos,
443
                                   sal_Int32 nStreamSize)
444
0
{
445
0
    if ( rSrc1.is()  )
446
0
    {
447
0
        BinaryXInputStream aCtlsStrm( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper( *rSrc1 ) ), true );
448
0
        aCtlsStrm.seek( nPos );
449
0
        OUString aStrmClassId = ::oox::ole::OleHelper::importGuid( aCtlsStrm );
450
0
        return  importControlFromStream( aCtlsStrm, rxFormComp, aStrmClassId, nStreamSize );
451
0
    }
452
0
    return false;
453
0
}
454
455
bool MSConvertOCXControls::importControlFromStream( ::oox::BinaryInputStream& rInStrm, Reference< XFormComponent >& rxFormComp, const OUString& rStrmClassId,
456
                                   sal_Int32 nStreamSize)
457
18.2k
{
458
18.2k
    if ( !rInStrm.isEof() )
459
18.2k
    {
460
        // Special processing for those html controls
461
18.2k
        bool bOneOfHtmlControls = false;
462
18.2k
        if ( rStrmClassId.toAsciiUpperCase() == HTML_GUID_SELECT
463
18.2k
          || rStrmClassId.toAsciiUpperCase() == HTML_GUID_TEXTBOX )
464
0
            bOneOfHtmlControls = true;
465
466
18.2k
        if ( bOneOfHtmlControls )
467
0
        {
468
            // html controls don't seem have a handy record length following the GUID
469
            // in the binary stream.
470
            // Given the control stream length create a stream of nStreamSize bytes starting from
471
            // nPos ( offset by the guid already read in )
472
0
            if ( !nStreamSize )
473
0
                return false;
474
0
            const int nGuidSize = 0x10;
475
0
            StreamDataSequence aDataSeq;
476
0
            sal_Int32 nBytesToRead = nStreamSize - nGuidSize;
477
0
            while ( nBytesToRead )
478
0
                nBytesToRead -= rInStrm.readData( aDataSeq, nBytesToRead );
479
0
            SequenceInputStream aInSeqStream( aDataSeq );
480
0
            importControlFromStream( aInSeqStream, rxFormComp, rStrmClassId );
481
0
        }
482
18.2k
        else
483
18.2k
        {
484
18.2k
            importControlFromStream( rInStrm, rxFormComp, rStrmClassId );
485
18.2k
        }
486
18.2k
    }
487
18.2k
    return rxFormComp.is();
488
18.2k
}
489
490
bool MSConvertOCXControls::ReadOCXStorage( rtl::Reference<SotStorage> const & xOleStg,
491
                                  Reference< XFormComponent > & rxFormComp )
492
18.2k
{
493
18.2k
    if ( xOleStg.is() )
494
18.2k
    {
495
18.2k
        rtl::Reference<SotStorageStream> pNameStream = xOleStg->OpenSotStream(u"\3OCXNAME"_ustr, StreamMode::READ);
496
18.2k
        BinaryXInputStream aNameStream( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper( *pNameStream ) ), true );
497
498
18.2k
        rtl::Reference<SotStorageStream> pContents = xOleStg->OpenSotStream(u"contents"_ustr, StreamMode::READ);
499
18.2k
        BinaryXInputStream aInStrm(  Reference< XInputStream >( new utl::OSeekableInputStreamWrapper( *pContents ) ), true );
500
501
18.2k
        rtl::Reference<SotStorageStream> pClsStrm = xOleStg->OpenSotStream(u"\1CompObj"_ustr, StreamMode::READ);
502
18.2k
        BinaryXInputStream aClsStrm( Reference< XInputStream >( new utl::OSeekableInputStreamWrapper(*pClsStrm ) ), true );
503
18.2k
        aClsStrm.skip(12);
504
505
18.2k
        OUString aStrmClassId = ::oox::ole::OleHelper::importGuid( aClsStrm );
506
18.2k
        if ( importControlFromStream(  aInStrm,  rxFormComp, aStrmClassId, aInStrm.size() ) )
507
0
        {
508
0
            OUString aName = aNameStream.readNulUnicodeArray();
509
0
            Reference< XControlModel > xCtlModel( rxFormComp, UNO_QUERY );
510
0
            if ( !aName.isEmpty() && xCtlModel.is() )
511
0
            {
512
0
                PropertyMap aPropMap;
513
0
                aPropMap.setProperty( PROP_Name, aName );
514
0
                PropertySet aPropSet( xCtlModel );
515
0
                aPropSet.setProperties( aPropMap );
516
0
            }
517
0
            return rxFormComp.is();
518
0
        }
519
18.2k
    }
520
18.2k
    return  false;
521
18.2k
}
522
523
bool MSConvertOCXControls::WriteOCXExcelKludgeStream( const css::uno::Reference< css::frame::XModel >& rxModel, const css::uno::Reference< css::io::XOutputStream >& xOutStrm, const css::uno::Reference< css::awt::XControlModel > &rxControlModel, const css::awt::Size& rSize,OUString &rName )
524
0
{
525
0
    OleFormCtrlExportHelper exportHelper( comphelper::getProcessComponentContext(), rxModel, rxControlModel );
526
0
    if ( !exportHelper.isValid() )
527
0
        return false;
528
0
    rName = exportHelper.getTypeName();
529
0
    SvGlobalName aName;
530
0
    (void)aName.MakeId(exportHelper.getGUID());
531
0
    BinaryXOutputStream aOut( xOutStrm, false );
532
0
    OleHelper::exportGuid( aOut, aName );
533
0
    exportHelper.exportControl( xOutStrm, rSize );
534
0
    return true;
535
0
}
536
537
bool MSConvertOCXControls::WriteOCXStream( const Reference< XModel >& rxModel, rtl::Reference<SotStorage> const &xOleStg,
538
    const Reference< XControlModel > &rxControlModel,
539
    const css::awt::Size& rSize, OUString &rName)
540
0
{
541
0
    SvGlobalName aName;
542
543
0
    OleFormCtrlExportHelper exportHelper( comphelper::getProcessComponentContext(), rxModel, rxControlModel );
544
545
0
    if ( !exportHelper.isValid() )
546
0
        return false;
547
548
0
    aName.MakeId(exportHelper.getGUID());
549
550
0
    OUString sFullName = exportHelper.getFullName();
551
0
    rName = exportHelper.getTypeName();
552
0
    xOleStg->SetClass( aName, SotClipboardFormatId::EMBEDDED_OBJ_OLE, sFullName);
553
0
    {
554
0
        rtl::Reference<SotStorageStream> pNameStream = xOleStg->OpenSotStream(u"\3OCXNAME"_ustr);
555
0
        Reference< XOutputStream > xOut = new utl::OSeekableOutputStreamWrapper( *pNameStream );
556
0
        exportHelper.exportName( xOut );
557
0
    }
558
0
    {
559
0
        rtl::Reference<SotStorageStream> pObjStream = xOleStg->OpenSotStream(u"\1CompObj"_ustr);
560
0
        Reference< XOutputStream > xOut = new utl::OSeekableOutputStreamWrapper( *pObjStream );
561
0
        exportHelper.exportCompObj( xOut );
562
0
    }
563
0
    {
564
0
        rtl::Reference<SotStorageStream> pContents = xOleStg->OpenSotStream(u"contents"_ustr);
565
0
        Reference< XOutputStream > xOut = new utl::OSeekableOutputStreamWrapper( *pContents );
566
0
        exportHelper.exportControl( xOut, rSize );
567
0
    }
568
0
    return true;
569
0
}
570
571
} // namespace oox
572
573
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */