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.

302 lines
8.4 KiB

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