1 //------------------------------------------------------------------------------------------------
2 //  MODULE    : OLEStreams.cpp
3 //  LANGUAGE  : C++
4 //  AUTHOR    : Yue Zhang
5 //  DATE    : Tuesday, Janurary 23, 1996
6 //  DESCRIPTION : This file contains  OLEStream object
7 //
8 //  COMMENT   : An OLEStream class contains an IStream in OLE library. Besides supporting
9 //          I/O functions in IStream, OLEStream class also provides a family of I/O
10 //          functions in forms of ReadVT_xx and WriteVT_xx to read/write VT_xx types data
11 //          defined in variant.h. In ReadVT_xx and WriteVT_xx functions, swapping bytes
12 //          is performed when the file encounted is created on different platforms (
13 //          Intel or Motorola).
14 //
15 //          I/O functions:
16 //            Read()/Write():       read/write any bytes of data, no swap bytes
17 //            ReadVT_xx()/WriteVT_xx(): read/write VT type of data, swap bytes, including,
18 //                        short, long, float, double, BOOL, CY, LPSTR,
19 //                        LPWSTR, FILETIME, BLOB, CLIPDATA, CLSID, VECTOR,
20 //                        VARIANT
21 //
22 //      SCCSID            : @(#)olestrm.cpp 1.7 10:45:28 12 Sep 1997
23 //  ----------------------------------------------------------------------------
24 //  Copyright (c) 1999 Digital Imaging Group, Inc.
25 //  For conditions of distribution and use, see copyright notice
26 //  in Flashpix.h
27 //  ----------------------------------------------------------------------------
28 //------------------------------------------------------------------------------------------------
29 
30 //  Includes
31 //  --------
32   #include  <stdio.h>
33 
34 #if defined(USE_LEGACY_INCLUDES)
35 #  include <iostream.h>
36 #else
37 #  include <iostream>
38    using namespace std;
39 #endif
40 
41 #ifndef OLECommun_h
42   #include "olecomm.h"
43 #endif
44 #ifndef OLECore_h
45   #include "olecore.h"
46 #endif
47 #ifndef OLEStreams_h
48   #include  "olestrm.h"
49 #endif
50 #ifndef OLEStorages_h
51   #include  "olestorg.h"
52 #endif
53 
54 //  Constants
55 //  ---------
56 
57 // This is the largest string authorized in this version. The purpose is to avoid
58 // allocation of humonguous arrays due to corrupted OLE files.
59 #define LARGEST_STRING 1024
60 
61 //  Variables
62 //  ---------
63 
64 //  ----------------------------------------------------------------------------
65 
66 //  ----------------------------------------------------------------------------
67 
68 //  ----------------------------------------------------------------------------
69 //  Methods of OLEStream
70 //  ----------------------------------------------------------------------------
71 
72 
73 // Create an OLEStream object from parent storage.
OLEStream(OLEStorage * parentStorage,IStream * currentStream)74 OLEStream::OLEStream(OLEStorage * parentStorage, IStream * currentStream)
75 {
76   // Set the bytes swap flag
77 #ifdef IN_BIG_ENDIAN
78   fSwapBytes = TRUE;
79 #else
80   fSwapBytes = FALSE;
81 #endif
82 
83   parStorage = parentStorage;
84 
85   oleStream  = currentStream;
86 #if 1
87   if (oleStream)
88     oleStream->AddRef();
89 #endif
90 }
91 
~OLEStream()92 OLEStream::~OLEStream()
93 {
94   Release();
95 
96 }
97 
98 // Add reference to the IStream object contained in the OLEStream
AddRef()99 void OLEStream::AddRef()
100 {
101   OLECore::AddRef();
102 
103   if (oleStream) {
104     oleStream->AddRef();
105   }
106 }
107 
108 // Release the IStream object contained in the OLEStream
Release()109 void OLEStream::Release()
110 {
111   if (oleStream)
112     oleStream->Release();
113 
114   OLECore::Release();
115 }
116 
117 // OLEStream::Read(), generic OLE stream read function
118 // Read the data of bufLen bytes to dataBuf from the stream, bytes are not swapped after
119 // read. Return NULL if fails
Read(void * dataBuf,size_t bufLen)120 Boolean OLEStream::Read(void * dataBuf, size_t bufLen)
121 {
122   HRESULT err;
123   if (oleStream) {
124     if (FAILED(err = oleStream->Read(dataBuf, bufLen, NULL)))
125     {
126       lastError = TranslateOLEError(err);
127       fpxStatus = OLEtoFPXError(err);     // CHG_FILE_ERR - improve reporting
128       return FALSE;
129     }
130   } else
131     return FALSE;
132 
133   return TRUE;
134 }
135 
136 // OLEStream::Write(), generic OLE stream write function
137 // Write the data of bufLen bytes in dataBuf to the stream, bytes are not swapped before
138 // write. Return NULL if fails
Write(const void * dataBuf,size_t bufLen)139 Boolean OLEStream::Write(const void * dataBuf, size_t bufLen)
140 {
141   HRESULT err;
142   if (oleStream) {
143     if (FAILED(err = oleStream->Write(dataBuf, bufLen, NULL)))
144     {
145       lastError = TranslateOLEError(err);
146       fpxStatus = OLEtoFPXError(err);     // CHG_FILE_ERR - improve reporting
147       return FALSE;
148     }
149   } else
150     return FALSE;
151 
152   return TRUE;
153 }
154 
155 // Set the stream to a new position. There are 3 modes,
156 // STREAM_SEEK_BEG: set the stream pointer to the offset from beginning of stream
157 // STREAM_SEEK_CUR: set the stream pointer to the offset from current of stream
158 // STREAM_SEEK_END: set the stream pointer to the offset from end of stream
Seek(const long offset,const unsigned long mode)159 Boolean OLEStream::Seek( const long offset, const unsigned long mode )
160 {
161   LARGE_INTEGER oleOffset;
162   HRESULT err;
163 
164   // Set the offset to a ULARGE_INTEGER
165   LISet32(oleOffset, offset);
166 
167   if (oleStream) {
168     if (FAILED(err = oleStream->Seek(oleOffset, mode, NULL)))
169     {
170       lastError = TranslateOLEError(err);
171       fpxStatus = OLEtoFPXError(err);     // CHG_FILE_ERR - improve reporting
172       return FALSE;
173     }
174   } else
175     return FALSE;
176 
177   return TRUE;
178 }
179 
180 // Get the position of end of the stream
GetEndOfFile(long * endPosition)181 Boolean OLEStream::GetEndOfFile( long *endPosition)
182 {
183   LARGE_INTEGER oleOffset;
184   ULARGE_INTEGER FAR position;
185   HRESULT err;
186 
187   // Initialize the positions
188   LISet32(oleOffset, 0);
189   *endPosition = 0;
190 
191   if (oleStream) {
192     if (FAILED(err = oleStream->Seek(oleOffset, STREAM_SEEK_END, &position)))
193     {
194       lastError = TranslateOLEError(err);
195       return FALSE;
196     }
197     // Save the position
198     *endPosition = position.LowPart;
199   } else
200     return FALSE;
201 
202   return TRUE;
203 }
204 
205 // Set the size of the stream
SetSize(unsigned long sizeOfStream)206 Boolean OLEStream::SetSize(unsigned long sizeOfStream)
207 {
208   ULARGE_INTEGER oleSize;
209   HRESULT err;
210 
211   // Set the length of stream to a ULARGE_INTEGER
212   ULISet32(oleSize, sizeOfStream);
213 
214   if (oleStream) {
215     if (FAILED(err = oleStream->SetSize(oleSize)))
216     {
217       lastError = TranslateOLEError(err);
218       return FALSE;
219     }
220   } else
221     return FALSE;
222 
223   return TRUE;
224 }
225 
226 // Copy the stream to a new one
CopyTo(LPSTREAM pstm,unsigned long copyLen)227 Boolean OLEStream::CopyTo( LPSTREAM pstm, unsigned long copyLen )
228 {
229   ULARGE_INTEGER oleLen;
230   HRESULT err;
231 
232   // Set the length of stream to a ULARGE_INTEGER
233   ULISet32(oleLen, copyLen);
234 
235   if (oleStream) {
236     if (FAILED(err = oleStream->CopyTo(pstm, oleLen, NULL, NULL)))
237     {
238       lastError = TranslateOLEError(err);
239       return FALSE;
240     }
241   } else
242     return FALSE;
243 
244   return TRUE;
245 }
246 
247 // Save the changes made to the stream
Commit()248 Boolean OLEStream::Commit( )
249 {
250   HRESULT err;
251   if (oleStream) {
252     if (FAILED(err = oleStream->Commit(0)))
253     {
254       lastError = TranslateOLEError(err);
255       return FALSE;
256     }
257 
258     return TRUE;
259   } else
260     return FALSE;
261 }
262 
263 // Discard the changes made to the stream
Revert()264 Boolean OLEStream::Revert( )
265 {
266   HRESULT err;
267   if (oleStream) {
268     if (FAILED(err = oleStream->Revert()) )
269     {
270       lastError = TranslateOLEError(err);
271       return FALSE;
272     }
273     return TRUE;
274   } else
275     return FALSE;
276 }
277 
278 
279 // NOTE: All read functions return the number of bytes of data stored
280 // IN MEMORY, and all write functions return the number of bytes of data
281 // written to THE STREAM. They are often different. This is a convention to
282 // make stream reading/writing very easy.
283 
284 //----------------------- ReadVT_xx functions -----------------------------/
285 
286 // OLEStream::ReadVT()
287 // This is a generic function that takes a property of the given type out of
288 // the given stream (at its current position) and puts it at the location
289 // pointed to by pData.
ReadVT(DWORD dwType,BYTE ** pData)290 DWORD OLEStream::ReadVT(DWORD dwType, BYTE **pData)
291 {
292   // If type is VT_VECTOR, read it
293   if (dwType & VT_VECTOR)
294   {
295     return ReadVT_VECTOR(dwType, (VECTOR **)pData);
296   }
297 
298   // Read the data into pData according to the VT type
299   switch(dwType)
300   {
301     case VT_I1:
302     case VT_UI1:
303       return ReadVT_I2((WORD *)*pData);
304     case VT_I2:
305     case VT_UI2:
306       return ReadVT_I2((WORD *)*pData);
307     case VT_I4:
308     case VT_UI4:
309     case VT_ERROR:
310       return ReadVT_I4((DWORD *)*pData);
311     case VT_R4:
312       return ReadVT_R4((float *)*pData);
313     case VT_R8:
314       return ReadVT_R8((double *)*pData);
315     case VT_CY:
316       return ReadVT_CY((CY *)*pData);
317     case VT_DATE:
318       return ReadVT_DATE((double *)*pData);
319     case VT_BOOL:
320       return ReadVT_BOOL((BOOL *)*pData);
321     case VT_I8:
322     case VT_UI8:
323     case VT_INT:
324     case VT_UINT:
325       return ReadVT_I8((LARGE_INTEGER *)*pData);
326     case VT_LPSTR:
327       return ReadVT_LPSTR((char **)pData);
328     case VT_LPWSTR:
329       return ReadVT_LPWSTR((WCHAR **)pData);
330     case VT_BSTR:
331       return ReadVT_LPWSTR((WCHAR **)pData);
332     case VT_FILETIME:
333       return ReadVT_FILETIME((FILETIME *)*pData);
334     case VT_BLOB:
335       return ReadVT_BLOB((BLOB **)pData);
336     case VT_STREAM:
337       return ReadVT_STREAM((char **)pData);
338     case VT_STORAGE:
339       return ReadVT_STORAGE((char **)pData);
340     case VT_STREAMED_OBJECT:
341       return ReadVT_STREAMED_OBJECT((char **)pData);
342     case VT_STORED_OBJECT:
343       return ReadVT_STORED_OBJECT((char **)pData);
344     case VT_BLOB_OBJECT:
345       return ReadVT_BLOB_OBJECT((char **)pData);
346     case VT_CF:
347       return ReadVT_CF((CLIPDATA **)pData);
348     case VT_CLSID:
349       return ReadVT_CLSID((CLSID **)pData);
350     default:
351       return FALSE;
352   }
353 }
354 
355 // OLEStream::ReadVT()
356 // This is a generic function that takes a property of the given type out of
357 // the given stream (at its current position) and puts it at the location
358 // pointed to by variant.
ReadVT(VARIANT * variant)359 DWORD OLEStream::ReadVT(VARIANT * variant)
360 {
361   // If type is VT_VECTOR, read it
362   if (variant->vt & VT_VECTOR)
363   {
364     return ReadVT_VECTOR(variant->vt, (VECTOR **)&V_BYREF(variant));
365   }
366 
367   // Read the data into variant according to the VT type
368   switch(variant->vt)
369   {
370     case VT_I1:
371     case VT_UI1:
372       return ReadVT_I2((WORD *)&V_I2(variant));
373     case VT_I2:
374     case VT_UI2:
375       return ReadVT_I2((WORD *)&V_I2(variant));
376     case VT_I4:
377     case VT_UI4:
378     case VT_ERROR:
379       return ReadVT_I4((DWORD *)&V_I4(variant));
380     case VT_R4:
381       return ReadVT_R4((float *)&V_R4(variant));
382     case VT_R8:
383       return ReadVT_R8((double *)&V_R8(variant));
384     case VT_CY:
385       return ReadVT_CY((CY *)&V_CY(variant));
386     case VT_DATE:
387       return ReadVT_DATE((double *)&V_DATE(variant));
388     case VT_BOOL:
389       return ReadVT_BOOL((BOOL *)&V_BOOL(variant));
390     case VT_I8:
391     case VT_UI8:
392     case VT_INT:
393     case VT_UINT:
394       return ReadVT_I8((LARGE_INTEGER *)&V_CY(variant));
395     case VT_LPSTR:
396 #ifdef _UNICODE
397       return ReadVT_LPSTR((LPSTR *)&V_UI1REF(variant));
398 #else
399       return ReadVT_LPSTR((char **)&V_BSTR(variant));
400 #endif
401     case VT_LPWSTR:
402       return ReadVT_LPWSTR((WCHAR **)&V_BYREF(variant));
403     case VT_BSTR:
404       return ReadVT_LPWSTR((WCHAR **)&V_BYREF(variant));
405     case VT_FILETIME:
406       return ReadVT_FILETIME((FILETIME *)&V_CY(variant));
407     case VT_BLOB:
408       return ReadVT_BLOB((BLOB **)&V_BYREF(variant));
409     case VT_STREAM:
410       return ReadVT_STREAM((char **)&V_BYREF(variant));
411     case VT_STORAGE:
412       return ReadVT_STORAGE((char **)&V_BYREF(variant));
413     case VT_STREAMED_OBJECT:
414       return ReadVT_STREAMED_OBJECT((char **)&V_BYREF(variant));
415     case VT_STORED_OBJECT:
416       return ReadVT_STORED_OBJECT((char **)&V_BYREF(variant));
417     case VT_BLOB_OBJECT:
418       return ReadVT_BLOB_OBJECT((char **)&V_BYREF(variant));
419     case VT_CF:
420       return ReadVT_CF((CLIPDATA **)&V_BYREF(variant));
421     case VT_CLSID:
422       return ReadVT_CLSID((CLSID **)&V_BYREF(variant));
423     default:
424       return FALSE;
425   }
426 }
427 
428 // ReadVT_I2()
429 // Reads a 2-byte WORD value from a stream. The bytes is swapped
430 // Caution: Since value in the stream is zero-padded to a 32-bit boundary, actual read
431 // data is 4 bytes despite it is a short type.
ReadVT_I2(WORD * pw)432 DWORD OLEStream::ReadVT_I2(WORD *pw)
433 {
434   WORD  wPad;   // Padded short
435 
436   // Read a short type and a padded short
437   if ( !Read(pw, sizeof (*pw)) || !Read(&wPad, sizeof (*pw)))
438     return FALSE;
439 
440   // Swap bytes if flag is set
441 #ifdef  IN_BIG_ENDIAN
442   if ( fSwapBytes )
443     SwapBytes((BYTE *)pw, sizeof(*pw));
444 #endif
445 
446   // Return the total bytes read, which is size of short ( 2 bytes )
447   return sizeof (*pw);
448 }
449 
450 // ReadVT_I2_NoPad()
451 // Reads a 2-byte WORD value without padding to 32-bit from a stream. The bytes is swapped
ReadVT_I2_NoPad(WORD * pw)452 DWORD OLEStream::ReadVT_I2_NoPad(WORD *pw)
453 {
454   // Read a short type and a padded short
455   if ( !Read(pw, sizeof (WORD)) )
456     return FALSE;
457 
458   // Swap bytes if flag is set
459 #ifdef  IN_BIG_ENDIAN
460   if ( fSwapBytes )
461     SwapBytes((BYTE *)pw, sizeof(*pw));
462 #endif
463 
464   // Return the total bytes read, which is size of short ( 2 bytes )
465   return sizeof (*pw);
466 }
467 
468 // ReadVT_I4()
469 // Reads a 4-byte DWORD value from a stream. The bytes is swapped
ReadVT_I4(DWORD * pdw)470 DWORD OLEStream::ReadVT_I4(DWORD *pdw)
471 {
472   if ( !Read(pdw, sizeof (*pdw)))
473     return FALSE;
474 
475   // Swap bytes if flag is set
476 #ifdef  IN_BIG_ENDIAN
477   if ( fSwapBytes )
478     SwapBytes((BYTE *)pdw, sizeof(*pdw));
479 #endif
480 
481   // Return the total bytes read
482   return sizeof (*pdw);
483 }
484 
485 // ReadVT_R4()
486 // Reads a 32-bit IEEE floating point value from a stream. The bytes is swapped
ReadVT_R4(float * pflt)487 DWORD OLEStream::ReadVT_R4(float *pflt)
488 {
489   if ( !Read(pflt, sizeof (float)))
490     return FALSE;
491 
492   // Swap bytes if flag is set
493 #ifdef  IN_BIG_ENDIAN
494   if ( fSwapBytes )
495     SwapBytes((BYTE *)pflt, sizeof(float));
496 #endif
497 
498   // Return the total bytes read, which is size of float ( 4 bytes )
499   return sizeof (float);
500 }
501 
502 // ReadVT_R8()
503 // Reads a 64-bit IEEE floating point value from a stream. The bytes is swapped
ReadVT_R8(double * pdbl)504 DWORD OLEStream::ReadVT_R8(double *pdbl)
505 {
506   if ( !Read(pdbl, sizeof(double)))
507     return FALSE;
508 
509   // Swap bytes if flag is set
510 #ifdef  IN_BIG_ENDIAN
511   if ( fSwapBytes )
512     SwapBytes((BYTE *)pdbl, sizeof(double));
513 #endif
514 
515   // Return the total bytes read, which is size of double ( 8 bytes )
516   return sizeof(double);
517 }
518 
519 // ReadVT_CY()
520 // Reads an 8-byte two's complement integer (scaled by 10,000) from a stream.
521 //  It's usually used for currency amounts (hence the CY type).The bytes is swapped
ReadVT_CY(CY * pcy)522 DWORD OLEStream::ReadVT_CY(CY *pcy)
523 {
524 #ifdef macintosh
525   if ( !ReadVT_I4((DWORD *)&pcy->Hi) || !ReadVT_I4(&pcy->Lo) )
526 #else
527   if ( !ReadVT_I4(&pcy->Lo) || !ReadVT_I4((DWORD *)&pcy->Hi) )
528 #endif
529     return FALSE;
530 
531   // Return the total bytes read, which is size of two DWORDs ( 8 bytes )
532   return sizeof (CY);
533 }
534 
535 // ReadVT_I8()
536 // Reads an 8-byte integer from a stream. The bytes is swapped
ReadVT_I8(LARGE_INTEGER * pli)537 DWORD OLEStream::ReadVT_I8(LARGE_INTEGER *pli)
538 {
539   if ( !ReadVT_I4(&pli->LowPart) || !ReadVT_I4((DWORD *)&pli->HighPart) )
540     return FALSE;
541 
542   // Return the total bytes read, which is size of two DWORDs ( 8 bytes )
543   return sizeof (LARGE_INTEGER);
544 }
545 
546 // ReadVT_BOOL()
547 // Reads a boolean from a stream. The bytes is swapped
548 // An OLE boolean is defined to be a 2-byte WORD containing 0 (FALSE) or
549 // -1 (TRUE). It is padded to a 32-bit boundary. A local boolean is not
550 // guaranteed to be anything, so we read in a dword and cast it as a TRUE
551 // or FALSE BOOL according to its value.
ReadVT_BOOL(BOOL * pf)552 DWORD OLEStream::ReadVT_BOOL(BOOL *pf)
553 {
554   WORD w;
555 
556   // Read the data
557   if (!ReadVT_I2(&w))
558     return FALSE;
559 
560   // Set the boolean value
561   *pf = (w==0)? FALSE: TRUE;
562 
563   // Return the total bytes read, which is size of BOOL ( 2 bytes )
564   return sizeof (BOOL);
565 }
566 
567 // ReadVT_LPSTR()
568 // Reads a character string from a stream. Return total bytes read . The array is
569 // dynamically allocated, and should be deleted after use.
ReadVT_LPSTR(char ** ppsz)570 DWORD OLEStream::ReadVT_LPSTR(char **ppsz)
571 {
572   DWORD dwLength, rem;
573   char *psz;
574 
575   // Read the length count including terminating NULL
576   if (!ReadVT_I4(&dwLength))
577     return FALSE;
578 
579   // If it is null character, return the size of string
580   if ( !dwLength )
581     return sizeof(DWORD);
582 
583   // Limit the size of a string to a reasonnable value
584   if (dwLength > LARGEST_STRING)
585     dwLength = LARGEST_STRING;
586 
587   // Get the remaining bytes to 32-bit for it is going to be padded to 32-bit boundary
588   rem = (dwLength % 4) ? 4 : 0;
589   rem -= dwLength % 4;
590 
591   // Allocate memory
592   psz = new char[dwLength];
593   *ppsz = psz;
594 
595   if (!psz)
596     return FALSE;
597 
598   // Read the string
599   if ( !Read(psz, dwLength * sizeof (char)) )
600     return FALSE;
601 
602   // Set the stream pointer to next 32-bit boundary in order to read next correctly
603   Seek(rem, STREAM_SEEK_CUR);
604 
605   // Return the total bytes read from stream, including bytes count and actual data length
606   return sizeof(DWORD) + dwLength;
607 }
608 
609 // ReadVT_LPSTR_NoPad()
610 // Reads a character string without padding to 32-bit from a stream. Return total bytes read. The array is
611 // dynamically allocated, and should be deleted after use.
ReadVT_LPSTR_NoPad(char ** ppsz)612 DWORD OLEStream::ReadVT_LPSTR_NoPad(char **ppsz)
613 {
614   DWORD dwLength;
615   char *psz;
616 
617   // Read the length count including terminating NULL
618   if (!ReadVT_I4(&dwLength))
619     return FALSE;
620 
621   // If it is null character, return the size of string
622   if ( !dwLength )
623     return sizeof(DWORD);
624 
625   // Limit the size of a string to a reasonnable value
626   if (dwLength > LARGEST_STRING)
627     dwLength = LARGEST_STRING;
628 
629   // Allocate memory
630   psz = new char[dwLength];
631   *ppsz = psz;
632 
633   if (!psz)
634     return FALSE;
635 
636   // Read the string
637   if ( !Read(psz, dwLength * sizeof (char)) )
638     return FALSE;
639 
640   // Return the total bytes read from stream, including bytes count and actual data length
641   return sizeof(DWORD) + dwLength;
642 }
643 
644 // ReadVT_LPWSTR()
645 // Reads a Unicode (16-bit) character string from a stream. Return total bytes read.
646 // The array is dynamically allocated, and should be deleted after use.
ReadVT_LPWSTR(WCHAR ** ppwsz)647 DWORD OLEStream::ReadVT_LPWSTR(WCHAR **ppwsz)
648 {
649   DWORD dwLength, rem;
650   WCHAR *pwsz = NULL;
651 
652   // Read the WCHAR count including terminating NULL
653   if (!ReadVT_I4(&dwLength))
654     return FALSE;
655 
656   // If it is null character, return the size of string
657   if ( !dwLength )
658     return sizeof(DWORD);
659 
660   // Limit the size of a string to a reasonnable value
661   if (dwLength > LARGEST_STRING)
662     dwLength = LARGEST_STRING;
663 
664   // Get the remaining bytes to 32-bit for it is going to be padded to 32-bit boundary
665   rem = ((dwLength * 2) % 4) ? 4 : 0;
666   rem -= (dwLength * 2) % 4;
667 
668   // Allocate memory
669   pwsz = new WCHAR[dwLength];
670   *ppwsz = pwsz;
671 
672   if (!pwsz)
673     return FALSE;
674 
675   // Read the wide char. Here we don't use ReadVT_I2 since unicode is not padded to 32-bit
676   for ( DWORD i = 0; i < dwLength; i++ )  {
677     if ( !ReadVT_I2_NoPad(&pwsz[i]) )
678       return FALSE;
679   }
680 
681   // Set the stream pointer to next 32-bit boundary in order to read next correctly
682   Seek(rem, STREAM_SEEK_CUR);
683 
684   // Return the total bytes read from stream, including WCHAR count and actual data
685   return sizeof (DWORD) + (dwLength) * sizeof (WCHAR);
686 }
687 
688 // ReadVT_LPWSTR_NoPad()
689 // Reads a Unicode (16-bit) character string without padding to 32-bit from a stream. Return total bytes read.
690 // The array is dynamically allocated, and should be deleted after use.
ReadVT_LPWSTR_NoPad(WCHAR ** ppwsz)691 DWORD OLEStream::ReadVT_LPWSTR_NoPad(WCHAR **ppwsz)
692 {
693   DWORD dwLength;
694   WCHAR *pwsz = NULL;
695 
696   // Read the WCHAR count including terminating NULL
697   if (!ReadVT_I4(&dwLength))
698     return FALSE;
699 
700   // If it is null character, return the size of string
701   if ( !dwLength )
702     return sizeof(DWORD);
703 
704   // Limit the size of a string to a reasonnable value
705   if (dwLength > LARGEST_STRING)
706     dwLength = LARGEST_STRING;
707 
708   // Allocate memory
709   pwsz = new WCHAR[dwLength];
710   *ppwsz = pwsz;
711 
712   if (!pwsz)
713     return FALSE;
714 
715   // Read the wide char. Here we don't use ReadVT_I2 since unicode is not padded to 32-bit
716   for ( DWORD i = 0; i < dwLength; i++ )  {
717     if ( !ReadVT_I2_NoPad(&pwsz[i]) )
718       return FALSE;
719   }
720 
721   // Return the total bytes read from stream, including WCHAR count and actual data
722   return sizeof (DWORD) + (dwLength) * sizeof (WCHAR);
723 }
724 
725 // ReadVT_FILETIME()
726 // Reads a FILETIME structure from a stream. The bytes is swapped
ReadVT_FILETIME(FILETIME * pft)727 DWORD OLEStream::ReadVT_FILETIME(FILETIME *pft)
728 {
729   // Read the filetime
730   if (!ReadVT_I4(&pft->dwLowDateTime) || !ReadVT_I4(&pft->dwHighDateTime))
731     return FALSE;
732 
733   // Return the total bytes read, which is size of FILETIME ( 16 bytes )
734   return sizeof (FILETIME);
735 }
736 
737 // ReadVT_BLOB()
738 // Reads a BLOB (length + raw block of data) from a stream. The BYTE array
739 // within the BLOB structure is dynamically allocated, so it should be deleted
740 // by the caller after being used.
ReadVT_BLOB(BLOB ** ppBlob)741 DWORD OLEStream::ReadVT_BLOB(BLOB **ppBlob)
742 {
743   DWORD   rem;
744   BLOB *  pblob;
745 
746   pblob = new BLOB;
747   if ( pblob==NULL ) {
748     return FALSE;
749   }
750 
751   // Read the size of the blob
752   if (!ReadVT_I4(&pblob->cbSize))
753     return FALSE;
754 
755   if (pblob->cbSize == 0)
756     return sizeof (DWORD);
757 
758   // Get the remaining bytes to 32-bit for it is going to be padded to 32-bit boundary
759   rem = (pblob->cbSize % 4) ? 4 : 0;
760   rem -= pblob->cbSize % 4;
761 
762   // Allocate the memory
763   pblob->pBlobData = new BYTE[pblob->cbSize];
764   if (!pblob->pBlobData)
765     return FALSE;
766 
767   // Read blob according to its size
768   if ( !Read(pblob->pBlobData, pblob->cbSize))
769     return FALSE;
770 
771   *ppBlob = pblob;
772 
773   // Set the stream pointer to next 32-bit boundary in order to read next correctly
774   Seek(rem, STREAM_SEEK_CUR);
775 
776   // Return the total bytes read, which is blob count (4 bytes) plus
777   // the total length of BLOB
778   return pblob->cbSize + sizeof(DWORD);
779 }
780 
781 // ReadVT_CLSID() with input of CLSID *
782 // Reads a CLSID from a stream (which is really a DWORD, two WORDs, and 8 bytes).
783 // The bytes is swapped
ReadVT_CLSID(CLSID * pclsid)784 DWORD OLEStream::ReadVT_CLSID(CLSID *pclsid)
785 {
786   // Read the first three integers in CLSID
787   // Here we use Read() for short type, not ReadVT_I2(), so bytes are not swapped
788   if (!ReadVT_I4(&pclsid->Data1) || !Read((WORD *)&pclsid->Data2, sizeof(short)) ||
789     !Read((WORD *)&pclsid->Data3, sizeof(short)) )
790     return FALSE;
791 
792   // Swap bytes if flag is set
793 #ifdef  IN_BIG_ENDIAN
794   if ( fSwapBytes ) {
795     SwapBytes((BYTE *)&pclsid->Data2, sizeof(short));
796     SwapBytes((BYTE *)&pclsid->Data3, sizeof(short));
797   }
798 #endif
799 
800   // Read the last 8 bytes in CLSID
801   if ( !Read(pclsid->Data4, 8))
802     return FALSE;
803 
804   // Return the total bytes read, which is size of CLSID ( 16 bytes )
805   return sizeof (CLSID);
806 }
807 
808 // ReadVT_CLSID() with input of CLSID **
809 // Just allocate the handle if none and call the method using a CLSID *
ReadVT_CLSID(CLSID ** ppClsid)810 DWORD OLEStream::ReadVT_CLSID(CLSID **ppClsid)
811 {
812   if (!*ppClsid) {
813     *ppClsid = new CLSID;
814     if (*ppClsid==NULL) {
815       return FALSE;
816     }
817   }
818   return ReadVT_CLSID (*ppClsid);
819 }
820 
821 // ReadVT_VARIANT()
822 // Reads a VARIANT from a stream (which is really four unsigned short, and a double).
823 // The bytes is swapped
ReadVT_VARIANT(VARIANT * pvar)824 DWORD OLEStream::ReadVT_VARIANT(VARIANT *pvar)
825 {
826   // Read a variant structure
827   // Here we use Read() for short type, not ReadVT_I2(), so bytes are not swapped
828   if ( !Read((WORD *)&pvar->vt,       sizeof(short)) ||
829      !Read((WORD *)&pvar->wReserved1, sizeof(short)) ||
830      !Read((WORD *)&pvar->wReserved2, sizeof(short)) ||
831      !Read((WORD *)&pvar->wReserved3, sizeof(short)) ||
832      !Read((double *)&pvar->dblVal,   sizeof(double)) )
833     return FALSE;
834 
835   // Swap bytes if flag is set
836 #ifdef  IN_BIG_ENDIAN
837   if ( fSwapBytes ) {
838     SwapBytes((BYTE *)&pvar->vt,     sizeof(short));
839     SwapBytes((BYTE *)&pvar->wReserved1, sizeof(short));
840     SwapBytes((BYTE *)&pvar->wReserved2, sizeof(short));
841     SwapBytes((BYTE *)&pvar->wReserved3, sizeof(short));
842     SwapBytes((BYTE *)&pvar->dblVal,   sizeof(double));
843   }
844 #endif
845 
846   // Return the total bytes read, which is size of VARIANT ( 16 bytes )
847   return sizeof (VARIANT);
848 }
849 
850 // ReadVT_CF()
851 // Reads a clipboard data structure (length + format + raw block of data)
852 // from a stream. The BYTE array within the CLIPDATA structure is dynamically
853 // allocated, so it should be deleted by the caller after being used.
ReadVT_CF(CLIPDATA ** ppClipData)854 DWORD OLEStream::ReadVT_CF(CLIPDATA **ppClipData)
855 {
856   DWORD     rem;
857   CLIPDATA *  pclipdata;
858 
859   pclipdata = new CLIPDATA;
860   if (pclipdata==NULL)
861     return FALSE;
862 
863   // Read the size and clip format
864   if ( !ReadVT_I4(&pclipdata->cbSize) )
865     return FALSE;
866 
867   if (pclipdata->cbSize == 0)
868     return sizeof (DWORD);
869 
870   // Get the remaining bytes to 32-bit for it is going to be padded to 32-bit boundary
871   rem = (pclipdata->cbSize % 4) ? 4 : 0;
872   rem -= pclipdata->cbSize % 4;
873 
874   // Allocate the memory
875   pclipdata->pClipData = new BYTE[pclipdata->cbSize];
876   if (!pclipdata->pClipData)
877     return FALSE;
878 
879   // Read clipdata according to its size
880   if ( !Read(pclipdata->pClipData, pclipdata->cbSize))
881     return FALSE;
882 
883   *ppClipData = pclipdata;
884 
885   // Set the stream pointer to next 32-bit boundary in order to read correctly
886   Seek(rem, STREAM_SEEK_CUR);
887 
888   // Return the total bytes read, which include clipdata count, clipdata format, and
889   // the total length of CLIPDATA
890   return sizeof(DWORD) + pclipdata->cbSize;
891 }
892 
893 
894 // ReadVT_VECTOR()
895 // Reads a vector data structure (cElements * length of each element), and return total bytes
896 // been read. The vector type is like VT_XX | VT_VECTOR. Right now 11 types are supported
897 // ( char, WORD, DWORD, float, double, LPSTR, LPWSTR, BLOB, CLIPDATA, CLSID, VARIANT).
898 // The vector structure is dynamically allocated, so it should be deleted
899 // by the caller after being used.
ReadVT_VECTOR(DWORD dwType,VECTOR ** ppVector)900 DWORD OLEStream::ReadVT_VECTOR(DWORD dwType, VECTOR **ppVector)
901 {
902   VECTOR *  pvector;
903   DWORD     i, strLen = 0, len = 0;
904   char * pstr;
905 
906   // Erase the VT_VECTOR bit, so remaining is the data type in vector
907   if (dwType & VT_VECTOR)
908     dwType ^= VT_VECTOR;
909 
910   // Read the vector length
911   if ( !ReadVT_I4(&strLen))
912     return FALSE;
913 
914   // If number of vector is 0, return with total length of vector of byte count( 4 bytes )
915   if (strLen == 0)
916     return sizeof(DWORD);
917 
918   // Allocate a vector
919   pvector = AllocVECTOR(dwType, strLen);
920   if ( !pvector )
921     return 0;
922   else
923     *ppVector = pvector;
924 
925   // Read the data according to its type
926   switch (dwType)
927   {
928     case VT_I1:
929     case VT_UI1:
930     {
931       // Read each char in the vector. It is same as string just without byte count at the beginning.
932       for ( i= 0; i < pvector->cElements; i++ )
933         if ( !Read(&pvector->prgb[i], sizeof(char)))
934           return FALSE;
935 
936       // Return the total bytes read, which is vector elements count (4 bytes) plus
937       // the total length of char *.
938       return pvector->cElements * sizeof(char) + sizeof(DWORD);
939     }
940     case VT_I2:
941     case VT_UI2:
942     case VT_BOOL:
943     {
944       // Read each short in the vector. Here we don't use ReadVT_I2 since the short type in
945       // vector is not 32-bit padded.
946       for ( i= 0; i < pvector->cElements; i++ )
947         if ( !ReadVT_I2_NoPad(&pvector->prgw[i]))
948           return FALSE;
949 
950       // Return the total bytes read, which is vector elements count (4 bytes) plus
951       // the total length of boolean.
952       return pvector->cElements * sizeof(short) + sizeof(DWORD);
953     }
954     case VT_I4:
955     case VT_UI4:
956     case VT_ERROR:
957     {
958       // Read each 4-byte element in the vector
959       for ( i= 0; i < pvector->cElements; i++ )
960         if ( !ReadVT_I4(&pvector->prgdw[i]))
961           return FALSE;
962 
963       // Return the total bytes read, which is vector elements count (4 bytes) plus
964       // the total length of elements
965       return pvector->cElements * 4 + sizeof(pvector->cElements);
966     }
967     case VT_R4:
968     {
969       // Read each float in the vector
970       for ( i= 0; i < pvector->cElements; i++ )
971         if ( !ReadVT_R4(&pvector->prgflt[i]))
972           return FALSE;
973 
974       // Return the total bytes read, which is vector elements count (4 bytes) plus
975       // the total length of float
976       return pvector->cElements * 4 + sizeof(pvector->cElements);
977     }
978     case VT_R8:
979     {
980       // Read each double in the vector
981       for ( i= 0; i < pvector->cElements; i++ ) {
982         if ( !ReadVT_R8(&pvector->prgdbl[i]))
983           return FALSE;
984       }
985 
986       // Return the total bytes read, which is vector elements count (4 bytes) plus
987       // the total length of doubles
988       return pvector->cElements * 8 + sizeof(pvector->cElements);
989     }
990     case VT_LPSTR:
991     {
992       memset(pvector->prgpsz, 0, pvector->cElements * sizeof(char *));
993 
994       // Read each string in the vector
995       for ( i= 0; i < pvector->cElements; i++ ) {
996         strLen = ReadVT_LPSTR(&pstr);
997 
998         // Save the string into vector
999         pvector->prgpsz[i] = pstr;
1000 
1001         // Add the total length of strings (bytes counts)
1002         len += strLen;
1003       }
1004 
1005       // Return the total bytes read, which is vector elements count (4 bytes)
1006       // plus total length of strings
1007       return len * sizeof(char) + sizeof(pvector->cElements);
1008     }
1009     case VT_BSTR:
1010     case VT_LPWSTR:
1011     {
1012       DWORD len = 0;
1013       WCHAR * pwstr;
1014 
1015       memset(pvector->prgpwz, 0, pvector->cElements * sizeof(WCHAR *));
1016 
1017       // Read each wide string in the vector
1018       for ( i= 0; i < pvector->cElements; i++ ) {
1019         strLen = ReadVT_LPWSTR(&pwstr);
1020 
1021         // Save the wide string into vector
1022         pvector->prgpwz[i] = pwstr;
1023 
1024         // Add the total length of wide strings (bytes counts)
1025         len += strLen;
1026       }
1027 
1028       // Return the total bytes read, which is vector elements  count (4 bytes) plus
1029       // total length of wide strings
1030       return len * sizeof(char) + sizeof(pvector->cElements);
1031     }
1032     case VT_BLOB:
1033     {
1034       DWORD len = 0;
1035 
1036       // Read each blob in the vector
1037       for ( i= 0; i < pvector->cElements; i++ ) {
1038 
1039         // If read wrong, continue next
1040         if ( !( strLen = ReadVT_BLOB(&pvector->prgblob[i])) )
1041           continue;
1042 
1043         // Add the total length of blobs (bytes counts)
1044         len += strLen;
1045       }
1046 
1047       // Return the total bytes read, which is vector elements count (4 bytes) plus
1048       // total length of blobs
1049       return len * sizeof(char) + sizeof(pvector->cElements);
1050     }
1051     case VT_CF:
1052     {
1053       DWORD len = 0;
1054 
1055       // Read each cf in the vector
1056       for ( i= 0; i < pvector->cElements; i++ ) {
1057 
1058         // If read wrong, continue next
1059         if ( !( strLen = ReadVT_CF(&pvector->pcd[i])) )
1060           continue;
1061 
1062         // Add the total length of cfs (bytes counts)
1063         len += strLen;
1064       }
1065 
1066       // Return the total bytes read, which is vector elements count (4 bytes) plus
1067       // total length of cfs
1068       return len * sizeof(char) + sizeof(pvector->cElements);
1069     }
1070     case VT_CLSID:
1071     {
1072       CLSID *pcls = NULL;
1073 
1074       // Read each clsid in the vector
1075       for ( i= 0; i < pvector->cElements; i++ ) {
1076 
1077         // If read wrong, continue next
1078         if ( !( strLen = ReadVT_CLSID(&pcls)) )
1079           continue;
1080 
1081         // Save the clsid into vector
1082         pvector->pclsid[i] = *pcls;
1083       }
1084 
1085       // Return the total bytes read, which is vector elements count (4 bytes) plus
1086       // total length of clsid
1087       return pvector->cElements * sizeof(CLSID) + sizeof(pvector->cElements);
1088     }
1089     uint32_t tmpType;
1090     case VT_VARIANT:
1091     {
1092       // Reset the memory
1093       memset(pvector->pvar, 0, pvector->cElements * sizeof(VARIANT));
1094 
1095       // Read each element in the vector
1096       for ( i= 0; i < pvector->cElements; i++ ) {
1097 
1098         // Read the variant type first ( unsigned long )
1099         ReadVT_I4(&tmpType);
1100         pvector->pvar[i].vt = tmpType;
1101         //ReadVT_I4((DWORD *)&pvector->pvar[i].vt);
1102         strLen += 4;
1103 
1104         // Read the data into the variant accordingly. The length(bytes counts) is
1105         // returned in strLen. (Before call ReadVT(), variant must be set to zero)
1106         strLen += ReadVT(&pvector->pvar[i]);
1107 
1108       }
1109 
1110       // Return the total length of vector(bytes counts), which is total length fix types
1111       // (number of DWORDs) plus total variable types length (in strLen), plus the vector
1112       // elements count (4 bytes).
1113       return sizeof(pvector->cElements) + strLen;
1114     }
1115     default:
1116       {
1117       // BUG: Any types not listed above are not supported.
1118       //cout << "The type is not supported.";
1119       return FALSE;
1120       }
1121   }
1122 }
1123 
1124 
1125 // FIX_DICT_PROP - added new method: ReadDICT_ENTRIES()
1126 //
1127 // Reads the entries in a dictionary data structure, and return total bytes that
1128 // been read. It assumes that the next thing in the stream is the first of one or
1129 //  more entries. It also assumes that pDict->cEntries has already been allocated
1130 //  with an array of pDict->cEntries elements.
ReadDICT_ENTRIES(DICTIONARY * pDict)1131 DWORD OLEStream::ReadDICT_ENTRIES(DICTIONARY *pDict)
1132 {
1133   ENTRY *   pEntry;
1134   DWORD     i, rem, strLen = 0;
1135 
1136   pEntry = pDict->rgEntry;        // Get ptr to start of array of entries
1137 
1138   for(i=0; i < pDict->cbEntries; i++, pEntry++) {
1139     if( !ReadVT_I4(&pEntry->dwPropID))
1140       return false;
1141 
1142     if( !ReadVT_I4(&pEntry->cb))
1143       return false;
1144 
1145     strLen += (sizeof(DWORD) * 2);    // Increment for the 2 VT_I4 reads
1146 
1147     // The string size read into 'cbName' includes the null terminator.
1148     //  There is no string padding to account for in dictionary strings.
1149     //  Allocate memory for the string and read it in.
1150     pEntry->sz = new char[pEntry->cb];
1151     if( !pEntry->sz )
1152       return false;
1153 
1154     if ( !Read( pEntry->sz, pEntry->cb) )
1155       return false;
1156 
1157     strLen += pEntry->cb;     // Increment for the string read
1158   }
1159 
1160   // Get the remaining bytes required to pad to the next 32-bit boundary
1161   rem = (strLen % 4) ? 4 : 0;
1162   rem -= strLen % 4;
1163 
1164   return( strLen + rem);
1165 }
1166 
1167 
1168 //--------------------------- WriteVT_xx functions ---------------------------------/
1169 
1170 // WriteVT()
1171 // This is a generic function that writes a property of any type in pData to a stream.
WriteVT(DWORD dwType,BYTE * pData)1172 DWORD OLEStream::WriteVT(DWORD dwType, BYTE *pData)
1173 {
1174   // If the data is VECTOR, write it
1175   if (dwType & VT_VECTOR)
1176   {
1177     return WriteVT_VECTOR(dwType, (VECTOR *)pData);
1178   }
1179 
1180   // Write the data according to its type
1181   switch(dwType)
1182   {
1183     case VT_I1:
1184     case VT_UI1:
1185       return WriteVT_I2((WORD *)pData);
1186     case VT_I2:
1187     case VT_UI2:
1188       return WriteVT_I2((WORD *)pData);
1189     case VT_I4:
1190     case VT_UI4:
1191       return WriteVT_I4((DWORD *)pData);
1192     case VT_R4:
1193       return WriteVT_R4((float *)pData);
1194     case VT_R8:
1195       return WriteVT_R8((double *)pData);
1196     case VT_CY:
1197       return WriteVT_CY((CY *)pData);
1198     case VT_DATE:
1199       return WriteVT_DATE((double *)pData);
1200     case VT_BOOL:
1201       return WriteVT_BOOL((BOOL *)pData);
1202     case VT_I8:
1203     case VT_UI8:
1204     case VT_INT:
1205     case VT_UINT:
1206       return WriteVT_I8((LARGE_INTEGER *)pData);
1207     case VT_LPSTR:
1208       return WriteVT_LPSTR(*(char **)pData);
1209     case VT_LPWSTR:
1210       return WriteVT_LPWSTR(*(WCHAR **)pData);
1211     case VT_BSTR:
1212       return WriteVT_LPWSTR(*(WCHAR **)pData);
1213     case VT_FILETIME:
1214       return WriteVT_FILETIME((FILETIME *)pData);
1215     case VT_BLOB:
1216       return WriteVT_BLOB((BLOB *)pData);
1217     case VT_STREAM:
1218       return WriteVT_STREAM(*(char **)pData);
1219     case VT_STORAGE:
1220       return WriteVT_STORAGE(*(char **)pData);
1221     case VT_STREAMED_OBJECT:
1222       return WriteVT_STREAMED_OBJECT(*(char **)pData);
1223     case VT_STORED_OBJECT:
1224       return WriteVT_STORED_OBJECT(*(char **)pData);
1225     case VT_BLOB_OBJECT:
1226       return WriteVT_BLOB_OBJECT(*(char **)pData);
1227     case VT_CF:
1228       return WriteVT_CF((CLIPDATA *)pData);
1229     case VT_CLSID:
1230       return WriteVT_CLSID((CLSID *)pData);
1231     default:
1232       return FALSE;
1233   }
1234 }
1235 
1236 // WriteVT()
1237 // This is a generic function that writes a property of any type to a stream.
WriteVT(VARIANT * variant)1238 DWORD OLEStream::WriteVT(VARIANT * variant)
1239 {
1240   // If the data is VECTOR, write it
1241   if (variant->vt & VT_VECTOR)
1242   {
1243     return WriteVT_VECTOR(variant->vt, (VECTOR *)V_BYREF(variant));
1244   }
1245 
1246   // Write the data according to its type
1247   switch(variant->vt)
1248   {
1249     case VT_I1:
1250     case VT_UI1:
1251       return WriteVT_I2((WORD *)&V_I2(variant));
1252     case VT_I2:
1253     case VT_UI2:
1254       return WriteVT_I2((WORD *)&V_I2(variant));
1255     case VT_I4:
1256     case VT_UI4:
1257       return WriteVT_I4((DWORD *)&V_I4(variant));
1258     case VT_R4:
1259       return WriteVT_R4(&V_R4(variant));
1260     case VT_R8:
1261       return WriteVT_R8(&V_R8(variant));
1262     case VT_CY:
1263       return WriteVT_CY((CY *)&V_CY(variant));
1264     case VT_DATE:
1265       return WriteVT_DATE(&V_R8(variant));
1266     case VT_BOOL:
1267       return WriteVT_BOOL((BOOL *)&V_BOOL(variant));
1268     case VT_I8:
1269     case VT_UI8:
1270     case VT_INT:
1271     case VT_UINT:
1272       return WriteVT_I8((LARGE_INTEGER *)&V_CY(variant));
1273     case VT_LPSTR:
1274 #ifdef _UNICODE
1275       return WriteVT_LPSTR((LPSTR)V_UI1REF(variant));
1276 #else
1277       return WriteVT_LPSTR(V_BSTR(variant));
1278 #endif
1279     case VT_LPWSTR:
1280       return WriteVT_LPWSTR((WCHAR *)V_BYREF(variant));
1281     case VT_BSTR:
1282       return WriteVT_LPWSTR((WCHAR *)V_BYREF(variant));
1283     case VT_FILETIME:
1284       return WriteVT_FILETIME((FILETIME *)&V_R8(variant));
1285     case VT_BLOB:
1286       return WriteVT_BLOB((BLOB *)V_BYREF(variant));
1287     case VT_STREAM:
1288       return WriteVT_STREAM((char *)V_BYREF(variant));
1289     case VT_STORAGE:
1290       return WriteVT_STORAGE((char *)V_BYREF(variant));
1291     case VT_STREAMED_OBJECT:
1292       return WriteVT_STREAMED_OBJECT((char *)V_BYREF(variant));
1293     case VT_STORED_OBJECT:
1294       return WriteVT_STORED_OBJECT((char *)V_BYREF(variant));
1295     case VT_BLOB_OBJECT:
1296       return WriteVT_BLOB_OBJECT((char *)V_BYREF(variant));
1297     case VT_CF:
1298       return WriteVT_CF((CLIPDATA *)V_BYREF(variant));
1299     case VT_CLSID:
1300       return WriteVT_CLSID((CLSID *)V_BYREF(variant));
1301     default:
1302       return FALSE;
1303   }
1304 }
1305 
1306 // WriteVT_I2()
1307 // Write a 2-byte WORD value to a stream. The bytes are swapped.
1308 // Caution: Since the value in the stream is zero-padded to a 32-bit boundary, the actual data
1309 // write to the stream is 4 bytes despite it is a short type.
WriteVT_I2(WORD * pw)1310 DWORD OLEStream::WriteVT_I2(WORD* pw)
1311 {
1312   WORD w, wPad = 0;
1313 
1314   w = *pw;
1315 
1316   // Swap bytes if flag is set
1317   #ifdef  IN_BIG_ENDIAN
1318   if ( fSwapBytes )
1319     SwapBytes((BYTE *)&w, sizeof(short));
1320   #endif
1321 
1322   // Write the data with padded bytes
1323   if ( !Write(&w, sizeof(WORD)) || !Write(&wPad, sizeof(WORD)))
1324     return FALSE;
1325 
1326   // Return the total bytes write, which is size of long ( 4 bytes )
1327   // Although the it is short type, the data is padded to a 32-bit
1328   // boundary so the actual data write to stream is 4 bytes.
1329   return sizeof (DWORD);
1330 }
1331 
1332 // WriteVT_I2_NoPad()
1333 // Write a 2-byte WORD value to a stream without padded to 32-bit boundary, so the actual data
1334 // write to the stream is 2 bytes. The bytes are swapped.
WriteVT_I2_NoPad(WORD * pw)1335 DWORD OLEStream::WriteVT_I2_NoPad(WORD* pw)
1336 {
1337   WORD w;
1338 
1339   w = *pw;
1340 
1341   // Swap bytes if flag is set
1342   #ifdef  IN_BIG_ENDIAN
1343   if ( fSwapBytes )
1344     SwapBytes((BYTE *)&w, sizeof(short));
1345   #endif
1346 
1347   // Write the data without padded bytes
1348   if ( !Write(&w, sizeof(WORD)) )
1349     return FALSE;
1350 
1351   // Return the total bytes write, which is size of short ( 2 bytes )
1352   return sizeof (WORD);
1353 }
1354 
1355 // WriteVT_I4()
1356 // Write a 4-byte DWORD value to a stream. The bytes are swapped.
WriteVT_I4(DWORD * pdw)1357 DWORD OLEStream::WriteVT_I4(DWORD* pdw)
1358 {
1359   DWORD dw;
1360 
1361   dw = *pdw;
1362 
1363   // Swap bytes if flag is set
1364   #ifdef  IN_BIG_ENDIAN
1365   if ( fSwapBytes )
1366     SwapBytes((BYTE *)&dw, sizeof(*pdw));
1367   #endif
1368 
1369   // Write the data
1370   if ( !Write(&dw, sizeof (DWORD)))
1371     return FALSE;
1372 
1373   // Return the total bytes write, which is size of long ( 4 bytes )
1374   return sizeof (DWORD);
1375 }
1376 
1377 // WriteVT_R4()
1378 // Write a 32-bit IEEE floating point value to a stream. The bytes are swapped
WriteVT_R4(float * pflt)1379 DWORD OLEStream::WriteVT_R4(float* pflt)
1380 {
1381   float flt;
1382 
1383   flt = *pflt;
1384 
1385   // Swap bytes if flag is set
1386   #ifdef  IN_BIG_ENDIAN
1387   if ( fSwapBytes )
1388     SwapBytes((BYTE *)&flt, sizeof(float));
1389   #endif
1390 
1391   // Write the data
1392   if ( !Write(&flt, sizeof (float)))
1393     return FALSE;
1394 
1395   // Return the total bytes write, which is size of float ( 4 bytes )
1396   return sizeof (float);
1397 }
1398 
1399 // WriteVT_R8()
1400 // Write a 64-bit IEEE floating point value to a stream. The bytes are swapped
WriteVT_R8(double * pdbl)1401 DWORD OLEStream::WriteVT_R8(double* pdbl)
1402 {
1403   double dbl;
1404 
1405   dbl = *pdbl;
1406 
1407   // Swap bytes if flag is set
1408   #ifdef  IN_BIG_ENDIAN
1409   if ( fSwapBytes )
1410     SwapBytes((BYTE *)&dbl, sizeof(double));
1411   #endif
1412 
1413   // Write the data
1414   if ( !Write(&dbl, sizeof (double)))
1415     return FALSE;
1416 
1417   // Return the total bytes write, which is size of double ( 8 bytes )
1418   return sizeof (double);
1419 }
1420 
1421 // WriteVT_CY()
1422 // Write a 8-byte two's complement integer (scaled by 10,000) to a stream.
1423 // It's usually used for currency amounts (hence the CY type). The bytes are swapped
WriteVT_CY(CY * pcy)1424 DWORD OLEStream::WriteVT_CY(CY *pcy)
1425 {
1426 #ifdef macintosh
1427   if ( !WriteVT_I4((DWORD *)&pcy->Hi) || !WriteVT_I4(&pcy->Lo) )
1428 #else
1429   if ( !WriteVT_I4(&pcy->Lo) || !WriteVT_I4((DWORD *)&pcy->Hi) )
1430 #endif
1431     return FALSE;
1432 
1433   // Return the total bytes write, which is size of two DWORDs ( 8 bytes )
1434   return sizeof (CY);
1435 }
1436 
1437 // WriteVT_I8()
1438 // Write a 8-byte integer to a stream. The bytes are swapped
WriteVT_I8(LARGE_INTEGER * pli)1439 DWORD OLEStream::WriteVT_I8(LARGE_INTEGER *pli)
1440 {
1441   if ( !WriteVT_I4(&pli->LowPart) || !WriteVT_I4((DWORD *)&pli->HighPart) )
1442     return FALSE;
1443 
1444   // Return the total bytes write, which is size of two DWORDs ( 8 bytes )
1445   return sizeof(LARGE_INTEGER);
1446 }
1447 
1448 // WriteVT_BOOL()
1449 // Write a boolean to a stream. The bytes are swapped. An OLE boolean is defined to
1450 // be a 2-byte WORD containing 0 (FALSE) or -1 (TRUE). It is padded to a 32-bit boundary.
WriteVT_BOOL(BOOL * pf)1451 DWORD OLEStream::WriteVT_BOOL(BOOL* pf)
1452 {
1453   DWORD dw; // Intermediate dword because bools are padded to 32 bits
1454 
1455   // Set the OLE boolean, 0 (FALSE) or -1 (TRUE)
1456   dw = *pf ? -1 : 0;
1457 
1458   if (!WriteVT_I4(&dw))
1459     return FALSE;
1460 
1461   // Although the BOOL is short type, the OLE boolean is padded to a 32-bit
1462   // boundary so the actual data write to stream is 4 bytes.
1463   return sizeof (DWORD);
1464 }
1465 
1466 // WriteVT_LPSTR()
1467 // Writes a zero-terminated character string padded to 32-bit boundary to a stream.
WriteVT_LPSTR(char * psz)1468 DWORD OLEStream::WriteVT_LPSTR(char *psz)
1469 {
1470   DWORD dwLength, rem;
1471 
1472   dwLength = strlen(psz);
1473 
1474   if ( dwLength == 0 ) {
1475     // Write the count of string
1476     WriteVT_I4(&dwLength);
1477     return sizeof(DWORD);
1478   }
1479   else
1480     dwLength++; // Count includes terminating zero if it is not null
1481 
1482   // Write the count of string
1483   if (!WriteVT_I4(&dwLength))
1484     return FALSE;
1485 
1486   // Write the string to the stream
1487   if ( !Write(psz, dwLength * sizeof (char)) )
1488     return FALSE;
1489 
1490   // Get the remaining bytes to 32-bit for it is going to be padded to 32-bit boundary
1491   rem = (dwLength % 4) ? 4 : 0;
1492   rem -= dwLength % 4;
1493 
1494   // Set the stream pointer to next 32-bit boundary
1495   Seek(rem, STREAM_SEEK_CUR);
1496 
1497   // Return the total bytes write to stream, including bytes count, actual data length and
1498   // padded bytes
1499   return sizeof(DWORD) + rem + dwLength;
1500 }
1501 
1502 // WriteVT_LPSTR_NoPad()
1503 // Writes a zero-terminated character string without padded to 32-bit boundary to a stream.
WriteVT_LPSTR_NoPad(const char * psz)1504 DWORD OLEStream::WriteVT_LPSTR_NoPad(const char *psz)
1505 {
1506   DWORD dwLength;
1507 
1508   dwLength = strlen(psz);
1509 
1510   if ( dwLength == 0 ) {
1511     // Write the count of string
1512     WriteVT_I4(&dwLength);
1513     return sizeof(DWORD);
1514   }
1515   else
1516     dwLength++; // Count includes terminating zero if it is not null
1517 
1518   // Write the count of string
1519   if (!WriteVT_I4(&dwLength))
1520     return FALSE;
1521 
1522   // Write the string to the stream
1523   if ( !Write(psz, dwLength * sizeof (char)) )
1524     return FALSE;
1525 
1526   // Return the total bytes write to stream, including bytes count, actual data length and
1527   // padded bytes
1528   return sizeof(DWORD) + dwLength;
1529 }
1530 
1531 // WriteVT_LPWSTR()
1532 // Writes a zero-terminated wide character string padded to 32-bit boundary to a stream.
1533 // Return total bytes write to stream in bytes ( not in WCHAR )
WriteVT_LPWSTR(WCHAR * pwsz)1534 DWORD OLEStream::WriteVT_LPWSTR(WCHAR *pwsz)
1535 {
1536   DWORD dwLength, rem = 0, wcount;
1537 
1538   wcount = wcslen(pwsz);  // Get wide char count doesn't include terminating zero
1539 
1540   if ( wcount == 0 ) {
1541     // CHG_MT_EXT_STR - since wide strings are null-terminated, and the terminiator is
1542     //  included in the count, an empty string containing a null and a length of 1
1543     //  is written
1544     wcount = 1;
1545     WriteVT_I4(&wcount);    // Write length = 1
1546     wcount = 0;
1547     WriteVT_I4(&wcount);    // Write null terminator
1548     return(sizeof(DWORD) *2);
1549   }
1550   else
1551     wcount++; // Count includes terminating zero if it is not null
1552 
1553   dwLength = sizeof (WCHAR) * wcount;   // Get the bytes count including terminating NULL
1554 
1555   // Get the remaining bytes to 32-bit for it is going to be padded to 32-bit boundary
1556   rem = (dwLength % 4) ? 4 : 0;
1557   rem -= dwLength % 4;
1558 
1559   // Write the WCHAR count
1560   if (!WriteVT_I4(&wcount))
1561     return FALSE;
1562 
1563   // Write the wide char string to the stream
1564   for ( DWORD i = 0; i < wcount; i++ )  {
1565 
1566     // Write the wide char
1567     if ( !WriteVT_I2_NoPad(&pwsz[i]))
1568       return FALSE;
1569   }
1570 
1571   // Set the stream pointer to next 32-bit boundary
1572   Seek(rem, STREAM_SEEK_CUR);
1573 
1574   // Return the total bytes write to stream, including WCHAR count, actual data length and
1575   // padded bytes
1576   return sizeof (DWORD) + (dwLength + rem) * sizeof (char);
1577 }
1578 
1579 // WriteVT_LPWSTR_NoPad()
1580 // Writes a zero-terminated wide character string without padded to 32-bit boundary to a stream.
1581 // Return total bytes write to stream in bytes ( not in WCHAR )
WriteVT_LPWSTR_NoPad(WCHAR * pwsz)1582 DWORD OLEStream::WriteVT_LPWSTR_NoPad(WCHAR *pwsz)
1583 {
1584   DWORD dwLength, wcount;
1585 
1586   dwLength = wcslen(pwsz);  // Get wide char count doesn't include terminating zero
1587 
1588   if ( dwLength == 0 ) {
1589     // Write the count of wide string
1590     WriteVT_I4(&dwLength);
1591     return sizeof(DWORD);
1592   }
1593   else
1594     dwLength++; // Count includes terminating zero if it is not null
1595 
1596    wcount = sizeof (WCHAR) * dwLength;
1597   // Write the WCHAR count
1598   if (!WriteVT_I4(&wcount))
1599     return FALSE;
1600 
1601   // Write the wide char string to the stream
1602   for ( DWORD i = 0; i < dwLength; i++ )  {
1603 
1604     // Write the wide char
1605     if ( !WriteVT_I2_NoPad(&pwsz[i]))
1606       return FALSE;
1607   }
1608 
1609   // Return the total bytes write to stream, including WCHAR count, actual data length and
1610   // padded bytes
1611   return sizeof (DWORD) + (dwLength) * sizeof (WCHAR);
1612 }
1613 
1614 // WriteVT_FILETIME()
1615 // Writes a FILETIME structure to a stream. The bytes is swapped
WriteVT_FILETIME(FILETIME * pft)1616 DWORD OLEStream::WriteVT_FILETIME(FILETIME *pft)
1617 {
1618   if (!WriteVT_I4(&pft->dwLowDateTime) || !WriteVT_I4(&pft->dwHighDateTime))
1619     return FALSE;
1620 
1621   // Return the total bytes write, which is size of two DWORDs ( 8 bytes )
1622   return sizeof (FILETIME);
1623 }
1624 
1625 // OLEStream::WriteVT_BLOB()
1626 // Writes a BLOB (length + raw block of data) to a stream. The bytes is swapped
WriteVT_BLOB(BLOB * pblob)1627 DWORD OLEStream::WriteVT_BLOB(BLOB *pblob)
1628 {
1629   WORD rem = 0;
1630 
1631   // Write the blob count
1632   if (!WriteVT_I4(&pblob->cbSize))
1633     return FALSE;
1634 
1635   // Get the remaining bytes to 32-bit for it is going to be padded to 32-bit boundary
1636   rem = (pblob->cbSize % 4) ? 4 : 0;
1637   rem -= (unsigned short) (pblob->cbSize % 4);
1638 
1639   // Write the blob according to its size
1640   if ( !Write(pblob->pBlobData, pblob->cbSize) )
1641     return FALSE;
1642 
1643   // Set the stream pointer to next 32-bit boundary
1644   Seek(rem, STREAM_SEEK_CUR);
1645 
1646   // Return the total bytes write to stream, including blob count, actual data length and
1647   // padded bytes
1648   return sizeof (DWORD) + pblob->cbSize + rem;
1649 }
1650 
1651 // WriteVT_VARIANT()
1652 // Writes a VARIANT into a stream (which is really four WORDs, and a double). The bytes is swapped
WriteVT_VARIANT(VARIANT * pvar)1653 DWORD OLEStream::WriteVT_VARIANT(VARIANT *pvar)
1654 {
1655   VARIANT var;
1656 
1657   var = *pvar;
1658 
1659   // Swap bytes if flag is set
1660 #ifdef  IN_BIG_ENDIAN
1661   if ( fSwapBytes ) {
1662     SwapBytes((BYTE *)&var.vt,      sizeof(short));
1663     SwapBytes((BYTE *)&var.wReserved1,  sizeof(short));
1664     SwapBytes((BYTE *)&var.wReserved2,  sizeof(short));
1665     SwapBytes((BYTE *)&var.wReserved3,  sizeof(short));
1666     SwapBytes((BYTE *)&var.dblVal,    sizeof(double));
1667   }
1668 #endif
1669 
1670   if ( !Write((WORD *)&var.vt,     sizeof(short)) ||
1671      !Write((WORD *)&var.wReserved1, sizeof(short)) ||
1672      !Write((WORD *)&var.wReserved2, sizeof(short)) ||
1673      !Write((WORD *)&var.wReserved3, sizeof(short)) ||
1674      !Write((double *)&var.dblVal,   sizeof(double)) )
1675     return FALSE;
1676 
1677   // Return the total bytes write, which is size of VARIANT ( 16 bytes )
1678   return sizeof (VARIANT);
1679 }
1680 
1681 // OLEStream::WriteVT_CF()
1682 // Writes a clipboard data structure (length + format + raw block of data)
1683 // to a stream.
WriteVT_CF(CLIPDATA * pclipdata)1684 DWORD OLEStream::WriteVT_CF(CLIPDATA *pclipdata)
1685 {
1686   WORD rem;
1687 
1688   // Write the clipdata count and format
1689   if ( !WriteVT_I4(&pclipdata->cbSize) )
1690     return FALSE;
1691 
1692   // Get the remaining bytes to 32-bit for it is going to be padded to 32-bit boundary
1693   rem = (pclipdata->cbSize % 4) ? 4 : 0;
1694   rem -= (unsigned short) (pclipdata->cbSize % 4);
1695 
1696   // Write the clipdata according to its size
1697   if ( !Write(pclipdata->pClipData, pclipdata->cbSize))
1698     return FALSE;
1699 
1700   // Set the stream pointer to next 32-bit boundary
1701   Seek(rem, STREAM_SEEK_CUR);
1702 
1703   // Return the total bytes write to stream, including clipdata count and format, actual data
1704   // length and padded bytes
1705   return sizeof (DWORD) + pclipdata->cbSize + rem;
1706 }
1707 
1708 // OLEStream::WriteVT_CLSID()
1709 // Writes a CLSID to a stream (which is really a DWORD, two WORDs, and 8 bytes).
WriteVT_CLSID(CLSID * pclsid)1710 DWORD OLEStream::WriteVT_CLSID(CLSID *pclsid)
1711 {
1712   CLSID cls;
1713 
1714   cls = *pclsid;
1715 
1716   // Swap bytes if flag is set
1717 #ifdef  IN_BIG_ENDIAN
1718   if ( fSwapBytes ) {
1719     SwapBytes((BYTE *)&cls.Data2, sizeof(short));
1720     SwapBytes((BYTE *)&cls.Data3, sizeof(short));
1721   }
1722 #endif
1723 
1724   if (!WriteVT_I4(&cls.Data1) || !Write((WORD *)&cls.Data2, sizeof(short)) ||
1725     !Write((WORD *)&cls.Data3, sizeof(short)))
1726     return FALSE;
1727 
1728   if ( !Write(cls.Data4, 8*sizeof(char)))
1729     return FALSE;
1730 
1731   // Return the total bytes write, which is size of CLSID ( 16 bytes )
1732   return sizeof (CLSID);
1733 }
1734 
1735 // WriteVT_VECTOR()
1736 // Writes a vector data structure (cElements * length of each element). The total bytes
1737 // written to the disk must be padded to 32-bit and returned. The vector type is like
1738 // VT_XX | VT_VECTOR. Right now 11 types are supported (char, WORD, DWORD, float, double,
1739 // LPSTR, LPWSTR, BLOB, CLIPDATA, CLSID, VARIANT).
WriteVT_VECTOR(DWORD dwType,VECTOR * pvector)1740 DWORD OLEStream::WriteVT_VECTOR(DWORD dwType, VECTOR *pvector)
1741 {
1742   DWORD   i, rem;
1743   DWORD strLen = 0;
1744 
1745 
1746   // Erase the VT_VECTOR bit, so remaining is the data type in vector
1747   if (dwType & VT_VECTOR)
1748     dwType ^= VT_VECTOR;
1749 
1750   // If vector pointer is NULL, return FALSE
1751   //if ( !pvector)  return FALSE;
1752   if ( !pvector)
1753   {
1754     strLen = 0;
1755     if(!WriteVT_I4(&strLen))
1756       return FALSE;
1757     return sizeof(DWORD);
1758   }
1759   // Write the count of vector elements. Return FALSE if wrong
1760   if ( !WriteVT_I4(&pvector->cElements))
1761     return FALSE;
1762 
1763   // If nothing in the vector, return size of vector count
1764   if ( pvector->cElements == 0 )
1765     return sizeof(DWORD);
1766 
1767   // Write the data and according to its type
1768   switch (dwType)
1769   {
1770     case VT_I1:
1771     case VT_UI1:
1772       // Get the remaining bytes to 32-bit for it is going to be padded to 32-bit boundary
1773       rem = (pvector->cElements % 4) ? 4 : 0;
1774       rem -= pvector->cElements % 4;
1775 
1776       // Write each char in the vector. It is same as string just without byte count.
1777       // PTCH_DCG - Pass 'prgb' to Write, not '&prgb', since it's an array
1778       if ( !Write( pvector->prgb, pvector->cElements * sizeof(char)) )
1779         return FALSE;
1780 
1781       // Set the stream pointer to next 32-bit boundary
1782       Seek(rem, STREAM_SEEK_CUR);
1783 
1784       // Return the total bytes write to stream, including vector count, actual data length
1785       // and padded bytes
1786       return (pvector->cElements + rem) * sizeof(char) + sizeof(DWORD);
1787     case VT_I2:
1788     case VT_UI2:
1789     case VT_BOOL:
1790       // Get the remaining bytes to 32-bit for it is going to be padded to 32-bit boundary
1791       rem = pvector->cElements % 2;
1792 
1793       for ( i= 0; i < pvector->cElements; i++ ) {
1794         // Write each short in the vector. Here we  use WriteVT_I2_NoPad since the short
1795         // type in vector is not 32-bit padded.
1796         if ( !WriteVT_I2_NoPad(&pvector->prgw[i]) )
1797           return FALSE;
1798       }
1799 
1800       // Set the stream pointer to next 32-bit boundary
1801       Seek(rem * sizeof(short), STREAM_SEEK_CUR);
1802 
1803       // Return the total bytes write to stream, including vector count, actual data length
1804       // and padded bytes
1805       return (pvector->cElements + rem) * sizeof(short) + sizeof(DWORD);
1806     case VT_I4:
1807     case VT_UI4:
1808     case VT_ERROR:
1809       // Write each long in the vector to the stream
1810       for ( i= 0; i < pvector->cElements; i++ ) {
1811         if ( !WriteVT_I4(&pvector->prgdw[i]))
1812           return FALSE;
1813       }
1814 
1815       // Return the total bytes write to stream, which is vector elements count (4 bytes) plus
1816       // the total length of longs
1817       return pvector->cElements * sizeof(DWORD) + sizeof(DWORD);
1818     case VT_R4:
1819       // Write each float in the vector to the stream
1820       for ( i= 0; i < pvector->cElements; i++ ) {
1821         if ( !WriteVT_R4(&pvector->prgflt[i]))
1822           return FALSE;
1823       }
1824 
1825       // Return the total bytes write to stream, which is vector elements count (4 bytes) plus
1826       // the total length of floats
1827       return pvector->cElements * sizeof(float) + sizeof(DWORD);
1828     case VT_R8:
1829       // Write each double in the vector to the stream
1830       for ( i= 0; i < pvector->cElements; i++ ) {
1831         if ( !WriteVT_R8(&pvector->prgdbl[i]))
1832           return FALSE;
1833       }
1834 
1835       // Return the total bytes write to stream, which is vector elements count (4 bytes) plus
1836       // the total length of doubles
1837       return pvector->cElements * sizeof(double) + sizeof(DWORD);
1838     case VT_LPSTR:
1839     {
1840       DWORD len = 0;
1841 
1842       // Write each LPSTR in the vector to the stream, the length is returned in strLen
1843       for ( i= 0; i < pvector->cElements; i++ ) {
1844         if ( !( strLen = WriteVT_LPSTR(pvector->prgpsz[i])) )
1845           return FALSE;
1846         len += strLen;
1847       }
1848 
1849       // Return the total bytes write to stream, which is vector elements count (4 bytes) plus
1850       // the total length of strings
1851       return len * sizeof(char) + sizeof(DWORD);
1852     }
1853     case VT_BSTR:
1854     case VT_LPWSTR:
1855     {
1856       DWORD len = 0;
1857 
1858       // Write each LPWSTR in the vector to the stream, the length in byte is returned in strLen
1859       for ( i= 0; i < pvector->cElements; i++ ) {
1860         if ( !( strLen = WriteVT_LPWSTR(pvector->prgpwz[i])) )
1861           return FALSE;
1862         len += strLen;
1863       }
1864 
1865       // Return the total bytes write to stream, which is vector elements count (4 bytes) plus
1866       // the total length of wide strings
1867       return len * sizeof(char) + sizeof(DWORD);
1868     }
1869     case VT_BLOB:
1870     {
1871       DWORD len = 0;
1872 
1873       // Write each blob in the vector to the stream, the length in byte is returned in strLen
1874       for ( i= 0; i < pvector->cElements; i++ ) {
1875         if ( !( strLen = WriteVT_BLOB(pvector->prgblob[i])) )
1876           return FALSE;
1877         len += strLen;
1878       }
1879 
1880       // Return the total bytes write to stream, which is vector elements count (4 bytes) plus
1881       // the total length of blobs
1882       return len * sizeof(char) + sizeof(DWORD);
1883     }
1884     case VT_CF:
1885     {
1886       DWORD len = 0;
1887 
1888       // Write each cilpdata in the vector to the stream, the length in byte is returned in strLen
1889       for ( i= 0; i < pvector->cElements; i++ ) {
1890         if ( !( strLen = WriteVT_CF(pvector->pcd[i])) )
1891           return FALSE;
1892         len += strLen;
1893       }
1894 
1895       // Return the total bytes write to stream, which is vector elements count (4 bytes) plus
1896       // the total length of clipdatas
1897       return len * sizeof(char) + sizeof(DWORD);
1898     }
1899     case VT_CLSID:
1900     {
1901       // Write each CLSID in the vector to the stream, the length in byte is returned in strLen
1902       for ( i= 0; i < pvector->cElements; i++ ) {
1903         if ( !( strLen = WriteVT_CLSID((CLSID *)&pvector->pclsid[i])) )
1904           return FALSE;
1905       }
1906 
1907       // Return the total bytes write to stream, which is vector elements count (4 bytes) plus
1908       // the total length of CLSIDs
1909       return pvector->cElements * sizeof(CLSID) + sizeof(DWORD);
1910     }
1911     uint32_t tmpVal;
1912     case VT_VARIANT:
1913     {
1914       for ( i= 0; i < pvector->cElements; i++ ) {
1915 
1916         // Write a variant type first ( unsigned long)
1917         tmpVal = pvector->pvar[i].vt;
1918         //WriteVT_I4((DWORD *)&pvector->pvar[i].vt);
1919         WriteVT_I4(&tmpVal);
1920         strLen += 4;
1921 
1922         // Write the variant accordingly. The total bytes write to the stream is returned
1923         // in strLen.
1924         strLen += WriteVT(&pvector->pvar[i]);
1925 
1926       }
1927 
1928       // Return the total length of vector(bytes counts), which is the vector elements count
1929       // (4 bytes) plus the total length of vector elements
1930       return sizeof(pvector->cElements) + strLen;
1931     }
1932     default:
1933     {
1934       // BUG: Any types not listed above are not supported.
1935       //cout << "The type is not supported.";
1936       return FALSE;
1937     }
1938   }
1939 }
1940 
1941 
1942 // FIX_DICT_PROP - added new method: ReadDICT_ENTRIES()
1943 //
1944 // Writes the entries in a dictionary data structure, and returns total bytes that
1945 // written. It assumes that the last thing written to the stream was the count of
1946 //  the number of entries.
WriteDICT_ENTRIES(DICTIONARY * pDict)1947 DWORD OLEStream::WriteDICT_ENTRIES(DICTIONARY *pDict)
1948 {
1949   ENTRY *   pEntry;
1950   DWORD     i, rem, dwLength = 0;
1951 
1952   pEntry = pDict->rgEntry;        // Get ptr to start of array of entries
1953 
1954   for(i=0; i < pDict->cbEntries; i++, pEntry++) {
1955     if( !WriteVT_I4(&pEntry->dwPropID))
1956       return false;
1957 
1958     if( !WriteVT_I4(&pEntry->cb))
1959       return false;
1960 
1961     dwLength += (sizeof(DWORD) * 2);  // Increment for the 2 VT_I4 writes
1962 
1963     // Write the string to the stream
1964     if ( !Write(pEntry->sz, pEntry->cb) )
1965       return false;
1966     dwLength += pEntry->cb;     // Increment for the string written
1967   }
1968 
1969   // Get the remaining bytes required to pad to the next 32-bit boundary
1970   rem = (dwLength % 4) ? 4 : 0;
1971   rem -= dwLength % 4;
1972 
1973   return( dwLength + rem);
1974 }
1975 
1976 
1977 // OLEStream::SizeVT()
1978 // Returns the size of an element of the specified type
SizeVT(DWORD dwType)1979 DWORD OLEStream::SizeVT(DWORD dwType)
1980 {
1981   switch(dwType)
1982   {
1983     case VT_I1:
1984     case VT_UI1:
1985       return sizeof (char);
1986     case VT_I2:
1987     case VT_UI2:
1988       return sizeof (WORD);
1989     case VT_I4:
1990     case VT_UI4:
1991     case VT_ERROR:
1992       return sizeof (DWORD);
1993     case VT_R4:
1994       return sizeof (float);
1995     case VT_R8:
1996       return sizeof (double);
1997     case VT_CY:
1998       return sizeof (CY);
1999     case VT_DATE:
2000       return sizeof (double);
2001     case VT_BOOL:
2002       return sizeof (BOOL);
2003     case VT_I8:
2004     case VT_UI8:
2005     case VT_INT:
2006     case VT_UINT:
2007       return sizeof (LARGE_INTEGER);
2008     case VT_LPSTR:
2009     case VT_STREAM:
2010     case VT_STORAGE:
2011     case VT_STREAMED_OBJECT:
2012     case VT_STORED_OBJECT:
2013     case VT_BLOB_OBJECT:
2014       return sizeof(char *);
2015     case VT_BSTR:
2016     case VT_LPWSTR:
2017       return sizeof(WCHAR *);
2018     case VT_FILETIME:
2019       return sizeof (FILETIME);
2020     case VT_BLOB:
2021       return sizeof (BLOB);
2022     case VT_CF:
2023       return sizeof (CLIPDATA);
2024     case VT_CLSID:
2025       return sizeof (CLSID);
2026     case VT_VECTOR:
2027       return sizeof (VECTOR);
2028     case DICT_PROP_TYPE:
2029       return sizeof (DICTIONARY);
2030     default:
2031       return 0;
2032   }
2033 }
2034 
2035 // VTtoString()
2036 // Returns a string representation of a VT type data. The returned string is dynamically
2037 // allocated, so it should be deleted after use.
VTtoString(VARIANT * variant,char ** ppsz)2038 Boolean OLEStream::VTtoString(VARIANT *variant, char **ppsz)
2039 {
2040   char  *psz=NULL, *pstr=NULL;
2041   char  pstr1[512];
2042   DWORD len, vtType, i;
2043   VECTOR *pvec;
2044 
2045   if (variant->vt & VT_VECTOR)  {
2046     pvec = (VECTOR *)V_BYREF(variant);
2047 
2048     psz   = new char [ 512 * pvec->cElements ];
2049     if (psz==NULL) {
2050       return FALSE;
2051     }
2052     sprintf(psz, "[VECTOR of %lu elements, type is %s.]\n",
2053         (unsigned long)pvec->cElements, VariantName(variant->vt ^ VT_VECTOR));
2054 
2055     vtType = variant->vt ^ VT_VECTOR;
2056     for ( i = 0; i < pvec->cElements; i++ )
2057     {
2058       if ( vtType == VT_VARIANT )
2059       {
2060         VTtoString(&pvec->pvar[i], &pstr);
2061         sprintf(pstr1, "%50s    %s\n", VariantName(pvec->pvar[i].vt), pstr);
2062 
2063         strcat(psz, pstr1);
2064         delete pstr;
2065         continue;
2066       }
2067 
2068       switch (vtType)
2069       {
2070         case VT_I1:
2071         case VT_UI1:
2072           VTtoString(&pvec->prgb[i], vtType, &pstr);
2073           break;
2074         case VT_I2:
2075         case VT_UI2:
2076         case VT_BOOL:
2077           VTtoString((BYTE *)&pvec->prgw[i], vtType, &pstr);
2078           break;
2079         case VT_I4:
2080         case VT_UI4:
2081         case VT_ERROR:
2082           VTtoString((BYTE *)&pvec->prgdw[i], vtType, &pstr);
2083           break;
2084         case VT_R4:
2085           VTtoString((BYTE *)&pvec->prgflt[i], vtType, &pstr);
2086           break;
2087         case VT_R8:
2088           VTtoString((BYTE *)&pvec->prgdbl[i], vtType, &pstr);
2089           break;
2090         case VT_LPSTR:
2091           VTtoString((BYTE *)pvec->prgpsz[i], vtType, &pstr);
2092           break;
2093         case VT_BSTR:
2094         case VT_LPWSTR:
2095           VTtoString((BYTE *)pvec->prgpwz[i], vtType, &pstr);
2096           break;
2097         case VT_BLOB:
2098           VTtoString((BYTE *)pvec->prgblob[i], vtType, &pstr);
2099           break;
2100         case VT_CF:
2101           VTtoString((BYTE *)pvec->pcd[i], vtType, &pstr);
2102           break;
2103         case VT_CLSID:
2104           VTtoString((BYTE *)&pvec->pclsid[i], vtType, &pstr);
2105           break;
2106         default:
2107           pstr = new char[256];
2108           if (pstr==NULL) {
2109             return FALSE;
2110           }
2111           sprintf(pstr, "The type is not supported in vector");
2112           break;
2113       }
2114       strcat(psz, "\t\t\t\t\t\t\t\t\t\t\t");
2115       strcat(psz, pstr);
2116       strcat(psz, "\n");
2117       delete pstr;
2118     }
2119 
2120     *ppsz = psz;
2121 
2122     return TRUE;
2123   }
2124 
2125   switch(variant->vt)
2126   {
2127     case VT_I1:
2128     case VT_UI1:
2129       psz = new char[2];
2130       if (psz==NULL) {
2131         return FALSE;
2132       }
2133       psz[0] = char(V_I4(variant));
2134       psz[1] = '\0';
2135       break;
2136     case VT_I2:
2137       psz = new char [256];
2138       if (psz==NULL) {
2139         return FALSE;
2140       }
2141 
2142       sprintf(psz, "%d", V_I2(variant));
2143       break;
2144     case VT_UI2:
2145       psz = new char [256];
2146       if (psz==NULL) {
2147         return FALSE;
2148       }
2149 
2150       sprintf(psz, "%u", V_I2(variant));
2151       break;
2152     case VT_I4:
2153       psz = new char [256];
2154       if (psz==NULL) {
2155         return FALSE;
2156       }
2157 
2158       sprintf(psz, "%ld", (long)V_I4(variant));
2159       break;
2160     case VT_UI4:
2161       psz = new char [256];
2162       if (psz==NULL) {
2163         return FALSE;
2164       }
2165 
2166       sprintf(psz, "%lu", (unsigned long)V_I4(variant));
2167       break;
2168     case VT_R4:
2169       psz = new char [256];
2170       if (psz==NULL) {
2171         return FALSE;
2172       }
2173 
2174       sprintf(psz, "%f", V_R4(variant));
2175       break;
2176     case VT_R8:
2177       psz = new char [256];
2178       if (psz==NULL) {
2179         return FALSE;
2180       }
2181 
2182       sprintf(psz, "%f", V_R8(variant));
2183       break;
2184     case VT_CY:
2185       psz = new char [256];
2186       if (psz==NULL) {
2187         return FALSE;
2188       }
2189 
2190 #ifdef macintosh
2191       sprintf(psz, "$%li.%li", V_CY(variant).Hi, V_CY(variant).Lo);
2192 #else
2193       sprintf(psz, "$%li.%li", (unsigned long)V_CY(variant).Lo, (long)V_CY(variant).Hi);
2194 #endif
2195       break;
2196     case VT_DATE:
2197       psz = new char [256];
2198       if (psz==NULL) {
2199         return FALSE;
2200       }
2201 
2202       sprintf(psz, "%f s", V_DATE(variant));
2203       break;
2204     case VT_BOOL:
2205       psz = new char [256];
2206       if (psz==NULL) {
2207         return FALSE;
2208       }
2209 
2210       strcpy(psz, V_BOOL(variant) ? "TRUE" : "FALSE");
2211       break;
2212     case VT_ERROR:
2213       psz = new char [256];
2214       if (psz==NULL) {
2215         return FALSE;
2216       }
2217 
2218       sprintf(psz, "%ld", (long)V_ERROR(variant));
2219       break;
2220     case VT_I8:
2221     case VT_INT:
2222       psz = new char [256];
2223       if (psz==NULL) {
2224         return FALSE;
2225       }
2226 
2227       LARGE_INTEGER li;
2228       li = *(LARGE_INTEGER *)&V_CY(variant);
2229       sprintf(psz, "%ld%ld", (long)li.HighPart, (unsigned long)li.LowPart);
2230       break;
2231     case VT_UI8:
2232     case VT_UINT:
2233       psz = new char [256];
2234       if (psz==NULL) {
2235         return FALSE;
2236       }
2237 
2238       li = *(LARGE_INTEGER *)&V_CY(variant);
2239       sprintf(psz, "%lu%lu", (long)li.HighPart, (unsigned long)li.LowPart);
2240       break;
2241     case VT_LPSTR:
2242     case VT_STREAM:
2243     case VT_STORAGE:
2244     case VT_STREAMED_OBJECT:
2245     case VT_STORED_OBJECT:
2246     case VT_BLOB_OBJECT:
2247 #ifdef _UNICODE
2248       if ( V_UI1REF(variant) )
2249       {
2250         len = strlen((LPSTR)V_UI1REF(variant)) + 1;
2251         psz = new char [len];
2252         strcpy(psz, (LPSTR)V_UI1REF(variant));
2253       }
2254       else
2255       {
2256         len = 1;
2257         psz = new char [len];
2258         if (psz==NULL) {
2259           return FALSE;
2260         }
2261 
2262         *psz = 0;
2263       }
2264       break;
2265 #else
2266       if ( V_BSTR(variant) )
2267       {
2268         len = strlen(V_BSTR(variant)) + 1;
2269         psz = new char [len];
2270         if (psz==NULL) {
2271           return FALSE;
2272         }
2273 
2274         strcpy(psz, V_BSTR(variant));
2275       }
2276       else
2277       {
2278         len = 1;
2279         psz = new char [len];
2280         if (psz==NULL) {
2281           return FALSE;
2282         }
2283 
2284         *psz = 0;
2285       }
2286       break;
2287 
2288 #endif
2289     case VT_BSTR:
2290     case VT_LPWSTR:
2291 #ifdef _WINDOWS
2292       WideCharToMultiByte(CP_ACP, 0, (WCHAR *)V_BYREF(variant), -1, psz, 128, NULL, NULL);
2293 #else
2294   #ifdef _MAC
2295       psz = WideCharToMultiByte((WCHAR *)V_BYREF(variant));
2296   #endif
2297 #endif
2298       break;
2299     case VT_FILETIME:
2300 #ifdef _WINDOWS
2301       SYSTEMTIME st;
2302       FileTimeToSystemTime((FILETIME *)&V_CY(variant), &st);
2303       sprintf(psz, "%02i/%02i/%02i %02i:%02i:%02i",
2304           st.wMonth, st.wDay, st.wYear,
2305           st.wHour, st.wMinute, st.wSecond);
2306 #else
2307   #ifdef _MAC
2308       unsigned long mactime;
2309       psz = new char [256];
2310       if (psz==NULL) {
2311         return FALSE;
2312       }
2313 
2314       CoFileTimeToMacDateTime((FILETIME *)&V_CY(variant), &mactime);
2315       sprintf(psz, "%lu", mactime);
2316   #endif
2317 #endif
2318       break;
2319     case VT_BLOB:
2320       psz = new char [256];
2321       if (psz==NULL) {
2322         return FALSE;
2323       }
2324 
2325       sprintf(psz, "[%lu byte BLOB]",
2326 	(unsigned long)((BLOB *)V_BYREF(variant))->cbSize);
2327       break;
2328     case VT_CF:
2329       psz = new char [256];
2330       if (psz==NULL) {
2331         return FALSE;
2332       }
2333 
2334       sprintf(psz, "[%lu byte CF]",
2335 	(unsigned long)((CLIPDATA *)V_BYREF(variant))->cbSize);
2336       break;
2337     case VT_CLSID:
2338       CLSID *pclsid;
2339       pclsid = (CLSID *)V_BYREF(variant);
2340       psz = new char [256];
2341       if (psz==NULL) {
2342         return FALSE;
2343       }
2344 
2345       sprintf(psz, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
2346           (unsigned int) pclsid->Data1, pclsid->Data2, pclsid->Data3,
2347           pclsid->Data4[0], pclsid->Data4[1], pclsid->Data4[2],
2348           pclsid->Data4[3], pclsid->Data4[4], pclsid->Data4[5],
2349           pclsid->Data4[6], pclsid->Data4[7]);
2350       break;
2351 
2352     default:
2353       psz = new char [256];
2354       if (psz==NULL) {
2355         return FALSE;
2356       }
2357 
2358       strcpy(psz, "Unknown type!");
2359       break;
2360   }
2361 
2362   *ppsz = psz;
2363   return TRUE;
2364 }
2365 
2366 // VTtoString()
2367 // Returns a string representation of the data of a VT type. The data is in the pdata. The
2368 // returned string is dynamically allocated, so it should be deleted after use.
VTtoString(BYTE * pData,DWORD vtType,char ** ppsz)2369 Boolean OLEStream::VTtoString(BYTE *pData, DWORD vtType, char **ppsz)
2370 {
2371   char  *psz=NULL;
2372   char  *pstr=NULL;
2373   char  pstr1[512];
2374   DWORD len, i;
2375 
2376   if ( vtType & VT_VECTOR )  {
2377     VECTOR *pvec = (VECTOR *)pData;
2378 
2379     psz   = new char [ 512 * pvec->cElements ];
2380     if (psz==NULL) {
2381       return FALSE;
2382     }
2383 
2384     sprintf(psz, "[VECTOR of %lu elements, type is %s.]\n",
2385         (unsigned long)pvec->cElements, VariantName(vtType ^ VT_VECTOR));
2386 
2387     vtType = vtType ^ VT_VECTOR;
2388     for ( i = 0; i < pvec->cElements; i++ )
2389     {
2390       if ( vtType == VT_VARIANT )
2391       {
2392         VTtoString(&pvec->pvar[i], &pstr);
2393         sprintf(pstr1, "%50s    %s\n", VariantName(pvec->pvar[i].vt), pstr);
2394 
2395         strcat(psz, pstr1);
2396         delete pstr;
2397         continue;
2398       }
2399 
2400       switch (vtType)
2401       {
2402         case VT_I1:
2403         case VT_UI1:
2404           VTtoString(&pvec->prgb[i], vtType, &pstr);
2405           break;
2406         case VT_I2:
2407         case VT_UI2:
2408         case VT_BOOL:
2409           VTtoString((BYTE *)&pvec->prgw[i], vtType, &pstr);
2410           break;
2411         case VT_I4:
2412         case VT_UI4:
2413         case VT_ERROR:
2414           VTtoString((BYTE *)&pvec->prgdw[i], vtType, &pstr);
2415           break;
2416         case VT_R4:
2417           VTtoString((BYTE *)&pvec->prgflt[i], vtType, &pstr);
2418           break;
2419         case VT_R8:
2420           VTtoString((BYTE *)&pvec->prgdbl[i], vtType, &pstr);
2421           break;
2422         case VT_LPSTR:
2423           VTtoString((BYTE *)pvec->prgpsz[i], vtType, &pstr);
2424           break;
2425         case VT_BSTR:
2426         case VT_LPWSTR:
2427           VTtoString((BYTE *)pvec->prgpwz[i], vtType, &pstr);
2428           break;
2429         case VT_BLOB:
2430           VTtoString((BYTE *)pvec->prgblob[i], vtType, &pstr);
2431           break;
2432         case VT_CF:
2433           VTtoString((BYTE *)pvec->pcd[i], vtType, &pstr);
2434           break;
2435         case VT_CLSID:
2436           VTtoString((BYTE *)&pvec->pclsid[i], vtType, &pstr);
2437           break;
2438         default:
2439           pstr = new char[256];
2440           if (pstr==NULL) {
2441             return FALSE;
2442           }
2443 
2444           sprintf(pstr, "The type is not supported in vector");
2445           break;
2446       }
2447       strcat(psz, "\t\t\t\t\t\t\t\t\t\t\t");
2448       strcat(psz, pstr);
2449       strcat(psz, "\n");
2450       delete pstr;
2451     }
2452     *ppsz = psz;
2453 
2454     return TRUE;
2455   }
2456 
2457   switch(vtType)
2458   {
2459     case VT_I1:
2460     case VT_UI1:
2461       psz = new char[2];
2462       if (psz==NULL) {
2463         return FALSE;
2464       }
2465 
2466       psz[0] = char(*(DWORD *)pData);
2467       psz[1] = '\0';
2468       break;
2469     case VT_I2:
2470       psz = new char [256];
2471       if (psz==NULL) {
2472         return FALSE;
2473       }
2474 
2475       sprintf(psz, "%d", *(WORD *)pData);
2476       break;
2477     case VT_UI2:
2478       psz = new char [256];
2479       if (psz==NULL) {
2480         return FALSE;
2481       }
2482 
2483       sprintf(psz, "%u", *(WORD *)pData);
2484       break;
2485     case VT_I4:
2486       psz = new char [256];
2487       if (psz==NULL) {
2488         return FALSE;
2489       }
2490 
2491       sprintf(psz, "%ld", *(long *)pData);
2492       break;
2493     case VT_UI4:
2494       psz = new char [256];
2495       if (psz==NULL) {
2496         return FALSE;
2497       }
2498 
2499       sprintf(psz, "%lu", (unsigned long)*(DWORD *)pData);
2500       break;
2501     case VT_R4:
2502       psz = new char [256];
2503       if (psz==NULL) {
2504         return FALSE;
2505       }
2506 
2507       sprintf(psz, "%f", *(float *)pData);
2508       break;
2509     case VT_R8:
2510       psz = new char [256];
2511       if (psz==NULL) {
2512         return FALSE;
2513       }
2514 
2515       sprintf(psz, "%f", *(double *)pData);
2516       break;
2517     case VT_CY:
2518       psz = new char [256];
2519       if (psz==NULL) {
2520         return FALSE;
2521       }
2522 
2523 #ifdef macintosh
2524       sprintf(psz, "$%li.%li", ((CY *)pData)->Hi, ((CY *)pData)->Lo);
2525 #else
2526       sprintf(psz, "$%li.%li", (unsigned long)((CY *)pData)->Lo,
2527 	(long)((CY *)pData)->Hi);
2528 #endif
2529       break;
2530     case VT_DATE:
2531       psz = new char [256];
2532       if (psz==NULL) {
2533         return FALSE;
2534       }
2535 
2536       sprintf(psz, "%f s", *(DATE *)pData);
2537       break;
2538     case VT_BOOL:
2539       psz = new char [256];
2540       if (psz==NULL) {
2541         return FALSE;
2542       }
2543 
2544       strcpy(psz, *(BOOL *)pData ? "TRUE" : "FALSE");
2545       break;
2546     case VT_ERROR:
2547       psz = new char [256];
2548       if (psz==NULL) {
2549         return FALSE;
2550       }
2551 
2552       sprintf(psz, "%ld", (long)*(DWORD *)pData);
2553       break;
2554     case VT_I8:
2555     case VT_INT:
2556       psz = new char [256];
2557       if (psz==NULL) {
2558         return FALSE;
2559       }
2560 
2561       LARGE_INTEGER li;
2562       li = *(LARGE_INTEGER *)pData;
2563       sprintf(psz, "%ld%ld", (long)li.HighPart, (unsigned long)li.LowPart);
2564       break;
2565     case VT_UI8:
2566     case VT_UINT:
2567       psz = new char [256];
2568       if (psz==NULL) {
2569         return FALSE;
2570       }
2571 
2572       li = *(LARGE_INTEGER *)pData;
2573       sprintf(psz, "%lu%lu", (long)li.HighPart, (unsigned long)li.LowPart);
2574       break;
2575     case VT_LPSTR:
2576     case VT_STREAM:
2577     case VT_STORAGE:
2578     case VT_STREAMED_OBJECT:
2579     case VT_STORED_OBJECT:
2580     case VT_BLOB_OBJECT:
2581       if ( pData )
2582       {
2583         len = strlen((char *)pData) + 1;
2584         psz = new char [len];
2585         if (psz==NULL) {
2586           return FALSE;
2587         }
2588 
2589         strcpy(psz, (char *)pData);
2590       }
2591       else
2592       {
2593         len = 1;
2594         psz = new char [len];
2595         if (psz==NULL) {
2596           return FALSE;
2597         }
2598 
2599         *psz = 0;
2600       }
2601       break;
2602     case VT_BSTR:
2603     case VT_LPWSTR:
2604 #ifdef _WINDOWS
2605       WideCharToMultiByte(CP_ACP, 0, (WCHAR *)pData, -1, psz, 128, NULL, NULL);
2606 #else
2607   #ifdef _MAC
2608       psz = WideCharToMultiByte((WCHAR *)pData);
2609   #endif
2610 #endif
2611       break;
2612     case VT_FILETIME:
2613 #ifdef _WINDOWS
2614       SYSTEMTIME st;
2615       FileTimeToSystemTime((FILETIME *)pData, &st);
2616       sprintf(psz, "%02i/%02i/%02i %02i:%02i:%02i",
2617           st.wMonth, st.wDay, st.wYear,
2618           st.wHour, st.wMinute, st.wSecond);
2619 #else
2620   #ifdef _MAC
2621       unsigned long mactime;
2622       psz = new char [256];
2623       if (psz==NULL) {
2624         return FALSE;
2625       }
2626 
2627       CoFileTimeToMacDateTime((FILETIME *)pData, &mactime);
2628       sprintf(psz, "%lu", mactime);
2629   #endif
2630 #endif
2631       break;
2632     case VT_BLOB:
2633       psz = new char [256];
2634       if (psz==NULL) {
2635         return FALSE;
2636       }
2637 
2638       sprintf(psz, "[%lu byte BLOB]",
2639 	(unsigned long)((BLOB *)pData)->cbSize);
2640       break;
2641     case VT_CF:
2642       psz = new char [256];
2643       if (psz==NULL) {
2644         return FALSE;
2645       }
2646 
2647       sprintf(psz, "[%lu byte CF]",
2648 	(unsigned long)((CLIPDATA *)pData)->cbSize);
2649       break;
2650     case VT_CLSID:
2651       CLSID *pclsid;
2652       pclsid = (CLSID *)pData;
2653       psz = new char [256];
2654       if (psz==NULL) {
2655         return FALSE;
2656       }
2657 
2658       sprintf(psz, "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
2659           (unsigned int) pclsid->Data1, pclsid->Data2, pclsid->Data3,
2660           pclsid->Data4[0], pclsid->Data4[1], pclsid->Data4[2],
2661           pclsid->Data4[3], pclsid->Data4[4], pclsid->Data4[5],
2662           pclsid->Data4[6], pclsid->Data4[7]);
2663       break;
2664 
2665     default:
2666       psz = new char [256];
2667       if (psz==NULL) {
2668         return FALSE;
2669       }
2670 
2671       strcpy(psz, "Unknown type!");
2672       break;
2673   }
2674 
2675   *ppsz = psz;
2676   return TRUE;
2677 }
2678