persiststreaminit.cpp
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:14k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * persiststreaminit.cpp: ActiveX control for VLC
  3.  *****************************************************************************
  4.  * Copyright (C) 2005 the VideoLAN team
  5.  *
  6.  * Authors: Damien Fouilleul <Damien.Fouilleul@laposte.net>
  7.  *
  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.
  12.  *
  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.
  17.  *
  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.  *****************************************************************************/
  22. #include "plugin.h"
  23. #include "persiststreaminit.h"
  24. #include "utils.h"
  25. #include <map>
  26. #include <malloc.h>
  27. #include <wchar.h>
  28. using namespace std;
  29. class AxVLCVariant
  30. {
  31. public:
  32.     AxVLCVariant(void)
  33.     {
  34.         VariantInit(&_v);
  35.     };
  36.     ~AxVLCVariant(void)
  37.     {
  38.         VariantClear(&_v);
  39.     }
  40.     AxVLCVariant(VARIANTARG &v)
  41.     {
  42.         VariantInit(&_v);
  43.         VariantCopy(&_v, &v);
  44.     };
  45.     AxVLCVariant(VARIANTARG *v)
  46.     {
  47.         VariantInit(&_v);
  48.         VariantCopy(&_v, v);
  49.     };
  50.     AxVLCVariant(const AxVLCVariant &vv)
  51.     {
  52.         VariantInit(&_v);
  53.         VariantCopy(&_v, const_cast<VARIANTARG *>(&(vv._v)));
  54.     };
  55.     AxVLCVariant(int i)
  56.     {
  57.         V_VT(&_v) = VT_I4;
  58.         V_I4(&_v) = i;
  59.     };
  60.     AxVLCVariant(BSTR bstr)
  61.     {
  62.         VARIANT arg;
  63.         V_VT(&arg) = VT_BSTR;
  64.         V_BSTR(&arg) = bstr;
  65.         VariantInit(&_v);
  66.         VariantCopy(&_v, &arg);
  67.     };
  68.     inline const VARIANTARG *variantArg(void) const {
  69.         return &_v;
  70.     }
  71.     inline void swap(AxVLCVariant &v1, AxVLCVariant &v2)
  72.     {
  73.         VARIANTARG tmp = v1._v;
  74.         v1._v = v2._v;
  75.         v2._v = tmp;
  76.     };
  77. private:
  78.     VARIANTARG _v;
  79. };
  80. class AxVLCWSTR
  81. {
  82. public:
  83.     AxVLCWSTR(void) : _data(NULL) {};
  84.     virtual ~AxVLCWSTR()
  85.     {
  86.         if( NULL != _data )
  87.         {
  88.             ULONG refcount = InterlockedDecrement(&(_data->refcount));
  89.             if( 0 == refcount )
  90.                 CoTaskMemFree(_data);
  91.         }
  92.     };
  93.     AxVLCWSTR(LPCWSTR s)
  94.     {
  95.         if( NULL != s )
  96.         {
  97.             size_t len = wcslen(s);
  98.             if( len > 0 )
  99.             {
  100.                 size_t size = len*sizeof(WCHAR);
  101.                 _data = (struct data *)CoTaskMemAlloc(sizeof(struct data)+size);
  102.                 if( NULL != _data )
  103.                 {
  104.                     _data->len = len;
  105.                     _data->refcount = 1;
  106.                     memcpy(_data->wstr, s, size);
  107.                     _data->wstr[len]=L'';
  108.                     return;
  109.                 }
  110.             }
  111.         }
  112.         _data = NULL;
  113.     };
  114.     AxVLCWSTR(const AxVLCWSTR &s)
  115.     {
  116.         _data = s._data;
  117.         if( NULL != _data )
  118.             InterlockedIncrement(&(_data->refcount));
  119.     };
  120.     inline bool operator<(const AxVLCWSTR &s) const
  121.     {
  122.         return compareNoCase(s.wstr()) < 0;
  123.     };
  124.     inline bool operator<(LPCWSTR s) const
  125.     {
  126.         return compareNoCase(s) < 0;
  127.     };
  128.     inline bool operator==(const AxVLCWSTR &s) const
  129.     {
  130.         return size() == s.size() ?
  131.                     (compareNoCase(s.wstr()) == 0) : false;
  132.     };
  133.     inline bool operator==(LPCWSTR s) const
  134.     {
  135.         return compareNoCase(s) == 0;
  136.     };
  137.     LPCWSTR wstr(void) const
  138.     {
  139.         return (NULL != _data) ? _data->wstr : NULL;
  140.     };
  141.     size_t size(void) const
  142.     {
  143.         return (NULL != _data) ? _data->len : 0;
  144.     };
  145. private:
  146.     inline int compareNoCase(LPCWSTR s) const
  147.     {
  148.         if( NULL == _data )
  149.         {
  150.             return (NULL == s) ? 0 : -1;
  151.         }
  152.         if( NULL == s )
  153.             return 1;
  154.         return _wcsicmp(_data->wstr, s);
  155.     };
  156.     struct data {
  157.         size_t  len;
  158.         LONG    refcount;
  159.         wchar_t wstr[1];
  160.     } *_data;
  161. };
  162. typedef pair<class AxVLCWSTR, class AxVLCVariant> AxVLCPropertyPair;
  163. typedef map<class AxVLCWSTR, class AxVLCVariant> AxVLCPropertyMap;
  164. ///////////////////////////
  165. class VLCPropertyBag : public IPropertyBag
  166. {
  167. public:
  168.     VLCPropertyBag(void) : _i_ref(1) {};
  169.     virtual ~VLCPropertyBag() {};
  170.     // IUnknown methods
  171.     STDMETHODIMP QueryInterface(REFIID riid, void **ppv)
  172.     {
  173.         if( NULL == ppv )
  174.             return E_POINTER;
  175.         if( (IID_IUnknown == riid)
  176.          || (IID_IPropertyBag == riid) )
  177.         {
  178.             AddRef();
  179.             *ppv = reinterpret_cast<LPVOID>(this);
  180.             return NOERROR;
  181.         }
  182.         // standalone object
  183.         return E_NOINTERFACE;
  184.     };
  185.     STDMETHODIMP_(ULONG) AddRef(void)
  186.         { return InterlockedIncrement(&_i_ref); };
  187.     STDMETHODIMP_(ULONG) Release(void)
  188.     {
  189.         ULONG refcount = InterlockedDecrement(&_i_ref);
  190.         if( 0 == refcount )
  191.         {
  192.             delete this;
  193.             return 0;
  194.         }
  195.         return refcount;
  196.     };
  197.     // IPropertyBag methods
  198.     STDMETHODIMP Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
  199.     {
  200.         if( (NULL == pszPropName) || (NULL == pVar) )
  201.             return E_POINTER;
  202.         AxVLCPropertyMap::const_iterator notfound = _pm.end();
  203.         AxVLCPropertyMap::const_iterator iter = _pm.find(pszPropName);
  204.         if( notfound != iter )
  205.         {
  206.             VARTYPE vtype = V_VT(pVar);
  207.             VARIANTARG v;
  208.             VariantInit(&v);
  209.             VariantCopy(&v, const_cast<VARIANTARG*>((*iter).second.variantArg()));
  210.             if( (V_VT(&v) != vtype) && FAILED(VariantChangeType(&v, &v, 0, vtype)) )
  211.             {
  212.                 VariantClear(&v);
  213.                 return E_FAIL;
  214.             }
  215.             *pVar = v;
  216.             return S_OK;
  217.         }
  218.         else
  219.             return E_INVALIDARG;
  220.     };
  221.  
  222.     STDMETHODIMP Write(LPCOLESTR pszPropName, VARIANT *pVar)
  223.     {
  224.         if( (NULL == pszPropName) || (NULL == pVar) )
  225.             return E_POINTER;
  226.         AxVLCPropertyPair val(pszPropName, pVar);
  227.         pair<AxVLCPropertyMap::iterator, bool> p = _pm.insert(val);
  228.         if( false == p.second )
  229.             // replace existing key value
  230.             (*p.first).second = val.second;
  231.         return S_OK;
  232.     };
  233.     // custom methods
  234.     HRESULT Load(LPSTREAM pStm)
  235.     {
  236.         if( NULL == pStm )
  237.             return E_INVALIDARG;
  238.         HRESULT result;
  239.         AxVLCPropertyPair *val;
  240.         result = ReadProperty(pStm, &val);
  241.         if( SUCCEEDED(result) )
  242.         {
  243.             if( (val->first == L"(Count)") && (VT_I4 == V_VT(val->second.variantArg())) )
  244.             {
  245.                 size_t count = V_I4(val->second.variantArg());
  246.                 delete val;
  247.                 while( count-- )
  248.                 {
  249.                     result = ReadProperty(pStm, &val);
  250.                     if( FAILED(result) )
  251.                         return result;
  252.                     pair<AxVLCPropertyMap::iterator, bool> p = _pm.insert(*val);
  253.                     if( false == p.second )
  254.                         // replace existing key value
  255.                         (*p.first).second = val->second;
  256.                     delete val;
  257.                 }
  258.             }
  259.         }
  260.         return result;
  261.     };
  262.     HRESULT Save(LPSTREAM pStm)
  263.     {
  264.         if( NULL == pStm )
  265.             return E_INVALIDARG;
  266.         HRESULT result;
  267.         AxVLCPropertyPair header(L"(Count)", _pm.size());
  268.         result = WriteProperty(pStm, header);
  269.         if( SUCCEEDED(result) )
  270.         {
  271.             AxVLCPropertyMap::const_iterator iter = _pm.begin();
  272.             AxVLCPropertyMap::const_iterator end  = _pm.end();
  273.             while( iter != end )
  274.             {
  275.                 result = WriteProperty(pStm, *(iter++));
  276.                 if( FAILED(result) )
  277.                     return result;
  278.             }
  279.         }
  280.         return result;
  281.     };
  282.     BOOL IsEmpty()
  283.     {
  284.         return _pm.size() == 0;
  285.     }
  286. private:
  287.     HRESULT WriteProperty(LPSTREAM pStm, const AxVLCPropertyPair &prop)
  288.     {
  289.         HRESULT result;
  290.         const AxVLCWSTR propName = prop.first;
  291.         ULONG len = propName.size();
  292.         if( 0 == len )
  293.             return E_INVALIDARG;
  294.         result = pStm->Write(&len, sizeof(len), NULL);
  295.         if( FAILED(result) )
  296.             return result;
  297.         result = pStm->Write(propName.wstr(), len*sizeof(WCHAR), NULL);
  298.         if( FAILED(result) )
  299.             return result;
  300.         const VARIANTARG *propValue = prop.second.variantArg();
  301.         VARTYPE vtype = V_VT(propValue);
  302.         switch( vtype )
  303.         {
  304.             case VT_BOOL:
  305.                 result = pStm->Write(&vtype, sizeof(vtype), NULL);
  306.                 if( FAILED(result) )
  307.                     return result;
  308.                 result = pStm->Write(&V_BOOL(propValue), sizeof(V_BOOL(propValue)), NULL);
  309.                 if( FAILED(result) )
  310.                     return result;
  311.                 break;
  312.             case VT_I4:
  313.                 result = pStm->Write(&vtype, sizeof(vtype), NULL);
  314.                 if( FAILED(result) )
  315.                     return result;
  316.                 result = pStm->Write(&V_I4(propValue), sizeof(V_I4(propValue)), NULL);
  317.                 if( FAILED(result) )
  318.                     return result;
  319.                 break;
  320.             case VT_BSTR:
  321.                 result = pStm->Write(&vtype, sizeof(vtype), NULL);
  322.                 if( FAILED(result) )
  323.                     return result;
  324.                 len = SysStringLen(V_BSTR(propValue));
  325.                 result = pStm->Write(&len, sizeof(len), NULL);
  326.                 if( FAILED(result) )
  327.                     return result;
  328.                 if( len > 0 )
  329.                 {
  330.                     result = pStm->Write(V_BSTR(propValue), len*sizeof(OLECHAR), NULL);
  331.                     if( FAILED(result) )
  332.                         return result;
  333.                 }
  334.                 break;
  335.             default:
  336.                 vtype = VT_EMPTY;
  337.                 result = pStm->Write(&vtype, sizeof(vtype), NULL);
  338.                 if( FAILED(result) )
  339.                     return result;
  340.         }
  341.         return result;
  342.     };
  343.     HRESULT ReadProperty(LPSTREAM pStm, AxVLCPropertyPair **prop)
  344.     {
  345.         HRESULT result;
  346.         ULONG len;
  347.         result = pStm->Read(&len, sizeof(len), NULL);
  348.         if( FAILED(result) )
  349.             return result;
  350.         if( 0 == len )
  351.             return E_INVALIDARG;
  352.         WCHAR propName[len + 1];
  353.         result = pStm->Read(propName, len*sizeof(WCHAR), NULL);
  354.         if( FAILED(result) )
  355.             return result;
  356.         propName[len] = L'';
  357.         VARIANTARG propValue;
  358.         VARTYPE vtype;
  359.         result = pStm->Read(&vtype, sizeof(vtype), NULL);
  360.         if( FAILED(result) )
  361.             return result;
  362.         switch( vtype )
  363.         {
  364.             case VT_BOOL:
  365.                 V_VT(&propValue) = vtype;
  366.                 result = pStm->Read(&V_BOOL(&propValue), sizeof(V_BOOL(&propValue)), NULL);
  367.                 if( FAILED(result) )
  368.                     return result;
  369.                 break;
  370.             case VT_I4:
  371.                 V_VT(&propValue) = vtype;
  372.                 result = pStm->Read(&V_I4(&propValue), sizeof(V_I4(&propValue)), NULL);
  373.                 if( FAILED(result) )
  374.                     return result;
  375.                 break;
  376.             case VT_BSTR:
  377.                 V_VT(&propValue) = vtype;
  378.                 result = pStm->Read(&len, sizeof(len), NULL);
  379.                 if( FAILED(result) )
  380.                     return result;
  381.                 V_BSTR(&propValue) = NULL;
  382.                 if( len > 0 )
  383.                 {
  384.                     V_BSTR(&propValue) = SysAllocStringLen(NULL, len);
  385.                     if( NULL == V_BSTR(&propValue) )
  386.                         return E_OUTOFMEMORY;
  387.                     result = pStm->Read(V_BSTR(&propValue), len*sizeof(OLECHAR), NULL);
  388.                     if( FAILED(result) )
  389.                     {
  390.                         SysFreeString(V_BSTR(&propValue));
  391.                         return result;
  392.                     }
  393.                 }
  394.                 break;
  395.             default:
  396.                 VariantInit(&propValue);
  397.         }
  398.         *prop = new AxVLCPropertyPair(propName, propValue);
  399.         return S_OK;
  400.     };
  401.     AxVLCPropertyMap _pm;
  402.     LONG _i_ref;
  403. };
  404. ///////////////////////////
  405. VLCPersistStreamInit::VLCPersistStreamInit(VLCPlugin *p_instance) : _p_instance(p_instance)
  406. {
  407.     _p_props = new VLCPropertyBag();
  408. };
  409. VLCPersistStreamInit::~VLCPersistStreamInit()
  410. {
  411.     _p_props->Release();
  412. };
  413. STDMETHODIMP VLCPersistStreamInit::GetClassID(LPCLSID pClsID)
  414. {
  415.     if( NULL == pClsID )
  416.         return E_POINTER;
  417.     *pClsID = _p_instance->getClassID();
  418.     return S_OK;
  419. };
  420. STDMETHODIMP VLCPersistStreamInit::InitNew(void)
  421. {
  422.     return _p_instance->onInit();
  423. };
  424. STDMETHODIMP VLCPersistStreamInit::Load(LPSTREAM pStm)
  425. {
  426.     HRESULT result = _p_props->Load(pStm);
  427.     if( FAILED(result) )
  428.         return result;
  429.     LPPERSISTPROPERTYBAG pPersistPropBag;
  430.     if( FAILED(QueryInterface(IID_IPersistPropertyBag, (void**)&pPersistPropBag)) )
  431.         return E_FAIL;
  432.     result = pPersistPropBag->Load(_p_props, NULL);
  433.     pPersistPropBag->Release();
  434.     return result;
  435. };
  436. STDMETHODIMP VLCPersistStreamInit::Save(LPSTREAM pStm, BOOL fClearDirty)
  437. {
  438.     if( NULL == pStm )
  439.         return E_INVALIDARG;
  440.     LPPERSISTPROPERTYBAG pPersistPropBag;
  441.     if( FAILED(QueryInterface(IID_IPersistPropertyBag, (void**)&pPersistPropBag)) )
  442.         return E_FAIL;
  443.     HRESULT result = pPersistPropBag->Save(_p_props, fClearDirty, _p_props->IsEmpty());
  444.     pPersistPropBag->Release();
  445.     if( FAILED(result) )
  446.         return result;
  447.     return _p_props->Save(pStm);
  448. };
  449. STDMETHODIMP VLCPersistStreamInit::IsDirty(void)
  450. {
  451.     return _p_instance->isDirty() ? S_OK : S_FALSE;
  452. };
  453. STDMETHODIMP VLCPersistStreamInit::GetSizeMax(ULARGE_INTEGER *pcbSize)
  454. {
  455.     pcbSize->HighPart = 0UL;
  456.     pcbSize->LowPart  = 16384UL; // just a guess
  457.     return S_OK;
  458. };