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.

457 lines
9.4 KiB

  1. /*
  2. * V A R . C P P
  3. *
  4. * XML document processing
  5. *
  6. * Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
  7. */
  8. #include "_xml.h"
  9. // ScVariantTypeFromString()
  10. //
  11. // Returns the variant type associated with a dav datatype string
  12. //
  13. SCODE
  14. ScVariantTypeFromString (LPCWSTR pwszType, USHORT& vt)
  15. {
  16. SCODE sc = S_OK;
  17. // NULL, "string" and "uri"
  18. //
  19. if (!pwszType ||
  20. !_wcsicmp (pwszType, gc_wszDavType_String) ||
  21. !_wcsicmp (pwszType, gc_wszUri))
  22. {
  23. vt = VT_LPWSTR;
  24. }
  25. // integer
  26. //
  27. else if (!_wcsicmp (pwszType, gc_wszDavType_Int))
  28. {
  29. vt = VT_I4;
  30. }
  31. // boolean.tf
  32. //
  33. else if (!_wcsicmp (pwszType, gc_wszDavType_Boolean))
  34. {
  35. vt = VT_BOOL;
  36. }
  37. // float (Floating/Reals)
  38. //
  39. else if (!_wcsicmp (pwszType, gc_wszDavType_Float))
  40. {
  41. vt = VT_R8;
  42. }
  43. // date.iso8601
  44. //
  45. else if (!_wcsicmp (pwszType, gc_wszDavType_Date_ISO8601))
  46. {
  47. vt = VT_FILETIME;
  48. }
  49. else
  50. {
  51. DebugTrace ("ScVariantTypeFromString(): unknown type");
  52. vt = VT_LPWSTR;
  53. sc = S_OK;
  54. }
  55. return sc;
  56. }
  57. // ScVariantValueFromString() ------------------------------------------------
  58. //
  59. // Sets the value of a PROPVARIANT
  60. //
  61. SCODE
  62. ScVariantValueFromString (PROPVARIANT& var, LPCWSTR pwszValue)
  63. {
  64. SCODE sc = S_OK;
  65. LPWSTR pwsz;
  66. SYSTEMTIME st;
  67. switch (var.vt)
  68. {
  69. case VT_LPWSTR:
  70. if (pwszValue)
  71. {
  72. pwsz = static_cast<LPWSTR>(CoTaskMemAlloc(CbSizeWsz(wcslen(pwszValue))));
  73. if (NULL == pwsz)
  74. {
  75. DebugTrace ("ScVariantValueFromString() - CoTaskMemAlloc() failed to allocate %d bytes\n", CbSizeWsz(wcslen(pwszValue)));
  76. sc = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  77. goto ret;
  78. }
  79. wcscpy (pwsz, pwszValue);
  80. var.pwszVal = pwsz;
  81. }
  82. else
  83. var.pwszVal = NULL;
  84. break;
  85. case VT_I4:
  86. Assert (pwszValue);
  87. var.lVal = _wtoi (pwszValue);
  88. break;
  89. case VT_BOOL:
  90. #pragma warning(disable:4310) // wtypes.h is broken
  91. Assert (pwszValue);
  92. if (!_wcsnicmp (pwszValue, gc_wsz1, 1))
  93. var.boolVal = VARIANT_TRUE;
  94. else if (!_wcsnicmp (pwszValue, gc_wsz0, 1))
  95. var.boolVal = VARIANT_FALSE;
  96. else
  97. {
  98. sc = E_INVALIDARG;
  99. goto ret;
  100. }
  101. break;
  102. #pragma warning(default:4310) // wtypes.h is broken
  103. case VT_R8:
  104. Assert (pwszValue);
  105. var.dblVal = wcstod (pwszValue, NULL);
  106. break;
  107. case VT_FILETIME:
  108. Assert (pwszValue);
  109. memset (&var.filetime, 0, sizeof(FILETIME));
  110. if (!FGetSystimeFromDateIso8601 (pwszValue, &st))
  111. {
  112. sc = E_INVALIDARG;
  113. goto ret;
  114. }
  115. SystemTimeToFileTime (&st, &var.filetime);
  116. break;
  117. default:
  118. Assert (pwszValue);
  119. TrapSz ("ScVariantValueFromString() unknown type");
  120. sc = E_INVALIDARG;
  121. goto ret;
  122. }
  123. ret:
  124. return sc;
  125. }
  126. // ScEmitFromVariant() ------------------------------------------------
  127. //
  128. SCODE
  129. ScEmitFromVariant (CXMLEmitter& emitter,
  130. CEmitterNode& enParent,
  131. LPCWSTR pwszTag,
  132. PROPVARIANT& var)
  133. {
  134. CEmitterNode en;
  135. CStackBuffer<CHAR,110> szBuf;
  136. CStackBuffer<WCHAR,128> wszBuf;
  137. LPCWSTR pwszType = NULL;
  138. LPWSTR pwszValue = NULL;
  139. SCODE sc = S_OK;
  140. SYSTEMTIME st;
  141. UINT cch;
  142. UINT i;
  143. VARIANT* pvarTrue = reinterpret_cast<VARIANT*>(&var);
  144. switch (var.vt)
  145. {
  146. case VT_NULL:
  147. case VT_EMPTY:
  148. break;
  149. case VT_BSTR:
  150. pwszValue = static_cast<LPWSTR>(var.bstrVal);
  151. break;
  152. case VT_LPWSTR:
  153. pwszValue = var.pwszVal;
  154. break;
  155. case VT_LPSTR:
  156. if (!var.pszVal)
  157. break;
  158. cch = static_cast<UINT>(strlen (var.pszVal));
  159. pwszValue = wszBuf.resize(CbSizeWsz(cch));
  160. if (NULL == pwszValue)
  161. {
  162. sc = E_OUTOFMEMORY;
  163. goto ret;
  164. }
  165. // We know that the numbers are in ASCII codepage and we know
  166. // that the buffer size is big enough.
  167. //
  168. cch = MultiByteToWideChar (CP_ACP,
  169. MB_ERR_INVALID_CHARS,
  170. var.pszVal,
  171. cch + 1,
  172. pwszValue,
  173. wszBuf.celems());
  174. if (0 == cch)
  175. {
  176. sc = HRESULT_FROM_WIN32(GetLastError());
  177. Assert(FAILED(sc));
  178. goto ret;
  179. }
  180. break;
  181. case VT_I1:
  182. pwszType = gc_wszDavType_Int;
  183. _itow (pvarTrue->cVal, wszBuf.get(), 10);
  184. pwszValue = wszBuf.get();
  185. break;
  186. case VT_UI1:
  187. pwszType = gc_wszDavType_Int;
  188. _ultow (var.bVal, wszBuf.get(), 10);
  189. pwszValue = wszBuf.get();
  190. break;
  191. case VT_I2:
  192. pwszType = gc_wszDavType_Int;
  193. _itow (var.iVal, wszBuf.get(), 10);
  194. pwszValue = wszBuf.get();
  195. break;
  196. case VT_UI2:
  197. pwszType = gc_wszDavType_Int;
  198. _ultow (var.uiVal, wszBuf.get(), 10);
  199. pwszValue = wszBuf.get();
  200. break;
  201. case VT_I4:
  202. pwszType = gc_wszDavType_Int;
  203. _ltow (var.lVal, wszBuf.get(), 10);
  204. pwszValue = wszBuf.get();
  205. break;
  206. case VT_UI4:
  207. pwszType = gc_wszDavType_Int;
  208. _ultow (var.ulVal, wszBuf.get(), 10);
  209. pwszValue = wszBuf.get();
  210. break;
  211. case VT_I8:
  212. pwszType = gc_wszDavType_Int;
  213. //$ REVIEW: negative values of _int64 seem to have problems in
  214. // the __i64tow() API. Handle those cases ourselves by using the wrapper
  215. // function Int64ToPwsz.
  216. //
  217. Int64ToPwsz (&var.hVal.QuadPart, wszBuf.get(), wszBuf.size());
  218. //
  219. //$ REVIEW: end
  220. pwszValue = wszBuf.get();
  221. break;
  222. case VT_UI8:
  223. pwszType = gc_wszDavType_Int;
  224. _ui64tow (var.uhVal.QuadPart, wszBuf.get(), 10);
  225. pwszValue = wszBuf.get();
  226. break;
  227. case VT_INT:
  228. pwszType = gc_wszDavType_Int;
  229. _itow (pvarTrue->intVal, wszBuf.get(), 10);
  230. pwszValue = wszBuf.get();
  231. break;
  232. case VT_UINT:
  233. pwszType = gc_wszDavType_Int;
  234. _ultow (pvarTrue->uintVal, wszBuf.get(), 10);
  235. pwszValue = wszBuf.get();
  236. break;
  237. case VT_BOOL:
  238. pwszType = gc_wszDavType_Boolean;
  239. _itow (!(VARIANT_FALSE == var.boolVal), wszBuf.get(), 10);
  240. pwszValue = wszBuf.get();
  241. break;
  242. case VT_R4:
  243. // _gcvt could add 8 extra chars then the number of digits asked
  244. // for example -3.1415e+019, '-','.' "e+019", plus the terminating
  245. // NULL doesn't count in digits asked. so we have to reserve
  246. // enough space in the provided buffer. using 11 to make sure
  247. // we are absolutely safe.
  248. //
  249. _gcvt (var.fltVal, szBuf.celems() - 11, szBuf.get());
  250. cch = static_cast<UINT>(strlen(szBuf.get()));
  251. pwszValue = wszBuf.resize(CbSizeWsz(cch));
  252. if (NULL == pwszValue)
  253. {
  254. sc = E_OUTOFMEMORY;
  255. goto ret;
  256. }
  257. // We know that the numbers are in ASCII codepage and we know
  258. // that the buffer size is big enough.
  259. //
  260. cch = MultiByteToWideChar(CP_ACP,
  261. MB_ERR_INVALID_CHARS,
  262. szBuf.get(),
  263. cch + 1,
  264. wszBuf.get(),
  265. wszBuf.celems());
  266. if (0 == cch)
  267. {
  268. sc = HRESULT_FROM_WIN32(GetLastError());
  269. Assert(FAILED(sc));
  270. goto ret;
  271. }
  272. pwszType = gc_wszDavType_R4;
  273. break;
  274. case VT_R8:
  275. // _gcvt could add 8 extra chars then the number of digits asked
  276. // for example -3.1415e+019, '-','.' "e+019", plus the terminating
  277. // NULL doesn't count in digits asked. so we have to reserve
  278. // enough space in the provided buffer. using 11 to make sure
  279. // we are absolutely safe.
  280. //
  281. _gcvt (var.dblVal, szBuf.celems() - 11, szBuf.get());
  282. cch = static_cast<UINT>(strlen(szBuf.get()));
  283. pwszValue = wszBuf.resize(CbSizeWsz(cch));
  284. if (NULL == pwszValue)
  285. {
  286. sc = E_OUTOFMEMORY;
  287. goto ret;
  288. }
  289. // We know that the numbers are in ASCII codepage and we know
  290. // that the buffer size is big enough.
  291. //
  292. cch = MultiByteToWideChar(CP_ACP,
  293. MB_ERR_INVALID_CHARS,
  294. szBuf.get(),
  295. cch + 1,
  296. wszBuf.get(),
  297. wszBuf.celems());
  298. if (0 == cch)
  299. {
  300. sc = HRESULT_FROM_WIN32(GetLastError());
  301. Assert(FAILED(sc));
  302. goto ret;
  303. }
  304. pwszType = gc_wszDavType_Float;
  305. break;
  306. case VT_FILETIME:
  307. if (!FileTimeToSystemTime (&var.filetime, &st))
  308. {
  309. // In case the filetime is invalid, default to zero
  310. //
  311. FILETIME ftDefault = {0};
  312. FileTimeToSystemTime (&ftDefault, &st);
  313. }
  314. if (!FGetDateIso8601FromSystime(&st, wszBuf.get(), wszBuf.celems()))
  315. return E_INVALIDARG;
  316. pwszType = gc_wszDavType_Date_ISO8601;
  317. pwszValue = wszBuf.get();
  318. break;
  319. case VT_VECTOR | VT_LPWSTR:
  320. {
  321. // Create the emitter node;
  322. //
  323. sc = en.ScConstructNode (emitter,
  324. enParent.Pxn(),
  325. pwszTag,
  326. NULL,
  327. gc_wszDavType_Mvstring);
  328. if (FAILED (sc))
  329. goto ret;
  330. // Add the values
  331. //
  332. for (i = 0; i < var.calpwstr.cElems; i++)
  333. {
  334. CEmitterNode enSub;
  335. sc = en.ScAddNode (gc_wszXml_V,
  336. enSub,
  337. var.calpwstr.pElems[i]);
  338. if (FAILED (sc))
  339. goto ret;
  340. }
  341. // In this case we have built up the node ourselves. We do not
  342. // want to fall into recreating the node.
  343. //
  344. return S_OK;
  345. }
  346. case VT_CY:
  347. case VT_DATE:
  348. case VT_DISPATCH:
  349. case VT_ERROR:
  350. case VT_VARIANT:
  351. case VT_UNKNOWN:
  352. case VT_DECIMAL:
  353. case VT_RECORD:
  354. case VT_BLOB:
  355. case VT_STREAM:
  356. case VT_STORAGE:
  357. case VT_STREAMED_OBJECT:
  358. case VT_STORED_OBJECT:
  359. case VT_BLOB_OBJECT:
  360. case VT_CF:
  361. case VT_CLSID:
  362. default:
  363. TrapSz ("ScEmitterNodeFromVariant() unknown type");
  364. return E_UNEXPECTED;
  365. break;
  366. }
  367. // Create the emitter node
  368. //
  369. sc = en.ScConstructNode (emitter,
  370. enParent.Pxn(),
  371. pwszTag,
  372. pwszValue,
  373. pwszType);
  374. if (FAILED (sc))
  375. goto ret;
  376. ret:
  377. return sc;
  378. }