00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "plugin.h"
00024 #include "persiststreaminit.h"
00025
00026 #include "utils.h"
00027 #include <map>
00028
00029 #include <malloc.h>
00030 #include <wchar.h>
00031
00032 using namespace std;
00033
00034 class AxVLCVariant
00035 {
00036
00037 public:
00038
00039 AxVLCVariant(void)
00040 {
00041 VariantInit(&_v);
00042 };
00043
00044 ~AxVLCVariant(void)
00045 {
00046 VariantClear(&_v);
00047 }
00048
00049 AxVLCVariant(VARIANTARG &v)
00050 {
00051
00052
00053 _v = v;
00054 };
00055
00056 AxVLCVariant(VARIANTARG *v)
00057 {
00058 VariantInit(&_v);
00059 VariantCopy(&_v, v);
00060 };
00061
00062 AxVLCVariant(const AxVLCVariant &vv)
00063 {
00064 VariantInit(&_v);
00065 VariantCopy(&_v, const_cast<VARIANTARG *>(&(vv._v)));
00066 };
00067
00068 AxVLCVariant(int i)
00069 {
00070 V_VT(&_v) = VT_I4;
00071 V_I4(&_v) = i;
00072 };
00073
00074 AxVLCVariant(BSTR bstr)
00075 {
00076 VARIANT arg;
00077 V_VT(&arg) = VT_BSTR;
00078 V_BSTR(&arg) = bstr;
00079 VariantInit(&_v);
00080 VariantCopy(&_v, &arg);
00081 };
00082
00083 inline const VARIANTARG *variantArg(void) const {
00084 return &_v;
00085 }
00086
00087 inline void swap(AxVLCVariant &v1, AxVLCVariant &v2)
00088 {
00089 VARIANTARG tmp = v1._v;
00090 v1._v = v2._v;
00091 v2._v = tmp;
00092 };
00093
00094 private:
00095
00096 VARIANTARG _v;
00097 };
00098
00099 class AxVLCWSTR
00100 {
00101
00102 public:
00103
00104 AxVLCWSTR(void) : _data(NULL) {};
00105
00106 virtual ~AxVLCWSTR()
00107 {
00108 if( NULL != _data )
00109 {
00110 ULONG refcount = InterlockedDecrement(&(_data->refcount));
00111 if( 0 == refcount )
00112 CoTaskMemFree(_data);
00113 }
00114 };
00115
00116 AxVLCWSTR(LPCWSTR s)
00117 {
00118 if( NULL != s )
00119 {
00120 size_t len = wcslen(s);
00121 if( len > 0 )
00122 {
00123 size_t size = len*sizeof(WCHAR);
00124 _data = (struct data *)CoTaskMemAlloc(sizeof(struct data)+size);
00125 if( NULL != _data )
00126 {
00127 _data->len = len;
00128 _data->refcount = 1;
00129 memcpy(_data->wstr, s, size);
00130 _data->wstr[len]=L'\0';
00131 return;
00132 }
00133 }
00134 }
00135 _data = NULL;
00136 };
00137
00138 AxVLCWSTR(const AxVLCWSTR &s)
00139 {
00140 _data = s._data;
00141 if( NULL != _data )
00142 InterlockedIncrement(&(_data->refcount));
00143 };
00144
00145 inline bool operator<(const AxVLCWSTR &s) const
00146 {
00147 return compareNoCase(s.wstr()) < 0;
00148 };
00149
00150 inline bool operator<(LPCWSTR s) const
00151 {
00152 return compareNoCase(s) < 0;
00153 };
00154
00155 inline bool operator==(const AxVLCWSTR &s) const
00156 {
00157 return size() == s.size() ?
00158 (compareNoCase(s.wstr()) == 0) : false;
00159 };
00160
00161 inline bool operator==(LPCWSTR s) const
00162 {
00163 return compareNoCase(s) == 0;
00164 };
00165
00166 LPCWSTR wstr(void) const
00167 {
00168 return (NULL != _data) ? _data->wstr : NULL;
00169 };
00170
00171 size_t size(void) const
00172 {
00173 return (NULL != _data) ? _data->len : 0;
00174 };
00175
00176 private:
00177
00178 inline int compareNoCase(LPCWSTR s) const
00179 {
00180 if( NULL == _data )
00181 {
00182 return (NULL == s) ? 0 : -1;
00183 }
00184 if( NULL == s )
00185 return 1;
00186
00187 return _wcsicmp(_data->wstr, s);
00188 };
00189
00190 struct data {
00191 size_t len;
00192 LONG refcount;
00193 wchar_t wstr[1];
00194 } *_data;
00195 };
00196
00197 typedef pair<class AxVLCWSTR, class AxVLCVariant> AxVLCPropertyPair;
00198 typedef map<class AxVLCWSTR, class AxVLCVariant> AxVLCPropertyMap;
00199
00201
00202 class VLCPropertyBag : public IPropertyBag
00203 {
00204
00205 public:
00206
00207 VLCPropertyBag(void) : _i_ref(1) {};
00208 virtual ~VLCPropertyBag() {};
00209
00210
00211 STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
00212 {
00213 if( NULL == ppv )
00214 return E_POINTER;
00215 if( (IID_IUnknown == riid)
00216 && (IID_IPropertyBag == riid) )
00217 {
00218 AddRef();
00219 *ppv = reinterpret_cast<LPVOID>(this);
00220 return NOERROR;
00221 }
00222
00223 return E_NOINTERFACE;
00224 };
00225
00226 STDMETHODIMP_(ULONG) AddRef(void)
00227 { return InterlockedIncrement(&_i_ref); };
00228
00229 STDMETHODIMP_(ULONG) Release(void)
00230 {
00231 ULONG refcount = InterlockedDecrement(&_i_ref);
00232 if( 0 == refcount )
00233 {
00234 delete this;
00235 return 0;
00236 }
00237 return refcount;
00238 };
00239
00240
00241
00242 STDMETHODIMP Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
00243 {
00244 if( (NULL == pszPropName) || (NULL == pVar) )
00245 return E_POINTER;
00246
00247 AxVLCPropertyMap::const_iterator notfound = _pm.end();
00248 AxVLCPropertyMap::const_iterator iter = _pm.find(pszPropName);
00249 if( notfound != iter )
00250 {
00251 VARTYPE vtype = V_VT(pVar);
00252 VARIANTARG v;
00253 VariantInit(&v);
00254 VariantCopy(&v, const_cast<VARIANTARG*>((*iter).second.variantArg()));
00255 if( (V_VT(&v) != vtype) && FAILED(VariantChangeType(&v, &v, 0, vtype)) )
00256 {
00257 VariantClear(&v);
00258 return E_FAIL;
00259 }
00260 *pVar = v;
00261 return S_OK;
00262 }
00263 else
00264 return E_INVALIDARG;
00265 };
00266
00267 STDMETHODIMP Write(LPCOLESTR pszPropName, VARIANT *pVar)
00268 {
00269 if( (NULL == pszPropName) || (NULL == pVar) )
00270 return E_POINTER;
00271
00272 AxVLCPropertyPair val(pszPropName, pVar);
00273 pair<AxVLCPropertyMap::iterator, bool> p = _pm.insert(val);
00274 if( false == p.second )
00275
00276 (*p.first).second = val.second;
00277 return S_OK;
00278 };
00279
00280
00281
00282 HRESULT Load(LPSTREAM pStm)
00283 {
00284 if( NULL == pStm )
00285 return E_INVALIDARG;
00286
00287 HRESULT result;
00288
00289 AxVLCPropertyPair *val;
00290 result = ReadProperty(pStm, &val);
00291 if( SUCCEEDED(result) )
00292 {
00293 if( (val->first == L"(Count)") && (VT_I4 == V_VT(val->second.variantArg())) )
00294 {
00295 size_t count = V_I4(val->second.variantArg());
00296 delete val;
00297 while( count-- )
00298 {
00299 result = ReadProperty(pStm, &val);
00300 if( FAILED(result) )
00301 return result;
00302
00303 pair<AxVLCPropertyMap::iterator, bool> p = _pm.insert(*val);
00304 if( false == p.second )
00305
00306 (*p.first).second = val->second;
00307 delete val;
00308 }
00309 }
00310 }
00311 return result;
00312 };
00313
00314 HRESULT Save(LPSTREAM pStm)
00315 {
00316 if( NULL == pStm )
00317 return E_INVALIDARG;
00318
00319 HRESULT result;
00320
00321 AxVLCPropertyPair header(L"(Count)", _pm.size());
00322 result = WriteProperty(pStm, header);
00323 if( SUCCEEDED(result) )
00324 {
00325 AxVLCPropertyMap::const_iterator iter = _pm.begin();
00326 AxVLCPropertyMap::const_iterator end = _pm.end();
00327
00328 while( iter != end )
00329 {
00330 result = WriteProperty(pStm, *(iter++));
00331 if( FAILED(result) )
00332 return result;
00333 }
00334 }
00335 return result;
00336 };
00337
00338 BOOL IsEmpty()
00339 {
00340 return _pm.size() == 0;
00341 }
00342
00343 private:
00344
00345 HRESULT WriteProperty(LPSTREAM pStm, const AxVLCPropertyPair &prop)
00346 {
00347 HRESULT result;
00348
00349 const AxVLCWSTR propName = prop.first;
00350
00351 ULONG len = propName.size();
00352
00353 if( 0 == len )
00354 return E_INVALIDARG;
00355
00356 result = pStm->Write(&len, sizeof(len), NULL);
00357 if( FAILED(result) )
00358 return result;
00359
00360 result = pStm->Write(propName.wstr(), len*sizeof(WCHAR), NULL);
00361 if( FAILED(result) )
00362 return result;
00363
00364 const VARIANTARG *propValue = prop.second.variantArg();
00365 VARTYPE vtype = V_VT(propValue);
00366 switch( vtype )
00367 {
00368 case VT_BOOL:
00369 result = pStm->Write(&vtype, sizeof(vtype), NULL);
00370 if( FAILED(result) )
00371 return result;
00372 result = pStm->Write(&V_BOOL(propValue), sizeof(V_BOOL(propValue)), NULL);
00373 if( FAILED(result) )
00374 return result;
00375 break;
00376 case VT_I4:
00377 result = pStm->Write(&vtype, sizeof(vtype), NULL);
00378 if( FAILED(result) )
00379 return result;
00380 result = pStm->Write(&V_I4(propValue), sizeof(V_I4(propValue)), NULL);
00381 if( FAILED(result) )
00382 return result;
00383 break;
00384 case VT_BSTR:
00385 result = pStm->Write(&vtype, sizeof(vtype), NULL);
00386 if( FAILED(result) )
00387 return result;
00388 len = SysStringLen(V_BSTR(propValue));
00389 result = pStm->Write(&len, sizeof(len), NULL);
00390 if( FAILED(result) )
00391 return result;
00392 if( len > 0 )
00393 {
00394 result = pStm->Write(V_BSTR(propValue), len*sizeof(OLECHAR), NULL);
00395 if( FAILED(result) )
00396 return result;
00397 }
00398 break;
00399 default:
00400 vtype = VT_EMPTY;
00401 result = pStm->Write(&vtype, sizeof(vtype), NULL);
00402 if( FAILED(result) )
00403 return result;
00404 }
00405 return result;
00406 };
00407
00408 HRESULT ReadProperty(LPSTREAM pStm, AxVLCPropertyPair **prop)
00409 {
00410 HRESULT result;
00411
00412 ULONG len;
00413
00414 result = pStm->Read(&len, sizeof(len), NULL);
00415 if( FAILED(result) )
00416 return result;
00417
00418 if( 0 == len )
00419 return E_INVALIDARG;
00420
00421 LPWSTR propName = (LPOLESTR)::alloca((len+1)*sizeof(WCHAR));
00422 if( NULL == propName )
00423 return E_OUTOFMEMORY;
00424
00425 result = pStm->Read(propName, len*sizeof(WCHAR), NULL);
00426 if( FAILED(result) )
00427 return result;
00428
00429 propName[len] = L'\0';
00430
00431 VARIANTARG propValue;
00432
00433 VARTYPE vtype;
00434 result = pStm->Read(&vtype, sizeof(vtype), NULL);
00435 if( FAILED(result) )
00436 return result;
00437
00438 switch( vtype )
00439 {
00440 case VT_BOOL:
00441 V_VT(&propValue) = vtype;
00442 result = pStm->Read(&V_BOOL(&propValue), sizeof(V_BOOL(&propValue)), NULL);
00443 if( FAILED(result) )
00444 return result;
00445 break;
00446 case VT_I4:
00447 V_VT(&propValue) = vtype;
00448 result = pStm->Read(&V_I4(&propValue), sizeof(V_I4(&propValue)), NULL);
00449 if( FAILED(result) )
00450 return result;
00451 break;
00452 case VT_BSTR:
00453 V_VT(&propValue) = vtype;
00454 result = pStm->Read(&len, sizeof(len), NULL);
00455 if( FAILED(result) )
00456 return result;
00457
00458 V_BSTR(&propValue) = NULL;
00459 if( len > 0 )
00460 {
00461 V_BSTR(&propValue) = SysAllocStringLen(NULL, len);
00462 if( NULL == V_BSTR(&propValue) )
00463 return E_OUTOFMEMORY;
00464
00465 result = pStm->Read(V_BSTR(&propValue), len*sizeof(OLECHAR), NULL);
00466 if( FAILED(result) )
00467 {
00468 SysFreeString(V_BSTR(&propValue));
00469 return result;
00470 }
00471 }
00472 break;
00473 default:
00474 VariantInit(&propValue);
00475 }
00476
00477 *prop = new AxVLCPropertyPair(propName, propValue);
00478
00479 return S_OK;
00480 };
00481
00482 AxVLCPropertyMap _pm;
00483 LONG _i_ref;
00484 };
00485
00487
00488 VLCPersistStreamInit::VLCPersistStreamInit(VLCPlugin *p_instance) : _p_instance(p_instance)
00489 {
00490 _p_props = new VLCPropertyBag();
00491 };
00492
00493 VLCPersistStreamInit::~VLCPersistStreamInit()
00494 {
00495 _p_props->Release();
00496 };
00497
00498 STDMETHODIMP VLCPersistStreamInit::GetClassID(LPCLSID pClsID)
00499 {
00500 if( NULL == pClsID )
00501 return E_POINTER;
00502
00503 *pClsID = _p_instance->getClassID();
00504
00505 return S_OK;
00506 };
00507
00508 STDMETHODIMP VLCPersistStreamInit::InitNew(void)
00509 {
00510 return _p_instance->onInit();
00511 };
00512
00513 STDMETHODIMP VLCPersistStreamInit::Load(LPSTREAM pStm)
00514 {
00515 HRESULT result = _p_props->Load(pStm);
00516 if( FAILED(result) )
00517 return result;
00518
00519 LPPERSISTPROPERTYBAG pPersistPropBag;
00520 if( FAILED(QueryInterface(IID_IPersistPropertyBag, (void**)&pPersistPropBag)) )
00521 return E_FAIL;
00522
00523 result = pPersistPropBag->Load(_p_props, NULL);
00524 pPersistPropBag->Release();
00525
00526 return result;
00527 };
00528
00529 STDMETHODIMP VLCPersistStreamInit::Save(LPSTREAM pStm, BOOL fClearDirty)
00530 {
00531 if( NULL == pStm )
00532 return E_INVALIDARG;
00533
00534 LPPERSISTPROPERTYBAG pPersistPropBag;
00535 if( FAILED(QueryInterface(IID_IPersistPropertyBag, (void**)&pPersistPropBag)) )
00536 return E_FAIL;
00537
00538 HRESULT result = pPersistPropBag->Save(_p_props, fClearDirty, _p_props->IsEmpty());
00539 pPersistPropBag->Release();
00540 if( FAILED(result) )
00541 return result;
00542
00543 return _p_props->Save(pStm);
00544 };
00545
00546 STDMETHODIMP VLCPersistStreamInit::IsDirty(void)
00547 {
00548 return _p_instance->isDirty() ? S_OK : S_FALSE;
00549 };
00550
00551 STDMETHODIMP VLCPersistStreamInit::GetSizeMax(ULARGE_INTEGER *pcbSize)
00552 {
00553 pcbSize->HighPart = 0UL;
00554 pcbSize->LowPart = 4096UL;
00555
00556 return S_OK;
00557 };
00558