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.

1439 lines
46 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: globals.cxx
  7. //
  8. // Contents: Global Variables for WinNT
  9. //
  10. // Functions:
  11. //
  12. // History: 25-March-96 KrishnaG Created.
  13. // Updated: 4-May-2000 sivaramr Added a property called Name to all
  14. // classes in order to support keys in UMI.
  15. // 13-Aug-2000 AjayR Added support to dynamically load
  16. // functions that are not on earlier NT versions.
  17. //
  18. //----------------------------------------------------------------------------
  19. #include "winnt.hxx"
  20. #pragma hdrstop
  21. //
  22. // Global variabled needed to keep track of dynamically
  23. // loaded libs.
  24. //
  25. HANDLE g_hDllNetapi32;
  26. HANDLE g_hDllAdvapi32;
  27. CRITICAL_SECTION g_csLoadLibs;
  28. BOOL g_fDllsLoaded;
  29. FRTLENCRYPTMEMORY g_pRtlEncryptMemory = NULL;
  30. FRTLDECRYPTMEMORY g_pRtlDecryptMemory = NULL;
  31. WCHAR *szProviderName = TEXT("WinNT");
  32. #define MAX_LONG (0x7FFFFFFF)
  33. #define MIN_LONG (0x80000000)
  34. #define MAX_BOOLEAN 1
  35. #define MAX_STRLEN (256)
  36. PROPERTYINFO DomainClass[] =
  37. { { TEXT("MinPasswordLength"), // FSDomainPassword
  38. TEXT(""), TEXT("Integer"), LM20_PWLEN+1, 0, FALSE,
  39. PROPERTY_RW, 0, NT_SYNTAX_ID_DWORD },
  40. { TEXT("MinPasswordAge"),
  41. TEXT(""), TEXT("Interval"), TIMEQ_FOREVER, 0, FALSE,
  42. PROPERTY_RW, 0, NT_SYNTAX_ID_DWORD },
  43. { TEXT("MaxPasswordAge"),
  44. TEXT(""),TEXT("Interval"), TIMEQ_FOREVER, ONE_DAY, FALSE,
  45. PROPERTY_RW, 0, NT_SYNTAX_ID_DWORD },
  46. { TEXT("MaxBadPasswordsAllowed"),
  47. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  48. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  49. //
  50. // NetAPI state DEF_MAX_PWHIST (8), but NetAPI devlpr confirm
  51. // current is 1024. Ignore Net Account - UNIQUEPWD limit.
  52. // Use DEF_MAX_PWHIST to be safe for now
  53. //
  54. { TEXT("PasswordHistoryLength"),
  55. TEXT(""), TEXT("Integer"), DEF_MAX_PWHIST, 0, FALSE,
  56. PROPERTY_RW, 0, NT_SYNTAX_ID_DWORD},
  57. { TEXT("AutoUnlockInterval"),
  58. TEXT(""), TEXT("Interval"), MAX_LONG, 0, FALSE,
  59. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  60. { TEXT("LockoutObservationInterval"),
  61. TEXT(""), TEXT("Interval"), MAX_LONG, 0, FALSE,
  62. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  63. { TEXT("Name"),
  64. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  65. PROPERTY_READABLE, 0, NT_SYNTAX_ID_LPTSTR }
  66. };
  67. DWORD gdwDomainTableSize = sizeof(DomainClass)/sizeof(PROPERTYINFO);
  68. PROPERTYINFO ComputerClass[] =
  69. { { TEXT("Owner"),
  70. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  71. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR },
  72. { TEXT("Division"),
  73. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  74. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR },
  75. { TEXT("OperatingSystem"), // ro
  76. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  77. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR},
  78. { TEXT("OperatingSystemVersion"), // ro
  79. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  80. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR},
  81. { TEXT("Processor"),
  82. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  83. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR },
  84. { TEXT("ProcessorCount"),
  85. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  86. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR },
  87. { TEXT("Name"),
  88. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  89. PROPERTY_READABLE, 4, NT_SYNTAX_ID_LPTSTR }
  90. };
  91. DWORD gdwComputerTableSize = sizeof(ComputerClass)/sizeof(PROPERTYINFO);
  92. PROPERTYINFO UserClass[] =
  93. { // USER_INFO3
  94. { TEXT("Description"), // FSUserBusinessInfo
  95. TEXT(""), TEXT("String"), MAXCOMMENTSZ+1, 0, FALSE,
  96. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR },
  97. { TEXT("FullName"),
  98. TEXT(""), TEXT("String"), MAXCOMMENTSZ+1, 0, FALSE,
  99. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR},
  100. { TEXT("AccountExpirationDate"),
  101. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  102. PROPERTY_RW, 3, NT_SYNTAX_ID_DATE_1970},
  103. { TEXT("PasswordAge"),
  104. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  105. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD},
  106. { TEXT("UserFlags"),
  107. TEXT(""), TEXT("Integer"), 0, 0, FALSE,
  108. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD},
  109. { TEXT("LoginWorkstations"),
  110. TEXT(""), TEXT("String"), MAX_STRLEN, 0, TRUE,
  111. PROPERTY_RW, 3, NT_SYNTAX_ID_DelimitedString },
  112. { TEXT("BadPasswordAttempts"), // ro
  113. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  114. PROPERTY_READABLE, 3, NT_SYNTAX_ID_DWORD },
  115. { TEXT("MaxLogins"),
  116. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  117. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  118. { TEXT("MaxStorage"),
  119. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  120. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  121. // USER_MAX_STORAGE_UNLIMITED
  122. { TEXT("PasswordExpired"),
  123. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  124. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  125. { TEXT("PasswordExpirationDate"),
  126. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  127. PROPERTY_RW, 3, NT_SYNTAX_ID_DATE_1970 },
  128. { TEXT("LastLogin"), // ro
  129. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  130. PROPERTY_READABLE, 3, NT_SYNTAX_ID_DATE_1970 },
  131. { TEXT("LastLogoff"), // ro
  132. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  133. PROPERTY_READABLE, 3, NT_SYNTAX_ID_DATE_1970 },
  134. { TEXT("HomeDirectory"),
  135. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  136. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR },
  137. { TEXT("Profile"),
  138. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  139. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR},
  140. { TEXT("Parameters"),
  141. TEXT(""), TEXT("String"), MAX_PATH, 0, FALSE,
  142. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR},
  143. { TEXT("HomeDirDrive"),
  144. TEXT(""), TEXT("String"), MAX_PATH, 0, FALSE,
  145. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR},
  146. { TEXT("LoginScript"),
  147. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  148. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR },
  149. { TEXT("LoginHours"),
  150. TEXT(""), TEXT("OctetString"), 0, 0, FALSE,
  151. PROPERTY_RW, 3, NT_SYNTAX_ID_OCTETSTRING},
  152. { TEXT("PrimaryGroupID"),
  153. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  154. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  155. //
  156. // USER_MODAL_INFO0
  157. // NOTE!! - user_modal_info0 CANNOT (!!) be changed in USER class
  158. // since they are meant for the entire domain.
  159. // - user_modal_info0 CAN (!!) be changed in DOMAIN class
  160. // only. Ref NetApi.
  161. //
  162. { TEXT("MinPasswordLength"), // FSDomainPassword
  163. TEXT(""), TEXT("Integer"), LM20_PWLEN+1, 0, FALSE,
  164. PROPERTY_READABLE, 10, NT_SYNTAX_ID_DWORD },
  165. { TEXT("MinPasswordAge"),
  166. TEXT(""), TEXT("Interval"), TIMEQ_FOREVER, 0, FALSE,
  167. PROPERTY_READABLE, 10, NT_SYNTAX_ID_DWORD },
  168. { TEXT("MaxPasswordAge"),
  169. TEXT(""),TEXT("Interval"), TIMEQ_FOREVER, ONE_DAY, FALSE,
  170. PROPERTY_READABLE, 10, NT_SYNTAX_ID_DWORD },
  171. //
  172. // NetAPI state DEF_MAX_PWHIST (8), but NetAPI devlpr confirm
  173. // current is 1024. Ignore Net Account - UNIQUEPWD limit.
  174. // Use DEF_MAX_PWHIST to be safe for now
  175. //
  176. { TEXT("PasswordHistoryLength"),
  177. TEXT(""), TEXT("Integer"), DEF_MAX_PWHIST, 0, FALSE,
  178. PROPERTY_READABLE, 10, NT_SYNTAX_ID_DWORD},
  179. //
  180. // USER_MODAL_INFO3
  181. // NOTE!! - user_modal_info3 CANNOT (!!) be changed in USER class
  182. // since they are meant for the entire domain.
  183. // - user_modal_info3 CAN (!!) be changed in DOMAIN class
  184. // only. Ref NetApi.
  185. //
  186. { TEXT("MaxBadPasswordsAllowed"),
  187. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  188. PROPERTY_READABLE, 13, NT_SYNTAX_ID_DWORD },
  189. { TEXT("AutoUnlockInterval"),
  190. TEXT(""), TEXT("Interval"), MAX_LONG, 0, FALSE,
  191. PROPERTY_READABLE, 13, NT_SYNTAX_ID_DWORD },
  192. { TEXT("LockoutObservationInterval"),
  193. TEXT(""), TEXT("Interval"), MAX_LONG, 0, FALSE,
  194. PROPERTY_READABLE, 13, NT_SYNTAX_ID_DWORD },
  195. //
  196. // Not for USER_INFO or USER_MODAL_INFO
  197. //
  198. { TEXT("objectSid"),
  199. TEXT(""), TEXT("OctetString"), 0, 0, FALSE,
  200. PROPERTY_READABLE, 20, NT_SYNTAX_ID_OCTETSTRING},
  201. #ifndef WIN95
  202. { TEXT("RasPermissions"),
  203. TEXT(""), TEXT("Integer"), 0, 0, FALSE,
  204. PROPERTY_RW, 21, NT_SYNTAX_ID_DWORD },
  205. #endif
  206. { TEXT("Name"),
  207. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  208. PROPERTY_READABLE, 3, NT_SYNTAX_ID_LPTSTR }
  209. };
  210. DWORD gdwUserTableSize = sizeof(UserClass)/sizeof(PROPERTYINFO);
  211. PROPERTYINFO GroupClass[] =
  212. {
  213. { TEXT("Description"), // FSGroupGeneralInfo
  214. TEXT(""), TEXT("String"), MAXCOMMENTSZ+1, 0, FALSE,
  215. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  216. { TEXT("objectSid"),
  217. TEXT(""), TEXT("OctetString"), 0, 0, FALSE,
  218. PROPERTY_READABLE, 20, NT_SYNTAX_ID_OCTETSTRING},
  219. { TEXT("groupType"),
  220. TEXT(""), TEXT("Integer"), 0, 0, FALSE,
  221. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD},
  222. { TEXT("Name"),
  223. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  224. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR }
  225. };
  226. DWORD gdwGroupTableSize = sizeof(GroupClass)/sizeof(PROPERTYINFO);
  227. PROPERTYINFO ServiceClass[] =
  228. { { TEXT("HostComputer"), // FSServiceConfiguration
  229. TEXT(""), TEXT("ADsPath"), MAX_STRLEN, 0, FALSE,
  230. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  231. { TEXT("DisplayName"),
  232. TEXT(""), TEXT("String"), 256, 0, FALSE,
  233. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  234. { TEXT("ServiceType"),
  235. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  236. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD},
  237. { TEXT("StartType"),
  238. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  239. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD },
  240. { TEXT("Path"),
  241. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  242. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  243. { TEXT("ErrorControl"),
  244. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  245. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD },
  246. { TEXT("LoadOrderGroup"),
  247. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  248. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  249. { TEXT("ServiceAccountName"),
  250. TEXT(""), TEXT("String"), DNLEN+UNLEN+2, 0, FALSE,
  251. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR},
  252. { TEXT("Dependencies"),
  253. TEXT(""), TEXT("String"), MAX_STRLEN, 0, TRUE,
  254. PROPERTY_RW, 1, NT_SYNTAX_ID_NulledString},
  255. { TEXT("Name"),
  256. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  257. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR }
  258. };
  259. DWORD gdwServiceTableSize = sizeof(ServiceClass)/sizeof(PROPERTYINFO);
  260. PROPERTYINFO FileServiceClass[] =
  261. { { TEXT("HostComputer"), // FSServiceConfiguration
  262. TEXT(""), TEXT("ADsPath"), MAX_STRLEN, 0, FALSE,
  263. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  264. { TEXT("DisplayName"),
  265. TEXT(""), TEXT("String"), 256, 0, FALSE,
  266. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  267. { TEXT("Version"),
  268. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  269. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  270. { TEXT("ServiceType"),
  271. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  272. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD},
  273. { TEXT("StartType"),
  274. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  275. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD },
  276. { TEXT("Path"),
  277. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  278. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  279. { TEXT("ErrorControl"),
  280. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  281. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD },
  282. { TEXT("LoadOrderGroup"),
  283. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  284. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  285. { TEXT("ServiceAccountName"),
  286. TEXT(""), TEXT("String"), DNLEN+UNLEN+2, 0, FALSE,
  287. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR},
  288. { TEXT("Dependencies"),
  289. TEXT(""), TEXT("String"), MAX_STRLEN, 0, TRUE,
  290. PROPERTY_RW, 1, NT_SYNTAX_ID_NulledString},
  291. { TEXT("Description"), // FSFileServiceGeneralInfo
  292. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  293. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  294. { TEXT("MaxUserCount"),
  295. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  296. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD },
  297. { TEXT("Name"),
  298. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  299. PROPERTY_READABLE, 2, NT_SYNTAX_ID_LPTSTR }
  300. };
  301. DWORD gdwFileServiceTableSize = sizeof(FileServiceClass)/sizeof(PROPERTYINFO);
  302. PROPERTYINFO SessionClass[] =
  303. { { TEXT("User"), // ro, FSSessionGeneralInfo
  304. TEXT(""), TEXT("String"), UNLEN+1, 0, FALSE,
  305. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  306. { TEXT("Computer"), // ro
  307. TEXT(""), TEXT("String"), UNCLEN+1, 0, FALSE,
  308. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR},
  309. { TEXT("ConnectTime"), // ro
  310. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  311. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DATE },
  312. { TEXT("IdleTime"), // ro
  313. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  314. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DATE},
  315. { TEXT("Name"),
  316. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  317. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR }
  318. };
  319. DWORD gdwSessionTableSize = sizeof(SessionClass)/sizeof(PROPERTYINFO);
  320. PROPERTYINFO ResourceClass[] =
  321. { { TEXT("User"), // ro, FSResourceGeneralInfo
  322. TEXT(""), TEXT("String"), UNLEN+1, 0, FALSE,
  323. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  324. { TEXT("Path"), // ro
  325. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  326. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  327. { TEXT("LockCount"), // ro
  328. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  329. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DWORD},
  330. { TEXT("Name"),
  331. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  332. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR }
  333. };
  334. DWORD gdwResourceTableSize = sizeof(ResourceClass)/sizeof(PROPERTYINFO);
  335. PROPERTYINFO FileShareClass[] =
  336. { { TEXT("CurrentUserCount"), // ro, FSFileShareGeneralInfo
  337. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  338. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD },
  339. { TEXT("Description"),
  340. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  341. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  342. { TEXT("HostComputer"),
  343. TEXT(""), TEXT("ADsPath"), MAX_STRLEN, 0, FALSE,
  344. PROPERTY_READABLE, 2, NT_SYNTAX_ID_LPTSTR },
  345. { TEXT("Path"),
  346. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  347. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  348. { TEXT("MaxUserCount"),
  349. TEXT(""), TEXT("Integer"), MAX_LONG, -1, FALSE,
  350. PROPERTY_RW, 2, NT_SYNTAX_ID_DWORD },
  351. { TEXT("Name"),
  352. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  353. PROPERTY_READABLE, 2, NT_SYNTAX_ID_LPTSTR }
  354. };
  355. DWORD gdwFileShareTableSize = sizeof(FileShareClass)/sizeof(PROPERTYINFO);
  356. PROPERTYINFO FPNWFileServiceClass[] =
  357. { { TEXT("HostComputer"), // FSServiceConfiguration
  358. TEXT(""), TEXT("ADsPath"), MAX_STRLEN, 0, FALSE,
  359. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  360. { TEXT("DisplayName"),
  361. TEXT(""), TEXT("String"), 256, 0, FALSE,
  362. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  363. { TEXT("Version"),
  364. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  365. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  366. { TEXT("ServiceType"),
  367. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  368. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD},
  369. { TEXT("StartType"),
  370. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  371. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD },
  372. { TEXT("Path"),
  373. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  374. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  375. { TEXT("ErrorControl"),
  376. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  377. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD },
  378. { TEXT("LoadOrderGroup"),
  379. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  380. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  381. { TEXT("ServiceAccountName"),
  382. TEXT(""), TEXT("String"), DNLEN+UNLEN+2, 0, FALSE,
  383. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR},
  384. { TEXT("Dependencies"),
  385. TEXT(""), TEXT("String"), MAX_STRLEN, 0, TRUE,
  386. PROPERTY_RW, 1, NT_SYNTAX_ID_NulledString},
  387. { TEXT("Description"), // FSFileServiceGeneralInfo
  388. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  389. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  390. { TEXT("MaxUserCount"),
  391. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  392. PROPERTY_RW, 2, NT_SYNTAX_ID_DWORD },
  393. { TEXT("Name"),
  394. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  395. PROPERTY_READABLE, 2, NT_SYNTAX_ID_LPTSTR }
  396. };
  397. DWORD gdwFPNWFileServiceTableSize = sizeof(FPNWFileServiceClass)/sizeof(PROPERTYINFO);
  398. PROPERTYINFO FPNWSessionClass[] =
  399. { { TEXT("User"), // ro, FSSessionGeneralInfo
  400. TEXT(""), TEXT("String"), UNLEN+1, 0, FALSE,
  401. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  402. { TEXT("Computer"), // ro
  403. TEXT(""), TEXT("String"), UNCLEN+1, 0, FALSE,
  404. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR},
  405. { TEXT("ConnectTime"), // ro
  406. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  407. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DATE },
  408. { TEXT("Name"),
  409. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  410. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR }
  411. };
  412. DWORD gdwFPNWSessionTableSize = sizeof(FPNWSessionClass)/sizeof(PROPERTYINFO);
  413. PROPERTYINFO FPNWResourceClass[] =
  414. { { TEXT("User"), // ro, FSResourceGeneralInfo
  415. TEXT(""), TEXT("String"), UNLEN+1, 0, FALSE,
  416. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  417. { TEXT("Path"), // ro
  418. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  419. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  420. { TEXT("LockCount"), // ro
  421. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  422. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DWORD},
  423. { TEXT("Name"),
  424. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  425. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR }
  426. };
  427. DWORD gdwFPNWResourceTableSize = sizeof(FPNWResourceClass)/sizeof(PROPERTYINFO);
  428. PROPERTYINFO FPNWFileShareClass[] =
  429. { { TEXT("CurrentUserCount"), // ro, FSFileShareGeneralInfo
  430. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  431. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DWORD },
  432. { TEXT("HostComputer"),
  433. TEXT(""), TEXT("ADsPath"), MAX_STRLEN, 0, FALSE,
  434. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  435. { TEXT("Path"),
  436. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  437. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  438. { TEXT("MaxUserCount"),
  439. TEXT(""), TEXT("Integer"), MAX_LONG, -1, FALSE,
  440. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD },
  441. { TEXT("Name"),
  442. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  443. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR }
  444. };
  445. DWORD gdwFPNWFileShareTableSize = sizeof(FPNWFileShareClass)/sizeof(PROPERTYINFO);
  446. PROPERTYINFO PrintQueueClass[] =
  447. { { TEXT("PrinterPath"), // FSPrintQueueGeneralInfo
  448. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  449. PROPERTY_READABLE, 2, NT_SYNTAX_ID_LPTSTR },
  450. { TEXT("PrinterName"), // friendly name
  451. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  452. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  453. { TEXT("Model"),
  454. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  455. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  456. { TEXT("Datatype"),
  457. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  458. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  459. { TEXT("PrintProcessor"),
  460. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  461. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  462. { TEXT("Description"),
  463. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  464. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  465. { TEXT("Location"),
  466. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  467. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  468. { TEXT("StartTime"),
  469. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  470. PROPERTY_RW, 2, NT_SYNTAX_ID_DATE },
  471. { TEXT("UntilTime"),
  472. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  473. PROPERTY_RW, 2, NT_SYNTAX_ID_DATE },
  474. { TEXT("DefaultJobPriority"),
  475. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  476. PROPERTY_RW, 2, NT_SYNTAX_ID_DWORD},
  477. { TEXT("JobCount"),
  478. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  479. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD},
  480. { TEXT("Priority"),
  481. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  482. PROPERTY_RW, 2, NT_SYNTAX_ID_DWORD },
  483. { TEXT("Attributes"),
  484. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  485. PROPERTY_RW, 2, NT_SYNTAX_ID_DWORD},
  486. { TEXT("BannerPage"),
  487. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  488. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  489. { TEXT("PrintDevices"),
  490. TEXT(""), TEXT("String"), MAX_STRLEN, 0, TRUE,
  491. PROPERTY_RW, 2, NT_SYNTAX_ID_DelimitedString } ,
  492. { TEXT("ObjectGUID"),
  493. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  494. PROPERTY_RW, 7, NT_SYNTAX_ID_LPTSTR },
  495. { TEXT("Action"),
  496. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  497. PROPERTY_RW, 7, NT_SYNTAX_ID_DWORD },
  498. { TEXT("Name"),
  499. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  500. PROPERTY_READABLE, 2, NT_SYNTAX_ID_LPTSTR }
  501. };
  502. DWORD gdwPrinterTableSize = sizeof(PrintQueueClass)/sizeof(PROPERTYINFO);
  503. PROPERTYINFO PrintJobClass[] =
  504. { { TEXT("HostPrintQueue"), // ro, FSPrintJobGeneralInfo
  505. TEXT(""), TEXT("ADsPath"), MAX_STRLEN, 0, FALSE,
  506. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  507. { TEXT("User"), // ro
  508. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  509. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  510. { TEXT("TimeSubmitted"), // ro
  511. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  512. PROPERTY_READABLE, 1, NT_SYNTAX_ID_SYSTEMTIME },
  513. { TEXT("TotalPages"), // ro
  514. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  515. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DWORD },
  516. { TEXT("Size"), // ro
  517. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  518. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD},
  519. { TEXT("Description"),
  520. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  521. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  522. { TEXT("Priority"),
  523. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  524. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD},
  525. { TEXT("StartTime"),
  526. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  527. PROPERTY_RW, 2, NT_SYNTAX_ID_DATE },
  528. { TEXT("UntilTime"),
  529. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  530. PROPERTY_RW, 2, NT_SYNTAX_ID_DATE },
  531. { TEXT("Notify"),
  532. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  533. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  534. { TEXT("TimeElapsed"), // ro
  535. TEXT(""), TEXT("Interval"), MAX_LONG, 0, FALSE,
  536. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD },
  537. { TEXT("PagesPrinted"), // ro
  538. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  539. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD },
  540. { TEXT("Position"),
  541. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  542. PROPERTY_RW, 2, NT_SYNTAX_ID_DWORD },
  543. { TEXT("ObjectGUID"),
  544. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  545. PROPERTY_RW, 7, NT_SYNTAX_ID_LPTSTR },
  546. { TEXT("Action"),
  547. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  548. PROPERTY_RW, 7, NT_SYNTAX_ID_DWORD },
  549. { TEXT("Name"),
  550. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  551. PROPERTY_READABLE, 2, NT_SYNTAX_ID_LPTSTR }
  552. };
  553. DWORD gdwJobTableSize = sizeof(PrintJobClass)/sizeof(PROPERTYINFO);
  554. CLASSINFO g_aWinNTClasses[] =
  555. {
  556. // Domain
  557. { DOMAIN_SCHEMA_NAME, &CLSID_WinNTDomain, &IID_IADsDomain,
  558. TEXT(""), FALSE,
  559. NULL,
  560. TEXT("MinPasswordLength,MinPasswordAge,MaxPasswordAge,MaxBadPasswordsAllowed,")
  561. TEXT("PasswordHistoryLength,AutoUnlockInterval,LockoutObservationInterval,Name"),
  562. NULL, TEXT("Computer,User,Group"),TRUE,
  563. TEXT(""), 0,
  564. DomainClass, sizeof(DomainClass)/sizeof(PROPERTYINFO) },
  565. // Computer
  566. { COMPUTER_SCHEMA_NAME, &CLSID_WinNTComputer, &IID_IADsComputer,
  567. TEXT(""), FALSE,
  568. NULL,
  569. TEXT("Owner,Division,OperatingSystem,OperatingSystemVersion,")
  570. TEXT("Processor,ProcessorCount,Name"),
  571. TEXT("Domain"), TEXT("User,Group,Service,FileService,PrintQueue"), TRUE,
  572. TEXT(""), 0,
  573. ComputerClass, sizeof(ComputerClass)/sizeof(PROPERTYINFO) },
  574. // User
  575. { USER_SCHEMA_NAME, &CLSID_WinNTUser, &IID_IADsUser,
  576. TEXT(""), FALSE,
  577. NULL,
  578. TEXT("Description,FullName,AccountExpirationDate,")
  579. TEXT("BadPasswordAttempts,HomeDirDrive,HomeDirectory,")
  580. TEXT("LastLogin,LastLogoff,LoginHours,LoginScript,LoginWorkstations,")
  581. TEXT("MaxLogins,MaxPasswordAge,MaxStorage,")
  582. TEXT("MinPasswordAge,MinPasswordLength,objectSid,")
  583. TEXT("Parameters,PasswordAge,PasswordExpired,")
  584. TEXT("PasswordHistoryLength,PrimaryGroupID,Profile,UserFlags,")
  585. TEXT("RasPermissions,Name"),
  586. TEXT("Domain,Computer"), NULL, FALSE,
  587. TEXT(""), 0,
  588. UserClass, sizeof(UserClass)/sizeof(PROPERTYINFO) },
  589. // Group
  590. { GROUP_SCHEMA_NAME, &CLSID_WinNTGroup, &IID_IADsGroup,
  591. TEXT(""), FALSE,
  592. TEXT("groupType"),
  593. TEXT("Description,objectSid,Name"),
  594. TEXT("Domain,Computer"), NULL, FALSE,
  595. TEXT(""), 0,
  596. GroupClass, sizeof(GroupClass)/sizeof(PROPERTYINFO) },
  597. { SERVICE_SCHEMA_NAME, &CLSID_WinNTService, &IID_IADsService,
  598. TEXT(""), FALSE,
  599. TEXT("StartType,ServiceType,")
  600. TEXT("DisplayName,Path,ErrorControl"),
  601. TEXT("HostComputer,")
  602. TEXT("LoadOrderGroup,ServiceAccountName,")
  603. TEXT("Dependencies,Name"),
  604. TEXT("Computer"), NULL, FALSE,
  605. TEXT(""), 0,
  606. ServiceClass, sizeof(ServiceClass)/sizeof(PROPERTYINFO) },
  607. { FILESERVICE_SCHEMA_NAME, &CLSID_WinNTFileService, &IID_IADsFileService,
  608. TEXT(""), FALSE,
  609. NULL,
  610. TEXT("HostComputer,DisplayName,Version,ServiceType,StartType,")
  611. TEXT("ErrorControl,LoadOrderGroup,ServiceAccountName,Dependencies,")
  612. TEXT("Description,MaxUserCount,Name"),
  613. TEXT("Computer"), TEXT("FileShare"), TRUE,
  614. TEXT(""), 0,
  615. FileServiceClass, sizeof(FileServiceClass)/sizeof(PROPERTYINFO) },
  616. { SESSION_SCHEMA_NAME, &CLSID_WinNTSession, &IID_IADsSession,
  617. TEXT(""), FALSE,
  618. NULL,
  619. TEXT("User,Computer,ConnectTime,IdleTime,Name"),
  620. NULL, NULL, FALSE,
  621. TEXT(""), 0,
  622. SessionClass, sizeof(SessionClass)/sizeof(PROPERTYINFO) },
  623. { RESOURCE_SCHEMA_NAME, &CLSID_WinNTResource, &IID_IADsResource,
  624. TEXT(""), FALSE,
  625. NULL,
  626. TEXT("User,Path,LockCount,Name"),
  627. NULL, NULL, FALSE,
  628. TEXT(""), 0,
  629. ResourceClass, sizeof(ResourceClass)/sizeof(PROPERTYINFO) },
  630. { FILESHARE_SCHEMA_NAME, &CLSID_WinNTFileShare, &IID_IADsFileShare,
  631. TEXT(""), FALSE,
  632. TEXT("Path,MaxUserCount"),
  633. TEXT("CurrentUserCount,Description,HostComputer,Name"),
  634. TEXT("FileService"),
  635. NULL, FALSE,
  636. TEXT(""), 0,
  637. FileShareClass, sizeof(FileShareClass)/sizeof(PROPERTYINFO) },
  638. { FPNW_FILESERVICE_SCHEMA_NAME, &CLSID_WinNTFileService, &IID_IADsFileService,
  639. TEXT(""), FALSE,
  640. NULL,
  641. TEXT("HostComputer,DisplayName,Version,ServiceType,")
  642. TEXT("StartType,Path,ErrorControl,LoadOrderGroup,")
  643. TEXT("Description,MaxUserCount,Name"),
  644. TEXT("Computer"), TEXT("FileShare"), TRUE,
  645. TEXT(""), 0,
  646. FileServiceClass, sizeof(FileServiceClass)/sizeof(PROPERTYINFO) },
  647. { FPNW_SESSION_SCHEMA_NAME, &CLSID_WinNTSession, &IID_IADsSession,
  648. TEXT(""), FALSE,
  649. NULL,
  650. TEXT("User,Computer,ConnectTime,Name"),
  651. NULL, NULL, FALSE,
  652. TEXT(""), 0,
  653. SessionClass, sizeof(SessionClass)/sizeof(PROPERTYINFO) },
  654. { FPNW_RESOURCE_SCHEMA_NAME, &CLSID_WinNTResource, &IID_IADsResource,
  655. TEXT(""), FALSE,
  656. NULL,
  657. TEXT("User,Path,LockCount,Name"),
  658. NULL, NULL, FALSE,
  659. TEXT(""), 0,
  660. ResourceClass, sizeof(ResourceClass)/sizeof(PROPERTYINFO) },
  661. { FPNW_FILESHARE_SCHEMA_NAME, &CLSID_WinNTFileShare, &IID_IADsFileShare,
  662. TEXT(""), FALSE,
  663. TEXT("Path,MaxUserCount"),
  664. TEXT("CurrentUserCount,HostComputer,Name"),
  665. TEXT("FileService"),
  666. NULL, FALSE,
  667. TEXT(""), 0,
  668. FileShareClass, sizeof(FileShareClass)/sizeof(PROPERTYINFO) },
  669. { PRINTER_SCHEMA_NAME, &CLSID_WinNTPrintQueue, &IID_IADsPrintQueue,
  670. TEXT(""), FALSE,
  671. TEXT("PrinterName,Model,Datatype,")
  672. TEXT("PrintProcessor,PrintDevices"),
  673. TEXT("HostComputer,Description,")
  674. TEXT("Location,StartTime,UntilTime,DefaultJobPriority,JobCount,Priority,")
  675. TEXT("Attributes,BannerPage,ObjectGUID,Action,Name"),
  676. TEXT("Computer"), NULL, FALSE,
  677. TEXT(""), 0,
  678. PrintQueueClass, sizeof(PrintQueueClass)/sizeof(PROPERTYINFO) },
  679. { PRINTJOB_SCHEMA_NAME, &CLSID_WinNTPrintJob, &IID_IADsPrintJob,
  680. TEXT(""), FALSE,
  681. NULL,
  682. TEXT("HostPrintQueue,User,TimeSubmitted,TotalPages,Size,Description,")
  683. TEXT("Priority,StartTime,UntilTime,Notify,TimeElapsed,PagesPrinted,")
  684. TEXT("Position,Name"),
  685. NULL, NULL, FALSE,
  686. TEXT(""), 0,
  687. PrintJobClass, sizeof(PrintJobClass)/sizeof(PROPERTYINFO) }
  688. };
  689. SYNTAXINFO g_aWinNTSyntax[] =
  690. { { TEXT("Boolean"), VT_BOOL },
  691. { TEXT("Counter"), VT_I4 },
  692. { TEXT("ADsPath"), VT_BSTR },
  693. { TEXT("EmailAddress"), VT_BSTR },
  694. { TEXT("FaxNumber"), VT_BSTR },
  695. { TEXT("Integer"), VT_I4 },
  696. { TEXT("Interval"), VT_I4 },
  697. { TEXT("List"), VT_VARIANT }, // VT_BSTR | VT_ARRAY
  698. { TEXT("NetAddress"), VT_BSTR },
  699. { TEXT("OctetString"), VT_VARIANT }, // VT_UI1| VT_ARRAY
  700. { TEXT("Path"), VT_BSTR },
  701. { TEXT("PhoneNumber"), VT_BSTR },
  702. { TEXT("PostalAddress"), VT_BSTR },
  703. { TEXT("SmallInterval"), VT_I4 },
  704. { TEXT("String"), VT_BSTR },
  705. { TEXT("Time"), VT_DATE }
  706. };
  707. DWORD g_cWinNTClasses = (sizeof(g_aWinNTClasses)/sizeof(g_aWinNTClasses[0]));
  708. DWORD g_cWinNTSyntax = (sizeof(g_aWinNTSyntax)/sizeof(g_aWinNTSyntax[0]));
  709. CObjNameCache * pgPDCNameCache = NULL;
  710. PROPERTYINFO g_aWinNTProperties[] =
  711. //
  712. // domain properties
  713. //
  714. { { TEXT("MinPasswordLength"), // FSDomainPassword
  715. TEXT(""), TEXT("Integer"), LM20_PWLEN+1, 0, FALSE,
  716. PROPERTY_RW, 0, NT_SYNTAX_ID_DWORD },
  717. { TEXT("MinPasswordAge"),
  718. TEXT(""), TEXT("Interval"), TIMEQ_FOREVER, 0, FALSE,
  719. PROPERTY_RW, 0, NT_SYNTAX_ID_DWORD },
  720. { TEXT("MaxPasswordAge"),
  721. TEXT(""),TEXT("Interval"), TIMEQ_FOREVER, ONE_DAY, FALSE,
  722. PROPERTY_RW, 0, NT_SYNTAX_ID_DWORD },
  723. { TEXT("MaxBadPasswordsAllowed"),
  724. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  725. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  726. //
  727. // NetAPI state DEF_MAX_PWHIST (8), but NetAPI devlpr confirm
  728. // current is 1024. Ignore Net Account - UNIQUEPWD limit.
  729. // User DEF_MAX_PWHIST to be safe for now.
  730. // not repeated for user ??
  731. //
  732. { TEXT("PasswordHistoryLength"),
  733. TEXT(""), TEXT("Integer"), DEF_MAX_PWHIST, 0, FALSE,
  734. PROPERTY_RW, 0, NT_SYNTAX_ID_DWORD},
  735. { TEXT("AutoUnlockInterval"),
  736. TEXT(""), TEXT("Interval"), MAX_LONG, 0, FALSE,
  737. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  738. { TEXT("LockoutObservationInterval"),
  739. TEXT(""), TEXT("Interval"), MAX_LONG, 0, FALSE,
  740. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  741. // Computer Properties
  742. { TEXT("Owner"),
  743. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  744. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR },
  745. { TEXT("Division"),
  746. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  747. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR },
  748. { TEXT("OperatingSystem"), // ro
  749. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  750. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR},
  751. { TEXT("OperatingSystemVersion"), // ro
  752. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  753. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR},
  754. { TEXT("Processor"),
  755. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  756. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR },
  757. { TEXT("ProcessorCount"),
  758. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  759. PROPERTY_RW, 4, NT_SYNTAX_ID_LPTSTR },
  760. // User Properties
  761. { TEXT("Description"), // FSUserBusinessInfo
  762. TEXT(""), TEXT("String"), MAXCOMMENTSZ+1, 0, FALSE,
  763. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR },
  764. { TEXT("FullName"),
  765. TEXT(""), TEXT("String"), MAXCOMMENTSZ+1, 0, FALSE,
  766. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR},
  767. { TEXT("AccountExpirationDate"),
  768. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  769. PROPERTY_RW, 3, NT_SYNTAX_ID_DATE_1970},
  770. { TEXT("PasswordAge"),
  771. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  772. PROPERTY_RW, 3, NT_SYNTAX_ID_DATE_1970},
  773. { TEXT("UserFlags"),
  774. TEXT(""), TEXT("Integer"), 0, 0, FALSE,
  775. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD},
  776. { TEXT("LoginWorkstations"),
  777. TEXT(""), TEXT("String"), MAX_STRLEN, 0, TRUE,
  778. PROPERTY_RW, 3, NT_SYNTAX_ID_DelimitedString },
  779. { TEXT("BadPasswordAttempts"), //ro
  780. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  781. PROPERTY_READABLE, 3, NT_SYNTAX_ID_DWORD },
  782. { TEXT("MaxLogins"),
  783. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  784. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  785. { TEXT("MaxStorage"),
  786. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  787. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  788. // USER_MAX_STORAGE_UNLIMITED
  789. { TEXT("PasswordExpired"),
  790. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  791. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  792. { TEXT("PasswordExpirationDate"),
  793. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  794. PROPERTY_RW, 3, NT_SYNTAX_ID_DATE_1970 },
  795. { TEXT("LastLogin"), // ro
  796. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  797. PROPERTY_READABLE, 3, NT_SYNTAX_ID_DATE_1970 },
  798. { TEXT("LastLogoff"), // ro
  799. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  800. PROPERTY_READABLE, 3, NT_SYNTAX_ID_DATE_1970 },
  801. { TEXT("HomeDirectory"),
  802. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  803. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR },
  804. { TEXT("Profile"),
  805. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  806. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR},
  807. { TEXT("Parameters"),
  808. TEXT(""), TEXT("String"), MAX_PATH, 0, FALSE,
  809. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR},
  810. { TEXT("HomeDirDrive"),
  811. TEXT(""), TEXT("String"), MAX_PATH, 0, FALSE,
  812. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR},
  813. { TEXT("LoginScript"),
  814. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  815. PROPERTY_RW, 3, NT_SYNTAX_ID_LPTSTR },
  816. { TEXT("LoginHours"),
  817. TEXT(""), TEXT("OctetString"), 0, 0, FALSE,
  818. PROPERTY_RW, 3, NT_SYNTAX_ID_OCTETSTRING},
  819. { TEXT("PrimaryGroupID"),
  820. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  821. PROPERTY_RW, 3, NT_SYNTAX_ID_DWORD },
  822. { TEXT("objectSid"),
  823. TEXT(""), TEXT("OctetString"), 0, 0, FALSE,
  824. PROPERTY_READABLE, 20, NT_SYNTAX_ID_OCTETSTRING},
  825. #ifndef WIN95
  826. { TEXT("RasPermissions"),
  827. TEXT(""), TEXT("Integer"), 0, 0, FALSE,
  828. PROPERTY_RW, 21, NT_SYNTAX_ID_DWORD},
  829. #endif
  830. // Group Properties
  831. { TEXT("groupType"),
  832. TEXT(""), TEXT("Integer"), 0, 0, FALSE,
  833. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD },
  834. //
  835. // Description (User)
  836. //
  837. // Service Properties
  838. { TEXT("HostComputer"), // FSServiceConfiguration
  839. TEXT(""), TEXT("ADsPath"), MAX_STRLEN, 0, FALSE,
  840. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  841. { TEXT("DisplayName"),
  842. TEXT(""), TEXT("String"), 256, 0, FALSE,
  843. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  844. { TEXT("ServiceType"),
  845. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  846. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD},
  847. { TEXT("StartType"),
  848. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  849. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD },
  850. { TEXT("Path"),
  851. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  852. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  853. { TEXT("ErrorControl"),
  854. TEXT(""), TEXT("Integer"), MAX_LONG, MIN_LONG, FALSE,
  855. PROPERTY_RW, 1, NT_SYNTAX_ID_DWORD },
  856. { TEXT("LoadOrderGroup"),
  857. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  858. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  859. { TEXT("ServiceAccountName"),
  860. TEXT(""), TEXT("String"), DNLEN+UNLEN+2, 0, FALSE,
  861. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR},
  862. { TEXT("Dependencies"),
  863. TEXT(""), TEXT("String"), MAX_STRLEN, 0, TRUE,
  864. PROPERTY_RW, 1, NT_SYNTAX_ID_NulledString},
  865. // File Service Properties
  866. //
  867. // HostComputer(Service
  868. //
  869. //
  870. // DisplayName (Service)
  871. //
  872. { TEXT("Version"),
  873. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  874. PROPERTY_RW, 1, NT_SYNTAX_ID_LPTSTR },
  875. //
  876. // ServiceType (service)
  877. //
  878. // StartType (service)
  879. //
  880. //
  881. // Path (Service)
  882. //
  883. //
  884. // ErrorControl (service)
  885. //
  886. //
  887. // LoadOrderGroup(service)
  888. //
  889. //
  890. // ServiceAccountName (service)
  891. //
  892. //
  893. // Dependencies (Service)
  894. //
  895. // Description (user)
  896. //
  897. { TEXT("MaxUserCount"),
  898. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  899. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD },
  900. // Session Properties
  901. { TEXT("User"), // ro, FSSessionGeneralInfo
  902. TEXT(""), TEXT("String"), UNLEN+1, 0, FALSE,
  903. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  904. { TEXT("Computer"), // ro
  905. TEXT(""), TEXT("String"), UNCLEN+1, 0, FALSE,
  906. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR},
  907. { TEXT("ConnectTime"), // ro
  908. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  909. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DATE },
  910. { TEXT("IdleTime"), // ro
  911. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  912. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DATE},
  913. // Resource Properties
  914. //
  915. // User (session)
  916. //
  917. // Path (service)
  918. //
  919. { TEXT("LockCount"), // ro
  920. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  921. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DWORD},
  922. // FileShareClass
  923. { TEXT("CurrentUserCount"), // ro, FSFileShareGeneralInfo
  924. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  925. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD },
  926. //
  927. // Description (User)
  928. //
  929. //
  930. // HostComputer(Service)
  931. //
  932. //
  933. // Path (service)
  934. //
  935. //
  936. // MaxUserCount(FileService)
  937. //
  938. // FPNWFileServiceClass
  939. //
  940. // HostComputer (Service)
  941. //
  942. //
  943. // DisplayName (Service)
  944. //
  945. // Version (FileService)
  946. //
  947. //
  948. // ServiceType (service)
  949. //
  950. // StartType (service)
  951. //
  952. //
  953. // Path (Service)
  954. //
  955. //
  956. // ErrorControl (Service)
  957. //
  958. //
  959. // LoadOrderGroup (Service)
  960. //
  961. //
  962. // ServiceAccountName (service)
  963. //
  964. //
  965. // Dependencies (service)
  966. //
  967. //
  968. // Description (User)
  969. //
  970. //
  971. // MaxUserCount(FileService)
  972. //
  973. // FPNWSession Class
  974. //
  975. // User (Session)
  976. //
  977. //
  978. // Computer (session)
  979. //
  980. // ConnectTime (session)
  981. // FPNWResourceClass
  982. //
  983. // User (Session)
  984. //
  985. //
  986. // Path (Service)
  987. //
  988. //
  989. // LockCount (resource)
  990. //
  991. // FPNWFileShareClass
  992. // CurrentUserCount (FileShare)
  993. //
  994. // HostComputer(Service)
  995. //
  996. //
  997. // Path (service)
  998. //
  999. //
  1000. // MaxUserCount (FileService)
  1001. //
  1002. // PrintQueueClass
  1003. { TEXT("PrinterPath"), // FSPrintQueueGeneralInfo
  1004. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  1005. PROPERTY_READABLE, 2, NT_SYNTAX_ID_LPTSTR },
  1006. { TEXT("PrinterName"), // friendly name
  1007. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  1008. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  1009. { TEXT("Model"),
  1010. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  1011. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  1012. { TEXT("Datatype"),
  1013. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  1014. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  1015. { TEXT("PrintProcessor"),
  1016. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  1017. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  1018. { TEXT("ObjectGUID"),
  1019. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  1020. PROPERTY_RW, 7, NT_SYNTAX_ID_LPTSTR },
  1021. { TEXT("Action"),
  1022. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  1023. PROPERTY_RW, 7, NT_SYNTAX_ID_DWORD },
  1024. //
  1025. // Description (user)
  1026. //
  1027. { TEXT("Location"),
  1028. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  1029. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  1030. { TEXT("StartTime"),
  1031. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  1032. PROPERTY_RW, 2, NT_SYNTAX_ID_DATE },
  1033. { TEXT("UntilTime"),
  1034. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  1035. PROPERTY_RW, 2, NT_SYNTAX_ID_DATE },
  1036. { TEXT("DefaultJobPriority"),
  1037. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  1038. PROPERTY_RW, 2, NT_SYNTAX_ID_DWORD},
  1039. { TEXT("JobCount"),
  1040. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  1041. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD},
  1042. { TEXT("Priority"),
  1043. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  1044. PROPERTY_RW, 2, NT_SYNTAX_ID_DWORD },
  1045. { TEXT("Attributes"),
  1046. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  1047. PROPERTY_RW, 2, NT_SYNTAX_ID_DWORD },
  1048. { TEXT("BannerPage"),
  1049. TEXT(""), TEXT("Path"), MAX_PATH, 0, FALSE,
  1050. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  1051. { TEXT("PrintDevices"),
  1052. TEXT(""), TEXT("String"), MAX_STRLEN, 0, TRUE,
  1053. PROPERTY_RW, 2, NT_SYNTAX_ID_DelimitedString },
  1054. // PrintJobClass
  1055. { TEXT("HostPrintQueue"), // ro, FSPrintJobGeneralInfo
  1056. TEXT(""), TEXT("ADsPath"), MAX_STRLEN, 0, FALSE,
  1057. PROPERTY_READABLE, 1, NT_SYNTAX_ID_LPTSTR },
  1058. { TEXT("TimeSubmitted"), // ro
  1059. TEXT(""), TEXT("Time"), 0, 0, FALSE,
  1060. PROPERTY_READABLE, 1, NT_SYNTAX_ID_SYSTEMTIME },
  1061. { TEXT("TotalPages"), // ro
  1062. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  1063. PROPERTY_READABLE, 1, NT_SYNTAX_ID_DWORD },
  1064. { TEXT("Size"), // ro
  1065. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  1066. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD},
  1067. //
  1068. // Description (User)
  1069. //
  1070. //
  1071. // Priority (PrintQueue)
  1072. //
  1073. // StartTime (PrintQueue)
  1074. //
  1075. // UntilTime (PrintQueue)
  1076. //
  1077. { TEXT("Notify"),
  1078. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  1079. PROPERTY_RW, 2, NT_SYNTAX_ID_LPTSTR },
  1080. { TEXT("TimeElapsed"), // ro
  1081. TEXT(""), TEXT("Interval"), MAX_LONG, 0, FALSE,
  1082. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD },
  1083. { TEXT("PagesPrinted"), // ro
  1084. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  1085. PROPERTY_READABLE, 2, NT_SYNTAX_ID_DWORD },
  1086. { TEXT("Position"),
  1087. TEXT(""), TEXT("Integer"), MAX_LONG, 0, FALSE,
  1088. PROPERTY_RW, 2, NT_SYNTAX_ID_DWORD },
  1089. // Name is common to all classes. Add one entry here for it.
  1090. { TEXT("Name"),
  1091. TEXT(""), TEXT("String"), MAX_STRLEN, 0, FALSE,
  1092. PROPERTY_READABLE, 0, NT_SYNTAX_ID_LPTSTR }
  1093. };
  1094. DWORD g_cWinNTProperties = sizeof(g_aWinNTProperties)/sizeof(PROPERTYINFO);
  1095. //
  1096. // Support routines for dynamically loading entry points.
  1097. //
  1098. void BindToDlls()
  1099. {
  1100. DWORD dwErr = 0;
  1101. if (!g_fDllsLoaded) {
  1102. EnterCriticalSection(&g_csLoadLibs);
  1103. if (!g_fDllsLoaded) {
  1104. g_hDllNetapi32 = LoadLibrary(L"NETAPI32.DLL");
  1105. if (!g_hDllNetapi32) {
  1106. dwErr = GetLastError();
  1107. }
  1108. if (g_hDllAdvapi32 = LoadLibrary(L"ADVAPI32.DLL")) {
  1109. if (dwErr) {
  1110. //
  1111. // Set the last error for whatever it is worth.
  1112. // This does not really matter cause any dll we
  1113. // cannot load, we will not get functions on that
  1114. // dll. If secur32 load failed, then that call
  1115. // would have set a relevant last error.
  1116. //
  1117. SetLastError(dwErr);
  1118. }
  1119. }
  1120. g_fDllsLoaded = TRUE;
  1121. LeaveCriticalSection(&g_csLoadLibs);
  1122. }
  1123. }
  1124. }
  1125. //
  1126. // Locates entry points in NetApi32.
  1127. //
  1128. PVOID LoadNetApi32Function(CHAR *function)
  1129. {
  1130. if (!g_fDllsLoaded) {
  1131. BindToDlls();
  1132. }
  1133. if (g_hDllNetapi32) {
  1134. return((PVOID*) GetProcAddress((HMODULE) g_hDllNetapi32, function));
  1135. }
  1136. return NULL;
  1137. }
  1138. //
  1139. // Locates entry points in advapi32
  1140. //
  1141. PVOID LoadAdvapi32Function(CHAR *function)
  1142. {
  1143. if (!g_fDllsLoaded) {
  1144. BindToDlls();
  1145. }
  1146. if (g_hDllAdvapi32) {
  1147. return((PVOID*) GetProcAddress((HMODULE) g_hDllAdvapi32, function));
  1148. }
  1149. return NULL;
  1150. }
  1151. //
  1152. // DsUnquoteRdnValueWrapper
  1153. //
  1154. BOOL ConvertStringSidToSidWrapper(
  1155. IN LPCWSTR StringSid,
  1156. OUT PSID *Sid
  1157. )
  1158. {
  1159. static PF_ConvertStringSidToSid pfConvertStringSidToSid = NULL;
  1160. static BOOL f_LoadAttempted = FALSE;
  1161. //
  1162. // Load the fn and set the variables accordingly.
  1163. //
  1164. if (!f_LoadAttempted && pfConvertStringSidToSid == NULL) {
  1165. pfConvertStringSidToSid
  1166. = (PF_ConvertStringSidToSid)
  1167. LoadAdvapi32Function(CONVERT_STRING_TO_SID_API);
  1168. f_LoadAttempted = TRUE;
  1169. }
  1170. if (pfConvertStringSidToSid != NULL) {
  1171. return ((*pfConvertStringSidToSid)(
  1172. StringSid,
  1173. Sid
  1174. )
  1175. );
  1176. }
  1177. else {
  1178. SetLastError(ERROR_GEN_FAILURE);
  1179. return (FALSE);
  1180. }
  1181. }
  1182. BOOL ConvertSidToStringSidWrapper(
  1183. IN PSID Sid,
  1184. OUT LPWSTR *StringSid
  1185. )
  1186. {
  1187. static PF_ConvertSidToStringSid pfConvertSidToSidString = NULL;
  1188. static BOOL f_LoadAttempted = FALSE;
  1189. //
  1190. // Load the fn and set the variables accordingly.
  1191. //
  1192. if (!f_LoadAttempted && pfConvertSidToSidString == NULL) {
  1193. pfConvertSidToSidString =
  1194. (PF_ConvertSidToStringSid)
  1195. LoadAdvapi32Function(CONVERT_SID_TO_STRING_API);
  1196. f_LoadAttempted = TRUE;
  1197. }
  1198. if (pfConvertSidToSidString != NULL) {
  1199. return ((*pfConvertSidToSidString)(
  1200. Sid,
  1201. StringSid
  1202. )
  1203. );
  1204. }
  1205. else {
  1206. SetLastError(ERROR_GEN_FAILURE);
  1207. return (FALSE);
  1208. }
  1209. }