Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1371 lines
45 KiB

  1. /*************************************************************************
  2. **
  3. ** OLE 2.0 Property Set Utilities
  4. **
  5. ** suminfo.cpp
  6. **
  7. ** This file contains functions that are useful for the manipulation
  8. ** of OLE 2.0 Property Sets particularly to manage the Summary Info
  9. ** property set.
  10. **
  11. ** (c) Copyright Microsoft Corp. 1990 - 1992 All Rights Reserved
  12. **
  13. *************************************************************************/
  14. // Note: this file is designed to be stand-alone; it includes a
  15. // carefully chosen, minimal set of headers.
  16. //
  17. // For conditional compilation we use the ole2 conventions,
  18. // _MAC = mac
  19. // WIN32 = Win32 (NT really)
  20. // <nothing> = defaults to Win16
  21. // REVIEW: the following needs to modified to handle _MAC
  22. #define STRICT
  23. #ifndef INC_OLE2
  24. #define INC_OLE2
  25. #endif
  26. #include <windows.h>
  27. #include <string.h>
  28. #include <ole2.h>
  29. #include "ole2ui.h"
  30. OLEDBGDATA
  31. /* A LPSUMINFO variable is a pointer to an instance of an abstract data
  32. ** type. There can be an arbitrary number of SummaryInfo streams open
  33. ** simultaneously (subject to available memory); each must have its
  34. ** own LPSUMINFO instance. Each LPSUMINFO instance must
  35. ** be initialized prior to use by calling Init and freed after its
  36. ** last use by calling Free. The param argument to Init is reserved
  37. ** for future expansion and should be zero initially. Once a LPSUMINFO
  38. ** instance is allocated (by Init), the user can call the Set
  39. ** procedures to initialize fields. A copy of the arguments is made
  40. ** in every case except SetThumbnail where control of the storage
  41. ** occupied by the METAFILEPICT is merely transferred. When the
  42. ** Free routine is called, all storage will be deallocated including
  43. ** that of the thumbnail. The arguments to SetThumbNail and the
  44. ** return values from GetThumbNail correspond to the OLE2.0 spec.
  45. ** Note that on input, the thumbnail is read on demand but all the
  46. ** other properties are pre-loaded. The thumbnail is manipulated as
  47. ** a windows handle to a METAFILEPICT structure, which in turn
  48. ** contains a handle to the METAFILE. The transferClip argument on
  49. ** GetThumbNail, when set to true, transfers responsibility for
  50. ** storage management of the thumbnail to the caller; that is, after
  51. ** Free has been called, the handle is still valid. Clear can be
  52. ** used to free storage for all the properties but then you must
  53. ** call Read to load them again. All the code is based on FAR
  54. ** pointers.
  55. ** CoInitialize MUST be called PRIOR to calling OleStdInitSummaryInfo.
  56. ** Memory is allocated using the currently active IMalloc*
  57. ** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ).
  58. **
  59. ** Common scenarios:
  60. ** Read SummaryInfo
  61. ** ----------------
  62. ** OleStdInitSummaryInfo()
  63. ** OleStdReadSummaryInfo()
  64. ** . . . . .
  65. ** call different Get routines
  66. ** . . . . .
  67. ** OleStdFreeSummaryInfo()
  68. **
  69. ** Create SummaryInfo
  70. ** ------------------
  71. ** OleStdInitSummaryInfo()
  72. ** call different Set routines
  73. ** OleStdWriteSummaryInfo()
  74. ** OleStdFreeSummaryInfo()
  75. **
  76. ** Update SummaryInfo
  77. ** ------------------
  78. ** OleStdInitSummaryInfo()
  79. ** OleStdReadSummaryInfo()
  80. ** OleStdGetThumbNailProperty(necessary only if no SetThumb)
  81. ** call different Set routines
  82. ** OleStdWriteSummaryInfo()
  83. ** OleStdFreeSummaryInfo()
  84. */
  85. #ifdef WIN32
  86. #define CHAR TCHAR
  87. #else
  88. #define CHAR unsigned char
  89. #endif
  90. #define fTrue 1
  91. #define fFalse 0
  92. #define BYTE unsigned char
  93. #define WORD unsigned short
  94. #define DWORD unsigned long
  95. #define LPVOID void FAR *
  96. #define uchar unsigned char
  97. #define ulong unsigned long
  98. #define BOOL unsigned char
  99. #define BF unsigned int
  100. #include "suminfo.h"
  101. #include "wn_dos.h"
  102. #if defined( _DEBUG )
  103. #ifndef NOASSERT
  104. // following is from compobj.dll (ole2)
  105. #ifdef UNICODE
  106. #define ASSERT(x) (!(x) ? FnAssert(TEXT(#x), NULL, \
  107. TEXT(__FILE__), __LINE__) : 0)
  108. #else
  109. #define ASSERT(x) (!(x) ? \
  110. { \
  111. WCHAR wsz[255]; \
  112. wcscpy(wsz, (#x)); \
  113. FnAssert(wsz, NULL, TEXT(__FILE__), __LINE__) \
  114. } \
  115. : 0)
  116. #endif
  117. #else
  118. #define ASSERT(x)
  119. #endif
  120. #else
  121. #define ASSERT(x)
  122. #endif
  123. typedef struct _RSUMINFO
  124. {
  125. WORD byteOrder;
  126. WORD formatVersion;
  127. WORD getOSVersion;
  128. WORD osVersion;
  129. CLSID classId; //from compobj.h
  130. DWORD cSections;
  131. PROPSETLIST rgPropSet[1/*cSections*/]; //one section in standard summary info
  132. STANDARDSECINMEM section;
  133. ULONG fileOffset; //offset for thumbnail to support demand read
  134. } RSUMINFO;
  135. typedef RSUMINFO FAR * LPRSI;
  136. typedef union _foo{
  137. ULARGE_INTEGER uli;
  138. struct {
  139. DWORD dw;
  140. DWORD dwh;
  141. };
  142. struct {
  143. WORD w0;
  144. WORD w1;
  145. WORD w2;
  146. WORD w3;
  147. };
  148. } Foo;
  149. /* MemAlloc
  150. ** ---------
  151. ** allocate memory using the currently active IMalloc* allocator
  152. */
  153. static LPVOID MemAlloc(ULONG ulSize)
  154. {
  155. LPVOID pout;
  156. LPMALLOC pmalloc;
  157. if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) {
  158. OleDbgAssert(pmalloc);
  159. return NULL;
  160. }
  161. pout = (LPVOID)pmalloc->Alloc(ulSize);
  162. if (pmalloc != NULL) {
  163. ULONG refs = pmalloc->Release();
  164. }
  165. return pout;
  166. }
  167. /* MemFree
  168. ** -------
  169. ** free memory using the currently active IMalloc* allocator
  170. */
  171. static void MemFree(LPVOID pmem)
  172. {
  173. LPMALLOC pmalloc;
  174. if (pmem == NULL)
  175. return;
  176. if (CoGetMalloc(MEMCTX_TASK, &pmalloc) != NOERROR) {
  177. OleDbgAssert(pmalloc);
  178. return;
  179. }
  180. pmalloc->Free(pmem);
  181. if (pmalloc != NULL) {
  182. ULONG refs = pmalloc->Release();
  183. }
  184. }
  185. // Replace the first argument with the product of itself and the multiplier
  186. static void ulargeMultiply(ULARGE_INTEGER FAR *ul, USHORT m)
  187. {
  188. Foo out, in;
  189. in.uli = *ul;
  190. out.dw = (ULONG)m * in.w0; in.w0 = out.w0;
  191. out.dw = (ULONG)m * in.w1 + out.w1; in.w1 = out.w0;
  192. out.dw = (ULONG)m * in.w2 + out.w1; in.w2 = out.w0;
  193. out.dw = (ULONG)m * in.w3 + out.w1; in.w3 = out.w0;
  194. *ul = in.uli;
  195. }
  196. // Replace the first argument with the product of itself and the multiplier
  197. static void ulargeDivide(ULARGE_INTEGER FAR *ul, USHORT m)
  198. {
  199. Foo out, in;
  200. DWORD i;
  201. in.uli = *ul;
  202. out.dwh = in.dwh/(ULONG)m;
  203. i = in.dwh%(ULONG)m;
  204. in.w2 = in.w1;
  205. in.w3 = (WORD)i;
  206. out.w1 = (WORD)(in.dwh/(ULONG)m);
  207. in.w1 = (WORD)(in.dwh%(ULONG)m);
  208. out.w0 = (WORD)(in.dw/(ULONG)m);
  209. *ul = out.uli;
  210. }
  211. static void setStandard(LPRSI lprsi)
  212. {
  213. int i;
  214. lprsi->cSections = 1;
  215. SetSumInfFMTID(&lprsi->rgPropSet[0].formatID);
  216. _fmemcpy(&lprsi->classId, &lprsi->rgPropSet[0].formatID, sizeof(FMTID));
  217. lprsi->rgPropSet[0].byteOffset = cbNewSummaryInfo(1);
  218. for (i=0; i<cPID_STANDARD; i++)
  219. lprsi->section.rgPropId[i].propertyID = PID_TITLE+i;
  220. lprsi->section.cProperties = cPID_STANDARD; //always; do null test to check validity
  221. }
  222. extern "C" {
  223. /*************************************************************************
  224. **
  225. ** OleStdInitSummaryInfo
  226. **
  227. ** Purpose:
  228. ** Initialize a Summary Info structure.
  229. **
  230. ** Parameters:
  231. ** int reserved - reserverd for future use. must be 0.
  232. **
  233. ** Return Value:
  234. ** LPSUMINFO
  235. **
  236. ** Comments:
  237. ** CoInitialize MUST be called PRIOR to calling OleStdInitSummaryInfo.
  238. ** Memory is allocated using the currently active IMalloc*
  239. ** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ).
  240. ** Each LPSUMINFO instance must be initialized prior to use by
  241. ** calling OleStdInitSummaryInfo. Once a LPSUMINFO instance is allocated
  242. ** (by OleStdInitSummaryInfo), the user can call the Set procedures to
  243. ** initialize fields.
  244. *************************************************************************/
  245. STDAPI_(LPSUMINFO) OleStdInitSummaryInfo(int reserved)
  246. {
  247. LPRSI lprsi;
  248. if ((lprsi = (LPRSI)MemAlloc(sizeof(RSUMINFO))) != NULL)
  249. {
  250. ClearSumInf(lprsi, sizeof(RSUMINFO));
  251. } else return NULL;
  252. setStandard(lprsi);
  253. return (LPSUMINFO)lprsi;
  254. }
  255. /*************************************************************************
  256. **
  257. ** OleStdFreeSummaryInfo
  258. **
  259. ** Purpose:
  260. ** Free a Summary Info structure.
  261. **
  262. ** Parameters:
  263. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  264. **
  265. ** Return Value:
  266. ** void
  267. **
  268. ** Comments:
  269. ** Memory is freed using the currently active IMalloc*
  270. ** allocator (as is returned by call CoGetMalloc(MEMCTX_TASK) ).
  271. ** Every LPSUMINFO struct must be freed after its last use.
  272. ** When the OleStdFreeSummaryInfo routine is called, all storage will be
  273. ** deallocated including that of the thumbnail (unless ownership of
  274. ** the thumbnail has been transfered to the caller -- see
  275. ** description of transferClip in GetThumbnail API).
  276. **
  277. *************************************************************************/
  278. STDAPI_(void) OleStdFreeSummaryInfo(LPSUMINFO FAR *lplp)
  279. {
  280. if (lplp==NULL||*lplp==NULL) return;
  281. OleStdClearSummaryInfo(*lplp);
  282. MemFree(*lplp);
  283. *lplp = NULL;
  284. }
  285. /*************************************************************************
  286. **
  287. ** OleStdClearSummaryInfo
  288. **
  289. ** Purpose:
  290. ** Free storage (memory) for all the properties of the LPSUMINFO.
  291. **
  292. ** Parameters:
  293. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  294. **
  295. ** Return Value:
  296. ** void
  297. **
  298. ** Comments:
  299. ** After calling OleStdClearSummaryInfo you must call OleStdReadSummaryInfo to
  300. ** load them again.
  301. **
  302. *************************************************************************/
  303. STDAPI_(void) OleStdClearSummaryInfo(LPSUMINFO lp)
  304. {
  305. OleStdSetStringProperty(lp, PID_TITLE, NULL);
  306. OleStdSetStringProperty(lp, PID_SUBJECT, NULL);
  307. OleStdSetStringProperty(lp, PID_AUTHOR, NULL);
  308. OleStdSetStringProperty(lp, PID_KEYWORDS, NULL);
  309. OleStdSetStringProperty(lp, PID_COMMENTS, NULL);
  310. OleStdSetStringProperty(lp, PID_TEMPLATE, NULL);
  311. OleStdSetStringProperty(lp, PID_REVNUMBER, NULL);
  312. OleStdSetStringProperty(lp, PID_APPNAME, NULL);
  313. OleStdSetThumbNailProperty(NULL, lp, VT_CF_EMPTY, 0, NULL, NULL, 0);
  314. ClearSumInf((LPRSI)lp, sizeof(RSUMINFO));
  315. }
  316. /*************************************************************************
  317. **
  318. ** OleStdReadSummaryInfo
  319. **
  320. ** Purpose:
  321. ** Read all Summary Info properties into memory (except thumbnail
  322. ** which is demand loaded).
  323. **
  324. ** Parameters:
  325. ** LPSTREAM lps - open SummaryInfo IStream*
  326. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  327. **
  328. ** Return Value:
  329. ** int - 1 for success
  330. ** - 0 if error occurs
  331. ** Comments:
  332. **
  333. *************************************************************************/
  334. STDAPI_(int) OleStdReadSummaryInfo(LPSTREAM lpStream, LPSUMINFO lp)
  335. {
  336. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  337. LPRSI lpSumInfo = (LPRSI)lp;
  338. SCODE sc;
  339. ULONG cbRead,i,sectionOffset;
  340. LARGE_INTEGER a;
  341. ULARGE_INTEGER b;
  342. int j,k,l;
  343. union {
  344. RSUMINFO rsi;
  345. STDZ stdz;
  346. };
  347. OleStdClearSummaryInfo(lp);
  348. LISet32(a, 0);
  349. sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
  350. if (FAILED(sc)) goto fail;
  351. sectionOffset = cbNewSummaryInfo(1);
  352. sc = GetScode(lpStream->Read(&rsi, sectionOffset, &cbRead));
  353. if (FAILED(sc)||cbRead<sectionOffset) goto fail;
  354. if (!FIntelOrder(&rsi)||rsi.formatVersion!=0) goto fail;
  355. j = (int)rsi.cSections;
  356. while (j-->0) {
  357. if (FEqSumInfFMTID(&rsi.rgPropSet[0].formatID)) {
  358. sectionOffset = rsi.rgPropSet[0].byteOffset;
  359. break;
  360. } else {
  361. sc = GetScode(lpStream->Read(&rsi.rgPropSet[0].formatID, sizeof(PROPSETLIST), &cbRead));
  362. if (FAILED(sc)||cbRead!=sizeof(PROPSETLIST)) goto fail;
  363. }
  364. if (j<=0) goto fail;
  365. }
  366. LISet32(a, sectionOffset);
  367. sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
  368. if (FAILED(sc)) goto fail;
  369. sc = GetScode(lpStream->Read(&rsi.section, cbNewSection(1), &cbRead));
  370. if (FAILED(sc)||cbRead!=cbNewSection(1)) goto fail;
  371. i = rsi.section.cBytes+sectionOffset;
  372. j = (int)rsi.section.cProperties;
  373. if (j>cPID_STANDARD) goto fail;
  374. k = 0;
  375. while (j-->0) {
  376. k++;
  377. switch (l=(int)rsi.section.rgPropId[0].propertyID) {
  378. case PID_PAGECOUNT:
  379. case PID_WORDCOUNT:
  380. case PID_CHARCOUNT:
  381. case PID_SECURITY:
  382. if (l==PID_SECURITY) l=3; else l-=PID_PAGECOUNT;
  383. cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset;
  384. if (cbRead>=i) goto fail;
  385. LISet32(a, cbRead);
  386. sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
  387. if (FAILED(sc)) goto fail;
  388. sc = GetScode(lpStream->Read(&lpSSIM->rgInts[l], sizeof(INTS), &cbRead));
  389. if (FAILED(sc)||cbRead!=sizeof(INTS)) goto fail;
  390. if (lpSSIM->rgInts[l].vtType==VT_EMPTY) break;
  391. if (lpSSIM->rgInts[l].vtType!=VT_I4) goto fail;
  392. break;
  393. case PID_EDITTIME:
  394. case PID_LASTPRINTED:
  395. case PID_CREATE_DTM_RO:
  396. case PID_LASTSAVE_DTM:
  397. l-=PID_EDITTIME;
  398. cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset;
  399. if (cbRead>=i) goto fail;
  400. LISet32(a, cbRead);
  401. sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
  402. if (FAILED(sc)) goto fail;
  403. sc = GetScode(lpStream->Read(&lpSSIM->rgTime[l], sizeof(TIME), &cbRead));
  404. if (FAILED(sc)||cbRead!=sizeof(TIME)) goto fail;
  405. if (lpSSIM->rgTime[l].vtType==VT_EMPTY) break;
  406. if (lpSSIM->rgTime[l].vtType!=VT_FILETIME) goto fail;
  407. break;
  408. case PID_TITLE:
  409. case PID_SUBJECT:
  410. case PID_AUTHOR:
  411. case PID_KEYWORDS:
  412. case PID_COMMENTS:
  413. case PID_TEMPLATE:
  414. case PID_LASTAUTHOR:
  415. case PID_REVNUMBER:
  416. case PID_APPNAME:
  417. cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset;
  418. if (cbRead>=i) goto fail;
  419. LISet32(a, cbRead);
  420. sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
  421. if (FAILED(sc)) goto fail;
  422. sc = GetScode(lpStream->Read(&stdz, sizeof(STDZ), &cbRead));
  423. if (FAILED(sc)||cbRead<sizeof(DWORD)*2) goto fail;
  424. if (stdz.vtType==VT_EMPTY||stdz.vtByteCount<=1) break;
  425. if (stdz.vtType!=VT_LPSTR||stdz.vtByteCount>WORDMAX) goto fail;
  426. stdz.rgchars[(int)stdz.vtByteCount-1] = TEXT('\0');
  427. OleStdSetStringProperty(lp, (DWORD)l, (LPTSTR)&stdz.rgchars[0]);
  428. break;
  429. case PID_THUMBNAIL:
  430. cbRead = sectionOffset+rsi.section.rgPropId[0].byteOffset;
  431. if (cbRead>=i) goto fail;
  432. LISet32(a, cbRead);
  433. sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
  434. if (FAILED(sc)) goto fail;
  435. lpSumInfo->fileOffset = cbRead+sizeof(DWORD)*3;
  436. sc = GetScode(lpStream->Read(&lpSSIM->thumb, sizeof(DWORD)*4, &cbRead));
  437. if (FAILED(sc)||cbRead!=sizeof(DWORD)*4) {
  438. lpSSIM->thumb.vtType = VT_EMPTY;
  439. goto fail;
  440. }
  441. if (lpSSIM->thumb.vtType == VT_EMPTY) {
  442. lpSSIM->thumb.cBytes = 0;
  443. break;
  444. }
  445. if (lpSSIM->thumb.vtType != VT_CF) {
  446. lpSSIM->thumb.vtType = VT_EMPTY;
  447. goto fail;
  448. }
  449. lpSSIM->thumb.cBytes -= sizeof(DWORD); //for selector
  450. if (lpSSIM->thumb.selector==VT_CF_WIN||lpSSIM->thumb.selector==VT_CF_MAC) {
  451. lpSumInfo->fileOffset += sizeof(DWORD);
  452. lpSSIM->thumb.cBytes -= sizeof(DWORD); //for format val
  453. }
  454. break;
  455. default: ;
  456. }
  457. if (j<=0)
  458. {
  459. // We should fail if the document is password-protected.
  460. if(OleStdGetSecurityProperty(lp)==fSecurityPassworded)
  461. goto fail;
  462. return 1;
  463. }
  464. LISet32(a, sectionOffset+sizeof(DWORD)*2+k*sizeof(PROPIDLIST));
  465. sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
  466. if (FAILED(sc)) goto fail;
  467. sc = GetScode(lpStream->Read(&rsi.section.rgPropId[0], sizeof(PROPIDLIST), &cbRead));
  468. if (FAILED(sc)||cbRead!=sizeof(PROPIDLIST)) goto fail;
  469. }
  470. fail:
  471. OleStdClearSummaryInfo(lpSumInfo);
  472. return 0;
  473. }
  474. /*************************************************************************
  475. **
  476. ** OleStdWriteSummaryInfo
  477. **
  478. ** Purpose:
  479. ** Write all Summary Info properties to a IStream*
  480. **
  481. ** Parameters:
  482. ** LPSTREAM lps - open SummaryInfo IStream*
  483. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  484. **
  485. ** Return Value:
  486. ** int - 1 for success
  487. ** - 0 if error occurs
  488. ** Comments:
  489. **
  490. *************************************************************************/
  491. STDAPI_(int) OleStdWriteSummaryInfo(LPSTREAM lpStream, LPSUMINFO lp)
  492. {
  493. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  494. // REVIEW: localization issues for propert sets
  495. // do we need to include a code page and dictionary?
  496. LPRSI lpSumInfo = (LPRSI)lp;
  497. SCODE sc;
  498. ULONG cbWritten;
  499. ULONG cBytes, oBytes, k,l,m,n;
  500. LARGE_INTEGER a;
  501. ULARGE_INTEGER b;
  502. CHAR FAR *lps;
  503. LPMETAFILEPICT lpmfp;
  504. int i,j,s;
  505. setStandard(lpSumInfo);
  506. oBytes = cbNewSection(cPID_STANDARD); //offsets are relative to the section
  507. cBytes = cbNewSection(cPID_STANDARD)+(sizeof(TIME)*MAXTIME)+(sizeof(INTS)*MAXINTS);
  508. lpSSIM->rgPropId[PID_EDITTIME-2].byteOffset = oBytes;
  509. lpSSIM->rgPropId[PID_LASTPRINTED-2].byteOffset = oBytes+sizeof(TIME);
  510. lpSSIM->rgPropId[PID_CREATE_DTM_RO-2].byteOffset = oBytes+sizeof(TIME)*2;
  511. lpSSIM->rgPropId[PID_LASTSAVE_DTM-2].byteOffset = oBytes+sizeof(TIME)*3;
  512. lpSSIM->rgPropId[PID_PAGECOUNT-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME);
  513. lpSSIM->rgPropId[PID_WORDCOUNT-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME+sizeof(INTS));
  514. lpSSIM->rgPropId[PID_CHARCOUNT-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME+sizeof(INTS)*2);
  515. lpSSIM->rgPropId[PID_SECURITY-2].byteOffset = oBytes+(sizeof(TIME)*MAXTIME+sizeof(INTS)*3);
  516. oBytes += sizeof(TIME)*MAXTIME + sizeof(INTS)*MAXINTS;
  517. lpSSIM->rgPropId[PID_THUMBNAIL-2].byteOffset = oBytes;
  518. l = 0;
  519. if (lpSSIM->thumb.vtType==VT_EMPTY) k = sizeof(DWORD);
  520. else {
  521. l = ((lpSSIM->thumb.cBytes+4-1)>>2)<<2;
  522. if (lpSSIM->thumb.selector==VT_CF_BYTES) k = sizeof(DWORD)*3;
  523. else if (lpSSIM->thumb.selector==VT_CF_FMTID) {k = sizeof(DWORD)*3; l += sizeof(FMTID); }
  524. else if (lpSSIM->thumb.selector==VT_CF_NAME) {k = sizeof(DWORD)*3; l += (((*lpSSIM->thumb.lpstzName+1+3)>>2)<<2);}
  525. else k = sizeof(DWORD)*4;
  526. }
  527. cBytes += k+l;
  528. oBytes += k+l;
  529. for (i=0; i<MAXSTDZ; i++) {
  530. j = 0;
  531. if (lpSSIM->rglpsz[i]!=NULL) {
  532. j = lpSSIM->rglpsz[i]->VTCB+1/*null*/;
  533. lpSSIM->rglpsz[i]->vtByteCount = j;
  534. j = (((j+4-1)>>2)<<2)+sizeof(DWORD);
  535. cBytes += j;
  536. }
  537. if (i!=MAXSTDZ-1) lpSSIM->rgPropId[i].byteOffset = oBytes;
  538. else lpSSIM->rgPropId[PID_APPNAME-2].byteOffset = oBytes;
  539. oBytes += j+sizeof(DWORD);
  540. cBytes += sizeof(DWORD); //type
  541. }
  542. lpSSIM->cBytes = cBytes;
  543. LISet32(a, 0);
  544. sc = GetScode(lpStream->Seek(a, STREAM_SEEK_SET, &b));
  545. if (FAILED(sc)) return 0;
  546. sc = GetScode(lpStream->Write(lpSumInfo, cbNewSummaryInfo(1), &cbWritten));
  547. if (FAILED(sc)||cbWritten!=cbNewSummaryInfo(1)) return 0;
  548. sc = GetScode(lpStream->Write(lpSSIM, cbNewSection(cPID_STANDARD)+sizeof(TIME)*MAXTIME+sizeof(INTS)*MAXINTS, &cbWritten));
  549. if (FAILED(sc)||cbWritten!=cbNewSection(cPID_STANDARD)+sizeof(TIME)*MAXTIME+sizeof(INTS)*MAXINTS) return 0;
  550. m = lpSSIM->thumb.cBytes;
  551. if (lpSSIM->thumb.lpstzName!=NULL) s = *lpSSIM->thumb.lpstzName;
  552. else s = 0;
  553. if (m!=0) {
  554. lpSSIM->thumb.cBytes = (k-sizeof(DWORD)*2)+
  555. (((lpSSIM->thumb.cBytes+4-1)>>2)<<2)+(((s+4-1)>>2)<<2);
  556. n = lpSSIM->thumb.selector;
  557. lps = lpSSIM->thumb.lpByte;
  558. OleDbgAssert(lps!=NULL); //maybe a GetThumbNail here
  559. OleDbgAssert(n!=VT_CF_NAME);
  560. if (n==VT_CF_WIN) { //bytes are in global memory
  561. lpmfp = (LPMETAFILEPICT)GlobalLock((HANDLE)(DWORD)lps);
  562. if (lpmfp==NULL) goto fail;
  563. lps = (CHAR FAR*)GlobalLock(lpmfp->hMF);
  564. }
  565. if (n==VT_CF_NAME) lpSSIM->thumb.selector = *lpSSIM->thumb.lpstzName+1/*null*/;
  566. }
  567. sc = GetScode(lpStream->Write(&lpSSIM->thumb, k, &cbWritten));
  568. if (FAILED(sc)||cbWritten!=k) goto fail;
  569. if (s!=0) {
  570. k = ((s+1+4-1)>>2)<<2;
  571. sc = GetScode(lpStream->Write(lpSSIM->thumb.lpstzName+1, k, &cbWritten));
  572. if (FAILED(sc)||cbWritten!=k) goto fail;
  573. }
  574. if (m!=0) {
  575. k = ((m+3)>>2)<<2;
  576. if (n==VT_CF_WIN||VT_CF_NAME) { //bytes are in global memory
  577. sc = GetScode(lpStream->Write(lpmfp, sizeof(METAFILEPICT), &cbWritten));
  578. k -= sizeof(METAFILEPICT);
  579. }
  580. sc = GetScode(lpStream->Write(lps, k, &cbWritten));
  581. if (FAILED(sc)||cbWritten!=k) goto fail;
  582. if (n==VT_CF_WIN||VT_CF_NAME) { //bytes are in global memory
  583. GlobalUnlock(lpmfp->hMF);
  584. GlobalUnlock((HANDLE)(DWORD)lpSSIM->thumb.lpByte);
  585. }
  586. }
  587. lpSSIM->thumb.cBytes = m; //restore in mem value
  588. lpSSIM->thumb.selector = n;
  589. k = VT_EMPTY;
  590. for (i=0; i<MAXSTDZ; i++) {
  591. if (lpSSIM->rglpsz[i]!=NULL) {
  592. l = lpSSIM->rglpsz[i]->vtByteCount;
  593. j = ((((int)l+4-1)/4)*4)+sizeof(DWORD)*2;
  594. sc = GetScode(lpStream->Write(lpSSIM->rglpsz[i], j, &cbWritten));
  595. if (FAILED(sc)||cbWritten!=(ULONG)j) return 0;
  596. lpSSIM->rglpsz[i]->vtByteCount = 0; //restore stz count convention
  597. lpSSIM->rglpsz[i]->VTCB = (int)l;
  598. } else {
  599. sc = GetScode(lpStream->Write(&k, sizeof(DWORD), &cbWritten));
  600. if (FAILED(sc)||cbWritten!=sizeof(DWORD)) return 0;
  601. }
  602. }
  603. return 1;
  604. fail:
  605. lpSSIM->thumb.cBytes = m; //restore in mem value
  606. lpSSIM->thumb.selector = n;
  607. if (m!=0&&(n==VT_CF_WIN||VT_CF_NAME)) { //bytes are in global memory
  608. GlobalUnlock((HANDLE)(DWORD)lps);
  609. }
  610. return 0;
  611. }
  612. /*************************************************************************
  613. **
  614. ** OleStdGetSecurityProperty
  615. **
  616. ** Purpose:
  617. ** Retrieve the Security Property
  618. **
  619. ** Parameters:
  620. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  621. **
  622. ** Return Value:
  623. ** DWORD - security level
  624. ** AllSecurityFlagsEqNone 0 - no security
  625. ** fSecurityPassworded 1 - password required
  626. ** fSecurityRORecommended 2 - read-only is recommended
  627. ** fSecurityRO 4 - read-only is required
  628. ** fSecurityLockedForAnnotations 8 - locked for annotations
  629. **
  630. ** Comments:
  631. ** by noting the (suggested; that is, application-enforced) security
  632. ** level on the document, an application other than the originator
  633. ** of the document can adjust its user interface to the properties
  634. ** appropriately. An application should not display any of the
  635. ** information about a password protected document, and should not
  636. ** allow modifications to enforced read-only or locked for
  637. ** annotations documents. It should warn the user about read-only
  638. ** recommended if the user attempts to modify properties.
  639. **
  640. *************************************************************************/
  641. STDAPI_(DWORD) OleStdGetSecurityProperty(LPSUMINFO lp)
  642. {
  643. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  644. if (lpSSIM->rgInts[3].vtType == VT_I4) return lpSSIM->rgInts[3].value;
  645. return 0;
  646. }
  647. /*************************************************************************
  648. **
  649. ** OleStdSetSecurityProperty
  650. **
  651. ** Purpose:
  652. ** Set the Security Property
  653. **
  654. ** Parameters:
  655. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  656. ** DWORD security - security level
  657. ** AllSecurityFlagsEqNone 0 - no security
  658. ** fSecurityPassworded 1 - password required
  659. ** fSecurityRORecommended 2 - read-only is recommended
  660. ** fSecurityRO 4 - read-only is required
  661. ** fSecurityLockedForAnnotations 8 - locked for annotations
  662. **
  663. ** Return Value:
  664. ** int - 1 for success
  665. ** - 0 if error occurs
  666. ** (there are no errors)
  667. **
  668. ** Comments:
  669. ** by noting the (suggested; that is, application-enforced) security
  670. ** level on the document, an application other than the originator
  671. ** of the document can adjust its user interface to the properties
  672. ** appropriately. An application should not display any of the
  673. ** information about a password protected document, and should not
  674. ** allow modifications to enforced read-only or locked for
  675. ** annotations documents. It should warn the user about read-only
  676. ** recommended if the user attempts to modify properties.
  677. **
  678. *************************************************************************/
  679. STDAPI_(int) OleStdSetSecurityProperty(LPSUMINFO lp, DWORD security)
  680. {
  681. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  682. // REVIEW: check valid transitions; how do we know APP called us?
  683. if (security==0) {
  684. lpSSIM->rgInts[3].vtType = VT_EMPTY;
  685. return 1;
  686. }
  687. lpSSIM->rgInts[3].vtType = VT_I4;
  688. lpSSIM->rgInts[3].value = security;
  689. return 1;
  690. }
  691. /*************************************************************************
  692. **
  693. ** OleStdGetStringProperty
  694. **
  695. ** Purpose:
  696. ** Retrieve a String Propety.
  697. ** (returns zero terminated string -- C string)
  698. **
  699. ** Parameters:
  700. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  701. ** DWORD pid - ID of String Property
  702. **
  703. ** Return Value:
  704. ** LPTSTR - value of String Property
  705. ** (zero terminated string--C string)
  706. **
  707. ** Comments:
  708. ** String should NOT be freed by caller. Memory for string will be
  709. ** freed when OleStdFreeSummaryInfo is called.
  710. *************************************************************************/
  711. STDAPI_(LPTSTR) OleStdGetStringProperty(LPSUMINFO lp, DWORD pid)
  712. {
  713. LPTSTR l = OleStdGetStringZProperty(lp,pid);
  714. if (l==NULL) return NULL; else return l+1;
  715. }
  716. /*************************************************************************
  717. **
  718. ** OleStdSetStringProperty
  719. **
  720. ** Purpose:
  721. ** Set a String Propety
  722. ** (takes zero terminated string -- C string)
  723. **
  724. ** Parameters:
  725. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  726. ** DWORD pid - ID of String Property
  727. ** LPTSTR lpsz - new value for String Property.
  728. ** zero terminated string -- C string.
  729. ** May be NULL, in which case the
  730. ** propery is cleared.
  731. **
  732. ** Return Value:
  733. ** int - 1 if successful
  734. ** - 0 invalid property id
  735. **
  736. ** Comments:
  737. ** The input string is copied.
  738. **
  739. *************************************************************************/
  740. STDAPI_(int) OleStdSetStringProperty(LPSUMINFO lp, DWORD pid, LPTSTR lpsz)
  741. {
  742. LPRSI lprsi=(LPRSI)lp;
  743. STANDARDSECINMEM FAR* lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  744. int i;
  745. if (pid==PID_APPNAME) {
  746. pid = MAXSTDZ-1;
  747. } else if (pid<PID_TITLE || pid>PID_REVNUMBER) return 0; else pid -= 2;
  748. OleDbgAssert(lpSSIM);
  749. if (lpSSIM->rglpsz[pid]) MemFree(lpSSIM->rglpsz[pid]);
  750. if ((lpsz==NULL)||(*lpsz==0)) {
  751. lpSSIM->rglpsz[pid] = NULL;
  752. return (1);
  753. }
  754. i = _fstrlen(lpsz);
  755. lpSSIM->rglpsz[pid] = (STDZ FAR*)MemAlloc((i+1/*null*/)*sizeof(TCHAR)+
  756. sizeof(DWORD)*2);
  757. if (lpSSIM->rglpsz[pid]==NULL) return 0;
  758. _fstrcpy((LPTSTR)&lpSSIM->rglpsz[pid]->rgchars, lpsz);
  759. lpSSIM->rglpsz[pid]->vtType = VT_LPSTR;
  760. lpSSIM->rglpsz[pid]->vtByteCount = 0;
  761. lpSSIM->rglpsz[pid]->VTCB = i;
  762. return (1);
  763. }
  764. /*************************************************************************
  765. **
  766. ** OleStdGetStringZProperty
  767. **
  768. ** Purpose:
  769. ** Retrieve a String Propety.
  770. ** (returns zero-terminated with leading byte count string)
  771. **
  772. ** Parameters:
  773. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  774. ** DWORD pid - ID of Property
  775. **
  776. ** Return Value:
  777. ** LPSTZR - value of String Property
  778. ** (zero-terminated with leading
  779. ** byte count)
  780. **
  781. ** Comments:
  782. ** String should NOT be freed by caller. Memory for string will be
  783. ** freed when OleStdFreeSummaryInfo is called.
  784. *************************************************************************/
  785. STDAPI_(LPSTZR) OleStdGetStringZProperty(LPSUMINFO lp, DWORD pid)
  786. {
  787. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  788. if (pid==PID_APPNAME) {
  789. pid = MAXSTDZ-1;
  790. } else if (pid<PID_TITLE || pid>PID_REVNUMBER) return NULL; else pid -= 2;
  791. if (lpSSIM->rglpsz[pid]!=NULL) {
  792. return (LPTSTR)&lpSSIM->rglpsz[pid]->VTCB;
  793. }
  794. return NULL;
  795. }
  796. /*************************************************************************
  797. **
  798. ** OleStdGetDocProperty
  799. **
  800. ** Purpose:
  801. ** Retrieve document properties (no. pages, no. words, no. characters)
  802. **
  803. ** Parameters:
  804. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  805. ** DWORD FAR *nPage - (OUT) number of pages in document
  806. ** DWORD FAR *nWords - (OUT) number of words in document
  807. ** DWORD FAR *nChars - (OUT) number of charactrs in doc
  808. **
  809. ** Return Value:
  810. ** void
  811. **
  812. ** Comments:
  813. **
  814. *************************************************************************/
  815. STDAPI_(void) OleStdGetDocProperty(
  816. LPSUMINFO lp,
  817. DWORD FAR* nPage,
  818. DWORD FAR* nWords,
  819. DWORD FAR* nChars
  820. )
  821. {
  822. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  823. *nPage=0; *nWords=0; *nChars=0;
  824. if (lpSSIM->rgInts[0].vtType == VT_I4) *nPage = lpSSIM->rgInts[0].value;
  825. if (lpSSIM->rgInts[1].vtType == VT_I4) *nWords = lpSSIM->rgInts[1].value;
  826. if (lpSSIM->rgInts[2].vtType == VT_I4) *nChars = lpSSIM->rgInts[2].value;
  827. }
  828. /*************************************************************************
  829. **
  830. ** OleStdSetDocProperty
  831. **
  832. ** Purpose:
  833. ** Set document properties (no. pages, no. words, no. characters)
  834. **
  835. ** Parameters:
  836. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  837. ** DWORD nPage - number of pages in document
  838. ** DWORD nWords - number of words in document
  839. ** DWORD nChars - number of charactrs in doc
  840. **
  841. ** Return Value:
  842. ** int - 1 for success
  843. ** - 0 if error occurs
  844. ** (there are no errors)
  845. **
  846. ** Comments:
  847. **
  848. *************************************************************************/
  849. STDAPI_(int) OleStdSetDocProperty(
  850. LPSUMINFO lp,
  851. DWORD nPage,
  852. DWORD nWords,
  853. DWORD nChars
  854. )
  855. {
  856. DWORD vttype=VT_I4;
  857. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  858. if ((nPage|nWords|nChars)==0) {
  859. vttype = VT_EMPTY;
  860. nPage=0; nWords=0; nChars=0;
  861. }
  862. lpSSIM->rgInts[0].vtType = vttype;
  863. lpSSIM->rgInts[1].vtType = vttype;
  864. lpSSIM->rgInts[2].vtType = vttype;
  865. lpSSIM->rgInts[0].value = nPage;
  866. lpSSIM->rgInts[1].value = nWords;
  867. lpSSIM->rgInts[2].value = nChars;
  868. return 1;
  869. }
  870. /*************************************************************************
  871. **
  872. ** OleStdGetThumbNailProperty
  873. **
  874. ** Purpose:
  875. ** Retrieve a Thumbnail Property
  876. **
  877. ** Parameters:
  878. ** LPSTREAM lps
  879. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  880. ** DWORD FAR* clipFormatNo - clipboard format for thumbnail
  881. ** (type of value depends on vtcf
  882. ** return value.)
  883. ** NOTE: ONLY VT_CF_WIN is
  884. ** implemented, so clipFormatNo
  885. ** will be CF_METAFILEPICT
  886. ** LPTSTR FAR* lpszName - format name if VT_CF_NAME is
  887. ** returned
  888. ** NOTE: NOT IMPLEMENTED
  889. ** THUMBNAIL FAR* clip - handle to thumbnail
  890. ** for VT_CF_WIN clip will be
  891. ** handle to MetafilePict
  892. ** NOTE: only VT_CF_WIN IMPLEMENTED
  893. ** DWORD FAR* byteCount - size of thumbnail stream
  894. ** for VT_CF_WIN case this should
  895. ** be combined size of both the
  896. ** Metafile as well as the
  897. ** MetafilePict structure.
  898. ** BOOL transferClip - transfer ownership of thumbnail
  899. ** to caller. (see comment)
  900. **
  901. ** Return Value:
  902. ** int vtcfNo - OLE thumbnail selector value
  903. ** VT_CF_WIN - Windows thumbnail
  904. ** (interpret clipFormatNo as
  905. ** Windows clipboard format)
  906. ** VT_CF_FMTID - (NOT IMPLEMENTED)
  907. ** thumbnail format is specified
  908. ** by ID. use clipFormatNo.
  909. ** (but NOT a Windows format ID)
  910. **
  911. ** VT_CF_NAME - (NOT IMPLEMENTED)
  912. ** thumbnail format is specified
  913. ** by name. use lpszName.
  914. ** VT_CF_EMPTY - blank thumbnail
  915. ** (clip will be NULL)
  916. ** VT_CF_OOM - Memory allocation failure
  917. **
  918. ** Comments:
  919. ** NOTE: Currently there is only proper support for VT_CF_WIN.
  920. ** OleStdSetThumbNailProperty does implement VT_CF_FMTID and VT_CF_NAME,
  921. ** however, OleStdGetThumbNailProperty, OleStdReadSummaryInfo and
  922. ** OleStdWriteSummaryInfo only support VT_CF_WIN.
  923. **
  924. ** Note that on input, the thumbnail is read on demand while all the
  925. ** other properties are pre-loaded. The thumbnail is manipulated as
  926. ** a windows handle to a METAFILEPICT structure, which in turn
  927. ** contains a handle to the METAFILE. The transferClip argument on
  928. ** GetThumbNail, when set to true, transfers responsibility for
  929. ** storage management of the thumbnail to the caller; that is, after
  930. ** OleStdFreeSummaryInfo has been called, the handle is still valid.
  931. *************************************************************************/
  932. STDAPI_(int) OleStdGetThumbNailProperty(
  933. LPSTREAM lps,
  934. LPSUMINFO lp,
  935. DWORD FAR* clipFormatNo,
  936. LPTSTR FAR* lpszName,
  937. THUMBNAIL FAR* clip,
  938. DWORD FAR* byteCount,
  939. BOOL transferClip
  940. )
  941. {
  942. int i;
  943. LPRSI lprsi=(LPRSI)lp;
  944. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  945. ULONG cbRead, cbToRead;
  946. LARGE_INTEGER a;
  947. ULARGE_INTEGER b;
  948. CHAR FAR *lpst;
  949. LPMETAFILEPICT lpmfp;
  950. HANDLE hst, hmfp;
  951. SCODE sc;
  952. *byteCount = 0;
  953. if (lpSSIM->thumb.cBytes==0) return VT_CF_EMPTY;
  954. if (lpSSIM->thumb.lpByte==NULL) {
  955. LISet32(a, lprsi->fileOffset);
  956. sc = GetScode(lps->Seek(a, STREAM_SEEK_SET, &b));
  957. if (FAILED(sc)) return VT_CF_EMPTY;
  958. i = (int) lpSSIM->thumb.selector;
  959. if (i>0||i==VT_CF_FMTID) {
  960. if (i>255) return VT_CF_EMPTY;
  961. else if (i==VT_CF_FMTID) i = sizeof(FMTID);
  962. else lpSSIM->thumb.selector = VT_CF_NAME;
  963. cbToRead = ((i+3)>>2)<<2;
  964. lpSSIM->thumb.lpstzName=(CHAR FAR*)MemAlloc(i+1/*n*/+1);
  965. if (lpSSIM->thumb.lpstzName==NULL) return VT_CF_OOM;
  966. sc = GetScode(lps->Read(lpSSIM->thumb.lpstzName+1, cbToRead, &cbRead));
  967. if (FAILED(sc)||cbRead!=cbToRead) return VT_CF_EMPTY;
  968. *lpSSIM->thumb.lpstzName = i;
  969. *(lpSSIM->thumb.lpstzName+i) = 0;
  970. lpSSIM->thumb.cBytes -= cbToRead+sizeof(DWORD);
  971. }
  972. i = (int) lpSSIM->thumb.selector;
  973. cbToRead = lpSSIM->thumb.cBytes;
  974. if (cbToRead>65535) return VT_CF_OOM;
  975. OleDbgAssert(i!=VT_CF_NAME);
  976. if (i==VT_CF_WIN) {
  977. cbToRead -= sizeof(METAFILEPICT);
  978. hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
  979. if (hmfp==NULL) return VT_CF_OOM;
  980. hst = GlobalAlloc(GMEM_MOVEABLE, cbToRead);
  981. if (hst==NULL) {
  982. GlobalFree(hmfp);
  983. return VT_CF_OOM;
  984. }
  985. lpmfp = (LPMETAFILEPICT)GlobalLock(hmfp);
  986. sc = GetScode(lps->Read(lpmfp, sizeof(METAFILEPICT), &cbRead));
  987. if (FAILED(sc)||cbRead!=sizeof(METAFILEPICT)) {
  988. GlobalUnlock(hmfp);
  989. GlobalFree(hmfp);
  990. GlobalFree(hst);
  991. return VT_CF_EMPTY;
  992. }
  993. lpst = (CHAR FAR*)GlobalLock(hst);
  994. lpmfp->hMF = (HMETAFILE)hst;
  995. lpSSIM->thumb.lpByte = (CHAR FAR*)hmfp;
  996. } else {
  997. lpst =(CHAR FAR*)MemAlloc((int)cbToRead);
  998. if (lpst==NULL) return VT_CF_OOM;
  999. lpSSIM->thumb.lpByte = lpst;
  1000. }
  1001. sc = GetScode(lps->Read(lpst, cbToRead, &cbRead));
  1002. if (i==VT_CF_WIN) {
  1003. GlobalUnlock(hst);
  1004. GlobalUnlock(hmfp);
  1005. }
  1006. if (FAILED(sc)||cbRead!=cbToRead) {
  1007. if (i==VT_CF_WIN) {
  1008. GlobalFree(hst);
  1009. GlobalFree(hmfp);
  1010. } else MemFree(lpst);
  1011. lpSSIM->thumb.lpByte = NULL;
  1012. if ((i==VT_CF_NAME||i==VT_CF_FMTID)&&(lpSSIM->thumb.lpstzName!=NULL))
  1013. MemFree(lpSSIM->thumb.lpstzName);
  1014. return VT_CF_EMPTY;
  1015. }
  1016. }
  1017. *clipFormatNo = lpSSIM->thumb.clipFormat;
  1018. *byteCount = lpSSIM->thumb.cBytes;
  1019. if(lpszName!=NULL)
  1020. *lpszName = (TCHAR FAR*)lpSSIM->thumb.lpstzName+1;
  1021. *clip = (TCHAR FAR*)lpSSIM->thumb.lpByte;
  1022. if (transferClip) lpSSIM->thumb.lpByte=NULL;
  1023. return (int)lpSSIM->thumb.selector;
  1024. }
  1025. /*************************************************************************
  1026. **
  1027. ** OleStdSetThumbNailProperty
  1028. **
  1029. ** Purpose:
  1030. ** Set a Thumbnail Property
  1031. **
  1032. ** Parameters:
  1033. ** LPSTREAM lps - open SummaryInfo IStream*
  1034. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  1035. ** int vtcfNo - OLE thumbnail selector value
  1036. ** VT_CF_WIN - Windows thumbnail
  1037. ** (interpret clipFormatNo as
  1038. ** Windows clipboard format)
  1039. ** VT_CF_FMTID - thumbnail format is specified
  1040. ** by ID. use clipFormatNo.
  1041. ** (but NOT a Windows format ID)
  1042. **
  1043. ** VT_CF_NAME - thumbnail format is specified
  1044. ** by name. use lpszName.
  1045. ** VT_CF_EMPTY - blank thumbnail
  1046. ** (clip will be NULL)
  1047. **
  1048. ** DWORD FAR* clipFormatNo - clipboard format for thumbnail
  1049. ** used if vtcfNo is VT_CF_WIN or
  1050. ** VT_CF_FMTID. interpretation of
  1051. ** value depends on vtcfNo specified.
  1052. ** (normally vtcfNo==VT_CF_WIN and
  1053. ** clipFormatNo==CF_METAFILEPICT)
  1054. ** LPSTR FAR* lpszName - format name if vtcfNo is VT_CF_NAME
  1055. ** THUMBNAIL clip - handle to thumbnail
  1056. ** for VT_CF_WIN clip will be
  1057. ** handle to MetafilePict
  1058. ** DWORD FAR* byteCount - size of thumbnail stream
  1059. ** for VT_CF_WIN case this should
  1060. ** be combined size of both the
  1061. ** Metafile as well as the
  1062. ** MetafilePict structure.
  1063. **
  1064. ** Return Value:
  1065. ** int - 1 for success
  1066. ** - 0 if error occurs
  1067. **
  1068. ** Comments:
  1069. ** NOTE: Currently there is only proper support for VT_CF_WIN.
  1070. ** OleStdSetThumbNailProperty does implement VT_CF_FMTID and VT_CF_NAME,
  1071. ** however, OleStdGetThumbNailProperty, OleStdReadSummaryInfo and
  1072. ** OleStdWriteSummaryInfo only support VT_CF_WIN.
  1073. **
  1074. ** This function copies lpszName but saves the "clip" handle passed.
  1075. **
  1076. ** NOTE: overwriting or emptying frees space for clip and name.
  1077. ** The thumbnail is manipulated as a windows handle to a
  1078. ** METAFILEPICT structure, which in turn contains a handle to the
  1079. ** METAFILE.
  1080. *************************************************************************/
  1081. STDAPI_(int) OleStdSetThumbNailProperty(
  1082. LPSTREAM lps,
  1083. LPSUMINFO lp,
  1084. int vtcfNo,
  1085. DWORD clipFormatNo,
  1086. LPTSTR lpszName,
  1087. THUMBNAIL clip,
  1088. DWORD byteCount
  1089. )
  1090. {
  1091. int i;
  1092. LPRSI lprsi=(LPRSI)lp;
  1093. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  1094. LPMETAFILEPICT lpmfp;
  1095. if (lpSSIM==NULL||vtcfNo>0||vtcfNo<VT_CF_EMPTY||(vtcfNo==VT_CF_NAME&&(lpszName==NULL||*lpszName==0))) {
  1096. return 0;
  1097. }
  1098. if (vtcfNo!=VT_CF_EMPTY&&(clip==0||byteCount==0)) return 0;
  1099. i = (int) lpSSIM->thumb.vtType;
  1100. if (i!=VT_EMPTY) {
  1101. i = (int) lpSSIM->thumb.selector;
  1102. OleDbgAssert(i!=VT_CF_NAME);
  1103. if (i==VT_CF_WIN) {
  1104. if (lpSSIM->thumb.lpByte!=NULL) {
  1105. lpmfp = (LPMETAFILEPICT)GlobalLock((HANDLE)(DWORD)lpSSIM->thumb.lpByte);
  1106. GlobalFree(lpmfp->hMF);
  1107. GlobalUnlock((HANDLE)(DWORD)lpSSIM->thumb.lpByte);
  1108. GlobalFree((HANDLE)(DWORD)lpSSIM->thumb.lpByte);
  1109. }
  1110. } else {
  1111. MemFree(lpSSIM->thumb.lpByte);
  1112. }
  1113. if ((i==VT_CF_NAME||i==VT_CF_FMTID)&&(lpSSIM->thumb.lpstzName!=NULL))
  1114. MemFree(lpSSIM->thumb.lpstzName);
  1115. lpSSIM->thumb.lpstzName = NULL;
  1116. lpSSIM->thumb.lpByte = NULL;
  1117. }
  1118. if (vtcfNo==VT_CF_EMPTY) {
  1119. lpSSIM->thumb.vtType = VT_EMPTY;
  1120. lpSSIM->thumb.cBytes = 0;
  1121. } else {
  1122. lpSSIM->thumb.vtType = VT_CF;
  1123. lpSSIM->thumb.selector = vtcfNo;
  1124. lpSSIM->thumb.cBytes = byteCount;
  1125. lpSSIM->thumb.clipFormat = clipFormatNo;
  1126. lpSSIM->thumb.lpByte = (CHAR FAR*)clip; //just save the hnadle
  1127. if (vtcfNo==VT_CF_NAME||vtcfNo==VT_CF_FMTID) {
  1128. i = _fstrlen(lpszName);
  1129. if (vtcfNo==VT_CF_FMTID) OleDbgAssert(i*sizeof(TCHAR)==sizeof(FMTID));
  1130. lpSSIM->thumb.lpstzName =
  1131. (CHAR FAR*)MemAlloc((i+1/*n*/+1/*null*/)*sizeof(TCHAR));
  1132. if (lpSSIM->thumb.lpstzName==NULL) {
  1133. lpSSIM->thumb.vtType = VT_EMPTY;
  1134. return 0;
  1135. }
  1136. _fstrcpy((TCHAR FAR*)lpSSIM->thumb.lpstzName+1, lpszName);
  1137. *lpSSIM->thumb.lpstzName = i;
  1138. }
  1139. }
  1140. return 1;
  1141. }
  1142. /*************************************************************************
  1143. **
  1144. ** OleStdGetDateProperty
  1145. **
  1146. ** Purpose:
  1147. ** Retrieve Data Property
  1148. **
  1149. ** Parameters:
  1150. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  1151. ** DWORD pid - ID of Property
  1152. ** int FAR *yr - (OUT) year
  1153. ** int FAR *mo - (OUT) month
  1154. ** int FAR *dy - (OUT) day
  1155. ** DWORD FAR *sc - (OUT) seconds
  1156. **
  1157. ** Return Value:
  1158. ** void
  1159. **
  1160. ** Comments:
  1161. **
  1162. *************************************************************************/
  1163. STDAPI_(void) OleStdGetDateProperty(
  1164. LPSUMINFO lp,
  1165. DWORD pid,
  1166. int FAR* yr,
  1167. int FAR* mo,
  1168. int FAR* dy,
  1169. DWORD FAR* sc
  1170. )
  1171. {
  1172. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  1173. SFFS sffs;
  1174. pid -= PID_EDITTIME;
  1175. *yr = 0; *mo = 0; *dy = 0; *sc = 0;
  1176. if (pid<0||pid>=MAXTIME) return;
  1177. if (lpSSIM->rgTime[pid].vtType == VT_FILETIME) {
  1178. if (pid==0) {
  1179. //convert from 100ns to seconds
  1180. ulargeDivide((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 10000);
  1181. ulargeDivide((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 1000);
  1182. pid = lpSSIM->rgTime[0].time.dwLowDateTime;
  1183. *sc = pid%((DWORD)60*60*24);
  1184. pid /= (DWORD)60*60*24;
  1185. *dy = (int)(pid%(DWORD)30);
  1186. pid /= (DWORD)30;
  1187. *mo = (int)(pid%(DWORD)12);
  1188. *yr = (int)(pid/(DWORD)12);
  1189. } else {
  1190. if (CoFileTimeToDosDateTime(&lpSSIM->rgTime[pid].time,
  1191. &sffs.dateVariable, &sffs.timeVariable)) {
  1192. *yr = sffs.yr+1980;
  1193. *mo = sffs.mon;
  1194. *dy = sffs.dom;
  1195. *sc = (DWORD)sffs.hr*3600+sffs.mint*60+sffs.sec*2;
  1196. }
  1197. }
  1198. }
  1199. return;
  1200. }
  1201. /*************************************************************************
  1202. **
  1203. ** OleStdSetDateProperty
  1204. **
  1205. ** Purpose:
  1206. ** Set Data Property
  1207. **
  1208. ** Parameters:
  1209. ** LPSUMINFO FAR *lp - pointer to open Summary Info struct
  1210. ** DWORD pid - ID of Property
  1211. ** int yr - year
  1212. ** int mo - month
  1213. ** int dy - day
  1214. ** DWORD sc - seconds
  1215. **
  1216. ** Return Value:
  1217. ** int - 1 for success
  1218. ** - 0 if error occurs
  1219. **
  1220. ** Comments:
  1221. ** Use all zeros to clear.
  1222. ** The following is an example of valid input:
  1223. ** yr=1993 mo=1(Jan) dy=1(1st) hr=12(noon) mn=30 sc=23
  1224. ** for PID_EDITTIME property, the values are a zero-origin duration
  1225. ** of time.
  1226. **
  1227. *************************************************************************/
  1228. STDAPI_(int) OleStdSetDateProperty(
  1229. LPSUMINFO lp,
  1230. DWORD pid,
  1231. int yr,
  1232. int mo,
  1233. int dy,
  1234. int hr,
  1235. int mn,
  1236. int sc
  1237. )
  1238. {
  1239. STANDARDSECINMEM FAR *lpSSIM=(STANDARDSECINMEM FAR*)&((LPRSI)lp)->section;
  1240. SFFS sffs;
  1241. pid -= PID_EDITTIME;
  1242. if (pid<0||pid>=MAXTIME) return 0;
  1243. if ((yr|mo|dy|hr|mn|sc)==0) { //all must be zero
  1244. lpSSIM->rgTime[pid].vtType = VT_EMPTY;
  1245. return 1;
  1246. }
  1247. lpSSIM->rgTime[pid].vtType = VT_FILETIME;
  1248. if (pid==0) {
  1249. lpSSIM->rgTime[0].time.dwLowDateTime =
  1250. (((((DWORD)yr*365+mo*30)+dy)*24+hr)*60+mn)*60+sc;
  1251. lpSSIM->rgTime[0].time.dwHighDateTime = 0;
  1252. //10^7 nanoseconds/second
  1253. ulargeMultiply((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 10000);
  1254. //convert to units of 100 ns
  1255. ulargeMultiply((ULARGE_INTEGER FAR*)&lpSSIM->rgTime[0].time, 1000);
  1256. } else {
  1257. sffs.yr = max(yr-1980,0);
  1258. sffs.mon = mo;
  1259. sffs.dom = dy;
  1260. sffs.hr = hr;
  1261. sffs.mint= mn;
  1262. sffs.sec = sc/2; //dos is 2 second intervals
  1263. if (!CoDosDateTimeToFileTime(sffs.date, sffs.time,
  1264. &lpSSIM->rgTime[pid].time)) {
  1265. lpSSIM->rgTime[pid].vtType = VT_EMPTY;
  1266. return 0;
  1267. }
  1268. }
  1269. return 1;
  1270. }
  1271. } //END C