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.

2905 lines
102 KiB

  1. //================================================================================
  2. // Copyright (C) 1997 Microsoft Corporation
  3. // Author: RameshV (critical code borrowed from shirish koti)
  4. // Description: This makes somethings easy for accessing the DS.
  5. //================================================================================
  6. #include <hdrmacro.h>
  7. #include <sterr.h> // error reporting stuff
  8. enum /* anonymous */ {
  9. REPEATED_ADDRESS1 = 0x01, // dont start error code with zero!
  10. REPEATED_ADDRESS2,
  11. REPEATED_ADDRESS3,
  12. INVALID_ADDRESS1,
  13. INVALID_ADDRESS2,
  14. INVALID_ADDRESS3,
  15. REPEATED_ADSPATH,
  16. INVALID_ADSPATH,
  17. REPEATED_FLAGS1,
  18. REPEATED_FLAGS2,
  19. INVALID_FLAGS1,
  20. INVALID_FLAGS2,
  21. REPEATED_DWORD1,
  22. REPEATED_DWORD2,
  23. INVALID_DWORD1,
  24. INVALID_DWORD2,
  25. REPEATED_STRING1,
  26. REPEATED_STRING2,
  27. REPEATED_STRING3,
  28. REPEATED_STRING4,
  29. INVALID_STRING1,
  30. INVALID_STRING2,
  31. INVALID_STRING3,
  32. INVALID_STRING4,
  33. REPEATED_BINARY1,
  34. REPEATED_BINARY2,
  35. INVALID_BINARY1,
  36. INVALID_BINARY2,
  37. INVALID_ATTRIB_FIELD,
  38. INVALID_BINARY_CODING,
  39. UNEXPECTED_COLLECTION_TYPE,
  40. UNEXPECTED_INTERNAL_ERROR,
  41. };
  42. //
  43. // Constants
  44. //
  45. // Retrive 256 rows per query
  46. #define DHCPDS_DS_SEARCH_PAGESIZE 256
  47. //================================================================================
  48. // structures
  49. //================================================================================
  50. //BeginExport(typedef)
  51. typedef struct _STORE_HANDLE { // this is what is used almost always
  52. DWORD MustBeZero; // for future use
  53. LPWSTR Location; // where does this refer to?
  54. LPWSTR UserName; // who is the user?
  55. LPWSTR Password; // what is the password?
  56. DWORD AuthFlags; // what permission was this opened with?
  57. HANDLE ADSIHandle; // handle to within ADSI
  58. ADS_SEARCH_HANDLE SearchHandle; // any searches going on?
  59. LPVOID Memory; // memory allocated for this call..
  60. DWORD MemSize; // how much was really allocated?
  61. BOOL SearchStarted; // Did we start the search?
  62. } STORE_HANDLE, *LPSTORE_HANDLE, *PSTORE_HANDLE;
  63. //EndExport(typedef)
  64. LPWSTR _inline
  65. MakeRootDSEString( // given DSDC or domain name, produce ROOT DSE name
  66. IN LPWSTR Server
  67. )
  68. {
  69. LPWSTR RootDSE;
  70. if( NULL == Server ) {
  71. RootDSE = MemAlloc( sizeof(DEFAULT_LDAP_ROOTDSE) ) ;
  72. if( NULL == RootDSE ) return NULL;
  73. wcscpy(RootDSE, DEFAULT_LDAP_ROOTDSE);
  74. return RootDSE;
  75. }
  76. RootDSE = MemAlloc(sizeof(LDAP_PREFIX) + SizeString(Server,FALSE) + sizeof(ROOTDSE_POSTFIX));
  77. if( NULL == RootDSE ) return NULL;
  78. wcscpy(RootDSE, LDAP_PREFIX);
  79. wcscat(RootDSE, Server);
  80. wcscat(RootDSE, ROOTDSE_POSTFIX);
  81. return RootDSE;
  82. }
  83. LPWSTR _inline
  84. MakeServerLocationString(
  85. IN LPWSTR Server,
  86. IN LPWSTR Location
  87. )
  88. {
  89. LPWSTR RetVal;
  90. Require(Location);
  91. RetVal = MemAlloc(sizeof(LDAP_PREFIX) + sizeof(WCHAR) + SizeString(Server,FALSE) + SizeString(Location,FALSE));
  92. if( NULL == RetVal ) return NULL;
  93. wcscpy(RetVal, LDAP_PREFIX);
  94. if( NULL != Server ) {
  95. wcscat(RetVal, Server);
  96. wcscat(RetVal, L"/");
  97. }
  98. wcscat(RetVal, Location);
  99. return RetVal;
  100. }
  101. HRESULT
  102. GetEnterpriseRootFromRootHandle( // given /ROOTDSE object handle, get enterprise config root handle..
  103. IN HANDLE DSERootHandle,
  104. IN LPWSTR Server,
  105. IN LPWSTR UserName,
  106. IN LPWSTR Password,
  107. IN DWORD AuthFlags,
  108. IN OUT LPWSTR *RootLocation,
  109. IN OUT HANDLE *hRoot
  110. )
  111. {
  112. HRESULT hResult;
  113. DWORD Chk;
  114. DWORD i, j;
  115. DWORD nAttributes;
  116. PADS_ATTR_INFO Attributes;
  117. BOOL Found;
  118. *RootLocation = NULL;
  119. hResult = ADSIGetObjectAttributes(
  120. DSERootHandle,
  121. (LPWSTR *)&constNamingContextString,
  122. 1,
  123. &Attributes,
  124. &nAttributes
  125. );
  126. if( FAILED(hResult) ) return hResult;
  127. if( 0 == nAttributes ) {
  128. return E_ADS_PROPERTY_NOT_FOUND;
  129. }
  130. Found = FALSE;
  131. for( i = 0; i < Attributes->dwNumValues ; i ++ ) {
  132. if( Attributes->pADsValues[i].dwType != ADSTYPE_CASE_IGNORE_STRING &&
  133. Attributes->pADsValues[i].dwType != ADSTYPE_DN_STRING )
  134. continue;
  135. Chk = _wcsnicmp(
  136. ENT_ROOT_PREFIX,
  137. Attributes->pADsValues[i].CaseIgnoreString,
  138. ENT_ROOT_PREFIX_LEN
  139. );
  140. if( 0 == Chk ) break;
  141. }
  142. if( i < Attributes->dwNumValues ) {
  143. *RootLocation = MakeServerLocationString(
  144. Server,
  145. Attributes->pADsValues[i].CaseIgnoreString
  146. );
  147. Found = TRUE;
  148. }
  149. FreeADsMem(Attributes);
  150. if( FALSE == Found ) return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  151. if( NULL == *RootLocation ) return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  152. hResult = ADSIOpenDSObject(
  153. *RootLocation,
  154. UserName,
  155. Password,
  156. AuthFlags,
  157. hRoot
  158. );
  159. if( SUCCEEDED(hResult) ) return S_OK;
  160. MemFree(*RootLocation);
  161. *RootLocation = NULL;
  162. return hResult;
  163. }
  164. DWORD
  165. GetEnterpriseRootObject( // get the /ROOTDSE object's naming context object..
  166. IN LPWSTR Server, // domain controller name or domain dns name
  167. IN LPWSTR UserName,
  168. IN LPWSTR Password,
  169. IN DWORD AuthFlags,
  170. IN OUT LPWSTR *RootLocation, // what is the value of the nameingContext attrib that we used?
  171. IN OUT HANDLE *hRoot // handle to the above object..
  172. )
  173. {
  174. DWORD Result;
  175. LPWSTR RootDSEString;
  176. LPWSTR RootEnterpriseString;
  177. HANDLE hRootDSE;
  178. HRESULT hResult;
  179. *RootLocation = NULL; *hRoot = NULL;
  180. RootDSEString = MakeRootDSEString(Server);
  181. if( NULL == RootDSEString ) return ERROR_NOT_ENOUGH_MEMORY;
  182. hResult = ADSIOpenDSObject(
  183. RootDSEString,
  184. UserName,
  185. Password,
  186. AuthFlags,
  187. &hRootDSE
  188. );
  189. MemFree(RootDSEString);
  190. if( FAILED(hResult) ) return ConvertHresult(hResult);
  191. hResult = GetEnterpriseRootFromRootHandle(
  192. hRootDSE,
  193. Server,
  194. UserName,
  195. Password,
  196. AuthFlags,
  197. RootLocation,
  198. hRoot
  199. );
  200. ADSICloseDSObject(hRootDSE);
  201. if( FAILED(hResult) ) return ConvertHresult(hResult);
  202. Require(hRoot && RootLocation);
  203. return ERROR_SUCCESS;
  204. }
  205. //================================================================================
  206. // exported functions
  207. //================================================================================
  208. //BeginExport(function)
  209. DWORD
  210. StoreInitHandle( // initialize a handle
  211. IN OUT STORE_HANDLE *hStore, // will be filled in with stuff..
  212. IN DWORD Reserved, // must be zero -- for future use
  213. IN LPWSTR Domain, // OPTIONAL NULL==>default Domain
  214. IN LPWSTR UserName, // OPTIONAL NULL==>default credentials
  215. IN LPWSTR Password, // OPTIONAL used only if UserName given
  216. IN DWORD AuthFlags // OPTIONAL 0 ==> default??????
  217. ) //EndExport(function)
  218. {
  219. DWORD Result;
  220. DWORD Size;
  221. LPWSTR EnterpriseRootLocation;
  222. HANDLE RootServer;
  223. LPBYTE Memory;
  224. Result = GetEnterpriseRootObject(
  225. Domain,
  226. UserName,
  227. Password,
  228. AuthFlags,
  229. &EnterpriseRootLocation,
  230. &RootServer
  231. );
  232. if( ERROR_SUCCESS != Result) return Result;
  233. Require(RootServer && EnterpriseRootLocation);
  234. Size = sizeof(LONG);
  235. Size += SizeString(UserName, FALSE);
  236. Size += SizeString(Password, FALSE);
  237. Memory = MemAlloc(Size);
  238. if( NULL == Memory ) {
  239. MemFree(EnterpriseRootLocation);
  240. ADSICloseDSObject(RootServer);
  241. return ERROR_NOT_ENOUGH_MEMORY;
  242. }
  243. hStore->MemSize = Size;
  244. Size = sizeof(LONG);
  245. hStore->MustBeZero = 0;
  246. hStore->Location = EnterpriseRootLocation;
  247. hStore->UserName = (LPWSTR)&Memory[Size]; Size += SizeString(UserName, FALSE);
  248. hStore->Password = (LPWSTR)&Memory[Size]; Size += SizeString(Password, FALSE);
  249. hStore->AuthFlags = AuthFlags;
  250. hStore->ADSIHandle = RootServer;
  251. hStore->SearchHandle = NULL;
  252. hStore->Memory = Memory;
  253. if( NULL == UserName ) hStore->UserName = NULL;
  254. else wcscpy(hStore->UserName, UserName);
  255. if( NULL == Password ) hStore->Password = NULL;
  256. else wcscpy(hStore->Password,Password);
  257. return ERROR_SUCCESS;
  258. }
  259. //BeginExport(function)
  260. DWORD
  261. StoreCleanupHandle( // cleanup the handle
  262. IN OUT LPSTORE_HANDLE hStore,
  263. IN DWORD Reserved
  264. ) //EndExport(function)
  265. {
  266. DWORD Result;
  267. AssertRet(hStore, ERROR_INVALID_PARAMETER);
  268. AssertRet(hStore->Location, ERROR_INVALID_PARAMETER);
  269. MemFree(hStore->Location);
  270. MemFree(hStore->Memory);
  271. if(hStore->SearchHandle)
  272. ADSICloseSearchHandle(hStore->ADSIHandle, hStore->SearchHandle);
  273. ADSICloseDSObject(hStore->ADSIHandle);
  274. // memset(hStore, 0, sizeof(*hStore));
  275. hStore->Location = NULL;
  276. hStore->UserName = NULL;
  277. hStore->Password = NULL;
  278. hStore->AuthFlags = 0;
  279. hStore->ADSIHandle = 0;
  280. hStore->Memory = NULL;
  281. hStore->MemSize = 0;
  282. // hStore->SearchStarted = FALSE;
  283. return ERROR_SUCCESS;
  284. }
  285. //BeginExport(enum)
  286. enum {
  287. StoreGetChildType,
  288. StoreGetAbsoluteSameServerType,
  289. StoreGetAbsoluteOtherServerType
  290. } _StoreGetType;
  291. //EndExport(enum)
  292. DWORD
  293. ConvertPath( // convert a "CN=X" type spec to "LDAP://Server/CN=X"..
  294. IN LPSTORE_HANDLE hStore, // needed to get the initial strings bits
  295. IN DWORD StoreGetType,
  296. IN LPWSTR PathIn,
  297. OUT LPWSTR *PathOut
  298. )
  299. {
  300. DWORD Size;
  301. DWORD PrefixSize;
  302. DWORD SuffixSize;
  303. LPWSTR TmpString;
  304. LPWSTR PrefixString;
  305. *PathOut = NULL;
  306. if( StoreGetChildType == StoreGetType ) {
  307. TmpString = PrefixString = hStore->Location;
  308. TmpString = wcschr(TmpString, L'/'); Require(TmpString); TmpString ++;
  309. TmpString = wcschr(TmpString, L'/'); Require(TmpString); TmpString ++;
  310. if( wcschr(TmpString, L'/') ) {
  311. TmpString = wcschr(TmpString, L'/'); TmpString ++;
  312. }
  313. PrefixSize = sizeof(WCHAR)*(DWORD)(TmpString - PrefixString );
  314. SuffixSize = SizeString(hStore->Location, FALSE)-PrefixSize;
  315. } else if( StoreGetAbsoluteSameServerType == StoreGetType ) {
  316. TmpString = PrefixString = hStore->Location;
  317. TmpString = wcschr(TmpString, L'/'); Require(TmpString); TmpString ++;
  318. TmpString = wcschr(TmpString, L'/'); Require(TmpString); TmpString ++;
  319. if( wcschr(TmpString, L'/') ) {
  320. TmpString = wcschr(TmpString, L'/'); TmpString ++;
  321. }
  322. PrefixSize = sizeof(WCHAR)*(DWORD)(TmpString - PrefixString );
  323. SuffixSize = 0;
  324. } else if( StoreGetAbsoluteOtherServerType == StoreGetType ) {
  325. PrefixSize = 0; // use the path given by the user
  326. SuffixSize = 0;
  327. } else {
  328. Require(FALSE);
  329. PrefixSize = SuffixSize = 0;
  330. }
  331. Size = PrefixSize + SuffixSize + SizeString(PathIn,FALSE) + sizeof(CONNECTOR) - sizeof(WCHAR);
  332. TmpString = MemAlloc(Size);
  333. if( NULL == TmpString ) return ERROR_NOT_ENOUGH_MEMORY;
  334. if( PrefixSize ) {
  335. memcpy((LPBYTE)TmpString, (LPBYTE)PrefixString, PrefixSize);
  336. }
  337. wcscpy((LPWSTR)(PrefixSize + (LPBYTE)TmpString), PathIn);
  338. if( SuffixSize ) {
  339. wcscat(TmpString, CONNECTOR);
  340. wcscat(TmpString, (LPWSTR)(PrefixSize+(LPBYTE)PrefixString));
  341. }
  342. *PathOut = TmpString;
  343. StoreTrace2("ConvertedPath: %ws\n", TmpString);
  344. return ERROR_SUCCESS;
  345. }
  346. //BeginExport(function)
  347. DWORD
  348. StoreGetHandle( // get handle to child object, absolute object..
  349. IN OUT LPSTORE_HANDLE hStore, // this gets modified..
  350. IN DWORD Reserved,
  351. IN DWORD StoreGetType, // same server? just a simple child?
  352. IN LPWSTR Path,
  353. IN OUT STORE_HANDLE *hStoreOut // new handle created..
  354. ) //EndExport(function)
  355. {
  356. HRESULT hResult;
  357. DWORD Result;
  358. DWORD Size;
  359. LPWSTR ConvertedPath;
  360. HANDLE ObjectHandle;
  361. LPBYTE Memory;
  362. AssertRet(hStore, ERROR_INVALID_PARAMETER);
  363. AssertRet(hStore->Location, ERROR_INVALID_PARAMETER);
  364. AssertRet(Path, ERROR_INVALID_PARAMETER);
  365. AssertRet(hStoreOut, ERROR_INVALID_PARAMETER);
  366. Result = ConvertPath(hStore, StoreGetType, Path, &ConvertedPath);
  367. if( ERROR_SUCCESS != Result ) return Result;
  368. Require(ConvertedPath);
  369. Memory = MemAlloc(hStore->MemSize);
  370. if( NULL == Memory ) {
  371. MemFree(ConvertedPath);
  372. return ERROR_NOT_ENOUGH_MEMORY;
  373. }
  374. hResult = ADSIOpenDSObject(
  375. ConvertedPath,
  376. hStore->UserName,
  377. hStore->Password,
  378. hStore->AuthFlags,
  379. &ObjectHandle
  380. );
  381. if( FAILED(hResult) ) {
  382. MemFree(ConvertedPath);
  383. MemFree(Memory);
  384. return ConvertHresult(hResult);
  385. }
  386. memcpy(Memory, hStore->Memory, hStore->MemSize);
  387. Size = sizeof(LONG);
  388. hStoreOut->MemSize = hStore->MemSize;
  389. hStoreOut->MustBeZero = 0;
  390. hStoreOut->Location = ConvertedPath;
  391. hStoreOut->UserName = (LPWSTR)&Memory[Size]; Size += SizeString(hStore->UserName, FALSE);
  392. hStoreOut->Password = (LPWSTR)&Memory[Size]; Size += SizeString(hStore->Password, FALSE);
  393. hStoreOut->AuthFlags = hStore->AuthFlags;
  394. hStoreOut->ADSIHandle = ObjectHandle;
  395. hStoreOut->SearchHandle = NULL;
  396. hStoreOut->Memory = Memory;
  397. if( NULL == hStore->UserName ) hStoreOut->UserName = NULL;
  398. if( NULL == hStore->Password ) hStoreOut->Password = NULL;
  399. return ERROR_SUCCESS;
  400. }
  401. //BeginExport(function)
  402. DWORD
  403. StoreSetSearchOneLevel( // search will return everything one level below
  404. IN OUT LPSTORE_HANDLE hStore,
  405. IN DWORD Reserved
  406. ) //EndExport(function)
  407. {
  408. HRESULT hResult;
  409. ADS_SEARCHPREF_INFO SearchPref[3];
  410. AssertRet(hStore && hStore->ADSIHandle, ERROR_INVALID_PARAMETER);
  411. AssertRet(Reserved == 0, ERROR_INVALID_PARAMETER);
  412. SearchPref[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  413. SearchPref[0].vValue.dwType = ADSTYPE_INTEGER;
  414. SearchPref[0].vValue.Integer = ADS_SCOPE_ONELEVEL;
  415. SearchPref[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  416. SearchPref[1].vValue.dwType = ADSTYPE_INTEGER;
  417. SearchPref[1].vValue.Integer = DHCPDS_DS_SEARCH_PAGESIZE;
  418. // Make it cache the results at the client side. This is
  419. // default, but try it anyway.
  420. SearchPref[2].dwSearchPref = ADS_SEARCHPREF_CACHE_RESULTS;
  421. SearchPref[2].vValue.dwType = ADSTYPE_BOOLEAN;
  422. SearchPref[2].vValue.Boolean = TRUE;
  423. hResult = ADSISetSearchPreference(
  424. /* hDSObject */ hStore->ADSIHandle,
  425. /* pSearchPrefs */ SearchPref,
  426. /* dwNumPrefs */ 2 // sizeof( SearchPref ) / sizeof( SearchPref[ 0 ])
  427. );
  428. if( FAILED(hResult) ) return ConvertHresult(hResult);
  429. return ERROR_SUCCESS;
  430. }
  431. //BeginExport(function)
  432. DWORD
  433. StoreSetSearchSubTree( // search will return the subtree below in ANY order
  434. IN OUT LPSTORE_HANDLE hStore,
  435. IN DWORD Reserved
  436. ) //EndExport(function)
  437. {
  438. HRESULT hResult;
  439. ADS_SEARCHPREF_INFO SearchPref[3];
  440. AssertRet(hStore && hStore->ADSIHandle, ERROR_INVALID_PARAMETER);
  441. AssertRet(Reserved == 0, ERROR_INVALID_PARAMETER);
  442. SearchPref[0].dwSearchPref = ADS_SEARCHPREF_SEARCH_SCOPE;
  443. SearchPref[0].vValue.dwType = ADSTYPE_INTEGER;
  444. SearchPref[0].vValue.Integer = ADS_SCOPE_SUBTREE;
  445. SearchPref[1].dwSearchPref = ADS_SEARCHPREF_PAGESIZE;
  446. SearchPref[1].vValue.dwType = ADSTYPE_INTEGER;
  447. SearchPref[1].vValue.Integer = DHCPDS_DS_SEARCH_PAGESIZE;
  448. // Make it cache the results at the client side. This is
  449. // default, but try it anyway.
  450. SearchPref[2].dwSearchPref = ADS_SEARCHPREF_CACHE_RESULTS;
  451. SearchPref[2].vValue.dwType = ADSTYPE_BOOLEAN;
  452. SearchPref[2].vValue.Boolean = TRUE;
  453. hResult = ADSISetSearchPreference(
  454. /* hDSObject */ hStore->ADSIHandle,
  455. /* pSearchPrefs */ SearchPref,
  456. /* dwNumPrefs */ sizeof( SearchPref ) / sizeof( SearchPref[ 0 ])
  457. );
  458. if( FAILED(hResult) ) return ConvertHresult(hResult);
  459. return ERROR_SUCCESS;
  460. }
  461. //BeginExport(function)
  462. DWORD
  463. StoreBeginSearch(
  464. IN OUT LPSTORE_HANDLE hStore,
  465. IN DWORD Reserved,
  466. IN LPWSTR SearchFilter
  467. ) //EndExport(function)
  468. {
  469. HRESULT hResult;
  470. LPWSTR nameAttrib;
  471. nameAttrib = ATTRIB_NAME;
  472. AssertRet(hStore && hStore->ADSIHandle, ERROR_INVALID_PARAMETER);
  473. AssertRet(Reserved == 0, ERROR_INVALID_PARAMETER);
  474. hResult = ADSIExecuteSearch(
  475. hStore->ADSIHandle,
  476. SearchFilter,
  477. (LPWSTR *)&nameAttrib,
  478. 1,
  479. &(hStore->SearchHandle)
  480. );
  481. if( FAILED(hResult) ) return ConvertHresult(hResult);
  482. hStore->SearchStarted = FALSE;
  483. return ERROR_SUCCESS;
  484. }
  485. //BeginExport(function)
  486. DWORD
  487. StoreEndSearch(
  488. IN OUT LPSTORE_HANDLE hStore,
  489. IN DWORD Reserved
  490. ) //EndExport(function)
  491. {
  492. HRESULT hResult;
  493. AssertRet(hStore, ERROR_INVALID_PARAMETER);
  494. AssertRet(hStore->SearchHandle, ERROR_INVALID_PARAMETER);
  495. AssertRet(Reserved == 0, ERROR_INVALID_PARAMETER);
  496. hResult = ADSICloseSearchHandle(hStore->ADSIHandle, hStore->SearchHandle);
  497. hStore->SearchHandle = NULL;
  498. hStore->SearchStarted = FALSE;
  499. if( FAILED(hResult) ) return ConvertHresult(hResult);
  500. return ERROR_SUCCESS;
  501. }
  502. //BeginExport(function)
  503. DWORD // ERROR_NO_MORE_ITEMS if exhausted
  504. StoreSearchGetNext(
  505. IN OUT LPSTORE_HANDLE hStore,
  506. IN DWORD Reserved,
  507. OUT LPSTORE_HANDLE hStoreOut
  508. ) //EndExport(function)
  509. {
  510. DWORD Result;
  511. HRESULT hResult;
  512. ADS_SEARCH_COLUMN Column;
  513. LPWSTR ColumnName;
  514. AssertRet(hStore && hStore->ADSIHandle && hStoreOut, ERROR_INVALID_PARAMETER);
  515. AssertRet(Reserved == 0, ERROR_INVALID_PARAMETER);
  516. if ( !hStore->SearchStarted ) {
  517. hResult = ADSIGetFirstRow( hStore->ADSIHandle,
  518. hStore->SearchHandle
  519. );
  520. hStore->SearchStarted = TRUE;
  521. }
  522. else {
  523. hResult = ADSIGetNextRow( hStore->ADSIHandle,
  524. hStore->SearchHandle
  525. );
  526. }
  527. if( FAILED(hResult) ) return ConvertHresult(hResult);
  528. if( S_ADS_NOMORE_ROWS == hResult ) return ERROR_NO_MORE_ITEMS;
  529. hResult = ADSIGetColumn(
  530. hStore->ADSIHandle,
  531. hStore->SearchHandle,
  532. ATTRIB_NAME,
  533. &Column
  534. );
  535. if( FAILED(hResult) ) {
  536. Require(FALSE);
  537. return ConvertHresult(hResult);
  538. }
  539. Require(1==Column.dwNumValues); // single valued
  540. if( Column.pADsValues[0].dwType == ADSTYPE_DN_STRING ) {
  541. Require(Column.pADsValues[0].DNString);
  542. ColumnName = MakeColumnName(Column.pADsValues[0].DNString);
  543. } else if( Column.pADsValues[0].dwType == ADSTYPE_CASE_IGNORE_STRING ) {
  544. Require(Column.pADsValues[0].CaseIgnoreString);
  545. ColumnName = MakeColumnName(Column.pADsValues[0].CaseIgnoreString);
  546. } else {
  547. Require(FALSE);
  548. ColumnName = NULL;
  549. }
  550. if( NULL == ColumnName ) Result = ERROR_NOT_ENOUGH_MEMORY;
  551. else {
  552. Result = StoreGetHandle(
  553. hStore,
  554. Reserved,
  555. StoreGetChildType,
  556. ColumnName,
  557. hStoreOut
  558. );
  559. MemFree(ColumnName);
  560. }
  561. ADSIFreeColumn(
  562. hStore->ADSIHandle,
  563. &Column
  564. );
  565. return Result;
  566. }
  567. //BeginExport(function)
  568. DWORD
  569. StoreCreateObjectVA( // create a new object - var-args ending with ADSTYPE_INVALID
  570. IN OUT LPSTORE_HANDLE hStore,
  571. IN DWORD Reserved,
  572. IN LPWSTR NewObjName, // name of the new object -- must be "CN=name" types
  573. ... // fmt is AttrType, AttrName, AttrValue [AttrValueLen]
  574. ) //EndExport(function) // LARGE_INTEGER type has hi_word followed by low_word
  575. {
  576. HRESULT hResult;
  577. DWORD Result;
  578. DWORD i;
  579. DWORD ArgType;
  580. DWORD nArgs;
  581. DWORD Arg1;
  582. va_list Args;
  583. PADS_ATTR_INFO Attributes;
  584. AssertRet(hStore, ERROR_INVALID_PARAMETER);
  585. AssertRet(NewObjName, ERROR_INVALID_PARAMETER);
  586. nArgs = 0;
  587. va_start(Args, NewObjName);
  588. do {
  589. ArgType = va_arg(Args, DWORD);
  590. if( ADSTYPE_INVALID == ArgType ) break;
  591. va_arg(Args, LPWSTR); // skip the name of attrib
  592. switch(ArgType) {
  593. case ADSTYPE_DN_STRING :
  594. case ADSTYPE_CASE_EXACT_STRING:
  595. case ADSTYPE_CASE_IGNORE_STRING:
  596. case ADSTYPE_PRINTABLE_STRING:
  597. case ADSTYPE_NUMERIC_STRING:
  598. case ADSTYPE_UTC_TIME:
  599. case ADSTYPE_OBJECT_CLASS:
  600. va_arg(Args, LPWSTR);
  601. break;
  602. case ADSTYPE_BOOLEAN:
  603. case ADSTYPE_INTEGER:
  604. va_arg(Args, DWORD);
  605. break;
  606. case ADSTYPE_OCTET_STRING:
  607. va_arg(Args, LPBYTE);
  608. va_arg(Args, DWORD); // additional DWORD values for these..
  609. break;
  610. case ADSTYPE_LARGE_INTEGER:
  611. va_arg(Args, LONG);
  612. va_arg(Args, DWORD); // additional DWORD values for these..
  613. break;
  614. default:
  615. return ERROR_INVALID_PARAMETER;
  616. }
  617. nArgs ++;
  618. } while( 1 );
  619. if( 0 == nArgs ) {
  620. Attributes = NULL;
  621. } else {
  622. Attributes = MemAlloc(nArgs * sizeof(*Attributes));
  623. if( NULL == Attributes ) return ERROR_NOT_ENOUGH_MEMORY;
  624. memset(Attributes, 0, sizeof(*Attributes));
  625. }
  626. va_start(Args, NewObjName);
  627. for(i = 0; i < nArgs; i ++ ) {
  628. ArgType = va_arg(Args, DWORD);
  629. Require(ADSTYPE_INVALID != ArgType);
  630. Attributes[i].dwNumValues = 1;
  631. Attributes[i].pADsValues = MemAlloc(sizeof(*Attributes[i].pADsValues));
  632. if( NULL == Attributes[i].pADsValues ) {
  633. nArgs = i;
  634. goto Cleanup;
  635. }
  636. Attributes[i].pszAttrName = (LPWSTR)va_arg(Args, LPWSTR);
  637. Attributes[i].dwControlCode = ADS_ATTR_APPEND;
  638. Attributes[i].dwADsType = ArgType;
  639. Attributes[i].pADsValues[0].dwType = ArgType;
  640. switch(ArgType) {
  641. case ADSTYPE_DN_STRING :
  642. Attributes[i].pADsValues[0].DNString = (LPWSTR)va_arg(Args,LPWSTR); break;
  643. case ADSTYPE_CASE_EXACT_STRING:
  644. Attributes[i].pADsValues[0].CaseExactString = (LPWSTR)va_arg(Args,LPWSTR); break;
  645. case ADSTYPE_CASE_IGNORE_STRING:
  646. Attributes[i].pADsValues[0].CaseIgnoreString = (LPWSTR)va_arg(Args,LPWSTR); break;
  647. case ADSTYPE_PRINTABLE_STRING:
  648. Attributes[i].pADsValues[0].PrintableString = (LPWSTR)va_arg(Args,LPWSTR); break;
  649. case ADSTYPE_NUMERIC_STRING:
  650. Attributes[i].pADsValues[0].NumericString = (LPWSTR)va_arg(Args,LPWSTR); break;
  651. case ADSTYPE_BOOLEAN:
  652. Attributes[i].pADsValues[0].Boolean = va_arg(Args,DWORD); break;
  653. case ADSTYPE_INTEGER:
  654. Attributes[i].pADsValues[0].Integer = va_arg(Args,DWORD); break;
  655. case ADSTYPE_OBJECT_CLASS:
  656. Attributes[i].pADsValues[0].ClassName = (LPWSTR)va_arg(Args,LPWSTR); break;
  657. case ADSTYPE_OCTET_STRING:
  658. Attributes[i].pADsValues[0].OctetString.lpValue = (LPBYTE)va_arg(Args,LPBYTE);
  659. Attributes[i].pADsValues[0].OctetString.dwLength = va_arg(Args, DWORD);
  660. break;
  661. case ADSTYPE_LARGE_INTEGER:
  662. Attributes[i].pADsValues[0].LargeInteger.HighPart = (LONG)va_arg(Args,LONG);
  663. Attributes[i].pADsValues[0].LargeInteger.LowPart = va_arg(Args, ULONG);
  664. break;
  665. case ADSTYPE_UTC_TIME:
  666. Attributes[i].pADsValues[0].UTCTime = *((ADS_UTC_TIME*)va_arg(Args,PVOID));
  667. break;
  668. default:
  669. nArgs = i;
  670. Result = ERROR_INVALID_PARAMETER;
  671. goto Cleanup;
  672. }
  673. }
  674. hResult = ADSICreateDSObject(
  675. hStore->ADSIHandle,
  676. NewObjName,
  677. Attributes,
  678. nArgs
  679. );
  680. if( HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hResult ||
  681. HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS) == hResult ||
  682. E_ADS_OBJECT_EXISTS == hResult ) {
  683. Result = ERROR_ALREADY_EXISTS;
  684. } else if( FAILED(hResult) ) {
  685. Result = ConvertHresult(hResult);
  686. } else {
  687. Result = ERROR_SUCCESS;
  688. }
  689. Cleanup:
  690. if( NULL != Attributes ) {
  691. for( i = 0; i < nArgs ; i ++ ) {
  692. if( Attributes[i].pADsValues ) MemFree(Attributes[i].pADsValues);
  693. }
  694. MemFree(Attributes);
  695. }
  696. return Result;
  697. }
  698. //BeginExport(function)
  699. DWORD
  700. StoreCreateObjectL( // create the object as an array
  701. IN OUT LPSTORE_HANDLE hStore,
  702. IN DWORD Reserved,
  703. IN LPWSTR NewObjName, // must be "CN=XXX" types
  704. IN PADS_ATTR_INFO Attributes, // the required attributes
  705. IN DWORD nAttributes // size of above array
  706. ) //EndExport(function)
  707. {
  708. HRESULT hResult;
  709. DWORD Result;
  710. hResult = ADSICreateDSObject(
  711. hStore->ADSIHandle,
  712. NewObjName,
  713. Attributes,
  714. nAttributes
  715. );
  716. if( HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS) == hResult ||
  717. HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS) == hResult ||
  718. E_ADS_OBJECT_EXISTS == hResult ) {
  719. Result = ERROR_ALREADY_EXISTS;
  720. } else if( FAILED(hResult) ) {
  721. Result = ConvertHresult(hResult);
  722. } else {
  723. Result = ERROR_SUCCESS;
  724. }
  725. return Result;
  726. }
  727. //BeginExport(defines)
  728. #define StoreCreateObject StoreCreateObjectVA
  729. //EndExport(defines)
  730. //BeginExport(function)
  731. DWORD
  732. StoreDeleteObject(
  733. IN OUT LPSTORE_HANDLE hStore,
  734. IN DWORD Reserved,
  735. IN LPWSTR ObjectName
  736. ) //EndExport(function)
  737. {
  738. DWORD Result;
  739. HRESULT hResult;
  740. AssertRet(hStore, ERROR_INVALID_PARAMETER);
  741. AssertRet(ObjectName, ERROR_INVALID_PARAMETER);
  742. hResult = ADSIDeleteDSObject(
  743. hStore->ADSIHandle,
  744. ObjectName
  745. );
  746. if( FAILED(hResult) ) return ConvertHresult(hResult);
  747. return ERROR_SUCCESS;
  748. }
  749. //BeginExport(function)
  750. //DOC StoreDeleteThisObject deletes the object defined by hStore,StoreGetType and ADsPath.
  751. //DOC The refer to the object just the same way as for StoreGetHandle.
  752. DWORD
  753. StoreDeleteThisObject( // delete an object
  754. IN LPSTORE_HANDLE hStore, // point of anchor frm which reference is done
  755. IN DWORD Reserved, // must be zero, reserved for future use
  756. IN DWORD StoreGetType, // path is relative, absolute or diff server?
  757. IN LPWSTR Path // ADsPath to the object or relative path
  758. ) //EndExport(function)
  759. {
  760. HRESULT hResult;
  761. DWORD Result;
  762. DWORD Size;
  763. LPWSTR ConvertedPath, ChildNameStart,ChildNameEnd;
  764. LPWSTR ChildName;
  765. HANDLE ParentObject;
  766. AssertRet(hStore, ERROR_INVALID_PARAMETER);
  767. AssertRet(hStore->Location, ERROR_INVALID_PARAMETER);
  768. AssertRet(Path, ERROR_INVALID_PARAMETER);
  769. Result = ConvertPath(hStore, StoreGetType, Path, &ConvertedPath);
  770. if( ERROR_SUCCESS != Result ) return Result;
  771. Require(ConvertedPath);
  772. ChildNameStart = wcschr(ConvertedPath, L'/'); Require(ChildNameStart); ChildNameStart++;
  773. ChildNameStart = wcschr(ChildNameStart, L'/'); Require(ChildNameStart); ChildNameStart++;
  774. if( wcschr(ChildNameStart, L'/') ) {
  775. ChildNameStart = wcschr(ChildNameStart, L'/');
  776. Require(ChildNameStart); ChildNameStart++;
  777. }
  778. ChildNameEnd = wcschr(ChildNameStart, L','); Require(ChildNameEnd); *ChildNameEnd++ = L'\0';
  779. ChildName = MemAlloc((DWORD)((LPBYTE)ChildNameEnd - (LPBYTE)ChildNameStart));
  780. if( NULL == ChildName ) {
  781. MemFree(ConvertPath);
  782. return ERROR_NOT_ENOUGH_MEMORY;
  783. }
  784. memcpy(ChildName, ChildNameStart, (int)((LPBYTE)ChildNameEnd - (LPBYTE)ChildNameStart));
  785. wcscpy(ChildNameStart, ChildNameEnd); // remove child name from ConvertPath
  786. hResult = ADSIOpenDSObject( // open the parent object
  787. ConvertedPath,
  788. hStore->UserName,
  789. hStore->Password,
  790. hStore->AuthFlags,
  791. &ParentObject
  792. );
  793. MemFree(ConvertedPath);
  794. if( FAILED(hResult) ) {
  795. MemFree(ChildName);
  796. return ConvertHresult(hResult);
  797. }
  798. hResult = ADSIDeleteDSObject( // delete the required child object
  799. ParentObject,
  800. ChildName
  801. );
  802. MemFree(ChildName);
  803. ADSICloseDSObject(ParentObject); // free up handles and memory
  804. if( FAILED(hResult) ) return ConvertHresult(hResult);
  805. return ERROR_SUCCESS; // : need to have better error messages than this
  806. }
  807. //BeginExport(function)
  808. DWORD
  809. StoreSetAttributesVA( // set the attributes, var_args interface (nearly similar to CreateVA)
  810. IN OUT LPSTORE_HANDLE hStore,
  811. IN DWORD Reserved,
  812. IN OUT DWORD* nAttributesModified,
  813. ... // fmt is {ADSTYPE, CtrlCode, AttribName, Value}* ending in ADSTYPE_INVALID
  814. ) //EndExport(function)
  815. {
  816. HRESULT hResult;
  817. DWORD Result;
  818. DWORD i;
  819. DWORD ArgType;
  820. DWORD nArgs;
  821. va_list Args;
  822. PADS_ATTR_INFO Attributes;
  823. AssertRet(hStore, ERROR_INVALID_PARAMETER);
  824. AssertRet(hStore->ADSIHandle, ERROR_INVALID_PARAMETER);
  825. nArgs = 0;
  826. va_start(Args, nAttributesModified);
  827. do {
  828. ArgType = va_arg(Args, DWORD);
  829. if( ADSTYPE_INVALID == ArgType ) break;
  830. va_arg(Args, DWORD); // skip control code
  831. va_arg(Args, LPWSTR); // skip the name of attrib
  832. switch(ArgType) {
  833. case ADSTYPE_DN_STRING :
  834. case ADSTYPE_CASE_EXACT_STRING:
  835. case ADSTYPE_CASE_IGNORE_STRING:
  836. case ADSTYPE_PRINTABLE_STRING:
  837. case ADSTYPE_NUMERIC_STRING:
  838. case ADSTYPE_OBJECT_CLASS:
  839. case ADSTYPE_UTC_TIME:
  840. va_arg(Args,LPWSTR);
  841. break;
  842. case ADSTYPE_BOOLEAN:
  843. case ADSTYPE_INTEGER:
  844. va_arg( Args, DWORD);
  845. break;
  846. case ADSTYPE_OCTET_STRING:
  847. va_arg(Args, LPBYTE);
  848. va_arg(Args, DWORD); // additional DWORD values for these..
  849. case ADSTYPE_LARGE_INTEGER:
  850. va_arg(Args, LONG);
  851. va_arg(Args, DWORD); // additional DWORD values for these..
  852. break;
  853. default:
  854. return ERROR_INVALID_PARAMETER;
  855. }
  856. nArgs ++;
  857. } while( 1 );
  858. if( 0 == nArgs ) {
  859. Attributes = NULL;
  860. } else {
  861. Attributes = MemAlloc(nArgs * sizeof(*Attributes));
  862. if( NULL == Attributes ) return ERROR_NOT_ENOUGH_MEMORY;
  863. memset(Attributes, 0, sizeof(*Attributes));
  864. }
  865. va_start(Args, nAttributesModified);
  866. for(i = 0; i < nArgs; i ++ ) {
  867. ArgType = va_arg(Args, DWORD);
  868. Require(ADSTYPE_INVALID != ArgType);
  869. Attributes[i].dwNumValues = 1;
  870. Attributes[i].pADsValues = MemAlloc(sizeof(*Attributes[i].pADsValues));
  871. if( NULL == Attributes[i].pADsValues ) {
  872. nArgs = i;
  873. goto Cleanup;
  874. }
  875. Attributes[i].dwControlCode = (DWORD)va_arg(Args, DWORD);
  876. Attributes[i].pszAttrName = (LPWSTR)va_arg(Args, LPWSTR);
  877. Attributes[i].dwADsType = ArgType;
  878. Attributes[i].pADsValues[0].dwType = ArgType;
  879. switch(ArgType) {
  880. case ADSTYPE_DN_STRING :
  881. Attributes[i].pADsValues[0].DNString = (LPWSTR)va_arg(Args,LPWSTR); break;
  882. case ADSTYPE_CASE_EXACT_STRING:
  883. Attributes[i].pADsValues[0].CaseExactString = (LPWSTR)va_arg(Args,LPWSTR); break;
  884. case ADSTYPE_CASE_IGNORE_STRING:
  885. Attributes[i].pADsValues[0].CaseIgnoreString = (LPWSTR)va_arg(Args,LPWSTR); break;
  886. case ADSTYPE_PRINTABLE_STRING:
  887. Attributes[i].pADsValues[0].PrintableString = (LPWSTR)va_arg(Args,LPWSTR); break;
  888. case ADSTYPE_NUMERIC_STRING:
  889. Attributes[i].pADsValues[0].NumericString = (LPWSTR)va_arg(Args,LPWSTR); break;
  890. case ADSTYPE_BOOLEAN:
  891. Attributes[i].pADsValues[0].Boolean = va_arg(Args,DWORD); break;
  892. case ADSTYPE_INTEGER:
  893. Attributes[i].pADsValues[0].Integer = va_arg(Args,DWORD); break;
  894. case ADSTYPE_OBJECT_CLASS:
  895. Attributes[i].pADsValues[0].ClassName = (LPWSTR)va_arg(Args,LPWSTR); break;
  896. case ADSTYPE_OCTET_STRING:
  897. Attributes[i].pADsValues[0].OctetString.lpValue = (LPBYTE)va_arg(Args,LPBYTE);
  898. Attributes[i].pADsValues[0].OctetString.dwLength = va_arg(Args, DWORD);
  899. break;
  900. case ADSTYPE_LARGE_INTEGER:
  901. Attributes[i].pADsValues[0].LargeInteger.HighPart = (LONG)va_arg(Args,LONG);
  902. Attributes[i].pADsValues[0].LargeInteger.LowPart = va_arg(Args, ULONG);
  903. break;
  904. case ADSTYPE_UTC_TIME:
  905. Attributes[i].pADsValues[0].UTCTime = *((ADS_UTC_TIME*)va_arg(Args,PVOID));
  906. break;
  907. default:
  908. nArgs = i;
  909. Result = ERROR_INVALID_PARAMETER;
  910. goto Cleanup;
  911. }
  912. }
  913. hResult = ADSISetObjectAttributes(
  914. hStore->ADSIHandle,
  915. Attributes,
  916. nArgs,
  917. nAttributesModified
  918. );
  919. if( FAILED(hResult) ) return ConvertHresult(hResult);
  920. Result = ERROR_SUCCESS;
  921. Cleanup:
  922. if( NULL != Attributes ) {
  923. for( i = 0; i < nArgs ; i ++ ) {
  924. if( Attributes[i].pADsValues ) MemFree(Attributes[i].pADsValues);
  925. }
  926. MemFree(Attributes);
  927. }
  928. return Result;
  929. }
  930. //BeginExport(function)
  931. DWORD
  932. StoreSetAttributesL( // PADS_ATTR_INFO array equiv for SetAttributesVA
  933. IN OUT LPSTORE_HANDLE hStore,
  934. IN DWORD Reserved,
  935. IN OUT DWORD* nAttributesModified,
  936. IN PADS_ATTR_INFO AttribArray,
  937. IN DWORD nAttributes
  938. ) //EndExport(function)
  939. {
  940. HRESULT hResult;
  941. AssertRet(hStore, ERROR_INVALID_PARAMETER);
  942. AssertRet(hStore->ADSIHandle, ERROR_INVALID_PARAMETER);
  943. hResult = ADSISetObjectAttributes(
  944. hStore->ADSIHandle,
  945. AttribArray,
  946. nAttributes,
  947. nAttributesModified
  948. );
  949. if( FAILED(hResult) ) return ConvertHresult(hResult);
  950. return ERROR_SUCCESS;
  951. }
  952. //================================================================================
  953. // dhcp specific stuff follow here..
  954. //================================================================================
  955. //BeginExport(typedef)
  956. typedef struct _EATTRIB { // encapsulated attribute
  957. unsigned int Address1_present : 1;
  958. unsigned int Address2_present : 1;
  959. unsigned int Address3_present : 1;
  960. unsigned int ADsPath_present : 1;
  961. unsigned int StoreGetType_present : 1;
  962. unsigned int Flags1_present : 1;
  963. unsigned int Flags2_present : 1;
  964. unsigned int Dword1_present : 1;
  965. unsigned int Dword2_present : 1;
  966. unsigned int String1_present : 1;
  967. unsigned int String2_present : 1;
  968. unsigned int String3_present : 1;
  969. unsigned int String4_present : 1;
  970. unsigned int Binary1_present : 1;
  971. unsigned int Binary2_present : 1;
  972. DWORD Address1; // character "i"
  973. DWORD Address2; // character "j"
  974. DWORD Address3; // character "k"
  975. LPWSTR ADsPath; // character "p" "r" "l"
  976. DWORD StoreGetType; // "p,r,l" ==> sameserver, child, otherserver
  977. DWORD Flags1; // character "f"
  978. DWORD Flags2; // character "g"
  979. DWORD Dword1; // character "d"
  980. DWORD Dword2; // character "e"
  981. LPWSTR String1; // character "s"
  982. LPWSTR String2; // character "t"
  983. LPWSTR String3; // character "u"
  984. LPWSTR String4; // character "v"
  985. LPBYTE Binary1; // character "b"
  986. DWORD BinLen1; // # of bytes of above
  987. LPBYTE Binary2; // character "d"
  988. DWORD BinLen2; // # of bytes of above
  989. } EATTRIB, *PEATTRIB, *LPEATTRIB;
  990. //EndExport(typedef)
  991. //BeginExport(defines)
  992. #define IS_ADDRESS1_PRESENT(pEA) ((pEA)->Address1_present)
  993. #define IS_ADDRESS1_ABSENT(pEA) (!IS_ADDRESS1_PRESENT(pEA))
  994. #define ADDRESS1_PRESENT(pEA) ((pEA)->Address1_present = 1 )
  995. #define ADDRESS1_ABSENT(pEA) ((pEA)->Address1_present = 0 )
  996. #define IS_ADDRESS2_PRESENT(pEA) ((pEA)->Address2_present)
  997. #define IS_ADDRESS2_ABSENT(pEA) (!IS_ADDRESS2_PRESENT(pEA))
  998. #define ADDRESS2_PRESENT(pEA) ((pEA)->Address2_present = 1 )
  999. #define ADDRESS2_ABSENT(pEA) ((pEA)->Address2_present = 0 )
  1000. #define IS_ADDRESS3_PRESENT(pEA) ((pEA)->Address3_present)
  1001. #define IS_ADDRESS3_ABSENT(pEA) (!IS_ADDRESS3_PRESENT(pEA))
  1002. #define ADDRESS3_PRESENT(pEA) ((pEA)->Address3_present = 1 )
  1003. #define ADDRESS3_ABSENT(pEA) ((pEA)->Address3_present = 0 )
  1004. #define IS_ADSPATH_PRESENT(pEA) ((pEA)->ADsPath_present)
  1005. #define IS_ADSPATH_ABSENT(pEA) (!IS_ADSPATH_PRESENT(pEA))
  1006. #define ADSPATH_PRESENT(pEA) ((pEA)->ADsPath_present = 1)
  1007. #define ADSPATH_ABSENT(pEA) ((pEA)->ADsPath_present = 0)
  1008. #define IS_STOREGETTYPE_PRESENT(pEA) ((pEA)->StoreGetType_present)
  1009. #define IS_STOREGETTYPE_ABSENT(pEA) (!((pEA)->StoreGetType_present))
  1010. #define STOREGETTYPE_PRESENT(pEA) ((pEA)->StoreGetType_present = 1)
  1011. #define STOREGETTYPE_ABSENT(pEA) ((pEA)->StoreGetType_present = 0)
  1012. #define IS_FLAGS1_PRESENT(pEA) ((pEA)->Flags1_present)
  1013. #define IS_FLAGS1_ABSENT(pEA) (!((pEA)->Flags1_present))
  1014. #define FLAGS1_PRESENT(pEA) ((pEA)->Flags1_present = 1)
  1015. #define FLAGS1_ABSENT(pEA) ((pEA)->Flags1_present = 0)
  1016. #define IS_FLAGS2_PRESENT(pEA) ((pEA)->Flags2_present)
  1017. #define IS_FLAGS2_ABSENT(pEA) (!((pEA)->Flags2_present))
  1018. #define FLAGS2_PRESENT(pEA) ((pEA)->Flags2_present = 1)
  1019. #define FLAGS2_ABSENT(pEA) ((pEA)->Flags2_present = 0)
  1020. #define IS_DWORD1_PRESENT(pEA) ((pEA)->Dword1_present)
  1021. #define IS_DWORD1_ABSENT(pEA) (!((pEA)->Dword1_present))
  1022. #define DWORD1_PRESENT(pEA) ((pEA)->Dword1_present = 1)
  1023. #define DWORD1_ABSENT(pEA) ((pEA)->Dword1_present = 0)
  1024. #define IS_DWORD2_PRESENT(pEA) ((pEA)->Dword2_present)
  1025. #define IS_DWORD2_ABSENT(pEA) (!((pEA)->Dword2_present))
  1026. #define DWORD2_PRESENT(pEA) ((pEA)->Dword2_present = 1)
  1027. #define DWORD2_ABSENT(pEA) ((pEA)->Dword2_present = 0)
  1028. #define IS_STRING1_PRESENT(pEA) ((pEA)->String1_present)
  1029. #define IS_STRING1_ABSENT(pEA) (!((pEA)->String1_present))
  1030. #define STRING1_PRESENT(pEA) ((pEA)->String1_present = 1)
  1031. #define STRING1_ABSENT(pEA) ((pEA)->String1_present = 0)
  1032. #define IS_STRING2_PRESENT(pEA) ((pEA)->String2_present)
  1033. #define IS_STRING2_ABSENT(pEA) (!((pEA)->String2_present))
  1034. #define STRING2_PRESENT(pEA) ((pEA)->String2_present = 1)
  1035. #define STRING2_ABSENT(pEA) ((pEA)->String2_present = 0)
  1036. #define IS_STRING3_PRESENT(pEA) ((pEA)->String3_present)
  1037. #define IS_STRING3_ABSENT(pEA) (!((pEA)->String3_present))
  1038. #define STRING3_PRESENT(pEA) ((pEA)->String3_present = 1)
  1039. #define STRING3_ABSENT(pEA) ((pEA)->String3_present = 0)
  1040. #define IS_STRING4_PRESENT(pEA) ((pEA)->String4_present)
  1041. #define IS_STRING4_ABSENT(pEA) (!((pEA)->String4_present))
  1042. #define STRING4_PRESENT(pEA) ((pEA)->String4_present = 1)
  1043. #define STRING4_ABSENT(pEA) ((pEA)->String4_present = 0)
  1044. #define IS_BINARY1_PRESENT(pEA) ((pEA)->Binary1_present)
  1045. #define IS_BINARY1_ABSENT(pEA) (!((pEA)->Binary1_present))
  1046. #define BINARY1_PRESENT(pEA) ((pEA)->Binary1_present = 1)
  1047. #define BINARY1_ABSENT(pEA) ((pEA)->Binary1_present = 0)
  1048. #define IS_BINARY2_PRESENT(pEA) ((pEA)->Binary2_present)
  1049. #define IS_BINARY2_ABSENT(pEA) (!((pEA)->Binary2_present))
  1050. #define BINARY2_PRESENT(pEA) ((pEA)->Binary2_present = 1)
  1051. #define BINARY2_ABSENT(pEA) ((pEA)->Binary2_present = 0)
  1052. //EndExport(defines)
  1053. //BeginExport(inline)
  1054. BOOL _inline
  1055. IsAnythingPresent(
  1056. IN PEATTRIB pEA
  1057. )
  1058. {
  1059. return IS_ADDRESS1_PRESENT(pEA)
  1060. || IS_ADDRESS2_PRESENT(pEA)
  1061. || IS_ADDRESS3_PRESENT(pEA)
  1062. || IS_ADSPATH_PRESENT(pEA)
  1063. || IS_STOREGETTYPE_PRESENT(pEA)
  1064. || IS_FLAGS1_PRESENT(pEA)
  1065. || IS_FLAGS2_PRESENT(pEA)
  1066. || IS_DWORD1_PRESENT(pEA)
  1067. || IS_DWORD2_PRESENT(pEA)
  1068. || IS_STRING1_PRESENT(pEA)
  1069. || IS_STRING2_PRESENT(pEA)
  1070. || IS_STRING3_PRESENT(pEA)
  1071. || IS_STRING4_PRESENT(pEA)
  1072. || IS_BINARY1_PRESENT(pEA)
  1073. || IS_BINARY2_PRESENT(pEA)
  1074. ;
  1075. }
  1076. //EndExport(inline)
  1077. //BeginExport(inline)
  1078. BOOL _inline
  1079. IsEverythingPresent(
  1080. IN PEATTRIB pEA
  1081. )
  1082. {
  1083. return IS_ADDRESS1_PRESENT(pEA)
  1084. && IS_ADDRESS2_PRESENT(pEA)
  1085. && IS_ADDRESS3_PRESENT(pEA)
  1086. && IS_ADSPATH_PRESENT(pEA)
  1087. && IS_STOREGETTYPE_PRESENT(pEA)
  1088. && IS_FLAGS1_PRESENT(pEA)
  1089. && IS_FLAGS2_PRESENT(pEA)
  1090. && IS_DWORD1_PRESENT(pEA)
  1091. && IS_DWORD2_PRESENT(pEA)
  1092. && IS_STRING1_PRESENT(pEA)
  1093. && IS_STRING2_PRESENT(pEA)
  1094. && IS_STRING3_PRESENT(pEA)
  1095. && IS_STRING4_PRESENT(pEA)
  1096. && IS_BINARY1_PRESENT(pEA)
  1097. && IS_BINARY2_PRESENT(pEA)
  1098. ;
  1099. }
  1100. //EndExport(inline)
  1101. //BeginExport(inline)
  1102. VOID _inline
  1103. EverythingPresent(
  1104. IN PEATTRIB pEA
  1105. )
  1106. {
  1107. ADDRESS1_PRESENT(pEA);
  1108. ADDRESS2_PRESENT(pEA);
  1109. ADDRESS3_PRESENT(pEA);
  1110. ADSPATH_PRESENT(pEA);
  1111. STOREGETTYPE_ABSENT(pEA);
  1112. FLAGS1_PRESENT(pEA);
  1113. FLAGS2_PRESENT(pEA);
  1114. DWORD1_PRESENT(pEA);
  1115. DWORD2_PRESENT(pEA);
  1116. STRING1_PRESENT(pEA);
  1117. STRING2_PRESENT(pEA);
  1118. STRING3_PRESENT(pEA);
  1119. STRING4_PRESENT(pEA);
  1120. BINARY1_PRESENT(pEA);
  1121. BINARY2_PRESENT(pEA);
  1122. }
  1123. //EndExport(inline)
  1124. //BeginExport(inline)
  1125. VOID _inline
  1126. NothingPresent(
  1127. IN PEATTRIB pEA
  1128. )
  1129. {
  1130. ADDRESS1_ABSENT(pEA);
  1131. ADDRESS2_ABSENT(pEA);
  1132. ADDRESS3_ABSENT(pEA);
  1133. ADSPATH_ABSENT(pEA);
  1134. STOREGETTYPE_ABSENT(pEA);
  1135. FLAGS1_ABSENT(pEA);
  1136. FLAGS2_ABSENT(pEA);
  1137. DWORD1_ABSENT(pEA);
  1138. DWORD2_ABSENT(pEA);
  1139. STRING1_ABSENT(pEA);
  1140. STRING2_ABSENT(pEA);
  1141. STRING3_ABSENT(pEA);
  1142. STRING4_ABSENT(pEA);
  1143. BINARY1_ABSENT(pEA);
  1144. BINARY2_ABSENT(pEA);
  1145. }
  1146. //EndExport(inline)
  1147. const char
  1148. ch_Address1 = L'i' ,
  1149. ch_Address2 = L'j' ,
  1150. ch_Address3 = L'k' ,
  1151. ch_ADsPath_relative = L'r' ,
  1152. ch_ADsPath_absolute = L'p' ,
  1153. ch_ADsPath_diff_srvr = L'l' ,
  1154. ch_Flags1 = L'f' ,
  1155. ch_Flags2 = L'g' ,
  1156. ch_Dword1 = L'd' ,
  1157. ch_Dword2 = L'e' ,
  1158. ch_String1 = L's' ,
  1159. ch_String2 = L't' ,
  1160. ch_String3 = L'u' ,
  1161. ch_String4 = L'v' ,
  1162. ch_Binary1 = L'b' ,
  1163. ch_Binary2 = L'c' ,
  1164. ch_FieldSep = L'$' ;
  1165. DWORD
  1166. StringToIpAddress( // convert a string to an ip-address
  1167. IN LPWSTR String,
  1168. IN OUT DWORD *Address
  1169. )
  1170. {
  1171. CHAR Buffer[20]; // large enough to hold any ip address stuff
  1172. DWORD Count;
  1173. LPSTR SkippedWhiteSpace;
  1174. Count = wcstombs(Buffer, String, sizeof(Buffer) - 1); // save space for '\0'
  1175. if( -1 == Count ) return ERROR_INVALID_DATA;
  1176. Buffer[Count] = '\0';
  1177. SkippedWhiteSpace = Buffer;
  1178. while(( ' ' == *SkippedWhiteSpace || '\t' == *SkippedWhiteSpace) &&
  1179. ( SkippedWhiteSpace < &Buffer[Count])) {
  1180. SkippedWhiteSpace++;
  1181. }
  1182. *Address= ntohl(inet_addr(SkippedWhiteSpace));// address is in host order..
  1183. if( '\0' == *SkippedWhiteSpace ) return ERROR_INVALID_DATA;
  1184. return Count <= sizeof("000.000.000.000") ? ERROR_SUCCESS : ERROR_INVALID_DATA;
  1185. }
  1186. DWORD _inline
  1187. StringToFlags( // convert a string to a DWORD
  1188. IN LPWSTR String,
  1189. IN OUT DWORD *Flags
  1190. )
  1191. {
  1192. DWORD Count;
  1193. LPWSTR Remaining;
  1194. *Flags = ntohl(wcstoul(String, &Remaining,0));// see input for # base. conv to host order
  1195. if( *Remaining == L'\0' ) return ERROR_SUCCESS;
  1196. return ERROR_INVALID_DATA;
  1197. }
  1198. BYTE _inline
  1199. Hex(
  1200. IN WCHAR wCh
  1201. )
  1202. {
  1203. if( wCh >= '0' && wCh <= '9' ) return wCh - '0';
  1204. if( wCh >= 'A' && wCh <= 'F' ) return wCh - 'A' + 10;
  1205. if( wCh >= 'a' && wCh <= 'f' ) return wCh - 'a' + 10;
  1206. return 0x0F+1; // this means error!!!
  1207. }
  1208. DWORD _inline
  1209. StringToBinary( // inline conversion of a string to binary
  1210. IN OUT LPWSTR String, // this string is mangled while converting
  1211. IN OUT LPBYTE *Bytes, // this ptr is set to some memory in String..
  1212. IN OUT DWORD *nBytes // # of hex bytes copied into location Bytes
  1213. ) {
  1214. LPBYTE HexString;
  1215. DWORD n;
  1216. BYTE ch1, ch2;
  1217. HexString = *Bytes = (LPBYTE)String;
  1218. n = 0;
  1219. while( *String != L'\0' ) { // look at each character
  1220. ch1 = Hex(*String++);
  1221. ch2 = Hex(*String++);
  1222. if( ch1 > 0xF || ch2 > 0xF ) { // invalid hex bytes for input?
  1223. return ERROR_INVALID_DATA;
  1224. }
  1225. *HexString ++ = (ch1 << 4 ) | ch2;
  1226. n ++;
  1227. }
  1228. *nBytes = n;
  1229. return ERROR_SUCCESS;
  1230. }
  1231. DWORD
  1232. ConvertStringtoEAttrib( // parse and get the fields out
  1233. IN OUT LPWSTR String, // may be destroyed in the process
  1234. IN OUT PEATTRIB Attrib // fill this in
  1235. )
  1236. {
  1237. DWORD Result;
  1238. DWORD Address;
  1239. DWORD Flags;
  1240. WCHAR ThisChar;
  1241. LPWSTR ThisString;
  1242. CHAR Dummy[20];
  1243. WCHAR Sep;
  1244. Require(Attrib);
  1245. NothingPresent(Attrib);
  1246. if( String ) StoreTrace2("ConvertStringtoEAttrib(%ws) called\n", String);
  1247. Sep = ch_FieldSep;
  1248. while(String && *String && (ThisChar = *String ++)) {
  1249. ThisString = String;
  1250. do { // skip to the next attrib
  1251. String = wcschr(String, Sep);
  1252. if( NULL == String ) break;
  1253. if( String[1] == Sep ) { // double consequtive field-sep's stand for the real thing..
  1254. wcscpy(String, &String[1]); // remove one of the field-separators, and try looking for one lateron.
  1255. String ++;
  1256. continue;
  1257. }
  1258. *String++ = L'\0'; // ok, got a real separator: mark that zero and prepare for next
  1259. break;
  1260. } while(1); // this could as well be while(0) ??
  1261. if( ch_Address1 == ThisChar ) { // this is address1
  1262. SetInternalFormatError(REPEATED_ADDRESS1, IS_ADDRESS1_PRESENT(Attrib));
  1263. Result = StringToIpAddress(
  1264. ThisString,
  1265. &Address
  1266. );
  1267. if( ERROR_SUCCESS != Result ) { // should not happen
  1268. SetInternalFormatError(INVALID_ADDRESS1, TRUE);
  1269. } else {
  1270. ADDRESS1_PRESENT(Attrib);
  1271. Attrib->Address1 = Address;
  1272. StoreTrace2("Found address1 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1273. }
  1274. continue;
  1275. }
  1276. if( ch_Address2 == ThisChar ) {
  1277. SetInternalFormatError(REPEATED_ADDRESS2, IS_ADDRESS2_PRESENT(Attrib));
  1278. Result = StringToIpAddress(
  1279. ThisString,
  1280. &Address
  1281. );
  1282. if( ERROR_SUCCESS != Result ) { // should not happen
  1283. SetInternalFormatError(INVALID_ADDRESS2, TRUE);
  1284. } else {
  1285. ADDRESS2_PRESENT(Attrib);
  1286. Attrib->Address2 = Address;
  1287. StoreTrace2("Found address2 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1288. }
  1289. continue;
  1290. }
  1291. if( ch_Address3 == ThisChar ) {
  1292. SetInternalFormatError(REPEATED_ADDRESS3, IS_ADDRESS3_PRESENT(Attrib));
  1293. Result = StringToIpAddress(
  1294. ThisString,
  1295. &Address
  1296. );
  1297. if( ERROR_SUCCESS != Result ) { // should not happen
  1298. SetInternalFormatError(INVALID_ADDRESS3, TRUE);
  1299. } else {
  1300. ADDRESS3_PRESENT(Attrib);
  1301. Attrib->Address3 = Address;
  1302. StoreTrace2("Found address3 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1303. }
  1304. continue;
  1305. }
  1306. if( ch_ADsPath_relative == ThisChar ||
  1307. ch_ADsPath_absolute == ThisChar ||
  1308. ch_ADsPath_diff_srvr == ThisChar ) {
  1309. SetInternalFormatError(REPEATED_ADSPATH, IS_ADSPATH_PRESENT(Attrib));
  1310. ADSPATH_PRESENT(Attrib);
  1311. STOREGETTYPE_PRESENT(Attrib);
  1312. Attrib->ADsPath = ThisString;
  1313. if( ch_ADsPath_relative == ThisChar )
  1314. Attrib->StoreGetType = StoreGetChildType;
  1315. else if(ch_ADsPath_absolute == ThisChar )
  1316. Attrib->StoreGetType = StoreGetAbsoluteSameServerType;
  1317. else if(ch_ADsPath_diff_srvr == ThisChar )
  1318. Attrib->StoreGetType = StoreGetAbsoluteOtherServerType;
  1319. StoreTrace3("Found path [%ld] [%ws]\n", Attrib->StoreGetType, ThisString);
  1320. continue;
  1321. }
  1322. if( ch_String1 == ThisChar ) {
  1323. SetInternalFormatError(REPEATED_STRING1, IS_STRING1_PRESENT(Attrib));
  1324. STRING1_PRESENT(Attrib);
  1325. Attrib->String1 = ThisString;
  1326. StoreTrace2("Found string1 [%ws]\n", ThisString);
  1327. continue;
  1328. }
  1329. if( ch_String2 == ThisChar ) {
  1330. SetInternalFormatError(REPEATED_STRING2, IS_STRING2_PRESENT(Attrib));
  1331. STRING2_PRESENT(Attrib);
  1332. Attrib->String2 = ThisString;
  1333. StoreTrace2("Found string2 [%ws]\n", ThisString);
  1334. continue;
  1335. }
  1336. if( ch_String3 == ThisChar ) {
  1337. SetInternalFormatError(REPEATED_STRING3, IS_STRING3_PRESENT(Attrib));
  1338. STRING3_PRESENT(Attrib);
  1339. Attrib->String3 = ThisString;
  1340. StoreTrace2("Found string3 [%ws]\n", ThisString);
  1341. continue;
  1342. }
  1343. if( ch_String4 == ThisChar ) {
  1344. SetInternalFormatError(REPEATED_STRING4, IS_STRING4_PRESENT(Attrib));
  1345. STRING4_PRESENT(Attrib);
  1346. Attrib->String4 = ThisString;
  1347. StoreTrace2("Found string4 [%ws]\n", ThisString);
  1348. continue;
  1349. }
  1350. if( ch_Flags1 == ThisChar ) {
  1351. SetInternalFormatError(REPEATED_FLAGS1, IS_FLAGS1_PRESENT(Attrib));
  1352. Result = StringToFlags(
  1353. ThisString,
  1354. &Flags
  1355. );
  1356. if( ERROR_SUCCESS != Result ) {
  1357. SetInternalFormatError(INVALID_FLAGS1, TRUE);
  1358. } else {
  1359. FLAGS1_PRESENT(Attrib);
  1360. Attrib->Flags1 = Flags;
  1361. StoreTrace2("Found flags1: 0x%lx\n", Flags);
  1362. }
  1363. continue;
  1364. }
  1365. if( ch_Flags2 == ThisChar ) {
  1366. SetInternalFormatError(REPEATED_FLAGS2, IS_FLAGS2_PRESENT(Attrib));
  1367. Result = StringToFlags(
  1368. ThisString,
  1369. &Flags
  1370. );
  1371. if( ERROR_SUCCESS != Result ) {
  1372. SetInternalFormatError(INVALID_FLAGS2, TRUE);
  1373. } else {
  1374. FLAGS2_PRESENT(Attrib);
  1375. Attrib->Flags2 = Flags;
  1376. StoreTrace2("Found flags2: 0x%lx\n", Flags);
  1377. }
  1378. continue;
  1379. }
  1380. if( ch_Dword1 == ThisChar ) {
  1381. SetInternalFormatError(REPEATED_DWORD1, IS_DWORD1_PRESENT(Attrib));
  1382. Result = StringToFlags(
  1383. ThisString,
  1384. &Flags
  1385. );
  1386. if( ERROR_SUCCESS != Result ) {
  1387. SetInternalFormatError(INVALID_DWORD1, TRUE);
  1388. } else {
  1389. DWORD1_PRESENT(Attrib);
  1390. Attrib->Dword1 = Flags;
  1391. StoreTrace2("Found dword1: 0x%lx\n", Flags);
  1392. }
  1393. continue;
  1394. }
  1395. if( ch_Dword2 == ThisChar ) {
  1396. SetInternalFormatError(REPEATED_DWORD2, IS_DWORD2_PRESENT(Attrib));
  1397. Result = StringToFlags(
  1398. ThisString,
  1399. &Flags
  1400. );
  1401. if( ERROR_SUCCESS != Result ) {
  1402. SetInternalFormatError(INVALID_DWORD2, TRUE);
  1403. } else {
  1404. DWORD2_PRESENT(Attrib);
  1405. Attrib->Dword2 = Flags;
  1406. StoreTrace2("Found dword2: 0x%lx\n", Flags);
  1407. }
  1408. continue;
  1409. }
  1410. if( ch_Binary1 == ThisChar ) {
  1411. SetInternalFormatError(REPEATED_BINARY1, IS_BINARY1_PRESENT(Attrib));
  1412. Result = StringToBinary(
  1413. ThisString,
  1414. &Attrib->Binary1,
  1415. &Attrib->BinLen1
  1416. );
  1417. if( ERROR_SUCCESS != Result ) {
  1418. SetInternalFormatError(INVALID_BINARY1, TRUE);
  1419. BINARY1_ABSENT(Attrib);
  1420. } else {
  1421. BINARY1_PRESENT(Attrib);
  1422. StoreTrace2("Found Binary1 of length %ld\n", Attrib->BinLen1);
  1423. }
  1424. continue;
  1425. }
  1426. if( ch_Binary2 == ThisChar ) {
  1427. SetInternalFormatError(REPEATED_BINARY2, IS_BINARY2_PRESENT(Attrib));
  1428. Result = StringToBinary(
  1429. ThisString,
  1430. &Attrib->Binary2,
  1431. &Attrib->BinLen2
  1432. );
  1433. if( ERROR_SUCCESS != Result ) {
  1434. SetInternalFormatError(INVALID_BINARY2, TRUE);
  1435. BINARY2_ABSENT(Attrib);
  1436. } else {
  1437. BINARY2_PRESENT(Attrib);
  1438. StoreTrace2("Found Binary2 of length %ld\n", Attrib->BinLen2);
  1439. }
  1440. continue;
  1441. }
  1442. SetInternalFormatError(INVALID_ATTRIB_FIELD, TRUE);
  1443. }
  1444. return IsAnythingPresent(Attrib)? ERROR_SUCCESS : ERROR_INVALID_DATA;
  1445. }
  1446. BOOL _inline
  1447. InvalidStringInBinary( // check if the given binary stream forms a LPWSTR
  1448. IN LPBYTE Data,
  1449. IN DWORD DataLen
  1450. )
  1451. {
  1452. if( 0 == DataLen ) return TRUE;
  1453. if( DataLen % sizeof(WCHAR) ) return TRUE;
  1454. DataLen /= sizeof(WCHAR);
  1455. if( L'\0' != ((LPWSTR)Data)[DataLen-1] ) return TRUE;
  1456. return FALSE;
  1457. }
  1458. DWORD
  1459. ConvertBinarytoEAttrib( // parse and get the fields out
  1460. IN OUT LPBYTE Data, // input free format data
  1461. IN DWORD DataLen, // bytes for data length
  1462. IN OUT PEATTRIB Attrib // fill this in
  1463. )
  1464. {
  1465. DWORD Result;
  1466. DWORD Address;
  1467. DWORD Flags;
  1468. DWORD Offset;
  1469. DWORD ThisDataLen;
  1470. DWORD xDataLen;
  1471. LPBYTE xData;
  1472. LPBYTE ThisData;
  1473. WCHAR ThisChar;
  1474. CHAR Dummy[20];
  1475. Require(Attrib);
  1476. NothingPresent(Attrib);
  1477. Offset = 0;
  1478. while( Data && DataLen >= sizeof(BYTE) + sizeof(WORD) ) {
  1479. ThisChar = ntohs(*(LPWORD)Data);
  1480. Data += sizeof(WORD); DataLen -= sizeof(WORD);
  1481. ThisDataLen = ntohs(*(LPWORD)Data);
  1482. Data += sizeof(WORD); DataLen -= sizeof(WORD);
  1483. if( ROUND_UP_COUNT(ThisDataLen, ALIGN_WORD) > DataLen ) {
  1484. SetInternalFormatError(INVALID_BINARY_CODING, TRUE);
  1485. break;
  1486. }
  1487. ThisData = Data;
  1488. Data += ROUND_UP_COUNT(ThisDataLen, ALIGN_WORD);
  1489. DataLen -= ROUND_UP_COUNT(ThisDataLen, ALIGN_WORD);
  1490. if( ch_Address1 == ThisChar ) { // this is address1
  1491. SetInternalFormatError(REPEATED_ADDRESS1, IS_ADDRESS1_PRESENT(Attrib));
  1492. if( sizeof(DWORD) != ThisDataLen ) {
  1493. SetInternalFormatError(INVALID_ADDRESS1, TRUE);
  1494. } else {
  1495. Address = ntohl(*(DWORD UNALIGNED *)ThisData);
  1496. ADDRESS1_PRESENT(Attrib);
  1497. Attrib->Address1 = Address;
  1498. StoreTrace2("Found address1 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1499. }
  1500. continue;
  1501. }
  1502. if( ch_Address2 == ThisChar ) {
  1503. SetInternalFormatError(REPEATED_ADDRESS2, IS_ADDRESS2_PRESENT(Attrib));
  1504. if( sizeof(DWORD) != ThisDataLen ) {
  1505. SetInternalFormatError(INVALID_ADDRESS2, TRUE);
  1506. } else {
  1507. Address = ntohl(*(DWORD UNALIGNED *)ThisData);
  1508. ADDRESS2_PRESENT(Attrib);
  1509. Attrib->Address2 = Address;
  1510. StoreTrace2("Found address2 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1511. }
  1512. continue;
  1513. }
  1514. if( ch_Address3 == ThisChar ) {
  1515. SetInternalFormatError(REPEATED_ADDRESS3, IS_ADDRESS3_PRESENT(Attrib));
  1516. if( sizeof(DWORD) != ThisDataLen ) {
  1517. SetInternalFormatError(INVALID_ADDRESS3, TRUE);
  1518. } else {
  1519. Address = ntohl(*(DWORD UNALIGNED *)ThisData);
  1520. ADDRESS3_PRESENT(Attrib);
  1521. Attrib->Address3 = Address;
  1522. StoreTrace2("Found address3 %s\n", inet_ntoa(*(struct in_addr*)&Address));
  1523. }
  1524. continue;
  1525. }
  1526. if( ch_ADsPath_relative == ThisChar ||
  1527. ch_ADsPath_absolute == ThisChar ||
  1528. ch_ADsPath_diff_srvr == ThisChar ) {
  1529. SetInternalFormatError(REPEATED_ADSPATH, IS_ADSPATH_PRESENT(Attrib));
  1530. if( InvalidStringInBinary(ThisData, ThisDataLen) ) {
  1531. SetInternalFormatError(INVALID_ADSPATH, TRUE);
  1532. continue;
  1533. }
  1534. ADSPATH_PRESENT(Attrib);
  1535. STOREGETTYPE_PRESENT(Attrib);
  1536. Attrib->ADsPath = (LPWSTR)ThisData;
  1537. if( ch_ADsPath_relative == ThisChar )
  1538. Attrib->StoreGetType = StoreGetChildType;
  1539. else if(ch_ADsPath_absolute == ThisChar )
  1540. Attrib->StoreGetType = StoreGetAbsoluteSameServerType;
  1541. else if(ch_ADsPath_diff_srvr == ThisChar )
  1542. Attrib->StoreGetType = StoreGetAbsoluteOtherServerType;
  1543. StoreTrace3("Found path [%ld] [%ws]\n", Attrib->StoreGetType, (LPWSTR)ThisData);
  1544. continue;
  1545. }
  1546. if( ch_String1 == ThisChar ) {
  1547. SetInternalFormatError(REPEATED_STRING1, IS_STRING1_PRESENT(Attrib));
  1548. if( InvalidStringInBinary(ThisData, ThisDataLen) ) {
  1549. SetInternalFormatError(INVALID_STRING1, TRUE);
  1550. continue;
  1551. }
  1552. STRING1_PRESENT(Attrib);
  1553. Attrib->String1 = (LPWSTR)ThisData;
  1554. StoreTrace2("Found string1 [%ws]\n", (LPWSTR)ThisData);
  1555. continue;
  1556. }
  1557. if( ch_String2 == ThisChar ) {
  1558. SetInternalFormatError(REPEATED_STRING2, IS_STRING2_PRESENT(Attrib));
  1559. if( InvalidStringInBinary(ThisData, ThisDataLen) ) {
  1560. SetInternalFormatError(INVALID_STRING2, TRUE);
  1561. continue;
  1562. }
  1563. STRING2_PRESENT(Attrib);
  1564. Attrib->String2 = (LPWSTR)ThisData;
  1565. StoreTrace2("Found string2 [%ws]\n", (LPWSTR)ThisData);
  1566. continue;
  1567. }
  1568. if( ch_String3 == ThisChar ) {
  1569. SetInternalFormatError(REPEATED_STRING3, IS_STRING3_PRESENT(Attrib));
  1570. if( InvalidStringInBinary(ThisData, ThisDataLen) ) {
  1571. SetInternalFormatError(INVALID_STRING3, TRUE);
  1572. continue;
  1573. }
  1574. STRING3_PRESENT(Attrib);
  1575. Attrib->String3 = (LPWSTR)ThisData;
  1576. StoreTrace2("Found string3 [%ws]\n", (LPWSTR)ThisData);
  1577. continue;
  1578. }
  1579. if( ch_String4 == ThisChar ) {
  1580. SetInternalFormatError(REPEATED_STRING4, IS_STRING4_PRESENT(Attrib));
  1581. if( InvalidStringInBinary(ThisData, ThisDataLen) ) {
  1582. SetInternalFormatError(INVALID_STRING4, TRUE);
  1583. continue;
  1584. }
  1585. STRING4_PRESENT(Attrib);
  1586. Attrib->String4 = (LPWSTR)ThisData;
  1587. StoreTrace2("Found string4 [%ws]\n", (LPWSTR)ThisData);
  1588. continue;
  1589. }
  1590. if( ch_Flags1 == ThisChar ) {
  1591. SetInternalFormatError(REPEATED_FLAGS1, IS_FLAGS1_PRESENT(Attrib));
  1592. if( sizeof(DWORD) != ThisDataLen ) {
  1593. SetInternalFormatError(INVALID_FLAGS1, TRUE);
  1594. } else {
  1595. Flags = ntohl(*(DWORD UNALIGNED *)ThisData);
  1596. FLAGS1_PRESENT(Attrib);
  1597. Attrib->Flags1 = Flags;
  1598. StoreTrace2("Found flags1: 0x%lx\n", Flags);
  1599. }
  1600. continue;
  1601. }
  1602. if( ch_Flags2 == ThisChar ) {
  1603. SetInternalFormatError(REPEATED_FLAGS2, IS_FLAGS2_PRESENT(Attrib));
  1604. if( sizeof(DWORD) != ThisDataLen ) {
  1605. SetInternalFormatError(INVALID_FLAGS2, TRUE);
  1606. } else {
  1607. Flags = ntohl(*(DWORD UNALIGNED *)ThisData);
  1608. FLAGS2_PRESENT(Attrib);
  1609. Attrib->Flags2 = Flags;
  1610. StoreTrace2("Found flags2: 0x%lx\n", Flags);
  1611. }
  1612. continue;
  1613. }
  1614. if( ch_Dword1 == ThisChar ) {
  1615. SetInternalFormatError(REPEATED_DWORD1, IS_DWORD1_PRESENT(Attrib));
  1616. if( sizeof(DWORD) != ThisDataLen ) {
  1617. SetInternalFormatError(INVALID_DWORD1, TRUE);
  1618. } else {
  1619. Flags = ntohl(*(DWORD UNALIGNED *)ThisData);
  1620. DWORD1_PRESENT(Attrib);
  1621. Attrib->Dword1 = Flags;
  1622. StoreTrace2("Found dword1: 0x%lx\n", Flags);
  1623. }
  1624. continue;
  1625. }
  1626. if( ch_Dword2 == ThisChar ) {
  1627. SetInternalFormatError(REPEATED_DWORD2, IS_DWORD2_PRESENT(Attrib));
  1628. if( sizeof(DWORD) != ThisDataLen ) {
  1629. SetInternalFormatError(INVALID_DWORD2, TRUE);
  1630. } else {
  1631. Flags = ntohl(*(DWORD UNALIGNED *)ThisData);
  1632. DWORD2_PRESENT(Attrib);
  1633. Attrib->Dword2 = Flags;
  1634. StoreTrace2("Found dword2: 0x%lx\n", Flags);
  1635. }
  1636. continue;
  1637. }
  1638. if( ch_Binary1 == ThisChar ) {
  1639. SetInternalFormatError(REPEATED_BINARY1, IS_BINARY1_PRESENT(Attrib));
  1640. BINARY1_PRESENT(Attrib);
  1641. Attrib->Binary1 = ThisData;
  1642. Attrib->BinLen1 = ThisDataLen;
  1643. StoreTrace2("Found %ld bytes of binary 1 data\n", ThisDataLen);
  1644. continue;
  1645. }
  1646. if( ch_Binary2 == ThisChar ) {
  1647. SetInternalFormatError(REPEATED_BINARY2, IS_BINARY2_PRESENT(Attrib));
  1648. BINARY2_PRESENT(Attrib);
  1649. Attrib->Binary2 = ThisData;
  1650. Attrib->BinLen2 = ThisDataLen;
  1651. StoreTrace2("Found %ld bytes of binary 2 data\n", ThisDataLen);
  1652. continue;
  1653. }
  1654. SetInternalFormatError(INVALID_ATTRIB_FIELD, TRUE);
  1655. }
  1656. return IsAnythingPresent(Attrib) ? ERROR_SUCCESS: ERROR_INVALID_DATA;
  1657. }
  1658. PEATTRIB
  1659. CloneAttrib(
  1660. IN PEATTRIB Attrib
  1661. )
  1662. {
  1663. PEATTRIB RetVal;
  1664. DWORD Size;
  1665. Size = sizeof(*Attrib);
  1666. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  1667. if( IS_ADSPATH_PRESENT(Attrib) ) {
  1668. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->ADsPath));
  1669. }
  1670. if( IS_STRING1_PRESENT(Attrib) ) {
  1671. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String1));
  1672. }
  1673. if( IS_STRING2_PRESENT(Attrib) ) {
  1674. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String2));
  1675. }
  1676. if( IS_STRING3_PRESENT(Attrib) ) {
  1677. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String3));
  1678. }
  1679. if( IS_STRING4_PRESENT(Attrib) ) {
  1680. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String4));
  1681. }
  1682. if( IS_BINARY1_PRESENT(Attrib) ) Size += Attrib->BinLen1;
  1683. if( IS_BINARY2_PRESENT(Attrib) ) Size += Attrib->BinLen2;
  1684. RetVal = (PEATTRIB)MemAlloc(Size);
  1685. if( NULL == RetVal ) return NULL;
  1686. Size = sizeof(*Attrib);
  1687. Size = ROUND_UP_COUNT(Size, ALIGN_WORST);
  1688. *RetVal = *Attrib;
  1689. if( IS_ADSPATH_PRESENT(Attrib) ) {
  1690. RetVal->ADsPath = (LPWSTR)(Size + (LPBYTE)RetVal);
  1691. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->ADsPath));
  1692. wcscpy(RetVal->ADsPath, Attrib->ADsPath);
  1693. }
  1694. if( IS_STRING1_PRESENT(Attrib) ) {
  1695. RetVal->String1 = (LPWSTR)(Size + (LPBYTE)RetVal);
  1696. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String1));
  1697. wcscpy(RetVal->String1, Attrib->String1);
  1698. }
  1699. if( IS_STRING2_PRESENT(Attrib) ) {
  1700. RetVal->String2 = (LPWSTR)(Size + (LPBYTE)RetVal);
  1701. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String2));
  1702. wcscpy(RetVal->String2, Attrib->String2);
  1703. }
  1704. if( IS_STRING3_PRESENT(Attrib) ) {
  1705. RetVal->String3 = (LPWSTR)(Size + (LPBYTE)RetVal);
  1706. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String3));
  1707. wcscpy(RetVal->String3, Attrib->String3);
  1708. }
  1709. if( IS_STRING4_PRESENT(Attrib) ) {
  1710. RetVal->String4 = (LPWSTR)(Size + (LPBYTE)RetVal);
  1711. Size += sizeof(WCHAR)*(1 + wcslen(Attrib->String4));
  1712. wcscpy(RetVal->String4, Attrib->String4);
  1713. }
  1714. if( IS_BINARY1_PRESENT(Attrib) ) {
  1715. RetVal->Binary1 = (Size + (LPBYTE)RetVal);
  1716. Size += Attrib->BinLen1;
  1717. memcpy(RetVal->Binary1, Attrib->Binary1, Attrib->BinLen1);
  1718. }
  1719. if( IS_BINARY2_PRESENT(Attrib) ) {
  1720. RetVal->Binary2 = (Size + (LPBYTE)RetVal);
  1721. Size += Attrib->BinLen2;
  1722. memcpy(RetVal->Binary2, Attrib->Binary2, Attrib->BinLen2);
  1723. }
  1724. return RetVal;
  1725. }
  1726. DWORD
  1727. AddAttribToArray(
  1728. IN OUT PARRAY Array,
  1729. IN PEATTRIB Attrib
  1730. )
  1731. {
  1732. DWORD Result;
  1733. Require(Attrib);
  1734. Attrib = CloneAttrib(Attrib);
  1735. if( NULL == Attrib) return ERROR_NOT_ENOUGH_MEMORY;
  1736. Result = MemArrayAddElement(Array, (LPVOID)Attrib);
  1737. if( ERROR_SUCCESS == Result ) return ERROR_SUCCESS;
  1738. MemFree(Attrib);
  1739. return Result;
  1740. }
  1741. BOOL _inline
  1742. OnlyADsPathPresent(
  1743. IN PEATTRIB pEA
  1744. )
  1745. {
  1746. if( ! IS_ADSPATH_PRESENT(pEA) ) return FALSE;
  1747. return IS_ADDRESS1_ABSENT(pEA)
  1748. && IS_ADDRESS2_ABSENT(pEA)
  1749. && IS_ADSPATH_ABSENT(pEA)
  1750. && IS_STOREGETTYPE_ABSENT(pEA)
  1751. && IS_FLAGS1_ABSENT(pEA)
  1752. && IS_FLAGS2_ABSENT(pEA)
  1753. && IS_STRING1_ABSENT(pEA)
  1754. && IS_STRING2_ABSENT(pEA)
  1755. && IS_BINARY1_ABSENT(pEA)
  1756. && IS_BINARY2_ABSENT(pEA)
  1757. ;
  1758. }
  1759. DWORD
  1760. StoreCollectAttributes( // fwd declaration
  1761. IN OUT PSTORE_HANDLE hStore,
  1762. IN DWORD Reserved,
  1763. IN LPWSTR AttribName,
  1764. IN OUT PARRAY ArrayToAddTo,
  1765. IN DWORD RecursionDepth
  1766. );
  1767. DWORD _inline
  1768. StoreCollectAttributesInternal(
  1769. IN OUT PSTORE_HANDLE hStore,
  1770. IN DWORD Reserved,
  1771. IN PEATTRIB Attrib,
  1772. IN LPWSTR AttribName,
  1773. IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
  1774. IN DWORD RecursionDepth // 0 ==> no recursion
  1775. )
  1776. {
  1777. DWORD Result, Result2;
  1778. STORE_HANDLE hStore2;
  1779. if( 0 == RecursionDepth ) {
  1780. Result = AddAttribToArray(ArrayToAddTo, Attrib);
  1781. if( ERROR_SUCCESS != Result ) SetInternalFormatError(UNEXPECTED_INTERNAL_ERROR, TRUE);
  1782. return ERROR_STACK_OVERFLOW;
  1783. }
  1784. StoreTrace2("Recursing to %ws\n", Attrib->ADsPath);
  1785. Result = StoreGetHandle(
  1786. hStore,
  1787. /*Reserved*/ 0,
  1788. Attrib->StoreGetType,
  1789. Attrib->ADsPath,
  1790. &hStore2
  1791. );
  1792. if( ERROR_SUCCESS != Result ) return Result;
  1793. Result = StoreCollectAttributes(
  1794. &hStore2,
  1795. Reserved,
  1796. AttribName,
  1797. ArrayToAddTo,
  1798. RecursionDepth-1
  1799. );
  1800. Result2 = StoreCleanupHandle( &hStore2, 0 );
  1801. return Result;
  1802. }
  1803. //BeginExport(function)
  1804. DWORD
  1805. StoreCollectAttributes(
  1806. IN OUT PSTORE_HANDLE hStore,
  1807. IN DWORD Reserved,
  1808. IN LPWSTR AttribName, // this attrib must be some kind of a text string
  1809. IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
  1810. IN DWORD RecursionDepth // 0 ==> no recursion
  1811. ) //EndExport(function)
  1812. {
  1813. HRESULT hResult;
  1814. DWORD Result;
  1815. DWORD Error;
  1816. DWORD nAttributes;
  1817. DWORD i;
  1818. PADS_ATTR_INFO Attributes;
  1819. LPWSTR Attribs[1];
  1820. LPWSTR ThisAttribStr;
  1821. EATTRIB ThisEAttrib;
  1822. Attribs[0] = AttribName;
  1823. Attributes = NULL;
  1824. nAttributes = 0;
  1825. hResult = ADSIGetObjectAttributes(
  1826. hStore->ADSIHandle,
  1827. Attribs,
  1828. sizeof(Attribs)/sizeof(Attribs[0]),
  1829. &Attributes,
  1830. &nAttributes
  1831. );
  1832. if( HRESULT_FROM_WIN32( ERROR_DS_NO_ATTRIBUTE_OR_VALUE) == hResult ) {
  1833. return ERROR_SUCCESS;
  1834. }
  1835. if( FAILED(hResult) ) return ConvertHresult(hResult);
  1836. if( 0 == nAttributes || NULL == Attributes )
  1837. return ERROR_SUCCESS;
  1838. Require( 1 == nAttributes );
  1839. Error = ERROR_SUCCESS;
  1840. for( i = 0; i < Attributes[0].dwNumValues ; i ++ ) {
  1841. switch(Attributes[0].pADsValues[i].dwType) {
  1842. case ADSTYPE_DN_STRING:
  1843. ThisAttribStr = Attributes[0].pADsValues[i].DNString; break;
  1844. case ADSTYPE_CASE_EXACT_STRING:
  1845. ThisAttribStr = Attributes[0].pADsValues[i].CaseExactString; break;
  1846. case ADSTYPE_CASE_IGNORE_STRING:
  1847. ThisAttribStr = Attributes[0].pADsValues[i].CaseIgnoreString; break;
  1848. case ADSTYPE_PRINTABLE_STRING:
  1849. ThisAttribStr = Attributes[0].pADsValues[i].PrintableString; break;
  1850. default:
  1851. SetInternalFormatError(UNEXPECTED_COLLECTION_TYPE, TRUE);
  1852. continue;
  1853. }
  1854. Require(ThisAttribStr);
  1855. Result = ConvertStringtoEAttrib(ThisAttribStr, &ThisEAttrib);
  1856. if( ERROR_SUCCESS == Result ) {
  1857. if( OnlyADsPathPresent(&ThisEAttrib) ) {
  1858. Result = StoreCollectAttributesInternal(
  1859. hStore,
  1860. Reserved,
  1861. &ThisEAttrib,
  1862. AttribName,
  1863. ArrayToAddTo,
  1864. RecursionDepth
  1865. );
  1866. } else {
  1867. Result = AddAttribToArray(ArrayToAddTo, &ThisEAttrib);
  1868. }
  1869. if( ERROR_SUCCESS != Result ) Error = Result;
  1870. } else Error = Result;
  1871. }
  1872. FreeADsMem(Attributes);
  1873. return Error;
  1874. }
  1875. DWORD
  1876. StoreCollectBinaryAttributes( // fwd declaration
  1877. IN OUT PSTORE_HANDLE hStore,
  1878. IN DWORD Reserved,
  1879. IN LPWSTR AttribName,
  1880. IN OUT PARRAY ArrayToAddTo,
  1881. IN DWORD RecursionDepth
  1882. );
  1883. DWORD _inline
  1884. StoreCollectBinaryAttributesInternal(
  1885. IN OUT PSTORE_HANDLE hStore,
  1886. IN DWORD Reserved,
  1887. IN PEATTRIB Attrib,
  1888. IN LPWSTR AttribName,
  1889. IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
  1890. IN DWORD RecursionDepth // 0 ==> no recursion
  1891. )
  1892. {
  1893. DWORD Result, Result2;
  1894. STORE_HANDLE hStore2;
  1895. if( 0 == RecursionDepth ) {
  1896. Result = AddAttribToArray(ArrayToAddTo, Attrib);
  1897. if( ERROR_SUCCESS != Result ) SetInternalFormatError(UNEXPECTED_INTERNAL_ERROR, TRUE);
  1898. return ERROR_STACK_OVERFLOW;
  1899. }
  1900. StoreTrace2("Recursing to %ws\n", Attrib->ADsPath);
  1901. Result = StoreGetHandle(
  1902. hStore,
  1903. /*Reserved*/ 0,
  1904. Attrib->StoreGetType,
  1905. Attrib->ADsPath,
  1906. &hStore2
  1907. );
  1908. if( ERROR_SUCCESS != Result ) return Result;
  1909. Result = StoreCollectBinaryAttributes(
  1910. &hStore2,
  1911. Reserved,
  1912. AttribName,
  1913. ArrayToAddTo,
  1914. RecursionDepth-1
  1915. );
  1916. Result2 = StoreCleanupHandle( &hStore2, 0 );
  1917. return Result;
  1918. }
  1919. //BeginExport(function)
  1920. DWORD
  1921. StoreCollectBinaryAttributes(
  1922. IN OUT PSTORE_HANDLE hStore,
  1923. IN DWORD Reserved,
  1924. IN LPWSTR AttribName, // accept only attrib type OCTET_STRING
  1925. IN OUT PARRAY ArrayToAddTo, // array of PEATTRIBs
  1926. IN DWORD RecursionDepth // 0 ==> no recursion
  1927. ) //EndExport(function)
  1928. {
  1929. HRESULT hResult;
  1930. DWORD Result;
  1931. DWORD Error;
  1932. DWORD nAttributes;
  1933. DWORD i;
  1934. DWORD DataLength;
  1935. PADS_ATTR_INFO Attributes;
  1936. LPWSTR Attribs[1];
  1937. LPBYTE Data;
  1938. EATTRIB ThisEAttrib;
  1939. Attribs[0] = AttribName;
  1940. Attributes = NULL;
  1941. nAttributes = 0;
  1942. hResult = ADSIGetObjectAttributes(
  1943. hStore->ADSIHandle,
  1944. Attribs,
  1945. sizeof(Attribs)/sizeof(Attribs[0]),
  1946. &Attributes,
  1947. &nAttributes
  1948. );
  1949. if( HRESULT_FROM_WIN32(ERROR_DS_NO_ATTRIBUTE_OR_VALUE) == hResult ) {
  1950. return ERROR_SUCCESS;
  1951. }
  1952. if( FAILED(hResult) ) return ConvertHresult(hResult);
  1953. if( 0 == nAttributes || NULL == Attributes )
  1954. return ERROR_SUCCESS;
  1955. Require( 1 == nAttributes );
  1956. Error = ERROR_SUCCESS;
  1957. for( i = 0; i < Attributes[0].dwNumValues ; i ++ ) {
  1958. if( ADSTYPE_OCTET_STRING != Attributes[0].pADsValues[i].dwType ) {
  1959. SetInternalFormatError(UNEXPECTED_COLLECTION_TYPE, TRUE);
  1960. continue;
  1961. }
  1962. Data = Attributes[0].pADsValues[i].OctetString.lpValue;
  1963. DataLength = Attributes[0].pADsValues[i].OctetString.dwLength;
  1964. Result = ConvertBinarytoEAttrib(Data, DataLength, &ThisEAttrib);
  1965. if( ERROR_SUCCESS == Result ) {
  1966. if( OnlyADsPathPresent(&ThisEAttrib) ) {
  1967. Result = StoreCollectBinaryAttributesInternal(
  1968. hStore,
  1969. Reserved,
  1970. &ThisEAttrib,
  1971. AttribName,
  1972. ArrayToAddTo,
  1973. RecursionDepth
  1974. );
  1975. } else {
  1976. Result = AddAttribToArray(ArrayToAddTo, &ThisEAttrib);
  1977. }
  1978. if( ERROR_SUCCESS != Result ) Error = Result;
  1979. } else Error = Result;
  1980. }
  1981. FreeADsMem(Attributes);
  1982. return Error;
  1983. }
  1984. DWORD _inline
  1985. SizeAfterSeparation( // the field separation character has to doubled.
  1986. IN LPWSTR String, // string with field separation character not escape'ed.
  1987. IN WCHAR Sep
  1988. )
  1989. {
  1990. DWORD RetVal;
  1991. RetVal = wcslen(String);
  1992. while(String = wcschr(String, Sep ) ) {
  1993. RetVal ++;
  1994. }
  1995. return RetVal;
  1996. }
  1997. LPWSTR
  1998. ConvertStringToString( // duplicate any field_sep characters found
  1999. IN LPWSTR InStr,
  2000. IN WCHAR PrefixChar,
  2001. IN LPWSTR Str, // copy into this pre-allocated buffer
  2002. IN WCHAR Sep
  2003. )
  2004. {
  2005. *Str++ = PrefixChar;
  2006. while( *InStr ) {
  2007. if( Sep != *InStr ) {
  2008. *Str ++ = *InStr;
  2009. } else {
  2010. *Str ++ = Sep;
  2011. *Str ++ = Sep;
  2012. }
  2013. InStr ++;
  2014. }
  2015. *Str = L'\0';
  2016. return Str;
  2017. }
  2018. LPWSTR // Return the ptr to where the '\0' is stored
  2019. ConvertAddressToString( // convert ip address to dotted notation LPWSTR
  2020. IN DWORD Address,
  2021. IN WCHAR PrefixChar,
  2022. IN LPWSTR Str // copy into this pre-allocated buffer
  2023. )
  2024. {
  2025. LPSTR AsciiStr;
  2026. Address = htonl(Address); // convert to n/w order before making string..
  2027. *Str ++ = PrefixChar;
  2028. AsciiStr = inet_ntoa(*(struct in_addr *)&Address);
  2029. while( *Str ++ = (WCHAR) *AsciiStr ++ )
  2030. ;
  2031. Str --; *Str = L'\0';
  2032. return Str;
  2033. }
  2034. LPWSTR
  2035. ConvertDwordToString( // convert a DWORD to string in 0x.... fmt
  2036. IN DWORD Dword,
  2037. IN WCHAR PrefixChar,
  2038. IN LPWSTR Str // copy into this pre-allocated buffer
  2039. )
  2040. {
  2041. UCHAR Ch;
  2042. LPWSTR Stream;
  2043. DWORD i;
  2044. Dword = htonl(Dword); // convert to n/w order before making string.
  2045. *Str ++ = PrefixChar;
  2046. *Str ++ = L'0'; *Str ++ = L'x' ;
  2047. Stream = Str; Str += sizeof(Dword)*2;
  2048. for( i = sizeof(Dword); i ; i -- ) {
  2049. Ch = (BYTE)(Dword & 0x0F);
  2050. Dword >>= 4;
  2051. Stream[i*2 -1] = (Ch < 10)? (L'0'+Ch) : (Ch-10 + L'A');
  2052. Ch = (BYTE)(Dword & 0x0F);
  2053. Dword >>= 4;
  2054. Stream[i*2 -2] = (Ch < 10)? (L'0'+Ch) : (Ch-10 + L'A');
  2055. }
  2056. *Str = L'\0';
  2057. return Str;
  2058. }
  2059. LPWSTR
  2060. ConvertBinaryToString( // convert a binary byte sequence to a string as 0F321B etc..
  2061. IN LPBYTE Bytes,
  2062. IN DWORD nBytes,
  2063. IN WCHAR PrefixChar,
  2064. IN LPWSTR Str
  2065. )
  2066. {
  2067. BYTE Ch, Ch1, Ch2;
  2068. DWORD i;
  2069. *Str ++ = PrefixChar;
  2070. for( i = 0; i < nBytes; i ++ ) {
  2071. Ch = *Bytes ++;
  2072. Ch1 = Ch >> 4;
  2073. Ch2 = Ch & 0x0F;
  2074. if( Ch1 >= 10 ) *Str ++ = Ch1 - 10 + L'A';
  2075. else *Str ++ = Ch1 + L'0';
  2076. if( Ch2 >= 10 ) *Str ++ = Ch2 - 10 + L'A';
  2077. else *Str ++ = Ch2 + L'0';
  2078. }
  2079. *Str = L'\0';
  2080. return Str;
  2081. }
  2082. DWORD
  2083. ConvertEAttribToString( // inverse of ConvertStringtoEAttrib
  2084. IN PEATTRIB Attrib, // the attrib to encapsulate
  2085. IN OUT LPWSTR *String, // allocated string
  2086. IN WCHAR Sep
  2087. )
  2088. {
  2089. DWORD nChars;
  2090. LPWSTR Str;
  2091. WCHAR PrefixChar;
  2092. AssertRet(String && Attrib, ERROR_INVALID_PARAMETER);
  2093. *String = NULL;
  2094. nChars = 0;
  2095. if( IS_ADDRESS1_PRESENT(Attrib) ) nChars += sizeof(L"$i000.000.000.000");
  2096. if( IS_ADDRESS2_PRESENT(Attrib) ) nChars += sizeof(L"$j000.000.000.000");
  2097. if( IS_ADDRESS3_PRESENT(Attrib) ) nChars += sizeof(L"$k000.000.000.000");
  2098. if( IS_ADSPATH_PRESENT(Attrib) ) {
  2099. AssertRet( IS_STOREGETTYPE_PRESENT(Attrib), ERROR_INVALID_PARAMETER );
  2100. AssertRet( Attrib->ADsPath, ERROR_INVALID_PARAMETER );
  2101. nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->ADsPath,Sep);
  2102. nChars += sizeof(L"$p");
  2103. }
  2104. if( IS_FLAGS1_PRESENT(Attrib) ) nChars += sizeof(L"$f0x") + sizeof(DWORD)*2*sizeof(WCHAR);
  2105. if( IS_FLAGS2_PRESENT(Attrib) ) nChars += sizeof(L"$g0x") + sizeof(DWORD)*2*sizeof(WCHAR);
  2106. if( IS_DWORD1_PRESENT(Attrib) ) nChars += sizeof(L"$d0x") + sizeof(DWORD)*2*sizeof(WCHAR);
  2107. if( IS_DWORD2_PRESENT(Attrib) ) nChars += sizeof(L"$e0x") + sizeof(DWORD)*2*sizeof(WCHAR);
  2108. if( IS_STRING1_PRESENT(Attrib) ) {
  2109. AssertRet( Attrib->String1, ERROR_INVALID_PARAMETER );
  2110. nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String1,Sep);
  2111. nChars += sizeof(L"$s");
  2112. }
  2113. if( IS_STRING2_PRESENT(Attrib) ) {
  2114. AssertRet( Attrib->String2, ERROR_INVALID_PARAMETER );
  2115. nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String2,Sep);
  2116. nChars += sizeof(L"$t");
  2117. }
  2118. if( IS_STRING3_PRESENT(Attrib) ) {
  2119. AssertRet( Attrib->String3, ERROR_INVALID_PARAMETER );
  2120. nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String3,Sep);
  2121. nChars += sizeof(L"$u");
  2122. }
  2123. if( IS_STRING4_PRESENT(Attrib) ) {
  2124. AssertRet( Attrib->String4, ERROR_INVALID_PARAMETER );
  2125. nChars += sizeof(WCHAR) * SizeAfterSeparation(Attrib->String4,Sep);
  2126. nChars += sizeof(L"$v");
  2127. }
  2128. if( IS_BINARY1_PRESENT(Attrib) ) {
  2129. nChars += sizeof(WCHAR) * 2 * Attrib->BinLen1;
  2130. nChars += sizeof(L"$b");
  2131. }
  2132. if( IS_BINARY2_PRESENT(Attrib) ) {
  2133. nChars += sizeof(WCHAR) * 2 * Attrib->BinLen2;
  2134. nChars += sizeof(L"$c");
  2135. }
  2136. if( 0 == nChars ) return ERROR_SUCCESS; // nothing is present really.
  2137. Str = MemAlloc(nChars + sizeof(L"") ); // take care of terminating the string
  2138. if( NULL == Str ) return ERROR_NOT_ENOUGH_MEMORY;
  2139. *String = Str; // save the return value, as Str keeps changing
  2140. if( IS_ADDRESS1_PRESENT(Attrib) ) {
  2141. Str = ConvertAddressToString(Attrib->Address1, ch_Address1, Str);
  2142. *Str++ = Sep;
  2143. }
  2144. if( IS_ADDRESS2_PRESENT(Attrib) ) {
  2145. Str = ConvertAddressToString(Attrib->Address2, ch_Address2, Str);
  2146. *Str++ = Sep;
  2147. }
  2148. if( IS_ADDRESS3_PRESENT(Attrib) ) {
  2149. Str = ConvertAddressToString(Attrib->Address3, ch_Address3, Str);
  2150. *Str++ = Sep;
  2151. }
  2152. if( IS_ADSPATH_PRESENT(Attrib) ) {
  2153. switch(Attrib->StoreGetType) {
  2154. case StoreGetChildType:
  2155. PrefixChar = ch_ADsPath_relative; break;
  2156. case StoreGetAbsoluteSameServerType:
  2157. PrefixChar = ch_ADsPath_absolute; break;
  2158. case StoreGetAbsoluteOtherServerType:
  2159. PrefixChar = ch_ADsPath_diff_srvr; break;
  2160. default:
  2161. Require(FALSE); // too late to do anything about this now.
  2162. PrefixChar = ch_ADsPath_diff_srvr; break;
  2163. }
  2164. Str = ConvertStringToString(Attrib->ADsPath, PrefixChar, Str,Sep);
  2165. *Str++ = Sep;
  2166. }
  2167. if( IS_FLAGS1_PRESENT(Attrib) ) {
  2168. Str = ConvertDwordToString(Attrib->Flags1, ch_Flags1, Str);
  2169. *Str++ = Sep;
  2170. }
  2171. if( IS_FLAGS2_PRESENT(Attrib) ) {
  2172. Str = ConvertDwordToString(Attrib->Flags2, ch_Flags2, Str);
  2173. *Str++ = Sep;
  2174. }
  2175. if( IS_DWORD1_PRESENT(Attrib) ) {
  2176. Str = ConvertDwordToString(Attrib->Dword1, ch_Dword1, Str);
  2177. *Str++ = Sep;
  2178. }
  2179. if( IS_DWORD2_PRESENT(Attrib) ) {
  2180. Str = ConvertDwordToString(Attrib->Dword2, ch_Dword2, Str);
  2181. *Str++ = Sep;
  2182. }
  2183. if( IS_STRING1_PRESENT(Attrib) ) {
  2184. Str = ConvertStringToString(Attrib->String1, ch_String1, Str,Sep);
  2185. *Str++ = Sep;
  2186. }
  2187. if( IS_STRING2_PRESENT(Attrib) ) {
  2188. Str = ConvertStringToString(Attrib->String2, ch_String2, Str,Sep);
  2189. *Str++ = Sep;
  2190. }
  2191. if( IS_STRING3_PRESENT(Attrib) ) {
  2192. Str = ConvertStringToString(Attrib->String3, ch_String3, Str,Sep);
  2193. *Str++ = Sep;
  2194. }
  2195. if( IS_STRING4_PRESENT(Attrib) ) {
  2196. Str = ConvertStringToString(Attrib->String4, ch_String4, Str,Sep);
  2197. *Str++ = Sep;
  2198. }
  2199. if( IS_BINARY1_PRESENT(Attrib) ) {
  2200. Str = ConvertBinaryToString(Attrib->Binary1, Attrib->BinLen1, ch_Binary1, Str);
  2201. *Str++ = Sep;
  2202. }
  2203. if( IS_BINARY2_PRESENT(Attrib) ) {
  2204. Str = ConvertBinaryToString(Attrib->Binary2, Attrib->BinLen2, ch_Binary2, Str);
  2205. }
  2206. *Str = L'\0';
  2207. Require(((LPBYTE)Str) < nChars + 1 + ((LPBYTE)(*String)) );
  2208. return ERROR_SUCCESS;
  2209. }
  2210. LPBYTE
  2211. ConvertDwordToBinary( // pack a DWORD in binary format
  2212. IN DWORD Dword,
  2213. IN WCHAR Character,
  2214. IN LPBYTE Buffer
  2215. )
  2216. {
  2217. *(LPWORD)Buffer = htons(Character); Buffer += sizeof(WORD);
  2218. *(LPWORD)Buffer = htons(sizeof(DWORD)); Buffer += sizeof(WORD);
  2219. *(DWORD UNALIGNED *)Buffer = htonl(Dword);
  2220. Buffer += sizeof(DWORD);
  2221. return Buffer;
  2222. }
  2223. LPBYTE
  2224. ConvertAddressToBinary( // pack an address to binary format..
  2225. IN DWORD Address,
  2226. IN WCHAR Character,
  2227. IN LPBYTE Buffer
  2228. )
  2229. {
  2230. return ConvertDwordToBinary(Address,Character,Buffer);
  2231. }
  2232. LPBYTE
  2233. ConvertStringToBinary( // pack a string in binary format
  2234. IN LPWSTR Str,
  2235. IN WCHAR Character,
  2236. IN LPBYTE Buffer
  2237. )
  2238. {
  2239. DWORD Size;
  2240. Size = sizeof(WCHAR)*(1+wcslen(Str));
  2241. *(LPWORD)Buffer = htons(Character); Buffer += sizeof(WORD);
  2242. *(LPWORD)Buffer = htons((WORD)Size); Buffer += sizeof(WORD);
  2243. memcpy(Buffer, Str, Size);
  2244. Buffer += ROUND_UP_COUNT(Size, ALIGN_WORD);
  2245. return Buffer;
  2246. }
  2247. DWORD
  2248. ConvertEAttribToBinary( // inverse of ConvertBinarytoEAttrib
  2249. IN PEATTRIB Attrib, // the attrib to encapsulate
  2250. IN OUT LPBYTE *Bytes, // allocated buffer
  2251. IN OUT DWORD *nBytes // # of bytes allocated
  2252. )
  2253. {
  2254. DWORD nChars;
  2255. LPBYTE Buf;
  2256. WCHAR PrefixChar;
  2257. AssertRet(Bytes && Attrib && nBytes, ERROR_INVALID_PARAMETER);
  2258. *Bytes = NULL; *nBytes =0;
  2259. nChars = 0; // WCHAR_opcode ~ WORD_size ~ DWORD_ipAddress
  2260. if( IS_ADDRESS1_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2261. if( IS_ADDRESS2_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2262. if( IS_ADDRESS3_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2263. if( IS_ADSPATH_PRESENT(Attrib) ) {
  2264. AssertRet( IS_STOREGETTYPE_PRESENT(Attrib), ERROR_INVALID_PARAMETER );
  2265. AssertRet( Attrib->ADsPath, ERROR_INVALID_PARAMETER );
  2266. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2267. nChars += sizeof(WCHAR) * (1+ wcslen(Attrib->ADsPath));
  2268. }
  2269. // WCHAR_opcode ~ WORD_size ~ DWORD_flags
  2270. if( IS_FLAGS1_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2271. if( IS_FLAGS2_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2272. if( IS_DWORD1_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2273. if( IS_DWORD2_PRESENT(Attrib) ) nChars += sizeof(WORD) + sizeof(WORD) + sizeof(DWORD);
  2274. if( IS_STRING1_PRESENT(Attrib) ) {
  2275. AssertRet( Attrib->String1, ERROR_INVALID_PARAMETER );
  2276. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2277. nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String1));
  2278. }
  2279. if( IS_STRING2_PRESENT(Attrib) ) {
  2280. AssertRet( Attrib->String2, ERROR_INVALID_PARAMETER );
  2281. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2282. nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String2));
  2283. }
  2284. if( IS_STRING3_PRESENT(Attrib) ) {
  2285. AssertRet( Attrib->String3, ERROR_INVALID_PARAMETER );
  2286. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2287. nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String3));
  2288. }
  2289. if( IS_STRING4_PRESENT(Attrib) ) {
  2290. AssertRet( Attrib->String4, ERROR_INVALID_PARAMETER );
  2291. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2292. nChars += sizeof(WCHAR) * (1 + wcslen(Attrib->String4));
  2293. }
  2294. if( IS_BINARY1_PRESENT(Attrib) ) {
  2295. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2296. nChars += ROUND_UP_COUNT(Attrib->BinLen1, ALIGN_WORD);
  2297. }
  2298. if( IS_BINARY2_PRESENT(Attrib) ) {
  2299. nChars += sizeof(WORD) + sizeof(WORD); // WCHAR_opcode ~ WORD_size
  2300. nChars += ROUND_UP_COUNT(Attrib->BinLen2, ALIGN_WORD);
  2301. }
  2302. if( 0 == nChars ) return ERROR_SUCCESS; // nothing is present really.
  2303. Buf = MemAlloc(nChars);
  2304. if( NULL == Buf ) return ERROR_NOT_ENOUGH_MEMORY;
  2305. *Bytes = Buf; // save the return value.. Buf itself is changed..
  2306. *nBytes = nChars;
  2307. if( IS_ADDRESS1_PRESENT(Attrib) ) Buf = ConvertAddressToBinary(Attrib->Address1, ch_Address1, Buf);
  2308. if( IS_ADDRESS2_PRESENT(Attrib) ) Buf = ConvertAddressToBinary(Attrib->Address2, ch_Address2, Buf);
  2309. if( IS_ADDRESS3_PRESENT(Attrib) ) Buf = ConvertAddressToBinary(Attrib->Address3, ch_Address3, Buf);
  2310. if( IS_ADSPATH_PRESENT(Attrib) ) {
  2311. switch(Attrib->StoreGetType) {
  2312. case StoreGetChildType:
  2313. PrefixChar = ch_ADsPath_relative; break;
  2314. case StoreGetAbsoluteSameServerType:
  2315. PrefixChar = ch_ADsPath_absolute; break;
  2316. case StoreGetAbsoluteOtherServerType:
  2317. PrefixChar = ch_ADsPath_diff_srvr; break;
  2318. default:
  2319. Require(FALSE); // too late to do anything about this now.
  2320. PrefixChar = ch_ADsPath_diff_srvr; break;
  2321. }
  2322. Buf = ConvertStringToBinary(Attrib->ADsPath, PrefixChar, Buf);
  2323. }
  2324. if( IS_FLAGS1_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Flags1, ch_Flags1, Buf);
  2325. if( IS_FLAGS2_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Flags2, ch_Flags2, Buf);
  2326. if( IS_DWORD1_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Dword1, ch_Dword1, Buf);
  2327. if( IS_DWORD2_PRESENT(Attrib) ) Buf = ConvertDwordToBinary(Attrib->Dword2, ch_Dword2, Buf);
  2328. if( IS_STRING1_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String1, ch_String1, Buf);
  2329. if( IS_STRING2_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String2, ch_String2, Buf);
  2330. if( IS_STRING3_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String3, ch_String3, Buf);
  2331. if( IS_STRING4_PRESENT(Attrib) ) Buf = ConvertStringToBinary(Attrib->String4, ch_String4, Buf);
  2332. if( IS_BINARY1_PRESENT(Attrib) ) {
  2333. *(LPWORD)Buf = htons(ch_Binary1); Buf += sizeof(WORD);
  2334. *(LPWORD)Buf = htons((WORD)Attrib->BinLen1); Buf += sizeof(WORD);
  2335. memcpy(Buf, Attrib->Binary1, Attrib->BinLen1);
  2336. Buf += ROUND_UP_COUNT(Attrib->BinLen1, ALIGN_WORD);
  2337. }
  2338. if( IS_BINARY2_PRESENT(Attrib) ) {
  2339. *(LPWORD)Buf = htons(ch_Binary2); Buf += sizeof(WORD);
  2340. *(LPWORD)Buf = htons((WORD)Attrib->BinLen2); Buf += sizeof(WORD);
  2341. memcpy(Buf, Attrib->Binary2, Attrib->BinLen2);
  2342. Buf += ROUND_UP_COUNT(Attrib->BinLen2, ALIGN_WORD);
  2343. }
  2344. Require( Buf == nChars + (*Bytes) );
  2345. return ERROR_SUCCESS;
  2346. }
  2347. StoreUpdateAttributesInternal( // update a list of attributes
  2348. IN OUT LPSTORE_HANDLE hStore, // handle to obj to update
  2349. IN DWORD Reserved, // for future use, must be zero
  2350. IN LPWSTR AttribName, // name of attrib, must be string type
  2351. IN PARRAY Array, // list of attribs
  2352. IN WCHAR Sep
  2353. ) //EndExport(function)
  2354. {
  2355. DWORD Result;
  2356. HRESULT hResult;
  2357. LONG nValues, i;
  2358. ADS_ATTR_INFO Attribute;
  2359. PADSVALUE Values;
  2360. ARRAY_LOCATION Loc;
  2361. LPWSTR Str;
  2362. PEATTRIB ThisAttrib;
  2363. if( NULL == hStore || NULL == hStore->ADSIHandle )
  2364. return ERROR_INVALID_PARAMETER;
  2365. if( NULL == AttribName || 0 != Reserved )
  2366. return ERROR_INVALID_PARAMETER;
  2367. if( NULL == Array )
  2368. return ERROR_INVALID_PARAMETER;
  2369. nValues = MemArraySize(Array);
  2370. if( 0 == nValues ) { // delete the attribute
  2371. Attribute.pszAttrName = AttribName;
  2372. Attribute.dwControlCode = ADS_ATTR_CLEAR;
  2373. Attribute.dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  2374. Attribute.pADsValues = NULL;
  2375. Attribute.dwNumValues = 0;
  2376. hResult = ADSISetObjectAttributes(
  2377. /* hDSObject */ hStore->ADSIHandle,
  2378. /* pAttributeEntr.. */ &Attribute,
  2379. /* dwNumAttributes */ 1,
  2380. /* pdwNumAttribut.. */ &nValues
  2381. );
  2382. if( FAILED(hResult) || 1 != nValues ) { // something went wrong
  2383. return ConvertHresult(hResult);
  2384. }
  2385. return ERROR_SUCCESS;
  2386. }
  2387. Values = MemAlloc(nValues * sizeof(ADSVALUE));
  2388. if( NULL == Values ) { // could not allocate ADs array
  2389. return ERROR_NOT_ENOUGH_MEMORY;
  2390. }
  2391. for(i = 0, Result = MemArrayInitLoc(Array, &Loc)
  2392. ; ERROR_FILE_NOT_FOUND != Result ; // convert to PADS_ATTR_INFO
  2393. i ++ , Result = MemArrayNextLoc(Array, &Loc)
  2394. ) {
  2395. Result = MemArrayGetElement(Array, &Loc, &ThisAttrib);
  2396. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  2397. Str = NULL;
  2398. Result = ConvertEAttribToString(ThisAttrib, &Str, Sep);
  2399. if( ERROR_SUCCESS != Result ) { // something went wrong!
  2400. goto Cleanup; // free allocated memory
  2401. }
  2402. Values[i].dwType = ADSTYPE_CASE_IGNORE_STRING;
  2403. Values[i].CaseIgnoreString = Str;
  2404. }
  2405. Attribute.pszAttrName = AttribName;
  2406. Attribute.dwControlCode = ADS_ATTR_UPDATE;
  2407. Attribute.dwADsType = ADSTYPE_CASE_IGNORE_STRING;
  2408. Attribute.pADsValues = Values;
  2409. Attribute.dwNumValues = nValues;
  2410. hResult = ADSISetObjectAttributes(
  2411. /* hDSObject */ hStore->ADSIHandle,
  2412. /* pAttributeEntr.. */ &Attribute,
  2413. /* dwNumAttributes */ 1,
  2414. /* pdwNumAttribut.. */ &nValues
  2415. );
  2416. if( FAILED(hResult) || 1 != nValues ) { // something went wrong
  2417. Result = ConvertHresult(hResult);
  2418. } else Result = ERROR_SUCCESS;
  2419. Cleanup:
  2420. if( Values ) { // got to free allocated memory
  2421. while( i -- ) { // got to free converted strings
  2422. if( Values[i].CaseIgnoreString )
  2423. MemFree(Values[i].CaseIgnoreString);
  2424. }
  2425. MemFree(Values);
  2426. }
  2427. return Result;
  2428. }
  2429. //BeginExport(function)
  2430. //DOC StoreUpdateAttributes is sort of the converse of StoreCollectAttributes.
  2431. //DOC This function takes an array of type EATTRIB elements and updates the DS
  2432. //DOC with this array. This function does not work when the attrib is of type
  2433. //DOC OCTET_STRING etc. It works only with types that can be derived from
  2434. //DOC PrintableString.
  2435. DWORD
  2436. StoreUpdateAttributes( // update a list of attributes
  2437. IN OUT LPSTORE_HANDLE hStore, // handle to obj to update
  2438. IN DWORD Reserved, // for future use, must be zero
  2439. IN LPWSTR AttribName, // name of attrib, must be string type
  2440. IN PARRAY Array // list of attribs
  2441. ) //EndExport(function)
  2442. {
  2443. DWORD Result;
  2444. HRESULT hResult;
  2445. Result = StoreUpdateAttributesInternal(
  2446. hStore, Reserved, AttribName, Array, ch_FieldSep );
  2447. return Result;
  2448. }
  2449. //BeginExport(function)
  2450. //DOC StoreUpdateBinaryAttributes is sort of the converse of StoreCollectBinaryAttributes
  2451. //DOC This function takes an array of type EATTRIB elements and updates the DS
  2452. //DOC with this array. This function works only when the attrib is of type
  2453. //DOC OCTET_STRING etc. It doesnt work with types that can be derived from
  2454. //DOC PrintableString!!!.
  2455. DWORD
  2456. StoreUpdateBinaryAttributes( // update a list of attributes
  2457. IN OUT LPSTORE_HANDLE hStore, // handle to obj to update
  2458. IN DWORD Reserved, // for future use, must be zero
  2459. IN LPWSTR AttribName, // name of attrib, must be OCTET_STRING type
  2460. IN PARRAY Array // list of attribs
  2461. ) //EndExport(function)
  2462. {
  2463. DWORD Result;
  2464. HRESULT hResult;
  2465. LONG nValues, i, nBytes;
  2466. ADS_ATTR_INFO Attribute;
  2467. PADSVALUE Values;
  2468. ARRAY_LOCATION Loc;
  2469. LPBYTE Bytes;
  2470. PEATTRIB ThisAttrib;
  2471. if( NULL == hStore || NULL == hStore->ADSIHandle )
  2472. return ERROR_INVALID_PARAMETER;
  2473. if( NULL == AttribName || 0 != Reserved )
  2474. return ERROR_INVALID_PARAMETER;
  2475. if( NULL == Array )
  2476. return ERROR_INVALID_PARAMETER;
  2477. nValues = MemArraySize(Array);
  2478. if( 0 == nValues ) { // delete the attribute
  2479. Attribute.pszAttrName = AttribName;
  2480. Attribute.dwControlCode = ADS_ATTR_CLEAR;
  2481. Attribute.dwADsType = ADSTYPE_OCTET_STRING;
  2482. Attribute.pADsValues = NULL;
  2483. Attribute.dwNumValues = 0;
  2484. hResult = ADSISetObjectAttributes(
  2485. /* hDSObject */ hStore->ADSIHandle,
  2486. /* pAttributeEntr.. */ &Attribute,
  2487. /* dwNumAttributes */ 1,
  2488. /* pdwNumAttribut.. */ &nValues
  2489. );
  2490. if( FAILED(hResult) || 1 != nValues ) { // something went wrong
  2491. return ConvertHresult(hResult);
  2492. }
  2493. return ERROR_SUCCESS;
  2494. }
  2495. Values = MemAlloc(nValues * sizeof(ADSVALUE));
  2496. if( NULL == Values ) { // could not allocate ADs array
  2497. return ERROR_NOT_ENOUGH_MEMORY;
  2498. }
  2499. for(i = 0, Result = MemArrayInitLoc(Array, &Loc)
  2500. ; ERROR_FILE_NOT_FOUND != Result ; // convert to PADS_ATTR_INFO
  2501. i ++ , Result = MemArrayNextLoc(Array, &Loc)
  2502. ) {
  2503. Result = MemArrayGetElement(Array, &Loc, &ThisAttrib);
  2504. //- ERROR_SUCCESS == Result && NULL != ThisAttrib
  2505. Bytes = NULL; nBytes =0;
  2506. Result = ConvertEAttribToBinary(ThisAttrib, &Bytes, &nBytes);
  2507. if( ERROR_SUCCESS != Result ) { // something went wrong!
  2508. goto Cleanup; // free allocated memory
  2509. }
  2510. Values[i].dwType = ADSTYPE_OCTET_STRING;
  2511. Values[i].OctetString.dwLength = nBytes;
  2512. Values[i].OctetString.lpValue = Bytes;
  2513. }
  2514. Attribute.pszAttrName = AttribName;
  2515. Attribute.dwControlCode = ADS_ATTR_UPDATE;
  2516. Attribute.dwADsType = ADSTYPE_OCTET_STRING;
  2517. Attribute.pADsValues = Values;
  2518. Attribute.dwNumValues = nValues;
  2519. hResult = ADSISetObjectAttributes(
  2520. /* hDSObject */ hStore->ADSIHandle,
  2521. /* pAttributeEntr.. */ &Attribute,
  2522. /* dwNumAttributes */ 1,
  2523. /* pdwNumAttribut.. */ &nValues
  2524. );
  2525. if( FAILED(hResult) || 1 != nValues ) { // something went wrong
  2526. Result = ConvertHresult(hResult);
  2527. } else Result = ERROR_SUCCESS;
  2528. Cleanup:
  2529. if( Values ) { // got to free allocated memory
  2530. while( i -- ) { // got to free converted strings
  2531. if( Values[i].OctetString.lpValue )
  2532. MemFree(Values[i].OctetString.lpValue);
  2533. }
  2534. MemFree(Values);
  2535. }
  2536. return Result;
  2537. }
  2538. //================================================================================
  2539. // end of file
  2540. //================================================================================