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.

436 lines
14 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. // These optionally-compiled directives tell the compiler & debugger
  20. // where the real file, rather than the copy, is located.
  21. #ifdef _ORIG_FILE_LOCATION_
  22. #if __LINE__ != 25
  23. #error File heading has change size
  24. #else
  25. #line 29 "\\nt\\private\\dcomidl\\ntprop.cxx"
  26. #endif
  27. #endif
  28. #define CCH_MAP (1 << CBIT_CHARMASK) // 32
  29. #define CHARMASK (CCH_MAP - 1) // 0x1f
  30. // we use static array instead of string literals because some systems
  31. // have 4 bytes string literals, and would not produce the correct result
  32. // for REF's 2 byte Unicode convention
  33. //
  34. OLECHAR aocMap[CCH_MAP + 1] = {'a','b','c','d','e','f','g',
  35. 'h','i','j','k','l','m','n',
  36. 'o','p','q','r','s','t','u',
  37. 'v','w','x','y','z',
  38. '0','1','2','3','4','5','\0'};
  39. #define CALPHACHARS (1 + (OLECHAR)'z' - (OLECHAR)'a')
  40. GUID guidSummary =
  41. { 0xf29f85e0,
  42. 0x4ff9, 0x1068,
  43. { 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9 } };
  44. OLECHAR oszSummary[] = {'S','u','m','m','a','r','y',
  45. 'I','n','f','o','r','m','a','t','i','o','n','\0'};
  46. GUID guidDocumentSummary =
  47. { 0xd5cdd502,
  48. 0x2e9c, 0x101b,
  49. { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };
  50. OLECHAR oszDocumentSummary[] = {'D','o','c','u','m','e','n','t',
  51. 'S','u','m','m','a','r','y',
  52. 'I','n','f','o','r','m','a','t','i','o','n',
  53. '\0'};
  54. // Note that user defined properties are placed in section 2 with the below
  55. // GUID as the FMTID -- alas, we did not expect Office95 to actually use it.
  56. GUID guidDocumentSummarySection2 =
  57. { 0xd5cdd505,
  58. 0x2e9c, 0x101b,
  59. { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };
  60. // *Global Info*
  61. OLECHAR oszGlobalInfo[] = {'G','l','o','b','a','l',' ','I','n','f','o','\0'};
  62. GUID guidGlobalInfo =
  63. { 0x56616F00,
  64. 0xC154, 0x11ce,
  65. { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
  66. // *Image Contents*
  67. OLECHAR oszImageContents[] = {'I','m','a','g','e',' ',
  68. 'C','o','n','t','e','n','t','s','\0'};
  69. GUID guidImageContents =
  70. { 0x56616400,
  71. 0xC154, 0x11ce,
  72. { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
  73. // *Image Info*
  74. OLECHAR oszImageInfo[] = {'I','m','a','g','e',' ','I','n','f','o','\0'};
  75. GUID guidImageInfo =
  76. { 0x56616500,
  77. 0xC154, 0x11ce,
  78. { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
  79. __inline OLECHAR
  80. MapChar(IN ULONG i)
  81. {
  82. return((OLECHAR) aocMap[i & CHARMASK]);
  83. }
  84. //+--------------------------------------------------------------------------
  85. // Function: PrGuidToPropertySetName
  86. //
  87. // Synopsis: Map property set GUID to null-terminated UNICODE name string.
  88. //
  89. // The awcname parameter is assumed to be a buffer with room for
  90. // CWC_PROPSETSZ (28) UNICODE characters. The first character
  91. // is always WC_PROPSET0 (0x05), as specified by the OLE Appendix
  92. // B documentation. The colon character normally used as an NT
  93. // stream name separator is not written to the caller's buffer.
  94. //
  95. // No error is possible.
  96. //
  97. // Arguments: IN GUID *pguid -- pointer to GUID to convert
  98. // OUT OLECHAR aocname[] -- output string buffer
  99. //
  100. // Returns: count of non-NULL characters in the output string buffer
  101. //---------------------------------------------------------------------------
  102. WINOLEAPI_(ULONG)
  103. PrGuidToPropertySetName(
  104. IN GUID const *pguid,
  105. OUT OLECHAR aocname[])
  106. {
  107. ULONG cbitRemain = CBIT_BYTE;
  108. OLECHAR *poc = aocname;
  109. BYTE *pb;
  110. BYTE *pbEnd;
  111. *poc++ = OC_PROPSET0;
  112. // -----------------------
  113. // Check for special-cases
  114. // -----------------------
  115. // Note: CCH_PROPSET includes the OC_PROPSET0, and sizeof(osz...)
  116. // includes the trailing '\0', so sizeof(osz...) is ok because the
  117. // OC_PROPSET0 character compensates for the trailing NULL character.
  118. // Is this the SummaryInformation propset?
  119. PROPASSERT(CCH_PROPSET >= sizeof(oszSummary)/sizeof(OLECHAR));
  120. if (*pguid == guidSummary)
  121. {
  122. RtlCopyMemory(poc, oszSummary, sizeof(oszSummary));
  123. return(sizeof(oszSummary)/sizeof(OLECHAR));
  124. }
  125. // Is this The DocumentSummaryInformation or User-Defined propset?
  126. PROPASSERT(CCH_PROPSET >= sizeof(oszDocumentSummary)/sizeof(OLECHAR));
  127. if (*pguid == guidDocumentSummary || *pguid == guidDocumentSummarySection2)
  128. {
  129. RtlCopyMemory(poc, oszDocumentSummary, sizeof(oszDocumentSummary));
  130. return(sizeof(oszDocumentSummary)/sizeof(OLECHAR));
  131. }
  132. // Is this the Global Info propset?
  133. PROPASSERT(CCH_PROPSET >= sizeof(oszGlobalInfo)/sizeof(OLECHAR));
  134. if (*pguid == guidGlobalInfo)
  135. {
  136. RtlCopyMemory(poc, oszGlobalInfo, sizeof(oszGlobalInfo));
  137. return(sizeof(oszGlobalInfo)/sizeof(OLECHAR));
  138. }
  139. // Is this the Image Contents propset?
  140. PROPASSERT(CCH_PROPSET >= sizeof(oszImageContents)/sizeof(OLECHAR));
  141. if (*pguid == guidImageContents)
  142. {
  143. RtlCopyMemory(poc, oszImageContents, sizeof(oszImageContents));
  144. return(sizeof(oszImageContents)/sizeof(OLECHAR));
  145. }
  146. // Is this the Image Info propset?
  147. PROPASSERT(CCH_PROPSET >= sizeof(oszImageInfo)/sizeof(OLECHAR));
  148. if (*pguid == guidImageInfo)
  149. {
  150. RtlCopyMemory(poc, oszImageInfo, sizeof(oszImageInfo));
  151. return(sizeof(oszImageInfo)/sizeof(OLECHAR));
  152. }
  153. // ------------------------------
  154. // Calculate the string-ized GUID
  155. // ------------------------------
  156. // If this is a big-endian system, we need to convert
  157. // the GUID to little-endian for the conversion.
  158. #if BIGENDIAN
  159. GUID guidByteSwapped = *pguid;
  160. PropByteSwap( &guidByteSwapped );
  161. pguid = &guidByteSwapped;
  162. #endif
  163. // Point to the beginning and ending of the GUID
  164. pb = (BYTE*) pguid;
  165. pbEnd = pb + sizeof(*pguid);
  166. // Walk 'pb' through each byte of the GUID.
  167. while (pb < pbEnd)
  168. {
  169. ULONG i = *pb >> (CBIT_BYTE - cbitRemain);
  170. if (cbitRemain >= CBIT_CHARMASK)
  171. {
  172. *poc = MapChar(i);
  173. if (cbitRemain == CBIT_BYTE && *poc >= (OLECHAR)'a'
  174. && *poc <= ((OLECHAR)'z'))
  175. {
  176. *poc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a') );
  177. }
  178. poc++;
  179. cbitRemain -= CBIT_CHARMASK;
  180. if (cbitRemain == 0)
  181. {
  182. pb++;
  183. cbitRemain = CBIT_BYTE;
  184. }
  185. }
  186. else
  187. {
  188. if (++pb < pbEnd)
  189. {
  190. i |= *pb << cbitRemain;
  191. }
  192. *poc++ = MapChar(i);
  193. cbitRemain += CBIT_BYTE - CBIT_CHARMASK;
  194. }
  195. } // while (pb < pbEnd)
  196. *poc = OLESTR( '\0' );
  197. return(CCH_PROPSET);
  198. }
  199. //+--------------------------------------------------------------------------
  200. // Function: PrPropertySetNameToGuid
  201. //
  202. // Synopsis: Map non null-terminated UNICODE string to a property set GUID.
  203. //
  204. // If the name is not properly formed as per
  205. // PrGuidToPropertySetName(), STATUS_INVALID_PARAMETER is
  206. // returned. The pguid parameter is assumed to point to a buffer
  207. // with room for a GUID structure.
  208. //
  209. // Arguments: IN ULONG cocname -- count of OLECHARs in string to convert
  210. // IN OLECHAR aocname[] -- input string to convert
  211. // OUT GUID *pguid -- pointer to buffer for converted GUID
  212. //
  213. // Returns: NTSTATUS
  214. //---------------------------------------------------------------------------
  215. NTSTATUS
  216. PrPropertySetNameToGuid(
  217. IN ULONG cocname,
  218. IN OLECHAR const aocname[],
  219. OUT GUID *pguid)
  220. {
  221. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  222. GUID guidReturn = GUID_NULL;
  223. OLECHAR const *poc = aocname;
  224. if (poc[0] == OC_PROPSET0)
  225. {
  226. // -----------------------
  227. // Check for Special-Cases
  228. // -----------------------
  229. // Note: cocname includes the OC_PROPSET0, and sizeof(osz...)
  230. // includes the trailing OLESTR('\0'), but the comparison excludes both
  231. // the leading OC_PROPSET0 and the trailing '\0'.
  232. // Is this SummaryInformation?
  233. if (cocname == sizeof(oszSummary)/sizeof(OLECHAR) &&
  234. // MAC: Create a dfsocsnicmp or convert strings to WCHARs
  235. //ocsnicmp(&poc[1], oszSummary, cocname - 1) == 0)
  236. dfwcsnicmp(&poc[1], oszSummary, cocname - 1) == 0)
  237. {
  238. *pguid = guidSummary;
  239. return(STATUS_SUCCESS);
  240. }
  241. // Is this DocumentSummaryInformation?
  242. if (cocname == sizeof(oszDocumentSummary)/sizeof(OLECHAR) &&
  243. //ocsnicmp(&poc[1], oszDocumentSummary, cocname - 1) == 0)
  244. dfwcsnicmp(&poc[1], oszDocumentSummary, cocname - 1) == 0)
  245. {
  246. *pguid = guidDocumentSummary;
  247. return(STATUS_SUCCESS);
  248. }
  249. // Is this Global Info?
  250. if (cocname == sizeof(oszGlobalInfo)/sizeof(OLECHAR) &&
  251. //ocsnicmp(&poc[1], oszGlobalInfo, cocname - 1) == 0)
  252. dfwcsnicmp(&poc[1], oszGlobalInfo, cocname - 1) == 0)
  253. {
  254. *pguid = guidGlobalInfo;
  255. return(STATUS_SUCCESS);
  256. }
  257. // Is this Image Info?
  258. if (cocname == sizeof(oszImageInfo)/sizeof(OLECHAR) &&
  259. //ocsnicmp(&poc[1], oszImageInfo, cocname - 1) == 0)
  260. dfwcsnicmp(&poc[1], oszImageInfo, cocname - 1) == 0)
  261. {
  262. *pguid = guidImageInfo;
  263. return(STATUS_SUCCESS);
  264. }
  265. // Is this Image Contents?
  266. if (cocname == sizeof(oszImageContents)/sizeof(OLECHAR) &&
  267. //ocsnicmp(&poc[1], oszImageContents, cocname - 1) == 0)
  268. dfwcsnicmp(&poc[1], oszImageContents, cocname - 1) == 0)
  269. {
  270. *pguid = guidImageContents;
  271. return(STATUS_SUCCESS);
  272. }
  273. // ------------------
  274. // Calculate the GUID
  275. // ------------------
  276. // None of the special-cases hit, so we must calculate
  277. // the GUID from the name.
  278. if (cocname == CCH_PROPSET)
  279. {
  280. ULONG cbit;
  281. BYTE *pb = (BYTE *) &guidReturn - 1;
  282. RtlZeroMemory(&guidReturn, sizeof(guidReturn));
  283. for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK)
  284. {
  285. ULONG cbitUsed = cbit % CBIT_BYTE;
  286. ULONG cbitStored;
  287. OLECHAR oc;
  288. if (cbitUsed == 0)
  289. {
  290. pb++;
  291. }
  292. oc = *++poc - (OLECHAR)'A'; // assume upper case
  293. // for wchar (unsigned) -ve values becomes a large number
  294. // but for char, which is signed, -ve is -ve
  295. if (oc > CALPHACHARS || oc < 0)
  296. {
  297. // oops, try lower case
  298. oc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a'));
  299. if (oc > CALPHACHARS || oc < 0)
  300. {
  301. // must be a digit
  302. oc += ((OLECHAR)'a') - ((OLECHAR)'0') + CALPHACHARS;
  303. if (oc > CHARMASK)
  304. {
  305. goto Exit; // invalid character
  306. }
  307. }
  308. }
  309. *pb |= (BYTE) (oc << cbitUsed);
  310. cbitStored = min(CBIT_BYTE - cbitUsed, CBIT_CHARMASK);
  311. // If the translated bits wouldn't all fit in the current byte
  312. if (cbitStored < CBIT_CHARMASK)
  313. {
  314. oc >>= CBIT_BYTE - cbitUsed;
  315. if (cbit + cbitStored == CBIT_GUID)
  316. {
  317. if (oc != 0)
  318. {
  319. goto Exit; // extra bits
  320. }
  321. break;
  322. }
  323. pb++;
  324. *pb |= (BYTE) oc;
  325. }
  326. } // for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK)
  327. Status = STATUS_SUCCESS;
  328. // If byte-swapping is necessary, do so now on the calculated
  329. // GUID.
  330. PropByteSwap( &guidReturn );
  331. } // if (cocname == CCH_PROPSET)
  332. } // if (poc[0] == OC_PROPSET0)
  333. // Ensure that the calculated GUID isn't one of the special ones. If it is,
  334. // then this is an error. We don't want to convert something to a GUID
  335. // that we can't convert back.
  336. if( guidSummary == guidReturn
  337. ||
  338. guidDocumentSummary == guidReturn
  339. ||
  340. guidGlobalInfo == guidReturn
  341. ||
  342. guidImageInfo == guidReturn
  343. ||
  344. guidImageContents == guidReturn
  345. )
  346. {
  347. return( STATUS_INVALID_PARAMETER );
  348. }
  349. // ----
  350. // Exit
  351. // ----
  352. Status = STATUS_SUCCESS; // Normalize results
  353. *pguid = guidReturn;
  354. Exit:
  355. return(Status);
  356. }