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.

388 lines
12 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992-1996
  5. //
  6. // File: ntprop.cxx
  7. //
  8. // Contents: OLE Appendix B property set support.
  9. //
  10. //
  11. //---------------------------------------------------------------------------
  12. #include "pch.cxx"
  13. #define CCH_MAP (1 << CBIT_CHARMASK) // 32
  14. #define CHARMASK (CCH_MAP - 1) // 0x1f
  15. // we use static array instead of string literals because some systems
  16. // have 4 bytes string literals, and would not produce the correct result
  17. // for REF's 2 byte Unicode convention
  18. //
  19. OLECHAR aocMap[CCH_MAP + 1] = {'a','b','c','d','e','f','g',
  20. 'h','i','j','k','l','m','n',
  21. 'o','p','q','r','s','t','u',
  22. 'v','w','x','y','z',
  23. '0','1','2','3','4','5','\0'};
  24. #define CALPHACHARS (1 + (OLECHAR)'z' - (OLECHAR)'a')
  25. GUID guidSummary =
  26. { 0xf29f85e0,
  27. 0x4ff9, 0x1068,
  28. { 0xab, 0x91, 0x08, 0x00, 0x2b, 0x27, 0xb3, 0xd9 } };
  29. OLECHAR oszSummary[] = {'S','u','m','m','a','r','y',
  30. 'I','n','f','o','r','m','a','t','i','o','n','\0'};
  31. GUID guidDocumentSummary =
  32. { 0xd5cdd502,
  33. 0x2e9c, 0x101b,
  34. { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };
  35. OLECHAR oszDocumentSummary[] = {'D','o','c','u','m','e','n','t',
  36. 'S','u','m','m','a','r','y',
  37. 'I','n','f','o','r','m','a','t','i','o','n',
  38. '\0'};
  39. // Note that user defined properties are placed in section 2 with the below
  40. // GUID as the FMTID -- alas, we did not expect Office95 to actually use it.
  41. GUID guidDocumentSummarySection2 =
  42. { 0xd5cdd505,
  43. 0x2e9c, 0x101b,
  44. { 0x93, 0x97, 0x08, 0x00, 0x2b, 0x2c, 0xf9, 0xae } };
  45. // *Global Info*
  46. OLECHAR oszGlobalInfo[] = {'G','l','o','b','a','l',' ','I','n','f','o','\0'};
  47. GUID guidGlobalInfo =
  48. { 0x56616F00,
  49. 0xC154, 0x11ce,
  50. { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
  51. // *Image Contents*
  52. OLECHAR oszImageContents[] = {'I','m','a','g','e',' ',
  53. 'C','o','n','t','e','n','t','s','\0'};
  54. GUID guidImageContents =
  55. { 0x56616500,
  56. 0xC154, 0x11ce,
  57. { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
  58. // *Image Info*
  59. OLECHAR oszImageInfo[] = {'I','m','a','g','e',' ','I','n','f','o'};
  60. GUID guidImageInfo =
  61. { 0x56616500,
  62. 0xC154, 0x11ce,
  63. { 0x85, 0x53, 0x00, 0xAA, 0x00, 0xA1, 0xF9, 0x5B } };
  64. __inline OLECHAR
  65. MapChar(IN ULONG i)
  66. {
  67. return((OLECHAR) aocMap[i & CHARMASK]);
  68. }
  69. //+--------------------------------------------------------------------------
  70. // Function: RtlGuidToPropertySetName
  71. //
  72. // Synopsis: Map property set GUID to null-terminated UNICODE name string.
  73. //
  74. // The awcname parameter is assumed to be a buffer with room for
  75. // CWC_PROPSETSZ (28) UNICODE characters. The first character
  76. // is always WC_PROPSET0 (0x05), as specified by the OLE Appendix
  77. // B documentation. The colon character normally used as an NT
  78. // stream name separator is not written to the caller's buffer.
  79. //
  80. // No error is possible.
  81. //
  82. // Arguments: IN GUID *pguid -- pointer to GUID to convert
  83. // OUT OLECHAR aocname[] -- output string buffer
  84. //
  85. // Returns: count of non-NULL characters in the output string buffer
  86. //---------------------------------------------------------------------------
  87. ULONG PROPSYSAPI PROPAPI
  88. RtlGuidToPropertySetName(
  89. IN GUID const *pguid,
  90. OUT OLECHAR aocname[])
  91. {
  92. ULONG cbitRemain = CBIT_BYTE;
  93. OLECHAR *poc = aocname;
  94. #ifdef BIGENDIAN // since we go thru it byte by byte
  95. GUID guidSwapped = *pguid; // we have to swap it for big endian
  96. ByteSwap(&guidSwapped);
  97. BYTE *pb = (BYTE *) &guidSwapped;
  98. #else
  99. BYTE *pb = (BYTE *) pguid;
  100. #endif
  101. BYTE *pbEnd = pb + sizeof(GUID);
  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. ULONG i = *pb >> (CBIT_BYTE - cbitRemain);
  161. if (cbitRemain >= CBIT_CHARMASK)
  162. {
  163. *poc = MapChar(i);
  164. if (cbitRemain == CBIT_BYTE && *poc >= (OLECHAR)'a'
  165. && *poc <= ((OLECHAR)'z'))
  166. {
  167. *poc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a') );
  168. }
  169. poc++;
  170. cbitRemain -= CBIT_CHARMASK;
  171. if (cbitRemain == 0)
  172. {
  173. pb++;
  174. cbitRemain = CBIT_BYTE;
  175. }
  176. }
  177. else
  178. {
  179. if (++pb < pbEnd)
  180. {
  181. i |= *pb << cbitRemain;
  182. }
  183. *poc++ = MapChar(i);
  184. cbitRemain += CBIT_BYTE - CBIT_CHARMASK;
  185. }
  186. }
  187. *poc = 0;
  188. return(CCH_PROPSET);
  189. }
  190. //+--------------------------------------------------------------------------
  191. // Function: RtlPropertySetNameToGuid
  192. //
  193. // Synopsis: Map non null-terminated UNICODE string to a property set GUID.
  194. //
  195. // If the name is not properly formed as per
  196. // RtlGuidToPropertySetName(), STATUS_INVALID_PARAMETER is
  197. // returned. The pguid parameter is assumed to point to a buffer
  198. // with room for a GUID structure.
  199. //
  200. // Arguments: IN ULONG cocname -- count of OLECHARs in string to convert
  201. // IN OLECHAR aocname[] -- input string to convert
  202. // OUT GUID *pguid -- pointer to buffer for converted GUID
  203. //
  204. // Returns: NTSTATUS
  205. //---------------------------------------------------------------------------
  206. NTSTATUS PROPSYSAPI PROPAPI
  207. RtlPropertySetNameToGuid(
  208. IN ULONG cocname,
  209. IN OLECHAR const aocname[],
  210. OUT GUID *pguid)
  211. {
  212. NTSTATUS Status = STATUS_INVALID_PARAMETER;
  213. OLECHAR const *poc = aocname;
  214. if (poc[0] == OC_PROPSET0)
  215. {
  216. // -----------------------
  217. // Check for Special-Cases
  218. // -----------------------
  219. // Note: cocname includes the OC_PROPSET0, and sizeof(osz...)
  220. // includes the trailing OLESTR('\0'), but the comparison excludes both
  221. // the leading OC_PROPSET0 and the trailing '\0'.
  222. // Is this SummaryInformation?
  223. if (cocname == sizeof(oszSummary)/sizeof(OLECHAR) &&
  224. ocsnicmp(&poc[1], oszSummary, cocname - 1) == 0)
  225. {
  226. *pguid = guidSummary;
  227. return(STATUS_SUCCESS);
  228. }
  229. // Is this DocumentSummaryInformation?
  230. if (cocname == sizeof(oszDocumentSummary)/sizeof(OLECHAR) &&
  231. ocsnicmp(&poc[1], oszDocumentSummary, cocname - 1) == 0)
  232. {
  233. *pguid = guidDocumentSummary;
  234. return(STATUS_SUCCESS);
  235. }
  236. // Is this Global Info?
  237. if (cocname == sizeof(oszGlobalInfo)/sizeof(OLECHAR) &&
  238. ocsnicmp(&poc[1], oszGlobalInfo, cocname - 1) == 0)
  239. {
  240. *pguid = guidGlobalInfo;
  241. return(STATUS_SUCCESS);
  242. }
  243. // Is this Image Info?
  244. if (cocname == sizeof(oszImageInfo)/sizeof(OLECHAR) &&
  245. ocsnicmp(&poc[1], oszImageInfo, cocname - 1) == 0)
  246. {
  247. *pguid = guidImageInfo;
  248. return(STATUS_SUCCESS);
  249. }
  250. // Is this Image Contents?
  251. if (cocname == sizeof(oszImageContents)/sizeof(OLECHAR) &&
  252. ocsnicmp(&poc[1], oszImageContents, cocname - 1) == 0)
  253. {
  254. *pguid = guidImageContents;
  255. return(STATUS_SUCCESS);
  256. }
  257. // ------------------
  258. // Calculate the GUID
  259. // ------------------
  260. // None of the special-cases hit, so we must calculate
  261. // the GUID from the name.
  262. if (cocname == CCH_PROPSET)
  263. {
  264. ULONG cbit;
  265. BYTE *pb = (BYTE *) pguid - 1;
  266. RtlZeroMemory(pguid, sizeof(*pguid));
  267. for (cbit = 0; cbit < CBIT_GUID; cbit += CBIT_CHARMASK)
  268. {
  269. ULONG cbitUsed = cbit % CBIT_BYTE;
  270. ULONG cbitStored;
  271. OLECHAR oc;
  272. if (cbitUsed == 0)
  273. {
  274. pb++;
  275. }
  276. oc = *++poc - (OLECHAR)'A'; // assume upper case
  277. // for wchar (unsigned) -ve values becomes a large number
  278. // but for char, which is signed, -ve is -ve
  279. if (oc > CALPHACHARS || oc < 0)
  280. {
  281. // oops, try lower case
  282. oc += (OLECHAR) ( ((OLECHAR)'A') - ((OLECHAR)'a'));
  283. if (oc > CALPHACHARS || oc < 0)
  284. {
  285. // must be a digit
  286. oc += ((OLECHAR)'a') - ((OLECHAR)'0') + CALPHACHARS;
  287. if (oc > CHARMASK)
  288. {
  289. goto fail; // invalid character
  290. }
  291. }
  292. }
  293. *pb |= (BYTE) (oc << cbitUsed);
  294. cbitStored = min(CBIT_BYTE - cbitUsed, CBIT_CHARMASK);
  295. // If the translated bits wouldn't all fit in the current byte
  296. if (cbitStored < CBIT_CHARMASK)
  297. {
  298. oc >>= CBIT_BYTE - cbitUsed;
  299. if (cbit + cbitStored == CBIT_GUID)
  300. {
  301. if (oc != 0)
  302. {
  303. goto fail; // extra bits
  304. }
  305. break;
  306. }
  307. pb++;
  308. *pb |= (BYTE) oc;
  309. }
  310. }
  311. Status = STATUS_SUCCESS;
  312. }
  313. }
  314. #ifdef BIGENDIAN
  315. ByteSwap(pguid); // on big endian, we will generate a guid
  316. // with the wrong byteorder, so we have to
  317. // swap it
  318. #endif
  319. return(Status);
  320. fail:
  321. return(Status);
  322. }