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.

285 lines
7.5 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // attrdnary.cpp
  8. //
  9. // SYNOPSIS
  10. //
  11. // Defines the class AttributeDictionary.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 04/13/2000 Original version.
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #include <windows.h>
  19. #include <attrdnary.h>
  20. #include <enumerators.h>
  21. #include <iasdb.h>
  22. #include <oledberr.h>
  23. #include <simtable.h>
  24. typedef struct _IASTable {
  25. ULONG numColumns;
  26. ULONG numRows;
  27. BSTR* columnNames;
  28. VARTYPE* columnTypes;
  29. VARIANT* table;
  30. } IASTable;
  31. // Command to retrieve attributes of interest.
  32. const WCHAR LEGACY_COMMAND_TEXT[] =
  33. L"SELECT ID, Name, Syntax, MultiValued, "
  34. L" VendorID, VendorTypeID, VendorTypeWidth, VendorLengthWidth, "
  35. L" [Exclude from NT4 IAS Log], [ODBC Log Ordinal], "
  36. L" IsAllowedInProfile, IsAllowedInCondition, "
  37. L" IsAllowedInProfile, IsAllowedInCondition, "
  38. L" Description, LDAPName "
  39. L"FROM Attributes;";
  40. const WCHAR COMMAND_TEXT[] =
  41. L"SELECT ID, Name, Syntax, MultiValued, "
  42. L" VendorID, VendorTypeID, VendorTypeWidth, VendorLengthWidth, "
  43. L" [Exclude from NT4 IAS Log], [ODBC Log Ordinal], "
  44. L" IsAllowedInProfile, IsAllowedInCondition, "
  45. L" IsAllowedInProxyProfile, IsAllowedInProxyCondition, "
  46. L" Description, LDAPName "
  47. L"FROM Attributes;";
  48. //////////
  49. // Allocates memory to store an IASTable struct and stores it in a VARIANT.
  50. //////////
  51. HRESULT
  52. WINAPI
  53. IASAllocateTable(
  54. IN ULONG cols,
  55. IN ULONG rows,
  56. OUT IASTable& table,
  57. OUT VARIANT& tableVariant
  58. ) throw ()
  59. {
  60. //Initialize the out parameters.
  61. memset(&table, 0, sizeof(table));
  62. VariantInit(&tableVariant);
  63. // Save the dimensions.
  64. table.numColumns = cols;
  65. table.numRows = rows;
  66. SAFEARRAYBOUND bound[2];
  67. bound[0].lLbound = bound[1].lLbound = 0;
  68. // The outer array has three elements:
  69. // (1) column names, (2) column types, and (3) table data.
  70. CComVariant value;
  71. bound[0].cElements = 3;
  72. V_ARRAY(&value) = SafeArrayCreate(VT_VARIANT, 1, bound);
  73. if (!V_ARRAY(&value)) { return E_OUTOFMEMORY; }
  74. V_VT(&value) = VT_ARRAY | VT_VARIANT;
  75. VARIANT* data = (VARIANT*)V_ARRAY(&value)->pvData;
  76. // First element is a vector of BSTRs for the column names.
  77. bound[0].cElements = table.numColumns;
  78. V_ARRAY(data) = SafeArrayCreate(VT_BSTR, 1, bound);
  79. if (!V_ARRAY(data)) { return E_OUTOFMEMORY; }
  80. V_VT(data) = VT_ARRAY | VT_BSTR;
  81. // Get the raw vector.
  82. table.columnNames = (BSTR*)V_ARRAY(data)->pvData;
  83. ++data;
  84. // Second element is a vector of USHORTs for the column names.
  85. bound[0].cElements = table.numColumns;
  86. V_ARRAY(data) = SafeArrayCreate(VT_UI2, 1, bound);
  87. if (!V_ARRAY(data)) { return E_OUTOFMEMORY; }
  88. V_VT(data) = VT_ARRAY | VT_UI2;
  89. // Get the raw vector.
  90. table.columnTypes = (USHORT*)V_ARRAY(data)->pvData;
  91. ++data;
  92. // Third element is a 2D matrix of VARIANTs for the table data.
  93. bound[0].cElements = table.numRows;
  94. bound[1].cElements = table.numColumns;
  95. V_ARRAY(data) = SafeArrayCreate(VT_VARIANT, 2, bound);
  96. if (!V_ARRAY(data)) { return E_OUTOFMEMORY; }
  97. V_VT(data) = VT_ARRAY | VT_VARIANT;
  98. // Get the raw table.
  99. table.table = (VARIANT*)V_ARRAY(data)->pvData;
  100. return value.Detach(&tableVariant);
  101. }
  102. STDMETHODIMP AttributeDictionary::GetDictionary(
  103. BSTR bstrPath,
  104. VARIANT* pVal
  105. )
  106. {
  107. HRESULT hr;
  108. // Initialize out parameter.
  109. if (pVal == NULL) { return E_POINTER; }
  110. VariantInit(pVal);
  111. // Validate in parameter.
  112. if (bstrPath == NULL) { return E_INVALIDARG; }
  113. // Open the database.
  114. CComPtr<IUnknown> session;
  115. hr = IASOpenJetDatabase(
  116. bstrPath,
  117. TRUE,
  118. &session
  119. );
  120. if (FAILED(hr)) { return hr; }
  121. // Process the enumerators table.
  122. Enumerators enums;
  123. hr = enums.initialize(session);
  124. if (FAILED(hr)) { return hr; }
  125. // Process the attributes table.
  126. ULONG rows;
  127. hr = IASExecuteSQLFunction(
  128. session,
  129. L"SELECT Count(*) AS X From Attributes;",
  130. (PLONG)&rows
  131. );
  132. if (FAILED(hr)) { return hr; }
  133. CComPtr<IRowset> rowset;
  134. hr = IASExecuteSQLCommand(
  135. session,
  136. COMMAND_TEXT,
  137. &rowset
  138. );
  139. if (hr == DB_E_PARAMNOTOPTIONAL)
  140. {
  141. hr = IASExecuteSQLCommand(
  142. session,
  143. LEGACY_COMMAND_TEXT,
  144. &rowset
  145. );
  146. }
  147. if (FAILED(hr)) { return hr; }
  148. CSimpleTable attrs;
  149. hr = attrs.Attach(rowset);
  150. if (FAILED(hr)) { return hr; }
  151. ULONG columns = (ULONG)attrs.GetColumnCount() + 2;
  152. // Allocate the IASTableObject.
  153. IASTable table;
  154. CComVariant tableVariant;
  155. hr = IASAllocateTable(
  156. columns,
  157. rows,
  158. table,
  159. tableVariant
  160. );
  161. if (FAILED(hr)) { return hr; }
  162. // Populate the column names and types. First from the rowset schema ...
  163. DBORDINAL i;
  164. BSTR* name = table.columnNames;
  165. VARTYPE* vt = table.columnTypes;
  166. for (i = 1; i <= attrs.GetColumnCount(); ++i, ++name, ++vt)
  167. {
  168. *name = SysAllocString(attrs.GetColumnName(i));
  169. if (!*name) { return E_OUTOFMEMORY; }
  170. switch (attrs.GetColumnType(i))
  171. {
  172. case DBTYPE_I4:
  173. *vt = VT_I4;
  174. break;
  175. case DBTYPE_BOOL:
  176. *vt = VT_BOOL;
  177. break;
  178. case DBTYPE_WSTR:
  179. *vt = VT_BSTR;
  180. break;
  181. default:
  182. *vt = VT_EMPTY;
  183. break;
  184. }
  185. }
  186. // ... and then the two derived columns.
  187. *name = SysAllocString(L"EnumNames");
  188. if (!*name) { return E_OUTOFMEMORY; }
  189. *vt = VT_ARRAY | VT_VARIANT;
  190. ++name;
  191. ++vt;
  192. *name = SysAllocString(L"EnumValues");
  193. if (!*name) { return E_OUTOFMEMORY; }
  194. *vt = VT_ARRAY | VT_VARIANT;
  195. // Populate the table data.
  196. VARIANT *v, *end = table.table + columns * rows;
  197. for (v = table.table; v != end && !attrs.MoveNext(); )
  198. {
  199. // Handle the ID separately since we need it later.
  200. LONG id = *(LONG*)attrs.GetValue(1);
  201. V_VT(v) = VT_I4;
  202. V_I4(v) = id;
  203. ++v;
  204. // Get the remaining columns from the rowset.
  205. for (DBORDINAL i = 2; i <= attrs.GetColumnCount(); ++i, ++v)
  206. {
  207. VariantInit(v);
  208. if (attrs.GetLength(i))
  209. {
  210. switch (attrs.GetColumnType(i))
  211. {
  212. case DBTYPE_I4:
  213. {
  214. V_I4(v) = *(LONG*)attrs.GetValue(i);
  215. V_VT(v) = VT_I4;
  216. break;
  217. }
  218. case DBTYPE_BOOL:
  219. {
  220. V_BOOL(v) = *(VARIANT_BOOL*)attrs.GetValue(i)
  221. ? VARIANT_TRUE : VARIANT_FALSE;
  222. V_VT(v) = VT_BOOL;
  223. break;
  224. }
  225. case DBTYPE_WSTR:
  226. {
  227. V_BSTR(v) = SysAllocString((PCWSTR)attrs.GetValue(i));
  228. if (!V_BSTR(v)) { return E_OUTOFMEMORY; }
  229. V_VT(v) = VT_BSTR;
  230. break;
  231. }
  232. }
  233. }
  234. }
  235. // Get the enumeration SAFEARRAYs.
  236. hr = enums.getEnumerators(id, v, v + 1);
  237. if (FAILED(hr)) { return hr; }
  238. v += 2;
  239. }
  240. // All went well so return the VARIANT to the caller.
  241. return tableVariant.Detach(pVal);
  242. }