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.

496 lines
14 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Active Directory 1.1 Sample Code
  4. //
  5. // Copyright (C) Microsoft Corporation, 1992 - 1995
  6. //
  7. // File: util.cxx
  8. //
  9. // Contents: Ansi to Unicode conversions and misc helper functions
  10. //
  11. //----------------------------------------------------------------------------//------------------------------------------------------------------------------
  12. #include "main.hxx"
  13. void
  14. PrintUsage(
  15. void
  16. )
  17. {
  18. printf("\nUsage: adsqry /b <baseObject> /f <search_filter> /a <attrlist> [/p <preference=value>] ");
  19. printf(" [/u <UserName> <Password>] /d <dialect> \n");
  20. printf("\n where:\n" );
  21. printf(" baseObject = ADsPath of the base of the search\n");
  22. printf(" search_filter = search filter string in LDAP format\n" );
  23. printf(" attrlist = list of the attributes to display\n" );
  24. printf(" dialect is one of \"ldap\", \"sql\", or \"default\"\n");
  25. printf(" preference could be one of:\n");
  26. printf(" Asynchronous, AttrTypesOnly, DerefAliases, SizeLimit, TimeLimit, sortOn \n");
  27. printf(" TimeOut, PageSize, SearchScope, CacheResults, SecureAuth and EncryptPassword\n");
  28. printf(" value is yes/no for a Boolean and the respective integer for integers\n");
  29. printf(" list of comma separated attributes for sortOn\n");
  30. printf(" scope is one of \"Base\", \"OneLevel\", or \"Subtree\"\n");
  31. printf("\nFor Example: adsqry /b \"LDAP://ntdsdc0/DC=COM/");
  32. printf("DC=MICROSOFT/DC=NTDEV\" /f \"(objectClass=Group)\" /a \"ADsPath, name, description\" ");
  33. printf(" /u \"CN=NTDEV,CN=Users,DC=NTDEV,DC=MICROSOFT,DC=COM,O=INTERNET\" \"NTDEV\" \n");
  34. printf("\nFor Example: adsqry /b \"LDAP://ntdsdc0/DC=COM/");
  35. printf("DC=MICROSOFT/DC=NTDEV\" /f \"objectClass='Group'\" /a \"ADsPath, name, description\" ");
  36. printf(" /d sql /u \"CN=NTDEV,CN=Users,DC=NTDEV,DC=MICROSOFT,DC=COM,O=INTERNET\" \"NTDEV\" \n");
  37. }
  38. //
  39. // Form the bindings array to specify the way the provider has to put the
  40. // data in consumer's buffers; Create the Accessor from the bindings
  41. //
  42. HRESULT
  43. CreateAccessorHelper(
  44. IRowset *pIRowset,
  45. DBORDINAL nAttrs,
  46. DBCOLUMNINFO *prgColInfo,
  47. HACCESSOR *phAccessor,
  48. DBBINDSTATUS *pBindStatus
  49. )
  50. {
  51. DBBINDING *prgBindings = NULL;
  52. HRESULT hr;
  53. ULONG i;
  54. IAccessor *pIAccessor = NULL;
  55. if(!phAccessor || !pBindStatus)
  56. return(E_INVALIDARG);
  57. prgBindings = (DBBINDING *) LocalAlloc(
  58. LPTR,
  59. sizeof(DBBINDING) * nAttrs
  60. );
  61. BAIL_ON_NULL(prgBindings);
  62. //
  63. // Set up rest of the attributes
  64. //
  65. for (i=0; i < nAttrs; i++) {
  66. prgBindings[i].iOrdinal = i+1;
  67. prgBindings[i].wType= prgColInfo[i+1].wType;
  68. if (prgBindings[i].wType == DBTYPE_DATE || prgBindings[i].wType == DBTYPE_I8)
  69. prgBindings[i].obValue = sizeof(Data)*i + offsetof(Data, obValue2);
  70. else
  71. prgBindings[i].obValue = sizeof(Data)*i + offsetof(Data, obValue);
  72. prgBindings[i].obLength= sizeof(Data)*i + offsetof(Data, obLength);
  73. prgBindings[i].obStatus= sizeof(Data)*i + offsetof(Data, status);
  74. prgBindings[i].dwPart= DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS;
  75. if(prgBindings[i].wType & DBTYPE_BYREF)
  76. prgBindings[i].dwMemOwner= DBMEMOWNER_PROVIDEROWNED;
  77. else
  78. prgBindings[i].dwMemOwner= DBMEMOWNER_CLIENTOWNED;
  79. prgBindings[i].dwFlags= 0;
  80. }
  81. hr= pIRowset->QueryInterface(
  82. IID_IAccessor,
  83. (void**) &pIAccessor
  84. );
  85. BAIL_ON_FAILURE(hr);
  86. //
  87. // With the bindings create the accessor
  88. //
  89. hr = pIAccessor->CreateAccessor(
  90. DBACCESSOR_ROWDATA,
  91. nAttrs,
  92. prgBindings,
  93. 0,
  94. phAccessor,
  95. pBindStatus
  96. );
  97. pIAccessor->Release();
  98. LOCAL_FREE(prgBindings);
  99. return(hr);
  100. error:
  101. LOCAL_FREE(prgBindings);
  102. return(hr);
  103. }
  104. //
  105. // Print the data depending on its type.
  106. //
  107. void
  108. PrintData(
  109. Data *prgData,
  110. DBORDINAL nAttrs,
  111. DBCOLUMNINFO *prgColInfo
  112. )
  113. {
  114. ULONG i, j;
  115. HRESULT hr;
  116. for (i=0; i < nAttrs; i++) {
  117. if(prgData[i].status == DBSTATUS_S_OK) {
  118. switch(prgColInfo[i+1].wType) {
  119. case DBTYPE_I4:
  120. wprintf(
  121. L"%s = %d \n",
  122. prgColInfo[i+1].pwszName,
  123. (DWORD_PTR) prgData[i].obValue
  124. );
  125. break;
  126. case DBTYPE_I8:
  127. wprintf(
  128. L"%s = %I64d \n",
  129. prgColInfo[i+1].pwszName,
  130. *((__int64 *) &prgData[i].obValue2)
  131. );
  132. break;
  133. case DBTYPE_BOOL:
  134. wprintf(
  135. L"%s = %s \n",
  136. prgColInfo[i+1].pwszName,
  137. *((VARIANT_BOOL *) &(prgData[i].obValue)) == VARIANT_TRUE ?
  138. L"TRUE" : L"FALSE"
  139. );
  140. break;
  141. case DBTYPE_STR | DBTYPE_BYREF:
  142. wprintf(
  143. L"%s = ",
  144. prgColInfo[i+1].pwszName
  145. );
  146. printf(
  147. "%s \n",
  148. (char *)prgData[i].obValue
  149. );
  150. break;
  151. case DBTYPE_BYTES | DBTYPE_BYREF:
  152. wprintf(
  153. L"%s = ",
  154. prgColInfo[i+1].pwszName
  155. );
  156. for (j=0; j<prgData[i].obLength; j++) {
  157. printf(
  158. "%x",
  159. ((BYTE *)prgData[i].obValue)[j]
  160. );
  161. }
  162. printf("\n");
  163. break;
  164. case DBTYPE_WSTR | DBTYPE_BYREF:
  165. wprintf(
  166. L"%s = %s \n",
  167. prgColInfo[i+1].pwszName,
  168. (WCHAR *) prgData[i].obValue
  169. );
  170. break;
  171. case DBTYPE_DATE:
  172. SYSTEMTIME UTCTime;
  173. hr = VariantTimeToSystemTime(
  174. prgData[i].obValue2,
  175. &UTCTime);
  176. BAIL_ON_FAILURE(hr);
  177. wprintf(L"%s = %d %d %d",
  178. prgColInfo[i+1].pwszName,
  179. UTCTime.wYear,
  180. UTCTime.wMonth,
  181. UTCTime.wDay);
  182. break;
  183. case DBTYPE_VARIANT | DBTYPE_BYREF:
  184. wprintf(
  185. L"%s = ",
  186. prgColInfo[i+1].pwszName
  187. );
  188. ULONG dwSLBound;
  189. ULONG dwSUBound;
  190. VARIANT *pVarArray;
  191. VARIANT *pVariant;
  192. pVarArray = NULL;
  193. pVariant = (VARIANT*) prgData[i].obValue;
  194. if (pVariant->vt == VT_DISPATCH) {
  195. IDispatch *pDispatch = NULL;
  196. IADsLargeInteger *pLargeInteger = NULL;
  197. LARGE_INTEGER LargeInteger;
  198. pDispatch = V_DISPATCH(pVariant);
  199. hr = pDispatch->QueryInterface(
  200. IID_IADsLargeInteger,
  201. (void **)&pLargeInteger
  202. );
  203. BAIL_ON_FAILURE(hr);
  204. hr = pLargeInteger->get_HighPart((LONG*)&LargeInteger.HighPart);
  205. BAIL_ON_FAILURE(hr);
  206. hr = pLargeInteger->get_LowPart((LONG*)&LargeInteger.LowPart);
  207. BAIL_ON_FAILURE(hr);
  208. wprintf(
  209. L"High:%ld, low:%ld",
  210. LargeInteger.HighPart,
  211. LargeInteger.LowPart
  212. );
  213. break;
  214. }
  215. else {
  216. if( !(pVariant->vt == (VT_ARRAY | VT_VARIANT)))
  217. BAIL_ON_FAILURE(hr = E_FAIL);
  218. hr = SafeArrayGetLBound(V_ARRAY(pVariant),
  219. 1,
  220. (long FAR *) &dwSLBound );
  221. BAIL_ON_FAILURE(hr);
  222. hr = SafeArrayGetUBound(V_ARRAY(pVariant),
  223. 1,
  224. (long FAR *) &dwSUBound );
  225. BAIL_ON_FAILURE(hr);
  226. hr = SafeArrayAccessData( V_ARRAY(pVariant),
  227. (void **) &pVarArray );
  228. BAIL_ON_FAILURE(hr);
  229. for (j=dwSLBound; j<=dwSUBound; j++) {
  230. switch((pVarArray[j]).vt) {
  231. case VT_DATE:
  232. SYSTEMTIME UTCTime;
  233. hr = VariantTimeToSystemTime(
  234. V_DATE(pVarArray+j),
  235. &UTCTime
  236. );
  237. BAIL_ON_FAILURE(hr);
  238. wprintf(L"%d %d %d #",
  239. UTCTime.wYear,
  240. UTCTime.wMonth,
  241. UTCTime.wDay);
  242. break;
  243. case VT_BSTR:
  244. wprintf(
  245. L"%s # ",
  246. V_BSTR(pVarArray+j)
  247. );
  248. break;
  249. case VT_I4:
  250. wprintf(
  251. L"%d # ",
  252. V_I4(pVarArray+j)
  253. );
  254. break;
  255. case VT_BOOL:
  256. wprintf(
  257. L"%s # ",
  258. V_BOOL(pVarArray+j) == VARIANT_TRUE ?
  259. L"TRUE" : L"FALSE"
  260. );
  261. break;
  262. #if 0
  263. case VT_I8:
  264. wprintf(
  265. L"%I64d # ",
  266. V_I8(pVarArray+j)
  267. );
  268. break;
  269. #endif
  270. default:
  271. wprintf(
  272. L"Unsupported # \n"
  273. );
  274. }
  275. }
  276. printf("\n");
  277. SafeArrayUnaccessData( V_ARRAY(pVariant) );
  278. break;
  279. }
  280. default:
  281. wprintf(
  282. L"Unsupported type for attribute %s\n",
  283. prgColInfo[i+1].pwszName
  284. );
  285. break;
  286. }
  287. }
  288. }
  289. if(nAttrs != 0)
  290. wprintf(L"\n");
  291. return;
  292. error:
  293. wprintf(
  294. L"Error in Printing data for %s\n",
  295. prgColInfo[i+1].pwszName
  296. );
  297. return;
  298. }
  299. int
  300. AnsiToUnicodeString(
  301. LPSTR pAnsi,
  302. LPWSTR pUnicode,
  303. DWORD StringLength
  304. )
  305. {
  306. int iReturn;
  307. if( StringLength == NULL_TERMINATED )
  308. StringLength = strlen( pAnsi );
  309. iReturn = MultiByteToWideChar(CP_ACP,
  310. MB_PRECOMPOSED,
  311. pAnsi,
  312. StringLength + 1,
  313. pUnicode,
  314. StringLength + 1 );
  315. //
  316. // Ensure NULL termination.
  317. //
  318. pUnicode[StringLength] = 0;
  319. return iReturn;
  320. }
  321. int
  322. UnicodeToAnsiString(
  323. LPWSTR pUnicode,
  324. LPSTR pAnsi,
  325. DWORD StringLength
  326. )
  327. {
  328. LPSTR pTempBuf = NULL;
  329. INT rc = 0;
  330. if( StringLength == NULL_TERMINATED ) {
  331. //
  332. // StringLength is just the
  333. // number of characters in the string
  334. //
  335. StringLength = wcslen( pUnicode );
  336. }
  337. //
  338. // WideCharToMultiByte doesn't NULL terminate if we're copying
  339. // just part of the string, so terminate here.
  340. //
  341. pUnicode[StringLength] = 0;
  342. //
  343. // Include one for the NULL
  344. //
  345. StringLength++;
  346. //
  347. // Unfortunately, WideCharToMultiByte doesn't do conversion in place,
  348. // so allocate a temporary buffer, which we can then copy:
  349. //
  350. if( pAnsi == (LPSTR)pUnicode )
  351. {
  352. pTempBuf = (LPSTR)LocalAlloc( LPTR, StringLength );
  353. pAnsi = pTempBuf;
  354. }
  355. if( pAnsi )
  356. {
  357. rc = WideCharToMultiByte( CP_ACP,
  358. 0,
  359. pUnicode,
  360. StringLength,
  361. pAnsi,
  362. StringLength,
  363. NULL,
  364. NULL );
  365. }
  366. /* If pTempBuf is non-null, we must copy the resulting string
  367. * so that it looks as if we did it in place:
  368. */
  369. if( pTempBuf && ( rc > 0 ) )
  370. {
  371. pAnsi = (LPSTR)pUnicode;
  372. strcpy( pAnsi, pTempBuf );
  373. LocalFree( pTempBuf );
  374. }
  375. return rc;
  376. }
  377. LPWSTR
  378. AllocateUnicodeString(
  379. LPSTR pAnsiString
  380. )
  381. {
  382. LPWSTR pUnicodeString = NULL;
  383. if (!pAnsiString)
  384. return NULL;
  385. pUnicodeString = (LPWSTR)LocalAlloc(
  386. LPTR,
  387. strlen(pAnsiString)*sizeof(WCHAR) +sizeof(WCHAR)
  388. );
  389. if (pUnicodeString) {
  390. AnsiToUnicodeString(
  391. pAnsiString,
  392. pUnicodeString,
  393. NULL_TERMINATED
  394. );
  395. }
  396. return pUnicodeString;
  397. }
  398. void
  399. FreeUnicodeString(
  400. LPWSTR pUnicodeString
  401. )
  402. {
  403. if (!pUnicodeString)
  404. return;
  405. LocalFree(pUnicodeString);
  406. return;
  407. }