Leaked source code of windows server 2003
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.

506 lines
17 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993
  5. //
  6. // File: ntprop.cxx
  7. //
  8. // Contents: OLE Appendix B property set support.
  9. //
  10. // History: 28-Nov-94 vich created
  11. // 15-Jul-96 MikeHill - PropSetNames: WCHAR=>OLECHAR, byte-swapping.
  12. // - Added special-cases for PictureIt! propsets.
  13. // 06-May-98 MikeHill - In PropertySetNameToGuid, disallow
  14. // a string-ized well-known GUID.
  15. //
  16. //---------------------------------------------------------------------------
  17. #include <pch.cxx>
  18. #include <olechar.h>
  19. #define CCH_MAP (1 << CBIT_CHARMASK) // 32
  20. #define CHARMASK (CCH_MAP - 1) // 0x1f
  21. // we use static array instead of string literals because some systems
  22. // have 4 bytes string literals, and would not produce the correct result
  23. // for REF's 2 byte Unicode convention
  24. //
  25. OLECHAR aocMap[CCH_MAP + 1] = {'a','b','c','d','e','f','g',
  26. 'h','i','j','k','l','m','n',
  27. 'o','p','q','r','s','t','u',
  28. 'v','w','x','y','z',
  29. '0','1','2','3','4','5','\0'};
  30. #define CALPHACHARS (1 + (OLECHAR)'z' - (OLECHAR)'a')
  31. GUID guidSummary =
  32. { 0xf29f85e0,
  33. 0x4ff9, 0x1068,
  34. { 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9 } };
  35. OLECHAR oszSummary[] = {'S','u','m','m','a','r','y',
  36. 'I','n','f','o','r','m','a','t','i','o','n','\0'};
  37. GUID guidDocumentSummary =
  38. { 0xd5cdd502,
  39. 0x2e9c, 0x101b,
  40. { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };
  41. OLECHAR oszDocumentSummary[] = {'D','o','c','u','m','e','n','t',
  42. 'S','u','m','m','a','r','y',
  43. 'I','n','f','o','r','m','a','t','i','o','n',
  44. '\0'};
  45. // Note that user defined properties are placed in section 2 with the below
  46. // GUID as the FMTID -- alas, we did not expect Office95 to actually use it.
  47. GUID guidDocumentSummarySection2 =
  48. { 0xd5cdd505,
  49. 0x2e9c, 0x101b,
  50. { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };
  51. // *Global Info*
  52. OLECHAR oszGlobalInfo[] = {'G','l','o','b','a','l',' ','I','n','f','o','\0'};
  53. GUID guidGlobalInfo =
  54. { 0x56616F00,
  55. 0xC154, 0x11ce,
  56. { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
  57. // *Image Contents*
  58. OLECHAR oszImageContents[] = {'I','m','a','g','e',' ',
  59. 'C','o','n','t','e','n','t','s','\0'};
  60. GUID guidImageContents =
  61. { 0x56616400,
  62. 0xC154, 0x11ce,
  63. { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
  64. // *Image Info*
  65. OLECHAR oszImageInfo[] = {'I','m','a','g','e',' ','I','n','f','o','\0'};
  66. GUID guidImageInfo =
  67. { 0x56616500,
  68. 0xC154, 0x11ce,
  69. { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
  70. __inline OLECHAR
  71. MapChar(IN ULONG i)
  72. {
  73. return((OLECHAR) aocMap[i & CHARMASK]);
  74. }
  75. //+--------------------------------------------------------------------------
  76. // Function: PrGuidToPropertySetName
  77. //
  78. // Synopsis: Map property set GUID to null-terminated UNICODE name string.
  79. //
  80. // The awcname parameter is assumed to be a buffer with room for
  81. // CWC_PROPSETSZ (28) UNICODE characters. The first character
  82. // is always WC_PROPSET0 (0x05), as specified by the OLE Appendix
  83. // B documentation. The colon character normally used as an NT
  84. // stream name separator is not written to the caller's buffer.
  85. //
  86. // No error is possible.
  87. //
  88. // Arguments: IN GUID *pguid -- pointer to GUID to convert
  89. // OUT OLECHAR aocname[] -- output string buffer
  90. //
  91. // Returns: count of non-NULL characters in the output string buffer
  92. //---------------------------------------------------------------------------
  93. WINOLEAPI_(ULONG)
  94. PrGuidToPropertySetName(
  95. IN GUID const *pguid,
  96. OUT OLECHAR aocname[])
  97. {
  98. ULONG cbitRemain = CBIT_BYTE;
  99. OLECHAR *poc = aocname;
  100. BYTE *pb;
  101. BYTE *pbEnd;
  102. *poc++ = OC_PROPSET0;
  103. // -----------------------
  104. // Check for special-cases
  105. // -----------------------
  106. // Note: CCH_PROPSET includes the OC_PROPSET0, and sizeof(osz...)
  107. // includes the trailing '\0', so sizeof(osz...) is ok because the
  108. // OC_PROPSET0 character compensates for the trailing NULL character.
  109. // Is this the SummaryInformation propset?
  110. PROPASSERT(CCH_PROPSET >= sizeof(oszSummary)/sizeof(OLECHAR));
  111. if (*pguid == guidSummary)
  112. {
  113. RtlCopyMemory(poc, oszSummary, sizeof(oszSummary));
  114. return(sizeof(oszSummary)/sizeof(OLECHAR));
  115. }
  116. // Is this The DocumentSummaryInformation or User-Defined propset?
  117. PROPASSERT(CCH_PROPSET >= sizeof(oszDocumentSummary)/sizeof(OLECHAR));
  118. if (*pguid == guidDocumentSummary || *pguid == guidDocumentSummarySection2)
  119. {
  120. RtlCopyMemory(poc, oszDocumentSummary, sizeof(oszDocumentSummary));
  121. return(sizeof(oszDocumentSummary)/sizeof(OLECHAR));
  122. }
  123. // Is this the Global Info propset?
  124. PROPASSERT(CCH_PROPSET >= sizeof(oszGlobalInfo)/sizeof(OLECHAR));
  125. if (*pguid == guidGlobalInfo)
  126. {
  127. RtlCopyMemory(poc, oszGlobalInfo, sizeof(oszGlobalInfo));
  128. return(sizeof(oszGlobalInfo)/sizeof(OLECHAR));
  129. }
  130. // Is this the Image Contents propset?
  131. PROPASSERT(CCH_PROPSET >= sizeof(oszImageContents)/sizeof(OLECHAR));
  132. if (*pguid == guidImageContents)
  133. {
  134. RtlCopyMemory(poc, oszImageContents, sizeof(oszImageContents));
  135. return(sizeof(oszImageContents)/sizeof(OLECHAR));
  136. }
  137. // Is this the Image Info propset?
  138. PROPASSERT(CCH_PROPSET >= sizeof(oszImageInfo)/sizeof(OLECHAR));
  139. if (*pguid == guidImageInfo)
  140. {
  141. RtlCopyMemory(poc, oszImageInfo, sizeof(oszImageInfo));
  142. return(sizeof(oszImageInfo)/sizeof(OLECHAR));
  143. }
  144. // ------------------------------
  145. // Calculate the string-ized GUID
  146. // ------------------------------
  147. // If this is a big-endian system, we need to convert
  148. // the GUID to little-endian for the conversion.
  149. #if BIGENDIAN
  150. GUID guidByteSwapped = *pguid;
  151. PropByteSwap( &guidByteSwapped );
  152. pguid = &guidByteSwapped;
  153. #endif
  154. // Point to the beginning and ending of the GUID
  155. pb = (BYTE*) pguid;
  156. pbEnd = pb + sizeof(*pguid);
  157. // Walk 'pb' through each byte of the GUID.
  158. while (pb < pbEnd)
  159. {
  160. // Get the value of the current byte, shifting down to
  161. // get at the bits which we haven't looked at yet.
  162. ULONG i = *pb >> (CBIT_BYTE - cbitRemain);
  163. // Does the currenty byte of the GUID have at least 5 bits
  164. // that we haven't looked at yet?
  165. if (cbitRemain >= CBIT_CHARMASK)
  166. {
  167. // Yes, we have enough bits. Map 5 of them to a character.
  168. *poc = MapChar(i);
  169. // If this is a byte boundary, uppercase the letter
  170. // (Don't know why, maybe to help debug?)
  171. if (cbitRemain == CBIT_BYTE && *poc >= (OLECHAR)'a'
  172. && *poc <= ((OLECHAR)'z'))
  173. {
  174. *poc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a') );
  175. }
  176. // Advance the output pointer
  177. poc++;
  178. // Decrement the count of interesting bits in this byte.
  179. cbitRemain -= CBIT_CHARMASK;
  180. // If we just used up the last bit in this byte, move on
  181. // to the next byte.
  182. if (cbitRemain == 0)
  183. {
  184. pb++;
  185. cbitRemain = CBIT_BYTE;
  186. }
  187. } // if (cbitRemain >= CBIT_CHARMASK)
  188. // Otherwise, we need to advance pb to the next byte.
  189. else
  190. {
  191. // Advance pb to the next byte.
  192. if (++pb < pbEnd)
  193. {
  194. // We haven't gone off the end of the GUID, so
  195. // add bits from the new byte to i (add them above
  196. // the interesting bits from the previous byte
  197. // which are already in i).
  198. i |= *pb << cbitRemain;
  199. }
  200. // Put the next character into the output string.
  201. // Note that on the last byte, we'll have less than
  202. // 5 bits in i (but the bits above cbitRemain will
  203. // be zero).
  204. *poc++ = MapChar(i);
  205. // Add 3 to the count of remaining interesting bits
  206. // in this new byte. E.g. if we brought over 1 bit
  207. // from the previous byte, then we used 4 bits from
  208. // this new byte, and we have 1+3=4 bits left in this
  209. // byte.
  210. cbitRemain += CBIT_BYTE - CBIT_CHARMASK;
  211. }
  212. } // while (pb < pbEnd)
  213. // Terminate the string and return its cch.
  214. *poc = OLESTR( '\0' );
  215. return(CCH_PROPSET);
  216. }
  217. //+--------------------------------------------------------------------------
  218. // Function: PrPropertySetNameToGuid
  219. //
  220. // Synopsis: Map non null-terminated UNICODE string to a property set GUID.
  221. //
  222. // If the name is not properly formed as per
  223. // PrGuidToPropertySetName(), STATUS_INVALID_PARAMETER is
  224. // returned. The pguid parameter is assumed to point to a buffer
  225. // with room for a GUID structure.
  226. //
  227. // Arguments: IN ULONG cocname -- count of OLECHARs in string to convert
  228. // IN OLECHAR aocname[] -- input string to convert
  229. // OUT GUID *pguid -- pointer to buffer for converted GUID
  230. //
  231. // Returns: NTSTATUS
  232. //---------------------------------------------------------------------------
  233. NTSTATUS
  234. PrPropertySetNameToGuid(
  235. IN ULONG cocname,
  236. IN OLECHAR const aocname[],
  237. OUT GUID *pguid)
  238. {
  239. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  240. GUID guidReturn = GUID_NULL;
  241. OLECHAR const *poc = aocname;
  242. if (poc[0] == OC_PROPSET0)
  243. {
  244. // -----------------------
  245. // Check for Special-Cases
  246. // -----------------------
  247. // Note: cocname includes the OC_PROPSET0, and sizeof(osz...)
  248. // includes the trailing OLESTR('\0'), but the comparison excludes both
  249. // the leading OC_PROPSET0 and the trailing '\0'.
  250. // Is this SummaryInformation?
  251. if (cocname == sizeof(oszSummary)/sizeof(OLECHAR) &&
  252. // MAC: Create a dfsocsnicmp or convert strings to WCHARs
  253. //ocsnicmp(&poc[1], oszSummary, cocname - 1) == 0)
  254. dfwcsnicmp(&poc[1], oszSummary, cocname - 1) == 0)
  255. {
  256. *pguid = guidSummary;
  257. return(STATUS_SUCCESS);
  258. }
  259. // Is this DocumentSummaryInformation?
  260. if (cocname == sizeof(oszDocumentSummary)/sizeof(OLECHAR) &&
  261. //ocsnicmp(&poc[1], oszDocumentSummary, cocname - 1) == 0)
  262. dfwcsnicmp(&poc[1], oszDocumentSummary, cocname - 1) == 0)
  263. {
  264. *pguid = guidDocumentSummary;
  265. return(STATUS_SUCCESS);
  266. }
  267. // Is this Global Info?
  268. if (cocname == sizeof(oszGlobalInfo)/sizeof(OLECHAR) &&
  269. //ocsnicmp(&poc[1], oszGlobalInfo, cocname - 1) == 0)
  270. dfwcsnicmp(&poc[1], oszGlobalInfo, cocname - 1) == 0)
  271. {
  272. *pguid = guidGlobalInfo;
  273. return(STATUS_SUCCESS);
  274. }
  275. // Is this Image Info?
  276. if (cocname == sizeof(oszImageInfo)/sizeof(OLECHAR) &&
  277. //ocsnicmp(&poc[1], oszImageInfo, cocname - 1) == 0)
  278. dfwcsnicmp(&poc[1], oszImageInfo, cocname - 1) == 0)
  279. {
  280. *pguid = guidImageInfo;
  281. return(STATUS_SUCCESS);
  282. }
  283. // Is this Image Contents?
  284. if (cocname == sizeof(oszImageContents)/sizeof(OLECHAR) &&
  285. //ocsnicmp(&poc[1], oszImageContents, cocname - 1) == 0)
  286. dfwcsnicmp(&poc[1], oszImageContents, cocname - 1) == 0)
  287. {
  288. *pguid = guidImageContents;
  289. return(STATUS_SUCCESS);
  290. }
  291. // ------------------
  292. // Calculate the GUID
  293. // ------------------
  294. // None of the special-cases hit, so we must calculate
  295. // the GUID from the name.
  296. if (cocname == CCH_PROPSET)
  297. {
  298. ULONG cbit;
  299. BYTE *pb = (BYTE *) &guidReturn - 1;
  300. RtlZeroMemory(&guidReturn, sizeof(guidReturn));
  301. // Loop through the output GUID, 5 bits at a time.
  302. for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK)
  303. {
  304. ULONG cbitStored;
  305. OLECHAR oc;
  306. // Calculate the number of bits in the current byte
  307. // that have already been used.
  308. ULONG cbitUsed = cbit % CBIT_BYTE;
  309. // If there are no bits remaining in this byte, move on to
  310. // the next byte.
  311. if (cbitUsed == 0)
  312. {
  313. pb++;
  314. }
  315. // Get the next character in the input string.
  316. // Assume it's an upper case character for now, then correct if
  317. // that doesn't work. (If it's lower case,
  318. // oc will be a very large number if it's a wchar,
  319. // a negative number if it's a char.)
  320. oc = *++poc - (OLECHAR)'A';
  321. if (oc > CALPHACHARS || oc < 0)
  322. {
  323. // oops, try lower case
  324. oc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a'));
  325. if (oc > CALPHACHARS || oc < 0)
  326. {
  327. // must be a digit
  328. oc += ((OLECHAR)'a') - ((OLECHAR)'0') + CALPHACHARS;
  329. if (oc > CHARMASK)
  330. {
  331. goto Exit; // invalid character
  332. }
  333. }
  334. }
  335. // Put at least some of the bits of this character into the
  336. // current byte.
  337. *pb |= (BYTE) (oc << cbitUsed);
  338. // How many of the bits of oc actually just went into *pb?
  339. cbitStored = min(CBIT_BYTE - cbitUsed, CBIT_CHARMASK);
  340. // If the translated bits wouldn't all fit in the current byte,
  341. // put then into the next byte (advancing pb).
  342. if( cbitStored < CBIT_CHARMASK )
  343. {
  344. // Get the bits that didn't go into *pb in to the
  345. // low-order bits of oc.
  346. oc >>= CBIT_BYTE - cbitUsed;
  347. // Have we already filled the ouput GUID?
  348. if (cbit + cbitStored == CBIT_GUID)
  349. {
  350. // Yes. There should be nothing left in cb.
  351. if (oc != 0)
  352. {
  353. goto Exit; // extra bits (error)
  354. }
  355. break;
  356. }
  357. // Otherwise, advance pb to the next byte in the output GUID
  358. pb++;
  359. // Put the leftover bits of this character (that didn't fit
  360. // into the last byte) into this new byte.
  361. *pb |= (BYTE) oc;
  362. }
  363. } // for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK)
  364. Status = STATUS_SUCCESS;
  365. // If byte-swapping is necessary, do so now on the calculated
  366. // GUID.
  367. PropByteSwap( &guidReturn );
  368. } // if (cocname == CCH_PROPSET)
  369. } // if (poc[0] == OC_PROPSET0)
  370. // Ensure that the calculated GUID isn't one of the special ones. If it is,
  371. // then this is an error. We don't want to convert something to a GUID
  372. // that we can't convert back.
  373. if( guidSummary == guidReturn
  374. ||
  375. guidDocumentSummary == guidReturn
  376. ||
  377. guidGlobalInfo == guidReturn
  378. ||
  379. guidImageInfo == guidReturn
  380. ||
  381. guidImageContents == guidReturn
  382. )
  383. {
  384. return( STATUS_INVALID_PARAMETER );
  385. }
  386. // ----
  387. // Exit
  388. // ----
  389. Status = STATUS_SUCCESS; // Normalize results
  390. *pguid = guidReturn;
  391. Exit:
  392. return(Status);
  393. }