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