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