1 //+-------------------------------------------------------------------------
2 //
3 //  For conditions of distribution and use, see copyright notice
4 //  in Flashpix.h
5 //
6 //  Copyright (c) 1999 Digital Imaging Group, Inc.
7 //
8 //  Contents:   Utility classes/functions for property implementation.
9 //
10 //  Classes:    CPropSetName -- wraps buffer and conversion of fmtids
11 //              CStackBuffer -- utility class that allows a small number
12 //                              of items be on stack, but more be on heap.
13 //
14 //  Functions:  PropVariantClear
15 //              FreePropVariantArray
16 //              AllocAndCopy
17 //              PropVariantCopy
18 //              PropSysAllocString
19 //              PropSysFreeString
20 //
21 //
22 //--------------------------------------------------------------------------
23 
24 #include "pch.cxx"
25 
26 //+-------------------------------------------------------------------
27 //
28 //  Member:     CPropSetName::CPropSetName
29 //
30 //  Synopsis:   Initialize internal buffer with converted FMTID
31 //
32 //  Arguments:  [rfmtid] -- FMTID to convert
33 //
34 //--------------------------------------------------------------------
35 
CPropSetName(REFFMTID rfmtid)36 CPropSetName::CPropSetName(REFFMTID rfmtid)
37 {
38     RtlGuidToPropertySetName(&rfmtid, _oszName);
39 }
40 
41 //+-------------------------------------------------------------------
42 //
43 //  Member:     CStackBuffer::Init
44 //
45 //  Synopsis:   Determine whether the class derived from this one
46 //              needs to have additional buffer allocated on the
47 //              heap and allocate it if neccessary.  Otherwise, if
48 //              there is space, use the internal buffer in the
49 //              derived class.
50 //
51 //  Arguments:  [cElements] -- the number of elements required.
52 //
53 //  Returns:    S_OK if buffer available
54 //              STG_E_INSUFFICIENTMEMORY if stack buffer was not
55 //                  big enough AND heap allocation failed.
56 //
57 //  Notes:      To be called directly by client after the derived
58 //              classes constructor initialized CStackBuffer.
59 //
60 //--------------------------------------------------------------------
61 
Init(ULONG cElements)62 HRESULT CStackBuffer::Init(ULONG cElements)
63 {
64     if (cElements > _cStackElements)
65     {
66         _pbHeapBuf = new BYTE[cElements * _cbElementSize];
67         if (_pbHeapBuf == NULL)
68         {
69             return(STG_E_INSUFFICIENTMEMORY);
70         }
71     }
72     return(S_OK);
73 }
74 
75 
76 //+-------------------------------------------------------------------------
77 //
78 //  Function:   PropVariantClear
79 //
80 //  Synopsis:   Deallocates the members of the PROPVARIANT that require
81 //              deallocation.
82 //
83 //  Arguments:  [pvarg] - variant to clear
84 //
85 //  Returns:    S_OK if successful,
86 //              STG_E_INVALIDPARAMETER if any part of the variant has
87 //                  an unknown vt type.  (In this case, ALL the elements
88 //                  that can be freed, will be freed.)
89 //
90 //  Modifies:   [pvarg] - the variant is left with vt = VT_EMPTY
91 //
92 //--------------------------------------------------------------------------
93 
PropVariantClear(PROPVARIANT * pvarg)94 STDAPI PropVariantClear(PROPVARIANT *pvarg)
95 {
96 
97     ULONG l;
98     HRESULT hr = S_OK;
99 
100     if (pvarg == NULL)
101         return(hr);
102 
103     switch (pvarg->vt)
104     {
105     case VT_EMPTY:
106     case VT_NULL:
107     case VT_ILLEGAL:
108 
109 #ifdef PROPVAR_VT_I1
110     case VT_I1:
111 #endif
112     case VT_UI1:
113     case VT_I2:
114     case VT_UI2:
115     case VT_I4:
116     case VT_UI4:
117     case VT_I8:
118     case VT_UI8:
119     case VT_R4:
120     case VT_R8:
121     case VT_CY:
122     case VT_DATE:
123         break;
124 
125     case VT_BSTR:
126         if (pvarg->bstrVal != NULL)
127             PropSysFreeString( pvarg->bstrVal );
128         break;
129 
130     case VT_BOOL:
131     case VT_ERROR:
132     case VT_FILETIME:
133         break;
134 
135     case VT_LPSTR:
136     case VT_LPWSTR:
137     case VT_CLSID:
138         PROPASSERT((void**)&pvarg->pszVal == (void**)&pvarg->pwszVal);
139         PROPASSERT((void**)&pvarg->pszVal == (void**)&pvarg->puuid);
140         CoTaskMemFree(pvarg->pszVal); // ptr at 0
141         break;
142 
143     case VT_CF:
144         if (pvarg->pclipdata != NULL)
145         {
146             CoTaskMemFree(pvarg->pclipdata->pClipData); // ptr at 8
147             CoTaskMemFree(pvarg->pclipdata);
148         }
149         break;
150 
151     case VT_BLOB:
152     case VT_BLOB_OBJECT:
153         CoTaskMemFree(pvarg->blob.pBlobData); //ptr at 4
154         break;
155 
156 #ifdef PROPVAR_VT_I1
157     case (VT_VECTOR | VT_I1):
158 #endif
159     case (VT_VECTOR | VT_UI1):
160     case (VT_VECTOR | VT_I2):
161     case (VT_VECTOR | VT_UI2):
162     case (VT_VECTOR | VT_I4):
163     case (VT_VECTOR | VT_UI4):
164     case (VT_VECTOR | VT_I8):
165     case (VT_VECTOR | VT_UI8):
166     case (VT_VECTOR | VT_R4):
167     case (VT_VECTOR | VT_R8):
168     case (VT_VECTOR | VT_CY):
169     case (VT_VECTOR | VT_DATE):
170 
171 FreeArray:
172         PROPASSERT((void**)&pvarg->caub.pElems == (void**)&pvarg->cai.pElems);
173         CoTaskMemFree(pvarg->caub.pElems);
174         break;
175 
176     case (VT_VECTOR | VT_BSTR):
177         if (pvarg->cabstr.pElems != NULL)
178         {
179             for (l=0; l< pvarg->cabstr.cElems; l++)
180             {
181                 if (pvarg->cabstr.pElems[l] != NULL)
182                 {
183                     PropSysFreeString( pvarg->cabstr.pElems[l] );
184                 }
185             }
186         }
187         goto FreeArray;
188 
189     case (VT_VECTOR | VT_BOOL):
190     case (VT_VECTOR | VT_ERROR):
191         goto FreeArray;
192 
193     case (VT_VECTOR | VT_LPSTR):
194     case (VT_VECTOR | VT_LPWSTR):
195         if (pvarg->calpstr.pElems != NULL)
196         for (l=0; l< pvarg->calpstr.cElems; l++)
197         {
198             CoTaskMemFree(pvarg->calpstr.pElems[l]);
199         }
200         goto FreeArray;
201 
202     case (VT_VECTOR | VT_FILETIME):
203     case (VT_VECTOR | VT_CLSID):
204         goto FreeArray;
205 
206     case (VT_VECTOR | VT_CF):
207         if (pvarg->caclipdata.pElems != NULL)
208             for (l=0; l< pvarg->caclipdata.cElems; l++)
209             {
210                 CoTaskMemFree(pvarg->caclipdata.pElems[l].pClipData);
211             }
212         goto FreeArray;
213 
214     case (VT_VECTOR | VT_VARIANT):
215         if (pvarg->capropvar.pElems != NULL)
216             hr = FreePropVariantArray(pvarg->capropvar.cElems, pvarg->capropvar.pElems);
217         goto FreeArray;
218 
219     default:
220         hr = STG_E_INVALIDPARAMETER;
221         break;
222     }
223 
224     //  We have all of the important information about the variant, so
225     //  let's clear it out.
226     //
227     PropVariantInit(pvarg);
228 
229     return (hr);
230 }
231 
232 //+---------------------------------------------------------------------------
233 //
234 //  Function:   FreePropVariantArray, public
235 //
236 //  Synopsis:   Frees a value array returned from ReadMultiple
237 //
238 //  Arguments:  [cval] - Number of elements
239 //              [rgvar] - Array
240 //
241 //  Returns:    S_OK if all types recognised and all freeable items were freed.
242 //              STG_E_INVALID_PARAMETER if one or more types were not
243 //              recognised but all items are freed too.
244 //
245 //  Notes:      Even if a vt-type is not understood, all the ones that are
246 //              understood are freed.  The error code will indicate
247 //              if *any* of the members were illegal types.
248 //
249 //----------------------------------------------------------------------------
250 
FreePropVariantArray(ULONG cVariants,PROPVARIANT * rgvars)251 STDAPI FreePropVariantArray (
252         ULONG cVariants,
253         PROPVARIANT *rgvars)
254 {
255     HRESULT hr = S_OK;
256 
257     if (rgvars != NULL)
258         for ( ULONG I=0; I < cVariants; I++ )
259             if (STG_E_INVALIDPARAMETER == PropVariantClear ( rgvars + I ))
260                 hr = STG_E_INVALIDPARAMETER;
261 
262     return hr;
263 }
264 
265 //+-------------------------------------------------------------------
266 //
267 //  Function:   AllocAndCopy
268 //
269 //  Synopsis:   Allocates enough memory to copy the passed data into and
270 //              then copies the data into the new buffer.
271 //
272 //  Arguments:  [cb] -- number of bytes of data to allocate and copy
273 //              [pvData]  --  the source of the data to copy
274 //              [phr] -- optional pointer to an HRESULT set to
275 //                       STG_E_INSUFFICIENTMEMORY if memory could
276 //                       not be allocated.
277 //
278 //
279 //  Returns:    NULL if no memory could be allocated,
280 //              Otherwise, pointer to allocated and copied data.
281 //
282 //--------------------------------------------------------------------
283 
AllocAndCopy(ULONG cb,void * pvData,HRESULT * phr=NULL)284 void * AllocAndCopy(ULONG cb, void * pvData, HRESULT *phr = NULL)
285 {
286     PROPASSERT(cb!=0);
287     void * pvNew  =  CoTaskMemAlloc(cb);
288     if (pvNew != NULL)
289     {
290         memcpy(pvNew, pvData, cb);
291     }
292     else
293     {
294         if (phr != NULL)
295         {
296             *phr = STG_E_INSUFFICIENTMEMORY;
297         }
298     }
299     return(pvNew);
300 }
301 
302 //+-------------------------------------------------------------------
303 //
304 //  Function:   SysAllocString
305 //              SysFreeString
306 //
307 //  Synopsis:   Exported BSTR allocation and deallocation routines
308 //
309 //
310 //--------------------------------------------------------------------
SysFreeString(BSTR bstr)311 STDAPI_(void) SysFreeString(BSTR bstr)
312 {
313     if (bstr)
314     {
315   BYTE* pab = (BYTE*) bstr;
316   delete[] (pab - sizeof(DWORD));
317     }
318 }
319 
SysAllocString(LPOLECHAR pwsz)320 STDAPI_(BSTR) SysAllocString(LPOLECHAR pwsz)
321 {
322     if (!pwsz) return NULL;
323 
324     DWORD cch = _tcslen(pwsz);
325 
326     /* a BSTR points to a DWORD length, followed by the string */
327     BYTE *pab = new BYTE[sizeof(DWORD) + ((cch+1)*sizeof(OLECHAR))];
328 
329     if (pab)
330     {
331         *((DWORD*) pab) = cch*sizeof(OLECHAR);
332         pab += sizeof(DWORD);
333         _tcscpy( (LPOLECHAR)pab, pwsz );
334     }
335     return ((BSTR) pab);
336 }
337 
338 //+---------------------------------------------------------------------------
339 //
340 //  Table:      g_TypeSizes, g_TypeSizesB
341 //
342 //  Synopsis:   Tables containing byte sizes and flags for various VT_ types.
343 //
344 //----------------------------------------------------------------------------
345 
346 #define BIT_VECTNOALLOC 0x80    // the VT_VECTOR with this type does not
347                                 // use heap allocation
348 
349 #define BIT_SIMPNOALLOC 0x40    // the non VT_VECTOR with this type does not
350                                 // use heap allocation
351 
352 #define BIT_INVALID     0x20    // marks an invalid type
353 
354 #define BIT_SIZEMASK    0x1F    // mask for size of underlying type
355 
356 const unsigned char g_TypeSizes[] =
357 {                     BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  0,                    //VT_EMPTY= 0,
358                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  0,                    //VT_NULL      = 1,
359                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  2,                    //VT_I2        = 2,
360                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  4,                    //VT_I4        = 3,
361                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  4,                    //VT_R4        = 4,
362                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  8,                    //VT_R8        = 5,
363                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  sizeof(CY),           //VT_CY        = 6,
364                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  sizeof(DATE),         //VT_DATE      = 7,
365                                                            sizeof(BSTR),         //VT_BSTR      = 8,
366         BIT_INVALID |                                      0,                    //VT_DISPATCH  = 9,
367                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  sizeof(SCODE),        //VT_ERROR     = 10,
368                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  sizeof(VARIANT_BOOL), //VT_BOOL      = 11,
369                                                            sizeof(PROPVARIANT),  //VT_VARIANT   = 12,
370         BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  0,                    //VT_UNKNOWN   = 13,
371         BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  0,                    // 14
372         BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  0,                    // 15
373 #ifdef PROPVAR_VT_I1
374                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  1,                    //VT_I1        = 16,
375 #else
376         BIT_INVALID /*BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  1,*/ | 0,             //VT_I1        = 16,
377 #endif
378                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  1,                    //VT_UI1       = 17,
379                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  2,                    //VT_UI2       = 18,
380                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  4,                    //VT_UI4       = 19,
381                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  8,                    //VT_I8        = 20,
382                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  8,                    //VT_UI8       = 21,
383         BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  0,                    //VT_INT  = 22,
384         BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  0,                    //VT_UINT = 23,
385         BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  0,                    //VT_VOID = 24,
386         BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  0,                    //VT_HRESULT      = 25,
387         BIT_INVALID |                                      0,                    //VT_PTR  = 26,
388         BIT_INVALID |                                      0,                    //VT_SAFEARRAY    = 27,
389         BIT_INVALID |                                      0,                    //VT_CARRAY       = 28,
390         BIT_INVALID |                                      0,                    //VT_USERDEFINED  = 29,
391                                                            sizeof(LPSTR),        //VT_LPSTR        = 30,
392                                                            sizeof(LPWSTR)        //VT_LPWSTR       = 31,
393 };
394 
395 const unsigned char g_TypeSizesB[] =
396 {
397     // BUGBUG vectors of types marked ** are tbd
398                       BIT_SIMPNOALLOC | BIT_VECTNOALLOC |  sizeof(FILETIME),     //VT_FILETIME     = 64,
399                                                            0,                    //**VT_BLOB = 65,
400                                                            0,                    //**VT_STREAM       = 66,
401                                                            0,                    //**VT_STORAGE      = 67,
402                                                            0,                    //**VT_STREAMED_OBJECT      = 68,
403                                                            0,                    //**VT_STORED_OBJECT        = 69,
404                                                            0,                    //**VT_BLOB_OBJECT  = 70,
405                                                            sizeof(CLIPDATA),     //VT_CF   = 71,
406                                         BIT_VECTNOALLOC |  sizeof(CLSID)         //VT_CLSID        = 72
407 };
408 
409 //+---------------------------------------------------------------------------
410 //
411 //  Function:   PropVariantCopy, public
412 //
413 //  Synopsis:   Copies a PROPVARIANT
414 //
415 //  Arguments:  [pDest] -- the destination PROPVARIANT
416 //              [pvarg] - the source PROPVARIANT
417 //
418 //  Returns:    Appropriate status code
419 //
420 //----------------------------------------------------------------------------
421 
PropVariantCopy(PROPVARIANT * pDest,const PROPVARIANT * pvarg)422 STDAPI PropVariantCopy ( PROPVARIANT * pDest, const PROPVARIANT * pvarg )
423 {
424     HRESULT     hr = S_OK;
425     register unsigned char TypeInfo;
426     register int iBaseType;
427 
428     // handle the simple types quickly
429     iBaseType = pvarg->vt & ~VT_VECTOR;
430 
431     if (iBaseType <= VT_LPWSTR)
432     {
433         TypeInfo = g_TypeSizes[iBaseType];
434     }
435     else
436     if (VT_FILETIME <= iBaseType && iBaseType <= VT_CLSID)
437     {
438         TypeInfo = g_TypeSizesB[iBaseType-VT_FILETIME];
439     }
440     else
441     {
442         hr = STG_E_INVALIDPARAMETER;
443         goto errRet;
444     }
445 
446     if ((TypeInfo & BIT_INVALID) != 0)
447     {
448         hr = STG_E_INVALIDPARAMETER;
449         goto errRet;
450     }
451 
452     *pDest = *pvarg;
453 
454     if ((pvarg->vt & VT_VECTOR) == 0)
455     {
456         // handle non-vector types
457 
458         if ((TypeInfo & BIT_SIMPNOALLOC) == 0)
459         {
460             void * pvAllocated = (void*)-1;
461 
462             switch (pvarg->vt)
463             {
464             case VT_BSTR:
465                 pvAllocated = pDest->bstrVal = PropSysAllocString( pvarg->bstrVal );
466                 break;
467 
468             case VT_LPSTR:
469                 if (pvarg->pszVal != NULL)
470                     pvAllocated = pDest->pszVal = (CHAR *)
471                         AllocAndCopy(strlen(pvarg->pszVal)+1, pvarg->pszVal);
472                 break;
473             case VT_LPWSTR:
474                 if (pvarg->pwszVal != NULL)
475                 {
476                     ULONG cbString = (Prop_wcslen(pvarg->pwszVal)+1) * sizeof(WCHAR);
477                     pvAllocated = pDest->pwszVal = (WCHAR *)
478                         AllocAndCopy(cbString, pvarg->pwszVal);
479                 }
480                 break;
481             case VT_CLSID:
482                 if (pvarg->puuid != NULL)
483                     pvAllocated = pDest->puuid = (GUID *)
484                         AllocAndCopy(sizeof(*(pvarg->puuid)), pvarg->puuid);
485                 break;
486 
487             case VT_CF:
488                 // first check if CLIPDATA is present
489                 if (pvarg->pclipdata != NULL)
490                 {
491                     // yes ... copy the clip data structure
492 
493                     pvAllocated = pDest->pclipdata = (CLIPDATA*)AllocAndCopy(
494                         sizeof(*(pvarg->pclipdata)), pvarg->pclipdata);
495 
496                     // did we allocate the CLIPDATA ?
497                     if (pvAllocated != NULL)
498                     {
499                         // yes ... initialize the destination.
500                         pDest->pclipdata->pClipData = NULL;
501 
502                         // Is the input valid?
503                         if (NULL == pvarg->pclipdata->pClipData
504                             &&
505                             0 != CBPCLIPDATA(*pvarg->pclipdata))
506                         {
507                             // no ... the input is not valid
508                             hr = STG_E_INVALIDPARAMETER;
509                         }
510 
511                         // Is there is any actual clip data ?
512                         else if (0 != CBPCLIPDATA(*pvarg->pclipdata))
513                         {
514                             // yes ... copy the actual clip data
515                             pvAllocated = pDest->pclipdata->pClipData =
516                                 (BYTE*)AllocAndCopy(CBPCLIPDATA(*pvarg->pclipdata),
517                                          pvarg->pclipdata->pClipData);
518                         }
519                     }   // if (pvAllocated != NULL)
520                 }   // if (pvarg->pclipdata != NULL)
521                 break;
522 
523             case VT_BLOB:
524             case VT_BLOB_OBJECT:
525                 if (pvarg->blob.pBlobData != NULL && pvarg->blob.cbSize != 0)
526                 {
527                     pvAllocated = pDest->blob.pBlobData = (BYTE *)
528                         AllocAndCopy(pvarg->blob.cbSize,
529                                      pvarg->blob.pBlobData);
530                 }
531                 else
532                 {
533                     // if the cbsize is 0 or pBlobData is NULL, make
534                     // sure both values are consistent in the destination
535                     pDest->blob.pBlobData = NULL;
536                     pDest->blob.cbSize = 0;
537                 }
538                 break;
539 
540             case VT_VARIANT:
541                 // drop through - this merely documents that VT_VARIANT has been thought of.
542 
543             default:
544                 //PROPASSERT(!"Unexpected non-vector type in PropVariantCopy");
545                 hr = STG_E_INVALIDPARAMETER;
546                 goto errRet;
547             }
548 
549             if( FAILED(hr) )
550                 goto errRet;
551 
552             if (pvAllocated == NULL)
553             {
554                 hr = STG_E_INSUFFICIENTMEMORY;
555                 goto errRet;
556             }
557         }   // if ((TypeInfo & BIT_SIMPNOALLOC) == 0)
558     }   // if ((pvarg->vt & VT_VECTOR) == 0)
559 
560     else
561     {
562         ULONG cbType = TypeInfo & BIT_SIZEMASK;
563         if (cbType == 0)
564         {
565             hr = STG_E_INVALIDPARAMETER;
566             goto errRet;
567         }
568 
569         // handle the vector types
570 
571         // this depends on the pointer and count being in the same place in
572         // each of CAUI1 CAI2 etc
573 
574         // allocate the array for pElems
575         if (pvarg->caub.pElems == NULL || pvarg->caub.cElems == 0)
576         {
577             PROPASSERT( hr == S_OK );
578             goto errRet; // not really an error
579         }
580 
581         void *pvAllocated = pDest->caub.pElems = (BYTE *)
582             AllocAndCopy(cbType * pvarg->caub.cElems, pvarg->caub.pElems);
583 
584         if (pvAllocated == NULL)
585         {
586             hr = STG_E_INSUFFICIENTMEMORY;
587             goto errRet;
588         }
589 
590         if ((TypeInfo & BIT_VECTNOALLOC) != 0)
591         {
592             // the vector needs no further allocation
593             PROPASSERT( hr == S_OK );
594             goto errRet;
595         }
596 
597         ULONG l;
598 
599         // vector types that require allocation ...
600         // we first zero out the pointers so that we can use PropVariantClear
601         // to clean up in the error case
602 
603         switch (pvarg->vt)
604         {
605         case (VT_VECTOR | VT_BSTR):
606             // initialize for error case
607             for (l=0; l< pvarg->cabstr.cElems; l++)
608             {
609                 pDest->cabstr.pElems[l] = NULL;
610             }
611             break;
612 
613         case (VT_VECTOR | VT_LPSTR):
614         case (VT_VECTOR | VT_LPWSTR):
615             // initialize for error case
616             for (l=0; l< pvarg->calpstr.cElems; l++)
617             {
618                 pDest->calpstr.pElems[l] = NULL;
619             }
620             break;
621 
622         case (VT_VECTOR | VT_CF):
623             // initialize for error case
624             for (l=0; l< pvarg->caclipdata.cElems; l++)
625             {
626                 pDest->caclipdata.pElems[l].pClipData  = NULL;
627             }
628             break;
629 
630         case (VT_VECTOR | VT_VARIANT):
631             // initialize for error case
632             for (l=0; l< pvarg->capropvar.cElems; l++)
633             {
634                 pDest->capropvar.pElems[l].vt = VT_ILLEGAL;
635             }
636             break;
637 
638         default:
639             PROPASSERT(!"Internal error: Unexpected type in PropVariantCopy");
640             CoTaskMemFree(pvAllocated);
641             hr = STG_E_INVALIDPARAMETER;
642             goto errRet;
643         }
644 
645         // now do the vector copy...
646 
647         switch (pvarg->vt)
648         {
649         case (VT_VECTOR | VT_BSTR):
650             for (l=0; l< pvarg->cabstr.cElems; l++)
651             {
652                 if (pvarg->cabstr.pElems[l] != NULL)
653                 {
654                     pDest->cabstr.pElems[l] = PropSysAllocString( pvarg->cabstr.pElems[l]);
655                     if (pDest->cabstr.pElems[l]  == NULL)
656                     {
657                         hr = STG_E_INSUFFICIENTMEMORY;
658                         break;
659                     }
660                 }
661             }
662             break;
663 
664         case (VT_VECTOR | VT_LPWSTR):
665             for (l=0; l< pvarg->calpwstr.cElems; l++)
666             {
667                 if (pvarg->calpwstr.pElems[l] != NULL)
668                 {
669 
670                     pDest->calpwstr.pElems[l] = (LPWSTR)AllocAndCopy(
671                         sizeof(WCHAR)*(Prop_wcslen(pvarg->calpwstr.pElems[l])+1),
672                         pvarg->calpwstr.pElems[l],
673                         &hr);
674 
675                     if (hr != S_OK)
676                         break;
677                 }
678             }
679             break;
680 
681         case (VT_VECTOR | VT_LPSTR):
682             for (l=0; l< pvarg->calpstr.cElems; l++)
683             {
684                 if (pvarg->calpstr.pElems[l] != NULL)
685                 {
686                     pDest->calpstr.pElems[l] = (LPSTR)AllocAndCopy(
687                         strlen(pvarg->calpstr.pElems[l])+1,
688                         pvarg->calpstr.pElems[l],
689                         &hr);
690 
691                     if (hr != S_OK)
692                         break;
693                 }
694             }
695             break;
696 
697         case (VT_VECTOR | VT_CF):
698             for (l=0; l< pvarg->caclipdata.cElems; l++)
699             {
700                 // Is the input valid?
701                 if (NULL == pvarg->caclipdata.pElems[l].pClipData
702                     &&
703                     0 != CBPCLIPDATA(pvarg->caclipdata.pElems[l] ))
704                 {
705                     hr = STG_E_INVALIDPARAMETER;
706                     break;
707                 }
708 
709                 // Is there data to copy?
710                 if (0 != CBPCLIPDATA(pvarg->caclipdata.pElems[l]))
711                 {
712                     pDest->caclipdata.pElems[l].pClipData  = (BYTE*)AllocAndCopy(
713                         CBPCLIPDATA(pvarg->caclipdata.pElems[l]),
714                         pvarg->caclipdata.pElems[l].pClipData,
715                         &hr);
716 
717                     if (hr != S_OK)
718                         break;
719                 }
720             }
721             break;
722 
723         case (VT_VECTOR | VT_VARIANT):
724             for (l=0; l< pvarg->capropvar.cElems; l++)
725             {
726                 hr = PropVariantCopy(pDest->capropvar.pElems + l,
727                                      pvarg->capropvar.pElems + l);
728                 if (hr != S_OK)
729                 {
730                     break;
731                 }
732             }
733             break;
734 
735         default:
736             PROPASSERT(!"Internal error: Unexpected type in PropVariantCopy");
737             CoTaskMemFree(pvAllocated);
738             hr = STG_E_INVALIDPARAMETER;
739             goto errRet;
740         }
741 
742         if (hr != S_OK)
743         {
744             PropVariantClear(pDest);
745             goto errRet;
746         }
747     }
748 
749 errRet:
750 
751     if (hr != S_OK)
752     {
753         // VT_EMPTY
754         PROPASSERT(VT_EMPTY == 0);
755         memset(pDest, 0, sizeof(*pDest));
756     }
757 
758     return(hr);
759 }
760 
761 //+---------------------------------------------------------------------------
762 //
763 //  Function:   NtStatusToScode, public
764 //
765 //  Synopsis:   Attempts to map an NTSTATUS code to an SCODE
766 //
767 //  Arguments:  [nts] - NTSTATUS
768 //
769 //  Returns:    Appropriate status code
770 //
771 //  History:    29-Jun-93       DrewB   Created
772 //
773 //  Notes:      Assumes [nts] is an error code
774 //              This function is by no means exhaustively complete
775 //
776 //----------------------------------------------------------------------------
777 
NtStatusToScode(NTSTATUS nts)778 SCODE NtStatusToScode(NTSTATUS nts)
779 {
780     SCODE sc;
781 
782     PropDbg((DEB_ITRACE, "In  NtStatusToScode(%lX)\n", nts));
783 
784     switch(nts)
785     {
786     case STATUS_INVALID_PARAMETER:
787     case STATUS_INVALID_PARAMETER_MIX:
788     case STATUS_INVALID_PARAMETER_1:
789     case STATUS_INVALID_PARAMETER_2:
790     case STATUS_INVALID_PARAMETER_3:
791     case STATUS_INVALID_PARAMETER_4:
792     case STATUS_INVALID_PARAMETER_5:
793     case STATUS_INVALID_PARAMETER_6:
794     case STATUS_INVALID_PARAMETER_7:
795     case STATUS_INVALID_PARAMETER_8:
796     case STATUS_INVALID_PARAMETER_9:
797     case STATUS_INVALID_PARAMETER_10:
798     case STATUS_INVALID_PARAMETER_11:
799     case STATUS_INVALID_PARAMETER_12:
800         sc = STG_E_INVALIDPARAMETER;
801         break;
802 
803     case STATUS_DUPLICATE_NAME:
804     case STATUS_DUPLICATE_OBJECTID:
805     case STATUS_OBJECTID_EXISTS:
806     case STATUS_OBJECT_NAME_COLLISION:
807         sc = STG_E_FILEALREADYEXISTS;
808         break;
809 
810     case STATUS_NO_SUCH_DEVICE:
811     case STATUS_NO_SUCH_FILE:
812     case STATUS_OBJECT_NAME_NOT_FOUND:
813     case STATUS_NOT_A_DIRECTORY:
814     case STATUS_FILE_IS_A_DIRECTORY:
815     case STATUS_PROPSET_NOT_FOUND:
816     case STATUS_NOT_FOUND:
817     case STATUS_OBJECT_TYPE_MISMATCH:
818         sc = STG_E_FILENOTFOUND;
819         break;
820 
821     case STATUS_OBJECT_NAME_INVALID:
822     case STATUS_OBJECT_PATH_SYNTAX_BAD:
823     case STATUS_OBJECT_PATH_INVALID:
824     case STATUS_NAME_TOO_LONG:
825         sc = STG_E_INVALIDNAME;
826         break;
827 
828     case STATUS_ACCESS_DENIED:
829         sc = STG_E_ACCESSDENIED;
830         break;
831 
832     case STATUS_NO_MEMORY:
833     case STATUS_INSUFFICIENT_RESOURCES:
834         sc = STG_E_INSUFFICIENTMEMORY;
835         break;
836 
837     case STATUS_INVALID_HANDLE:
838     case STATUS_FILE_INVALID:
839     case STATUS_FILE_FORCED_CLOSED:
840         sc = STG_E_INVALIDHANDLE;
841         break;
842 
843     case STATUS_INVALID_DEVICE_REQUEST:
844     case STATUS_INVALID_SYSTEM_SERVICE:
845     case STATUS_NOT_IMPLEMENTED:
846         sc = STG_E_INVALIDFUNCTION;
847         break;
848 
849     case STATUS_NO_MEDIA_IN_DEVICE:
850     case STATUS_UNRECOGNIZED_MEDIA:
851     case STATUS_DISK_CORRUPT_ERROR:
852     case STATUS_DATA_ERROR:
853         sc = STG_E_WRITEFAULT;
854         break;
855 
856     case STATUS_OBJECT_PATH_NOT_FOUND:
857         sc = STG_E_PATHNOTFOUND;
858         break;
859 
860     case STATUS_SHARING_VIOLATION:
861         sc = STG_E_SHAREVIOLATION;
862         break;
863 
864     case STATUS_FILE_LOCK_CONFLICT:
865     case STATUS_LOCK_NOT_GRANTED:
866         sc = STG_E_LOCKVIOLATION;
867         break;
868 
869     case STATUS_DISK_FULL:
870         sc = STG_E_MEDIUMFULL;
871         break;
872 
873     case STATUS_ACCESS_VIOLATION:
874     case STATUS_INVALID_USER_BUFFER:
875         sc = STG_E_INVALIDPOINTER;
876         break;
877 
878     case STATUS_TOO_MANY_OPENED_FILES:
879         sc = STG_E_TOOMANYOPENFILES;
880         break;
881 
882     case STATUS_DIRECTORY_NOT_EMPTY:
883         sc = WIN32_SCODE(ERROR_DIR_NOT_EMPTY);
884         break;
885 
886     case STATUS_DELETE_PENDING:
887         sc = STG_E_REVERTED;
888         break;
889 
890     case STATUS_INTERNAL_DB_CORRUPTION:
891         sc = STG_E_INVALIDHEADER;
892         break;
893 
894     case STATUS_UNSUCCESSFUL:
895         sc = E_FAIL;
896         break;
897 
898     case STATUS_UNMAPPABLE_CHARACTER:
899         sc = HRESULT_FROM_WIN32( ERROR_NO_UNICODE_TRANSLATION );
900         break;
901 
902     default:
903         PropDbg((DEB_ERROR, "NtStatusToScode: Unknown status %lX\n", nts));
904 
905         sc = HRESULT_FROM_NT(nts);
906         break;
907     }
908 
909     PropDbg((DEB_ITRACE, "Out NtStatusToScode => %lX\n", sc));
910     return sc;
911 }
912 
913 #if DBG!=0
914 
915 ULONG
DbgPrint(PCHAR Format,...)916 DbgPrint(
917     PCHAR Format,
918     ...
919     )
920 {
921     va_list arglist;
922     CHAR Buffer[512];
923     int cb;
924 
925     //
926     // Format the output into a buffer and then print it.
927     //
928 
929     va_start(arglist, Format);
930     cb = PropVsprintfA(Buffer, Format, arglist);
931     if (cb == -1) {             // detect buffer overflow
932         cb = sizeof(Buffer);
933         Buffer[sizeof(Buffer) - 2] = '\n';
934         Buffer[sizeof(Buffer) - 1] = '\0';
935     }
936 
937     OutputDebugString(Buffer);
938 
939     return 0;
940 }
941 #endif
942 
943