TextMessage.cpp
author Volker Birk <vb@pep-project.org>
Sat, 30 May 2015 19:36:36 +0200
changeset 32 b9e23540d7fd
parent 31 83a083fb4810
permissions -rw-r--r--
locking
     1 // TextMessage.cpp : Implementation of CTextMessage
     2 
     3 #include "stdafx.h"
     4 #include "TextMessage.h"
     5 
     6 using namespace pEp::utility;
     7 
     8 // CTextMessage
     9 
    10 STDMETHODIMP CTextMessage::InterfaceSupportsErrorInfo(REFIID riid)
    11 {
    12 	static const IID* const arr[] = 
    13 	{
    14 		&IID_ITextMessage
    15 	};
    16 
    17 	for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
    18 	{
    19 		if (InlineIsEqualGUID(*arr[i],riid))
    20 			return S_OK;
    21 	}
    22 	return S_FALSE;
    23 }
    24 
    25 
    26 STDMETHODIMP CTextMessage::get_from(pEp_identity_s* pVal)
    27 {
    28     assert(pVal);
    29 
    30     try {
    31         copy_identity(pVal, msg()->from);
    32     }
    33     catch (bad_alloc&) {
    34         return E_OUTOFMEMORY;
    35     }
    36     catch (exception&) {
    37         return E_FAIL;
    38     }
    39 
    40     return S_OK;
    41 }
    42 
    43 
    44 STDMETHODIMP CTextMessage::put_from(pEp_identity_s* newVal)
    45 {
    46     assert(newVal);
    47 
    48     ::pEp_identity *_from;
    49     
    50     try {
    51         _from = new_identity(newVal);
    52     }
    53     catch (bad_alloc&) {
    54         return E_OUTOFMEMORY;
    55     }
    56     catch (exception&)
    57     {
    58         return E_FAIL;
    59     }
    60 
    61     ::free_identity(msg()->from);
    62     msg()->from = _from;
    63     return S_OK;
    64 }
    65 
    66 static HRESULT il_get(const identity_list *il, LPSAFEARRAY * sa)
    67 {
    68     assert(sa);
    69     int len = identity_list_length(il);
    70 
    71     LPSAFEARRAY _sa = newSafeArray<pEp_identity_s>(len);
    72     if (_sa == NULL)
    73         return E_OUTOFMEMORY;
    74 
    75     const identity_list *_il;
    76     LONG i;
    77     for (i = 0, _il = il; _il && _il->ident; _il = _il->next, i++) {
    78         pEp_identity_s cs;
    79         
    80         try {
    81             copy_identity(&cs, _il->ident);
    82 
    83             ::SafeArrayPutElement(_sa, &i, &cs);
    84 
    85             IRecordInfo *ir = getRecordInfo<pEp_identity_s>();
    86             ir->RecordClear(&cs);
    87         }
    88         catch (bad_alloc&) {
    89             IRecordInfo *ir = getRecordInfo<pEp_identity_s>();
    90             ir->RecordClear(&cs);
    91             SafeArrayDestroy(_sa);
    92             return E_OUTOFMEMORY;
    93         }
    94         catch (exception&) {
    95             IRecordInfo *ir = getRecordInfo<pEp_identity_s>();
    96             ir->RecordClear(&cs);
    97             SafeArrayDestroy(_sa);
    98             return E_FAIL;
    99         }
   100     }
   101 
   102     *sa = _sa;
   103     return S_OK;
   104 }
   105 
   106 static HRESULT il_put(identity_list **target, SAFEARRAY * newVal)
   107 {
   108     assert(newVal);
   109     if (newVal == NULL)
   110         return E_INVALIDARG;
   111 
   112     identity_list *il = new_identity_list(NULL);
   113     if (il == NULL)
   114         return E_OUTOFMEMORY;
   115 
   116     identity_list *_il;
   117     LONG lbound, ubound;
   118     LONG i;
   119     SafeArrayGetLBound(newVal, 1, &lbound);
   120     SafeArrayGetUBound(newVal, 1, &ubound);
   121 
   122     for (i = lbound, _il = il; i <= ubound; i++) {
   123         pEp_identity * ident;
   124         pEp_identity_s cs;
   125         memset(&cs, 0, sizeof(pEp_identity_s));
   126 
   127         try {
   128             HRESULT hr = ::SafeArrayGetElement(newVal, &i, &cs);
   129             if (hr != S_OK) {
   130                 IRecordInfo *ri = getRecordInfo<pEp_identity_s>();
   131                 ri->RecordClear(&cs);
   132                 free_identity_list(il);
   133                 return hr;
   134             }
   135             ident = new_identity(&cs);
   136 
   137             IRecordInfo *ri = getRecordInfo<pEp_identity_s>();
   138             ri->RecordClear(&cs);
   139         }
   140         catch (bad_alloc&) {
   141             IRecordInfo *ri = getRecordInfo<pEp_identity_s>();
   142             ri->RecordClear(&cs);
   143             free_identity_list(il);
   144             return E_OUTOFMEMORY;
   145         }
   146         catch (exception&) {
   147             IRecordInfo *ri = getRecordInfo<pEp_identity_s>();
   148             ri->RecordClear(&cs);
   149             free_identity_list(il);
   150             return E_FAIL;
   151         }
   152         _il = identity_list_add(_il, ident);
   153         if (_il == NULL) {
   154             free_identity_list(il);
   155             return E_OUTOFMEMORY;
   156         }
   157     }
   158 
   159     free_identity_list(*target);
   160     *target = il;
   161 
   162     return S_OK;
   163 }
   164 
   165 STDMETHODIMP CTextMessage::get_to(LPSAFEARRAY * pVal)
   166 {
   167     return il_get(msg()->to, pVal);
   168 }
   169 
   170 STDMETHODIMP CTextMessage::put_to(SAFEARRAY * newVal)
   171 {
   172     return il_put(&msg()->to, newVal);
   173 }
   174 
   175 STDMETHODIMP CTextMessage::get_recv_by(pEp_identity_s* pVal)
   176 {
   177     assert(pVal);
   178 
   179     try {
   180         copy_identity(pVal, msg()->recv_by);
   181     }
   182     catch (bad_alloc&) {
   183         return E_OUTOFMEMORY;
   184     }
   185     catch (exception&) {
   186         return E_FAIL;
   187     }
   188 
   189     return S_OK;
   190 }
   191 
   192 
   193 STDMETHODIMP CTextMessage::put_recv_by(pEp_identity_s* newVal)
   194 {
   195     assert(newVal);
   196 
   197     ::pEp_identity *_recv_by;
   198 
   199     try {
   200         _recv_by = new_identity(newVal);
   201     }
   202     catch (bad_alloc&) {
   203         return E_OUTOFMEMORY;
   204     }
   205     catch (exception&) {
   206         return E_FAIL;
   207     }
   208 
   209     ::free_identity(msg()->recv_by);
   210     msg()->recv_by = _recv_by;
   211     return S_OK;
   212 }
   213 
   214 STDMETHODIMP CTextMessage::get_cc(LPSAFEARRAY * pVal)
   215 {
   216     return il_get(msg()->cc, pVal);
   217 }
   218 
   219 STDMETHODIMP CTextMessage::put_cc(SAFEARRAY * newVal)
   220 {
   221     return il_put(&msg()->cc, newVal);
   222 }
   223 
   224 STDMETHODIMP CTextMessage::get_bcc(LPSAFEARRAY * pVal)
   225 {
   226     return il_get(msg()->bcc, pVal);
   227 }
   228 
   229 STDMETHODIMP CTextMessage::put_bcc(SAFEARRAY * newVal)
   230 {
   231     return il_put(&msg()->bcc, newVal);
   232 }
   233 
   234 STDMETHODIMP CTextMessage::get_reply_to(LPSAFEARRAY * pVal)
   235 {
   236     return il_get(msg()->reply_to, pVal);
   237 }
   238 
   239 STDMETHODIMP CTextMessage::put_reply_to(SAFEARRAY * newVal)
   240 {
   241     return il_put(&msg()->reply_to, newVal);
   242 }
   243 
   244 STDMETHODIMP CTextMessage::get_dir(pEp_msg_direction *pVal)
   245 {
   246     assert(pVal);
   247 
   248     *pVal = (pEp_msg_direction) msg()->dir;
   249 
   250     return S_OK;
   251 }
   252 
   253 STDMETHODIMP CTextMessage::put_dir(pEp_msg_direction newVal)
   254 {
   255     msg()->dir = (PEP_msg_direction) newVal;
   256 
   257     return S_OK;
   258 }
   259 
   260 STDMETHODIMP CTextMessage::get_id(BSTR * pVal)
   261 {
   262     assert(pVal);
   263 
   264     _bstr_t val;
   265 
   266     if (msg()->id) {
   267         try {
   268             val = utf16_bstr(msg()->id);
   269         }
   270         catch (bad_alloc&) {
   271             return E_OUTOFMEMORY;
   272         }
   273         catch (exception&) {
   274             return E_FAIL;
   275         }
   276         *pVal = val.Detach();
   277     }
   278 
   279     return S_OK;
   280 }
   281 
   282 STDMETHODIMP CTextMessage::put_id(BSTR newVal)
   283 {
   284     char *_val = NULL;
   285     string val;
   286 
   287     if (newVal) {
   288         try {
   289             val = utf8_string(newVal);
   290         }
   291         catch (bad_alloc&) {
   292             return E_OUTOFMEMORY;
   293         }
   294         catch (exception&) {
   295             return E_FAIL;
   296         }
   297 
   298         _val = _strdup(val.c_str());
   299         if (_val == NULL)
   300             return E_OUTOFMEMORY;
   301     }
   302 
   303     if (msg()->id)
   304         free(msg()->id);
   305 
   306     msg()->id = _val;
   307     return S_OK;
   308 }
   309 
   310 STDMETHODIMP CTextMessage::get_shortmsg(BSTR * pVal)
   311 {
   312     assert(pVal);
   313 
   314     _bstr_t val;
   315 
   316     if (msg()->shortmsg) {
   317         try {
   318             val = utf16_bstr(msg()->shortmsg);
   319         }
   320         catch (bad_alloc&) {
   321             return E_OUTOFMEMORY;
   322         }
   323         catch (exception&) {
   324             return E_FAIL;
   325         }
   326         *pVal = val.Detach();
   327     }
   328 
   329     return S_OK;
   330 }
   331 
   332 STDMETHODIMP CTextMessage::put_shortmsg(BSTR newVal)
   333 {
   334     char *_val = NULL;
   335 
   336     if (newVal) {
   337         string val;
   338 
   339         try {
   340             val = utf8_string(newVal);
   341         }
   342         catch (bad_alloc&) {
   343             return E_OUTOFMEMORY;
   344         }
   345         catch (exception&) {
   346             return E_FAIL;
   347         }
   348 
   349         _val = _strdup(val.c_str());
   350         if (_val == NULL)
   351             return E_OUTOFMEMORY;
   352     }
   353 
   354     if (msg()->shortmsg)
   355         free(msg()->shortmsg);
   356 
   357     msg()->shortmsg = _val;
   358     return S_OK;
   359 }
   360 
   361 STDMETHODIMP CTextMessage::get_longmsg(BSTR * pVal)
   362 {
   363     assert(pVal);
   364 
   365     _bstr_t val;
   366 
   367     if (msg()->longmsg) {
   368         try {
   369             val = utf16_bstr(msg()->longmsg);
   370         }
   371         catch (bad_alloc&) {
   372             return E_OUTOFMEMORY;
   373         }
   374         catch (exception&) {
   375             return E_FAIL;
   376         }
   377         *pVal = val.Detach();
   378     }
   379 
   380     return S_OK;
   381 }
   382 
   383 STDMETHODIMP CTextMessage::put_longmsg(BSTR newVal)
   384 {
   385     char * _val = NULL;
   386 
   387     if (newVal) {
   388         string val;
   389 
   390         try {
   391             val = utf8_string(newVal);
   392         }
   393         catch (bad_alloc&) {
   394             return E_OUTOFMEMORY;
   395         }
   396         catch (exception&) {
   397             return E_FAIL;
   398         }
   399 
   400         _val = _strdup(val.c_str());
   401         if (_val == NULL)
   402             return E_OUTOFMEMORY;
   403     }
   404 
   405     if (msg()->longmsg)
   406         free(msg()->longmsg);
   407 
   408     msg()->longmsg = _val;
   409     return S_OK;
   410 }
   411 
   412 STDMETHODIMP CTextMessage::get_longmsg_formatted(BSTR * pVal)
   413 {
   414     assert(pVal);
   415 
   416     _bstr_t val;
   417 
   418     if (msg()->longmsg_formatted) {
   419         try {
   420             val = utf16_bstr(msg()->longmsg_formatted);
   421         }
   422         catch (bad_alloc&) {
   423             return E_OUTOFMEMORY;
   424         }
   425         catch (exception&) {
   426             return E_FAIL;
   427         }
   428         *pVal = val.Detach();
   429     }
   430 
   431     return S_OK;
   432 }
   433 
   434 STDMETHODIMP CTextMessage::put_longmsg_formatted(BSTR newVal)
   435 {
   436     char *_val = NULL;
   437 
   438     if (newVal) {
   439         string val;
   440 
   441         try {
   442             val = utf8_string(newVal);
   443         }
   444         catch (bad_alloc&) {
   445             return E_OUTOFMEMORY;
   446         }
   447         catch (exception&) {
   448             return E_FAIL;
   449         }
   450 
   451         _val = _strdup(val.c_str());
   452         if (_val == NULL)
   453             return E_OUTOFMEMORY;
   454     }
   455 
   456     if (msg()->longmsg_formatted)
   457         free(msg()->longmsg_formatted);
   458 
   459     msg()->longmsg_formatted = _val;
   460     return S_OK;
   461 }
   462 
   463 STDMETHODIMP CTextMessage::add_attachment(SAFEARRAY * data, BSTR mime_type, BSTR filename)
   464 {
   465     assert(data);
   466     if (data == NULL)
   467         return E_INVALIDARG;
   468 
   469     CComSafeArray<BYTE> sa_data(data);
   470     size_t len = sa_data.GetCount();
   471 
   472     char *_data = (char *) malloc(sa_data.GetCount() + 1);
   473     assert(_data);
   474     if (_data == NULL)
   475         return E_OUTOFMEMORY;
   476 
   477     memcpy(_data, sa_data.m_psa->pvData, len);
   478     _data[len] = 0;
   479     sa_data.Detach();
   480 
   481     string _mime_type;
   482     if (mime_type) {
   483         try {
   484             _mime_type = utf8_string(mime_type);
   485         }
   486         catch (bad_alloc&) {
   487             free(_data);
   488             return E_OUTOFMEMORY;
   489         }
   490         catch (exception&) {
   491             free(_data);
   492             return E_FAIL;
   493         }
   494     }
   495 
   496     string _filename;
   497     if (filename) {
   498         try {
   499             _filename = utf8_string(filename);
   500         }
   501         catch (bad_alloc&) {
   502             free(_data);
   503             return E_OUTOFMEMORY;
   504         }
   505         catch (exception&) {
   506             free(_data);
   507             return E_FAIL;
   508         }
   509     }
   510 
   511     bloblist_t *blob = bloblist_add(msg()->attachments, _data, len, _mime_type.c_str(), _filename.c_str());
   512     if (blob == NULL) {
   513         free(_data);
   514         return E_OUTOFMEMORY;
   515     }
   516 
   517     if (msg()->attachments == NULL)
   518         msg()->attachments = blob;
   519 
   520     return S_OK;
   521 }
   522 
   523 STDMETHODIMP CTextMessage::has_attachments(boolean *result)
   524 {
   525     assert(result);
   526 
   527     if (msg()->attachments == NULL || msg()->attachments->data == NULL) {
   528         m_next_attachment = NULL;
   529         *result = false;
   530         return S_OK;
   531     }
   532 
   533     m_next_attachment = msg()->attachments;
   534     *result = true;
   535 
   536     return S_OK;
   537 }
   538 
   539 STDMETHODIMP CTextMessage::next_attachment(SAFEARRAY ** data, BSTR * mime_type, BSTR * filename, boolean *result)
   540 {
   541     assert(data);
   542     assert(mime_type);
   543     assert(filename);
   544     assert(result);
   545 
   546     if (m_next_attachment == NULL)
   547         return E_ILLEGAL_METHOD_CALL;
   548 
   549     CComSafeArray<BYTE> sa;
   550     try {
   551         sa.Create(m_next_attachment->size);
   552     }
   553     catch (bad_alloc&) {
   554         return E_OUTOFMEMORY;
   555     }
   556 
   557     memcpy(sa.m_psa->pvData, m_next_attachment->data, m_next_attachment->size);
   558 
   559     _bstr_t _mime_type;
   560     if (m_next_attachment->mime_type) {
   561         try {
   562             _mime_type = utf16_bstr(m_next_attachment->mime_type);
   563         }
   564         catch (bad_alloc&) {
   565             return E_OUTOFMEMORY;
   566         }
   567         catch (exception&) {
   568             return E_FAIL;
   569         }
   570     }
   571 
   572     _bstr_t _filename;
   573     if (m_next_attachment->filename) {
   574         try {
   575             _filename = utf16_bstr(m_next_attachment->filename);
   576         }
   577         catch (bad_alloc&) {
   578             return E_OUTOFMEMORY;
   579         }
   580         catch (exception&) {
   581             return E_FAIL;
   582         }
   583     }
   584 
   585     *data = sa.Detach();
   586     *mime_type = _mime_type.Detach();
   587     *filename = _filename.Detach();
   588 
   589     m_next_attachment = m_next_attachment->next;
   590     *result = m_next_attachment != NULL;
   591 
   592     return S_OK;
   593 }
   594 
   595 STDMETHODIMP CTextMessage::get_sent(hyper * result)
   596 {
   597     assert(result);
   598 
   599     if (msg()->sent == NULL)
   600         return E_NOT_SET;
   601 
   602     *result = mktime(msg()->sent);
   603     return S_OK;
   604 }
   605 
   606 STDMETHODIMP CTextMessage::put_sent(hyper val)
   607 {
   608     ::timestamp * ts = new_timestamp(val);
   609     if (ts == NULL)
   610         return E_OUTOFMEMORY;
   611 
   612     if (msg()->sent)
   613         free_timestamp(msg()->sent);
   614     msg()->sent = ts;
   615 
   616     return S_OK;
   617 }
   618 
   619 STDMETHODIMP CTextMessage::get_recv(hyper * result)
   620 {
   621     assert(result);
   622 
   623     if (msg()->recv == NULL)
   624         return E_NOT_SET;
   625 
   626     *result = mktime(msg()->recv);
   627     return S_OK;
   628 }
   629 
   630 STDMETHODIMP CTextMessage::put_recv(hyper val)
   631 {
   632     ::timestamp * ts = new_timestamp(val);
   633     if (ts == NULL)
   634         return E_OUTOFMEMORY;
   635 
   636     if (msg()->recv)
   637         free_timestamp(msg()->recv);
   638     msg()->recv = ts;
   639 
   640     return S_OK;
   641 }
   642 
   643 STDMETHODIMP CTextMessage::get_references(SAFEARRAY ** pVal)
   644 {
   645     assert(pVal);
   646 
   647     CComSafeArray<BSTR> sa;
   648     try {
   649         if (msg()->references) {
   650             sa = string_array(msg()->references);
   651         }
   652         else {
   653             sa.Create(0UL);
   654         }
   655     }
   656     catch (bad_alloc&) {
   657         return E_OUTOFMEMORY;
   658     }
   659     catch (exception&) {
   660         return E_FAIL;
   661     }
   662     
   663     *pVal = sa.Detach();
   664     return S_OK;
   665 }
   666 
   667 STDMETHODIMP CTextMessage::put_references(SAFEARRAY * newVal)
   668 {
   669     assert(newVal);
   670 
   671     stringlist_t *sl;
   672     
   673     try {
   674         sl = new_stringlist(newVal);
   675     }
   676     catch (bad_alloc&) {
   677         return E_OUTOFMEMORY;
   678     }
   679     catch (exception&) {
   680         return E_FAIL;
   681     }
   682 
   683     if (msg()->references)
   684         free_stringlist(msg()->references);
   685 
   686     msg()->references = sl;
   687 
   688     return S_OK;
   689 }
   690 
   691 STDMETHODIMP CTextMessage::get_keywords(SAFEARRAY ** pVal)
   692 {
   693     assert(pVal);
   694 
   695     CComSafeArray<BSTR> sa;
   696     try {
   697         if (msg()->keywords) {
   698             sa = string_array(msg()->keywords);
   699         }
   700         else {
   701             sa.Create(0UL);
   702         }
   703     }
   704     catch (bad_alloc&) {
   705         return E_OUTOFMEMORY;
   706     }
   707     catch (exception&) {
   708         return E_FAIL;
   709     }
   710 
   711     *pVal = sa.Detach();
   712     return S_OK;
   713 }
   714 
   715 STDMETHODIMP CTextMessage::put_keywords(SAFEARRAY * newVal)
   716 {
   717     assert(newVal);
   718 
   719     stringlist_t *sl;
   720 
   721     try {
   722         sl = new_stringlist(newVal);
   723     }
   724     catch (bad_alloc&) {
   725         return E_OUTOFMEMORY;
   726     }
   727     catch (exception&) {
   728         return E_FAIL;
   729     }
   730 
   731     if (msg()->keywords)
   732         free_stringlist(msg()->keywords);
   733 
   734     msg()->keywords = sl;
   735 
   736     return S_OK;
   737 }
   738 
   739 STDMETHODIMP CTextMessage::get_comments(BSTR * pVal)
   740 {
   741     assert(pVal);
   742 
   743     _bstr_t val;
   744 
   745     if (msg()->comments) {
   746         try {
   747             val = utf16_bstr(msg()->comments);
   748         }
   749         catch (bad_alloc&) {
   750             return E_OUTOFMEMORY;
   751         }
   752         catch (exception&) {
   753             return E_FAIL;
   754         }
   755         *pVal = val.Detach();
   756     }
   757 
   758     return S_OK;
   759 }
   760 
   761 STDMETHODIMP CTextMessage::put_comments(BSTR newVal)
   762 {
   763     char * _val = NULL;
   764 
   765     if (newVal) {
   766         string val;
   767 
   768         try {
   769             val = utf8_string(newVal);
   770         }
   771         catch (bad_alloc&) {
   772             return E_OUTOFMEMORY;
   773         }
   774         catch (exception&) {
   775             return E_FAIL;
   776         }
   777 
   778         _val = _strdup(val.c_str());
   779         if (_val == NULL)
   780             return E_OUTOFMEMORY;
   781     }
   782 
   783     if (msg()->comments)
   784         free(msg()->comments);
   785 
   786     msg()->comments = _val;
   787     return S_OK;
   788 }
   789 
   790 STDMETHODIMP CTextMessage::get_opt_fields(LPSAFEARRAY * pVal)
   791 {
   792     assert(pVal);
   793 
   794     if (msg()->opt_fields == NULL)
   795         return S_OK;
   796 
   797     int len = stringpair_list_length(msg()->opt_fields);
   798 
   799     LPSAFEARRAY sa = newSafeArray<struct opt_field>(len);
   800     if (sa == NULL)
   801         return E_OUTOFMEMORY;
   802 
   803     stringpair_list_t *il;
   804     LONG i;
   805     for (i = 0, il = msg()->opt_fields; il && il->value; il = il->next, i++) {
   806         opt_field fld;
   807         memset(&fld, 0, sizeof(opt_field));
   808 
   809         try {
   810             fld.name = utf16_bstr(il->value->key).Detach();
   811             fld.value = utf16_bstr(il->value->value).Detach();
   812 
   813             ::SafeArrayPutElement(sa, &i, &fld);
   814 
   815             IRecordInfo *ir = getRecordInfo<opt_field>();
   816             ir->RecordClear(&fld);
   817         }
   818         catch (bad_alloc&) {
   819             IRecordInfo *ir = getRecordInfo<opt_field>();
   820             ir->RecordClear(&fld);
   821             SafeArrayDestroy(sa);
   822             return E_OUTOFMEMORY;
   823         }
   824         catch (exception&) {
   825             IRecordInfo *ir = getRecordInfo<opt_field>();
   826             ir->RecordClear(&fld);
   827             SafeArrayDestroy(sa);
   828             return E_FAIL;
   829         }
   830     }
   831 
   832     *pVal = sa;
   833     return S_OK;
   834 }
   835 
   836 STDMETHODIMP CTextMessage::put_opt_fields(SAFEARRAY * newVal)
   837 {
   838     assert(newVal);
   839 
   840     if (newVal == NULL)
   841         return E_INVALIDARG;
   842 
   843     stringpair_list_t *il = new_stringpair_list(NULL);
   844     if (il == NULL)
   845         return E_OUTOFMEMORY;
   846 
   847     stringpair_list_t *_il;
   848     LONG lbound, ubound;
   849     LONG i;
   850     SafeArrayGetLBound(newVal, 1, &lbound);
   851     SafeArrayGetUBound(newVal, 1, &ubound);
   852 
   853     for (i = lbound, _il = il; i <= ubound; i++) {
   854         stringpair_t * pair;
   855         try {
   856             struct opt_field cs;
   857             memset(&cs, 0, sizeof(opt_field));
   858             HRESULT hr = ::SafeArrayGetElement(newVal, &i, &cs);
   859             pair = new_stringpair(utf8_string(cs.name).c_str(), utf8_string(cs.value).c_str());
   860             IRecordInfo *ri = getRecordInfo<opt_field>();
   861             ri->RecordClear(&cs);
   862         }
   863         catch (bad_alloc&) {
   864             free_stringpair_list(il);
   865             return E_OUTOFMEMORY;
   866         }
   867         catch (exception&) {
   868             free_stringpair_list(il);
   869             return E_FAIL;
   870         }
   871         _il = stringpair_list_add(_il, pair);
   872         if (_il == NULL) {
   873             free_stringpair_list(il);
   874             return E_OUTOFMEMORY;
   875         }
   876     }
   877 
   878     free_stringpair_list(msg()->opt_fields);
   879     msg()->opt_fields = il;
   880 
   881     return S_OK;
   882 }