1 /*****************************************************************************
2 * persiststreaminit.cpp: ActiveX control for VLC
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
6 * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
24 #include "persiststreaminit.h"
49 AxVLCVariant(VARIANTARG
&v
)
55 AxVLCVariant(VARIANTARG
*v
)
61 AxVLCVariant(const AxVLCVariant
&vv
)
64 VariantCopy(&_v
, const_cast<VARIANTARG
*>(&(vv
._v
)));
73 AxVLCVariant(BSTR bstr
)
79 VariantCopy(&_v
, &arg
);
82 inline const VARIANTARG
*variantArg(void) const {
86 inline void swap(AxVLCVariant
&v1
, AxVLCVariant
&v2
)
88 VARIANTARG tmp
= v1
._v
;
103 AxVLCWSTR(void) : _data(NULL
) {};
109 ULONG refcount
= InterlockedDecrement(&(_data
->refcount
));
111 CoTaskMemFree(_data
);
119 size_t len
= wcslen(s
);
122 size_t size
= len
*sizeof(WCHAR
);
123 _data
= (struct data
*)CoTaskMemAlloc(sizeof(struct data
)+size
);
128 memcpy(_data
->wstr
, s
, size
);
129 _data
->wstr
[len
]=L
'\0';
137 AxVLCWSTR(const AxVLCWSTR
&s
)
141 InterlockedIncrement(&(_data
->refcount
));
144 inline bool operator<(const AxVLCWSTR
&s
) const
146 return compareNoCase(s
.wstr()) < 0;
149 inline bool operator<(LPCWSTR s
) const
151 return compareNoCase(s
) < 0;
154 inline bool operator==(const AxVLCWSTR
&s
) const
156 return size() == s
.size() ?
157 (compareNoCase(s
.wstr()) == 0) : false;
160 inline bool operator==(LPCWSTR s
) const
162 return compareNoCase(s
) == 0;
165 LPCWSTR
wstr(void) const
167 return (NULL
!= _data
) ? _data
->wstr
: NULL
;
170 size_t size(void) const
172 return (NULL
!= _data
) ? _data
->len
: 0;
177 inline int compareNoCase(LPCWSTR s
) const
181 return (NULL
== s
) ? 0 : -1;
186 return _wcsicmp(_data
->wstr
, s
);
196 typedef pair
<class AxVLCWSTR
, class AxVLCVariant
> AxVLCPropertyPair
;
197 typedef map
<class AxVLCWSTR
, class AxVLCVariant
> AxVLCPropertyMap
;
199 ///////////////////////////
201 class VLCPropertyBag
: public IPropertyBag
206 VLCPropertyBag(void) : _i_ref(1) {};
207 virtual ~VLCPropertyBag() {};
210 STDMETHODIMP
QueryInterface(REFIID riid
, void **ppv
)
214 if( (IID_IUnknown
== riid
)
215 || (IID_IPropertyBag
== riid
) )
218 *ppv
= reinterpret_cast<LPVOID
>(this);
222 return E_NOINTERFACE
;
225 STDMETHODIMP_(ULONG
) AddRef(void)
226 { return InterlockedIncrement(&_i_ref
); };
228 STDMETHODIMP_(ULONG
) Release(void)
230 ULONG refcount
= InterlockedDecrement(&_i_ref
);
239 // IPropertyBag methods
241 STDMETHODIMP
Read(LPCOLESTR pszPropName
, VARIANT
*pVar
, IErrorLog
*pErrorLog
)
243 if( (NULL
== pszPropName
) || (NULL
== pVar
) )
246 AxVLCPropertyMap::const_iterator notfound
= _pm
.end();
247 AxVLCPropertyMap::const_iterator iter
= _pm
.find(pszPropName
);
248 if( notfound
!= iter
)
250 VARTYPE vtype
= V_VT(pVar
);
253 VariantCopy(&v
, const_cast<VARIANTARG
*>((*iter
).second
.variantArg()));
254 if( (V_VT(&v
) != vtype
) && FAILED(VariantChangeType(&v
, &v
, 0, vtype
)) )
266 STDMETHODIMP
Write(LPCOLESTR pszPropName
, VARIANT
*pVar
)
268 if( (NULL
== pszPropName
) || (NULL
== pVar
) )
271 AxVLCPropertyPair
val(pszPropName
, pVar
);
272 pair
<AxVLCPropertyMap::iterator
, bool> p
= _pm
.insert(val
);
273 if( false == p
.second
)
274 // replace existing key value
275 (*p
.first
).second
= val
.second
;
281 HRESULT
Load(LPSTREAM pStm
)
288 AxVLCPropertyPair
*val
;
289 result
= ReadProperty(pStm
, &val
);
290 if( SUCCEEDED(result
) )
292 if( (val
->first
== L
"(Count)") && (VT_I4
== V_VT(val
->second
.variantArg())) )
294 size_t count
= V_I4(val
->second
.variantArg());
298 result
= ReadProperty(pStm
, &val
);
302 pair
<AxVLCPropertyMap::iterator
, bool> p
= _pm
.insert(*val
);
303 if( false == p
.second
)
304 // replace existing key value
305 (*p
.first
).second
= val
->second
;
313 HRESULT
Save(LPSTREAM pStm
)
320 AxVLCPropertyPair
header(L
"(Count)", _pm
.size());
321 result
= WriteProperty(pStm
, header
);
322 if( SUCCEEDED(result
) )
324 AxVLCPropertyMap::const_iterator iter
= _pm
.begin();
325 AxVLCPropertyMap::const_iterator end
= _pm
.end();
329 result
= WriteProperty(pStm
, *(iter
++));
339 return _pm
.size() == 0;
344 HRESULT
WriteProperty(LPSTREAM pStm
, const AxVLCPropertyPair
&prop
)
348 const AxVLCWSTR propName
= prop
.first
;
350 ULONG len
= propName
.size();
355 result
= pStm
->Write(&len
, sizeof(len
), NULL
);
359 result
= pStm
->Write(propName
.wstr(), len
*sizeof(WCHAR
), NULL
);
363 const VARIANTARG
*propValue
= prop
.second
.variantArg();
364 VARTYPE vtype
= V_VT(propValue
);
368 result
= pStm
->Write(&vtype
, sizeof(vtype
), NULL
);
371 result
= pStm
->Write(&V_BOOL(propValue
), sizeof(V_BOOL(propValue
)), NULL
);
376 result
= pStm
->Write(&vtype
, sizeof(vtype
), NULL
);
379 result
= pStm
->Write(&V_I4(propValue
), sizeof(V_I4(propValue
)), NULL
);
384 result
= pStm
->Write(&vtype
, sizeof(vtype
), NULL
);
387 len
= SysStringLen(V_BSTR(propValue
));
388 result
= pStm
->Write(&len
, sizeof(len
), NULL
);
393 result
= pStm
->Write(V_BSTR(propValue
), len
*sizeof(OLECHAR
), NULL
);
400 result
= pStm
->Write(&vtype
, sizeof(vtype
), NULL
);
407 HRESULT
ReadProperty(LPSTREAM pStm
, AxVLCPropertyPair
**prop
)
413 result
= pStm
->Read(&len
, sizeof(len
), NULL
);
420 LPWSTR propName
= (LPOLESTR
)::alloca((len
+1)*sizeof(WCHAR
));
421 if( NULL
== propName
)
422 return E_OUTOFMEMORY
;
424 result
= pStm
->Read(propName
, len
*sizeof(WCHAR
), NULL
);
428 propName
[len
] = L
'\0';
430 VARIANTARG propValue
;
433 result
= pStm
->Read(&vtype
, sizeof(vtype
), NULL
);
440 V_VT(&propValue
) = vtype
;
441 result
= pStm
->Read(&V_BOOL(&propValue
), sizeof(V_BOOL(&propValue
)), NULL
);
446 V_VT(&propValue
) = vtype
;
447 result
= pStm
->Read(&V_I4(&propValue
), sizeof(V_I4(&propValue
)), NULL
);
452 V_VT(&propValue
) = vtype
;
453 result
= pStm
->Read(&len
, sizeof(len
), NULL
);
457 V_BSTR(&propValue
) = NULL
;
460 V_BSTR(&propValue
) = SysAllocStringLen(NULL
, len
);
461 if( NULL
== V_BSTR(&propValue
) )
462 return E_OUTOFMEMORY
;
464 result
= pStm
->Read(V_BSTR(&propValue
), len
*sizeof(OLECHAR
), NULL
);
467 SysFreeString(V_BSTR(&propValue
));
473 VariantInit(&propValue
);
476 *prop
= new AxVLCPropertyPair(propName
, propValue
);
481 AxVLCPropertyMap _pm
;
485 ///////////////////////////
487 VLCPersistStreamInit::VLCPersistStreamInit(VLCPlugin
*p_instance
) : _p_instance(p_instance
)
489 _p_props
= new VLCPropertyBag();
492 VLCPersistStreamInit::~VLCPersistStreamInit()
497 STDMETHODIMP
VLCPersistStreamInit::GetClassID(LPCLSID pClsID
)
502 *pClsID
= _p_instance
->getClassID();
507 STDMETHODIMP
VLCPersistStreamInit::InitNew(void)
509 return _p_instance
->onInit();
512 STDMETHODIMP
VLCPersistStreamInit::Load(LPSTREAM pStm
)
514 HRESULT result
= _p_props
->Load(pStm
);
518 LPPERSISTPROPERTYBAG pPersistPropBag
;
519 if( FAILED(QueryInterface(IID_IPersistPropertyBag
, (void**)&pPersistPropBag
)) )
522 result
= pPersistPropBag
->Load(_p_props
, NULL
);
523 pPersistPropBag
->Release();
528 STDMETHODIMP
VLCPersistStreamInit::Save(LPSTREAM pStm
, BOOL fClearDirty
)
533 LPPERSISTPROPERTYBAG pPersistPropBag
;
534 if( FAILED(QueryInterface(IID_IPersistPropertyBag
, (void**)&pPersistPropBag
)) )
537 HRESULT result
= pPersistPropBag
->Save(_p_props
, fClearDirty
, _p_props
->IsEmpty());
538 pPersistPropBag
->Release();
542 return _p_props
->Save(pStm
);
545 STDMETHODIMP
VLCPersistStreamInit::IsDirty(void)
547 return _p_instance
->isDirty() ? S_OK
: S_FALSE
;
550 STDMETHODIMP
VLCPersistStreamInit::GetSizeMax(ULARGE_INTEGER
*pcbSize
)
552 pcbSize
->HighPart
= 0UL;
553 pcbSize
->LowPart
= 16384UL; // just a guess